najaeda 0.1.6__cp39-cp39-macosx_11_0_arm64.whl → 0.1.8__cp39-cp39-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/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.6
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', 'arm_core_netlist.v')])
100
+ top = netlist.load_verilog([path.join(benchmarks, 'verilog', 'vexriscv.v')])
96
101
 
97
102
  Print all the instances in the netlist
98
103
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -144,6 +149,37 @@ This specific use case shows how to count the number of leaf instances in a netl
144
149
  print(f"nb constants={leaves['constants']}")
145
150
  print(f"nb other leaves={leaves['count']}")
146
151
 
152
+ DLE (Dead Logic Elimination)
153
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
154
+ This example demonstrates how to perform Dead Logic Elimination (DLE) on a netlist.
155
+
156
+ .. code-block:: python
157
+
158
+ def apply_dle(top):
159
+ # Trace back from design outputs
160
+ visited = set()
161
+ output_terms = top.get_flat_output_terms()
162
+ for termToTrace in output_terms:
163
+ queue = deque([termToTrace])
164
+ while queue:
165
+ term = queue.popleft()
166
+ if term in visited:
167
+ continue
168
+ visited.add(term)
169
+ equipotential = term.get_equipotential()
170
+ leaf_drivers = equipotential.get_leaf_drivers()
171
+ for driver in leaf_drivers:
172
+ instance = driver.get_instance()
173
+ instances.add(instance)
174
+ input_terms = instance.get_flat_input_terms()
175
+ queue.extend(input_terms)
176
+
177
+ leaf_children = top.get_leaf_children()
178
+ to_delete = [leaf for leaf in leaf_children if leaf not in instances]
179
+ for leaf in to_delete:
180
+ leaf.delete()
181
+ return to_delete
182
+
147
183
  Documentation
148
184
  -------------
149
185
  Naja EDA is a work in progress, and the documentation is still under development.
@@ -0,0 +1,25 @@
1
+ najaeda-0.1.8.dist-info/RECORD,,
2
+ najaeda-0.1.8.dist-info/WHEEL,sha256=Qmm8uWPQTspuPJ9tUBLJdmqmcf0_LWu4zzBSlc_SSWo,112
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=-PzmvQSTQEJjrxor6S7BQtzv56JJpUbeA8Yknwav8P8,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
@@ -1,18 +0,0 @@
1
- najaeda/netlist.py,sha256=Lg0JHaYD1xJl-tOFxdUorkev8TonBP8RNqDnxViOsxg,25751
2
- najaeda/libnaja_snl_python.dylib,sha256=6dVXWXS0ofwGPtcG1B8V_WA-UIr7E-uDCuMgBiNiies,740160
3
- najaeda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- najaeda/libnaja_snl.dylib,sha256=8Ei7KKU0b14IqlvH_8yQSSCpH0rjbxpeRaXgyfSemMY,574112
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/make.bat,sha256=L4I5T7uDUIjwGyMRJ-y9FoT61sxIyCuaYuJyLt8c-nA,804
9
- najaeda/docs/source/index.rst,sha256=VBWfJySZ9v8mWfWt3kuSCZh7Gp0zUrFjXGQH7tZZfy0,323
10
- najaeda/docs/source/conf.py,sha256=3qkykCg12ZYqawHl8VEg2Fti6rc3G-soGYM0L6zL3CU,1387
11
- najaeda/docs/source/api.rst,sha256=H2Bw0JmHS9z-NhQARepmH74wsWHzjSVPbeXppSmtgCQ,141
12
- najaeda/primitives/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- najaeda/primitives/xilinx.py,sha256=fuu4KxEIuC0ueCK4C_gds6hzgtJsLE3tjDtOHtY9McM,25947
14
- najaeda-0.1.6.dist-info/RECORD,,
15
- najaeda-0.1.6.dist-info/WHEEL,sha256=Qmm8uWPQTspuPJ9tUBLJdmqmcf0_LWu4zzBSlc_SSWo,112
16
- najaeda-0.1.6.dist-info/METADATA,sha256=BNHiU6acY0ppMEC7I66Q34H4oDDalUoepVBas2Oqr5E,5608
17
- najaeda-0.1.6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
18
- najaeda-0.1.6.dist-info/licenses/AUTHORS,sha256=7NYEGDAX_1QZvCCHfq8YVXC5ZbwH_pbNI8DcSmm70GU,377