diff --git a/Makefile b/Makefile index 7ccb458cc..6108a48bf 100644 --- a/Makefile +++ b/Makefile @@ -128,8 +128,8 @@ build-tests: # User Verilator to lint the target lint: - verilator ${src} --lint-only \ - ${list_incdir} + verilator $(ariane_pkg) $(src) --lint-only \ + $(list_incdir) --top-module ariane clean: rm -rf work/ *.ucdb diff --git a/include/ariane_pkg.svh b/include/ariane_pkg.svh index f7b8383b4..42e7993cf 100644 --- a/include/ariane_pkg.svh +++ b/include/ariane_pkg.svh @@ -96,11 +96,12 @@ package ariane_pkg; // --------------- // store the decompressed instruction typedef struct packed { - branchpredict_sbe branch_predict; - logic [63:0] address; - logic [31:0] instruction; - logic is_compressed; - logic is_illegal; + branchpredict_sbe branch_predict; // this field contains branch prediction information regarding the forward branch path + exception ex; // this field contains exceptions which might have happened earlier, e.g.: fetch exceptions + logic [63:0] address; // the address of the instructions from below + logic [31:0] instruction; // instruction word + logic is_compressed; // bit indicating whether this instruction was previously compressed (e.g.: 16 bit) + logic is_illegal; // bit indicating whether the instruction was an illegal compressed instructions } fetch_entry; // --------------- diff --git a/src/ariane.sv b/src/ariane.sv index d466fefae..ee32450a4 100644 --- a/src/ariane.sv +++ b/src/ariane.sv @@ -18,9 +18,11 @@ // University of Bologna. // import ariane_pkg::*; +`ifndef verilator `ifndef SYNTHESIS import instruction_tracer_pkg::*; `endif +`endif module ariane #( @@ -184,6 +186,7 @@ module ariane logic fetch_gnt_ex_if; logic fetch_valid_ex_if; logic [31:0] fetch_rdata_ex_if; + exception fetch_ex_ex_if; logic fetch_err_ex_if; logic [63:0] fetch_vaddr_if_ex; // -------------- @@ -253,11 +256,11 @@ module ariane .instr_gnt_i ( fetch_gnt_ex_if ), .instr_rvalid_i ( fetch_valid_ex_if ), .instr_rdata_i ( fetch_rdata_ex_if ), + .instr_ex_i ( fetch_ex_ex_if ), // fetch exception .fetch_entry_o ( fetch_entry_if_id ), .fetch_entry_valid_i ( fetch_valid_if_id ), .instr_ack_i ( decode_ack_id_if ), - .ex_o ( exception_if_id ), .* ); @@ -276,7 +279,6 @@ module ariane .fetch_entry_i ( fetch_entry_if_id ), .fetch_entry_valid_i ( fetch_valid_if_id ), .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 ), .tvm_i ( tvm_csr_id ), @@ -377,6 +379,7 @@ module ariane .fetch_err_o ( fetch_err_ex_if ), .fetch_vaddr_i ( fetch_vaddr_if_ex ), .fetch_rdata_o ( fetch_rdata_ex_if ), + .fetch_ex_o ( fetch_ex_ex_if ), // fetch exception to IF .priv_lvl_i ( priv_lvl ), // from CSR .flag_pum_i ( flag_pum_csr_ex ), // from CSR .flag_mxr_i ( flag_mxr_csr_ex ), // from CSR @@ -463,6 +466,7 @@ module ariane // Instruction Tracer // ------------------- `ifndef SYNTHESIS + `ifndef verilator instruction_tracer_if tracer_if (clk_i); // assign instruction tracer interface // control signals @@ -494,6 +498,7 @@ module ariane instr_tracer instr_tracer_i (tracer_if); `endif + `endif always_ff @(posedge clk_i or negedge rst_ni) begin if(~rst_ni) begin diff --git a/src/ex_stage.sv b/src/ex_stage.sv index 459243d12..e5850c026 100644 --- a/src/ex_stage.sv +++ b/src/ex_stage.sv @@ -77,6 +77,7 @@ module ex_stage #( output logic fetch_err_o, input logic [63:0] fetch_vaddr_i, output logic [31:0] fetch_rdata_o, + output exception fetch_ex_o, input priv_lvl_t priv_lvl_i, input logic flag_pum_i, input logic flag_mxr_i, diff --git a/src/fetch_fifo.sv b/src/fetch_fifo.sv index 7a1365f7f..b1bbcf5ca 100644 --- a/src/fetch_fifo.sv +++ b/src/fetch_fifo.sv @@ -29,6 +29,7 @@ module fetch_fifo // that we have two compressed instruction (or one compressed instruction and one unaligned instruction) so we // only predict on one entry and discard (or keep) the other depending on its position and prediction. input branchpredict_sbe branch_predict_i, + input exception ex_i, // fetch exception in input logic [63:0] in_addr_i, input logic [31:0] in_rdata_i, input logic in_valid_i, @@ -43,6 +44,7 @@ module fetch_fifo // input registers - bounding the path from memory branchpredict_sbe branch_predict_n, branch_predict_q; + exception ex_n, ex_q; logic [63:0] in_addr_n, in_addr_q; logic [31:0] in_rdata_n, in_rdata_q; logic in_valid_n, in_valid_q; @@ -84,12 +86,14 @@ module fetch_fifo in_rdata_n = in_rdata_i; in_valid_n = in_valid_i; branch_predict_n = branch_predict_i; + ex_n = ex_i; // otherwise stall end else begin in_addr_n = in_addr_q; in_rdata_n = in_rdata_q; in_valid_n = in_valid_q; branch_predict_n = branch_predict_q; + ex_n = ex_q; end // flush the input registers if (flush_i) begin @@ -140,7 +144,7 @@ module fetch_fifo if (in_rdata_q[1:0] != 2'b11) begin // it is compressed mem_n[write_pointer_q] = { - branch_predict_q, in_addr_q, decompressed_instruction[0], 1'b1, is_illegal[0] + branch_predict_q, ex_q, in_addr_q, decompressed_instruction[0], 1'b1, is_illegal[0] }; status_cnt++; @@ -155,7 +159,7 @@ module fetch_fifo if (in_rdata_q[17:16] != 2'b11 && !(branch_predict_q.valid && branch_predict_q.predict_taken && branch_predict_q.is_lower_16)) begin mem_n[write_pointer_q + 1'b1] = { - branch_predict_q, {in_addr_q[63:2], 2'b10}, decompressed_instruction[1], 1'b1, is_illegal[1] + branch_predict_q, ex_q, {in_addr_q[63:2], 2'b10}, decompressed_instruction[1], 1'b1, is_illegal[1] }; status_cnt++; @@ -181,7 +185,7 @@ module fetch_fifo // | instruction [31:0] | // |______________________ mem_n[write_pointer_q] = { - branch_predict_q, in_addr_q, in_rdata_q, 1'b0, 1'b0 + branch_predict_q, ex_q, in_addr_q, in_rdata_q, 1'b0, 1'b0 }; status_cnt++; write_pointer++; @@ -192,7 +196,7 @@ module fetch_fifo if (in_valid_q && unaligned_q) begin mem_n[write_pointer_q] = { - branch_predict_q, unaligned_address_q, {in_rdata_q[15:0], unaligned_instr_q}, 1'b0, 1'b0 + branch_predict_q, ex_q, unaligned_address_q, {in_rdata_q[15:0], unaligned_instr_q}, 1'b0, 1'b0 }; status_cnt++; @@ -206,7 +210,7 @@ module fetch_fifo // but only if we predicted it to be taken, the predict was on the lower 16 bit compressed instruction if (in_rdata_q[17:16] != 2'b11 && !(branch_predict_q.valid && branch_predict_q.predict_taken && branch_predict_q.is_lower_16)) begin mem_n[write_pointer_q + 1'b1] = { - branch_predict_q, {in_addr_q[63:2], 2'b10}, decompressed_instruction[1], 1'b1, is_illegal[1] + branch_predict_q, ex_q, {in_addr_q[63:2], 2'b10}, decompressed_instruction[1], 1'b1, is_illegal[1] }; status_cnt++; @@ -240,7 +244,7 @@ module fetch_fifo if (in_rdata_q[17:16] != 2'b11) begin // it is compressed mem_n[write_pointer_q] = { - branch_predict_q, in_addr_q, decompressed_instruction[1], 1'b1, is_illegal[1] + branch_predict_q, ex_q, in_addr_q, decompressed_instruction[1], 1'b1, is_illegal[1] }; status_cnt++; @@ -296,6 +300,7 @@ module fetch_fifo in_rdata_q <= 32'b0; in_valid_q <= 1'b0; branch_predict_q <= '{default: 0}; + ex_q <= '{default: 0}; end else begin status_cnt_q <= status_cnt_n; mem_q <= mem_n; @@ -309,6 +314,7 @@ module fetch_fifo in_rdata_q <= in_rdata_n; in_valid_q <= in_valid_n; branch_predict_q <= branch_predict_n; + ex_q <= ex_n; end end diff --git a/src/id_stage.sv b/src/id_stage.sv index e98ef0e2e..b5bc55d46 100644 --- a/src/id_stage.sv +++ b/src/id_stage.sv @@ -33,7 +33,6 @@ module id_stage #( input fetch_entry fetch_entry_i, 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 input logic tvm_i, @@ -99,9 +98,6 @@ module id_stage #( logic issue_instr_valid_sb_iro; logic issue_ack_iro_sb; // --------------------------------------------------- - // Compressed Decoder <-> Decoder - // --------------------------------------------------- - // --------------------------------------------------- // Decoder (DC) <-> Scoreboard (SB) // --------------------------------------------------- scoreboard_entry decoded_instr_dc_sb; @@ -110,9 +106,9 @@ module id_stage #( // --------------------------------------------------- logic is_control_flow_instr; - // ----------------- - // Branch logic - // ----------------- + // --------------------------------------------------- + // Branch (resolve) logic + // --------------------------------------------------- // This should basically prevent the scoreboard from accepting // instructions past a branch. We need to resolve the branch beforehand. // This limitation is in place to ease the backtracking of mis-predicted branches as they @@ -145,7 +141,7 @@ module id_stage #( .instruction_i ( fetch_entry_i.instruction ), .branch_predict_i ( fetch_entry_i.branch_predict ), .is_illegal_i ( fetch_entry_i.is_illegal ), - .ex_i ( ex_if_i ), + .ex_i ( fetch_entry_i.ex ), .instruction_o ( decoded_instr_dc_sb ), .is_control_flow_instr_o ( is_control_flow_instr ), .* diff --git a/src/if_stage.sv b/src/if_stage.sv index 9e5dca8d9..ba5c824f2 100644 --- a/src/if_stage.sv +++ b/src/if_stage.sv @@ -36,11 +36,11 @@ module if_stage ( input logic instr_gnt_i, input logic instr_rvalid_i, input logic [31:0] instr_rdata_i, + input exception instr_ex_i, // Instruction fetch exception, valid if rvalid is one // Output of IF Pipeline stage output fetch_entry fetch_entry_o, // fetch entry containing all relevant data for the ID stage output logic fetch_entry_valid_i, // instruction in IF is valid - input logic instr_ack_i, // ID acknowledged this instruction - output exception ex_o // pass on if an fetch-exception happened + input logic instr_ack_i // ID acknowledged this instruction ); enum logic [1:0] {IDLE, WAIT_GNT, WAIT_RVALID, WAIT_ABORTED } CS, NS; @@ -66,6 +66,7 @@ module if_stage ( //--------------------------------- fetch_fifo fetch_fifo_i ( .branch_predict_i ( branchpredict_q ), + .ex_i ( instr_ex_i ), .in_addr_i ( instr_addr_q ), .in_rdata_i ( instr_rdata_i ), .in_valid_i ( fifo_valid ), @@ -224,16 +225,12 @@ module if_stage ( CS <= IDLE; instr_addr_q <= '0; branchpredict_q <= '{default: 0}; - ex_o <= '{default: 0}; end else begin CS <= NS; if (addr_valid) begin instr_addr_q <= fetch_address_i; branchpredict_q <= branch_predict_i; end - ex_o.cause <= 64'b0; // TODO: Output exception - ex_o.tval <= 64'b0; // TODO: Output exception - ex_o.valid <= 1'b0; //illegal_compressed_instr; // TODO: Output exception end end //------------- diff --git a/src/lsu.sv b/src/lsu.sv index f9f66de81..1effc3da1 100644 --- a/src/lsu.sv +++ b/src/lsu.sv @@ -46,6 +46,7 @@ module lsu #( output logic fetch_err_o, // Instruction fetch interface input logic [63:0] fetch_vaddr_i, // Instruction fetch interface output logic [31:0] fetch_rdata_o, // Instruction fetch interface + output logic fetch_ex_o, // Instruction fetch interface input priv_lvl_t priv_lvl_i, // From CSR register file input logic flag_pum_i, // From CSR register file diff --git a/src/mmu.sv b/src/mmu.sv index a906a54d1..8357b538e 100644 --- a/src/mmu.sv +++ b/src/mmu.sv @@ -36,7 +36,8 @@ module mmu #( output logic fetch_valid_o, output logic fetch_err_o, input logic [63:0] fetch_vaddr_i, - output logic [31:0] fetch_rdata_o, // pass-through because of interfaces + output logic [31:0] fetch_rdata_o, // pass-through because of interfaces + output exception fetch_ex_o, // write-back fetch exceptions (e.g.: bus faults, page faults, etc.) // LSU interface // this is a more minimalistic interface because the actual addressing logic is handled // in the LSU as we distinguish load and stores, what we do here is simple address translation diff --git a/src/regfile_ff.sv b/src/regfile_ff.sv index fb8e44418..b33ae937c 100644 --- a/src/regfile_ff.sv +++ b/src/regfile_ff.sv @@ -26,7 +26,7 @@ // // //////////////////////////////////////////////////////////////////////////////// -module regfile +module regfile_ff #( parameter DATA_WIDTH = 32 )