mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-22 13:07:33 -04:00
early branch aliasing correction support
This commit is contained in:
parent
1beda7d033
commit
303ac3be16
5 changed files with 52 additions and 17 deletions
|
@ -46,6 +46,7 @@ module fetch(
|
|||
ras_interface.fetch ras,
|
||||
|
||||
//Instruction Metadata
|
||||
output logic early_branch_flush,
|
||||
output logic [31:0] if_pc,
|
||||
output logic [31:0] fetch_instruction,
|
||||
|
||||
|
@ -53,7 +54,10 @@ module fetch(
|
|||
local_memory_interface.master instruction_bram,
|
||||
input logic icache_on,
|
||||
l1_arbiter_request_interface.master l1_request,
|
||||
l1_arbiter_return_interface.master l1_response
|
||||
l1_arbiter_return_interface.master l1_response,
|
||||
|
||||
//Trace Interface
|
||||
output logic tr_early_branch_correction
|
||||
);
|
||||
|
||||
localparam NUM_SUB_UNITS = USE_I_SCRATCH_MEM + USE_ICACHE;
|
||||
|
@ -75,6 +79,7 @@ module fetch(
|
|||
logic address_valid;
|
||||
|
||||
typedef struct packed{
|
||||
logic is_predicted_branch_or_jump;
|
||||
logic address_valid;
|
||||
logic mmu_fault;
|
||||
logic [NUM_SUB_UNITS_W-1:0] subunit_id;
|
||||
|
@ -102,7 +107,7 @@ module fetch(
|
|||
//Implementation
|
||||
////////////////////////////////////////////////////
|
||||
//Fetch PC
|
||||
assign update_pc = new_mem_request | gc_fetch_flush;
|
||||
assign update_pc = new_mem_request | gc_fetch_flush | early_branch_flush;
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
pc <= RESET_VEC;
|
||||
|
@ -117,7 +122,7 @@ module fetch(
|
|||
next_pc = gc_fetch_pc;
|
||||
else if (branch_flush)
|
||||
next_pc = bp.branch_flush_pc;
|
||||
else if (bp.use_prediction)
|
||||
else if (bp.use_prediction & ~early_branch_flush)
|
||||
next_pc = bp.is_return ? ras.addr : bp.predicted_pc;
|
||||
else
|
||||
next_pc = pc_plus_4;
|
||||
|
@ -127,7 +132,7 @@ module fetch(
|
|||
//hold the fetching of data from memory until the status of the
|
||||
//exception has been resolved
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst | gc_fetch_flush)
|
||||
if (flush_or_rst)
|
||||
exception_pending <= 0;
|
||||
else if (tlb.is_fault | (new_mem_request & ~address_valid))
|
||||
exception_pending <= 1;
|
||||
|
@ -137,10 +142,10 @@ module fetch(
|
|||
assign bp.next_pc = next_pc;
|
||||
assign bp.if_pc = pc;
|
||||
|
||||
assign ras.pop = bp.use_prediction & bp.is_return & ~branch_flush & ~gc_fetch_pc_override & new_mem_request;
|
||||
assign ras.push = bp.use_prediction & bp.is_call & ~branch_flush & ~gc_fetch_pc_override & new_mem_request;
|
||||
assign ras.pop = bp.use_prediction & bp.is_return & ~branch_flush & ~gc_fetch_pc_override & new_mem_request & (~early_branch_flush);
|
||||
assign ras.push = bp.use_prediction & bp.is_call & ~branch_flush & ~gc_fetch_pc_override & new_mem_request & (~early_branch_flush);
|
||||
assign ras.new_addr = pc_plus_4;
|
||||
assign ras.branch_fetched = bp.use_prediction & bp.is_branch & new_mem_request; //flush not needed as FIFO resets inside of RAS
|
||||
assign ras.branch_fetched = bp.use_prediction & bp.is_branch & new_mem_request & (~early_branch_flush); //flush not needed as FIFO resets inside of RAS
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//TLB
|
||||
|
@ -157,9 +162,9 @@ module fetch(
|
|||
|
||||
//////////////////////////////////////////////
|
||||
//Issue Control Signals
|
||||
assign flush_or_rst = (rst | gc_fetch_flush);
|
||||
assign flush_or_rst = (rst | gc_fetch_flush | early_branch_flush);
|
||||
|
||||
assign new_mem_request = (~tlb_on | tlb.done) & pc_id_available & units_ready & ~gc_fetch_hold & ~exception_pending;
|
||||
assign new_mem_request = (~tlb_on | tlb.done) & pc_id_available & units_ready & (~gc_fetch_hold) & (~exception_pending);
|
||||
assign pc_id_assigned = new_mem_request | tlb.is_fault;
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
@ -173,6 +178,7 @@ module fetch(
|
|||
.one_hot (sub_unit_address_match),
|
||||
.int_out (fetch_attr_next.subunit_id)
|
||||
);
|
||||
assign fetch_attr_next.is_predicted_branch_or_jump = bp.use_prediction;
|
||||
assign fetch_attr_next.address_valid = address_valid;
|
||||
assign fetch_attr_next.mmu_fault = tlb.is_fault;
|
||||
|
||||
|
@ -231,12 +237,25 @@ module fetch(
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Instruction metada updates
|
||||
logic valid_fetch_result;
|
||||
assign valid_fetch_result = fetch_attr_fifo.valid & fetch_attr.address_valid & (~fetch_attr.mmu_fault);
|
||||
|
||||
assign if_pc = pc;
|
||||
assign fetch_instruction = unit_data_array[fetch_attr.subunit_id];
|
||||
assign fetch_complete = (|unit_data_valid) | (fetch_attr_fifo.valid & ~fetch_attr.address_valid);//allow instruction to propagate to decode if address is invalid
|
||||
assign fetch_metadata.ok = fetch_attr.address_valid & ~fetch_attr.mmu_fault;
|
||||
assign fetch_metadata.ok = valid_fetch_result;
|
||||
assign fetch_metadata.error_code = fetch_attr.mmu_fault ? FETCH_PAGE_FAULT : FETCH_ACCESS_FAULT;
|
||||
|
||||
assign fetch_instruction = unit_data_array[fetch_attr.subunit_id];
|
||||
assign fetch_complete = ((fetch_attr_fifo.valid & ~valid_fetch_result) | (|unit_data_valid) & (~early_branch_flush));//allow instruction to propagate to decode if address is invalid
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Branch Predictor correction
|
||||
logic is_branch_or_jump;
|
||||
assign is_branch_or_jump = fetch_instruction[6:2] inside {JAL_T, JALR_T, BRANCH_T};
|
||||
assign early_branch_flush = (valid_fetch_result & (|unit_data_valid)) & fetch_attr.is_predicted_branch_or_jump & (~is_branch_or_jump);
|
||||
generate if (ENABLE_TRACE_INTERFACE) begin
|
||||
assign tr_early_branch_correction = early_branch_flush;
|
||||
end endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -39,6 +39,7 @@ module instruction_metadata_and_id_management
|
|||
input logic pc_id_assigned,
|
||||
|
||||
output id_t fetch_id,
|
||||
input logic early_branch_flush,
|
||||
input logic fetch_complete,
|
||||
input logic [31:0] fetch_instruction,
|
||||
input fetch_metadata_t fetch_metadata,
|
||||
|
@ -176,8 +177,13 @@ module instruction_metadata_and_id_management
|
|||
//On a fetch buffer flush, the next ID is restored to the current decode ID.
|
||||
//This prevents a stall in the case where all IDs are either in-flight or
|
||||
//in the fetch buffer at the point of a fetch flush.
|
||||
id_t next_pc_id_base;
|
||||
id_t next_fetch_id_base;
|
||||
assign next_pc_id_base = gc_fetch_flush ? decode_id : (early_branch_flush ? fetch_id : pc_id);
|
||||
assign next_fetch_id_base = gc_fetch_flush ? decode_id : fetch_id;
|
||||
|
||||
assign pc_id_next = gc_init_clear ? clear_index :
|
||||
((gc_fetch_flush ? decode_id : pc_id) + LOG2_MAX_IDS'({pc_id_assigned & ~gc_fetch_flush}));
|
||||
(next_pc_id_base + LOG2_MAX_IDS'({pc_id_assigned & ~gc_fetch_flush}));
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
pc_id <= 0;
|
||||
|
@ -185,8 +191,8 @@ module instruction_metadata_and_id_management
|
|||
decode_id <= 0;
|
||||
end
|
||||
else begin
|
||||
pc_id <= (gc_fetch_flush ? decode_id : pc_id) + LOG2_MAX_IDS'({pc_id_assigned & ~gc_fetch_flush});
|
||||
fetch_id <= (gc_fetch_flush ? decode_id : fetch_id) + LOG2_MAX_IDS'({fetch_complete & ~gc_fetch_flush});
|
||||
pc_id <= next_pc_id_base + LOG2_MAX_IDS'({pc_id_assigned & (~gc_fetch_flush) & (~early_branch_flush)});
|
||||
fetch_id <= next_fetch_id_base + LOG2_MAX_IDS'({fetch_complete & ~gc_fetch_flush});
|
||||
decode_id <= decode_id + LOG2_MAX_IDS'({decode_advance & ~gc_fetch_flush});
|
||||
end
|
||||
end
|
||||
|
|
|
@ -94,6 +94,7 @@ module taiga (
|
|||
id_t fetch_id;
|
||||
logic fetch_complete;
|
||||
logic [31:0] fetch_instruction;
|
||||
logic early_branch_flush;
|
||||
fetch_metadata_t fetch_metadata;
|
||||
//Decode stage
|
||||
logic decode_advance;
|
||||
|
@ -150,6 +151,7 @@ module taiga (
|
|||
id_t id_for_rd [COMMIT_PORTS];
|
||||
|
||||
//Trace Interface Signals
|
||||
logic tr_early_branch_correction;
|
||||
logic tr_operand_stall;
|
||||
logic tr_unit_stall;
|
||||
logic tr_no_id_stall;
|
||||
|
@ -216,6 +218,7 @@ module taiga (
|
|||
.if_pc (if_pc),
|
||||
.pc_id_assigned (pc_id_assigned),
|
||||
.fetch_id (fetch_id),
|
||||
.early_branch_flush (early_branch_flush),
|
||||
.fetch_complete (fetch_complete),
|
||||
.fetch_instruction (fetch_instruction),
|
||||
.fetch_metadata (fetch_metadata),
|
||||
|
@ -259,6 +262,7 @@ module taiga (
|
|||
.fetch_metadata (fetch_metadata),
|
||||
.bp (bp),
|
||||
.ras (ras),
|
||||
.early_branch_flush (early_branch_flush),
|
||||
.if_pc (if_pc),
|
||||
.fetch_instruction (fetch_instruction),
|
||||
.instruction_bram (instruction_bram),
|
||||
|
@ -267,7 +271,8 @@ module taiga (
|
|||
.tlb_on (tlb_on),
|
||||
.l1_request(l1_request[L1_ICACHE_ID]),
|
||||
.l1_response(l1_response[L1_ICACHE_ID]),
|
||||
.exception(1'b0)
|
||||
.exception(1'b0),
|
||||
.tr_early_branch_correction (tr_early_branch_correction)
|
||||
);
|
||||
|
||||
branch_predictor bp_block (
|
||||
|
@ -291,7 +296,7 @@ module taiga (
|
|||
tlb_lut_ram #(ITLB_WAYS, ITLB_DEPTH) i_tlb (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.abort_request (gc_fetch_flush),
|
||||
.abort_request (gc_fetch_flush | early_branch_flush),
|
||||
.gc_tlb_flush (gc_tlb_flush),
|
||||
.asid (asid),
|
||||
.tlb (itlb),
|
||||
|
@ -556,6 +561,7 @@ module taiga (
|
|||
//Trace Interface
|
||||
generate if (ENABLE_TRACE_INTERFACE) begin
|
||||
always_ff @(posedge clk) begin
|
||||
tr.events.early_branch_correction <= tr_early_branch_correction;
|
||||
tr.events.operand_stall <= tr_operand_stall;
|
||||
tr.events.unit_stall <= tr_unit_stall;
|
||||
tr.events.no_id_stall <= tr_no_id_stall;
|
||||
|
|
|
@ -232,6 +232,9 @@ package taiga_types;
|
|||
} fifo_type_t;
|
||||
|
||||
typedef struct packed {
|
||||
//Fetch
|
||||
logic early_branch_correction;
|
||||
|
||||
//Decode
|
||||
logic operand_stall;
|
||||
logic unit_stall;
|
||||
|
|
|
@ -39,6 +39,7 @@ template <typename T, int N>
|
|||
constexpr int arraySize(T(&)[N]) { return N; }
|
||||
|
||||
static const char * const eventNames[] = {
|
||||
"early_branch_correction",
|
||||
"operand_stall",
|
||||
"unit_stall",
|
||||
"no_id_stall",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue