From 5c67c7222cf5331e436c0314e3c45f085e4257ca Mon Sep 17 00:00:00 2001 From: Rob Taylor Date: Fri, 23 May 2025 17:22:00 +0100 Subject: [PATCH 1/4] Better set up dev environment * Move developer commands into pyproject * Remove Makefiles * Add nice checking * Update CI --- .github/workflows/main.yaml | 2 +- mcu_soc/Makefile | 45 ---------------------------- minimal/Makefile | 45 ---------------------------- pyproject.toml | 60 ++++++++++++++++++++++++++----------- tools/__init__.py | 0 tools/check_project.py | 20 +++++++++++++ 6 files changed, 63 insertions(+), 109 deletions(-) delete mode 100644 mcu_soc/Makefile delete mode 100644 minimal/Makefile create mode 100644 tools/__init__.py create mode 100644 tools/check_project.py diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index eea831c..591ae20 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -102,7 +102,7 @@ jobs: - name: Run simulation tests working-directory: ./${{ matrix.design }} run: | - make sim-check + pdm sim-check - name: Test submit dry run working-directory: ./${{ matrix.design }} diff --git a/mcu_soc/Makefile b/mcu_soc/Makefile deleted file mode 100644 index 66b531b..0000000 --- a/mcu_soc/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -ARG ?= SPI - -.PHONY: init # Init local environemnt -init: - pdm install - -.PHONY: sim-build # Builds a local binary to run the design in simulation -sim-build: - pdm run chipflow sim - -.PHONY: software-build # Builds the RISC-V software/bios to run on the design -software-build: sim-build - pdm run chipflow software - -.PHONY: board-build # Build a bitstream for the board -board-build: - pdm run chipflow board - -.PHONY: board-load-software-ulx3s # Load the software/bios onto a ulx3s board -board-load-software-ulx3s: - openFPGALoader -fb ulx3s -o 0x00100000 build/software/software.bin - -.PHONY: board-load-ulx3s # Load the design onto a ulx3s board -board-load-ulx3s: - openFPGALoader -b ulx3s build/top.bit - -.PHONY: sim-run # Run the simulation of the design -sim-run: sim-build software-build - cd build/sim && ./sim_soc - -.PHONY: sim-check -sim-check: sim-run - pdm run json-compare design/tests/events_reference.json build/sim/events.json - -.PHONY: silicon-prepare # Build RTLIL for the design -silicon-prepare: - pdm run chipflow silicon prepare - -.PHONY: silicon-submit # Send to API to submit for manufacture -silicon-submit: - pdm run chipflow silicon submit - -.PHONY: clean # Clean/delete the builds -clean: - rm -fr build diff --git a/minimal/Makefile b/minimal/Makefile deleted file mode 100644 index 66b531b..0000000 --- a/minimal/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -ARG ?= SPI - -.PHONY: init # Init local environemnt -init: - pdm install - -.PHONY: sim-build # Builds a local binary to run the design in simulation -sim-build: - pdm run chipflow sim - -.PHONY: software-build # Builds the RISC-V software/bios to run on the design -software-build: sim-build - pdm run chipflow software - -.PHONY: board-build # Build a bitstream for the board -board-build: - pdm run chipflow board - -.PHONY: board-load-software-ulx3s # Load the software/bios onto a ulx3s board -board-load-software-ulx3s: - openFPGALoader -fb ulx3s -o 0x00100000 build/software/software.bin - -.PHONY: board-load-ulx3s # Load the design onto a ulx3s board -board-load-ulx3s: - openFPGALoader -b ulx3s build/top.bit - -.PHONY: sim-run # Run the simulation of the design -sim-run: sim-build software-build - cd build/sim && ./sim_soc - -.PHONY: sim-check -sim-check: sim-run - pdm run json-compare design/tests/events_reference.json build/sim/events.json - -.PHONY: silicon-prepare # Build RTLIL for the design -silicon-prepare: - pdm run chipflow silicon prepare - -.PHONY: silicon-submit # Send to API to submit for manufacture -silicon-submit: - pdm run chipflow silicon submit - -.PHONY: clean # Clean/delete the builds -clean: - rm -fr build diff --git a/pyproject.toml b/pyproject.toml index 81a1fd9..a03f7b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,30 +28,15 @@ dependencies = [ requires = ["pdm-backend"] build-backend = "pdm.backend" -# Development workflow configuration - -[tool.pdm.dev-dependencies] -test = [ - "pytest>=7.3.1", -] -#dev = [ -# "-e file:///${PROJECT_ROOT}/../chipflow-lib#egg=chipflow-lib" -#] - -[tool.pdm.scripts] -_.env_file = ".env.toolchain" -test.cmd = "pytest" -json-compare.call = "tools.json_compare:main" - [tool.pdm.resolution] allow-prereleases = true +# Development workflow configuration + [tool.pyright] -include = ['my_design/**'] diagnosticMode=false typeCheckingMode = "off" reportInvalidTypeForm = false -reportUnboundVariable = false reportAttributeAccessIssue = false reportGeneralTypeIssues = false reportWildcardImportFromLibrary = false @@ -61,4 +46,43 @@ reportMissingImports = "none" include = ["pyproject.toml", "**/*.py", "chipflow.toml"] [tool.ruff.lint] -ignore = ['F403', 'F405'] +ignore = ['F403', 'F405', 'E701', 'F841'] + +[tool.pdm.version] +source = "scm" + +[tool.pdm.scripts] +_.env_file = ".env.toolchain" +_json-compare.call = "tools.json_compare:main" +_check-project.call = "tools.check_project:main" +_run-sim.shell = "cd $PDM_RUN_CWD/build/sim && ./sim_soc" +submit.composite = ["check-project", "chipflow silicon submit {args}"] +chipflow.shell = "cd $PDM_RUN_CWD && chipflow" +sim-run.composite = [ + "_check-project", + "chipflow sim", + "chipflow software", + "_run-sim {args}" + ] +sim-check.composite = [ + "_check-project", + "sim-run {args}", + "_json-compare design/tests/events_reference.json build/sim/events.json" + ] +board-load-software-ulx3s.composite = ["check_project", "openFPGALoader -fb ulx3s -o 0x00100000 $PDM_RUN_CWD/build/software/software.bin"] +board-load-ulx3s.composite = ["check_project", "openFPGALoader -b ulx3s $PDM_RUN_CWD/build/top.bit"] +test.cmd = "pytest" +test-cov.cmd = "pytest --cov=my_design cov-report=term" +test-cov-html.cmd = "pytest --cov=my_design --cov-report=html" +# test-docs.cmd = "sphinx-build -b doctest docs/ docs/_build" +lint.cmd = "ruff check" +# docs.cmd = "sphinx-build docs/ docs/_build/ -W --keep-going" + + + +[dependency-groups] +dev = [ + "ruff>=0.9.2", + "pytest>=7.2.0", + "pytest-cov>=0.6", +] diff --git a/tools/__init__.py b/tools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tools/check_project.py b/tools/check_project.py new file mode 100644 index 0000000..be05441 --- /dev/null +++ b/tools/check_project.py @@ -0,0 +1,20 @@ +import os + +from pathlib import Path + +working_dir = Path(os.environ["PDM_RUN_CWD"] if "PDM_RUN_CWD" in os.environ else "./") + +def main(): + if (working_dir / "chipflow.toml").exists(): + exit(0) + else: + print("chipflow.toml not found, this is not a valid project directory") + tomls = sorted(working_dir.glob('**/chipflow.toml')) + if tomls: + print("Valid projects in this directory:") + for f in tomls: + print(f" {str(f.parent.relative_to(working_dir))}") + exit(1) + +if __name__ == "__main__": + main() From cc5e3f4d7dd0c7c2463dd788de121d3fd012138c Mon Sep 17 00:00:00 2001 From: Rob Taylor Date: Fri, 23 May 2025 17:22:27 +0100 Subject: [PATCH 2/4] Fix lint issues from lint config changes --- mcu_soc/design/design.py | 2 +- mcu_soc/design/ips/pdm.py | 3 +-- mcu_soc/design/ips/pwm.py | 3 +-- mcu_soc/design/sim/doit_build.py | 2 +- mcu_soc/design/software/doit_build.py | 3 +-- mcu_soc/design/steps/sim.py | 2 -- minimal/design/design.py | 6 +----- minimal/design/sim/doit_build.py | 2 +- minimal/design/software/doit_build.py | 3 +-- minimal/design/steps/sim.py | 2 -- 10 files changed, 8 insertions(+), 20 deletions(-) diff --git a/mcu_soc/design/design.py b/mcu_soc/design/design.py index b29f1aa..cc5a3fb 100644 --- a/mcu_soc/design/design.py +++ b/mcu_soc/design/design.py @@ -3,7 +3,7 @@ from amaranth import Module from amaranth.lib import wiring -from amaranth.lib.wiring import In, Out, flipped, connect +from amaranth.lib.wiring import Out, flipped, connect from amaranth_soc import csr, wishbone from amaranth_soc.csr.wishbone import WishboneCSRBridge diff --git a/mcu_soc/design/ips/pdm.py b/mcu_soc/design/ips/pdm.py index f731caf..5426d84 100644 --- a/mcu_soc/design/ips/pdm.py +++ b/mcu_soc/design/ips/pdm.py @@ -1,6 +1,5 @@ from amaranth import * -from amaranth import Elaboratable, Module -from amaranth.build import Platform +from amaranth import Module from amaranth.lib import wiring from amaranth.lib.wiring import In, Out, flipped, connect diff --git a/mcu_soc/design/ips/pwm.py b/mcu_soc/design/ips/pwm.py index 286d81d..ef39fc1 100644 --- a/mcu_soc/design/ips/pwm.py +++ b/mcu_soc/design/ips/pwm.py @@ -1,6 +1,5 @@ from amaranth import * -from amaranth import Elaboratable, Module -from amaranth.build import Platform +from amaranth import Module from amaranth.lib import wiring from amaranth.lib.wiring import In, Out, flipped, connect diff --git a/mcu_soc/design/sim/doit_build.py b/mcu_soc/design/sim/doit_build.py index 20cae70..e58bba8 100644 --- a/mcu_soc/design/sim/doit_build.py +++ b/mcu_soc/design/sim/doit_build.py @@ -9,7 +9,7 @@ RUNTIME_DIR = importlib.resources.files("yowasp_yosys") / "share/include/backends/cxxrtl/runtime" ZIG_CXX = f"{sys.executable} -m ziglang c++" -CXXFLAGS = f"-O3 -g -std=c++17 -Wno-array-bounds -Wno-shift-count-overflow -fbracket-depth=1024" +CXXFLAGS = "-O3 -g -std=c++17 -Wno-array-bounds -Wno-shift-count-overflow -fbracket-depth=1024" INCLUDES = f"-I {OUTPUT_DIR} -I {COMMON_DIR} -I {COMMON_DIR}/vendor -I {RUNTIME_DIR}" diff --git a/mcu_soc/design/software/doit_build.py b/mcu_soc/design/software/doit_build.py index de5b5a7..4f52824 100644 --- a/mcu_soc/design/software/doit_build.py +++ b/mcu_soc/design/software/doit_build.py @@ -4,7 +4,6 @@ import shutil from doit import create_after -from doit.action import CmdAction import chipflow_lib.config @@ -15,7 +14,7 @@ CINCLUDES = f"-I. -I{BUILD_DIR} -I{DESIGN_DIR}/software" LINKER_SCR = f"{BUILD_DIR}/generated/sections.lds" SOFTWARE_START = f"{BUILD_DIR}/generated/start.S" -CFLAGS = f"-g -mcpu=baseline_rv32-a-c-d -mabi=ilp32 -Wl,-Bstatic,-T," +CFLAGS = "-g -mcpu=baseline_rv32-a-c-d -mabi=ilp32 -Wl,-Bstatic,-T," CFLAGS += f"{LINKER_SCR},--strip-debug -static -ffreestanding -nostdlib {CINCLUDES}" diff --git a/mcu_soc/design/steps/sim.py b/mcu_soc/design/steps/sim.py index df8624e..62c61cc 100644 --- a/mcu_soc/design/steps/sim.py +++ b/mcu_soc/design/steps/sim.py @@ -1,8 +1,6 @@ from chipflow_lib.steps.sim import SimStep from amaranth import * -from amaranth.lib import wiring -from amaranth.lib.wiring import connect, flipped from amaranth.back import rtlil from ..design import MySoC diff --git a/minimal/design/design.py b/minimal/design/design.py index 223fef6..a3b675b 100644 --- a/minimal/design/design.py +++ b/minimal/design/design.py @@ -1,9 +1,8 @@ -from chipflow_lib.platforms.sim import SimPlatform from chipflow_lib.software.soft_gen import SoftwareGenerator from amaranth import Module from amaranth.lib import wiring -from amaranth.lib.wiring import In, Out, flipped, connect +from amaranth.lib.wiring import Out, flipped, connect from amaranth_soc import csr, wishbone from amaranth_soc.csr.wishbone import WishboneCSRBridge @@ -13,12 +12,9 @@ from amaranth_soc.wishbone.sram import WishboneSRAM from amaranth_orchard.io import GPIOPeripheral from amaranth_orchard.io import UARTPeripheral -from amaranth_orchard.io import SPISignature, SPIPeripheral -from amaranth_orchard.io import I2CSignature, I2CPeripheral from minerva.core import Minerva -from chipflow_lib.platforms import InputPinSignature, OutputPinSignature # from .ips.pdm import PDMPeripheral __all__ = ["MySoC"] diff --git a/minimal/design/sim/doit_build.py b/minimal/design/sim/doit_build.py index 7c33eb2..eaae05d 100644 --- a/minimal/design/sim/doit_build.py +++ b/minimal/design/sim/doit_build.py @@ -9,7 +9,7 @@ RUNTIME_DIR = importlib.resources.files("yowasp_yosys") / "share/include/backends/cxxrtl/runtime" ZIG_CXX = f"{sys.executable} -m ziglang c++" -CXXFLAGS = f"-O3 -g -std=c++17 -Wno-array-bounds -Wno-shift-count-overflow -fbracket-depth=1024" +CXXFLAGS = "-O3 -g -std=c++17 -Wno-array-bounds -Wno-shift-count-overflow -fbracket-depth=1024" INCLUDES = f"-I {OUTPUT_DIR} -I {COMMON_DIR} -I {COMMON_DIR}/vendor -I {RUNTIME_DIR}" diff --git a/minimal/design/software/doit_build.py b/minimal/design/software/doit_build.py index de5b5a7..4f52824 100644 --- a/minimal/design/software/doit_build.py +++ b/minimal/design/software/doit_build.py @@ -4,7 +4,6 @@ import shutil from doit import create_after -from doit.action import CmdAction import chipflow_lib.config @@ -15,7 +14,7 @@ CINCLUDES = f"-I. -I{BUILD_DIR} -I{DESIGN_DIR}/software" LINKER_SCR = f"{BUILD_DIR}/generated/sections.lds" SOFTWARE_START = f"{BUILD_DIR}/generated/start.S" -CFLAGS = f"-g -mcpu=baseline_rv32-a-c-d -mabi=ilp32 -Wl,-Bstatic,-T," +CFLAGS = "-g -mcpu=baseline_rv32-a-c-d -mabi=ilp32 -Wl,-Bstatic,-T," CFLAGS += f"{LINKER_SCR},--strip-debug -static -ffreestanding -nostdlib {CINCLUDES}" diff --git a/minimal/design/steps/sim.py b/minimal/design/steps/sim.py index df8624e..62c61cc 100644 --- a/minimal/design/steps/sim.py +++ b/minimal/design/steps/sim.py @@ -1,8 +1,6 @@ from chipflow_lib.steps.sim import SimStep from amaranth import * -from amaranth.lib import wiring -from amaranth.lib.wiring import connect, flipped from amaranth.back import rtlil from ..design import MySoC From b91cc9631e0ee9ecfcdd238e5e7e5fe8da2bc5c1 Mon Sep 17 00:00:00 2001 From: Rob Taylor Date: Thu, 1 May 2025 15:07:59 +0100 Subject: [PATCH 3/4] Update readme --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2cb9e21..6585085 100644 --- a/README.md +++ b/README.md @@ -44,21 +44,20 @@ First choose a design to test. Here we will use the `minimal` design. Change into the `minimal` directory in `chipflow-examples` to use this design. Now we need to 'lock' our pins - the ChipFlow tooling will then automatically allocate inputs and outputs from your design to pins on the chip. ``` -pdm run chipflow pin lock +pdm chipflow pin lock ``` We can now simulate and test the design by running: ``` -make sim-check +pdm sim-check ``` You should see the simulation model being built and run - and a small test firmware running on the simulated System-on-a-Chip (aided by our local friendly cat!) ``` -pdm run chipflow sim -- build_sim_cxxrtl -- build_sim -pdm run chipflow software +pdm chipflow software -- gather_depencencies -- build_software_elf -- build_software @@ -74,7 +73,7 @@ Event logs are identical Now you are ready to try building this design into a chip! To submit your design to ChipFlow Platform where it will be built into GDS, run: ``` -pdm run chipflow silicon submit +pdm submit ``` This should return something like: @@ -88,7 +87,7 @@ Your design will now start building: pictures and logs of the build are availabl If you would like to get the build logs streamed to your command-line, you can instead call: ``` -pdm run chipflow silicon submit --wait +pdm submit --wait ``` From 02e543ab155170fdf345be045298afaacb493d98 Mon Sep 17 00:00:00 2001 From: gatecat Date: Fri, 28 Mar 2025 09:47:34 +0100 Subject: [PATCH 4/4] Simplify board initialisation and get it back working again --- mcu_soc/chipflow.toml | 1 + mcu_soc/design/steps/board.py | 119 ++++++++++++---------------------- minimal/chipflow.toml | 1 + minimal/design/steps/board.py | 119 ++++++++++++---------------------- 4 files changed, 86 insertions(+), 154 deletions(-) diff --git a/mcu_soc/chipflow.toml b/mcu_soc/chipflow.toml index 3bddb91..c82200e 100644 --- a/mcu_soc/chipflow.toml +++ b/mcu_soc/chipflow.toml @@ -6,6 +6,7 @@ soc = "design.design:MySoC" [chipflow.steps] sim = "design.steps.sim:MySimStep" +board = "design.steps.board:MyBoardStep" silicon = "chipflow_lib.steps.silicon:SiliconStep" software = "design.steps.software:MySoftwareStep" diff --git a/mcu_soc/design/steps/board.py b/mcu_soc/design/steps/board.py index 2f13e64..c91b0d0 100644 --- a/mcu_soc/design/steps/board.py +++ b/mcu_soc/design/steps/board.py @@ -4,8 +4,7 @@ from amaranth import * from amaranth.lib import wiring -from amaranth.lib.wiring import connect, flipped -from amaranth.build import Resource, Subsignal, Pins, Attrs +from amaranth.lib.cdc import ResetSynchronizer from ..design import MySoC @@ -17,84 +16,51 @@ def elaborate(self, platform): m.submodules.soc = soc = MySoC() m.domains += ClockDomain("sync") - m.submodules.clock_reset_provider = platform.providers.ClockResetProvider() - m.submodules.spiflash_provider = spiflash_provider = platform.providers.QSPIFlashProvider() - connect(m, flipped(spiflash_provider.pins), soc.flash) - - m.submodules.led_gpio_provider = led_gpio_provider = platform.providers.LEDGPIOProvider() - connect(m, flipped(led_gpio_provider.pins), soc.gpio_0) - - m.submodules.uart_provider = uart_provider = platform.providers.UARTProvider() - connect(m, flipped(uart_provider.pins), soc.uart_0) - - # Extra IO on headers - platform.add_resources([ - Resource( - "expansion", - 0, - Subsignal("user_spi0_sck", Pins("0+", conn=("gpio", 0), dir='o')), - Subsignal("user_spi0_copi", Pins("0-", conn=("gpio", 0), dir='o')), - Subsignal("user_spi0_cipo", Pins("1+", conn=("gpio", 0), dir='i')), - Subsignal("user_spi0_csn", Pins("1-", conn=("gpio", 0), dir='o')), - - Subsignal("user_spi1_sck", Pins("2+", conn=("gpio", 0), dir='o')), - Subsignal("user_spi1_copi", Pins("2-", conn=("gpio", 0), dir='o')), - Subsignal("user_spi1_cipo", Pins("3+", conn=("gpio", 0), dir='i')), - Subsignal("user_spi1_csn", Pins("3-", conn=("gpio", 0), dir='o')), - - Subsignal("i2c0_sda", Pins("4+", conn=("gpio", 0), dir='io')), - Subsignal("i2c0_scl", Pins("4-", conn=("gpio", 0), dir='io')), - - Subsignal("motor_pwm0_pwm", Pins("5+", conn=("gpio", 0), dir='o')), - Subsignal("motor_pwm0_dir", Pins("5-", conn=("gpio", 0), dir='o')), - Subsignal("motor_pwm0_stop", Pins("6+", conn=("gpio", 0), dir='i'), Attrs(PULLMODE="DOWN")), - - Subsignal("motor_pwm1_pwm", Pins("6-", conn=("gpio", 0), dir='o')), - Subsignal("motor_pwm1_dir", Pins("7+", conn=("gpio", 0), dir='o')), - Subsignal("motor_pwm1_stop", Pins("7-", conn=("gpio", 0), dir='i'), Attrs(PULLMODE="DOWN")), - - Subsignal("uart1_rx", Pins("8+", conn=("gpio", 0), dir='i')), - Subsignal("uart1_tx", Pins("8-", conn=("gpio", 0), dir='o')), - - Subsignal("cpu_jtag_tck", Pins("9+", conn=("gpio", 0), dir='i')), - Subsignal("cpu_jtag_tms", Pins("9-", conn=("gpio", 0), dir='i')), - Subsignal("cpu_jtag_tdi", Pins("10+", conn=("gpio", 0), dir='i')), - Subsignal("cpu_jtag_tdo", Pins("10-", conn=("gpio", 0), dir='o')), - Subsignal("cpu_jtag_trst", Pins("11+", conn=("gpio", 0), dir='i')), - - Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP"), + m.d.comb += ClockSignal("sync").eq(platform.request("clk25").i) + + btn_rst = platform.request("button_pwr") + m.submodules.rst_sync = ResetSynchronizer(arst=btn_rst.i, domain="sync") + + flash = platform.request("spi_flash", dir=dict(cs='-', copi='-', cipo='-', wp='-', hold='-')) + # Flash clock requires a special primitive to access in ECP5 + m.submodules.usrmclk = Instance( + "USRMCLK", + i_USRMCLKI=soc.flash.clk.o, + i_USRMCLKTS=ResetSignal(), # tristate in reset for programmer accesss + a_keep=1, + ) + + # Flash IO buffers + m.submodules += Instance( + "OBZ", + o_O=flash.cs.io, + i_I=soc.flash.csn.o, + i_T=ResetSignal(), + ) + + # Connect flash data pins in order + data_pins = ["copi", "cipo", "wp", "hold"] + for i in range(4): + m.submodules += Instance( + "BB", + io_B=getattr(flash, data_pins[i]).io, + i_I=soc.flash.d.o[i], + i_T=~soc.flash.d.oe[i], + o_O=soc.flash.d.i[i] ) - ]) - - exp = platform.request("expansion") - def _connect_interface(interface, name): - pins = dict() - for member in interface.signature.members: - pin, suffix = member.rsplit("_", 2) - assert suffix in ("o", "i", "oe"), suffix - pins[pin] = getattr(interface, member).width - for pin, width in pins.items(): - for i in range(width): - platform_pin = getattr(exp, f"{name}_{pin}{'' if width == 1 else str(i)}") - if hasattr(interface, f"{pin}_i"): - m.d.comb += getattr(interface, f"{pin}_i")[i].eq(platform_pin.i) - if hasattr(interface, f"{pin}_o"): - m.d.comb += platform_pin.o.eq(getattr(interface, f"{pin}_o")[i]) - if hasattr(interface, f"{pin}_oe"): - m.d.comb += platform_pin.oe.eq(getattr(interface, f"{pin}_oe")[i]) - - _connect_interface(soc.user_spi_0, "user_spi0") - _connect_interface(soc.user_spi_1, "user_spi1") - - _connect_interface(soc.i2c_0, "i2c0") - - _connect_interface(soc.motor_pwm0, "motor_pwm0") - _connect_interface(soc.motor_pwm1, "motor_pwm1") - _connect_interface(soc.uart_1, "uart1") + # Connect LEDs to GPIO0 + for i in range(8): + led = platform.request("led", i) + m.d.comb += led.o.eq(soc.gpio_0.gpio.o[i]) - _connect_interface(soc.cpu_jtag, "cpu_jtag") + # Connect UART0 + uart = platform.request("uart") + m.d.comb += [ + uart.tx.o.eq(soc.uart_0.tx.o), + soc.uart_0.rx.i.eq(uart.rx.i), + ] return m @@ -102,7 +68,6 @@ class MyBoardStep(BoardStep): def __init__(self, config): platform = ULX3S_85F_Platform() - platform.providers = board_ulx3s_providers super().__init__(config, platform) diff --git a/minimal/chipflow.toml b/minimal/chipflow.toml index 7c1b3e3..130eb5a 100644 --- a/minimal/chipflow.toml +++ b/minimal/chipflow.toml @@ -6,6 +6,7 @@ soc = "design.design:MySoC" [chipflow.steps] sim = "design.steps.sim:MySimStep" +board = "design.steps.board:MyBoardStep" silicon = "chipflow_lib.steps.silicon:SiliconStep" software = "design.steps.software:MySoftwareStep" diff --git a/minimal/design/steps/board.py b/minimal/design/steps/board.py index 2f13e64..c91b0d0 100644 --- a/minimal/design/steps/board.py +++ b/minimal/design/steps/board.py @@ -4,8 +4,7 @@ from amaranth import * from amaranth.lib import wiring -from amaranth.lib.wiring import connect, flipped -from amaranth.build import Resource, Subsignal, Pins, Attrs +from amaranth.lib.cdc import ResetSynchronizer from ..design import MySoC @@ -17,84 +16,51 @@ def elaborate(self, platform): m.submodules.soc = soc = MySoC() m.domains += ClockDomain("sync") - m.submodules.clock_reset_provider = platform.providers.ClockResetProvider() - m.submodules.spiflash_provider = spiflash_provider = platform.providers.QSPIFlashProvider() - connect(m, flipped(spiflash_provider.pins), soc.flash) - - m.submodules.led_gpio_provider = led_gpio_provider = platform.providers.LEDGPIOProvider() - connect(m, flipped(led_gpio_provider.pins), soc.gpio_0) - - m.submodules.uart_provider = uart_provider = platform.providers.UARTProvider() - connect(m, flipped(uart_provider.pins), soc.uart_0) - - # Extra IO on headers - platform.add_resources([ - Resource( - "expansion", - 0, - Subsignal("user_spi0_sck", Pins("0+", conn=("gpio", 0), dir='o')), - Subsignal("user_spi0_copi", Pins("0-", conn=("gpio", 0), dir='o')), - Subsignal("user_spi0_cipo", Pins("1+", conn=("gpio", 0), dir='i')), - Subsignal("user_spi0_csn", Pins("1-", conn=("gpio", 0), dir='o')), - - Subsignal("user_spi1_sck", Pins("2+", conn=("gpio", 0), dir='o')), - Subsignal("user_spi1_copi", Pins("2-", conn=("gpio", 0), dir='o')), - Subsignal("user_spi1_cipo", Pins("3+", conn=("gpio", 0), dir='i')), - Subsignal("user_spi1_csn", Pins("3-", conn=("gpio", 0), dir='o')), - - Subsignal("i2c0_sda", Pins("4+", conn=("gpio", 0), dir='io')), - Subsignal("i2c0_scl", Pins("4-", conn=("gpio", 0), dir='io')), - - Subsignal("motor_pwm0_pwm", Pins("5+", conn=("gpio", 0), dir='o')), - Subsignal("motor_pwm0_dir", Pins("5-", conn=("gpio", 0), dir='o')), - Subsignal("motor_pwm0_stop", Pins("6+", conn=("gpio", 0), dir='i'), Attrs(PULLMODE="DOWN")), - - Subsignal("motor_pwm1_pwm", Pins("6-", conn=("gpio", 0), dir='o')), - Subsignal("motor_pwm1_dir", Pins("7+", conn=("gpio", 0), dir='o')), - Subsignal("motor_pwm1_stop", Pins("7-", conn=("gpio", 0), dir='i'), Attrs(PULLMODE="DOWN")), - - Subsignal("uart1_rx", Pins("8+", conn=("gpio", 0), dir='i')), - Subsignal("uart1_tx", Pins("8-", conn=("gpio", 0), dir='o')), - - Subsignal("cpu_jtag_tck", Pins("9+", conn=("gpio", 0), dir='i')), - Subsignal("cpu_jtag_tms", Pins("9-", conn=("gpio", 0), dir='i')), - Subsignal("cpu_jtag_tdi", Pins("10+", conn=("gpio", 0), dir='i')), - Subsignal("cpu_jtag_tdo", Pins("10-", conn=("gpio", 0), dir='o')), - Subsignal("cpu_jtag_trst", Pins("11+", conn=("gpio", 0), dir='i')), - - Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP"), + m.d.comb += ClockSignal("sync").eq(platform.request("clk25").i) + + btn_rst = platform.request("button_pwr") + m.submodules.rst_sync = ResetSynchronizer(arst=btn_rst.i, domain="sync") + + flash = platform.request("spi_flash", dir=dict(cs='-', copi='-', cipo='-', wp='-', hold='-')) + # Flash clock requires a special primitive to access in ECP5 + m.submodules.usrmclk = Instance( + "USRMCLK", + i_USRMCLKI=soc.flash.clk.o, + i_USRMCLKTS=ResetSignal(), # tristate in reset for programmer accesss + a_keep=1, + ) + + # Flash IO buffers + m.submodules += Instance( + "OBZ", + o_O=flash.cs.io, + i_I=soc.flash.csn.o, + i_T=ResetSignal(), + ) + + # Connect flash data pins in order + data_pins = ["copi", "cipo", "wp", "hold"] + for i in range(4): + m.submodules += Instance( + "BB", + io_B=getattr(flash, data_pins[i]).io, + i_I=soc.flash.d.o[i], + i_T=~soc.flash.d.oe[i], + o_O=soc.flash.d.i[i] ) - ]) - - exp = platform.request("expansion") - def _connect_interface(interface, name): - pins = dict() - for member in interface.signature.members: - pin, suffix = member.rsplit("_", 2) - assert suffix in ("o", "i", "oe"), suffix - pins[pin] = getattr(interface, member).width - for pin, width in pins.items(): - for i in range(width): - platform_pin = getattr(exp, f"{name}_{pin}{'' if width == 1 else str(i)}") - if hasattr(interface, f"{pin}_i"): - m.d.comb += getattr(interface, f"{pin}_i")[i].eq(platform_pin.i) - if hasattr(interface, f"{pin}_o"): - m.d.comb += platform_pin.o.eq(getattr(interface, f"{pin}_o")[i]) - if hasattr(interface, f"{pin}_oe"): - m.d.comb += platform_pin.oe.eq(getattr(interface, f"{pin}_oe")[i]) - - _connect_interface(soc.user_spi_0, "user_spi0") - _connect_interface(soc.user_spi_1, "user_spi1") - - _connect_interface(soc.i2c_0, "i2c0") - - _connect_interface(soc.motor_pwm0, "motor_pwm0") - _connect_interface(soc.motor_pwm1, "motor_pwm1") - _connect_interface(soc.uart_1, "uart1") + # Connect LEDs to GPIO0 + for i in range(8): + led = platform.request("led", i) + m.d.comb += led.o.eq(soc.gpio_0.gpio.o[i]) - _connect_interface(soc.cpu_jtag, "cpu_jtag") + # Connect UART0 + uart = platform.request("uart") + m.d.comb += [ + uart.tx.o.eq(soc.uart_0.tx.o), + soc.uart_0.rx.i.eq(uart.rx.i), + ] return m @@ -102,7 +68,6 @@ class MyBoardStep(BoardStep): def __init__(self, config): platform = ULX3S_85F_Platform() - platform.providers = board_ulx3s_providers super().__init__(config, platform)