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 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>] make -f $RV_ROOT/tools/Makefile [<simulator>] [debug=1] [snapshot=mybuild] [target=<target>] [TEST=<test>] [TEST_DIR=<path_to_test_dir>]
where: 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. 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. 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' <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 TEST_DIR - alternative to test source directory testbench/asm
<snapshot> - run and build executable model of custom CPU configuration, remember to provide 'snapshot' argument <snapshot> - run and build executable model of custom CPU configuration, remember to provide 'snapshot' argument
for runs on custom configurations. 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] 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 The Makefile uses `$RV_ROOT/testbench/link.ld` file by default to build test executable.
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.
User can provide test specific linker file in form `<test_name>.ld` to build the 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. in the same directory with the test source.
User also can create a test specific makefile in form `<test_name>.makefile`, containing building instructions 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 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. 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)*. 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: 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_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 - coremark benchmark running with code and data in external memories
cmark_dccm - the same as above, running data and stack from DCCM (faster) 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, 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 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: 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 use default settings for one of the targets
-set=var=value -set=var=value
@ -191,6 +191,8 @@ my $pic_total_int;
my $top_align_iccm = 0; my $top_align_iccm = 0;
my $lsu2dma = 0;
my $target = "default"; my $target = "default";
my $snapshot ; my $snapshot ;
my $build_path ; my $build_path ;
@ -319,7 +321,10 @@ my $opensource=0;
# IDEA: is ghr at 5b the right size for el2 core # 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") { elsif ($target eq "typical_pd") {
print "$self: Using target \"typical_pd\"\n"; print "$self: Using target \"typical_pd\"\n";
@ -339,7 +344,7 @@ elsif ($target eq "default_ahb") {
print "$self: Using target \"default_ahb\"\n"; print "$self: Using target \"default_ahb\"\n";
} }
else { 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 "iccm_only" => 'derived', # Used by design
"icache_only" => 'derived', # Used by design "icache_only" => 'derived', # Used by design
"no_iccm_no_icache" => '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" => { "dccm" => {
@ -825,8 +831,23 @@ our %config = (#{{{
"pic_mpiccfg_offset" => '0x3000', # Testbench only: Offset of mpiccfg relative to pic_base_addr "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_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_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" => { "testbench" => {
"TOP" => "tb_top", "TOP" => "tb_top",
@ -927,6 +948,7 @@ our %config = (#{{{
# need to have this be width in binary # need to have this be width in binary
# for now autosize to the data # for now autosize to the data
our %verilog_parms = ( our %verilog_parms = (
"lsu2dma" => '1',
"fast_interrupt_redirect" => '1', "fast_interrupt_redirect" => '1',
"inst_access_enable0" => '1', "inst_access_enable0" => '1',
"inst_access_addr0" => '32', "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{#{{{ sub dump_whisper_config{#{{{
my ($config, $path) = @_; my ($config, $path) = @_;
@ -2063,6 +2111,11 @@ sub dump_whisper_config{#{{{
# Collect pic configs. # Collect pic configs.
if (exists $config{pic}) { 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}}) { while (my ($k, $v) = each %{$config{pic}}) {
next if $k eq 'pic_base_addr'; # derived from region and offset next if $k eq 'pic_base_addr'; # derived from region and offset
if ($k eq 'pic_size') { if ($k eq 'pic_size') {

View File

@ -109,6 +109,7 @@ import el2_pkg::*;
// general inputs // general inputs
input logic clk, input logic clk,
input logic rst_l, input logic rst_l,
input logic dbg_rst_l,
input logic clk_override, input logic clk_override,
input logic scan_mode input logic scan_mode
); );
@ -147,6 +148,8 @@ import el2_pkg::*;
logic dmstatus_havereset_wren; logic dmstatus_havereset_wren;
logic dmstatus_havereset_rst; logic dmstatus_havereset_rst;
logic dmstatus_resumeack; logic dmstatus_resumeack;
logic dmstatus_unavail;
logic dmstatus_running;
logic dmstatus_halted; logic dmstatus_halted;
logic dmstatus_havereset; logic dmstatus_havereset;
@ -227,7 +230,7 @@ import el2_pkg::*;
// end clocking section // end clocking section
// Reset logic // 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]; assign dbg_core_rst_l = ~dmcontrol_reg[1];
// system bus register // 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 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) | assign sbaddress0_incr[3:0] = ({4{(sbcs_reg[19:17] == 3'h0)}} & 4'b0001) |
({4{(sbcs_reg[19:17] == 3'b001)}} & 4'b0010) | ({4{(sbcs_reg[19:17] == 3'h1)}} & 4'b0010) |
({4{(sbcs_reg[19:17] == 3'b010)}} & 4'b0100) | ({4{(sbcs_reg[19:17] == 3'h2)}} & 4'b0100) |
({4{(sbcs_reg[19:17] == 3'b100)}} & 4'b1000); ({4{(sbcs_reg[19:17] == 3'h3)}} & 4'b1000);
// sbdata // 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 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 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 // 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 // rest all the bits are zeroed out
// dmactive flop is reset based on core rst_l, all other flops use dm_rst_l // 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_wren = (dmi_reg_addr == 7'h10) & dmi_reg_en & dmi_reg_wr_en;
assign dmcontrol_reg[29] = '0;
assign dmcontrol_reg[27:2] = '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 #(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(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)); 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 // dmstatus register bits that are implemented
@ -301,10 +305,12 @@ import el2_pkg::*;
// rest all the bits are zeroed out // rest all the bits are zeroed out
assign dmstatus_reg[31:20] = '0; assign dmstatus_reg[31:20] = '0;
assign dmstatus_reg[19:18] = {2{dmstatus_havereset}}; 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[7] = '1;
assign dmstatus_reg[6:4] = '0; assign dmstatus_reg[6:4] = '0;
assign dmstatus_reg[17:16] = {2{dmstatus_resumeack}}; 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[9:8] = {2{dmstatus_halted}};
assign dmstatus_reg[3:0] = 4'h2; 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_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_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)); 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)); 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)); 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_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_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_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) & assign abstractcs_error_sel4 = (dmi_reg_addr == 7'h17) & dmi_reg_en & dmi_reg_wr_en &
( ((dmi_reg_wdata[22:20] == 3'b001) & data1_reg[0]) | ((dmi_reg_wdata[22:20] != 3'b010) | ((dmi_reg_wdata[31:24] == 8'h2) && (|data1_reg[1:0]))); // Only word size is allowed
((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_sel5 = (dmi_reg_addr == 7'h16) & dmi_reg_en & dmi_reg_wr_en; 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 // command[16] = 1: write, 0: read
// Size - 2, Bits Not implemented: 23 (aamvirtual), 19-autoincrement, 18-postexec, 17-transfer // 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_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)); 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 // data0 reg
@ -386,18 +392,18 @@ import el2_pkg::*;
dbg_state_en = 1'b0; dbg_state_en = 1'b0;
abstractcs_busy_wren = 1'b0; abstractcs_busy_wren = 1'b0;
abstractcs_busy_din = 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 dbg_resume_req = 1'b0; // single pulse output to the core
case (dbg_state) case (dbg_state)
IDLE: begin IDLE: begin
dbg_nxtstate = (dmstatus_reg[9] | dec_tlu_mpc_halted_only) ? HALTED : HALTING; // initiate the halt command to the core 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_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 end
HALTING : begin HALTING : begin
dbg_nxtstate = HALTED; // Goto HALTED once the core sends an ACK dbg_nxtstate = dmcontrol_reg[1] ? IDLE : HALTED; // Goto HALTED once the core sends an ACK
dbg_state_en = dmstatus_reg[9]; // core indicates halted dbg_state_en = dmstatus_reg[9] | dmcontrol_reg[1]; // core indicates halted
end end
HALTED: begin HALTED: begin
// wait for halted to go away before send to resume. Else start of new command // 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 dbg_resume_req = dbg_state_en & (dbg_nxtstate == RESUMING); // single cycle pulse to core if resuming
end end
CMD_START: begin CMD_START: begin
dbg_nxtstate = (|abstractcs_reg[10:8]) ? CMD_DONE : CMD_WAIT; // new command sent to the core 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]); dbg_state_en = dbg_cmd_valid | (|abstractcs_reg[10:8]) | dmcontrol_reg[1];
end end
CMD_WAIT: begin CMD_WAIT: begin
dbg_nxtstate = CMD_DONE; dbg_nxtstate = dmcontrol_reg[1] ? IDLE : CMD_DONE;
dbg_state_en = core_dbg_cmd_done; // go to done state for one cycle after completing current command dbg_state_en = core_dbg_cmd_done | dmcontrol_reg[1]; // go to done state for one cycle after completing current command
end end
CMD_DONE: begin CMD_DONE: begin
dbg_nxtstate = HALTED; dbg_nxtstate = dmcontrol_reg[1] ? IDLE : HALTED;
dbg_state_en = 1'b1; dbg_state_en = 1'b1;
abstractcs_busy_wren = dbg_state_en; // remove the busy bit from the abstracts ( bit 12 ) abstractcs_busy_wren = dbg_state_en; // remove the busy bit from the abstracts ( bit 12 )
abstractcs_busy_din = 1'b0; abstractcs_busy_din = 1'b0;
end end
RESUMING : begin RESUMING : begin
dbg_nxtstate = IDLE; 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 end
default : begin default : begin
dbg_nxtstate = IDLE; dbg_nxtstate = IDLE;
@ -450,7 +456,7 @@ import el2_pkg::*;
({32{dmi_reg_addr == 7'h3d}} & sbdata1_reg[31:0]); ({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 // 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)); 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}; 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_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_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 assign rv_trace_pkt.rv_i_tval_ip = dec_tlu_mtval_wb1[31:0]; // replicate across ports
// end trace // end trace

View File

@ -28,6 +28,7 @@ import el2_pkg::*;
( (
input logic clk, input logic clk,
input logic rst_l, input logic rst_l,
input logic dbg_rst_l,
input logic [31:1] rst_vec, input logic [31:1] rst_vec,
input logic nmi_int, input logic nmi_int,
input logic [31:1] nmi_vec, 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_valid_ip,
output logic [1:0] trace_rv_i_exception_ip, output logic [1:0] trace_rv_i_exception_ip,
output logic [4:0] trace_rv_i_ecause_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 [31:0] trace_rv_i_tval_ip,
output logic dccm_clk_override, 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!"); 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 `endif
// ----------------- DEBUG END -----------------------------
assign core_rst_l = rst_l & (dbg_core_rst_l | scan_mode); assign core_rst_l = rst_l & (dbg_core_rst_l | scan_mode);
// fetch // fetch
el2_ifu #(.pt(pt)) ifu ( el2_ifu #(.pt(pt)) ifu (
.rst_l(core_rst_l), .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_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_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_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]; 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 clk,
input logic rst_l, input logic rst_l,
input logic dbg_rst_l,
input logic [31:1] rst_vec, input logic [31:1] rst_vec,
input logic nmi_int, input logic nmi_int,
input logic [31:1] nmi_vec, 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_valid_ip,
output logic [1:0] trace_rv_i_exception_ip, output logic [1:0] trace_rv_i_exception_ip,
output logic [4:0] trace_rv_i_ecause_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 [31:0] trace_rv_i_tval_ip,
// Bus signals // Bus signals
@ -695,7 +696,7 @@ import el2_pkg::*;
.tdoEnable (), // Test Data Output enable .tdoEnable (), // Test Data Output enable
// Processor Signals // 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 .core_clk (clk), // Core clock
.jtag_id (jtag_id), // 32 bit JTAG ID .jtag_id (jtag_id), // 32 bit JTAG ID
.rd_data (dmi_reg_rdata), // 32 bit Read data from Processor .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_BANK_HI:2] == i) ?
addr_bank_inc[pt.ICCM_BITS-1 : pt.ICCM_BANK_INDEX_LO] : addr_bank_inc[pt.ICCM_BITS-1 : pt.ICCM_BANK_INDEX_LO] :
iccm_rw_addr[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 if (pt.ICCM_INDEX_BITS == 6 ) begin : iccm
ram_64x39 iccm_bank ( ram_64x39 iccm_bank (
@ -212,6 +225,8 @@ import el2_pkg::*;
); );
end // block: iccm end // block: iccm
`endif
// match the redundant rows // 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)) | 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)))); ((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_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)); 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 [31:0] rv_i_address_ip;
logic [1:0] rv_i_exception_ip; logic [1:0] rv_i_exception_ip;
logic [4:0] rv_i_ecause_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; logic [31:0] rv_i_tval_ip;
} el2_trace_pkt_t; } el2_trace_pkt_t;

View File

@ -257,7 +257,7 @@ import el2_pkg::*;
logic is_sideeffects_m; logic is_sideeffects_m;
logic [2:0] dma_mem_tag_d, dma_mem_tag_m; logic [2:0] dma_mem_tag_d, dma_mem_tag_m;
logic ldst_nodma_mtor; 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 [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; 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 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_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 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 [31:0] store_data_m,
input logic dma_dccm_wen, input logic dma_dccm_wen,
input logic dma_pic_wen,
input logic [2:0] dma_mem_tag_m, 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_lo,
input logic [31:0] dma_dccm_wdata_hi, 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 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]; 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 // 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_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_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_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]}; 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" #include "defines.h"
#define ITERATIONS 1
extern int STACK; extern int STACK;
void main(); void main();
@ -1198,7 +1199,9 @@ MAIN_RETURN_TYPE main(int argc, char *argv[]) {
#else #else
ee_printf("Total time (secs): %d\n",time_in_secs(total_time)); ee_printf("Total time (secs): %d\n",time_in_secs(total_time));
if (time_in_secs(total_time) > 0) 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 #endif
if (time_in_secs(total_time) < 10) { if (time_in_secs(total_time) < 10) {
ee_printf("ERROR! Must execute for at least 10 secs for a valid result!\n"); 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 seed2_volatile=0x8;
volatile ee_s32 seed3_volatile=0x8; volatile ee_s32 seed3_volatile=0x8;
#endif #endif
// volatile ee_s32 seed4_volatile=ITERATIONS; volatile ee_s32 seed4_volatile=ITERATIONS;
volatile ee_s32 seed4_volatile=1;
volatile ee_s32 seed5_volatile=0; volatile ee_s32 seed5_volatile=0;
/* Porting : Timing functions /* Porting : Timing functions
How to capture time and convert to seconds must be ported to whatever is supported by the platform. 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 MYTIMEDIFF(fin,ini) ((fin)-(ini))
#define TIMER_RES_DIVIDER 1 #define TIMER_RES_DIVIDER 1
#define SAMPLE_TIME_IMPLEMENTATION 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. */ /** Define Host specific (POSIX), or target specific global time variables. */
static CORETIMETYPE start_time_val, stop_time_val; 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 .global _start
_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 // Enable Caches in MRAC
ori x5, x5, 0 li x1, 0x5f555555
csrrw x2, 0x305, x5 csrw 0x7c0, x1
// Load string from hw_data
// and write to stdout address
lui x6, 382293 li x3, STDOUT
ori x6, x6, 1365 la x4, hw_data
csrrw x1, 0x7c0, x6
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
.data
lui x5, 0 hw_data:
ori x5, x5, 0 .ascii "----------------------------------\n"
csrrw x2, 0x7f8, x5 .ascii "Hello World from SweRV EL2 @WDC !!\n"
.ascii "----------------------------------\n"
.byte 0
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

View File

@ -5,7 +5,7 @@ ENTRY(_start)
SECTIONS { SECTIONS {
.text : { *(.text*) } .text : { *(.text*) }
_end = .; _end = .;
. = 0xfff8; . = 0x1fff8;
.data.ctl : { LONG(0xf0040000); LONG(STACK) } .data.ctl : { LONG(0xf0040000); LONG(STACK) }
. = 0xf0040000; . = 0xf0040000;
.data : AT(0x10000) { *(.*data) *(.rodata*) STACK = ALIGN(16) + 0x8000;} .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 +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 //-y $SYNOPSYS_SYN_ROOT/dw/sim_ver
$RV_ROOT/design/el2_swerv_wrapper.sv $RV_ROOT/design/el2_swerv_wrapper.sv
$RV_ROOT/design/el2_mem.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_trigger.sv
$RV_ROOT/design/dec/el2_dec.sv $RV_ROOT/design/dec/el2_dec.sv
$RV_ROOT/design/exu/el2_exu_alu_ctl.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_mul_ctl.sv
$RV_ROOT/design/exu/el2_exu_div_ctl.sv $RV_ROOT/design/exu/el2_exu_div_ctl.sv
$RV_ROOT/design/exu/el2_exu.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/beh_lib.sv
-v $RV_ROOT/design/lib/mem_lib.sv -v $RV_ROOT/design/lib/mem_lib.sv
-y $RV_ROOT/design/lib -y $RV_ROOT/design/lib
//$RV_ROOT/design/lib/ahb_to_svci.sv -v $RV_ROOT/testbench/axi_lsu_dma_bridge.sv
//$RV_ROOT/design/lib/ahb_to_axi4.sv
//$RV_ROOT/design/lib/axi4_to_ahb.sv

View File

@ -13,64 +13,62 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// //
`ifndef VERILATOR `ifdef VERILATOR
module tb_top;
`else
module tb_top ( input bit core_clk ); module tb_top ( input bit core_clk );
`endif `else
module tb_top;
`ifndef VERILATOR
bit core_clk; bit core_clk;
`endif `endif
logic rst_l; logic rst_l;
logic porst_l;
logic nmi_int; logic nmi_int;
logic [31:0] reset_vector; logic [31:0] reset_vector;
logic [31:0] nmi_vector; logic [31:0] nmi_vector;
logic [31:1] jtag_id; logic [31:1] jtag_id;
logic [31:0] ic_haddr ; logic [31:0] ic_haddr;
logic [2:0] ic_hburst ; logic [2:0] ic_hburst;
logic ic_hmastlock ; logic ic_hmastlock;
logic [3:0] ic_hprot ; logic [3:0] ic_hprot;
logic [2:0] ic_hsize ; logic [2:0] ic_hsize;
logic [1:0] ic_htrans ; logic [1:0] ic_htrans;
logic ic_hwrite ; logic ic_hwrite;
logic [63:0] ic_hrdata ; logic [63:0] ic_hrdata;
logic ic_hready ; logic ic_hready;
logic ic_hresp ; logic ic_hresp;
logic [31:0] lsu_haddr ; logic [31:0] lsu_haddr;
logic [2:0] lsu_hburst ; logic [2:0] lsu_hburst;
logic lsu_hmastlock ; logic lsu_hmastlock;
logic [3:0] lsu_hprot ; logic [3:0] lsu_hprot;
logic [2:0] lsu_hsize ; logic [2:0] lsu_hsize;
logic [1:0] lsu_htrans ; logic [1:0] lsu_htrans;
logic lsu_hwrite ; logic lsu_hwrite;
logic [63:0] lsu_hrdata ; logic [63:0] lsu_hrdata;
logic [63:0] lsu_hwdata ; logic [63:0] lsu_hwdata;
logic lsu_hready ; logic lsu_hready;
logic lsu_hresp ; logic lsu_hresp;
logic [31:0] sb_haddr ; logic [31:0] sb_haddr;
logic [2:0] sb_hburst ; logic [2:0] sb_hburst;
logic sb_hmastlock ; logic sb_hmastlock;
logic [3:0] sb_hprot ; logic [3:0] sb_hprot;
logic [2:0] sb_hsize ; logic [2:0] sb_hsize;
logic [1:0] sb_htrans ; logic [1:0] sb_htrans;
logic sb_hwrite ; logic sb_hwrite;
logic [63:0] sb_hrdata ; logic [63:0] sb_hrdata;
logic [63:0] sb_hwdata ; logic [63:0] sb_hwdata;
logic sb_hready ; logic sb_hready;
logic sb_hresp ; logic sb_hresp;
logic [31:0] trace_rv_i_insn_ip; logic [31:0] trace_rv_i_insn_ip;
logic [31:0] trace_rv_i_address_ip; logic [31:0] trace_rv_i_address_ip;
logic [1:0] trace_rv_i_valid_ip; logic [1:0] trace_rv_i_valid_ip;
logic [1:0] trace_rv_i_exception_ip; logic [1:0] trace_rv_i_exception_ip;
logic [4:0] trace_rv_i_ecause_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 [31:0] trace_rv_i_tval_ip;
logic o_debug_mode_status; logic o_debug_mode_status;
@ -82,10 +80,10 @@ module tb_top ( input bit core_clk );
logic o_cpu_run_ack; logic o_cpu_run_ack;
logic mailbox_write; logic mailbox_write;
logic [63:0] dma_hrdata ; logic [63:0] dma_hrdata;
logic [63:0] dma_hwdata ; logic [63:0] dma_hwdata;
logic dma_hready ; logic dma_hready;
logic dma_hresp ; logic dma_hresp;
logic mpc_debug_halt_req; logic mpc_debug_halt_req;
logic mpc_debug_run_req; logic mpc_debug_run_req;
@ -94,7 +92,7 @@ module tb_top ( input bit core_clk );
logic mpc_debug_run_ack; logic mpc_debug_run_ack;
logic debug_brkpt_status; logic debug_brkpt_status;
bit [31:0] cycleCnt ; bit [31:0] cycleCnt;
logic mailbox_data_val; logic mailbox_data_val;
wire dma_hready_out; wire dma_hready_out;
@ -286,6 +284,27 @@ module tb_top ( input bit core_clk );
wire [1:0] dma_axi_rresp; wire [1:0] dma_axi_rresp;
wire dma_axi_rlast; 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 `endif
wire[63:0] WriteData; 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_valid[0] <= rvtop.swerv.dec.dec_i0_wen_r;
wb_dest[0] <= rvtop.swerv.dec.dec_i0_waddr_r; wb_dest[0] <= rvtop.swerv.dec.dec_i0_waddr_r;
wb_data[0] <= rvtop.swerv.dec.dec_i0_wdata_r; wb_data[0] <= rvtop.swerv.dec.dec_i0_wdata_r;
if (rvtop.trace_rv_i_valid_ip !== 0) begin if (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, $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, 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); trace_rv_i_tval_ip,trace_rv_i_interrupt_ip);
// Basic trace - no exception register updates // Basic trace - no exception register updates
// #1 0 ee000000 b0201073 c 0b02 00000000 // #1 0 ee000000 b0201073 c 0b02 00000000
for (int i=0; i<1; i++) 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++; commit_count++;
$fwrite (el, "%10d : %6s 0 %h %h %s\n", cycleCnt, $sformatf("#%0d",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], 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 end
end end
@ -363,6 +382,7 @@ module tb_top ( input bit core_clk );
fd = $fopen("console.log","w"); fd = $fopen("console.log","w");
commit_count = 0; commit_count = 0;
preload_dccm(); preload_dccm();
preload_iccm();
`ifndef VERILATOR `ifndef VERILATOR
if($test$plusargs("dumpon")) $dumpvars; if($test$plusargs("dumpon")) $dumpvars;
@ -372,12 +392,14 @@ module tb_top ( input bit core_clk );
assign rst_l = cycleCnt > 5; assign rst_l = cycleCnt > 5;
assign porst_l = cycleCnt > 2;
//=========================================================================- //=========================================================================-
// RTL instance // RTL instance
//=========================================================================- //=========================================================================-
el2_swerv_wrapper rvtop ( el2_swerv_wrapper rvtop (
.rst_l ( rst_l ), .rst_l ( rst_l ),
.dbg_rst_l ( porst_l ),
.clk ( core_clk ), .clk ( core_clk ),
.rst_vec ( reset_vector[31:1]), .rst_vec ( reset_vector[31:1]),
.nmi_int ( nmi_int ), .nmi_int ( nmi_int ),
@ -590,40 +612,40 @@ el2_swerv_wrapper rvtop (
//-------------------------- DMA AXI signals-------------------------- //-------------------------- DMA AXI signals--------------------------
// AXI Write Channels // AXI Write Channels
.dma_axi_awvalid (1'b0), .dma_axi_awvalid (dma_axi_awvalid),
.dma_axi_awready (dma_axi_awready), .dma_axi_awready (dma_axi_awready),
.dma_axi_awid (dma_axi_awid), .dma_axi_awid ('0),
.dma_axi_awaddr (dma_axi_awaddr), .dma_axi_awaddr (lsu_axi_awaddr),
.dma_axi_awsize (dma_axi_awsize), .dma_axi_awsize (lsu_axi_awsize),
.dma_axi_awprot (dma_axi_awprot), .dma_axi_awprot (lsu_axi_awprot),
.dma_axi_awlen (dma_axi_awlen), .dma_axi_awlen (lsu_axi_awlen),
.dma_axi_awburst (dma_axi_awburst), .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_wready (dma_axi_wready),
.dma_axi_wdata (dma_axi_wdata), .dma_axi_wdata (lsu_axi_wdata),
.dma_axi_wstrb (dma_axi_wstrb), .dma_axi_wstrb (lsu_axi_wstrb),
.dma_axi_wlast (dma_axi_wlast), .dma_axi_wlast (lsu_axi_wlast),
.dma_axi_bvalid (dma_axi_bvalid), .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_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_arready (dma_axi_arready),
.dma_axi_arid (dma_axi_arid), .dma_axi_arid ('0),
.dma_axi_araddr (dma_axi_araddr), .dma_axi_araddr (lsu_axi_araddr),
.dma_axi_arsize (dma_axi_arsize), .dma_axi_arsize (lsu_axi_arsize),
.dma_axi_arprot (dma_axi_arprot), .dma_axi_arprot (lsu_axi_arprot),
.dma_axi_arlen (dma_axi_arlen), .dma_axi_arlen (lsu_axi_arlen),
.dma_axi_arburst (dma_axi_arburst), .dma_axi_arburst (lsu_axi_arburst),
.dma_axi_rvalid (dma_axi_rvalid), .dma_axi_rvalid (dma_axi_rvalid),
.dma_axi_rready (1'b0), .dma_axi_rready (dma_axi_rready),
.dma_axi_rid (dma_axi_rid), .dma_axi_rid (),
.dma_axi_rdata (dma_axi_rdata), .dma_axi_rdata (dma_axi_rdata),
.dma_axi_rresp (dma_axi_rresp), .dma_axi_rresp (dma_axi_rresp),
.dma_axi_rlast (dma_axi_rlast), .dma_axi_rlast (dma_axi_rlast),
@ -768,23 +790,23 @@ defparam lmem.TAGW =`RV_LSU_BUS_TAG;
axi_slv lmem( axi_slv lmem(
.aclk(core_clk), .aclk(core_clk),
.rst_l(rst_l), .rst_l(rst_l),
.arvalid(lsu_axi_arvalid), .arvalid(lmem_axi_arvalid),
.arready(lsu_axi_arready), .arready(lmem_axi_arready),
.araddr(lsu_axi_araddr), .araddr(lsu_axi_araddr),
.arid(lsu_axi_arid), .arid(lsu_axi_arid),
.arlen(lsu_axi_arlen), .arlen(lsu_axi_arlen),
.arburst(lsu_axi_arburst), .arburst(lsu_axi_arburst),
.arsize(lsu_axi_arsize), .arsize(lsu_axi_arsize),
.rvalid(lsu_axi_rvalid), .rvalid(lmem_axi_rvalid),
.rready(lsu_axi_rready), .rready(lmem_axi_rready),
.rdata(lsu_axi_rdata), .rdata(lmem_axi_rdata),
.rresp(lsu_axi_rresp), .rresp(lmem_axi_rresp),
.rid(lsu_axi_rid), .rid(lmem_axi_rid),
.rlast(lsu_axi_rlast), .rlast(lmem_axi_rlast),
.awvalid(lsu_axi_awvalid), .awvalid(lmem_axi_awvalid),
.awready(lsu_axi_awready), .awready(lmem_axi_awready),
.awaddr(lsu_axi_awaddr), .awaddr(lsu_axi_awaddr),
.awid(lsu_axi_awid), .awid(lsu_axi_awid),
.awlen(lsu_axi_awlen), .awlen(lsu_axi_awlen),
@ -793,25 +815,145 @@ axi_slv lmem(
.wdata(lsu_axi_wdata), .wdata(lsu_axi_wdata),
.wstrb(lsu_axi_wstrb), .wstrb(lsu_axi_wstrb),
.wvalid(lsu_axi_wvalid), .wvalid(lmem_axi_wvalid),
.wready(lsu_axi_wready), .wready(lmem_axi_wready),
.bvalid(lsu_axi_bvalid), .bvalid(lmem_axi_bvalid),
.bready(lsu_axi_bready), .bready(lmem_axi_bready),
.bresp(lsu_axi_bresp), .bresp(lmem_axi_bresp),
.bid(lsu_axi_bid) .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 `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; task preload_dccm;
bit[31:0] data; bit[31:0] data;
bit[31:0] addr, eaddr; bit[31:0] addr, eaddr;
int adr; int adr;
/*
addresses:
0xfff8 - DCCM start address to load
0xfffc - ICCM end address to load
0x0 - lmem start addres to load from
*/
addr = 'hfff8; addr = 'hfff8;
eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]};
if (eaddr != `RV_DCCM_SADR) return; 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; addr = 'hfffc;
eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; 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); $display("DCCM pre-load from %h to %h", `RV_DCCM_SADR, eaddr);
@ -824,16 +966,20 @@ end
endtask endtask
`define ICCM_PATH `RV_TOP.mem.iccm.iccm
`ifdef VERILATOR `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 `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 `endif
task slam_dccm_ram(input [31:0] addr, input[38:0] data); task slam_dccm_ram(input [31:0] addr, input[38:0] data);
int bank, indx; int bank, indx;
bank = get_dccm_bank(addr, indx); bank = get_dccm_bank(addr, indx);
//`ifndef VERILATOR `ifdef RV_DCCM_ENABLE
case(bank) case(bank)
0: `DRAM(0)[indx] = data; 0: `DRAM(0)[indx] = data;
1: `DRAM(1)[indx] = data; 1: `DRAM(1)[indx] = data;
@ -850,7 +996,82 @@ case(bank)
7: `DRAM(7)[indx] = data; 7: `DRAM(7)[indx] = data;
`endif `endif
endcase 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 endtask
@ -866,7 +1087,7 @@ synd[6] = ^{data, synd[5:0]};
return synd; return synd;
endfunction 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 `ifdef RV_DCCM_NUM_BANKS_2
bank_idx = int'(addr[`RV_DCCM_BITS-1:3]); bank_idx = int'(addr[`RV_DCCM_BITS-1:3]);
return int'( addr[2]); return int'( addr[2]);
@ -879,4 +1100,21 @@ function int get_dccm_bank(input int addr, output int bank_idx);
`endif `endif
endfunction 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 endmodule

View File

@ -32,38 +32,32 @@ double sc_time_stamp () {
int main(int argc, char** argv) { int main(int argc, char** argv) {
std::cout << "\nVerilatorTB: Start of sim\n" << std::endl; 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); Verilated::commandArgs(argc, argv);
Vtb_top* tb = new Vtb_top; Vtb_top* tb = new Vtb_top;
// init trace dump // init trace dump
Verilated::traceEverOn(true); VerilatedVcdC* tfp = NULL;
VerilatedVcdC* tfp = new VerilatedVcdC;
tb->trace (tfp, 24);
if (dumpWaves)
tfp->open ("sim.vcd");
#if VM_TRACE
Verilated::traceEverOn(true);
tfp = new VerilatedVcdC;
tb->trace (tfp, 24);
tfp->open ("sim.vcd");
#endif
// Simulate // Simulate
while(!Verilated::gotFinish()){ while(!Verilated::gotFinish()){
if (dumpWaves) #if VM_TRACE
tfp->dump (main_time); tfp->dump (main_time);
#endif
main_time += 5; main_time += 5;
tb->core_clk = !tb->core_clk; tb->core_clk = !tb->core_clk;
tb->eval(); tb->eval();
} }
if (dumpWaves) #if VM_TRACE
tfp->close(); tfp->close();
#endif
std::cout << "\nVerilatorTB: End of sim" << std::endl; std::cout << "\nVerilatorTB: End of sim" << std::endl;
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: Apache-2.0 # 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with 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 SWERV_CONFIG = ${RV_ROOT}/configs/swerv.config
IRUN = xrun IRUN = xrun
VCS = vcs VCS = vcs
VLOG = qverilog
VERILATOR = verilator VERILATOR = verilator
GCC_PREFIX = riscv64-unknown-elf GCC_PREFIX = riscv64-unknown-elf
BUILD_DIR = snapshots/${snapshot} BUILD_DIR = snapshots/${snapshot}
TBDIR = ${RV_ROOT}/testbench TBDIR = ${RV_ROOT}/testbench
# Define test name # Define test name
TEST = hello_world2 TEST = hello_world
# Define test name # Define test name
TEST_DIR = ${RV_ROOT}/testbench/asm TEST_DIR = ${TBDIR}/asm
HEX_DIR = ${TBDIR}/hex
ifdef debug ifdef debug
DEBUG_PLUS = +dumpon DEBUG_PLUS = +dumpon
IRUN_DEBUG = -access +rc IRUN_DEBUG = -access +rc
IRUN_DEBUG_RUN = -input ${RV_ROOT}/testbench/input.tcl IRUN_DEBUG_RUN = -input ${RV_ROOT}/testbench/input.tcl
VERILATOR_DEBUG = --trace
endif endif
# provide specific link file # provide specific link file
@ -73,18 +76,18 @@ all: clean verilator
clean: clean:
rm -rf *.log *.s *.hex *.dis *.tbl irun* vcs* simv* snapshots swerv* \ 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. # If define files do not exist, then run swerv.config.
${BUILD_DIR}/defines.h : ${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 verilator-build: ${TBFILES} ${BUILD_DIR}/defines.h test_tb_top.cpp
echo '`undef ASSERT_ON' >> ${BUILD_DIR}/common_defines.vh echo '`undef ASSERT_ON' >> ${BUILD_DIR}/common_defines.vh
$(VERILATOR) '-UASSERT_ON' --cc -CFLAGS ${CFLAGS} $(defines) \ $(VERILATOR) '-UASSERT_ON' --cc -CFLAGS ${CFLAGS} $(defines) \
$(includes) -I${RV_ROOT}/testbench -f ${RV_ROOT}/testbench/flist \ $(includes) -I${RV_ROOT}/testbench -f ${RV_ROOT}/testbench/flist \
-Wno-WIDTH -Wno-UNOPTFLAT ${TBFILES} --top-module tb_top \ -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/ cp ${RV_ROOT}/testbench/test_tb_top.cpp obj_dir/
$(MAKE) -C obj_dir/ -f Vtb_top.mk $(VERILATOR_MAKE_FLAGS) $(MAKE) -C obj_dir/ -f Vtb_top.mk $(VERILATOR_MAKE_FLAGS)
touch verilator-build touch verilator-build
@ -107,7 +110,7 @@ irun-build: ${TBFILES} ${BUILD_DIR}/defines.h
touch irun-build touch irun-build
verilator: program.hex verilator-build verilator: program.hex verilator-build
./obj_dir/Vtb_top ${DEBUG_PLUS} ./obj_dir/Vtb_top
irun: program.hex irun-build irun: program.hex irun-build
$(IRUN) -64bit -abvglobalfailurelimit 1 +lic_queue -licqueue \ $(IRUN) -64bit -abvglobalfailurelimit 1 +lic_queue -licqueue \
@ -117,23 +120,30 @@ irun: program.hex irun-build
vcs: program.hex vcs-build vcs: program.hex vcs-build
./simv $(DEBUG_PLUS) +vcs+lic+wait -l vcs.log ./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) program.hex: $(TEST).o $(LINK)
@echo Building $(TEST) @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)-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 ".data*" --change-section-lma .data*-0x10000 $(TEST).exe data.hex
$(GCC_PREFIX)-objcopy -O verilog --only-section ".text" $(TEST).exe program.hex $(GCC_PREFIX)-objcopy -O verilog --only-section ".text*" $(TEST).exe program.hex
$(GCC_PREFIX)-objdump -S $(TEST).exe > $(TEST).dis $(GCC_PREFIX)-objdump -S $(TEST).exe > $(TEST).dis
$(GCC_PREFIX)-nm -f posix -C $(TEST).exe > $(TEST).tbl $(GCC_PREFIX)-nm -f posix -C $(TEST).exe > $(TEST).tbl
@echo Completed building $(TEST) @echo Completed building $(TEST)
else
$(MAKE) -f $(TEST_DIR)/$(TEST).makefile
endif
endif
%.o : %.s ${BUILD_DIR}/defines.h %.o : %.s ${BUILD_DIR}/defines.h
$(GCC_PREFIX)-cpp -I${BUILD_DIR} $< > $(TEST).cpp.s $(GCC_PREFIX)-cpp -I${BUILD_DIR} $< > $(TEST).cpp.s
@ -144,9 +154,12 @@ ABI = -mabi=ilp32 -march=rv32imc
%.o : %.c ${BUILD_DIR}/defines.h %.o : %.c ${BUILD_DIR}/defines.h
$(GCC_PREFIX)-gcc -I${BUILD_DIR} ${TEST_CFLAGS} ${ABI} -nostdlib -c $< -o $@ $(GCC_PREFIX)-gcc -I${BUILD_DIR} ${TEST_CFLAGS} ${ABI} -nostdlib -c $< -o $@
endif
endif
help: help:
@echo Make sure the environment variable RV_ROOT is set. @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