digsim-logic-simulator 0.8.0__py3-none-any.whl → 0.10.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/model/_model_shortcuts.py +1 -2
- digsim/circuit/components/_yosys_component.py +57 -46
- digsim/circuit/components/ic/74162.json +3 -2
- digsim/circuit/components/ic/7448.json +14 -13
- digsim/utils/__init__.py +1 -1
- digsim/utils/_yosys_netlist.py +97 -241
- {digsim_logic_simulator-0.8.0.dist-info → digsim_logic_simulator-0.10.0.dist-info}/METADATA +2 -2
- {digsim_logic_simulator-0.8.0.dist-info → digsim_logic_simulator-0.10.0.dist-info}/RECORD +11 -11
- {digsim_logic_simulator-0.8.0.dist-info → digsim_logic_simulator-0.10.0.dist-info}/WHEEL +0 -0
- {digsim_logic_simulator-0.8.0.dist-info → digsim_logic_simulator-0.10.0.dist-info}/licenses/LICENSE.md +0 -0
- {digsim_logic_simulator-0.8.0.dist-info → digsim_logic_simulator-0.10.0.dist-info}/top_level.txt +0 -0
|
@@ -77,10 +77,9 @@ class ModelShortcuts:
|
|
|
77
77
|
shortcuts_dict[key] = component.name()
|
|
78
78
|
return shortcuts_dict
|
|
79
79
|
|
|
80
|
-
def from_dict(self,
|
|
80
|
+
def from_dict(self, shortcuts_dict):
|
|
81
81
|
"""Generate shortcuts from dict"""
|
|
82
82
|
self.clear()
|
|
83
|
-
shortcuts_dict = model_dict.get("shortcuts")
|
|
84
83
|
if shortcuts_dict is not None:
|
|
85
84
|
for key, component_name in shortcuts_dict.items():
|
|
86
85
|
component = self._app_model.objects.circuit.get_component(component_name)
|
|
@@ -10,8 +10,9 @@ import json
|
|
|
10
10
|
|
|
11
11
|
import digsim.circuit.components._yosys_atoms
|
|
12
12
|
from digsim.synth import Synthesis
|
|
13
|
-
from digsim.utils import YosysNetlist
|
|
13
|
+
from digsim.utils import YosysCell, YosysModule, YosysNetlist
|
|
14
14
|
|
|
15
|
+
from ._static_level import GND, VDD
|
|
15
16
|
from .atoms import Component, DigsimException, MultiComponent, PortMultiBitWire
|
|
16
17
|
|
|
17
18
|
|
|
@@ -29,6 +30,7 @@ class YosysComponent(MultiComponent):
|
|
|
29
30
|
self._gates_comp = None
|
|
30
31
|
self._net_comp = None
|
|
31
32
|
self._netlist_module = None
|
|
33
|
+
self._netlist_nets = None
|
|
32
34
|
self._setup_base()
|
|
33
35
|
|
|
34
36
|
if nets:
|
|
@@ -47,13 +49,15 @@ class YosysComponent(MultiComponent):
|
|
|
47
49
|
modules = netlist_object.get_modules()
|
|
48
50
|
module_name = list(modules.keys())[0]
|
|
49
51
|
self._netlist_module = netlist_object.get_modules()[module_name]
|
|
52
|
+
self._netlist_nets = self._netlist_module.get_nets()
|
|
53
|
+
|
|
50
54
|
# Set Name
|
|
51
55
|
self.set_name(module_name)
|
|
52
56
|
self.set_display_name(module_name)
|
|
53
57
|
# Add External Ports
|
|
54
|
-
for portname, port_dict in self._netlist_module.
|
|
58
|
+
for portname, port_dict in self._netlist_module.ports.items():
|
|
55
59
|
external_port = PortMultiBitWire(
|
|
56
|
-
self, portname, width=len(port_dict
|
|
60
|
+
self, portname, width=len(port_dict.bits), output=port_dict.is_output
|
|
57
61
|
)
|
|
58
62
|
self.add_port(external_port)
|
|
59
63
|
# Create component
|
|
@@ -64,18 +68,10 @@ class YosysComponent(MultiComponent):
|
|
|
64
68
|
modules = netlist_object.get_modules()
|
|
65
69
|
module_name = list(modules.keys())[0]
|
|
66
70
|
reload_module = netlist_object.get_modules()[module_name]
|
|
71
|
+
reload_nets = reload_module.get_nets()
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
current_ext_if = self._netlist_module.get_external_interface()
|
|
70
|
-
new_ext_if = reload_module.get_external_interface()
|
|
71
|
-
|
|
72
|
-
if current_ext_if.keys() != new_ext_if.keys():
|
|
73
|
+
if not self._netlist_module.is_same_interface(reload_module):
|
|
73
74
|
raise YosysComponentException("Yosys component interface differs")
|
|
74
|
-
for key, _ in current_ext_if.items():
|
|
75
|
-
if len(current_ext_if[key]["nets"]) != len(new_ext_if[key]["nets"]):
|
|
76
|
-
raise YosysComponentException("Yosys component interface differs")
|
|
77
|
-
if current_ext_if[key]["output"] != new_ext_if[key]["output"]:
|
|
78
|
-
raise YosysComponentException("Yosys component interface differs")
|
|
79
75
|
|
|
80
76
|
# Disconnect ports
|
|
81
77
|
self._disconnect_external_ports()
|
|
@@ -86,63 +82,79 @@ class YosysComponent(MultiComponent):
|
|
|
86
82
|
self._net_comp.delete_all_ports()
|
|
87
83
|
# Setup netlist
|
|
88
84
|
self._netlist_module = reload_module
|
|
85
|
+
self._netlist_nets = reload_nets
|
|
89
86
|
# Create component
|
|
90
87
|
self._create_component()
|
|
91
88
|
|
|
92
89
|
def _create_cells(self):
|
|
93
90
|
"""Create cells in component"""
|
|
94
91
|
components_dict = {}
|
|
95
|
-
for cellname, cell in self._netlist_module.
|
|
92
|
+
for cellname, cell in self._netlist_module.cells.items():
|
|
93
|
+
if cell.type == "$scopeinfo":
|
|
94
|
+
continue
|
|
96
95
|
component_class = getattr(
|
|
97
|
-
digsim.circuit.components._yosys_atoms, cell.
|
|
96
|
+
digsim.circuit.components._yosys_atoms, cell.component_type()
|
|
98
97
|
)
|
|
99
|
-
component = component_class(self._circuit, name=cell.
|
|
98
|
+
component = component_class(self._circuit, name=cell.component_name(cellname))
|
|
100
99
|
self._gates_comp.add(component)
|
|
101
100
|
components_dict[cellname] = component
|
|
101
|
+
|
|
102
|
+
vdd = VDD(self._circuit)
|
|
103
|
+
self._gates_comp.add(vdd)
|
|
104
|
+
components_dict["VDD"] = vdd
|
|
105
|
+
gnd = GND(self._circuit)
|
|
106
|
+
self._gates_comp.add(gnd)
|
|
107
|
+
components_dict["GND"] = gnd
|
|
108
|
+
|
|
102
109
|
return components_dict
|
|
103
110
|
|
|
104
|
-
def
|
|
105
|
-
"""Connect
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
net = source_port.get_nets()[0]
|
|
109
|
-
for sink_port in source_port.get_sinks():
|
|
110
|
-
if sink_port.get_parent().get_type() == "module":
|
|
111
|
+
def _connect_sinks(self, components_dict, src_comp_port, sinks):
|
|
112
|
+
"""Connect a source port to multiple sinks"""
|
|
113
|
+
for sink_port in sinks:
|
|
114
|
+
if isinstance(sink_port.parent, YosysModule):
|
|
111
115
|
# Connect cell output to module top
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
dst_port = self.port(sink_port.name()).get_bit(dst_bit)
|
|
115
|
-
src_comp_port.wire = dst_port
|
|
116
|
+
dst_port = self.port(sink_port.name).get_bit(sink_port.bit_index)
|
|
117
|
+
src_comp_port.wire = dst_port
|
|
116
118
|
else:
|
|
117
119
|
# Connect cell output to cell input
|
|
118
|
-
dst_comp = components_dict[sink_port.
|
|
119
|
-
src_comp_port.wire = dst_comp.port(sink_port.name
|
|
120
|
+
dst_comp = components_dict[sink_port.parent_name]
|
|
121
|
+
src_comp_port.wire = dst_comp.port(sink_port.name)
|
|
120
122
|
|
|
121
123
|
def _connect_cells(self, components_dict):
|
|
122
124
|
"""Connect all cells"""
|
|
123
|
-
for
|
|
124
|
-
|
|
125
|
-
|
|
125
|
+
for net, source in self._netlist_nets.source.items():
|
|
126
|
+
if isinstance(source.parent, YosysModule):
|
|
127
|
+
# Only connect cells here
|
|
128
|
+
continue
|
|
129
|
+
if isinstance(source.parent, YosysCell):
|
|
130
|
+
src_comp = components_dict[source.parent_name]
|
|
131
|
+
self._connect_sinks(
|
|
132
|
+
components_dict, src_comp.port(source.name), self._netlist_nets.sinks[net]
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
gnd_sinks = self._netlist_nets.sinks.get("0", [])
|
|
136
|
+
self._connect_sinks(components_dict, components_dict["GND"].port("O"), gnd_sinks)
|
|
137
|
+
vdd_sinks = self._netlist_nets.sinks.get("1", [])
|
|
138
|
+
self._connect_sinks(components_dict, components_dict["VDD"].port("O"), vdd_sinks)
|
|
126
139
|
|
|
127
140
|
def _connect_external_input_port(self, components_dict, portname, port_dict):
|
|
128
|
-
"""
|
|
129
|
-
for bit_idx, net in enumerate(port_dict
|
|
130
|
-
for sink_port in self.
|
|
131
|
-
if sink_port.
|
|
141
|
+
"""Connect external input port"""
|
|
142
|
+
for bit_idx, net in enumerate(port_dict.bits):
|
|
143
|
+
for sink_port in self._netlist_nets.sinks[net]:
|
|
144
|
+
if isinstance(sink_port.parent, YosysModule):
|
|
132
145
|
# Connect module input to module output
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
dst_port = self.port(sink_port.name()).get_bit(dst_bit)
|
|
136
|
-
self.port(portname).get_bit(bit_idx).wire = dst_port
|
|
146
|
+
dst_port = self.port(sink_port.name).get_bit(sink_port.bit_index)
|
|
147
|
+
self.port(portname).get_bit(bit_idx).wire = dst_port
|
|
137
148
|
else:
|
|
138
149
|
# Connect module input to cell input
|
|
139
|
-
|
|
140
|
-
|
|
150
|
+
self._connect_sinks(
|
|
151
|
+
components_dict, self.port(portname).get_bit(bit_idx), [sink_port]
|
|
152
|
+
)
|
|
141
153
|
|
|
142
154
|
def _connect_external_input(self, components_dict):
|
|
143
155
|
"""Connect all external input ports"""
|
|
144
|
-
for portname, port_dict in self._netlist_module.
|
|
145
|
-
if
|
|
156
|
+
for portname, port_dict in self._netlist_module.ports.items():
|
|
157
|
+
if port_dict.direction == "output":
|
|
146
158
|
continue
|
|
147
159
|
self._connect_external_input_port(components_dict, portname, port_dict)
|
|
148
160
|
|
|
@@ -176,8 +188,7 @@ class YosysComponent(MultiComponent):
|
|
|
176
188
|
else:
|
|
177
189
|
raise YosysComponentException(f"Unknown file extension '{self._path}'")
|
|
178
190
|
|
|
179
|
-
yosys_netlist = YosysNetlist()
|
|
180
|
-
yosys_netlist.from_dict(netlist_dict)
|
|
191
|
+
yosys_netlist = YosysNetlist(**netlist_dict)
|
|
181
192
|
modules = yosys_netlist.get_modules()
|
|
182
193
|
|
|
183
194
|
if len(modules) > 1:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
{
|
|
3
|
-
"creator": "Yosys 0.
|
|
3
|
+
"creator": "Yosys 0.57 (git sha1 3aca86049, ccache clang++ 18.1.3 -O3 -flto -flto)",
|
|
4
4
|
"modules": {
|
|
5
5
|
"ttl_74162": {
|
|
6
6
|
"attributes": {
|
|
@@ -821,7 +821,7 @@
|
|
|
821
821
|
}
|
|
822
822
|
},
|
|
823
823
|
"netnames": {
|
|
824
|
-
"$abc$895$auto$opt_dff.cc:
|
|
824
|
+
"$abc$895$auto$opt_dff.cc:247:make_patterns_logic$32": {
|
|
825
825
|
"hide_name": 1,
|
|
826
826
|
"bits": [ 18 ],
|
|
827
827
|
"attributes": {
|
|
@@ -1111,3 +1111,4 @@
|
|
|
1111
1111
|
}
|
|
1112
1112
|
}
|
|
1113
1113
|
}
|
|
1114
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
{
|
|
3
|
-
"creator": "Yosys 0.
|
|
3
|
+
"creator": "Yosys 0.57 (git sha1 3aca86049, ccache clang++ 18.1.3 -O3 -flto -flto)",
|
|
4
4
|
"modules": {
|
|
5
5
|
"ic7448": {
|
|
6
6
|
"attributes": {
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
"Y": "output"
|
|
77
77
|
},
|
|
78
78
|
"connections": {
|
|
79
|
-
"A": [
|
|
80
|
-
"B": [
|
|
79
|
+
"A": [ 3 ],
|
|
80
|
+
"B": [ 2 ],
|
|
81
81
|
"Y": [ 15 ]
|
|
82
82
|
}
|
|
83
83
|
},
|
|
@@ -114,8 +114,8 @@
|
|
|
114
114
|
"Y": "output"
|
|
115
115
|
},
|
|
116
116
|
"connections": {
|
|
117
|
-
"A": [
|
|
118
|
-
"B": [
|
|
117
|
+
"A": [ 4 ],
|
|
118
|
+
"B": [ 3 ],
|
|
119
119
|
"Y": [ 17 ]
|
|
120
120
|
}
|
|
121
121
|
},
|
|
@@ -170,8 +170,8 @@
|
|
|
170
170
|
"Y": "output"
|
|
171
171
|
},
|
|
172
172
|
"connections": {
|
|
173
|
-
"A": [
|
|
174
|
-
"B": [
|
|
173
|
+
"A": [ 3 ],
|
|
174
|
+
"B": [ 2 ],
|
|
175
175
|
"Y": [ 19 ]
|
|
176
176
|
}
|
|
177
177
|
},
|
|
@@ -376,8 +376,8 @@
|
|
|
376
376
|
"Y": "output"
|
|
377
377
|
},
|
|
378
378
|
"connections": {
|
|
379
|
-
"A": [
|
|
380
|
-
"B": [
|
|
379
|
+
"A": [ 3 ],
|
|
380
|
+
"B": [ 2 ],
|
|
381
381
|
"Y": [ 28 ]
|
|
382
382
|
}
|
|
383
383
|
},
|
|
@@ -526,8 +526,8 @@
|
|
|
526
526
|
"Y": "output"
|
|
527
527
|
},
|
|
528
528
|
"connections": {
|
|
529
|
-
"A": [
|
|
530
|
-
"B": [
|
|
529
|
+
"A": [ 3 ],
|
|
530
|
+
"B": [ 2 ],
|
|
531
531
|
"Y": [ 34 ]
|
|
532
532
|
}
|
|
533
533
|
},
|
|
@@ -600,8 +600,8 @@
|
|
|
600
600
|
"Y": "output"
|
|
601
601
|
},
|
|
602
602
|
"connections": {
|
|
603
|
-
"A": [
|
|
604
|
-
"B": [
|
|
603
|
+
"A": [ 3 ],
|
|
604
|
+
"B": [ 2 ],
|
|
605
605
|
"Y": [ 37 ]
|
|
606
606
|
}
|
|
607
607
|
},
|
|
@@ -895,3 +895,4 @@
|
|
|
895
895
|
}
|
|
896
896
|
}
|
|
897
897
|
}
|
|
898
|
+
|
digsim/utils/__init__.py
CHANGED
digsim/utils/_yosys_netlist.py
CHANGED
|
@@ -5,268 +5,124 @@
|
|
|
5
5
|
Module with classes to parse a yosys netlist
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
from __future__ import annotations
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
"""A class describing a port within a netlist"""
|
|
10
|
+
from typing import Any, Optional, Union
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
self._name = name
|
|
15
|
-
self._is_source = is_source
|
|
16
|
-
self._sinks = []
|
|
17
|
-
if net is None:
|
|
18
|
-
self._nets = []
|
|
19
|
-
else:
|
|
20
|
-
self._nets = [net]
|
|
21
|
-
|
|
22
|
-
def name(self):
|
|
23
|
-
"""Return port name"""
|
|
24
|
-
return self._name
|
|
25
|
-
|
|
26
|
-
def get_parent(self):
|
|
27
|
-
"""Return port parent"""
|
|
28
|
-
return self._parent
|
|
29
|
-
|
|
30
|
-
def is_source(self):
|
|
31
|
-
"""Return true if port is a source (false for sink)"""
|
|
32
|
-
return self._is_source
|
|
33
|
-
|
|
34
|
-
def add_sinks(self, sinks):
|
|
35
|
-
"""Add sinks to source port"""
|
|
36
|
-
self._sinks.extend(sinks)
|
|
37
|
-
|
|
38
|
-
def get_sinks(self):
|
|
39
|
-
"""Get source port sinks"""
|
|
40
|
-
return self._sinks
|
|
41
|
-
|
|
42
|
-
def get_nets(self):
|
|
43
|
-
"""Get port nets"""
|
|
44
|
-
return self._nets
|
|
45
|
-
|
|
46
|
-
def from_module_dict(self, port_dict, global_nets):
|
|
47
|
-
"""Create xternal port from module dict"""
|
|
48
|
-
self._is_source = port_dict["direction"] == "input"
|
|
49
|
-
for net in port_dict["bits"]:
|
|
50
|
-
if net not in global_nets:
|
|
51
|
-
global_nets.append(net)
|
|
52
|
-
self._nets.append(net)
|
|
12
|
+
from pydantic import Field
|
|
13
|
+
from pydantic.dataclasses import dataclass
|
|
53
14
|
|
|
54
15
|
|
|
55
|
-
|
|
56
|
-
|
|
16
|
+
@dataclass
|
|
17
|
+
class NetPort:
|
|
18
|
+
parent: Union[YosysModule, YosysCell]
|
|
19
|
+
parent_name: str
|
|
20
|
+
name: str
|
|
21
|
+
bit_index: Optional[int] = None
|
|
57
22
|
|
|
58
|
-
def __init__(self, name, block_type=None):
|
|
59
|
-
self._name = name
|
|
60
|
-
self._ports = {}
|
|
61
|
-
self._nets = []
|
|
62
|
-
self._block_type = block_type
|
|
63
|
-
self._net_to_source_port = {}
|
|
64
|
-
self._net_to_sink_ports = {}
|
|
65
23
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
24
|
+
@dataclass
|
|
25
|
+
class Nets:
|
|
26
|
+
source: dict[int, NetPort] = Field(default_factory=dict)
|
|
27
|
+
sinks: dict[int, list[NetPort]] = Field(default_factory=dict)
|
|
69
28
|
|
|
70
|
-
def get_type(self):
|
|
71
|
-
"""Get type"""
|
|
72
|
-
return self._block_type
|
|
73
29
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
30
|
+
@dataclass
|
|
31
|
+
class YosysPort:
|
|
32
|
+
direction: str
|
|
33
|
+
bits: list[Union[int, str]]
|
|
77
34
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
self.
|
|
81
|
-
nets = port.get_nets()
|
|
82
|
-
if port.is_source():
|
|
83
|
-
for net in nets:
|
|
84
|
-
self._net_to_source_port[net] = port
|
|
85
|
-
else:
|
|
86
|
-
for net in nets:
|
|
87
|
-
if net not in self._net_to_sink_ports:
|
|
88
|
-
self._net_to_sink_ports[net] = []
|
|
89
|
-
if port not in self._net_to_sink_ports[net]:
|
|
90
|
-
self._net_to_sink_ports[net].append(port)
|
|
91
|
-
|
|
92
|
-
def get_nets(self):
|
|
93
|
-
"""Get nets of block (cell or module)"""
|
|
94
|
-
return self._nets
|
|
95
|
-
|
|
96
|
-
def get_source_ports(self):
|
|
97
|
-
"""Get source ports of block (cell or module)"""
|
|
98
|
-
ports = []
|
|
99
|
-
for _, port in self._net_to_source_port.items():
|
|
100
|
-
ports.append(port)
|
|
101
|
-
return ports
|
|
102
|
-
|
|
103
|
-
def get_source_port(self, net):
|
|
104
|
-
"""Get source port of block (cell or module)"""
|
|
105
|
-
return self._net_to_source_port.get(net)
|
|
35
|
+
@property
|
|
36
|
+
def is_output(self):
|
|
37
|
+
return self.direction == "output"
|
|
106
38
|
|
|
107
|
-
def
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
class _NetlistCell(_NetlistBlock):
|
|
113
|
-
"""A class holding a cell in a yosys netlist"""
|
|
39
|
+
def is_same(self, compare_port):
|
|
40
|
+
return (compare_port.direction == self.direction) and (
|
|
41
|
+
len(compare_port.bits) == len(self.bits)
|
|
42
|
+
)
|
|
114
43
|
|
|
115
|
-
def __init__(self, name):
|
|
116
|
-
super().__init__(name)
|
|
117
44
|
|
|
118
|
-
|
|
45
|
+
@dataclass
|
|
46
|
+
class YosysCell:
|
|
47
|
+
type: str
|
|
48
|
+
port_directions: dict[str, str] = Field(default_factory=dict)
|
|
49
|
+
connections: dict[str, list[Union[str, int]]] = Field(default_factory=dict)
|
|
50
|
+
hide_name: int = 0
|
|
51
|
+
parameters: dict[str, Any] = Field(default_factory=dict)
|
|
52
|
+
attributes: dict[str, Any] = Field(default_factory=dict)
|
|
53
|
+
|
|
54
|
+
def get_nets(self, name, nets):
|
|
55
|
+
for port_name, net_list in self.connections.items():
|
|
56
|
+
net = net_list[0]
|
|
57
|
+
port = NetPort(parent=self, parent_name=name, name=port_name)
|
|
58
|
+
if self.port_directions[port_name] == "input":
|
|
59
|
+
if net not in nets.sinks:
|
|
60
|
+
nets.sinks[net] = []
|
|
61
|
+
nets.sinks[net].append(port)
|
|
62
|
+
else:
|
|
63
|
+
nets.source[net] = port
|
|
64
|
+
|
|
65
|
+
def component_name(self, name):
|
|
119
66
|
"""Return a friendly name for a netlist cell"""
|
|
120
|
-
return f"{
|
|
67
|
+
return f"{name.split('$')[-1]}_{self.component_type()}"
|
|
121
68
|
|
|
122
|
-
def
|
|
69
|
+
def component_type(self):
|
|
123
70
|
"""Return a friendly type for a netlist cell"""
|
|
124
|
-
return f"_{self.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
},
|
|
156
|
-
self._nets,
|
|
157
|
-
)
|
|
158
|
-
self._cells["StaticLevel"] = static_cell
|
|
159
|
-
|
|
160
|
-
def from_dict(self, module_dict):
|
|
161
|
-
"""Create module from dict"""
|
|
162
|
-
for ext_port_name, port_dict in module_dict["ports"].items():
|
|
163
|
-
ext_port = _NetlistPort(self, ext_port_name)
|
|
164
|
-
ext_port.from_module_dict(port_dict, self._nets)
|
|
165
|
-
nets = ext_port.get_nets()
|
|
166
|
-
ext_port_dict = {"output": ext_port.is_source(), "nets": nets}
|
|
167
|
-
self._ext_if[ext_port_name] = ext_port_dict
|
|
168
|
-
self.add_port(ext_port_name, ext_port)
|
|
169
|
-
|
|
170
|
-
for cell_name, cell_dict in module_dict["cells"].items():
|
|
171
|
-
cell = _NetlistCell(cell_name)
|
|
172
|
-
cell.from_dict(cell_dict, self._nets)
|
|
173
|
-
if cell.get_type() == "$scopeinfo":
|
|
174
|
-
continue
|
|
175
|
-
self._cells[cell_name] = cell
|
|
176
|
-
|
|
177
|
-
def get_cells(self):
|
|
178
|
-
"""Get cells dict"""
|
|
179
|
-
return self._cells
|
|
180
|
-
|
|
181
|
-
def get_external_interface(self):
|
|
182
|
-
"""Get external interface dict"""
|
|
183
|
-
return self._ext_if
|
|
184
|
-
|
|
185
|
-
def get_source(self, net):
|
|
186
|
-
"""Get source port for net"""
|
|
187
|
-
module_port = self.get_source_port(net)
|
|
188
|
-
if module_port is not None:
|
|
189
|
-
return module_port
|
|
190
|
-
for _, cell in self._cells.items():
|
|
191
|
-
cell_port = cell.get_source_port(net)
|
|
192
|
-
if cell_port is not None:
|
|
193
|
-
return cell_port
|
|
194
|
-
return None
|
|
195
|
-
|
|
196
|
-
def get_sinks(self, net):
|
|
197
|
-
"""Get module sinks (input ports)"""
|
|
198
|
-
sink_ports = self.get_sink_ports(net)
|
|
199
|
-
for _, cell in self._cells.items():
|
|
200
|
-
cell_sink_ports = cell.get_sink_ports(net)
|
|
201
|
-
for port in cell_sink_ports:
|
|
202
|
-
if port not in sink_ports:
|
|
203
|
-
sink_ports.append(port)
|
|
204
|
-
return sink_ports
|
|
205
|
-
|
|
206
|
-
def connect(self):
|
|
207
|
-
"""Connect all nets within module"""
|
|
208
|
-
_source_port_dict = {}
|
|
209
|
-
_sink_ports_dict = {}
|
|
210
|
-
_cells_dict = {}
|
|
211
|
-
|
|
212
|
-
# Build net to cell dict
|
|
213
|
-
for _, cell in self._cells.items():
|
|
214
|
-
for cell_net in cell.get_nets():
|
|
215
|
-
if cell_net not in _cells_dict:
|
|
216
|
-
_cells_dict[cell_net] = []
|
|
217
|
-
_cells_dict[cell_net].append(cell)
|
|
71
|
+
return f"_{self.type[2:-1]}_"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@dataclass
|
|
75
|
+
class YosysNetName:
|
|
76
|
+
bits: list[int]
|
|
77
|
+
attributes: dict[str, Any] = Field(default_factory=dict)
|
|
78
|
+
hide_name: int = 0
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@dataclass
|
|
82
|
+
class YosysModule:
|
|
83
|
+
attributes: dict[str, Any] = Field(default_factory=dict)
|
|
84
|
+
parameter_default_values: dict[str, Any] = Field(default_factory=dict)
|
|
85
|
+
ports: dict[str, YosysPort] = Field(default_factory=dict)
|
|
86
|
+
cells: dict[str, YosysCell] = Field(default_factory=dict)
|
|
87
|
+
netnames: dict[str, YosysNetName] = Field(default_factory=dict)
|
|
88
|
+
|
|
89
|
+
def is_same_interface(self, netlist):
|
|
90
|
+
is_same = True
|
|
91
|
+
if len(netlist.ports) == len(self.ports):
|
|
92
|
+
for netlist_port_name, netlist_port in netlist.ports.items():
|
|
93
|
+
module_port = self.ports.get(netlist_port_name)
|
|
94
|
+
if module_port is None or not module_port.is_same(netlist_port):
|
|
95
|
+
# Port does not exist or has a different bitwidth
|
|
96
|
+
is_same = False
|
|
97
|
+
break
|
|
98
|
+
else:
|
|
99
|
+
# The number of ports does not match
|
|
100
|
+
is_same = False
|
|
101
|
+
return is_same
|
|
218
102
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
# Module
|
|
222
|
-
port = self.get_source_port(net)
|
|
223
|
-
if port is not None:
|
|
224
|
-
_source_port_dict[net] = port
|
|
225
|
-
sink_ports = self.get_sink_ports(net)
|
|
226
|
-
# Cells
|
|
227
|
-
for cell in _cells_dict.get(net, []):
|
|
228
|
-
port = cell.get_source_port(net)
|
|
229
|
-
if port is not None:
|
|
230
|
-
_source_port_dict[net] = port
|
|
231
|
-
cell_sink_ports = cell.get_sink_ports(net)
|
|
232
|
-
sink_ports.extend(cell_sink_ports)
|
|
233
|
-
_sink_ports_dict[net] = sink_ports
|
|
103
|
+
def get_nets(self):
|
|
104
|
+
nets = Nets()
|
|
234
105
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
106
|
+
for port_name, port_item in self.ports.items():
|
|
107
|
+
for bit_index, net in enumerate(port_item.bits):
|
|
108
|
+
port = NetPort(parent=self, parent_name="top", name=port_name, bit_index=bit_index)
|
|
109
|
+
if port_item.is_output:
|
|
110
|
+
if net not in nets.sinks:
|
|
111
|
+
nets.sinks[net] = []
|
|
112
|
+
nets.sinks[net].append(port)
|
|
113
|
+
else:
|
|
114
|
+
nets.source[net] = port
|
|
240
115
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
nets = module_net.get_nets()
|
|
244
|
-
ports = []
|
|
245
|
-
for net in nets:
|
|
246
|
-
port = _source_port_dict[net]
|
|
247
|
-
ports.append(port)
|
|
248
|
-
module_net.set_ports(ports)
|
|
116
|
+
for cell_name, cell in self.cells.items():
|
|
117
|
+
cell.get_nets(cell_name, nets)
|
|
249
118
|
|
|
250
|
-
|
|
251
|
-
"""Get the nets for this module"""
|
|
252
|
-
return self._module_nets
|
|
119
|
+
return nets
|
|
253
120
|
|
|
254
121
|
|
|
122
|
+
@dataclass
|
|
255
123
|
class YosysNetlist:
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
def __init__(self):
|
|
259
|
-
self._modules = {}
|
|
124
|
+
creator: Optional[str] = None
|
|
125
|
+
modules: dict[str, YosysModule] = Field(default_factory=dict)
|
|
260
126
|
|
|
261
127
|
def get_modules(self):
|
|
262
|
-
|
|
263
|
-
return self._modules
|
|
264
|
-
|
|
265
|
-
def from_dict(self, netlist_dict):
|
|
266
|
-
"""Parse netlist from dict"""
|
|
267
|
-
for module_name, module_dict in netlist_dict["modules"].items():
|
|
268
|
-
module = _NestlistModule(module_name)
|
|
269
|
-
module.from_dict(module_dict)
|
|
270
|
-
self._modules[module_name] = module
|
|
271
|
-
for _, module in self._modules.items():
|
|
272
|
-
module.connect()
|
|
128
|
+
return self.modules
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: digsim-logic-simulator
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: Interactive Digital Logic Simulator
|
|
5
5
|
Author-email: Fredrik Andersson <freand@gmail.com>
|
|
6
6
|
Maintainer-email: Fredrik Andersson <freand@gmail.com>
|
|
@@ -22,7 +22,7 @@ Requires-Dist: pyside6==6.9.1
|
|
|
22
22
|
Requires-Dist: pexpect==4.9.0
|
|
23
23
|
Requires-Dist: pydantic==2.11.7
|
|
24
24
|
Requires-Dist: qtawesome==1.4.0
|
|
25
|
-
Requires-Dist: yowasp-yosys==0.
|
|
25
|
+
Requires-Dist: yowasp-yosys==0.57.0.0.post986
|
|
26
26
|
Dynamic: license-file
|
|
27
27
|
|
|
28
28
|
# DigSim - Interactive Digital Logic Simulator
|
|
@@ -54,7 +54,7 @@ digsim/app/model/_model_components.py,sha256=Q2iztl7MlWv_7vaa7me-dp-gOx6-7Tg3LZm
|
|
|
54
54
|
digsim/app/model/_model_new_wire.py,sha256=5HnF5-gtKtB1Tp6ZIF7QuNo5zEHmsUpnBEmj6ZllLiA,1810
|
|
55
55
|
digsim/app/model/_model_objects.py,sha256=lqOjNIygIHT6Dq_PPa-D0B5elC49dB0KshF0ATzJZ0s,5217
|
|
56
56
|
digsim/app/model/_model_settings.py,sha256=FewI3hm1iwbjPwdN3IeixuINPtamDORrTh1ANGRNwX8,1035
|
|
57
|
-
digsim/app/model/_model_shortcuts.py,sha256=
|
|
57
|
+
digsim/app/model/_model_shortcuts.py,sha256=xrUgs2Y18mSVun3sxzVscYTZ6n5DJTTZOnFhs4Jt_0M,2439
|
|
58
58
|
digsim/app/settings/__init__.py,sha256=0tkoBSYeJFFiUI8c_FqvqqyM4-_SU9Xq7mXCwiew5Oo,308
|
|
59
59
|
digsim/app/settings/_component_settings.py,sha256=88D9OuEcFIlaqZozomWHSYrl7opz4jZW2e8xGuUyTpg,16287
|
|
60
60
|
digsim/app/settings/_gui_settings.py,sha256=sDi2POUsHvS7_4SO5qsTu_nN48HsTN4UfGPzdmECs9w,2764
|
|
@@ -83,23 +83,23 @@ digsim/circuit/components/_seven_segment.py,sha256=UxxjGLuIirVB2Px09XlL8_zjgE7F8
|
|
|
83
83
|
digsim/circuit/components/_static_level.py,sha256=2Assm1cmAfryVZ3KTQ1uGY8Q6eRrBipdwLITewXfIHg,677
|
|
84
84
|
digsim/circuit/components/_static_value.py,sha256=vfRPS_F9mKOXpHJxzs0JQKXqcj0o6d-090zbyZaECA4,1236
|
|
85
85
|
digsim/circuit/components/_yosys_atoms.py,sha256=NeH8XjjpoACHBfQRqR5RJxWorZhSjGk0t73cJOviSZw,37599
|
|
86
|
-
digsim/circuit/components/_yosys_component.py,sha256=
|
|
86
|
+
digsim/circuit/components/_yosys_component.py,sha256=LkYneNSvzQMn61RzlHk3aSkl9tF6JjibknfwmLeWCFk,8792
|
|
87
87
|
digsim/circuit/components/atoms/__init__.py,sha256=NU45pfJcSrdwZA-SVQeORlaznl_0BciY4VN3vVSnD8o,498
|
|
88
88
|
digsim/circuit/components/atoms/_component.py,sha256=DpMS1yOWWgk11Y9ae0PfuOJdlJsrzgrzuYrgsN62dbQ,8815
|
|
89
89
|
digsim/circuit/components/atoms/_digsim_exception.py,sha256=Y5mBve15zZbduqNNAyf7WzqDk4NtvUL_g2vYy5kBQ3U,173
|
|
90
90
|
digsim/circuit/components/atoms/_port.py,sha256=yT1TqmKPVlw8G_0r_6dErcqIkXCqB8z0pE5oL6Bnxzo,12596
|
|
91
|
-
digsim/circuit/components/ic/74162.json,sha256=
|
|
92
|
-
digsim/circuit/components/ic/7448.json,sha256=
|
|
91
|
+
digsim/circuit/components/ic/74162.json,sha256=RAeSva6TVuwfKHsvU9HC-ZVfRVrCkIsQUz_jcANT_fE,26693
|
|
92
|
+
digsim/circuit/components/ic/7448.json,sha256=hKMXhPqW-JBTF6rdz9u5HC_hY9cBRpJtMkLP7uOQXIo,21185
|
|
93
93
|
digsim/storage_model/__init__.py,sha256=lubmO9_BCUtEahyW1yE7f3aGHngEevGIwf_0LeOB7Y8,289
|
|
94
94
|
digsim/storage_model/_app.py,sha256=Aer9s_mUBKSydsyeWYvVPHX2XF5ZGPuXq8z4PoXu8lA,1353
|
|
95
95
|
digsim/storage_model/_circuit.py,sha256=NnaHLwqb9gAhqAxeZ1RkHHvoS_YJwixlz0xs-zmIrQU,3596
|
|
96
96
|
digsim/synth/__init__.py,sha256=jhBHLOHf-vNa94Zg5q5dGcf0fgQTModfjUKtmUSffiw,180
|
|
97
97
|
digsim/synth/__main__.py,sha256=wZWAzWsisoxA7hfqkKtu3H066uWyFajgPro2MEGlKbs,2173
|
|
98
98
|
digsim/synth/_synthesis.py,sha256=ug9vSeTyZrvRCboNLL7dDIFVpGqH_ibr5fhOZJHpqUs,4271
|
|
99
|
-
digsim/utils/__init__.py,sha256=
|
|
100
|
-
digsim/utils/_yosys_netlist.py,sha256=
|
|
101
|
-
digsim_logic_simulator-0.
|
|
102
|
-
digsim_logic_simulator-0.
|
|
103
|
-
digsim_logic_simulator-0.
|
|
104
|
-
digsim_logic_simulator-0.
|
|
105
|
-
digsim_logic_simulator-0.
|
|
99
|
+
digsim/utils/__init__.py,sha256=MT9TNcpa7fNAqtBsmCcceKMrUSU_v9xeJ6Nox_TL7Lo,191
|
|
100
|
+
digsim/utils/_yosys_netlist.py,sha256=Lcuo9seKcDu4O-NdBpJUpExvTT7Rx1STCBtF0xT8Nkc,3843
|
|
101
|
+
digsim_logic_simulator-0.10.0.dist-info/licenses/LICENSE.md,sha256=FrvohZfyfpH4xrvKdXiQ5hD7dUB7w4DcsRA3p-pOmLw,1693
|
|
102
|
+
digsim_logic_simulator-0.10.0.dist-info/METADATA,sha256=Sjx2LJyb7CSKNkJVmT17qGyOmKOCtaFmeyKBdi6ip9U,4558
|
|
103
|
+
digsim_logic_simulator-0.10.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
104
|
+
digsim_logic_simulator-0.10.0.dist-info/top_level.txt,sha256=qpCMzQKADZHVqZIoQgFrv3qJ3u7PPU73gTCXQglqLa8,7
|
|
105
|
+
digsim_logic_simulator-0.10.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{digsim_logic_simulator-0.8.0.dist-info → digsim_logic_simulator-0.10.0.dist-info}/top_level.txt
RENAMED
|
File without changes
|