diff --git a/src/Cpu/FetchStage.bsv b/src/Cpu/FetchStage.bsv index 0b89be1..d5f6060 100644 --- a/src/Cpu/FetchStage.bsv +++ b/src/Cpu/FetchStage.bsv @@ -11,7 +11,7 @@ import GetPut::*; import Memory::*; interface FetchStage_Ifc#(numeric type xlen); - method ActionValue#(IF_ID#(xlen)) step(ProgramCounter#(xlen) pc, Maybe#(ProgramCounter#(xlen)) redirection); + method ActionValue#(IF_ID#(xlen)) step(PC_IF#(xlen) pc_if); interface ReadOnlyMemoryClient#(xlen, 32) memoryClient; endinterface @@ -58,7 +58,7 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen)); // 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(ProgramCounter#(xlen) pc, Maybe#(ProgramCounter#(xlen)) redirection); + method ActionValue#(IF_ID#(xlen)) step(PC_IF#(xlen) pc_if); IF_ID#(xlen) if_id = defaultValue; // If there's an active request, handle it if it's returned @@ -75,7 +75,7 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen)); // Determine the PC the instruction will be fetchted from. It's either the calculated PC // or a redirected PC (due to a branch, jump, exception, etc) - ProgramCounter#(xlen) updatedPc_ = fromMaybe(pc, redirection); + ProgramCounter#(xlen) updatedPc_ = fromMaybe(pc_if.pc, pc_if.redirection); // Check for a misaligned request if (updatedPc_[1:0] != 0) begin diff --git a/src/Cpu/FetchStage_tb.bsv b/src/Cpu/FetchStage_tb.bsv index 3f30676..bae73e6 100644 --- a/src/Cpu/FetchStage_tb.bsv +++ b/src/Cpu/FetchStage_tb.bsv @@ -12,7 +12,7 @@ import FIFOF::*; import GetPut::*; module mkTopModule(Empty); - Reg#(Bit#(20)) testNumber <- mkReg(0); + Reg#(Bit#(20)) stepNumber <- mkReg(0); // 32 bit IsaCfg#(32) rv32 = IsaCfg{ @@ -27,14 +27,15 @@ module mkTopModule(Empty); (* no_implicit_conditions *) rule test; + PC_IF#(32) pc_if = defaultValue; - case(testNumber) + case(stepNumber) // Misaligned instruction trap 0: begin - ProgramCounter#(32) pc = 'h101; + pc_if.pc = 'h101; - let if_id <- fetchStage32.step(pc, tagged Invalid); - dynamicAssert(if_id.common.pc == pc, "Fetch - Misaligned instruction trap check - common.pc"); + let if_id <- fetchStage32.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(!if_id.common.isBubble, "Fetch - Misaligned instruction trap check - common.isBubble"); dynamicAssert(isValid(if_id.common.trap), "Fetch - Misaligned instruction trap check - contains trap"); @@ -43,19 +44,19 @@ module mkTopModule(Empty); // Memory request denied trap (request submit) 1: begin - ProgramCounter#(32) pc = 'h100; + pc_if.pc = 'h100; // The fetch should proceed and return a bubble. - let if_id <- fetchStage32.step(pc, tagged Invalid); + let if_id <- fetchStage32.step(pc_if); dynamicAssert(if_id == defaultValue, "Fetch - Memory request denied trap check - request should return a bubble"); end // Memory request denied trap (request receipt) 2: begin - ProgramCounter#(32) pc = 'h100; + pc_if.pc = 'h100; // Ensure the fetch returns a bubble while the memory request is in flight - let if_id <- fetchStage32.step(pc, tagged Invalid); + let if_id <- fetchStage32.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"); @@ -71,11 +72,11 @@ module mkTopModule(Empty); // Memory request denied trap (return trap check) 3: begin - ProgramCounter#(32) pc = 'h100; + pc_if.pc = 'h100; // The fetch should proceed and return a bubble. - let if_id <- fetchStage32.step(pc, tagged Invalid); - dynamicAssert(if_id.common.pc == pc, "Fetch - Memory request denied trap check - common.pc"); + let if_id <- fetchStage32.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(!if_id.common.isBubble, "Fetch - Memory request denied trap check - common.isBubble"); dynamicAssert(isValid(if_id.common.trap), "Fetch - Memory request denied trap check - contains trap"); @@ -84,19 +85,19 @@ module mkTopModule(Empty); // Normal memory request (request submit) 4: begin - ProgramCounter#(32) pc = 'h100; + pc_if.pc = 'h100; // The fetch should proceed and return a bubble. - let if_id <- fetchStage32.step(pc, tagged Invalid); + let if_id <- fetchStage32.step(pc_if); dynamicAssert(if_id == defaultValue, "Fetch - Normal request - request should return a bubble"); end // Normal memory request (request receipt) 5: begin - ProgramCounter#(32) pc = 'h100; + pc_if.pc = 'h100; // Ensure the fetch returns a bubble while the memory request is in flight - let if_id <- fetchStage32.step(pc, tagged Invalid); + let if_id <- fetchStage32.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"); @@ -112,25 +113,25 @@ module mkTopModule(Empty); // Normal memory request (return value check) 6: begin - ProgramCounter#(32) pc = 'h100; + pc_if.pc = 'h100; // The fetch should proceed and return a bubble. - let if_id <- fetchStage32.step(pc, tagged Invalid); - dynamicAssert(if_id.common.pc == pc, "Fetch - Normal request - common.pc"); + let if_id <- fetchStage32.step(pc_if); + dynamicAssert(if_id.common.pc == pc_if.pc, "Fetch - Normal request - common.pc"); dynamicAssert(!if_id.common.isBubble, "Fetch - Normal request - common.isBubble"); 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"); end default: begin - dynamicAssert(testNumber == 7, "Fetch - not all tests run"); + dynamicAssert(stepNumber == 7, "Fetch - not all tests run"); $display(">>>PASS"); $finish(); end endcase endrule - rule increment_test_number; - testNumber <= testNumber + 1; + rule increment_step_number; + stepNumber <= stepNumber + 1; endrule endmodule diff --git a/src/Cpu/PipelineRegisters.bsv b/src/Cpu/PipelineRegisters.bsv index 60cba39..192d56c 100644 --- a/src/Cpu/PipelineRegisters.bsv +++ b/src/Cpu/PipelineRegisters.bsv @@ -19,6 +19,21 @@ endinstance // typedef Bit#(xlen) ProgramCounter#(numeric type xlen); +// +// PC_IF +// +typedef struct { + ProgramCounter#(xlen) pc; + Maybe#(ProgramCounter#(xlen)) redirection; +} PC_IF#(numeric type xlen) deriving(Bits, Eq, FShow); + +instance DefaultValue #(PC_IF#(xlen)); + defaultValue = PC_IF { + pc: 'h-1, + redirection: tagged Invalid + }; +endinstance + // // PipelineRegisterCommon //