mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-23 05:27:23 -04:00
exception updates
This commit is contained in:
parent
279efe70a9
commit
56c5b2bbf3
8 changed files with 141 additions and 131 deletions
|
@ -46,6 +46,7 @@ module csr_unit
|
|||
//GC
|
||||
input logic interrupt_taken,
|
||||
output logic interrupt_pending,
|
||||
output logic processing_csr,
|
||||
|
||||
//TLB and MMU
|
||||
output logic tlb_on,
|
||||
|
@ -102,6 +103,8 @@ module csr_unit
|
|||
endfunction
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
assign processing_csr = busy | issue.new_request;
|
||||
|
||||
assign issue.ready = ~busy;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
|
|
|
@ -25,6 +25,7 @@ module decode_and_issue
|
|||
import taiga_config::*;
|
||||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
import csr_types::*;
|
||||
|
||||
# (
|
||||
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG,
|
||||
|
@ -40,6 +41,7 @@ module decode_and_issue
|
|||
input logic pc_id_available,
|
||||
input decode_packet_t decode,
|
||||
output logic decode_advance,
|
||||
output exception_sources_t decode_exception_unit,
|
||||
|
||||
//Renamer
|
||||
renamer_interface.decode renamer,
|
||||
|
@ -68,9 +70,9 @@ module decode_and_issue
|
|||
unit_issue_interface.decode unit_issue [NUM_UNITS-1:0],
|
||||
|
||||
input gc_outputs_t gc,
|
||||
output logic gc_flush_required,
|
||||
input logic [1:0] current_privilege,
|
||||
|
||||
output logic illegal_instruction,
|
||||
exception_interface.unit exception,
|
||||
|
||||
//Trace signals
|
||||
output logic tr_operand_stall,
|
||||
|
@ -124,6 +126,7 @@ module decode_and_issue
|
|||
logic [NUM_UNITS-1:0] issue_ready;
|
||||
logic [NUM_UNITS-1:0] issue_to;
|
||||
|
||||
logic pre_issue_exception_pending;
|
||||
logic illegal_instruction_pattern;
|
||||
|
||||
logic issue_stage_ready;
|
||||
|
@ -197,16 +200,16 @@ module decode_and_issue
|
|||
assign decode_rs_wb_group[RS1] = renamer.rs_wb_group[RS1];
|
||||
assign decode_rs_wb_group[RS2] = renamer.rs_wb_group[RS2];
|
||||
|
||||
|
||||
//TODO: Consider ways of parameterizing so that any exception generating unit
|
||||
//can be automatically added to this expression
|
||||
exception_sources_t decode_exception_unit;
|
||||
always_comb begin
|
||||
unique case (1'b1)
|
||||
unit_needed[UNIT_IDS.LS] : decode_exception_unit = LS_EXCEPTION;
|
||||
unit_needed[UNIT_IDS.BR] : decode_exception_unit = BR_EXCEPTION;
|
||||
default : decode_exception_unit = IEC_EXCEPTION;
|
||||
default : decode_exception_unit = PRE_ISSUE_EXCEPTION;
|
||||
endcase
|
||||
if (illegal_instruction_pattern)
|
||||
decode_exception_unit = PRE_ISSUE_EXCEPTION;
|
||||
end
|
||||
////////////////////////////////////////////////////
|
||||
//Issue
|
||||
|
@ -261,7 +264,7 @@ module decode_and_issue
|
|||
assign operands_ready = (~rs1_conflict) & (~rs2_conflict);
|
||||
|
||||
assign issue_ready = unit_needed_issue_stage & unit_ready;
|
||||
assign issue_valid = issue.stage_valid & operands_ready & ~gc.issue_hold;
|
||||
assign issue_valid = issue.stage_valid & operands_ready & ~gc.issue_hold & ~pre_issue_exception_pending;
|
||||
|
||||
assign issue_to = {NUM_UNITS{issue_valid & ~gc.fetch_flush}} & issue_ready;
|
||||
|
||||
|
@ -467,10 +470,10 @@ module decode_and_issue
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Global Control unit inputs
|
||||
logic potential_flush;
|
||||
logic is_ecall;
|
||||
logic is_ebreak;
|
||||
logic is_ret;
|
||||
logic is_ecall_r;
|
||||
logic is_ebreak_r;
|
||||
logic is_mret_r;
|
||||
logic is_sret_r;
|
||||
logic is_ifence_r;
|
||||
|
||||
logic [7:0] sys_op_match;
|
||||
|
@ -488,7 +491,6 @@ module decode_and_issue
|
|||
case (decode.instruction[31:20]) inside
|
||||
ECALL_imm : sys_op_match[ECALL_i] = CONFIG.INCLUDE_M_MODE;
|
||||
EBREAK_imm : sys_op_match[EBREAK_i] = CONFIG.INCLUDE_M_MODE;
|
||||
URET_imm : sys_op_match[URET_i] = CONFIG.INCLUDE_U_MODE;
|
||||
SRET_imm : sys_op_match[SRET_i] = CONFIG.INCLUDE_S_MODE;
|
||||
MRET_imm : sys_op_match[MRET_i] = CONFIG.INCLUDE_M_MODE;
|
||||
SFENCE_imm : sys_op_match[SFENCE_i] = CONFIG.INCLUDE_S_MODE;
|
||||
|
@ -498,22 +500,18 @@ module decode_and_issue
|
|||
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue_stage_ready) begin
|
||||
is_ecall <= environment_op & sys_op_match[ECALL_i];
|
||||
is_ebreak <= environment_op & sys_op_match[EBREAK_i];
|
||||
is_ret <= environment_op & (sys_op_match[URET_i] | sys_op_match[SRET_i] | sys_op_match[MRET_i]);
|
||||
is_ecall_r <= sys_op_match[ECALL_i];
|
||||
is_ebreak_r <= sys_op_match[EBREAK_i];
|
||||
is_mret_r <= sys_op_match[MRET_i];
|
||||
is_sret_r <= sys_op_match[SRET_i];
|
||||
is_ifence_r <= is_ifence;
|
||||
potential_flush <= (environment_op | is_ifence);
|
||||
end
|
||||
end
|
||||
|
||||
assign gc_inputs.is_ecall = is_ecall;
|
||||
assign gc_inputs.is_ebreak = is_ebreak;
|
||||
assign gc_inputs.is_ret = is_ret;
|
||||
assign gc_inputs.pc_p4 = constant_alu;
|
||||
assign gc_inputs.instruction = issue.instruction;
|
||||
assign gc_inputs.is_i_fence = CONFIG.INCLUDE_M_MODE & issue_to[UNIT_IDS.IEC] & is_ifence_r;
|
||||
|
||||
assign gc_flush_required = CONFIG.INCLUDE_M_MODE && issue_to[UNIT_IDS.IEC] && potential_flush;
|
||||
assign gc_inputs.is_ifence = is_ifence_r;
|
||||
assign gc_inputs.is_mret = is_mret_r;
|
||||
assign gc_inputs.is_mret = is_sret_r;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//CSR unit inputs
|
||||
|
@ -580,20 +578,65 @@ module decode_and_issue
|
|||
//Illegal Instruction check
|
||||
logic illegal_instruction_pattern_r;
|
||||
generate if (CONFIG.INCLUDE_M_MODE) begin
|
||||
illegal_instruction_checker # (.CONFIG(CONFIG))
|
||||
illegal_op_check (
|
||||
.instruction(decode.instruction), .illegal_instruction(illegal_instruction_pattern)
|
||||
);
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
illegal_instruction_pattern_r <= 0;
|
||||
else if (issue_stage_ready)
|
||||
illegal_instruction_pattern_r <= illegal_instruction_pattern;
|
||||
illegal_instruction_checker # (.CONFIG(CONFIG))
|
||||
illegal_op_check (
|
||||
.instruction(decode.instruction), .illegal_instruction(illegal_instruction_pattern)
|
||||
);
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
illegal_instruction_pattern_r <= 0;
|
||||
else if (issue_stage_ready)
|
||||
illegal_instruction_pattern_r <= illegal_instruction_pattern;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ECALL/EBREAK
|
||||
//The type of call instruction is depedent on the current privilege level
|
||||
exception_code_t ecall_code;
|
||||
always_comb begin
|
||||
case (current_privilege)
|
||||
USER_PRIVILEGE : ecall_code = ECALL_U;
|
||||
SUPERVISOR_PRIVILEGE : ecall_code = ECALL_S;
|
||||
MACHINE_PRIVILEGE : ecall_code = ECALL_M;
|
||||
default : ecall_code = ECALL_U;
|
||||
endcase
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Exception generation (ecall/ebreak/illegal instruction/propagated fetch error)
|
||||
logic new_exception;
|
||||
exception_code_t ecode;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
pre_issue_exception_pending <= 0;
|
||||
else if (issue_stage_ready)
|
||||
pre_issue_exception_pending <= illegal_instruction_pattern | (opcode_trim inside {SYSTEM_T} & ~is_csr & (sys_op_match[ECALL_i] | sys_op_match[EBREAK_i])) | ~decode.fetch_metadata.ok;
|
||||
end
|
||||
|
||||
assign new_exception = issue.stage_valid & pre_issue_exception_pending & ~(gc.issue_hold | gc.fetch_flush);
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
exception.valid <= 0;
|
||||
else
|
||||
exception.valid <= (exception.valid | new_exception) & ~exception.ack;
|
||||
end
|
||||
|
||||
assign ecode =
|
||||
illegal_instruction_pattern_r ? ILLEGAL_INST :
|
||||
is_ecall_r ? ecall_code :
|
||||
~issue.fetch_metadata.ok ? issue.fetch_metadata.error_code :
|
||||
BREAK;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (new_exception) begin
|
||||
exception.code <= ecode;
|
||||
exception.tval <= issue.instruction;
|
||||
exception.id <= issue.id;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//Illegal instruction if the instruction is invalid, but could otherwise be issued
|
||||
assign illegal_instruction = illegal_instruction_pattern_r & issue.stage_valid & ~gc.issue_hold & ~gc.fetch_flush;
|
||||
end endgenerate
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
|
@ -601,11 +644,6 @@ module decode_and_issue
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
//TODO: convert into exception and expand support into all fetch stage exceptions
|
||||
//If an invalid fetch address has reached the issue stage and has not been flushed as a branch, processor state is corrupted
|
||||
invalid_fetch_address_assertion:
|
||||
assert property (@(posedge clk) disable iff (rst) (issue.stage_valid & (~issue.fetch_metadata.ok & issue.fetch_metadata.error_code == FETCH_ACCESS_FAULT)) |-> (gc.fetch_flush))
|
||||
else $error("invalid fetch address");
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Trace Interface
|
||||
|
|
|
@ -260,7 +260,7 @@ module fetch
|
|||
|
||||
assign if_pc = pc;
|
||||
assign fetch_metadata.ok = valid_fetch_result;
|
||||
assign fetch_metadata.error_code = fetch_attr.mmu_fault ? FETCH_PAGE_FAULT : FETCH_ACCESS_FAULT;
|
||||
assign fetch_metadata.error_code = INST_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);//allow instruction to propagate to decode if address is invalid
|
||||
|
|
112
core/gc_unit.sv
112
core/gc_unit.sv
|
@ -35,14 +35,15 @@ module gc_unit
|
|||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
|
||||
//Decode
|
||||
unit_issue_interface.unit issue,
|
||||
input gc_inputs_t gc_inputs,
|
||||
input logic gc_flush_required,
|
||||
|
||||
//Branch miss predict
|
||||
input logic branch_flush,
|
||||
|
||||
//exception_interface.unit pre_issue_exception,
|
||||
|
||||
//Exception
|
||||
exception_interface.econtrol exception [NUM_EXCEPTION_SOURCES],
|
||||
input logic [31:0] exception_target_pc,
|
||||
|
@ -61,6 +62,8 @@ module gc_unit
|
|||
input logic interrupt_pending,
|
||||
output logic interrupt_taken,
|
||||
|
||||
input logic processing_csr,
|
||||
|
||||
//Output controls
|
||||
output gc_outputs_t gc,
|
||||
|
||||
|
@ -75,18 +78,19 @@ module gc_unit
|
|||
localparam int INIT_CLEAR_DEPTH = CONFIG.INCLUDE_S_MODE ? (TLB_CLEAR_DEPTH > 64 ? TLB_CLEAR_DEPTH : 64) : 64;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Instructions
|
||||
//All instructions are processed only if in IDLE state, meaning there can be no exceptions caused by instructions already further in the pipeline.
|
||||
//FENCE:
|
||||
// Drain Load/Store FIFO
|
||||
//Overview
|
||||
//All CSR instructions hold the issue stage until they are the oldest instruction and complete.
|
||||
// As such, their values are known at issue time for any call/ret instruction.
|
||||
|
||||
//FENCE.I:
|
||||
// flush and hold fetch until L/S unit empty
|
||||
// Local mem (nothing extra required for coherency)
|
||||
// Caches, currently not supported. Need snooping for Icache and draining of data FIFO to L2 and after FIFO drained, poping at least the current number of entries in the invalidation FIFO
|
||||
// Caches, currently not supported. Requires L2 monitoring. Need to know that all previous stores from this processor
|
||||
// have been sent out as potential invalidations and ack-ed before fetch can resume
|
||||
//SFENCE
|
||||
// flush and hold fetch, wait until L/S input FIFO empty, hold fetch until TLB update complete
|
||||
//ECALL, EBREAK, SRET, MRET:
|
||||
// flush fetch, update to CSRs is pipelined
|
||||
// flush fetch, hold until oldest instruction
|
||||
|
||||
//Interrupt
|
||||
//wait until issue/execute exceptions are no longer possible, flush fetch, take exception
|
||||
|
@ -106,27 +110,16 @@ module gc_unit
|
|||
//LS exceptions (miss-aligned, TLB and MMU) (issue stage)
|
||||
//fetch flush, take exception. If execute or later exception occurs first, exception is overridden
|
||||
|
||||
typedef enum {RST_STATE, PRE_CLEAR_STATE, INIT_CLEAR_STATE, IDLE_STATE, HOLD_STATE, TLB_CLEAR_STATE, IQ_DRAIN} gc_state;
|
||||
typedef enum {RST_STATE, PRE_CLEAR_STATE, INIT_CLEAR_STATE, IDLE_STATE, TLB_CLEAR_STATE, ISSUE_DRAIN, ISSUE_DISCARD} gc_state;
|
||||
gc_state state;
|
||||
gc_state next_state;
|
||||
|
||||
logic init_clear_done;
|
||||
logic tlb_clear_done;
|
||||
|
||||
logic i_fence_flush;
|
||||
exception_code_t ecall_code;
|
||||
logic second_cycle_flush;
|
||||
|
||||
logic system_op_or_exception_complete;
|
||||
logic exception_with_rd_complete;
|
||||
|
||||
logic [1:0] current_privilege;
|
||||
|
||||
gc_inputs_t stage1;
|
||||
|
||||
gc_inputs_t gc_inputs_r;
|
||||
logic post_issue_idle;
|
||||
//CSR
|
||||
logic processing_csr;
|
||||
|
||||
//GC registered global outputs
|
||||
logic gc_init_clear;
|
||||
|
@ -143,21 +136,19 @@ module gc_unit
|
|||
//Implementation
|
||||
//Input registering
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue.possible_issue & ~gc.issue_hold) begin
|
||||
stage1 <= gc_inputs;
|
||||
end
|
||||
if (issue.possible_issue & ~gc.issue_hold)
|
||||
gc_inputs_r <= gc_inputs;
|
||||
end
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//GC Operation
|
||||
assign post_issue_idle = (post_issue_count == 0) & sq_empty;
|
||||
assign gc.fetch_flush = branch_flush | gc_pc_override;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
gc_fetch_hold <= next_state inside {PRE_CLEAR_STATE, INIT_CLEAR_STATE};
|
||||
gc_issue_hold <= issue.new_request | processing_csr | (next_state inside {PRE_CLEAR_STATE, INIT_CLEAR_STATE, HOLD_STATE, TLB_CLEAR_STATE, IQ_DRAIN});
|
||||
gc_supress_writeback <= next_state inside {PRE_CLEAR_STATE, INIT_CLEAR_STATE, TLB_CLEAR_STATE};
|
||||
gc_fetch_hold <= next_state inside {PRE_CLEAR_STATE, INIT_CLEAR_STATE, ISSUE_DRAIN};
|
||||
gc_issue_hold <= processing_csr | (next_state inside {PRE_CLEAR_STATE, INIT_CLEAR_STATE, TLB_CLEAR_STATE, ISSUE_DRAIN});
|
||||
gc_supress_writeback <= next_state inside {PRE_CLEAR_STATE, INIT_CLEAR_STATE};
|
||||
gc_init_clear <= next_state inside {INIT_CLEAR_STATE};
|
||||
gc_tlb_flush <= next_state inside {INIT_CLEAR_STATE, TLB_CLEAR_STATE};
|
||||
end
|
||||
|
@ -183,16 +174,11 @@ module gc_unit
|
|||
PRE_CLEAR_STATE : next_state = INIT_CLEAR_STATE;
|
||||
INIT_CLEAR_STATE : if (init_clear_done) next_state = IDLE_STATE;
|
||||
IDLE_STATE : begin
|
||||
if (issue.new_request)
|
||||
next_state = HOLD_STATE;
|
||||
//IF exception and post-issue > 1 OR FLUSHING interrupts
|
||||
//if (ls_exception.valid | potential_branch_exception | system_op_or_exception_complete) begin
|
||||
// next_state = IQ_DRAIN;
|
||||
//end
|
||||
if (issue.new_request | interrupt_pending | gc.exception_pending)
|
||||
next_state = ISSUE_DRAIN;
|
||||
end
|
||||
HOLD_STATE : if (post_issue_idle) next_state = IDLE_STATE;
|
||||
TLB_CLEAR_STATE : if (tlb_clear_done) next_state = IDLE_STATE;
|
||||
IQ_DRAIN : if (post_issue_idle) next_state = IDLE_STATE;
|
||||
ISSUE_DRAIN : if (post_issue_idle) next_state = IDLE_STATE;
|
||||
default : next_state = RST_STATE;
|
||||
endcase
|
||||
end
|
||||
|
@ -209,65 +195,49 @@ module gc_unit
|
|||
assign init_clear_done = state_counter[$clog2(INIT_CLEAR_DEPTH)];
|
||||
assign tlb_clear_done = state_counter[$clog2(TLB_CLEAR_DEPTH)];
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//mret/sret
|
||||
always_ff @ (posedge clk) begin
|
||||
mret = issue.new_request & gc_inputs.is_ret & (gc_inputs.instruction[31:25] == 7'b0011000);
|
||||
sret = issue.new_request & gc_inputs.is_ret & (gc_inputs.instruction[31:25] == 7'b0001000);
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Exception handling
|
||||
|
||||
//The type of call instruction is depedent on the current privilege level
|
||||
always_comb begin
|
||||
case (current_privilege)
|
||||
USER_PRIVILEGE : ecall_code = ECALL_U;
|
||||
SUPERVISOR_PRIVILEGE : ecall_code = ECALL_S;
|
||||
MACHINE_PRIVILEGE : ecall_code = ECALL_M;
|
||||
default : ecall_code = ECALL_U;
|
||||
endcase
|
||||
end
|
||||
|
||||
//Re-assigning interface inputs to array types so that they can be dynamically indexed
|
||||
logic [NUM_EXCEPTION_SOURCES-1:0] ex_pending;
|
||||
exception_code_t [NUM_EXCEPTION_SOURCES-1:0] ex_code;
|
||||
id_t [NUM_EXCEPTION_SOURCES-1:0] ex_id;
|
||||
logic [NUM_EXCEPTION_SOURCES-1:0][31:0] ex_tval;
|
||||
logic ex_ack;
|
||||
logic [NUM_EXCEPTION_SOURCES-1:0] exception_pending;
|
||||
exception_code_t [NUM_EXCEPTION_SOURCES-1:0] exception_code;
|
||||
id_t [NUM_EXCEPTION_SOURCES-1:0] exception_id;
|
||||
logic [NUM_EXCEPTION_SOURCES-1:0][31:0] exception_tval;
|
||||
logic exception_ack;
|
||||
generate
|
||||
for (genvar i = 0; i < NUM_EXCEPTION_SOURCES; i++) begin
|
||||
assign ex_pending[i] = exception[i].valid;
|
||||
assign ex_code[i] = exception[i].code;
|
||||
assign ex_id[i] = exception[i].id;
|
||||
assign ex_tval[i] = exception[i].tval;
|
||||
assign exception[i].ack = ex_ack;
|
||||
assign exception_pending[i] = exception[i].valid;
|
||||
assign exception_code[i] = exception[i].code;
|
||||
assign exception_id[i] = exception[i].id;
|
||||
assign exception_tval[i] = exception[i].tval;
|
||||
assign exception[i].ack = exception_ack;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
//Exception valid when the oldest instruction is a valid ID. This is done with a level of indirection (through the exception unit table)
|
||||
//for better scalability, avoiding the need to compare against all exception sources.
|
||||
always_comb begin
|
||||
gc.exception_pending = |ex_pending;
|
||||
gc.exception.valid = (retire_ids[0] == ex_id[current_exception_unit]) & ex_pending[current_exception_unit];
|
||||
gc.exception_pending = |exception_pending;
|
||||
gc.exception.valid = (retire_ids[0] == exception_id[current_exception_unit]) & exception_pending[current_exception_unit];
|
||||
gc.exception.pc = oldest_pc;
|
||||
gc.exception.code = ex_code[current_exception_unit];
|
||||
gc.exception.tval = ex_tval[current_exception_unit];
|
||||
gc.exception.code = exception_code[current_exception_unit];
|
||||
gc.exception.tval = exception_tval[current_exception_unit];
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
ex_ack <= gc.exception.valid;
|
||||
exception_ack <= gc.exception.valid;
|
||||
end
|
||||
|
||||
//PC determination (trap, flush or return)
|
||||
//Two cycles: on first cycle the processor front end is flushed,
|
||||
//on the second cycle the new PC is fetched
|
||||
always_ff @ (posedge clk) begin
|
||||
second_cycle_flush <= gc_flush_required;
|
||||
gc_pc_override <= gc_flush_required | second_cycle_flush | gc.exception.valid | (next_state == INIT_CLEAR_STATE);
|
||||
gc_pc_override <= issue.new_request | gc.exception.valid | (next_state == INIT_CLEAR_STATE);
|
||||
gc_pc <=
|
||||
gc.exception.valid ? exception_target_pc :
|
||||
gc_inputs.is_ret ? epc :
|
||||
stage1.pc_p4; //ifence
|
||||
(gc_inputs.is_mret | gc_inputs.is_sret) ? epc :
|
||||
gc_inputs.pc_p4; //ifence
|
||||
end
|
||||
//work-around for verilator BLKANDNBLK signal optimizations
|
||||
assign gc.pc_override = gc_pc_override;
|
||||
|
|
|
@ -52,6 +52,7 @@ module instruction_metadata_and_id_management
|
|||
input logic decode_advance,
|
||||
input logic decode_uses_rd,
|
||||
input rs_addr_t decode_rd_addr,
|
||||
input exception_sources_t decode_exception_unit,
|
||||
//renamer
|
||||
input phys_addr_t decode_phys_rd_addr,
|
||||
|
||||
|
@ -149,8 +150,8 @@ module instruction_metadata_and_id_management
|
|||
////////////////////////////////////////////////////
|
||||
//Exception unit table
|
||||
always_ff @ (posedge clk) begin
|
||||
if (instruction_issued)
|
||||
exception_unit_table[issue.id] <= issue.exception_unit;
|
||||
if (decode_advance)
|
||||
exception_unit_table[decode_id] <= decode_exception_unit;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -148,6 +148,7 @@ module taiga
|
|||
decode_packet_t decode;
|
||||
logic decode_uses_rd;
|
||||
rs_addr_t decode_rd_addr;
|
||||
exception_sources_t decode_exception_unit;
|
||||
phys_addr_t decode_phys_rd_addr;
|
||||
phys_addr_t decode_phys_rs_addr [REGFILE_READ_PORTS];
|
||||
logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] decode_rs_wb_group [REGFILE_READ_PORTS];
|
||||
|
@ -181,11 +182,12 @@ module taiga
|
|||
logic interrupt_taken;
|
||||
logic interrupt_pending;
|
||||
|
||||
logic processing_csr;
|
||||
|
||||
//Decode Unit and Fetch Unit
|
||||
logic illegal_instruction;
|
||||
logic instruction_issued;
|
||||
logic instruction_issued_with_rd;
|
||||
logic gc_flush_required;
|
||||
|
||||
//LS
|
||||
wb_packet_t wb_snoop;
|
||||
|
@ -267,6 +269,7 @@ module taiga
|
|||
.decode_uses_rd (decode_uses_rd),
|
||||
.decode_rd_addr (decode_rd_addr),
|
||||
.decode_phys_rd_addr (decode_phys_rd_addr),
|
||||
.decode_exception_unit (decode_exception_unit),
|
||||
.issue (issue),
|
||||
.instruction_issued (instruction_issued),
|
||||
.instruction_issued_with_rd (instruction_issued_with_rd),
|
||||
|
@ -386,6 +389,7 @@ module taiga
|
|||
.renamer (decode_rename_interface),
|
||||
.decode_uses_rd (decode_uses_rd),
|
||||
.decode_rd_addr (decode_rd_addr),
|
||||
.decode_exception_unit (decode_exception_unit),
|
||||
.decode_phys_rd_addr (decode_phys_rd_addr),
|
||||
.decode_phys_rs_addr (decode_phys_rs_addr),
|
||||
.decode_rs_wb_group (decode_rs_wb_group),
|
||||
|
@ -402,8 +406,8 @@ module taiga
|
|||
.div_inputs (div_inputs),
|
||||
.unit_issue (unit_issue),
|
||||
.gc (gc),
|
||||
.gc_flush_required (gc_flush_required),
|
||||
.illegal_instruction (illegal_instruction),
|
||||
.current_privilege (current_privilege),
|
||||
.exception (exception[PRE_ISSUE_EXCEPTION]),
|
||||
.tr_operand_stall (tr_operand_stall),
|
||||
.tr_unit_stall (tr_unit_stall),
|
||||
.tr_no_id_stall (tr_no_id_stall),
|
||||
|
@ -534,6 +538,7 @@ module taiga
|
|||
.current_privilege(current_privilege),
|
||||
.interrupt_taken(interrupt_taken),
|
||||
.interrupt_pending(interrupt_pending),
|
||||
.processing_csr(processing_csr),
|
||||
.tlb_on(tlb_on),
|
||||
.asid(asid),
|
||||
.immu(immu),
|
||||
|
@ -555,7 +560,6 @@ module taiga
|
|||
.rst (rst),
|
||||
.issue (unit_issue[UNIT_IDS.IEC]),
|
||||
.gc_inputs (gc_inputs),
|
||||
.gc_flush_required (gc_flush_required),
|
||||
.branch_flush (branch_flush),
|
||||
.exception (exception),
|
||||
.exception_target_pc (exception_target_pc),
|
||||
|
@ -569,6 +573,7 @@ module taiga
|
|||
.retire_ids (retire_ids),
|
||||
.interrupt_taken(interrupt_taken),
|
||||
.interrupt_pending(interrupt_pending),
|
||||
.processing_csr(processing_csr),
|
||||
.sq_empty (sq_empty),
|
||||
.post_issue_count (post_issue_count)
|
||||
);
|
||||
|
|
|
@ -255,7 +255,7 @@ package taiga_config;
|
|||
typedef enum bit [1:0] {
|
||||
LS_EXCEPTION = 0,
|
||||
BR_EXCEPTION = 1,
|
||||
IEC_EXCEPTION = 2
|
||||
PRE_ISSUE_EXCEPTION = 2
|
||||
} exception_sources_t;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -56,14 +56,9 @@ package taiga_types;
|
|||
id_t id;
|
||||
} exception_packet_t;
|
||||
|
||||
typedef enum logic {
|
||||
FETCH_ACCESS_FAULT = 1'b0,
|
||||
FETCH_PAGE_FAULT = 1'b1
|
||||
} fetch_error_codes_t;
|
||||
|
||||
typedef struct packed{
|
||||
logic ok;
|
||||
fetch_error_codes_t error_code;
|
||||
exception_code_t error_code;
|
||||
} fetch_metadata_t;
|
||||
|
||||
typedef struct packed{
|
||||
|
@ -185,13 +180,11 @@ package taiga_types;
|
|||
|
||||
typedef struct packed{
|
||||
logic [31:0] pc_p4;
|
||||
logic [31:0] instruction;
|
||||
logic is_csr;
|
||||
logic is_fence;
|
||||
logic is_i_fence;
|
||||
logic is_ecall;
|
||||
logic is_ebreak;
|
||||
logic is_ret;
|
||||
logic is_ifence;
|
||||
logic is_mret;
|
||||
logic is_sret;
|
||||
logic is_exception;
|
||||
exception_code_t code;
|
||||
} gc_inputs_t;
|
||||
|
||||
typedef struct packed{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue