From c06e4697dc3d62ccb045a2a2f87d37df239ff698 Mon Sep 17 00:00:00 2001 From: Carlos de Paula Date: Wed, 25 Mar 2020 11:01:00 -0300 Subject: [PATCH] Restructured Makefile and Readme for multi-boards Added a couple of improvements to the Makefile and Readme: * Restructured the Makefile to support multiple boards based on variable * Verilator build is also done in Docker container with local option * Restructured Readme to reflect changes in the Makefile * Support for running the verilator chiselwatt binary in a Docker container in case the OS is not Linux. Signed-off-by: Carlos de Paula --- .gitignore | 13 +++++ .travis.yml | 3 +- Makefile | 139 +++++++++++++++++++++++++++++----------------------- README.md | 96 ++++++++++++++++++++---------------- 4 files changed, 148 insertions(+), 103 deletions(-) diff --git a/.gitignore b/.gitignore index 9ad7f61..fa7321f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,16 @@ test_run_dir/ *.anno.json *.fir *.vcd +insns.hex +firrtl_black_box_resource_files.f +chiselwatt_out.config +chiselwatt.svf +chiselwatt.json +chiselwatt.bit +chiselwatt +MemoryBlackBox.v +Core.v +Core.fir +Core.anno.json +LoadStoreInsns.hex +MemoryBlackBoxInsns.hex \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index b78fa8f..f290896 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,4 +6,5 @@ services: docker before_install: docker pull verilator/verilator:latest script: - docker run --rm -t -v `pwd`:/build -w /build --entrypoint /bin/bash verilator/verilator:latest -c "apt update && apt install -y default-jre-headless python3-pexpect curl && make && make check && ./scripts/test_micropython_long.py" + # Unset the VERILATOR variable so the container won't fail when running inside another container in Travis + docker run --rm -t -v `pwd`:/build -w /build --entrypoint /bin/bash verilator/verilator:latest -c "apt update && apt install -y default-jre-headless python3-pexpect curl && make VERILATOR= && make VERILATOR= check && ./scripts/test_micropython_long.py" diff --git a/Makefile b/Makefile index 46b522b..2a76672 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,23 @@ -all: chiselwatt +# Use Docker images for synthesis and verilator +DOCKER=docker +#DOCKER=podman + +PWD = $(shell pwd) +DOCKERARGS = run --rm -v $(PWD):/src -w /src +VERILATORARGS = run --name verilator --hostname verilator --rm -it --entrypoint= -v $(PWD):/work -w /work + +YOSYS = $(DOCKER) $(DOCKERARGS) ghdl/synth:beta yosys +NEXTPNR = $(DOCKER) $(DOCKERARGS) ghdl/synth:nextpnr-ecp5 nextpnr-ecp5 +ECPPACK = $(DOCKER) $(DOCKERARGS) ghdl/synth:trellis ecppack +OPENOCD = $(DOCKER) $(DOCKERARGS) --device /dev/bus/usb ghdl/synth:prog openocd +VERILATOR = $(DOCKER) $(VERILATORARGS) verilator/verilator + +# Uncomment to use local tools for synthesis +#YOSYS = yosys +#NEXTPNR = nextpnr-ecp5 +#ECPPACK = ecppack +#OPENOCD = openocd +#VERILATOR = verilator scala_files = $(wildcard src/main/scala/*scala) @@ -6,60 +25,10 @@ verilog_files = Core.v MemoryBlackBox.v verilator_binary = chiselwatt -$(verilog_files): $(scala_files) - scripts/mill chiselwatt.run - -$(verilator_binary): $(verilog_files) chiselwatt.cpp uart.c - # Warnings disabled until we fix the Chisel issues - #verilator -O3 -Wall --assert --cc Core.v --exe chiselwatt.cpp uart.c #--trace - verilator -O3 --assert --cc Core.v --exe chiselwatt.cpp uart.c -o $@ #--trace - make -C obj_dir -f VCore.mk - @cp -f obj_dir/chiselwatt chiselwatt - -clean: - @rm -f Core.fir firrtl_black_box_resource_files.f Core.v Core.anno.json MemoryBlackBox.v - @rm -rf obj_dir test_run_dir target project - @rm -f chiselwatt - @rm -f *.bit *.json *.svf *.config - @rm -f LoadStoreInsns.hex MemoryBlackBoxInsns.hex - -scala_tests: $(verilator_binary) - scripts/mill chiselwatt.test - tests = $(sort $(patsubst tests/%.out,%,$(wildcard tests/*.out))) -check: scala_tests $(tests) - -$(tests): $(verilator_binary) - @./scripts/run_test.sh $@ - -# Use local tools for synthesis -#YOSYS = yosys -#NEXTPNR = nextpnr-ecp5 -#ECPPACK = ecppack -#OPENOCD = openocd - -# Use Docker images for synthesis -DOCKER=docker -#DOCKER=podman -# -PWD = $(shell pwd) -DOCKERARGS = run --rm -v $(PWD):/src -w /src -# -YOSYS = $(DOCKER) $(DOCKERARGS) ghdl/synth:beta yosys -NEXTPNR = $(DOCKER) $(DOCKERARGS) ghdl/synth:nextpnr-ecp5 nextpnr-ecp5 -ECPPACK = $(DOCKER) $(DOCKERARGS) ghdl/synth:trellis ecppack -OPENOCD = $(DOCKER) $(DOCKERARGS) --device /dev/bus/usb ghdl/synth:prog openocd - - -# OrangeCrab with ECP85 -#LPF=constraints/orange-crab.lpf -#PLL=pll/pll_bypass.v -#PACKAGE=CSFBGA285 -#NEXTPNR_FLAGS=--um5g-85k --freq 50 -#OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg -#OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg - +# Define board parameters +ifeq ($(ECP5_BOARD),evn) # ECP5-EVN LPF=constraints/ecp5-evn.lpf PLL=pll/pll_ehxplll.v @@ -67,16 +36,56 @@ PACKAGE=CABGA381 NEXTPNR_FLAGS=--um5g-85k --freq 12 OPENOCD_JTAG_CONFIG=openocd/ecp5-evn.cfg OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg - +else ifeq ($(ECP5_BOARD),orangecrab) +# OrangeCrab with ECP85 +LPF=constraints/orange-crab.lpf +PLL=pll/pll_bypass.v +PACKAGE=CSFBGA285 +NEXTPNR_FLAGS=--um5g-85k --freq 50 +OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg +OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg +else ifeq ($(ECP5_BOARD),colorlight) # Colorlight 5A-75B -#LPF=constraints/colorlight_5A-75B.lpf -#PLL=pll/pll_ehxplll_25MHz.v -#PACKAGE=CABGA256 -#NEXTPNR_FLAGS=--25k --freq 25 -#OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg -#OPENOCD_DEVICE_CONFIG=openocd/LFE5U-25F.cfg +LPF=constraints/colorlight_5A-75B.lpf +PLL=pll/pll_ehxplll_25MHz.v +PACKAGE=CABGA256 +NEXTPNR_FLAGS=--25k --freq 25 +OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg +OPENOCD_DEVICE_CONFIG=openocd/LFE5U-25F.cfg +else +endif -synth: chiselwatt.bit +# Targets + +all: chiselwatt + +$(verilog_files): $(scala_files) + scripts/mill chiselwatt.run + +$(verilator_binary): $(verilog_files) chiselwatt.cpp uart.c +# Warnings disabled until we fix the Chisel issues +#$(VERILATOR) verilator -O3 -Wall --assert --cc Core.v --exe chiselwatt.cpp uart.c #--trace + $(VERILATOR) verilator -O3 --assert --cc Core.v --exe chiselwatt.cpp uart.c -o $@ #--trace + $(VERILATOR) make -C obj_dir -f VCore.mk + @cp -f obj_dir/chiselwatt chiselwatt + +scala_tests: $(verilator_binary) + scripts/mill chiselwatt.test + +check: scala_tests $(tests) + +$(tests): $(verilator_binary) + @./scripts/run_test.sh $@ + +dockerlator: chiselwatt + @echo "To execute chiselwatt Verilator binary, run ./chiselwatt at the prompt." +# Mask exit code from verilator on Make + @$(VERILATOR) bash || true + +synth: test-vars chiselwatt.bit + +test-vars: + @test -n "$(LPF)" || (echo "If synthesizing, use \"synth\" target with ECP5_BOARD variable to either \"evn\", \"orangecrab\", \"colorlight\"\n" ; exit 1) chiselwatt.json: insns.hex $(verilog_files) $(PLL) toplevel.v $(YOSYS) -p "read_verilog -sv $(verilog_files) $(PLL) toplevel.v; synth_ecp5 -json $@ -top toplevel" @@ -92,5 +101,13 @@ chiselwatt.svf: chiselwatt.bit prog: chiselwatt.svf $(OPENOCD) -f $(OPENOCD_JTAG_CONFIG) -f $(OPENOCD_DEVICE_CONFIG) -c "transport select jtag; init; svf $<; exit" +clean: + @rm -f Core.fir firrtl_black_box_resource_files.f Core.v Core.anno.json MemoryBlackBox.v + @rm -rf obj_dir test_run_dir target project + @rm -f chiselwatt + @rm -f *.bit *.json *.svf *.config + @rm -f LoadStoreInsns.hex MemoryBlackBoxInsns.hex + .PHONY: clean prog .PRECIOUS: chiselwatt.json chiselwatt_out.config chiselwatt.bit + diff --git a/README.md b/README.md index 755ca1c..75a034d 100644 --- a/README.md +++ b/README.md @@ -4,32 +4,39 @@ A tiny POWER Open ISA soft processor written in Chisel. ## Simulation using verilator -* Chiselwatt uses `verilator` for simulation. Either install this from your -distro or build it. On Fedora you can install the distro version using: +* Chiselwatt uses `verilator` for simulation. It is built by default and run in +a Docker container. To build with local verilator install, edit `Makefile`. + +* First build chiselwatt: ```sh -$ sudo dnf install verilator -``` - -* Next build chiselwatt: - -```sh -$ git clone https://github.com/antonblanchard/chiselwatt -$ cd chiselwatt -$ make +git clone https://github.com/antonblanchard/chiselwatt +cd chiselwatt +make ``` * A micropython image is included in the repo. To use it, link the memory image into chiselwatt: ```sh -$ ln -s micropython/firmware.hex insns.hex +ln -s micropython/firmware.hex insns.hex ``` * Now run chiselwatt: ```sh -$ ./chiselwatt +./chiselwatt +``` + +* If your operating system is not Linux, run chiselwatt inside a container: + +```sh +make dockerlator +# Inside the container prompt, run: +./chiselwatt + +# type "exit" to exit the container +exit ``` ## Building micropython from scratch @@ -42,11 +49,11 @@ example below I installed it in usr/local/powerpc64le-power8--glibc--bleeding-ed and the tools begin with `powerpc64-linux-*`: ```sh -$ git clone https://github.com/micropython/micropython.git -$ cd micropython -$ cd ports/powerpc -$ make CROSS_COMPILE=/usr/local/powerpc64le-power8--glibc--bleeding-edge-2018.11-1/bin/powerpc64le-linux- -j$(nproc) -$ cd ../../../ +git clone https://github.com/micropython/micropython.git +cd micropython +cd ports/powerpc +make CROSS_COMPILE=/usr/local/powerpc64le-power8--glibc--bleeding-edge-2018.11-1/bin/powerpc64le-linux- -j$(nproc) +cd ../../../ ``` * Build chiselwatt, import the the micropython image and run it. We use @@ -54,24 +61,22 @@ bin2hex.py to convert a binary file into a series of 64 bit hex values expected by the tools: ```sh -$ cd chiselwatt -$ make -$ scripts/bin2hex.py ../micropython/ports/powerpc/build/firmware.bin > insns.hex -$ ./chiselwatt +cd chiselwatt +make +scripts/bin2hex.py ../micropython/ports/powerpc/build/firmware.bin > insns.hex +./chiselwatt ``` ## Synthesis using Open Source tools (yosys/nextpnr) Synthesis on FPGAs is supported with yosys/nextpnr. At the moment the tools support -Lattice ECP5 FPGAs. It uses Docker images, so no software other than Docker needs +Lattice ECP5 FPGAs. The build process uses Docker images, so no software other than Docker needs to be installed. If you prefer podman you can use that too, just adjust it in `Makefile`, `DOCKER=podman`. -Edit `Makefile` to configure your FPGA, JTAG device etc. - ### hello_world -hello_world should run everywhere, so start with it. Edit `src/main/scala/Core.scala` +The `hello_world` example should run everywhere, so start with it. Edit `src/main/scala/Core.scala` and set memory to 16 kB (`16*1024`): ``` @@ -81,19 +86,27 @@ chisel3.Driver.execute(Array[String](), () => new Core(64, 16*1024, "insns.hex", Then link in the hello_world image: ```sh -$ ln -s hello_world/hello_world.hex insns.hex +ln -s hello_world/hello_world.hex insns.hex ``` -To build: +### Building and programming the FPGA + +The `Makefile` currently supports the following FPGA boards by defining the `ECP5_BOARD` parameter on make: + +* Lattice [ECP5 Evaluation Board](http://www.latticesemi.com/ecp5-evaluation) - `evn` +* Greg Davill [Orangecrab](https://github.com/gregdavill/OrangeCrab) - `orangecrab` +* Q3k [Colorlight](https://github.com/q3k/chubby75/tree/master/5a-75b) - `colorlight` + +For example, to build for the Evaluation Board, run: ```sh -$ make chiselwatt.bit +make ECP5_BOARD=evn synth` ``` and to program the FPGA: ```sh -$ make prog +make ECP5_BOARD=evn prog ``` If you connect to the serial port of the FPGA at 115200 8n1, you should see "Hello World" @@ -103,7 +116,8 @@ Another option below is a simple python script. ### Micropython Unfortunately due to an issue in yosys/nextpnr, dual port RAMs are not -working. More details can be found in https://github.com/YosysHQ/yosys/issues/1101. +working. More details can be found in . + This means we use twice as much block RAM as you would expect. This also means Micropython won't fit on an ECP5 85F, because the ~400kB of available BRAM is halved to ~200k. Micropython requires 384 kB. @@ -117,25 +131,24 @@ chisel3.Driver.execute(Array[String](), () => new Core(64, 384*1024, "insns.hex" Then link in the micropython image: ```sh -$ ln -s micropython/firmware.hex insns.hex +ln -s micropython/firmware.hex insns.hex ``` -To build: +For example, to build for the Orangecrab, run: ```sh -$ make chiselwatt.bit +make ECP5_BOARD=orangecrab synth` ``` and to program the FPGA: ```sh -$ make prog +make ECP5_BOARD=orangecrab prog ``` ## Simple Python script for reading USB serial port ```python - #!/usr/bin/python import serial @@ -158,8 +171,9 @@ while 1: ## Issues -Now that it is functional, we have a number of things to add -- A few instructions -- Wishbone interconnect -- Caches -- Pipelining and bypassing +Now that it is functional, we have a number of things to add: + +* A few instructions +* Wishbone interconnect +* Caches +* Pipelining and bypassing