Release 1.1

This commit is contained in:
Joseph Rahmeh 2020-03-04 15:36:01 -08:00
parent a49b298b4a
commit 1d2db09a2b
20 changed files with 586 additions and 257 deletions

View File

@ -1,4 +1,4 @@
# EL2 SweRV RISC-V Core<sup>TM</sup> 1.0 from Western Digital
# EL2 SweRV RISC-V Core<sup>TM</sup> 1.1 from Western Digital
This repository contains the SweRV EL2 Core<sup>TM</sup> design RTL
@ -141,12 +141,12 @@ The simulation run/build command has following generic form:
make -f $RV_ROOT/tools/Makefile [<simulator>] [debug=1] [snapshot=mybuild] [target=<target>] [TEST=<test>] [TEST_DIR=<path_to_test_dir>]
where:
```
<simulator> - can be 'verilator' (by default) 'irun' - Cadence xrun, 'vcs' - Synopsys VCS
```
<simulator> - can be 'verilator' (by default) 'irun' - Cadence xrun, 'vcs' - Synopsys VCS, 'vlog' Mentor Questa
if not provided, 'make' cleans work directory, builds verilator executable and runs a test.
debug=1 - allows VCD generation for verilator and VCS and SHM waves for irun option.
<target> - predefined CPU configurations 'default' ( by default), 'default_ahb', 'typical_pd', 'high_perf'
TEST - allows to run a C (<test>.c) or assembly (<test>.s) test, hello_world2 is run by default
TEST - allows to run a C (<test>.c) or assembly (<test>.s) test, hello_world is run by default
TEST_DIR - alternative to test source directory testbench/asm
<snapshot> - run and build executable model of custom CPU configuration, remember to provide 'snapshot' argument
for runs on custom configurations.
@ -164,28 +164,33 @@ If you want to compile a test only, you can run:
make -f $RV_ROOT/tools/Makefile program.hex TEST=<test> [TEST_DIR=/path/to/dir]
For the cmark test, the script in `$RV_ROOT/tools/calc_cmarks.pl` can be used
to extract the core-marks score by invoking that script in the run
directory.
The Makefile uses `$RV_ROOT/testbench/linker.ld` file by default to build test executable.
The Makefile uses `$RV_ROOT/testbench/link.ld` file by default to build test executable.
User can provide test specific linker file in form `<test_name>.ld` to build the test executable,
in the same directory with the test source.
User also can create a test specific makefile in form `<test_name>.makefile`, containing building instructions
how to create `program.hex` and `data.hex` files used by simulation. The private makefile should be in the same directory
as the test source.
*(`program.hex` file is loaded to instruction bus memory slave and 'data.hex' file is loaded to LSU bus memory slave and
*(`program.hex` file is loaded to instruction bus memory slave and `data.hex` file is loaded to LSU bus memory slave and
optionally to DCCM at the beginning of simulation)*.
Note: You may need to delete `program.hex` file from work directory, when run a new test.
The `$RV_ROOT/testbench/asm` directory contains following tests ready to simulate:
```
hello_world2 - default tes to run, prints Hello World message to screen and console.log
hello_world - default tes to run, prints Hello World message to screen and console.log
hello_world_dccm - the same as above, but takes the string from preloaded DCCM.
hello_world_iccm - the same as hello_world, but loads the test code to ICCM via LSU to DMA bridge and then executes
it from there. Runs on EL2 with AXI4 buses only.
cmark - coremark benchmark running with code and data in external memories
cmark_dccm - the same as above, running data and stack from DCCM (faster)
cmark_iccm - the same as above with preloaded code to ICCM.
```
The `$RV_ROOT/testbench/hex` directory contains precompiled hex files of the tests, ready for simulation in case RISCV SW tools are not installed.
**Note**: The testbench has a simple synthesizable bridge that allows you to load the ICCM via load/store instructions. This is only supported for AXI4 builds.
----
Western Digital, the Western Digital logo, G-Technology, SanDisk, Tegile, Upthere, WD, SweRV Core, SweRV ISS,
and OmniXtend are registered trademarks or trademarks of Western Digital Corporation or its affiliates in the US

View File

@ -81,7 +81,7 @@ This script can be run stand-alone by processes not running vsim
User options:
-target = {default, typical_pd, high_perf, default_ahb}
-target = {default, typical_pd, high_perf, default_ahb, lsu2dma_axi}
use default settings for one of the targets
-set=var=value
@ -191,6 +191,8 @@ my $pic_total_int;
my $top_align_iccm = 0;
my $lsu2dma = 0;
my $target = "default";
my $snapshot ;
my $build_path ;
@ -319,7 +321,10 @@ my $opensource=0;
# IDEA: is ghr at 5b the right size for el2 core
if ($target eq "default") {
if ($target eq "default") { }
elsif ($target eq "lsu2dma_axi") {
$lsu2dma = 1;
$iccm_enable = 1;
}
elsif ($target eq "typical_pd") {
print "$self: Using target \"typical_pd\"\n";
@ -339,7 +344,7 @@ elsif ($target eq "default_ahb") {
print "$self: Using target \"default_ahb\"\n";
}
else {
die "$self: ERROR! Unsupported target \"$target\". Supported are 'default', 'default_ahb', 'typical_pd', 'high_perf'\n" ;
die "$self: ERROR! Unsupported target \"$target\". Supported are 'default', 'default_ahb', 'typical_pd', 'high_perf', 'lsu2dma_axi\n" ;
}
@ -734,7 +739,8 @@ our %config = (#{{{
"iccm_only" => 'derived', # Used by design
"icache_only" => 'derived', # Used by design
"no_iccm_no_icache" => 'derived', # Used by design
"fast_interrupt_redirect" => "$fast_interrupt_redirect" # Design Parm, Overridable
"fast_interrupt_redirect" => "$fast_interrupt_redirect", # Design Parm, Overridable
"lsu2dma" => $lsu2dma, # used by design/TB for LSU to DMA bridge
},
"dccm" => {
@ -825,8 +831,23 @@ our %config = (#{{{
"pic_mpiccfg_offset" => '0x3000', # Testbench only: Offset of mpiccfg relative to pic_base_addr
"pic_meipt_offset" => '0x3004', # Testbench only: Offset of meipt relative to pic_base_addr -- deprecated
"pic_meigwctrl_offset" => '0x4000', # Testbench only: gateway control regs relative to pic_base_addr
"pic_meigwclr_offset" => '0x5000' # Testbench only: gateway clear regs relative to pic_base_addr
"pic_meigwclr_offset" => '0x5000', # Testbench only: gateway clear regs relative to pic_base_addr
"pic_meipl_mask" => '0xf',
"pic_meip_mask" => '0x0',
"pic_meie_mask" => '0x1',
"pic_mpiccfg_mask" => '0x1',
"pic_meipt_mask" => '0x0',
"pic_meigwctrl_mask" => '0x3',
"pic_meigwclr_mask" => '0x0',
"pic_meipl_count" => $pic_total_int,
"pic_meip_count" => 4,
"pic_meie_count" => $pic_total_int,
"pic_mpiccfg_count" => 1,
"pic_meipt_count" => $pic_total_int,
"pic_meigwctrl_count" => $pic_total_int,
"pic_meigwclr_count" => $pic_total_int
},
"testbench" => {
"TOP" => "tb_top",
@ -927,6 +948,7 @@ our %config = (#{{{
# need to have this be width in binary
# for now autosize to the data
our %verilog_parms = (
"lsu2dma" => '1',
"fast_interrupt_redirect" => '1',
"inst_access_enable0" => '1',
"inst_access_addr0" => '32',
@ -1987,6 +2009,32 @@ sub collect_mem_protection {
}
# Collect the memory mapped registers associated with the pic (platform
# interrup controller) to include in the whisper.json file.
sub collect_mem_mapped_regs {
my ($pic, $results) = @_;
my $default_mask = 0;
$results->{default_mask} = $default_mask;
my $addr = hex($pic->{pic_region})*256*1024*1024 + hex($pic->{pic_offset});
$results->{address} = sprintf("0x%x", $addr);
$results->{size} = sprintf("0x%x", $pic->{pic_size}*1024);
my @names = qw ( mpiccfg meipl meip meie meigwctrl meigwclr meidels );
$results->{registers} = {};
foreach my $name (@names) {
my $tag = "pic_${name}_offset";
next unless exists $pic->{$tag};
my %item;
my $offset = hex($pic->{$tag});
$offset += 4 if ($name ne 'mpiccfg' and $name ne 'meip');
$item{address} = sprintf("0x%x", $addr + $offset);
$item{mask} = $pic->{"pic_${name}_mask"};
$item{count} = $pic->{"pic_${name}_count"};
$results->{registers}{$name} = \%item;
}
}
sub dump_whisper_config{#{{{
my ($config, $path) = @_;
@ -2063,6 +2111,11 @@ sub dump_whisper_config{#{{{
# Collect pic configs.
if (exists $config{pic}) {
my %mem_mapped;
collect_mem_mapped_regs($config{pic}, \%mem_mapped);
$jh{'memory_mapped_registers'} = \%mem_mapped;
# This is now deprecated. To be removed soon.
while (my ($k, $v) = each %{$config{pic}}) {
next if $k eq 'pic_base_addr'; # derived from region and offset
if ($k eq 'pic_size') {

View File

@ -109,6 +109,7 @@ import el2_pkg::*;
// general inputs
input logic clk,
input logic rst_l,
input logic dbg_rst_l,
input logic clk_override,
input logic scan_mode
);
@ -147,6 +148,8 @@ import el2_pkg::*;
logic dmstatus_havereset_wren;
logic dmstatus_havereset_rst;
logic dmstatus_resumeack;
logic dmstatus_unavail;
logic dmstatus_running;
logic dmstatus_halted;
logic dmstatus_havereset;
@ -227,7 +230,7 @@ import el2_pkg::*;
// end clocking section
// Reset logic
assign dbg_dm_rst_l = rst_l & (dmcontrol_reg[0] | scan_mode);
assign dbg_dm_rst_l = dbg_rst_l & (dmcontrol_reg[0] | scan_mode);
assign dbg_core_rst_l = ~dmcontrol_reg[1];
// system bus register
@ -253,10 +256,10 @@ import el2_pkg::*;
assign sbcs_illegal_size = sbcs_reg[19]; // Anything bigger than 64 bits is illegal
assign sbaddress0_incr[3:0] = ({4{(sbcs_reg[19:17] == 3'b000)}} & 4'b0001) |
({4{(sbcs_reg[19:17] == 3'b001)}} & 4'b0010) |
({4{(sbcs_reg[19:17] == 3'b010)}} & 4'b0100) |
({4{(sbcs_reg[19:17] == 3'b100)}} & 4'b1000);
assign sbaddress0_incr[3:0] = ({4{(sbcs_reg[19:17] == 3'h0)}} & 4'b0001) |
({4{(sbcs_reg[19:17] == 3'h1)}} & 4'b0010) |
({4{(sbcs_reg[19:17] == 3'h2)}} & 4'b0100) |
({4{(sbcs_reg[19:17] == 3'h3)}} & 4'b1000);
// sbdata
assign sbdata0_reg_wren0 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h3c); // write data only when single read is 0
@ -287,13 +290,14 @@ import el2_pkg::*;
assign sbdata0wr_access = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h3c); // write to sbdata0 will start write command to system bus
// memory mapped registers
// dmcontrol register has only 6 bits implemented. 31: haltreq, 30: resumereq, 29: haltreset, 28: ackhavereset, 1: ndmreset, 0: dmactive.
// dmcontrol register has only 5 bits implemented. 31: haltreq, 30: resumereq, 28: ackhavereset, 1: ndmreset, 0: dmactive.
// rest all the bits are zeroed out
// dmactive flop is reset based on core rst_l, all other flops use dm_rst_l
assign dmcontrol_wren = (dmi_reg_addr == 7'h10) & dmi_reg_en & dmi_reg_wr_en;
assign dmcontrol_reg[29] = '0;
assign dmcontrol_reg[27:2] = '0;
rvdffs #(5) dmcontrolff (.din({dmi_reg_wdata[31:28],dmi_reg_wdata[1]}), .dout({dmcontrol_reg[31:28], dmcontrol_reg[1]}), .en(dmcontrol_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
rvdffs #(1) dmcontrol_dmactive_ff (.din(dmi_reg_wdata[0]), .dout(dmcontrol_reg[0]), .en(dmcontrol_wren), .rst_l(rst_l), .clk(dbg_free_clk));
rvdffs #(4) dmcontrolff (.din({dmi_reg_wdata[31:30],dmi_reg_wdata[28],dmi_reg_wdata[1]}), .dout({dmcontrol_reg[31:30], dmcontrol_reg[28], dmcontrol_reg[1]}), .en(dmcontrol_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
rvdffs #(1) dmcontrol_dmactive_ff (.din(dmi_reg_wdata[0]), .dout(dmcontrol_reg[0]), .en(dmcontrol_wren), .rst_l(dbg_rst_l), .clk(dbg_free_clk));
rvdff #(1) dmcontrol_wrenff(.din(dmcontrol_wren), .dout(dmcontrol_wren_Q), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
// dmstatus register bits that are implemented
@ -301,10 +305,12 @@ import el2_pkg::*;
// rest all the bits are zeroed out
assign dmstatus_reg[31:20] = '0;
assign dmstatus_reg[19:18] = {2{dmstatus_havereset}};
assign dmstatus_reg[15:10] = '0;
assign dmstatus_reg[15:14] = '0;
assign dmstatus_reg[7] = '1;
assign dmstatus_reg[6:4] = '0;
assign dmstatus_reg[17:16] = {2{dmstatus_resumeack}};
assign dmstatus_reg[13:12] = {2{dmstatus_unavail}};
assign dmstatus_reg[11:10] = {2{dmstatus_running}};
assign dmstatus_reg[9:8] = {2{dmstatus_halted}};
assign dmstatus_reg[3:0] = 4'h2;
@ -314,6 +320,9 @@ import el2_pkg::*;
assign dmstatus_havereset_wren = (dmi_reg_addr == 7'h10) & dmi_reg_wdata[1] & dmi_reg_en & dmi_reg_wr_en;
assign dmstatus_havereset_rst = (dmi_reg_addr == 7'h10) & dmi_reg_wdata[28] & dmi_reg_en & dmi_reg_wr_en;
assign dmstatus_unavail = dmcontrol_reg[1] | ~rst_l;
assign dmstatus_running = ~(dmstatus_unavail | dmstatus_halted);
rvdffs #(1) dmstatus_resumeack_reg (.din(dmstatus_resumeack_din), .dout(dmstatus_resumeack), .en(dmstatus_resumeack_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
rvdff #(1) dmstatus_halted_reg (.din(dec_tlu_dbg_halted & ~dec_tlu_mpc_halted_only), .dout(dmstatus_halted), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
rvdffsc #(1) dmstatus_havereset_reg (.din(1'b1), .dout(dmstatus_havereset), .en(dmstatus_havereset_wren), .clear(dmstatus_havereset_rst), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
@ -332,11 +341,8 @@ import el2_pkg::*;
assign abstractcs_error_sel1 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h17) & ~((dmi_reg_wdata[31:24] == 8'b0) | (dmi_reg_wdata[31:24] == 8'h2));
assign abstractcs_error_sel2 = core_dbg_cmd_done & core_dbg_cmd_fail;
assign abstractcs_error_sel3 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h17) & ~dmstatus_reg[9]; //(dbg_state != HALTED);
assign abstractcs_error_sel4 = (dmi_reg_addr == 7'h17) & dmi_reg_en & dmi_reg_wr_en & (dmi_reg_wdata[31:24] == 8'h2) &
( ((dmi_reg_wdata[22:20] == 3'b001) & data1_reg[0]) |
((dmi_reg_wdata[22:20] == 3'b010) & (|data1_reg[1:0])) |
dmi_reg_wdata[22] | (dmi_reg_wdata[22:20] == 3'b011)
);
assign abstractcs_error_sel4 = (dmi_reg_addr == 7'h17) & dmi_reg_en & dmi_reg_wr_en &
((dmi_reg_wdata[22:20] != 3'b010) | ((dmi_reg_wdata[31:24] == 8'h2) && (|data1_reg[1:0]))); // Only word size is allowed
assign abstractcs_error_sel5 = (dmi_reg_addr == 7'h16) & dmi_reg_en & dmi_reg_wr_en;
@ -358,7 +364,7 @@ import el2_pkg::*;
// command[16] = 1: write, 0: read
// Size - 2, Bits Not implemented: 23 (aamvirtual), 19-autoincrement, 18-postexec, 17-transfer
assign command_wren = (dmi_reg_addr == 7'h17) & dmi_reg_en & dmi_reg_wr_en & (dbg_state == HALTED);
assign command_din[31:0] = {dmi_reg_wdata[31:24],1'b0,3'b010,3'b0,dmi_reg_wdata[16:0]};
assign command_din[31:0] = {dmi_reg_wdata[31:24],1'b0,dmi_reg_wdata[22:20],3'b0,dmi_reg_wdata[16:0]};
rvdffe #(32) dmcommand_reg (.*, .din(command_din[31:0]), .dout(command_reg[31:0]), .en(command_wren), .rst_l(dbg_dm_rst_l));
// data0 reg
@ -386,18 +392,18 @@ import el2_pkg::*;
dbg_state_en = 1'b0;
abstractcs_busy_wren = 1'b0;
abstractcs_busy_din = 1'b0;
dbg_halt_req = dmcontrol_wren_Q & dmcontrol_reg[31]; // single pulse output to the core. Need to drive every time this register is written since core might be halted due to MPC
dbg_halt_req = dmcontrol_wren_Q & dmcontrol_reg[31] & ~dmcontrol_reg[1]; // single pulse output to the core. Need to drive every time this register is written since core might be halted due to MPC
dbg_resume_req = 1'b0; // single pulse output to the core
case (dbg_state)
IDLE: begin
dbg_nxtstate = (dmstatus_reg[9] | dec_tlu_mpc_halted_only) ? HALTED : HALTING; // initiate the halt command to the core
dbg_state_en = ((dmcontrol_reg[31] & ~dec_tlu_debug_mode) | dmstatus_reg[9] | dec_tlu_mpc_halted_only) & ~dmcontrol_reg[1]; // when the jtag writes the halt bit in the DM register, OR when the status indicates H
dbg_halt_req = dmcontrol_reg[31]; // only when jtag has written the halt_req bit in the control. Removed debug mode qualification during MPC changes
dbg_halt_req = dmcontrol_reg[31] & ~dmcontrol_reg[1]; // only when jtag has written the halt_req bit in the control. Removed debug mode qualification during MPC changes
end
HALTING : begin
dbg_nxtstate = HALTED; // Goto HALTED once the core sends an ACK
dbg_state_en = dmstatus_reg[9]; // core indicates halted
dbg_nxtstate = dmcontrol_reg[1] ? IDLE : HALTED; // Goto HALTED once the core sends an ACK
dbg_state_en = dmstatus_reg[9] | dmcontrol_reg[1]; // core indicates halted
end
HALTED: begin
// wait for halted to go away before send to resume. Else start of new command
@ -409,22 +415,22 @@ import el2_pkg::*;
dbg_resume_req = dbg_state_en & (dbg_nxtstate == RESUMING); // single cycle pulse to core if resuming
end
CMD_START: begin
dbg_nxtstate = (|abstractcs_reg[10:8]) ? CMD_DONE : CMD_WAIT; // new command sent to the core
dbg_state_en = dbg_cmd_valid | (|abstractcs_reg[10:8]);
dbg_nxtstate = dmcontrol_reg[1] ? IDLE : (|abstractcs_reg[10:8]) ? CMD_DONE : CMD_WAIT; // new command sent to the core
dbg_state_en = dbg_cmd_valid | (|abstractcs_reg[10:8]) | dmcontrol_reg[1];
end
CMD_WAIT: begin
dbg_nxtstate = CMD_DONE;
dbg_state_en = core_dbg_cmd_done; // go to done state for one cycle after completing current command
dbg_nxtstate = dmcontrol_reg[1] ? IDLE : CMD_DONE;
dbg_state_en = core_dbg_cmd_done | dmcontrol_reg[1]; // go to done state for one cycle after completing current command
end
CMD_DONE: begin
dbg_nxtstate = HALTED;
dbg_nxtstate = dmcontrol_reg[1] ? IDLE : HALTED;
dbg_state_en = 1'b1;
abstractcs_busy_wren = dbg_state_en; // remove the busy bit from the abstracts ( bit 12 )
abstractcs_busy_din = 1'b0;
end
RESUMING : begin
dbg_nxtstate = IDLE;
dbg_state_en = dmstatus_reg[17]; // resume ack has been updated in the dmstatus register
dbg_state_en = dmstatus_reg[17] | dmcontrol_reg[1]; // resume ack has been updated in the dmstatus register
end
default : begin
dbg_nxtstate = IDLE;
@ -450,7 +456,7 @@ import el2_pkg::*;
({32{dmi_reg_addr == 7'h3d}} & sbdata1_reg[31:0]);
rvdffs #($bits(state_t)) dbg_state_reg (.din(dbg_nxtstate), .dout({dbg_state}), .en(dbg_state_en), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
rvdffs #($bits(state_t)) dbg_state_reg (.din(dbg_nxtstate), .dout({dbg_state}), .en(dbg_state_en), .rst_l(dbg_dm_rst_l & rst_l), .clk(dbg_free_clk));
// Ack will use the power on reset only otherwise there won't be any ack until dmactive is 1
rvdffs #(32) dmi_rddata_reg (.din(dmi_reg_rdata_din[31:0]), .dout(dmi_reg_rdata[31:0]), .en(dmi_reg_en), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));

View File

@ -425,7 +425,7 @@ import el2_pkg::*;
dec_tlu_i0_valid_wb1 | dec_tlu_i0_exc_valid_wb1};
assign rv_trace_pkt.rv_i_exception_ip = {dec_tlu_int_valid_wb1, dec_tlu_i0_exc_valid_wb1};
assign rv_trace_pkt.rv_i_ecause_ip = dec_tlu_exc_cause_wb1[4:0]; // replicate across ports
assign rv_trace_pkt.rv_i_interrupt_ip = {dec_tlu_int_valid_wb1,2'b0};
assign rv_trace_pkt.rv_i_interrupt_ip = {dec_tlu_int_valid_wb1,1'b0};
assign rv_trace_pkt.rv_i_tval_ip = dec_tlu_mtval_wb1[31:0]; // replicate across ports
// end trace

View File

@ -28,6 +28,7 @@ import el2_pkg::*;
(
input logic clk,
input logic rst_l,
input logic dbg_rst_l,
input logic [31:1] rst_vec,
input logic nmi_int,
input logic [31:1] nmi_vec,
@ -38,7 +39,7 @@ import el2_pkg::*;
output logic [1:0] trace_rv_i_valid_ip,
output logic [1:0] trace_rv_i_exception_ip,
output logic [4:0] trace_rv_i_ecause_ip,
output logic [2:0] trace_rv_i_interrupt_ip,
output logic [1:0] trace_rv_i_interrupt_ip,
output logic [31:0] trace_rv_i_tval_ip,
output logic dccm_clk_override,
@ -825,10 +826,8 @@ import el2_pkg::*;
assert_fetch_indbghalt: assert #0 (~(ifu.ifc_fetch_req_f & dec.tlu.dbg_tlu_halted_f & ~dec.tlu.dcsr_single_step_running)) else $display("ERROR: Fetching in dBG halt!");
`endif
// ----------------- DEBUG END -----------------------------
assign core_rst_l = rst_l & (dbg_core_rst_l | scan_mode);
// fetch
el2_ifu #(.pt(pt)) ifu (
.rst_l(core_rst_l),
@ -1250,7 +1249,7 @@ if (pt.BUILD_AHB_LITE == 1) begin
assign trace_rv_i_valid_ip[1:0] = rv_trace_pkt.rv_i_valid_ip[1:0];
assign trace_rv_i_exception_ip[1:0] = rv_trace_pkt.rv_i_exception_ip[1:0];
assign trace_rv_i_ecause_ip[4:0] = rv_trace_pkt.rv_i_ecause_ip[4:0];
assign trace_rv_i_interrupt_ip[2:0] = rv_trace_pkt.rv_i_interrupt_ip[2:0];
assign trace_rv_i_interrupt_ip[1:0] = rv_trace_pkt.rv_i_interrupt_ip[1:0];
assign trace_rv_i_tval_ip[31:0] = rv_trace_pkt.rv_i_tval_ip[31:0];

View File

@ -28,6 +28,7 @@ import el2_pkg::*;
(
input logic clk,
input logic rst_l,
input logic dbg_rst_l,
input logic [31:1] rst_vec,
input logic nmi_int,
input logic [31:1] nmi_vec,
@ -39,7 +40,7 @@ import el2_pkg::*;
output logic [1:0] trace_rv_i_valid_ip,
output logic [1:0] trace_rv_i_exception_ip,
output logic [4:0] trace_rv_i_ecause_ip,
output logic [2:0] trace_rv_i_interrupt_ip,
output logic [1:0] trace_rv_i_interrupt_ip,
output logic [31:0] trace_rv_i_tval_ip,
// Bus signals
@ -695,7 +696,7 @@ import el2_pkg::*;
.tdoEnable (), // Test Data Output enable
// Processor Signals
.core_rst_n (core_rst_l), // Core reset, active low
.core_rst_n (dbg_rst_l), // Primary reset active low
.core_clk (clk), // Core clock
.jtag_id (jtag_id), // 32 bit JTAG ID
.rd_data (dmi_reg_rdata), // 32 bit Read data from Processor

View File

@ -89,6 +89,19 @@ import el2_pkg::*;
((addr_bank_inc[pt.ICCM_BANK_HI:2] == i) ?
addr_bank_inc[pt.ICCM_BITS-1 : pt.ICCM_BANK_INDEX_LO] :
iccm_rw_addr[pt.ICCM_BITS-1 : pt.ICCM_BANK_INDEX_LO]);
`ifdef VERILATOR
el2_ram #(.depth(1<<pt.ICCM_INDEX_BITS), .width(39)) iccm_bank (
// Primary ports
.ME(iccm_clken[i]),
.CLK(clk),
.WE(wren_bank[i]),
.ADR(addr_bank[i]),
.D(iccm_bank_wr_data[i][38:0]),
.Q(iccm_bank_dout[i][38:0])
);
`else
if (pt.ICCM_INDEX_BITS == 6 ) begin : iccm
ram_64x39 iccm_bank (
@ -212,6 +225,8 @@ import el2_pkg::*;
);
end // block: iccm
`endif
// match the redundant rows
assign sel_red1[i] = (redundant_valid[1] & (((iccm_rw_addr[pt.ICCM_BITS-1:2] == redundant_address[1][pt.ICCM_BITS-1:2]) & (iccm_rw_addr[3:2] == i)) |
((addr_bank_inc[pt.ICCM_BITS-1:2]== redundant_address[1][pt.ICCM_BITS-1:2]) & (addr_bank_inc[3:2] == i))));

View File

@ -1343,7 +1343,7 @@ assign ic_real_rd_wp_unused = (ifc_fetch_req_bf & ~ifc_iccm_access_bf & ~i
assign ic_wr_en[pt.ICACHE_NUM_WAYS-1:0] = bus_ic_wr_en[pt.ICACHE_NUM_WAYS-1:0] & {pt.ICACHE_NUM_WAYS{write_ic_16_bytes}};
assign ic_write_stall = write_ic_16_bytes & ~((((miss_state== CRIT_BYP_OK) | (miss_state==STREAM)) & ~(bus_ifu_wr_en_ff & last_beat & ~uncacheable_miss_ff)));
assign ic_write_stall = write_ic_16_bytes & ~((((miss_state== CRIT_BYP_OK) | ((miss_state==STREAM) & ~(exu_flush_final | ifu_bp_hit_taken_q_f | stream_eol_f ))) & ~(bus_ifu_wr_en_ff & last_beat & ~uncacheable_miss_ff)));
rvdff #(1) reset_all_tag_ff (.*, .clk(active_clk), .din(dec_tlu_fence_i_wb), .dout(reset_all_tags));

View File

@ -9,7 +9,7 @@ typedef struct packed {
logic [31:0] rv_i_address_ip;
logic [1:0] rv_i_exception_ip;
logic [4:0] rv_i_ecause_ip;
logic [2:0] rv_i_interrupt_ip;
logic [1:0] rv_i_interrupt_ip;
logic [31:0] rv_i_tval_ip;
} el2_trace_pkt_t;

View File

@ -257,7 +257,7 @@ import el2_pkg::*;
logic is_sideeffects_m;
logic [2:0] dma_mem_tag_d, dma_mem_tag_m;
logic ldst_nodma_mtor;
logic dma_dccm_wen;
logic dma_dccm_wen, dma_pic_wen;
logic [31:0] dma_dccm_wdata_lo, dma_dccm_wdata_hi;
logic [pt.DCCM_ECC_WIDTH-1:0] dma_dccm_wdata_ecc_lo, dma_dccm_wdata_ecc_hi;
@ -291,6 +291,7 @@ import el2_pkg::*;
assign dccm_ready = ~(dec_lsu_valid_raw_d | ldst_nodma_mtor | ld_single_ecc_error_r_ff);
assign dma_dccm_wen = dma_dccm_req & dma_mem_write & addr_in_dccm_d;
assign dma_pic_wen = dma_dccm_req & dma_mem_write & addr_in_pic_d;
assign {dma_dccm_wdata_hi[31:0], dma_dccm_wdata_lo[31:0]} = dma_mem_wdata[63:0] >> {dma_mem_addr[2:0], 3'b000}; // Shift the dma data to lower bits to make it consistent to lsu stores

View File

@ -100,7 +100,10 @@ import el2_pkg::*;
input logic [31:0] store_data_m,
input logic dma_dccm_wen,
input logic dma_pic_wen,
input logic [2:0] dma_mem_tag_m,
input logic [31:0] dma_mem_addr, // DMA address
input logic [63:0] dma_mem_wdata, // DMA write data
input logic [31:0] dma_dccm_wdata_lo,
input logic [31:0] dma_dccm_wdata_hi,
input logic [pt.DCCM_ECC_WIDTH-1:0] dma_dccm_wdata_ecc_hi, // ECC bits for the DMA wdata
@ -365,14 +368,14 @@ import el2_pkg::*;
assign dccm_data_ecc_hi_m[pt.DCCM_ECC_WIDTH-1:0] = dccm_rd_data_hi[pt.DCCM_FDATA_WIDTH-1:pt.DCCM_DATA_WIDTH];
// PIC signals. PIC ignores the lower 2 bits of address since PIC memory registers are 32-bits
assign picm_wren = lsu_pkt_r.valid & lsu_pkt_r.store & addr_in_pic_r & lsu_commit_r;
assign picm_wren = (lsu_pkt_r.valid & lsu_pkt_r.store & addr_in_pic_r & lsu_commit_r) | dma_pic_wen;
assign picm_rden = lsu_pkt_d.valid & lsu_pkt_d.load & addr_in_pic_d;
assign picm_mken = lsu_pkt_d.valid & lsu_pkt_d.store & addr_in_pic_d; // Get the mask for stores
assign picm_rdaddr[31:0] = pt.PIC_BASE_ADDR | {17'b0,lsu_addr_d[14:0]};
assign picm_rdaddr[31:0] = pt.PIC_BASE_ADDR | {{32-pt.PIC_BITS{1'b0}},lsu_addr_d[pt.PIC_BITS-1:0]};
assign picm_wraddr[31:0] = pt.PIC_BASE_ADDR | {{32-pt.PIC_BITS{1'b0}},lsu_addr_r[pt.PIC_BITS-1:0]};
assign picm_wraddr[31:0] = pt.PIC_BASE_ADDR | {{32-pt.PIC_BITS{1'b0}},(dma_pic_wen ? dma_mem_addr[pt.PIC_BITS-1:0] : lsu_addr_r[pt.PIC_BITS-1:0])};
assign picm_wr_data[31:0] = store_datafn_lo_r[31:0];
assign picm_wr_data[31:0] = dma_pic_wen ? dma_mem_wdata[31:0] : store_datafn_lo_r[31:0];
assign picm_mask_data_m[31:0] = picm_rd_data_m[31:0];
assign picm_rd_data_m[63:0] = {picm_rd_data[31:0],picm_rd_data[31:0]};

Binary file not shown.

View File

@ -1,5 +1,6 @@
#include "defines.h"
#define ITERATIONS 1
extern int STACK;
void main();
@ -1198,7 +1199,9 @@ MAIN_RETURN_TYPE main(int argc, char *argv[]) {
#else
ee_printf("Total time (secs): %d\n",time_in_secs(total_time));
if (time_in_secs(total_time) > 0)
ee_printf("Iterations/Sec : %d\n",default_num_contexts*results[0].iterations/time_in_secs(total_time));
// ee_printf("Iterations/Sec : %d\n",default_num_contexts*results[0].iterations/time_in_secs(total_time));
ee_printf("Iterat/Sec/MHz : %d.%d\n",1000*default_num_contexts*results[0].iterations/time_in_secs(total_time),
100000*default_num_contexts*results[0].iterations/time_in_secs(total_time) % 100);
#endif
if (time_in_secs(total_time) < 10) {
ee_printf("ERROR! Must execute for at least 10 secs for a valid result!\n");
@ -2080,8 +2083,7 @@ ee_u8 check_data_types() {
volatile ee_s32 seed2_volatile=0x8;
volatile ee_s32 seed3_volatile=0x8;
#endif
// volatile ee_s32 seed4_volatile=ITERATIONS;
volatile ee_s32 seed4_volatile=1;
volatile ee_s32 seed4_volatile=ITERATIONS;
volatile ee_s32 seed5_volatile=0;
/* Porting : Timing functions
How to capture time and convert to seconds must be ported to whatever is supported by the platform.
@ -2102,7 +2104,9 @@ ee_u8 check_data_types() {
#define MYTIMEDIFF(fin,ini) ((fin)-(ini))
#define TIMER_RES_DIVIDER 1
#define SAMPLE_TIME_IMPLEMENTATION 1
#define EE_TICKS_PER_SEC (NSECS_PER_SEC / TIMER_RES_DIVIDER)
//#define EE_TICKS_PER_SEC (NSECS_PER_SEC / TIMER_RES_DIVIDER)
#define EE_TICKS_PER_SEC 1000
/** Define Host specific (POSIX), or target specific global time variables. */
static CORETIMETYPE start_time_val, stop_time_val;

View File

@ -1,67 +1,71 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2019 Western Digital Corporation or its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Assembly code for Hello World
// Not using only ALU ops for creating the string
#include "defines.h"
#define STDOUT 0xd0580000
// Code to execute
.section .text
.global _start
_start:
csrrw x2, 0xb02, x3
// Clear minstret
csrw minstret, zero
csrw minstreth, zero
// Set up MTVEC - not expecting to use it though
li x1, RV_ICCM_SADR
csrw mtvec, x1
lui x5, 974848
ori x5, x5, 0
csrrw x2, 0x305, x5
// Enable Caches in MRAC
li x1, 0x5f555555
csrw 0x7c0, x1
// Load string from hw_data
// and write to stdout address
lui x6, 382293
ori x6, x6, 1365
csrrw x1, 0x7c0, x6
li x3, STDOUT
la x4, hw_data
loop:
lb x5, 0(x4)
sb x5, 0(x3)
addi x4, x4, 1
bnez x5, loop
// Write 0xff to STDOUT for TB to termiate test.
_finish:
li x3, STDOUT
addi x5, x0, 0xff
sb x5, 0(x3)
beq x0, x0, _finish
.rept 100
nop
.endr
lui x5, 0
ori x5, x5, 0
csrrw x2, 0x7f8, x5
lui x5, 0
ori x5, x5, 0
csrrw x2, 0x7f9, x5
addi x0, x0, 0
lui x11, 853376
ori x9, x0, 'H'
sw x9, 0 (x11)
ori x9, x0, 'E'
sw x9, 0 (x11)
ori x9, x0, 'L'
sw x9, 0 (x11)
sw x9, 0 (x11)
ori x9, x0, 'O'
sw x9, 0 (x11)
ori x9, x0, ' '
sw x9, 0 (x11)
addi x9, x0, 'W'
sw x9, 0 (x11)
ori x9, x0, 'O'
sw x9, 0 (x11)
ori x9, x0, 'R'
sw x9, 0 (x11)
ori x9, x0, 'L'
sw x9, 0 (x11)
ori x9, x0, 'D'
sw x9, 0 (x11)
ori x9, x0, '!'
sw x9, 0 (x11)
ori x9, x0, 255
sw x9, 0 (x11)
addi x1,x0,0
finish:
addi x1,x1,1
jal x0, finish;
addi x0,x0,0
addi x0,x0,0
addi x0,x0,0
addi x0,x0,0
.data
hw_data:
.ascii "----------------------------------\n"
.ascii "Hello World from SweRV EL2 @WDC !!\n"
.ascii "----------------------------------\n"
.byte 0

View File

@ -5,7 +5,7 @@ ENTRY(_start)
SECTIONS {
.text : { *(.text*) }
_end = .;
. = 0xfff8;
. = 0x1fff8;
.data.ctl : { LONG(0xf0040000); LONG(STACK) }
. = 0xf0040000;
.data : AT(0x10000) { *(.*data) *(.rodata*) STACK = ALIGN(16) + 0x8000;}

View File

@ -1 +1 @@
hello_world2.s
hello_world.s

View File

@ -1,8 +1,4 @@
+libext+.v+.sv
//-incdir $RV_ROOT/design/lib
//-incdir $RV_ROOT/design/include
//-incdir $RV_ROOT/design/dmi
//-incdir $SYNOPSYS_SYN_ROOT/dw/sim_ver
//-y $SYNOPSYS_SYN_ROOT/dw/sim_ver
$RV_ROOT/design/el2_swerv_wrapper.sv
$RV_ROOT/design/el2_mem.sv
@ -24,7 +20,6 @@ $RV_ROOT/design/dec/el2_dec_tlu_ctl.sv
$RV_ROOT/design/dec/el2_dec_trigger.sv
$RV_ROOT/design/dec/el2_dec.sv
$RV_ROOT/design/exu/el2_exu_alu_ctl.sv
//$RV_ROOT/design/exu/el2_exu_br_ctl.sv
$RV_ROOT/design/exu/el2_exu_mul_ctl.sv
$RV_ROOT/design/exu/el2_exu_div_ctl.sv
$RV_ROOT/design/exu/el2_exu.sv
@ -47,6 +42,4 @@ $RV_ROOT/design/lib/el2_lib.sv
-v $RV_ROOT/design/lib/beh_lib.sv
-v $RV_ROOT/design/lib/mem_lib.sv
-y $RV_ROOT/design/lib
//$RV_ROOT/design/lib/ahb_to_svci.sv
//$RV_ROOT/design/lib/ahb_to_axi4.sv
//$RV_ROOT/design/lib/axi4_to_ahb.sv
-v $RV_ROOT/testbench/axi_lsu_dma_bridge.sv

View File

@ -13,64 +13,62 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
`ifndef VERILATOR
module tb_top;
`else
`ifdef VERILATOR
module tb_top ( input bit core_clk );
`endif
`ifndef VERILATOR
`else
module tb_top;
bit core_clk;
`endif
logic rst_l;
logic porst_l;
logic nmi_int;
logic [31:0] reset_vector;
logic [31:0] nmi_vector;
logic [31:1] jtag_id;
logic [31:0] ic_haddr ;
logic [2:0] ic_hburst ;
logic ic_hmastlock ;
logic [3:0] ic_hprot ;
logic [2:0] ic_hsize ;
logic [1:0] ic_htrans ;
logic ic_hwrite ;
logic [63:0] ic_hrdata ;
logic ic_hready ;
logic ic_hresp ;
logic [31:0] ic_haddr;
logic [2:0] ic_hburst;
logic ic_hmastlock;
logic [3:0] ic_hprot;
logic [2:0] ic_hsize;
logic [1:0] ic_htrans;
logic ic_hwrite;
logic [63:0] ic_hrdata;
logic ic_hready;
logic ic_hresp;
logic [31:0] lsu_haddr ;
logic [2:0] lsu_hburst ;
logic lsu_hmastlock ;
logic [3:0] lsu_hprot ;
logic [2:0] lsu_hsize ;
logic [1:0] lsu_htrans ;
logic lsu_hwrite ;
logic [63:0] lsu_hrdata ;
logic [63:0] lsu_hwdata ;
logic lsu_hready ;
logic lsu_hresp ;
logic [31:0] lsu_haddr;
logic [2:0] lsu_hburst;
logic lsu_hmastlock;
logic [3:0] lsu_hprot;
logic [2:0] lsu_hsize;
logic [1:0] lsu_htrans;
logic lsu_hwrite;
logic [63:0] lsu_hrdata;
logic [63:0] lsu_hwdata;
logic lsu_hready;
logic lsu_hresp;
logic [31:0] sb_haddr ;
logic [2:0] sb_hburst ;
logic sb_hmastlock ;
logic [3:0] sb_hprot ;
logic [2:0] sb_hsize ;
logic [1:0] sb_htrans ;
logic sb_hwrite ;
logic [31:0] sb_haddr;
logic [2:0] sb_hburst;
logic sb_hmastlock;
logic [3:0] sb_hprot;
logic [2:0] sb_hsize;
logic [1:0] sb_htrans;
logic sb_hwrite;
logic [63:0] sb_hrdata ;
logic [63:0] sb_hwdata ;
logic sb_hready ;
logic sb_hresp ;
logic [63:0] sb_hrdata;
logic [63:0] sb_hwdata;
logic sb_hready;
logic sb_hresp;
logic [31:0] trace_rv_i_insn_ip;
logic [31:0] trace_rv_i_address_ip;
logic [1:0] trace_rv_i_valid_ip;
logic [1:0] trace_rv_i_exception_ip;
logic [4:0] trace_rv_i_ecause_ip;
logic [2:0] trace_rv_i_interrupt_ip;
logic [1:0] trace_rv_i_interrupt_ip;
logic [31:0] trace_rv_i_tval_ip;
logic o_debug_mode_status;
@ -82,10 +80,10 @@ module tb_top ( input bit core_clk );
logic o_cpu_run_ack;
logic mailbox_write;
logic [63:0] dma_hrdata ;
logic [63:0] dma_hwdata ;
logic dma_hready ;
logic dma_hresp ;
logic [63:0] dma_hrdata;
logic [63:0] dma_hwdata;
logic dma_hready;
logic dma_hresp;
logic mpc_debug_halt_req;
logic mpc_debug_run_req;
@ -94,7 +92,7 @@ module tb_top ( input bit core_clk );
logic mpc_debug_run_ack;
logic debug_brkpt_status;
bit [31:0] cycleCnt ;
bit [31:0] cycleCnt;
logic mailbox_data_val;
wire dma_hready_out;
@ -286,6 +284,27 @@ module tb_top ( input bit core_clk );
wire [1:0] dma_axi_rresp;
wire dma_axi_rlast;
wire lmem_axi_arvalid;
wire lmem_axi_arready;
wire lmem_axi_rvalid;
wire [`RV_LSU_BUS_TAG-1:0] lmem_axi_rid;
wire [1:0] lmem_axi_rresp;
wire [63:0] lmem_axi_rdata;
wire lmem_axi_rlast;
wire lmem_axi_rready;
wire lmem_axi_awvalid;
wire lmem_axi_awready;
wire lmem_axi_wvalid;
wire lmem_axi_wready;
wire [1:0] lmem_axi_bresp;
wire lmem_axi_bvalid;
wire [`RV_LSU_BUS_TAG-1:0] lmem_axi_bid;
wire lmem_axi_bready;
`endif
wire[63:0] WriteData;
@ -329,18 +348,18 @@ module tb_top ( input bit core_clk );
wb_valid[0] <= rvtop.swerv.dec.dec_i0_wen_r;
wb_dest[0] <= rvtop.swerv.dec.dec_i0_waddr_r;
wb_data[0] <= rvtop.swerv.dec.dec_i0_wdata_r;
if (rvtop.trace_rv_i_valid_ip !== 0) begin
$fwrite(tp,"%b,%h,%h,%0h,%0h,3,%b,%h,%h,%b\n", rvtop.trace_rv_i_valid_ip, 0, trace_rv_i_address_ip,
if (trace_rv_i_valid_ip !== 0) begin
$fwrite(tp,"%b,%h,%h,%0h,%0h,3,%b,%h,%h,%b\n", trace_rv_i_valid_ip, 0, trace_rv_i_address_ip,
0, trace_rv_i_insn_ip,trace_rv_i_exception_ip,trace_rv_i_ecause_ip,
trace_rv_i_tval_ip,trace_rv_i_interrupt_ip);
// Basic trace - no exception register updates
// #1 0 ee000000 b0201073 c 0b02 00000000
for (int i=0; i<1; i++)
if (rvtop.trace_rv_i_valid_ip[i]==1) begin
if (trace_rv_i_valid_ip[i]==1) begin
commit_count++;
$fwrite (el, "%10d : %6s 0 %h %h %s\n", cycleCnt, $sformatf("#%0d",commit_count),
trace_rv_i_address_ip[31+i*32 -:32], trace_rv_i_insn_ip[31+i*32-:32],
wb_dest[i] !=0 ? $sformatf("r%0d=%h", wb_dest[i], wb_data[i]) : "");
(wb_dest[i] !=0 && wb_data[0])? $sformatf("r%0d=%h", wb_dest[i], wb_data[i]) : "");
end
end
end
@ -363,6 +382,7 @@ module tb_top ( input bit core_clk );
fd = $fopen("console.log","w");
commit_count = 0;
preload_dccm();
preload_iccm();
`ifndef VERILATOR
if($test$plusargs("dumpon")) $dumpvars;
@ -372,12 +392,14 @@ module tb_top ( input bit core_clk );
assign rst_l = cycleCnt > 5;
assign porst_l = cycleCnt > 2;
//=========================================================================-
// RTL instance
//=========================================================================-
el2_swerv_wrapper rvtop (
.rst_l ( rst_l ),
.dbg_rst_l ( porst_l ),
.clk ( core_clk ),
.rst_vec ( reset_vector[31:1]),
.nmi_int ( nmi_int ),
@ -590,40 +612,40 @@ el2_swerv_wrapper rvtop (
//-------------------------- DMA AXI signals--------------------------
// AXI Write Channels
.dma_axi_awvalid (1'b0),
.dma_axi_awvalid (dma_axi_awvalid),
.dma_axi_awready (dma_axi_awready),
.dma_axi_awid (dma_axi_awid),
.dma_axi_awaddr (dma_axi_awaddr),
.dma_axi_awsize (dma_axi_awsize),
.dma_axi_awprot (dma_axi_awprot),
.dma_axi_awlen (dma_axi_awlen),
.dma_axi_awburst (dma_axi_awburst),
.dma_axi_awid ('0),
.dma_axi_awaddr (lsu_axi_awaddr),
.dma_axi_awsize (lsu_axi_awsize),
.dma_axi_awprot (lsu_axi_awprot),
.dma_axi_awlen (lsu_axi_awlen),
.dma_axi_awburst (lsu_axi_awburst),
.dma_axi_wvalid (1'b0),
.dma_axi_wvalid (dma_axi_wvalid),
.dma_axi_wready (dma_axi_wready),
.dma_axi_wdata (dma_axi_wdata),
.dma_axi_wstrb (dma_axi_wstrb),
.dma_axi_wlast (dma_axi_wlast),
.dma_axi_wdata (lsu_axi_wdata),
.dma_axi_wstrb (lsu_axi_wstrb),
.dma_axi_wlast (lsu_axi_wlast),
.dma_axi_bvalid (dma_axi_bvalid),
.dma_axi_bready (1'b0),
.dma_axi_bready (dma_axi_bready),
.dma_axi_bresp (dma_axi_bresp),
.dma_axi_bid (dma_axi_bid),
.dma_axi_bid (),
.dma_axi_arvalid (1'b0),
.dma_axi_arvalid (dma_axi_arvalid),
.dma_axi_arready (dma_axi_arready),
.dma_axi_arid (dma_axi_arid),
.dma_axi_araddr (dma_axi_araddr),
.dma_axi_arsize (dma_axi_arsize),
.dma_axi_arprot (dma_axi_arprot),
.dma_axi_arlen (dma_axi_arlen),
.dma_axi_arburst (dma_axi_arburst),
.dma_axi_arid ('0),
.dma_axi_araddr (lsu_axi_araddr),
.dma_axi_arsize (lsu_axi_arsize),
.dma_axi_arprot (lsu_axi_arprot),
.dma_axi_arlen (lsu_axi_arlen),
.dma_axi_arburst (lsu_axi_arburst),
.dma_axi_rvalid (dma_axi_rvalid),
.dma_axi_rready (1'b0),
.dma_axi_rid (dma_axi_rid),
.dma_axi_rready (dma_axi_rready),
.dma_axi_rid (),
.dma_axi_rdata (dma_axi_rdata),
.dma_axi_rresp (dma_axi_rresp),
.dma_axi_rlast (dma_axi_rlast),
@ -768,23 +790,23 @@ defparam lmem.TAGW =`RV_LSU_BUS_TAG;
axi_slv lmem(
.aclk(core_clk),
.rst_l(rst_l),
.arvalid(lsu_axi_arvalid),
.arready(lsu_axi_arready),
.arvalid(lmem_axi_arvalid),
.arready(lmem_axi_arready),
.araddr(lsu_axi_araddr),
.arid(lsu_axi_arid),
.arlen(lsu_axi_arlen),
.arburst(lsu_axi_arburst),
.arsize(lsu_axi_arsize),
.rvalid(lsu_axi_rvalid),
.rready(lsu_axi_rready),
.rdata(lsu_axi_rdata),
.rresp(lsu_axi_rresp),
.rid(lsu_axi_rid),
.rlast(lsu_axi_rlast),
.rvalid(lmem_axi_rvalid),
.rready(lmem_axi_rready),
.rdata(lmem_axi_rdata),
.rresp(lmem_axi_rresp),
.rid(lmem_axi_rid),
.rlast(lmem_axi_rlast),
.awvalid(lsu_axi_awvalid),
.awready(lsu_axi_awready),
.awvalid(lmem_axi_awvalid),
.awready(lmem_axi_awready),
.awaddr(lsu_axi_awaddr),
.awid(lsu_axi_awid),
.awlen(lsu_axi_awlen),
@ -793,25 +815,145 @@ axi_slv lmem(
.wdata(lsu_axi_wdata),
.wstrb(lsu_axi_wstrb),
.wvalid(lsu_axi_wvalid),
.wready(lsu_axi_wready),
.wvalid(lmem_axi_wvalid),
.wready(lmem_axi_wready),
.bvalid(lsu_axi_bvalid),
.bready(lsu_axi_bready),
.bresp(lsu_axi_bresp),
.bid(lsu_axi_bid)
.bvalid(lmem_axi_bvalid),
.bready(lmem_axi_bready),
.bresp(lmem_axi_bresp),
.bid(lmem_axi_bid)
);
axi_lsu_dma_bridge # (`RV_LSU_BUS_TAG,`RV_LSU_BUS_TAG ) bridge(
.clk(core_clk),
.reset_l(rst_l),
.m_arvalid(lsu_axi_arvalid),
.m_arid(lsu_axi_arid),
.m_araddr(lsu_axi_araddr),
.m_arready(lsu_axi_arready),
.m_rvalid(lsu_axi_rvalid),
.m_rready(lsu_axi_rready),
.m_rdata(lsu_axi_rdata),
.m_rid(lsu_axi_rid),
.m_rresp(lsu_axi_rresp),
.m_rlast(lsu_axi_rlast),
.m_awvalid(lsu_axi_awvalid),
.m_awid(lsu_axi_awid),
.m_awaddr(lsu_axi_awaddr),
.m_awready(lsu_axi_awready),
.m_wvalid(lsu_axi_wvalid),
.m_wready(lsu_axi_wready),
.m_bresp(lsu_axi_bresp),
.m_bvalid(lsu_axi_bvalid),
.m_bid(lsu_axi_bid),
.m_bready(lsu_axi_bready),
.s0_arvalid(lmem_axi_arvalid),
.s0_arready(lmem_axi_arready),
.s0_rvalid(lmem_axi_rvalid),
.s0_rid(lmem_axi_rid),
.s0_rresp(lmem_axi_rresp),
.s0_rdata(lmem_axi_rdata),
.s0_rlast(lmem_axi_rlast),
.s0_rready(lmem_axi_rready),
.s0_awvalid(lmem_axi_awvalid),
.s0_awready(lmem_axi_awready),
.s0_wvalid(lmem_axi_wvalid),
.s0_wready(lmem_axi_wready),
.s0_bresp(lmem_axi_bresp),
.s0_bvalid(lmem_axi_bvalid),
.s0_bid(lmem_axi_bid),
.s0_bready(lmem_axi_bready),
.s1_arvalid(dma_axi_arvalid),
.s1_arready(dma_axi_arready),
.s1_rvalid(dma_axi_rvalid),
.s1_rresp(dma_axi_rresp),
.s1_rdata(dma_axi_rdata),
.s1_rlast(dma_axi_rlast),
.s1_rready(dma_axi_rready),
.s1_awvalid(dma_axi_awvalid),
.s1_awready(dma_axi_awready),
.s1_wvalid(dma_axi_wvalid),
.s1_wready(dma_axi_wready),
.s1_bresp(dma_axi_bresp),
.s1_bvalid(dma_axi_bvalid),
.s1_bready(dma_axi_bready)
);
`endif
task preload_iccm;
bit[31:0] data;
bit[31:0] addr, eaddr, saddr, faddr;
int adr;
/*
addresses:
0xffec - ICCM start address to load
0xfff0 - ICCM end address to load
0xfff4 - imem start address
*/
addr = 'hffec;
saddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]};
if ( (saddr < `RV_ICCM_SADR) || (saddr > `RV_ICCM_EADR)) return;
`ifndef RV_ICCM_ENABLE
$display("********************************************************");
$display("ICCM preload: there is no ICCM in SweRV, terminating !!!");
$display("********************************************************");
$finish;
`endif
init_iccm;
addr = 'hfff0;
eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]};
addr = 'hfff4;
faddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]};
$display("ICCM pre-load from %h to %h", saddr, eaddr);
for(addr= saddr; addr <= eaddr; addr+=4) begin
adr = faddr & 'hffff;
data = {imem.mem[adr+3],imem.mem[adr+2],imem.mem[adr+1],imem.mem[adr]};
slam_iccm_ram(addr, data == 0 ? 0 : {riscv_ecc32(data),data});
faddr+=4;
end
endtask
task preload_dccm;
bit[31:0] data;
bit[31:0] addr, eaddr;
int adr;
/*
addresses:
0xfff8 - DCCM start address to load
0xfffc - ICCM end address to load
0x0 - lmem start addres to load from
*/
addr = 'hfff8;
eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]};
if (eaddr != `RV_DCCM_SADR) return;
`ifndef RV_DCCM_ENABLE
$display("********************************************************");
$display("DCCM preload: there is no DCCM in SweRV, terminating !!!");
$display("********************************************************");
$finish;
`endif
addr = 'hfffc;
eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]};
$display("DCCM pre-load from %h to %h", `RV_DCCM_SADR, eaddr);
@ -824,16 +966,20 @@ end
endtask
`define ICCM_PATH `RV_TOP.mem.iccm.iccm
`ifdef VERILATOR
`define DRAM(bank) rvtop.mem.Gen_dccm_enable.dccm.mem_bank[bank].ram.ram_core
`define DRAM(bk) rvtop.mem.Gen_dccm_enable.dccm.mem_bank[bk].ram.ram_core
`define IRAM(bk) `ICCM_PATH.mem_bank[bk].iccm_bank.ram_core
`else
`define DRAM(bank) rvtop.mem.Gen_dccm_enable.dccm.mem_bank[bank].dccm.dccm_bank.ram_core
`define DRAM(bk) rvtop.mem.Gen_dccm_enable.dccm.mem_bank[bk].dccm.dccm_bank.ram_core
`define IRAM(bk) `ICCM_PATH.mem_bank[bk].iccm.iccm_bank.ram_core
`endif
task slam_dccm_ram(input [31:0] addr, input[38:0] data);
int bank, indx;
bank = get_dccm_bank(addr, indx);
//`ifndef VERILATOR
`ifdef RV_DCCM_ENABLE
case(bank)
0: `DRAM(0)[indx] = data;
1: `DRAM(1)[indx] = data;
@ -850,7 +996,82 @@ case(bank)
7: `DRAM(7)[indx] = data;
`endif
endcase
//`endif
`endif
//$display("Writing bank %0d indx=%0d A=%h, D=%h",bank, indx, addr, data);
endtask
task slam_iccm_ram( input[31:0] addr, input[38:0] data);
int bank, idx;
bank = get_iccm_bank(addr, idx);
`ifdef RV_ICCM_ENABLE
case(bank) // {
0: `IRAM(0)[idx] = data;
1: `IRAM(1)[idx] = data;
`ifdef RV_ICCM_NUM_BANKS_4
2: `IRAM(2)[idx] = data;
3: `IRAM(3)[idx] = data;
`endif
`ifdef RV_ICCM_NUM_BANKS_8
2: `IRAM(2)[idx] = data;
3: `IRAM(3)[idx] = data;
4: `IRAM(4)[idx] = data;
5: `IRAM(5)[idx] = data;
6: `IRAM(6)[idx] = data;
7: `IRAM(7)[idx] = data;
`endif
`ifdef RV_ICCM_NUM_BANKS_16
2: `IRAM(2)[idx] = data;
3: `IRAM(3)[idx] = data;
4: `IRAM(4)[idx] = data;
5: `IRAM(5)[idx] = data;
6: `IRAM(6)[idx] = data;
7: `IRAM(7)[idx] = data;
8: `IRAM(8)[idx] = data;
9: `IRAM(9)[idx] = data;
10: `IRAM(10)[idx] = data;
11: `IRAM(11)[idx] = data;
12: `IRAM(12)[idx] = data;
13: `IRAM(13)[idx] = data;
14: `IRAM(14)[idx] = data;
15: `IRAM(15)[idx] = data;
`endif
endcase // }
`endif
endtask
task init_iccm;
`ifdef RV_ICCM_ENABLE
`IRAM(0) = '{default:39'h0};
`IRAM(1) = '{default:39'h0};
`ifdef RV_ICCM_NUM_BANKS_4
`IRAM(2) = '{default:39'h0};
`IRAM(3) = '{default:39'h0};
`endif
`ifdef RV_ICCM_NUM_BANKS_8
`IRAM(4) = '{default:39'h0};
`IRAM(5) = '{default:39'h0};
`IRAM(6) = '{default:39'h0};
`IRAM(7) = '{default:39'h0};
`endif
`ifdef RV_ICCM_NUM_BANKS_16
`IRAM(4) = '{default:39'h0};
`IRAM(5) = '{default:39'h0};
`IRAM(6) = '{default:39'h0};
`IRAM(7) = '{default:39'h0};
`IRAM(8) = '{default:39'h0};
`IRAM(9) = '{default:39'h0};
`IRAM(10) = '{default:39'h0};
`IRAM(11) = '{default:39'h0};
`IRAM(12) = '{default:39'h0};
`IRAM(13) = '{default:39'h0};
`IRAM(14) = '{default:39'h0};
`IRAM(15) = '{default:39'h0};
`endif
`endif
endtask
@ -866,7 +1087,7 @@ synd[6] = ^{data, synd[5:0]};
return synd;
endfunction
function int get_dccm_bank(input int addr, output int bank_idx);
function int get_dccm_bank(input[31:0] addr, output int bank_idx);
`ifdef RV_DCCM_NUM_BANKS_2
bank_idx = int'(addr[`RV_DCCM_BITS-1:3]);
return int'( addr[2]);
@ -879,4 +1100,21 @@ function int get_dccm_bank(input int addr, output int bank_idx);
`endif
endfunction
function int get_iccm_bank(input[31:0] addr, output int bank_idx);
`ifdef RV_DCCM_NUM_BANKS_2
bank_idx = int'(addr[`RV_DCCM_BITS-1:3]);
return int'( addr[2]);
`elsif RV_ICCM_NUM_BANKS_4
bank_idx = int'(addr[`RV_ICCM_BITS-1:4]);
return int'(addr[3:2]);
`elsif RV_ICCM_NUM_BANKS_8
bank_idx = int'(addr[`RV_ICCM_BITS-1:5]);
return int'( addr[4:2]);
`elsif RV_ICCM_NUM_BANKS_16
bank_idx = int'(addr[`RV_ICCM_BITS-1:6]);
return int'( addr[5:2]);
`endif
endfunction
endmodule

View File

@ -32,38 +32,32 @@ double sc_time_stamp () {
int main(int argc, char** argv) {
std::cout << "\nVerilatorTB: Start of sim\n" << std::endl;
// Check for +dumpon and remove it from argv
bool dumpWaves = false;
int newArgc = 0;
for (int i = 0; i < argc; ++i)
if (strcmp(argv[i], "+dumpon") == 0)
dumpWaves = true;
else
argv[newArgc++] = argv[i];
argc = newArgc;
Verilated::commandArgs(argc, argv);
Vtb_top* tb = new Vtb_top;
// init trace dump
Verilated::traceEverOn(true);
VerilatedVcdC* tfp = new VerilatedVcdC;
tb->trace (tfp, 24);
if (dumpWaves)
tfp->open ("sim.vcd");
VerilatedVcdC* tfp = NULL;
#if VM_TRACE
Verilated::traceEverOn(true);
tfp = new VerilatedVcdC;
tb->trace (tfp, 24);
tfp->open ("sim.vcd");
#endif
// Simulate
while(!Verilated::gotFinish()){
if (dumpWaves)
tfp->dump (main_time);
#if VM_TRACE
tfp->dump (main_time);
#endif
main_time += 5;
tb->core_clk = !tb->core_clk;
tb->eval();
}
if (dumpWaves)
tfp->close();
#if VM_TRACE
tfp->close();
#endif
std::cout << "\nVerilatorTB: End of sim" << std::endl;
exit(EXIT_SUCCESS);

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2019 Western Digital Corporation or its affiliates.
# Copyright 2020 Western Digital Corporation or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -27,21 +27,24 @@ snapshot = $(target)
SWERV_CONFIG = ${RV_ROOT}/configs/swerv.config
IRUN = xrun
VCS = vcs
VLOG = qverilog
VERILATOR = verilator
GCC_PREFIX = riscv64-unknown-elf
BUILD_DIR = snapshots/${snapshot}
TBDIR = ${RV_ROOT}/testbench
# Define test name
TEST = hello_world2
TEST = hello_world
# Define test name
TEST_DIR = ${RV_ROOT}/testbench/asm
TEST_DIR = ${TBDIR}/asm
HEX_DIR = ${TBDIR}/hex
ifdef debug
DEBUG_PLUS = +dumpon
IRUN_DEBUG = -access +rc
IRUN_DEBUG_RUN = -input ${RV_ROOT}/testbench/input.tcl
VERILATOR_DEBUG = --trace
endif
# provide specific link file
@ -73,18 +76,18 @@ all: clean verilator
clean:
rm -rf *.log *.s *.hex *.dis *.tbl irun* vcs* simv* snapshots swerv* \
verilator* *.exe obj* *.o ucli.key vc_hdrs.h csrc *.csv
verilator* *.exe obj* *.o ucli.key vc_hdrs.h csrc *.csv work
# If define files do not exist, then run swerv.config.
${BUILD_DIR}/defines.h :
BUILD_PATH=${BUILD_DIR} ${RV_ROOT}/configs/swerv.config -target=$(target)
BUILD_PATH=${BUILD_DIR} ${RV_ROOT}/configs/swerv.config -target=$(target) $(CONF_PARAMS)
verilator-build: ${TBFILES} ${BUILD_DIR}/defines.h test_tb_top.cpp
echo '`undef ASSERT_ON' >> ${BUILD_DIR}/common_defines.vh
$(VERILATOR) '-UASSERT_ON' --cc -CFLAGS ${CFLAGS} $(defines) \
$(includes) -I${RV_ROOT}/testbench -f ${RV_ROOT}/testbench/flist \
-Wno-WIDTH -Wno-UNOPTFLAT ${TBFILES} --top-module tb_top \
-exe test_tb_top.cpp --trace --autoflush
-exe test_tb_top.cpp --autoflush $(VERILATOR_DEBUG)
cp ${RV_ROOT}/testbench/test_tb_top.cpp obj_dir/
$(MAKE) -C obj_dir/ -f Vtb_top.mk $(VERILATOR_MAKE_FLAGS)
touch verilator-build
@ -107,7 +110,7 @@ irun-build: ${TBFILES} ${BUILD_DIR}/defines.h
touch irun-build
verilator: program.hex verilator-build
./obj_dir/Vtb_top ${DEBUG_PLUS}
./obj_dir/Vtb_top
irun: program.hex irun-build
$(IRUN) -64bit -abvglobalfailurelimit 1 +lic_queue -licqueue \
@ -117,23 +120,30 @@ irun: program.hex irun-build
vcs: program.hex vcs-build
./simv $(DEBUG_PLUS) +vcs+lic+wait -l vcs.log
vlog: program.hex ${TBFILES} ${BUILD_DIR}/defines.h
$(VLOG) -l vlog.log -sv -mfcu +incdir+${BUILD_DIR}+${RV_ROOT}/design/include+${RV_ROOT}/design/lib\
$(defines) -f ${RV_ROOT}/testbench/flist ${TBFILES} -R ${DEBUG_PLUS}
ifeq ($(shell which $(GCC_PREFIX)-gcc 2> /dev/null),)
program.hex: ${BUILD_DIR}/defines.h
@echo " !!! No $(GCC_PREFIX)-gcc in path, using canned hex files !!"
cp ${HEX_DIR}/$(TEST).program.hex program.hex
cp ${HEX_DIR}/$(TEST).data.hex data.hex
else
ifneq (,$(wildcard $(TEST_DIR)/$(TEST).makefile))
program.hex:
$(MAKE) -f $(TEST_DIR)/$(TEST).makefile
else
program.hex: $(TEST).o $(LINK)
@echo Building $(TEST)
ifeq ($(shell which $(GCC_PREFIX)-as),)
@echo " !!! No $(GCC_PREFIX)-as in path, using canned hex files !!"
cp ${RV_ROOT}/testbench/hex/*.hex .
else
ifeq (,$(wildcard $(TEST_DIR)/$(TEST).makefile))
$(GCC_PREFIX)-ld -m elf32lriscv --discard-none -T$(LINK) -o $(TEST).exe $(TEST).o
$(GCC_PREFIX)-objcopy -O verilog --only-section ".data*" --change-section-lma .data=0 $(TEST).exe data.hex
$(GCC_PREFIX)-objcopy -O verilog --only-section ".text" $(TEST).exe program.hex
$(GCC_PREFIX)-objcopy -O verilog --only-section ".data*" --change-section-lma .data*-0x10000 $(TEST).exe data.hex
$(GCC_PREFIX)-objcopy -O verilog --only-section ".text*" $(TEST).exe program.hex
$(GCC_PREFIX)-objdump -S $(TEST).exe > $(TEST).dis
$(GCC_PREFIX)-nm -f posix -C $(TEST).exe > $(TEST).tbl
@echo Completed building $(TEST)
else
$(MAKE) -f $(TEST_DIR)/$(TEST).makefile
endif
endif
%.o : %.s ${BUILD_DIR}/defines.h
$(GCC_PREFIX)-cpp -I${BUILD_DIR} $< > $(TEST).cpp.s
@ -144,9 +154,12 @@ ABI = -mabi=ilp32 -march=rv32imc
%.o : %.c ${BUILD_DIR}/defines.h
$(GCC_PREFIX)-gcc -I${BUILD_DIR} ${TEST_CFLAGS} ${ABI} -nostdlib -c $< -o $@
endif
endif
help:
@echo Make sure the environment variable RV_ROOT is set.
@echo Possible targets: verilator vcs irun help clean all verilator-build irun-build vcs-build program.hex
@echo Possible targets: verilator vcs irun vlog help clean all verilator-build irun-build vcs-build program.hex
.PHONY: help clean verilator vcs irun
.PHONY: help clean verilator vcs irun vlog