diff --git a/include/ariane_pkg.svh b/include/ariane_pkg.svh index 2c953b388..436948bb3 100644 --- a/include/ariane_pkg.svh +++ b/include/ariane_pkg.svh @@ -91,7 +91,7 @@ package ariane_pkg; // set lower than operations SLTS, SLTU, // CSR functions - MRET, SRET, ECALL, WFI, SFENCE_VMA, CSR_WRITE, CSR_READ, CSR_SET, CSR_CLEAR, + MRET, SRET, ECALL, WFI, FENCE_I, SFENCE_VMA, CSR_WRITE, CSR_READ, CSR_SET, CSR_CLEAR, // LSU functions LD, SD, LW, LWU, SW, LH, LHU, SH, LB, SB, LBU } fu_op; diff --git a/src/ariane.sv b/src/ariane.sv index 1d6174aa5..8d383b562 100644 --- a/src/ariane.sv +++ b/src/ariane.sv @@ -35,6 +35,7 @@ module ariane input logic clock_en_i, // enable clock, otherwise it is gated input logic test_en_i, // enable all clock gates for testing + output logic flush_icache_o, // request to flush icache // CPU Control Signals input logic fetch_enable_i, output logic core_busy_o, @@ -227,6 +228,7 @@ module ariane logic flush_ctrl_id; logic flush_ctrl_ex; logic flush_tlb_ctrl_ex; + logic fence_i_commit_controller; logic sfence_vma_commit_controller; logic halt_ctrl_commit; logic halt_debug_ctrl; @@ -450,6 +452,7 @@ module ariane .csr_wdata_o ( csr_wdata_commit_csr ), .csr_rdata_i ( csr_rdata_csr_commit ), .csr_exception_i ( csr_exception_csr_commit ), + .fence_i_o ( fence_i_commit_controller ), .sfence_vma_o ( sfence_vma_commit_controller ), .* ); @@ -509,7 +512,9 @@ module ariane .ex_i ( ex_commit ), .flush_csr_i ( flush_csr_ctrl ), .resolved_branch_i ( resolved_branch ), + .fence_i_i ( fence_i_commit_controller ), .sfence_vma_i ( sfence_vma_commit_controller ), + .* ); diff --git a/src/commit_stage.sv b/src/commit_stage.sv index 10b1b6a3b..762cde92d 100644 --- a/src/commit_stage.sv +++ b/src/commit_stage.sv @@ -46,6 +46,7 @@ module commit_stage ( output logic commit_lsu_o, // commit the pending store input logic no_st_pending_i, // there is no store pending output logic commit_csr_o, // commit the pending CSR instruction + output logic fence_i_o, // flush icache and pipeline output logic sfence_vma_o // flush TLBs and pipeline ); @@ -65,6 +66,7 @@ module commit_stage ( wdata_a_o = commit_instr_i.result; csr_op_o = ADD; // this corresponds to a CSR NOP csr_wdata_o = 64'b0; + fence_i_o = 1'b0; sfence_vma_o = 1'b0; // we will not commit the instruction if we took an exception @@ -112,6 +114,14 @@ module commit_stage ( commit_ack_o = 1'b0; end end + // ------------------ + // FENCE.I Logic + // ------------------ + if (commit_instr_i.op == FENCE_I) begin + commit_ack_o = 1'b1; + // tell the controller to flush the I$ + fence_i_o = 1'b1; + end end end diff --git a/src/controller.sv b/src/controller.sv index bd676a743..1238de795 100644 --- a/src/controller.sv +++ b/src/controller.sv @@ -29,6 +29,7 @@ module controller ( output logic flush_unissued_instr_o, // Flush un-issued instructions of the scoreboard output logic flush_id_o, // Flush ID stage output logic flush_ex_o, // Flush EX stage + output logic flush_icache_o, // Flush ICache output logic flush_tlb_o, // Flush TLBs input logic halt_csr_i, // Halt request from CSR (WFI instruction) @@ -38,6 +39,7 @@ module controller ( input exception ex_i, // We got an exception, flush the pipeline input branchpredict resolved_branch_i, // We got a resolved branch, check if we need to flush the front-end input logic flush_csr_i, // We got an instruction which altered the CSR, flush the pipeline + input logic fence_i_i, // fence.i in input logic sfence_vma_i // We got an instruction to flush the TLBs and pipeline ); // flush branch prediction @@ -65,6 +67,21 @@ module controller ( flush_if_o = 1'b1; end + // ---------------------- + // FENCE + // ---------------------- + + // ---------------------- + // FENCE.I + // ---------------------- + if (fence_i_i) begin + flush_pcgen_o = 1'b1; + flush_if_o = 1'b1; + flush_unissued_instr_o = 1'b1; + flush_id_o = 1'b1; + flush_ex_o = 1'b1; + flush_icache_o = 1'b1; + end // ---------------------- // SFENCE.VMA // ---------------------- diff --git a/src/decoder.sv b/src/decoder.sv index 23f328fec..0d56e62c7 100644 --- a/src/decoder.sv +++ b/src/decoder.sv @@ -200,14 +200,24 @@ module decoder ( end OPCODE_FENCE: begin + // FENCE.I + if (instr.itype.funct3 == 3'b001) begin + instruction_o.fu = CSR; + instruction_o.op = FENCE_I; + instruction_o.rs1 = '0; + instruction_o.rs2 = '0; + instruction_o.rd = '0; + + // FENCE // TODO: Implement - // FENCE, FENCE.I - // Implement as NOP - instruction_o.fu = ALU; - instruction_o.op = ADD; - instruction_o.rs1 = '0; - instruction_o.rs2 = '0; - instruction_o.rd = '0; + end else begin + // Currently implemented as NOP + instruction_o.fu = ALU; + instruction_o.op = ADD; + instruction_o.rs1 = '0; + instruction_o.rs2 = '0; + instruction_o.rd = '0; + end end // -------------------------- diff --git a/tb/core_tb.sv b/tb/core_tb.sv index 348261ed5..47706e01a 100644 --- a/tb/core_tb.sv +++ b/tb/core_tb.sv @@ -146,6 +146,7 @@ module core_tb; .test_en_i ( core_if.test_en ), .fetch_enable_i ( core_if.fetch_enable ), .core_busy_o ( core_if.core_busy ), + .flush_icache_o ( ), .ext_perf_counters_i ( ), .boot_addr_i ( core_if.boot_addr ), .core_id_i ( core_if.core_id ),