From b4b9333b0207d124d2884a3c0b50e21ae78fb289 Mon Sep 17 00:00:00 2001 From: Christophe Alexandre Date: Thu, 17 Oct 2024 16:14:15 +0200 Subject: [PATCH] Readme restructured (#114) * Rework README * Rework new Python scripts page * typo * Restructuring README, regress and naja_edit examples * start moving regress to naja_edit examples * update examples * update examples * reuse cleaning * Improve README and naja_edit examples * more cleaning --- .gitignore | 30 ++--- .reuse/dep5 | 2 +- Dockerfile.regress | 2 +- README.md | 84 +----------- README_pages/images/design_stats.png | Bin 0 -> 47760 bytes README_pages/naja-edit-python-examples.md | 122 ++++++++++++++++++ regress/Makefile.inc | 8 -- regress/arm_core/src/add_error.py | 46 ------- .../apps/naja_edit/examples}/Makefile | 0 src/apps/naja_edit/examples/Makefile.inc | 8 ++ .../apps/naja_edit/examples}/adder/Makefile | 5 +- .../naja_edit/examples}/adder/src/adder.v | 0 .../naja_edit/examples}/adder/src/comp.ys | 0 .../naja_edit/examples}/adder/src/synth.ys | 0 .../naja_edit/examples}/arm_core/Makefile | 14 +- .../examples}/arm_core/gen_edge_list.py | 0 .../examples}/arm_core/src/arm_core.v | 0 .../naja_edit/examples}/arm_core/src/comp.eqy | 0 .../examples}/arm_core/src/comp_error.ys | 0 .../examples}/arm_core/src/comp_gold.ys | 0 .../naja_edit/examples}/arm_core/src/synth.ys | 0 .../examples/scripts/plot_designs_stats.py | 36 ++++++ .../examples/scripts/print_design_tree.py | 20 +++ .../examples/scripts/remove_iobufs.py | 27 ++++ .../naja_edit/examples}/test_args/Makefile | 0 .../naja_edit/examples}/test_args/module1.v | 0 .../naja_edit/examples}/test_args/module2.v | 0 .../apps/naja_edit/examples}/test_args/top.v | 0 .../naja_edit/examples}/vexriscv/Makefile | 0 .../naja_edit/examples}/vexriscv/src/comp.ys | 0 .../naja_edit/examples}/vexriscv/src/synth.ys | 0 .../vexriscv/src/vexriscv.demo.GenFull.v | 0 32 files changed, 244 insertions(+), 160 deletions(-) create mode 100644 README_pages/images/design_stats.png create mode 100644 README_pages/naja-edit-python-examples.md delete mode 100644 regress/Makefile.inc delete mode 100644 regress/arm_core/src/add_error.py rename {regress => src/apps/naja_edit/examples}/Makefile (100%) create mode 100644 src/apps/naja_edit/examples/Makefile.inc rename {regress => src/apps/naja_edit/examples}/adder/Makefile (77%) rename {regress => src/apps/naja_edit/examples}/adder/src/adder.v (100%) rename {regress => src/apps/naja_edit/examples}/adder/src/comp.ys (100%) rename {regress => src/apps/naja_edit/examples}/adder/src/synth.ys (100%) rename {regress => src/apps/naja_edit/examples}/arm_core/Makefile (71%) rename {regress => src/apps/naja_edit/examples}/arm_core/gen_edge_list.py (100%) rename {regress => src/apps/naja_edit/examples}/arm_core/src/arm_core.v (100%) rename {regress => src/apps/naja_edit/examples}/arm_core/src/comp.eqy (100%) rename {regress => src/apps/naja_edit/examples}/arm_core/src/comp_error.ys (100%) rename {regress => src/apps/naja_edit/examples}/arm_core/src/comp_gold.ys (100%) rename {regress => src/apps/naja_edit/examples}/arm_core/src/synth.ys (100%) create mode 100644 src/apps/naja_edit/examples/scripts/plot_designs_stats.py create mode 100644 src/apps/naja_edit/examples/scripts/print_design_tree.py create mode 100644 src/apps/naja_edit/examples/scripts/remove_iobufs.py rename {regress => src/apps/naja_edit/examples}/test_args/Makefile (100%) rename {regress => src/apps/naja_edit/examples}/test_args/module1.v (100%) rename {regress => src/apps/naja_edit/examples}/test_args/module2.v (100%) rename {regress => src/apps/naja_edit/examples}/test_args/top.v (100%) rename {regress => src/apps/naja_edit/examples}/vexriscv/Makefile (100%) rename {regress => src/apps/naja_edit/examples}/vexriscv/src/comp.ys (100%) rename {regress => src/apps/naja_edit/examples}/vexriscv/src/synth.ys (100%) rename {regress => src/apps/naja_edit/examples}/vexriscv/src/vexriscv.demo.GenFull.v (100%) diff --git a/.gitignore b/.gitignore index 6e68d6fd..5fae92fd 100644 --- a/.gitignore +++ b/.gitignore @@ -7,26 +7,22 @@ *.DS_Store build install +venv .vscode __pycache__ -regress/test_args/*.log -regress/adder/*.v -regress/vexriscv/*.v -regress/arm_core/*.v -regress/arm_core/*.log -regress/arm_core/*.gold -regress/arm_core/*.error -regress/*/abc.history +src/apps/naja_edit/examples/**/*.log +src/apps/naja_edit/examples/**/*.png +src/apps/naja_edit/examples/adder/*.v +src/apps/naja_edit/examples/vexriscv/*.v +src/apps/naja_edit/examples/arm_core/*.v +src/apps/naja_edit/examples/arm_core/*_snl +src/apps/naja_edit/examples/arm_core/*.gold +src/apps/naja_edit/examples/arm_core/*.error +src/apps/naja_edit/examples/arm_core/*.list +src/apps/naja_edit/examples/*/abc.history src/apps/naja_edit/examples/abc.history src/apps/naja_edit/examples/addaccu/addaccu_*.v -src/apps/naja_edit/examples/addaccu/*.log src/apps/naja_edit/examples/addaccu/*.txt src/apps/naja_edit/examples/addaccu/*_snl -regress/arm_core/comp/* -regress/arm_core/nodes.list -regress/arm_core/edges.list -regress/arm_core/arm_core_snl/* -regress/jpeg/*.log -regress/jpeg/jpeg_encoder_snl/* -regress/black_parrot/*.log -regress/black_parrot/black_parrot_snl/* \ No newline at end of file +src/apps/naja_edit/examples/test_args/top_out.v +src/apps/naja_edit/examples/adder/verilator.done diff --git a/.reuse/dep5 b/.reuse/dep5 index 0b153997..336666bc 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -7,7 +7,7 @@ Files: .github/workflows/* .gitmodules Copyright: 2022 The Naja Authors. License: Apache-2.0 -Files: README.md AUTHORS docs/* +Files: README.md README_pages/* AUTHORS docs/* Copyright: 2022 The Naja Authors. License: Apache-2.0 diff --git a/Dockerfile.regress b/Dockerfile.regress index 38476c20..c9836ff4 100644 --- a/Dockerfile.regress +++ b/Dockerfile.regress @@ -41,7 +41,7 @@ RUN rm -rf /naja-install WORKDIR /naja/build RUN cmake .. -DCMAKE_INSTALL_PREFIX=/naja-install && make -j$(nproc) && make install -WORKDIR /naja/regress +WORKDIR /naja/src/apps/naja_edit/examples ENV SET_PYTHONPATH=/naja-install/lib/python ENV LD_LIBRARY_PATH=/naja-install/lib ENV NAJA_EDIT=/naja-install/bin/naja_edit diff --git a/README.md b/README.md index 0cc177f7..a8511674 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,6 @@ Naja is an Electronic Design Automation (EDA) project that provides open source Naja best starting point is: [naja-edit](#naja_edit). - - ### Acknowledgement [](https://nlnet.nl/project/Naja) @@ -29,6 +27,8 @@ This project is supported and funded by NLNet through the [NGI0 Entrust](https:/ `naja_edit`, located in the `$NAJA_INSTALL/bin` directory, is a tool designed for optimizing, editing and translating netlists. +:tv: We presented naja_edit’s latest features and results at [ORConf 2024](https://fossi-foundation.org/orconf/2024). You can watch the full presentation [here](https://www.youtube.com/watch?v=JpwZGCuWekU). + ### Workflow Overview The workflow for `naja_edit` is outlined in the schema below. It's important to note that the only mandatory step in the process is the initial loading of the input netlist. @@ -71,85 +71,13 @@ naja_edit -f snl -t snl -i input.snl -o output.snl -a dle \ -e pre_script.py -z post_edit.py ``` -`naja_edit` editing script examples are available [here](https://github.com/najaeda/naja/blob/main/src/apps/edit/examples). +This [page](README_pages/naja-edit-python-examples.md) provides a collection of example Python scripts for using the naja_edit API. + +`naja_edit` editing script examples are also available [here](https://github.com/najaeda/naja/blob/main/src/apps/najae_edit/examples). The [Naja Regress](https://github.com/najaeda/naja-regress) repository features a collection of examples showcasing extensive use of `naja_edit`. -### Python API Examples - -To use the Python API in `naja_edit`, start by creating a Python script containing an `edit` function. - -```python -from naja import snl - -def edit(): - universe = snl.SNLUniverse.get() - top = universe.getTopDesign() - - # Do something with 'top' -``` - -#### Print All Design Content - -The following script recursively browses the design and prints instances, terminals, nets, and their connectivity. - -```python -from naja import snl - -def print_instance_tree(design): - for ins in design.getInstances(): - print(f"Instance: {ins.getName()}") - model = ins.getModel() - for term in design.getTerms(): - print(f" Terminal: {term}") - for net in design.getNets(): - print(f" Net: {net}") - for bit in net.getBits(): - for component in bit.getComponents(): - print(f" Component: {component}") - print_instance_tree(model) - -def edit(): - universe = snl.SNLUniverse.get() - top = universe.getTopDesign() - - print_instance_tree(top) -``` - -#### Remove Interface Buffers from an FPGA Design - -The following script removes interface buffers `'IBUF'`, `'OBUF'`, and `'BUFG'` from a design synthesized for an FPGA. - -```python -from naja import snl - -def delete_io_bufs(design): - for ins in design.getInstances(): - model = ins.getModel() - if model.isPrimitive(): - model_name = model.getName() - if model_name in ['IBUF', 'BUFG']: - input_net = ins.getInstTerm(model.getScalarTerm('I')).getNet() - output_net = ins.getInstTerm(model.getScalarTerm('O')).getNet() - for component in output_net.getComponents(): - component.setNet(input_net) - output_net.destroy() - ins.destroy() - elif model_name == 'OBUF': - input_net = ins.getInstTerm(model.getScalarTerm('I')).getNet() - output_net = ins.getInstTerm(model.getScalarTerm('O')).getNet() - for component in input_net.getComponents(): - component.setNet(output_net) - input_net.destroy() - ins.destroy() - -def edit(): - universe = snl.SNLUniverse.get() - top = universe.getTopDesign() - - delete_io_bufs(top) -```
[ ↑ Back to top ↑ ]
@@ -314,7 +242,7 @@ capnp decode --packed snl_implementation.capnp DBImplementation < snl/db_impleme ##### Verilog -For Verilog parsing, Naja relies on naja-verilog submodule (https://github.com/najaeda/naja-verilog). +For Verilog parsing, Naja relies on naja-verilog [submodule](https://github.com/najaeda/naja-verilog). Leaf primitives are loaded through the Python primitive loader: [SNLPrimitivesLoader](https://github.com/najaeda/naja/blob/main/src/snl/python/primitives/SNLPrimitivesLoader.h). An application snippet can be found [here](https://github.com/najaeda/naja/blob/main/src/snl/snippets/app/src/SNLVRLSnippet.cpp) and examples of primitive libraries described using the Python interface can be found in the diff --git a/README_pages/images/design_stats.png b/README_pages/images/design_stats.png new file mode 100644 index 0000000000000000000000000000000000000000..86315790cf9b0995334fe84de780194bcc10e986 GIT binary patch literal 47760 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�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 n: - break - - #get n nets and destroy - n = 20 - destroyed = 0 - for net in top.getNets(): - destroyed += 1 - net.destroy() - if destroyed > n: - break - - - #lut14Mask = lut14.getInstParameter('INIT') - #if lut14Mask is None: - # logging.critical('cannot find \'INIT\' in ' + str(lut14)) - # return 1 - #else: - # logging.info('Found ' + str(lut14Mask)) - - #lut14Mask.setValue('8\'hfb') - - - diff --git a/regress/Makefile b/src/apps/naja_edit/examples/Makefile similarity index 100% rename from regress/Makefile rename to src/apps/naja_edit/examples/Makefile diff --git a/src/apps/naja_edit/examples/Makefile.inc b/src/apps/naja_edit/examples/Makefile.inc new file mode 100644 index 00000000..b88eca81 --- /dev/null +++ b/src/apps/naja_edit/examples/Makefile.inc @@ -0,0 +1,8 @@ +YOSYS ?= yosys +EQY ?= eqy +VERILATOR ?= verilator +NAJA_EDIT ?= ../../../../../install/bin/naja_edit +PRIMITIVES ?= ../../../../../primitives/xilinx.py +ASAP7_PRIMITIVES ?= $(realpath ../../../primitives/asap7.py) +NANGATE45_PRIMITIVES ?= $(realpath ../../../primitives/nangate45.py) +SET_PYTHONPATH ?= ../../../../../install/lib/python diff --git a/regress/adder/Makefile b/src/apps/naja_edit/examples/adder/Makefile similarity index 77% rename from regress/adder/Makefile rename to src/apps/naja_edit/examples/adder/Makefile index 8089ffbe..9f3b8a58 100644 --- a/regress/adder/Makefile +++ b/src/apps/naja_edit/examples/adder/Makefile @@ -1,9 +1,10 @@ include ../Makefile.inc -all: adder_snl.v primitives.v verilator +all: adder_snl.v primitives.v verilator.done -verilator: adder_snl.v primitives.v +verilator.done: adder_snl.v primitives.v ${VERILATOR} --top-module adder --lint-only primitives.v adder_snl.v + touch verilator.done adder_netlist.v: src/adder.v ${YOSYS} src/synth.ys diff --git a/regress/adder/src/adder.v b/src/apps/naja_edit/examples/adder/src/adder.v similarity index 100% rename from regress/adder/src/adder.v rename to src/apps/naja_edit/examples/adder/src/adder.v diff --git a/regress/adder/src/comp.ys b/src/apps/naja_edit/examples/adder/src/comp.ys similarity index 100% rename from regress/adder/src/comp.ys rename to src/apps/naja_edit/examples/adder/src/comp.ys diff --git a/regress/adder/src/synth.ys b/src/apps/naja_edit/examples/adder/src/synth.ys similarity index 100% rename from regress/adder/src/synth.ys rename to src/apps/naja_edit/examples/adder/src/synth.ys diff --git a/regress/arm_core/Makefile b/src/apps/naja_edit/examples/arm_core/Makefile similarity index 71% rename from regress/arm_core/Makefile rename to src/apps/naja_edit/examples/arm_core/Makefile index 41515719..28072a56 100644 --- a/regress/arm_core/Makefile +++ b/src/apps/naja_edit/examples/arm_core/Makefile @@ -1,10 +1,10 @@ include ../Makefile.inc -all: edges.list verif.gold verilator.gold verif.error +all: edges.list verif.gold verilator.gold -verif.error: arm_core_snl_error.v primitives.v - ${YOSYS} src/comp_error.ys - touch $@ +#verif.error: arm_core_snl_error.v primitives.v +# ${YOSYS} src/comp_error.ys +# touch $@ verif.gold: arm_core_snl.v primitives.v ${YOSYS} src/comp_gold.ys @@ -34,9 +34,9 @@ arm_core_snl.v primitives.v: arm_core_netlist.v export PYTHONPATH=${SET_PYTHONPATH}; \ ${NAJA_EDIT} -f verilog -t verilog -p ${PRIMITIVES} -i arm_core_netlist.v -o arm_core_snl.v -d primitives.v -arm_core_snl_error.v: arm_core_netlist.v src/add_error.py - export PYTHONPATH=${SET_PYTHONPATH}; \ - ${NAJA_EDIT} -e src/add_error.py -f verilog -t verilog -p ${PRIMITIVES} -i arm_core_netlist.v -o arm_core_snl_error.v -d primitives.v +arm_core_snl_error.v: arm_core_netlist.v ../scripts/plot_designs_stats.py + export PYTHONPATH=${SET_PYTHONPATH}:./venv/lib/python3.12/site-packages; \ + ${NAJA_EDIT} -e ../scripts/plot_designs_stats.py -f verilog -p ${PRIMITIVES} -i arm_core_netlist.v clean: -rm arm_core_snl.v primitives.v arm_core_netlist.v diff --git a/regress/arm_core/gen_edge_list.py b/src/apps/naja_edit/examples/arm_core/gen_edge_list.py similarity index 100% rename from regress/arm_core/gen_edge_list.py rename to src/apps/naja_edit/examples/arm_core/gen_edge_list.py diff --git a/regress/arm_core/src/arm_core.v b/src/apps/naja_edit/examples/arm_core/src/arm_core.v similarity index 100% rename from regress/arm_core/src/arm_core.v rename to src/apps/naja_edit/examples/arm_core/src/arm_core.v diff --git a/regress/arm_core/src/comp.eqy b/src/apps/naja_edit/examples/arm_core/src/comp.eqy similarity index 100% rename from regress/arm_core/src/comp.eqy rename to src/apps/naja_edit/examples/arm_core/src/comp.eqy diff --git a/regress/arm_core/src/comp_error.ys b/src/apps/naja_edit/examples/arm_core/src/comp_error.ys similarity index 100% rename from regress/arm_core/src/comp_error.ys rename to src/apps/naja_edit/examples/arm_core/src/comp_error.ys diff --git a/regress/arm_core/src/comp_gold.ys b/src/apps/naja_edit/examples/arm_core/src/comp_gold.ys similarity index 100% rename from regress/arm_core/src/comp_gold.ys rename to src/apps/naja_edit/examples/arm_core/src/comp_gold.ys diff --git a/regress/arm_core/src/synth.ys b/src/apps/naja_edit/examples/arm_core/src/synth.ys similarity index 100% rename from regress/arm_core/src/synth.ys rename to src/apps/naja_edit/examples/arm_core/src/synth.ys diff --git a/src/apps/naja_edit/examples/scripts/plot_designs_stats.py b/src/apps/naja_edit/examples/scripts/plot_designs_stats.py new file mode 100644 index 00000000..b362614f --- /dev/null +++ b/src/apps/naja_edit/examples/scripts/plot_designs_stats.py @@ -0,0 +1,36 @@ +from naja import snl +import pandas as pd +import matplotlib.pyplot as plt + + +def plot_design_stats(library): + data_list = [] + for design in library.getDesigns(): + nb_terms = sum(1 for _ in design.getBitTerms()) + nb_nets = sum(1 for _ in design.getBitNets()) + nb_instances = sum(1 for _ in design.getInstances()) + data_list.append({ + 'design': design.getName(), + 'nb_terms': nb_terms, + 'nb_nets': nb_nets, + 'nb_instances': nb_instances + }) + pandas_data = pd.DataFrame(data_list).set_index('design') + plot = pandas_data.plot.bar(y=['nb_terms', 'nb_nets', 'nb_instances'], stacked=True) + + # Set title and labels + plot.set_title('Design Statistics', fontsize=16, fontweight='bold') + plot.set_xlabel('Design Name', fontsize=12) + plot.set_ylabel('Count', fontsize=12) + + plot_figure = plot.get_figure() + plot_figure.tight_layout() + plot_figure.savefig('design_stats.png') + + +def edit(): + universe = snl.SNLUniverse.get() + topDesign = universe.getTopDesign() + topLibrary = topDesign.getLibrary() #top library contains top design + + plot_design_stats(topLibrary) \ No newline at end of file diff --git a/src/apps/naja_edit/examples/scripts/print_design_tree.py b/src/apps/naja_edit/examples/scripts/print_design_tree.py new file mode 100644 index 00000000..ac58beff --- /dev/null +++ b/src/apps/naja_edit/examples/scripts/print_design_tree.py @@ -0,0 +1,20 @@ +from naja import snl + +def print_design_tree(design): + for ins in design.getInstances(): + print(f"Instance: {ins.getName()}") + model = ins.getModel() + for term in design.getTerms(): + print(f" Terminal: {term}") + for net in design.getNets(): + print(f" Net: {net}") + for bit in net.getBits(): + for component in bit.getComponents(): + print(f" Component: {component}") + print_design_tree(model) + +def edit(): + universe = snl.SNLUniverse.get() + top = universe.getTopDesign() + + print_design_tree(top) \ No newline at end of file diff --git a/src/apps/naja_edit/examples/scripts/remove_iobufs.py b/src/apps/naja_edit/examples/scripts/remove_iobufs.py new file mode 100644 index 00000000..7a160e3f --- /dev/null +++ b/src/apps/naja_edit/examples/scripts/remove_iobufs.py @@ -0,0 +1,27 @@ +from naja import snl + +def remove_io_bufs(design): + for ins in design.getInstances(): + model = ins.getModel() + if model.isPrimitive(): + model_name = model.getName() + if model_name in ['IBUF', 'BUFG']: + input_net = ins.getInstTerm(model.getScalarTerm('I')).getNet() + output_net = ins.getInstTerm(model.getScalarTerm('O')).getNet() + for component in output_net.getComponents(): + component.setNet(input_net) + output_net.destroy() + ins.destroy() + elif model_name == 'OBUF': + input_net = ins.getInstTerm(model.getScalarTerm('I')).getNet() + output_net = ins.getInstTerm(model.getScalarTerm('O')).getNet() + for component in input_net.getComponents(): + component.setNet(output_net) + input_net.destroy() + ins.destroy() + +def edit(): + universe = snl.SNLUniverse.get() + top = universe.getTopDesign() + + remove_io_bufs(top) \ No newline at end of file diff --git a/regress/test_args/Makefile b/src/apps/naja_edit/examples/test_args/Makefile similarity index 100% rename from regress/test_args/Makefile rename to src/apps/naja_edit/examples/test_args/Makefile diff --git a/regress/test_args/module1.v b/src/apps/naja_edit/examples/test_args/module1.v similarity index 100% rename from regress/test_args/module1.v rename to src/apps/naja_edit/examples/test_args/module1.v diff --git a/regress/test_args/module2.v b/src/apps/naja_edit/examples/test_args/module2.v similarity index 100% rename from regress/test_args/module2.v rename to src/apps/naja_edit/examples/test_args/module2.v diff --git a/regress/test_args/top.v b/src/apps/naja_edit/examples/test_args/top.v similarity index 100% rename from regress/test_args/top.v rename to src/apps/naja_edit/examples/test_args/top.v diff --git a/regress/vexriscv/Makefile b/src/apps/naja_edit/examples/vexriscv/Makefile similarity index 100% rename from regress/vexriscv/Makefile rename to src/apps/naja_edit/examples/vexriscv/Makefile diff --git a/regress/vexriscv/src/comp.ys b/src/apps/naja_edit/examples/vexriscv/src/comp.ys similarity index 100% rename from regress/vexriscv/src/comp.ys rename to src/apps/naja_edit/examples/vexriscv/src/comp.ys diff --git a/regress/vexriscv/src/synth.ys b/src/apps/naja_edit/examples/vexriscv/src/synth.ys similarity index 100% rename from regress/vexriscv/src/synth.ys rename to src/apps/naja_edit/examples/vexriscv/src/synth.ys diff --git a/regress/vexriscv/src/vexriscv.demo.GenFull.v b/src/apps/naja_edit/examples/vexriscv/src/vexriscv.demo.GenFull.v similarity index 100% rename from regress/vexriscv/src/vexriscv.demo.GenFull.v rename to src/apps/naja_edit/examples/vexriscv/src/vexriscv.demo.GenFull.v