diff --git a/src/Cpu/FetchStage.bsv b/src/Cpu/FetchStage.bsv index 8bb20a7..419b8a8 100644 --- a/src/Cpu/FetchStage.bsv +++ b/src/Cpu/FetchStage.bsv @@ -17,17 +17,17 @@ interface FetchStage_Ifc#(numeric type xlen); endinterface module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen)); - Reg#(Epoch) epoch <- mkReg(defaultValue); - 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. + Reg#(Epoch) requestEpoch <- mkRegU; // Holds the epoch of the initiating request. + // Memory request output Reg#(Maybe#(ReadOnlyMemoryRequest#(xlen))) inflightMemoryRequest <- mkReg(tagged Invalid); 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(). + // Note: This is an unguarded FIFO so status must be checked before attempting to enq() and deq(). FIFOF#(ReadOnlyMemoryResponse#(32)) memoryResponses <- mkUGFIFOF1; // @@ -38,9 +38,8 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen)); function IF_ID#(xlen) processMemoryResponse(ReadOnlyMemoryResponse#(32) response); IF_ID#(xlen) if_id = defaultValue; if_id.common.pc = inflightMemoryRequest.Valid.address; - if_id.common.isBubble = False; if_id.npc = updatedPc + 4; - if_id.epoch = epoch; + if_id.epoch = requestEpoch; if (!response.accessFault) begin if_id.common.ir.value = response.data; @@ -81,10 +80,13 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen)); ProgramCounter#(xlen) updatedPc_ = fromMaybe(pc_if.pc, pc_if.redirection); // If a redirection was specified, reflect that with a change in the epoch. + let epoch = pc_if.epoch; if (isValid(pc_if.redirection)) begin - epoch <= ~epoch; + epoch = ~epoch; end + requestEpoch <= epoch; + // Check for a misaligned request if (updatedPc_[1:0] != 0) begin // Address request was misaligned... @@ -95,7 +97,6 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen)); }; if_id.common.pc = updatedPc_; 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 { diff --git a/src/Cpu/FetchStage_tb.bsv b/src/Cpu/FetchStage_tb.bsv index a1be71c..bcf8ec3 100644 --- a/src/Cpu/FetchStage_tb.bsv +++ b/src/Cpu/FetchStage_tb.bsv @@ -37,7 +37,6 @@ module mkTopModule(Empty); 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"); dynamicAssert(if_id.common.trap.Valid.cause == exception_INSTRUCTION_ADDRESS_MISALIGNED, "Fetch - Misaligned instruction trap check - cause is misaligned address"); dynamicAssert(if_id.npc == defaultValue, "Fetch - Misaligned instruction trap check - NPC incorrect"); @@ -78,7 +77,6 @@ module mkTopModule(Empty); 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"); dynamicAssert(if_id.common.trap.Valid.cause == exception_INSTRUCTION_ACCESS_FAULT, "Memory request denied trap check - cause is access fault"); dynamicAssert(if_id.npc == 'h104, "Fetch - Misaligned instruction trap check - NPC incorrect"); @@ -119,7 +117,6 @@ module mkTopModule(Empty); 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"); dynamicAssert(if_id.npc == 'h104, "Fetch - Normal request - NPC incorrect"); @@ -160,7 +157,6 @@ module mkTopModule(Empty); // The fetch should proceed and return a bubble. let if_id <- fetchStage32.step(pc_if); dynamicAssert(if_id.common.pc == 'h8000, "Fetch - Redirect check - common.pc"); - dynamicAssert(!if_id.common.isBubble, "Fetch - Redirect check - common.isBubble"); 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"); dynamicAssert(if_id.npc == 'h8004, "Fetch - Redirect check - NPC incorrect"); diff --git a/src/Cpu/MemoryAccessStage.bsv b/src/Cpu/MemoryAccessStage.bsv index c849d27..da69c71 100644 --- a/src/Cpu/MemoryAccessStage.bsv +++ b/src/Cpu/MemoryAccessStage.bsv @@ -20,7 +20,7 @@ module mkMemoryAccessStage#(IsaCfg#(xlen) cfg)(MemoryAccessStage_Ifc#(xlen)); 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(). + // Note: This is an unguarded FIFO so status must be checked before attempting to enq() and deq(). FIFOF#(MemoryResponse#(xlen)) memoryResponses <- mkUGFIFOF1; // @@ -29,8 +29,17 @@ module mkMemoryAccessStage#(IsaCfg#(xlen) cfg)(MemoryAccessStage_Ifc#(xlen)); // method ActionValue#(MEM_WB#(xlen)) step(EX_MEM#(xlen) ex_mem); MEM_WB#(xlen) mem_wb = defaultValue; - if (!ex_mem.common.isBubble) begin - end + + case (mem_wb.common.ir.value[6:0]) + matches 7'b0?00011: begin + // LOAD/STORE + + end + default: begin + // All other opcodes + mem_wb.common = ex_mem.common; + end + endcase return mem_wb; endmethod diff --git a/src/Cpu/PipelineRegisters.bsv b/src/Cpu/PipelineRegisters.bsv index 8431941..f1999e9 100644 --- a/src/Cpu/PipelineRegisters.bsv +++ b/src/Cpu/PipelineRegisters.bsv @@ -30,12 +30,14 @@ typedef Bit#(xlen) ProgramCounter#(numeric type xlen); typedef struct { ProgramCounter#(xlen) pc; Maybe#(ProgramCounter#(xlen)) redirection; + Epoch epoch; } PC_IF#(numeric type xlen) deriving(Bits, Eq, FShow); -instance DefaultValue #(PC_IF#(xlen)); +instance DefaultValue#(PC_IF#(xlen)); defaultValue = PC_IF { pc: 'h-1, - redirection: tagged Invalid + redirection: tagged Invalid, + epoch: defaultValue }; endinstance @@ -45,7 +47,6 @@ endinstance typedef struct { Instruction ir; ProgramCounter#(xlen) pc; - Bool isBubble; Maybe#(Trap#(xlen)) trap; } PipelineRegisterCommon#(numeric type xlen) deriving(Bits, Eq, FShow); @@ -53,7 +54,6 @@ instance DefaultValue #(PipelineRegisterCommon#(xlen)); defaultValue = PipelineRegisterCommon { ir: defaultValue, pc: defaultValue, - isBubble: True, trap: tagged Invalid }; endinstance