From ffc2c219707ff141e02d4f4800e912194bb16869 Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Tue, 11 Apr 2023 09:33:22 -0400 Subject: [PATCH 01/16] code cleanups Signed-off-by: Eric Matthews --- core/cva5.sv | 1 - core/fetch.sv | 52 ++++++++++++++------------- core/internal_interfaces.sv | 72 +++++-------------------------------- core/writeback.sv | 24 ++++++------- 4 files changed, 47 insertions(+), 102 deletions(-) diff --git a/core/cva5.sv b/core/cva5.sv index f482df4..137e402 100755 --- a/core/cva5.sv +++ b/core/cva5.sv @@ -286,7 +286,6 @@ module cva5 .iwishbone (iwishbone), .icache_on ('1), .tlb (itlb), - .tlb_on (tlb_on), .l1_request (l1_request[L1_ICACHE_ID]), .l1_response (l1_response[L1_ICACHE_ID]), .exception (1'b0) diff --git a/core/fetch.sv b/core/fetch.sv index 4793887..82455b1 100755 --- a/core/fetch.sv +++ b/core/fetch.sv @@ -36,7 +36,6 @@ module fetch input logic branch_flush, input gc_outputs_t gc, - input logic tlb_on, input logic exception, //ID Support @@ -94,7 +93,7 @@ module fetch logic mmu_fault; logic [NUM_SUB_UNITS_W-1:0] subunit_id; } fetch_attributes_t; - fetch_attributes_t fetch_attr_next; + fetch_attributes_t fetch_attr_in; fetch_attributes_t fetch_attr; logic [MAX_OUTSTANDING_REQUESTS_W:0] inflight_count; @@ -117,8 +116,6 @@ module fetch logic exception_pending; logic internal_fetch_complete; - logic [31:0] translated_address; - genvar i; //////////////////////////////////////////////////// //Implementation @@ -161,42 +158,49 @@ module fetch 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.pc_override & new_mem_request & (~early_branch_flush); - assign ras.push = bp.use_prediction & bp.is_call & ~branch_flush & ~gc.pc_override & new_mem_request & (~early_branch_flush); + //////////////////////////////////////////////////// + //RAS support + logic ras_update_permitted; + assign ras_update_permitted = bp.use_prediction & new_mem_request & ~(branch_flush | gc.pc_override | early_branch_flush); + + assign ras.pop = bp.is_return & ras_update_permitted; + assign ras.push = bp.is_call & ras_update_permitted; + assign ras.branch_fetched = bp.is_branch & ras_update_permitted; assign ras.new_addr = pc_plus_4; - assign ras.branch_fetched = bp.use_prediction & bp.is_branch & new_mem_request & (~early_branch_flush); //flush not needed as FIFO resets inside of RAS //////////////////////////////////////////////////// //TLB assign tlb.virtual_address = pc; assign tlb.execute = 1; assign tlb.rnw = 0; - 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; + assign tlb.new_request = tlb.ready; ////////////////////////////////////////////// //Issue Control Signals assign flush_or_rst = (rst | gc.fetch_flush | early_branch_flush); - assign new_mem_request = (~tlb_on | tlb.done) & pc_id_available & ~fetch_attr_fifo.full & units_ready & (~gc.fetch_hold) & (~exception_pending); + assign new_mem_request = tlb.done & pc_id_available & ~fetch_attr_fifo.full & units_ready & (~gc.fetch_hold) & (~exception_pending); assign pc_id_assigned = new_mem_request | tlb.is_fault; ////////////////////////////////////////////// //Subunit Tracking - assign fetch_attr_fifo.push = pc_id_assigned; - assign fetch_attr_fifo.potential_push = pc_id_assigned; - assign fetch_attr_fifo.pop = internal_fetch_complete; + logic [NUM_SUB_UNITS_W-1:0] subunit_id; one_hot_to_integer #(NUM_SUB_UNITS) hit_way_conv ( .one_hot (sub_unit_address_match), - .int_out (fetch_attr_next.subunit_id) + .int_out (subunit_id) ); - assign fetch_attr_next.is_predicted_branch_or_jump = bp.use_prediction; - assign fetch_attr_next.is_branch = bp.use_prediction & bp.is_branch; - assign fetch_attr_next.address_valid = address_valid; - assign fetch_attr_next.mmu_fault = tlb.is_fault; - - assign fetch_attr_fifo.data_in = fetch_attr_next; + assign fetch_attr_in = '{ + is_predicted_branch_or_jump : bp.use_prediction, + is_branch : (bp.use_prediction & bp.is_branch), + address_valid : address_valid, + mmu_fault : tlb.is_fault, + subunit_id : subunit_id + }; + assign fetch_attr_fifo.data_in = fetch_attr_in; + assign fetch_attr_fifo.push = pc_id_assigned; + assign fetch_attr_fifo.potential_push = pc_id_assigned; + assign fetch_attr_fifo.pop = internal_fetch_complete; cva5_fifo #(.DATA_WIDTH($bits(fetch_attributes_t)), .FIFO_DEPTH(MAX_OUTSTANDING_REQUESTS)) attributes_fifo ( @@ -231,7 +235,7 @@ module fetch //In either case, data_valid must NOT be asserted. generate for (i=0; i < NUM_SUB_UNITS; i++) begin : gen_fetch_sources assign sub_unit[i].new_request = fetch_attr_fifo.push & sub_unit_address_match[i]; - assign sub_unit[i].addr = translated_address; + assign sub_unit[i].addr = tlb.physical_address; assign sub_unit[i].re = 1; assign sub_unit[i].we = 0; assign sub_unit[i].be = '0; @@ -244,7 +248,7 @@ module fetch endgenerate generate if (CONFIG.INCLUDE_ILOCAL_MEM) begin : gen_fetch_local_mem - assign sub_unit_address_match[LOCAL_MEM_ID] = ilocal_mem_addr_utils.address_range_check(translated_address); + assign sub_unit_address_match[LOCAL_MEM_ID] = ilocal_mem_addr_utils.address_range_check(tlb.physical_address); local_mem_sub_unit i_local_mem ( .clk (clk), .rst (rst), @@ -255,7 +259,7 @@ module fetch endgenerate generate if (CONFIG.INCLUDE_IBUS) begin : gen_fetch_ibus - assign sub_unit_address_match[BUS_ID] = ibus_addr_utils.address_range_check(translated_address); + assign sub_unit_address_match[BUS_ID] = ibus_addr_utils.address_range_check(tlb.physical_address); wishbone_master iwishbone_bus ( .clk (clk), .rst (rst), @@ -266,7 +270,7 @@ module fetch endgenerate generate if (CONFIG.INCLUDE_ICACHE) begin : gen_fetch_icache - assign sub_unit_address_match[ICACHE_ID] = icache_addr_utils.address_range_check(translated_address); + assign sub_unit_address_match[ICACHE_ID] = icache_addr_utils.address_range_check(tlb.physical_address); icache #(.CONFIG(CONFIG)) i_cache ( .clk (clk), diff --git a/core/internal_interfaces.sv b/core/internal_interfaces.sv index e5a4ac0..08a15c8 100755 --- a/core/internal_interfaces.sv +++ b/core/internal_interfaces.sv @@ -51,21 +51,6 @@ interface branch_predictor_interface; endinterface -interface unit_decode_interface; - import cva5_types::*; - import cva5_config::*; - - logic [31:0] instruction; - logic issue_stage_ready; - - logic unit_needed; - logic uses_rs [REGFILE_READ_PORTS]; - logic uses_rd; - - modport decode (input unit_needed, uses_rs, uses_rd, output instruction, issue_stage_ready); - modport unit (output unit_needed, uses_rs, uses_rd, input instruction, issue_stage_ready); -endinterface - interface unit_issue_interface; import cva5_types::*; @@ -79,24 +64,19 @@ interface unit_issue_interface; modport unit (output ready, input possible_issue, new_request, id); endinterface -interface unit_writeback_interface; +interface unit_writeback_interface #(parameter type PAYLOAD_TYPE = logic); import riscv_types::*; import cva5_types::*; - logic ack; + //Handshaking + logic ack; + logic done; - id_t id; - logic done; - logic [XLEN-1:0] rd; + id_t id; + logic [31:0] rd; - modport unit ( - input ack, - output id, done, rd - ); - modport wb ( - output ack, - input id, done, rd - ); + modport unit (input ack, output done, id, rd); + modport wb (output ack, input done, id, rd); endinterface interface ras_interface; @@ -129,20 +109,6 @@ interface exception_interface; modport econtrol (input valid, code, id, tval, output ack); endinterface -interface csr_exception_interface; - import riscv_types::*; - import cva5_types::*; - - logic valid; - exception_code_t code; - logic [31:0] tval; - logic [31:0] exception_pc; - logic [31:0] trap_pc; - - modport econtrol (output valid, code, tval, exception_pc, input trap_pc); - modport csr (input valid, code, tval, exception_pc, output trap_pc); -endinterface - interface fifo_interface #(parameter DATA_WIDTH = 42);//#(parameter type data_type = logic[31:0]); logic push; logic pop; @@ -268,28 +234,6 @@ interface store_queue_interface; ); endinterface -interface writeback_store_interface; - import riscv_types::*; - import cva5_types::*; - - id_t id_needed; - logic possibly_waiting; - logic waiting; - logic ack; - - logic id_done; - logic [31:0] data; - - modport ls ( - input id_done, data, - output id_needed, possibly_waiting ,waiting, ack - ); - modport wb ( - input id_needed, possibly_waiting, waiting, ack, - output id_done, data - ); -endinterface - interface cache_functions_interface #(parameter int TAG_W = 8, parameter int LINE_W = 4, parameter int SUB_LINE_W = 2); function logic [LINE_W-1:0] xor_mask (int WAY); diff --git a/core/writeback.sv b/core/writeback.sv index 28a233f..0c853d3 100644 --- a/core/writeback.sv +++ b/core/writeback.sv @@ -40,27 +40,23 @@ module writeback output wb_packet_t wb_packet ); - //Writeback - logic [NUM_WB_UNITS-1:0] unit_ack; //aliases for write-back-interface signals id_t [NUM_WB_UNITS-1:0] unit_instruction_id; logic [NUM_WB_UNITS-1:0] unit_done; + logic [31:0] unit_rd [NUM_WB_UNITS]; + logic [NUM_WB_UNITS-1:0] unit_ack; - logic [XLEN-1:0] unit_rd [NUM_WB_UNITS]; - - localparam int unsigned LOG2_NUM_WB_UNITS = NUM_WB_UNITS == 1 ? 1 : $clog2(NUM_WB_UNITS); - //Per-ID muxes for commit buffer + localparam int unsigned LOG2_NUM_WB_UNITS = (NUM_WB_UNITS == 1) ? 1 : $clog2(NUM_WB_UNITS); logic [LOG2_NUM_WB_UNITS-1:0] unit_sel; - genvar i; //////////////////////////////////////////////////// //Implementation //Re-assigning interface inputs to array types so that they can be dynamically indexed - generate for (i = 0; i < NUM_WB_UNITS; i++) begin : gen_wb_unit_unpacking + generate for (genvar i = 0; i < NUM_WB_UNITS; i++) begin : gen_wb_unit_unpacking assign unit_instruction_id[i] = unit_wb[i].id; assign unit_done[i] = unit_wb[i].done; - assign unit_wb[i].ack = unit_ack[i]; assign unit_rd[i] = unit_wb[i].rd; + assign unit_wb[i].ack = unit_ack[i]; end endgenerate //////////////////////////////////////////////////// @@ -72,11 +68,13 @@ module writeback unit_done_encoder ( .priority_vector (unit_done), - .encoded_result (unit_sel[LOG2_NUM_WB_UNITS -1 : 0]) + .encoded_result (unit_sel) ); - assign wb_packet.valid = |unit_done; - assign wb_packet.id = unit_instruction_id[unit_sel]; - assign wb_packet.data = unit_rd[unit_sel]; + assign wb_packet = '{ + valid : |unit_done, + id : unit_instruction_id[unit_sel], + data : unit_rd[unit_sel] + }; assign unit_ack = NUM_WB_UNITS'(wb_packet.valid) << unit_sel; From 6c63d2724e2d228f3cdc3526cd04e3133475dfc0 Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Tue, 11 Apr 2023 14:43:39 -0400 Subject: [PATCH 02/16] Consolidate struct-to-bits type conversion into FIFO/LUTRAMs Signed-off-by: Eric Matthews --- core/cva5_fifo.sv | 6 ++-- core/dcache.sv | 4 +-- core/div_unit.sv | 52 +++++++++++++++----------------- core/fetch.sv | 9 ++---- core/icache.sv | 4 +-- core/internal_interfaces.sv | 6 ++-- core/load_store_queue.sv | 20 +++++------- core/load_store_unit.sv | 10 +++--- core/lutrams/lutram_1w_1r.sv | 8 ++--- core/lutrams/lutram_1w_mr.sv | 10 +++--- core/ras.sv | 10 ++++-- core/register_file.sv | 2 +- core/register_free_list.sv | 4 +-- core/renamer.sv | 8 ++--- core/store_queue.sv | 10 +++--- core/tlb_lut_ram.sv | 2 +- core/toggle_memory.sv | 2 +- examples/litex/l1_to_wishbone.sv | 25 ++++++++------- examples/nexys/l1_to_axi.sv | 25 ++++++++------- l2_arbiter/l2_arbiter.sv | 32 ++++++++++---------- 20 files changed, 118 insertions(+), 131 deletions(-) diff --git a/core/cva5_fifo.sv b/core/cva5_fifo.sv index 3ee151a..f202cb1 100755 --- a/core/cva5_fifo.sv +++ b/core/cva5_fifo.sv @@ -32,7 +32,7 @@ module cva5_fifo import cva5_types::*; #( - parameter DATA_WIDTH = 70, + parameter type DATA_TYPE = logic, parameter FIFO_DEPTH = 4 ) ( @@ -63,7 +63,7 @@ module cva5_fifo //connected as a shift reg for the same resources as a LUTRAM FIFO //but with better timing else if (FIFO_DEPTH == 2) begin : gen_width_two - logic [DATA_WIDTH-1:0] shift_reg [FIFO_DEPTH]; + DATA_TYPE shift_reg [FIFO_DEPTH]; logic [LOG2_FIFO_DEPTH:0] inflight_count; //////////////////////////////////////////////////// //Occupancy Tracking @@ -115,7 +115,7 @@ module cva5_fifo .value(write_index) ); //Force FIFO depth to next power of 2 - lutram_1w_1r #(.WIDTH(DATA_WIDTH), .DEPTH(2**LOG2_FIFO_DEPTH)) + lutram_1w_1r #(.DATA_TYPE(DATA_TYPE), .DEPTH(2**LOG2_FIFO_DEPTH)) write_port ( .clk(clk), .waddr(write_index), diff --git a/core/dcache.sv b/core/dcache.sv index fb5bfdd..8674acd 100644 --- a/core/dcache.sv +++ b/core/dcache.sv @@ -186,7 +186,7 @@ module dcache //////////////////////////////////////////////////// //L1 Arbiter Interface //Priority to oldest request - fifo_interface #(.DATA_WIDTH(1)) request_order(); + fifo_interface #(.DATA_TYPE(logic)) request_order(); assign request_order.data_in = load_request; assign request_order.push = load_request | store_request; @@ -194,7 +194,7 @@ module dcache assign request_order.pop = l1_request.ack | load_hit; - cva5_fifo #(.DATA_WIDTH(1), .FIFO_DEPTH(2)) + cva5_fifo #(.DATA_TYPE(logic), .FIFO_DEPTH(2)) request_order_fifo ( .clk (clk), .rst (rst), diff --git a/core/div_unit.sv b/core/div_unit.sv index 287694d..b0533eb 100755 --- a/core/div_unit.sv +++ b/core/div_unit.sv @@ -71,6 +71,7 @@ module div_unit logic reuse_result; id_t id; } div_attributes_t; + div_attributes_t wb_attr; typedef struct packed{ logic [XLEN-1:0] unsigned_dividend; @@ -80,17 +81,12 @@ module div_unit div_attributes_t attr; } div_fifo_inputs_t; - div_fifo_inputs_t issue_fifo_inputs; - div_fifo_inputs_t div_stage; - div_attributes_t wb_attr; - unsigned_division_interface #(.DATA_WIDTH(32)) div_core(); logic in_progress; logic div_done; - fifo_interface #(.DATA_WIDTH($bits(div_fifo_inputs_t))) input_fifo(); - fifo_interface #(.DATA_WIDTH(XLEN)) wb_fifo(); + fifo_interface #(.DATA_TYPE(div_fifo_inputs_t)) input_fifo(); function logic [31:0] negate_if (input logic [31:0] a, logic b); return ({32{b}} ^ a) + 32'(b); @@ -159,22 +155,11 @@ module div_unit clz divisor_clz_block (.clz_input(unsigned_divisor), .clz(divisor_CLZ)); assign divisor_is_zero = (&divisor_CLZ) & ~rf[RS2][0]; - assign issue_fifo_inputs.unsigned_dividend = unsigned_dividend; - assign issue_fifo_inputs.unsigned_divisor = unsigned_divisor; - assign issue_fifo_inputs.dividend_CLZ = divisor_is_zero ? '0 : dividend_CLZ; - assign issue_fifo_inputs.divisor_CLZ = divisor_CLZ; - - assign issue_fifo_inputs.attr.remainder_op = issue_stage.fn3[1]; - assign issue_fifo_inputs.attr.negate_result = issue_stage.fn3[1] ? negate_remainder : (negate_quotient & ~divisor_is_zero); - assign issue_fifo_inputs.attr.divisor_is_zero = divisor_is_zero; - assign issue_fifo_inputs.attr.reuse_result = div_op_reuse; - assign issue_fifo_inputs.attr.id = issue.id; - //////////////////////////////////////////////////// //Input FIFO //Currently just a register (DEPTH=1). As one div instruction can be in-progress //and one in this input "fifo," we can support two in-flight div ops. - cva5_fifo #(.DATA_WIDTH($bits(div_fifo_inputs_t)), .FIFO_DEPTH(1)) + cva5_fifo #(.DATA_TYPE(div_fifo_inputs_t), .FIFO_DEPTH(1)) div_input_fifo ( .clk (clk), .rst (rst), @@ -184,17 +169,28 @@ module div_unit logic div_ready; assign div_ready = (~in_progress) | wb.ack; - assign input_fifo.data_in = issue_fifo_inputs; + assign input_fifo.data_in = '{ + unsigned_dividend : unsigned_dividend, + unsigned_divisor : unsigned_divisor, + dividend_CLZ : divisor_is_zero ? '0 : dividend_CLZ, + divisor_CLZ : divisor_CLZ, + attr : '{ + remainder_op : issue_stage.fn3[1], + negate_result : (issue_stage.fn3[1] ? negate_remainder : (negate_quotient & ~divisor_is_zero)), + divisor_is_zero : divisor_is_zero, + reuse_result : div_op_reuse, + id : issue.id + } + }; assign input_fifo.push = issue.new_request; assign input_fifo.potential_push = issue.possible_issue; assign issue.ready = ~input_fifo.full | (~in_progress); assign input_fifo.pop = input_fifo.valid & div_ready; - assign div_stage = input_fifo.data_out; //////////////////////////////////////////////////// //Control Signals - assign div_core.start = input_fifo.pop & ~div_stage.attr.reuse_result; - assign div_done = div_core.done | (input_fifo.pop & div_stage.attr.reuse_result); + assign div_core.start = input_fifo.pop & ~input_fifo.data_out.attr.reuse_result; + assign div_done = div_core.done | (input_fifo.pop & input_fifo.data_out.attr.reuse_result); //If more than one cycle, set in_progress so that multiple div.start signals are not sent to the div unit. set_clr_reg_with_rst #(.SET_OVER_CLR(1), .WIDTH(1), .RST_VALUE('0)) @@ -206,16 +202,16 @@ module div_unit ); always_ff @ (posedge clk) begin if (input_fifo.pop) - wb_attr <= div_stage.attr; + wb_attr <= input_fifo.data_out.attr; end //////////////////////////////////////////////////// //Div core - assign div_core.dividend = div_stage.unsigned_dividend; - assign div_core.divisor = div_stage.unsigned_divisor; - assign div_core.dividend_CLZ = div_stage.dividend_CLZ; - assign div_core.divisor_CLZ = div_stage.divisor_CLZ; - assign div_core.divisor_is_zero = div_stage.attr.divisor_is_zero; + assign div_core.dividend = input_fifo.data_out.unsigned_dividend; + assign div_core.divisor = input_fifo.data_out.unsigned_divisor; + assign div_core.dividend_CLZ = input_fifo.data_out.dividend_CLZ; + assign div_core.divisor_CLZ = input_fifo.data_out.divisor_CLZ; + assign div_core.divisor_is_zero = input_fifo.data_out.attr.divisor_is_zero; div_core #(.DIV_WIDTH(32)) divider_block ( diff --git a/core/fetch.sv b/core/fetch.sv index 82455b1..3352be1 100755 --- a/core/fetch.sv +++ b/core/fetch.sv @@ -93,7 +93,6 @@ module fetch logic mmu_fault; logic [NUM_SUB_UNITS_W-1:0] subunit_id; } fetch_attributes_t; - fetch_attributes_t fetch_attr_in; fetch_attributes_t fetch_attr; logic [MAX_OUTSTANDING_REQUESTS_W:0] inflight_count; @@ -109,7 +108,7 @@ module fetch logic [31:0] pc; logic flush_or_rst; - fifo_interface #(.DATA_WIDTH($bits(fetch_attributes_t))) fetch_attr_fifo(); + fifo_interface #(.DATA_TYPE(fetch_attributes_t)) fetch_attr_fifo(); logic update_pc; logic new_mem_request; @@ -190,25 +189,23 @@ module fetch .one_hot (sub_unit_address_match), .int_out (subunit_id) ); - assign fetch_attr_in = '{ + assign fetch_attr_fifo.data_in = '{ is_predicted_branch_or_jump : bp.use_prediction, is_branch : (bp.use_prediction & bp.is_branch), address_valid : address_valid, mmu_fault : tlb.is_fault, subunit_id : subunit_id }; - assign fetch_attr_fifo.data_in = fetch_attr_in; assign fetch_attr_fifo.push = pc_id_assigned; assign fetch_attr_fifo.potential_push = pc_id_assigned; assign fetch_attr_fifo.pop = internal_fetch_complete; - cva5_fifo #(.DATA_WIDTH($bits(fetch_attributes_t)), .FIFO_DEPTH(MAX_OUTSTANDING_REQUESTS)) + cva5_fifo #(.DATA_TYPE(fetch_attributes_t), .FIFO_DEPTH(MAX_OUTSTANDING_REQUESTS)) attributes_fifo ( .clk (clk), .rst (rst), .fifo (fetch_attr_fifo) ); - assign fetch_attr = fetch_attr_fifo.data_out; assign inflight_count_next = inflight_count + MAX_OUTSTANDING_REQUESTS_W'(fetch_attr_fifo.push) - MAX_OUTSTANDING_REQUESTS_W'(fetch_attr_fifo.pop); diff --git a/core/icache.sv b/core/icache.sv index c99d358..1a7887f 100755 --- a/core/icache.sv +++ b/core/icache.sv @@ -68,7 +68,7 @@ module icache logic second_cycle; logic [31:0] second_cycle_addr; - fifo_interface #(.DATA_WIDTH(32)) input_fifo(); + fifo_interface #(.DATA_TYPE(logic[31:0])) input_fifo(); logic new_request; logic [31:0] new_request_addr; @@ -88,7 +88,7 @@ module icache assign new_request_addr = input_fifo.valid ? input_fifo.data_out : fetch_sub.addr; - cva5_fifo #(.DATA_WIDTH(32), .FIFO_DEPTH(2)) + cva5_fifo #(.DATA_TYPE(logic[31:0]), .FIFO_DEPTH(2)) cache_input_fifo ( .clk (clk), .rst (rst), diff --git a/core/internal_interfaces.sv b/core/internal_interfaces.sv index 08a15c8..adf09d4 100755 --- a/core/internal_interfaces.sv +++ b/core/internal_interfaces.sv @@ -109,11 +109,11 @@ interface exception_interface; modport econtrol (input valid, code, id, tval, output ack); endinterface -interface fifo_interface #(parameter DATA_WIDTH = 42);//#(parameter type data_type = logic[31:0]); +interface fifo_interface #(parameter type DATA_TYPE = logic); logic push; logic pop; - logic [DATA_WIDTH-1:0] data_in; - logic [DATA_WIDTH-1:0] data_out; + DATA_TYPE data_in; + DATA_TYPE data_out; logic valid; logic full; logic potential_push; diff --git a/core/load_store_queue.sv b/core/load_store_queue.sv index 92bdc74..484772f 100644 --- a/core/load_store_queue.sv +++ b/core/load_store_queue.sv @@ -52,17 +52,13 @@ module load_store_queue //ID-based input buffer for Load/Store Unit logic [LOG2_SQ_DEPTH-1:0] sq_index; } lq_entry_t; - logic [LOG2_SQ_DEPTH-1:0] sq_index; logic [LOG2_SQ_DEPTH-1:0] sq_oldest; addr_hash_t addr_hash; logic potential_store_conflict; sq_entry_t sq_entry; - lq_entry_t lq_data_in; - lq_entry_t lq_data_out; - - fifo_interface #(.DATA_WIDTH($bits(lq_entry_t))) lq(); + fifo_interface #(.DATA_TYPE(lq_entry_t)) lq(); store_queue_interface sq(); //////////////////////////////////////////////////// //Implementation @@ -83,7 +79,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit //////////////////////////////////////////////////// //Load Queue - cva5_fifo #(.DATA_WIDTH($bits(lq_entry_t)), .FIFO_DEPTH(MAX_IDS)) + cva5_fifo #(.DATA_TYPE(lq_entry_t), .FIFO_DEPTH(MAX_IDS)) load_queue_fifo ( .clk(clk), .rst(rst), @@ -96,15 +92,13 @@ module load_store_queue //ID-based input buffer for Load/Store Unit assign lq.pop = lsq.load_pop; //FIFO data ports - assign lq_data_in = '{ + assign lq.data_in = '{ addr : lsq.data_in.addr, fn3 : lsq.data_in.fn3, id : lsq.data_in.id, store_collision : potential_store_conflict, sq_index : sq_index }; - assign lq.data_in = lq_data_in; - assign lq_data_out = lq.data_out; //////////////////////////////////////////////////// //Store Queue assign sq.push = lsq.push & lsq.data_in.store; @@ -129,19 +123,19 @@ 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 no loads are ready logic load_blocked; - assign load_blocked = (lq_data_out.store_collision & (lq_data_out.sq_index != sq_oldest)); + assign load_blocked = (lq.data_out.store_collision & (lq.data_out.sq_index != sq_oldest)); assign lsq.load_valid = lq.valid & ~load_blocked; assign lsq.store_valid = sq.valid; assign lsq.load_data_out = '{ - addr : lq_data_out.addr, + addr : lq.data_out.addr, load : 1, store : 0, be : 'x, - fn3 : lq_data_out.fn3, + fn3 : lq.data_out.fn3, data_in : 'x, - id : lq_data_out.id + id : lq.data_out.id }; assign lsq.store_data_out = '{ diff --git a/core/load_store_unit.sv b/core/load_store_unit.sv index 14eadde..55a1db6 100755 --- a/core/load_store_unit.sv +++ b/core/load_store_unit.sv @@ -137,13 +137,13 @@ module load_store_unit id_t id; logic [NUM_SUB_UNITS_W-1:0] subunit_id; } load_attributes_t; - load_attributes_t mem_attr, wb_attr; + load_attributes_t wb_attr; common_instruction_t instruction;//rs1_addr, rs2_addr, fn3, fn7, rd_addr, upper/lower opcode logic [3:0] be; //FIFOs - fifo_interface #(.DATA_WIDTH($bits(load_attributes_t))) load_attributes(); + fifo_interface #(.DATA_TYPE(load_attributes_t)) load_attributes(); load_store_queue_interface lsq(); //////////////////////////////////////////////////// @@ -359,7 +359,7 @@ module load_store_unit endcase end - assign mem_attr = '{ + assign load_attributes.data_in = '{ is_signed : ~|lsq.load_data_out.fn3[2:1], byte_addr : lsq.load_data_out.addr[1:0], sign_sel : lsq.load_data_out.addr[1:0] | {1'b0, lsq.load_data_out.fn3[0]},//halfwrord @@ -367,12 +367,10 @@ module load_store_unit id : lsq.load_data_out.id, subunit_id : subunit_id }; - - assign load_attributes.data_in = mem_attr; assign load_attributes.push = sub_unit_load_issue; assign load_attributes.potential_push = load_attributes.push; - cva5_fifo #(.DATA_WIDTH($bits(load_attributes_t)), .FIFO_DEPTH(ATTRIBUTES_DEPTH)) + cva5_fifo #(.DATA_TYPE(load_attributes_t), .FIFO_DEPTH(ATTRIBUTES_DEPTH)) attributes_fifo ( .clk (clk), .rst (rst), diff --git a/core/lutrams/lutram_1w_1r.sv b/core/lutrams/lutram_1w_1r.sv index d19454c..c05e9cb 100644 --- a/core/lutrams/lutram_1w_1r.sv +++ b/core/lutrams/lutram_1w_1r.sv @@ -22,7 +22,7 @@ module lutram_1w_1r #( - parameter WIDTH = 32, + parameter type DATA_TYPE = logic, parameter DEPTH = 32 ) ( @@ -32,11 +32,11 @@ module lutram_1w_1r input logic[$clog2(DEPTH)-1:0] raddr, input logic ram_write, - input logic[WIDTH-1:0] new_ram_data, - output logic[WIDTH-1:0] ram_data_out + input DATA_TYPE new_ram_data, + output DATA_TYPE ram_data_out ); - (* ramstyle = "MLAB, no_rw_check", ram_style = "distributed" *) logic [WIDTH-1:0] ram [DEPTH-1:0]; + (* ramstyle = "MLAB, no_rw_check", ram_style = "distributed" *) logic [$bits(DATA_TYPE)-1:0] ram [DEPTH-1:0]; initial ram = '{default: 0}; always_ff @ (posedge clk) begin diff --git a/core/lutrams/lutram_1w_mr.sv b/core/lutrams/lutram_1w_mr.sv index 4533013..b5b2182 100644 --- a/core/lutrams/lutram_1w_mr.sv +++ b/core/lutrams/lutram_1w_mr.sv @@ -25,7 +25,7 @@ module lutram_1w_mr import cva5_config::*; #( - parameter WIDTH = 32, + parameter type DATA_TYPE = logic, parameter DEPTH = 32, parameter NUM_READ_PORTS = 2 ) @@ -36,14 +36,14 @@ module lutram_1w_mr input logic[$clog2(DEPTH)-1:0] raddr [NUM_READ_PORTS], input logic ram_write, - input logic[WIDTH-1:0] new_ram_data, - output logic[WIDTH-1:0] ram_data_out [NUM_READ_PORTS] + input DATA_TYPE new_ram_data, + output DATA_TYPE ram_data_out [NUM_READ_PORTS] ); //For Xilinx with their wider selection of LUTRAMs, infer a multi-read port LUTRAM //For Intel, build the multi-read port ram from simple-dual-port LUTRAMs generate if (FPGA_VENDOR == XILINX) begin : xilinx_gen - logic [WIDTH-1:0] ram [DEPTH-1:0]; + logic [$bits(DATA_TYPE)-1:0] ram [DEPTH-1:0]; initial ram = '{default: 0}; always_ff @ (posedge clk) begin @@ -61,7 +61,7 @@ end else if (FPGA_VENDOR == INTEL) begin : intel_gen for (genvar i = 0; i < NUM_READ_PORTS; i++) begin : lutrams - lutram_1w_1r #(.WIDTH(WIDTH), .DEPTH(DEPTH)) + lutram_1w_1r #(.DATA_TYPE(DATA_TYPE), .DEPTH(DEPTH)) write_port ( .clk(clk), .waddr(waddr), diff --git a/core/ras.sv b/core/ras.sv index 3333e85..496d11d 100755 --- a/core/ras.sv +++ b/core/ras.sv @@ -43,7 +43,7 @@ module ras 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(); + fifo_interface #(.DATA_TYPE(logic[RAS_DEPTH_W-1:0])) ri_fifo(); /////////////////////////////////////////////////////// //For simulation purposes initial lut_ram = '{default: 0}; @@ -52,8 +52,12 @@ module ras //On a speculative branch, save the current stack pointer //Restored if branch is misspredicted (gc_fetch_flush) - cva5_fifo #(.DATA_WIDTH(RAS_DEPTH_W), .FIFO_DEPTH(MAX_IDS)) - read_index_fifo (.clk, .rst(rst | gc.fetch_flush | early_branch_flush_ras_adjust), .fifo(ri_fifo)); + cva5_fifo #(.DATA_TYPE(logic[RAS_DEPTH_W-1:0]), .FIFO_DEPTH(MAX_IDS)) + read_index_fifo ( + .clk, + .rst(rst | gc.fetch_flush | early_branch_flush_ras_adjust), + .fifo(ri_fifo) + ); assign ri_fifo.data_in = read_index; assign ri_fifo.push = ras.branch_fetched; diff --git a/core/register_file.sv b/core/register_file.sv index 0447676..233df5e 100755 --- a/core/register_file.sv +++ b/core/register_file.sv @@ -108,7 +108,7 @@ module register_file //LUTRAM implementation //Read in decode stage, writeback groups muxed and output registered per regfile read port generate for (genvar i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin : register_file_gen - lutram_1w_mr #(.WIDTH(32), .DEPTH(64), .NUM_READ_PORTS(REGFILE_READ_PORTS)) + lutram_1w_mr #(.DATA_TYPE(logic[31:0]), .DEPTH(64), .NUM_READ_PORTS(REGFILE_READ_PORTS)) register_file_bank ( .clk, .waddr(wb_phys_addr[i]), diff --git a/core/register_free_list.sv b/core/register_free_list.sv index 9f6193b..ea3acf2 100644 --- a/core/register_free_list.sv +++ b/core/register_free_list.sv @@ -32,7 +32,7 @@ module register_free_list import cva5_types::*; #( - parameter DATA_WIDTH = 70, + parameter type DATA_TYPE = logic, parameter FIFO_DEPTH = 4 ) ( @@ -45,7 +45,7 @@ module register_free_list localparam LOG2_FIFO_DEPTH = $clog2(FIFO_DEPTH); //Force FIFO depth to next power of 2 - (* ramstyle = "MLAB, no_rw_check" *) logic [DATA_WIDTH-1:0] lut_ram [(2**LOG2_FIFO_DEPTH)]; + (* ramstyle = "MLAB, no_rw_check" *) logic [$bits(DATA_TYPE)-1:0] lut_ram [(2**LOG2_FIFO_DEPTH)]; logic [LOG2_FIFO_DEPTH-1:0] write_index; logic [LOG2_FIFO_DEPTH-1:0] read_index; logic [LOG2_FIFO_DEPTH:0] inflight_count; diff --git a/core/renamer.sv b/core/renamer.sv index 34e0117..df27b9e 100644 --- a/core/renamer.sv +++ b/core/renamer.sv @@ -58,7 +58,7 @@ module renamer logic [5:0] clear_index; - fifo_interface #(.DATA_WIDTH($bits(phys_addr_t))) free_list (); + fifo_interface #(.DATA_TYPE(phys_addr_t)) free_list (); logic rename_valid; logic rollback; @@ -83,7 +83,7 @@ module renamer //////////////////////////////////////////////////// //Free list FIFO - register_free_list #(.DATA_WIDTH($bits(phys_addr_t)), .FIFO_DEPTH(32)) free_list_fifo ( + register_free_list #(.DATA_TYPE(phys_addr_t), .FIFO_DEPTH(32)) free_list_fifo ( .clk (clk), .rst (rst), .fifo (free_list), @@ -106,7 +106,7 @@ module renamer previous_wb_group : spec_table_previous_r.wb_group }; - lutram_1w_1r #(.WIDTH($bits(renamer_metadata_t)), .DEPTH(MAX_IDS)) + lutram_1w_1r #(.DATA_TYPE(renamer_metadata_t), .DEPTH(MAX_IDS)) inuse_table ( .clk (clk), .waddr (issue.id), @@ -168,7 +168,7 @@ module renamer assign spec_table_read_addr[1+:REGFILE_READ_PORTS] = decode.rs_addr; lutram_1w_mr #( - .WIDTH($bits(spec_table_t)), + .DATA_TYPE(spec_table_t), .DEPTH(32), .NUM_READ_PORTS(REGFILE_READ_PORTS+1) ) diff --git a/core/store_queue.sv b/core/store_queue.sv index d81c578..1c7d5c6 100644 --- a/core/store_queue.sv +++ b/core/store_queue.sv @@ -121,7 +121,7 @@ module store_queue be : sq.data_in.be, data : '0 }; - lutram_1w_1r #(.WIDTH($bits(sq_entry_t)), .DEPTH(CONFIG.SQ_DEPTH)) + lutram_1w_1r #(.DATA_TYPE(sq_entry_t), .DEPTH(CONFIG.SQ_DEPTH)) store_attr ( .clk(clk), .waddr(sq_index), @@ -170,7 +170,7 @@ module store_queue end assign retire_table_in = '{id_needed : sq.data_in.id_needed, wb_group : store_forward_wb_group, sq_index : sq_index}; - lutram_1w_1r #(.WIDTH($bits(retire_table_t)), .DEPTH(MAX_IDS)) + lutram_1w_1r #(.DATA_TYPE(retire_table_t), .DEPTH(MAX_IDS)) store_retire_table_lutram ( .clk(clk), .waddr(sq.data_in.id), @@ -183,7 +183,7 @@ module store_queue logic [31:0] wb_data [NUM_OF_FORWARDING_PORTS+1]; //Data issued with the store can be stored by store-id - lutram_1w_1r #(.WIDTH(32), .DEPTH(MAX_IDS)) + lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(MAX_IDS)) non_forwarded_port ( .clk(clk), .waddr(sq.data_in.id), @@ -196,7 +196,7 @@ module store_queue //Data from wb ports is stored by ID and then accessed by store-id to store-id-needed translation generate for (genvar i = 0; i < NUM_OF_FORWARDING_PORTS; i++) begin : lutrams - lutram_1w_1r #(.WIDTH(32), .DEPTH(MAX_IDS)) + lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(MAX_IDS)) writeback_port ( .clk(clk), .waddr(wb_snoop[i+1].id), @@ -210,7 +210,7 @@ module store_queue //Final storage table for the store queue //SQ-index addressed - lutram_1w_1r #(.WIDTH(32), .DEPTH(CONFIG.SQ_DEPTH)) + lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(CONFIG.SQ_DEPTH)) sq_data_lutram ( .clk(clk), .waddr(retire_table_out.sq_index), diff --git a/core/tlb_lut_ram.sv b/core/tlb_lut_ram.sv index a2893cd..db21485 100755 --- a/core/tlb_lut_ram.sv +++ b/core/tlb_lut_ram.sv @@ -91,7 +91,7 @@ module tlb_lut_ram genvar i; generate for (i=0; i Date: Tue, 11 Apr 2023 19:35:04 -0400 Subject: [PATCH 03/16] Convert id_metadata from inferred LUTRAMs to LUTRAM modules Signed-off-by: Eric Matthews --- .../instruction_metadata_and_id_management.sv | 216 ++++++++++-------- examples/nexys/nexys_sim.sv | 4 +- test_benches/verilator/cva5_sim.sv | 4 +- 3 files changed, 119 insertions(+), 105 deletions(-) diff --git a/core/instruction_metadata_and_id_management.sv b/core/instruction_metadata_and_id_management.sv index f90976c..b37c12f 100644 --- a/core/instruction_metadata_and_id_management.sv +++ b/core/instruction_metadata_and_id_management.sv @@ -81,18 +81,16 @@ module instruction_metadata_and_id_management output logic [$clog2(NUM_EXCEPTION_SOURCES)-1:0] current_exception_unit ); ////////////////////////////////////////// - (* ramstyle = "MLAB, no_rw_check" *) logic [31:0] pc_table [MAX_IDS]; - (* ramstyle = "MLAB, no_rw_check" *) logic [31:0] instruction_table [MAX_IDS]; - (* ramstyle = "MLAB, no_rw_check" *) logic [0:0] valid_fetch_addr_table [MAX_IDS]; + logic [31:0] decode_pc; + logic [31:0] decode_instruction; + fetch_metadata_t decode_fetch_metadata; - (* ramstyle = "MLAB, no_rw_check" *) logic [0:0] uses_rd_table [MAX_IDS]; - (* ramstyle = "MLAB, no_rw_check" *) logic [0:0] is_store_table [MAX_IDS]; - - (* ramstyle = "MLAB, no_rw_check" *) phys_addr_t id_to_phys_rd_table [MAX_IDS]; - - (* ramstyle = "MLAB, no_rw_check" *) logic [$bits(fetch_metadata_t)-1:0] fetch_metadata_table [MAX_IDS]; - - (* ramstyle = "MLAB, no_rw_check" *) logic [$bits(exception_sources_t)-1:0] exception_unit_table [MAX_IDS]; + typedef struct packed { + logic is_rd; + logic is_store; + } instruction_type_t; + instruction_type_t decode_type; + instruction_type_t retire_type [RETIRE_PORTS]; id_t decode_id; id_t oldest_pre_issue_id; @@ -115,60 +113,98 @@ module instruction_metadata_and_id_management //////////////////////////////////////////////////// //Instruction Metadata - //PC table - //Number of read ports = 1 or 2 (decode stage + exception logic (if enabled)) - always_ff @ (posedge clk) begin - if (pc_id_assigned) - pc_table[pc_id] <= if_pc; - end + //PC table(s) + lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(MAX_IDS)) + pc_table ( + .clk(clk), + .waddr(pc_id), + .raddr(decode_id), + .ram_write(pc_id_assigned), + .new_ram_data(if_pc), + .ram_data_out(decode_pc) + ); + + generate if (CONFIG.INCLUDE_M_MODE) begin : gen_pc_id_exception_support + lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(MAX_IDS)) + pc_table_exception ( + .clk(clk), + .waddr(pc_id), + .raddr(retire_ids_next[0]), + .ram_write(pc_id_assigned), + .new_ram_data(if_pc), + .ram_data_out(oldest_pc) + ); + end endgenerate //////////////////////////////////////////////////// //Instruction table - //Number of read ports = 1 (decode stage) - always_ff @ (posedge clk) begin - if (fetch_complete) - instruction_table[fetch_id] <= fetch_instruction; - end + lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(MAX_IDS)) + instruction_table ( + .clk(clk), + .waddr(fetch_id), + .raddr(decode_id), + .ram_write(fetch_complete), + .new_ram_data(fetch_instruction), + .ram_data_out(decode_instruction) + ); //////////////////////////////////////////////////// //Valid fetched address table - //Number of read ports = 1 (decode stage) - always_ff @ (posedge clk) begin - if (fetch_complete) - fetch_metadata_table[fetch_id] <= fetch_metadata; - end - + lutram_1w_1r #(.DATA_TYPE(fetch_metadata_t), .DEPTH(MAX_IDS)) + fetch_metadata_table ( + .clk(clk), + .waddr(fetch_id), + .raddr(decode_id), + .ram_write(fetch_complete), + .new_ram_data(fetch_metadata), + .ram_data_out(decode_fetch_metadata) + ); //////////////////////////////////////////////////// - //Uses rd table + //Retire Instruction Type Table //Number of read ports = RETIRE_PORTS - always_ff @ (posedge clk) begin - if (decode_advance) - uses_rd_table[decode_id] <= decode_uses_rd & |decode_rd_addr; - end - - //////////////////////////////////////////////////// - //Is store table - //Number of read ports = RETIRE_PORTS - always_ff @ (posedge clk) begin - if (decode_advance) - is_store_table[decode_id] <= decode_is_store; - end + lutram_1w_mr #(.DATA_TYPE(instruction_type_t), .DEPTH(MAX_IDS), .NUM_READ_PORTS(RETIRE_PORTS)) + retire_instruction_type_table ( + .clk(clk), + .waddr(decode_id), + .raddr(retire_ids_next), + .ram_write(decode_advance), + .new_ram_data('{ + is_rd : (decode_uses_rd & |decode_rd_addr), + is_store : decode_is_store + }), + .ram_data_out(retire_type) + ); //////////////////////////////////////////////////// //id_to_phys_rd_table //Number of read ports = WB_GROUPS - always_ff @ (posedge clk) begin - if (decode_advance) - id_to_phys_rd_table[decode_id] <= decode_phys_rd_addr; - end + id_t wb_ids [CONFIG.NUM_WB_GROUPS]; + always_comb for (int i = 0; i < CONFIG.NUM_WB_GROUPS; i++) + wb_ids[i] = wb_packet[i].id; + lutram_1w_mr #(.DATA_TYPE(phys_addr_t), .DEPTH(MAX_IDS), .NUM_READ_PORTS(CONFIG.NUM_WB_GROUPS)) + id_to_phys_rd_table ( + .clk(clk), + .waddr(decode_id), + .raddr(wb_ids), + .ram_write(decode_advance), + .new_ram_data(decode_phys_rd_addr), + .ram_data_out(wb_phys_addr) + ); //////////////////////////////////////////////////// //Exception unit table - always_ff @ (posedge clk) begin - if (decode_advance) - exception_unit_table[decode_id] <= decode_exception_unit; - end + generate if (CONFIG.INCLUDE_M_MODE) begin : gen_id_exception_support + lutram_1w_1r #(.DATA_TYPE(logic[$bits(exception_sources_t)-1:0]), .DEPTH(MAX_IDS)) + exception_unit_table ( + .clk(clk), + .waddr(decode_id), + .raddr(retire_ids_next[0]), + .ram_write(decode_advance), + .new_ram_data(decode_exception_unit), + .ram_data_out(current_exception_unit) + ); + end endgenerate //////////////////////////////////////////////////// //ID Management @@ -282,11 +318,6 @@ module instruction_metadata_and_id_management .in_use (id_waiting_for_writeback) ); - //////////////////////////////////////////////////// - //WB phys_addr lookup - always_comb for (int i = 0; i < CONFIG.NUM_WB_GROUPS; i++) - wb_phys_addr[i] = id_to_phys_rd_table[wb_packet[i].id]; - //////////////////////////////////////////////////// //Retirer logic contiguous_retire; @@ -294,15 +325,6 @@ module instruction_metadata_and_id_management logic id_ready_to_retire [RETIRE_PORTS]; logic [LOG2_RETIRE_PORTS-1:0] retire_with_rd_sel; logic [LOG2_RETIRE_PORTS-1:0] retire_with_store_sel; - logic [RETIRE_PORTS-1:0] retire_id_uses_rd; - logic [RETIRE_PORTS-1:0] retire_id_is_store; - logic [RETIRE_PORTS-1:0] retire_id_waiting_for_writeback; - - generate for (i = 0; i < RETIRE_PORTS; i++) begin : gen_retire_writeback - assign retire_id_uses_rd[i] = uses_rd_table[retire_ids_next[i]]; - assign retire_id_is_store[i] = is_store_table[retire_ids_next[i]]; - assign retire_id_waiting_for_writeback[i] = id_waiting_for_writeback[i]; - end endgenerate //Supports retiring up to RETIRE_PORTS instructions. The retired block of instructions must be //contiguous and must start with the first retire port. Additionally, only one register file writing @@ -315,29 +337,36 @@ module instruction_metadata_and_id_management contiguous_retire = ~gc.retire_hold; retire_with_rd_found = 0; retire_with_store_found = 0; + + retire_with_rd_sel = 0; + retire_with_store_sel = 0; for (int i = 0; i < RETIRE_PORTS; i++) begin id_is_post_issue[i] = post_issue_count > ID_COUNTER_W'(i); id_ready_to_retire[i] = (id_is_post_issue[i] & contiguous_retire & ~id_waiting_for_writeback[i]); - retire_port_valid_next[i] = id_ready_to_retire[i] & ~((retire_id_uses_rd[i] & retire_with_rd_found) | (retire_id_is_store[i] & retire_with_store_found)); + retire_port_valid_next[i] = id_ready_to_retire[i] & ~((retire_type[i].is_rd & retire_with_rd_found) | (retire_type[i].is_store & retire_with_store_found)); - retire_with_rd_found |= retire_port_valid_next[i] & retire_id_uses_rd[i]; - retire_with_store_found |= retire_port_valid_next[i] & retire_id_is_store[i]; - + retire_with_rd_found |= retire_port_valid_next[i] & retire_type[i].is_rd; + retire_with_store_found |= retire_port_valid_next[i] & retire_type[i].is_store; contiguous_retire &= retire_port_valid_next[i] & ~gc.exception_pending; + + if (retire_port_valid_next[i] & retire_type[i].is_rd) + retire_with_rd_sel = LOG2_RETIRE_PORTS'(i); + if (retire_port_valid_next[i] & retire_type[i].is_store) + retire_with_store_sel = LOG2_RETIRE_PORTS'(i); end end - //retire_next packet - priority_encoder #(.WIDTH(RETIRE_PORTS)) - retire_with_rd_sel_encoder ( - .priority_vector (retire_id_uses_rd), - .encoded_result (retire_with_rd_sel) - ); + //retire_next packets + assign wb_retire_next = '{ + id : retire_ids_next[retire_with_rd_sel], + valid : retire_with_rd_found + }; + assign store_retire_next = '{ + id : retire_ids_next[retire_with_store_sel], + valid : retire_with_store_found + }; - assign wb_retire_next.id = retire_ids_next[retire_with_rd_sel]; - assign wb_retire_next.valid = retire_with_rd_found; - always_comb begin retire_count_next = 0; for (int i = 0; i < RETIRE_PORTS; i++) begin @@ -346,42 +375,27 @@ module instruction_metadata_and_id_management end always_ff @ (posedge clk) begin - wb_retire.valid <= wb_retire_next.valid; - wb_retire.id <= wb_retire_next.id; + wb_retire <= wb_retire_next; + store_retire <= store_retire_next; retire_count <= gc.writeback_supress ? '0 : retire_count_next; for (int i = 0; i < RETIRE_PORTS; i++) retire_port_valid[i] <= retire_port_valid_next[i] & ~gc.writeback_supress; end - priority_encoder #(.WIDTH(RETIRE_PORTS)) - retire_with_store_sel_encoder ( - .priority_vector (retire_id_is_store), - .encoded_result (retire_with_store_sel) - ); - - assign store_retire_next.id = retire_ids_next[retire_with_store_sel]; - assign store_retire_next.valid = retire_with_store_found; - - always_ff @ (posedge clk) begin - store_retire <= store_retire_next; - end //////////////////////////////////////////////////// //Outputs assign pc_id_available = ~inflight_count[LOG2_MAX_IDS]; //Decode - assign decode.id = decode_id; - assign decode.valid = fetched_count_neg[LOG2_MAX_IDS]; - assign decode.pc = pc_table[decode_id]; - assign decode.instruction = instruction_table[decode_id]; - assign decode.fetch_metadata = CONFIG.INCLUDE_M_MODE ? fetch_metadata_table[decode_id] : '{ok : 1, error_code : INST_ACCESS_FAULT}; - - //Exception Support - generate if (CONFIG.INCLUDE_M_MODE) begin : gen_id_exception_support - assign oldest_pc = pc_table[retire_ids_next[0]]; - assign current_exception_unit = exception_unit_table[retire_ids_next[0]]; - end endgenerate + localparam fetch_metadata_t ADDR_OK = '{ok : 1, error_code : INST_ADDR_MISSALIGNED}; + assign decode = '{ + id : decode_id, + valid : fetched_count_neg[LOG2_MAX_IDS], + pc : decode_pc, + instruction : decode_instruction, + fetch_metadata : CONFIG.INCLUDE_M_MODE ? decode_fetch_metadata : ADDR_OK + }; //////////////////////////////////////////////////// //End of Implementation diff --git a/examples/nexys/nexys_sim.sv b/examples/nexys/nexys_sim.sv index 65e3dad..1b2a5a0 100644 --- a/examples/nexys/nexys_sim.sv +++ b/examples/nexys/nexys_sim.sv @@ -477,8 +477,8 @@ module cva5_sim assign NUM_RETIRE_PORTS = RETIRE_PORTS; generate for (genvar i = 0; i < RETIRE_PORTS; i++) begin - assign retire_ports_pc[i] = cpu.id_block.pc_table[cpu.retire_ids[i]]; - assign retire_ports_instruction[i] = cpu.id_block.instruction_table[cpu.retire_ids[i]]; + assign retire_ports_pc[i] = cpu.id_block.pc_table.ram[cpu.retire_ids[i]]; + assign retire_ports_instruction[i] = cpu.id_block.instruction_table.ram[cpu.retire_ids[i]]; assign retire_ports_valid[i] = cpu.retire_port_valid[i]; end endgenerate diff --git a/test_benches/verilator/cva5_sim.sv b/test_benches/verilator/cva5_sim.sv index 3954298..4db159f 100644 --- a/test_benches/verilator/cva5_sim.sv +++ b/test_benches/verilator/cva5_sim.sv @@ -612,8 +612,8 @@ module cva5_sim assign NUM_RETIRE_PORTS = RETIRE_PORTS; generate for (genvar i = 0; i < RETIRE_PORTS; i++) begin - assign retire_ports_pc[i] = cpu.id_block.pc_table[cpu.retire_ids[i]]; - assign retire_ports_instruction[i] = cpu.id_block.instruction_table[cpu.retire_ids[i]]; + assign retire_ports_pc[i] = cpu.id_block.pc_table.ram[cpu.retire_ids[i]]; + assign retire_ports_instruction[i] = cpu.id_block.instruction_table.ram[cpu.retire_ids[i]]; assign retire_ports_valid[i] = cpu.retire_port_valid[i]; end endgenerate From 9a188e39f9a142bcf2d176888a73483d7b8cc723 Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Tue, 11 Apr 2023 19:45:27 -0400 Subject: [PATCH 04/16] Remove unused rtl files Signed-off-by: Eric Matthews --- core/binary_occupancy.sv | 115 --------------- core/ddata_bank.sv | 47 ------- core/illegal_instruction_checker.sv | 209 ---------------------------- core/one_hot_occupancy.sv | 69 --------- core/placer_randomizer.sv | 16 --- core/shift_counter.sv | 47 ------- tools/compile_order | 4 - 7 files changed, 507 deletions(-) delete mode 100755 core/binary_occupancy.sv delete mode 100755 core/ddata_bank.sv delete mode 100644 core/illegal_instruction_checker.sv delete mode 100755 core/one_hot_occupancy.sv delete mode 100644 core/placer_randomizer.sv delete mode 100644 core/shift_counter.sv diff --git a/core/binary_occupancy.sv b/core/binary_occupancy.sv deleted file mode 100755 index 261eafb..0000000 --- a/core/binary_occupancy.sv +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright © 2017-2019 Eric Matthews, Lesley Shannon - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Initial code developed under the supervision of Dr. Lesley Shannon, - * Reconfigurable Computing Lab, Simon Fraser University. - * - * Author(s): - * Eric Matthews - */ - -module binary_occupancy - - import cva5_config::*; - import cva5_types::*; - - #(parameter DEPTH = 4) - ( - input logic clk, - input logic rst, - input logic push, - input logic pop, - output logic almost_full, - output logic full, - output logic empty, - output logic almost_empty, - output logic valid - ); - - logic[$clog2(DEPTH)-1:0] count; - - //Occupancy Tracking - always_ff @ (posedge clk) begin - if (rst) - count <= 0; - else begin - case ({push, pop}) - 2'b10: count <= count + 1; - 2'b01: count <= count - 1; - default : count <= count; - endcase - end - end - - always_ff @ (posedge clk) begin - if (rst) - valid <= 0; - else begin - case ({push, pop}) - 2'b10: valid <= 1; - 2'b01: valid <= !(count == 1); - default : valid <= valid; - endcase - end - end - - // always_ff @ (posedge clk) begin - // if (rst) - // full <= 0; - // else begin - // case ({push, pop}) - // 2'b10: full <= (count == DEPTH-2); - // 2'b01: full <= 0; - // default : full <= full; - // endcase - // end - // end - - // always_ff @ (posedge clk) begin - // if (rst) - // almost_full <= 0; - // else begin - // case ({push, pop}) - // 2'b10: almost_full <= (count == DEPTH-3); - // 2'b01: almost_full <= (count == DEPTH-1); - // default : almost_full <= almost_full; - // endcase - // end - // end - - // always_ff @ (posedge clk) begin - // if (rst) - // almost_empty <= 0; - // else begin - // case ({push, pop}) - // 2'b10: almost_empty <=(count == 0); - // 2'b01: almost_empty <= (count == 2); - // default : almost_empty <= almost_empty; - // endcase - // end - // end - - assign empty = ~valid; - - //////////////////////////////////////////////////// - //Assertions - always_ff @ (posedge clk) begin - assert (!(~rst & full & push)) else $error("overflow"); - assert (!(~rst & empty & pop)) else $error("underflow"); - end - -endmodule - - diff --git a/core/ddata_bank.sv b/core/ddata_bank.sv deleted file mode 100755 index 6f3db48..0000000 --- a/core/ddata_bank.sv +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright © 2017 Eric Matthews, Lesley Shannon - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Initial code developed under the supervision of Dr. Lesley Shannon, - * Reconfigurable Computing Lab, Simon Fraser University. - * - * Author(s): - * Eric Matthews - */ - -module ddata_bank - - import cva5_config::*; - import cva5_types::*; - - #( - parameter LINES = 2048 - ) - ( - input logic clk, - input logic[$clog2(LINES)-1:0] addr_a, - input logic en_a, - input logic[3:0] be_a, - input logic[31:0] data_in_a, - output logic[31:0] data_out_a, - - //write only port - input logic[$clog2(LINES)-1:0] addr_b, - input logic en_b, - input logic[31:0] data_in_b - ); - - byte_en_BRAM #(LINES, "", 0) ram_block (.*, .be_b({4{en_b}}), .data_out_b()); - -endmodule diff --git a/core/illegal_instruction_checker.sv b/core/illegal_instruction_checker.sv deleted file mode 100644 index 006e461..0000000 --- a/core/illegal_instruction_checker.sv +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright © 2020 Eric Matthews, Lesley Shannon - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Initial code developed under the supervision of Dr. Lesley Shannon, - * Reconfigurable Computing Lab, Simon Fraser University. - * - * Author(s): - * Eric Matthews - */ - -module illegal_instruction_checker - - import cva5_config::*; - import riscv_types::*; - - # ( - parameter cpu_config_t CONFIG = EXAMPLE_CONFIG - ) - - ( - input logic [31:0] instruction, - output logic illegal_instruction - ); - - //////////////////////////////////////////////////// - //Instruction Patterns for Illegal Instruction Checking - - //Base ISA - localparam [31:0] BEQ = 32'b?????????????????000?????1100011; - localparam [31:0] BNE = 32'b?????????????????001?????1100011; - localparam [31:0] BLT = 32'b?????????????????100?????1100011; - localparam [31:0] BGE = 32'b?????????????????101?????1100011; - localparam [31:0] BLTU = 32'b?????????????????110?????1100011; - localparam [31:0] BGEU = 32'b?????????????????111?????1100011; - localparam [31:0] JALR = 32'b?????????????????000?????1100111; - localparam [31:0] JAL = 32'b?????????????????????????1101111; - localparam [31:0] LUI = 32'b?????????????????????????0110111; - localparam [31:0] AUIPC = 32'b?????????????????????????0010111; - localparam [31:0] ADDI = 32'b?????????????????000?????0010011; - localparam [31:0] SLLI = 32'b000000???????????001?????0010011; - localparam [31:0] SLTI = 32'b?????????????????010?????0010011; - localparam [31:0] SLTIU = 32'b?????????????????011?????0010011; - localparam [31:0] XORI = 32'b?????????????????100?????0010011; - localparam [31:0] SRLI = 32'b000000???????????101?????0010011; - localparam [31:0] SRAI = 32'b010000???????????101?????0010011; - localparam [31:0] ORI = 32'b?????????????????110?????0010011; - localparam [31:0] ANDI = 32'b?????????????????111?????0010011; - localparam [31:0] ADD = 32'b0000000??????????000?????0110011; - localparam [31:0] SUB = 32'b0100000??????????000?????0110011; - localparam [31:0] SLL = 32'b0000000??????????001?????0110011; - localparam [31:0] SLT = 32'b0000000??????????010?????0110011; - localparam [31:0] SLTU = 32'b0000000??????????011?????0110011; - localparam [31:0] XOR = 32'b0000000??????????100?????0110011; - localparam [31:0] SRL = 32'b0000000??????????101?????0110011; - localparam [31:0] SRA = 32'b0100000??????????101?????0110011; - localparam [31:0] OR = 32'b0000000??????????110?????0110011; - localparam [31:0] AND = 32'b0000000??????????111?????0110011; - localparam [31:0] LB = 32'b?????????????????000?????0000011; - localparam [31:0] LH = 32'b?????????????????001?????0000011; - localparam [31:0] LW = 32'b?????????????????010?????0000011; - localparam [31:0] LBU = 32'b?????????????????100?????0000011; - localparam [31:0] LHU = 32'b?????????????????101?????0000011; - localparam [31:0] SB = 32'b?????????????????000?????0100011; - localparam [31:0] SH = 32'b?????????????????001?????0100011; - localparam [31:0] SW = 32'b?????????????????010?????0100011; - localparam [31:0] FENCE = 32'b?????????????????000?????0001111; - localparam [31:0] FENCE_I = 32'b?????????????????001?????0001111; - localparam [31:0] ECALL = 32'b00000000000000000000000001110011; - localparam [31:0] EBREAK = 32'b00000000000100000000000001110011; - - localparam [31:0] CSRRW = 32'b?????????????????001?????1110011; - localparam [31:0] CSRRS = 32'b?????????????????010?????1110011; - localparam [31:0] CSRRC = 32'b?????????????????011?????1110011; - localparam [31:0] CSRRWI = 32'b?????????????????101?????1110011; - localparam [31:0] CSRRSI = 32'b?????????????????110?????1110011; - localparam [31:0] CSRRCI = 32'b?????????????????111?????1110011; - - //Mul - localparam [31:0] MUL = 32'b0000001??????????000?????0110011; - localparam [31:0] MULH = 32'b0000001??????????001?????0110011; - localparam [31:0] MULHSU = 32'b0000001??????????010?????0110011; - localparam [31:0] MULHU = 32'b0000001??????????011?????0110011; - //Div - localparam [31:0] DIV = 32'b0000001??????????100?????0110011; - localparam [31:0] DIVU = 32'b0000001??????????101?????0110011; - localparam [31:0] REM = 32'b0000001??????????110?????0110011; - localparam [31:0] REMU = 32'b0000001??????????111?????0110011; - - //AMO - localparam [31:0] AMO_ADD = 32'b00000????????????010?????0101111; - localparam [31:0] AMO_XOR = 32'b00100????????????010?????0101111; - localparam [31:0] AMO_OR = 32'b01000????????????010?????0101111; - localparam [31:0] AMO_AND = 32'b01100????????????010?????0101111; - localparam [31:0] AMO_MIN = 32'b10000????????????010?????0101111; - localparam [31:0] AMO_MAX = 32'b10100????????????010?????0101111; - localparam [31:0] AMO_MINU = 32'b11000????????????010?????0101111; - localparam [31:0] AMO_MAXU = 32'b11100????????????010?????0101111; - localparam [31:0] AMO_SWAP = 32'b00001????????????010?????0101111; - localparam [31:0] LR = 32'b00010??00000?????010?????0101111; - localparam [31:0] SC = 32'b00011????????????010?????0101111; - - //Machine/Supervisor - localparam [31:0] SRET = 32'b00010000001000000000000001110011; - localparam [31:0] MRET = 32'b00110000001000000000000001110011; - localparam [31:0] SFENCE_VMA = 32'b0001001??????????000000001110011; - localparam [31:0] WFI = 32'b00010000010100000000000001110011; - - logic base_legal; - logic csr_legal; - logic csr_addr_base; - logic csr_addr_machine; - logic csr_addr_supervisor; - logic csr_addr_debug; - logic mul_legal; - logic div_legal; - logic ifence_legal; - logic amo_legal; - logic machine_legal; - logic supervisor_legal; - //////////////////////////////////////////////////// - //Implementation - - assign base_legal = instruction inside { - BEQ, BNE, BLT, BGE, BLTU, BGEU, JALR, JAL, LUI, AUIPC, - ADDI, SLLI, SLTI, SLTIU, XORI, SRLI, SRAI, ORI, ANDI, - ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, - LB, LH, LW, LBU, LHU, SB, SH, SW, - FENCE - }; - - assign csr_addr_base = instruction[31:20] inside { - FFLAGS, FRM, FCSR, - CYCLE, TIME, INSTRET, CYCLEH, TIMEH, INSTRETH - }; - - assign csr_addr_machine = instruction[31:20] inside { - MVENDORID, MARCHID, MIMPID, MHARTID, - MSTATUS, MISA, MEDELEG, MIDELEG, MIE, MTVEC, MCOUNTEREN, - MSCRATCH, MEPC, MCAUSE, MTVAL, MIP, - MCYCLE, MINSTRET, MCYCLEH, MINSTRETH - }; - - assign csr_addr_supervisor = instruction[31:20] inside { - SSTATUS, SEDELEG, SIDELEG, SIE, STVEC, SCOUNTEREN, - SSCRATCH, SEPC, SCAUSE, STVAL, SIP, - SATP - }; - - assign csr_addr_debug = instruction[31:20] inside { - DCSR, DPC, DSCRATCH - }; - - //Privilege check done later on instruction issue - //Here we just check instruction encoding and valid CSR address - assign csr_legal = instruction inside { - CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, CSRRCI - } && ( - csr_addr_base | - (CONFIG.INCLUDE_M_MODE & csr_addr_machine) | - (CONFIG.INCLUDE_S_MODE & csr_addr_supervisor) - ); - - assign mul_legal = instruction inside { - MUL, MULH, MULHSU, MULHU - }; - - assign div_legal = instruction inside { - DIV, DIVU, REM, REMU - }; - - assign ifence_legal = instruction inside {FENCE_I}; - - assign amo_legal = instruction inside { - AMO_ADD, AMO_XOR, AMO_OR, AMO_AND, AMO_MIN, AMO_MAX, AMO_MINU, AMO_MAXU, AMO_SWAP, - LR, SC - }; - - assign machine_legal = instruction inside { - MRET, ECALL, EBREAK - }; - - assign supervisor_legal = instruction inside { - SRET, SFENCE_VMA, WFI - }; - - assign illegal_instruction = ~( - base_legal | - (CONFIG.INCLUDE_CSRS & csr_legal) | - (CONFIG.INCLUDE_MUL & mul_legal) | - (CONFIG.INCLUDE_DIV & div_legal) | - (CONFIG.INCLUDE_AMO & amo_legal) | - (CONFIG.INCLUDE_IFENCE & ifence_legal) | - (CONFIG.INCLUDE_M_MODE & machine_legal) | - (CONFIG.INCLUDE_S_MODE & supervisor_legal) - ); - -endmodule diff --git a/core/one_hot_occupancy.sv b/core/one_hot_occupancy.sv deleted file mode 100755 index f38d04b..0000000 --- a/core/one_hot_occupancy.sv +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright © 2017-2019 Eric Matthews, Lesley Shannon - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Initial code developed under the supervision of Dr. Lesley Shannon, - * Reconfigurable Computing Lab, Simon Fraser University. - * - * Author(s): - * Eric Matthews - */ - -module one_hot_occupancy - #(parameter DEPTH = 4) - ( - input logic clk, - input logic rst, - input logic push, - input logic pop, - output logic almost_full, - output logic full, - output logic empty, - output logic almost_empty, - output logic valid - ); - - logic [DEPTH:0] valid_chain; - - //Occupancy Tracking - always_ff @ (posedge clk) begin - if (rst) begin - valid_chain[0] <= 1; - valid_chain[DEPTH:1] <= 0; - end - else begin - case({push,pop}) - 2'b10 : valid_chain <= {valid_chain[DEPTH-1:0], 1'b0}; - 2'b01 : valid_chain <= {1'b0, valid_chain[DEPTH:1]}; - default : valid_chain <= valid_chain; - endcase - end - end - - assign empty = valid_chain[0]; - assign almost_empty = valid_chain[1]; - - assign valid = ~valid_chain[0]; - assign full = valid_chain[DEPTH]; - - assign almost_full = valid_chain[DEPTH-1]; - - //////////////////////////////////////////////////// - //Assertions - always_ff @ (posedge clk) begin - assert (!(~rst & valid_chain[DEPTH] & push)) else $error("overflow"); - assert (!(~rst & valid_chain[0] & pop)) else $error("underflow"); - end - -endmodule diff --git a/core/placer_randomizer.sv b/core/placer_randomizer.sv deleted file mode 100644 index 842b6da..0000000 --- a/core/placer_randomizer.sv +++ /dev/null @@ -1,16 +0,0 @@ -module placer_randomizer # ( - parameter logic [7:0] PLACER_SEED = 8'h2B - ) - ( - input logic clk, - input logic [7:0] samples, - output logic result - ); - - always_ff @(posedge clk) begin - result <= |(samples & PLACER_SEED); - end - -endmodule - - diff --git a/core/shift_counter.sv b/core/shift_counter.sv deleted file mode 100644 index 079d64f..0000000 --- a/core/shift_counter.sv +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright © 2019 Eric Matthews, Lesley Shannon - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Initial code developed under the supervision of Dr. Lesley Shannon, - * Reconfigurable Computing Lab, Simon Fraser University. - * - * Author(s): - * Eric Matthews - */ - -module shift_counter - - import cva5_config::*; - import cva5_types::*; - - #(parameter DEPTH = 16) - ( - input logic clk, - input logic rst, - input logic start, - output logic done - ); - - logic [DEPTH-1:0] counter; - //////////////////////////////////////////////////// - //Implementation - - //TLB_CLEAR state shift reg - always_ff @ (posedge clk) begin - counter[0] <= start; - counter[DEPTH-1:1] <= counter[DEPTH-2:0]; - end - assign done = counter[DEPTH-1]; - -endmodule diff --git a/tools/compile_order b/tools/compile_order index b80ac0e..af96faa 100644 --- a/tools/compile_order +++ b/tools/compile_order @@ -17,13 +17,10 @@ core/lutrams/lutram_1w_1r.sv core/lutrams/lutram_1w_mr.sv core/set_clr_reg_with_rst.sv -core/one_hot_occupancy.sv -core/binary_occupancy.sv core/one_hot_to_integer.sv core/cycler.sv core/lfsr.sv core/cva5_fifo.sv -core/shift_counter.sv core/priority_encoder.sv core/toggle_memory.sv @@ -76,7 +73,6 @@ core/branch_predictor_ram.sv core/branch_predictor.sv core/fetch.sv -core/illegal_instruction_checker.sv core/decode_and_issue.sv core/register_free_list.sv From 38d0336d9ebe0c65abbc5c4570c87f23a579f901 Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Wed, 12 Apr 2023 19:39:47 -0400 Subject: [PATCH 05/16] Move store-data-marshalling to retire Signed-off-by: Eric Matthews --- core/store_queue.sv | 70 +++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/core/store_queue.sv b/core/store_queue.sv index 1c7d5c6..35821fd 100644 --- a/core/store_queue.sv +++ b/core/store_queue.sv @@ -59,7 +59,6 @@ module store_queue logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] wb_group; sq_index_t sq_index; } retire_table_t; - retire_table_t retire_table_in; retire_table_t retire_table_out; wb_packet_t wb_snoop [CONFIG.NUM_WB_GROUPS]; @@ -70,9 +69,9 @@ module store_queue addr_hash_t [CONFIG.SQ_DEPTH-1:0] hashes; //LUTRAM-based memory blocks - sq_entry_t sq_entry_in; sq_entry_t output_entry; sq_entry_t output_entry_r; + logic [1:0] retire_alignment; sq_index_t sq_index_next; sq_index_t sq_oldest_next; @@ -82,6 +81,7 @@ module store_queue logic [CONFIG.SQ_DEPTH-1:0] issued_one_hot; logic [31:0] data_pre_alignment; + logic [31:0] marshalled_data; logic [31:0] sq_data_out; //////////////////////////////////////////////////// //Implementation @@ -116,24 +116,32 @@ module store_queue assign sq.empty = ~|valid; //SQ attributes and issue data - assign sq_entry_in = '{ - addr : sq.data_in.addr, - be : sq.data_in.be, - data : '0 - }; lutram_1w_1r #(.DATA_TYPE(sq_entry_t), .DEPTH(CONFIG.SQ_DEPTH)) store_attr ( .clk(clk), .waddr(sq_index), .raddr(sq_oldest_next), .ram_write(sq.push), - .new_ram_data(sq_entry_in), + .new_ram_data('{ + addr : sq.data_in.addr, + be : sq.data_in.be, + data : '0 + }), .ram_data_out(output_entry) ); always_ff @ (posedge clk) begin output_entry_r <= output_entry; end - + + lutram_1w_1r #(.DATA_TYPE(logic[1:0]), .DEPTH(MAX_IDS)) + store_alignment ( + .clk(clk), + .waddr(sq.data_in.id), + .raddr(store_retire.id), + .ram_write(sq.push), + .new_ram_data(sq.data_in.addr[1:0]), + .ram_data_out(retire_alignment) + ); //Compare store addr-hashes against new load addr-hash always_comb begin potential_store_conflict = 0; @@ -169,14 +177,17 @@ module store_queue wb_snoop <= wb_packet; end - assign retire_table_in = '{id_needed : sq.data_in.id_needed, wb_group : store_forward_wb_group, sq_index : sq_index}; lutram_1w_1r #(.DATA_TYPE(retire_table_t), .DEPTH(MAX_IDS)) store_retire_table_lutram ( .clk(clk), .waddr(sq.data_in.id), .raddr(store_retire.id), .ram_write(sq.push), - .new_ram_data(retire_table_in), + .new_ram_data('{ + id_needed : sq.data_in.id_needed, + wb_group : store_forward_wb_group, + sq_index : sq_index + }), .ram_data_out(retire_table_out) ); @@ -208,6 +219,24 @@ module store_queue end endgenerate + //////////////////////////////////////////////////// + //Data Marshalling + assign data_pre_alignment = wb_data[retire_table_out.wb_group]; + always_comb begin + //Input: ABCD + //Assuming aligned requests, + //Possible byte selections: (A/C/D, B/D, C/D, D) + marshalled_data[7:0] = data_pre_alignment[7:0]; + marshalled_data[15:8] = (retire_alignment[1:0] == 2'b01) ? data_pre_alignment[7:0] : data_pre_alignment[15:8]; + marshalled_data[23:16] = (retire_alignment[1:0] == 2'b10) ? data_pre_alignment[7:0] : data_pre_alignment[23:16]; + case(retire_alignment[1:0]) + 2'b10 : marshalled_data[31:24] = data_pre_alignment[15:8]; + 2'b11 : marshalled_data[31:24] = data_pre_alignment[7:0]; + default : marshalled_data[31:24] = data_pre_alignment[31:24]; + endcase + end + + //Final storage table for the store queue //SQ-index addressed lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(CONFIG.SQ_DEPTH)) @@ -216,24 +245,9 @@ module store_queue .waddr(retire_table_out.sq_index), .raddr(sq_oldest), .ram_write(store_retire.valid), - .new_ram_data(wb_data[retire_table_out.wb_group]), - .ram_data_out(data_pre_alignment) + .new_ram_data(marshalled_data), + .ram_data_out(sq_data_out) ); - //////////////////////////////////////////////////// - //Store Transaction Outputs - always_comb begin - //Input: ABCD - //Assuming aligned requests, - //Possible byte selections: (A/C/D, B/D, C/D, D) - sq_data_out[7:0] = data_pre_alignment[7:0]; - sq_data_out[15:8] = (output_entry_r.addr[1:0] == 2'b01) ? data_pre_alignment[7:0] : data_pre_alignment[15:8]; - sq_data_out[23:16] = (output_entry_r.addr[1:0] == 2'b10) ? data_pre_alignment[7:0] : data_pre_alignment[23:16]; - case(output_entry_r.addr[1:0]) - 2'b10 : sq_data_out[31:24] = data_pre_alignment[15:8]; - 2'b11 : sq_data_out[31:24] = data_pre_alignment[7:0]; - default : sq_data_out[31:24] = data_pre_alignment[31:24]; - endcase - end assign sq.valid = |released_count; assign sq.data_out = '{ From a5b8088b10246692158d9f5bc42b72e7db340529 Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Fri, 14 Apr 2023 15:42:46 -0400 Subject: [PATCH 06/16] CSR unit cleanups Signed-off-by: Eric Matthews --- core/csr_unit.sv | 527 ++++++++++++++++++++++++----------------------- 1 file changed, 269 insertions(+), 258 deletions(-) diff --git a/core/csr_unit.sv b/core/csr_unit.sv index 3781fc8..394a456 100755 --- a/core/csr_unit.sv +++ b/core/csr_unit.sv @@ -90,9 +90,19 @@ module csr_unit logic[1:0] op; logic reads; logic writes; - logic [XLEN-1:0] data; + logic [31:0] data; } csr_inputs_t; + typedef enum logic [2:0] { + MSTATUS_UNCHANGED = 0, + MSTATUS_WRITE = 1, + MSTATUS_INTERRUPT = 2, + MSTATUS_EXCEPTION = 3, + MSTATUS_MRET = 4, + MSTATUS_SRET = 5 + } mstatus_cases_t; + mstatus_cases_t mstatus_case; + logic busy; logic commit; logic commit_in_progress; @@ -104,23 +114,79 @@ module csr_unit privilege_t next_privilege_level; //write_logic - logic supervisor_write; - logic machine_write; + logic swrite; + logic mwrite; + logic [255:0] sub_write_en; - logic [XLEN-1:0] selected_csr; - logic [XLEN-1:0] selected_csr_r; + logic [31:0] selected_csr; + logic [31:0] selected_csr_r; logic [31:0] updated_csr; - logic swrite; - logic mwrite; - function logic mwrite_en (input csr_addr_t addr); - return mwrite & (csr_inputs_r.addr.sub_addr == addr.sub_addr); + return mwrite & sub_write_en[addr.sub_addr]; endfunction function logic swrite_en (input csr_addr_t addr); - return swrite & (csr_inputs_r.addr.sub_addr == addr.sub_addr); + return swrite & sub_write_en[addr.sub_addr]; endfunction + + //////////////////////////////////////////////////// + //Legalization Functions + function logic [31:0] init_medeleg_mask(); + init_medeleg_mask = 0; + if (CONFIG.INCLUDE_S_MODE) begin + init_medeleg_mask[INST_ADDR_MISSALIGNED] = 1; + init_medeleg_mask[INST_ACCESS_FAULT] = 1; + init_medeleg_mask[ILLEGAL_INST] = 1; + init_medeleg_mask[BREAK] = 1; + init_medeleg_mask[LOAD_ADDR_MISSALIGNED] = 1; + init_medeleg_mask[LOAD_FAULT] = 1; + init_medeleg_mask[STORE_AMO_ADDR_MISSALIGNED] = 1; + init_medeleg_mask[STORE_AMO_FAULT] = 1; + init_medeleg_mask[ECALL_U] = 1; + init_medeleg_mask[INST_PAGE_FAULT] = 1; + init_medeleg_mask[LOAD_PAGE_FAULT] = 1; + init_medeleg_mask[STORE_OR_AMO_PAGE_FAULT] = 1; + end + endfunction + + function logic [31:0] init_mideleg_mask(); + init_mideleg_mask = 0; + if (CONFIG.INCLUDE_S_MODE) begin + init_mideleg_mask[S_SOFTWARE_INTERRUPT] = CONFIG.INCLUDE_S_MODE; + init_mideleg_mask[S_TIMER_INTERRUPT] = CONFIG.INCLUDE_S_MODE; + init_mideleg_mask[S_EXTERNAL_INTERRUPT] = CONFIG.INCLUDE_S_MODE; + end + endfunction + + function logic [2**ECODE_W-1:0] init_exception_masking_rom(); + init_exception_masking_rom = '{default: 0}; + init_exception_masking_rom[INST_ADDR_MISSALIGNED] = 1; + init_exception_masking_rom[INST_ACCESS_FAULT] = CONFIG.INCLUDE_S_MODE; + init_exception_masking_rom[ILLEGAL_INST] = 1; + init_exception_masking_rom[BREAK] = 1; + init_exception_masking_rom[LOAD_ADDR_MISSALIGNED] = 1; + init_exception_masking_rom[LOAD_FAULT] = CONFIG.INCLUDE_S_MODE; + init_exception_masking_rom[STORE_AMO_ADDR_MISSALIGNED] = 1; + init_exception_masking_rom[STORE_AMO_FAULT] = CONFIG.INCLUDE_S_MODE; + init_exception_masking_rom[ECALL_U] = CONFIG.INCLUDE_S_MODE; + init_exception_masking_rom[ECALL_S] = CONFIG.INCLUDE_S_MODE; + init_exception_masking_rom[ECALL_M] = 1; + init_exception_masking_rom[INST_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE; + init_exception_masking_rom[LOAD_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE; + init_exception_masking_rom[STORE_OR_AMO_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE; + endfunction + + function logic [2**ECODE_W-1:0] init_interrupt_masking_rom(); + init_interrupt_masking_rom = '{default: 0}; + init_interrupt_masking_rom[S_SOFTWARE_INTERRUPT] = CONFIG.INCLUDE_S_MODE; + init_interrupt_masking_rom[M_SOFTWARE_INTERRUPT] = 1; + init_interrupt_masking_rom[S_TIMER_INTERRUPT] = CONFIG.INCLUDE_S_MODE; + init_interrupt_masking_rom[M_TIMER_INTERRUPT] = 1; + init_interrupt_masking_rom[S_EXTERNAL_INTERRUPT] = CONFIG.INCLUDE_S_MODE; + init_interrupt_masking_rom[M_EXTERNAL_INTERRUPT] = 1; + endfunction + //////////////////////////////////////////////////// //Implementation @@ -134,11 +200,13 @@ module csr_unit end //////////////////////////////////////////////////// //Issue - assign csr_inputs.addr = issue_stage.instruction[31:20]; - assign csr_inputs.op = issue_stage.fn3[1:0]; - assign csr_inputs.data = issue_stage.fn3[2] ? {27'b0, issue_rs_addr[RS1]} : rf[RS1]; - assign csr_inputs.reads = ~((issue_stage.fn3[1:0] == CSR_RW) && (issue_stage.rd_addr == 0)); - assign csr_inputs.writes = ~((issue_stage.fn3[1:0] == CSR_RC) && (issue_rs_addr[RS1] == 0)); + assign csr_inputs = '{ + addr : issue_stage.instruction[31:20], + op : issue_stage.fn3[1:0], + data : issue_stage.fn3[2] ? {27'b0, issue_rs_addr[RS1]} : rf[RS1], + reads : ~((issue_stage.fn3[1:0] == CSR_RW) && (issue_stage.rd_addr == 0)), + writes : ~((issue_stage.fn3[1:0] == CSR_RC) && (issue_rs_addr[RS1] == 0)) + }; assign processing_csr = busy | issue.new_request; @@ -184,8 +252,9 @@ module csr_unit assign wb.rd = selected_csr_r; //////////////////////////////////////////////////// - //Shared logic + //Shared logic always_ff @(posedge clk) begin + sub_write_en <= (1 << csr_inputs_r.addr.sub_addr); mwrite <= CONFIG.INCLUDE_M_MODE && commit && (csr_inputs_r.addr.rw_bits != CSR_READ_ONLY && csr_inputs_r.addr.privilege == MACHINE_PRIVILEGE); swrite <= CONFIG.INCLUDE_S_MODE && commit && (csr_inputs_r.addr.rw_bits != CSR_READ_ONLY && csr_inputs_r.addr.privilege == SUPERVISOR_PRIVILEGE); end @@ -210,87 +279,90 @@ module csr_unit //////////////////////////////////////////////////// //Machine ISA register - 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)}; + localparam 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 = CONFIG.CSRS.MACHINE_IMPLEMENTATION_ID; - const logic [XLEN-1:0] mhartid = CONFIG.CSRS.CPU_ID; + localparam logic [31:0] mvendorid = 0; + localparam logic [31:0] marchid = 0; + localparam logic [31:0] mimpid = CONFIG.CSRS.MACHINE_IMPLEMENTATION_ID; + localparam logic [31:0] mhartid = CONFIG.CSRS.CPU_ID; //////////////////////////////////////////////////// //MSTATUS - const logic [XLEN-1:0] mstatush = 0; //Always little endian + localparam logic [31:0] mstatush = 0; //Always little endian //////////////////////////////////////////////////// //Non-Constant Registers mstatus_t mstatus; - - logic[XLEN-1:0] mtvec; - logic[XLEN-1:0] medeleg; - logic[XLEN-1:0] mideleg; - mip_t mip, mip_mask, mip_w_mask, mip_new; - mie_t mie, mie_mask; - mip_t sip_mask; - mie_t sie_mask; - - logic[XLEN-1:0] mepc; - - logic[XLEN-1:0] mtimecmp; - + logic[31:0] mtvec; + logic[31:0] medeleg; + logic[31:0] mideleg; + logic[31:0] mepc; + mip_t mip, mip_new; + mie_t mie; mcause_t mcause; - logic[XLEN-1:0] mtval; - - logic[XLEN-1:0] mscratch; + logic[31:0] mtval; + logic[31:0] mscratch; //Virtualization support: TSR, TW, TVM unused //Extension context status: SD, FS, XS unused - const mstatus_t mstatus_mask = - '{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)}; + localparam mstatus_t mstatus_mask = '{ + 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}; + localparam mstatus_t sstatus_mask = '{default:0, mxr:1, sum:1, spp:1, spie:1, sie:1}; + + localparam mip_t sip_mask = '{default:0, seip:CONFIG.INCLUDE_S_MODE, stip:CONFIG.INCLUDE_S_MODE, ssip:CONFIG.INCLUDE_S_MODE}; + localparam mie_t sie_mask = '{default:0, seie:CONFIG.INCLUDE_S_MODE, stie:CONFIG.INCLUDE_S_MODE, ssie:CONFIG.INCLUDE_S_MODE}; generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode - - privilege_t trap_return_privilege_level; - privilege_t exception_privilege_level; - privilege_t interrupt_privilege_level; - - mstatus_t mstatus_exception; - mstatus_t mstatus_return; mstatus_t mstatus_new; - + mstatus_t mstatus_write_mask; logic [ECODE_W-1:0] interrupt_cause_r; //Interrupt and Exception Delegation //Can delegate to supervisor if currently in supervisor or user modes - always_comb begin - exception_privilege_level = MACHINE_PRIVILEGE; - interrupt_privilege_level = MACHINE_PRIVILEGE; - if (CONFIG.INCLUDE_S_MODE && privilege_level inside {SUPERVISOR_PRIVILEGE, USER_PRIVILEGE}) begin - if (exception.valid & medeleg[exception.code]) - exception_privilege_level = SUPERVISOR_PRIVILEGE; - if (interrupt_taken & mideleg[interrupt_cause_r]) - interrupt_privilege_level = SUPERVISOR_PRIVILEGE; - end - end + logic can_delegate; + logic exception_delegated; + logic interrupt_delegated; - //return from trap privilege determination - assign trap_return_privilege_level = mret ? privilege_t'(mstatus.mpp) : privilege_t'({1'b0,mstatus.spp}); + assign can_delegate = CONFIG.INCLUDE_S_MODE & privilege_level inside {SUPERVISOR_PRIVILEGE, USER_PRIVILEGE}; + assign exception_delegated = can_delegate & exception.valid & medeleg[exception.code]; + assign interrupt_delegated = can_delegate & interrupt_taken & mideleg[interrupt_cause_r]; + + one_hot_to_integer #(6) + mstatus_case_one_hot ( + .one_hot ({sret, mret, exception.valid, interrupt_taken, (mwrite_en(MSTATUS) | swrite_en(SSTATUS)), 1'b0}), + .int_out (mstatus_case) + ); always_comb begin - if(mret | sret) - next_privilege_level = trap_return_privilege_level; - else if (interrupt_taken) - next_privilege_level = interrupt_privilege_level; - else if (exception.valid) - next_privilege_level = exception_privilege_level; - else - next_privilege_level = privilege_level; + case (mstatus_case) inside + MSTATUS_MRET : next_privilege_level = privilege_t'(mstatus.mpp); + MSTATUS_SRET : next_privilege_level = privilege_t'({1'b0,mstatus.spp}); + MSTATUS_INTERRUPT : next_privilege_level = interrupt_delegated ? SUPERVISOR_PRIVILEGE : MACHINE_PRIVILEGE; + MSTATUS_EXCEPTION : next_privilege_level = exception_delegated ? SUPERVISOR_PRIVILEGE : MACHINE_PRIVILEGE; + default : next_privilege_level = privilege_level; + endcase end //Current privilege level @@ -302,51 +374,39 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode end assign current_privilege = privilege_level; - always_comb begin - mstatus_exception = mstatus; - case (next_privilege_level) - SUPERVISOR_PRIVILEGE: begin - mstatus_exception.spie = (privilege_level == SUPERVISOR_PRIVILEGE) ? mstatus.sie : 0; - mstatus_exception.sie = 0; - mstatus_exception.spp = privilege_level[0]; //one if from supervisor-mode, zero if from user-mode - end - default: begin - mstatus_exception.mpie = (privilege_level == MACHINE_PRIVILEGE) ? mstatus.mie : ((privilege_level == SUPERVISOR_PRIVILEGE) ? mstatus.sie : 0); - mstatus_exception.mie = 0; - mstatus_exception.mpp = privilege_level; //machine,supervisor or user - end - endcase - end - - //return from trap - always_comb begin - mstatus_return = mstatus; - if (sret) begin - mstatus_return.sie = mstatus.spie; - mstatus_return.spie = 1; - mstatus_return.spp = USER_PRIVILEGE[0]; - mstatus_return.mprv = 0; - end - else if (mret) begin - mstatus_return.mie = mstatus.mpie; - mstatus_return.mpie = 1; - mstatus_return.mpp = CONFIG.INCLUDE_U_MODE ? USER_PRIVILEGE : MACHINE_PRIVILEGE; - if (mstatus.mpp != MACHINE_PRIVILEGE) - mstatus_return.mprv = 0; - end - end - - mstatus_t mstatus_write_mask; assign mstatus_write_mask = swrite ? sstatus_mask : mstatus_mask; always_comb begin mstatus_new = mstatus; - if (mwrite_en(MSTATUS) | swrite_en(SSTATUS)) - mstatus_new = (mstatus & ~mstatus_write_mask) | (updated_csr & mstatus_write_mask); - else if (interrupt_taken | exception.valid) - mstatus_new = mstatus_exception; - else if (mret | sret) - mstatus_new = mstatus_return; + case (mstatus_case) inside + MSTATUS_WRITE : mstatus_new = (mstatus & ~mstatus_write_mask) | (updated_csr & mstatus_write_mask); + MSTATUS_MRET : begin + mstatus_new.mie = mstatus.mpie; + mstatus_new.mpie = 1; + mstatus_new.mpp = CONFIG.INCLUDE_U_MODE ? USER_PRIVILEGE : MACHINE_PRIVILEGE; + if (mstatus.mpp != MACHINE_PRIVILEGE) + mstatus_new.mprv = 0; + end + MSTATUS_SRET : begin + mstatus_new.sie = mstatus.spie; + mstatus_new.spie = 1; + mstatus_new.spp = USER_PRIVILEGE[0]; + mstatus_new.mprv = 0; + end + MSTATUS_INTERRUPT, MSTATUS_EXCEPTION : begin + if (next_privilege_level == SUPERVISOR_PRIVILEGE) begin + mstatus_new.spie = (privilege_level == SUPERVISOR_PRIVILEGE) ? mstatus.sie : 0; + mstatus_new.sie = 0; + mstatus_new.spp = privilege_level[0]; //one if from supervisor-mode, zero if from user-mode + end + else begin + mstatus_new.mpie = (privilege_level == MACHINE_PRIVILEGE) ? mstatus.mie : ((privilege_level == SUPERVISOR_PRIVILEGE) ? mstatus.sie : 0); + mstatus_new.mie = 0; + mstatus_new.mpp = privilege_level; //machine,supervisor or user + end + end + default : mstatus_new = mstatus; + endcase end always_ff @(posedge clk) begin @@ -363,31 +423,13 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode always_ff @(posedge clk) begin mtvec[1:0] <= '0; if (CONFIG.CSRS.NON_STANDARD_OPTIONS.MTVEC_WRITEABLE & mwrite_en(MTVEC)) - mtvec[XLEN-1:2] <= updated_csr[XLEN-1:2]; + mtvec[31:2] <= updated_csr[31:2]; end assign exception_target_pc = mtvec; //////////////////////////////////////////////////// //MEDELEG - logic [31:0] medeleg_mask; - always_comb begin - medeleg_mask = 0; - if (CONFIG.INCLUDE_S_MODE) begin - medeleg_mask[INST_ADDR_MISSALIGNED] = 1; - medeleg_mask[INST_ACCESS_FAULT] = 1; - medeleg_mask[ILLEGAL_INST] = 1; - medeleg_mask[BREAK] = 1; - medeleg_mask[LOAD_ADDR_MISSALIGNED] = 1; - medeleg_mask[LOAD_FAULT] = 1; - medeleg_mask[STORE_AMO_ADDR_MISSALIGNED] = 1; - medeleg_mask[STORE_AMO_FAULT] = 1; - medeleg_mask[ECALL_U] = 1; - medeleg_mask[INST_PAGE_FAULT] = 1; - medeleg_mask[LOAD_PAGE_FAULT] = 1; - medeleg_mask[STORE_OR_AMO_PAGE_FAULT] = 1; - end - end - + localparam logic [31:0] medeleg_mask = init_medeleg_mask(); always_ff @(posedge clk) begin if (rst) medeleg <= '0; @@ -397,15 +439,7 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode //////////////////////////////////////////////////// //MIDELEG - logic [31:0] mideleg_mask; - always_comb begin - mideleg_mask = 0; - 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 + localparam logic [31:0] mideleg_mask = init_mideleg_mask(); always_ff @(posedge clk) begin if (rst) mideleg <= '0; @@ -415,8 +449,8 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode //////////////////////////////////////////////////// //MIP - 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}; - assign mip_w_mask = '{default:0, seip:CONFIG.INCLUDE_S_MODE, stip:CONFIG.INCLUDE_S_MODE, ssip:CONFIG.INCLUDE_S_MODE}; + localparam mip_t 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}; + localparam mip_t mip_w_mask = '{default:0, seip:CONFIG.INCLUDE_S_MODE, stip:CONFIG.INCLUDE_S_MODE, ssip:CONFIG.INCLUDE_S_MODE}; always_comb begin mip_new = '0; @@ -441,9 +475,7 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode //////////////////////////////////////////////////// //MIE - 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}; - + localparam mie_t 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}; always_ff @(posedge clk) begin if (rst) mie <= '0; @@ -458,7 +490,7 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode always_ff @(posedge clk) begin mepc[1:0] <= '0; if (mwrite_en(MEPC) | exception.valid | interrupt_taken) - mepc[XLEN-1:2] <= (exception.valid | interrupt_taken) ? exception.pc[XLEN-1:2] : updated_csr[XLEN-1:2]; + mepc[31:2] <= (exception.valid | interrupt_taken) ? exception.pc[31:2] : updated_csr[31:2]; end assign epc = mepc; @@ -468,37 +500,12 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode //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 M_EXCEPTION_MASKING_ROM [2**ECODE_W]; - logic M_INTERRUPT_MASKING_ROM [2**ECODE_W]; - always_comb begin - M_EXCEPTION_MASKING_ROM = '{default: 0}; - M_EXCEPTION_MASKING_ROM[INST_ADDR_MISSALIGNED] = 1; - M_EXCEPTION_MASKING_ROM[INST_ACCESS_FAULT] = CONFIG.INCLUDE_S_MODE; - M_EXCEPTION_MASKING_ROM[ILLEGAL_INST] = 1; - M_EXCEPTION_MASKING_ROM[BREAK] = 1; - M_EXCEPTION_MASKING_ROM[LOAD_ADDR_MISSALIGNED] = 1; - M_EXCEPTION_MASKING_ROM[LOAD_FAULT] = CONFIG.INCLUDE_S_MODE; - M_EXCEPTION_MASKING_ROM[STORE_AMO_ADDR_MISSALIGNED] = 1; - M_EXCEPTION_MASKING_ROM[STORE_AMO_FAULT] = CONFIG.INCLUDE_S_MODE; - M_EXCEPTION_MASKING_ROM[ECALL_U] = CONFIG.INCLUDE_S_MODE; - M_EXCEPTION_MASKING_ROM[ECALL_S] = CONFIG.INCLUDE_S_MODE; - M_EXCEPTION_MASKING_ROM[ECALL_M] = 1; - M_EXCEPTION_MASKING_ROM[INST_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE; - M_EXCEPTION_MASKING_ROM[LOAD_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE; - M_EXCEPTION_MASKING_ROM[STORE_OR_AMO_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE; - - M_INTERRUPT_MASKING_ROM = '{default: 0}; - M_INTERRUPT_MASKING_ROM[S_SOFTWARE_INTERRUPT] = CONFIG.INCLUDE_S_MODE; - M_INTERRUPT_MASKING_ROM[M_SOFTWARE_INTERRUPT] = 1; - M_INTERRUPT_MASKING_ROM[S_TIMER_INTERRUPT] = CONFIG.INCLUDE_S_MODE; - M_INTERRUPT_MASKING_ROM[M_TIMER_INTERRUPT] = 1; - M_INTERRUPT_MASKING_ROM[S_EXTERNAL_INTERRUPT] = CONFIG.INCLUDE_S_MODE; - M_INTERRUPT_MASKING_ROM[M_EXTERNAL_INTERRUPT] = 1; - end + localparam logic [2**ECODE_W-1:0] M_EXCEPTION_MASKING_ROM = init_exception_masking_rom(); + localparam logic [2**ECODE_W-1:0] M_INTERRUPT_MASKING_ROM = init_interrupt_masking_rom(); logic mcause_write_valid; always_comb begin - if (updated_csr[XLEN-1]) //interrupt + if (updated_csr[31]) //interrupt mcause_write_valid = M_INTERRUPT_MASKING_ROM[updated_csr[ECODE_W-1:0]]; else mcause_write_valid = M_EXCEPTION_MASKING_ROM[updated_csr[ECODE_W-1:0]]; @@ -508,7 +515,7 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode logic [5:0] mip_priority_vector; logic [2:0] mip_cause_sel; - const logic [ECODE_W-1:0] interruput_code_table [7:0] = '{ 0, 0, + localparam logic [ECODE_W-1:0] interruput_code_table [7:0] = '{ 0, 0, M_EXTERNAL_INTERRUPT, M_TIMER_INTERRUPT, M_SOFTWARE_INTERRUPT, S_EXTERNAL_INTERRUPT, S_TIMER_INTERRUPT, S_SOFTWARE_INTERRUPT }; @@ -533,7 +540,7 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode mcause.code <= 0; end else if (CONFIG.CSRS.NON_STANDARD_OPTIONS.INCLUDE_MCAUSE & ((mcause_write_valid & mwrite_en(MCAUSE)) | exception.valid | interrupt_taken)) begin - mcause.is_interrupt <= interrupt_taken | (mwrite_en(MCAUSE) & updated_csr[XLEN-1]); + mcause.is_interrupt <= interrupt_taken | (mwrite_en(MCAUSE) & updated_csr[31]); mcause.code <= interrupt_taken ? interrupt_cause_r : exception.valid ? exception.code : updated_csr[ECODE_W-1:0]; end end @@ -573,20 +580,20 @@ endgenerate //////////////////////////////////////////////////// //BEGIN OF SUPERVISOR REGS //////////////////////////////////////////////////// - logic[XLEN-1:0] sepc; + logic[31:0] sepc; - logic[XLEN-1:0] stime; - logic[XLEN-1:0] stimecmp; + logic[31:0] stime; + logic[31:0] stimecmp; - logic[XLEN-1:0] scause; - logic[XLEN-1:0] stval; + logic[31:0] scause; + logic[31:0] stval; - logic[XLEN-1:0] sstatus; - logic[XLEN-1:0] stvec; + logic[31:0] sstatus; + logic[31:0] stvec; satp_t satp; - logic[XLEN-1:0] sscratch; + logic[31:0] sscratch; //TLB status --- used to mux physical/virtual address assign tlb_on = CONFIG.INCLUDE_S_MODE & satp.mode; @@ -606,21 +613,19 @@ generate if (CONFIG.INCLUDE_S_MODE) begin : gen_csr_s_mode assign dmmu.satp_ppn = satp.ppn; //////////////////////////////////////////////////// - assign sip_mask = '{default:0, seip:1, stip:1, ssip:1}; - //////////////////////////////////////////////////// //STVEC logic [31:0] stvec_mask = '1; always_ff @(posedge clk) begin if (rst) - stvec <= {CONFIG.CSRS.RESET_VEC[XLEN-1:2], 2'b00}; + stvec <= {CONFIG.CSRS.RESET_VEC[31:2], 2'b00}; else if (swrite_en(STVEC)) stvec <= (updated_csr & stvec_mask); end //////////////////////////////////////////////////// //SATP - logic[XLEN-1:0] satp_mask; + logic[31:0] satp_mask; assign satp_mask = '1; always_ff @(posedge clk) begin if (rst) @@ -648,122 +653,128 @@ endgenerate //Timers and Counters //Register increment for instructions completed //Increments suppressed on writes to these registers - logic[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:0] mcycle; - logic[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:0] mtime; - logic[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:0] minst_ret; + localparam COUNTER_W = CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W; + localparam MCYCLE_WRITEABLE = CONFIG.CSRS.NON_STANDARD_OPTIONS.MCYCLE_WRITEABLE; + localparam MINSTR_WRITEABLE = CONFIG.CSRS.NON_STANDARD_OPTIONS.MINSTR_WRITEABLE; - logic[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:0] mcycle_input_next; - logic[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:0] minst_ret_input_next; + logic[COUNTER_W-1:0] mcycle; + logic[COUNTER_W-1:0] mtime; + logic[COUNTER_W-1:0] minst_ret; + + logic[COUNTER_W-1:0] mcycle_input_next; + logic[COUNTER_W-1:0] minst_ret_input_next; logic[LOG2_RETIRE_PORTS:0] minst_ret_inc; logic mcycle_inc; - always_comb begin - mcycle_input_next = mcycle; - if (CONFIG.CSRS.NON_STANDARD_OPTIONS.MCYCLE_WRITEABLE & mwrite_en(MCYCLE)) - mcycle_input_next[31:0] = updated_csr; - if (CONFIG.CSRS.NON_STANDARD_OPTIONS.MCYCLE_WRITEABLE & mwrite_en(MCYCLEH)) - mcycle_input_next[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:32] = updated_csr[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-33:0]; - end - - assign mcycle_inc = ~(CONFIG.CSRS.NON_STANDARD_OPTIONS.MCYCLE_WRITEABLE & (mwrite_en(MCYCLE) | mwrite_en(MCYCLEH))); + assign mcycle_input_next[31:0] = (MCYCLE_WRITEABLE & mwrite_en(MCYCLE)) ? updated_csr : mcycle[31:0]; + assign mcycle_input_next[COUNTER_W-1:32] = (MCYCLE_WRITEABLE & mwrite_en(MCYCLE)) ? updated_csr[COUNTER_W-33:0] : mcycle[COUNTER_W-1:32]; + assign mcycle_inc = ~(MCYCLE_WRITEABLE & (mwrite_en(MCYCLE) | mwrite_en(MCYCLEH))); always_ff @(posedge clk) begin if (rst) mcycle <= 0; else - mcycle <= mcycle_input_next + CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W'(mcycle_inc); + mcycle <= mcycle_input_next + COUNTER_W'(mcycle_inc); end - always_comb begin - minst_ret_input_next = minst_ret; - if (CONFIG.CSRS.NON_STANDARD_OPTIONS.MINSTR_WRITEABLE & mwrite_en(MINSTRET)) - minst_ret_input_next[31:0] = updated_csr; - if (CONFIG.CSRS.NON_STANDARD_OPTIONS.MINSTR_WRITEABLE & mwrite_en(MINSTRETH)) - minst_ret_input_next[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:32] = updated_csr[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-33:0]; - end - - assign minst_ret_inc = {(LOG2_RETIRE_PORTS+1){~(CONFIG.CSRS.NON_STANDARD_OPTIONS.MINSTR_WRITEABLE & (mwrite_en(MINSTRET) | mwrite_en(MINSTRETH)))}} & retire_count; - + assign minst_ret_input_next[31:0] = (MINSTR_WRITEABLE & mwrite_en(MINSTRET)) ? updated_csr : minst_ret[31:0]; + assign minst_ret_input_next[COUNTER_W-1:32] = (MINSTR_WRITEABLE & mwrite_en(MINSTRET)) ? updated_csr[COUNTER_W-33:0] : minst_ret[COUNTER_W-1:32]; + assign minst_ret_inc = (MINSTR_WRITEABLE & (mwrite_en(MINSTRET) | mwrite_en(MINSTRETH))) ? '0 : retire_count; + always_ff @(posedge clk) begin if (rst) minst_ret <= 0; else - minst_ret <= minst_ret_input_next + CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W'(minst_ret_inc); + minst_ret <= minst_ret_input_next + COUNTER_W'(minst_ret_inc); end //////////////////////////////////////////////////// //CSR mux + logic [31:0] read_mask; + always_comb begin + case (csr_inputs_r.addr) inside + SSTATUS : read_mask = CONFIG.INCLUDE_S_MODE ? sstatus_mask : '1; + SIE : read_mask = CONFIG.INCLUDE_S_MODE ? sie_mask : '1; + SIP : read_mask = CONFIG.INCLUDE_S_MODE ? sip_mask : '1; + default : read_mask = '1; + endcase + end always_comb begin case (csr_inputs_r.addr) inside //Machine info - 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; + 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 = 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 : 0; - MTVEC : selected_csr = CONFIG.INCLUDE_M_MODE ? mtvec : 0; - MCOUNTEREN : selected_csr = 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 : '0; + MTVEC : selected_csr = CONFIG.INCLUDE_M_MODE ? mtvec : '0; + MCOUNTEREN : selected_csr = '0; //Machine trap handling - MSCRATCH : selected_csr = CONFIG.INCLUDE_M_MODE ? mscratch : 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; + MSCRATCH : selected_csr = CONFIG.INCLUDE_M_MODE ? mscratch : '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; + [12'h3EF : 12'h3A0] : selected_csr = '0; //Machine Timers and Counters - 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 = CONFIG.INCLUDE_M_MODE ? 32'(mcycle[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:XLEN]) : 0; - MINSTRETH : selected_csr = CONFIG.INCLUDE_M_MODE ? 32'(minst_ret[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:XLEN]) : 0; - [12'hB83 : 12'hB9F] : selected_csr = 0; + MCYCLE : selected_csr = CONFIG.INCLUDE_M_MODE ? mcycle[31:0] : '0; + MINSTRET : selected_csr = CONFIG.INCLUDE_M_MODE ? minst_ret[31:0] : '0; + [12'hB03 : 12'hB1F] : selected_csr = '0; + MCYCLEH : selected_csr = CONFIG.INCLUDE_M_MODE ? 32'(mcycle[COUNTER_W-1:32]) : '0; + MINSTRETH : selected_csr = CONFIG.INCLUDE_M_MODE ? 32'(minst_ret[COUNTER_W-1:32]) : '0; + [12'hB83 : 12'hB9F] : selected_csr = '0; //Machine Counter Setup - [12'h320 : 12'h33F] : selected_csr = 0; + [12'h320 : 12'h33F] : selected_csr = '0; //Supervisor Trap Setup - 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 = CONFIG.INCLUDE_S_MODE ? (mie & sie_mask) : '0; + SSTATUS : selected_csr = CONFIG.INCLUDE_S_MODE ? mstatus : '0; + SEDELEG : selected_csr = '0; //No user-level interrupts/exception handling + SIDELEG : selected_csr = '0; + SIE : selected_csr = CONFIG.INCLUDE_S_MODE ? mie : '0; STVEC : selected_csr = CONFIG.INCLUDE_S_MODE ? stvec : '0; - SCOUNTEREN : selected_csr = 0; + SCOUNTEREN : selected_csr = '0; //Supervisor trap handling SSCRATCH : selected_csr = CONFIG.INCLUDE_S_MODE ? sscratch : '0; SEPC : selected_csr = CONFIG.INCLUDE_S_MODE ? sscratch : '0; SCAUSE : selected_csr = CONFIG.INCLUDE_S_MODE ? sscratch : '0; STVAL : selected_csr = CONFIG.INCLUDE_S_MODE ? sscratch : '0; - SIP : selected_csr = CONFIG.INCLUDE_S_MODE ? (mip & sip_mask) : '0; + SIP : selected_csr = CONFIG.INCLUDE_S_MODE ? mip : '0; //Supervisor Protection and Translation SATP : selected_csr = CONFIG.INCLUDE_S_MODE ? satp : '0; //User status //Floating point - FFLAGS : selected_csr = 0; - FRM : selected_csr = 0; - FCSR : selected_csr = 0; + FFLAGS : selected_csr = '0; + FRM : selected_csr = '0; + FCSR : selected_csr = '0; //User Counter Timers - CYCLE : selected_csr = mcycle[XLEN-1:0]; - 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[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:XLEN]); - TIMEH : selected_csr = 32'(mcycle[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:XLEN]); - INSTRETH : selected_csr = 32'(minst_ret[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:XLEN]); - [12'hC83 : 12'hC9F] : selected_csr = 0; + CYCLE : selected_csr = mcycle[31:0]; + TIME : selected_csr = mcycle[31:0]; + INSTRET : selected_csr = minst_ret[31:0]; + [12'hC03 : 12'hC1F] : selected_csr = '0; + CYCLEH : selected_csr = 32'(mcycle[COUNTER_W-1:32]); + TIMEH : selected_csr = 32'(mcycle[COUNTER_W-1:32]); + INSTRETH : selected_csr = 32'(minst_ret[COUNTER_W-1:32]); + [12'hC83 : 12'hC9F] : selected_csr = '0; - default : selected_csr = 0; + default : selected_csr = '0; endcase end always_ff @(posedge clk) begin if (commit) - selected_csr_r <= selected_csr; + selected_csr_r <= selected_csr & read_mask; end + //////////////////////////////////////////////////// + //Assertions + mstatus_update_assertion: + assert property (@(posedge clk) disable iff (rst) $onehot0({mret,sret,interrupt_taken, exception.valid,(mwrite_en(MSTATUS) | swrite_en(SSTATUS))})) else $error("multiple write to mstatus"); + endmodule From 6b8090504524702bb1ec5788fa06448f64a29b1b Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Fri, 14 Apr 2023 20:21:05 -0400 Subject: [PATCH 07/16] Reorganize source files Signed-off-by: Eric Matthews --- core/{ => common_components}/byte_en_BRAM.sv | 0 core/{ => common_components}/clz.sv | 0 core/{ => common_components}/cva5_fifo.sv | 0 core/{ => common_components}/cycler.sv | 0 core/{ => common_components}/lfsr.sv | 0 .../lutram_1w_1r.sv | 0 .../lutram_1w_mr.sv | 0 .../one_hot_to_integer.sv | 0 .../priority_encoder.sv | 0 .../set_clr_reg_with_rst.sv | 0 core/{ => common_components}/toggle_memory.sv | 0 .../toggle_memory_set.sv | 0 .../intel/intel_byte_enable_ram.sv | 0 .../xilinx/cva5_wrapper_xilinx.sv | 0 .../xilinx/xilinx_byte_enable_ram.sv | 0 core/{ => execution_units}/alu_unit.sv | 0 core/{ => execution_units}/barrel_shifter.sv | 0 .../branch_comparator.sv | 0 core/{ => execution_units}/branch_unit.sv | 0 core/{ => execution_units}/csr_unit.sv | 0 core/{ => execution_units}/custom_unit.sv | 0 core/{ => execution_units}/div_core.sv | 0 core/{ => execution_units}/div_unit.sv | 0 core/{ => execution_units}/gc_unit.sv | 0 .../load_store_unit}/addr_hash.sv | 0 .../load_store_unit}/amo_alu.sv | 0 .../load_store_unit}/dcache.sv | 0 .../load_store_unit}/dcache_tag_banks.sv | 0 .../load_store_unit}/load_store_queue.sv | 0 .../load_store_unit}/load_store_unit.sv | 0 .../load_store_unit}/store_queue.sv | 0 core/{ => execution_units}/mul_unit.sv | 0 core/{ => fetch_stage}/branch_predictor.sv | 0 .../{ => fetch_stage}/branch_predictor_ram.sv | 0 core/{ => fetch_stage}/fetch.sv | 0 core/{ => fetch_stage}/icache.sv | 0 core/{ => fetch_stage}/icache_tag_banks.sv | 0 core/{ => fetch_stage}/ras.sv | 0 core/{ => fetch_stage}/tag_bank.sv | 0 core/{ => memory_sub_units}/avalon_master.sv | 0 core/{ => memory_sub_units}/axi_master.sv | 0 .../local_mem_sub_unit.sv | 0 .../{ => memory_sub_units}/wishbone_master.sv | 0 core/{ => types_and_interfaces}/csr_types.sv | 0 .../{ => types_and_interfaces}/cva5_config.sv | 10 +- core/{ => types_and_interfaces}/cva5_types.sv | 0 .../external_interfaces.sv | 0 .../internal_interfaces.sv | 0 core/{ => types_and_interfaces}/opcodes.sv | 0 .../{ => types_and_interfaces}/riscv_types.sv | 0 examples/nexys/scripts/cva5-ip-core-base.tcl | 10 +- {core => l2_arbiter}/axi_to_arb.sv | 0 scripts/xilinx/cva5_wrapper_IP.tcl | 12 +- tools/compile_order | 122 +++++++++--------- 54 files changed, 75 insertions(+), 79 deletions(-) rename core/{ => common_components}/byte_en_BRAM.sv (100%) rename core/{ => common_components}/clz.sv (100%) rename core/{ => common_components}/cva5_fifo.sv (100%) rename core/{ => common_components}/cycler.sv (100%) rename core/{ => common_components}/lfsr.sv (100%) rename core/{lutrams => common_components}/lutram_1w_1r.sv (100%) rename core/{lutrams => common_components}/lutram_1w_mr.sv (100%) rename core/{ => common_components}/one_hot_to_integer.sv (100%) rename core/{ => common_components}/priority_encoder.sv (100%) rename core/{ => common_components}/set_clr_reg_with_rst.sv (100%) rename core/{ => common_components}/toggle_memory.sv (100%) rename core/{ => common_components}/toggle_memory_set.sv (100%) rename core/{ => common_components/vendor_support}/intel/intel_byte_enable_ram.sv (100%) rename core/{ => common_components/vendor_support}/xilinx/cva5_wrapper_xilinx.sv (100%) rename core/{ => common_components/vendor_support}/xilinx/xilinx_byte_enable_ram.sv (100%) rename core/{ => execution_units}/alu_unit.sv (100%) rename core/{ => execution_units}/barrel_shifter.sv (100%) rename core/{ => execution_units}/branch_comparator.sv (100%) rename core/{ => execution_units}/branch_unit.sv (100%) rename core/{ => execution_units}/csr_unit.sv (100%) rename core/{ => execution_units}/custom_unit.sv (100%) rename core/{ => execution_units}/div_core.sv (100%) rename core/{ => execution_units}/div_unit.sv (100%) rename core/{ => execution_units}/gc_unit.sv (100%) rename core/{ => execution_units/load_store_unit}/addr_hash.sv (100%) rename core/{ => execution_units/load_store_unit}/amo_alu.sv (100%) rename core/{ => execution_units/load_store_unit}/dcache.sv (100%) rename core/{ => execution_units/load_store_unit}/dcache_tag_banks.sv (100%) rename core/{ => execution_units/load_store_unit}/load_store_queue.sv (100%) rename core/{ => execution_units/load_store_unit}/load_store_unit.sv (100%) rename core/{ => execution_units/load_store_unit}/store_queue.sv (100%) rename core/{ => execution_units}/mul_unit.sv (100%) rename core/{ => fetch_stage}/branch_predictor.sv (100%) rename core/{ => fetch_stage}/branch_predictor_ram.sv (100%) rename core/{ => fetch_stage}/fetch.sv (100%) rename core/{ => fetch_stage}/icache.sv (100%) rename core/{ => fetch_stage}/icache_tag_banks.sv (100%) rename core/{ => fetch_stage}/ras.sv (100%) rename core/{ => fetch_stage}/tag_bank.sv (100%) rename core/{ => memory_sub_units}/avalon_master.sv (100%) rename core/{ => memory_sub_units}/axi_master.sv (100%) rename core/{ => memory_sub_units}/local_mem_sub_unit.sv (100%) rename core/{ => memory_sub_units}/wishbone_master.sv (100%) rename core/{ => types_and_interfaces}/csr_types.sv (100%) rename core/{ => types_and_interfaces}/cva5_config.sv (98%) rename core/{ => types_and_interfaces}/cva5_types.sv (100%) rename core/{ => types_and_interfaces}/external_interfaces.sv (100%) rename core/{ => types_and_interfaces}/internal_interfaces.sv (100%) rename core/{ => types_and_interfaces}/opcodes.sv (100%) rename core/{ => types_and_interfaces}/riscv_types.sv (100%) rename {core => l2_arbiter}/axi_to_arb.sv (100%) diff --git a/core/byte_en_BRAM.sv b/core/common_components/byte_en_BRAM.sv similarity index 100% rename from core/byte_en_BRAM.sv rename to core/common_components/byte_en_BRAM.sv diff --git a/core/clz.sv b/core/common_components/clz.sv similarity index 100% rename from core/clz.sv rename to core/common_components/clz.sv diff --git a/core/cva5_fifo.sv b/core/common_components/cva5_fifo.sv similarity index 100% rename from core/cva5_fifo.sv rename to core/common_components/cva5_fifo.sv diff --git a/core/cycler.sv b/core/common_components/cycler.sv similarity index 100% rename from core/cycler.sv rename to core/common_components/cycler.sv diff --git a/core/lfsr.sv b/core/common_components/lfsr.sv similarity index 100% rename from core/lfsr.sv rename to core/common_components/lfsr.sv diff --git a/core/lutrams/lutram_1w_1r.sv b/core/common_components/lutram_1w_1r.sv similarity index 100% rename from core/lutrams/lutram_1w_1r.sv rename to core/common_components/lutram_1w_1r.sv diff --git a/core/lutrams/lutram_1w_mr.sv b/core/common_components/lutram_1w_mr.sv similarity index 100% rename from core/lutrams/lutram_1w_mr.sv rename to core/common_components/lutram_1w_mr.sv diff --git a/core/one_hot_to_integer.sv b/core/common_components/one_hot_to_integer.sv similarity index 100% rename from core/one_hot_to_integer.sv rename to core/common_components/one_hot_to_integer.sv diff --git a/core/priority_encoder.sv b/core/common_components/priority_encoder.sv similarity index 100% rename from core/priority_encoder.sv rename to core/common_components/priority_encoder.sv diff --git a/core/set_clr_reg_with_rst.sv b/core/common_components/set_clr_reg_with_rst.sv similarity index 100% rename from core/set_clr_reg_with_rst.sv rename to core/common_components/set_clr_reg_with_rst.sv diff --git a/core/toggle_memory.sv b/core/common_components/toggle_memory.sv similarity index 100% rename from core/toggle_memory.sv rename to core/common_components/toggle_memory.sv diff --git a/core/toggle_memory_set.sv b/core/common_components/toggle_memory_set.sv similarity index 100% rename from core/toggle_memory_set.sv rename to core/common_components/toggle_memory_set.sv diff --git a/core/intel/intel_byte_enable_ram.sv b/core/common_components/vendor_support/intel/intel_byte_enable_ram.sv similarity index 100% rename from core/intel/intel_byte_enable_ram.sv rename to core/common_components/vendor_support/intel/intel_byte_enable_ram.sv diff --git a/core/xilinx/cva5_wrapper_xilinx.sv b/core/common_components/vendor_support/xilinx/cva5_wrapper_xilinx.sv similarity index 100% rename from core/xilinx/cva5_wrapper_xilinx.sv rename to core/common_components/vendor_support/xilinx/cva5_wrapper_xilinx.sv diff --git a/core/xilinx/xilinx_byte_enable_ram.sv b/core/common_components/vendor_support/xilinx/xilinx_byte_enable_ram.sv similarity index 100% rename from core/xilinx/xilinx_byte_enable_ram.sv rename to core/common_components/vendor_support/xilinx/xilinx_byte_enable_ram.sv diff --git a/core/alu_unit.sv b/core/execution_units/alu_unit.sv similarity index 100% rename from core/alu_unit.sv rename to core/execution_units/alu_unit.sv diff --git a/core/barrel_shifter.sv b/core/execution_units/barrel_shifter.sv similarity index 100% rename from core/barrel_shifter.sv rename to core/execution_units/barrel_shifter.sv diff --git a/core/branch_comparator.sv b/core/execution_units/branch_comparator.sv similarity index 100% rename from core/branch_comparator.sv rename to core/execution_units/branch_comparator.sv diff --git a/core/branch_unit.sv b/core/execution_units/branch_unit.sv similarity index 100% rename from core/branch_unit.sv rename to core/execution_units/branch_unit.sv diff --git a/core/csr_unit.sv b/core/execution_units/csr_unit.sv similarity index 100% rename from core/csr_unit.sv rename to core/execution_units/csr_unit.sv diff --git a/core/custom_unit.sv b/core/execution_units/custom_unit.sv similarity index 100% rename from core/custom_unit.sv rename to core/execution_units/custom_unit.sv diff --git a/core/div_core.sv b/core/execution_units/div_core.sv similarity index 100% rename from core/div_core.sv rename to core/execution_units/div_core.sv diff --git a/core/div_unit.sv b/core/execution_units/div_unit.sv similarity index 100% rename from core/div_unit.sv rename to core/execution_units/div_unit.sv diff --git a/core/gc_unit.sv b/core/execution_units/gc_unit.sv similarity index 100% rename from core/gc_unit.sv rename to core/execution_units/gc_unit.sv diff --git a/core/addr_hash.sv b/core/execution_units/load_store_unit/addr_hash.sv similarity index 100% rename from core/addr_hash.sv rename to core/execution_units/load_store_unit/addr_hash.sv diff --git a/core/amo_alu.sv b/core/execution_units/load_store_unit/amo_alu.sv similarity index 100% rename from core/amo_alu.sv rename to core/execution_units/load_store_unit/amo_alu.sv diff --git a/core/dcache.sv b/core/execution_units/load_store_unit/dcache.sv similarity index 100% rename from core/dcache.sv rename to core/execution_units/load_store_unit/dcache.sv diff --git a/core/dcache_tag_banks.sv b/core/execution_units/load_store_unit/dcache_tag_banks.sv similarity index 100% rename from core/dcache_tag_banks.sv rename to core/execution_units/load_store_unit/dcache_tag_banks.sv diff --git a/core/load_store_queue.sv b/core/execution_units/load_store_unit/load_store_queue.sv similarity index 100% rename from core/load_store_queue.sv rename to core/execution_units/load_store_unit/load_store_queue.sv diff --git a/core/load_store_unit.sv b/core/execution_units/load_store_unit/load_store_unit.sv similarity index 100% rename from core/load_store_unit.sv rename to core/execution_units/load_store_unit/load_store_unit.sv diff --git a/core/store_queue.sv b/core/execution_units/load_store_unit/store_queue.sv similarity index 100% rename from core/store_queue.sv rename to core/execution_units/load_store_unit/store_queue.sv diff --git a/core/mul_unit.sv b/core/execution_units/mul_unit.sv similarity index 100% rename from core/mul_unit.sv rename to core/execution_units/mul_unit.sv diff --git a/core/branch_predictor.sv b/core/fetch_stage/branch_predictor.sv similarity index 100% rename from core/branch_predictor.sv rename to core/fetch_stage/branch_predictor.sv diff --git a/core/branch_predictor_ram.sv b/core/fetch_stage/branch_predictor_ram.sv similarity index 100% rename from core/branch_predictor_ram.sv rename to core/fetch_stage/branch_predictor_ram.sv diff --git a/core/fetch.sv b/core/fetch_stage/fetch.sv similarity index 100% rename from core/fetch.sv rename to core/fetch_stage/fetch.sv diff --git a/core/icache.sv b/core/fetch_stage/icache.sv similarity index 100% rename from core/icache.sv rename to core/fetch_stage/icache.sv diff --git a/core/icache_tag_banks.sv b/core/fetch_stage/icache_tag_banks.sv similarity index 100% rename from core/icache_tag_banks.sv rename to core/fetch_stage/icache_tag_banks.sv diff --git a/core/ras.sv b/core/fetch_stage/ras.sv similarity index 100% rename from core/ras.sv rename to core/fetch_stage/ras.sv diff --git a/core/tag_bank.sv b/core/fetch_stage/tag_bank.sv similarity index 100% rename from core/tag_bank.sv rename to core/fetch_stage/tag_bank.sv diff --git a/core/avalon_master.sv b/core/memory_sub_units/avalon_master.sv similarity index 100% rename from core/avalon_master.sv rename to core/memory_sub_units/avalon_master.sv diff --git a/core/axi_master.sv b/core/memory_sub_units/axi_master.sv similarity index 100% rename from core/axi_master.sv rename to core/memory_sub_units/axi_master.sv diff --git a/core/local_mem_sub_unit.sv b/core/memory_sub_units/local_mem_sub_unit.sv similarity index 100% rename from core/local_mem_sub_unit.sv rename to core/memory_sub_units/local_mem_sub_unit.sv diff --git a/core/wishbone_master.sv b/core/memory_sub_units/wishbone_master.sv similarity index 100% rename from core/wishbone_master.sv rename to core/memory_sub_units/wishbone_master.sv diff --git a/core/csr_types.sv b/core/types_and_interfaces/csr_types.sv similarity index 100% rename from core/csr_types.sv rename to core/types_and_interfaces/csr_types.sv diff --git a/core/cva5_config.sv b/core/types_and_interfaces/cva5_config.sv similarity index 98% rename from core/cva5_config.sv rename to core/types_and_interfaces/cva5_config.sv index d8c767d..1bc7976 100755 --- a/core/cva5_config.sv +++ b/core/types_and_interfaces/cva5_config.sv @@ -157,8 +157,8 @@ package cva5_config; localparam cpu_config_t EXAMPLE_CONFIG = '{ //ISA options INCLUDE_M_MODE : 1, - INCLUDE_S_MODE : 1, - INCLUDE_U_MODE : 1, + INCLUDE_S_MODE : 0, + INCLUDE_U_MODE : 0, INCLUDE_MUL : 1, INCLUDE_DIV : 1, INCLUDE_IFENCE : 1, @@ -173,10 +173,10 @@ package cva5_config; RESET_MTVEC : 32'h80000100, NON_STANDARD_OPTIONS : '{ COUNTER_W : 33, - MCYCLE_WRITEABLE : 1, - MINSTR_WRITEABLE : 1, + MCYCLE_WRITEABLE : 0, + MINSTR_WRITEABLE : 0, MTVEC_WRITEABLE : 1, - INCLUDE_MSCRATCH : 1, + INCLUDE_MSCRATCH : 0, INCLUDE_MCAUSE : 1, INCLUDE_MTVAL : 1 } diff --git a/core/cva5_types.sv b/core/types_and_interfaces/cva5_types.sv similarity index 100% rename from core/cva5_types.sv rename to core/types_and_interfaces/cva5_types.sv diff --git a/core/external_interfaces.sv b/core/types_and_interfaces/external_interfaces.sv similarity index 100% rename from core/external_interfaces.sv rename to core/types_and_interfaces/external_interfaces.sv diff --git a/core/internal_interfaces.sv b/core/types_and_interfaces/internal_interfaces.sv similarity index 100% rename from core/internal_interfaces.sv rename to core/types_and_interfaces/internal_interfaces.sv diff --git a/core/opcodes.sv b/core/types_and_interfaces/opcodes.sv similarity index 100% rename from core/opcodes.sv rename to core/types_and_interfaces/opcodes.sv diff --git a/core/riscv_types.sv b/core/types_and_interfaces/riscv_types.sv similarity index 100% rename from core/riscv_types.sv rename to core/types_and_interfaces/riscv_types.sv diff --git a/examples/nexys/scripts/cva5-ip-core-base.tcl b/examples/nexys/scripts/cva5-ip-core-base.tcl index 7522438..e810b9f 100644 --- a/examples/nexys/scripts/cva5-ip-core-base.tcl +++ b/examples/nexys/scripts/cva5-ip-core-base.tcl @@ -28,11 +28,11 @@ if {[string equal [get_filesets -quiet sources_1] ""]} { import_files -norecurse $sources_dir/examples/nexys/nexys_wrapper.sv import_files -norecurse $sources_dir/l2_arbiter/l2_external_interfaces.sv import_files -norecurse $sources_dir/local_memory/local_memory_interface.sv -import_files -norecurse $sources_dir/core/external_interfaces.sv -import_files -norecurse $sources_dir/core/cva5_config.sv -import_files -norecurse $sources_dir/core/riscv_types.sv -import_files -norecurse $sources_dir/core/cva5_types.sv -import_files -norecurse $sources_dir/core/csr_types.sv +import_files -norecurse $sources_dir/core/types_and_interfaces/external_interfaces.sv +import_files -norecurse $sources_dir/core/types_and_interfaces/cva5_config.sv +import_files -norecurse $sources_dir/core/types_and_interfaces/riscv_types.sv +import_files -norecurse $sources_dir/core/types_and_interfaces/cva5_types.sv +import_files -norecurse $sources_dir/core/types_and_interfaces/csr_types.sv import_files -norecurse $sources_dir/l2_arbiter/l2_config_and_types.sv # Set IP repository paths diff --git a/core/axi_to_arb.sv b/l2_arbiter/axi_to_arb.sv similarity index 100% rename from core/axi_to_arb.sv rename to l2_arbiter/axi_to_arb.sv diff --git a/scripts/xilinx/cva5_wrapper_IP.tcl b/scripts/xilinx/cva5_wrapper_IP.tcl index 7f71b0c..a1b4f66 100644 --- a/scripts/xilinx/cva5_wrapper_IP.tcl +++ b/scripts/xilinx/cva5_wrapper_IP.tcl @@ -117,14 +117,14 @@ if {[string equal [get_filesets -quiet sources_1] ""]} { #import_files -fileset [get_filesets sources_1] $origin_dir/l2_arbiter #import_files -fileset [get_filesets sources_1] $origin_dir/local_memory -import_files -norecurse $origin_dir/../../core/xilinx/cva5_wrapper_xilinx.sv -force +import_files -norecurse $origin_dir/../../core/common_components/vendor_support/xilinx/cva5_wrapper_xilinx.sv -force import_files -norecurse $origin_dir/../../l2_arbiter/l2_external_interfaces.sv -force import_files -norecurse $origin_dir/../../local_memory/local_memory_interface.sv -force -import_files -norecurse $origin_dir/../../core/external_interfaces.sv -force -import_files -norecurse $origin_dir/../../core/cva5_config.sv -force -import_files -norecurse $origin_dir/../../core/riscv_types.sv -force -import_files -norecurse $origin_dir/../../core/cva5_types.sv -force -import_files -norecurse $origin_dir/../../core/csr_types.sv -force +import_files -norecurse $origin_dir/../../core/types_and_interfaces/external_interfaces.sv -force +import_files -norecurse $origin_dir/../../core/types_and_interfaces/cva5_config.sv -force +import_files -norecurse $origin_dir/../../core/types_and_interfaces/riscv_types.sv -force +import_files -norecurse $origin_dir/../../core/types_and_interfaces/cva5_types.sv -force +import_files -norecurse $origin_dir/../../core/types_and_interfaces/csr_types.sv -force import_files -norecurse $origin_dir/../../l2_arbiter/l2_config_and_types.sv -force # Set IP repository paths diff --git a/tools/compile_order b/tools/compile_order index af96faa..2699fa1 100644 --- a/tools/compile_order +++ b/tools/compile_order @@ -1,94 +1,90 @@ -core/cva5_config.sv -core/riscv_types.sv -core/csr_types.sv -core/cva5_types.sv -core/opcodes.sv +core/types_and_interfaces/cva5_config.sv +core/types_and_interfaces/riscv_types.sv +core/types_and_interfaces/csr_types.sv +core/types_and_interfaces/cva5_types.sv +core/types_and_interfaces/opcodes.sv -l2_arbiter/l2_config_and_types.sv +l2_arbiter/l2_config_and_types.sv l2_arbiter/l2_interfaces.sv l2_arbiter/l2_external_interfaces.sv -local_memory/local_memory_interface.sv +local_memory/local_memory_interface.sv local_memory/local_mem.sv -core/internal_interfaces.sv -core/external_interfaces.sv +core/types_and_interfaces/internal_interfaces.sv +core/types_and_interfaces/external_interfaces.sv -core/lutrams/lutram_1w_1r.sv -core/lutrams/lutram_1w_mr.sv +core/common_components/lutram_1w_1r.sv +core/common_components/lutram_1w_mr.sv +core/common_components/set_clr_reg_with_rst.sv +core/common_components/one_hot_to_integer.sv +core/common_components/cycler.sv +core/common_components/lfsr.sv +core/common_components/cva5_fifo.sv +core/common_components/priority_encoder.sv +core/common_components/toggle_memory.sv +core/common_components/toggle_memory_set.sv -core/set_clr_reg_with_rst.sv -core/one_hot_to_integer.sv -core/cycler.sv -core/lfsr.sv -core/cva5_fifo.sv -core/priority_encoder.sv +core/common_components/vendor_support/intel/intel_byte_enable_ram.sv +core/common_components/vendor_support/xilinx/xilinx_byte_enable_ram.sv +core/common_components/byte_en_BRAM.sv -core/toggle_memory.sv -core/toggle_memory_set.sv +core/execution_units/csr_unit.sv +core/execution_units/gc_unit.sv -core/intel/intel_byte_enable_ram.sv -core/xilinx/xilinx_byte_enable_ram.sv -core/byte_en_BRAM.sv +core/execution_units/branch_comparator.sv +core/execution_units/branch_unit.sv -core/csr_unit.sv -core/gc_unit.sv +core/execution_units/barrel_shifter.sv +core/execution_units/alu_unit.sv -core/branch_comparator.sv -core/branch_unit.sv +core/memory_sub_units/local_mem_sub_unit.sv +core/memory_sub_units/axi_master.sv +core/memory_sub_units/avalon_master.sv +core/memory_sub_units/wishbone_master.sv -core/barrel_shifter.sv -core/alu_unit.sv +core/execution_units/load_store_unit/dcache_tag_banks.sv +core/execution_units/load_store_unit/amo_alu.sv +core/execution_units/load_store_unit/dcache.sv +core/execution_units/load_store_unit/addr_hash.sv +core/execution_units/load_store_unit/store_queue.sv +core/execution_units/load_store_unit/load_store_queue.sv +core/execution_units/load_store_unit/load_store_unit.sv -core/local_mem_sub_unit.sv -core/axi_master.sv -core/avalon_master.sv -core/wishbone_master.sv +core/execution_units/mul_unit.sv +core/execution_units/custom_unit.sv -core/tag_bank.sv -core/dcache_tag_banks.sv -core/amo_alu.sv -core/dcache.sv -core/addr_hash.sv -core/store_queue.sv -core/load_store_queue.sv -core/load_store_unit.sv +core/common_components/clz.sv +core/execution_units/div_core.sv +core/execution_units/div_unit.sv -core/icache_tag_banks.sv -core/icache.sv +core/fetch_stage/ras.sv +core/fetch_stage/branch_predictor_ram.sv +core/fetch_stage/branch_predictor.sv +core/fetch_stage/tag_bank.sv +core/fetch_stage/icache_tag_banks.sv +core/fetch_stage/icache.sv +core/fetch_stage/fetch.sv -core/clz.sv -core/div_core.sv -core/div_unit.sv +core/instruction_metadata_and_id_management.sv -core/tlb_lut_ram.sv -core/mmu.sv - -core/mul_unit.sv - -core/custom_unit.sv - -core/ras.sv -core/branch_predictor_ram.sv -core/branch_predictor.sv -core/fetch.sv +core/tlb_lut_ram.sv +core/mmu.sv core/decode_and_issue.sv core/register_free_list.sv core/renamer.sv core/register_file.sv + core/writeback.sv +core/l1_arbiter.sv + l2_arbiter/l2_fifo.sv l2_arbiter/l2_reservation_logic.sv l2_arbiter/l2_round_robin.sv l2_arbiter/l2_arbiter.sv -core/axi_to_arb.sv - -core/instruction_metadata_and_id_management.sv - -core/l1_arbiter.sv - -core/cva5.sv +l2_arbiter/axi_to_arb.sv +core/cva5.sv \ No newline at end of file From 24baf185e7c92a4622f289e68e0525d17e52dab1 Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Fri, 14 Apr 2023 23:06:22 -0400 Subject: [PATCH 08/16] Convert remaining inferred lutram memories to lutram modules Signed-off-by: Eric Matthews --- .../load_store_unit/load_store_unit.sv | 37 ++++++++++--------- core/fetch_stage/branch_predictor.sv | 23 +++++++----- core/fetch_stage/ras.sv | 21 +++++------ 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/core/execution_units/load_store_unit/load_store_unit.sv b/core/execution_units/load_store_unit/load_store_unit.sv index 55a1db6..93ad508 100755 --- a/core/execution_units/load_store_unit/load_store_unit.sv +++ b/core/execution_units/load_store_unit/load_store_unit.sv @@ -191,22 +191,25 @@ module load_store_unit end end - (* ramstyle = "MLAB, no_rw_check" *) id_t rd_to_id_table [32]; - (* ramstyle = "MLAB, no_rw_check" *) logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] rd_to_wb_group_table [32]; - - id_t store_forward_id; - logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] store_forward_wb_group; - - always_ff @ (posedge clk) begin - if (instruction_issued_with_rd) begin - rd_to_id_table[issue_stage.rd_addr] <= issue_stage.id; - rd_to_wb_group_table[issue_stage.rd_addr] <= issue_rd_wb_group; - end - end - - assign store_forward_id = rd_to_id_table[issue_rs_addr[RS2]]; - assign store_forward_wb_group = rs2_inuse ? rd_to_wb_group_table[issue_rs_addr[RS2]] : '0; + typedef struct packed{ + id_t id; + logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] wb_group; + } rd_attributes_t; + rd_attributes_t rd_attributes; + lutram_1w_1r #(.DATA_TYPE(rd_attributes_t), .DEPTH(32)) + rd_to_id_table ( + .clk(clk), + .waddr(issue_stage.rd_addr), + .raddr(issue_rs_addr[RS2]), + .ram_write(instruction_issued_with_rd), + .new_ram_data('{ + id : issue_stage.id, + wb_group : issue_rd_wb_group + }), + .ram_data_out(rd_attributes) + ); + //////////////////////////////////////////////////// //Alignment Exception generate if (CONFIG.INCLUDE_M_MODE) begin : gen_ls_exceptions @@ -288,7 +291,7 @@ module load_store_unit load : is_load_r, store : is_store_r, id : issue.id, - id_needed : store_forward_id + id_needed : rd_attributes.id }; assign lsq.potential_push = issue.possible_issue; @@ -299,7 +302,7 @@ module load_store_unit .rst (rst), .gc (gc), .lsq (lsq), - .store_forward_wb_group (store_forward_wb_group), + .store_forward_wb_group (rs2_inuse ? rd_attributes.wb_group : '0), .wb_packet (wb_packet), .store_retire (store_retire) ); diff --git a/core/fetch_stage/branch_predictor.sv b/core/fetch_stage/branch_predictor.sv index 1090973..2142211 100755 --- a/core/fetch_stage/branch_predictor.sv +++ b/core/fetch_stage/branch_predictor.sv @@ -83,8 +83,6 @@ module branch_predictor 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; @@ -172,15 +170,20 @@ module branch_predictor .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]; + lutram_1w_1r #(.DATA_TYPE(branch_metadata_t), .DEPTH(MAX_IDS)) + branch_metadata_table ( + .clk(clk), + .waddr(bp.pc_id), + .raddr(br_results.id), + .ram_write(bp.pc_id_assigned), + .new_ram_data('{ + branch_predictor_metadata : if_entry[hit_way].metadata, + branch_prediction_used : use_predicted_pc, + branch_predictor_update_way : tag_match ? tag_matches : replacement_way + }), + .ram_data_out(branch_metadata_ex) + ); //////////////////////////////////////////////////// //Execution stage update diff --git a/core/fetch_stage/ras.sv b/core/fetch_stage/ras.sv index 496d11d..d1218ec 100755 --- a/core/fetch_stage/ras.sv +++ b/core/fetch_stage/ras.sv @@ -38,17 +38,11 @@ module ras ras_interface.self ras ); - (* ramstyle = "MLAB, no_rw_check" *) logic[31:0] lut_ram [CONFIG.BP.RAS_ENTRIES]; - 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_TYPE(logic[RAS_DEPTH_W-1:0])) ri_fifo(); - /////////////////////////////////////////////////////// - //For simulation purposes - initial lut_ram = '{default: 0}; /////////////////////////////////////////////////////// - assign ras.addr = lut_ram[read_index]; //On a speculative branch, save the current stack pointer //Restored if branch is misspredicted (gc_fetch_flush) @@ -64,11 +58,16 @@ module ras assign ri_fifo.potential_push = ras.branch_fetched; assign ri_fifo.pop = ras.branch_retired & ri_fifo.valid; //Prevent popping from fifo if reset due to early_branch_flush_ras_adjust - always_ff @ (posedge clk) begin - if (ras.push) - lut_ram[new_index] <= ras.new_addr; - end - + lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(CONFIG.BP.RAS_ENTRIES)) + ras_stack ( + .clk(clk), + .waddr(new_index), + .raddr(read_index), + .ram_write(ras.push), + .new_ram_data(ras.new_addr), + .ram_data_out(ras.addr) + ); + //Rolls over when full, most recent calls will be correct, but calls greater than depth //will be lost. logic [RAS_DEPTH_W-1:0] new_index_base; From 17c45f00504921e20ecec8d23b2376c38d649d56 Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Mon, 17 Apr 2023 13:15:24 -0400 Subject: [PATCH 09/16] Consolidate BRAM implementations Signed-off-by: Eric Matthews --- .../{byte_en_BRAM.sv => byte_en_bram.sv} | 2 +- .../dual_port_bram.sv} | 47 ++++++++------ .../execution_units/load_store_unit/dcache.sv | 2 +- .../load_store_unit/dcache_tag_banks.sv | 3 +- core/fetch_stage/branch_predictor.sv | 38 ++++++----- core/fetch_stage/branch_predictor_ram.sv | 64 ------------------- core/fetch_stage/icache.sv | 14 ++-- core/fetch_stage/icache_tag_banks.sv | 3 +- examples/zedboard/cva5_wrapper.sv | 2 +- local_memory/local_mem.sv | 2 +- tools/compile_order | 5 +- 11 files changed, 64 insertions(+), 118 deletions(-) rename core/common_components/{byte_en_BRAM.sv => byte_en_bram.sv} (98%) rename core/{fetch_stage/tag_bank.sv => common_components/dual_port_bram.sv} (64%) mode change 100755 => 100644 delete mode 100644 core/fetch_stage/branch_predictor_ram.sv diff --git a/core/common_components/byte_en_BRAM.sv b/core/common_components/byte_en_bram.sv similarity index 98% rename from core/common_components/byte_en_BRAM.sv rename to core/common_components/byte_en_bram.sv index 94d1bbb..660ae79 100755 --- a/core/common_components/byte_en_BRAM.sv +++ b/core/common_components/byte_en_bram.sv @@ -22,7 +22,7 @@ -module byte_en_BRAM +module byte_en_bram import cva5_config::*; import cva5_types::*; diff --git a/core/fetch_stage/tag_bank.sv b/core/common_components/dual_port_bram.sv old mode 100755 new mode 100644 similarity index 64% rename from core/fetch_stage/tag_bank.sv rename to core/common_components/dual_port_bram.sv index 3afc013..61da14a --- a/core/fetch_stage/tag_bank.sv +++ b/core/common_components/dual_port_bram.sv @@ -1,5 +1,5 @@ /* - * Copyright © 2017-2020 Eric Matthews, Lesley Shannon + * Copyright © 2023 Eric Matthews, Lesley Shannon * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,46 +20,51 @@ * Eric Matthews */ -module tag_bank - #( + + +module dual_port_bram + + import cva5_config::*; + import cva5_types::*; + import riscv_types::*; + + #( parameter WIDTH = 32, - parameter LINES = 512 + parameter LINES = 4096 ) ( input logic clk, - input logic rst, - input logic[$clog2(LINES)-1:0] addr_a, - input logic[$clog2(LINES)-1:0] addr_b, input logic en_a, - input logic en_b, input logic wen_a, + input logic[$clog2(LINES)-1:0] addr_a, + input logic[WIDTH-1:0] data_in_a, + output logic[WIDTH-1:0] data_out_a, + + input logic en_b, input logic wen_b, - input logic [WIDTH-1:0] data_in_a, - input logic [WIDTH-1:0] data_in_b, - output logic [WIDTH-1:0] data_out_a, - output logic [WIDTH-1:0] data_out_b + input logic[$clog2(LINES)-1:0] addr_b, + input logic[WIDTH-1:0] data_in_b, + output logic[WIDTH-1:0] data_out_b ); - (* ram_style = "block", ramstyle = "no_rw_check" *) logic [WIDTH-1:0] tag_entry [LINES]; - initial tag_entry = '{default: 0}; + (* ram_style = "block", ramstyle = "no_rw_check" *) logic [WIDTH-1:0] ram [LINES]; + initial ram = '{default: 0}; always_ff @ (posedge clk) begin if (en_a) begin if (wen_a) - tag_entry[addr_a] <= data_in_a; - else - data_out_a <= tag_entry[addr_a]; + ram[addr_a] <= data_in_a; + data_out_a <= ram[addr_a]; end end always_ff @ (posedge clk) begin if (en_b) begin if (wen_b) - tag_entry[addr_b] <= data_in_b; - else - data_out_b <= tag_entry[addr_b]; + ram[addr_b] <= data_in_b; + data_out_b <= ram[addr_b]; end end -endmodule \ No newline at end of file +endmodule diff --git a/core/execution_units/load_store_unit/dcache.sv b/core/execution_units/load_store_unit/dcache.sv index 8674acd..8bb93e3 100644 --- a/core/execution_units/load_store_unit/dcache.sv +++ b/core/execution_units/load_store_unit/dcache.sv @@ -253,7 +253,7 @@ module dcache assign data_read_addr = load_state[LOAD_FILL] ? {addr_utils.getTagLineAddr(stage2_load.addr), word_count} : addr_utils.getDataLineAddr(ls_load.addr); generate for (genvar i=0; i < CONFIG.DCACHE.WAYS; i++) begin : data_bank_gen - byte_en_BRAM #(CONFIG.DCACHE.LINES*CONFIG.DCACHE.LINE_W) data_bank ( + byte_en_bram #(CONFIG.DCACHE.LINES*CONFIG.DCACHE.LINE_W) data_bank ( .clk(clk), .addr_a(data_read_addr), .addr_b(addr_utils.getDataLineAddr(stage2_store.addr)), diff --git a/core/execution_units/load_store_unit/dcache_tag_banks.sv b/core/execution_units/load_store_unit/dcache_tag_banks.sv index 4c5da5c..572db71 100644 --- a/core/execution_units/load_store_unit/dcache_tag_banks.sv +++ b/core/execution_units/load_store_unit/dcache_tag_banks.sv @@ -90,9 +90,8 @@ module dcache_tag_banks //////////////////////////////////////////////////// //Memory instantiation and hit detection generate for (genvar i = 0; i < CONFIG.DCACHE.WAYS; i++) begin : tag_bank_gen - tag_bank #($bits(dtag_entry_t), CONFIG.DCACHE.LINES) dtag_bank ( + dual_port_bram #(.WIDTH($bits(dtag_entry_t)), .LINES(CONFIG.DCACHE.LINES)) dtag_bank ( .clk (clk), - .rst (rst), .en_a (store_req | (miss_req & miss_way[i]) | external_inv), .wen_a ((miss_req & miss_way[i]) | external_inv), .addr_a (porta_addr), diff --git a/core/fetch_stage/branch_predictor.sv b/core/fetch_stage/branch_predictor.sv index 2142211..ef2ea7b 100755 --- a/core/fetch_stage/branch_predictor.sv +++ b/core/fetch_stage/branch_predictor.sv @@ -104,31 +104,37 @@ module branch_predictor genvar i; generate if (CONFIG.INCLUDE_BRANCH_PREDICTOR) for (i=0; i - */ - -module branch_predictor_ram - - import cva5_config::*; - import cva5_types::*; - - #( - parameter C_DATA_WIDTH = 20, - parameter C_DEPTH = 512 - ) - ( - input logic clk, - input logic rst, - input logic [$clog2(C_DEPTH)-1:0] write_addr, - input logic write_en, - input logic [$clog2(C_DEPTH)-1:0] read_addr, - input logic read_en, - input logic [C_DATA_WIDTH-1:0] write_data, - output logic [C_DATA_WIDTH-1:0] read_data - ); - (* ram_style = "block" *)logic [C_DATA_WIDTH-1:0] branch_ram [C_DEPTH-1:0]; - //////////////////////////////////////////////////// - //Implementation - initial branch_ram = '{default: 0}; - always_ff @(posedge clk) begin - if (write_en) - branch_ram[write_addr] <= write_data; - end - always_ff @(posedge clk) begin - if (read_en) - read_data <= branch_ram[read_addr]; - end - //////////////////////////////////////////////////// - //End of Implementation - //////////////////////////////////////////////////// - - //////////////////////////////////////////////////// - //Assertions - - //////////////////////////////////////////////////// - //Trace Interface - -endmodule diff --git a/core/fetch_stage/icache.sv b/core/fetch_stage/icache.sv index 1a7887f..a81463b 100755 --- a/core/fetch_stage/icache.sv +++ b/core/fetch_stage/icache.sv @@ -190,17 +190,17 @@ module icache //Data Banks genvar i; 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 ( + dual_port_bram #(.WIDTH(32), .LINES(CONFIG.ICACHE.LINES*CONFIG.ICACHE.LINE_W)) idata_bank ( .clk(clk), - .addr_a(addr_utils.getDataLineAddr(new_request_addr)), - .addr_b(addr_utils.getDataLineAddr({second_cycle_addr[31:SCONFIG.SUB_LINE_ADDR_W+2], word_count, 2'b0})), .en_a(new_request), - .en_b(tag_update_way[i] & l1_response.data_valid), - .be_a('0), - .be_b('1), + .wen_a(0), + .addr_a(addr_utils.getDataLineAddr(new_request_addr)), .data_in_a('0), - .data_in_b(l1_response.data), .data_out_a(data_out[i]), + .en_b(1), + .wen_b(tag_update_way[i] & l1_response.data_valid), + .addr_b(addr_utils.getDataLineAddr({second_cycle_addr[31:SCONFIG.SUB_LINE_ADDR_W+2], word_count, 2'b0})), + .data_in_b(l1_response.data), .data_out_b() ); end endgenerate diff --git a/core/fetch_stage/icache_tag_banks.sv b/core/fetch_stage/icache_tag_banks.sv index 4589566..f350e91 100755 --- a/core/fetch_stage/icache_tag_banks.sv +++ b/core/fetch_stage/icache_tag_banks.sv @@ -63,7 +63,8 @@ module itag_banks genvar i; generate for (i=0; i < CONFIG.ICACHE.WAYS; i++) begin : tag_bank_gen - tag_bank #(SCONFIG.TAG_W+1, CONFIG.ICACHE.LINES) itag_bank (.*, + dual_port_bram #(.WIDTH(SCONFIG.TAG_W+1), .LINES(CONFIG.ICACHE.LINES)) itag_bank (.*, + .clk(clk), .en_a(stage1_adv), .wen_a('0), .addr_a(stage1_line_addr), diff --git a/examples/zedboard/cva5_wrapper.sv b/examples/zedboard/cva5_wrapper.sv index f70292a..654384f 100755 --- a/examples/zedboard/cva5_wrapper.sv +++ b/examples/zedboard/cva5_wrapper.sv @@ -243,7 +243,7 @@ module cva5_wrapper ( endgenerate //arm proc(.*); - byte_en_BRAM #(MEM_LINES, "/home/ematthew/Research/RISCV/software2/riscv-tools/riscv-tests/benchmarks/fft.riscv.hw_init", 1) inst_data_ram ( + byte_en_bram #(MEM_LINES, "/home/ematthew/Research/RISCV/software2/riscv-tools/riscv-tests/benchmarks/fft.riscv.hw_init", 1) inst_data_ram ( .clk(clk), .addr_a(instruction_bram.addr[$clog2(MEM_LINES)- 1:0]), .en_a(instruction_bram.en), diff --git a/local_memory/local_mem.sv b/local_memory/local_mem.sv index 6e1fbfb..5bb7bc6 100644 --- a/local_memory/local_mem.sv +++ b/local_memory/local_mem.sv @@ -36,7 +36,7 @@ module local_mem localparam LINES = (RAM_SIZE/4)*1024; //RAM width is 32-bits, so for RAM_SIZE in KB, divide by 4 and multiply by 1024. - byte_en_BRAM #(LINES, preload_file, USE_PRELOAD_FILE) inst_data_ram ( + byte_en_bram #(LINES, preload_file, USE_PRELOAD_FILE) inst_data_ram ( .clk(clk), .addr_a(portA.addr[$clog2(LINES)- 1:0]), .en_a(portA.en), diff --git a/tools/compile_order b/tools/compile_order index 2699fa1..32fa972 100644 --- a/tools/compile_order +++ b/tools/compile_order @@ -15,6 +15,7 @@ core/types_and_interfaces/external_interfaces.sv core/common_components/lutram_1w_1r.sv core/common_components/lutram_1w_mr.sv +core/common_components/dual_port_bram.sv core/common_components/set_clr_reg_with_rst.sv core/common_components/one_hot_to_integer.sv core/common_components/cycler.sv @@ -26,7 +27,7 @@ core/common_components/toggle_memory_set.sv core/common_components/vendor_support/intel/intel_byte_enable_ram.sv core/common_components/vendor_support/xilinx/xilinx_byte_enable_ram.sv -core/common_components/byte_en_BRAM.sv +core/common_components/byte_en_bram.sv core/execution_units/csr_unit.sv core/execution_units/gc_unit.sv @@ -59,9 +60,7 @@ core/execution_units/div_core.sv core/execution_units/div_unit.sv core/fetch_stage/ras.sv -core/fetch_stage/branch_predictor_ram.sv core/fetch_stage/branch_predictor.sv -core/fetch_stage/tag_bank.sv core/fetch_stage/icache_tag_banks.sv core/fetch_stage/icache.sv core/fetch_stage/fetch.sv From 89810cec57c25a9a75b51c6c1ebe7121b7ac4e29 Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Fri, 28 Apr 2023 14:18:35 -0400 Subject: [PATCH 10/16] Decode/Issue cleanup Signed-off-by: Eric Matthews --- core/decode_and_issue.sv | 105 +++++++----------- core/execution_units/gc_unit.sv | 2 +- .../internal_interfaces.sv | 4 +- examples/nexys/nexys_sim.sv | 17 ++- test_benches/verilator/cva5_sim.sv | 17 ++- 5 files changed, 66 insertions(+), 79 deletions(-) diff --git a/core/decode_and_issue.sv b/core/decode_and_issue.sv index 1d32be2..194890f 100755 --- a/core/decode_and_issue.sv +++ b/core/decode_and_issue.sv @@ -85,13 +85,11 @@ module decode_and_issue logic uses_rd; rs_addr_t decode_rs_addr [REGFILE_READ_PORTS]; + logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] decode_wb_group; - logic issue_valid; - logic operands_ready; - + logic issue_hold; + logic [REGFILE_READ_PORTS-1:0] operand_ready; logic [NUM_UNITS-1:0] unit_needed_issue_stage; - logic [NUM_UNITS-1:0] unit_ready; - logic [NUM_UNITS-1:0] issue_ready; logic [NUM_UNITS-1:0] issue_to; logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] issue_rs_wb_group [REGFILE_READ_PORTS]; @@ -99,9 +97,6 @@ module decode_and_issue logic pre_issue_exception_pending; logic illegal_instruction_pattern; - logic illegal_instruction_pattern_r; - - logic [REGFILE_READ_PORTS-1:0] rs_conflict; genvar i; //////////////////////////////////////////////////// @@ -109,8 +104,8 @@ module decode_and_issue //Can move data into issue stage if: // there is no instruction currently in the issue stage, or - // an instruction could issue (issue_flush, issue_hold and whether the instruction is valid are not needed in this check) - assign issue_stage_ready = ((~issue.stage_valid) | (issue_valid & |issue_ready)) & ~gc.issue_hold; + // an instruction could issue (ignoring gc.fetch_flush) + assign issue_stage_ready = (~issue.stage_valid) | (|issue_to); assign decode_advance = decode.valid & issue_stage_ready; //Instruction aliases @@ -132,19 +127,18 @@ module decode_and_issue //////////////////////////////////////////////////// //Renamer Support - logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] renamer_wb_group; always_comb begin - renamer_wb_group = $clog2(CONFIG.NUM_WB_GROUPS)'(CONFIG.NUM_WB_GROUPS - 1); + decode_wb_group = $clog2(CONFIG.NUM_WB_GROUPS)'(CONFIG.NUM_WB_GROUPS - 1); if (unit_needed[UNIT_IDS.ALU]) - renamer_wb_group = 0; + decode_wb_group = 0; else if (unit_needed[UNIT_IDS.LS] ) - renamer_wb_group = 1; + decode_wb_group = 1; end + assign renamer.rd_addr = decode_instruction.rd_addr; assign renamer.rs_addr = decode_rs_addr; assign renamer.uses_rd = uses_rd; - - assign renamer.rd_wb_group = renamer_wb_group; + assign renamer.rd_wb_group = decode_wb_group; assign renamer.id = decode.id; //////////////////////////////////////////////////// @@ -168,7 +162,7 @@ module decode_and_issue issue_rs_wb_group <= renamer.rs_wb_group; issue.rd_addr <= decode_instruction.rd_addr; issue.phys_rd_addr <= renamer.phys_rd_addr; - issue_rd_wb_group <= renamer_wb_group; + issue_rd_wb_group <= decode_wb_group; issue.is_multicycle <= ~unit_needed[UNIT_IDS.ALU]; issue.id <= decode.id; issue.exception_unit <= decode_exception_unit; @@ -190,24 +184,23 @@ module decode_and_issue end //////////////////////////////////////////////////// - //Unit ready - generate for (i=0; i Date: Fri, 28 Apr 2023 19:47:16 -0400 Subject: [PATCH 11/16] Mul cleanup Signed-off-by: Eric Matthews --- core/execution_units/mul_unit.sv | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/core/execution_units/mul_unit.sv b/core/execution_units/mul_unit.sv index 5e6ec92..6bb279c 100755 --- a/core/execution_units/mul_unit.sv +++ b/core/execution_units/mul_unit.sv @@ -50,7 +50,7 @@ module mul_unit logic valid [2]; id_t id [2]; - logic rs1_is_signed, rs2_is_signed; + logic rs1_is_signed, rs2_is_signed, is_mulhx; logic signed [32:0] rs1_ext, rs2_ext; logic signed [32:0] rs1_r, rs2_r; @@ -68,14 +68,19 @@ module mul_unit uses_rs[RS2] = unit_needed; uses_rd = unit_needed; end + + assign instruction = decode_stage.instruction; + always_ff @(posedge clk) begin + if (issue_stage_ready) begin + rs1_is_signed <= instruction.fn3[1:0] inside {MULH_fn3[1:0], MULHSU_fn3[1:0]}; + rs2_is_signed <= instruction.fn3[1:0] inside {MULH_fn3[1:0]}; + is_mulhx <= instruction.fn3[1:0] inside {MULH_fn3[1:0], MULHSU_fn3[1:0], MULHU_fn3[1:0]}; + end + end //////////////////////////////////////////////////// //Issue - - assign rs1_is_signed = issue_stage.fn3[1:0] inside {MULH_fn3[1:0], MULHSU_fn3[1:0]};//MUL doesn't matter - assign rs2_is_signed = issue_stage.fn3[1:0] inside {MUL_fn3[1:0], MULH_fn3[1:0]};//MUL doesn't matter - - assign rs1_ext = signed'({rf[RS1][31] & rs1_is_signed, rf[RS1]}); - assign rs2_ext = signed'({rf[RS2][31] & rs2_is_signed, rf[RS2]}); + assign rs1_ext = signed'({rs1_is_signed & rf[RS1][31], rf[RS1]}); + assign rs2_ext = signed'({rs2_is_signed & rf[RS2][31], rf[RS2]}); //Pipeline advancement control signals assign issue.ready = stage1_advance; @@ -96,7 +101,7 @@ module mul_unit //Attribute Pipeline always_ff @ (posedge clk) begin if (stage1_advance) begin - mulh[0] <= (issue_stage.fn3[1:0] != MUL_fn3[1:0]); + mulh[0] <= is_mulhx; id[0] <= issue.id; end if (stage2_advance) begin From 1d0ac14e704ee01d3c59cd45024af0ca1375747d Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Fri, 28 Apr 2023 19:51:18 -0400 Subject: [PATCH 12/16] Cleanup unit writeback group and ID assignment Signed-off-by: Eric Matthews --- core/cva5.sv | 168 +++++++++-------------- core/decode_and_issue.sv | 30 ++-- core/execution_units/csr_unit.sv | 2 +- core/types_and_interfaces/cva5_config.sv | 83 ++++++----- core/writeback.sv | 13 +- examples/litex/litex_wrapper.sv | 28 ++-- examples/nexys/nexys_sim.sv | 32 +++-- examples/nexys/nexys_wrapper.sv | 14 +- test_benches/verilator/cva5_sim.sv | 18 +-- 9 files changed, 195 insertions(+), 193 deletions(-) diff --git a/core/cva5.sv b/core/cva5.sv index 137e402..91e81ba 100755 --- a/core/cva5.sv +++ b/core/cva5.sv @@ -52,49 +52,12 @@ module cva5 ); //////////////////////////////////////////////////// - //Unit ID Assignment - //Generate Issue IDs based on configuration options - //Then assigned to a struct for ease in passing to sub modules + //WB Assignment + localparam unit_id_enum_t WB_GROUP1 [1] = '{ALU_ID}; + localparam unit_id_enum_t WB_GROUP2 [1] = '{LS_ID}; + localparam unit_id_enum_t WB_GROUP3 [4] = '{MUL_ID, DIV_ID, CSR_ID, CUSTOM_ID}; - //Units with writeback - localparam int unsigned ALU_UNIT_ID = 32'd0; - localparam int unsigned LS_UNIT_ID = 32'd1; - localparam int unsigned CSR_UNIT_ID = LS_UNIT_ID + int'(CONFIG.INCLUDE_CSRS); - localparam int unsigned MUL_UNIT_ID = CSR_UNIT_ID + int'(CONFIG.INCLUDE_MUL); - localparam int unsigned DIV_UNIT_ID = MUL_UNIT_ID + int'(CONFIG.INCLUDE_DIV); - localparam int unsigned CUSTOM_UNIT_ID = DIV_UNIT_ID + int'(CONFIG.INCLUDE_CUSTOM); - //Non-writeback units - localparam int unsigned BRANCH_UNIT_ID = CUSTOM_UNIT_ID + 1; - localparam int unsigned IEC_UNIT_ID = BRANCH_UNIT_ID + 1; - - //Total number of units - localparam int unsigned NUM_UNITS = IEC_UNIT_ID + 1; - - localparam unit_id_param_t UNIT_IDS = '{ - ALU : ALU_UNIT_ID, - LS : LS_UNIT_ID, - CSR : CSR_UNIT_ID, - MUL : MUL_UNIT_ID, - DIV : DIV_UNIT_ID, - CUSTOM : CUSTOM_UNIT_ID, - BR : BRANCH_UNIT_ID, - IEC : IEC_UNIT_ID - }; - - //////////////////////////////////////////////////// - //Writeback Port Assignment - // - localparam int unsigned NUM_WB_UNITS_GROUP_1 = 1;//ALU - localparam int unsigned ALU_UNIT_WB1_ID = 32'd0; - - localparam int unsigned NUM_WB_UNITS_GROUP_2 = 1;//LS - localparam int unsigned LS_UNIT_WB2_ID = 32'd0; - - localparam int unsigned NUM_WB_UNITS_GROUP_3 = int'(CONFIG.INCLUDE_CSRS) + int'(CONFIG.INCLUDE_MUL) + int'(CONFIG.INCLUDE_DIV) + int'(CONFIG.INCLUDE_CUSTOM); - localparam int unsigned DIV_UNIT_WB3_ID = 32'd0; - localparam int unsigned MUL_UNIT_WB3_ID = 32'd0 + int'(CONFIG.INCLUDE_DIV); - localparam int unsigned CSR_UNIT_WB3_ID = 32'd0 + int'(CONFIG.INCLUDE_MUL)+ int'(CONFIG.INCLUDE_DIV); - localparam int unsigned CUSTOM_UNIT_WB3_ID = 32'd0 + int'(CONFIG.INCLUDE_MUL)+ int'(CONFIG.INCLUDE_DIV) + int'(CONFIG.INCLUDE_CSRS); + unit_writeback_interface unit_wb [MAX_NUM_UNITS](); //////////////////////////////////////////////////// //Connecting Signals @@ -115,21 +78,17 @@ module cva5 issue_packet_t issue; register_file_issue_interface #(.NUM_WB_GROUPS(CONFIG.NUM_WB_GROUPS)) rf_issue(); - logic [NUM_UNITS-1:0] unit_needed; - logic [NUM_UNITS-1:0][REGFILE_READ_PORTS-1:0] unit_uses_rs; - logic [NUM_UNITS-1:0] unit_uses_rd; + logic [MAX_NUM_UNITS-1:0] unit_needed; + logic [MAX_NUM_UNITS-1:0][REGFILE_READ_PORTS-1:0] unit_uses_rs; + logic [MAX_NUM_UNITS-1:0] unit_uses_rd; logic [31:0] constant_alu; - unit_issue_interface unit_issue [NUM_UNITS-1:0](); + unit_issue_interface unit_issue [MAX_NUM_UNITS-1:0](); exception_packet_t ls_exception; logic ls_exception_is_store; - unit_writeback_interface unit_wb1 [NUM_WB_UNITS_GROUP_1](); - unit_writeback_interface unit_wb2 [NUM_WB_UNITS_GROUP_2](); - unit_writeback_interface unit_wb3 [NUM_WB_UNITS_GROUP_3 == 0 ? 1 : NUM_WB_UNITS_GROUP_3](); - mmu_interface immu(); mmu_interface dmmu(); @@ -356,10 +315,8 @@ module cva5 //////////////////////////////////////////////////// //Decode/Issue decode_and_issue #( - .CONFIG (CONFIG), - .NUM_UNITS (NUM_UNITS), - .UNIT_IDS (UNIT_IDS) - ) + .CONFIG (CONFIG) + ) decode_and_issue_block ( .clk (clk), .rst (rst), @@ -418,12 +375,12 @@ module cva5 .decode_stage (decode), .issue_stage (issue), .issue_stage_ready (issue_stage_ready), - .unit_needed (unit_needed[UNIT_IDS.BR]), - .uses_rs (unit_uses_rs[UNIT_IDS.BR]), - .uses_rd (unit_uses_rd[UNIT_IDS.BR]), + .unit_needed (unit_needed[BR_ID]), + .uses_rs (unit_uses_rs[BR_ID]), + .uses_rd (unit_uses_rd[BR_ID]), .rf (rf_issue.data), .constant_alu (constant_alu), - .issue (unit_issue[UNIT_IDS.BR]), + .issue (unit_issue[BR_ID]), .br_results (br_results), .branch_flush (branch_flush), .exception (exception[BR_EXCEPTION]) @@ -436,14 +393,14 @@ module cva5 .decode_stage (decode), .issue_stage (issue), .issue_stage_ready (issue_stage_ready), - .unit_needed (unit_needed[UNIT_IDS.ALU]), - .uses_rs (unit_uses_rs[UNIT_IDS.ALU]), - .uses_rd (unit_uses_rd[UNIT_IDS.ALU]), + .unit_needed (unit_needed[ALU_ID]), + .uses_rs (unit_uses_rs[ALU_ID]), + .uses_rd (unit_uses_rd[ALU_ID]), .rf (rf_issue.data), .constant_alu (constant_alu), .issue_rs_addr (issue_rs_addr), - .issue (unit_issue[UNIT_IDS.ALU]), - .wb (unit_wb1[ALU_UNIT_WB1_ID]) + .issue (unit_issue[ALU_ID]), + .wb (unit_wb[ALU_ID]) ); load_store_unit #(.CONFIG(CONFIG)) @@ -454,16 +411,16 @@ module cva5 .decode_stage (decode), .issue_stage (issue), .issue_stage_ready (issue_stage_ready), - .unit_needed (unit_needed[UNIT_IDS.LS]), - .uses_rs (unit_uses_rs[UNIT_IDS.LS]), - .uses_rd (unit_uses_rd[UNIT_IDS.LS]), + .unit_needed (unit_needed[LS_ID]), + .uses_rs (unit_uses_rs[LS_ID]), + .uses_rd (unit_uses_rd[LS_ID]), .decode_is_store (decode_is_store), .instruction_issued_with_rd (instruction_issued_with_rd), .issue_rs_addr (issue_rs_addr), .issue_rd_wb_group (issue_rd_wb_group), .rs2_inuse (rf_issue.inuse[RS2]), .rf (rf_issue.data), - .issue (unit_issue[UNIT_IDS.LS]), + .issue (unit_issue[LS_ID]), .dcache_on (1'b1), .clear_reservation (1'b0), .tlb (dtlb), @@ -480,7 +437,7 @@ module cva5 .store_retire (store_retire), .exception (exception[LS_EXCEPTION]), .load_store_status(load_store_status), - .wb (unit_wb2[LS_UNIT_WB2_ID]) + .wb (unit_wb[LS_ID]) ); generate if (CONFIG.INCLUDE_S_MODE) begin : gen_dtlb_dmmu @@ -511,7 +468,7 @@ module cva5 end endgenerate - generate if (CONFIG.INCLUDE_CSRS) begin : gen_csrs + generate if (CONFIG.INCLUDE_UNIT.CSR) begin : gen_csrs csr_unit # (.CONFIG(CONFIG)) csr_unit_block ( .clk(clk), @@ -520,12 +477,12 @@ module cva5 .issue_stage (issue), .issue_stage_ready (issue_stage_ready), .issue_rs_addr (issue_rs_addr), - .unit_needed (unit_needed[UNIT_IDS.CSR]), - .uses_rs (unit_uses_rs[UNIT_IDS.CSR]), - .uses_rd (unit_uses_rd[UNIT_IDS.CSR]), + .unit_needed (unit_needed[CSR_ID]), + .uses_rs (unit_uses_rs[CSR_ID]), + .uses_rd (unit_uses_rd[CSR_ID]), .rf (rf_issue.data), - .issue (unit_issue[UNIT_IDS.CSR]), - .wb (unit_wb3[CSR_UNIT_WB3_ID]), + .issue (unit_issue[CSR_ID]), + .wb (unit_wb[CSR_ID]), .current_privilege(current_privilege), .interrupt_taken(interrupt_taken), .interrupt_pending(interrupt_pending), @@ -554,12 +511,12 @@ module cva5 .decode_stage (decode), .issue_stage (issue), .issue_stage_ready (issue_stage_ready), - .unit_needed (unit_needed[UNIT_IDS.IEC]), - .uses_rs (unit_uses_rs[UNIT_IDS.IEC]), - .uses_rd (unit_uses_rd[UNIT_IDS.IEC]), + .unit_needed (unit_needed[IEC_ID]), + .uses_rs (unit_uses_rs[IEC_ID]), + .uses_rd (unit_uses_rd[IEC_ID]), .constant_alu (constant_alu), .rf (rf_issue.data), - .issue (unit_issue[UNIT_IDS.IEC]), + .issue (unit_issue[IEC_ID]), .branch_flush (branch_flush), .exception (exception), .exception_target_pc (exception_target_pc), @@ -579,23 +536,23 @@ module cva5 .post_issue_count (post_issue_count) ); - generate if (CONFIG.INCLUDE_MUL) begin : gen_mul + generate if (CONFIG.INCLUDE_UNIT.MUL) begin : gen_mul mul_unit mul_unit_block ( .clk (clk), .rst (rst), .decode_stage (decode), .issue_stage (issue), .issue_stage_ready (issue_stage_ready), - .unit_needed (unit_needed[UNIT_IDS.MUL]), - .uses_rs (unit_uses_rs[UNIT_IDS.MUL]), - .uses_rd (unit_uses_rd[UNIT_IDS.MUL]), + .unit_needed (unit_needed[MUL_ID]), + .uses_rs (unit_uses_rs[MUL_ID]), + .uses_rd (unit_uses_rd[MUL_ID]), .rf (rf_issue.data), - .issue (unit_issue[UNIT_IDS.MUL]), - .wb (unit_wb3[MUL_UNIT_WB3_ID]) + .issue (unit_issue[MUL_ID]), + .wb (unit_wb[MUL_ID]) ); end endgenerate - generate if (CONFIG.INCLUDE_DIV) begin : gen_div + generate if (CONFIG.INCLUDE_UNIT.DIV) begin : gen_div div_unit div_unit_block ( .clk (clk), .rst (rst), @@ -605,67 +562,68 @@ module cva5 .issue_stage (issue), .issue_stage_ready (issue_stage_ready), .issue_rs_addr (issue_rs_addr), - .unit_needed (unit_needed[UNIT_IDS.DIV]), - .uses_rs (unit_uses_rs[UNIT_IDS.DIV]), - .uses_rd (unit_uses_rd[UNIT_IDS.DIV]), + .unit_needed (unit_needed[DIV_ID]), + .uses_rs (unit_uses_rs[DIV_ID]), + .uses_rd (unit_uses_rd[DIV_ID]), .rf (rf_issue.data), - .issue (unit_issue[UNIT_IDS.DIV]), - .wb (unit_wb3[DIV_UNIT_WB3_ID]) + .issue (unit_issue[DIV_ID]), + .wb (unit_wb[DIV_ID]) ); end endgenerate - generate if (CONFIG.INCLUDE_CUSTOM) begin : gen_custom + generate if (CONFIG.INCLUDE_UNIT.CUSTOM) begin : gen_custom custom_unit custom_unit_block ( .clk (clk), .rst (rst), .decode_stage (decode), - .unit_needed (unit_needed[UNIT_IDS.CUSTOM]), - .uses_rs (unit_uses_rs[UNIT_IDS.CUSTOM]), - .uses_rd (unit_uses_rd[UNIT_IDS.CUSTOM]), + .unit_needed (unit_needed[CUSTOM_ID]), + .uses_rs (unit_uses_rs[CUSTOM_ID]), + .uses_rd (unit_uses_rd[CUSTOM_ID]), .issue_stage (issue), .issue_stage_ready (issue_stage_ready), .rf (rf_issue.data), - .issue (unit_issue[UNIT_IDS.CUSTOM]), - .wb (unit_wb3[CUSTOM_UNIT_WB3_ID]) + .issue (unit_issue[CUSTOM_ID]), + .wb (unit_wb[CUSTOM_ID]) ); end endgenerate //////////////////////////////////////////////////// //Writeback - //First writeback port: ALU - //Second writeback port: LS, CSR, [MUL], [DIV] writeback #( .CONFIG (CONFIG), - .NUM_WB_UNITS (NUM_WB_UNITS_GROUP_1) + .NUM_WB_UNITS ($size(WB_GROUP1)), + .WB_INDEX (WB_GROUP1) ) writeback_block1 ( .clk (clk), .rst (rst), .wb_packet (wb_packet[0]), - .unit_wb (unit_wb1) + .unit_wb (unit_wb) ); writeback #( .CONFIG (CONFIG), - .NUM_WB_UNITS (NUM_WB_UNITS_GROUP_2) + .NUM_WB_UNITS ($size(WB_GROUP2)), + .WB_INDEX (WB_GROUP2) ) writeback_block2 ( .clk (clk), .rst (rst), .wb_packet (wb_packet[1]), - .unit_wb (unit_wb2) + .unit_wb (unit_wb) ); - generate if (NUM_WB_UNITS_GROUP_3 > 0) begin : gen_wb3 + generate if ($size(WB_GROUP3) > 0) begin : gen_wb3 writeback #( .CONFIG (CONFIG), - .NUM_WB_UNITS (NUM_WB_UNITS_GROUP_3) + .NUM_WB_UNITS ($size(WB_GROUP3)), + .WB_INDEX (WB_GROUP3) ) writeback_block3 ( .clk (clk), .rst (rst), .wb_packet (wb_packet[2]), - .unit_wb (unit_wb3) + .unit_wb (unit_wb) ); end endgenerate //////////////////////////////////////////////////// diff --git a/core/decode_and_issue.sv b/core/decode_and_issue.sv index 194890f..f5c9a77 100755 --- a/core/decode_and_issue.sv +++ b/core/decode_and_issue.sv @@ -29,9 +29,7 @@ module decode_and_issue import opcodes::*; # ( - parameter cpu_config_t CONFIG = EXAMPLE_CONFIG, - parameter NUM_UNITS = 7, - parameter unit_id_param_t UNIT_IDS = EXAMPLE_UNIT_IDS + parameter cpu_config_t CONFIG = EXAMPLE_CONFIG ) ( @@ -47,9 +45,9 @@ module decode_and_issue //Renamer renamer_interface.decode renamer, - input logic [NUM_UNITS-1:0] unit_needed, - input logic [NUM_UNITS-1:0][REGFILE_READ_PORTS-1:0] unit_uses_rs, - input logic [NUM_UNITS-1:0] unit_uses_rd, + input logic [MAX_NUM_UNITS-1:0] unit_needed, + input logic [MAX_NUM_UNITS-1:0][REGFILE_READ_PORTS-1:0] unit_uses_rs, + input logic [MAX_NUM_UNITS-1:0] unit_uses_rd, output logic decode_uses_rd, output rs_addr_t decode_rd_addr, @@ -70,7 +68,7 @@ module decode_and_issue output logic [31:0] constant_alu, - unit_issue_interface.decode unit_issue [NUM_UNITS-1:0], + unit_issue_interface.decode unit_issue [MAX_NUM_UNITS-1:0], input gc_outputs_t gc, input logic [1:0] current_privilege, @@ -89,8 +87,8 @@ module decode_and_issue logic issue_hold; logic [REGFILE_READ_PORTS-1:0] operand_ready; - logic [NUM_UNITS-1:0] unit_needed_issue_stage; - logic [NUM_UNITS-1:0] issue_to; + logic [MAX_NUM_UNITS-1:0] unit_needed_issue_stage; + logic [MAX_NUM_UNITS-1:0] issue_to; logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] issue_rs_wb_group [REGFILE_READ_PORTS]; logic issue_uses_rs [REGFILE_READ_PORTS]; @@ -120,7 +118,7 @@ module decode_and_issue always_comb begin uses_rd = |unit_uses_rd; uses_rs = '{default: 0}; - for (int i = 0; i < NUM_UNITS; i++) + for (int i = 0; i < MAX_NUM_UNITS; i++) for (int j = 0; j < REGFILE_READ_PORTS; j++) uses_rs[j] |= unit_uses_rs[i][j]; end @@ -129,9 +127,9 @@ module decode_and_issue //Renamer Support always_comb begin decode_wb_group = $clog2(CONFIG.NUM_WB_GROUPS)'(CONFIG.NUM_WB_GROUPS - 1); - if (unit_needed[UNIT_IDS.ALU]) + if (unit_needed[ALU_ID]) decode_wb_group = 0; - else if (unit_needed[UNIT_IDS.LS] ) + else if (unit_needed[LS_ID] ) decode_wb_group = 1; end @@ -163,7 +161,7 @@ module decode_and_issue issue.rd_addr <= decode_instruction.rd_addr; issue.phys_rd_addr <= renamer.phys_rd_addr; issue_rd_wb_group <= decode_wb_group; - issue.is_multicycle <= ~unit_needed[UNIT_IDS.ALU]; + issue.is_multicycle <= ~unit_needed[ALU_ID]; issue.id <= decode.id; issue.exception_unit <= decode_exception_unit; issue_uses_rs <= uses_rs; @@ -193,7 +191,7 @@ module decode_and_issue //////////////////////////////////////////////////// //Unit EX signals - generate for (i = 0; i < NUM_UNITS; i++) begin : gen_unit_issue_signals + generate for (i = 0; i < MAX_NUM_UNITS; i++) begin : gen_unit_issue_signals assign unit_issue[i].possible_issue = issue.stage_valid & unit_needed_issue_stage[i] & unit_issue[i].ready; assign issue_to[i] = unit_issue[i].possible_issue & (&operand_ready) & ~issue_hold; assign unit_issue[i].new_request = issue_to[i] & ~gc.fetch_flush; @@ -233,8 +231,8 @@ module decode_and_issue //can be automatically added to this expression always_comb begin unique case (1'b1) - unit_needed[UNIT_IDS.LS] : decode_exception_unit = LS_EXCEPTION; - unit_needed[UNIT_IDS.BR] : decode_exception_unit = BR_EXCEPTION; + unit_needed[LS_ID] : decode_exception_unit = LS_EXCEPTION; + unit_needed[BR_ID] : decode_exception_unit = BR_EXCEPTION; default : decode_exception_unit = PRE_ISSUE_EXCEPTION; endcase if (~decode.fetch_metadata.ok) diff --git a/core/execution_units/csr_unit.sv b/core/execution_units/csr_unit.sv index 394a456..d644e96 100755 --- a/core/execution_units/csr_unit.sv +++ b/core/execution_units/csr_unit.sv @@ -284,7 +284,7 @@ module csr_unit mxlen:1, A:(CONFIG.INCLUDE_AMO), I:1, - M:(CONFIG.INCLUDE_MUL && CONFIG.INCLUDE_DIV), + M:(CONFIG.INCLUDE_UNIT.MUL && CONFIG.INCLUDE_UNIT.DIV), S:(CONFIG.INCLUDE_S_MODE), U:(CONFIG.INCLUDE_U_MODE) }; diff --git a/core/types_and_interfaces/cva5_config.sv b/core/types_and_interfaces/cva5_config.sv index 1bc7976..57e78b0 100755 --- a/core/types_and_interfaces/cva5_config.sv +++ b/core/types_and_interfaces/cva5_config.sv @@ -99,17 +99,51 @@ package cva5_config; int unsigned DEPTH; } tlb_config_t; + //////////////////////////////////////////////////// + //Unit IDs + //To add a new unit update: + // - MAX_NUM_UNITS + // - units_t + // - unit_id_enum_t + //ensuring that the bit index in units_t matches the enum value in unit_id_enum_t + + localparam MAX_NUM_UNITS = 8; + typedef struct packed { + bit IEC; + bit BR; + //End of Write-Back Units + bit CUSTOM; + bit CSR; + bit DIV; + bit MUL; + bit LS; + bit ALU; + } units_t; + + typedef enum bit [$clog2(MAX_NUM_UNITS)-1:0] { + IEC_ID = 7, + BR_ID = 6, + //End of Write-Back Units + CUSTOM_ID = 5, + CSR_ID = 4, + DIV_ID = 3, + MUL_ID = 2, + LS_ID = 1, + ALU_ID = 0 + } unit_id_enum_t; + 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_IFENCE; //local mem operations only - bit INCLUDE_CSRS; - bit INCLUDE_AMO; //cache operations only - bit INCLUDE_CUSTOM; + bit INCLUDE_AMO; + + //Units + units_t INCLUDE_UNIT; + //CSR constants csr_config_t CSRS; //Memory Options @@ -159,12 +193,21 @@ package cva5_config; INCLUDE_M_MODE : 1, INCLUDE_S_MODE : 0, INCLUDE_U_MODE : 0, - INCLUDE_MUL : 1, - INCLUDE_DIV : 1, + + INCLUDE_UNIT : '{ + ALU : 1, + LS : 1, + MUL : 1, + DIV : 1, + CSR : 1, + CUSTOM : 0, + BR : 1, + IEC : 1 + }, + INCLUDE_IFENCE : 1, - INCLUDE_CSRS : 1, INCLUDE_AMO : 0, - INCLUDE_CUSTOM : 0, + //CSR constants CSRS : '{ MACHINE_IMPLEMENTATION_ID : 0, @@ -256,29 +299,7 @@ package cva5_config; NUM_WB_GROUPS : 3 }; - //////////////////////////////////////////////////// - //Unit IDs - typedef struct packed { - int unsigned ALU; - int unsigned LS; - int unsigned CSR; - int unsigned MUL; - int unsigned DIV; - int unsigned CUSTOM; - int unsigned BR; - int unsigned IEC; - } unit_id_param_t; - localparam unit_id_param_t EXAMPLE_UNIT_IDS = '{ - ALU : 0, - LS : 1, - CSR : 2, - MUL : 3, - DIV : 4, - CUSTOM : 5, - BR : 6, - IEC : 7 - }; //////////////////////////////////////////////////// //Bus Options diff --git a/core/writeback.sv b/core/writeback.sv index 0c853d3..7652591 100644 --- a/core/writeback.sv +++ b/core/writeback.sv @@ -28,14 +28,15 @@ module writeback # ( parameter cpu_config_t CONFIG = EXAMPLE_CONFIG, - parameter int unsigned NUM_WB_UNITS = 5 + parameter int unsigned NUM_WB_UNITS = 5, + parameter unit_id_enum_t WB_INDEX [NUM_WB_UNITS] = '{ALU_ID, MUL_ID, DIV_ID, LS_ID, CSR_ID} ) ( input logic clk, input logic rst, //Unit writeback - unit_writeback_interface.wb unit_wb[NUM_WB_UNITS], + unit_writeback_interface.wb unit_wb[MAX_NUM_UNITS], //WB output output wb_packet_t wb_packet ); @@ -53,10 +54,10 @@ module writeback //Implementation //Re-assigning interface inputs to array types so that they can be dynamically indexed generate for (genvar i = 0; i < NUM_WB_UNITS; i++) begin : gen_wb_unit_unpacking - assign unit_instruction_id[i] = unit_wb[i].id; - assign unit_done[i] = unit_wb[i].done; - assign unit_rd[i] = unit_wb[i].rd; - assign unit_wb[i].ack = unit_ack[i]; + assign unit_instruction_id[i] = unit_wb[WB_INDEX[i]].id; + assign unit_done[i] = unit_wb[WB_INDEX[i]].done; + assign unit_rd[i] = unit_wb[WB_INDEX[i]].rd; + assign unit_wb[WB_INDEX[i]].ack = unit_ack[i]; end endgenerate //////////////////////////////////////////////////// diff --git a/examples/litex/litex_wrapper.sv b/examples/litex/litex_wrapper.sv index 2838fff..f9aa573 100755 --- a/examples/litex/litex_wrapper.sv +++ b/examples/litex/litex_wrapper.sv @@ -79,12 +79,18 @@ module litex_wrapper INCLUDE_M_MODE : 1, INCLUDE_S_MODE : 0, INCLUDE_U_MODE : 0, - INCLUDE_MUL : 0, - INCLUDE_DIV : 0, + INCLUDE_UNIT : '{ + ALU : 1, + LS : 1, + MUL : 0, + DIV : 0, + CSR : 1, + CUSTOM : 0, + BR : 1, + IEC : 1 + }, INCLUDE_IFENCE : 0, - INCLUDE_CSRS : 1, INCLUDE_AMO : 0, - INCLUDE_CUSTOM : 0, //CSR constants CSRS : '{ MACHINE_IMPLEMENTATION_ID : 0, @@ -181,12 +187,18 @@ module litex_wrapper INCLUDE_M_MODE : 1, INCLUDE_S_MODE : 0, INCLUDE_U_MODE : 0, - INCLUDE_MUL : 1, - INCLUDE_DIV : 1, + INCLUDE_UNIT : '{ + ALU : 1, + LS : 1, + MUL : 1, + DIV : 1, + CSR : 1, + CUSTOM : 0, + BR : 1, + IEC : 1 + }, INCLUDE_IFENCE : 0, - INCLUDE_CSRS : 1, INCLUDE_AMO : 0, - INCLUDE_CUSTOM : 0, //CSR constants CSRS : '{ MACHINE_IMPLEMENTATION_ID : 0, diff --git a/examples/nexys/nexys_sim.sv b/examples/nexys/nexys_sim.sv index d8e1472..6741d29 100644 --- a/examples/nexys/nexys_sim.sv +++ b/examples/nexys/nexys_sim.sv @@ -106,12 +106,18 @@ module cva5_sim INCLUDE_M_MODE : 1, INCLUDE_S_MODE : 0, INCLUDE_U_MODE : 0, - INCLUDE_MUL : 1, - INCLUDE_DIV : 1, + INCLUDE_UNIT : '{ + ALU : 1, + LS : 1, + MUL : 1, + DIV : 1, + CSR : 1, + CUSTOM : 0, + BR : 1, + IEC : 1 + }, INCLUDE_IFENCE : 0, - INCLUDE_CSRS : 1, INCLUDE_AMO : 0, - INCLUDE_CUSTOM : 0, //CSR constants CSRS : '{ MACHINE_IMPLEMENTATION_ID : 0, @@ -348,7 +354,7 @@ module cva5_sim //Issue rd_addr to unit mem //Used for determining what outputs an operand stall is waiting on - logic [`ISSUE_P.NUM_UNITS-1:0] rd_addr_table [32]; + logic [MAX_NUM_UNITS-1:0] rd_addr_table [32]; always_ff @(posedge clk) begin if (cpu.instruction_issued_with_rd) @@ -367,8 +373,8 @@ module cva5_sim assign darb_stall = cpu.l1_request[L1_DCACHE_ID].request & ~cpu.l1_request[L1_DCACHE_ID].ack; end endgenerate - logic [`ISSUE_P.NUM_UNITS-1:0] unit_ready; - generate for (i=0; i<`ISSUE_P.NUM_UNITS; i++) + logic [MAX_NUM_UNITS-1:0] unit_ready; + generate for (i=0; i Date: Sat, 29 Apr 2023 18:37:42 -0400 Subject: [PATCH 13/16] Move write-back group config into cpu_config struct Signed-off-by: Eric Matthews --- core/cva5.sv | 43 ++++-------------------- core/types_and_interfaces/cva5_config.sv | 28 +++++++++++++-- core/writeback.sv | 2 +- examples/litex/litex_wrapper.sv | 20 +++++++++-- examples/nexys/nexys_sim.sv | 10 +++++- examples/nexys/nexys_wrapper.sv | 10 +++++- 6 files changed, 70 insertions(+), 43 deletions(-) diff --git a/core/cva5.sv b/core/cva5.sv index 91e81ba..5287c86 100755 --- a/core/cva5.sv +++ b/core/cva5.sv @@ -51,14 +51,6 @@ module cva5 input interrupt_t m_interrupt ); - //////////////////////////////////////////////////// - //WB Assignment - localparam unit_id_enum_t WB_GROUP1 [1] = '{ALU_ID}; - localparam unit_id_enum_t WB_GROUP2 [1] = '{LS_ID}; - localparam unit_id_enum_t WB_GROUP3 [4] = '{MUL_ID, DIV_ID, CSR_ID, CUSTOM_ID}; - - unit_writeback_interface unit_wb [MAX_NUM_UNITS](); - //////////////////////////////////////////////////// //Connecting Signals l1_arbiter_request_interface l1_request[L1_CONNECTIONS-1:0](); @@ -129,6 +121,7 @@ module cva5 logic retire_port_valid [RETIRE_PORTS]; logic [LOG2_RETIRE_PORTS : 0] retire_count; //Writeback + unit_writeback_interface unit_wb [MAX_NUM_UNITS](); wb_packet_t wb_packet [CONFIG.NUM_WB_GROUPS]; phys_addr_t wb_phys_addr [CONFIG.NUM_WB_GROUPS]; //Exception @@ -590,42 +583,20 @@ module cva5 //////////////////////////////////////////////////// //Writeback - writeback #( - .CONFIG (CONFIG), - .NUM_WB_UNITS ($size(WB_GROUP1)), - .WB_INDEX (WB_GROUP1) - ) - writeback_block1 ( - .clk (clk), - .rst (rst), - .wb_packet (wb_packet[0]), - .unit_wb (unit_wb) - ); - writeback #( - .CONFIG (CONFIG), - .NUM_WB_UNITS ($size(WB_GROUP2)), - .WB_INDEX (WB_GROUP2) - ) - writeback_block2 ( - .clk (clk), - .rst (rst), - .wb_packet (wb_packet[1]), - .unit_wb (unit_wb) - ); - - generate if ($size(WB_GROUP3) > 0) begin : gen_wb3 + generate for (genvar i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin : gen_wb writeback #( .CONFIG (CONFIG), - .NUM_WB_UNITS ($size(WB_GROUP3)), - .WB_INDEX (WB_GROUP3) + .NUM_WB_UNITS (get_num_wb_units(CONFIG.WB_GROUP[i])), + .WB_INDEX (CONFIG.WB_GROUP[i]) ) - writeback_block3 ( + writeback_block ( .clk (clk), .rst (rst), - .wb_packet (wb_packet[2]), + .wb_packet (wb_packet[i]), .unit_wb (unit_wb) ); end endgenerate + //////////////////////////////////////////////////// //End of Implementation //////////////////////////////////////////////////// diff --git a/core/types_and_interfaces/cva5_config.sv b/core/types_and_interfaces/cva5_config.sv index 57e78b0..1e5a266 100755 --- a/core/types_and_interfaces/cva5_config.sv +++ b/core/types_and_interfaces/cva5_config.sv @@ -106,7 +106,7 @@ package cva5_config; // - units_t // - unit_id_enum_t //ensuring that the bit index in units_t matches the enum value in unit_id_enum_t - + //Additionally, writeback units must be grouped before non-writeback units localparam MAX_NUM_UNITS = 8; typedef struct packed { bit IEC; @@ -120,6 +120,7 @@ package cva5_config; bit ALU; } units_t; + typedef enum bit [$clog2(MAX_NUM_UNITS)-1:0] { IEC_ID = 7, BR_ID = 6, @@ -131,6 +132,9 @@ package cva5_config; LS_ID = 1, ALU_ID = 0 } unit_id_enum_t; + localparam unit_id_enum_t NON_WRITEBACK_ID = BR_ID; + + typedef unit_id_enum_t [MAX_NUM_UNITS-1:0][MAX_NUM_UNITS-1:0] wb_group_config_t; typedef struct packed { //ISA options @@ -175,6 +179,7 @@ package cva5_config; branch_predictor_config_t BP; //Writeback Options int unsigned NUM_WB_GROUPS; + wb_group_config_t WB_GROUP; } cpu_config_t; //Function to generate derived cache parameters @@ -188,6 +193,24 @@ package cva5_config; endfunction + //WB config + //ALU requires its own WB port + //LS unit must be the first unit on its writeback port (LS unit does not use ack signal for timing considerations) + localparam wb_group_config_t EXAMPLE_WB_GROUP_CONFIG = '{ + 0 : '{0: ALU_ID, default : NON_WRITEBACK_ID}, + 1 : '{0: LS_ID, default : NON_WRITEBACK_ID}, + 2 : '{0: MUL_ID, 1: DIV_ID, 2: CSR_ID, 3: CUSTOM_ID, default : NON_WRITEBACK_ID}, + default : '{default : NON_WRITEBACK_ID} + }; + + //Convenience function for determining how many writeback units are in each writeback group + function int unsigned get_num_wb_units (input unit_id_enum_t [MAX_NUM_UNITS-1:0] ids); + get_num_wb_units = 0; + for (int i = 0; i < MAX_NUM_UNITS; i++) + if (ids[i] != NON_WRITEBACK_ID) + get_num_wb_units++; + endfunction + localparam cpu_config_t EXAMPLE_CONFIG = '{ //ISA options INCLUDE_M_MODE : 1, @@ -296,7 +319,8 @@ package cva5_config; RAS_ENTRIES : 8 }, //Writeback Options - NUM_WB_GROUPS : 3 + NUM_WB_GROUPS : 3, + WB_GROUP : EXAMPLE_WB_GROUP_CONFIG }; diff --git a/core/writeback.sv b/core/writeback.sv index 7652591..9b9ef4b 100644 --- a/core/writeback.sv +++ b/core/writeback.sv @@ -29,7 +29,7 @@ module writeback # ( parameter cpu_config_t CONFIG = EXAMPLE_CONFIG, parameter int unsigned NUM_WB_UNITS = 5, - parameter unit_id_enum_t WB_INDEX [NUM_WB_UNITS] = '{ALU_ID, MUL_ID, DIV_ID, LS_ID, CSR_ID} + parameter unit_id_enum_t [MAX_NUM_UNITS-1:0] WB_INDEX = '{0: ALU_ID, 1: MUL_ID, 2: DIV_ID, 3: LS_ID, 4: CSR_ID, default: NON_WRITEBACK_ID} ) ( diff --git a/examples/litex/litex_wrapper.sv b/examples/litex/litex_wrapper.sv index f9aa573..a775895 100755 --- a/examples/litex/litex_wrapper.sv +++ b/examples/litex/litex_wrapper.sv @@ -74,6 +74,13 @@ module litex_wrapper input logic idbus_err ); + + localparam wb_group_config_t MINIMAL_WB_GROUP_CONFIG = '{ + 0 : '{0: ALU_ID, default : NON_WRITEBACK_ID}, + 1 : '{0: LS_ID, 1: CSR_ID, default : NON_WRITEBACK_ID}, + default : '{default : NON_WRITEBACK_ID} + }; + localparam cpu_config_t MINIMAL_CONFIG = '{ //ISA options INCLUDE_M_MODE : 1, @@ -179,7 +186,15 @@ module litex_wrapper RAS_ENTRIES : 8 }, //Writeback Options - NUM_WB_GROUPS : 2 + NUM_WB_GROUPS : 2, + WB_GROUP : MINIMAL_WB_GROUP_CONFIG + }; + + localparam wb_group_config_t STANDARD_WB_GROUP_CONFIG = '{ + 0 : '{0: ALU_ID, default : NON_WRITEBACK_ID}, + 1 : '{0: LS_ID, default : NON_WRITEBACK_ID}, + 2 : '{0: MUL_ID, 1: DIV_ID, 2: CSR_ID, 3: CUSTOM_ID, default : NON_WRITEBACK_ID}, + default : '{default : NON_WRITEBACK_ID} }; localparam cpu_config_t STANDARD_CONFIG = '{ @@ -287,7 +302,8 @@ module litex_wrapper RAS_ENTRIES : 8 }, //Writeback Options - NUM_WB_GROUPS : 3 + NUM_WB_GROUPS : 3, + WB_GROUP : STANDARD_WB_GROUP_CONFIG }; function cpu_config_t config_select (input integer variant); diff --git a/examples/nexys/nexys_sim.sv b/examples/nexys/nexys_sim.sv index 6741d29..4f404df 100644 --- a/examples/nexys/nexys_sim.sv +++ b/examples/nexys/nexys_sim.sv @@ -101,6 +101,13 @@ module cva5_sim output logic store_queue_empty ); + localparam wb_group_config_t NEXYS_WB_GROUP_CONFIG = '{ + 0 : '{0: ALU_ID, default : NON_WRITEBACK_ID}, + 1 : '{0: LS_ID, default : NON_WRITEBACK_ID}, + 2 : '{0: MUL_ID, 1: DIV_ID, 2: CSR_ID, 3: CUSTOM_ID, default : NON_WRITEBACK_ID}, + default : '{default : NON_WRITEBACK_ID} + }; + localparam cpu_config_t NEXYS_CONFIG = '{ //ISA options INCLUDE_M_MODE : 1, @@ -206,7 +213,8 @@ module cva5_sim RAS_ENTRIES : 8 }, //Writeback Options - NUM_WB_GROUPS : 3 + NUM_WB_GROUPS : 3, + WB_GROUP : NEXYS_WB_GROUP_CONFIG }; parameter SCRATCH_MEM_KB = 128; diff --git a/examples/nexys/nexys_wrapper.sv b/examples/nexys/nexys_wrapper.sv index bd68ae3..261018b 100644 --- a/examples/nexys/nexys_wrapper.sv +++ b/examples/nexys/nexys_wrapper.sv @@ -75,6 +75,13 @@ module nexys_wrapper input logic [5:0] m_axi_bid ); + localparam wb_group_config_t NEXYS_WB_GROUP_CONFIG = '{ + 0 : '{0: ALU_ID, default : NON_WRITEBACK_ID}, + 1 : '{0: LS_ID, default : NON_WRITEBACK_ID}, + 2 : '{0: MUL_ID, 1: DIV_ID, 2: CSR_ID, 3: CUSTOM_ID, default : NON_WRITEBACK_ID}, + default : '{default : NON_WRITEBACK_ID} + }; + localparam cpu_config_t NEXYS_CONFIG = '{ //ISA options INCLUDE_M_MODE : 1, @@ -180,7 +187,8 @@ module nexys_wrapper RAS_ENTRIES : 8 }, //Writeback Options - NUM_WB_GROUPS : 3 + NUM_WB_GROUPS : 3, + WB_GROUP : NEXYS_WB_GROUP_CONFIG }; //Unused outputs From 583976c7ea4fb0bf8519fce72411d6322724cf68 Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Sat, 29 Apr 2023 18:48:16 -0400 Subject: [PATCH 14/16] Share nexys config between simulation and hardware wrapper Signed-off-by: Eric Matthews --- examples/nexys/nexys_config.sv | 144 +++++++++++++++++++ examples/nexys/nexys_sim.sv | 119 +-------------- examples/nexys/nexys_wrapper.sv | 117 +-------------- examples/nexys/scripts/cva5-ip-core-base.tcl | 1 + tools/cva5.mak | 2 +- 5 files changed, 149 insertions(+), 234 deletions(-) create mode 100644 examples/nexys/nexys_config.sv diff --git a/examples/nexys/nexys_config.sv b/examples/nexys/nexys_config.sv new file mode 100644 index 0000000..8624fd7 --- /dev/null +++ b/examples/nexys/nexys_config.sv @@ -0,0 +1,144 @@ +/* + * Copyright © 2023 Eric Matthews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Initial code developed under the supervision of Dr. Lesley Shannon, + * Reconfigurable Computing Lab, Simon Fraser University. + * + * Author(s): + * Eric Matthews + */ + + + +package nexys_config; + import cva5_config::*; + + localparam wb_group_config_t NEXYS_WB_GROUP_CONFIG = '{ + 0 : '{0: ALU_ID, default : NON_WRITEBACK_ID}, + 1 : '{0: LS_ID, default : NON_WRITEBACK_ID}, + 2 : '{0: MUL_ID, 1: DIV_ID, 2: CSR_ID, 3: CUSTOM_ID, default : NON_WRITEBACK_ID}, + default : '{default : NON_WRITEBACK_ID} + }; + + localparam cpu_config_t NEXYS_CONFIG = '{ + //ISA options + INCLUDE_M_MODE : 1, + INCLUDE_S_MODE : 0, + INCLUDE_U_MODE : 0, + INCLUDE_UNIT : '{ + ALU : 1, + LS : 1, + MUL : 1, + DIV : 1, + CSR : 1, + CUSTOM : 0, + BR : 1, + IEC : 1 + }, + INCLUDE_IFENCE : 0, + INCLUDE_AMO : 0, + //CSR constants + CSRS : '{ + MACHINE_IMPLEMENTATION_ID : 0, + CPU_ID : 0, + RESET_VEC : 32'h80000000, + RESET_MTVEC : 32'h80000000, + NON_STANDARD_OPTIONS : '{ + COUNTER_W : 33, + MCYCLE_WRITEABLE : 0, + MINSTR_WRITEABLE : 0, + MTVEC_WRITEABLE : 1, + INCLUDE_MSCRATCH : 0, + INCLUDE_MCAUSE : 1, + INCLUDE_MTVAL : 1 + } + }, + //Memory Options + SQ_DEPTH : 8, + INCLUDE_FORWARDING_TO_STORES : 1, + INCLUDE_ICACHE : 1, + ICACHE_ADDR : '{ + L : 32'h80000000, + H : 32'h87FFFFFF + }, + ICACHE : '{ + LINES : 256, + LINE_W : 8, + WAYS : 2, + USE_EXTERNAL_INVALIDATIONS : 0, + USE_NON_CACHEABLE : 0, + NON_CACHEABLE : '{ + L : 32'h88000000, + H : 32'h8FFFFFFF + } + }, + ITLB : '{ + WAYS : 2, + DEPTH : 64 + }, + INCLUDE_DCACHE : 1, + DCACHE_ADDR : '{ + L : 32'h80000000, + H : 32'h8FFFFFFF + }, + DCACHE : '{ + LINES : 512, + LINE_W : 8, + WAYS : 1, + USE_EXTERNAL_INVALIDATIONS : 0, + USE_NON_CACHEABLE : 1, + NON_CACHEABLE : '{ + L : 32'h88000000, + H : 32'h8FFFFFFF + } + }, + DTLB : '{ + WAYS : 2, + DEPTH : 64 + }, + INCLUDE_ILOCAL_MEM : 0, + ILOCAL_MEM_ADDR : '{ + L : 32'h80000000, + H : 32'h8FFFFFFF + }, + INCLUDE_DLOCAL_MEM : 0, + DLOCAL_MEM_ADDR : '{ + L : 32'h80000000, + H : 32'h8FFFFFFF + }, + INCLUDE_IBUS : 0, + IBUS_ADDR : '{ + L : 32'h00000000, + H : 32'hFFFFFFFF + }, + INCLUDE_PERIPHERAL_BUS : 0, + PERIPHERAL_BUS_ADDR : '{ + L : 32'h00000000, + H : 32'hFFFFFFFF + }, + PERIPHERAL_BUS_TYPE : AXI_BUS, + //Branch Predictor Options + INCLUDE_BRANCH_PREDICTOR : 1, + BP : '{ + WAYS : 2, + ENTRIES : 512, + RAS_ENTRIES : 8 + }, + //Writeback Options + NUM_WB_GROUPS : 3, + WB_GROUP : NEXYS_WB_GROUP_CONFIG + }; + +endpackage \ No newline at end of file diff --git a/examples/nexys/nexys_sim.sv b/examples/nexys/nexys_sim.sv index 4f404df..c11b03c 100644 --- a/examples/nexys/nexys_sim.sv +++ b/examples/nexys/nexys_sim.sv @@ -26,9 +26,10 @@ module cva5_sim import l2_config_and_types::*; import riscv_types::*; import cva5_types::*; + import nexys_config::*; # ( - parameter MEMORY_FILE = "/home/ematthew/Research/RISCV/software/riscv-tools/riscv-tests/benchmarks/dhrystone.riscv.hw_init" //change this to appropriate location "/home/ematthew/Downloads/dhrystone.riscv.sim_init" + parameter MEMORY_FILE = ".hw_init" //change this to appropriate location ) ( input logic clk, @@ -101,122 +102,6 @@ module cva5_sim output logic store_queue_empty ); - localparam wb_group_config_t NEXYS_WB_GROUP_CONFIG = '{ - 0 : '{0: ALU_ID, default : NON_WRITEBACK_ID}, - 1 : '{0: LS_ID, default : NON_WRITEBACK_ID}, - 2 : '{0: MUL_ID, 1: DIV_ID, 2: CSR_ID, 3: CUSTOM_ID, default : NON_WRITEBACK_ID}, - default : '{default : NON_WRITEBACK_ID} - }; - - localparam cpu_config_t NEXYS_CONFIG = '{ - //ISA options - INCLUDE_M_MODE : 1, - INCLUDE_S_MODE : 0, - INCLUDE_U_MODE : 0, - INCLUDE_UNIT : '{ - ALU : 1, - LS : 1, - MUL : 1, - DIV : 1, - CSR : 1, - CUSTOM : 0, - BR : 1, - IEC : 1 - }, - INCLUDE_IFENCE : 0, - INCLUDE_AMO : 0, - //CSR constants - CSRS : '{ - MACHINE_IMPLEMENTATION_ID : 0, - CPU_ID : 0, - RESET_VEC : 32'h80000000, - RESET_MTVEC : 32'h80000000, - NON_STANDARD_OPTIONS : '{ - COUNTER_W : 33, - MCYCLE_WRITEABLE : 0, - MINSTR_WRITEABLE : 0, - MTVEC_WRITEABLE : 1, - INCLUDE_MSCRATCH : 0, - INCLUDE_MCAUSE : 1, - INCLUDE_MTVAL : 1 - } - }, - //Memory Options - SQ_DEPTH : 8, - INCLUDE_FORWARDING_TO_STORES : 1, - INCLUDE_ICACHE : 1, - ICACHE_ADDR : '{ - L : 32'h80000000, - H : 32'h87FFFFFF - }, - ICACHE : '{ - LINES : 256, - LINE_W : 8, - WAYS : 2, - USE_EXTERNAL_INVALIDATIONS : 0, - USE_NON_CACHEABLE : 0, - NON_CACHEABLE : '{ - L : 32'h88000000, - H : 32'h8FFFFFFF - } - }, - ITLB : '{ - WAYS : 2, - DEPTH : 64 - }, - INCLUDE_DCACHE : 1, - DCACHE_ADDR : '{ - L : 32'h80000000, - H : 32'h8FFFFFFF - }, - DCACHE : '{ - LINES : 512, - LINE_W : 8, - WAYS : 1, - USE_EXTERNAL_INVALIDATIONS : 0, - USE_NON_CACHEABLE : 1, - NON_CACHEABLE : '{ - L : 32'h88000000, - H : 32'h8FFFFFFF - } - }, - DTLB : '{ - WAYS : 2, - DEPTH : 64 - }, - INCLUDE_ILOCAL_MEM : 0, - ILOCAL_MEM_ADDR : '{ - L : 32'h80000000, - H : 32'h8FFFFFFF - }, - INCLUDE_DLOCAL_MEM : 0, - DLOCAL_MEM_ADDR : '{ - L : 32'h80000000, - H : 32'h8FFFFFFF - }, - INCLUDE_IBUS : 0, - IBUS_ADDR : '{ - L : 32'h00000000, - H : 32'hFFFFFFFF - }, - INCLUDE_PERIPHERAL_BUS : 0, - PERIPHERAL_BUS_ADDR : '{ - L : 32'h88000000, - H : 32'h8FFFFFFF - }, - PERIPHERAL_BUS_TYPE : AXI_BUS, - //Branch Predictor Options - INCLUDE_BRANCH_PREDICTOR : 1, - BP : '{ - WAYS : 2, - ENTRIES : 512, - RAS_ENTRIES : 8 - }, - //Writeback Options - NUM_WB_GROUPS : 3, - WB_GROUP : NEXYS_WB_GROUP_CONFIG - }; - parameter SCRATCH_MEM_KB = 128; parameter MEM_LINES = (SCRATCH_MEM_KB*1024)/4; parameter UART_ADDR = 32'h88001000; diff --git a/examples/nexys/nexys_wrapper.sv b/examples/nexys/nexys_wrapper.sv index 261018b..4ad4e54 100644 --- a/examples/nexys/nexys_wrapper.sv +++ b/examples/nexys/nexys_wrapper.sv @@ -27,6 +27,7 @@ module nexys_wrapper import cva5_config::*; import cva5_types::*; import l2_config_and_types::*; + import nexys_config::*; ( input logic clk, @@ -75,122 +76,6 @@ module nexys_wrapper input logic [5:0] m_axi_bid ); - localparam wb_group_config_t NEXYS_WB_GROUP_CONFIG = '{ - 0 : '{0: ALU_ID, default : NON_WRITEBACK_ID}, - 1 : '{0: LS_ID, default : NON_WRITEBACK_ID}, - 2 : '{0: MUL_ID, 1: DIV_ID, 2: CSR_ID, 3: CUSTOM_ID, default : NON_WRITEBACK_ID}, - default : '{default : NON_WRITEBACK_ID} - }; - - localparam cpu_config_t NEXYS_CONFIG = '{ - //ISA options - INCLUDE_M_MODE : 1, - INCLUDE_S_MODE : 0, - INCLUDE_U_MODE : 0, - INCLUDE_UNIT : '{ - ALU : 1, - LS : 1, - MUL : 1, - DIV : 1, - CSR : 1, - CUSTOM : 0, - BR : 1, - IEC : 1 - }, - INCLUDE_IFENCE : 0, - INCLUDE_AMO : 0, - //CSR constants - CSRS : '{ - MACHINE_IMPLEMENTATION_ID : 0, - CPU_ID : 0, - RESET_VEC : 32'h80000000, - RESET_MTVEC : 32'h80000000, - NON_STANDARD_OPTIONS : '{ - COUNTER_W : 33, - MCYCLE_WRITEABLE : 0, - MINSTR_WRITEABLE : 0, - MTVEC_WRITEABLE : 1, - INCLUDE_MSCRATCH : 0, - INCLUDE_MCAUSE : 1, - INCLUDE_MTVAL : 1 - } - }, - //Memory Options - SQ_DEPTH : 8, - INCLUDE_FORWARDING_TO_STORES : 1, - INCLUDE_ICACHE : 1, - ICACHE_ADDR : '{ - L : 32'h80000000, - H : 32'h87FFFFFF - }, - ICACHE : '{ - LINES : 256, - LINE_W : 8, - WAYS : 2, - USE_EXTERNAL_INVALIDATIONS : 0, - USE_NON_CACHEABLE : 0, - NON_CACHEABLE : '{ - L : 32'h88000000, - H : 32'h8FFFFFFF - } - }, - ITLB : '{ - WAYS : 2, - DEPTH : 64 - }, - INCLUDE_DCACHE : 1, - DCACHE_ADDR : '{ - L : 32'h80000000, - H : 32'h8FFFFFFF - }, - DCACHE : '{ - LINES : 512, - LINE_W : 8, - WAYS : 1, - USE_EXTERNAL_INVALIDATIONS : 0, - USE_NON_CACHEABLE : 1, - NON_CACHEABLE : '{ - L : 32'h88000000, - H : 32'h8FFFFFFF - } - }, - DTLB : '{ - WAYS : 2, - DEPTH : 64 - }, - INCLUDE_ILOCAL_MEM : 0, - ILOCAL_MEM_ADDR : '{ - L : 32'h80000000, - H : 32'h8FFFFFFF - }, - INCLUDE_DLOCAL_MEM : 0, - DLOCAL_MEM_ADDR : '{ - L : 32'h80000000, - H : 32'h8FFFFFFF - }, - INCLUDE_IBUS : 0, - IBUS_ADDR : '{ - L : 32'h00000000, - H : 32'hFFFFFFFF - }, - INCLUDE_PERIPHERAL_BUS : 0, - PERIPHERAL_BUS_ADDR : '{ - L : 32'h00000000, - H : 32'hFFFFFFFF - }, - PERIPHERAL_BUS_TYPE : AXI_BUS, - //Branch Predictor Options - INCLUDE_BRANCH_PREDICTOR : 1, - BP : '{ - WAYS : 2, - ENTRIES : 512, - RAS_ENTRIES : 8 - }, - //Writeback Options - NUM_WB_GROUPS : 3, - WB_GROUP : NEXYS_WB_GROUP_CONFIG - }; - //Unused outputs local_memory_interface instruction_bram (); local_memory_interface data_bram (); diff --git a/examples/nexys/scripts/cva5-ip-core-base.tcl b/examples/nexys/scripts/cva5-ip-core-base.tcl index e810b9f..0d6266e 100644 --- a/examples/nexys/scripts/cva5-ip-core-base.tcl +++ b/examples/nexys/scripts/cva5-ip-core-base.tcl @@ -25,6 +25,7 @@ if {[string equal [get_filesets -quiet sources_1] ""]} { } #import sources needed for blackbox packaging +import_files -norecurse $sources_dir/examples/nexys/nexys_config.sv import_files -norecurse $sources_dir/examples/nexys/nexys_wrapper.sv import_files -norecurse $sources_dir/l2_arbiter/l2_external_interfaces.sv import_files -norecurse $sources_dir/local_memory/local_memory_interface.sv diff --git a/tools/cva5.mak b/tools/cva5.mak index 61a34a7..97685f4 100644 --- a/tools/cva5.mak +++ b/tools/cva5.mak @@ -93,7 +93,7 @@ $(CVA5_SIM): $(CVA5_HW_SRCS) $(CVA5_SIM_SRCS) -o cva5-sim \ $(VERILATOR_LINT_IGNORE) $(VERILATOR_CFLAGS) \ $(CVA5_SIM_SRCS) \ - $(CVA5_HW_SRCS) $(CVA5_DIR)/test_benches/sim_stats.sv $(CVA5_DIR)/examples/nexys/l1_to_axi.sv $(CVA5_DIR)/examples/nexys/nexys_sim.sv --top-module cva5_sim + $(CVA5_HW_SRCS) $(CVA5_DIR)/test_benches/sim_stats.sv $(CVA5_DIR)/examples/nexys/nexys_config.sv $(CVA5_DIR)/examples/nexys/l1_to_axi.sv $(CVA5_DIR)/examples/nexys/nexys_sim.sv --top-module cva5_sim $(MAKE) -C $(CVA5_SIM_DIR) -f Vcva5_sim.mk .PHONY: clean-cva5-sim From f11b9582e80b8895e7db31cd2388682803c01561 Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Mon, 1 May 2023 16:42:41 -0400 Subject: [PATCH 15/16] Autogenerate decode_wb_group from config data Signed-off-by: Eric Matthews --- core/decode_and_issue.sv | 38 ++++++++++++-------- core/types_and_interfaces/cva5_config.sv | 46 +++++++++++++++--------- 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/core/decode_and_issue.sv b/core/decode_and_issue.sv index f5c9a77..e3be1e5 100755 --- a/core/decode_and_issue.sv +++ b/core/decode_and_issue.sv @@ -79,8 +79,7 @@ module decode_and_issue common_instruction_t decode_instruction;//rs1_addr, rs2_addr, fn3, fn7, rd_addr, upper/lower opcode - logic uses_rs [REGFILE_READ_PORTS]; - logic uses_rd; + logic decode_uses_rs [REGFILE_READ_PORTS]; rs_addr_t decode_rs_addr [REGFILE_READ_PORTS]; logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] decode_wb_group; @@ -116,36 +115,44 @@ module decode_and_issue //////////////////////////////////////////////////// //Register File Support always_comb begin - uses_rd = |unit_uses_rd; - uses_rs = '{default: 0}; + decode_uses_rd = |unit_uses_rd; + decode_uses_rs = '{default: 0}; for (int i = 0; i < MAX_NUM_UNITS; i++) for (int j = 0; j < REGFILE_READ_PORTS; j++) - uses_rs[j] |= unit_uses_rs[i][j]; + decode_uses_rs[j] |= unit_uses_rs[i][j]; end //////////////////////////////////////////////////// - //Renamer Support + //WB Group Determination + localparam units_t [MAX_NUM_UNITS-1:0] WB_UNITS_TYPE_REP = get_wb_units_type_representation(CONFIG.WB_GROUP); + logic [CONFIG.NUM_WB_GROUPS-1:0] uses_wb_group; + always_comb begin - decode_wb_group = $clog2(CONFIG.NUM_WB_GROUPS)'(CONFIG.NUM_WB_GROUPS - 1); - if (unit_needed[ALU_ID]) - decode_wb_group = 0; - else if (unit_needed[LS_ID] ) - decode_wb_group = 1; + for (int i = 0; i < CONFIG.NUM_WB_GROUPS; i++) + uses_wb_group[i] = |(unit_needed & WB_UNITS_TYPE_REP[i]); end + one_hot_to_integer #(.C_WIDTH(CONFIG.NUM_WB_GROUPS)) + wb_group_one_hot_block ( + .one_hot (uses_wb_group), + .int_out (decode_wb_group) + ); + + //////////////////////////////////////////////////// + //Renamer Support assign renamer.rd_addr = decode_instruction.rd_addr; assign renamer.rs_addr = decode_rs_addr; - assign renamer.uses_rd = uses_rd; + assign renamer.uses_rd = decode_uses_rd; assign renamer.rd_wb_group = decode_wb_group; assign renamer.id = decode.id; //////////////////////////////////////////////////// //Decode ID Support - assign decode_uses_rd = uses_rd; assign decode_rd_addr = decode_instruction.rd_addr; assign decode_phys_rd_addr = renamer.phys_rd_addr; assign decode_phys_rs_addr = renamer.phys_rs_addr; assign decode_rs_wb_group = renamer.rs_wb_group; + //////////////////////////////////////////////////// //Issue always_ff @(posedge clk) begin @@ -164,8 +171,8 @@ module decode_and_issue issue.is_multicycle <= ~unit_needed[ALU_ID]; issue.id <= decode.id; issue.exception_unit <= decode_exception_unit; - issue_uses_rs <= uses_rs; - issue.uses_rd <= uses_rd; + issue_uses_rs <= decode_uses_rs; + issue.uses_rd <= decode_uses_rd; end end @@ -209,6 +216,7 @@ module decode_and_issue assign rf.single_cycle_or_flush = (instruction_issued_with_rd & |issue.rd_addr & ~issue.is_multicycle) | (issue.stage_valid & issue.uses_rd & |issue.rd_addr & gc.fetch_flush); + //////////////////////////////////////////////////// //Constant ALU: // provides LUI, AUIPC, JAL, JALR results for ALU // provides PC+4 for BRANCH unit and ifence in GC unit diff --git a/core/types_and_interfaces/cva5_config.sv b/core/types_and_interfaces/cva5_config.sv index 1e5a266..7831fd0 100755 --- a/core/types_and_interfaces/cva5_config.sv +++ b/core/types_and_interfaces/cva5_config.sv @@ -120,11 +120,10 @@ package cva5_config; bit ALU; } units_t; - typedef enum bit [$clog2(MAX_NUM_UNITS)-1:0] { IEC_ID = 7, BR_ID = 6, - //End of Write-Back Units + //End of Write-Back Units (insert new writeback units here) CUSTOM_ID = 5, CSR_ID = 4, DIV_ID = 3, @@ -134,8 +133,30 @@ package cva5_config; } unit_id_enum_t; localparam unit_id_enum_t NON_WRITEBACK_ID = BR_ID; + //WB Group config + // First index is write-back port + // Second index is position within the write-back port (Priority selection, with highest priority for index 0) + // See EXAMPLE_WB_GROUP_CONFIG below for an example of how to specify the configuration typedef unit_id_enum_t [MAX_NUM_UNITS-1:0][MAX_NUM_UNITS-1:0] wb_group_config_t; + //Convenience function for determining how many writeback units are in each writeback group + function int unsigned get_num_wb_units (input unit_id_enum_t [MAX_NUM_UNITS-1:0] ids); + get_num_wb_units = 0; + for (int i = 0; i < MAX_NUM_UNITS; i++) + if (ids[i] != NON_WRITEBACK_ID) + get_num_wb_units++; + endfunction + + //Convenience function for turning the enum-based WB grouping into the units_t bit-vector representation + //used in decode stage to determine the writeback group for the current instruction + function units_t [MAX_NUM_UNITS-1:0] get_wb_units_type_representation(input wb_group_config_t ids); + get_wb_units_type_representation = '{default : '0}; + for (int i = 0; i < MAX_NUM_UNITS; i++) + for (int j = 0; j < MAX_NUM_UNITS; j++) + if (ids[i][j] != NON_WRITEBACK_ID) + get_wb_units_type_representation[i][ids[i][j]] = 1; + endfunction + typedef struct packed { //ISA options bit INCLUDE_M_MODE; @@ -192,10 +213,13 @@ package cva5_config; }; endfunction - - //WB config - //ALU requires its own WB port - //LS unit must be the first unit on its writeback port (LS unit does not use ack signal for timing considerations) + //////////////////////////////////////////////////// + //Example Config + // ALU requires its own WB port + // LS unit must be the first unit on its writeback port (LS unit does not use ack signal for timing considerations) + // Index in group is the priority order (highest priority for index zero) + // For optimal resource usage, there should be no holes in the write-back unit ordering + // (i.e. if a unit is often not included, either remove from the WB config or place at the end of a writeback group) localparam wb_group_config_t EXAMPLE_WB_GROUP_CONFIG = '{ 0 : '{0: ALU_ID, default : NON_WRITEBACK_ID}, 1 : '{0: LS_ID, default : NON_WRITEBACK_ID}, @@ -203,14 +227,6 @@ package cva5_config; default : '{default : NON_WRITEBACK_ID} }; - //Convenience function for determining how many writeback units are in each writeback group - function int unsigned get_num_wb_units (input unit_id_enum_t [MAX_NUM_UNITS-1:0] ids); - get_num_wb_units = 0; - for (int i = 0; i < MAX_NUM_UNITS; i++) - if (ids[i] != NON_WRITEBACK_ID) - get_num_wb_units++; - endfunction - localparam cpu_config_t EXAMPLE_CONFIG = '{ //ISA options INCLUDE_M_MODE : 1, @@ -323,8 +339,6 @@ package cva5_config; WB_GROUP : EXAMPLE_WB_GROUP_CONFIG }; - - //////////////////////////////////////////////////// //Bus Options parameter C_M_AXI_ADDR_WIDTH = 32; //Kept as parameter, due to localparam failing with scripted IP packaging From 876984224980ed2e7eb43c26b2afcf07520ffaeb Mon Sep 17 00:00:00 2001 From: Eric Matthews Date: Tue, 2 May 2023 14:58:26 -0400 Subject: [PATCH 16/16] Add dcache cbo instruction support Signed-off-by: Eric Matthews --- .../execution_units/load_store_unit/dcache.sv | 9 ++- .../load_store_unit/dcache_tag_banks.sv | 5 +- .../load_store_unit/load_store_queue.sv | 4 +- .../load_store_unit/load_store_unit.sv | 79 ++++++++++--------- .../load_store_unit/store_queue.sv | 2 + core/types_and_interfaces/cva5_config.sv | 4 +- core/types_and_interfaces/cva5_types.sv | 3 + core/types_and_interfaces/opcodes.sv | 5 ++ examples/nexys/nexys_config.sv | 2 + examples/nexys/nexys_sim.sv | 2 +- test_benches/verilator/cva5_sim.sv | 2 +- 11 files changed, 70 insertions(+), 47 deletions(-) diff --git a/core/execution_units/load_store_unit/dcache.sv b/core/execution_units/load_store_unit/dcache.sv index 8bb93e3..b28b45c 100644 --- a/core/execution_units/load_store_unit/dcache.sv +++ b/core/execution_units/load_store_unit/dcache.sv @@ -68,6 +68,7 @@ module dcache logic [31:0] addr; logic [3:0] be; logic [31:0] data; + logic cache_op; logic uncacheable; } store_stage2_t; store_stage2_t stage2_store; @@ -167,8 +168,8 @@ module dcache end always_comb begin - store_state_next[STORE_IDLE] = (store_state[STORE_IDLE] & ~store_request) | (store_l1_arb_ack & ~store_request); - store_state_next[STORE_L1_REQUEST] = (store_state[STORE_L1_REQUEST] & ~store_l1_arb_ack) | store_request; + store_state_next[STORE_IDLE] = (store_state[STORE_IDLE] & (~store_request | (store_request & ls_store.cache_op))) | (store_l1_arb_ack & ~store_request); + store_state_next[STORE_L1_REQUEST] = (store_state[STORE_L1_REQUEST] & ~store_l1_arb_ack) | (store_request & ~ls_store.cache_op); end assign store_ready = (store_state[STORE_IDLE] | store_l1_arb_ack) & (load_state[LOAD_IDLE] | load_hit); @@ -180,6 +181,7 @@ module dcache stage2_store.uncacheable <= uncacheable_store; stage2_store.be <= ls_store.be; stage2_store.data <= ls_store.data_in; + stage2_store.cache_op <= ls_store.cache_op; end end @@ -189,7 +191,7 @@ module dcache fifo_interface #(.DATA_TYPE(logic)) request_order(); assign request_order.data_in = load_request; - assign request_order.push = load_request | store_request; + assign request_order.push = load_request | (store_request & ~ls_store.cache_op); assign request_order.potential_push = request_order.push; assign request_order.pop = l1_request.ack | load_hit; @@ -241,6 +243,7 @@ module dcache .store_addr (ls_store.addr), .store_addr_r (stage2_store.addr), .store_req (store_request), + .cache_op_req (ls_store.cache_op), .load_tag_hit (load_hit), .load_tag_hit_way (load_tag_hit_way), .store_tag_hit (store_hit), diff --git a/core/execution_units/load_store_unit/dcache_tag_banks.sv b/core/execution_units/load_store_unit/dcache_tag_banks.sv index 572db71..2a8b764 100644 --- a/core/execution_units/load_store_unit/dcache_tag_banks.sv +++ b/core/execution_units/load_store_unit/dcache_tag_banks.sv @@ -48,6 +48,7 @@ module dcache_tag_banks input logic[31:0] store_addr, input logic[31:0] store_addr_r, input logic store_req, + input logic cache_op_req, output logic load_tag_hit, output logic store_tag_hit, @@ -76,7 +77,7 @@ module dcache_tag_banks //////////////////////////////////////////////////// //Implementation always_ff @ (posedge clk) load_req_r <= load_req; - always_ff @ (posedge clk) store_req_r <= store_req; + always_ff @ (posedge clk) store_req_r <= store_req & ~cache_op_req; assign external_inv = extern_inv & CONFIG.DCACHE.USE_EXTERNAL_INVALIDATIONS; @@ -93,7 +94,7 @@ module dcache_tag_banks dual_port_bram #(.WIDTH($bits(dtag_entry_t)), .LINES(CONFIG.DCACHE.LINES)) dtag_bank ( .clk (clk), .en_a (store_req | (miss_req & miss_way[i]) | external_inv), - .wen_a ((miss_req & miss_way[i]) | external_inv), + .wen_a ((miss_req & miss_way[i]) | external_inv | (store_req & cache_op_req)), .addr_a (porta_addr), .data_in_a (new_tagline), .data_out_a (tag_line_a[i]), diff --git a/core/execution_units/load_store_unit/load_store_queue.sv b/core/execution_units/load_store_unit/load_store_queue.sv index 484772f..f083be4 100644 --- a/core/execution_units/load_store_unit/load_store_queue.sv +++ b/core/execution_units/load_store_unit/load_store_queue.sv @@ -101,7 +101,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit }; //////////////////////////////////////////////////// //Store Queue - assign sq.push = lsq.push & lsq.data_in.store; + assign sq.push = lsq.push & (lsq.data_in.store | lsq.data_in.cache_op); assign sq.pop = lsq.store_pop; assign sq.data_in = lsq.data_in; @@ -132,6 +132,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit addr : lq.data_out.addr, load : 1, store : 0, + cache_op : 0, be : 'x, fn3 : lq.data_out.fn3, data_in : 'x, @@ -142,6 +143,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit addr : sq.data_out.addr, load : 0, store : 1, + cache_op : sq.data_out.cache_op, be : sq.data_out.be, fn3 : 'x, data_in : sq.data_out.data, diff --git a/core/execution_units/load_store_unit/load_store_unit.sv b/core/execution_units/load_store_unit/load_store_unit.sv index 93ad508..91eeea1 100755 --- a/core/execution_units/load_store_unit/load_store_unit.sv +++ b/core/execution_units/load_store_unit/load_store_unit.sv @@ -153,42 +153,44 @@ module load_store_unit //Decode assign instruction = decode_stage.instruction; - assign unit_needed = decode_stage.instruction inside {LB, LH, LW, LBU, LHU, SB, SH, SW, FENCE}; + assign unit_needed = decode_stage.instruction inside {LB, LH, LW, LBU, LHU, SB, SH, SW, FENCE} | (CONFIG.INCLUDE_CBO & decode_stage.instruction inside {CBO_INVAL, CBO_CLEAN, CBO_FLUSH}); always_comb begin uses_rs = '0; - uses_rs[RS1] = decode_stage.instruction inside {LB, LH, LW, LBU, LHU, SB, SH, SW}; + uses_rs[RS1] = decode_stage.instruction inside {LB, LH, LW, LBU, LHU, SB, SH, SW} | (CONFIG.INCLUDE_CBO & decode_stage.instruction inside {CBO_INVAL, CBO_CLEAN, CBO_FLUSH}); uses_rs[RS2] = CONFIG.INCLUDE_FORWARDING_TO_STORES ? 0 : decode_stage.instruction inside {SB, SH, SW}; uses_rd = decode_stage.instruction inside {LB, LH, LW, LBU, LHU}; end - amo_details_t amo; - amo_details_t amo_r; - logic is_load; - logic is_store; - logic is_load_r; - logic is_store_r; - logic is_fence_r; - logic [2:0] fn3_r; - logic [11:0] ls_offset_r; + //////////////////////////////////////////////////// + //LS specific decode support + typedef struct packed{ + logic is_load; + logic is_store; + logic is_fence; + logic is_cbo; + logic [11:0] offset; + } ls_attr_t; + ls_attr_t decode_attr; + ls_attr_t issue_attr; - assign amo.is_amo = CONFIG.INCLUDE_AMO & (instruction.upper_opcode == AMO_T); - assign amo.op = CONFIG.INCLUDE_AMO ? decode_stage.instruction[31:27] : '0; - assign amo.is_lr = CONFIG.INCLUDE_AMO & (amo.op == AMO_LR_FN5); - assign amo.is_sc = CONFIG.INCLUDE_AMO & (amo.op == AMO_SC_FN5); + logic [11:0] load_offset; + logic [11:0] store_offset; + assign load_offset = decode_stage.instruction[31:20]; + assign store_offset = {decode_stage.instruction[31:25], decode_stage.instruction[11:7]}; - assign is_load = (instruction.upper_opcode inside {LOAD_T, AMO_T}) & !(amo.is_amo & amo.is_sc); //LR and AMO_ops perform a read operation as well - assign is_store = (instruction.upper_opcode == STORE_T) | (amo.is_amo & amo.is_sc);//Used for LS unit and for ID tracking - assign decode_is_store = is_store; + + assign decode_attr = '{ + is_load : decode_stage.instruction inside {LB, LH, LW, LBU, LHU}, + is_store : decode_stage.instruction inside {SB, SH, SW}, + is_fence : decode_stage.instruction inside {FENCE}, + is_cbo : CONFIG.INCLUDE_CBO & decode_stage.instruction inside {CBO_INVAL, CBO_CLEAN, CBO_FLUSH}, + offset : decode_stage.instruction[5] ? store_offset : ((CONFIG.INCLUDE_CBO & decode_stage.instruction[2]) ? '0 :load_offset) + }; + assign decode_is_store = decode_attr.is_store | decode_attr.is_cbo; always_ff @(posedge clk) begin - if (issue_stage_ready) begin - ls_offset_r <= decode_stage.instruction[5] ? {decode_stage.instruction[31:25], decode_stage.instruction[11:7]} : decode_stage.instruction[31:20]; - is_load_r <= is_load; - is_store_r <= is_store; - is_fence_r <= (instruction.upper_opcode == FENCE_T); - amo_r <= amo; - fn3_r <= amo.is_amo ? LS_W_fn3 : instruction.fn3; - end + if (issue_stage_ready) + issue_attr <= decode_attr; end typedef struct packed{ @@ -215,14 +217,14 @@ module load_store_unit generate if (CONFIG.INCLUDE_M_MODE) begin : gen_ls_exceptions logic new_exception; always_comb begin - case(fn3_r) + case(issue_stage.fn3) LS_H_fn3, L_HU_fn3 : unaligned_addr = virtual_address[0]; LS_W_fn3 : unaligned_addr = |virtual_address[1:0]; default : unaligned_addr = 0; endcase end - assign new_exception = unaligned_addr & issue.new_request & ~is_fence_r; + assign new_exception = unaligned_addr & issue.new_request & ~issue_attr.is_fence; always_ff @(posedge clk) begin if (rst) exception.valid <= 0; @@ -232,7 +234,7 @@ module load_store_unit always_ff @(posedge clk) begin if (new_exception & ~exception.valid) begin - exception.code <= is_store_r ? STORE_AMO_ADDR_MISSALIGNED : LOAD_ADDR_MISSALIGNED; + exception.code <= issue_attr.is_store ? STORE_AMO_ADDR_MISSALIGNED : LOAD_ADDR_MISSALIGNED; exception.tval <= virtual_address; exception.id <= issue.id; end @@ -256,12 +258,12 @@ module load_store_unit //////////////////////////////////////////////////// //TLB interface - assign virtual_address = rf[RS1] + 32'(signed'(ls_offset_r)); + assign virtual_address = rf[RS1] + 32'(signed'(issue_attr.offset)); assign tlb.virtual_address = virtual_address; assign tlb.new_request = tlb_on & issue.new_request; assign tlb.execute = 0; - assign tlb.rnw = is_load_r & ~is_store_r; + assign tlb.rnw = issue_attr.is_load & ~issue_attr.is_store; //////////////////////////////////////////////////// //Byte enable generation @@ -271,7 +273,7 @@ module load_store_unit // SB: specific byte always_comb begin be = 0; - case(fn3_r[1:0]) + case(issue_stage.fn3[1:0]) LS_B_fn3[1:0] : be[virtual_address[1:0]] = 1; LS_H_fn3[1:0] : begin be[virtual_address[1:0]] = 1; @@ -285,17 +287,18 @@ module load_store_unit //Load Store Queue assign lsq.data_in = '{ addr : tlb_on ? tlb.physical_address : virtual_address, - fn3 : fn3_r, + fn3 : issue_stage.fn3, be : be, data : rf[RS2], - load : is_load_r, - store : is_store_r, + load : issue_attr.is_load, + store : issue_attr.is_store, + cache_op : issue_attr.is_cbo, id : issue.id, id_needed : rd_attributes.id }; assign lsq.potential_push = issue.possible_issue; - assign lsq.push = issue.new_request & ~unaligned_addr & (~tlb_on | tlb.done) & ~is_fence_r; + assign lsq.push = issue.new_request & ~unaligned_addr & (~tlb_on | tlb.done) & ~issue_attr.is_fence; load_store_queue # (.CONFIG(CONFIG)) lsq_block ( .clk (clk), @@ -341,7 +344,7 @@ module load_store_unit if (rst) fence_hold <= 0; else - fence_hold <= (fence_hold & ~load_store_status.idle) | (issue.new_request & is_fence_r); + fence_hold <= (fence_hold & ~load_store_status.idle) | (issue.new_request & issue_attr.is_fence); end //////////////////////////////////////////////////// @@ -463,7 +466,7 @@ module load_store_unit .sc_complete (sc_complete), .sc_success (sc_success), .clear_reservation (clear_reservation), - .amo (amo_r), + .amo (), .uncacheable_load (uncacheable_load), .uncacheable_store (uncacheable_store), .is_load (sel_load), diff --git a/core/execution_units/load_store_unit/store_queue.sv b/core/execution_units/load_store_unit/store_queue.sv index 35821fd..cb6190b 100644 --- a/core/execution_units/load_store_unit/store_queue.sv +++ b/core/execution_units/load_store_unit/store_queue.sv @@ -125,6 +125,7 @@ module store_queue .new_ram_data('{ addr : sq.data_in.addr, be : sq.data_in.be, + cache_op : sq.data_in.cache_op, data : '0 }), .ram_data_out(output_entry) @@ -253,6 +254,7 @@ module store_queue assign sq.data_out = '{ addr : output_entry_r.addr, be : output_entry_r.be, + cache_op : output_entry_r.cache_op, data : sq_data_out }; diff --git a/core/types_and_interfaces/cva5_config.sv b/core/types_and_interfaces/cva5_config.sv index 7831fd0..c4e3d02 100755 --- a/core/types_and_interfaces/cva5_config.sv +++ b/core/types_and_interfaces/cva5_config.sv @@ -165,6 +165,7 @@ package cva5_config; bit INCLUDE_IFENCE; //local mem operations only bit INCLUDE_AMO; + bit INCLUDE_CBO; //Data cache invalidation operations //Units units_t INCLUDE_UNIT; @@ -246,7 +247,8 @@ package cva5_config; INCLUDE_IFENCE : 1, INCLUDE_AMO : 0, - + INCLUDE_CBO : 0, + //CSR constants CSRS : '{ MACHINE_IMPLEMENTATION_ID : 0, diff --git a/core/types_and_interfaces/cva5_types.sv b/core/types_and_interfaces/cva5_types.sv index 4d5638f..56bdd99 100755 --- a/core/types_and_interfaces/cva5_types.sv +++ b/core/types_and_interfaces/cva5_types.sv @@ -107,6 +107,7 @@ package cva5_types; logic [31:0] addr; logic load; logic store; + logic cache_op; logic [3:0] be; logic [2:0] fn3; logic [31:0] data; @@ -117,6 +118,7 @@ package cva5_types; typedef struct packed { logic [31:0] addr; logic [3:0] be; + logic cache_op; logic [31:0] data; } sq_entry_t; @@ -141,6 +143,7 @@ package cva5_types; logic [31:0] addr; logic load; logic store; + logic cache_op; logic [3:0] be; logic [2:0] fn3; logic [31:0] data_in; diff --git a/core/types_and_interfaces/opcodes.sv b/core/types_and_interfaces/opcodes.sv index 8a0d3ad..a417d0b 100644 --- a/core/types_and_interfaces/opcodes.sv +++ b/core/types_and_interfaces/opcodes.sv @@ -101,6 +101,11 @@ package opcodes; localparam [31:0] SFENCE_VMA = 32'b0001001??????????000000001110011; localparam [31:0] WFI = 32'b00010000010100000000000001110011; + //Cache + localparam [31:0] CBO_INVAL = 32'b000000000000?????010000000001111; + localparam [31:0] CBO_CLEAN = 32'b000000000001?????010000000001111; + localparam [31:0] CBO_FLUSH = 32'b000000000010?????010000000001111; + localparam [31:0] CUSTOM = 32'b?????????????????????????1111011; diff --git a/examples/nexys/nexys_config.sv b/examples/nexys/nexys_config.sv index 8624fd7..b147b5f 100644 --- a/examples/nexys/nexys_config.sv +++ b/examples/nexys/nexys_config.sv @@ -49,6 +49,8 @@ package nexys_config; }, INCLUDE_IFENCE : 0, INCLUDE_AMO : 0, + INCLUDE_CBO : 0, + //CSR constants CSRS : '{ MACHINE_IMPLEMENTATION_ID : 0, diff --git a/examples/nexys/nexys_sim.sv b/examples/nexys/nexys_sim.sv index c11b03c..eceb638 100644 --- a/examples/nexys/nexys_sim.sv +++ b/examples/nexys/nexys_sim.sv @@ -309,7 +309,7 @@ module cva5_sim //Misc Issue stats stats[ISSUE_OPERAND_STALL_FOR_BRANCH_STAT] = stats[ISSUE_OPERANDS_NOT_READY_STAT] & `ISSUE_P.unit_needed_issue_stage[BR_ID]; - stats[ISSUE_STORE_WITH_FORWARDED_DATA_STAT] = `ISSUE_P.issue_to[LS_ID] & `LS_P.is_store_r & `LS_P.rs2_inuse; + stats[ISSUE_STORE_WITH_FORWARDED_DATA_STAT] = `ISSUE_P.issue_to[LS_ID] & `LS_P.issue_attr.is_store & `LS_P.rs2_inuse; stats[ISSUE_DIVIDER_RESULT_REUSE_STAT] = `ISSUE_P.issue_to[DIV_ID] & `DIV_P.div_op_reuse; //Issue Stall Source diff --git a/test_benches/verilator/cva5_sim.sv b/test_benches/verilator/cva5_sim.sv index a51dbbe..ff9383f 100644 --- a/test_benches/verilator/cva5_sim.sv +++ b/test_benches/verilator/cva5_sim.sv @@ -545,7 +545,7 @@ module cva5_sim //Misc Issue stats stats[ISSUE_OPERAND_STALL_FOR_BRANCH_STAT] = stats[ISSUE_OPERANDS_NOT_READY_STAT] & `ISSUE_P.unit_needed_issue_stage[BR_ID]; - stats[ISSUE_STORE_WITH_FORWARDED_DATA_STAT] = `ISSUE_P.issue_to[LS_ID] & `LS_P.is_store_r & `LS_P.rs2_inuse; + stats[ISSUE_STORE_WITH_FORWARDED_DATA_STAT] = `ISSUE_P.issue_to[LS_ID] & `LS_P.issue_attr.is_store & `LS_P.rs2_inuse; stats[ISSUE_DIVIDER_RESULT_REUSE_STAT] = `ISSUE_P.issue_to[DIV_ID] & `DIV_P.div_op_reuse; //Issue Stall Source