diff --git a/Bender.yml b/Bender.yml index c4bcd6af..077b5eb8 100644 --- a/Bender.yml +++ b/Bender.yml @@ -6,12 +6,12 @@ package: dependencies: # TODO: only 1st level dependencies needed, also semantic versions prefered over commit hashes apb_gpio: { git: "https://github.com/pulp-platform/apb_gpio.git", rev: "f82caeb7f7d89427f05e9af5ed31e0675efe0d83" } - apb_uart: { git: "https://github.com/pulp-platform/apb_uart.git", rev: "6c7dde3d749ac8274377745c105da8c8b8cd27c6" } + apb_uart: { git: "https://github.com/pulp-platform/apb_uart.git", version: "0.2.3" } axi: { git: "https://github.com/pulp-platform/axi.git", version: "0.38.0" } common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: "1.37.0" } - riscv-dbg: { git: "https://github.com/pulp-platform/riscv-dbg.git", rev: "618ee6e0e2610ef47e0dcc4df6748af3dffff731" } + riscv-dbg: { git: "https://github.com/pulp-platform/riscv-dbg.git", version: "0.8.1" } apb: { git: "https://github.com/pulp-platform/apb.git", version: "0.2.1" } - obi: { git: "https://github.com/pulp-platform/obi.git", rev: "ad1d48f025be540344960ea83b4bff39876f9b36" } + obi: { git: "https://github.com/pulp-platform/obi.git", version: "0.1.7" } vbench: { git: "https://github.com/ANurmi/vbench", rev: "main" } # tech_cells_generic: { git: "https://github.com/pulp-platform/tech_cells_generic.git", rev: "7968dd6e6180df2c644636bc6d2908a49f2190cf" } # kth_ss: { path: 'Subsystem_KTH/src/interface/kth_ss' } @@ -45,6 +45,7 @@ sources: - vendor_ips/ibex/rtl/ibex_fetch_fifo.sv - vendor_ips/ibex/rtl/ibex_prefetch_buffer.sv - vendor_ips/ibex/rtl/ibex_multdiv_fast.sv + - vendor_ips/ibex/rtl/ibex_multdiv_slow.sv - vendor_ips/ibex/rtl/ibex_register_file_ff.sv - vendor_ips/ibex/rtl/ibex_ex_block.sv - vendor_ips/ibex/rtl/ibex_controller.sv @@ -136,7 +137,13 @@ sources: - src/generated/SysCtrl_SS_wrapper_0.v - src/generated/Didactic.v - - target: not(synthesis) + - target: verilator + files: + - src/rtl/mock_uart.sv + - verilator/rtl/didactic_student_domain.sv + - verilator/rtl/didactic_vtop.sv + + - target: not(any(synthesis, verilator)) files: - src/tech_generic/io_cell.sv - vendor_ips/pulp/rtl/tb/riscv_pkg.sv @@ -177,6 +184,7 @@ vendor_package: - "rtl/ibex_fetch_fifo.sv" - "rtl/ibex_prefetch_buffer.sv" - "rtl/ibex_multdiv_fast.sv" + - "rtl/ibex_multdiv_slow.sv" - "rtl/ibex_register_file_ff.sv" - "rtl/ibex_ex_block.sv" - "rtl/ibex_controller.sv" diff --git a/Makefile b/Makefile index 34ff04ac..03568a88 100644 --- a/Makefile +++ b/Makefile @@ -93,6 +93,19 @@ fpga: check-env # verilator targets ###################################################################### +.PHONY: vlint +vlint: + $(MAKE) -C verilator vlint + +.PHONY: vbuild +vbuild: + $(MAKE) -C verilator vbuild + +.PHONY: simv +simv: + $(MAKE) -C verilator simv + +# Legacy target .PHONY: verilate verilate: @python3 ./verification/verilator/verilate.py diff --git a/src/generated/SysCtrl_SS_0.v b/src/generated/SysCtrl_SS_0.v index 66cb3a4f..16b234d7 100644 --- a/src/generated/SysCtrl_SS_0.v +++ b/src/generated/SysCtrl_SS_0.v @@ -1349,6 +1349,7 @@ module SysCtrl_SS_0 #( .spi_sdo2 (apb_spi_master_spi_sdo2), .spi_sdo3 (apb_spi_master_spi_sdo3)); +`ifndef VERILATOR // IP-XACT VLNV: tuni.fi:pulp.peripheral:apb_uart:1.0 apb_uart apb_uart( // Interface: APB @@ -1378,6 +1379,21 @@ module SysCtrl_SS_0 #( .OUT1N (), .OUT2N (), .RTSN ()); +`else + mock_uart i_mock_uart ( + .clk_i (apb_uart_CLK), + .rst_ni (apb_uart_RSTN), + .penable_i (apb_uart_PENABLE), + .pwrite_i (apb_uart_PWRITE), + .paddr_i ({29'b0,apb_uart_PADDR}), + .psel_i (apb_uart_PSEL), + .pwdata_i (apb_uart_PWDATA), + .prdata_o (apb_uart_PRDATA), + .pready_o (apb_uart_PREADY), + .pslverr_o (apb_uart_PSLVERR) +); +assign apb_uart_INT = 1'b0; +`endif // IP-XACT VLNV: tuni.fi:ip:SS_Ctrl_reg_array:1.1 SS_Ctrl_reg_array #( diff --git a/src/rtl/SS_Ctrl_reg_array.sv b/src/rtl/SS_Ctrl_reg_array.sv index 269c2d00..71741c58 100644 --- a/src/rtl/SS_Ctrl_reg_array.sv +++ b/src/rtl/SS_Ctrl_reg_array.sv @@ -169,7 +169,7 @@ module SS_Ctrl_reg_array #( default: begin // io cell cfg for(int i=0; i < IOCELL_COUNT; i++) begin - if ( addr_i[15:0] == 'h28+i*4) begin // check 28 - 88 + if ( addr_i[15:0] == 16'('h28+i*4)) begin // check 28 - 88 io_cell_cfg_reg[i] <= wdata_i; end end @@ -205,7 +205,7 @@ module SS_Ctrl_reg_array #( default: begin // io cell cfg for(int i=0; i < IOCELL_COUNT; i++) begin - if ( addr_i[15:0] == 'h28+i*4) begin // check 28 - 88 + if ( addr_i[15:0] == 16'('h28+i*4)) begin // check 28 - 88 rdata_out_reg <= io_cell_cfg_reg[i]; end end @@ -233,7 +233,7 @@ module SS_Ctrl_reg_array #( rdata_o = rdata_out_reg; for(int i=0; i < IOCELL_COUNT; i++) begin - cell_cfg[i*IOCELL_CFG_W +:IOCELL_CFG_W] = io_cell_cfg_reg[i]; + cell_cfg[i*IOCELL_CFG_W +:IOCELL_CFG_W] = io_cell_cfg_reg[i][9:0]; end end // comb_logic @@ -257,7 +257,7 @@ assign irq_en_4 = ss_4_ctrl_reg[31]; assign ss_ctrl_4 = ss_4_ctrl_reg[SS_CTRL_W-1:0]; assign ss_ctrl_icn = icn_ctrl_reg[SS_CTRL_W-1:0]; -assign pmod_sel = pmod_sel_reg; +assign pmod_sel = pmod_sel_reg[7:0]; assign fetch_en = fetch_en_reg[3:0]; diff --git a/src/rtl/mock_uart.sv b/src/rtl/mock_uart.sv new file mode 100644 index 00000000..1cf0eb33 --- /dev/null +++ b/src/rtl/mock_uart.sv @@ -0,0 +1,120 @@ +// Copyright 2018 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +// +// Author: Florian Zaruba, ETH Zurich +// Date: 28/09/2018 +// Description: Mock replacement for UART in testbench (not synthesiesable!) + +module mock_uart ( + input logic clk_i, + input logic rst_ni, + input logic penable_i, + input logic pwrite_i, + input logic [31:0] paddr_i, + input logic psel_i, + input logic [31:0] pwdata_i, + output logic [31:0] prdata_o, + output logic pready_o, + output logic pslverr_o +); + localparam RBR = 0; + localparam THR = 0; + localparam IER = 1; + localparam IIR = 2; + localparam FCR = 2; + localparam LCR = 3; + localparam MCR = 4; + localparam LSR = 5; + localparam MSR = 6; + localparam SCR = 7; + localparam DLL = 0; + localparam DLM = 1; + + localparam THRE = 5; // transmit holding register empty + localparam TEMT = 6; // transmit holding register empty + + byte lcr = 0; + byte dlm = 0; + byte dll = 0; + byte mcr = 0; + byte lsr = 0; + byte ier = 0; + byte msr = 0; + byte scr = 0; + logic fifo_enabled = 1'b0; + + assign pready_o = 1'b1; + assign pslverr_o = 1'b0; + + function void uart_tx(byte ch); + $write("%c", ch); + endfunction : uart_tx + +/* verilator lint_off WIDTHTRUNC */ +/* verilator lint_off WIDTHEXPAND */ +/* verilator lint_off WIDTHCONCAT */ + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (rst_ni) begin + if (psel_i & penable_i & pwrite_i) begin + case ((paddr_i >> 'h2) & 'h7) + THR: begin + if (lcr & 'h80) dll <= byte'(pwdata_i[7:0]); + else uart_tx(byte'(pwdata_i[7:0])); + end + IER: begin + if (lcr & 'h80) dlm <= byte'(pwdata_i[7:0]); + else ier <= byte'(pwdata_i[7:0] & 'hF); + end + FCR: begin + if (pwdata_i[0]) fifo_enabled <= 1'b1; + else fifo_enabled <= 1'b0; + end + LCR: lcr <= byte'(pwdata_i[7:0]); + MCR: mcr <= byte'(pwdata_i[7:0] & 'h1F); + LSR: lsr <= byte'(pwdata_i[7:0]); + MSR: msr <= byte'(pwdata_i[7:0]); + SCR: scr <= byte'(pwdata_i[7:0]); + default:; + endcase + end + end + end + + always_comb begin + prdata_o = '0; + if (psel_i & penable_i & ~pwrite_i) begin + case ((paddr_i >> 'h2) & 'h7) + THR: begin + if (lcr & 'h80) prdata_o = {24'b0, dll}; + end + IER: begin + if (lcr & 'h80) prdata_o = {24'b0, dlm}; + else prdata_o = {24'b0, ier}; + end + IIR: begin + if (fifo_enabled) prdata_o = {24'b0, 8'hc0}; + else prdata_o = {24'b0, 8'b0}; + end + LCR: prdata_o = {24'b0, lcr}; + MCR: prdata_o = {24'b0, mcr}; + LSR: prdata_o = {24'b0, (lsr | (1 << THRE) | (1 << TEMT))}; + MSR: prdata_o = {24'b0, msr}; + SCR: prdata_o = {24'b0, scr}; + default:; + endcase + end + end + +/* verilator lint_on WIDTHTRUNC */ +/* verilator lint_on WIDTHEXPAND */ +/* verilatr lint_on WIDTHCONCAT */ + +endmodule diff --git a/src/rtl/peripherals_obi_to_apb.sv b/src/rtl/peripherals_obi_to_apb.sv index 2d8fddf7..0bee6fcd 100644 --- a/src/rtl/peripherals_obi_to_apb.sv +++ b/src/rtl/peripherals_obi_to_apb.sv @@ -219,7 +219,7 @@ module peripherals_obi_to_apb #( assign peripheral_bus[0].prdata = APB_GPIO_PRDATA; assign peripheral_bus[0].pready = APB_GPIO_PREADY; assign peripheral_bus[0].pslverr = APB_GPIO_PSLVERR; - assign APB_GPIO_PADDR = peripheral_bus[0].paddr; + assign APB_GPIO_PADDR = peripheral_bus[0].paddr[11:0]; assign APB_GPIO_PENABLE = peripheral_bus[0].penable; assign APB_GPIO_PSEL = peripheral_bus[0].psel; assign APB_GPIO_PWDATA = peripheral_bus[0].pwdata; @@ -229,7 +229,7 @@ module peripherals_obi_to_apb #( assign peripheral_bus[1].prdata = APB_UART_PRDATA; assign peripheral_bus[1].pready = APB_UART_PREADY; assign peripheral_bus[1].pslverr = APB_UART_PSLVERR; - assign APB_UART_PADDR = peripheral_bus[1].paddr; + assign APB_UART_PADDR = peripheral_bus[1].paddr[11:0]; assign APB_UART_PENABLE = peripheral_bus[1].penable; assign APB_UART_PSEL = peripheral_bus[1].psel; assign APB_UART_PWDATA = peripheral_bus[1].pwdata; @@ -239,7 +239,7 @@ module peripherals_obi_to_apb #( assign peripheral_bus[2].prdata = APB_SPI_PRDATA; assign peripheral_bus[2].pready = APB_SPI_PREADY; assign peripheral_bus[2].pslverr = APB_SPI_PSLVERR; - assign APB_SPI_PADDR = peripheral_bus[2].paddr; + assign APB_SPI_PADDR = peripheral_bus[2].paddr[11:0]; assign APB_SPI_PENABLE = peripheral_bus[2].penable; assign APB_SPI_PSEL = peripheral_bus[2].psel; assign APB_SPI_PWDATA = peripheral_bus[2].pwdata; diff --git a/src/rtl/sp_sram.sv b/src/rtl/sp_sram.sv index 117babd9..93b1a6c2 100644 --- a/src/rtl/sp_sram.sv +++ b/src/rtl/sp_sram.sv @@ -57,7 +57,9 @@ module sp_sram #( `ifndef ASIC /************* SIM MODEL / FPGA INFERENCE *******************/ logic [DATA_WIDTH-1:0] ram [NUM_WORDS-1:0]; - logic [ADDR_WIDTH-1:0] raddr_q; + logic [ADDR_WIDTH-1:0] raddr_q, local_addr; + + assign local_addr = addr_i >> 2; generate // if defined, preload simulation memory with external file @@ -79,7 +81,7 @@ module sp_sram #( end else begin if(req_i && !we_i) - raddr_q <= addr_i; + raddr_q <= local_addr; end end @@ -89,7 +91,7 @@ module sp_sram #( always @(posedge clk_i) begin if (req_i && we_i) begin if(be_i[i]) begin - ram[addr_i][(i+1)*8-1:i*8]<= wdata_i[(i+1)*8-1:i*8]; + ram[local_addr][(i+1)*8-1:i*8]<= wdata_i[(i+1)*8-1:i*8]; end end end @@ -100,6 +102,4 @@ module sp_sram #( `endif - assign ruser_o = 1'b0; - endmodule diff --git a/sw/Makefile b/sw/Makefile index e21a694b..63414414 100644 --- a/sw/Makefile +++ b/sw/Makefile @@ -11,7 +11,7 @@ SHELL = bash BUILD_DIR ?= ../build XLEN ?= 32 PREFIX ?= riscv$(XLEN)-unknown-elf -ARCH_FLAGS ?= -march=rv32imc -mabi=ilp32 +ARCH_FLAGS ?= -march=rv32imc_zicsr -mabi=ilp32 CC=$(PREFIX)-gcc CFLAGS=-O2 -g -ffunction-sections -fdata-sections -Icommon/ OBJDUMP ?= $(PREFIX)-objdump diff --git a/sw/common/crt0.S b/sw/common/crt0.S index 93ed70a6..e1724026 100644 --- a/sw/common/crt0.S +++ b/sw/common/crt0.S @@ -14,7 +14,9 @@ reset_handler: la x2, stack - la ra, postMain + la ra, postMain + //la t0, default_handler + //csrw mtvec, t0 j main /* Didactic specific return code pass over through jtag */ @@ -24,6 +26,7 @@ postMain: li t1, 0x80000000 or a0, a0, t1 sw a0, 0(t0) + wfi .global changeStack changeStack: @@ -33,7 +36,7 @@ changeStack: .section .vectors, "ax" .option norvc; .org 0x0 - jal x0, default_handler + jal x0, reset_handler jal x0, default_handler jal x0, default_handler jal x0, default_handler @@ -75,4 +78,7 @@ loop: j loop default_handler: - mret + li t0, 0x01020380 + li t1, 0x8BADC0DE + sw t1, 0(t0) + wfi diff --git a/sw/common/uart.h b/sw/common/uart.h index b8b9704f..726d9a35 100644 --- a/sw/common/uart.h +++ b/sw/common/uart.h @@ -41,29 +41,34 @@ void uart_init(){ } +// Poll until the transmit buffer is empty +int is_transmit_empty() +{ + return (LSR) & 0x20; +} + +// Poll until the transmit buffer is empty +void write_serial(char a) +{ + while (!is_transmit_empty()) {}; + RBR_THR_DLL = a; +} + void uart_print(const char str[]){ for (int i = 0; str[i] != '\0'; i++) { + write_serial(str[i]); + } +} +void mock_uart_print(const char str[]) { + //for (int i = 0; str[i] != '\0'; i++) { + //RBR_THR_DLL = str[i]; + //} + int i=0; + do { RBR_THR_DLL = str[i]; - - // best: IRQ based - // TBD - - // better: poll when char has been sent - // volatile int temp = LSR; - // while(temp != 0){ - // temp = LSR; - // - // } - // } - - // basic: manually nop until time has passed - volatile uint32_t wait_loop=0; - while(wait_loop<500){ - asm("nop"); - wait_loop++; - } - } + i++; + } while (str[i] != '\0'); } int uart_loopback_test(){ diff --git a/sw/hello/hello.c b/sw/hello/hello.c index 59475379..c9dac7d3 100644 --- a/sw/hello/hello.c +++ b/sw/hello/hello.c @@ -13,7 +13,8 @@ int main() { uart_init(); - uart_print("hello from didactic!\n"); + //uart_print("hello from didactic!\n"); + mock_uart_print("hello from didactic!\n"); return 0; -} \ No newline at end of file +} diff --git a/verilator/Makefile b/verilator/Makefile new file mode 100644 index 00000000..042a69d5 --- /dev/null +++ b/verilator/Makefile @@ -0,0 +1,85 @@ +ROOT = $(realpath $(CURDIR))/.. +BUILD_DIR = $(ROOT)/build +VERIL_DIR = $(ROOT)/verilator +VERIL_BUILD_DIR = $(BUILD_DIR)/verilator_build + +DUT_TOP = didactic_vtop +CPP_TOP = $(VERIL_DIR)/TbDidactic.cpp +WAIVER = $(VERIL_DIR)/didactic.vlt + +IMEM_WORDS = 16384 +DMEM_START = 16385 + +BENDER_TARGETS = \ + -t tech_cells_generic_exclude_deprecated \ + -t rtl \ + -t vendor \ + -t verilator \ + -t tracer \ + -t didactic_obi + +VBENCH = $(shell bender path vbench) + +SRC_FILES = $(shell bender script flist $(BENDER_TARGETS)) + +VERIL_DEFINES ?= \ + +define+VERILATOR=1 \ + +define+ROOT=$(ROOT) \ + +define+RVFI \ + +define+DV_FCOV_DISABLE \ + +define+COMMON_CELLS_ASSERTS_OFF + +VERIL_INCLUDES ?= \ + +incdir+$(ROOT)/vendor_ips/ibex/vendor/lowrisc_ip/dv/sv/dv_utils \ + +incdir+$(ROOT)/vendor_ips/ibex/vendor/lowrisc_ip/ip/prim/rtl \ + +incdir+$(shell bender path common_cells)/include \ + +incdir+$(shell bender path apb)/include \ + +incdir+$(shell bender path axi)/include \ + +incdir+$(shell bender path obi)/include \ + +incdir+$(shell bender path register_interface)/include + +VERIL_COMMON = \ + $(VERIL_DEFINES) \ + $(VERIL_INCLUDES) \ + $(WAIVER) \ + $(SRC_FILES) \ + --top-module $(DUT_TOP) \ + +.PHONY: init clean vlint vbuild simv + +init: + @mkdir -p $(VERIL_BUILD_DIR) + +vlint: + verilator --lint-only \ + $(VERIL_COMMON) + @echo "Lint [OK]" + + +.PHONY: $(TEST) +$(TEST): + @cp $(BUILD_DIR)/sw/$(TEST).hex $(VERIL_BUILD_DIR)/verilator_stim.hex + @head -$(IMEM_WORDS) $(VERIL_BUILD_DIR)/verilator_stim.hex > $(VERIL_BUILD_DIR)/imem_stim.hex + @tail -n +$(DMEM_START) $(VERIL_BUILD_DIR)/verilator_stim.hex > $(VERIL_BUILD_DIR)/dmem_stim.hex + +vbuild: init + verilator \ + $(VERIL_COMMON) \ + --timing \ + --trace-fst \ + --trace-structs \ + --trace-params \ + --hierarchical \ + --exe $(CPP_TOP) \ + --cc \ + -CFLAGS "-I$(VBENCH)/src -DROOT=$(ROOT)" \ + --unroll-count 256 \ + --build \ + --Mdir $(VERIL_BUILD_DIR)/obj_dir \ + -j `nproc` + +simv: $(TEST) + $(VERIL_BUILD_DIR)/obj_dir/V$(DUT_TOP) $(TEST) + +clean: + @rm -fr $(VERIL_BUILD_DIR) diff --git a/verilator/TbDidactic.cpp b/verilator/TbDidactic.cpp new file mode 100644 index 00000000..e6e9a1fd --- /dev/null +++ b/verilator/TbDidactic.cpp @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +#define CLKI clk_i +#define RSTNI rst_ni + +#define JTAGTCK jtag_tck_i +#define JTAGTDI jtag_td_i +#define JTAGTDO jtag_td_o +#define JTAGTMS jtag_tms_i +#define JTAGTRSTN jtag_trst_ni + +#define IDCODE 0x1c0ffee1 + +#include "TbDidactic.h" + +int main(int argc, char** argv) { + + Verilated::commandArgs(argc, argv); + + TbDidactic* tb = new TbDidactic(); + tb->print_logo(); + + if (argc == 1) { + printf("[TB] No TEST specified, exiting..\n\n"); + std::exit(EXIT_SUCCESS); + } + + const std::string TracePath = std::string(xstr(ROOT)) + "/build/verilator_build/waveform.fst"; + std::cout << "[TB] Waveform path: " << TracePath << std::endl; + tb->open_trace(TracePath.c_str()); + // this tb assumes only one passed argument: the ELF + const std::string elfname(argv[1]); + std::filesystem::path elfpath = tb->resolve_elf(elfname); + + tb->reset(); + tb->jtag_reset_master(); + tb->jtag_init(); + + tb->jtag_halt_hart(); + std::cout << "[TB] Running preloaded program from entry point in " + << elfpath.string() + << std::endl; + tb->jtag_resume_hart_from(tb->get_entry(elfpath.string())); + tb->jtag_wait_eoc(); + + delete tb; + + return 0; +} diff --git a/verilator/TbDidactic.h b/verilator/TbDidactic.h new file mode 100644 index 00000000..b250d9cd --- /dev/null +++ b/verilator/TbDidactic.h @@ -0,0 +1,46 @@ +#include "verilated_fst_c.h" +#include "verilated.h" +#include "Vdidactic_vtop.h" +#include "Testbench.h" + +#define xstr(s) str(s) +#define str(s) #s + +// Add platform-specific overrides in this file +class TbDidactic : public Testbench { + + public: + + void print_logo(void) { + printf(" ___ _ _ _ _ _____ _ _ _ \n"); + printf(" / (_) __| | __ _ ___| |_(_) ___ /__ \\___ ___| |_| |__ ___ _ __ ___| |__ \n"); + printf(" / /\\ / |/ _` |/ _` |/ __| __| |/ __| / /\\/ _ \\/ __| __| '_ \\ / _ \\ '_ \\ / __| '_ \\ \n"); + printf(" / /_//| | (_| | (_| | (__| |_| | (__ / / | __/\\__ \\ |_| |_) | __/ | | | (__| | | |\n"); + printf("/___,' |_|\\__,_|\\__,_|\\___|\\__|_|\\___| \\/ \\___||___/\\__|_.__/ \\___|_| |_|\\___|_| |_|\n"); + printf("///////////////////////////////////////////////////////////////////////////////////////\n"); + printf("\n"); + } + + std::filesystem::path resolve_elf(std::string elf_name) { + std::filesystem::path res = elf_name; + if (elf_name.substr(elf_name.size() - 4) != ".elf") { + res += ".elf"; + } + + if (!std::filesystem::exists(res)) { + // naive path does not exist, look in build dir + std::string repo_root = xstr(ROOT); + std::filesystem::path bd = repo_root + "/build/sw/"; + std::filesystem::path full_path = bd.string() + res.string(); + if (std::filesystem::exists( full_path.string())) { + res = full_path; + } else { + std::cerr << "ELF not found! Looked in:" << std::endl + << "1: " << res.string() << std::endl + << "2: " << bd.string() + res.string() << std::endl; + std::exit(EXIT_FAILURE); + } + } + return res; + } +}; diff --git a/verilator/didactic.vlt b/verilator/didactic.vlt new file mode 100644 index 00000000..c5c6246f --- /dev/null +++ b/verilator/didactic.vlt @@ -0,0 +1,56 @@ +`verilator_config + +// Ignore duplicate modules +//lint_off -rule MODDUP + +// Waive macro redefinition warnings on prim_assert +lint_off -rule REDEFMACRO -file "**/prim_assert_dummy_macros.svh" -match "*" +lint_off -rule REDEFMACRO -file "**/prim_assert.sv" -match "*" + +// Waivers on external dependcies +lint_off -rule WIDTHTRUNC -file "*/.bender/*" -match "*" +lint_off -rule WIDTHEXPAND -file "*/.bender/*" -match "*" +lint_off -rule BLKSEQ -file "*/.bender/*" -match "*" +lint_off -rule LATCH -file "*/.bender/*" -match "*" +lint_off -rule UNOPTFLAT -file "*/.bender/*" -match "*" +lint_off -rule CASEINCOMPLETE -file "*/vendor_ips/*" -match "*" +lint_off -rule UNOPTFLAT -file "*/vendor_ips/*" -match "*" +lint_off -rule UNUSEDPARAM -file "*/vendor_ips/*" -match "*" +lint_off -rule UNUSEDPARAM -file "*/.bender/*" -match "*" +lint_off -rule UNUSEDSIGNAL -file "*/vendor_ips/*" -match "*" +lint_off -rule UNUSEDSIGNAL -file "*/.bender/*" -match "*" +lint_off -rule UNDRIVEN -file "*/vendor_ips/*" -match "*" +lint_off -rule CASEINCOMPLETE -file "*/.bender/*" -match "*" +lint_off -rule CMPCONST -file "*/.bender/*" -match "*" +lint_off -rule WIDTHEXPAND -file "*/vendor_ips/*" -match "*" +lint_off -rule UNSIGNED -file "*/.bender/*" -match "*" + +// OBI +// ASCRANGE unknown by 5.008 +//lint_off -rule ASCRANGE -file "*/obi-*/*" -match "*" +//lint_off -rule ASCRANGE -file "*/obi*.sv" -match "*" +lint_off -rule LITENDIAN -file "*/obi-*/*" -match "*" +lint_off -rule LITENDIAN -file "*/obi*.sv" -match "*" +lint_off -rule LITENDIAN -file "*/apb_gpio-*.sv" -match "*" +lint_off -rule WIDTHTRUNC -file "*/obi*.sv" -match "*" +lint_off -rule WIDTHEXPAND -file "*/obi*.sv" -match "*" + +lint_off -rule BLKSEQ -file "*/tech_generic/*" -match "*" + + +// Waivers on generated RTL +lint_off -rule UNUSEDSIGNAL -file "*/generated/*" -match "*" +lint_off -rule PINMISSING -file "*/generated/*" -match "*" + +// Waivers on DTU subsystem +lint_off -rule UNUSEDSIGNAL -file "*/DtuSubsystem.sv" -match "*" + +// Waive MODDUP in AXI repo +lint_off -rule MODDUP -file "*/axi-*/*" -match "*" + + +// Waive MULTIDRIVEN on Ibex tracer +lint_off -rule MULTIDRIVEN -file "*/ibex_tracer.sv" -match "*" + +// LATCH intentional, waive warning +lint_off -rule LATCH -file "*/prim_clock_gating.v" -match "*" diff --git a/verilator/rtl/didactic_student_domain.sv b/verilator/rtl/didactic_student_domain.sv new file mode 100644 index 00000000..860ac866 --- /dev/null +++ b/verilator/rtl/didactic_student_domain.sv @@ -0,0 +1,19 @@ +module didactic_student_domain #( + parameter int unsigned ApbAddrWidth = 32'd12, + parameter int unsigned ApbDataWidth = 32'd32 +) ( + input logic clk_i, + input logic rst_ni, + output logic irq_o, + input logic penable_i, + input logic psel_i, + output logic pready_o, + output logic pslverr_o, + input logic [ApbAddrWidth-1:0] paddr_i, + input logic [ApbDataWidth-1:0] pwdata_i, + output logic [ApbDataWidth-1:0] prdata_o +); + + +endmodule : didactic_student_domain + diff --git a/verilator/rtl/didactic_vtop.sv b/verilator/rtl/didactic_vtop.sv new file mode 100644 index 00000000..6437610f --- /dev/null +++ b/verilator/rtl/didactic_vtop.sv @@ -0,0 +1,113 @@ +/* + * A Verilator-friendly, minimal SysCtrl + student subsystem + * wrapper for COMP.CE.250 System-on-Chip Design. + * + * Author: Antti Nurmi + */ + +module didactic_vtop #( +) ( + input logic clk_i, + input logic rst_ni, + input logic jtag_tck_i, + input logic jtag_tms_i, + input logic jtag_trst_ni, + input logic jtag_td_i, + output logic jtag_td_o +); + + logic dut_uart_tx; + + SysCtrl_SS_0 #( + .IOCELL_CFG_W(10), + .IOCELL_COUNT(25), + .NUM_GPIO (16), + .SS_CTRL_W (8), + .OBI_IDW (1), + .OBI_CHKW (1), + .OBI_USERW (1), + .OBI_AW (32), + .OBI_DW (32), + .NUM_SS (5) + ) SysCtrl_SS ( + .clk_internal (clk_i), + .gpio_to_core (), + .gpio_from_core (), + .ss_ctrl_icn (), + .sysctrl_irq_i (), + .jtag_tck_internal (jtag_tck_i), + .jtag_tdi_internal (jtag_td_i), + .jtag_tms_internal (jtag_tms_i), + .jtag_trst_internal(jtag_trst_ni), + .jtag_tdo_internal (jtag_td_o), + .obi_err (), + .obi_gnt (), + .obi_gntpar (), + .obi_rdata (), + .obi_rid (), + .obi_rvalid (), + .obi_rvalidpar (), + .obi_addr (), + .obi_aid (), + .obi_be (), + .obi_req (), + .obi_reqpar (), + .obi_rready (), + .obi_rreadypar (), + .obi_wdata (), + .obi_we (), + .reset_internal (rst_ni), + .reset_icn (), + .reset_ss (), + .spim_miso_internal(), + .spim_csn_internal (), + .spim_mosi_internal(), + .spim_sck_internal (), + .irq_en_0 (), + .ss_ctrl_0 (), + .irq_en_1 (), + .ss_ctrl_1 (), + .irq_en_2 (), + .ss_ctrl_2 (), + .irq_en_3 (), + .ss_ctrl_3 (), + .uart_rx_internal (), + .uart_tx_internal (dut_uart_tx), + .cell_cfg (), + .pmod_sel (), + .irq_en_4 (), + .ss_ctrl_4 (), + .irq_upper_tieoff (15'h0) + ); + + didactic_student_domain #( + .ApbAddrWidth(32'd12), + .ApbDataWidth(32'd32) + ) i_student_domain ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .irq_o (), + .paddr_i (), + .penable_i(), + .psel_i (), + .pwdata_i (), + .prdata_o (), + .pready_o (), + .pslverr_o() + ); + + /// SIMULATION-ONLY UTILITIES /// + + `define STR(s) `"s`" + string RepoRoot = `STR(`ROOT); + + initial begin : sim_loader + @(posedge rst_ni); + $display("[DUT:SimLoader] Initializing program with $readmemh"); + $display("[DUT:SimLoader] APPLICABLE TO SIMULATED DESIGNS ONLY"); + $readmemh({RepoRoot,"/build/verilator_build/imem_stim.hex"}, SysCtrl_SS.i_imem.ram); + $readmemh({RepoRoot,"/build/verilator_build/dmem_stim.hex"}, SysCtrl_SS.i_dmem.ram); + end : sim_loader + +endmodule : didactic_vtop +