├── MANIFEST.in
├── docs
├── bugs.rst
├── about.rst
├── tutorial
│ └── index.rst
├── flows.rst
├── copyright.rst
├── requirements.txt
├── index.rst
├── contents.rst
├── Makefile
├── quickstart.rst
└── conf.py
├── tests
├── resources
│ ├── test.v
│ ├── cocotb
│ │ └── results.xml
│ ├── design0
│ │ └── design0.toml
│ ├── Fitter_Resource_Utilization_by_Entity.csv
│ └── Flow_Summary.csv
├── fake_tools
│ ├── vivado
│ ├── xtclsh
│ ├── quartus_sh
│ └── resource
│ │ └── fake_vivado_reports
├── __init__.py
├── test_gtkw.py
├── test_cli.py
├── test_verilator.py
├── test_nvc.py
├── test_cocotb.py
├── test_ghdl.py
├── test_ise.py
├── test_yosys.py
└── test_vivado.py
├── src
└── xeda
│ ├── data
│ ├── __init__.py
│ ├── boards
│ │ ├── __init__.py
│ │ └── ulx3s
│ │ │ └── __init__.py
│ └── boards.toml
│ ├── flows
│ ├── vivado
│ │ ├── templates
│ │ │ ├── __init__.py
│ │ │ ├── vivado_power.tcl
│ │ │ ├── clock.xdc
│ │ │ └── util.tcl
│ │ ├── vivado_postsynthsim.py
│ │ └── vivado_power.py
│ ├── diamond
│ │ └── templates
│ │ │ ├── __init__.py
│ │ │ ├── constraints.ldc
│ │ │ ├── constraints.sdc
│ │ │ └── constraints.fdc
│ ├── modelsim
│ │ ├── templates
│ │ │ ├── __init__.py
│ │ │ └── run.tcl
│ │ └── __init__.py
│ ├── openroad
│ │ ├── openroad_scripts
│ │ │ ├── README.md
│ │ │ ├── deletePowerNets.tcl
│ │ │ ├── deleteNonClkNets.tcl
│ │ │ ├── view_cells.tcl
│ │ │ ├── gui.tcl
│ │ │ └── LICENSE.md
│ │ └── templates
│ │ │ ├── filler.tcl
│ │ │ ├── orflow.tcl
│ │ │ ├── detailed_place.tcl
│ │ │ ├── load.tcl
│ │ │ ├── clocks.sdc
│ │ │ ├── cts.tcl
│ │ │ ├── io_place.tcl
│ │ │ ├── floorplan.tcl
│ │ │ ├── resize.tcl
│ │ │ ├── detailed_route.tcl
│ │ │ ├── finalize.tcl
│ │ │ ├── macros.tcl.j2
│ │ │ ├── global_route.tcl
│ │ │ ├── global_place.tcl
│ │ │ └── resynth.tcl
│ ├── yosys
│ │ ├── __init__.py
│ │ ├── templates
│ │ │ ├── post_rtl.tcl
│ │ │ ├── write_netlist.tcl
│ │ │ ├── yosys_fpga_synth.tcl
│ │ │ └── yosys_synth.tcl
│ │ └── cxx_rtl.py
│ ├── ise
│ │ └── templates
│ │ │ ├── constraints.ucf
│ │ │ ├── constraints.xcf
│ │ │ └── ise_synth.tcl
│ ├── openxc7
│ │ └── templates
│ │ │ └── constraints.xdc
│ ├── quartus
│ │ ├── templates
│ │ │ ├── clock.sdc
│ │ │ ├── settings.dse
│ │ │ └── create_project.tcl
│ │ └── quartus_dse.py
│ ├── dc
│ │ └── templates
│ │ │ └── constraints.sdc
│ ├── __init__.py
│ └── openfpgaloader.py
│ ├── console.py
│ ├── platforms
│ ├── sky130hs
│ │ ├── tapcell.tcl
│ │ ├── fastroute.tcl
│ │ ├── fastroute_base.tcl
│ │ ├── cells_clkgate_hs.v
│ │ ├── cells_latch_hs.v
│ │ ├── make_tracks.tcl
│ │ ├── setRC.tcl
│ │ ├── cells_adders_hs.v
│ │ └── pdn.tcl
│ ├── sky130hd
│ │ ├── tapcell.tcl
│ │ ├── lib
│ │ │ └── sky130_fd_sc_hd__tt_025C_1v80.lib.gz
│ │ ├── fastroute.tcl
│ │ ├── fastroute_base.tcl
│ │ ├── cells_clkgate_hd.v
│ │ ├── cells_latch_hd.v
│ │ ├── make_tracks.tcl
│ │ ├── setRC.tcl
│ │ ├── cells_adders_hd.v
│ │ └── pdn.tcl
│ ├── nangate45
│ │ ├── tapcell.tcl
│ │ ├── gds
│ │ │ ├── NangateOpenCellLibrary.gds
│ │ │ └── NangateOpenCellLibrary.gds.orig
│ │ ├── lib
│ │ │ └── NangateOpenCellLibrary_typical.lib.gz
│ │ ├── fastroute.tcl
│ │ ├── cells_clkgate.v
│ │ ├── template_pga.cfg
│ │ ├── cells_latch.v
│ │ ├── README.md
│ │ ├── make_tracks.tcl
│ │ ├── setRC.tcl
│ │ ├── fakeram.tcl
│ │ ├── cells_adders.v
│ │ ├── grid_strategy-M1-M4-M7.tcl
│ │ └── fakeram.cfg
│ ├── asap7
│ │ ├── openlane
│ │ │ ├── README
│ │ │ ├── mapping.json
│ │ │ └── asap7sc7p5t
│ │ │ │ ├── config.tcl
│ │ │ │ └── no_synth.cells
│ │ ├── yosys
│ │ │ ├── cells_clkgate_L.v
│ │ │ ├── cells_clkgate_R.v
│ │ │ ├── cells_clkgate_SL.v
│ │ │ ├── cells_latch_L.v
│ │ │ ├── cells_latch_R.v
│ │ │ ├── cells_latch_SL.v
│ │ │ ├── cells_adders_L.v
│ │ │ ├── cells_adders_R.v
│ │ │ └── cells_adders_SL.v
│ │ ├── openroad
│ │ │ ├── tapcell.tcl
│ │ │ ├── pdn
│ │ │ │ ├── pdn.cfg
│ │ │ │ └── grid_strategy-M1-M2-M5-M6.tcl
│ │ │ ├── post_mergeLib.py
│ │ │ └── make_tracks.tcl
│ │ ├── setRC.tcl
│ │ ├── fakeram.cfg
│ │ ├── config.lvt.toml
│ │ └── config.slvt.toml
│ ├── __init__.py
│ ├── mk_to_toml.py
│ └── platform.py
│ ├── types.py
│ ├── flow_runner
│ ├── dse
│ │ └── __init__.py
│ └── __init__.py
│ ├── version.py
│ ├── __init__.py
│ ├── flow
│ ├── __init__.py
│ └── sim.py
│ ├── board.py
│ └── units.py
├── .gitattributes
├── xeda.png
├── examples
├── boards
│ └── ulx3s
│ │ ├── dvi_test
│ │ ├── ecp5pll.vhdl
│ │ ├── gen_pll.py
│ │ ├── xedaproject.toml
│ │ ├── blink.vhd
│ │ └── utils_pkg.vhdl
│ │ └── blinky
│ │ ├── blinky.xeda.yaml
│ │ ├── blinky_vhdl.xeda.yaml
│ │ ├── blinky.v
│ │ └── xedaproject.toml
├── requirements.txt
├── sv
│ └── fifo
│ │ ├── fifo_cocotb.xeda.yaml
│ │ ├── fifo.xeda.yaml
│ │ └── fifo.sv
├── mixed_language
│ └── blink
│ │ ├── xedaproject.toml
│ │ ├── blink.sv
│ │ ├── blinky.xeda.toml
│ │ └── blink_tb.cpp
└── vhdl
│ ├── full_adder.vhd
│ ├── pipeline
│ ├── pipelined_adder.toml
│ ├── synthesize.py
│ └── pipelined_adder.vhdl
│ ├── Trivium
│ ├── trivium.xeda.yaml
│ └── trivium.toml
│ ├── xedaproject.toml
│ ├── sqrt
│ ├── sqrt.toml
│ ├── test.py
│ └── tb_sqrt.py
│ ├── full_adder_piped.vhd
│ └── full_adder_tb.vhd
├── notebooks
└── requirements.txt
├── .github
├── dependabot.yml
└── workflows
│ ├── dependency-review.yml
│ ├── python-publish.yml
│ ├── ci.yml
│ └── codeql.yml
├── .readthedocs.yml
├── TODO.md
├── CHANGELOG.md
├── .pre-commit-config.yaml
├── tox.ini
├── .gitignore
└── get_oss_cad_suite.py
/MANIFEST.in:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/bugs.rst:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/about.rst:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/tutorial/index.rst:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/resources/test.v:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/xeda/data/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/xeda/data/boards/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/xeda/data/boards/ulx3s/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/fake_tools/vivado:
--------------------------------------------------------------------------------
1 | fake_tool.py
--------------------------------------------------------------------------------
/tests/fake_tools/xtclsh:
--------------------------------------------------------------------------------
1 | fake_tool.py
--------------------------------------------------------------------------------
/src/xeda/flows/vivado/templates/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/fake_tools/quartus_sh:
--------------------------------------------------------------------------------
1 | fake_tool.py
--------------------------------------------------------------------------------
/src/xeda/flows/diamond/templates/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/xeda/flows/modelsim/templates/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | src/xeda/_version.py export-subst
2 |
--------------------------------------------------------------------------------
/docs/flows.rst:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Flows
5 | -----
6 |
7 |
--------------------------------------------------------------------------------
/xeda.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XedaHQ/xeda/HEAD/xeda.png
--------------------------------------------------------------------------------
/examples/boards/ulx3s/dvi_test/ecp5pll.vhdl:
--------------------------------------------------------------------------------
1 | ../blinky/ecp5pll.vhdl
--------------------------------------------------------------------------------
/src/xeda/console.py:
--------------------------------------------------------------------------------
1 | from rich.console import Console
2 |
3 | console = Console()
4 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hs/tapcell.tcl:
--------------------------------------------------------------------------------
1 | tapcell \
2 | -distance 14 \
3 | -tapcell_master "sky130_fd_sc_hs__tap_1"
4 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hd/tapcell.tcl:
--------------------------------------------------------------------------------
1 | tapcell \
2 | -distance 14 \
3 | -tapcell_master "sky130_fd_sc_hd__tapvpwrvgnd_1"
4 |
--------------------------------------------------------------------------------
/tests/fake_tools/resource/fake_vivado_reports:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XedaHQ/xeda/HEAD/tests/fake_tools/resource/fake_vivado_reports
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/openroad_scripts/README.md:
--------------------------------------------------------------------------------
1 | Scripts are adopted from https://github.com/The-OpenROAD-Project/OpenROAD-flow-scripts
2 |
--------------------------------------------------------------------------------
/notebooks/requirements.txt:
--------------------------------------------------------------------------------
1 | pandas
2 | jupyterlab
3 | nbformat
4 | plotly
5 | kaleido
6 | # for bokeh plots:
7 | bokeh
8 | jupyter_bokeh
9 | selenium
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/tapcell.tcl:
--------------------------------------------------------------------------------
1 | tapcell \
2 | -distance 120 \
3 | -tapcell_master "TAPCELL_X1" \
4 | -endcap_master "TAPCELL_X1"
5 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 | TESTS_DIR = Path(__file__).parent.absolute()
4 | RESOURCES_DIR = TESTS_DIR / "resources"
5 |
--------------------------------------------------------------------------------
/docs/copyright.rst:
--------------------------------------------------------------------------------
1 | *********
2 | Copyright
3 | *********
4 |
5 | XEDA and this documentation is:
6 |
7 | Copyright © 2020 Kamyar Mohajerani. All rights reserved.
--------------------------------------------------------------------------------
/src/xeda/flows/diamond/templates/constraints.ldc:
--------------------------------------------------------------------------------
1 | create_clock -period {{ "%.3f"|format(flow.clock_period) }} -name clock [get_ports {{design.rtl.clock_port}}]
2 |
--------------------------------------------------------------------------------
/src/xeda/flows/diamond/templates/constraints.sdc:
--------------------------------------------------------------------------------
1 | create_clock -period {{ "%.3f"|format(flow.clock_period) }} -name clock [get_ports {{design.rtl.clock_port}}]
2 |
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/gds/NangateOpenCellLibrary.gds:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XedaHQ/xeda/HEAD/src/xeda/platforms/nangate45/gds/NangateOpenCellLibrary.gds
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: pip
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | open-pull-requests-limit: 10
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/openlane/README:
--------------------------------------------------------------------------------
1 | This is for an experimental integration of OpenROAD-flow-scripts into
2 | OpenLane. These files are not used directly by ORFS.
3 |
--------------------------------------------------------------------------------
/src/xeda/types.py:
--------------------------------------------------------------------------------
1 | """Type definitions"""
2 |
3 | import os
4 | from pathlib import Path
5 | from typing import Union
6 |
7 | PathLike = Union[str, Path, os.PathLike]
8 |
--------------------------------------------------------------------------------
/src/xeda/platforms/__init__.py:
--------------------------------------------------------------------------------
1 | from .asics import AsicsPlatform
2 | from .platform import Platform
3 |
4 | __all__ = [
5 | "Platform",
6 | "AsicsPlatform",
7 | ]
8 |
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/gds/NangateOpenCellLibrary.gds.orig:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XedaHQ/xeda/HEAD/src/xeda/platforms/nangate45/gds/NangateOpenCellLibrary.gds.orig
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hd/lib/sky130_fd_sc_hd__tt_025C_1v80.lib.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XedaHQ/xeda/HEAD/src/xeda/platforms/sky130hd/lib/sky130_fd_sc_hd__tt_025C_1v80.lib.gz
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/lib/NangateOpenCellLibrary_typical.lib.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XedaHQ/xeda/HEAD/src/xeda/platforms/nangate45/lib/NangateOpenCellLibrary_typical.lib.gz
--------------------------------------------------------------------------------
/src/xeda/flow_runner/dse/__init__.py:
--------------------------------------------------------------------------------
1 | from .dse_runner import Dse, Optimizer
2 | from .fmax import FmaxOptimizer
3 |
4 | __all__ = [
5 | "Dse",
6 | "Optimizer",
7 | "FmaxOptimizer",
8 | ]
9 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/filler.tcl:
--------------------------------------------------------------------------------
1 | set_propagated_clock [all_clocks]
2 |
3 | filler_placement {{platform.fill_cells|join(" ")|embrace}}
4 | check_placement
5 |
6 | {{ write_checkpoint(step) }}
7 |
--------------------------------------------------------------------------------
/.readthedocs.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | sphinx:
4 | configuration: docs/conf.py
5 | fail_on_warning: false
6 |
7 | python:
8 | version: "3.8"
9 | install:
10 | - requirements: docs/requirements.txt
11 |
--------------------------------------------------------------------------------
/examples/requirements.txt:
--------------------------------------------------------------------------------
1 | cocotb ~= 2.0.0
2 | cocotb-coverage ~= 2.0.0
3 | setuptools >= 65.0
4 | pytest >= 8.0
5 | # cocolight>=0.0.3
6 | cocolight @ git+https://github.com/kammoh/cocolight.git
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hs/fastroute.tcl:
--------------------------------------------------------------------------------
1 | set_global_routing_layer_adjustment $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) 0.3
2 |
3 | set_routing_layers -signal $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER)
4 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hd/fastroute.tcl:
--------------------------------------------------------------------------------
1 | set_global_routing_layer_adjustment $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) 0.3
2 |
3 | set_routing_layers -signal $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER)
4 |
5 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hd/fastroute_base.tcl:
--------------------------------------------------------------------------------
1 | set_global_routing_layer_adjustment $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) 0.3
2 |
3 | set_routing_layers -signal $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER)
4 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hs/fastroute_base.tcl:
--------------------------------------------------------------------------------
1 | set_global_routing_layer_adjustment $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) 0.3
2 |
3 | set_routing_layers -signal $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER)
4 |
--------------------------------------------------------------------------------
/examples/sv/fifo/fifo_cocotb.xeda.yaml:
--------------------------------------------------------------------------------
1 | sources:
2 | - fifo.sv
3 | top: fifo
4 |
5 | clock.port: clk
6 |
7 | tb:
8 | sources:
9 | - fifo_tb.py
10 | top: fifo_tb
11 |
12 | flows:
13 | verilator:
14 | timing: false
--------------------------------------------------------------------------------
/src/xeda/version.py:
--------------------------------------------------------------------------------
1 | from importlib.metadata import PackageNotFoundError, version
2 |
3 | try:
4 | __version__ = version("xeda")
5 | except PackageNotFoundError:
6 | # package is not installed
7 | __version__ = "unknown"
8 |
--------------------------------------------------------------------------------
/examples/mixed_language/blink/xedaproject.toml:
--------------------------------------------------------------------------------
1 | [[design]]
2 | name = "blink"
3 |
4 | [design.rtl]
5 | sources = ["blink.sv"]
6 |
7 | [design.tb]
8 | sources = ["blink_tb.cpp"]
9 |
10 | [flows.cxxrtl]
11 | cxxrtl.filename = "blink.cpp"
12 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | sphinx
2 | docutils
3 | sphinx-tabs
4 | sphinx-jinja
5 | sphinxcontrib.bibtex
6 | sphinx_panels
7 | sphinxext.rediraffe
8 | sphinxcontrib.mermaid
9 | sphinxext.opengraph
10 | autodoc_pydantic
11 | sphinx_book_theme
12 | myst-parser
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/fastroute.tcl:
--------------------------------------------------------------------------------
1 | set_global_routing_layer_adjustment metal2-metal3 0.5
2 | set_global_routing_layer_adjustment metal4-$::env(MAX_ROUTING_LAYER) 0.25
3 |
4 | set_routing_layers -signal $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER)
5 |
--------------------------------------------------------------------------------
/src/xeda/data/boards.toml:
--------------------------------------------------------------------------------
1 | ## board name _ variant _ version (no dots or otherwise surround with double quotes)
2 | [ULX3S_85F]
3 | name = 'ulx3s'
4 | fpga.part = 'LFE5U-85F-6BG381C'
5 | lpf = 'https://raw.githubusercontent.com/emard/ulx3s/master/doc/constraints/ulx3s_v20.lpf'
6 |
--------------------------------------------------------------------------------
/src/xeda/flows/yosys/__init__.py:
--------------------------------------------------------------------------------
1 | from .cxx_rtl import CxxRtl
2 | from .yosys import HiLoMap, Yosys, preproc_libs
3 | from .yosys_fpga import YosysFpga
4 |
5 | __all__ = [
6 | "Yosys",
7 | "HiLoMap",
8 | "preproc_libs",
9 | "YosysFpga",
10 | "CxxRtl",
11 | ]
12 |
--------------------------------------------------------------------------------
/examples/boards/ulx3s/blinky/blinky.xeda.yaml:
--------------------------------------------------------------------------------
1 | sources: ["blinky.v"]
2 | top: blinky
3 | clock.port: "clk_25mhz"
4 |
5 | flows:
6 | openfpgaloader:
7 | clock.freq: 25MHz
8 | nextpnr:
9 | board: ULX3S_85F
10 | yosys_fpga:
11 | fpga.family: ecp5
12 | clock.freq: 25MHz
13 |
--------------------------------------------------------------------------------
/src/xeda/flows/ise/templates/constraints.ucf:
--------------------------------------------------------------------------------
1 | {% for clock_name, clock in settings.clocks.items() %}
2 | {% if clock.port %}
3 | NET "{{clock.port}}" TNM_NET = "{{clock.port}}";
4 | TIMESPEC "TS{{clock.port}}" = PERIOD "{{clock.port}}" {{"%.03f" % clock.period}} ns HIGH 50%;
5 | {% endif %}
6 | {% endfor %}
--------------------------------------------------------------------------------
/src/xeda/flows/ise/templates/constraints.xcf:
--------------------------------------------------------------------------------
1 | {% for clock_name, clock in settings.clocks.items() %}
2 | {% if clock.port %}
3 | NET "{{clock.port}}" TNM_NET = "{{clock.port}}";
4 | TIMESPEC "TS{{clock.port}}" = PERIOD "{{clock.port}}" {{"%.03f" % clock.period}} ns HIGH 50%;
5 | {% endif %}
6 | {% endfor %}
--------------------------------------------------------------------------------
/examples/sv/fifo/fifo.xeda.yaml:
--------------------------------------------------------------------------------
1 | sources:
2 | - fifo.sv
3 | top: fifo
4 |
5 | clock.port: clk
6 |
7 | tb:
8 | sources:
9 | - fifo_tb.sv
10 | # - tb/fifo_tb.py
11 | # cocotb: true
12 | # top: fifo_tb
13 |
14 | flows:
15 | verilator:
16 | timing: true
17 | vcd: $PWD/fifo.vcd
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/cells_clkgate.v:
--------------------------------------------------------------------------------
1 | module OPENROAD_CLKGATE (CK, E, GCK);
2 | input CK;
3 | input E;
4 | output GCK;
5 |
6 | `ifdef OPENROAD_CLKGATE
7 |
8 | CLKGATE_X1 latch (.CK (CK), .E(E), .GCK(GCK));
9 |
10 | `else
11 |
12 | assign GCK = CK;
13 |
14 | `endif
15 |
16 | endmodule
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hd/cells_clkgate_hd.v:
--------------------------------------------------------------------------------
1 | module OPENROAD_CLKGATE (CK, E, GCK);
2 | input CK;
3 | input E;
4 | output GCK;
5 |
6 | `ifdef OPENROAD_CLKGATE
7 |
8 | sky130_fd_sc_hd__dlclkp_1 latch (.CLK (CK), .GATE(E), .GCLK(GCK));
9 |
10 | `else
11 |
12 | assign GCK = CK;
13 |
14 | `endif
15 |
16 | endmodule
17 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hs/cells_clkgate_hs.v:
--------------------------------------------------------------------------------
1 | module OPENROAD_CLKGATE (CK, E, GCK);
2 | input CK;
3 | input E;
4 | output GCK;
5 |
6 | `ifdef OPENROAD_CLKGATE
7 |
8 | sky130_fd_sc_hs__dlclkp_1 latch (.CLK (CK), .GATE(E), .GCLK(GCK));
9 |
10 | `else
11 |
12 | assign GCK = CK;
13 |
14 | `endif
15 |
16 | endmodule
17 |
--------------------------------------------------------------------------------
/examples/boards/ulx3s/dvi_test/gen_pll.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import logging
3 | from xeda.flows.nextpnr import EcpPLL
4 |
5 | log = logging.getLogger(__name__)
6 |
7 | log.root.setLevel(logging.DEBUG)
8 |
9 | f_pixel = 25.0
10 |
11 | if __name__ == "__main__":
12 | EcpPLL(clkouts=[600]).generate() # type: ignore
13 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/yosys/cells_clkgate_L.v:
--------------------------------------------------------------------------------
1 | module OPENROAD_CLKGATE (CK, E, GCK);
2 | input CK;
3 | input E;
4 | output GCK;
5 |
6 | `ifdef OPENROAD_CLKGATE
7 |
8 | ICGx1_ASAP7_75t_L latch ( .CLK(CK), .ENA(E), .SE(1'b0), .GCLK(GCK) );
9 |
10 | `else
11 |
12 | assign GCK = CK;
13 |
14 | `endif
15 |
16 | endmodule
17 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/yosys/cells_clkgate_R.v:
--------------------------------------------------------------------------------
1 | module OPENROAD_CLKGATE (CK, E, GCK);
2 | input CK;
3 | input E;
4 | output GCK;
5 |
6 | `ifdef OPENROAD_CLKGATE
7 |
8 | ICGx1_ASAP7_75t_R latch ( .CLK(CK), .ENA(E), .SE(1'b0), .GCLK(GCK) );
9 |
10 | `else
11 |
12 | assign GCK = CK;
13 |
14 | `endif
15 |
16 | endmodule
17 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/yosys/cells_clkgate_SL.v:
--------------------------------------------------------------------------------
1 | module OPENROAD_CLKGATE (CK, E, GCK);
2 | input CK;
3 | input E;
4 | output GCK;
5 |
6 | `ifdef OPENROAD_CLKGATE
7 |
8 | ICGx1_ASAP7_75t_SL latch ( .CLK(CK), .ENA(E), .SE(1'b0), .GCLK(GCK) );
9 |
10 | `else
11 |
12 | assign GCK = CK;
13 |
14 | `endif
15 |
16 | endmodule
17 |
--------------------------------------------------------------------------------
/examples/boards/ulx3s/blinky/blinky_vhdl.xeda.yaml:
--------------------------------------------------------------------------------
1 | hdl.vhdl.standard: "2008"
2 |
3 | sources: ["ecp5pll.vhdl", "blinky.vhdl"]
4 | top: blinky
5 | clock.port: "clk_25mhz"
6 |
7 | flows:
8 | openfpgaloader:
9 | clock.freq: 25MHz
10 | nextpnr:
11 | board: ULX3S_85F
12 | yosys_fpga:
13 | fpga.family: ecp5
14 | clock.freq: 25MHz
15 |
--------------------------------------------------------------------------------
/src/xeda/flows/openxc7/templates/constraints.xdc:
--------------------------------------------------------------------------------
1 | {% for clock_name, clock in settings.clocks.items() -%}
2 | {% if clock.port -%}
3 | create_clock -period {{"%.03f" % clock.period}} -name {{clock_name}} [get_ports {{clock.port}}]
4 | {% endif -%}
5 | {% endfor -%}
6 |
7 | {% if other_constraints %}
8 | {{ other_constraints }}
9 | {% endif -%}
10 |
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/template_pga.cfg:
--------------------------------------------------------------------------------
1 | pdn specify_grid stdcell {
2 | name low
3 | rails metal1
4 | layers {
5 | metal1 {width 0.17 pitch 2.4 offset 0}
6 | metal4 {width 0.48 pitch 55.2 offset 2}
7 | metal7 {width 1.40 pitch 40.8 offset 2}
8 | }
9 | connect {{metal1 metal4} {metal4 metal7}}
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/examples/mixed_language/blink/blink.sv:
--------------------------------------------------------------------------------
1 | module blink(
2 | input clk,
3 | input reset,
4 | output led
5 | );
6 | logic [7:0] counter;
7 |
8 | always @(posedge clk) begin
9 | if (reset == 1)
10 | counter <= 0;
11 | else
12 | counter <= counter + 1'b1;
13 | end
14 |
15 | assign led = counter[7];
16 |
17 | endmodule
18 |
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/cells_latch.v:
--------------------------------------------------------------------------------
1 | module $_DLATCH_P_(input E, input D, output Q);
2 | DLH_X1 _TECHMAP_REPLACE_ (
3 | .D(D),
4 | .G(E),
5 | .Q(Q)
6 | );
7 | endmodule
8 |
9 | module $_DLATCH_N_(input E, input D, output Q);
10 | DLL_X1 _TECHMAP_REPLACE_ (
11 | .D(D),
12 | .GN(E),
13 | .Q(Q)
14 | );
15 | endmodule
--------------------------------------------------------------------------------
/src/xeda/flows/quartus/templates/clock.sdc:
--------------------------------------------------------------------------------
1 | {% for clock_name,clock in settings.clocks.items() -%}
2 | {% if clock.port -%}
3 | # create_clock -period {{ "%.3f"|format(clock.period) }} -name {{clock_name}} [get_ports {{clock.port}}]
4 | create_clock -period {{clock.period|round(3,'floor')}} -name {{clock_name}} [get_ports {{clock.port}}]
5 | {% endif -%}
6 | {% endfor -%}
7 |
8 | derive_pll_clocks
9 | derive_clock_uncertainty
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/openroad/tapcell.tcl:
--------------------------------------------------------------------------------
1 | puts "\[INFO-FLOW\] Tap and End Cap cell insertion"
2 | puts "\[INFO-FLOW\] TAP Cell : $::env(TAP_CELL_NAME)"
3 | puts "\[INFO-FLOW\] ENDCAP Cell : $::env(TAP_CELL_NAME)"
4 | puts "\[INFO-FLOW\] TAP Cell Distance : 25"
5 |
6 | tapcell \
7 | -distance 25 \
8 | -tapcell_master "$::env(TAP_CELL_NAME)" \
9 | -endcap_master "$::env(TAP_CELL_NAME)"
10 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/yosys/cells_latch_L.v:
--------------------------------------------------------------------------------
1 | module $_DLATCH_P_(input E, input D, output Q);
2 | DHLx1_ASAP7_75t_L _TECHMAP_REPLACE_ (
3 | .D(D),
4 | .CLK(E),
5 | .Q(Q)
6 | );
7 | endmodule
8 |
9 | module $_DLATCH_N_(input E, input D, output Q);
10 | DLLx1_ASAP7_75t_L _TECHMAP_REPLACE_ (
11 | .D(D),
12 | .CLK(E),
13 | .Q(Q)
14 | );
15 | endmodule
16 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/yosys/cells_latch_R.v:
--------------------------------------------------------------------------------
1 | module $_DLATCH_P_(input E, input D, output Q);
2 | DHLx1_ASAP7_75t_R _TECHMAP_REPLACE_ (
3 | .D(D),
4 | .CLK(E),
5 | .Q(Q)
6 | );
7 | endmodule
8 |
9 | module $_DLATCH_N_(input E, input D, output Q);
10 | DLLx1_ASAP7_75t_R _TECHMAP_REPLACE_ (
11 | .D(D),
12 | .CLK(E),
13 | .Q(Q)
14 | );
15 | endmodule
16 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/yosys/cells_latch_SL.v:
--------------------------------------------------------------------------------
1 | module $_DLATCH_P_(input E, input D, output Q);
2 | DHLx1_ASAP7_75t_SL _TECHMAP_REPLACE_ (
3 | .D(D),
4 | .CLK(E),
5 | .Q(Q)
6 | );
7 | endmodule
8 |
9 | module $_DLATCH_N_(input E, input D, output Q);
10 | DLLx1_ASAP7_75t_SL _TECHMAP_REPLACE_ (
11 | .D(D),
12 | .CLK(E),
13 | .Q(Q)
14 | );
15 | endmodule
16 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hd/cells_latch_hd.v:
--------------------------------------------------------------------------------
1 | module $_DLATCH_P_(input E, input D, output Q);
2 | sky130_fd_sc_hd__dlxtp_1 _TECHMAP_REPLACE_ (
3 | .D(D),
4 | .GATE(E),
5 | .Q(Q)
6 | );
7 | endmodule
8 |
9 | module $_DLATCH_N_(input E, input D, output Q);
10 | sky130_fd_sc_hd__dlxtn_1 _TECHMAP_REPLACE_ (
11 | .D(D),
12 | .GATE_N(E),
13 | .Q(Q)
14 | );
15 | endmodule
16 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hs/cells_latch_hs.v:
--------------------------------------------------------------------------------
1 | module $_DLATCH_P_(input E, input D, output Q);
2 | sky130_fd_sc_hs__dlxtp_1 _TECHMAP_REPLACE_ (
3 | .D(D),
4 | .GATE(E),
5 | .Q(Q)
6 | );
7 | endmodule
8 |
9 | module $_DLATCH_N_(input E, input D, output Q);
10 | sky130_fd_sc_hs__dlxtn_1 _TECHMAP_REPLACE_ (
11 | .D(D),
12 | .GATE_N(E),
13 | .Q(Q)
14 | );
15 | endmodule
16 |
--------------------------------------------------------------------------------
/examples/vhdl/full_adder.vhd:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 |
4 | entity full_adder is
5 | port (
6 | a : in std_logic;
7 | b : in std_logic;
8 | ci : in std_logic;
9 | s : out std_logic;
10 | co : out std_logic);
11 | end;
12 |
13 | architecture behavioral of full_adder is
14 | begin
15 | s <= a xor b xor ci;
16 | co <= (a and b) or (b and ci) or (ci and a);
17 | end;
--------------------------------------------------------------------------------
/tests/resources/cocotb/results.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/examples/mixed_language/blink/blinky.xeda.toml:
--------------------------------------------------------------------------------
1 | [rtl]
2 | sources = ["blink.sv"]
3 | top = "blink"
4 | # clocks = [{port = "clk"}]
5 | clock.port = "clk"
6 |
7 | [tb]
8 | sources = ["blink_tb.cpp"]
9 |
10 | [flows.cxxrtl]
11 | cxxrtl.filename = "blink.cpp"
12 |
13 | [flows.yosys_fpga]
14 | fpga.vendor = "xilinx"
15 | fpga.family = "xc7"
16 | clock.period = 5.0
17 |
18 | [flows.vivado_synth]
19 | fpga.part = "xc7a100tftg256-2L"
20 | clock.period = 5.0
21 |
--------------------------------------------------------------------------------
/examples/vhdl/pipeline/pipelined_adder.toml:
--------------------------------------------------------------------------------
1 | name = 'pipelined_adder'
2 | description = 'Example VHDL design'
3 | language.vhdl.standard = 2008
4 |
5 | [rtl]
6 | sources = ['pipelined_adder.vhdl']
7 | top = 'pipelined_adder'
8 | clock_port = 'clock'
9 |
10 | [tb]
11 | sources = ['pipelined_adder_tb.vhdl']
12 | top = 'pipelined_adder_tb'
13 | uut = 'uut'
14 |
15 | [flow.openroad]
16 | platform = "sky130hd"
17 | clocks.main_clock.freq = "200 MHz"
18 | core_utilization = 45
19 |
--------------------------------------------------------------------------------
/src/xeda/flows/diamond/templates/constraints.fdc:
--------------------------------------------------------------------------------
1 | {% if not flow.allow_dsps %}
2 | define_global_attribute syn_multstyle logic
3 |
4 | define_scope_collection all_insts {find -hier -net {*}}
5 | define_attribute {$all_insts} {syn_multstyle} {logic}
6 | {% endif %}
7 |
8 | {% if not flow.allow_brams %}
9 | define_global_attribute {syn_ramstyle} {distributed}
10 |
11 | define_scope_collection all_insts {find -hier -net {*}}
12 | define_attribute {$all_insts} {syn_ramstyle} {distributed}
13 | {% endif %}
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hd/make_tracks.tcl:
--------------------------------------------------------------------------------
1 | make_tracks li1 -x_offset 0.23 -x_pitch 0.46 -y_offset 0.17 -y_pitch 0.34
2 | make_tracks met1 -x_offset 0.17 -x_pitch 0.34 -y_offset 0.17 -y_pitch 0.34
3 | make_tracks met2 -x_offset 0.23 -x_pitch 0.46 -y_offset 0.23 -y_pitch 0.46
4 | make_tracks met3 -x_offset 0.34 -x_pitch 0.68 -y_offset 0.34 -y_pitch 0.68
5 | make_tracks met4 -x_offset 0.46 -x_pitch 0.92 -y_offset 0.46 -y_pitch 0.92
6 | make_tracks met5 -x_offset 1.70 -x_pitch 3.40 -y_offset 1.70 -y_pitch 3.40
7 |
--------------------------------------------------------------------------------
/tests/resources/design0/design0.toml:
--------------------------------------------------------------------------------
1 | name = 'design0'
2 | description = 'test'
3 | language.vhdl.standard = "2008"
4 |
5 | [rtl]
6 | sources = ['../test.v'] # by default relative paths are relative to the location of the TOML file, unless overridden by the "design_root" field
7 | top = 'design0'
8 | clock_port = 'clk'
9 | parameters = { G_IN_WIDTH = 32, G_ITERATIVE = true, G_STR= "abcd", G_BITVECTOR="7'b0101001" }
10 |
11 | # [tb]
12 | # sources = []
13 | # cocotb = true
14 | # # top = 'tb_sqrt'
15 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hs/make_tracks.tcl:
--------------------------------------------------------------------------------
1 | make_tracks li1 -x_offset 0.24 -x_pitch 0.48 -y_offset 0.185 -y_pitch 0.37
2 | make_tracks met1 -x_offset 0.185 -x_pitch 0.37 -y_offset 0.185 -y_pitch 0.37
3 | make_tracks met2 -x_offset 0.24 -x_pitch 0.48 -y_offset 0.24 -y_pitch 0.48
4 | make_tracks met3 -x_offset 0.37 -x_pitch 0.74 -y_offset 0.37 -y_pitch 0.74
5 | make_tracks met4 -x_offset 0.48 -x_pitch 0.96 -y_offset 0.48 -y_pitch 0.96
6 | make_tracks met5 -x_offset 1.85 -x_pitch 3.33 -y_offset 1.85 -y_pitch 3.33
7 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | .. XEDA documentation master file, created by
2 | sphinx-quickstart on Tue Sep 1 01:28:46 2020.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to XEDA's documentation!
7 | ================================
8 |
9 | .. toctree::
10 | :maxdepth: 2
11 | :caption: Contents:
12 |
13 |
14 |
15 | Indices and tables
16 | ==================
17 |
18 | * :ref:`genindex`
19 | * :ref:`modindex`
20 | * :ref:`search`
21 |
--------------------------------------------------------------------------------
/examples/vhdl/pipeline/synthesize.py:
--------------------------------------------------------------------------------
1 | from subprocess import check_call
2 |
3 |
4 | def quartus_synth():
5 | check_call(
6 | [
7 | "xeda",
8 | "run",
9 | "quartus",
10 | "--design",
11 | "pipelined_adder.toml",
12 | "--settings",
13 | "dockerized=true",
14 | "fpga.part=10CL016YU256C6G",
15 | "clock_period=15",
16 | ]
17 | )
18 |
19 |
20 | if __name__ == "__main__":
21 | quartus_synth()
22 |
--------------------------------------------------------------------------------
/src/xeda/flows/vivado/templates/vivado_power.tcl:
--------------------------------------------------------------------------------
1 | set_param tclapp.enableGitAccess 0
2 |
3 | puts "\n================================( Opening routed design from checkpoint )================================="
4 | open_checkpoint {{checkpoint}}
5 |
6 | puts "\n================================( Reporting power from {{settings.saif}} )================================="
7 | reset_switching_activity -all
8 | eval read_saif -verbose {{saif_file}}
9 | report_power -hier all -format xml -verbose -file {{settings.power_report_xml}}
10 |
--------------------------------------------------------------------------------
/tests/resources/Fitter_Resource_Utilization_by_Entity.csv:
--------------------------------------------------------------------------------
1 | Compilation Hierarchy Node,ALMs needed [=A-B+C],[A] ALMs used in final placement,[B] Estimate of ALMs recoverable by dense packing,[C] Estimate of ALMs unavailable,ALMs used for memory,Combinational ALUTs,Dedicated Logic Registers,I/O Registers,Block Memory Bits,M10Ks,DSP Blocks,Pins,Virtual Pins,Full Hierarchy Name,Entity Name,Library Name
2 | |full_adder_piped,1.5 (1.5),1.5 (1.5),0.0 (0.0),0.0 (0.0),0.0 (0.0),3 (3),2 (2),0 (0),0,0,0,7,0,|full_adder_piped,full_adder_piped,work
3 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/orflow.tcl:
--------------------------------------------------------------------------------
1 | {% from "macros.tcl.j2" import write_checkpoint, load_checkpoint, preamble, epilogue, section with context %}
2 |
3 | {% for step in steps_to_run %}
4 | {% set step_index = loop.index0 + starting_index %}
5 | {% set step_id = "%d_%s"|format(step_index, step) %}
6 | {% set prev_step_id = get_prev_step_id(step) %}
7 | {% if loop.index0 == 0 %}
8 | {% include "utils.tcl" %}
9 | {% endif %}
10 | {{ preamble(step, step_index) }}
11 | {% include step + '.tcl' %}
12 | {{ epilogue(step) }}
13 | {% endfor %}
14 |
--------------------------------------------------------------------------------
/examples/vhdl/Trivium/trivium.xeda.yaml:
--------------------------------------------------------------------------------
1 | hdl.vhdl.standard: 2008
2 |
3 | sources:
4 | - trivium.vhdl
5 | parameters:
6 | G_IN_BITS: 64
7 | G_OUT_BITS: 64
8 | G_SETUP_ROUNDS: 4
9 | top: trivium
10 | clock.port: clk
11 |
12 | test:
13 | sources:
14 | - trivium_tb.py
15 | - cref/trivium64.c
16 |
17 | flows:
18 | vivado_synth:
19 | fpga.part: xc7a12tcsg325-3
20 | clock.freq: 200MHz
21 | yosys_fpga:
22 | fpga.part: xc7a12tcsg325-3
23 | clock.freq: 200MHz
24 | dc:
25 | target_libraries:
26 | - $PWD/lib/SAED90/saed90nm_typ_ht.db
27 |
--------------------------------------------------------------------------------
/src/xeda/flow_runner/__init__.py:
--------------------------------------------------------------------------------
1 | from . import dse
2 | from .default_runner import (
3 | DIR_NAME_HASH_LEN,
4 | DefaultRunner,
5 | FlowNotFoundError,
6 | FlowRunner,
7 | XedaOptions,
8 | add_file_logger,
9 | get_flow_class,
10 | scrub_runs,
11 | )
12 | from .dse import Dse
13 |
14 | __all__ = [
15 | "dse",
16 | "Dse",
17 | "FlowRunner",
18 | "DefaultRunner",
19 | "FlowNotFoundError",
20 | "XedaOptions",
21 | "get_flow_class",
22 | "add_file_logger",
23 | "DIR_NAME_HASH_LEN",
24 | "scrub_runs",
25 | ]
26 |
--------------------------------------------------------------------------------
/docs/contents.rst:
--------------------------------------------------------------------------------
1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 | Xeda Documentation Contents
3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4 |
5 |
6 |
7 | **Xeda** `/ˈziːdə/` is a cross-platform, cross-EDA, cross-target automated synthesis and simulation platform.
8 | It helps hardware developers to verify, evaluate, and deploy their RTL designs using multiple commercial and open-source electronic design automation flows.
9 |
10 |
11 | .. toctree::
12 | tutorial/index.rst
13 |
14 | about.rst
15 | quickstart.rst
16 | flows.rst
17 | bugs.rst
18 | copyright.rst
19 | license.rst
--------------------------------------------------------------------------------
/examples/vhdl/Trivium/trivium.toml:
--------------------------------------------------------------------------------
1 | name = "trivium"
2 |
3 | language.vhdl.standard = "2008"
4 |
5 | [rtl]
6 | sources = [ #
7 | "trivium.vhdl",
8 | ]
9 | parameters.G_IN_BITS = 64
10 | parameters.G_OUT_BITS = 64 # 96
11 | # parameters.G_SETUP_ROUNDS = 4
12 | top = "trivium"
13 | clock.port = "clk"
14 |
15 |
16 | [tb]
17 | sources = ["trivium_tb.py", "cref/trivium64.c"]
18 | cocotb = true
19 |
20 | [flow.vivado_synth]
21 | fpga.part = "xc7a12tcsg325-3"
22 | clock.freq = "200 MHz"
23 |
24 | [flow.yosys_fpga]
25 | fpga.part = "xc7a12tcsg325-3"
26 | clock.freq = "200 MHz"
27 |
--------------------------------------------------------------------------------
/src/xeda/flows/quartus/templates/settings.dse:
--------------------------------------------------------------------------------
1 | # This file is generated by XEDA
2 | launcher=local
3 | group_id=xeda_dse
4 | num_concurrent={{dse.num_concurrent}}
5 | num_parallel_processors={{dse.nproc}}
6 | num_seeds={{dse.num_seeds}}
7 | explore={{dse.explore}}
8 | compile_flow={{dse.compile_flow}}
9 | auto_discover_files=True
10 | auto_overwrite_project=True
11 | save_results=all
12 | skip_base_compile=True
13 | time_limit_value={{dse.timeout}}
14 | stop_after_timing_met={{dse.stop_on_success}}
15 | report_filename={{settings.reports_dir}}/quartus_dse_report.json
16 | report_format=json
--------------------------------------------------------------------------------
/src/xeda/__init__.py:
--------------------------------------------------------------------------------
1 | from . import design, flow_runner, flows
2 | from .cocotb import Cocotb
3 | from .design import Design
4 | from .flow import FPGA, Flow, SimFlow, SynthFlow
5 | from .flow_runner import DefaultRunner, Dse, FlowRunner
6 | from .tool import Tool
7 | from .version import __version__
8 |
9 | __all__ = [
10 | "__version__",
11 | "Cocotb",
12 | "DefaultRunner",
13 | "design",
14 | "Design",
15 | "Dse",
16 | "flow_runner",
17 | "FlowRunner",
18 | "flows",
19 | "Flow",
20 | "FPGA",
21 | "SimFlow",
22 | "SynthFlow",
23 | "Tool",
24 | ]
25 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/openroad/pdn/pdn.cfg:
--------------------------------------------------------------------------------
1 | # Floorplan information - core boundary coordinates, std. cell row height,
2 |
3 | set ::halo 2
4 |
5 | # POWER or GROUND #Std. cell rails starting with power or ground rails at the bottom of the core area
6 | set ::rails_start_with "POWER" ;
7 |
8 | # POWER or GROUND #Upper metal stripes starting with power or ground rails at the left/bottom of the core area
9 | set ::stripes_start_with "POWER" ;
10 |
11 | # Power nets
12 | set ::power_nets "VDD"
13 | set ::ground_nets "VSS"
14 |
15 | ##===> Power grid strategy
16 | source $::env(PLATFORM_DIR)/openRoad/pdn/grid_strategy-M1-M2-M5-M6.cfg
17 |
--------------------------------------------------------------------------------
/examples/vhdl/xedaproject.toml:
--------------------------------------------------------------------------------
1 | [[design]]
2 | name = 'full-adder'
3 | description = 'Example VHDL design'
4 | [design.rtl]
5 | sources = ['full_adder.vhd']
6 | top = 'full_adder'
7 | clock_port = ''
8 | [design.tb]
9 | sources = ['full_adder_tb.vhd']
10 | top = 'full_adder_tb'
11 |
12 |
13 | [flows.ghdl_sim]
14 | warn_error = true
15 |
16 | [flows.vivado_prj_synth]
17 | fpga.part = 'xc7a12tcsg325-1'
18 | clock_period = 5.0
19 |
20 | [flows.vivado_synth]
21 | fpga.part = 'xc7a12tcsg325-1'
22 | clock_period = 5.0
23 |
24 | [flows.ise_synth]
25 | fpga.family = "virtex5"
26 | fpga.device = "XC5VLX50"
27 | fpga.speed = -1
28 | fpga.package = "FFG676C"
29 | clock_period = 5.0
30 |
31 |
--------------------------------------------------------------------------------
/tests/test_gtkw.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 | from xeda.flows.ghdl import _get_wave_opt_signals, common_root
4 |
5 | TESTS_DIR = Path(__file__).parent.absolute()
6 | RESOURCES_DIR = TESTS_DIR / "resources"
7 |
8 |
9 | def test_gen_gtkw():
10 | opt_file = RESOURCES_DIR / "wave.opt"
11 | extra_top = "top"
12 |
13 | signals, root_group = _get_wave_opt_signals(opt_file, extra_top)
14 | assert len(signals) > 1
15 | assert len(root_group) == 2
16 |
17 |
18 | def test_common_root():
19 | cr = common_root([[1, 2, 3, 4, 5], [1, 2, 3, 7], [1, 2, 3], [1, 2, 3, 9]])
20 | assert cr == [1, 2, 3]
21 |
22 |
23 | if __name__ == "__main__":
24 | test_gen_gtkw()
25 |
--------------------------------------------------------------------------------
/examples/boards/ulx3s/dvi_test/xedaproject.toml:
--------------------------------------------------------------------------------
1 | [design]
2 |
3 | name = "dvi_test"
4 |
5 | [design.language]
6 | vhdl.standard = 2008
7 |
8 | [design.rtl]
9 | sources = [
10 | "utils_pkg.vhdl",
11 | "vga.vhd",
12 | "vga2dvid.vhd",
13 | "tmds_encoder.vhd",
14 | "ecp5pll.vhdl",
15 | "top_vgatest.vhd",
16 | ]
17 | top = "top_vgatest"
18 |
19 | clock_port = "clk_25mhz"
20 |
21 | [flows.nextpnr]
22 | board = "ULX3S_85F"
23 | clock_period = 40 # 25 MHz
24 | detailed_timing_report = false # nextpnr BUG, o/w crashes
25 |
26 | [flows.openfpgaloader]
27 | board = "ULX3S_85F"
28 | clock_period = 40 # 25 MHz
29 | nextpnr.detailed_timing_report = false
30 | nextpnr.timing_allow_fail = true
31 |
--------------------------------------------------------------------------------
/examples/boards/ulx3s/dvi_test/blink.vhd:
--------------------------------------------------------------------------------
1 | -- (c)EMARD
2 | -- License=BSD
3 |
4 | library IEEE;
5 | use IEEE.STD_LOGIC_1164.ALL;
6 |
7 | entity blink is
8 | generic
9 | (
10 | bits: integer := 23
11 | );
12 | port
13 | (
14 | clk: in std_logic; -- main clock input from 25MHz clock source
15 | led: out std_logic_vector(7 downto 0)
16 | );
17 | end;
18 |
19 | architecture Behavioral of blink is
20 | signal R_blink: std_logic_vector(bits-1 downto 0);
21 | begin
22 | process(clk)
23 | begin
24 | if rising_edge(clk) then
25 | R_blink <= R_blink+1;
26 | end if;
27 | end process;
28 | led <= R_blink(R_blink'high downto R_blink'high-7);
29 | end Behavioral;
30 |
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/README.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | The Nangate Open Cell Library is a generic open-source, standard-cell
4 | library provided for the purposes of research, testing, and exploring EDA
5 | flows. This library is purposely non-manufacturable.
6 |
7 | Version: PDKv1.3_v2010_12.Apache.CCL
8 |
9 | # Source
10 |
11 | Downloaded from https://projects.si2.org/openeda.si2.org/project/showfiles.php?group_id=63#503
12 |
13 | # Modifications
14 |
15 | - Performed abstract generation from the gds files to avoid polygon pin shapes in the LEF.
16 | - Added additional files and info required for the OpenROAD flow.
17 | - Fix contact enclosure by poly on cell `AOI21_X1` (rule CONTACT.5).
18 | - Added LICENSE.
19 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/examples/boards/ulx3s/blinky/blinky.v:
--------------------------------------------------------------------------------
1 |
2 | module blinky(
3 | input clk_25mhz,
4 | input [6:0] btn,
5 | output [7:0] led
6 | );
7 |
8 | localparam ctr_width = 32;
9 | localparam ctr_lsb = 20;
10 |
11 | wire clk;
12 | assign clk = clk_25mhz;
13 |
14 | // __GEN_ECP5_PLL gen_pll_inst(.in_clk(clk_25mhz), .out_clk(pll_clk0), .locked(pll_locked));
15 |
16 |
17 | reg [ctr_width-1:0] ctr;
18 |
19 | wire [2:0] cx;
20 | wire [2:0] shift_val;
21 |
22 | assign cx = ctr[ctr_lsb + 2:ctr_lsb];
23 | assign shift_val = ctr[ctr_lsb + 3] ? (7 - cx) : cx;
24 |
25 | always @(posedge clk) begin
26 | ctr <= ctr + 1;
27 | led <= 1 << shift_val;
28 | end
29 |
30 | endmodule
31 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/detailed_place.tcl:
--------------------------------------------------------------------------------
1 |
2 | set_placement_padding -global \
3 | -left {{platform.cell_pad_in_sites_detail_placement}} \
4 | -right {{platform.cell_pad_in_sites_detail_placement}}
5 | detailed_placement
6 |
7 | if {[info exists ::env(ENABLE_DPO)] && $::env(ENABLE_DPO)} {
8 | if {[info exist ::env(DPO_MAX_DISPLACEMENT)]} {
9 | improve_placement -max_displacement $::env(DPO_MAX_DISPLACEMENT)
10 | } else {
11 | improve_placement
12 | }
13 | }
14 | optimize_mirroring
15 |
16 | utl::info FLW 12 "Placement violations [check_placement -verbose]."
17 |
18 | estimate_parasitics -placement
19 |
20 | report_metrics "detailed place" true false
21 |
22 | {{ write_checkpoint(step) }}
23 |
--------------------------------------------------------------------------------
/tests/resources/Flow_Summary.csv:
--------------------------------------------------------------------------------
1 | Flow Status,Successful - Tue Mar 1 11:10:35 2022
2 | Quartus Prime Version,21.1.0 Build 842 10/21/2021 SJ Lite Edition
3 | Revision Name,pipelined_adder
4 | Top-level Entity Name,full_adder_piped
5 | Family,Cyclone V
6 | Device,5CGXBC3B6F23C7
7 | Timing Models,Final
8 | Logic utilization (in ALMs),2 / 13,460 ( < 1 % )
9 | Total registers,2
10 | Total pins,7 / 222 ( 3 % )
11 | Total virtual pins,0
12 | Total block memory bits,0 / 1,382,400 ( 0 % )
13 | Total DSP Blocks,0 / 57 ( 0 % )
14 | Total HSSI RX PCSs,0 / 3 ( 0 % )
15 | Total HSSI PMA RX Deserializers,0 / 3 ( 0 % )
16 | Total HSSI TX PCSs,0 / 3 ( 0 % )
17 | Total HSSI PMA TX Serializers,0 / 3 ( 0 % )
18 | Total PLLs,0 / 7 ( 0 % )
19 | Total DLLs,0 / 3 ( 0 % )
20 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/openroad_scripts/deletePowerNets.tcl:
--------------------------------------------------------------------------------
1 | read_lef $::env(TECH_LEF)
2 | read_lef $::env(SC_LEF)
3 | if {[info exist ::env(ADDITIONAL_LEFS)]} {
4 | foreach lef $::env(ADDITIONAL_LEFS) {
5 | read_lef $lef
6 | }
7 | }
8 |
9 | # Read liberty files
10 | source $::env(SCRIPTS_DIR)/read_liberty.tcl
11 |
12 | # Read def and sdc
13 | read_def {{settings.results_dir}}/6_final.def
14 |
15 | proc deleteNetByName {name} {
16 | set db [ord::get_db]
17 | set chip [$db getChip]
18 | set block [$chip getBlock]
19 | set net [$block findNet $name]
20 | $net destroySWires
21 | puts "\[INFO\] Deleted net '[$net getName]'"
22 | }
23 |
24 | deleteNetByName VDD
25 | deleteNetByName VSS
26 |
27 | write_def {{settings.results_dir}}/6_final_no_power.def
28 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | # Documentation
2 | - [ ] Usage
3 | - [ ] Development
4 | - [ ] Adding new flows
5 | - [ ] Developer docs for adding new flows
6 |
7 | # Main code
8 |
9 | - [ ] FIX lingering child processes after being killed
10 | - [x] Idea: Some code in Suite should be refactored to a FlowRunner class, suites/flows? should provide a run method.
11 | - [x] parallel runs
12 | - [.] Flow chaining
13 | - [ ] move DSE code to a plugin
14 | - [ ] Installation / set-up of tools
15 | - [ ] Run in docker
16 |
17 | ## Flows
18 |
19 | - [.] Support multiple clocks in synthesis at least with DefaultRunner
20 | - [x] Modelsim
21 | - [.] ghdl + yosys + nextpnr-ecp5
22 | - [ ] Synopsys VCS
23 | - [.] Synopsys DC
24 | - [ ] Synopsys ICC2
25 | - [ ] OpenROAD/OpenLANE
26 | - [x] Quartus: Power estimation
27 |
--------------------------------------------------------------------------------
/src/xeda/flow/__init__.py:
--------------------------------------------------------------------------------
1 | from .flow import (
2 | Flow,
3 | FlowDependencyFailure,
4 | FlowException,
5 | FlowFatalError,
6 | FlowSettingsError,
7 | FlowSettingsException,
8 | registered_flows,
9 | )
10 |
11 | # from .decorators import define_flow, sim_flow, synth_flow
12 | from .fpga import FPGA
13 | from .sim import SimFlow
14 | from .synth import AsicSynthFlow, FpgaSynthFlow, PhysicalClock, SynthFlow
15 |
16 | __all__ = [
17 | "Flow",
18 | "FPGA",
19 | "SimFlow",
20 | "SynthFlow",
21 | "FpgaSynthFlow",
22 | "AsicSynthFlow",
23 | "PhysicalClock",
24 | "registered_flows",
25 | "FlowDependencyFailure",
26 | "FlowFatalError",
27 | "FlowSettingsException",
28 | "FlowSettingsError",
29 | "FlowException",
30 | ]
31 |
--------------------------------------------------------------------------------
/src/xeda/flows/yosys/templates/post_rtl.tcl:
--------------------------------------------------------------------------------
1 | {%- if settings.rtl_json %}
2 | yosys log -stdout "Writing JSON {{settings.rtl_json}}"
3 | yosys write_json {{settings.rtl_json}}
4 | {%- endif %}
5 | {%- if settings.rtl_verilog %}
6 | yosys log -stdout "Writing Verilog {{settings.rtl_verilog}}"
7 | yosys write_verilog {{settings.rtl_verilog}}
8 | {%- endif %}
9 | {%- if settings.rtl_vhdl %}
10 | yosys log -stdout " Writing VHDL {{settings.rtl_vhdl}}"
11 | yosys write_vhdl {{settings.rtl_vhdl}}
12 | {%- endif %}
13 | {%- if settings.rtl_graph %}
14 | yosys log -stdout "Writing RTL graph to {{settings.rtl_graph.with_suffix('dot')}}"
15 | yosys show -prefix {{settings.rtl_graph.with_suffix("")}} -format dot {{settings.rtl_graph_flags|join(" ")}}
16 | {%- endif %}
17 |
18 | {%- if settings.stop_after == "rtl" %}
19 | exit
20 | {%- endif %}
--------------------------------------------------------------------------------
/examples/vhdl/sqrt/sqrt.toml:
--------------------------------------------------------------------------------
1 | name = "sqrt"
2 | description = "Iterative computation of square-root of an integer"
3 | language.vhdl.standard = "2008"
4 |
5 | [rtl]
6 | sources = ["sqrt.vhdl"]
7 | top = "sqrt"
8 | clock_port = "clk"
9 | parameters = { G_IN_WIDTH = 32 }
10 | # parameters = { G_IN_WIDTH = 32, G_ITERATIVE = true, G_STR= "abcd", G_BITVECTOR="7'b0101001" }
11 |
12 | [tb]
13 | sources = ["tb_sqrt.py"]
14 | cocotb = true
15 | # top = "tb_sqrt" # FIXME
16 |
17 | [flows.yosys_fpga]
18 | fpga.part = "xc7a100tftg256-2L"
19 | clock.freq = "100MHz"
20 |
21 | [flows.vivado_synth]
22 | fpga.part = "xc7a100tftg256-2L"
23 | clock_period = 5.0
24 |
25 | [flows.vivado_alt_synth]
26 | fpga.part = "xc7a100tftg256-2L"
27 | synth.strategy = "ExtraTimingCongestion"
28 | impl.strategy = "ExtraTimingCongestion"
29 | clock_period = 5.0
30 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/openroad/post_mergeLib.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import sys
3 |
4 | print("[INFO-FLOW] Post Merge Lib")
5 | mergedFile = sys.argv[1]
6 | print("[INFO-FLOW] ", mergedFile)
7 | f = open(mergedFile, "r")
8 |
9 | lines = f.readlines()
10 | f.close()
11 | fo = open(mergedFile, "w")
12 | flag_pg = 0
13 | for line in lines:
14 | if len(line.split()) < 1:
15 | fo.write(line)
16 | continue
17 | if line.split()[0] == "pg_pin":
18 | flag_pg = 1
19 | fo.write(line)
20 | # fo.write(' direction : input;\n')
21 | continue
22 | if flag_pg == 1 and line.split()[0] == "}":
23 | flag_pg = 0
24 | fo.write(line)
25 | continue
26 | if flag_pg == 1 and line.split()[0] == "direction":
27 | continue
28 | fo.write(line)
29 | fo.close()
30 |
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/make_tracks.tcl:
--------------------------------------------------------------------------------
1 | make_tracks metal1 -x_offset 0.095 -x_pitch 0.19 -y_offset 0.07 -y_pitch 0.14
2 | make_tracks metal2 -x_offset 0.095 -x_pitch 0.19 -y_offset 0.07 -y_pitch 0.14
3 | make_tracks metal3 -x_offset 0.095 -x_pitch 0.19 -y_offset 0.07 -y_pitch 0.14
4 | make_tracks metal4 -x_offset 0.095 -x_pitch 0.28 -y_offset 0.07 -y_pitch 0.28
5 | make_tracks metal5 -x_offset 0.095 -x_pitch 0.28 -y_offset 0.07 -y_pitch 0.28
6 | make_tracks metal6 -x_offset 0.095 -x_pitch 0.28 -y_offset 0.07 -y_pitch 0.28
7 | make_tracks metal7 -x_offset 0.095 -x_pitch 0.8 -y_offset 0.07 -y_pitch 0.8
8 | make_tracks metal8 -x_offset 0.095 -x_pitch 0.8 -y_offset 0.07 -y_pitch 0.8
9 | make_tracks metal9 -x_offset 0.095 -x_pitch 1.6 -y_offset 0.07 -y_pitch 1.6
10 | make_tracks metal10 -x_offset 0.095 -x_pitch 1.6 -y_offset 0.07 -y_pitch 1.6
11 |
--------------------------------------------------------------------------------
/examples/boards/ulx3s/blinky/xedaproject.toml:
--------------------------------------------------------------------------------
1 | [[design]]
2 | name = 'blinky'
3 | description = 'Running LEDs on the ULX3S board'
4 |
5 | [design.rtl]
6 | sources = ['blinky.v']
7 | top = 'blinky'
8 | clock_port = 'clk_25mhz'
9 |
10 | [[design]]
11 | name = 'blinky-vhdl'
12 | description = 'LED chaser on ULX3S'
13 | language.vhdl.standard = 2008
14 |
15 | [design.rtl]
16 | sources = [ #
17 | "ecp5pll.vhdl",
18 | 'blinky.vhdl',
19 | ]
20 | top = 'blinky'
21 | clock_port = 'clk_25mhz'
22 |
23 |
24 | [flows.openfpgaloader]
25 | board = 'ULX3S_85F'
26 | clock_period = 40 # 25 MHz
27 | nextpnr.detailed_timing_report = false
28 | nextpnr.timing_allow_fail = true
29 |
30 | [flows.nextpnr]
31 | board = 'ULX3S_85F'
32 | clock_period = 40 # 25 MHz
33 |
34 | [flows.yosys_fpga]
35 | fpga.family = 'ecp5'
36 | clock_period = 40 #
37 |
--------------------------------------------------------------------------------
/tests/test_cli.py:
--------------------------------------------------------------------------------
1 | from click.testing import CliRunner
2 |
3 | from xeda.cli import cli
4 |
5 | flows = ["ghdl_sim", "yosys", "nextpnr", "vivado_sim", "vivado_synth"]
6 |
7 |
8 | def test_cli_run_help():
9 | runner = CliRunner()
10 | result = runner.invoke(cli, ["run", "--help"])
11 | assert result.exit_code == 0
12 | assert "Usage: " in result.output
13 |
14 |
15 | def test_cli_list_flows():
16 | runner = CliRunner()
17 | result = runner.invoke(cli, ["list-flows"])
18 | assert result.exit_code == 0
19 | for flow in flows:
20 | assert flow in result.output
21 |
22 |
23 | def test_cli_list_settings():
24 | runner = CliRunner()
25 | for flow_name in flows:
26 | result = runner.invoke(cli, ["list-settings", flow_name])
27 | assert result.exit_code == 0, f"Failed: CLI list-settings {flow_name}"
28 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 |
5 | ## [Unreleased]
6 |
7 | ### Fixed
8 | - Command line interface:
9 | - `list-settings`: improved display of types and default values
10 | ### Changed
11 | - WIP: Handling settings of dependency flow during `Settings` validation.
12 | ### Removed
13 |
14 | ### Added
15 | - Tool: ecppll (nextpnr's Lattice ECP5 PLL tool)
16 | - Examples: ULX3S adopted DVI test from EMARD
17 | - change LED chaser speed with buttons `5` and `6`!
18 | - Examples: improved version of `blinky` for the ULX3S board in VHDL
19 | - change LED chaser speed with buttons `5` and `6`!
20 |
21 | ## [v0.1.0-alpha.11] - 2022-04-16
22 |
23 |
24 | [Unreleased]: https://github.com/XedaHQ/xeda/compare/v0.1.0-alpha.1...HEAD
25 | [v0.1.0-alpha.11]: https://github.com/XedaHQ/xeda/releases/tag/v0.1.0-alpha.11
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hd/setRC.tcl:
--------------------------------------------------------------------------------
1 | # correlateRC.py gcd,ibex,aes,jpeg,chameleon,riscv32i,chameleon_hier
2 | # cap units pf/um
3 | set_layer_rc -layer li1 -capacitance 1.499e-04 -resistance 7.176e-02
4 | set_layer_rc -layer met1 -capacitance 1.72375E-04 -resistance 8.929e-04
5 | set_layer_rc -layer met2 -capacitance 1.36233E-04 -resistance 8.929e-04
6 | set_layer_rc -layer met3 -capacitance 2.14962E-04 -resistance 1.567e-04
7 | set_layer_rc -layer met4 -capacitance 1.48128E-04 -resistance 1.567e-04
8 | set_layer_rc -layer met5 -capacitance 1.54087E-04 -resistance 1.781e-05
9 | # end correlate
10 |
11 | set_layer_rc -via mcon -resistance 9.249146E-3
12 | set_layer_rc -via via -resistance 4.5E-3
13 | set_layer_rc -via via2 -resistance 3.368786E-3
14 | set_layer_rc -via via3 -resistance 0.376635E-3
15 | set_layer_rc -via via4 -resistance 0.00580E-3
16 |
17 | set_wire_rc -signal -layer met2
18 | set_wire_rc -clock -layer met5
19 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hs/setRC.tcl:
--------------------------------------------------------------------------------
1 | # correlateRC.py gcd,ibex,aes,jpeg,chameleon,riscv32i,chameleon_hier
2 | # cap units pf/um
3 | set_layer_rc -layer li1 -capacitance 1.499e-04 -resistance 7.176e-02
4 | set_layer_rc -layer met1 -capacitance 1.72375E-04 -resistance 8.929e-04
5 | set_layer_rc -layer met2 -capacitance 1.36233E-04 -resistance 8.929e-04
6 | set_layer_rc -layer met3 -capacitance 2.14962E-04 -resistance 1.567e-04
7 | set_layer_rc -layer met4 -capacitance 1.48128E-04 -resistance 1.567e-04
8 | set_layer_rc -layer met5 -capacitance 1.54087E-04 -resistance 1.781e-05
9 | # end correlate
10 |
11 | set_layer_rc -via mcon -resistance 9.249146E-3
12 | set_layer_rc -via via -resistance 4.5E-3
13 | set_layer_rc -via via2 -resistance 3.368786E-3
14 | set_layer_rc -via via3 -resistance 0.376635E-3
15 | set_layer_rc -via via4 -resistance 0.00580E-3
16 |
17 | set_wire_rc -signal -layer met2
18 | set_wire_rc -clock -layer met5
19 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/load.tcl:
--------------------------------------------------------------------------------
1 | #===========================(Read liberty libs)===============================#
2 | read_libraries
3 | #=============================(Read LEF files)================================#
4 | read_lef {{platform.tech_lef}}
5 | {% if platform.std_cell_lef %}
6 | read_lef {{platform.std_cell_lef}}
7 | {% endif %}
8 |
9 | {% for lef in platform.additional_lef_files %}
10 | read_lef {{lef}}
11 | {% endfor %}
12 |
13 | read_verilog {{netlist}}
14 | link_design {{design.rtl.top}}
15 |
16 | {% for sdc in settings.sdc_files %}
17 | read_sdc {{sdc}}
18 | {% endfor %}
19 |
20 | {% if platform.derate_tcl %}
21 | source {{platform.derate_tcl}}
22 | {% endif %}
23 | {% if platform.setrc_tcl %}
24 | source {{platform.setrc_tcl}}
25 | {% endif %}
26 |
27 | puts "Default units for flow"
28 | report_units
29 | report_units_metric
30 |
31 | puts "number instances in verilog is [llength [get_cells -hier *]]"
32 |
33 | {{ write_checkpoint(step) }}
34 |
--------------------------------------------------------------------------------
/src/xeda/flows/vivado/templates/clock.xdc:
--------------------------------------------------------------------------------
1 | {% for clock_name, clock in settings.clocks.items() -%}
2 | {% if clock.port -%}
3 | create_clock -period {{"%.03f" % clock.period}} -name {{clock_name}} [get_ports {{clock.port}}]
4 | {% if settings.default_max_input_delay is not none -%} set_input_delay -max -clock {{clock_name}} {{settings.default_max_input_delay}} [filter [all_inputs] {NAME != {{clock.port}} }] {%- endif %}
5 | {% if settings.default_min_input_delay is not none -%} set_input_delay -min -clock {{clock_name}} {{settings.default_min_input_delay}} [filter [all_inputs] {NAME != {{clock.port}} }] {%- endif %}
6 | {% if settings.default_max_output_delay is not none -%} set_output_delay -max -clock {{clock_name}} {{settings.default_max_output_delay}} [all_outputs] {%- endif %}
7 | {% if settings.default_min_output_delay is not none -%} set_output_delay -min -clock {{clock_name}} {{settings.default_min_output_delay}} [all_outputs] {%- endif %}
8 | {% endif -%}
9 | {% endfor -%}
10 |
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/setRC.tcl:
--------------------------------------------------------------------------------
1 | # Liberty units are fF,kOhm
2 | set_layer_rc -layer metal1 -resistance 5.4286e-03 -capacitance 7.41819E-02
3 | set_layer_rc -layer metal2 -resistance 3.5714e-03 -capacitance 6.74606E-02
4 | set_layer_rc -layer metal3 -resistance 3.5714e-03 -capacitance 8.88758E-02
5 | set_layer_rc -layer metal4 -resistance 1.5000e-03 -capacitance 1.07121E-01
6 | set_layer_rc -layer metal5 -resistance 1.5000e-03 -capacitance 1.08964E-01
7 | set_layer_rc -layer metal6 -resistance 1.5000e-03 -capacitance 1.02044E-01
8 | set_layer_rc -layer metal7 -resistance 1.8750e-04 -capacitance 1.10436E-01
9 | set_layer_rc -layer metal8 -resistance 1.8750e-04 -capacitance 9.69714E-02
10 | # No calibration data available for metal9 and metal10
11 | #set_layer_rc -layer metal9 -resistance 3.7500e-05 -capacitance 3.6864e-02
12 | #set_layer_rc -layer metal10 -resistance 3.7500e-05 -capacitance 2.8042e-02
13 |
14 | set_wire_rc -signal -layer metal3
15 | set_wire_rc -clock -layer metal5
16 |
--------------------------------------------------------------------------------
/.github/workflows/dependency-review.yml:
--------------------------------------------------------------------------------
1 | # Dependency Review Action
2 | #
3 | # This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
4 | #
5 | # Source repository: https://github.com/actions/dependency-review-action
6 | # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
7 | name: 'Dependency Review'
8 | on: [pull_request]
9 |
10 | permissions:
11 | contents: read
12 |
13 | jobs:
14 | dependency-review:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - name: 'Checkout Repository'
18 | uses: actions/checkout@v3
19 | - name: 'Dependency Review'
20 | uses: actions/dependency-review-action@v2
21 |
--------------------------------------------------------------------------------
/examples/vhdl/full_adder_piped.vhd:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 |
4 | entity full_adder_piped is
5 | port(
6 | clk : in std_logic;
7 | reset : in std_logic;
8 | in_a : in std_logic;
9 | in_b : in std_logic;
10 | in_ci : in std_logic;
11 | s : out std_logic;
12 | co : out std_logic
13 | );
14 | end;
15 |
16 | architecture behavioral of full_adder_piped is
17 | signal a, b, ci : std_logic;
18 | begin
19 | process(clk)
20 | begin
21 | if rising_edge(clk) then
22 | if reset = '1' then
23 | s <= '0'; -- not really needed
24 | co <= '0'; -- not really needed
25 | else
26 | a <= in_a;
27 | b <= in_b;
28 | ci <= in_ci;
29 | s <= a xor b xor ci;
30 | co <= (a and b) or (b and ci) or (ci and a);
31 | end if; -- reset
32 | end if; -- clk rising_edge
33 | end process;
34 | end;
35 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/openroad_scripts/deleteNonClkNets.tcl:
--------------------------------------------------------------------------------
1 | read_lef $::env(TECH_LEF)
2 | read_lef $::env(SC_LEF)
3 | if {[info exist ::env(ADDITIONAL_LEFS)]} {
4 | foreach lef $::env(ADDITIONAL_LEFS) {
5 | read_lef $lef
6 | }
7 | }
8 |
9 | # Read liberty files
10 | source $::env(SCRIPTS_DIR)/read_liberty.tcl
11 |
12 | # Read def and sdc
13 | read_def {{settings.results_dir}}/6_final.def
14 |
15 | set block [[[ord::get_db] getChip] getBlock]
16 | set nets [$block getNets]
17 | set insts [$block getInsts]
18 |
19 | # Delete all non-clock nets
20 | foreach net $nets {
21 | set sigType [$net getSigType]
22 | set wire [$net getWire]
23 | if {"$sigType" eq "SIGNAL" && "$wire" ne "NULL"} {
24 | odb::dbWire_destroy $wire
25 | } elseif {"$sigType" eq "POWER" ||
26 | "$sigType" eq "GROUND"} {
27 | $net destroySWires
28 | }
29 | }
30 |
31 | # Delete fill cells to clean up screenshot
32 | foreach inst $insts {
33 | if {"[[$inst getMaster] getType]" eq "CORE_SPACER"} {
34 | odb::dbInst_destroy $inst
35 | }
36 | }
37 |
38 | write_def {{settings.results_dir}}/6_final_only_clk.def
39 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/setRC.tcl:
--------------------------------------------------------------------------------
1 | # Liberty units are fF,kOhm
2 | set_layer_rc -layer M1 -capacitance 1.1368e-01 -resistance 1.3889e-01
3 | set_layer_rc -layer M2 -capacitance 1.3426e-01 -resistance 2.4222e-02
4 | set_layer_rc -layer M3 -capacitance 1.2918e-01 -resistance 2.4222e-02
5 | set_layer_rc -layer M4 -capacitance 1.1396e-01 -resistance 1.6778e-02
6 | set_layer_rc -layer M5 -capacitance 1.3323e-01 -resistance 1.4677e-02
7 | set_layer_rc -layer M6 -capacitance 1.1575e-01 -resistance 1.0371e-02
8 | set_layer_rc -layer M7 -capacitance 1.3293e-01 -resistance 9.6720e-03
9 | set_layer_rc -layer M8 -capacitance 1.1822e-01 -resistance 7.4310e-03
10 | set_layer_rc -layer M9 -capacitance 1.3497e-01 -resistance 6.8740e-03
11 |
12 | set_layer_rc -via V1 -resistance 1.72E-02
13 | set_layer_rc -via V2 -resistance 1.72E-02
14 | set_layer_rc -via V3 -resistance 1.72E-02
15 | set_layer_rc -via V4 -resistance 1.18E-02
16 | set_layer_rc -via V5 -resistance 1.18E-02
17 | set_layer_rc -via V6 -resistance 8.20E-03
18 | set_layer_rc -via V7 -resistance 8.20E-03
19 | set_layer_rc -via V8 -resistance 6.30E-03
20 |
21 | set_wire_rc -layer M3
22 |
--------------------------------------------------------------------------------
/.github/workflows/python-publish.yml:
--------------------------------------------------------------------------------
1 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
2 |
3 | name: Upload 📦 to PyPI
4 | on:
5 | pull_request:
6 | branches:
7 | - 'main'
8 | - 'releases/**'
9 | push:
10 | branches:
11 | - 'main'
12 | - 'releases/**'
13 | release:
14 | types: [published]
15 | jobs:
16 | deploy:
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: actions/checkout@v3
20 | - name: Set up 🐍
21 | uses: actions/setup-python@v3
22 | with:
23 | python-version: '3.x'
24 | - name: Install dependencies
25 | run: |
26 | python -m pip install --upgrade pip
27 | pip install build
28 | - name: Build package
29 | run: python -m build
30 | - name: Publish 📦 to PyPI
31 | if: github.event.pull_request.merged == true || startsWith(github.ref, 'refs/tags')
32 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
33 | with:
34 | user: __token__
35 | password: ${{ secrets.PYPI_API_TOKEN }}
36 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v4.4.0
4 | hooks:
5 | - id: check-ast
6 | - id: check-yaml
7 | - id: check-toml
8 | # - id: end-of-file-fixer
9 | # - id: check-added-large-files
10 | - id: check-case-conflict
11 | - id: check-merge-conflict
12 | - id: check-symlinks
13 | - id: destroyed-symlinks
14 | # - id: trailing-whitespace
15 | - id: check-vcs-permalinks
16 | - id: mixed-line-ending
17 | - id: detect-private-key
18 | - repo: https://github.com/psf/black
19 | rev: 22.12.0
20 | hooks:
21 | - id: black
22 | - repo: https://github.com/pre-commit/mirrors-mypy
23 | rev: v1.4.1
24 | hooks:
25 | - id: mypy
26 | args: [--install-types, --non-interactive, --ignore-missing-imports]
27 | additional_dependencies:
28 | - "pydantic>=1.10.4,<2.0"
29 | # - repo: local
30 | # hooks:
31 | # - id: pytest-check
32 | # name: pytest-check
33 | # entry: pytest
34 | # language: system
35 | # pass_filenames: false
36 | # always_run: false
37 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | push:
4 | branches: ["main", "dev"]
5 | pull_request:
6 | branches: ["main", "dev"]
7 | workflow_dispatch:
8 |
9 | jobs:
10 | tox:
11 | strategy:
12 | fail-fast: false
13 | matrix:
14 | python-version: ["3.10", "3.11", "3.12", "3.13"]
15 |
16 | runs-on: ubuntu-latest
17 |
18 | steps:
19 | - uses: ghdl/setup-ghdl@v1
20 | with:
21 | backend: llvm
22 | - uses: YosysHQ/setup-oss-cad-suite@v3
23 | - uses: nickg/setup-nvc@v1
24 | with:
25 | version: latest
26 | - uses: actions/checkout@v4
27 | with:
28 | submodules: true
29 | fetch-depth: 0
30 | - name: Set up Python ${{ matrix.python-version }}
31 | uses: actions/setup-python@v5
32 | with:
33 | python-version: "${{ matrix.python-version }}"
34 | - name: Install dependencies
35 | run: |
36 | python -VV
37 | python -m pip install --upgrade pip
38 | python -m pip install --upgrade tox tox-gh-actions
39 | - name: "Run tox targets for ${{ matrix.python-version }}"
40 | run: "python -m tox"
41 |
--------------------------------------------------------------------------------
/src/xeda/flows/dc/templates/constraints.sdc:
--------------------------------------------------------------------------------
1 | {% for clock_name, clock in settings.clocks.items() -%}
2 | {% if clock.port -%}
3 | create_clock -period {{"%.03f" % clock.period}} -name {{clock_name}} [get_ports {{clock.port}}]
4 |
5 | {% if settings.default_max_input_delay is not none -%}
6 | set max_input_delay {{settings.default_max_input_delay}}
7 | set input_ports [all_inputs -exclude_clock_ports]
8 | foreach_in_collection port $input_ports {
9 | set port_name [get_object_name $port]
10 | puts "Settings MAX input delay of port $port_name to $max_input_delay"
11 | set_input_delay -clock {{clock_name}} -max $max_input_delay $input_ports
12 | }
13 | {% endif -%}
14 |
15 | {% if settings.default_max_output_delay is not none -%}
16 | # Ensuring valid output can be captured on the clock edge
17 | set max_output_delay {{settings.default_max_output_delay}}
18 | set output_ports [all_outputs]
19 | foreach_in_collection port $output_ports {
20 | puts "Settings MAX output delay of port $port_name to $max_output_delay"
21 | set_output_delay -clock {{clock_name}} -max $max_output_delay $output_ports
22 | }
23 | {% endif -%}
24 | # set_dont_touch_network [find port {{clock.port}}]
25 | {% endif -%}
26 | {% endfor -%}
27 |
--------------------------------------------------------------------------------
/tests/test_verilator.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import tempfile
3 | from pathlib import Path
4 |
5 | from xeda.flow_runner import DefaultRunner
6 | from xeda.flows import Verilator
7 |
8 | TESTS_DIR = Path(__file__).parent.absolute()
9 | EXAMPLES_DIR = TESTS_DIR.parent / "examples"
10 |
11 | debug = False
12 |
13 |
14 | def test_yosys_synth_py() -> None:
15 | design_paths = [
16 | EXAMPLES_DIR / "sv" / "fifo" / "fifo.xeda.yaml",
17 | EXAMPLES_DIR / "sv" / "fifo" / "fifo_cocotb.xeda.yaml",
18 | ]
19 | with tempfile.TemporaryDirectory(dir=Path.cwd()) as run_dir:
20 | print("Xeda run dir: ", run_dir)
21 | for design in design_paths:
22 | xeda_runner = DefaultRunner(run_dir, debug=debug)
23 | flow = xeda_runner.run(Verilator, design, flow_overrides=dict(debug=debug, verbose=debug))
24 | assert flow is not None, "run_flow returned None"
25 | settings_json = flow.run_path / "settings.json"
26 | results_json = flow.run_path / "results.json"
27 | assert settings_json.exists()
28 | assert flow.succeeded
29 | assert isinstance(flow.settings, Verilator.Settings)
30 | assert results_json.exists()
31 |
32 |
33 | if __name__ == "__main__":
34 | test_yosys_synth_py()
35 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/openroad/make_tracks.tcl:
--------------------------------------------------------------------------------
1 | make_tracks Pad -x_offset 0.116 -x_pitch 0.080 -y_offset 0.116 -y_pitch 0.080
2 | make_tracks M9 -x_offset 0.116 -x_pitch 0.080 -y_offset 0.116 -y_pitch 0.080
3 | make_tracks M8 -x_offset 0.116 -x_pitch 0.080 -y_offset 0.116 -y_pitch 0.080
4 | make_tracks M7 -x_offset 0.016 -x_pitch 0.064 -y_offset 0.016 -y_pitch 0.064
5 | make_tracks M6 -x_offset 0.012 -x_pitch 0.048 -y_offset 0.016 -y_pitch 0.064
6 | make_tracks M5 -x_offset 0.012 -x_pitch 0.048 -y_offset 0.012 -y_pitch 0.048
7 | make_tracks M4 -x_offset 0.009 -x_pitch 0.036 -y_offset 0.012 -y_pitch 0.048
8 | make_tracks M3 -x_offset 0.009 -x_pitch 0.036 -y_offset 0.009 -y_pitch 0.036
9 |
10 | make_tracks M2 -x_offset 0.009 -x_pitch 0.036 -y_offset 0.045 -y_pitch 0.270
11 | make_tracks M2 -x_offset 0.009 -x_pitch 0.036 -y_offset 0.081 -y_pitch 0.270
12 | make_tracks M2 -x_offset 0.009 -x_pitch 0.036 -y_offset 0.117 -y_pitch 0.270
13 | make_tracks M2 -x_offset 0.009 -x_pitch 0.036 -y_offset 0.153 -y_pitch 0.270
14 | make_tracks M2 -x_offset 0.009 -x_pitch 0.036 -y_offset 0.189 -y_pitch 0.270
15 | make_tracks M2 -x_offset 0.009 -x_pitch 0.036 -y_offset 0.225 -y_pitch 0.270
16 | make_tracks M2 -x_offset 0.009 -x_pitch 0.036 -y_offset 0.270 -y_pitch 0.270
17 |
18 | make_tracks M1 -x_offset 0.009 -x_pitch 0.036 -y_offset 0.009 -y_pitch 0.036
19 |
--------------------------------------------------------------------------------
/tests/test_nvc.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import tempfile
3 | from pathlib import Path
4 |
5 | from xeda.flow_runner import DefaultRunner
6 | from xeda.flows import Nvc
7 |
8 | TESTS_DIR = Path(__file__).parent.absolute()
9 | EXAMPLES_DIR = TESTS_DIR.parent / "examples"
10 |
11 | debug = False
12 |
13 |
14 | def test_yosys_synth_py() -> None:
15 | design_paths = [
16 | EXAMPLES_DIR / "vhdl" / "sqrt" / "sqrt.toml",
17 | EXAMPLES_DIR / "vhdl" / "Trivium" / "trivium.xeda.yaml",
18 | EXAMPLES_DIR / "vhdl" / "pipeline" / "pipelined_adder.toml",
19 | ]
20 | with tempfile.TemporaryDirectory(dir=Path.cwd()) as run_dir:
21 | print("Xeda run dir: ", run_dir)
22 | for design in design_paths:
23 | xeda_runner = DefaultRunner(run_dir, debug=debug)
24 | flow = xeda_runner.run(Nvc, design, flow_overrides=dict(debug=debug, verbose=debug))
25 | assert flow is not None, "run_flow returned None"
26 | settings_json = flow.run_path / "settings.json"
27 | results_json = flow.run_path / "results.json"
28 | assert settings_json.exists()
29 | assert flow.succeeded
30 | assert isinstance(flow.settings, Nvc.Settings)
31 | assert results_json.exists()
32 |
33 |
34 | if __name__ == "__main__":
35 | test_yosys_synth_py()
36 |
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/fakeram.tcl:
--------------------------------------------------------------------------------
1 |
2 | set design_rams {
3 | swerv {2048x39 256x34 64x21}
4 | bp_be_top {64x96 512x64 64x15}
5 | tinyRocket {64x32 1024x32}
6 | black_parrot {64x7 64x96 512x64 256x95 64x15}
7 | bp_multi_top {64x7 32x64 64x96 512x64 256x96 64x15}
8 | bp_fe_top {64x7 64x96 512x64}
9 | }
10 |
11 | set results_dir "~/import/fakeram/results"
12 | set flow_dir "~/import/flow/flow/platforms/nangate45"
13 |
14 | proc make_fakeram_links {} {
15 | global design_rams flow_dir
16 |
17 | foreach {design sizes} $design_rams {
18 | cd $flow_dir/$design
19 | foreach size $sizes {
20 | file delete fakeram45_$size.lib
21 | file delete fakeram45_$size.lef
22 | file link -symbolic fakeram45_$size.lib \
23 | ../../../platforms/nangate45/lib/fakeram45_$size.lib
24 | file link -symbolic fakeram45_$size.lef \
25 | ../../../platforms/nangate45/lef/fakeram45_$size.lef
26 | }
27 | }
28 | }
29 |
30 | proc copy_fakeram_results {} {
31 | global design_rams results_dir flow_dir
32 |
33 | foreach {design sizes} $design_rams {
34 | foreach size $sizes {
35 | file copy -force $results_dir/fakeram45_$size/fakeram45_$size.lib $flow_dir/lib/fakeram45_$size.lib
36 | file copy -force $results_dir/fakeram45_$size/fakeram45_$size.lef $flow_dir/lef/fakeram45_$size.lef
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/examples/sv/fifo/fifo.sv:
--------------------------------------------------------------------------------
1 | `default_nettype none
2 |
3 | module fifo #(
4 | parameter DATA_WIDTH = 8,
5 | parameter LOG2_DEPTH = 4
6 | ) (
7 | input logic clk,
8 | input logic reset,
9 | input logic enq_valid,
10 | input logic [DATA_WIDTH-1:0] enq_data,
11 | output logic enq_ready,
12 | input logic deq_ready,
13 | output logic [DATA_WIDTH-1:0] deq_data,
14 | output logic deq_valid
15 | );
16 | logic [DATA_WIDTH-1:0] mem[2**LOG2_DEPTH];
17 | logic [LOG2_DEPTH-1:0] write_ptr, read_ptr;
18 | logic maybe_full, overlap, do_write, do_read;
19 |
20 | assign overlap = write_ptr == read_ptr;
21 | assign do_write = enq_valid && enq_ready;
22 | assign do_read = deq_valid && deq_ready;
23 |
24 | assign enq_ready = !(overlap && maybe_full);
25 | assign deq_valid = maybe_full || !overlap;
26 | assign deq_data = mem[read_ptr];
27 |
28 |
29 | always_ff @(posedge clk) begin
30 | if (reset) begin
31 | write_ptr <= '0;
32 | read_ptr <= '0;
33 | maybe_full <= 1'b0;
34 | end else begin
35 | if (do_write) begin
36 | mem[write_ptr] <= enq_data;
37 | write_ptr <= write_ptr + 1;
38 | maybe_full <= 1'b1;
39 | end
40 | if (do_read) begin
41 | read_ptr <= read_ptr + 1;
42 | maybe_full <= 1'b0;
43 | end
44 | end
45 | end
46 |
47 | endmodule
48 |
--------------------------------------------------------------------------------
/tests/test_cocotb.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from typing import Any, Dict
3 |
4 | from xeda import Cocotb
5 | from xeda.utils import WorkingDirectory
6 |
7 | TESTS_DIR = Path(__file__).parent.absolute()
8 | RESOURCES_DIR = TESTS_DIR / "resources"
9 |
10 |
11 | def test_cocotb_version():
12 | cocotb = Cocotb(sim_name="ghdl") # type: ignore
13 |
14 | assert cocotb.version_gte(0)
15 | assert cocotb.version_gte(0, 0)
16 | assert cocotb.version_gte(0, 1)
17 | assert cocotb.version_gte(0, 1, 1)
18 | assert cocotb.version_gte(0, 1, 1, 1)
19 | assert cocotb.version_gte(1)
20 | assert cocotb.version_gte(1, 5)
21 | assert cocotb.version_gte(1, 6)
22 |
23 |
24 | def test_cocotb_parse_xml():
25 | assert (RESOURCES_DIR / "cocotb" / "results.xml").exists()
26 | with WorkingDirectory(RESOURCES_DIR / "cocotb"):
27 | cocotb = Cocotb(sim_name="dummy") # type: ignore
28 | if cocotb.results is not None:
29 | for suite in cocotb.results.test_suites:
30 | for case in suite.test_cases:
31 | print(case)
32 | results: Dict[str, Any] = {"success": True}
33 | cocotb.add_results(results)
34 | print("Results:", results)
35 | assert results["success"] is False
36 |
37 |
38 | if __name__ == "__main__":
39 | test_cocotb_version()
40 | test_cocotb_parse_xml()
41 |
--------------------------------------------------------------------------------
/tests/test_ghdl.py:
--------------------------------------------------------------------------------
1 | import tempfile
2 | from pathlib import Path
3 |
4 | from xeda.flow_runner import DefaultRunner
5 | from xeda.flows import GhdlSim
6 |
7 | TESTS_DIR = Path(__file__).parent.absolute()
8 | EXAMPLES_DIR = TESTS_DIR.parent / "examples"
9 |
10 | debug = False
11 |
12 |
13 | def test_yosys_synth_py() -> None:
14 | # settings = dict(fpga=FPGA("xc7a12tcsg325-1"), clock_period=5.5)
15 | # run_dir = "tests_run_dir"
16 | design_paths = [
17 | EXAMPLES_DIR / "vhdl" / "sqrt" / "sqrt.toml",
18 | EXAMPLES_DIR / "vhdl" / "Trivium" / "trivium.xeda.yaml",
19 | EXAMPLES_DIR / "vhdl" / "pipeline" / "pipelined_adder.toml",
20 | ]
21 | with tempfile.TemporaryDirectory(dir=Path.cwd()) as run_dir:
22 | print("Xeda run dir: ", run_dir)
23 | for design in design_paths:
24 | xeda_runner = DefaultRunner(run_dir, debug=debug)
25 | flow = xeda_runner.run(GhdlSim, design, flow_overrides=dict(debug=debug, verbose=debug))
26 | assert flow is not None, "run_flow returned None"
27 | settings_json = flow.run_path / "settings.json"
28 | results_json = flow.run_path / "results.json"
29 | assert settings_json.exists()
30 | assert flow.succeeded
31 | assert isinstance(flow.settings, GhdlSim.Settings)
32 | assert results_json.exists()
33 |
34 |
35 | if __name__ == "__main__":
36 | test_yosys_synth_py()
37 |
--------------------------------------------------------------------------------
/tests/test_ise.py:
--------------------------------------------------------------------------------
1 | import os
2 | import tempfile
3 | from pathlib import Path
4 |
5 | from xeda import Design
6 | from xeda.flow import FPGA
7 | from xeda.flow_runner import DefaultRunner
8 | from xeda.flows import IseSynth
9 |
10 | TESTS_DIR = Path(__file__).parent.absolute()
11 | RESOURCES_DIR = TESTS_DIR / "resources"
12 | EXAMPLES_DIR = TESTS_DIR.parent / "examples"
13 |
14 | os.environ["PATH"] += os.pathsep + os.path.join(TESTS_DIR, "fake_tools")
15 |
16 |
17 | def test_ise_synth_py() -> None:
18 | path = RESOURCES_DIR / "design0/design0.toml"
19 | # Append to PATH so if the actual tool exists, would take precedences.
20 | assert path.exists()
21 | design = Design.from_toml(EXAMPLES_DIR / "vhdl" / "sqrt" / "sqrt.toml")
22 | settings = dict(fpga=FPGA("xc7a12tcsg325-1"), clock_period=5.5)
23 | with tempfile.TemporaryDirectory() as run_dir:
24 | print("Xeda run dir: ", run_dir)
25 | xeda_runner = DefaultRunner(run_dir, debug=True)
26 | flow = xeda_runner.run_flow(IseSynth, design, settings)
27 | assert flow is not None, "run_flow returned None"
28 | assert flow.run_path is not None, "run_flow returned None"
29 | settings_json = flow.run_path / "settings.json"
30 | results_json = flow.run_path / "results.json"
31 | assert settings_json.exists()
32 | assert results_json.exists()
33 | # assert flow.succeeded
34 |
35 |
36 | if __name__ == "__main__":
37 | test_ise_synth_py()
38 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/clocks.sdc:
--------------------------------------------------------------------------------
1 | {% set all_clock_ports = settings.clocks.values()|map(attribute="port") %}
2 |
3 | set all_input_ports [all_inputs]
4 | set all_output_ports [all_outputs]
5 | set all_clock_ports [list {{all_clock_ports|join(" ")}}]
6 |
7 | {% for clock_name, clock in settings.clocks.items() %}
8 | {% if clock.port %}
9 | {% set clock_period = clock.period_unit(settings.platform.time_unit) %}
10 | set clk_port [get_ports {{clock.port}}]
11 | create_clock -period {{ "%.3f"|format(clock_period) }} -name {{clock_name}} $clk_port
12 |
13 | ## NOTE: includes other clock ports if multiple clocks are present
14 | set non_clock_inputs [lsearch -inline -all -not -exact $all_input_ports $clk_port]
15 |
16 | {% if settings.input_delay is not none %}
17 | set_input_delay {{"%.3f"|format(settings.input_delay)}} -clock {{clock_name}} $non_clock_inputs
18 | {% elif settings.input_delay_frac is not none %}
19 | set_input_delay [expr {{"%.3f"|format(settings.input_delay_frac)}} * {{"%.3f"|format(clock_period)}}] -clock {{clock_name}} $non_clock_inputs
20 | {% endif %}
21 | {% if settings.output_delay is not none %}
22 | set_output_delay {{"%.3f"|format(settings.output_delay)}} -clock {{clock_name}} $all_output_ports
23 | {% elif settings.output_delay_frac is not none %}
24 | set_output_delay [expr {{"%.3f"|format(settings.output_delay_frac)}} * {{"%.3f"|format(clock_period)}}] -clock {{clock_name}} $all_output_ports
25 | {% endif %}
26 |
27 | {% endif %}
28 | {% endfor %}
29 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/cts.tcl:
--------------------------------------------------------------------------------
1 | # Clone clock tree inverters next to register loads
2 | # so cts does not try to buffer the inverted clocks.
3 | repair_clock_inverters
4 |
5 | # Run CTS
6 | clock_tree_synthesis -root_buf "{{platform.cts_buf_cell}}" -buf_list "{{platform.cts_buf_cell}}" \
7 | -sink_clustering_enable \
8 | -sink_clustering_size {{settings.cts_cluster_size}} \
9 | -sink_clustering_max_diameter {{settings.cts_cluster_diameter}} {% if settings.cts_buf_distance %} -distance_between_buffers {{settings.cts_buf_distance}} {% endif %} \
10 | -balance_levels
11 |
12 | set_propagated_clock [all_clocks]
13 | set_dont_use {{settings.dont_use_cells|join(" ")|embrace}}
14 |
15 | estimate_parasitics -placement
16 | report_metrics "cts pre-repair"
17 |
18 | repair_clock_nets
19 | estimate_parasitics -placement
20 | report_metrics "cts post-repair"
21 |
22 | set_placement_padding -global \
23 | -left {{platform.cell_pad_in_sites_detail_placement}} \
24 | -right {{platform.cell_pad_in_sites_detail_placement}}
25 | detailed_placement
26 |
27 | estimate_parasitics -placement
28 |
29 | puts "Repair setup and hold violations..."
30 | repair_timing {% if settings.setup_slack_margin %} -setup_margin {{settings.setup_slack_margin}} {% endif %} {% if settings.hold_slack_margin %} -hold_margin {{settings.hold_slack_margin}} {% endif %}
31 |
32 | detailed_placement
33 | check_placement -verbose
34 | report_metrics "cts final"
35 |
36 | {{ write_checkpoint(step, sdc=true)}}
37 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/openroad_scripts/view_cells.tcl:
--------------------------------------------------------------------------------
1 | # layout out all cells in SC_LEF in a grid for viewing
2 |
3 | read_lef $::env(TECH_LEF)
4 | read_lef $::env(SC_LEF)
5 |
6 | # Create the block
7 | set db [ord::get_db]
8 | set chip [odb::dbChip_create $db]
9 | set block [odb::dbBlock_create $chip all_cells]
10 |
11 | # Get all the masters
12 | set masters {}
13 | foreach lib [$db getLibs] {
14 | foreach master [$lib getMasters] {
15 | lappend masters $master
16 | }
17 | }
18 |
19 | # Find the number of masters & the max width and height of any master
20 | set max_width 0
21 | set max_height 0
22 | set num_masters 0
23 | foreach master $masters {
24 | set max_width [expr max($max_width, [$master getWidth])]
25 | set max_height [expr max($max_height, [$master getHeight])]
26 | incr num_masters
27 | }
28 |
29 | # The steps for laying out the cells
30 | set x_step [expr round(1.5 * $max_width)]
31 | set y_step [expr round(1.5 * $max_height)]
32 |
33 | # The number of cells per row
34 | set x_width [expr ceil(sqrt($num_masters * $y_step / $x_step))]
35 |
36 | # Make the instance array of masters
37 | set x 0
38 | set y 0
39 | foreach master $masters {
40 | set inst [odb::dbInst_create $block $master [$master getName]]
41 | $inst setPlacementStatus PLACED
42 | $inst setLocation [expr $x * $x_step] [expr $y * $y_step]
43 |
44 | incr x
45 | if {$x == $x_width} {
46 | set x 0
47 | incr y
48 | }
49 | }
50 | gui::design_created
51 | gui::fit
52 |
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/cells_adders.v:
--------------------------------------------------------------------------------
1 |
2 | (* techmap_celltype = "$fa" *)
3 | module _tech_fa (A, B, C, X, Y);
4 | parameter WIDTH = 1;
5 | (* force_downto *)
6 | input [WIDTH-1 : 0] A, B, C;
7 | (* force_downto *)
8 | output [WIDTH-1 : 0] X, Y;
9 |
10 | parameter _TECHMAP_CONSTVAL_A_ = WIDTH'bx;
11 | parameter _TECHMAP_CONSTVAL_B_ = WIDTH'bx;
12 | parameter _TECHMAP_CONSTVAL_C_ = WIDTH'bx;
13 |
14 | genvar i;
15 | generate for (i = 0; i < WIDTH; i = i + 1) begin
16 | if (_TECHMAP_CONSTVAL_A_[i] === 1'b0 || _TECHMAP_CONSTVAL_B_[i] === 1'b0 || _TECHMAP_CONSTVAL_C_[i] === 1'b0) begin
17 | if (_TECHMAP_CONSTVAL_C_[i] === 1'b0) begin
18 | HA_X1 halfadder_Cconst (
19 | .A(A[i]),
20 | .B(B[i]),
21 | .CO(X[i]), .S(Y[i])
22 | );
23 | end
24 | else begin
25 | if (_TECHMAP_CONSTVAL_B_[i] === 1'b0) begin
26 | HA_X1 halfadder_Bconst (
27 | .A(A[i]),
28 | .B(C[i]),
29 | .CO(X[i]), .S(Y[i])
30 | );
31 | end
32 | else begin
33 | HA_X1 halfadder_Aconst (
34 | .A(B[i]),
35 | .B(C[i]),
36 | .CO(X[i]), .S(Y[i])
37 | );
38 | end
39 | end
40 | end
41 | else begin
42 | FA_X1 fulladder (
43 | .A(A[i]), .B(B[i]), .CI(C[i]), .CO(X[i]), .S(Y[i])
44 | );
45 | end
46 | end endgenerate
47 |
48 | endmodule
49 |
--------------------------------------------------------------------------------
/src/xeda/flows/modelsim/templates/run.tcl:
--------------------------------------------------------------------------------
1 | puts "\n===========================( Compiling HDL Sources )==========================="
2 | {% for src in design.sim_sources if src.type -%}
3 | {% if src.type == 'verilog' -%}
4 | if { [catch {eval vlog {{src.file}} {% if src.variant == "systemverilog" -%} -sv {%- endif -%} {{vlog_opts}} } error]} {
5 | puts $error
6 | exit 1
7 | }
8 | {% elif src.type == 'vhdl' -%}
9 | if { [catch {eval vcom {{src.file}} {{vcom_opts}} {%- if design.language.vhdl.standard in ("93", "1993") %} -93 {% elif design.language.vhdl.standard in ("08", "2008") %} -2008 {% elif design.language.vhdl.standard %} -{{design.language.vhdl.standard}} {% endif -%} } error]} {
10 | puts $error
11 | exit 1
12 | }
13 | {%- endif %}
14 | {%- endfor %}
15 |
16 | puts "\n===========================( Running simulation )==========================="
17 |
18 | {% if settings.vcd %}
19 | vcd file {{settings.vcd}}
20 | {% endif %}
21 |
22 | puts "\n===========================( *ENABLE ECHO* )==========================="
23 | if { [catch {eval vsim -t ps {{design.sim_tops|join(' ')}} {{vsim_opts}} {{generics_options}} } error]} {
24 | puts $error
25 | exit 1
26 | }
27 | vcd add -r {% if not debug and design.tb.uut %} {{design.tb.uut}}/* {% else %} * {% endif %}
28 | #run_wave
29 | run {% if 'stop_time' in flow %} {{settings.stop_time}} {%- else %} -all {%- endif %}
30 | puts "\n===========================( *DISABLE ECHO* )==========================="
31 |
32 | {% if settings.vcd %}
33 | vcd flush
34 | {% endif %}
35 |
36 | exit
37 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/io_place.tcl:
--------------------------------------------------------------------------------
1 | {% if settings.floorplan_def %}
2 | puts "Skipping IO placement as DEF file was used to initialize floorplan."
3 | {% else %}
4 |
5 | {% if settings.io_constraints %} {# ---------------------------- #}
6 | source {{settings.io_constraints}}
7 |
8 | {% else %} {# -------------------------------------------------- #}
9 | # check the lower boundary of the PLACE_DENSITY and add PLACE_DENSITY_LB_ADDON if it exists
10 | {% if settings.place_density_lb_addon is not none %}
11 | set place_density_lb [gpl::get_global_placement_uniform_density \
12 | -pad_left {{platform.cell_pad_in_sites_global_placement}} \
13 | -pad_right {{platform.cell_pad_in_sites_global_placement}}]
14 | set place_density [expr $place_density_lb + {{settings.place_density_lb_addon}} + 0.01]
15 | if {$place_density > 1.0} {
16 | set place_density 1.0
17 | }
18 | {% else %}
19 | set place_density {{settings.place_density or platform.place_density}}
20 | {% endif %}
21 |
22 | global_placement -skip_io -density $place_density \
23 | -pad_left {{platform.cell_pad_in_sites_global_placement}} \
24 | -pad_right {{platform.cell_pad_in_sites_global_placement}} {{ settings.global_placement_args|join(" ") }}
25 |
26 | {% endif %} {# ------------------------------------------------- #}
27 |
28 | place_pins -hor_layer {{platform.io_placer_h}} -ver_layer {{platform.io_placer_v}} {% if settings.io_place_random %} -random {% endif %} {{settings.place_pins_args|join(" ")}}
29 | {% endif %} {# --not settings.floorplan_def-- #}
30 |
31 | {{ write_checkpoint(step) }}
32 |
--------------------------------------------------------------------------------
/examples/vhdl/sqrt/test.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import logging
4 | import os
5 | from pathlib import Path
6 |
7 | from xeda import Design, Flow
8 | from xeda.flow_runner import DefaultRunner
9 | from xeda.flows import GhdlSim, YosysFpga
10 | from xeda.tool import ExecutableNotFound
11 |
12 | log = logging.getLogger(__name__)
13 |
14 | SCRIPT_DIR = Path(__file__).parent.resolve()
15 |
16 | design = Design.from_toml(SCRIPT_DIR / "sqrt.toml")
17 | xeda_runner = DefaultRunner()
18 |
19 |
20 | def test_sqrt() -> None:
21 | LONG_TEST = [8, 9, 16, 17, 18, 20, 21, 31, 32, 63, 64, 66]
22 | QUICK_TEST = [8, 32]
23 | ws = QUICK_TEST
24 | if os.environ.get("LONG_TEST"):
25 | print("runing long test!")
26 | ws = LONG_TEST
27 | for w in ws:
28 | assert design.tb
29 | design.tb.parameters = {**design.tb.parameters, "G_IN_WIDTH": w}
30 | os.environ["NUM_TV"] = str(50)
31 | f: Flow = xeda_runner.run_flow(GhdlSim, design)
32 | if not f.succeeded:
33 | raise AssertionError(f"test failed for w={w}")
34 |
35 |
36 | def test_sqrt_yosys_synth() -> None:
37 | design.tb.parameters["G_IN_WIDTH"] = 32
38 | try:
39 | f = xeda_runner.run_flow(
40 | YosysFpga,
41 | design,
42 | {"fpga": {"part": "LFE5U-25F-6BG381C"}, "clock_period": 10.0},
43 | )
44 | assert f.succeeded
45 | except ExecutableNotFound:
46 | log.critical("Yosys executable not found")
47 |
48 |
49 | if __name__ == "__main__":
50 | test_sqrt()
51 | test_sqrt_yosys_synth()
52 |
--------------------------------------------------------------------------------
/src/xeda/platforms/mk_to_toml.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python3
2 | import argparse
3 | import re
4 | from pathlib import Path
5 |
6 |
7 | def escape(s: str):
8 | try:
9 | return str(float(s))
10 | except ValueError:
11 | pass
12 | for d in ["$(ADDITIONAL_GDS)", "$(ADDITIONAL_LIBS)", "$(PLATFORM_DIR)/"]:
13 | s = s.replace(d, "")
14 | s = s.strip()
15 | if s.startswith('"') and s.endswith('"'):
16 | return s
17 | if not (s.startswith("$(") and s.endswith(")")):
18 | sp = re.split(r"\s+", s)
19 | if len(sp) > 1:
20 | return "[" + ", ".join(escape(s) for s in sp) + "]"
21 | s = s.replace("\\", "\\\\")
22 | s = s.replace('"', '\\"')
23 | return '"' + s + '"'
24 |
25 |
26 | def comment(s: str):
27 | return " # overridable" if s.startswith("?") else ""
28 |
29 |
30 | def callback(pat):
31 | return f"{pat.group(1).lower()} = {escape(pat.group(3))}{comment(pat.group(2))}\n"
32 |
33 |
34 | def convert(args):
35 | with open(args.config_mk) as f:
36 | content = f.read()
37 | # line continuations
38 | content = re.sub(r"[^\S\r\n]*\\[^\S\r\n]*\n[^\S\r\n]*", " ", content, re.MULTILINE | re.UNICODE)
39 |
40 | content = re.sub(r"export\s+(\w+)\s*(\??=)\s*([^\n]+)\s*", callback, content)
41 | with open(Path(args.config_mk).parent / "config.toml", "w") as f:
42 | f.write(content)
43 |
44 |
45 | if __name__ == "__main__":
46 | arg_parser = argparse.ArgumentParser()
47 | arg_parser.add_argument("config_mk", type=Path)
48 | args = arg_parser.parse_args()
49 | convert(args)
50 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hd/cells_adders_hd.v:
--------------------------------------------------------------------------------
1 |
2 | (* techmap_celltype = "$fa" *)
3 | module _tech_fa (A, B, C, X, Y);
4 | parameter WIDTH = 1;
5 | (* force_downto *)
6 | input [WIDTH-1 : 0] A, B, C;
7 | (* force_downto *)
8 | output [WIDTH-1 : 0] X, Y;
9 |
10 | parameter _TECHMAP_CONSTVAL_A_ = WIDTH'bx;
11 | parameter _TECHMAP_CONSTVAL_B_ = WIDTH'bx;
12 | parameter _TECHMAP_CONSTVAL_C_ = WIDTH'bx;
13 |
14 | genvar i;
15 | generate for (i = 0; i < WIDTH; i = i + 1) begin
16 | if (_TECHMAP_CONSTVAL_A_[i] === 1'b0 || _TECHMAP_CONSTVAL_B_[i] === 1'b0 || _TECHMAP_CONSTVAL_C_[i] === 1'b0) begin
17 | if (_TECHMAP_CONSTVAL_C_[i] === 1'b0) begin
18 | sky130_fd_sc_hd__ha_1 halfadder_Cconst (
19 | .A(A[i]),
20 | .B(B[i]),
21 | .COUT(X[i]), .SUM(Y[i])
22 | );
23 | end
24 | else begin
25 | if (_TECHMAP_CONSTVAL_B_[i] === 1'b0) begin
26 | sky130_fd_sc_hd__ha_1 halfadder_Bconst (
27 | .A(A[i]),
28 | .B(C[i]),
29 | .COUT(X[i]), .SUM(Y[i])
30 | );
31 | end
32 | else begin
33 | sky130_fd_sc_hd__ha_1 halfadder_Aconst (
34 | .A(B[i]),
35 | .B(C[i]),
36 | .COUT(X[i]), .SUM(Y[i])
37 | );
38 | end
39 | end
40 | end
41 | else begin
42 | sky130_fd_sc_hd__fa_1 fulladder (
43 | .A(A[i]), .B(B[i]), .CIN(C[i]), .COUT(X[i]), .SUM(Y[i])
44 | );
45 | end
46 | end endgenerate
47 |
48 | endmodule
49 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hs/cells_adders_hs.v:
--------------------------------------------------------------------------------
1 |
2 | (* techmap_celltype = "$fa" *)
3 | module _tech_fa (A, B, C, X, Y);
4 | parameter WIDTH = 1;
5 | (* force_downto *)
6 | input [WIDTH-1 : 0] A, B, C;
7 | (* force_downto *)
8 | output [WIDTH-1 : 0] X, Y;
9 |
10 | parameter _TECHMAP_CONSTVAL_A_ = WIDTH'bx;
11 | parameter _TECHMAP_CONSTVAL_B_ = WIDTH'bx;
12 | parameter _TECHMAP_CONSTVAL_C_ = WIDTH'bx;
13 |
14 | genvar i;
15 | generate for (i = 0; i < WIDTH; i = i + 1) begin
16 | if (_TECHMAP_CONSTVAL_A_[i] === 1'b0 || _TECHMAP_CONSTVAL_B_[i] === 1'b0 || _TECHMAP_CONSTVAL_C_[i] === 1'b0) begin
17 | if (_TECHMAP_CONSTVAL_C_[i] === 1'b0) begin
18 | sky130_fd_sc_hs__ha_1 halfadder_Cconst (
19 | .A(A[i]),
20 | .B(B[i]),
21 | .COUT(X[i]), .SUM(Y[i])
22 | );
23 | end
24 | else begin
25 | if (_TECHMAP_CONSTVAL_B_[i] === 1'b0) begin
26 | sky130_fd_sc_hs__ha_1 halfadder_Bconst (
27 | .A(A[i]),
28 | .B(C[i]),
29 | .COUT(X[i]), .SUM(Y[i])
30 | );
31 | end
32 | else begin
33 | sky130_fd_sc_hs__ha_1 halfadder_Aconst (
34 | .A(B[i]),
35 | .B(C[i]),
36 | .COUT(X[i]), .SUM(Y[i])
37 | );
38 | end
39 | end
40 | end
41 | else begin
42 | sky130_fd_sc_hs__fa_1 fulladder (
43 | .A(A[i]), .B(B[i]), .CIN(C[i]), .COUT(X[i]), .SUM(Y[i])
44 | );
45 | end
46 | end endgenerate
47 |
48 | endmodule
49 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/floorplan.tcl:
--------------------------------------------------------------------------------
1 | {% if settings.floorplan_def %}
2 | # Initialize floorplan by reading in floorplan DEF
3 | puts "Read in Floorplan DEF to initialize floorplan: {{settings.floorplan_def}}"
4 | read_def -floorplan_initialize {{settings.floorplan_def}}
5 |
6 | {% elif settings.footprint %}
7 | # Initialize floorplan using ICeWall footprint
8 | ICeWall load_footprint {{settings.footprint}}
9 | initialize_floorplan \
10 | -die_area [ICeWall get_die_area] \
11 | -core_area [ICeWall get_core_area] \
12 | -site {{platform.place_site}}
13 | ICeWall init_footprint {{settings.sig_map_file}}
14 |
15 | {% elif settings.core_utilization %}
16 | # Initialize floorplan using core_utilization
17 | initialize_floorplan -utilization {{settings.core_utilization}} \
18 | -aspect_ratio {{settings.core_aspect_ratio}} \
19 | -core_space {{settings.core_margin}} \
20 | -site {{platform.place_site}}
21 |
22 | {% elif settings.core_area and settings.die_area %}
23 | # Initialize floorplan using DIE_AREA/CORE_AREA
24 | initialize_floorplan -die_area {{settings.die_area|join(" ")|embrace}} \
25 | -core_area {{settings.core_area|join(" ")|embrace}} \
26 | -site {{platform.place_site}}
27 | {% endif %}
28 |
29 | {% set make_tracks_tcl = settings.make_tracks_tcl or platform.make_tracks_tcl %}
30 | {% if make_tracks_tcl %}
31 | source {{make_tracks_tcl}}
32 | {% else %}
33 | make_tracks
34 | {% endif %}
35 |
36 | {% if settings.footprint_tcl %}
37 | source {{settings.footprint_tcl}}
38 | {% endif %}
39 |
40 | # remove buffers inserted by yosys/abc
41 | remove_buffers
42 |
43 | {{ write_checkpoint(step, sdc=true)}}
44 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/resize.tcl:
--------------------------------------------------------------------------------
1 | estimate_parasitics -placement
2 | report_metrics "resizer pre" false false
3 |
4 | print_banner "instance_count"
5 | puts [sta::network_leaf_instance_count]
6 |
7 | print_banner "pin_count"
8 | puts [sta::network_leaf_pin_count]
9 |
10 | set_dont_use {{settings.dont_use_cells|join(" ")|embrace}}
11 |
12 | # Do not buffer chip-level designs
13 | {% if settings.footprint %}
14 | puts "Perform port buffering..."
15 | buffer_ports
16 | {% endif %}
17 |
18 | puts "Perform buffer insertion..."
19 | repair_design
20 |
21 | # Repair tie lo fanout
22 | puts "Repair tie lo fanout..."
23 | set tielo_cell_name {{platform.tielo_cell}}
24 | set tielo_lib_name [get_name [get_property [lindex [get_lib_cell $tielo_cell_name] 0] library]]
25 | set tielo_pin $tielo_lib_name/$tielo_cell_name/{{platform.tielo_port}}
26 | repair_tie_fanout -separation {{settings.tie_separation}} $tielo_pin
27 |
28 | # Repair tie hi fanout
29 | puts "Repair tie hi fanout..."
30 | set tiehi_cell_name {{platform.tiehi_cell}}
31 | set tiehi_lib_name [get_name [get_property [lindex [get_lib_cell $tiehi_cell_name] 0] library]]
32 | set tiehi_pin $tiehi_lib_name/$tiehi_cell_name/{{platform.tiehi_port}}
33 | repair_tie_fanout -separation {{settings.tie_separation}} $tiehi_pin
34 |
35 | # hold violations are not repaired until after CTS
36 |
37 | print_banner "report_floating_nets"
38 | report_floating_nets
39 |
40 | report_metrics "resizer" true false
41 |
42 | print_banner "instance_count"
43 | puts [sta::network_leaf_instance_count]
44 |
45 | print_banner "pin_count"
46 | puts [sta::network_leaf_pin_count]
47 |
48 | {{ write_checkpoint(step) }}
49 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/fakeram.cfg:
--------------------------------------------------------------------------------
1 | # config file to drive ABKGroup Black-box FakeRAM2.0 Generator
2 | # https://github.com/ABKGroup/FakeRAM2.0.git
3 | # using Matt's fork to fix pin access issue
4 | # https://github.com/maliberty/FakeRAM2.0.git fix-obs branch
5 |
6 | #SAMPLE INPUT FILE; VALUES NOT REALISTIC
7 | {
8 | # The process node.
9 | "tech_nm": 7,
10 |
11 | # The operating voltage.
12 | "voltage": 0.7,
13 |
14 | # String to add in front of every metal layer number for the layer name.
15 | "metal_prefix": "M",
16 |
17 | # Horizontal Metal layer for macro pins
18 | "metal_layer": "M4",
19 |
20 | # The pin width for signal pins.
21 | "pin_width_nm": 24,
22 |
23 | # The minimum pin pitch for signal pins
24 | "pin_pitch_nm": 48,
25 |
26 | # Metal track pitch
27 | "metal_track_pitch_nm": 48,
28 |
29 | # Manufacturing Grid
30 | "manufacturing_grid_nm": 1,
31 |
32 | # Contacted Poly Pitch
33 | "contacted_poly_pitch_nm": 54,
34 |
35 | #column mux factor
36 | "column_mux_factor": 1,
37 |
38 | # Fin pitch
39 | "fin_pitch_nm" : 27,
40 |
41 | # Optional snap the width and height of the sram to a multiple value.
42 | "snap_width_nm": 190,
43 | "snap_height_nm": 1400,
44 |
45 | # List of SRAM configurations (name width depth and banks)
46 | "srams": [
47 | {"name": "fakeram7_64x21", "width": 21, "depth": 64, "banks": 1},
48 | {"name": "fakeram7_256x32", "width": 32, "depth": 256, "banks": 1},
49 | {"name": "fakeram7_256x34", "width": 34, "depth": 256, "banks": 1},
50 | {"name": "fakeram7_2048x39", "width": 39, "depth": 2048, "banks": 1}
51 | ]
52 | # TENTATIVE PARAMETERS
53 | }
54 |
--------------------------------------------------------------------------------
/src/xeda/flows/modelsim/__init__.py:
--------------------------------------------------------------------------------
1 | # © 2020 [Kamyar Mohajerani](mailto:kamyar@ieee.org)
2 |
3 | from typing import Optional
4 |
5 | from ...flow import SimFlow
6 | from ...tool import Tool
7 | from ...utils import SDF
8 |
9 |
10 | class Modelsim(SimFlow):
11 | class Settings(SimFlow.Settings):
12 | sdf: SDF = SDF()
13 | modelsimini: Optional[str] = None
14 |
15 | def run(self) -> None:
16 | assert isinstance(self.settings, self.Settings)
17 | vcom_options = ["-lint"]
18 | vlog_options = ["-lint"]
19 | vsim_opts = []
20 | tb = self.design.tb
21 | ss = self.settings
22 | # TODO are library paths supported?
23 | vsim_opts.extend([f"-L {lib_name}" for lib_name in ss.lib_paths])
24 | sdf_root = ss.sdf.root if ss.sdf.root else tb.uut
25 | for dt, f in ss.sdf.delay_items():
26 | assert sdf_root, "Neither settings.sdf.root or design.tb.uut are provided"
27 | vsim_opts.extend([f"-sdf{dt}", f"{sdf_root}={f}"])
28 |
29 | tb_generics_opts = " ".join([f"-g{k}={v}" for k, v in tb.parameters.items()])
30 |
31 | script_path = self.copy_from_template(
32 | "run.tcl",
33 | generics_options=tb_generics_opts,
34 | vcom_opts=" ".join(vcom_options),
35 | vlog_opts=" ".join(vlog_options),
36 | vsim_opts=" ".join(vsim_opts),
37 | )
38 |
39 | modelsim_opts = ["-batch", "-do", f"do {script_path}"]
40 | if ss.modelsimini:
41 | modelsim_opts.extend(["-modelsimini", ss.modelsimini])
42 | vsim = Tool("vsim")
43 | vsim.run(*modelsim_opts)
44 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/yosys/cells_adders_L.v:
--------------------------------------------------------------------------------
1 |
2 | (* techmap_celltype = "$fa" *)
3 | module _tech_fa (A, B, C, X, Y);
4 | parameter WIDTH = 1;
5 | (* force_downto *)
6 | input [WIDTH-1 : 0] A, B, C;
7 | (* force_downto *)
8 | output [WIDTH-1 : 0] X, Y;
9 |
10 | wire [WIDTH-1 : 0] NX, NY;
11 |
12 | parameter _TECHMAP_CONSTVAL_A_ = WIDTH'bx;
13 | parameter _TECHMAP_CONSTVAL_B_ = WIDTH'bx;
14 | parameter _TECHMAP_CONSTVAL_C_ = WIDTH'bx;
15 |
16 | genvar i;
17 | generate for (i = 0; i < WIDTH; i = i + 1) begin
18 | if (_TECHMAP_CONSTVAL_A_[i] === 1'b0 || _TECHMAP_CONSTVAL_B_[i] === 1'b0 || _TECHMAP_CONSTVAL_C_[i] === 1'b0) begin
19 | if (_TECHMAP_CONSTVAL_C_[i] === 1'b0) begin
20 | HAxp5_ASAP7_75t_L halfadder_Cconst (
21 | .A(A[i]),
22 | .B(B[i]),
23 | .CON(NX[i]), .SN(NY[i])
24 | );
25 | end
26 | else begin
27 | if (_TECHMAP_CONSTVAL_B_[i] === 1'b0) begin
28 | HAxp5_ASAP7_75t_L halfadder_Bconst (
29 | .A(A[i]),
30 | .B(C[i]),
31 | .CON(NX[i]), .SN(NY[i])
32 | );
33 | end
34 | else begin
35 | HAxp5_ASAP7_75t_L halfadder_Aconst (
36 | .A(B[i]),
37 | .B(C[i]),
38 | .CON(NX[i]), .SN(NY[i])
39 | );
40 | end
41 | end
42 | end
43 | else begin
44 | FAx1_ASAP7_75t_L fulladder (
45 | .A(A[i]), .B(B[i]), .CI(C[i]), .CON(NX[i]), .SN(NY[i])
46 | );
47 | end
48 |
49 | assign X[i] = ~NX[i];
50 | assign Y[i] = ~NY[i];
51 |
52 | end endgenerate
53 |
54 | endmodule
55 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/yosys/cells_adders_R.v:
--------------------------------------------------------------------------------
1 |
2 | (* techmap_celltype = "$fa" *)
3 | module _tech_fa (A, B, C, X, Y);
4 | parameter WIDTH = 1;
5 | (* force_downto *)
6 | input [WIDTH-1 : 0] A, B, C;
7 | (* force_downto *)
8 | output [WIDTH-1 : 0] X, Y;
9 |
10 | wire [WIDTH-1 : 0] NX, NY;
11 |
12 | parameter _TECHMAP_CONSTVAL_A_ = WIDTH'bx;
13 | parameter _TECHMAP_CONSTVAL_B_ = WIDTH'bx;
14 | parameter _TECHMAP_CONSTVAL_C_ = WIDTH'bx;
15 |
16 | genvar i;
17 | generate for (i = 0; i < WIDTH; i = i + 1) begin
18 | if (_TECHMAP_CONSTVAL_A_[i] === 1'b0 || _TECHMAP_CONSTVAL_B_[i] === 1'b0 || _TECHMAP_CONSTVAL_C_[i] === 1'b0) begin
19 | if (_TECHMAP_CONSTVAL_C_[i] === 1'b0) begin
20 | HAxp5_ASAP7_75t_R halfadder_Cconst (
21 | .A(A[i]),
22 | .B(B[i]),
23 | .CON(NX[i]), .SN(NY[i])
24 | );
25 | end
26 | else begin
27 | if (_TECHMAP_CONSTVAL_B_[i] === 1'b0) begin
28 | HAxp5_ASAP7_75t_R halfadder_Bconst (
29 | .A(A[i]),
30 | .B(C[i]),
31 | .CON(NX[i]), .SN(NY[i])
32 | );
33 | end
34 | else begin
35 | HAxp5_ASAP7_75t_R halfadder_Aconst (
36 | .A(B[i]),
37 | .B(C[i]),
38 | .CON(NX[i]), .SN(NY[i])
39 | );
40 | end
41 | end
42 | end
43 | else begin
44 | FAx1_ASAP7_75t_R fulladder (
45 | .A(A[i]), .B(B[i]), .CI(C[i]), .CON(NX[i]), .SN(NY[i])
46 | );
47 | end
48 |
49 | assign X[i] = ~NX[i];
50 | assign Y[i] = ~NY[i];
51 |
52 | end endgenerate
53 |
54 | endmodule
55 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/yosys/cells_adders_SL.v:
--------------------------------------------------------------------------------
1 |
2 | (* techmap_celltype = "$fa" *)
3 | module _tech_fa (A, B, C, X, Y);
4 | parameter WIDTH = 1;
5 | (* force_downto *)
6 | input [WIDTH-1 : 0] A, B, C;
7 | (* force_downto *)
8 | output [WIDTH-1 : 0] X, Y;
9 |
10 | wire [WIDTH-1 : 0] NX, NY;
11 |
12 | parameter _TECHMAP_CONSTVAL_A_ = WIDTH'bx;
13 | parameter _TECHMAP_CONSTVAL_B_ = WIDTH'bx;
14 | parameter _TECHMAP_CONSTVAL_C_ = WIDTH'bx;
15 |
16 | genvar i;
17 | generate for (i = 0; i < WIDTH; i = i + 1) begin
18 | if (_TECHMAP_CONSTVAL_A_[i] === 1'b0 || _TECHMAP_CONSTVAL_B_[i] === 1'b0 || _TECHMAP_CONSTVAL_C_[i] === 1'b0) begin
19 | if (_TECHMAP_CONSTVAL_C_[i] === 1'b0) begin
20 | HAxp5_ASAP7_75t_SL halfadder_Cconst (
21 | .A(A[i]),
22 | .B(B[i]),
23 | .CON(NX[i]), .SN(NY[i])
24 | );
25 | end
26 | else begin
27 | if (_TECHMAP_CONSTVAL_B_[i] === 1'b0) begin
28 | HAxp5_ASAP7_75t_SL halfadder_Bconst (
29 | .A(A[i]),
30 | .B(C[i]),
31 | .CON(NX[i]), .SN(NY[i])
32 | );
33 | end
34 | else begin
35 | HAxp5_ASAP7_75t_SL halfadder_Aconst (
36 | .A(B[i]),
37 | .B(C[i]),
38 | .CON(NX[i]), .SN(NY[i])
39 | );
40 | end
41 | end
42 | end
43 | else begin
44 | FAx1_ASAP7_75t_SL fulladder (
45 | .A(A[i]), .B(B[i]), .CI(C[i]), .CON(NX[i]), .SN(NY[i])
46 | );
47 | end
48 |
49 | assign X[i] = ~NX[i];
50 | assign Y[i] = ~NY[i];
51 |
52 | end endgenerate
53 |
54 | endmodule
55 |
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | [tox]
2 | minversion = 4.0
3 | envlist = py{310,311,312,313}, mypy, black, ruff
4 | requires =
5 | tox-gh-actions
6 | isolated_build = True
7 |
8 | [gh-actions]
9 | python =
10 | 3.10: py310, mypy
11 | 3.11: py311, mypy, ruff
12 | 3.12: py312, mypy, black, ruff
13 | 3.13: py313, mypy, black, ruff
14 |
15 | [testenv]
16 | passenv =
17 | HOME
18 | PIP_*
19 | PYTEST_*
20 | deps =
21 | pytest>7
22 | pytest-cov
23 | mypy
24 | pylint
25 | ruff
26 | -r examples/requirements.txt
27 | # extras =
28 |
29 | commands =
30 | pytest
31 |
32 | [testenv:pytest]
33 | minversion = 7.1
34 | addopts =
35 | --verbose
36 | --doctest-modules
37 | testpaths =
38 | tests/
39 | # examples/vhdl/sqrt
40 | # examples
41 | asyncio_mode=auto
42 | deps =
43 | pytest>7
44 | pytest-cov
45 | -r examples/requirements.txt
46 | commands =
47 | pytest -s -v
48 | skip_install = false
49 |
50 | [testenv:mypy]
51 | testpaths =
52 | src/
53 | deps =
54 | mypy>=0.991
55 | commands =
56 | python -m mypy --install-types --non-interactive src
57 | skip_install = false
58 |
59 | [testenv:pylint]
60 | testpaths =
61 | src/
62 | deps = pylint
63 | commands =
64 | pylint --rcfile=pyproject.toml src
65 |
66 | [testenv:black]
67 | testpaths =
68 | src/
69 | deps =
70 | black
71 | commands =
72 | black --check --diff src
73 |
74 | [pycodestyle]
75 | max-line-length = 100
76 | # extend-ignore = D,E203 # D: Docstring errors, E203: see https://github.com/PyCQA/pycodestyle/issues/373
77 | ignore =
78 | E501
79 | line-too-long
80 | missing-module-docstring
81 | missing-function-docstring
82 | indent-size = 4
83 | exclude =
84 | .github
85 | .eggs
86 | .tox
87 |
--------------------------------------------------------------------------------
/tests/test_yosys.py:
--------------------------------------------------------------------------------
1 | import tempfile
2 | from pathlib import Path
3 |
4 | from xeda.flow_runner import DefaultRunner
5 | from xeda.flows import YosysFpga
6 |
7 | TESTS_DIR = Path(__file__).parent.absolute()
8 | EXAMPLES_DIR = TESTS_DIR.parent / "examples"
9 |
10 |
11 | def test_yosys_synth_py() -> None:
12 | # settings = dict(fpga=FPGA("xc7a12tcsg325-1"), clock_period=5.5)
13 | # run_dir = "tests_run_dir"
14 | design_paths = [
15 | EXAMPLES_DIR / "boards" / "ulx3s" / "blinky" / "blinky.xeda.yaml",
16 | EXAMPLES_DIR / "vhdl" / "sqrt" / "sqrt.toml",
17 | EXAMPLES_DIR / "vhdl" / "Trivium" / "trivium.toml",
18 | EXAMPLES_DIR / "vhdl" / "Trivium" / "trivium.xeda.yaml",
19 | EXAMPLES_DIR / "boards" / "ulx3s" / "blinky" / "blinky_vhdl.xeda.yaml",
20 | ]
21 | with tempfile.TemporaryDirectory(dir=Path.cwd()) as run_dir:
22 | print("Xeda run dir: ", run_dir)
23 | for design in design_paths:
24 | xeda_runner = DefaultRunner(run_dir, debug=True)
25 | flow = xeda_runner.run(YosysFpga, design, flow_overrides=dict(debug=True, verbose=True))
26 | assert flow is not None, "run_flow returned None"
27 | settings_json = flow.run_path / "settings.json"
28 | results_json = flow.run_path / "results.json"
29 | assert settings_json.exists()
30 | assert flow.succeeded
31 | assert isinstance(flow.settings, YosysFpga.Settings)
32 | assert flow.settings.fpga is not None
33 | if flow.settings.fpga.vendor == "xilinx":
34 | assert flow.results.LUT > 1
35 | assert flow.results.FF > 1
36 | assert results_json.exists()
37 |
38 |
39 | if __name__ == "__main__":
40 | test_yosys_synth_py()
41 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/openroad_scripts/gui.tcl:
--------------------------------------------------------------------------------
1 | # Read liberty files
2 | source $::env(SCRIPTS_DIR)/read_liberty.tcl
3 |
4 | # Read def
5 | if {[info exist ::env(DEF_FILE)]} {
6 | # Read lef
7 | read_lef $::env(TECH_LEF)
8 | read_lef $::env(SC_LEF)
9 | if {[info exist ::env(ADDITIONAL_LEFS)]} {
10 | foreach lef $::env(ADDITIONAL_LEFS) {
11 | read_lef $lef
12 | }
13 | }
14 | set input_file $::env(DEF_FILE)
15 | read_def $input_file
16 | } else {
17 | set input_file $::env(ODB_FILE)
18 | read_db $input_file
19 | }
20 |
21 | if {![info exist ::env(GUI_NO_TIMING)]} {
22 | # Determine design stage (1 ... 6)
23 | set design_stage [lindex [split [file tail $input_file] "_"] 0]
24 |
25 | # Read SDC, first try to find the most recent SDC file for the stage
26 | set sdc_file ""
27 | for {set s $design_stage} {$s > 0} {incr s -1} {
28 | set sdc_file [glob -nocomplain -directory {{settings.results_dir}} -types f "${s}_\[A-Za-z\]*\.sdc"]
29 | if {$sdc_file != ""} {
30 | break
31 | }
32 | }
33 | if {$sdc_file == ""} {
34 | set sdc_file $::env(SDC_FILE)
35 | }
36 | read_sdc $sdc_file
37 | if [file exists $::env(PLATFORM_DIR)/derate.tcl] {
38 | source $::env(PLATFORM_DIR)/derate.tcl
39 | }
40 |
41 | source $::env(PLATFORM_DIR)/setRC.tcl
42 | if {$design_stage >= 4} {
43 | # CTS has run, so propagate clocks
44 | set_propagated_clock [all_clocks]
45 | }
46 |
47 | if {$design_stage >= 6 && [file exist {{settings.results_dir}}/6_final.spef]} {
48 | puts "Loading spef"
49 | read_spef {{settings.results_dir}}/6_final.spef
50 | } elseif {$design_stage >= 3} {
51 | puts "Estimating parasitics"
52 | estimate_parasitics -placement
53 | }
54 |
55 | # Cleanup temporary variables
56 | unset sdc_file s design_stage
57 | }
58 |
--------------------------------------------------------------------------------
/examples/boards/ulx3s/dvi_test/utils_pkg.vhdl:
--------------------------------------------------------------------------------
1 | --===============================================================================================--
2 | --! @file utils_pkg.vhdl
3 | --! @brief Utility package
4 | --! @author Kamyar Mohajerani
5 | --! @copyright Copyright (c) 2022 Kamyar Mohajerani
6 | --!
7 | --! @license Solderpad Hardware License v2.1 ([SHL-2.1](https://solderpad.org/licenses/SHL-2.1/))
8 | --! @vhdl VHDL 2008 and later
9 | --!
10 | --! @details collection of utility functions, procedures, type definitions, etc.
11 | --!
12 | --===============================================================================================--
13 |
14 | library ieee;
15 | use ieee.std_logic_1164.all;
16 | use ieee.numeric_std.all;
17 |
18 | package utils_pkg is
19 | -- types
20 | type T_UNSIGNED_ARRAY is array (natural range <>) of unsigned;
21 |
22 | -- functions
23 | function log2ceil(n : natural) return natural;
24 | function sum_bits(slv : std_logic_vector) return unsigned;
25 |
26 | end package;
27 |
28 | package body utils_pkg is
29 | --! Returns the number of bits required to represet values less than n (0 to n - 1 inclusive)
30 | function log2ceil(n : natural) return natural is
31 | variable r : natural := 0;
32 | begin
33 | while n > 2 ** r loop
34 | r := r + 1;
35 | end loop;
36 | return r;
37 | end function;
38 |
39 | --! Returns the sum of all bits in `slv`
40 | function sum_bits(slv : std_logic_vector) return unsigned is
41 | variable sum : unsigned(log2ceil(slv'length + 1) - 1 downto 0) := (others => '0');
42 | begin
43 | for i in slv'range loop
44 | sum := sum + slv(i);
45 | end loop;
46 | return sum;
47 | end function;
48 |
49 | end package body;
50 |
--------------------------------------------------------------------------------
/examples/vhdl/full_adder_tb.vhd:
--------------------------------------------------------------------------------
1 | -------------------------------------------------------------------------------
2 | -- Testbench for full_adder
3 | -- Adopted from https://vhdlguide.readthedocs.io/en/latest/vhdl/testbench.html
4 | -------------------------------------------------------------------------------
5 |
6 | library ieee;
7 | use ieee.std_logic_1164.all;
8 |
9 | entity full_adder_tb is
10 | end full_adder_tb;
11 |
12 | architecture behavior of full_adder_tb is
13 | component full_adder is
14 | port (
15 | a : in std_logic;
16 | b : in std_logic;
17 | ci : in std_logic;
18 | s : out std_logic;
19 | co : out std_logic);
20 | end component;
21 | signal a, b, ci, s, co : std_logic;
22 |
23 | type test_vector is record
24 | a, b, ci : std_logic;
25 | s, co : std_logic;
26 | end record;
27 |
28 | type test_vector_array is array (natural range <>) of test_vector;
29 | constant test_vectors : test_vector_array := (
30 | -- a, b, ci, s , co
31 | ('0', '0', '0', '0', '0'),
32 | ('0', '0', '1', '1', '0'),
33 | ('0', '1', '0', '1', '0'),
34 | ('1', '0', '0', '1', '0'),
35 | ('1', '1', '0', '0', '1'),
36 | ('0', '1', '1', '0', '1'),
37 | ('1', '0', '1', '0', '1'),
38 | ('1', '1', '1', '1', '1')
39 | );
40 | begin
41 | uut : full_adder port map(
42 | a => a,
43 | b => b,
44 | ci => ci,
45 | s => s,
46 | co => co
47 | );
48 | stim_proc : process
49 | constant delay : time := 10 ns;
50 | begin
51 | for i in test_vectors'range loop
52 | a <= test_vectors(i).a;
53 | b <= test_vectors(i).b;
54 | ci <= test_vectors(i).ci;
55 | wait for delay;
56 | assert (s = test_vectors(i).s) and (co = test_vectors(i).co)
57 | report "test_vector " & integer'image(i) & " failed" severity failure;
58 | end loop;
59 | report "full_adder_tb finished!";
60 | wait;
61 | end process;
62 | end;
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/config.lvt.toml:
--------------------------------------------------------------------------------
1 | platform = "asap7.lvt"
2 | version = "2.0"
3 | extends = "asap7"
4 |
5 |
6 | tiehi_cell = "TIEHIx1_ASAP7_75t_L"
7 | tiehi_port = "H"
8 | tielo_cell = "TIELOx1_ASAP7_75t_L"
9 | tielo_port = "L"
10 | min_buf_cells = "BUFx2_ASAP7_75t_L"
11 | min_buf_ports = ["A", "Y"]
12 | hold_buf_cell = "BUFx2_ASAP7_75t_L"
13 | abc_driver_cell = "BUFx2_ASAP7_75t_L"
14 | cts_buf_cell = "BUFx4_ASAP7_75t_L"
15 | fill_cells = "FILLERxp5_ASAP7_75t_L"
16 | tap_cell_name = "TAPCELL_ASAP7_75t_L"
17 | gds_files = ["gds/asap7sc7p5t_28_L_220121a.gds"]
18 | sc_lef = "lef/asap7sc7p5t_28_L_1x_220121a.lef"
19 | latch_map_file = "yosys/cells_latch_L.v"
20 | clkgate_map_file = "yosys/cells_clkgate_L.v"
21 | adder_map_file = "yosys/cells_adders_L.v" # overridable
22 |
23 | [corner.FF]
24 | dff_lib_file = "lib/asap7sc7p5t_SEQ_LVT_FF_nldm_220123.lib"
25 | lib_files = [
26 | "lib/asap7sc7p5t_AO_LVT_FF_nldm_211120.lib.gz",
27 | "lib/asap7sc7p5t_INVBUF_LVT_FF_nldm_220122.lib.gz",
28 | "lib/asap7sc7p5t_OA_LVT_FF_nldm_211120.lib.gz",
29 | "lib/asap7sc7p5t_SIMPLE_LVT_FF_nldm_211120.lib.gz",
30 | "lib/asap7sc7p5t_SEQ_LVT_FF_nldm_220123.lib",
31 | ]
32 |
33 | [corner.SS]
34 | dff_lib_file = "lib/asap7sc7p5t_SEQ_LVT_SS_nldm_220123.lib"
35 | lib_files = [
36 | "lib/asap7sc7p5t_AO_LVT_SS_nldm_211120.lib.gz",
37 | "lib/asap7sc7p5t_INVBUF_LVT_SS_nldm_220122.lib.gz",
38 | "lib/asap7sc7p5t_OA_LVT_SS_nldm_211120.lib.gz",
39 | "lib/asap7sc7p5t_SEQ_LVT_SS_nldm_220123.lib",
40 | "lib/asap7sc7p5t_SIMPLE_LVT_SS_nldm_211120.lib.gz",
41 | ]
42 |
43 | [corner.TT]
44 | dff_lib_file = "lib/asap7sc7p5t_SEQ_LVT_TT_nldm_220123.lib"
45 | lib_files = [
46 | "lib/asap7sc7p5t_AO_LVT_TT_nldm_211120.lib.gz",
47 | "lib/asap7sc7p5t_INVBUF_LVT_TT_nldm_220122.lib.gz",
48 | "lib/asap7sc7p5t_OA_LVT_TT_nldm_211120.lib.gz",
49 | "lib/asap7sc7p5t_SEQ_LVT_TT_nldm_220123.lib",
50 | "lib/asap7sc7p5t_SIMPLE_LVT_TT_nldm_211120.lib.gz",
51 | ]
52 |
--------------------------------------------------------------------------------
/src/xeda/flows/yosys/templates/write_netlist.tcl:
--------------------------------------------------------------------------------
1 | {% for arg in settings.post_synth_rename -%}
2 | yosys rename {{arg}}
3 | {% endfor -%}
4 |
5 | tee -o "final_check.log" check {% if settings.check_assert %} -assert {% endif %}
6 |
7 | yosys log -stdout "Writing stat to {{artifacts["utilization_report"]}}"
8 | tee -q -o {{artifacts["utilization_report"]}} stat {% if (artifacts.utilization_report|string).endswith(".json") %} -json {% endif %} {% if settings.liberty is defined and settings.liberty %} {% for lib in settings.liberty %} -liberty {{lib}} {% endfor %} {% elif settings.gates is defined and settings.gates %} -tech cmos {% endif %}
9 | {% if settings.sta -%}
10 | yosys log -stdout "Writing timing report to {{artifacts["timing_report"]}}"
11 | tee -o {{artifacts["timing_report"]}} ltp
12 | tee -a {{artifacts["timing_report"]}} sta
13 | {% endif -%}
14 |
15 | {% if settings.ltp -%}
16 | tee -o ltp.out ltp
17 | {% endif -%}
18 |
19 | {% if settings.debug or settings.verbose > 1 -%}
20 | yosys echo on
21 | {% endif -%}
22 |
23 | {% if artifacts.netlist_json -%}
24 | yosys log -stdout "Writing netlist {{artifacts.netlist_json}}"
25 | yosys write_json {{artifacts.netlist_json}}
26 | {% endif -%}
27 |
28 | {% if artifacts.netlist_verilog -%}
29 | {% for attr in settings.netlist_unset_attributes -%}
30 | yosys setattr -unset {{attr}}
31 | {% endfor -%}
32 | yosys log -stdout "Writing netlist {{artifacts.netlist_verilog}}"
33 | yosys write_verilog {{settings.netlist_verilog_flags|join(" ")}} {{artifacts.netlist_verilog}}
34 | {% endif -%}
35 |
36 | {% if settings.write_blif -%}
37 | yosys log -stdout "Writing BLIF to {{settings.write_blif}}"
38 | yosys write_blif -noalias {{settings.write_blif}}
39 | {% endif -%}
40 |
41 | {% if settings.netlist_graph -%}
42 | yosys log -stdout "Writing netlist graph to {{settings.netlist_graph.with_suffix('.dot')}}"
43 | yosys show -prefix {{settings.netlist_graph.with_suffix("")}} -format dot {{settings.netlist_graph_flags|join(" ")}}
44 | {% endif -%}
45 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/config.slvt.toml:
--------------------------------------------------------------------------------
1 | platform = "asap7.slvt"
2 | version = "2.0"
3 | extends = "asap7"
4 |
5 |
6 | tiehi_cell = "TIEHIx1_ASAP7_75t_SL"
7 | tiehi_port = "H"
8 | tielo_cell = "TIELOx1_ASAP7_75t_SL"
9 | tielo_port = "L"
10 | min_buf_cell = "BUFx2_ASAP7_75t_SL"
11 | min_buf_ports = ["A", "Y"]
12 | hold_buf_cell = "BUFx2_ASAP7_75t_SL"
13 | abc_driver_cell = "BUFx2_ASAP7_75t_SL"
14 | cts_buf_cell = "BUFx4_ASAP7_75t_SL"
15 | fill_cells = "FILLERxp5_ASAP7_75t_SL"
16 | tap_cell_name = "TAPCELL_ASAP7_75t_SL"
17 | gds_files = ["gds/asap7sc7p5t_28_SL_220121a.gds"]
18 | sc_lef = "lef/asap7sc7p5t_28_SL_1x_220121a.lef"
19 | latch_map_file = "yosys/cells_latch_SL.v"
20 | clkgate_map_file = "yosys/cells_clkgate_SL.v"
21 | adder_map_file = "yosys/cells_adders_SL.v" # overridable
22 |
23 | [corner.FF]
24 | dff_lib_file = "lib/asap7sc7p5t_SEQ_SLVT_FF_nldm_220123.lib"
25 | lib_files = [
26 | "lib/asap7sc7p5t_AO_SLVT_FF_nldm_211120.lib.gz",
27 | "lib/asap7sc7p5t_INVBUF_SLVT_FF_nldm_220122.lib.gz",
28 | "lib/asap7sc7p5t_OA_SLVT_FF_nldm_211120.lib.gz",
29 | "lib/asap7sc7p5t_SIMPLE_SLVT_FF_nldm_211120.lib.gz",
30 | "lib/asap7sc7p5t_SEQ_SLVT_FF_nldm_220123.lib",
31 | ]
32 |
33 | [corner.SS]
34 | dff_lib_file = "lib/asap7sc7p5t_SEQ_SLVT_SS_nldm_220123.lib"
35 | lib_files = [
36 | "lib/asap7sc7p5t_AO_SLVT_SS_nldm_211120.lib.gz",
37 | "lib/asap7sc7p5t_INVBUF_SLVT_SS_nldm_220122.lib.gz",
38 | "lib/asap7sc7p5t_OA_SLVT_SS_nldm_211120.lib.gz",
39 | "lib/asap7sc7p5t_SEQ_SLVT_SS_nldm_220123.lib",
40 | "lib/asap7sc7p5t_SIMPLE_SLVT_SS_nldm_211120.lib.gz",
41 | ]
42 |
43 | [corner.TT]
44 | dff_lib_file = "lib/asap7sc7p5t_SEQ_SLVT_TT_nldm_220123.lib"
45 | lib_files = [
46 | "lib/asap7sc7p5t_AO_SLVT_TT_nldm_211120.lib.gz",
47 | "lib/asap7sc7p5t_INVBUF_SLVT_TT_nldm_220122.lib.gz",
48 | "lib/asap7sc7p5t_OA_SLVT_TT_nldm_211120.lib.gz",
49 | "lib/asap7sc7p5t_SEQ_SLVT_TT_nldm_220123.lib",
50 | "lib/asap7sc7p5t_SIMPLE_SLVT_TT_nldm_211120.lib.gz",
51 | ]
52 |
--------------------------------------------------------------------------------
/src/xeda/flows/vivado/templates/util.tcl:
--------------------------------------------------------------------------------
1 | proc reportCriticalPaths {fileName} {
2 | set FH [open $fileName w]
3 | puts $FH "Startpoint,StartClock,Endpoint,EndClock,Slack,Levels,LogicDelay,TotalDelay"
4 | # (max = setup/recovery, min = hold/removal)
5 | foreach path [get_timing_paths -delay_type max -max_paths 50 -nworst 1] {
6 | set startpoint [get_property STARTPOINT_PIN $path]
7 | set startclock [get_property STARTPOINT_CLOCK $path]
8 | set endpoint [get_property ENDPOINT_PIN $path]
9 | set endclock [get_property ENDPOINT_CLOCK $path]
10 | # Get the slack on the Timing Path object
11 | set slack [get_property SLACK $path]
12 | # Get the number of logic levels between startpoint and endpoint
13 | set levels [get_property LOGIC_LEVELS $path]
14 | # Get the logic delay
15 | set logic_delay [get_property DATAPATH_LOGIC_DELAY $path]
16 | # Get the total datapath delay
17 | set delay [get_property DATAPATH_DELAY $path]
18 | # Write to the CSV file
19 | puts $FH "$startpoint,$startclock,$endpoint,$endclock,$slack,$levels,$logic_delay,$delay"
20 | }
21 | close $FH
22 | puts "Created critical paths report: $fileName\n"
23 | }
24 |
25 | proc showWarningsAndErrors {} {
26 | set num_errors [get_msg_config -severity {ERROR} -count]
27 | set num_crit_warns [get_msg_config -severity {CRITICAL WARNING} -count]
28 | set num_warns [get_msg_config -severity {WARNING} -count]
29 | if {$num_errors > 0} {
30 | puts "Exiting Vivado due to $num_errors error(s)!"
31 | exit 1
32 | }
33 | if {$num_crit_warns > 0} {
34 | puts "** Number of Critical Warnings: $num_crit_warns"
35 | {%- if settings.fail_critical_warning %}
36 | puts "Exiting due to $num_crit_warns critical warning(s)!"
37 | exit 1
38 | {%- endif %}
39 | }
40 | # if $num_warns is non-emty and not zero
41 | if {[string length $num_warns] > 0 && $num_warns != 0} {
42 | puts "** Number of Warnings: $num_warns"
43 | }
44 | puts "\n"
45 | }
46 |
--------------------------------------------------------------------------------
/src/xeda/flows/quartus/templates/create_project.tcl:
--------------------------------------------------------------------------------
1 | set design_name {{design.name}}
2 | set top {{design.rtl.top}}
3 | set fpga_part {{settings.fpga.part}}
4 | {%- if settings.debug %}
5 | foreach key [array names quartus] {
6 | puts "${key}=$quartus($key)"
7 | }
8 | {%- endif %}
9 |
10 | package require ::quartus::project
11 |
12 | puts "\n===========================( Setting up project and settings )==========================="
13 | project_new ${design_name} -overwrite
14 | {% if settings.nthreads is not none %}
15 | set_global_assignment -name NUM_PARALLEL_PROCESSORS {{settings.nthreads}}
16 | {% endif %}
17 | puts "supported FPGA families: [get_family_list]"
18 |
19 | set fpga_part_report [report_part_info $fpga_part]
20 | puts $fpga_part_report
21 |
22 | {%- if settings.fpga.family %}
23 | set_global_assignment -name FAMILY "{{settings.fpga.family}}"
24 | {%- endif %}
25 | # Use get_part_list to get a list of supported part numbers
26 | set_global_assignment -name DEVICE $fpga_part
27 |
28 | set_global_assignment -name TOP_LEVEL_ENTITY ${top}
29 |
30 | {%- if design.language.vhdl.standard %}
31 | set_global_assignment -name VHDL_INPUT_VERSION VHDL_{{design.language.vhdl.standard}}
32 | {%- endif %}
33 |
34 | {%- for src in design.rtl.sources %}
35 | set_global_assignment -name {{src.type.name|upper}}_FILE {{src.file}}
36 | {%- endfor %}
37 |
38 | {%- for k,v in design.rtl.parameters.items() %}
39 | set_parameter -name {{k}} {%if v is boolean -%} {{"true" if v else "false"}} {% elif v is string -%} "{{v}}" {%else-%} {{v}} {%endif%}
40 | {%- endfor %}
41 |
42 | {%- for sdc_file in sdc_files %}
43 | set_global_assignment -name SDC_FILE {{sdc_file}}
44 | {%- endfor %}
45 |
46 | {%- for k,v in project_settings.items() %}
47 | {%- if v is not none %}
48 | set_global_assignment -name {{k}} {%if v is boolean -%} {{"ON" if v else "OFF"}} {% elif v is number -%} {{v}} {%- else -%} "{{v}}" {%- endif %}
49 | {%- endif %}
50 | {%- endfor %}
51 |
52 | project_close
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/openlane/mapping.json:
--------------------------------------------------------------------------------
1 | {
2 | "liberty": {
3 | "pdk": "flow/platforms/asap7/lib",
4 | "openlane": "libs.ref/asap7sc7p5t/lib",
5 | "files": ["*RVT*.lib"]
6 | },
7 | "techlef": {
8 | "pdk": "flow/platforms/asap7/lef",
9 | "openlane": "libs.ref/asap7sc7p5t/techlef",
10 | "files": ["asap7_tech_1x_201209.lef"]
11 | },
12 | "lef": {
13 | "pdk": "flow/platforms/asap7/lef",
14 | "openlane": "libs.ref/asap7sc7p5t/lef",
15 | "files": ["asap7sc7p5t_27_R_1x_201211.lef"]
16 | },
17 | "gds": {
18 | "pdk": "flow/platforms/asap7/gds",
19 | "openlane": "libs.ref/asap7sc7p5t/gds",
20 | "files": ["asap7sc7p5t_27_R_1x_201211.gds"]
21 | },
22 | "klayout": {
23 | "pdk": "flow/platforms/asap7/KLayout",
24 | "openlane": "libs.tech/klayout",
25 | "files": ["*.lyp", "*.lyt"]
26 | },
27 | "rcx": {
28 | "pdk": "flow/platforms/asap7",
29 | "openlane": "libs.tech/openlane",
30 | "files": ["*.rules"]
31 | },
32 | "config-platform": {
33 | "pdk": "flow/platforms/asap7/openlane",
34 | "openlane": "libs.tech/openlane",
35 | "files": ["config.tcl"]
36 | },
37 | "config-stdcells": {
38 | "pdk": "flow/platforms/asap7/openlane/asap7sc7p5t",
39 | "openlane": "libs.tech/openlane/asap7sc7p5t",
40 | "files": ["config.tcl"]
41 | },
42 | "pdn": {
43 | "pdk": "flow/platforms/asap7/openRoad/pdn",
44 | "openlane": "libs.tech/openlane/asap7sc7p5t",
45 | "files": ["grid_strategy-M1-M2-M5-M6.cfg"]
46 | },
47 | "tracks": {
48 | "pdk": "flow/platforms/asap7/openRoad",
49 | "openlane": "libs.tech/openlane/asap7sc7p5t",
50 | "files": ["make_tracks.tcl"]
51 | },
52 | "dont-use": {
53 | "pdk": "flow/platforms/asap7/openlane/asap7sc7p5t",
54 | "openlane": "libs.tech/openlane/asap7sc7p5t",
55 | "files": ["no_synth.cells"]
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/detailed_route.tcl:
--------------------------------------------------------------------------------
1 | set_propagated_clock [all_clocks]
2 |
3 | {% if settings.nthreads %}
4 | set_thread_count {{settings.nthreads}}
5 | {% endif %}
6 |
7 | {%- set additional_args = settings.detailed_route_additional_args|join(" ") %}
8 | {%- if platform.min_routing_layer %}
9 | {%- set additional_args = additional_args + " -bottom_routing_layer " + platform.min_routing_layer %}
10 | {%- endif %}
11 | {%- if platform.max_routing_layer %}
12 | {%- set additional_args = additional_args + " -top_routing_layer " + platform.max_routing_layer %}
13 | {%- endif %}
14 | {%- if platform.via_in_pin_min_layer %}
15 | {%- set additional_args = additional_args + " -via_in_pin_bottom_layer " + platform.via_in_pin_min_layer %}
16 | {%- endif %}
17 | {%- if platform.via_in_pin_max_layer %}
18 | {%- set additional_args = additional_args + " -via_in_pin_bottom_layer " + platform.via_in_pin_max_layer %}
19 | {%- endif %}
20 | {%- if settings.disable_via_gen %}
21 | {%- set additional_args = additional_args + " -disable_via_gen" %}
22 | {%- endif %}
23 | {%- if settings.db_process_node is not none %}
24 | {%- set additional_args = additional_args + " -db_process_node " + settings.db_process_node %}
25 | {%- endif %}
26 | {%- if settings.detailed_route_or_seed is not none %}
27 | {%- set additional_args = additional_args + " -or-seed " + settings.detailed_route_or_seed %}
28 | {%- endif %}
29 | {%- if settings.detailed_route_or_k is not none %}
30 | {%- set additional_args = additional_args + " -or-k " + settings.detailed_route_or_k %}
31 | {%- endif %}
32 | {%- if settings.repair_pdn_via_layer %}
33 | {%- set additional_args = additional_args + " -repair_pdn_vias " + settings.repair_pdn_via_layer %}
34 | {%- endif %}
35 |
36 | detailed_route -output_drc {{settings.reports_dir}}/{{step_id}}_drc.rpt \
37 | -output_maze {{settings.results_dir}}/maze.log \
38 | -save_guide_updates -verbose {{settings.verbose}} {{additional_args}}
39 |
40 | {% if settings.post_detailed_route_tcl %}
41 | source {{settings.post_detailed_route_tcl}}
42 | {% endif %}
43 |
44 | {{ write_checkpoint(step) }}
45 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/finalize.tcl:
--------------------------------------------------------------------------------
1 | {{ load_checkpoint(step, sdc_from="cts") }}
2 |
3 | set_propagated_clock [all_clocks]
4 |
5 | # Ensure all OR created (rsz/cts) instances are connected
6 | global_connect
7 |
8 | # Delete routing obstructions for final DEF
9 | deleteRoutingObstructions
10 |
11 | {%- if settings.density_fill %}
12 | density_fill -rules {{platform.fill_config}}
13 | {%- endif %}
14 |
15 | {{ write_checkpoint(step, verilog=true, def=true) }}
16 |
17 | {% if platform.default_corner_settings.rcx_rules %}
18 | puts "Starting RCX"
19 | # RCX section
20 | define_process_corner -ext_model_index 0 X
21 | extract_parasitics -ext_model_file {{platform.default_corner_settings.rcx_rules}}
22 |
23 | set spef_file $results_dir/{{step_id}}.spef
24 | write_spef $spef_file
25 | file delete {{design.rtl.top}}.totCap
26 |
27 | # Read Spef for OpenSTA
28 | if { [file exists $spef_file]} {
29 | read_spef $spef_file
30 | } else {
31 | utl::error FLW 99 "SPEF file $spef_file does not exist!"
32 | }
33 |
34 | {% if settings.final_irdrop_analysis %}
35 | # Static IR drop analysis
36 | {% for net, voltage in platform.pwr_nets_voltages.items() %}
37 | puts "set_pdnsim_net_voltage {{net}}..."
38 | set_pdnsim_net_voltage -net {{net}} -voltage {{voltage}}
39 | puts "analyze_power_grid {{net}}..."
40 | analyze_power_grid -net {{net}}
41 | {% endfor %}
42 | {% for net, voltage in platform.gnd_nets_voltages.items() %}
43 | puts "set_pdnsim_net_voltage {{net}}..."
44 | set_pdnsim_net_voltage -net {{net}} -voltage {{voltage}}
45 | puts "analyze_power_grid {{net}}..."
46 | analyze_power_grid -net {{net}}
47 | {% endfor %}
48 | {% endif %}
49 |
50 | {% endif %}
51 |
52 | {% if settings.write_cdl and settings.cdl_masters_file %}
53 | write_cdl -masters {{cdl_masters_file}} $results_dir/{{step_id}}.cdl
54 | {% endif %}
55 |
56 | report_metrics {{step}}
57 |
58 | {% if settings.save_images %}
59 | {% include "save_images.tcl" %}
60 |
61 | # Save a final image if openroad is compiled with the gui
62 | if {[expr [llength [info procs save_image]] > 0]} {
63 | gui::show save_images false
64 | }
65 | {% endif %}
66 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/macros.tcl.j2:
--------------------------------------------------------------------------------
1 | {% macro banner(msg, line_len = 80, line_char="=", top_line=true, bottom_line=true) %}
2 | {% set msg_len = (msg|length) %}
3 | {% set sp1 = (line_len - msg_len) // 2 %}
4 | {% set sp2 = line_len - sp1 - msg_len %}
5 | {% if top_line %}
6 | puts "{{ line_char * line_len }}"
7 | {% endif %}
8 | puts "{{ line_char * sp1 }}{{msg}}{{line_char * sp2 }}"
9 | {% if bottom_line %}
10 | puts "{{ line_char * line_len }}"
11 | {% endif %}
12 | {% endmacro %}
13 |
14 | {% macro preamble(step, step_index) %}
15 | {% set msg = (" Starting %s (%d/%d) "|format(step, step_index + 1, total_steps)) %}
16 | {{ banner(msg) }}
17 | {% endmacro %}
18 |
19 | {% macro epilogue(step) %}
20 | {{ banner("( %s done )"|format(step), line_char="-", top_line=false, bottom_line=false) }}
21 | {% endmacro %}
22 |
23 | {% macro load_checkpoint(step, sdc_from=none) %}
24 | {% set prev_step_id = get_prev_step_id(step) %}
25 | {% if prev_step_id and should_load_checkpoint(step) %}
26 | read_libraries
27 | read_db {{settings.checkpoints_dir}}/{{prev_step_id}}.odb
28 | {% if sdc_from %}
29 | {% set sdc_step_id = get_step_id(sdc_from) %}
30 | read_sdc {{settings.results_dir}}/{{sdc_step_id}}.sdc
31 | {% endif %}
32 | {% if platform.derate_tcl %}
33 | source {{platform.derate_tcl}}
34 | {% endif %}
35 | {% if platform.setrc_tcl %}
36 | source {{platform.setrc_tcl}}
37 | {% endif %}
38 | {% endif %}
39 | {% endmacro %}
40 |
41 | {% macro write_checkpoint(step, db=true, sdc=false, def=false, verilog=false) %}
42 | {% set step_id = get_step_id(step) %}
43 | {% if should_write_checkpoint(step) %}
44 | {% if db %}
45 | write_db {{settings.checkpoints_dir}}/{{step_id}}.odb
46 | {% endif %}
47 | {% if sdc %}
48 | write_sdc {{settings.results_dir}}/{{step_id}}.sdc
49 | {% endif %}
50 | {% if def %}
51 | write_def {{settings.results_dir}}/{{step_id}}.def
52 | {% endif %}
53 | {% if verilog %}
54 | write_verilog {{settings.results_dir}}/{{step_id}}.v
55 | {% endif %}
56 | {% endif %}
57 | {% endmacro %}
58 |
59 | {% macro section(name) %}
60 | {{ banner(" %s "|format(name), line_char="-", top_line=false, bottom_line=false) }}
61 | {% endmacro %}
62 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/openroad/pdn/grid_strategy-M1-M2-M5-M6.tcl:
--------------------------------------------------------------------------------
1 | ####################################
2 | # global connections
3 | ####################################
4 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDD$} -power
5 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDDPE$}
6 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDDCE$}
7 | add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {^VSS$} -ground
8 | add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {^VSSE$}
9 | global_connect
10 | ####################################
11 | # voltage domains
12 | ####################################
13 | set_voltage_domain -name {CORE} -power {VDD} -ground {VSS}
14 | ####################################
15 | # standard cell grid
16 | ####################################
17 | define_pdn_grid -name {top} -voltage_domains {CORE}
18 | add_pdn_stripe -grid {top} -layer {M1} -width {0.018} -pitch {0.54} -offset {0} -followpins
19 | add_pdn_stripe -grid {top} -layer {M2} -width {0.018} -pitch {0.54} -offset {0} -followpins
20 | add_pdn_stripe -grid {top} -layer {M5} -width {0.12} -spacing {0.072} -pitch {11.88} -offset {0.300}
21 | add_pdn_stripe -grid {top} -layer {M6} -width {0.288} -spacing {0.096} -pitch {12} -offset {0.513}
22 | add_pdn_connect -grid {top} -layers {M1 M2}
23 | add_pdn_connect -grid {top} -layers {M2 M5}
24 | add_pdn_connect -grid {top} -layers {M5 M6}
25 | ####################################
26 | # macro grids
27 | ####################################
28 | ####################################
29 | # grid for: CORE_macro_grid_1
30 | ####################################
31 | define_pdn_grid -name {CORE_macro_grid_1} -voltage_domains {CORE} -macro -orient {R0 R180 MX MY} -cells {.*}
32 | add_pdn_connect -grid {CORE_macro_grid_1} -layers {M4 M5}
33 | ####################################
34 | # grid for: CORE_macro_grid_2
35 | ####################################
36 | define_pdn_grid -name {CORE_macro_grid_2} -voltage_domains {CORE} -macro -orient {R90 R270 MXR90 MYR90} -cells {.*}
37 | add_pdn_connect -grid {CORE_macro_grid_2} -layers {M4 M5}
38 |
--------------------------------------------------------------------------------
/src/xeda/flows/yosys/templates/yosys_fpga_synth.tcl:
--------------------------------------------------------------------------------
1 | yosys logger -notime -stderr
2 | {% include 'read_files.tcl' -%}
3 |
4 | {% if settings.prep is not none -%}
5 | yosys prep {%- if settings.flatten %} -flatten {%- endif %} {%- if design.rtl.top %} -top {{design.rtl.top}} {%- else %} -auto-top {%- endif %} {{settings.prep|join(" ")}}
6 | {% else %}
7 | yosys proc
8 | {% if settings.flatten -%}
9 | yosys flatten
10 | {% endif -%}
11 | {% endif -%}
12 |
13 | {% include "post_rtl.tcl" -%}
14 |
15 | {% if settings.pre_synth_opt -%}
16 | yosys log -stdout "** Pre-synthesis optimization **"
17 | yosys opt -undriven -purge -keepdc -noff
18 | {% endif -%}
19 |
20 | yosys opt_clean -purge
21 |
22 | {% if settings.abc9 -%}
23 | {% if settings.flow3 -%} yosys scratchpad -copy abc9.script.flow3 abc9.script {%- endif %}
24 | {# decrease the target delay to account for interconnect delay #}
25 | {% if settings.main_clock and settings.main_clock.period_ps -%} yosys scratchpad -set abc9.D {{settings.main_clock.period_ps / 1.5}} {%- endif %}
26 | {% endif -%}
27 |
28 | yosys log -stdout "** FPGA synthesis for device {{settings.fpga}} **"
29 | {% if settings.fpga.vendor == "xilinx" -%}
30 | yosys log -stdout "*** Target: Xilinx {%if settings.fpga.part%} {{settings.fpga.part}} {%else%} {{settings.fpga.device}} {%endif%} ***"
31 | yosys synth_xilinx {% if settings.fpga.family %} -family {{"xc7" if settings.fpga.family.endswith("7") else settings.fpga.family}} {% endif %} {{settings.synth_flags|join(" ")}}
32 | {% elif settings.fpga.family %}
33 | yosys log -stdout "*** Target: {{settings.fpga.family}} ***"
34 | yosys synth_{{settings.fpga.family}} {{settings.synth_flags|join(" ")}} {% if design.rtl.top %} -top {{design.rtl.top}}{% endif %}
35 | {% else %}
36 | yosys log -stdout "[ERROR] Unknown FPGA vendor, family, or device"
37 | {% endif -%}
38 |
39 |
40 | {% if settings.post_synth_opt -%}
41 | yosys log -stdout "** Post-synthesis optimization **"
42 | yosys opt -full -fine -purge -sat -undriven
43 | {% endif -%}
44 |
45 | yosys opt_clean -purge
46 |
47 | {% if settings.splitnets -%}
48 | yosys splitnets
49 | {% endif -%}
50 |
51 | {% include "write_netlist.tcl" -%}
52 |
--------------------------------------------------------------------------------
/src/xeda/flows/__init__.py:
--------------------------------------------------------------------------------
1 | # all Flow classes imported here can be used from FlowRunners and will be reported on the command-line help
2 | from __future__ import annotations
3 |
4 | import pkgutil
5 | from importlib import import_module
6 | from inspect import isabstract, isclass
7 | from typing import List, Type
8 |
9 | from ..flow import Flow
10 | from .bsc import Bsc
11 | from .dc import Dc
12 | from .diamond import DiamondSynth
13 | from .ghdl import GhdlSim, GhdlSynth
14 | from .ise import IseSynth
15 | from .modelsim import Modelsim
16 | from .nextpnr import Nextpnr
17 | from .nvc import Nvc
18 | from .openfpgaloader import Openfpgaloader
19 | from .openroad import Openroad
20 | from .openxc7 import OpenXC7
21 | from .quartus import Quartus
22 | from .vcs import Vcs
23 | from .verilator import Verilator
24 | from .vivado.vivado_alt_synth import VivadoAltSynth
25 | from .vivado.vivado_postsynthsim import VivadoPostsynthSim
26 | from .vivado.vivado_power import VivadoPower
27 | from .vivado.vivado_project import VivadoProject
28 | from .vivado.vivado_sim import VivadoSim
29 | from .vivado.vivado_synth import VivadoSynth
30 | from .yosys import CxxRtl, Yosys, YosysFpga
31 |
32 | __builtin_flows__: List[Type[Flow]] = []
33 |
34 | __all__ = [
35 | "__builtin_flows__",
36 | "Dc",
37 | "Bsc",
38 | "CxxRtl",
39 | "DiamondSynth",
40 | "GhdlSim",
41 | "GhdlSynth",
42 | "IseSynth",
43 | "Modelsim",
44 | "Nextpnr",
45 | "Nvc",
46 | "Openfpgaloader",
47 | "Openroad",
48 | "OpenXC7",
49 | "Quartus",
50 | "Nvc",
51 | "Verilator",
52 | "VivadoAltSynth",
53 | "VivadoPostsynthSim",
54 | "VivadoPower",
55 | "VivadoProject",
56 | "VivadoSim",
57 | "VivadoSynth",
58 | "Yosys",
59 | "YosysFpga",
60 | "Vcs",
61 | ]
62 |
63 | for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
64 | module = import_module("." + module_name, __package__)
65 | for attribute_name in dir(module):
66 | cls = getattr(module, attribute_name)
67 | if isclass(cls) and issubclass(cls, Flow) and not isabstract(cls):
68 | __builtin_flows__.append(cls)
69 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/global_route.tcl:
--------------------------------------------------------------------------------
1 | {% if platform.fastroute_tcl %}
2 | source {{platform.fastroute_tcl}}
3 | {% else %}
4 | set_global_routing_layer_adjustment {{platform.min_routing_layer}}-{{platform.max_routing_layer}} {{settings.global_routing_layer_adjustment}}
5 | set_routing_layers -signal {{platform.min_routing_layer}}-{{platform.max_routing_layer}}
6 | {% endif %}
7 |
8 | global_route -guide_file {{settings.results_dir}}/route.guide \
9 | -congestion_iterations {{settings.congestion_iterations}} \
10 | -congestion_report_file {{settings.reports_dir}}/congestion.rpt {% if settings.verbose %} -verbose {% endif %}
11 |
12 | set_propagated_clock [all_clocks]
13 | estimate_parasitics -global_routing
14 | report_metrics "global route"
15 |
16 | {% if settings.repair_antennas %}
17 | repair_antennas
18 | {% endif %}
19 |
20 | print_banner "check_antennas"
21 | check_antennas -report_file {{settings.reports_dir}}/{{step_id}}_antenna.log
22 |
23 | {% if (settings.clocks|length) == 1 and settings.update_sdc_margin %}
24 | {{section("write_ref_sdc")}}
25 | # Write an SDC file with clock periods that result in slightly negative (failing) slack.
26 | set clks [all_clocks]
27 | set clk [lindex $clks 0]
28 | set clk_name [get_name $clk]
29 | set period [get_property $clk "period"]
30 | # Period is in sdc/liberty units.
31 | utl::info "write_ref_sdc" 7 "clock $clk_name period $period"
32 | set slack [sta::time_sta_ui [sta::worst_slack_cmd "max"]]
33 | set ref_period [expr ($period - $slack) * (1.0 - {{settings.update_sdc_margin}})]
34 | utl::info "write_ref_sdc" 8 "Clock $clk_name period [format %.3f $ref_period]"
35 | utl::info "write_ref_sdc" 9 "Clock $clk_name slack [format %.3f $slack]"
36 |
37 | set sources [$clk sources]
38 | # Redefine clock with updated period.
39 | create_clock -name $clk_name -period $ref_period $sources
40 | # Undo the set_propagated_clock so SDC at beginning of flow uses ideal clocks.
41 | unset_propagated_clock [all_clocks]
42 | write_sdc {{settings.results_dir}}/{{step_id}}_updated_clks.sdc
43 | # Reset
44 | create_clock -name $clk_name -period $period $sources
45 | set_propagated_clock [all_clocks]
46 | {% endif %}
47 |
48 | {{ write_checkpoint(step) }}
49 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/openroad_scripts/LICENSE.md:
--------------------------------------------------------------------------------
1 | The OpenROAD-flow-scripts repository (build and run scripts) has a BSD 3-Clause License with its text below.
2 | The flow relies on several tools, platforms and designs that each have their own licenses.
3 |
4 | The license below applies ***only*** to the build and run scripts, not the OpenROAD tools.
5 | See the README.md file LICENSE section for details on the location of each components' individual license.
6 |
7 | License for Build and Run scripts in the OpenROAD-flow-scripts repository only :
8 |
9 | BSD 3-Clause License
10 |
11 | Copyright (c) 2018, The Regents of the University of California
12 | All rights reserved.
13 |
14 | Redistribution and use in source and binary forms, with or without
15 | modification, are permitted provided that the following conditions are met:
16 |
17 | * Redistributions of source code must retain the above copyright notice, this
18 | list of conditions and the following disclaimer.
19 |
20 | * Redistributions in binary form must reproduce the above copyright notice,
21 | this list of conditions and the following disclaimer in the documentation
22 | and/or other materials provided with the distribution.
23 |
24 | * Neither the name of the copyright holder nor the names of its
25 | contributors may be used to endorse or promote products derived from
26 | this software without specific prior written permission.
27 |
28 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/global_place.tcl:
--------------------------------------------------------------------------------
1 |
2 | set_dont_use {{settings.dont_use_cells|join(" ")|embrace}}
3 |
4 | # set fastroute layer reduction
5 | {% if platform.fastroute_tcl %}
6 | source {{platform.fastroute_tcl}}
7 | {% else %}
8 |
9 | set_global_routing_layer_adjustment {{platform.min_routing_layer}}-{{platform.max_routing_layer}} 0.5
10 | set_routing_layers -signal {{platform.min_routing_layer}}-{{platform.max_routing_layer}}
11 | set_macro_extension 2
12 | {% endif %}
13 |
14 | # check the lower boundary of the PLACE_DENSITY and add PLACE_DENSITY_LB_ADDON if it exists
15 | {% if settings.place_density_lb_addon %}
16 | set place_density_lb [gpl::get_global_placement_uniform_density \
17 | -pad_left {{platform.cell_pad_in_sites_global_placement}} \
18 | -pad_right {{platform.cell_pad_in_sites_global_placement}}]
19 | set place_density [expr $place_density_lb + ((1.0 - $place_density_lb) * {{settings.place_density_lb_addon}} + 0.01]
20 | if {$place_density > 1.0} {
21 | utl::error FLW 24 "Place density exceeds 1.0 (current PLACE_DENSITY_LB_ADDON = {{settings.place_density_lb_addon}}). Please check if the value of PLACE_DENSITY_LB_ADDON is between 0 and 0.99."
22 | }
23 | {% else %}
24 | set place_density {{settings.place_density or platform.place_density}}
25 | {% endif %}
26 |
27 | set global_placement_args "{{ settings.global_placement_args|join(" ") }}"
28 | {% if settings.gpl_routability_driven %}
29 | append global_placement_args " -routability_driven"
30 | {% endif %}
31 | {% if settings.gpl_timing_driven %}
32 | append global_placement_args " -timing_driven"
33 | {% endif %}
34 | {% if settings.min_phi_coef is not none %}
35 | append global_placement_args " -min_phi_coef {{settings.min_phi_coef}}"
36 | {% endif %}
37 |
38 | {% if settings.max_phi_coef is not none %}
39 | append global_placement_args " -max_phi_coef {{settings.max_phi_coef}}"
40 | {% endif %}
41 |
42 | global_placement -density $place_density \
43 | -pad_left {{platform.cell_pad_in_sites_global_placement}} \
44 | -pad_right {{platform.cell_pad_in_sites_global_placement}} \
45 | {*}$global_placement_args
46 |
47 | estimate_parasitics -placement
48 | report_metrics "global place" false false
49 |
50 | {{ write_checkpoint(step) }}
51 |
--------------------------------------------------------------------------------
/examples/mixed_language/blink/blink_tb.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 |
6 | #include "blink.h"
7 |
8 | int main() {
9 | cxxrtl_design::p_blink top;
10 |
11 | auto vcd_filename = "waves.vcd";
12 |
13 | std::cout << "dumbping waveform to " << vcd_filename << std::endl;
14 |
15 | // debug_items maps the hierarchical names of signals and memories in the
16 | // design to a cxxrtl_object (a value, a wire, or a memory)
17 | cxxrtl::debug_items all_debug_items;
18 |
19 | // Load the debug items of the top down the whole design hierarchy
20 | top.debug_info(all_debug_items);
21 |
22 | // vcd_writer is the CXXRTL object that's responsible of creating a string
23 | // with the VCD file contents.
24 | cxxrtl::vcd_writer vcd;
25 | vcd.timescale(1, "ns");
26 |
27 | // Here we tell the vcd writer to dump all the signals of the design, except
28 | // for the memories, to the VCD file.
29 | //
30 | // It's not necessary to load all debug objects to the VCD. There is, for
31 | // example, a vcd.add(, )) method which allows
32 | // creating your custom filter to decide what to add and what not.
33 | vcd.add_without_memories(all_debug_items);
34 |
35 | std::ofstream waves(vcd_filename);
36 |
37 | bool prev_led = 0;
38 |
39 | /// Is only a single-threaded sequential driver/monitor simulation supported?!
40 |
41 | for (int step = 0; step < 1000; ++step) {
42 |
43 | top.p_clk.set(false);
44 | top.step();
45 | vcd.sample(step * 2 + 0);
46 |
47 | top.p_clk.set(true);
48 | top.step();
49 | vcd.sample(step * 2 + 1);
50 |
51 | if (step < 2){
52 | top.p_reset.set(true);
53 | continue;
54 | } else {
55 | top.p_reset.set(false);
56 | }
57 |
58 | bool cur_led = top.p_led.get();
59 | uint32_t counter = top.p_counter.get();
60 |
61 | if (cur_led != prev_led) {
62 | std::cout << "cycle " << step << " - led: " << cur_led
63 | << ", counter: " << counter << std::endl;
64 | }
65 | prev_led = cur_led;
66 |
67 | waves << vcd.buffer;
68 | vcd.buffer.clear();
69 | }
70 | }
--------------------------------------------------------------------------------
/src/xeda/flow/sim.py:
--------------------------------------------------------------------------------
1 | """simulation flow"""
2 |
3 | from __future__ import annotations
4 |
5 | import logging
6 | from abc import ABCMeta
7 | from pathlib import Path
8 | from typing import Dict, List, Optional, Union
9 |
10 | from ..cocotb import Cocotb, CocotbSettings
11 | from ..dataclass import Field, validator
12 | from ..design import Design
13 | from .flow import Flow
14 |
15 | log = logging.getLogger(__name__)
16 |
17 | __all__ = [
18 | "SimFlow",
19 | ]
20 |
21 |
22 | class SimFlow(Flow, metaclass=ABCMeta):
23 | """superclass of all simulation flows"""
24 |
25 | cocotb_sim_name: Optional[str] = None
26 |
27 | class Settings(Flow.Settings):
28 | vcd: Union[None, str, Path] = Field(
29 | None, alias="waveform", description="Write waveform to file"
30 | )
31 | stop_time: Union[None, str, int, float] = None
32 | cocotb: CocotbSettings = CocotbSettings() # type: ignore
33 | optimization_flags: List[str] = Field([], description="Optimization flags")
34 |
35 | @validator("vcd", pre=True)
36 | def _validate_vcd(cls, vcd): # pylint: disable=no-self-argument
37 | if vcd is not None:
38 | if isinstance(vcd, bool) and vcd is True:
39 | vcd = "dump.vcd"
40 | else:
41 | if (
42 | isinstance(vcd, str) and vcd[1:].count(".") == 0
43 | ): # if it doesn't have an extension
44 | vcd += ".vcd"
45 | return vcd
46 |
47 | def __init__(
48 | self,
49 | settings: Union[Settings, Dict],
50 | design: Union[Design, Dict],
51 | run_path: Optional[Path] = None,
52 | **kwargs,
53 | ):
54 | super().__init__(settings, design, run_path, **kwargs)
55 | assert isinstance(
56 | self.settings, self.Settings
57 | ), "self.settings is not an instance of self.Settings class"
58 | self.cocotb: Optional[Cocotb] = (
59 | Cocotb(
60 | **self.settings.cocotb.dict(),
61 | sim_name=self.cocotb_sim_name,
62 | dockerized=self.settings.dockerized,
63 | )
64 | if self.cocotb_sim_name and self.design.tb.cocotb
65 | else None
66 | )
67 |
--------------------------------------------------------------------------------
/src/xeda/platforms/platform.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import os
3 | from pathlib import Path
4 | from typing import Any, Dict, Optional, Type, TypeVar, Union
5 |
6 | from importlib_resources import as_file, files
7 |
8 | from ..dataclass import XedaBaseModel
9 | from ..utils import toml_load
10 |
11 | log = logging.getLogger(__name__)
12 |
13 |
14 | PlatformType = TypeVar("PlatformType", bound="Platform")
15 |
16 |
17 | class Platform(XedaBaseModel):
18 | root_dir: Path
19 | name: Optional[str] = None
20 | version: Optional[str] = None
21 | description: Optional[str] = None
22 |
23 | @classmethod
24 | def create(cls: Type[PlatformType], **kwargs) -> PlatformType:
25 | log.debug("create: kwargs=%s", str(kwargs))
26 | return cls(**kwargs)
27 |
28 | @classmethod
29 | def from_toml(
30 | cls: Type[PlatformType], platform_toml: Union[str, os.PathLike], overrides={}
31 | ) -> PlatformType:
32 | path = Path(platform_toml)
33 | kv = {**toml_load(path), **overrides}
34 | return cls.create(root_dir=path.parent, **kv).with_absolute_paths()
35 |
36 | @classmethod
37 | def from_resource(cls: Type[PlatformType], name: str, overrides={}) -> PlatformType:
38 | res = files(__package__).joinpath(name, "config.toml")
39 | with as_file(res) as path:
40 | d = cls.from_toml(path, overrides)
41 | if not d.name:
42 | d.name = name
43 | return d
44 |
45 | def with_absolute_paths(self: PlatformType) -> PlatformType:
46 | rd = self.root_dir.absolute()
47 |
48 | def to_abs(v):
49 | if v and isinstance(v, Path) and not os.path.isabs(v):
50 | return rd / v
51 | return v
52 |
53 | def convert_rec(kv: Dict[str, Any], exclude_keys=[]):
54 | for k, v in kv.items():
55 | if k in exclude_keys:
56 | continue
57 | if isinstance(v, dict):
58 | v = convert_rec(v)
59 | elif isinstance(v, (list, tuple)):
60 | v = [to_abs(ve) for ve in v]
61 | else:
62 | v = to_abs(v)
63 | kv[k] = v
64 | return kv
65 |
66 | return self.__class__(**convert_rec(self.dict(), exclude_keys=["root_dir"]))
67 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hd/pdn.tcl:
--------------------------------------------------------------------------------
1 | ####################################
2 | # global connections
3 | ####################################
4 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDD$} -power
5 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDDPE$}
6 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDDCE$}
7 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {VPWR}
8 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {VPB}
9 | add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {^VSS$} -ground
10 | add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {^VSSE$}
11 | add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {VGND}
12 | add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {VNB}
13 | global_connect
14 | ####################################
15 | # voltage domains
16 | ####################################
17 | set_voltage_domain -name {CORE} -power {VDD} -ground {VSS}
18 | ####################################
19 | # standard cell grid
20 | ####################################
21 | define_pdn_grid -name {grid} -voltage_domains {CORE}
22 | add_pdn_stripe -grid {grid} -layer {met1} -width {0.48} -pitch {5.44} -offset {0} -followpins
23 | add_pdn_stripe -grid {grid} -layer {met4} -width {1.600} -pitch {27.140} -offset {13.570}
24 | add_pdn_stripe -grid {grid} -layer {met5} -width {1.600} -pitch {27.200} -offset {13.600}
25 | add_pdn_connect -grid {grid} -layers {met1 met4}
26 | add_pdn_connect -grid {grid} -layers {met4 met5}
27 | ####################################
28 | # macro grids
29 | ####################################
30 | ####################################
31 | # grid for: CORE_macro_grid_1
32 | ####################################
33 | define_pdn_grid -name {CORE_macro_grid_1} -voltage_domains {CORE} -macro -orient {R0 R180 MX MY} -halo {2.0 2.0 2.0 2.0} -default -grid_over_boundary
34 | add_pdn_connect -grid {CORE_macro_grid_1} -layers {met4 met5}
35 | ####################################
36 | # grid for: CORE_macro_grid_2
37 | ####################################
38 | define_pdn_grid -name {CORE_macro_grid_2} -voltage_domains {CORE} -macro -orient {R90 R270 MXR90 MYR90} -halo {2.0 2.0 2.0 2.0} -default -grid_over_boundary
39 | add_pdn_connect -grid {CORE_macro_grid_2} -layers {met4 met5}
40 |
--------------------------------------------------------------------------------
/src/xeda/platforms/sky130hs/pdn.tcl:
--------------------------------------------------------------------------------
1 | ####################################
2 | # global connections
3 | ####################################
4 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDD$} -power
5 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDDPE$}
6 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDDCE$}
7 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {VPWR}
8 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {VPB}
9 | add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {^VSS$} -ground
10 | add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {^VSSE$}
11 | add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {VGND}
12 | add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {VNB}
13 | global_connect
14 | ####################################
15 | # voltage domains
16 | ####################################
17 | set_voltage_domain -name {CORE} -power {VDD} -ground {VSS}
18 | ####################################
19 | # standard cell grid
20 | ####################################
21 | define_pdn_grid -name {grid} -voltage_domains {CORE}
22 | add_pdn_stripe -grid {grid} -layer {met1} -width {0.48} -pitch {6.66} -offset {0} -followpins
23 | add_pdn_stripe -grid {grid} -layer {met4} -width {1.600} -pitch {27.140} -offset {13.570}
24 | add_pdn_stripe -grid {grid} -layer {met5} -width {1.600} -pitch {27.200} -offset {13.600}
25 | add_pdn_connect -grid {grid} -layers {met1 met4}
26 | add_pdn_connect -grid {grid} -layers {met4 met5}
27 | ####################################
28 | # macro grids
29 | ####################################
30 | ####################################
31 | # grid for: CORE_macro_grid_1
32 | ####################################
33 | define_pdn_grid -name {CORE_macro_grid_1} -voltage_domains {CORE} -macro -orient {R0 R180 MX MY} -halo {2.0 2.0 2.0 2.0} -default -grid_over_boundary
34 | add_pdn_connect -grid {CORE_macro_grid_1} -layers {met4 met5}
35 | ####################################
36 | # grid for: CORE_macro_grid_2
37 | ####################################
38 | define_pdn_grid -name {CORE_macro_grid_2} -voltage_domains {CORE} -macro -orient {R90 R270 MXR90 MYR90} -halo {2.0 2.0 2.0 2.0} -default -grid_over_boundary
39 | add_pdn_connect -grid {CORE_macro_grid_2} -layers {met4 met5}
40 |
--------------------------------------------------------------------------------
/examples/vhdl/pipeline/pipelined_adder.vhdl:
--------------------------------------------------------------------------------
1 | library ieee;
2 | use ieee.std_logic_1164.all;
3 | use ieee.numeric_std.all;
4 |
5 | entity pipelined_adder is
6 | generic(
7 | W : positive := 32
8 | );
9 | port(
10 | clock : in std_logic;
11 | reset : in std_logic;
12 | in_a : in std_logic_vector(W - 1 downto 0);
13 | in_b : in std_logic_vector(W - 1 downto 0);
14 | in_valid : in std_logic;
15 | in_ready : out std_logic;
16 | out_sum : out std_logic_vector(W downto 0);
17 | out_valid : out std_logic;
18 | out_ready : in std_logic
19 | );
20 | end;
21 |
22 | architecture behavioral of pipelined_adder is
23 | constant DEPTH : positive := 2;
24 |
25 | -- registers
26 | signal l0_a, l0_b : std_logic_vector(W - 1 downto 0);
27 | signal l1_s : std_logic_vector(W downto 0);
28 | signal valid_pipe : std_logic_vector(0 to DEPTH - 1);
29 |
30 | -- wires
31 | signal valids : std_logic_vector(0 to DEPTH);
32 | signal readies : std_logic_vector(0 to DEPTH);
33 | begin
34 |
35 | process(all)
36 | begin
37 | readies(DEPTH) <= out_ready;
38 | in_ready <= readies(0);
39 | valids(0) <= in_valid;
40 | out_valid <= valids(DEPTH);
41 |
42 | for i in 0 to DEPTH - 1 loop
43 | readies(i) <= not valid_pipe(i) or readies(i + 1);
44 | valids(i + 1) <= valid_pipe(i);
45 | end loop;
46 |
47 | out_sum <= l1_s;
48 | end process;
49 |
50 | process(clock)
51 | begin
52 | if rising_edge(clock) then
53 | if reset = '1' then
54 | valid_pipe <= (others => '0');
55 | else
56 | for i in 0 to DEPTH - 1 loop
57 | if readies(i) then
58 | valid_pipe(i) <= valids(i);
59 | end if;
60 | end loop;
61 | end if;
62 | end if;
63 | end process;
64 |
65 | process(clock)
66 | begin
67 | if rising_edge(clock) then
68 | -- Update logic for each stage:
69 | if readies(0) then
70 | l0_a <= in_a;
71 | l0_b <= in_b;
72 | end if;
73 | if readies(1) then
74 | l1_s <= std_logic_vector(unsigned('0' & l0_a) + unsigned(l0_b));
75 | end if;
76 | end if;
77 | end process;
78 | end;
79 |
--------------------------------------------------------------------------------
/examples/vhdl/sqrt/tb_sqrt.py:
--------------------------------------------------------------------------------
1 | import os
2 | import random
3 |
4 | import cocotb
5 | from cocotb.handle import HierarchyObject
6 | from cocolight import DutClock, DutReset, ValidReadyTb
7 |
8 | NUM_TV = int(os.environ.get("NUM_TV", 2000))
9 | DEBUG = bool(os.environ.get("DEBUG", False))
10 |
11 |
12 | class SqrtTb(ValidReadyTb):
13 | def __init__(self, dut: HierarchyObject, debug: bool = DEBUG):
14 | super().__init__(dut, DutClock("clk"), DutReset("rst"), debug)
15 | self.in_bus = self.driver("in", data_suffix="data")
16 | self.out_bus = self.monitor("out", data_suffix=["data_root", "data_rem"])
17 |
18 | async def verify(self, rad: int):
19 | stimulus = cocotb.start_soon(self.in_bus.enqueue(rad))
20 | out = await self.out_bus.dequeue()
21 | await stimulus
22 |
23 | root = int(out.data_root)
24 | remainder = int(out.data_rem)
25 |
26 | assert rad == root**2 + remainder, f"{rad} != {root} ** 2 + {remainder}"
27 | assert rad < (root + 1) ** 2, "returned root was smaller than expected"
28 |
29 | self.log.debug("radicand=%d got root=%d remainder=%d", rad, root, remainder)
30 |
31 |
32 | @cocotb.test
33 | async def test_sqrt_corners(dut: HierarchyObject, debug=False):
34 | tb = SqrtTb(dut, debug=debug)
35 | await tb.reset()
36 | tb.log.info("DUT: %s", str(dut))
37 | # get bound parameters/generics from the simulator
38 | G_IN_WIDTH = tb.get_int_value("G_IN_WIDTH")
39 | tb.log.info(f"G_IN_WIDTH:{G_IN_WIDTH}")
40 | # await tb.clock_edge
41 | # TODO make sure ranges are within G_IN_WIDTH bits
42 | assert G_IN_WIDTH and G_IN_WIDTH >= 6
43 | testcases = list(range(30)) + list(range(2**G_IN_WIDTH - 70, 2**G_IN_WIDTH))
44 | testcases += list(range(2**G_IN_WIDTH // 2 - 30, 2**G_IN_WIDTH // 2 + 30))
45 | for rad in testcases:
46 | await tb.verify(rad)
47 |
48 | @cocotb.test
49 | async def test_sqrt(dut: HierarchyObject, num_tests: int = NUM_TV, debug=DEBUG):
50 | tb = SqrtTb(dut, debug=debug)
51 | await tb.reset()
52 | # get bound parameters/generics from the simulator
53 | G_IN_WIDTH = tb.get_value("G_IN_WIDTH", int)
54 | tb.log.info("G_IN_WIDTH:%d num_tests:%d", G_IN_WIDTH, num_tests)
55 | # await tb.clock_edge
56 | testcases = [random.getrandbits(G_IN_WIDTH) for _ in range(num_tests)]
57 | testcases = list(set(testcases))
58 | for rad in testcases:
59 | await tb.verify(rad)
60 |
--------------------------------------------------------------------------------
/src/xeda/board.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import os
3 | from typing import Any, Dict, Optional, Union
4 |
5 | from importlib_resources import as_file, files
6 |
7 | from .dataclass import root_validator
8 | from .flow import FPGA, FpgaSynthFlow
9 | from .utils import toml_load
10 |
11 | __all__ = [
12 | "get_board_file_path",
13 | "get_board_data",
14 | "WithFpgaBoardSettings",
15 | ]
16 |
17 | log = logging.getLogger(__name__)
18 |
19 |
20 | def get_board_file_path(file: str):
21 | # FIXME refactor and verify behavior
22 | # return pkg_resources.resource_filename("xeda.data.boards", file)
23 | res = files("xeda.data.boards").joinpath(file)
24 | return as_file(res)
25 |
26 |
27 | def get_board_data(
28 | board: Optional[str], custom_toml_file: Union[None, str, os.PathLike] = None
29 | ) -> Optional[Dict[str, Any]]:
30 | if not board:
31 | return None
32 | boards_data = {}
33 | if custom_toml_file:
34 | log.debug("Retrieving board data for %s from %s", board, custom_toml_file)
35 | boards_data = toml_load(custom_toml_file)
36 | else:
37 | res = files("xeda.data").joinpath("boards.toml")
38 | with as_file(res) as p:
39 | boards_data = toml_load(p)
40 | if boards_data and board in boards_data:
41 | log.info("Retrieved board data for %s", board)
42 | # else:
43 | # log.error(
44 | # "Unable to get resource %s.%s. Please check xeda installation.",
45 | # "xeda.data",
46 | # "boards.toml",
47 | # )
48 | return boards_data.get(board)
49 |
50 |
51 | class WithFpgaBoardSettings(FpgaSynthFlow.Settings):
52 | board: Optional[str] = None
53 | custom_boards_file: Optional[str] = None
54 |
55 | @root_validator(pre=True)
56 | def _fpga_validate(cls, values: Dict[str, Any]) -> Dict[str, Any]:
57 | board_name = values.get("board")
58 | log.debug("_fpga_validate! board_name=%s", board_name)
59 | fpga = values.get("fpga")
60 | if not fpga and board_name:
61 | board_data = get_board_data(board_name)
62 | if board_data:
63 | board_fpga = board_data.get("fpga")
64 | log.info("FPGA info for board %s: %s", board_name, str(board_fpga))
65 | if board_fpga:
66 | if isinstance(board_fpga, str):
67 | board_fpga = {"part": board_fpga}
68 | values["fpga"] = FPGA(**board_fpga)
69 | return values
70 |
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/grid_strategy-M1-M4-M7.tcl:
--------------------------------------------------------------------------------
1 | ####################################
2 | # global connections
3 | ####################################
4 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDD$} -power
5 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDDPE$}
6 | add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDDCE$}
7 | add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {^VSS$} -ground
8 | add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {^VSSE$}
9 | global_connect
10 | ####################################
11 | # voltage domains
12 | ####################################
13 | set_voltage_domain -name {CORE} -power {VDD} -ground {VSS}
14 | ####################################
15 | # standard cell grid
16 | ####################################
17 | define_pdn_grid -name {grid} -voltage_domains {CORE}
18 | add_pdn_stripe -grid {grid} -layer {metal1} -width {0.17} -pitch {2.4} -offset {0} -followpins
19 | add_pdn_stripe -grid {grid} -layer {metal4} -width {0.48} -pitch {56.0} -offset {2}
20 | add_pdn_stripe -grid {grid} -layer {metal7} -width {1.40} -pitch {40.0} -offset {2}
21 | add_pdn_connect -grid {grid} -layers {metal1 metal4}
22 | add_pdn_connect -grid {grid} -layers {metal4 metal7}
23 | ####################################
24 | # macro grids
25 | ####################################
26 | ####################################
27 | # grid for: CORE_macro_grid_1
28 | ####################################
29 | define_pdn_grid -name {CORE_macro_grid_1} -voltage_domains {CORE} -macro -orient {R0 R180 MX MY} -halo {2.0 2.0 2.0 2.0} -cells {.*}
30 | add_pdn_stripe -grid {CORE_macro_grid_1} -layer {metal5} -width {0.93} -pitch {10.0} -offset {2}
31 | add_pdn_stripe -grid {CORE_macro_grid_1} -layer {metal6} -width {0.93} -pitch {10.0} -offset {2}
32 | add_pdn_connect -grid {CORE_macro_grid_1} -layers {metal4 metal5}
33 | add_pdn_connect -grid {CORE_macro_grid_1} -layers {metal5 metal6}
34 | add_pdn_connect -grid {CORE_macro_grid_1} -layers {metal6 metal7}
35 | ####################################
36 | # grid for: CORE_macro_grid_2
37 | ####################################
38 | define_pdn_grid -name {CORE_macro_grid_2} -voltage_domains {CORE} -macro -orient {R90 R270 MXR90 MYR90} -halo {2.0 2.0 2.0 2.0} -cells {.*}
39 | add_pdn_stripe -grid {CORE_macro_grid_2} -layer {metal6} -width {0.93} -pitch {40.0} -offset {2}
40 | add_pdn_connect -grid {CORE_macro_grid_2} -layers {metal4 metal6}
41 | add_pdn_connect -grid {CORE_macro_grid_2} -layers {metal6 metal7}
42 |
--------------------------------------------------------------------------------
/src/xeda/platforms/nangate45/fakeram.cfg:
--------------------------------------------------------------------------------
1 | # config file to drive BSG Black-box SRAM Generator
2 | # https://github.com/bespoke-silicon-group/bsg_fakeram.git
3 | # using cherry's fork to fix bugs
4 | # https://github.com/jjcherry56/bsg_fakeram.git nangate45 branch
5 | {
6 | # The process node. This is used to tell cacti what technology to use when
7 | # estimating power, performance and area numbers.
8 | "tech_nm": 45,
9 |
10 | # The operating voltage.
11 | "voltage": 1.1,
12 |
13 | # String to add in front of every metal layer number for the layer name.
14 | "metalPrefix": "metal",
15 |
16 | # The pin width for signal pins.
17 | "pinWidth_nm": 70,
18 |
19 | # The minimum pin pitch for signal pins (all pins will have a pitch that is a
20 | # multuple of this pitch. The first pin will be a multiple of this pitch from
21 | # the bottom edge of the macro too.
22 | "pinPitch_nm": 210,
23 |
24 | # Optional: snap the width and height of the sram to a multiple value.
25 | "snapWidth_nm": 190,
26 | "snapHeight_nm": 1400,
27 |
28 | # swap width and height to match existing aspect ratio
29 | "swapWidthHeight": true,
30 |
31 | # Flips the pin orientations. Non-fliped assumes metal1 is vertical therefore
32 | # supply pins on metal4 will be horizontal and signal pins will also be on
33 | # metal4. If set to true, supply pins on metal4 will be vertical and signal
34 | # pins will be on metal3.
35 | "flipPins": true,
36 |
37 | "libertyTimeUnit": "ns",
38 | "libertyCapUnit": "ff",
39 | "libertyPowerUnit": "nw",
40 |
41 | # List of SRAM configurations (name, width, depth, and banks)
42 | "srams": [
43 | {"name": "fakeram45_1024x32", "width": 32, "depth": 1024, "banks": 1},
44 | {"name": "fakeram45_2048x39", "width": 39, "depth": 2048, "banks": 1},
45 | {"name": "fakeram45_256x34", "width": 34, "depth": 256, "banks": 1},
46 | {"name": "fakeram45_256x95", "width": 95, "depth": 256, "banks": 1},
47 | {"name": "fakeram45_256x96", "width": 96, "depth": 256, "banks": 1},
48 | {"name": "fakeram45_32x64", "width": 64, "depth": 32, "banks": 1},
49 | {"name": "fakeram45_512x64", "width": 64, "depth": 512, "banks": 1},
50 | {"name": "fakeram45_64x15", "width": 15, "depth": 64, "banks": 1},
51 | {"name": "fakeram45_64x21", "width": 21, "depth": 64, "banks": 1},
52 | {"name": "fakeram45_64x32", "width": 32, "depth": 64, "banks": 1},
53 | {"name": "fakeram45_64x7", "width": 7, "depth": 64, "banks": 1},
54 | {"name": "fakeram45_64x96", "width": 96, "depth": 64, "banks": 1}
55 | ]
56 | }
57 |
--------------------------------------------------------------------------------
/docs/quickstart.rst:
--------------------------------------------------------------------------------
1 | Quickstart
2 | ==========
3 |
4 | .. OUTDATED FIXME
5 |
6 | To get started with xeda, first create a ``xedaproject.toml`` file for your design.
7 | This file contains metadata, list of source files, and flow settings regarding
8 | your design. Below is an example ``xedaproject.toml`` which can be adapted to any design.
9 |
10 | Checkout the xedaproject_ section for the detailed structure of the file.
11 |
12 | .. TODO add xedaproject.toml breakdown
13 |
14 |
15 | .. code-block:: toml
16 |
17 | [project]
18 | name = "Project1"
19 | description = "My Project with 2 designs"
20 |
21 | [[design]]
22 | name = 'Design1'
23 | [design.rtl]
24 | sources = [
25 | 'src_rtl/module1.vhd',
26 | 'src_rtl/top.v'
27 | ]
28 | top = 'Top'
29 | clock = 'clk'
30 | [design.tb]
31 | sources = [
32 | 'top_tb.vhd',
33 | ]
34 | top = 'TopTB'
35 |
36 |
37 |
38 | After the ``xedaproject.toml`` file has been created for your design, you can now use xeda to generate simulation, synthesis and implementation results for your design using the supported tool of your choice.
39 |
40 | For example, if we want to simulate the above design with GHDL, we would run
41 |
42 | .. code-block:: bash
43 |
44 | $ xeda ghdl_sim
45 |
46 | If we are satisfied with the results of the simulation, we can have xeda synthesis and implement our design. For example, with Xilinx Vivado:
47 |
48 | .. code-block:: bash
49 |
50 | $ xeda vivado_synth
51 |
52 | If multiple ``[[design]]`` entries are present, the active design needs be specified using ``--design`` flag
53 |
54 | That's it! That's all xeda requires to simulate, synthesis, and implement an HDL design.
55 |
56 | As always, you can run ``xeda --help`` for the full list of arguments.
57 |
58 |
59 | xedaproject
60 | -----------
61 | Settings:
62 |
63 | - ``project``
64 | - ``design`` can be a list of multiple TOML tables, must use ``[[design]]`` instead of ``[design]``
65 | - ``name``: a string that designates a name for this design. Recommended to avoid any whitespace.
66 | - ``rtl``
67 | - ``sources``: a list of HDL files used for synthesis and simulation
68 | - ``top``: syntehsis top entity/module
69 | - ``tb``
70 | - ``sources``: a list of testbench files used for simulation only
71 | - ``top``: simulation top entity/module/function
72 | - ``flows``
73 |
74 | The sub-tables may include optional entries referenced only by a particular plugin.
75 | E.g., ``design.lwc`` is used by ``lwc`` plugins.
76 |
77 |
78 | bash-completion
79 | ---------------
80 |
81 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/openlane/asap7sc7p5t/config.tcl:
--------------------------------------------------------------------------------
1 | set current_folder [file dirname [file normalize [info script]]]
2 | # Technology lib
3 |
4 | set libs_ref "$::env(PDK_ROOT)/$::env(PDK)/libs.ref/$::env(STD_CELL_LIBRARY)"
5 |
6 | set libs_tech "$::env(PDK_ROOT)/$::env(PDK)/libs.tech"
7 |
8 | set ::env(LIB_FASTEST) ""
9 | set ::env(LIB_TYPICAL) ""
10 | set ::env(LIB_SLOWEST) ""
11 |
12 | set lib_path "$libs_ref/lib"
13 | foreach lib {"AO" "INVBUF" "OA" "SEQ" "SIMPLE"} {
14 | append ::env(LIB_FASTEST) "$lib_path/asap7sc7p5t_${lib}_RVT_FF_nldm_201020.lib "
15 | append ::env(LIB_TYPICAL) "$lib_path/asap7sc7p5t_${lib}_RVT_TT_nldm_201020.lib "
16 | append ::env(LIB_SLOWEST) "$lib_path/asap7sc7p5t_${lib}_RVT_SS_nldm_201020.lib "
17 | }
18 |
19 | set ::env(LIB_SYNTH) $::env(LIB_TYPICAL)
20 | set ::env(LIB_RESIZER_OPT) $::env(LIB_SYNTH)
21 |
22 | set ::env(DFF_LIB_SYNTH) "$lib_path/asap7sc7p5t_SEQ_RVT_TT_nldm_201020.lib"
23 |
24 | set ::env(LIB_CTS) $::env(LIB_TYPICAL)
25 |
26 | # Placement site for core cells
27 | # This can be found in the technology lef
28 | set ::env(PLACE_SITE) "asap7sc7p5t"
29 | set ::env(PLACE_SITE_WIDTH) 0.054
30 | set ::env(PLACE_SITE_HEIGHT) 0.270
31 |
32 | # welltap and endcap cells
33 | set ::env(FP_WELLTAP_CELL) "TAPCELL_ASAP7_75t_R"
34 | set ::env(FP_ENDCAP_CELL) "TAPCELL_ASAP7_75t_R"
35 |
36 | # defaults (can be overridden by designs):
37 | set ::env(SYNTH_DRIVING_CELL) "BUFx2_ASAP7_75t_R"
38 | set ::env(SYNTH_DRIVING_CELL_PIN) "Y"
39 | set ::env(SYNTH_CAP_LOAD) "4.61057" ; # femtofarad INVx8_ASAP7_75t_R pin A cap
40 | set ::env(SYNTH_MIN_BUF_PORT) "BUFx2_ASAP7_75t_R A Y"
41 | set ::env(SYNTH_TIEHI_PORT) "TIEHIx1_ASAP7_75t_R H"
42 | set ::env(SYNTH_TIELO_PORT) "TIELOx1_ASAP7_75t_R L"
43 |
44 | # cts defaults
45 | set ::env(CTS_ROOT_BUFFER) BUFx4_ASAP7_75t_R
46 | set ::env(CELL_CLK_PORT) CLK
47 |
48 | # Placement defaults
49 | set ::env(PL_LIB) $::env(LIB_TYPICAL)
50 |
51 | # Fillcell insertion
52 | set ::env(FILL_CELL) "FILLERxp5_ASAP7_75t_R"
53 | set ::env(DECAP_CELL) "DECAPx1_ASAP7_75t_R"
54 | set ::env(RE_BUFFER_CELL) ""
55 |
56 | set ::env(CELL_PAD) 2
57 | set ::env(CELL_PAD_EXCLUDE) ""
58 |
59 | # Clk Buffers info CTS data
60 | set ::env(ROOT_CLK_BUFFER) BUFx4_ASAP7_75t_R
61 | set ::env(CLK_BUFFER) BUFx4_ASAP7_75t_R
62 | set ::env(CLK_BUFFER_INPUT) A
63 | set ::env(CLK_BUFFER_OUTPUT) Y
64 | set ::env(CTS_CLK_BUFFER_LIST) "BUFx4_ASAP7_75t_R"
65 | set ::env(FP_PDN_RAIL_WIDTH) 0.48
66 | # Determined from BUFx24_ASAP7_75t_R
67 | set ::env(CTS_MAX_CAP) 1474.56
68 | set ::env(DEFAULT_MAX_TRAN) 320
69 |
70 | set ::env(PDN_CFG) "$::env(PDK_ROOT)/$::env(PDK)/libs.tech/openlane/$::env(STD_CELL_LIBRARY)/grid_strategy-M1-M2-M5-M6.cfg"
71 |
--------------------------------------------------------------------------------
/src/xeda/flows/openroad/templates/resynth.tcl:
--------------------------------------------------------------------------------
1 | {% if settings.resynth_for_timing %}
2 | repair_design
3 | repair_timing
4 | # pre restructure area/timing report (ideal clocks)
5 | puts "Post synth-opt area"
6 | report_design_area
7 | report_worst_slack -min -digits 3
8 | puts "Post synth-opt wns"
9 | report_worst_slack -max -digits 3
10 | puts "Post synth-opt tns"
11 | report_tns -digits 3
12 |
13 | if {![info exists save_checkpoint] || $save_checkpoint} {
14 | write_verilog {{settings.results_dir}}/{{step_id}}_pre_abc_timing.v
15 | }
16 |
17 | restructure -target timing -liberty_file {{merged_lib_file}} \
18 | -work_dir {{settings.results_dir}}
19 |
20 | if {![info exists save_checkpoint] || $save_checkpoint} {
21 | write_verilog {{settings.results_dir}}/{{step_id}}_post_abc_timing.v
22 | }
23 |
24 | # post restructure area/timing report (ideal clocks)
25 | remove_buffers
26 | repair_design
27 | repair_timing
28 |
29 | puts "Post restructure-opt wns"
30 | report_worst_slack -max -digits 3
31 | puts "Post restructure-opt tns"
32 | report_tns -digits 3
33 |
34 | # remove buffers inserted by optimization
35 | remove_buffers
36 | {% endif %}
37 |
38 | {% if settings.resynth_for_area %}
39 | set num_instances [llength [get_cells -hier *]]
40 | puts "number instances before restructure is $num_instances"
41 | puts "Design Area before restructure"
42 | report_design_area
43 | report_design_area_metrics
44 |
45 | if {![info exists save_checkpoint] || $save_checkpoint} {
46 | write_verilog {{settings.results_dir}}/{{step_id}}_pre_abc.v
47 | }
48 |
49 | set tielo_cell_name {{platform.tielo_cell}}
50 | set tielo_lib_name [get_name [get_property [lindex [get_lib_cell $tielo_cell_name] 0] library]]
51 | set tielo_port $tielo_lib_name/$tielo_cell_name/{{platform.tielo_port}}
52 |
53 | set tiehi_cell_name {{platform.tiehi_cell}}
54 | set tiehi_lib_name [get_name [get_property [lindex [get_lib_cell $tiehi_cell_name] 0] library]]
55 | set tiehi_port $tiehi_lib_name/$tiehi_cell_name/{{platform.tiehi_port}}
56 |
57 | restructure -liberty_file {{merged_lib_file}} -target "area" \
58 | -tiehi_port $tiehi_port \
59 | -tielo_port $tielo_port \
60 | -work_dir {{settings.results_dir}}
61 |
62 | # remove buffers inserted by abc
63 | remove_buffers
64 |
65 | if {![info exists save_checkpoint] || $save_checkpoint} {
66 | write_verilog {{settings.results_dir}}/{{step_id}}_post_abc.v
67 | }
68 | set num_instances [llength [get_cells -hier *]]
69 | puts "number instances after restructure is $num_instances"
70 | puts "Design Area after restructure"
71 | report_design_area
72 | report_design_area_metrics
73 | {% endif %}
74 |
75 | report_metrics "after resynth" false false
76 |
77 | {{ write_checkpoint(step) }}
78 |
--------------------------------------------------------------------------------
/src/xeda/flows/vivado/vivado_postsynthsim.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | from ...design import DesignSource, RtlSettings
4 | from ...flow import FlowFatalError
5 | from ...utils import SDF
6 | from .vivado_sim import VivadoSim
7 | from .vivado_synth import VivadoSynth
8 |
9 | log = logging.getLogger(__name__)
10 |
11 |
12 | class VivadoPostsynthSim(VivadoSim):
13 | """
14 | Synthesizes & implements the design, then runs post-synthesis/post-implementation simulation on the generated netlist.
15 | The netlist can be optionally annotated with generated timing information (SDF).
16 | Depends on VivadoSynth
17 | """
18 |
19 | class Settings(VivadoSim.Settings):
20 | synth: VivadoSynth.Settings
21 | timing_sim: bool = False
22 |
23 | def init(self) -> None:
24 | ss = self.settings
25 | assert isinstance(ss, self.Settings)
26 |
27 | ss.synth.write_netlist = True
28 | self.add_dependency(VivadoSynth, ss.synth)
29 |
30 | def run(self) -> None:
31 | synth_flow = self.completed_dependencies[0]
32 | assert isinstance(synth_flow, VivadoSynth)
33 | ss = self.settings
34 | assert isinstance(ss, self.Settings)
35 |
36 | artifacts_path = synth_flow.run_path / synth_flow.settings.outputs_dir / "route_design"
37 | synth_netlist_path = artifacts_path / "timesim.v"
38 | if not synth_netlist_path.exists():
39 | raise FlowFatalError(f"Netlist {synth_netlist_path} does not exist!")
40 | postsynth_sources = [DesignSource(synth_netlist_path)]
41 | log.info("Setting post-synthesis sources to: %s", postsynth_sources)
42 | # also removing top-level generics and everything else
43 | self.design.rtl = RtlSettings(
44 | top=self.design.rtl.top, sources=postsynth_sources, attributes={}
45 | )
46 | assert self.design.tb and self.design.tb.top
47 | self.design.tb.top = (self.design.tb.top[0], "glbl")
48 |
49 | if "simprims_ver" not in ss.lib_paths:
50 | ss.lib_paths.append(("simprims_ver", None))
51 |
52 | if ss.timing_sim:
53 | if not ss.sdf.delay_items():
54 | ss.sdf = SDF(max=str(artifacts_path / "timesim.max.sdf"))
55 | if not ss.sdf.root:
56 | ss.sdf.root = self.design.tb.uut
57 | log.info("Timing simulation using SDF %s", ss.sdf)
58 |
59 | ss.elab_flags.extend(
60 | [
61 | "-maxdelay",
62 | "-transport_int_delays",
63 | "-pulse_r 0",
64 | "-pulse_int_r 0",
65 | "-pulse_e 0",
66 | "-pulse_int_e 0",
67 | ]
68 | )
69 | # run VivadoSim
70 | super().run()
71 |
--------------------------------------------------------------------------------
/tests/test_vivado.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 | import tempfile
4 | from pathlib import Path
5 |
6 | from xeda import Design
7 | from xeda.flow import FPGA
8 | from xeda.flow_runner import DefaultRunner
9 | from xeda.flows import VivadoSynth
10 | from xeda.flows.vivado.vivado_synth import parse_hier_util, vivado_synth_generics
11 |
12 | TESTS_DIR = Path(__file__).parent.absolute()
13 | RESOURCES_DIR = TESTS_DIR / "resources"
14 | EXAMPLES_DIR = TESTS_DIR.parent / "examples"
15 |
16 |
17 | def test_vivado_synth_template() -> None:
18 | design = Design.from_toml(RESOURCES_DIR / "design0/design0.toml")
19 | settings = VivadoSynth.Settings(fpga=FPGA(part="abcd"), clock_period=5.5) # type: ignore
20 | run_dir = Path.cwd() / "vivado_synth_run"
21 | run_dir.mkdir(exist_ok=True)
22 | flow = VivadoSynth(settings, design, run_dir) # type: ignore
23 | tcl_file = flow.copy_from_template(
24 | "vivado_synth.tcl",
25 | xdc_files=[],
26 | tcl_files=[],
27 | generics=vivado_synth_generics(design.rtl.parameters),
28 | )
29 | with open(run_dir / tcl_file) as f:
30 | vivado_tcl = f.read()
31 | expected_lines = [
32 | """set_property generic {G_IN_WIDTH=32 G_ITERATIVE=1'b1 G_STR=\\"abcd\\" G_BITVECTOR=7'b0101001} [current_fileset]""",
33 | ]
34 | for line in expected_lines:
35 | assert line in vivado_tcl
36 |
37 |
38 | def test_vivado_synth_py() -> None:
39 | # Append to PATH so if the actual tool exists, would take precedences.
40 | os.environ["PATH"] = (
41 | os.path.join(TESTS_DIR, "fake_tools") + os.pathsep + os.environ.get("PATH", "")
42 | )
43 | design = Design.from_toml(EXAMPLES_DIR / "vhdl" / "sqrt" / "sqrt.toml")
44 | settings = dict(fpga=FPGA("xc7a12tcsg325-1"), clock_period=5.5)
45 | with tempfile.TemporaryDirectory(dir=Path.cwd()) as run_dir:
46 | print("Xeda run dir: ", run_dir)
47 | xeda_runner = DefaultRunner(run_dir, debug=True)
48 | flow = xeda_runner.run_flow(VivadoSynth, design, settings)
49 | assert flow is not None, "run_flow returned None"
50 | settings_json = flow.run_path / "settings.json"
51 | results_json = flow.run_path / "results.json"
52 | assert settings_json.exists()
53 | assert results_json.exists()
54 | assert flow.succeeded
55 | assert 0.3 < flow.results.runtime # type: ignore
56 |
57 |
58 | def test_parse_hier_util() -> None:
59 | d = parse_hier_util("tests/resources/vivado_synth/hierarchical_utilization.xml")
60 | # print(json.dumps(d, indent=2))
61 | with open("hier.json", "w") as f:
62 | json.dump(d, f, indent=4)
63 | assert d
64 |
65 |
66 | if __name__ == "__main__":
67 | # test_vivado_synth_py()
68 | test_parse_hier_util()
69 |
--------------------------------------------------------------------------------
/src/xeda/units.py:
--------------------------------------------------------------------------------
1 | import re
2 | from typing import Optional, Union
3 |
4 | from pint import UnitRegistry
5 |
6 | unit_registry = UnitRegistry(case_sensitive=False)
7 | Q_ = unit_registry.Quantity
8 |
9 |
10 | def unit_maybe_scale(unit: str):
11 | unit = unit.strip()
12 | scale = None
13 | m = re.match(r"(\d*\.?\d*)\s*(\w+)", unit)
14 | if m:
15 | sc = m.group(1)
16 | if sc and sc != "1":
17 | scale = float(sc)
18 | unit = m.group(2)
19 | if unit == "ps":
20 | unit = "picoseconds"
21 | if unit == "ns":
22 | unit = "nanoseconds"
23 | if unit == "ms":
24 | unit = "milliseconds"
25 | if unit == "us":
26 | unit = "microseconds"
27 | return unit, scale
28 |
29 |
30 | def convert_unit(
31 | value,
32 | to_unit,
33 | from_unit=None,
34 | ) -> float:
35 | try:
36 | value = float(value)
37 | except ValueError:
38 | pass
39 | from_scale = None
40 | to_scale = None
41 | if from_unit:
42 | from_unit, from_scale = unit_maybe_scale(from_unit)
43 | to_unit, to_scale = unit_maybe_scale(to_unit)
44 | if from_unit and isinstance(value, (float, int)):
45 | value = Q_(value, from_unit).to(to_unit).m
46 | elif isinstance(value, str):
47 | value = Q_(value).to(to_unit).m
48 | if from_scale:
49 | value *= from_scale
50 | if to_scale:
51 | value /= to_scale
52 | return float(value)
53 |
54 |
55 | def convert_freq(f: Union[str, float, int], target_unit="MHz") -> float:
56 | return convert_unit(f, target_unit)
57 |
58 |
59 | def freq_mhz_optional(
60 | f: Union[str, float, int, None], target_unit="MHz", require_positive=True, optional=True
61 | ) -> Optional[float]:
62 | if f is None:
63 | if optional:
64 | return f
65 | raise ValueError("Value is required")
66 | f = convert_freq(f, target_unit)
67 | if require_positive and f <= 0:
68 | raise ValueError("Value should be positive")
69 | return f
70 |
71 |
72 | def convert_time(
73 | f: Union[str, float, int],
74 | target_unit="ns",
75 | ) -> float:
76 | return convert_unit(f, target_unit)
77 |
78 |
79 | def time_ns_optional(
80 | f: Union[str, float, int, None],
81 | target_unit="ns",
82 | require_non_negative=True,
83 | require_non_zero=False,
84 | optional=True,
85 | ) -> Optional[float]:
86 | if f is None:
87 | if optional:
88 | return f
89 | raise ValueError("Value is required")
90 | f = convert_time(f, target_unit)
91 | if require_non_zero and f == 0:
92 | raise ValueError("Value should be non-zero")
93 | if require_non_negative and f < 0:
94 | raise ValueError("Value should be non-negative")
95 | return f
96 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # IDE folders
2 | .vscode/
3 |
4 | # Byte-compiled / optimized / DLL files
5 | __pycache__/
6 | *.py[cod]
7 | *$py.class
8 |
9 | # C extensions
10 | *.so
11 |
12 | # Distribution / packaging
13 | .Python
14 | build/
15 | develop-eggs/
16 | dist/
17 | downloads/
18 | eggs/
19 | .eggs/
20 | /lib/
21 | lib64/
22 | parts/
23 | sdist/
24 | var/
25 | wheels/
26 | share/python-wheels/
27 | *.egg-info/
28 | .installed.cfg
29 | *.egg
30 | MANIFEST
31 |
32 | # PyInstaller
33 | # Usually these files are written by a python script from a template
34 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
35 | *.manifest
36 | *.spec
37 |
38 | # Installer logs
39 | pip-log.txt
40 | pip-delete-this-directory.txt
41 |
42 | # Unit test / coverage reports
43 | htmlcov/
44 | .tox/
45 | .nox/
46 | .coverage
47 | .coverage.*
48 | .cache
49 | nosetests.xml
50 | coverage.xml
51 | *.cover
52 | *.py,cover
53 | .hypothesis/
54 | .pytest_cache/
55 | cover/
56 |
57 | # Translations
58 | *.mo
59 | *.pot
60 |
61 | # Django stuff:
62 | *.log
63 | local_settings.py
64 | db.sqlite3
65 | db.sqlite3-journal
66 |
67 | # Flask stuff:
68 | instance/
69 | .webassets-cache
70 |
71 | # Scrapy stuff:
72 | .scrapy
73 |
74 | # Sphinx documentation
75 | docs/_build/
76 |
77 | # PyBuilder
78 | .pybuilder/
79 | target/
80 |
81 | # Jupyter Notebook
82 | .ipynb_checkpoints
83 |
84 | # IPython
85 | profile_default/
86 | ipython_config.py
87 |
88 | # pyenv
89 | # For a library or package, you might want to ignore these files since the code is
90 | # intended to run in multiple environments; otherwise, check them in:
91 | # .python-version
92 |
93 | # pipenv
94 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
96 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
97 | # install all needed dependencies.
98 | #Pipfile.lock
99 |
100 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
101 | __pypackages__/
102 |
103 | # Celery stuff
104 | celerybeat-schedule
105 | celerybeat.pid
106 |
107 | # SageMath parsed files
108 | *.sage.py
109 |
110 | # Environments
111 | .env
112 | .venv
113 | env/
114 | venv/
115 | ENV/
116 | env.bak/
117 | venv.bak/
118 |
119 | # Spyder project settings
120 | .spyderproject
121 | .spyproject
122 |
123 | # Rope project settings
124 | .ropeproject
125 |
126 | # mkdocs documentation
127 | /site
128 |
129 | # mypy
130 | .mypy_cache/
131 | .dmypy.json
132 | dmypy.json
133 |
134 | # Pyre type checker
135 | .pyre/
136 |
137 | # pytype static type analyzer
138 | .pytype/
139 |
140 | # Cython debug symbols
141 | cython_debug/
142 |
143 |
--------------------------------------------------------------------------------
/src/xeda/flows/ise/templates/ise_synth.tcl:
--------------------------------------------------------------------------------
1 |
2 | ## Automatically generated by Xeda
3 | ## ISE 14.7
4 |
5 | puts "\n==============================( Creating Project )================================"
6 | if { [catch { project new {{design.name}} }] } {
7 | project open {{design.name}}
8 | }
9 | {% if settings.fpga.family %}
10 | project set family {{settings.fpga.family}}
11 | {% endif %}
12 | {% if settings.fpga.device %}
13 | project set device {{settings.fpga.device}}
14 | {% endif %}
15 | {% if settings.fpga.package %}
16 | project set package {{settings.fpga.package}}
17 | {% endif %}
18 | {% if settings.fpga.speed %}
19 | project set speed "-{{settings.fpga.speed}}"
20 | {% endif %}
21 |
22 | project set "Generate Detailed MAP Report" TRUE
23 |
24 |
25 | puts "\n==============================( Adding RTL Sources )================================"
26 | {% for src in design.rtl.sources %}
27 | xfile add {{src.file}} -copy
28 | {%- endfor %}
29 |
30 | {% if design.rtl.top %}
31 | project set top {{design.rtl.top}}
32 | {% else %}
33 | project set "Auto Implementation Top" TRUE
34 | {% endif %}
35 |
36 | puts "\n==============================( Adding Constraint Files )================================"
37 | {% for ucf_file in settings.ucf_files %}
38 | if { [catch { xfile add {{ucf_file}} }] } {
39 | puts "unable to add {{ucf_file}}"
40 | }
41 | {% endfor %}
42 |
43 | {% if settings.xcf_file %}
44 | project set "Use Synthesis Constraints File" TRUE
45 | project set "Synthesis Constraints File" "{{settings.xcf_file}}"
46 | {% endif %}
47 |
48 | # puts [project properties] # to see the full list of properties
49 |
50 | puts "\n==============================( Setting Options )================================"
51 | {% if settings.nthreads is not none %}
52 | project set "Enable Multi-Threading" {{2 if settings.nthreads and settings.nthreads > 1 else "Off"}} -process "MAP"
53 | project set "Enable Multi-Threading" {{[settings.nthreads, 4]|min if settings.nthreads and settings.nthreads > 1 else "Off"}} -process "Place & Route"
54 | {% endif %}
55 |
56 | {% for k, v in settings.translate_options.items() %}
57 | project set "{{k}}" {{v}} -process "Translate"
58 | {% endfor %}
59 | {% for k, v in settings.synthesis_options.items() %}
60 | project set "{{k}}" {{v}} -process "Synthesize - XST"
61 | {% endfor %}
62 | {% for k, v in settings.map_options.items() %}
63 | project set "{{k}}" {{v}} -process "Map"
64 | {% endfor %}
65 | {% for k, v in settings.pnr_options.items() %}
66 | project set "{{k}}" {{v}} -process "Place & Route"
67 | {% endfor %}
68 | {% for k, v in settings.trace_options.items() %}
69 | project set "{{k}}" {{v}} -process "Generate Post-Place & Route Static Timing"
70 | {% endfor %}
71 |
72 |
73 | puts "\n==============================( Implementing Design )================================"
74 |
75 | process run "Implement Design"
76 |
77 | # project close
78 |
79 |
--------------------------------------------------------------------------------
/get_oss_cad_suite.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # pip install progressbar
4 | import progressbar
5 |
6 | import json
7 | import pprint
8 | import urllib.request
9 | import platform
10 | from pathlib import Path
11 | from shutil import unpack_archive, rmtree
12 |
13 | system = platform.system().lower()
14 | arch = platform.machine().lower()
15 |
16 | if arch == "x86_64" or arch == "amd64":
17 | arch = "x64"
18 | elif arch == "aarch64":
19 | arch = "arm64"
20 |
21 | # print("platform=", platform.platform())
22 | print(system, arch)
23 |
24 | repo = "YosysHQ/oss-cad-suite-build"
25 |
26 | _json = json.loads(
27 | urllib.request.urlopen(
28 | urllib.request.Request(
29 | f"https://api.github.com/repos/{repo}/releases/latest",
30 | headers={"Accept": "application/vnd.github.v3+json"},
31 | )
32 | ).read()
33 | )
34 |
35 | assets = _json["assets"]
36 |
37 | asset_ext = "tgz" if system in ["linux", "darwin"] else "zip"
38 |
39 | assets = [
40 | asset
41 | for asset in assets
42 | if asset["name"].endswith(asset_ext) and f"{system}-{arch}" in asset["name"]
43 | ]
44 |
45 | if not assets:
46 | print(f"No suitable asset found for {system}-{arch}.")
47 | exit(1)
48 |
49 | asset = assets[0]
50 | # pprint.pprint(asset)
51 | name = asset["name"]
52 | size = asset["size"]
53 | updated_at = asset["updated_at"]
54 | url = asset["browser_download_url"]
55 |
56 |
57 | class MyProgressBar:
58 | def __init__(self):
59 | self.pbar = None
60 |
61 | def __call__(self, block_num, block_size, total_size):
62 | if not self.pbar:
63 | self.pbar = progressbar.ProgressBar(maxval=total_size)
64 | self.pbar.start()
65 |
66 | downloaded = block_num * block_size
67 | if downloaded < total_size:
68 | self.pbar.update(downloaded)
69 | else:
70 | self.pbar.finish()
71 |
72 |
73 | archive_file = Path(name)
74 | if archive_file.exists() and archive_file.stat().st_size == size:
75 | print(f"using previously downloaded {archive_file}...")
76 | else:
77 | print(f"Downloading {name} ({size} Bytes) from {url}...")
78 | urllib.request.urlretrieve(url, name, MyProgressBar())
79 |
80 |
81 | target_dir = Path.home() / ".xeda" / "tools"
82 |
83 | # content of the archive
84 | target_subdir = target_dir / "oss-cad-suite"
85 |
86 | if target_dir.exists():
87 | if target_subdir.exists():
88 | print(f"Removing existing installation at {target_subdir}...")
89 | rmtree(target_subdir)
90 | else:
91 | target_dir.mkdir(parents=True)
92 |
93 | print(f"Unpacking {name} to {target_subdir}...")
94 | unpack_archive(name, target_dir)
95 |
96 | assert target_subdir.exists() and target_subdir.is_dir()
97 | bin_dir = target_subdir / "bin"
98 | assert bin_dir.exists() and bin_dir.is_dir()
99 | print(f"Installation complete. Add {bin_dir} to your PATH.")
100 |
--------------------------------------------------------------------------------
/src/xeda/flows/yosys/templates/yosys_synth.tcl:
--------------------------------------------------------------------------------
1 | yosys logger -notime -stderr
2 | {% include 'read_files.tcl' %}
3 |
4 | {% if settings.prep is not none %}
5 | prep {% if settings.flatten %} -flatten {% endif %} {%if design.rtl.top %} -top {{design.rtl.top}} {% else %} -auto-top {% endif %} {{settings.prep|join(" ")}}
6 | {%- else %}
7 | procs
8 | {%- if settings.flatten %}
9 | flatten
10 | {%- endif %}
11 | {%- endif %}
12 |
13 | {% include "post_rtl.tcl" %}
14 |
15 | {%- if not settings.nosynth %}
16 | log -stdout "Running synthesis"
17 | synth {{settings.synth_flags|join(" ")}} {% if design.rtl.top %} -top {{design.rtl.top}}{% endif %} {%- if settings.noabc %} -noabc {%- endif %}
18 | {%- endif %}
19 |
20 | {#- TODO: ##### LSOracle ###### #}
21 |
22 | {%- if settings.post_synth_opt %}
23 | log -stdout "Post-synth optimization"
24 | opt -full -purge -sat
25 | {%- else %}
26 | opt -purge
27 | {%- endif %}
28 |
29 | {%- if settings.adder_map %}
30 | extract_fa
31 | techmap -map {{settings.adder_map}}
32 | techmap
33 | opt -purge
34 | {%- endif %}
35 |
36 | {%- for map in settings.other_maps %}
37 | techmap -map {{map}}
38 | {%- endfor %}
39 |
40 | {%- if settings.liberty %}
41 | log -stdout "Prepare mapping FFs to technology"
42 | dfflibmap -prepare -liberty {% if settings.dff_liberty -%} {{settings.dff_liberty}} {%- else -%} {{settings.liberty[0]}} {%- endif %}
43 | opt -purge
44 | {%- endif %}
45 |
46 | {%- if not settings.noabc %}
47 | log -stdout "Running ABC"
48 | abc {{settings.abc_flags|join(" ")}}
49 | {%- if settings.main_clock and settings.main_clock.period_ps %} -D {{"%.3f"|format(settings.main_clock.period_ps)}} {% endif %}
50 | {%- if settings.abc_script %} -script "{{settings.abc_script}}" {%- endif %}
51 | {%- if settings.liberty %} -liberty "{{settings.liberty[0]}}" {%- endif %}
52 | {%- if abc_constr_file %} -constr "{{abc_constr_file}}" {%- endif %}
53 | opt -purge
54 | {%- endif %}
55 |
56 | {%- if settings.liberty %}
57 | log -stdout "Mapping FFs to technology"
58 | dfflibmap -liberty {% if settings.dff_liberty -%} {{settings.dff_liberty}} {%- else -%} {{settings.liberty[0]}} {%- endif %}
59 | opt -purge
60 | {%- endif %}
61 |
62 | # replace undefined values with 0
63 | setundef -zero
64 | opt -full -purge
65 |
66 | {%- if settings.splitnets %}
67 | splitnets {%- if settings.splitnets_driver %} -driver {%- endif %} {%- if settings.splitnets_ports %} -ports {%-endif %}
68 | {%- endif %}
69 |
70 | opt_clean -purge
71 |
72 | {%- if settings.hilomap %}
73 | hilomap {% if settings.hilomap.singleton %} -singleton {% endif %} -hicell {{settings.hilomap.hi|join(" ")}} -locell {{settings.hilomap.lo|join(" ")}}
74 | {%- endif %}
75 | {% if settings.insbuf %}
76 | insbuf -buf {{settings.insbuf|join(" ")}}
77 | {%- endif %}
78 |
79 | opt -full -purge
80 | clean -purge
81 |
82 | {%- if settings.rmports %}
83 | rmports
84 | {%- endif %}
85 |
86 | {%- if settings.liberty %}
87 | check {% if settings.check_assert -%} -assert {% endif -%} -mapped
88 | {%- endif %}
89 | {% include "write_netlist.tcl" %}
90 |
91 | log -stdout "***** Synthesis Completed *****"
92 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ "main" ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ "main" ]
20 | schedule:
21 | - cron: '18 21 * * 1'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'python' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
38 |
39 | steps:
40 | - name: Checkout repository
41 | uses: actions/checkout@v3
42 |
43 | # Initializes the CodeQL tools for scanning.
44 | - name: Initialize CodeQL
45 | uses: github/codeql-action/init@v2
46 | with:
47 | languages: ${{ matrix.language }}
48 | # If you wish to specify custom queries, you can do so here or in a config file.
49 | # By default, queries listed here will override any specified in a config file.
50 | # Prefix the list here with "+" to use these queries and those in the config file.
51 |
52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
53 | # queries: security-extended,security-and-quality
54 |
55 |
56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
57 | # If this step fails, then you should remove it and run the build manually (see below)
58 | - name: Autobuild
59 | uses: github/codeql-action/autobuild@v2
60 |
61 | # ℹ️ Command-line programs to run using the OS shell.
62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
63 |
64 | # If the Autobuild fails above, remove it and uncomment the following three lines.
65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
66 |
67 | # - run: |
68 | # echo "Run, Build Application using script"
69 | # ./location_of_script_within_repo/buildscript.sh
70 |
71 | - name: Perform CodeQL Analysis
72 | uses: github/codeql-action/analyze@v2
73 | with:
74 | category: "/language:${{matrix.language}}"
75 |
--------------------------------------------------------------------------------
/src/xeda/flows/quartus/quartus_dse.py:
--------------------------------------------------------------------------------
1 | # TODO
2 | # class QuartusDse(QuartusSynth, DseFlow):
3 | # def run(self):
4 | # self.create_project()
5 | # # 'explore': Exploration flow to use, if not specified in --config
6 | # # configuration file. Valid flows: timing_aggressive,
7 | # # all_optimization_modes, timing_high_effort, seed,
8 | # # area_aggressive, power_high_effort, power_aggressive
9 | # # 'compile_flow': 'full_compile', 'fit_sta' and 'fit_sta_asm'.
10 | # # 'timeout': Limit the amount of time a compute node is allowed to run. Format: hh:mm:ss
11 | # if 'dse' not in self.settings.flow:
12 | # self.fatal('`flows.quartus.dse` settings are missing!')
13 |
14 | # dse = self.settings.flow['dse']
15 | # if 'nproc' not in dse or not dse['nproc']:
16 | # dse['nproc'] = self.nthreads
17 |
18 | # script_path = self.copy_from_template(f'settings.dse',
19 | # dse=dse
20 | # )
21 | # self.run_process('quartus_dse',
22 | # ['--use-dse-file', script_path, self.settings.design['name']],
23 | # stdout_logfile='dse_stdout.log',
24 | # initial_step="Running Quartus DSE",
25 | # )
26 | # self.run_process('quartus_sh',
27 | # ['--dse', '-project', self.settings.design['name'], '-nogui', '-concurrent-compiles', '8', '-exploration-space',
28 | # "Extra Effort Space", '-optimization-goal', "Optimize for Speed", '-report-all-resource-usage', '-ignore-failed-base'],
29 | # stdout_logfile='dse_stdout.log'
30 | # )
31 | # def quartus_gen_convert(k, x, sim):
32 | # if sim:
33 | # if isinstance(x, dict) and "file" in x:
34 | # p = x["file"]
35 | # assert isinstance(p, str), "value of `file` should be a relative or absolute path string"
36 | # x = self.conv_to_relative_path(p.strip())
37 | # self.logger.info(f'Converting generic `{k}` marked as `file`: {p} -> {x}')
38 | # xl = str(x).strip().lower()
39 | # if xl == 'false':
40 | # return "1\\'b0"
41 | # if xl == 'true':
42 | # return "1\\'b1"
43 | # return x
44 |
45 | # self.run_process('quartus_eda', [prj_name, '--simulation', '--functional', '--tool=modelsim_oem', '--format=verilog'],
46 | # stdout_logfile='eda_1_stdout.log'
47 | # )
48 | # DSE:
49 |
50 | # Available exploration spaces for this family are:
51 | # "Seed Sweep"
52 | # "Extra Effort Space"
53 | # "Extra Effort Space for Quartus Prime Integrated Synthesis Projects"
54 | # "Area Optimization Space"
55 | # "Signature: Placement Effort Multiplier"
56 | # "Custom Space"
57 |
58 | # Valid optimization-goal options are:
59 | # "Optimize for Speed"
60 | # "Optimize for Area"
61 | # "Optimize for Power"
62 | # "Optimize for Negative Slack and Failing Paths"
63 | # "Optimize for Average Period"
64 | # "Optimize for Quality of Fit"
65 |
--------------------------------------------------------------------------------
/src/xeda/flows/vivado/vivado_power.py:
--------------------------------------------------------------------------------
1 | import html
2 | import logging
3 | from typing import Any, Dict
4 | from xml.etree import ElementTree
5 |
6 | from .vivado_postsynthsim import VivadoPostsynthSim
7 | from .vivado_sim import VivadoSim
8 | from .vivado_synth import VivadoSynth
9 |
10 | logger = logging.getLogger(__name__)
11 |
12 |
13 | class VivadoPower(VivadoSim):
14 | class Settings(VivadoSim.Settings):
15 | timing_sim: bool = True
16 | elab_debug: str = "typical"
17 | saif: str = "activity.saif"
18 | postsynthsim: VivadoPostsynthSim.Settings
19 | power_report_xml: str = "power_impl_timing.xml"
20 |
21 | def init(self) -> None:
22 | assert self.design.tb, "A testbench is required for power estimation"
23 | ss = self.settings
24 | assert isinstance(ss, self.Settings)
25 | ss.postsynthsim.timing_sim = ss.timing_sim
26 | ss.postsynthsim.elab_debug = ss.elab_debug
27 | ss.postsynthsim.saif = ss.saif
28 | self.add_dependency(VivadoPostsynthSim, ss.postsynthsim)
29 |
30 | def run(self) -> None:
31 | assert isinstance(self.settings, self.Settings)
32 |
33 | postsynth_sim_flow = self.pop_dependency(VivadoPostsynthSim)
34 | synth_flow = postsynth_sim_flow.pop_dependency(VivadoSynth)
35 |
36 | checkpoint = str(
37 | synth_flow.run_path
38 | / f"{self.design.name}.runs"
39 | / "impl_1"
40 | / f"{self.design.rtl.top}_routed.dcp"
41 | )
42 | saif_file = str(postsynth_sim_flow.run_path / self.settings.saif)
43 |
44 | # assert isinstance(dep_synth_flow.settings, VivadoSynth.Settings)
45 | script_path = self.copy_from_template(
46 | "vivado_power.tcl",
47 | checkpoint=checkpoint,
48 | saif_file=saif_file,
49 | )
50 |
51 | self.vivado.run("-source", script_path)
52 |
53 | def parse_power_report(self, report_xml) -> Dict[str, Any]:
54 | tree = ElementTree.parse(report_xml)
55 | results = {}
56 | for tablerow in tree.findall("./section[@title='Summary']/table/tablerow"):
57 | tablecells = tablerow.findall("tablecell")
58 | key, value = (html.unescape(x.attrib["contents"]).strip() for x in tablecells)
59 | results[key] = value
60 |
61 | for tablerow in tree.findall(
62 | "./section[@title='Summary']/section[@title='On-Chip Components']/table/tablerow"
63 | ):
64 | tablecells = tablerow.findall("tablecell")
65 | if len(tablecells) >= 2:
66 | contents = [html.unescape(x.attrib["contents"]).strip() for x in tablecells]
67 | key = contents[0]
68 | value = contents[1]
69 | results[f"Component Power: {key}"] = value
70 |
71 | return results
72 |
73 | def parse_reports(self) -> bool:
74 | assert isinstance(self.settings, self.Settings)
75 | report_xml = self.run_path / self.settings.power_report_xml
76 | results = self.parse_power_report(report_xml)
77 | self.results.update(**results)
78 | return True
79 |
--------------------------------------------------------------------------------
/src/xeda/flows/yosys/cxx_rtl.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from pathlib import Path
3 | from typing import Any, List, Optional
4 |
5 | from ...dataclass import XedaBaseModel
6 | from ...design import SourceType
7 | from ...flow import SimFlow
8 | from ...flows.ghdl import GhdlSynth
9 | from ...tool import Docker, Tool
10 | from .common import YosysBase
11 |
12 | log = logging.getLogger(__name__)
13 |
14 |
15 | class CxxRtl(XedaBaseModel):
16 | filename: Optional[str] = None
17 | header: bool = True
18 | flatten: bool = True
19 | hierarchy: bool = True
20 | proc: bool = True
21 | debug: Optional[int] = None
22 | opt: Optional[int] = None
23 | namespace: Optional[str] = None
24 | ccflags: List[str] = []
25 |
26 |
27 | class YosysSim(YosysBase, SimFlow):
28 | """Simulate with CXXRTL"""
29 |
30 | class Settings(YosysBase.Settings):
31 | cxxrtl: CxxRtl = CxxRtl()
32 |
33 | def run(self) -> None:
34 | assert isinstance(self.settings, self.Settings)
35 | ss = self.settings
36 | yosys = Tool(
37 | executable="yosys",
38 | docker=Docker(image="hdlc/impl"), # pyright: reportGeneralTypeIssues=none
39 | )
40 | ss.flatten = True
41 | if not ss.cxxrtl.filename:
42 | ss.cxxrtl.filename = (
43 | self.design.rtl.top if self.design.rtl.top else self.design.name + ".cpp"
44 | )
45 | script_path = self.copy_from_template(
46 | "yosys_sim.tcl",
47 | lstrip_blocks=True,
48 | trim_blocks=True,
49 | ghdl_args=GhdlSynth.synth_args(ss.ghdl, self.design),
50 | )
51 | log.info("Yosys script: %s", self.run_path.relative_to(Path.cwd()) / script_path)
52 | # args = ['-s', script_path]
53 | args = ["-c", script_path]
54 | if ss.log_file:
55 | args.extend(["-L", ss.log_file])
56 | if not ss.verbose: # reduce noise unless verbose
57 | args.extend(["-T", "-Q"])
58 | if not ss.debug:
59 | args.append("-q")
60 | self.results["_tool"] = yosys.info # TODO where should this go?
61 | log.info("Logging yosys output to %s", ss.log_file)
62 | yosys.run(*args)
63 |
64 | yosys_config = yosys.derive("yosys-config")
65 | yosys_include_dir = yosys_config.run_get_stdout("--datdir/include")
66 | cxx = yosys.derive("g++")
67 | assert ss.cxxrtl.filename
68 | cxxrtl_cpp = Path(ss.cxxrtl.filename)
69 | cxx_args: List[Any] = [cxxrtl_cpp] + [
70 | f.path for f in self.design.sim_sources_of_type(SourceType.Cpp)
71 | ]
72 | sim_bin_file = cxxrtl_cpp.with_suffix("")
73 | cxx_args += ["-std=c++14"]
74 | cxx_args += ["-o", sim_bin_file]
75 | cxx_args += [f"-I{yosys_include_dir}"]
76 | if ss.cxxrtl.header:
77 | cxx_args += [f"-I{cxxrtl_cpp.parent}"]
78 | cxx_args += ss.cxxrtl.ccflags
79 | cxx.run(*cxx_args)
80 | sim_bin = yosys.derive(executable=Path.cwd() / sim_bin_file)
81 | sim_bin.run()
82 |
83 | def parse_reports(self) -> bool:
84 | return True
85 |
--------------------------------------------------------------------------------
/src/xeda/flows/openfpgaloader.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from typing import Optional
3 |
4 | from ..board import WithFpgaBoardSettings, get_board_data
5 | from ..dataclass import validator
6 | from ..flow import FlowSettingsException, FpgaSynthFlow
7 | from ..tool import Tool
8 | from .nextpnr import Nextpnr
9 |
10 | __all__ = ["Openfpgaloader"]
11 |
12 | log = logging.getLogger(__name__)
13 |
14 |
15 | class Openfpgaloader(FpgaSynthFlow):
16 | ofpga_loader = Tool("openFPGALoader")
17 |
18 | class Settings(WithFpgaBoardSettings):
19 | clock_period: float
20 | reset: bool = False
21 | cable: Optional[str] = None
22 | nextpnr: Optional[Nextpnr.Settings] = None
23 |
24 | @validator("nextpnr", always=True, pre=True)
25 | def _validate_nextpnr(cls, value, values):
26 | clocks = values.get("clocks")
27 | fpga = values.get("fpga")
28 | board = values.get("board")
29 | if value is None:
30 | value = {}
31 | if isinstance(value, Nextpnr.Settings):
32 | value = value.dict()
33 | assert isinstance(value, (dict)), f"not a dict: {value}"
34 | value["fpga"] = fpga
35 | value["board"] = board
36 | value["clocks"] = clocks
37 | return Nextpnr.Settings(**value)
38 |
39 | def init(self) -> None:
40 | self.packer: Optional[Tool] = None
41 | assert isinstance(self.settings, self.Settings)
42 | ss = self.settings
43 | assert ss.nextpnr is not None
44 | self.add_dependency(Nextpnr, ss.nextpnr)
45 | if ss.fpga is None:
46 | raise FlowSettingsException("")
47 | if ss.fpga.family == "ecp5": # FIXME from fpga/board
48 | self.packer = Tool("ecppack")
49 |
50 | def run(self) -> None:
51 | assert isinstance(self.settings, self.Settings)
52 | ss = self.settings
53 | board_id = ss.board
54 | board_name = None
55 | if board_id:
56 | board_data = get_board_data(board_id)
57 | if board_data:
58 | board_name = board_data.get("name")
59 | next_pnr = self.completed_dependencies[0]
60 | assert isinstance(next_pnr, Nextpnr)
61 | assert isinstance(next_pnr.settings, Nextpnr.Settings)
62 | assert next_pnr.settings.textcfg
63 | text_cfg = next_pnr.run_path / next_pnr.settings.textcfg
64 | assert text_cfg.exists(), f"Can't find {text_cfg} generated by Nextpnr!"
65 | bitstream = f"{board_name}.bit" if board_name else "bitstream.bit"
66 | if self.packer:
67 | self.packer.run(text_cfg, bitstream)
68 | args = ["--bitstream", bitstream]
69 | if ss.cable:
70 | args.extend(["--cable", ss.cable])
71 | elif board_name:
72 | args.extend(["--board", board_name])
73 | assert ss.fpga is not None
74 | if ss.fpga.part:
75 | args.extend(["--fpga-part", ss.fpga.part])
76 | if ss.reset:
77 | args.append("--reset")
78 | if ss.verbose:
79 | args.append("--verbose")
80 | self.ofpga_loader.run(*args)
81 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | # import os
14 | # import sys
15 | # sys.path.insert(0, os.path.abspath("."))
16 |
17 | from importlib.metadata import version as release_version
18 |
19 | # -- Project information -----------------------------------------------------
20 |
21 | project = "xeda"
22 | copyright = "2022, Kamyar Mohajerani"
23 | author = "Kamyar Mohajerani"
24 | version = release_version("xeda")
25 |
26 | master_doc = "index"
27 | language = "en"
28 |
29 |
30 | # -- General configuration ---------------------------------------------------
31 |
32 | # Add any Sphinx extension module names here, as strings. They can be
33 | # extensions coming with Sphinx (named "sphinx.ext.*") or your custom
34 | # ones.
35 | extensions = [
36 | # "sphinxcontrib.bibtex",
37 | "myst_parser",
38 | "sphinx.ext.autodoc",
39 | "sphinx.ext.intersphinx",
40 | "sphinx.ext.viewcode",
41 | "sphinx_panels",
42 | "sphinxext.rediraffe",
43 | "sphinxcontrib.mermaid",
44 | "sphinxext.opengraph",
45 | "sphinxcontrib.autodoc_pydantic",
46 | "sphinx.ext.autosummary",
47 | "sphinx.ext.autodoc"
48 | ]
49 |
50 | # Add any paths that contain templates here, relative to this directory.
51 | templates_path = ["_templates"]
52 |
53 | # List of patterns, relative to source directory, that match files and
54 | # directories to ignore when looking for source files.
55 | # This pattern also affects html_static_path and html_extra_path.
56 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
57 |
58 |
59 | # -- Options for HTML output -------------------------------------------------
60 |
61 | # The theme to use for HTML and HTML Help pages. See the documentation for
62 | # a list of builtin themes.
63 | #
64 | html_theme = "sphinx_book_theme"
65 | html_logo = "../logo.svg"
66 | # html_favicon = "../logo.svg"
67 | html_title = ""
68 | html_theme_options = {
69 | "github_url": "https://github.com/XedaHQ/xeda",
70 | "repository_url": "https://github.com/XedaHQ/xeda",
71 | "use_edit_page_button": True,
72 | "repository_branch": "dev",
73 | "path_to_docs": "docs",
74 | }
75 |
76 | # Add any paths that contain custom static files (such as style sheets) here,
77 | # relative to this directory. They are copied after the builtin static files,
78 | # so a file named "default.css" will overwrite the builtin "default.css".
79 | html_static_path = ["_static"]
80 |
81 | intersphinx_mapping = {
82 | "python": ("https://docs.python.org/3.9", None),
83 | "pydantic": ("https://www.sphinx-doc.org/en/master", None),
84 | }
85 |
86 |
87 | autosummary_generate = True
88 | # autodoc_member_order = "bysource"
89 |
--------------------------------------------------------------------------------
/src/xeda/platforms/asap7/openlane/asap7sc7p5t/no_synth.cells:
--------------------------------------------------------------------------------
1 | A2O1A1Ixp33_ASAP7_75t_R
2 | A2O1A1O1Ixp25_ASAP7_75t_R
3 | AO21x1_ASAP7_75t_R
4 | AO221x1_ASAP7_75t_R
5 | AO22x1_ASAP7_75t_R
6 | AO32x1_ASAP7_75t_R
7 | AO331x1_ASAP7_75t_R
8 | AO332x1_ASAP7_75t_R
9 | AO333x1_ASAP7_75t_R
10 | AOI211x1_ASAP7_75t_R
11 | AOI211xp5_ASAP7_75t_R
12 | AOI21x1_ASAP7_75t_R
13 | AOI21xp33_ASAP7_75t_R
14 | AOI21xp5_ASAP7_75t_R
15 | AOI221x1_ASAP7_75t_R
16 | AOI221xp5_ASAP7_75t_R
17 | AOI222xp33_ASAP7_75t_R
18 | AOI22x1_ASAP7_75t_R
19 | AOI22xp33_ASAP7_75t_R
20 | AOI22xp5_ASAP7_75t_R
21 | AOI311xp33_ASAP7_75t_R
22 | AOI31xp33_ASAP7_75t_R
23 | AOI31xp67_ASAP7_75t_R
24 | AOI321xp33_ASAP7_75t_R
25 | AOI322xp5_ASAP7_75t_R
26 | AOI32xp33_ASAP7_75t_R
27 | AOI331xp33_ASAP7_75t_R
28 | AOI332xp33_ASAP7_75t_R
29 | AOI333xp33_ASAP7_75t_R
30 | AOI33xp33_ASAP7_75t_R
31 | HB1xp67_ASAP7_75t_R
32 | HB2xp67_ASAP7_75t_R
33 | HB3xp67_ASAP7_75t_R
34 | HB4xp67_ASAP7_75t_R
35 | INVx1_ASAP7_75t_R
36 | INVxp33_ASAP7_75t_R
37 | INVxp67_ASAP7_75t_R
38 | O2A1O1Ixp33_ASAP7_75t_R
39 | O2A1O1Ixp5_ASAP7_75t_R
40 | OA331x1_ASAP7_75t_R
41 | OA332x1_ASAP7_75t_R
42 | OA333x1_ASAP7_75t_R
43 | OAI211xp5_ASAP7_75t_R
44 | OAI21x1_ASAP7_75t_R
45 | OAI21xp33_ASAP7_75t_R
46 | OAI21xp5_ASAP7_75t_R
47 | OAI221xp5_ASAP7_75t_R
48 | OAI222xp33_ASAP7_75t_R
49 | OAI22x1_ASAP7_75t_R
50 | OAI22xp33_ASAP7_75t_R
51 | OAI22xp5_ASAP7_75t_R
52 | OAI311xp33_ASAP7_75t_R
53 | OAI31xp33_ASAP7_75t_R
54 | OAI31xp67_ASAP7_75t_R
55 | OAI321xp33_ASAP7_75t_R
56 | OAI322xp33_ASAP7_75t_R
57 | OAI32xp33_ASAP7_75t_R
58 | OAI331xp33_ASAP7_75t_R
59 | OAI332xp33_ASAP7_75t_R
60 | OAI333xp33_ASAP7_75t_R
61 | OAI33xp33_ASAP7_75t_R
62 | ASYNC_DFFHx1_ASAP7_75t_R
63 | DFFHQNx1_ASAP7_75t_R
64 | DFFHQNx2_ASAP7_75t_R
65 | DFFHQNx3_ASAP7_75t_R
66 | DFFHQx4_ASAP7_75t_R
67 | DFFLQNx1_ASAP7_75t_R
68 | DHLx1_ASAP7_75t_R
69 | DLLx1_ASAP7_75t_R
70 | ICGx1_ASAP7_75t_R
71 | ICGx2_ASAP7_75t_R
72 | ICGx2p67DC_ASAP7_75t_R
73 | ICGx3_ASAP7_75t_R
74 | ICGx4DC_ASAP7_75t_R
75 | ICGx4_ASAP7_75t_R
76 | ICGx5_ASAP7_75t_R
77 | ICGx5p33DC_ASAP7_75t_R
78 | ICGx6p67DC_ASAP7_75t_R
79 | ICGx8DC_ASAP7_75t_R
80 | SDFHx1_ASAP7_75t_R
81 | SDFHx2_ASAP7_75t_R
82 | SDFHx3_ASAP7_75t_R
83 | SDFHx4_ASAP7_75t_R
84 | SDFLx1_ASAP7_75t_R
85 | SDFLx2_ASAP7_75t_R
86 | SDFLx3_ASAP7_75t_R
87 | SDFLx4_ASAP7_75t_R
88 | AND3x1_ASAP7_75t_R
89 | AND4x1_ASAP7_75t_R
90 | AND5x1_ASAP7_75t_R
91 | FAx1_ASAP7_75t_R
92 | HAxp5_ASAP7_75t_R
93 | MAJIxp5_ASAP7_75t_R
94 | NAND2x1_ASAP7_75t_R
95 | NAND2x1p5_ASAP7_75t_R
96 | NAND2xp33_ASAP7_75t_R
97 | NAND2xp5_ASAP7_75t_R
98 | NAND2xp67_ASAP7_75t_R
99 | NAND3x1_ASAP7_75t_R
100 | NAND3xp33_ASAP7_75t_R
101 | NAND4xp25_ASAP7_75t_R
102 | NAND4xp75_ASAP7_75t_R
103 | NAND5xp2_ASAP7_75t_R
104 | NOR2x1_ASAP7_75t_R
105 | NOR2x1p5_ASAP7_75t_R
106 | NOR2xp33_ASAP7_75t_R
107 | NOR2xp67_ASAP7_75t_R
108 | NOR3x1_ASAP7_75t_R
109 | NOR3xp33_ASAP7_75t_R
110 | NOR4xp25_ASAP7_75t_R
111 | NOR4xp75_ASAP7_75t_R
112 | NOR5xp2_ASAP7_75t_R
113 | OR3x1_ASAP7_75t_R
114 | OR4x1_ASAP7_75t_R
115 | OR5x1_ASAP7_75t_R
116 | TIEHIx1_ASAP7_75t_R
117 | TIELOx1_ASAP7_75t_R
118 | XNOR2x1_ASAP7_75t_R
119 | XNOR2xp5_ASAP7_75t_R
120 | XOR2x1_ASAP7_75t_R
121 | XOR2xp5_ASAP7_75t_R
122 |
--------------------------------------------------------------------------------