najaeda 0.1.7__cp310-cp310-macosx_11_0_arm64.whl → 0.1.8__cp310-cp310-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of najaeda might be problematic. Click here for more details.
- najaeda/docs/.readthedocs.yaml +2 -8
- najaeda/docs/requirements.txt +7 -0
- najaeda/docs/source/api.rst +2 -2
- najaeda/docs/source/conf.py +1 -1
- najaeda/docs/source/equipotential.rst +20 -0
- najaeda/docs/source/index.rst +4 -0
- najaeda/docs/source/instance.rst +23 -0
- najaeda/docs/source/net.rst +20 -0
- najaeda/docs/source/term.rst +20 -0
- najaeda/libnaja_snl_python.dylib +0 -0
- najaeda/netlist.py +116 -66
- najaeda/stats.py +320 -0
- {najaeda-0.1.7.dist-info → najaeda-0.1.8.dist-info}/METADATA +7 -2
- najaeda-0.1.8.dist-info/RECORD +25 -0
- najaeda/docs/conf.py +0 -26
- najaeda-0.1.7.dist-info/RECORD +0 -20
- {najaeda-0.1.7.dist-info → najaeda-0.1.8.dist-info}/WHEEL +0 -0
- {najaeda-0.1.7.dist-info → najaeda-0.1.8.dist-info}/licenses/AUTHORS +0 -0
- {najaeda-0.1.7.dist-info → najaeda-0.1.8.dist-info}/licenses/LICENSE +0 -0
najaeda/docs/.readthedocs.yaml
CHANGED
|
@@ -11,18 +11,12 @@ version: 2
|
|
|
11
11
|
# Set the OS, Python version and other tools you might need
|
|
12
12
|
build:
|
|
13
13
|
os: ubuntu-22.04
|
|
14
|
-
apt_packages:
|
|
15
|
-
- cmake
|
|
16
14
|
tools:
|
|
17
15
|
python: "3.12"
|
|
18
|
-
# You can also specify other tool versions:
|
|
19
|
-
# nodejs: "19"
|
|
20
|
-
# rust: "1.64"
|
|
21
|
-
# golang: "1.19"
|
|
22
16
|
|
|
23
17
|
# Build documentation in the "docs/" directory with Sphinx
|
|
24
18
|
sphinx:
|
|
25
|
-
configuration: docs/conf.py
|
|
19
|
+
configuration: src/najaeda/najaeda/docs/source/conf.py
|
|
26
20
|
|
|
27
21
|
# Optionally build your docs in additional formats such as PDF and ePub
|
|
28
22
|
# formats:
|
|
@@ -34,4 +28,4 @@ sphinx:
|
|
|
34
28
|
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
|
|
35
29
|
python:
|
|
36
30
|
install:
|
|
37
|
-
- requirements: docs/requirements.txt
|
|
31
|
+
- requirements: src/najaeda/najaeda/docs/requirements.txt
|
najaeda/docs/source/api.rst
CHANGED
najaeda/docs/source/conf.py
CHANGED
|
@@ -15,7 +15,7 @@ sys.path.insert(0, os.path.abspath('../../../'))
|
|
|
15
15
|
project = 'najaeda'
|
|
16
16
|
copyright = '2024, Naja authors'
|
|
17
17
|
author = 'Naja authors'
|
|
18
|
-
release = '0.1.
|
|
18
|
+
release = '0.1.8'
|
|
19
19
|
|
|
20
20
|
# -- General configuration ---------------------------------------------------
|
|
21
21
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Equipotential Class
|
|
2
|
+
===================
|
|
3
|
+
|
|
4
|
+
.. automodule:: najaeda.equipotential
|
|
5
|
+
:members:
|
|
6
|
+
:undoc-members:
|
|
7
|
+
:show-inheritance:
|
|
8
|
+
|
|
9
|
+
Equipotential Overview
|
|
10
|
+
----------------------
|
|
11
|
+
|
|
12
|
+
The `Equipotential` class is responsible for managing equipotentials in the `najaeda` system.
|
|
13
|
+
|
|
14
|
+
Equipotential Attributes
|
|
15
|
+
------------------------
|
|
16
|
+
|
|
17
|
+
.. autoclass:: najaeda.netlist.Equipotential
|
|
18
|
+
:members:
|
|
19
|
+
:undoc-members:
|
|
20
|
+
:show-inheritance:
|
najaeda/docs/source/index.rst
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Instance Class
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
.. automodule:: najaeda.instance
|
|
5
|
+
:members:
|
|
6
|
+
:undoc-members:
|
|
7
|
+
:show-inheritance:
|
|
8
|
+
|
|
9
|
+
Instance Overview
|
|
10
|
+
-----------------
|
|
11
|
+
|
|
12
|
+
In `najaeda`, an `Instance` encapsulates the concept of an instance in its hierarchical context.
|
|
13
|
+
|
|
14
|
+
When an `Instance` is modified through editing methods,
|
|
15
|
+
`najaeda` will automatically manage the necessary uniquification.
|
|
16
|
+
|
|
17
|
+
Instance Attributes
|
|
18
|
+
-------------------
|
|
19
|
+
|
|
20
|
+
.. autoclass:: najaeda.netlist.Instance
|
|
21
|
+
:members:
|
|
22
|
+
:undoc-members:
|
|
23
|
+
:show-inheritance:
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Net Class
|
|
2
|
+
=========
|
|
3
|
+
|
|
4
|
+
.. automodule:: najaeda.net
|
|
5
|
+
:members:
|
|
6
|
+
:undoc-members:
|
|
7
|
+
:show-inheritance:
|
|
8
|
+
|
|
9
|
+
Net Overview
|
|
10
|
+
------------
|
|
11
|
+
|
|
12
|
+
The `Net` class is responsible for managing nets in the `najaeda` system.
|
|
13
|
+
|
|
14
|
+
Net Attributes
|
|
15
|
+
--------------
|
|
16
|
+
|
|
17
|
+
.. autoclass:: najaeda.netlist.Net
|
|
18
|
+
:members:
|
|
19
|
+
:undoc-members:
|
|
20
|
+
:show-inheritance:
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Term Class
|
|
2
|
+
==========
|
|
3
|
+
|
|
4
|
+
.. automodule:: najaeda.term
|
|
5
|
+
:members:
|
|
6
|
+
:undoc-members:
|
|
7
|
+
:show-inheritance:
|
|
8
|
+
|
|
9
|
+
Term Overview
|
|
10
|
+
-------------
|
|
11
|
+
|
|
12
|
+
The `Term` class is responsible for managing terms in the `najaeda` system.
|
|
13
|
+
|
|
14
|
+
Term Attributes
|
|
15
|
+
---------------
|
|
16
|
+
|
|
17
|
+
.. autoclass:: najaeda.netlist.Term
|
|
18
|
+
:members:
|
|
19
|
+
:undoc-members:
|
|
20
|
+
:show-inheritance:
|
najaeda/libnaja_snl_python.dylib
CHANGED
|
Binary file
|
najaeda/netlist.py
CHANGED
|
@@ -32,7 +32,6 @@ def consistent_hash(obj):
|
|
|
32
32
|
return b''.join(hash_object(i) for i in o)
|
|
33
33
|
else:
|
|
34
34
|
return hash_value(o)
|
|
35
|
-
|
|
36
35
|
serialized_obj = default_serializer(obj)
|
|
37
36
|
obj_bytes = hash_object(serialized_obj)
|
|
38
37
|
return int(hashlib.sha256(obj_bytes).hexdigest(), 16)
|
|
@@ -71,6 +70,7 @@ class Equipotential:
|
|
|
71
70
|
|
|
72
71
|
def __init__(self, term):
|
|
73
72
|
snl_term = get_snl_term_for_ids(term.pathIDs, term.termIDs)
|
|
73
|
+
inst_term = None
|
|
74
74
|
if isinstance(snl_term, snl.SNLBusTerm):
|
|
75
75
|
raise ValueError("Equipotential cannot be constructed on bus term")
|
|
76
76
|
if len(term.pathIDs) == 0:
|
|
@@ -82,10 +82,11 @@ class Equipotential:
|
|
|
82
82
|
if inst_term is None:
|
|
83
83
|
self.equi = None
|
|
84
84
|
return
|
|
85
|
+
else:
|
|
86
|
+
snl_term = get_snl_term_for_ids(inst_term.pathIDs, inst_term.termIDs)
|
|
85
87
|
else:
|
|
86
88
|
inst_term = term
|
|
87
89
|
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
90
|
ito = snl.SNLNetComponentOccurrence(
|
|
90
91
|
path.getHeadPath(),
|
|
91
92
|
path.getTailInstance().getInstTerm(snl_term)
|
|
@@ -95,6 +96,9 @@ class Equipotential:
|
|
|
95
96
|
def __eq__(self, value):
|
|
96
97
|
return self.equi == value.equi
|
|
97
98
|
|
|
99
|
+
def dump_dot(self, path: str):
|
|
100
|
+
self.equi.dumpDotFile(path)
|
|
101
|
+
|
|
98
102
|
def get_inst_terms(self):
|
|
99
103
|
if self.equi is not None:
|
|
100
104
|
for term in self.equi.getInstTermOccurrences():
|
|
@@ -106,7 +110,7 @@ class Equipotential:
|
|
|
106
110
|
def get_top_terms(self):
|
|
107
111
|
if self.equi is not None:
|
|
108
112
|
for term in self.equi.getTerms():
|
|
109
|
-
yield Term(
|
|
113
|
+
yield Term([], term)
|
|
110
114
|
|
|
111
115
|
def get_leaf_readers(self):
|
|
112
116
|
if self.equi is not None:
|
|
@@ -151,10 +155,13 @@ class Net:
|
|
|
151
155
|
raise ValueError(
|
|
152
156
|
"Only one of `net` or `net_concat` should be provided, not both."
|
|
153
157
|
)
|
|
154
|
-
if path.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
+
if isinstance(path, snl.SNLPath):
|
|
159
|
+
if path.size() > 0:
|
|
160
|
+
self.pathIDs = path.getPathIDs()
|
|
161
|
+
else:
|
|
162
|
+
self.pathIDs = []
|
|
163
|
+
elif isinstance(path, list):
|
|
164
|
+
self.pathIDs = path.copy()
|
|
158
165
|
if net is not None:
|
|
159
166
|
self.net = net
|
|
160
167
|
elif net_concat is not None:
|
|
@@ -235,11 +242,10 @@ class Net:
|
|
|
235
242
|
return sum(1 for _ in self.net_concat)
|
|
236
243
|
|
|
237
244
|
def get_bits(self):
|
|
238
|
-
path = get_snl_path_from_id_list(self.pathIDs)
|
|
239
245
|
if hasattr(self, "net"):
|
|
240
246
|
if isinstance(self.net, snl.SNLBusNet):
|
|
241
247
|
for bit in self.net.getBits():
|
|
242
|
-
yield Net(
|
|
248
|
+
yield Net(self.pathIDs, bit)
|
|
243
249
|
else:
|
|
244
250
|
yield self
|
|
245
251
|
else:
|
|
@@ -247,30 +253,28 @@ class Net:
|
|
|
247
253
|
yield net
|
|
248
254
|
|
|
249
255
|
def get_bit(self, index: int):
|
|
250
|
-
path = get_snl_path_from_id_list(self.pathIDs)
|
|
251
256
|
if hasattr(self, "net"):
|
|
252
257
|
if isinstance(self.net, snl.SNLBusNet):
|
|
253
|
-
return Net(
|
|
258
|
+
return Net(self.pathIDs, self.net.getBit(index))
|
|
254
259
|
else:
|
|
255
260
|
return None
|
|
256
261
|
if 0 <= index < len(self.net_concat):
|
|
257
|
-
return Net(
|
|
262
|
+
return Net(self.pathIDs, self.net_concat[index])
|
|
258
263
|
return None
|
|
259
264
|
|
|
260
265
|
def get_inst_terms(self):
|
|
261
|
-
init_path = get_snl_path_from_id_list(self.pathIDs)
|
|
262
266
|
if hasattr(self, "net_concat"):
|
|
263
267
|
raise ValueError("Cannot get inst terms from a net_concat")
|
|
264
268
|
for term in self.net.getInstTerms():
|
|
265
|
-
path =
|
|
269
|
+
path = self.pathIDs.copy()
|
|
270
|
+
path.append(term.getInstance().getID())
|
|
266
271
|
yield Term(path, term.getBitTerm())
|
|
267
272
|
|
|
268
273
|
def get_design_terms(self):
|
|
269
|
-
path = get_snl_path_from_id_list(self.pathIDs)
|
|
270
274
|
if hasattr(self, "net_concat"):
|
|
271
275
|
raise ValueError("Cannot get terms from a net_concat")
|
|
272
276
|
for term in self.net.getBitTerms():
|
|
273
|
-
yield Term(
|
|
277
|
+
yield Term(self.pathIDs, term)
|
|
274
278
|
|
|
275
279
|
def get_terms(self):
|
|
276
280
|
for term in itertools.chain(self.get_design_terms(), self.get_inst_terms()):
|
|
@@ -306,10 +310,13 @@ class Term:
|
|
|
306
310
|
else:
|
|
307
311
|
self.termIDs = [term.getID(), term.getBit()]
|
|
308
312
|
|
|
309
|
-
if path.
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
+
if isinstance(path, snl.SNLPath):
|
|
314
|
+
if path.size() > 0:
|
|
315
|
+
self.pathIDs = path.getPathIDs()
|
|
316
|
+
else:
|
|
317
|
+
self.pathIDs = []
|
|
318
|
+
elif isinstance(path, list):
|
|
319
|
+
self.pathIDs = path.copy()
|
|
313
320
|
|
|
314
321
|
def __eq__(self, other) -> bool:
|
|
315
322
|
return self.pathIDs == other.pathIDs and self.termIDs == other.termIDs
|
|
@@ -453,23 +460,21 @@ class Term:
|
|
|
453
460
|
return None
|
|
454
461
|
|
|
455
462
|
def get_lower_net(self) -> Net:
|
|
456
|
-
path = get_snl_path_from_id_list(self.pathIDs)
|
|
457
463
|
"""Return the lower net of the term."""
|
|
458
|
-
return self.__get_net(
|
|
464
|
+
return self.__get_net(self.pathIDs, self.__get_snl_lower_bitnet)
|
|
459
465
|
|
|
460
466
|
def get_net(self) -> Net:
|
|
461
467
|
"""Return the net of the term."""
|
|
462
|
-
|
|
463
|
-
if
|
|
468
|
+
head_path = self.pathIDs.copy()
|
|
469
|
+
if len(head_path) == 0:
|
|
464
470
|
return None
|
|
465
471
|
# path is one level up
|
|
466
|
-
head_path
|
|
472
|
+
head_path.pop()
|
|
467
473
|
return self.__get_net(head_path, self.__get_snl_bitnet)
|
|
468
474
|
|
|
469
475
|
def get_instance(self):
|
|
470
|
-
path = get_snl_path_from_id_list(self.pathIDs)
|
|
471
476
|
"""Return the instance of the term."""
|
|
472
|
-
return Instance(
|
|
477
|
+
return Instance(self.pathIDs)
|
|
473
478
|
|
|
474
479
|
def get_flat_fanout(self):
|
|
475
480
|
return self.get_equipotential().get_leaf_readers()
|
|
@@ -488,17 +493,16 @@ class Term:
|
|
|
488
493
|
return snlterm.getDirection() == snl.SNLTerm.Direction.Output
|
|
489
494
|
|
|
490
495
|
def get_bits(self):
|
|
491
|
-
path = get_snl_path_from_id_list(self.pathIDs)
|
|
492
496
|
if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
|
|
493
497
|
for bit in get_snl_term_for_ids(self.pathIDs, self.termIDs).getBits():
|
|
494
|
-
yield Term(
|
|
498
|
+
yield Term(self.pathIDs, bit)
|
|
495
499
|
else:
|
|
496
500
|
yield self
|
|
497
501
|
|
|
498
502
|
def get_bit(self, index: int):
|
|
499
|
-
path = get_snl_path_from_id_list(self.pathIDs)
|
|
500
503
|
if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
|
|
501
|
-
return Term(
|
|
504
|
+
return Term(self.pathIDs, get_snl_term_for_ids(
|
|
505
|
+
self.pathIDs, self.termIDs).getBit(index))
|
|
502
506
|
return None
|
|
503
507
|
|
|
504
508
|
def disconnect(self):
|
|
@@ -564,10 +568,13 @@ class Instance:
|
|
|
564
568
|
"""
|
|
565
569
|
|
|
566
570
|
def __init__(self, path=snl.SNLPath()):
|
|
567
|
-
if path.
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
+
if isinstance(path, snl.SNLPath):
|
|
572
|
+
if path.size() > 0:
|
|
573
|
+
self.pathIDs = path.getPathIDs()
|
|
574
|
+
else:
|
|
575
|
+
self.pathIDs = []
|
|
576
|
+
elif isinstance(path, list):
|
|
577
|
+
self.pathIDs = path.copy()
|
|
571
578
|
|
|
572
579
|
def __eq__(self, other) -> bool:
|
|
573
580
|
return self.pathIDs == other.pathIDs
|
|
@@ -658,17 +665,26 @@ class Instance:
|
|
|
658
665
|
return found_model
|
|
659
666
|
return None
|
|
660
667
|
|
|
668
|
+
def dump_full_dot(self, path: str):
|
|
669
|
+
"""Dump the full dot file of this instance."""
|
|
670
|
+
self.__get_snl_model().dumpFullDotFile(path)
|
|
671
|
+
|
|
672
|
+
def dump_context_dot(self, path: str):
|
|
673
|
+
self.__get_snl_model().dumpContextDotFile(path)
|
|
674
|
+
|
|
661
675
|
def get_child_instance(self, name: str):
|
|
676
|
+
"""Return the child instance with the given name."""
|
|
662
677
|
childInst = self.__get_snl_model().getInstance(name)
|
|
663
678
|
if childInst is None:
|
|
664
679
|
return None
|
|
665
|
-
path =
|
|
666
|
-
|
|
680
|
+
path = self.pathIDs.copy()
|
|
681
|
+
path.append(childInst.getID())
|
|
682
|
+
return Instance(path)
|
|
667
683
|
|
|
668
684
|
def get_child_instances(self):
|
|
669
685
|
for inst in self.__get_snl_model().getInstances():
|
|
670
|
-
|
|
671
|
-
path
|
|
686
|
+
path = self.pathIDs.copy()
|
|
687
|
+
path.append(inst.getID())
|
|
672
688
|
yield Instance(path)
|
|
673
689
|
|
|
674
690
|
def get_number_of_child_instances(self) -> int:
|
|
@@ -691,24 +707,28 @@ class Instance:
|
|
|
691
707
|
# stack.append([inst_child, path_child])
|
|
692
708
|
|
|
693
709
|
def get_nets(self):
|
|
694
|
-
|
|
710
|
+
"""Return the nets of the instance.
|
|
711
|
+
This will iterate over all scalar nets and bus nets.
|
|
712
|
+
"""
|
|
695
713
|
for net in self.__get_snl_model().getNets():
|
|
696
|
-
yield Net(
|
|
714
|
+
yield Net(self.pathIDs, net)
|
|
697
715
|
|
|
698
716
|
def get_flat_nets(self):
|
|
699
|
-
|
|
717
|
+
"""Return the nets of the instance.
|
|
718
|
+
This will iterate over all scalar nets and bus net bits.
|
|
719
|
+
"""
|
|
700
720
|
for net in self.__get_snl_model().getNets():
|
|
701
721
|
if isinstance(net, snl.SNLBusNet):
|
|
702
722
|
for bit in net.getBits():
|
|
703
|
-
yield Net(
|
|
723
|
+
yield Net(self.pathIDs, bit)
|
|
704
724
|
else:
|
|
705
|
-
yield Net(
|
|
725
|
+
yield Net(self.pathIDs, net)
|
|
706
726
|
|
|
707
727
|
def get_net(self, name: str) -> Net:
|
|
708
|
-
|
|
728
|
+
"""Return the net with the given name."""
|
|
709
729
|
net = self.__get_snl_model().getNet(name)
|
|
710
730
|
if net is not None:
|
|
711
|
-
return Net(
|
|
731
|
+
return Net(self.pathIDs, net)
|
|
712
732
|
return None
|
|
713
733
|
|
|
714
734
|
def is_primitive(self) -> bool:
|
|
@@ -716,60 +736,73 @@ class Instance:
|
|
|
716
736
|
return self.__get_snl_model().isPrimitive()
|
|
717
737
|
|
|
718
738
|
def get_terms(self):
|
|
719
|
-
|
|
739
|
+
"""Return the terms of the instance.
|
|
740
|
+
This will iterate over all scalar terms and bus terms.
|
|
741
|
+
"""
|
|
720
742
|
for term in self.__get_snl_model().getTerms():
|
|
721
|
-
yield Term(
|
|
743
|
+
yield Term(self.pathIDs, term)
|
|
722
744
|
|
|
723
745
|
def get_flat_terms(self):
|
|
724
|
-
|
|
746
|
+
"""Return the flat terms of the instance.
|
|
747
|
+
This will iterate over all scalar terms and bus term bits.
|
|
748
|
+
"""
|
|
725
749
|
for term in self.__get_snl_model().getBitTerms():
|
|
726
|
-
yield Term(
|
|
750
|
+
yield Term(self.pathIDs, term)
|
|
727
751
|
|
|
728
752
|
def get_term(self, name: str) -> Term:
|
|
729
|
-
|
|
753
|
+
"""Return the term with the given name."""
|
|
730
754
|
term = self.__get_snl_model().getTerm(name)
|
|
731
755
|
if term is not None:
|
|
732
|
-
return Term(
|
|
756
|
+
return Term(self.pathIDs, self.__get_snl_model().getTerm(name))
|
|
733
757
|
return None
|
|
734
758
|
|
|
735
759
|
def get_input_terms(self):
|
|
736
|
-
|
|
760
|
+
"""Return the input terms of the instance.
|
|
761
|
+
This will iterate over all scalar input terms and bus input terms.
|
|
762
|
+
"""
|
|
737
763
|
for term in self.__get_snl_model().getTerms():
|
|
738
764
|
if term.getDirection() != snl.SNLTerm.Direction.Output:
|
|
739
|
-
yield Term(
|
|
765
|
+
yield Term(self.pathIDs, term)
|
|
740
766
|
|
|
741
767
|
def get_flat_input_terms(self):
|
|
742
|
-
|
|
768
|
+
"""Return the flat input terms of the instance.
|
|
769
|
+
This will iterate over all scalar input terms and bus input term bits.
|
|
770
|
+
"""
|
|
743
771
|
for term in self.__get_snl_model().getTerms():
|
|
744
772
|
if term.getDirection() != snl.SNLTerm.Direction.Output:
|
|
745
773
|
if isinstance(term, snl.SNLBusTerm):
|
|
746
774
|
for bit in term.getBits():
|
|
747
|
-
yield Term(
|
|
775
|
+
yield Term(self.pathIDs, bit)
|
|
748
776
|
else:
|
|
749
|
-
yield Term(
|
|
777
|
+
yield Term(self.pathIDs, term)
|
|
750
778
|
|
|
751
779
|
def get_output_terms(self):
|
|
752
|
-
|
|
780
|
+
"""Return the output terms of the instance.
|
|
781
|
+
This will iterate over all scalar output terms and bus output terms.
|
|
782
|
+
"""
|
|
753
783
|
for term in self.__get_snl_model().getTerms():
|
|
754
784
|
if term.getDirection() != snl.SNLTerm.Direction.Input:
|
|
755
|
-
yield Term(
|
|
785
|
+
yield Term(self.pathIDs, term)
|
|
756
786
|
|
|
757
787
|
def get_flat_output_terms(self):
|
|
758
|
-
|
|
788
|
+
"""Return the flat output terms of the instance.
|
|
789
|
+
This will iterate over all scalar output terms and bus output term bits.
|
|
790
|
+
"""
|
|
759
791
|
for term in self.__get_snl_model().getTerms():
|
|
760
792
|
if term.getDirection() != snl.SNLTerm.Direction.Input:
|
|
761
793
|
if isinstance(term, snl.SNLBusTerm):
|
|
762
794
|
for bit in term.getBits():
|
|
763
|
-
yield Term(
|
|
795
|
+
yield Term(self.pathIDs, bit)
|
|
764
796
|
else:
|
|
765
|
-
yield Term(
|
|
797
|
+
yield Term(self.pathIDs, term)
|
|
766
798
|
|
|
767
799
|
def delete_instance(self, name: str):
|
|
768
|
-
|
|
800
|
+
"""Delete the child instance with the given name."""
|
|
769
801
|
if name == "":
|
|
770
802
|
raise ValueError(
|
|
771
803
|
"Cannot delete instance with empty name. Try delete_instance_by_id instead."
|
|
772
804
|
)
|
|
805
|
+
init_path = get_snl_path_from_id_list(self.pathIDs)
|
|
773
806
|
path = snl.SNLPath(init_path, self.__get_snl_model().getInstance(name))
|
|
774
807
|
snl.SNLUniquifier(path)
|
|
775
808
|
if init_path.size() > 0:
|
|
@@ -777,6 +810,7 @@ class Instance:
|
|
|
777
810
|
self.__get_snl_model().getInstance(name).destroy()
|
|
778
811
|
|
|
779
812
|
def delete_instance_by_id(self, id: str):
|
|
813
|
+
"""Delete the child instance with the given ID."""
|
|
780
814
|
init_path = get_snl_path_from_id_list(self.pathIDs)
|
|
781
815
|
path = snl.SNLPath(init_path, self.__get_snl_model().getInstanceByID(id))
|
|
782
816
|
snl.SNLUniquifier(path)
|
|
@@ -784,19 +818,22 @@ class Instance:
|
|
|
784
818
|
self.__get_snl_model().getInstanceByID(id).destroy()
|
|
785
819
|
|
|
786
820
|
def get_design(self):
|
|
787
|
-
|
|
821
|
+
"""Return the Instance containing this instance."""
|
|
822
|
+
path = self.pathIDs.copy()
|
|
788
823
|
if len(self.pathIDs) == 1:
|
|
789
824
|
return get_top()
|
|
790
|
-
|
|
825
|
+
path.pop()
|
|
826
|
+
return Instance(path)
|
|
791
827
|
|
|
792
828
|
def delete(self):
|
|
829
|
+
"""Delete this instance."""
|
|
793
830
|
path = get_snl_path_from_id_list(self.pathIDs)
|
|
794
831
|
snl.SNLUniquifier(path)
|
|
795
832
|
self.get_design().delete_instance_by_id(path.getTailInstance().getID())
|
|
796
833
|
|
|
797
834
|
def get_name(self) -> str:
|
|
798
|
-
path = get_snl_path_from_id_list(self.pathIDs)
|
|
799
835
|
"""Return the name of the instance or name of the top is this is the top."""
|
|
836
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
800
837
|
if self.is_top():
|
|
801
838
|
return self.get_model_name()
|
|
802
839
|
else:
|
|
@@ -807,10 +844,12 @@ class Instance:
|
|
|
807
844
|
return self.__get_snl_model().getName()
|
|
808
845
|
|
|
809
846
|
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."""
|
|
810
848
|
model = self.__get_snl_model()
|
|
811
849
|
return model.getDB().getID(), model.getLibrary().getID(), model.getID()
|
|
812
850
|
|
|
813
851
|
def create_child_instance(self, model: str, name: str):
|
|
852
|
+
"""Create a child instance with the given model and name."""
|
|
814
853
|
path = get_snl_path_from_id_list(self.pathIDs)
|
|
815
854
|
if path.size() > 0:
|
|
816
855
|
snl.SNLUniquifier(path)
|
|
@@ -826,6 +865,7 @@ class Instance:
|
|
|
826
865
|
return Instance(path)
|
|
827
866
|
|
|
828
867
|
def create_term(self, name: str, direction: snl.SNLTerm.Direction) -> Term:
|
|
868
|
+
"""Create a Term in this Instance with the given name and direction."""
|
|
829
869
|
path = get_snl_path_from_id_list(self.pathIDs)
|
|
830
870
|
if path.size() > 0:
|
|
831
871
|
snl.SNLUniquifier(path)
|
|
@@ -835,15 +875,19 @@ class Instance:
|
|
|
835
875
|
return Term(path, newSNLTerm)
|
|
836
876
|
|
|
837
877
|
def create_output_term(self, name: str) -> Term:
|
|
878
|
+
"""Create an output Term in this Instance with the given name."""
|
|
838
879
|
return self.create_term(name, snl.SNLTerm.Direction.Output)
|
|
839
880
|
|
|
840
881
|
def create_input_term(self, name: str) -> Term:
|
|
882
|
+
"""Create an input Term in this Instance with the given name."""
|
|
841
883
|
return self.create_term(name, snl.SNLTerm.Direction.Input)
|
|
842
884
|
|
|
843
885
|
def create_inout_term(self, name: str) -> Term:
|
|
886
|
+
"""Create an inout Term in this Instance with the given name."""
|
|
844
887
|
return self.create_term(name, snl.SNLTerm.Direction.InOut)
|
|
845
888
|
|
|
846
889
|
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."""
|
|
847
891
|
path = get_snl_path_from_id_list(self.pathIDs)
|
|
848
892
|
if path.size() > 0:
|
|
849
893
|
snl.SNLUniquifier(path)
|
|
@@ -853,15 +897,19 @@ class Instance:
|
|
|
853
897
|
return Term(path, newSNLTerm)
|
|
854
898
|
|
|
855
899
|
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."""
|
|
856
901
|
return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.InOut)
|
|
857
902
|
|
|
858
903
|
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."""
|
|
859
905
|
return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.Output)
|
|
860
906
|
|
|
861
907
|
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."""
|
|
862
909
|
return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.Input)
|
|
863
910
|
|
|
864
911
|
def create_net(self, name: str) -> Net:
|
|
912
|
+
"""Create a scalar Net in this Instance with the given name."""
|
|
865
913
|
path = get_snl_path_from_id_list(self.pathIDs)
|
|
866
914
|
if path.size() > 0:
|
|
867
915
|
snl.SNLUniquifier(path)
|
|
@@ -871,6 +919,7 @@ class Instance:
|
|
|
871
919
|
return Net(path, newSNLNet)
|
|
872
920
|
|
|
873
921
|
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."""
|
|
874
923
|
path = get_snl_path_from_id_list(self.pathIDs)
|
|
875
924
|
if path.size() > 0:
|
|
876
925
|
snl.SNLUniquifier(path)
|
|
@@ -880,6 +929,7 @@ class Instance:
|
|
|
880
929
|
return Net(path, newSNLNet)
|
|
881
930
|
|
|
882
931
|
def dump_verilog(self, path: str, name: str):
|
|
932
|
+
"""Dump the verilog of this instance."""
|
|
883
933
|
self.__get_snl_model().dumpVerilog(path, name)
|
|
884
934
|
|
|
885
935
|
|
najaeda/stats.py
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2024 The Naja authors <https://github.com/najaeda/naja/blob/main/AUTHORS>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from najaeda import netlist
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DesignsStats:
|
|
10
|
+
def __init__(self):
|
|
11
|
+
self.blackboxes = dict()
|
|
12
|
+
self.hier_designs = dict()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DesignStats:
|
|
16
|
+
def __init__(self):
|
|
17
|
+
self.name = ""
|
|
18
|
+
self.assigns = 0
|
|
19
|
+
self.flat_assigns = 0
|
|
20
|
+
self.basic_primitives = dict()
|
|
21
|
+
self.primitives = dict()
|
|
22
|
+
self.flat_basic_primitives = dict()
|
|
23
|
+
self.flat_primitives = dict()
|
|
24
|
+
self.blackboxes = dict()
|
|
25
|
+
self.flat_blackboxes = dict()
|
|
26
|
+
self.ins = dict()
|
|
27
|
+
self.flat_ins = dict()
|
|
28
|
+
self.terms = dict()
|
|
29
|
+
self.bit_terms = dict()
|
|
30
|
+
self.net_stats = dict()
|
|
31
|
+
|
|
32
|
+
def add_ins_stats(self, ins_stats):
|
|
33
|
+
self.flat_assigns += ins_stats.flat_assigns
|
|
34
|
+
for ins, nb in ins_stats.flat_ins.items():
|
|
35
|
+
self.flat_ins[ins] = self.flat_ins.get(ins, 0) + nb
|
|
36
|
+
for ins, nb in ins_stats.flat_blackboxes.items():
|
|
37
|
+
self.flat_blackboxes[ins] = self.flat_blackboxes.get(ins, 0) + nb
|
|
38
|
+
for primitive, nb in ins_stats.flat_primitives.items():
|
|
39
|
+
self.flat_primitives[primitive] = (
|
|
40
|
+
self.flat_primitives.get(primitive, 0) + nb
|
|
41
|
+
)
|
|
42
|
+
for primitive, nb in ins_stats.flat_basic_primitives.items():
|
|
43
|
+
self.flat_basic_primitives[primitive] = (
|
|
44
|
+
self.flat_basic_primitives.get(primitive, 0) + nb
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def is_basic_primitive(design):
|
|
49
|
+
return (
|
|
50
|
+
design.is_const0() or design.is_const1() or design.is_buf() or design.is_inv()
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def compute_design_stats(design, designs_stats):
|
|
55
|
+
if design.get_model_id() in designs_stats.hier_designs:
|
|
56
|
+
return designs_stats.hier_designs.get(design.get_model_id())
|
|
57
|
+
design_stats = DesignStats()
|
|
58
|
+
design_stats.name = design.get_model_name()
|
|
59
|
+
for ins in design.get_child_instances():
|
|
60
|
+
model_id = ins.get_model_id()
|
|
61
|
+
if ins.is_assign():
|
|
62
|
+
design_stats.assigns += 1
|
|
63
|
+
design_stats.flat_assigns += 1
|
|
64
|
+
elif ins.is_primitive():
|
|
65
|
+
if is_basic_primitive(ins):
|
|
66
|
+
design_stats.basic_primitives[model_id] = (
|
|
67
|
+
design_stats.basic_primitives.get(model_id, 0) + 1
|
|
68
|
+
)
|
|
69
|
+
design_stats.flat_basic_primitives[model_id] = (
|
|
70
|
+
design_stats.flat_basic_primitives.get(model_id, 0) + 1
|
|
71
|
+
)
|
|
72
|
+
else:
|
|
73
|
+
design_stats.primitives[model_id] = (
|
|
74
|
+
design_stats.primitives.get(model_id, 0) + 1
|
|
75
|
+
)
|
|
76
|
+
design_stats.flat_primitives[model_id] = (
|
|
77
|
+
design_stats.flat_primitives.get(model_id, 0) + 1
|
|
78
|
+
)
|
|
79
|
+
elif ins.is_blackbox():
|
|
80
|
+
design_stats.blackboxes[model_id] = (
|
|
81
|
+
design_stats.blackboxes.get(model_id, 0) + 1
|
|
82
|
+
)
|
|
83
|
+
design_stats.flat_blackboxes[model_id] = (
|
|
84
|
+
design_stats.flat_blackboxes.get(model_id, 0) + 1
|
|
85
|
+
)
|
|
86
|
+
if model_id not in designs_stats.blackboxes:
|
|
87
|
+
designs_stats.blackboxes[model_id] = dict()
|
|
88
|
+
compute_design_terms(model_id, designs_stats.blackboxes[model_id])
|
|
89
|
+
else:
|
|
90
|
+
if model_id in designs_stats.hier_designs:
|
|
91
|
+
model_stats = designs_stats.hier_designs[model_id]
|
|
92
|
+
else:
|
|
93
|
+
model_stats = compute_design_stats(ins, designs_stats)
|
|
94
|
+
design_stats.ins[model_id] = design_stats.ins.get(model_id, 0) + 1
|
|
95
|
+
design_stats.flat_ins[model_id] = design_stats.flat_ins.get(model_id, 0) + 1
|
|
96
|
+
design_stats.add_ins_stats(model_stats)
|
|
97
|
+
compute_design_terms(design, design_stats)
|
|
98
|
+
compute_design_net_stats(design, design_stats)
|
|
99
|
+
designs_stats.hier_designs[design.get_model_id()] = design_stats
|
|
100
|
+
return design_stats
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def compute_design_terms(design, design_stats):
|
|
104
|
+
for term in design.get_terms():
|
|
105
|
+
if term.get_direction() == netlist.Term.INPUT:
|
|
106
|
+
design_stats.terms["inputs"] = design_stats.terms.get("inputs", 0) + 1
|
|
107
|
+
bit_terms = sum(1 for _ in term.get_bits())
|
|
108
|
+
design_stats.bit_terms["inputs"] = (
|
|
109
|
+
design_stats.bit_terms.get("inputs", 0) + bit_terms
|
|
110
|
+
)
|
|
111
|
+
elif term.get_direction() == netlist.Term.OUTPUT:
|
|
112
|
+
design_stats.terms["outputs"] = design_stats.terms.get("outputs", 0) + 1
|
|
113
|
+
bit_terms = sum(1 for _ in term.get_bits())
|
|
114
|
+
design_stats.bit_terms["outputs"] = (
|
|
115
|
+
design_stats.bit_terms.get("outputs", 0) + bit_terms
|
|
116
|
+
)
|
|
117
|
+
elif term.get_direction() == netlist.Term.INOUT:
|
|
118
|
+
design_stats.terms["inouts"] = design_stats.terms.get("inouts", 0) + 1
|
|
119
|
+
bit_terms = sum(1 for _ in term.get_bits())
|
|
120
|
+
design_stats.bit_terms["inouts"] = (
|
|
121
|
+
design_stats.bit_terms.get("inouts", 0) + bit_terms
|
|
122
|
+
)
|
|
123
|
+
else:
|
|
124
|
+
design_stats.terms["unknowns"] = design_stats.terms.get("unknowns", 0) + 1
|
|
125
|
+
bit_terms = sum(1 for _ in term.get_bits())
|
|
126
|
+
design_stats.bit_terms["unknowns"] = (
|
|
127
|
+
design_stats.bit_terms.get("unknowns", 0) + bit_terms
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def compute_design_net_stats(design, design_stats):
|
|
132
|
+
for net in design.get_flat_nets():
|
|
133
|
+
if net.is_const():
|
|
134
|
+
pass
|
|
135
|
+
nb_components = sum(1 for c in net.get_terms())
|
|
136
|
+
design_stats.net_stats[nb_components] = (
|
|
137
|
+
design_stats.net_stats.get(nb_components, 0) + 1
|
|
138
|
+
)
|
|
139
|
+
design_stats.net_stats = dict(sorted(design_stats.net_stats.items()))
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def dump_instances(stats_file, title, instances):
|
|
143
|
+
if len(instances) == 0:
|
|
144
|
+
return
|
|
145
|
+
sorted_instances = sorted(
|
|
146
|
+
instances.items(), key=lambda item: netlist.get_model_name(item[0])
|
|
147
|
+
)
|
|
148
|
+
stats_file.write(title + " " + str(sum(j for i, j in sorted_instances)) + "\n")
|
|
149
|
+
line_char = 0
|
|
150
|
+
for instance in sorted_instances:
|
|
151
|
+
model_name = netlist.get_model_name(instance[0])
|
|
152
|
+
if line_char != 0:
|
|
153
|
+
stats_file.write(",")
|
|
154
|
+
line_char += 1
|
|
155
|
+
if line_char > 80:
|
|
156
|
+
stats_file.write("\n")
|
|
157
|
+
line_char = 0
|
|
158
|
+
elif line_char != 0:
|
|
159
|
+
stats_file.write(" ")
|
|
160
|
+
line_char += 1
|
|
161
|
+
instance_char = model_name + ":" + str(instance[1])
|
|
162
|
+
line_char += len(instance_char)
|
|
163
|
+
stats_file.write(instance_char)
|
|
164
|
+
stats_file.write("\n\n")
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def dump_blackboxes_stats(stats_file, design_stats):
|
|
168
|
+
if len(design_stats.blackboxes) > 0:
|
|
169
|
+
stats_file.write("*** BlackBoxes ***\n")
|
|
170
|
+
for bbox in design_stats.blackboxes.items():
|
|
171
|
+
design = bbox[0]
|
|
172
|
+
design_terms = bbox[1]
|
|
173
|
+
stats_file.write("*** " + design.getName() + " ***\n")
|
|
174
|
+
if len(design_terms) > 0:
|
|
175
|
+
stats_file.write("Terms: ")
|
|
176
|
+
first = True
|
|
177
|
+
for terms in design_terms.items():
|
|
178
|
+
if not first:
|
|
179
|
+
stats_file.write(", ")
|
|
180
|
+
else:
|
|
181
|
+
first = False
|
|
182
|
+
stats_file.write(terms[0] + ":" + str(terms[1]))
|
|
183
|
+
stats_file.write("\n")
|
|
184
|
+
stats_file.write("\n")
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def dump_stats(design, stats_file, designs_stats, dumped_models):
|
|
188
|
+
if design.is_primitive() or design.is_blackbox():
|
|
189
|
+
return
|
|
190
|
+
if design in dumped_models:
|
|
191
|
+
return
|
|
192
|
+
dumped_models.add(design)
|
|
193
|
+
stats_file.write("*** " + design.get_name() + " ***\n")
|
|
194
|
+
design_stats = designs_stats.hier_designs.get(design.get_model_id())
|
|
195
|
+
if design_stats is None:
|
|
196
|
+
print("Cannot find " + str(design) + " in design_stats")
|
|
197
|
+
raise
|
|
198
|
+
if len(design_stats.terms) > 0:
|
|
199
|
+
stats_file.write("Terms: ")
|
|
200
|
+
first = True
|
|
201
|
+
for terms in design_stats.terms.items():
|
|
202
|
+
if not first:
|
|
203
|
+
stats_file.write(", ")
|
|
204
|
+
else:
|
|
205
|
+
first = False
|
|
206
|
+
stats_file.write(terms[0] + ":" + str(terms[1]))
|
|
207
|
+
stats_file.write("\n")
|
|
208
|
+
|
|
209
|
+
dump_instances(stats_file, "Instances:", design_stats.ins)
|
|
210
|
+
nb_primitives = sum(design_stats.basic_primitives.values()) + sum(
|
|
211
|
+
design_stats.primitives.values()
|
|
212
|
+
)
|
|
213
|
+
if nb_primitives > 1:
|
|
214
|
+
stats_file.write("Primitives: " + str(nb_primitives) + "\n")
|
|
215
|
+
dump_instances(stats_file, "Simple Primitives:", design_stats.basic_primitives)
|
|
216
|
+
dump_instances(stats_file, "Other Primitives:", design_stats.primitives)
|
|
217
|
+
dump_instances(stats_file, "Blackboxes:", design_stats.blackboxes)
|
|
218
|
+
if design_stats.assigns > 0:
|
|
219
|
+
stats_file.write("Assigns: " + str(design_stats.assigns) + "\n")
|
|
220
|
+
dump_instances(stats_file, "Flat Instances:", design_stats.flat_ins)
|
|
221
|
+
dump_instances(stats_file, "Flat Blackboxes:", design_stats.flat_blackboxes)
|
|
222
|
+
nb_primitives = sum(design_stats.flat_basic_primitives.values()) + sum(
|
|
223
|
+
design_stats.flat_primitives.values()
|
|
224
|
+
)
|
|
225
|
+
if nb_primitives > 1:
|
|
226
|
+
stats_file.write("Flat Primitives: " + str(nb_primitives) + "\n")
|
|
227
|
+
dump_instances(
|
|
228
|
+
stats_file, "Flat Simple Primitives:", design_stats.flat_basic_primitives
|
|
229
|
+
)
|
|
230
|
+
dump_instances(stats_file, "Flat Other Primitives:", design_stats.flat_primitives)
|
|
231
|
+
if design_stats.flat_assigns > 0:
|
|
232
|
+
stats_file.write("Flat Assigns: " + str(design_stats.flat_assigns) + "\n")
|
|
233
|
+
stats_file.write("\n")
|
|
234
|
+
for ins in design.get_child_instances():
|
|
235
|
+
dump_stats(ins, stats_file, designs_stats, dumped_models)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# def dump_pandas(designs_stats):
|
|
239
|
+
# import pandas
|
|
240
|
+
# import matplotlib.pyplot as plt
|
|
241
|
+
#
|
|
242
|
+
# #create a figures directory erase the previous one
|
|
243
|
+
# if os.path.exists('figures'):
|
|
244
|
+
# import shutil
|
|
245
|
+
# shutil.rmtree('figures')
|
|
246
|
+
# os.makedirs('figures')
|
|
247
|
+
#
|
|
248
|
+
# data = []
|
|
249
|
+
# for design, design_stats in designs_stats.hier_designs.items():
|
|
250
|
+
# data.append([
|
|
251
|
+
# design.getName(),
|
|
252
|
+
# sum(design_stats.terms.values()),
|
|
253
|
+
# sum(design_stats.bit_terms.values()),
|
|
254
|
+
# sum(design_stats.basic_primitives.values()),
|
|
255
|
+
# sum(design_stats.primitives.values()),
|
|
256
|
+
# sum(design_stats.blackboxes.values()),
|
|
257
|
+
# sum(design_stats.ins.values()),
|
|
258
|
+
# sum(design_stats.flat_ins.values()),
|
|
259
|
+
# sum(design_stats.flat_blackboxes.values()),
|
|
260
|
+
# sum(design_stats.flat_basic_primitives.values()),
|
|
261
|
+
# sum(design_stats.flat_primitives.values())])
|
|
262
|
+
# df = pandas.DataFrame(data, columns=[
|
|
263
|
+
# 'Design', 'Terms', 'Bit Terms',
|
|
264
|
+
# 'Basic Primitives', 'Primitives', 'Blackboxes', 'Instances',
|
|
265
|
+
# 'Flat Instances', 'Flat Blackboxes',
|
|
266
|
+
# 'Flat Basic Primitives', 'Flat Primitives'])
|
|
267
|
+
# df.to_csv('figures/designs_stats.csv', index=False)
|
|
268
|
+
#
|
|
269
|
+
# net_series = pandas.Series(design_stats.net_stats)
|
|
270
|
+
# nets_plot = net_series.plot(kind='bar',
|
|
271
|
+
# title='Number of nets with a given number of components for\n' + design.getName(),
|
|
272
|
+
# xlabel='number of components', ylabel='number of nets')
|
|
273
|
+
# nets_plot.set_yscale('log')
|
|
274
|
+
# nets_plot.xaxis.set_major_locator(plt.MaxNLocator(100))
|
|
275
|
+
# nets_figure = nets_plot.get_figure()
|
|
276
|
+
# nets_figure.tight_layout()
|
|
277
|
+
# nets_figure.savefig('figures/nets_' + design.getName() + '.png')
|
|
278
|
+
#
|
|
279
|
+
# flat_primitives_series = pandas.Series(design_stats.flat_primitives)
|
|
280
|
+
# primitives_plot = flat_primitives_series.plot(kind='bar',
|
|
281
|
+
# title='Number of primitives for\n' + design.getName(),
|
|
282
|
+
# xlabel='primitive', ylabel='number of flat instances')
|
|
283
|
+
# primitives_plot.set_yscale('log')
|
|
284
|
+
# primitives_figure = primitives_plot.get_figure()
|
|
285
|
+
# primitives_figure.tight_layout()
|
|
286
|
+
# primitives_figure.savefig('figures/flat_primitives_' + design.getName() + '.png')
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def compute_and_dump_design_stats(design, stats_file, with_pandas=False):
|
|
290
|
+
designs_stats = DesignsStats()
|
|
291
|
+
compute_design_stats(design, designs_stats)
|
|
292
|
+
dumped_models = set()
|
|
293
|
+
dump_stats(design, stats_file, designs_stats, dumped_models)
|
|
294
|
+
dump_blackboxes_stats(stats_file, designs_stats)
|
|
295
|
+
# if with_pandas:
|
|
296
|
+
# dump_pandas(designs_stats)
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def dump_constants(design, analyzed_models):
|
|
300
|
+
if design.isPrimitive():
|
|
301
|
+
return
|
|
302
|
+
if design in analyzed_models:
|
|
303
|
+
return
|
|
304
|
+
analyzed_models.add(design)
|
|
305
|
+
for bitnet in design.getBitNets():
|
|
306
|
+
if bitnet.isConstant():
|
|
307
|
+
message = f"In design {design.getName()}, \
|
|
308
|
+
constant net {bitnet.getName()} \
|
|
309
|
+
of type {bitnet.getTypeAsString()}"
|
|
310
|
+
logging.info(message)
|
|
311
|
+
if all(False for _ in bitnet.getComponents()):
|
|
312
|
+
logging.info(" with zero connections\n")
|
|
313
|
+
else:
|
|
314
|
+
logging.info(" connected to:\n")
|
|
315
|
+
for component in bitnet.getComponents():
|
|
316
|
+
logging.info(str(component) + "\n")
|
|
317
|
+
|
|
318
|
+
for ins in design.getInstances():
|
|
319
|
+
model = ins.getModel()
|
|
320
|
+
dump_constants(model, analyzed_models)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: najaeda
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
4
4
|
Summary: Naja EDA Python package
|
|
5
5
|
Author-Email: Naja Authors <contact@keplertech.io>
|
|
6
6
|
License: Apache License 2.0
|
|
@@ -54,6 +54,11 @@ Install Naja EDA using pip:
|
|
|
54
54
|
|
|
55
55
|
pip install najaeda
|
|
56
56
|
|
|
57
|
+
Documentation
|
|
58
|
+
-------------
|
|
59
|
+
|
|
60
|
+
Naja EDA online documentation is available `here <https://najaeda.readthedocs.io/en/latest/index.html>`_.
|
|
61
|
+
|
|
57
62
|
Examples
|
|
58
63
|
--------
|
|
59
64
|
|
|
@@ -92,7 +97,7 @@ easily extended in the future. Don't hesitate to reach out if you need help.
|
|
|
92
97
|
|
|
93
98
|
netlist.load_primitives('xilinx')
|
|
94
99
|
benchmarks = path.join('..','benchmarks')
|
|
95
|
-
top = netlist.load_verilog([path.join(benchmarks, 'verilog', '
|
|
100
|
+
top = netlist.load_verilog([path.join(benchmarks, 'verilog', 'vexriscv.v')])
|
|
96
101
|
|
|
97
102
|
Print all the instances in the netlist
|
|
98
103
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
najaeda-0.1.8.dist-info/RECORD,,
|
|
2
|
+
najaeda-0.1.8.dist-info/WHEEL,sha256=rOJaAfyDeYqpyZcvF2uMKwvjCoDaR0tVOjIX1nCiRq8,114
|
|
3
|
+
najaeda-0.1.8.dist-info/METADATA,sha256=Gs7f1HbI7hS--g6TbdjGTvnIa85u8WDsmFnAHdslz2g,6880
|
|
4
|
+
najaeda-0.1.8.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
5
|
+
najaeda-0.1.8.dist-info/licenses/AUTHORS,sha256=7NYEGDAX_1QZvCCHfq8YVXC5ZbwH_pbNI8DcSmm70GU,377
|
|
6
|
+
najaeda/netlist.py,sha256=xcn-v5Vhjt1di8yDJV5T9SKpKIkyXKRnodBzP50RiCw,37044
|
|
7
|
+
najaeda/libnaja_snl_python.dylib,sha256=QPhv3dnV7usAOptZ1r3E2xXvQBF8Jd0OtljA0x69X84,808208
|
|
8
|
+
najaeda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
najaeda/libnaja_snl.dylib,sha256=AFqR64aX6KnzkX6lrLGCuscx2f5E07umNC_7E9cNrT0,574272
|
|
10
|
+
najaeda/snl.so,sha256=d9W9rNMzNl0T88DpH7thDuP3NK6nyVgJYXYKx3Uxm7I,97888
|
|
11
|
+
najaeda/stats.py,sha256=9taIJ2ns8E8W_Cm9xThq9-S6Gr6TMPb7qLTJPfx4jFk,12891
|
|
12
|
+
najaeda/instance_visitor.py,sha256=2HnQ5y8-0tSOKd9nS4WYiypccQWLJgKfs84wp357Tls,1781
|
|
13
|
+
najaeda/docs/requirements.txt,sha256=1XIBGTIplm2arC9HhDCfLuAjozGdVSXkqmOj8ybuT6U,121
|
|
14
|
+
najaeda/docs/Makefile,sha256=4zv3TVkTACm6JBaKgTES3ZI9cETXgM6ULbZkXZP1as8,638
|
|
15
|
+
najaeda/docs/make.bat,sha256=L4I5T7uDUIjwGyMRJ-y9FoT61sxIyCuaYuJyLt8c-nA,804
|
|
16
|
+
najaeda/docs/.readthedocs.yaml,sha256=TL2hK9gR25hw-7_gMeywIqBikAP0mVPRB-O4wGfrdPU,900
|
|
17
|
+
najaeda/docs/source/index.rst,sha256=nYkctDLuoue7UMQi5gV-PARChvJDb_3P4e_9NTqzJtc,367
|
|
18
|
+
najaeda/docs/source/instance.rst,sha256=uqyHR7dN9po3sN_APC3C8vk7W2MT0ca49memgtFpzCk,517
|
|
19
|
+
najaeda/docs/source/conf.py,sha256=GIJ89oFBSXucgDBXLcyyWC-cU_lC3GvfswnmLxm9pVM,1387
|
|
20
|
+
najaeda/docs/source/term.rst,sha256=Xh4xis6lR_Oe26Qm3vCt7ziU3PR0cKBBGO8OmCHWt0M,341
|
|
21
|
+
najaeda/docs/source/net.rst,sha256=QNkCZp1bp8_h_fUcf4jwPF4DByZmMtiSb56gOki0wSI,331
|
|
22
|
+
najaeda/docs/source/equipotential.rst,sha256=1wG1sbwexs9JhxxSY2z9XucsLE0SfopVK7VIty0r3mw,431
|
|
23
|
+
najaeda/docs/source/api.rst,sha256=P_-1jiVrIajvFCqP1Wx2W1l6a4T2RHXlWG00rls1qF0,159
|
|
24
|
+
najaeda/primitives/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
|
+
najaeda/primitives/xilinx.py,sha256=fuu4KxEIuC0ueCK4C_gds6hzgtJsLE3tjDtOHtY9McM,25947
|
najaeda/docs/conf.py
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
#...
|
|
2
|
-
#extensions = [
|
|
3
|
-
# "breathe",
|
|
4
|
-
# 'sphinx_rtd_theme',
|
|
5
|
-
#]
|
|
6
|
-
#...
|
|
7
|
-
|
|
8
|
-
project = 'najaeda'
|
|
9
|
-
copyright = '2023, The Naja authors'
|
|
10
|
-
author = 'The Naja authors'
|
|
11
|
-
|
|
12
|
-
html_theme = "sphinx_rtd_theme"
|
|
13
|
-
html_title = "najaeda Documentation"
|
|
14
|
-
|
|
15
|
-
breathe_default_project = "najaeda"
|
|
16
|
-
|
|
17
|
-
#import os
|
|
18
|
-
#if 'IN_READ_THE_DOCS' in os.environ:
|
|
19
|
-
# import subprocess
|
|
20
|
-
# #call doxygen from cmake
|
|
21
|
-
# subprocess.call('mkdir build', shell=True)
|
|
22
|
-
# subprocess.call('cd build; cmake ../.. -DBUILD_ONLY_DOC=ON', shell=True)
|
|
23
|
-
# subprocess.call('cd build; make docs', shell=True)
|
|
24
|
-
# subprocess.call('cd build/docs; pwd; ls -all', shell=True)
|
|
25
|
-
#
|
|
26
|
-
#breathe_projects = { "najaeda" : "./build/docs/xml/" }
|
najaeda-0.1.7.dist-info/RECORD
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
najaeda/netlist.py,sha256=_ojRBNwyvfcrsuoNRpCc1LCIo6uzFQSQcmaTR7qvOQc,34660
|
|
2
|
-
najaeda/libnaja_snl_python.dylib,sha256=NqVz2Bm-W16xZgwNvQ7gXbWZ9wQMaibR9hcW5IsHvDU,741024
|
|
3
|
-
najaeda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
najaeda/libnaja_snl.dylib,sha256=AFqR64aX6KnzkX6lrLGCuscx2f5E07umNC_7E9cNrT0,574272
|
|
5
|
-
najaeda/snl.so,sha256=d9W9rNMzNl0T88DpH7thDuP3NK6nyVgJYXYKx3Uxm7I,97888
|
|
6
|
-
najaeda/instance_visitor.py,sha256=2HnQ5y8-0tSOKd9nS4WYiypccQWLJgKfs84wp357Tls,1781
|
|
7
|
-
najaeda/docs/Makefile,sha256=4zv3TVkTACm6JBaKgTES3ZI9cETXgM6ULbZkXZP1as8,638
|
|
8
|
-
najaeda/docs/conf.py,sha256=XmqDjqssSJswFPmC7RhVS_dYKOjzML4UmrbhUowF78M,653
|
|
9
|
-
najaeda/docs/make.bat,sha256=L4I5T7uDUIjwGyMRJ-y9FoT61sxIyCuaYuJyLt8c-nA,804
|
|
10
|
-
najaeda/docs/.readthedocs.yaml,sha256=yP012ik240oBTMApJYBOvjhNzFDzsAI4vmqX1R7KDrA,988
|
|
11
|
-
najaeda/docs/source/index.rst,sha256=VBWfJySZ9v8mWfWt3kuSCZh7Gp0zUrFjXGQH7tZZfy0,323
|
|
12
|
-
najaeda/docs/source/conf.py,sha256=3qkykCg12ZYqawHl8VEg2Fti6rc3G-soGYM0L6zL3CU,1387
|
|
13
|
-
najaeda/docs/source/api.rst,sha256=H2Bw0JmHS9z-NhQARepmH74wsWHzjSVPbeXppSmtgCQ,141
|
|
14
|
-
najaeda/primitives/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
-
najaeda/primitives/xilinx.py,sha256=fuu4KxEIuC0ueCK4C_gds6hzgtJsLE3tjDtOHtY9McM,25947
|
|
16
|
-
najaeda-0.1.7.dist-info/RECORD,,
|
|
17
|
-
najaeda-0.1.7.dist-info/WHEEL,sha256=rOJaAfyDeYqpyZcvF2uMKwvjCoDaR0tVOjIX1nCiRq8,114
|
|
18
|
-
najaeda-0.1.7.dist-info/METADATA,sha256=4ac4lOScunYkRke1pZTzxQiLM3XwMGQxbekUHq2PMdw,6752
|
|
19
|
-
najaeda-0.1.7.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
20
|
-
najaeda-0.1.7.dist-info/licenses/AUTHORS,sha256=7NYEGDAX_1QZvCCHfq8YVXC5ZbwH_pbNI8DcSmm70GU,377
|
|
File without changes
|
|
File without changes
|
|
File without changes
|