mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' into cache
Conflicts: wally-pipelined/src/uncore/dtim.sv
This commit is contained in:
commit
2f5d854f87
3
.gitignore
vendored
3
.gitignore
vendored
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
.nfs*
|
.nfs*
|
||||||
|
|
||||||
|
__pycache__/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
#vsim work files to ignore
|
#vsim work files to ignore
|
||||||
transcript
|
transcript
|
||||||
vsim.wlf
|
vsim.wlf
|
||||||
|
1
wally-pipelined/ppa/config/config.sv
Normal file
1
wally-pipelined/ppa/config/config.sv
Normal file
@ -0,0 +1 @@
|
|||||||
|
`define LIB SKY130
|
@ -2,9 +2,6 @@
|
|||||||
// Teo Ene & David_Harris@hmc.edu 25 Feb 2021
|
// Teo Ene & David_Harris@hmc.edu 25 Feb 2021
|
||||||
// Measure PPA of various building blocks
|
// Measure PPA of various building blocks
|
||||||
|
|
||||||
// replace this with the tools setting a library path to a config/skl130 directory containing config.vh
|
|
||||||
`define LIB SKL130
|
|
||||||
|
|
||||||
module top(
|
module top(
|
||||||
input logic a1,
|
input logic a1,
|
||||||
input logic [7:0] a8, b8,
|
input logic [7:0] a8, b8,
|
||||||
@ -49,7 +46,7 @@ endmodule
|
|||||||
|
|
||||||
module INVX2(input logic a, output logic y);
|
module INVX2(input logic a, output logic y);
|
||||||
generate
|
generate
|
||||||
if (LIB == SKL130)
|
if (LIB == SKY130)
|
||||||
sky130_osu_sc_12T_ms__inv_2 inv(a, y);
|
sky130_osu_sc_12T_ms__inv_2 inv(a, y);
|
||||||
else if (LIB == SKL90)
|
else if (LIB == SKL90)
|
||||||
scc9gena_inv_2 inv(a, y)
|
scc9gena_inv_2 inv(a, y)
|
||||||
|
@ -48,7 +48,7 @@ module ahblite (
|
|||||||
input logic [1:0] MemSizeM,
|
input logic [1:0] MemSizeM,
|
||||||
// Signals from MMU
|
// Signals from MMU
|
||||||
input logic [`XLEN-1:0] MMUPAdr,
|
input logic [`XLEN-1:0] MMUPAdr,
|
||||||
input logic MMUTranslate,
|
input logic MMUTranslate, MMUTranslationComplete,
|
||||||
output logic [`XLEN-1:0] MMUReadPTE,
|
output logic [`XLEN-1:0] MMUReadPTE,
|
||||||
output logic MMUReady,
|
output logic MMUReady,
|
||||||
// Return from bus
|
// Return from bus
|
||||||
@ -75,7 +75,8 @@ module ahblite (
|
|||||||
);
|
);
|
||||||
|
|
||||||
logic GrantData;
|
logic GrantData;
|
||||||
logic [2:0] ISize;
|
logic [31:0] AccessAddress;
|
||||||
|
logic [2:0] AccessSize, PTESize, ISize;
|
||||||
logic [`AHBW-1:0] HRDATAMasked, ReadDataM, ReadDataNewW, ReadDataOldW, WriteData;
|
logic [`AHBW-1:0] HRDATAMasked, ReadDataM, ReadDataNewW, ReadDataOldW, WriteData;
|
||||||
logic IReady, DReady;
|
logic IReady, DReady;
|
||||||
logic CaptureDataM;
|
logic CaptureDataM;
|
||||||
@ -89,47 +90,69 @@ module ahblite (
|
|||||||
// Data accesses have priority over instructions. However, if a data access comes
|
// Data accesses have priority over instructions. However, if a data access comes
|
||||||
// while an instruction read is occuring, the instruction read finishes before
|
// while an instruction read is occuring, the instruction read finishes before
|
||||||
// the data access can take place.
|
// the data access can take place.
|
||||||
typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADC, ATOMICREAD, ATOMICWRITE} statetype;
|
typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADC, ATOMICREAD, ATOMICWRITE, MMUTRANSLATE, MMUIDLE} statetype;
|
||||||
statetype BusState, NextBusState;
|
statetype BusState, NextBusState;
|
||||||
|
|
||||||
flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextBusState, IDLE, BusState);
|
flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextBusState, IDLE, BusState);
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
case (BusState)
|
case (BusState)
|
||||||
IDLE: if (AtomicM[1]) NextBusState = ATOMICREAD;
|
IDLE: if (MMUTranslate) NextBusState = MMUTRANSLATE;
|
||||||
else if (MemReadM) NextBusState = MEMREAD; // Memory has pirority over instructions
|
else if (AtomicM[1]) NextBusState = ATOMICREAD;
|
||||||
else if (MemWriteM) NextBusState = MEMWRITE;
|
else if (MemReadM) NextBusState = MEMREAD; // Memory has priority over instructions
|
||||||
else if (InstrReadF) NextBusState = INSTRREAD;
|
else if (MemWriteM) NextBusState = MEMWRITE;
|
||||||
else NextBusState = IDLE;
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
||||||
ATOMICREAD: if (~HREADY) NextBusState = ATOMICREAD;
|
else NextBusState = IDLE;
|
||||||
else NextBusState = ATOMICWRITE;
|
MMUTRANSLATE: if (~HREADY) NextBusState = MMUTRANSLATE;
|
||||||
ATOMICWRITE: if (~HREADY) NextBusState = ATOMICWRITE;
|
else NextBusState = MMUIDLE;
|
||||||
else if (InstrReadF) NextBusState = INSTRREAD;
|
// *** Could the MMUIDLE state just be the normal idle state?
|
||||||
else NextBusState = IDLE;
|
// Do we trust MMUTranslate to be high exactly when we need translation?
|
||||||
MEMREAD: if (~HREADY) NextBusState = MEMREAD;
|
MMUIDLE: if (~MMUTranslationComplete)
|
||||||
else if (InstrReadF) NextBusState = INSTRREADC;
|
NextBusState = MMUTRANSLATE;
|
||||||
else NextBusState = IDLE;
|
else if (AtomicM[1]) NextBusState = ATOMICREAD;
|
||||||
MEMWRITE: if (~HREADY) NextBusState = MEMWRITE;
|
else if (MemReadM) NextBusState = MEMREAD; // Memory has priority over instructions
|
||||||
else if (InstrReadF) NextBusState = INSTRREAD;
|
else if (MemWriteM) NextBusState = MEMWRITE;
|
||||||
else NextBusState = IDLE;
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
||||||
|
else NextBusState = IDLE;
|
||||||
|
ATOMICREAD: if (~HREADY) NextBusState = ATOMICREAD;
|
||||||
|
else NextBusState = ATOMICWRITE;
|
||||||
|
ATOMICWRITE: if (~HREADY) NextBusState = ATOMICWRITE;
|
||||||
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
||||||
|
else NextBusState = IDLE;
|
||||||
|
MEMREAD: if (~HREADY) NextBusState = MEMREAD;
|
||||||
|
else if (InstrReadF) NextBusState = INSTRREADC;
|
||||||
|
else NextBusState = IDLE;
|
||||||
|
MEMWRITE: if (~HREADY) NextBusState = MEMWRITE;
|
||||||
|
else if (InstrReadF) NextBusState = INSTRREAD;
|
||||||
|
else NextBusState = IDLE;
|
||||||
INSTRREAD:
|
INSTRREAD:
|
||||||
if (~HREADY) NextBusState = INSTRREAD;
|
if (~HREADY) NextBusState = INSTRREAD;
|
||||||
else NextBusState = IDLE; // if (InstrReadF still high)
|
else NextBusState = IDLE; // if (InstrReadF still high)
|
||||||
INSTRREADC: if (~HREADY) NextBusState = INSTRREADC; // "C" for "competing", meaning please don't mess up the memread in the W stage.
|
INSTRREADC: if (~HREADY) NextBusState = INSTRREADC; // "C" for "competing", meaning please don't mess up the memread in the W stage.
|
||||||
else NextBusState = IDLE;
|
else NextBusState = IDLE;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
// stall signals
|
// stall signals
|
||||||
assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) ||
|
assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) ||
|
||||||
(NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE);
|
(NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE) ||
|
||||||
assign #1 InstrStall = (NextBusState == INSTRREAD) || (NextBusState == INSTRREADC);
|
(NextBusState == MMUTRANSLATE) || (NextBusState == MMUIDLE);
|
||||||
|
// *** Could get finer grained stalling if we distinguish between MMU
|
||||||
|
// instruction address translation and data address translation
|
||||||
|
assign #1 InstrStall = (NextBusState == INSTRREAD) || (NextBusState == INSTRREADC) ||
|
||||||
|
(NextBusState == MMUTRANSLATE) || (NextBusState == MMUIDLE);
|
||||||
|
|
||||||
// bus outputs
|
// bus outputs
|
||||||
assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) ||
|
assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) ||
|
||||||
(NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE);
|
(NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE);
|
||||||
assign #1 HADDR = (GrantData) ? MemPAdrM[31:0] : InstrPAdrF[31:0];
|
assign #1 AccessAddress = (GrantData) ? MemPAdrM[31:0] : InstrPAdrF[31:0];
|
||||||
|
assign #1 HADDR = (MMUTranslate) ? MMUPAdr[31:0] : AccessAddress;
|
||||||
|
generate
|
||||||
|
if (`XLEN == 32) assign PTESize = 3'b010; // in rv32, PTEs are 4 bytes
|
||||||
|
else assign PTESize = 3'b011; // in rv64, PTEs are 8 bytes
|
||||||
|
endgenerate
|
||||||
assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width; ignored on reads anyway
|
assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width; ignored on reads anyway
|
||||||
assign #1 HSIZE = GrantData ? {1'b0, MemSizeM} : ISize;
|
assign #1 AccessSize = (GrantData) ? {1'b0, MemSizeM} : ISize;
|
||||||
|
assign #1 HSIZE = (MMUTranslate) ? PTESize : AccessSize;
|
||||||
assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfH
|
assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfH
|
||||||
assign HPROT = 4'b0011; // not used; see Section 3.7
|
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 HTRANS = (NextBusState != IDLE) ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise
|
||||||
@ -145,7 +168,10 @@ module ahblite (
|
|||||||
// Route signals to Instruction and Data Caches
|
// Route signals to Instruction and Data Caches
|
||||||
// *** assumes AHBW = XLEN
|
// *** assumes AHBW = XLEN
|
||||||
|
|
||||||
|
assign #1 MMUReady = (NextBusState == MMUIDLE);
|
||||||
|
|
||||||
assign InstrRData = HRDATA;
|
assign InstrRData = HRDATA;
|
||||||
|
assign MMUReadPTE = HRDATA;
|
||||||
assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021
|
assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021
|
||||||
assign CaptureDataM = ((BusState == MEMREAD) && (NextBusState != MEMREAD)) ||
|
assign CaptureDataM = ((BusState == MEMREAD) && (NextBusState != MEMREAD)) ||
|
||||||
((BusState == ATOMICREAD) && (NextBusState == ATOMICWRITE));
|
((BusState == ATOMICREAD) && (NextBusState == ATOMICWRITE));
|
||||||
|
@ -32,25 +32,29 @@ module pagetablewalker (
|
|||||||
|
|
||||||
input logic [`XLEN-1:0] SATP_REGW,
|
input logic [`XLEN-1:0] SATP_REGW,
|
||||||
|
|
||||||
|
input logic MemWriteM,
|
||||||
input logic ITLBMissF, DTLBMissM,
|
input logic ITLBMissF, DTLBMissM,
|
||||||
input logic [`XLEN-1:0] PCF, MemAdrM,
|
input logic [`XLEN-1:0] PCF, MemAdrM,
|
||||||
|
|
||||||
output logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM,
|
output logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM,
|
||||||
output logic ITLBWriteF, DTLBWriteM,
|
output logic ITLBWriteF, DTLBWriteM,
|
||||||
// *** handshake to tlbs probably not needed, since stalls take effect
|
// *** handshake to tlbs probably not needed, since stalls take effect
|
||||||
// output logic TranslationComplete
|
output logic MMUTranslationComplete,
|
||||||
|
|
||||||
// Signals from and to ahblite
|
// Signals from and to ahblite
|
||||||
input logic [`XLEN-1:0] MMUReadPTE,
|
input logic [`XLEN-1:0] MMUReadPTE,
|
||||||
input logic MMUReady,
|
input logic MMUReady,
|
||||||
|
|
||||||
output logic [`XLEN-1:0] MMUPAdr,
|
output logic [`XLEN-1:0] MMUPAdr,
|
||||||
output logic MMUTranslate
|
output logic MMUTranslate,
|
||||||
|
|
||||||
|
// Faults
|
||||||
|
output logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM
|
||||||
);
|
);
|
||||||
|
|
||||||
logic SvMode;
|
logic SvMode;
|
||||||
logic [`PPN_BITS-1:0] BasePageTablePPN;
|
logic [`PPN_BITS-1:0] BasePageTablePPN;
|
||||||
logic [`XLEN-1:0] DirectInstrPTE, DirectMemPTE;
|
logic [`XLEN-1:0] DirectInstrPTE, DirectMemPTE, TranslationVAdr;
|
||||||
|
|
||||||
logic [9:0] DirectPTEFlags = {2'b0, 8'b00001111};
|
logic [9:0] DirectPTEFlags = {2'b0, 8'b00001111};
|
||||||
|
|
||||||
@ -73,71 +77,233 @@ module pagetablewalker (
|
|||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
flopenr #(`XLEN) instrpte(clk, reset, ITLBMissF, DirectInstrPTE, PageTableEntryF);
|
//flopenr #(`XLEN) instrpte(clk, reset, ITLBMissF, DirectInstrPTE, PageTableEntryF);
|
||||||
flopenr #(`XLEN) datapte(clk, reset, DTLBMissM, DirectMemPTE, PageTableEntryM);
|
//flopenr #(`XLEN) datapte(clk, reset, DTLBMissM, DirectMemPTE, PageTableEntryM);
|
||||||
|
|
||||||
flopr #(1) iwritesignal(clk, reset, ITLBMissF, ITLBWriteF);
|
//flopr #(1) iwritesignal(clk, reset, ITLBMissF, ITLBWriteF);
|
||||||
flopr #(1) dwritesignal(clk, reset, DTLBMissM, DTLBWriteM);
|
//flopr #(1) dwritesignal(clk, reset, DTLBMissM, DTLBWriteM);
|
||||||
|
|
||||||
|
// Prefer data address translations over instruction address translations
|
||||||
|
assign TranslationVAdr = (DTLBMissM) ? MemAdrM : PCF;
|
||||||
|
assign MMUTranslate = DTLBMissM || ITLBMissF;
|
||||||
|
|
||||||
/*
|
|
||||||
generate
|
generate
|
||||||
if (`XLEN == 32) begin
|
if (`XLEN == 32) begin
|
||||||
assign SvMode = SATP_REGW[31];
|
assign SvMode = SATP_REGW[31];
|
||||||
|
|
||||||
logic VPN1 [9:0] = TranslationVAdr[31:22];
|
logic [9:0] VPN1 = TranslationVAdr[31:22];
|
||||||
logic VPN0 [9:0] = TranslationVAdr[21:12]; // *** could optimize by not passing offset?
|
logic [9:0] VPN0 = TranslationVAdr[21:12]; // *** could optimize by not passing offset?
|
||||||
|
|
||||||
logic TranslationPAdr [33:0];
|
logic [33:0] TranslationPAdr;
|
||||||
|
logic [21:0] CurrentPPN;
|
||||||
|
|
||||||
typedef enum {IDLE, DATA_LEVEL1, DATA_LEVEL0, DATA_LEAF, DATA FAULT} statetype;
|
logic Dirty, Accessed, Global, User,
|
||||||
|
Executable, Writable, Readable, Valid;
|
||||||
|
logic ValidPTE, AccessAlert, MegapageMisaligned, BadMegapage, LeafPTE;
|
||||||
|
|
||||||
|
typedef enum {IDLE, LEVEL1, LEVEL0, LEAF, FAULT} statetype;
|
||||||
statetype WalkerState, NextWalkerState;
|
statetype WalkerState, NextWalkerState;
|
||||||
|
|
||||||
always_ff @(posedge HCLK, negedge HRESETn)
|
// *** Do we need a synchronizer here for walker to talk to ahblite?
|
||||||
if (~HRESETn) WalkerState <= #1 IDLE;
|
flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState);
|
||||||
else WalkerState <= #1 NextWalkerState;
|
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
NextWalkerState = 'X;
|
|
||||||
case (WalkerState)
|
case (WalkerState)
|
||||||
IDLE: if (TLBMissM) NextWalkerState = LEVEL1;
|
IDLE: if (MMUTranslate) NextWalkerState = LEVEL1;
|
||||||
else NextWalkerState = IDLE;
|
else NextWalkerState = IDLE;
|
||||||
LEVEL1: if (HREADY && ValidEntry) NextWalkerState = LEVEL0;
|
LEVEL1: if (~MMUReady) NextWalkerState = LEVEL1;
|
||||||
else if (HREADY) NextWalkerState = FAULT;
|
// else if (~ValidPTE || (LeafPTE && BadMegapage))
|
||||||
else NextWalkerState = LEVEL1;
|
// NextWalkerState = FAULT;
|
||||||
LEVEL2: if (HREADY && ValidEntry) NextWalkerState = LEAF;
|
// *** Leave megapage implementation for later
|
||||||
else if (HREADY) NextWalkerState = FAULT;
|
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF;
|
||||||
else NextWalkerState = LEVEL2;
|
else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0;
|
||||||
LEAF: NextWalkerState = IDLE;
|
else NextWalkerState = FAULT;
|
||||||
|
LEVEL0: if (~MMUReady) NextWalkerState = LEVEL0;
|
||||||
|
else if (ValidPTE && LeafPTE && ~AccessAlert)
|
||||||
|
NextWalkerState = LEAF;
|
||||||
|
else NextWalkerState = FAULT;
|
||||||
|
LEAF: if (MMUTranslate) NextWalkerState = LEVEL1;
|
||||||
|
else NextWalkerState = IDLE;
|
||||||
|
FAULT: if (MMUTranslate) NextWalkerState = LEVEL1;
|
||||||
|
else NextWalkerState = IDLE;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge HCLK, negedge HRESETn)
|
// unswizzle PTE bits
|
||||||
if (~HRESETn) begin
|
assign {Dirty, Accessed, Global, User,
|
||||||
|
Executable, Writable, Readable, Valid} = MMUReadPTE[7:0];
|
||||||
|
|
||||||
|
// A megapage is a Level 1 leaf page. This page must have zero PPN[0].
|
||||||
|
assign MegapageMisaligned = |(CurrentPPN[9:0]);
|
||||||
|
assign LeafPTE = Executable | Writable | Readable;
|
||||||
|
assign ValidPTE = Valid && ~(Writable && ~Readable);
|
||||||
|
assign AccessAlert = ~Accessed || (MemWriteM && ~Dirty);
|
||||||
|
assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
|
||||||
|
|
||||||
|
// *** Should translate this flop block into our flop module notation
|
||||||
|
always_ff @(posedge clk, negedge reset)
|
||||||
|
if (reset) begin
|
||||||
TranslationPAdr <= '0;
|
TranslationPAdr <= '0;
|
||||||
PageTableEntryF <= '0;
|
PageTableEntryF <= '0;
|
||||||
TranslationComplete <= '0;
|
MMUTranslationComplete <= '0;
|
||||||
|
DTLBWriteM <= '0;
|
||||||
|
ITLBWriteF <= '0;
|
||||||
|
InstrPageFaultM <= '0;
|
||||||
|
LoadPageFaultM <= '0;
|
||||||
|
StorePageFaultM <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
// default values
|
// default values
|
||||||
|
TranslationPAdr <= '0;
|
||||||
|
PageTableEntryF <= '0;
|
||||||
|
MMUTranslationComplete <= '0;
|
||||||
|
DTLBWriteM <= '0;
|
||||||
|
ITLBWriteF <= '0;
|
||||||
|
InstrPageFaultM <= '0;
|
||||||
|
LoadPageFaultM <= '0;
|
||||||
|
StorePageFaultM <= '0;
|
||||||
case (NextWalkerState)
|
case (NextWalkerState)
|
||||||
LEVEL1: TranslationPAdr <= {BasePageTablePPN, VPN1, 2'b00};
|
LEVEL1: begin
|
||||||
LEVEL2: TranslationPAdr <= {CurrentPPN, VPN0, 2'b00};
|
TranslationPAdr <= {BasePageTablePPN, VPN1, 2'b00};
|
||||||
|
end
|
||||||
|
LEVEL0: begin
|
||||||
|
TranslationPAdr <= {CurrentPPN, VPN0, 2'b00};
|
||||||
|
end
|
||||||
LEAF: begin
|
LEAF: begin
|
||||||
PageTableEntryF <= CurrentPageTableEntry;
|
PageTableEntryF <= MMUReadPTE;
|
||||||
TranslationComplete <= '1;
|
PageTableEntryM <= MMUReadPTE;
|
||||||
end
|
MMUTranslationComplete <= '1;
|
||||||
|
DTLBWriteM <= DTLBMissM;
|
||||||
|
ITLBWriteF <= ~DTLBMissM; // Prefer data over instructions
|
||||||
|
end
|
||||||
|
FAULT: begin
|
||||||
|
InstrPageFaultM <= ~DTLBMissM;
|
||||||
|
LoadPageFaultM <= DTLBMissM && ~MemWriteM;
|
||||||
|
StorePageFaultM <= DTLBMissM && MemWriteM;
|
||||||
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
assign #1 Translate = (NextWalkerState == LEVEL1);
|
// Interpret inputs from ahblite
|
||||||
|
assign CurrentPPN = MMUReadPTE[31:10];
|
||||||
|
|
||||||
|
// Assign outputs to ahblite
|
||||||
|
// *** Currently truncate address to 32 bits. This must be changed if
|
||||||
|
// we support larger physical address spaces
|
||||||
|
assign MMUPAdr = TranslationPAdr[31:0];
|
||||||
|
|
||||||
end else begin
|
end else begin
|
||||||
// sv39 not yet implemented
|
|
||||||
assign SvMode = SATP_REGW[63];
|
assign SvMode = SATP_REGW[63];
|
||||||
|
|
||||||
|
logic [8:0] VPN2 = TranslationVAdr[38:30];
|
||||||
|
logic [8:0] VPN1 = TranslationVAdr[29:21];
|
||||||
|
logic [8:0] VPN0 = TranslationVAdr[20:12]; // *** could optimize by not passing offset?
|
||||||
|
|
||||||
|
logic [55:0] TranslationPAdr;
|
||||||
|
logic [43:0] CurrentPPN;
|
||||||
|
|
||||||
|
logic Dirty, Accessed, Global, User,
|
||||||
|
Executable, Writable, Readable, Valid;
|
||||||
|
logic ValidPTE, AccessAlert, GigapageMisaligned, MegapageMisaligned,
|
||||||
|
BadGigapage, BadMegapage, LeafPTE;
|
||||||
|
|
||||||
|
typedef enum {IDLE, LEVEL2, LEVEL1, LEVEL0, LEAF, FAULT} statetype;
|
||||||
|
statetype WalkerState, NextWalkerState;
|
||||||
|
|
||||||
|
// *** Do we need a synchronizer here for walker to talk to ahblite?
|
||||||
|
flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState);
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
case (WalkerState)
|
||||||
|
IDLE: if (MMUTranslate) NextWalkerState = LEVEL1;
|
||||||
|
else NextWalkerState = IDLE;
|
||||||
|
LEVEL2: if (~MMUReady) NextWalkerState = LEVEL2;
|
||||||
|
else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL1;
|
||||||
|
else NextWalkerState = FAULT;
|
||||||
|
LEVEL1: if (~MMUReady) NextWalkerState = LEVEL1;
|
||||||
|
// else if (~ValidPTE || (LeafPTE && BadMegapage))
|
||||||
|
// NextWalkerState = FAULT;
|
||||||
|
// *** Leave megapage implementation for later
|
||||||
|
// else if (ValidPTE && LeafPTE) NextWalkerState = LEAF;
|
||||||
|
else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0;
|
||||||
|
else NextWalkerState = FAULT;
|
||||||
|
LEVEL0: if (~MMUReady) NextWalkerState = LEVEL0;
|
||||||
|
else if (ValidPTE && LeafPTE && ~AccessAlert)
|
||||||
|
NextWalkerState = LEAF;
|
||||||
|
else NextWalkerState = FAULT;
|
||||||
|
LEAF: if (MMUTranslate) NextWalkerState = LEVEL2;
|
||||||
|
else NextWalkerState = IDLE;
|
||||||
|
FAULT: if (MMUTranslate) NextWalkerState = LEVEL2;
|
||||||
|
else NextWalkerState = IDLE;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
// unswizzle PTE bits
|
||||||
|
assign {Dirty, Accessed, Global, User,
|
||||||
|
Executable, Writable, Readable, Valid} = MMUReadPTE[7:0];
|
||||||
|
|
||||||
|
// A megapage is a Level 1 leaf page. This page must have zero PPN[0].
|
||||||
|
assign GigapageMisaligned = |(CurrentPPN[17:0]);
|
||||||
|
assign MegapageMisaligned = |(CurrentPPN[8:0]);
|
||||||
|
assign LeafPTE = Executable | Writable | Readable;
|
||||||
|
assign ValidPTE = Valid && ~(Writable && ~Readable);
|
||||||
|
assign AccessAlert = ~Accessed || (MemWriteM && ~Dirty);
|
||||||
|
assign BadGigapage = GigapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
|
||||||
|
assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme
|
||||||
|
|
||||||
|
// *** Should translate this flop block into our flop module notation
|
||||||
|
always_ff @(posedge clk, negedge reset)
|
||||||
|
if (reset) begin
|
||||||
|
TranslationPAdr <= '0;
|
||||||
|
PageTableEntryF <= '0;
|
||||||
|
MMUTranslationComplete <= '0;
|
||||||
|
DTLBWriteM <= '0;
|
||||||
|
ITLBWriteF <= '0;
|
||||||
|
InstrPageFaultM <= '0;
|
||||||
|
LoadPageFaultM <= '0;
|
||||||
|
StorePageFaultM <= '0;
|
||||||
|
end else begin
|
||||||
|
// default values
|
||||||
|
TranslationPAdr <= '0;
|
||||||
|
PageTableEntryF <= '0;
|
||||||
|
MMUTranslationComplete <= '0;
|
||||||
|
DTLBWriteM <= '0;
|
||||||
|
ITLBWriteF <= '0;
|
||||||
|
InstrPageFaultM <= '0;
|
||||||
|
LoadPageFaultM <= '0;
|
||||||
|
StorePageFaultM <= '0;
|
||||||
|
case (NextWalkerState)
|
||||||
|
LEVEL2: begin
|
||||||
|
TranslationPAdr <= {BasePageTablePPN, VPN2, 3'b00};
|
||||||
|
end
|
||||||
|
LEVEL1: begin
|
||||||
|
TranslationPAdr <= {CurrentPPN, VPN1, 3'b00};
|
||||||
|
end
|
||||||
|
LEVEL0: begin
|
||||||
|
TranslationPAdr <= {CurrentPPN, VPN0, 3'b00};
|
||||||
|
end
|
||||||
|
LEAF: begin
|
||||||
|
PageTableEntryF <= MMUReadPTE;
|
||||||
|
PageTableEntryM <= MMUReadPTE;
|
||||||
|
MMUTranslationComplete <= '1;
|
||||||
|
DTLBWriteM <= DTLBMissM;
|
||||||
|
ITLBWriteF <= ~DTLBMissM; // Prefer data over instructions
|
||||||
|
end
|
||||||
|
FAULT: begin
|
||||||
|
InstrPageFaultM <= ~DTLBMissM;
|
||||||
|
LoadPageFaultM <= DTLBMissM && ~MemWriteM;
|
||||||
|
StorePageFaultM <= DTLBMissM && MemWriteM;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
// Interpret inputs from ahblite
|
||||||
|
assign CurrentPPN = MMUReadPTE[53:10];
|
||||||
|
|
||||||
|
// Assign outputs to ahblite
|
||||||
|
// *** Currently truncate address to 32 bits. This must be changed if
|
||||||
|
// we support larger physical address spaces
|
||||||
|
assign MMUPAdr = TranslationPAdr[31:0];
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
// rv32 case
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
@ -51,7 +51,20 @@ module csrm #(parameter
|
|||||||
PMPCFG2 = 12'h3A2,
|
PMPCFG2 = 12'h3A2,
|
||||||
PMPCFG3 = 12'h3A3,
|
PMPCFG3 = 12'h3A3,
|
||||||
PMPADDR0 = 12'h3B0,
|
PMPADDR0 = 12'h3B0,
|
||||||
//... more physical memory protection
|
PMPADDR1 = 12'h3B1,
|
||||||
|
PMPADDR2 = 12'h3B2,
|
||||||
|
PMPADDR3 = 12'h3B3,
|
||||||
|
PMPADDR4 = 12'h3B4,
|
||||||
|
PMPADDR5 = 12'h3B5,
|
||||||
|
PMPADDR6 = 12'h3B6,
|
||||||
|
PMPADDR7 = 12'h3B7,
|
||||||
|
PMPADDR8 = 12'h3B8,
|
||||||
|
PMPADDR9 = 12'h3B9,
|
||||||
|
PMPADDR10 = 12'h3BA,
|
||||||
|
PMPADDR11 = 12'h3BB,
|
||||||
|
PMPADDR12 = 12'h3BC,
|
||||||
|
PMPADDR13 = 12'h3BD,
|
||||||
|
PMPADDR14 = 12'h3BE,
|
||||||
PMPADDR15 = 12'h3BF,
|
PMPADDR15 = 12'h3BF,
|
||||||
TSELECT = 12'h7A0,
|
TSELECT = 12'h7A0,
|
||||||
TDATA1 = 12'h7A1,
|
TDATA1 = 12'h7A1,
|
||||||
@ -77,7 +90,8 @@ module csrm #(parameter
|
|||||||
logic [`XLEN-1:0] MISA_REGW;
|
logic [`XLEN-1:0] MISA_REGW;
|
||||||
logic [`XLEN-1:0] MSCRATCH_REGW,MCAUSE_REGW, MTVAL_REGW;
|
logic [`XLEN-1:0] MSCRATCH_REGW,MCAUSE_REGW, MTVAL_REGW;
|
||||||
logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW; // 64-bit registers in RV64, or two 32-bit registers in RV32
|
logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW; // 64-bit registers in RV64, or two 32-bit registers in RV32
|
||||||
logic [`XLEN-1:0] PMPADDR0_REGW; // will need to add more
|
logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [0:15]; // *** Might have to make 16 individual registers
|
||||||
|
//logic [`XLEN-1:0] PMPADDR0_REGW;
|
||||||
logic [`XLEN-1:0] zero = 0;
|
logic [`XLEN-1:0] zero = 0;
|
||||||
logic [31:0] allones = {32{1'b1}};
|
logic [31:0] allones = {32{1'b1}};
|
||||||
logic [`XLEN-1:0] MEDELEG_MASK = ~(zero | 1'b1 << 11); // medeleg[11] hardwired to zero per Privileged Spec 3.1.8
|
logic [`XLEN-1:0] MEDELEG_MASK = ~(zero | 1'b1 << 11); // medeleg[11] hardwired to zero per Privileged Spec 3.1.8
|
||||||
@ -86,7 +100,7 @@ module csrm #(parameter
|
|||||||
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
||||||
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
||||||
logic WritePMPCFG0M, WritePMPCFG2M;
|
logic WritePMPCFG0M, WritePMPCFG2M;
|
||||||
logic WritePMPADDR0M;
|
logic WritePMPADDRM [0:15];
|
||||||
logic [25:0] MISAbits = `MISA;
|
logic [25:0] MISAbits = `MISA;
|
||||||
|
|
||||||
// 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
|
||||||
@ -103,7 +117,22 @@ module csrm #(parameter
|
|||||||
assign WriteMTVALM = MTrapM | (CSRMWriteM && (CSRAdrM == MTVAL));
|
assign WriteMTVALM = MTrapM | (CSRMWriteM && (CSRAdrM == MTVAL));
|
||||||
assign WritePMPCFG0M = (CSRMWriteM && (CSRAdrM == PMPCFG0));
|
assign WritePMPCFG0M = (CSRMWriteM && (CSRAdrM == PMPCFG0));
|
||||||
assign WritePMPCFG2M = (CSRMWriteM && (CSRAdrM == PMPCFG2));
|
assign WritePMPCFG2M = (CSRMWriteM && (CSRAdrM == PMPCFG2));
|
||||||
assign WritePMPADDR0M = (CSRMWriteM && (CSRAdrM == PMPADDR0));
|
assign WritePMPADDRM[0] = (CSRMWriteM && (CSRAdrM == PMPADDR0));
|
||||||
|
assign WritePMPADDRM[1] = (CSRMWriteM && (CSRAdrM == PMPADDR1));
|
||||||
|
assign WritePMPADDRM[2] = (CSRMWriteM && (CSRAdrM == PMPADDR2));
|
||||||
|
assign WritePMPADDRM[3] = (CSRMWriteM && (CSRAdrM == PMPADDR3));
|
||||||
|
assign WritePMPADDRM[4] = (CSRMWriteM && (CSRAdrM == PMPADDR4));
|
||||||
|
assign WritePMPADDRM[5] = (CSRMWriteM && (CSRAdrM == PMPADDR5));
|
||||||
|
assign WritePMPADDRM[6] = (CSRMWriteM && (CSRAdrM == PMPADDR6));
|
||||||
|
assign WritePMPADDRM[7] = (CSRMWriteM && (CSRAdrM == PMPADDR7));
|
||||||
|
assign WritePMPADDRM[8] = (CSRMWriteM && (CSRAdrM == PMPADDR8));
|
||||||
|
assign WritePMPADDRM[9] = (CSRMWriteM && (CSRAdrM == PMPADDR9));
|
||||||
|
assign WritePMPADDRM[10] = (CSRMWriteM && (CSRAdrM == PMPADDR10));
|
||||||
|
assign WritePMPADDRM[11] = (CSRMWriteM && (CSRAdrM == PMPADDR11));
|
||||||
|
assign WritePMPADDRM[12] = (CSRMWriteM && (CSRAdrM == PMPADDR12));
|
||||||
|
assign WritePMPADDRM[13] = (CSRMWriteM && (CSRAdrM == PMPADDR13));
|
||||||
|
assign WritePMPADDRM[14] = (CSRMWriteM && (CSRAdrM == PMPADDR14));
|
||||||
|
assign WritePMPADDRM[15] = (CSRMWriteM && (CSRAdrM == PMPADDR15));
|
||||||
assign WriteMCOUNTERENM = CSRMWriteM && (CSRAdrM == MCOUNTEREN);
|
assign WriteMCOUNTERENM = CSRMWriteM && (CSRAdrM == MCOUNTEREN);
|
||||||
assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT);
|
assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT);
|
||||||
|
|
||||||
@ -132,7 +161,15 @@ module csrm #(parameter
|
|||||||
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], allones, MCOUNTEREN_REGW);
|
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], allones, MCOUNTEREN_REGW);
|
||||||
endgenerate
|
endgenerate
|
||||||
flopenl #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], allones, MCOUNTINHIBIT_REGW);
|
flopenl #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], allones, MCOUNTINHIBIT_REGW);
|
||||||
flopenr #(`XLEN) PMPADDR0reg(clk, reset, WritePMPADDR0M, CSRWriteValM, PMPADDR0_REGW);
|
|
||||||
|
// There are 16 PMPADDR registers, each of which has its own flop
|
||||||
|
generate
|
||||||
|
genvar i;
|
||||||
|
for (i = 0; i < 16; i++) begin: pmp_flop
|
||||||
|
flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]);
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
// PMPCFG registers are a pair of 64-bit in RV64 and four 32-bit in RV32
|
// PMPCFG registers are a pair of 64-bit in RV64 and four 32-bit in RV32
|
||||||
generate
|
generate
|
||||||
if (`XLEN==64) begin
|
if (`XLEN==64) begin
|
||||||
@ -175,7 +212,22 @@ module csrm #(parameter
|
|||||||
PMPCFG1: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG01_REGW[63:31]};
|
PMPCFG1: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG01_REGW[63:31]};
|
||||||
PMPCFG2: CSRMReadValM = PMPCFG23_REGW[`XLEN-1:0];
|
PMPCFG2: CSRMReadValM = PMPCFG23_REGW[`XLEN-1:0];
|
||||||
PMPCFG3: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG23_REGW[63:31]};
|
PMPCFG3: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG23_REGW[63:31]};
|
||||||
PMPADDR0: CSRMReadValM = PMPADDR0_REGW;
|
PMPADDR0: CSRMReadValM = PMPADDR_ARRAY_REGW[0];
|
||||||
|
PMPADDR1: CSRMReadValM = PMPADDR_ARRAY_REGW[1];
|
||||||
|
PMPADDR2: CSRMReadValM = PMPADDR_ARRAY_REGW[2];
|
||||||
|
PMPADDR3: CSRMReadValM = PMPADDR_ARRAY_REGW[3];
|
||||||
|
PMPADDR4: CSRMReadValM = PMPADDR_ARRAY_REGW[4];
|
||||||
|
PMPADDR5: CSRMReadValM = PMPADDR_ARRAY_REGW[5];
|
||||||
|
PMPADDR6: CSRMReadValM = PMPADDR_ARRAY_REGW[6];
|
||||||
|
PMPADDR7: CSRMReadValM = PMPADDR_ARRAY_REGW[7];
|
||||||
|
PMPADDR8: CSRMReadValM = PMPADDR_ARRAY_REGW[8];
|
||||||
|
PMPADDR9: CSRMReadValM = PMPADDR_ARRAY_REGW[9];
|
||||||
|
PMPADDR10: CSRMReadValM = PMPADDR_ARRAY_REGW[10];
|
||||||
|
PMPADDR11: CSRMReadValM = PMPADDR_ARRAY_REGW[11];
|
||||||
|
PMPADDR12: CSRMReadValM = PMPADDR_ARRAY_REGW[12];
|
||||||
|
PMPADDR13: CSRMReadValM = PMPADDR_ARRAY_REGW[13];
|
||||||
|
PMPADDR14: CSRMReadValM = PMPADDR_ARRAY_REGW[14];
|
||||||
|
PMPADDR15: CSRMReadValM = PMPADDR_ARRAY_REGW[15];
|
||||||
default: begin
|
default: begin
|
||||||
CSRMReadValM = 0;
|
CSRMReadValM = 0;
|
||||||
IllegalCSRMAccessM = 1;
|
IllegalCSRMAccessM = 1;
|
||||||
|
@ -39,6 +39,7 @@ module privileged (
|
|||||||
input logic InstrValidW, FloatRegWriteW, LoadStallD, BPPredWrongM,
|
input logic InstrValidW, FloatRegWriteW, LoadStallD, BPPredWrongM,
|
||||||
input logic [3:0] InstrClassM,
|
input logic [3:0] InstrClassM,
|
||||||
input logic PrivilegedM,
|
input logic PrivilegedM,
|
||||||
|
input logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM,
|
||||||
input logic InstrMisalignedFaultM, InstrAccessFaultF, IllegalIEUInstrFaultD,
|
input logic InstrMisalignedFaultM, InstrAccessFaultF, IllegalIEUInstrFaultD,
|
||||||
input logic LoadMisalignedFaultM, LoadAccessFaultM,
|
input logic LoadMisalignedFaultM, LoadAccessFaultM,
|
||||||
input logic StoreMisalignedFaultM, StoreAccessFaultM,
|
input logic StoreMisalignedFaultM, StoreAccessFaultM,
|
||||||
@ -48,7 +49,7 @@ module privileged (
|
|||||||
output logic [1:0] PrivilegeModeW,
|
output logic [1:0] PrivilegeModeW,
|
||||||
output logic [`XLEN-1:0] SATP_REGW,
|
output logic [`XLEN-1:0] SATP_REGW,
|
||||||
output logic [2:0] FRM_REGW,
|
output logic [2:0] FRM_REGW,
|
||||||
input logic FlushD, FlushE, FlushM, StallD, StallW
|
input logic FlushD, FlushE, FlushM, StallD, StallW, StallE, StallM
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [1:0] NextPrivilegeModeM;
|
logic [1:0] NextPrivilegeModeM;
|
||||||
@ -65,7 +66,6 @@ module privileged (
|
|||||||
logic IllegalInstrFaultM;
|
logic IllegalInstrFaultM;
|
||||||
|
|
||||||
logic BreakpointFaultM, EcallFaultM;
|
logic BreakpointFaultM, EcallFaultM;
|
||||||
logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM;
|
|
||||||
logic MTrapM, STrapM, UTrapM;
|
logic MTrapM, STrapM, UTrapM;
|
||||||
|
|
||||||
logic [1:0] STATUS_MPP;
|
logic [1:0] STATUS_MPP;
|
||||||
@ -119,9 +119,11 @@ module privileged (
|
|||||||
|
|
||||||
assign BreakpointFaultM = ebreakM; // could have other causes too
|
assign BreakpointFaultM = ebreakM; // could have other causes too
|
||||||
assign EcallFaultM = ecallM;
|
assign EcallFaultM = ecallM;
|
||||||
assign InstrPageFaultM = 0;
|
// *** Page faults now driven by page table walker. Might need to make the
|
||||||
assign LoadPageFaultM = 0;
|
// below signals ORs of a walker fault and a tlb fault if both of those come in
|
||||||
assign StorePageFaultM = 0;
|
// assign InstrPageFaultM = 0;
|
||||||
|
// assign LoadPageFaultM = 0;
|
||||||
|
// assign StorePageFaultM = 0;
|
||||||
|
|
||||||
// pipeline fault signals
|
// pipeline fault signals
|
||||||
flopenrc #(1) faultregD(clk, reset, FlushD, ~StallD, InstrAccessFaultF, InstrAccessFaultD);
|
flopenrc #(1) faultregD(clk, reset, FlushD, ~StallD, InstrAccessFaultF, InstrAccessFaultD);
|
||||||
|
@ -87,13 +87,13 @@ module dtim #(parameter BASE=0, RANGE = 65535) (
|
|||||||
always_ff @(posedge HCLK) begin
|
always_ff @(posedge HCLK) begin
|
||||||
HWADDR <= #1 A;
|
HWADDR <= #1 A;
|
||||||
HREADTim0 <= #1 RAM[A[31:3]];
|
HREADTim0 <= #1 RAM[A[31:3]];
|
||||||
if (memwrite && risingHREADYTim) RAM[HWADDR[31:3]] <= HWDATA;
|
if (memwrite && risingHREADYTim) RAM[HWADDR[31:3]] <= #1 HWDATA;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
always_ff @(posedge HCLK) begin
|
always_ff @(posedge HCLK) begin
|
||||||
HWADDR <= #1 A;
|
HWADDR <= #1 A;
|
||||||
HREADTim0 <= #1 RAM[A[31:2]];
|
HREADTim0 <= #1 RAM[A[31:2]];
|
||||||
if (memwrite && risingHREADYTim) RAM[HWADDR[31:2]] <= HWDATA;
|
if (memwrite && risingHREADYTim) RAM[HWADDR[31:2]] <= #1 HWDATA;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
@ -76,6 +76,7 @@ module wallypipelinedhart (
|
|||||||
logic InstrMisalignedFaultM;
|
logic InstrMisalignedFaultM;
|
||||||
logic DataMisalignedM;
|
logic DataMisalignedM;
|
||||||
logic IllegalBaseInstrFaultD, IllegalIEUInstrFaultD;
|
logic IllegalBaseInstrFaultD, IllegalIEUInstrFaultD;
|
||||||
|
logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM;
|
||||||
logic LoadMisalignedFaultM, LoadAccessFaultM;
|
logic LoadMisalignedFaultM, LoadAccessFaultM;
|
||||||
logic StoreMisalignedFaultM, StoreAccessFaultM;
|
logic StoreMisalignedFaultM, StoreAccessFaultM;
|
||||||
logic [`XLEN-1:0] InstrMisalignedAdrM;
|
logic [`XLEN-1:0] InstrMisalignedAdrM;
|
||||||
@ -100,7 +101,7 @@ module wallypipelinedhart (
|
|||||||
// IMem stalls
|
// IMem stalls
|
||||||
logic ICacheStallF;
|
logic ICacheStallF;
|
||||||
logic [`XLEN-1:0] MMUPAdr, MMUReadPTE;
|
logic [`XLEN-1:0] MMUPAdr, MMUReadPTE;
|
||||||
logic MMUTranslate, MMUReady;
|
logic MMUTranslate, MMUTranslationComplete, MMUReady;
|
||||||
|
|
||||||
// bus interface to dmem
|
// bus interface to dmem
|
||||||
logic MemReadM, MemWriteM;
|
logic MemReadM, MemWriteM;
|
||||||
|
Loading…
Reference in New Issue
Block a user