initial ID rework for processor front end

This commit is contained in:
Eric Matthews 2020-05-21 19:22:35 -07:00
parent a31320a79f
commit 06f3c14115
17 changed files with 588 additions and 221 deletions

View file

@ -29,6 +29,7 @@ module branch_comparator(
input logic less_than,
input logic [31:0] a,
input logic [31:0] b,
input logic xor_result,
output logic result
);
@ -45,6 +46,7 @@ module branch_comparator(
logic [15:0] sub_eq_a;
logic [15:0] sub_toss;
logic carry_out;
logic eq_carry_in;
logic ls_carry_in;
@ -87,6 +89,11 @@ module branch_comparator(
sub_eq_a[i] = (eq_a[2*i] | eq_b[2*i]) & (eq_a[2*i + 1] | eq_b[2*i + 1]); //bits are equal
end
//branch_inputs.fn3[0] is xor_result and selects the inverse result
//i.e. (not eq, greater than). Included here to reduce the number of inputs
//in the branch target adder
sub_ls_a[15] ^= xor_result;
sub_eq_a[15] ^= xor_result;
end

View file

@ -27,7 +27,10 @@ import taiga_types::*;
module branch_predictor (
input logic clk,
input logic rst,
branch_predictor_interface.branch_predictor bp,
output branch_metadata_t branch_metadata_if,
input branch_metadata_t branch_metadata_ex,
input branch_results_t br_results
);
@ -62,24 +65,25 @@ module branch_predictor (
branch_table_entry_t if_entry [BRANCH_PREDICTOR_WAYS-1:0];
branch_table_entry_t ex_entry;
logic branch_predictor_direction_changed;
logic [31:0] new_jump_addr;
logic [31:0] predicted_pc [BRANCH_PREDICTOR_WAYS-1:0];
logic [BRANCH_PREDICTOR_WAYS-1:0] tag_matches;
logic [BRANCH_PREDICTOR_WAYS-1:0] replacement_way;
logic [BRANCH_PREDICTOR_WAYS-1:0] update_way;
logic [BRANCH_PREDICTOR_WAYS-1:0] tag_update_way;
logic [BRANCH_PREDICTOR_WAYS-1:0] target_update_way;
logic [$clog2(BRANCH_PREDICTOR_WAYS > 1 ? BRANCH_PREDICTOR_WAYS : 2)-1:0] hit_way;
logic tag_match;
logic use_predicted_pc;
/////////////////////////////////////////
cycler #(BRANCH_PREDICTOR_WAYS) replacement_policy (.*, .en(1'b1), .one_hot(replacement_way));
genvar i;
generate if (USE_BRANCH_PREDICTOR)
for (i=0; i<BRANCH_PREDICTOR_WAYS; i++) begin : branch_tag_banks
branch_predictor_ram #(.C_DATA_WIDTH($bits(branch_table_entry_t)), .C_DEPTH(BRANCH_TABLE_ENTRIES))
tag_bank (.*,
.write_addr(br_results.pc_ex[2 +: BRANCH_ADDR_W]), .write_en(update_way[i]), .write_data(ex_entry),
.write_addr(br_results.pc_ex[2 +: BRANCH_ADDR_W]), .write_en(tag_update_way[i]), .write_data(ex_entry),
.read_addr(bp.next_pc[2 +: BRANCH_ADDR_W]), .read_en(bp.new_mem_request), .read_data(if_entry[i]));
end
endgenerate
@ -88,7 +92,7 @@ module branch_predictor (
for (i=0; i<BRANCH_PREDICTOR_WAYS; i++) begin : branch_table_banks
branch_predictor_ram #(.C_DATA_WIDTH(32), .C_DEPTH(BRANCH_TABLE_ENTRIES))
addr_table (.*,
.write_addr(br_results.pc_ex[2 +: BRANCH_ADDR_W]), .write_en(update_way[i]), .write_data(new_jump_addr),
.write_addr(br_results.pc_ex[2 +: BRANCH_ADDR_W]), .write_en(target_update_way[i]), .write_data(br_results.new_pc),
.read_addr(bp.next_pc[2 +: BRANCH_ADDR_W]), .read_en(bp.new_mem_request), .read_data(predicted_pc[i]));
end
endgenerate
@ -99,6 +103,8 @@ module branch_predictor (
end
endgenerate
////////////////////////////////////////////////////
//Instruction Fetch Response
generate if (BRANCH_PREDICTOR_WAYS > 1)
one_hot_to_integer #(BRANCH_PREDICTOR_WAYS) hit_way_conv (.*, .one_hot(tag_matches), .int_out(hit_way));
else
@ -106,38 +112,46 @@ module branch_predictor (
endgenerate
assign tag_match = |tag_matches;
assign bp.predicted_pc = predicted_pc[hit_way];
assign bp.metadata = if_entry[hit_way].metadata;
assign bp.use_ras = if_entry[hit_way].use_ras;
assign bp.update_way = tag_matches;
assign use_predicted_pc = USE_BRANCH_PREDICTOR & tag_match;
//Predict next branch to same location/direction as current
//Predicted PC and whether the prediction is valid
assign bp.predicted_pc = predicted_pc[hit_way];
assign bp.use_prediction = use_predicted_pc;
assign bp.use_ras = if_entry[hit_way].use_ras;
////////////////////////////////////////////////////
//Execution stage update
assign ex_entry.valid = 1;
assign ex_entry.tag = get_tag(br_results.pc_ex);
assign ex_entry.use_ras = br_results.is_return_ex;
assign new_jump_addr = ex_entry.metadata[1] ? br_results.jump_pc : br_results.njump_pc;
//2-bit saturating counter
always_comb begin
case(br_results.branch_ex_metadata)
case(branch_metadata_ex.branch_predictor_metadata)
2'b00 : ex_entry.metadata = br_results.branch_taken ? 2'b01 : 2'b00;
2'b01 : ex_entry.metadata = br_results.branch_taken ? 2'b10 : 2'b00;
2'b10 : ex_entry.metadata = br_results.branch_taken ? 2'b11 : 2'b01;
2'b11 : ex_entry.metadata = br_results.branch_taken ? 2'b11 : 2'b10;
endcase
if (~br_results.branch_prediction_used)
if (~branch_metadata_ex.branch_prediction_used)
ex_entry.metadata = br_results.branch_taken ? 2'b11 : 2'b00;
end
assign branch_predictor_direction_changed =
(~branch_metadata_ex.branch_prediction_used) |
(branch_metadata_ex.branch_predictor_metadata[1] ^ ex_entry.metadata[1]);
assign update_way = {BRANCH_PREDICTOR_WAYS{br_results.branch_ex}} & (br_results.branch_prediction_used ? br_results.bp_update_way : replacement_way);
assign tag_update_way = {BRANCH_PREDICTOR_WAYS{br_results.branch_ex}} & (branch_metadata_ex.branch_predictor_update_way);
assign target_update_way = {BRANCH_PREDICTOR_WAYS{branch_predictor_direction_changed}} & tag_update_way;
////////////////////////////////////////////////////
//Target PC if branch flush occured
assign bp.branch_flush_pc = br_results.new_pc;
assign bp.branch_flush_pc = br_results.branch_taken ? br_results.jump_pc : br_results.njump_pc;
////////////////////////////////////////////////////
//Instruction Fetch metadata
cycler #(BRANCH_PREDICTOR_WAYS) replacement_policy (.*, .en(1'b1), .one_hot(replacement_way));
generate if (USE_BRANCH_PREDICTOR) begin
assign bp.use_prediction = tag_match;
end else begin
assign bp.use_prediction = 0;
end endgenerate
assign branch_metadata_if.branch_predictor_metadata = if_entry[hit_way].metadata;
assign branch_metadata_if.branch_prediction_used = use_predicted_pc;
assign branch_metadata_if.branch_predictor_update_way = tag_match ? tag_matches : replacement_way;
endmodule

View file

@ -30,10 +30,14 @@ module branch_unit(
unit_issue_interface.unit issue,
input branch_inputs_t branch_inputs,
input logic [31:0] dec_pc_plus_4,//Sourced from ALU datapath on jal/jalr
output branch_results_t br_results,
ras_interface.branch_unit ras,
output logic branch_flush,
output logic branch_complete,
output id_t branch_id,
output logic potential_branch_exception,
output logic branch_exception_is_jump,
output exception_packet_t br_exception,
@ -47,13 +51,7 @@ module branch_unit(
logic branch_issued_r;
logic[19:0] jal_imm;
logic[11:0] jalr_imm;
logic[11:0] br_imm;
logic [31:0] pc_offset;
logic [31:0] jump_base;
logic [31:0] jump_pc_dec;
logic result;
logic result_ex;
@ -63,10 +61,15 @@ module branch_unit(
//Branch Predictor
logic branch_taken;
logic branch_taken_ex;
logic branch_correctly_taken;
logic branch_correclty_not_taken;
logic miss_predict;
id_t id_ex;
logic [31:0] new_pc;
logic [31:0] new_pc_ex;
logic [31:0] pc_ex;
logic [31:0] jump_pc;
logic [31:0] njump_pc;
@ -102,23 +105,11 @@ module branch_unit(
.less_than(branch_inputs.fn3[2]),
.a(branch_inputs.rs1),
.b(branch_inputs.rs2),
.xor_result(branch_inputs.fn3[0]),
.result(result)
);
assign branch_taken = (~jump_ex & (result_ex ^ fn3_ex[0])) | jump_ex;
assign jal_imm = {branch_inputs.instruction[31], branch_inputs.instruction[19:12], branch_inputs.instruction[20], branch_inputs.instruction[30:21]};
assign jalr_imm = branch_inputs.instruction[31:20];
assign br_imm = {branch_inputs.instruction[31], branch_inputs.instruction[7], branch_inputs.instruction[30:25], branch_inputs.instruction[11:8]};
always_comb begin
unique if (branch_inputs.jalr)
pc_offset = 32'(signed'(jalr_imm));
else if (branch_inputs.jal)
pc_offset = 32'(signed'({jal_imm, 1'b0}));
else
pc_offset = 32'(signed'({br_imm, 1'b0}));
end
assign branch_taken = result | branch_inputs.jalr | branch_inputs.jal;
always_comb begin
if (branch_inputs.jalr)
@ -127,13 +118,17 @@ module branch_unit(
jump_base = branch_inputs.dec_pc;
end
assign jump_pc_dec = jump_base + pc_offset;
assign new_pc = jump_base + (branch_taken ? 32'(signed'(branch_inputs.pc_offset)) : 4);
always_ff @(posedge clk) begin
if (instruction_is_completing | ~branch_issued_r) begin
branch_taken_ex <= branch_taken;
new_pc_ex <= new_pc;
fn3_ex <= branch_inputs.fn3;
result_ex <= result;
jump_ex <= (branch_inputs.jal | branch_inputs.jalr);
id_ex <= issue.id;
end
end
@ -147,50 +142,42 @@ module branch_unit(
jmp_instruction_id <= issue.instruction_id;
end
assign potential_branch_exception = jump_pc_dec[1] & issue.new_request;
assign potential_branch_exception = 0;// jump_pc_dec[1] & issue.new_request;
assign br_exception.valid = (jump_pc[1] & branch_taken) & branch_issued_r;
assign br_exception.valid = 0;//(jump_pc[1] & branch_taken) & branch_issued_r;
assign br_exception.code = INST_ADDR_MISSALIGNED;
assign br_exception.pc = pc_ex;
assign br_exception.tval = jump_pc;
assign br_exception.tval = new_pc_ex;
assign br_exception.id = jmp_instruction_id;
assign branch_exception_is_jump = (branch_inputs.jal | branch_inputs.jalr);
end
endgenerate
////////////////////////////////////////////////////
//ID Management
assign branch_complete = instruction_is_completing;
assign branch_id = id_ex;
////////////////////////////////////////////////////
//Predictor support
always_ff @(posedge clk) begin
if (issue.new_request)
njump_pc <= dec_pc_plus_4;
end
always_ff @(posedge clk) begin
if (instruction_is_completing | ~branch_issued_r) begin
pc_ex <= branch_inputs.dec_pc;
jump_pc <= {jump_pc_dec[31:1], 1'b0};
njump_pc <= branch_inputs.dec_pc + 4;
branch_metadata <= branch_inputs.branch_metadata;
branch_prediction_used <= branch_inputs.branch_prediction_used;
bp_update_way <= branch_inputs.bp_update_way;
end
end
assign br_results.pc_ex = pc_ex;
assign br_results.jump_pc = jump_pc;
assign br_results.njump_pc = njump_pc;
assign br_results.branch_ex_metadata = branch_metadata;
assign br_results.branch_taken = branch_taken;
assign br_results.new_pc = new_pc_ex;
assign br_results.branch_taken = branch_taken_ex;
assign br_results.branch_ex = instruction_is_completing;
assign br_results.is_return_ex = is_return;
assign br_results.branch_prediction_used = branch_prediction_used;
assign br_results.bp_update_way = bp_update_way;
assign branch_correctly_taken = {branch_taken, branch_inputs.dec_pc[31:1]} == {1'b1, jump_pc[31:1]};
assign branch_correclty_not_taken = {branch_taken, branch_inputs.dec_pc[31:1]} == {1'b0, njump_pc[31:1]};
assign miss_predict = ~(branch_correctly_taken | branch_correclty_not_taken);
assign branch_flush = USE_BRANCH_PREDICTOR ?
instruction_is_completing & miss_predict:
instruction_is_completing & branch_taken;
assign branch_flush = instruction_is_completing && (branch_inputs.dec_pc[31:1] != new_pc_ex[31:1]);
////////////////////////////////////////////////////
//RAS support
@ -217,10 +204,10 @@ module branch_unit(
////////////////////////////////////////////////////
//Trace Interface
generate if (ENABLE_TRACE_INTERFACE) begin
assign tr_branch_correct = instruction_is_completing & ~is_return & ~miss_predict;
assign tr_branch_misspredict = instruction_is_completing & ~is_return & miss_predict;
assign tr_return_correct = instruction_is_completing & is_return & ~miss_predict;
assign tr_return_misspredict = instruction_is_completing & is_return & miss_predict;
assign tr_branch_correct = instruction_is_completing & ~is_return & ~branch_flush;
assign tr_branch_misspredict = instruction_is_completing & ~is_return & branch_flush;
assign tr_return_correct = instruction_is_completing & is_return & ~branch_flush;
assign tr_return_misspredict = instruction_is_completing & is_return & branch_flush;
end
endgenerate

View file

@ -57,7 +57,7 @@ module csr_regs
mmu_interface.csr dmmu,
//WB
input logic instruction_complete,
input logic instruction_retired,
//External
@ -490,13 +490,13 @@ endgenerate
////////////////////////////////////////////////////
//Timers and Counters
//Register increment for instructions completed
logic instruction_retired;
assign instruction_retired = instruction_complete & ~gc_supress_writeback;
logic instruction_completed;
assign instruction_completed = instruction_retired & ~gc_supress_writeback;
always_ff @(posedge clk) begin
if (rst)
inst_ret_inc <= 0;
else
inst_ret_inc <= INST_RET_INC_W'(instruction_retired) + INST_RET_INC_W'(instruction_issued_no_rd);
inst_ret_inc <= INST_RET_INC_W'(instruction_completed) + INST_RET_INC_W'(instruction_issued_no_rd);
end
always_ff @(posedge clk) begin

View file

@ -28,9 +28,12 @@ module decode_and_issue (
input logic clk,
input logic rst,
output logic pre_decode_pop,
input logic fb_valid,
input fetch_buffer_packet_t fb,
//ID Management
output logic decode_advance,
input id_t decode_id,
input logic decode_id_valid,
input logic [31:0] decode_pc,
input logic [31:0] decode_instruction,
tracking_interface.decode ti,
register_file_issue_interface.issue rf_issue,
@ -51,6 +54,10 @@ module decode_and_issue (
output logic instruction_issued,
output id_t issue_id,
output logic issue_stage_valid,
output logic id_issued,
output logic dummy_id_complete,
output logic instruction_issued_no_rd,
output logic instruction_issued_with_rd,
output logic illegal_instruction,
@ -111,8 +118,7 @@ module decode_and_issue (
logic illegal_instruction_pattern;
logic dec_advance;
logic issue_stage_valid;
logic issue_stage_ready;
logic [2:0] fn3_issue_stage;
logic [6:0] opcode_issue_stage;
@ -126,42 +132,37 @@ module decode_and_issue (
genvar i;
////////////////////////////////////////////////////
//Implementation
assign dec_advance = (~issue_stage_valid) | instruction_issued;
assign issue_stage_ready = (~issue_stage_valid) | instruction_issued;
assign decode_advance = decode_id_valid & issue_stage_ready;
always_ff @(posedge clk) begin
if (rst | gc_fetch_flush)
issue_stage_valid <= 0;
else if (dec_advance)
issue_stage_valid <= fb_valid & ~gc_fetch_flush & ~illegal_instruction_pattern;
else if (issue_stage_ready)
issue_stage_valid <= decode_id_valid;
end
always_ff @(posedge clk) begin
if (dec_advance) begin
pc_issue_stage <= fb.pc;
instruction_issue_stage <= fb.instruction;
if (issue_stage_ready) begin
pc_issue_stage <= decode_pc;
instruction_issue_stage <= decode_instruction;
fn3_issue_stage <= fn3;
opcode_issue_stage <= opcode;
rs1_addr_issue_stage <= rs1_addr;
rs2_addr_issue_stage <= rs2_addr;
rd_addr_issue_stage <= rd_addr;
uses_rd_issue_stage <= uses_rd;
issue_id <= decode_id;
end
end
////////////////////////////////////////////////////
//Instruction Buffer
assign pre_decode_pop = fb_valid & dec_advance;
//Instruction aliases
assign opcode = fb.instruction[6:0];
assign opcode = decode_instruction[6:0];
assign opcode_trim = opcode[6:2];
assign fn3 = fb.instruction[14:12];
assign rs1_addr = fb.instruction[19:15];
assign rs2_addr = fb.instruction[24:20];
assign rd_addr = fb.instruction[11:7];
assign fn3 = decode_instruction[14:12];
assign rs1_addr = decode_instruction[19:15];
assign rs2_addr = decode_instruction[24:20];
assign rd_addr = decode_instruction[11:7];
assign csr_imm_op = (opcode_trim == SYSTEM_T) && fn3[2];
assign environment_op = (opcode_trim == SYSTEM_T) && (fn3 == 0);
@ -182,7 +183,7 @@ module decode_and_issue (
assign rf_issue.rd_addr = rd_addr_issue_stage;
always_ff @(posedge clk) begin
if (dec_advance) begin
if (issue_stage_ready) begin
rf_issue.uses_rs1 <= uses_rs1;
rf_issue.uses_rs2 <= uses_rs2;
end
@ -200,7 +201,7 @@ module decode_and_issue (
one_hot_to_integer #(NUM_WB_UNITS) unit_id_gen (.*, .one_hot(unit_needed_for_id_gen), .int_out(unit_needed_for_id_gen_int));
always_ff @(posedge clk) begin
if (dec_advance) begin
if (issue_stage_ready) begin
ti.inflight_packet.is_store <= is_store;
ti.issue_unit_id <= unit_needed_for_id_gen_int;
ti.exception_possible <= opcode_trim inside {LOAD_T, STORE_T, AMO_T};
@ -212,11 +213,11 @@ module decode_and_issue (
////////////////////////////////////////////////////
//Unit Determination
assign unit_needed[BRANCH_UNIT_ID] = opcode_trim inside {BRANCH_T, JAL_T, JALR_T};
assign unit_needed[ALU_UNIT_WB_ID] = ((opcode_trim == ARITH_T) && ~fb.instruction[25]) || (opcode_trim inside {ARITH_IMM_T, AUIPC_T, LUI_T, JAL_T, JALR_T});
assign unit_needed[ALU_UNIT_WB_ID] = ((opcode_trim == ARITH_T) && ~decode_instruction[25]) || (opcode_trim inside {ARITH_IMM_T, AUIPC_T, LUI_T, JAL_T, JALR_T});
assign unit_needed[LS_UNIT_WB_ID] = opcode_trim inside {LOAD_T, STORE_T, AMO_T};
assign unit_needed[GC_UNIT_ID] = opcode_trim inside {SYSTEM_T, FENCE_T};
assign mult_div_op = (opcode_trim == ARITH_T) && fb.instruction[25];
assign mult_div_op = (opcode_trim == ARITH_T) && decode_instruction[25];
generate if (USE_MUL)
assign unit_needed[MUL_UNIT_WB_ID] = mult_div_op && ~fn3[2];
endgenerate
@ -226,7 +227,7 @@ module decode_and_issue (
endgenerate
always_ff @(posedge clk) begin
if (dec_advance)
if (issue_stage_ready)
unit_needed_issue_stage <= unit_needed;
end
@ -255,7 +256,8 @@ module decode_and_issue (
assign instruction_issued_no_rd = instruction_issued & ~uses_rd_issue_stage;
assign instruction_issued_with_rd = instruction_issued & uses_rd_issue_stage;
assign id_issued = instruction_issued;
assign dummy_id_complete = instruction_issued & ~unit_needed_issue_stage[BRANCH_UNIT_ID];
////////////////////////////////////////////////////
//ALU unit inputs
logic [XLEN-1:0] alu_rs1_data;
@ -286,7 +288,7 @@ module decode_and_issue (
end
always_ff @(posedge clk) begin
if (dec_advance) begin
if (issue_stage_ready) begin
alu_rs1_sel_r <= alu_rs1_sel;
alu_rs2_sel_r <= alu_rs2_sel;
end
@ -310,7 +312,7 @@ module decode_and_issue (
//Add cases: JAL, JALR, LUI, AUIPC, ADD[I], all logic ops
//sub cases: SUB, SLT[U][I]
logic sub_instruction;
assign sub_instruction = (fn3 == ADD_SUB_fn3) && fb.instruction[30] && opcode[5];//If ARITH instruction
assign sub_instruction = (fn3 == ADD_SUB_fn3) && decode_instruction[30] && opcode[5];//If ARITH instruction
alu_logic_op_t alu_logic_op;
always_comb begin
@ -335,7 +337,7 @@ module decode_and_issue (
logic alu_slt_path;
always_ff @(posedge clk) begin
if (dec_advance) begin
if (issue_stage_ready) begin
alu_logic_op_r <= alu_logic_op;
alu_subtract <= ~opcode[2] & (fn3 inside {SLTU_fn3, SLT_fn3} || sub_instruction);//opcode[2] covers LUI,AUIPC,JAL,JALR
alu_lshift <= ~fn3[2];
@ -366,7 +368,7 @@ module decode_and_issue (
logic [4:0] amo_type;
assign amo_op = USE_AMO ? (opcode_trim == AMO_T) : 1'b0;
assign amo_type = fb.instruction[31:27];
assign amo_type = decode_instruction[31:27];
assign store_conditional = (amo_type == AMO_SC);
assign load_reserve = (amo_type == AMO_LR);
@ -388,8 +390,8 @@ module decode_and_issue (
logic is_load_r;
logic is_store_r;
always_ff @(posedge clk) begin
if (dec_advance) begin
ls_offset <= opcode[5] ? {fb.instruction[31:25], fb.instruction[11:7]} : fb.instruction[31:20];
if (issue_stage_ready) begin
ls_offset <= opcode[5] ? {decode_instruction[31:25], decode_instruction[11:7]} : decode_instruction[31:20];
is_load_r <= is_load;
is_store_r <= is_store;
end
@ -420,31 +422,43 @@ module decode_and_issue (
assign rs1_eq_rd = (rs1_addr == rd_addr);
logic br_use_signed;
branch_predictor_metadata_t branch_metadata;
logic branch_prediction_used;
logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way;
always_ff @(posedge clk) begin
if (dec_advance) begin
if (issue_stage_ready) begin
is_return <= (opcode_trim == JALR_T) && ((rs1_link & ~rd_link) | (rs1_link & rd_link & ~rs1_eq_rd));
is_call <= (opcode_trim inside {JAL_T, JALR_T}) && rd_link;
br_use_signed <= !(fn3 inside {BLTU_fn3, BGEU_fn3});
//Branch Predictor support
branch_metadata <= fb.branch_metadata;
branch_prediction_used <= fb.branch_prediction_used;
bp_update_way <= fb.bp_update_way;
end
end
assign branch_inputs.branch_metadata = branch_metadata;
assign branch_inputs.branch_prediction_used = branch_prediction_used;
assign branch_inputs.bp_update_way = bp_update_way;
logic[19:0] jal_imm;
logic[11:0] jalr_imm;
logic[11:0] br_imm;
logic [20:0] pc_offset;
logic [20:0] pc_offset_r;
assign jal_imm = {decode_instruction[31], decode_instruction[19:12], decode_instruction[20], decode_instruction[30:21]};
assign jalr_imm = decode_instruction[31:20];
assign br_imm = {decode_instruction[31], decode_instruction[7], decode_instruction[30:25], decode_instruction[11:8]};
always_comb begin
unique if (~opcode[3] & opcode[2])
pc_offset = 21'(signed'(jalr_imm));
else if (opcode[3])
pc_offset = 21'(signed'({jal_imm, 1'b0}));
else
pc_offset = 21'(signed'({br_imm, 1'b0}));
end
always_ff @(posedge clk) begin
if (issue_stage_ready)
pc_offset_r <= pc_offset;
end
assign branch_inputs.is_return = is_return;
assign branch_inputs.is_call = is_call;
assign branch_inputs.fn3 = fn3_issue_stage;
assign branch_inputs.instruction = instruction_issue_stage;
assign branch_inputs.pc_offset = pc_offset_r;
assign branch_inputs.use_signed = br_use_signed;
assign branch_inputs.jal = opcode_issue_stage[3];//(opcode == JAL);
assign branch_inputs.jalr = ~opcode_issue_stage[3] & opcode_issue_stage[2];//(opcode == JALR);
@ -463,7 +477,7 @@ module decode_and_issue (
logic is_csr;
logic is_csr_r;
logic potential_flush;
assign sfence = fb.instruction[25];
assign sfence = decode_instruction[25];
assign ifence = (opcode_trim == FENCE_T) && fn3[0];
assign is_csr = (opcode_trim == SYSTEM_T) && (fn3 != 0);
@ -474,11 +488,11 @@ module decode_and_issue (
logic is_ifence_r;
always_ff @(posedge clk) begin
if (dec_advance) begin
if (issue_stage_ready) begin
is_csr_r <= is_csr;
is_ecall <= ENABLE_M_MODE && environment_op && (fb.instruction[21:20] == 0);
is_ebreak <= ENABLE_M_MODE && environment_op && (fb.instruction[21:20] == 2'b01);
is_ret <= ENABLE_M_MODE && environment_op && (fb.instruction[21:20] == 2'b10);
is_ecall <= ENABLE_M_MODE && environment_op && (decode_instruction[21:20] == 0);
is_ebreak <= ENABLE_M_MODE && environment_op && (decode_instruction[21:20] == 2'b01);
is_ret <= ENABLE_M_MODE && environment_op && (decode_instruction[21:20] == 2'b10);
is_fence <= ENABLE_M_MODE && (opcode_trim == FENCE_T) && ~fn3[0];
is_ifence_r <= ifence;
potential_flush <= (environment_op | ifence);
@ -548,6 +562,7 @@ module decode_and_issue (
assign unit_issue[i].possible_issue = unit_needed_issue_stage[i] & unit_operands_ready[i] & issue_stage_valid & ti.id_available & ~gc_issue_hold;
assign unit_issue[i].new_request = issue[i];
assign unit_issue[i].instruction_id = ti.issue_id;
assign unit_issue[i].id = issue_id;
always_ff @(posedge clk) begin
unit_issue[i].new_request_r <= issue[i];
end
@ -558,12 +573,12 @@ module decode_and_issue (
logic illegal_instruction_pattern_r;
generate if (ENABLE_M_MODE) begin
illegal_instruction_checker illegal_op_check (
.instruction(fb.instruction), .illegal_instruction(illegal_instruction_pattern)
.instruction(decode_instruction), .illegal_instruction(illegal_instruction_pattern)
);
always_ff @(posedge clk) begin
if (rst)
illegal_instruction_pattern_r <= 0;
else if (dec_advance)
else if (issue_stage_ready)
illegal_instruction_pattern_r <= illegal_instruction_pattern;
end
@ -593,7 +608,7 @@ module decode_and_issue (
//Instruction Mix
always_ff @(posedge clk) begin
if (dec_advance) begin
if (issue_stage_ready) begin
tr_alu_op <= instruction_issued && (opcode_trim inside {ARITH_T, ARITH_IMM_T, AUIPC_T, LUI_T} && ~tr_mul_op && ~tr_div_op);
tr_branch_or_jump_op <= instruction_issued && (opcode_trim inside {JAL_T, JALR_T, BRANCH_T});
tr_load_op <= instruction_issued && (opcode_trim inside {LOAD_T, AMO_T});

View file

@ -34,23 +34,23 @@ module fetch(
input logic exception,
input logic [31:0] gc_fetch_pc,
//ID Support
input logic pc_id_available,
output logic pc_id_assigned,
output logic fetch_complete,
branch_predictor_interface.fetch bp,
ras_interface.fetch ras,
//Instruction Metadata
output logic [31:0] if_pc,
output logic [31:0] fetch_instruction,
tlb_interface.mem tlb,
local_memory_interface.master instruction_bram,
input logic icache_on,
l1_arbiter_request_interface.master l1_request,
l1_arbiter_return_interface.master l1_response,
input logic pre_decode_pop,
output logic [31:0] pre_decode_instruction,
output logic [31:0] pre_decode_pc,
output branch_predictor_metadata_t branch_metadata,
output logic branch_prediction_used,
output logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way,
output logic pre_decode_push
l1_arbiter_return_interface.master l1_response
);
localparam NUM_SUB_UNITS = USE_I_SCRATCH_MEM + USE_ICACHE;
@ -59,7 +59,6 @@ module fetch(
localparam BRAM_ID = 0;
localparam ICACHE_ID = USE_I_SCRATCH_MEM;
localparam FETCH_BUFFER_DEPTH_W = $clog2(FETCH_BUFFER_DEPTH);
localparam NEXT_ID_DEPTH = USE_ICACHE ? 2 : 1;
//Subunit signals
@ -76,9 +75,8 @@ module fetch(
logic [31:0] pc;
logic flush_or_rst;
logic [FETCH_BUFFER_DEPTH_W:0] inflight_count;
fifo_interface #(.DATA_WIDTH(NUM_SUB_UNITS_W)) next_unit();
logic space_in_inst_buffer;
logic new_mem_request;
//Cache related
@ -109,7 +107,6 @@ module fetch(
assign bp.new_mem_request = new_mem_request | gc_fetch_flush;
assign bp.next_pc = next_pc;
assign bp.if_pc = pc;
////////////////////////////////////////////////////
@ -127,15 +124,8 @@ module fetch(
//Issue Control Signals
assign flush_or_rst = (rst | gc_fetch_flush);
always_ff @(posedge clk) begin
if (flush_or_rst)
inflight_count <= '1;
else
inflight_count <= inflight_count - (FETCH_BUFFER_DEPTH_W+1)'(new_mem_request) + (FETCH_BUFFER_DEPTH_W+1)'(pre_decode_pop);
end
assign space_in_inst_buffer = inflight_count[FETCH_BUFFER_DEPTH_W];
assign new_mem_request = tlb.complete & space_in_inst_buffer & units_ready;
assign new_mem_request = tlb.complete & pc_id_available & units_ready;
assign pc_id_assigned = new_mem_request & ~gc_fetch_flush;
//////////////////////////////////////////////
//Subunit Tracking
@ -147,6 +137,9 @@ module fetch(
////////////////////////////////////////////////////
//Subunit Interfaces
//In the case of a gc_fetch_flush, a request may already be in progress
//for any sub unit. That request can either be completed or aborted.
//In either case, data_valid must NOT be asserted.
logic cache_address_match;
generate
for (i = 0; i < NUM_SUB_UNITS; i++) begin
@ -175,17 +168,9 @@ module fetch(
endgenerate
////////////////////////////////////////////////////
//Pre-Decode Output
assign pre_decode_instruction = unit_data_array[next_unit.data_out];
assign pre_decode_pc = stage2_phys_address;
assign pre_decode_push = units_data_valid;//FIFO is cleared on gc_fetch_flush
always_ff @(posedge clk) begin
if (new_mem_request) begin
branch_metadata <= bp.metadata;
branch_prediction_used <= bp.use_prediction;
bp_update_way <= bp.update_way;
end
end
//Instruction metada updates
assign if_pc = pc;
assign fetch_instruction = unit_data_array[next_unit.data_out];
assign fetch_complete = units_data_valid;
endmodule

View file

@ -56,8 +56,12 @@ module gc_unit(
mmu_interface.csr immu,
mmu_interface.csr dmmu,
//ID Management
output logic system_op_complete,
output id_t system_op_id,
//WB
input logic instruction_complete,
input logic instruction_retired,
input logic instruction_queue_empty,
input instruction_id_t oldest_id,
//unit_writeback_interface.unit gc_wb,
@ -184,6 +188,11 @@ module gc_unit(
end
end
////////////////////////////////////////////////////
//ID Management
assign system_op_complete = issue.new_request & (gc_inputs.is_fence | gc_inputs.is_i_fence);
assign system_op_id = issue.id;
//Instruction decode
assign opcode = stage1.instruction[6:0];
assign opcode_trim = opcode[6:2];

213
core/id_management.sv Normal file
View file

@ -0,0 +1,213 @@
/*
* Copyright © 2020 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
*/
module id_management
import taiga_config::*;
import taiga_types::*;
(
input logic clk,
input logic rst,
input logic gc_fetch_flush,
//ID issuing
output id_t pc_id,
output logic pc_id_available,
input logic pc_id_assigned,
//Fetch stage
output id_t fetch_id,
input logic fetch_complete,
//Decode stage
input logic decode_advance,
output id_t decode_id,
output logic decode_id_valid,
//Issue stage
input id_t issue_id,
input logic issue_stage_valid,
input logic dummy_id_complete,
input logic id_issued,
//ID freeing
input logic store_complete,
input id_t store_id,
input logic branch_complete,
input id_t branch_id,
input logic system_op_complete,
input id_t system_op_id,
input logic instruction_retired,
input id_t retired_id
);
//////////////////////////////////////////
id_t pc_id_i;
localparam LOG2_MAX_IDS = $clog2(MAX_IDS);
//FIFO to store IDs that have been fetched but not yet decoded
fifo_interface #(.DATA_WIDTH(LOG2_MAX_IDS)) fetch_fifo();
//Toggle memory blocks for tracking completion after issue
logic decoded_toggle_mem [MAX_IDS];
logic decoded_issued_toggle_mem [MAX_IDS];
logic issued_toggle_mem [MAX_IDS];
logic dummy_toggle_mem [MAX_IDS];
logic branch_complete_toggle_mem [MAX_IDS];
logic store_complete_toggle_mem [MAX_IDS];
logic system_op_complete_toggle_mem [MAX_IDS];
logic retired_toggle_mem [MAX_IDS];
////////////////////////////////////////////////////
//Implementation
//Next ID always increases, even on a fetch buffer flush
//If this leads to a temporary shortage of IDs, the oldest non-issued
//ID can be found and pc_id could be reset to that.
assign pc_id_i = pc_id + LOG2_MAX_IDS'(pc_id_assigned);
always_ff @ (posedge clk) begin
if (rst)
pc_id <= 0;
else
pc_id <= pc_id_i;
end
always_ff @ (posedge clk) begin
if (rst)
fetch_id <= 0;
else if (gc_fetch_flush)
fetch_id <= pc_id;
else
fetch_id <= fetch_id + LOG2_MAX_IDS'(fetch_complete);
end
////////////////////////////////////////////////////
//Fetch buffer
assign fetch_fifo.data_in = fetch_id;
assign fetch_fifo.push = fetch_complete;
assign fetch_fifo.pop = decode_advance;
assign fetch_fifo.supress_push = 0;
taiga_fifo #(.DATA_WIDTH(LOG2_MAX_IDS), .FIFO_DEPTH(MAX_IDS)) fetch_fifo_block (
.fifo(fetch_fifo),
.rst(rst | gc_fetch_flush),
.clk
);
assign decode_id = fetch_fifo.data_out;
assign decode_id_valid = fetch_fifo.valid;
////////////////////////////////////////////////////
//Issue Tracking
//As there are multiple completion sources, each source toggles a bit in its own LUTRAM.
//All LUTRAMs are then xor-ed together to produce the status of the ID.
//TODO: support arbitrary rst assertion (clear signal from global control)
//Instruction decoded and (issued or flushed) pair
initial decoded_toggle_mem = '{default: 0};
always_ff @ (posedge clk) begin
if (decode_advance & ~gc_fetch_flush)
decoded_toggle_mem[decode_id] <= ~decoded_toggle_mem[decode_id];
end
initial decoded_issued_toggle_mem = '{default: 0};
always_ff @ (posedge clk) begin
if (id_issued | (gc_fetch_flush & issue_stage_valid))
decoded_issued_toggle_mem[issue_id] <= ~decoded_issued_toggle_mem[issue_id];
end
//Post issue status tracking
initial issued_toggle_mem = '{default: 0};
always_ff @ (posedge clk) begin
if (id_issued)
issued_toggle_mem[issue_id] <= ~issued_toggle_mem[issue_id];
end
initial dummy_toggle_mem = '{default: 0};
always_ff @ (posedge clk) begin
if (dummy_id_complete)
dummy_toggle_mem[issue_id] <= ~dummy_toggle_mem[issue_id];
end
initial branch_complete_toggle_mem = '{default: 0};
always_ff @ (posedge clk) begin
if (branch_complete)
branch_complete_toggle_mem[branch_id] <= ~branch_complete_toggle_mem[branch_id];
end
initial store_complete_toggle_mem = '{default: 0};
always_ff @ (posedge clk) begin
if (store_complete)
store_complete_toggle_mem[store_id] <= ~store_complete_toggle_mem[store_id];
end
initial system_op_complete_toggle_mem = '{default: 0};
always_ff @ (posedge clk) begin
if (system_op_complete)
system_op_complete_toggle_mem[system_op_id] <= ~system_op_complete_toggle_mem[system_op_id];
end
initial retired_toggle_mem = '{default: 0};
always_ff @ (posedge clk) begin
if (instruction_retired)
retired_toggle_mem[retired_id] <= ~retired_toggle_mem[retired_id];
end
//Computed one cycle in advance using pc_id_i
logic id_not_in_decode_issue;
logic id_not_inflight;
assign id_not_in_decode_issue = ~(decoded_toggle_mem[pc_id_i] ^ decoded_issued_toggle_mem[pc_id_i]);
assign id_not_inflight =
~(issued_toggle_mem[pc_id_i] ^
branch_complete_toggle_mem[pc_id_i] ^
dummy_toggle_mem[pc_id_i]
);// ^
//store_complete_toggle_mem[pc_id_i] ^
//system_op_complete_toggle_mem[pc_id_i] ^
//retired_toggle_mem[pc_id_i]);
always_ff @ (posedge clk) begin
if (rst)
pc_id_available <= 1;
else
pc_id_available <= id_not_in_decode_issue & id_not_inflight;
end
////////////////////////////////////////////////////
//End of Implementation
////////////////////////////////////////////////////
////////////////////////////////////////////////////
//Assertions
pc_id_assigned_without_pc_id_available_assertion:
assert property (@(posedge clk) disable iff (rst) !(~pc_id_available & pc_id_assigned))
else $error("ID assigned without any ID available");
decode_advanced_without_id_assertion:
assert property (@(posedge clk) disable iff (rst) !(~decode_id_valid & decode_advance))
else $error("Decode advanced without ID");
endmodule

View file

@ -0,0 +1,106 @@
/*
* Copyright © 2020 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
*/
module instruction_metadata
import taiga_config::*;
import taiga_types::*;
(
input logic clk,
input logic rst,
//Fetch
input id_t pc_id,
input logic [31:0] if_pc,
input logic pc_id_assigned,
input id_t fetch_id,
input logic fetch_complete,
input logic [31:0] fetch_instruction,
//Decode ID
input id_t decode_id,
output logic [31:0] decode_pc,
output logic [31:0] decode_instruction,
//Branch Predictor
input branch_metadata_t branch_metadata_if,
input id_t branch_id,
output branch_metadata_t branch_metadata_ex
//Exception
//input id_t exception_id,
//output logic [31:0] exception_pc,
//output logic [31:0] exception_instruction
);
//////////////////////////////////////////
logic [31:0] pc_table [MAX_IDS];
logic [31:0] instruction_table [MAX_IDS];
logic [$bits(branch_metadata_t)-1:0] branch_metadata_table [MAX_IDS];
////////////////////////////////////////////////////
//Implementation
//pc table
always_ff @ (posedge clk) begin
if (pc_id_assigned)
pc_table[pc_id] <= if_pc;
end
//branch metadata table
always_ff @ (posedge clk) begin
if (pc_id_assigned)
branch_metadata_table[pc_id] <= branch_metadata_if;
end
//instruction table
always_ff @ (posedge clk) begin
if (fetch_complete)
instruction_table[fetch_id] <= fetch_instruction;
end
////////////////////////////////////////////////////
//Outputs
//Decode
assign decode_pc = pc_table[decode_id];
assign decode_instruction = instruction_table[decode_id];
//Branch Predictor
assign branch_metadata_ex = branch_metadata_table[branch_id];
//Exception Support
// generate if (ENABLE_M_MODE) begin
// assign exception_pc = pc_table[exception_id];
// assign exception_instruction = instruction_table[exception_id];
// end endgenerate
////////////////////////////////////////////////////
//End of Implementation
////////////////////////////////////////////////////
////////////////////////////////////////////////////
//Assertions
endmodule

View file

@ -28,6 +28,7 @@ import l2_config_and_types::*;
interface branch_predictor_interface;
//Fetch signals
logic [31:0] if_pc;
id_t if_id;
logic new_mem_request;
logic [31:0] next_pc;
@ -35,17 +36,15 @@ interface branch_predictor_interface;
logic [31:0] branch_flush_pc;
logic [31:0] predicted_pc;
logic use_prediction;
logic [BRANCH_PREDICTOR_WAYS-1:0] update_way;
logic use_ras;
branch_predictor_metadata_t metadata;
modport branch_predictor (
input if_pc, new_mem_request, next_pc,
output branch_flush_pc, predicted_pc, use_prediction, update_way, use_ras, metadata
input if_pc, if_id, new_mem_request, next_pc,
output branch_flush_pc, predicted_pc, use_prediction, use_ras
);
modport fetch (
input branch_flush_pc, predicted_pc, use_prediction, update_way, use_ras, metadata,
output if_pc, new_mem_request, next_pc
input branch_flush_pc, predicted_pc, use_prediction, use_ras,
output if_pc, if_id, new_mem_request, next_pc
);
endinterface
@ -55,11 +54,12 @@ interface unit_issue_interface;
logic new_request;
logic new_request_r;
instruction_id_t instruction_id;
id_t id;
logic ready;
modport decode (input ready, output possible_issue, new_request, new_request_r, instruction_id);
modport unit (output ready, input possible_issue, new_request, new_request_r, instruction_id);
modport decode (input ready, output possible_issue, new_request, new_request_r, instruction_id, id);
modport unit (output ready, input possible_issue, new_request, new_request_r, instruction_id, id);
endinterface
interface ras_interface;

View file

@ -48,6 +48,10 @@ module load_store_unit (
local_memory_interface.master data_bram,
//ID Management
output logic store_complete,
output id_t store_id,
//Writeback-Store Interface
writeback_store_interface.ls wb_store,
@ -208,6 +212,11 @@ endgenerate
assign lsq.accepted = lsq.transaction_ready & ready_for_issue;
////////////////////////////////////////////////////
//ID Management
assign store_complete = (lsq.accepted & lsq.transaction_out.store) | (ls_exception_ack & exception_is_store);
assign store_id = $clog2(MAX_IDS)'(wb_store.commit_id);
////////////////////////////////////////////////////
//Writeback-Store interface
assign wb_store.id_needed_at_issue = ls_inputs.store_forward_id;

View file

@ -83,16 +83,38 @@ module taiga (
logic tlb_on;
logic [ASIDLEN-1:0] asid;
//Pre-Decode
logic pre_decode_push;
logic pre_decode_pop;
logic [31:0] pre_decode_instruction;
logic [31:0] pre_decode_pc;
branch_predictor_metadata_t branch_metadata;
logic branch_prediction_used;
logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way;
logic fb_valid;
fetch_buffer_packet_t fb;
//Instruction ID/Metadata
//ID issuing
id_t pc_id;
logic pc_id_available;
logic pc_id_assigned;
logic [31:0] if_pc;
//Fetch stage
id_t fetch_id;
logic fetch_complete;
logic [31:0] fetch_instruction;
//Decode stage
logic decode_advance;
id_t decode_id;
logic decode_id_valid;
logic [31:0] decode_pc;
logic [31:0] decode_instruction;
//Issue stage
logic issue_stage_valid;
logic dummy_id_complete;
id_t issue_id;
//Branch predictor
branch_metadata_t branch_metadata_if;
branch_metadata_t branch_metadata_ex;
//ID freeing
logic store_complete;
id_t store_id;
logic branch_complete;
id_t branch_id;
logic system_op_complete;
id_t system_op_id;
logic instruction_retired;
id_t retired_id;
//Global Control
logic gc_issue_hold;
@ -112,10 +134,10 @@ module taiga (
logic illegal_instruction;
logic instruction_queue_empty;
logic id_issued;
logic instruction_issued;
logic instruction_issued_no_rd;
logic instruction_issued_with_rd;
logic instruction_complete;
logic gc_flush_required;
//LS
@ -171,7 +193,12 @@ module taiga (
endgenerate
////////////////////////////////////////////////////
// Fetch and Pre-Decode
// ID support
id_management id_management_block (.*);
instruction_metadata id_metadata_block (.*);
////////////////////////////////////////////////////
// Fetch
fetch fetch_block (.*, .icache_on('1), .tlb(itlb), .l1_request(l1_request[L1_ICACHE_ID]), .l1_response(l1_response[L1_ICACHE_ID]), .exception(1'b0));
branch_predictor bp_block (.*);
ras ras_block(.*);
@ -184,7 +211,6 @@ module taiga (
assign itlb.physical_address = itlb.virtual_address;
end
endgenerate
pre_decode pre_decode_block(.*);
////////////////////////////////////////////////////
//Decode/Issue
@ -193,7 +219,7 @@ module taiga (
////////////////////////////////////////////////////
//Execution Units
branch_unit branch_unit_block (.*, .issue(unit_issue[BRANCH_UNIT_ID]));
branch_unit branch_unit_block (.*, .issue(unit_issue[BRANCH_UNIT_ID]), .dec_pc_plus_4(unit_wb[ALU_UNIT_WB_ID].rd));
alu_unit alu_unit_block (.*, .issue(unit_issue[ALU_UNIT_WB_ID]), .wb(unit_wb[ALU_UNIT_WB_ID]));
load_store_unit load_store_unit_block (.*, .dcache_on(1'b1), .clear_reservation(1'b0), .tlb(dtlb), .issue(unit_issue[LS_UNIT_WB_ID]), .wb(unit_wb[LS_UNIT_WB_ID]), .l1_request(l1_request[L1_DCACHE_ID]), .l1_response(l1_response[L1_DCACHE_ID]));
generate if (ENABLE_S_MODE) begin

View file

@ -29,7 +29,7 @@ package taiga_config;
//Privileged ISA Options
//Enable Machine level privilege spec
parameter ENABLE_M_MODE = 0;
parameter ENABLE_M_MODE = 1;
//Enable Supervisor level privilege spec
parameter ENABLE_S_MODE = 0;
//Enable User level privilege spec
@ -158,13 +158,14 @@ package taiga_config;
//Branch Predictor Options
parameter USE_BRANCH_PREDICTOR = 1;
parameter BRANCH_PREDICTOR_WAYS = 2;
parameter BRANCH_TABLE_ENTRIES = 512;
parameter BRANCH_TABLE_ENTRIES = 512;//min 512
parameter RAS_DEPTH = 8;
////////////////////////////////////////////////////
//FIFO/Buffer Depths
//All parameters restricted to powers of two
parameter MAX_IDS = 16;
parameter MAX_INFLIGHT_COUNT = 4;
parameter FETCH_BUFFER_DEPTH = 4;

View file

@ -41,16 +41,16 @@ module taiga_fifo #(parameter DATA_WIDTH = 70, parameter FIFO_DEPTH = 4)
logic [LOG2_FIFO_DEPTH-1:0] write_index;
logic [LOG2_FIFO_DEPTH-1:0] read_index;
logic [LOG2_FIFO_DEPTH:0] inflight_count;
logic supressed_push;
logic potentially_supressed_push;
////////////////////////////////////////////////////
//Implementation
assign supressed_push = fifo.push & ~fifo.supress_push;
assign potentially_supressed_push = fifo.push & ~fifo.supress_push;
generate if (FIFO_DEPTH == 1) begin
always_ff @ (posedge clk) begin
if (rst)
fifo.valid <= 0;
else if (supressed_push)
else if (potentially_supressed_push)
fifo.valid <= 1;
else if (fifo.pop)
fifo.valid <= 0;
@ -69,7 +69,7 @@ module taiga_fifo #(parameter DATA_WIDTH = 70, parameter FIFO_DEPTH = 4)
if (rst)
inflight_count <= 0;
else
inflight_count <= inflight_count + (LOG2_FIFO_DEPTH+1)'(fifo.pop) - (LOG2_FIFO_DEPTH+1)'(supressed_push);
inflight_count <= inflight_count + (LOG2_FIFO_DEPTH+1)'(fifo.pop) - (LOG2_FIFO_DEPTH+1)'(potentially_supressed_push);
end
assign fifo.valid = inflight_count[LOG2_FIFO_DEPTH];
@ -82,7 +82,7 @@ module taiga_fifo #(parameter DATA_WIDTH = 70, parameter FIFO_DEPTH = 4)
end
else begin
read_index <= read_index + LOG2_FIFO_DEPTH'(fifo.pop);
write_index <= write_index + LOG2_FIFO_DEPTH'(supressed_push);
write_index <= write_index + LOG2_FIFO_DEPTH'(potentially_supressed_push);
end
end
@ -96,10 +96,8 @@ module taiga_fifo #(parameter DATA_WIDTH = 70, parameter FIFO_DEPTH = 4)
////////////////////////////////////////////////////
//Assertions
always_ff @ (posedge clk) begin
assert (!(~rst & fifo.full & supressed_push & ~fifo.pop)) else $error("overflow");
//assert (!(~rst & ~fifo.valid & ~supressed_push & fifo.pop)) else $error("underflow");
end
fifo_overflow_assertion:
assert property (@(posedge clk) disable iff (rst) !(fifo.full & potentially_supressed_push & ~fifo.pop)) else $error("overflow");
fifo_underflow_assertion:
assert property (@(posedge clk) disable iff (rst) !(~fifo.valid & fifo.pop)) else $error("underflow");
endmodule

View file

@ -27,6 +27,8 @@ package taiga_types;
localparam ID_W = $clog2(MAX_INFLIGHT_COUNT);
localparam WB_UNITS_WIDTH = $clog2(NUM_WB_UNITS);
typedef logic[$clog2(MAX_IDS)-1:0] id_t;
typedef logic[ID_W-1:0] instruction_id_t;
typedef logic[WB_UNITS_WIDTH-1:0] unit_id_t;
typedef logic[1:0] branch_predictor_metadata_t;
@ -82,20 +84,17 @@ package taiga_types;
typedef struct packed{
branch_predictor_metadata_t branch_predictor_metadata;
logic branch_prediction_used;
logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way;
} branch_unit_metadata_t;
logic [BRANCH_PREDICTOR_WAYS-1:0] branch_predictor_update_way;
} branch_metadata_t;
typedef struct packed{
logic id_assigned;
instruction_id_t pc_id;
id_t pc_id;
logic [31:0] pc;
branch_unit_metadata_t branch_unit_metadata;
logic complete;
instruction_id_t instruction_id;
id_t instruction_id;
logic [31:0] instruction;
} fetch_instruction_metadata_t;
typedef struct packed{
@ -128,22 +127,15 @@ package taiga_types;
logic jalr;
logic is_call;
logic is_return;
logic [31:0] instruction;
branch_predictor_metadata_t branch_metadata;
logic branch_prediction_used;
logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way;
logic [20:0] pc_offset;
} branch_inputs_t;
typedef struct packed {
logic[31:0] pc_ex;
logic [31:0] jump_pc;
logic [31:0] njump_pc;
logic [31:0] new_pc;
logic branch_taken;
logic branch_ex;
logic is_return_ex;
branch_predictor_metadata_t branch_ex_metadata;
logic branch_prediction_used;
logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way;
} branch_results_t;
typedef struct packed{

View file

@ -34,7 +34,8 @@ module write_back(
input unit_writeback_t unit_wb[NUM_WB_UNITS-1:0],
register_file_writeback_interface.writeback rf_wb,
tracking_interface.wb ti,
output logic instruction_complete,
output logic instruction_retired,
output id_t retired_id,
output logic instruction_queue_empty,
output instruction_id_t oldest_id,
@ -209,11 +210,12 @@ module write_back(
end
//Instruction completion tracking for retired instruction count
assign instruction_complete = retiring & ~retiring_instruction_packet.is_store;
assign instruction_retired = retiring & ~retiring_instruction_packet.is_store;
assign retired_id = $clog2(MAX_IDS)'(id_retiring);
assign rf_wb.rd_addr = retiring_instruction_packet.rd_addr;
assign rf_wb.id = id_retiring;
assign rf_wb.retiring = instruction_complete;
assign rf_wb.retiring = instruction_retired;
assign rf_wb.rd_nzero = |retiring_instruction_packet.rd_addr;
assign rf_wb.rd_data = results_by_id[id_retiring];

View file

@ -93,8 +93,8 @@
../core/ras.sv
../core/branch_predictor_ram.sv
../core/branch_predictor.sv
../core/fetch.sv
../core/pre_decode.sv
../core/fetch.sv
../core/illegal_instruction_checker.sv
../core/decode_and_issue.sv
@ -112,5 +112,8 @@
../l2_arbiter/l2_round_robin.sv
../l2_arbiter/l2_arbiter.sv
../core/id_management.sv
../core/instruction_metadata.sv
../core/taiga.sv