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

Nic30 / hwt / 733769f4-cf4a-49ab-be2e-a16b131a1a9c

13 Sep 2025 11:10AM UTC coverage: 83.85% (-0.7%) from 84.558%
733769f4-cf4a-49ab-be2e-a16b131a1a9c

push

circleci

Nic30
feat(HBitsRtlSignal._ternary): support non-scalar types

3439 of 4566 branches covered (75.32%)

Branch coverage included in aggregate %.

2 of 17 new or added lines in 1 file covered. (11.76%)

220 existing lines in 15 files now uncovered.

11966 of 13806 relevant lines covered (86.67%)

0.87 hits per line

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

88.24
/hwt/hwModule.py
1
from copy import copy
1✔
2
from natsort.natsort import natsorted
1✔
3
from typing import Optional, Union
1✔
4

5
from hdlConvertorAst.hdlAst._defs import HdlIdDef
1✔
6
from hdlConvertorAst.hdlAst._structural import HdlCompInst, HdlModuleDec
1✔
7
from hwt.doc_markers import internal
1✔
8
from hwt.hdl.portItem import HdlPortItem
1✔
9
from hwt.mainBases import HwIOBase
1✔
10
from hwt.synthesizer.dummyPlatform import DummyPlatform
1✔
11
from hwt.synthesizer.exceptions import IntfLvlConfErr
1✔
12
from hwt.synthesizer.interfaceLevel.hwModuleImplHelpers import HwModuleImplHelpers, \
1✔
13
    _default_param_updater
14
from hwt.synthesizer.interfaceLevel.propDeclrCollector import PropDeclrCollector
1✔
15
from hwt.synthesizer.rtlLevel.netlist import RtlNetlist
1✔
16
from hwt.synthesizer.typePath import TypePath
1✔
17
from ipCorePackager.constants import DIRECTION
1✔
18

19

20
class HdlConstraintList(list):
1✔
21
    """
22
    Containers of hw design constraints
23
    """
24
    pass
1✔
25

26

27
class HwModule(PropDeclrCollector, HwModuleImplHelpers):
1✔
28
    """
29
    Objects of this class are representation of design in hwt HCL.
30
    This object is a container of the netlist with interfaces
31
    and internal hierarchical structure.
32

33
    :cvar ~._serializeDecision: function to decide if HDL object derived from
34
        this unit should be serialized or not, if None all is always serialized
35
    :cvar ~._PROTECTED_NAMES: set of names which can not be overridden
36
    :ivar ~._hwIOs: all public interfaces
37
    :type ~._hwIOs: List[HwIO]
38
    :ivar ~._private_hwIOs: all internal interfaces
39
        which are not accessible from outside of unit
40
    :type _private_hwIOs: List[HwIO]
41
    :ivar ~._subHwModules: all units defined on this object
42
    :type ~._subHwModules: List[HwModule]
43
    :ivar ~._hwParams: all params defined on this object
44
    :type ~._hwParams: List[HwParam]
45
    :ivar ~._constraints: additional HW specifications
46
    :ivar ~._parent: parent object
47
    :type ~._parent: Optional[HwModule]
48
    :ivar ~._lazy_loaded: container of RTL object which were lazy loaded
49
        in implementation phase (this object has to be returned
50
        from :func:`~._to_rtl` of parent before it it's own objects)
51
    :ivar ~._shared_component_with: Optional tuple of the other :class:`hwt.hwModule.HwModule` instance
52
        which produces an exactly same component in HDL and interface
53
        signal map current to shared and shared to current
54
    :type ~._shared_component_with: Optional[Tuple[HwModule,
55
        Dict[Interface, Interface],
56
        Dict[Interface, Interface]]]
57
    :attention: if :func:`~._shared_component_with` is not None the body
58
        of this instance is not generated at all
59
        and the component from :func:`~._shared_component_with` is used instead
60
    :ivar ~._target_platform: meta-informations about target platform
61
    :ivar ~._name: a name of this component
62
    :ivar ~._onParentPropertyPath: :see: :class:`HwIO`
63
    :ivar ~._hdl_module_name: a name of HDL module for this component
64
        (vhdl entity name, Verilog module name)
65
    """
66

67
    _serializeDecision = None
1✔
68
    # properties which are used internally by this library
69
    _PROTECTED_NAMES = {
1✔
70
        "_PROTECTED_NAMES",
71
        "_name", "_hdl_module_name",
72
        "_hwIOs", "_private_hwIOs",
73
        "_units", "_hwParams", "_parent", "_constraints",
74
        "_lazy_loaded", "_rtlCtx", "_shared_component_with",
75
        "_target_platform", "_store_manager",
76
    }
77

78
    def __init__(self, hdlName:Optional[str]=None):
1✔
79
        self._parent: Optional[HwModule] = None
1✔
80
        self._name: Optional[str] = None
1✔
81
        self._onParentPropertyPath: Optional[TypePath] = None
1✔
82
        self._shared_component_with = None
1✔
83
        self._hdl_module_name: Optional[str] = None
1✔
84
        assert hdlName is None or isinstance(hdlName, str), hdlName
1✔
85
        self._hdlNameOverride = hdlName
1✔
86
        self._lazy_loaded: list[Union[HwModule, HwIOBase]] = []
1✔
87
        self._rtlCtx = RtlNetlist(self)
1✔
88
        self._constraints = HdlConstraintList()
1✔
89
        self._loadConfig()
1✔
90

91
    @internal
1✔
92
    def _loadHwIODeclarations(self, hwIO: HwIOBase, isExtern: bool):
1✔
93
        hwIO._loadHwDeclarations()
1✔
94
        hwIO._setAsExtern(isExtern)
1✔
95

96
    @internal
1✔
97
    def _loadHwDeclarations(self):
1✔
98
        """
99
        Load all declarations from _decl() method, recursively
100
        for all interfaces/units.
101
        """
102
        if not hasattr(self, "_hwIOs"):
1!
103
            self._hwIOs = []
1✔
104
        if not hasattr(self, "_private_hwIOs"):
1!
105
            self._private_hwIOs = []
1✔
106
        if not hasattr(self, "_subHwModules"):
1!
107
            self._subHwModules = []
1✔
108
        self._setAttrListener = self._declrCollector
1✔
109
        self.hwDeclr()
1✔
110
        self._setAttrListener = None
1✔
111
        for hio in self._hwIOs:
1✔
112
            self._loadHwIODeclarations(hio, True)
1✔
113

114
        # if I am a unit load subunits
115
        for u in self._subHwModules:
1✔
116
            u._loadHwDeclarations()
1✔
117

118
    @internal
1✔
119
    def _registerHwIOInHwImpl(self, hwIOName: str, hwIO: HwIOBase, onParentPath: TypePath):
1✔
120
        """
121
        Register interface in implementation phase
122
        """
123
        self._registerHwIO(hwIOName, hwIO, onParentPath, True)
1✔
124
        self._loadHwIODeclarations(hwIO, False)
1✔
125
        hwIO._signalsForHwIO(
1✔
126
            self._rtlCtx, None, self._store_manager.name_scope)
127

128
    def _getDefaultName(self) -> str:
1✔
129
        return self.__class__.__name__
1✔
130

131
    def _get_hdl_doc(self) -> Optional[str]:
1✔
132
        if self.__doc__ is not HwModule.__doc__:
1!
133
            return self.__doc__
1✔
134

135
    @internal
1✔
136
    def _to_rtl(self, target_platform: DummyPlatform,
1✔
137
                store_manager: "StoreManager", add_param_asserts=True):
138
        """
139
        synthesize all subunits, make connections between them,
140
        build verilog like module/vhdl like entity and architecture for this unit
141
        """
142
        if self._hdl_module_name is None:
1✔
143
            if self._hdlNameOverride:
1!
UNCOV
144
                self._hdl_module_name = self._hdlNameOverride
×
145
            else:
146
                self._hdl_module_name = self._getDefaultName()
1✔
147
        if self._name is None:
1✔
148
            self._name = self._getDefaultName()
1✔
149
        self._target_platform = target_platform
1✔
150
        self._store_manager = store_manager
1✔
151
        do_serialize_this, replacement = store_manager.filter.do_serialize(
1✔
152
            self)
153
        if replacement is not None:
1✔
154
            assert not do_serialize_this
1✔
155
            assert len(self._hwIOs) == len(replacement._hwIOs), \
1✔
156
                "No lazy loaded interfaces declared in hwImpl()"
157
            copy_HdlModuleDec(replacement, self)
1✔
158
            yield False, self
1✔
159
            self._cleanThisSubunitRtlSignals()
1✔
160
            self._subHwModules = None
1✔
161
            self._private_hwIOs = None
1✔
162
            hwIO_map_repl_to_self = sharedCompBuildHwIOMap(
1✔
163
                replacement, self)
164
            hwIO_map_self_to_repl = {
1✔
165
                v: k
166
                for k, v in hwIO_map_repl_to_self.items()}
167
            self._shared_component_with = replacement, \
1✔
168
                hwIO_map_self_to_repl, hwIO_map_repl_to_self
169
            return
1✔
170

171
        for proc in target_platform.beforeToRtl:
1!
UNCOV
172
            proc(self)
×
173

174
        mdec = self._rtlCtx.create_HdlModuleDec(
1✔
175
            self._hdl_module_name, store_manager, self._hwParams)
176
        mdec.origin = self
1✔
177
        mdec.doc = self._get_hdl_doc()
1✔
178

179
        # prepare signals for interfaces
180
        for hwIO in self._hwIOs:
1✔
181
            if hwIO._isExtern:
1!
182
                ei = self._rtlCtx.hwIOs
1✔
183
            else:
UNCOV
184
                ei = None
×
185
            # we are reversing direction because we are looking
186
            # at the interface from inside of component
187
            hwIO._signalsForHwIO(
1✔
188
                self._rtlCtx, ei,
189
                store_manager.name_scope, reverse_dir=True)
190
        store_manager.hierarchy_pop(mdec)
1✔
191

192
        if do_serialize_this:
1✔
193
            # prepare subunits
194
            for sm in self._subHwModules:
1✔
195
                yield from sm._to_rtl(target_platform, store_manager)
1✔
196

197
            # now every sub unit has a HdlModuleDec prepared
198
            for sm in self._subHwModules:
1✔
199
                subHwModuleName = sm._name
1✔
200
                sm._signalsForSubHwModuleEntity(self._rtlCtx, "sig_" + subHwModuleName)
1✔
201

202
            for proc in target_platform.beforeToRtlImpl:
1!
UNCOV
203
                proc(self)
×
204

205
        try:
1✔
206
            store_manager.hierarchy_push(mdec)
1✔
207
            if do_serialize_this:
1✔
208
                self._loadImpl()
1✔
209
                yield from self._lazy_loaded
1✔
210

211
                if not self._rtlCtx.hwIOs:
1!
UNCOV
212
                    raise IntfLvlConfErr(
×
213
                        "Can not find any external interface for unit %s"
214
                        "- unit without interfaces are not synthesisable"
215
                        % self._name)
216

217
            for proc in target_platform.afterToRtlImpl:
1!
UNCOV
218
                proc(self)
×
219

220
            mdec.params[:] = natsorted(mdec.params, key=lambda x: x.name)
1✔
221
            mdec.ports[:] = natsorted(mdec.ports, key=lambda x: x.name)
1✔
222
            if do_serialize_this:
1✔
223
                # synthesize signal level context
224
                mdef = self._rtlCtx.create_HdlModuleDef(
1✔
225
                    target_platform, store_manager)
226
                mdef.origin = self
1✔
227

228
            for hwIO in self._hwIOs:
1✔
229
                if hwIO._isExtern:
1!
230
                    # reverse because other components
231
                    # looks at this interface from the outside
232
                    hwIO._reverseDirection()
1✔
233

234
            if do_serialize_this:
1✔
235
                if add_param_asserts and self._hwParams:
1✔
236
                    mdef.objs.extend(store_manager.as_hdl_ast._as_hdl_HdlModuleDef_param_asserts(mdec))
1✔
237
                store_manager.write(mdef)
1✔
238

239
            yield True, self
1✔
240

241
            # after synthesis clean up interface so this :class:`hwt.hwModule.HwModule` object can be
242
            # used elsewhere
243
            self._cleanThisSubunitRtlSignals()
1✔
244
            if do_serialize_this:
1✔
245
                self._checkCompInstances()
1✔
246

247
            for proc in target_platform.afterToRtl:
1!
UNCOV
248
                proc(self)
×
249
        finally:
250
            store_manager.hierarchy_pop(mdec)
1✔
251

252
    def _updateHwParamsFrom(self, otherObj: PropDeclrCollector,
1✔
253
                          updater=_default_param_updater,
254
                          exclude: Optional[tuple[set[str], set[str]]]=None,
255
                          prefix=""):
256
        """
257
        :note: doc in
258
            :func:`hwt.synthesizer.interfaceLevel.propDeclCollector._updateHwParamsFrom`
259
        """
260
        return PropDeclrCollector._updateHwParamsFrom(self, otherObj,
1✔
261
                                                    updater, exclude, prefix)
262

263
    @internal
1✔
264
    def _checkCompInstances(self):
1✔
265
        cInstances = [o for o in self._rtlCtx.hwModDef.objs
1✔
266
                      if isinstance(o, HdlCompInst)]
267
        cInst_cnt = len(cInstances)
1✔
268
        unit_cnt = len(self._subHwModules)
1✔
269
        if cInst_cnt != unit_cnt:
1!
270
            # resolve the error message
271
            inRtl = set(x.name for x in cInstances)
×
272
            inHwIO = set(x._name for x in self._subHwModules)
×
273
            cls_name = self.__class__.__name__
×
274
            if cInst_cnt > unit_cnt:
×
275
                diff = inRtl - inHwIO
×
UNCOV
276
                raise IntfLvlConfErr(
×
277
                    f"{cls_name:s}, {self._name:s}: unit(s) were found in HDL but were"
278
                    f" not registered {diff}")
279
            else:
280
                assert cInst_cnt < unit_cnt
×
281
                diff = inHwIO - inRtl
×
UNCOV
282
                raise IntfLvlConfErr(
×
283
                    f"{cls_name:s}, {self._name:s}: _to_rtl: unit(s) are missing in produced HDL {diff}")
284

285

286
def copy_HdlModuleDec_HwIO(orig_io: HwIOBase, new_io: HwIOBase,
1✔
287
                           ports: list[HdlPortItem], new_m: HwModule):
288
    new_io._direction = orig_io._direction
1✔
289
    if orig_io._hdlPort is not None:
1✔
290
        s = orig_io._sigInside
1✔
291
        assert s is not None, (
1✔
292
            "the component which shares a body with this component"
293
            " is actually some parent of this component")
294
        pi = copy(orig_io._hdlPort)
1✔
295
        pi.module = new_m
1✔
296
        ports.append(pi)
1✔
297
        d = pi.direction
1✔
298
        if d == DIRECTION.OUT:
1✔
299
            pi.dst = None
1✔
300
        elif d == DIRECTION.IN:
1✔
301
            pi.src = None
1✔
302
        else:
303
            raise NotImplementedError(d)
304
        new_io._hdlPort = pi
1✔
305
        new_io._sigInside = s
1✔
306
    else:
307
        for hwIO in orig_io._hwIOs:
1✔
308
            n_i = getattr(new_io, hwIO._name)
1✔
309
            copy_HdlModuleDec_HwIO(hwIO, n_i, ports, new_m)
1✔
310

311

312
def copy_HdlModuleDec(orig_m: HwModule, new_m: HwModule):
1✔
313
    assert not new_m._rtlCtx.statements
1✔
314
    assert not new_m._rtlCtx.hwIOs
1✔
315
    assert not new_m._rtlCtx.signals
1✔
316
    assert new_m._rtlCtx.hwModDec is None
1✔
317

318
    new_m._hdl_module_name = orig_m._hdl_module_name
1✔
319
    hwModDec = new_m._rtlCtx.hwModDec = copy(orig_m._rtlCtx.hwModDec)
1✔
320
    hwModDec: HdlModuleDec
321

322
    params = []
1✔
323
    param_by_name = {p._name: p for p in new_m._hwParams}
1✔
324
    for p in hwModDec.params:
1✔
325
        p: HdlIdDef
326
        new_p_def = copy(p)
1✔
327
        old_p = new_p_def.origin = param_by_name[p.origin._name]
1✔
328
        old_p._name = p.origin._name
1✔
329
        new_p_def.value = old_p.get_hdl_value()
1✔
330
        params.append(new_p_def)
1✔
331

332
    hwModDec.params = params
1✔
333

334
    hwModDec.ports = []
1✔
335
    for hwO, hwI in zip(orig_m._hwIOs, new_m._hwIOs):
1✔
336
        if hwO._isExtern:
1!
337
            copy_HdlModuleDec_HwIO(hwO, hwI, hwModDec.ports, new_m)
1✔
338

339
    # params should be already sorted
340
    # hwModDec.params[:] = natsorted(hwModDec.params, key=lambda x: x.name)
341
    hwModDec.ports[:] = natsorted(hwModDec.ports, key=lambda x: x.name)
1✔
342

343

344
def _sharedCompBuildHwIOMapList(replacement: list[HwIOBase],
1✔
345
                                          substituted: list[HwIOBase],
346
                                          res: dict[HwIOBase, HwIOBase]):
347
    assert len(replacement) == len(substituted)
1✔
348
    for r, s in zip(replacement, substituted):
1✔
349
        assert r._name == s._name, (r._name, s._name)
1✔
350
        res[r] = s
1✔
351
        if r._hwIOs:
1✔
352
            _sharedCompBuildHwIOMapList(
1✔
353
                r._hwIOs, s._hwIOs, res)
354

355

356
def sharedCompBuildHwIOMap(replacement_m: HwModule, substituted_m: HwModule):
1✔
357
    """
358
    Build a dictionary which maps
359
    interface of replacement_m to interface of substituted_m
360
    """
361
    res = {}
1✔
362
    _sharedCompBuildHwIOMapList(
1✔
363
        replacement_m._hwIOs, substituted_m._hwIOs, res)
364
    return res
1✔
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