diff --git a/target/sim/src/tb_chimera_soc.sv b/target/sim/src/tb_chimera_soc.sv index c35548a..3a61566 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,74 @@ 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 +110,22 @@ 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(); + fix.dut.i_cluster_domain.gen_clusters[0].i_chimera_cluster.boot_cluster(); + fix.dut.i_cluster_domain.gen_clusters[1].i_chimera_cluster.boot_cluster(); + fix.dut.i_cluster_domain.gen_clusters[2].i_chimera_cluster.boot_cluster(); + fix.dut.i_cluster_domain.gen_clusters[3].i_chimera_cluster.boot_cluster(); + fix.dut.i_cluster_domain.gen_clusters[4].i_chimera_cluster.boot_cluster(); + fix.vip.jtag_wait_for_eoc(exit_code); + end default: begin $fatal(1, "Unsupported preload mode %d (reserved)!", boot_mode); end @@ -63,4 +144,4 @@ module tb_chimera_soc #( $finish; end -endmodule +endmodule \ No newline at end of file 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;