Added tim only test to regression-wally. Minor cleanup to ifu.

This commit is contained in:
Ross Thompson 2022-01-14 11:13:06 -06:00
parent e0e30c1e9e
commit 3bec276862
8 changed files with 2400 additions and 107 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,133 @@
//////////////////////////////////////////
// wally-config.vh
//
// Written: David_Harris@hmc.edu 4 January 2021
// Modified:
//
// Purpose: Specify which features are configured
// Macros to determine which modes are supported based on MISA
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
// include shared configuration
`include "wally-shared.vh"
`define FPGA 0
`define QEMU 0
`define BUILDROOT 0
`define BUSYBEAR 0
`define DESIGN_COMPILER 0
// RV32 or RV64: XLEN = 32 or 64
`define XLEN 32
// IEEE 754 compliance
`define IEEE754 0
`define MISA (32'h00000104)
`define ZICSR_SUPPORTED 1
`define ZIFENCEI_SUPPORTED 0
`define COUNTERS 32
`define ZICOUNTERS_SUPPORTED 0
// Microarchitectural Features
`define UARCH_PIPELINED 1
`define UARCH_SUPERSCALR 0
`define UARCH_SINGLECYCLE 0
`define MEM_DTIM 1
`define MEM_DCACHE 0
`define MEM_IROM 1
`define MEM_ICACHE 0
`define MEM_VIRTMEM 0
`define VECTORED_INTERRUPTS_SUPPORTED 1
// TLB configuration. Entries should be a power of 2
`define ITLB_ENTRIES 0
`define DTLB_ENTRIES 0
// Cache configuration. Sizes should be a power of two
// typical configuration 4 ways, 4096 bytes per way, 256 bit or more lines
`define DCACHE_NUMWAYS 4
`define DCACHE_WAYSIZEINBYTES 4096
`define DCACHE_LINELENINBITS 256
`define DCACHE_REPLBITS 3
`define ICACHE_NUMWAYS 4
`define ICACHE_WAYSIZEINBYTES 4096
`define ICACHE_LINELENINBITS 256
// Integer Divider Configuration
// DIV_BITSPERCYCLE must be 1, 2, or 4
`define DIV_BITSPERCYCLE 4
// Legal number of PMP entries are 0, 16, or 64
`define PMP_ENTRIES 0
// Address space
`define RESET_VECTOR 32'h80000000
// Peripheral Addresses
// Peripheral memory space extends from BASE to BASE+RANGE
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
`define BOOTROM_SUPPORTED 1'b1
`define BOOTROM_BASE 34'h00001000
`define BOOTROM_RANGE 34'h00000FFF
`define RAM_SUPPORTED 1'b1
`define RAM_BASE 34'h80000000
`define RAM_RANGE 34'h07FFFFFF
`define EXT_MEM_SUPPORTED 1'b0
`define EXT_MEM_BASE 34'h80000000
`define EXT_MEM_RANGE 34'h07FFFFFF
`define CLINT_SUPPORTED 1'b1
`define CLINT_BASE 34'h02000000
`define CLINT_RANGE 34'h0000FFFF
`define GPIO_SUPPORTED 1'b1
`define GPIO_BASE 34'h10012000
`define GPIO_RANGE 34'h000000FF
`define UART_SUPPORTED 1'b1
`define UART_BASE 34'h10000000
`define UART_RANGE 34'h00000007
`define PLIC_SUPPORTED 1'b1
`define PLIC_BASE 34'h0C000000
`define PLIC_RANGE 34'h03FFFFFF
`define SDC_SUPPORTED 1'b0
`define SDC_BASE 34'h00012100
`define SDC_RANGE 34'h0000001F
// Bus Interface width
`define AHBW 32
// Test modes
// Tie GPIO outputs back to inputs
`define GPIO_LOOPBACK_TEST 1
// Hardware configuration
`define UART_PRESCALE 1
// Interrupt configuration
`define PLIC_NUM_SRC 4
// comment out the following if >=32 sources
`define PLIC_NUM_SRC_LT_32
`define PLIC_GPIO_ID 3
`define PLIC_UART_ID 4
`define TWO_BIT_PRELOAD "../config/rv32ic/twoBitPredictor.txt"
`define BTB_PRELOAD "../config/rv32ic/BTBPredictor.txt"
`define BPRED_ENABLED 1
`define BPTYPE "BPGSHARE" // BPLOCALPAg or BPGLOBAL or BPTWOBIT or BPGSHARE
`define TESTSBP 0

View File

@ -77,6 +77,15 @@ for test in tests32ic:
grepstr="All tests ran without failures")
configs.append(tc)
tests32tim = ["arch32i", "arch32c"]
for test in tests32tim:
tc = TestCase(
name=test,
variant="rv32tim",
cmd="vsim > {} -c <<!\ndo wally-pipelined-tim-batch.do rv32tim "+test+"\n!",
grepstr="All tests ran without failures")
configs.append(tc)
import os
from multiprocessing import Pool, TimeoutError

View File

@ -0,0 +1,50 @@
# wally-pipelined-batch.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
# Usage: do wally-pipelined-batch.do <config> <testcases>
# Example: do wally-pipelined-batch.do rv32ic imperas-32i
# Use this wally-pipelined-batch.do file to run this example.
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
# do wally-pipelined-batch.do
# or, to run from a shell, type the following at the shell prompt:
# vsim -do wally-pipelined-batch.do -c
# (omit the "-c" to see the GUI while running from the shell)
onbreak {resume}
# create library
if [file exists work_${1}_${2}] {
vdel -lib work_${1}_${2} -all
}
vlib work_${1}_${2}
# compile source files
# suppress spurious warnngs about
# "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt
# default to config/rv64ic, but allow this to be overridden at the command line. For example:
# do wally-pipelined-batch.do ../config/rv32ic rv32ic
vlog -lint -work work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-tim.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
vopt work_${1}_${2}.testbench -work work_${1}_${2} -G TEST=$2 -o testbenchopt
vsim -lib work_${1}_${2} testbenchopt
# Adding coverage increases runtime from 2:00 to 4:29. Can't run it all the time
#vopt work_$2.testbench -work work_$2 -o workopt_$2 +cover=sbectf
#vsim -coverage -lib work_$2 workopt_$2
run -all
#coverage report -file wally-pipelined-coverage.txt
# These aren't doing anything helpful
#coverage report -memory
#profile report -calltree -file wally-pipelined-calltree.rpt -cutoff 2
quit

View File

@ -0,0 +1,56 @@
# 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
# default to config/rv64ic, but allow this to be overridden at the command line. For example:
# do wally-pipelined.do ../config/rv32ic
#switch $argc {
# 0 {vlog +incdir+../config/rv64ic +incdir+../config/shared ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv -suppress 2583}
# 1 {vlog +incdir+$1 +incdir+../config/shared ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv -suppress 2583}
#}
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
vlog +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-tim.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583
vopt +acc work.testbench -G TEST=$2 -o workopt
vsim workopt
view wave
-- display input and output signals as hexidecimal values
#do ./wave-dos/peripheral-waves.do
add log -recursive /*
do wave.do
-- Run the Simulation
#run 3600
run -all
#quit
#noview ../testbench/testbench-imperas.sv
noview ../testbench/testbench.sv
view wave

View File

@ -118,64 +118,64 @@ module ifu (
logic [31:0] PostSpillInstrRawF;
if(`C_SUPPORTED) begin : SpillSupport
logic [`XLEN-1:0] PCFp2;
logic Spill;
logic SelSpill, SpillSave;
logic [15:0] SpillDataLine0;
if(`C_SUPPORTED) begin : SpillSupport
logic [`XLEN-1:0] PCFp2;
logic Spill;
logic SelSpill, SpillSave;
logic [15:0] SpillDataLine0;
// this exists only if there are compressed instructions.
assign PCFp2 = PCF + `XLEN'b10;
assign PCNextFMux = SelNextSpill ? PCFp2[11:0] : PCNextF[11:0];
assign PCFMux = SelSpill ? PCFp2 : PCF;
assign Spill = &PCF[$clog2(SPILLTHRESHOLD)+1:1];
// this exists only if there are compressed instructions.
assign PCFp2 = PCF + `XLEN'b10;
assign PCNextFMux = SelNextSpill ? PCFp2[11:0] : PCNextF[11:0];
assign PCFMux = SelSpill ? PCFp2 : PCF;
assign Spill = &PCF[$clog2(SPILLTHRESHOLD)+1:1];
typedef enum {STATE_SPILL_READY, STATE_SPILL_SPILL} statetype;
(* mark_debug = "true" *) statetype CurrState, NextState;
typedef enum {STATE_SPILL_READY, STATE_SPILL_SPILL} statetype;
(* mark_debug = "true" *) statetype CurrState, NextState;
always_ff @(posedge clk)
if (reset) CurrState <= #1 STATE_SPILL_READY;
else CurrState <= #1 NextState;
always_ff @(posedge clk)
if (reset) CurrState <= #1 STATE_SPILL_READY;
else CurrState <= #1 NextState;
always_comb begin
case(CurrState)
STATE_SPILL_READY: if (Spill & ~(ICacheStallF | BusStall)) NextState = STATE_SPILL_SPILL;
else NextState = STATE_SPILL_READY;
STATE_SPILL_SPILL: if(ICacheStallF | BusStall | StallF) NextState = STATE_SPILL_SPILL;
else NextState = STATE_SPILL_READY;
default: NextState = STATE_SPILL_READY;
endcase
end
assign SelSpill = CurrState == STATE_SPILL_SPILL;
assign SelNextSpill = (CurrState == STATE_SPILL_READY & (Spill & ~(ICacheStallF | BusStall))) |
(CurrState == STATE_SPILL_SPILL & (ICacheStallF | BusStall));
assign SpillSave = CurrState == STATE_SPILL_READY & (Spill & ~(ICacheStallF | BusStall));
flopenr #(16) SpillInstrReg(.clk(clk),
.en(SpillSave),
.reset(reset),
.d(`MEM_ICACHE ? InstrRawF[15:0] : InstrRawF[31:16]),
.q(SpillDataLine0));
assign PostSpillInstrRawF = Spill ? {InstrRawF[15:0], SpillDataLine0} : InstrRawF;
assign CompressedF = PostSpillInstrRawF[1:0] != 2'b11;
// end of spill support
end else begin : NoSpillSupport // line: SpillSupport
assign PCNextFMux = PCNextF[11:0];
assign PCFMux = PCF;
assign SelNextSpill = 0;
assign PostSpillInstrRawF = InstrRawF;
always_comb begin
case(CurrState)
STATE_SPILL_READY: if (Spill & ~(ICacheStallF | BusStall)) NextState = STATE_SPILL_SPILL;
else NextState = STATE_SPILL_READY;
STATE_SPILL_SPILL: if(ICacheStallF | BusStall | StallF) NextState = STATE_SPILL_SPILL;
else NextState = STATE_SPILL_READY;
default: NextState = STATE_SPILL_READY;
endcase
end
assign SelSpill = CurrState == STATE_SPILL_SPILL;
assign SelNextSpill = (CurrState == STATE_SPILL_READY & (Spill & ~(ICacheStallF | BusStall))) |
(CurrState == STATE_SPILL_SPILL & (ICacheStallF | BusStall));
assign SpillSave = CurrState == STATE_SPILL_READY & (Spill & ~(ICacheStallF | BusStall));
flopenr #(16) SpillInstrReg(.clk(clk),
.en(SpillSave),
.reset(reset),
.d(`MEM_ICACHE ? InstrRawF[15:0] : InstrRawF[31:16]),
.q(SpillDataLine0));
assign PostSpillInstrRawF = Spill ? {InstrRawF[15:0], SpillDataLine0} : InstrRawF;
assign CompressedF = PostSpillInstrRawF[1:0] != 2'b11;
// end of spill support
end else begin : NoSpillSupport // line: SpillSupport
assign PCNextFMux = PCNextF[11:0];
assign PCFMux = PCF;
assign SelNextSpill = 0;
assign PostSpillInstrRawF = InstrRawF;
end
assign PCFExt = {2'b00, PCFMux};
//
mmu #(.TLB_ENTRIES(`ITLB_ENTRIES), .IMMU(1))
immu(.PAdr(PCFExt[`PA_BITS-1:0]),
.VAdr(PCFMux),
@ -208,23 +208,16 @@ module ifu (
// branch predictor signal
logic SelBPPredF;
logic [`XLEN-1:0] BPPredPCF, PCNext0F, PCNext1F, PCNext2F, PCNext3F;
logic [4:0] InstrClassD, InstrClassE;
// *** put memory interface on here, InstrF becomes output
//assign ICacheBusAdr = PCF; // *** no MMU
//assign IFUBusFetch = ~StallD; // *** & ICacheMissF; add later
// assign IFUBusFetch = 1; // *** & ICacheMissF; add later
// conditional
// 1. ram // controlled by `MEM_IROM
// 2. cache // `MEM_ICACHE
// 3. wire pass-through
// If we have `MEM_IROM we don't have the bus controller
// otherwise we have the bus controller and either a cache or a passthrough.
localparam integer WORDSPERLINE = `MEM_ICACHE ? `ICACHE_LINELENINBITS/`XLEN : 1;
localparam integer SPILLTHRESHOLD = `MEM_ICACHE ? `ICACHE_LINELENINBITS/32 : 1;
localparam integer LOGWPL = `MEM_ICACHE ? $clog2(WORDSPERLINE) : 1;
@ -235,56 +228,13 @@ module ifu (
localparam integer OFFSETLEN = $clog2(LINEBYTELEN);
logic [LOGWPL-1:0] WordCount;
logic [LINELEN-1:0] ICacheMemWriteData;
logic [LINELEN-1:0] ICacheMemWriteData;
logic ICacheBusAck;
logic [`PA_BITS-1:0] LocalIFUBusAdr;
logic [`PA_BITS-1:0] ICacheBusAdr;
logic SelUncachedAdr;
if(`MEM_ICACHE) begin : icache
logic [1:0] IFURWF;
assign IFURWF = CacheableF ? 2'b10 : 2'b00;
logic [`XLEN-1:0] FinalInstrRawF_FIXME;
cache #(.LINELEN(`ICACHE_LINELENINBITS),
.NUMLINES(`ICACHE_WAYSIZEINBYTES*8/`ICACHE_LINELENINBITS),
.NUMWAYS(`ICACHE_NUMWAYS), .DCACHE(0))
icache(.clk, .reset, .CPUBusy, .IgnoreRequest, .CacheMemWriteData(ICacheMemWriteData) , .CacheBusAck(ICacheBusAck),
.CacheBusAdr(ICacheBusAdr), .CacheStall(ICacheStallF), .ReadDataWord(FinalInstrRawF_FIXME),
.CacheFetchLine(ICacheFetchLine),
.CacheWriteLine(),
.ReadDataLineSets(),
.CacheMiss(ICacheMiss),
.CacheAccess(ICacheAccess),
.FinalWriteData('0),
.RW(IFURWF),
.Atomic(2'b00),
.FlushCache(1'b0),
.NextAdr(PCNextFMux),
.PAdr(PCPF),
.CacheCommitted(),
.InvalidateCacheM(InvalidateICacheM));
assign FinalInstrRawF = FinalInstrRawF_FIXME[31:0];
end else begin
assign ICacheFetchLine = 0;
assign ICacheBusAdr = 0;
assign ICacheStallF = 0;
if(!`MEM_IROM) assign FinalInstrRawF = 0;
assign ICacheAccess = CacheableF;
assign ICacheMiss = CacheableF;
end
// select between dcache and direct from the BUS. Always selected if no dcache.
// handled in the busfsm.
mux2 #(32) UnCachedInstrMux(.d0(FinalInstrRawF),
.d1(ICacheMemWriteData[31:0]),
.s(SelUncachedAdr),
.y(InstrRawF));
if (`MEM_IROM == 1) begin : irom
if (`MEM_IROM) begin : irom
logic [`XLEN-1:0] FinalInstrRawF_FIXME;
simpleram #(
@ -323,7 +273,56 @@ module ifu (
.BusStall, .LSUBusWrite(), .LSUBusRead(IFUBusRead), .DCacheBusAck(ICacheBusAck),
.BusCommittedM(), .SelUncachedAdr(SelUncachedAdr), .WordCount);
end
end
if(`MEM_ICACHE) begin : icache
logic [1:0] IFURWF;
assign IFURWF = CacheableF ? 2'b10 : 2'b00;
logic [`XLEN-1:0] FinalInstrRawF_FIXME;
cache #(.LINELEN(`ICACHE_LINELENINBITS),
.NUMLINES(`ICACHE_WAYSIZEINBYTES*8/`ICACHE_LINELENINBITS),
.NUMWAYS(`ICACHE_NUMWAYS), .DCACHE(0))
icache(.clk, .reset, .CPUBusy, .IgnoreRequest, .CacheMemWriteData(ICacheMemWriteData) , .CacheBusAck(ICacheBusAck),
.CacheBusAdr(ICacheBusAdr), .CacheStall(ICacheStallF), .ReadDataWord(FinalInstrRawF_FIXME),
.CacheFetchLine(ICacheFetchLine),
.CacheWriteLine(),
.ReadDataLineSets(),
.CacheMiss(ICacheMiss),
.CacheAccess(ICacheAccess),
.FinalWriteData('0),
.RW(IFURWF),
.Atomic(2'b00),
.FlushCache(1'b0),
.NextAdr(PCNextFMux),
.PAdr(PCPF),
.CacheCommitted(),
.InvalidateCacheM(InvalidateICacheM));
assign FinalInstrRawF = FinalInstrRawF_FIXME[31:0];
end else begin
assign ICacheFetchLine = 0;
assign ICacheBusAdr = 0;
assign ICacheStallF = 0;
if(!`MEM_IROM) assign FinalInstrRawF = 0;
assign ICacheAccess = CacheableF;
assign ICacheMiss = CacheableF;
end
// branch predictor signal
logic SelBPPredF;
logic [`XLEN-1:0] BPPredPCF, PCNext0F, PCNext1F, PCNext2F, PCNext3F;
logic [4:0] InstrClassD, InstrClassE;
// select between dcache and direct from the BUS. Always selected if no dcache.
// handled in the busfsm.
mux2 #(32) UnCachedInstrMux(.d0(FinalInstrRawF),
.d1(ICacheMemWriteData[31:0]),
.s(SelUncachedAdr),
.y(InstrRawF));
assign IFUStallF = ICacheStallF | BusStall | SelNextSpill;
assign CPUBusy = StallF & ~SelNextSpill;
@ -331,11 +330,9 @@ module ifu (
// this is a difference with the dcache.
// uses interlock fsm.
assign IgnoreRequest = ITLBMissF;
flopenl #(32) AlignedInstrRawDFlop(clk, reset | reset_q, ~StallD, FlushD ? nop : PostSpillInstrRawF, nop, InstrRawD);
assign PrivilegedChangePCM = RetM | TrapM;
mux2 #(`XLEN) pcmux0(.d0(PCPlus2or4F),