• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Nic30 / hwt / 597902fe-2f5f-4132-93c3-f98ed9d143f4

19 Jun 2025 12:10PM UTC coverage: 84.558% (-0.05%) from 84.61%
597902fe-2f5f-4132-93c3-f98ed9d143f4

push

circleci

Nic30
feat(HwIO_getName): support invalid parent (this fn. is for debug)

3430 of 4502 branches covered (76.19%)

Branch coverage included in aggregate %.

0 of 5 new or added lines in 1 file covered. (0.0%)

94 existing lines in 2 files now uncovered.

11902 of 13630 relevant lines covered (87.32%)

0.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.02
/hwt/synthesizer/interfaceLevel/hwModuleImplHelpers.py
1
from itertools import chain
1✔
2
from typing import Union, Optional, Tuple
1✔
3

4
from hwt.constants import NOT_SPECIFIED
1✔
5
from hwt.doc_markers import internal
1✔
6
from hwt.hwIOs.std import HwIOSignal, HwIOClk, HwIORst, HwIORst_n
1✔
7
from hwt.hwIOs.hwIOStruct import HdlType_to_HwIO, HwIOStruct
1✔
8
from hwt.hObjList import HObjList
1✔
9
from hwt.hdl.operatorDefs import HOperatorDef
1✔
10
from hwt.hdl.types.array import HArray
1✔
11
from hwt.hdl.types.defs import BIT
1✔
12
from hwt.hdl.types.hdlType import HdlType
1✔
13
from hwt.hdl.types.struct import HStruct
1✔
14
from hwt.mainBases import HwModuleBase, HwIOBase
1✔
15
from hwt.mainBases import RtlSignalBase
1✔
16
from hwt.synthesizer.interfaceLevel.getDefaultClkRts import getClk, getRst
1✔
17
from hwt.synthesizer.rtlLevel.netlist import RtlNetlist
1✔
18
from hwt.synthesizer.rtlLevel.rtlSignal import RtlSignal
1✔
19
from ipCorePackager.constants import INTF_DIRECTION
1✔
20

21

22
def getSignalName(sig: RtlSignalBase):
1✔
23
    """
24
    Name getter which works for RtlSignal and HwIO instances as well
25
    """
26
    return sig._name
1✔
27

28

29
def HwIO_getName(top: HwModuleBase, io: Union[HwIOBase, RtlSignal,
1✔
30
                                              Tuple[Union[HwIOBase, RtlSignal]]]):
31
    if isinstance(io, HwIOBase):
×
32
        prefix = []
×
33
        parent = io._parent
×
34
        while parent is not None:
×
35
            if parent is top:
×
36
                break
×
NEW
37
            try:
×
NEW
38
                prefix.append(parent._name)
×
NEW
39
            except AttributeError:
×
NEW
40
                prefix.append(repr(parent))
×
NEW
41
                break
×
42
                
43
            parent = parent._parent
×
44

45
        n = io._getFullName()
×
46
        if prefix:
×
47
            prefix.reverse()
×
48
            prefix.append(n)
×
49
            return ".".join(prefix)
×
50
        else:
51
            return n
×
52
    elif isinstance(io, tuple):
×
53
        return f"({', '.join(HwIO_getName(top, _io) for _io in io)})"
×
54
    else:
55
        return getSignalName(io)
×
56

57

58
@internal
1✔
59
def _default_param_updater(self, myP: "HwParam", otherP_val):
1✔
60
    myP.set_value(otherP_val)
1✔
61

62

63
@internal
1✔
64
def _normalize_default_value_dict_for_HwIO_array(root_val: dict,
1✔
65
                                                val: Union[dict, list, None],
66
                                                name_prefix: str,
67
                                                hobj_list: HObjList,
68
                                                neutral_value):
69
    """
70
    This function is called to convert data in format
71
    .. code-block:: python
72

73
        {"x": [3, 4]}
74
        # into
75
        {"x_0": 3, "x_1": 4}
76

77
    This is required because the items of HObjList are stored in _hwIOs as a separate items
78
    and thus we can not resolve the value association otherwise.
79
    """
80

81
    for i, intf in enumerate(hobj_list):
1✔
82
        if val is neutral_value:
1!
83
            continue
×
84
        elif isinstance(val, dict):
1!
85
            _val = val.get(i, neutral_value)
×
86
        else:
87
            _val = val[i]
1✔
88
        if _val is neutral_value:
1!
89
            continue
×
90

91
        elm_name = f"{name_prefix:s}_{i:d}"
1✔
92
        if isinstance(intf, HObjList):
1!
93
            _normalize_default_value_dict_for_HwIO_array(root_val, _val, elm_name, intf, neutral_value)
×
94
        else:
95
            root_val[elm_name] = _val
1✔
96

97

98
@internal
1✔
99
def _instantiate_signals(hwIO: Union[HwIOSignal, HObjList, HwIOStruct],
1✔
100
                         clk: HwIOClk, rst: Union[HwIORst, HwIORst_n],
101
                         def_val:Union[int, None, dict, list],
102
                         nop_val:Union[int, None, dict, list],
103
                         nextSig: Optional[RtlSignalBase], signal_create_fn):
104
    hwIO._direction = INTF_DIRECTION.UNKNOWN
1✔
105
    if isinstance(hwIO, HwIOSignal):
1✔
106
        name = hwIO._getHdlName()
1✔
107
        hwIO._sig = signal_create_fn(
1✔
108
            name,
109
            hwIO._dtype,
110
            clk, rst, def_val, nop_val, nextSig)
111
        hwIO._sig._hwIO = hwIO
1✔
112

113
    elif isinstance(hwIO, HObjList):
1✔
114
        intf_len = len(hwIO)
1✔
115
        if isinstance(def_val, dict):
1!
116
            for k in def_val.keys():
×
117
                assert k > 0 and k < intf_len, ("Default value for", hwIO, " specifies ", k, " which is not present on interface")
×
118
        elif def_val is not None:
1!
119
            assert len(def_val) == intf_len, ("Default value does not have same size, ", len(def_val), intf_len, hwIO)
1✔
120

121
        if isinstance(nop_val, dict):
1!
122
            for k in nop_val.keys():
×
123
                assert k > 0 and k < intf_len, ("Nop value for", hwIO, " specifies ", k, " which is not present on interface")
×
124
        elif nop_val is not NOT_SPECIFIED:
1!
125
            assert len(nop_val) == intf_len, ("Nop value does not have same size, ", len(nop_val), intf_len, hwIO)
×
126

127
        for i, elm in enumerate(hwIO):
1✔
128
            if def_val is None:
1!
129
                _def_val = None
×
130
            elif isinstance(def_val, dict):
1!
131
                _def_val = def_val.get(i, None)
×
132
            else:
133
                _def_val = def_val[i]
1✔
134

135
            if nop_val is NOT_SPECIFIED:
1!
136
                _nop_val = NOT_SPECIFIED
1✔
137
            elif isinstance(nop_val, dict):
×
138
                _nop_val = nop_val.get(i, NOT_SPECIFIED)
×
139
            else:
140
                _nop_val = nop_val[i]
×
141
            if nextSig is NOT_SPECIFIED:
1!
142
                _nextSig = NOT_SPECIFIED
1✔
143
            else:
144
                _nextSig = nextSig.get(i, NOT_SPECIFIED)
×
145
            _instantiate_signals(elm, clk, rst, _def_val, _nop_val, _nextSig, signal_create_fn)
1✔
146

147
    else:
148
        if def_val is not None:
1✔
149
            for k in tuple(def_val.keys()):
1✔
150
                _i = getattr(hwIO, k, NOT_SPECIFIED)
1✔
151
                assert _i is not NOT_SPECIFIED, ("Default value for", hwIO, " specifies ", k, " which is not present on interface")
1✔
152
                if isinstance(_i, HObjList):
1✔
153
                    _normalize_default_value_dict_for_HwIO_array(
1✔
154
                        def_val, def_val[k], k, _i, None)
155

156
        if nop_val is not NOT_SPECIFIED:
1!
157
            for k in tuple(nop_val.keys()):
×
158
                _i = getattr(hwIO, k, NOT_SPECIFIED)
×
159
                assert _i is not NOT_SPECIFIED, ("Nop value for", hwIO, " specifies ", k, " which is not present on interface")
×
160
                if isinstance(_i, HObjList):
×
161
                    _normalize_default_value_dict_for_HwIO_array(
×
162
                        nop_val, nop_val[k],
163
                        k, _i, NOT_SPECIFIED)
164

165
        for elm in hwIO._hwIOs:
1✔
166
            name = elm._name
1✔
167
            if def_val is None:
1✔
168
                _def_val = None
1✔
169
            else:
170
                _def_val = def_val.get(name, None)
1✔
171

172
            if nop_val is NOT_SPECIFIED:
1!
173
                _nop_val = NOT_SPECIFIED
1✔
174
            else:
175
                _nop_val = nop_val.get(name, NOT_SPECIFIED)
×
176

177
            if nextSig is NOT_SPECIFIED:
1!
178
                _nextSig = NOT_SPECIFIED
1✔
179
            else:
180
                _nextSig = getattr(nextSig, name)
×
181
            _instantiate_signals(elm, clk, rst, _def_val, _nop_val, _nextSig, signal_create_fn)
1✔
182

183

184
@internal
1✔
185
def _loadHwDeclarations(intf_or_list: Union[HObjList, HwIOBase], suggested_name: str):
1✔
186
    if isinstance(intf_or_list, HObjList):
1✔
187
        for i, intf in enumerate(intf_or_list):
1✔
188
            _loadHwDeclarations(intf, f"{suggested_name:s}_{i:d}")
1✔
189
    else:
190
        intf_or_list._name = suggested_name
1✔
191
        intf_or_list._loadHwDeclarations()
1✔
192

193

194
def HwIO_without_registration(
1✔
195
        parent:HwModuleBase,
196
        container: Union[HwIOBase, HObjList],
197
        suggested_name:str,
198
        def_val: Union[int, None, dict, list]=None,
199
        nop_val: Union[int, None, dict, list, "NOT_SPECIFIED"]=NOT_SPECIFIED,
200
        nextSig:Optional[RtlSignalBase]=NOT_SPECIFIED):
201
    """
202
    Load all parts of interface and construct signals in RtlNetlist context with an automatic name check,
203
    without need to explicitly add the HwIO into _hwIOs list.
204
    """
205
    _loadHwDeclarations(container, suggested_name)
1✔
206
    _instantiate_signals(
1✔
207
        container, None, None, def_val, nop_val, nextSig,
208
        lambda name, dtype, clk, rst, def_val, nop_val, nextSig: parent._sig(name, dtype,
209
                                                                  def_val=def_val,
210
                                                                  nop_val=nop_val,
211
                                                                  ))
212
    container._parent = parent
1✔
213
    parent._private_hwIOs.append(container)
1✔
214
    return container
1✔
215

216

217
class HwModuleImplHelpers(HwModuleBase):
1✔
218

219
    def _reg(self, name: str,
1✔
220
             dtype: HdlType=BIT,
221
             def_val: Union[int, None, dict, list]=None,
222
             clk: Union[RtlSignalBase, None, Tuple[RtlSignalBase, HOperatorDef]]=None,
223
             rst: Optional[RtlSignalBase]=None,
224
             nextSig:Optional[RtlSignalBase]=NOT_SPECIFIED) -> RtlSignal:
225
        """
226
        Create RTL FF register in this unit
227

228
        :param def_val: s default value of this register,
229
            if this value is specified reset signal of this component is used
230
            to generate a reset logic
231
        :param clk: optional clock signal specification,
232
            (signal or tuple(signal, edge type (AllOps.RISING_EDGE/FALLING_EDGE)))
233
        :param rst: optional reset signal specification
234
        :param nextSig: the signal which should be used as "next" signal for this register
235
            if is not specified the new signal is generated. (Next signal holds value which should be in register in next clk.)
236
        :note: rst/rst_n resolution is done from signal type,
237
            if it is negated type the reset signal is interpreted as rst_n
238
        :note: if clk or rst is not specified default signal
239
            from parent unit instance will be used
240
        """
241
        if clk is None:
1✔
242
            clk = getClk(self)
1✔
243

244
        if def_val is None:
1✔
245
            # if no value is specified reset is not required
246
            rst = None
1✔
247
        elif rst is None:
1✔
248
            rst = getRst(self)
1✔
249

250
        if isinstance(dtype, (HStruct, HArray)):
1✔
251
            container = HdlType_to_HwIO().apply(dtype)
1✔
252
            _loadHwDeclarations(container, name)
1✔
253
            _instantiate_signals(
1✔
254
                container, clk, rst, def_val, nextSig, NOT_SPECIFIED,
255
                lambda name, dtype, clk, rst, def_val, nop_val, nextSig: self._reg(name, dtype,
256
                                                                                   def_val=def_val,
257
                                                                                   clk=clk, rst=rst,
258
                                                                                   nextSig=nextSig))
259
            container._parent = self
1✔
260
            return container
1✔
261
        else:
262
            # primitive data type signal
263
            return self._rtlCtx.sig(
1✔
264
                name,
265
                dtype=dtype,
266
                clk=clk,
267
                syncRst=rst,
268
                def_val=def_val,
269
                nextSig=nextSig,
270
            )
271

272
    def _sig(self, name: str,
1✔
273
             dtype: HdlType=BIT,
274
             def_val: Union[int, None, dict, list]=None,
275
             nop_val: Union[int, None, dict, list, "NOT_SPECIFIED"]=NOT_SPECIFIED) -> RtlSignal:
276
        """
277
        Create signal in this unit
278

279
        :see: :func:`hwt.synthesizer.rtlLevel.netlist.RtlNetlist.sig`
280
        """
281
        if isinstance(dtype, HStruct):
1✔
282
            container = HdlType_to_HwIO().apply(dtype)
1✔
283
            return HwIO_without_registration(self, container, name, def_val=def_val, nop_val=nop_val)
1✔
284
        else:
285
            # primitive data type signal
286
            return self._rtlCtx.sig(name, dtype=dtype, def_val=def_val, nop_val=nop_val)
1✔
287

288
    @internal
1✔
289
    def _cleanThisSubunitRtlSignals(self):
1✔
290
        """
291
        Disconnect internal signals so unit can be reused by parent unit
292
        """
293
        for hwio in chain(self._hwIOs, self._private_hwIOs):
1✔
294
            hwio._cleanRtlSignals()
1✔
295

296
    @internal
1✔
297
    def _signalsForSubHwModuleEntity(self, context: RtlNetlist, prefix: str):
1✔
298
        """
299
        generate signals in this context for all ports of this subunit
300
        """
301
        for hio in self._hwIOs:
1✔
302
            if hio._isExtern:
1!
303
                hio._signalsForHwIO(context, None, None, prefix=prefix + hio._NAME_SEPARATOR)
1✔
304

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc