thomas fixed it before I did

This commit is contained in:
bbracker 2021-04-24 09:38:52 -04:00
commit 86946266cf
18 changed files with 1947 additions and 590 deletions

View File

@ -13,12 +13,13 @@ if ($#ARGV == -1) {
}
# array to hold contents of memory file
my @memfilebytes = (0)*16384*4;
my $maxmemfilesize = 1000000;
my @memfilebytes = (0)*$maxmemfilesize*4;
my $maxaddress = 0;
STDOUT->autoflush(1);
# *** Ross Thompson I think there is a bug here needs to be +1
print ("Processing $#ARGV memfiles: ");
my $numfiles = $#ARGV+1;
print ("Processing $numfiles memfiles: ");
my $frac = $#ARGV/10;
for(my $i=0; $i<=$#ARGV; $i++) {
if ($i < 10 || $i % $frac == 0) { print ("$i ") };
@ -43,7 +44,7 @@ for(my $i=0; $i<=$#ARGV; $i++) {
my $address;
# initialize to all zeros;
for (my $i=0; $i < 65536*4; $i++) {
for (my $i=0; $i < $maxmemfilesize*4; $i++) {
$memfilebytes[$i] = "00";
}
@ -84,7 +85,11 @@ for(my $i=0; $i<=$#ARGV; $i++) {
open(MEMFILE, ">$memfile") || die("Can't write $memfile");
for (my $i=0; $i<= $maxaddress; $i = $i + 4) {
for ($j=3; $j>=0; $j--) {
print MEMFILE "$memfilebytes[$i+$j]";
if (defined($memfilebytes[$i+$j])) {
print MEMFILE "$memfilebytes[$i+$j]";
} else {
print MEMFILE "00";
}
}
print MEMFILE "\n";
}
@ -93,7 +98,11 @@ for(my $i=0; $i<=$#ARGV; $i++) {
open(MEMFILE, ">$memfile") || die("Can't write $memfile");
for (my $i=0; $i<= $maxaddress; $i = $i + 8) {
for ($j=7; $j>=0; $j--) {
print MEMFILE "$memfilebytes[$i+$j]";
if (defined($memfilebytes[$i+$j])) {
print MEMFILE "$memfilebytes[$i+$j]";
} else {
print MEMFILE "00";
}
}
print MEMFILE "\n";
}

View File

@ -2,9 +2,9 @@
# The verilator lint tool is faster and better than Modelsim so it is best to run this first.
echo "rv64ic linting..."
verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv
verilator --lint-only "$@" --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv
echo "rv32ic linting..."
verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv32ic src/*/*.sv
verilator --lint-only "$@" --top-module wallypipelinedsoc -Iconfig/rv32ic src/*/*.sv
#verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv src/*/div/*.sv
# --lint-only just runs lint rather than trying to compile and simulate

View File

@ -8,8 +8,35 @@
#
##################################
# edit this line to add more configurations
confignames = ["rv32ic", "rv64ic", "busybear"]
from collections import namedtuple
# name: the name of this test configuration/script
# cmd: the command to run to test (should include the logfile as {})
# grepstr: the string to grep through the log file for, success iff grep finds that string
Config = namedtuple("Config", ['name', 'cmd', 'grepstr'])
# edit this list to add more configurations
configs = [
Config(
name="busybear",
cmd="vsim -do wally-busybear-batch.do -c > {}",
grepstr="# loaded 800000 instructions"
),
Config(
name="buildroot",
cmd="vsim -do wally-buildroot-batch.do -c > {}",
grepstr="# loaded 100000 instructions"
),
Config(
name="rv32ic",
cmd="vsim > {} -c <<!\ndo wally-pipelined-batch.do ../config/rv32ic rv32ic\n!",
grepstr="All tests ran without failures"
),
Config(
name="rv64ic",
cmd="vsim > {} -c <<!\ndo wally-pipelined-batch.do ../config/rv64ic rv64ic\n!",
grepstr="All tests ran without failures"
),
]
import multiprocessing, os
@ -21,35 +48,28 @@ def search_log_for_text(text, logfile):
return os.system(grepcmd) == 0
def test_config(config, print_res=True):
"""Run the given config, and return 0 if it suceeds and 1 if it fails"""
logname = "wally_"+config+".log"
if config == "busybear":
# Handle busybear separately
cmd = "vsim -do wally-busybear-batch.do -c >" + logname
os.system(cmd)
# check for success. grep returns 0 if found, 1 if not found
passed = search_log_for_text("# loaded 800000 instructions", logname)
else:
# Any other configuration loads that name from the config folder and runs vsim
cmd = "vsim -c >" + logname +" <<!\ndo wally-pipelined-batch.do ../config/" + config + " " + config + "\n!\n"
"""Run the given config, and return 0 if it suceeds and 1 if it fails"""
logname = "wally_"+config.name+".log"
cmd = config.cmd.format(logname)
print(cmd)
os.system(cmd)
# check for success. grep returns 0 if found, 1 if not found
passed = search_log_for_text("All tests ran without failures", logname)
if passed:
if print_res:print(logname+": Success")
return 0
else:
if print_res:print(logname+": failures detected")
return 1
passed = search_log_for_text(config.grepstr, logname)
if passed:
if print_res:print(logname+": Success")
return 0
else:
if print_res:print(logname+": failures detected")
return 1
# Run the tests and count the failures
pool = multiprocessing.Pool(min(len(confignames), 12))
fail = sum(pool.map(test_config, confignames))
pool = multiprocessing.Pool(min(len(configs), 12))
fail = sum(pool.map(test_config, configs))
if (fail):
print ("Regression failed with " +str(fail)+ " failed configurations")
exit(1)
print("Regression failed with " +str(fail)+ " failed configurations")
print("Reminder: have you run `make allclean`?")
exit(1)
else:
print ("SUCCESS! All tests ran without failures")
exit(0)
print("SUCCESS! All tests ran without failures")
exit(0)

View File

@ -31,7 +31,7 @@
`include "wally-config.vh"
package ahbliteState;
typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADC, ATOMICREAD, ATOMICWRITE, MMUTRANSLATE, MMUIDLE} statetype;
typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADC, ATOMICREAD, ATOMICWRITE, MMUTRANSLATE} statetype;
endpackage
module ahblite (
@ -51,10 +51,13 @@ module ahblite (
input logic [`XLEN-1:0] WriteDataM,
input logic [1:0] MemSizeM,
// Signals from MMU
input logic MMUStall,
input logic [`XLEN-1:0] MMUPAdr,
input logic MMUTranslate, MMUTranslationComplete,
output logic [`XLEN-1:0] MMUReadPTE,
output logic MMUReady,
// Signals from PMA checker
input logic SquashAHBAccess,
// Return from bus
output logic [`XLEN-1:0] ReadDataW,
// AHB-Lite external signals
@ -102,6 +105,10 @@ module ahblite (
flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextBusState, IDLE, BusState);
// *** If the SquashAHBAccess signal is high, we need to set NextBusState to IDLE.
// We could either have this case statement set a signal ProposedNextBusState, which gets
// used for NextBusState when we are not squashing. Alternatively, we could add a bunch of
// conditional statments below
always_comb
case (BusState)
IDLE: if (MMUTranslate) NextBusState = MMUTRANSLATE;
@ -136,11 +143,10 @@ module ahblite (
// since translation might not be complete.
assign #2 DataStall = ((NextBusState == MEMREAD) || (NextBusState == MEMWRITE) ||
(NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE) ||
(NextBusState == MMUTRANSLATE) || (MMUTranslate && ~MMUTranslationComplete));
// *** Could get finer grained stalling if we distinguish between MMU
// instruction address translation and data address translation
MMUStall);
assign #1 InstrStall = ((NextBusState == INSTRREAD) || (NextBusState == INSTRREADC) ||
(NextBusState == MMUTRANSLATE) || (MMUTranslate && ~MMUTranslationComplete));
MMUStall);
// Determine access type (important for determining whether to fault)
assign Atomic = ((NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE));

View File

@ -60,6 +60,9 @@ module pagetablewalker (
output logic MMUTranslate,
output logic MMUTranslationComplete,
// Stall signal
output logic MMUStall,
// Faults
output logic WalkerInstrPageFaultF,
output logic WalkerLoadPageFaultM,
@ -197,8 +200,12 @@ module pagetablewalker (
WalkerInstrPageFaultF = '0;
WalkerLoadPageFaultM = '0;
WalkerStorePageFaultM = '0;
MMUStall = '1;
case (NextWalkerState)
IDLE: begin
MMUStall = '0;
end
LEVEL1: begin
TranslationPAdr = {BasePageTablePPN, VPN1, 2'b00};
end
@ -220,6 +227,7 @@ module pagetablewalker (
WalkerInstrPageFaultF = ~DTLBMissM;
WalkerLoadPageFaultM = DTLBMissM && ~MemStore;
WalkerStorePageFaultM = DTLBMissM && MemStore;
MMUStall = '0; // Drop the stall early to enter trap handling code
end
default: begin
// nothing
@ -302,8 +310,12 @@ module pagetablewalker (
WalkerInstrPageFaultF = '0;
WalkerLoadPageFaultM = '0;
WalkerStorePageFaultM = '0;
MMUStall = '1;
case (NextWalkerState)
IDLE: begin
MMUStall = '0;
end
LEVEL2: begin
TranslationPAdr = {BasePageTablePPN, VPN2, 3'b000};
end
@ -329,6 +341,7 @@ module pagetablewalker (
WalkerInstrPageFaultF = ~DTLBMissM;
WalkerLoadPageFaultM = DTLBMissM && ~MemStore;
WalkerStorePageFaultM = DTLBMissM && MemStore;
MMUStall = '0; // Drop the stall early to enter trap handling code
end
default: begin
// nothing

View File

@ -0,0 +1,86 @@
///////////////////////////////////////////
// pmachecker.sv
//
// Written: tfleming@hmc.edu & jtorrey@hmc.edu 20 April 2021
// Modified:
//
// Purpose: Examines all physical memory accesses and identifies attributes of
// the memory region accessed.
// Can report illegal accesses to the trap unit and cause a fault.
//
// 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 "wally-config.vh"
module pmachecker (
input logic [31:0] HADDR,
input logic [2:0] HSIZE,
input logic HWRITE,
input logic [2:0] HBURST,
input logic Atomic, Execute, Write, Read,
// *** Add pipeline suffixes
output logic Cacheable, Idempotent, AtomicAllowed,
output logic SquashAHBAccess,
output logic [5:0] HSELRegions,
output logic InstrAccessFaultF,
output logic LoadAccessFaultM,
output logic StoreAccessFaultM
);
// Signals are high if the memory access is within the given region
logic HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC;
logic PreHSELUART;
logic Empty;
// Determine which region of physical memory (if any) is being accessed
adrdec boottimdec(HADDR, `BOOTTIMBASE, `BOOTTIMRANGE, HSELBootTim);
adrdec timdec(HADDR, `TIMBASE, `TIMRANGE, HSELTim);
adrdec clintdec(HADDR, `CLINTBASE, `CLINTRANGE, HSELCLINT);
adrdec gpiodec(HADDR, `GPIOBASE, `GPIORANGE, HSELGPIO);
adrdec uartdec(HADDR, `UARTBASE, `UARTRANGE, PreHSELUART);
adrdec plicdec(HADDR, `PLICBASE, `PLICRANGE, HSELPLIC);
assign HSELUART = PreHSELUART && (HSIZE == 3'b000); // only byte writes to UART are supported
// Swizzle region bits
assign HSELRegions = {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC};
// Only RAM memory regions are cacheable
assign Cacheable = HSELBootTim | HSELTim;
// *** Temporarily assume only RAM regions are idempotent -- likely wrong
assign Idempotent = HSELBootTim | HSELTim;
// *** Temporarily assume only RAM regions allow full atomic operations -- likely wrong
assign AtomicAllowed = HSELBootTim | HSELTim;
assign Empty = ~|HSELRegions;
assign InstrAccessFaultF = Empty && Execute;
assign LoadAccessFaultM = Empty && Read;
assign StoreAccessFaultM = Empty && Write;
assign SquashAHBAccess = InstrAccessFaultF || LoadAccessFaultM || StoreAccessFaultM;
endmodule

View File

@ -22,7 +22,10 @@ module booth(xExt, choose, add1, e, pp);
3'b100 : pp = {negx, 1'b0}; // -2
3'b101 : pp = {1'b1, negx}; // -1
3'b110 : pp = {1'b1, negx}; // -1
3'b111 : pp = 55'h7fffffffffffff; // -0
// *** <Thomas Fleming> I changed this to fix a lint error. '1 should
// fill the signal with all ones.
// 3'b111 : pp = 55'hfffffffffffffff;
3'b111 : pp = '1; // -0
endcase
always_comb

View File

@ -28,7 +28,6 @@
`include "wally-config.vh"
`include "wally-constants.vh"
// *** use actual flop notation instead of initialbegin and alwaysff
module tlb_ram #(parameter ENTRY_BITS = 3) (
input clk, reset,
input [ENTRY_BITS-1:0] VPNIndex, // Index to read from
@ -44,17 +43,22 @@ module tlb_ram #(parameter ENTRY_BITS = 3) (
logic [`XLEN-1:0] ram [0:NENTRIES-1];
logic [`XLEN-1:0] PageTableEntry;
always @(posedge clk) begin
if (TLBWrite) ram[WriteIndex] <= PageTableEntryWrite;
end
logic [NENTRIES-1:0] RAMEntryWrite;
decoder #(ENTRY_BITS) tlb_ram_decoder(WriteIndex, RAMEntryWrite);
// Generate a flop for every entry in the RAM
generate
genvar i;
for (i = 0; i < NENTRIES; i++) begin: tlb_ram_flops
flopenr #(`XLEN) pte_flop(clk, reset, RAMEntryWrite[i] & TLBWrite,
PageTableEntryWrite, ram[i]);
end
endgenerate
assign PageTableEntry = ram[VPNIndex];
assign PTEAccessBits = PageTableEntry[7:0];
assign PhysicalPageNumber = PageTableEntry[`PPN_BITS+9:10];
initial begin
for (int i = 0; i < NENTRIES; i++)
ram[i] = `XLEN'b0;
end
endmodule

View File

@ -23,6 +23,13 @@
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
// *** <Thomas Fleming> I added these verilator controls to clean up the
// lint output. The linter warnings should be fixed, but now the output is at
// least readable.
/* verilator lint_off COMBDLY */
/* verilator lint_off IMPLICIT */
module div (Q, rem0, done, divBusy, div0, N, D, clk, reset, start);
input logic [63:0] N, D;
@ -1554,3 +1561,5 @@ module shifter_r32 (Z, A, Shift);
endmodule // shifter_r32
/* verilator lint_on COMBDLY */
/* verilator lint_on IMPLICIT */

View File

@ -107,8 +107,10 @@ module csrm #(parameter
logic WritePMPCFG0M, WritePMPCFG2M;
logic WritePMPADDRM [0:15];
localparam MISA_26 = (`MISA) & 32'h03ffffff;
// MISA is hardwired. Spec says it could be written to disable features, but this is not supported by Wally
assign MISA_REGW = {(`XLEN == 32 ? 2'b01 : 2'b10), {(`XLEN-28){1'b0}}, {`MISA}[25:0]};
assign MISA_REGW = {(`XLEN == 32 ? 2'b01 : 2'b10), {(`XLEN-28){1'b0}}, MISA_26[25:0]};
// Write machine Mode CSRs
assign WriteMSTATUSM = CSRMWriteM && (CSRAdrM == MSTATUS);

View File

@ -42,9 +42,9 @@ module privileged (
input logic PrivilegedM,
input logic ITLBInstrPageFaultF, DTLBLoadPageFaultM, DTLBStorePageFaultM,
input logic WalkerInstrPageFaultF, WalkerLoadPageFaultM, WalkerStorePageFaultM,
input logic InstrMisalignedFaultM, InstrAccessFaultF, IllegalIEUInstrFaultD,
input logic LoadMisalignedFaultM, LoadAccessFaultM,
input logic StoreMisalignedFaultM, StoreAccessFaultM,
input logic InstrMisalignedFaultM, IllegalIEUInstrFaultD,
input logic LoadMisalignedFaultM,
input logic StoreMisalignedFaultM,
input logic TimerIntM, ExtIntM, SwIntM,
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
input logic [4:0] SetFflagsM,
@ -52,7 +52,16 @@ module privileged (
output logic [`XLEN-1:0] SATP_REGW,
output logic STATUS_MXR, STATUS_SUM,
output logic [2:0] FRM_REGW,
input logic FlushD, FlushE, FlushM, StallD, StallW, StallE, StallM
input logic FlushD, FlushE, FlushM, StallD, StallW, StallE, StallM,
// PMA checker signals
input logic [31:0] HADDR,
input logic [2:0] HSIZE, HBURST,
input logic HWRITE,
input logic Atomic, Execute, Write, Read,
output logic Cacheable, Idempotent, AtomicAllowed,
output logic SquashAHBAccess,
output logic [5:0] HSELRegions
);
logic [1:0] NextPrivilegeModeM;
@ -67,7 +76,8 @@ module privileged (
logic IllegalIEUInstrFaultE, IllegalIEUInstrFaultM;
logic LoadPageFaultM, StorePageFaultM;
logic InstrPageFaultF, InstrPageFaultD, InstrPageFaultE, InstrPageFaultM;
logic InstrAccessFaultD, InstrAccessFaultE, InstrAccessFaultM;
logic InstrAccessFaultF, InstrAccessFaultD, InstrAccessFaultE, InstrAccessFaultM;
logic LoadAccessFaultM, StoreAccessFaultM;
logic IllegalInstrFaultM;
logic BreakpointFaultM, EcallFaultM;
@ -118,6 +128,12 @@ module privileged (
csr csr(.*);
///////////////////////////////////////////
// Check physical memory accesses
///////////////////////////////////////////
pmachecker pmachecker(.*);
///////////////////////////////////////////
// Extract exceptions by name and handle them
///////////////////////////////////////////

View File

@ -37,6 +37,7 @@ module trap (
input logic [`XLEN-1:0] MEPC_REGW, SEPC_REGW, UEPC_REGW, UTVEC_REGW, STVEC_REGW, MTVEC_REGW,
input logic [11:0] MIP_REGW, MIE_REGW,
input logic STATUS_MIE, STATUS_SIE,
input logic [`XLEN-1:0] PCM,
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
input logic [31:0] InstrM,
output logic TrapM, MTrapM, STrapM, UTrapM, RetM,
@ -128,7 +129,7 @@ module trap (
if (InstrMisalignedFaultM) NextFaultMtvalM = InstrMisalignedAdrM;
else if (LoadMisalignedFaultM) NextFaultMtvalM = MemAdrM;
else if (StoreMisalignedFaultM) NextFaultMtvalM = MemAdrM;
else if (InstrPageFaultM) NextFaultMtvalM = 0; // *** implement
else if (InstrPageFaultM) NextFaultMtvalM = PCM;
else if (LoadPageFaultM) NextFaultMtvalM = MemAdrM;
else if (StorePageFaultM) NextFaultMtvalM = MemAdrM;
else if (IllegalInstrFaultM) NextFaultMtvalM = {{(`XLEN-32){1'b0}}, InstrM};

View File

@ -47,8 +47,11 @@ module uncore (
input logic [2:0] HADDRD,
input logic [3:0] HSIZED,
input logic HWRITED,
// PMA checker signals
input logic [5:0] HSELRegions,
// bus interface
output logic DataAccessFaultM,
// PMA checker now handles access faults. *** This can be deleted
// output logic DataAccessFaultM,
// peripheral pins
output logic TimerIntM, SwIntM, ExtIntM,
input logic [31:0] GPIOPinsIn,
@ -68,8 +71,11 @@ module uncore (
logic HSELBootTim, HSELBootTimD, HRESPBootTim, HREADYBootTim;
logic [1:0] MemRWboottim;
logic UARTIntr,GPIOIntr;
// unswizzle HSEL signals
assign {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC} = HSELRegions;
/* PMA checker now handles decoding addresses. *** This can be deleted.
// AHB Address decoder
adrdec timdec(HADDR, `TIMBASE, `TIMRANGE, HSELTim);
adrdec boottimdec(HADDR, `BOOTTIMBASE, `BOOTTIMRANGE, HSELBootTim);
@ -78,6 +84,7 @@ module uncore (
adrdec gpiodec(HADDR, `GPIOBASE, `GPIORANGE, HSELGPIO);
adrdec uartdec(HADDR, `UARTBASE, `UARTRANGE, PreHSELUART);
assign HSELUART = PreHSELUART && (HSIZE == 3'b000); // only byte writes to UART are supported
*/
// subword accesses: converts HWDATAIN to HWDATA
subwordwrite sww(.*);
@ -115,9 +122,10 @@ module uncore (
HSELBootTimD & HREADYBootTim |
HSELUARTD & HREADYUART;
/* PMA checker now handles access faults. *** This can be deleted
// Faults
assign DataAccessFaultM = ~(HSELTimD | HSELCLINTD | HSELPLICD | HSELGPIOD | HSELBootTimD | HSELUARTD);
*/
// Address Decoder Delay (figure 4-2 in spec)
flopr #(1) hseltimreg(HCLK, ~HRESETn, HSELTim, HSELTimD);

View File

@ -48,6 +48,7 @@ module wallypipelinedhart (
output logic [3:0] HPROT,
output logic [1:0] HTRANS,
output logic HMASTLOCK,
output logic [5:0] HSELRegions,
// Delayed signals for subword write
output logic [2:0] HADDRD,
output logic [3:0] HSIZED,
@ -110,9 +111,15 @@ module wallypipelinedhart (
logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM;
logic [1:0] PageTypeF, PageTypeM;
// PMA checker signals
logic Atomic, Execute, Write, Read;
logic Cacheable, Idempotent, AtomicAllowed;
logic SquashAHBAccess;
// IMem stalls
logic ICacheStallF;
logic [`XLEN-1:0] MMUPAdr, MMUReadPTE;
logic MMUStall;
logic MMUTranslate, MMUTranslationComplete, MMUReady;
// bus interface to dmem

View File

@ -60,6 +60,7 @@ module wallypipelinedsoc (
// Uncore signals
logic [`AHBW-1:0] HRDATA; // from AHB mux in uncore
logic HREADY, HRESP;
logic [5:0] HSELRegions;
logic InstrAccessFaultF, DataAccessFaultM;
logic TimerIntM, SwIntM; // from CLINT
logic ExtIntM; // from PLIC
@ -72,8 +73,6 @@ module wallypipelinedsoc (
// instantiate processor and memories
wallypipelinedhart hart(.*);
// *** Temporary driving of access fault to low until PMA checker is complete
assign InstrAccessFaultF = '0;
// instructions now come from uncore memory. This line can be removed at any time.
// imem imem(.AdrF(PCF[`XLEN-1:1]), .*); // temporary until uncore memory is finished***
uncore uncore(.HWDATAIN(HWDATA), .*);

View File

@ -29,6 +29,76 @@ module testbench();
// instantiate processor and memories
wallypipelinedsoc dut(.*);
/**
* Walk the page table stored in dtim according to sv39 logic and translate a
* virtual address to a physical address.
*
* See section 4.3.2 of the RISC-V Privileged specification for a full
* explanation of the below algorithm.
*/
function logic [`XLEN-1:0] adrTranslator(
input logic [`XLEN-1:0] adrIn);
begin
logic SvMode, PTE_R, PTE_X;
logic [`XLEN-1:0] SATP, PTE;
logic [55:0] BaseAdr, PAdr;
logic [8:0] VPN [0:2];
logic [11:0] Offset;
int i;
// Grab the SATP register from privileged unit
SATP = dut.hart.priv.csr.SATP_REGW;
// Split the virtual address into page number segments and offset
VPN[2] = adrIn[38:30];
VPN[1] = adrIn[29:21];
VPN[0] = adrIn[20:12];
Offset = adrIn[11:0];
// We do not support sv48; only sv39
SvMode = SATP[63];
// Only perform translation if translation is on and the processor is not
// in machine mode
if (SvMode && (dut.hart.priv.PrivilegeModeW != `M_MODE)) begin
BaseAdr = SATP[43:0] << 12;
for (i = 2; i >= 0; i--) begin
PAdr = BaseAdr + (VPN[i] << 3);
// dtim.RAM is 64-bit addressed. PAdr specifies a byte. We right shift
// by 3 (the PTE size) to get the requested 64-bit PTE.
PTE = dut.uncore.dtim.RAM[PAdr >> 3];
PTE_R = PTE[1];
PTE_X = PTE[3];
if (PTE_R || PTE_X) begin
// Leaf page found
break;
end else begin
// Go to next level of table
BaseAdr = PTE[53:10] << 12;
end
end
// Determine which parts of the PTE page number to use based on the
// level of the page table we reached.
if (i == 2) begin
// Gigapage
assign adrTranslator = {8'b0, PTE[53:28], VPN[1], VPN[0], Offset};
end else if (i == 1) begin
// Megapage
assign adrTranslator = {8'b0, PTE[53:19], VPN[0], Offset};
end else begin
// Kilopage
assign adrTranslator = {8'b0, PTE[53:10], Offset};
end
end else begin
// Direct translation if address translation is not on
assign adrTranslator = adrIn;
end
end
endfunction
// initialize test
initial
@ -68,7 +138,7 @@ module testbench();
// read CSR trace file
integer data_file_csr, scan_file_csr;
initial begin
data_file_csr = $fopen({`BUSYBEAR_TEST_VECTORS,"parsedCSRs.txt"}, "r");
data_file_csr = $fopen({`BUSYBEAR_TEST_VECTORS,"parsedCSRs2.txt"}, "r");
if (data_file_csr == 0) begin
$display("file couldn't be opened");
$stop;
@ -189,7 +259,7 @@ module testbench();
logic [63:0] readMask;
assign readMask = ((1 << (8*(1 << HSIZE))) - 1) << 8 * HADDR[2:0];
logic [`XLEN-1:0] readAdrExpected;
logic [`XLEN-1:0] readAdrExpected, readAdrTranslated;
import ahbliteState::*;
always @(dut.HRDATA) begin
@ -204,8 +274,9 @@ module testbench();
end
scan_file_memR = $fscanf(data_file_memR, "%x\n", readAdrExpected);
scan_file_memR = $fscanf(data_file_memR, "%x\n", HRDATA);
if (~equal(HADDR,readAdrExpected,4)) begin
$display("%0t ps, instr %0d: HADDR does not equal readAdrExpected: %x, %x", $time, instrs, HADDR, readAdrExpected);
assign readAdrTranslated = adrTranslator(readAdrExpected);
if (~equal(HADDR,readAdrTranslated,4)) begin
$display("%0t ps, instr %0d: HADDR does not equal readAdrExpected: %x, %x", $time, instrs, HADDR, readAdrTranslated);
`ERROR
end
if ((readMask & HRDATA) !== (readMask & dut.HRDATA)) begin
@ -227,7 +298,7 @@ module testbench();
end
logic [`XLEN-1:0] writeDataExpected, writeAdrExpected;
logic [`XLEN-1:0] writeDataExpected, writeAdrExpected, writeAdrTranslated;
// this might need to change
//always @(HWDATA or HADDR or HSIZE or HWRITE) begin
@ -240,12 +311,14 @@ module testbench();
end
scan_file_memW = $fscanf(data_file_memW, "%x\n", writeDataExpected);
scan_file_memW = $fscanf(data_file_memW, "%x\n", writeAdrExpected);
assign writeAdrTranslated = adrTranslator(writeAdrExpected);
if (writeDataExpected != HWDATA) begin
$display("%0t ps, instr %0d: HWDATA does not equal writeDataExpected: %x, %x", $time, instrs, HWDATA, writeDataExpected);
`ERROR
end
if (~equal(writeAdrExpected,HADDR,1)) begin
$display("%0t ps, instr %0d: HADDR does not equal writeAdrExpected: %x, %x", $time, instrs, HADDR, writeAdrExpected);
if (~equal(writeAdrTranslated,HADDR,1)) begin
$display("%0t ps, instr %0d: HADDR does not equal writeAdrExpected: %x, %x", $time, instrs, HADDR, writeAdrTranslated);
`ERROR
end
end
@ -346,10 +419,6 @@ module testbench();
//$stop;
generate
if (`BUSYBEAR == 1) begin
initial begin
#34140421;
$stop;
end
initial begin //this is temporary until the bug can be fixed!!!
#11130100;
force dut.hart.ieu.dp.regf.rf[5] = 64'h0000000080000004;

View File

@ -334,7 +334,8 @@ module testbench();
"rv32i/WALLY-CSRRC", "4000",
"rv32i/WALLY-CSRRWI", "3000",
"rv32i/WALLY-CSRRSI", "3000",
"rv32i/WALLY-CSRRCI", "3000"
"rv32i/WALLY-CSRRCI", "3000",
"rv32i/WALLY-PIPELINE", "1a800"
};
string testsBP64[] = '{
@ -409,7 +410,7 @@ module testbench();
// if (`F_SUPPORTED) tests = {tests64f, tests};
// if (`D_SUPPORTED) tests = {tests64d, tests};
if (`A_SUPPORTED) tests = {tests, tests64a};
if (`MEM_VIRTMEM) tests = {tests64mmu, tests};
// if (`MEM_VIRTMEM) tests = {tests64mmu, tests};
end
//tests = {tests64a, tests};

File diff suppressed because it is too large Load Diff