2021-06-23 22:03:54 +00:00
|
|
|
///////////////////////////////////////////
|
|
|
|
// lsuArb.sv
|
|
|
|
//
|
|
|
|
// Written: Ross THompson and Kip Macsai-Goren
|
|
|
|
// Modified: kmacsaigoren@hmc.edu June 23, 2021
|
|
|
|
//
|
|
|
|
// Purpose: LSU arbiter between the CPU's demand request for data memory and
|
|
|
|
// the page table walker
|
|
|
|
//
|
|
|
|
// 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"
|
|
|
|
|
2021-06-24 18:05:22 +00:00
|
|
|
module lsuArb
|
|
|
|
(input logic clk, reset,
|
|
|
|
|
|
|
|
// from page table walker
|
|
|
|
input logic HPTWTranslate,
|
2021-06-30 16:24:26 +00:00
|
|
|
input logic HPTWRead,
|
2021-06-24 18:05:22 +00:00
|
|
|
input logic [`XLEN-1:0] HPTWPAdr,
|
|
|
|
// to page table walker.
|
|
|
|
output logic [`XLEN-1:0] HPTWReadPTE,
|
2021-06-28 22:26:11 +00:00
|
|
|
output logic HPTWStall,
|
2021-06-24 18:05:22 +00:00
|
|
|
|
|
|
|
// from CPU
|
|
|
|
input logic [1:0] MemRWM,
|
|
|
|
input logic [2:0] Funct3M,
|
|
|
|
input logic [1:0] AtomicM,
|
|
|
|
input logic [`XLEN-1:0] MemAdrM,
|
|
|
|
input logic [`XLEN-1:0] WriteDataM,
|
2021-06-28 22:26:11 +00:00
|
|
|
input logic StallW,
|
2021-06-24 18:05:22 +00:00
|
|
|
// to CPU
|
|
|
|
output logic [`XLEN-1:0] ReadDataW,
|
|
|
|
output logic CommittedM,
|
|
|
|
output logic SquashSCW,
|
|
|
|
output logic DataMisalignedM,
|
|
|
|
output logic DCacheStall,
|
|
|
|
|
|
|
|
// to LSU
|
|
|
|
output logic DisableTranslation,
|
|
|
|
output logic [1:0] MemRWMtoLSU,
|
2021-07-04 22:56:30 +00:00
|
|
|
output logic [2:0] SizeToLSU,
|
2021-06-24 18:05:22 +00:00
|
|
|
output logic [1:0] AtomicMtoLSU,
|
|
|
|
output logic [`XLEN-1:0] MemAdrMtoLSU,
|
|
|
|
output logic [`XLEN-1:0] WriteDataMtoLSU,
|
2021-06-28 22:26:11 +00:00
|
|
|
output logic StallWtoLSU,
|
2021-06-24 18:05:22 +00:00
|
|
|
// from LSU
|
|
|
|
input logic CommittedMfromLSU,
|
|
|
|
input logic SquashSCWfromLSU,
|
|
|
|
input logic DataMisalignedMfromLSU,
|
|
|
|
input logic [`XLEN-1:0] ReadDataWFromLSU,
|
|
|
|
input logic DataStall
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
// HPTWTranslate is the request for memory by the page table walker. When
|
|
|
|
// this is high the page table walker gains priority over the CPU's data
|
|
|
|
// input. Note the ptw only makes a request after an instruction or data
|
|
|
|
// tlb miss. It is entirely possible the dcache is currently processing
|
|
|
|
// a data cache miss when an instruction tlb miss occurs. If an instruction
|
|
|
|
// in the E stage causes a d cache miss, the d cache will immediately start
|
|
|
|
// processing the request. Simultaneously the ITLB misses. By the time
|
|
|
|
// the TLB miss causes the page table walker to issue the first request
|
|
|
|
// to data memory the d cache is already busy. We can interlock by
|
|
|
|
// leveraging Stall as a d cache busy. We will need an FSM to handle this.
|
|
|
|
|
2021-06-30 21:25:03 +00:00
|
|
|
typedef enum{StateReady,
|
|
|
|
StatePTWPending,
|
|
|
|
StatePTWActive} statetype;
|
|
|
|
|
2021-06-24 18:05:22 +00:00
|
|
|
|
2021-06-30 21:25:03 +00:00
|
|
|
statetype CurrState, NextState;
|
2021-06-24 18:05:22 +00:00
|
|
|
logic SelPTW;
|
2021-06-30 03:33:57 +00:00
|
|
|
logic HPTWStallD;
|
2021-07-04 22:56:30 +00:00
|
|
|
logic [2:0] PTWSize;
|
2021-06-24 18:05:22 +00:00
|
|
|
|
2021-06-23 23:59:06 +00:00
|
|
|
|
2021-06-30 21:25:03 +00:00
|
|
|
flopenl #(.TYPE(statetype)) StateReg(.clk(clk),
|
|
|
|
.load(reset),
|
|
|
|
.en(1'b1),
|
|
|
|
.d(NextState),
|
|
|
|
.val(StateReady),
|
|
|
|
.q(CurrState));
|
2021-06-24 18:05:22 +00:00
|
|
|
|
|
|
|
always_comb begin
|
|
|
|
case(CurrState)
|
|
|
|
StateReady:
|
2021-07-01 22:37:53 +00:00
|
|
|
if (HPTWTranslate) NextState = StatePTWActive;
|
|
|
|
else NextState = StateReady;
|
|
|
|
StatePTWActive:
|
|
|
|
if (HPTWTranslate) NextState = StatePTWActive;
|
|
|
|
else NextState = StateReady;
|
|
|
|
default: NextState = StateReady;
|
|
|
|
endcase
|
|
|
|
end
|
|
|
|
|
2021-06-30 21:25:03 +00:00
|
|
|
/* -----\/----- EXCLUDED -----\/-----
|
2021-07-01 22:37:53 +00:00
|
|
|
|
|
|
|
always_comb begin
|
|
|
|
case(CurrState)
|
|
|
|
StateReady:
|
|
|
|
/-* -----\/----- EXCLUDED -----\/-----
|
|
|
|
if (HPTWTranslate & DataStall) NextState = StatePTWPending;
|
|
|
|
else
|
|
|
|
-----/\----- EXCLUDED -----/\----- *-/
|
|
|
|
if (HPTWTranslate) NextState = StatePTWActive;
|
|
|
|
else NextState = StateReady;
|
2021-06-24 18:05:22 +00:00
|
|
|
StatePTWPending:
|
2021-07-01 22:37:53 +00:00
|
|
|
if (HPTWTranslate & ~DataStall) NextState = StatePTWActive;
|
|
|
|
else if (HPTWTranslate & DataStall) NextState = StatePTWPending;
|
|
|
|
else NextState = StateReady;
|
2021-06-24 18:05:22 +00:00
|
|
|
StatePTWActive:
|
2021-07-01 22:37:53 +00:00
|
|
|
if (HPTWTranslate) NextState = StatePTWActive;
|
|
|
|
else NextState = StateReady;
|
2021-06-25 00:01:11 +00:00
|
|
|
default: NextState = StateReady;
|
|
|
|
endcase
|
2021-06-24 18:05:22 +00:00
|
|
|
end
|
|
|
|
|
2021-07-01 22:37:53 +00:00
|
|
|
-----/\----- EXCLUDED -----/\----- */
|
2021-06-24 18:05:22 +00:00
|
|
|
|
|
|
|
// multiplex the outputs to LSU
|
|
|
|
assign DisableTranslation = SelPTW; // change names between SelPTW would be confusing in DTLB.
|
2021-07-01 17:49:09 +00:00
|
|
|
assign SelPTW = (CurrState == StatePTWActive && HPTWTranslate) || (CurrState == StateReady && HPTWTranslate);
|
2021-06-30 16:24:26 +00:00
|
|
|
assign MemRWMtoLSU = SelPTW ? {HPTWRead, 1'b0} : MemRWM;
|
2021-06-23 23:59:06 +00:00
|
|
|
|
|
|
|
generate
|
2021-07-04 22:52:16 +00:00
|
|
|
assign PTWSize = (`XLEN==32 ? 3'b010 : 3'b011); // 32 or 64-bit access from htpw
|
2021-06-23 23:59:06 +00:00
|
|
|
endgenerate
|
2021-07-04 22:56:30 +00:00
|
|
|
mux2 #(3) sizemux(Funct3M, PTWSize, SelPTW, SizeToLSU);
|
2021-06-23 23:59:06 +00:00
|
|
|
|
2021-06-24 18:05:22 +00:00
|
|
|
assign AtomicMtoLSU = SelPTW ? 2'b00 : AtomicM;
|
|
|
|
assign MemAdrMtoLSU = SelPTW ? HPTWPAdr : MemAdrM;
|
|
|
|
assign WriteDataMtoLSU = SelPTW ? `XLEN'b0 : WriteDataM;
|
2021-06-28 22:26:11 +00:00
|
|
|
assign StallWtoLSU = SelPTW ? 1'b0 : StallW;
|
2021-06-23 22:03:54 +00:00
|
|
|
|
2021-06-24 18:05:22 +00:00
|
|
|
// demux the inputs from LSU to walker or cpu's data port.
|
2021-06-23 22:03:54 +00:00
|
|
|
|
2021-06-24 18:05:22 +00:00
|
|
|
assign ReadDataW = SelPTW ? `XLEN'b0 : ReadDataWFromLSU; // probably can avoid this demux
|
|
|
|
assign HPTWReadPTE = SelPTW ? ReadDataWFromLSU : `XLEN'b0 ; // probably can avoid this demux
|
|
|
|
assign CommittedM = SelPTW ? 1'b0 : CommittedMfromLSU;
|
|
|
|
assign SquashSCW = SelPTW ? 1'b0 : SquashSCWfromLSU;
|
|
|
|
assign DataMisalignedM = SelPTW ? 1'b0 : DataMisalignedMfromLSU;
|
2021-06-28 22:26:11 +00:00
|
|
|
// *** need to rename DcacheStall and Datastall.
|
|
|
|
// not clear at all. I think it should be LSUStall from the LSU,
|
|
|
|
// which is demuxed to HPTWStall and CPUDataStall? (not sure on this last one).
|
2021-06-30 21:25:03 +00:00
|
|
|
assign HPTWStall = SelPTW ? DataStall : 1'b1;
|
|
|
|
//assign HPTWStallD = SelPTW ? DataStall : 1'b1;
|
|
|
|
/* -----\/----- EXCLUDED -----\/-----
|
2021-06-30 03:33:57 +00:00
|
|
|
assign HPTWStallD = SelPTW ? DataStall : 1'b1;
|
|
|
|
flopr #(1) HPTWStallReg (.clk(clk),
|
|
|
|
.reset(reset),
|
|
|
|
.d(HPTWStallD),
|
|
|
|
.q(HPTWStall));
|
2021-06-30 21:25:03 +00:00
|
|
|
-----/\----- EXCLUDED -----/\----- */
|
2021-06-30 03:33:57 +00:00
|
|
|
|
2021-07-01 17:49:09 +00:00
|
|
|
assign DCacheStall = SelPTW ? 1'b1 : DataStall; // *** this is probably going to change.
|
2021-06-24 18:05:22 +00:00
|
|
|
|
2021-06-23 22:03:54 +00:00
|
|
|
endmodule
|