najaeda 0.1.7__cp311-cp311-macosx_11_0_arm64.whl → 0.1.9__cp311-cp311-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
@@ -7,10 +7,10 @@ import itertools
7
7
  import time
8
8
  import logging
9
9
  import hashlib
10
- # import json
11
- from najaeda import snl
12
10
  import struct
13
11
 
12
+ from najaeda import snl
13
+
14
14
 
15
15
  def consistent_hash(obj):
16
16
  def default_serializer(o):
@@ -23,13 +23,13 @@ def consistent_hash(obj):
23
23
 
24
24
  def hash_value(value):
25
25
  if isinstance(value, int):
26
- return struct.pack('!q', value)
26
+ return struct.pack("!q", value)
27
27
  else:
28
28
  raise TypeError(f"Unsupported type: {type(value)}")
29
29
 
30
30
  def hash_object(o):
31
31
  if isinstance(o, (list, tuple)):
32
- return b''.join(hash_object(i) for i in o)
32
+ return b"".join(hash_object(i) for i in o)
33
33
  else:
34
34
  return hash_value(o)
35
35
 
@@ -71,6 +71,7 @@ class Equipotential:
71
71
 
72
72
  def __init__(self, term):
73
73
  snl_term = get_snl_term_for_ids(term.pathIDs, term.termIDs)
74
+ inst_term = None
74
75
  if isinstance(snl_term, snl.SNLBusTerm):
75
76
  raise ValueError("Equipotential cannot be constructed on bus term")
76
77
  if len(term.pathIDs) == 0:
@@ -82,20 +83,29 @@ class Equipotential:
82
83
  if inst_term is None:
83
84
  self.equi = None
84
85
  return
86
+ else:
87
+ snl_term = get_snl_term_for_ids(inst_term.pathIDs, inst_term.termIDs)
85
88
  else:
86
89
  inst_term = term
87
90
  path = get_snl_path_from_id_list(inst_term.pathIDs)
88
- snl_term = get_snl_term_for_ids(inst_term.pathIDs, inst_term.termIDs)
89
91
  ito = snl.SNLNetComponentOccurrence(
90
- path.getHeadPath(),
91
- path.getTailInstance().getInstTerm(snl_term)
92
+ path.getHeadPath(), path.getTailInstance().getInstTerm(snl_term)
92
93
  )
93
94
  self.equi = snl.SNLEquipotential(ito)
94
95
 
95
96
  def __eq__(self, value):
96
97
  return self.equi == value.equi
97
98
 
99
+ def dump_dot(self, path: str):
100
+ """Dump the dot file of this equipotential."""
101
+ self.equi.dumpDotFile(path)
102
+
98
103
  def get_inst_terms(self):
104
+ """Iterate over the instance terminals of this equipotential.
105
+
106
+ :return: an iterator over the instance terminals of this equipotential.
107
+ :rtype: Iterator[Term]
108
+ """
99
109
  if self.equi is not None:
100
110
  for term in self.equi.getInstTermOccurrences():
101
111
  yield Term(
@@ -104,9 +114,14 @@ class Equipotential:
104
114
  )
105
115
 
106
116
  def get_top_terms(self):
117
+ """Iterate over the top terminals of this equipotential.
118
+
119
+ :return: an iterator over the top terminals of this equipotential.
120
+ :rtype: Iterator[Term]
121
+ """
107
122
  if self.equi is not None:
108
123
  for term in self.equi.getTerms():
109
- yield Term(snl.SNLPath(), term)
124
+ yield Term([], term)
110
125
 
111
126
  def get_leaf_readers(self):
112
127
  if self.equi is not None:
@@ -115,7 +130,9 @@ class Equipotential:
115
130
  if direction != snl.SNLTerm.Direction.Output:
116
131
  if term.getInstTerm().getInstance().getModel().isLeaf():
117
132
  yield Term(
118
- snl.SNLPath(term.getPath(), term.getInstTerm().getInstance()),
133
+ snl.SNLPath(
134
+ term.getPath(), term.getInstTerm().getInstance()
135
+ ),
119
136
  term.getInstTerm().getBitTerm(),
120
137
  )
121
138
 
@@ -126,7 +143,9 @@ class Equipotential:
126
143
  if direction != snl.SNLTerm.Direction.Input:
127
144
  if term.getInstTerm().getInstance().getModel().isLeaf():
128
145
  yield Term(
129
- snl.SNLPath(term.getPath(), term.getInstTerm().getInstance()),
146
+ snl.SNLPath(
147
+ term.getPath(), term.getInstTerm().getInstance()
148
+ ),
130
149
  term.getInstTerm().getBitTerm(),
131
150
  )
132
151
 
@@ -151,10 +170,13 @@ class Net:
151
170
  raise ValueError(
152
171
  "Only one of `net` or `net_concat` should be provided, not both."
153
172
  )
154
- if path.size() > 0:
155
- self.pathIDs = path.getPathIDs()
156
- else:
157
- self.pathIDs = []
173
+ if isinstance(path, snl.SNLPath):
174
+ if path.size() > 0:
175
+ self.pathIDs = path.getPathIDs()
176
+ else:
177
+ self.pathIDs = []
178
+ elif isinstance(path, list):
179
+ self.pathIDs = path.copy()
158
180
  if net is not None:
159
181
  self.net = net
160
182
  elif net_concat is not None:
@@ -182,45 +204,72 @@ class Net:
182
204
  return net_str
183
205
 
184
206
  def get_name(self) -> str:
185
- """Return the name of the net."""
207
+ """
208
+ :return: the name of this Net.
209
+ :rtype: str
210
+ """
186
211
  if hasattr(self, "net"):
187
212
  return self.net.getName()
188
213
  return "{" + ",".join(map(str, self.net_concat)) + "}"
189
214
 
190
215
  def get_msb(self) -> int:
191
- """Return the most significant bit of the net if it is a bus."""
216
+ """
217
+ :return: the most significant bit of the net if it is a bus.
218
+ :rtype: int
219
+ """
192
220
  if hasattr(self, "net") and isinstance(self.net, snl.SNLBusNet):
193
221
  return self.net.getMSB()
194
222
  return None
195
223
 
196
224
  def get_lsb(self) -> int:
197
- """Return the least significant bit of the net if it is a bus."""
225
+ """
226
+ :return: the least significant bit of the net if it is a bus.
227
+ :rtype: int
228
+ """
198
229
  if hasattr(self, "net") and isinstance(self.net, snl.SNLBusNet):
199
230
  return self.net.getLSB()
200
231
  return None
201
232
 
202
233
  def is_bus(self) -> bool:
203
- """Return True if the net is a bus."""
234
+ """
235
+ :return: True if the net is a bus.
236
+ :rtype: bool
237
+ """
204
238
  return hasattr(self, "net") and isinstance(self.net, snl.SNLBusNet)
205
239
 
206
240
  def is_bus_bit(self) -> bool:
207
- """Return True if the net is a bit of a bus."""
241
+ """
242
+ :return: True if the net is a bit of a bus.
243
+ :rtype: bool
244
+ """
208
245
  return hasattr(self, "net") and isinstance(self.net, snl.SNLBusNetBit)
209
246
 
210
247
  def is_scalar(self) -> bool:
211
- """Return True if the net is a scalar."""
248
+ """
249
+ :return: True if the net is a scalar.
250
+ :rtype: bool
251
+ """
212
252
  return hasattr(self, "net") and isinstance(self.net, snl.SNLScalarNet)
213
253
 
214
254
  def is_bit(self) -> bool:
215
- """Return True if the net is a bit."""
255
+ """
256
+ :return: True if the net is a bit.
257
+ :rtype: bool
258
+ """
216
259
  return self.is_scalar() or self.is_bus_bit()
217
260
 
218
261
  def is_concat(self) -> bool:
219
- """Return True if the net is a concatenation."""
262
+ """
263
+ :return: True if the net is a concatenation.
264
+ :rtype: bool
265
+ """
220
266
  return hasattr(self, "net_concat")
221
267
 
222
268
  def is_const(self) -> bool:
223
- """Return True if the net is a constant generator."""
269
+ """
270
+ :return: True if the net is a constant generator.
271
+ :rtype: bool
272
+ """
224
273
  if hasattr(self, "net"):
225
274
  return self.net.isConstant()
226
275
  for net in self.net_concat:
@@ -229,17 +278,24 @@ class Net:
229
278
  return True
230
279
 
231
280
  def get_width(self) -> int:
232
- """Return the width of the net."""
281
+ """
282
+ :return: the width of the net.
283
+ :rtype: int
284
+ """
233
285
  if hasattr(self, "net"):
234
286
  return self.net.getWidth()
235
287
  return sum(1 for _ in self.net_concat)
236
288
 
237
289
  def get_bits(self):
238
- path = get_snl_path_from_id_list(self.pathIDs)
290
+ """Iterate over the bits of this Net.
291
+ The iterator will return itself if the Net is scalar.
292
+ :return: an iterator over the bits of this Net.
293
+ :rtype: Iterator[Net]
294
+ """
239
295
  if hasattr(self, "net"):
240
296
  if isinstance(self.net, snl.SNLBusNet):
241
297
  for bit in self.net.getBits():
242
- yield Net(path, bit)
298
+ yield Net(self.pathIDs, bit)
243
299
  else:
244
300
  yield self
245
301
  else:
@@ -247,32 +303,47 @@ class Net:
247
303
  yield net
248
304
 
249
305
  def get_bit(self, index: int):
250
- path = get_snl_path_from_id_list(self.pathIDs)
306
+ """
307
+ :param int index: the index of the bit to get.
308
+ :return: the Net bit at the given index or None if it does not exist.
309
+ :rtype: Net
310
+ """
251
311
  if hasattr(self, "net"):
252
312
  if isinstance(self.net, snl.SNLBusNet):
253
- return Net(path, self.net.getBit(index))
313
+ return Net(self.pathIDs, self.net.getBit(index))
254
314
  else:
255
315
  return None
256
316
  if 0 <= index < len(self.net_concat):
257
- return Net(path, self.net_concat[index])
317
+ return Net(self.pathIDs, self.net_concat[index])
258
318
  return None
259
319
 
260
320
  def get_inst_terms(self):
261
- init_path = get_snl_path_from_id_list(self.pathIDs)
321
+ """
322
+ :return: an iterator over the instance terminals of the net.
323
+ :rtype: Iterator[Term]
324
+ """
262
325
  if hasattr(self, "net_concat"):
263
326
  raise ValueError("Cannot get inst terms from a net_concat")
264
327
  for term in self.net.getInstTerms():
265
- path = snl.SNLPath(init_path, term.getInstance())
328
+ path = self.pathIDs.copy()
329
+ path.append(term.getInstance().getID())
266
330
  yield Term(path, term.getBitTerm())
267
331
 
268
332
  def get_design_terms(self):
269
- path = get_snl_path_from_id_list(self.pathIDs)
333
+ """
334
+ :return: an iterator over the design terminals of the net.
335
+ :rtype: Iterator[Term]
336
+ """
270
337
  if hasattr(self, "net_concat"):
271
338
  raise ValueError("Cannot get terms from a net_concat")
272
339
  for term in self.net.getBitTerms():
273
- yield Term(path, term)
340
+ yield Term(self.pathIDs, term)
274
341
 
275
342
  def get_terms(self):
343
+ """
344
+ :return: an iterator over the terminals of the net.
345
+ :rtype: Iterator[Term]
346
+ """
276
347
  for term in itertools.chain(self.get_design_terms(), self.get_inst_terms()):
277
348
  yield term
278
349
 
@@ -306,10 +377,13 @@ class Term:
306
377
  else:
307
378
  self.termIDs = [term.getID(), term.getBit()]
308
379
 
309
- if path.size() > 0:
310
- self.pathIDs = path.getPathIDs()
311
- else:
312
- self.pathIDs = []
380
+ if isinstance(path, snl.SNLPath):
381
+ if path.size() > 0:
382
+ self.pathIDs = path.getPathIDs()
383
+ else:
384
+ self.pathIDs = []
385
+ elif isinstance(path, list):
386
+ self.pathIDs = path.copy()
313
387
 
314
388
  def __eq__(self, other) -> bool:
315
389
  return self.pathIDs == other.pathIDs and self.termIDs == other.termIDs
@@ -345,7 +419,9 @@ class Term:
345
419
  if path.size() == 0:
346
420
  return get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()
347
421
  else:
348
- return f"{path}/{get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()}"
422
+ return (
423
+ f"{path}/{get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()}"
424
+ )
349
425
 
350
426
  def __repr__(self) -> str:
351
427
  path = get_snl_path_from_id_list(self.pathIDs)
@@ -358,43 +434,76 @@ class Term:
358
434
  snl.SNLUniquifier(path)
359
435
 
360
436
  def is_bus(self) -> bool:
361
- """Return True if the term is a bus."""
362
- return isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm)
437
+ """
438
+ :return: True if the term is a bus.
439
+ :rtype: bool
440
+ """
441
+ return isinstance(
442
+ get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm
443
+ )
363
444
 
364
445
  def is_bus_bit(self) -> bool:
365
- """Return True if the term is a bit of a bus."""
366
- return isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTermBit)
446
+ """
447
+ :return: True if the term is a bit of a bus.
448
+ :rtype: bool
449
+ """
450
+ return isinstance(
451
+ get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTermBit
452
+ )
367
453
 
368
454
  def is_scalar(self) -> bool:
369
- """Return True if the term is a scalar."""
370
- return isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLScalarTerm)
455
+ """
456
+ :return: True if the term is a scalar.
457
+ :rtype: bool
458
+ """
459
+ return isinstance(
460
+ get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLScalarTerm
461
+ )
371
462
 
372
463
  def is_bit(self) -> bool:
373
- """Return True if the term is a bit."""
464
+ """
465
+ :return: True if the term is a bit.
466
+ :rtype: bool
467
+ """
374
468
  return self.is_scalar() or self.is_bus_bit()
375
469
 
376
470
  def get_msb(self) -> int:
377
- """Return the most significant bit of the term if it is a bus."""
471
+ """
472
+ :return: the most significant bit of the term if it is a bus.
473
+ :rtype: int or None
474
+ """
378
475
  if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
379
476
  return get_snl_term_for_ids(self.pathIDs, self.termIDs).getMSB()
380
477
  return None
381
478
 
382
479
  def get_lsb(self) -> int:
383
- """Return the least significant bit of the term if it is a bus."""
480
+ """
481
+ :return: the least significant bit of the term if it is a bus.
482
+ :rtype: int or None
483
+ """
384
484
  if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
385
485
  return get_snl_term_for_ids(self.pathIDs, self.termIDs).getLSB()
386
486
  return None
387
487
 
388
488
  def get_width(self) -> int:
389
- """Return the width of the term. 1 if scalar."""
489
+ """
490
+ :return: the width of the term. 1 if scalar.
491
+ :rtype: int
492
+ """
390
493
  return get_snl_term_for_ids(self.pathIDs, self.termIDs).getWidth()
391
494
 
392
495
  def get_name(self) -> str:
393
- """Return the name of the term."""
496
+ """
497
+ :return: the name of the term.
498
+ :rtype: str
499
+ """
394
500
  return get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()
395
501
 
396
502
  def get_direction(self) -> snl.SNLTerm.Direction:
397
- """Return the direction of the term."""
503
+ """
504
+ :return: the direction of the term.
505
+ :rtype: snl.SNLTerm.Direction
506
+ """
398
507
  snlterm = get_snl_term_for_ids(self.pathIDs, self.termIDs)
399
508
  if snlterm.getDirection() == snl.SNLTerm.Direction.Input:
400
509
  return Term.INPUT
@@ -447,29 +556,38 @@ class Term:
447
556
  if all(element is not None for element in snl_nets):
448
557
  return Net(path, net_concat=snl_nets)
449
558
  else:
450
- snl_net = snl_term_net_accessor(get_snl_term_for_ids(self.pathIDs, self.termIDs))
559
+ snl_net = snl_term_net_accessor(
560
+ get_snl_term_for_ids(self.pathIDs, self.termIDs)
561
+ )
451
562
  if snl_net is not None:
452
563
  return Net(path, snl_net)
453
564
  return None
454
565
 
455
566
  def get_lower_net(self) -> Net:
456
- path = get_snl_path_from_id_list(self.pathIDs)
457
- """Return the lower net of the term."""
458
- return self.__get_net(path, self.__get_snl_lower_bitnet)
567
+ """
568
+ :return: the lower net of the term.
569
+ :rtype: Net
570
+ """
571
+ return self.__get_net(self.pathIDs, self.__get_snl_lower_bitnet)
459
572
 
460
573
  def get_net(self) -> Net:
461
- """Return the net of the term."""
462
- path = get_snl_path_from_id_list(self.pathIDs)
463
- if path.empty():
574
+ """
575
+ :return: the net of the term.
576
+ :rtype: Net
577
+ """
578
+ head_path = self.pathIDs.copy()
579
+ if len(head_path) == 0:
464
580
  return None
465
581
  # path is one level up
466
- head_path = path.getHeadPath()
582
+ head_path.pop()
467
583
  return self.__get_net(head_path, self.__get_snl_bitnet)
468
584
 
469
585
  def get_instance(self):
470
- path = get_snl_path_from_id_list(self.pathIDs)
471
- """Return the instance of the term."""
472
- return Instance(path)
586
+ """
587
+ :return: the instance of this Term.
588
+ :rtype: Instance
589
+ """
590
+ return Instance(self.pathIDs)
473
591
 
474
592
  def get_flat_fanout(self):
475
593
  return self.get_equipotential().get_leaf_readers()
@@ -478,30 +596,48 @@ class Term:
478
596
  return Equipotential(self)
479
597
 
480
598
  def is_input(self) -> bool:
481
- """Return True if the term is an input."""
599
+ """
600
+ :return: True if the term is an input.
601
+ :rtype: bool
602
+ """
482
603
  snlterm = get_snl_term_for_ids(self.pathIDs, self.termIDs)
483
604
  return snlterm.getDirection() == snl.SNLTerm.Direction.Input
484
605
 
485
606
  def is_output(self) -> bool:
486
- """Return True if the term is an output."""
607
+ """
608
+ :return: True if the term is an output.
609
+ :rtype: bool
610
+ """
487
611
  snlterm = get_snl_term_for_ids(self.pathIDs, self.termIDs)
488
612
  return snlterm.getDirection() == snl.SNLTerm.Direction.Output
489
613
 
490
614
  def get_bits(self):
491
- path = get_snl_path_from_id_list(self.pathIDs)
615
+ """
616
+ :return: an iterator over the bits of the term.
617
+ If the term is scalar, it will return an iterator over itself.
618
+ :rtype: Iterator[Term]
619
+ """
492
620
  if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
493
621
  for bit in get_snl_term_for_ids(self.pathIDs, self.termIDs).getBits():
494
- yield Term(path, bit)
622
+ yield Term(self.pathIDs, bit)
495
623
  else:
496
624
  yield self
497
625
 
498
626
  def get_bit(self, index: int):
499
- path = get_snl_path_from_id_list(self.pathIDs)
627
+ """
628
+ :param int index: the index of the bit to get.
629
+ :return: the Term bit at the given index or None if it does not exist.
630
+ :rtype: Term or None
631
+ """
500
632
  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))
633
+ return Term(
634
+ self.pathIDs,
635
+ get_snl_term_for_ids(self.pathIDs, self.termIDs).getBit(index),
636
+ )
502
637
  return None
503
638
 
504
639
  def disconnect(self):
640
+ """Disconnect this term from its net."""
505
641
  path = get_snl_path_from_id_list(self.pathIDs)
506
642
  self.__make_unique()
507
643
  inst = path.getTailInstance()
@@ -510,21 +646,27 @@ class Term:
510
646
  iterm.setNet(None)
511
647
 
512
648
  def connect(self, net: Net):
649
+ """Connect this term to the given Net.
650
+
651
+ :param Net net: the Net to connect to.
652
+ """
513
653
  if self.get_width() != net.get_width():
514
654
  raise ValueError("Width mismatch")
515
655
  if self.get_instance().is_top():
516
- for bterm, bnet in zip(get_snl_term_for_ids(self.pathIDs,
517
- self.termIDs).getBits(),
518
- net.net.getBits()):
656
+ for bterm, bnet in zip(
657
+ get_snl_term_for_ids(self.pathIDs, self.termIDs).getBits(),
658
+ net.net.getBits(),
659
+ ):
519
660
  logging.debug(f"Connecting {bterm} to {bnet}")
520
661
  bterm.setNet(bnet)
521
662
  else:
522
663
  self.__make_unique()
523
664
  path = get_snl_path_from_id_list(self.pathIDs)
524
665
  inst = path.getTailInstance()
525
- for bterm, bnet in zip(get_snl_term_for_ids(self.pathIDs,
526
- self.termIDs).getBits(),
527
- net.net.getBits()):
666
+ for bterm, bnet in zip(
667
+ get_snl_term_for_ids(self.pathIDs, self.termIDs).getBits(),
668
+ net.net.getBits(),
669
+ ):
528
670
  iterm = inst.getInstTerm(bterm)
529
671
  iterm.setNet(bnet)
530
672
 
@@ -564,10 +706,13 @@ class Instance:
564
706
  """
565
707
 
566
708
  def __init__(self, path=snl.SNLPath()):
567
- if path.size() > 0:
568
- self.pathIDs = path.getPathIDs()
569
- else:
570
- self.pathIDs = []
709
+ if isinstance(path, snl.SNLPath):
710
+ if path.size() > 0:
711
+ self.pathIDs = path.getPathIDs()
712
+ else:
713
+ self.pathIDs = []
714
+ elif isinstance(path, list):
715
+ self.pathIDs = path.copy()
571
716
 
572
717
  def __eq__(self, other) -> bool:
573
718
  return self.pathIDs == other.pathIDs
@@ -591,6 +736,11 @@ class Instance:
591
736
  return consistent_hash(self.pathIDs)
592
737
 
593
738
  def get_leaf_children(self):
739
+ """Iterate over the leaf children of this Instance.
740
+ Equivalent to the underlying leaves of the instanciation tree.
741
+ :return: an iterator over the leaf children Instance of this Instance.
742
+ :rtype: Iterator[Instance]
743
+ """
594
744
  initial_path = get_snl_path_from_id_list(self.pathIDs)
595
745
  for inst in self.__get_snl_model().getInstances():
596
746
  if inst.getModel().isLeaf():
@@ -608,42 +758,72 @@ class Instance:
608
758
  stack.append([inst_child, path_child])
609
759
 
610
760
  def is_top(self) -> bool:
611
- """Return True if this is the top design."""
761
+ """
762
+ :return: True if this is the top design.
763
+ :rtype: bool
764
+ """
612
765
  return len(self.pathIDs) == 0
613
766
 
614
767
  def is_assign(self) -> bool:
768
+ """Example: (assign a=b) will create an instance of assign connecting
769
+ the wire a to the output of the assign and b to the input.
770
+
771
+ :return: True if this is an assign. Assigns are represented with
772
+ anonymous Assign instances.
773
+ :rtype: bool
774
+ """
615
775
  return self.__get_snl_model().isAssign()
616
776
 
617
777
  def is_blackbox(self) -> bool:
618
- """Return True if this is a blackbox."""
778
+ """
779
+ :return: True if this is a blackbox.
780
+ :rtype: bool
781
+ """
619
782
  return self.__get_snl_model().isBlackBox()
620
783
 
621
784
  def is_leaf(self) -> bool:
622
- """Return True if this is a leaf."""
785
+ """
786
+ :return: True if this is a leaf.
787
+ :rtype: bool
788
+ """
623
789
  return self.__get_snl_model().isLeaf()
624
790
 
625
791
  def is_const0(self) -> bool:
626
- """Return True if this is a constant 0 generator."""
792
+ """
793
+ :return: True if this is a constant 0 generator.
794
+ :rtype: bool
795
+ """
627
796
  return self.__get_snl_model().isConst0()
628
797
 
629
798
  def is_const1(self) -> bool:
630
- """Return True if this is a constant 1 generator."""
799
+ """
800
+ :return: True if this is a constant 1 generator.
801
+ :rtype: bool
802
+ """
631
803
  return self.__get_snl_model().isConst1()
632
804
 
633
805
  def is_const(self) -> bool:
634
- """Return True if this is a constant generator."""
806
+ """
807
+ :return: True if this is a constant generator.
808
+ :rtype: bool
809
+ """
635
810
  return self.__get_snl_model().isConst()
636
811
 
637
812
  def is_buf(self) -> bool:
638
- """Return True if this is a buffer."""
813
+ """
814
+ :return: True if this is a buffer.
815
+ :rtype: bool
816
+ """
639
817
  return self.__get_snl_model().isBuf()
640
818
 
641
819
  def is_inv(self) -> bool:
642
- """Return True if this is an inverter."""
820
+ """
821
+ :return: True if this is an inverter.
822
+ :rtype: bool
823
+ """
643
824
  return self.__get_snl_model().isInv()
644
825
 
645
826
  def __get_snl_model(self):
646
- """Return the model of the instance."""
647
827
  if self.is_top():
648
828
  return snl.SNLUniverse.get().getTopDesign()
649
829
  instance = get_snl_instance_from_id_list(self.pathIDs)
@@ -658,20 +838,43 @@ class Instance:
658
838
  return found_model
659
839
  return None
660
840
 
841
+ def dump_full_dot(self, path: str):
842
+ """Dump the full dot file of this instance."""
843
+ self.__get_snl_model().dumpFullDotFile(path)
844
+
845
+ def dump_context_dot(self, path: str):
846
+ self.__get_snl_model().dumpContextDotFile(path)
847
+
661
848
  def get_child_instance(self, name: str):
849
+ """
850
+ :param str name: the name of the child Instance to get.
851
+ :return: the child Instance with the given name or None if it does not exist.
852
+ :rtype: Instance or None
853
+ """
662
854
  childInst = self.__get_snl_model().getInstance(name)
663
855
  if childInst is None:
664
856
  return None
665
- path = get_snl_path_from_id_list(self.pathIDs)
666
- return Instance(snl.SNLPath(path, childInst))
857
+ path = self.pathIDs.copy()
858
+ path.append(childInst.getID())
859
+ return Instance(path)
667
860
 
668
861
  def get_child_instances(self):
862
+ """Iterate over the child instances of this instance.
863
+ Equivalent to go down one level in hierarchy.
864
+
865
+ :return: an iterator over the child instances of this instance.
866
+ :rtype: Iterator[Instance]
867
+ """
669
868
  for inst in self.__get_snl_model().getInstances():
670
- path_init = get_snl_path_from_id_list(self.pathIDs)
671
- path = snl.SNLPath(path_init, inst)
869
+ path = self.pathIDs.copy()
870
+ path.append(inst.getID())
672
871
  yield Instance(path)
673
872
 
674
873
  def get_number_of_child_instances(self) -> int:
874
+ """
875
+ :return: the number of child instances of this instance.
876
+ :rtype: int
877
+ """
675
878
  return sum(1 for _ in self.__get_snl_model().getInstances())
676
879
 
677
880
  # def get_flat_primitive_instances(self):
@@ -691,85 +894,130 @@ class Instance:
691
894
  # stack.append([inst_child, path_child])
692
895
 
693
896
  def get_nets(self):
694
- path = get_snl_path_from_id_list(self.pathIDs)
897
+ """Iterate over all scalar nets and bus nets.
898
+
899
+ :return: an iterator over the nets of this Instance.
900
+ :rtype: Iterator[Net]
901
+ """
695
902
  for net in self.__get_snl_model().getNets():
696
- yield Net(path, net)
903
+ yield Net(self.pathIDs, net)
697
904
 
698
905
  def get_flat_nets(self):
699
- path = get_snl_path_from_id_list(self.pathIDs)
906
+ """Iterate over all scalar nets and bus net bits.
907
+
908
+ :return: an iterator over the flat nets of this Instance.
909
+ :rtype: Iterator[Net]
910
+ """
700
911
  for net in self.__get_snl_model().getNets():
701
912
  if isinstance(net, snl.SNLBusNet):
702
913
  for bit in net.getBits():
703
- yield Net(path, bit)
914
+ yield Net(self.pathIDs, bit)
704
915
  else:
705
- yield Net(path, net)
916
+ yield Net(self.pathIDs, net)
706
917
 
707
918
  def get_net(self, name: str) -> Net:
708
- path = get_snl_path_from_id_list(self.pathIDs)
919
+ """
920
+ :param str name: the name of the Net to get.
921
+ :return: the Net with the given name or None if it does not exist.
922
+ :rtype: Net or None
923
+ """
709
924
  net = self.__get_snl_model().getNet(name)
710
925
  if net is not None:
711
- return Net(path, net)
926
+ return Net(self.pathIDs, net)
712
927
  return None
713
928
 
714
929
  def is_primitive(self) -> bool:
715
- """Return True if this is a primitive."""
930
+ """
931
+ :return: True if this is a primitive.
932
+ :rtype: bool
933
+ """
716
934
  return self.__get_snl_model().isPrimitive()
717
935
 
718
936
  def get_terms(self):
719
- path = get_snl_path_from_id_list(self.pathIDs)
937
+ """Iterate over all scalar terms and bus terms of this Instance.
938
+
939
+ :return: the terms of this Instance.
940
+ :rtype: Iterator[Term]
941
+ """
720
942
  for term in self.__get_snl_model().getTerms():
721
- yield Term(path, term)
943
+ yield Term(self.pathIDs, term)
722
944
 
723
945
  def get_flat_terms(self):
724
- path = get_snl_path_from_id_list(self.pathIDs)
946
+ """Iterate over all scalar terms and bus term bits.
947
+
948
+ :return: the flat terms of this Instance.
949
+ :rtype: Iterator[Term]
950
+ """
725
951
  for term in self.__get_snl_model().getBitTerms():
726
- yield Term(path, term)
952
+ yield Term(self.pathIDs, term)
727
953
 
728
954
  def get_term(self, name: str) -> Term:
729
- path = get_snl_path_from_id_list(self.pathIDs)
955
+ """
956
+ :param str name: the name of the Term to get.
957
+ :return: the Term with the given name.
958
+ :rtype: Term or None
959
+ """
730
960
  term = self.__get_snl_model().getTerm(name)
731
961
  if term is not None:
732
- return Term(path, self.__get_snl_model().getTerm(name))
962
+ return Term(self.pathIDs, self.__get_snl_model().getTerm(name))
733
963
  return None
734
964
 
735
965
  def get_input_terms(self):
736
- path = get_snl_path_from_id_list(self.pathIDs)
966
+ """Iterate over all scalar input terms and bus input terms
967
+ of this Instance.
968
+
969
+ :return: the input terms of this Instance.
970
+ :rtype: Iterator[Term]
971
+ """
737
972
  for term in self.__get_snl_model().getTerms():
738
973
  if term.getDirection() != snl.SNLTerm.Direction.Output:
739
- yield Term(path, term)
974
+ yield Term(self.pathIDs, term)
740
975
 
741
976
  def get_flat_input_terms(self):
742
- path = get_snl_path_from_id_list(self.pathIDs)
977
+ """Iterate over all scalar input terms and bus input term bits
978
+ of this Instance.
979
+
980
+ :return: the flat input terms of this Instance.
981
+ :rtype: Iterator[Term]
982
+ """
743
983
  for term in self.__get_snl_model().getTerms():
744
984
  if term.getDirection() != snl.SNLTerm.Direction.Output:
745
985
  if isinstance(term, snl.SNLBusTerm):
746
986
  for bit in term.getBits():
747
- yield Term(path, bit)
987
+ yield Term(self.pathIDs, bit)
748
988
  else:
749
- yield Term(path, term)
989
+ yield Term(self.pathIDs, term)
750
990
 
751
991
  def get_output_terms(self):
752
- path = get_snl_path_from_id_list(self.pathIDs)
992
+ """Iterate over all scalar output terms and bus output terms
993
+ of this Instance.
994
+
995
+ :return: the output terms of this Instance.
996
+ :rtype: Iterator[Term]
997
+ """
753
998
  for term in self.__get_snl_model().getTerms():
754
999
  if term.getDirection() != snl.SNLTerm.Direction.Input:
755
- yield Term(path, term)
1000
+ yield Term(self.pathIDs, term)
756
1001
 
757
1002
  def get_flat_output_terms(self):
758
- path = get_snl_path_from_id_list(self.pathIDs)
1003
+ """Return the flat output terms of the instance.
1004
+ This will iterate over all scalar output terms and bus output term bits.
1005
+ """
759
1006
  for term in self.__get_snl_model().getTerms():
760
1007
  if term.getDirection() != snl.SNLTerm.Direction.Input:
761
1008
  if isinstance(term, snl.SNLBusTerm):
762
1009
  for bit in term.getBits():
763
- yield Term(path, bit)
1010
+ yield Term(self.pathIDs, bit)
764
1011
  else:
765
- yield Term(path, term)
1012
+ yield Term(self.pathIDs, term)
766
1013
 
767
1014
  def delete_instance(self, name: str):
768
- init_path = get_snl_path_from_id_list(self.pathIDs)
1015
+ """Delete the child instance with the given name."""
769
1016
  if name == "":
770
1017
  raise ValueError(
771
1018
  "Cannot delete instance with empty name. Try delete_instance_by_id instead."
772
1019
  )
1020
+ init_path = get_snl_path_from_id_list(self.pathIDs)
773
1021
  path = snl.SNLPath(init_path, self.__get_snl_model().getInstance(name))
774
1022
  snl.SNLUniquifier(path)
775
1023
  if init_path.size() > 0:
@@ -777,6 +1025,10 @@ class Instance:
777
1025
  self.__get_snl_model().getInstance(name).destroy()
778
1026
 
779
1027
  def delete_instance_by_id(self, id: str):
1028
+ """Delete the child instance with the given ID.
1029
+
1030
+ :param str id: the ID of the Instance to delete.
1031
+ """
780
1032
  init_path = get_snl_path_from_id_list(self.pathIDs)
781
1033
  path = snl.SNLPath(init_path, self.__get_snl_model().getInstanceByID(id))
782
1034
  snl.SNLUniquifier(path)
@@ -784,33 +1036,57 @@ class Instance:
784
1036
  self.__get_snl_model().getInstanceByID(id).destroy()
785
1037
 
786
1038
  def get_design(self):
787
- path = get_snl_path_from_id_list(self.pathIDs)
1039
+ """
1040
+ :return: the Instance containing this instance.
1041
+ :rtype: Instance
1042
+ """
1043
+ path = self.pathIDs.copy()
788
1044
  if len(self.pathIDs) == 1:
789
1045
  return get_top()
790
- return Instance(path.getHeadPath())
1046
+ path.pop()
1047
+ return Instance(path)
791
1048
 
792
1049
  def delete(self):
1050
+ """Delete this instance."""
793
1051
  path = get_snl_path_from_id_list(self.pathIDs)
794
1052
  snl.SNLUniquifier(path)
795
1053
  self.get_design().delete_instance_by_id(path.getTailInstance().getID())
796
1054
 
797
1055
  def get_name(self) -> str:
1056
+ """
1057
+ :return: the name of the instance or name of the top is this is the top.
1058
+ :rtype: str
1059
+ """
798
1060
  path = get_snl_path_from_id_list(self.pathIDs)
799
- """Return the name of the instance or name of the top is this is the top."""
800
1061
  if self.is_top():
801
1062
  return self.get_model_name()
802
1063
  else:
803
1064
  return path.getTailInstance().getName()
804
1065
 
805
1066
  def get_model_name(self) -> str:
806
- """Return the name of the model of the instance or name of the top is this is the top."""
1067
+ """
1068
+ :return: the name of the model of the instance
1069
+ or name of the top is this is the top.
1070
+ :rtype: str
1071
+ """
807
1072
  return self.__get_snl_model().getName()
808
1073
 
809
1074
  def get_model_id(self) -> tuple[int, int, int]:
1075
+ """
1076
+ :return: the ID of the model of this Instance
1077
+ or ID of the top if this is the top.
1078
+ """
810
1079
  model = self.__get_snl_model()
811
1080
  return model.getDB().getID(), model.getLibrary().getID(), model.getID()
812
1081
 
813
1082
  def create_child_instance(self, model: str, name: str):
1083
+ """Create a child instance with the given model and name.
1084
+
1085
+ :param str model: the name of the model of the instance to create.
1086
+ :param str name: the name of the instance to create.
1087
+ :return: the created Instance.
1088
+ :rtype: Instance
1089
+ """
814
1090
  path = get_snl_path_from_id_list(self.pathIDs)
815
1091
  if path.size() > 0:
816
1092
  snl.SNLUniquifier(path)
@@ -826,6 +1102,12 @@ class Instance:
826
1102
  return Instance(path)
827
1103
 
828
1104
  def create_term(self, name: str, direction: snl.SNLTerm.Direction) -> Term:
1105
+ """Create a Term in this Instance with the given name and direction.
1106
+
1107
+ :param str name: the name of the Term to create.
1108
+ :param snl.SNLTerm.Direction direction: the direction of the Term to create.
1109
+ :return: the created Term.
1110
+ """
829
1111
  path = get_snl_path_from_id_list(self.pathIDs)
830
1112
  if path.size() > 0:
831
1113
  snl.SNLUniquifier(path)
@@ -835,15 +1117,40 @@ class Instance:
835
1117
  return Term(path, newSNLTerm)
836
1118
 
837
1119
  def create_output_term(self, name: str) -> Term:
1120
+ """Create an output Term in this Instance with the given name.
1121
+
1122
+ :param str name: the name of the Term to create.
1123
+ :return: the created Term.
1124
+ :rtype: Term
1125
+ """
838
1126
  return self.create_term(name, snl.SNLTerm.Direction.Output)
839
1127
 
840
1128
  def create_input_term(self, name: str) -> Term:
1129
+ """Create an input Term in this Instance with the given name.
1130
+
1131
+ :param str name: the name of the Term to create.
1132
+ :return: the created Term.
1133
+ :rtype: Term
1134
+ """
841
1135
  return self.create_term(name, snl.SNLTerm.Direction.Input)
842
1136
 
843
1137
  def create_inout_term(self, name: str) -> Term:
1138
+ """Create an inout Term in this Instance with the given name.
1139
+
1140
+ :param str name: the name of the Term to create.
1141
+ :return: the created Term.
1142
+ :rtype: Term
1143
+ """
844
1144
  return self.create_term(name, snl.SNLTerm.Direction.InOut)
845
1145
 
846
1146
  def create_bus_term(self, name: str, msb: int, lsb: int, direction) -> Term:
1147
+ """Create a bus Term in this Instance with the given name, msb, lsb and direction.
1148
+ :param str name: the name of the Term to create.
1149
+ :param int msb: the most significant bit of the Term to create.
1150
+ :param int lsb: the least significant bit of the Term to create.
1151
+ :param snl.SNLTerm.Direction direction: the direction of the Term to create.
1152
+ :return: the created Term.
1153
+ """
847
1154
  path = get_snl_path_from_id_list(self.pathIDs)
848
1155
  if path.size() > 0:
849
1156
  snl.SNLUniquifier(path)
@@ -853,15 +1160,45 @@ class Instance:
853
1160
  return Term(path, newSNLTerm)
854
1161
 
855
1162
  def create_inout_bus_term(self, name: str, msb: int, lsb: int) -> Term:
1163
+ """Create an inout bus Term in this Instance with the given name, msb and lsb.
1164
+
1165
+ :param str name: the name of the Term to create.
1166
+ :param int msb: the most significant bit of the Term to create.
1167
+ :param int lsb: the least significant bit of the Term to create.
1168
+ :return: the created Term.
1169
+ :rtype: Term
1170
+ """
856
1171
  return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.InOut)
857
1172
 
858
1173
  def create_output_bus_term(self, name: str, msb: int, lsb: int) -> Term:
1174
+ """Create an output bus Term in this Instance with the given name, msb and lsb.
1175
+
1176
+ :param str name: the name of the Term to create.
1177
+ :param int msb: the most significant bit of the Term to create.
1178
+ :param int lsb: the least significant bit of the Term to create.
1179
+ :return: the created Term.
1180
+ :rtype: Term
1181
+ """
859
1182
  return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.Output)
860
1183
 
861
1184
  def create_input_bus_term(self, name: str, msb: int, lsb: int) -> Term:
1185
+ """Create an input bus Term in this Instance with the given name, msb and lsb.
1186
+
1187
+ :param str name: the name of the Term to create.
1188
+ :param int msb: the most significant bit of the Term to create.
1189
+ :param int lsb: the least significant bit of the Term to create.
1190
+ :return: the created Term.
1191
+ :rtype: Term
1192
+ """
862
1193
  return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.Input)
863
1194
 
864
1195
  def create_net(self, name: str) -> Net:
1196
+ """Create a scalar Net in this Instance with the given name.
1197
+
1198
+ :param str name: the name of the Net to create.
1199
+ :return: the created Net.
1200
+ :rtype: Net
1201
+ """
865
1202
  path = get_snl_path_from_id_list(self.pathIDs)
866
1203
  if path.size() > 0:
867
1204
  snl.SNLUniquifier(path)
@@ -871,6 +1208,14 @@ class Instance:
871
1208
  return Net(path, newSNLNet)
872
1209
 
873
1210
  def create_bus_net(self, name: str, msb: int, lsb: int) -> Net:
1211
+ """Create a bus Net in this Instance with the given name, msb and lsb.
1212
+
1213
+ :param str name: the name of the Net to create.
1214
+ :param int msb: the most significant bit of the Net to create.
1215
+ :param int lsb: the least significant bit of the Net to create.
1216
+ :return: the created Net.
1217
+ :rtype: Net
1218
+ """
874
1219
  path = get_snl_path_from_id_list(self.pathIDs)
875
1220
  if path.size() > 0:
876
1221
  snl.SNLUniquifier(path)
@@ -880,6 +1225,11 @@ class Instance:
880
1225
  return Net(path, newSNLNet)
881
1226
 
882
1227
  def dump_verilog(self, path: str, name: str):
1228
+ """Dump the verilog of this instance.
1229
+
1230
+ :param str path: the path where to dump the verilog.
1231
+ :param str name: the name of the verilog file.
1232
+ """
883
1233
  self.__get_snl_model().dumpVerilog(path, name)
884
1234
 
885
1235
 
@@ -893,10 +1243,20 @@ def get_top_db() -> snl.SNLDB:
893
1243
 
894
1244
 
895
1245
  def get_top():
1246
+ """
1247
+ :return: the top Instance.
1248
+ :rtype: Instance
1249
+ """
896
1250
  return Instance(snl.SNLPath())
897
1251
 
898
1252
 
899
1253
  def create_top(name: str) -> Instance:
1254
+ """Create a top instance with the given name.
1255
+
1256
+ :param str name: the name of the top instance to create.
1257
+ :return: the created top Instance.
1258
+ :rtype: Instance
1259
+ """
900
1260
  # init
901
1261
  db = get_top_db()
902
1262
  # create top design
@@ -916,11 +1276,15 @@ def load_verilog(files: list):
916
1276
 
917
1277
 
918
1278
  def load_liberty(files: list):
919
- logging.info(f"Loading liberty: {', '.join(files)}")
1279
+ logging.info(f"Loading liberty files: {', '.join(files)}")
920
1280
  get_top_db().loadLibertyPrimitives(files)
921
1281
 
922
1282
 
923
1283
  def load_primitives(name: str):
1284
+ """Loads a primitive library embedded in najaeda.
1285
+ Currently supported libraries are:
1286
+ - xilinx
1287
+ """
924
1288
  if name == "xilinx":
925
1289
  logging.info("Loading xilinx primitives")
926
1290
  from najaeda.primitives import xilinx
@@ -938,7 +1302,11 @@ def get_primitives_library() -> snl.SNLLibrary:
938
1302
 
939
1303
 
940
1304
  def get_model_name(id: tuple[int, int, int]) -> str:
941
- """Return the name of the model given its id."""
1305
+ """
1306
+ :param tuple[int, int, int] id: the id of the model.
1307
+ :return: the name of the model given its id or None if it does not exist.
1308
+ :rtype: str or None
1309
+ """
942
1310
  u = snl.SNLUniverse.get()
943
1311
  if u:
944
1312
  db = u.getDB(id[0])