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

Nic30 / hwt / 8b945dd2-6cbf-43b3-be54-881b32d4f5e4

10 Jun 2025 09:35PM UTC coverage: 84.734% (-2.6%) from 87.284%
8b945dd2-6cbf-43b3-be54-881b32d4f5e4

push

circleci

Nic30
test: fix call of unittestMain

3415 of 4468 branches covered (76.43%)

Branch coverage included in aggregate %.

11877 of 13579 relevant lines covered (87.47%)

0.87 hits per line

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

69.14
/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
×
37

38
            prefix.append(parent._name)
×
39
            parent = parent._parent
×
40
        n = io._getFullName()
×
41
        if prefix:
×
42
            prefix.reverse()
×
43
            prefix.append(n)
×
44
            return ".".join(prefix)
×
45
        else:
46
            return n
×
47
    elif isinstance(io, tuple):
×
48
        return f"({', '.join(HwIO_getName(top, _io) for _io in io)})"
×
49
    else:
50
        return getSignalName(io)
×
51

52

53
@internal
1✔
54
def _default_param_updater(self, myP: "HwParam", otherP_val):
1✔
55
    myP.set_value(otherP_val)
1✔
56

57

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

68
        {"x": [3, 4]}
69
        # into
70
        {"x_0": 3, "x_1": 4}
71

72
    This is required because the items of HObjList are stored in _hwIOs as a separate items
73
    and thus we can not resolve the value association otherwise.
74
    """
75

76
    for i, intf in enumerate(hobj_list):
1✔
77
        if val is neutral_value:
1!
78
            continue
×
79
        elif isinstance(val, dict):
1!
80
            _val = val.get(i, neutral_value)
×
81
        else:
82
            _val = val[i]
1✔
83
        if _val is neutral_value:
1!
84
            continue
×
85

86
        elm_name = f"{name_prefix:s}_{i:d}"
1✔
87
        if isinstance(intf, HObjList):
1!
88
            _normalize_default_value_dict_for_HwIO_array(root_val, _val, elm_name, intf, neutral_value)
×
89
        else:
90
            root_val[elm_name] = _val
1✔
91

92

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

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

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

122
        for i, elm in enumerate(hwIO):
1✔
123
            if def_val is None:
1!
124
                _def_val = None
×
125
            elif isinstance(def_val, dict):
1!
126
                _def_val = def_val.get(i, None)
×
127
            else:
128
                _def_val = def_val[i]
1✔
129

130
            if nop_val is NOT_SPECIFIED:
1!
131
                _nop_val = NOT_SPECIFIED
1✔
132
            elif isinstance(nop_val, dict):
×
133
                _nop_val = nop_val.get(i, NOT_SPECIFIED)
×
134
            else:
135
                _nop_val = nop_val[i]
×
136
            if nextSig is NOT_SPECIFIED:
1!
137
                _nextSig = NOT_SPECIFIED
1✔
138
            else:
139
                _nextSig = nextSig.get(i, NOT_SPECIFIED)
×
140
            _instantiate_signals(elm, clk, rst, _def_val, _nop_val, _nextSig, signal_create_fn)
1✔
141

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

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

160
        for elm in hwIO._hwIOs:
1✔
161
            name = elm._name
1✔
162
            if def_val is None:
1✔
163
                _def_val = None
1✔
164
            else:
165
                _def_val = def_val.get(name, None)
1✔
166

167
            if nop_val is NOT_SPECIFIED:
1!
168
                _nop_val = NOT_SPECIFIED
1✔
169
            else:
170
                _nop_val = nop_val.get(name, NOT_SPECIFIED)
×
171

172
            if nextSig is NOT_SPECIFIED:
1!
173
                _nextSig = NOT_SPECIFIED
1✔
174
            else:
175
                _nextSig = getattr(nextSig, name)
×
176
            _instantiate_signals(elm, clk, rst, _def_val, _nop_val, _nextSig, signal_create_fn)
1✔
177

178

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

188

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

211

212
class HwModuleImplHelpers(HwModuleBase):
1✔
213

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

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

239
        if def_val is None:
1✔
240
            # if no value is specified reset is not required
241
            rst = None
1✔
242
        elif rst is None:
1✔
243
            rst = getRst(self)
1✔
244

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

267
    def _sig(self, name: str,
1✔
268
             dtype: HdlType=BIT,
269
             def_val: Union[int, None, dict, list]=None,
270
             nop_val: Union[int, None, dict, list, "NOT_SPECIFIED"]=NOT_SPECIFIED) -> RtlSignal:
271
        """
272
        Create signal in this unit
273

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

283
    @internal
1✔
284
    def _cleanThisSubunitRtlSignals(self):
1✔
285
        """
286
        Disconnect internal signals so unit can be reused by parent unit
287
        """
288
        for hwio in chain(self._hwIOs, self._private_hwIOs):
1✔
289
            hwio._cleanRtlSignals()
1✔
290

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

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