Initial load of files
This commit is contained in:
94
src_Core/Debug_Module/Test/Makefile
Normal file
94
src_Core/Debug_Module/Test/Makefile
Normal 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
|
||||
597
src_Core/Debug_Module/Test/Testbench.bsv
Normal file
597
src_Core/Debug_Module/Test/Testbench.bsv
Normal 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
|
||||
Reference in New Issue
Block a user