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

Nic30 / hwtSimApi / 4d09beae-0d47-4f56-86f4-9c052e9e29a2

17 Nov 2025 04:14PM UTC coverage: 71.62% (+1.1%) from 70.567%
4d09beae-0d47-4f56-86f4-9c052e9e29a2

push

circleci

Nic30
test(circleci): update to python 3.13.7

220 of 360 branches covered (61.11%)

Branch coverage included in aggregate %.

956 of 1282 relevant lines covered (74.57%)

0.75 hits per line

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

81.43
/hwtSimApi/basic_hdl_simulator/proxy.py
1
from typing import Union
1✔
2

3
from hwtSimApi.basic_hdl_simulator.sim_utils import valueHasChanged
1✔
4
from pyMathBitPrecise.array3t import Array3t
1✔
5
from pyMathBitPrecise.bits3t import Bits3t, Bits3val
1✔
6

7

8
class BasicRtlSimProxy():
1✔
9
    """
10
    Signal proxy which manages the access to a memory in simulation
11

12
    :ivar ~.callbacks: list of sim processes which will be waken up if signal value is updated
13
    :ivar ~.sim: main simulator
14
    :ivar ~._name: name of property which is this proxy stored in on parent
15
    :ivar ~._hdlName: signal name which was used in HDL
16
    :ivar ~._dtype: data type of this signal
17
    :ivar ~._origin: the object which was this proxy generated from
18
    :ivar ~._ag: agent which controls this proxy
19
    :ivar ~.parent: parent object
20
    :ivar ~.def_val: value used for initialization of value (done on sim. startup)
21
    :ivar ~.val: actual value of signal
22
    :ivar ~.val_next: place for metainformations about next update
23
    """
24
    __slots__ = ["callbacks", "sim", "_name", "_hdlName", "parent",
1✔
25
                 "_dtype", "_origin", "_ag",
26
                 "def_val", "val", "val_next",
27
                 "simRisingSensProcs", "simFallingSensProcs", "simSensProcs"]
28
    BIT_t = Bits3t(1, False)
1✔
29

30
    def __init__(self, sim: "BasicRtlSimulator", parent, name, dtype, def_val):
1✔
31
        self.callbacks = []
1✔
32
        self.sim = sim
1✔
33
        self.parent = parent
1✔
34
        self.def_val = def_val
1✔
35
        self.val = dtype.from_py(None)
1✔
36
        self.val_next = None
1✔
37
        # properties used for simplified associations and debug in python
38
        self._hdlName = name  # physical name
1✔
39
        self._name = name  # logical name
1✔
40
        self._dtype = dtype  # type notation for python
1✔
41
        self._origin = None  # signal object which this proxy substitutes
1✔
42
        self._ag = None  # simulation agent which drive or monitor this signal
1✔
43
        self.simRisingSensProcs = set()
1✔
44
        self.simFallingSensProcs = set()
1✔
45
        self.simSensProcs = set()
1✔
46

47
    def init_def_val(self, *args, **kwargs):
1✔
48
        self.def_val = self._dtype.from_py(*args, **kwargs)
×
49
        return self
×
50

51
    def read(self):
1✔
52
        assert self.sim.read_only_not_write_only
1✔
53
        return self.val.__copy__()
1✔
54

55
    def write(self, val: Union[None, int, Bits3val]):
1✔
56
        assert not self.sim.read_only_not_write_only
1✔
57
        t = getattr(val, "_dtype", None)
1✔
58
        if t is None:
1✔
59
            val = self._dtype.from_py(val)
1✔
60
        else:
61
            assert self._dtype.bit_length() == val._dtype.bit_length(), (self, val._dtype)
1✔
62
            val = self._dtype._from_py(
1✔
63
                val.val,
64
                val.vld_mask & self._dtype.all_mask()
65
            )
66
        if valueHasChanged(self.val, val):
1✔
67
            self.val = val
1✔
68
            self._propagate_changes(None)
1✔
69

70
    def wait(self, cb):
1✔
71
        self.callbacks.append(cb)
1✔
72
        self.sim.signals_checked_for_change.add(cb)
1✔
73

74
    def _apply_update(self, valUpdater):
1✔
75
        """
76
        Method called by simulator to update new value for this object
77
        """
78
        dirty_flag, new_val = valUpdater(self.val)
1✔
79
        assert new_val._dtype == self._dtype, (self, self.sim.time, new_val._dtype, self._dtype)
1✔
80
        if dirty_flag:
1✔
81
            self.val = new_val
1✔
82
            self._propagate_changes(valUpdater)
1✔
83

84
    def _propagate_changes(self, valUpdater):
1✔
85
        v = self.val
1✔
86
        sim = self.sim
1✔
87
        sim._updated_in_this_step.add(self)
1✔
88
        log = sim.logChange
1✔
89
        if log:
1!
90
            log(sim.time, self, v, valUpdater)
1✔
91

92
        log = sim.logPropagation
1✔
93
        if log:
1!
94
            log(sim, self, self.simSensProcs)
×
95

96
        # # run all sensitive processes
97
        for p in self.simSensProcs:
1✔
98
            sim._add_hdl_proc_to_run(self, p)
1✔
99

100
        # run write callbacks we have to create new list to allow
101
        # registering of new call backs in callbacks
102
        self.sim.pending_event_list.extend(self.callbacks)
1✔
103
        self.callbacks.clear()
1✔
104

105
        if self.simRisingSensProcs:
1✔
106
            if v.val or not v.vld_mask:
1✔
107
                if log:
1!
108
                    log(sim, self, self.simRisingSensProcs)
×
109
                for p in self.simRisingSensProcs:
1✔
110
                    sim._add_hdl_proc_to_run(self, p)
1✔
111

112
        if self.simFallingSensProcs:
1!
113
            if not v.val or not v.vld_mask:
×
114
                if log:
×
115
                    log(sim, self, self.simFallingSensProcs)
×
116
                for p in self.simFallingSensProcs:
×
117
                    sim._add_hdl_proc_to_run(self, p)
×
118

119
    def _onRisingEdge(self):
1✔
120
        v = self.val
1✔
121
        is_rising = self in self.sim._updated_in_this_step\
1✔
122
            and (v.val or not v.vld_mask)
123
        return self.BIT_t.from_py(int(is_rising), int(bool(v.vld_mask)))
1✔
124

125
    def _onFallingEdge(self):
1✔
126
        v = self.val
×
127
        is_falling = self in self.sim._updated_in_this_step\
×
128
            and (not v.val or not v.vld_mask)
129
        return self.BIT_t.from_py(int(is_falling), int(bool(v.vld_mask)))
×
130

131
    def __getitem__(self, index):
1✔
132
        if not isinstance(self._dtype, Array3t):
1!
133
            raise TypeError("%r is not iterable because it uses type %r"
×
134
                            % (self, self._dtype))
135
        elif index < 0 or index >= self._dtype.size:
1✔
136
            raise IndexError(self._dtype.size, index)
1✔
137
        else:
138
            return BasicRtlSimProxyArrItem(self, index)
1✔
139

140
    def __len__(self):
1✔
141
        if not isinstance(self._dtype, Array3t):
1!
142
            raise TypeError("%r is not iterable because it uses type %r"
×
143
                            % (self, self._dtype))
144
        else:
145
            return self._dtype.size
1✔
146

147
    def __repr__(self):
148
        return f"<{self.__class__.__name__:s} {self.parent}.{self._name:s} {self.val}<-{self.val_next}>"
149

150

151
class BasicRtlSimProxyArrItem():
1✔
152
    """
153
    Virtual proxy for an array item of BasicRtlSimProxy
154
    """
155

156
    def __init__(self, parent_proxy, item_index):
1✔
157
        self.parent_proxy = parent_proxy
1✔
158
        self.item_index = item_index
1✔
159
        self.sim = parent_proxy.sim
1✔
160
        self.parent = parent_proxy.parent
1✔
161
        self._dtype = parent_proxy._dtype.element_t
1✔
162

163
    def read(self):
1✔
164
        assert self.sim.read_only_not_write_only
1✔
165
        v = self.parent_proxy.val.val.get(self.item_index, None)
1✔
166
        if v is None:
1✔
167
            return self._dtype.from_py(None)
1✔
168

169
        return v.__copy__()
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