Also fixed undetected bug with amo concurrent with tlb miss. It was possible for the amoalu to apply a function to the hptw readdata.

Merge branch 'main' of github.com:davidharrishmc/riscv-wally into main
This commit is contained in:
Ross Thompson 2022-01-06 23:28:02 -06:00
commit de3bbd3fe0
22 changed files with 224 additions and 437 deletions

@ -1 +1 @@
Subproject commit be67c99bd461742aa1c100bcc0732657faae2230
Subproject commit 307c77b26e070ae85ffea665ad9b642b40e33c86

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# james.stine@okstate.edu 4 Jan 2022
# Script to run elf2hex for memfile for

View File

@ -1,170 +0,0 @@
#!/usr/bin/perl -w
# exe2memfile.pl
# David_Harris@hmc.edu 26 November 2020
# Converts an executable file to a series of 32-bit hex instructions
# to read into a Verilog simulation with $readmemh
use File::stat;
use IO::Handle;
if ($#ARGV == -1) {
die("Usage: $0 executable_file");
}
# array to hold contents of memory file
my $maxmemfilesize = 1000000;
my @memfilebytes = (0)*$maxmemfilesize*4;
my $maxaddress = 0;
STDOUT->autoflush(1);
my $numfiles = $#ARGV+1;
if ($numfiles > 1) {
print ("Processing $numfiles memfiles: ");
}
my $frac = $#ARGV/10;
for(my $i=0; $i<=$#ARGV; $i++) {
if ($i > 0 && ($i < 10 || $i % $frac == 0)) { print ("$i ") };
my $fname = $ARGV[$i];
# print "fname = $fname";
my $ofile = $fname.".objdump";
my $memfile = $fname.".memfile";
my $needsprocessing = 0;
if (!-e $memfile) { $needsprocessing = 1; } # create memfile if it doesn't exist
else {
my $osb = stat($ofile) || die("Can't stat $ofile");
my $msb = stat($memfile) || die("Can't stat $memfile");
my $otime = $osb->mtime;
my $mtime = $msb->mtime;
if ($otime > $mtime) { $needsprocessing = 1; } # is memfile out of date?
}
if ($needsprocessing == 1) {
open(FILE, $ofile) || die("Can't read $ofile");
my $mode = 0; # parse for code
my $address;
# initialize to all zeros;
for (my $i=0; $i < $maxmemfilesize*4; $i++) {
$memfilebytes[$i] = "00";
}
while(<FILE>) {
if ($mode == 0) { # Parse code
# print("Examining $_\n");
if (/^\s*(\S\S\S\S\S\S\S\S):\s+(\S+)\s+/) {
$address = &fixadr($1);
my $instr = $2;
my $len = length($instr);
for (my $i=0; $i<$len/2; $i++) {
$memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2);
}
# print ("address $address $instr\n");
}
if (/Disassembly of section .data:/) { $mode = 1;}
} elsif ($mode == 1) { # Parse data segment
# if (/^\s*(\S\S\S\S\S\S\S\S):\s+(.*)/) { # changed to \t 30 Oct 2021 dmh to fix parsing issue in d_fmadd_b17
if (/^\s*(\S\S\S\S\S\S\S\S):\s+(.*)/) {
$address = &fixadr($1);
# print "addresss $address maxaddress $maxaddress\n";
if ($address > $maxaddress) { $maxaddress = $address; }
#print "test $address $1 $2\n";
my $lineorig = $2;
my $line = $2;
# strip off leading 0x
$line =~ s/^0x//;
# merge chunks with spaces
$line =~ s/(\S)\s(\S)/$1$2/g;
my $linemerge = $line;
# strip off comments
$line =~ /^(\S*)/;
$payload = $1;
# if ($address >= 17520 && $address <= 17552) { # was 12304
# print "Address: $address\n orig: $lineorig \n merge: $linemerge \n line: $line \n payload: $payload\n";
# }
&emitData($address, $payload);
}
if (/Disassembly of section .riscv.attributes:/) { $mode = 2; }
}
}
close(FILE);
# print("maxaddress: $maxaddress\n");
$maxaddress += 32; # pad some zeros at the end
# print("maxaddress: $maxaddress\n");
# print to memory file
if ($fname =~ /rv32/) {
open(MEMFILE, ">$memfile") || die("Can't write $memfile");
for (my $i=0; $i<= $maxaddress; $i = $i + 4) {
for ($j=3; $j>=0; $j--) {
if (defined($memfilebytes[$i+$j])) {
print MEMFILE "$memfilebytes[$i+$j]";
} else {
print MEMFILE "00";
}
}
print MEMFILE "\n";
}
close(MEMFILE);
} else {
open(MEMFILE, ">$memfile") || die("Can't write $memfile");
for (my $i=0; $i<= $maxaddress; $i = $i + 8) {
for ($j=7; $j>=0; $j--) {
my $loc = $i+$j;
# if ($loc >= 17520 && $loc <= 17552) {
# print "loc: $loc val $memfilebytes[$loc]\n";
# }
if (defined($memfilebytes[$loc])) {
print MEMFILE "$memfilebytes[$loc]";
} else {
print MEMFILE "00";
}
}
print MEMFILE "\n";
}
close(MEMFILE);
}
}
}
print("\n");
sub emitData {
# print the data portion of the ELF into a memroy file, including 0s for empty stuff
# deal with endianness
my $address = shift;
my $payload = shift;
# if ($address > 17520 && $address < 17552) { # was 12304
# print("Emitting data. address = $address payload = $payload\n");
# }
my $len = length($payload);
if ($len <= 8) {
# print word or halfword
for(my $i=0; $i<$len/2; $i++) {
my $adr = $address+$i;
my $b = substr($payload, $len-2-2*$i, 2);
$memfilebytes[$adr] = $b;
# if ($address >= 17520 && $address <= 17552) {
# print(" Wrote $b to $adr\n");
# }
# print(" $adr $b\n");
}
} elsif ($len == 12) {
# weird case of three halfwords on line
&emitData($address, substr($payload, 0, 4));
&emitData($address+2, substr($payload, 4, 4));
&emitData($address+4, substr($payload, 8, 4));
} else {
&emitData($address, substr($payload, 0, 8));
&emitData($address+4, substr($payload, 8, $len-8));
}
}
sub fixadr {
# strip off leading 8 from address and convert to decimal
my $adr = shift;
if ($adr =~ s/^8/0/) { return hex($adr); }
else { die("address $adr lacks leading 8\n"); }
}

View File

@ -1,3 +1,4 @@
// abc_cout s
000_00
001_01
010_01

View File

@ -40,18 +40,18 @@ module ahblite (
input logic UnsignedLoadM,
input logic [1:0] AtomicMaskedM,
// Signals from Instruction Cache
input logic [`PA_BITS-1:0] IfuBusAdr,
input logic IfuBusRead,
output logic [`XLEN-1:0] IfuBusHRDATA,
output logic IfuBusAck,
input logic [`PA_BITS-1:0] IFUBusAdr,
input logic IFUBusRead,
output logic [`XLEN-1:0] IFUBusHRDATA,
output logic IFUBusAck,
// Signals from Data Cache
input logic [`PA_BITS-1:0] LsuBusAdr,
input logic LsuBusRead,
input logic LsuBusWrite,
input logic [`XLEN-1:0] LsuBusHWDATA,
output logic [`XLEN-1:0] LsuBusHRDATA,
input logic [2:0] LsuBusSize,
output logic LsuBusAck,
input logic [`PA_BITS-1:0] LSUBusAdr,
input logic LSUBusRead,
input logic LSUBusWrite,
input logic [`XLEN-1:0] LSUBusHWDATA,
output logic [`XLEN-1:0] LSUBusHRDATA,
input logic [2:0] LSUBusSize,
output logic LSUBusAck,
// AHB-Lite external signals
(* mark_debug = "true" *) input logic [`AHBW-1:0] HRDATA,
(* mark_debug = "true" *) input logic HREADY, HRESP,
@ -98,35 +98,35 @@ module ahblite (
// interface that might be used in place of the ahblite.
always_comb
case (BusState)
IDLE: if (LsuBusRead) NextBusState = MEMREAD; // Memory has priority over instructions
else if (LsuBusWrite)NextBusState = MEMWRITE;
else if (IfuBusRead) NextBusState = INSTRREAD;
IDLE: if (LSUBusRead) NextBusState = MEMREAD; // Memory has priority over instructions
else if (LSUBusWrite)NextBusState = MEMWRITE;
else if (IFUBusRead) NextBusState = INSTRREAD;
else NextBusState = IDLE;
MEMREAD: if (~HREADY) NextBusState = MEMREAD;
else if (IfuBusRead) NextBusState = INSTRREAD;
else if (IFUBusRead) NextBusState = INSTRREAD;
else NextBusState = IDLE;
MEMWRITE: if (~HREADY) NextBusState = MEMWRITE;
else if (IfuBusRead) NextBusState = INSTRREAD;
else if (IFUBusRead) NextBusState = INSTRREAD;
else NextBusState = IDLE;
INSTRREAD: if (~HREADY) NextBusState = INSTRREAD;
else NextBusState = IDLE; // if (IfuBusRead still high)
else NextBusState = IDLE; // if (IFUBusRead still high)
default: NextBusState = IDLE;
endcase
// bus outputs
assign #1 GrantData = (NextBusState == MEMREAD) | (NextBusState == MEMWRITE);
assign #1 AccessAddress = (GrantData) ? LsuBusAdr[31:0] : IfuBusAdr[31:0];
assign #1 AccessAddress = (GrantData) ? LSUBusAdr[31:0] : IFUBusAdr[31:0];
assign #1 HADDR = AccessAddress;
assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width; ignored on reads anyway
assign HSIZE = (GrantData) ? {1'b0, LsuBusSize[1:0]} : ISize;
assign HSIZE = (GrantData) ? {1'b0, LSUBusSize[1:0]} : ISize;
assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfH
assign HPROT = 4'b0011; // not used; see Section 3.7
assign HTRANS = (NextBusState != IDLE) ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise
assign HMASTLOCK = 0; // no locking supported
assign HWRITE = NextBusState == MEMWRITE;
// delay write data by one cycle for
flop #(`XLEN) wdreg(HCLK, LsuBusHWDATA, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
flop #(`XLEN) wdreg(HCLK, LSUBusHWDATA, HWDATA); // delay HWDATA by 1 cycle per spec; *** assumes AHBW = XLEN
// delay signals for subword writes
flop #(3) adrreg(HCLK, HADDR[2:0], HADDRD);
flop #(4) sizereg(HCLK, {UnsignedLoadM, HSIZE}, HSIZED);
@ -136,9 +136,9 @@ module ahblite (
// *** assumes AHBW = XLEN
assign IfuBusHRDATA = HRDATA;
assign LsuBusHRDATA = HRDATA;
assign IfuBusAck = (BusState == INSTRREAD) & (NextBusState != INSTRREAD);
assign LsuBusAck = (BusState == MEMREAD) & (NextBusState != MEMREAD) | (BusState == MEMWRITE) & (NextBusState != MEMWRITE);
assign IFUBusHRDATA = HRDATA;
assign LSUBusHRDATA = HRDATA;
assign IFUBusAck = (BusState == INSTRREAD) & (NextBusState != INSTRREAD);
assign LSUBusAck = (BusState == MEMREAD) & (NextBusState != MEMREAD) | (BusState == MEMWRITE) & (NextBusState != MEMWRITE);
endmodule

View File

@ -28,8 +28,8 @@
module hazard(
// Detect hazards
(* mark_debug = "true" *) input logic BPPredWrongE, CSRWritePendingDEM, RetM, TrapM,
(* mark_debug = "true" *) input logic LoadStallD, StoreStallD, MulDivStallD, CSRRdStallD,
(* mark_debug = "true" *) input logic LSUStall, IfuStallF,
(* mark_debug = "true" *) input logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD,
(* mark_debug = "true" *) input logic LSUStall, IFUStallF,
(* mark_debug = "true" *) input logic FPUStallD, FStallD,
(* mark_debug = "true" *) input logic DivBusyE,FDivBusyE,
(* mark_debug = "true" *) input logic EcallFaultM, BreakpointFaultM,
@ -56,10 +56,10 @@ module hazard(
// If any stages are stalled, the first stage that isn't stalled must flush.
assign StallFCause = CSRWritePendingDEM & ~(TrapM | RetM | BPPredWrongE);
assign StallDCause = (LoadStallD | StoreStallD | MulDivStallD | CSRRdStallD | FPUStallD | FStallD) & ~(TrapM | RetM | BPPredWrongE); // stall in decode if instruction is a load/mul/csr dependent on previous
assign StallDCause = (LoadStallD | StoreStallD | MDUStallD | CSRRdStallD | FPUStallD | FStallD) & ~(TrapM | RetM | BPPredWrongE); // stall in decode if instruction is a load/mul/csr dependent on previous
assign StallECause = DivBusyE | FDivBusyE;
assign StallMCause = 0;
assign StallWCause = LSUStall | IfuStallF;
assign StallWCause = LSUStall | IFUStallF;
assign StallF = StallFCause | StallD;
assign StallD = StallDCause | StallE;

View File

@ -44,7 +44,7 @@ module controller(
output logic ALUResultSrcE,
output logic MemReadE, CSRReadE, // for Hazard Unit
output logic [2:0] Funct3E,
output logic MulDivE, W64E,
output logic MDUE, W64E,
output logic JumpE,
// Memory stage control signals
input logic StallM, FlushM,
@ -83,7 +83,7 @@ module controller(
logic ALUOpD;
logic [2:0] ALUControlD;
logic ALUSrcAD, ALUSrcBD;
logic ALUResultSrcD, W64D, MulDivD;
logic ALUResultSrcD, W64D, MDUD;
logic CSRZeroSrcD;
logic CSRReadD;
logic [1:0] AtomicD;
@ -111,7 +111,7 @@ module controller(
// Main Instruction Decoder
always_comb
case(OpD)
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MulDiv_Atomic_Illegal
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MDU_Atomic_Illegal
7'b0000000: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // illegal instruction
7'b0000011: ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // lw
7'b0000111: ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // flw
@ -162,7 +162,7 @@ module controller(
assign IllegalBaseInstrFaultD = ControlsD[0];
assign {RegWriteD, ImmSrcD, ALUSrcAD, ALUSrcBD, MemRWD,
ResultSrcD, BranchD, ALUOpD, JumpD, ALUResultSrcD, W64D, CSRReadD,
PrivilegedD, FenceD, MulDivD, AtomicD, unused} = IllegalIEUInstrFaultD ? `CTRLW'b0 : ControlsD;
PrivilegedD, FenceD, MDUD, AtomicD, unused} = IllegalIEUInstrFaultD ? `CTRLW'b0 : ControlsD;
// *** move Privileged, CSRwrite?? Or move controller out of IEU into datapath and handle all instructions
assign CSRZeroSrcD = InstrD[14] ? (InstrD[19:15] == 0) : (Rs1D == 0); // Is a CSR instruction using zero as the source?
@ -194,8 +194,8 @@ module controller(
// Execute stage pipeline control register and logic
flopenrc #(27) controlregE(clk, reset, FlushE, ~StallE,
{RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, MulDivD, AtomicD, InvalidateICacheD, FlushDCacheD, InstrValidD},
{IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, MulDivE, AtomicE, InvalidateICacheE, FlushDCacheE, InstrValidE});
{RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, InstrValidD},
{IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, InstrValidE});
// Branch Logic
assign {eqE, ltE, ltuE} = FlagsE;

View File

@ -58,7 +58,7 @@ module datapath (
input logic [2:0] ResultSrcW,
output logic [`XLEN-1:0] ReadDataW,
// input logic [`XLEN-1:0] PCLinkW,
input logic [`XLEN-1:0] CSRReadValW, ReadDataM, MulDivResultW,
input logic [`XLEN-1:0] CSRReadValW, ReadDataM, MDUResultW,
// Hazard Unit signals
output logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E,
output logic [4:0] RdE, RdM, RdW
@ -121,7 +121,7 @@ module datapath (
flopenrc #(`XLEN) ResultWReg(clk, reset, FlushW, ~StallW, ResultM, ResultW);
flopenrc #(5) RdWReg(clk, reset, FlushW, ~StallW, RdM, RdW);
flopen #(`XLEN) ReadDataWReg(.clk, .en(~StallW), .d(ReadDataM), .q(ReadDataW));
mux5 #(`XLEN) resultmuxW(ResultW, ReadDataW, CSRReadValW, MulDivResultW, SCResultW, ResultSrcW, WriteDataW);
mux5 #(`XLEN) resultmuxW(ResultW, ReadDataW, CSRReadValW, MDUResultW, SCResultW, ResultSrcW, WriteDataW);
// floating point interactions: fcvt, fp stores
if (`F_SUPPORTED) begin:fpmux

View File

@ -46,7 +46,7 @@ module extend (
3'b100: ExtImmD = {{(`XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
// Store Conditional: zero offset
3'b101: if (`A_SUPPORTED) ExtImmD = 0;
else ExtImmD = undefined;
else ExtImmD = undefined;
default: ExtImmD = undefined; // undefined
endcase
endmodule

View File

@ -28,13 +28,13 @@
module forward(
// Detect hazards
input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
input logic MemReadE, MulDivE, CSRReadE,
input logic MemReadE, MDUE, CSRReadE,
input logic RegWriteM, RegWriteW,
input logic FWriteIntE,
input logic SCE,
// Forwarding controls
output logic [1:0] ForwardAE, ForwardBE,
output logic FPUStallD, LoadStallD, MulDivStallD, CSRRdStallD
output logic FPUStallD, LoadStallD, MDUStallD, CSRRdStallD
);
logic MatchDE;
@ -55,7 +55,6 @@ module forward(
assign MatchDE = (Rs1D == RdE) | (Rs2D == RdE); // Decode-stage instruction source depends on result from execute stage instruction
assign FPUStallD = FWriteIntE & MatchDE;
assign LoadStallD = (MemReadE|SCE) & MatchDE;
assign MulDivStallD = MulDivE & MatchDE;
assign MDUStallD = MDUE & MatchDE;
assign CSRRdStallD = CSRReadE & MatchDE;
endmodule

View File

@ -38,7 +38,7 @@ module ieu (
input logic IllegalFPUInstrE,
input logic [`XLEN-1:0] FWriteDataE,
output logic [`XLEN-1:0] IEUAdrE,
output logic MulDivE, W64E,
output logic MDUE, W64E,
output logic [2:0] Funct3E,
output logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // these are the src outputs before the mux choosing between them and PCE to put in srcA/B
@ -56,7 +56,7 @@ module ieu (
output logic InvalidateICacheM, FlushDCacheM,
// Writeback stage
input logic [`XLEN-1:0] CSRReadValW, ReadDataM, MulDivResultW,
input logic [`XLEN-1:0] CSRReadValW, ReadDataM, MDUResultW,
output logic [4:0] RdW,
output logic [`XLEN-1:0] ReadDataW,
// input logic [`XLEN-1:0] PCLinkW,
@ -64,7 +64,7 @@ module ieu (
// hazards
input logic StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW,
output logic FPUStallD, LoadStallD, MulDivStallD, CSRRdStallD,
output logic FPUStallD, LoadStallD, MDUStallD, CSRRdStallD,
output logic PCSrcE,
output logic CSRReadM, CSRWriteM, PrivilegedM,
output logic CSRWritePendingDEM,
@ -89,68 +89,26 @@ module ieu (
logic JumpE;
controller c(
.clk, .reset,
// Decode stage control signals
.StallD, .FlushD, .InstrD, .ImmSrcD,
.IllegalIEUInstrFaultD, .IllegalBaseInstrFaultD,
// Execute stage control signals
.StallE, .FlushE, .FlagsE, .FWriteIntE,
.PCSrcE, // for datapath and Hazard Unit
.ALUControlE, .ALUSrcAE, .ALUSrcBE,
.ALUResultSrcE,
.MemReadE, .CSRReadE, // for Hazard Unit
.Funct3E, .MulDivE, .W64E,
.JumpE,
// Memory stage control signals
.StallM, .FlushM, .MemRWM,
.CSRReadM, .CSRWriteM, .PrivilegedM,
.SCE, .AtomicE, .AtomicM, .Funct3M,
.RegWriteM, // for Hazard Unit
.InvalidateICacheM, .FlushDCacheM, .InstrValidM,
.FWriteIntM,
// Writeback stage control signals
.StallW, .FlushW,
.RegWriteW, // for datapath and Hazard Unit
.ResultSrcW,
// Stall during CSRs
.CSRWritePendingDEM,
.StoreStallD
);
.clk, .reset, .StallD, .FlushD, .InstrD, .ImmSrcD,
.IllegalIEUInstrFaultD, .IllegalBaseInstrFaultD, .StallE, .FlushE, .FlagsE, .FWriteIntE,
.PCSrcE, .ALUControlE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .MemReadE, .CSRReadE,
.Funct3E, .MDUE, .W64E, .JumpE, .StallM, .FlushM, .MemRWM,
.CSRReadM, .CSRWriteM, .PrivilegedM, .SCE, .AtomicE, .AtomicM, .Funct3M,
.RegWriteM, .InvalidateICacheM, .FlushDCacheM, .InstrValidM, .FWriteIntM,
.StallW, .FlushW, .RegWriteW, .ResultSrcW, .CSRWritePendingDEM, .StoreStallD);
datapath dp(
.clk, .reset,
// Decode stage signals
.ImmSrcD, .InstrD,
// Execute stage signals
.StallE, .FlushE, .ForwardAE, .ForwardBE,
.ALUControlE, .Funct3E, .ALUSrcAE, .ALUSrcBE,
.ALUResultSrcE, .JumpE, .IllegalFPUInstrE,
.FWriteDataE, .PCE, .PCLinkE, .FlagsE,
.IEUAdrE,
.ForwardedSrcAE, .ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B
// Memory stage signals
.StallM, .FlushM, .FWriteIntM, .FIntResM,
.SrcAM, .WriteDataM,
// Writeback stage signals
.StallW, .FlushW, .RegWriteW,
.SquashSCW, .ResultSrcW, .ReadDataW,
// input logic [`XLEN-1:0] PCLinkW,
.CSRReadValW, .ReadDataM, .MulDivResultW,
// Hazard Unit signals
.Rs1D, .Rs2D, .Rs1E, .Rs2E,
.RdE, .RdM, .RdW
);
.clk, .reset, .ImmSrcD, .InstrD, .StallE, .FlushE, .ForwardAE, .ForwardBE,
.ALUControlE, .Funct3E, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .JumpE, .IllegalFPUInstrE,
.FWriteDataE, .PCE, .PCLinkE, .FlagsE, .IEUAdrE, .ForwardedSrcAE, .ForwardedSrcBE,
.StallM, .FlushM, .FWriteIntM, .FIntResM, .SrcAM, .WriteDataM,
.StallW, .FlushW, .RegWriteW, .SquashSCW, .ResultSrcW, .ReadDataW,
.CSRReadValW, .ReadDataM, .MDUResultW, .Rs1D, .Rs2D, .Rs1E, .Rs2E, .RdE, .RdM, .RdW);
forward fw(
.Rs1D, .Rs2D, .Rs1E, .Rs2E, .RdE, .RdM, .RdW,
.MemReadE, .MulDivE, .CSRReadE,
.RegWriteM, .RegWriteW,
.FWriteIntE,
.SCE,
// Forwarding controls
.ForwardAE, .ForwardBE,
.FPUStallD, .LoadStallD, .MulDivStallD, .CSRRdStallD
);
.MemReadE, .MDUE, .CSRReadE, .RegWriteM, .RegWriteW,
.FWriteIntE, .SCE, .ForwardAE, .ForwardBE,
.FPUStallD, .LoadStallD, .MDUStallD, .CSRRdStallD);
endmodule

View File

@ -31,11 +31,11 @@ module ifu (
input logic StallF, StallD, StallE, StallM, StallW,
input logic FlushF, FlushD, FlushE, FlushM, FlushW,
// Bus interface
(* mark_debug = "true" *) input logic [`XLEN-1:0] IfuBusHRDATA,
(* mark_debug = "true" *) input logic IfuBusAck,
(* mark_debug = "true" *) output logic [`PA_BITS-1:0] IfuBusAdr,
(* mark_debug = "true" *) output logic IfuBusRead,
(* mark_debug = "true" *) output logic IfuStallF,
(* mark_debug = "true" *) input logic [`XLEN-1:0] IFUBusHRDATA,
(* mark_debug = "true" *) input logic IFUBusAck,
(* mark_debug = "true" *) output logic [`PA_BITS-1:0] IFUBusAdr,
(* mark_debug = "true" *) output logic IFUBusRead,
(* mark_debug = "true" *) output logic IFUStallF,
(* mark_debug = "true" *) output logic [`XLEN-1:0] PCF,
// Execute
output logic [`XLEN-1:0] PCLinkE,
@ -210,8 +210,8 @@ module ifu (
// *** 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
//assign IFUBusFetch = ~StallD; // *** & ICacheMissF; add later
// assign IFUBusFetch = 1; // *** & ICacheMissF; add later
// conditional
// 1. ram // controlled by `MEM_IROM
@ -229,13 +229,13 @@ module ifu (
logic [LOGWPL-1:0] WordCount;
logic [LINELEN-1:0] ICacheMemWriteData;
logic ICacheBusAck;
logic [`PA_BITS-1:0] LocalIfuBusAdr;
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 [1:0] IFURWF;
assign IFURWF = CacheableF ? 2'b10 : 2'b00;
/* -----\/----- EXCLUDED -----\/-----
icache #(.LINELEN(`ICACHE_LINELENINBITS),
@ -244,7 +244,7 @@ module ifu (
icache(.clk, .reset, .CPUBusy, .IgnoreRequest, .ICacheMemWriteData , .ICacheBusAck,
.ICacheBusAdr, .ICacheStallF, .FinalInstrRawF,
.ICacheFetchLine,
.IfuRWF(IfuRWF), //aways read
.IFURWF(IFURWF), //aways read
.PCNextF(PCNextFMux),
.PCPF(PCPF),
.PCF(PCFMux),
@ -264,7 +264,7 @@ module ifu (
.CacheMiss(),
.CacheAccess(),
.FinalWriteData('0),
.RW(IfuRWF),
.RW(IFURWF),
.Atomic(2'b00),
.FlushCache(1'b0),
.NextAdr(PCNextFMux),
@ -292,23 +292,23 @@ module ifu (
genvar index;
for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer
flopen #(`XLEN) fb(.clk(clk),
.en(IfuBusAck & IfuBusRead & (index == WordCount)),
.d(IfuBusHRDATA),
.en(IFUBusAck & IFUBusRead & (index == WordCount)),
.d(IFUBusHRDATA),
.q(ICacheMemWriteData[(index+1)*`XLEN-1:index*`XLEN]));
end
assign LocalIfuBusAdr = SelUncachedAdr ? PCPF : ICacheBusAdr;
assign IfuBusAdr = ({{`PA_BITS-LOGWPL{1'b0}}, WordCount} << $clog2(`XLEN/8)) + LocalIfuBusAdr;
assign LocalIFUBusAdr = SelUncachedAdr ? PCPF : ICacheBusAdr;
assign IFUBusAdr = ({{`PA_BITS-LOGWPL{1'b0}}, WordCount} << $clog2(`XLEN/8)) + LocalIFUBusAdr;
busfsm #(WordCountThreshold, LOGWPL, `MEM_ICACHE)
busfsm(.clk, .reset, .IgnoreRequest,
.LsuRWM(2'b10), .DCacheFetchLine(ICacheFetchLine), .DCacheWriteLine(1'b0),
.LsuBusAck(IfuBusAck),
.LSURWM(2'b10), .DCacheFetchLine(ICacheFetchLine), .DCacheWriteLine(1'b0),
.LSUBusAck(IFUBusAck),
.CPUBusy, .CacheableM(CacheableF),
.BusStall, .LsuBusWrite(), .LsuBusRead(IfuBusRead), .DCacheBusAck(ICacheBusAck),
.BusStall, .LSUBusWrite(), .LSUBusRead(IFUBusRead), .DCacheBusAck(ICacheBusAck),
.BusCommittedM(), .SelUncachedAdr(SelUncachedAdr), .WordCount);
assign IfuStallF = ICacheStallF | BusStall | SelNextSpill;
assign IFUStallF = ICacheStallF | BusStall | SelNextSpill;
assign CPUBusy = StallF & ~SelNextSpill;
//assign IgnoreRequest = ITLBMissF | ExceptionM | PendingInterruptM;

View File

@ -32,16 +32,16 @@ module busfsm #(parameter integer WordCountThreshold,
input logic reset,
input logic IgnoreRequest,
input logic [1:0] LsuRWM,
input logic [1:0] LSURWM,
input logic DCacheFetchLine,
input logic DCacheWriteLine,
input logic LsuBusAck,
input logic LSUBusAck,
input logic CPUBusy,
input logic CacheableM,
output logic BusStall,
output logic LsuBusWrite,
output logic LsuBusRead,
output logic LSUBusWrite,
output logic LSUBusRead,
output logic DCacheBusAck,
output logic BusCommittedM,
output logic SelUncachedAdr,
@ -49,8 +49,8 @@ module busfsm #(parameter integer WordCountThreshold,
logic UnCachedLsuBusRead;
logic UnCachedLsuBusWrite;
logic UnCachedLSUBusRead;
logic UnCachedLSUBusWrite;
logic CntEn, PreCntEn;
logic CntReset;
logic WordCountFlag;
@ -80,7 +80,7 @@ module busfsm #(parameter integer WordCountThreshold,
assign NextWordCount = WordCount + 1'b1;
assign WordCountFlag = (WordCount == WordCountThreshold[LOGWPL-1:0]);
assign CntEn = PreCntEn & LsuBusAck;
assign CntEn = PreCntEn & LSUBusAck;
assign UnCachedAccess = ~CacheEnabled | ~CacheableM;
@ -91,14 +91,14 @@ module busfsm #(parameter integer WordCountThreshold,
always_comb begin
case(BusCurrState)
STATE_BUS_READY: if(IgnoreRequest) BusNextState = STATE_BUS_READY;
else if(LsuRWM[0] & (UnCachedAccess)) BusNextState = STATE_BUS_UNCACHED_WRITE;
else if(LsuRWM[1] & (UnCachedAccess)) BusNextState = STATE_BUS_UNCACHED_READ;
else if(LSURWM[0] & (UnCachedAccess)) BusNextState = STATE_BUS_UNCACHED_WRITE;
else if(LSURWM[1] & (UnCachedAccess)) BusNextState = STATE_BUS_UNCACHED_READ;
else if(DCacheFetchLine) BusNextState = STATE_BUS_FETCH;
else if(DCacheWriteLine) BusNextState = STATE_BUS_WRITE;
else BusNextState = STATE_BUS_READY;
STATE_BUS_UNCACHED_WRITE: if(LsuBusAck) BusNextState = STATE_BUS_UNCACHED_WRITE_DONE;
STATE_BUS_UNCACHED_WRITE: if(LSUBusAck) BusNextState = STATE_BUS_UNCACHED_WRITE_DONE;
else BusNextState = STATE_BUS_UNCACHED_WRITE;
STATE_BUS_UNCACHED_READ: if(LsuBusAck) BusNextState = STATE_BUS_UNCACHED_READ_DONE;
STATE_BUS_UNCACHED_READ: if(LSUBusAck) BusNextState = STATE_BUS_UNCACHED_READ_DONE;
else BusNextState = STATE_BUS_UNCACHED_READ;
STATE_BUS_UNCACHED_WRITE_DONE: if(CPUBusy) BusNextState = STATE_BUS_CPU_BUSY;
else BusNextState = STATE_BUS_READY;
@ -106,9 +106,9 @@ module busfsm #(parameter integer WordCountThreshold,
else BusNextState = STATE_BUS_READY;
STATE_BUS_CPU_BUSY: if(CPUBusy) BusNextState = STATE_BUS_CPU_BUSY;
else BusNextState = STATE_BUS_READY;
STATE_BUS_FETCH: if (WordCountFlag & LsuBusAck) BusNextState = STATE_BUS_READY;
STATE_BUS_FETCH: if (WordCountFlag & LSUBusAck) BusNextState = STATE_BUS_READY;
else BusNextState = STATE_BUS_FETCH;
STATE_BUS_WRITE: if(WordCountFlag & LsuBusAck) BusNextState = STATE_BUS_READY;
STATE_BUS_WRITE: if(WordCountFlag & LSUBusAck) BusNextState = STATE_BUS_READY;
else BusNextState = STATE_BUS_WRITE;
default: BusNextState = STATE_BUS_READY;
endcase
@ -116,24 +116,24 @@ module busfsm #(parameter integer WordCountThreshold,
assign CntReset = BusCurrState == STATE_BUS_READY;
assign BusStall = (BusCurrState == STATE_BUS_READY & ~IgnoreRequest & ((UnCachedAccess & (|LsuRWM)) | DCacheFetchLine | DCacheWriteLine)) |
assign BusStall = (BusCurrState == STATE_BUS_READY & ~IgnoreRequest & ((UnCachedAccess & (|LSURWM)) | DCacheFetchLine | DCacheWriteLine)) |
(BusCurrState == STATE_BUS_UNCACHED_WRITE) |
(BusCurrState == STATE_BUS_UNCACHED_READ) |
(BusCurrState == STATE_BUS_FETCH) |
(BusCurrState == STATE_BUS_WRITE);
assign PreCntEn = BusCurrState == STATE_BUS_FETCH | BusCurrState == STATE_BUS_WRITE;
assign UnCachedLsuBusWrite = (BusCurrState == STATE_BUS_READY & UnCachedAccess & (LsuRWM[0])) |
assign UnCachedLSUBusWrite = (BusCurrState == STATE_BUS_READY & UnCachedAccess & (LSURWM[0])) |
(BusCurrState == STATE_BUS_UNCACHED_WRITE);
assign LsuBusWrite = UnCachedLsuBusWrite | (BusCurrState == STATE_BUS_WRITE);
assign LSUBusWrite = UnCachedLSUBusWrite | (BusCurrState == STATE_BUS_WRITE);
assign UnCachedLsuBusRead = (BusCurrState == STATE_BUS_READY & UnCachedAccess & (|LsuRWM[1])) |
assign UnCachedLSUBusRead = (BusCurrState == STATE_BUS_READY & UnCachedAccess & (|LSURWM[1])) |
(BusCurrState == STATE_BUS_UNCACHED_READ);
assign LsuBusRead = UnCachedLsuBusRead | (BusCurrState == STATE_BUS_FETCH) | (BusCurrState == STATE_BUS_READY & DCacheFetchLine);
assign LSUBusRead = UnCachedLSUBusRead | (BusCurrState == STATE_BUS_FETCH) | (BusCurrState == STATE_BUS_READY & DCacheFetchLine);
assign DCacheBusAck = (BusCurrState == STATE_BUS_FETCH & WordCountFlag & LsuBusAck) |
(BusCurrState == STATE_BUS_WRITE & WordCountFlag & LsuBusAck);
assign DCacheBusAck = (BusCurrState == STATE_BUS_FETCH & WordCountFlag & LSUBusAck) |
(BusCurrState == STATE_BUS_WRITE & WordCountFlag & LSUBusAck);
assign BusCommittedM = BusCurrState != STATE_BUS_READY;
assign SelUncachedAdr = (BusCurrState == STATE_BUS_READY & (|LsuRWM & UnCachedAccess)) |
assign SelUncachedAdr = (BusCurrState == STATE_BUS_READY & (|LSURWM & UnCachedAccess)) |
(BusCurrState == STATE_BUS_UNCACHED_READ |
BusCurrState == STATE_BUS_UNCACHED_READ_DONE |
BusCurrState == STATE_BUS_UNCACHED_WRITE |

View File

@ -31,10 +31,10 @@ module lrsc
input logic clk, reset,
input logic FlushW, CPUBusy,
input logic MemReadM,
input logic [1:0] PreLsuRWM,
output logic [1:0] LsuRWM,
input logic [1:0] LsuAtomicM,
input logic [`PA_BITS-1:0] LsuPAdrM, // from mmu to dcache
input logic [1:0] PreLSURWM,
output logic [1:0] LSURWM,
input logic [1:0] LSUAtomicM,
input logic [`PA_BITS-1:0] LSUPAdrM, // from mmu to dcache
output logic SquashSCW
);
// Handle atomic load reserved / store conditional
@ -43,17 +43,17 @@ module lrsc
logic lrM, scM, WriteAdrMatchM;
logic SquashSCM;
assign lrM = MemReadM & LsuAtomicM[0];
assign scM = PreLsuRWM[0] & LsuAtomicM[0];
assign WriteAdrMatchM = PreLsuRWM[0] & (LsuPAdrM[`PA_BITS-1:2] == ReservationPAdrW) & ReservationValidW;
assign lrM = MemReadM & LSUAtomicM[0];
assign scM = PreLSURWM[0] & LSUAtomicM[0];
assign WriteAdrMatchM = PreLSURWM[0] & (LSUPAdrM[`PA_BITS-1:2] == ReservationPAdrW) & ReservationValidW;
assign SquashSCM = scM & ~WriteAdrMatchM;
assign LsuRWM = SquashSCM ? 2'b00 : PreLsuRWM;
assign LSURWM = SquashSCM ? 2'b00 : PreLSURWM;
always_comb begin // ReservationValidM (next value of valid reservation)
if (lrM) ReservationValidM = 1; // set valid on load reserve
else if (scM | WriteAdrMatchM) ReservationValidM = 0; // clear valid on store to same address or any sc
else ReservationValidM = ReservationValidW; // otherwise don't change valid
end
flopenrc #(`PA_BITS-2) resadrreg(clk, reset, FlushW, lrM, LsuPAdrM[`PA_BITS-1:2], ReservationPAdrW); // could drop clear on this one but not valid
flopenrc #(`PA_BITS-2) resadrreg(clk, reset, FlushW, lrM, LSUPAdrM[`PA_BITS-1:2], ReservationPAdrW); // could drop clear on this one but not valid
flopenrc #(1) resvldreg(clk, reset, FlushW, lrM, ReservationValidM, ReservationValidW);
flopenrc #(1) squashreg(clk, reset, FlushW, ~CPUBusy, SquashSCM, SquashSCW);
endmodule

View File

@ -63,13 +63,13 @@ module lsu
output logic StoreMisalignedFaultM, StoreAccessFaultM,
// connect to ahb
(* mark_debug = "true" *) output logic [`PA_BITS-1:0] LsuBusAdr,
(* mark_debug = "true" *) output logic LsuBusRead,
(* mark_debug = "true" *) output logic LsuBusWrite,
(* mark_debug = "true" *) input logic LsuBusAck,
(* mark_debug = "true" *) input logic [`XLEN-1:0] LsuBusHRDATA,
(* mark_debug = "true" *) output logic [`XLEN-1:0] LsuBusHWDATA,
(* mark_debug = "true" *) output logic [2:0] LsuBusSize,
(* mark_debug = "true" *) output logic [`PA_BITS-1:0] LSUBusAdr,
(* mark_debug = "true" *) output logic LSUBusRead,
(* mark_debug = "true" *) output logic LSUBusWrite,
(* mark_debug = "true" *) input logic LSUBusAck,
(* mark_debug = "true" *) input logic [`XLEN-1:0] LSUBusHRDATA,
(* mark_debug = "true" *) output logic [`XLEN-1:0] LSUBusHWDATA,
(* mark_debug = "true" *) output logic [2:0] LSUBusSize,
// mmu management
@ -90,18 +90,18 @@ module lsu
logic DTLBPageFaultM;
logic [`PA_BITS-1:0] LsuPAdrM; // from mmu to dcache
logic [`PA_BITS-1:0] LSUPAdrM; // from mmu to dcache
logic [`XLEN+1:0] IEUAdrExtM;
logic DTLBMissM;
logic DTLBWriteM;
logic [1:0] LsuRWM;
logic [1:0] PreLsuRWM;
logic [2:0] LsuFunct3M;
logic [7:0] LsuFunct7M;
logic [1:0] LsuAtomicM;
(* mark_debug = "true" *) logic [`PA_BITS-1:0] PreLsuPAdrM, LocalLsuBusAdr;
logic [11:0] PreLsuAdrE, LsuAdrE;
logic [1:0] LSURWM;
logic [1:0] PreLSURWM;
logic [2:0] LSUFunct3M;
logic [6:0] LSUFunct7M;
logic [1:0] LSUAtomicM;
(* mark_debug = "true" *) logic [`PA_BITS-1:0] PreLSUPAdrM, LocalLSUBusAdr;
logic [11:0] PreLSUAdrE, LSUAdrE;
logic CPUBusy;
logic MemReadM;
logic DCacheStall;
@ -145,12 +145,12 @@ module lsu
// arbiter between IEU and hptw
// multiplex the outputs to LSU
mux2 #(2) rwmux(MemRWM, {HPTWRead, 1'b0}, SelHPTW, PreLsuRWM);
mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LsuFunct3M);
mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LsuFunct7M);
mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LsuAtomicM);
mux2 #(12) adremux(IEUAdrE[11:0], HPTWAdr[11:0], SelHPTW, PreLsuAdrE);
mux2 #(`PA_BITS) lsupadrmux(IEUAdrExtM[`PA_BITS-1:0], HPTWAdr, SelHPTW, PreLsuPAdrM);
mux2 #(2) rwmux(MemRWM, {HPTWRead, 1'b0}, SelHPTW, PreLSURWM);
mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M);
mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M);
mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LSUAtomicM);
mux2 #(12) adremux(IEUAdrE[11:0], HPTWAdr[11:0], SelHPTW, PreLSUAdrE);
mux2 #(`PA_BITS) lsupadrmux(IEUAdrExtM[`PA_BITS-1:0], HPTWAdr, SelHPTW, PreLSUPAdrM);
// always block interrupts when using the hardware page table walker.
assign CPUBusy = StallW & ~SelHPTW;
@ -160,17 +160,17 @@ module lsu
//flop #(`PA_BITS) HPTWAdrMReg(clk, HPTWAdr, HPTWAdrM); // delay HPTWAdrM by a cycle
// Specify which type of page fault is occurring
assign DTLBLoadPageFaultM = DTLBPageFaultM & PreLsuRWM[1];
assign DTLBStorePageFaultM = DTLBPageFaultM & PreLsuRWM[0];
assign DTLBLoadPageFaultM = DTLBPageFaultM & PreLSURWM[1];
assign DTLBStorePageFaultM = DTLBPageFaultM & PreLSURWM[0];
// When replaying CPU memory request after PTW select the IEUAdrM for correct address.
assign LsuAdrE = SelReplayCPURequest ? IEUAdrM[11:0] : PreLsuAdrE;
assign LSUAdrE = SelReplayCPURequest ? IEUAdrM[11:0] : PreLSUAdrE;
end // if (`MEM_VIRTMEM)
else begin
assign InterlockStall = 1'b0;
assign LsuAdrE = PreLsuAdrE;
assign LSUAdrE = PreLSUAdrE;
assign SelHPTW = 1'b0;
assign IgnoreRequest = 1'b0;
@ -179,12 +179,12 @@ module lsu
assign DTLBWriteM = 1'b0;
assign ITLBWriteF = 1'b0;
assign PreLsuRWM = MemRWM;
assign LsuFunct3M = Funct3M;
assign LsuFunct7M = Funct7M;
assign LsuAtomicM = AtomicM;
assign PreLsuAdrE = IEUAdrE[11:0];
assign PreLsuPAdrM = IEUAdrExtM;
assign PreLSURWM = MemRWM;
assign LSUFunct3M = Funct3M;
assign LSUFunct7M = Funct7M;
assign LSUAtomicM = AtomicM;
assign PreLSUAdrE = IEUAdrE[11:0];
assign PreLSUPAdrM = IEUAdrExtM;
assign CPUBusy = StallW;
assign DTLBLoadPageFaultM = 1'b0;
@ -207,21 +207,21 @@ module lsu
mmu #(.TLB_ENTRIES(`DTLB_ENTRIES), .IMMU(0))
dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
.PrivilegeModeW, .DisableTranslation(SelHPTW),
.PAdr(PreLsuPAdrM),
.PAdr(PreLSUPAdrM),
.VAdr(IEUAdrM),
.Size(LsuFunct3M[1:0]),
.Size(LSUFunct3M[1:0]),
.PTE,
.PageTypeWriteVal(PageType),
.TLBWrite(DTLBWriteM),
.TLBFlush(DTLBFlushM),
.PhysicalAddress(LsuPAdrM),
.PhysicalAddress(LSUPAdrM),
.TLBMiss(DTLBMissM),
.Cacheable(CacheableM),
.Idempotent(), .AtomicAllowed(),
.TLBPageFault(DTLBPageFaultM),
.InstrAccessFaultF(), .LoadAccessFaultM, .StoreAccessFaultM,
.AtomicAccessM(1'b0), .ExecuteAccessF(1'b0), /// atomicaccessm is probably a bug
.WriteAccessM(PreLsuRWM[0]), .ReadAccessM(PreLsuRWM[1]),
.WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]),
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW
); // *** the pma/pmp instruction access faults don't really matter here. is it possible to parameterize which outputs exist?
@ -240,7 +240,7 @@ module lsu
assign StoreMisalignedFaultM = DataMisalignedM & MemRWM[0];
end else begin
assign LsuPAdrM = PreLsuPAdrM;
assign LSUPAdrM = PreLSUPAdrM;
assign DTLBMissM = 0;
assign CacheableM = 1;
assign DTLBPageFaultM = 0;
@ -252,14 +252,14 @@ module lsu
assign LSUStall = DCacheStall | InterlockStall | BusStall;
// use PreLsu as prefix for lrsc
// use PreLSU as prefix for lrsc
if (`A_SUPPORTED) begin:lrsc
assign MemReadM = PreLsuRWM[1] & ~(IgnoreRequest) & ~DTLBMissM;
lrsc lrsc(.clk, .reset, .FlushW, .CPUBusy, .MemReadM, .PreLsuRWM, .LsuAtomicM, .LsuPAdrM,
.SquashSCW, .LsuRWM);
assign MemReadM = PreLSURWM[1] & ~(IgnoreRequest) & ~DTLBMissM;
lrsc lrsc(.clk, .reset, .FlushW, .CPUBusy, .MemReadM, .PreLSURWM, .LSUAtomicM, .LSUPAdrM,
.SquashSCW, .LSURWM);
end else begin:lrsc
assign SquashSCW = 0;
assign LsuRWM = PreLsuRWM;
assign LSURWM = PreLSURWM;
end
@ -279,7 +279,7 @@ module lsu
// temp
logic [`XLEN-1:0] FinalAMOWriteDataM, FinalWriteDataM;
(* mark_debug = "true" *) logic [`XLEN-1:0] PreLsuBusHWDATA;
(* mark_debug = "true" *) logic [`XLEN-1:0] PreLSUBusHWDATA;
logic [`XLEN-1:0] ReadDataWordM;
logic [LINELEN-1:0] DCacheMemWriteData;
@ -303,8 +303,8 @@ module lsu
cache #(.LINELEN(`DCACHE_LINELENINBITS), .NUMLINES(`DCACHE_WAYSIZEINBYTES*8/LINELEN),
.NUMWAYS(`DCACHE_NUMWAYS), .DCACHE(1))
dcache(.clk, .reset, .CPUBusy,
.RW(CacheableM ? LsuRWM : 2'b00), .FlushCache(FlushDCacheM), .Atomic(CacheableM ? LsuAtomicM : 2'b00),
.NextAdr(LsuAdrE), .PAdr(LsuPAdrM),
.RW(CacheableM ? LSURWM : 2'b00), .FlushCache(FlushDCacheM), .Atomic(CacheableM ? LSUAtomicM : 2'b00),
.NextAdr(LSUAdrE), .PAdr(LSUPAdrM),
.FinalWriteData(FinalWriteDataM), .ReadDataWord(ReadDataWordM), .CacheStall(DCacheStall),
.CacheMiss(DCacheMiss), .CacheAccess(DCacheAccess),
.IgnoreRequest, .CacheCommitted(DCacheCommittedM),
@ -333,23 +333,23 @@ module lsu
// sub word selection for read and writes and optional amo alu.
// finally swr
subwordread subwordread(.ReadDataWordMuxM,
.LsuPAdrM(LsuPAdrM[2:0]),
.Funct3M(LsuFunct3M),
.LSUPAdrM(LSUPAdrM[2:0]),
.Funct3M(LSUFunct3M),
.ReadDataM);
if (`A_SUPPORTED) begin : amo
logic [`XLEN-1:0] AMOResult;
amoalu amoalu(.srca(ReadDataM), .srcb(WriteDataM), .funct(LsuFunct7M), .width(LsuFunct3M[1:0]),
amoalu amoalu(.srca(ReadDataM), .srcb(WriteDataM), .funct(LSUFunct7M), .width(LSUFunct3M[1:0]),
.result(AMOResult));
mux2 #(`XLEN) wdmux(WriteDataM, AMOResult, LsuAtomicM[1], FinalAMOWriteDataM);
mux2 #(`XLEN) wdmux(WriteDataM, AMOResult, LSUAtomicM[1], FinalAMOWriteDataM);
end else
assign FinalAMOWriteDataM = WriteDataM;
// this might only get instantiated if there is a dcache or dtim.
// There is a copy in the ebu.
subwordwrite subwordwrite(.HRDATA(ReadDataWordM),
.HADDRD(LsuPAdrM[2:0]),
.HSIZED({LsuFunct3M[2], 1'b0, LsuFunct3M[1:0]}),
.HADDRD(LSUPAdrM[2:0]),
.HSIZED({LSUFunct3M[2], 1'b0, LSUFunct3M[1:0]}),
.HWDATAIN(FinalAMOWriteDataM),
.HWDATA(FinalWriteDataM));
@ -362,22 +362,22 @@ module lsu
genvar index;
for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer
flopen #(`XLEN) fb(.clk,
.en(LsuBusAck & LsuBusRead & (index == WordCount)),
.d(LsuBusHRDATA),
.en(LSUBusAck & LSUBusRead & (index == WordCount)),
.d(LSUBusHRDATA),
.q(DCacheMemWriteData[(index+1)*`XLEN-1:index*`XLEN]));
end
assign LocalLsuBusAdr = SelUncachedAdr ? LsuPAdrM : DCacheBusAdr ;
assign LsuBusAdr = ({{`PA_BITS-LOGWPL{1'b0}}, WordCount} << $clog2(`XLEN/8)) + LocalLsuBusAdr;
assign PreLsuBusHWDATA = ReadDataLineSetsM[WordCount];
assign LsuBusHWDATA = SelUncachedAdr ? WriteDataM : PreLsuBusHWDATA; // *** why is this not FinalWriteDataM? which does not work.
assign LocalLSUBusAdr = SelUncachedAdr ? LSUPAdrM : DCacheBusAdr ;
assign LSUBusAdr = ({{`PA_BITS-LOGWPL{1'b0}}, WordCount} << $clog2(`XLEN/8)) + LocalLSUBusAdr;
assign PreLSUBusHWDATA = ReadDataLineSetsM[WordCount];
assign LSUBusHWDATA = SelUncachedAdr ? WriteDataM : PreLSUBusHWDATA; // *** why is this not FinalWriteDataM? which does not work.
if (`XLEN == 32) assign LsuBusSize = SelUncachedAdr ? LsuFunct3M : 3'b010;
else assign LsuBusSize = SelUncachedAdr ? LsuFunct3M : 3'b011;
if (`XLEN == 32) assign LSUBusSize = SelUncachedAdr ? LSUFunct3M : 3'b010;
else assign LSUBusSize = SelUncachedAdr ? LSUFunct3M : 3'b011;
busfsm #(WordCountThreshold, LOGWPL, `MEM_DCACHE)
busfsm(.clk, .reset, .IgnoreRequest, .LsuRWM, .DCacheFetchLine, .DCacheWriteLine,
.LsuBusAck, .CPUBusy, .CacheableM, .BusStall, .LsuBusWrite, .LsuBusRead,
busfsm(.clk, .reset, .IgnoreRequest, .LSURWM, .DCacheFetchLine, .DCacheWriteLine,
.LSUBusAck, .CPUBusy, .CacheableM, .BusStall, .LSUBusWrite, .LSUBusRead,
.DCacheBusAck, .BusCommittedM, .SelUncachedAdr, .WordCount);
endmodule

View File

@ -28,7 +28,7 @@
module subwordread
(
input logic [`XLEN-1:0] ReadDataWordMuxM,
input logic [2:0] LsuPAdrM,
input logic [2:0] LSUPAdrM,
input logic [2:0] Funct3M,
output logic [`XLEN-1:0] ReadDataM
);
@ -41,7 +41,7 @@ module subwordread
if (`XLEN == 64) begin:swrmux
// ByteMe mux
always_comb
case(LsuPAdrM[2:0])
case(LSUPAdrM[2:0])
3'b000: ByteM = ReadDataWordMuxM[7:0];
3'b001: ByteM = ReadDataWordMuxM[15:8];
3'b010: ByteM = ReadDataWordMuxM[23:16];
@ -54,7 +54,7 @@ module subwordread
// halfword mux
always_comb
case(LsuPAdrM[2:1])
case(LSUPAdrM[2:1])
2'b00: HalfwordM = ReadDataWordMuxM[15:0];
2'b01: HalfwordM = ReadDataWordMuxM[31:16];
2'b10: HalfwordM = ReadDataWordMuxM[47:32];
@ -64,7 +64,7 @@ module subwordread
logic [31:0] WordM;
always_comb
case(LsuPAdrM[2])
case(LSUPAdrM[2])
1'b0: WordM = ReadDataWordMuxM[31:0];
1'b1: WordM = ReadDataWordMuxM[63:32];
endcase
@ -84,7 +84,7 @@ module subwordread
end else begin:swrmux // 32-bit
// byte mux
always_comb
case(LsuPAdrM[1:0])
case(LSUPAdrM[1:0])
2'b00: ByteM = ReadDataWordMuxM[7:0];
2'b01: ByteM = ReadDataWordMuxM[15:8];
2'b10: ByteM = ReadDataWordMuxM[23:16];
@ -93,7 +93,7 @@ module subwordread
// halfword mux
always_comb
case(LsuPAdrM[1])
case(LSUPAdrM[1])
1'b0: HalfwordM = ReadDataWordMuxM[15:0];
1'b1: HalfwordM = ReadDataWordMuxM[31:16];
endcase

View File

@ -57,7 +57,5 @@ module tlbcam #(parameter TLB_ENTRIES = 8,
.WriteEnable(WriteEnables), .PageTypeRead, .Match(Matches));
assign CAMHit = |Matches & ~TLBFlush;
or_rows #(TLB_ENTRIES,2) PageTypeOr(PageTypeRead, HitPageType);
//assign HitPageType = PageTypeRead.or; // applies OR to elements of the (TLB_ENTRIES x 2) array to get 2-bit result
endmodule

View File

@ -47,6 +47,7 @@ module tlblru #(parameter TLB_ENTRIES = 8) (
assign RUBitsAccessed = AccessLines | RUBits;
assign AllUsed = &RUBitsAccessed; // if all recently used, then clear to none
assign RUBitsNext = AllUsed ? 0 : RUBitsAccessed;
// enable must be ORd with TLBFlush to ensure flop fires on a flush. DH 7/8/21
flopenrc #(TLB_ENTRIES) lrustate(clk, reset, TLBFlush, (CAMHit | TLBWrite), RUBitsNext, RUBits);
// *** seems like enable must be ORd with TLBFlush to ensure flop fires on a flush. DH 7/8/21
endmodule

View File

@ -31,16 +31,16 @@ module muldiv (
// input logic [`XLEN-1:0] SrcAE, SrcBE,
input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B
input logic [2:0] Funct3E, Funct3M,
input logic MulDivE, W64E,
input logic MDUE, W64E,
// Writeback stage
output logic [`XLEN-1:0] MulDivResultW,
output logic [`XLEN-1:0] MDUResultW,
// Divide Done
output logic DivBusyE,
// hazards
input logic StallM, StallW, FlushM, FlushW
);
logic [`XLEN-1:0] MulDivResultM;
logic [`XLEN-1:0] MDUResultM;
logic [`XLEN-1:0] PrelimResultM;
logic [`XLEN-1:0] QuotM, RemM;
logic [`XLEN*2-1:0] ProdM;
@ -54,7 +54,7 @@ module muldiv (
// Divide
// Start a divide when a new division instruction is received and the divider isn't already busy or finishing
assign DivE = MulDivE & Funct3E[2];
assign DivE = MDUE & Funct3E[2];
assign DivSignedE = ~Funct3E[0];
intdivrestoring div(.clk, .reset, .StallM, .DivSignedE, .W64E, .DivE,
.ForwardedSrcAE, .ForwardedSrcBE, .DivBusyE, .QuotM, .RemM);
@ -75,13 +75,13 @@ module muldiv (
// Handle sign extension for W-type instructions
flopenrc #(1) W64MReg(clk, reset, FlushM, ~StallM, W64E, W64M);
if (`XLEN == 64) begin:resmux // RV64 has W-type instructions
assign MulDivResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM;
assign MDUResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM;
end else begin:resmux // RV32 has no W-type instructions
assign MulDivResultM = PrelimResultM;
assign MDUResultM = PrelimResultM;
end
// Writeback stage pipeline register
flopenrc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, ~StallW, MulDivResultM, MulDivResultW);
flopenrc #(`XLEN) MDUResultWReg(clk, reset, FlushW, ~StallW, MDUResultM, MDUResultW);
endmodule // muldiv

View File

@ -56,7 +56,7 @@ module wallypipelinedhart (
(* mark_debug = "true" *) logic TrapM;
// new signals that must connect through DP
logic MulDivE, W64E;
logic MDUE, W64E;
logic CSRReadM, CSRWriteM, PrivilegedM;
logic [1:0] AtomicE;
logic [1:0] AtomicM;
@ -68,7 +68,7 @@ module wallypipelinedhart (
(* mark_debug = "true" *) logic [31:0] InstrM;
logic [`XLEN-1:0] PCF, PCD, PCE, PCLinkE;
(* mark_debug = "true" *) logic [`XLEN-1:0] PCM;
logic [`XLEN-1:0] CSRReadValW, MulDivResultW;
logic [`XLEN-1:0] CSRReadValW, MDUResultW;
logic [`XLEN-1:0] PrivilegedNextPCM;
(* mark_debug = "true" *) logic [1:0] MemRWM;
(* mark_debug = "true" *) logic InstrValidM;
@ -82,7 +82,7 @@ module wallypipelinedhart (
logic PCSrcE;
logic CSRWritePendingDEM;
logic DivBusyE;
logic LoadStallD, StoreStallD, MulDivStallD, CSRRdStallD;
logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD;
logic SquashSCW;
// floating point unit signals
logic [2:0] FRM_REGW;
@ -113,7 +113,7 @@ module wallypipelinedhart (
var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0];
// IMem stalls
logic IfuStallF;
logic IFUStallF;
logic LSUStall;
@ -128,18 +128,18 @@ module wallypipelinedhart (
logic CommittedM;
// AHB ifu interface
logic [`PA_BITS-1:0] IfuBusAdr;
logic [`XLEN-1:0] IfuBusHRDATA;
logic IfuBusRead;
logic IfuBusAck;
logic [`PA_BITS-1:0] IFUBusAdr;
logic [`XLEN-1:0] IFUBusHRDATA;
logic IFUBusRead;
logic IFUBusAck;
// AHB LSU interface
logic [`PA_BITS-1:0] LsuBusAdr;
logic LsuBusRead;
logic LsuBusWrite;
logic LsuBusAck;
logic [`XLEN-1:0] LsuBusHRDATA;
logic [`XLEN-1:0] LsuBusHWDATA;
logic [`PA_BITS-1:0] LSUBusAdr;
logic LSUBusRead;
logic LSUBusWrite;
logic LSUBusAck;
logic [`XLEN-1:0] LSUBusHRDATA;
logic [`XLEN-1:0] LSUBusHWDATA;
logic BPPredWrongE;
logic BPPredDirWrongM;
@ -148,7 +148,7 @@ module wallypipelinedhart (
logic BPPredClassNonCFIWrongM;
logic [4:0] InstrClassM;
logic InstrAccessFaultF;
logic [2:0] LsuBusSize;
logic [2:0] LSUBusSize;
logic ExceptionM;
logic PendingInterruptM;
@ -164,8 +164,8 @@ module wallypipelinedhart (
.ExceptionM, .PendingInterruptM,
// Fetch
.IfuBusHRDATA, .IfuBusAck, .PCF, .IfuBusAdr,
.IfuBusRead, .IfuStallF,
.IFUBusHRDATA, .IFUBusAck, .PCF, .IFUBusAdr,
.IFUBusRead, .IFUStallF,
// Execute
.PCLinkE, .PCSrcE, .IEUAdrE, .PCE,
@ -206,7 +206,7 @@ module wallypipelinedhart (
// Execute Stage interface
.PCE, .PCLinkE, .FWriteIntE, .IllegalFPUInstrE,
.FWriteDataE, .IEUAdrE, .MulDivE, .W64E,
.FWriteDataE, .IEUAdrE, .MDUE, .W64E,
.Funct3E, .ForwardedSrcAE, .ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B
// Memory stage interface
@ -220,14 +220,14 @@ module wallypipelinedhart (
.RdM, .FIntResM, .InvalidateICacheM, .FlushDCacheM,
// Writeback stage
.CSRReadValW, .ReadDataM, .MulDivResultW,
.CSRReadValW, .ReadDataM, .MDUResultW,
.RdW, .ReadDataW,
.InstrValidM,
// hazards
.StallD, .StallE, .StallM, .StallW,
.FlushD, .FlushE, .FlushM, .FlushW,
.FPUStallD, .LoadStallD, .MulDivStallD, .CSRRdStallD,
.FPUStallD, .LoadStallD, .MDUStallD, .CSRRdStallD,
.PCSrcE,
.CSRReadM, .CSRWriteM, .PrivilegedM,
.CSRWritePendingDEM, .StoreStallD
@ -246,8 +246,8 @@ module wallypipelinedhart (
.IEUAdrE, .IEUAdrM, .WriteDataM,
.ReadDataM, .FlushDCacheM,
// connected to ahb (all stay the same)
.LsuBusAdr, .LsuBusRead, .LsuBusWrite, .LsuBusAck,
.LsuBusHRDATA, .LsuBusHWDATA, .LsuBusSize,
.LSUBusAdr, .LSUBusRead, .LSUBusWrite, .LSUBusAck,
.LSUBusHRDATA, .LSUBusHWDATA, .LSUBusSize,
// connect to csr or privilege and stay the same.
.PrivilegeModeW, // connects to csr
@ -277,13 +277,13 @@ module wallypipelinedhart (
ahblite ebu(// IFU connections
.clk, .reset,
.UnsignedLoadM(1'b0), .AtomicMaskedM(2'b00),
.IfuBusAdr,
.IfuBusRead, .IfuBusHRDATA, .IfuBusAck,
.IFUBusAdr,
.IFUBusRead, .IFUBusHRDATA, .IFUBusAck,
// Signals from Data Cache
.LsuBusAdr, .LsuBusRead, .LsuBusWrite, .LsuBusHWDATA,
.LsuBusHRDATA,
.LsuBusSize,
.LsuBusAck,
.LSUBusAdr, .LSUBusRead, .LSUBusWrite, .LSUBusHWDATA,
.LSUBusHRDATA,
.LSUBusSize,
.LSUBusAck,
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn,
.HADDR, .HWDATA, .HWRITE, .HSIZE, .HBURST,
@ -293,8 +293,8 @@ module wallypipelinedhart (
hazard hzu(
.BPPredWrongE, .CSRWritePendingDEM, .RetM, .TrapM,
.LoadStallD, .StoreStallD, .MulDivStallD, .CSRRdStallD,
.LSUStall, .IfuStallF,
.LoadStallD, .StoreStallD, .MDUStallD, .CSRRdStallD,
.LSUStall, .IFUStallF,
.FPUStallD, .FStallD,
.DivBusyE, .FDivBusyE,
.EcallFaultM, .BreakpointFaultM,
@ -347,12 +347,12 @@ module wallypipelinedhart (
muldiv mdu(
.clk, .reset,
.ForwardedSrcAE, .ForwardedSrcBE,
.Funct3E, .Funct3M, .MulDivE, .W64E,
.MulDivResultW, .DivBusyE,
.Funct3E, .Funct3M, .MDUE, .W64E,
.MDUResultW, .DivBusyE,
.StallM, .StallW, .FlushM, .FlushW
);
end else begin // no M instructions supported
assign MulDivResultW = 0;
assign MDUResultW = 0;
assign DivBusyE = 0;
end

View File

@ -438,7 +438,7 @@ module testbench;
end \
if(`"STAGE`"=="M") begin \
// override on special conditions \
if (dut.hart.lsu.LsuPAdrM == 'h10000005) \
if (dut.hart.lsu.LSUPAdrM == 'h10000005) \
//$display("%tns, %d instrs: Overwrite UART's LSR in memory stage.", $time, InstrCountW-1); \
force dut.hart.ieu.dp.ReadDataM = ExpectedMemReadDataM; \
else \

View File

@ -11,11 +11,11 @@ export RISCV=/opt/riscv # change this if you installed the tools in a differen
# Tools
# GCCZ
export LD_LIBRARY_PATH=$RISCV/riscv-gnu-toolchain/lib:$RISCV/riscv-gnu-toolchain/riscv64-unknown-elf/lib:$LD_LIBRARY_PATH
export PATH=$RISCV/riscv-gnu-toolchain/bin:$RISCV/riscv-gnu-toolchain/riscv64-unknown-elf/bin:$PATH # GCC tools
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$RISCV/riscv-gnu-toolchain/lib:$RISCV/riscv-gnu-toolchain/riscv64-unknown-elf/lib
export PATH=$PATH:$RISCV/riscv-gnu-toolchain/bin:$RISCV/riscv-gnu-toolchain/riscv64-unknown-elf/bin # GCC tools
# Spike
export LD_LIBRARY_PATH=$RISCV/lib:$LD_LIBRARY_PATH
export PATH=$RISCV/bin:$PATH
export PATH=$PATH:$RISCV/bin
# exe2memfile
export PATH=~/riscv-wally/bin:$PATH # exe2memfile; change this if riscv-wally isn't at your home directory
# Verilator