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 # array to hold contents of memory file
my @memfilebytes = (0)*16384*4; my $maxmemfilesize = 1000000;
my @memfilebytes = (0)*$maxmemfilesize*4;
my $maxaddress = 0; my $maxaddress = 0;
STDOUT->autoflush(1); STDOUT->autoflush(1);
# *** Ross Thompson I think there is a bug here needs to be +1 my $numfiles = $#ARGV+1;
print ("Processing $#ARGV memfiles: "); print ("Processing $numfiles memfiles: ");
my $frac = $#ARGV/10; my $frac = $#ARGV/10;
for(my $i=0; $i<=$#ARGV; $i++) { for(my $i=0; $i<=$#ARGV; $i++) {
if ($i < 10 || $i % $frac == 0) { print ("$i ") }; if ($i < 10 || $i % $frac == 0) { print ("$i ") };
@ -43,7 +44,7 @@ for(my $i=0; $i<=$#ARGV; $i++) {
my $address; my $address;
# initialize to all zeros; # initialize to all zeros;
for (my $i=0; $i < 65536*4; $i++) { for (my $i=0; $i < $maxmemfilesize*4; $i++) {
$memfilebytes[$i] = "00"; $memfilebytes[$i] = "00";
} }
@ -84,7 +85,11 @@ for(my $i=0; $i<=$#ARGV; $i++) {
open(MEMFILE, ">$memfile") || die("Can't write $memfile"); open(MEMFILE, ">$memfile") || die("Can't write $memfile");
for (my $i=0; $i<= $maxaddress; $i = $i + 4) { for (my $i=0; $i<= $maxaddress; $i = $i + 4) {
for ($j=3; $j>=0; $j--) { 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"; print MEMFILE "\n";
} }
@ -93,7 +98,11 @@ for(my $i=0; $i<=$#ARGV; $i++) {
open(MEMFILE, ">$memfile") || die("Can't write $memfile"); open(MEMFILE, ">$memfile") || die("Can't write $memfile");
for (my $i=0; $i<= $maxaddress; $i = $i + 8) { for (my $i=0; $i<= $maxaddress; $i = $i + 8) {
for ($j=7; $j>=0; $j--) { 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"; 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. # The verilator lint tool is faster and better than Modelsim so it is best to run this first.
echo "rv64ic linting..." 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..." 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 #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 # --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 from collections import namedtuple
confignames = ["rv32ic", "rv64ic", "busybear"] # 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 import multiprocessing, os
@ -21,35 +48,28 @@ def search_log_for_text(text, logfile):
return os.system(grepcmd) == 0 return os.system(grepcmd) == 0
def test_config(config, print_res=True): def test_config(config, print_res=True):
"""Run the given config, and return 0 if it suceeds and 1 if it fails""" """Run the given config, and return 0 if it suceeds and 1 if it fails"""
logname = "wally_"+config+".log" logname = "wally_"+config.name+".log"
if config == "busybear": cmd = config.cmd.format(logname)
# 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"
print(cmd) print(cmd)
os.system(cmd) os.system(cmd)
# check for success. grep returns 0 if found, 1 if not found # check for success. grep returns 0 if found, 1 if not found
passed = search_log_for_text("All tests ran without failures", logname) passed = search_log_for_text(config.grepstr, logname)
if passed: if passed:
if print_res:print(logname+": Success") if print_res:print(logname+": Success")
return 0 return 0
else: else:
if print_res:print(logname+": failures detected") if print_res:print(logname+": failures detected")
return 1 return 1
# Run the tests and count the failures # Run the tests and count the failures
pool = multiprocessing.Pool(min(len(confignames), 12)) pool = multiprocessing.Pool(min(len(configs), 12))
fail = sum(pool.map(test_config, confignames)) fail = sum(pool.map(test_config, configs))
if (fail): if (fail):
print ("Regression failed with " +str(fail)+ " failed configurations") print("Regression failed with " +str(fail)+ " failed configurations")
exit(1) print("Reminder: have you run `make allclean`?")
exit(1)
else: else:
print ("SUCCESS! All tests ran without failures") print("SUCCESS! All tests ran without failures")
exit(0) exit(0)

View File

@ -31,7 +31,7 @@
`include "wally-config.vh" `include "wally-config.vh"
package ahbliteState; 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 endpackage
module ahblite ( module ahblite (
@ -51,10 +51,13 @@ module ahblite (
input logic [`XLEN-1:0] WriteDataM, input logic [`XLEN-1:0] WriteDataM,
input logic [1:0] MemSizeM, input logic [1:0] MemSizeM,
// Signals from MMU // Signals from MMU
input logic MMUStall,
input logic [`XLEN-1:0] MMUPAdr, input logic [`XLEN-1:0] MMUPAdr,
input logic MMUTranslate, MMUTranslationComplete, input logic MMUTranslate, MMUTranslationComplete,
output logic [`XLEN-1:0] MMUReadPTE, output logic [`XLEN-1:0] MMUReadPTE,
output logic MMUReady, output logic MMUReady,
// Signals from PMA checker
input logic SquashAHBAccess,
// Return from bus // Return from bus
output logic [`XLEN-1:0] ReadDataW, output logic [`XLEN-1:0] ReadDataW,
// AHB-Lite external signals // AHB-Lite external signals
@ -102,6 +105,10 @@ module ahblite (
flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextBusState, IDLE, BusState); 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 always_comb
case (BusState) case (BusState)
IDLE: if (MMUTranslate) NextBusState = MMUTRANSLATE; IDLE: if (MMUTranslate) NextBusState = MMUTRANSLATE;
@ -136,11 +143,10 @@ module ahblite (
// since translation might not be complete. // since translation might not be complete.
assign #2 DataStall = ((NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || assign #2 DataStall = ((NextBusState == MEMREAD) || (NextBusState == MEMWRITE) ||
(NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE) || (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE) ||
(NextBusState == MMUTRANSLATE) || (MMUTranslate && ~MMUTranslationComplete)); MMUStall);
// *** Could get finer grained stalling if we distinguish between MMU
// instruction address translation and data address translation
assign #1 InstrStall = ((NextBusState == INSTRREAD) || (NextBusState == INSTRREADC) || assign #1 InstrStall = ((NextBusState == INSTRREAD) || (NextBusState == INSTRREADC) ||
(NextBusState == MMUTRANSLATE) || (MMUTranslate && ~MMUTranslationComplete)); MMUStall);
// Determine access type (important for determining whether to fault) // Determine access type (important for determining whether to fault)
assign Atomic = ((NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE)); assign Atomic = ((NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE));

View File

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

View File

@ -28,7 +28,6 @@
`include "wally-config.vh" `include "wally-config.vh"
`include "wally-constants.vh" `include "wally-constants.vh"
// *** use actual flop notation instead of initialbegin and alwaysff
module tlb_ram #(parameter ENTRY_BITS = 3) ( module tlb_ram #(parameter ENTRY_BITS = 3) (
input clk, reset, input clk, reset,
input [ENTRY_BITS-1:0] VPNIndex, // Index to read from 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] ram [0:NENTRIES-1];
logic [`XLEN-1:0] PageTableEntry; logic [`XLEN-1:0] PageTableEntry;
always @(posedge clk) begin
if (TLBWrite) ram[WriteIndex] <= PageTableEntryWrite; logic [NENTRIES-1:0] RAMEntryWrite;
end
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 PageTableEntry = ram[VPNIndex];
assign PTEAccessBits = PageTableEntry[7:0]; assign PTEAccessBits = PageTableEntry[7:0];
assign PhysicalPageNumber = PageTableEntry[`PPN_BITS+9:10]; assign PhysicalPageNumber = PageTableEntry[`PPN_BITS+9:10];
initial begin
for (int i = 0; i < NENTRIES; i++)
ram[i] = `XLEN'b0;
end
endmodule endmodule

View File

@ -23,6 +23,13 @@
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 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); module div (Q, rem0, done, divBusy, div0, N, D, clk, reset, start);
input logic [63:0] N, D; input logic [63:0] N, D;
@ -1554,3 +1561,5 @@ module shifter_r32 (Z, A, Shift);
endmodule // shifter_r32 endmodule // shifter_r32
/* verilator lint_on COMBDLY */
/* verilator lint_on IMPLICIT */

View File

@ -107,8 +107,10 @@ module csrm #(parameter
logic WritePMPCFG0M, WritePMPCFG2M; logic WritePMPCFG0M, WritePMPCFG2M;
logic WritePMPADDRM [0:15]; 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 // 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 // Write machine Mode CSRs
assign WriteMSTATUSM = CSRMWriteM && (CSRAdrM == MSTATUS); assign WriteMSTATUSM = CSRMWriteM && (CSRAdrM == MSTATUS);

View File

@ -42,9 +42,9 @@ module privileged (
input logic PrivilegedM, input logic PrivilegedM,
input logic ITLBInstrPageFaultF, DTLBLoadPageFaultM, DTLBStorePageFaultM, input logic ITLBInstrPageFaultF, DTLBLoadPageFaultM, DTLBStorePageFaultM,
input logic WalkerInstrPageFaultF, WalkerLoadPageFaultM, WalkerStorePageFaultM, input logic WalkerInstrPageFaultF, WalkerLoadPageFaultM, WalkerStorePageFaultM,
input logic InstrMisalignedFaultM, InstrAccessFaultF, IllegalIEUInstrFaultD, input logic InstrMisalignedFaultM, IllegalIEUInstrFaultD,
input logic LoadMisalignedFaultM, LoadAccessFaultM, input logic LoadMisalignedFaultM,
input logic StoreMisalignedFaultM, StoreAccessFaultM, input logic StoreMisalignedFaultM,
input logic TimerIntM, ExtIntM, SwIntM, input logic TimerIntM, ExtIntM, SwIntM,
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM, input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
input logic [4:0] SetFflagsM, input logic [4:0] SetFflagsM,
@ -52,7 +52,16 @@ module privileged (
output logic [`XLEN-1:0] SATP_REGW, output logic [`XLEN-1:0] SATP_REGW,
output logic STATUS_MXR, STATUS_SUM, output logic STATUS_MXR, STATUS_SUM,
output logic [2:0] FRM_REGW, 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; logic [1:0] NextPrivilegeModeM;
@ -67,7 +76,8 @@ module privileged (
logic IllegalIEUInstrFaultE, IllegalIEUInstrFaultM; logic IllegalIEUInstrFaultE, IllegalIEUInstrFaultM;
logic LoadPageFaultM, StorePageFaultM; logic LoadPageFaultM, StorePageFaultM;
logic InstrPageFaultF, InstrPageFaultD, InstrPageFaultE, InstrPageFaultM; logic InstrPageFaultF, InstrPageFaultD, InstrPageFaultE, InstrPageFaultM;
logic InstrAccessFaultD, InstrAccessFaultE, InstrAccessFaultM; logic InstrAccessFaultF, InstrAccessFaultD, InstrAccessFaultE, InstrAccessFaultM;
logic LoadAccessFaultM, StoreAccessFaultM;
logic IllegalInstrFaultM; logic IllegalInstrFaultM;
logic BreakpointFaultM, EcallFaultM; logic BreakpointFaultM, EcallFaultM;
@ -118,6 +128,12 @@ module privileged (
csr csr(.*); csr csr(.*);
///////////////////////////////////////////
// Check physical memory accesses
///////////////////////////////////////////
pmachecker pmachecker(.*);
/////////////////////////////////////////// ///////////////////////////////////////////
// Extract exceptions by name and handle them // 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 [`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 [11:0] MIP_REGW, MIE_REGW,
input logic STATUS_MIE, STATUS_SIE, input logic STATUS_MIE, STATUS_SIE,
input logic [`XLEN-1:0] PCM,
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM, input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
input logic [31:0] InstrM, input logic [31:0] InstrM,
output logic TrapM, MTrapM, STrapM, UTrapM, RetM, output logic TrapM, MTrapM, STrapM, UTrapM, RetM,
@ -128,7 +129,7 @@ module trap (
if (InstrMisalignedFaultM) NextFaultMtvalM = InstrMisalignedAdrM; if (InstrMisalignedFaultM) NextFaultMtvalM = InstrMisalignedAdrM;
else if (LoadMisalignedFaultM) NextFaultMtvalM = MemAdrM; else if (LoadMisalignedFaultM) NextFaultMtvalM = MemAdrM;
else if (StoreMisalignedFaultM) 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 (LoadPageFaultM) NextFaultMtvalM = MemAdrM;
else if (StorePageFaultM) NextFaultMtvalM = MemAdrM; else if (StorePageFaultM) NextFaultMtvalM = MemAdrM;
else if (IllegalInstrFaultM) NextFaultMtvalM = {{(`XLEN-32){1'b0}}, InstrM}; else if (IllegalInstrFaultM) NextFaultMtvalM = {{(`XLEN-32){1'b0}}, InstrM};

View File

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

View File

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

View File

@ -60,6 +60,7 @@ module wallypipelinedsoc (
// Uncore signals // Uncore signals
logic [`AHBW-1:0] HRDATA; // from AHB mux in uncore logic [`AHBW-1:0] HRDATA; // from AHB mux in uncore
logic HREADY, HRESP; logic HREADY, HRESP;
logic [5:0] HSELRegions;
logic InstrAccessFaultF, DataAccessFaultM; logic InstrAccessFaultF, DataAccessFaultM;
logic TimerIntM, SwIntM; // from CLINT logic TimerIntM, SwIntM; // from CLINT
logic ExtIntM; // from PLIC logic ExtIntM; // from PLIC
@ -72,8 +73,6 @@ module wallypipelinedsoc (
// instantiate processor and memories // instantiate processor and memories
wallypipelinedhart hart(.*); 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. // 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*** // imem imem(.AdrF(PCF[`XLEN-1:1]), .*); // temporary until uncore memory is finished***
uncore uncore(.HWDATAIN(HWDATA), .*); uncore uncore(.HWDATAIN(HWDATA), .*);

View File

@ -29,6 +29,76 @@ module testbench();
// instantiate processor and memories // instantiate processor and memories
wallypipelinedsoc dut(.*); 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 // initialize test
initial initial
@ -68,7 +138,7 @@ module testbench();
// read CSR trace file // read CSR trace file
integer data_file_csr, scan_file_csr; integer data_file_csr, scan_file_csr;
initial begin 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 if (data_file_csr == 0) begin
$display("file couldn't be opened"); $display("file couldn't be opened");
$stop; $stop;
@ -189,7 +259,7 @@ module testbench();
logic [63:0] readMask; logic [63:0] readMask;
assign readMask = ((1 << (8*(1 << HSIZE))) - 1) << 8 * HADDR[2:0]; assign readMask = ((1 << (8*(1 << HSIZE))) - 1) << 8 * HADDR[2:0];
logic [`XLEN-1:0] readAdrExpected; logic [`XLEN-1:0] readAdrExpected, readAdrTranslated;
import ahbliteState::*; import ahbliteState::*;
always @(dut.HRDATA) begin always @(dut.HRDATA) begin
@ -204,8 +274,9 @@ module testbench();
end end
scan_file_memR = $fscanf(data_file_memR, "%x\n", readAdrExpected); scan_file_memR = $fscanf(data_file_memR, "%x\n", readAdrExpected);
scan_file_memR = $fscanf(data_file_memR, "%x\n", HRDATA); scan_file_memR = $fscanf(data_file_memR, "%x\n", HRDATA);
if (~equal(HADDR,readAdrExpected,4)) begin assign readAdrTranslated = adrTranslator(readAdrExpected);
$display("%0t ps, instr %0d: HADDR does not equal readAdrExpected: %x, %x", $time, instrs, HADDR, readAdrExpected); if (~equal(HADDR,readAdrTranslated,4)) begin
$display("%0t ps, instr %0d: HADDR does not equal readAdrExpected: %x, %x", $time, instrs, HADDR, readAdrTranslated);
`ERROR `ERROR
end end
if ((readMask & HRDATA) !== (readMask & dut.HRDATA)) begin if ((readMask & HRDATA) !== (readMask & dut.HRDATA)) begin
@ -227,7 +298,7 @@ module testbench();
end end
logic [`XLEN-1:0] writeDataExpected, writeAdrExpected; logic [`XLEN-1:0] writeDataExpected, writeAdrExpected, writeAdrTranslated;
// this might need to change // this might need to change
//always @(HWDATA or HADDR or HSIZE or HWRITE) begin //always @(HWDATA or HADDR or HSIZE or HWRITE) begin
@ -240,12 +311,14 @@ module testbench();
end end
scan_file_memW = $fscanf(data_file_memW, "%x\n", writeDataExpected); scan_file_memW = $fscanf(data_file_memW, "%x\n", writeDataExpected);
scan_file_memW = $fscanf(data_file_memW, "%x\n", writeAdrExpected); scan_file_memW = $fscanf(data_file_memW, "%x\n", writeAdrExpected);
assign writeAdrTranslated = adrTranslator(writeAdrExpected);
if (writeDataExpected != HWDATA) begin if (writeDataExpected != HWDATA) begin
$display("%0t ps, instr %0d: HWDATA does not equal writeDataExpected: %x, %x", $time, instrs, HWDATA, writeDataExpected); $display("%0t ps, instr %0d: HWDATA does not equal writeDataExpected: %x, %x", $time, instrs, HWDATA, writeDataExpected);
`ERROR `ERROR
end end
if (~equal(writeAdrExpected,HADDR,1)) begin if (~equal(writeAdrTranslated,HADDR,1)) begin
$display("%0t ps, instr %0d: HADDR does not equal writeAdrExpected: %x, %x", $time, instrs, HADDR, writeAdrExpected); $display("%0t ps, instr %0d: HADDR does not equal writeAdrExpected: %x, %x", $time, instrs, HADDR, writeAdrTranslated);
`ERROR `ERROR
end end
end end
@ -346,10 +419,6 @@ module testbench();
//$stop; //$stop;
generate generate
if (`BUSYBEAR == 1) begin if (`BUSYBEAR == 1) begin
initial begin
#34140421;
$stop;
end
initial begin //this is temporary until the bug can be fixed!!! initial begin //this is temporary until the bug can be fixed!!!
#11130100; #11130100;
force dut.hart.ieu.dp.regf.rf[5] = 64'h0000000080000004; force dut.hart.ieu.dp.regf.rf[5] = 64'h0000000080000004;

View File

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

File diff suppressed because it is too large Load Diff