Fixed up NPC and Epoch handling.
This commit is contained in:
parent
9881cf00d4
commit
61d2a7cab4
@ -17,6 +17,8 @@ interface FetchStage_Ifc#(numeric type xlen);
|
|||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen));
|
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
|
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.
|
// that is used to update the PC when the fetch completes.
|
||||||
|
|
||||||
@ -37,7 +39,8 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen));
|
|||||||
IF_ID#(xlen) if_id = defaultValue;
|
IF_ID#(xlen) if_id = defaultValue;
|
||||||
if_id.common.pc = inflightMemoryRequest.Valid.address;
|
if_id.common.pc = inflightMemoryRequest.Valid.address;
|
||||||
if_id.common.isBubble = False;
|
if_id.common.isBubble = False;
|
||||||
if_id.npc = updatedPc;
|
if_id.npc = updatedPc + 4;
|
||||||
|
if_id.epoch = epoch;
|
||||||
|
|
||||||
if (!response.accessFault) begin
|
if (!response.accessFault) begin
|
||||||
if_id.common.ir.value = response.data;
|
if_id.common.ir.value = response.data;
|
||||||
@ -73,10 +76,15 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen));
|
|||||||
end else begin
|
end else begin
|
||||||
// No memory request is in flight...
|
// No memory request is in flight...
|
||||||
|
|
||||||
// Determine the PC the instruction will be fetchted from. It's either the calculated PC
|
// Determine the PC the instruction will be fetched 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_if.pc, pc_if.redirection);
|
ProgramCounter#(xlen) updatedPc_ = fromMaybe(pc_if.pc, pc_if.redirection);
|
||||||
|
|
||||||
|
// If a redirection was specified, reflect that with a change in the epoch.
|
||||||
|
if (isValid(pc_if.redirection)) begin
|
||||||
|
epoch <= ~epoch;
|
||||||
|
end
|
||||||
|
|
||||||
// Check for a misaligned request
|
// Check for a misaligned request
|
||||||
if (updatedPc_[1:0] != 0) begin
|
if (updatedPc_[1:0] != 0) begin
|
||||||
// Address request was misaligned...
|
// Address request was misaligned...
|
||||||
|
|||||||
@ -40,6 +40,7 @@ module mkTopModule(Empty);
|
|||||||
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");
|
||||||
dynamicAssert(if_id.common.trap.Valid.cause == exception_INSTRUCTION_ADDRESS_MISALIGNED, "Fetch - Misaligned instruction trap check - cause is misaligned address");
|
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");
|
||||||
end
|
end
|
||||||
|
|
||||||
// Memory request denied trap (request submit)
|
// Memory request denied trap (request submit)
|
||||||
@ -74,13 +75,14 @@ module mkTopModule(Empty);
|
|||||||
3: begin
|
3: begin
|
||||||
pc_if.pc = 'h100;
|
pc_if.pc = 'h100;
|
||||||
|
|
||||||
// The fetch should proceed and return a bubble.
|
|
||||||
let if_id <- fetchStage32.step(pc_if);
|
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.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");
|
||||||
dynamicAssert(if_id.common.trap.Valid.cause == exception_INSTRUCTION_ACCESS_FAULT, "Memory request denied trap check - cause is access fault");
|
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");
|
||||||
|
dynamicAssert(if_id.epoch == defaultValue, "Fetch - Misaligned instruction trap check - Verify epoch unchanged");
|
||||||
end
|
end
|
||||||
|
|
||||||
// Normal memory request (request submit)
|
// Normal memory request (request submit)
|
||||||
@ -115,16 +117,58 @@ module mkTopModule(Empty);
|
|||||||
6: begin
|
6: begin
|
||||||
pc_if.pc = 'h100;
|
pc_if.pc = 'h100;
|
||||||
|
|
||||||
// The fetch should proceed and return a bubble.
|
|
||||||
let if_id <- fetchStage32.step(pc_if);
|
let if_id <- fetchStage32.step(pc_if);
|
||||||
dynamicAssert(if_id.common.pc == pc_if.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");
|
||||||
|
dynamicAssert(if_id.npc == 'h104, "Fetch - Normal request - NPC incorrect");
|
||||||
|
dynamicAssert(if_id.epoch == defaultValue, "Fetch - Normal request - Verify epoch unchanged");
|
||||||
|
end
|
||||||
|
|
||||||
|
// Redirect handling check
|
||||||
|
7: begin
|
||||||
|
pc_if.pc = 'h100;
|
||||||
|
pc_if.redirection = tagged Valid 'h8000;
|
||||||
|
|
||||||
|
// The fetch should proceed and return a bubble.
|
||||||
|
let if_id <- fetchStage32.step(pc_if);
|
||||||
|
dynamicAssert(if_id == defaultValue, "Fetch - Redirect check - request should return a bubble");
|
||||||
|
end
|
||||||
|
|
||||||
|
8: begin
|
||||||
|
pc_if.pc = 'h100;
|
||||||
|
|
||||||
|
// Ensure the fetch returns a bubble while the memory request is in flight
|
||||||
|
let if_id <- fetchStage32.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");
|
||||||
|
let memoryRequest = memoryRequests32.first;
|
||||||
|
memoryRequests32.deq;
|
||||||
|
|
||||||
|
dynamicAssert(memoryRequest.address == 'h8000, "Fetch - Redirect check - memory request should have correct address");
|
||||||
|
fetchStage32.memoryClient.response.put(ReadOnlyMemoryResponse {
|
||||||
|
data: 'haabb_ccee,
|
||||||
|
accessFault: False
|
||||||
|
});
|
||||||
|
end
|
||||||
|
|
||||||
|
9: begin
|
||||||
|
pc_if.pc = 'h100;
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
dynamicAssert(if_id.epoch == 'h1, "Fetch - Redirect check - Verify epoch changed");
|
||||||
end
|
end
|
||||||
|
|
||||||
default: begin
|
default: begin
|
||||||
dynamicAssert(stepNumber == 7, "Fetch - not all tests run");
|
dynamicAssert(stepNumber == 10, "Fetch - not all tests run");
|
||||||
$display(">>>PASS");
|
$display(">>>PASS");
|
||||||
$finish();
|
$finish();
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
import Trap::*;
|
import Trap::*;
|
||||||
import DefaultValue::*;
|
import DefaultValue::*;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Epoch
|
||||||
|
//
|
||||||
|
typedef Bit#(1) Epoch;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Instruction
|
// Instruction
|
||||||
//
|
//
|
||||||
@ -58,14 +63,14 @@ endinstance
|
|||||||
//
|
//
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PipelineRegisterCommon#(xlen) common;
|
PipelineRegisterCommon#(xlen) common;
|
||||||
Bit#(1) epoch;
|
Epoch epoch;
|
||||||
ProgramCounter#(xlen) npc; // Next program counter
|
ProgramCounter#(xlen) npc; // Next program counter
|
||||||
} IF_ID#(numeric type xlen) deriving(Bits, Eq, FShow);
|
} IF_ID#(numeric type xlen) deriving(Bits, Eq, FShow);
|
||||||
|
|
||||||
instance DefaultValue #(IF_ID#(xlen));
|
instance DefaultValue #(IF_ID#(xlen));
|
||||||
defaultValue = IF_ID {
|
defaultValue = IF_ID {
|
||||||
common: defaultValue,
|
common: defaultValue,
|
||||||
epoch: 'h-1,
|
epoch: defaultValue,
|
||||||
npc: defaultValue
|
npc: defaultValue
|
||||||
};
|
};
|
||||||
endinstance
|
endinstance
|
||||||
@ -75,7 +80,7 @@ endinstance
|
|||||||
//
|
//
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PipelineRegisterCommon#(xlen) common;
|
PipelineRegisterCommon#(xlen) common;
|
||||||
Bit#(1) epoch;
|
Epoch epoch;
|
||||||
ProgramCounter#(xlen) npc; // Next program counter
|
ProgramCounter#(xlen) npc; // Next program counter
|
||||||
Bit#(xlen) a; // Operand 1
|
Bit#(xlen) a; // Operand 1
|
||||||
Bit#(xlen) b; // Operand 2
|
Bit#(xlen) b; // Operand 2
|
||||||
@ -86,7 +91,7 @@ typedef struct {
|
|||||||
instance DefaultValue #(ID_EX#(xlen));
|
instance DefaultValue #(ID_EX#(xlen));
|
||||||
defaultValue = ID_EX {
|
defaultValue = ID_EX {
|
||||||
common: defaultValue,
|
common: defaultValue,
|
||||||
epoch: 0,
|
epoch: defaultValue,
|
||||||
npc: defaultValue,
|
npc: defaultValue,
|
||||||
a: 'h-1,
|
a: 'h-1,
|
||||||
b: 'h-1,
|
b: 'h-1,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user