forked from Github_Repos/cvw
Merge branch 'main' of github.com:davidharrishmc/riscv-wally
This commit is contained in:
commit
97661a023a
@ -5,7 +5,8 @@ WALLYDIR:= $(ROOT)/tests/wally-riscv-arch-test
|
|||||||
# IMPERASDIR := $(ROOT)/tests/imperas-riscv-tests
|
# IMPERASDIR := $(ROOT)/tests/imperas-riscv-tests
|
||||||
# ALLDIRS := $(ARCHDIR)/$(SUFFIX) $(WALLYDIR)/$(SUFFIX) $(IMPERASDIR)/$(SUFFIX)
|
# ALLDIRS := $(ARCHDIR)/$(SUFFIX) $(WALLYDIR)/$(SUFFIX) $(IMPERASDIR)/$(SUFFIX)
|
||||||
IMPERASDIR := $(ROOT)/tests/imperas-riscv-tests
|
IMPERASDIR := $(ROOT)/tests/imperas-riscv-tests
|
||||||
ALLDIRS := $(ARCHDIR)/$(SUFFIX) $(WALLYDIR)/$(SUFFIX)
|
#ALLDIRS := $(ARCHDIR)/$(SUFFIX) $(WALLYDIR)/$(SUFFIX)
|
||||||
|
ALLDIRS := $(ARCHDIR)/$(SUFFIX)
|
||||||
|
|
||||||
ELFFILES ?= $(shell find $(ALLDIRS) -type f -regex ".*\.elf")
|
ELFFILES ?= $(shell find $(ALLDIRS) -type f -regex ".*\.elf")
|
||||||
OBJDUMPFILES ?= $(shell find $(ALLDIRS) -type f -regex ".*\.elf.objdump")
|
OBJDUMPFILES ?= $(shell find $(ALLDIRS) -type f -regex ".*\.elf.objdump")
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
# wally-pipelined.do
|
|
||||||
#
|
|
||||||
# Modification by Oklahoma State University & Harvey Mudd College
|
|
||||||
# Use with Testbench
|
|
||||||
# James Stine, 2008; David Harris 2021
|
|
||||||
# Go Cowboys!!!!!!
|
|
||||||
#
|
|
||||||
# Takes 1:10 to run RV64IC tests using gui
|
|
||||||
|
|
||||||
# run with vsim -do "do wally-pipelined.do rv64ic riscvarchtest-64m"
|
|
||||||
|
|
||||||
# Use this wally-pipelined.do file to run this example.
|
|
||||||
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
|
|
||||||
# do wally-pipelined.do
|
|
||||||
# or, to run from a shell, type the following at the shell prompt:
|
|
||||||
# vsim -do wally-pipelined.do -c
|
|
||||||
# (omit the "-c" to see the GUI while running from the shell)
|
|
||||||
|
|
||||||
onbreak {resume}
|
|
||||||
|
|
||||||
# create library
|
|
||||||
if [file exists work] {
|
|
||||||
vdel -all
|
|
||||||
}
|
|
||||||
vlib work
|
|
||||||
|
|
||||||
# compile source files
|
|
||||||
# suppress spurious warnngs about
|
|
||||||
# "Extra checking for conflicts with always_comb done at vopt time"
|
|
||||||
# because vsim will run vopt
|
|
||||||
|
|
||||||
# start and run simulation
|
|
||||||
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
|
|
||||||
# *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings.
|
|
||||||
vlog +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench_imperas.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 -suppress 7063
|
|
||||||
vopt +acc work.testbench -G DEBUG=1 -o workopt
|
|
||||||
vsim workopt +nowarn3829 -fatal 7
|
|
||||||
view wave
|
|
||||||
#-- display input and output signals as hexidecimal values
|
|
||||||
add log -recursive /*
|
|
||||||
do wave.do
|
|
||||||
|
|
||||||
run -all
|
|
||||||
noview ../testbench/testbench_imperas.sv
|
|
||||||
view wave
|
|
@ -98,7 +98,6 @@ module hptw (
|
|||||||
logic [2:0] HPTWSize; // 32 or 64 bit access
|
logic [2:0] HPTWSize; // 32 or 64 bit access
|
||||||
(* mark_debug = "true" *) statetype WalkerState, NextWalkerState, InitialWalkerState;
|
(* mark_debug = "true" *) statetype WalkerState, NextWalkerState, InitialWalkerState;
|
||||||
|
|
||||||
|
|
||||||
// map hptw access faults onto either the original LSU load/store fault or instruction access fault
|
// map hptw access faults onto either the original LSU load/store fault or instruction access fault
|
||||||
assign LoadAccessFaultM = WalkerState == IDLE ? LSULoadAccessFaultM : (LSULoadAccessFaultM | LSUStoreAmoAccessFaultM) & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
assign LoadAccessFaultM = WalkerState == IDLE ? LSULoadAccessFaultM : (LSULoadAccessFaultM | LSUStoreAmoAccessFaultM) & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
||||||
assign StoreAmoAccessFaultM = WalkerState == IDLE ? LSUStoreAmoAccessFaultM : (LSULoadAccessFaultM | LSUStoreAmoAccessFaultM) & DTLBWalk & MemRWM[0];
|
assign StoreAmoAccessFaultM = WalkerState == IDLE ? LSUStoreAmoAccessFaultM : (LSULoadAccessFaultM | LSUStoreAmoAccessFaultM) & DTLBWalk & MemRWM[0];
|
||||||
@ -189,13 +188,13 @@ module hptw (
|
|||||||
// FSM to track PageType based on the levels of the page table traversed
|
// FSM to track PageType based on the levels of the page table traversed
|
||||||
flopr #(2) PageTypeReg(clk, reset, NextPageType, PageType);
|
flopr #(2) PageTypeReg(clk, reset, NextPageType, PageType);
|
||||||
always_comb
|
always_comb
|
||||||
case (WalkerState)
|
case (WalkerState)
|
||||||
L3_RD: NextPageType = 2'b11; // terapage
|
L3_RD: NextPageType = 2'b11; // terapage
|
||||||
L2_RD: NextPageType = 2'b10; // gigapage
|
L2_RD: NextPageType = 2'b10; // gigapage
|
||||||
L1_RD: NextPageType = 2'b01; // megapage
|
L1_RD: NextPageType = 2'b01; // megapage
|
||||||
L0_RD: NextPageType = 2'b00; // kilopage
|
L0_RD: NextPageType = 2'b00; // kilopage
|
||||||
default: NextPageType = PageType;
|
default: NextPageType = PageType;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// HPTWAdr muxing
|
// HPTWAdr muxing
|
||||||
if (`XLEN==32) begin // RV32
|
if (`XLEN==32) begin // RV32
|
||||||
|
@ -107,16 +107,10 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) (
|
|||||||
.Cacheable, .Idempotent, .SelTIM,
|
.Cacheable, .Idempotent, .SelTIM,
|
||||||
.PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM);
|
.PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM);
|
||||||
|
|
||||||
if (`PMP_ENTRIES > 0) // instantiate PMP
|
pmpchecker pmpchecker(.PhysicalAddress, .PrivilegeModeW,
|
||||||
pmpchecker pmpchecker(.PhysicalAddress, .PrivilegeModeW,
|
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
||||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
.ExecuteAccessF, .WriteAccessM, .ReadAccessM,
|
||||||
.ExecuteAccessF, .WriteAccessM, .ReadAccessM,
|
.PMPInstrAccessFaultF, .PMPLoadAccessFaultM, .PMPStoreAmoAccessFaultM);
|
||||||
.PMPInstrAccessFaultF, .PMPLoadAccessFaultM, .PMPStoreAmoAccessFaultM);
|
|
||||||
else begin
|
|
||||||
assign PMPInstrAccessFaultF = 0;
|
|
||||||
assign PMPLoadAccessFaultM = 0;
|
|
||||||
assign PMPStoreAmoAccessFaultM = 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
// Access faults
|
// Access faults
|
||||||
// If TLB miss and translating we want to not have faults from the PMA and PMP checkers.
|
// If TLB miss and translating we want to not have faults from the PMA and PMP checkers.
|
||||||
|
@ -49,28 +49,34 @@ module pmpchecker (
|
|||||||
output logic PMPStoreAmoAccessFaultM
|
output logic PMPStoreAmoAccessFaultM
|
||||||
);
|
);
|
||||||
|
|
||||||
// Bit i is high when the address falls in PMP region i
|
if (`PMP_ENTRIES > 0) begin
|
||||||
logic EnforcePMP;
|
// Bit i is high when the address falls in PMP region i
|
||||||
logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
|
logic EnforcePMP;
|
||||||
logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
|
logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
|
||||||
logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null
|
logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
|
||||||
logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
|
logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null
|
||||||
logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
|
logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
|
||||||
|
logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
|
||||||
|
|
||||||
pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0](
|
pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0](
|
||||||
.PhysicalAddress,
|
.PhysicalAddress,
|
||||||
.PMPCfg(PMPCFG_ARRAY_REGW),
|
.PMPCfg(PMPCFG_ARRAY_REGW),
|
||||||
.PMPAdr(PMPADDR_ARRAY_REGW),
|
.PMPAdr(PMPADDR_ARRAY_REGW),
|
||||||
.PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}),
|
.PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}),
|
||||||
.PAgePMPAdrOut(PAgePMPAdr),
|
.PAgePMPAdrOut(PAgePMPAdr),
|
||||||
.Match, .Active, .L, .X, .W, .R);
|
.Match, .Active, .L, .X, .W, .R);
|
||||||
|
|
||||||
priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches.
|
priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches.
|
||||||
|
|
||||||
// Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region
|
// Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region
|
||||||
assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |(L & FirstMatch) : |Active;
|
assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |(L & FirstMatch) : |Active;
|
||||||
|
|
||||||
assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|(X & FirstMatch) ;
|
assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|(X & FirstMatch) ;
|
||||||
assign PMPStoreAmoAccessFaultM = EnforcePMP & WriteAccessM & ~|(W & FirstMatch) ;
|
assign PMPStoreAmoAccessFaultM = EnforcePMP & WriteAccessM & ~|(W & FirstMatch) ;
|
||||||
assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|(R & FirstMatch) ;
|
assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|(R & FirstMatch) ;
|
||||||
|
end else begin
|
||||||
|
assign PMPInstrAccessFaultF = 0;
|
||||||
|
assign PMPStoreAmoAccessFaultM = 0;
|
||||||
|
assign PMPLoadAccessFaultM = 0;
|
||||||
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -63,12 +63,8 @@ module tlbcontrol #(parameter ITLB = 0) (
|
|||||||
// Determine whether TLB is being used
|
// Determine whether TLB is being used
|
||||||
assign TLBAccess = ReadAccess | WriteAccess;
|
assign TLBAccess = ReadAccess | WriteAccess;
|
||||||
|
|
||||||
if (`XLEN==64) // Check whether upper bits of 64-bit virtual addressses are all equal
|
// Check that upper bits are legal (all 0s or all 1s)
|
||||||
vm64check vm64check(.SATP_MODE, .VAdr, .SV39Mode, .UpperBitsUnequalPageFault);
|
vm64check vm64check(.SATP_MODE, .VAdr, .SV39Mode, .UpperBitsUnequalPageFault);
|
||||||
else begin
|
|
||||||
assign SV39Mode = 0;
|
|
||||||
assign UpperBitsUnequalPageFault = 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
// unswizzle useful PTE bits
|
// unswizzle useful PTE bits
|
||||||
assign {PTE_D, PTE_A} = PTEAccessBits[7:6];
|
assign {PTE_D, PTE_A} = PTEAccessBits[7:6];
|
||||||
|
@ -35,12 +35,16 @@ module vm64check (
|
|||||||
output logic UpperBitsUnequalPageFault
|
output logic UpperBitsUnequalPageFault
|
||||||
);
|
);
|
||||||
|
|
||||||
logic eq_63_47, eq_46_38;
|
if (`XLEN == 64) begin
|
||||||
|
assign SV39Mode = (SATP_MODE == `SV39);
|
||||||
|
|
||||||
assign SV39Mode = (SATP_MODE == `SV39);
|
// page fault if upper bits aren't all the same
|
||||||
|
logic eq_63_47, eq_46_38;
|
||||||
// page fault if upper bits aren't all the same
|
assign eq_46_38 = &(VAdr[46:38]) | ~|(VAdr[46:38]);
|
||||||
assign eq_46_38 = &(VAdr[46:38]) | ~|(VAdr[46:38]);
|
assign eq_63_47 = &(VAdr[63:47]) | ~|(VAdr[63:47]);
|
||||||
assign eq_63_47 = &(VAdr[63:47]) | ~|(VAdr[63:47]);
|
assign UpperBitsUnequalPageFault = SV39Mode ? ~(eq_63_47 & eq_46_38) : ~eq_63_47;
|
||||||
assign UpperBitsUnequalPageFault = SV39Mode ? ~(eq_63_47 & eq_46_38) : ~eq_63_47;
|
end else begin
|
||||||
|
assign SV39Mode = 0;
|
||||||
|
assign UpperBitsUnequalPageFault = 0;
|
||||||
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1,251 +0,0 @@
|
|||||||
`include "wally-config.vh"
|
|
||||||
|
|
||||||
`define NUM_REGS 32
|
|
||||||
`define NUM_CSRS 4096
|
|
||||||
|
|
||||||
`define PRINT_PC_INSTR 1
|
|
||||||
`define PRINT_MOST 1
|
|
||||||
`define PRINT_ALL 0
|
|
||||||
|
|
||||||
module rvviTrace #(
|
|
||||||
parameter int ILEN = `XLEN, // Instruction length in bits
|
|
||||||
parameter int XLEN = `XLEN, // GPR length in bits
|
|
||||||
parameter int FLEN = `FLEN, // FPR length in bits
|
|
||||||
parameter int VLEN = 0, // Vector register size in bits
|
|
||||||
parameter int NHART = 1, // Number of harts reported
|
|
||||||
parameter int RETIRE = 1) // Number of instructions that can retire during valid event
|
|
||||||
();
|
|
||||||
|
|
||||||
localparam NUMREGS = `E_SUPPORTED ? 16 : 32;
|
|
||||||
|
|
||||||
// wally specific signals
|
|
||||||
logic reset;
|
|
||||||
|
|
||||||
logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM, PCW;
|
|
||||||
logic [`XLEN-1:0] InstrRawD, InstrRawE, InstrRawM, InstrRawW;
|
|
||||||
logic InstrValidM, InstrValidW;
|
|
||||||
logic StallE, StallM, StallW;
|
|
||||||
logic FlushD, FlushE, FlushM, FlushW;
|
|
||||||
logic TrapM, TrapW;
|
|
||||||
logic IntrF, IntrD, IntrE, IntrM, IntrW;
|
|
||||||
logic HaltM, HaltW;
|
|
||||||
logic [1:0] PrivilegeModeW;
|
|
||||||
logic [`XLEN-1:0] rf[NUMREGS];
|
|
||||||
logic [NUMREGS-1:0] rf_wb;
|
|
||||||
logic [4:0] rf_a3;
|
|
||||||
logic rf_we3;
|
|
||||||
logic [`XLEN-1:0] frf[32];
|
|
||||||
logic [`NUM_REGS-1:0] frf_wb;
|
|
||||||
logic [4:0] frf_a4;
|
|
||||||
logic frf_we4;
|
|
||||||
logic [`XLEN-1:0] CSRArray [logic[11:0]];
|
|
||||||
logic CSRWriteM, CSRWriteW;
|
|
||||||
logic [11:0] CSRAdrM, CSRAdrW;
|
|
||||||
|
|
||||||
// tracer signals
|
|
||||||
logic clk;
|
|
||||||
logic valid;
|
|
||||||
logic [63:0] order [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic [ILEN-1:0] insn [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic intr [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic [(XLEN-1):0] pc_rdata [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic [(XLEN-1):0] pc_wdata [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic trap [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic halt [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic [1:0] mode [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic [1:0] ixl [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic [`NUM_REGS-1:0][(XLEN-1):0] x_wdata [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic [`NUM_REGS-1:0] x_wb [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic [`NUM_REGS-1:0][(XLEN-1):0] f_wdata [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic [`NUM_REGS-1:0] f_wb [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic [4095:0][(XLEN-1):0] csr [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic [4095:0] csr_wb [(NHART-1):0][(RETIRE-1):0];
|
|
||||||
logic lrsc_cancel[(NHART-1):0][(RETIRE-1):0];
|
|
||||||
|
|
||||||
assign clk = testbench.dut.clk;
|
|
||||||
// assign InstrValidF = testbench.dut.core.ieu.InstrValidF; // not needed yet
|
|
||||||
assign InstrValidD = testbench.dut.core.ieu.c.InstrValidD;
|
|
||||||
assign InstrValidE = testbench.dut.core.ieu.c.InstrValidE;
|
|
||||||
assign InstrValidM = testbench.dut.core.ieu.InstrValidM;
|
|
||||||
assign InstrRawD = testbench.dut.core.ifu.InstrRawD;
|
|
||||||
assign PCNextF = testbench.dut.core.ifu.PCNextF;
|
|
||||||
assign PCF = testbench.dut.core.ifu.PCF;
|
|
||||||
assign PCD = testbench.dut.core.ifu.PCD;
|
|
||||||
assign PCE = testbench.dut.core.ifu.PCE;
|
|
||||||
assign PCM = testbench.dut.core.ifu.PCM;
|
|
||||||
assign reset = testbench.reset;
|
|
||||||
assign StallE = testbench.dut.core.StallE;
|
|
||||||
assign StallM = testbench.dut.core.StallM;
|
|
||||||
assign StallW = testbench.dut.core.StallW;
|
|
||||||
assign FlushD = testbench.dut.core.FlushD;
|
|
||||||
assign FlushE = testbench.dut.core.FlushE;
|
|
||||||
assign FlushM = testbench.dut.core.FlushM;
|
|
||||||
assign FlushW = testbench.dut.core.FlushW;
|
|
||||||
assign TrapM = testbench.dut.core.TrapM;
|
|
||||||
assign HaltM = testbench.DCacheFlushStart;
|
|
||||||
assign PrivilegeModeW = testbench.dut.core.priv.priv.privmode.PrivilegeModeW;
|
|
||||||
assign STATUS_SXL = testbench.dut.core.priv.priv.csr.csrsr.STATUS_SXL;
|
|
||||||
assign STATUS_UXL = testbench.dut.core.priv.priv.csr.csrsr.STATUS_UXL;
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
// machine CSRs
|
|
||||||
// *** missing PMP and performance counters.
|
|
||||||
CSRArray[12'h300] = testbench.dut.core.priv.priv.csr.csrm.MSTATUS_REGW;
|
|
||||||
CSRArray[12'h310] = testbench.dut.core.priv.priv.csr.csrm.MSTATUSH_REGW;
|
|
||||||
CSRArray[12'h305] = testbench.dut.core.priv.priv.csr.csrm.MTVEC_REGW;
|
|
||||||
CSRArray[12'h341] = testbench.dut.core.priv.priv.csr.csrm.MEPC_REGW;
|
|
||||||
CSRArray[12'h306] = testbench.dut.core.priv.priv.csr.csrm.MCOUNTEREN_REGW;
|
|
||||||
CSRArray[12'h320] = testbench.dut.core.priv.priv.csr.csrm.MCOUNTINHIBIT_REGW;
|
|
||||||
CSRArray[12'h302] = testbench.dut.core.priv.priv.csr.csrm.MEDELEG_REGW;
|
|
||||||
CSRArray[12'h303] = testbench.dut.core.priv.priv.csr.csrm.MIDELEG_REGW;
|
|
||||||
CSRArray[12'h344] = testbench.dut.core.priv.priv.csr.csrm.MIP_REGW;
|
|
||||||
CSRArray[12'h304] = testbench.dut.core.priv.priv.csr.csrm.MIE_REGW;
|
|
||||||
CSRArray[12'h301] = testbench.dut.core.priv.priv.csr.csrm.MISA_REGW;
|
|
||||||
CSRArray[12'hF14] = testbench.dut.core.priv.priv.csr.csrm.MHARTID_REGW;
|
|
||||||
CSRArray[12'h340] = testbench.dut.core.priv.priv.csr.csrm.MSCRATCH_REGW;
|
|
||||||
CSRArray[12'h342] = testbench.dut.core.priv.priv.csr.csrm.MCAUSE_REGW;
|
|
||||||
CSRArray[12'h343] = testbench.dut.core.priv.priv.csr.csrm.MTVAL_REGW;
|
|
||||||
CSRArray[12'hF11] = 0;
|
|
||||||
CSRArray[12'hF12] = 0;
|
|
||||||
CSRArray[12'hF13] = `XLEN'h100;
|
|
||||||
CSRArray[12'hF15] = 0;
|
|
||||||
CSRArray[12'h34A] = 0;
|
|
||||||
// MCYCLE and MINSTRET
|
|
||||||
CSRArray[12'hB00] = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[0];
|
|
||||||
CSRArray[12'hB02] = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2];
|
|
||||||
// supervisor CSRs
|
|
||||||
CSRArray[12'h100] = testbench.dut.core.priv.priv.csr.csrs.SSTATUS_REGW;
|
|
||||||
CSRArray[12'h104] = testbench.dut.core.priv.priv.csr.csrm.MIE_REGW & 12'h222;
|
|
||||||
CSRArray[12'h105] = testbench.dut.core.priv.priv.csr.csrs.STVEC_REGW;
|
|
||||||
CSRArray[12'h141] = testbench.dut.core.priv.priv.csr.csrs.SEPC_REGW;
|
|
||||||
CSRArray[12'h106] = testbench.dut.core.priv.priv.csr.csrs.SCOUNTEREN_REGW;
|
|
||||||
CSRArray[12'h180] = testbench.dut.core.priv.priv.csr.csrs.SATP_REGW;
|
|
||||||
CSRArray[12'h140] = testbench.dut.core.priv.priv.csr.csrs.csrs.SSCRATCH_REGW;
|
|
||||||
CSRArray[12'h143] = testbench.dut.core.priv.priv.csr.csrs.csrs.STVAL_REGW;
|
|
||||||
CSRArray[12'h142] = testbench.dut.core.priv.priv.csr.csrs.csrs.SCAUSE_REGW;
|
|
||||||
CSRArray[12'h144] = testbench.dut.core.priv.priv.csr.csrm.MIP_REGW & & 12'h222 & testbench.dut.core.priv.priv.csr.csrm.MIDELEG_REGW;
|
|
||||||
// user CSRs
|
|
||||||
CSRArray[12'h001] = testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW;
|
|
||||||
CSRArray[12'h002] = testbench.dut.core.priv.priv.csr.csru.FRM_REGW;
|
|
||||||
CSRArray[12'h003] = {testbench.dut.core.priv.priv.csr.csru.FRM_REGW, testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW};
|
|
||||||
end
|
|
||||||
|
|
||||||
genvar index;
|
|
||||||
assign rf[0] = '0;
|
|
||||||
for(index = 1; index < NUMREGS; index += 1)
|
|
||||||
assign rf[index] = testbench.dut.core.ieu.dp.regf.rf[index];
|
|
||||||
|
|
||||||
assign rf_a3 = testbench.dut.core.ieu.dp.regf.a3;
|
|
||||||
assign rf_we3 = testbench.dut.core.ieu.dp.regf.we3;
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
rf_wb <= '0;
|
|
||||||
if(rf_we3)
|
|
||||||
rf_wb[rf_a3] <= 1'b1;
|
|
||||||
end
|
|
||||||
|
|
||||||
for(index = 0; index < NUMREGS; index += 1)
|
|
||||||
assign frf[index] = testbench.dut.core.fpu.fpu.fregfile.rf[index];
|
|
||||||
|
|
||||||
assign frf_a4 = testbench.dut.core.fpu.fpu.fregfile.a4;
|
|
||||||
assign frf_we4 = testbench.dut.core.fpu.fpu.fregfile.we4;
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
frf_wb <= '0;
|
|
||||||
if(frf_we4)
|
|
||||||
frf_wb[frf_a4] <= 1'b1;
|
|
||||||
end
|
|
||||||
|
|
||||||
assign CSRAdrM = testbench.dut.core.priv.priv.csr.CSRAdrM;
|
|
||||||
assign CSRWriteM = testbench.dut.core.priv.priv.csr.CSRWriteM;
|
|
||||||
|
|
||||||
// pipeline to writeback stage
|
|
||||||
flopenrc #(`XLEN) InstrRawEReg (clk, reset, FlushE, ~StallE, InstrRawD, InstrRawE);
|
|
||||||
flopenrc #(`XLEN) InstrRawMReg (clk, reset, FlushM, ~StallM, InstrRawE, InstrRawM);
|
|
||||||
flopenrc #(`XLEN) InstrRawWReg (clk, reset, FlushW, ~StallW, InstrRawM, InstrRawW);
|
|
||||||
flopenrc #(`XLEN) PCWReg (clk, reset, FlushW, ~StallW, PCM, PCW);
|
|
||||||
flopenrc #(1) InstrValidMReg (clk, reset, FlushW, ~StallW, InstrValidM, InstrValidW);
|
|
||||||
flopenrc #(1) TrapWReg (clk, reset, 1'b0, ~StallW, TrapM, TrapW);
|
|
||||||
flopenrc #(1) HaltWReg (clk, reset, 1'b0, ~StallW, HaltM, HaltW);
|
|
||||||
|
|
||||||
flopenrc #(1) IntrFReg (clk, reset, 1'b0, ~StallF, TrapM, IntrF);
|
|
||||||
flopenrc #(1) IntrDReg (clk, reset, FlushD, ~StallD, IntrF, IntrD);
|
|
||||||
flopenrc #(1) IntrEReg (clk, reset, FlushE, ~StallE, IntrD, IntrE);
|
|
||||||
flopenrc #(1) IntrMReg (clk, reset, FlushM, ~StallM, IntrE, IntrM);
|
|
||||||
flopenrc #(1) IntrWReg (clk, reset, FlushW, ~StallW, IntrM, IntrW);
|
|
||||||
|
|
||||||
flopenrc #(12) CSRAdrWReg (clk, reset, FlushW, ~StallW, CSRAdrM, CSRAdrW);
|
|
||||||
flopenrc #(1) CSRWriteWReg (clk, reset, FlushW, ~StallW, CSRWriteM, CSRWriteW);
|
|
||||||
|
|
||||||
// Initially connecting the writeback stage signals, but may need to use M stage
|
|
||||||
// and gate on ~FlushW.
|
|
||||||
|
|
||||||
assign valid = InstrValidW & ~StallW & ~FlushW;
|
|
||||||
assign order[0][0] = CSRArray[12'hB02];
|
|
||||||
assign insn[0][0] = InstrRawW;
|
|
||||||
assign pc_rdata[0][0] = PCW;
|
|
||||||
assign trap[0][0] = TrapW;
|
|
||||||
assign halt[0][0] = HaltW;
|
|
||||||
assign intr[0][0] = IntrW;
|
|
||||||
assign mode[0][0] = PrivilegeModeW;
|
|
||||||
assign ixl[0][0] = PrivilegeModeW == 2'b11 ? 2'b10 :
|
|
||||||
PrivilegeModeW == 2'b01 ? STATUS_SXL : STATUS_UXL;
|
|
||||||
assign pc_wdata[0][0] = ~FlushW ? PCM :
|
|
||||||
~FlushM ? PCE :
|
|
||||||
~FlushE ? PCD :
|
|
||||||
~FlushD ? PCF : PCNextF;
|
|
||||||
|
|
||||||
for(index = 0; index < `NUM_REGS; index += 1) begin
|
|
||||||
assign x_wdata[0][0][index] = rf[index];
|
|
||||||
assign x_wb[0][0][index] = rf_wb[index];
|
|
||||||
assign f_wdata[0][0][index] = frf[index];
|
|
||||||
assign f_wb[0][0][index] = frf_wb[index];
|
|
||||||
end
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
csr_wb[0][0] <= '0;
|
|
||||||
if(CSRWriteW)
|
|
||||||
csr_wb[0][0][CSRAdrW] <= 1'b1;
|
|
||||||
end
|
|
||||||
|
|
||||||
integer index3;
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
for(index3 = 0; index3 < `NUM_CSRS; index3 += 1) begin
|
|
||||||
if(CSRArray.exists(index3))
|
|
||||||
csr[0][0][index3] = CSRArray[index3];
|
|
||||||
else
|
|
||||||
csr[0][0][index3] = '0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// *** implementation only cancel? so sc does not clear?
|
|
||||||
assign lrsc_cancel[0][0] = '0;
|
|
||||||
|
|
||||||
integer index2;
|
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if(valid) begin
|
|
||||||
if(`PRINT_PC_INSTR & !(`PRINT_ALL | `PRINT_MOST))
|
|
||||||
$display("order = %08d, PC = %08x, insn = %08x", order[0][0], pc_rdata[0][0], insn[0][0]);
|
|
||||||
else if(`PRINT_MOST & !`PRINT_ALL)
|
|
||||||
$display("order = %08d, PC = %010x, insn = %08x, trap = %1d, halt = %1d, intr = %1d, mode = %1x, ixl = %1x, pc_wdata = %010x, x%02d = %016x, f%02d = %016x, csr%03x = %016x",
|
|
||||||
order[0][0], pc_rdata[0][0], insn[0][0], trap[0][0], halt[0][0], intr[0][0], mode[0][0], ixl[0][0], pc_wdata[0][0], rf_a3, x_wdata[0][0][rf_a3], frf_a4, f_wdata[0][0][frf_a4], CSRAdrW, csr[0][0][CSRAdrW]);
|
|
||||||
else if(`PRINT_ALL) begin
|
|
||||||
$display("order = %08d, PC = %08x, insn = %08x, trap = %1d, halt = %1d, intr = %1d, mode = %1x, ixl = %1x, pc_wdata = %08x",
|
|
||||||
order[0][0], pc_rdata[0][0], insn[0][0], trap[0][0], halt[0][0], intr[0][0], mode[0][0], ixl[0][0], pc_wdata[0][0]);
|
|
||||||
for(index2 = 0; index2 < `NUM_REGS; index2 += 1) begin
|
|
||||||
$display("x%02d = %08x", index2, x_wdata[0][0][index2]);
|
|
||||||
end
|
|
||||||
for(index2 = 0; index2 < `NUM_REGS; index2 += 1) begin
|
|
||||||
$display("f%02d = %08x", index2, f_wdata[0][0][index2]);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if(HaltW) $stop();
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
|
||||||
|
|
@ -155,7 +155,7 @@ module testbench;
|
|||||||
`define MCOUNTEREN `CSR_BASE.csrm.mcounteren.MCOUNTERENreg.q
|
`define MCOUNTEREN `CSR_BASE.csrm.mcounteren.MCOUNTERENreg.q
|
||||||
`define SCOUNTEREN `CSR_BASE.csrs.csrs.SCOUNTERENreg.q
|
`define SCOUNTEREN `CSR_BASE.csrs.csrs.SCOUNTERENreg.q
|
||||||
`define MSCRATCH `CSR_BASE.csrm.MSCRATCHreg.q
|
`define MSCRATCH `CSR_BASE.csrm.MSCRATCHreg.q
|
||||||
`define SSCRATCH `CSR_BASE.csrs.csrs.csrs.SSCRATCHreg.q
|
`define SSCRATCH `CSR_BASE.csrs.csrs.SSCRATCHreg.q
|
||||||
`define MTVEC `CSR_BASE.csrm.MTVECreg.q
|
`define MTVEC `CSR_BASE.csrm.MTVECreg.q
|
||||||
`define STVEC `CSR_BASE.csrs.csrs.STVECreg.q
|
`define STVEC `CSR_BASE.csrs.csrs.STVECreg.q
|
||||||
`define SATP `CSR_BASE.csrs.csrs.genblk1.SATPreg.q
|
`define SATP `CSR_BASE.csrs.csrs.genblk1.SATPreg.q
|
||||||
|
@ -692,55 +692,3 @@ task automatic updateProgramAddrLabelArray;
|
|||||||
$fclose(ProgramAddrMapFP);
|
$fclose(ProgramAddrMapFP);
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
`define NUM_REGS 32
|
|
||||||
`define NUM_CSRS 4096
|
|
||||||
|
|
||||||
module rvviTrace();
|
|
||||||
|
|
||||||
// wally specific signals
|
|
||||||
logic reset;
|
|
||||||
|
|
||||||
logic [`XLEN-1:0] PCM, PCW;
|
|
||||||
logic [`XLEN-1:0] InstrRawD, InstrRawE, InstrRawM, InstrRawW;
|
|
||||||
logic InstrValidM, InstrValidW;
|
|
||||||
logic StallE, StallM, StallW;
|
|
||||||
logic FlushE, FlushM, FlushW;
|
|
||||||
|
|
||||||
// tracer signals
|
|
||||||
logic clk;
|
|
||||||
logic valid;
|
|
||||||
logic [`XLEN-1:0] insn;
|
|
||||||
logic [`XLEN-1:0 ] pc_rdata;
|
|
||||||
|
|
||||||
assign clk = testbench.dut.clk;
|
|
||||||
assign InstrValidM = testbench.dut.core.ieu.InstrValidM;
|
|
||||||
assign InstrRawD = testbench.dut.core.ifu.InstrRawD;
|
|
||||||
assign PCM = testbench.dut.core.ifu.PCM;
|
|
||||||
assign reset = testbench.reset;
|
|
||||||
assign StallE = testbench.dut.core.StallE;
|
|
||||||
assign StallM = testbench.dut.core.StallM;
|
|
||||||
assign StallW = testbench.dut.core.StallW;
|
|
||||||
assign FlushE = testbench.dut.core.FlushE;
|
|
||||||
assign FlushM = testbench.dut.core.FlushM;
|
|
||||||
assign FlushW = testbench.dut.core.FlushW;
|
|
||||||
|
|
||||||
// pipeline to writeback stage
|
|
||||||
flopenrc #(`XLEN) InstrRawEReg (clk, reset, FlushE, ~StallE, InstrRawD, InstrRawE);
|
|
||||||
flopenrc #(`XLEN) InstrRawMReg (clk, reset, FlushM, ~StallM, InstrRawE, InstrRawM);
|
|
||||||
flopenrc #(`XLEN) InstrRawWReg (clk, reset, FlushW, ~StallW, InstrRawM, InstrRawW);
|
|
||||||
flopenrc #(`XLEN) PCWReg (clk, reset, FlushW, ~StallW, PCM, PCW);
|
|
||||||
flopenrc #(1) InstrValidMReg (clk, reset, FlushW, ~StallW, InstrValidM, InstrValidW);
|
|
||||||
|
|
||||||
assign valid = InstrValidW;
|
|
||||||
assign insn = InstrRawW;
|
|
||||||
assign pc_rdata = PCW;
|
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if(valid) begin
|
|
||||||
$display("PC = %x, insn = %x", pc_rdata, insn);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user