More fetch stage refactoring

This commit is contained in:
John Terrell 2023-03-24 08:19:13 -07:00
parent 1fad6db424
commit 9881cf00d4
Signed by untrusted user who does not match committer: johnt
GPG Key ID: 2E424258DD3731F4
3 changed files with 41 additions and 25 deletions

View File

@ -11,7 +11,7 @@ import GetPut::*;
import Memory::*; import Memory::*;
interface FetchStage_Ifc#(numeric type xlen); 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; interface ReadOnlyMemoryClient#(xlen, 32) memoryClient;
endinterface 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 // 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. // 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_ID#(xlen) if_id = defaultValue;
// If there's an active request, handle it if it's returned // 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 // 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) // 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 // Check for a misaligned request
if (updatedPc_[1:0] != 0) begin if (updatedPc_[1:0] != 0) begin

View File

@ -12,7 +12,7 @@ import FIFOF::*;
import GetPut::*; import GetPut::*;
module mkTopModule(Empty); module mkTopModule(Empty);
Reg#(Bit#(20)) testNumber <- mkReg(0); Reg#(Bit#(20)) stepNumber <- mkReg(0);
// 32 bit // 32 bit
IsaCfg#(32) rv32 = IsaCfg{ IsaCfg#(32) rv32 = IsaCfg{
@ -27,14 +27,15 @@ module mkTopModule(Empty);
(* no_implicit_conditions *) (* no_implicit_conditions *)
rule test; rule test;
PC_IF#(32) pc_if = defaultValue;
case(testNumber) case(stepNumber)
// Misaligned instruction trap // Misaligned instruction trap
0: begin 0: begin
ProgramCounter#(32) pc = 'h101; pc_if.pc = 'h101;
let if_id <- fetchStage32.step(pc, tagged Invalid); let if_id <- fetchStage32.step(pc_if);
dynamicAssert(if_id.common.pc == pc, "Fetch - Misaligned instruction trap check - common.pc"); 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.ir == defaultValue, "Fetch - Misaligned instruction trap check - common.ir");
dynamicAssert(!if_id.common.isBubble, "Fetch - Misaligned instruction trap check - common.isBubble"); 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(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) // Memory request denied trap (request submit)
1: begin 1: begin
ProgramCounter#(32) pc = 'h100; pc_if.pc = 'h100;
// The fetch should proceed and return a bubble. // 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"); dynamicAssert(if_id == defaultValue, "Fetch - Memory request denied trap check - request should return a bubble");
end end
// Memory request denied trap (request receipt) // Memory request denied trap (request receipt)
2: begin 2: begin
ProgramCounter#(32) pc = 'h100; pc_if.pc = 'h100;
// Ensure the fetch returns a bubble while the memory request is in flight // 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(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"); 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) // Memory request denied trap (return trap check)
3: begin 3: begin
ProgramCounter#(32) pc = 'h100; pc_if.pc = 'h100;
// The fetch should proceed and return a bubble. // 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.common.pc == pc, "Fetch - Memory request denied trap check - common.pc"); 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.ir == defaultValue, "Fetch - Memory request denied trap check - common.ir");
dynamicAssert(!if_id.common.isBubble, "Fetch - Memory request denied trap check - common.isBubble"); 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(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) // Normal memory request (request submit)
4: begin 4: begin
ProgramCounter#(32) pc = 'h100; pc_if.pc = 'h100;
// The fetch should proceed and return a bubble. // 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"); dynamicAssert(if_id == defaultValue, "Fetch - Normal request - request should return a bubble");
end end
// Normal memory request (request receipt) // Normal memory request (request receipt)
5: begin 5: begin
ProgramCounter#(32) pc = 'h100; pc_if.pc = 'h100;
// Ensure the fetch returns a bubble while the memory request is in flight // 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(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"); 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) // Normal memory request (return value check)
6: begin 6: begin
ProgramCounter#(32) pc = 'h100; pc_if.pc = 'h100;
// The fetch should proceed and return a bubble. // 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.common.pc == pc, "Fetch - Normal request - common.pc"); dynamicAssert(if_id.common.pc == pc_if.pc, "Fetch - Normal request - common.pc");
dynamicAssert(!if_id.common.isBubble, "Fetch - Normal request - common.isBubble"); dynamicAssert(!if_id.common.isBubble, "Fetch - Normal request - common.isBubble");
dynamicAssert(!isValid(if_id.common.trap), "Fetch - Normal request - contains no trap"); 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.common.ir.value == 'haabb_ccdd, "Fetch - Normal request - contains expected instruction data");
end end
default: begin default: begin
dynamicAssert(testNumber == 7, "Fetch - not all tests run"); dynamicAssert(stepNumber == 7, "Fetch - not all tests run");
$display(">>>PASS"); $display(">>>PASS");
$finish(); $finish();
end end
endcase endcase
endrule endrule
rule increment_test_number; rule increment_step_number;
testNumber <= testNumber + 1; stepNumber <= stepNumber + 1;
endrule endrule
endmodule endmodule

View File

@ -19,6 +19,21 @@ endinstance
// //
typedef Bit#(xlen) ProgramCounter#(numeric type xlen); 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 // PipelineRegisterCommon
// //