More fetch stage refactoring
This commit is contained in:
parent
1fad6db424
commit
9881cf00d4
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
//
|
//
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user