diff --git a/include/ariane_pkg.svh b/include/ariane_pkg.svh index e2977b1dd..e9fd3e9bc 100644 --- a/include/ariane_pkg.svh +++ b/include/ariane_pkg.svh @@ -223,9 +223,9 @@ package ariane_pkg; localparam LD_ACCESS_FAULT = 64'h5; localparam ST_ADDR_MISALIGNED = 64'h6; localparam ST_ACCESS_FAULT = 64'h7; - localparam ENV_CALL_UMODE = 64'h8; - localparam ENV_CALL_SMODE = 64'h9; - localparam ENV_CALL_MMODE = 64'hB; + localparam ENV_CALL_UMODE = 64'h8; // environment call from user mode + localparam ENV_CALL_SMODE = 64'h9; // environment call from supvervisor mode + localparam ENV_CALL_MMODE = 64'hB; // environment call from machine mode typedef enum logic [11:0] { CSR_SSTATUS = 12'h100, diff --git a/src/ariane.sv b/src/ariane.sv index 361983db9..1b0a7a25b 100644 --- a/src/ariane.sv +++ b/src/ariane.sv @@ -205,6 +205,9 @@ module ariane logic flush_unissued_instr_ctrl_id; logic flush_scoreboard_ctrl_id; logic flush_ctrl_if; + logic flush_ctrl_id; + logic flush_controller_ex; + // TODO: Preliminary signal assignments logic flush_tlb; @@ -271,6 +274,7 @@ module ariane .decoded_instr_ack_o ( decode_ack_id_if ), .ex_if_i ( exception_if_id ), // exception from if .ready_o ( ready_id_if ), + .priv_lvl_i ( priv_lvl ), // Functional Units .operator_o ( operator_id_ex ), .operand_a_o ( operand_a_id_ex ), @@ -424,19 +428,15 @@ module ariane // ------------ // Controller // ------------ - logic flush_commit_i; - logic flush_controller_ex; - controller controller_i ( .flush_bp_o ( ), .flush_scoreboard_o ( flush_scoreboard_ctrl_id ), .flush_unissued_instr_o ( flush_unissued_instr_ctrl_id ), .flush_if_o ( flush_ctrl_if ), - .flush_id_o ( ), + .flush_id_o ( flush_ctrl_id ), .flush_ex_o ( flush_controller_ex ), - .flush_ready_lsu_i ( ), - .flush_commit_i ( flush_commit_i ), + .ex_i ( ex_commit ), .flush_csr_i ( flush_csr_ctrl ), .resolved_branch_i ( resolved_branch ), .* @@ -449,23 +449,23 @@ module ariane instruction_tracer_if tracer_if (clk_i); // assign instruction tracer interface // control signals - assign tracer_if.rstn = rst_ni; + assign tracer_if.rstn = rst_ni; assign tracer_if.flush_unissued = flush_unissued_instr_ctrl_id; assign tracer_if.flush = flush_controller_ex; // fetch - assign tracer_if.fetch = fetch_entry_if_id; - assign tracer_if.fetch_valid = fetch_valid_if_id; - assign tracer_if.fetch_ack = decode_ack_id_if; + assign tracer_if.fetch = fetch_entry_if_id; + assign tracer_if.fetch_valid = fetch_valid_if_id; + assign tracer_if.fetch_ack = decode_ack_id_if; // Issue - assign tracer_if.issue_ack = id_stage_i.scoreboard_i.issue_ack_i; - assign tracer_if.issue_sbe = id_stage_i.scoreboard_i.issue_instr_o; + assign tracer_if.issue_ack = id_stage_i.scoreboard_i.issue_ack_i; + assign tracer_if.issue_sbe = id_stage_i.scoreboard_i.issue_instr_o; // write-back - assign tracer_if.waddr = waddr_a_commit_id; - assign tracer_if.wdata = wdata_a_commit_id; - assign tracer_if.we = we_a_commit_id; + assign tracer_if.waddr = waddr_a_commit_id; + assign tracer_if.wdata = wdata_a_commit_id; + assign tracer_if.we = we_a_commit_id; // commit - assign tracer_if.commit_instr = commit_instr_id_commit; - assign tracer_if.commit_ack = commit_ack_commit_id; + assign tracer_if.commit_instr = commit_instr_id_commit; + assign tracer_if.commit_ack = commit_ack_commit_id; program instr_tracer (instruction_tracer_if tracer_if); instruction_tracer it = new (tracer_if); diff --git a/src/commit_stage.sv b/src/commit_stage.sv index 420cca5ed..506005535 100644 --- a/src/commit_stage.sv +++ b/src/commit_stage.sv @@ -19,8 +19,8 @@ import ariane_pkg::*; module commit_stage ( - input logic clk_i, // Clock - input logic rst_ni, // Asynchronous reset active low + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low output exception exception_o, // take exception to controller @@ -39,9 +39,9 @@ module commit_stage ( output logic [63:0] csr_wdata_o, input logic [63:0] csr_rdata_i, input exception csr_exception_i, - // to ex - output logic commit_lsu_o, - output logic commit_csr_o, + // commit signals to ex + output logic commit_lsu_o, // commit the pending store + output logic commit_csr_o, // commit the pending CSR instruction // general control signal input logic [4:0] irq_enable_i ); diff --git a/src/controller.sv b/src/controller.sv index ba9b161c9..e7930dfdb 100644 --- a/src/controller.sv +++ b/src/controller.sv @@ -23,30 +23,61 @@ module controller ( input logic clk_i, // Clock input logic rst_ni, // Asynchronous reset active low - output logic flush_bp_o, // flush branch prediction data structures - output logic flush_unissued_instr_o, - output logic flush_scoreboard_o, - output logic flush_if_o, - output logic flush_id_o, - output logic flush_ex_o, + output logic flush_bp_o, // flush branch prediction data structures + output logic flush_if_o, // flush the IF stage + output logic flush_unissued_instr_o, // flush un-issued instructions of the scoreboard + output logic flush_scoreboard_o, // flush the whole scoreboard + output logic flush_id_o, // flush ID stage + output logic flush_ex_o, // flush EX stage - input logic flush_ready_lsu_i, // we need to wait for this signal from LSU - input logic flush_commit_i, // flush request from commit stage in - input logic flush_csr_i, - input branchpredict resolved_branch_i + 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 ); + // flush branch prediction assign flush_bp_o = 1'b0; + // ------------ + // Flush CTRL + // ------------ always_comb begin : flush_ctrl + flush_if_o = 1'b0; flush_unissued_instr_o = 1'b0; flush_scoreboard_o = 1'b0; - flush_if_o = 1'b0; + flush_id_o = 1'b0; + flush_ex_o = 1'b0; + + // ------------ + // Mis-predict + // ------------ // flush on mispredict if (resolved_branch_i.is_mispredict) begin + // flush only un-issued instructions flush_unissued_instr_o = 1'b1; + // and if stage flush_if_o = 1'b1; end + // ------------ + // Exception + // ------------ + if (ex_i.valid) begin + flush_if_o = 1'b1; + flush_scoreboard_o = 1'b1; + flush_id_o = 1'b1; + flush_ex_o = 1'b1; + end + + // --------------------------------- + // CSR instruction with side-effect + // --------------------------------- + if (flush_csr_i) begin + flush_if_o = 1'b1; + flush_scoreboard_o = 1'b1; + flush_id_o = 1'b1; + flush_ex_o = 1'b1; + end + end // flush on exception endmodule diff --git a/src/csr_regfile.sv b/src/csr_regfile.sv index 3073df8f3..3914d56d1 100644 --- a/src/csr_regfile.sv +++ b/src/csr_regfile.sv @@ -165,6 +165,7 @@ module csr_regfile #( // CSR Write and update logic // --------------------------- always_comb begin : csr_update + flush_o = 1'b0; update_access_exception = 1'b0; priv_lvl_n = priv_lvl_q; @@ -233,6 +234,8 @@ module csr_regfile #( CSR_MTVAL: mtval_n = csr_wdata; default: update_access_exception = 1'b1; endcase + // TODO: this is unnecessary + flush_o = 1'b1; end else begin update_access_exception = 1'b1; end diff --git a/src/decoder.sv b/src/decoder.sv index 920d52411..957845d1e 100644 --- a/src/decoder.sv +++ b/src/decoder.sv @@ -18,10 +18,15 @@ module decoder ( input logic [31:0] instruction_i, // instruction from IF input branchpredict_sbe branch_predict_i, input exception ex_i, // if an exception occured in if + input priv_lvl_t priv_lvl_i, // current privilege level output scoreboard_entry instruction_o, // scoreboard entry to scoreboard output logic is_control_flow_instr_o // this instruction will change the control flow ); logic illegal_instr; + // this instruction is an environment call (ecall), it is handled like an exception + logic ecall; + // this instruction is a software break-point + logic ebreak; instruction instr; assign instr = instruction'(instruction_i); // -------------------- @@ -60,6 +65,8 @@ module decoder ( instruction_o.is_compressed = is_compressed_i; instruction_o.use_zimm = 1'b0; instruction_o.bp = branch_predict_i; + ecall = 1'b0; + ebreak = 1'b0; if (~ex_i.valid) begin case (instr.rtype.opcode) @@ -70,10 +77,32 @@ module decoder ( unique case (instr.itype.funct3) 3'b000: begin - // TODO: - // ECALL, EBREAK, SFEBCE.VM - // MRET/SRET/URET, WFI - illegal_instr = 1'b1; + case (instr.itype.imm) + // ECALL + 12'b0: ecall = 1'b1; + // EBREAK: + 12'b1: ebreak = 1'b1; + + // URET + // 12'b10: ; + + // SRET + // 12'b100000010:; + + // MRET + // 12'b1100000010:; + + // WFI + // 12'b1_0000_0101:; + // SFENCE.VMA + default: begin + // if (instr.itype.imm[11:5] == 7'b1001) begin + // + // end else begin + illegal_instr = 1'b1; + // end + end + endcase end // atomically swaps values in the CSR and integer register 3'b001: begin// CSRRW @@ -408,15 +437,24 @@ module decoder ( instruction_o.valid = 1'b0; // look if we didn't already get an exception in any previous // stage - we should not overwrite it as we retain order regarding the exception - if (~ex_i.valid && illegal_instr) begin + if (~ex_i.valid) begin // instructions which will throw an exception are marked as valid // e.g.: they can be committed anytime and do not need to wait for any functional unit - instruction_o.valid = 1'b1; - instruction_o.ex.valid = 1'b1; - // we decoded an illegal exception here - instruction_o.ex.cause = ILLEGAL_INSTR; - // if we decoded an illegal instruction save the faulting instruction to tval - instruction_o.ex.tval = instruction_i; + if (illegal_instr) begin + instruction_o.valid = 1'b1; + instruction_o.ex.valid = 1'b1; + // we decoded an illegal exception here + instruction_o.ex.cause = ILLEGAL_INSTR; + // if we decoded an illegal instruction save the faulting instruction to tval + instruction_o.ex.tval = instruction_i; + // we got an ecall, set the correct cause depending on the current privilege level + end else if (ecall) begin + case (priv_lvl_i) begin + + endcase + end else if (ebreak) begin + + end end end endmodule \ No newline at end of file diff --git a/src/id_stage.sv b/src/id_stage.sv index f5ba700e0..7583fa2a0 100644 --- a/src/id_stage.sv +++ b/src/id_stage.sv @@ -35,6 +35,8 @@ module id_stage #( input logic fetch_entry_valid_i, output logic decoded_instr_ack_o, input exception ex_if_i, // we already got an exception in IF + // from CSR file + input priv_lvl_t priv_lvl_i, // current privilege level output logic ready_o, // id is ready output fu_op operator_o, diff --git a/tb/wave/wave_core.do b/tb/wave/wave_core.do index 7d7becc79..0b523b4eb 100644 --- a/tb/wave/wave_core.do +++ b/tb/wave/wave_core.do @@ -21,5 +21,3 @@ add wave -noupdate -group ex_stage /core_tb/dut/ex_stage_i/* add wave -noupdate -group commit_stage /core_tb/dut/commit_stage_i/* add wave -noupdate -group csr_file /core_tb/dut/csr_regfile_i/* add wave -noupdate -group controller /core_tb/dut/controller_i/* - -TreeUpdate [SetDefaultTree]