diff --git a/core/branch_comparator.sv b/core/branch_comparator.sv index 2abe792..ba22bb5 100644 --- a/core/branch_comparator.sv +++ b/core/branch_comparator.sv @@ -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 diff --git a/core/branch_predictor.sv b/core/branch_predictor.sv index d03b50d..069e112 100755 --- a/core/branch_predictor.sv +++ b/core/branch_predictor.sv @@ -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 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 diff --git a/core/branch_unit.sv b/core/branch_unit.sv index 292429a..bb6e5fe 100755 --- a/core/branch_unit.sv +++ b/core/branch_unit.sv @@ -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 diff --git a/core/csr_regs.sv b/core/csr_regs.sv index 4583e8f..207086b 100755 --- a/core/csr_regs.sv +++ b/core/csr_regs.sv @@ -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 diff --git a/core/decode_and_issue.sv b/core/decode_and_issue.sv index 0ff2776..88584d4 100755 --- a/core/decode_and_issue.sv +++ b/core/decode_and_issue.sv @@ -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}); diff --git a/core/fetch.sv b/core/fetch.sv index e98d466..c4ef4e2 100755 --- a/core/fetch.sv +++ b/core/fetch.sv @@ -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 diff --git a/core/gc_unit.sv b/core/gc_unit.sv index 49852d9..d28ea41 100644 --- a/core/gc_unit.sv +++ b/core/gc_unit.sv @@ -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]; diff --git a/core/id_management.sv b/core/id_management.sv new file mode 100644 index 0000000..a01fcf7 --- /dev/null +++ b/core/id_management.sv @@ -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 + */ + +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 diff --git a/core/instruction_metadata.sv b/core/instruction_metadata.sv new file mode 100644 index 0000000..c93801c --- /dev/null +++ b/core/instruction_metadata.sv @@ -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 + */ + +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 diff --git a/core/interfaces.sv b/core/interfaces.sv index 82f9688..7275f86 100755 --- a/core/interfaces.sv +++ b/core/interfaces.sv @@ -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; diff --git a/core/load_store_unit.sv b/core/load_store_unit.sv index 09020a1..686e6e7 100755 --- a/core/load_store_unit.sv +++ b/core/load_store_unit.sv @@ -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; diff --git a/core/taiga.sv b/core/taiga.sv index 9682881..267d8dc 100755 --- a/core/taiga.sv +++ b/core/taiga.sv @@ -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 diff --git a/core/taiga_config.sv b/core/taiga_config.sv index faf9197..75eb344 100755 --- a/core/taiga_config.sv +++ b/core/taiga_config.sv @@ -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; diff --git a/core/taiga_fifo.sv b/core/taiga_fifo.sv index 3269f4d..819d312 100755 --- a/core/taiga_fifo.sv +++ b/core/taiga_fifo.sv @@ -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 - - diff --git a/core/taiga_types.sv b/core/taiga_types.sv index c063c76..39fbc60 100755 --- a/core/taiga_types.sv +++ b/core/taiga_types.sv @@ -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{ diff --git a/core/write_back.sv b/core/write_back.sv index 6024350..cfe20ba 100755 --- a/core/write_back.sv +++ b/core/write_back.sv @@ -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]; diff --git a/tools/taiga_compile_order b/tools/taiga_compile_order index f0833bf..5c28c11 100644 --- a/tools/taiga_compile_order +++ b/tools/taiga_compile_order @@ -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