From 28e4704ed83ebeb6a8302392da67722499fe3420 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Sat, 6 Jul 2024 16:55:42 +0200 Subject: [PATCH 01/34] Lock arch-tests in CI to 3.9 until incompatibility is resolved riscv-arch-test 3.9.1 fails to run with errors about multiple definitions of _start. Needs more investigation before updating. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 012ae92..8699e46 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: echo $GITHUB_WORKSPACE/sail-riscv >> $GITHUB_PATH - name: Init arch tests - run: riscof arch-test --clone + run: riscof arch-test --clone --get-version 3.9 - name: Run RV32I compliance tests run: riscof run --config=$SERV/verif/config.ini --suite=riscv-arch-test/riscv-test-suite/rv32i_m/I --env=riscv-arch-test/riscv-test-suite/env --no-browser From 830d8084b0a32956b59fe694b1ed5fc48226818c Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Fri, 2 Aug 2024 16:40:56 +0200 Subject: [PATCH 02/34] Update to Zephyr 3.7.0 --- west.yml | 2 +- zephyr/soc/riscv/servant/CMakeLists.txt | 1 + zephyr/soc/riscv/servant/cpu_idle.c | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 zephyr/soc/riscv/servant/cpu_idle.c diff --git a/west.yml b/west.yml index 1f14b1a..cc4c437 100644 --- a/west.yml +++ b/west.yml @@ -5,5 +5,5 @@ manifest: projects: - name: zephyr remote: zephyrproject-rtos - revision: v3.5.0 + revision: v3.7.0 import: true diff --git a/zephyr/soc/riscv/servant/CMakeLists.txt b/zephyr/soc/riscv/servant/CMakeLists.txt index ffe3a45..aee4e42 100644 --- a/zephyr/soc/riscv/servant/CMakeLists.txt +++ b/zephyr/soc/riscv/servant/CMakeLists.txt @@ -4,4 +4,5 @@ zephyr_sources( soc_irq.S vector.S + cpu_idle.c irq.c) diff --git a/zephyr/soc/riscv/servant/cpu_idle.c b/zephyr/soc/riscv/servant/cpu_idle.c new file mode 100644 index 0000000..dc318c6 --- /dev/null +++ b/zephyr/soc/riscv/servant/cpu_idle.c @@ -0,0 +1,22 @@ +#include +#include + +// Override arch_cpu_idle() and arch_cpu_atomic_idle() to prevent insertion +// of `wfi` instructions, which lock up our system. This was introduced in +// Zephyr 3.6.0 with commit 5fb6e267f629dedb8382da6bcad8018b1bb8930a. +// +// This is probably a hardware bug in SERV. This issue is tracked as #131. +// https://github.com/olofk/serv/issues/131 + +void arch_cpu_idle(void) +{ + sys_trace_idle(); + irq_unlock(MSTATUS_IEN); +} + +void arch_cpu_atomic_idle(unsigned int key) +{ + sys_trace_idle(); + irq_unlock(key); +} + From 1fc6e7da9bd6cd94ddc3889fabe62d9674904c22 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Thu, 22 Aug 2024 22:11:24 +0200 Subject: [PATCH 03/34] Set correct value of mstatus[mpp] The correct value of mstatus[mpp] for machine-mode is 11, but SERV had this set to 00. Changes in the regression test suite uncovered this error. --- rtl/serv_csr.v | 4 +++- rtl/serv_state.v | 4 ++++ rtl/serv_top.v | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/rtl/serv_csr.v b/rtl/serv_csr.v index 1a2cdfc..2db8207 100644 --- a/rtl/serv_csr.v +++ b/rtl/serv_csr.v @@ -14,6 +14,8 @@ module serv_csr input wire i_cnt0to3, input wire i_cnt3, input wire i_cnt7, + input wire i_cnt11, + input wire i_cnt12, input wire i_cnt_done, input wire i_mem_op, input wire i_mtip, @@ -63,7 +65,7 @@ module serv_csr (i_csr_source == CSR_SOURCE_CSR) ? csr_out : {W{1'bx}}; - assign csr_out = ({i_mstatus_en & mstatus_mie & i_cnt3 & i_en,{B{1'b0}}}) | + assign csr_out = (i_mstatus_en & i_en & ((mstatus_mie & i_cnt3) | (i_cnt11 | i_cnt12))) | i_rf_csr_out | ({W{i_mcause_en & i_en}} & mcause); diff --git a/rtl/serv_state.v b/rtl/serv_state.v index 348d319..4e0f293 100644 --- a/rtl/serv_state.v +++ b/rtl/serv_state.v @@ -20,6 +20,8 @@ module serv_state output wire o_cnt2, output wire o_cnt3, output wire o_cnt7, + output wire o_cnt11, + output wire o_cnt12, output wire o_cnt_done, output wire o_bufreg_en, output wire o_ctrl_pc_en, @@ -77,6 +79,8 @@ module serv_state assign o_cnt2 = (o_cnt[4:2] == 3'd0) & cnt_r[2]; assign o_cnt3 = (o_cnt[4:2] == 3'd0) & cnt_r[3]; assign o_cnt7 = (o_cnt[4:2] == 3'd1) & cnt_r[3]; + assign o_cnt11 = (o_cnt[4:2] == 3'd2) & cnt_r[3]; + assign o_cnt12 = (o_cnt[4:2] == 3'd3) & cnt_r[0]; //Take branch for jump or branch instructions (opcode == 1x0xx) if //a) It's an unconditional branch (opcode[0] == 1) diff --git a/rtl/serv_top.v b/rtl/serv_top.v index a4e9a90..37a9f03 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -117,6 +117,8 @@ module serv_top wire cnt2; wire cnt3; wire cnt7; + wire cnt11; + wire cnt12; wire cnt_done; @@ -241,6 +243,8 @@ module serv_top .o_cnt2 (cnt2), .o_cnt3 (cnt3), .o_cnt7 (cnt7), + .o_cnt11 (cnt11), + .o_cnt12 (cnt12), .o_cnt_done (cnt_done), .o_bufreg_en (bufreg_en), .o_ctrl_pc_en (ctrl_pc_en), @@ -546,6 +550,8 @@ module serv_top .i_cnt0to3 (cnt0to3), .i_cnt3 (cnt3), .i_cnt7 (cnt7), + .i_cnt11 (cnt11), + .i_cnt12 (cnt12), .i_cnt_done (cnt_done), .i_mem_op (!mtval_pc), .i_mtip (i_timer_irq), From 40d34d204a5fd1356e1f84e2c791e3a4b29d0112 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Thu, 22 Aug 2024 22:14:04 +0200 Subject: [PATCH 04/34] Avoid matching misa CSR as mstatus Reads from the (unimplemented) misa register matched mstatus which in turn caused garbage data to be written to other CSRs. Make the matching mask slightly stricter to avoid this particular issue. --- rtl/serv_decode.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index 3719819..54ed74b 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -188,7 +188,7 @@ module serv_decode wire co_rd_csr_en = csr_op; wire co_csr_en = csr_op & csr_valid; - wire co_csr_mstatus_en = csr_op & !op26 & !op22; + wire co_csr_mstatus_en = csr_op & !op26 & !op22 & !op20; wire co_csr_mie_en = csr_op & !op26 & op22 & !op20; wire co_csr_mcause_en = csr_op & op21 & !op20; From 24006a7297b69caec78a69953ce10d93deeb9106 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Thu, 22 Aug 2024 22:18:07 +0200 Subject: [PATCH 05/34] Fix symbols and linker script for compliance tests --- verif/plugin-serv/env/link.ld | 5 +---- verif/plugin-serv/env/model_test.h | 9 ++------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/verif/plugin-serv/env/link.ld b/verif/plugin-serv/env/link.ld index db7be33..0225e89 100644 --- a/verif/plugin-serv/env/link.ld +++ b/verif/plugin-serv/env/link.ld @@ -1,15 +1,12 @@ OUTPUT_ARCH( "riscv" ) -ENTRY(_start) +ENTRY(rvtest_entry_point) SECTIONS { . = 0x00000000; .text.init : { *(.text.init) } - . = ALIGN(0x1000); .tohost : { *(.tohost) } - . = ALIGN(0x1000); .text : { *(.text) } - . = ALIGN(0x1000); .data : { *(.data) } .data.string : { *(.data.string)} .bss : { *(.bss) } diff --git a/verif/plugin-serv/env/model_test.h b/verif/plugin-serv/env/model_test.h index e247bf8..f7ffdf1 100644 --- a/verif/plugin-serv/env/model_test.h +++ b/verif/plugin-serv/env/model_test.h @@ -48,12 +48,7 @@ .align 4; .global end_signature; end_signature: \ -#define RVMODEL_BOOT \ -.section .text.init; \ - .align 4; \ - .globl _start; \ -_start: - +#define RVMODEL_BOOT #define LOCAL_IO_WRITE_STR(_STR) RVMODEL_IO_WRITE_STR(x31, _STR) #define RVMODEL_IO_WRITE_STR(_SP, _STR) @@ -68,4 +63,4 @@ _start: #define RVMODEL_CLEAR_MTIMER_INT #define RVMODEL_CLEAR_MEXT_INT -#endif // _COMPLIANCE_MODEL_H \ No newline at end of file +#endif // _COMPLIANCE_MODEL_H From 7065906532bfda548e4615fcbf36efde6216b81a Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 1 Oct 2024 20:12:40 +0200 Subject: [PATCH 06/34] Improve data sheet --- doc/conf.py | 1 + doc/datasheet.rst | 1 + doc/interface.rst | 29 +++++++++++++++++++++++++++++ doc/overview.rst | 42 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+) create mode 100644 doc/overview.rst diff --git a/doc/conf.py b/doc/conf.py index e2aa689..9c639e6 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -28,6 +28,7 @@ author = 'Olof Kindgren' # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ + 'sphinx.ext.autosectionlabel', 'sphinxcontrib.wavedrom' ] diff --git a/doc/datasheet.rst b/doc/datasheet.rst index a9e8d89..0c54ad4 100644 --- a/doc/datasheet.rst +++ b/doc/datasheet.rst @@ -2,4 +2,5 @@ Datasheet ********* +.. include:: overview.rst .. include:: interface.rst diff --git a/doc/interface.rst b/doc/interface.rst index 8edbedb..4e5cd72 100644 --- a/doc/interface.rst +++ b/doc/interface.rst @@ -1,6 +1,9 @@ Interface ========= +Top level +--------- + Users of SERV can choose to use either serv_top or serv_rf_top depending on what best fits the application. serv_top contains all the main logic of SERV except for the actual storage for the register file (RF). .. image:: serv_top.png @@ -191,3 +194,29 @@ Signals - 1 - in - RF interface channel 1 read data + +Extension interface +------------------- + +The SERV CPU, being the smallest RISC-V CPU, has a design that is primarily focused on simplicity and minimalism. However, to increase its utility without complicating the core design, it can be extended using an extension interface. The extension interface allows additional functionality to be added to the SERV CPU core through custom accelerators that are called for when specific instructions are encountered. SERV has built-in support for connecting an MDU (Multiplication/Division Unit) that implements the M ISA extension by setting the MDU parameter. Other accelerators need changes to the decoder. + +When SERV detects instructions to be executed by an external accelerator through the extension interface, it will treat them as :ref:`two-stage operations`. In stage 1, the values in `o_ext_rs1` and `o_ext_rs2` are prepared to be sent to the accelerator. Once stage 1 is completed, SERV will assert the corresponding valid signal for the accelerator (e.g. `o_mdu_valid` for the M extension accelerator). The accelerator can now perform its work and when it has completed its result it will return that value in `i_ext_rd` and strobe `i_ext_ready` for one cycle. The following cycle, SERV will start stage two and store the received result. The waveform below explains this in more detail. + +.. wavedrom:: + + { signal: [ + { name: "clk" , wave: "P...|...|...|..."}, + { name: "init" , wave: "1...|..0|...|...", node: ".......d..", data: "r0"}, + { name: "o_rf_wreq" , wave: "0...|...|10.|...", node: ".........g", data: "r1"}, + { name: "i_rf_ready" , wave: "010.|...|10.|...", node: ".a.......h.", data: "r1"}, + { name: "cnt_en" , wave: "0.1.|..0|.1.|..0", node: "..b.......i"}, + { name: "cnt_done" , wave: "0...|.10|...|.10", node: "......c.."}, + { name: "o_ext_rs1" , wave: ".234567x|...|...", node: "..", data: "d0 d1 ... d30 d31"}, + { name: "o_ext_rs2" , wave: ".234567x|...|...", node: "..", data: "d0 d1 ... d30 d31"}, + { name: "o_mdu_valid", wave: "0...|..1|.0.|...", node: ".......e", data: "0 1 ... 30 31"}, + { name: "i_ext_ready", wave: "0...|...|10.|...", node: ".........f", data: "0 1 ... 30 31"}, + { name: "i_ext_rd" , wave: "....|...|234567x", node: "..", data: "d0 d1 ... d30 d31"}, + ], + edge : [ + "a~>b", "c~>d", "e~>f", "f~>g", "h~>i"] + } diff --git a/doc/overview.rst b/doc/overview.rst new file mode 100644 index 0000000..2d4bad0 --- /dev/null +++ b/doc/overview.rst @@ -0,0 +1,42 @@ +Overview +======== + +The SERV RISC-V CPU is an award-winning and highly compact processor core based on the RISC-V instruction set architecture (ISA). It is designed to be the smallest possible RISC-V compliant CPU and is particularly well-suited for embedded systems and applications where silicon area is critical. + +Key Features +------------ + +* **ISA:** RISC-V RV32IZifencei +* **Optional ISA extensions:** C, M, Zicsr +* **Optional features:** Timer interrupts, Extension interface +* **Architecture:** Bit-serial (one bit processed per clock cycle) +* **License:** ISC (available under other commercial licenses upon request) +* **OS support:** Zephyr 3.7 +* **SW support:** Compatible with standard RISC-V toolchains +* **Area:** Smallest RISC-V core available + +Applications +------------ + +* **Embedded Systems:** Ideal for minimalistic embedded control tasks +* **IoT Devices:** Suitable for Internet of Things devices where space and power are limited +* **Education:** Excellent resource for teaching and understanding the RISC-V architecture and CPU design +* **Research:** Platform for research in minimalistic computing designs and for bringing up new fabrication processes + +Area +---- + +.. list-table:: Area for minimal configuration [#]_ + :widths: 25 25 25 25 + :header-rows: 1 + + * - Lattice iCE40 + - Altera Cyclone10LP + - AMD Artix-7 + - CMOS + * - 198LUT/164FF + - 239LUT/164FF + - 125LUT/164FF + - 2.1kGE + +.. [#] Excluding register file From c12fecb4f637617769537105b73cff4d40290f53 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 1 Oct 2024 21:31:40 +0200 Subject: [PATCH 07/34] Syntax fix for Servant docs --- doc/servant.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/servant.rst b/doc/servant.rst index b188a24..8828a9d 100644 --- a/doc/servant.rst +++ b/doc/servant.rst @@ -184,7 +184,7 @@ Pin B1 is used for UART output with 115200 baud rate. The serial port on Kolibri ldprog -Ks build/servant_1.3.0/machdyne_kolibri-icestorm/servant_1.3.0.bin MAX10 10M08 Evaluation Kit -^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^ FPGA Pin 75 (Arduino_IO01 J5 pin 7) is used for UART output with 57600 baud rate. SW1 is reset and Led 1 q output. From f001e5b09eb16a5f538b78620ee0e2da0b54c1d9 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 1 Oct 2024 22:52:58 +0200 Subject: [PATCH 08/34] Update verilator waiver file --- data/verilator_waiver.vlt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/verilator_waiver.vlt b/data/verilator_waiver.vlt index 8e90edc..212044f 100644 --- a/data/verilator_waiver.vlt +++ b/data/verilator_waiver.vlt @@ -1,6 +1,6 @@ `verilator_config // Bits [1:0] in i_wb_rdt are not used at all -lint_off -rule UNUSED -file "*/serv_top.v" -lines 178 +lint_off -rule UNUSED -file "*/serv_top.v" -lines 179 //Some bits in the instruction word are not used in serv_decode but it's easier //to just send in the whole word than picking out bits From 7b1044c01c7ab52d7a1320940631e26db9a8d974 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 1 Oct 2024 22:56:36 +0200 Subject: [PATCH 09/34] Fix GDS generation gh action --- .github/workflows/openlane.yml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/openlane.yml b/.github/workflows/openlane.yml index 1c3324f..ab069c6 100644 --- a/.github/workflows/openlane.yml +++ b/.github/workflows/openlane.yml @@ -2,19 +2,23 @@ name: Build GDS using OpenLANE and sky130 PDK on: [push] jobs: - build-openlane: + build-openlane-sky130: runs-on: ubuntu-latest + env: + REPO : serv + VLNV : serv steps: - - name: Checkout subservient + - name: Checkout repo uses: actions/checkout@v4 - - name: Build with Openlane - uses: librecores/ci-fusesoc-action@migrate-dockerized with: - core: serv - target: sky130 - tool: openlane + path: serv + - run: echo "EDALIZE_LAUNCHER=el_docker" >> $GITHUB_ENV + - run: pip3 install fusesoc + - run: fusesoc library add $REPO $GITHUB_WORKSPACE/$REPO + - run: fusesoc run --target=sky130 $VLNV + - run: find -name *.gds - name: Store artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: serv.gds - path: /home/runner/work/serv/serv/build/serv_1.3.0/sky130-openlane/gds/serv_synth_wrapper.gds + path: /home/runner/work/serv/serv/serv/build/serv_1.3.0/sky130-openlane/runs/serv_synth_wrapper/results/final/gds/serv_synth_wrapper.gds From 7865252e042a5976a5ae422749ea98215bf15fae Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Wed, 2 Oct 2024 09:24:54 +0200 Subject: [PATCH 10/34] Fix CI badge in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bded006..6ae45f6 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # SERV [![Join the chat at https://gitter.im/librecores/serv](https://badges.gitter.im/librecores/serv.svg)](https://gitter.im/librecores/serv?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![CI status](https://github.com/olofk/serv/workflows/CI/badge.svg)](https://github.com/olofk/serv/actions?query=workflow%3ACI) +[![Compliance tests](https://github.com/olofk/serv/actions/workflows/ci.yml/badge.svg)](https://github.com/olofk/serv/actions/workflows/ci.yml) [![Documentation Status](https://readthedocs.org/projects/serv/badge/?version=latest)](https://serv.readthedocs.io/en/latest/?badge=latest) SERV is an award-winning bit-serial RISC-V core From 4f04e9d933ba28e8fb75419dc66b8bcbb71027d5 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Sat, 5 Oct 2024 11:27:04 +0200 Subject: [PATCH 11/34] Use latest regression test suite in CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8699e46..012ae92 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: echo $GITHUB_WORKSPACE/sail-riscv >> $GITHUB_PATH - name: Init arch tests - run: riscof arch-test --clone --get-version 3.9 + run: riscof arch-test --clone - name: Run RV32I compliance tests run: riscof run --config=$SERV/verif/config.ini --suite=riscv-arch-test/riscv-test-suite/rv32i_m/I --env=riscv-arch-test/riscv-test-suite/env --no-browser From 1c5d44e5c4ee2ccb6fef993262c53af79993fadb Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Sat, 5 Oct 2024 11:27:51 +0200 Subject: [PATCH 12/34] Make CSR module 4-bit compatible --- rtl/serv_csr.v | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/rtl/serv_csr.v b/rtl/serv_csr.v index 2db8207..547accf 100644 --- a/rtl/serv_csr.v +++ b/rtl/serv_csr.v @@ -65,7 +65,17 @@ module serv_csr (i_csr_source == CSR_SOURCE_CSR) ? csr_out : {W{1'bx}}; - assign csr_out = (i_mstatus_en & i_en & ((mstatus_mie & i_cnt3) | (i_cnt11 | i_cnt12))) | + wire [B:0] mstatus; + + generate + if (W==1) begin : gen_mstatus_w1 + assign mstatus = ((mstatus_mie & i_cnt3) | (i_cnt11 | i_cnt12)); + end else if (W==4) begin : gen_mstatus_w4 + assign mstatus = {i_cnt11 | (mstatus_mie & i_cnt3), 2'b00, i_cnt12}; + end + endgenerate + + assign csr_out = ({W{i_mstatus_en & i_en}} & mstatus) | i_rf_csr_out | ({W{i_mcause_en & i_en}} & mcause); From 376dcd701db9388e10e36afc8301f7211f8c430a Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Sat, 5 Oct 2024 12:02:34 +0200 Subject: [PATCH 13/34] Introduce width parameter Expose the width (or W internally) parameter to set the SERV datapath width. Note: Only width=1 is function at this time. --- bench/servant_sim.v | 2 ++ bench/servant_tb.v | 8 ++++- data/verilator_waiver.vlt | 6 ++-- rtl/serv_rf_top.v | 17 ++++++---- rtl/serv_top.v | 68 +++++++++++++++++++++------------------ servant.core | 7 ++++ servant/servant.v | 7 ++-- servile/servile.v | 14 +++++--- serving/serving.v | 1 + 9 files changed, 79 insertions(+), 51 deletions(-) diff --git a/bench/servant_sim.v b/bench/servant_sim.v index c5e2f65..dc744d1 100644 --- a/bench/servant_sim.v +++ b/bench/servant_sim.v @@ -8,6 +8,7 @@ module servant_sim parameter memfile = ""; parameter memsize = 8192; + parameter width = 1; parameter with_csr = 1; parameter compressed = 0; parameter align = compressed; @@ -22,6 +23,7 @@ module servant_sim servant #(.memfile (memfile), .memsize (memsize), + .width (width), .sim (1), .with_csr (with_csr), .compress (compressed[0:0]), diff --git a/bench/servant_tb.v b/bench/servant_tb.v index 1952520..be42a98 100644 --- a/bench/servant_tb.v +++ b/bench/servant_tb.v @@ -3,8 +3,13 @@ module servant_tb; parameter memfile = "hello_uart.hex"; parameter memsize = 8192; + parameter width = 1; parameter with_csr = 1; + localparam baud_rate = + (width == 4) ? 57600*3 : + 57600; + reg wb_clk = 1'b0; reg wb_rst = 1'b1; @@ -15,11 +20,12 @@ module servant_tb; vlog_tb_utils vtu(); - uart_decoder #(57600) uart_decoder (q); + uart_decoder #(baud_rate) uart_decoder (q); servant_sim #(.memfile (memfile), .memsize (memsize), + .width (width), .with_csr (with_csr)) dut (.wb_clk (wb_clk), diff --git a/data/verilator_waiver.vlt b/data/verilator_waiver.vlt index 212044f..0e9d1dc 100644 --- a/data/verilator_waiver.vlt +++ b/data/verilator_waiver.vlt @@ -1,14 +1,12 @@ `verilator_config // Bits [1:0] in i_wb_rdt are not used at all -lint_off -rule UNUSED -file "*/serv_top.v" -lines 179 +lint_off -rule UNUSED -file "*/serv_top.v" -lines 181 //Some bits in the instruction word are not used in serv_decode but it's easier //to just send in the whole word than picking out bits lint_off -rule UNUSED -file "*/serv_decode.v" -lines 8 -lint_off -rule UNUSED -file "*/serv_top.v" -lines 177 - //Some variables are only used when we connect an Extension with serv_decode -lint_off -rule UNUSED -file "*/serv_top.v" -lines 67 +lint_off -rule UNUSED -file "*/serv_top.v" -lines 69 diff --git a/rtl/serv_rf_top.v b/rtl/serv_rf_top.v index da81c7b..8eeaa42 100644 --- a/rtl/serv_rf_top.v +++ b/rtl/serv_rf_top.v @@ -28,7 +28,8 @@ module serv_rf_top */ parameter RESET_STRATEGY = "MINI", parameter WITH_CSR = 1, - parameter RF_WIDTH = 2, + parameter W = 1, + parameter RF_WIDTH = W * 2, parameter RF_L2D = $clog2((32+(WITH_CSR*4))*32/RF_WIDTH)) ( input wire clk, @@ -86,13 +87,13 @@ module serv_rf_top wire [4+WITH_CSR:0] wreg1; wire wen0; wire wen1; - wire wdata0; - wire wdata1; + wire [W-1:0] wdata0; + wire [W-1:0] wdata1; wire [4+WITH_CSR:0] rreg0; wire [4+WITH_CSR:0] rreg1; wire rf_ready; - wire rdata0; - wire rdata1; + wire [W-1:0] rdata0; + wire [W-1:0] rdata1; wire [RF_L2D-1:0] waddr; wire [RF_WIDTH-1:0] wdata; @@ -104,7 +105,8 @@ module serv_rf_top serv_rf_ram_if #(.width (RF_WIDTH), .reset_strategy (RESET_STRATEGY), - .csr_regs (CSR_REGS)) + .csr_regs (CSR_REGS), + .W(W)) rf_ram_if (.i_clk (clk), .i_rst (i_rst), @@ -147,7 +149,8 @@ module serv_rf_top .WITH_CSR (WITH_CSR), .MDU(MDU), .COMPRESSED(COMPRESSED), - .ALIGN(ALIGN)) + .ALIGN(ALIGN), + .W(W)) cpu ( .clk (clk), diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 37a9f03..e01324d 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -2,6 +2,8 @@ module serv_top #(parameter WITH_CSR = 1, + parameter W = 1, + parameter B = W-1, parameter PRE_REGISTER = 1, parameter RESET_STRATEGY = "MINI", parameter RESET_PC = 32'd0, @@ -43,12 +45,12 @@ module serv_top output wire [4+WITH_CSR:0] o_wreg1, output wire o_wen0, output wire o_wen1, - output wire o_wdata0, - output wire o_wdata1, + output wire [B:0] o_wdata0, + output wire [B:0] o_wdata1, output wire [4+WITH_CSR:0] o_rreg0, output wire [4+WITH_CSR:0] o_rreg1, - input wire i_rdata0, - input wire i_rdata1, + input wire [B:0] i_rdata0, + input wire [B:0] i_rdata1, output wire [31:0] o_ibus_adr, output wire o_ibus_cyc, @@ -92,10 +94,10 @@ module serv_top wire rd_alu_en; wire rd_csr_en; wire rd_mem_en; - wire ctrl_rd; - wire alu_rd; - wire mem_rd; - wire csr_rd; + wire [B:0] ctrl_rd; + wire [B:0] alu_rd; + wire [B:0] mem_rd; + wire [B:0] csr_rd; wire mtval_pc; wire ctrl_pc_en; @@ -103,7 +105,7 @@ module serv_top wire jal_or_jalr; wire utype; wire mret; - wire imm; + wire [B:0] imm; wire trap; wire pc_rel; wire iscomp; @@ -127,8 +129,8 @@ module serv_top wire bufreg_rs1_en; wire bufreg_imm_en; wire bufreg_clr_lsb; - wire bufreg_q; - wire bufreg2_q; + wire [B:0] bufreg_q; + wire [B:0] bufreg2_q; wire [31:0] dbus_rdt; wire dbus_ack; @@ -139,11 +141,11 @@ module serv_top wire alu_cmp; wire [2:0] alu_rd_sel; - wire rs1; - wire rs2; + wire [B:0] rs1; + wire [B:0] rs2; wire rd_en; - wire op_b; + wire [B:0] op_b; wire op_b_sel; wire mem_signed; @@ -156,20 +158,20 @@ module serv_top wire mem_misalign; - wire bad_pc; + wire [B:0] bad_pc; wire csr_mstatus_en; wire csr_mie_en; wire csr_mcause_en; wire [1:0] csr_source; - wire csr_imm; + wire [B:0] csr_imm; wire csr_d_sel; wire csr_en; wire [1:0] csr_addr; - wire csr_pc; + wire [B:0] csr_pc; wire csr_imm_en; - wire csr_in; - wire rf_csr_out; + wire [B:0] csr_in; + wire [B:0] rf_csr_out; wire dbus_en; wire new_irq; @@ -226,7 +228,8 @@ module serv_top #(.RESET_STRATEGY (RESET_STRATEGY), .WITH_CSR (WITH_CSR[0:0]), .MDU(MDU), - .ALIGN(ALIGN)) + .ALIGN(ALIGN), + .W(W)) state ( .i_clk (clk), @@ -420,7 +423,8 @@ module serv_top serv_ctrl #(.RESET_PC (RESET_PC), .RESET_STRATEGY (RESET_STRATEGY), - .WITH_CSR (WITH_CSR)) + .WITH_CSR (WITH_CSR), + .W (W)) ctrl ( .clk (clk), @@ -447,7 +451,7 @@ module serv_top //External .o_ibus_adr (wb_ibus_adr)); - serv_alu alu + serv_alu #(.W (W)) alu ( .clk (clk), //State @@ -467,7 +471,7 @@ module serv_top .o_rd (alu_rd)); serv_rf_if - #(.WITH_CSR (WITH_CSR)) + #(.WITH_CSR (WITH_CSR), .W(W)) rf_if (//RF interface .i_cnt_en (cnt_en), @@ -485,7 +489,7 @@ module serv_top //Trap interface .i_trap (trap), .i_mret (mret), - .i_mepc (wb_ibus_adr[0]), + .i_mepc (wb_ibus_adr[B:0]), .i_mtval_pc (mtval_pc), .i_bufreg_q (bufreg_q), .i_bad_pc (bad_pc), @@ -516,7 +520,8 @@ module serv_top .o_csr (rf_csr_out)); serv_mem_if - #(.WITH_CSR (WITH_CSR[0:0])) + #(.WITH_CSR (WITH_CSR[0:0]), + .W (W)) mem_if ( .i_clk (clk), @@ -539,7 +544,8 @@ module serv_top generate if (|WITH_CSR) begin : gen_csr serv_csr - #(.RESET_STRATEGY (RESET_STRATEGY)) + #(.RESET_STRATEGY (RESET_STRATEGY), + .W(W)) csr ( .i_clk (clk), @@ -574,8 +580,8 @@ module serv_top .i_rs1 (rs1), .o_q (csr_rd)); end else begin : gen_no_csr - assign csr_in = 1'b0; - assign csr_rd = 1'b0; + assign csr_in = {W{1'b0}}; + assign csr_rd = {W{1'b0}}; assign new_irq = 1'b0; end endgenerate @@ -597,7 +603,7 @@ module serv_top /* Store data written to rd */ if (o_wen0) - rvfi_rd_wdata <= {o_wdata0,rvfi_rd_wdata[31:1]}; + rvfi_rd_wdata <= {o_wdata0,rvfi_rd_wdata[31:W]}; if (cnt_done & ctrl_pc_en) begin rvfi_pc_rdata <= pc; @@ -626,8 +632,8 @@ module serv_top rvfi_rd_addr <= rd_addr; end if (rs_en) begin - rvfi_rs1_rdata <= {!immdec_en[1] & rs1,rvfi_rs1_rdata[31:1]}; - rvfi_rs2_rdata <= {!immdec_en[2] & rs2,rvfi_rs2_rdata[31:1]}; + rvfi_rs1_rdata <= {(!immdec_en[1] ? rs1 : {W{1'b0}}),rvfi_rs1_rdata[31:W]}; + rvfi_rs2_rdata <= {(!immdec_en[2] ? rs2 : {W{1'b0}}),rvfi_rs2_rdata[31:W]}; end if (i_dbus_ack) begin diff --git a/servant.core b/servant.core index cf1d47e..8f1f908 100644 --- a/servant.core +++ b/servant.core @@ -580,6 +580,7 @@ targets: filesets : [soc, servant_tb] parameters : - RISCV_FORMAL + - width - "mdu? (MDU=1)" - SERV_CLEAR_RAM=true - firmware @@ -649,6 +650,7 @@ targets: - uart_baudrate - vcd - vcd_start + - width - compressed - align - with_csr=1 @@ -744,6 +746,11 @@ parameters: description : Delay start of VCD dumping until the specified time paramtype : plusarg + width: + datatype : int + description : Interal datapath width (1=SERV, 4=QERV) + paramtype : vlogparam + with_csr: datatype : int description : Enable/Disable CSR support diff --git a/servant/servant.v b/servant/servant.v index 0ced369..34cbc91 100644 --- a/servant/servant.v +++ b/servant/servant.v @@ -8,6 +8,7 @@ module servant parameter memfile = "zephyr_hello.hex"; parameter memsize = 8192; parameter reset_strategy = "MINI"; + parameter width = 1; parameter sim = 0; parameter with_csr = 1; parameter [0:0] compress = 0; @@ -23,7 +24,7 @@ module servant localparam aw = $clog2(memsize); localparam csr_regs = with_csr*4; - localparam rf_width = 2; + localparam rf_width = width * 2; localparam rf_l2d = $clog2((32+csr_regs)*32/rf_width); wire timer_irq; @@ -133,7 +134,7 @@ module servant .o_rdata (rf_rdata)); servile - #(.rf_width (rf_width), + #(.width (width), .sim (sim[0]), .with_c (compress[0]), .with_csr (with_csr[0]), @@ -159,7 +160,7 @@ module servant .o_wb_ext_stb (wb_ext_stb), .i_wb_ext_rdt (wb_ext_rdt), .i_wb_ext_ack (wb_ext_ack), - + .o_rf_waddr (rf_waddr), .o_rf_wdata (rf_wdata), .o_rf_wen (rf_wen), diff --git a/servile/servile.v b/servile/servile.v index a6f5af7..157b07d 100644 --- a/servile/servile.v +++ b/servile/servile.v @@ -8,14 +8,16 @@ `default_nettype none module servile #( + parameter width = 1, parameter reset_pc = 32'h00000000, parameter reset_strategy = "MINI", - parameter rf_width = 8, + parameter rf_width = 2*width, parameter [0:0] sim = 1'b0, parameter [0:0] with_c = 1'b0, parameter [0:0] with_csr = 1'b0, parameter [0:0] with_mdu = 1'b0, //Internally calculated. Do not touch + parameter B = width-1, parameter regs = 32+with_csr*4, parameter rf_l2d = $clog2(regs*32/rf_width)) ( @@ -78,13 +80,13 @@ module servile wire [$clog2(regs)-1:0] wreg1; wire wen0; wire wen1; - wire wdata0; - wire wdata1; + wire [B:0] wdata0; + wire [B:0] wdata1; wire [$clog2(regs)-1:0] rreg0; wire [$clog2(regs)-1:0] rreg1; wire rf_ready; - wire rdata0; - wire rdata1; + wire [B:0] rdata0; + wire [B:0] rdata1; wire [31:0] mdu_rs1; wire [31:0] mdu_rs2; @@ -149,6 +151,7 @@ module servile serv_rf_ram_if #(.width (rf_width), + .W (width), .reset_strategy (reset_strategy), .csr_regs (with_csr*4)) rf_ram_if @@ -196,6 +199,7 @@ module servile serv_top #( .WITH_CSR (with_csr?1:0), + .W (width), .PRE_REGISTER (1'b1), .RESET_STRATEGY (reset_strategy), .RESET_PC (reset_pc), diff --git a/serving/serving.v b/serving/serving.v index ef4ce63..1a12054 100644 --- a/serving/serving.v +++ b/serving/serving.v @@ -109,6 +109,7 @@ module serving servile #(.reset_pc (32'h0000_0000), .reset_strategy (RESET_STRATEGY), + .rf_width (rf_width), .sim (sim), .with_csr (WITH_CSR)) servile From 2bcf4104d0a36ab954ce3184ce8012e6505bd048 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Thu, 22 Aug 2024 22:21:41 +0200 Subject: [PATCH 14/34] Add debug module --- bench/servant_sim.v | 1 + data/verilator_waiver.vlt | 4 +- rtl/serv_debug.v | 232 ++++++++++++++++++++++++++++++++++++++ rtl/serv_rf_top.v | 2 + rtl/serv_top.v | 30 ++++- serv.core | 1 + servant/servant.v | 2 + servile/servile.v | 4 +- 8 files changed, 269 insertions(+), 7 deletions(-) create mode 100644 rtl/serv_debug.v diff --git a/bench/servant_sim.v b/bench/servant_sim.v index dc744d1..2317279 100644 --- a/bench/servant_sim.v +++ b/bench/servant_sim.v @@ -24,6 +24,7 @@ module servant_sim #(.memfile (memfile), .memsize (memsize), .width (width), + .debug (1'b1), .sim (1), .with_csr (with_csr), .compress (compressed[0:0]), diff --git a/data/verilator_waiver.vlt b/data/verilator_waiver.vlt index 0e9d1dc..d17b4a7 100644 --- a/data/verilator_waiver.vlt +++ b/data/verilator_waiver.vlt @@ -1,12 +1,12 @@ `verilator_config // Bits [1:0] in i_wb_rdt are not used at all -lint_off -rule UNUSED -file "*/serv_top.v" -lines 181 +lint_off -rule UNUSED -file "*/serv_top.v" -lines 182 //Some bits in the instruction word are not used in serv_decode but it's easier //to just send in the whole word than picking out bits lint_off -rule UNUSED -file "*/serv_decode.v" -lines 8 //Some variables are only used when we connect an Extension with serv_decode -lint_off -rule UNUSED -file "*/serv_top.v" -lines 69 +lint_off -rule UNUSED -file "*/serv_top.v" -lines 70 diff --git a/rtl/serv_debug.v b/rtl/serv_debug.v new file mode 100644 index 0000000..0d800d1 --- /dev/null +++ b/rtl/serv_debug.v @@ -0,0 +1,232 @@ +module serv_debug + #(parameter W = 1) + ( + input wire i_clk, + input wire i_rst, + input wire i_ibus_ack, + input wire [31:0] i_ibus_rdt, + input wire [4:0] i_rd_addr, + input wire i_cnt_en, + input wire i_csr_in, + input wire i_csr_mstatus_en, + input wire i_csr_mie_en, + input wire i_csr_mcause_en, + input wire i_csr_en, + input wire [1:0] i_csr_addr, + input wire i_wen0, + input wire i_wdata0, + input wire i_cnt_done); + + reg update_rd = 1'b0; + reg [31:0] dbg_rd = 32'hxxxxxxxx; + reg [31:0] dbg_csr = 32'hxxxxxxxx; + reg [31:0] dbg_mstatus = 32'hxxxxxxxx; + reg [31:0] dbg_mie = 32'hxxxxxxxx; + reg [31:0] dbg_mcause = 32'hxxxxxxxx; + reg [31:0] dbg_mscratch = 32'hxxxxxxxx; + reg [31:0] dbg_mtvec = 32'hxxxxxxxx; + reg [31:0] dbg_mepc = 32'hxxxxxxxx; + reg [31:0] dbg_mtval = 32'hxxxxxxxx; + reg [31:0] x1 = 32'hxxxxxxxx; + reg [31:0] x2 = 32'hxxxxxxxx; + reg [31:0] x3 = 32'hxxxxxxxx; + reg [31:0] x4 = 32'hxxxxxxxx; + reg [31:0] x5 = 32'hxxxxxxxx; + reg [31:0] x6 = 32'hxxxxxxxx; + reg [31:0] x7 = 32'hxxxxxxxx; + reg [31:0] x8 = 32'hxxxxxxxx; + reg [31:0] x9 = 32'hxxxxxxxx; + reg [31:0] x10 = 32'hxxxxxxxx; + reg [31:0] x11 = 32'hxxxxxxxx; + reg [31:0] x12 = 32'hxxxxxxxx; + reg [31:0] x13 = 32'hxxxxxxxx; + reg [31:0] x14 = 32'hxxxxxxxx; + reg [31:0] x15 = 32'hxxxxxxxx; + reg [31:0] x16 = 32'hxxxxxxxx; + reg [31:0] x17 = 32'hxxxxxxxx; + reg [31:0] x18 = 32'hxxxxxxxx; + reg [31:0] x19 = 32'hxxxxxxxx; + reg [31:0] x20 = 32'hxxxxxxxx; + reg [31:0] x21 = 32'hxxxxxxxx; + reg [31:0] x22 = 32'hxxxxxxxx; + reg [31:0] x23 = 32'hxxxxxxxx; + reg [31:0] x24 = 32'hxxxxxxxx; + reg [31:0] x25 = 32'hxxxxxxxx; + reg [31:0] x26 = 32'hxxxxxxxx; + reg [31:0] x27 = 32'hxxxxxxxx; + reg [31:0] x28 = 32'hxxxxxxxx; + reg [31:0] x29 = 32'hxxxxxxxx; + reg [31:0] x30 = 32'hxxxxxxxx; + reg [31:0] x31 = 32'hxxxxxxxx; + + always @(posedge i_clk) begin + update_rd <= i_cnt_done & i_wen0; + + if (i_wen0) + dbg_rd <= {i_wdata0,dbg_rd[31:W]}; + + //End of instruction that writes to RF + if (update_rd) begin + case (i_rd_addr) + 5'd1 : x1 <= dbg_rd; + 5'd2 : x2 <= dbg_rd; + 5'd3 : x3 <= dbg_rd; + 5'd4 : x4 <= dbg_rd; + 5'd5 : x5 <= dbg_rd; + 5'd6 : x6 <= dbg_rd; + 5'd7 : x7 <= dbg_rd; + 5'd8 : x8 <= dbg_rd; + 5'd9 : x9 <= dbg_rd; + 5'd10 : x10 <= dbg_rd; + 5'd11 : x11 <= dbg_rd; + 5'd12 : x12 <= dbg_rd; + 5'd13 : x13 <= dbg_rd; + 5'd14 : x14 <= dbg_rd; + 5'd15 : x15 <= dbg_rd; + 5'd16 : x16 <= dbg_rd; + 5'd17 : x17 <= dbg_rd; + 5'd18 : x18 <= dbg_rd; + 5'd19 : x19 <= dbg_rd; + 5'd20 : x20 <= dbg_rd; + 5'd21 : x21 <= dbg_rd; + 5'd22 : x22 <= dbg_rd; + 5'd23 : x23 <= dbg_rd; + 5'd24 : x24 <= dbg_rd; + 5'd25 : x25 <= dbg_rd; + 5'd26 : x26 <= dbg_rd; + 5'd27 : x27 <= dbg_rd; + 5'd28 : x28 <= dbg_rd; + 5'd29 : x29 <= dbg_rd; + 5'd30 : x30 <= dbg_rd; + 5'd31 : x31 <= dbg_rd; + default : ; + endcase + end + + if (i_cnt_en) + dbg_csr <= {i_csr_in, dbg_csr[31:1]}; + if (update_rd) + if (i_csr_mstatus_en) + dbg_mstatus <= dbg_csr; + else if (i_csr_mie_en) + dbg_mie <= dbg_csr; + else if (i_csr_mcause_en) + dbg_mcause <= dbg_csr; + else if (i_csr_en) + case (i_csr_addr) + 2'b00 : dbg_mscratch <= dbg_csr; + 2'b01 : dbg_mtvec <= dbg_csr; + 2'b10 : dbg_mepc <= dbg_csr; + 2'b11 : dbg_mtval <= dbg_csr; + endcase + end + + reg LUI, AUIPC, JAL, JALR, BEQ, BNE, BLT, BGE, BLTU, BGEU, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI, SLTIU, XORI, ORI, ANDI,SLLI, SRLI, SRAI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, FENCE, ECALL, EBREAK; + reg CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, CSRRCI; + reg OTHER; + + always @(posedge i_clk) begin + if (i_ibus_ack) begin + LUI <= 1'b0; + AUIPC <= 1'b0; + JAL <= 1'b0; + JALR <= 1'b0; + BEQ <= 1'b0; + BNE <= 1'b0; + BLT <= 1'b0; + BGE <= 1'b0; + BLTU <= 1'b0; + BGEU <= 1'b0; + LB <= 1'b0; + LH <= 1'b0; + LW <= 1'b0; + LBU <= 1'b0; + LHU <= 1'b0; + SB <= 1'b0; + SH <= 1'b0; + SW <= 1'b0; + ADDI <= 1'b0; + SLTI <= 1'b0; + SLTIU <= 1'b0; + XORI <= 1'b0; + ORI <= 1'b0; + ANDI <= 1'b0; + SLLI <= 1'b0; + SRLI <= 1'b0; + SRAI <= 1'b0; + ADD <= 1'b0; + SUB <= 1'b0; + SLL <= 1'b0; + SLT <= 1'b0; + SLTU <= 1'b0; + XOR <= 1'b0; + SRL <= 1'b0; + SRA <= 1'b0; + OR <= 1'b0; + AND <= 1'b0; + FENCE <= 1'b0; + ECALL <= 1'b0; + EBREAK <= 1'b0; + CSRRW <= 1'b0; + CSRRS <= 1'b0; + CSRRC <= 1'b0; + CSRRWI <= 1'b0; + CSRRSI <= 1'b0; + CSRRCI <= 1'b0; + OTHER <= 1'b0; + + casez(i_ibus_rdt) + // 3322222_22222 11111_111 11 + // 1098765_43210 98765_432 10987_65432_10 + 32'b???????_?????_?????_???_?????_01101_11 : LUI <= 1'b1; + 32'b???????_?????_?????_???_?????_00101_11 : AUIPC <= 1'b1; + 32'b???????_?????_?????_???_?????_11011_11 : JAL <= 1'b1; + 32'b???????_?????_?????_000_?????_11001_11 : JALR <= 1'b1; + 32'b???????_?????_?????_000_?????_11000_11 : BEQ <= 1'b1; + 32'b???????_?????_?????_001_?????_11000_11 : BNE <= 1'b1; + 32'b???????_?????_?????_100_?????_11000_11 : BLT <= 1'b1; + 32'b???????_?????_?????_101_?????_11000_11 : BGE <= 1'b1; + 32'b???????_?????_?????_110_?????_11000_11 : BLTU <= 1'b1; + 32'b???????_?????_?????_111_?????_11000_11 : BGEU <= 1'b1; + 32'b???????_?????_?????_000_?????_00000_11 : LB <= 1'b1; + 32'b???????_?????_?????_001_?????_00000_11 : LH <= 1'b1; + 32'b???????_?????_?????_010_?????_00000_11 : LW <= 1'b1; + 32'b???????_?????_?????_100_?????_00000_11 : LBU <= 1'b1; + 32'b???????_?????_?????_101_?????_00000_11 : LHU <= 1'b1; + 32'b???????_?????_?????_000_?????_01000_11 : SB <= 1'b1; + 32'b???????_?????_?????_001_?????_01000_11 : SH <= 1'b1; + 32'b???????_?????_?????_010_?????_01000_11 : SW <= 1'b1; + 32'b???????_?????_?????_000_?????_00100_11 : ADDI <= 1'b1; + 32'b???????_?????_?????_010_?????_00100_11 : SLTI <= 1'b1; + 32'b???????_?????_?????_011_?????_00100_11 : SLTIU <= 1'b1; + 32'b???????_?????_?????_100_?????_00100_11 : XORI <= 1'b1; + 32'b???????_?????_?????_110_?????_00100_11 : ORI <= 1'b1; + 32'b???????_?????_?????_111_?????_00100_11 : ANDI <= 1'b1; + 32'b0000000_?????_?????_001_?????_00100_11 : SLLI <= 1'b1; + 32'b0000000_?????_?????_101_?????_00100_11 : SRLI <= 1'b1; + 32'b0100000_?????_?????_101_?????_00100_11 : SRAI <= 1'b1; + 32'b0000000_?????_?????_000_?????_01100_11 : ADD <= 1'b1; + 32'b0100000_?????_?????_000_?????_01100_11 : SUB <= 1'b1; + 32'b0000000_?????_?????_001_?????_01100_11 : SLL <= 1'b1; + 32'b0000000_?????_?????_010_?????_01100_11 : SLT <= 1'b1; + 32'b0000000_?????_?????_011_?????_01100_11 : SLTU <= 1'b1; + 32'b???????_?????_?????_100_?????_01100_11 : XOR <= 1'b1; + 32'b0000000_?????_?????_101_?????_01100_11 : SRL <= 1'b1; + 32'b0100000_?????_?????_101_?????_01100_11 : SRA <= 1'b1; + 32'b???????_?????_?????_110_?????_01100_11 : OR <= 1'b1; + 32'b???????_?????_?????_111_?????_01100_11 : AND <= 1'b1; + 32'b???????_?????_?????_000_?????_00011_11 : FENCE <= 1'b1; + 32'b0000000_00000_00000_000_00000_11100_11 : ECALL <= 1'b1; + 32'b0000000_00001_00000_000_00000_11100_11 : EBREAK <= 1'b1; + 32'b???????_?????_?????_001_?????_11100_11 : CSRRW <= 1'b1; + 32'b???????_?????_?????_010_?????_11100_11 : CSRRS <= 1'b1; + 32'b???????_?????_?????_011_?????_11100_11 : CSRRC <= 1'b1; + 32'b???????_?????_?????_101_?????_11100_11 : CSRRWI <= 1'b1; + 32'b???????_?????_?????_110_?????_11100_11 : CSRRSI <= 1'b1; + 32'b???????_?????_?????_111_?????_11100_11 : CSRRCI <= 1'b1; + default : OTHER <= 1'b1; + endcase + end + end + +endmodule diff --git a/rtl/serv_rf_top.v b/rtl/serv_rf_top.v index 8eeaa42..7b1c21a 100644 --- a/rtl/serv_rf_top.v +++ b/rtl/serv_rf_top.v @@ -27,6 +27,7 @@ module serv_rf_top restart execution from the instruction at RESET_PC */ parameter RESET_STRATEGY = "MINI", + parameter [0:0] DEBUG = 1'b0, parameter WITH_CSR = 1, parameter W = 1, parameter RF_WIDTH = W * 2, @@ -147,6 +148,7 @@ module serv_rf_top .PRE_REGISTER (PRE_REGISTER), .RESET_STRATEGY (RESET_STRATEGY), .WITH_CSR (WITH_CSR), + .DEBUG (DEBUG), .MDU(MDU), .COMPRESSED(COMPRESSED), .ALIGN(ALIGN), diff --git a/rtl/serv_top.v b/rtl/serv_top.v index e01324d..cf833d1 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -1,12 +1,13 @@ `default_nettype none module serv_top - #(parameter WITH_CSR = 1, + #(parameter WITH_CSR = 1, parameter W = 1, parameter B = W-1, - parameter PRE_REGISTER = 1, - parameter RESET_STRATEGY = "MINI", - parameter RESET_PC = 32'd0, + parameter PRE_REGISTER = 1, + parameter RESET_STRATEGY = "MINI", + parameter RESET_PC = 32'd0, + parameter [0:0] DEBUG = 1'b0, parameter [0:0] MDU = 1'b0, parameter [0:0] COMPRESSED=0, parameter [0:0] ALIGN = COMPRESSED) @@ -586,6 +587,27 @@ module serv_top end endgenerate + generate + if (DEBUG) begin : gen_debug + serv_debug #(.W (W)) debug + ( + .i_clk (clk), + .i_rst (i_rst), + .i_ibus_rdt (i_ibus_rdt), + .i_ibus_ack (i_ibus_ack), + .i_rd_addr (rd_addr ), + .i_cnt_en (cnt_en ), + .i_csr_in (csr_in ), + .i_csr_mstatus_en (csr_mstatus_en), + .i_csr_mie_en (csr_mie_en ), + .i_csr_mcause_en (csr_mcause_en ), + .i_csr_en (csr_en ), + .i_csr_addr (csr_addr), + .i_wen0 (o_wen0), + .i_wdata0 (o_wdata0), + .i_cnt_done (cnt_done)); + end + endgenerate `ifdef RISCV_FORMAL reg [31:0] pc = RESET_PC; diff --git a/serv.core b/serv.core index 6385058..f52b0af 100644 --- a/serv.core +++ b/serv.core @@ -18,6 +18,7 @@ filesets: - rtl/serv_rf_ram_if.v - rtl/serv_rf_ram.v - rtl/serv_state.v + - rtl/serv_debug.v - rtl/serv_top.v - rtl/serv_rf_top.v - rtl/serv_aligner.v diff --git a/servant/servant.v b/servant/servant.v index 34cbc91..fb027df 100644 --- a/servant/servant.v +++ b/servant/servant.v @@ -10,6 +10,7 @@ module servant parameter reset_strategy = "MINI"; parameter width = 1; parameter sim = 0; + parameter [0:0] debug = 1'b0; parameter with_csr = 1; parameter [0:0] compress = 0; parameter [0:0] align = compress; @@ -136,6 +137,7 @@ module servant servile #(.width (width), .sim (sim[0]), + .debug (debug), .with_c (compress[0]), .with_csr (with_csr[0]), .with_mdu (with_mdu)) diff --git a/servile/servile.v b/servile/servile.v index 157b07d..64abc4a 100644 --- a/servile/servile.v +++ b/servile/servile.v @@ -8,11 +8,12 @@ `default_nettype none module servile #( - parameter width = 1, + parameter width = 1, parameter reset_pc = 32'h00000000, parameter reset_strategy = "MINI", parameter rf_width = 2*width, parameter [0:0] sim = 1'b0, + parameter [0:0] debug = 1'b0, parameter [0:0] with_c = 1'b0, parameter [0:0] with_csr = 1'b0, parameter [0:0] with_mdu = 1'b0, @@ -203,6 +204,7 @@ module servile .PRE_REGISTER (1'b1), .RESET_STRATEGY (reset_strategy), .RESET_PC (reset_pc), + .DEBUG (debug), .MDU (with_mdu), .COMPRESSED (with_c)) cpu From 9bf8672fb248701cf561ff8f18d41d33e9925ead Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Sat, 12 Oct 2024 23:15:33 +0200 Subject: [PATCH 15/34] Move RVFI signals into serv_debug --- rtl/serv_debug.v | 109 ++++++++++++++++++++++++++++++++- rtl/serv_top.v | 154 ++++++++++++++++++++--------------------------- 2 files changed, 170 insertions(+), 93 deletions(-) diff --git a/rtl/serv_debug.v b/rtl/serv_debug.v index 0d800d1..7f9571b 100644 --- a/rtl/serv_debug.v +++ b/rtl/serv_debug.v @@ -1,10 +1,55 @@ module serv_debug - #(parameter W = 1) + #(parameter W = 1, + parameter RESET_PC = 0, + //Internally calculated. Do not touch + parameter B=W-1) ( +`ifdef RISCV_FORMAL + output reg rvfi_valid = 1'b0, + output reg [63:0] rvfi_order = 64'd0, + output reg [31:0] rvfi_insn = 32'd0, + output reg rvfi_trap = 1'b0, + output reg rvfi_halt = 1'b0, // Not used + output reg rvfi_intr = 1'b0, // Not used + output reg [1:0] rvfi_mode = 2'b11, // Not used + output reg [1:0] rvfi_ixl = 2'b01, // Not used + output reg [4:0] rvfi_rs1_addr, + output reg [4:0] rvfi_rs2_addr, + output reg [31:0] rvfi_rs1_rdata, + output reg [31:0] rvfi_rs2_rdata, + output reg [4:0] rvfi_rd_addr, + output wire [31:0] rvfi_rd_wdata, + output reg [31:0] rvfi_pc_rdata, + output wire [31:0] rvfi_pc_wdata, + output reg [31:0] rvfi_mem_addr, + output reg [3:0] rvfi_mem_rmask, + output reg [3:0] rvfi_mem_wmask, + output reg [31:0] rvfi_mem_rdata, + output reg [31:0] rvfi_mem_wdata, + input wire [31:0] i_dbus_adr, + input wire [31:0] i_dbus_dat, + input wire [3:0] i_dbus_sel, + input wire i_dbus_we, + input wire [31:0] i_dbus_rdt, + input wire i_dbus_ack, + input wire i_ctrl_pc_en, + input wire [B:0] rs1, + input wire [B:0] rs2, + input wire [4:0] rs1_addr, + input wire [4:0] rs2_addr, + input wire [3:0] immdec_en, + input wire rd_en, + input wire trap, + input wire i_rf_ready, + input wire i_ibus_cyc, + input wire two_stage_op, + input wire init, + input wire [31:0] i_ibus_adr, +`endif input wire i_clk, input wire i_rst, - input wire i_ibus_ack, input wire [31:0] i_ibus_rdt, + input wire i_ibus_ack, input wire [4:0] i_rd_addr, input wire i_cnt_en, input wire i_csr_in, @@ -14,7 +59,7 @@ module serv_debug input wire i_csr_en, input wire [1:0] i_csr_addr, input wire i_wen0, - input wire i_wdata0, + input wire [B:0] i_wdata0, input wire i_cnt_done); reg update_rd = 1'b0; @@ -229,4 +274,62 @@ module serv_debug end end +`ifdef RISCV_FORMAL + reg [31:0] pc = RESET_PC; + + wire rs_en = two_stage_op ? init : i_ctrl_pc_en; + + assign rvfi_rd_wdata = update_rd ? dbg_rd : 32'd0; + + always @(posedge i_clk) begin + /* End of instruction */ + rvfi_valid <= i_cnt_done & i_ctrl_pc_en & !i_rst; + rvfi_order <= rvfi_order + {63'd0,rvfi_valid}; + + /* Get instruction word when it's fetched from ibus */ + if (i_ibus_cyc & i_ibus_ack) + rvfi_insn <= i_ibus_rdt; + + + if (i_cnt_done & i_ctrl_pc_en) begin + rvfi_pc_rdata <= pc; + if (!(rd_en & (|i_rd_addr))) begin + rvfi_rd_addr <= 5'd0; + end + end + rvfi_trap <= trap; + if (rvfi_valid) begin + rvfi_trap <= 1'b0; + pc <= rvfi_pc_wdata; + end + + /* RS1 not valid during J, U instructions (immdec_en[1]) */ + /* RS2 not valid during I, J, U instructions (immdec_en[2]) */ + if (i_rf_ready) begin + rvfi_rs1_addr <= !immdec_en[1] ? rs1_addr : 5'd0; + rvfi_rs2_addr <= !immdec_en[2] /*rs2_valid*/ ? rs2_addr : 5'd0; + rvfi_rd_addr <= i_rd_addr; + end + if (rs_en) begin + rvfi_rs1_rdata <= {(!immdec_en[1] ? rs1 : {W{1'b0}}),rvfi_rs1_rdata[31:W]}; + rvfi_rs2_rdata <= {(!immdec_en[2] ? rs2 : {W{1'b0}}),rvfi_rs2_rdata[31:W]}; + end + + if (i_dbus_ack) begin + rvfi_mem_addr <= i_dbus_adr; + rvfi_mem_rmask <= i_dbus_we ? 4'b0000 : i_dbus_sel; + rvfi_mem_wmask <= i_dbus_we ? i_dbus_sel : 4'b0000; + rvfi_mem_rdata <= i_dbus_rdt; + rvfi_mem_wdata <= i_dbus_dat; + end + if (i_ibus_ack) begin + rvfi_mem_rmask <= 4'b0000; + rvfi_mem_wmask <= 4'b0000; + end + end + + assign rvfi_pc_wdata = i_ibus_adr; + +`endif + endmodule diff --git a/rtl/serv_top.v b/rtl/serv_top.v index cf833d1..dafa15f 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -16,27 +16,27 @@ module serv_top input wire i_rst, input wire i_timer_irq, `ifdef RISCV_FORMAL - output reg rvfi_valid = 1'b0, - output reg [63:0] rvfi_order = 64'd0, - output reg [31:0] rvfi_insn = 32'd0, - output reg rvfi_trap = 1'b0, - output reg rvfi_halt = 1'b0, - output reg rvfi_intr = 1'b0, - output reg [1:0] rvfi_mode = 2'b11, - output reg [1:0] rvfi_ixl = 2'b01, - output reg [4:0] rvfi_rs1_addr, - output reg [4:0] rvfi_rs2_addr, - output reg [31:0] rvfi_rs1_rdata, - output reg [31:0] rvfi_rs2_rdata, - output reg [4:0] rvfi_rd_addr, - output reg [31:0] rvfi_rd_wdata, - output reg [31:0] rvfi_pc_rdata, - output reg [31:0] rvfi_pc_wdata, - output reg [31:0] rvfi_mem_addr, - output reg [3:0] rvfi_mem_rmask, - output reg [3:0] rvfi_mem_wmask, - output reg [31:0] rvfi_mem_rdata, - output reg [31:0] rvfi_mem_wdata, + output wire rvfi_valid, + output wire [63:0] rvfi_order, + output wire [31:0] rvfi_insn, + output wire rvfi_trap, + output wire rvfi_halt, + output wire rvfi_intr, + output wire [1:0] rvfi_mode, + output wire [1:0] rvfi_ixl, + output wire [4:0] rvfi_rs1_addr, + output wire [4:0] rvfi_rs2_addr, + output wire [31:0] rvfi_rs1_rdata, + output wire [31:0] rvfi_rs2_rdata, + output wire [4:0] rvfi_rd_addr, + output wire [31:0] rvfi_rd_wdata, + output wire [31:0] rvfi_pc_rdata, + output wire [31:0] rvfi_pc_wdata, + output wire [31:0] rvfi_mem_addr, + output wire [3:0] rvfi_mem_rmask, + output wire [3:0] rvfi_mem_wmask, + output wire [31:0] rvfi_mem_rdata, + output wire [31:0] rvfi_mem_wdata, `endif //RF Interface output wire o_rf_rreq, @@ -589,8 +589,50 @@ module serv_top generate if (DEBUG) begin : gen_debug - serv_debug #(.W (W)) debug + serv_debug #(.W (W), .RESET_PC (RESET_PC)) debug ( +`ifdef RISCV_FORMAL + .rvfi_valid (rvfi_valid ), + .rvfi_order (rvfi_order ), + .rvfi_insn (rvfi_insn ), + .rvfi_trap (rvfi_trap ), + .rvfi_halt (rvfi_halt ), + .rvfi_intr (rvfi_intr ), + .rvfi_mode (rvfi_mode ), + .rvfi_ixl (rvfi_ixl ), + .rvfi_rs1_addr (rvfi_rs1_addr ), + .rvfi_rs2_addr (rvfi_rs2_addr ), + .rvfi_rs1_rdata (rvfi_rs1_rdata), + .rvfi_rs2_rdata (rvfi_rs2_rdata), + .rvfi_rd_addr (rvfi_rd_addr ), + .rvfi_rd_wdata (rvfi_rd_wdata ), + .rvfi_pc_rdata (rvfi_pc_rdata ), + .rvfi_pc_wdata (rvfi_pc_wdata ), + .rvfi_mem_addr (rvfi_mem_addr ), + .rvfi_mem_rmask (rvfi_mem_rmask), + .rvfi_mem_wmask (rvfi_mem_wmask), + .rvfi_mem_rdata (rvfi_mem_rdata), + .rvfi_mem_wdata (rvfi_mem_wdata), + .i_dbus_adr (o_dbus_adr), + .i_dbus_dat (o_dbus_dat), + .i_dbus_sel (o_dbus_sel), + .i_dbus_we (o_dbus_we ), + .i_dbus_rdt (i_dbus_rdt), + .i_dbus_ack (i_dbus_ack), + .i_ctrl_pc_en (ctrl_pc_en), + .rs1 (rs1), + .rs2 (rs2), + .rs1_addr (rs1_addr), + .rs2_addr (rs2_addr), + .immdec_en (immdec_en), + .rd_en (rd_en), + .trap (trap), + .i_rf_ready (i_rf_ready), + .i_ibus_cyc (o_ibus_cyc), + .two_stage_op (two_stage_op), + .init (init), + .i_ibus_adr (o_ibus_adr), +`endif .i_clk (clk), .i_rst (i_rst), .i_ibus_rdt (i_ibus_rdt), @@ -609,74 +651,6 @@ module serv_top end endgenerate -`ifdef RISCV_FORMAL - reg [31:0] pc = RESET_PC; - - wire rs_en = two_stage_op ? init : ctrl_pc_en; - - always @(posedge clk) begin - /* End of instruction */ - rvfi_valid <= cnt_done & ctrl_pc_en & !i_rst; - rvfi_order <= rvfi_order + {63'd0,rvfi_valid}; - - /* Get instruction word when it's fetched from ibus */ - if (wb_ibus_cyc & wb_ibus_ack) - rvfi_insn <= i_wb_rdt; - - /* Store data written to rd */ - if (o_wen0) - rvfi_rd_wdata <= {o_wdata0,rvfi_rd_wdata[31:W]}; - - if (cnt_done & ctrl_pc_en) begin - rvfi_pc_rdata <= pc; - if (!(rd_en & (|rd_addr))) begin - rvfi_rd_addr <= 5'd0; - rvfi_rd_wdata <= 32'd0; - end - end - rvfi_trap <= trap; - if (rvfi_valid) begin - rvfi_trap <= 1'b0; - pc <= rvfi_pc_wdata; - end - - /* Not used */ - rvfi_halt <= 1'b0; - rvfi_intr <= 1'b0; - rvfi_mode <= 2'd3; - rvfi_ixl = 2'd1; - - /* RS1 not valid during J, U instructions (immdec_en[1]) */ - /* RS2 not valid during I, J, U instructions (immdec_en[2]) */ - if (i_rf_ready) begin - rvfi_rs1_addr <= !immdec_en[1] ? rs1_addr : 5'd0; - rvfi_rs2_addr <= !immdec_en[2] /*rs2_valid*/ ? rs2_addr : 5'd0; - rvfi_rd_addr <= rd_addr; - end - if (rs_en) begin - rvfi_rs1_rdata <= {(!immdec_en[1] ? rs1 : {W{1'b0}}),rvfi_rs1_rdata[31:W]}; - rvfi_rs2_rdata <= {(!immdec_en[2] ? rs2 : {W{1'b0}}),rvfi_rs2_rdata[31:W]}; - end - - if (i_dbus_ack) begin - rvfi_mem_addr <= o_dbus_adr; - rvfi_mem_rmask <= o_dbus_we ? 4'b0000 : o_dbus_sel; - rvfi_mem_wmask <= o_dbus_we ? o_dbus_sel : 4'b0000; - rvfi_mem_rdata <= i_dbus_rdt; - rvfi_mem_wdata <= o_dbus_dat; - end - if (wb_ibus_ack) begin - rvfi_mem_rmask <= 4'b0000; - rvfi_mem_wmask <= 4'b0000; - end - end - /* verilator lint_off COMBDLY */ - always @(wb_ibus_adr) - rvfi_pc_wdata <= wb_ibus_adr; - /* verilator lint_on COMBDLY */ - - -`endif generate if (MDU) begin: gen_mdu From cd60abe837f6eef70d2134f9de87bf5a5fe32c7d Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Thu, 17 Oct 2024 14:34:08 +0200 Subject: [PATCH 16/34] Fix CSR width issues in debug module --- rtl/serv_debug.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtl/serv_debug.v b/rtl/serv_debug.v index 7f9571b..7449ab6 100644 --- a/rtl/serv_debug.v +++ b/rtl/serv_debug.v @@ -52,7 +52,7 @@ module serv_debug input wire i_ibus_ack, input wire [4:0] i_rd_addr, input wire i_cnt_en, - input wire i_csr_in, + input wire [B:0] i_csr_in, input wire i_csr_mstatus_en, input wire i_csr_mie_en, input wire i_csr_mcause_en, @@ -149,7 +149,7 @@ module serv_debug end if (i_cnt_en) - dbg_csr <= {i_csr_in, dbg_csr[31:1]}; + dbg_csr <= {i_csr_in, dbg_csr[31:W]}; if (update_rd) if (i_csr_mstatus_en) dbg_mstatus <= dbg_csr; From 8ad248d4e780b80b69931c5507fe6338601f5b8d Mon Sep 17 00:00:00 2001 From: cdwijs <8469638+cdwijs@users.noreply.github.com> Date: Sun, 10 Nov 2024 22:15:44 +0100 Subject: [PATCH 17/34] typo in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ae45f6..e8680cf 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ This will synthesize for the default Vivado part. To synthesise for a specific d SERV, or rather the Servant SoC, can run the [Zephyr RTOS](https://www.zephyrproject.org). The Servant-specific drivers and BSP is located in the zephyr subdirectory of the SERV repository. In order to use Zephyr on Servant, a project directory structure must be set up that allows Zephyr to load the Servant-specific files as a module. -First, the Zephyr SDK and the "west" build too must be installed. The [Zephyr getting started guide](https://docs.zephyrproject.org/latest/getting_started/index.html) describes these steps in more detail. +First, the Zephyr SDK and the "west" build tool must be installed. The [Zephyr getting started guide](https://docs.zephyrproject.org/latest/getting_started/index.html) describes these steps in more detail. Assuming that SERV was installed into `$WORKSPACE/fusesoc_libraries/serv` as per the prerequisites, run the following command to make the workspace also work as a Zephyr workspace. From e97bdaf7a1175ad02bc3ba3adb4b1b26d6204fad Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Mon, 11 Nov 2024 08:13:32 +0100 Subject: [PATCH 18/34] Update cad-suite GH action --- .github/workflows/formal.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/formal.yml b/.github/workflows/formal.yml index 1d62e38..37425a3 100644 --- a/.github/workflows/formal.yml +++ b/.github/workflows/formal.yml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@v4 with: path: cores/serv/serv-src - - uses: YosysHQ/setup-oss-cad-suite@v2 + - uses: YosysHQ/setup-oss-cad-suite@v3 with: github-token: ${{ secrets.GITHUB_TOKEN }} - name: Prepare formal tests From 1e4ea0527e0c7a3737bc501aa5d93bb16508ec15 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 19 Nov 2024 13:17:13 +0100 Subject: [PATCH 19/34] Fix CSR write detection in debug module --- rtl/serv_debug.v | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/rtl/serv_debug.v b/rtl/serv_debug.v index 7449ab6..af3c34f 100644 --- a/rtl/serv_debug.v +++ b/rtl/serv_debug.v @@ -63,6 +63,14 @@ module serv_debug input wire i_cnt_done); reg update_rd = 1'b0; + reg update_mscratch; + reg update_mtvec; + reg update_mepc; + reg update_mtval; + reg update_mstatus; + reg update_mie; + reg update_mcause; + reg [31:0] dbg_rd = 32'hxxxxxxxx; reg [31:0] dbg_csr = 32'hxxxxxxxx; reg [31:0] dbg_mstatus = 32'hxxxxxxxx; @@ -148,22 +156,24 @@ module serv_debug endcase end + update_mscratch <= i_cnt_done & i_csr_en & (i_csr_addr == 2'b00); + update_mtvec <= i_cnt_done & i_csr_en & (i_csr_addr == 2'b01); + update_mepc <= i_cnt_done & i_csr_en & (i_csr_addr == 2'b10); + update_mtval <= i_cnt_done & i_csr_en & (i_csr_addr == 2'b11); + update_mstatus <= i_cnt_done & i_csr_mstatus_en; + update_mie <= i_cnt_done & i_csr_mie_en; + update_mcause <= i_cnt_done & i_csr_mcause_en; + if (i_cnt_en) dbg_csr <= {i_csr_in, dbg_csr[31:W]}; - if (update_rd) - if (i_csr_mstatus_en) - dbg_mstatus <= dbg_csr; - else if (i_csr_mie_en) - dbg_mie <= dbg_csr; - else if (i_csr_mcause_en) - dbg_mcause <= dbg_csr; - else if (i_csr_en) - case (i_csr_addr) - 2'b00 : dbg_mscratch <= dbg_csr; - 2'b01 : dbg_mtvec <= dbg_csr; - 2'b10 : dbg_mepc <= dbg_csr; - 2'b11 : dbg_mtval <= dbg_csr; - endcase + + if (update_mscratch) dbg_mscratch <= dbg_csr; + if (update_mtvec) dbg_mtvec <= dbg_csr; + if (update_mepc ) dbg_mepc <= dbg_csr; + if (update_mtval) dbg_mtval <= dbg_csr; + if (update_mstatus) dbg_mstatus <= dbg_csr; + if (update_mie) dbg_mie <= dbg_csr; + if (update_mcause) dbg_mcause <= dbg_csr; end reg LUI, AUIPC, JAL, JALR, BEQ, BNE, BLT, BGE, BLTU, BGEU, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI, SLTIU, XORI, ORI, ANDI,SLLI, SRLI, SRAI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, FENCE, ECALL, EBREAK; From 007f42850df1b94100ffbe28a584764120a4c919 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 26 Nov 2024 19:58:35 +0100 Subject: [PATCH 20/34] servile_mux: Declare variable before use --- servile/servile_mux.v | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/servile/servile_mux.v b/servile/servile_mux.v index 01808f3..e4d8c5c 100644 --- a/servile/servile_mux.v +++ b/servile/servile_mux.v @@ -61,11 +61,12 @@ module servile_mux generate if (sim) begin + integer f = 0; + assign sig_en = |f & i_wb_cpu_we & (i_wb_cpu_adr == sim_sig_adr); assign halt_en = i_wb_cpu_we & (i_wb_cpu_adr == sim_halt_adr); reg [1023:0] signature_file; - integer f = 0; initial /* verilator lint_off WIDTH */ From 7e7b453eb080c56ae9a7fc948ad5b641fbab4172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20B=C3=A5nvik?= Date: Sat, 30 Nov 2024 17:59:29 +0100 Subject: [PATCH 21/34] Added support for Trenz Electronic TE0802 --- data/te0802.xdc | 22 +++++++++++++++ doc/servant.rst | 7 +++++ servant.core | 15 ++++++++++ servant/servant_te0802.v | 33 ++++++++++++++++++++++ servant/servant_te0802_clock_gen.v | 45 ++++++++++++++++++++++++++++++ 5 files changed, 122 insertions(+) create mode 100644 data/te0802.xdc create mode 100644 servant/servant_te0802.v create mode 100644 servant/servant_te0802_clock_gen.v diff --git a/data/te0802.xdc b/data/te0802.xdc new file mode 100644 index 0000000..d0ab18b --- /dev/null +++ b/data/te0802.xdc @@ -0,0 +1,22 @@ +## Clock signal +set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS18 } [get_ports i_clk]; +create_clock -add -name sys_clk_pin -period 40.00 [get_ports i_clk]; + +## LED 0 +set_property -dict { PACKAGE_PIN P1 IOSTANDARD LVCMOS18 } [get_ports o_led_0]; + +# PMOD A, Connector J5 +# Connector pin, Package pin, PMOD type 4 UART +# 1, F8, CTS +# 2, F7, TXD +# 3, E6, RXD +# 4, E5, RTS +# 5, GND +# 6, VCC +# 7, G6, +# 8, G5, +# 9, C8, +# 10, C7, +# 11, GND +# 12, VCC +set_property -dict { PACKAGE_PIN F7 IOSTANDARD LVCMOS33 } [get_ports o_uart_tx] diff --git a/doc/servant.rst b/doc/servant.rst index 8828a9d..e5061bf 100644 --- a/doc/servant.rst +++ b/doc/servant.rst @@ -248,6 +248,13 @@ FPGA Pin F14 (HSTC GPIO addon connector J2, pin 2) is used for UART output with fusesoc run --target=sockit servant +Trenz Electronic TE0802 +^^^^^^^^^^^^^^^^^^^^^^^ + +PMOD A marked J5, pin two, on the board is used for UART output with 115200 baud rate. + + fusesoc run --target=te0802 servant + TinyFPGA BX ^^^^^^^^^^^ diff --git a/servant.core b/servant.core index 8f1f908..f1f0674 100644 --- a/servant.core +++ b/servant.core @@ -218,6 +218,12 @@ filesets: - servant/servive_clock_gen.v : {file_type : verilogSource} - servant/servive.v : {file_type : verilogSource} + te0802: + files: + - servant/servant_te0802_clock_gen.v : {file_type : verilogSource} + - servant/servant_te0802.v : {file_type : verilogSource} + - data/te0802.xdc : {file_type : xdc} + tinyfpga_bx: {files: [data/tinyfpga_bx.pcf : {file_type : PCF}]} ulx3s: @@ -598,6 +604,15 @@ targets: device : 5CSXFC6D6F31C6 toplevel: servive + te0802: + default_tool: vivado + description : Trenz Electronic TE0802 + filesets : [mem_files, soc, te0802] + parameters : [memfile, memsize] + tools: + vivado: {part : xczu2cg-sbva484-1-e} + toplevel : servant_te0802 + tinyfpga_bx: description: TinyFPGA BX filesets : [mem_files, soc, service, tinyfpga_bx] diff --git a/servant/servant_te0802.v b/servant/servant_te0802.v new file mode 100644 index 0000000..b72b4cc --- /dev/null +++ b/servant/servant_te0802.v @@ -0,0 +1,33 @@ +`default_nettype none +module servant_te0802 + ( + input wire i_clk, + output wire o_uart_tx, + output wire o_led_0 + ); + + parameter memfile = "zephyr_hello.hex"; + parameter memsize = 8192; + + wire clk; + wire rst; + wire q; + + assign o_uart_tx = q; + assign o_led_0 = q; + + servant_te0802_clock_gen + clock_gen + (.i_clk (i_clk), + .o_clk (clk), + .o_rst (rst)); + + servant + #(.memfile (memfile), + .memsize (memsize)) + servant + (.wb_clk (clk), + .wb_rst (rst), + .q (q)); + +endmodule diff --git a/servant/servant_te0802_clock_gen.v b/servant/servant_te0802_clock_gen.v new file mode 100644 index 0000000..fe118a1 --- /dev/null +++ b/servant/servant_te0802_clock_gen.v @@ -0,0 +1,45 @@ +`default_nettype none +module servant_te0802_clock_gen + (input wire i_clk, + output wire o_clk, + output reg o_rst); + + wire clkfb; + wire locked; + reg locked_r; + + // Generate a 32 MHz clock from the 25MHz clock input + MMCME4_ADV + #(.DIVCLK_DIVIDE (1), + .CLKFBOUT_MULT_F (48.000), + .CLKOUT0_DIVIDE_F (37.5), + .CLKIN1_PERIOD (40.0), //25MHz + .STARTUP_WAIT ("FALSE")) + mmcm + (.CLKFBOUT (clkfb), + .CLKFBOUTB (), + .CLKOUT0 (o_clk), + .CLKOUT0B (), + .CLKOUT1 (), + .CLKOUT1B (), + .CLKOUT2 (), + .CLKOUT2B (), + .CLKOUT3 (), + .CLKOUT3B (), + .CLKOUT4 (), + .CLKOUT5 (), + .CLKOUT6 (), + .CLKIN1 (i_clk), + .CLKIN2 (1'b0), + .CLKINSEL (1'b1), + .LOCKED (locked), + .PWRDWN (1'b0), + .RST (1'b0), + .CLKFBIN (clkfb)); + + always @(posedge o_clk) begin + locked_r <= locked; + o_rst <= !locked_r; + end + +endmodule From 1b06ae60330afd20442fa750d62e54ed1f719846 Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Sun, 15 Dec 2024 10:55:34 +0100 Subject: [PATCH 22/34] Update to Zephyr 4.0.0 --- west.yml | 2 +- zephyr/drivers/serial/uart_bitbang.c | 1 + zephyr/soc/riscv/servant/Kconfig.defconfig | 12 ++++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/west.yml b/west.yml index cc4c437..f76966f 100644 --- a/west.yml +++ b/west.yml @@ -5,5 +5,5 @@ manifest: projects: - name: zephyr remote: zephyrproject-rtos - revision: v3.7.0 + revision: v4.0.0 import: true diff --git a/zephyr/drivers/serial/uart_bitbang.c b/zephyr/drivers/serial/uart_bitbang.c index 1d606cb..927b3a0 100644 --- a/zephyr/drivers/serial/uart_bitbang.c +++ b/zephyr/drivers/serial/uart_bitbang.c @@ -8,6 +8,7 @@ #include #include #include +#include #define DT_DRV_COMPAT olofk_serial diff --git a/zephyr/soc/riscv/servant/Kconfig.defconfig b/zephyr/soc/riscv/servant/Kconfig.defconfig index 8479a98..607f6ff 100644 --- a/zephyr/soc/riscv/servant/Kconfig.defconfig +++ b/zephyr/soc/riscv/servant/Kconfig.defconfig @@ -23,4 +23,16 @@ config SERV_TIMER bool default y +config ARCH_HAS_CUSTOM_CPU_IDLE + bool + default y + +config ARCH_HAS_CUSTOM_CPU_ATOMIC_IDLE + bool + default y + +config RISCV_SOC_EXCEPTION_FROM_IRQ + bool + default y + endif # SOC_RISCV32_SERVANT From de4c3b44ee626c787d8395cd91f613267bbf59c0 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Wed, 18 Dec 2024 13:48:27 +0100 Subject: [PATCH 23/34] Add Subservient documentation --- doc/conf.py | 1 - doc/reservoir.rst | 1 + doc/subservient.png | Bin 0 -> 8811 bytes doc/subservient.rst | 10 ++++++++++ 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 doc/subservient.png create mode 100644 doc/subservient.rst diff --git a/doc/conf.py b/doc/conf.py index 9c639e6..e2aa689 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -28,7 +28,6 @@ author = 'Olof Kindgren' # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autosectionlabel', 'sphinxcontrib.wavedrom' ] diff --git a/doc/reservoir.rst b/doc/reservoir.rst index 2791c65..9a9d0a3 100644 --- a/doc/reservoir.rst +++ b/doc/reservoir.rst @@ -9,3 +9,4 @@ Welcome to the reservoir, a pool of ready-made designs and subsystems for differ .. include:: servile.rst .. include:: serving.rst .. include:: servant.rst +.. include:: subservient.rst diff --git a/doc/subservient.png b/doc/subservient.png new file mode 100644 index 0000000000000000000000000000000000000000..21589c318f000d7119c81eb686a94382042a6061 GIT binary patch literal 8811 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 literal 0 HcmV?d00001 diff --git a/doc/subservient.rst b/doc/subservient.rst new file mode 100644 index 0000000..e017e17 --- /dev/null +++ b/doc/subservient.rst @@ -0,0 +1,10 @@ +Subservient : SERV ASIC macro +============================= + +.. figure:: subservient.png + + Subservient ASIC macro + +`Subservient `_ is a minimal reference system that just requires connecting one single-port SRAM for data, instructions and RF. It is intended to make ASIC integration easier. + + From 01e74ef7fde1eb8b08988239e3d4808f5607685a Mon Sep 17 00:00:00 2001 From: Mikadore Date: Wed, 29 Jan 2025 06:13:51 +0100 Subject: [PATCH 24/34] Remove duplicate `tools` entry in servant.core In `servant.core`:`targets`:`machdyne_kolibri` --- servant.core | 1 - 1 file changed, 1 deletion(-) diff --git a/servant.core b/servant.core index f1f0674..901250f 100644 --- a/servant.core +++ b/servant.core @@ -490,7 +490,6 @@ targets: description : Machdyne Kolibri FPGA Dongle filesets : [mem_files, soc, machdyne_kolibri] parameters : [memfile, memsize] - tools: tools: icestorm: nextpnr_options : [--hx4k, --package, bg121, --freq, 48] From 842c2df0ca453db66b2ce6d9479cdfba8a471b18 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 28 Jan 2025 23:13:36 +0100 Subject: [PATCH 25/34] Enable zicsr flag for GCC --- sw/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sw/Makefile b/sw/Makefile index c97dba5..f82ddc6 100644 --- a/sw/Makefile +++ b/sw/Makefile @@ -1,7 +1,7 @@ TOOLCHAIN_PREFIX?=riscv64-unknown-elf- %.elf: %.S link.ld - $(TOOLCHAIN_PREFIX)gcc -nostartfiles -nostdlib -march=rv32i -mabi=ilp32 -Tlink.ld -o$@ $< + $(TOOLCHAIN_PREFIX)gcc -nostartfiles -nostdlib -march=rv32i_zicsr -mabi=ilp32 -Tlink.ld -o$@ $< %.bin: %.elf $(TOOLCHAIN_PREFIX)objcopy -O binary $< $@ %.hex: %.bin From 129a9294c67629ef1238a100a6e05ab6e16b365c Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Sat, 1 Mar 2025 16:49:20 +0100 Subject: [PATCH 26/34] Remove slt_or_branch control signal --- rtl/serv_decode.v | 4 ---- rtl/serv_state.v | 13 +++++++++---- rtl/serv_top.v | 5 ++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index 54ed74b..2aa5b8a 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -15,7 +15,6 @@ module serv_decode output reg o_ebreak, output reg o_branch_op, output reg o_shift_op, - output reg o_slt_or_branch, output reg o_rd_op, output reg o_two_stage_op, output reg o_dbus_en, @@ -79,7 +78,6 @@ module serv_decode ~opcode[2] | (funct3[0] & ~funct3[1] & ~opcode[0] & ~opcode[4]) | (funct3[1] & ~funct3[2] & ~opcode[0] & ~opcode[4]) | co_mdu_op; wire co_shift_op = (opcode[2] & ~funct3[1]) & !co_mdu_op; - wire co_slt_or_branch = (opcode[4] | (funct3[1] & opcode[2]) | (imm30 & opcode[2] & opcode[3] & ~funct3[2])) & !co_mdu_op; wire co_branch_op = opcode[4]; wire co_dbus_en = ~opcode[2] & ~opcode[4]; wire co_mtval_pc = opcode[4]; @@ -259,7 +257,6 @@ module serv_decode o_ebreak = co_ebreak; o_branch_op = co_branch_op; o_shift_op = co_shift_op; - o_slt_or_branch = co_slt_or_branch; o_rd_op = co_rd_op; o_mdu_op = co_mdu_op; o_ext_funct3 = co_ext_funct3; @@ -321,7 +318,6 @@ module serv_decode o_mtval_pc <= co_mtval_pc; o_branch_op <= co_branch_op; o_shift_op <= co_shift_op; - o_slt_or_branch <= co_slt_or_branch; o_rd_op <= co_rd_op; o_mdu_op <= co_mdu_op; o_ext_funct3 <= co_ext_funct3; diff --git a/rtl/serv_state.v b/rtl/serv_state.v index 4e0f293..03b7684 100644 --- a/rtl/serv_state.v +++ b/rtl/serv_state.v @@ -40,7 +40,8 @@ module serv_state input wire i_branch_op, input wire i_shift_op, input wire i_sh_right, - input wire i_slt_or_branch, + input wire i_alu_rd_sel1, + input wire i_rd_alu_en, input wire i_e_op, input wire i_rd_op, //MDU @@ -95,10 +96,14 @@ module serv_state //Prepare RF for writes when everything is ready to enter stage two // and the first stage didn't cause a misalign exception - assign o_rf_wreq = !misalign_trap_sync & !o_cnt_en & init_done & - ((i_shift_op & (i_sh_done | !i_sh_right)) | + //Left shifts, SLT & Branch ops. First cycle after init + //Right shift. o_sh_done + //Mem ops. i_dbus_ack + //MDU ops. i_mdu_ready + assign o_rf_wreq = (i_shift_op & (i_sh_right ? (i_sh_done & !o_cnt_en & init_done) : stage_two_req)) | i_dbus_ack | (MDU & i_mdu_ready) | - i_slt_or_branch); + (i_branch_op & stage_two_req & !misalign_trap_sync) | + (i_rd_alu_en & i_alu_rd_sel1 & stage_two_req); assign o_dbus_cyc = !o_cnt_en & init_done & i_dbus_en & !i_mem_misalign; diff --git a/rtl/serv_top.v b/rtl/serv_top.v index dafa15f..8bac6af 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -88,7 +88,6 @@ module serv_top wire ebreak; wire branch_op; wire shift_op; - wire slt_or_branch; wire rd_op; wire mdu_op; @@ -267,7 +266,8 @@ module serv_top .i_branch_op (branch_op), .i_shift_op (shift_op), .i_sh_right (sh_right), - .i_slt_or_branch (slt_or_branch), + .i_alu_rd_sel1 (alu_rd_sel[1]), + .i_rd_alu_en (rd_alu_en), .i_e_op (e_op), .i_rd_op (rd_op), //MDU @@ -303,7 +303,6 @@ module serv_top .o_ebreak (ebreak), .o_branch_op (branch_op), .o_shift_op (shift_op), - .o_slt_or_branch (slt_or_branch), .o_rd_op (rd_op), .o_sh_right (sh_right), .o_mdu_op (mdu_op), From 91628a056a120d3214f227d7d41c9af4779d91c7 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Sat, 1 Mar 2025 17:03:32 +0100 Subject: [PATCH 27/34] Simplify one-hot counter enable --- rtl/serv_state.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtl/serv_state.v b/rtl/serv_state.v index 03b7684..0db68fd 100644 --- a/rtl/serv_state.v +++ b/rtl/serv_state.v @@ -189,7 +189,7 @@ module serv_state reg [3:0] cnt_lsb; always @(posedge i_clk) begin o_cnt <= o_cnt + {2'd0,cnt_r[3]}; - cnt_lsb <= {cnt_lsb[2:0],(cnt_lsb[3] & !o_cnt_done) | (i_rf_ready & !o_cnt_en)}; + cnt_lsb <= {cnt_lsb[2:0],(cnt_lsb[3] & !o_cnt_done) | i_rf_ready}; if (i_rst & (RESET_STRATEGY != "NONE")) begin o_cnt <= 3'd0; cnt_lsb <= 4'b0000; From 2f23449f0f2e296ff2713891d1195da4e998496a Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 28 Jan 2025 23:14:03 +0100 Subject: [PATCH 28/34] Make branches, slt and left shifts one cycle faster --- rtl/serv_bufreg2.v | 6 ++---- rtl/serv_state.v | 22 ++++++++++++---------- rtl/serv_top.v | 3 --- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/rtl/serv_bufreg2.v b/rtl/serv_bufreg2.v index 57cf753..4afffb7 100644 --- a/rtl/serv_bufreg2.v +++ b/rtl/serv_bufreg2.v @@ -8,7 +8,6 @@ module serv_bufreg2 input wire [1:0] i_lsb, input wire i_byte_valid, output wire o_sh_done, - output wire o_sh_done_r, //Control input wire i_op_b_sel, input wire i_shift_op, @@ -36,8 +35,8 @@ module serv_bufreg2 shifted out at the appropriate time to end up in the correct position in rd shift : Data is shifted in during init. After that, the six LSB are used as - a downcounter (with bit 5 initially set to 0) that triggers - o_sh_done and o_sh_done_r when they wrap around to indicate that + a downcounter (with bit 5 initially set to 0) that trigger + o_sh_done when they wrap around to indicate that the requested number of shifts have been performed */ wire [5:0] dat_shamt = (i_shift_op & !i_init) ? @@ -47,7 +46,6 @@ module serv_bufreg2 {dat[6] & !(i_shift_op & i_cnt_done),dat[5:1]}; assign o_sh_done = dat_shamt[5]; - assign o_sh_done_r = dat[5]; assign o_q = ((i_lsb == 2'd3) & dat[24]) | diff --git a/rtl/serv_state.v b/rtl/serv_state.v index 0db68fd..487bd82 100644 --- a/rtl/serv_state.v +++ b/rtl/serv_state.v @@ -29,7 +29,6 @@ module serv_state output wire o_ctrl_trap, input wire i_ctrl_misalign, input wire i_sh_done, - input wire i_sh_done_r, output wire [1:0] o_mem_bytecnt, input wire i_mem_misalign, //Control @@ -91,6 +90,8 @@ module serv_state //been calculated. wire take_branch = i_branch_op & (!i_cond_branch | (i_alu_cmp^i_bne_or_bge)); + wire last_init = o_cnt_done & o_init; + //valid signal for mdu assign o_mdu_valid = MDU & !o_cnt_en & init_done & i_mdu_op; @@ -100,16 +101,16 @@ module serv_state //Right shift. o_sh_done //Mem ops. i_dbus_ack //MDU ops. i_mdu_ready - assign o_rf_wreq = (i_shift_op & (i_sh_right ? (i_sh_done & !o_cnt_en & init_done) : stage_two_req)) | + assign o_rf_wreq = (i_shift_op & (i_sh_right ? (i_sh_done & !o_cnt_en & init_done) : last_init)) | i_dbus_ack | (MDU & i_mdu_ready) | - (i_branch_op & stage_two_req & !misalign_trap_sync) | - (i_rd_alu_en & i_alu_rd_sel1 & stage_two_req); + (i_branch_op & (last_init & !trap_pending)) | + (i_rd_alu_en & i_alu_rd_sel1 & last_init); assign o_dbus_cyc = !o_cnt_en & init_done & i_dbus_en & !i_mem_misalign; //Prepare RF for reads when a new instruction is fetched // or when stage one caused an exception (rreq implies a write request too) - assign o_rf_rreq = i_ibus_ack | (stage_two_req & misalign_trap_sync); + assign o_rf_rreq = i_ibus_ack | (trap_pending & last_init); assign o_rf_rd_en = i_rd_op & !o_init; @@ -124,7 +125,8 @@ module serv_state shift : Shift in during phase 1. Continue shifting between phases (except for the first cycle after init). Shift out during phase 2 */ - assign o_bufreg_en = (o_cnt_en & (o_init | ((o_ctrl_trap | i_branch_op) & i_two_stage_op))) | (i_shift_op & !stage_two_req & (i_sh_right | i_sh_done_r) & init_done); + + assign o_bufreg_en = (o_cnt_en & (o_init | ((o_ctrl_trap | i_branch_op) & i_two_stage_op))) | (i_shift_op & init_done & (i_sh_right ? !stage_two_req : i_sh_done)); assign o_ibus_cyc = ibus_cyc & !i_rst; @@ -215,15 +217,15 @@ module serv_state assign o_ctrl_trap = WITH_CSR & (i_e_op | i_new_irq | misalign_trap_sync); - generate - if (WITH_CSR) begin : gen_csr - reg misalign_trap_sync_r; - //trap_pending is only guaranteed to have correct value during the // last cycle of the init stage wire trap_pending = WITH_CSR & ((take_branch & i_ctrl_misalign & !ALIGN) | (i_dbus_en & i_mem_misalign)); + generate + if (WITH_CSR) begin : gen_csr + reg misalign_trap_sync_r; + always @(posedge i_clk) begin if (i_ibus_ack | o_cnt_done | i_rst) misalign_trap_sync_r <= !(i_ibus_ack | i_rst) & ((trap_pending & o_init) | misalign_trap_sync_r); diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 8bac6af..b6523ad 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -153,7 +153,6 @@ module serv_top wire mem_half; wire [1:0] mem_bytecnt; wire sh_done; - wire sh_done_r; wire byte_valid; wire mem_misalign; @@ -255,7 +254,6 @@ module serv_top .o_ctrl_trap (trap), .i_ctrl_misalign(lsb[1]), .i_sh_done (sh_done), - .i_sh_done_r (sh_done_r), .o_mem_bytecnt (mem_bytecnt), .i_mem_misalign (mem_misalign), //Control @@ -406,7 +404,6 @@ module serv_top .i_lsb (lsb), .i_byte_valid (byte_valid), .o_sh_done (sh_done), - .o_sh_done_r (sh_done_r), //Control .i_op_b_sel (op_b_sel), .i_shift_op (shift_op), From 0a55885d3b4b1c5e04fe2b31ce62300dbeee20b6 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Thu, 30 Jan 2025 18:24:47 +0100 Subject: [PATCH 29/34] Move bytecnt to bufreg2 --- rtl/serv_bufreg2.v | 19 +++++++++++++++++-- rtl/serv_mem_if.v | 16 ---------------- rtl/serv_top.v | 4 +--- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/rtl/serv_bufreg2.v b/rtl/serv_bufreg2.v index 4afffb7..fe6d4c2 100644 --- a/rtl/serv_bufreg2.v +++ b/rtl/serv_bufreg2.v @@ -6,7 +6,7 @@ module serv_bufreg2 input wire i_init, input wire i_cnt_done, input wire [1:0] i_lsb, - input wire i_byte_valid, + input wire [1:0] i_bytecnt, output wire o_sh_done, //Control input wire i_op_b_sel, @@ -23,9 +23,24 @@ module serv_bufreg2 reg [31:0] dat; + /* + Before a store operation, the data to be written needs to be shifted into + place. Depending on the address alignment, we need to shift different + amounts. One formula for calculating this is to say that we shift when + i_lsb + i_bytecnt < 4. Unfortunately, the synthesis tools don't seem to be + clever enough so the hideous expression below is used to achieve the same + thing in a more optimal way. + */ + wire byte_valid + = (!i_lsb[0] & !i_lsb[1]) | + (!i_bytecnt[0] & !i_bytecnt[1]) | + (!i_bytecnt[1] & !i_lsb[1]) | + (!i_bytecnt[1] & !i_lsb[0]) | + (!i_bytecnt[0] & !i_lsb[1]); + assign o_op_b = i_op_b_sel ? i_rs2 : i_imm; - wire dat_en = i_shift_op | (i_en & i_byte_valid); + wire dat_en = i_shift_op | (i_en & byte_valid); /* The dat register has three different use cases for store, load and shift operations. diff --git a/rtl/serv_mem_if.v b/rtl/serv_mem_if.v index 7cdb39f..be68499 100644 --- a/rtl/serv_mem_if.v +++ b/rtl/serv_mem_if.v @@ -10,7 +10,6 @@ module serv_mem_if //State input wire [1:0] i_bytecnt, input wire [1:0] i_lsb, - output wire o_byte_valid, output wire o_misalign, //Control input wire i_signed, @@ -26,21 +25,6 @@ module serv_mem_if reg signbit; - /* - Before a store operation, the data to be written needs to be shifted into - place. Depending on the address alignment, we need to shift different - amounts. One formula for calculating this is to say that we shift when - i_lsb + i_bytecnt < 4. Unfortunately, the synthesis tools don't seem to be - clever enough so the hideous expression below is used to achieve the same - thing in a more optimal way. - */ - assign o_byte_valid - = (!i_lsb[0] & !i_lsb[1]) | - (!i_bytecnt[0] & !i_bytecnt[1]) | - (!i_bytecnt[1] & !i_lsb[1]) | - (!i_bytecnt[1] & !i_lsb[0]) | - (!i_bytecnt[0] & !i_lsb[1]); - wire dat_valid = i_mdu_op | i_word | diff --git a/rtl/serv_top.v b/rtl/serv_top.v index b6523ad..0b39662 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -153,7 +153,6 @@ module serv_top wire mem_half; wire [1:0] mem_bytecnt; wire sh_done; - wire byte_valid; wire mem_misalign; @@ -402,7 +401,7 @@ module serv_top .i_init (init), .i_cnt_done (cnt_done), .i_lsb (lsb), - .i_byte_valid (byte_valid), + .i_bytecnt (mem_bytecnt), .o_sh_done (sh_done), //Control .i_op_b_sel (op_b_sel), @@ -525,7 +524,6 @@ module serv_top //State .i_bytecnt (mem_bytecnt), .i_lsb (lsb), - .o_byte_valid (byte_valid), .o_misalign (mem_misalign), //Control .i_mdu_op (mdu_op), From a38110aea9862d7d70de448aa68622ab0f0b6053 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 4 Feb 2025 07:51:52 +0100 Subject: [PATCH 30/34] bufreg2: Split up dat_en to cnt_en and shift_en --- rtl/serv_bufreg2.v | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rtl/serv_bufreg2.v b/rtl/serv_bufreg2.v index fe6d4c2..a8b0ad1 100644 --- a/rtl/serv_bufreg2.v +++ b/rtl/serv_bufreg2.v @@ -40,12 +40,14 @@ module serv_bufreg2 assign o_op_b = i_op_b_sel ? i_rs2 : i_imm; - wire dat_en = i_shift_op | (i_en & byte_valid); + wire shift_en = i_shift_op ? (i_en & i_init) : (i_en & byte_valid); + + wire cnt_en = (i_shift_op & !i_init); /* The dat register has three different use cases for store, load and shift operations. store : Data to be written is shifted to the correct position in dat during - init by dat_en and is presented on the data bus as o_wb_dat + init by shift_en and is presented on the data bus as o_wb_dat load : Data from the bus gets latched into dat during i_wb_ack and is then shifted out at the appropriate time to end up in the correct position in rd @@ -54,7 +56,7 @@ module serv_bufreg2 o_sh_done when they wrap around to indicate that the requested number of shifts have been performed */ - wire [5:0] dat_shamt = (i_shift_op & !i_init) ? + wire [5:0] dat_shamt = cnt_en ? //Down counter mode dat[5:0]-1 : //Shift reg mode with optional clearing of bit 5 @@ -71,7 +73,7 @@ module serv_bufreg2 assign o_dat = dat; always @(posedge i_clk) begin - if (dat_en | i_load) + if (shift_en | cnt_en | i_load) dat <= i_load ? i_dat : {o_op_b, dat[31:7], dat_shamt}; end From 9e73e11d86309cfcd783a94e05dfbd0536f38d9a Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Sat, 1 Mar 2025 23:18:59 +0100 Subject: [PATCH 31/34] Fix verilator_waiver.vlt --- data/verilator_waiver.vlt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/verilator_waiver.vlt b/data/verilator_waiver.vlt index d17b4a7..e6d7bcc 100644 --- a/data/verilator_waiver.vlt +++ b/data/verilator_waiver.vlt @@ -1,6 +1,6 @@ `verilator_config // Bits [1:0] in i_wb_rdt are not used at all -lint_off -rule UNUSED -file "*/serv_top.v" -lines 182 +lint_off -rule UNUSED -file "*/serv_top.v" -lines 179 //Some bits in the instruction word are not used in serv_decode but it's easier //to just send in the whole word than picking out bits From 79768a8ac99de8ff66fe316565388c2a4031d96a Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 18 Mar 2025 13:15:46 +0100 Subject: [PATCH 32/34] Silence warning about unused return value in testbench --- bench/servant_tb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bench/servant_tb.cpp b/bench/servant_tb.cpp index 7641ab6..92a56b9 100644 --- a/bench/servant_tb.cpp +++ b/bench/servant_tb.cpp @@ -154,7 +154,7 @@ int main(int argc, char **argv, char **env) do_gpio(&gpio_context, top->q); } if (tf && top->wb_clk && top->pc_vld) - write(tf, (void *)&top->pc_adr, 4); + if (write(tf, (void *)&top->pc_adr, 4) < 0) exit(1); if (timeout && (main_time >= timeout)) { printf("Timeout: Exiting at time %lu\n", main_time); done = true; From 629e6727f58b956c75b1dfeb0ada7c7563d04604 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 11 Feb 2025 10:36:12 +0100 Subject: [PATCH 33/34] Move shamt to top byte in bufreg2 Instead of shifting shamt all the way to bits 4:0, we just shift 8 steps. This saves some energy and allows us to be finished before cnt_done. --- rtl/serv_bufreg2.v | 10 +++++----- rtl/serv_top.v | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/rtl/serv_bufreg2.v b/rtl/serv_bufreg2.v index a8b0ad1..3445700 100644 --- a/rtl/serv_bufreg2.v +++ b/rtl/serv_bufreg2.v @@ -4,7 +4,7 @@ module serv_bufreg2 //State input wire i_en, input wire i_init, - input wire i_cnt_done, + input wire i_cnt7, input wire [1:0] i_lsb, input wire [1:0] i_bytecnt, output wire o_sh_done, @@ -40,7 +40,7 @@ module serv_bufreg2 assign o_op_b = i_op_b_sel ? i_rs2 : i_imm; - wire shift_en = i_shift_op ? (i_en & i_init) : (i_en & byte_valid); + wire shift_en = i_shift_op ? (i_en & i_init & (i_bytecnt == 2'b00)) : (i_en & byte_valid); wire cnt_en = (i_shift_op & !i_init); @@ -58,9 +58,9 @@ module serv_bufreg2 */ wire [5:0] dat_shamt = cnt_en ? //Down counter mode - dat[5:0]-1 : + dat[29:24]-1 : //Shift reg mode with optional clearing of bit 5 - {dat[6] & !(i_shift_op & i_cnt_done),dat[5:1]}; + {dat[30] & !(i_shift_op & i_cnt7),dat[29:25]}; assign o_sh_done = dat_shamt[5]; @@ -74,7 +74,7 @@ module serv_bufreg2 always @(posedge i_clk) begin if (shift_en | cnt_en | i_load) - dat <= i_load ? i_dat : {o_op_b, dat[31:7], dat_shamt}; + dat <= i_load ? i_dat : {o_op_b, dat[31], dat_shamt, dat[24:1]}; end endmodule diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 0b39662..3a9fc76 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -399,7 +399,7 @@ module serv_top //State .i_en (cnt_en), .i_init (init), - .i_cnt_done (cnt_done), + .i_cnt7 (cnt7), .i_lsb (lsb), .i_bytecnt (mem_bytecnt), .o_sh_done (sh_done), From f6116cf2ec8cb2d906f01c1c4d279fadc2d38d3f Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 11 Feb 2025 15:41:41 +0100 Subject: [PATCH 34/34] Make right-shifts one cycle faster This allows removing the stage_two_req register as well. --- rtl/serv_bufreg2.v | 4 +++- rtl/serv_state.v | 9 ++------- rtl/serv_top.v | 2 ++ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/rtl/serv_bufreg2.v b/rtl/serv_bufreg2.v index 3445700..ee25576 100644 --- a/rtl/serv_bufreg2.v +++ b/rtl/serv_bufreg2.v @@ -5,6 +5,8 @@ module serv_bufreg2 input wire i_en, input wire i_init, input wire i_cnt7, + input wire i_cnt_done, + input wire i_sh_right, input wire [1:0] i_lsb, input wire [1:0] i_bytecnt, output wire o_sh_done, @@ -42,7 +44,7 @@ module serv_bufreg2 wire shift_en = i_shift_op ? (i_en & i_init & (i_bytecnt == 2'b00)) : (i_en & byte_valid); - wire cnt_en = (i_shift_op & !i_init); + wire cnt_en = (i_shift_op & (!i_init | (i_cnt_done & i_sh_right))); /* The dat register has three different use cases for store, load and shift operations. diff --git a/rtl/serv_state.v b/rtl/serv_state.v index 487bd82..bd73b3c 100644 --- a/rtl/serv_state.v +++ b/rtl/serv_state.v @@ -59,7 +59,6 @@ module serv_state input wire i_rf_ready, output wire o_rf_rd_en); - reg stage_two_req; reg init_done; wire misalign_trap_sync; @@ -101,7 +100,7 @@ module serv_state //Right shift. o_sh_done //Mem ops. i_dbus_ack //MDU ops. i_mdu_ready - assign o_rf_wreq = (i_shift_op & (i_sh_right ? (i_sh_done & !o_cnt_en & init_done) : last_init)) | + assign o_rf_wreq = (i_shift_op & (i_sh_right ? (i_sh_done & (last_init | !o_cnt_en & init_done)) : last_init)) | i_dbus_ack | (MDU & i_mdu_ready) | (i_branch_op & (last_init & !trap_pending)) | (i_rd_alu_en & i_alu_rd_sel1 & last_init); @@ -126,7 +125,7 @@ module serv_state for the first cycle after init). Shift out during phase 2 */ - assign o_bufreg_en = (o_cnt_en & (o_init | ((o_ctrl_trap | i_branch_op) & i_two_stage_op))) | (i_shift_op & init_done & (i_sh_right ? !stage_two_req : i_sh_done)); + assign o_bufreg_en = (o_cnt_en & (o_init | ((o_ctrl_trap | i_branch_op) & i_two_stage_op))) | (i_shift_op & init_done & (i_sh_right | i_sh_done)); assign o_ibus_cyc = ibus_cyc & !i_rst; @@ -152,14 +151,10 @@ module serv_state o_ctrl_jump <= o_init & take_branch; end - //Need a strobe for the first cycle in the IDLE state after INIT - stage_two_req <= o_cnt_done & o_init; - if (i_rst) begin if (RESET_STRATEGY != "NONE") begin init_done <= 1'b0; o_ctrl_jump <= 1'b0; - stage_two_req <= 1'b0; end end end diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 3a9fc76..425f325 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -400,6 +400,8 @@ module serv_top .i_en (cnt_en), .i_init (init), .i_cnt7 (cnt7), + .i_cnt_done (cnt_done), + .i_sh_right (sh_right), .i_lsb (lsb), .i_bytecnt (mem_bytecnt), .o_sh_done (sh_done),