najaeda 0.1.5__cp312-cp312-macosx_11_0_arm64.whl → 0.1.7__cp312-cp312-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/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
- if isinstance(term.term, snl.SNLBusTerm):
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
- term.path.getHeadPath(), term.path.getTailInstance().getInstTerm(term.term)
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
- for term in self.equi.getInstTermOccurrences():
31
- yield Term(
32
- snl.SNLPath(term.getPath(), term.getInstTerm().getInstance()),
33
- term.getInstTerm().getBitTerm(),
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
- for term in self.equi.getTerms():
38
- yield Term(snl.SNLPath(), term)
39
-
40
- def get_all_leaf_readers(self):
41
- for term in self.equi.getInstTermOccurrences():
42
- direction = term.getInstTerm().getDirection()
43
- if direction != snl.SNLTerm.Direction.Output:
44
- if term.getInstTerm().getInstance().getModel().isLeaf():
45
- yield Term(
46
- snl.SNLPath(term.getPath(), term.getInstTerm().getInstance()),
47
- term.getInstTerm().getBitTerm(),
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
- self.path = path
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
- if self.path.size() > 0:
80
- return f"{self.path}/{net_str}"
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(self.path, bit)
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(self.path, self.net.getBit(index))
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(self.path, self.net_concat[index])
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(self.path, term.getInstance())
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(self.path, 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.path = path
182
- self.term = term
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.path == other.path and self.term == other.term
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.path != other.path:
192
- return self.path < other.path
193
- return self.term < other.term
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
- if self.path.size() == 0:
206
- return self.term.getName()
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"{self.path}/{self.term}"
348
+ return f"{path}/{get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()}"
209
349
 
210
350
  def __repr__(self) -> str:
211
- return f"Term({self.path}, {self.term})"
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
- if self.path.size() > 1:
215
- path = self.path.getHeadPath()
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.term, snl.SNLBusTerm)
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.term, snl.SNLBusTermBit)
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.term, snl.SNLScalarTerm)
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.term, snl.SNLBusTerm):
246
- return self.term.getMSB()
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.term, snl.SNLBusTerm):
252
- return self.term.getLSB()
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.term.getWidth()
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.term.getName()
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
- if self.term.getDirection() == snl.SNLTerm.Direction.Input:
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 self.term.getDirection() == snl.SNLTerm.Direction.Output:
401
+ elif snlterm.getDirection() == snl.SNLTerm.Direction.Output:
268
402
  return Term.OUTPUT
269
- elif self.term.getDirection() == snl.SNLTerm.Direction.InOut:
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
- if self.path.size() > 0:
275
- instTerm = self.path.getTailInstance().getInstTerm(bit)
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.term, snl.SNLBusTerm):
438
+ if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
304
439
  snl_nets = []
305
- for bit in self.term.getBits():
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.term)
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(self.path, self.__get_snl_lower_bitnet)
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
- if self.path.empty():
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
- path = self.path.getHeadPath()
330
- return self.__get_net(path, self.__get_snl_bitnet)
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(self.path)
472
+ return Instance(path)
335
473
 
336
474
  def get_flat_fanout(self):
337
- return self.get_equipotential().get_all_leaf_readers()
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
- return self.term.getDirection() == snl.SNLTerm.Direction.Input
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
- return self.term.getDirection() == snl.SNLTerm.Direction.Output
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
- if isinstance(self.term, snl.SNLBusTerm):
352
- for bit in self.term.getBits():
353
- yield Term(self.path, bit)
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
- if isinstance(self.term, snl.SNLBusTerm):
359
- return Term(self.path, self.term.getBit(index))
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 = self.path.getTailInstance()
365
- for bit in self.term.getBits():
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.term.getBits(), net.net.getBits()):
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
- inst = self.path.getTailInstance()
379
- for bterm, bnet in zip(self.term.getBits(), net.net.getBits()):
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 name in pathlist:
410
- path = snl.SNLPath(path, design.getInstance(name))
411
- instance = design.getInstance(name)
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
- self.path = path
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.path == other.path
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
- return str(self.path)
583
+ path = get_snl_path_from_id_list(self.pathIDs)
584
+ return str(path)
437
585
 
438
586
  def __repr__(self) -> str:
439
- return f"Instance({self.path})"
587
+ path = get_snl_path_from_id_list(self.pathIDs)
588
+ return f"Instance({path})"
440
589
 
441
590
  def __hash__(self):
442
- return hash(self.path)
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.path.size() == 0
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
- return self.path.getTailInstance().getModel()
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
- return Instance(snl.SNLPath(self.path, childInst))
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
- path = snl.SNLPath(self.path, inst)
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(self.path, 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(self.path, bit)
703
+ yield Net(path, bit)
533
704
  else:
534
- yield Net(self.path, 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(self.path, 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(self.path, 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(self.path, 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(self.path, self.__get_snl_model().getTerm(name))
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() == snl.SNLTerm.Direction.Input:
563
- yield Term(self.path, 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() == snl.SNLTerm.Direction.Input:
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(self.path, bit)
747
+ yield Term(path, bit)
571
748
  else:
572
- yield Term(self.path, 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() == snl.SNLTerm.Direction.Output:
577
- yield Term(self.path, 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() == snl.SNLTerm.Direction.Output:
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(self.path, bit)
763
+ yield Term(path, bit)
585
764
  else:
586
- yield Term(self.path, term)
765
+ yield Term(path, term)
587
766
 
588
767
  def delete_instance(self, name: str):
589
- path = snl.SNLPath(self.path, self.__get_snl_model().getInstance(name))
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().getInstance(name).destroy()
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 self.path.getTailInstance().getName()
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
- if self.path.size() > 0:
613
- path = self.path
814
+ path = get_snl_path_from_id_list(self.pathIDs)
815
+ if path.size() > 0:
614
816
  snl.SNLUniquifier(path)
615
- self.path = refresh_path(self.path)
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(self.path, newSNLInstance)
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
- if self.path.size() > 0:
628
- path = self.path
829
+ path = get_snl_path_from_id_list(self.pathIDs)
830
+ if path.size() > 0:
629
831
  snl.SNLUniquifier(path)
630
- self.path = refresh_path(self.path)
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(self.path, newSNLTerm)
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
- if self.path.size() > 0:
646
- path = self.path
847
+ path = get_snl_path_from_id_list(self.pathIDs)
848
+ if path.size() > 0:
647
849
  snl.SNLUniquifier(path)
648
- self.path = refresh_path(self.path)
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(self.path, newSNLTerm)
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
- if self.path.size() > 0:
664
- path = self.path
865
+ path = get_snl_path_from_id_list(self.pathIDs)
866
+ if path.size() > 0:
665
867
  snl.SNLUniquifier(path)
666
- self.path = refresh_path(self.path)
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(self.path, newSNLNet)
871
+ return Net(path, newSNLNet)
670
872
 
671
873
  def create_bus_net(self, name: str, msb: int, lsb: int) -> Net:
672
- if self.path.size() > 0:
673
- path = self.path
874
+ path = get_snl_path_from_id_list(self.pathIDs)
875
+ if path.size() > 0:
674
876
  snl.SNLUniquifier(path)
675
- self.path = refresh_path(self.path)
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(self.path, newSNLNet)
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