najaeda 0.1.5__cp39-cp39-macosx_11_0_arm64.whl → 0.1.7__cp39-cp39-macosx_11_0_arm64.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 najaeda might be problematic. Click here for more details.
- najaeda/docs/.readthedocs.yaml +37 -0
- najaeda/docs/Makefile +20 -0
- najaeda/docs/conf.py +26 -0
- najaeda/docs/make.bat +35 -0
- najaeda/docs/source/api.rst +7 -0
- najaeda/docs/source/conf.py +40 -0
- najaeda/docs/source/index.rst +13 -0
- najaeda/instance_visitor.py +12 -6
- najaeda/libnaja_snl.dylib +0 -0
- najaeda/libnaja_snl_python.dylib +0 -0
- najaeda/netlist.py +346 -144
- najaeda-0.1.7.dist-info/METADATA +192 -0
- najaeda-0.1.7.dist-info/RECORD +20 -0
- najaeda-0.1.5.dist-info/METADATA +0 -102
- najaeda-0.1.5.dist-info/RECORD +0 -13
- {najaeda-0.1.5.dist-info → najaeda-0.1.7.dist-info}/WHEEL +0 -0
- {najaeda-0.1.5.dist-info → najaeda-0.1.7.dist-info}/licenses/AUTHORS +0 -0
- {najaeda-0.1.5.dist-info → najaeda-0.1.7.dist-info}/licenses/LICENSE +0 -0
najaeda/netlist.py
CHANGED
|
@@ -6,8 +6,62 @@
|
|
|
6
6
|
import itertools
|
|
7
7
|
import time
|
|
8
8
|
import logging
|
|
9
|
-
|
|
9
|
+
import hashlib
|
|
10
|
+
# import json
|
|
10
11
|
from najaeda import snl
|
|
12
|
+
import struct
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def consistent_hash(obj):
|
|
16
|
+
def default_serializer(o):
|
|
17
|
+
if isinstance(o, (str, int, float, bool, type(None))):
|
|
18
|
+
return o
|
|
19
|
+
elif isinstance(o, (list, tuple)):
|
|
20
|
+
return [default_serializer(i) for i in o]
|
|
21
|
+
else:
|
|
22
|
+
return str(o)
|
|
23
|
+
|
|
24
|
+
def hash_value(value):
|
|
25
|
+
if isinstance(value, int):
|
|
26
|
+
return struct.pack('!q', value)
|
|
27
|
+
else:
|
|
28
|
+
raise TypeError(f"Unsupported type: {type(value)}")
|
|
29
|
+
|
|
30
|
+
def hash_object(o):
|
|
31
|
+
if isinstance(o, (list, tuple)):
|
|
32
|
+
return b''.join(hash_object(i) for i in o)
|
|
33
|
+
else:
|
|
34
|
+
return hash_value(o)
|
|
35
|
+
|
|
36
|
+
serialized_obj = default_serializer(obj)
|
|
37
|
+
obj_bytes = hash_object(serialized_obj)
|
|
38
|
+
return int(hashlib.sha256(obj_bytes).hexdigest(), 16)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def get_snl_instance_from_id_list(id_list: list) -> snl.SNLInstance:
|
|
42
|
+
top = snl.SNLUniverse.get().getTopDesign()
|
|
43
|
+
design = top
|
|
44
|
+
instance = None
|
|
45
|
+
for id in id_list:
|
|
46
|
+
instance = design.getInstanceByID(id)
|
|
47
|
+
assert instance is not None
|
|
48
|
+
design = instance.getModel()
|
|
49
|
+
return instance
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_snl_path_from_id_list(id_list: list) -> snl.SNLPath:
|
|
53
|
+
top = snl.SNLUniverse.get().getTopDesign()
|
|
54
|
+
design = top
|
|
55
|
+
path = snl.SNLPath()
|
|
56
|
+
for id in id_list:
|
|
57
|
+
instance = design.getInstanceByID(id)
|
|
58
|
+
assert instance is not None
|
|
59
|
+
path = snl.SNLPath(path, instance)
|
|
60
|
+
assert path.getTailInstance() is not None
|
|
61
|
+
design = instance.getModel()
|
|
62
|
+
if len(id_list) > 0:
|
|
63
|
+
assert path.getTailInstance() is not None
|
|
64
|
+
return path
|
|
11
65
|
|
|
12
66
|
|
|
13
67
|
class Equipotential:
|
|
@@ -16,10 +70,25 @@ class Equipotential:
|
|
|
16
70
|
"""
|
|
17
71
|
|
|
18
72
|
def __init__(self, term):
|
|
19
|
-
|
|
73
|
+
snl_term = get_snl_term_for_ids(term.pathIDs, term.termIDs)
|
|
74
|
+
if isinstance(snl_term, snl.SNLBusTerm):
|
|
20
75
|
raise ValueError("Equipotential cannot be constructed on bus term")
|
|
76
|
+
if len(term.pathIDs) == 0:
|
|
77
|
+
net = term.get_lower_net()
|
|
78
|
+
if net is None:
|
|
79
|
+
self.equi = None
|
|
80
|
+
return
|
|
81
|
+
inst_term = next(net.get_inst_terms(), None)
|
|
82
|
+
if inst_term is None:
|
|
83
|
+
self.equi = None
|
|
84
|
+
return
|
|
85
|
+
else:
|
|
86
|
+
inst_term = term
|
|
87
|
+
path = get_snl_path_from_id_list(inst_term.pathIDs)
|
|
88
|
+
snl_term = get_snl_term_for_ids(inst_term.pathIDs, inst_term.termIDs)
|
|
21
89
|
ito = snl.SNLNetComponentOccurrence(
|
|
22
|
-
|
|
90
|
+
path.getHeadPath(),
|
|
91
|
+
path.getTailInstance().getInstTerm(snl_term)
|
|
23
92
|
)
|
|
24
93
|
self.equi = snl.SNLEquipotential(ito)
|
|
25
94
|
|
|
@@ -27,25 +96,53 @@ class Equipotential:
|
|
|
27
96
|
return self.equi == value.equi
|
|
28
97
|
|
|
29
98
|
def get_inst_terms(self):
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
99
|
+
if self.equi is not None:
|
|
100
|
+
for term in self.equi.getInstTermOccurrences():
|
|
101
|
+
yield Term(
|
|
102
|
+
snl.SNLPath(term.getPath(), term.getInstTerm().getInstance()),
|
|
103
|
+
term.getInstTerm().getBitTerm(),
|
|
104
|
+
)
|
|
35
105
|
|
|
36
106
|
def get_top_terms(self):
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
107
|
+
if self.equi is not None:
|
|
108
|
+
for term in self.equi.getTerms():
|
|
109
|
+
yield Term(snl.SNLPath(), term)
|
|
110
|
+
|
|
111
|
+
def get_leaf_readers(self):
|
|
112
|
+
if self.equi is not None:
|
|
113
|
+
for term in self.equi.getInstTermOccurrences():
|
|
114
|
+
direction = term.getInstTerm().getDirection()
|
|
115
|
+
if direction != snl.SNLTerm.Direction.Output:
|
|
116
|
+
if term.getInstTerm().getInstance().getModel().isLeaf():
|
|
117
|
+
yield Term(
|
|
118
|
+
snl.SNLPath(term.getPath(), term.getInstTerm().getInstance()),
|
|
119
|
+
term.getInstTerm().getBitTerm(),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
def get_leaf_drivers(self):
|
|
123
|
+
if self.equi is not None:
|
|
124
|
+
for term in self.equi.getInstTermOccurrences():
|
|
125
|
+
direction = term.getInstTerm().getDirection()
|
|
126
|
+
if direction != snl.SNLTerm.Direction.Input:
|
|
127
|
+
if term.getInstTerm().getInstance().getModel().isLeaf():
|
|
128
|
+
yield Term(
|
|
129
|
+
snl.SNLPath(term.getPath(), term.getInstTerm().getInstance()),
|
|
130
|
+
term.getInstTerm().getBitTerm(),
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
def get_top_readers(self):
|
|
134
|
+
if self.equi is not None:
|
|
135
|
+
for term in self.equi.getTerms():
|
|
136
|
+
direction = term.getDirection()
|
|
137
|
+
if direction != snl.SNLTerm.Direction.Input:
|
|
138
|
+
yield Term(snl.SNLPath(), term)
|
|
139
|
+
|
|
140
|
+
def get_top_drivers(self):
|
|
141
|
+
if self.equi is not None:
|
|
142
|
+
for term in self.equi.getTerms():
|
|
143
|
+
direction = term.getDirection()
|
|
144
|
+
if direction != snl.SNLTerm.Direction.Output:
|
|
145
|
+
yield Term(snl.SNLPath(), term)
|
|
49
146
|
|
|
50
147
|
|
|
51
148
|
class Net:
|
|
@@ -54,7 +151,10 @@ class Net:
|
|
|
54
151
|
raise ValueError(
|
|
55
152
|
"Only one of `net` or `net_concat` should be provided, not both."
|
|
56
153
|
)
|
|
57
|
-
|
|
154
|
+
if path.size() > 0:
|
|
155
|
+
self.pathIDs = path.getPathIDs()
|
|
156
|
+
else:
|
|
157
|
+
self.pathIDs = []
|
|
58
158
|
if net is not None:
|
|
59
159
|
self.net = net
|
|
60
160
|
elif net_concat is not None:
|
|
@@ -76,8 +176,9 @@ class Net:
|
|
|
76
176
|
net_str = str(self.net)
|
|
77
177
|
elif hasattr(self, "net_concat"):
|
|
78
178
|
net_str = "{" + ",".join(map(str, self.net_concat)) + "}"
|
|
79
|
-
|
|
80
|
-
|
|
179
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
180
|
+
if path.size() > 0:
|
|
181
|
+
return f"{path}/{net_str}"
|
|
81
182
|
return net_str
|
|
82
183
|
|
|
83
184
|
def get_name(self) -> str:
|
|
@@ -134,10 +235,11 @@ class Net:
|
|
|
134
235
|
return sum(1 for _ in self.net_concat)
|
|
135
236
|
|
|
136
237
|
def get_bits(self):
|
|
238
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
137
239
|
if hasattr(self, "net"):
|
|
138
240
|
if isinstance(self.net, snl.SNLBusNet):
|
|
139
241
|
for bit in self.net.getBits():
|
|
140
|
-
yield Net(
|
|
242
|
+
yield Net(path, bit)
|
|
141
243
|
else:
|
|
142
244
|
yield self
|
|
143
245
|
else:
|
|
@@ -145,52 +247,80 @@ class Net:
|
|
|
145
247
|
yield net
|
|
146
248
|
|
|
147
249
|
def get_bit(self, index: int):
|
|
250
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
148
251
|
if hasattr(self, "net"):
|
|
149
252
|
if isinstance(self.net, snl.SNLBusNet):
|
|
150
|
-
return Net(
|
|
253
|
+
return Net(path, self.net.getBit(index))
|
|
151
254
|
else:
|
|
152
255
|
return None
|
|
153
256
|
if 0 <= index < len(self.net_concat):
|
|
154
|
-
return Net(
|
|
257
|
+
return Net(path, self.net_concat[index])
|
|
155
258
|
return None
|
|
156
259
|
|
|
157
260
|
def get_inst_terms(self):
|
|
261
|
+
init_path = get_snl_path_from_id_list(self.pathIDs)
|
|
158
262
|
if hasattr(self, "net_concat"):
|
|
159
263
|
raise ValueError("Cannot get inst terms from a net_concat")
|
|
160
264
|
for term in self.net.getInstTerms():
|
|
161
|
-
path = snl.SNLPath(
|
|
265
|
+
path = snl.SNLPath(init_path, term.getInstance())
|
|
162
266
|
yield Term(path, term.getBitTerm())
|
|
163
267
|
|
|
164
268
|
def get_design_terms(self):
|
|
269
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
165
270
|
if hasattr(self, "net_concat"):
|
|
166
271
|
raise ValueError("Cannot get terms from a net_concat")
|
|
167
272
|
for term in self.net.getBitTerms():
|
|
168
|
-
yield Term(
|
|
273
|
+
yield Term(path, term)
|
|
169
274
|
|
|
170
275
|
def get_terms(self):
|
|
171
276
|
for term in itertools.chain(self.get_design_terms(), self.get_inst_terms()):
|
|
172
277
|
yield term
|
|
173
278
|
|
|
174
279
|
|
|
280
|
+
def get_snl_term_for_ids(pathIDs, termIDs):
|
|
281
|
+
path = get_snl_path_from_id_list(pathIDs)
|
|
282
|
+
model = None
|
|
283
|
+
if len(pathIDs) == 0:
|
|
284
|
+
model = snl.SNLUniverse.get().getTopDesign()
|
|
285
|
+
else:
|
|
286
|
+
model = path.getTailInstance().getModel()
|
|
287
|
+
if termIDs[1] == -1:
|
|
288
|
+
return model.getTermByID(termIDs[0])
|
|
289
|
+
else:
|
|
290
|
+
snlterm = model.getTermByID(termIDs[0])
|
|
291
|
+
if isinstance(snlterm, snl.SNLBusTerm):
|
|
292
|
+
return snlterm.getBit(termIDs[1])
|
|
293
|
+
else:
|
|
294
|
+
return snlterm
|
|
295
|
+
|
|
296
|
+
|
|
175
297
|
class Term:
|
|
176
298
|
INPUT = snl.SNLTerm.Direction.Input
|
|
177
299
|
OUTPUT = snl.SNLTerm.Direction.Output
|
|
178
300
|
INOUT = snl.SNLTerm.Direction.InOut
|
|
179
301
|
|
|
180
302
|
def __init__(self, path, term):
|
|
181
|
-
self.
|
|
182
|
-
|
|
303
|
+
self.termIDs = []
|
|
304
|
+
if isinstance(term, snl.SNLBusTerm):
|
|
305
|
+
self.termIDs = [term.getID(), -1]
|
|
306
|
+
else:
|
|
307
|
+
self.termIDs = [term.getID(), term.getBit()]
|
|
308
|
+
|
|
309
|
+
if path.size() > 0:
|
|
310
|
+
self.pathIDs = path.getPathIDs()
|
|
311
|
+
else:
|
|
312
|
+
self.pathIDs = []
|
|
183
313
|
|
|
184
314
|
def __eq__(self, other) -> bool:
|
|
185
|
-
return self.
|
|
315
|
+
return self.pathIDs == other.pathIDs and self.termIDs == other.termIDs
|
|
186
316
|
|
|
187
317
|
def __ne__(self, other) -> bool:
|
|
188
318
|
return not self == other
|
|
189
319
|
|
|
190
320
|
def __lt__(self, other) -> bool:
|
|
191
|
-
if self.
|
|
192
|
-
return self.
|
|
193
|
-
return self.
|
|
321
|
+
if self.pathIDs != other.pathIDs:
|
|
322
|
+
return self.pathIDs < other.pathIDs
|
|
323
|
+
return self.termIDs < other.termIDs
|
|
194
324
|
|
|
195
325
|
def __le__(self, other) -> bool:
|
|
196
326
|
return self < other or self == other
|
|
@@ -201,40 +331,43 @@ class Term:
|
|
|
201
331
|
def __ge__(self, other) -> bool:
|
|
202
332
|
return not self < other
|
|
203
333
|
|
|
334
|
+
def __hash__(self):
|
|
335
|
+
termIDs = []
|
|
336
|
+
snlterm = get_snl_term_for_ids(self.pathIDs, self.termIDs)
|
|
337
|
+
if isinstance(snlterm, snl.SNLBusTerm):
|
|
338
|
+
termIDs = [snlterm.getID(), -1]
|
|
339
|
+
else:
|
|
340
|
+
termIDs = [snlterm.getID(), snlterm.getBit()]
|
|
341
|
+
return consistent_hash((self.pathIDs, termIDs))
|
|
342
|
+
|
|
204
343
|
def __str__(self):
|
|
205
|
-
|
|
206
|
-
|
|
344
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
345
|
+
if path.size() == 0:
|
|
346
|
+
return get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()
|
|
207
347
|
else:
|
|
208
|
-
return f"{
|
|
348
|
+
return f"{path}/{get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()}"
|
|
209
349
|
|
|
210
350
|
def __repr__(self) -> str:
|
|
211
|
-
|
|
351
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
352
|
+
return f"Term({path}, {get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()})"
|
|
212
353
|
|
|
213
354
|
def __make_unique(self):
|
|
214
|
-
|
|
215
|
-
|
|
355
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
356
|
+
if path.size() > 1:
|
|
357
|
+
path = path.getHeadPath()
|
|
216
358
|
snl.SNLUniquifier(path)
|
|
217
|
-
if self.is_bus_bit():
|
|
218
|
-
term = (
|
|
219
|
-
self.path.getTailInstance().getModel().getTerm(self.term.getName())
|
|
220
|
-
)
|
|
221
|
-
self.term = term.getBit(self.term.getBit())
|
|
222
|
-
else:
|
|
223
|
-
self.term = (
|
|
224
|
-
self.path.getTailInstance().getModel().getTerm(self.term.getName())
|
|
225
|
-
)
|
|
226
359
|
|
|
227
360
|
def is_bus(self) -> bool:
|
|
228
361
|
"""Return True if the term is a bus."""
|
|
229
|
-
return isinstance(self.
|
|
362
|
+
return isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm)
|
|
230
363
|
|
|
231
364
|
def is_bus_bit(self) -> bool:
|
|
232
365
|
"""Return True if the term is a bit of a bus."""
|
|
233
|
-
return isinstance(self.
|
|
366
|
+
return isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTermBit)
|
|
234
367
|
|
|
235
368
|
def is_scalar(self) -> bool:
|
|
236
369
|
"""Return True if the term is a scalar."""
|
|
237
|
-
return isinstance(self.
|
|
370
|
+
return isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLScalarTerm)
|
|
238
371
|
|
|
239
372
|
def is_bit(self) -> bool:
|
|
240
373
|
"""Return True if the term is a bit."""
|
|
@@ -242,37 +375,39 @@ class Term:
|
|
|
242
375
|
|
|
243
376
|
def get_msb(self) -> int:
|
|
244
377
|
"""Return the most significant bit of the term if it is a bus."""
|
|
245
|
-
if isinstance(self.
|
|
246
|
-
return self.
|
|
378
|
+
if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
|
|
379
|
+
return get_snl_term_for_ids(self.pathIDs, self.termIDs).getMSB()
|
|
247
380
|
return None
|
|
248
381
|
|
|
249
382
|
def get_lsb(self) -> int:
|
|
250
383
|
"""Return the least significant bit of the term if it is a bus."""
|
|
251
|
-
if isinstance(self.
|
|
252
|
-
return self.
|
|
384
|
+
if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
|
|
385
|
+
return get_snl_term_for_ids(self.pathIDs, self.termIDs).getLSB()
|
|
253
386
|
return None
|
|
254
387
|
|
|
255
388
|
def get_width(self) -> int:
|
|
256
389
|
"""Return the width of the term. 1 if scalar."""
|
|
257
|
-
return self.
|
|
390
|
+
return get_snl_term_for_ids(self.pathIDs, self.termIDs).getWidth()
|
|
258
391
|
|
|
259
392
|
def get_name(self) -> str:
|
|
260
393
|
"""Return the name of the term."""
|
|
261
|
-
return self.
|
|
394
|
+
return get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()
|
|
262
395
|
|
|
263
396
|
def get_direction(self) -> snl.SNLTerm.Direction:
|
|
264
397
|
"""Return the direction of the term."""
|
|
265
|
-
|
|
398
|
+
snlterm = get_snl_term_for_ids(self.pathIDs, self.termIDs)
|
|
399
|
+
if snlterm.getDirection() == snl.SNLTerm.Direction.Input:
|
|
266
400
|
return Term.INPUT
|
|
267
|
-
elif
|
|
401
|
+
elif snlterm.getDirection() == snl.SNLTerm.Direction.Output:
|
|
268
402
|
return Term.OUTPUT
|
|
269
|
-
elif
|
|
403
|
+
elif snlterm.getDirection() == snl.SNLTerm.Direction.InOut:
|
|
270
404
|
return Term.INOUT
|
|
271
405
|
|
|
272
406
|
def __get_snl_bitnet(self, bit) -> Net:
|
|
273
407
|
# single bit
|
|
274
|
-
|
|
275
|
-
|
|
408
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
409
|
+
if path.size() > 0:
|
|
410
|
+
instTerm = path.getTailInstance().getInstTerm(bit)
|
|
276
411
|
return instTerm.getNet()
|
|
277
412
|
else:
|
|
278
413
|
return bit.getNet()
|
|
@@ -300,9 +435,9 @@ class Term:
|
|
|
300
435
|
return snl_bus_net
|
|
301
436
|
|
|
302
437
|
def __get_net(self, path, snl_term_net_accessor) -> Net:
|
|
303
|
-
if isinstance(self.
|
|
438
|
+
if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
|
|
304
439
|
snl_nets = []
|
|
305
|
-
for bit in self.
|
|
440
|
+
for bit in get_snl_term_for_ids(self.pathIDs, self.termIDs).getBits():
|
|
306
441
|
snl_net = snl_term_net_accessor(bit)
|
|
307
442
|
snl_nets.append(snl_net)
|
|
308
443
|
snl_bus_net = self.__get_snl_busnet(snl_nets)
|
|
@@ -312,57 +447,65 @@ class Term:
|
|
|
312
447
|
if all(element is not None for element in snl_nets):
|
|
313
448
|
return Net(path, net_concat=snl_nets)
|
|
314
449
|
else:
|
|
315
|
-
snl_net = snl_term_net_accessor(self.
|
|
450
|
+
snl_net = snl_term_net_accessor(get_snl_term_for_ids(self.pathIDs, self.termIDs))
|
|
316
451
|
if snl_net is not None:
|
|
317
452
|
return Net(path, snl_net)
|
|
318
453
|
return None
|
|
319
454
|
|
|
320
455
|
def get_lower_net(self) -> Net:
|
|
456
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
321
457
|
"""Return the lower net of the term."""
|
|
322
|
-
return self.__get_net(
|
|
458
|
+
return self.__get_net(path, self.__get_snl_lower_bitnet)
|
|
323
459
|
|
|
324
460
|
def get_net(self) -> Net:
|
|
325
461
|
"""Return the net of the term."""
|
|
326
|
-
|
|
462
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
463
|
+
if path.empty():
|
|
327
464
|
return None
|
|
328
465
|
# path is one level up
|
|
329
|
-
|
|
330
|
-
return self.__get_net(
|
|
466
|
+
head_path = path.getHeadPath()
|
|
467
|
+
return self.__get_net(head_path, self.__get_snl_bitnet)
|
|
331
468
|
|
|
332
469
|
def get_instance(self):
|
|
470
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
333
471
|
"""Return the instance of the term."""
|
|
334
|
-
return Instance(
|
|
472
|
+
return Instance(path)
|
|
335
473
|
|
|
336
474
|
def get_flat_fanout(self):
|
|
337
|
-
return self.get_equipotential().
|
|
475
|
+
return self.get_equipotential().get_leaf_readers()
|
|
338
476
|
|
|
339
477
|
def get_equipotential(self) -> Equipotential:
|
|
340
478
|
return Equipotential(self)
|
|
341
479
|
|
|
342
480
|
def is_input(self) -> bool:
|
|
343
481
|
"""Return True if the term is an input."""
|
|
344
|
-
|
|
482
|
+
snlterm = get_snl_term_for_ids(self.pathIDs, self.termIDs)
|
|
483
|
+
return snlterm.getDirection() == snl.SNLTerm.Direction.Input
|
|
345
484
|
|
|
346
485
|
def is_output(self) -> bool:
|
|
347
486
|
"""Return True if the term is an output."""
|
|
348
|
-
|
|
487
|
+
snlterm = get_snl_term_for_ids(self.pathIDs, self.termIDs)
|
|
488
|
+
return snlterm.getDirection() == snl.SNLTerm.Direction.Output
|
|
349
489
|
|
|
350
490
|
def get_bits(self):
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
491
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
492
|
+
if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
|
|
493
|
+
for bit in get_snl_term_for_ids(self.pathIDs, self.termIDs).getBits():
|
|
494
|
+
yield Term(path, bit)
|
|
354
495
|
else:
|
|
355
496
|
yield self
|
|
356
497
|
|
|
357
498
|
def get_bit(self, index: int):
|
|
358
|
-
|
|
359
|
-
|
|
499
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
500
|
+
if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
|
|
501
|
+
return Term(path, get_snl_term_for_ids(self.pathIDs, self.termIDs).getBit(index))
|
|
360
502
|
return None
|
|
361
503
|
|
|
362
504
|
def disconnect(self):
|
|
505
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
363
506
|
self.__make_unique()
|
|
364
|
-
inst =
|
|
365
|
-
for bit in self.
|
|
507
|
+
inst = path.getTailInstance()
|
|
508
|
+
for bit in get_snl_term_for_ids(self.pathIDs, self.termIDs).getBits():
|
|
366
509
|
iterm = inst.getInstTerm(bit)
|
|
367
510
|
iterm.setNet(None)
|
|
368
511
|
|
|
@@ -370,13 +513,18 @@ class Term:
|
|
|
370
513
|
if self.get_width() != net.get_width():
|
|
371
514
|
raise ValueError("Width mismatch")
|
|
372
515
|
if self.get_instance().is_top():
|
|
373
|
-
for bterm, bnet in zip(self.
|
|
516
|
+
for bterm, bnet in zip(get_snl_term_for_ids(self.pathIDs,
|
|
517
|
+
self.termIDs).getBits(),
|
|
518
|
+
net.net.getBits()):
|
|
374
519
|
logging.debug(f"Connecting {bterm} to {bnet}")
|
|
375
520
|
bterm.setNet(bnet)
|
|
376
521
|
else:
|
|
377
522
|
self.__make_unique()
|
|
378
|
-
|
|
379
|
-
|
|
523
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
524
|
+
inst = path.getTailInstance()
|
|
525
|
+
for bterm, bnet in zip(get_snl_term_for_ids(self.pathIDs,
|
|
526
|
+
self.termIDs).getBits(),
|
|
527
|
+
net.net.getBits()):
|
|
380
528
|
iterm = inst.getInstTerm(bterm)
|
|
381
529
|
iterm.setNet(bnet)
|
|
382
530
|
|
|
@@ -396,19 +544,15 @@ def get_instance_by_path(names: list):
|
|
|
396
544
|
|
|
397
545
|
|
|
398
546
|
def refresh_path(path: snl.SNLPath):
|
|
399
|
-
pathlist =
|
|
400
|
-
pathTemp = path
|
|
401
|
-
while pathTemp.size() > 0:
|
|
402
|
-
pathlist.append(pathTemp.getHeadInstance().getName())
|
|
403
|
-
pathTemp = pathTemp.getTailPath()
|
|
547
|
+
pathlist = path.getPathIDs()
|
|
404
548
|
assert len(pathlist) > 0
|
|
405
549
|
path = snl.SNLPath()
|
|
406
550
|
instance = None
|
|
407
551
|
top = snl.SNLUniverse.get().getTopDesign()
|
|
408
552
|
design = top
|
|
409
|
-
for
|
|
410
|
-
path = snl.SNLPath(path, design.
|
|
411
|
-
instance = design.
|
|
553
|
+
for id in pathlist:
|
|
554
|
+
path = snl.SNLPath(path, design.getInstanceByID(id))
|
|
555
|
+
instance = design.getInstanceByID(id)
|
|
412
556
|
assert instance is not None
|
|
413
557
|
design = instance.getModel()
|
|
414
558
|
return path
|
|
@@ -420,10 +564,13 @@ class Instance:
|
|
|
420
564
|
"""
|
|
421
565
|
|
|
422
566
|
def __init__(self, path=snl.SNLPath()):
|
|
423
|
-
|
|
567
|
+
if path.size() > 0:
|
|
568
|
+
self.pathIDs = path.getPathIDs()
|
|
569
|
+
else:
|
|
570
|
+
self.pathIDs = []
|
|
424
571
|
|
|
425
572
|
def __eq__(self, other) -> bool:
|
|
426
|
-
return self.
|
|
573
|
+
return self.pathIDs == other.pathIDs
|
|
427
574
|
|
|
428
575
|
def __str__(self):
|
|
429
576
|
if self.is_top():
|
|
@@ -433,17 +580,36 @@ class Instance:
|
|
|
433
580
|
else:
|
|
434
581
|
return ""
|
|
435
582
|
else:
|
|
436
|
-
|
|
583
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
584
|
+
return str(path)
|
|
437
585
|
|
|
438
586
|
def __repr__(self) -> str:
|
|
439
|
-
|
|
587
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
588
|
+
return f"Instance({path})"
|
|
440
589
|
|
|
441
590
|
def __hash__(self):
|
|
442
|
-
return
|
|
591
|
+
return consistent_hash(self.pathIDs)
|
|
592
|
+
|
|
593
|
+
def get_leaf_children(self):
|
|
594
|
+
initial_path = get_snl_path_from_id_list(self.pathIDs)
|
|
595
|
+
for inst in self.__get_snl_model().getInstances():
|
|
596
|
+
if inst.getModel().isLeaf():
|
|
597
|
+
yield Instance(snl.SNLPath(initial_path, inst))
|
|
598
|
+
path = snl.SNLPath(initial_path, inst)
|
|
599
|
+
stack = [[inst, path]]
|
|
600
|
+
while stack:
|
|
601
|
+
current = stack.pop()
|
|
602
|
+
current_inst = current[0]
|
|
603
|
+
current_path = current[1]
|
|
604
|
+
for inst_child in current_inst.getModel().getInstances():
|
|
605
|
+
path_child = snl.SNLPath(current_path, inst_child)
|
|
606
|
+
if inst_child.getModel().isLeaf():
|
|
607
|
+
yield Instance(path_child)
|
|
608
|
+
stack.append([inst_child, path_child])
|
|
443
609
|
|
|
444
610
|
def is_top(self) -> bool:
|
|
445
611
|
"""Return True if this is the top design."""
|
|
446
|
-
return self.
|
|
612
|
+
return len(self.pathIDs) == 0
|
|
447
613
|
|
|
448
614
|
def is_assign(self) -> bool:
|
|
449
615
|
return self.__get_snl_model().isAssign()
|
|
@@ -480,7 +646,8 @@ class Instance:
|
|
|
480
646
|
"""Return the model of the instance."""
|
|
481
647
|
if self.is_top():
|
|
482
648
|
return snl.SNLUniverse.get().getTopDesign()
|
|
483
|
-
|
|
649
|
+
instance = get_snl_instance_from_id_list(self.pathIDs)
|
|
650
|
+
return instance.getModel()
|
|
484
651
|
|
|
485
652
|
def __find_snl_model(self, name: str) -> snl.SNLDesign:
|
|
486
653
|
u = snl.SNLUniverse.get()
|
|
@@ -495,11 +662,13 @@ class Instance:
|
|
|
495
662
|
childInst = self.__get_snl_model().getInstance(name)
|
|
496
663
|
if childInst is None:
|
|
497
664
|
return None
|
|
498
|
-
|
|
665
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
666
|
+
return Instance(snl.SNLPath(path, childInst))
|
|
499
667
|
|
|
500
668
|
def get_child_instances(self):
|
|
501
669
|
for inst in self.__get_snl_model().getInstances():
|
|
502
|
-
|
|
670
|
+
path_init = get_snl_path_from_id_list(self.pathIDs)
|
|
671
|
+
path = snl.SNLPath(path_init, inst)
|
|
503
672
|
yield Instance(path)
|
|
504
673
|
|
|
505
674
|
def get_number_of_child_instances(self) -> int:
|
|
@@ -522,21 +691,24 @@ class Instance:
|
|
|
522
691
|
# stack.append([inst_child, path_child])
|
|
523
692
|
|
|
524
693
|
def get_nets(self):
|
|
694
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
525
695
|
for net in self.__get_snl_model().getNets():
|
|
526
|
-
yield Net(
|
|
696
|
+
yield Net(path, net)
|
|
527
697
|
|
|
528
698
|
def get_flat_nets(self):
|
|
699
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
529
700
|
for net in self.__get_snl_model().getNets():
|
|
530
701
|
if isinstance(net, snl.SNLBusNet):
|
|
531
702
|
for bit in net.getBits():
|
|
532
|
-
yield Net(
|
|
703
|
+
yield Net(path, bit)
|
|
533
704
|
else:
|
|
534
|
-
yield Net(
|
|
705
|
+
yield Net(path, net)
|
|
535
706
|
|
|
536
707
|
def get_net(self, name: str) -> Net:
|
|
708
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
537
709
|
net = self.__get_snl_model().getNet(name)
|
|
538
710
|
if net is not None:
|
|
539
|
-
return Net(
|
|
711
|
+
return Net(path, net)
|
|
540
712
|
return None
|
|
541
713
|
|
|
542
714
|
def is_primitive(self) -> bool:
|
|
@@ -544,61 +716,91 @@ class Instance:
|
|
|
544
716
|
return self.__get_snl_model().isPrimitive()
|
|
545
717
|
|
|
546
718
|
def get_terms(self):
|
|
719
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
547
720
|
for term in self.__get_snl_model().getTerms():
|
|
548
|
-
yield Term(
|
|
721
|
+
yield Term(path, term)
|
|
549
722
|
|
|
550
723
|
def get_flat_terms(self):
|
|
724
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
551
725
|
for term in self.__get_snl_model().getBitTerms():
|
|
552
|
-
yield Term(
|
|
726
|
+
yield Term(path, term)
|
|
553
727
|
|
|
554
728
|
def get_term(self, name: str) -> Term:
|
|
729
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
555
730
|
term = self.__get_snl_model().getTerm(name)
|
|
556
731
|
if term is not None:
|
|
557
|
-
return Term(
|
|
732
|
+
return Term(path, self.__get_snl_model().getTerm(name))
|
|
558
733
|
return None
|
|
559
734
|
|
|
560
735
|
def get_input_terms(self):
|
|
736
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
561
737
|
for term in self.__get_snl_model().getTerms():
|
|
562
|
-
if term.getDirection()
|
|
563
|
-
yield Term(
|
|
738
|
+
if term.getDirection() != snl.SNLTerm.Direction.Output:
|
|
739
|
+
yield Term(path, term)
|
|
564
740
|
|
|
565
741
|
def get_flat_input_terms(self):
|
|
742
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
566
743
|
for term in self.__get_snl_model().getTerms():
|
|
567
|
-
if term.getDirection()
|
|
744
|
+
if term.getDirection() != snl.SNLTerm.Direction.Output:
|
|
568
745
|
if isinstance(term, snl.SNLBusTerm):
|
|
569
746
|
for bit in term.getBits():
|
|
570
|
-
yield Term(
|
|
747
|
+
yield Term(path, bit)
|
|
571
748
|
else:
|
|
572
|
-
yield Term(
|
|
749
|
+
yield Term(path, term)
|
|
573
750
|
|
|
574
751
|
def get_output_terms(self):
|
|
752
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
575
753
|
for term in self.__get_snl_model().getTerms():
|
|
576
|
-
if term.getDirection()
|
|
577
|
-
yield Term(
|
|
754
|
+
if term.getDirection() != snl.SNLTerm.Direction.Input:
|
|
755
|
+
yield Term(path, term)
|
|
578
756
|
|
|
579
757
|
def get_flat_output_terms(self):
|
|
758
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
580
759
|
for term in self.__get_snl_model().getTerms():
|
|
581
|
-
if term.getDirection()
|
|
760
|
+
if term.getDirection() != snl.SNLTerm.Direction.Input:
|
|
582
761
|
if isinstance(term, snl.SNLBusTerm):
|
|
583
762
|
for bit in term.getBits():
|
|
584
|
-
yield Term(
|
|
763
|
+
yield Term(path, bit)
|
|
585
764
|
else:
|
|
586
|
-
yield Term(
|
|
765
|
+
yield Term(path, term)
|
|
587
766
|
|
|
588
767
|
def delete_instance(self, name: str):
|
|
589
|
-
|
|
768
|
+
init_path = get_snl_path_from_id_list(self.pathIDs)
|
|
769
|
+
if name == "":
|
|
770
|
+
raise ValueError(
|
|
771
|
+
"Cannot delete instance with empty name. Try delete_instance_by_id instead."
|
|
772
|
+
)
|
|
773
|
+
path = snl.SNLPath(init_path, self.__get_snl_model().getInstance(name))
|
|
774
|
+
snl.SNLUniquifier(path)
|
|
775
|
+
if init_path.size() > 0:
|
|
776
|
+
# Delete the last instance in uniq_path
|
|
777
|
+
self.__get_snl_model().getInstance(name).destroy()
|
|
778
|
+
|
|
779
|
+
def delete_instance_by_id(self, id: str):
|
|
780
|
+
init_path = get_snl_path_from_id_list(self.pathIDs)
|
|
781
|
+
path = snl.SNLPath(init_path, self.__get_snl_model().getInstanceByID(id))
|
|
590
782
|
snl.SNLUniquifier(path)
|
|
591
|
-
if self.path.size() > 0:
|
|
592
|
-
self.path = refresh_path(self.path)
|
|
593
783
|
# Delete the last instance in uniq_path
|
|
594
|
-
self.__get_snl_model().
|
|
784
|
+
self.__get_snl_model().getInstanceByID(id).destroy()
|
|
785
|
+
|
|
786
|
+
def get_design(self):
|
|
787
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
788
|
+
if len(self.pathIDs) == 1:
|
|
789
|
+
return get_top()
|
|
790
|
+
return Instance(path.getHeadPath())
|
|
791
|
+
|
|
792
|
+
def delete(self):
|
|
793
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
794
|
+
snl.SNLUniquifier(path)
|
|
795
|
+
self.get_design().delete_instance_by_id(path.getTailInstance().getID())
|
|
595
796
|
|
|
596
797
|
def get_name(self) -> str:
|
|
798
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
597
799
|
"""Return the name of the instance or name of the top is this is the top."""
|
|
598
800
|
if self.is_top():
|
|
599
801
|
return self.get_model_name()
|
|
600
802
|
else:
|
|
601
|
-
return
|
|
803
|
+
return path.getTailInstance().getName()
|
|
602
804
|
|
|
603
805
|
def get_model_name(self) -> str:
|
|
604
806
|
"""Return the name of the model of the instance or name of the top is this is the top."""
|
|
@@ -609,10 +811,10 @@ class Instance:
|
|
|
609
811
|
return model.getDB().getID(), model.getLibrary().getID(), model.getID()
|
|
610
812
|
|
|
611
813
|
def create_child_instance(self, model: str, name: str):
|
|
612
|
-
|
|
613
|
-
|
|
814
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
815
|
+
if path.size() > 0:
|
|
614
816
|
snl.SNLUniquifier(path)
|
|
615
|
-
|
|
817
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
616
818
|
design = self.__get_snl_model()
|
|
617
819
|
new_instance_model = self.__find_snl_model(model)
|
|
618
820
|
if new_instance_model is None:
|
|
@@ -620,17 +822,17 @@ class Instance:
|
|
|
620
822
|
f"Cannot create instance {name} in {self}: model {model} cannot be found"
|
|
621
823
|
)
|
|
622
824
|
newSNLInstance = snl.SNLInstance.create(design, new_instance_model, name)
|
|
623
|
-
path = snl.SNLPath(
|
|
825
|
+
path = snl.SNLPath(path, newSNLInstance)
|
|
624
826
|
return Instance(path)
|
|
625
827
|
|
|
626
828
|
def create_term(self, name: str, direction: snl.SNLTerm.Direction) -> Term:
|
|
627
|
-
|
|
628
|
-
|
|
829
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
830
|
+
if path.size() > 0:
|
|
629
831
|
snl.SNLUniquifier(path)
|
|
630
|
-
|
|
832
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
631
833
|
design = self.__get_snl_model()
|
|
632
834
|
newSNLTerm = snl.SNLScalarTerm.create(design, direction, name)
|
|
633
|
-
return Term(
|
|
835
|
+
return Term(path, newSNLTerm)
|
|
634
836
|
|
|
635
837
|
def create_output_term(self, name: str) -> Term:
|
|
636
838
|
return self.create_term(name, snl.SNLTerm.Direction.Output)
|
|
@@ -642,13 +844,13 @@ class Instance:
|
|
|
642
844
|
return self.create_term(name, snl.SNLTerm.Direction.InOut)
|
|
643
845
|
|
|
644
846
|
def create_bus_term(self, name: str, msb: int, lsb: int, direction) -> Term:
|
|
645
|
-
|
|
646
|
-
|
|
847
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
848
|
+
if path.size() > 0:
|
|
647
849
|
snl.SNLUniquifier(path)
|
|
648
|
-
|
|
850
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
649
851
|
design = self.__get_snl_model()
|
|
650
852
|
newSNLTerm = snl.SNLBusTerm.create(design, direction, msb, lsb, name)
|
|
651
|
-
return Term(
|
|
853
|
+
return Term(path, newSNLTerm)
|
|
652
854
|
|
|
653
855
|
def create_inout_bus_term(self, name: str, msb: int, lsb: int) -> Term:
|
|
654
856
|
return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.InOut)
|
|
@@ -660,22 +862,22 @@ class Instance:
|
|
|
660
862
|
return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.Input)
|
|
661
863
|
|
|
662
864
|
def create_net(self, name: str) -> Net:
|
|
663
|
-
|
|
664
|
-
|
|
865
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
866
|
+
if path.size() > 0:
|
|
665
867
|
snl.SNLUniquifier(path)
|
|
666
|
-
|
|
868
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
667
869
|
model = self.__get_snl_model()
|
|
668
870
|
newSNLNet = snl.SNLScalarNet.create(model, name)
|
|
669
|
-
return Net(
|
|
871
|
+
return Net(path, newSNLNet)
|
|
670
872
|
|
|
671
873
|
def create_bus_net(self, name: str, msb: int, lsb: int) -> Net:
|
|
672
|
-
|
|
673
|
-
|
|
874
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
875
|
+
if path.size() > 0:
|
|
674
876
|
snl.SNLUniquifier(path)
|
|
675
|
-
|
|
877
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
676
878
|
model = self.__get_snl_model()
|
|
677
879
|
newSNLNet = snl.SNLBusNet.create(model, msb, lsb, name)
|
|
678
|
-
return Net(
|
|
880
|
+
return Net(path, newSNLNet)
|
|
679
881
|
|
|
680
882
|
def dump_verilog(self, path: str, name: str):
|
|
681
883
|
self.__get_snl_model().dumpVerilog(path, name)
|
|
@@ -731,7 +933,7 @@ def load_primitives(name: str):
|
|
|
731
933
|
def get_primitives_library() -> snl.SNLLibrary:
|
|
732
934
|
lib = get_top_db().getLibrary("PRIMS")
|
|
733
935
|
if lib is None:
|
|
734
|
-
lib = snl.SNLLibrary.createPrimitives(get_top_db())
|
|
936
|
+
lib = snl.SNLLibrary.createPrimitives(get_top_db(), "PRIMS")
|
|
735
937
|
return lib
|
|
736
938
|
|
|
737
939
|
|