Complete exception wiring and issuing exceptions

Exceptions are passed through by the issue stage. They count as valid
instructions which are already ready for commit.
This commit is contained in:
Florian Zaruba 2017-05-04 14:37:59 +02:00
parent b757641a49
commit 749762650f
7 changed files with 117 additions and 99 deletions

View file

@ -36,7 +36,7 @@ package ariane_pkg;
} misspredict;
typedef enum logic[3:0] {
NONE, LSU, ALU, MULT, CSR
NONE, LSU, ALU, MULT
} fu_t;
localparam EXC_OFF_RST = 8'h80;
@ -139,13 +139,6 @@ package ariane_pkg;
localparam OPCODE_AUIPC = 7'h17;
localparam OPCODE_LUI = 7'h37;
// --------------------
// Immediate select
// --------------------
typedef enum logic[3:0] {
NOIMM, PCIMM, IIMM, SIMM, BIMM, UIMM, JIMM
} imm_sel_t;
// --------------------
// Privilege Spec
// --------------------

View file

@ -118,6 +118,8 @@ module ariane
logic [0:0] asid_i;
logic flush_tlb_i;
logic lsu_exception;
assign id_ready_i = 1'b1;
assign halt_if_i = 1'b0;
@ -158,7 +160,7 @@ module ariane
.instruction_valid_i ( instr_valid_id_o ),
.is_compressed_i ( is_compressed_id_o ),
.pc_if_i ( pc_if_o ), // PC from if
.ex_i ( exception_if ), // exception from if
.ex_if_i ( exception_if ), // exception from if
.ready_o ( ready_o ),
.operator_o ( operator_o ),
.operand_a_o ( operand_a_o ),
@ -173,6 +175,7 @@ module ariane
.mult_valid_o ( ),
.trans_id_i ( {alu_trans_id, lsu_trans_id} ),
.wdata_i ( {alu_result, lsu_result} ),
.ex_ex_i ( {'b0, lsu_exception } ),
.wb_valid_i ( {alu_valid_o, lsu_valid_o} ),
.waddr_a_i ( waddr_a_i ),
@ -184,29 +187,29 @@ module ariane
);
ex_stage ex_stage_i (
.clk_i ( clk_i ),
.rst_ni ( rst_n ),
.flush_i ( 1'b0 ),
.operator_i ( operator_o ),
.operand_a_i ( operand_a_o ),
.operand_b_i ( operand_b_o ),
.imm_i ( imm_o ),
.trans_id_i ( trans_id_o ),
.comparison_result_o ( comparison_result_o ),
.clk_i ( clk_i ),
.rst_ni ( rst_n ),
.flush_i ( 1'b0 ),
.operator_i ( operator_o ),
.operand_a_i ( operand_a_o ),
.operand_b_i ( operand_b_o ),
.imm_i ( imm_o ),
.trans_id_i ( trans_id_o ),
.comparison_result_o ( comparison_result_o ),
.alu_ready_o ( alu_ready_i ),
.alu_valid_i ( alu_valid_i ),
.alu_result_o ( alu_result ),
.alu_trans_id_o ( alu_trans_id ),
.alu_valid_o ( alu_valid_o ),
.lsu_ready_o ( lsu_ready_o ),
.lsu_valid_i ( lsu_valid_i ),
.lsu_result_o ( lsu_result ),
.lsu_trans_id_o ( lsu_trans_id ),
.lsu_valid_o ( lsu_valid_o ),
.lsu_commit_i ( ),
.alu_ready_o ( alu_ready_i ),
.alu_valid_i ( alu_valid_i ),
.alu_result_o ( alu_result ),
.alu_trans_id_o ( alu_trans_id ),
.alu_valid_o ( alu_valid_o ),
.lsu_ready_o ( lsu_ready_o ),
.lsu_valid_i ( lsu_valid_i ),
.lsu_result_o ( lsu_result ),
.lsu_trans_id_o ( lsu_trans_id ),
.lsu_valid_o ( lsu_valid_o ),
.lsu_commit_i ( ),
.lsu_exception_o ( lsu_exception ),
// memory management
.enable_translation_i ( 1'b0 ), // from CSR
.fetch_req_i ( fetch_req_i ),
@ -222,8 +225,8 @@ module ariane
.asid_i ( asid_i ), // from CSR
.flush_tlb_i ( flush_tlb_i ),
.mult_ready_o ( mult_ready_o ),
.mult_valid_i ( mult_valid_i ),
.mult_ready_o ( mult_ready_o ),
.mult_valid_i ( mult_valid_i ),
.*
);

View file

@ -22,7 +22,12 @@ module decoder (
);
instruction instr;
assign instr = instruction'(instruction_i);
imm_sel_t imm_select;
// --------------------
// Immediate select
// --------------------
enum logic[3:0] {
NOIMM, PCIMM, IIMM, SIMM, BIMM, UIMM, JIMM
} imm_select;
logic [63:0] imm_i_type;
logic [63:0] imm_iz_type;
@ -304,14 +309,17 @@ module decoder (
end
endcase
end
// --------------------------------
// Exception handling
// --------------------------------
always_comb begin : exception_handling
instruction_o.ex = ex_i;
// 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_o) begin
instruction_o.ex.valid = 1'b1;
// we decoded an illegal exception here
instruction_o.ex.cause = ILLEGAL_INSTR;
end
end

View file

@ -46,6 +46,7 @@ module ex_stage #(
output logic [63:0] lsu_result_o,
output logic [TRANS_ID_BITS-1:0] lsu_trans_id_o,
input logic lsu_commit_i,
output exception lsu_exception_o,
// memory management
input logic enable_translation_i,
input logic fetch_req_i,
@ -100,11 +101,8 @@ module ex_stage #(
// Multiplication
// Load-Store Unit
exception lsu_exception_o;
lsu i_lsu (
.lsu_trans_id_i ( trans_id_i ),
.lsu_exception_o ( lsu_exception_o ), // TODO: exception
.commit_i ( lsu_commit_i ),
.*
);

View file

@ -24,8 +24,9 @@ module id_stage #(
input logic instruction_valid_i,
input logic is_compressed_i,
input logic [63:0] pc_if_i,
input exception ex_i,
output logic ready_o, // id is ready
input exception ex_if_i, // we already got an exception in IF
output logic ready_o, // id is ready
output fu_op operator_o,
output logic [63:0] operand_a_o,
output logic [63:0] operand_b_o,
@ -43,6 +44,7 @@ module id_stage #(
// write back port
input logic [NR_WB_PORTS-1:0][TRANS_ID_BITS-1:0] trans_id_i,
input logic [NR_WB_PORTS-1:0][63:0] wdata_i,
input exception [NR_WB_PORTS-1:0] ex_ex_i, // exception from execute stage
input logic [NR_WB_PORTS-1:0] wb_valid_i,
// commit port
input logic[4:0] waddr_a_i,
@ -78,7 +80,7 @@ module id_stage #(
.pc_i ( pc_if_i ),
.is_compressed_i ( is_compressed_i ),
.instruction_i ( instruction_i ),
.ex_i ( ex_i ),
.ex_i ( ex_if_i ),
.instruction_o ( decoded_instr_i ),
.illegal_instr_o ( illegal_instr_o )
);
@ -89,59 +91,60 @@ module id_stage #(
)
scoreboard_i
(
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.full_o (full_o ),
.flush_i (flush_i ),
.rd_clobber_o (rd_clobber_o ),
.rs1_i (rs1_i ),
.rs1_o (rs1_o ),
.rs1_valid_o (rs1_valid_o ),
.rs2_i (rs2_i ),
.rs2_o (rs2_o ),
.rs2_valid_o (rs2_valid_o ),
.commit_instr_o (commit_instr_o ),
.commit_ack_i (commit_ack_i ),
.decoded_instr_i (decoded_instr_i ),
.decoded_instr_valid_i (instruction_valid_i ),
.issue_instr_o (issue_instr_o ),
.issue_instr_valid_o (issue_instr_valid_o ),
.issue_ack_i (issue_ack_i ),
.trans_id_i (trans_id_i ),
.wdata_i (wdata_i ),
.wb_valid_i (wb_valid_i )
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.full_o ( full_o ),
.flush_i ( flush_i ),
.rd_clobber_o ( rd_clobber_o ),
.rs1_i ( rs1_i ),
.rs1_o ( rs1_o ),
.rs1_valid_o ( rs1_valid_o ),
.rs2_i ( rs2_i ),
.rs2_o ( rs2_o ),
.rs2_valid_o ( rs2_valid_o ),
.commit_instr_o ( commit_instr_o ),
.commit_ack_i ( commit_ack_i ),
.decoded_instr_i ( decoded_instr_i ),
.decoded_instr_valid_i ( instruction_valid_i ),
.issue_instr_o ( issue_instr_o ),
.issue_instr_valid_o ( issue_instr_valid_o ),
.issue_ack_i ( issue_ack_i ),
.trans_id_i ( trans_id_i ),
.wdata_i ( wdata_i ),
.ex_i ( ex_ex_i ),
.wb_valid_i ( wb_valid_i )
);
issue_read_operands issue_read_operands_i (
.clk_i (clk_i ),
.rst_ni (rst_ni ),
.flush_i (flush_i ),
.test_en_i (test_en_i ),
.issue_instr_i (issue_instr_o ),
.issue_instr_valid_i (issue_instr_valid_o),
.issue_ack_o (issue_ack_i ),
.rs1_o (rs1_i ),
.rs1_i (rs1_o ),
.rs1_valid_i (rs1_valid_o ),
.rs2_o (rs2_i ),
.rs2_i (rs2_o ),
.rs2_valid_i (rs2_valid_o ),
.rd_clobber_i (rd_clobber_o ),
.operator_o (operator_o ),
.operand_a_o (operand_a_o ),
.operand_b_o (operand_b_o ),
.imm_o (imm_o ),
.trans_id_o (trans_id_o ),
.alu_ready_i (alu_ready_i ),
.alu_valid_o (alu_valid_o ),
.lsu_ready_i (lsu_ready_i ),
.lsu_valid_o (lsu_valid_o ),
.mult_ready_i (mult_ready_i ),
.mult_valid_o (mult_valid_o ),
.waddr_a_i (waddr_a_i ),
.wdata_a_i (wdata_a_i ),
.we_a_i (we_a_i )
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( flush_i ),
.test_en_i ( test_en_i ),
.issue_instr_i ( issue_instr_o ),
.issue_instr_valid_i ( issue_instr_valid_o),
.issue_ack_o ( issue_ack_i ),
.rs1_o ( rs1_i ),
.rs1_i ( rs1_o ),
.rs1_valid_i ( rs1_valid_o ),
.rs2_o ( rs2_i ),
.rs2_i ( rs2_o ),
.rs2_valid_i ( rs2_valid_o ),
.rd_clobber_i ( rd_clobber_o ),
.operator_o ( operator_o ),
.operand_a_o ( operand_a_o ),
.operand_b_o ( operand_b_o ),
.imm_o ( imm_o ),
.trans_id_o ( trans_id_o ),
.alu_ready_i ( alu_ready_i ),
.alu_valid_o ( alu_valid_o ),
.lsu_ready_i ( lsu_ready_i ),
.lsu_valid_o ( lsu_valid_o ),
.mult_ready_i ( mult_ready_i ),
.mult_valid_o ( mult_valid_o ),
.waddr_a_i ( waddr_a_i ),
.wdata_a_i ( wdata_a_i ),
.we_a_i ( we_a_i )
);
endmodule

View file

@ -44,8 +44,6 @@ module issue_read_operands (
// MULT
input logic mult_ready_i, // FU is ready
output logic mult_valid_o, // Output is valid
// Forward port
// commit port
input logic [4:0] waddr_a_i,
input logic [63:0] wdata_a_i,
@ -81,10 +79,24 @@ module issue_read_operands (
issue_ack_o = 1'b0;
// check that we didn't stall, that the instruction we got is valid
// and that the functional unit we need is not busy
if (~stall && issue_instr_valid_i && ~fu_busy) begin
// check that the corresponding functional unit is not busy
// no other instruction has the same destination register -> fetch the instruction
if (rd_clobber_i[issue_instr_i.rd] == NONE) begin
if (issue_instr_valid_i) begin
if (~stall && ~fu_busy) begin
// check that the corresponding functional unit is not busy
// no other instruction has the same destination register -> fetch the instruction
if (rd_clobber_i[issue_instr_i.rd] == NONE) begin
issue_ack_o = 1'b1;
end
end
// we can also issue the instruction under the following two circumstances:
// we can do this even if we are stalled or no functional unit is ready (as we don't need one)
// the decoder needs to make sure that the instruction is marked as valid when it does not
// need any functional unit or if an exception occurred previous to the execute stage.
// 1. we already got an exception
if (issue_instr_i.ex.valid) begin
issue_ack_o = 1'b1;
end
// 2. it is an instruction which does not need any functional unit
if (issue_instr_i.fu == NONE) begin
issue_ack_o = 1'b1;
end
end
@ -101,8 +113,6 @@ module issue_read_operands (
fu_busy = ~mult_ready_i;
LSU:
fu_busy = ~lsu_ready_i;
CSR:
fu_busy = 1'b0;
default:
fu_busy = 1'b0;
endcase

View file

@ -46,6 +46,7 @@ module scoreboard #(
// write-back port
input logic [NR_WB_PORTS-1:0][TRANS_ID_BITS-1:0] trans_id_i, // transaction ID at which to write the result back
input logic [NR_WB_PORTS-1:0][63:0] wdata_i, // write data in
input exception [NR_WB_PORTS-1:0] ex_i, // exception from a functional unit (e.g.: ld/st exception, divide by zero)
input logic [NR_WB_PORTS-1:0] wb_valid_i // data in is valid
);
localparam BITS_ENTRIES = $clog2(NR_ENTRIES);
@ -135,13 +136,14 @@ always_comb begin : read_operands
end
// provide a direct combinational path from WB a.k.a forwarding
// make sure that we are not forwarding a result that got an exception
for (int j = 0; j < NR_WB_PORTS; j++) begin
if (mem_q[trans_id_i[j]].rd == rs1_i && wb_valid_i[j]) begin
if (mem_q[trans_id_i[j]].rd == rs1_i && wb_valid_i[j] && ~ex_i[j].valid) begin
rs1_o = wdata_i[j];
rs1_valid_o = wb_valid_i[j];
break;
end
if (mem_q[trans_id_i[j]].rd == rs2_i && wb_valid_i[j]) begin
if (mem_q[trans_id_i[j]].rd == rs2_i && wb_valid_i[j] && ~ex_i[j].valid) begin
rs2_o = wdata_i[j];
rs2_valid_o = wb_valid_i[j];
break;
@ -177,6 +179,7 @@ always_comb begin : push_instruction_and_wb
if (mem_q[i].trans_id == trans_id_i[j]) begin
mem_n[i].valid = 1'b1;
mem_n[i].result = wdata_i[j];
mem_n[i].ex = ex_i[j];
end
end
end