diff --git a/src/Cpu/DecodeStage.bsv b/src/Cpu/DecodeStage.bsv index 0d1ecad..9181792 100644 --- a/src/Cpu/DecodeStage.bsv +++ b/src/Cpu/DecodeStage.bsv @@ -5,7 +5,9 @@ import PipelineRegisters::*; import RV_ISA::*; import Trap::*; -interface DecodeStageIfc#(numeric type xlen); +import GetPut::*; + +interface DecodeModuleIfc#(numeric type xlen); method ActionValue#(ID_EX#(xlen)) step( IF_ID#(xlen) if_id, GprReadPort#(xlen) gprReadPort1, @@ -14,7 +16,7 @@ interface DecodeStageIfc#(numeric type xlen); ); endinterface -module mkDecodeStage#(IsaCfg#(xlen) cfg)(DecodeStageIfc#(xlen)) +module mkDecodeModule#(IsaCfg#(xlen) cfg)(DecodeModuleIfc#(xlen)) provisos( Add#(a__, 20, xlen), Add#(b__, 5, xlen), @@ -121,3 +123,43 @@ module mkDecodeStage#(IsaCfg#(xlen) cfg)(DecodeStageIfc#(xlen)) return id_ex; endmethod endmodule + +interface DecodeStageIfc#(numeric type xlen); + interface Put#(IF_ID#(xlen)) put; + interface Get#(ID_EX#(xlen)) get; +endinterface + +module mkDecodeStage#(IsaCfg#(xlen) cfg, + GprReadPort#(xlen) gprReadPort1, + GprReadPort#(xlen) gprReadPort2, + CsrReadPort#(xlen) csrReadPort)(DecodeStageIfc#(xlen)) + provisos( + Add#(a__, 20, xlen), + Add#(b__, 5, xlen), + Add#(c__, 13, xlen), + Add#(d__, 21, xlen), + Add#(e__, 12, xlen) + ); + + // + // State + // + Wire#(IF_ID#(xlen)) if_id <- mkWire; + Reg#(ID_EX#(xlen)) id_ex <- mkRegU; + DecodeModuleIfc#(xlen) decodeModule <- mkDecodeModule(cfg); + + // + // Rules + // + (* no_implicit_conditions *) + rule step; + let id_ex_ <- decodeModule.step(if_id, gprReadPort1, gprReadPort2, csrReadPort); + id_ex <= id_ex_; + endrule + + // + // Interfaces + // + interface Put put = toPut(asIfc(if_id)); + interface Get get = toGet(id_ex); +endmodule diff --git a/src/Cpu/DecodeStage_tb.bsv b/src/Cpu/DecodeStage_tb.bsv index 8fadafd..ca13da9 100644 --- a/src/Cpu/DecodeStage_tb.bsv +++ b/src/Cpu/DecodeStage_tb.bsv @@ -16,7 +16,7 @@ module mkTopModule(Empty); extS: False, extU: False }; - DecodeStageIfc#(32) decodeStage32 <- mkDecodeStage(rv32); + DecodeModuleIfc#(32) decodeModule32 <- mkDecodeModule(rv32); // // GPR diff --git a/src/Cpu/FetchStage.bsv b/src/Cpu/FetchStage.bsv index 616359b..c88d249 100644 --- a/src/Cpu/FetchStage.bsv +++ b/src/Cpu/FetchStage.bsv @@ -12,13 +12,13 @@ import Memory::*; typedef ReadOnlyMemoryRequest#(xlen, 32) InstructionMemoryRequest#(numeric type xlen); -interface FetchStageIfc#(numeric type xlen); +interface FetchModuleIfc#(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)(FetchStageIfc#(xlen)); +module mkFetchModule#(IsaCfg#(xlen) cfg)(FetchModuleIfc#(xlen)); Reg#(ProgramCounter#(xlen)) updatedPc <- mkRegU; // Holds the updated PC that is calculated when a fetch is issued // that is used to update the PC when the fetch completes. @@ -125,3 +125,35 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStageIfc#(xlen)); endinterface endinterface endmodule + +interface FetchStageIfc#(numeric type xlen); + interface Put#(PC_IF#(xlen)) put; + interface Get#(IF_ID#(xlen)) get; + + interface ReadOnlyMemoryClient#(xlen, 32) memoryClient; +endinterface + +module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStageIfc#(xlen)); + // + // State + // + Wire#(PC_IF#(xlen)) pc_if <- mkWire; + Reg#(IF_ID#(xlen)) if_id <- mkRegU; + FetchModuleIfc#(xlen) fetchModule <- mkFetchModule(cfg); + + // + // Rules + // + (* no_implicit_conditions *) + rule step; + let if_id_ <- fetchModule.step(pc_if); + if_id <= if_id_; + endrule + + // + // Interfaces + // + interface Put put = toPut(asIfc(pc_if)); + interface Get get = toGet(if_id); + interface MemoryClient memoryClient = fetchModule.memoryClient; +endmodule diff --git a/src/Cpu/FetchStage_tb.bsv b/src/Cpu/FetchStage_tb.bsv index 6600fcb..734fd17 100644 --- a/src/Cpu/FetchStage_tb.bsv +++ b/src/Cpu/FetchStage_tb.bsv @@ -20,10 +20,10 @@ module mkTopModule(Empty); extS: False, extU: False }; - FetchStageIfc#(32) fetchStage32 <- mkFetchStage(rv32); + FetchModuleIfc#(32) fetchModule32 <- mkFetchModule(rv32); FIFOF#(InstructionMemoryRequest#(32)) memoryRequests32 <- mkUGFIFOF1(); - mkConnection(fetchStage32.memoryClient.request, toPut(asIfc(memoryRequests32))); + mkConnection(fetchModule32.memoryClient.request, toPut(asIfc(memoryRequests32))); (* no_implicit_conditions *) rule test; @@ -34,7 +34,7 @@ module mkTopModule(Empty); 0: begin pc_if.pc = 'h101; - let if_id <- fetchStage32.step(pc_if); + let if_id <- fetchModule32.step(pc_if); dynamicAssert(if_id.common.pc == pc_if.pc, "Fetch - Misaligned instruction trap check - common.pc"); dynamicAssert(if_id.common.ir == defaultValue, "Fetch - Misaligned instruction trap check - common.ir"); dynamicAssert(isValid(if_id.common.trap), "Fetch - Misaligned instruction trap check - contains trap"); @@ -47,7 +47,7 @@ module mkTopModule(Empty); pc_if.pc = 'h100; // The fetch should proceed and return a bubble. - let if_id <- fetchStage32.step(pc_if); + let if_id <- fetchModule32.step(pc_if); dynamicAssert(if_id == defaultValue, "Fetch - Memory request denied trap check - request should return a bubble"); end @@ -56,7 +56,7 @@ module mkTopModule(Empty); pc_if.pc = 'h100; // Ensure the fetch returns a bubble while the memory request is in flight - let if_id <- fetchStage32.step(pc_if); + let if_id <- fetchModule32.step(pc_if); dynamicAssert(if_id == defaultValue, "Fetch - Memory request denied trap check - request should return a bubble while fetch is in flight"); dynamicAssert(memoryRequests32.notEmpty, "Fetch - Memory request denied trap check - memory request queue should not be empty"); @@ -64,7 +64,8 @@ module mkTopModule(Empty); memoryRequests32.deq; dynamicAssert(memoryRequest.address == 'h100, "Fetch - Memory request denied trap check - memory request should have correct address"); - fetchStage32.memoryClient.response.put(FallibleMemoryResponse { + dynamicAssert(memoryRequest.byteen == 'b1111, "Fetch - Memory request denied trap check - memory request byte enable should be 'b1111"); + fetchModule32.memoryClient.response.put(FallibleMemoryResponse { data: 'h-1, accessFault: True }); @@ -74,7 +75,7 @@ module mkTopModule(Empty); 3: begin pc_if.pc = 'h100; - let if_id <- fetchStage32.step(pc_if); + let if_id <- fetchModule32.step(pc_if); dynamicAssert(if_id.common.pc == pc_if.pc, "Fetch - Memory request denied trap check - common.pc"); dynamicAssert(if_id.common.ir == defaultValue, "Fetch - Memory request denied trap check - common.ir"); dynamicAssert(isValid(if_id.common.trap), "Fetch - Memory request denied trap check - contains trap"); @@ -88,7 +89,7 @@ module mkTopModule(Empty); pc_if.pc = 'h100; // The fetch should proceed and return a bubble. - let if_id <- fetchStage32.step(pc_if); + let if_id <- fetchModule32.step(pc_if); dynamicAssert(if_id == defaultValue, "Fetch - Normal request - request should return a bubble"); end @@ -97,7 +98,7 @@ module mkTopModule(Empty); pc_if.pc = 'h100; // Ensure the fetch returns a bubble while the memory request is in flight - let if_id <- fetchStage32.step(pc_if); + let if_id <- fetchModule32.step(pc_if); dynamicAssert(if_id == defaultValue, "Fetch - Normal request - request should return a bubble while fetch is in flight"); dynamicAssert(memoryRequests32.notEmpty, "Fetch - Normal request - memory request queue should not be empty"); @@ -105,7 +106,8 @@ module mkTopModule(Empty); memoryRequests32.deq; dynamicAssert(memoryRequest.address == 'h100, "Fetch - Normal request - memory request should have correct address"); - fetchStage32.memoryClient.response.put(FallibleMemoryResponse { + dynamicAssert(memoryRequest.byteen == 'b1111, "Fetch - Normal request - memory request byte enable should be 'b1111"); + fetchModule32.memoryClient.response.put(FallibleMemoryResponse { data: 'haabb_ccdd, accessFault: False }); @@ -115,7 +117,7 @@ module mkTopModule(Empty); 6: begin pc_if.pc = 'h100; - let if_id <- fetchStage32.step(pc_if); + let if_id <- fetchModule32.step(pc_if); dynamicAssert(if_id.common.pc == pc_if.pc, "Fetch - Normal request - common.pc"); dynamicAssert(!isValid(if_id.common.trap), "Fetch - Normal request - contains no trap"); dynamicAssert(if_id.common.ir.value == 'haabb_ccdd, "Fetch - Normal request - contains expected instruction data"); @@ -129,7 +131,7 @@ module mkTopModule(Empty); pc_if.redirection = tagged Valid 'h8000; // The fetch should proceed and return a bubble. - let if_id <- fetchStage32.step(pc_if); + let if_id <- fetchModule32.step(pc_if); dynamicAssert(if_id == defaultValue, "Fetch - Redirect check - request should return a bubble"); end @@ -138,7 +140,7 @@ module mkTopModule(Empty); pc_if.pc = 'h100; // Ensure the fetch returns a bubble while the memory request is in flight - let if_id <- fetchStage32.step(pc_if); + let if_id <- fetchModule32.step(pc_if); dynamicAssert(if_id == defaultValue, "Fetch - Redirect check - request should return a bubble while fetch is in flight"); dynamicAssert(memoryRequests32.notEmpty, "Fetch - Redirect check - memory request queue should not be empty"); @@ -146,7 +148,8 @@ module mkTopModule(Empty); memoryRequests32.deq; dynamicAssert(memoryRequest.address == 'h8000, "Fetch - Redirect check - memory request should have correct address"); - fetchStage32.memoryClient.response.put(FallibleMemoryResponse { + dynamicAssert(memoryRequest.byteen == 'b1111, "Fetch - Redirect check - memory request byte enable should be 'b1111"); + fetchModule32.memoryClient.response.put(FallibleMemoryResponse { data: 'haabb_ccee, accessFault: False }); @@ -156,7 +159,7 @@ module mkTopModule(Empty); 9: begin pc_if.pc = 'h100; - let if_id <- fetchStage32.step(pc_if); + let if_id <- fetchModule32.step(pc_if); dynamicAssert(if_id.common.pc == 'h8000, "Fetch - Redirect check - common.pc"); dynamicAssert(!isValid(if_id.common.trap), "Fetch - Redirect check - contains no trap"); dynamicAssert(if_id.common.ir.value == 'haabb_ccee, "Fetch - Redirect check - contains expected instruction data"); diff --git a/src/Cpu/MemoryAccessStage.bsv b/src/Cpu/MemoryAccessStage.bsv index f0e577c..2397a99 100644 --- a/src/Cpu/MemoryAccessStage.bsv +++ b/src/Cpu/MemoryAccessStage.bsv @@ -9,12 +9,12 @@ import FIFOF::*; import GetPut::*; import Memory::*; -interface MemoryAccessStageIfc#(numeric type xlen); +interface MemoryAccessModuleIfc#(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)(MemoryAccessStageIfc#(xlen)); +module mkMemoryAccessModule#(IsaCfg#(xlen) cfg)(MemoryAccessModuleIfc#(xlen)); // Memory request output Reg#(Bool) memoryRequestInFlight <- mkReg(False); Wire#(MemoryRequest#(xlen, xlen)) memoryRequest <- mkWire; @@ -54,3 +54,32 @@ module mkMemoryAccessStage#(IsaCfg#(xlen) cfg)(MemoryAccessStageIfc#(xlen)); endinterface endinterface endmodule + +interface MemoryAccessStageIfc#(numeric type xlen); + interface Put#(EX_MEM#(xlen)) put; + interface Get#(MEM_WB#(xlen)) get; +endinterface + +module mkMemoryAccessStage#(IsaCfg#(xlen) cfg)(MemoryAccessStageIfc#(xlen)); + // + // State + // + Wire#(EX_MEM#(xlen)) ex_mem <- mkWire; + Reg#(MEM_WB#(xlen)) mem_wb <- mkRegU; + MemoryAccessModuleIfc#(xlen) memoryAccessModule <- mkMemoryAccessModule(cfg); + + // + // Rules + // + (* no_implicit_conditions *) + rule step; + let mem_wb_ <- memoryAccessModule.step(ex_mem); + mem_wb <= mem_wb_; + endrule + + // + // Interfaces + // + interface Put put = toPut(asIfc(ex_mem)); + interface Get get = toGet(mem_wb); +endmodule diff --git a/src/Cpu/MemoryAccessStage_tb.bsv b/src/Cpu/MemoryAccessStage_tb.bsv index e3d31fc..6664415 100644 --- a/src/Cpu/MemoryAccessStage_tb.bsv +++ b/src/Cpu/MemoryAccessStage_tb.bsv @@ -20,11 +20,11 @@ module mkTopModule(Empty); extS: False, extU: False }; - MemoryAccessStageIfc#(32) memoryAccessStage32 <- mkMemoryAccessStage(rv32); + MemoryAccessModuleIfc#(32) memoryAccessModule32 <- mkMemoryAccessModule(rv32); FIFOF#(MemoryRequest#(32, 32)) memoryRequests32 <- mkUGFIFOF1(); - mkConnection(memoryAccessStage32.memoryClient.request, toPut(asIfc(memoryRequests32))); + mkConnection(memoryAccessModule32.memoryClient.request, toPut(asIfc(memoryRequests32))); (* no_implicit_conditions *) rule test; @@ -33,7 +33,7 @@ module mkTopModule(Empty); case(testNumber) // Simple bubble passthrough 0: begin - let mem_wb <- memoryAccessStage32.step(ex_mem); + let mem_wb <- memoryAccessModule32.step(ex_mem); dynamicAssert(mem_wb == defaultValue, "MemoryAccess - Bubble passthrough check"); end