diff --git a/core/csr_unit.sv b/core/csr_unit.sv index 94b4a21..2827fa3 100755 --- a/core/csr_unit.sv +++ b/core/csr_unit.sv @@ -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 diff --git a/core/decode_and_issue.sv b/core/decode_and_issue.sv index 7c5aa42..afdf621 100755 --- a/core/decode_and_issue.sv +++ b/core/decode_and_issue.sv @@ -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 diff --git a/core/fetch.sv b/core/fetch.sv index 3153797..2fb37f1 100755 --- a/core/fetch.sv +++ b/core/fetch.sv @@ -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 diff --git a/core/gc_unit.sv b/core/gc_unit.sv index b759480..1f903c5 100644 --- a/core/gc_unit.sv +++ b/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; diff --git a/core/instruction_metadata_and_id_management.sv b/core/instruction_metadata_and_id_management.sv index 6bda09b..e713a09 100644 --- a/core/instruction_metadata_and_id_management.sv +++ b/core/instruction_metadata_and_id_management.sv @@ -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 //////////////////////////////////////////////////// diff --git a/core/taiga.sv b/core/taiga.sv index cabf7a4..d987e5d 100755 --- a/core/taiga.sv +++ b/core/taiga.sv @@ -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) ); diff --git a/core/taiga_config.sv b/core/taiga_config.sv index 742f262..e867232 100755 --- a/core/taiga_config.sv +++ b/core/taiga_config.sv @@ -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; //////////////////////////////////////////////////// diff --git a/core/taiga_types.sv b/core/taiga_types.sv index 568655d..1074357 100755 --- a/core/taiga_types.sv +++ b/core/taiga_types.sv @@ -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{