mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Moved lsu interlock fpm to separate module.
This commit is contained in:
parent
81741925aa
commit
90ccc94e5e
@ -205,7 +205,7 @@ add wave -noupdate -group AHB /testbench/dut/hart/ebu/HMASTLOCK
|
|||||||
add wave -noupdate -group AHB /testbench/dut/hart/ebu/HADDRD
|
add wave -noupdate -group AHB /testbench/dut/hart/ebu/HADDRD
|
||||||
add wave -noupdate -group AHB /testbench/dut/hart/ebu/HSIZED
|
add wave -noupdate -group AHB /testbench/dut/hart/ebu/HSIZED
|
||||||
add wave -noupdate -group AHB /testbench/dut/hart/ebu/HWRITED
|
add wave -noupdate -group AHB /testbench/dut/hart/ebu/HWRITED
|
||||||
add wave -noupdate -expand -group lsu -color Gold /testbench/dut/hart/lsu/MEM_VIRTMEM/InterlockCurrState
|
add wave -noupdate -expand -group lsu -color Gold /testbench/dut/hart/lsu/MEM_VIRTMEM/interlockfsm/InterlockCurrState
|
||||||
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/SelHPTW
|
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/SelHPTW
|
||||||
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/InterlockStall
|
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/InterlockStall
|
||||||
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/LSUStall
|
add wave -noupdate -expand -group lsu /testbench/dut/hart/lsu/LSUStall
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// busfsm.sv
|
// busfsm.sv
|
||||||
//
|
//
|
||||||
// Written: Ross Thompson ross1728@gmail.com
|
// Written: Ross Thompson ross1728@gmail.com December 29, 2021
|
||||||
// Modified:
|
// Modified:
|
||||||
//
|
//
|
||||||
// Purpose: Load/Store Unit's interface to BUS
|
// Purpose: Load/Store Unit's interface to BUS
|
||||||
|
113
wally-pipelined/src/lsu/interlockfsm.sv
Normal file
113
wally-pipelined/src/lsu/interlockfsm.sv
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
///////////////////////////////////////////
|
||||||
|
// interlockfsm.sv
|
||||||
|
//
|
||||||
|
// Written: Ross Thompson ross1728@gmail.com December 29, 2021
|
||||||
|
// Modified:
|
||||||
|
//
|
||||||
|
// Purpose: Allows the HPTW to take control of the dcache to walk page table and then replay the memory operation if
|
||||||
|
// there was on.
|
||||||
|
//
|
||||||
|
// 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 interlockfsm
|
||||||
|
(input logic clk,
|
||||||
|
input logic reset,
|
||||||
|
input logic AnyCPUReqM,
|
||||||
|
input logic ITLBMissF,
|
||||||
|
input logic ITLBWriteF,
|
||||||
|
input logic DTLBMissM,
|
||||||
|
input logic DTLBWriteM,
|
||||||
|
input logic ExceptionM,
|
||||||
|
input logic PendingInterruptM,
|
||||||
|
input logic DCacheStall,
|
||||||
|
|
||||||
|
output logic InterlockStall,
|
||||||
|
output logic SelReplayCPURequest,
|
||||||
|
output logic SelHPTW,
|
||||||
|
output logic IgnoreRequest);
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {STATE_T0_READY,
|
||||||
|
STATE_T0_REPLAY,
|
||||||
|
STATE_T3_DTLB_MISS,
|
||||||
|
STATE_T4_ITLB_MISS,
|
||||||
|
STATE_T5_ITLB_MISS,
|
||||||
|
STATE_T7_DITLB_MISS} statetype;
|
||||||
|
|
||||||
|
statetype InterlockCurrState, InterlockNextState;
|
||||||
|
|
||||||
|
|
||||||
|
always_ff @(posedge clk)
|
||||||
|
if (reset) InterlockCurrState <= #1 STATE_T0_READY;
|
||||||
|
else InterlockCurrState <= #1 InterlockNextState;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
case(InterlockCurrState)
|
||||||
|
STATE_T0_READY: if(~ITLBMissF & DTLBMissM & AnyCPUReqM) InterlockNextState = STATE_T3_DTLB_MISS;
|
||||||
|
else if(ITLBMissF & ~DTLBMissM & ~AnyCPUReqM) InterlockNextState = STATE_T4_ITLB_MISS;
|
||||||
|
else if(ITLBMissF & ~DTLBMissM & AnyCPUReqM) InterlockNextState = STATE_T5_ITLB_MISS;
|
||||||
|
else if(ITLBMissF & DTLBMissM & AnyCPUReqM) InterlockNextState = STATE_T7_DITLB_MISS;
|
||||||
|
else InterlockNextState = STATE_T0_READY;
|
||||||
|
STATE_T0_REPLAY: if(DCacheStall) InterlockNextState = STATE_T0_REPLAY;
|
||||||
|
else InterlockNextState = STATE_T0_READY;
|
||||||
|
STATE_T3_DTLB_MISS: if(DTLBWriteM) InterlockNextState = STATE_T0_REPLAY;
|
||||||
|
else InterlockNextState = STATE_T3_DTLB_MISS;
|
||||||
|
STATE_T4_ITLB_MISS: if(ITLBWriteF) InterlockNextState = STATE_T0_READY;
|
||||||
|
else InterlockNextState = STATE_T4_ITLB_MISS;
|
||||||
|
STATE_T5_ITLB_MISS: if(ITLBWriteF) InterlockNextState = STATE_T0_REPLAY;
|
||||||
|
else InterlockNextState = STATE_T5_ITLB_MISS;
|
||||||
|
STATE_T7_DITLB_MISS: if(DTLBWriteM) InterlockNextState = STATE_T5_ITLB_MISS;
|
||||||
|
else InterlockNextState = STATE_T7_DITLB_MISS;
|
||||||
|
default: InterlockNextState = STATE_T0_READY;
|
||||||
|
endcase
|
||||||
|
end // always_comb
|
||||||
|
|
||||||
|
// signal to CPU it needs to wait on HPTW.
|
||||||
|
/* -----\/----- EXCLUDED -----\/-----
|
||||||
|
// this code has a problem with imperas64mmu as it reads in an invalid uninitalized instruction. InterlockStall becomes x and it propagates
|
||||||
|
// everywhere. The case statement below implements the same logic but any x on the inputs will resolve to 0.
|
||||||
|
// Note this will cause a problem for post synthesis gate simulation.
|
||||||
|
assign InterlockStall = (InterlockCurrState == STATE_T0_READY & (DTLBMissM | ITLBMissF)) |
|
||||||
|
(InterlockCurrState == STATE_T3_DTLB_MISS) | (InterlockCurrState == STATE_T4_ITLB_MISS) |
|
||||||
|
(InterlockCurrState == STATE_T5_ITLB_MISS) | (InterlockCurrState == STATE_T7_DITLB_MISS);
|
||||||
|
|
||||||
|
-----/\----- EXCLUDED -----/\----- */
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
InterlockStall = 1'b0;
|
||||||
|
case(InterlockCurrState)
|
||||||
|
STATE_T0_READY: if(DTLBMissM | ITLBMissF) InterlockStall = 1'b1;
|
||||||
|
STATE_T3_DTLB_MISS: InterlockStall = 1'b1;
|
||||||
|
STATE_T4_ITLB_MISS: InterlockStall = 1'b1;
|
||||||
|
STATE_T5_ITLB_MISS: InterlockStall = 1'b1;
|
||||||
|
STATE_T7_DITLB_MISS: InterlockStall = 1'b1;
|
||||||
|
default: InterlockStall = 1'b0;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
assign SelReplayCPURequest = (InterlockNextState == STATE_T0_REPLAY);
|
||||||
|
assign SelHPTW = (InterlockCurrState == STATE_T3_DTLB_MISS) | (InterlockCurrState == STATE_T4_ITLB_MISS) |
|
||||||
|
(InterlockCurrState == STATE_T5_ITLB_MISS) | (InterlockCurrState == STATE_T7_DITLB_MISS);
|
||||||
|
assign IgnoreRequest = (InterlockCurrState == STATE_T0_READY & (ITLBMissF | DTLBMissM | ExceptionM | PendingInterruptM)) |
|
||||||
|
((InterlockCurrState == STATE_T0_REPLAY)
|
||||||
|
& (ExceptionM | PendingInterruptM));
|
||||||
|
|
||||||
|
endmodule
|
@ -128,78 +128,13 @@ module lsu
|
|||||||
logic [2:0] HPTWSize;
|
logic [2:0] HPTWSize;
|
||||||
logic SelReplayCPURequest;
|
logic SelReplayCPURequest;
|
||||||
|
|
||||||
typedef enum {STATE_T0_READY,
|
assign AnyCPUReqM = (|MemRWM) | (|AtomicM);
|
||||||
STATE_T0_REPLAY,
|
|
||||||
STATE_T3_DTLB_MISS,
|
|
||||||
STATE_T4_ITLB_MISS,
|
|
||||||
STATE_T5_ITLB_MISS,
|
|
||||||
STATE_T7_DITLB_MISS} statetype;
|
|
||||||
|
|
||||||
statetype InterlockCurrState, InterlockNextState;
|
interlockfsm interlockfsm (.clk, .reset, .AnyCPUReqM, .ITLBMissF, .ITLBWriteF,
|
||||||
|
.DTLBMissM, .DTLBWriteM, .ExceptionM, .PendingInterruptM, .DCacheStall,
|
||||||
|
.InterlockStall, .SelReplayCPURequest, .SelHPTW,
|
||||||
|
.IgnoreRequest);
|
||||||
|
|
||||||
assign AnyCPUReqM = (|MemRWM) | (|AtomicM);
|
|
||||||
|
|
||||||
always_ff @(posedge clk)
|
|
||||||
if (reset) InterlockCurrState <= #1 STATE_T0_READY;
|
|
||||||
else InterlockCurrState <= #1 InterlockNextState;
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
case(InterlockCurrState)
|
|
||||||
STATE_T0_READY: if(~ITLBMissF & DTLBMissM & AnyCPUReqM) InterlockNextState = STATE_T3_DTLB_MISS;
|
|
||||||
else if(ITLBMissF & ~DTLBMissM & ~AnyCPUReqM) InterlockNextState = STATE_T4_ITLB_MISS;
|
|
||||||
else if(ITLBMissF & ~DTLBMissM & AnyCPUReqM) InterlockNextState = STATE_T5_ITLB_MISS;
|
|
||||||
else if(ITLBMissF & DTLBMissM & AnyCPUReqM) InterlockNextState = STATE_T7_DITLB_MISS;
|
|
||||||
else InterlockNextState = STATE_T0_READY;
|
|
||||||
STATE_T0_REPLAY: if(DCacheStall) InterlockNextState = STATE_T0_REPLAY;
|
|
||||||
else InterlockNextState = STATE_T0_READY;
|
|
||||||
STATE_T3_DTLB_MISS: if(DTLBWriteM) InterlockNextState = STATE_T0_REPLAY;
|
|
||||||
else InterlockNextState = STATE_T3_DTLB_MISS;
|
|
||||||
STATE_T4_ITLB_MISS: if(ITLBWriteF) InterlockNextState = STATE_T0_READY;
|
|
||||||
else InterlockNextState = STATE_T4_ITLB_MISS;
|
|
||||||
STATE_T5_ITLB_MISS: if(ITLBWriteF) InterlockNextState = STATE_T0_REPLAY;
|
|
||||||
else InterlockNextState = STATE_T5_ITLB_MISS;
|
|
||||||
STATE_T7_DITLB_MISS: if(DTLBWriteM) InterlockNextState = STATE_T5_ITLB_MISS;
|
|
||||||
else InterlockNextState = STATE_T7_DITLB_MISS;
|
|
||||||
default: InterlockNextState = STATE_T0_READY;
|
|
||||||
endcase
|
|
||||||
end // always_comb
|
|
||||||
|
|
||||||
// signal to CPU it needs to wait on HPTW.
|
|
||||||
/* -----\/----- EXCLUDED -----\/-----
|
|
||||||
// this code has a problem with imperas64mmu as it reads in an invalid uninitalized instruction. InterlockStall becomes x and it propagates
|
|
||||||
// everywhere. The case statement below implements the same logic but any x on the inputs will resolve to 0.
|
|
||||||
assign InterlockStall = (InterlockCurrState == STATE_T0_READY & (DTLBMissM | ITLBMissF)) |
|
|
||||||
(InterlockCurrState == STATE_T3_DTLB_MISS) | (InterlockCurrState == STATE_T4_ITLB_MISS) |
|
|
||||||
(InterlockCurrState == STATE_T5_ITLB_MISS) | (InterlockCurrState == STATE_T7_DITLB_MISS);
|
|
||||||
|
|
||||||
-----/\----- EXCLUDED -----/\----- */
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
InterlockStall = 1'b0;
|
|
||||||
case(InterlockCurrState)
|
|
||||||
STATE_T0_READY: if(DTLBMissM | ITLBMissF) InterlockStall = 1'b1;
|
|
||||||
STATE_T3_DTLB_MISS: InterlockStall = 1'b1;
|
|
||||||
STATE_T4_ITLB_MISS: InterlockStall = 1'b1;
|
|
||||||
STATE_T5_ITLB_MISS: InterlockStall = 1'b1;
|
|
||||||
STATE_T7_DITLB_MISS: InterlockStall = 1'b1;
|
|
||||||
default: InterlockStall = 1'b0;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
// When replaying CPU memory request after PTW select the IEUAdrM for correct address.
|
|
||||||
assign SelReplayCPURequest = (InterlockNextState == STATE_T0_REPLAY);
|
|
||||||
assign SelHPTW = (InterlockCurrState == STATE_T3_DTLB_MISS) | (InterlockCurrState == STATE_T4_ITLB_MISS) |
|
|
||||||
(InterlockCurrState == STATE_T5_ITLB_MISS) | (InterlockCurrState == STATE_T7_DITLB_MISS);
|
|
||||||
assign IgnoreRequest = (InterlockCurrState == STATE_T0_READY & (ITLBMissF | DTLBMissM | ExceptionM | PendingInterruptM)) |
|
|
||||||
((InterlockCurrState == STATE_T0_REPLAY)
|
|
||||||
& (ExceptionM | PendingInterruptM));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// *** add generate to conditionally create hptw, lsuArb, and mmu
|
|
||||||
// based on `MEM_VIRTMEM
|
|
||||||
hptw hptw(.clk, .reset, .SATP_REGW, .PCF, .IEUAdrM,
|
hptw hptw(.clk, .reset, .SATP_REGW, .PCF, .IEUAdrM,
|
||||||
.ITLBMissF(ITLBMissF & ~PendingInterruptM),
|
.ITLBMissF(ITLBMissF & ~PendingInterruptM),
|
||||||
.DTLBMissM(DTLBMissM & ~PendingInterruptM),
|
.DTLBMissM(DTLBMissM & ~PendingInterruptM),
|
||||||
@ -216,25 +151,18 @@ module lsu
|
|||||||
mux2 #(12) adremux(IEUAdrE[11:0], HPTWAdr[11:0], SelHPTW, LsuAdrE);
|
mux2 #(12) adremux(IEUAdrE[11:0], HPTWAdr[11:0], SelHPTW, LsuAdrE);
|
||||||
mux2 #(`PA_BITS) lsupadrmux(IEUAdrExtM[`PA_BITS-1:0], HPTWAdr, SelHPTW, PreLsuPAdrM);
|
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;
|
assign CPUBusy = StallW & ~SelHPTW;
|
||||||
|
|
||||||
// always block interrupts when using the hardware page table walker.
|
// It is not possible to pipeline hptw as the following load will depend on the previous load's
|
||||||
|
// data. Therefore we don't need a pipeline register
|
||||||
// this is for the d cache SRAM.
|
|
||||||
// turns out because we cannot pipeline hptw requests we don't need this register
|
|
||||||
//flop #(`PA_BITS) HPTWAdrMReg(clk, HPTWAdr, HPTWAdrM); // delay HPTWAdrM by a cycle
|
//flop #(`PA_BITS) HPTWAdrMReg(clk, HPTWAdr, HPTWAdrM); // delay HPTWAdrM by a cycle
|
||||||
|
|
||||||
//assign PreLsuRWM = SelHPTW ? {HPTWRead, 1'b0} : MemRWM;
|
|
||||||
//assign LsuAdrE = SelHPTW ? HPTWAdr[11:0] : IEUAdrE[11:0];
|
|
||||||
//assign LsuAtomicM = SelHPTW ? 2'b00 : AtomicM;
|
|
||||||
//assign PreLsuPAdrM = SelHPTW ? HPTWAdr : IEUAdrExtM[`PA_BITS-1:0];
|
|
||||||
|
|
||||||
|
|
||||||
// Specify which type of page fault is occurring
|
// Specify which type of page fault is occurring
|
||||||
// *** `MEM_VIRTMEM
|
|
||||||
assign DTLBLoadPageFaultM = DTLBPageFaultM & PreLsuRWM[1];
|
assign DTLBLoadPageFaultM = DTLBPageFaultM & PreLsuRWM[1];
|
||||||
assign DTLBStorePageFaultM = DTLBPageFaultM & PreLsuRWM[0];
|
assign DTLBStorePageFaultM = DTLBPageFaultM & PreLsuRWM[0];
|
||||||
|
|
||||||
|
// When replaying CPU memory request after PTW select the IEUAdrM for correct address.
|
||||||
assign DCacheAdrE = SelReplayCPURequest ? IEUAdrM[11:0] : LsuAdrE;
|
assign DCacheAdrE = SelReplayCPURequest ? IEUAdrM[11:0] : LsuAdrE;
|
||||||
|
|
||||||
end // if (`MEM_VIRTMEM)
|
end // if (`MEM_VIRTMEM)
|
||||||
@ -263,6 +191,13 @@ module lsu
|
|||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
// **** look into this confusing signal.
|
// **** look into this confusing signal.
|
||||||
|
// This signal is confusing. CommittedM tells the CPU's trap unit the current instruction
|
||||||
|
// in the memory stage is a memory operaton and that memory operation is either completed
|
||||||
|
// or is partially executed. This signal is only low for the first cycle of a memory
|
||||||
|
// operation.
|
||||||
|
// **** I think there is also a bug here. Data cache misses and TLB misses both
|
||||||
|
// set this bit in the first cycle. It is not strickly wrong, but it may be better
|
||||||
|
// to flush the memory operation at that time.
|
||||||
assign CommittedM = SelHPTW | DCacheCommittedM | BusCommittedM;
|
assign CommittedM = SelHPTW | DCacheCommittedM | BusCommittedM;
|
||||||
|
|
||||||
generate
|
generate
|
||||||
|
Loading…
Reference in New Issue
Block a user