diff --git a/core/branch_unit.sv b/core/branch_unit.sv index 2cc3e58..844ab4e 100755 --- a/core/branch_unit.sv +++ b/core/branch_unit.sv @@ -34,7 +34,6 @@ module branch_unit( ras_interface.branch_unit ras, output logic branch_flush, - output logic branch_complete, output id_t branch_id, input branch_metadata_t branch_metadata_ex, @@ -65,6 +64,7 @@ module branch_unit( logic [31:0] pc_ex; logic instruction_is_completing; + logic branch_complete; logic jal_jalr_ex; //////////////////////////////////////////////////// //Implementation diff --git a/core/csr_regs.sv b/core/csr_regs.sv index 39aabb0..1e02f40 100755 --- a/core/csr_regs.sv +++ b/core/csr_regs.sv @@ -53,8 +53,8 @@ module csr_regs mmu_interface.csr immu, mmu_interface.csr dmmu, - //WB - input logic [$clog2(MAX_COMPLETE_COUNT)-1:0] retire_inc, + //Retire + input retire_packet_t retire, //External input logic interrupt, @@ -543,7 +543,7 @@ endgenerate end logic[COUNTER_W-1:0] minst_ret_next; - assign minst_ret_next = minst_ret + COUNTER_W'(retire_inc); + assign minst_ret_next = minst_ret + COUNTER_W'(retire.count); always_ff @(posedge clk) begin if (rst) begin diff --git a/core/decode_and_issue.sv b/core/decode_and_issue.sv index 58ba043..d1a11bc 100755 --- a/core/decode_and_issue.sv +++ b/core/decode_and_issue.sv @@ -33,8 +33,18 @@ module decode_and_issue ( input decode_packet_t decode, output logic decode_advance, + //Renamer + renamer_interface.decode renamer, + + output logic decode_uses_rd, + output rs_addr_t decode_rd_addr, + output phys_addr_t decode_phys_rd_addr, + output logic instruction_issued, + output logic instruction_issued_with_rd, output issue_packet_t issue, - input logic [31:0] rs_data [REGFILE_READ_PORTS], + + //Register File + register_file_issue_interface.issue rf, output alu_inputs_t alu_inputs, output load_store_inputs_t ls_inputs, @@ -44,8 +54,6 @@ module decode_and_issue ( output div_inputs_t div_inputs, unit_issue_interface.decode unit_issue [NUM_UNITS-1:0], - input logic potential_branch_exception, - output logic alu_issued, input logic gc_fetch_hold, input logic gc_issue_hold, @@ -53,13 +61,6 @@ module decode_and_issue ( input logic gc_issue_flush, output logic gc_flush_required, - //ID Management - input logic rs_inuse [REGFILE_READ_PORTS], - input id_t rs_id [REGFILE_READ_PORTS], - input logic rs_id_inuse [REGFILE_READ_PORTS], - - output logic instruction_issued, - output logic instruction_issued_with_rd, output logic illegal_instruction, //Trace signals @@ -102,7 +103,6 @@ module decode_and_issue ( logic environment_op; logic issue_valid; - logic operands_ready; logic [NUM_UNITS-1:0] unit_operands_ready; logic mult_div_op; @@ -149,32 +149,6 @@ module decode_and_issue ( assign uses_rs2 = opcode_trim inside {BRANCH_T, STORE_T, ARITH_T, AMO_T}; assign uses_rd = !(opcode_trim inside {BRANCH_T, STORE_T, FENCE_T} || environment_op); - always_ff @(posedge clk) begin - if (rst | gc_fetch_flush) - issue.stage_valid <= 0; - else if (issue_stage_ready) - issue.stage_valid <= decode.valid; - end - - always_ff @(posedge clk) begin - if (issue_stage_ready) begin - issue.pc <= decode.pc; - issue.instruction <= decode.instruction; - issue.fetch_metadata <= decode.fetch_metadata; - issue.fn3 <= fn3; - issue.opcode <= opcode; - issue.rs_addr[RS1] <= rs1_addr; - issue.rs_addr[RS2] <= rs2_addr; - issue.rs_phys_addr[RS1] <= {1'b0, rs1_addr}; - issue.rs_phys_addr[RS2] <= {1'b0, rs2_addr}; - issue.rd_addr <= rd_addr; - issue.id <= decode.id; - issue.uses_rs1 <= uses_rs1; - issue.uses_rs2 <= uses_rs2; - issue.uses_rd <= uses_rd; - end - end - //////////////////////////////////////////////////// //Unit Determination assign unit_needed[BRANCH_UNIT_ID] = opcode_trim inside {BRANCH_T, JAL_T, JALR_T}; @@ -191,11 +165,58 @@ module decode_and_issue ( assign unit_needed[DIV_UNIT_ID] = mult_div_op && fn3[2]; endgenerate + //////////////////////////////////////////////////// + //Renamer Support + assign renamer.rd_addr = rd_addr; + assign renamer.rs_addr[RS1] = rs1_addr; + assign renamer.rs_addr[RS2] = rs2_addr; + assign renamer.uses_rd = uses_rd; + assign renamer.rd_wb_group = ~unit_needed[ALU_UNIT_ID];//TODO: automate generation of wb group logic + assign renamer.id = decode.id; + + //////////////////////////////////////////////////// + //Decode ID Support + assign decode_uses_rd = uses_rd; + assign decode_rd_addr = rd_addr; + assign decode_phys_rd_addr = renamer.phys_rd_addr; + + //////////////////////////////////////////////////// + //Issue + always_ff @(posedge clk) begin + if (issue_stage_ready) begin + issue.pc <= decode.pc; + issue.instruction <= decode.instruction; + issue.fetch_metadata <= decode.fetch_metadata; + issue.fn3 <= fn3; + issue.opcode <= opcode; + issue.rs_addr[RS1] <= rs1_addr; + issue.rs_addr[RS2] <= rs2_addr; + issue.phys_rs_addr[RS1] <= renamer.phys_rs_addr[RS1]; + issue.phys_rs_addr[RS2] <= renamer.phys_rs_addr[RS2]; + issue.rs_wb_group <= renamer.rs_wb_group; + issue.rd_addr <= rd_addr; + issue.phys_rd_addr <= renamer.phys_rd_addr; + issue.rd_wb_group <= ~unit_needed[ALU_UNIT_ID]; + issue.id <= decode.id; + issue.uses_rs1 <= uses_rs1; + issue.uses_rs2 <= uses_rs2; + issue.uses_rd <= uses_rd; + end + end + always_ff @(posedge clk) begin if (issue_stage_ready) unit_needed_issue_stage <= unit_needed; end + always_ff @(posedge clk) begin + if (rst | gc_fetch_flush) + issue.stage_valid <= 0; + else if (issue_stage_ready) + issue.stage_valid <= decode.valid; + end + + //////////////////////////////////////////////////// //Unit ready generate for (i=0; i ITLB_DEPTH) ? DTLB_DEPTH : ITLB_DEPTH; //For general reset clear, greater of TLB depth or id-flight memory blocks (MAX_IDS) - localparam int INIT_CLEAR_DEPTH = ENABLE_S_MODE ? (TLB_CLEAR_DEPTH > MAX_IDS ? TLB_CLEAR_DEPTH : MAX_IDS) : MAX_IDS; + localparam int INIT_CLEAR_DEPTH = ENABLE_S_MODE ? (TLB_CLEAR_DEPTH > 64 ? TLB_CLEAR_DEPTH : 64) : 64; //////////////////////////////////////////////////// //Instructions @@ -137,6 +131,9 @@ module gc_unit( exception_code_t ecall_code; logic second_cycle_flush; + logic system_op_or_exception_complete; + logic exception_with_rd_complete; + //CSR logic mret; logic sret; @@ -182,7 +179,7 @@ module gc_unit( system_op_or_exception_complete <= (issue.new_request & (gc_inputs.is_ret | gc_inputs.is_fence | gc_inputs.is_i_fence)) | gc_exception.valid; - system_op_or_exception_id <= exception_or_system_id; + exception_id <= exception_or_system_id; exception_with_rd_complete <= (ls_exception.valid & ~ls_exception_is_store) | (br_exception.valid & branch_exception_is_jump); end @@ -338,7 +335,7 @@ module gc_unit( .asid(asid), .immu(immu), .dmmu(dmmu), - .retire_inc(retire_inc), + .retire(retire), .interrupt(interrupt), .timer_interrupt(timer_interrupt), .wb_csr(wb_csr), diff --git a/core/instruction_metadata_and_id_management.sv b/core/instruction_metadata_and_id_management.sv index 954c8c6..d29fdb1 100644 --- a/core/instruction_metadata_and_id_management.sv +++ b/core/instruction_metadata_and_id_management.sv @@ -47,37 +47,32 @@ module instruction_metadata_and_id_management //Decode ID output decode_packet_t decode, input logic decode_advance, + input logic decode_uses_rd, + input rs_addr_t decode_rd_addr, + //renamer + input phys_addr_t decode_phys_rd_addr, //Issue stage input issue_packet_t issue, input logic instruction_issued, - output id_t rs_id [REGFILE_READ_PORTS], - output logic rs_inuse [REGFILE_READ_PORTS], - output logic rs_id_inuse[REGFILE_READ_PORTS], + input logic instruction_issued_with_rd, //Branch Predictor input branch_metadata_t branch_metadata_if, + input id_t branch_id, output branch_metadata_t branch_metadata_ex, - //ID freeing - input logic store_complete, - input id_t store_id, + //WB + input wb_packet_t wb_packet [NUM_WB_GROUPS], + output commit_packet_t commit_packet [NUM_WB_GROUPS], - input logic branch_complete, - input id_t branch_id, + //Retirer + output retire_packet_t retire, + output id_t retire_ids [RETIRE_PORTS], + output logic retire_ids_retired [RETIRE_PORTS], - input logic system_op_or_exception_complete, - input logic exception_with_rd_complete, - input id_t system_op_or_exception_id, - - output logic [$clog2(MAX_COMPLETE_COUNT)-1:0] retire_inc, - - //Writeback/Register File - input id_t ids_retiring [COMMIT_PORTS], - input logic retired [COMMIT_PORTS], - output logic [4:0] retired_rd_addr [COMMIT_PORTS], - output id_t id_for_rd [COMMIT_PORTS], //Exception + input id_t exception_id, output logic [31:0] exception_pc ); @@ -86,39 +81,21 @@ module instruction_metadata_and_id_management logic [31:0] instruction_table [MAX_IDS]; logic valid_fetch_addr_table [MAX_IDS]; - logic [4:0] rd_addr_table [MAX_IDS]; + rs_addr_t rd_addr_table [MAX_IDS]; + phys_addr_t phys_addr_table [MAX_IDS]; + logic uses_rd_table [MAX_IDS]; + logic [$bits(branch_metadata_t)-1:0] branch_metadata_table [MAX_IDS]; logic [$bits(fetch_metadata_t)-1:0] fetch_metadata_table [MAX_IDS]; localparam LOG2_MAX_IDS = $clog2(MAX_IDS); - id_t clear_index; - id_t pc_id_next; id_t decode_id; + logic [LOG2_MAX_IDS:0] fetched_count; //MSB used as valid for decode stage + logic [LOG2_MAX_IDS:0] pre_issue_count; + logic [LOG2_MAX_IDS:0] post_issue_count; + logic [LOG2_MAX_IDS:0] inflight_count; - //Toggle memory results for tracking completion after issue - logic decoded_status; - logic decoded_issued_status; - - logic issued_status; - logic issued_status_rs [REGFILE_READ_PORTS]; - - logic branch_complete_status; - logic store_complete_status; - - logic system_op_or_exception_complete_status; - logic exception_with_rd_complete_status_rs [REGFILE_READ_PORTS]; - - logic [COMMIT_PORTS-1:0] retired_status; - logic [COMMIT_PORTS-1:0] retired_status_rs [REGFILE_READ_PORTS]; - - logic [$clog2(MAX_COMPLETE_COUNT)-1:0] complete_count; - - logic id_not_in_decode_issue; - logic id_not_inflight; - - //Writes to register file - id_t rd_to_id_table [32]; genvar i; //////////////////////////////////////////////////// //Implementation @@ -143,40 +120,42 @@ module instruction_metadata_and_id_management instruction_table[fetch_id] <= fetch_instruction; end - //rd table - always_ff @ (posedge clk) begin - if (fetch_complete) - rd_addr_table[fetch_id] <= fetch_instruction[11:7]; - end - //valid fetched address table always_ff @ (posedge clk) begin if (fetch_complete) fetch_metadata_table[fetch_id] <= fetch_metadata; end - - //Operand inuse determination - initial rd_to_id_table = '{default: 0}; + //phys rd table always_ff @ (posedge clk) begin - if (instruction_issued & issue.uses_rd)//tracks most recently issued instruction that writes to the register file - rd_to_id_table[issue.rd_addr] <= issue.id; + if (decode_advance) + phys_addr_table[decode_id] <= decode_phys_rd_addr; end + //rd table + always_ff @ (posedge clk) begin + if (decode_advance) + rd_addr_table[decode_id] <= decode_rd_addr; + end + + //uses rd table + always_ff @ (posedge clk) begin + if (decode_advance) + uses_rd_table[decode_id] <= decode_uses_rd; + end //////////////////////////////////////////////////// //ID Management //Next ID always increases, except on a fetch buffer flush. - //On a fetch buffer flush, the next ID is restored to the current decode ID. + //On a fetch buffer flush, the next ID is restored to the oldest non-issued ID (decode or issue stage) //This prevents a stall in the case where all IDs are either in-flight or //in the fetch buffer at the point of a fetch flush. id_t next_pc_id_base; id_t next_fetch_id_base; - assign next_pc_id_base = gc_fetch_flush ? decode_id : (early_branch_flush ? fetch_id : pc_id); - assign next_fetch_id_base = gc_fetch_flush ? decode_id : fetch_id; + assign next_pc_id_base = gc_fetch_flush ? (issue.stage_valid ? issue.id : decode_id) : (early_branch_flush ? fetch_id : pc_id); + assign next_fetch_id_base = gc_fetch_flush ? (issue.stage_valid ? issue.id : decode_id) : fetch_id; - assign pc_id_next = next_pc_id_base + LOG2_MAX_IDS'({pc_id_assigned & ~gc_fetch_flush}); always_ff @ (posedge clk) begin if (rst) begin pc_id <= 0; @@ -186,103 +165,107 @@ module instruction_metadata_and_id_management else begin pc_id <= next_pc_id_base + LOG2_MAX_IDS'({pc_id_assigned & (~gc_fetch_flush)}); fetch_id <= next_fetch_id_base + LOG2_MAX_IDS'({fetch_complete & ~gc_fetch_flush}); - decode_id <= decode_id + LOG2_MAX_IDS'({decode_advance & ~gc_fetch_flush}); + decode_id <= ((gc_fetch_flush & issue.stage_valid) ? issue.id : decode_id) + LOG2_MAX_IDS'({decode_advance & ~gc_fetch_flush}); end end + //Retire IDs + generate for (i = 0; i < RETIRE_PORTS; i++) begin + always_ff @ (posedge clk) begin + if (rst) + retire_ids[i] <= LOG2_MAX_IDS'(i); + else + retire_ids[i] <= retire_ids[i] + LOG2_MAX_IDS'(retire.count); + end + end endgenerate always_ff @ (posedge clk) begin if (rst | gc_fetch_flush) fetched_count <= 0; else - fetched_count <= fetched_count + (LOG2_MAX_IDS+1)'(decode_advance) - (LOG2_MAX_IDS+1)'(fetch_complete); + fetched_count <= fetched_count + (LOG2_MAX_IDS+1)'(fetch_complete) - (LOG2_MAX_IDS+1)'(decode_advance); end - //////////////////////////////////////////////////// - //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. - - //Computed one cycle in advance using pc_id_next - logic id_in_decode_issue [1]; - toggle_memory_set # ( - .DEPTH (MAX_IDS), - .NUM_WRITE_PORTS (2), - .NUM_READ_PORTS (1), - .WRITE_INDEX_FOR_RESET (0), - .READ_INDEX_FOR_RESET (0) - ) id_in_decode_tracking - ( - .clk (clk), - .rst (rst), - .init_clear (gc_init_clear), - .toggle ('{(decode_advance & ~gc_fetch_flush), (instruction_issued | (gc_fetch_flush & issue.stage_valid))}), - .toggle_addr ('{decode.id, issue.id}), - .read_addr ('{pc_id_next}), - .in_use (id_in_decode_issue) - ); - assign id_not_in_decode_issue = ~id_in_decode_issue[0]; - - //////////////////////////////////////////////////// - //Outputs - logic id_inflight [1]; - toggle_memory_set # ( - .DEPTH (MAX_IDS), - .NUM_WRITE_PORTS (6), - .NUM_READ_PORTS (1), - .WRITE_INDEX_FOR_RESET (0), - .READ_INDEX_FOR_RESET (0) - ) id_inflight_tracking - ( - .clk (clk), - .rst (rst), - .init_clear (gc_init_clear), - .toggle ('{instruction_issued, branch_complete, store_complete, system_op_or_exception_complete, retired[0], retired[1]}), - .toggle_addr ('{issue.id, branch_id, store_id, system_op_or_exception_id, ids_retiring[0], ids_retiring[1]}), - .read_addr ('{pc_id_next}), - .in_use (id_inflight) - ); - assign id_not_inflight = ~id_inflight[0]; - - //rs1/rs2 conflicts don't check branch or store memories as the only - //IDs stored in the rs to ID table are instructions that write to the register file - toggle_memory_set # ( - .DEPTH (MAX_IDS), - .NUM_WRITE_PORTS (4), - .NUM_READ_PORTS (2), - .WRITE_INDEX_FOR_RESET (0), - .READ_INDEX_FOR_RESET (0) - ) rs_inuse_tacking - ( - .clk (clk), - .rst (rst), - .init_clear (gc_init_clear), - .toggle ('{(instruction_issued & issue.uses_rd), exception_with_rd_complete, retired[0], retired[1]}), - .toggle_addr ('{issue.id, system_op_or_exception_id, ids_retiring[0], ids_retiring[1]}), - .read_addr (rs_id), - .in_use (rs_id_inuse) - ); + always_ff @ (posedge clk) begin + if (rst | gc_fetch_flush) + pre_issue_count <= 0; + else + pre_issue_count <= pre_issue_count + + (LOG2_MAX_IDS+1)'(pc_id_assigned) + - (LOG2_MAX_IDS+1)'(instruction_issued); + end always_ff @ (posedge clk) begin if (rst) - pc_id_available <= 1; + post_issue_count <= 0; else - pc_id_available <= id_not_in_decode_issue & id_not_inflight; + post_issue_count <= post_issue_count + + (LOG2_MAX_IDS+1)'(instruction_issued) + - (LOG2_MAX_IDS+1)'(retire.count); end - localparam MCC_W = $clog2(MAX_COMPLETE_COUNT); + assign inflight_count = pre_issue_count + post_issue_count; + + //////////////////////////////////////////////////// + //ID in-use determination + logic id_inuse [RETIRE_PORTS]; + //WB group zero is not included as it completes within a single cycle + //Non-writeback instructions not included as current instruction set + //complete in their first cycle of the execute stage, or do not cause an + //exception after that point + toggle_memory_set # ( + .DEPTH (MAX_IDS), + .NUM_WRITE_PORTS (2), + .NUM_READ_PORTS (RETIRE_PORTS), + .WRITE_INDEX_FOR_RESET (0), + .READ_INDEX_FOR_RESET (0) + ) id_inuse_toggle_mem_set + ( + .clk (clk), + .rst (rst), + .init_clear (gc_init_clear), + .toggle ('{(instruction_issued_with_rd & (issue.rd_wb_group == 1)), wb_packet[1].valid}), + .toggle_addr ('{issue.id, wb_packet[1].id}), + .read_addr (retire_ids), + .in_use (id_inuse) + ); + + //////////////////////////////////////////////////// + //Retirer + logic contiguous_retire; + always_comb begin - complete_count = MCC_W'(branch_complete) + MCC_W'(store_complete) + MCC_W'(system_op_or_exception_complete); - for (int i = 0; i < COMMIT_PORTS; i++) begin - complete_count += MCC_W'(retired[i]); + contiguous_retire = 1; + retire_ids_retired = '{default: 0}; + + retire.valid = 0; + retire.count = 0; + retire.phys_id = retire_ids[0]; + + for (int i = 0; i < RETIRE_PORTS; i++) begin + //Only pop if all older entries have been popped and only if this is either the first entry that writes to the regfile + //or does not write to the regfile + if ((post_issue_count > (LOG2_MAX_IDS+1)'(i)) && contiguous_retire) begin + retire_ids_retired[i] = (~uses_rd_table[retire_ids[i]] | (~id_inuse[i] & ~retire.valid)); + contiguous_retire &= retire_ids_retired[i]; + retire.count += retire_ids_retired[i]; + + if (retire_ids_retired[i] & uses_rd_table[retire_ids[i]]) begin + retire.valid |= 1; + retire.phys_id = retire_ids[i]; + end + end end + + retire.rd_addr = rd_addr_table[retire.phys_id]; end - always_ff @ (posedge clk) begin - retire_inc <= complete_count; - end + + //////////////////////////////////////////////////// + //Outputs + assign pc_id_available = ~inflight_count[LOG2_MAX_IDS]; //Decode assign decode.id = decode_id; - assign decode.valid = fetched_count[LOG2_MAX_IDS]; + assign decode.valid = |fetched_count; assign decode.pc = pc_table[decode_id]; assign decode.instruction = instruction_table[decode_id]; assign decode.fetch_metadata = fetch_metadata_table[decode_id]; @@ -290,30 +273,24 @@ module instruction_metadata_and_id_management //Branch Predictor assign branch_metadata_ex = branch_metadata_table[branch_id]; - //Issue + //Writeback/Commit support always_comb begin - for (int i = 0; i < REGFILE_READ_PORTS; i++) begin - rs_id[i] = rd_to_id_table[issue.rs_addr[i]]; - rs_inuse[i] = (|issue.rs_addr[i]) & (issue.rs_addr[i] == rd_addr_table[rs_id[i]]); - end - end - - //Writeback support - always_comb begin - retired_rd_addr[0] = issue.rd_addr; - for (int i = 1; i < COMMIT_PORTS; i++) begin - retired_rd_addr[i] = rd_addr_table[ids_retiring[i]]; + for (int i = 0; i < NUM_WB_GROUPS; i++) begin + commit_packet[i].id = wb_packet[i].id; + commit_packet[i].valid = wb_packet[i].valid; + commit_packet[i].data = wb_packet[i].data; end end always_comb begin - for (int i = 0; i < COMMIT_PORTS; i++) begin - id_for_rd[i] = rd_to_id_table[retired_rd_addr[i]]; + commit_packet[0].phys_addr = issue.phys_rd_addr; + for (int i = 1; i < NUM_WB_GROUPS; i++) begin + commit_packet[i].phys_addr = phys_addr_table[wb_packet[i].id]; end end //Exception Support generate if (ENABLE_M_MODE) begin - assign exception_pc = pc_table[system_op_or_exception_id]; + assign exception_pc = pc_table[exception_id]; end endgenerate //////////////////////////////////////////////////// diff --git a/core/interfaces.sv b/core/interfaces.sv index 97430c9..6c4aeb9 100755 --- a/core/interfaces.sv +++ b/core/interfaces.sv @@ -271,3 +271,46 @@ interface unsigned_division_interface #(parameter DATA_WIDTH = 32); modport divider (output remainder, quotient, done, divisor_is_zero, input dividend, divisor, start); endinterface +interface renamer_interface; + rs_addr_t rd_addr; + rs_addr_t [REGFILE_READ_PORTS-1:0] rs_addr; + rs_wb_group_t rd_wb_group; + logic uses_rd; + id_t id; + + phys_addr_t [REGFILE_READ_PORTS-1:0] phys_rs_addr; + phys_addr_t phys_rd_addr; + + rs_wb_group_t [REGFILE_READ_PORTS-1:0] rs_wb_group; + + modport renamer ( + input rd_addr, rs_addr, rd_wb_group, uses_rd, id, + output phys_rs_addr, rs_wb_group, phys_rd_addr + ); + modport decode ( + input phys_rs_addr, rs_wb_group, phys_rd_addr, + output rd_addr, rs_addr, rd_wb_group, uses_rd, id + ); +endinterface + +interface register_file_issue_interface; + //read interface + phys_addr_t phys_rs_addr [REGFILE_READ_PORTS]; + logic [LOG2_COMMIT_PORTS-1:0] rs_wb_group [REGFILE_READ_PORTS]; + logic [31:0] data [REGFILE_READ_PORTS]; + logic inuse [REGFILE_READ_PORTS]; + + //write interface + phys_addr_t phys_rd_addr; + logic [LOG2_COMMIT_PORTS-1:0] rd_wb_group; + logic issued; + + modport register_file ( + input phys_rs_addr, phys_rd_addr, issued, rs_wb_group, rd_wb_group, + output data, inuse + ); + modport issue ( + output phys_rs_addr, phys_rd_addr, issued, rs_wb_group, rd_wb_group, + input data, inuse + ); +endinterface diff --git a/core/load_store_queue.sv b/core/load_store_queue.sv index a7054f9..9ea5a01 100644 --- a/core/load_store_queue.sv +++ b/core/load_store_queue.sv @@ -36,9 +36,10 @@ module load_store_queue //ID-based input buffer for Load/Store Unit //Writeback snooping input wb_packet_t wb_snoop, - //Writeback release - input id_t ids_released [COMMIT_PORTS], - input logic wb_released [COMMIT_PORTS], + //Retire release + input id_t retire_ids [RETIRE_PORTS], + input logic retire_ids_retired [RETIRE_PORTS], + output logic tr_possible_load_conflict_delay ); localparam SQ_DEPTH = 4; @@ -97,8 +98,8 @@ module load_store_queue //ID-based input buffer for Load/Store Unit .sq_entry (sq_entry), .sq_data (sq_data), .wb_snoop (wb_snoop), - .ids_released (ids_released), - .wb_released (wb_released), + .retire_ids (retire_ids), + .retire_ids_retired (retire_ids_retired), .store_ack (store_ack), .sq_output_valid (sq_output_valid) ); diff --git a/core/load_store_unit.sv b/core/load_store_unit.sv index adeb3f5..5f6672c 100755 --- a/core/load_store_unit.sv +++ b/core/load_store_unit.sv @@ -49,13 +49,13 @@ module load_store_unit ( local_memory_interface.master data_bram, - //ID Management - output logic store_complete, - output id_t store_id, - //Writeback-Store Interface input wb_packet_t wb_snoop, + //Retire release + input id_t retire_ids [RETIRE_PORTS], + input logic retire_ids_retired [RETIRE_PORTS], + //CSR support output logic ls_is_idle, @@ -188,29 +188,20 @@ endgenerate assign lsq.new_issue = issue.new_request & ~unaligned_addr & (~tlb_on | tlb.done); load_store_queue lsq_block ( - .clk (clk), - .rst (rst), - .gc_fetch_flush (gc_fetch_flush), - .gc_issue_flush (gc_issue_flush), - .lsq (lsq), - .wb_snoop (wb_snoop), - .ids_released ('{LOG2_MAX_IDS'(1'b0), store_id}), - .wb_released ('{1'b0, store_complete}), + .clk (clk), + .rst (rst), + .gc_fetch_flush (gc_fetch_flush), + .gc_issue_flush (gc_issue_flush), + .lsq (lsq), + .wb_snoop (wb_snoop), + .retire_ids (retire_ids), + .retire_ids_retired (retire_ids_retired), .tr_possible_load_conflict_delay (tr_possible_load_conflict_delay) ); assign shared_inputs = lsq.transaction_out; - assign lsq.accepted = issue_request; - //////////////////////////////////////////////////// - //ID Management - always_ff @ (posedge clk) begin - store_id <= lsq.id; - if (rst) - store_complete <= 0; - else - store_complete <= lsq.new_issue & lsq.store; - end + //////////////////////////////////////////////////// //Unit tracking assign current_unit = sub_unit_address_match; diff --git a/core/register_bank.sv b/core/register_bank.sv new file mode 100644 index 0000000..12786d9 --- /dev/null +++ b/core/register_bank.sv @@ -0,0 +1,67 @@ +/* + * Copyright © 2017-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 register_bank + import taiga_config::*; + import riscv_types::*; + import taiga_types::*; + #( + parameter NUM_READ_PORTS = 2 + ) + ( + input logic clk, + input logic rst, + + //Writeback + input phys_addr_t write_addr, + input logic [31:0] new_data, + input logic commit, + + //Issue + input phys_addr_t read_addr [NUM_READ_PORTS], + output logic [31:0] data [NUM_READ_PORTS] + ); + + logic [31:0] register_file_bank [64]; + //////////////////////////////////////////////////// + //Implementation + + //////////////////////////////////////////////////// + //Register File + //Assign zero to r0 and initialize all registers to zero for simulation + initial register_file_bank = '{default: 0}; + always_ff @ (posedge clk) begin + if (commit) + register_file_bank[write_addr] <= new_data; + end + always_comb begin + foreach(read_addr[i]) + data[i] = register_file_bank[read_addr[i]]; + end + + //////////////////////////////////////////////////// + //Assertions + write_to_zero_reg_assertion: + assert property (@(posedge clk) disable iff (rst) !(commit & write_addr == 0)) + else $error("Write to zero reg occured!"); + +endmodule diff --git a/core/register_file.sv b/core/register_file.sv old mode 100644 new mode 100755 index 9069fef..86cf091 --- a/core/register_file.sv +++ b/core/register_file.sv @@ -1,5 +1,5 @@ /* - * Copyright © 2017-2020 Eric Matthews, Lesley Shannon + * 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. @@ -24,44 +24,86 @@ module register_file import taiga_config::*; import riscv_types::*; import taiga_types::*; - #( - parameter NUM_READ_PORTS = 2 - ) ( input logic clk, input logic rst, + input logic gc_init_clear, + + //Issue interface + register_file_issue_interface.register_file rf_issue, + //Writeback - input phys_addr_t write_addr, - input logic [31:0] new_data, - input logic commit, - - //Issue - input phys_addr_t [NUM_READ_PORTS-1:0] read_addr, - output logic [31:0] data [NUM_READ_PORTS] + input commit_packet_t commit [NUM_WB_GROUPS] ); + typedef logic [31:0] rs_data_set_t [REGFILE_READ_PORTS]; + rs_data_set_t rs_data_set [NUM_WB_GROUPS]; - logic [31:0] register_file [64]; + typedef logic inuse_t [REGFILE_READ_PORTS]; + inuse_t phys_reg_inuse_set [NUM_WB_GROUPS]; + + genvar i; //////////////////////////////////////////////////// //Implementation //////////////////////////////////////////////////// - //Register File - //Assign zero to r0 and initialize all registers to zero for simulation - initial register_file = '{default: 0}; - always_ff @ (posedge clk) begin - if (commit) - register_file[write_addr] <= new_data; - end + //Phys register inuse + //WB group 0 contains the ALU, a single-cycle unit, thus any preceeding + //instructions will have written their data to the register file + assign phys_reg_inuse_set[0] = '{default : 0}; + + //WB groups 1+ have multiple-cycle operation and thus a status flag is set + //for each physical register + toggle_memory_set # ( + .DEPTH (64), + .NUM_WRITE_PORTS (2), + .NUM_READ_PORTS (REGFILE_READ_PORTS), + .WRITE_INDEX_FOR_RESET (0), + .READ_INDEX_FOR_RESET (0) + ) id_inuse_toggle_mem_set + ( + .clk (clk), + .rst (rst), + .init_clear (gc_init_clear), + .toggle ('{(rf_issue.issued & (rf_issue.rd_wb_group == 1) & |rf_issue.phys_rd_addr), (commit[1].valid & |commit[1].phys_addr)}), + .toggle_addr ('{rf_issue.phys_rd_addr, commit[1].phys_addr}), + .read_addr (rf_issue.phys_rs_addr), + .in_use (phys_reg_inuse_set[1]) + ); always_comb begin - foreach(read_addr[i]) - data[i] = register_file[read_addr[i]]; + for (int i = 0; i < REGFILE_READ_PORTS; i++) begin + rf_issue.inuse[i] = phys_reg_inuse_set[rf_issue.rs_wb_group[i]][i]; + end end + //////////////////////////////////////////////////// + //Register Banks + //Implemented in seperate module as there is not universal tool support for inferring + //arrays of memory blocks. + generate for (i = 0; i < NUM_WB_GROUPS; i++) begin : register_file_gen + register_bank #(.NUM_READ_PORTS(REGFILE_READ_PORTS)) reg_group ( + .clk, .rst, + .write_addr(commit[i].phys_addr), + .new_data(commit[i].data), + .commit(commit[i].valid & (|commit[i].phys_addr)), + .read_addr(rf_issue.phys_rs_addr), + .data(rs_data_set[i]) + ); + end endgenerate + + //////////////////////////////////////////////////// + //Register File Muxing + always_comb begin + for (int i = 0; i < REGFILE_READ_PORTS; i++) begin + rf_issue.data[i] = rs_data_set[rf_issue.rs_wb_group[i]][i]; + end + end + + //////////////////////////////////////////////////// + //End of Implementation + //////////////////////////////////////////////////// + //////////////////////////////////////////////////// //Assertions - write_to_zero_reg_assertion: - assert property (@(posedge clk) disable iff (rst) !(commit & write_addr == 0)) - else $error("Write to zero reg occured!"); endmodule diff --git a/core/register_free_list.sv b/core/register_free_list.sv new file mode 100644 index 0000000..230de50 --- /dev/null +++ b/core/register_free_list.sv @@ -0,0 +1,92 @@ +/* + * Copyright © 2017-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 + */ + +/* + * FIFOs Not underflow/overflow safe. + * Intended for small FIFO depths. + * For continuous operation when full, enqueing side must inspect pop signal + */ +module register_free_list + import taiga_config::*; + import riscv_types::*; + import taiga_types::*; + #( + parameter DATA_WIDTH = 70, + parameter FIFO_DEPTH = 4 + ) + ( + input logic clk, + input logic rst, + fifo_interface.structure fifo, + input logic rollback + ); + + localparam LOG2_FIFO_DEPTH = $clog2(FIFO_DEPTH); + + //Force FIFO depth to next power of 2 + (* ramstyle = "MLAB, no_rw_check" *) logic [DATA_WIDTH-1:0] lut_ram [(2**LOG2_FIFO_DEPTH)]; + logic [LOG2_FIFO_DEPTH-1:0] write_index; + logic [LOG2_FIFO_DEPTH-1:0] read_index; + logic [LOG2_FIFO_DEPTH:0] inflight_count; + //////////////////////////////////////////////////// + //Implementation + + //////////////////////////////////////////////////// + //Occupancy Tracking + always_ff @ (posedge clk) begin + if (rst) + inflight_count <= 0; + else + inflight_count <= inflight_count + + (LOG2_FIFO_DEPTH+1)'(fifo.pop) + - (LOG2_FIFO_DEPTH+1)'(fifo.push) + - (LOG2_FIFO_DEPTH+1)'(rollback); + end + + assign fifo.valid = inflight_count[LOG2_FIFO_DEPTH]; + assign fifo.full = fifo.valid & ~|inflight_count[LOG2_FIFO_DEPTH-1:0]; + + always_ff @ (posedge clk) begin + if (rst) begin + read_index <= '0; + write_index <= '0; + end + else begin + read_index <= read_index + LOG2_FIFO_DEPTH'(fifo.pop) - LOG2_FIFO_DEPTH'(rollback); + write_index <= write_index + LOG2_FIFO_DEPTH'(fifo.push); + end + end + + always_ff @ (posedge clk) begin + if (fifo.potential_push) + lut_ram[write_index] <= fifo.data_in; + end + assign fifo.data_out = lut_ram[read_index]; + + //////////////////////////////////////////////////// + //Assertions + fifo_overflow_assertion: + assert property (@(posedge clk) disable iff (rst) fifo.push |-> (~fifo.full | fifo.pop)) else $error("overflow"); + fifo_underflow_assertion: + assert property (@(posedge clk) disable iff (rst) fifo.pop |-> fifo.valid) else $error("underflow"); + +endmodule \ No newline at end of file diff --git a/core/renamer.sv b/core/renamer.sv new file mode 100644 index 0000000..f873b62 --- /dev/null +++ b/core/renamer.sv @@ -0,0 +1,163 @@ +/* + * 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 renamer + + import taiga_config::*; + import taiga_types::*; + + ( + input logic clk, + input logic rst, + + input logic gc_init_clear, + input logic gc_fetch_flush, + + //Decode + input logic decode_advance, + renamer_interface.renamer decode, + + //Issue stage + input issue_packet_t issue, + + //Retire response + input retire_packet_t retire + ); + ////////////////////////////////////////// + phys_addr_t architectural_id_to_phys_table [MAX_IDS]; + phys_addr_t speculative_rd_to_phys_table [32]; + + rs_wb_group_t spec_wb_group [32]; + rs_wb_group_t arch_wb_group [32]; + rs_wb_group_t rollback_wb_group; + + logic [5:0] clear_index; + fifo_interface #(.DATA_WIDTH(6)) free_list (); + logic rename_valid; + logic rollback; + phys_addr_t rollback_phys_addr; + //////////////////////////////////////////////////// + //Implementation + assign rename_valid = (~gc_fetch_flush) & decode_advance & decode.uses_rd & |decode.rd_addr; + + //Revert physcial address assignment on a flush + assign rollback = gc_fetch_flush & issue.stage_valid & issue.uses_rd & |issue.rd_addr; + + //counter for indexing through memories for post-reset clearing/initialization + initial clear_index = 0; + always_ff @ (posedge clk) begin + if (rst) + clear_index <= 0; + else + clear_index <= clear_index + 6'(gc_init_clear); + end + //////////////////////////////////////////////////// + //Free list FIFO + register_free_list #(.DATA_WIDTH(6), .FIFO_DEPTH(32)) free_list_fifo ( + .clk (clk), + .rst (rst), + .fifo (free_list), + .rollback (rollback) + ); + + //During post reset init, initialize FIFO with free list (registers 32-63) + assign free_list.potential_push = (gc_init_clear & ~clear_index[5]) | (retire.valid & |retire.rd_addr); + assign free_list.push = free_list.potential_push; + //TODO: restore spec if instruction has been discarded due to a speculation failure + assign free_list.data_in = gc_init_clear ? {1'b1, clear_index[4:0]} : architectural_id_to_phys_table[retire.phys_id]; + assign free_list.pop = rename_valid; + + //////////////////////////////////////////////////// + //Speculative rd-to-phys Table + //On rollback restore the previous contents + //During post reset init, initialize rd_to_phys with in-use list (lower 32 registers) + logic spec_table_update; + logic [4:0] spec_table_write_index; + logic [5:0] spec_table_write_data; + logic [$clog2(NUM_WB_GROUPS)-1:0] spec_table_wb_group_data; + + assign spec_table_update = rename_valid | rollback | gc_init_clear; + + always_comb begin + if (gc_init_clear) begin + spec_table_write_index = clear_index[4:0]; + spec_table_write_data = {1'b0, clear_index[4:0]}; + spec_table_wb_group_data = '0; + end + else if (rollback) begin + spec_table_write_index = issue.rd_addr; + spec_table_write_data = rollback_phys_addr; + spec_table_wb_group_data = rollback_wb_group; + end + else begin + spec_table_write_index = decode.rd_addr; + spec_table_write_data = free_list.data_out; + spec_table_wb_group_data = decode.rd_wb_group; + end + end + + always_ff @ (posedge clk) begin + if (spec_table_update) begin + speculative_rd_to_phys_table[spec_table_write_index] <= spec_table_write_data; + rollback_phys_addr <= speculative_rd_to_phys_table[spec_table_write_index]; + end + end + + //WB group + always_ff @ (posedge clk) begin + if (spec_table_update) begin + spec_wb_group[spec_table_write_index] <= spec_table_wb_group_data; + rollback_wb_group <= spec_wb_group[spec_table_write_index]; + end + end + + //////////////////////////////////////////////////// + //Arch ID-to-phys Table + always_ff @ (posedge clk) begin + if (rename_valid) + architectural_id_to_phys_table[decode.id] <= speculative_rd_to_phys_table[spec_table_write_index]; + end + + //////////////////////////////////////////////////// + //Renamed Outputs + always_comb begin + for (int i = 0; i < REGFILE_READ_PORTS; i++) begin + decode.phys_rs_addr[i] = speculative_rd_to_phys_table[decode.rs_addr[i]]; + decode.rs_wb_group[i] = spec_wb_group[decode.rs_addr[i]]; + end + end + + assign decode.phys_rd_addr = rename_valid ? free_list.data_out : '0; + //////////////////////////////////////////////////// + //End of Implementation + //////////////////////////////////////////////////// + + //////////////////////////////////////////////////// + //Assertions + rename_rd_zero_assertion: + assert property (@(posedge clk) disable iff (rst) (decode.rd_addr == 0) |-> (decode.phys_rd_addr == 0)) else $error("rd zero renamed"); + + for (genvar i = 0; i < REGFILE_READ_PORTS; i++) begin : rename_rs_zero_assertion + assert property (@(posedge clk) disable iff (rst) (decode.rs_addr[i] == 0) |-> (decode.phys_rs_addr[i] == 0)) else $error("rs zero renamed"); + end + +endmodule diff --git a/core/store_queue.sv b/core/store_queue.sv index fe73a15..b41bef4 100644 --- a/core/store_queue.sv +++ b/core/store_queue.sv @@ -51,9 +51,9 @@ module store_queue # ( //Writeback snooping input wb_packet_t wb_snoop, - //Writeback release - input id_t ids_released [COMMIT_PORTS], - input wb_released [COMMIT_PORTS], + //Retire + input id_t retire_ids [RETIRE_PORTS], + input logic retire_ids_retired [RETIRE_PORTS], //lsq output output sq_entry_t sq_entry, @@ -208,11 +208,13 @@ module store_queue # ( //////////////////////////////////////////////////// //Release Handling //Can be released on the same cycle the store arrives at the store queue + //TODO: change to toggle memory logic [DEPTH-1:0] newly_released; always_comb begin for (int i = 0; i < DEPTH; i++) begin - for (int j = 0; j < COMMIT_PORTS; j++) begin - newly_released[i] = (ids[i] == ids_released[j]) & wb_released[j]; + newly_released[i] = 0; + for (int j = 0; j < RETIRE_PORTS; j++) begin + newly_released[i] |= (ids[i] == retire_ids[j]) & retire_ids_retired[j]; end end end diff --git a/core/taiga.sv b/core/taiga.sv index 4d05822..2901f99 100755 --- a/core/taiga.sv +++ b/core/taiga.sv @@ -58,7 +58,7 @@ module taiga ( ras_interface ras(); issue_packet_t issue; - logic [31:0] rs_data [REGFILE_READ_PORTS]; + register_file_issue_interface rf_issue(); alu_inputs_t alu_inputs; @@ -69,7 +69,6 @@ module taiga ( gc_inputs_t gc_inputs; unit_issue_interface unit_issue [NUM_UNITS-1:0](); - logic alu_issued; exception_packet_t ls_exception; logic ls_exception_is_store; @@ -99,28 +98,27 @@ module taiga ( fetch_metadata_t fetch_metadata; //Decode stage logic decode_advance; - decode_packet_t decode; - //Issue stage - id_t rs_id [REGFILE_READ_PORTS]; - logic rs_inuse [REGFILE_READ_PORTS]; - logic rs_id_inuse [REGFILE_READ_PORTS]; + decode_packet_t decode; + logic decode_uses_rd; + rs_addr_t decode_rd_addr; + phys_addr_t decode_phys_rd_addr; //Branch predictor + id_t branch_id; 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_or_exception_complete; - logic exception_with_rd_complete; - id_t system_op_or_exception_id; - logic instruction_retired; - logic [$clog2(MAX_COMPLETE_COUNT)-1:0] retire_inc; - //Exception + retire_packet_t retire; + id_t retire_ids [RETIRE_PORTS]; + logic retire_ids_retired [RETIRE_PORTS]; + //Writeback + wb_packet_t wb_packet [NUM_WB_GROUPS]; + commit_packet_t commit_packet [NUM_WB_GROUPS]; + //Exception id_t exception_id; logic [31:0] exception_pc; + renamer_interface decode_rename_interface (); + //Global Control logic gc_init_clear; logic gc_fetch_hold; @@ -142,12 +140,6 @@ module taiga ( //LS wb_packet_t wb_snoop; - //WB - id_t ids_retiring [COMMIT_PORTS]; - logic retired [COMMIT_PORTS]; - logic [4:0] retired_rd_addr [COMMIT_PORTS]; - id_t id_for_rd [COMMIT_PORTS]; - //Trace Interface Signals logic tr_early_branch_correction; logic tr_operand_stall; @@ -195,13 +187,13 @@ module taiga ( generate if (ENABLE_S_MODE || USE_ICACHE || USE_DCACHE) l1_arbiter arb( - .clk (clk), - .rst (rst), - .l2 (l2), - .sc_complete (sc_complete), - .sc_success (sc_success), - .l1_request (l1_request), - .l1_response (l1_response) + .clk (clk), + .rst (rst), + .l2 (l2), + .sc_complete (sc_complete), + .sc_success (sc_success), + .l1_request (l1_request), + .l1_response (l1_response) ); endgenerate @@ -209,109 +201,105 @@ module taiga ( //////////////////////////////////////////////////// // ID support instruction_metadata_and_id_management id_block ( - .clk (clk), - .rst (rst), - .gc_init_clear (gc_init_clear), - .gc_fetch_flush (gc_fetch_flush), - .pc_id (pc_id), - .pc_id_available (pc_id_available), - .if_pc (if_pc), - .pc_id_assigned (pc_id_assigned), - .fetch_id (fetch_id), + .clk (clk), + .rst (rst), + .gc_init_clear (gc_init_clear), + .gc_fetch_flush (gc_fetch_flush), + .pc_id (pc_id), + .pc_id_available (pc_id_available), + .if_pc (if_pc), + .pc_id_assigned (pc_id_assigned), + .fetch_id (fetch_id), .early_branch_flush (early_branch_flush), - .fetch_complete (fetch_complete), - .fetch_instruction (fetch_instruction), - .fetch_metadata (fetch_metadata), - .decode (decode), - .decode_advance (decode_advance), - .issue (issue), - .instruction_issued (instruction_issued), - .rs_id (rs_id), - .rs_inuse (rs_inuse), - .rs_id_inuse (rs_id_inuse), - .branch_metadata_if (branch_metadata_if), - .branch_metadata_ex (branch_metadata_ex), - .store_complete (store_complete), - .store_id (store_id), - .branch_complete (branch_complete), - .branch_id (branch_id), - .system_op_or_exception_complete (system_op_or_exception_complete), - .exception_with_rd_complete (exception_with_rd_complete), - .system_op_or_exception_id (system_op_or_exception_id), - .retire_inc (retire_inc), - .ids_retiring (ids_retiring), - .retired (retired), - .retired_rd_addr (retired_rd_addr), - .id_for_rd (id_for_rd), - .exception_pc (exception_pc) + .fetch_complete (fetch_complete), + .fetch_instruction (fetch_instruction), + .fetch_metadata (fetch_metadata), + .decode (decode), + .decode_advance (decode_advance), + .decode_uses_rd (decode_uses_rd), + .decode_rd_addr (decode_rd_addr), + .decode_phys_rd_addr (decode_phys_rd_addr), + .issue (issue), + .instruction_issued (instruction_issued), + .instruction_issued_with_rd (instruction_issued_with_rd), + .branch_metadata_if (branch_metadata_if), + .branch_metadata_ex (branch_metadata_ex), + .branch_id (branch_id), + .wb_packet (wb_packet), + .commit_packet (commit_packet), + .retire (retire), + .retire_ids (retire_ids), + .retire_ids_retired(retire_ids_retired), + .exception_id (exception_id), + .exception_pc (exception_pc) ); //////////////////////////////////////////////////// // Fetch fetch fetch_block ( - .clk (clk), - .rst (rst), - .branch_flush (branch_flush), - .gc_fetch_hold (gc_fetch_hold), - .gc_fetch_flush (gc_fetch_flush), - .gc_fetch_pc_override (gc_fetch_pc_override), - .gc_fetch_pc (gc_fetch_pc), - .pc_id_available (pc_id_available), - .pc_id_assigned (pc_id_assigned), - .fetch_complete (fetch_complete), - .fetch_metadata (fetch_metadata), - .bp (bp), - .ras (ras), + .clk (clk), + .rst (rst), + .branch_flush (branch_flush), + .gc_fetch_hold (gc_fetch_hold), + .gc_fetch_flush (gc_fetch_flush), + .gc_fetch_pc_override (gc_fetch_pc_override), + .gc_fetch_pc (gc_fetch_pc), + .pc_id_available (pc_id_available), + .pc_id_assigned (pc_id_assigned), + .fetch_complete (fetch_complete), + .fetch_metadata (fetch_metadata), + .bp (bp), + .ras (ras), .early_branch_flush (early_branch_flush), .early_branch_flush_ras_adjust (early_branch_flush_ras_adjust), - .if_pc (if_pc), - .fetch_instruction (fetch_instruction), - .instruction_bram (instruction_bram), - .icache_on('1), - .tlb(itlb), - .tlb_on (tlb_on), - .l1_request(l1_request[L1_ICACHE_ID]), - .l1_response(l1_response[L1_ICACHE_ID]), - .exception(1'b0), + .if_pc (if_pc), + .fetch_instruction (fetch_instruction), + .instruction_bram (instruction_bram), + .icache_on ('1), + .tlb (itlb), + .tlb_on (tlb_on), + .l1_request (l1_request[L1_ICACHE_ID]), + .l1_response (l1_response[L1_ICACHE_ID]), + .exception (1'b0), .tr_early_branch_correction (tr_early_branch_correction) ); branch_predictor bp_block ( - .clk (clk), - .rst (rst), - .bp (bp), - .branch_metadata_if (branch_metadata_if), - .branch_metadata_ex (branch_metadata_ex), - .br_results (br_results) + .clk (clk), + .rst (rst), + .bp (bp), + .branch_metadata_if (branch_metadata_if), + .branch_metadata_ex (branch_metadata_ex), + .br_results (br_results) ); ras ras_block( - .clk (clk), - .rst (rst), - .gc_fetch_flush (gc_fetch_flush), + .clk (clk), + .rst (rst), + .gc_fetch_flush (gc_fetch_flush), .early_branch_flush_ras_adjust (early_branch_flush_ras_adjust), - .ras (ras) + .ras (ras) ); generate if (ENABLE_S_MODE) begin tlb_lut_ram #(ITLB_WAYS, ITLB_DEPTH) i_tlb ( - .clk (clk), - .rst (rst), - .abort_request (gc_fetch_flush | early_branch_flush), + .clk (clk), + .rst (rst), + .abort_request (gc_fetch_flush | early_branch_flush), .gc_tlb_flush (gc_tlb_flush), - .asid (asid), - .tlb (itlb), - .mmu (immu) + .asid (asid), + .tlb (itlb), + .mmu (immu) ); mmu i_mmu ( - .clk (clk), - .rst (rst), - .mmu (immu) , + .clk (clk), + .rst (rst), + .mmu (immu) , .abort_request (gc_fetch_flush), - .l1_request (l1_request[L1_IMMU_ID]), - .l1_response (l1_response[L1_IMMU_ID]) + .l1_request (l1_request[L1_IMMU_ID]), + .l1_response (l1_response[L1_IMMU_ID]) ); end @@ -323,155 +311,155 @@ module taiga ( endgenerate //////////////////////////////////////////////////// - //Decode/Issue - decode_and_issue decode_and_issue_block ( - .clk (clk), - .rst (rst), - .pc_id_available (pc_id_available), - .decode (decode), - .decode_advance (decode_advance), - .issue (issue), - .rs_data (rs_data), - .alu_inputs (alu_inputs), - .ls_inputs (ls_inputs), - .branch_inputs (branch_inputs), - .gc_inputs (gc_inputs), - .mul_inputs (mul_inputs), - .div_inputs (div_inputs), - .unit_issue (unit_issue), - .potential_branch_exception (potential_branch_exception), - .alu_issued (alu_issued), - .gc_fetch_hold (gc_fetch_hold), - .gc_issue_hold (gc_issue_hold), - .gc_fetch_flush (gc_fetch_flush), - .gc_issue_flush (gc_issue_flush), - .gc_flush_required (gc_flush_required), - .rs_inuse (rs_inuse), - .rs_id (rs_id), - .rs_id_inuse (rs_id_inuse), - .instruction_issued (instruction_issued), - .instruction_issued_with_rd (instruction_issued_with_rd), - .illegal_instruction (illegal_instruction), - .tr_operand_stall (tr_operand_stall), - .tr_unit_stall (tr_unit_stall), - .tr_no_id_stall (tr_no_id_stall), - .tr_no_instruction_stall (tr_no_instruction_stall), - .tr_other_stall (tr_other_stall), - .tr_branch_operand_stall (tr_branch_operand_stall), - .tr_alu_operand_stall (tr_alu_operand_stall), - .tr_ls_operand_stall (tr_ls_operand_stall), - .tr_div_operand_stall (tr_div_operand_stall), - .tr_alu_op (tr_alu_op), - .tr_branch_or_jump_op (tr_branch_or_jump_op), - .tr_load_op (tr_load_op), - .tr_store_op (tr_store_op), - .tr_mul_op (tr_mul_op), - .tr_div_op (tr_div_op), - .tr_misc_op (tr_misc_op), - .tr_instruction_issued_dec (tr_instruction_issued_dec), - .tr_instruction_pc_dec (tr_instruction_pc_dec), - .tr_instruction_data_dec (tr_instruction_data_dec) + //Renamer + renamer renamer_block ( + .clk (clk), + .rst (rst), + .gc_init_clear (gc_init_clear), + .gc_fetch_flush (gc_fetch_flush), + .decode_advance (decode_advance), + .decode (decode_rename_interface), + .issue (issue), //packet + .retire (retire) //packet ); //////////////////////////////////////////////////// - //Register File and Writeback - register_file_and_writeback register_file_and_writeback_block ( - .clk (clk), - .rst (rst), - .issue (issue), + //Decode/Issue + decode_and_issue decode_and_issue_block ( + .clk (clk), + .rst (rst), + .pc_id_available (pc_id_available), + .decode (decode), + .decode_advance (decode_advance), + .renamer (decode_rename_interface), + .decode_uses_rd (decode_uses_rd), + .decode_rd_addr (decode_rd_addr), + .decode_phys_rd_addr (decode_phys_rd_addr), + .instruction_issued (instruction_issued), .instruction_issued_with_rd (instruction_issued_with_rd), - .alu_issued (alu_issued), - .rs_data (rs_data), - .ids_retiring (ids_retiring), - .retired (retired), - .retired_rd_addr (retired_rd_addr), - .id_for_rd (id_for_rd), - .unit_wb (unit_wb), - .wb_snoop (wb_snoop), - .tr_rs1_forwarding_needed (tr_rs1_forwarding_needed), - .tr_rs2_forwarding_needed (tr_rs2_forwarding_needed), - .tr_rs1_and_rs2_forwarding_needed (tr_rs1_and_rs2_forwarding_needed) + .issue (issue), + .rf (rf_issue), + .alu_inputs (alu_inputs), + .ls_inputs (ls_inputs), + .branch_inputs (branch_inputs), + .gc_inputs (gc_inputs), + .mul_inputs (mul_inputs), + .div_inputs (div_inputs), + .unit_issue (unit_issue), + .gc_fetch_hold (gc_fetch_hold), + .gc_issue_hold (gc_issue_hold), + .gc_fetch_flush (gc_fetch_flush), + .gc_issue_flush (gc_issue_flush), + .gc_flush_required (gc_flush_required), + .illegal_instruction (illegal_instruction), + .tr_operand_stall (tr_operand_stall), + .tr_unit_stall (tr_unit_stall), + .tr_no_id_stall (tr_no_id_stall), + .tr_no_instruction_stall (tr_no_instruction_stall), + .tr_other_stall (tr_other_stall), + .tr_branch_operand_stall (tr_branch_operand_stall), + .tr_alu_operand_stall (tr_alu_operand_stall), + .tr_ls_operand_stall (tr_ls_operand_stall), + .tr_div_operand_stall (tr_div_operand_stall), + .tr_alu_op (tr_alu_op), + .tr_branch_or_jump_op (tr_branch_or_jump_op), + .tr_load_op (tr_load_op), + .tr_store_op (tr_store_op), + .tr_mul_op (tr_mul_op), + .tr_div_op (tr_div_op), + .tr_misc_op (tr_misc_op), + .tr_instruction_issued_dec (tr_instruction_issued_dec), + .tr_instruction_pc_dec (tr_instruction_pc_dec), + .tr_instruction_data_dec (tr_instruction_data_dec) + ); + + //////////////////////////////////////////////////// + //Register File + register_file register_file_block ( + .clk (clk), + .rst (rst), + .gc_init_clear (gc_init_clear), + .rf_issue (rf_issue), + .commit (commit_packet) ); //////////////////////////////////////////////////// //Execution Units branch_unit branch_unit_block ( - .clk (clk ), - .rst (rst ), - .issue (unit_issue[BRANCH_UNIT_ID]), - .branch_inputs (branch_inputs ), - .br_results (br_results ), - .ras (ras ), - .branch_flush (branch_flush ), - .branch_complete (branch_complete ), - .branch_id (branch_id ), - .branch_metadata_ex (branch_metadata_ex ), - .potential_branch_exception (potential_branch_exception), - .branch_exception_is_jump (branch_exception_is_jump ), - .br_exception (br_exception ), - .tr_branch_correct (tr_branch_correct ), - .tr_branch_misspredict (tr_branch_misspredict ), - .tr_return_correct (tr_return_correct ), - .tr_return_misspredict (tr_return_misspredict ) + .clk (clk), + .rst (rst), + .issue (unit_issue[BRANCH_UNIT_ID]), + .branch_inputs (branch_inputs), + .br_results (br_results), + .ras (ras), + .branch_flush (branch_flush), + .branch_id (branch_id), + .branch_metadata_ex (branch_metadata_ex), + .potential_branch_exception (potential_branch_exception), + .branch_exception_is_jump (branch_exception_is_jump), + .br_exception (br_exception), + .tr_branch_correct (tr_branch_correct), + .tr_branch_misspredict (tr_branch_misspredict), + .tr_return_correct (tr_return_correct), + .tr_return_misspredict (tr_return_misspredict) ); alu_unit alu_unit_block ( - .clk (clk), - .rst (rst), - .alu_inputs (alu_inputs), - .issue (unit_issue[ALU_UNIT_ID]), - .wb (unit_wb[ALU_UNIT_ID]) + .clk (clk), + .rst (rst), + .alu_inputs (alu_inputs), + .issue (unit_issue[ALU_UNIT_ID]), + .wb (unit_wb[ALU_UNIT_ID]) ); load_store_unit load_store_unit_block ( - .clk (clk), - .rst (rst), - .ls_inputs (ls_inputs), - .issue (unit_issue[LS_UNIT_ID]), - .dcache_on (1'b1), - .clear_reservation (1'b0), - .tlb (dtlb), - .gc_fetch_flush (gc_fetch_flush), - .gc_issue_flush (gc_issue_flush), - .tlb_on (tlb_on), - .l1_request (l1_request[L1_DCACHE_ID]), - .l1_response (l1_response[L1_DCACHE_ID]), - .sc_complete (sc_complete), - .sc_success (sc_success), - .m_axi (m_axi), - .m_avalon (m_avalon), - .m_wishbone (m_wishbone), - .data_bram (data_bram), - .store_complete (store_complete), - .store_id (store_id), - .wb_snoop (wb_snoop), - .ls_is_idle (ls_is_idle), - .ls_exception (ls_exception), - .ls_exception_is_store (ls_exception_is_store), - .wb (unit_wb[LS_UNIT_ID]), - .tr_load_conflict_delay (tr_load_conflict_delay) + .clk (clk), + .rst (rst), + .ls_inputs (ls_inputs), + .issue (unit_issue[LS_UNIT_ID]), + .dcache_on (1'b1), + .clear_reservation (1'b0), + .tlb (dtlb), + .gc_fetch_flush (gc_fetch_flush), + .gc_issue_flush (gc_issue_flush), + .tlb_on (tlb_on), + .l1_request (l1_request[L1_DCACHE_ID]), + .l1_response (l1_response[L1_DCACHE_ID]), + .sc_complete (sc_complete), + .sc_success (sc_success), + .m_axi (m_axi), + .m_avalon (m_avalon), + .m_wishbone (m_wishbone), + .data_bram (data_bram), + .wb_snoop (wb_snoop), + .retire_ids (retire_ids), + .retire_ids_retired(retire_ids_retired), + .ls_is_idle (ls_is_idle), + .ls_exception (ls_exception), + .ls_exception_is_store (ls_exception_is_store), + .wb (unit_wb[LS_UNIT_ID]), + .tr_load_conflict_delay (tr_load_conflict_delay) ); generate if (ENABLE_S_MODE) begin - tlb_lut_ram #(DTLB_WAYS, DTLB_DEPTH) d_tlb ( - .clk (clk), - .rst (rst), - .abort_request (1'b0), + .clk (clk), + .rst (rst), + .abort_request (1'b0), .gc_tlb_flush (gc_tlb_flush), - .asid (asid), - .tlb (dtlb), - .mmu (dmmu) + .asid (asid), + .tlb (dtlb), + .mmu (dmmu) ); mmu d_mmu ( - .clk (clk), - .rst (rst), - .mmu (dmmu) , + .clk (clk), + .rst (rst), + .mmu (dmmu) , .abort_request (1'b0), - .l1_request (l1_request[L1_DMMU_ID]), - .l1_response (l1_response[L1_DMMU_ID]) + .l1_request (l1_request[L1_DMMU_ID]), + .l1_response (l1_response[L1_DMMU_ID]) ); end else begin @@ -480,69 +468,73 @@ module taiga ( assign dtlb.physical_address = dtlb.virtual_address; end endgenerate + gc_unit gc_unit_block ( - .clk (clk), - .rst (rst), - .issue (unit_issue[GC_UNIT_ID]), - .gc_inputs (gc_inputs), - .gc_flush_required (gc_flush_required), - .branch_flush (branch_flush), - .potential_branch_exception (potential_branch_exception), - .branch_exception_is_jump (branch_exception_is_jump), - .br_exception (br_exception), - .illegal_instruction (illegal_instruction), - .ls_exception (ls_exception), - .ls_exception_is_store (ls_exception_is_store), - .tlb_on (tlb_on), - .asid (asid), - .immu (immu), - .dmmu (dmmu), - .system_op_or_exception_complete (system_op_or_exception_complete), - .exception_with_rd_complete (exception_with_rd_complete), - .system_op_or_exception_id (system_op_or_exception_id), - .exception_pc (exception_pc), - .retire_inc (retire_inc), - .instruction_retired (instruction_retired), - .interrupt (interrupt), - .timer_interrupt (timer_interrupt), - .gc_init_clear (gc_init_clear), - .gc_fetch_hold (gc_fetch_hold), - .gc_issue_hold (gc_issue_hold), - .gc_issue_flush (gc_issue_flush), - .gc_fetch_flush (gc_fetch_flush), - .gc_fetch_pc_override (gc_fetch_pc_override), - .gc_supress_writeback (gc_supress_writeback), - .gc_tlb_flush (gc_tlb_flush), - .gc_fetch_pc (gc_fetch_pc), - .ls_is_idle (ls_is_idle), + .clk (clk), + .rst (rst), + .issue (unit_issue[GC_UNIT_ID]), + .gc_inputs (gc_inputs), + .gc_flush_required (gc_flush_required), + .branch_flush (branch_flush), + .potential_branch_exception (potential_branch_exception), + .branch_exception_is_jump (branch_exception_is_jump), + .br_exception (br_exception), + .illegal_instruction (illegal_instruction), + .ls_exception (ls_exception), + .ls_exception_is_store (ls_exception_is_store), + .tlb_on (tlb_on), + .asid (asid), + .immu (immu), + .dmmu (dmmu), + .exception_id (exception_id), + .exception_pc (exception_pc), + .retire (retire), + .interrupt (interrupt), + .timer_interrupt (timer_interrupt), + .gc_init_clear (gc_init_clear), + .gc_fetch_hold (gc_fetch_hold), + .gc_issue_hold (gc_issue_hold), + .gc_issue_flush (gc_issue_flush), + .gc_fetch_flush (gc_fetch_flush), + .gc_fetch_pc_override (gc_fetch_pc_override), + .gc_supress_writeback (gc_supress_writeback), + .gc_tlb_flush (gc_tlb_flush), + .gc_fetch_pc (gc_fetch_pc), + .ls_is_idle (ls_is_idle), .wb (unit_wb[GC_UNIT_ID]) ); generate if (USE_MUL) - mul_unit mul_unit_block (.*, - .clk (clk), - .rst (rst), - .mul_inputs (mul_inputs), - .issue (unit_issue[MUL_UNIT_ID]), - .wb (unit_wb[MUL_UNIT_ID]) + .clk (clk), + .rst (rst), + .mul_inputs (mul_inputs), + .issue (unit_issue[MUL_UNIT_ID]), + .wb (unit_wb[MUL_UNIT_ID]) ); - endgenerate generate if (USE_DIV) - div_unit div_unit_block ( - .clk (clk), - .rst (rst), - .gc_fetch_flush (gc_fetch_flush), - .div_inputs (div_inputs), - .issue (unit_issue[DIV_UNIT_ID]), - .wb (unit_wb[DIV_UNIT_ID]) + .clk (clk), + .rst (rst), + .gc_fetch_flush (gc_fetch_flush), + .div_inputs (div_inputs), + .issue (unit_issue[DIV_UNIT_ID]), + .wb (unit_wb[DIV_UNIT_ID]) ); - endgenerate + //////////////////////////////////////////////////// + //Writeback + writeback writeback_block ( + .clk (clk), + .rst (rst), + .wb_packet (wb_packet), + .unit_wb (unit_wb), + .wb_snoop (wb_snoop) + ); + //////////////////////////////////////////////////// //End of Implementation //////////////////////////////////////////////////// diff --git a/core/taiga_config.sv b/core/taiga_config.sv index 6389c63..3749a79 100755 --- a/core/taiga_config.sv +++ b/core/taiga_config.sv @@ -155,12 +155,12 @@ package taiga_config; //////////////////////////////////////////////////// //ID limit //MAX_IDS restricted to a power of 2 - localparam MAX_IDS = 8; //8 sufficient for rv32im configs + localparam MAX_IDS = 16; //8 sufficient for rv32im configs //////////////////////////////////////////////////// //Number of commit ports - localparam COMMIT_PORTS = 2; //min 2 - localparam REGFILE_READ_PORTS = 2; //min 2, for RS1 and RS2 + localparam RETIRE_PORTS = 2; //min 2. (Non-powers of two supported) + localparam REGFILE_READ_PORTS = 2; //min 2, for RS1 and RS2. (Non-powers of two supported) typedef enum logic { RS1 = 0, RS2 = 1 @@ -180,7 +180,6 @@ package taiga_config; localparam L1_ICACHE_ID = 2;//ENABLE_S_MODE + USE_DCACHE; localparam L1_IMMU_ID = 3;//ENABLE_S_MODE + USE_DCACHE + USE_ICACHE; - //////////////////////////////////////////////////// //Write-Back Unit IDs localparam NUM_WB_UNITS_GROUP_1 = 1;//ALU diff --git a/core/taiga_types.sv b/core/taiga_types.sv index 34a62d4..b94aa4d 100755 --- a/core/taiga_types.sv +++ b/core/taiga_types.sv @@ -24,10 +24,9 @@ package taiga_types; import taiga_config::*; import riscv_types::*; - localparam MAX_COMPLETE_COUNT = 3 + COMMIT_PORTS; //Branch + Store + System + COMMIT_PORTS - + localparam RETIRE_W = $clog2(RETIRE_PORTS); localparam WB_UNITS_WIDTH = $clog2(NUM_WB_UNITS); - localparam LOG2_COMMIT_PORTS = $clog2(COMMIT_PORTS); + localparam LOG2_COMMIT_PORTS = $clog2(NUM_WB_GROUPS); localparam LOG2_MAX_IDS = $clog2(MAX_IDS); typedef logic[LOG2_MAX_IDS-1:0] id_t; @@ -36,6 +35,7 @@ package taiga_types; typedef logic [3:0] addr_hash_t; typedef logic [5:0] phys_addr_t; + typedef logic [$clog2(NUM_WB_GROUPS)-1:0] rs_wb_group_t; typedef enum logic [1:0] { ALU_LOGIC_XOR = 2'b00, @@ -102,9 +102,12 @@ package taiga_types; logic [6:0] opcode; rs_addr_t [REGFILE_READ_PORTS-1:0] rs_addr; - phys_addr_t [REGFILE_READ_PORTS-1:0] rs_phys_addr; + phys_addr_t [REGFILE_READ_PORTS-1:0] phys_rs_addr; + rs_wb_group_t [REGFILE_READ_PORTS-1:0] rs_wb_group; - logic [4:0] rd_addr; + rs_addr_t rd_addr; + phys_addr_t phys_rd_addr; + rs_wb_group_t rd_wb_group; logic uses_rs1; logic uses_rs2; @@ -234,12 +237,27 @@ package taiga_types; logic forwarded_store; } sq_entry_t; - typedef struct packed { - logic [31:0] data; + typedef struct packed{ id_t id; logic valid; + logic [31:0] data; } wb_packet_t; + typedef struct packed{ + id_t id; + logic valid; + phys_addr_t phys_addr; + logic [31:0] data; + } commit_packet_t; + + typedef struct packed{ + logic valid; + id_t phys_id; + phys_addr_t phys_addr; + rs_addr_t rd_addr; + logic [RETIRE_W : 0] count; + } retire_packet_t; + typedef struct packed { logic [31:0] addr; logic load; diff --git a/core/register_file_and_writeback.sv b/core/writeback.sv old mode 100755 new mode 100644 similarity index 52% rename from core/register_file_and_writeback.sv rename to core/writeback.sv index 01419d4..6a6a7d7 --- a/core/register_file_and_writeback.sv +++ b/core/writeback.sv @@ -20,55 +20,31 @@ * Eric Matthews */ -module register_file_and_writeback +module writeback import taiga_config::*; import riscv_types::*; import taiga_types::*; ( input logic clk, input logic rst, - - //Issue interface - input issue_packet_t issue, - input logic instruction_issued_with_rd, - input logic alu_issued, - output logic [31:0] rs_data [REGFILE_READ_PORTS], - //ID Metadata - output id_t ids_retiring [COMMIT_PORTS], - output logic retired [COMMIT_PORTS], - input logic [4:0] retired_rd_addr [COMMIT_PORTS], - input id_t id_for_rd [COMMIT_PORTS], - //Writeback + //Unit writeback unit_writeback_interface.wb unit_wb[NUM_WB_UNITS], - output wb_packet_t wb_snoop, - - //Trace signals - output logic tr_rs1_forwarding_needed, - output logic tr_rs2_forwarding_needed, - output logic tr_rs1_and_rs2_forwarding_needed + //WB output + output wb_packet_t wb_packet [NUM_WB_GROUPS], + //Snoop interface (LS unit) + output wb_packet_t wb_snoop ); - //Register File - typedef logic [XLEN-1:0] register_file_t [32]; - register_file_t register_file [COMMIT_PORTS]; - logic [LOG2_COMMIT_PORTS-1:0] rs_sel [REGFILE_READ_PORTS]; - //Writeback - logic alu_selected; logic [NUM_WB_UNITS-1:0] unit_ack [NUM_WB_GROUPS]; //aliases for write-back-interface signals id_t [NUM_WB_UNITS-1:0] unit_instruction_id [NUM_WB_GROUPS]; logic [NUM_WB_UNITS-1:0] unit_done [NUM_WB_GROUPS]; - typedef logic [XLEN-1:0] unit_rd_t [NUM_WB_UNITS]; unit_rd_t unit_rd [NUM_WB_GROUPS]; //Per-ID muxes for commit buffer - logic [$clog2(NUM_WB_UNITS)-1:0] retiring_unit_select [NUM_WB_GROUPS]; - logic [31:0] retiring_data [NUM_WB_GROUPS]; - - typedef logic [31:0] rs_data_set_t [REGFILE_READ_PORTS]; - rs_data_set_t rs_data_set [NUM_WB_GROUPS]; + logic [$clog2(NUM_WB_UNITS)-1:0] unit_sel [NUM_WB_GROUPS]; genvar i, j; //////////////////////////////////////////////////// @@ -87,14 +63,13 @@ module register_file_and_writeback //As units are selected for commit ports based on their unit ID, //for each additional commit port one unit can be skipped for the commit mux generate - for (i = 0; i < NUM_WB_GROUPS; i++) begin : wb_rd_mux_gen + for (i = 0; i < NUM_WB_GROUPS; i++) begin for (j = 0; j < NUM_WB_UNITS_GROUP[i]; j++) begin assign unit_rd[i][j] = unit_wb[CUMULATIVE_NUM_WB_UNITS_GROUP[i] + j].rd; end end endgenerate - //////////////////////////////////////////////////// //Unit select for register file //Iterating through all commit ports: @@ -103,73 +78,37 @@ module register_file_and_writeback always_comb begin for (int i = 0; i < NUM_WB_GROUPS; i++) begin unit_ack[i] = '{default: 0}; - retired[i] = 0; - retiring_unit_select[i] = WB_UNITS_WIDTH'(NUM_WB_UNITS_GROUP[i]-1); + wb_packet[i].valid = 0; + unit_sel[i] = WB_UNITS_WIDTH'(NUM_WB_UNITS_GROUP[i]-1); for (int j = 0; j < (NUM_WB_UNITS_GROUP[i] - 1); j++) begin if (unit_done[i][j]) begin - retiring_unit_select[i] = WB_UNITS_WIDTH'(j); + unit_sel[i] = WB_UNITS_WIDTH'(j); break; end end //ID and data muxes - retired[i] = unit_done[i][retiring_unit_select[i]]; - ids_retiring[i] = unit_instruction_id[i][retiring_unit_select[i]]; - retiring_data[i] = unit_rd[i][retiring_unit_select[i]]; - unit_ack[i][retiring_unit_select[i]] = retired[i]; - end - - retired[0] = alu_issued; - unit_ack[0][retiring_unit_select[0]] = retired[0]; - - end - - //////////////////////////////////////////////////// - //Register Files - //Implemented in seperate module as there is not universal tool support for inferring - //arrays of memory blocks. - generate for (i = 0; i < COMMIT_PORTS; i++) begin - register_file #(.NUM_READ_PORTS(REGFILE_READ_PORTS)) register_file_blocks ( - .clk, .rst, - .write_addr({1'b0, retired_rd_addr[i]}), - .new_data(retiring_data[i]), - .commit(retired[i] & (|retired_rd_addr[i])), - .read_addr(issue.rs_phys_addr), - .data(rs_data_set[i]) - ); - end endgenerate - - //////////////////////////////////////////////////// - //Register File LVT - logic [$clog2(COMMIT_PORTS)-1:0] bank_sel [32]; - always_ff @ (posedge clk) begin - if (instruction_issued_with_rd) - bank_sel[issue.rd_addr] <= ~alu_issued; - end - always_comb begin - for (int i = 0; i < REGFILE_READ_PORTS; i++) begin - rs_sel[i] = bank_sel[issue.rs_addr[i]]; - end - end - - //////////////////////////////////////////////////// - //Register File Muxing - always_comb begin - for (int i = 0; i < REGFILE_READ_PORTS; i++) begin - rs_data[i] = rs_data_set[rs_sel[i]][i]; - end + wb_packet[i].valid = unit_done[i][unit_sel[i]]; + wb_packet[i].id = unit_instruction_id[i][unit_sel[i]]; + wb_packet[i].data = unit_rd[i][unit_sel[i]]; + unit_ack[i][unit_sel[i]] = wb_packet[i].valid; + end end //////////////////////////////////////////////////// //Store Forwarding Support + //TODO: support additional writeback groups + //currently limited to one writeback group with the + //assumption that writeback group zero has single-cycle + //operation always_ff @ (posedge clk) begin if (rst) wb_snoop.valid <= 0; else - wb_snoop.valid <= retired[1]; + wb_snoop.valid <= wb_packet[1].valid; end always_ff @ (posedge clk) begin - wb_snoop.data <= retiring_data[1]; - wb_snoop.id <= ids_retiring[1]; + wb_snoop.data <= wb_packet[1].data; + wb_snoop.id <= wb_packet[1].id; end //////////////////////////////////////////////////// diff --git a/tools/taiga_compile_order b/tools/taiga_compile_order index 234e679..48df009 100644 --- a/tools/taiga_compile_order +++ b/tools/taiga_compile_order @@ -88,9 +88,11 @@ core/fetch.sv core/illegal_instruction_checker.sv core/decode_and_issue.sv -core/regfile_bank_sel.sv +core/register_free_list.sv +core/renamer.sv +core/register_bank.sv core/register_file.sv -core/register_file_and_writeback.sv +core/writeback.sv core/placer_randomizer.sv