Initial load of files

This commit is contained in:
rsnikhil
2019-03-26 14:49:40 -04:00
parent bc62f17032
commit ee24a93944
1008 changed files with 354221 additions and 224 deletions

View File

@@ -0,0 +1,94 @@
default: compile link
all: compile link simulate
TOP = Testbench
TOPFILE = $(TOP).bsv
TOPMODULE = mk$(TOP)
# BSCFLAGS = -keep-fires -aggressive-conditions -no-warn-action-shadowing -no-inline-rwire
# BSCFLAGS = -keep-fires -aggressive-conditions -no-inline-rwire -show-range-conflict -show-schedule
BSCFLAGS = -D RV32 \
-keep-fires \
-aggressive-conditions \
-suppress-warnings G0020 \
-show-schedule
# ----------------------------------------------------------------
# FOR BLUESIM
ISA_DECLS_DIR = $(HOME)/Projects/RISCV/Bluespec_RISCV/ISA
TRX_DIR = $(HOME)/Projects/RISCV/Bluespec_RISCV/Fabrics/TRX
ADDL_LIBS_DIR = $(HOME)/Projects/RISCV/Bluespec_RISCV/BSV_Additional_Libs/BSV
BSCDIRS_BSIM = -simdir build_bsim -bdir build -info-dir build
BSCPATH_BSIM = -p .:..:$(ISA_DECLS_DIR):$(TRX_DIR):$(ADDL_LIBS_DIR):%/Prelude:%/Libraries
build_bsim:
mkdir -p $@
build:
mkdir -p $@
.PHONY: compile
compile: build_bsim build
@echo Compiling...
bsc -u -sim $(BSCDIRS_BSIM) $(BSCFLAGS) $(BSCPATH_BSIM) $(TOPFILE)
@echo Compilation finished
.PHONY: link
link:
@echo Linking...
bsc -e $(TOPMODULE) $(BSCFLAGS) -parallel-sim-link 8 -sim -o ./$(TOP)_bsim_exe $(BSCDIRS_BSIM) $(BSCPATH_BSIM)
@echo Linking finished
.PHONY: simulate
simulate:
@echo Simulation...
logsave bsim.log ./$(TOP)_bsim_exe -V
@echo Simulation finished
# ----------------------------------------------------------------
# FOR VERILOG
BSCDIRS_V = -vdir verilog -bdir build_v -info-dir build_v
BSCPATH_V = -p .:./$(SRC_BSV):%/Prelude:%/Libraries:%/Libraries/TLM3
# Set VSIM to desired Verilog simulator
# VSIM = modelsim
VSIM ?= cvc
# VSIM ?= iverilog
build_v:
mkdir -p $@
verilog:
mkdir -p $@
.PHONY: rtl
rtl: build_v verilog
@echo Verilog generation ...
bsc -u -elab -verilog $(BSCDIRS_V) $(BSCFLAGS) $(BSCPATH_V) $(TOPFILE)
@echo Verilog generation finished
.PHONY: vlink
vlink:
bsc -v -e $(TOPMODULE) -verilog -o ./out_v -vdir verilog -vsim $(VSIM) -keep-fires \
verilog/$(TOPMODULE).v
.PHONY: vsim
vsim:
@echo Simulation...
./out_v
@echo Simulation finished
# ----------------------------------------------------------------
.PHONY: clean
clean:
rm -f *~ src_*/*~ src_*/*.o build/* build_bsim/* build_v/* *.cxx *.h *.o
.PHONY: full_clean
full_clean: clean
rm -r -f *_bsim_exe *.so out_v verilog build build_bsim dump.vcd bsim.log

View File

@@ -0,0 +1,597 @@
package Testbench;
// ================================================================
// Testbench for basic sanity-check testing of the Debug Module.
// ================================================================
// BSV library imports
import FIFOF :: *;
import GetPut :: *;
import ClientServer :: *;
import Connectable :: *;
import StmtFSM :: *;
// ----------------
// Other library imports
import Semi_FIFOF :: *;
// ================================================================
import ISA_Decls :: *;
import TRX :: *;
import Debug_Module :: *;
// ================================================================
Integer csr_addr_dcsr = 'h7b0;
Integer csr_addr_dpc = 'h7b1;
Integer csr_addr_dscratch0 = 'h7b2;
Integer csr_addr_dscratch1 = 'h7b3;
// ================================================================
(* synthesize *)
module mkTestbench (Empty);
// ================================================================
// Cycle-counter and cycle-limit termination
Reg #(Bit #(32)) rg_cycle <- mkReg (0);
Integer cycle_limit = 100;
rule rl_count_cycles;
if (rg_cycle == fromInteger (100)) begin
$display ("Testench: stopping at cycle %0d", cycle_limit);
$finish (0);
end
rg_cycle <= rg_cycle +1;
endrule
// ================================================================
// The Debug Module
Debug_Module_IFC dm <- mkDebug_Module;
// ================================================================
// Model of a hart, and connections to dm
Hart_DM_IFC hart0 <- mkHart_Model (0);
// Reset
mkConnection (dm.hart0_reset_req, hart0.hart_reset_req);
// Run-control
mkConnection (dm.hart0_run_req_rsp, hart0.hart_run_req_rsp);
// GPR access
mkConnection (dm.master_for_gprs, hart0.slave_for_gprs);
// CSR access
mkConnection (dm.master_for_csrs, hart0.slave_for_csrs);
// ================================================================
// Over-simplified model of platform reset (all except DM)
rule rl_ndm_reset;
let x <- dm.ndm_reset_req.get;
$display ("Testbench.rl_ndm_reset: Resetting all platform except Debug Module");
endrule
// ================================================================
// Over-simplified model of system (RISC-V) memory
// On reads, return addr + 2.
rule rl_mem_read;
let rda <- pop_o (dm.master.fo_rda);
let data = rda.addr + 2; // Bogus data, for now
let rdr = TRX_RdR {trans_id: rda.trans_id,
status : TRX_OKAY,
data : data};
dm.master.fi_rdr.enq (rdr);
$display ("Testbench: memory read [0x%08h] => 0x%08h", rda.addr, data);
endrule
rule rl_mem_write;
let wra <- pop_o (dm.master.fo_wra);
let wrd <- pop_o (dm.master.fo_wrd);
let wrr = TRX_WrR {trans_id: wra.trans_id,
status : TRX_OKAY};
dm.master.fi_wrr.enq (wrr);
$display ("Testbench: memory write [0x%08h] <= 0x%08h", wra.addr, wrd.data);
endrule
// ================================================================
// Abstract command sequences (read/write GPR/CSR)
Reg #(Bit #(32)) rg_abstractcs <- mkRegU;
// Read a register
function Stmt fn_stmt_read_reg (Bit #(16) regno);
return
seq
$display ("----------------\nRead RISC-V reg");
// Clear any prior error status
dm.write (dm_addr_abstractcs, fn_mk_abstractcs (dm_cmderr_w1c));
// Perform the read
dm.write (dm_addr_command,
fn_mk_command_access_reg (DM_COMMAND_ACCESS_REG_SIZE_LOWER32,
False, // postexec
True, // transfer
False, // write
regno));
// Read status to check no error
action
let x <- dm.av_read (dm_addr_abstractcs);
rg_abstractcs <= x;
endaction
while (fn_abstractcs_busy (rg_abstractcs)) seq
$display ("Testbench: read reg: busy");
action
let x <- dm.av_read (dm_addr_abstractcs);
rg_abstractcs <= x;
endaction
endseq
if (fn_abstractcs_cmderr (rg_abstractcs) != DM_ABSTRACTCS_CMDERR_NONE)
$display ("Testbench: read reg => ", fshow (fn_abstractcs_cmderr (rg_abstractcs)));
else action
let x <- dm.av_read (dm_addr_data0);
$display ("Testbench: read reg => 0x%08h", x);
endaction
endseq;
endfunction
// Write a register
function Stmt fn_stmt_write_reg (Bit #(16) regno, Bit #(32) data);
return
seq
$display ("----------------\nWrite RISC-V reg");
// Clear any prior error status
dm.write (dm_addr_abstractcs, fn_mk_abstractcs (dm_cmderr_w1c));
// Write data0
dm.write (dm_addr_data0, data);
// Perform the write
dm.write (dm_addr_command,
fn_mk_command_access_reg (DM_COMMAND_ACCESS_REG_SIZE_LOWER32,
False, // postexec
True, // transfer
True, // write
regno));
// Read status to check no error
action
let x <- dm.av_read (dm_addr_abstractcs);
rg_abstractcs <= x;
endaction
while (fn_abstractcs_busy (rg_abstractcs)) seq
$display ("Testbench: write reg: busy");
action
let x <- dm.av_read (dm_addr_abstractcs);
rg_abstractcs <= x;
endaction
endseq
$display ("Testbench: write reg => ", fshow (fn_abstractcs_cmderr (rg_abstractcs)));
endseq;
endfunction
// ================================================================
// System Bus access sequences (read/write RISC-V memory)
Reg #(Bool) rg_busy <- mkRegU;
Reg #(Bit #(32)) rg_j <- mkRegU;
Reg #(Bit #(32)) rg_addr <- mkRegU;
Reg #(Bit #(32)) rg_data <- mkRegU;
Stmt stmt_wait_for_sb_nonbusy = (
seq
rg_busy <= True;
while (rg_busy) seq
delay (1);
action
let x <- dm.av_read (dm_addr_sbcs);
let sberror = fn_sbcs_sberror (x);
rg_busy <= (sberror == DM_SBERROR_BUSY_STALE);
if ( (sberror != DM_SBERROR_NONE)
&& (sberror != DM_SBERROR_BUSY_STALE))
begin
$display ("Testbench: stmt_wait_for_sb_nonbusy: ", fshow (sberror));
$finish (1);
end
endaction
endseq
endseq);
// Do a single-read from memory
Stmt stmt_mem_read_1 = (
seq
dm.write (dm_addr_sbaddress0, 'h1_0000);
dm.write (dm_addr_sbcs, fn_mk_sbcs (True, // sbsingleread
DM_SBACCESS_32_BIT,
False, // sbautoincrement
False, // sbautoread
DM_SBERROR_UNDEF7_W1C)); // clear sberror
stmt_wait_for_sb_nonbusy;
action
let x <- dm.av_read (dm_addr_sbdata0);
$display ("stmt_mem_read_1: read-data = 0x%08h", x);
endaction
endseq);
// Do a multiple-read from memory
Stmt stmt_mem_read_4 = (
seq
dm.write (dm_addr_sbaddress0, 'h1_0000);
dm.write (dm_addr_sbcs, fn_mk_sbcs (True, // sbsingleread
DM_SBACCESS_32_BIT,
True, // sbautoincrement
True, // sbautoread
DM_SBERROR_UNDEF7_W1C)); // clear sberror
for (rg_j <= 0; rg_j < 3; rg_j <= rg_j + 1) seq
stmt_wait_for_sb_nonbusy;
action
let x <- dm.av_read (dm_addr_sbdata0);
$display ("stmt_mem_read_4: read-data [%0d] = 0x%08h", rg_j, x);
endaction
endseq
dm.write (dm_addr_sbcs, fn_mk_sbcs (False, // sbsingleread
DM_SBACCESS_32_BIT,
False, // sbautoincrement
False, // sbautoread
DM_SBERROR_UNDEF7_W1C)); // clear sberror
stmt_wait_for_sb_nonbusy;
action
let x <- dm.av_read (dm_addr_sbdata0);
$display ("stmt_mem_read_4: read-data [%0d] = 0x%08h", rg_j, x);
endaction
endseq);
// Do a single-write to memory
Stmt stmt_mem_write_1 = (
seq
dm.write (dm_addr_sbcs, fn_mk_sbcs (False, // sbsingleread
DM_SBACCESS_32_BIT,
False, // sbautoincrement
False, // sbautoread
DM_SBERROR_UNDEF7_W1C)); // clear sberror
stmt_wait_for_sb_nonbusy;
dm.write (dm_addr_sbaddress0, 'h1_0000);
dm.write (dm_addr_sbdata0, 'h_BEEF);
endseq);
// Do a multiple-write to memory
Stmt stmt_mem_write_4 = (
seq
dm.write (dm_addr_sbcs, fn_mk_sbcs (False, // sbsingleread
DM_SBACCESS_32_BIT,
True, // sbautoincrement
False, // sbautoread
DM_SBERROR_UNDEF7_W1C)); // clear sberror
stmt_wait_for_sb_nonbusy;
action
rg_addr <= 'h_2000;
rg_data <= 'h_DAFA_0000;
endaction
dm.write (dm_addr_sbaddress0, rg_addr);
for (rg_j <= 0; rg_j < 4; rg_j <= rg_j + 1) seq
stmt_wait_for_sb_nonbusy;
action
$display ("stmt_mem_write_4: [0x%08h] x = 0x%08h", rg_addr + rg_j, rg_data);
dm.write (dm_addr_sbdata0, rg_data);
rg_data <= rg_data + 1;
endaction
endseq
endseq);
// ================================================================
// Run-control test sequences (reset, run, halt, single-step)
let dmcontrol_dm_reset
= fn_mk_dmcontrol (False, // haltreq
False, // resumereq
False, // hartreset
False, // hasel
0, // hartsel,
False, // ndmreset
False); // dmactive; assert reset
let dmcontrol_ndmreset
= fn_mk_dmcontrol (False, // haltreq
False, // resumereq
False, // hartreset
False, // hasel,
0, // hartsel
True, // ndmreset
True); // dmactive
let dmcontrol_err_hasel
= fn_mk_dmcontrol (False, // haltreq
False, // resumereq
False, // hartreset
True, // hasel,
0, // hartsel
False, // ndmreset
True); // dmactive
let dmcontrol_err_hartsel
= fn_mk_dmcontrol (False, // haltreq
False, // resumereq
False, // hartreset
False, // hasel,
3, // hartsel
False, // ndmreset
True); // dmactive
let dmcontrol_hartreset
= fn_mk_dmcontrol (False, // haltreq
False, // resumereq
True, // hartreset
False, // hasel,
0, // hartsel
False, // ndmreset
True); // dmactive
let dmcontrol_err_haltreq_resumereq
= fn_mk_dmcontrol (True, // haltreq
True, // resumereq
False, // hartreset
False, // hasel,
0, // hartsel
False, // ndmreset
True); // dmactive
let dmcontrol_haltreq
= fn_mk_dmcontrol (True, // haltreq
False, // resumereq
False, // hartreset
False, // hasel,
0, // hartsel
False, // ndmreset
True); // dmactive
let dmcontrol_resumereq
= fn_mk_dmcontrol (False, // haltreq
True, // resumereq
False, // hartreset
False, // hasel,
0, // hartsel
False, // ndmreset
True); // dmactive
function Stmt fn_stmt_run_control (DM_Word dm_word);
return seq
dm.write (dm_addr_dmcontrol, dm_word);
delay (5);
// Check and show status
action
let x <- dm.av_read (dm_addr_dmstatus);
$display (" ", fshow_dmstatus (x));
endaction
endseq;
endfunction
// ----------------
// For single-step, set 'step' bit in DCSR, then run
let dcsr_step = {4'h4, // xdebugver
12'b0,
1'b0, // ebreakm
1'b0,
1'b0, // ebreaks
1'b0, // ebreaku
1'b0, // stepie
1'b0, // stepcount
1'b0, // steptime
3'b0, // cause
3'b0,
1'b1, // step
2'h3};
Stmt stmt_single_step = (
seq
// set 'step' in dcsr
fn_stmt_write_reg (fromInteger (dm_command_access_reg_regno_csr_0 + csr_addr_dcsr),
dcsr_step); // priv
fn_stmt_run_control (dmcontrol_resumereq);
endseq);
// ================================================================
// Top-level test. Comment/Uncomment desired parts.
Stmt test = seq
// Reset DM
$display ("----------------\n'Testbench: Reset DM'");
fn_stmt_run_control (dmcontrol_dm_reset);
/*
$display ("----------------\n'Testbench: Reset Platform'");
fn_stmt_run_control (dmcontrol_ndmreset);
$display ("----------------\n'Testbench: Err hasel'");
fn_stmt_run_control (dmcontrol_err_hasel);
$display ("----------------\n'Testbench: Err hartsel'");
fn_stmt_run_control (dmcontrol_err_hartsel);
$display ("----------------\n'Testbench: Reset hart'");
fn_stmt_run_control (dmcontrol_hartreset);
$display ("----------------\n'Testbench: Err haltreq and resumereq'");
fn_stmt_run_control (dmcontrol_err_haltreq_resumereq);
$display ("----------------\n'Testbench: Continue'");
fn_stmt_run_control (dmcontrol_resumereq);
$display ("----------------\n'Testbench: Halt'");
fn_stmt_run_control (dmcontrol_haltreq);
$display ("----------------\n'Testbench: Single step'");
stmt_single_step;
*/
$display ("----------------\n'Testbench: Read GPR'");
fn_stmt_read_reg (fromInteger (dm_command_access_reg_regno_gpr_0 + 5));
$display ("----------------\n'Testbench: Read CSR'");
fn_stmt_read_reg (fromInteger (dm_command_access_reg_regno_csr_0 + 3));
$display ("----------------\n'Testbench: Write GPR'");
fn_stmt_write_reg (fromInteger (dm_command_access_reg_regno_gpr_0 + 5), 'h_AAAA_0005);
$display ("----------------\n'Testbench: Write CSR'");
fn_stmt_write_reg (fromInteger (dm_command_access_reg_regno_csr_0 + 3), 'h_CCCC_0003);
/*
$display ("----------------\n'Testbench: Read 1'");
stmt_mem_read_1;
$display ("----------------\n'Testbench: Write 1'");
stmt_mem_write_1;
$display ("----------------\n'Testbench: Read 4'");
stmt_mem_read_4;
$display ("----------------\n'Testbench: Write 4'");
stmt_mem_write_4;
*/
await (False);
endseq;
mkAutoFSM (test);
endmodule
// ================================================================
// Over-simplified model of a hart (reset, run/halt, read/write GPR/CSR)
interface Hart_DM_IFC;
// Reset
interface Put #(Token) hart_reset_req;
// Run-control
interface Server #(Bool, Bool) hart_run_req_rsp;
// GPR access
interface TRX_Slave_IFC #(5,32,0) slave_for_gprs;
// CSR access
interface TRX_Slave_IFC #(12,32,0) slave_for_csrs;
endinterface
(* synthesize *)
module mkHart_Model #(parameter Bit #(10) hart_id) (Hart_DM_IFC);
Reg #(Bool) rg_hart_running <- mkReg (False);
FIFOF #(Token) f_hart_reset_reqs <- mkFIFOF;
FIFOF #(Bool) f_hart_run_reqs <- mkFIFOF;
FIFOF #(Bool) f_hart_run_rsps <- mkFIFOF;
// TRX interface to gprs
TRX_Buffer_IFC #(5,32,0) trx_buf_gprs <- mkTRX_Buffer;
// TRX interface to crs
TRX_Buffer_IFC #(12,32,0) trx_buf_csrs <- mkTRX_Buffer;
// ----------------------------------------------------------------
// BEHAVIOR
// ----------------
// Reset
rule rl_hart_reset;
let x = f_hart_reset_reqs.first;
f_hart_reset_reqs.deq;
$display ("Testbench.hart [%0d]: reset", hart_id);
endrule
// ----------------
// Run-control
rule rl_resume_hart (f_hart_run_reqs.first);
f_hart_run_reqs.deq;
rg_hart_running <= True;
if (rg_hart_running)
$display ("Testbench.hart [%0d].rl_resume_hart: already running", hart_id);
else
$display ("Testbench.hart [%0d].rl_resume_hart: resuming", hart_id);
f_hart_run_rsps.enq (True);
endrule
rule rl_halt_hart (! f_hart_run_reqs.first);
f_hart_run_reqs.deq;
rg_hart_running <= False;
if (rg_hart_running)
$display ("Testbench.hart [%0d].rl_halt_hart: halting", hart_id);
else
$display ("Testbench.hart [%0d].rl_halt_hart: already halted", hart_id);
f_hart_run_rsps.enq (False);
endrule
// ----------------
// GPR access
rule rl_read_gpr;
let rda <- pop_o (trx_buf_gprs.master.fo_rda);
Bit #(32) data = extend (rda.addr) + 'h1000;
let rdr = TRX_RdR {trans_id: rda.trans_id,
status: TRX_OKAY,
data: data};
trx_buf_gprs.master.fi_rdr.enq (rdr);
$display ("Testbench.hart [%0d]: Read GPR [%0h] => 0x%08h", hart_id, rda.addr, data);
endrule
rule rl_read_csr;
let rda <- pop_o (trx_buf_csrs.master.fo_rda);
Bit #(32) data = extend (rda.addr) + 'h2000;
let rdr = TRX_RdR {trans_id: rda.trans_id,
status: TRX_OKAY,
data: data};
trx_buf_csrs.master.fi_rdr.enq (rdr);
$display ("Testbench.hart [%0d]: Read CSR [%0h] => 0x%08h", hart_id, rda.addr, data);
endrule
rule rl_write_gpr;
let wra <- pop_o (trx_buf_gprs.master.fo_wra);
let wrd <- pop_o (trx_buf_gprs.master.fo_wrd);
let wrr = TRX_WrR {trans_id: wra.trans_id, status: TRX_OKAY};
trx_buf_gprs.master.fi_wrr.enq (wrr);
$display ("Testbench.hart [%0d]: Write GPR [%0h] <= 0x%08h", hart_id, wra.addr, wrd.data);
endrule
rule rl_write_csr;
let wra <- pop_o (trx_buf_csrs.master.fo_wra);
let wrd <- pop_o (trx_buf_csrs.master.fo_wrd);
let wrr = TRX_WrR {trans_id: wra.trans_id, status: TRX_OKAY};
trx_buf_csrs.master.fi_wrr.enq (wrr);
$display ("Testbench.hart [%0d]: Write CSR [%0h] <= 0x%08h", hart_id, wra.addr, wrd.data);
endrule
// ----------------------------------------------------------------
// INTERFACE
// Reset
interface Put hart_reset_req = toPut (f_hart_reset_reqs);
// Run-control
interface Server hart_run_req_rsp = toGPServer (f_hart_run_reqs, f_hart_run_rsps);
// GPR access
interface TRX_Slave_IFC slave_for_gprs = trx_buf_gprs.slave;
// CSR access
interface TRX_Slave_IFC slave_for_csrs = trx_buf_csrs.slave;
endmodule
// ================================================================
endpackage