From 041b644a838102a17b023f4ba4de43bbd096c7fe Mon Sep 17 00:00:00 2001 From: Arpan Suravi Prasad Date: Mon, 9 Dec 2024 09:54:09 +0100 Subject: [PATCH 1/2] [TB] Fast Preload of binary for fast debug In the existing testbench the binary preload takes a lot of time due to JTAG load. A fast preload of binary is done by forcing the relevant signals in the narrow interconnect of the memory island. The method still relies on JTAG to halt and unhalt the core whereas the preload(significant portion) is done through forcing the relevant memory signals. --- target/sim/src/tb_chimera_soc.sv | 82 ++++++++++++++++++++++++++++++- target/sim/src/vip_chimera_soc.sv | 28 +++++++++++ 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/target/sim/src/tb_chimera_soc.sv b/target/sim/src/tb_chimera_soc.sv index c35548a..ff46bf6 100644 --- a/target/sim/src/tb_chimera_soc.sv +++ b/target/sim/src/tb_chimera_soc.sv @@ -5,7 +5,9 @@ // Nicole Narr // Christopher Reinwardt -module tb_chimera_soc #( +module tb_chimera_soc + import cheshire_pkg::*; +#( /// The selected simulation configuration from the `tb_chimera_pkg`. parameter int unsigned SelectedCfg = 32'd0 ); @@ -17,11 +19,75 @@ module tb_chimera_soc #( logic [ 1:0] boot_mode; logic [ 1:0] preload_mode; bit [31:0] exit_code; + import "DPI-C" function byte read_elf(input string filename); + 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 + ); + + // Load a binary + task automatic force_write(doub_bt addr, doub_bt data); + static doub_bt write_address; + static doub_bt write_data; + write_address = addr; + write_data = data; + force fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_addr_i[1] = write_address; + force fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_req_i[1] = 1'b1; + force fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_we_i[1] = 1'b1; + force fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_wdata_i[1] = write_data; + force fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_strb_i[1] = 4'hf; + force fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_gnt_o[1] = 1'b0; + force fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_rvalid_o[1] = 1'b0; + endtask + + + task automatic fast_elf_preload(input string binary); + longint sec_addr, sec_len; + $display("[FAST PRELOAD] Preloading ELF binary: %s", binary); + if (read_elf(binary)) $fatal(1, "[JTAG] Failed to load ELF!"); + while (get_section( + sec_addr, sec_len + )) begin + byte bf[] = new[sec_len]; + $display("[FAST PRELOAD] Preloading section at 0x%h (%0d bytes)", sec_addr, sec_len); + if (read_section(sec_addr, bf, sec_len)) + $fatal(1, "[FAST PRELOAD] Failed to read ELF section!"); + @(posedge fix.vip.soc_clk); // + for (longint i = 0; i <= sec_len; i += riscv::XLEN / 8) begin + bit checkpoint = (i != 0 && i % 512 == 0); + if (checkpoint) + $display( + "[FAST PRELOAD] - %0d/%0d bytes (%0d%%)", + i, + sec_len, + i * 100 / (sec_len > 1 ? sec_len - 1 : 1) + ); + @(posedge fix.vip.soc_clk); + force_write((sec_addr + i), {bf[i+3], bf[i+2], bf[i+1], bf[i]}); + end + end + @(posedge fix.vip.soc_clk); + release fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_addr_i[1]; + release fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_req_i[1]; + release fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_we_i[1]; + release fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_wdata_i[1]; + release fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_strb_i[1]; + release fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_gnt_o[1]; + release fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_rvalid_o[1]; + // a few cycles safety margin after the end of transactions + repeat (3) @(posedge fix.vip.soc_clk); + endtask initial begin // Fetch plusargs or use safe (fail-fast) defaults if (!$value$plusargs("BOOTMODE=%d", boot_mode)) boot_mode = 0; - if (!$value$plusargs("PRELMODE=%d", preload_mode)) preload_mode = 0; + if (!$value$plusargs("PRELMODE=%d", preload_mode)) preload_mode = 3; if (!$value$plusargs("BINARY=%s", preload_elf)) preload_elf = ""; if (!$value$plusargs("IMAGE=%s", boot_hex)) boot_hex = ""; @@ -45,6 +111,18 @@ module tb_chimera_soc #( 2: begin // UART fix.vip.uart_debug_elf_run_and_wait(preload_elf, exit_code); end + 3: begin // FAST DEBUG + // Initialize JTAG + fix.vip.jtag_init(); + // Halt the core + fix.vip.jtag_elf_halt(); + // Preload the binary through FAST PRELOAD + fast_elf_preload(preload_elf); + // Unhalt the core + fix.vip.jtag_elf_unhalt(); + // Wait for the end of computation + fix.vip.jtag_wait_for_eoc(exit_code); + end default: begin $fatal(1, "Unsupported preload mode %d (reserved)!", boot_mode); end diff --git a/target/sim/src/vip_chimera_soc.sv b/target/sim/src/vip_chimera_soc.sv index 973c618..2339fa5 100644 --- a/target/sim/src/vip_chimera_soc.sv +++ b/target/sim/src/vip_chimera_soc.sv @@ -310,6 +310,34 @@ module vip_chimera_soc jtag_elf_preload(binary, entry); endtask + // Halt the core + task automatic jtag_elf_halt(); + dm::dmstatus_t status; + // Halt hart 0 + jtag_write(dm::DMControl, dm::dmcontrol_t'{haltreq: 1, dmactive: 1, default: '0}); + do jtag_dbg.read_dmi_exp_backoff(dm::DMStatus, status); while (~status.allhalted); + repeat (2) @(posedge jtag_tck); + $display("[JTAG] Halted hart 0"); + endtask + + // Unhalt the core + task automatic jtag_elf_unhalt(); + doub_bt entry; + repeat (2) @(posedge jtag_tck); + void'(get_entry(entry)); + // Repoint execution + jtag_write(dm::Data1, entry[63:32]); + jtag_write(dm::Data0, entry[31:0]); + if (riscv::XLEN == 64) begin + jtag_write(dm::Command, 32'h0033_07b1, 0, 1); + end else begin + jtag_write(dm::Command, 32'h0023_07b1, 0, 1); + end + // Resume hart 0 + jtag_write(dm::DMControl, dm::dmcontrol_t'{resumereq: 1, dmactive: 1, default: '0}); + $display("[JTAG] Resumed hart 0 from 0x%h", entry); + endtask + // Run a binary task automatic jtag_elf_run(input string binary); doub_bt entry; From 8f40e776e236793fd206d0ad3e07eb9e40518bbd Mon Sep 17 00:00:00 2001 From: Arpan Suravi Prasad Date: Thu, 12 Dec 2024 15:20:34 +0100 Subject: [PATCH 2/2] [TB] Cosmetic changes --- target/sim/src/tb_chimera_soc.sv | 12 ++++++------ target/sim/src/vip_chimera_soc.sv | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/target/sim/src/tb_chimera_soc.sv b/target/sim/src/tb_chimera_soc.sv index ff46bf6..3ca6d76 100644 --- a/target/sim/src/tb_chimera_soc.sv +++ b/target/sim/src/tb_chimera_soc.sv @@ -33,11 +33,11 @@ module tb_chimera_soc // Load a binary task automatic force_write(doub_bt addr, doub_bt data); - static doub_bt write_address; + static doub_bt write_addr; static doub_bt write_data; - write_address = addr; - write_data = data; - force fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_addr_i[1] = write_address; + write_addr = addr; + write_data = data; + force fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_addr_i[1] = write_addr; force fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_req_i[1] = 1'b1; force fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_we_i[1] = 1'b1; force fix.dut.i_memisland_domain.i_memory_island.i_memory_island.narrow_wdata_i[1] = write_data; @@ -115,11 +115,11 @@ module tb_chimera_soc // Initialize JTAG fix.vip.jtag_init(); // Halt the core - fix.vip.jtag_elf_halt(); + fix.vip.jtag_halt_hart(); // Preload the binary through FAST PRELOAD fast_elf_preload(preload_elf); // Unhalt the core - fix.vip.jtag_elf_unhalt(); + fix.vip.jtag_resume_hart(); // Wait for the end of computation fix.vip.jtag_wait_for_eoc(exit_code); end diff --git a/target/sim/src/vip_chimera_soc.sv b/target/sim/src/vip_chimera_soc.sv index 2339fa5..0fd65e6 100644 --- a/target/sim/src/vip_chimera_soc.sv +++ b/target/sim/src/vip_chimera_soc.sv @@ -311,7 +311,7 @@ module vip_chimera_soc endtask // Halt the core - task automatic jtag_elf_halt(); + task automatic jtag_halt_hart(); dm::dmstatus_t status; // Halt hart 0 jtag_write(dm::DMControl, dm::dmcontrol_t'{haltreq: 1, dmactive: 1, default: '0}); @@ -321,7 +321,7 @@ module vip_chimera_soc endtask // Unhalt the core - task automatic jtag_elf_unhalt(); + task automatic jtag_resume_hart(); doub_bt entry; repeat (2) @(posedge jtag_tck); void'(get_entry(entry));