From d465ed8c05027b743cb40420f17c8b62cba1075a Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Tue, 8 Jul 2025 16:53:11 +0200 Subject: [PATCH 01/26] target/sim: Add libfesvr support in Questa & VCS --- cheshire.mk | 2 +- target/sim/vcs/start.cheshire_soc.sh | 2 +- target/sim/vsim/start.cheshire_soc.tcl | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cheshire.mk b/cheshire.mk index f838911b7..8e0028af8 100644 --- a/cheshire.mk +++ b/cheshire.mk @@ -149,7 +149,7 @@ CHS_BOOTROM_ALL += $(CHS_ROOT)/hw/bootrom/cheshire_bootrom.sv $(CHS_ROOT)/hw/boo $(CHS_ROOT)/target/sim/vsim/compile.cheshire_soc.tcl: $(CHS_ROOT)/Bender.yml $(BENDER) script vsim -t sim -t test $(CHS_BENDER_RTL_FLAGS) --vlog-arg="$(VLOG_ARGS)" > $@ - echo 'vlog "$(realpath $(CHS_ROOT))/target/sim/src/elfloader.cpp" -ccflags "-std=c++11" -cpppath "$(CXX_PATH)"' >> $@ + echo 'vlog "$(realpath $(CHS_ROOT))/target/sim/src/elfloader.cpp" -ccflags "-std=c++17 -I/scratch/ga25f6/riscv-isa-sim/install/include" -cpppath "$(CXX_PATH)"' >> $@ $(CHS_ROOT)/target/sim/vcs/compile.cheshire_soc.sh: $(CHS_ROOT)/Bender.yml $(BENDER) script vcs -t sim -t test $(CHS_BENDER_RTL_FLAGS) --vlog-arg="$(VLOGAN_ARGS)" --vlogan-bin="$(VLOGAN)" > $@ diff --git a/target/sim/vcs/start.cheshire_soc.sh b/target/sim/vcs/start.cheshire_soc.sh index 6352c5203..e8623fb3a 100755 --- a/target/sim/vcs/start.cheshire_soc.sh +++ b/target/sim/vcs/start.cheshire_soc.sh @@ -50,7 +50,7 @@ fi COLOR_NC='\e[0m' COLOR_BLUE='\e[0;34m' -${VCS_BIN} ${flags} ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log +${VCS_BIN} ${flags} -CFLAGS "-std=c++17 -I/scratch/ga25f6/riscv-isa-sim/install/include" -LIBS "-rdynamic -Wl,-rpath=/scratch/ga25f6/riscv-isa-sim/install/lib -L/scratch/ga25f6/riscv-isa-sim/install/lib -lfesvr" ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log # Start simulation printf ${COLOR_BLUE}"${VCS_VERSION} ${VERDI_VERSION} ./simv ${pargs}"${COLOR_NC}"\n" diff --git a/target/sim/vsim/start.cheshire_soc.tcl b/target/sim/vsim/start.cheshire_soc.tcl index e6a005d4a..c732b1969 100644 --- a/target/sim/vsim/start.cheshire_soc.tcl +++ b/target/sim/vsim/start.cheshire_soc.tcl @@ -48,6 +48,9 @@ if { [info exists USE_DRAMSYS] } { } } +# Need to link fesvr library +append flags "-gblso /scratch/ga25f6/riscv-isa-sim/install/lib/libfesvr.so" + # tclint-disable-next-line command-args eval "vsim -c ${TESTBENCH} -t 1ps -vopt -voptargs=\"${VOPTARGS}\"" ${pargs} ${flags} From 95c0d40d6e61ffae2c1d854aba9ed22c8150c529 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Tue, 8 Jul 2025 18:00:34 +0200 Subject: [PATCH 02/26] SimDTM : Add sv module and dpi to use the dtm from fesvr to boot pk and run an helloworld --- Bender.yml | 1 + hw/cheshire_soc.sv | 24 ++++--- sw/apps/helloworld.c | 6 ++ sw/apps/pk_dram | Bin 0 -> 80704 bytes target/sim/src/SimDTM.sv | 83 +++++++++++++++++++++++++ target/sim/src/elfloader.cpp | 62 ++++++++++++++++++ target/sim/src/fixture_cheshire_soc.sv | 16 ++++- target/sim/src/tb_cheshire_soc.sv | 6 +- target/sim/src/vip_cheshire_soc.sv | 48 +++++++++++++- 9 files changed, 233 insertions(+), 13 deletions(-) create mode 100644 sw/apps/helloworld.c create mode 100755 sw/apps/pk_dram create mode 100644 target/sim/src/SimDTM.sv diff --git a/Bender.yml b/Bender.yml index edddb742b..eaae185c8 100644 --- a/Bender.yml +++ b/Bender.yml @@ -47,6 +47,7 @@ sources: - target: any(simulation, test) files: + - target/sim/src/SimDTM.sv - target/sim/models/s25fs512s.v - target/sim/models/24FC1025.v - target/sim/src/vip_cheshire_soc.sv diff --git a/hw/cheshire_soc.sv b/hw/cheshire_soc.sv index b3b625443..a4a0aa754 100644 --- a/hw/cheshire_soc.sv +++ b/hw/cheshire_soc.sv @@ -105,7 +105,15 @@ module cheshire_soc import cheshire_pkg::*; #( output logic [UsbNumPorts-1:0] usb_dm_oe_o, input logic [UsbNumPorts-1:0] usb_dp_i, output logic [UsbNumPorts-1:0] usb_dp_o, - output logic [UsbNumPorts-1:0] usb_dp_oe_o + output logic [UsbNumPorts-1:0] usb_dp_oe_o, + // DMI interface + input dm::dmi_req_t dmi_req_i, + input logic dmi_req_valid_i, + output logic dmi_req_ready_o, + + output dm::dmi_resp_t dmi_resp_o, + input logic dmi_resp_ready_i, + output logic dmi_resp_valid_o ); `include "axi/typedef.svh" @@ -913,13 +921,13 @@ module cheshire_soc import cheshire_pkg::*; #( .master_r_rdata_i ( dbg_sba_rdata ), .master_r_err_i ( dbg_sba_err ), .master_r_other_err_i ( 1'b0 ), - .dmi_rst_ni ( dbg_dmi_rst_n ), - .dmi_req_valid_i ( dbg_dmi_req_valid ), - .dmi_req_ready_o ( dbg_dmi_req_ready ), - .dmi_req_i ( dbg_dmi_req ), - .dmi_resp_valid_o ( dbg_dmi_rsp_valid ), - .dmi_resp_ready_i ( dbg_dmi_rsp_ready ), - .dmi_resp_o ( dbg_dmi_rsp ) + .dmi_rst_ni ( rst_ni ), // not handled by SimDTM and his done like this in dmi_jtag + .dmi_req_valid_i ( dmi_req_valid_i ), + .dmi_req_ready_o ( dmi_req_ready_o ), + .dmi_req_i ( dmi_req_i ), + .dmi_resp_valid_o ( dmi_resp_valid_o ), + .dmi_resp_ready_i ( dmi_resp_ready_i ), + .dmi_resp_o ( dmi_resp_o ) ); axi_mst_req_t axi_dbg_req; diff --git a/sw/apps/helloworld.c b/sw/apps/helloworld.c new file mode 100644 index 000000000..36bc20ccd --- /dev/null +++ b/sw/apps/helloworld.c @@ -0,0 +1,6 @@ +#include + +int main() { + printf("hello world\n"); + return 0; +} diff --git a/sw/apps/pk_dram b/sw/apps/pk_dram new file mode 100755 index 0000000000000000000000000000000000000000..2de2254f4b8c5a7032e87ebf94288bfbc8b9182e GIT binary patch literal 80704 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 G@c#oNMVlu8 literal 0 HcmV?d00001 diff --git a/target/sim/src/SimDTM.sv b/target/sim/src/SimDTM.sv new file mode 100644 index 000000000..445599ab0 --- /dev/null +++ b/target/sim/src/SimDTM.sv @@ -0,0 +1,83 @@ +// See LICENSE.SiFive for license details. +//VCS coverage exclude_file + +import "DPI-C" function int debug_tick +( + output bit debug_req_valid, + input bit debug_req_ready, + output int debug_req_bits_addr, + output int debug_req_bits_op, + output int debug_req_bits_data, + + input bit debug_resp_valid, + output bit debug_resp_ready, + input int debug_resp_bits_resp, + input int debug_resp_bits_data +); + +module SimDTM( + input clk, + input reset, + + output debug_req_valid, + input debug_req_ready, + output [ 6:0] debug_req_bits_addr, + output [ 1:0] debug_req_bits_op, + output [31:0] debug_req_bits_data, + + input debug_resp_valid, + output debug_resp_ready, + input [ 1:0] debug_resp_bits_resp, + input [31:0] debug_resp_bits_data, + + output [31:0] exit +); + + //bit r_reset; + + wire #0.1 __debug_req_ready = debug_req_ready; + wire #0.1 __debug_resp_valid = debug_resp_valid; + wire [31:0] #0.1 __debug_resp_bits_resp = {30'b0, debug_resp_bits_resp}; + wire [31:0] #0.1 __debug_resp_bits_data = debug_resp_bits_data; + + bit __debug_req_valid; + int __debug_req_bits_addr; + int __debug_req_bits_op; + int __debug_req_bits_data; + bit __debug_resp_ready; + int __exit; + + assign #0.1 debug_req_valid = __debug_req_valid; + assign #0.1 debug_req_bits_addr = __debug_req_bits_addr[6:0]; + assign #0.1 debug_req_bits_op = __debug_req_bits_op[1:0]; + assign #0.1 debug_req_bits_data = __debug_req_bits_data[31:0]; + assign #0.1 debug_resp_ready = __debug_resp_ready; + assign #0.1 exit = __exit; + + always @(posedge clk) + begin + /* reset condition was not working... + r_reset <= reset; + if (reset || r_reset) */ + if(!reset) + begin + __debug_req_valid = 0; + __debug_resp_ready = 0; + __exit = 0; + end + else + begin + __exit = debug_tick( + __debug_req_valid, + __debug_req_ready, + __debug_req_bits_addr, + __debug_req_bits_op, + __debug_req_bits_data, + __debug_resp_valid, + __debug_resp_ready, + __debug_resp_bits_resp, + __debug_resp_bits_data + ); + end + end +endmodule diff --git a/target/sim/src/elfloader.cpp b/target/sim/src/elfloader.cpp index b02860c91..f03538e66 100644 --- a/target/sim/src/elfloader.cpp +++ b/target/sim/src/elfloader.cpp @@ -9,6 +9,7 @@ // Christopher Reinwardt #include +#include #include #include #if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__)) @@ -30,6 +31,7 @@ #include #include #include +#include #define IS_ELF(hdr) \ ((hdr).e_ident[0] == 0x7f && (hdr).e_ident[1] == 'E' && \ @@ -160,6 +162,16 @@ extern "C" { char get_section(long long *address_ret, long long *len_ret); char read_section(long long address, const svOpenArrayHandle buffer, long long len); char read_elf(const char *filename); + int debug_tick( + unsigned char* debug_req_valid, + unsigned char debug_req_ready, + int* debug_req_bits_addr, + int* debug_req_bits_op, + int* debug_req_bits_data, + unsigned char debug_resp_valid, + unsigned char* debug_resp_ready, + int debug_resp_bits_resp, + int debug_resp_bits_data); } static void write (uint64_t address, uint64_t len, uint8_t *buf) @@ -398,3 +410,53 @@ extern "C" char read_elf(const char *filename) { return 0; } #endif + +dtm_t* dtm; +/*------------------------ +From SimDTM.cc +------------------------*/ +extern "C" int debug_tick +( + unsigned char* debug_req_valid, + unsigned char debug_req_ready, + int* debug_req_bits_addr, + int* debug_req_bits_op, + int* debug_req_bits_data, + unsigned char debug_resp_valid, + unsigned char* debug_resp_ready, + int debug_resp_bits_resp, + int debug_resp_bits_data +) +{ + if (!dtm) { + //the list of argv are the program that will be runned after pk is booted. + // Need to find a way to make it easier to change programs, maybe like it was done... + int htif_argc = 3; + char* htif_argv[htif_argc]; + htif_argv[0] = (char*)"htif"; + htif_argv[1] = (char*)"/scratch/ga25f6/cheshire/sw/apps/pk_dram"; + htif_argv[2] = (char*)"/scratch/ga25f6/cheshire/sw/apps/helloworld.o"; + + dtm = new dtm_t(htif_argc, htif_argv); + } + + + dtm_t::resp resp_bits; + resp_bits.resp = debug_resp_bits_resp; + resp_bits.data = debug_resp_bits_data; + + dtm->tick + ( + debug_req_ready, + debug_resp_valid, + resp_bits + ); + + *debug_resp_ready = dtm->resp_ready(); + *debug_req_valid = dtm->req_valid(); + *debug_req_bits_addr = dtm->req_bits().addr; + *debug_req_bits_op = dtm->req_bits().op; + *debug_req_bits_data = dtm->req_bits().data; + + return dtm->done() ? (dtm->exit_code() << 1 | 1) : 0; +} diff --git a/target/sim/src/fixture_cheshire_soc.sv b/target/sim/src/fixture_cheshire_soc.sv index 056f0b338..1b9745f1c 100644 --- a/target/sim/src/fixture_cheshire_soc.sv +++ b/target/sim/src/fixture_cheshire_soc.sv @@ -63,6 +63,14 @@ module fixture_cheshire_soc #( logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_i; logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_o; + //DMI + dm::dmi_req_t dmi_req; + logic dmi_req_valid; + logic dmi_req_ready; + dm::dmi_resp_t dmi_resp; + logic dmi_resp_ready; + logic dmi_resp_valid; + cheshire_soc #( .Cfg ( DutCfg ), .ExtHartinfo ( '0 ), @@ -142,7 +150,13 @@ module fixture_cheshire_soc #( .usb_dm_oe_o ( ), .usb_dp_i ( '0 ), .usb_dp_o ( ), - .usb_dp_oe_o ( ) + .usb_dp_oe_o ( ), + .dmi_req_valid_i ( dmi_req_valid ), + .dmi_req_ready_o ( dmi_req_ready ), + .dmi_req_i ( dmi_req ), + .dmi_resp_valid_o ( dmi_resp_valid ), + .dmi_resp_ready_i ( dmi_resp_ready ), + .dmi_resp_o ( dmi_resp ) ); //////////////////////// diff --git a/target/sim/src/tb_cheshire_soc.sv b/target/sim/src/tb_cheshire_soc.sv index 57a15e8b6..548c08250 100644 --- a/target/sim/src/tb_cheshire_soc.sv +++ b/target/sim/src/tb_cheshire_soc.sv @@ -46,8 +46,8 @@ module tb_cheshire_soc #( fix.vip.jtag_elf_run(preload_elf); fix.vip.jtag_wait_for_eoc(exit_code); end 1: begin // Serial Link - fix.vip.slink_elf_run(preload_elf); - fix.vip.slink_wait_for_eoc(exit_code); + /*fix.vip.slink_elf_run(preload_elf); + fix.vip.slink_wait_for_eoc(exit_code);*/ end 2: begin // UART fix.vip.uart_debug_elf_run_and_wait(preload_elf, exit_code); end default: begin @@ -65,7 +65,7 @@ module tb_cheshire_soc #( // Wait for the UART to finish reading the current byte wait (fix.vip.uart_reading_byte == 0); - $finish; + //$finish; end endmodule diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index e32e5410f..6dccf4631 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -72,7 +72,14 @@ module vip_cheshire_soc import cheshire_pkg::*; #( output logic [SlinkNumChan-1:0] slink_rcv_clk_i, input logic [SlinkNumChan-1:0] slink_rcv_clk_o, output logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_i, - input logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_o + input logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_o, + // DMI + output dm::dmi_req_t dmi_req, + output logic dmi_req_valid, + input logic dmi_req_ready, + input dm::dmi_resp_t dmi_resp, + output logic dmi_resp_ready, + input logic dmi_resp_valid ); `include "cheshire/typedef.svh" @@ -88,6 +95,19 @@ module vip_cheshire_soc import cheshire_pkg::*; #( import "DPI-C" function byte get_entry(output longint entry); import "DPI-C" function byte get_section(output longint address, output longint len); import "DPI-C" context function byte read_section(input longint address, inout byte buffer[], input longint len); + import "DPI-C" function int debug_tick +( + output bit debug_req_valid, + input bit debug_req_ready, + output int debug_req_bits_addr, + output int debug_req_bits_op, + output int debug_req_bits_data, + + input bit debug_resp_valid, + output bit debug_resp_ready, + input int debug_resp_bits_resp, + input int debug_resp_bits_data +); //////////// // DRAM // @@ -954,6 +974,32 @@ module vip_cheshire_soc import cheshire_pkg::*; #( if (exit_code) $error("[SLINK] FAILED: return code %0d", exit_code); else $display("[SLINK] SUCCESS"); endtask + task automatic wait_boot_pk(); + #(ClkPeriodSys * 200000 * 2); // wait 2s, pk should be booted (take around 1.5s). + endtask + + ////////////// + // SimDTM // + ////////////// + + logic [31:0] sim_exit; // TODO: wire this up in the testbench + logic [1:0] dmi_req_bits_op; + assign dmi_req.op = dm::dtm_op_e'(dmi_req_bits_op); // need to check if it's this variable, + + SimDTM i_SimDTM ( + .clk ( clk ), + .reset ( rst_n ), + .debug_req_valid ( dmi_req_valid ), + .debug_req_ready ( dmi_req_ready ), + .debug_req_bits_addr ( dmi_req.addr ), + .debug_req_bits_op ( dmi_req_bits_op ), + .debug_req_bits_data ( dmi_req.data ), + .debug_resp_valid ( dmi_resp_valid ), + .debug_resp_ready ( dmi_resp_ready ), + .debug_resp_bits_resp ( dmi_resp.resp ), + .debug_resp_bits_data ( dmi_resp.data ), + .exit ( sim_exit ) + ); endmodule From dcba07956d879da5b41dbdb174a09fbdb18ad21f Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Wed, 9 Jul 2025 15:26:35 +0200 Subject: [PATCH 03/26] FESVR : Add a variable to use fesvr and new compilation script for it --- cheshire.mk | 10 +++++++++ hw/cheshire_soc.sv | 30 ++++++++++++++++++-------- target/sim/src/fixture_cheshire_soc.sv | 18 ++++++++++------ target/sim/src/tb_cheshire_soc.sv | 12 ++++++++--- target/sim/src/vip_cheshire_soc.sv | 18 ++++++++++------ 5 files changed, 63 insertions(+), 25 deletions(-) diff --git a/cheshire.mk b/cheshire.mk index 8e0028af8..055d292aa 100644 --- a/cheshire.mk +++ b/cheshire.mk @@ -151,10 +151,18 @@ $(CHS_ROOT)/target/sim/vsim/compile.cheshire_soc.tcl: $(CHS_ROOT)/Bender.yml $(BENDER) script vsim -t sim -t test $(CHS_BENDER_RTL_FLAGS) --vlog-arg="$(VLOG_ARGS)" > $@ echo 'vlog "$(realpath $(CHS_ROOT))/target/sim/src/elfloader.cpp" -ccflags "-std=c++17 -I/scratch/ga25f6/riscv-isa-sim/install/include" -cpppath "$(CXX_PATH)"' >> $@ +$(CHS_ROOT)/target/sim/vsim/compile.cheshire_soc_fesvr.tcl: $(CHS_ROOT)/Bender.yml + $(BENDER) script vsim -t sim -t test $(CHS_BENDER_RTL_FLAGS) --vlog-arg="$(VLOG_ARGS) +define+FESVR_DTM" > $@ + echo 'vlog "$(realpath $(CHS_ROOT))/target/sim/src/elfloader.cpp" -ccflags "-std=c++17 -I/scratch/ga25f6/riscv-isa-sim/install/include" -cpppath "$(CXX_PATH)"' >> $@ + $(CHS_ROOT)/target/sim/vcs/compile.cheshire_soc.sh: $(CHS_ROOT)/Bender.yml $(BENDER) script vcs -t sim -t test $(CHS_BENDER_RTL_FLAGS) --vlog-arg="$(VLOGAN_ARGS)" --vlogan-bin="$(VLOGAN)" > $@ chmod +x $@ +$(CHS_ROOT)/target/sim/vcs/compile.cheshire_soc_fesvr.sh: $(CHS_ROOT)/Bender.yml + $(BENDER) script vcs -t sim -t test $(CHS_BENDER_RTL_FLAGS) --vlog-arg="$(VLOGAN_ARGS) +define+FESVR_DTM" --vlogan-bin="$(VLOGAN)" > $@ + chmod +x $@ + .PRECIOUS: $(CHS_ROOT)/target/sim/models $(CHS_ROOT)/target/sim/models: mkdir -p $@ @@ -173,7 +181,9 @@ $(CHS_ROOT)/target/sim/models/24FC1025.v: $(CHS_ROOT)/Bender.yml | $(CHS_ROOT)/t CHS_SIM_ALL += $(CHS_ROOT)/target/sim/models/s25fs512s.v CHS_SIM_ALL += $(CHS_ROOT)/target/sim/models/24FC1025.v CHS_SIM_ALL += $(CHS_ROOT)/target/sim/vsim/compile.cheshire_soc.tcl +CHS_SIM_ALL += $(CHS_ROOT)/target/sim/vsim/compile.cheshire_soc_fesvr.tcl CHS_SIM_ALL += $(CHS_ROOT)/target/sim/vcs/compile.cheshire_soc.sh +CHS_SIM_ALL += $(CHS_ROOT)/target/sim/vcs/compile.cheshire_soc_fesvr.sh ########### # DRAMSys # diff --git a/hw/cheshire_soc.sv b/hw/cheshire_soc.sv index a4a0aa754..af84c3ae2 100644 --- a/hw/cheshire_soc.sv +++ b/hw/cheshire_soc.sv @@ -97,6 +97,16 @@ module cheshire_soc import cheshire_pkg::*; #( output logic [Cfg.VgaRedWidth -1:0] vga_red_o, output logic [Cfg.VgaGreenWidth-1:0] vga_green_o, output logic [Cfg.VgaBlueWidth -1:0] vga_blue_o, +`ifdef FESVR_DTM + // DMI interface + input dm::dmi_req_t dmi_req_i, + input logic dmi_req_valid_i, + output logic dmi_req_ready_o, + + output dm::dmi_resp_t dmi_resp_o, + input logic dmi_resp_ready_i, + output logic dmi_resp_valid_o, +`endif // USB interface input logic usb_clk_i, input logic usb_rst_ni, @@ -105,15 +115,7 @@ module cheshire_soc import cheshire_pkg::*; #( output logic [UsbNumPorts-1:0] usb_dm_oe_o, input logic [UsbNumPorts-1:0] usb_dp_i, output logic [UsbNumPorts-1:0] usb_dp_o, - output logic [UsbNumPorts-1:0] usb_dp_oe_o, - // DMI interface - input dm::dmi_req_t dmi_req_i, - input logic dmi_req_valid_i, - output logic dmi_req_ready_o, - - output dm::dmi_resp_t dmi_resp_o, - input logic dmi_resp_ready_i, - output logic dmi_resp_valid_o + output logic [UsbNumPorts-1:0] usb_dp_oe_o ); `include "axi/typedef.svh" @@ -921,6 +923,7 @@ module cheshire_soc import cheshire_pkg::*; #( .master_r_rdata_i ( dbg_sba_rdata ), .master_r_err_i ( dbg_sba_err ), .master_r_other_err_i ( 1'b0 ), + `ifdef FESVR_DTM .dmi_rst_ni ( rst_ni ), // not handled by SimDTM and his done like this in dmi_jtag .dmi_req_valid_i ( dmi_req_valid_i ), .dmi_req_ready_o ( dmi_req_ready_o ), @@ -928,6 +931,15 @@ module cheshire_soc import cheshire_pkg::*; #( .dmi_resp_valid_o ( dmi_resp_valid_o ), .dmi_resp_ready_i ( dmi_resp_ready_i ), .dmi_resp_o ( dmi_resp_o ) + `else + .dmi_rst_ni ( dbg_dmi_rst_n ), + .dmi_req_valid_i ( dbg_dmi_req_valid ), + .dmi_req_ready_o ( dbg_dmi_req_ready ), + .dmi_req_i ( dbg_dmi_req ), + .dmi_resp_valid_o ( dbg_dmi_rsp_valid ), + .dmi_resp_ready_i ( dbg_dmi_rsp_ready ), + .dmi_resp_o ( dbg_dmi_rsp ) + `endif ); axi_mst_req_t axi_dbg_req; diff --git a/target/sim/src/fixture_cheshire_soc.sv b/target/sim/src/fixture_cheshire_soc.sv index 1b9745f1c..4dcfd058b 100644 --- a/target/sim/src/fixture_cheshire_soc.sv +++ b/target/sim/src/fixture_cheshire_soc.sv @@ -63,6 +63,7 @@ module fixture_cheshire_soc #( logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_i; logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_o; +`ifdef FESVR_DTM //DMI dm::dmi_req_t dmi_req; logic dmi_req_valid; @@ -70,6 +71,7 @@ module fixture_cheshire_soc #( dm::dmi_resp_t dmi_resp; logic dmi_resp_ready; logic dmi_resp_valid; +`endif cheshire_soc #( .Cfg ( DutCfg ), @@ -143,6 +145,14 @@ module fixture_cheshire_soc #( .vga_red_o ( ), .vga_green_o ( ), .vga_blue_o ( ), + `ifdef FESVR_DTM + .dmi_req_valid_i ( dmi_req_valid ), + .dmi_req_ready_o ( dmi_req_ready ), + .dmi_req_i ( dmi_req ), + .dmi_resp_valid_o ( dmi_resp_valid ), + .dmi_resp_ready_i ( dmi_resp_ready ), + .dmi_resp_o ( dmi_resp ), + `endif .usb_clk_i ( 1'b0 ), .usb_rst_ni ( 1'b1 ), .usb_dm_i ( '0 ), @@ -150,13 +160,7 @@ module fixture_cheshire_soc #( .usb_dm_oe_o ( ), .usb_dp_i ( '0 ), .usb_dp_o ( ), - .usb_dp_oe_o ( ), - .dmi_req_valid_i ( dmi_req_valid ), - .dmi_req_ready_o ( dmi_req_ready ), - .dmi_req_i ( dmi_req ), - .dmi_resp_valid_o ( dmi_resp_valid ), - .dmi_resp_ready_i ( dmi_resp_ready ), - .dmi_resp_o ( dmi_resp ) + .usb_dp_oe_o ( ) ); //////////////////////// diff --git a/target/sim/src/tb_cheshire_soc.sv b/target/sim/src/tb_cheshire_soc.sv index 548c08250..9a9c61cb7 100644 --- a/target/sim/src/tb_cheshire_soc.sv +++ b/target/sim/src/tb_cheshire_soc.sv @@ -37,6 +37,9 @@ module tb_cheshire_soc #( // Wait for reset fix.vip.wait_for_reset(); +// if using fesvr, the preloading is handled by fesvr dtn +`ifndef FESVR_DTM + // Preload in idle mode or wait for completion in autonomous boot if (boot_mode == 0) begin // Idle boot: preload with the specified mode @@ -46,8 +49,9 @@ module tb_cheshire_soc #( fix.vip.jtag_elf_run(preload_elf); fix.vip.jtag_wait_for_eoc(exit_code); end 1: begin // Serial Link - /*fix.vip.slink_elf_run(preload_elf); - fix.vip.slink_wait_for_eoc(exit_code);*/ + fix.vip.slink_elf_run(preload_elf); + fix.vip.slink_wait_for_eoc(exit_code); + fix.vip.wait_boot_pk(); end 2: begin // UART fix.vip.uart_debug_elf_run_and_wait(preload_elf, exit_code); end default: begin @@ -65,7 +69,9 @@ module tb_cheshire_soc #( // Wait for the UART to finish reading the current byte wait (fix.vip.uart_reading_byte == 0); - //$finish; + $finish; +`endif + end endmodule diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index 6dccf4631..56343acec 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -68,18 +68,20 @@ module vip_cheshire_soc import cheshire_pkg::*; #( inout wire spih_sck, inout wire [SpihNumCs-1:0] spih_csb, inout wire [ 3:0] spih_sd, - // Serial link interface - output logic [SlinkNumChan-1:0] slink_rcv_clk_i, - input logic [SlinkNumChan-1:0] slink_rcv_clk_o, - output logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_i, - input logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_o, +`ifdef FESVR_DTM // DMI output dm::dmi_req_t dmi_req, output logic dmi_req_valid, input logic dmi_req_ready, input dm::dmi_resp_t dmi_resp, output logic dmi_resp_ready, - input logic dmi_resp_valid + input logic dmi_resp_valid, +`endif + // Serial link interface + output logic [SlinkNumChan-1:0] slink_rcv_clk_i, + input logic [SlinkNumChan-1:0] slink_rcv_clk_o, + output logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_i, + input logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_o ); `include "cheshire/typedef.svh" @@ -95,6 +97,7 @@ module vip_cheshire_soc import cheshire_pkg::*; #( import "DPI-C" function byte get_entry(output longint entry); import "DPI-C" function byte get_section(output longint address, output longint len); import "DPI-C" context function byte read_section(input longint address, inout byte buffer[], input longint len); +`ifdef FESVR_DTM import "DPI-C" function int debug_tick ( output bit debug_req_valid, @@ -108,6 +111,7 @@ module vip_cheshire_soc import cheshire_pkg::*; #( input int debug_resp_bits_resp, input int debug_resp_bits_data ); +`endif //////////// // DRAM // @@ -978,6 +982,7 @@ module vip_cheshire_soc import cheshire_pkg::*; #( #(ClkPeriodSys * 200000 * 2); // wait 2s, pk should be booted (take around 1.5s). endtask +`ifdef FESVR_DTM ////////////// // SimDTM // ////////////// @@ -1000,6 +1005,7 @@ module vip_cheshire_soc import cheshire_pkg::*; #( .debug_resp_bits_data ( dmi_resp.data ), .exit ( sim_exit ) ); +`endif endmodule From 292c2e105696222f2f7d7735608b36229e55c93c Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Wed, 9 Jul 2025 16:17:22 +0200 Subject: [PATCH 04/26] wait_boot_pk: Add comment for it use case --- target/sim/src/tb_cheshire_soc.sv | 9 +++------ target/sim/src/vip_cheshire_soc.sv | 5 ++++- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/target/sim/src/tb_cheshire_soc.sv b/target/sim/src/tb_cheshire_soc.sv index 9a9c61cb7..732a36670 100644 --- a/target/sim/src/tb_cheshire_soc.sv +++ b/target/sim/src/tb_cheshire_soc.sv @@ -37,9 +37,8 @@ module tb_cheshire_soc #( // Wait for reset fix.vip.wait_for_reset(); -// if using fesvr, the preloading is handled by fesvr dtn +// if using fesvr, the preloading is handled by fesvr dtm `ifndef FESVR_DTM - // Preload in idle mode or wait for completion in autonomous boot if (boot_mode == 0) begin // Idle boot: preload with the specified mode @@ -51,7 +50,7 @@ module tb_cheshire_soc #( end 1: begin // Serial Link fix.vip.slink_elf_run(preload_elf); fix.vip.slink_wait_for_eoc(exit_code); - fix.vip.wait_boot_pk(); + //fix.vip.wait_boot_pk(); end 2: begin // UART fix.vip.uart_debug_elf_run_and_wait(preload_elf, exit_code); end default: begin @@ -70,8 +69,6 @@ module tb_cheshire_soc #( wait (fix.vip.uart_reading_byte == 0); $finish; -`endif - end - +`endif endmodule diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index 56343acec..e148607fa 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -978,7 +978,10 @@ module vip_cheshire_soc import cheshire_pkg::*; #( if (exit_code) $error("[SLINK] FAILED: return code %0d", exit_code); else $display("[SLINK] SUCCESS"); endtask - task automatic wait_boot_pk(); + + // when running pk, there is not eoc, so it will never ends, + //that why you should us this function instead of slink_wait_for_eoc + task automatic wait_boot_pk(); #(ClkPeriodSys * 200000 * 2); // wait 2s, pk should be booted (take around 1.5s). endtask From 006161aaa78d37c264293e39260fee09930d7782 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Fri, 11 Jul 2025 13:09:24 +0200 Subject: [PATCH 05/26] SimDTM : Add a logic to start it --- target/sim/src/tb_cheshire_soc.sv | 38 +++++++++++++++++++++++++++--- target/sim/src/vip_cheshire_soc.sv | 25 ++++++++++---------- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/target/sim/src/tb_cheshire_soc.sv b/target/sim/src/tb_cheshire_soc.sv index 732a36670..b5d536a43 100644 --- a/target/sim/src/tb_cheshire_soc.sv +++ b/target/sim/src/tb_cheshire_soc.sv @@ -29,6 +29,11 @@ module tb_cheshire_soc #( if (!$value$plusargs("BINARY=%s", preload_elf)) preload_elf = ""; if (!$value$plusargs("IMAGE=%s", boot_hex)) boot_hex = ""; +`ifdef FESVR_DTM + // locking SimDTM + assign fix.vip.start_SimDTM = 1'b0; +`endif + // Set boot mode and preload boot image if there is one fix.vip.set_boot_mode(boot_mode); fix.vip.i2c_eeprom_preload(boot_hex); @@ -37,9 +42,36 @@ module tb_cheshire_soc #( // Wait for reset fix.vip.wait_for_reset(); -// if using fesvr, the preloading is handled by fesvr dtm -`ifndef FESVR_DTM - // Preload in idle mode or wait for completion in autonomous boot +`ifdef FESVR_DTM + if (boot_mode == 0) begin + // Idle boot: preload with the specified mode + case (preload_mode) + // JTAG : jtag_dmi not connected when using fesvr + 1: begin // Serial Link + fix.vip.wait_boot_pk(); // tmp : to check that it works + assign fix.vip.start_SimDTM = 1'b1; + end 2: begin // UART + fix.vip.wait_boot_pk(); // tmp : to check that it works + assign fix.vip.start_SimDTM = 1'b1; + end default: begin + $fatal(1, "Unsupported preload mode %d (reserved)!", boot_mode); + end + endcase + end else if (boot_mode == 1) begin + $fatal(1, "Unsupported boot mode %d (SD Card)!", boot_mode); + end else begin + // Autonomous boot: Only poll return code + fix.vip.jtag_init(); + fix.vip.jtag_wait_for_eoc(exit_code); + end + + // Wait for the UART to finish reading the current byte + wait (fix.vip.uart_reading_byte == 0); + + // finish will end the simulation but it's still running.. + //$finish; + end +`else if (boot_mode == 0) begin // Idle boot: preload with the specified mode case (preload_mode) diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index e148607fa..229fa36ff 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -990,23 +990,24 @@ module vip_cheshire_soc import cheshire_pkg::*; #( // SimDTM // ////////////// + logic start_SimDTM; // wired up in the testbench logic [31:0] sim_exit; // TODO: wire this up in the testbench logic [1:0] dmi_req_bits_op; assign dmi_req.op = dm::dtm_op_e'(dmi_req_bits_op); // need to check if it's this variable, SimDTM i_SimDTM ( - .clk ( clk ), - .reset ( rst_n ), - .debug_req_valid ( dmi_req_valid ), - .debug_req_ready ( dmi_req_ready ), - .debug_req_bits_addr ( dmi_req.addr ), - .debug_req_bits_op ( dmi_req_bits_op ), - .debug_req_bits_data ( dmi_req.data ), - .debug_resp_valid ( dmi_resp_valid ), - .debug_resp_ready ( dmi_resp_ready ), - .debug_resp_bits_resp ( dmi_resp.resp ), - .debug_resp_bits_data ( dmi_resp.data ), - .exit ( sim_exit ) + .clk ( clk ), + .reset ( rst_n & start_SimDTM ), + .debug_req_valid ( dmi_req_valid ), + .debug_req_ready ( dmi_req_ready ), + .debug_req_bits_addr ( dmi_req.addr ), + .debug_req_bits_op ( dmi_req_bits_op ), + .debug_req_bits_data ( dmi_req.data ), + .debug_resp_valid ( dmi_resp_valid ), + .debug_resp_ready ( dmi_resp_ready ), + .debug_resp_bits_resp ( dmi_resp.resp ), + .debug_resp_bits_data ( dmi_resp.data ), + .exit ( sim_exit ) ); `endif From 2fddf4b3c13c518920b664de07125b9addc85a6a Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Fri, 11 Jul 2025 15:18:35 +0200 Subject: [PATCH 06/26] target/sim: Preload of pk done with slink then fesvr dtm take the lead --- target/sim/src/elfloader.cpp | 10 ++++++++-- target/sim/src/tb_cheshire_soc.sv | 7 ++----- target/sim/src/vip_cheshire_soc.sv | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/target/sim/src/elfloader.cpp b/target/sim/src/elfloader.cpp index f03538e66..aa31a4693 100644 --- a/target/sim/src/elfloader.cpp +++ b/target/sim/src/elfloader.cpp @@ -411,7 +411,13 @@ extern "C" char read_elf(const char *filename) { } #endif -dtm_t* dtm; +class preload_aware_dtm_t : public dtm_t { + public: + preload_aware_dtm_t(int argc, char **argv) : dtm_t(argc, argv) {} + bool is_address_preloaded(addr_t taddr, size_t len) override { return true; } +}; + +preload_aware_dtm_t* dtm; /*------------------------ From SimDTM.cc ------------------------*/ @@ -437,7 +443,7 @@ extern "C" int debug_tick htif_argv[1] = (char*)"/scratch/ga25f6/cheshire/sw/apps/pk_dram"; htif_argv[2] = (char*)"/scratch/ga25f6/cheshire/sw/apps/helloworld.o"; - dtm = new dtm_t(htif_argc, htif_argv); + dtm = new preload_aware_dtm_t(htif_argc, htif_argv); } diff --git a/target/sim/src/tb_cheshire_soc.sv b/target/sim/src/tb_cheshire_soc.sv index b5d536a43..f26abd272 100644 --- a/target/sim/src/tb_cheshire_soc.sv +++ b/target/sim/src/tb_cheshire_soc.sv @@ -46,12 +46,9 @@ module tb_cheshire_soc #( if (boot_mode == 0) begin // Idle boot: preload with the specified mode case (preload_mode) - // JTAG : jtag_dmi not connected when using fesvr + // Preload done only using slink in this case cause it's the fastest way available 1: begin // Serial Link - fix.vip.wait_boot_pk(); // tmp : to check that it works - assign fix.vip.start_SimDTM = 1'b1; - end 2: begin // UART - fix.vip.wait_boot_pk(); // tmp : to check that it works + fix.vip.slink_elf_prerun(preload_elf); assign fix.vip.start_SimDTM = 1'b1; end default: begin $fatal(1, "Unsupported preload mode %d (reserved)!", boot_mode); diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index 229fa36ff..6a0246a77 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -971,6 +971,24 @@ module vip_cheshire_soc import cheshire_pkg::*; #( $display("[SLINK] Wrote launch signal and entry point 0x%h", entry); endtask + // Preload a binary without running it -> prerun ? + task automatic slink_elf_prerun(input string binary); + doub_bt entry; + // Wait for bootrom to ungate Serial Link + if (DutCfg.LlcNotBypass) begin + word_bt regval; + $display("[SLINK] Wait for LLC configuration"); + slink_poll_bit0(AmLlc + axi_llc_reg_pkg::AXI_LLC_CFG_SPM_LOW_OFFSET, regval, 20); + end + // Preload + slink_elf_preload(binary, entry); + // Write entry point + slink_write_32(AmRegs + cheshire_reg_pkg::CHESHIRE_SCRATCH_1_OFFSET, entry[63:32]); + slink_write_32(AmRegs + cheshire_reg_pkg::CHESHIRE_SCRATCH_0_OFFSET, entry[32:0]); + // Not resuming hart 0, handled by fesvr's dtm + $display("[SLINK] Wrote entry point 0x%h", entry); + endtask + // Wait for termination signal and get return code task automatic slink_wait_for_eoc(output word_bt exit_code); slink_poll_bit0(AmRegs + cheshire_reg_pkg::CHESHIRE_SCRATCH_2_OFFSET, exit_code, 800); From 7936028d0878521be7d3fcc19abea2c0ae7667d1 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Wed, 16 Jul 2025 16:24:06 +0200 Subject: [PATCH 07/26] target/sim: Handling end of simulation with fesvr --- target/sim/src/tb_cheshire_soc.sv | 22 ++++------------------ target/sim/src/vip_cheshire_soc.sv | 8 ++++++++ 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/target/sim/src/tb_cheshire_soc.sv b/target/sim/src/tb_cheshire_soc.sv index f26abd272..b212e8e90 100644 --- a/target/sim/src/tb_cheshire_soc.sv +++ b/target/sim/src/tb_cheshire_soc.sv @@ -42,34 +42,20 @@ module tb_cheshire_soc #( // Wait for reset fix.vip.wait_for_reset(); -`ifdef FESVR_DTM if (boot_mode == 0) begin - // Idle boot: preload with the specified mode +`ifdef FESVR_DTM + // Idle boot: preload with the specified mode, only slink when fesvr case (preload_mode) // Preload done only using slink in this case cause it's the fastest way available 1: begin // Serial Link fix.vip.slink_elf_prerun(preload_elf); assign fix.vip.start_SimDTM = 1'b1; + fix.vip.fesvr_wait_for_exit(exit_code); end default: begin $fatal(1, "Unsupported preload mode %d (reserved)!", boot_mode); end endcase - end else if (boot_mode == 1) begin - $fatal(1, "Unsupported boot mode %d (SD Card)!", boot_mode); - end else begin - // Autonomous boot: Only poll return code - fix.vip.jtag_init(); - fix.vip.jtag_wait_for_eoc(exit_code); - end - - // Wait for the UART to finish reading the current byte - wait (fix.vip.uart_reading_byte == 0); - - // finish will end the simulation but it's still running.. - //$finish; - end `else - if (boot_mode == 0) begin // Idle boot: preload with the specified mode case (preload_mode) 0: begin // JTAG @@ -86,6 +72,7 @@ module tb_cheshire_soc #( $fatal(1, "Unsupported preload mode %d (reserved)!", boot_mode); end endcase +`endif end else if (boot_mode == 1) begin $fatal(1, "Unsupported boot mode %d (SD Card)!", boot_mode); end else begin @@ -99,5 +86,4 @@ module tb_cheshire_soc #( $finish; end -`endif endmodule diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index 6a0246a77..1237c5528 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -1027,6 +1027,14 @@ module vip_cheshire_soc import cheshire_pkg::*; #( .debug_resp_bits_data ( dmi_resp.data ), .exit ( sim_exit ) ); + + task automatic fesvr_wait_for_exit(output word_bt exit_code); + while (~sim_exit[0]) begin + #(ClkPeriodSys * 100); + end + if (sim_exit == 1) $error("[FESVR] SUCCESS"); + else $display("[FESVR] FAILED: return code %0d", sim_exit); + endtask `endif endmodule From 8f2b8610ae59b82edc8f0005386af0983f330eeb Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Thu, 24 Jul 2025 17:01:50 +0200 Subject: [PATCH 08/26] target/sim : using chandle to use a dtm class --- target/sim/src/SimDTM.sv | 83 ------------------------ target/sim/src/elfloader.cpp | 48 ++++++++------ target/sim/src/tb_cheshire_soc.sv | 5 +- target/sim/src/vip_cheshire_soc.sv | 101 +++++++++++++++++++++-------- 4 files changed, 105 insertions(+), 132 deletions(-) delete mode 100644 target/sim/src/SimDTM.sv diff --git a/target/sim/src/SimDTM.sv b/target/sim/src/SimDTM.sv deleted file mode 100644 index 445599ab0..000000000 --- a/target/sim/src/SimDTM.sv +++ /dev/null @@ -1,83 +0,0 @@ -// See LICENSE.SiFive for license details. -//VCS coverage exclude_file - -import "DPI-C" function int debug_tick -( - output bit debug_req_valid, - input bit debug_req_ready, - output int debug_req_bits_addr, - output int debug_req_bits_op, - output int debug_req_bits_data, - - input bit debug_resp_valid, - output bit debug_resp_ready, - input int debug_resp_bits_resp, - input int debug_resp_bits_data -); - -module SimDTM( - input clk, - input reset, - - output debug_req_valid, - input debug_req_ready, - output [ 6:0] debug_req_bits_addr, - output [ 1:0] debug_req_bits_op, - output [31:0] debug_req_bits_data, - - input debug_resp_valid, - output debug_resp_ready, - input [ 1:0] debug_resp_bits_resp, - input [31:0] debug_resp_bits_data, - - output [31:0] exit -); - - //bit r_reset; - - wire #0.1 __debug_req_ready = debug_req_ready; - wire #0.1 __debug_resp_valid = debug_resp_valid; - wire [31:0] #0.1 __debug_resp_bits_resp = {30'b0, debug_resp_bits_resp}; - wire [31:0] #0.1 __debug_resp_bits_data = debug_resp_bits_data; - - bit __debug_req_valid; - int __debug_req_bits_addr; - int __debug_req_bits_op; - int __debug_req_bits_data; - bit __debug_resp_ready; - int __exit; - - assign #0.1 debug_req_valid = __debug_req_valid; - assign #0.1 debug_req_bits_addr = __debug_req_bits_addr[6:0]; - assign #0.1 debug_req_bits_op = __debug_req_bits_op[1:0]; - assign #0.1 debug_req_bits_data = __debug_req_bits_data[31:0]; - assign #0.1 debug_resp_ready = __debug_resp_ready; - assign #0.1 exit = __exit; - - always @(posedge clk) - begin - /* reset condition was not working... - r_reset <= reset; - if (reset || r_reset) */ - if(!reset) - begin - __debug_req_valid = 0; - __debug_resp_ready = 0; - __exit = 0; - end - else - begin - __exit = debug_tick( - __debug_req_valid, - __debug_req_ready, - __debug_req_bits_addr, - __debug_req_bits_op, - __debug_req_bits_data, - __debug_resp_valid, - __debug_resp_ready, - __debug_resp_bits_resp, - __debug_resp_bits_data - ); - end - end -endmodule diff --git a/target/sim/src/elfloader.cpp b/target/sim/src/elfloader.cpp index aa31a4693..c1fe32d9c 100644 --- a/target/sim/src/elfloader.cpp +++ b/target/sim/src/elfloader.cpp @@ -157,12 +157,21 @@ std::map> mems; uint64_t entry = 0; int section_index = 0; +// custom class for dtm +class preload_aware_dtm_t : public dtm_t { + public: + preload_aware_dtm_t(int argc, char **argv) : dtm_t(argc, argv) {} + bool is_address_preloaded(addr_t taddr, size_t len) override { return true; } +}; + extern "C" { char get_entry(long long *entry_ret); char get_section(long long *address_ret, long long *len_ret); char read_section(long long address, const svOpenArrayHandle buffer, long long len); char read_elf(const char *filename); + void* debug_new(char *pk_path, char *app_path); int debug_tick( + preload_aware_dtm_t* dtm, unsigned char* debug_req_valid, unsigned char debug_req_ready, int* debug_req_bits_addr, @@ -172,6 +181,7 @@ extern "C" { unsigned char* debug_resp_ready, int debug_resp_bits_resp, int debug_resp_bits_data); + int read_csr_dtm(); } static void write (uint64_t address, uint64_t len, uint8_t *buf) @@ -411,18 +421,29 @@ extern "C" char read_elf(const char *filename) { } #endif -class preload_aware_dtm_t : public dtm_t { - public: - preload_aware_dtm_t(int argc, char **argv) : dtm_t(argc, argv) {} - bool is_address_preloaded(addr_t taddr, size_t len) override { return true; } -}; -preload_aware_dtm_t* dtm; + /*------------------------ -From SimDTM.cc +Inspired by SimDTM.cc ------------------------*/ + +extern "C" void* debug_new(char *pk_path, char *app_path) { + int htif_argc = 3; + char* htif_argv[htif_argc]; + htif_argv[0] = (char*)"htif"; + htif_argv[1] = pk_path; + htif_argv[2] = app_path; + + preload_aware_dtm_t *dtm = (preload_aware_dtm_t *) malloc(sizeof(preload_aware_dtm_t)); + dtm = new preload_aware_dtm_t(htif_argc, htif_argv); + + return (void *)dtm; +} + + extern "C" int debug_tick ( + preload_aware_dtm_t* dtm, unsigned char* debug_req_valid, unsigned char debug_req_ready, int* debug_req_bits_addr, @@ -434,19 +455,6 @@ extern "C" int debug_tick int debug_resp_bits_data ) { - if (!dtm) { - //the list of argv are the program that will be runned after pk is booted. - // Need to find a way to make it easier to change programs, maybe like it was done... - int htif_argc = 3; - char* htif_argv[htif_argc]; - htif_argv[0] = (char*)"htif"; - htif_argv[1] = (char*)"/scratch/ga25f6/cheshire/sw/apps/pk_dram"; - htif_argv[2] = (char*)"/scratch/ga25f6/cheshire/sw/apps/helloworld.o"; - - dtm = new preload_aware_dtm_t(htif_argc, htif_argv); - } - - dtm_t::resp resp_bits; resp_bits.resp = debug_resp_bits_resp; resp_bits.data = debug_resp_bits_data; diff --git a/target/sim/src/tb_cheshire_soc.sv b/target/sim/src/tb_cheshire_soc.sv index b212e8e90..e3cd89024 100644 --- a/target/sim/src/tb_cheshire_soc.sv +++ b/target/sim/src/tb_cheshire_soc.sv @@ -31,7 +31,7 @@ module tb_cheshire_soc #( `ifdef FESVR_DTM // locking SimDTM - assign fix.vip.start_SimDTM = 1'b0; + fix.vip.fesvr_stop(); `endif // Set boot mode and preload boot image if there is one @@ -49,7 +49,8 @@ module tb_cheshire_soc #( // Preload done only using slink in this case cause it's the fastest way available 1: begin // Serial Link fix.vip.slink_elf_prerun(preload_elf); - assign fix.vip.start_SimDTM = 1'b1; + fix.vip.fesvr_set(preload_elf, "/scratch/ga25f6/cheshire/sw/apps/helloworld.riscv"); + fix.vip.fesvr_start(); fix.vip.fesvr_wait_for_exit(exit_code); end default: begin $fatal(1, "Unsupported preload mode %d (reserved)!", boot_mode); diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index 1237c5528..4b4844de5 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -98,18 +98,21 @@ module vip_cheshire_soc import cheshire_pkg::*; #( import "DPI-C" function byte get_section(output longint address, output longint len); import "DPI-C" context function byte read_section(input longint address, inout byte buffer[], input longint len); `ifdef FESVR_DTM + import "DPI-C" function chandle debug_new(input string pk_path, input string app_path); import "DPI-C" function int debug_tick ( - output bit debug_req_valid, - input bit debug_req_ready, - output int debug_req_bits_addr, - output int debug_req_bits_op, - output int debug_req_bits_data, - - input bit debug_resp_valid, - output bit debug_resp_ready, - input int debug_resp_bits_resp, - input int debug_resp_bits_data + input chandle fesvr_dtm, + + output bit debug_req_valid, + input bit debug_req_ready, + output int debug_req_bits_addr, + output int debug_req_bits_op, + output int debug_req_bits_data, + + input bit debug_resp_valid, + output bit debug_resp_ready, + input int debug_resp_bits_resp, + input int debug_resp_bits_data ); `endif @@ -1008,32 +1011,76 @@ module vip_cheshire_soc import cheshire_pkg::*; #( // SimDTM // ////////////// - logic start_SimDTM; // wired up in the testbench + /*--------------------------------- + Mostly comming from SimDTM.sv +---------------------------------*/ + + chandle fesvr_dtm; + + logic start_SimDTM; // wired up in the testbench logic [31:0] sim_exit; // TODO: wire this up in the testbench logic [1:0] dmi_req_bits_op; assign dmi_req.op = dm::dtm_op_e'(dmi_req_bits_op); // need to check if it's this variable, - SimDTM i_SimDTM ( - .clk ( clk ), - .reset ( rst_n & start_SimDTM ), - .debug_req_valid ( dmi_req_valid ), - .debug_req_ready ( dmi_req_ready ), - .debug_req_bits_addr ( dmi_req.addr ), - .debug_req_bits_op ( dmi_req_bits_op ), - .debug_req_bits_data ( dmi_req.data ), - .debug_resp_valid ( dmi_resp_valid ), - .debug_resp_ready ( dmi_resp_ready ), - .debug_resp_bits_resp ( dmi_resp.resp ), - .debug_resp_bits_data ( dmi_resp.data ), - .exit ( sim_exit ) - ); + wire #0.1 __debug_req_ready = dmi_req_ready; + wire #0.1 __debug_resp_valid = dmi_resp_valid; + wire [31:0] #0.1 __debug_resp_bits_resp = {30'b0, dmi_resp.resp}; + wire [31:0] #0.1 __debug_resp_bits_data = dmi_resp.data; + + bit __debug_req_valid; + int __debug_req_bits_addr; + int __debug_req_bits_op; + int __debug_req_bits_data; + bit __debug_resp_ready; + int __exit; + + assign #0.1 dmi_req_valid = __debug_req_valid; + assign #0.1 dmi_req.addr = __debug_req_bits_addr[6:0]; + assign #0.1 dmi_req_bits_op = __debug_req_bits_op[1:0]; + assign #0.1 dmi_req.data = __debug_req_bits_data[31:0]; + assign #0.1 dmi_resp_ready = __debug_resp_ready; + assign #0.1 sim_exit = __exit; + + always @(posedge clk) + begin + if(!(rst_n & start_SimDTM)) begin + __debug_req_valid = 0; + __debug_resp_ready = 0; + __exit = 0; + end else begin + __exit = debug_tick( + fesvr_dtm, + __debug_req_valid, + __debug_req_ready, + __debug_req_bits_addr, + __debug_req_bits_op, + __debug_req_bits_data, + __debug_resp_valid, + __debug_resp_ready, + __debug_resp_bits_resp, + __debug_resp_bits_data + ); + end + end task automatic fesvr_wait_for_exit(output word_bt exit_code); while (~sim_exit[0]) begin #(ClkPeriodSys * 100); end - if (sim_exit == 1) $error("[FESVR] SUCCESS"); - else $display("[FESVR] FAILED: return code %0d", sim_exit); + if (sim_exit == 1) $display("[FESVR] SUCCESS"); + else $error("[FESVR] FAILED: return code %0d", sim_exit); + endtask + + task automatic fesvr_stop(); + start_SimDTM = 0; + endtask + + task automatic fesvr_start(); + start_SimDTM = 1; + endtask + + task automatic fesvr_set(input string kernel, input string binary); + fesvr_dtm = debug_new(kernel, binary); endtask `endif From 0854d8fb585ce3bbfa86cb32b496f0ea2e82d2a8 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Thu, 24 Jul 2025 17:04:27 +0200 Subject: [PATCH 09/26] bender.yml: removing SimDTM.sv --- Bender.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/Bender.yml b/Bender.yml index eaae185c8..edddb742b 100644 --- a/Bender.yml +++ b/Bender.yml @@ -47,7 +47,6 @@ sources: - target: any(simulation, test) files: - - target/sim/src/SimDTM.sv - target/sim/models/s25fs512s.v - target/sim/models/24FC1025.v - target/sim/src/vip_cheshire_soc.sv From e5a13dedb691e7cab7a0677d5de413e2e2fb633c Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Mon, 28 Jul 2025 17:06:18 +0200 Subject: [PATCH 10/26] treewide: cleaner & with dmi_rst --- hw/cheshire_soc.sv | 15 +++++++++------ target/sim/src/elfloader.cpp | 1 - target/sim/src/fixture_cheshire_soc.sv | 2 ++ target/sim/src/vip_cheshire_soc.sv | 10 +++++----- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/hw/cheshire_soc.sv b/hw/cheshire_soc.sv index af84c3ae2..d1d0b914d 100644 --- a/hw/cheshire_soc.sv +++ b/hw/cheshire_soc.sv @@ -99,13 +99,14 @@ module cheshire_soc import cheshire_pkg::*; #( output logic [Cfg.VgaBlueWidth -1:0] vga_blue_o, `ifdef FESVR_DTM // DMI interface - input dm::dmi_req_t dmi_req_i, - input logic dmi_req_valid_i, - output logic dmi_req_ready_o, + input logic dmi_rst_ni, + input dm::dmi_req_t dmi_req_i, + input logic dmi_req_valid_i, + output logic dmi_req_ready_o, output dm::dmi_resp_t dmi_resp_o, - input logic dmi_resp_ready_i, - output logic dmi_resp_valid_o, + input logic dmi_resp_ready_i, + output logic dmi_resp_valid_o, `endif // USB interface input logic usb_clk_i, @@ -797,7 +798,9 @@ module cheshire_soc import cheshire_pkg::*; #( logic dbg_sba_err; // JTAG DMI to debug module + `ifndef FESVR_DTM logic dbg_dmi_rst_n; + `endif dm::dmi_req_t dbg_dmi_req; logic dbg_dmi_req_ready, dbg_dmi_req_valid; dm::dmi_resp_t dbg_dmi_rsp; @@ -924,7 +927,7 @@ module cheshire_soc import cheshire_pkg::*; #( .master_r_err_i ( dbg_sba_err ), .master_r_other_err_i ( 1'b0 ), `ifdef FESVR_DTM - .dmi_rst_ni ( rst_ni ), // not handled by SimDTM and his done like this in dmi_jtag + .dmi_rst_ni ( dmi_rst_ni ), // not handled by SimDTM and his done like this in dmi_jtag .dmi_req_valid_i ( dmi_req_valid_i ), .dmi_req_ready_o ( dmi_req_ready_o ), .dmi_req_i ( dmi_req_i ), diff --git a/target/sim/src/elfloader.cpp b/target/sim/src/elfloader.cpp index c1fe32d9c..b955d97d3 100644 --- a/target/sim/src/elfloader.cpp +++ b/target/sim/src/elfloader.cpp @@ -181,7 +181,6 @@ extern "C" { unsigned char* debug_resp_ready, int debug_resp_bits_resp, int debug_resp_bits_data); - int read_csr_dtm(); } static void write (uint64_t address, uint64_t len, uint8_t *buf) diff --git a/target/sim/src/fixture_cheshire_soc.sv b/target/sim/src/fixture_cheshire_soc.sv index 4dcfd058b..c88b909a1 100644 --- a/target/sim/src/fixture_cheshire_soc.sv +++ b/target/sim/src/fixture_cheshire_soc.sv @@ -65,6 +65,7 @@ module fixture_cheshire_soc #( `ifdef FESVR_DTM //DMI + logic dmi_rst_ni; dm::dmi_req_t dmi_req; logic dmi_req_valid; logic dmi_req_ready; @@ -146,6 +147,7 @@ module fixture_cheshire_soc #( .vga_green_o ( ), .vga_blue_o ( ), `ifdef FESVR_DTM + .dmi_rst_ni ( dmi_rst_ni ), .dmi_req_valid_i ( dmi_req_valid ), .dmi_req_ready_o ( dmi_req_ready ), .dmi_req_i ( dmi_req ), diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index 4b4844de5..909e84069 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -70,6 +70,7 @@ module vip_cheshire_soc import cheshire_pkg::*; #( inout wire [ 3:0] spih_sd, `ifdef FESVR_DTM // DMI + output logic dmi_rst_ni, output dm::dmi_req_t dmi_req, output logic dmi_req_valid, input logic dmi_req_ready, @@ -1017,7 +1018,6 @@ module vip_cheshire_soc import cheshire_pkg::*; #( chandle fesvr_dtm; - logic start_SimDTM; // wired up in the testbench logic [31:0] sim_exit; // TODO: wire this up in the testbench logic [1:0] dmi_req_bits_op; assign dmi_req.op = dm::dtm_op_e'(dmi_req_bits_op); // need to check if it's this variable, @@ -1043,7 +1043,7 @@ module vip_cheshire_soc import cheshire_pkg::*; #( always @(posedge clk) begin - if(!(rst_n & start_SimDTM)) begin + if(!(rst_n & dmi_rst_ni)) begin __debug_req_valid = 0; __debug_resp_ready = 0; __exit = 0; @@ -1072,16 +1072,16 @@ module vip_cheshire_soc import cheshire_pkg::*; #( endtask task automatic fesvr_stop(); - start_SimDTM = 0; + dmi_rst_ni = 0; endtask task automatic fesvr_start(); - start_SimDTM = 1; + dmi_rst_ni = 1; endtask task automatic fesvr_set(input string kernel, input string binary); fesvr_dtm = debug_new(kernel, binary); - endtask + endtask `endif endmodule From c8c7e1f94efb110317ab2d731ef28d58945d0b5f Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Mon, 28 Jul 2025 17:07:07 +0200 Subject: [PATCH 11/26] target/sim: using BINARY variable for the app instead of pk --- target/sim/src/tb_cheshire_soc.sv | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/sim/src/tb_cheshire_soc.sv b/target/sim/src/tb_cheshire_soc.sv index e3cd89024..bc24fb7ee 100644 --- a/target/sim/src/tb_cheshire_soc.sv +++ b/target/sim/src/tb_cheshire_soc.sv @@ -48,10 +48,10 @@ module tb_cheshire_soc #( case (preload_mode) // Preload done only using slink in this case cause it's the fastest way available 1: begin // Serial Link - fix.vip.slink_elf_prerun(preload_elf); - fix.vip.fesvr_set(preload_elf, "/scratch/ga25f6/cheshire/sw/apps/helloworld.riscv"); - fix.vip.fesvr_start(); - fix.vip.fesvr_wait_for_exit(exit_code); + fix.vip.slink_elf_prerun("/scratch/ga25f6/pk_dram"); // preload with slink + fix.vip.fesvr_set("/scratch/ga25f6/pk_dram", preload_elf); // creating a dtm class + fix.vip.fesvr_start(); // starting dtm tick + fix.vip.fesvr_wait_for_exit(exit_code); //waiting on exit code to be zero end default: begin $fatal(1, "Unsupported preload mode %d (reserved)!", boot_mode); end From 06a3937834795f23138cb626fdb7e2eeaffde9ce Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Mon, 28 Jul 2025 17:33:23 +0200 Subject: [PATCH 12/26] target/sim: Parameter to precise pk path --- target/sim/src/tb_cheshire_soc.sv | 6 ++++-- target/sim/vcs/start.cheshire_soc.sh | 1 + target/sim/vsim/start.cheshire_soc.tcl | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/target/sim/src/tb_cheshire_soc.sv b/target/sim/src/tb_cheshire_soc.sv index bc24fb7ee..d984db39e 100644 --- a/target/sim/src/tb_cheshire_soc.sv +++ b/target/sim/src/tb_cheshire_soc.sv @@ -16,6 +16,7 @@ module tb_cheshire_soc #( .UseDramSys (UseDramSys) ) fix(); + string pk_path; string preload_elf; string boot_hex; logic [1:0] boot_mode; @@ -28,6 +29,7 @@ module tb_cheshire_soc #( if (!$value$plusargs("PRELMODE=%d", preload_mode)) preload_mode = 0; if (!$value$plusargs("BINARY=%s", preload_elf)) preload_elf = ""; if (!$value$plusargs("IMAGE=%s", boot_hex)) boot_hex = ""; + if (!$value$plusargs("PK=%s", pk_path)) pk_path = ""; `ifdef FESVR_DTM // locking SimDTM @@ -48,8 +50,8 @@ module tb_cheshire_soc #( case (preload_mode) // Preload done only using slink in this case cause it's the fastest way available 1: begin // Serial Link - fix.vip.slink_elf_prerun("/scratch/ga25f6/pk_dram"); // preload with slink - fix.vip.fesvr_set("/scratch/ga25f6/pk_dram", preload_elf); // creating a dtm class + fix.vip.slink_elf_prerun(pk_path); // preload with slink + fix.vip.fesvr_set(pk_path, preload_elf); // creating a dtm class fix.vip.fesvr_start(); // starting dtm tick fix.vip.fesvr_wait_for_exit(exit_code); //waiting on exit code to be zero end default: begin diff --git a/target/sim/vcs/start.cheshire_soc.sh b/target/sim/vcs/start.cheshire_soc.sh index e8623fb3a..9d7754cc2 100755 --- a/target/sim/vcs/start.cheshire_soc.sh +++ b/target/sim/vcs/start.cheshire_soc.sh @@ -35,6 +35,7 @@ pargs="" [[ -n "${PRELMODE}" ]] && pargs+="+PRELMODE=${PRELMODE} " [[ -n "${BINARY}" ]] && pargs+="+BINARY=${BINARY} " [[ -n "${IMAGE}" ]] && pargs+="+IMAGE=${IMAGE} " +[[ -n "${PK}" ]] && pargs+="+PK=${PK} " # DRAMSys if [ -n "${USE_DRAMSYS}" ]; then diff --git a/target/sim/vsim/start.cheshire_soc.tcl b/target/sim/vsim/start.cheshire_soc.tcl index c732b1969..d6c7fc2a1 100644 --- a/target/sim/vsim/start.cheshire_soc.tcl +++ b/target/sim/vsim/start.cheshire_soc.tcl @@ -35,6 +35,7 @@ if { [info exists BOOTMODE] } { append pargs "+BOOTMODE=${BOOTMODE} " } if { [info exists PRELMODE] } { append pargs "+PRELMODE=${PRELMODE} " } if { [info exists BINARY] } { append pargs "+BINARY=${BINARY} " } if { [info exists IMAGE] } { append pargs "+IMAGE=${IMAGE} " } +if { [info exists PK] } { append pargs "+PK=${PK} " } # DRAMSys if { [info exists USE_DRAMSYS] } { From 3d50337ed95b448ec53b89262c4f840cc5f5789d Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Thu, 31 Jul 2025 14:04:25 +0200 Subject: [PATCH 13/26] target/sim/src: wait_boot_pk deprecatred --- target/sim/src/tb_cheshire_soc.sv | 1 - target/sim/src/vip_cheshire_soc.sv | 6 ------ 2 files changed, 7 deletions(-) diff --git a/target/sim/src/tb_cheshire_soc.sv b/target/sim/src/tb_cheshire_soc.sv index d984db39e..f76fabceb 100644 --- a/target/sim/src/tb_cheshire_soc.sv +++ b/target/sim/src/tb_cheshire_soc.sv @@ -68,7 +68,6 @@ module tb_cheshire_soc #( end 1: begin // Serial Link fix.vip.slink_elf_run(preload_elf); fix.vip.slink_wait_for_eoc(exit_code); - //fix.vip.wait_boot_pk(); end 2: begin // UART fix.vip.uart_debug_elf_run_and_wait(preload_elf, exit_code); end default: begin diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index 909e84069..ef7334519 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -1001,12 +1001,6 @@ module vip_cheshire_soc import cheshire_pkg::*; #( else $display("[SLINK] SUCCESS"); endtask - // when running pk, there is not eoc, so it will never ends, - //that why you should us this function instead of slink_wait_for_eoc - task automatic wait_boot_pk(); - #(ClkPeriodSys * 200000 * 2); // wait 2s, pk should be booted (take around 1.5s). - endtask - `ifdef FESVR_DTM ////////////// // SimDTM // From 6efc15950bd22a6e13e5e23b4606a5c88d2365b6 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Thu, 31 Jul 2025 17:17:30 +0200 Subject: [PATCH 14/26] tqrget/sim/src: fix even exitcode that would cause the simulation to never finish --- target/sim/src/vip_cheshire_soc.sv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index ef7334519..47d5387fe 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -1058,7 +1058,8 @@ module vip_cheshire_soc import cheshire_pkg::*; #( end task automatic fesvr_wait_for_exit(output word_bt exit_code); - while (~sim_exit[0]) begin + logic [31:0] sim_init = sim_exit; + while (sim_init == sim_exit) begin #(ClkPeriodSys * 100); end if (sim_exit == 1) $display("[FESVR] SUCCESS"); From 31081f10db58b96141d402e55a13e092b9747db6 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Mon, 4 Aug 2025 15:19:01 +0200 Subject: [PATCH 15/26] mt_doc: add documentation about new features & changes --- mt_doc/fesvr_support_cheshire.svg | 4 + mt_doc/readme.md | 129 ++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 mt_doc/fesvr_support_cheshire.svg create mode 100644 mt_doc/readme.md diff --git a/mt_doc/fesvr_support_cheshire.svg b/mt_doc/fesvr_support_cheshire.svg new file mode 100644 index 000000000..ca5774e9a --- /dev/null +++ b/mt_doc/fesvr_support_cheshire.svg @@ -0,0 +1,4 @@ + + + +
TB
TB
Fixture
Fixture
VIP
VIP
SoC
SoC
DM
DM
dmi_jtag
dmi_jtag
A
X
I
A...
dmi
dmi
JTAG VIP
JTAG VIP
dmi
dmi
jtag
jtag
SimDTM
SimDTM
dmi
dmi
FESVR
FESVR
DPI
DPI
call tasks
call tasks
wrapper
wrapper
drive clock and I/O
drive clock and I/O
cheshire
cheshire
Text is not SVG - cannot display
\ No newline at end of file diff --git a/mt_doc/readme.md b/mt_doc/readme.md new file mode 100644 index 000000000..b40c57161 --- /dev/null +++ b/mt_doc/readme.md @@ -0,0 +1,129 @@ +# FESVR support on chesire + +# Getting Started + +## Things needed : + - fesvr + - pk + +### RISC-V Frontend Server : fesvr +Install fesvr : `` git clone https://github.com/riscv-software-src/riscv-isa-sim.git`` + +Make sure that **USE_CONTEXT** is not defined in *fesvr/context.h*, the **line 10** can be commented. + +You should also had ``fesvr_install_shared_lib = yes`` in *fesvr/fesvr.mk.in* it will install a shared lib, the static one will not work with sim tools. +Remember the path of the installation, it’s needed to modify **Cheshire.mk** and **target/sim/vXXX/start.cheshire_soc.XXX** and update the path. +``` +mkdir build install +cd build +../configure --prefix=`realpath ../install/` --without-boost-regex +make +make install +``` + +### Cheshire +Nothing change for the installation, 2 new script should be generated, to add fesvr usage when running vsim or vcs, make sure that you have given the right path to libfesvr.so in the previous step ! +Then you can run ``make all`` as usual. + +### RISC-V Proxy kernel : pk +You can git clone pk from my fork, and follow the installation from the readme, don’t forget to use -with_dts=path/to/cheshire.dts when doing the ../configure command. Like this + +``` +mkdir build install +cd build +../configure --prefix=`realpath ../install/` --host=riscv64-unknown-elf --with-dts=`realpath ../../cheshire/sw/boot/cheshire_spm.dts` +make +make install +``` +Keep in mind the path to your pk installation, it will be used in cheshire simulation + + +## Simulation +To run a simulation using fesvr dtm, with questa, do like this in *./target/sim/vsim*: +``` +set PK /path/riscv-pk/install/pk +set BINARY /path/sw/apps/helloworld.riscv +set BOOTMODE 0 +set PRELMODE 1 + +# Compile design WITH fesvr +source compile.cheshire_soc_fesvr.tcl + +# Start and run simulation +source start.cheshire_soc.tcl +run -all +``` +If you want to run an other simulation with a new app, you just have to set **BINARY** with an other value and run again the **start.cheshire_soc** script. + +# How it works +## Strucural change +![Cheshire fesvr supported block diagram](./fesvr_support_cheshire.svg) + +## Behavior of the simulation +There is several steps in the simulation, that can be observed by looking at the wave of dmi signals. + +First, pk is preloaded using serial link, this reduce the simulation time by using the burst mode of serial link to preload pk faster. + +Then, the frontend server (FESVR) take the lead, a dtm object is created, it will resume the core and start the proxy-kernel (pk). + +Once pk is booted, the FESVR will preload the binary using the debug module and runs it. When it's finished, the fesvr return an exitcode, allowing to know if everything went well or not. + + +# Changes done & Explanation +## DPI +2 DPI have been added, they are inspired by the DPI inside of *SimDTM.cc* and an upper class of *dtm_t* have been created. + +**preload_aware_dtm**: this upper class of dtm_t does change the *is_address_preloaded* function (from htif_f), this allow to preload the first binary that will be preloaded by the dtm object, in our case, pk.\ +This makes the simulation faster because when a binary is preloaded by the dtm, it uses dmi signals to communicate with the debug module, and only 64bits of data are transmitted. So it takes 24 instructions to write 64bits of the elf file in the memory of the SoC, as pk is a big program, around 90kB, it can be long to preload it (3-4min in real time when simulating) + +**debug_new**: it return a void* (chandle in sv) and takes 2 paths as arguments.\ +This DPI create a new dtm class, with the pk as a kernel and the binary that will be executed. It will be called by the testbench. + +**debug_tick**: it return an integer and takes a dtm object and dmi signals as arguments\ +This DPI call the *tick* function from dtm, this allow to get the value for the dmi request and 2 handshake signals, depending on dmi response and 2 corresponding handshake signals.\ +Overall this DPI allow to assign values to dmi signals, to ensure a proper communication with the debug module. It will be called in the VIP at every clockcycle. + +### Useful information about dtm +When a dtm class is created, everything take place at the initialisation.\ +An sub-htif object is initialised with the arguments coming from dtm arg. Then a function is called, *start_host_thread*, it will make a context switch and call the *producer_thread* function. That will enable the debugger of Cheshire and call the *run* function from htif.\ +This last function, preload the binary (if needed) and resume the core to run the binary. This function as an internal loop, until the binary as finished running and then return the exitcode. + +## VIP +Inside the VIP, a few changes have been done, the code from SimDTM has been reused with a few changes. +The way that the reset signal is handled as changed because it was not working for me and a *dmi_rst_ni* signal have been added. +A chandle have been added, to comply with the new feature of the DPI. It will be initialised thanks to the *fesvr_set* task. +Tasks have been created to handle the *dmi_rst_ni* signals. + +**Be careful, when running a testbench,** you must set fesvr before starting it, so call the task *fesvr_set* before *fesvr_start*. + +The task *fesvr_wait_for_exit* will loop until sim_exit has changed, so when the binary is finished. +It consider that the program should return 1, to say that everything went fine. In case of a problem, it should print the exitcode. + +The I/O have also been changed to add dmi signals when FESVR_DTM is defined, so when the fesvr compile script is used. + +## SoC +Inside of the SoC, dmi signals have been added as I/O, they do replace the dmi signals coming from the dmi_jtag module, that convert information coming from jtag to the debug module. This means that **when using fesvr, you can not use jtag.**\ +About the *dmi_rst_ni* signal, it is only used to reset a FIFO that contains the dmi signals inside of the debug module. + +## Testbench +Few changes have been done to handle and run fesvr. As you can see, the proxy kernel is preloaded using serial link.\ +Then a chandle for dtm_t is created and it is started by setting the dmi reset to 1, starting to use the dpi, debug_tick at every clock cycle. the task coming from vip will wait for the end and the simulation will finish. + +# Possible upgrade +### Running several app in a single simulation +To do this, changes must be done to the FESVR library. +There is a function in *htif.cc*, called *run*, that loop on a value of the object called **stopped**. This value is set at the initialisation of the object to *false* and when run is finished, it's set to *true*. +There is no other function changing this value. So this is the first modification that would be needed if you want to run a new binary with the same object. +x +Also, inside *dtm.cc*, there is a function called *producer_thread*. It is called at the end of the initialisation of the dtm class and used to connect the fesvr to the debug module and to run the program (with *htif_t::run*). The thing is that at the end, there is a loop with only nop, so this function never really finish. The end of the simulation is endled by the testbench thanks to the exitcode comming from *htif_t::run*. + +An other solution, would be to use the chandle feature, but there is no clean way to close the connection between the debug module and dtm, a proper destructor might be needed... +It would have to make sure that everything is finished and get back to running pk, that will poll htif registers. +This could allow to create a 1st dtm class, with pk and binary 1, then run it and destruct it properly, than you could create a 2nd dtm class, with + +# Others +The fesvr implementation inside of the CVA6 is a bit old and has not been update or evolved. It was inspired by the work done in Chipyard Framework. Inside this framework repository, we can find updated documentations with useful information that can come in hand to understand how it works and also to add features (TSI support or GDB - OpenOCD - JTAG support). + +[Chipyard - Boot process](https://chipyard.readthedocs.io/en/latest/Customization/Boot-Process.html#) + +[Chipyard - Chip communication](https://chipyard.readthedocs.io/en/latest/Advanced-Concepts/Chip-Communication.html) \ No newline at end of file From f8322a6965408457b045a945d3d7790c370a65c4 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Tue, 5 Aug 2025 11:40:06 +0200 Subject: [PATCH 16/26] target/sim/src: add support to run elf without pk --- target/sim/src/elfloader.cpp | 17 +++++++++++++++-- target/sim/src/tb_cheshire_soc.sv | 16 +++++++++++++--- target/sim/src/vip_cheshire_soc.sv | 13 +++++++++---- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/target/sim/src/elfloader.cpp b/target/sim/src/elfloader.cpp index b955d97d3..a1353ed3c 100644 --- a/target/sim/src/elfloader.cpp +++ b/target/sim/src/elfloader.cpp @@ -169,7 +169,8 @@ extern "C" { char get_section(long long *address_ret, long long *len_ret); char read_section(long long address, const svOpenArrayHandle buffer, long long len); char read_elf(const char *filename); - void* debug_new(char *pk_path, char *app_path); + void* debug_new_pk(char *pk_path, char *app_path); + void* debug_new(char *app_path); int debug_tick( preload_aware_dtm_t* dtm, unsigned char* debug_req_valid, @@ -426,7 +427,7 @@ extern "C" char read_elf(const char *filename) { Inspired by SimDTM.cc ------------------------*/ -extern "C" void* debug_new(char *pk_path, char *app_path) { +extern "C" void* debug_new_pk(char *pk_path, char *app_path) { int htif_argc = 3; char* htif_argv[htif_argc]; htif_argv[0] = (char*)"htif"; @@ -439,6 +440,18 @@ extern "C" void* debug_new(char *pk_path, char *app_path) { return (void *)dtm; } +extern "C" void* debug_new(char *app_path) { + int htif_argc = 2; + char* htif_argv[htif_argc]; + htif_argv[0] = (char*)"htif"; + htif_argv[1] = app_path; + + preload_aware_dtm_t *dtm = (preload_aware_dtm_t *) malloc(sizeof(preload_aware_dtm_t)); + dtm = new preload_aware_dtm_t(htif_argc, htif_argv); + + return (void *)dtm; +} + extern "C" int debug_tick ( diff --git a/target/sim/src/tb_cheshire_soc.sv b/target/sim/src/tb_cheshire_soc.sv index f76fabceb..fb849d46d 100644 --- a/target/sim/src/tb_cheshire_soc.sv +++ b/target/sim/src/tb_cheshire_soc.sv @@ -22,6 +22,7 @@ module tb_cheshire_soc #( logic [1:0] boot_mode; logic [1:0] preload_mode; bit [31:0] exit_code; + logic using_pk; initial begin // Fetch plusargs or use safe (fail-fast) defaults @@ -29,7 +30,10 @@ module tb_cheshire_soc #( if (!$value$plusargs("PRELMODE=%d", preload_mode)) preload_mode = 0; if (!$value$plusargs("BINARY=%s", preload_elf)) preload_elf = ""; if (!$value$plusargs("IMAGE=%s", boot_hex)) boot_hex = ""; - if (!$value$plusargs("PK=%s", pk_path)) pk_path = ""; + if (!$value$plusargs("PK=%s", pk_path)) begin + pk_path = ""; + using_pk = 0; + end else using_pk = 1; `ifdef FESVR_DTM // locking SimDTM @@ -49,9 +53,15 @@ module tb_cheshire_soc #( // Idle boot: preload with the specified mode, only slink when fesvr case (preload_mode) // Preload done only using slink in this case cause it's the fastest way available + // !! fesvr_set before fesvr_start !! 1: begin // Serial Link - fix.vip.slink_elf_prerun(pk_path); // preload with slink - fix.vip.fesvr_set(pk_path, preload_elf); // creating a dtm class + if (using_pk) begin + fix.vip.slink_elf_prerun(pk_path); // preload with slink + fix.vip.fesvr_set_pk(pk_path, preload_elf); // creating a dtm class + end else begin + fix.vip.slink_elf_prerun(preload_elf); // preload with slink + fix.vip.fesvr_set(preload_elf); // creating a dtm class + end fix.vip.fesvr_start(); // starting dtm tick fix.vip.fesvr_wait_for_exit(exit_code); //waiting on exit code to be zero end default: begin diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index 47d5387fe..658317d75 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -99,7 +99,8 @@ module vip_cheshire_soc import cheshire_pkg::*; #( import "DPI-C" function byte get_section(output longint address, output longint len); import "DPI-C" context function byte read_section(input longint address, inout byte buffer[], input longint len); `ifdef FESVR_DTM - import "DPI-C" function chandle debug_new(input string pk_path, input string app_path); + import "DPI-C" function chandle debug_new_pk(input string pk_path, input string app_path); + import "DPI-C" function chandle debug_new(input string app_path); import "DPI-C" function int debug_tick ( input chandle fesvr_dtm, @@ -1062,7 +1063,7 @@ module vip_cheshire_soc import cheshire_pkg::*; #( while (sim_init == sim_exit) begin #(ClkPeriodSys * 100); end - if (sim_exit == 1) $display("[FESVR] SUCCESS"); + if (sim_exit == 1) $display("[FESVR] SUCCESS : code %0d", sim_exit); else $error("[FESVR] FAILED: return code %0d", sim_exit); endtask @@ -1074,8 +1075,12 @@ module vip_cheshire_soc import cheshire_pkg::*; #( dmi_rst_ni = 1; endtask - task automatic fesvr_set(input string kernel, input string binary); - fesvr_dtm = debug_new(kernel, binary); + task automatic fesvr_set(input string binary); + fesvr_dtm = debug_new(binary); + endtask + + task automatic fesvr_set_pk(input string kernel, input string binary); + fesvr_dtm = debug_new_pk(kernel, binary); endtask `endif From b49daf8ad6f999b39a81449e9c244c6fabb58a48 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Tue, 5 Aug 2025 12:02:19 +0200 Subject: [PATCH 17/26] target/sim/src: proprely handling exitcode --- target/sim/src/vip_cheshire_soc.sv | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index 658317d75..70c3aef8a 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -1059,12 +1059,12 @@ module vip_cheshire_soc import cheshire_pkg::*; #( end task automatic fesvr_wait_for_exit(output word_bt exit_code); - logic [31:0] sim_init = sim_exit; - while (sim_init == sim_exit) begin + while (!sim_exit[0]) begin #(ClkPeriodSys * 100); end - if (sim_exit == 1) $display("[FESVR] SUCCESS : code %0d", sim_exit); - else $error("[FESVR] FAILED: return code %0d", sim_exit); + exit_code = sim_exit >> 1; + if (exit_code == 0) $display("[FESVR] SUCCESS"); + else $error("[FESVR] FAILED: return code %0d", exit_code); endtask task automatic fesvr_stop(); From 85764e94f0a4dba45c72aef3ecbdeda027d291da Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Wed, 6 Aug 2025 10:57:57 +0200 Subject: [PATCH 18/26] sw/deps: add riscv-pk and riscv-isa-sim for fesvr --- .gitmodules | 8 ++++++++ sw/deps/riscv-isa-sim | 1 + sw/deps/riscv-pk | 1 + 3 files changed, 10 insertions(+) create mode 160000 sw/deps/riscv-isa-sim create mode 160000 sw/deps/riscv-pk diff --git a/.gitmodules b/.gitmodules index 620a456ac..78504bf8a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,3 +6,11 @@ path = sw/deps/cva6-sdk url = https://github.com/pulp-platform/cva6-sdk.git ignore = dirty +[submodule "sw/deps/riscv-isa-sim"] + path = sw/deps/riscv-isa-sim + url = https://github.com/riscv-software-src/riscv-isa-sim + ignore = dirty +[submodule "sw/deps/riscv-pk"] + path = sw/deps/riscv-pk + url = https://github.com/riscv-software-src/riscv-pk.git + ignore = dirty diff --git a/sw/deps/riscv-isa-sim b/sw/deps/riscv-isa-sim new file mode 160000 index 000000000..d4568f669 --- /dev/null +++ b/sw/deps/riscv-isa-sim @@ -0,0 +1 @@ +Subproject commit d4568f6693c9e38a48264c4453a5de7f8b3d38a3 diff --git a/sw/deps/riscv-pk b/sw/deps/riscv-pk new file mode 160000 index 000000000..b4abf92e9 --- /dev/null +++ b/sw/deps/riscv-pk @@ -0,0 +1 @@ +Subproject commit b4abf92e9954aaed291d0282c580f94254f9b11c From 19c4d27cdda55680bef0c0ed4f1a9292a7612a32 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Wed, 6 Aug 2025 12:10:30 +0200 Subject: [PATCH 19/26] treewide: Update fesvr path to sw/deps --- cheshire.mk | 4 ++-- target/sim/vcs/start.cheshire_soc.sh | 2 +- target/sim/vsim/start.cheshire_soc.tcl | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cheshire.mk b/cheshire.mk index 055d292aa..244c8c1a6 100644 --- a/cheshire.mk +++ b/cheshire.mk @@ -149,11 +149,11 @@ CHS_BOOTROM_ALL += $(CHS_ROOT)/hw/bootrom/cheshire_bootrom.sv $(CHS_ROOT)/hw/boo $(CHS_ROOT)/target/sim/vsim/compile.cheshire_soc.tcl: $(CHS_ROOT)/Bender.yml $(BENDER) script vsim -t sim -t test $(CHS_BENDER_RTL_FLAGS) --vlog-arg="$(VLOG_ARGS)" > $@ - echo 'vlog "$(realpath $(CHS_ROOT))/target/sim/src/elfloader.cpp" -ccflags "-std=c++17 -I/scratch/ga25f6/riscv-isa-sim/install/include" -cpppath "$(CXX_PATH)"' >> $@ + echo 'vlog "$(realpath $(CHS_ROOT))/target/sim/src/elfloader.cpp" -ccflags "-std=c++17 -I$(realpath $(CHS_ROOT))/sw/deps/riscv-isa-sim/install/include" -cpppath "$(CXX_PATH)"' >> $@ $(CHS_ROOT)/target/sim/vsim/compile.cheshire_soc_fesvr.tcl: $(CHS_ROOT)/Bender.yml $(BENDER) script vsim -t sim -t test $(CHS_BENDER_RTL_FLAGS) --vlog-arg="$(VLOG_ARGS) +define+FESVR_DTM" > $@ - echo 'vlog "$(realpath $(CHS_ROOT))/target/sim/src/elfloader.cpp" -ccflags "-std=c++17 -I/scratch/ga25f6/riscv-isa-sim/install/include" -cpppath "$(CXX_PATH)"' >> $@ + echo 'vlog "$(realpath $(CHS_ROOT))/target/sim/src/elfloader.cpp" -ccflags "-std=c++17 -I$(realpath $(CHS_ROOT))/sw/deps/riscv-isa-sim/install/include" -cpppath "$(CXX_PATH)"' >> $@ $(CHS_ROOT)/target/sim/vcs/compile.cheshire_soc.sh: $(CHS_ROOT)/Bender.yml $(BENDER) script vcs -t sim -t test $(CHS_BENDER_RTL_FLAGS) --vlog-arg="$(VLOGAN_ARGS)" --vlogan-bin="$(VLOGAN)" > $@ diff --git a/target/sim/vcs/start.cheshire_soc.sh b/target/sim/vcs/start.cheshire_soc.sh index 9d7754cc2..00c708738 100755 --- a/target/sim/vcs/start.cheshire_soc.sh +++ b/target/sim/vcs/start.cheshire_soc.sh @@ -51,7 +51,7 @@ fi COLOR_NC='\e[0m' COLOR_BLUE='\e[0;34m' -${VCS_BIN} ${flags} -CFLAGS "-std=c++17 -I/scratch/ga25f6/riscv-isa-sim/install/include" -LIBS "-rdynamic -Wl,-rpath=/scratch/ga25f6/riscv-isa-sim/install/lib -L/scratch/ga25f6/riscv-isa-sim/install/lib -lfesvr" ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log +${VCS_BIN} ${flags} -CFLAGS "-std=c++17 -I../../../sw/deps/riscv-isa-sim/install/include" -LIBS "-rdynamic -Wl,-rpath=../../../sw/deps/riscv-isa-sim/install/lib -L../../../sw/deps/riscv-isa-sim/install/lib -lfesvr" ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log # Start simulation printf ${COLOR_BLUE}"${VCS_VERSION} ${VERDI_VERSION} ./simv ${pargs}"${COLOR_NC}"\n" diff --git a/target/sim/vsim/start.cheshire_soc.tcl b/target/sim/vsim/start.cheshire_soc.tcl index d6c7fc2a1..8fca15ed6 100644 --- a/target/sim/vsim/start.cheshire_soc.tcl +++ b/target/sim/vsim/start.cheshire_soc.tcl @@ -50,7 +50,7 @@ if { [info exists USE_DRAMSYS] } { } # Need to link fesvr library -append flags "-gblso /scratch/ga25f6/riscv-isa-sim/install/lib/libfesvr.so" +append flags "-gblso ../../../sw/deps/riscv-isa-sim/install/lib/libfesvr.so" # tclint-disable-next-line command-args eval "vsim -c ${TESTBENCH} -t 1ps -vopt -voptargs=\"${VOPTARGS}\"" ${pargs} ${flags} From adaecb121908ee13fcff78a8ef3865b2a7ca889f Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Mon, 11 Aug 2025 11:44:40 +0200 Subject: [PATCH 20/26] mt_doc: more details, information and how to run with/without pk --- mt_doc/readme.md | 90 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 29 deletions(-) diff --git a/mt_doc/readme.md b/mt_doc/readme.md index b40c57161..e7bdb6fa9 100644 --- a/mt_doc/readme.md +++ b/mt_doc/readme.md @@ -6,42 +6,39 @@ - fesvr - pk -### RISC-V Frontend Server : fesvr -Install fesvr : `` git clone https://github.com/riscv-software-src/riscv-isa-sim.git`` +They are inside *sw/deps*, you will just need to run ``git submodule update --init --recursive`` to download them. -Make sure that **USE_CONTEXT** is not defined in *fesvr/context.h*, the **line 10** can be commented. +### RISC-V Frontend Server : fesvr +To build the fesvr, you can run make build-fesvr from cheshire directory.\ +It will create a shared library, that will be used by simulation tools and DPI. -You should also had ``fesvr_install_shared_lib = yes`` in *fesvr/fesvr.mk.in* it will install a shared lib, the static one will not work with sim tools. -Remember the path of the installation, it’s needed to modify **Cheshire.mk** and **target/sim/vXXX/start.cheshire_soc.XXX** and update the path. -``` -mkdir build install -cd build -../configure --prefix=`realpath ../install/` --without-boost-regex -make -make install -``` +Make sure that fesvr is correctly build, you should see in *sw/deps*, the lib in *riscv-isa-sim/install/lib* and 3 directories in *riscv-isa-sim/install/include* ### Cheshire -Nothing change for the installation, 2 new script should be generated, to add fesvr usage when running vsim or vcs, make sure that you have given the right path to libfesvr.so in the previous step ! +Nothing change for the installation, 2 new script should be generated, to add fesvr support when running vsim or vcs. Then you can run ``make all`` as usual. -### RISC-V Proxy kernel : pk -You can git clone pk from my fork, and follow the installation from the readme, don’t forget to use -with_dts=path/to/cheshire.dts when doing the ../configure command. Like this - +### RISC-V Proxy kernel : pk +To build pk, you can do as following : ``` mkdir build install cd build -../configure --prefix=`realpath ../install/` --host=riscv64-unknown-elf --with-dts=`realpath ../../cheshire/sw/boot/cheshire_spm.dts` +../configure --prefix=`realpath ../install/` --host=riscv64-unknown-elf --with-dts=`realpath ../../cheshire/sw/boot/cheshire.dtsi` make make install ``` -Keep in mind the path to your pk installation, it will be used in cheshire simulation +Keep in mind the path to your pk installation, it might be used in cheshire simulation ## Simulation -To run a simulation using fesvr dtm, with questa, do like this in *./target/sim/vsim*: +To run a simulation using fesvr dtm, with questa, you have two choice, to run it with pk or not. \ +The proxy kernel (pk) does bring syscall support and more, allowing to run program with standard lib and I/O, like *printf* for example.\ +Going without pk can be useful if you want to run binary from **riscv-tests**, such as benchmarks or isa tests, are they are made to easily run bare-metal with fesvr.\ +The choice of using comes to setting **PK** or not, when setting the parameter for the simulation in your tool. + +Here is an example of running a binary over pk: ``` -set PK /path/riscv-pk/install/pk +set PK /path/sw/deps/riscv-pk/install/pk set BINARY /path/sw/apps/helloworld.riscv set BOOTMODE 0 set PRELMODE 1 @@ -55,49 +52,71 @@ run -all ``` If you want to run an other simulation with a new app, you just have to set **BINARY** with an other value and run again the **start.cheshire_soc** script. +Giving the right compilation script, will make cheshire RTL compiled with fesvr support, you should run the one with **_fesvr** at the end, like in the example. + # How it works -## Strucural change -![Cheshire fesvr supported block diagram](./fesvr_support_cheshire.svg) ## Behavior of the simulation There is several steps in the simulation, that can be observed by looking at the wave of dmi signals. +### If using the proxy-kernel First, pk is preloaded using serial link, this reduce the simulation time by using the burst mode of serial link to preload pk faster. Then, the frontend server (FESVR) take the lead, a dtm object is created, it will resume the core and start the proxy-kernel (pk). Once pk is booted, the FESVR will preload the binary using the debug module and runs it. When it's finished, the fesvr return an exitcode, allowing to know if everything went well or not. +The exitcode is handled by the testbench, to finish the simulation. + +### Without the proxy-kernel +First, the binary is preloaded using serial link, like when using pk, to make the simulatio faster. + +Then, the frontend server (FESVR) take the lead, a dtm object is created, it will resume the core and start the binary. When it's finished, the fesvr return an exitcode, allowing to know if everything went well or not. + +The exitcode is handled by the testbench, to finish the simulation. + +## Strucural change +![Cheshire fesvr supported block diagram](./fesvr_support_cheshire.svg) + +All the changes happens when compiled with the FESVR parameter.\ +I/O have been added for the dmi signals, to connect the front-end server with the debug module of Cheshire.\ +The architecture of SimDTM as been taken and his now directly in the VIP. Which will take care of calling the DPI to communicate. # Changes done & Explanation ## DPI -2 DPI have been added, they are inspired by the DPI inside of *SimDTM.cc* and an upper class of *dtm_t* have been created. +3 DPI have been added, they are inspired by the DPI inside of *SimDTM.cc* and an upper class of *dtm_t* have been created. **preload_aware_dtm**: this upper class of dtm_t does change the *is_address_preloaded* function (from htif_f), this allow to preload the first binary that will be preloaded by the dtm object, in our case, pk.\ This makes the simulation faster because when a binary is preloaded by the dtm, it uses dmi signals to communicate with the debug module, and only 64bits of data are transmitted. So it takes 24 instructions to write 64bits of the elf file in the memory of the SoC, as pk is a big program, around 90kB, it can be long to preload it (3-4min in real time when simulating) -**debug_new**: it return a void* (chandle in sv) and takes 2 paths as arguments.\ +**debug_new_pk**: it return a void* (chandle in sv) and takes 2 paths as arguments.\ This DPI create a new dtm class, with the pk as a kernel and the binary that will be executed. It will be called by the testbench. +**debug_new**: it return a void* (chandle in sv) and takes a path as argument.\ +This DPI create a new dtm class, with the binary that will be executed. It will be called by the testbench.\ +So the difference with *debug_new_pk* is that there is no kernel used in this one, allowing to run application + **debug_tick**: it return an integer and takes a dtm object and dmi signals as arguments\ This DPI call the *tick* function from dtm, this allow to get the value for the dmi request and 2 handshake signals, depending on dmi response and 2 corresponding handshake signals.\ Overall this DPI allow to assign values to dmi signals, to ensure a proper communication with the debug module. It will be called in the VIP at every clockcycle. ### Useful information about dtm When a dtm class is created, everything take place at the initialisation.\ -An sub-htif object is initialised with the arguments coming from dtm arg. Then a function is called, *start_host_thread*, it will make a context switch and call the *producer_thread* function. That will enable the debugger of Cheshire and call the *run* function from htif.\ +A sub-htif object is initialised with the arguments coming from dtm arg. Then a function is called, *start_host_thread*, it will make a context switch and call the *producer_thread* function. That will enable the debugger of Cheshire and call the *run* function from htif.\ This last function, preload the binary (if needed) and resume the core to run the binary. This function as an internal loop, until the binary as finished running and then return the exitcode. ## VIP Inside the VIP, a few changes have been done, the code from SimDTM has been reused with a few changes. The way that the reset signal is handled as changed because it was not working for me and a *dmi_rst_ni* signal have been added. -A chandle have been added, to comply with the new feature of the DPI. It will be initialised thanks to the *fesvr_set* task. +A chandle have been added, to comply with the new feature of the DPI. It will be initialised thanks to the *fesvr_set* task.\ Tasks have been created to handle the *dmi_rst_ni* signals. +As you can see, the full code of SimDTM have been copied into the VIP, it's easier to do this way, as SimDTM has never been updated since it's in the CVA6 + **Be careful, when running a testbench,** you must set fesvr before starting it, so call the task *fesvr_set* before *fesvr_start*. -The task *fesvr_wait_for_exit* will loop until sim_exit has changed, so when the binary is finished. -It consider that the program should return 1, to say that everything went fine. In case of a problem, it should print the exitcode. +The task *fesvr_wait_for_exit* will loop until the bit 0 of sim_exit is set to 1, so when the binary is finished.\ +A shift is done on sim_exit to get the exit code of the program. Which will be used to know if the simulation was succesful or not. The I/O have also been changed to add dmi signals when FESVR_DTM is defined, so when the fesvr compile script is used. @@ -109,12 +128,25 @@ About the *dmi_rst_ni* signal, it is only used to reset a FIFO that contains the Few changes have been done to handle and run fesvr. As you can see, the proxy kernel is preloaded using serial link.\ Then a chandle for dtm_t is created and it is started by setting the dmi reset to 1, starting to use the dpi, debug_tick at every clock cycle. the task coming from vip will wait for the end and the simulation will finish. +## RISC-V Frontend Server : fesvr +### Problems encountered when installing it +Two main problems happen when installing the fesvr like explained in it documentation : +- No shared lib created -> needed by simulation tools +- wrong ucontext used -> assert error when running fesvr + +To solve the first problem, the shared lib can simply be created by adding ``fesvr_install_shared_lib = yes`` in *fesvr/fesvr.mk.in* but this would require to change the code, it can also be done by running a command in the terminal to create it directly than copying it in the *install/lib* directory. + +The second problem is caused by **USE_CONTEXT** being defined in *fesvr/context.h*.\ +This is due to **\_\_GLIBC\_\_** being defined because, when compiling context.cc, the flag ``-I/usr/include`` give the full repository which will cause **\_\_GLIBC\_\_** to be defined. But context.cc only needs one header inside of */usr/include*, so by giving it as an argument instead of the full directory when compiling context.cc, we can bypass this problem. + +A script allow to compile the shared lib, making it easier. + # Possible upgrade ### Running several app in a single simulation To do this, changes must be done to the FESVR library. There is a function in *htif.cc*, called *run*, that loop on a value of the object called **stopped**. This value is set at the initialisation of the object to *false* and when run is finished, it's set to *true*. There is no other function changing this value. So this is the first modification that would be needed if you want to run a new binary with the same object. -x + Also, inside *dtm.cc*, there is a function called *producer_thread*. It is called at the end of the initialisation of the dtm class and used to connect the fesvr to the debug module and to run the program (with *htif_t::run*). The thing is that at the end, there is a loop with only nop, so this function never really finish. The end of the simulation is endled by the testbench thanks to the exitcode comming from *htif_t::run*. An other solution, would be to use the chandle feature, but there is no clean way to close the connection between the debug module and dtm, a proper destructor might be needed... From 1f76091a049c873aa96b864b97055c156b3d6754 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Mon, 11 Aug 2025 12:51:33 +0200 Subject: [PATCH 21/26] treewide: Add script to compile fesvr and pk --- cheshire.mk | 4 +-- sw/sw.mk | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/cheshire.mk b/cheshire.mk index 244c8c1a6..1b3f15466 100644 --- a/cheshire.mk +++ b/cheshire.mk @@ -206,8 +206,8 @@ include $(CHS_ROOT)/target/xilinx/xilinx.mk CHS_ALL += $(CHS_SW_ALL) $(CHS_HW_ALL) $(CHS_SIM_ALL) -chs-all: $(CHS_ALL) -chs-sw-all: $(CHS_SW_ALL) +chs-all: $(CHS_ALL) build-deps +chs-sw-all: $(CHS_SW_ALL) build-deps chs-hw-all: $(CHS_HW_ALL) chs-bootrom-all: $(CHS_BOOTROM_ALL) chs-sim-all: $(CHS_SIM_ALL) diff --git a/sw/sw.mk b/sw/sw.mk index baa9ee411..6daa58199 100644 --- a/sw/sw.mk +++ b/sw/sw.mk @@ -194,3 +194,80 @@ CHS_SW_TESTS += $(CHS_SW_TEST_ROM_DUMP:.rom.dump=.rom.memh) $(CHS_SW_TEST_ROM_DU # Add all dumps to test build CHS_SW_TESTS += $(CHS_SW_TEST_DUMP) + +######### +# FESVR # +######### +.PHONY: build-fesvr + +FESVR_DIR := sw/deps/riscv-isa-sim +FESVR_BUILD := $(FESVR_DIR)/build +FESVR_INSTALL := $(FESVR_DIR)/install +FESVR_PREFIX := $(shell realpath $(FESVR_INSTALL)) + +FESVR_OBJS := $(patsubst ../%.cc,%.o,$(FESVR_SRCS)) + +FESVR_LDFLAGS := -L. -Wl,--export-dynamic -L/usr/lib64 \ + -Wl,-rpath,$(FESVR_PREFIX)/lib \ + -shared + +FESVR_LIBS := -lpthread -ldl -lpthread + +FESVR_CXXFLAGS_COMMON := -MMD -MP \ + -DPREFIX=\"$(FESVR_PREFIX)/\" \ + -Wall -Wno-nonportable-include-path \ + -g -O2 -fPIC -std=c++2a \ + -iquote . -I.. -iquote ../fesvr -iquote ../riscv -iquote ../softfloat + +FESVR_CXXFLAGS := $(FESVR_CXXFLAGS_COMMON) +# context need to only have pthread.h +FESVR_CXXFLAGS_CONTEXT := $(FESVR_CXXFLAGS_COMMON) + + +# List of source files EXCLUDING context.cc +FESVR_SRCS := \ + ../fesvr/elfloader.cc \ + ../fesvr/htif.cc \ + ../fesvr/memif.cc \ + ../fesvr/dtm.cc \ + ../fesvr/syscall.cc \ + ../fesvr/device.cc \ + ../fesvr/rfb.cc \ + ../fesvr/htif_pthread.cc \ + ../fesvr/htif_hexwriter.cc \ + ../fesvr/dummy.cc \ + ../fesvr/option_parser.cc \ + ../fesvr/term.cc \ + ../fesvr/tsi.cc + +build-fesvr: + @mkdir -p $(FESVR_BUILD) $(FESVR_INSTALL)/lib \ + $(FESVR_INSTALL)/include/fesvr \ + $(FESVR_INSTALL)/include/riscv \ + $(FESVR_INSTALL)/include/softfloat + ( cd $(FESVR_BUILD) && \ + ../configure --prefix=$(FESVR_PREFIX) --without-boost-regex && \ + $(CXX) $(FESVR_CXXFLAGS) -c $(FESVR_SRCS) && \ + $(CXX) $(FESVR_CXXFLAGS_CONTEXT) -c ../fesvr/context.cc && \ + $(CXX) $(FESVR_LDFLAGS) -o libfesvr.so *.o $(FESVR_LIBS) ) + cp $(FESVR_BUILD)/libfesvr.so $(FESVR_INSTALL)/lib + cp $(FESVR_DIR)/fesvr/*.h $(FESVR_INSTALL)/include/fesvr + cp $(FESVR_DIR)/riscv/*.h $(FESVR_INSTALL)/include/riscv + cp $(FESVR_DIR)/softfloat/*.h $(FESVR_INSTALL)/include/softfloat + +.PHONY: build-pk + +PK_DIR := sw/deps/riscv-pk +PK_BUILD := $(PK_DIR)/build +PK_INSTALL := $(PK_DIR)/install +PK_PREFIX := $(shell realpath $(PK_INSTALL)) + +build-pk: + @mkdir $(PK_BUILD) $(PK_INSTALL) + ( cd $(PK_BUILD) && \ + ../configure --prefix=$(PK_PREFIX) --host=riscv64-unknown-elf --with-dts=$(CHS_SW_DIR)/boot/cheshire.dtsi && \ + make && \ + make install ) + +.PHONY: build-deps +build-deps: build-fesvr build-pk \ No newline at end of file From f038e67a6ea6c816616097a368fba770c02c8d31 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Mon, 11 Aug 2025 13:32:58 +0200 Subject: [PATCH 22/26] treewide: update documentation about new script and clean a script --- mt_doc/readme.md | 18 +++++++++++------- sw/sw.mk | 11 +++-------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/mt_doc/readme.md b/mt_doc/readme.md index e7bdb6fa9..75e43d05f 100644 --- a/mt_doc/readme.md +++ b/mt_doc/readme.md @@ -8,17 +8,22 @@ They are inside *sw/deps*, you will just need to run ``git submodule update --init --recursive`` to download them. +### Cheshire +Nothing change for the installation, 2 new script should be generated, to add fesvr support when running vsim or vcs. +Then you can run ``make all`` as usual. + ### RISC-V Frontend Server : fesvr +FESVR should have been built when running the ``make all``.\ +Make sure that fesvr is correctly build, you should see in *sw/deps*, the lib in *riscv-isa-sim/install/lib* and 3 directories in *riscv-isa-sim/install/include* + To build the fesvr, you can run make build-fesvr from cheshire directory.\ It will create a shared library, that will be used by simulation tools and DPI. -Make sure that fesvr is correctly build, you should see in *sw/deps*, the lib in *riscv-isa-sim/install/lib* and 3 directories in *riscv-isa-sim/install/include* - -### Cheshire -Nothing change for the installation, 2 new script should be generated, to add fesvr support when running vsim or vcs. -Then you can run ``make all`` as usual. ### RISC-V Proxy kernel : pk +pk should have been built when running the ``make all``.\ +Keep in mind the path to your pk installation, it might be used in cheshire simulation. + To build pk, you can do as following : ``` mkdir build install @@ -27,7 +32,6 @@ cd build make make install ``` -Keep in mind the path to your pk installation, it might be used in cheshire simulation ## Simulation @@ -137,7 +141,7 @@ Two main problems happen when installing the fesvr like explained in it document To solve the first problem, the shared lib can simply be created by adding ``fesvr_install_shared_lib = yes`` in *fesvr/fesvr.mk.in* but this would require to change the code, it can also be done by running a command in the terminal to create it directly than copying it in the *install/lib* directory. The second problem is caused by **USE_CONTEXT** being defined in *fesvr/context.h*.\ -This is due to **\_\_GLIBC\_\_** being defined because, when compiling context.cc, the flag ``-I/usr/include`` give the full repository which will cause **\_\_GLIBC\_\_** to be defined. But context.cc only needs one header inside of */usr/include*, so by giving it as an argument instead of the full directory when compiling context.cc, we can bypass this problem. +This is due to **\_\_GLIBC\_\_** being defined because, when compiling context.cc, the flag ``-I/usr/include`` is used. Giving the full directory which will cause **\_\_GLIBC\_\_** to be defined. But context.cc does not needs it, in fact, not a single file compiled does need it (for fesvr library), so we can bypass this problem by not using this flag when compiling our own fesvr shared library. A script allow to compile the shared lib, making it easier. diff --git a/sw/sw.mk b/sw/sw.mk index 6daa58199..2f93bd1bb 100644 --- a/sw/sw.mk +++ b/sw/sw.mk @@ -213,17 +213,12 @@ FESVR_LDFLAGS := -L. -Wl,--export-dynamic -L/usr/lib64 \ FESVR_LIBS := -lpthread -ldl -lpthread -FESVR_CXXFLAGS_COMMON := -MMD -MP \ +FESVR_CXXFLAGS := -MMD -MP \ -DPREFIX=\"$(FESVR_PREFIX)/\" \ -Wall -Wno-nonportable-include-path \ -g -O2 -fPIC -std=c++2a \ -iquote . -I.. -iquote ../fesvr -iquote ../riscv -iquote ../softfloat -FESVR_CXXFLAGS := $(FESVR_CXXFLAGS_COMMON) -# context need to only have pthread.h -FESVR_CXXFLAGS_CONTEXT := $(FESVR_CXXFLAGS_COMMON) - - # List of source files EXCLUDING context.cc FESVR_SRCS := \ ../fesvr/elfloader.cc \ @@ -238,7 +233,8 @@ FESVR_SRCS := \ ../fesvr/dummy.cc \ ../fesvr/option_parser.cc \ ../fesvr/term.cc \ - ../fesvr/tsi.cc + ../fesvr/tsi.cc \ + ../fesvr/context.cc build-fesvr: @mkdir -p $(FESVR_BUILD) $(FESVR_INSTALL)/lib \ @@ -248,7 +244,6 @@ build-fesvr: ( cd $(FESVR_BUILD) && \ ../configure --prefix=$(FESVR_PREFIX) --without-boost-regex && \ $(CXX) $(FESVR_CXXFLAGS) -c $(FESVR_SRCS) && \ - $(CXX) $(FESVR_CXXFLAGS_CONTEXT) -c ../fesvr/context.cc && \ $(CXX) $(FESVR_LDFLAGS) -o libfesvr.so *.o $(FESVR_LIBS) ) cp $(FESVR_BUILD)/libfesvr.so $(FESVR_INSTALL)/lib cp $(FESVR_DIR)/fesvr/*.h $(FESVR_INSTALL)/include/fesvr From c3f984de356d8b63313f326e42ecd42c60f5a45e Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Mon, 11 Aug 2025 15:26:43 +0200 Subject: [PATCH 23/26] target/sim/vcs: Fix path to fesvr --- target/sim/vcs/start.cheshire_soc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/sim/vcs/start.cheshire_soc.sh b/target/sim/vcs/start.cheshire_soc.sh index 00c708738..9c99461dd 100755 --- a/target/sim/vcs/start.cheshire_soc.sh +++ b/target/sim/vcs/start.cheshire_soc.sh @@ -51,7 +51,7 @@ fi COLOR_NC='\e[0m' COLOR_BLUE='\e[0;34m' -${VCS_BIN} ${flags} -CFLAGS "-std=c++17 -I../../../sw/deps/riscv-isa-sim/install/include" -LIBS "-rdynamic -Wl,-rpath=../../../sw/deps/riscv-isa-sim/install/lib -L../../../sw/deps/riscv-isa-sim/install/lib -lfesvr" ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log +${VCS_BIN} ${flags} -CFLAGS "-std=c++17 -I../../../../sw/deps/riscv-isa-sim/install/include" -LIBS "-rdynamic -Wl,-rpath=../../../../sw/deps/riscv-isa-sim/install/lib -L../../../../sw/deps/riscv-isa-sim/install/lib -lfesvr" ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log # Start simulation printf ${COLOR_BLUE}"${VCS_VERSION} ${VERDI_VERSION} ./simv ${pargs}"${COLOR_NC}"\n" From ee694724fdcc30b24d560c596010d551bb0131e5 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Wed, 13 Aug 2025 17:01:22 +0200 Subject: [PATCH 24/26] treewide: Fix support of libfesvr in VCS --- sw/sw.mk | 5 ++++- target/sim/vcs/start.cheshire_soc.sh | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/sw/sw.mk b/sw/sw.mk index 2f93bd1bb..0d9f3e4c2 100644 --- a/sw/sw.mk +++ b/sw/sw.mk @@ -200,7 +200,7 @@ CHS_SW_TESTS += $(CHS_SW_TEST_DUMP) ######### .PHONY: build-fesvr -FESVR_DIR := sw/deps/riscv-isa-sim +FESVR_DIR := $(CHS_ROOT)/sw/deps/riscv-isa-sim FESVR_BUILD := $(FESVR_DIR)/build FESVR_INSTALL := $(FESVR_DIR)/install FESVR_PREFIX := $(shell realpath $(FESVR_INSTALL)) @@ -249,6 +249,9 @@ build-fesvr: cp $(FESVR_DIR)/fesvr/*.h $(FESVR_INSTALL)/include/fesvr cp $(FESVR_DIR)/riscv/*.h $(FESVR_INSTALL)/include/riscv cp $(FESVR_DIR)/softfloat/*.h $(FESVR_INSTALL)/include/softfloat + mkdir $(CHS_ROOT)/target/sim/vcs/simv.daidir + ( cd $(CHS_ROOT)/target/sim/vcs/simv.daidir && \ + ln -s $(FESVR_INSTALL)/lib/libfesvr.so . ) .PHONY: build-pk diff --git a/target/sim/vcs/start.cheshire_soc.sh b/target/sim/vcs/start.cheshire_soc.sh index 9c99461dd..507987dfe 100755 --- a/target/sim/vcs/start.cheshire_soc.sh +++ b/target/sim/vcs/start.cheshire_soc.sh @@ -51,7 +51,7 @@ fi COLOR_NC='\e[0m' COLOR_BLUE='\e[0;34m' -${VCS_BIN} ${flags} -CFLAGS "-std=c++17 -I../../../../sw/deps/riscv-isa-sim/install/include" -LIBS "-rdynamic -Wl,-rpath=../../../../sw/deps/riscv-isa-sim/install/lib -L../../../../sw/deps/riscv-isa-sim/install/lib -lfesvr" ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log +${VCS_BIN} ${flags} -CFLAGS "-std=c++17 -I/scratch/ga25f6/cheshire/sw/deps/riscv-isa-sim/install/include" -L/scratch/ga25f6/cheshire/sw/deps/riscv-isa-sim/install/lib -lfesvr ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log # Start simulation printf ${COLOR_BLUE}"${VCS_VERSION} ${VERDI_VERSION} ./simv ${pargs}"${COLOR_NC}"\n" From ea08c6f1e61669c16108f8b0aab3901158f57e46 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Wed, 13 Aug 2025 17:28:37 +0200 Subject: [PATCH 25/26] target/sim/vcs: Switching to relative path for fesvr --- target/sim/vcs/start.cheshire_soc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/sim/vcs/start.cheshire_soc.sh b/target/sim/vcs/start.cheshire_soc.sh index 507987dfe..6657bf7a4 100755 --- a/target/sim/vcs/start.cheshire_soc.sh +++ b/target/sim/vcs/start.cheshire_soc.sh @@ -51,7 +51,7 @@ fi COLOR_NC='\e[0m' COLOR_BLUE='\e[0;34m' -${VCS_BIN} ${flags} -CFLAGS "-std=c++17 -I/scratch/ga25f6/cheshire/sw/deps/riscv-isa-sim/install/include" -L/scratch/ga25f6/cheshire/sw/deps/riscv-isa-sim/install/lib -lfesvr ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log +${VCS_BIN} ${flags} -CFLAGS "-std=c++17 -I../../../../sw/deps/riscv-isa-sim/install/include" -L../../../../sw/deps/riscv-isa-sim/install/lib -lfesvr ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log # Start simulation printf ${COLOR_BLUE}"${VCS_VERSION} ${VERDI_VERSION} ./simv ${pargs}"${COLOR_NC}"\n" From fcaefca403aef8ecb70614e8a3e5b538088e80a1 Mon Sep 17 00:00:00 2001 From: mtravaillard Date: Wed, 20 Aug 2025 11:46:22 +0200 Subject: [PATCH 26/26] treewide: clean fix for VCS shared lib linking issue --- sw/sw.mk | 3 --- target/sim/vcs/start.cheshire_soc.sh | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/sw/sw.mk b/sw/sw.mk index 0d9f3e4c2..b8cf59958 100644 --- a/sw/sw.mk +++ b/sw/sw.mk @@ -249,9 +249,6 @@ build-fesvr: cp $(FESVR_DIR)/fesvr/*.h $(FESVR_INSTALL)/include/fesvr cp $(FESVR_DIR)/riscv/*.h $(FESVR_INSTALL)/include/riscv cp $(FESVR_DIR)/softfloat/*.h $(FESVR_INSTALL)/include/softfloat - mkdir $(CHS_ROOT)/target/sim/vcs/simv.daidir - ( cd $(CHS_ROOT)/target/sim/vcs/simv.daidir && \ - ln -s $(FESVR_INSTALL)/lib/libfesvr.so . ) .PHONY: build-pk diff --git a/target/sim/vcs/start.cheshire_soc.sh b/target/sim/vcs/start.cheshire_soc.sh index 6657bf7a4..837e9ee48 100755 --- a/target/sim/vcs/start.cheshire_soc.sh +++ b/target/sim/vcs/start.cheshire_soc.sh @@ -51,7 +51,7 @@ fi COLOR_NC='\e[0m' COLOR_BLUE='\e[0;34m' -${VCS_BIN} ${flags} -CFLAGS "-std=c++17 -I../../../../sw/deps/riscv-isa-sim/install/include" -L../../../../sw/deps/riscv-isa-sim/install/lib -lfesvr ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log +${VCS_BIN} ${flags} -CFLAGS "-std=c++17 -I../../../../sw/deps/riscv-isa-sim/install/include" ../../../sw/deps/riscv-isa-sim/install/lib/libfesvr.so ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log # Start simulation printf ${COLOR_BLUE}"${VCS_VERSION} ${VERDI_VERSION} ./simv ${pargs}"${COLOR_NC}"\n"