digsim-logic-simulator 0.7.0__py3-none-any.whl → 0.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of digsim-logic-simulator might be problematic. Click here for more details.
- digsim/app/gui/_circuit_area.py +2 -2
- digsim/app/gui_objects/_image_objects.py +4 -2
- digsim/circuit/_circuit.py +60 -41
- digsim/circuit/_waves_writer.py +19 -8
- digsim/circuit/components/_label_wire.py +3 -3
- digsim/circuit/components/_yosys_component.py +57 -46
- digsim/circuit/components/atoms/__init__.py +2 -1
- digsim/circuit/components/atoms/_component.py +40 -37
- digsim/circuit/components/atoms/_port.py +70 -65
- digsim/circuit/components/ic/74162.json +88 -86
- digsim/circuit/components/ic/7448.json +75 -73
- digsim/utils/__init__.py +1 -1
- digsim/utils/_yosys_netlist.py +87 -234
- {digsim_logic_simulator-0.7.0.dist-info → digsim_logic_simulator-0.9.0.dist-info}/METADATA +5 -38
- {digsim_logic_simulator-0.7.0.dist-info → digsim_logic_simulator-0.9.0.dist-info}/RECORD +18 -18
- {digsim_logic_simulator-0.7.0.dist-info → digsim_logic_simulator-0.9.0.dist-info}/WHEEL +1 -1
- {digsim_logic_simulator-0.7.0.dist-info → digsim_logic_simulator-0.9.0.dist-info}/licenses/LICENSE.md +0 -0
- {digsim_logic_simulator-0.7.0.dist-info → digsim_logic_simulator-0.9.0.dist-info}/top_level.txt +0 -0
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
# Copyright (c) Fredrik Andersson, 2023-
|
|
1
|
+
# Copyright (c) Fredrik Andersson, 2023-2025
|
|
2
2
|
# All rights reserved
|
|
3
3
|
|
|
4
4
|
"""This module contains the base classes for all component types"""
|
|
5
5
|
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
6
8
|
import abc
|
|
7
9
|
import copy
|
|
10
|
+
from typing import Callable
|
|
8
11
|
|
|
9
12
|
from ._digsim_exception import DigsimException
|
|
13
|
+
from ._port import Port
|
|
10
14
|
|
|
11
15
|
|
|
12
16
|
class ComponentException(DigsimException):
|
|
@@ -16,15 +20,14 @@ class ComponentException(DigsimException):
|
|
|
16
20
|
class Component(abc.ABC):
|
|
17
21
|
"""The component base class"""
|
|
18
22
|
|
|
19
|
-
def __init__(self, circuit, name=None, display_name=None):
|
|
23
|
+
def __init__(self, circuit, name: str | None = None, display_name: str | None = None):
|
|
20
24
|
self._circuit = circuit
|
|
21
|
-
self._name = name or self.__class__.__name__
|
|
22
|
-
self._parent = None
|
|
23
|
-
self._ports = []
|
|
24
|
-
self._edge_detect_dict = {}
|
|
25
|
+
self._name: str = name or self.__class__.__name__
|
|
26
|
+
self._parent: Component | None = None
|
|
27
|
+
self._ports: list[Port] = []
|
|
25
28
|
self._circuit.add_component(self)
|
|
26
|
-
self._display_name = display_name or self.__class__.__name__
|
|
27
|
-
self._parameters = {}
|
|
29
|
+
self._display_name: str = display_name or self.__class__.__name__
|
|
30
|
+
self._parameters: dict[str, int | str | bool] = {}
|
|
28
31
|
|
|
29
32
|
def init(self):
|
|
30
33
|
"""Initialize port, will be called when circuit is initialized"""
|
|
@@ -37,15 +40,15 @@ class Component(abc.ABC):
|
|
|
37
40
|
def clear(self):
|
|
38
41
|
"""Remove static state within the component class"""
|
|
39
42
|
|
|
40
|
-
def parameter_set(self, parameter, value):
|
|
43
|
+
def parameter_set(self, parameter: str, value: int | str | bool):
|
|
41
44
|
"""Set component parameter"""
|
|
42
45
|
self._parameters[parameter] = value
|
|
43
46
|
|
|
44
|
-
def parameter_get(self, parameter):
|
|
47
|
+
def parameter_get(self, parameter: str) -> int | str | bool:
|
|
45
48
|
"""Get component parameter"""
|
|
46
49
|
return self._parameters[parameter]
|
|
47
50
|
|
|
48
|
-
def add_port(self, port):
|
|
51
|
+
def add_port(self, port: Port):
|
|
49
52
|
"""
|
|
50
53
|
Add port to component,
|
|
51
54
|
also add a 'portname' variable to the component with help of the 'self.__dict__'
|
|
@@ -59,7 +62,7 @@ class Component(abc.ABC):
|
|
|
59
62
|
"""
|
|
60
63
|
self._ports = []
|
|
61
64
|
|
|
62
|
-
def path(self):
|
|
65
|
+
def path(self) -> str:
|
|
63
66
|
"""Get component path"""
|
|
64
67
|
if self._parent is not None:
|
|
65
68
|
return f"{self._parent.path()}.{self.name()}"
|
|
@@ -70,22 +73,22 @@ class Component(abc.ABC):
|
|
|
70
73
|
"""Get component ports"""
|
|
71
74
|
return self._ports
|
|
72
75
|
|
|
73
|
-
def _get_ports(self, output):
|
|
76
|
+
def _get_ports(self, output) -> list[Port]:
|
|
74
77
|
sel_ports = []
|
|
75
78
|
for port in self._ports:
|
|
76
79
|
if port.is_output() == output:
|
|
77
80
|
sel_ports.append(port)
|
|
78
81
|
return sel_ports
|
|
79
82
|
|
|
80
|
-
def inports(self):
|
|
83
|
+
def inports(self) -> list[Port]:
|
|
81
84
|
"""Get component input ports"""
|
|
82
85
|
return self._get_ports(False)
|
|
83
86
|
|
|
84
|
-
def outports(self):
|
|
87
|
+
def outports(self) -> list[Port]:
|
|
85
88
|
"""Get component output ports"""
|
|
86
89
|
return self._get_ports(True)
|
|
87
90
|
|
|
88
|
-
def port(self, portname):
|
|
91
|
+
def port(self, portname: str) -> Port:
|
|
89
92
|
"""Get port with name 'portname'"""
|
|
90
93
|
for port in self._ports:
|
|
91
94
|
if port.name() == portname:
|
|
@@ -97,46 +100,46 @@ class Component(abc.ABC):
|
|
|
97
100
|
"""Get the circuit for the current component"""
|
|
98
101
|
return self._circuit
|
|
99
102
|
|
|
100
|
-
def name(self):
|
|
103
|
+
def name(self) -> str:
|
|
101
104
|
"""Get the component name"""
|
|
102
105
|
return self._name
|
|
103
106
|
|
|
104
|
-
def set_name(self, name, update_circuit=True):
|
|
107
|
+
def set_name(self, name: str, update_circuit: bool = True):
|
|
105
108
|
"""Set the component name"""
|
|
106
109
|
if update_circuit:
|
|
107
110
|
self.circuit.change_component_name(self, name)
|
|
108
111
|
else:
|
|
109
112
|
self._name = name
|
|
110
113
|
|
|
111
|
-
def display_name(self):
|
|
114
|
+
def display_name(self) -> str:
|
|
112
115
|
"""Get the component display name"""
|
|
113
116
|
return self._display_name
|
|
114
117
|
|
|
115
|
-
def set_display_name(self, display_name):
|
|
118
|
+
def set_display_name(self, display_name: str):
|
|
116
119
|
"""Set the component display name"""
|
|
117
120
|
self._display_name = display_name
|
|
118
121
|
|
|
119
122
|
@property
|
|
120
|
-
def parent(self):
|
|
123
|
+
def parent(self) -> Component | None:
|
|
121
124
|
"""Get parent component"""
|
|
122
125
|
return self._parent
|
|
123
126
|
|
|
124
|
-
def is_toplevel(self):
|
|
125
|
-
"""Return True if this component is a toplevel component"""
|
|
126
|
-
return self._parent is None
|
|
127
|
-
|
|
128
127
|
@parent.setter
|
|
129
|
-
def parent(self, parent):
|
|
128
|
+
def parent(self, parent: Component):
|
|
130
129
|
"""Set component parent"""
|
|
131
130
|
self._parent = parent
|
|
132
131
|
|
|
132
|
+
def is_toplevel(self) -> bool:
|
|
133
|
+
"""Return True if this component is a toplevel component"""
|
|
134
|
+
return self._parent is None
|
|
135
|
+
|
|
133
136
|
@property
|
|
134
137
|
def wire(self):
|
|
135
138
|
"""Property needed to be able to have a setter"""
|
|
136
139
|
raise ComponentException(f"Cannot get wire for component '{self.display_name}'")
|
|
137
140
|
|
|
138
141
|
@wire.setter
|
|
139
|
-
def wire(self, port):
|
|
142
|
+
def wire(self, port: Port):
|
|
140
143
|
"""Some components have a single output port, they can wired at component level"""
|
|
141
144
|
self.outports()[0].wire = port
|
|
142
145
|
|
|
@@ -146,14 +149,14 @@ class Component(abc.ABC):
|
|
|
146
149
|
def remove_connections(self):
|
|
147
150
|
"""Remove component connections"""
|
|
148
151
|
for src_port in self.outports():
|
|
149
|
-
for dst_port in src_port.
|
|
152
|
+
for dst_port in src_port.wired_ports:
|
|
150
153
|
dst_port.set_driver(None)
|
|
151
154
|
|
|
152
155
|
for dst_port in self.inports():
|
|
153
156
|
if dst_port.has_driver():
|
|
154
157
|
dst_port.get_driver().disconnect(dst_port)
|
|
155
158
|
|
|
156
|
-
def add_event(self, port, value, delay_ns):
|
|
159
|
+
def add_event(self, port: Port, value: int, delay_ns: int):
|
|
157
160
|
"""Add delta cycle event"""
|
|
158
161
|
self.circuit.add_event(port, value, delay_ns)
|
|
159
162
|
|
|
@@ -166,12 +169,12 @@ class Component(abc.ABC):
|
|
|
166
169
|
return comp_str
|
|
167
170
|
|
|
168
171
|
@property
|
|
169
|
-
def has_action(self):
|
|
172
|
+
def has_action(self) -> bool:
|
|
170
173
|
"""Return True if this component is interactive"""
|
|
171
174
|
return False
|
|
172
175
|
|
|
173
176
|
@property
|
|
174
|
-
def active(self):
|
|
177
|
+
def active(self) -> bool:
|
|
175
178
|
"""Return True if this component is active/activated ('on' for a switch for example)"""
|
|
176
179
|
return False
|
|
177
180
|
|
|
@@ -185,7 +188,7 @@ class Component(abc.ABC):
|
|
|
185
188
|
"""Get component settings from dict"""
|
|
186
189
|
raise ComponentException(f"No setup for component '{self.display_name}'")
|
|
187
190
|
|
|
188
|
-
def settings_to_dict(self):
|
|
191
|
+
def settings_to_dict(self) -> dict[str, int | str | bool]:
|
|
189
192
|
"""Return component settings as a dict"""
|
|
190
193
|
return copy.deepcopy(self._parameters)
|
|
191
194
|
|
|
@@ -194,7 +197,7 @@ class Component(abc.ABC):
|
|
|
194
197
|
"""Return parameters"""
|
|
195
198
|
return {}
|
|
196
199
|
|
|
197
|
-
def update_settings(self, settings):
|
|
200
|
+
def update_settings(self, settings: dict[str, int | str | bool]):
|
|
198
201
|
"""Update parameters from settings dict"""
|
|
199
202
|
for setting, value in settings.items():
|
|
200
203
|
self.parameter_set(setting, value)
|
|
@@ -222,9 +225,9 @@ class Component(abc.ABC):
|
|
|
222
225
|
class MultiComponent(Component):
|
|
223
226
|
"""A component that holds one or several sub components"""
|
|
224
227
|
|
|
225
|
-
def __init__(self, circuit, name):
|
|
228
|
+
def __init__(self, circuit, name: str):
|
|
226
229
|
super().__init__(circuit, name)
|
|
227
|
-
self._components = []
|
|
230
|
+
self._components: list[Component] = []
|
|
228
231
|
|
|
229
232
|
def init(self):
|
|
230
233
|
super().init()
|
|
@@ -253,11 +256,11 @@ class CallbackComponent(Component):
|
|
|
253
256
|
objects when the component change value.
|
|
254
257
|
"""
|
|
255
258
|
|
|
256
|
-
def __init__(self, circuit, name, callback=None):
|
|
259
|
+
def __init__(self, circuit, name: str, callback: Callable[[Component], None] | None = None):
|
|
257
260
|
super().__init__(circuit, name)
|
|
258
261
|
self._callback = callback
|
|
259
262
|
|
|
260
|
-
def set_callback(self, callback):
|
|
263
|
+
def set_callback(self, callback: Callable[[Component], None]):
|
|
261
264
|
"""Set CallbackComponent callback function"""
|
|
262
265
|
self._callback = callback
|
|
263
266
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
# Copyright (c) Fredrik Andersson, 2023-
|
|
1
|
+
# Copyright (c) Fredrik Andersson, 2023-2025
|
|
2
2
|
# All rights reserved
|
|
3
3
|
|
|
4
4
|
"""This module contains the classes for all component ports"""
|
|
5
5
|
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
6
8
|
import abc
|
|
7
9
|
|
|
8
10
|
from ._digsim_exception import DigsimException
|
|
@@ -15,14 +17,14 @@ class PortConnectionError(DigsimException):
|
|
|
15
17
|
class Port(abc.ABC):
|
|
16
18
|
"""The abstract base class for all ports"""
|
|
17
19
|
|
|
18
|
-
def __init__(self, parent, name, width=1, output=False):
|
|
20
|
+
def __init__(self, parent, name: str, width: int = 1, output: bool = False):
|
|
19
21
|
self._parent = parent # The parent component
|
|
20
|
-
self._name = name # The name of this port
|
|
21
|
-
self._width = width # The bit-width of this port
|
|
22
|
-
self._output = output # Is this port an output port
|
|
23
|
-
self._wired_ports = [] # The ports that this port drives
|
|
24
|
-
self._value = None # The value of this port
|
|
25
|
-
self._edge_detect_value = "X" # Last edge detect value
|
|
22
|
+
self._name: str = name # The name of this port
|
|
23
|
+
self._width: int = width # The bit-width of this port
|
|
24
|
+
self._output: bool = output # Is this port an output port
|
|
25
|
+
self._wired_ports: list[Port] = [] # The ports that this port drives
|
|
26
|
+
self._value: int | str | None = None # The value of this port
|
|
27
|
+
self._edge_detect_value: int | str | None = "X" # Last edge detect value
|
|
26
28
|
self.init() # Initialize the port
|
|
27
29
|
|
|
28
30
|
def init(self):
|
|
@@ -32,27 +34,27 @@ class Port(abc.ABC):
|
|
|
32
34
|
self.update_wires("X")
|
|
33
35
|
|
|
34
36
|
@property
|
|
35
|
-
def wired_ports(self):
|
|
37
|
+
def wired_ports(self) -> list[Port]:
|
|
36
38
|
"""Get wires from thisport"""
|
|
37
39
|
return self._wired_ports
|
|
38
40
|
|
|
39
41
|
@property
|
|
40
|
-
def value(self):
|
|
42
|
+
def value(self) -> int | str | None:
|
|
41
43
|
"""Get the value of the port, can be "X" """
|
|
42
44
|
return self._value
|
|
43
45
|
|
|
44
46
|
@value.setter
|
|
45
|
-
def value(self, value):
|
|
47
|
+
def value(self, value: int | str | None):
|
|
46
48
|
"""Set the value of the port"""
|
|
47
49
|
self.set_value(value)
|
|
48
50
|
|
|
49
51
|
@property
|
|
50
|
-
def width(self):
|
|
52
|
+
def width(self) -> int:
|
|
51
53
|
"""Get the bit-width of the port"""
|
|
52
54
|
return self._width
|
|
53
55
|
|
|
54
56
|
@width.setter
|
|
55
|
-
def width(self, width):
|
|
57
|
+
def width(self, width: int):
|
|
56
58
|
"""Set the bit-width of the port, will force a disconnect if it is connected"""
|
|
57
59
|
if width != self._width:
|
|
58
60
|
driver = self.get_driver()
|
|
@@ -68,7 +70,7 @@ class Port(abc.ABC):
|
|
|
68
70
|
raise PortConnectionError("Cannot get a wire")
|
|
69
71
|
|
|
70
72
|
@wire.setter
|
|
71
|
-
def wire(self, port):
|
|
73
|
+
def wire(self, port: PortWire):
|
|
72
74
|
"""Wire setter, connect this port to an input port (of same width)"""
|
|
73
75
|
if port.has_driver():
|
|
74
76
|
raise PortConnectionError(f"The port {port.path()}.{port.name()} already has a driver")
|
|
@@ -84,11 +86,11 @@ class Port(abc.ABC):
|
|
|
84
86
|
port.set_driver(None)
|
|
85
87
|
self._wired_ports = []
|
|
86
88
|
|
|
87
|
-
def name(self):
|
|
89
|
+
def name(self) -> str:
|
|
88
90
|
"""Get port name"""
|
|
89
91
|
return self._name
|
|
90
92
|
|
|
91
|
-
def path(self):
|
|
93
|
+
def path(self) -> str:
|
|
92
94
|
"""Get port path, <component_name>...<component_name>"""
|
|
93
95
|
return self._parent.path()
|
|
94
96
|
|
|
@@ -96,7 +98,7 @@ class Port(abc.ABC):
|
|
|
96
98
|
"""Get parent component"""
|
|
97
99
|
return self._parent
|
|
98
100
|
|
|
99
|
-
def update_wires(self, value):
|
|
101
|
+
def update_wires(self, value: int | str | None):
|
|
100
102
|
"""Update connected wires (and self._value) with value"""
|
|
101
103
|
if self._value == value:
|
|
102
104
|
return
|
|
@@ -104,26 +106,22 @@ class Port(abc.ABC):
|
|
|
104
106
|
for port in self._wired_ports:
|
|
105
107
|
port.value = self._value
|
|
106
108
|
|
|
107
|
-
def
|
|
108
|
-
"""Get connected ports"""
|
|
109
|
-
return self._wired_ports
|
|
110
|
-
|
|
111
|
-
def get_wired_ports_recursive(self):
|
|
109
|
+
def get_wired_ports_recursive(self) -> list[Port]:
|
|
112
110
|
"""Get all connected ports (recursive)"""
|
|
113
111
|
all_wired_ports = [self]
|
|
114
112
|
for port in self._wired_ports:
|
|
115
113
|
all_wired_ports.extend(port.get_wired_ports_recursive())
|
|
116
114
|
return all_wired_ports
|
|
117
115
|
|
|
118
|
-
def is_output(self):
|
|
116
|
+
def is_output(self) -> bool:
|
|
119
117
|
"""Return True if this port is an output port"""
|
|
120
118
|
return self._output
|
|
121
119
|
|
|
122
|
-
def is_input(self):
|
|
120
|
+
def is_input(self) -> bool:
|
|
123
121
|
"""Return True if this port is an input port"""
|
|
124
122
|
return not self._output
|
|
125
123
|
|
|
126
|
-
def is_rising_edge(self):
|
|
124
|
+
def is_rising_edge(self) -> bool:
|
|
127
125
|
"""
|
|
128
126
|
Return True if a rising edge has occured
|
|
129
127
|
Note: This function can only be called once per 'update'
|
|
@@ -134,7 +132,7 @@ class Port(abc.ABC):
|
|
|
134
132
|
self._edge_detect_value = self.value
|
|
135
133
|
return rising_edge
|
|
136
134
|
|
|
137
|
-
def is_falling_edge(self):
|
|
135
|
+
def is_falling_edge(self) -> bool:
|
|
138
136
|
"""
|
|
139
137
|
Return True if a falling edge has occured
|
|
140
138
|
Note: This function can only be called once per 'update'
|
|
@@ -146,14 +144,21 @@ class Port(abc.ABC):
|
|
|
146
144
|
return falling_edge
|
|
147
145
|
|
|
148
146
|
@abc.abstractmethod
|
|
149
|
-
def set_value(self, value):
|
|
147
|
+
def set_value(self, value: int | str | None):
|
|
150
148
|
"""Set value on port"""
|
|
151
149
|
|
|
152
150
|
@abc.abstractmethod
|
|
153
|
-
def set_driver(self, port):
|
|
151
|
+
def set_driver(self, port: Port | None):
|
|
154
152
|
"""Set port driver"""
|
|
155
153
|
|
|
156
|
-
|
|
154
|
+
@abc.abstractmethod
|
|
155
|
+
def has_driver(self) -> bool:
|
|
156
|
+
"""Return True if port has driver"""
|
|
157
|
+
|
|
158
|
+
def get_driver(self):
|
|
159
|
+
"""Get port driver"""
|
|
160
|
+
|
|
161
|
+
def can_add_wire(self) -> bool:
|
|
157
162
|
"""Return True if it is possible to add a wire to this port"""
|
|
158
163
|
if self.is_output():
|
|
159
164
|
return True
|
|
@@ -161,14 +166,14 @@ class Port(abc.ABC):
|
|
|
161
166
|
return True
|
|
162
167
|
return False
|
|
163
168
|
|
|
164
|
-
def disconnect(self, port):
|
|
169
|
+
def disconnect(self, port: Port):
|
|
165
170
|
"""Disconnect port if it is wired"""
|
|
166
171
|
if port in self._wired_ports:
|
|
167
172
|
index = self._wired_ports.index(port)
|
|
168
173
|
del self._wired_ports[index]
|
|
169
174
|
port.set_driver(None)
|
|
170
175
|
|
|
171
|
-
def strval(self):
|
|
176
|
+
def strval(self) -> str:
|
|
172
177
|
"""Return value as string"""
|
|
173
178
|
if self.value == "X":
|
|
174
179
|
return "X"
|
|
@@ -176,7 +181,7 @@ class Port(abc.ABC):
|
|
|
176
181
|
return f"0x{self.value:x}"
|
|
177
182
|
return f"{self.value}"
|
|
178
183
|
|
|
179
|
-
def __str__(self):
|
|
184
|
+
def __str__(self) -> str:
|
|
180
185
|
return f"{self._parent.name()}:{self._name}={self.value}"
|
|
181
186
|
|
|
182
187
|
|
|
@@ -186,22 +191,22 @@ class PortWire(Port):
|
|
|
186
191
|
* The port wire will instantaneously update the driven wires upon change.
|
|
187
192
|
"""
|
|
188
193
|
|
|
189
|
-
def __init__(self, parent, name, width=1, output=False):
|
|
194
|
+
def __init__(self, parent, name: str, width: int = 1, output: bool = False):
|
|
190
195
|
super().__init__(parent, name, width, output)
|
|
191
|
-
self._port_driver = None # The port that drives this port
|
|
196
|
+
self._port_driver: Port | None = None # The port that drives this port
|
|
192
197
|
|
|
193
|
-
def set_value(self, value):
|
|
198
|
+
def set_value(self, value: int | str | None):
|
|
194
199
|
if value != self.value:
|
|
195
200
|
self.update_wires(value)
|
|
196
201
|
|
|
197
|
-
def set_driver(self, port):
|
|
202
|
+
def set_driver(self, port: Port | None):
|
|
198
203
|
self._port_driver = port
|
|
199
204
|
|
|
200
|
-
def get_driver(self):
|
|
205
|
+
def get_driver(self) -> Port | None:
|
|
201
206
|
"""Get driver for port"""
|
|
202
207
|
return self._port_driver
|
|
203
208
|
|
|
204
|
-
def has_driver(self):
|
|
209
|
+
def has_driver(self) -> bool:
|
|
205
210
|
"""Return True if port has driver"""
|
|
206
211
|
return self._port_driver is not None
|
|
207
212
|
|
|
@@ -213,10 +218,10 @@ class PortIn(PortWire):
|
|
|
213
218
|
* The port will update the parent component upon change.
|
|
214
219
|
"""
|
|
215
220
|
|
|
216
|
-
def __init__(self, parent, name, width=1):
|
|
221
|
+
def __init__(self, parent, name: str, width: int = 1):
|
|
217
222
|
super().__init__(parent, name, width, output=False)
|
|
218
223
|
|
|
219
|
-
def set_value(self, value):
|
|
224
|
+
def set_value(self, value: int | str | None):
|
|
220
225
|
super().set_value(value)
|
|
221
226
|
self.parent().update()
|
|
222
227
|
|
|
@@ -228,40 +233,40 @@ class PortOutDelta(Port):
|
|
|
228
233
|
* The port will update the parent component if the _update_parent variable is set to true.
|
|
229
234
|
"""
|
|
230
235
|
|
|
231
|
-
def __init__(self, parent, name, width=1, delay_ns=1):
|
|
236
|
+
def __init__(self, parent, name: str, width: int = 1, delay_ns: int = 1):
|
|
232
237
|
super().__init__(parent, name, width, output=True)
|
|
233
238
|
self._delay_ns = delay_ns # Propagation delay for this port
|
|
234
239
|
self._update_parent = False # Should this port update parent on change
|
|
235
240
|
|
|
236
|
-
def update_parent(self, update_parent):
|
|
241
|
+
def update_parent(self, update_parent: bool):
|
|
237
242
|
"""Set update parent valiable (True/False)"""
|
|
238
243
|
self._update_parent = update_parent
|
|
239
244
|
|
|
240
|
-
def set_delay_ns(self, delay_ns):
|
|
245
|
+
def set_delay_ns(self, delay_ns: int):
|
|
241
246
|
"""Set port propagation delay"""
|
|
242
247
|
self._delay_ns = delay_ns
|
|
243
248
|
|
|
244
|
-
def set_value(self, value):
|
|
249
|
+
def set_value(self, value: int | str | None):
|
|
245
250
|
self.parent().add_event(self, value, self._delay_ns)
|
|
246
251
|
|
|
247
|
-
def update_port(self, value):
|
|
252
|
+
def update_port(self, value: int | str | None):
|
|
248
253
|
"""Update the port output and the connected wires"""
|
|
249
254
|
self.update_wires(value)
|
|
250
255
|
if self._update_parent:
|
|
251
256
|
self.parent().update()
|
|
252
257
|
|
|
253
|
-
def delta_cycle(self, value):
|
|
258
|
+
def delta_cycle(self, value: int | str | None):
|
|
254
259
|
"""Handle the delta cycle event from the circuit"""
|
|
255
260
|
self.update_port(value)
|
|
256
261
|
|
|
257
|
-
def set_driver(self, port):
|
|
262
|
+
def set_driver(self, port: Port | None):
|
|
258
263
|
raise PortConnectionError(f"The port {self.path()}.{self.name()} cannot be driven")
|
|
259
264
|
|
|
260
|
-
def get_driver(self):
|
|
265
|
+
def get_driver(self) -> Port | None:
|
|
261
266
|
"""Get driver for port, the output port has no driver"""
|
|
262
267
|
return None
|
|
263
268
|
|
|
264
|
-
def has_driver(self):
|
|
269
|
+
def has_driver(self) -> bool:
|
|
265
270
|
"""Return False since the port does not have a driver"""
|
|
266
271
|
return False
|
|
267
272
|
|
|
@@ -274,14 +279,14 @@ class PortOutImmediate(PortOutDelta):
|
|
|
274
279
|
* The port will update the parent component if the _update_parent variable is set to true.
|
|
275
280
|
"""
|
|
276
281
|
|
|
277
|
-
def __init__(self, parent, name, width=1):
|
|
282
|
+
def __init__(self, parent, name: str, width: int = 1):
|
|
278
283
|
super().__init__(parent, name, width)
|
|
279
284
|
|
|
280
|
-
def set_value(self, value):
|
|
285
|
+
def set_value(self, value: int | str | None):
|
|
281
286
|
self.parent().add_event(self, value, 0)
|
|
282
287
|
super().update_port(value)
|
|
283
288
|
|
|
284
|
-
def delta_cycle(self, value):
|
|
289
|
+
def delta_cycle(self, value: int | str | None):
|
|
285
290
|
"""
|
|
286
291
|
Do nothing here, the event is just used to updates waves in Circuit class
|
|
287
292
|
"""
|
|
@@ -294,15 +299,15 @@ class PortWireBit(PortWire):
|
|
|
294
299
|
The PortWireBit will update its parent (a PortMultiBitWire) upon change.
|
|
295
300
|
"""
|
|
296
301
|
|
|
297
|
-
def __init__(self, parent, name, parent_port, output):
|
|
302
|
+
def __init__(self, parent, name: str, parent_port: PortMultiBitWire, output: bool):
|
|
298
303
|
super().__init__(parent, name, 1, output)
|
|
299
304
|
self._parent_port = parent_port
|
|
300
305
|
|
|
301
|
-
def set_value(self, value):
|
|
306
|
+
def set_value(self, value: int | str | None):
|
|
302
307
|
super().set_value(value)
|
|
303
308
|
self._parent_port.update_value_from_bits()
|
|
304
309
|
|
|
305
|
-
def get_parent_port(self):
|
|
310
|
+
def get_parent_port(self) -> PortMultiBitWire:
|
|
306
311
|
"""Get the parent PortMultiBitWire for this port"""
|
|
307
312
|
return self._parent_port
|
|
308
313
|
|
|
@@ -314,8 +319,8 @@ class PortMultiBitWire(Port):
|
|
|
314
319
|
The PortWireMultiBit will add events to the circuit upon change to update vcd output.
|
|
315
320
|
"""
|
|
316
321
|
|
|
317
|
-
def __init__(self, parent, name, width, output=False):
|
|
318
|
-
self._port_driver = None # The port that drives this port
|
|
322
|
+
def __init__(self, parent, name: str, width: int, output: bool = False):
|
|
323
|
+
self._port_driver: Port | None = None # The port that drives this port
|
|
319
324
|
self._bits = []
|
|
320
325
|
super().__init__(parent, name, width, output)
|
|
321
326
|
for bit_id in range(self.width):
|
|
@@ -328,32 +333,32 @@ class PortMultiBitWire(Port):
|
|
|
328
333
|
for bit in self._bits:
|
|
329
334
|
bit.init()
|
|
330
335
|
|
|
331
|
-
def set_value(self, value):
|
|
332
|
-
if value
|
|
336
|
+
def set_value(self, value: int | str | None):
|
|
337
|
+
if value is None or isinstance(value, str):
|
|
333
338
|
return
|
|
334
339
|
for bit_id, bit in enumerate(self._bits):
|
|
335
340
|
bit_val = (value >> bit_id) & 1
|
|
336
341
|
bit.value = bit_val
|
|
337
342
|
|
|
338
|
-
def get_wired_ports_recursive(self):
|
|
343
|
+
def get_wired_ports_recursive(self) -> list[Port]:
|
|
339
344
|
all_wired_ports = super().get_wired_ports_recursive()
|
|
340
345
|
for bit in self._bits:
|
|
341
346
|
all_wired_ports.extend(bit.get_wired_ports_recursive())
|
|
342
347
|
return all_wired_ports
|
|
343
348
|
|
|
344
|
-
def set_driver(self, port):
|
|
349
|
+
def set_driver(self, port: Port | None):
|
|
345
350
|
"""Set port driver"""
|
|
346
351
|
self._port_driver = port
|
|
347
352
|
|
|
348
|
-
def get_driver(self):
|
|
353
|
+
def get_driver(self) -> Port | None:
|
|
349
354
|
"""Get port driver"""
|
|
350
355
|
return self._port_driver
|
|
351
356
|
|
|
352
|
-
def has_driver(self):
|
|
357
|
+
def has_driver(self) -> bool:
|
|
353
358
|
"""Return True if port has driver"""
|
|
354
359
|
return self._port_driver is not None
|
|
355
360
|
|
|
356
|
-
def get_bit(self, bit_id):
|
|
361
|
+
def get_bit(self, bit_id: int) -> Port:
|
|
357
362
|
"""Get bit port"""
|
|
358
363
|
return self._bits[bit_id]
|
|
359
364
|
|
|
@@ -370,7 +375,7 @@ class PortMultiBitWire(Port):
|
|
|
370
375
|
# Send event just to update waves
|
|
371
376
|
self.parent().add_event(self, value, 0)
|
|
372
377
|
|
|
373
|
-
def delta_cycle(self, value):
|
|
378
|
+
def delta_cycle(self, value: int | str | None):
|
|
374
379
|
"""
|
|
375
380
|
Do nothing here, the event passed in 'update_value_from_bits'
|
|
376
381
|
is just used to updates waves in Circuit class
|