forked from Github_Repos/cvw
thomas fixed it before I did
This commit is contained in:
commit
86946266cf
@ -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";
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
86
wally-pipelined/src/ebu/pmachecker.sv
Normal file
86
wally-pipelined/src/ebu/pmachecker.sv
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
///////////////////////////////////////////
|
||||
|
@ -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};
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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), .*);
|
||||
|
@ -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;
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user