Version 1.9.

This commit is contained in:
Joseph Rahmeh 2021-01-27 09:36:43 -08:00
parent bcb5b33726
commit ec254f5491
55 changed files with 12276 additions and 8268 deletions

View File

@ -1,6 +1,6 @@
# EH1 SweRV RISC-V Core<sup>TM</sup> 1.8 from Western Digital
# EH1 RISC-V SweRV Core<sup>TM</sup> 1.9 from Western Digital
This repository contains the SweRV EH1 Core<sup>TM</sup> design RTL
This repository contains the EH1 SweRV Core<sup>TM</sup> design RTL
## License
@ -16,7 +16,7 @@ Files under the [tools](tools/) directory may be available under a different lic
│   ├── dec # Decode, Registers and Exceptions
│   ├── dmi # DMI block
│   ├── exu # EXU (ALU/MUL/DIV)
│   ├── ifu # Fetch & Branch Prediction
│   ├── ifu # Fetch & Branch Predictor
│   ├── include
│   ├── lib
│   └── lsu # Load/Store
@ -28,7 +28,7 @@ Files under the [tools](tools/) directory may be available under a different lic
## Dependencies
- Verilator **(4.030 or later)** must be installed on the system if running with verilator
- Verilator **(4.102 or later)** must be installed on the system if running with verilator
- If adding/removing instructions, espresso must be installed (used by *tools/coredecode*)
- RISCV tool chain (based on gcc version 7.3 or higher) must be
installed so that it can be used to prepare RISCV binaries to run.
@ -61,7 +61,7 @@ the `-target=name` option to swerv.config.
This script derives the following consistent set of include files :
$RV_ROOT/configs/snapshots/default
snapshots/default
├── common_defines.vh # `defines for testbench or design
├── defines.h # #defines for C/assembly headers
├── pd_defines.vh # `defines for physical design
@ -87,13 +87,10 @@ Example for csh or its derivatives:
*(Name your snapshot to distinguish it from the default. Without an explicit name, it will update/override the __default__ snapshot)*
For example if `mybuild` is the name for the snapshot:
set BUILD_PATH environment variable:
`setenv BUILD_PATH snapshots/mybuild`
`$RV_ROOT/configs/swerv.config [configuration options..] -snapshot=mybuild`
Snapshots are placed in `$BUILD_PATH` directory
Snapshots are placed in ./snapshots directory
**Building an FPGA speed optimized model:**
Use ``-fpga_optimize=1`` option to ``swerv.config`` to build a model that removes clock gating logic from flop model so that the FPGA builds can run at higher speeds. **This is now the default option for
@ -191,10 +188,13 @@ The `$RV_ROOT/testbench/asm` directory contains following tests ready to simula
```
hello_world - default test 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 above, but CPU copies the code from external memory to ICCM via AXI LSU to DMA bridge
and then jumps there. The test runs only on CPU configurations with ICCM and AXI bus.
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, but with code preloaded to iccm - runs only on CPU with ICCM
use CONF_PARAMS=-set=iccm_enable argument to `make` to build CPU with ICCM
dhry - dhrystone benchmark - example of multi source files program
```
The `$RV_ROOT/testbench/hex` directory contains precompiled hex files of the tests, ready for simulation in case RISCV SW tools are not installed.

View File

@ -243,6 +243,9 @@ my $pdfile = "$build_path/pd_defines.vh";
# Whisper config file path
my $whisperfile = "$build_path/whisper.json";
# Default linker file
my $linkerfile = "$build_path/link.ld";
# Perl defines file path
my $perlfile = "$build_path/perl_configs.pl";
@ -368,8 +371,8 @@ our @triggers = (#{{{
},
{
"reset" => ["0x23e00000", "0x00000000", "0x00000000"],
"mask" => ["0x081818c7", "0xffffffff", "0x00000000"],
"poke_mask" => ["0x081818c7", "0xffffffff", "0x00000000"]
"mask" => ["0x081810c7", "0xffffffff", "0x00000000"],
"poke_mask" => ["0x081810c7", "0xffffffff", "0x00000000"]
},
{
"reset" => ["0x23e00000", "0x00000000", "0x00000000"],
@ -378,8 +381,8 @@ our @triggers = (#{{{
},
{
"reset" => ["0x23e00000", "0x00000000", "0x00000000"],
"mask" => ["0x081818c7", "0xffffffff", "0x00000000"],
"poke_mask" => ["0x081818c7", "0xffffffff", "0x00000000"]
"mask" => ["0x081810c7", "0xffffffff", "0x00000000"],
"poke_mask" => ["0x081810c7", "0xffffffff", "0x00000000"]
},
);#}}}
@ -417,7 +420,7 @@ our %csr = (#{{{
"exists" => "true",
},
"mimpid" => {
"reset" => "0x5",
"reset" => "0x6",
"mask" => "0x0",
"exists" => "true",
},
@ -621,7 +624,7 @@ our %csr = (#{{{
"mfdc" => {
"number" => "0x7f9",
"reset" => "0x00070000",
"mask" => "0x000707ff",
"mask" => "0x000727ff",
"exists" => "true",
},
"dmst" => {
@ -1153,57 +1156,6 @@ if($config{bht}{bht_size}==2048){
$config{bht}{bht_addr_hi} = 5;
$config{bht}{bht_array_depth}= 4;
}
#if($config{bht}{bht_size}==2048){
# $config{bht}{bht_ghr_size}= 8;
# $config{bht}{bht_ghr_range}= "7:0";
# $config{bht}{bht_ghr_pad}= "fghr[7:4],3'b0";
# $config{bht}{bht_ghr_pad2}= "fghr[7:3],2'b0";
# $config{bht}{bht_array_depth}= 256;
# $config{bht}{bht_addr_hi}= 11;
#} elsif($config{bht}{bht_size}==1024){
# $config{bht}{bht_ghr_size}= 7;
# $config{bht}{bht_ghr_range}= "6:0";
# $config{bht}{bht_ghr_pad}= "fghr[6:4],3'b0";
# $config{bht}{bht_ghr_pad2}= "fghr[6:3],2'b0";
# $config{bht}{bht_array_depth}= 128;
# $config{bht}{bht_addr_hi}= 10;
#} elsif($config{bht}{bht_size}==512){
# $config{bht}{bht_ghr_size}= 6;
# $config{bht}{bht_ghr_range}= "5:0";
# $config{bht}{bht_ghr_pad}= "fghr[5:4],3'b0";
# $config{bht}{bht_ghr_pad2}= "fghr[5:3],2'b0";
# $config{bht}{bht_array_depth}= 64;
# $config{bht}{bht_addr_hi}= 9;
#} elsif($config{bht}{bht_size}==256){
# $config{bht}{bht_ghr_size}= 5;
# $config{bht}{bht_ghr_range}= "4:0";
# $config{bht}{bht_ghr_pad}= "fghr[4],3'b0";
# $config{bht}{bht_ghr_pad2}= "fghr[4:3],2'b0";
# $config{bht}{bht_addr_hi} = 8;
# $config{bht}{bht_array_depth}= 32;
#} elsif($config{bht}{bht_size}==128){
# $config{bht}{bht_ghr_size}= 5;
# $config{bht}{bht_ghr_range}= "4:0";
# $config{bht}{bht_ghr_pad}= "fghr[4],3'b0";
# $config{bht}{bht_ghr_pad2}= "fghr[4:3],2'b0";
# $config{bht}{bht_addr_hi} = 7;
# $config{bht}{bht_array_depth}= 16;
#} elsif($config{bht}{bht_size}==64){
# $config{bht}{bht_ghr_size}= 4;
# $config{bht}{bht_ghr_range}= "3:0";
# $config{bht}{bht_ghr_pad}= "3'b0 ";
# $config{bht}{bht_ghr_pad2}= "fghr[4],2'b0";
# $config{bht}{bht_addr_hi} = 6;
# $config{bht}{bht_array_depth}= 8;
#} elsif($config{bht}{bht_size}==32){
# $config{bht}{bht_ghr_size}= 3;
# $config{bht}{bht_ghr_range}= "2:0";
# $config{bht}{bht_ghr_pad}= "2'b0 ";
# $config{bht}{bht_ghr_pad2}= "2'b0";
# $config{bht}{bht_addr_hi} = 5;
# $config{bht}{bht_array_depth}= 4;
# $config{bht}{bht_ghr_size_2} = 1;
#}
$config{bht}{bht_hash_string} = &ghrhash($config{btb}{btb_index1_hi}, $config{bht}{bht_ghr_size}-1);
@ -1603,6 +1555,8 @@ print FILE Data::Dumper->Dump([\%config], [ qw(*config) ]);
print FILE "1;\n";
close FILE;
# Default linker script
gen_default_linker_script();
# Done ##################################################################
#
exit(0);
@ -1960,7 +1914,7 @@ sub dump_whisper_config{#{{{
$jh{memmap}{inst} = [@inst_mem_prot] if @inst_mem_prot;
$jh{memmap}{data} = [@data_mem_prot] if @data_mem_prot;
$config{memmap}{consoleio} = $config{memmap}{serialio} if exists $config{memmap}{serialio};
foreach my $tag (qw (size page_size serialio consoleio)) {
foreach my $tag (qw ( size page_size serialio consoleio)) {
$jh{memmap}{$tag} = $config{memmap}{$tag} if exists $config{memmap}{$tag};
}
@ -2048,3 +2002,56 @@ sub log2 {
my ($n) = @_;
return log($n)/log(2);
}
sub gen_default_linker_script {#{{{
open (FILE, ">$linkerfile") || die "Cannot open $linkerfile for writing $!";
print "$self: Writing $linkerfile\n";
print FILE "/*\n";
print_header();
my $io = "0xd0580000";
$io = $config{memmap}{serialio} if exists $config{memmap}{serialio};
my $iccm = ""; my $iccm_ctl = "";
if (exists $config{iccm} and $config{iccm}{iccm_enable}) {
my $sa = $config{iccm}{iccm_sadr}; my $ea = $config{iccm}{iccm_eadr};
$iccm = " . = $sa ;";
$iccm_ctl = " . = 0xfffffff0; .iccm.ctl . : { LONG($sa); LONG($ea) }" ;
}
my $sa = $config{memmap}{external_data}; my $dccm_ctl = "";
if (exists $config{dccm} and $config{dccm}{dccm_enable}) {
$sa = $config{dccm}{dccm_sadr};
$dccm_ctl = " . = 0xfffffff8; .data.ctl : { LONG($sa); LONG(STACK) }" ;
}
my $data_loc = " . = $sa ;";
print FILE <<EOF;
*/
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
SECTIONS
{
. = $config{reset_vec};
.text.init . : { *(.text.init) }
$iccm
.text . : { *(.text) }
_end = .;
. = $io;
.data.io . : { *(.data.io) }
$data_loc
.data : ALIGN(0x800) { *(.*data) *(.rodata*)}
.bss : {BSS_START = .; *(.*bss)}
BSS_END = .;
STACK = ALIGN(16) + 0x1000;
$iccm_ctl
$dccm_ctl
}
EOF
close FILE;
} #}}}

View File

@ -1,42 +1,34 @@
#!/usr/bin/env python3
#!/usr/bin/env python
from fusesoc.capi2.generator import Generator
import os
import shutil
import subprocess
import sys
import tempfile
if sys.version[0] == '2':
devnull = open(os.devnull, 'w')
else:
from subprocess import DEVNULL as devnull
class SwervConfigGenerator(Generator):
def run(self):
build_path="swerv_config"
script_root = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..'))
files = [
{os.path.join(build_path, "common_defines.vh") : {
{"configs/snapshots/default/common_defines.vh" : {
"copyto" : "config/common_defines.vh",
"file_type" : "systemVerilogSource"}},
{os.path.join(build_path, "pic_ctrl_verilator_unroll.sv") : {
{"configs/snapshots/default/pic_ctrl_verilator_unroll.sv" : {
"copyto" : "config/pic_ctrl_verilator_unroll.sv",
"is_include_file" : True,
"file_type" : "systemVerilogSource"}},
{os.path.join(build_path, "pic_map_auto.h") : {
{"configs/snapshots/default/pic_map_auto.h" : {
"copyto" : "config/pic_map_auto.h",
"is_include_file" : True,
"file_type" : "systemVerilogSource"}}]
tmp_dir = os.path.join(tempfile.mkdtemp(), 'core')
shutil.copytree(script_root, tmp_dir)
shutil.copytree(self.files_root, tmp_dir)
cwd = tmp_dir
env = os.environ.copy()
env['RV_ROOT'] = tmp_dir
env['BUILD_PATH'] = build_path
args = ['configs/swerv.config'] + self.config.get('args', [])
rc = subprocess.call(args, cwd=cwd, env=env, stdout=devnull)
rc = subprocess.call(args, cwd=cwd, env=env)
if rc:
exit(1)

View File

@ -109,7 +109,7 @@ module dbg (
// general inputs
input logic clk,
input logic free_clk,
input logic rst_l,
input logic rst_l, // This includes both top rst and dbg rst
input logic dbg_rst_l,
input logic clk_override,
input logic scan_mode
@ -165,13 +165,12 @@ module dbg (
logic dmstatus_dmerr_wren;
logic dmstatus_resumeack_wren;
logic dmstatus_resumeack_din;
logic dmstatus_havereset_wren;
logic dmstatus_havereset_rst;
logic dmstatus_haveresetn_wren;
logic dmstatus_resumeack;
logic dmstatus_unavail;
logic dmstatus_running;
logic dmstatus_halted;
logic dmstatus_havereset;
logic dmstatus_havereset, dmstatus_haveresetn;
// dmcontrol
logic resumereq;
@ -297,7 +296,7 @@ module dbg (
// Reset logic
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] | scan_mode;
// system bus register
// sbcs[31:29], sbcs - [22]:sbbusyerror, [21]: sbbusy, [20]:sbreadonaddr, [19:17]:sbaccess, [16]:sbautoincrement, [15]:sbreadondata, [14:12]:sberror, sbsize=32, 128=0, 64/32/16/8 are legal
@ -308,7 +307,7 @@ module dbg (
assign sbcs_reg[4:0] = 5'b01111;
assign sbcs_wren = (dmi_reg_addr == 7'h38) & dmi_reg_en & dmi_reg_wr_en & (sb_state == SBIDLE); // & (sbcs_reg[14:12] == 3'b000);
assign sbcs_sbbusyerror_wren = (sbcs_wren & dmi_reg_wdata[22]) |
((sb_state != SBIDLE) & dmi_reg_en & ((dmi_reg_addr == 7'h39) | (dmi_reg_addr == 7'h3c) | (dmi_reg_addr == 7'h3d)));
(sbcs_reg[21] & dmi_reg_en & ((dmi_reg_wr_en & (dmi_reg_addr == 7'h39)) | (dmi_reg_addr == 7'h3c) | (dmi_reg_addr == 7'h3d)));
assign sbcs_sbbusyerror_din = ~(sbcs_wren & dmi_reg_wdata[22]); // Clear when writing one
rvdffs #(1) sbcs_sbbusyerror_reg (.din(sbcs_sbbusyerror_din), .dout(sbcs_reg[22]), .en(sbcs_sbbusyerror_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
@ -387,15 +386,15 @@ module dbg (
assign dmstatus_resumeack_wren = ((dbg_state == RESUMING) & dec_tlu_resume_ack) | (dmstatus_resumeack & resumereq & dmstatus_halted);
assign dmstatus_resumeack_din = (dbg_state == RESUMING) & dec_tlu_resume_ack;
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_haveresetn_wren = (dmi_reg_addr == 7'h10) & dmi_reg_wdata[28] & dmi_reg_en & dmi_reg_wr_en & dmcontrol_reg[0]; // clear the havereset
assign dmstatus_havereset = ~dmstatus_haveresetn;
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));
rvdffs #(1) dmstatus_haveresetn_reg (.din(1'b1), .dout(dmstatus_haveresetn), .en(dmstatus_haveresetn_wren), .rst_l(rst_l), .clk(dbg_free_clk));
// haltsum0 register
assign haltsum0_reg[31:1] = '0;
@ -631,7 +630,7 @@ module dbg (
case (sb_state)
SBIDLE: begin
sb_nxtstate = sbdata0wr_access ? WAIT_WR : WAIT_RD;
sb_state_en = (sbdata0wr_access | sbreadondata_access | sbreadonaddr_access) & ~(|sbcs_reg[14:12]);
sb_state_en = (sbdata0wr_access | sbreadondata_access | sbreadonaddr_access) & ~(|sbcs_reg[14:12]) & ~sbcs_reg[22];
sbcs_sbbusy_wren = sb_state_en; // set the single read bit if it is a singlread command
sbcs_sbbusy_din = 1'b1;
sbcs_sberror_wren = sbcs_wren & (|dmi_reg_wdata[14:12]); // write to clear the error bits

View File

@ -206,7 +206,7 @@ csr[ csr_mfdc ] = { csr_mfdc presync postsync }
csr[ csr_dcsr ] = { csr_dcsr }
csr[ csr_dpc ] = { csr_dpc }
csr[ csr_mtsel ] = { csr_mtsel }
csr[ csr_mtdata1 ] = { csr_mtdata1 postsync }
csr[ csr_mtdata1 ] = { csr_mtdata1 presync postsync }
csr[ csr_mtdata2 ] = { csr_mtdata2 postsync }
csr[ csr_mhpmc3 ] = { csr_mhpmc3 presync }
csr[ csr_mhpmc4 ] = { csr_mhpmc4 presync }

View File

@ -157,6 +157,8 @@ module dec
input logic iccm_dma_sb_error, // ICCM DMA single bit error
input logic dma_mem_dccm_req,
input logic exu_i0_flush_final, // slot0 flush
input logic exu_i1_flush_final, // slot1 flush
@ -378,6 +380,7 @@ module dec
output logic dec_tlu_sideeffect_posted_disable, // disable posted writes to side-effect address
output logic dec_tlu_core_ecc_disable, // disable core ECC
output logic dec_tlu_sec_alu_disable, // disable secondary ALU
output logic dec_tlu_dccm_nonblock_dma_disable, // disable dma nonblock
output logic dec_tlu_non_blocking_disable, // disable non blocking loads
output logic dec_tlu_fast_div_disable, // disable fast divider
output logic dec_tlu_bpred_disable, // disable branch prediction

View File

@ -70,6 +70,7 @@ module dec_tlu_ctl
input logic lsu_pmu_bus_error, // D side bus error
input logic lsu_pmu_bus_busy, // D side bus busy
input logic dma_mem_dccm_req,
input logic iccm_dma_sb_error, // I side dma single bit error
@ -232,6 +233,7 @@ module dec_tlu_ctl
output logic dec_tlu_dual_issue_disable, // disable dual issue
output logic dec_tlu_core_ecc_disable, // disable core ECC
output logic dec_tlu_sec_alu_disable, // disable secondary ALU
output logic dec_tlu_dccm_nonblock_dma_disable, // disable dma nonblock
output logic dec_tlu_non_blocking_disable, // disable non blocking loads
output logic dec_tlu_fast_div_disable, // disable fast divider
output logic dec_tlu_bpred_disable, // disable branch prediction
@ -256,7 +258,8 @@ module dec_tlu_ctl
logic dec_csr_wen_wb_mod, clk_override, e4e5_int_clk, nmi_lsu_load_type, nmi_lsu_store_type, nmi_int_detected_f, nmi_lsu_load_type_f,
nmi_lsu_store_type_f, allow_dbg_halt_csr_write, dbg_cmd_done_ns, i_cpu_run_req_d1_raw, debug_mode_status, lsu_single_ecc_error_wb,
i0_mp_e4, i1_mp_e4, sel_npc_e4, sel_npc_wb, ce_int, mtval_capture_lsu_wb, wr_mdeau_wb, micect_cout_nc, miccmect_cout_nc,
mdccmect_cout_nc, nmi_in_debug_mode, dpc_capture_npc, dpc_capture_pc, tdata_load, tdata_opcode, tdata_action, perfcnt_halted;
mdccmect_cout_nc, nmi_in_debug_mode, dpc_capture_npc, dpc_capture_pc, tdata_load, tdata_opcode, tdata_action, perfcnt_halted, tdata_chain,
tdata_kill_write;
logic reset_delayed, reset_detect, reset_detected;
@ -359,7 +362,7 @@ module dec_tlu_ctl
logic [2:0] trigger_chain;
logic i0_trigger_hit_e4, i0_trigger_hit_raw_e4, i0_trigger_action_e4,
trigger_hit_e4, trigger_hit_wb, i0_trigger_hit_wb,
mepc_trigger_hit_sel_pc_e4,
mepc_trigger_hit_sel_pc_e4, i0_trigger_set_hit_e4, i1_trigger_set_hit_e4,
mepc_trigger_hit_sel_pc_wb;
logic i1_trigger_hit_e4, i1_trigger_hit_raw_e4, i1_trigger_action_e4;
logic [3:0] update_hit_bit_e4, update_hit_bit_wb, i0_iside_trigger_has_pri_e4, i1_iside_trigger_has_pri_e4,
@ -370,7 +373,7 @@ module dec_tlu_ctl
logic wr_mcgc_wb, wr_mfdc_wb;
logic [8:0] mcgc;
logic [18:0] mfdc;
logic [13:0] mfdc_int, mfdc_ns;
logic [14:0] mfdc_int, mfdc_ns;
logic i_cpu_halt_req_sync_qual, i_cpu_run_req_sync_qual, pmu_fw_halt_req_ns, pmu_fw_halt_req_f, int_timer_stalled,
fw_halt_req, enter_pmu_fw_halt_req, pmu_fw_tlu_halted, pmu_fw_tlu_halted_f, internal_pmu_fw_halt_mode,
internal_pmu_fw_halt_mode_f, int_timer0_int_hold, int_timer1_int_hold, int_timer0_int_hold_f, int_timer1_int_hold_f;
@ -409,9 +412,11 @@ module dec_tlu_ctl
rvoclkhdr lsu_e3_e4_cgc ( .en(lsu_error_pkt_dc3.exc_valid | lsu_error_pkt_dc4.exc_valid | lsu_error_pkt_dc3.single_ecc_error | lsu_error_pkt_dc4.single_ecc_error | clk_override), .l1clk(lsu_e3_e4_clk), .* );
rvoclkhdr lsu_e4_e5_cgc ( .en(lsu_error_pkt_dc4.exc_valid | lsu_exc_valid_wb | clk_override), .l1clk(lsu_e4_e5_clk), .* );
logic freeze_rfpc_e4, rfpc_postsync_in, rfpc_postsync, dma_mem_dccm_req_f;
logic e4e5_clk, e4_valid, e5_valid, e4e5_valid, internal_dbg_halt_mode_f, internal_dbg_halt_mode_f2, internal_dbg_halt_mode_f3;
assign e4_valid = dec_tlu_i0_valid_e4 | dec_tlu_i1_valid_e4;
assign e4e5_valid = e4_valid | e5_valid;
assign e4e5_valid = e4_valid | e5_valid | freeze_rfpc_e4;
rvoclkhdr e4e5_cgc ( .en(e4e5_valid | clk_override), .l1clk(e4e5_clk), .* );
rvoclkhdr e4e5_int_cgc ( .en(e4e5_valid | internal_dbg_halt_mode_f | i_cpu_run_req_d1 | interrupt_valid | interrupt_valid_wb | reset_delayed | pause_expired_e4 | pause_expired_wb | clk_override), .l1clk(e4e5_int_clk), .* );
@ -496,7 +501,7 @@ module dec_tlu_ctl
// acks back to interface
assign mpc_debug_halt_ack_ns = mpc_halt_state_f & internal_dbg_halt_mode_f & mpc_debug_halt_req_sync & core_empty;
assign mpc_debug_run_ack_ns = (mpc_debug_run_req_sync & ~dbg_halt_state_ns & ~mpc_debug_halt_req_sync) | (mpc_debug_run_ack_f & mpc_debug_run_req_sync) ;
assign mpc_debug_run_ack_ns = (mpc_debug_run_req_sync & ~internal_dbg_halt_mode & ~mpc_debug_halt_req_sync) | (mpc_debug_run_ack_f & mpc_debug_run_req_sync) ;
// Pins
assign mpc_debug_halt_ack = mpc_debug_halt_ack_f;
@ -580,7 +585,7 @@ module dec_tlu_ctl
assign pause_expired_e4 = ~dec_pause_state & dec_pause_state_f & ~(ext_int_ready | ce_int_ready | timer_int_ready | int_timer0_int_hold_f | int_timer1_int_hold_f | nmi_int_detected) & ~interrupt_valid_wb & ~debug_halt_req_f & ~pmu_fw_halt_req_f & ~halt_taken_f;
// stall dma fifo if a fence is pending, decode is waiting for lsu to idle before decoding the fence inst.
assign dec_tlu_stall_dma = dec_fence_pending;
assign dec_tlu_stall_dma = dec_fence_pending & dec_tlu_dccm_nonblock_dma_disable; // Stall the DMA for fences when chicken bit is set;
assign dec_tlu_flush_leak_one_wb = dec_tlu_flush_lower_wb & dcsr[`DCSR_STEP] & (dec_tlu_resume_ack | dcsr_single_step_running);
assign dec_tlu_flush_err_wb = dec_tlu_flush_lower_wb & (ic_perr_wb | iccm_sbecc_wb);
@ -661,13 +666,18 @@ module dec_tlu_ctl
// Actions include breakpoint, or dmode. Dmode is only possible if the DMODE bit is set.
// Otherwise, take a breakpoint.
assign trigger_action[3:0] = {mtdata1_t3[`MTDATA1_ACTION] & mtdata1_t3[`MTDATA1_DMODE],
mtdata1_t2[`MTDATA1_ACTION] & mtdata1_t2[`MTDATA1_DMODE],
mtdata1_t2[`MTDATA1_ACTION] & mtdata1_t2[`MTDATA1_DMODE] & ~mtdata1_t2[`MTDATA1_CHAIN],
mtdata1_t1[`MTDATA1_ACTION] & mtdata1_t1[`MTDATA1_DMODE],
mtdata1_t0[`MTDATA1_ACTION] & mtdata1_t0[`MTDATA1_DMODE]};
mtdata1_t0[`MTDATA1_ACTION] & mtdata1_t0[`MTDATA1_DMODE] & ~mtdata1_t0[`MTDATA1_CHAIN]};
// this is needed to set the HIT bit in the triggers
assign update_hit_bit_e4[3:0] = ({4{i0_trigger_hit_e4 }} & i0_trigger_chain_masked_e4[3:0]) |
({4{i1_trigger_hit_e4 & ~i0_trigger_hit_e4}} & i1_trigger_chain_masked_e4[3:0]);
assign i0_trigger_set_hit_e4 = |i0_trigger_e4[3:0] & ~(dec_tlu_flush_lower_wb | dec_tlu_dbg_halted | rfpc_i0_e4);
assign i1_trigger_set_hit_e4 = |i1_trigger_e4[3:0] & ~(dec_tlu_flush_lower_wb | dec_tlu_dbg_halted |
~tlu_i0_commit_cmt | exu_i0_br_mp_e4 | dec_tlu_dbg_halted |
lsu_freeze_pulse_e4 | lsu_i0_rfnpc_dc4 | rfpc_i1_e4);
assign update_hit_bit_e4[3:0] = ({4{i0_trigger_set_hit_e4}} & {i0_trigger_chain_masked_e4[3], i0_trigger_e4[2], i0_trigger_chain_masked_e4[1], i0_trigger_e4[0]} ) |
({4{i1_trigger_set_hit_e4}} & {i1_trigger_chain_masked_e4[3], i1_trigger_e4[2], i1_trigger_chain_masked_e4[1], i1_trigger_e4[0]} );
// action, 1 means dmode. Simultaneous triggers with at least 1 set for dmode force entire action to dmode.
assign i0_trigger_action_e4 = |(i0_trigger_chain_masked_e4[3:0] & trigger_action[3:0]);
@ -730,7 +740,7 @@ module dec_tlu_ctl
assign cpu_halt_ack = i_cpu_halt_req_d1 & pmu_fw_tlu_halted_f;
assign cpu_halt_status = (pmu_fw_tlu_halted_f & ~i_cpu_run_req_d1) | (o_cpu_halt_status & ~i_cpu_run_req_d1 & ~internal_dbg_halt_mode_f);
assign cpu_run_ack = (o_cpu_halt_status & i_cpu_run_req_sync_qual) | (o_cpu_run_ack & i_cpu_run_req_sync_qual);
assign cpu_run_ack = (o_cpu_halt_status & i_cpu_run_req_d1_raw) | (o_cpu_run_ack & i_cpu_run_req_sync);
assign debug_mode_status = internal_dbg_halt_mode_f;
assign o_debug_mode_status = debug_mode_status;// & ~mpc_debug_run_ack_f;
@ -813,9 +823,20 @@ module dec_tlu_ctl
assign tlu_i0_kill_writeb_e4 = rfpc_i0_e4 | lsu_i0_exc_dc4 | inst_acc_e4 | (illegal_e4 & dec_tlu_dbg_halted) | i0_trigger_hit_e4 ;
assign tlu_i1_kill_writeb_e4 = rfpc_i0_e4 | rfpc_i1_e4 | lsu_exc_valid_e4 | exu_i0_br_mp_e4 | inst_acc_e4 | (illegal_e4 & dec_tlu_dbg_halted) | trigger_hit_e4 | lsu_i0_rfnpc_dc4;
// Auto postsync loads that freeze when DMA requests are stalled, if not disabled with MFDC[13].
assign freeze_rfpc_e4 = (lsu_block_interrupts_e4 | (dma_mem_dccm_req_f & lsu_freeze_e4)) & ~dec_tlu_flush_lower_wb & mfdc[13];
assign rfpc_postsync_in = (freeze_rfpc_e4 | rfpc_postsync) & ~tlu_i0_commit_cmt;
assign dec_tlu_dccm_nonblock_dma_disable = ~mfdc[13];
rvdff #(2) freezerfpc_ff (.*, .clk(free_clk),
.din({rfpc_postsync_in, dma_mem_dccm_req}),
.dout({rfpc_postsync, dma_mem_dccm_req_f}));
// refetch PC, microarch flush
// ic errors only in pipe0
assign rfpc_i0_e4 = dec_tlu_i0_valid_e4 & ~tlu_flush_lower_wb & (exu_i0_br_error_e4 | exu_i0_br_start_error_e4 | ic_perr_e4 | iccm_sbecc_e4 | lsu_i0_rfpc_dc4) & ~i0_trigger_hit_e4;
assign rfpc_i0_e4 = freeze_rfpc_e4 | (
dec_tlu_i0_valid_e4 & ~tlu_flush_lower_wb & (exu_i0_br_error_e4 | exu_i0_br_start_error_e4 | ic_perr_e4 | iccm_sbecc_e4 | lsu_i0_rfpc_dc4) & ~i0_trigger_hit_e4);
assign rfpc_i1_e4 = dec_tlu_i1_valid_e4 & ~tlu_flush_lower_wb & ~i0_exception_valid_e4 & ~exu_i0_br_mp_e4 & ~lsu_i0_exc_dc4 & ~lsu_i0_rfnpc_dc4 &
~(exu_i0_br_error_e4 | exu_i0_br_start_error_e4 | ic_perr_e4 | iccm_sbecc_e4 | lsu_i0_rfpc_dc4) &
(exu_i1_br_error_e4 | exu_i1_br_start_error_e4 | lsu_i1_rfpc_dc4) &
@ -1355,13 +1376,15 @@ module dec_tlu_ctl
// MFDC (RW) Feature Disable Control
// [31:19] : Reserved, reads 0x0
// [18:16] : DMA QoS Prty
// [15:11] : Reserved, reads 0x0
// [15:14] : Reserved, reads 0x0
// [13] : Disable blocking DMA
// [12:11] : Reserved, reads 0x0
// [10] : Disable dual issue
// [9] : Disable pic multiple ints
// [8] : Disable core ecc
// [7] : Disable secondary alu?s
// [6] : Disable multiple outstanding sideeffect accesses to bus
// [5] : Disable non-blocking loads/divides
// [5] : Disable non-blocking divides
// [4] : Disable fast divide
// [3] : Disable branch prediction and return stack
// [2] : Disable write buffer coalescing
@ -1372,15 +1395,15 @@ module dec_tlu_ctl
assign wr_mfdc_wb = dec_csr_wen_wb_mod & (dec_csr_wraddr_wb[11:0] == `MFDC);
rvdffe #(14) mfdc_ff (.*, .en(wr_mfdc_wb), .din(mfdc_ns[13:0]), .dout(mfdc_int[13:0]));
rvdffe #(15) mfdc_ff (.*, .en(wr_mfdc_wb), .din(mfdc_ns[14:0]), .dout(mfdc_int[14:0]));
`ifdef RV_BUILD_AXI4
// flip poweron value of bit 6 for AXI build
assign mfdc_ns[13:0] = {~dec_csr_wrdata_wb[18:16],dec_csr_wrdata_wb[10:7], ~dec_csr_wrdata_wb[6], dec_csr_wrdata_wb[5:0]};
assign mfdc[18:0] = {~mfdc_int[13:11], 5'b0, mfdc_int[10:7], ~mfdc_int[6], mfdc_int[5:0]};
assign mfdc_ns[14:0] = {~dec_csr_wrdata_wb[18:16],dec_csr_wrdata_wb[13], dec_csr_wrdata_wb[10:7], ~dec_csr_wrdata_wb[6], dec_csr_wrdata_wb[5:0]};
assign mfdc[18:0] = {~mfdc_int[14:12], 2'b0, mfdc_int[11], 2'b0, mfdc_int[10:7], ~mfdc_int[6], mfdc_int[5:0]};
`else
assign mfdc_ns[13:0] = {~dec_csr_wrdata_wb[18:16],dec_csr_wrdata_wb[10:0]};
assign mfdc[18:0] = {~mfdc_int[13:11], 5'b0, mfdc_int[10:0]};
assign mfdc_ns[14:0] = {~dec_csr_wrdata_wb[18:16],dec_csr_wrdata_wb[13],dec_csr_wrdata_wb[10:0]};
assign mfdc[18:0] = {~mfdc_int[14:12], 2'b0, mfdc_int[11], 2'b0, mfdc_int[10:0]};
`endif
assign dec_tlu_dma_qos_prty[2:0] = mfdc[18:16];
@ -1451,7 +1474,7 @@ module dec_tlu_ctl
// only capture error bus if the MDSEAC reg is not locked
assign mdseac_locked_ns = mdseac_en | (mdseac_locked_f & ~wr_mdeau_wb);
assign mdseac_en = (lsu_imprecise_error_store_any | lsu_imprecise_error_load_any) & ~mdseac_locked_f;
assign mdseac_en = (lsu_imprecise_error_store_any | lsu_imprecise_error_load_any) & ~nmi_int_detected_f & ~mdseac_locked_f;
rvdffe #(32) mdseac_ff (.*, .en(mdseac_en), .din(lsu_imprecise_error_addr_any[31:0]), .dout(mdseac[31:0]));
@ -1783,10 +1806,19 @@ module dec_tlu_ctl
// don't allow clearing DMODE and action=1
assign tdata_action = (dec_csr_wrdata_wb[27] & dbg_tlu_halted_f) & dec_csr_wrdata_wb[12];
// Chain bit has conditions: WARL for triggers without chains. Force to zero if dmode is 0 but next trigger dmode is 1.
assign tdata_chain = mtsel[0] ? 1'b0 : // triggers 1 and 3 chain bit is always zero
mtsel[1] ? dec_csr_wrdata_wb[11] & ~(mtdata1_t3[`MTDATA1_DMODE] & ~dec_csr_wrdata_wb[27]) : // trigger 2
dec_csr_wrdata_wb[11] & ~(mtdata1_t1[`MTDATA1_DMODE] & ~dec_csr_wrdata_wb[27]); // trigger 0
// Kill mtdata1 write if dmode=1 but prior trigger has dmode=0/chain=1. Only applies to T1 and T3
assign tdata_kill_write = mtsel[1] ? dec_csr_wrdata_wb[27] & (~mtdata1_t2[`MTDATA1_DMODE] & mtdata1_t2[`MTDATA1_CHAIN]) : // trigger 3
dec_csr_wrdata_wb[27] & (~mtdata1_t0[`MTDATA1_DMODE] & mtdata1_t0[`MTDATA1_CHAIN]) ; // trigger 1
assign tdata_wrdata_wb[9:0] = {dec_csr_wrdata_wb[27] & dbg_tlu_halted_f,
dec_csr_wrdata_wb[20:19],
tdata_action,
dec_csr_wrdata_wb[11],
tdata_chain,
dec_csr_wrdata_wb[7:6],
tdata_opcode,
dec_csr_wrdata_wb[1],
@ -1797,7 +1829,7 @@ module dec_tlu_ctl
assign mtdata1_t0_ns[9:0] = wr_mtdata1_t0_wb ? tdata_wrdata_wb[9:0] :
{mtdata1_t0[9], update_hit_bit_wb[0] | mtdata1_t0[8], mtdata1_t0[7:0]};
assign wr_mtdata1_t1_wb = dec_csr_wen_wb_mod & (dec_csr_wraddr_wb[11:0] == `MTDATA1) & (mtsel[1:0] == 2'b01) & (~mtdata1_t1[`MTDATA1_DMODE] | dbg_tlu_halted_f);
assign wr_mtdata1_t1_wb = dec_csr_wen_wb_mod & (dec_csr_wraddr_wb[11:0] == `MTDATA1) & (mtsel[1:0] == 2'b01) & (~mtdata1_t1[`MTDATA1_DMODE] | dbg_tlu_halted_f) & ~tdata_kill_write;
assign mtdata1_t1_ns[9:0] = wr_mtdata1_t1_wb ? tdata_wrdata_wb[9:0] :
{mtdata1_t1[9], update_hit_bit_wb[1] | mtdata1_t1[8], mtdata1_t1[7:0]};
@ -1805,7 +1837,7 @@ module dec_tlu_ctl
assign mtdata1_t2_ns[9:0] = wr_mtdata1_t2_wb ? tdata_wrdata_wb[9:0] :
{mtdata1_t2[9], update_hit_bit_wb[2] | mtdata1_t2[8], mtdata1_t2[7:0]};
assign wr_mtdata1_t3_wb = dec_csr_wen_wb_mod & (dec_csr_wraddr_wb[11:0] == `MTDATA1) & (mtsel[1:0] == 2'b11) & (~mtdata1_t3[`MTDATA1_DMODE] | dbg_tlu_halted_f);
assign wr_mtdata1_t3_wb = dec_csr_wen_wb_mod & (dec_csr_wraddr_wb[11:0] == `MTDATA1) & (mtsel[1:0] == 2'b11) & (~mtdata1_t3[`MTDATA1_DMODE] | dbg_tlu_halted_f) & ~tdata_kill_write;
assign mtdata1_t3_ns[9:0] = wr_mtdata1_t3_wb ? tdata_wrdata_wb[9:0] :
{mtdata1_t3[9], update_hit_bit_wb[3] | mtdata1_t3[8], mtdata1_t3[7:0]};
@ -2438,12 +2470,13 @@ assign presync = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]) | (
!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]) | (
dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
&dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[4]
&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]) | (
dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]) | (dec_csr_rdaddr_d[11]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[1]
&!dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[5]
&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
&dec_csr_rdaddr_d[1]);
&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]) | (dec_csr_rdaddr_d[7]
&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]);
assign postsync = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
&dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[5]
@ -2542,7 +2575,7 @@ assign legal_csr = (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d
assign dec_tlu_presync_d = presync & dec_csr_any_unq_d & ~dec_csr_wen_unq_d;
assign dec_tlu_postsync_d = postsync & dec_csr_any_unq_d;
assign dec_tlu_postsync_d = (postsync & dec_csr_any_unq_d) | rfpc_postsync;
assign valid_csr = ( legal_csr & (~(csr_dcsr | csr_dpc | csr_dmst | csr_dicawics | csr_dicad0 | csr_dicad1 | csr_dicago) | dbg_tlu_halted_f));
assign dec_csr_legal_d = ( dec_csr_any_unq_d &
@ -2553,7 +2586,7 @@ assign dec_csr_legal_d = ( dec_csr_any_unq_d &
assign dec_csr_rddata_d[31:0] = ( ({32{csr_misa}} & 32'h40001104) |
({32{csr_mvendorid}} & 32'h00000045) |
({32{csr_marchid}} & 32'h0000000b) |
({32{csr_mimpid}} & 32'h5) |
({32{csr_mimpid}} & 32'h6) |
({32{csr_mstatus}} & {19'b0, 2'b11, 3'b0, mstatus[1], 3'b0, mstatus[0], 3'b0}) |
({32{csr_mtvec}} & {mtvec[30:1], 1'b0, mtvec[0]}) |
({32{csr_mip}} & {1'b0, mip[5:3], 16'b0, mip[2], 3'b0, mip[1], 3'b0, mip[0], 3'b0}) |

View File

@ -105,6 +105,8 @@ module dma_ctrl (
input logic dec_tlu_stall_dma, // stall dma accesses, tlu is attempting to enter halt/debug mode
input logic [2:0] dec_tlu_dma_qos_prty, // DMA QoS priority coming from MFDC [18:15]
output logic dma_mem_dccm_req, // Used by TLU to do rfpc in case of freeze
input logic scan_mode
);
@ -236,8 +238,8 @@ module dma_ctrl (
//------------------------LOGIC STARTS HERE---------------------------------
// FIFO inputs
assign fifo_addr_in[31:0] = dbg_cmd_valid ? dbg_cmd_addr[31:0] : axi_mstr_addr[31:0];
assign fifo_sz_in[2:0] = dbg_cmd_valid ? {1'b0,dbg_cmd_size[1:0]} : axi_mstr_size[2:0];
assign fifo_addr_in[31:0] = dbg_cmd_valid ? dbg_cmd_addr[31:0] : (axi_mstr_write & (axi_mstr_wstrb[7:0] == 8'hf0)) ? {axi_mstr_addr[31:3],1'b1,axi_mstr_addr[1:0]} : axi_mstr_addr[31:0];
assign fifo_sz_in[2:0] = dbg_cmd_valid ? {1'b0,dbg_cmd_size[1:0]} : (axi_mstr_write & ((axi_mstr_wstrb[7:0] == 8'h0f) | (axi_mstr_wstrb[7:0] == 8'hf0))) ? 3'h2 : axi_mstr_size[2:0];
assign fifo_write_in = dbg_cmd_valid ? dbg_cmd_write : axi_mstr_write;
assign fifo_posted_write_in = axi_mstr_valid & axi_mstr_posted_write;
assign fifo_dbg_in = dbg_cmd_valid;
@ -315,11 +317,13 @@ module dma_ctrl (
// Error logic
assign dma_address_error = axi_mstr_valid & (~(dma_addr_in_dccm | dma_addr_in_iccm)); // request not for ICCM or DCCM
assign dma_alignment_error = axi_mstr_valid & ~dma_address_error &
(((axi_mstr_size[2:0] == 3'h1) & (axi_mstr_addr[0] | (axi_mstr_write & (axi_mstr_wstrb[axi_mstr_addr[2:0]+:2] != 2'b11)))) | // HW size but unaligned
((axi_mstr_size[2:0] == 3'h2) & ((|axi_mstr_addr[1:0]) | (axi_mstr_write & (axi_mstr_wstrb[axi_mstr_addr[2:0]+:4] != 4'hf)))) | // W size but unaligned
((axi_mstr_size[2:0] == 3'h3) & ((|axi_mstr_addr[2:0]) | (axi_mstr_write & (axi_mstr_wstrb[7:0] != 8'hff)))) | // DW size but unaligned
(((axi_mstr_size[2:0] == 3'h1) & axi_mstr_addr[0]) | // HW size but unaligned
((axi_mstr_size[2:0] == 3'h2) & (|axi_mstr_addr[1:0])) | // W size but unaligned
((axi_mstr_size[2:0] == 3'h3) & (|axi_mstr_addr[2:0])) | // DW size but unaligned
(dma_addr_in_iccm & ~((axi_mstr_size[1:0] == 2'b10) | (axi_mstr_size[1:0] == 2'b11))) | // ICCM access not word size
(dma_addr_in_dccm & axi_mstr_write & ~((axi_mstr_size[1:0] == 2'b10) | (axi_mstr_size[1:0] == 2'b11)))); // DCCM write not word size
(dma_addr_in_dccm & axi_mstr_write & ~((axi_mstr_size[1:0] == 2'b10) | (axi_mstr_size[1:0] == 2'b11))) | // DCCM write not word size
(axi_mstr_write & (axi_mstr_size[2:0] == 3'h2) & (axi_mstr_wstrb[axi_mstr_addr[2:0]+:4] != 4'hf)) | // Write byte enables not aligned for word store
(axi_mstr_write & (axi_mstr_size[2:0] == 3'h3) & ~((axi_mstr_wstrb[7:0] == 8'h0f) | (axi_mstr_wstrb[7:0] == 8'hf0) | (axi_mstr_wstrb[7:0] == 8'hff)))); // Write byte enables not aligned for dword store
//Dbg outputs
assign dma_dbg_ready = fifo_empty & dbg_dma_bubble;
@ -358,6 +362,7 @@ module dma_ctrl (
// Core outputs
assign dma_mem_req = fifo_valid[RdPtr] & ~fifo_rpend[RdPtr] & ~fifo_done[RdPtr] & ~(|fifo_error[RdPtr]) & (~fifo_write[RdPtr] | fifo_data_valid[RdPtr]);
assign dma_mem_dccm_req = dma_mem_req & fifo_dccm_valid[RdPtr]; // Only used by TLU for rfpc
assign dma_dccm_req = dma_mem_req & fifo_dccm_valid[RdPtr] & dccm_ready;
assign dma_iccm_req = dma_mem_req & fifo_iccm_valid[RdPtr] & iccm_ready;
assign dma_mem_addr[31:0] = fifo_addr[RdPtr];

View File

@ -22,7 +22,6 @@
//-------------------------------------------------------------------------------------
module dmi_wrapper(
// JTAG signals
input trst_n, // JTAG reset
input tck, // JTAG clock

View File

@ -41,7 +41,7 @@ module lsu
input logic dec_tlu_cancel_e4, // cancel the bus load in dc4 and reset the freeze
// chicken signals
input logic dec_tlu_non_blocking_disable, // disable the non block
input logic dec_tlu_dccm_nonblock_dma_disable, // disable dma nonblock
input logic dec_tlu_wb_coalescing_disable, // disable the write buffer coalesce
input logic dec_tlu_ld_miss_byp_wb_disable, // disable the miss bypass in the write buffer
input logic dec_tlu_sideeffect_posted_disable, // disable posted writes to sideeffect addr to the bus

View File

@ -158,7 +158,7 @@ module lsu_addrcheck
// 3. DCCM -> PIC offset cross when DCCM/PIC in same region (PIC access are always word aligned so no cross possible from PIC->DCCM)
// 4. Ld/St access to picm are not word aligned
// 5. Address not in protected space or dccm/pic region
if (DCCM_REGION == PIC_REGION) begin
if (DCCM_ENABLE & (DCCM_REGION == PIC_REGION)) begin
assign access_fault_dc1 = ((start_addr_in_dccm_region_dc1 & ~(start_addr_in_dccm_dc1 | start_addr_in_pic_dc1)) |
(end_addr_in_dccm_region_dc1 & ~(end_addr_in_dccm_dc1 | end_addr_in_pic_dc1)) |
(start_addr_in_dccm_dc1 & end_addr_in_pic_dc1) |

View File

@ -42,7 +42,7 @@ module lsu_bus_buffer
input logic clk,
input logic rst_l,
input logic scan_mode,
input logic dec_tlu_non_blocking_disable, // disable non block
input logic dec_tlu_dccm_nonblock_dma_disable, // disable dma nonblock
input logic dec_tlu_wb_coalescing_disable, // disable write buffer coalescing
input logic dec_tlu_ld_miss_byp_wb_disable, // disable ld miss bypass of the write buffer
input logic dec_tlu_sideeffect_posted_disable, // disable posted writes to sideeffect addr to the bus
@ -752,7 +752,7 @@ module lsu_bus_buffer
// Freeze logic
assign FreezePtrEn = lsu_busreq_dc3 & lsu_pkt_dc3.load & ld_freeze_dc3;
assign ld_freeze_en = (is_sideeffects_dc2 | dec_nonblock_load_freeze_dc2 | dec_tlu_non_blocking_disable) & lsu_busreq_dc2 & lsu_pkt_dc2.load & ~lsu_freeze_dc3 & ~flush_dc2_up & ~ld_full_hit_dc2;
assign ld_freeze_en = (dec_nonblock_load_freeze_dc2 | (dec_tlu_dccm_nonblock_dma_disable & is_sideeffects_dc2)) & lsu_busreq_dc2 & lsu_pkt_dc2.load & ~lsu_freeze_dc3 & ~flush_dc2_up & ~ld_full_hit_dc2;
always_comb begin
ld_freeze_rst = flush_dc3 | (dec_tlu_cancel_e4 & ld_freeze_dc3);
for (int i=0; i<DEPTH; i++) begin
@ -766,7 +766,7 @@ module lsu_bus_buffer
assign ld_bus_error_addr_dc3[31:0] = buf_addr[FreezePtr][31:0];
// Non blocking ports
assign lsu_nonblock_load_valid_dc3 = lsu_busreq_dc3 & lsu_pkt_dc3.valid & lsu_pkt_dc3.load & ~flush_dc3 & ~dec_nonblock_load_freeze_dc3 & ~lsu_freeze_dc3 & ~dec_tlu_non_blocking_disable;
assign lsu_nonblock_load_valid_dc3 = lsu_busreq_dc3 & lsu_pkt_dc3.valid & lsu_pkt_dc3.load & ~flush_dc3 & ~dec_nonblock_load_freeze_dc3 & ~lsu_freeze_dc3;
assign lsu_nonblock_load_tag_dc3[DEPTH_LOG2-1:0] = WrPtr0_dc3[DEPTH_LOG2-1:0];
assign lsu_nonblock_load_inv_dc5 = lsu_nonblock_load_valid_dc5 & ~lsu_commit_dc5;
assign lsu_nonblock_load_inv_tag_dc5[DEPTH_LOG2-1:0] = WrPtr0_dc5[DEPTH_LOG2-1:0]; // dc5 tag needs to be accurate even if there is no invalidate
@ -781,10 +781,10 @@ module lsu_bus_buffer
lsu_nonblock_load_data_hi[31:0] = '0;
for (int i=0; i<DEPTH; i++) begin
// Use buf_rst[i] instead of buf_state_en[i] for timing
lsu_nonblock_load_data_valid_hi |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_rst[i] & ~dec_tlu_non_blocking_disable & buf_nb[i] & ~buf_error[i] & (buf_dual[i] & buf_dualhi[i]);
lsu_nonblock_load_data_valid_lo |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_rst[i] & ~dec_tlu_non_blocking_disable & buf_nb[i] & ~buf_error[i] & (~buf_dual[i] | ~buf_dualhi[i]);
lsu_nonblock_load_data_error_hi |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_rst[i] & ~dec_tlu_non_blocking_disable & buf_error[i] & buf_nb[i] & (buf_dual[i] & buf_dualhi[i]);
lsu_nonblock_load_data_error_lo |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_rst[i] & ~dec_tlu_non_blocking_disable & buf_error[i] & buf_nb[i] & (~buf_dual[i] | ~buf_dualhi[i]);
lsu_nonblock_load_data_valid_hi |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_rst[i] & buf_nb[i] & ~buf_error[i] & (buf_dual[i] & buf_dualhi[i]);
lsu_nonblock_load_data_valid_lo |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_rst[i] & buf_nb[i] & ~buf_error[i] & (~buf_dual[i] | ~buf_dualhi[i]);
lsu_nonblock_load_data_error_hi |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_rst[i] & buf_error[i] & buf_nb[i] & (buf_dual[i] & buf_dualhi[i]);
lsu_nonblock_load_data_error_lo |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_rst[i] & buf_error[i] & buf_nb[i] & (~buf_dual[i] | ~buf_dualhi[i]);
lsu_nonblock_load_data_tag[DEPTH_LOG2-1:0] |= DEPTH_LOG2'(i) & {DEPTH_LOG2{((buf_state[i] == DONE) & buf_nb[i] & buf_rst[i] & (~buf_dual[i] | ~buf_dualhi[i]))}};
lsu_nonblock_load_data_lo[31:0] |= buf_data[i][31:0] & {32{((buf_state[i] == DONE) & buf_nb[i] & buf_rst[i] & (~buf_dual[i] | ~buf_dualhi[i]))}};
lsu_nonblock_load_data_hi[31:0] |= buf_data[i][31:0] & {32{((buf_state[i] == DONE) & buf_nb[i] & buf_rst[i] & (buf_dual[i] & buf_dualhi[i]))}};

View File

@ -28,7 +28,7 @@ module lsu_bus_intf
input logic clk,
input logic rst_l,
input logic scan_mode,
input logic dec_tlu_non_blocking_disable, // disable non block
input logic dec_tlu_dccm_nonblock_dma_disable, // disable dma nonblock
input logic dec_tlu_wb_coalescing_disable, // disable write buffer coalescing
input logic dec_tlu_ld_miss_byp_wb_disable, // disable ld miss bypass of the write buffer
input logic dec_tlu_sideeffect_posted_disable, // disable posted writes to sideeffect addr to the bus

View File

@ -811,6 +811,8 @@ module swerv
logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] exu_i0_br_index_e4;
logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] exu_i1_br_index_e4;
logic dma_mem_dccm_req;
logic dma_dccm_req;
logic dma_iccm_req;
logic [31:0] dma_mem_addr;
@ -865,6 +867,7 @@ module swerv
// feature disable from mfdc
logic dec_tlu_sec_alu_disable;
logic dec_tlu_dccm_nonblock_dma_disable; // disable dma nonblock
logic dec_tlu_non_blocking_disable;
logic dec_tlu_fast_div_disable;
logic dec_tlu_bpred_disable;
@ -970,6 +973,7 @@ module swerv
assign core_dbg_rddata[31:0] = dma_dbg_cmd_done ? dma_dbg_rddata[31:0] : dec_dbg_rddata[31:0];
dbg dbg (
.rst_l(core_rst_l),
.clk_override(dec_tlu_misc_clk_override),
.*
);
@ -1034,6 +1038,7 @@ module swerv
// AXI4 -> AHB Gasket for LSU
axi4_to_ahb #(.TAG(LSU_BUS_TAG)) lsu_axi4_to_ahb (
.rst_l(core_rst_l),
.clk_override(dec_tlu_bus_clk_override),
.bus_clk_en(lsu_bus_clk_en),
@ -1089,6 +1094,7 @@ module swerv
// AXI4 -> AHB Gasket for System Bus
axi4_to_ahb #(.TAG(SB_BUS_TAG)) sb_axi4_to_ahb (
.rst_l(dbg_rst_l),
.clk_override(dec_tlu_bus_clk_override),
.bus_clk_en(dbg_bus_clk_en),
@ -1144,6 +1150,7 @@ module swerv
axi4_to_ahb #(.TAG(IFU_BUS_TAG)) ifu_axi4_to_ahb (
.clk(clk),
.rst_l(core_rst_l),
.clk_override(dec_tlu_bus_clk_override),
.bus_clk_en(ifu_bus_clk_en),
@ -1199,6 +1206,7 @@ module swerv
//AHB -> AXI4 Gasket for DMA
ahb_to_axi4 #(.TAG(DMA_BUS_TAG)) dma_ahb_to_axi4 (
.rst_l(core_rst_l),
.clk_override(dec_tlu_bus_clk_override),
.bus_clk_en(dma_bus_clk_en),

View File

@ -401,6 +401,7 @@ module swerv_wrapper
logic [31:0] dmi_reg_rdata;
logic dmi_hard_reset;
// Instantiate the swerv core
swerv swerv (
.*
@ -414,7 +415,6 @@ module swerv_wrapper
// Instantiate the JTAG/DMI
dmi_wrapper dmi_wrapper (
// JTAG signals
.trst_n(jtag_trst_n), // JTAG reset
.tck (jtag_tck), // JTAG clock
@ -433,7 +433,7 @@ module swerv_wrapper
.reg_en (dmi_reg_en), // 1 bit Write interface bit to Processor
.reg_wr_en (dmi_reg_wr_en), // 1 bit Write enable to Processor
.dmi_hard_reset (dmi_hard_reset) //a hard reset of the DTM, causing the DTM to forget about any outstanding DMI transactions
);
);
endmodule

View File

@ -1,3 +1,20 @@
# SweRV RISC-V Core<sup>TM</sup> 1.9 from Western Digital
## Release Notes
* Removed unused scan_mode input from dmi_wrapper (PR#89)
* Enhanced DMA/Side-Effect-load interlock to conditionally allow Side-Effect loads to be non-blocking
* See PRM for new enable bit in MFDC[13]
* Bug fixes for NMI, MPC, PMU corner cases, MPC ack timing fixes
* Trigger chaining compliance fixes for 0.13.2 missing cases
* Fixed qualification in DCCM access fault equation
* Updated reset hookup for AHB gasket
* Demo TB updates:
* added AXI LSU/DMA bridge and ICCM preload by CPU test,
* dhrystone test,
* exec.log shows instruction mnemonics
# SweRV RISC-V Core<sup>TM</sup> 1.8 from Western Digital
## Release Notes

View File

@ -1,35 +1,6 @@
#include "defines.h"
#define ITERATIONS 1
extern int STACK;
void main();
#define STDOUT 0xd0580000
__asm (".section .text");
__asm (".global _start");
__asm ("_start:");
// Enable Caches in MRAC
__asm ("li t0, 0x5f555555");
__asm ("csrw 0x7c0, t0");
// Set stack pointer.
__asm ("la sp, STACK");
__asm ("jal main");
// Write 0xff to STDOUT for TB to termiate test.
__asm (".global _finish");
__asm ("_finish:");
__asm ("li t0, 0xd0580000");
__asm ("addi t1, zero, 0xff");
__asm ("sb t1, 0(t0)");
__asm ("beq x0, x0, _finish");
__asm (".rept 10");
__asm ("nop");
__asm (".endr");
/*
@ -1200,7 +1171,7 @@ MAIN_RETURN_TYPE main(int argc, char *argv[]) {
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("Iterat/Sec/MHz : %d.%d\n",1000*default_num_contexts*results[0].iterations/time_in_secs(total_time),
ee_printf("Iterat/Sec/MHz : %d.%02d\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) {
@ -2182,213 +2153,6 @@ void portable_fini(core_portable *p)
}
#include <stdarg.h>
// Special address. Writing (store byte instruction) to this address
// causes the simulator to write to the console.
volatile char __whisper_console_io = 0;
static int
whisperPutc(char c)
{
// __whisper_console_io = c;
// __whisper_console_io = c;
*(volatile char*)(STDOUT) = c;
return c;
}
static int
whisperPuts(const char* s)
{
while (*s)
whisperPutc(*s++);
return 1;
}
static int
whisperPrintDecimal(int value)
{
char buffer[20];
int charCount = 0;
unsigned neg = value < 0;
if (neg)
{
value = -value;
whisperPutc('-');
}
do
{
char c = '0' + (value % 10);
value = value / 10;
buffer[charCount++] = c;
}
while (value);
char* p = buffer + charCount - 1;
for (unsigned i = 0; i < charCount; ++i)
whisperPutc(*p--);
if (neg)
charCount++;
return charCount;
}
static int
whisperPrintInt(int value, int base)
{
if (base == 10)
return whisperPrintDecimal(value);
char buffer[20];
int charCount = 0;
unsigned uu = value;
if (base == 8)
{
do
{
char c = '0' + (uu & 7);
buffer[charCount++] = c;
uu >>= 3;
}
while (uu);
}
else if (base == 16)
{
do
{
int digit = uu & 0xf;
char c = digit < 10 ? '0' + digit : 'a' + digit - 10;
buffer[charCount++] = c;
uu >>= 4;
}
while (uu);
}
else
return -1;
char* p = buffer + charCount - 1;
for (unsigned i = 0; i < charCount; ++i)
whisperPutc(*p--);
return charCount;
}
int
whisperPrintfImpl(const char* format, va_list ap)
{
int count = 0; // Printed character count
for (const char* fp = format; *fp; fp++)
{
if (*fp != '%')
{
whisperPutc(*fp);
++count;
continue;
}
++fp; // Skip %
if (*fp == 0)
break;
if (*fp == '%')
{
whisperPutc('%');
continue;
}
if (*fp == '-')
{
fp++; // Pad right not yet implemented.
}
while (*fp == '0')
{
fp++; // Pad zero not yet implented.
}
if (*fp == '*')
{
int width = va_arg(ap, int);
fp++; // Width not yet implemented.
}
else
{
while (*fp >= '0' && *fp <= '9')
++fp; // Width not yet implemented.
}
switch (*fp)
{
case 'd':
count += whisperPrintDecimal(va_arg(ap, int));
break;
case 'u':
count += whisperPrintDecimal((unsigned) va_arg(ap, unsigned));
break;
case 'x':
case 'X':
count += whisperPrintInt(va_arg(ap, int), 16);
break;
case 'o':
count += whisperPrintInt(va_arg(ap, int), 8);
break;
case 'c':
whisperPutc(va_arg(ap, int));
++count;
break;
case 's':
count += whisperPuts(va_arg(ap, char*));
break;
}
}
return count;
}
int
whisperPrintf(const char* format, ...)
{
va_list ap;
va_start(ap, format);
int code = whisperPrintfImpl(format, ap);
va_end(ap);
return code;
}
int
printf(const char* format, ...)
{
va_list ap;
va_start(ap, format);
int code = whisperPrintfImpl(format, ap);
va_end(ap);
return code;
}
void* memset(void* s, int c, size_t n)
{
asm("mv t0, a0");

1
testbench/asm/cmark.mki Normal file
View File

@ -0,0 +1 @@
OFILES = crt0.o printf.o cmark.o

View File

@ -0,0 +1 @@
cmark.mki

View File

@ -7,10 +7,12 @@ MEMORY {
ICCM : ORIGIN = 0xee000000, LENGTH = 0x80000
DCCM : ORIGIN = 0xf0040000, LENGTH = 0x10000
CTL : ORIGIN = 0xfffffff0, LENGTH = 16
IO : ORIGIN = 0xd0580000, LENGTH = 0x1000
}
SECTIONS {
.text_init : {*(.text_init)} > EXTCODE
.text.init : {*(.text.init)} > EXTCODE
init_end = .;
.data.io : { *(.data.io) } > IO
.text : { *(.text) *(.text.startup)} > ICCM
text_end = .;
.data : { *(.*data) *(.rodata*) *(.sbss) STACK = ALIGN(16) + 0x1000;} > DCCM

View File

@ -0,0 +1 @@
cmark.mki

48
testbench/asm/crt0.s Normal file
View File

@ -0,0 +1,48 @@
# SPDX-License-Identifier: Apache-2.0
# 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.
# 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.
#
// startup code to support HLL programs
#include "defines.h"
.section .text.init
.global _start
_start:
// enable caching, except region 0xd
li t0, 0x59555555
csrw 0x7c0, t0
la sp, STACK
call main
.global _finish
_finish:
la t0, tohost
li t1, 0xff
sb t1, 0(t0) // DemoTB test termination
li t1, 1
sw t1, 0(t0) // Whisper test termination
beq x0, x0, _finish
.rept 10
nop
.endr
.section .data.io
.global tohost
tohost: .word 0

View File

@ -5,9 +5,10 @@ ENTRY(_start)
SECTIONS {
.text : { *(.text*) }
_end = .;
. = 0xd0580000;
.data.io : { *(.data.io) }
. = 0xf0040000;
.data : { *(.*data) *(.rodata*) *(.sbss) STACK = ALIGN(16) + 0x1000;}
.bss : { *(.bss) }
.data : { *(.*data) *(.rodata*) *(.*bss) STACK = ALIGN(16) + 0x1000;}
. = 0xfffffff8;
.data.ctl : { LONG(0xf0040000); LONG(STACK) }
}

View File

@ -0,0 +1,13 @@
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
SECTIONS {
.text : { *(.text*) }
. = 0x10000;
.data : { *(.*data) *(.rodata*)}
. = ALIGN(4);
printf_start = .;
. = 0xee000000;
.data_load : AT(printf_start) {*(.data_text)}
printf_end = printf_start + SIZEOF(.data_load);
}

View File

@ -0,0 +1,85 @@
// 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
.set mfdc, 0x7f9
.extern printf_start, printf_end
// Code to execute
.section .text
.global _start
_start:
// Enable Caches in MRAC
li x1, 0x5f555555
csrw 0x7c0, x1
li x3, 4 + (1<<13) // unblock DMA be stalled by fences mfdc[13]!!!
csrw mfdc, x3 // disable store merging mfdc[2]
li x3, RV_ICCM_SADR
la x4, printf_start
la x5, printf_end
load:
lw x6, 0 (x4)
sw x6, 0 (x3)
addi x4,x4,4
addi x3,x3,4
bltu x4, x5, load
fence.i
call printf
// 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
hw_data:
.ascii "----------------------------------------\n"
.ascii "Hello World from SweRV EL2 ICCM @WDC !!\n"
.ascii "----------------------------------------\n"
.byte 0
.section .data_text, "ax"
// Load string from hw_data
// and write to stdout address
printf:
li x3, STDOUT
la x4, hw_data
loop:
lb x5, 0(x4)
sb x5, 0(x3)
addi x4, x4, 1
bnez x5, loop
ret
.long 0,1,2,3,4

312
testbench/asm/printf.c Normal file
View File

@ -0,0 +1,312 @@
// SPDX-License-Identifier: Apache-2.0
// 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.
// 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.
//
#include <stdarg.h>
#include <stdint.h>
extern volatile char tohost;
static int
whisperPutc(char c)
{
tohost = c;
return c;
}
static int
whisperPuts(const char* s)
{
while (*s)
whisperPutc(*s++);
whisperPutc('\n');
// whisperPutc(0xd);
return 1;
}
static int
whisperPrintUnsigned(unsigned value, int width, char pad)
{
char buffer[20];
int charCount = 0;
do
{
char c = '0' + (value % 10);
value = value / 10;
buffer[charCount++] = c;
}
while (value);
for (int i = charCount; i < width; ++i)
whisperPutc(pad);
char* p = buffer + charCount - 1;
for (int i = 0; i < charCount; ++i)
whisperPutc(*p--);
return charCount;
}
static int
whisperPrintDecimal(int value, int width, char pad)
{
char buffer[20];
int charCount = 0;
unsigned neg = value < 0;
if (neg)
{
value = -value;
whisperPutc('-');
width--;
}
do
{
char c = '0' + (value % 10);
value = value / 10;
buffer[charCount++] = c;
}
while (value);
for (int i = charCount; i < width; ++i)
whisperPutc(pad);
char* p = buffer + charCount - 1;
for (int i = 0; i < charCount; ++i)
whisperPutc(*p--);
if (neg)
charCount++;
return charCount;
}
static int
whisperPrintInt(int value, int width, int pad, int base)
{
if (base == 10)
return whisperPrintDecimal(value, width, pad);
char buffer[20];
int charCount = 0;
unsigned uu = value;
if (base == 8)
{
do
{
char c = '0' + (uu & 7);
buffer[charCount++] = c;
uu >>= 3;
}
while (uu);
}
else if (base == 16)
{
do
{
int digit = uu & 0xf;
char c = digit < 10 ? '0' + digit : 'a' + digit - 10;
buffer[charCount++] = c;
uu >>= 4;
}
while (uu);
}
else
return -1;
char* p = buffer + charCount - 1;
for (unsigned i = 0; i < charCount; ++i)
whisperPutc(*p--);
return charCount;
}
/*
// Print with g format
static int
whisperPrintDoubleG(double value)
{
return 0;
}
// Print with f format
static int
whisperPrintDoubleF(double value)
{
return 0;
}
*/
int
whisperPrintfImpl(const char* format, va_list ap)
{
int count = 0; // Printed character count
for (const char* fp = format; *fp; fp++)
{
char pad = ' ';
int width = 0; // Field width
if (*fp != '%')
{
whisperPutc(*fp);
++count;
continue;
}
++fp; // Skip %
if (*fp == 0)
break;
if (*fp == '%')
{
whisperPutc('%');
continue;
}
while (*fp == '0')
{
pad = '0';
fp++; // Pad zero not yet implented.
}
if (*fp == '-')
{
fp++; // Pad right not yet implemented.
}
if (*fp == '*')
{
int outWidth = va_arg(ap, int);
fp++; // Width not yet implemented.
}
else if (*fp >= '0' && *fp <= '9')
{ // Width not yet implemented.
while (*fp >= '0' && *fp <= '9')
width = width * 10 + (*fp++ - '0');
}
switch (*fp)
{
case 'd':
count += whisperPrintDecimal(va_arg(ap, int), width, pad);
break;
case 'u':
count += whisperPrintUnsigned((unsigned) va_arg(ap, unsigned), width, pad);
break;
case 'x':
case 'X':
count += whisperPrintInt(va_arg(ap, int), width, pad, 16);
break;
case 'o':
count += whisperPrintInt(va_arg(ap, int), width, pad, 8);
break;
case 'c':
whisperPutc(va_arg(ap, int));
++count;
break;
case 's':
count += whisperPuts(va_arg(ap, char*));
break;
/*
case 'g':
count += whisperPrintDoubleG(va_arg(ap, double));
break;
case 'f':
count += whisperPrintDoubleF(va_arg(ap, double));
*/
}
}
return count;
}
int
whisperPrintf(const char* format, ...)
{
va_list ap;
va_start(ap, format);
int code = whisperPrintfImpl(format, ap);
va_end(ap);
return code;
}
int
putchar(int c)
{
return whisperPutc(c);
}
struct FILE;
int
putc(int c, struct FILE* f)
{
return whisperPutc(c);
}
int
puts(const char* s)
{
return whisperPuts(s);
}
int
printf(const char* format, ...)
{
va_list ap;
va_start(ap, format);
int code = whisperPrintfImpl(format, ap);
va_end(ap);
return code;
}
// function to read cpu mcycle csr for performance measurements
// simplified version
uint64_t get_mcycle(){
unsigned int mcyclel;
unsigned int mcycleh0 = 0, mcycleh1=1;
uint64_t cycles;
while(mcycleh0 != mcycleh1) {
asm volatile ("csrr %0,mcycleh" : "=r" (mcycleh0) );
asm volatile ("csrr %0,mcycle" : "=r" (mcyclel) );
asm volatile ("csrr %0,mcycleh" : "=r" (mcycleh1) );
}
cycles = mcycleh1;
return (cycles << 32) | mcyclel;
}

View File

@ -0,0 +1,201 @@
// connects LSI master to external AXI slave and DMA slave
module axi_lsu_dma_bridge
#(
parameter M_ID_WIDTH = 8,
parameter S0_ID_WIDTH = 8
)
(
input clk,
input reset_l,
// master read bus
input m_arvalid,
input [M_ID_WIDTH-1:0] m_arid,
input[31:0] m_araddr,
output m_arready,
output m_rvalid,
input m_rready,
output [63:0] m_rdata,
output [M_ID_WIDTH-1:0] m_rid,
output [1:0] m_rresp,
output m_rlast,
// master write bus
input m_awvalid,
input [M_ID_WIDTH-1:0] m_awid,
input[31:0] m_awaddr,
output m_awready,
input m_wvalid,
output m_wready,
output[1:0] m_bresp,
output m_bvalid,
output[M_ID_WIDTH-1:0] m_bid,
input m_bready,
// slave 0 if general ext memory
output s0_arvalid,
input s0_arready,
input s0_rvalid,
input[S0_ID_WIDTH-1:0] s0_rid,
input[1:0] s0_rresp,
input[63:0] s0_rdata,
input s0_rlast,
output s0_rready,
output s0_awvalid,
input s0_awready,
output s0_wvalid,
input s0_wready,
input[1:0] s0_bresp,
input s0_bvalid,
input[S0_ID_WIDTH-1:0] s0_bid,
output s0_bready,
// slave 1 if DMA port
output s1_arvalid,
input s1_arready,
input s1_rvalid,
input[1:0] s1_rresp,
input[63:0] s1_rdata,
input s1_rlast,
output s1_rready,
output s1_awvalid,
input s1_awready,
output s1_wvalid,
input s1_wready,
input[1:0] s1_bresp,
input s1_bvalid,
output s1_bready
);
parameter ICCM_BASE = `RV_ICCM_BITS; // in LSBs
localparam IDFIFOSZ = $clog2(`RV_DMA_BUF_DEPTH);
bit[31:0] iccm_real_base_addr = `RV_ICCM_SADR ;
wire ar_slave_select;
wire aw_slave_select;
wire w_slave_select;
wire rresp_select;
wire bresp_select;
wire ar_iccm_select;
wire aw_iccm_select;
reg [1:0] wsel_iptr, wsel_optr;
reg [2:0] wsel_count;
reg [3:0] wsel;
reg [M_ID_WIDTH-1:0] arid [1<<IDFIFOSZ];
reg [M_ID_WIDTH-1:0] awid [1<<IDFIFOSZ];
reg [IDFIFOSZ-1:0] arid_cnt;
reg [IDFIFOSZ-1:0] awid_cnt;
reg [IDFIFOSZ-1:0] rid_cnt;
reg [IDFIFOSZ-1:0] bid_cnt;
// 1 select slave 1; 0 - slave 0
assign ar_slave_select = ar_iccm_select;
assign aw_slave_select = aw_iccm_select;
assign ar_iccm_select = m_araddr[31:ICCM_BASE] == iccm_real_base_addr[31:ICCM_BASE];
assign aw_iccm_select = m_awaddr[31:ICCM_BASE] == iccm_real_base_addr[31:ICCM_BASE];
assign s0_arvalid = m_arvalid & ~ar_slave_select;
assign s1_arvalid = m_arvalid & ar_slave_select;
assign m_arready = ar_slave_select ? s1_arready : s0_arready;
assign s0_awvalid = m_awvalid & ~aw_slave_select;
assign s1_awvalid = m_awvalid & aw_slave_select;
assign m_awready = aw_slave_select ? s1_awready : s0_awready;
assign s0_wvalid = m_wvalid & ~w_slave_select;
assign s1_wvalid = m_wvalid & w_slave_select;
assign m_wready = w_slave_select ? s1_wready : s0_wready;
assign w_slave_select = (wsel_count == 0 || wsel_count[2]) ? aw_slave_select : wsel[wsel_optr];
assign m_rvalid = s0_rvalid | s1_rvalid;
assign s0_rready = m_rready & ~rresp_select;
assign s1_rready = m_rready & rresp_select;
assign m_rdata = rresp_select ? s1_rdata : s0_rdata;
assign m_rresp = rresp_select ? s1_rresp : s0_rresp;
assign m_rid = rresp_select ? arid[rid_cnt] : s0_rid;
assign m_rlast = rresp_select ? s1_rlast : s0_rlast;
assign rresp_select = s1_rvalid & ~s0_rvalid;
assign m_bvalid = s0_bvalid | s1_bvalid;
assign s0_bready = m_bready & ~bresp_select;
assign s1_bready = m_bready & bresp_select;
assign m_bid = bresp_select ? awid[bid_cnt] : s0_bid;
assign m_bresp = bresp_select ? s1_bresp : s0_bresp;
assign bresp_select = s1_bvalid & ~s0_bvalid;
// W-channel select fifo
always @ (posedge clk or negedge reset_l)
if(!reset_l) begin
wsel_count <= '0;
wsel_iptr <= '0;
wsel_optr <= '0;
end
else begin
if(m_awvalid & m_awready) begin
wsel[wsel_iptr] <= aw_slave_select;
if(!(m_wready & m_wvalid )) wsel_count <= wsel_count + 1;
wsel_iptr <= wsel_iptr + 1;
end
if(m_wvalid & m_wready) begin
if(!(m_awready & m_awvalid ) ) wsel_count <= wsel_count - 1;
wsel_optr <= wsel_optr + 1;
end
end
// id replacement for narrow ID slave
always @ (posedge clk or negedge reset_l)
if(!reset_l) begin
arid_cnt <= '0;
rid_cnt <= '0;
end
else begin
if(ar_slave_select & m_arready & m_arvalid) begin
arid[arid_cnt] <= m_arid;
arid_cnt <= arid_cnt + 1;
end
if(rresp_select & m_rready & m_rvalid) begin
rid_cnt <= rid_cnt + 1;
end
end
always @ (posedge clk or negedge reset_l)
if(!reset_l) begin
awid_cnt <= '0;
bid_cnt <= '0;
end
else begin
if(aw_slave_select & m_awready & m_awvalid) begin
awid[awid_cnt] <= m_awid;
awid_cnt <= awid_cnt + 1;
end
if(bresp_select & m_bready & m_bvalid) begin
bid_cnt <= bid_cnt + 1;
end
end
endmodule

395
testbench/dasm.svi Normal file
View File

@ -0,0 +1,395 @@
// 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.
//
// Run time disassembler functions
// supports RISCV extentions I, C, M, A
`ifndef RV_NUM_THREADS
`define RV_NUM_THREADS 1
`endif
bit[31:0] [31:0] gpr[`RV_NUM_THREADS];
// main DASM function
function string dasm(input[31:0] opcode, input[31:0] pc, input[4:0] regn, input[31:0] regv, input tid=0);
dasm = (opcode[1:0] == 2'b11) ? dasm32(opcode, pc, tid) : dasm16(opcode, pc, tid);
if(regn) gpr[tid][regn] = regv;
endfunction
///////////////// 16 bits instructions ///////////////////////
function string dasm16( input[31:0] opcode, input[31:0] pc, input tid=0);
case(opcode[1:0])
0: return dasm16_0(opcode, tid);
1: return dasm16_1(opcode, pc);
2: return dasm16_2(opcode);
endcase
return $sformatf(".short 0x%h", opcode[15:0]);
endfunction
function string dasm16_0( input[31:0] opcode, tid);
case(opcode[15:13])
3'b000: return dasm16_ciw(opcode);
3'b001: return {"c.fld ", dasm16_cl(opcode, tid)};
3'b010: return {"c.lw ", dasm16_cl(opcode, tid)};
3'b011: return {"c.flw ", dasm16_cl(opcode, tid)};
3'b101: return {"c.fsd ", dasm16_cl(opcode, tid)};
3'b110: return {"c.sw ", dasm16_cl(opcode, tid)};
3'b111: return {"c.fsw ", dasm16_cl(opcode, tid)};
endcase
return $sformatf(".short 0x%h", opcode[15:0]);
endfunction
function string dasm16_ciw( input[31:0] opcode);
int imm;
imm=0;
if(opcode[15:0] == 0) return ".short 0";
{imm[5:4],imm[9:6],imm[2],imm[3]} = opcode[12:5];
return $sformatf("c.addi4spn %s,0x%0h", abi_reg[opcode[4:2]+8], imm);
endfunction
function string dasm16_cl( input[31:0] opcode, input tid=0);
int imm;
imm=0;
imm[5:3] = opcode[12:10];
imm[7:6] = opcode[6:5];
return $sformatf(" %s,%0d(%s) [%h]", abi_reg[opcode[4:2]+8], imm, abi_reg[opcode[9:7]+8], gpr[tid][opcode[9:7]+8]+imm);
endfunction
function string dasm16_1( input[31:0] opcode, input[31:0] pc);
case(opcode[15:13])
3'b000: return opcode[11:7]==0 ? "c.nop" : {"c.addi ",dasm16_ci(opcode)};
3'b001: return {"c.jal ", dasm16_cj(opcode, pc)};
3'b010: return {"c.li ", dasm16_ci(opcode)};
3'b011: return dasm16_1_3(opcode);
3'b100: return dasm16_cr(opcode);
3'b101: return {"c.j ", dasm16_cj(opcode, pc)};
3'b110: return {"c.beqz ", dasm16_cb(opcode, pc)};
3'b111: return {"c.bnez ", dasm16_cb(opcode, pc)};
endcase
endfunction
function string dasm16_ci( input[31:0] opcode);
int imm;
imm=0;
imm[4:0] = opcode[6:2];
if(opcode[12]) imm [31:5] = '1;
return $sformatf("%s,%0d", abi_reg[opcode[11:7]], imm);
endfunction
function string dasm16_cj( input[31:0] opcode, input[31:0] pc);
bit[31:0] imm;
imm=0;
{imm[11],imm[4],imm[9:8],imm[10],imm[6], imm[7],imm[3:1], imm[5]} = opcode[12:2];
if(opcode[12]) imm [31:12] = '1;
return $sformatf("0x%0h", imm+pc);
endfunction
function string dasm16_cb( input[31:0] opcode, input[31:0] pc);
bit[31:0] imm;
imm=0;
{imm[8],imm[4:3]} = opcode[12:10];
{imm[7:6],imm[2:1], imm[5]} = opcode[6:2];
if(opcode[12]) imm [31:9] = '1;
return $sformatf("%s,0x%0h",abi_reg[opcode[9:7]+8], imm+pc);
endfunction
function string dasm16_cr( input[31:0] opcode);
bit[31:0] imm;
imm = 0;
imm[4:0] = opcode[6:2];
if(opcode[5]) imm [31:5] = '1;
case(opcode[11:10])
0: return $sformatf("c.srli %s,%0d", abi_reg[opcode[9:7]+8], imm[5:0]);
1: return $sformatf("c.srai %s,%0d", abi_reg[opcode[9:7]+8], imm[5:0]);
2: return $sformatf("c.andi %s,0x%0h", abi_reg[opcode[9:7]+8], imm);
endcase
case(opcode[6:5])
0: return $sformatf("c.sub %s,%s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]);
1: return $sformatf("c.xor %s,%s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]);
2: return $sformatf("c.or %s,%s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]);
3: return $sformatf("c.and %s,%s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]);
endcase
endfunction
function string dasm16_1_3( input[31:0] opcode);
int imm;
imm=0;
if(opcode[11:7] == 2) begin
{imm[4], imm[6],imm[8:7], imm[5]} = opcode[6:2];
if(opcode[12]) imm [31:9] = '1;
return $sformatf("c.addi16sp %0d", imm);
end
else begin
imm[16:12] = opcode[6:2];
if(opcode[12]) imm [31:17] = '1;
return $sformatf("c.lui %s,0x%0h", abi_reg[opcode[11:7]], imm);
end
endfunction
function string dasm16_2( input[31:0] opcode, input tid=0);
case(opcode[15:13])
3'b000: return {"c.slli ", dasm16_ci(opcode)};
3'b001: return {"c.fldsp ", dasm16_cls(opcode,1,tid)};
3'b010: return {"c.lwsp ", dasm16_cls(opcode,0,tid)};
3'b011: return {"c.flwsp ", dasm16_cls(opcode,0,tid)};
3'b101: return {"c.fsdsp ", dasm16_css(opcode,1,tid)};
3'b110: return {"c.swsp ", dasm16_css(opcode,0,tid)};
3'b111: return {"c.fswsp ", dasm16_css(opcode,0,tid)};
endcase
if(opcode[12]) begin
if(opcode[12:2] == 0) return "c.ebreak";
else if(opcode[6:2] == 0) return $sformatf("c.jalr %s", abi_reg[opcode[11:7]]);
else return $sformatf("c.add %s,%s", abi_reg[opcode[11:7]], abi_reg[opcode[6:2]]);
end
else begin
if(opcode[6:2] == 0) return $sformatf("c.jr %s", abi_reg[opcode[11:7]]);
else return $sformatf("c.mv %s,%s", abi_reg[opcode[11:7]], abi_reg[opcode[6:2]]);
end
endfunction
function string dasm16_cls( input[31:0] opcode, input sh1=0, tid=0);
bit[31:0] imm;
imm=0;
if(sh1) {imm[4:3],imm[8:6]} = opcode[6:2];
else {imm[4:2],imm[7:6]} = opcode[6:2];
imm[5] = opcode[12];
return $sformatf("%s,0x%0h [%h]", abi_reg[opcode[11:7]], imm, gpr[tid][2]+imm);
endfunction
function string dasm16_css( input[31:0] opcode, input sh1=0, tid=0);
bit[31:0] imm;
imm=0;
if(sh1) {imm[5:3],imm[8:6]} = opcode[12:7];
else {imm[5:2],imm[7:6]} = opcode[12:7];
return $sformatf("%s,0x%0h [%h]", abi_reg[opcode[6:2]], imm, gpr[tid][2]+imm);
endfunction
///////////////// 32 bit instructions ///////////////////////
function string dasm32( input[31:0] opcode, input[31:0] pc, input tid=0);
case(opcode[6:0])
7'b0110111: return {"lui ", dasm32_u(opcode)};
7'b0010111: return {"auipc ", dasm32_u(opcode)};
7'b1101111: return {"jal ", dasm32_j(opcode,pc)};
7'b1100111: return {"jalr ", dasm32_jr(opcode,pc)};
7'b1100011: return dasm32_b(opcode,pc);
7'b0000011: return dasm32_l(opcode,tid);
7'b0100011: return dasm32_s(opcode,tid);
7'b0010011: return dasm32_ai(opcode);
7'b0110011: return dasm32_ar(opcode);
7'b0001111: return {"fence", dasm32_fence(opcode)};
7'b1110011: return dasm32_e(opcode);
7'b0101111: return dasm32_a(opcode,tid);
endcase
return $sformatf(".long 0x%h", opcode);
endfunction
function string dasm32_u( input[31:0] opcode);
bit[31:0] imm;
imm=0;
imm[31:12] = opcode[31:12];
return $sformatf("%s,0x%0h", abi_reg[opcode[11:7]], imm);
endfunction
function string dasm32_j( input[31:0] opcode, input[31:0] pc);
int imm;
imm=0;
{imm[20], imm[10:1], imm[11], imm[19:12]} = opcode[31:12];
if(opcode[31]) imm[31:20] = '1;
return $sformatf("%s,0x%0h",abi_reg[opcode[11:7]], imm+pc);
endfunction
function string dasm32_jr( input[31:0] opcode, input[31:0] pc);
int imm;
imm=0;
imm[11:1] = opcode[31:19];
if(opcode[31]) imm[31:12] = '1;
return $sformatf("%s,%s,0x%0h",abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm+pc);
endfunction
function string dasm32_b( input[31:0] opcode, input[31:0] pc);
int imm;
string mn;
imm=0;
{imm[12],imm[10:5]} = opcode[31:25];
{imm[4:1],imm[11]} = opcode[11:7];
if(opcode[31]) imm[31:12] = '1;
case(opcode[14:12])
0: mn = "beq ";
1: mn = "bne ";
2,3 : return $sformatf(".long 0x%h", opcode);
4: mn = "blt ";
5: mn = "bge ";
6: mn = "bltu ";
7: mn = "bgeu ";
endcase
return $sformatf("%s%s,%s,0x%0h", mn, abi_reg[opcode[19:15]], abi_reg[opcode[24:20]], imm+pc);
endfunction
function string dasm32_l( input[31:0] opcode, input tid=0);
int imm;
string mn;
imm=0;
imm[11:0] = opcode[31:20];
if(opcode[31]) imm[31:12] = '1;
case(opcode[14:12])
0: mn = "lb ";
1: mn = "lh ";
2: mn = "lw ";
4: mn = "lbu ";
5: mn = "lhu ";
default : return $sformatf(".long 0x%h", opcode);
endcase
return $sformatf("%s%s,%0d(%s) [%h]", mn, abi_reg[opcode[11:7]], imm, abi_reg[opcode[19:15]], imm+gpr[tid][opcode[19:15]]);
endfunction
function string dasm32_s( input[31:0] opcode, input tid=0);
int imm;
string mn;
imm=0;
imm[11:5] = opcode[31:25];
imm[4:0] = opcode[11:7];
if(opcode[31]) imm[31:12] = '1;
case(opcode[14:12])
0: mn = "sb ";
1: mn = "sh ";
2: mn = "sw ";
default : return $sformatf(".long 0x%h", opcode);
endcase
return $sformatf("%s%s,%0d(%s) [%h]", mn, abi_reg[opcode[24:20]], imm, abi_reg[opcode[19:15]], imm+gpr[tid][opcode[19:15]]);
endfunction
function string dasm32_ai( input[31:0] opcode);
int imm;
string mn;
imm=0;
imm[11:0] = opcode[31:20];
if(opcode[31]) imm[31:12] = '1;
case(opcode[14:12])
0: mn = "addi ";
2: mn = "slti ";
3: mn = "sltiu ";
4: mn = "xori ";
6: mn = "ori ";
7: mn = "andi ";
default: return dasm32_si(opcode);
endcase
return $sformatf("%s%s,%s,%0d", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm);
endfunction
function string dasm32_si( input[31:0] opcode);
int imm;
string mn;
imm = opcode[24:20];
case(opcode[14:12])
1: mn = "slli";
5: mn = opcode[30] ? "srli": "srai";
endcase
return $sformatf("%s %s,%s,%0d", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm);
endfunction
function string dasm32_ar( input[31:0] opcode);
string mn;
if(opcode[25])
case(opcode[14:12])
0: mn = "mul ";
1: mn = "mulh ";
2: mn = "mulhsu ";
3: mn = "mulhu ";
4: mn = "div ";
5: mn = "divu ";
6: mn = "rem ";
7: mn = "remu ";
endcase
else
case(opcode[14:12])
0: mn = opcode[30]? "sub ":"add ";
1: mn = "sll ";
2: mn = "slt ";
3: mn = "sltu ";
4: mn = "xor ";
5: mn = opcode[30]? "sra ":"srl ";
6: mn = "or ";
7: mn = "and ";
endcase
return $sformatf("%s%s,%s,%s", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], abi_reg[opcode[24:20]]);
endfunction
function string dasm32_fence( input[31:0] opcode);
return opcode[12] ? ".i" : "";
endfunction
function string dasm32_e(input[31:0] opcode);
if(opcode[31:7] == 0) return "ecall";
else if({opcode[31:21],opcode [19:7]} == 0) return "ebreak";
else
case(opcode[14:12])
1: return {"csrrw ", dasm32_csr(opcode)};
2: return {"csrrs ", dasm32_csr(opcode)};
3: return {"csrrc ", dasm32_csr(opcode)};
5: return {"csrrwi ", dasm32_csr(opcode, 1)};
6: return {"csrrsi ", dasm32_csr(opcode, 1)};
7: return {"csrrci ", dasm32_csr(opcode, 1)};
endcase
endfunction
function string dasm32_csr(input[31:0] opcode, input im=0);
bit[11:0] csr;
csr = opcode[31:20];
if(im) begin
return $sformatf("%s,csr_%0h,0x%h", abi_reg[opcode[11:7]], csr, opcode[19:15]);
end
else begin
return $sformatf("%s,csr_%0h,%s", abi_reg[opcode[11:7]], csr, abi_reg[opcode[19:15]]);
end
endfunction
//atomics
function string dasm32_a(input[31:0] opcode, input tid=0);
case(opcode[31:27])
'b00010: return $sformatf("lr.w %s,(%s) [%h]", abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], gpr[tid][opcode[19:15]]);
'b00011: return $sformatf("sc.w %s,%s,(%s) [%h]", abi_reg[opcode[11:7]], abi_reg[opcode[24:20]], abi_reg[opcode[19:15]], gpr[tid][opcode[19:15]]);
'b00001: return {"amoswap.w", dasm32_amo(opcode, tid)};
'b00000: return {"amoadd.w", dasm32_amo(opcode, tid)};
'b00100: return {"amoxor.w", dasm32_amo(opcode, tid)};
'b01100: return {"amoand.w", dasm32_amo(opcode, tid)};
'b01000: return {"amoor.w", dasm32_amo(opcode, tid)};
'b10000: return {"amomin.w", dasm32_amo(opcode, tid)};
'b10100: return {"amomax.w", dasm32_amo(opcode, tid)};
'b11000: return {"amominu.w", dasm32_amo(opcode, tid)};
'b11100: return {"amomaxu.w", dasm32_amo(opcode, tid)};
endcase
return $sformatf(".long 0x%h", opcode);
endfunction
function string dasm32_amo( input[31:0] opcode, input tid=0);
return $sformatf(" %s,%s,(%s) [%h]", abi_reg[opcode[11:7]], abi_reg[opcode[24:20]], abi_reg[opcode[19:15]], gpr[tid][opcode[19:15]]);
endfunction

View File

@ -1,3 +1,4 @@
+incdir+$RV_ROOT/testbench
$RV_ROOT/design/swerv_wrapper.sv
$RV_ROOT/design/mem.sv
$RV_ROOT/design/pic_ctrl.sv

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

312
testbench/hex/dhry.hex Normal file
View File

@ -0,0 +1,312 @@
@00000000
B7 52 55 59 93 82 52 55 73 90 02 7C 17 11 04 F0
13 01 41 61 55 2A 97 02 58 D0 93 82 A2 FE 13 03
F0 0F 23 80 62 00 05 43 23 A0 62 00 E3 05 00 FE
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 41 11 4A C0 37 29 00 00 83 27 09 73
22 C4 00 41 94 43 03 AF 47 00 83 AE 87 00 03 AE
07 01 03 A3 47 01 83 A8 87 01 03 A8 C7 01 90 57
D8 57 CC 53 06 C6 26 C2 AA 84 88 53 14 C0 94 40
23 22 E4 01 23 24 D4 01 23 28 C4 01 23 2A 64 00
23 2C 14 01 23 2E 04 01 08 D0 10 D4 58 D4 4C D0
15 47 D8 C4 14 C0 9C 43 B7 26 00 00 83 A5 86 72
1C C0 03 26 09 73 58 C4 29 45 31 06 EF 00 A0 6E
5C 40 A1 CF 9C 40 B2 40 22 44 03 AF 07 00 83 AE
47 00 03 AE 87 00 03 A3 C7 00 83 A8 07 01 03 A8
47 01 88 4F CC 4F 90 53 D4 53 98 57 DC 57 23 A0
E4 01 23 A2 D4 01 23 A4 C4 01 23 A6 64 00 23 A8
14 01 23 AA 04 01 88 CC CC CC 90 D0 D4 D0 98 D4
DC D4 02 49 92 44 41 01 82 80 88 44 99 47 93 05
84 00 5C C4 99 25 83 27 09 73 48 44 13 06 C4 00
9C 43 B2 40 92 44 1C C0 22 44 02 49 A9 45 41 01
9D A5 B7 27 00 00 03 C7 C7 72 93 07 10 04 63 03
F7 00 82 80 1C 41 37 27 00 00 03 27 87 72 A5 07
99 8F 1C C1 82 80 B7 27 00 00 03 A6 07 73 09 C6
18 42 18 C1 03 A6 07 73 B7 27 00 00 83 A5 87 72
31 06 29 45 0D A5 B7 27 00 00 83 C7 C7 72 37 27
00 00 83 26 C7 7F 93 87 F7 FB 93 B7 17 00 D5 8F
23 2E F7 7E B7 27 00 00 13 07 20 04 A3 86 E7 72
82 80 B7 27 00 00 13 07 10 04 23 86 E7 72 B7 27
00 00 23 AE 07 7E 82 80 37 07 04 F0 6D 71 13 07
C7 59 B7 07 04 F0 93 87 C7 5B 03 2F 07 00 83 2E
47 00 03 2E 87 00 DA D9 93 0F 01 0A 37 2B 00 00
83 28 07 01 03 28 47 01 08 4F 83 55 C7 01 03 46
E7 01 94 43 03 23 C7 00 23 28 FB 73 D8 43 89 4F
23 24 81 10 23 22 91 10 7E D5 84 18 93 0F 80 02
37 24 00 00 23 26 11 10 E2 D5 7E D7 7A D9 76 DB
72 DD 23 20 21 11 CE DF D2 DD D6 DB DE D7 E6 D3
EA D1 EE CF 23 22 94 72 26 D1 1A DF C6 C1 C2 C3
83 A8 87 00 03 A8 C7 00 23 16 B1 0C 23 07 C1 0C
8C 4B D0 4B 36 D8 3A DA 94 4F 03 D7 C7 01 83 C7
E7 01 AA C5 37 0C 00 00 37 05 04 F0 23 16 E1 04
23 07 F1 04 13 07 0C 01 A9 47 13 05 45 08 23 2E
F7 64 02 D3 46 DC 42 DE AE C0 B2 C2 B6 C4 EF 00
90 08 B7 07 04 F0 83 A7 C7 61 63 8A 07 4A 37 05
04 F0 13 05 45 0B EF 00 10 07 37 05 04 F0 93 05
80 3E 13 05 05 11 EF 00 10 08 EF 00 F0 09 B7 07
00 00 23 A6 A7 00 B7 07 04 F0 93 87 C7 5D D8 43
83 AD 07 00 37 08 04 F0 3A C2 98 47 85 44 B7 29
00 00 3A C4 D8 47 37 2A 00 00 37 24 00 00 3A C6
98 4B B7 2B 00 00 B7 2A 00 00 3A C8 D8 4B 93 0C
C8 5F 3A CA 98 4F 3A CC 03 D7 C7 01 83 C7 E7 01
23 1E E1 00 A3 0F F1 00 13 07 10 04 23 86 E9 72
13 07 20 04 A3 06 E4 72 12 47 85 47 8C 08 BA CA
22 47 08 18 23 2E FA 7E BA CC 32 47 3E D6 EE C8
BA CE 42 47 BA D0 52 47 BA D2 62 47 BA D4 03 57
C1 01 23 16 E1 06 03 47 F1 01 23 07 E1 06 4D 21
93 37 15 00 30 10 8D 45 09 45 23 2E FA 7E 9D 47
3E D4 15 21 A2 56 0D 46 93 05 0C 01 13 85 4B 73
39 29 03 25 0B 73 7D 31 03 47 D4 72 93 07 00 04
63 F7 E7 36 13 0D 10 04 0D 49 6A 85 93 05 30 04
91 21 B2 57 13 07 1D 00 63 00 F5 30 83 47 D4 72
13 7D F7 0F E3 F3 A7 FF 93 17 19 00 3E 99 A2 58
83 C6 C9 72 13 07 10 04 33 46 19 03 B2 87 63 97
E6 00 03 A7 8A 72 93 07 96 00 99 8F 85 04 13 07
90 3E E3 9B E4 F2 46 C6 32 C4 3E C2 EF 00 C0 76
AA 85 37 05 04 F0 B7 2C 00 00 13 05 05 14 23 A0
BC 72 EF 00 40 73 37 05 04 F0 13 05 05 15 EF 00
80 70 83 A5 8A 72 37 05 04 F0 13 05 85 18 B7 04
04 F0 EF 00 40 71 95 45 13 85 44 1A EF 00 A0 70
83 25 CA 7F 37 05 04 F0 13 05 05 1C EF 00 A0 6F
85 45 13 85 44 1A EF 00 00 6F 83 C5 C9 72 37 05
04 F0 13 05 C5 1D EF 00 00 6E B7 09 04 F0 93 05
10 04 13 85 89 1F EF 00 00 6D 83 45 D4 72 37 05
04 F0 13 05 45 21 EF 00 00 6C 93 05 20 04 13 85
89 1F EF 00 40 6B 93 8B 4B 73 83 A5 0B 02 37 05
04 F0 13 05 05 23 EF 00 00 6A 9D 45 13 85 44 1A
EF 00 60 69 B7 07 00 00 93 87 07 01 83 A5 C7 65
37 05 04 F0 13 05 C5 24 BD 2D 37 05 04 F0 13 05
85 26 91 2D 03 27 0B 73 37 05 04 F0 13 05 45 29
0C 43 37 0C 04 F0 B7 0B 04 F0 B1 2D 37 05 04 F0
13 05 05 2B 0D 2D 03 27 0B 73 13 05 0C 2E B7 0A
04 F0 4C 43 37 0A 04 F0 B7 09 04 F0 2D 2D 81 45
13 85 44 1A 0D 2D 03 27 0B 73 13 85 CB 2F 37 04
00 00 0C 47 0D 25 89 45 13 85 44 1A 29 2D 03 27
0B 73 13 85 8A 31 4C 47 39 25 C5 45 13 85 44 1A
19 25 83 25 0B 73 13 05 4A 33 37 2B 00 00 C1 05
DD 2B 13 85 C9 34 C1 2B 03 27 4B 72 37 05 04 F0
13 05 05 38 0C 43 C5 23 37 05 04 F0 13 05 C5 39
5D 2B 03 27 4B 72 13 05 0C 2E 4C 43 E9 23 81 45
13 85 44 1A C9 23 03 27 4B 72 13 85 CB 2F 0C 47
5D 2B 85 45 13 85 44 1A 7D 23 03 27 4B 72 13 85
8A 31 4C 47 4D 23 C9 45 13 85 44 1A 69 2B 83 25
4B 72 13 05 4A 33 C1 05 79 23 13 85 C9 34 A5 23
92 47 37 05 04 F0 13 05 C5 3D BE 85 AD 2B 95 45
13 85 44 1A 8D 2B B2 48 22 46 37 05 04 F0 33 09
19 41 93 17 39 00 33 89 27 41 B3 05 C9 40 13 05
85 3F 91 2B B5 45 13 85 44 1A B1 23 A2 55 37 05
04 F0 13 05 45 41 81 23 9D 45 13 85 44 1A 25 2B
B2 55 37 05 04 F0 13 05 05 43 35 23 85 45 13 85
44 1A 15 23 37 05 04 F0 0C 18 13 05 C5 44 21 2B
37 05 04 F0 13 05 45 46 FD 21 37 05 04 F0 8C 08
13 05 85 49 09 23 37 05 04 F0 13 05 05 4B E1 29
29 45 55 29 B7 07 00 00 03 A7 C7 00 83 A5 0C 72
93 07 70 0C 99 8D 23 24 B4 00 63 C4 B7 0A 37 05
04 F0 13 05 45 4E C1 29 37 05 04 F0 13 05 45 4F
5D 21 37 05 04 F0 13 05 C5 52 71 29 29 45 A5 29
83 20 C1 10 03 24 81 10 83 24 41 10 03 29 01 10
FE 59 6E 5A DE 5A 4E 5B BE 5B 2E 5C 9E 5C 0E 5D
FE 4D 01 45 51 61 82 80 6C 10 01 45 7D 20 03 AE
0C 00 03 A3 4C 00 83 A8 8C 00 03 A8 CC 00 03 A5
0C 01 83 A5 4C 01 03 A6 8C 01 83 D6 CC 01 03 C7
EC 01 83 47 D4 72 05 0D F2 C8 9A CA C6 CC C2 CE
AA D0 AE D2 B2 D4 23 16 D1 06 23 07 E1 06 23 A4
9A 72 13 7D FD 0F 26 89 E3 F1 A7 CB 75 B9 25 49
7D B9 37 05 04 F0 13 06 80 3E 13 05 C5 54 25 21
37 05 04 F0 13 05 45 57 39 29 83 25 84 00 B7 F7
76 48 93 87 07 80 B3 C7 B7 02 13 06 40 06 37 05
04 F0 13 05 45 59 33 E6 C7 02 B7 D7 9A 3B 93 87
07 A0 B3 C5 B7 02 C5 2E 29 45 75 26 15 BF 37 05
04 F0 13 05 05 0E C1 26 89 BE 09 47 63 0A E5 02
8D 47 9C C1 85 47 63 09 F5 00 63 FF A7 00 91 47
63 1F F5 00 98 C1 82 80 B7 27 00 00 03 A7 87 72
93 07 40 06 E3 D9 E7 FE 23 A0 05 00 82 80 82 80
85 47 9C C1 82 80 09 05 2E 95 08 C2 82 80 13 07
56 00 13 08 80 0C 33 08 07 03 93 17 27 00 0A 06
3E 95 14 C1 38 DD 54 C1 B3 07 C8 00 AE 97 94 4B
D8 CB 98 CF 13 87 16 00 98 CB 18 41 C2 95 85 67
B2 95 BE 95 23 AA E5 FA B7 27 00 00 15 47 23 A4
E7 72 82 80 13 75 F5 0F 93 F5 F5 0F 63 04 B5 00
01 45 82 80 B7 27 00 00 23 86 A7 72 05 45 82 80
03 47 25 00 83 C7 35 00 63 02 F7 02 41 11 06 C6
B1 2E 81 47 63 58 A0 00 B7 27 00 00 29 47 23 A4
E7 72 85 47 B2 40 3E 85 41 01 82 80 01 A0 79 15
13 35 15 00 82 80 03 48 05 00 63 0B 08 28 39 71
22 DE 37 04 04 F0 26 DC 4A DA 4E D8 52 D6 AA 86
56 D4 5A D2 5E D0 01 45 93 0F 50 02 B7 08 58 D0
13 03 00 03 93 09 D0 02 13 09 A0 02 93 04 00 02
13 04 04 00 29 4F 93 03 B1 00 A5 42 13 0A D0 02
03 C6 16 00 93 87 16 00 63 03 F8 03 23 80 08 01
05 05 BE 86 32 88 E3 15 08 FE 72 54 E2 54 52 59
C2 59 32 5A A2 5A 12 5B 82 5B 21 61 82 80 75 D6
13 8E 26 00 63 00 F6 07 63 1D 66 1E 03 C7 17 00
BE 86 85 07 E3 0C 67 FE 89 06 03 C8 17 00 63 05
37 03 63 0A 27 03 93 0A 07 FD 13 FE FA 0F 81 4E
63 F2 C2 05 13 07 87 FA 13 77 F7 0F E3 E5 E4 FA
0A 07 22 97 1C 43 82 87 42 87 03 C8 27 00 B6 87
85 06 E3 1A 27 FD 42 87 91 05 03 C8 27 00 85 06
81 4E C9 BF 23 80 08 01 03 C8 26 00 F2 86 E3 11
08 F6 A5 BF 03 C8 17 00 19 A0 93 0A 07 FD 13 9E
2E 00 76 9E 93 06 08 FD 3E 8B 06 0E 85 07 93 F6
F6 0F 42 87 B3 8E CA 01 03 C8 17 00 E3 FF D2 FC
93 06 2B 00 41 BF 98 41 81 47 91 05 11 A0 B2 87
93 7E F7 00 13 8E 7E 05 63 C4 D2 01 13 8E 0E 03
13 86 17 00 93 0E C1 00 B2 9E A3 8F CE FF 11 83
79 FF 78 00 BA 97 03 C7 07 00 FD 17 23 80 E8 00
E3 9B F3 FE 32 95 E3 15 08 EE 01 B7 03 AE 05 00
01 47 91 05 B3 7A EE 03 13 0B C1 00 BA 87 05 07
B3 0B EB 00 72 8B 93 8A 0A 03 A3 8F 5B FF 33 5E
EE 03 E3 E1 62 FF 3A 8E 63 57 D7 01 23 80 C8 00
05 0E E3 9D CE FF 70 00 B2 97 03 C6 07 00 FD 17
23 80 C8 00 E3 9B 77 FE 3A 95 E3 1B 08 E8 75 B5
98 41 91 05 83 47 07 00 99 C7 05 07 23 80 F8 00
83 47 07 00 FD FB 23 80 E8 01 05 05 E3 1A 08 E6
69 B5 90 41 01 47 91 05 13 7E 76 00 BA 87 93 0E
C1 00 05 07 BA 9E 13 0E 0E 03 A3 8F CE FF 0D 82
65 F6 70 00 B2 97 03 C6 07 00 FD 17 23 80 C8 00
E3 9B 77 FE 3A 95 55 B7 83 AB 05 00 91 05 5E 87
63 CA 0B 06 81 47 33 6E E7 03 3E 8B 93 0A C1 00
85 07 BE 9A 33 47 E7 03 13 0E 0E 03 A3 8F CA FF
7D F3 3E 87 63 D7 D7 01 23 80 C8 00 05 07 E3 1D
D7 FF 78 00 5A 97 03 46 07 00 7D 17 23 80 C8 00
E3 1B 77 FE 63 C4 0B 02 3E 95 E3 13 08 DE F5 BB
83 C7 05 00 05 05 91 05 23 80 F8 00 E3 1A 08 DC
ED B3 32 87 F2 86 13 06 00 02 01 BD 93 07 2B 00
3E 95 E1 BF 33 07 70 41 23 80 48 01 FD 1E 59 B7
01 45 82 80 39 71 13 03 41 02 2E D2 9A 85 06 CE
32 D4 36 D6 3A D8 3E DA 42 DC 46 DE 1A C6 A1 33
F2 40 21 61 82 80 13 77 F5 0F B7 07 58 D0 23 80
E7 00 3A 85 82 80 13 77 F5 0F B7 07 58 D0 23 80
E7 00 3A 85 82 80 83 47 05 00 37 07 58 D0 99 C7
05 05 23 00 F7 00 83 47 05 00 FD FB A9 47 23 00
F7 00 05 45 82 80 39 71 13 03 41 02 2E D2 9A 85
06 CE 32 D4 36 D6 3A D8 3E DA 42 DC 46 DE 1A C6
DD 31 F2 40 21 61 82 80 F3 25 00 B8 73 25 00 B0
F3 27 00 B8 E3 9A F5 FE 82 80 00 00 33 67 B5 00
93 03 F0 FF 13 77 37 00 63 10 07 10 B7 87 7F 7F
93 87 F7 F7 03 26 05 00 83 A6 05 00 B3 72 F6 00
33 63 F6 00 B3 82 F2 00 B3 E2 62 00 63 92 72 10
63 16 D6 08 03 26 45 00 83 A6 45 00 B3 72 F6 00
33 63 F6 00 B3 82 F2 00 B3 E2 62 00 63 9E 72 0C
63 16 D6 06 03 26 85 00 83 A6 85 00 B3 72 F6 00
33 63 F6 00 B3 82 F2 00 B3 E2 62 00 63 98 72 0C
63 16 D6 04 03 26 C5 00 83 A6 C5 00 B3 72 F6 00
33 63 F6 00 B3 82 F2 00 B3 E2 62 00 63 92 72 0C
63 16 D6 02 03 26 05 01 83 A6 05 01 B3 72 F6 00
33 63 F6 00 B3 82 F2 00 B3 E2 62 00 63 9C 72 0A
13 05 45 01 93 85 45 01 E3 0E D6 F4 13 17 06 01
93 97 06 01 63 1E F7 00 13 57 06 01 93 D7 06 01
33 05 F7 40 93 75 F5 0F 63 90 05 02 67 80 00 00
13 57 07 01 93 D7 07 01 33 05 F7 40 93 75 F5 0F
63 94 05 00 67 80 00 00 13 77 F7 0F 93 F7 F7 0F
33 05 F7 40 67 80 00 00 03 46 05 00 83 C6 05 00
13 05 15 00 93 85 15 00 63 14 D6 00 E3 16 06 FE
33 05 D6 40 67 80 00 00 13 05 45 00 93 85 45 00
E3 1C D6 FC 13 05 00 00 67 80 00 00 13 05 85 00
93 85 85 00 E3 12 D6 FC 13 05 00 00 67 80 00 00
13 05 C5 00 93 85 C5 00 E3 18 D6 FA 13 05 00 00
67 80 00 00 13 05 05 01 93 85 05 01 E3 1E D6 F8
13 05 00 00 67 80 00 00
@D0580000
00 00 00 00
@F0040000
66 09 00 00 A6 08 00 00 A6 08 00 00 A6 08 00 00
A6 08 00 00 A6 08 00 00 A6 08 00 00 A6 08 00 00
A6 08 00 00 A6 08 00 00 A6 08 00 00 B0 0A 00 00
58 0A 00 00 A6 08 00 00 A6 08 00 00 A6 08 00 00
A6 08 00 00 A6 08 00 00 A6 08 00 00 A6 08 00 00
A6 08 00 00 A6 08 00 00 A6 08 00 00 22 0A 00 00
A6 08 00 00 A6 08 00 00 A6 08 00 00 00 0A 00 00
A6 08 00 00 AC 09 00 00 A6 08 00 00 A6 08 00 00
66 09 00 00 44 68 72 79 73 74 6F 6E 65 20 42 65
6E 63 68 6D 61 72 6B 2C 20 56 65 72 73 69 6F 6E
20 32 2E 31 20 28 4C 61 6E 67 75 61 67 65 3A 20
43 29 00 00 50 72 6F 67 72 61 6D 20 63 6F 6D 70
69 6C 65 64 20 77 69 74 68 20 27 72 65 67 69 73
74 65 72 27 20 61 74 74 72 69 62 75 74 65 00 00
50 72 6F 67 72 61 6D 20 63 6F 6D 70 69 6C 65 64
20 77 69 74 68 6F 75 74 20 27 72 65 67 69 73 74
65 72 27 20 61 74 74 72 69 62 75 74 65 00 00 00
45 78 65 63 75 74 69 6F 6E 20 73 74 61 72 74 73
2C 20 25 64 20 72 75 6E 73 20 74 68 72 6F 75 67
68 20 44 68 72 79 73 74 6F 6E 65 0A 00 00 00 00
45 6E 64 5F 74 69 6D 65 3D 25 64 0A 00 00 00 00
46 69 6E 61 6C 20 76 61 6C 75 65 73 20 6F 66 20
74 68 65 20 76 61 72 69 61 62 6C 65 73 20 75 73
65 64 20 69 6E 20 74 68 65 20 62 65 6E 63 68 6D
61 72 6B 3A 0A 00 00 00 49 6E 74 5F 47 6C 6F 62
3A 20 20 20 20 20 20 20 20 20 20 20 20 25 64 0A
00 00 00 00 20 20 20 20 20 20 20 20 73 68 6F 75
6C 64 20 62 65 3A 20 20 20 25 64 0A 00 00 00 00
42 6F 6F 6C 5F 47 6C 6F 62 3A 20 20 20 20 20 20
20 20 20 20 20 25 64 0A 00 00 00 00 43 68 5F 31
5F 47 6C 6F 62 3A 20 20 20 20 20 20 20 20 20 20
20 25 63 0A 00 00 00 00 20 20 20 20 20 20 20 20
73 68 6F 75 6C 64 20 62 65 3A 20 20 20 25 63 0A
00 00 00 00 43 68 5F 32 5F 47 6C 6F 62 3A 20 20
20 20 20 20 20 20 20 20 20 25 63 0A 00 00 00 00
41 72 72 5F 31 5F 47 6C 6F 62 5B 38 5D 3A 20 20
20 20 20 20 20 25 64 0A 00 00 00 00 41 72 72 5F
32 5F 47 6C 6F 62 5B 38 5D 5B 37 5D 3A 20 20 20
20 25 64 0A 00 00 00 00 20 20 20 20 20 20 20 20
73 68 6F 75 6C 64 20 62 65 3A 20 20 20 4E 75 6D
62 65 72 5F 4F 66 5F 52 75 6E 73 20 2B 20 31 30
00 00 00 00 50 74 72 5F 47 6C 6F 62 2D 3E 50 74
72 5F 43 6F 6D 70 3A 20 20 25 78 0A 00 00 00 00
20 20 20 20 20 20 20 20 73 68 6F 75 6C 64 20 62
65 3A 20 20 20 28 69 6D 70 6C 65 6D 65 6E 74 61
74 69 6F 6E 2D 64 65 70 65 6E 64 65 6E 74 29 00
20 20 44 69 73 63 72 3A 20 20 20 20 20 20 20 20
20 20 20 20 20 25 64 0A 00 00 00 00 20 20 45 6E
75 6D 5F 43 6F 6D 70 3A 20 20 20 20 20 20 20 20
20 25 64 0A 00 00 00 00 20 20 49 6E 74 5F 43 6F
6D 70 3A 20 20 20 20 20 20 20 20 20 20 25 64 0A
00 00 00 00 20 20 53 74 72 5F 43 6F 6D 70 3A 20
20 20 20 20 20 20 20 20 20 25 73 00 20 20 20 20
20 20 20 20 73 68 6F 75 6C 64 20 62 65 3A 20 20
20 44 48 52 59 53 54 4F 4E 45 20 50 52 4F 47 52
41 4D 2C 20 53 4F 4D 45 20 53 54 52 49 4E 47 00
4E 65 78 74 5F 50 74 72 5F 47 6C 6F 62 2D 3E 50
74 72 5F 43 6F 6D 70 3A 25 78 0A 00 20 20 20 20
20 20 20 20 73 68 6F 75 6C 64 20 62 65 3A 20 20
20 28 69 6D 70 6C 65 6D 65 6E 74 61 74 69 6F 6E
2D 64 65 70 65 6E 64 65 6E 74 29 2C 20 73 61 6D
65 20 61 73 20 61 62 6F 76 65 00 00 49 6E 74 5F
31 5F 4C 6F 63 3A 20 20 20 20 20 20 20 20 20 20
20 25 64 0A 00 00 00 00 49 6E 74 5F 32 5F 4C 6F
63 3A 20 20 20 20 20 20 20 20 20 20 20 25 64 0A
00 00 00 00 49 6E 74 5F 33 5F 4C 6F 63 3A 20 20
20 20 20 20 20 20 20 20 20 25 64 0A 00 00 00 00
45 6E 75 6D 5F 4C 6F 63 3A 20 20 20 20 20 20 20
20 20 20 20 20 25 64 0A 00 00 00 00 53 74 72 5F
31 5F 4C 6F 63 3A 20 20 20 20 20 20 20 20 20 20
20 25 73 00 20 20 20 20 20 20 20 20 73 68 6F 75
6C 64 20 62 65 3A 20 20 20 44 48 52 59 53 54 4F
4E 45 20 50 52 4F 47 52 41 4D 2C 20 31 27 53 54
20 53 54 52 49 4E 47 00 53 74 72 5F 32 5F 4C 6F
63 3A 20 20 20 20 20 20 20 20 20 20 20 25 73 00
20 20 20 20 20 20 20 20 73 68 6F 75 6C 64 20 62
65 3A 20 20 20 44 48 52 59 53 54 4F 4E 45 20 50
52 4F 47 52 41 4D 2C 20 32 27 4E 44 20 53 54 52
49 4E 47 00 55 73 65 72 20 74 69 6D 65 20 25 64
0A 00 00 00 4D 65 61 73 75 72 65 64 20 74 69 6D
65 20 74 6F 6F 20 73 6D 61 6C 6C 20 74 6F 20 6F
62 74 61 69 6E 20 6D 65 61 6E 69 6E 67 66 75 6C
20 72 65 73 75 6C 74 73 00 00 00 00 50 6C 65 61
73 65 20 69 6E 63 72 65 61 73 65 20 6E 75 6D 62
65 72 20 6F 66 20 72 75 6E 73 00 00 52 75 6E 20
74 69 6D 65 20 3D 20 25 64 20 63 6C 6F 63 6B 73
20 66 6F 72 20 25 64 20 44 68 72 79 73 74 6F 6E
65 73 0A 00 44 68 72 79 73 74 6F 6E 65 73 20 70
65 72 20 53 65 63 6F 6E 64 20 70 65 72 20 4D 48
7A 3A 20 00 25 64 2E 25 30 32 64 00 44 48 52 59
53 54 4F 4E 45 20 50 52 4F 47 52 41 4D 2C 20 53
4F 4D 45 20 53 54 52 49 4E 47 00 00 44 48 52 59
53 54 4F 4E 45 20 50 52 4F 47 52 41 4D 2C 20 31
27 53 54 20 53 54 52 49 4E 47 00 00 44 48 52 59
53 54 4F 4E 45 20 50 52 4F 47 52 41 4D 2C 20 32
27 4E 44 20 53 54 52 49 4E 47 00 00 44 48 52 59
53 54 4F 4E 45 20 50 52 4F 47 52 41 4D 2C 20 33
27 52 44 20 53 54 52 49 4E 47 00 00 00 00 00 00
@FFFFFFF8
00 00 04 F0 20 16 04 F0

View File

@ -25,4 +25,4 @@ B7 50 55 5F 93 80 50 55 73 90 00 7C B7 01 58 D0
2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
2D 2D 2D 2D 2D 2D 2D 2D 0A 00
@FFFFFFF8
00 00 04 F0 70 80 04 F0
00 00 04 F0 70 10 04 F0

View File

@ -0,0 +1,32 @@
@00000000
B7 50 55 5F 93 80 50 55 73 90 00 7C 89 61 91 01
73 90 91 7F B7 01 00 EE 17 02 01 00 13 02 42 06
97 02 01 00 93 82 C2 08 03 23 02 00 23 A0 61 00
11 02 91 01 E3 6A 52 FE 0F 10 00 00 97 00 00 EE
E7 80 40 FC B7 01 58 D0 93 02 F0 0F 23 80 51 00
E3 0A 00 FE 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
01 00 01 00 01 00 01 00 01 00 01 00
@00010000
2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
2D 2D 2D 2D 2D 2D 2D 2D 0A 48 65 6C 6C 6F 20 57
6F 72 6C 64 20 66 72 6F 6D 20 53 77 65 52 56 20
45 4C 32 20 49 43 43 4D 20 20 40 57 44 43 20 21
21 0A 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 0A 00
@0001007C
B7 01 58 D0 17 02 01 12 13 02 C2 FF 83 02 02 00
23 80 51 00 05 02 E3 9B 02 FE 82 80 00 00 00 00
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00

View File

@ -9,4 +9,7 @@ SECTIONS
_end = .;
. = 0x10000;
.data : ALIGN(0x800) { *(.*data) *(.rodata*) STACK = ALIGN(16) + 0x8000; }
.bss : { *(.bss) }
. = 0xd0580000;
.data.io : { *(.data.io) }
}

View File

@ -288,9 +288,33 @@ module tb_top;
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;
string abi_reg[32]; // ABI register names
`define DEC rvtop.swerv.dec
assign mailbox_write = lmem.mailbox_write;
assign WriteData = lmem.WriteData;
@ -314,7 +338,7 @@ module tb_top;
end
// End Of test monitor
if(mailbox_write && WriteData[7:0] == 8'hff) begin
$display("\nFinished : minstret = %0d, mcycle = %0d", rvtop.swerv.dec.tlu.minstretl[31:0],rvtop.swerv.dec.tlu.mcyclel[31:0]);
$display("\nFinished : minstret = %0d, mcycle = %0d", `DEC.tlu.minstretl[31:0],`DEC.tlu.mcyclel[31:0]);
$display("See \"exec.log\" for execution trace with register updates..\n");
$display("TEST_PASSED");
$finish;
@ -328,9 +352,9 @@ module tb_top;
// trace monitor
always @(posedge core_clk) begin
wb_valid[1:0] <= '{rvtop.swerv.dec.dec_i1_wen_wb, rvtop.swerv.dec.dec_i0_wen_wb};
wb_dest[1:0] <= '{rvtop.swerv.dec.dec_i1_waddr_wb, rvtop.swerv.dec.dec_i0_waddr_wb};
wb_data[1:0] <= '{rvtop.swerv.dec.dec_i1_wdata_wb, rvtop.swerv.dec.dec_i0_wdata_wb};
wb_valid[1:0] <= '{`DEC.dec_i1_wen_wb, `DEC.dec_i0_wen_wb};
wb_dest[1:0] <= '{`DEC.dec_i1_waddr_wb, `DEC.dec_i0_waddr_wb};
wb_data[1:0] <= '{`DEC.dec_i1_wdata_wb, `DEC.dec_i0_wdata_wb};
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, trace_rv_i_address_ip[63:32], trace_rv_i_address_ip[31:0],
trace_rv_i_insn_ip[63:32], trace_rv_i_insn_ip[31:0],trace_rv_i_exception_ip,trace_rv_i_ecause_ip,
@ -340,15 +364,53 @@ module tb_top;
for (int i=0; i<2; i++)
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),
$fwrite (el, "%10d : %8s %0d %h %h%13s ; %s\n",cycleCnt, $sformatf("#%0d",commit_count), 0,
trace_rv_i_address_ip[31+i*32 -:32], trace_rv_i_insn_ip[31+i*32-:32],
(wb_dest[i] !=0 && wb_valid[i]) ? $sformatf("r%0d=%h", wb_dest[i], wb_data[i]) : "");
(wb_dest[i] !=0 && wb_valid[i]) ? $sformatf("%s=%h", abi_reg[wb_dest[i]], wb_data[i]) : " ",
dasm(trace_rv_i_insn_ip[31+i*32 -:32], trace_rv_i_address_ip[31+i*32-:32], wb_dest[i] & {5{wb_valid[i]}}, wb_data[i])
);
end
end
if(`DEC.dec_nonblock_load_wen) begin
$fwrite (el, "%10d : %10d%22s=%h ; nbL\n", cycleCnt, 0, abi_reg[`DEC.dec_nonblock_load_waddr], `DEC.lsu_nonblock_load_data);
tb_top.gpr[0][`DEC.dec_nonblock_load_waddr] = `DEC.lsu_nonblock_load_data;
end
end
initial begin
abi_reg[0] = "zero";
abi_reg[1] = "ra";
abi_reg[2] = "sp";
abi_reg[3] = "gp";
abi_reg[4] = "tp";
abi_reg[5] = "t0";
abi_reg[6] = "t1";
abi_reg[7] = "t2";
abi_reg[8] = "s0";
abi_reg[9] = "s1";
abi_reg[10] = "a0";
abi_reg[11] = "a1";
abi_reg[12] = "a2";
abi_reg[13] = "a3";
abi_reg[14] = "a4";
abi_reg[15] = "a5";
abi_reg[16] = "a6";
abi_reg[17] = "a7";
abi_reg[18] = "s2";
abi_reg[19] = "s3";
abi_reg[20] = "s4";
abi_reg[21] = "s5";
abi_reg[22] = "s6";
abi_reg[23] = "s7";
abi_reg[24] = "s8";
abi_reg[25] = "s9";
abi_reg[26] = "s10";
abi_reg[27] = "s11";
abi_reg[28] = "t3";
abi_reg[29] = "t4";
abi_reg[30] = "t5";
abi_reg[31] = "t6";
// tie offs
jtag_id[31:28] = 4'b1;
jtag_id[27:12] = '0;
@ -361,7 +423,8 @@ module tb_top;
$readmemh("program.hex", imem.mem);
tp = $fopen("trace_port.csv","w");
el = $fopen("exec.log","w");
$fwrite (el, "//Cycle : #inst 0 pc opcode reg regnum value\n");
$fwrite (el, "// Cycle : #inst hart pc opcode reg=value ; mnemonic\n");
$fwrite (el, "//---------------------------------------------------------------\n");
fd = $fopen("console.log","w");
commit_count = 0;
preload_dccm();
@ -595,40 +658,40 @@ 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), // ids are not used on DMA since it always responses in order
.dma_axi_awaddr (lsu_axi_awaddr),
.dma_axi_awsize (lsu_axi_awsize),
.dma_axi_awprot ('0),
.dma_axi_awlen ('0),
.dma_axi_awburst ('0),
.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 (1'b1),
.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 ('0),
.dma_axi_arlen ('0),
.dma_axi_arburst ('0),
.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),
@ -636,10 +699,10 @@ swerv_wrapper rvtop (
.timer_int ( 1'b0 ),
.extintsrc_req ( '0 ),
.lsu_bus_clk_en ( 1'b1 ),// Clock ratio b/w cpu core clk & AHB master interface
.ifu_bus_clk_en ( 1'b1 ),// Clock ratio b/w cpu core clk & AHB master interface
.dbg_bus_clk_en ( 1'b1 ),// Clock ratio b/w cpu core clk & AHB Debug master interface
.dma_bus_clk_en ( 1'b1 ),// Clock ratio b/w cpu core clk & AHB slave interface
.lsu_bus_clk_en ( 1'b1 ),
.ifu_bus_clk_en ( 1'b1 ),
.dbg_bus_clk_en ( 1'b1 ),
.dma_bus_clk_en ( 1'b1 ),
.trace_rv_i_insn_ip (trace_rv_i_insn_ip),
.trace_rv_i_address_ip (trace_rv_i_address_ip),
@ -659,23 +722,23 @@ swerv_wrapper rvtop (
.mpc_debug_halt_req ( 1'b0),
.mpc_debug_run_ack ( mpc_debug_run_ack),
.mpc_debug_run_req ( 1'b1),
.mpc_reset_run_req ( 1'b1), // Start running after reset
.mpc_reset_run_req ( 1'b1),
.debug_brkpt_status (debug_brkpt_status),
.i_cpu_halt_req ( 1'b0 ), // Async halt req to CPU
.o_cpu_halt_ack ( o_cpu_halt_ack ), // core response to halt
.o_cpu_halt_status ( o_cpu_halt_status ), // 1'b1 indicates core is halted
.i_cpu_run_req ( 1'b0 ), // Async restart req to CPU
.i_cpu_halt_req ( 1'b0 ),
.o_cpu_halt_ack ( o_cpu_halt_ack ),
.o_cpu_halt_status ( o_cpu_halt_status ),
.i_cpu_run_req ( 1'b0 ),
.o_debug_mode_status (o_debug_mode_status),
.o_cpu_run_ack ( o_cpu_run_ack ), // Core response to run req
.o_cpu_run_ack ( o_cpu_run_ack ),
.dec_tlu_perfcnt0 (dec_tlu_perfcnt0),
.dec_tlu_perfcnt1 (dec_tlu_perfcnt1),
.dec_tlu_perfcnt2 (dec_tlu_perfcnt2),
.dec_tlu_perfcnt3 (dec_tlu_perfcnt3),
.scan_mode ( 1'b0 ), // To enable scan mode
.mbist_mode ( 1'b0 ) // to enable mbist
.scan_mode ( 1'b0 ),
.mbist_mode ( 1'b0 )
);
@ -771,23 +834,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),
@ -796,14 +859,86 @@ 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;
@ -967,4 +1102,14 @@ function int get_iccm_bank(input int addr, output int bank_idx);
`endif
endfunction
/* verilator lint_off WIDTH */
/* verilator lint_off CASEINCOMPLETE */
`include "dasm.svi"
/* verilator lint_on CASEINCOMPLETE */
/* verilator lint_on WIDTH */
endmodule
`ifdef RV_BUILD_AXI4
`include "axi_lsu_dma_bridge.sv"
`endif

View File

@ -0,0 +1,6 @@
export TEST = cmark_dccm
export OFILES = crt0.o cmark_dccm.o printf.o
export BUILD_DIR = ../snapshots/default
clean .DEFAULT:
$(MAKE) -e -f $(RV_ROOT)/tools/MakeHex $@

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
SECTIONS {
.text : { *(.text*) }
_end = .;
. = 0xf0040000;
.data : { *(.*data) *(.rodata*) *(.sbss) STACK = ALIGN(16) + 0x1000;}
.bss : { *(.bss) }
. = 0xfffffff8;
.data.ctl : { LONG(0xf0040000); LONG(STACK) }
}

View File

@ -0,0 +1,29 @@
extern int STACK;
void main();
#define STDOUT 0xd0580000
__asm (".section .text");
__asm (".global _start");
__asm ("_start:");
// Enable Caches in MRAC
__asm ("li t0, 0x5f555555");
__asm ("csrw 0x7c0, t0");
// Set stack pointer.
__asm ("la sp, STACK");
__asm ("jal main");
// Write 0xff to STDOUT for TB to termiate test.
__asm (".global _finish");
__asm ("_finish:");
__asm ("li t0, 0xd0580000");
__asm ("addi t1, zero, 0xff");
__asm ("sb t1, 0(t0)");
__asm ("beq x0, x0, _finish");
__asm (".rept 10");
__asm ("nop");
__asm (".endr");

View File

@ -0,0 +1,191 @@
#include <stdarg.h>
// This should be in some .h file.
#define STDOUT 0xd0580000
static int
whisperPutc(char c)
{
// __whisper_console_io = c;
// __whisper_console_io = c;
*(volatile char*)(STDOUT) = c;
return c;
}
static int
whisperPuts(const char* s)
{
while (*s)
whisperPutc(*s++);
return 1;
}
static int
whisperPrintDecimal(int value)
{
char buffer[20];
int charCount = 0;
unsigned neg = value < 0;
if (neg)
{
value = -value;
whisperPutc('-');
}
do
{
char c = '0' + (value % 10);
value = value / 10;
buffer[charCount++] = c;
}
while (value);
char* p = buffer + charCount - 1;
for (unsigned i = 0; i < charCount; ++i)
whisperPutc(*p--);
if (neg)
charCount++;
return charCount;
}
static int
whisperPrintInt(int value, int base)
{
if (base == 10)
return whisperPrintDecimal(value);
char buffer[20];
int charCount = 0;
unsigned uu = value;
if (base == 8)
{
do
{
char c = '0' + (uu & 7);
buffer[charCount++] = c;
uu >>= 3;
}
while (uu);
}
else if (base == 16)
{
do
{
int digit = uu & 0xf;
char c = digit < 10 ? '0' + digit : 'a' + digit - 10;
buffer[charCount++] = c;
uu >>= 4;
}
while (uu);
}
else
return -1;
char* p = buffer + charCount - 1;
for (unsigned i = 0; i < charCount; ++i)
whisperPutc(*p--);
return charCount;
}
int
whisperPrintfImpl(const char* format, va_list ap)
{
int count = 0; // Printed character count
for (const char* fp = format; *fp; fp++)
{
if (*fp != '%')
{
whisperPutc(*fp);
++count;
continue;
}
++fp; // Skip %
if (*fp == 0)
break;
if (*fp == '%')
{
whisperPutc('%');
continue;
}
if (*fp == '-')
{
fp++; // Pad right not yet implemented.
}
while (*fp == '0')
{
fp++; // Pad zero not yet implented.
}
if (*fp == '*')
{
int width = va_arg(ap, int);
fp++; // Width not yet implemented.
}
else
{
while (*fp >= '0' && *fp <= '9')
++fp; // Width not yet implemented.
}
switch (*fp)
{
case 'd':
count += whisperPrintDecimal(va_arg(ap, int));
break;
case 'u':
count += whisperPrintDecimal((unsigned) va_arg(ap, unsigned));
break;
case 'x':
case 'X':
count += whisperPrintInt(va_arg(ap, int), 16);
break;
case 'o':
count += whisperPrintInt(va_arg(ap, int), 8);
break;
case 'c':
whisperPutc(va_arg(ap, int));
++count;
break;
case 's':
count += whisperPuts(va_arg(ap, char*));
break;
}
}
return count;
}
int
whisperPrintf(const char* format, ...)
{
va_list ap;
va_start(ap, format);
int code = whisperPrintfImpl(format, ap);
va_end(ap);
return code;
}

View File

@ -0,0 +1,7 @@
This is dhrystone, compiled according to the spec:
1. Files dhry_1.c and dhry2_.c compiled separately.
2. No inlining.
to run in demo TB:
make -f $RV_ROOT/tools/Makefile [<simulator>] TEST=dhry

1
testbench/tests/dhry/crt0.s Symbolic link
View File

@ -0,0 +1 @@
../../asm/crt0.s

437
testbench/tests/dhry/dhry.h Normal file
View File

@ -0,0 +1,437 @@
#pragma once
/*
****************************************************************************
*
* "DHRYSTONE" Benchmark Program
* -----------------------------
*
* Version: C, Version 2.1
*
* File: dhry.h (part 1 of 3)
*
* Date: May 25, 1988
*
* Author: Reinhold P. Weicker
* Siemens AG, E STE 35
* Postfach 3240
* 8520 Erlangen
* Germany (West)
* Phone: [xxx-49]-9131-7-20330
* (8-17 Central European Time)
* Usenet: ..!mcvax!unido!estevax!weicker
*
* Original Version (in Ada) published in
* "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
* pp. 1013 - 1030, together with the statistics
* on which the distribution of statements etc. is based.
*
* In this C version, the following C library functions are used:
* - strcpy, strcmp (inside the measurement loop)
* - printf, scanf (outside the measurement loop)
* In addition, Berkeley UNIX system calls "times ()" or "time ()"
* are used for execution time measurement. For measurements
* on other systems, these calls have to be changed.
*
* Collection of Results:
* Reinhold Weicker (address see above) and
*
* Rick Richardson
* PC Research. Inc.
* 94 Apple Orchard Drive
* Tinton Falls, NJ 07724
* Phone: (201) 389-8963 (9-17 EST)
* Usenet: ...!uunet!pcrat!rick
*
* Please send results to Rick Richardson and/or Reinhold Weicker.
* Complete information should be given on hardware and software used.
* Hardware information includes: Machine type, CPU, type and size
* of caches; for microprocessors: clock frequency, memory speed
* (number of wait states).
* Software information includes: Compiler (and runtime library)
* manufacturer and version, compilation switches, OS version.
* The Operating System version may give an indication about the
* compiler; Dhrystone itself performs no OS calls in the measurement loop.
*
* The complete output generated by the program should be mailed
* such that at least some checks for correctness can be made.
*
***************************************************************************
*
* History: This version C/2.1 has been made for two reasons:
*
* 1) There is an obvious need for a common C version of
* Dhrystone, since C is at present the most popular system
* programming language for the class of processors
* (microcomputers, minicomputers) where Dhrystone is used most.
* There should be, as far as possible, only one C version of
* Dhrystone such that results can be compared without
* restrictions. In the past, the C versions distributed
* by Rick Richardson (Version 1.1) and by Reinhold Weicker
* had small (though not significant) differences.
*
* 2) As far as it is possible without changes to the Dhrystone
* statistics, optimizing compilers should be prevented from
* removing significant statements.
*
* This C version has been developed in cooperation with
* Rick Richardson (Tinton Falls, NJ), it incorporates many
* ideas from the "Version 1.1" distributed previously by
* him over the UNIX network Usenet.
* I also thank Chaim Benedelac (National Semiconductor),
* David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
* Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
* for their help with comments on earlier versions of the
* benchmark.
*
* Changes: In the initialization part, this version follows mostly
* Rick Richardson's version distributed via Usenet, not the
* version distributed earlier via floppy disk by Reinhold Weicker.
* As a concession to older compilers, names have been made
* unique within the first 8 characters.
* Inside the measurement loop, this version follows the
* version previously distributed by Reinhold Weicker.
*
* At several places in the benchmark, code has been added,
* but within the measurement loop only in branches that
* are not executed. The intention is that optimizing compilers
* should be prevented from moving code out of the measurement
* loop, or from removing code altogether. Since the statements
* that are executed within the measurement loop have NOT been
* changed, the numbers defining the "Dhrystone distribution"
* (distribution of statements, operand types and locality)
* still hold. Except for sophisticated optimizing compilers,
* execution times for this version should be the same as
* for previous versions.
*
* Since it has proven difficult to subtract the time for the
* measurement loop overhead in a correct way, the loop check
* has been made a part of the benchmark. This does have
* an impact - though a very minor one - on the distribution
* statistics which have been updated for this version.
*
* All changes within the measurement loop are described
* and discussed in the companion paper "Rationale for
* Dhrystone version 2".
*
* Because of the self-imposed limitation that the order and
* distribution of the executed statements should not be
* changed, there are still cases where optimizing compilers
* may not generate code for some statements. To a certain
* degree, this is unavoidable for small synthetic benchmarks.
* Users of the benchmark are advised to check code listings
* whether code is generated for all statements of Dhrystone.
*
* Version 2.1 is identical to version 2.0 distributed via
* the UNIX network Usenet in March 1988 except that it corrects
* some minor deficiencies that were found by users of version 2.0.
* The only change within the measurement loop is that a
* non-executed "else" part was added to the "if" statement in
* Func_3, and a non-executed "else" part removed from Proc_3.
*
***************************************************************************
*
* Defines: The following "Defines" are possible:
* -DREG=register (default: Not defined)
* As an approximation to what an average C programmer
* might do, the "register" storage class is applied
* (if enabled by -DREG=register)
* - for local variables, if they are used (dynamically)
* five or more times
* - for parameters if they are used (dynamically)
* six or more times
* Note that an optimal "register" strategy is
* compiler-dependent, and that "register" declarations
* do not necessarily lead to faster execution.
* -DNOSTRUCTASSIGN (default: Not defined)
* Define if the C compiler does not support
* assignment of structures.
* -DNOENUMS (default: Not defined)
* Define if the C compiler does not support
* enumeration types.
* -DTIMES (default)
* -DTIME
* The "times" function of UNIX (returning process times)
* or the "time" function (returning wallclock time)
* is used for measurement.
* For single user machines, "time ()" is adequate. For
* multi-user machines where you cannot get single-user
* access, use the "times ()" function. If you have
* neither, use a stopwatch in the dead of night.
* "printf"s are provided marking the points "Start Timer"
* and "Stop Timer". DO NOT use the UNIX "time(1)"
* command, as this will measure the total time to
* run this program, which will (erroneously) include
* the time to allocate storage (malloc) and to perform
* the initialization.
* -DHZ=nnn
* In Berkeley UNIX, the function "times" returns process
* time in 1/HZ seconds, with HZ = 60 for most systems.
* CHECK YOUR SYSTEM DESCRIPTION BEFORE YOU JUST APPLY
* A VALUE.
*
***************************************************************************
*
* Compilation model and measurement (IMPORTANT):
*
* This C version of Dhrystone consists of three files:
* - dhry.h (this file, containing global definitions and comments)
* - dhry_1.c (containing the code corresponding to Ada package Pack_1)
* - dhry_2.c (containing the code corresponding to Ada package Pack_2)
*
* The following "ground rules" apply for measurements:
* - Separate compilation
* - No procedure merging
* - Otherwise, compiler optimizations are allowed but should be indicated
* - Default results are those without register declarations
* See the companion paper "Rationale for Dhrystone Version 2" for a more
* detailed discussion of these ground rules.
*
* For 16-Bit processors (e.g. 80186, 80286), times for all compilation
* models ("small", "medium", "large" etc.) should be given if possible,
* together with a definition of these models for the compiler system used.
*
**************************************************************************
*
* Dhrystone (C version) statistics:
*
* [Comment from the first distribution, updated for version 2.
* Note that because of language differences, the numbers are slightly
* different from the Ada version.]
*
* The following program contains statements of a high level programming
* language (here: C) in a distribution considered representative:
*
* assignments 52 (51.0 %)
* control statements 33 (32.4 %)
* procedure, function calls 17 (16.7 %)
*
* 103 statements are dynamically executed. The program is balanced with
* respect to the three aspects:
*
* - statement type
* - operand type
* - operand locality
* operand global, local, parameter, or constant.
*
* The combination of these three aspects is balanced only approximately.
*
* 1. Statement Type:
* ----------------- number
*
* V1 = V2 9
* (incl. V1 = F(..)
* V = Constant 12
* Assignment, 7
* with array element
* Assignment, 6
* with record component
* --
* 34 34
*
* X = Y +|-|"&&"|"|" Z 5
* X = Y +|-|"==" Constant 6
* X = X +|- 1 3
* X = Y *|/ Z 2
* X = Expression, 1
* two operators
* X = Expression, 1
* three operators
* --
* 18 18
*
* if .... 14
* with "else" 7
* without "else" 7
* executed 3
* not executed 4
* for ... 7 | counted every time
* while ... 4 | the loop condition
* do ... while 1 | is evaluated
* switch ... 1
* break 1
* declaration with 1
* initialization
* --
* 34 34
*
* P (...) procedure call 11
* user procedure 10
* library procedure 1
* X = F (...)
* function call 6
* user function 5
* library function 1
* --
* 17 17
* ---
* 103
*
* The average number of parameters in procedure or function calls
* is 1.82 (not counting the function values aX *
*
* 2. Operators
* ------------
* number approximate
* percentage
*
* Arithmetic 32 50.8
*
* + 21 33.3
* - 7 11.1
* * 3 4.8
* / (int div) 1 1.6
*
* Comparison 27 42.8
*
* == 9 14.3
* /= 4 6.3
* > 1 1.6
* < 3 4.8
* >= 1 1.6
* <= 9 14.3
*
* Logic 4 6.3
*
* && (AND-THEN) 1 1.6
* | (OR) 1 1.6
* ! (NOT) 2 3.2
*
* -- -----
* 63 100.1
*
*
* 3. Operand Type (counted once per operand reference):
* ---------------
* number approximate
* percentage
*
* Integer 175 72.3 %
* Character 45 18.6 %
* Pointer 12 5.0 %
* String30 6 2.5 %
* Array 2 0.8 %
* Record 2 0.8 %
* --- -------
* 242 100.0 %
*
* When there is an access path leading to the final operand (e.g. a record
* component), only the final data type on the access path is counted.
*
*
* 4. Operand Locality:
* -------------------
* number approximate
* percentage
*
* local variable 114 47.1 %
* global variable 22 9.1 %
* parameter 45 18.6 %
* value 23 9.5 %
* reference 22 9.1 %
* function result 6 2.5 %
* constant 55 22.7 %
* --- -------
* 242 100.0 %
*
*
* The program does not compute anything meaningful, but it is syntactically
* and semantically correct. All variables have a value assigned to them
* before they are used as a source operand.
*
* There has been no explicit effort to account for the effects of a
* cache, or to balance the use of long or short displacements for code or
* data.
*
***************************************************************************
*/
/* Compiler and system dependent definitions: */
#ifndef TIME
#undef TIMES
#define TIMES
#endif
/* Use times(2) time function unless */
/* explicitly defined otherwise */
#ifdef MSC_CLOCK
#undef HZ
#undef TIMES
#include <time.h>
#define HZ CLK_TCK
#endif
/* Use Microsoft C hi-res clock */
#ifdef TIMES
#include <sys/types.h>
#include <sys/times.h>
#ifndef HZ
#define HZ 100
#endif
/* for "times" */
#endif
#define Mic_secs_Per_Second 1000000.0
/* Berkeley UNIX C returns process times in seconds/HZ */
#ifdef NOSTRUCTASSIGN
#define structassign(d, s) memcpy(&(d), &(s), sizeof(d))
#else
#define structassign(d, s) d = s
#endif
#ifdef NOENUM
#define Ident_1 0
#define Ident_2 1
#define Ident_3 2
#define Ident_4 3
#define Ident_5 4
typedef int Enumeration;
#else
typedef enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5}
Enumeration;
#endif
/* for boolean and enumeration types in Ada, Pascal */
/* General definitions: */
//#include <stdio.h>
/* for strcpy, strcmp */
#define Null 0
/* Value of a Null pointer */
#define true 1
#define false 0
typedef int One_Thirty;
typedef int One_Fifty;
typedef char Capital_Letter;
typedef int Boolean;
typedef char Str_30 [31];
typedef int Arr_1_Dim [50];
typedef int Arr_2_Dim [50] [50];
typedef struct record
{
struct record *Ptr_Comp;
Enumeration Discr;
union {
struct {
Enumeration Enum_Comp;
int Int_Comp;
char Str_Comp [31];
} var_1;
struct {
Enumeration E_Comp_2;
char Str_2_Comp [31];
} var_2;
struct {
char Ch_1_Comp;
char Ch_2_Comp;
} var_3;
} variant;
} Rec_Type, *Rec_Pointer;

View File

@ -0,0 +1 @@
../../asm/hello_world_dccm.ld

View File

@ -0,0 +1,2 @@
OFILES = crt0.o dhry_1.o dhry_2.o printf.o
TEST_CFLAGS = -g -O3

View File

@ -0,0 +1,452 @@
#define SWERV
/*
****************************************************************************
*
* "DHRYSTONE" Benchmark Program
* -----------------------------
*
* Version: C, Version 2.1
*
* File: dhry_1.c (part 2 of 3)
*
* Date: May 25, 1988
*
* Author: Reinhold P. Weicker
*
****************************************************************************
*/
#ifdef SWERV
#include <stdio.h>
#include <stdint.h>
extern uint64_t get_mcycle();
#endif
#include "dhry.h"
/* Global Variables: */
Rec_Pointer Ptr_Glob,
Next_Ptr_Glob;
int Int_Glob;
Boolean Bool_Glob;
char Ch_1_Glob,
Ch_2_Glob;
int Arr_1_Glob [50];
int Arr_2_Glob [50] [50];
Enumeration Func_1 ();
/* forward declaration necessary since Enumeration may not simply be int */
#ifndef REG
Boolean Reg = false;
#define REG
/* REG becomes defined as empty */
/* i.e. no register variables */
#else
Boolean Reg = true;
#endif
/* variables for time measurement: */
#ifdef TIMES
struct tms time_info;
#define Too_Small_Time (2*HZ)
/* Measurements should last at least about 2 seconds */
#endif
#ifdef TIME
extern long time();
/* see library function "time" */
#define Too_Small_Time 2
/* Measurements should last at least 2 seconds */
#endif
#ifdef MSC_CLOCK
extern clock_t clock();
#define Too_Small_Time (2*HZ)
#endif
long
Begin_Time,
End_Time,
User_Time;
float Microseconds,
Dhrystones_Per_Second;
/* end of variables for time measurement */
extern char* strcpy(char*, const char*);
extern Boolean Func_2 (Str_30, Str_30);
extern void Proc_7 (One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val,
One_Fifty *Int_Par_Ref);
extern void Proc_8 (Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref,
int Int_1_Par_Val, int Int_2_Par_Val);
extern void Proc_6 (Enumeration Enum_Val_Par,
Enumeration *Enum_Ref_Par);
void Proc_5();
void Proc_4();
void Proc_1(Rec_Pointer Ptr_Val_Par);
void Proc_2(One_Fifty *Int_Par_Ref);
void Proc_3(Rec_Pointer *Ptr_Ref_Par);
int
main ()
/*****/
/* main program, corresponds to procedures */
/* Main and Proc_0 in the Ada version */
{
One_Fifty Int_1_Loc;
REG One_Fifty Int_2_Loc;
One_Fifty Int_3_Loc;
REG char Ch_Index;
Enumeration Enum_Loc;
Str_30 Str_1_Loc;
Str_30 Str_2_Loc;
REG int Run_Index;
REG int Number_Of_Runs;
/* Initializations */
Rec_Type rec0;
Rec_Type rec1;
Next_Ptr_Glob = &rec0;
Ptr_Glob = &rec1;
Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
Ptr_Glob->Discr = Ident_1;
Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
Ptr_Glob->variant.var_1.Int_Comp = 40;
strcpy (Ptr_Glob->variant.var_1.Str_Comp,
"DHRYSTONE PROGRAM, SOME STRING");
strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
Arr_2_Glob [8][7] = 10;
/* Was missing in published program. Without this statement, */
/* Arr_2_Glob [8][7] would have an undefined value. */
/* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */
/* overflow may occur for this array element. */
printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
if (Reg)
{
printf ("Program compiled with 'register' attribute\n");
}
else
{
printf ("Program compiled without 'register' attribute\n");
}
#ifndef SWERV
printf ("Please give the number of runs through the benchmark: ");
{
int n = 1000;
scanf ("%d", &n);
Number_Of_Runs = n;
}
printf ("\n");
#else
// We do not have scanf. Hardwire number of runs.
Number_Of_Runs = 1000;
#endif
printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs);
/***************/
/* Start timer */
/***************/
#ifdef SWERV
Begin_Time = get_mcycle();
#else
#ifdef TIMES
times (&time_info);
Begin_Time = (long) time_info.tms_utime;
#endif
#ifdef TIME
Begin_Time = time ( (long *) 0);
#endif
#ifdef MSC_CLOCK
Begin_Time = clock();
#endif
#endif
__asm("__perf_start:");
for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index)
{
__asm("__loop_start:");
Proc_5();
Proc_4();
/* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
Int_1_Loc = 2;
Int_2_Loc = 3;
strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
Enum_Loc = Ident_2;
Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
/* Bool_Glob == 1 */
while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
{
Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
/* Int_3_Loc == 7 */
Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
/* Int_3_Loc == 7 */
Int_1_Loc += 1;
} /* while */
/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
/* Int_Glob == 5 */
Proc_1 (Ptr_Glob);
for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
/* loop body executed twice */
{
if (Enum_Loc == Func_1 (Ch_Index, 'C'))
/* then, not executed */
{
Proc_6 (Ident_1, &Enum_Loc);
strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
Int_2_Loc = Run_Index;
Int_Glob = Run_Index;
}
}
/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
Int_2_Loc = Int_2_Loc * Int_1_Loc;
Int_1_Loc = Int_2_Loc / Int_3_Loc;
Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
/* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
Proc_2 (&Int_1_Loc);
/* Int_1_Loc == 5 */
} /* loop "for Run_Index" */
__asm("__perf_end:");
/**************/
/* Stop timer */
/**************/
#ifdef SWERV
End_Time = get_mcycle();
printf("End_time=%d\n", (int) End_Time);
#else
#ifdef TIMES
times (&time_info);
End_Time = (long) time_info.tms_utime;
#endif
#ifdef TIME
End_Time = time ( (long *) 0);
#endif
#ifdef MSC_CLOCK
End_Time = clock();
#endif
#endif
printf ("Final values of the variables used in the benchmark:\n\n");
printf ("Int_Glob: %d\n", Int_Glob);
printf (" should be: %d\n", 5);
printf ("Bool_Glob: %d\n", Bool_Glob);
printf (" should be: %d\n", 1);
printf ("Ch_1_Glob: %c\n", Ch_1_Glob);
printf (" should be: %c\n", 'A');
printf ("Ch_2_Glob: %c\n", Ch_2_Glob);
printf (" should be: %c\n", 'B');
printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]);
printf (" should be: %d\n", 7);
printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]);
printf (" should be: Number_Of_Runs + 10\n");
printf ("Ptr_Glob->Ptr_Comp: %x\n", (int) Ptr_Glob->Ptr_Comp);
printf (" should be: (implementation-dependent)\n");
printf (" Discr: %d\n", Ptr_Glob->Discr);
printf (" should be: %d\n", 0);
printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp);
printf (" should be: %d\n", 2);
printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp);
printf (" should be: %d\n", 17);
printf (" Str_Comp: %s", Ptr_Glob->variant.var_1.Str_Comp);
printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
printf ("Next_Ptr_Glob->Ptr_Comp:%x\n", (int) Next_Ptr_Glob->Ptr_Comp);
printf (" should be: (implementation-dependent), same as above\n");
printf (" Discr: %d\n", Next_Ptr_Glob->Discr);
printf (" should be: %d\n", 0);
printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp);
printf (" should be: %d\n", 1);
printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp);
printf (" should be: %d\n", 18);
printf (" Str_Comp: %s", Next_Ptr_Glob->variant.var_1.Str_Comp);
printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
printf ("Int_1_Loc: %d\n", Int_1_Loc);
printf (" should be: %d\n", 5);
printf ("Int_2_Loc: %d\n", Int_2_Loc);
printf (" should be: %d\n", 13);
printf ("Int_3_Loc: %d\n", Int_3_Loc);
printf (" should be: %d\n", 7);
printf ("Enum_Loc: %d\n", Enum_Loc);
printf (" should be: %d\n", 1);
printf ("Str_1_Loc: %s", Str_1_Loc);
printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
printf ("Str_2_Loc: %s", Str_2_Loc);
printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
printf ("\n");
User_Time = End_Time - Begin_Time;
if (User_Time < Too_Small_Time)
{
printf ("User time %d\n", User_Time);
printf ("Measured time too small to obtain meaningful results\n");
printf ("Please increase number of runs\n");
printf ("\n");
}
else
{
#ifdef SWERV
printf ("Run time = %d clocks for %d Dhrystones\n", User_Time, Number_Of_Runs );
printf ("Dhrystones per Second per MHz: ");
printf ("%d.%02d", 1000000*Number_Of_Runs/User_Time,(100000000*Number_Of_Runs/User_Time) % 100);
#else
#ifdef TIME
Microseconds = (float) User_Time * Mic_secs_Per_Second
/ (float) Number_Of_Runs;
Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time;
#else
Microseconds = (float) User_Time * Mic_secs_Per_Second
/ ((float) HZ * ((float) Number_Of_Runs));
Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs)
/ (float) User_Time;
#endif
printf ("Microseconds for one run through Dhrystone: ");
printf ("%6.1f \n", Microseconds);
printf ("Dhrystones per Second: ");
printf ("%6.1f \n", Dhrystones_Per_Second);
#endif
printf ("\n");
}
}
void
Proc_1 (Ptr_Val_Par)
/******************/
REG Rec_Pointer Ptr_Val_Par;
/* executed once */
{
REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
/* == Ptr_Glob_Next */
/* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */
/* corresponds to "rename" in Ada, "with" in Pascal */
structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob);
Ptr_Val_Par->variant.var_1.Int_Comp = 5;
Next_Record->variant.var_1.Int_Comp
= Ptr_Val_Par->variant.var_1.Int_Comp;
Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
Proc_3 (&Next_Record->Ptr_Comp);
/* Ptr_Val_Par->Ptr_Comp->Ptr_Comp
== Ptr_Glob->Ptr_Comp */
if (Next_Record->Discr == Ident_1)
/* then, executed */
{
Next_Record->variant.var_1.Int_Comp = 6;
Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp,
&Next_Record->variant.var_1.Enum_Comp);
Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
Proc_7 (Next_Record->variant.var_1.Int_Comp, 10,
&Next_Record->variant.var_1.Int_Comp);
}
else /* not executed */
structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
} /* Proc_1 */
void
Proc_2 (Int_Par_Ref)
/******************/
/* executed once */
/* *Int_Par_Ref == 1, becomes 4 */
One_Fifty *Int_Par_Ref;
{
One_Fifty Int_Loc;
Enumeration Enum_Loc;
Int_Loc = *Int_Par_Ref + 10;
do /* executed once */
if (Ch_1_Glob == 'A')
/* then, executed */
{
Int_Loc -= 1;
*Int_Par_Ref = Int_Loc - Int_Glob;
Enum_Loc = Ident_1;
} /* if */
while (Enum_Loc != Ident_1); /* true */
} /* Proc_2 */
void
Proc_3 (Ptr_Ref_Par)
/******************/
/* executed once */
/* Ptr_Ref_Par becomes Ptr_Glob */
Rec_Pointer *Ptr_Ref_Par;
{
if (Ptr_Glob != Null)
/* then, executed */
*Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
} /* Proc_3 */
void
Proc_4 () /* without parameters */
/*******/
/* executed once */
{
Boolean Bool_Loc;
Bool_Loc = Ch_1_Glob == 'A';
Bool_Glob = Bool_Loc | Bool_Glob;
Ch_2_Glob = 'B';
} /* Proc_4 */
void
Proc_5 () /* without parameters */
/*******/
/* executed once */
{
Ch_1_Glob = 'A';
Bool_Glob = false;
} /* Proc_5 */
/* Procedure for the assignment of structures, */
/* if the C compiler doesn't support this feature */
#ifdef NOSTRUCTASSIGN
memcpy (d, s, l)
register char *d;
register char *s;
register int l;
{
while (l--) *d++ = *s++;
}
#endif

View File

@ -0,0 +1,214 @@
/*
****************************************************************************
*
* "DHRYSTONE" Benchmark Program
* -----------------------------
*
* Version: C, Version 2.1
*
* File: dhry_2.c (part 3 of 3)
*
* Date: May 25, 1988
*
* Author: Reinhold P. Weicker
*
****************************************************************************
*/
#include "dhry.h"
#ifndef REG
#define REG
/* REG becomes defined as empty */
/* i.e. no register variables */
#endif
extern int Int_Glob;
extern char Ch_1_Glob;
#if 0
int
strcmp(const char* s1, const char* s2)
{
while (*s1 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s1 == *s2)
return 0;
return *s1 > *s2? 1 : -1;
}
#else
extern int strcmp( char* s1, char* s2);
#endif
Boolean Func_3 (Enumeration Enum_Par_Val);
void
Proc_6 (Enum_Val_Par, Enum_Ref_Par)
/*********************************/
/* executed once */
/* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
Enumeration Enum_Val_Par;
Enumeration *Enum_Ref_Par;
{
*Enum_Ref_Par = Enum_Val_Par;
if (! Func_3 (Enum_Val_Par))
/* then, not executed */
*Enum_Ref_Par = Ident_4;
switch (Enum_Val_Par)
{
case Ident_1:
*Enum_Ref_Par = Ident_1;
break;
case Ident_2:
if (Int_Glob > 100)
/* then */
*Enum_Ref_Par = Ident_1;
else *Enum_Ref_Par = Ident_4;
break;
case Ident_3: /* executed */
*Enum_Ref_Par = Ident_2;
break;
case Ident_4: break;
case Ident_5:
*Enum_Ref_Par = Ident_3;
break;
} /* switch */
} /* Proc_6 */
void
Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref)
/**********************************************/
/* executed three times */
/* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */
/* Int_Par_Ref becomes 7 */
/* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
/* Int_Par_Ref becomes 17 */
/* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
/* Int_Par_Ref becomes 18 */
One_Fifty Int_1_Par_Val;
One_Fifty Int_2_Par_Val;
One_Fifty *Int_Par_Ref;
{
One_Fifty Int_Loc;
Int_Loc = Int_1_Par_Val + 2;
*Int_Par_Ref = Int_2_Par_Val + Int_Loc;
} /* Proc_7 */
void
Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val)
/*********************************************************************/
/* executed once */
/* Int_Par_Val_1 == 3 */
/* Int_Par_Val_2 == 7 */
Arr_1_Dim Arr_1_Par_Ref;
Arr_2_Dim Arr_2_Par_Ref;
int Int_1_Par_Val;
int Int_2_Par_Val;
{
REG One_Fifty Int_Index;
REG One_Fifty Int_Loc;
Int_Loc = Int_1_Par_Val + 5;
Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
Int_Glob = 5;
} /* Proc_8 */
Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val)
/*************************************************/
/* executed three times */
/* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */
/* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */
/* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */
Capital_Letter Ch_1_Par_Val;
Capital_Letter Ch_2_Par_Val;
{
Capital_Letter Ch_1_Loc;
Capital_Letter Ch_2_Loc;
Ch_1_Loc = Ch_1_Par_Val;
Ch_2_Loc = Ch_1_Loc;
if (Ch_2_Loc != Ch_2_Par_Val)
/* then, executed */
return (Ident_1);
else /* not executed */
{
Ch_1_Glob = Ch_1_Loc;
return (Ident_2);
}
} /* Func_1 */
Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref)
/*************************************************/
/* executed once */
/* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
/* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
Str_30 Str_1_Par_Ref;
Str_30 Str_2_Par_Ref;
{
REG One_Thirty Int_Loc;
Capital_Letter Ch_Loc;
Int_Loc = 2;
while (Int_Loc <= 2) /* loop body executed once */
if (Func_1 (Str_1_Par_Ref[Int_Loc],
Str_2_Par_Ref[Int_Loc+1]) == Ident_1)
/* then, executed */
{
Ch_Loc = 'A';
Int_Loc += 1;
} /* if, while */
if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
/* then, not executed */
Int_Loc = 7;
if (Ch_Loc == 'R')
/* then, not executed */
return (true);
else /* executed */
{
if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
/* then, not executed */
{
Int_Loc += 7;
Int_Glob = Int_Loc;
return (true);
}
else /* executed */
return (false);
} /* if Ch_Loc */
} /* Func_2 */
Boolean Func_3 (Enum_Par_Val)
/***************************/
/* executed once */
/* Enum_Par_Val == Ident_3 */
Enumeration Enum_Par_Val;
{
Enumeration Enum_Loc;
Enum_Loc = Enum_Par_Val;
if (Enum_Loc == Ident_3)
/* then, executed */
return (true);
else /* not executed */
return (false);
} /* Func_3 */

View File

@ -0,0 +1 @@
../../asm/printf.c

View File

@ -0,0 +1,6 @@
export TEST = hello_world
export OFILES = hello_world.o
export BUILD_DIR = ../snapshots/default
clean .DEFAULT:
$(MAKE) -e -f $(RV_ROOT)/tools/MakeHex $@

View File

@ -0,0 +1,72 @@
// 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:
// 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
// Enable Caches in MRAC
li x1, 0x5f555555
csrw 0x7c0, x1
// Load string from hw_data
// and write to stdout address
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 terminate test.
_finish:
li x3, STDOUT
addi x5, x0, 0xff
sb x5, 0(x3)
beq x0, x0, _finish
.rept 100
nop
.endr
.global hw_data
.data
hw_data:
.ascii "----------------------------------\n"
.ascii "Hello World from SweRV EH1 @WDC !!\n"
.ascii "----------------------------------\n"
.byte 0

View File

@ -13,12 +13,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
CONF_PARAMS = -set iccm_enable
# Check for RV_ROOT
ifeq (,$(wildcard ${RV_ROOT}/configs/swerv.config))
$(error env var RV_ROOT does not point to a valid dir! Exiting!)
endif
TEST_CFLAGS = -g -O3 -funroll-all-loops
ABI = -mabi=ilp32 -march=rv32imc
# Allow snapshot override
target = default
snapshot = $(target)
@ -40,6 +43,9 @@ TEST = hello_world
# Define default test directory
TEST_DIR = $(TBDIR)/asm
HEX_DIR = $(TBDIR)/hex
ifneq (,$(wildcard $(TBDIR)/tests/$(TEST)))
TEST_DIR = $(TBDIR)/tests/$(TEST)
endif
ifdef debug
DEBUG_PLUS = +dumpon
@ -57,6 +63,10 @@ else
LINK = $(TEST_DIR)/$(TEST).ld
endif
OFILES = $(TEST).o
-include $(TEST_DIR)/$(TEST).mki
VPATH = $(TEST_DIR) $(BUILD_DIR) $(TBDIR)
TBFILES = $(TBDIR)/tb_top.sv $(TBDIR)/ahb_sif.sv
@ -67,13 +77,13 @@ includes = -I${RV_ROOT}/design/include -I${RV_ROOT}/design/lib -I${BUILD_DIR}
CFLAGS += "-std=c++11"
# Optimization for better performance; alternative is nothing for slower runtime (faster compiles)
# -O2 for faster runtime (slower compiles), or -O for balance.
VERILATOR_MAKE_FLAGS = OPT_FAST="-O2"
VERILATOR_MAKE_FLAGS = OPT_FAST="-Os"
# Targets
all: clean verilator
clean:
rm -rf *.log *.s *.hex *.dis *.tbl irun* vcs* simv* snapshots swerv* \
rm -rf *.log *.s *.hex *.dis *.tbl irun* vcs* simv* *.map snapshots swerv* \
verilator* *.exe obj* *.o ucli.key vc_hdrs.h csrc *.csv \
work dataset.asdb library.cfg
@ -81,16 +91,18 @@ clean:
${BUILD_DIR}/defines.h :
BUILD_PATH=${BUILD_DIR} ${SWERV_CONFIG} -target=$(target) $(CONF_PARAMS)
##################### Verilog Builds #####################################
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) \
$(VERILATOR) --cc -CFLAGS ${CFLAGS} $(defines) $(includes) \
-Wno-UNOPTFLAT \
-I${RV_ROOT}/testbench \
-f ${RV_ROOT}/testbench/flist \
${TBFILES} \
--top-module tb_top -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)
$(MAKE) -j -C obj_dir/ -f Vtb_top.mk $(VERILATOR_MAKE_FLAGS)
touch verilator-build
vcs-build: ${TBFILES} ${BUILD_DIR}/defines.h
@ -108,7 +120,7 @@ irun-build: ${TBFILES} ${BUILD_DIR}/defines.h
-incdir ${RV_ROOT}/design/lib -incdir ${RV_ROOT}/design/include -incdir ${BUILD_DIR} -vlog_ext +.vh+.h\
$(defines) -f ${RV_ROOT}/testbench/flist\
-top tb_top ${TBFILES} -I${RV_ROOT}/testbench \
-elaborate -snapshot $(snapshot)
-elaborate -snapshot $(snapshot) $(profile)
touch irun-build
riviera-build: ${TBFILES} ${BUILD_DIR}/defines.h
@ -121,23 +133,30 @@ riviera-build: ${TBFILES} ${BUILD_DIR}/defines.h
${TBFILES}
touch riviera-build
##################### Simulation Runs #####################################
verilator: program.hex verilator-build
./obj_dir/Vtb_top ${DEBUG_PLUS}
irun: program.hex irun-build
$(IRUN) -64bit -abvglobalfailurelimit 1 +lic_queue -licqueue -status -xmlibdirpath . -xmlibdirname swerv.build \
-snapshot ${snapshot} -r ${snapshot} $(IRUN_DEBUG_RUN)
$(IRUN) -64bit +lic_queue -licqueue -status -xmlibdirpath . -xmlibdirname swerv.build \
-snapshot ${snapshot} -r ${snapshot} $(IRUN_DEBUG_RUN) $(profile)
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}
$(defines) -f ${RV_ROOT}/testbench/flist ${TBFILES} -R +nowarn3829 ${DEBUG_PLUS}
riviera: program.hex riviera-build
vsim -c -lib work ${DEBUG_PLUS} ${RIVIERA_DEBUG} tb_top -do "run -all; exit" -l riviera.log
##################### Test Build #####################################
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 !!"
@ -147,19 +166,17 @@ ifneq (,$(wildcard $(TEST_DIR)/$(TEST).makefile))
program.hex:
$(MAKE) -f $(TEST_DIR)/$(TEST).makefile
else
program.hex: $(TEST).o $(LINK)
program.hex: $(OFILES) $(LINK)
@echo Building $(TEST)
$(GCC_PREFIX)-ld -m elf32lriscv --discard-none -T$(LINK) -o $(TEST).exe $(TEST).o
$(GCC_PREFIX)-gcc $(ABI) -Wl,-Map=$(TEST).map -lgcc -T$(LINK) -o $(TEST).exe $(OFILES) -nostartfiles $(TEST_LIBS)
$(GCC_PREFIX)-objcopy -O verilog $(TEST).exe program.hex
$(GCC_PREFIX)-objdump -S $(TEST).exe > $(TEST).dis
@echo Completed building $(TEST)
%.o : %.s ${BUILD_DIR}/defines.h
$(GCC_PREFIX)-cpp -I${BUILD_DIR} $< > $(TEST).cpp.s
$(GCC_PREFIX)-as -march=rv32gc $(TEST).cpp.s -o $(TEST).o
$(GCC_PREFIX)-cpp -I${BUILD_DIR} $< > $*.cpp.s
$(GCC_PREFIX)-as $(ABI) $*.cpp.s -o $@
TEST_CFLAGS = -g -O3 -funroll-all-loops
ABI = -mabi=ilp32 -march=rv32imc
%.o : %.c ${BUILD_DIR}/defines.h
$(GCC_PREFIX)-gcc -I${BUILD_DIR} ${TEST_CFLAGS} ${ABI} -nostdlib -c $< -o $@

View File

@ -1 +1,2 @@
set_property is_global_include true [get_files config/common_defines.vh]
set_property IS_GLOBAL_INCLUDE 1 [get_files include/def.sv]