najaeda 0.1.2__cp310-cp310-macosx_11_0_arm64.whl → 0.1.3__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/libnaja_snl_python.dylib +0 -0
- najaeda/netlist.py +186 -97
- {najaeda-0.1.2.dist-info → najaeda-0.1.3.dist-info}/METADATA +18 -14
- najaeda-0.1.3.dist-info/RECORD +11 -0
- najaeda-0.1.2.dist-info/RECORD +0 -11
- {najaeda-0.1.2.dist-info → najaeda-0.1.3.dist-info}/WHEEL +0 -0
- {najaeda-0.1.2.dist-info → najaeda-0.1.3.dist-info}/licenses/AUTHORS +0 -0
- {najaeda-0.1.2.dist-info → najaeda-0.1.3.dist-info}/licenses/LICENSE +0 -0
najaeda/libnaja_snl_python.dylib
CHANGED
|
Binary file
|
najaeda/netlist.py
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
|
|
6
6
|
import itertools
|
|
7
|
+
import logging
|
|
8
|
+
|
|
7
9
|
from najaeda import snl
|
|
8
10
|
|
|
9
11
|
|
|
@@ -46,102 +48,121 @@ class Equipotential:
|
|
|
46
48
|
|
|
47
49
|
|
|
48
50
|
class Net:
|
|
49
|
-
def __init__(self, path, net):
|
|
51
|
+
def __init__(self, path, net=None, net_concat=None):
|
|
52
|
+
if net is not None and net_concat is not None:
|
|
53
|
+
raise ValueError(
|
|
54
|
+
"Only one of `net` or `net_concat` should be provided, not both."
|
|
55
|
+
)
|
|
50
56
|
self.path = path
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def __ne__(self, value):
|
|
57
|
-
return not self == value
|
|
58
|
-
|
|
59
|
-
def __lt__(self, value):
|
|
60
|
-
if self.path != value.path:
|
|
61
|
-
return self.path < value.path
|
|
62
|
-
return self.net < value.net
|
|
63
|
-
|
|
64
|
-
def __le__(self, value):
|
|
65
|
-
if self.path != value.path:
|
|
66
|
-
return self.path < value.path
|
|
67
|
-
return self.net <= value.net
|
|
57
|
+
if net is not None:
|
|
58
|
+
self.net = net
|
|
59
|
+
elif net_concat is not None:
|
|
60
|
+
self.net_concat = net_concat
|
|
68
61
|
|
|
69
|
-
def
|
|
70
|
-
if
|
|
71
|
-
return
|
|
72
|
-
return self
|
|
62
|
+
def __eq__(self, other):
|
|
63
|
+
if not isinstance(other, Net):
|
|
64
|
+
return NotImplemented
|
|
65
|
+
return vars(self) == vars(other)
|
|
73
66
|
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
67
|
+
def __ne__(self, other):
|
|
68
|
+
eq_result = self.__eq__(other)
|
|
69
|
+
if eq_result is NotImplemented:
|
|
70
|
+
return NotImplemented
|
|
71
|
+
return not eq_result
|
|
78
72
|
|
|
79
73
|
def __str__(self):
|
|
74
|
+
if hasattr(self, "net"):
|
|
75
|
+
net_str = str(self.net)
|
|
76
|
+
elif hasattr(self, "net_concat"):
|
|
77
|
+
net_str = "{" + ",".join(map(str, self.net_concat)) + "}"
|
|
80
78
|
if self.path.size() > 0:
|
|
81
|
-
return f"{self.path}/{
|
|
82
|
-
return
|
|
83
|
-
|
|
84
|
-
def __repr__(self):
|
|
85
|
-
return f"Net({self.path}, {self.net})"
|
|
79
|
+
return f"{self.path}/{net_str}"
|
|
80
|
+
return net_str
|
|
86
81
|
|
|
87
82
|
def get_name(self) -> str:
|
|
88
83
|
"""Return the name of the net."""
|
|
89
|
-
|
|
84
|
+
if hasattr(self, "net"):
|
|
85
|
+
return self.net.getName()
|
|
86
|
+
return "{" + ",".join(map(str, self.net_concat)) + "}"
|
|
90
87
|
|
|
91
88
|
def get_msb(self) -> int:
|
|
92
89
|
"""Return the most significant bit of the net if it is a bus."""
|
|
93
|
-
if isinstance(self.net, snl.SNLBusNet):
|
|
90
|
+
if hasattr(self, "net") and isinstance(self.net, snl.SNLBusNet):
|
|
94
91
|
return self.net.getMSB()
|
|
95
92
|
return None
|
|
96
93
|
|
|
97
94
|
def get_lsb(self) -> int:
|
|
98
95
|
"""Return the least significant bit of the net if it is a bus."""
|
|
99
|
-
if isinstance(self.net, snl.SNLBusNet):
|
|
96
|
+
if hasattr(self, "net") and isinstance(self.net, snl.SNLBusNet):
|
|
100
97
|
return self.net.getLSB()
|
|
101
98
|
return None
|
|
102
99
|
|
|
103
100
|
def is_bus(self) -> bool:
|
|
104
101
|
"""Return True if the net is a bus."""
|
|
105
|
-
return isinstance(self.net, snl.SNLBusNet)
|
|
102
|
+
return hasattr(self, "net") and isinstance(self.net, snl.SNLBusNet)
|
|
106
103
|
|
|
107
104
|
def is_bus_bit(self) -> bool:
|
|
108
105
|
"""Return True if the net is a bit of a bus."""
|
|
109
|
-
return isinstance(self.net, snl.SNLBusNetBit)
|
|
106
|
+
return hasattr(self, "net") and isinstance(self.net, snl.SNLBusNetBit)
|
|
110
107
|
|
|
111
108
|
def is_scalar(self) -> bool:
|
|
112
109
|
"""Return True if the net is a scalar."""
|
|
113
|
-
return isinstance(self.net, snl.SNLScalarNet)
|
|
110
|
+
return hasattr(self, "net") and isinstance(self.net, snl.SNLScalarNet)
|
|
114
111
|
|
|
115
112
|
def is_bit(self) -> bool:
|
|
116
113
|
"""Return True if the net is a bit."""
|
|
117
114
|
return self.is_scalar() or self.is_bus_bit()
|
|
118
115
|
|
|
119
|
-
def
|
|
116
|
+
def is_concat(self) -> bool:
|
|
117
|
+
"""Return True if the net is a concatenation."""
|
|
118
|
+
return hasattr(self, "net_concat")
|
|
119
|
+
|
|
120
|
+
def is_const(self) -> bool:
|
|
120
121
|
"""Return True if the net is a constant generator."""
|
|
121
|
-
|
|
122
|
+
if hasattr(self, "net"):
|
|
123
|
+
return self.net.isConstant()
|
|
124
|
+
for net in self.net_concat:
|
|
125
|
+
if not net.isConstant():
|
|
126
|
+
return False
|
|
127
|
+
return True
|
|
122
128
|
|
|
123
129
|
def get_width(self) -> int:
|
|
124
130
|
"""Return the width of the net."""
|
|
125
|
-
|
|
131
|
+
if hasattr(self, "net"):
|
|
132
|
+
return self.net.getWidth()
|
|
133
|
+
return sum(1 for _ in self.net_concat)
|
|
126
134
|
|
|
127
135
|
def get_bits(self):
|
|
128
|
-
if
|
|
129
|
-
|
|
130
|
-
|
|
136
|
+
if hasattr(self, "net"):
|
|
137
|
+
if isinstance(self.net, snl.SNLBusNet):
|
|
138
|
+
for bit in self.net.getBits():
|
|
139
|
+
yield Net(self.path, bit)
|
|
140
|
+
else:
|
|
141
|
+
yield self
|
|
131
142
|
else:
|
|
132
|
-
|
|
143
|
+
for net in self.net_concat:
|
|
144
|
+
yield net
|
|
133
145
|
|
|
134
146
|
def get_bit(self, index: int):
|
|
135
|
-
if
|
|
136
|
-
|
|
147
|
+
if hasattr(self, "net"):
|
|
148
|
+
if isinstance(self.net, snl.SNLBusNet):
|
|
149
|
+
return Net(self.path, self.net.getBit(index))
|
|
150
|
+
else:
|
|
151
|
+
return None
|
|
152
|
+
if 0 <= index < len(self.net_concat):
|
|
153
|
+
return Net(self.path, self.net_concat[index])
|
|
137
154
|
return None
|
|
138
155
|
|
|
139
156
|
def get_inst_terms(self):
|
|
157
|
+
if hasattr(self, "net_concat"):
|
|
158
|
+
raise ValueError("Cannot get inst terms from a net_concat")
|
|
140
159
|
for term in self.net.getInstTerms():
|
|
141
160
|
path = snl.SNLPath(self.path, term.getInstance())
|
|
142
161
|
yield Term(path, term.getBitTerm())
|
|
143
162
|
|
|
144
163
|
def get_terms(self):
|
|
164
|
+
if hasattr(self, "net_concat"):
|
|
165
|
+
raise ValueError("Cannot get terms from a net_concat")
|
|
145
166
|
for term in self.net.getBitTerms():
|
|
146
167
|
yield Term(self.path, term)
|
|
147
168
|
|
|
@@ -151,9 +172,9 @@ class Net:
|
|
|
151
172
|
|
|
152
173
|
|
|
153
174
|
class Term:
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
175
|
+
INPUT = snl.SNLTerm.Direction.Input
|
|
176
|
+
OUTPUT = snl.SNLTerm.Direction.Output
|
|
177
|
+
INOUT = snl.SNLTerm.Direction.InOut
|
|
157
178
|
|
|
158
179
|
def __init__(self, path, term):
|
|
159
180
|
self.path = path
|
|
@@ -179,15 +200,19 @@ class Term:
|
|
|
179
200
|
def __ge__(self, other) -> bool:
|
|
180
201
|
return not self < other
|
|
181
202
|
|
|
182
|
-
def __str__(self)
|
|
183
|
-
|
|
203
|
+
def __str__(self):
|
|
204
|
+
if self.path.size() == 0:
|
|
205
|
+
return self.term.getName()
|
|
206
|
+
else:
|
|
207
|
+
return f"{self.path}/{self.term}"
|
|
184
208
|
|
|
185
209
|
def __repr__(self) -> str:
|
|
186
210
|
return f"Term({self.path}, {self.term})"
|
|
187
211
|
|
|
188
212
|
def __make_unique(self):
|
|
189
|
-
if self.path.size() >
|
|
190
|
-
|
|
213
|
+
if self.path.size() > 1:
|
|
214
|
+
path = self.path.getHeadPath()
|
|
215
|
+
snl.SNLUniquifier(path)
|
|
191
216
|
if self.is_bus_bit():
|
|
192
217
|
term = (
|
|
193
218
|
self.path.getTailInstance().getModel().getTerm(self.term.getName())
|
|
@@ -237,24 +262,74 @@ class Term:
|
|
|
237
262
|
def get_direction(self) -> snl.SNLTerm.Direction:
|
|
238
263
|
"""Return the direction of the term."""
|
|
239
264
|
if self.term.getDirection() == snl.SNLTerm.Direction.Input:
|
|
240
|
-
return Term.
|
|
265
|
+
return Term.INPUT
|
|
241
266
|
elif self.term.getDirection() == snl.SNLTerm.Direction.Output:
|
|
242
|
-
return Term.
|
|
267
|
+
return Term.OUTPUT
|
|
243
268
|
elif self.term.getDirection() == snl.SNLTerm.Direction.InOut:
|
|
244
|
-
return Term.
|
|
269
|
+
return Term.INOUT
|
|
245
270
|
|
|
246
|
-
def
|
|
247
|
-
|
|
248
|
-
return None # FIXME xtof in the future
|
|
249
|
-
net = None
|
|
271
|
+
def __get_snl_bitnet(self, bit) -> Net:
|
|
272
|
+
# single bit
|
|
250
273
|
if self.path.size() > 0:
|
|
251
|
-
instTerm = self.path.getTailInstance().getInstTerm(
|
|
252
|
-
|
|
274
|
+
instTerm = self.path.getTailInstance().getInstTerm(bit)
|
|
275
|
+
return instTerm.getNet()
|
|
276
|
+
else:
|
|
277
|
+
return bit.getNet()
|
|
278
|
+
|
|
279
|
+
def __get_snl_lower_bitnet(self, bit) -> Net:
|
|
280
|
+
return bit.getNet()
|
|
281
|
+
|
|
282
|
+
def __get_snl_busnet(self, snl_nets) -> snl.SNLBusNet:
|
|
283
|
+
# iterate on all elements of the list and check if
|
|
284
|
+
# a full SNLBusNet can be reconstructed
|
|
285
|
+
snl_bus_net = None
|
|
286
|
+
for i in range(len(snl_nets)):
|
|
287
|
+
snl_net = snl_nets[i]
|
|
288
|
+
if not isinstance(snl_net, snl.SNLBusNetBit):
|
|
289
|
+
return None
|
|
290
|
+
bit_bus = snl_net.getBus()
|
|
291
|
+
if bit_bus.getWidth() != len(snl_nets):
|
|
292
|
+
return None
|
|
293
|
+
if snl_bus_net is None:
|
|
294
|
+
snl_bus_net = bit_bus
|
|
295
|
+
if snl_bus_net != bit_bus:
|
|
296
|
+
return None
|
|
297
|
+
if snl_bus_net.getBitAtPosition(i) != snl_net:
|
|
298
|
+
return None
|
|
299
|
+
return snl_bus_net
|
|
300
|
+
|
|
301
|
+
def __get_net(self, path, snl_term_net_accessor) -> Net:
|
|
302
|
+
if isinstance(self.term, snl.SNLBusTerm):
|
|
303
|
+
snl_nets = []
|
|
304
|
+
for bit in self.term.getBits():
|
|
305
|
+
snl_net = snl_term_net_accessor(bit)
|
|
306
|
+
snl_nets.append(snl_net)
|
|
307
|
+
snl_bus_net = self.__get_snl_busnet(snl_nets)
|
|
308
|
+
if snl_bus_net is not None:
|
|
309
|
+
return Net(path, snl_bus_net)
|
|
310
|
+
else:
|
|
311
|
+
if all(element is not None for element in snl_nets):
|
|
312
|
+
return Net(path, net_concat=snl_nets)
|
|
253
313
|
else:
|
|
254
|
-
|
|
255
|
-
|
|
314
|
+
snl_net = snl_term_net_accessor(self.term)
|
|
315
|
+
if snl_net is not None:
|
|
316
|
+
return Net(path, snl_net)
|
|
317
|
+
return None
|
|
318
|
+
|
|
319
|
+
def get_lower_net(self) -> Net:
|
|
320
|
+
"""Return the lower net of the term."""
|
|
321
|
+
return self.__get_net(self.path, self.__get_snl_lower_bitnet)
|
|
322
|
+
|
|
323
|
+
def get_net(self) -> Net:
|
|
324
|
+
"""Return the net of the term."""
|
|
325
|
+
if self.path.empty():
|
|
326
|
+
return None
|
|
327
|
+
# path is one level up
|
|
328
|
+
path = self.path.getHeadPath()
|
|
329
|
+
return self.__get_net(path, self.__get_snl_bitnet)
|
|
256
330
|
|
|
257
331
|
def get_instance(self):
|
|
332
|
+
"""Return the instance of the term."""
|
|
258
333
|
return Instance(self.path)
|
|
259
334
|
|
|
260
335
|
def get_flat_fanout(self):
|
|
@@ -295,6 +370,7 @@ class Term:
|
|
|
295
370
|
raise ValueError("Width mismatch")
|
|
296
371
|
if self.get_instance().is_top():
|
|
297
372
|
for bterm, bnet in zip(self.term.getBits(), net.net.getBits()):
|
|
373
|
+
logging.debug(f"Connecting {bterm} to {bnet}")
|
|
298
374
|
bterm.setNet(bnet)
|
|
299
375
|
else:
|
|
300
376
|
self.__make_unique()
|
|
@@ -348,8 +424,15 @@ class Instance:
|
|
|
348
424
|
def __eq__(self, other) -> bool:
|
|
349
425
|
return self.path == other.path
|
|
350
426
|
|
|
351
|
-
def __str__(self)
|
|
352
|
-
|
|
427
|
+
def __str__(self):
|
|
428
|
+
if self.is_top():
|
|
429
|
+
top = self.__get_snl_model()
|
|
430
|
+
if top is not None:
|
|
431
|
+
return top.getName()
|
|
432
|
+
else:
|
|
433
|
+
return ""
|
|
434
|
+
else:
|
|
435
|
+
return str(self.path)
|
|
353
436
|
|
|
354
437
|
def __repr__(self) -> str:
|
|
355
438
|
return f"Instance({self.path})"
|
|
@@ -396,8 +479,6 @@ class Instance:
|
|
|
396
479
|
|
|
397
480
|
def __find_snl_model(self, name: str) -> snl.SNLDesign:
|
|
398
481
|
u = snl.SNLUniverse.get()
|
|
399
|
-
if u is None:
|
|
400
|
-
return None
|
|
401
482
|
for db in u.getUserDBs():
|
|
402
483
|
for lib in db.getLibraries():
|
|
403
484
|
found_model = lib.getDesign(name)
|
|
@@ -419,15 +500,21 @@ class Instance:
|
|
|
419
500
|
def get_number_of_child_instances(self) -> int:
|
|
420
501
|
return sum(1 for _ in self.__get_snl_model().getInstances())
|
|
421
502
|
|
|
422
|
-
def
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
503
|
+
# def get_flat_primitive_instances(self):
|
|
504
|
+
# FIXME: concat first local path with the path of the instance
|
|
505
|
+
# model = self.__get_snl_model()
|
|
506
|
+
# for inst in model.getInstances():
|
|
507
|
+
# path = snl.SNLPath(inst)
|
|
508
|
+
# stack = [[inst, path]]
|
|
509
|
+
# while stack:
|
|
510
|
+
# current = stack.pop()
|
|
511
|
+
# current_inst = current[0]
|
|
512
|
+
# current_path = current[1]
|
|
513
|
+
# for inst_child in current_inst.getModel().getInstances():
|
|
514
|
+
# path_child = snl.SNLPath(current_path, inst_child)
|
|
515
|
+
# if inst_child.getModel().isPrimitive():
|
|
516
|
+
# yield Instance(path_child)
|
|
517
|
+
# stack.append([inst_child, path_child])
|
|
431
518
|
|
|
432
519
|
def get_nets(self):
|
|
433
520
|
for net in self.__get_snl_model().getNets():
|
|
@@ -448,8 +535,23 @@ class Instance:
|
|
|
448
535
|
return None
|
|
449
536
|
|
|
450
537
|
def is_primitive(self) -> bool:
|
|
538
|
+
"""Return True if this is a primitive."""
|
|
451
539
|
return self.__get_snl_model().isPrimitive()
|
|
452
540
|
|
|
541
|
+
def get_terms(self):
|
|
542
|
+
for term in self.__get_snl_model().getTerms():
|
|
543
|
+
yield Term(self.path, term)
|
|
544
|
+
|
|
545
|
+
def get_flat_terms(self):
|
|
546
|
+
for term in self.__get_snl_model().getBitTerms():
|
|
547
|
+
yield Term(self.path, term)
|
|
548
|
+
|
|
549
|
+
def get_term(self, name: str) -> Term:
|
|
550
|
+
term = self.__get_snl_model().getTerm(name)
|
|
551
|
+
if term is not None:
|
|
552
|
+
return Term(self.path, self.__get_snl_model().getTerm(name))
|
|
553
|
+
return None
|
|
554
|
+
|
|
453
555
|
def get_input_terms(self):
|
|
454
556
|
for term in self.__get_snl_model().getTerms():
|
|
455
557
|
if term.getDirection() == snl.SNLTerm.Direction.Input:
|
|
@@ -531,9 +633,10 @@ class Instance:
|
|
|
531
633
|
def create_input_term(self, name: str) -> Term:
|
|
532
634
|
return self.create_term(name, snl.SNLTerm.Direction.Input)
|
|
533
635
|
|
|
534
|
-
def
|
|
535
|
-
self
|
|
536
|
-
|
|
636
|
+
def create_inout_term(self, name: str) -> Term:
|
|
637
|
+
return self.create_term(name, snl.SNLTerm.Direction.InOut)
|
|
638
|
+
|
|
639
|
+
def create_bus_term(self, name: str, msb: int, lsb: int, direction) -> Term:
|
|
537
640
|
if self.path.size() > 0:
|
|
538
641
|
path = self.path
|
|
539
642
|
snl.SNLUniquifier(path)
|
|
@@ -542,6 +645,9 @@ class Instance:
|
|
|
542
645
|
newSNLTerm = snl.SNLBusTerm.create(design, direction, msb, lsb, name)
|
|
543
646
|
return Term(self.path, newSNLTerm)
|
|
544
647
|
|
|
648
|
+
def create_inout_bus_term(self, name: str, msb: int, lsb: int) -> Term:
|
|
649
|
+
return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.InOut)
|
|
650
|
+
|
|
545
651
|
def create_output_bus_term(self, name: str, msb: int, lsb: int) -> Term:
|
|
546
652
|
return self.create_bus_term(name, msb, lsb, snl.SNLTerm.Direction.Output)
|
|
547
653
|
|
|
@@ -621,20 +727,3 @@ def get_model_name(id: tuple[int, int, int]) -> str:
|
|
|
621
727
|
if model:
|
|
622
728
|
return model.getName()
|
|
623
729
|
return None
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
def get_all_primitive_instances():
|
|
627
|
-
top = snl.SNLUniverse.get().getTopDesign()
|
|
628
|
-
|
|
629
|
-
for inst in top.getInstances():
|
|
630
|
-
path = snl.SNLPath(inst)
|
|
631
|
-
stack = [[inst, path]]
|
|
632
|
-
while stack:
|
|
633
|
-
current = stack.pop()
|
|
634
|
-
current_inst = current[0]
|
|
635
|
-
current_path = current[1]
|
|
636
|
-
for inst_child in current_inst.getModel().getInstances():
|
|
637
|
-
path_child = snl.SNLPath(current_path, inst_child)
|
|
638
|
-
if inst_child.getModel().isPrimitive():
|
|
639
|
-
yield Instance(path_child)
|
|
640
|
-
stack.append([inst_child, path_child])
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: najaeda
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Naja EDA Python package
|
|
5
5
|
Author-Email: Naja Authors <contact@keplertech.io>
|
|
6
6
|
License: Apache License 2.0
|
|
@@ -11,15 +11,8 @@ Description-Content-Type: text/x-rst
|
|
|
11
11
|
Naja EDA Python Package
|
|
12
12
|
=======================
|
|
13
13
|
|
|
14
|
-
Naja EDA is a Python package that provides data structures and APIs for developing post-synthesis Electronic Design Automation (EDA) algorithms.
|
|
15
|
-
|
|
16
|
-
Features
|
|
17
|
-
--------
|
|
18
|
-
|
|
19
|
-
- **Netlist Simplification**: Perform constant propagation and dead logic elimination.
|
|
20
|
-
- **Logic Replication**: Facilitate duplication of logic elements for optimization.
|
|
21
|
-
- **Netlist Partitioning**: Divide netlists into manageable sections.
|
|
22
|
-
- **Place and Route Support**: Assist in ASIC and FPGA design flows.
|
|
14
|
+
Naja EDA is a Python package that provides data structures and APIs for developing post-synthesis Electronic Design Automation (EDA) algorithms.
|
|
15
|
+
It serves as the Python counterpart to the `Naja C++ project <https://github.com/najaeda/naja>`_.
|
|
23
16
|
|
|
24
17
|
Installation
|
|
25
18
|
------------
|
|
@@ -32,24 +25,35 @@ Install Naja EDA using pip:
|
|
|
32
25
|
|
|
33
26
|
Examples
|
|
34
27
|
--------
|
|
28
|
+
|
|
29
|
+
Load a design from a liberty file and a Verilog file
|
|
30
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
35
31
|
Following snippet shows how to load primitive cells from a liberty file and
|
|
36
32
|
a netlist from a Verilog file.
|
|
33
|
+
|
|
37
34
|
.. code-block:: python
|
|
38
35
|
|
|
39
36
|
from os import path
|
|
37
|
+
import sys
|
|
40
38
|
from najaeda import netlist
|
|
41
39
|
|
|
42
40
|
benchmarks = path.join('..','benchmarks')
|
|
43
|
-
liberty_files = [
|
|
41
|
+
liberty_files = [
|
|
42
|
+
'NangateOpenCellLibrary_typical.lib',
|
|
43
|
+
'fakeram45_1024x32.lib',
|
|
44
|
+
'fakeram45_64x32.lib'
|
|
45
|
+
]
|
|
44
46
|
liberty_files = list(map(lambda p:path.join(benchmarks, 'liberty', p), liberty_files))
|
|
45
47
|
|
|
46
48
|
netlist.load_liberty(liberty_files)
|
|
47
49
|
top = netlist.load_verilog([path.join(benchmarks, 'verilog', 'tinyrocket.v')])
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
top.dump_verilog('tinyrocket_naja.v')
|
|
51
|
+
top.dump_verilog('.', 'tinyrocket_naja.v')
|
|
51
52
|
|
|
53
|
+
Print all the instances in the netlist
|
|
54
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
52
55
|
Next example shows how to browse all the netlist and print all its content.
|
|
56
|
+
|
|
53
57
|
.. code-block:: python
|
|
54
58
|
|
|
55
59
|
def print_netlist(instance):
|
|
@@ -60,7 +64,7 @@ Next example shows how to browse all the netlist and print all its content.
|
|
|
60
64
|
Documentation
|
|
61
65
|
-------------
|
|
62
66
|
|
|
63
|
-
|
|
67
|
+
Naja documentation is available on the `Naja GitHub repository <https://github.com/najaeda/naja>`_.
|
|
64
68
|
|
|
65
69
|
License
|
|
66
70
|
-------
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
najaeda-0.1.3.dist-info/RECORD,,
|
|
2
|
+
najaeda-0.1.3.dist-info/WHEEL,sha256=rOJaAfyDeYqpyZcvF2uMKwvjCoDaR0tVOjIX1nCiRq8,114
|
|
3
|
+
najaeda-0.1.3.dist-info/METADATA,sha256=cUsTBMA9mhbFVF1WSI0wQYb3hc9-ThpBYShih2Yru6E,2147
|
|
4
|
+
najaeda-0.1.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
5
|
+
najaeda-0.1.3.dist-info/licenses/AUTHORS,sha256=e4DCPGHo6wKMyQz24V59EP7zMwalK-KBDBHHlMLFxHY,330
|
|
6
|
+
najaeda/netlist.py,sha256=sKIacJE8olG3-NxUru0ntAnzeU-enJNocnvJ3O0Jnp0,25102
|
|
7
|
+
najaeda/libnaja_snl_python.dylib,sha256=GyZAaw5tt9Q-KuNYiErmU5p0qWVS1MvIMxo9fGUpVx8,740160
|
|
8
|
+
najaeda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
najaeda/libnaja_snl.dylib,sha256=8Ei7KKU0b14IqlvH_8yQSSCpH0rjbxpeRaXgyfSemMY,574112
|
|
10
|
+
najaeda/snl.so,sha256=bEV8QN-wHqCYSDkEpcgMuw4TIWkoNFQSG0zk_fw_bxk,97888
|
|
11
|
+
najaeda/.dylibs/Python,sha256=gNPmu4BlzZFW7BRGmYn97Rh9oazzWgnlPqRHMuLQpdw,9729168
|
najaeda-0.1.2.dist-info/RECORD
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
najaeda-0.1.2.dist-info/RECORD,,
|
|
2
|
-
najaeda-0.1.2.dist-info/WHEEL,sha256=rOJaAfyDeYqpyZcvF2uMKwvjCoDaR0tVOjIX1nCiRq8,114
|
|
3
|
-
najaeda-0.1.2.dist-info/METADATA,sha256=agjVbL5DID69VNnjngj23q1t-TEOHBaCUhMnhIGEjZI,2267
|
|
4
|
-
najaeda-0.1.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
5
|
-
najaeda-0.1.2.dist-info/licenses/AUTHORS,sha256=e4DCPGHo6wKMyQz24V59EP7zMwalK-KBDBHHlMLFxHY,330
|
|
6
|
-
najaeda/netlist.py,sha256=usJ__3Vh_A8GFK7xUdhwJSdsTc7DWhaIF3Ptp3dfuZU,21251
|
|
7
|
-
najaeda/libnaja_snl_python.dylib,sha256=aukMc3uXSMpY8HW72IFztL8w8D2SWJst8iBBVak88co,739872
|
|
8
|
-
najaeda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
najaeda/libnaja_snl.dylib,sha256=8Ei7KKU0b14IqlvH_8yQSSCpH0rjbxpeRaXgyfSemMY,574112
|
|
10
|
-
najaeda/snl.so,sha256=bEV8QN-wHqCYSDkEpcgMuw4TIWkoNFQSG0zk_fw_bxk,97888
|
|
11
|
-
najaeda/.dylibs/Python,sha256=gNPmu4BlzZFW7BRGmYn97Rh9oazzWgnlPqRHMuLQpdw,9729168
|
|
File without changes
|
|
File without changes
|
|
File without changes
|