E-Series/src/Cpu/FetchStage.bsv
2023-03-17 23:43:25 -07:00

106 lines
3.9 KiB
Plaintext

import IsaCfg::*;
import MemoryTypes::*;
import PipelineRegisters::*;
import RV_ISA::*;
import Trap::*;
import Assert::*;
import ClientServer::*;
import FIFOF::*;
import GetPut::*;
import Memory::*;
interface FetchStage_Ifc#(numeric type xlen);
method ActionValue#(IF_ID#(xlen)) step(PC_IF#(xlen) pc_if);
interface ReadOnlyMemoryClient#(xlen, 32) memoryClient;
endinterface
module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen));
Reg#(Bool) stall <- mkReg(False);
Reg#(Bool) externalStall <- mkReg(False);
// Memory request output
Reg#(Bool) memoryRequestInFlight <- mkReg(False);
Wire#(ReadOnlyMemoryRequest#(xlen)) memoryRequest <- mkWire;
// Memory response input (FIFO)
// Note: This is an unguarded FIFO so status much be checked before attempting to enq() and deq().
FIFOF#(ReadOnlyMemoryResponse#(32)) memoryResponses <- mkUGFIFOF1;
//
// processMemoryResponse - takes a memory response and returns an IF_ID containing
// the encoded instruction (or a trap if the original request
// was denied by the memory system)
//
function IF_ID#(xlen) processMemoryResponse(PC_IF#(xlen) pc_if, ReadOnlyMemoryResponse#(32) response);
IF_ID#(xlen) if_id = defaultValue;
if_id.common.pc = pc_if.pc;
if_id.common.isBubble = False;
if_id.npc = pc_if.pc + 4;
if (!response.accessFault) begin
if_id.common.ir.value = response.data;
if_id.common.trap = tagged Invalid;
end else begin
Trap#(xlen) trap = Trap {
cause: exception_INSTRUCTION_ACCESS_FAULT,
isInterrupt: False,
tval: 0
};
if_id.common.trap = tagged Valid(trap);
end
return if_id;
endfunction
method ActionValue#(IF_ID#(xlen)) step(PC_IF#(xlen) pc_if);
IF_ID#(xlen) if_id = defaultValue;
if (!pc_if.isBubble) begin
// If there's an active request, handle it if it's returned
if (memoryRequestInFlight) begin
if (memoryResponses.notEmpty) begin
if_id = processMemoryResponse(pc_if, memoryResponses.first);
memoryResponses.deq;
memoryRequestInFlight <= False;
end else begin
// Memory request is in flight but hasn't returned yet.
end
end else begin
// No memory request is in flight...
// Check for a misaligned request
if (pc_if.pc[1:0] != 0) begin
// Address request was misaligned...
Trap#(xlen) trap = Trap {
cause: exception_INSTRUCTION_ADDRESS_MISALIGNED,
isInterrupt: False,
tval: 0
};
if_id.common.pc = pc_if.pc;
if_id.common.trap = tagged Valid(trap);
if_id.common.isBubble = False;
end else begin
// Construct a memory request and send it out.
ReadOnlyMemoryRequest#(xlen) request = ReadOnlyMemoryRequest {
address: pc_if.pc
};
memoryRequest <= request;
memoryRequestInFlight <= True;
end
end
end
return if_id;
endmethod
interface ReadOnlyMemoryClient memoryClient;
interface Get request = toGet(memoryRequest);
interface Put response;
method Action put(ReadOnlyMemoryResponse#(32) response);
dynamicAssert(memoryResponses.notFull, "FetchStage - attempt to put a memory respnose on a full queue");
memoryResponses.enq(response);
endmethod
endinterface
endinterface
endmodule