diff --git a/core/axi_to_arb.sv b/core/axi_to_arb.sv index 34d3587..25f075d 100755 --- a/core/axi_to_arb.sv +++ b/core/axi_to_arb.sv @@ -85,7 +85,7 @@ module axi_to_arb logic address_phase_complete; logic [31:0] amo_result; logic [31:0] amo_result_r; - logic [DCACHE_SUB_LINE_ADDR_W-1:0] read_count; + logic [$clog2(EXAMPLE_CONFIG.DCACHE.LINE_W)-1:0] read_count; logic amo_write_ready; logic[4:0] write_reference_burst_count; @@ -141,7 +141,7 @@ module axi_to_arb //TODO: assumption that all data caches have same line size, would have to update wrt the burst size to be safe if they have different line lengths //also update araddr always_ff @ (posedge clk) begin - if (axi_rvalid && (read_count == l2.addr[DCACHE_SUB_LINE_ADDR_W-1:0])) + if (axi_rvalid && (read_count == l2.addr[$clog2(EXAMPLE_CONFIG.DCACHE.LINE_W)-1:0])) amo_result_r <= amo_result; end @@ -150,7 +150,7 @@ module axi_to_arb amo_write_ready <= 0; else if (pop) amo_write_ready <= 0; - else if (l2.is_amo && axi_rvalid && read_count == l2.addr[DCACHE_SUB_LINE_ADDR_W-1:0]) + else if (l2.is_amo && axi_rvalid && read_count == l2.addr[$clog2(EXAMPLE_CONFIG.DCACHE.LINE_W)-1:0]) amo_write_ready <= 1; end //End AMO @@ -166,7 +166,7 @@ module axi_to_arb assign axi_arprot = '0; assign axi_arid = 6'(l2.id); - assign axi_araddr ={l2.addr[29:DCACHE_SUB_LINE_ADDR_W], {DCACHE_SUB_LINE_ADDR_W{1'b0}}, 2'b00}; + assign axi_araddr ={l2.addr[29:$clog2(EXAMPLE_CONFIG.DCACHE.LINE_W)], {$clog2(EXAMPLE_CONFIG.DCACHE.LINE_W){1'b0}}, 2'b00}; assign write_reference_burst_count = read_modify_write ? 0 : burst_count; diff --git a/core/branch_predictor.sv b/core/branch_predictor.sv index 285939c..92c9841 100755 --- a/core/branch_predictor.sv +++ b/core/branch_predictor.sv @@ -26,30 +26,33 @@ module branch_predictor import riscv_types::*; import taiga_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( 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 + input branch_results_t br_results, + ras_interface.branch_predictor ras ); //BP tag width can be reduced, based on memory size, when virtual address //support is not enabled - localparam longint CACHE_RANGE = 64'(MEMORY_ADDR_H) - 64'(MEMORY_ADDR_L) + 1; - localparam longint SCRATCH_RANGE = 64'(SCRATCH_ADDR_H) - 64'(SCRATCH_ADDR_L) + 1; + localparam longint CACHE_RANGE = 64'(CONFIG.ICACHE_ADDR.H) - 64'(CONFIG.ICACHE_ADDR.L) + 1; + localparam longint SCRATCH_RANGE = 64'(CONFIG.ILOCAL_MEM_ADDR.H) - 64'(CONFIG.ILOCAL_MEM_ADDR.L) + 1; function int get_memory_width(); - if(ENABLE_S_MODE) + if(CONFIG.INCLUDE_S_MODE) return 32; - else if (USE_ICACHE && CACHE_RANGE > SCRATCH_RANGE) + else if (CONFIG.INCLUDE_ICACHE && CACHE_RANGE > SCRATCH_RANGE) return $clog2(CACHE_RANGE); else return $clog2(SCRATCH_RANGE); endfunction - localparam BRANCH_ADDR_W = $clog2(BRANCH_TABLE_ENTRIES); + localparam BRANCH_ADDR_W = $clog2(CONFIG.BP.ENTRIES); localparam BTAG_W = get_memory_width() - BRANCH_ADDR_W - 2; function logic[BTAG_W-1:0] get_tag (input logic[31:0] pc); @@ -65,31 +68,39 @@ module branch_predictor branch_predictor_metadata_t metadata; } branch_table_entry_t; - - branch_table_entry_t [BRANCH_PREDICTOR_WAYS-1:0] if_entry; + branch_table_entry_t [CONFIG.BP.WAYS-1:0] if_entry; branch_table_entry_t ex_entry; + typedef struct packed{ + branch_predictor_metadata_t branch_predictor_metadata; + logic branch_prediction_used; + logic [CONFIG.BP.WAYS-1:0] branch_predictor_update_way; + } branch_metadata_t; + (* ramstyle = "MLAB, no_rw_check" *) logic [$bits(branch_metadata_t)-1:0] branch_metadata_table [MAX_IDS]; + branch_metadata_t branch_metadata_if; + branch_metadata_t branch_metadata_ex; + logic branch_predictor_direction_changed; logic [31:0] new_jump_addr; - logic [BRANCH_PREDICTOR_WAYS-1:0][31:0] predicted_pc; + logic [CONFIG.BP.WAYS-1:0][31:0] predicted_pc; - logic [BRANCH_PREDICTOR_WAYS-1:0] tag_matches; - logic [BRANCH_PREDICTOR_WAYS-1:0] replacement_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 [CONFIG.BP.WAYS-1:0] tag_matches; + logic [CONFIG.BP.WAYS-1:0] replacement_way; + logic [CONFIG.BP.WAYS-1:0] tag_update_way; + logic [CONFIG.BP.WAYS-1:0] target_update_way; + logic [$clog2(CONFIG.BP.WAYS > 1 ? CONFIG.BP.WAYS : 2)-1:0] hit_way; logic tag_match; logic use_predicted_pc; ///////////////////////////////////////// genvar i; - generate if (USE_BRANCH_PREDICTOR) - for (i=0; i 1) - one_hot_to_integer #(BRANCH_PREDICTOR_WAYS) hit_way_conv ( + generate if (CONFIG.BP.WAYS > 1) + one_hot_to_integer #(CONFIG.BP.WAYS) hit_way_conv ( .clk (clk), .rst (rst), .one_hot(tag_matches), @@ -134,7 +145,7 @@ module branch_predictor endgenerate assign tag_match = |tag_matches; - assign use_predicted_pc = USE_BRANCH_PREDICTOR & tag_match; + assign use_predicted_pc = CONFIG.INCLUDE_BRANCH_PREDICTOR & tag_match; //Predicted PC and whether the prediction is valid assign bp.predicted_pc = predicted_pc[hit_way]; @@ -143,13 +154,32 @@ module branch_predictor assign bp.is_return = if_entry[hit_way].is_return; assign bp.is_call = if_entry[hit_way].is_call; + //////////////////////////////////////////////////// + //Instruction Fetch metadata + cycler #(CONFIG.BP.WAYS) + replacement_policy ( + .clk (clk), + .rst (rst), + .en (1'b1), + .one_hot (replacement_way) + ); + 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; + + always_ff @ (posedge clk) begin + if (bp.pc_id_assigned) + branch_metadata_table[bp.pc_id] <= branch_metadata_if; + end + assign branch_metadata_ex = branch_metadata_table[br_results.id]; + //////////////////////////////////////////////////// //Execution stage update assign ex_entry.valid = 1; - assign ex_entry.tag = get_tag(br_results.pc_ex); - assign ex_entry.is_branch = br_results.is_branch_ex; - assign ex_entry.is_return = br_results.is_return_ex; - assign ex_entry.is_call = br_results.is_call_ex; + assign ex_entry.tag = get_tag(br_results.pc); + assign ex_entry.is_branch = br_results.is_branch; + assign ex_entry.is_return = br_results.is_return; + assign ex_entry.is_call = br_results.is_call; //2-bit saturating counter @@ -167,23 +197,14 @@ module branch_predictor (~branch_metadata_ex.branch_prediction_used) | (branch_metadata_ex.branch_predictor_metadata[1] ^ ex_entry.metadata[1]); - 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; + assign tag_update_way = {CONFIG.BP.WAYS{br_results.valid}} & (branch_metadata_ex.branch_predictor_update_way); + assign target_update_way = {CONFIG.BP.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.target_pc; //////////////////////////////////////////////////// - //Instruction Fetch metadata - cycler #(BRANCH_PREDICTOR_WAYS) replacement_policy ( - .clk (clk), - .rst (rst), - .en (1'b1), - .one_hot (replacement_way) - ); - - 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; + //RAS support + assign ras.branch_retired = br_results.valid & br_results.is_branch & branch_metadata_ex.branch_prediction_used; endmodule diff --git a/core/branch_unit.sv b/core/branch_unit.sv index bc317cf..1e3b1f3 100755 --- a/core/branch_unit.sv +++ b/core/branch_unit.sv @@ -26,6 +26,10 @@ module branch_unit import riscv_types::*; import taiga_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -33,12 +37,8 @@ module branch_unit unit_issue_interface.unit issue, input branch_inputs_t branch_inputs, output branch_results_t br_results, - ras_interface.branch_unit ras, output logic branch_flush, - output id_t branch_id, - input branch_metadata_t branch_metadata_ex, - output logic potential_branch_exception, output logic branch_exception_is_jump, output exception_packet_t br_exception, @@ -115,7 +115,7 @@ module branch_unit //Exception support id_t jmp_id; - generate if (ENABLE_M_MODE) begin + generate if (CONFIG.INCLUDE_M_MODE) begin always_ff @(posedge clk) begin if (issue.possible_issue) begin jmp_id <= issue.id; @@ -131,15 +131,6 @@ module branch_unit end endgenerate - //////////////////////////////////////////////////// - //ID Management - assign branch_complete = instruction_is_completing & (~jal_jalr_ex) & (~br_exception.valid); - assign branch_id = id_ex; - - //////////////////////////////////////////////////// - //RAS support - assign ras.branch_retired = branch_complete & branch_metadata_ex.branch_prediction_used; - //////////////////////////////////////////////////// //Predictor support logic is_return; @@ -152,13 +143,14 @@ module branch_unit end end - assign br_results.pc_ex = pc_ex; - assign br_results.new_pc = new_pc_ex; + assign br_results.id = id_ex; + assign br_results.valid = instruction_is_completing; + assign br_results.pc = pc_ex; + assign br_results.target_pc = new_pc_ex; assign br_results.branch_taken = branch_taken_ex; - assign br_results.branch_ex = instruction_is_completing; - assign br_results.is_branch_ex = ~jal_jalr_ex; - assign br_results.is_return_ex = is_return; - assign br_results.is_call_ex = is_call; + assign br_results.is_branch = ~jal_jalr_ex; + assign br_results.is_return = is_return; + assign br_results.is_call = is_call; assign branch_flush = instruction_is_completing && (branch_inputs.issue_pc[31:1] != new_pc_ex[31:1]); diff --git a/core/csr_regs.sv b/core/csr_regs.sv index 3b71ea3..5b80da3 100755 --- a/core/csr_regs.sv +++ b/core/csr_regs.sv @@ -27,6 +27,10 @@ module csr_regs import taiga_types::*; import csr_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -89,9 +93,9 @@ module csr_regs satp_t satp; - logic[COUNTER_W-1:0] mcycle; - logic[COUNTER_W-1:0] mtime; - logic[COUNTER_W-1:0] minst_ret; + logic[CONFIG.CSRS.COUNTER_W-1:0] mcycle; + logic[CONFIG.CSRS.COUNTER_W-1:0] mtime; + logic[CONFIG.CSRS.COUNTER_W-1:0] minst_ret; localparam INST_RET_INC_W = 2; logic [INST_RET_INC_W-1:0] inst_ret_inc; @@ -152,14 +156,14 @@ module csr_regs //////////////////////////////////////////////////// //Machine ISA register - const misa_t misa = '{default:0, mxlen:1, A:(USE_AMO), I:1, M:(USE_MUL && USE_DIV), S:(ENABLE_S_MODE), U:(ENABLE_U_MODE)}; + const misa_t misa = '{default:0, mxlen:1, A:(CONFIG.INCLUDE_AMO), I:1, M:(CONFIG.INCLUDE_MUL && CONFIG.INCLUDE_DIV), S:(CONFIG.INCLUDE_S_MODE), U:(CONFIG.INCLUDE_U_MODE)}; //////////////////////////////////////////////////// //Machine Version Registers const logic [XLEN-1:0] mvendorid = 0; const logic [XLEN-1:0] marchid = 0; - const logic [XLEN-1:0] mimpid = MACHINE_IMPLEMENTATION_ID; - const logic [XLEN-1:0] mhartid = CPU_ID; + const logic [XLEN-1:0] mimpid = CONFIG.CSRS.MACHINE_IMPLEMENTATION_ID; + const logic [XLEN-1:0] mhartid = CONFIG.CSRS.CPU_ID; //////////////////////////////////////////////////// //MSTATUS @@ -185,14 +189,14 @@ module csr_regs //Virtualization support: TSR, TW, TVM unused //Extension context status: SD, FS, XS unused const mstatus_t mstatus_mask = - '{default:0, mprv:(ENABLE_U_MODE | ENABLE_S_MODE), mxr:(ENABLE_S_MODE), - sum:(ENABLE_U_MODE & ENABLE_S_MODE), mpp:'1, spp:(ENABLE_S_MODE), - mpie:1, spie:(ENABLE_S_MODE), mie:1, sie:(ENABLE_S_MODE)}; + '{default:0, mprv:(CONFIG.INCLUDE_U_MODE | CONFIG.INCLUDE_S_MODE), mxr:(CONFIG.INCLUDE_S_MODE), + sum:(CONFIG.INCLUDE_U_MODE & CONFIG.INCLUDE_S_MODE), mpp:'1, spp:(CONFIG.INCLUDE_S_MODE), + mpie:1, spie:(CONFIG.INCLUDE_S_MODE), mie:1, sie:(CONFIG.INCLUDE_S_MODE)}; const mstatus_t sstatus_mask = '{default:0, mxr:1, sum:1, spp:1, spie:1, sie:1}; -generate if (ENABLE_M_MODE) begin +generate if (CONFIG.INCLUDE_M_MODE) begin privilege_t trap_return_privilege_level; privilege_t exception_privilege_level; @@ -207,7 +211,7 @@ generate if (ENABLE_M_MODE) begin always_comb begin exception_privilege_level = MACHINE_PRIVILEGE; interrupt_privilege_level = MACHINE_PRIVILEGE; - if (ENABLE_S_MODE && privilege_level inside {SUPERVISOR_PRIVILEGE, USER_PRIVILEGE}) begin + if (CONFIG.INCLUDE_S_MODE && privilege_level inside {SUPERVISOR_PRIVILEGE, USER_PRIVILEGE}) begin if (medeleg[gc_exception.code]) exception_privilege_level = SUPERVISOR_PRIVILEGE; if (mideleg[gc_exception.code]) @@ -265,7 +269,7 @@ generate if (ENABLE_M_MODE) begin end else if (mret) begin mstatus_return.mie = mstatus.mpie; mstatus_return.mpie = 1; - mstatus_return.mpp = ENABLE_U_MODE ? USER_PRIVILEGE : MACHINE_PRIVILEGE; + mstatus_return.mpp = CONFIG.INCLUDE_U_MODE ? USER_PRIVILEGE : MACHINE_PRIVILEGE; if (mstatus.mpp != MACHINE_PRIVILEGE) mstatus_return.mprv = 0; end @@ -307,7 +311,7 @@ generate if (ENABLE_M_MODE) begin logic [31:0] medeleg_mask; always_comb begin medeleg_mask = 0; - if (ENABLE_S_MODE) begin + if (CONFIG.INCLUDE_S_MODE) begin medeleg_mask[INST_ADDR_MISSALIGNED] = 1; medeleg_mask[INST_ACCESS_FAULT] = 1; medeleg_mask[ILLEGAL_INST] = 1; @@ -335,10 +339,10 @@ generate if (ENABLE_M_MODE) begin logic [31:0] mideleg_mask; always_comb begin mideleg_mask = 0; - if (ENABLE_S_MODE) begin - mideleg_mask[S_SOFTWARE_INTERRUPT] = ENABLE_S_MODE; - mideleg_mask[S_TIMER_INTERRUPT] = ENABLE_S_MODE; - mideleg_mask[S_EXTERNAL_INTERRUPT] = ENABLE_S_MODE; + if (CONFIG.INCLUDE_S_MODE) begin + mideleg_mask[S_SOFTWARE_INTERRUPT] = CONFIG.INCLUDE_S_MODE; + mideleg_mask[S_TIMER_INTERRUPT] = CONFIG.INCLUDE_S_MODE; + mideleg_mask[S_EXTERNAL_INTERRUPT] = CONFIG.INCLUDE_S_MODE; end end always_ff @(posedge clk) begin @@ -350,7 +354,7 @@ generate if (ENABLE_M_MODE) begin //////////////////////////////////////////////////// //MIP - assign mip_mask = '{default:0, meip:1, seip:ENABLE_S_MODE, mtip:1, stip:ENABLE_S_MODE, msip:1, ssip:ENABLE_S_MODE}; + assign mip_mask = '{default:0, meip:1, seip:CONFIG.INCLUDE_S_MODE, mtip:1, stip:CONFIG.INCLUDE_S_MODE, msip:1, ssip:CONFIG.INCLUDE_S_MODE}; always_ff @(posedge clk) begin if (rst) mip <= 0; @@ -360,7 +364,7 @@ generate if (ENABLE_M_MODE) begin //////////////////////////////////////////////////// //MIE - assign mie_mask = '{default:0, meie:1, seie:ENABLE_S_MODE, mtie:1, stie:ENABLE_S_MODE, msie:1, ssie:ENABLE_S_MODE}; + assign mie_mask = '{default:0, meie:1, seie:CONFIG.INCLUDE_S_MODE, mtie:1, stie:CONFIG.INCLUDE_S_MODE, msie:1, ssie:CONFIG.INCLUDE_S_MODE}; assign sie_mask = '{default:0, seie:1, stie:1, ssie:1}; always_ff @(posedge clk) begin @@ -389,40 +393,40 @@ generate if (ENABLE_M_MODE) begin //As the exception and interrupts codes are sparsely populated, //to ensure that only legal values are written, a ROM lookup //is used to validate the CSR write operation - logic MCAUSE_EXCEPTION_MASKING_ROM [2**ECODE_W]; - logic MCAUSE_INTERRUPT_MASKING_ROM [2**ECODE_W]; + logic MCAINCLUDE_EXCEPTION_MASKING_ROM [2**ECODE_W]; + logic MCAINCLUDE_INTERRUPT_MASKING_ROM [2**ECODE_W]; always_comb begin - MCAUSE_EXCEPTION_MASKING_ROM = '{default: 0}; - MCAUSE_EXCEPTION_MASKING_ROM[INST_ADDR_MISSALIGNED] = 1; - MCAUSE_EXCEPTION_MASKING_ROM[INST_ACCESS_FAULT] = ENABLE_S_MODE; - MCAUSE_EXCEPTION_MASKING_ROM[ILLEGAL_INST] = 1; - MCAUSE_EXCEPTION_MASKING_ROM[BREAK] = 1; - MCAUSE_EXCEPTION_MASKING_ROM[LOAD_ADDR_MISSALIGNED] = 1; - MCAUSE_EXCEPTION_MASKING_ROM[LOAD_FAULT] = ENABLE_S_MODE; - MCAUSE_EXCEPTION_MASKING_ROM[STORE_AMO_ADDR_MISSALIGNED] = 1; - MCAUSE_EXCEPTION_MASKING_ROM[STORE_AMO_FAULT] = ENABLE_S_MODE; - MCAUSE_EXCEPTION_MASKING_ROM[ECALL_U] = ENABLE_S_MODE; - MCAUSE_EXCEPTION_MASKING_ROM[ECALL_S] = ENABLE_S_MODE; - MCAUSE_EXCEPTION_MASKING_ROM[ECALL_M] = 1; - MCAUSE_EXCEPTION_MASKING_ROM[INST_PAGE_FAULT] = ENABLE_S_MODE; - MCAUSE_EXCEPTION_MASKING_ROM[LOAD_PAGE_FAULT] = ENABLE_S_MODE; - MCAUSE_EXCEPTION_MASKING_ROM[STORE_OR_AMO_PAGE_FAULT] = ENABLE_S_MODE; + MCAINCLUDE_EXCEPTION_MASKING_ROM = '{default: 0}; + MCAINCLUDE_EXCEPTION_MASKING_ROM[INST_ADDR_MISSALIGNED] = 1; + MCAINCLUDE_EXCEPTION_MASKING_ROM[INST_ACCESS_FAULT] = CONFIG.INCLUDE_S_MODE; + MCAINCLUDE_EXCEPTION_MASKING_ROM[ILLEGAL_INST] = 1; + MCAINCLUDE_EXCEPTION_MASKING_ROM[BREAK] = 1; + MCAINCLUDE_EXCEPTION_MASKING_ROM[LOAD_ADDR_MISSALIGNED] = 1; + MCAINCLUDE_EXCEPTION_MASKING_ROM[LOAD_FAULT] = CONFIG.INCLUDE_S_MODE; + MCAINCLUDE_EXCEPTION_MASKING_ROM[STORE_AMO_ADDR_MISSALIGNED] = 1; + MCAINCLUDE_EXCEPTION_MASKING_ROM[STORE_AMO_FAULT] = CONFIG.INCLUDE_S_MODE; + MCAINCLUDE_EXCEPTION_MASKING_ROM[ECALL_U] = CONFIG.INCLUDE_S_MODE; + MCAINCLUDE_EXCEPTION_MASKING_ROM[ECALL_S] = CONFIG.INCLUDE_S_MODE; + MCAINCLUDE_EXCEPTION_MASKING_ROM[ECALL_M] = 1; + MCAINCLUDE_EXCEPTION_MASKING_ROM[INST_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE; + MCAINCLUDE_EXCEPTION_MASKING_ROM[LOAD_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE; + MCAINCLUDE_EXCEPTION_MASKING_ROM[STORE_OR_AMO_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE; - MCAUSE_INTERRUPT_MASKING_ROM = '{default: 0}; - MCAUSE_INTERRUPT_MASKING_ROM[S_SOFTWARE_INTERRUPT] = ENABLE_S_MODE; - MCAUSE_INTERRUPT_MASKING_ROM[M_SOFTWARE_INTERRUPT] = 1; - MCAUSE_INTERRUPT_MASKING_ROM[S_TIMER_INTERRUPT] = ENABLE_S_MODE; - MCAUSE_INTERRUPT_MASKING_ROM[M_TIMER_INTERRUPT] = 1; - MCAUSE_INTERRUPT_MASKING_ROM[S_EXTERNAL_INTERRUPT] = ENABLE_S_MODE; - MCAUSE_INTERRUPT_MASKING_ROM[M_EXTERNAL_INTERRUPT] = 1; + MCAINCLUDE_INTERRUPT_MASKING_ROM = '{default: 0}; + MCAINCLUDE_INTERRUPT_MASKING_ROM[S_SOFTWARE_INTERRUPT] = CONFIG.INCLUDE_S_MODE; + MCAINCLUDE_INTERRUPT_MASKING_ROM[M_SOFTWARE_INTERRUPT] = 1; + MCAINCLUDE_INTERRUPT_MASKING_ROM[S_TIMER_INTERRUPT] = CONFIG.INCLUDE_S_MODE; + MCAINCLUDE_INTERRUPT_MASKING_ROM[M_TIMER_INTERRUPT] = 1; + MCAINCLUDE_INTERRUPT_MASKING_ROM[S_EXTERNAL_INTERRUPT] = CONFIG.INCLUDE_S_MODE; + MCAINCLUDE_INTERRUPT_MASKING_ROM[M_EXTERNAL_INTERRUPT] = 1; end logic mcause_write_valid; always_comb begin if (updated_csr[XLEN-1]) //interrupt - mcause_write_valid = MCAUSE_INTERRUPT_MASKING_ROM[updated_csr[ECODE_W-1:0]]; + mcause_write_valid = MCAINCLUDE_INTERRUPT_MASKING_ROM[updated_csr[ECODE_W-1:0]]; else - mcause_write_valid = MCAUSE_EXCEPTION_MASKING_ROM[updated_csr[ECODE_W-1:0]]; + mcause_write_valid = MCAINCLUDE_EXCEPTION_MASKING_ROM[updated_csr[ECODE_W-1:0]]; end always_ff @(posedge clk) begin @@ -474,11 +478,11 @@ endgenerate //BEGIN OF SUPERVISOR REGS //////////////////////////////////////////////////// //TLB status --- used to mux physical/virtual address - assign tlb_on = ENABLE_S_MODE & satp.mode; + assign tlb_on = CONFIG.INCLUDE_S_MODE & satp.mode; assign asid = satp.asid; //****************** -generate if (ENABLE_S_MODE) begin +generate if (CONFIG.INCLUDE_S_MODE) begin //////////////////////////////////////////////////// //MMU interface assign immu.mxr = mstatus.mxr; @@ -498,7 +502,7 @@ generate if (ENABLE_S_MODE) begin logic [31:0] stvec_mask = '1; always_ff @(posedge clk) begin if (rst) - stvec <= {RESET_VEC[XLEN-1:2], 2'b00}; + stvec <= {CONFIG.CSRS.RESET_VEC[XLEN-1:2], 2'b00}; else if (swrite_decoder[STVEC[7:0]]) stvec <= (updated_csr & stvec_mask); end @@ -525,7 +529,7 @@ endgenerate //////////////////////////////////////////////////// //Timers and Counters //Register increment for instructions completed - logic[COUNTER_W-1:0] mcycle_next; + logic[CONFIG.CSRS.COUNTER_W-1:0] mcycle_next; assign mcycle_next = mcycle + 1; //As the CSR write takes effect after the instruction has otherwise completed, @@ -535,23 +539,23 @@ endgenerate always_ff @(posedge clk) begin if (rst) begin mcycle[31:0] <= 0; - mcycle[COUNTER_W-1:32] <= 0; + mcycle[CONFIG.CSRS.COUNTER_W-1:32] <= 0; end else begin mcycle[31:0] <= mwrite_decoder[MCYCLE[7:0]] ? updated_csr : mcycle_next[31:0]; - mcycle[COUNTER_W-1:32] <= mwrite_decoder[MCYCLEH[7:0]] ? updated_csr[COUNTER_W-33:0] : mcycle_next[COUNTER_W-1:32]; + mcycle[CONFIG.CSRS.COUNTER_W-1:32] <= mwrite_decoder[MCYCLEH[7:0]] ? updated_csr[CONFIG.CSRS.COUNTER_W-33:0] : mcycle_next[CONFIG.CSRS.COUNTER_W-1:32]; end end - logic[COUNTER_W-1:0] minst_ret_next; - assign minst_ret_next = minst_ret + COUNTER_W'(retire.count); + logic[CONFIG.CSRS.COUNTER_W-1:0] minst_ret_next; + assign minst_ret_next = minst_ret + CONFIG.CSRS.COUNTER_W'(retire.count); always_ff @(posedge clk) begin if (rst) begin minst_ret[31:0] <= 0; - minst_ret[COUNTER_W-1:32] <= 0; + minst_ret[CONFIG.CSRS.COUNTER_W-1:32] <= 0; end else begin minst_ret[31:0] <= mwrite_decoder[MINSTRET[7:0]] ? updated_csr : minst_ret_next[31:0]; - minst_ret[COUNTER_W-1:32] <= mwrite_decoder[MINSTRETH[7:0]] ? updated_csr[COUNTER_W-33:0] : minst_ret_next[COUNTER_W-1:32]; + minst_ret[CONFIG.CSRS.COUNTER_W-1:32] <= mwrite_decoder[MINSTRETH[7:0]] ? updated_csr[CONFIG.CSRS.COUNTER_W-33:0] : minst_ret_next[CONFIG.CSRS.COUNTER_W-1:32]; end end @@ -559,51 +563,51 @@ endgenerate invalid_addr = 0; case (csr_addr) inside //Machine info - MISA : selected_csr = ENABLE_M_MODE ? misa : 0; - MVENDORID : selected_csr = ENABLE_M_MODE ? mvendorid : 0; - MARCHID : selected_csr = ENABLE_M_MODE ? marchid : 0; - MIMPID : selected_csr = ENABLE_M_MODE ? mimpid : 0; - MHARTID : selected_csr = ENABLE_M_MODE ? mhartid : 0; + MISA : selected_csr = CONFIG.INCLUDE_M_MODE ? misa : 0; + MVENDORID : selected_csr = CONFIG.INCLUDE_M_MODE ? mvendorid : 0; + MARCHID : selected_csr = CONFIG.INCLUDE_M_MODE ? marchid : 0; + MIMPID : selected_csr = CONFIG.INCLUDE_M_MODE ? mimpid : 0; + MHARTID : selected_csr = CONFIG.INCLUDE_M_MODE ? mhartid : 0; //Machine trap setup - MSTATUS : selected_csr = ENABLE_M_MODE ? mstatus : 0; - MEDELEG : selected_csr = ENABLE_M_MODE ? medeleg : 0; - MIDELEG : selected_csr = ENABLE_M_MODE ? mideleg : 0; - MIE : selected_csr = ENABLE_M_MODE ? mie_reg : 0; - MTVEC : selected_csr = ENABLE_M_MODE ? mtvec : 0; + MSTATUS : selected_csr = CONFIG.INCLUDE_M_MODE ? mstatus : 0; + MEDELEG : selected_csr = CONFIG.INCLUDE_M_MODE ? medeleg : 0; + MIDELEG : selected_csr = CONFIG.INCLUDE_M_MODE ? mideleg : 0; + MIE : selected_csr = CONFIG.INCLUDE_M_MODE ? mie_reg : 0; + MTVEC : selected_csr = CONFIG.INCLUDE_M_MODE ? mtvec : 0; MCOUNTEREN : selected_csr = 0; //Machine trap handling - MSCRATCH : selected_csr = ENABLE_M_MODE ? scratch_out : 0; - MEPC : selected_csr = ENABLE_M_MODE ? mepc : 0; - MCAUSE : selected_csr = ENABLE_M_MODE ? mcause : 0; - MTVAL : selected_csr = ENABLE_M_MODE ? mtval : 0; - MIP : selected_csr = ENABLE_M_MODE ? mip : 0; + MSCRATCH : selected_csr = CONFIG.INCLUDE_M_MODE ? scratch_out : 0; + MEPC : selected_csr = CONFIG.INCLUDE_M_MODE ? mepc : 0; + MCAUSE : selected_csr = CONFIG.INCLUDE_M_MODE ? mcause : 0; + MTVAL : selected_csr = CONFIG.INCLUDE_M_MODE ? mtval : 0; + MIP : selected_csr = CONFIG.INCLUDE_M_MODE ? mip : 0; //Machine Memory Protection [12'h3EF : 12'h3A0] : selected_csr = 0; //Machine Timers and Counters - MCYCLE : selected_csr = ENABLE_M_MODE ? mcycle[XLEN-1:0] : 0; - MINSTRET : selected_csr = ENABLE_M_MODE ? minst_ret[XLEN-1:0] : 0; + MCYCLE : selected_csr = CONFIG.INCLUDE_M_MODE ? mcycle[XLEN-1:0] : 0; + MINSTRET : selected_csr = CONFIG.INCLUDE_M_MODE ? minst_ret[XLEN-1:0] : 0; [12'hB03 : 12'hB1F] : selected_csr = 0; - MCYCLEH : selected_csr = ENABLE_M_MODE ? 32'(mcycle[COUNTER_W-1:XLEN]) : 0; - MINSTRETH : selected_csr = ENABLE_M_MODE ? 32'(minst_ret[COUNTER_W-1:XLEN]) : 0; + MCYCLEH : selected_csr = CONFIG.INCLUDE_M_MODE ? 32'(mcycle[CONFIG.CSRS.COUNTER_W-1:XLEN]) : 0; + MINSTRETH : selected_csr = CONFIG.INCLUDE_M_MODE ? 32'(minst_ret[CONFIG.CSRS.COUNTER_W-1:XLEN]) : 0; [12'hB83 : 12'hB9F] : selected_csr = 0; //Machine Counter Setup [12'h320 : 12'h33F] : selected_csr = 0; //Supervisor Trap Setup - SSTATUS : selected_csr = ENABLE_S_MODE ? (mstatus & sstatus_mask) : '0; + SSTATUS : selected_csr = CONFIG.INCLUDE_S_MODE ? (mstatus & sstatus_mask) : '0; SEDELEG : selected_csr = 0; //No user-level interrupts/exception handling SIDELEG : selected_csr = 0; - SIE : selected_csr = ENABLE_S_MODE ? (mie_reg & sie_mask) : '0; - STVEC : selected_csr = ENABLE_S_MODE ? stvec : '0; + SIE : selected_csr = CONFIG.INCLUDE_S_MODE ? (mie_reg & sie_mask) : '0; + STVEC : selected_csr = CONFIG.INCLUDE_S_MODE ? stvec : '0; SCOUNTEREN : selected_csr = 0; //Supervisor trap handling - SSCRATCH : selected_csr = ENABLE_S_MODE ? scratch_out : '0; - SEPC : selected_csr = ENABLE_S_MODE ? scratch_out : '0; - SCAUSE : selected_csr = ENABLE_S_MODE ? scratch_out : '0; - STVAL : selected_csr = ENABLE_S_MODE ? scratch_out : '0; - SIP : selected_csr = ENABLE_S_MODE ? (mip & sip_mask) : '0; + SSCRATCH : selected_csr = CONFIG.INCLUDE_S_MODE ? scratch_out : '0; + SEPC : selected_csr = CONFIG.INCLUDE_S_MODE ? scratch_out : '0; + SCAUSE : selected_csr = CONFIG.INCLUDE_S_MODE ? scratch_out : '0; + STVAL : selected_csr = CONFIG.INCLUDE_S_MODE ? scratch_out : '0; + SIP : selected_csr = CONFIG.INCLUDE_S_MODE ? (mip & sip_mask) : '0; //Supervisor Protection and Translation - SATP : selected_csr = ENABLE_S_MODE ? satp : '0; + SATP : selected_csr = CONFIG.INCLUDE_S_MODE ? satp : '0; //User status //Floating point @@ -615,9 +619,9 @@ endgenerate TIME : selected_csr = mcycle[XLEN-1:0]; INSTRET : selected_csr = minst_ret[XLEN-1:0]; [12'hC03 : 12'hC1F] : selected_csr = 0; - CYCLEH : selected_csr = 32'(mcycle[COUNTER_W-1:XLEN]); - TIMEH : selected_csr = 32'(mcycle[COUNTER_W-1:XLEN]); - INSTRETH : selected_csr = 32'(minst_ret[COUNTER_W-1:XLEN]); + CYCLEH : selected_csr = 32'(mcycle[CONFIG.CSRS.COUNTER_W-1:XLEN]); + TIMEH : selected_csr = 32'(mcycle[CONFIG.CSRS.COUNTER_W-1:XLEN]); + INSTRETH : selected_csr = 32'(minst_ret[CONFIG.CSRS.COUNTER_W-1:XLEN]); [12'hC83 : 12'hC9F] : selected_csr = 0; default : begin selected_csr = 0; invalid_addr = 1; end diff --git a/core/dcache.sv b/core/dcache.sv index 58c9b8b..5fb79da 100755 --- a/core/dcache.sv +++ b/core/dcache.sv @@ -25,7 +25,11 @@ module dcache import taiga_config::*; import riscv_types::*; import taiga_types::*; - + + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -43,26 +47,27 @@ module dcache ls_sub_unit_interface.sub_unit ls ); - localparam DCACHE_SIZE_IN_WORDS = DCACHE_LINES*DCACHE_LINE_W*DCACHE_WAYS; + localparam DCACHE_SIZE_IN_WORDS = CONFIG.DCACHE.LINES*CONFIG.DCACHE.LINE_W*CONFIG.DCACHE.WAYS; + localparam derived_cache_config_t SCONFIG = get_derived_cache_params(CONFIG, CONFIG.DCACHE, CONFIG.DCACHE_ADDR); logic [$clog2(DCACHE_SIZE_IN_WORDS)-1:0] data_bank_addr_a; logic [$clog2(DCACHE_SIZE_IN_WORDS)-1:0] data_bank_addr_b; logic tag_hit; - logic [DCACHE_WAYS-1:0] tag_hit_way; + logic [CONFIG.DCACHE.WAYS-1:0] tag_hit_way; - logic [$clog2(DCACHE_WAYS)-1:0] tag_hit_way_int; + logic [$clog2(CONFIG.DCACHE.WAYS)-1:0] tag_hit_way_int; logic tag_update; - logic [DCACHE_WAYS-1:0] tag_update_way; - logic [DCACHE_WAYS-1:0] replacement_way; + logic [CONFIG.DCACHE.WAYS-1:0] tag_update_way; + logic [CONFIG.DCACHE.WAYS-1:0] replacement_way; - logic [$clog2(DCACHE_WAYS)-1:0] replacement_way_int; - logic [$clog2(DCACHE_WAYS)-1:0] tag_update_way_int; + logic [$clog2(CONFIG.DCACHE.WAYS)-1:0] replacement_way_int; + logic [$clog2(CONFIG.DCACHE.WAYS)-1:0] tag_update_way_int; - logic [DCACHE_SUB_LINE_ADDR_W-1:0] word_count; - logic [DCACHE_SUB_LINE_ADDR_W-1:0] sc_write_index; - logic [DCACHE_SUB_LINE_ADDR_W-1:0] update_word_index; + logic [SCONFIG.SUB_LINE_ADDR_W-1:0] word_count; + logic [SCONFIG.SUB_LINE_ADDR_W-1:0] sc_write_index; + logic [SCONFIG.SUB_LINE_ADDR_W-1:0] update_word_index; logic line_complete; logic reservation; @@ -148,7 +153,7 @@ module dcache assign l1_request.data = stage2_data; assign l1_request.rnw = ~stage2_store; assign l1_request.be = stage2_be; - assign l1_request.size = stage2_load ? (DCACHE_LINE_W-1) : 0;//LR and AMO ops are included in load + assign l1_request.size = stage2_load ? 5'(CONFIG.DCACHE.LINE_W-1) : 0;//LR and AMO ops are included in load assign l1_request.is_amo = (stage2_amo.is_amo | stage2_amo.is_lr | stage2_amo.is_sc); assign l1_request.amo = stage2_amo.op; @@ -158,7 +163,7 @@ module dcache else if (l1_response.data_valid) word_count <= word_count + 1; end - assign is_target_word = (stage2_addr[DCACHE_SUB_LINE_ADDR_W+1:2] == word_count); + assign is_target_word = (stage2_addr[SCONFIG.SUB_LINE_ADDR_W+1:2] == word_count); assign new_arb_request = second_cycle & (~(tag_hit & read_hit_allowed) | ~dcache_on); always_ff @ (posedge clk) begin @@ -173,7 +178,7 @@ module dcache //////////////////////////////////////////////////// //Replacement policy (free runing one-hot cycler, i.e. pseudo random) - cycler #(DCACHE_WAYS) replacement_policy ( + cycler #(CONFIG.DCACHE.WAYS) replacement_policy ( .clk (clk), .rst (rst), .en (1'b1), @@ -181,13 +186,13 @@ module dcache ); //One-hot tag hit / update logic to binary int - one_hot_to_integer #(DCACHE_WAYS) hit_way_conv ( + one_hot_to_integer #(CONFIG.DCACHE.WAYS) hit_way_conv ( .clk (clk), .rst (rst), .one_hot(tag_hit_way), .int_out(tag_hit_way_int) ); - one_hot_to_integer #(DCACHE_WAYS) update_way_conv ( + one_hot_to_integer #(CONFIG.DCACHE.WAYS) update_way_conv ( .clk (clk), .rst (rst), .one_hot (replacement_way), @@ -207,20 +212,21 @@ module dcache //////////////////////////////////////////////////// //Tag banks - dtag_banks dcache_tag_banks ( - .clk (clk), - .rst (rst), - .stage1_addr (ls_inputs.addr), - .stage2_addr (stage2_addr), - .inv_addr ({l1_response.inv_addr, 2'b00}), - .update_way (tag_update_way), - .update (tag_update), - .stage1_adv (ls.new_request), - .stage1_inv (1'b0),//For software invalidation - .extern_inv (l1_response.inv_valid), - .extern_inv_complete (l1_response.inv_ack), - .tag_hit (tag_hit), - .tag_hit_way (tag_hit_way) + dtag_banks #(.CONFIG(CONFIG), .SCONFIG(SCONFIG)) + dcache_tag_banks ( + .clk (clk), + .rst (rst), + .stage1_addr (ls_inputs.addr), + .stage2_addr (stage2_addr), + .inv_addr ({l1_response.inv_addr, 2'b00}), + .update_way (tag_update_way), + .update (tag_update), + .stage1_adv (ls.new_request), + .stage1_inv (1'b0),//For software invalidation + .extern_inv (l1_response.inv_valid), + .extern_inv_complete (l1_response.inv_ack), + .tag_hit (tag_hit), + .tag_hit_way (tag_hit_way) ); //////////////////////////////////////////////////// @@ -233,10 +239,10 @@ module dcache assign amo_alu_inputs.rs2 = amo_rs2; assign amo_alu_inputs.op = stage2_amo.op; - generate if (USE_AMO) + generate if (CONFIG.INCLUDE_AMO) amo_alu amo_unit ( .amo_alu_inputs (amo_alu_inputs), - .result (amo_result) + .result (amo_result) ); endgenerate @@ -249,7 +255,7 @@ module dcache new_line_data = l1_response.data; end - assign sc_write_index = stage2_addr[DCACHE_SUB_LINE_ADDR_W+1:2]; + assign sc_write_index = stage2_addr[SCONFIG.SUB_LINE_ADDR_W+1:2]; //////////////////////////////////////////////////// @@ -259,8 +265,8 @@ module dcache assign write_hit_be = stage2_be & {4{tag_hit}}; assign update_word_index = stage2_amo.is_sc ? sc_write_index : word_count; - assign data_bank_addr_a = {tag_hit_way_int, stage2_addr[DCACHE_LINE_ADDR_W+DCACHE_SUB_LINE_ADDR_W+2-1:2]}; - assign data_bank_addr_b = {tag_update_way_int, stage2_addr[DCACHE_LINE_ADDR_W+DCACHE_SUB_LINE_ADDR_W+2-1:DCACHE_SUB_LINE_ADDR_W+2], update_word_index}; + assign data_bank_addr_a = {tag_hit_way_int, stage2_addr[SCONFIG.LINE_ADDR_W+SCONFIG.SUB_LINE_ADDR_W+2-1:2]}; + assign data_bank_addr_b = {tag_update_way_int, stage2_addr[SCONFIG.LINE_ADDR_W+SCONFIG.SUB_LINE_ADDR_W+2-1:SCONFIG.SUB_LINE_ADDR_W+2], update_word_index}; ddata_bank #(.LINES(DCACHE_SIZE_IN_WORDS)) data_bank ( .clk(clk), @@ -287,7 +293,7 @@ module dcache //////////////////////////////////////////////////// //Pipeline Advancement - assign line_complete = (l1_response.data_valid && (word_count == $clog2(DCACHE_LINE_W)'(DCACHE_LINE_W-1))); //covers load, LR, AMO + assign line_complete = (l1_response.data_valid && (word_count == $clog2(CONFIG.DCACHE.LINE_W)'(CONFIG.DCACHE.LINE_W-1))); //covers load, LR, AMO assign store_complete = l1_request.ack & stage2_store & ~stage2_amo.is_sc; //read miss complete includes store conditional complete diff --git a/core/decode_and_issue.sv b/core/decode_and_issue.sv index 2bcc288..8c53e69 100755 --- a/core/decode_and_issue.sv +++ b/core/decode_and_issue.sv @@ -25,7 +25,13 @@ module decode_and_issue import taiga_config::*; import riscv_types::*; import taiga_types::*; - + + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG, + parameter NUM_UNITS = 5, + parameter unit_id_param_t UNIT_IDS = EXAMPLE_UNIT_IDS + ) + ( input logic clk, input logic rst, @@ -108,8 +114,6 @@ module decode_and_issue logic operands_ready; logic mult_div_op; - logic [NUM_WB_UNITS-1:0] unit_needed_for_id_gen; - logic [WB_UNITS_WIDTH-1:0] unit_needed_for_id_gen_int; logic [NUM_UNITS-1:0] unit_needed; logic [NUM_UNITS-1:0] unit_needed_issue_stage; logic [NUM_UNITS-1:0] unit_ready; @@ -152,18 +156,18 @@ 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_ID] = (opcode_trim inside {ARITH_T, ARITH_IMM_T, AUIPC_T, LUI_T, JAL_T, JALR_T}) & ~mult_div_op; - assign unit_needed[LS_UNIT_ID] = opcode_trim inside {LOAD_T, STORE_T, AMO_T}; - assign unit_needed[GC_UNIT_ID] = opcode_trim inside {SYSTEM_T, FENCE_T}; + assign unit_needed[UNIT_IDS.BR] = opcode_trim inside {BRANCH_T, JAL_T, JALR_T}; + assign unit_needed[UNIT_IDS.ALU] = (opcode_trim inside {ARITH_T, ARITH_IMM_T, AUIPC_T, LUI_T, JAL_T, JALR_T}) & ~mult_div_op; + assign unit_needed[UNIT_IDS.LS] = opcode_trim inside {LOAD_T, STORE_T, AMO_T}; + assign unit_needed[UNIT_IDS.CSR] = opcode_trim inside {SYSTEM_T, FENCE_T}; assign mult_div_op = (opcode_trim == ARITH_T) && decode.instruction[25]; - generate if (USE_MUL) - assign unit_needed[MUL_UNIT_ID] = mult_div_op && ~fn3[2]; + generate if (CONFIG.INCLUDE_MUL) + assign unit_needed[UNIT_IDS.MUL] = mult_div_op && ~fn3[2]; endgenerate - generate if (USE_DIV) - assign unit_needed[DIV_UNIT_ID] = mult_div_op && fn3[2]; + generate if (CONFIG.INCLUDE_DIV) + assign unit_needed[UNIT_IDS.DIV] = mult_div_op && fn3[2]; endgenerate //////////////////////////////////////////////////// @@ -172,7 +176,7 @@ module decode_and_issue 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.rd_wb_group = ~unit_needed[UNIT_IDS.ALU];//TODO: automate generation of wb group logic assign renamer.id = decode.id; //////////////////////////////////////////////////// @@ -183,6 +187,8 @@ module decode_and_issue //////////////////////////////////////////////////// //Issue + logic [REGFILE_READ_PORTS-1:0][$clog2(CONFIG.NUM_WB_GROUPS)-1:0] issue_rs_wb_group; + always_ff @(posedge clk) begin if (issue_stage_ready) begin issue.pc <= decode.pc; @@ -194,10 +200,10 @@ module decode_and_issue 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_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.is_multicycle <= ~unit_needed[UNIT_IDS.ALU]; issue.id <= decode.id; issue.uses_rs1 <= uses_rs1; issue.uses_rs2 <= uses_rs2; @@ -241,9 +247,9 @@ module decode_and_issue assign rf.phys_rs_addr[RS1] = issue.phys_rs_addr[RS1]; assign rf.phys_rs_addr[RS2] = issue.phys_rs_addr[RS2]; assign rf.phys_rd_addr = issue.phys_rd_addr; - assign rf.rs_wb_group[RS1] = issue.rs_wb_group[RS1]; - assign rf.rs_wb_group[RS2] = issue.rs_wb_group[RS2]; - assign rf.rd_wb_group = issue.rd_wb_group; + assign rf.rs_wb_group[RS1] = issue_rs_wb_group[RS1]; + assign rf.rs_wb_group[RS2] = issue_rs_wb_group[RS2]; + assign rf.rd_wb_group = issue.is_multicycle; assign rf.issued = instruction_issued_with_rd; //////////////////////////////////////////////////// //ALU unit inputs @@ -319,12 +325,12 @@ module decode_and_issue logic load_reserve; logic [4:0] amo_type; - assign amo_op = USE_AMO ? (opcode_trim == AMO_T) : 1'b0; + assign amo_op = CONFIG.INCLUDE_AMO ? (opcode_trim == AMO_T) : 1'b0; assign amo_type = decode.instruction[31:27]; assign store_conditional = (amo_type == AMO_SC); assign load_reserve = (amo_type == AMO_LR); - generate if (USE_AMO) begin + generate if (CONFIG.INCLUDE_AMO) begin assign ls_inputs.amo.is_lr = load_reserve; assign ls_inputs.amo.is_sc = store_conditional; assign ls_inputs.amo.is_amo = amo_op & ~(load_reserve | store_conditional); @@ -459,12 +465,12 @@ module decode_and_issue always_comb begin sys_op_match = '0; case (decode.instruction[31:20]) inside - ECALL_imm : sys_op_match[ECALL_i] = ENABLE_M_MODE; - EBREAK_imm : sys_op_match[EBREAK_i] = ENABLE_M_MODE; - URET_imm : sys_op_match[URET_i] = ENABLE_U_MODE; - SRET_imm : sys_op_match[SRET_i] = ENABLE_S_MODE; - MRET_imm : sys_op_match[MRET_i] = ENABLE_M_MODE; - SFENCE_imm : sys_op_match[SFENCE_i] = ENABLE_S_MODE; + ECALL_imm : sys_op_match[ECALL_i] = CONFIG.INCLUDE_M_MODE; + EBREAK_imm : sys_op_match[EBREAK_i] = CONFIG.INCLUDE_M_MODE; + URET_imm : sys_op_match[URET_i] = CONFIG.INCLUDE_U_MODE; + SRET_imm : sys_op_match[SRET_i] = CONFIG.INCLUDE_S_MODE; + MRET_imm : sys_op_match[MRET_i] = CONFIG.INCLUDE_M_MODE; + SFENCE_imm : sys_op_match[SFENCE_i] = CONFIG.INCLUDE_S_MODE; default : sys_op_match = '0; endcase end @@ -476,7 +482,7 @@ module decode_and_issue is_ecall <= environment_op & sys_op_match[ECALL_i]; is_ebreak <= environment_op & sys_op_match[EBREAK_i]; is_ret <= environment_op & (sys_op_match[URET_i] | sys_op_match[SRET_i] | sys_op_match[MRET_i]); - is_fence <= ENABLE_M_MODE && (opcode_trim == FENCE_T) && ~fn3[0]; + is_fence <= CONFIG.INCLUDE_M_MODE && (opcode_trim == FENCE_T) && ~fn3[0]; is_ifence_r <= (opcode_trim == FENCE_T) && fn3[0]; potential_flush <= (environment_op | ifence); end @@ -489,15 +495,15 @@ module decode_and_issue assign gc_inputs.instruction = issue.instruction; assign gc_inputs.is_csr = is_csr_r; assign gc_inputs.is_fence = is_fence; - assign gc_inputs.is_i_fence = ENABLE_M_MODE & issue_to[GC_UNIT_ID] & is_ifence_r; + assign gc_inputs.is_i_fence = CONFIG.INCLUDE_M_MODE & issue_to[UNIT_IDS.CSR] & is_ifence_r; assign gc_inputs.rs1 = rf.data[RS1]; assign gc_inputs.rs2 = rf.data[RS2]; - assign gc_flush_required = ENABLE_M_MODE && issue_to[GC_UNIT_ID] && potential_flush; + assign gc_flush_required = CONFIG.INCLUDE_M_MODE && issue_to[UNIT_IDS.CSR] && potential_flush; //////////////////////////////////////////////////// //Mul unit inputs - generate if (USE_MUL) begin + generate if (CONFIG.INCLUDE_MUL) begin assign mul_inputs.rs1 = rf.data[RS1]; assign mul_inputs.rs2 = rf.data[RS2]; assign mul_inputs.op = issue.fn3[1:0]; @@ -505,7 +511,7 @@ module decode_and_issue //////////////////////////////////////////////////// //Div unit inputs - generate if (USE_DIV) begin + generate if (CONFIG.INCLUDE_DIV) begin logic [4:0] prev_div_rs1_addr; logic [4:0] prev_div_rs2_addr; logic prev_div_result_valid; @@ -513,7 +519,7 @@ module decode_and_issue logic div_op_reuse; always_ff @(posedge clk) begin - if (issue_to[DIV_UNIT_ID]) begin + if (issue_to[UNIT_IDS.DIV]) begin prev_div_rs1_addr <= rs1_addr; prev_div_rs2_addr <= rs2_addr; end @@ -522,11 +528,11 @@ module decode_and_issue assign div_op_reuse = {prev_div_result_valid, prev_div_rs1_addr, prev_div_rs2_addr} == {1'b1, issue.rs_addr[RS1], issue.rs_addr[RS2]}; //If current div operation overwrites an input register OR any other instruction overwrites the last div operations input registers - assign div_rs_overwrite = (issue.rd_addr == (unit_needed_issue_stage[DIV_UNIT_ID] ? issue.rs_addr[RS1] : prev_div_rs1_addr)) || (issue.rd_addr == (unit_needed_issue_stage[DIV_UNIT_ID] ? issue.rs_addr[RS2] : prev_div_rs2_addr)); + assign div_rs_overwrite = (issue.rd_addr == (unit_needed_issue_stage[UNIT_IDS.DIV] ? issue.rs_addr[RS1] : prev_div_rs1_addr)) || (issue.rd_addr == (unit_needed_issue_stage[UNIT_IDS.DIV] ? issue.rs_addr[RS2] : prev_div_rs2_addr)); set_clr_reg_with_rst #(.SET_OVER_CLR(0), .WIDTH(1), .RST_VALUE(0)) prev_div_result_valid_m ( .clk, .rst, - .set(instruction_issued & unit_needed_issue_stage[DIV_UNIT_ID]), + .set(instruction_issued & unit_needed_issue_stage[UNIT_IDS.DIV]), .clr(instruction_issued & issue.uses_rd & div_rs_overwrite), .result(prev_div_result_valid) ); @@ -551,8 +557,9 @@ module decode_and_issue //////////////////////////////////////////////////// //Illegal Instruction check logic illegal_instruction_pattern_r; - generate if (ENABLE_M_MODE) begin - illegal_instruction_checker illegal_op_check ( + generate if (CONFIG.INCLUDE_M_MODE) begin + illegal_instruction_checker # (.CONFIG(CONFIG)) + illegal_op_check ( .instruction(decode.instruction), .illegal_instruction(illegal_instruction_pattern) ); always_ff @(posedge clk) begin @@ -586,10 +593,10 @@ module decode_and_issue assign tr_no_id_stall = (~issue.stage_valid & ~pc_id_available & ~gc_fetch_flush); //All instructions in execution pipeline assign tr_no_instruction_stall = (~tr_no_id_stall & ~issue.stage_valid) | gc_fetch_flush; assign tr_other_stall = issue.stage_valid & ~instruction_issued & ~(tr_operand_stall | tr_unit_stall | tr_no_id_stall | tr_no_instruction_stall); - assign tr_branch_operand_stall = tr_operand_stall & unit_needed_issue_stage[BRANCH_UNIT_ID]; - assign tr_alu_operand_stall = tr_operand_stall & unit_needed_issue_stage[ALU_UNIT_ID] & ~unit_needed_issue_stage[BRANCH_UNIT_ID]; - assign tr_ls_operand_stall = tr_operand_stall & unit_needed_issue_stage[LS_UNIT_ID]; - assign tr_div_operand_stall = tr_operand_stall & unit_needed_issue_stage[DIV_UNIT_ID]; + assign tr_branch_operand_stall = tr_operand_stall & unit_needed_issue_stage[UNIT_IDS.BR]; + assign tr_alu_operand_stall = tr_operand_stall & unit_needed_issue_stage[UNIT_IDS.ALU] & ~unit_needed_issue_stage[UNIT_IDS.BR]; + assign tr_ls_operand_stall = tr_operand_stall & unit_needed_issue_stage[UNIT_IDS.LS]; + assign tr_div_operand_stall = tr_operand_stall & unit_needed_issue_stage[UNIT_IDS.DIV]; //Instruction Mix always_ff @(posedge clk) begin @@ -598,8 +605,8 @@ module decode_and_issue 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}); tr_store_op <= instruction_issued && (opcode_trim inside {STORE_T}); - tr_mul_op <= instruction_issued && unit_needed_issue_stage[MUL_UNIT_ID]; - tr_div_op <= instruction_issued && unit_needed_issue_stage[DIV_UNIT_ID]; + tr_mul_op <= instruction_issued && unit_needed_issue_stage[UNIT_IDS.MUL]; + tr_div_op <= instruction_issued && unit_needed_issue_stage[UNIT_IDS.DIV]; tr_misc_op <= instruction_issued & ~(tr_alu_op | tr_branch_or_jump_op | tr_load_op | tr_store_op | tr_mul_op | tr_div_op); end end diff --git a/core/dtag_banks.sv b/core/dtag_banks.sv index 9d6faf6..b33832f 100755 --- a/core/dtag_banks.sv +++ b/core/dtag_banks.sv @@ -25,6 +25,11 @@ module dtag_banks import taiga_config::*; import taiga_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG, + parameter derived_cache_config_t SCONFIG = '{default: 0} + ) + ( input logic clk, input logic rst, @@ -33,7 +38,7 @@ module dtag_banks input logic[31:0] stage2_addr, input logic[31:0] inv_addr, - input logic[DCACHE_WAYS-1:0] update_way, + input logic[CONFIG.DCACHE.WAYS-1:0] update_way, input logic update, input logic stage1_adv, @@ -43,36 +48,36 @@ module dtag_banks output logic extern_inv_complete, output tag_hit, - output logic[DCACHE_WAYS-1:0] tag_hit_way + output logic[CONFIG.DCACHE.WAYS-1:0] tag_hit_way ); typedef struct packed{ logic valid; - logic [DCACHE_TAG_W-1:0] tag; + logic [SCONFIG.TAG_W-1:0] tag; } dtag_entry_t; - function logic[DCACHE_TAG_W-1:0] getTag(logic[31:0] addr); - return addr[2+DCACHE_SUB_LINE_ADDR_W+DCACHE_LINE_ADDR_W +: DCACHE_TAG_W]; + function logic[SCONFIG.TAG_W-1:0] getTag(logic[31:0] addr); + return addr[2+SCONFIG.SUB_LINE_ADDR_W+SCONFIG.LINE_ADDR_W +: SCONFIG.TAG_W]; endfunction - function logic[DCACHE_LINE_ADDR_W-1:0] getLineAddr(logic[31:0] addr); - return addr[DCACHE_LINE_ADDR_W + DCACHE_SUB_LINE_ADDR_W + 1 : DCACHE_SUB_LINE_ADDR_W + 2]; + function logic[SCONFIG.LINE_ADDR_W-1:0] getLineAddr(logic[31:0] addr); + return addr[SCONFIG.LINE_ADDR_W + SCONFIG.SUB_LINE_ADDR_W + 1 : SCONFIG.SUB_LINE_ADDR_W + 2]; endfunction - dtag_entry_t tag_line [DCACHE_WAYS - 1:0]; - dtag_entry_t inv_tag_line [DCACHE_WAYS - 1:0]; + dtag_entry_t tag_line [CONFIG.DCACHE.WAYS - 1:0]; + dtag_entry_t inv_tag_line [CONFIG.DCACHE.WAYS - 1:0]; dtag_entry_t new_tagline; logic miss_or_extern_invalidate; - logic [DCACHE_WAYS - 1:0] update_tag_way; + logic [CONFIG.DCACHE.WAYS - 1:0] update_tag_way; logic inv_tags_accessed; - logic[DCACHE_WAYS-1:0] inv_hit_way; - logic[DCACHE_WAYS-1:0] inv_hit_way_r; + logic[CONFIG.DCACHE.WAYS-1:0] inv_hit_way; + logic[CONFIG.DCACHE.WAYS-1:0] inv_hit_way_r; - logic [DCACHE_LINE_ADDR_W-1:0] update_port_addr; + logic [SCONFIG.LINE_ADDR_W-1:0] update_port_addr; //////////////////////////////////////////////////// //Implementation @@ -106,10 +111,10 @@ module dtag_banks assign inv_hit_comparison_tagline.valid = 1; assign inv_hit_comparison_tagline.tag = getTag(inv_addr); - for (i=0; i < DCACHE_WAYS; i=i+1) begin : dtag_bank_gen + for (i=0; i < CONFIG.DCACHE.WAYS; i=i+1) begin : dtag_bank_gen assign update_tag_way[i] = update_way[i] | (inv_hit_way[i] & extern_inv_complete); - tag_bank #($bits(dtag_entry_t), DCACHE_LINES) dtag_bank ( + tag_bank #($bits(dtag_entry_t), CONFIG.DCACHE.LINES) dtag_bank ( .clk (clk), .rst (rst), .en_a (stage1_adv), diff --git a/core/fetch.sv b/core/fetch.sv index afda7a6..5dba3c8 100755 --- a/core/fetch.sv +++ b/core/fetch.sv @@ -26,6 +26,10 @@ module fetch import riscv_types::*; import taiga_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -39,6 +43,7 @@ module fetch input logic [31:0] gc_fetch_pc, //ID Support + input id_t pc_id, input logic pc_id_available, output logic pc_id_assigned, output logic fetch_complete, @@ -63,16 +68,18 @@ module fetch output logic tr_early_branch_correction ); - localparam NUM_SUB_UNITS = USE_I_SCRATCH_MEM + USE_ICACHE; + localparam NUM_SUB_UNITS = int'(CONFIG.INCLUDE_ILOCAL_MEM) + int'(CONFIG.INCLUDE_ICACHE); localparam NUM_SUB_UNITS_W = (NUM_SUB_UNITS == 1) ? 1 : $clog2(NUM_SUB_UNITS); localparam BRAM_ID = 0; - localparam ICACHE_ID = USE_I_SCRATCH_MEM; + localparam ICACHE_ID = int'(CONFIG.INCLUDE_ILOCAL_MEM); - localparam NEXT_ID_DEPTH = USE_ICACHE ? 2 : 1; + localparam NEXT_ID_DEPTH = CONFIG.INCLUDE_ICACHE ? 2 : 1; //Subunit signals - fetch_sub_unit_interface fetch_sub[NUM_SUB_UNITS-1:0](); + fetch_sub_unit_interface #(.BASE_ADDR(CONFIG.ILOCAL_MEM_ADDR.L), .UPPER_BOUND(CONFIG.ILOCAL_MEM_ADDR.H)) bram(); + fetch_sub_unit_interface #(.BASE_ADDR(CONFIG.ICACHE_ADDR.L), .UPPER_BOUND(CONFIG.ICACHE_ADDR.H)) cache(); + logic [NUM_SUB_UNITS-1:0] sub_unit_address_match; logic [NUM_SUB_UNITS-1:0] unit_ready; logic [NUM_SUB_UNITS-1:0] unit_data_valid; @@ -117,7 +124,7 @@ module fetch assign update_pc = new_mem_request | gc_fetch_flush | early_branch_flush; always_ff @(posedge clk) begin if (rst) - pc <= RESET_VEC; + pc <= CONFIG.CSRS.RESET_VEC; else if (update_pc) pc <= {next_pc[31:2], 2'b0}; end @@ -148,6 +155,8 @@ module fetch assign bp.new_mem_request = update_pc; assign bp.next_pc = next_pc; assign bp.if_pc = pc; + assign bp.pc_id = pc_id; + assign bp.pc_id_assigned = pc_id_assigned; assign ras.pop = bp.use_prediction & bp.is_return & ~branch_flush & ~gc_fetch_pc_override & new_mem_request & (~early_branch_flush); assign ras.push = bp.use_prediction & bp.is_call & ~branch_flush & ~gc_fetch_pc_override & new_mem_request & (~early_branch_flush); @@ -159,8 +168,8 @@ module fetch assign tlb.virtual_address = pc; assign tlb.execute = 1; assign tlb.rnw = 0; - assign tlb.new_request = tlb.ready & (ENABLE_S_MODE & tlb_on); - assign translated_address = (ENABLE_S_MODE & tlb_on) ? tlb.physical_address : pc; + assign tlb.new_request = tlb.ready & (CONFIG.INCLUDE_S_MODE & tlb_on); + assign translated_address = (CONFIG.INCLUDE_S_MODE & tlb_on) ? tlb.physical_address : pc; always_ff @(posedge clk) begin if (new_mem_request) @@ -193,11 +202,11 @@ module fetch assign fetch_attr_fifo.data_in = fetch_attr_next; taiga_fifo #(.DATA_WIDTH($bits(fetch_attributes_t)), .FIFO_DEPTH(NEXT_ID_DEPTH)) - attributes_fifo ( - .clk (clk), - .rst (flush_or_rst), - .fifo (fetch_attr_fifo) - ); + attributes_fifo ( + .clk (clk), + .rst (flush_or_rst), + .fifo (fetch_attr_fifo) + ); assign fetch_attr = fetch_attr_fifo.data_out; @@ -206,43 +215,48 @@ module fetch //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. - generate - for (i = 0; i < NUM_SUB_UNITS; i++) begin - assign unit_ready[i] = fetch_sub[i].ready; - assign unit_data_valid[i] = fetch_sub[i].data_valid; - assign fetch_sub[i].new_request = new_mem_request & sub_unit_address_match[i]; - assign fetch_sub[i].stage1_addr = translated_address; - assign fetch_sub[i].stage2_addr = stage2_phys_address; - assign fetch_sub[i].flush = gc_fetch_flush; - assign unit_data_array[i] = fetch_sub[i].data_out; - end + generate if (CONFIG.INCLUDE_ILOCAL_MEM) begin + assign sub_unit_address_match[BRAM_ID] = bram.address_range_check(translated_address); + assign unit_ready[BRAM_ID] = bram.ready; + assign unit_data_valid[BRAM_ID] = bram.data_valid; + assign bram.new_request = new_mem_request & sub_unit_address_match[BRAM_ID]; + assign bram.stage1_addr = translated_address; + assign bram.stage2_addr = stage2_phys_address; + assign bram.flush = gc_fetch_flush; + assign unit_data_array[BRAM_ID] = bram.data_out; + + ibram i_bram ( + .clk (clk), + .rst (rst), + .fetch_sub (bram), + .instruction_bram (instruction_bram) + ); + end endgenerate + generate if (CONFIG.INCLUDE_ICACHE) begin + assign sub_unit_address_match[ICACHE_ID] = cache.address_range_check(translated_address); + assign unit_ready[ICACHE_ID] = cache.ready; + assign unit_data_valid[ICACHE_ID] = cache.data_valid; + assign cache.new_request = new_mem_request & sub_unit_address_match[ICACHE_ID]; + assign cache.stage1_addr = translated_address; + assign cache.stage2_addr = stage2_phys_address; + assign cache.flush = gc_fetch_flush; + assign unit_data_array[ICACHE_ID] = cache.data_out; + icache #(.CONFIG(CONFIG)) + i_cache ( + .clk (clk), + .rst (rst), + .icache_on (icache_on), + .l1_request (l1_request), + .l1_response (l1_response), + .fetch_sub (cache) + ); + end + endgenerate + assign units_ready = &unit_ready; assign address_valid = |sub_unit_address_match; - generate if (USE_I_SCRATCH_MEM) begin - ibram i_bram ( - .clk (clk), - .rst (rst), - .fetch_sub (fetch_sub[BRAM_ID]), - .instruction_bram (instruction_bram) - ); - assign sub_unit_address_match[BRAM_ID] = translated_address[31:32-SCRATCH_BIT_CHECK] == SCRATCH_ADDR_L[31:32-SCRATCH_BIT_CHECK]; - end - endgenerate - generate if (USE_ICACHE) begin - icache i_cache ( - .clk (clk), - .rst (rst), - .icache_on (icache_on), - .l1_request (l1_request), - .l1_response (l1_response), - .fetch_sub (fetch_sub[ICACHE_ID]) - ); - assign sub_unit_address_match[ICACHE_ID] = translated_address[31:32-MEMORY_BIT_CHECK] == MEMORY_ADDR_L[31:32-MEMORY_BIT_CHECK]; - end - endgenerate - //////////////////////////////////////////////////// //Instruction metada updates logic valid_fetch_result; diff --git a/core/gc_unit.sv b/core/gc_unit.sv index 1805cbf..2e781db 100644 --- a/core/gc_unit.sv +++ b/core/gc_unit.sv @@ -27,6 +27,10 @@ module gc_unit import taiga_types::*; import csr_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -89,9 +93,9 @@ module gc_unit ); //Largest depth for TLBs - localparam int TLB_CLEAR_DEPTH = (DTLB_DEPTH > ITLB_DEPTH) ? DTLB_DEPTH : ITLB_DEPTH; + localparam int TLB_CLEAR_DEPTH = (CONFIG.DTLB.DEPTH > CONFIG.ITLB.DEPTH) ? CONFIG.DTLB.DEPTH : CONFIG.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 > 64 ? TLB_CLEAR_DEPTH : 64) : 64; + localparam int INIT_CLEAR_DEPTH = CONFIG.INCLUDE_S_MODE ? (TLB_CLEAR_DEPTH > 64 ? TLB_CLEAR_DEPTH : 64) : 64; //////////////////////////////////////////////////// //Instructions @@ -301,7 +305,7 @@ module gc_unit end logic ecall_break_exception; assign ecall_break_exception = issue.new_request & (gc_inputs.is_ecall | gc_inputs.is_ebreak); - assign gc_exception.valid = ENABLE_M_MODE & (ecall_break_exception | ls_exception.valid | br_exception.valid | illegal_instruction); + assign gc_exception.valid = CONFIG.INCLUDE_M_MODE & (ecall_break_exception | ls_exception.valid | br_exception.valid | illegal_instruction); //PC determination (trap, flush or return) //Two cycles: on first cycle the processor front end is flushed, @@ -325,7 +329,8 @@ module gc_unit assign csr_inputs.rs1_is_zero = (rs1_addr == 0); assign csr_inputs.rd_is_zero = (rd_addr == 0); - csr_regs csr_registers ( + csr_regs # (.CONFIG(CONFIG)) + csr_registers ( .clk(clk), .rst(rst), .csr_inputs(csr_inputs), .new_request(stage1.is_csr), diff --git a/core/icache.sv b/core/icache.sv index fee0a2b..59df525 100755 --- a/core/icache.sv +++ b/core/icache.sv @@ -26,6 +26,10 @@ module icache import riscv_types::*; import taiga_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -36,18 +40,20 @@ module icache fetch_sub_unit_interface.sub_unit fetch_sub ); + localparam derived_cache_config_t SCONFIG = get_derived_cache_params(CONFIG, CONFIG.ICACHE, CONFIG.ICACHE_ADDR); + logic tag_hit; - logic [ICACHE_WAYS-1:0] tag_hit_way; + logic [CONFIG.ICACHE.WAYS-1:0] tag_hit_way; logic tag_update; - logic [ICACHE_WAYS-1:0] replacement_way; - logic [ICACHE_WAYS-1:0] tag_update_way; + logic [CONFIG.ICACHE.WAYS-1:0] replacement_way; + logic [CONFIG.ICACHE.WAYS-1:0] tag_update_way; - logic [$clog2(ICACHE_LINE_W)-1:0] word_count; + logic [SCONFIG.SUB_LINE_ADDR_W-1:0] word_count; logic is_target_word; logic line_complete; - logic [31:0] data_out [ICACHE_WAYS-1:0]; + logic [31:0] data_out [CONFIG.ICACHE.WAYS-1:0]; logic [31:0] miss_data; logic miss_in_progress; @@ -92,7 +98,7 @@ module icache end //Replacement policy is psuedo random - cycler #(ICACHE_WAYS) replacement_policy ( + cycler #(CONFIG.ICACHE.WAYS) replacement_policy ( .clk (clk), .rst (rst), .en (1'b1), @@ -112,7 +118,7 @@ module icache assign l1_request.data = 0; assign l1_request.rnw = 1; assign l1_request.be = 0; - assign l1_request.size = (ICACHE_LINE_W-1); + assign l1_request.size = 5'(CONFIG.ICACHE.LINE_W-1); assign l1_request.is_amo = 0; assign l1_request.amo = 0; @@ -143,7 +149,8 @@ module icache //////////////////////////////////////////////////// //Tag banks - itag_banks icache_tag_banks ( + itag_banks #(.CONFIG(CONFIG), .SCONFIG(SCONFIG)) + icache_tag_banks ( .clk(clk), .rst(rst | fetch_sub.flush), //clears the read_hit_allowed flag .stage1_addr(fetch_sub.stage1_addr), @@ -158,11 +165,11 @@ module icache //////////////////////////////////////////////////// //Data Banks genvar i; - generate for (i=0; i < ICACHE_WAYS; i++) begin : idata_bank_gen - byte_en_BRAM #(ICACHE_LINES*ICACHE_LINE_W) idata_bank ( + generate for (i=0; i < CONFIG.ICACHE.WAYS; i++) begin : idata_bank_gen + byte_en_BRAM #(CONFIG.ICACHE.LINES*CONFIG.ICACHE.LINE_W) idata_bank ( .clk(clk), - .addr_a(fetch_sub.stage1_addr[2 +: ICACHE_LINE_ADDR_W+ICACHE_SUB_LINE_ADDR_W]), - .addr_b({fetch_sub.stage2_addr[(2+ICACHE_SUB_LINE_ADDR_W) +: ICACHE_LINE_ADDR_W], word_count}), + .addr_a(fetch_sub.stage1_addr[2 +: SCONFIG.LINE_ADDR_W+SCONFIG.SUB_LINE_ADDR_W]), + .addr_b({fetch_sub.stage2_addr[(2+SCONFIG.SUB_LINE_ADDR_W) +: SCONFIG.LINE_ADDR_W], word_count}), .en_a(fetch_sub.new_request), .en_b(tag_update_way[i] & l1_response.data_valid), .be_a('0), @@ -183,7 +190,7 @@ module icache word_count <= word_count + 1; end - assign is_target_word = (fetch_sub.stage2_addr[2 +: ICACHE_SUB_LINE_ADDR_W] == word_count); + assign is_target_word = (fetch_sub.stage2_addr[2 +: SCONFIG.SUB_LINE_ADDR_W] == word_count); always_ff @ (posedge clk) begin if (l1_response.data_valid & is_target_word) @@ -199,7 +206,7 @@ module icache miss_data_valid <= (miss_in_progress & ~miss_aborted_by_flush) & l1_response.data_valid & is_target_word; end - assign line_complete = (l1_response.data_valid && (word_count == $clog2(ICACHE_LINE_W)'(ICACHE_LINE_W-1))); + assign line_complete = (l1_response.data_valid && (word_count == SCONFIG.SUB_LINE_ADDR_W'(CONFIG.ICACHE.LINE_W-1))); always_ff @ (posedge clk) begin if (rst) memory_complete <= 0; @@ -211,7 +218,7 @@ module icache //Output muxing always_comb begin fetch_sub.data_out = miss_data;//zero if not a miss - for (int i = 0; i < ICACHE_WAYS; i++) begin + for (int i = 0; i < CONFIG.ICACHE.WAYS; i++) begin fetch_sub.data_out = fetch_sub.data_out | (data_out[i] & {32{tag_hit_way[i]}}); end end diff --git a/core/illegal_instruction_checker.sv b/core/illegal_instruction_checker.sv index 9e1c516..766cdfc 100644 --- a/core/illegal_instruction_checker.sv +++ b/core/illegal_instruction_checker.sv @@ -24,6 +24,10 @@ module illegal_instruction_checker import taiga_config::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic [31:0] instruction, output logic illegal_instruction @@ -153,11 +157,11 @@ module illegal_instruction_checker assign illegal_instruction = ~( base_legal | - (USE_MUL & mul_legal) | - (USE_DIV & div_legal) | - (USE_AMO & amo_legal) | - (ENABLE_M_MODE & machine_legal) | - (ENABLE_S_MODE & supervisor_legal) + (CONFIG.INCLUDE_MUL & mul_legal) | + (CONFIG.INCLUDE_DIV & div_legal) | + (CONFIG.INCLUDE_AMO & amo_legal) | + (CONFIG.INCLUDE_M_MODE & machine_legal) | + (CONFIG.INCLUDE_S_MODE & supervisor_legal) ); endmodule diff --git a/core/instruction_metadata_and_id_management.sv b/core/instruction_metadata_and_id_management.sv index edb0c4c..b10e944 100644 --- a/core/instruction_metadata_and_id_management.sv +++ b/core/instruction_metadata_and_id_management.sv @@ -26,6 +26,10 @@ module instruction_metadata_and_id_management import riscv_types::*; import taiga_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -58,14 +62,9 @@ module instruction_metadata_and_id_management input logic instruction_issued, 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, - //WB - input wb_packet_t wb_packet [NUM_WB_GROUPS], - output commit_packet_t commit_packet [NUM_WB_GROUPS], + input wb_packet_t wb_packet [CONFIG.NUM_WB_GROUPS], + output commit_packet_t commit_packet [CONFIG.NUM_WB_GROUPS], //Retirer output retire_packet_t retire, @@ -87,12 +86,11 @@ module instruction_metadata_and_id_management (* ramstyle = "MLAB, no_rw_check" *) phys_addr_t phys_addr_table [MAX_IDS]; (* ramstyle = "MLAB, no_rw_check" *) logic [0:0] uses_rd_table [MAX_IDS]; - (* ramstyle = "MLAB, no_rw_check" *) logic [$bits(branch_metadata_t)-1:0] branch_metadata_table [MAX_IDS]; (* ramstyle = "MLAB, no_rw_check" *) logic [$bits(fetch_metadata_t)-1:0] fetch_metadata_table [MAX_IDS]; id_t decode_id; - logic [LOG2_MAX_IDS:0] fetched_count; //MSB used as valid for decode stage + logic [LOG2_MAX_IDS:0] fetched_count; logic [LOG2_MAX_IDS:0] pre_issue_count; logic [LOG2_MAX_IDS:0] pre_issue_count_next; logic [LOG2_MAX_IDS:0] post_issue_count_next; @@ -111,14 +109,6 @@ module instruction_metadata_and_id_management pc_table[pc_id] <= if_pc; end - //////////////////////////////////////////////////// - //Branch metadata table - //Number of read ports = 1 (branch unit) - always_ff @ (posedge clk) begin - if (pc_id_assigned) - branch_metadata_table[pc_id] <= branch_metadata_if; - end - //////////////////////////////////////////////////// //Instruction table //Number of read ports = 1 (decode stage) @@ -235,7 +225,7 @@ module instruction_metadata_and_id_management .clk (clk), .rst (rst), .init_clear (gc_init_clear), - .toggle ('{(instruction_issued_with_rd & (issue.rd_wb_group == 1)), wb_packet[1].valid}), + .toggle ('{(instruction_issued_with_rd & issue.is_multicycle), wb_packet[1].valid}), .toggle_addr ('{issue.id, wb_packet[1].id}), .read_addr (retire_ids), .in_use (id_inuse) @@ -293,17 +283,14 @@ module instruction_metadata_and_id_management assign decode.instruction = instruction_table[decode_id]; assign decode.fetch_metadata = fetch_metadata_table[decode_id]; - //Branch Predictor - assign branch_metadata_ex = branch_metadata_table[branch_id]; - //Writeback/Commit support - phys_addr_t commit_phys_addr [NUM_WB_GROUPS]; + phys_addr_t commit_phys_addr [CONFIG.NUM_WB_GROUPS]; assign commit_phys_addr[0] = issue.phys_rd_addr; - generate for (i = 1; i < NUM_WB_GROUPS; i++) begin + generate for (i = 1; i < CONFIG.NUM_WB_GROUPS; i++) begin assign commit_phys_addr[i] = phys_addr_table[wb_packet[i].id]; end endgenerate - generate for (i = 0; i < NUM_WB_GROUPS; i++) begin + generate for (i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin assign commit_packet[i].id = wb_packet[i].id; assign commit_packet[i].phys_addr = commit_phys_addr[i]; assign commit_packet[i].valid = wb_packet[i].valid & |commit_phys_addr[i]; @@ -311,7 +298,7 @@ module instruction_metadata_and_id_management end endgenerate //Exception Support - generate if (ENABLE_M_MODE) begin + generate if (CONFIG.INCLUDE_M_MODE) begin assign exception_pc = pc_table[exception_id]; end endgenerate diff --git a/core/interfaces.sv b/core/interfaces.sv index a9e3b16..36d0c3a 100755 --- a/core/interfaces.sv +++ b/core/interfaces.sv @@ -28,6 +28,9 @@ interface branch_predictor_interface; id_t if_id; logic new_mem_request; logic [31:0] next_pc; + + id_t pc_id; + logic pc_id_assigned; //Branch Predictor logic [31:0] branch_flush_pc; @@ -38,12 +41,12 @@ interface branch_predictor_interface; logic is_branch; modport branch_predictor ( - input if_pc, if_id, new_mem_request, next_pc, + input if_pc, if_id, new_mem_request, next_pc, pc_id, pc_id_assigned, output branch_flush_pc, predicted_pc, use_prediction, is_return, is_call, is_branch ); modport fetch ( input branch_flush_pc, predicted_pc, use_prediction, is_return, is_call, is_branch, - output if_pc, if_id, new_mem_request, next_pc + output if_pc, if_id, new_mem_request, next_pc, pc_id, pc_id_assigned ); endinterface @@ -91,7 +94,7 @@ interface ras_interface; logic [31:0] new_addr; logic [31:0] addr; - modport branch_unit (output branch_retired); + modport branch_predictor (output branch_retired); modport self (input push, pop, new_addr, branch_fetched, branch_retired, output addr); modport fetch (input addr, output pop, push, new_addr, branch_fetched); endinterface @@ -239,13 +242,27 @@ interface writeback_store_interface; ); endinterface -interface ls_sub_unit_interface #(parameter BASE_ADDR = 32'h00000000, parameter UPPER_BOUND = 32'hFFFFFFFF, parameter BIT_CHECK = 4); +interface ls_sub_unit_interface #(parameter bit [31:0] BASE_ADDR = 32'h00000000, parameter bit [31:0] UPPER_BOUND = 32'hFFFFFFFF); logic data_valid; logic ready; logic new_request; - function address_range_check (input logic[31:0] addr); - return (addr[31:32-BIT_CHECK] == BASE_ADDR[31:32-BIT_CHECK]); + //Based on the lower and upper address ranges, + //find the number of bits needed to uniquely identify this memory range. + //Assumption: address range is aligned to its size + function int unsigned bit_range (); + int unsigned i = 0; + for(; i < 32; i++) begin + if (BASE_ADDR[i] == UPPER_BOUND[i]) + break; + end + return (32 - i); + endfunction + + localparam int unsigned BIT_RANGE = bit_range(); + + function address_range_check (input logic[31:0] addr); + return (addr[31:32-BIT_RANGE] == BASE_ADDR[31:32-BIT_RANGE]); endfunction modport sub_unit (input new_request, output data_valid, ready); @@ -254,7 +271,7 @@ interface ls_sub_unit_interface #(parameter BASE_ADDR = 32'h00000000, parameter endinterface -interface fetch_sub_unit_interface; +interface fetch_sub_unit_interface #(parameter bit [31:0] BASE_ADDR = 32'h00000000, parameter bit [31:0] UPPER_BOUND = 32'hFFFFFFFF); logic [31:0] stage1_addr; logic [31:0] stage2_addr; @@ -264,6 +281,24 @@ interface fetch_sub_unit_interface; logic new_request; logic flush; + //Based on the lower and upper address ranges, + //find the number of bits needed to uniquely identify this memory range. + //Assumption: address range is aligned to its size + function int unsigned bit_range (); + int unsigned i = 0; + for(; i < 32; i++) begin + if (BASE_ADDR[i] == UPPER_BOUND[i]) + break; + end + return (32 - i); + endfunction + + localparam int unsigned BIT_RANGE = bit_range(); + + function address_range_check (input logic[31:0] addr); + return (addr[31:32-BIT_RANGE] == BASE_ADDR[31:32-BIT_RANGE]); + endfunction + modport sub_unit (input stage1_addr, stage2_addr, new_request, flush, output data_out, data_valid, ready); modport fetch (output stage1_addr, stage2_addr, new_request, flush, input data_out, data_valid, ready); @@ -284,21 +319,21 @@ interface unsigned_division_interface #(parameter DATA_WIDTH = 32); modport divider (output remainder, quotient, done, input dividend, dividend_CLZ, divisor, divisor_CLZ, divisor_is_zero, start); endinterface -interface renamer_interface; +interface renamer_interface #(parameter NUM_WB_GROUPS = 2); import taiga_config::*; import riscv_types::*; import taiga_types::*; rs_addr_t rd_addr; rs_addr_t [REGFILE_READ_PORTS-1:0] rs_addr; - rs_wb_group_t rd_wb_group; + logic [$clog2(NUM_WB_GROUPS)-1:0] 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; + logic [REGFILE_READ_PORTS-1:0][$clog2(NUM_WB_GROUPS)-1:0] rs_wb_group; modport renamer ( input rd_addr, rs_addr, rd_wb_group, uses_rd, id, @@ -310,20 +345,20 @@ interface renamer_interface; ); endinterface -interface register_file_issue_interface; +interface register_file_issue_interface #(parameter NUM_WB_GROUPS = 2); import taiga_config::*; import riscv_types::*; import taiga_types::*; //read interface phys_addr_t phys_rs_addr [REGFILE_READ_PORTS]; - logic [LOG2_COMMIT_PORTS-1:0] rs_wb_group [REGFILE_READ_PORTS]; + logic [$clog2(NUM_WB_GROUPS)-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 [$clog2(NUM_WB_GROUPS)-1:0] rd_wb_group; logic issued; modport register_file ( diff --git a/core/itag_banks.sv b/core/itag_banks.sv index c3d7666..ea7883c 100755 --- a/core/itag_banks.sv +++ b/core/itag_banks.sv @@ -25,6 +25,11 @@ module itag_banks import taiga_config::*; import taiga_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG, + parameter derived_cache_config_t SCONFIG = '{default: 0} + ) + ( input logic clk, input logic rst, @@ -32,27 +37,27 @@ module itag_banks input logic[31:0] stage1_addr, input logic[31:0] stage2_addr, - input logic[ICACHE_WAYS-1:0] update_way, + input logic[CONFIG.ICACHE.WAYS-1:0] update_way, input logic update, input logic stage1_adv, output tag_hit, - output logic[ICACHE_WAYS-1:0] tag_hit_way + output logic[CONFIG.ICACHE.WAYS-1:0] tag_hit_way ); - typedef logic [ICACHE_TAG_W : 0] itag_entry_t; + typedef logic [SCONFIG.TAG_W : 0] itag_entry_t; - function logic[ICACHE_TAG_W-1:0] getTag(logic[31:0] addr); - return addr[2+ICACHE_SUB_LINE_ADDR_W+ICACHE_LINE_ADDR_W +: ICACHE_TAG_W]; + function logic[SCONFIG.TAG_W-1:0] getTag(logic[31:0] addr); + return addr[2+SCONFIG.SUB_LINE_ADDR_W+SCONFIG.LINE_ADDR_W +: SCONFIG.TAG_W]; endfunction - function logic[ICACHE_LINE_ADDR_W-1:0] getLineAddr(logic[31:0] addr); - return addr[ICACHE_LINE_ADDR_W + ICACHE_SUB_LINE_ADDR_W + 1 : ICACHE_SUB_LINE_ADDR_W + 2]; + function logic[SCONFIG.LINE_ADDR_W-1:0] getLineAddr(logic[31:0] addr); + return addr[SCONFIG.LINE_ADDR_W + SCONFIG.SUB_LINE_ADDR_W + 1 : SCONFIG.SUB_LINE_ADDR_W + 2]; endfunction logic hit_allowed; - itag_entry_t tag_line[ICACHE_WAYS-1:0]; + itag_entry_t tag_line[CONFIG.ICACHE.WAYS-1:0]; itag_entry_t stage2_tag; assign stage2_tag = {1'b1, getTag(stage2_addr)}; @@ -67,9 +72,9 @@ module itag_banks genvar i; generate - for (i=0; i < ICACHE_WAYS; i++) begin : tag_bank_gen + for (i=0; i < CONFIG.ICACHE.WAYS; i++) begin : tag_bank_gen - tag_bank #(ICACHE_TAG_W+1, ICACHE_LINES) itag_bank (.*, + tag_bank #(SCONFIG.TAG_W+1, CONFIG.ICACHE.LINES) itag_bank (.*, .en_a(stage1_adv), .wen_a('0), .addr_a(getLineAddr(stage1_addr)), .data_in_a('0), .data_out_a(tag_line[i]), diff --git a/core/l1_arbiter.sv b/core/l1_arbiter.sv index 972713f..50fe1c5 100755 --- a/core/l1_arbiter.sv +++ b/core/l1_arbiter.sv @@ -27,6 +27,10 @@ module l1_arbiter import taiga_types::*; import l2_config_and_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -72,12 +76,12 @@ module l1_arbiter //////////////////////////////////////////////////// //Dcache Specific - assign l2.wr_data_push = USE_DCACHE & (push_ready & l1_request[L1_DCACHE_ID].request & ~l1_request[L1_DCACHE_ID].rnw); //Assumes data cache has highest priority + assign l2.wr_data_push = CONFIG.INCLUDE_DCACHE & (push_ready & l1_request[L1_DCACHE_ID].request & ~l1_request[L1_DCACHE_ID].rnw); //Assumes data cache has highest priority assign l2.wr_data = l1_request[L1_DCACHE_ID].data; - assign l2.inv_ack = USE_DTAG_INVALIDATIONS ? l1_response[L1_DCACHE_ID].inv_ack : l2.inv_valid; + assign l2.inv_ack = CONFIG.DCACHE.USE_EXTERNAL_INVALIDATIONS ? l1_response[L1_DCACHE_ID].inv_ack : l2.inv_valid; assign l1_response[L1_DCACHE_ID].inv_addr = l2.inv_addr; - assign l1_response[L1_DCACHE_ID].inv_valid = USE_DTAG_INVALIDATIONS & l2.inv_valid; + assign l1_response[L1_DCACHE_ID].inv_valid = CONFIG.DCACHE.USE_EXTERNAL_INVALIDATIONS & l2.inv_valid; //////////////////////////////////////////////////// //Interface mapping diff --git a/core/load_store_queue.sv b/core/load_store_queue.sv index 34c1ce4..6424c14 100644 --- a/core/load_store_queue.sv +++ b/core/load_store_queue.sv @@ -124,7 +124,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit //Priority is for loads over stores. //A store will be selected only if either no loads are ready, OR if the store queue is full and a store is ready - assign load_selected = lq_output_valid & ~store_conflict & ~(sq_full & sq_output_valid); + assign load_selected = lq_output_valid & ~store_conflict;// & ~(sq_full & sq_output_valid); assign lsq.transaction_ready = (lq_output_valid & ~store_conflict) | sq_output_valid; assign load_ack = lsq.accepted & load_selected; @@ -150,7 +150,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit //////////////////////////////////////////////////// //Trace Interface generate if (ENABLE_TRACE_INTERFACE) begin - assign tr_possible_load_conflict_delay = lq_output_valid & store_conflict; + assign tr_possible_load_conflict_delay = lq_output_valid & (store_conflict | (sq_full & sq_output_valid)); end endgenerate diff --git a/core/load_store_unit.sv b/core/load_store_unit.sv index 4898caf..af7caec 100755 --- a/core/load_store_unit.sv +++ b/core/load_store_unit.sv @@ -26,6 +26,10 @@ module load_store_unit import riscv_types::*; import taiga_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -69,20 +73,20 @@ module load_store_unit output logic tr_load_conflict_delay ); - localparam NUM_SUB_UNITS = USE_D_SCRATCH_MEM+USE_BUS+USE_DCACHE; + localparam NUM_SUB_UNITS = int'(CONFIG.INCLUDE_DLOCAL_MEM) + int'(CONFIG.INCLUDE_PERIPHERAL_BUS) + int'(CONFIG.INCLUDE_DCACHE); localparam NUM_SUB_UNITS_W = (NUM_SUB_UNITS == 1) ? 1 : $clog2(NUM_SUB_UNITS); localparam BRAM_ID = 0; - localparam BUS_ID = USE_D_SCRATCH_MEM; - localparam DCACHE_ID = USE_D_SCRATCH_MEM+USE_BUS; + localparam BUS_ID = int'(CONFIG.INCLUDE_DLOCAL_MEM); + localparam DCACHE_ID = int'(CONFIG.INCLUDE_DLOCAL_MEM) + int'(CONFIG.INCLUDE_PERIPHERAL_BUS); //Should be equal to pipeline depth of longest load/store subunit - localparam ATTRIBUTES_DEPTH = USE_DCACHE ? 2 : 1; + localparam ATTRIBUTES_DEPTH = CONFIG.INCLUDE_DCACHE ? 2 : 1; data_access_shared_inputs_t shared_inputs; - ls_sub_unit_interface #(.BASE_ADDR(SCRATCH_ADDR_L), .UPPER_BOUND(SCRATCH_ADDR_H), .BIT_CHECK(SCRATCH_BIT_CHECK)) bram(); - ls_sub_unit_interface #(.BASE_ADDR(BUS_ADDR_L), .UPPER_BOUND(BUS_ADDR_H), .BIT_CHECK(BUS_BIT_CHECK)) bus(); - ls_sub_unit_interface #(.BASE_ADDR(MEMORY_ADDR_L), .UPPER_BOUND(MEMORY_ADDR_H), .BIT_CHECK(MEMORY_BIT_CHECK)) cache(); + ls_sub_unit_interface #(.BASE_ADDR(CONFIG.DLOCAL_MEM_ADDR.L), .UPPER_BOUND(CONFIG.DLOCAL_MEM_ADDR.H)) bram(); + ls_sub_unit_interface #(.BASE_ADDR(CONFIG.PERIPHERAL_BUS_ADDR.L), .UPPER_BOUND(CONFIG.PERIPHERAL_BUS_ADDR.H)) bus(); + ls_sub_unit_interface #(.BASE_ADDR(CONFIG.DCACHE_ADDR.L), .UPPER_BOUND(CONFIG.DCACHE_ADDR.H)) cache(); logic units_ready; logic unit_switch_stall; @@ -129,7 +133,7 @@ module load_store_unit //////////////////////////////////////////////////// //Alignment Exception -generate if (ENABLE_M_MODE) begin +generate if (CONFIG.INCLUDE_M_MODE) begin always_comb begin case(ls_inputs.fn3) @@ -261,7 +265,7 @@ endgenerate //////////////////////////////////////////////////// //Unit Instantiation - generate if (USE_D_SCRATCH_MEM) begin + generate if (CONFIG.INCLUDE_DLOCAL_MEM) begin assign sub_unit_address_match[BRAM_ID] = bram.address_range_check(shared_inputs.addr); assign bram.new_request = sub_unit_address_match[BRAM_ID] & issue_request; @@ -279,14 +283,14 @@ endgenerate end endgenerate - generate if (USE_BUS) begin + generate if (CONFIG.INCLUDE_PERIPHERAL_BUS) begin assign sub_unit_address_match[BUS_ID] = bus.address_range_check(shared_inputs.addr); assign bus.new_request = sub_unit_address_match[BUS_ID] & issue_request; assign unit_ready[BUS_ID] = bus.ready; assign unit_data_valid[BUS_ID] = bus.data_valid; - if(BUS_TYPE == AXI_BUS) + if(CONFIG.PERIPHERAL_BUS_TYPE == AXI_BUS) axi_master axi_bus ( .clk (clk), .rst (rst), @@ -297,7 +301,7 @@ endgenerate .ls (bus) ); //Lower two bits of fn3 match AXI specification for request size (byte/halfword/word) - else if (BUS_TYPE == WISHBONE_BUS) + else if (CONFIG.PERIPHERAL_BUS_TYPE == WISHBONE_BUS) wishbone_master wishbone_bus ( .clk (clk), .rst (rst), @@ -306,7 +310,7 @@ endgenerate .ls_inputs (shared_inputs), .ls (bus) ); - else if (BUS_TYPE == AVALON_BUS) begin + else if (CONFIG.PERIPHERAL_BUS_TYPE == AVALON_BUS) begin avalon_master avalon_bus ( .clk (clk), .rst (rst), @@ -319,14 +323,15 @@ endgenerate end endgenerate - generate if (USE_DCACHE) begin + generate if (CONFIG.INCLUDE_DCACHE) begin assign sub_unit_address_match[DCACHE_ID] = cache.address_range_check(shared_inputs.addr); assign cache.new_request = sub_unit_address_match[DCACHE_ID] & issue_request; assign unit_ready[DCACHE_ID] = cache.ready; assign unit_data_valid[DCACHE_ID] = cache.data_valid; - dcache data_cache ( + dcache # (.CONFIG(CONFIG)) + data_cache ( .clk (clk), .rst (rst), .dcache_on (dcache_on), diff --git a/core/ras.sv b/core/ras.sv index 731d148..81d80be 100755 --- a/core/ras.sv +++ b/core/ras.sv @@ -26,6 +26,10 @@ module ras import riscv_types::*; import taiga_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -34,9 +38,9 @@ module ras ras_interface.self ras ); - (* ramstyle = "MLAB, no_rw_check" *) logic[31:0] lut_ram [RAS_DEPTH]; + (* ramstyle = "MLAB, no_rw_check" *) logic[31:0] lut_ram [CONFIG.BP.RAS_ENTRIES]; - localparam RAS_DEPTH_W = $clog2(RAS_DEPTH); + localparam RAS_DEPTH_W = $clog2(CONFIG.BP.RAS_ENTRIES); logic [RAS_DEPTH_W-1:0] read_index; logic [RAS_DEPTH_W-1:0] new_index; fifo_interface #(.DATA_WIDTH(RAS_DEPTH_W)) ri_fifo(); diff --git a/core/register_file.sv b/core/register_file.sv index be65832..b14c2b3 100755 --- a/core/register_file.sv +++ b/core/register_file.sv @@ -26,6 +26,10 @@ module register_file import riscv_types::*; import taiga_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -36,13 +40,13 @@ module register_file register_file_issue_interface.register_file rf_issue, //Writeback - input commit_packet_t commit [NUM_WB_GROUPS] + input commit_packet_t commit [CONFIG.NUM_WB_GROUPS] ); typedef logic [31:0] rs_data_set_t [REGFILE_READ_PORTS]; - rs_data_set_t rs_data_set [NUM_WB_GROUPS]; + rs_data_set_t rs_data_set [CONFIG.NUM_WB_GROUPS]; typedef logic inuse_t [REGFILE_READ_PORTS]; - inuse_t phys_reg_inuse_set [NUM_WB_GROUPS]; + inuse_t phys_reg_inuse_set [CONFIG.NUM_WB_GROUPS]; genvar i; //////////////////////////////////////////////////// @@ -82,7 +86,7 @@ module register_file //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 + generate for (i = 0; i < CONFIG.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), @@ -107,7 +111,7 @@ module register_file //////////////////////////////////////////////////// //Assertions - for (genvar i = 0; i < NUM_WB_GROUPS; i++) begin : write_to_rd_zero_assertion + for (genvar i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin : write_to_rd_zero_assertion assert property (@(posedge clk) disable iff (rst) (commit[i].valid) |-> (commit[i].phys_addr != 0)) else $error("write to register zero"); end diff --git a/core/renamer.sv b/core/renamer.sv index 2ac55bd..388b3fa 100644 --- a/core/renamer.sv +++ b/core/renamer.sv @@ -25,6 +25,10 @@ module renamer import taiga_config::*; import taiga_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -86,7 +90,7 @@ module renamer //During post reset init, initialize rd_to_phys with in-use list (lower 32 registers) typedef struct packed{ phys_addr_t phys_addr; - rs_wb_group_t wb_group; + logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] wb_group; } spec_table_t; spec_table_t spec_table_next; spec_table_t spec_table_old; diff --git a/core/taiga.sv b/core/taiga.sv index a801b34..e38c62a 100755 --- a/core/taiga.sv +++ b/core/taiga.sv @@ -29,6 +29,10 @@ module taiga import riscv_types::*; import taiga_types::*; + #( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG + ) + ( input logic clk, input logic rst, @@ -48,6 +52,41 @@ module taiga input logic interrupt ); + //////////////////////////////////////////////////// + //Unit ID Assignment + //Generate Issue IDs based on configuration options + //Then assigned to a struct for ease in passing to sub modules + + //Units with writeback + localparam int unsigned ALU_UNIT_ID = 32'd0; + localparam int unsigned LS_UNIT_ID = 32'd1; + localparam int unsigned GC_UNIT_ID = 32'd2; + localparam int unsigned MUL_UNIT_ID = GC_UNIT_ID + int'(CONFIG.INCLUDE_MUL); + localparam int unsigned DIV_UNIT_ID = MUL_UNIT_ID + int'(CONFIG.INCLUDE_DIV); + //Non-writeback units + localparam int unsigned BRANCH_UNIT_ID = DIV_UNIT_ID + 1; + + //Total number of units + localparam int unsigned NUM_UNITS = BRANCH_UNIT_ID + 1; + + localparam unit_id_param_t UNIT_IDS = '{ + ALU : ALU_UNIT_ID, + LS : LS_UNIT_ID, + CSR : GC_UNIT_ID, + MUL : MUL_UNIT_ID, + DIV : DIV_UNIT_ID, + BR : BRANCH_UNIT_ID + }; + + //////////////////////////////////////////////////// + //Writeback Port Assignment + // + localparam int unsigned NUM_WB_UNITS_GROUP_1 = 1;//ALU + localparam int unsigned NUM_WB_UNITS_GROUP_2 = 2 + int'(CONFIG.INCLUDE_MUL) + int'(CONFIG.INCLUDE_DIV);//LS + CSR + localparam int unsigned NUM_WB_UNITS = NUM_WB_UNITS_GROUP_1 + NUM_WB_UNITS_GROUP_2; + + //////////////////////////////////////////////////// + //Connecting Signals l1_arbiter_request_interface l1_request[L1_CONNECTIONS-1:0](); l1_arbiter_return_interface l1_response[L1_CONNECTIONS-1:0](); logic sc_complete; @@ -63,7 +102,7 @@ module taiga ras_interface ras(); issue_packet_t issue; - register_file_issue_interface rf_issue(); + register_file_issue_interface #(.NUM_WB_GROUPS(CONFIG.NUM_WB_GROUPS)) rf_issue(); alu_inputs_t alu_inputs; @@ -106,23 +145,19 @@ module taiga 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; + phys_addr_t decode_phys_rd_addr; //ID freeing retire_packet_t retire; id_t retire_ids [RETIRE_PORTS]; logic retire_port_valid [RETIRE_PORTS]; //Writeback - wb_packet_t wb_packet [NUM_WB_GROUPS]; - commit_packet_t commit_packet [NUM_WB_GROUPS]; + wb_packet_t wb_packet [CONFIG.NUM_WB_GROUPS]; + commit_packet_t commit_packet [CONFIG.NUM_WB_GROUPS]; //Exception id_t exception_id; logic [31:0] exception_pc; - renamer_interface decode_rename_interface (); + renamer_interface #(.NUM_WB_GROUPS(CONFIG.NUM_WB_GROUPS)) decode_rename_interface (); //Global Control logic gc_init_clear; @@ -181,18 +216,16 @@ module taiga logic tr_rs2_forwarding_needed; logic tr_rs1_and_rs2_forwarding_needed; - unit_id_t tr_num_instructions_completing; - id_t tr_num_instructions_in_flight; - id_t tr_num_of_instructions_pending_writeback; //////////////////////////////////////////////////// //Implementation //////////////////////////////////////////////////// // Memory Interface - generate if (ENABLE_S_MODE || USE_ICACHE || USE_DCACHE) + generate if (CONFIG.INCLUDE_S_MODE || CONFIG.INCLUDE_ICACHE || CONFIG.INCLUDE_DCACHE) - l1_arbiter arb( + l1_arbiter #(.CONFIG(CONFIG)) + arb( .clk (clk), .rst (rst), .l2 (l2), @@ -206,7 +239,8 @@ module taiga //////////////////////////////////////////////////// // ID support - instruction_metadata_and_id_management id_block ( + instruction_metadata_and_id_management #(.CONFIG(CONFIG)) + id_block ( .clk (clk), .rst (rst), .gc_init_clear (gc_init_clear), @@ -228,9 +262,6 @@ module taiga .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), @@ -243,14 +274,16 @@ module taiga //////////////////////////////////////////////////// // Fetch - fetch fetch_block ( + fetch # (.CONFIG(CONFIG)) + 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), + .gc_fetch_pc (gc_fetch_pc), + .pc_id (pc_id), .pc_id_available (pc_id_available), .pc_id_assigned (pc_id_assigned), .fetch_complete (fetch_complete), @@ -271,16 +304,17 @@ module taiga .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) + branch_predictor #(.CONFIG(CONFIG)) + bp_block ( + .clk (clk), + .rst (rst), + .bp (bp), + .br_results (br_results), + .ras (ras) ); - ras ras_block( + ras # (.CONFIG(CONFIG)) + ras_block( .clk (clk), .rst (rst), .gc_fetch_flush (gc_fetch_flush), @@ -288,9 +322,10 @@ module taiga .ras (ras) ); - generate if (ENABLE_S_MODE) begin + generate if (CONFIG.INCLUDE_S_MODE) begin - tlb_lut_ram #(ITLB_WAYS, ITLB_DEPTH) i_tlb ( + tlb_lut_ram #(.WAYS(CONFIG.ITLB.WAYS), .DEPTH(CONFIG.ITLB.DEPTH)) + i_tlb ( .clk (clk), .rst (rst), .abort_request (gc_fetch_flush | early_branch_flush), @@ -319,7 +354,8 @@ module taiga //////////////////////////////////////////////////// //Renamer - renamer renamer_block ( + renamer #(.CONFIG(CONFIG)) + renamer_block ( .clk (clk), .rst (rst), .gc_init_clear (gc_init_clear), @@ -332,7 +368,12 @@ module taiga //////////////////////////////////////////////////// //Decode/Issue - decode_and_issue decode_and_issue_block ( + decode_and_issue #( + .CONFIG (CONFIG), + .NUM_UNITS (NUM_UNITS), + .UNIT_IDS (UNIT_IDS) + ) + decode_and_issue_block ( .clk (clk), .rst (rst), .pc_id_available (pc_id_available), @@ -382,7 +423,8 @@ module taiga //////////////////////////////////////////////////// //Register File - register_file register_file_block ( + register_file #(.CONFIG(CONFIG)) + register_file_block ( .clk (clk), .rst (rst), .gc_init_clear (gc_init_clear), @@ -392,16 +434,14 @@ module taiga //////////////////////////////////////////////////// //Execution Units - branch_unit branch_unit_block ( + branch_unit #(.CONFIG(CONFIG)) + branch_unit_block ( .clk (clk), .rst (rst), - .issue (unit_issue[BRANCH_UNIT_ID]), + .issue (unit_issue[UNIT_IDS.BR]), .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), @@ -416,15 +456,16 @@ module taiga .clk (clk), .rst (rst), .alu_inputs (alu_inputs), - .issue (unit_issue[ALU_UNIT_ID]), - .wb (unit_wb[ALU_UNIT_ID]) + .issue (unit_issue[UNIT_IDS.ALU]), + .wb (unit_wb[UNIT_IDS.ALU]) ); - load_store_unit load_store_unit_block ( + load_store_unit #(.CONFIG(CONFIG)) + load_store_unit_block ( .clk (clk), .rst (rst), .ls_inputs (ls_inputs), - .issue (unit_issue[LS_UNIT_ID]), + .issue (unit_issue[UNIT_IDS.LS]), .dcache_on (1'b1), .clear_reservation (1'b0), .tlb (dtlb), @@ -445,12 +486,13 @@ module taiga .ls_is_idle (ls_is_idle), .ls_exception (ls_exception), .ls_exception_is_store (ls_exception_is_store), - .wb (unit_wb[LS_UNIT_ID]), + .wb (unit_wb[UNIT_IDS.LS]), .tr_load_conflict_delay (tr_load_conflict_delay) ); - generate if (ENABLE_S_MODE) begin - tlb_lut_ram #(DTLB_WAYS, DTLB_DEPTH) d_tlb ( + generate if (CONFIG.INCLUDE_S_MODE) begin + tlb_lut_ram #(.WAYS(CONFIG.DTLB.WAYS), .DEPTH(CONFIG.DTLB.DEPTH)) + d_tlb ( .clk (clk), .rst (rst), .abort_request (1'b0), @@ -476,10 +518,11 @@ module taiga end endgenerate - gc_unit gc_unit_block ( + gc_unit #(.CONFIG(CONFIG)) + gc_unit_block ( .clk (clk), .rst (rst), - .issue (unit_issue[GC_UNIT_ID]), + .issue (unit_issue[UNIT_IDS.CSR]), .gc_inputs (gc_inputs), .gc_flush_required (gc_flush_required), .branch_flush (branch_flush), @@ -509,33 +552,41 @@ module taiga .gc_fetch_pc (gc_fetch_pc), .ls_is_idle (ls_is_idle), .post_issue_count (post_issue_count), - .wb (unit_wb[GC_UNIT_ID]) + .wb (unit_wb[UNIT_IDS.CSR]) ); - generate if (USE_MUL) + generate if (CONFIG.INCLUDE_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]) + .issue (unit_issue[UNIT_IDS.MUL]), + .wb (unit_wb[UNIT_IDS.MUL]) ); endgenerate - generate if (USE_DIV) + generate if (CONFIG.INCLUDE_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]) + .issue (unit_issue[UNIT_IDS.DIV]), + .wb (unit_wb[UNIT_IDS.DIV]) ); endgenerate //////////////////////////////////////////////////// //Writeback - writeback writeback_block ( + //First writeback port: ALU + //Second writeback port: LS, CSR, [MUL], [DIV] + localparam int unsigned NUM_UNITS_PER_PORT [CONFIG.NUM_WB_GROUPS] = '{NUM_WB_UNITS_GROUP_1, NUM_WB_UNITS_GROUP_2}; + writeback #( + .CONFIG (CONFIG), + .NUM_UNITS (NUM_UNITS_PER_PORT), + .NUM_WB_UNITS (NUM_WB_UNITS) + ) + writeback_block ( .clk (clk), .rst (rst), .wb_packet (wb_packet), @@ -587,9 +638,6 @@ module taiga tr.events.rs1_forwarding_needed <= tr_rs1_forwarding_needed; tr.events.rs2_forwarding_needed <= tr_rs2_forwarding_needed; tr.events.rs1_and_rs2_forwarding_needed <= tr_rs1_and_rs2_forwarding_needed; - tr.events.num_instructions_completing <= tr_num_instructions_completing; - tr.events.num_instructions_in_flight <= tr_num_instructions_in_flight; - tr.events.num_of_instructions_pending_writeback <= tr_num_of_instructions_pending_writeback; tr.instruction_pc_dec <= tr_instruction_pc_dec; tr.instruction_data_dec <= tr_instruction_data_dec; end diff --git a/core/taiga_config.sv b/core/taiga_config.sv index 9078f61..423f010 100755 --- a/core/taiga_config.sv +++ b/core/taiga_config.sv @@ -25,126 +25,202 @@ package taiga_config; //////////////////////////////////////////////////// //Vendor Selection localparam FPGA_VENDOR = "xilinx"; //xilinx or intel - //////////////////////////////////////////////////// - //Privileged ISA Options - - //Enable Machine level privilege spec - localparam ENABLE_M_MODE = 1; - //Enable Supervisor level privilege spec - localparam ENABLE_S_MODE = 1; - //Enable User level privilege spec - localparam ENABLE_U_MODE = 1; - - localparam MACHINE_IMPLEMENTATION_ID = 0; - localparam CPU_ID = 0;//32-bicd ..t value - - //CSR counter width (33-64 bits): 48-bits --> 32 days @ 100MHz - localparam COUNTER_W = 33; //////////////////////////////////////////////////// - //ISA Options - - //Multiply and Divide Inclusion - localparam USE_MUL = 1; - localparam USE_DIV = 1; - - //Enable Atomic extension (cache operations only) - localparam USE_AMO = 0; - + //CSR Options + typedef struct packed { + bit [31:0] MACHINE_IMPLEMENTATION_ID; + bit [31:0] CPU_ID; + bit [31:0] RESET_VEC; //PC value on reset + int unsigned COUNTER_W; //CSR counter width (33-64 bits): 48-bits --> 32 days @ 100MHz + } csr_config_t; //////////////////////////////////////////////////// - //Memory Sources - //Must select at least one source for instruction and data interfaces + //Cache Options + //Size in bytes: (LINES * WAYS * LINE_W * 4) + //For optimal BRAM packing, LINES should not be less than 512 + typedef struct packed { + int unsigned LINES; + int unsigned LINE_W;// In words + int unsigned WAYS; + bit USE_EXTERNAL_INVALIDATIONS; + } cache_config_t; - //Local memory - localparam USE_I_SCRATCH_MEM = 1; - localparam USE_D_SCRATCH_MEM = 1; + typedef struct packed { + int unsigned LINE_ADDR_W; + int unsigned SUB_LINE_ADDR_W; + int unsigned TAG_W; + } derived_cache_config_t; - //Peripheral bus + //Memory range [L, H] + //Address range is inclusive and must be aligned to its size + typedef struct packed { + bit [31:0] L; + bit [31:0] H; + } memory_config_t; + + //////////////////////////////////////////////////// + //Branch Predictor Options + typedef struct packed { + int unsigned WAYS; + int unsigned ENTRIES;//min512 + int unsigned RAS_ENTRIES; + } branch_predictor_config_t; + + //////////////////////////////////////////////////// + //Bus Options typedef enum { AXI_BUS, AVALON_BUS, WISHBONE_BUS - } bus_type_t; - - localparam USE_BUS = 1; - localparam bus_type_t BUS_TYPE = AXI_BUS; - - //Caches - localparam USE_DCACHE = 0; - localparam USE_ICACHE = 0; - + } peripheral_bus_type_t; //////////////////////////////////////////////////// - //Address space - localparam SCRATCH_ADDR_L = 32'h80000000; - localparam SCRATCH_ADDR_H = 32'h8001FFFF; - localparam SCRATCH_BIT_CHECK = 4; + //TLB Options + typedef struct packed { + int unsigned WAYS; + int unsigned DEPTH; + } tlb_config_t; - localparam MEMORY_ADDR_L = 32'h40000000; - localparam MEMORY_ADDR_H = 32'h4FFFFFFF; - localparam MEMORY_BIT_CHECK = 4; + typedef struct packed { + //ISA options + bit INCLUDE_M_MODE; + bit INCLUDE_S_MODE; + bit INCLUDE_U_MODE; + bit INCLUDE_MUL; + bit INCLUDE_DIV; + bit INCLUDE_AMO; //Enable Atomic extension (cache operations only) + csr_config_t CSRS; + //Memory Options + bit INCLUDE_ICACHE; + cache_config_t ICACHE; + memory_config_t ICACHE_ADDR; + tlb_config_t ITLB; + bit INCLUDE_DCACHE; + cache_config_t DCACHE; + memory_config_t DCACHE_ADDR; + tlb_config_t DTLB; + bit INCLUDE_ILOCAL_MEM; + memory_config_t ILOCAL_MEM_ADDR; + bit INCLUDE_DLOCAL_MEM; + memory_config_t DLOCAL_MEM_ADDR; + bit INCLUDE_PERIPHERAL_BUS; + memory_config_t PERIPHERAL_BUS_ADDR; + peripheral_bus_type_t PERIPHERAL_BUS_TYPE; + //Branch Predictor Options + bit INCLUDE_BRANCH_PREDICTOR; + branch_predictor_config_t BP; + //Writeback Options + int unsigned NUM_WB_GROUPS; + } cpu_config_t; - localparam BUS_ADDR_L = 32'h60000000; - localparam BUS_ADDR_H = 32'h6FFFFFFF; - localparam BUS_BIT_CHECK = 4; + //Function to generate derived cache parameters + //Tag width based off of memory size and cache parameters + function derived_cache_config_t get_derived_cache_params (input cpu_config_t cpu, input cache_config_t cache, input memory_config_t addr); + return '{ + LINE_ADDR_W : $clog2(cache.LINES), + SUB_LINE_ADDR_W : $clog2(cache.LINE_W), + TAG_W : $clog2(64'(addr.H)-64'(addr.L)+1) - $clog2(cache.LINES) - $clog2(cache.LINE_W) - 2 + }; + endfunction - //PC address on reset - localparam bit[31:0] RESET_VEC = 32'h80000000; + + localparam cpu_config_t EXAMPLE_CONFIG = '{ + //ISA options + INCLUDE_M_MODE : 1, + INCLUDE_S_MODE : 1, + INCLUDE_U_MODE : 1, + INCLUDE_MUL : 1, + INCLUDE_DIV : 1, + INCLUDE_AMO : 0, + CSRS : '{ + MACHINE_IMPLEMENTATION_ID : 0, + CPU_ID : 0, + RESET_VEC : 32'h80000000, + COUNTER_W : 33 + }, + //Memory Options + INCLUDE_ICACHE : 0, + ICACHE_ADDR : '{ + L: 32'h40000000, + H: 32'h4FFFFFFF + }, + ICACHE : '{ + LINES : 512, + LINE_W : 4, + WAYS : 2, + USE_EXTERNAL_INVALIDATIONS : 0 + }, + ITLB : '{ + WAYS : 2, + DEPTH : 64 + }, + INCLUDE_DCACHE : 0, + DCACHE_ADDR : '{ + L: 32'h40000000, + H: 32'h4FFFFFFF + }, + DCACHE : '{ + LINES : 512, + LINE_W : 4, + WAYS : 2, + USE_EXTERNAL_INVALIDATIONS : 0 + }, + DTLB : '{ + WAYS : 2, + DEPTH : 64 + }, + INCLUDE_ILOCAL_MEM : 1, + ILOCAL_MEM_ADDR : '{ + L : 32'h80000000, + H : 32'h8FFFFFFF + }, + INCLUDE_DLOCAL_MEM : 1, + DLOCAL_MEM_ADDR : '{ + L : 32'h80000000, + H : 32'h8FFFFFFF + }, + INCLUDE_PERIPHERAL_BUS : 1, + PERIPHERAL_BUS_ADDR : '{ + L : 32'h60000000, + H : 32'h6FFFFFFF + }, + PERIPHERAL_BUS_TYPE : AXI_BUS, + //Branch Predictor Options + INCLUDE_BRANCH_PREDICTOR : 1, + BP : '{ + WAYS : 2, + ENTRIES : 512, + RAS_ENTRIES : 8 + }, + NUM_WB_GROUPS : 2 + }; + + //////////////////////////////////////////////////// + //Unit IDs + typedef struct packed { + int unsigned ALU; + int unsigned LS; + int unsigned CSR; + int unsigned MUL; + int unsigned DIV; + int unsigned BR; + } unit_id_param_t; + + localparam unit_id_param_t EXAMPLE_UNIT_IDS = '{ + ALU : 0, + LS : 1, + CSR : 2, + MUL : 3, + DIV : 4, + BR : 5 + }; //////////////////////////////////////////////////// //Bus Options parameter C_M_AXI_ADDR_WIDTH = 32; //Kept as parameter, due to localparam failing with scripted IP packaging parameter C_M_AXI_DATA_WIDTH = 32; //Kept as parameter, due to localparam failing with scripted IP packaging - - //////////////////////////////////////////////////// - //Instruction Cache Options - //Size in bytes: (ICACHE_LINES * ICACHE_WAYS * ICACHE_LINE_W * 4) - //For optimal BRAM packing, lines should not be less than 512 - localparam ICACHE_LINES = 512; - localparam ICACHE_WAYS = 2; - localparam ICACHE_LINE_ADDR_W = $clog2(ICACHE_LINES); - localparam ICACHE_LINE_W = 4; //In words - localparam ICACHE_SUB_LINE_ADDR_W = $clog2(ICACHE_LINE_W); - localparam ICACHE_TAG_W = $clog2(64'(MEMORY_ADDR_H)-64'(MEMORY_ADDR_L)+1) - ICACHE_LINE_ADDR_W - ICACHE_SUB_LINE_ADDR_W - 2; - - - //////////////////////////////////////////////////// - //Data Cache Options - //Size in bytes: (DCACHE_LINES * DCACHE_WAYS * DCACHE_LINE_W * 4) - //For optimal BRAM packing, lines should not be less than 512 - localparam DCACHE_LINES = 512; - localparam DCACHE_WAYS = 2; - localparam DCACHE_LINE_ADDR_W = $clog2(DCACHE_LINES); - localparam DCACHE_LINE_W = 4; //In words - localparam DCACHE_SUB_LINE_ADDR_W = $clog2(DCACHE_LINE_W); - localparam DCACHE_TAG_W = $clog2(64'(MEMORY_ADDR_H)-64'(MEMORY_ADDR_L)+1) - DCACHE_LINE_ADDR_W - DCACHE_SUB_LINE_ADDR_W - 2; - - localparam USE_DTAG_INVALIDATIONS = 0; - - - //////////////////////////////////////////////////// - //Instruction TLB Options - localparam ITLB_WAYS = 2; - localparam ITLB_DEPTH = 32; - - - //////////////////////////////////////////////////// - //Data TLB Options - localparam DTLB_WAYS = 2; - localparam DTLB_DEPTH = 32; - /////////////////////////////////////////////////// - - - //////////////////////////////////////////////////// - //Branch Predictor Options - localparam USE_BRANCH_PREDICTOR = 1; - localparam BRANCH_PREDICTOR_WAYS = 2; - localparam BRANCH_TABLE_ENTRIES = 512; //min 512 - localparam RAS_DEPTH = 8; - - //////////////////////////////////////////////////// //ID limit //MAX_IDS restricted to a power of 2 @@ -154,7 +230,7 @@ package taiga_config; //Number of commit ports localparam RETIRE_PORTS = 2; //min 1. (Non-powers of two supported) > 1 is recommended to allow stores to commit sooner localparam REGFILE_READ_PORTS = 2; //min 2, for RS1 and RS2. (Non-powers of two supported) - typedef enum logic { + typedef enum bit { RS1 = 0, RS2 = 1 } rs1_index_t; @@ -167,41 +243,13 @@ package taiga_config; //////////////////////////////////////////////////// //L1 Arbiter IDs - localparam L1_CONNECTIONS = 4;//USE_ICACHE + USE_DCACHE + ENABLE_S_MODE*2; - localparam L1_DCACHE_ID = 0; - localparam L1_DMMU_ID = 1;//ENABLE_S_MODE; - 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 - localparam NUM_WB_UNITS_GROUP_2 = 2 + USE_MUL + USE_DIV;//LS + CSR - localparam NUM_WB_UNITS = NUM_WB_UNITS_GROUP_1 + NUM_WB_UNITS_GROUP_2; - localparam NUM_UNITS = NUM_WB_UNITS + 1;//Branch - - localparam NUM_WB_GROUPS = 2; - localparam int NUM_WB_UNITS_GROUP [2] = '{NUM_WB_UNITS_GROUP_1, NUM_WB_UNITS_GROUP_2}; - localparam int CUMULATIVE_NUM_WB_UNITS_GROUP [2] = '{0, NUM_WB_UNITS_GROUP_1}; - - localparam ALU_UNIT_ID = 0; - localparam LS_UNIT_ID = 1; - localparam DIV_UNIT_ID = LS_UNIT_ID + USE_DIV; - localparam MUL_UNIT_ID = DIV_UNIT_ID + USE_MUL; - localparam GC_UNIT_ID = MUL_UNIT_ID + 1; - //Non-writeback units - localparam BRANCH_UNIT_ID = GC_UNIT_ID + 1; - - //Writeback group 1 - localparam ALU_UNIT_WB1_ID = 0; - - //Writeback group 2 - localparam LS_UNIT_WB2_ID = 0; - localparam DIV_UNIT_WB2_ID = LS_UNIT_WB2_ID + USE_DIV; - localparam MUL_UNIT_WB2_ID = DIV_UNIT_WB2_ID + USE_MUL; - localparam GC_UNIT_WB2_ID = MUL_UNIT_WB2_ID + 1; - - + localparam L1_CONNECTIONS = 4; + typedef enum bit [1:0] { + L1_DCACHE_ID = 0, + L1_DMMU_ID = 1, + L1_ICACHE_ID = 2, + L1_IMMU_ID = 3 + } l1_id_t; //////////////////////////////////////////////////// //Debug Parameters diff --git a/core/taiga_types.sv b/core/taiga_types.sv index 3c2434c..2de98b6 100755 --- a/core/taiga_types.sv +++ b/core/taiga_types.sv @@ -25,17 +25,13 @@ package taiga_types; import riscv_types::*; localparam LOG2_RETIRE_PORTS = $clog2(RETIRE_PORTS); - localparam WB_UNITS_WIDTH = $clog2(NUM_WB_UNITS); - localparam LOG2_COMMIT_PORTS = $clog2(NUM_WB_GROUPS); localparam LOG2_MAX_IDS = $clog2(MAX_IDS); typedef logic[LOG2_MAX_IDS-1:0] id_t; - typedef logic[WB_UNITS_WIDTH-1:0] unit_id_t; typedef logic[1:0] branch_predictor_metadata_t; 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_CONSTANT = 2'b00, @@ -58,12 +54,6 @@ package taiga_types; id_t id; } exception_packet_t; - typedef struct packed{ - branch_predictor_metadata_t branch_predictor_metadata; - logic branch_prediction_used; - logic [BRANCH_PREDICTOR_WAYS-1:0] branch_predictor_update_way; - } branch_metadata_t; - typedef enum logic { FETCH_ACCESS_FAULT = 1'b0, FETCH_PAGE_FAULT = 1'b1 @@ -90,15 +80,14 @@ package taiga_types; rs_addr_t [REGFILE_READ_PORTS-1:0] rs_addr; phys_addr_t [REGFILE_READ_PORTS-1:0] phys_rs_addr; - rs_wb_group_t [REGFILE_READ_PORTS-1:0] rs_wb_group; rs_addr_t rd_addr; phys_addr_t phys_rd_addr; - rs_wb_group_t rd_wb_group; logic uses_rs1; logic uses_rs2; logic uses_rd; + logic is_multicycle; id_t id; logic stage_valid; fetch_metadata_t fetch_metadata; @@ -133,13 +122,14 @@ package taiga_types; } branch_inputs_t; typedef struct packed { - logic[31:0] pc_ex; - logic [31:0] new_pc; + id_t id; + logic valid; + logic [31:0] pc; + logic [31:0] target_pc; logic branch_taken; - logic branch_ex; - logic is_branch_ex; - logic is_return_ex; - logic is_call_ex; + logic is_branch; + logic is_return; + logic is_call; } branch_results_t; typedef struct packed{ @@ -314,10 +304,6 @@ package taiga_types; logic rs2_forwarding_needed; logic rs1_and_rs2_forwarding_needed; - //Writeback - unit_id_t num_instructions_completing; - id_t num_instructions_in_flight; - id_t num_of_instructions_pending_writeback; } taiga_trace_events_t; typedef struct packed { diff --git a/core/writeback.sv b/core/writeback.sv index 6a14e94..fbcc275 100644 --- a/core/writeback.sv +++ b/core/writeback.sv @@ -26,38 +26,58 @@ module writeback import riscv_types::*; import taiga_types::*; + # ( + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG, + parameter int unsigned NUM_UNITS [CONFIG.NUM_WB_GROUPS] = '{1, 4}, + parameter int unsigned NUM_WB_UNITS = 5 + ) + ( input logic clk, input logic rst, //Unit writeback unit_writeback_interface.wb unit_wb[NUM_WB_UNITS], //WB output - output wb_packet_t wb_packet [NUM_WB_GROUPS], + output wb_packet_t wb_packet [CONFIG.NUM_WB_GROUPS], //Snoop interface (LS unit) output wb_packet_t wb_snoop ); //Writeback - logic [NUM_WB_UNITS-1:0] unit_ack [NUM_WB_GROUPS]; + logic [NUM_WB_UNITS-1:0] unit_ack [CONFIG.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]; + id_t [NUM_WB_UNITS-1:0] unit_instruction_id [CONFIG.NUM_WB_GROUPS]; + logic [NUM_WB_UNITS-1:0] unit_done [CONFIG.NUM_WB_GROUPS]; typedef logic [XLEN-1:0] unit_rd_t [NUM_WB_UNITS]; - unit_rd_t unit_rd [NUM_WB_GROUPS]; + unit_rd_t unit_rd [CONFIG.NUM_WB_GROUPS]; //Per-ID muxes for commit buffer - logic [$clog2(NUM_WB_UNITS)-1:0] unit_sel [NUM_WB_GROUPS]; + logic [$clog2(NUM_WB_UNITS)-1:0] unit_sel [CONFIG.NUM_WB_GROUPS]; + + typedef int unsigned unit_count_t [CONFIG.NUM_WB_GROUPS]; + + function unit_count_t get_cumulative_unit_count(); + unit_count_t counts; + int unsigned cumulative_count = 0; + for (int i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin + counts[i] = cumulative_count; + cumulative_count += NUM_UNITS[i]; + end + return counts; + endfunction + + localparam unit_count_t CUMULATIVE_NUM_UNITS = get_cumulative_unit_count(); genvar i, j; //////////////////////////////////////////////////// //Implementation //Re-assigning interface inputs to array types so that they can be dynamically indexed generate - for (i = 0; i < NUM_WB_GROUPS; i++) begin - for (j = 0; j < NUM_WB_UNITS_GROUP[i]; j++) begin - assign unit_instruction_id[i][j] = unit_wb[CUMULATIVE_NUM_WB_UNITS_GROUP[i] + j].id; - assign unit_done[i][j] = unit_wb[CUMULATIVE_NUM_WB_UNITS_GROUP[i] + j].done; - assign unit_wb[CUMULATIVE_NUM_WB_UNITS_GROUP[i] + j].ack = unit_ack[i][j]; + for (i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin + for (j = 0; j < NUM_UNITS[i]; j++) begin + assign unit_instruction_id[i][j] = unit_wb[CUMULATIVE_NUM_UNITS[i] + j].id; + assign unit_done[i][j] = unit_wb[CUMULATIVE_NUM_UNITS[i] + j].done; + assign unit_wb[CUMULATIVE_NUM_UNITS[i] + j].ack = unit_ack[i][j]; end end endgenerate @@ -65,9 +85,9 @@ module 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 - 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; + for (i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin + for (j = 0; j < NUM_UNITS[i]; j++) begin + assign unit_rd[i][j] = unit_wb[CUMULATIVE_NUM_UNITS[i] + j].rd; end end endgenerate @@ -77,13 +97,13 @@ module writeback //Iterating through all commit ports: // Search for complete units (in fixed unit order) // Assign to a commit port, mask that unit and commit port - generate for (i = 0; i < NUM_WB_GROUPS; i++) begin + generate for (i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin priority_encoder - #(.WIDTH(NUM_WB_UNITS_GROUP[i])) + #(.WIDTH(NUM_UNITS[i])) unit_done_encoder ( - .priority_vector (unit_done[i][NUM_WB_UNITS_GROUP[i]-1 : 0]), - .encoded_result (unit_sel[i][NUM_WB_UNITS_GROUP[i] == 1 ? 0 : ($clog2(NUM_WB_UNITS_GROUP[i])-1) : 0]) + .priority_vector (unit_done[i][NUM_UNITS[i]-1 : 0]), + .encoded_result (unit_sel[i][NUM_UNITS[i] == 1 ? 0 : ($clog2(NUM_UNITS[i])-1) : 0]) ); assign wb_packet[i].valid = |unit_done[i]; assign wb_packet [i].id = unit_instruction_id[i][unit_sel[i]]; @@ -91,7 +111,7 @@ module writeback end endgenerate always_comb begin - for (int i = 0; i < NUM_WB_GROUPS; i++) begin + for (int i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin unit_ack[i] = '0; unit_ack[i][unit_sel[i]] = wb_packet[i].valid; end diff --git a/examples/zedboard/taiga_wrapper.sv b/examples/zedboard/taiga_wrapper.sv index fa49e42..281a82c 100755 --- a/examples/zedboard/taiga_wrapper.sv +++ b/examples/zedboard/taiga_wrapper.sv @@ -235,7 +235,7 @@ module taiga_wrapper ( //design_2 infra(.*); generate - if (ENABLE_S_MODE || USE_ICACHE || USE_DCACHE) begin + if (EXAMPLE_CONFIG.INCLUDE_S_MODE || EXAMPLE_CONFIG.INCLUDE_ICACHE || EXAMPLE_CONFIG.INCLUDE_DCACHE) begin l2_arbiter l2_arb (.*, .request(l2)); axi_to_arb l2_to_mem (.*, .l2(mem)); end diff --git a/test_benches/verilator/TaigaTracer.h b/test_benches/verilator/TaigaTracer.h index c59a550..a40e84c 100644 --- a/test_benches/verilator/TaigaTracer.h +++ b/test_benches/verilator/TaigaTracer.h @@ -68,10 +68,7 @@ static const char * const eventNames[] = { "load_conflict_delay", "rs1_forwarding_needed", "rs2_forwarding_needed", - "rs1_and_rs2_forwarding_needed", - "num_instructions_completing", - "num_instructions_in_flight", - "num_of_instructions_pending_writeback" + "rs1_and_rs2_forwarding_needed" }; static const int numEvents = arraySize(eventNames); diff --git a/test_benches/verilator/taiga_sim.sv b/test_benches/verilator/taiga_sim.sv index ec2e2c3..4a6091d 100644 --- a/test_benches/verilator/taiga_sim.sv +++ b/test_benches/verilator/taiga_sim.sv @@ -286,7 +286,7 @@ module taiga_sim assign data_bram_data_in = data_bram.data_in; assign data_bram.data_out = data_bram_data_out; - taiga cpu(.*, .l2(l2[0])); + taiga #(.CONFIG(EXAMPLE_CONFIG)) cpu(.*, .l2(l2[0])); //read channel logic[3:0] read_counter; @@ -436,13 +436,13 @@ module taiga_sim //////////////////////////////////////////////////// //Performs the lookups to provide the speculative architectural register file with //standard register names for simulation purposes - logic [31:0][31:0] sim_registers_unamed_groups[NUM_WB_GROUPS]; + logic [31:0][31:0] sim_registers_unamed_groups[EXAMPLE_CONFIG.NUM_WB_GROUPS]; logic [31:0][31:0] sim_registers_unamed; simulation_named_regfile sim_register; genvar i, j; generate for (i = 0; i < 32; i++) begin - for (j = 0; j < NUM_WB_GROUPS; j++) begin + for (j = 0; j < EXAMPLE_CONFIG.NUM_WB_GROUPS; j++) begin assign sim_registers_unamed_groups[j][i] = cpu.register_file_block.register_file_gen[j].reg_group.register_file_bank[cpu.renamer_block.spec_table[i].phys_addr]; end