From c36dfd55aefa18dc8c7439e43211d40031fa3591 Mon Sep 17 00:00:00 2001 From: John Terrell Date: Sat, 18 Mar 2023 12:43:56 -0700 Subject: [PATCH] Initial skeleton MemoryAccessStage with testbench. --- src/Cpu/FetchStage.bsv | 11 +++---- src/Cpu/FetchStage_tb.bsv | 8 ----- src/Cpu/MemoryAccessStage.bsv | 43 +++++++++++++++++++++++++++ src/Cpu/MemoryAccessStage_tb.bsv | 50 ++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 src/Cpu/MemoryAccessStage.bsv create mode 100644 src/Cpu/MemoryAccessStage_tb.bsv diff --git a/src/Cpu/FetchStage.bsv b/src/Cpu/FetchStage.bsv index 16d183d..33c78cc 100644 --- a/src/Cpu/FetchStage.bsv +++ b/src/Cpu/FetchStage.bsv @@ -16,11 +16,8 @@ interface FetchStage_Ifc#(numeric type xlen); 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); + Reg#(Bool) memoryRequestInFlight <- mkReg(False); Wire#(ReadOnlyMemoryRequest#(xlen)) memoryRequest <- mkWire; // Memory response input (FIFO) @@ -28,7 +25,7 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen)); FIFOF#(ReadOnlyMemoryResponse#(32)) memoryResponses <- mkUGFIFOF1; // - // processMemoryResponse - takes a memory response and returns an IF_ID containing + // 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) // @@ -53,6 +50,10 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen)); return if_id; endfunction + // + // step - Execute fetch step by sending an instruction memory request if one isn't already in flight and + // responding to any responses that have returned. If a request is in flight, a bubble is returned. + // method ActionValue#(IF_ID#(xlen)) step(PC_IF#(xlen) pc_if); IF_ID#(xlen) if_id = defaultValue; if (!pc_if.isBubble) begin diff --git a/src/Cpu/FetchStage_tb.bsv b/src/Cpu/FetchStage_tb.bsv index 299919c..e9c3b98 100644 --- a/src/Cpu/FetchStage_tb.bsv +++ b/src/Cpu/FetchStage_tb.bsv @@ -26,14 +26,6 @@ module mkTopModule(Empty); mkConnection(fetchStage32.memoryClient.request, toPut(asIfc(memoryRequests32))); - // 64 bit - IsaCfg#(64) rv64 = IsaCfg{ - extN: False, - extS: False, - extU: False - }; - FetchStage_Ifc#(64) fetchStage64 <- mkFetchStage(rv64); - (* no_implicit_conditions *) rule test; PC_IF#(32) pc_if = defaultValue; diff --git a/src/Cpu/MemoryAccessStage.bsv b/src/Cpu/MemoryAccessStage.bsv new file mode 100644 index 0000000..4a8cbd9 --- /dev/null +++ b/src/Cpu/MemoryAccessStage.bsv @@ -0,0 +1,43 @@ +import IsaCfg::*; +import PipelineRegisters::*; +import RV_ISA::*; +import Trap::*; + +import Assert::*; +import ClientServer::*; +import FIFOF::*; +import GetPut::*; +import Memory::*; + +interface MemoryAccessStage_Ifc#(numeric type xlen); + method ActionValue#(MEM_WB#(xlen)) step(EX_MEM#(xlen) ex_mem); + interface MemoryClient#(xlen, xlen) memoryClient; +endinterface + +module mkMemoryAccessStage#(IsaCfg#(xlen) cfg)(MemoryAccessStage_Ifc#(xlen)); + // Memory request output + Reg#(Bool) memoryRequestInFlight <- mkReg(False); + Wire#(MemoryRequest#(xlen, 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#(MemoryResponse#(xlen)) memoryResponses <- mkUGFIFOF1; + + // + // step - Execute memory access step by sending a data memory request (if needed) if one isn't already in flight and + // responding to any responses that have returned. If a request is in flight, a bubble is returned. + // + method ActionValue#(MEM_WB#(xlen)) step(EX_MEM#(xlen) ex_mem); + return defaultValue; + endmethod + + interface MemoryClient memoryClient; + interface Get request = toGet(memoryRequest); + interface Put response; + method Action put(MemoryResponse#(xlen) response); + dynamicAssert(memoryResponses.notFull, "MemoryStage - attempt to put a memory respnose on a full queue"); + memoryResponses.enq(response); + endmethod + endinterface + endinterface +endmodule diff --git a/src/Cpu/MemoryAccessStage_tb.bsv b/src/Cpu/MemoryAccessStage_tb.bsv new file mode 100644 index 0000000..4a0ca2c --- /dev/null +++ b/src/Cpu/MemoryAccessStage_tb.bsv @@ -0,0 +1,50 @@ +import MemoryAccessStage::*; +import IsaCfg::*; +import PipelineRegisters::*; +import RV_ISA::*; +import Trap::*; + +import Assert::*; +import ClientServer::*; +import Connectable::*; +import FIFOF::*; +import GetPut::*; +import Memory::*; + +module mkTopModule(Empty); + Reg#(Bit#(20)) testNumber <- mkReg(0); + + // 32 bit + IsaCfg#(32) rv32 = IsaCfg{ + extN: False, + extS: False, + extU: False + }; + MemoryAccessStage_Ifc#(32) memoryAccessStage32 <- mkMemoryAccessStage(rv32); + + FIFOF#(MemoryRequest#(32, 32)) memoryRequests32 <- mkUGFIFOF1(); + + mkConnection(memoryAccessStage32.memoryClient.request, toPut(asIfc(memoryRequests32))); + + (* no_implicit_conditions *) + rule test; + EX_MEM#(32) ex_mem = defaultValue; + + case(testNumber) + // Simple bubble passthrough + 0: begin + let mem_wb <- memoryAccessStage32.step(ex_mem); + dynamicAssert(mem_wb == defaultValue, "MemoryAccess - Bubble passthrough check"); + end + + default: begin + $display(">>>PASS"); + $finish(); + end + endcase + endrule + + rule increment_test_number; + testNumber <= testNumber + 1; + endrule +endmodule