najaeda 0.1.12__cp312-cp312-macosx_11_0_arm64.whl → 0.1.14__cp312-cp312-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of najaeda might be problematic. Click here for more details.
- najaeda/.dylibs/libcapnp-1.1.0.dylib +0 -0
- najaeda/.dylibs/libkj-1.1.0.dylib +0 -0
- najaeda/libnaja_snl.dylib +0 -0
- najaeda/libnaja_snl_python.dylib +0 -0
- najaeda/native/__init__.py +0 -0
- najaeda/native/stats.py +341 -0
- najaeda/net_visitor.py +53 -0
- najaeda/netlist.py +123 -57
- najaeda/primitives/xilinx.py +2 -0
- najaeda/snl.so +0 -0
- najaeda/stats.py +2 -4
- {najaeda-0.1.12.dist-info → najaeda-0.1.14.dist-info}/METADATA +1 -1
- {najaeda-0.1.12.dist-info → najaeda-0.1.14.dist-info}/RECORD +16 -11
- {najaeda-0.1.12.dist-info → najaeda-0.1.14.dist-info}/WHEEL +0 -0
- {najaeda-0.1.12.dist-info → najaeda-0.1.14.dist-info}/licenses/AUTHORS +0 -0
- {najaeda-0.1.12.dist-info → najaeda-0.1.14.dist-info}/licenses/LICENSE +0 -0
|
Binary file
|
|
Binary file
|
najaeda/libnaja_snl.dylib
CHANGED
|
Binary file
|
najaeda/libnaja_snl_python.dylib
CHANGED
|
Binary file
|
|
File without changes
|
najaeda/native/stats.py
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
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
|
+
import os
|
|
7
|
+
from naja import snl
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DesignsStats:
|
|
11
|
+
def __init__(self):
|
|
12
|
+
self.blackboxes = dict()
|
|
13
|
+
self.hier_designs = dict()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DesignStats:
|
|
17
|
+
def __init__(self):
|
|
18
|
+
self.name = ""
|
|
19
|
+
self.assigns = 0
|
|
20
|
+
self.flat_assigns = 0
|
|
21
|
+
self.basic_primitives = dict()
|
|
22
|
+
self.primitives = dict()
|
|
23
|
+
self.flat_basic_primitives = dict()
|
|
24
|
+
self.flat_primitives = dict()
|
|
25
|
+
self.blackboxes = dict()
|
|
26
|
+
self.flat_blackboxes = dict()
|
|
27
|
+
self.ins = dict()
|
|
28
|
+
self.flat_ins = dict()
|
|
29
|
+
self.terms = dict()
|
|
30
|
+
self.bit_terms = dict()
|
|
31
|
+
self.net_stats = dict()
|
|
32
|
+
|
|
33
|
+
def add_ins_stats(self, ins_stats):
|
|
34
|
+
self.flat_assigns += ins_stats.flat_assigns
|
|
35
|
+
for ins, nb in ins_stats.flat_ins.items():
|
|
36
|
+
self.flat_ins[ins] = self.flat_ins.get(ins, 0) + nb
|
|
37
|
+
for ins, nb in ins_stats.flat_blackboxes.items():
|
|
38
|
+
self.flat_blackboxes[ins] = self.flat_blackboxes.get(ins, 0) + nb
|
|
39
|
+
for primitive, nb in ins_stats.flat_primitives.items():
|
|
40
|
+
self.flat_primitives[primitive] = (
|
|
41
|
+
self.flat_primitives.get(primitive, 0) + nb
|
|
42
|
+
)
|
|
43
|
+
for primitive, nb in ins_stats.flat_basic_primitives.items():
|
|
44
|
+
self.flat_basic_primitives[primitive] = (
|
|
45
|
+
self.flat_basic_primitives.get(primitive, 0) + nb
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def isBasicPrimitive(design):
|
|
50
|
+
return design.isConst0() or design.isConst1() or design.isBuf() or design.isInv()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def compute_design_stats(design, designs_stats):
|
|
54
|
+
if design in designs_stats.hier_designs:
|
|
55
|
+
return designs_stats.hier_designs.get(design)
|
|
56
|
+
design_stats = DesignStats()
|
|
57
|
+
design_stats.name = design.getName()
|
|
58
|
+
for ins in design.getInstances():
|
|
59
|
+
model = ins.getModel()
|
|
60
|
+
if model.isAssign():
|
|
61
|
+
design_stats.assigns += 1
|
|
62
|
+
design_stats.flat_assigns += 1
|
|
63
|
+
elif model.isPrimitive():
|
|
64
|
+
if isBasicPrimitive(model):
|
|
65
|
+
design_stats.basic_primitives[model] = (
|
|
66
|
+
design_stats.basic_primitives.get(model, 0) + 1
|
|
67
|
+
)
|
|
68
|
+
design_stats.flat_basic_primitives[model] = (
|
|
69
|
+
design_stats.flat_basic_primitives.get(model, 0) + 1
|
|
70
|
+
)
|
|
71
|
+
else:
|
|
72
|
+
design_stats.primitives[model] = (
|
|
73
|
+
design_stats.primitives.get(model, 0) + 1
|
|
74
|
+
)
|
|
75
|
+
design_stats.flat_primitives[model] = (
|
|
76
|
+
design_stats.flat_primitives.get(model, 0) + 1
|
|
77
|
+
)
|
|
78
|
+
elif model.isBlackBox():
|
|
79
|
+
design_stats.blackboxes[model] = design_stats.blackboxes.get(model, 0) + 1
|
|
80
|
+
design_stats.flat_blackboxes[model] = (
|
|
81
|
+
design_stats.flat_blackboxes.get(model, 0) + 1
|
|
82
|
+
)
|
|
83
|
+
if model not in designs_stats.blackboxes:
|
|
84
|
+
designs_stats.blackboxes[model] = dict()
|
|
85
|
+
compute_design_terms(model, designs_stats.blackboxes[model])
|
|
86
|
+
else:
|
|
87
|
+
if model in designs_stats.hier_designs:
|
|
88
|
+
model_stats = designs_stats.hier_designs[model]
|
|
89
|
+
else:
|
|
90
|
+
model_stats = compute_design_stats(model, designs_stats)
|
|
91
|
+
design_stats.ins[model] = design_stats.ins.get(model, 0) + 1
|
|
92
|
+
design_stats.flat_ins[model] = design_stats.flat_ins.get(model, 0) + 1
|
|
93
|
+
design_stats.add_ins_stats(model_stats)
|
|
94
|
+
compute_design_terms(design, design_stats)
|
|
95
|
+
compute_design_net_stats(design, design_stats)
|
|
96
|
+
designs_stats.hier_designs[design] = design_stats
|
|
97
|
+
return design_stats
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def compute_design_terms(design, design_stats):
|
|
101
|
+
for term in design.getTerms():
|
|
102
|
+
if term.getDirection() == snl.SNLTerm.Direction.Input:
|
|
103
|
+
design_stats.terms["inputs"] = design_stats.terms.get("inputs", 0) + 1
|
|
104
|
+
bit_terms = sum(1 for _ in term.getBits())
|
|
105
|
+
design_stats.bit_terms["inputs"] = (
|
|
106
|
+
design_stats.bit_terms.get("inputs", 0) + bit_terms
|
|
107
|
+
)
|
|
108
|
+
elif term.getDirection() == snl.SNLTerm.Direction.Output:
|
|
109
|
+
design_stats.terms["outputs"] = design_stats.terms.get("outputs", 0) + 1
|
|
110
|
+
bit_terms = sum(1 for _ in term.getBits())
|
|
111
|
+
design_stats.bit_terms["outputs"] = (
|
|
112
|
+
design_stats.bit_terms.get("outputs", 0) + bit_terms
|
|
113
|
+
)
|
|
114
|
+
elif term.getDirection() == snl.SNLTerm.Direction.InOut:
|
|
115
|
+
design_stats.terms["inouts"] = design_stats.terms.get("inouts", 0) + 1
|
|
116
|
+
bit_terms = sum(1 for _ in term.getBits())
|
|
117
|
+
design_stats.bit_terms["inouts"] = (
|
|
118
|
+
design_stats.bit_terms.get("inouts", 0) + bit_terms
|
|
119
|
+
)
|
|
120
|
+
else:
|
|
121
|
+
design_stats.terms["unknowns"] = design_stats.terms.get("unknowns", 0) + 1
|
|
122
|
+
bit_terms = sum(1 for _ in term.getBits())
|
|
123
|
+
design_stats.bit_terms["unknowns"] = (
|
|
124
|
+
design_stats.bit_terms.get("unknowns", 0) + bit_terms
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def compute_design_net_stats(design, design_stats):
|
|
129
|
+
for net in design.getBitNets():
|
|
130
|
+
if net.isConstant():
|
|
131
|
+
pass
|
|
132
|
+
nb_components = sum(1 for c in net.getComponents())
|
|
133
|
+
design_stats.net_stats[nb_components] = (
|
|
134
|
+
design_stats.net_stats.get(nb_components, 0) + 1
|
|
135
|
+
)
|
|
136
|
+
design_stats.net_stats = dict(sorted(design_stats.net_stats.items()))
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def dump_instances(stats_file, title, instances):
|
|
140
|
+
if len(instances) == 0:
|
|
141
|
+
return
|
|
142
|
+
sorted_instances = sorted(instances.items(), key=lambda item: item[0].getName())
|
|
143
|
+
stats_file.write(title + " " + str(sum(j for i, j in sorted_instances)) + "\n")
|
|
144
|
+
line_char = 0
|
|
145
|
+
for instance in sorted_instances:
|
|
146
|
+
if line_char != 0:
|
|
147
|
+
stats_file.write(",")
|
|
148
|
+
line_char += 1
|
|
149
|
+
if line_char > 80:
|
|
150
|
+
stats_file.write("\n")
|
|
151
|
+
line_char = 0
|
|
152
|
+
elif line_char != 0:
|
|
153
|
+
stats_file.write(" ")
|
|
154
|
+
line_char += 1
|
|
155
|
+
instance_char = instance[0].getName() + ":" + str(instance[1])
|
|
156
|
+
line_char += len(instance_char)
|
|
157
|
+
stats_file.write(instance_char)
|
|
158
|
+
stats_file.write("\n\n")
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def dump_blackboxes_stats(stats_file, design_stats):
|
|
162
|
+
if len(design_stats.blackboxes) > 0:
|
|
163
|
+
stats_file.write("*** BlackBoxes ***\n")
|
|
164
|
+
for bbox in design_stats.blackboxes.items():
|
|
165
|
+
design = bbox[0]
|
|
166
|
+
design_terms = bbox[1]
|
|
167
|
+
stats_file.write("*** " + design.getName() + " ***\n")
|
|
168
|
+
if len(design_terms) > 0:
|
|
169
|
+
stats_file.write("Terms: ")
|
|
170
|
+
first = True
|
|
171
|
+
for terms in design_terms.items():
|
|
172
|
+
if not first:
|
|
173
|
+
stats_file.write(", ")
|
|
174
|
+
else:
|
|
175
|
+
first = False
|
|
176
|
+
stats_file.write(terms[0] + ":" + str(terms[1]))
|
|
177
|
+
stats_file.write("\n")
|
|
178
|
+
stats_file.write("\n")
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def dump_stats(design, stats_file, designs_stats, dumped_models):
|
|
182
|
+
if design.isPrimitive() or design.isBlackBox():
|
|
183
|
+
return
|
|
184
|
+
if design in dumped_models:
|
|
185
|
+
return
|
|
186
|
+
dumped_models.add(design)
|
|
187
|
+
stats_file.write("*** " + design.getName() + " ***\n")
|
|
188
|
+
design_stats = designs_stats.hier_designs.get(design)
|
|
189
|
+
if design_stats is None:
|
|
190
|
+
print("Cannot find " + str(design) + " in design_stats")
|
|
191
|
+
raise
|
|
192
|
+
if len(design_stats.terms) > 0:
|
|
193
|
+
stats_file.write("Terms: ")
|
|
194
|
+
first = True
|
|
195
|
+
for terms in design_stats.terms.items():
|
|
196
|
+
if not first:
|
|
197
|
+
stats_file.write(", ")
|
|
198
|
+
else:
|
|
199
|
+
first = False
|
|
200
|
+
stats_file.write(terms[0] + ":" + str(terms[1]))
|
|
201
|
+
stats_file.write("\n")
|
|
202
|
+
|
|
203
|
+
dump_instances(stats_file, "Instances:", design_stats.ins)
|
|
204
|
+
nb_primitives = sum(design_stats.basic_primitives.values()) + sum(
|
|
205
|
+
design_stats.primitives.values()
|
|
206
|
+
)
|
|
207
|
+
if nb_primitives > 1:
|
|
208
|
+
stats_file.write("Primitives: " + str(nb_primitives) + "\n")
|
|
209
|
+
dump_instances(stats_file, "Simple Primitives:", design_stats.basic_primitives)
|
|
210
|
+
dump_instances(stats_file, "Other Primitives:", design_stats.primitives)
|
|
211
|
+
dump_instances(stats_file, "Blackboxes:", design_stats.blackboxes)
|
|
212
|
+
if design_stats.assigns > 0:
|
|
213
|
+
stats_file.write("Assigns: " + str(design_stats.assigns) + "\n")
|
|
214
|
+
dump_instances(stats_file, "Flat Instances:", design_stats.flat_ins)
|
|
215
|
+
dump_instances(stats_file, "Flat Blackboxes:", design_stats.flat_blackboxes)
|
|
216
|
+
nb_primitives = sum(design_stats.flat_basic_primitives.values()) + sum(
|
|
217
|
+
design_stats.flat_primitives.values()
|
|
218
|
+
)
|
|
219
|
+
if nb_primitives > 1:
|
|
220
|
+
stats_file.write("Flat Primitives: " + str(nb_primitives) + "\n")
|
|
221
|
+
dump_instances(
|
|
222
|
+
stats_file, "Flat Simple Primitives:", design_stats.flat_basic_primitives
|
|
223
|
+
)
|
|
224
|
+
dump_instances(stats_file, "Flat Other Primitives:", design_stats.flat_primitives)
|
|
225
|
+
if design_stats.flat_assigns > 0:
|
|
226
|
+
stats_file.write("Flat Assigns: " + str(design_stats.flat_assigns) + "\n")
|
|
227
|
+
stats_file.write("\n")
|
|
228
|
+
for ins in design.getInstances():
|
|
229
|
+
model = ins.getModel()
|
|
230
|
+
dump_stats(model, stats_file, designs_stats, dumped_models)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def dump_pandas(designs_stats):
|
|
234
|
+
import pandas
|
|
235
|
+
import matplotlib.pyplot as plt
|
|
236
|
+
|
|
237
|
+
# create a figures directory erase the previous one
|
|
238
|
+
if os.path.exists("figures"):
|
|
239
|
+
import shutil
|
|
240
|
+
|
|
241
|
+
shutil.rmtree("figures")
|
|
242
|
+
os.makedirs("figures")
|
|
243
|
+
|
|
244
|
+
data = []
|
|
245
|
+
for design, design_stats in designs_stats.hier_designs.items():
|
|
246
|
+
data.append(
|
|
247
|
+
[
|
|
248
|
+
design.getName(),
|
|
249
|
+
sum(design_stats.terms.values()),
|
|
250
|
+
sum(design_stats.bit_terms.values()),
|
|
251
|
+
sum(design_stats.basic_primitives.values()),
|
|
252
|
+
sum(design_stats.primitives.values()),
|
|
253
|
+
sum(design_stats.blackboxes.values()),
|
|
254
|
+
sum(design_stats.ins.values()),
|
|
255
|
+
sum(design_stats.flat_ins.values()),
|
|
256
|
+
sum(design_stats.flat_blackboxes.values()),
|
|
257
|
+
sum(design_stats.flat_basic_primitives.values()),
|
|
258
|
+
sum(design_stats.flat_primitives.values()),
|
|
259
|
+
]
|
|
260
|
+
)
|
|
261
|
+
df = pandas.DataFrame(
|
|
262
|
+
data,
|
|
263
|
+
columns=[
|
|
264
|
+
"Design",
|
|
265
|
+
"Terms",
|
|
266
|
+
"Bit Terms",
|
|
267
|
+
"Basic Primitives",
|
|
268
|
+
"Primitives",
|
|
269
|
+
"Blackboxes",
|
|
270
|
+
"Instances",
|
|
271
|
+
"Flat Instances",
|
|
272
|
+
"Flat Blackboxes",
|
|
273
|
+
"Flat Basic Primitives",
|
|
274
|
+
"Flat Primitives",
|
|
275
|
+
],
|
|
276
|
+
)
|
|
277
|
+
df.to_csv("figures/designs_stats.csv", index=False)
|
|
278
|
+
|
|
279
|
+
net_series = pandas.Series(design_stats.net_stats)
|
|
280
|
+
nets_plot = net_series.plot(
|
|
281
|
+
kind="bar",
|
|
282
|
+
title="Number of nets with a given number of components for\n"
|
|
283
|
+
+ design.getName(),
|
|
284
|
+
xlabel="number of components",
|
|
285
|
+
ylabel="number of nets",
|
|
286
|
+
)
|
|
287
|
+
nets_plot.set_yscale("log")
|
|
288
|
+
nets_plot.xaxis.set_major_locator(plt.MaxNLocator(100))
|
|
289
|
+
nets_figure = nets_plot.get_figure()
|
|
290
|
+
nets_figure.tight_layout()
|
|
291
|
+
nets_figure.savefig("figures/nets_" + design.getName() + ".png")
|
|
292
|
+
|
|
293
|
+
flat_primitives_series = pandas.Series(design_stats.flat_primitives)
|
|
294
|
+
primitives_plot = flat_primitives_series.plot(
|
|
295
|
+
kind="bar",
|
|
296
|
+
title="Number of primitives for\n" + design.getName(),
|
|
297
|
+
xlabel="primitive",
|
|
298
|
+
ylabel="number of flat instances",
|
|
299
|
+
)
|
|
300
|
+
primitives_plot.set_yscale("log")
|
|
301
|
+
primitives_figure = primitives_plot.get_figure()
|
|
302
|
+
primitives_figure.tight_layout()
|
|
303
|
+
primitives_figure.savefig("figures/flat_primitives_" + design.getName() + ".png")
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def compute_and_dump_design_stats(design, stats_file, with_pandas=False):
|
|
307
|
+
designs_stats = DesignsStats()
|
|
308
|
+
compute_design_stats(design, designs_stats)
|
|
309
|
+
dumped_models = set()
|
|
310
|
+
dump_stats(design, stats_file, designs_stats, dumped_models)
|
|
311
|
+
dump_blackboxes_stats(stats_file, designs_stats)
|
|
312
|
+
if with_pandas:
|
|
313
|
+
dump_pandas(designs_stats)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def dump_constants(design, analyzed_models):
|
|
317
|
+
if design.isPrimitive():
|
|
318
|
+
return
|
|
319
|
+
if design in analyzed_models:
|
|
320
|
+
return
|
|
321
|
+
analyzed_models.add(design)
|
|
322
|
+
for bitnet in design.getBitNets():
|
|
323
|
+
if bitnet.isConstant():
|
|
324
|
+
logging.info(
|
|
325
|
+
"In design "
|
|
326
|
+
+ design.getName()
|
|
327
|
+
+ ", constant net "
|
|
328
|
+
+ bitnet.getName()
|
|
329
|
+
+ " of type "
|
|
330
|
+
+ bitnet.getTypeAsString()
|
|
331
|
+
)
|
|
332
|
+
if all(False for _ in bitnet.getComponents()):
|
|
333
|
+
logging.info(" with zero connections\n")
|
|
334
|
+
else:
|
|
335
|
+
logging.info(" connected to:\n")
|
|
336
|
+
for component in bitnet.getComponents():
|
|
337
|
+
logging.info(str(component) + "\n")
|
|
338
|
+
|
|
339
|
+
for ins in design.getInstances():
|
|
340
|
+
model = ins.getModel()
|
|
341
|
+
dump_constants(model, analyzed_models)
|
najaeda/net_visitor.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2024 The Naja authors
|
|
2
|
+
# <https://github.com/najaeda/naja/blob/main/AUTHORS>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
# from typing import Callable
|
|
7
|
+
# from najaeda import netlist
|
|
8
|
+
#
|
|
9
|
+
#
|
|
10
|
+
# class VisitorConfig:
|
|
11
|
+
# def __init__(
|
|
12
|
+
# self,
|
|
13
|
+
# enter_condition: Callable[[netlist.Instance], bool] = lambda node: True,
|
|
14
|
+
# callback: Callable[..., None] = lambda node, *args, **kwargs: None,
|
|
15
|
+
# args: tuple = (),
|
|
16
|
+
# kwargs: dict = None,
|
|
17
|
+
# ):
|
|
18
|
+
# """
|
|
19
|
+
# :param enter_condition: A callable that takes a node (dict)
|
|
20
|
+
# and returns True if the visitor should enter.
|
|
21
|
+
# :param callback: A callable that takes a node (dict) and performs an operation on it.
|
|
22
|
+
# :param args: Positional arguments to pass to the callback.
|
|
23
|
+
# :param kwargs: Keyword arguments to pass to the callback.
|
|
24
|
+
# """
|
|
25
|
+
# self.enter_condition = enter_condition
|
|
26
|
+
# self.callback = callback
|
|
27
|
+
# self.args = args
|
|
28
|
+
# self.kwargs = kwargs or {}
|
|
29
|
+
#
|
|
30
|
+
#
|
|
31
|
+
# def visit(equipotential: netlist.Equipotential, config: VisitorConfig):
|
|
32
|
+
# """Recursively visits nodes in the netlist hierarchy.
|
|
33
|
+
#
|
|
34
|
+
# :param instance: The current node in the netlist instance hierarchy.
|
|
35
|
+
# :param config: VisitorConfig object defining conditions and callbacks.
|
|
36
|
+
# """
|
|
37
|
+
# # Execute the callback
|
|
38
|
+
# config.callback(equipotential, *config.args, **config.kwargs)
|
|
39
|
+
#
|
|
40
|
+
# # Check if we should proceed to children
|
|
41
|
+
# if config.enter_condition(equipotential):
|
|
42
|
+
# for component in equipotential.get .get_child_instances():
|
|
43
|
+
# visit(child, config)
|
|
44
|
+
#
|
|
45
|
+
# def visit(term: netlist.Term, config: VisitorConfig):
|
|
46
|
+
# config.callback(term, *config.args, **config.kwargs)
|
|
47
|
+
#
|
|
48
|
+
# #get the corresponding iterms
|
|
49
|
+
# instance = term.get_instance()
|
|
50
|
+
# if instance is not None:
|
|
51
|
+
# for iterm in instance.get_iterms():
|
|
52
|
+
# visit(iterm, config)
|
|
53
|
+
#
|
najaeda/netlist.py
CHANGED
|
@@ -8,11 +8,16 @@ import time
|
|
|
8
8
|
import logging
|
|
9
9
|
import hashlib
|
|
10
10
|
import struct
|
|
11
|
+
import sys
|
|
11
12
|
from enum import Enum
|
|
12
13
|
|
|
13
14
|
from najaeda import snl
|
|
14
15
|
|
|
15
16
|
|
|
17
|
+
def get_none_existent():
|
|
18
|
+
return sys.maxsize
|
|
19
|
+
|
|
20
|
+
|
|
16
21
|
def consistent_hash(obj):
|
|
17
22
|
def default_serializer(o):
|
|
18
23
|
if isinstance(o, (str, int, float, bool, type(None))):
|
|
@@ -40,14 +45,14 @@ def consistent_hash(obj):
|
|
|
40
45
|
|
|
41
46
|
|
|
42
47
|
def get_snl_instance_from_id_list(id_list: list) -> snl.SNLInstance:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return
|
|
48
|
+
design = snl.SNLUniverse.get().getTopDesign()
|
|
49
|
+
# instance = None
|
|
50
|
+
# for id in id_list:
|
|
51
|
+
# instance = design.getInstanceByID(id)
|
|
52
|
+
# assert instance is not None
|
|
53
|
+
# design = instance.getModel()
|
|
54
|
+
# return instance
|
|
55
|
+
return design.getInstanceByIDList(id_list)
|
|
51
56
|
|
|
52
57
|
|
|
53
58
|
def get_snl_path_from_id_list(id_list: list) -> snl.SNLPath:
|
|
@@ -71,7 +76,8 @@ class Equipotential:
|
|
|
71
76
|
"""
|
|
72
77
|
|
|
73
78
|
def __init__(self, term):
|
|
74
|
-
|
|
79
|
+
path = get_snl_path_from_id_list(term.pathIDs)
|
|
80
|
+
snl_term = get_snl_term_for_ids_with_path(path, term.termIDs)
|
|
75
81
|
inst_term = None
|
|
76
82
|
if isinstance(snl_term, snl.SNLBusTerm):
|
|
77
83
|
raise ValueError("Equipotential cannot be constructed on bus term")
|
|
@@ -85,10 +91,10 @@ class Equipotential:
|
|
|
85
91
|
self.equi = None
|
|
86
92
|
return
|
|
87
93
|
else:
|
|
94
|
+
path = snl.SNLPath(path, get_snl_instance_from_id_list(inst_term.pathIDs))
|
|
88
95
|
snl_term = get_snl_term_for_ids(inst_term.pathIDs, inst_term.termIDs)
|
|
89
96
|
else:
|
|
90
97
|
inst_term = term
|
|
91
|
-
path = get_snl_path_from_id_list(inst_term.pathIDs)
|
|
92
98
|
ito = snl.SNLNetComponentOccurrence(
|
|
93
99
|
path.getHeadPath(), path.getTailInstance().getInstTerm(snl_term)
|
|
94
100
|
)
|
|
@@ -109,10 +115,10 @@ class Equipotential:
|
|
|
109
115
|
"""
|
|
110
116
|
if self.equi is not None:
|
|
111
117
|
for term in self.equi.getInstTermOccurrences():
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
118
|
+
path = term.getPath().getPathIDs()
|
|
119
|
+
path.append(term.getInstTerm().getInstance().getID())
|
|
120
|
+
yield Term(path,
|
|
121
|
+
term.getInstTerm().getBitTerm())
|
|
116
122
|
|
|
117
123
|
def get_top_terms(self):
|
|
118
124
|
"""Iterate over the top terminals of this equipotential.
|
|
@@ -130,12 +136,10 @@ class Equipotential:
|
|
|
130
136
|
direction = term.getInstTerm().getDirection()
|
|
131
137
|
if direction != snl.SNLTerm.Direction.Output:
|
|
132
138
|
if term.getInstTerm().getInstance().getModel().isLeaf():
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
)
|
|
137
|
-
term.getInstTerm().getBitTerm(),
|
|
138
|
-
)
|
|
139
|
+
path = term.getPath().getPathIDs()
|
|
140
|
+
path.append(term.getInstTerm().getInstance().getID())
|
|
141
|
+
yield Term(path,
|
|
142
|
+
term.getInstTerm().getBitTerm())
|
|
139
143
|
|
|
140
144
|
def get_leaf_drivers(self):
|
|
141
145
|
if self.equi is not None:
|
|
@@ -143,26 +147,24 @@ class Equipotential:
|
|
|
143
147
|
direction = term.getInstTerm().getDirection()
|
|
144
148
|
if direction != snl.SNLTerm.Direction.Input:
|
|
145
149
|
if term.getInstTerm().getInstance().getModel().isLeaf():
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
)
|
|
150
|
-
term.getInstTerm().getBitTerm(),
|
|
151
|
-
)
|
|
150
|
+
path = term.getPath().getPathIDs()
|
|
151
|
+
path.append(term.getInstTerm().getInstance().getID())
|
|
152
|
+
yield Term(path,
|
|
153
|
+
term.getInstTerm().getBitTerm())
|
|
152
154
|
|
|
153
155
|
def get_top_readers(self):
|
|
154
156
|
if self.equi is not None:
|
|
155
157
|
for term in self.equi.getTerms():
|
|
156
158
|
direction = term.getDirection()
|
|
157
159
|
if direction != snl.SNLTerm.Direction.Input:
|
|
158
|
-
yield Term(
|
|
160
|
+
yield Term([], term)
|
|
159
161
|
|
|
160
162
|
def get_top_drivers(self):
|
|
161
163
|
if self.equi is not None:
|
|
162
164
|
for term in self.equi.getTerms():
|
|
163
165
|
direction = term.getDirection()
|
|
164
166
|
if direction != snl.SNLTerm.Direction.Output:
|
|
165
|
-
yield Term(
|
|
167
|
+
yield Term([], term)
|
|
166
168
|
|
|
167
169
|
|
|
168
170
|
class Net:
|
|
@@ -343,10 +345,11 @@ class Net:
|
|
|
343
345
|
"""
|
|
344
346
|
if hasattr(self, "net_concat"):
|
|
345
347
|
raise ValueError("Cannot get inst terms from a net_concat")
|
|
348
|
+
path = self.pathIDs.copy()
|
|
346
349
|
for term in self.net.getInstTerms():
|
|
347
|
-
path = self.pathIDs.copy()
|
|
348
350
|
path.append(term.getInstance().getID())
|
|
349
351
|
yield Term(path, term.getBitTerm())
|
|
352
|
+
path.pop()
|
|
350
353
|
|
|
351
354
|
def get_design_terms(self):
|
|
352
355
|
"""
|
|
@@ -374,12 +377,28 @@ def get_snl_term_for_ids(pathIDs, termIDs):
|
|
|
374
377
|
model = snl.SNLUniverse.get().getTopDesign()
|
|
375
378
|
else:
|
|
376
379
|
model = path.getTailInstance().getModel()
|
|
377
|
-
if termIDs[1] ==
|
|
380
|
+
if termIDs[1] == get_none_existent():
|
|
381
|
+
return model.getTermByID(termIDs[0])
|
|
382
|
+
else:
|
|
383
|
+
snlterm = model.getTermByID(termIDs[0])
|
|
384
|
+
if isinstance(snlterm, snl.SNLBusTerm):
|
|
385
|
+
return snlterm.getBusTermBit(termIDs[1])
|
|
386
|
+
else:
|
|
387
|
+
return snlterm
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
def get_snl_term_for_ids_with_path(path, termIDs):
|
|
391
|
+
model = None
|
|
392
|
+
if path.size() == 0:
|
|
393
|
+
model = snl.SNLUniverse.get().getTopDesign()
|
|
394
|
+
else:
|
|
395
|
+
model = path.getTailInstance().getModel()
|
|
396
|
+
if termIDs[1] == get_none_existent():
|
|
378
397
|
return model.getTermByID(termIDs[0])
|
|
379
398
|
else:
|
|
380
399
|
snlterm = model.getTermByID(termIDs[0])
|
|
381
400
|
if isinstance(snlterm, snl.SNLBusTerm):
|
|
382
|
-
return snlterm.
|
|
401
|
+
return snlterm.getBusTermBit(termIDs[1])
|
|
383
402
|
else:
|
|
384
403
|
return snlterm
|
|
385
404
|
|
|
@@ -390,19 +409,12 @@ class Term:
|
|
|
390
409
|
INOUT = snl.SNLTerm.Direction.InOut
|
|
391
410
|
|
|
392
411
|
def __init__(self, path, term):
|
|
393
|
-
self.termIDs = []
|
|
394
|
-
if isinstance(term, snl.SNLBusTerm):
|
|
395
|
-
|
|
396
|
-
else:
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
if isinstance(path, snl.SNLPath):
|
|
400
|
-
if path.size() > 0:
|
|
401
|
-
self.pathIDs = path.getPathIDs()
|
|
402
|
-
else:
|
|
403
|
-
self.pathIDs = []
|
|
404
|
-
elif isinstance(path, list):
|
|
405
|
-
self.pathIDs = path.copy()
|
|
412
|
+
# self.termIDs = []
|
|
413
|
+
# if isinstance(term, snl.SNLBusTerm):
|
|
414
|
+
# self.termIDs = [term.getID(), -1]
|
|
415
|
+
# else:
|
|
416
|
+
self.termIDs = [term.getID(), term.getBit()]
|
|
417
|
+
self.pathIDs = path.copy()
|
|
406
418
|
|
|
407
419
|
def __eq__(self, other) -> bool:
|
|
408
420
|
return self.pathIDs == other.pathIDs and self.termIDs == other.termIDs
|
|
@@ -434,13 +446,19 @@ class Term:
|
|
|
434
446
|
return consistent_hash((self.pathIDs, termIDs))
|
|
435
447
|
|
|
436
448
|
def __str__(self):
|
|
449
|
+
term_str = ""
|
|
437
450
|
path = get_snl_path_from_id_list(self.pathIDs)
|
|
438
451
|
if path.size() == 0:
|
|
439
|
-
|
|
452
|
+
term_str = get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()
|
|
440
453
|
else:
|
|
441
|
-
|
|
454
|
+
term_str = (
|
|
442
455
|
f"{path}/{get_snl_term_for_ids(self.pathIDs, self.termIDs).getName()}"
|
|
443
456
|
)
|
|
457
|
+
if self.is_bus:
|
|
458
|
+
term_str += f"[{self.get_msb()}:{self.get_lsb()}]"
|
|
459
|
+
elif self.is_bus_bit:
|
|
460
|
+
term_str += f"[{self.get_lsb()}]"
|
|
461
|
+
return term_str
|
|
444
462
|
|
|
445
463
|
def __repr__(self) -> str:
|
|
446
464
|
path = get_snl_path_from_id_list(self.pathIDs)
|
|
@@ -486,6 +504,17 @@ class Term:
|
|
|
486
504
|
"""
|
|
487
505
|
return self.is_scalar() or self.is_bus_bit()
|
|
488
506
|
|
|
507
|
+
def get_bit_number(self):
|
|
508
|
+
"""
|
|
509
|
+
:return: the bit index of the term if it is a bit.
|
|
510
|
+
:rtype: int or None
|
|
511
|
+
"""
|
|
512
|
+
if isinstance(
|
|
513
|
+
get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTermBit
|
|
514
|
+
):
|
|
515
|
+
return get_snl_term_for_ids(self.pathIDs, self.termIDs).getBit()
|
|
516
|
+
return None
|
|
517
|
+
|
|
489
518
|
def get_msb(self) -> int:
|
|
490
519
|
"""
|
|
491
520
|
:return: the most significant bit of the term if it is a bus.
|
|
@@ -651,7 +680,7 @@ class Term:
|
|
|
651
680
|
if isinstance(get_snl_term_for_ids(self.pathIDs, self.termIDs), snl.SNLBusTerm):
|
|
652
681
|
return Term(
|
|
653
682
|
self.pathIDs,
|
|
654
|
-
get_snl_term_for_ids(self.pathIDs, self.termIDs).
|
|
683
|
+
get_snl_term_for_ids(self.pathIDs, self.termIDs).getBusTermBit(index),
|
|
655
684
|
)
|
|
656
685
|
return None
|
|
657
686
|
|
|
@@ -754,13 +783,23 @@ class Instance:
|
|
|
754
783
|
"""
|
|
755
784
|
|
|
756
785
|
def __init__(self, path=snl.SNLPath()):
|
|
786
|
+
self.inst = None
|
|
787
|
+
self.revisionCount = 0
|
|
788
|
+
self.SNLID = [0, 0, 0, 0, 0, 0]
|
|
757
789
|
if isinstance(path, snl.SNLPath):
|
|
758
790
|
if path.size() > 0:
|
|
759
791
|
self.pathIDs = path.getPathIDs()
|
|
792
|
+
self.revisionCount = path.getTailInstance().getModel().getRevisionCount()
|
|
793
|
+
self.inst = path.getTailInstance()
|
|
760
794
|
else:
|
|
761
795
|
self.pathIDs = []
|
|
762
796
|
elif isinstance(path, list):
|
|
763
797
|
self.pathIDs = path.copy()
|
|
798
|
+
if len(path) > 0:
|
|
799
|
+
self.inst = get_snl_instance_from_id_list(path)
|
|
800
|
+
self.revisionCount = self.inst.getModel().getRevisionCount()
|
|
801
|
+
if self.inst is not None:
|
|
802
|
+
self.SNLID = self.inst.getModel().getSNLID()
|
|
764
803
|
|
|
765
804
|
def __eq__(self, other) -> bool:
|
|
766
805
|
return self.pathIDs == other.pathIDs
|
|
@@ -872,11 +911,24 @@ class Instance:
|
|
|
872
911
|
"""
|
|
873
912
|
return self.__get_snl_model().isInv()
|
|
874
913
|
|
|
914
|
+
def is_basic_primitive(instance):
|
|
915
|
+
design = instance.__get_snl_model()
|
|
916
|
+
return (
|
|
917
|
+
design.isConst0() or design.isConst1() or design.isBuf() or design.isInv()
|
|
918
|
+
)
|
|
919
|
+
|
|
875
920
|
def __get_snl_model(self):
|
|
876
921
|
if self.is_top():
|
|
877
922
|
return snl.SNLUniverse.get().getTopDesign()
|
|
878
|
-
|
|
879
|
-
|
|
923
|
+
if (
|
|
924
|
+
self.inst.getModel().getRevisionCount() != self.revisionCount or
|
|
925
|
+
self.inst.getModel().getSNLID() != self.SNLID
|
|
926
|
+
):
|
|
927
|
+
self.inst = get_snl_instance_from_id_list(self.pathIDs)
|
|
928
|
+
self.revisionCount = self.inst.getModel().getRevisionCount()
|
|
929
|
+
self.SNLID = self.inst.getModel().getSNLID()
|
|
930
|
+
|
|
931
|
+
return self.inst.getModel()
|
|
880
932
|
|
|
881
933
|
def __get_leaf_snl_object(self):
|
|
882
934
|
if self.is_top():
|
|
@@ -919,10 +971,11 @@ class Instance:
|
|
|
919
971
|
:return: an iterator over the child instances of this instance.
|
|
920
972
|
:rtype: Iterator[Instance]
|
|
921
973
|
"""
|
|
974
|
+
path = get_snl_path_from_id_list(self.pathIDs)
|
|
922
975
|
for inst in self.__get_snl_model().getInstances():
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
976
|
+
path_child = snl.SNLPath(path, inst)
|
|
977
|
+
yield Instance(path_child)
|
|
978
|
+
# path.pop()
|
|
926
979
|
|
|
927
980
|
def get_number_of_child_instances(self) -> int:
|
|
928
981
|
"""
|
|
@@ -1181,7 +1234,7 @@ class Instance:
|
|
|
1181
1234
|
path = get_snl_path_from_id_list(self.pathIDs)
|
|
1182
1235
|
design = self.__get_snl_model()
|
|
1183
1236
|
newSNLTerm = snl.SNLScalarTerm.create(design, direction, name)
|
|
1184
|
-
return Term(path, newSNLTerm)
|
|
1237
|
+
return Term(path.getPathIDs(), newSNLTerm)
|
|
1185
1238
|
|
|
1186
1239
|
def create_output_term(self, name: str) -> Term:
|
|
1187
1240
|
"""Create an output Term in this Instance with the given name.
|
|
@@ -1222,10 +1275,9 @@ class Instance:
|
|
|
1222
1275
|
path = get_snl_path_from_id_list(self.pathIDs)
|
|
1223
1276
|
if path.size() > 0:
|
|
1224
1277
|
snl.SNLUniquifier(path)
|
|
1225
|
-
path = get_snl_path_from_id_list(self.pathIDs)
|
|
1226
1278
|
design = self.__get_snl_model()
|
|
1227
1279
|
newSNLTerm = snl.SNLBusTerm.create(design, direction, msb, lsb, name)
|
|
1228
|
-
return Term(
|
|
1280
|
+
return Term(self.pathIDs, newSNLTerm)
|
|
1229
1281
|
|
|
1230
1282
|
def create_inout_bus_term(self, name: str, msb: int, lsb: int) -> Term:
|
|
1231
1283
|
"""Create an inout bus Term in this Instance with the given name, msb and lsb.
|
|
@@ -1300,6 +1352,13 @@ class Instance:
|
|
|
1300
1352
|
"""
|
|
1301
1353
|
self.__get_snl_model().dumpVerilog(path, name)
|
|
1302
1354
|
|
|
1355
|
+
def get_truth_table(self):
|
|
1356
|
+
"""
|
|
1357
|
+
:return: the truth table of the instance.
|
|
1358
|
+
:rtype: list[str]
|
|
1359
|
+
"""
|
|
1360
|
+
return self.__get_snl_model().getTruthTable()
|
|
1361
|
+
|
|
1303
1362
|
|
|
1304
1363
|
def get_top_db() -> snl.SNLDB:
|
|
1305
1364
|
if snl.SNLUniverse.get() is None:
|
|
@@ -1334,10 +1393,17 @@ def create_top(name: str) -> Instance:
|
|
|
1334
1393
|
return Instance()
|
|
1335
1394
|
|
|
1336
1395
|
|
|
1337
|
-
|
|
1396
|
+
class VerilogConfig:
|
|
1397
|
+
def __init__(self, keep_assigns=True):
|
|
1398
|
+
self.keep_assigns = keep_assigns
|
|
1399
|
+
|
|
1400
|
+
|
|
1401
|
+
def load_verilog(files: list, config: VerilogConfig = None) -> Instance:
|
|
1402
|
+
if config is None:
|
|
1403
|
+
config = VerilogConfig() # Use default settings
|
|
1338
1404
|
start_time = time.time()
|
|
1339
1405
|
logging.info(f"Loading verilog: {', '.join(files)}")
|
|
1340
|
-
get_top_db().loadVerilog(files)
|
|
1406
|
+
get_top_db().loadVerilog(files, keep_assigns=config.keep_assigns)
|
|
1341
1407
|
execution_time = time.time() - start_time
|
|
1342
1408
|
logging.info(f"Loading done in {execution_time:.2f} seconds")
|
|
1343
1409
|
return get_top()
|
najaeda/primitives/xilinx.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
|
|
5
|
+
import logging
|
|
5
6
|
from najaeda import snl
|
|
6
7
|
|
|
7
8
|
|
|
@@ -426,6 +427,7 @@ def constructRAMB36E1(lib):
|
|
|
426
427
|
|
|
427
428
|
|
|
428
429
|
def load(db):
|
|
430
|
+
logging.info("Loading Xilinx primitives")
|
|
429
431
|
lib = snl.SNLLibrary.createPrimitives(db, "xilinx")
|
|
430
432
|
constructIBUF(lib)
|
|
431
433
|
constructOBUF(lib)
|
najaeda/snl.so
CHANGED
|
Binary file
|
najaeda/stats.py
CHANGED
|
@@ -150,10 +150,8 @@ class InstanceStats:
|
|
|
150
150
|
)
|
|
151
151
|
|
|
152
152
|
|
|
153
|
-
def is_basic_primitive(
|
|
154
|
-
return (
|
|
155
|
-
design.is_const0() or design.is_const1() or design.is_buf() or design.is_inv()
|
|
156
|
-
)
|
|
153
|
+
def is_basic_primitive(instance):
|
|
154
|
+
return instance.is_basic_primitive()
|
|
157
155
|
|
|
158
156
|
|
|
159
157
|
def compute_instance_stats(instance, instances_stats):
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
najaeda/netlist.py,sha256=
|
|
2
|
-
najaeda/libnaja_snl_python.dylib,sha256=
|
|
1
|
+
najaeda/netlist.py,sha256=FadEyKqZMS5cGzDt-WOZRmDcDc3dFFvQSw2iJusW7Y0,49236
|
|
2
|
+
najaeda/libnaja_snl_python.dylib,sha256=hn_lZr90ne3WHgWoG4epgWooshxMItzUm-PZs9W3Qag,887680
|
|
3
3
|
najaeda/pandas_stats.py,sha256=yOb4ka965U7rN4D6AwvSGmRyeT_O7Ed-5cmT8BFbfeo,1070
|
|
4
4
|
najaeda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
najaeda/
|
|
6
|
-
najaeda/
|
|
7
|
-
najaeda/
|
|
5
|
+
najaeda/net_visitor.py,sha256=P_esjibYb-wBDuF-AyF7es9sJYw1Ha8RhTPu-qKe7G4,1940
|
|
6
|
+
najaeda/libnaja_snl.dylib,sha256=_W6nRABcp6q9xoBF0hTOBDWwHBUB6-n8anUoTyNkn-s,574288
|
|
7
|
+
najaeda/snl.so,sha256=vOvrtrEd8rj7C5on32f29P2XFkCfDvyIhSlfrjLn3pY,98272
|
|
8
|
+
najaeda/stats.py,sha256=wackXsf0x24ic9v-UifECHj4t5yveUWssMDZp2B057A,16187
|
|
8
9
|
najaeda/instance_visitor.py,sha256=JMsPSQaWNiDjxS05rxg83a0PIsrOIuTi9G35hkwdibs,1530
|
|
10
|
+
najaeda/native/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
najaeda/native/stats.py,sha256=3iIPr-jitdMhbHthA4BauaTXwx1ijYIQuXwtoDyCf-A,13056
|
|
9
12
|
najaeda/docs/requirements.txt,sha256=1XIBGTIplm2arC9HhDCfLuAjozGdVSXkqmOj8ybuT6U,121
|
|
10
13
|
najaeda/docs/.readthedocs.yaml,sha256=nN_Psro-YdfPcIiueZkJcZepts68g23rqVThhKnmVRw,790
|
|
11
14
|
najaeda/docs/source/index.rst,sha256=80VMfeEGHObnOUXRBxIzISQsG_HNkgT-pUpsDZsCfOY,387
|
|
@@ -21,10 +24,12 @@ najaeda/docs/source/equipotential.rst,sha256=0MDi-4fPEsX7K_ezWj5DB3mCalnhqN-sicY
|
|
|
21
24
|
najaeda/docs/source/netlist_classes.rst,sha256=Zrha9MQVEdEwxmP2zhgC0K3iioZXXerzeFoOz5SrOXM,132
|
|
22
25
|
najaeda/docs/source/introduction.rst,sha256=kE4qxEJCgcAswiT3rIJS21oBYIMg1cyT_rKmOzQgvsI,2095
|
|
23
26
|
najaeda/docs/source/api.rst,sha256=47VCPyF4Py_1cklZ3q9fmOMhqqI17rxwU_VUJETfCwY,151
|
|
27
|
+
najaeda/.dylibs/libcapnp-1.1.0.dylib,sha256=l9SvRdxPrCI2mB_UitO7QjsaC7I5mq2R3rZjoIQKEYI,709328
|
|
28
|
+
najaeda/.dylibs/libkj-1.1.0.dylib,sha256=pB7dMks8b8ybJ6xKWqFR_hHjKsmpf7wzbcunZaS7gO4,578320
|
|
24
29
|
najaeda/primitives/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
|
-
najaeda/primitives/xilinx.py,sha256=
|
|
26
|
-
najaeda-0.1.
|
|
27
|
-
najaeda-0.1.
|
|
28
|
-
najaeda-0.1.
|
|
29
|
-
najaeda-0.1.
|
|
30
|
-
najaeda-0.1.
|
|
30
|
+
najaeda/primitives/xilinx.py,sha256=_VPQfWAp3oc4EgOzW-gy96BXdFZK6E4C7aOSdCn4JRU,26008
|
|
31
|
+
najaeda-0.1.14.dist-info/RECORD,,
|
|
32
|
+
najaeda-0.1.14.dist-info/WHEEL,sha256=bS2kxwU1pioFffhNQmlfvjD0H1flBf5ZtxV4jDj8Nvc,114
|
|
33
|
+
najaeda-0.1.14.dist-info/METADATA,sha256=80hWLRV3mUTPKIbrne0o4kPXICFNFUO9oPtLN6zpA7o,2475
|
|
34
|
+
najaeda-0.1.14.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
35
|
+
najaeda-0.1.14.dist-info/licenses/AUTHORS,sha256=7NYEGDAX_1QZvCCHfq8YVXC5ZbwH_pbNI8DcSmm70GU,377
|
|
File without changes
|
|
File without changes
|
|
File without changes
|