SimplHDL 0.4.0__tar.gz → 0.5.1__tar.gz
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.
- {simplhdl-0.4.0 → simplhdl-0.5.1}/PKG-INFO +2 -1
- {simplhdl-0.4.0 → simplhdl-0.5.1}/pyproject.toml +1 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/SimplHDL.egg-info/PKG-INFO +2 -1
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/SimplHDL.egg-info/SOURCES.txt +2 -0
- simplhdl-0.5.1/src/simplhdl/__init__.py +1 -0
- simplhdl-0.5.1/src/simplhdl/flows/quartusexport/quartusexportflow.py +157 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/quartusflow.py +7 -6
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/questasim/questasimflow.py +12 -0
- simplhdl-0.5.1/src/simplhdl/generators/spd.py +367 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/plugins.py +1 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/pyedaa/__init__.py +11 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/pyedaa/design.py +15 -1
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/quartus/project.tcl.j2 +16 -2
- simplhdl-0.5.1/src/simplhdl/resources/templates/xsim/__init__.py +0 -0
- simplhdl-0.4.0/src/simplhdl/__init__.py +0 -1
- simplhdl-0.4.0/src/simplhdl/generators/spd.py +0 -211
- {simplhdl-0.4.0 → simplhdl-0.5.1}/.github/workflows/publish.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/.gitignore +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/.readthedocs.yaml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/LICENSE +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/README.md +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/_static/simplhdl_dark.png +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/_static/simplhdl_light.png +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/_static/simplhdl_light_1.png +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/conf.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/drawing.svg +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/flows/ghdl.rst +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/flows/icarus.rst +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/flows/quartus.rst +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/flows/questasim.rst +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/flows/vcs.rst +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/flows/vivado.rst +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/flows/xsim.rst +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/flows.rst +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/index.rst +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/intel-ips.md +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/introduction.rst +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/plugins.rst +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/docs/requirements.txt +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/adder/adder.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/adder/hdl/adder.sv +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/adder/sim/testbench.sv +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/adder/sim/testbench.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/adder/syn/build.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/adder/syn/placement.xdc +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/adder/syn/timing.xdc +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/adder/syn/top.sv +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/alu.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/hdl/add.sv +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/hdl/alu.sv +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/hdl/mul.sv +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/hdl/sub.sv +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/alu_vip/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/alu_vip/agent.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/alu_vip/aluif.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/alu_vip/driver.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/alu_vip/monitor.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/alu_vip/sequenceitem.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/alu_vip/sequencer.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/clock_vip/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/clock_vip/agent.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/clock_vip/clockif.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/pyuvm.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/test/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/test/env.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/test/seq_lib.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/test/test.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/pyuvm/testbench.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/alu_vip/agent.svh +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/alu_vip/alu_vip.sv +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/alu_vip/alu_vip.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/alu_vip/driver.svh +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/alu_vip/env.svh +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/alu_vip/monitor.svh +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/alu_vip/sequence_item.svh +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/tb_env/seq_lib/add_seq.svh +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/tb_env/seq_lib/base_seq.svh +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/tb_env/tb_env.sv +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/tb_env/tb_env.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/tb_env/test/base_test.svh +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/tb_env/test/test_add.svh +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/testbench/alu_if.sv +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/testbench/testbench.sv +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/testbench/testbench.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/sim/uvm/testcases/test_add/test_add.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/syn/build.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/syn/placement.xdc +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/alu/syn/timing.xdc +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/hello/build.sbt +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/hello/hello.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/hello/src/main/scala/Hello.scala +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/hdl/hello/syn/build.yml +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/plugins/simple_parser/setup.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/plugins/simple_parser/src/simple_parser/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/examples/plugins/simple_parser/src/simple_parser/simple_parser.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/setup.cfg +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/SimplHDL.egg-info/dependency_links.txt +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/SimplHDL.egg-info/entry_points.txt +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/SimplHDL.egg-info/requires.txt +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/SimplHDL.egg-info/top_level.txt +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/__main__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/cocotb.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flow.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/encrypt/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/encrypt/encryptflow.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/flake8/flake8flow.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/implementationflow.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/lint/lintflow.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/modelsim/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/modelsim/modelsimflow.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/quartusdse/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/quartusdse/quartusdseflow.py +0 -0
- {simplhdl-0.4.0/src/simplhdl/flows/questasim → simplhdl-0.5.1/src/simplhdl/flows/quartusexport}/__init__.py +0 -0
- {simplhdl-0.4.0/src/simplhdl/flows/rivierapro → simplhdl-0.5.1/src/simplhdl/flows/questasim}/__init__.py +0 -0
- {simplhdl-0.4.0/src/simplhdl/flows/vcs → simplhdl-0.5.1/src/simplhdl/flows/rivierapro}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/rivierapro/rivieraproflow.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/simulationflow.py +0 -0
- {simplhdl-0.4.0/src/simplhdl/flows/verible → simplhdl-0.5.1/src/simplhdl/flows/vcs}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/vcs/vcsflow.py +0 -0
- {simplhdl-0.4.0/src/simplhdl/flows/vsg → simplhdl-0.5.1/src/simplhdl/flows/verible}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/verible/veribleflow.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/vivadoflow.py +0 -0
- {simplhdl-0.4.0/src/simplhdl/flows/xsim → simplhdl-0.5.1/src/simplhdl/flows/vsg}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/vsg/vsgflow.py +0 -0
- {simplhdl-0.4.0/src/simplhdl/generators → simplhdl-0.5.1/src/simplhdl/flows/xsim}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/flows/xsim/xsimflow.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/generator.py +0 -0
- {simplhdl-0.4.0/src/simplhdl/parsers → simplhdl-0.5.1/src/simplhdl/generators}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/generators/chisel.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/generators/ipxact.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/generators/systemrdl.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/info.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/parser.py +0 -0
- {simplhdl-0.4.0/src/simplhdl/resources → simplhdl-0.5.1/src/simplhdl/parsers}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/parsers/fusesocparser.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/parsers/simplhdlparser.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/pyedaa/attributes.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/pyedaa/fileset.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/pyedaa/filetypes.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/pyedaa/project.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/pyedaa/target.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/pyedaa/vhdllibrary.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/repo.py +0 -0
- {simplhdl-0.4.0/src/simplhdl/resources/templates → simplhdl-0.5.1/src/simplhdl/resources}/__init__.py +0 -0
- {simplhdl-0.4.0/src/simplhdl/resources/templates/flake8 → simplhdl-0.5.1/src/simplhdl/resources/templates}/__init__.py +0 -0
- {simplhdl-0.4.0/src/simplhdl/resources/templates/modelsim → simplhdl-0.5.1/src/simplhdl/resources/templates/flake8}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/flake8/setup.cfg.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/modelsim/Makefile.j2 +0 -0
- {simplhdl-0.4.0/src/simplhdl/resources/templates/quartus → simplhdl-0.5.1/src/simplhdl/resources/templates/modelsim}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/modelsim/cocotb.mk.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/modelsim/dependencies.mk.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/modelsim/files.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/modelsim/fileset.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/modelsim/modelsim.tcl.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/modelsim/project.mk.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/modelsim/run.do.j2 +0 -0
- {simplhdl-0.4.0/src/simplhdl/resources/templates/questasim → simplhdl-0.5.1/src/simplhdl/resources/templates/quartus}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/quartus/run.tcl.j2 +0 -0
- {simplhdl-0.4.0/src/simplhdl/resources/templates/rivierapro → simplhdl-0.5.1/src/simplhdl/resources/templates/questasim}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/questasim/modelsim.tcl.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/questasim/project.qrun.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/questasim/visualizer.tcl.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/questasim/vsim-run.do.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/rivierapro/Makefile.j2 +0 -0
- {simplhdl-0.4.0/src/simplhdl/resources/templates/vcs → simplhdl-0.5.1/src/simplhdl/resources/templates/rivierapro}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/rivierapro/cocotb.mk.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/rivierapro/dependencies.mk.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/rivierapro/files.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/rivierapro/fileset.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/rivierapro/project.mk.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vcs/Makefile.j2 +0 -0
- {simplhdl-0.4.0/src/simplhdl/resources/templates/verible → simplhdl-0.5.1/src/simplhdl/resources/templates/vcs}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vcs/cocotb.mk.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vcs/dependencies.mk.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vcs/files.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vcs/fileset.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vcs/pli.tab.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vcs/project.mk.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vcs/synopsys_sim.setup.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vcs/vcs.parameters.j2 +0 -0
- {simplhdl-0.4.0/src/simplhdl/resources/templates/vivado → simplhdl-0.5.1/src/simplhdl/resources/templates/verible}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/verible/rules.cfg.j2 +0 -0
- {simplhdl-0.4.0/src/simplhdl/resources/templates/vsg → simplhdl-0.5.1/src/simplhdl/resources/templates/vivado}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vivado/launch_run.sh.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vivado/project.tcl.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vivado/run.tcl.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vivado/steps.tcl.j2 +0 -0
- {simplhdl-0.4.0/src/simplhdl/resources/templates/xsim → simplhdl-0.5.1/src/simplhdl/resources/templates/vsg}/__init__.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vsg/files.json.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/vsg/rules.yml.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/xsim/Makefile.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/xsim/cocotb.mk.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/xsim/dependencies.mk.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/xsim/files.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/xsim/fileset.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/resources/templates/xsim/project.mk.j2 +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/run.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/simplhdl.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/tools.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/src/simplhdl/utils.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/tests/test_dummy.py +0 -0
- {simplhdl-0.4.0 → simplhdl-0.5.1}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: SimplHDL
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: A framework for simulating and implementing HDL designs
|
|
5
5
|
Author-email: Rasmus Grøndahl Olsen <simplhdl@gmail.com>
|
|
6
6
|
Maintainer-email: Rasmus Grøndahl Olsen <simplhdl@gmail.com>
|
|
@@ -37,6 +37,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
37
37
|
Classifier: Programming Language :: Python :: 3.10
|
|
38
38
|
Classifier: Programming Language :: Python :: 3.11
|
|
39
39
|
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
40
41
|
Classifier: Intended Audience :: Developers
|
|
41
42
|
Classifier: License :: OSI Approved :: MIT License
|
|
42
43
|
Classifier: Operating System :: OS Independent
|
|
@@ -43,6 +43,7 @@ classifiers = [
|
|
|
43
43
|
"Programming Language :: Python :: 3.10",
|
|
44
44
|
"Programming Language :: Python :: 3.11",
|
|
45
45
|
"Programming Language :: Python :: 3.12",
|
|
46
|
+
"Programming Language :: Python :: 3.13",
|
|
46
47
|
"Intended Audience :: Developers",
|
|
47
48
|
"License :: OSI Approved :: MIT License",
|
|
48
49
|
"Operating System :: OS Independent",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: SimplHDL
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: A framework for simulating and implementing HDL designs
|
|
5
5
|
Author-email: Rasmus Grøndahl Olsen <simplhdl@gmail.com>
|
|
6
6
|
Maintainer-email: Rasmus Grøndahl Olsen <simplhdl@gmail.com>
|
|
@@ -37,6 +37,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
37
37
|
Classifier: Programming Language :: Python :: 3.10
|
|
38
38
|
Classifier: Programming Language :: Python :: 3.11
|
|
39
39
|
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
40
41
|
Classifier: Intended Audience :: Developers
|
|
41
42
|
Classifier: License :: OSI Approved :: MIT License
|
|
42
43
|
Classifier: Operating System :: OS Independent
|
|
@@ -111,6 +111,8 @@ src/simplhdl/flows/modelsim/__init__.py
|
|
|
111
111
|
src/simplhdl/flows/modelsim/modelsimflow.py
|
|
112
112
|
src/simplhdl/flows/quartusdse/__init__.py
|
|
113
113
|
src/simplhdl/flows/quartusdse/quartusdseflow.py
|
|
114
|
+
src/simplhdl/flows/quartusexport/__init__.py
|
|
115
|
+
src/simplhdl/flows/quartusexport/quartusexportflow.py
|
|
114
116
|
src/simplhdl/flows/questasim/__init__.py
|
|
115
117
|
src/simplhdl/flows/questasim/questasimflow.py
|
|
116
118
|
src/simplhdl/flows/rivierapro/__init__.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.5.1"
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
import logging
|
|
3
|
+
import zipfile
|
|
4
|
+
|
|
5
|
+
from argparse import Namespace
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from simplhdl.flow import FlowFactory, FlowTools
|
|
9
|
+
from simplhdl.flows.implementationflow import ImplementationFlow
|
|
10
|
+
from simplhdl.flows.quartusflow import QuartusFlow
|
|
11
|
+
from simplhdl.resources.templates import quartus as templates
|
|
12
|
+
from simplhdl.flows.encrypt.encryptflow import encrypt
|
|
13
|
+
from simplhdl.pyedaa.project import Project
|
|
14
|
+
from simplhdl.pyedaa.attributes import UsedIn
|
|
15
|
+
from simplhdl.pyedaa import (
|
|
16
|
+
File,
|
|
17
|
+
HDLSearchPath,
|
|
18
|
+
HDLIncludeFile,
|
|
19
|
+
HDLSourceFile,
|
|
20
|
+
VerilogIncludeFile,
|
|
21
|
+
VerilogSourceFile,
|
|
22
|
+
SystemVerilogSourceFile,
|
|
23
|
+
VHDLSourceFile,
|
|
24
|
+
ConstraintFile,
|
|
25
|
+
QuartusQIPSpecificationFile,
|
|
26
|
+
QuartusIPSpecificationFile,
|
|
27
|
+
SettingFile
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
logger = logging.getLogger(__name__)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@FlowFactory.register('quartus-export')
|
|
34
|
+
class QuartusExportFlow(ImplementationFlow):
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def parse_args(self, subparsers) -> None:
|
|
38
|
+
parser = subparsers.add_parser('quartus-export', help='Export Quartus project')
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
'--encrypt',
|
|
41
|
+
action='store_true',
|
|
42
|
+
help="Encrypt HDL source files"
|
|
43
|
+
)
|
|
44
|
+
parser.add_argument(
|
|
45
|
+
'-o',
|
|
46
|
+
'--output',
|
|
47
|
+
action='store',
|
|
48
|
+
metavar='FILE',
|
|
49
|
+
dest='archivefile',
|
|
50
|
+
type=Path,
|
|
51
|
+
help="Output zip file"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
def __init__(self, name, args: Namespace, project: Project, builddir: Path):
|
|
55
|
+
super().__init__(name, args, project, builddir)
|
|
56
|
+
self.vendors = ['mentor', 'synopsys']
|
|
57
|
+
self.templates = templates
|
|
58
|
+
self.tools.add(FlowTools.QUARTUS)
|
|
59
|
+
|
|
60
|
+
def copy_files(self):
|
|
61
|
+
seen = dict()
|
|
62
|
+
files = [f for f in self.project.DefaultDesign.Files() if 'implementation' in f[UsedIn]]
|
|
63
|
+
for file in files:
|
|
64
|
+
fileid = str(file.Path.resolve())
|
|
65
|
+
if fileid in seen:
|
|
66
|
+
file._path = seen.get(fileid)._path
|
|
67
|
+
continue
|
|
68
|
+
elif isinstance(file, SettingFile):
|
|
69
|
+
continue
|
|
70
|
+
elif isinstance(file, (ConstraintFile, QuartusQIPSpecificationFile)):
|
|
71
|
+
dest = self.builddir.joinpath('constraints', file.Path.name)
|
|
72
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
73
|
+
shutil.copyfile(file.Path, dest)
|
|
74
|
+
elif isinstance(file, (HDLSearchPath, QuartusIPSpecificationFile)):
|
|
75
|
+
dest = file.Path
|
|
76
|
+
elif isinstance(file, (HDLSourceFile, HDLIncludeFile)):
|
|
77
|
+
if isinstance(file, HDLSourceFile):
|
|
78
|
+
dest = self.builddir.joinpath('rtl', file.Path.name)
|
|
79
|
+
else:
|
|
80
|
+
dest = self.builddir.joinpath('rtl', 'include', file.Path.name)
|
|
81
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
82
|
+
if self.args.encrypt:
|
|
83
|
+
encrypt(file.Path, dest, language=get_language(file), vendors=self.vendors)
|
|
84
|
+
else:
|
|
85
|
+
shutil.copyfile(file.Path, dest)
|
|
86
|
+
else:
|
|
87
|
+
dest = self.builddir.joinpath('misc', file.Path.name)
|
|
88
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
89
|
+
shutil.copyfile(file.Path, dest)
|
|
90
|
+
file._path = dest.absolute().relative_to(self.builddir.absolute())
|
|
91
|
+
# Convert to relative path
|
|
92
|
+
file._path = dest.absolute().relative_to(self.builddir.absolute())
|
|
93
|
+
seen[fileid] = file
|
|
94
|
+
|
|
95
|
+
def create_project(self) -> None:
|
|
96
|
+
args = Namespace(step='project', archive=False, gui=False)
|
|
97
|
+
quartus = QuartusFlow('quartus', args, self.project, self.builddir)
|
|
98
|
+
quartus.run()
|
|
99
|
+
|
|
100
|
+
def archive_project(self) -> None:
|
|
101
|
+
if self.args.archivefile:
|
|
102
|
+
archive(self.builddir, self.args.archivefile)
|
|
103
|
+
else:
|
|
104
|
+
output = self.builddir.parrent.joinpath(self.project.Name).with_suffix('.zip')
|
|
105
|
+
archive(self.builddir, output)
|
|
106
|
+
shutil.move(output, self.builddir)
|
|
107
|
+
|
|
108
|
+
def run(self) -> None:
|
|
109
|
+
self.copy_files()
|
|
110
|
+
self.create_project()
|
|
111
|
+
self.archive_project()
|
|
112
|
+
|
|
113
|
+
def is_tool_setup(self) -> None:
|
|
114
|
+
exit: bool = False
|
|
115
|
+
if shutil.which('quartus_sh') is None:
|
|
116
|
+
logger.error('quartus_sh: not found in PATH')
|
|
117
|
+
exit = True
|
|
118
|
+
if shutil.which('quartus') is None:
|
|
119
|
+
logger.error('quartus: not found in PATH')
|
|
120
|
+
exit = True
|
|
121
|
+
if exit:
|
|
122
|
+
raise FileNotFoundError("Quartus is not setup correctly")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def get_language(file: File) -> str:
|
|
126
|
+
fileMap = {
|
|
127
|
+
SystemVerilogSourceFile: 'systemverilog',
|
|
128
|
+
VerilogSourceFile: 'verilog',
|
|
129
|
+
VerilogIncludeFile: 'systemverilog',
|
|
130
|
+
VHDLSourceFile: 'vhdl'
|
|
131
|
+
}
|
|
132
|
+
return fileMap[file.FileType]
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def archive(directory: Path, destination: Path) -> Path:
|
|
136
|
+
"""
|
|
137
|
+
Recursively zip all contents of the given folder into a zip file.
|
|
138
|
+
The zip archive will contain a top-level folder with the same name
|
|
139
|
+
as the zip file (excluding the extension).
|
|
140
|
+
|
|
141
|
+
Parameters:
|
|
142
|
+
directory (Path): The folder whose contents will be zipped.
|
|
143
|
+
destination (Path): The path to the resulting zip file.
|
|
144
|
+
Its stem will be used as the top-level folder name.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Path: The path to the created zip archive.
|
|
148
|
+
"""
|
|
149
|
+
top_folder = destination.stem # top folder inside the archive
|
|
150
|
+
with zipfile.ZipFile(destination, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
|
151
|
+
# Walk through all files in the directory
|
|
152
|
+
for file in directory.rglob('*'):
|
|
153
|
+
if file.is_file():
|
|
154
|
+
# Place each file under the top_folder
|
|
155
|
+
arcname = Path(top_folder) / file.relative_to(directory)
|
|
156
|
+
zipf.write(file, arcname=arcname)
|
|
157
|
+
return destination
|
|
@@ -18,7 +18,7 @@ from ..pyedaa import (QuartusIPSpecificationFile, VerilogIncludeFile, VerilogSou
|
|
|
18
18
|
SystemVerilogSourceFile, VHDLSourceFile, ConstraintFile,
|
|
19
19
|
EDIFNetlistFile, NetlistFile, SettingFile, QuartusSignalTapFile,
|
|
20
20
|
QuartusIniFile, QuartusQIPSpecificationFile, QuartusQSYSSpecificationFile,
|
|
21
|
-
HDLSearchPath, VerilogIncludeSearchPath)
|
|
21
|
+
HDLSearchPath, VerilogIncludeSearchPath, MemoryInitFile)
|
|
22
22
|
from ..pyedaa.project import Project
|
|
23
23
|
from ..pyedaa.attributes import UsedIn
|
|
24
24
|
|
|
@@ -62,10 +62,11 @@ class QuartusFlow(ImplementationFlow):
|
|
|
62
62
|
def run(self) -> None:
|
|
63
63
|
if self.args.archive:
|
|
64
64
|
self.archive()
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
else:
|
|
66
|
+
self.validate()
|
|
67
|
+
self.configure()
|
|
68
|
+
self.generate()
|
|
69
|
+
self.execute(self.args.step)
|
|
69
70
|
|
|
70
71
|
def archive(self) -> None:
|
|
71
72
|
name = self.project.Name
|
|
@@ -79,7 +80,6 @@ class QuartusFlow(ImplementationFlow):
|
|
|
79
80
|
raise Exception("Unknown value for argument --archive: {self.args.archive}")
|
|
80
81
|
command = f"quartus_sh --archive -use_file_set {fileset} -revision {name} -no_discover -output {name}.qar {name}" # noqa
|
|
81
82
|
sh(command.split(), output=True, cwd=self.builddir)
|
|
82
|
-
raise SystemExit
|
|
83
83
|
|
|
84
84
|
def validate(self):
|
|
85
85
|
if self.project.DefaultDesign.DefaultFileSet.TopLevel is None:
|
|
@@ -113,6 +113,7 @@ class QuartusFlow(ImplementationFlow):
|
|
|
113
113
|
QuartusQIPSpecificationFile=QuartusQIPSpecificationFile,
|
|
114
114
|
QuartusQSYSSpecificationFile=QuartusQSYSSpecificationFile,
|
|
115
115
|
QuartusIniFile=QuartusIniFile,
|
|
116
|
+
MemoryInitFile=MemoryInitFile,
|
|
116
117
|
project=self.project,
|
|
117
118
|
UsedIn=UsedIn)
|
|
118
119
|
template = environment.get_template('run.tcl.j2')
|
|
@@ -16,6 +16,7 @@ from jinja2 import Template
|
|
|
16
16
|
from simplhdl.pyedaa.project import Project
|
|
17
17
|
from simplhdl.utils import sh, escape
|
|
18
18
|
from simplhdl.flow import FlowFactory, FlowTools
|
|
19
|
+
from simplhdl.info import Info
|
|
19
20
|
from simplhdl.resources.templates import questasim as questasimtemplates
|
|
20
21
|
from simplhdl.flows.simulationflow import SimulationFlow, FileSetWalker
|
|
21
22
|
from simplhdl.utils import generate_from_template
|
|
@@ -45,6 +46,11 @@ class QuestaSimFlow(SimulationFlow):
|
|
|
45
46
|
default='',
|
|
46
47
|
help="flow step to run"
|
|
47
48
|
)
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
'--info',
|
|
51
|
+
action='store_true',
|
|
52
|
+
help="Print project"
|
|
53
|
+
)
|
|
48
54
|
parser.add_argument(
|
|
49
55
|
'-w',
|
|
50
56
|
'--wavedump',
|
|
@@ -225,6 +231,12 @@ class QuestaSimFlow(SimulationFlow):
|
|
|
225
231
|
sh(['qrun', '-clean'], cwd=self.builddir, output=True)
|
|
226
232
|
return
|
|
227
233
|
|
|
234
|
+
if self.args.info:
|
|
235
|
+
args = Namespace(files=False, filesets=False, libraries=False, hooks=False)
|
|
236
|
+
info = Info(self.name, args, self.project, self.builddir)
|
|
237
|
+
info.run()
|
|
238
|
+
return
|
|
239
|
+
|
|
228
240
|
self.run_hooks('pre')
|
|
229
241
|
|
|
230
242
|
if step == 'generate':
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
from typing import List, Generator, Optional
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from xml.etree.ElementTree import Element, parse
|
|
7
|
+
from zipfile import ZipFile
|
|
8
|
+
from shutil import copy, copytree, rmtree
|
|
9
|
+
|
|
10
|
+
from simplhdl.pyedaa import (
|
|
11
|
+
File,
|
|
12
|
+
HDLSourceFile,
|
|
13
|
+
HDLSearchPath,
|
|
14
|
+
VerilogSourceFile,
|
|
15
|
+
SystemVerilogSourceFile,
|
|
16
|
+
VHDLSourceFile,
|
|
17
|
+
ConstraintFile,
|
|
18
|
+
HDLLibrary,
|
|
19
|
+
MemoryInitFile,
|
|
20
|
+
QuartusIPSpecificationFile,
|
|
21
|
+
QuartusIPCompressedSpecificationFile,
|
|
22
|
+
QuartusQSYSSpecificationFile,
|
|
23
|
+
QuartusQSYSCompressedSpecificationFile,
|
|
24
|
+
QuartusQIPSpecificationFile
|
|
25
|
+
)
|
|
26
|
+
from simplhdl.pyedaa.fileset import FileSet
|
|
27
|
+
from simplhdl.pyedaa.attributes import UsedIn
|
|
28
|
+
from simplhdl.flow import FlowBase, FlowCategory, FlowTools
|
|
29
|
+
from simplhdl.generator import GeneratorFactory, GeneratorBase, GeneratorError
|
|
30
|
+
from simplhdl.utils import md5write, md5check, sh
|
|
31
|
+
|
|
32
|
+
logger = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
FILETYPE_MAP = {
|
|
36
|
+
'SYSTEM_VERILOG': SystemVerilogSourceFile,
|
|
37
|
+
'SYSTEM_VERILOG_ENCRYPT': SystemVerilogSourceFile,
|
|
38
|
+
'VERILOG': VerilogSourceFile,
|
|
39
|
+
'VERILOG_ENCRYPT': VerilogSourceFile,
|
|
40
|
+
'VHDL': VHDLSourceFile,
|
|
41
|
+
'VHDL_ENCRYPT': VHDLSourceFile,
|
|
42
|
+
'SDC_ENTITY': ConstraintFile,
|
|
43
|
+
'HEX': MemoryInitFile
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
TOOL_MAP = {
|
|
47
|
+
FlowTools.VCS: 'vcs',
|
|
48
|
+
FlowTools.NCSIM: 'ncsim',
|
|
49
|
+
FlowTools.QUESTASIM: 'modelsim',
|
|
50
|
+
FlowTools.MODELSIM: 'modelsim',
|
|
51
|
+
FlowTools.VCS: 'vcs',
|
|
52
|
+
FlowTools.RIVIERAPRO: 'riviera'
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class Spd:
|
|
57
|
+
|
|
58
|
+
def __init__(self, filename: Path, flow: FlowBase, ip_path: Optional[Path] = None) -> None:
|
|
59
|
+
self._files = list()
|
|
60
|
+
self._filename = filename.absolute()
|
|
61
|
+
self.flow = flow
|
|
62
|
+
self.libraries = dict()
|
|
63
|
+
self.simulators = set()
|
|
64
|
+
spdfile = filename.parent.joinpath(filename.stem, filename.name).with_suffix('.spd')
|
|
65
|
+
if not spdfile.exists():
|
|
66
|
+
if ip_path:
|
|
67
|
+
command = f"qsys-generate --simulation=VERILOG --search-path={ip_path},$ {filename.absolute()}".split()
|
|
68
|
+
else:
|
|
69
|
+
command = f"qsys-generate --simulation=VERILOG {filename.absolute()}".split()
|
|
70
|
+
logger.info(f'Generate simulation files for {filename}')
|
|
71
|
+
sh(command, cwd=filename.parent)
|
|
72
|
+
if not spdfile.exists():
|
|
73
|
+
raise FileNotFoundError(f"{spdfile}: doesn't exits")
|
|
74
|
+
self.tree = parse(spdfile)
|
|
75
|
+
self.root = self.tree.getroot()
|
|
76
|
+
self.location = spdfile.parent.absolute()
|
|
77
|
+
for element in self.file_elements():
|
|
78
|
+
self._files.append(self.element_to_file(element))
|
|
79
|
+
if self.simulators and not self.supported(self.flow, self.simulators):
|
|
80
|
+
names = [n.name.capitalize() for n in self.flow.tools]
|
|
81
|
+
raise GeneratorError(f"Encrypted IP {filename} does not support {','.join(names)}")
|
|
82
|
+
|
|
83
|
+
def file_elements(self) -> Generator[Element, None, None]:
|
|
84
|
+
for f in self.root:
|
|
85
|
+
if f.tag == 'file':
|
|
86
|
+
properties = f.attrib
|
|
87
|
+
if 'simulator' in properties:
|
|
88
|
+
simulators = re.split(r'\s*,\s*', properties['simulator'])
|
|
89
|
+
if not self.supported(self.flow, simulators):
|
|
90
|
+
continue
|
|
91
|
+
yield f
|
|
92
|
+
|
|
93
|
+
def element_to_file(self, element: Element) -> File:
|
|
94
|
+
properties = element.attrib
|
|
95
|
+
if properties['path'].startswith('/'):
|
|
96
|
+
path = Path(properties['path'])
|
|
97
|
+
else:
|
|
98
|
+
path = Path(self.location, properties['path'])
|
|
99
|
+
libraryname = properties['library']
|
|
100
|
+
if libraryname not in self.libraries:
|
|
101
|
+
self.libraries[libraryname] = HDLLibrary(libraryname)
|
|
102
|
+
fileclass = FILETYPE_MAP.get(properties['type'], File)
|
|
103
|
+
if issubclass(fileclass, HDLSourceFile):
|
|
104
|
+
return fileclass(path=path, library=self.libraries[libraryname])
|
|
105
|
+
else:
|
|
106
|
+
return fileclass(path=path)
|
|
107
|
+
|
|
108
|
+
def supported(self, flow: FlowBase, simulators: List) -> bool:
|
|
109
|
+
self.simulators.update(simulators)
|
|
110
|
+
for tool in flow.tools:
|
|
111
|
+
if TOOL_MAP.get(tool, None) in simulators:
|
|
112
|
+
return True
|
|
113
|
+
return False
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def filesets(self):
|
|
117
|
+
filesets = list()
|
|
118
|
+
for library in self.libraries.values():
|
|
119
|
+
name = f"{self._filename}.{library.Name}"
|
|
120
|
+
fileset = FileSet(name, vhdlLibrary=library)
|
|
121
|
+
for file in self._files:
|
|
122
|
+
if isinstance(file, HDLSourceFile):
|
|
123
|
+
if file.Library == library:
|
|
124
|
+
fileset.AddFile(file)
|
|
125
|
+
else:
|
|
126
|
+
fileset.AddFile(file)
|
|
127
|
+
filesets.append(fileset)
|
|
128
|
+
return filesets
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@GeneratorFactory.register('QuartusIP')
|
|
132
|
+
class QuartusIP(GeneratorBase):
|
|
133
|
+
|
|
134
|
+
def unpack_ip(self, filename: QuartusIPSpecificationFile) -> QuartusIPSpecificationFile: # noqa: C901
|
|
135
|
+
ipdir = self.builddir.joinpath('ips')
|
|
136
|
+
dest = ipdir.joinpath(filename.Path.name).with_suffix('')
|
|
137
|
+
md5file = dest.with_suffix('.md5')
|
|
138
|
+
ipdir.mkdir(exist_ok=True)
|
|
139
|
+
if filename.FileType == QuartusQSYSSpecificationFile:
|
|
140
|
+
filename = self.copy_qsys(filename, dest, md5file)
|
|
141
|
+
ipfiles = self.parse_qsys(filename)
|
|
142
|
+
if self.flow.category == FlowCategory.SIMULATION:
|
|
143
|
+
for ipfile in ipfiles:
|
|
144
|
+
spd = Spd(ipfile.Path, self.flow, dest.absolute())
|
|
145
|
+
parent = filename.FileSet
|
|
146
|
+
for fileset in reversed(spd.filesets):
|
|
147
|
+
# Add fileset to parent, then set parent to fileset to make a chain
|
|
148
|
+
parent._fileSets[fileset.Name] = fileset
|
|
149
|
+
parent = fileset
|
|
150
|
+
else:
|
|
151
|
+
fileset = FileSet(filename.Path.name, vhdlLibrary=self.project.DefaultDesign.DefaultFileSet.VHDLLibrary)
|
|
152
|
+
fileset.AddFiles(ipfiles)
|
|
153
|
+
filename.FileSet.AddFileSet(fileset)
|
|
154
|
+
elif filename.FileType == QuartusIPCompressedSpecificationFile:
|
|
155
|
+
update = True
|
|
156
|
+
if md5file.exists():
|
|
157
|
+
update = not md5check(filename.Path, filename=md5file)
|
|
158
|
+
if update:
|
|
159
|
+
with ZipFile(filename.Path, 'r') as zip:
|
|
160
|
+
zip.extractall(ipdir)
|
|
161
|
+
md5write(filename.Path, filename=md5file)
|
|
162
|
+
logger.debug(f"Copy {filename.Path} to {dest}")
|
|
163
|
+
|
|
164
|
+
if filename.Path.suffix == '.zip':
|
|
165
|
+
filename._path = dest.absolute()
|
|
166
|
+
else:
|
|
167
|
+
filename._path = dest.with_suffix('.ip').absolute()
|
|
168
|
+
filename._fileType = QuartusIPSpecificationFile
|
|
169
|
+
|
|
170
|
+
elif filename.FileType == QuartusIPSpecificationFile:
|
|
171
|
+
update = True
|
|
172
|
+
dir = filename.Path.with_suffix('')
|
|
173
|
+
if dir.exists():
|
|
174
|
+
if md5file.exists():
|
|
175
|
+
update = not md5check(filename.Path, dir, filename=md5file)
|
|
176
|
+
if update:
|
|
177
|
+
copy(str(filename.Path), str(dest.with_suffix('.ip')))
|
|
178
|
+
md5write(filename.Path, filename=md5file)
|
|
179
|
+
if dir.exists():
|
|
180
|
+
copytree(str(dir), str(dest.with_suffix('')), dirs_exist_ok=True)
|
|
181
|
+
md5write(filename.Path, dir, filename=md5file)
|
|
182
|
+
logger.debug(f"Copy {filename.Path} to {dest}")
|
|
183
|
+
filename._path = dest.with_suffix('.ip').absolute()
|
|
184
|
+
return filename
|
|
185
|
+
|
|
186
|
+
def run(self, flow: FlowBase) -> None:
|
|
187
|
+
seen = dict()
|
|
188
|
+
self.flow = flow
|
|
189
|
+
ip_dir = self.builddir.joinpath('ips')
|
|
190
|
+
qsys_dir = self.builddir.joinpath('qsys')
|
|
191
|
+
files = list(self.project.DefaultDesign.DefaultFileSet.Files(fileType=QuartusIPSpecificationFile))
|
|
192
|
+
# files = filter_duplicated_files(files)
|
|
193
|
+
if not flow.category == FlowCategory.DEFAULT:
|
|
194
|
+
for file in files:
|
|
195
|
+
# The second time we see a file it is already proccessed and we just
|
|
196
|
+
# Update the file path
|
|
197
|
+
fileid = str(file.Path.resolve())
|
|
198
|
+
if fileid in seen:
|
|
199
|
+
file._path = seen.get(fileid)._path
|
|
200
|
+
continue
|
|
201
|
+
if file.FileType == QuartusQIPSpecificationFile:
|
|
202
|
+
continue
|
|
203
|
+
elif file.FileType == QuartusIPCompressedSpecificationFile:
|
|
204
|
+
file = unpack_ipfile(file, ip_dir)
|
|
205
|
+
elif file.FileType == QuartusIPSpecificationFile:
|
|
206
|
+
file = copy_ipfile(file, ip_dir)
|
|
207
|
+
elif file.FileType == QuartusQSYSCompressedSpecificationFile:
|
|
208
|
+
file = unpack_qsysfile(file, qsys_dir)
|
|
209
|
+
elif file.FileType == QuartusQSYSSpecificationFile:
|
|
210
|
+
file = copy_qsysfile(file, qsys_dir)
|
|
211
|
+
parse_file(file, flow, self.project.DefaultDesign.DefaultFileSet.VHDLLibrary)
|
|
212
|
+
# register the file as seen
|
|
213
|
+
seen[fileid] = file
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def parse_qsys(filename: QuartusQSYSSpecificationFile) -> List[File]:
|
|
217
|
+
"""
|
|
218
|
+
Search for IP files in a QSYS file and return a list of QuartusIPSpecificationFile objects.
|
|
219
|
+
"""
|
|
220
|
+
files = list()
|
|
221
|
+
with filename.Path.open() as file:
|
|
222
|
+
lines = file.readlines()
|
|
223
|
+
for line in lines:
|
|
224
|
+
m = re.search(r'<ipxact:value>(.*\.ip)</ipxact:value>', line)
|
|
225
|
+
if m:
|
|
226
|
+
ipfile = filename.Path.parent.joinpath(m.group(1))
|
|
227
|
+
if ipfile.exists():
|
|
228
|
+
files.append(QuartusIPSpecificationFile(ipfile))
|
|
229
|
+
else:
|
|
230
|
+
logger.warning(f"File {ipfile} not found")
|
|
231
|
+
return files
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def qsys_to_fileset(file: QuartusQSYSSpecificationFile, flow: FlowBase, library) -> FileSet:
|
|
235
|
+
"""
|
|
236
|
+
Parse a QSYS file and return a FileSet object.
|
|
237
|
+
"""
|
|
238
|
+
ipfiles = parse_qsys(file)
|
|
239
|
+
if flow.category == FlowCategory.SIMULATION:
|
|
240
|
+
parent = file.FileSet
|
|
241
|
+
for ipfile in ipfiles + [file]:
|
|
242
|
+
spd = Spd(ipfile.Path, flow, file.Path.parent.absolute())
|
|
243
|
+
for fileset in reversed(spd.filesets):
|
|
244
|
+
# Add fileset to parent, then set parent to fileset to make a chain
|
|
245
|
+
parent._fileSets[fileset.Name] = fileset
|
|
246
|
+
parent = fileset
|
|
247
|
+
elif flow.category == FlowCategory.IMPLEMENTATION:
|
|
248
|
+
# NOTE: Some qsys require a search path to find the HEX files
|
|
249
|
+
searchpath = HDLSearchPath(file.Path.parent)
|
|
250
|
+
searchpath[UsedIn] = {'implementation'}
|
|
251
|
+
fileset = FileSet(file.Path.name, vhdlLibrary=library)
|
|
252
|
+
fileset.AddFiles(ipfiles + [searchpath])
|
|
253
|
+
file.FileSet.AddFileSet(fileset)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def parse_file(file: File, flow: FlowBase, library) -> FileSet:
|
|
257
|
+
if file.FileType == QuartusQSYSSpecificationFile:
|
|
258
|
+
return qsys_to_fileset(file, flow, library)
|
|
259
|
+
elif file.FileType == QuartusIPSpecificationFile:
|
|
260
|
+
if flow.category == FlowCategory.SIMULATION:
|
|
261
|
+
spd = Spd(file.Path, flow)
|
|
262
|
+
parent = file.FileSet
|
|
263
|
+
for fileset in reversed(spd.filesets):
|
|
264
|
+
# Add fileset to parent, then set parent to fileset to make a chain
|
|
265
|
+
parent._fileSets[fileset.Name] = fileset
|
|
266
|
+
parent = fileset
|
|
267
|
+
else:
|
|
268
|
+
return file
|
|
269
|
+
else:
|
|
270
|
+
raise GeneratorError(f"Unsupported file type: {file.FileType}")
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def copy_ipfile(file: QuartusIPSpecificationFile, dest: Path) -> QuartusIPSpecificationFile:
|
|
274
|
+
"""
|
|
275
|
+
Copy IP files to a directory and return a new QuartusIPSpecificationFile object with the new path.
|
|
276
|
+
"""
|
|
277
|
+
dest.mkdir(parents=True, exist_ok=True)
|
|
278
|
+
md5file = dest.joinpath(file.Path.name).with_suffix('.md5')
|
|
279
|
+
srcdir = file.Path.with_suffix('')
|
|
280
|
+
destdir = dest.joinpath(file.Path.name).with_suffix('')
|
|
281
|
+
destfile = dest.joinpath(file.Path.name)
|
|
282
|
+
if srcdir.exists():
|
|
283
|
+
if not md5file.exists() or not md5check(file.Path, srcdir, filename=md5file):
|
|
284
|
+
logger.info(f"Copy {file.Path} to {destfile}")
|
|
285
|
+
logger.info(f"Copy {srcdir} to {destdir}")
|
|
286
|
+
copy(str(file.Path), str(destfile))
|
|
287
|
+
copytree(str(srcdir), str(destdir), dirs_exist_ok=True)
|
|
288
|
+
md5write(file.Path, srcdir, filename=md5file)
|
|
289
|
+
else:
|
|
290
|
+
if not md5file.exists() or not md5check(file.Path, filename=md5file):
|
|
291
|
+
logger.info(f"Copy {file.Path} to {destfile}")
|
|
292
|
+
rmtree(destdir, ignore_errors=True)
|
|
293
|
+
copy(str(file.Path), str(destfile))
|
|
294
|
+
md5write(file.Path, filename=md5file)
|
|
295
|
+
file._fileType = QuartusIPSpecificationFile
|
|
296
|
+
file._path = destfile.resolve()
|
|
297
|
+
return file
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def copy_qsysfile(file: QuartusQSYSSpecificationFile, dest: Path) -> QuartusQSYSSpecificationFile:
|
|
301
|
+
"""
|
|
302
|
+
Copy QSYS files to a directory and return a new QuartusQSYSSpecificationFile object with the new path.
|
|
303
|
+
"""
|
|
304
|
+
md5file = dest.joinpath(file.Path.name).with_suffix('.md5')
|
|
305
|
+
qsysdir = dest.joinpath(file.Path.name)
|
|
306
|
+
src = file.Path.parent
|
|
307
|
+
if not md5file.exists() or not md5check(src, filename=md5file):
|
|
308
|
+
copytree(str(src), str(qsysdir), dirs_exist_ok=True)
|
|
309
|
+
md5write(src, filename=md5file)
|
|
310
|
+
file._fileType = QuartusQSYSSpecificationFile
|
|
311
|
+
file._path = qsysdir.joinpath(file.Path.name).with_suffix('.qsys').resolve()
|
|
312
|
+
if file.Path.exists():
|
|
313
|
+
return file
|
|
314
|
+
else:
|
|
315
|
+
raise FileNotFoundError(f"{file.Path}: doesn't exits")
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def unpack_ipfile(file: QuartusIPCompressedSpecificationFile, dest: Path) -> QuartusIPSpecificationFile:
|
|
319
|
+
"""
|
|
320
|
+
Unpack IP files to a directory and return a new QuartusIPSpecificationFile object with the new path.
|
|
321
|
+
"""
|
|
322
|
+
unpack(file.Path, dest)
|
|
323
|
+
file._fileType = QuartusIPSpecificationFile
|
|
324
|
+
file._path = dest.joinpath(file.Path.name).with_suffix('').resolve()
|
|
325
|
+
if file.Path.exists():
|
|
326
|
+
return file
|
|
327
|
+
else:
|
|
328
|
+
raise FileNotFoundError(f"{file.Path.resolve()}: doesn't exits")
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def unpack_qsysfile(file: QuartusQSYSCompressedSpecificationFile, dest: Path) -> QuartusQSYSSpecificationFile:
|
|
332
|
+
"""
|
|
333
|
+
Unpack QSYS files to a directory and return a new QuartusQSYSSpecificationFile object with the new path.
|
|
334
|
+
"""
|
|
335
|
+
dest = dest.joinpath(file.Path.name).with_suffix('').with_suffix('')
|
|
336
|
+
unpack(file.Path, dest)
|
|
337
|
+
file._fileType = QuartusQSYSSpecificationFile
|
|
338
|
+
file._path = dest.joinpath(file.Path.name).with_suffix('').resolve()
|
|
339
|
+
if file.Path.exists():
|
|
340
|
+
return file
|
|
341
|
+
else:
|
|
342
|
+
raise FileNotFoundError(f"{file.Path}: doesn't exits")
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def unpack(file: Path, dest: Path) -> None:
|
|
346
|
+
"""
|
|
347
|
+
Unpack a file to a directory and return the new path.
|
|
348
|
+
"""
|
|
349
|
+
md5file = dest.joinpath(file.name).with_suffix('.md5')
|
|
350
|
+
if not md5file.exists() or not md5check(file, filename=md5file):
|
|
351
|
+
logger.info(f"Unpack {file} to {dest}")
|
|
352
|
+
with ZipFile(file, 'r') as zip:
|
|
353
|
+
zip.extractall(dest)
|
|
354
|
+
md5write(file, filename=md5file)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def filter_duplicated_files(files: List[File]) -> List[File]:
|
|
358
|
+
"""
|
|
359
|
+
Filter duplicated files in a list of files.
|
|
360
|
+
"""
|
|
361
|
+
unique_files = set(files)
|
|
362
|
+
filtered_files = dict()
|
|
363
|
+
for file in unique_files:
|
|
364
|
+
# if file.Path.name in filtered_files:
|
|
365
|
+
# logger.warning(f"Duplicate files - {file.Path} will override {filtered_files[file.Path.name].Path}")
|
|
366
|
+
filtered_files[file.Path.name] = file
|
|
367
|
+
return list(filtered_files.values())
|
|
@@ -30,6 +30,7 @@ def load_builtin_plugins() -> None:
|
|
|
30
30
|
import_module('simplhdl.flows.xsim.xsimflow')
|
|
31
31
|
import_module('simplhdl.flows.rivierapro.rivieraproflow')
|
|
32
32
|
import_module('simplhdl.flows.quartusdse.quartusdseflow')
|
|
33
|
+
import_module('simplhdl.flows.quartusexport.quartusexportflow')
|
|
33
34
|
import_module('simplhdl.flows.encrypt.encryptflow')
|
|
34
35
|
import_module('simplhdl.flows.vsg.vsgflow')
|
|
35
36
|
import_module('simplhdl.flows.verible.veribleflow')
|
|
@@ -154,6 +154,10 @@ class QuartusQSYSSpecificationFile(QuartusIPSpecificationFile):
|
|
|
154
154
|
pass
|
|
155
155
|
|
|
156
156
|
|
|
157
|
+
class QuartusQSYSCompressedSpecificationFile(QuartusQSYSSpecificationFile):
|
|
158
|
+
pass
|
|
159
|
+
|
|
160
|
+
|
|
157
161
|
class QuartusQIPSpecificationFile(QuartusIPSpecificationFile):
|
|
158
162
|
pass
|
|
159
163
|
|
|
@@ -165,6 +169,13 @@ class QuartusIniFile(File):
|
|
|
165
169
|
self[UsedIn] = {IMPLEMENTATION}
|
|
166
170
|
|
|
167
171
|
|
|
172
|
+
class QuartusSourceTCLFile(TCLSourceFile):
|
|
173
|
+
def _registerAttributes(self):
|
|
174
|
+
super()._registerAttributes()
|
|
175
|
+
FileMixIn._registerAttributes(self)
|
|
176
|
+
self[UsedIn] = {IMPLEMENTATION}
|
|
177
|
+
|
|
178
|
+
|
|
168
179
|
class VivadoIPSpecificationFile(IPSpecificationFile):
|
|
169
180
|
pass
|
|
170
181
|
|