najaeda 0.1.8__cp313-cp313t-macosx_11_0_arm64.whl → 0.1.11__cp313-cp313t-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,9 +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
11
+ from enum import Enum
12
+
13
+ from najaeda import snl
13
14
 
14
15
 
15
16
  def consistent_hash(obj):
@@ -23,15 +24,16 @@ def consistent_hash(obj):
23
24
 
24
25
  def hash_value(value):
25
26
  if isinstance(value, int):
26
- return struct.pack('!q', value)
27
+ return struct.pack("!q", value)
27
28
  else:
28
29
  raise TypeError(f"Unsupported type: {type(value)}")
29
30
 
30
31
  def hash_object(o):
31
32
  if isinstance(o, (list, tuple)):
32
- return b''.join(hash_object(i) for i in o)
33
+ return b"".join(hash_object(i) for i in o)
33
34
  else:
34
35
  return hash_value(o)
36
+
35
37
  serialized_obj = default_serializer(obj)
36
38
  obj_bytes = hash_object(serialized_obj)
37
39
  return int(hashlib.sha256(obj_bytes).hexdigest(), 16)
@@ -88,8 +90,7 @@ class Equipotential:
88
90
  inst_term = term
89
91
  path = get_snl_path_from_id_list(inst_term.pathIDs)
90
92
  ito = snl.SNLNetComponentOccurrence(
91
- path.getHeadPath(),
92
- path.getTailInstance().getInstTerm(snl_term)
93
+ path.getHeadPath(), path.getTailInstance().getInstTerm(snl_term)
93
94
  )
94
95
  self.equi = snl.SNLEquipotential(ito)
95
96
 
@@ -97,9 +98,15 @@ class Equipotential:
97
98
  return self.equi == value.equi
98
99
 
99
100
  def dump_dot(self, path: str):
101
+ """Dump the dot file of this equipotential."""
100
102
  self.equi.dumpDotFile(path)
101
103
 
102
104
  def get_inst_terms(self):
105
+ """Iterate over the instance terminals of this equipotential.
106
+
107
+ :return: an iterator over the instance terminals of this equipotential.
108
+ :rtype: Iterator[Term]
109
+ """
103
110
  if self.equi is not None:
104
111
  for term in self.equi.getInstTermOccurrences():
105
112
  yield Term(
@@ -108,6 +115,11 @@ class Equipotential:
108
115
  )
109
116
 
110
117
  def get_top_terms(self):
118
+ """Iterate over the top terminals of this equipotential.
119
+
120
+ :return: an iterator over the top terminals of this equipotential.
121
+ :rtype: Iterator[Term]
122
+ """
111
123
  if self.equi is not None:
112
124
  for term in self.equi.getTerms():
113
125
  yield Term([], term)
@@ -119,7 +131,9 @@ class Equipotential:
119
131
  if direction != snl.SNLTerm.Direction.Output:
120
132
  if term.getInstTerm().getInstance().getModel().isLeaf():
121
133
  yield Term(
122
- snl.SNLPath(term.getPath(), term.getInstTerm().getInstance()),
134
+ snl.SNLPath(
135
+ term.getPath(), term.getInstTerm().getInstance()
136
+ ),
123
137
  term.getInstTerm().getBitTerm(),
124
138
  )
125
139
 
@@ -130,7 +144,9 @@ class Equipotential:
130
144
  if direction != snl.SNLTerm.Direction.Input:
131
145
  if term.getInstTerm().getInstance().getModel().isLeaf():
132
146
  yield Term(
133
- snl.SNLPath(term.getPath(), term.getInstTerm().getInstance()),
147
+ snl.SNLPath(
148
+ term.getPath(), term.getInstTerm().getInstance()
149
+ ),
134
150
  term.getInstTerm().getBitTerm(),
135
151
  )
136
152
 
@@ -150,6 +166,13 @@ class Equipotential:
150
166
 
151
167
 
152
168
  class Net:
169
+ class Type(Enum):
170
+ STANDARD = snl.SNLNet.Type.Standard
171
+ ASSIGN0 = snl.SNLNet.Type.Assign0
172
+ ASSIGN1 = snl.SNLNet.Type.Assign1
173
+ SUPPLY0 = snl.SNLNet.Type.Supply0
174
+ SUPPLY1 = snl.SNLNet.Type.Supply1
175
+
153
176
  def __init__(self, path, net=None, net_concat=None):
154
177
  if net is not None and net_concat is not None:
155
178
  raise ValueError(
@@ -189,59 +212,105 @@ class Net:
189
212
  return net_str
190
213
 
191
214
  def get_name(self) -> str:
192
- """Return the name of the net."""
215
+ """
216
+ :return: the name of this Net.
217
+ :rtype: str
218
+ """
193
219
  if hasattr(self, "net"):
194
220
  return self.net.getName()
195
221
  return "{" + ",".join(map(str, self.net_concat)) + "}"
196
222
 
197
223
  def get_msb(self) -> int:
198
- """Return the most significant bit of the net if it is a bus."""
224
+ """
225
+ :return: the most significant bit of the net if it is a bus.
226
+ :rtype: int
227
+ """
199
228
  if hasattr(self, "net") and isinstance(self.net, snl.SNLBusNet):
200
229
  return self.net.getMSB()
201
230
  return None
202
231
 
203
232
  def get_lsb(self) -> int:
204
- """Return the least significant bit of the net if it is a bus."""
233
+ """
234
+ :return: the least significant bit of the net if it is a bus.
235
+ :rtype: int
236
+ """
205
237
  if hasattr(self, "net") and isinstance(self.net, snl.SNLBusNet):
206
238
  return self.net.getLSB()
207
239
  return None
208
240
 
209
241
  def is_bus(self) -> bool:
210
- """Return True if the net is a bus."""
242
+ """
243
+ :return: True if the net is a bus.
244
+ :rtype: bool
245
+ """
211
246
  return hasattr(self, "net") and isinstance(self.net, snl.SNLBusNet)
212
247
 
213
248
  def is_bus_bit(self) -> bool:
214
- """Return True if the net is a bit of a bus."""
249
+ """
250
+ :return: True if the net is a bit of a bus.
251
+ :rtype: bool
252
+ """
215
253
  return hasattr(self, "net") and isinstance(self.net, snl.SNLBusNetBit)
216
254
 
217
255
  def is_scalar(self) -> bool:
218
- """Return True if the net is a scalar."""
256
+ """
257
+ :return: True if the net is a scalar.
258
+ :rtype: bool
259
+ """
219
260
  return hasattr(self, "net") and isinstance(self.net, snl.SNLScalarNet)
220
261
 
221
262
  def is_bit(self) -> bool:
222
- """Return True if the net is a bit."""
263
+ """
264
+ :return: True if the net is a bit.
265
+ :rtype: bool
266
+ """
223
267
  return self.is_scalar() or self.is_bus_bit()
224
268
 
225
269
  def is_concat(self) -> bool:
226
- """Return True if the net is a concatenation."""
270
+ """
271
+ :return: True if the net is a concatenation.
272
+ :rtype: bool
273
+ """
227
274
  return hasattr(self, "net_concat")
228
275
 
229
276
  def is_const(self) -> bool:
230
- """Return True if the net is a constant generator."""
277
+ """
278
+ :return: True if the net is a constant generator.
279
+ :rtype: bool
280
+ """
231
281
  if hasattr(self, "net"):
232
282
  return self.net.isConstant()
233
- for net in self.net_concat:
234
- if not net.isConstant():
235
- return False
236
- return True
283
+ else:
284
+ for net in self.net_concat:
285
+ if not net.isConstant():
286
+ return False
287
+ return True
288
+
289
+ def set_type(self, net_type: Type):
290
+ """
291
+ :param Type net_type: the type of the net.
292
+ """
293
+ if hasattr(self, "net"):
294
+ self.net.setType(net_type.value)
295
+ else:
296
+ for net in self.net_concat:
297
+ net.setType(net_type.value)
237
298
 
238
299
  def get_width(self) -> int:
239
- """Return the width of the net."""
300
+ """
301
+ :return: the width of the net.
302
+ :rtype: int
303
+ """
240
304
  if hasattr(self, "net"):
241
305
  return self.net.getWidth()
242
306
  return sum(1 for _ in self.net_concat)
243
307
 
244
308
  def get_bits(self):
309
+ """Iterate over the bits of this Net.
310
+ The iterator will return itself if the Net is scalar.
311
+ :return: an iterator over the bits of this Net.
312
+ :rtype: Iterator[Net]
313
+ """
245
314
  if hasattr(self, "net"):
246
315
  if isinstance(self.net, snl.SNLBusNet):
247
316
  for bit in self.net.getBits():
@@ -250,9 +319,14 @@ class Net:
250
319
  yield self
251
320
  else:
252
321
  for net in self.net_concat:
253
- yield net
322
+ yield Net(net)
254
323
 
255
324
  def get_bit(self, index: int):
325
+ """
326
+ :param int index: the index of the bit to get.
327
+ :return: the Net bit at the given index or None if it does not exist.
328
+ :rtype: Net
329
+ """
256
330
  if hasattr(self, "net"):
257
331
  if isinstance(self.net, snl.SNLBusNet):
258
332
  return Net(self.pathIDs, self.net.getBit(index))
@@ -263,6 +337,10 @@ class Net:
263
337
  return None
264
338
 
265
339
  def get_inst_terms(self):
340
+ """
341
+ :return: an iterator over the instance terminals of the net.
342
+ :rtype: Iterator[Term]
343
+ """
266
344
  if hasattr(self, "net_concat"):
267
345
  raise ValueError("Cannot get inst terms from a net_concat")
268
346
  for term in self.net.getInstTerms():
@@ -271,12 +349,20 @@ class Net:
271
349
  yield Term(path, term.getBitTerm())
272
350
 
273
351
  def get_design_terms(self):
352
+ """
353
+ :return: an iterator over the design terminals of the net.
354
+ :rtype: Iterator[Term]
355
+ """
274
356
  if hasattr(self, "net_concat"):
275
357
  raise ValueError("Cannot get terms from a net_concat")
276
358
  for term in self.net.getBitTerms():
277
359
  yield Term(self.pathIDs, term)
278
360
 
279
361
  def get_terms(self):
362
+ """
363
+ :return: an iterator over the terminals of the net.
364
+ :rtype: Iterator[Term]
365
+ """
280
366
  for term in itertools.chain(self.get_design_terms(), self.get_inst_terms()):
281
367
  yield term
282
368
 
@@ -352,7 +438,9 @@ class Term:
352
438
  if path.size() == 0:
353
439
  return get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()
354
440
  else:
355
- return f"{path}/{get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()}"
441
+ return (
442
+ f"{path}/{get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()}"
443
+ )
356
444
 
357
445
  def __repr__(self) -> str:
358
446
  path = get_snl_path_from_id_list(self.pathIDs)
@@ -365,43 +453,76 @@ class Term:
365
453
  snl.SNLUniquifier(path)
366
454
 
367
455
  def is_bus(self) -> bool:
368
- """Return True if the term is a bus."""
369
- return isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm)
456
+ """
457
+ :return: True if the term is a bus.
458
+ :rtype: bool
459
+ """
460
+ return isinstance(
461
+ get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm
462
+ )
370
463
 
371
464
  def is_bus_bit(self) -> bool:
372
- """Return True if the term is a bit of a bus."""
373
- return isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTermBit)
465
+ """
466
+ :return: True if the term is a bit of a bus.
467
+ :rtype: bool
468
+ """
469
+ return isinstance(
470
+ get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTermBit
471
+ )
374
472
 
375
473
  def is_scalar(self) -> bool:
376
- """Return True if the term is a scalar."""
377
- return isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLScalarTerm)
474
+ """
475
+ :return: True if the term is a scalar.
476
+ :rtype: bool
477
+ """
478
+ return isinstance(
479
+ get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLScalarTerm
480
+ )
378
481
 
379
482
  def is_bit(self) -> bool:
380
- """Return True if the term is a bit."""
483
+ """
484
+ :return: True if the term is a bit.
485
+ :rtype: bool
486
+ """
381
487
  return self.is_scalar() or self.is_bus_bit()
382
488
 
383
489
  def get_msb(self) -> int:
384
- """Return the most significant bit of the term if it is a bus."""
490
+ """
491
+ :return: the most significant bit of the term if it is a bus.
492
+ :rtype: int or None
493
+ """
385
494
  if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
386
495
  return get_snl_term_for_ids(self.pathIDs, self.termIDs).getMSB()
387
496
  return None
388
497
 
389
498
  def get_lsb(self) -> int:
390
- """Return the least significant bit of the term if it is a bus."""
499
+ """
500
+ :return: the least significant bit of the term if it is a bus.
501
+ :rtype: int or None
502
+ """
391
503
  if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
392
504
  return get_snl_term_for_ids(self.pathIDs, self.termIDs).getLSB()
393
505
  return None
394
506
 
395
507
  def get_width(self) -> int:
396
- """Return the width of the term. 1 if scalar."""
508
+ """
509
+ :return: the width of the term. 1 if scalar.
510
+ :rtype: int
511
+ """
397
512
  return get_snl_term_for_ids(self.pathIDs, self.termIDs).getWidth()
398
513
 
399
514
  def get_name(self) -> str:
400
- """Return the name of the term."""
515
+ """
516
+ :return: the name of the term.
517
+ :rtype: str
518
+ """
401
519
  return get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()
402
520
 
403
521
  def get_direction(self) -> snl.SNLTerm.Direction:
404
- """Return the direction of the term."""
522
+ """
523
+ :return: the direction of the term.
524
+ :rtype: snl.SNLTerm.Direction
525
+ """
405
526
  snlterm = get_snl_term_for_ids(self.pathIDs, self.termIDs)
406
527
  if snlterm.getDirection() == snl.SNLTerm.Direction.Input:
407
528
  return Term.INPUT
@@ -454,17 +575,25 @@ class Term:
454
575
  if all(element is not None for element in snl_nets):
455
576
  return Net(path, net_concat=snl_nets)
456
577
  else:
457
- snl_net = snl_term_net_accessor(get_snl_term_for_ids(self.pathIDs, self.termIDs))
578
+ snl_net = snl_term_net_accessor(
579
+ get_snl_term_for_ids(self.pathIDs, self.termIDs)
580
+ )
458
581
  if snl_net is not None:
459
582
  return Net(path, snl_net)
460
583
  return None
461
584
 
462
585
  def get_lower_net(self) -> Net:
463
- """Return the lower net of the term."""
586
+ """
587
+ :return: the lower net of the term.
588
+ :rtype: Net
589
+ """
464
590
  return self.__get_net(self.pathIDs, self.__get_snl_lower_bitnet)
465
591
 
466
592
  def get_net(self) -> Net:
467
- """Return the net of the term."""
593
+ """
594
+ :return: the net of the term.
595
+ :rtype: Net
596
+ """
468
597
  head_path = self.pathIDs.copy()
469
598
  if len(head_path) == 0:
470
599
  return None
@@ -473,7 +602,10 @@ class Term:
473
602
  return self.__get_net(head_path, self.__get_snl_bitnet)
474
603
 
475
604
  def get_instance(self):
476
- """Return the instance of the term."""
605
+ """
606
+ :return: the instance of this Term.
607
+ :rtype: Instance
608
+ """
477
609
  return Instance(self.pathIDs)
478
610
 
479
611
  def get_flat_fanout(self):
@@ -483,16 +615,27 @@ class Term:
483
615
  return Equipotential(self)
484
616
 
485
617
  def is_input(self) -> bool:
486
- """Return True if the term is an input."""
618
+ """
619
+ :return: True if the term is an input.
620
+ :rtype: bool
621
+ """
487
622
  snlterm = get_snl_term_for_ids(self.pathIDs, self.termIDs)
488
623
  return snlterm.getDirection() == snl.SNLTerm.Direction.Input
489
624
 
490
625
  def is_output(self) -> bool:
491
- """Return True if the term is an output."""
626
+ """
627
+ :return: True if the term is an output.
628
+ :rtype: bool
629
+ """
492
630
  snlterm = get_snl_term_for_ids(self.pathIDs, self.termIDs)
493
631
  return snlterm.getDirection() == snl.SNLTerm.Direction.Output
494
632
 
495
633
  def get_bits(self):
634
+ """
635
+ :return: an iterator over the bits of the term.
636
+ If the term is scalar, it will return an iterator over itself.
637
+ :rtype: Iterator[Term]
638
+ """
496
639
  if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
497
640
  for bit in get_snl_term_for_ids(self.pathIDs, self.termIDs).getBits():
498
641
  yield Term(self.pathIDs, bit)
@@ -500,12 +643,20 @@ class Term:
500
643
  yield self
501
644
 
502
645
  def get_bit(self, index: int):
646
+ """
647
+ :param int index: the index of the bit to get.
648
+ :return: the Term bit at the given index or None if it does not exist.
649
+ :rtype: Term or None
650
+ """
503
651
  if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
504
- return Term(self.pathIDs, get_snl_term_for_ids(
505
- self.pathIDs, self.termIDs).getBit(index))
652
+ return Term(
653
+ self.pathIDs,
654
+ get_snl_term_for_ids(self.pathIDs, self.termIDs).getBit(index),
655
+ )
506
656
  return None
507
657
 
508
658
  def disconnect(self):
659
+ """Disconnect this term from its net."""
509
660
  path = get_snl_path_from_id_list(self.pathIDs)
510
661
  self.__make_unique()
511
662
  inst = path.getTailInstance()
@@ -514,21 +665,27 @@ class Term:
514
665
  iterm.setNet(None)
515
666
 
516
667
  def connect(self, net: Net):
668
+ """Connect this term to the given Net.
669
+
670
+ :param Net net: the Net to connect to.
671
+ """
517
672
  if self.get_width() != net.get_width():
518
673
  raise ValueError("Width mismatch")
519
674
  if self.get_instance().is_top():
520
- for bterm, bnet in zip(get_snl_term_for_ids(self.pathIDs,
521
- self.termIDs).getBits(),
522
- net.net.getBits()):
675
+ for bterm, bnet in zip(
676
+ get_snl_term_for_ids(self.pathIDs, self.termIDs).getBits(),
677
+ net.net.getBits(),
678
+ ):
523
679
  logging.debug(f"Connecting {bterm} to {bnet}")
524
680
  bterm.setNet(bnet)
525
681
  else:
526
682
  self.__make_unique()
527
683
  path = get_snl_path_from_id_list(self.pathIDs)
528
684
  inst = path.getTailInstance()
529
- for bterm, bnet in zip(get_snl_term_for_ids(self.pathIDs,
530
- self.termIDs).getBits(),
531
- net.net.getBits()):
685
+ for bterm, bnet in zip(
686
+ get_snl_term_for_ids(self.pathIDs, self.termIDs).getBits(),
687
+ net.net.getBits(),
688
+ ):
532
689
  iterm = inst.getInstTerm(bterm)
533
690
  iterm.setNet(bnet)
534
691
 
@@ -547,19 +704,36 @@ def get_instance_by_path(names: list):
547
704
  return Instance(path)
548
705
 
549
706
 
550
- def refresh_path(path: snl.SNLPath):
551
- pathlist = path.getPathIDs()
552
- assert len(pathlist) > 0
553
- path = snl.SNLPath()
554
- instance = None
555
- top = snl.SNLUniverse.get().getTopDesign()
556
- design = top
557
- for id in pathlist:
558
- path = snl.SNLPath(path, design.getInstanceByID(id))
559
- instance = design.getInstanceByID(id)
560
- assert instance is not None
561
- design = instance.getModel()
562
- return path
707
+ # def refresh_path(path: snl.SNLPath):
708
+ # pathlist = path.getPathIDs()
709
+ # assert len(pathlist) > 0
710
+ # path = snl.SNLPath()
711
+ # instance = None
712
+ # top = snl.SNLUniverse.get().getTopDesign()
713
+ # design = top
714
+ # for id in pathlist:
715
+ # path = snl.SNLPath(path, design.getInstanceByID(id))
716
+ # instance = design.getInstanceByID(id)
717
+ # assert instance is not None
718
+ # design = instance.getModel()
719
+ # return path
720
+
721
+
722
+ class Attribute:
723
+ def __init__(self, snlAttribute):
724
+ self.snlAttribute = snlAttribute
725
+
726
+ def __str__(self):
727
+ return str(self.snlAttribute)
728
+
729
+ def get_name(self):
730
+ return self.snlAttribute.getName()
731
+
732
+ def has_value(self):
733
+ return self.snlAttribute.hasValue()
734
+
735
+ def get_value(self):
736
+ return self.snlAttribute.getValue()
563
737
 
564
738
 
565
739
  class Instance:
@@ -598,6 +772,11 @@ class Instance:
598
772
  return consistent_hash(self.pathIDs)
599
773
 
600
774
  def get_leaf_children(self):
775
+ """Iterate over the leaf children of this Instance.
776
+ Equivalent to the underlying leaves of the instanciation tree.
777
+ :return: an iterator over the leaf children Instance of this Instance.
778
+ :rtype: Iterator[Instance]
779
+ """
601
780
  initial_path = get_snl_path_from_id_list(self.pathIDs)
602
781
  for inst in self.__get_snl_model().getInstances():
603
782
  if inst.getModel().isLeaf():
@@ -615,47 +794,82 @@ class Instance:
615
794
  stack.append([inst_child, path_child])
616
795
 
617
796
  def is_top(self) -> bool:
618
- """Return True if this is the top design."""
797
+ """
798
+ :return: True if this is the top design.
799
+ :rtype: bool
800
+ """
619
801
  return len(self.pathIDs) == 0
620
802
 
621
803
  def is_assign(self) -> bool:
804
+ """Example: (assign a=b) will create an instance of assign connecting
805
+ the wire a to the output of the assign and b to the input.
806
+
807
+ :return: True if this is an assign. Assigns are represented with
808
+ anonymous Assign instances.
809
+ :rtype: bool
810
+ """
622
811
  return self.__get_snl_model().isAssign()
623
812
 
624
813
  def is_blackbox(self) -> bool:
625
- """Return True if this is a blackbox."""
814
+ """
815
+ :return: True if this is a blackbox.
816
+ :rtype: bool
817
+ """
626
818
  return self.__get_snl_model().isBlackBox()
627
819
 
628
820
  def is_leaf(self) -> bool:
629
- """Return True if this is a leaf."""
821
+ """
822
+ :return: True if this is a leaf.
823
+ :rtype: bool
824
+ """
630
825
  return self.__get_snl_model().isLeaf()
631
826
 
632
827
  def is_const0(self) -> bool:
633
- """Return True if this is a constant 0 generator."""
828
+ """
829
+ :return: True if this is a constant 0 generator.
830
+ :rtype: bool
831
+ """
634
832
  return self.__get_snl_model().isConst0()
635
833
 
636
834
  def is_const1(self) -> bool:
637
- """Return True if this is a constant 1 generator."""
835
+ """
836
+ :return: True if this is a constant 1 generator.
837
+ :rtype: bool
838
+ """
638
839
  return self.__get_snl_model().isConst1()
639
840
 
640
841
  def is_const(self) -> bool:
641
- """Return True if this is a constant generator."""
842
+ """
843
+ :return: True if this is a constant generator.
844
+ :rtype: bool
845
+ """
642
846
  return self.__get_snl_model().isConst()
643
847
 
644
848
  def is_buf(self) -> bool:
645
- """Return True if this is a buffer."""
849
+ """
850
+ :return: True if this is a buffer.
851
+ :rtype: bool
852
+ """
646
853
  return self.__get_snl_model().isBuf()
647
854
 
648
855
  def is_inv(self) -> bool:
649
- """Return True if this is an inverter."""
856
+ """
857
+ :return: True if this is an inverter.
858
+ :rtype: bool
859
+ """
650
860
  return self.__get_snl_model().isInv()
651
861
 
652
862
  def __get_snl_model(self):
653
- """Return the model of the instance."""
654
863
  if self.is_top():
655
864
  return snl.SNLUniverse.get().getTopDesign()
656
865
  instance = get_snl_instance_from_id_list(self.pathIDs)
657
866
  return instance.getModel()
658
867
 
868
+ def __get_leaf_snl_object(self):
869
+ if self.is_top():
870
+ return snl.SNLUniverse.get().getTopDesign()
871
+ return get_snl_instance_from_id_list(self.pathIDs)
872
+
659
873
  def __find_snl_model(self, name: str) -> snl.SNLDesign:
660
874
  u = snl.SNLUniverse.get()
661
875
  for db in u.getUserDBs():
@@ -673,7 +887,11 @@ class Instance:
673
887
  self.__get_snl_model().dumpContextDotFile(path)
674
888
 
675
889
  def get_child_instance(self, name: str):
676
- """Return the child instance with the given name."""
890
+ """
891
+ :param str name: the name of the child Instance to get.
892
+ :return: the child Instance with the given name or None if it does not exist.
893
+ :rtype: Instance or None
894
+ """
677
895
  childInst = self.__get_snl_model().getInstance(name)
678
896
  if childInst is None:
679
897
  return None
@@ -682,12 +900,22 @@ class Instance:
682
900
  return Instance(path)
683
901
 
684
902
  def get_child_instances(self):
903
+ """Iterate over the child instances of this instance.
904
+ Equivalent to go down one level in hierarchy.
905
+
906
+ :return: an iterator over the child instances of this instance.
907
+ :rtype: Iterator[Instance]
908
+ """
685
909
  for inst in self.__get_snl_model().getInstances():
686
910
  path = self.pathIDs.copy()
687
911
  path.append(inst.getID())
688
912
  yield Instance(path)
689
913
 
690
914
  def get_number_of_child_instances(self) -> int:
915
+ """
916
+ :return: the number of child instances of this instance.
917
+ :rtype: int
918
+ """
691
919
  return sum(1 for _ in self.__get_snl_model().getInstances())
692
920
 
693
921
  # def get_flat_primitive_instances(self):
@@ -707,15 +935,19 @@ class Instance:
707
935
  # stack.append([inst_child, path_child])
708
936
 
709
937
  def get_nets(self):
710
- """Return the nets of the instance.
711
- This will iterate over all scalar nets and bus nets.
938
+ """Iterate over all scalar nets and bus nets.
939
+
940
+ :return: an iterator over the nets of this Instance.
941
+ :rtype: Iterator[Net]
712
942
  """
713
943
  for net in self.__get_snl_model().getNets():
714
944
  yield Net(self.pathIDs, net)
715
945
 
716
946
  def get_flat_nets(self):
717
- """Return the nets of the instance.
718
- This will iterate over all scalar nets and bus net bits.
947
+ """Iterate over all scalar nets and bus net bits.
948
+
949
+ :return: an iterator over the flat nets of this Instance.
950
+ :rtype: Iterator[Net]
719
951
  """
720
952
  for net in self.__get_snl_model().getNets():
721
953
  if isinstance(net, snl.SNLBusNet):
@@ -725,48 +957,69 @@ class Instance:
725
957
  yield Net(self.pathIDs, net)
726
958
 
727
959
  def get_net(self, name: str) -> Net:
728
- """Return the net with the given name."""
960
+ """
961
+ :param str name: the name of the Net to get.
962
+ :return: the Net with the given name or None if it does not exist.
963
+ :rtype: Net or None
964
+ """
729
965
  net = self.__get_snl_model().getNet(name)
730
966
  if net is not None:
731
967
  return Net(self.pathIDs, net)
732
968
  return None
733
969
 
734
970
  def is_primitive(self) -> bool:
735
- """Return True if this is a primitive."""
971
+ """
972
+ :return: True if this is a primitive.
973
+ :rtype: bool
974
+ """
736
975
  return self.__get_snl_model().isPrimitive()
737
976
 
738
977
  def get_terms(self):
739
- """Return the terms of the instance.
740
- This will iterate over all scalar terms and bus terms.
978
+ """Iterate over all scalar terms and bus terms of this Instance.
979
+
980
+ :return: the terms of this Instance.
981
+ :rtype: Iterator[Term]
741
982
  """
742
983
  for term in self.__get_snl_model().getTerms():
743
984
  yield Term(self.pathIDs, term)
744
985
 
745
986
  def get_flat_terms(self):
746
- """Return the flat terms of the instance.
747
- This will iterate over all scalar terms and bus term bits.
987
+ """Iterate over all scalar terms and bus term bits.
988
+
989
+ :return: the flat terms of this Instance.
990
+ :rtype: Iterator[Term]
748
991
  """
749
992
  for term in self.__get_snl_model().getBitTerms():
750
993
  yield Term(self.pathIDs, term)
751
994
 
752
995
  def get_term(self, name: str) -> Term:
753
- """Return the term with the given name."""
996
+ """
997
+ :param str name: the name of the Term to get.
998
+ :return: the Term with the given name.
999
+ :rtype: Term or None
1000
+ """
754
1001
  term = self.__get_snl_model().getTerm(name)
755
1002
  if term is not None:
756
1003
  return Term(self.pathIDs, self.__get_snl_model().getTerm(name))
757
1004
  return None
758
1005
 
759
1006
  def get_input_terms(self):
760
- """Return the input terms of the instance.
761
- This will iterate over all scalar input terms and bus input terms.
1007
+ """Iterate over all scalar input terms and bus input terms
1008
+ of this Instance.
1009
+
1010
+ :return: the input terms of this Instance.
1011
+ :rtype: Iterator[Term]
762
1012
  """
763
1013
  for term in self.__get_snl_model().getTerms():
764
1014
  if term.getDirection() != snl.SNLTerm.Direction.Output:
765
1015
  yield Term(self.pathIDs, term)
766
1016
 
767
1017
  def get_flat_input_terms(self):
768
- """Return the flat input terms of the instance.
769
- This will iterate over all scalar input terms and bus input term bits.
1018
+ """Iterate over all scalar input terms and bus input term bits
1019
+ of this Instance.
1020
+
1021
+ :return: the flat input terms of this Instance.
1022
+ :rtype: Iterator[Term]
770
1023
  """
771
1024
  for term in self.__get_snl_model().getTerms():
772
1025
  if term.getDirection() != snl.SNLTerm.Direction.Output:
@@ -777,8 +1030,11 @@ class Instance:
777
1030
  yield Term(self.pathIDs, term)
778
1031
 
779
1032
  def get_output_terms(self):
780
- """Return the output terms of the instance.
781
- This will iterate over all scalar output terms and bus output terms.
1033
+ """Iterate over all scalar output terms and bus output terms
1034
+ of this Instance.
1035
+
1036
+ :return: the output terms of this Instance.
1037
+ :rtype: Iterator[Term]
782
1038
  """
783
1039
  for term in self.__get_snl_model().getTerms():
784
1040
  if term.getDirection() != snl.SNLTerm.Direction.Input:
@@ -796,6 +1052,11 @@ class Instance:
796
1052
  else:
797
1053
  yield Term(self.pathIDs, term)
798
1054
 
1055
+ def get_attributes(self):
1056
+ leaf_object = self.__get_leaf_snl_object()
1057
+ for attribute in leaf_object.getAttributes():
1058
+ yield Attribute(attribute)
1059
+
799
1060
  def delete_instance(self, name: str):
800
1061
  """Delete the child instance with the given name."""
801
1062
  if name == "":
@@ -810,7 +1071,10 @@ class Instance:
810
1071
  self.__get_snl_model().getInstance(name).destroy()
811
1072
 
812
1073
  def delete_instance_by_id(self, id: str):
813
- """Delete the child instance with the given ID."""
1074
+ """Delete the child instance with the given ID.
1075
+
1076
+ :param str id: the ID of the Instance to delete.
1077
+ """
814
1078
  init_path = get_snl_path_from_id_list(self.pathIDs)
815
1079
  path = snl.SNLPath(init_path, self.__get_snl_model().getInstanceByID(id))
816
1080
  snl.SNLUniquifier(path)
@@ -818,7 +1082,10 @@ class Instance:
818
1082
  self.__get_snl_model().getInstanceByID(id).destroy()
819
1083
 
820
1084
  def get_design(self):
821
- """Return the Instance containing this instance."""
1085
+ """
1086
+ :return: the Instance containing this instance.
1087
+ :rtype: Instance
1088
+ """
822
1089
  path = self.pathIDs.copy()
823
1090
  if len(self.pathIDs) == 1:
824
1091
  return get_top()
@@ -832,7 +1099,10 @@ class Instance:
832
1099
  self.get_design().delete_instance_by_id(path.getTailInstance().getID())
833
1100
 
834
1101
  def get_name(self) -> str:
835
- """Return the name of the instance or name of the top is this is the top."""
1102
+ """
1103
+ :return: the name of the instance or name of the top is this is the top.
1104
+ :rtype: str
1105
+ """
836
1106
  path = get_snl_path_from_id_list(self.pathIDs)
837
1107
  if self.is_top():
838
1108
  return self.get_model_name()
@@ -840,16 +1110,29 @@ class Instance:
840
1110
  return path.getTailInstance().getName()
841
1111
 
842
1112
  def get_model_name(self) -> str:
843
- """Return the name of the model of the instance or name of the top is this is the top."""
1113
+ """
1114
+ :return: the name of the model of the instance
1115
+ or name of the top is this is the top.
1116
+ :rtype: str
1117
+ """
844
1118
  return self.__get_snl_model().getName()
845
1119
 
846
1120
  def get_model_id(self) -> tuple[int, int, int]:
847
- """Return the ID of the model of the instance or ID of the top is this is the top."""
1121
+ """
1122
+ :return: the ID of the model of this Instance
1123
+ or ID of the top if this is the top.
1124
+ """
848
1125
  model = self.__get_snl_model()
849
1126
  return model.getDB().getID(), model.getLibrary().getID(), model.getID()
850
1127
 
851
1128
  def create_child_instance(self, model: str, name: str):
852
- """Create a child instance with the given model and name."""
1129
+ """Create a child instance with the given model and name.
1130
+
1131
+ :param str model: the name of the model of the instance to create.
1132
+ :param str name: the name of the instance to create.
1133
+ :return: the created Instance.
1134
+ :rtype: Instance
1135
+ """
853
1136
  path = get_snl_path_from_id_list(self.pathIDs)
854
1137
  if path.size() > 0:
855
1138
  snl.SNLUniquifier(path)
@@ -865,7 +1148,12 @@ class Instance:
865
1148
  return Instance(path)
866
1149
 
867
1150
  def create_term(self, name: str, direction: snl.SNLTerm.Direction) -> Term:
868
- """Create a Term in this Instance with the given name and direction."""
1151
+ """Create a Term in this Instance with the given name and direction.
1152
+
1153
+ :param str name: the name of the Term to create.
1154
+ :param snl.SNLTerm.Direction direction: the direction of the Term to create.
1155
+ :return: the created Term.
1156
+ """
869
1157
  path = get_snl_path_from_id_list(self.pathIDs)
870
1158
  if path.size() > 0:
871
1159
  snl.SNLUniquifier(path)
@@ -875,19 +1163,40 @@ class Instance:
875
1163
  return Term(path, newSNLTerm)
876
1164
 
877
1165
  def create_output_term(self, name: str) -> Term:
878
- """Create an output Term in this Instance with the given name."""
1166
+ """Create an output Term in this Instance with the given name.
1167
+
1168
+ :param str name: the name of the Term to create.
1169
+ :return: the created Term.
1170
+ :rtype: Term
1171
+ """
879
1172
  return self.create_term(name, snl.SNLTerm.Direction.Output)
880
1173
 
881
1174
  def create_input_term(self, name: str) -> Term:
882
- """Create an input Term in this Instance with the given name."""
1175
+ """Create an input Term in this Instance with the given name.
1176
+
1177
+ :param str name: the name of the Term to create.
1178
+ :return: the created Term.
1179
+ :rtype: Term
1180
+ """
883
1181
  return self.create_term(name, snl.SNLTerm.Direction.Input)
884
1182
 
885
1183
  def create_inout_term(self, name: str) -> Term:
886
- """Create an inout Term in this Instance with the given name."""
1184
+ """Create an inout Term in this Instance with the given name.
1185
+
1186
+ :param str name: the name of the Term to create.
1187
+ :return: the created Term.
1188
+ :rtype: Term
1189
+ """
887
1190
  return self.create_term(name, snl.SNLTerm.Direction.InOut)
888
1191
 
889
1192
  def create_bus_term(self, name: str, msb: int, lsb: int, direction) -> Term:
890
- """Create a bus Term in this Instance with the given name, msb, lsb and direction."""
1193
+ """Create a bus Term in this Instance with the given name, msb, lsb and direction.
1194
+ :param str name: the name of the Term to create.
1195
+ :param int msb: the most significant bit of the Term to create.
1196
+ :param int lsb: the least significant bit of the Term to create.
1197
+ :param snl.SNLTerm.Direction direction: the direction of the Term to create.
1198
+ :return: the created Term.
1199
+ """
891
1200
  path = get_snl_path_from_id_list(self.pathIDs)
892
1201
  if path.size() > 0:
893
1202
  snl.SNLUniquifier(path)
@@ -897,19 +1206,45 @@ class Instance:
897
1206
  return Term(path, newSNLTerm)
898
1207
 
899
1208
  def create_inout_bus_term(self, name: str, msb: int, lsb: int) -> Term:
900
- """Create an inout bus Term in this Instance with the given name, msb and lsb."""
1209
+ """Create an inout bus Term in this Instance with the given name, msb and lsb.
1210
+
1211
+ :param str name: the name of the Term to create.
1212
+ :param int msb: the most significant bit of the Term to create.
1213
+ :param int lsb: the least significant bit of the Term to create.
1214
+ :return: the created Term.
1215
+ :rtype: Term
1216
+ """
901
1217
  return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.InOut)
902
1218
 
903
1219
  def create_output_bus_term(self, name: str, msb: int, lsb: int) -> Term:
904
- """Create an output bus Term in this Instance with the given name, msb and lsb."""
1220
+ """Create an output bus Term in this Instance with the given name, msb and lsb.
1221
+
1222
+ :param str name: the name of the Term to create.
1223
+ :param int msb: the most significant bit of the Term to create.
1224
+ :param int lsb: the least significant bit of the Term to create.
1225
+ :return: the created Term.
1226
+ :rtype: Term
1227
+ """
905
1228
  return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.Output)
906
1229
 
907
1230
  def create_input_bus_term(self, name: str, msb: int, lsb: int) -> Term:
908
- """Create an input bus Term in this Instance with the given name, msb and lsb."""
1231
+ """Create an input bus Term in this Instance with the given name, msb and lsb.
1232
+
1233
+ :param str name: the name of the Term to create.
1234
+ :param int msb: the most significant bit of the Term to create.
1235
+ :param int lsb: the least significant bit of the Term to create.
1236
+ :return: the created Term.
1237
+ :rtype: Term
1238
+ """
909
1239
  return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.Input)
910
1240
 
911
1241
  def create_net(self, name: str) -> Net:
912
- """Create a scalar Net in this Instance with the given name."""
1242
+ """Create a scalar Net in this Instance with the given name.
1243
+
1244
+ :param str name: the name of the Net to create.
1245
+ :return: the created Net.
1246
+ :rtype: Net
1247
+ """
913
1248
  path = get_snl_path_from_id_list(self.pathIDs)
914
1249
  if path.size() > 0:
915
1250
  snl.SNLUniquifier(path)
@@ -919,7 +1254,14 @@ class Instance:
919
1254
  return Net(path, newSNLNet)
920
1255
 
921
1256
  def create_bus_net(self, name: str, msb: int, lsb: int) -> Net:
922
- """Create a bus Net in this Instance with the given name, msb and lsb."""
1257
+ """Create a bus Net in this Instance with the given name, msb and lsb.
1258
+
1259
+ :param str name: the name of the Net to create.
1260
+ :param int msb: the most significant bit of the Net to create.
1261
+ :param int lsb: the least significant bit of the Net to create.
1262
+ :return: the created Net.
1263
+ :rtype: Net
1264
+ """
923
1265
  path = get_snl_path_from_id_list(self.pathIDs)
924
1266
  if path.size() > 0:
925
1267
  snl.SNLUniquifier(path)
@@ -929,7 +1271,11 @@ class Instance:
929
1271
  return Net(path, newSNLNet)
930
1272
 
931
1273
  def dump_verilog(self, path: str, name: str):
932
- """Dump the verilog of this instance."""
1274
+ """Dump the verilog of this instance.
1275
+
1276
+ :param str path: the path where to dump the verilog.
1277
+ :param str name: the name of the verilog file.
1278
+ """
933
1279
  self.__get_snl_model().dumpVerilog(path, name)
934
1280
 
935
1281
 
@@ -943,10 +1289,20 @@ def get_top_db() -> snl.SNLDB:
943
1289
 
944
1290
 
945
1291
  def get_top():
1292
+ """
1293
+ :return: the top Instance.
1294
+ :rtype: Instance
1295
+ """
946
1296
  return Instance(snl.SNLPath())
947
1297
 
948
1298
 
949
1299
  def create_top(name: str) -> Instance:
1300
+ """Create a top instance with the given name.
1301
+
1302
+ :param str name: the name of the top instance to create.
1303
+ :return: the created top Instance.
1304
+ :rtype: Instance
1305
+ """
950
1306
  # init
951
1307
  db = get_top_db()
952
1308
  # create top design
@@ -966,11 +1322,15 @@ def load_verilog(files: list):
966
1322
 
967
1323
 
968
1324
  def load_liberty(files: list):
969
- logging.info(f"Loading liberty: {', '.join(files)}")
1325
+ logging.info(f"Loading liberty files: {', '.join(files)}")
970
1326
  get_top_db().loadLibertyPrimitives(files)
971
1327
 
972
1328
 
973
1329
  def load_primitives(name: str):
1330
+ """Loads a primitive library embedded in najaeda.
1331
+ Currently supported libraries are:
1332
+ - xilinx
1333
+ """
974
1334
  if name == "xilinx":
975
1335
  logging.info("Loading xilinx primitives")
976
1336
  from najaeda.primitives import xilinx
@@ -988,7 +1348,11 @@ def get_primitives_library() -> snl.SNLLibrary:
988
1348
 
989
1349
 
990
1350
  def get_model_name(id: tuple[int, int, int]) -> str:
991
- """Return the name of the model given its id."""
1351
+ """
1352
+ :param tuple[int, int, int] id: the id of the model.
1353
+ :return: the name of the model given its id or None if it does not exist.
1354
+ :rtype: str or None
1355
+ """
992
1356
  u = snl.SNLUniverse.get()
993
1357
  if u:
994
1358
  db = u.getDB(id[0])