// Copyright 2021 ETH Zurich and University of Bologna. // Solderpad Hardware License, Version 0.51, see LICENSE for details. // SPDX-License-Identifier: SHL-0.51 module mempool_tile import mempool_pkg::*; import cf_math_pkg::idx_width; #( // TCDM parameter addr_t TCDMBaseAddr = 32'b0, // Boot address parameter logic [31:0] BootAddr = 32'h0000_1000, // Dependent parameters. DO NOT CHANGE. parameter int unsigned NumCaches = NumCoresPerTile / NumCoresPerCache ) ( // Clock and reset input logic clk_i, input logic rst_ni, // Scan chain input logic scan_enable_i, input logic scan_data_i, output logic scan_data_o, // Tile ID input logic [idx_width(NumTiles)-1:0] tile_id_i, // TCDM Master interfaces output tcdm_master_req_t [NumGroups-1:0] tcdm_master_req_o, output logic [NumGroups-1:0] tcdm_master_req_valid_o, input logic [NumGroups-1:0] tcdm_master_req_ready_i, input tcdm_master_resp_t [NumGroups-1:0] tcdm_master_resp_i, input logic [NumGroups-1:0] tcdm_master_resp_valid_i, output logic [NumGroups-1:0] tcdm_master_resp_ready_o, // TCDM slave interfaces input tcdm_slave_req_t [NumGroups-1:0] tcdm_slave_req_i, input logic [NumGroups-1:0] tcdm_slave_req_valid_i, output logic [NumGroups-1:0] tcdm_slave_req_ready_o, output tcdm_slave_resp_t [NumGroups-1:0] tcdm_slave_resp_o, output logic [NumGroups-1:0] tcdm_slave_resp_valid_o, input logic [NumGroups-1:0] tcdm_slave_resp_ready_i, // AXI Interface output axi_tile_req_t axi_mst_req_o, input axi_tile_resp_t axi_mst_resp_i, // Wake up interface input logic [NumCoresPerTile-1:0] wake_up_i ); /**************** * Includes * ****************/ //the below line includes register definitions --> not sure why this is required, why do we have such a file ? `include "common_cells/registers.svh" /***************** * Definitions * *****************/ import snitch_pkg::dreq_t; import snitch_pkg::dresp_t; typedef logic [idx_width(NumGroups)-1:0] group_id_t; // TCDM Memory Region localparam addr_t TCDMSize = NumBanks * TCDMSizePerBank; localparam addr_t TCDMMask = ~(TCDMSize - 1); // Local interconnect address width typedef logic [idx_width(NumCoresPerTile + NumGroups)-1:0] local_req_interco_addr_t; // Group ID logic [idx_width(NumGroups)-1:0] group_id; if (NumGroups != 1) begin: gen_group_id assign group_id = tile_id_i[$clog2(NumTiles)-1 -: $clog2(NumGroups)]; end else begin: gen_group_id assign group_id = '0; end: gen_group_id /*********** * Cores * ***********/ // Instruction interfaces addr_t [NumCaches-1:0][NumCoresPerCache-1:0] snitch_inst_addr; data_t [NumCaches-1:0][NumCoresPerCache-1:0] snitch_inst_data; logic [NumCaches-1:0][NumCoresPerCache-1:0] snitch_inst_valid; logic [NumCaches-1:0][NumCoresPerCache-1:0] snitch_inst_ready; // Data interfaces addr_t [NumCoresPerTile-1:0] snitch_data_qaddr; logic [NumCoresPerTile-1:0] snitch_data_qwrite; amo_t [NumCoresPerTile-1:0] snitch_data_qamo; data_t [NumCoresPerTile-1:0] snitch_data_qdata; strb_t [NumCoresPerTile-1:0] snitch_data_qstrb; meta_id_t [NumCoresPerTile-1:0] snitch_data_qid; logic [NumCoresPerTile-1:0] snitch_data_qvalid; logic [NumCoresPerTile-1:0] snitch_data_qready; data_t [NumCoresPerTile-1:0] snitch_data_pdata; logic [NumCoresPerTile-1:0] snitch_data_perror; meta_id_t [NumCoresPerTile-1:0] snitch_data_pid; logic [NumCoresPerTile-1:0] snitch_data_pvalid; logic [NumCoresPerTile-1:0] snitch_data_pready; for (genvar c = 0; unsigned'(c) < NumCoresPerTile; c++) begin: gen_cores logic [31:0] hart_id; assign hart_id = {unsigned'(tile_id_i), c[idx_width(NumCoresPerTile)-1:0]}; if (!TrafficGeneration) begin: gen_mempool_cc mempool_cc #( .BootAddr (BootAddr) ) riscv_core ( .clk_i (clk_i ), .rst_i (!rst_ni ), .hart_id_i (hart_id ), // IMEM Port .inst_addr_o (snitch_inst_addr[c/NumCoresPerCache][c%NumCoresPerCache] ), .inst_data_i (snitch_inst_data[c/NumCoresPerCache][c%NumCoresPerCache] ), .inst_valid_o (snitch_inst_valid[c/NumCoresPerCache][c%NumCoresPerCache]), .inst_ready_i (snitch_inst_ready[c/NumCoresPerCache][c%NumCoresPerCache]), // Data Ports .data_qaddr_o (snitch_data_qaddr[c] ), .data_qwrite_o (snitch_data_qwrite[c] ), .data_qamo_o (snitch_data_qamo[c] ), .data_qdata_o (snitch_data_qdata[c] ), .data_qstrb_o (snitch_data_qstrb[c] ), .data_qid_o (snitch_data_qid[c] ), .data_qvalid_o (snitch_data_qvalid[c] ), .data_qready_i (snitch_data_qready[c] ), .data_pdata_i (snitch_data_pdata[c] ), .data_perror_i (snitch_data_perror[c] ), .data_pid_i (snitch_data_pid[c] ), .data_pvalid_i (snitch_data_pvalid[c] ), .data_pready_o (snitch_data_pready[c] ), .wake_up_sync_i(wake_up_i[c] ), // Core Events .core_events_o (/* Unused */ ) ); end else begin assign snitch_data_qaddr[c] = '0; assign snitch_data_qwrite[c] = '0; assign snitch_data_qamo[c] = '0; assign snitch_data_qdata[c] = '0; assign snitch_data_qstrb[c] = '0; assign snitch_data_qid[c] = '0; assign snitch_data_qvalid[c] = '0; assign snitch_data_pready[c] = '0; assign snitch_inst_addr[c/NumCoresPerCache][c%NumCoresPerCache] = '0; assign snitch_inst_valid[c/NumCoresPerCache][c%NumCoresPerCache] = '0; end end /*********************** * Instruction Cache * ***********************/ // Instruction interface addr_t [NumCaches-1:0] refill_qaddr; logic [NumCaches-1:0][7:0] refill_qlen; logic [NumCaches-1:0] refill_qvalid; logic [NumCaches-1:0] refill_qready; logic [NumCaches-1:0][AxiDataWidth-1:0] refill_pdata; logic [NumCaches-1:0] refill_perror; logic [NumCaches-1:0] refill_pvalid; logic [NumCaches-1:0] refill_plast; logic [NumCaches-1:0] refill_pready; for (genvar c = 0; unsigned'(c) < NumCaches; c++) begin: gen_caches snitch_icache #( .NR_FETCH_PORTS (NumCoresPerCache ), /// Cache Line Width .L0_LINE_COUNT (4 ), .LINE_WIDTH (ICacheLineWidth ), .LINE_COUNT (ICacheSizeByte / (ICacheSets * ICacheLineWidth / 8) ), .SET_COUNT (ICacheSets ), .FETCH_AW (AddrWidth ), .FETCH_DW (DataWidth ), .FILL_AW (AddrWidth ), .FILL_DW (AxiDataWidth ), .L1_TAG_SCM (1 ), /// Make the early cache latch-based. This reduces latency at the cost of /// increased combinatorial path lengths and the hassle of having latches in /// the design. .EARLY_LATCH (1 ), .L0_EARLY_TAG_WIDTH (11 ), .ISO_CROSSING (0 ) ) i_snitch_icache ( .clk_i (clk_i ), .clk_d2_i (clk_i ), .rst_ni (rst_ni ), .enable_prefetching_i (snitch_inst_valid[c] ), .icache_events_o (/* Unused */ ), .flush_valid_i (1'b0 ), .flush_ready_o (/* Unused */ ), .inst_addr_i (snitch_inst_addr[c] ), .inst_data_o (snitch_inst_data[c] ), .inst_cacheable_i ({NumCoresPerCache{1'b1}}), .inst_valid_i (snitch_inst_valid[c] ), .inst_ready_o (snitch_inst_ready[c] ), .inst_error_o (/* Unused */ ), .refill_qaddr_o (refill_qaddr[c] ), .refill_qlen_o (refill_qlen[c] ), .refill_qvalid_o (refill_qvalid[c] ), .refill_qready_i (refill_qready[c] ), .refill_pdata_i (refill_pdata[c] ), .refill_perror_i (refill_perror[c] ), .refill_pvalid_i (refill_pvalid[c] ), .refill_plast_i (refill_plast[c] ), .refill_pready_o (refill_pready[c] ) ); end /****************** * Memory Banks * ******************/ // Bank metadata typedef struct packed { local_req_interco_addr_t ini_addr; meta_id_t meta_id; tile_group_id_t tile_id; tile_core_id_t core_id; } bank_metadata_t; // Memory interfaces logic [NumBanksPerTile-1:0] bank_req_valid; logic [NumBanksPerTile-1:0] bank_req_ready; local_req_interco_addr_t [NumBanksPerTile-1:0] bank_req_ini_addr; tcdm_slave_req_t [NumBanksPerTile-1:0] bank_req_payload; logic [NumBanksPerTile-1:0] bank_resp_valid; logic [NumBanksPerTile-1:0] bank_resp_ready; tcdm_slave_resp_t [NumBanksPerTile-1:0] bank_resp_payload; local_req_interco_addr_t [NumBanksPerTile-1:0] bank_resp_ini_addr; for (genvar b = 0; unsigned'(b) < NumBanksPerTile; b++) begin: gen_banks bank_metadata_t meta_in; bank_metadata_t meta_out; logic req_valid; logic req_write; bank_addr_t req_addr; data_t req_wdata; data_t resp_rdata; strb_t req_be; // Un/Pack metadata assign meta_in = '{ ini_addr : bank_req_ini_addr[b], meta_id : bank_req_payload[b].wdata.meta_id, core_id : bank_req_payload[b].wdata.core_id, tile_id : bank_req_payload[b].ini_addr }; assign bank_resp_ini_addr[b] = meta_out.ini_addr; assign bank_resp_payload[b].rdata.meta_id = meta_out.meta_id; assign bank_resp_payload[b].ini_addr = meta_out.tile_id; assign bank_resp_payload[b].rdata.core_id = meta_out.core_id; assign bank_resp_payload[b].rdata.amo = '0; // Don't care tcdm_adapter #( .AddrWidth (TCDMAddrMemWidth), .DataWidth (DataWidth ), .metadata_t (bank_metadata_t ), .LrScEnable (LrScEnable ), .RegisterAmo(1'b0 ) ) i_tcdm_adapter ( .clk_i (clk_i ), .rst_ni (rst_ni ), .in_valid_i (bank_req_valid[b] ), .in_ready_o (bank_req_ready[b] ), .in_address_i(bank_req_payload[b].tgt_addr[idx_width(NumBanksPerTile) +: TCDMAddrMemWidth]), .in_amo_i (bank_req_payload[b].wdata.amo ), .in_write_i (bank_req_payload[b].wen ), .in_wdata_i (bank_req_payload[b].wdata.data ), .in_meta_i (meta_in ), .in_be_i (bank_req_payload[b].be ), .in_valid_o (bank_resp_valid[b] ), .in_ready_i (bank_resp_ready[b] ), .in_rdata_o (bank_resp_payload[b].rdata.data ), .in_meta_o (meta_out ), .out_req_o (req_valid ), .out_add_o (req_addr ), .out_write_o (req_write ), .out_wdata_o (req_wdata ), .out_be_o (req_be ), .out_rdata_i (resp_rdata ) ); // Bank tc_sram #( .DataWidth(DataWidth ), .NumWords (2**TCDMAddrMemWidth), .NumPorts (1 ) ) mem_bank ( .clk_i (clk_i ), .rst_ni (rst_ni ), .req_i (req_valid ), .we_i (req_write ), .addr_i (req_addr ), .wdata_i(req_wdata ), .be_i (req_be ), .rdata_o(resp_rdata) ); end /*************** * Registers * ***************/ // These are required to break dependencies between request and response, establishing a correct // valid/ready handshake. tcdm_master_req_t [NumGroups-1:0] prereg_tcdm_master_req; logic [NumGroups-1:0] prereg_tcdm_master_req_valid; logic [NumGroups-1:0] prereg_tcdm_master_req_ready; tcdm_slave_req_t [NumGroups-1:0] postreg_tcdm_slave_req; logic [NumGroups-1:0] postreg_tcdm_slave_req_valid; logic [NumGroups-1:0] postreg_tcdm_slave_req_ready; tcdm_slave_resp_t [NumGroups-1:0] prereg_tcdm_slave_resp; logic [NumGroups-1:0] prereg_tcdm_slave_resp_valid; logic [NumGroups-1:0] prereg_tcdm_slave_resp_ready; tcdm_master_resp_t [NumGroups-1:0] postreg_tcdm_master_resp; tile_core_id_t [NumGroups-1:0] postreg_tcdm_master_resp_ini_sel; logic [NumGroups-1:0] postreg_tcdm_master_resp_valid; logic [NumGroups-1:0] postreg_tcdm_master_resp_ready; // Break paths between request and response with registers for (genvar h = 0; unsigned'(h) < NumGroups; h++) begin: gen_tcdm_registers spill_register #( .T(tcdm_master_req_t) ) i_tcdm_master_req_register ( .clk_i (clk_i ), .rst_ni (rst_ni ), .data_i (prereg_tcdm_master_req[h] ), .valid_i(prereg_tcdm_master_req_valid[h]), .ready_o(prereg_tcdm_master_req_ready[h]), .data_o (tcdm_master_req_o[h] ), .valid_o(tcdm_master_req_valid_o[h] ), .ready_i(tcdm_master_req_ready_i[h] ) ); fall_through_register #( .T(tcdm_master_resp_t) ) i_tcdm_master_resp_register ( .clk_i (clk_i ), .rst_ni (rst_ni ), .clr_i (1'b0 ), .testmode_i(1'b0 ), .data_i (tcdm_master_resp_i[h] ), .valid_i (tcdm_master_resp_valid_i[h] ), .ready_o (tcdm_master_resp_ready_o[h] ), .data_o (postreg_tcdm_master_resp[h] ), .valid_o (postreg_tcdm_master_resp_valid[h]), .ready_i (postreg_tcdm_master_resp_ready[h]) ); // Helper signal to drive the remote response interconnect assign postreg_tcdm_master_resp_ini_sel[h] = postreg_tcdm_master_resp[h].rdata.core_id; fall_through_register #( .T(tcdm_slave_req_t) ) i_tcdm_slave_req_register ( .clk_i (clk_i ), .rst_ni (rst_ni ), .clr_i (1'b0 ), .testmode_i(1'b0 ), .data_i (tcdm_slave_req_i[h] ), .valid_i (tcdm_slave_req_valid_i[h] ), .ready_o (tcdm_slave_req_ready_o[h] ), .data_o (postreg_tcdm_slave_req[h] ), .valid_o (postreg_tcdm_slave_req_valid[h]), .ready_i (postreg_tcdm_slave_req_ready[h]) ); spill_register #( .T(tcdm_slave_resp_t) ) i_tcdm_slave_resp_register ( .clk_i (clk_i ), .rst_ni (rst_ni ), .data_i (prereg_tcdm_slave_resp[h] ), .valid_i(prereg_tcdm_slave_resp_valid[h]), .ready_o(prereg_tcdm_slave_resp_ready[h]), .data_o (tcdm_slave_resp_o[h] ), .valid_o(tcdm_slave_resp_valid_o[h] ), .ready_i(tcdm_slave_resp_ready_i[h] ) ); end: gen_tcdm_registers /**************************** * Remote Interconnects * ****************************/ tcdm_master_req_t [NumCoresPerTile-1:0] remote_req_interco; logic [NumCoresPerTile-1:0] remote_req_interco_valid; logic [NumCoresPerTile-1:0] remote_req_interco_ready; group_id_t [NumCoresPerTile-1:0] remote_req_interco_tgt_sel; tcdm_master_resp_t [NumCoresPerTile-1:0] remote_resp_interco; logic [NumCoresPerTile-1:0] remote_resp_interco_valid; logic [NumCoresPerTile-1:0] remote_resp_interco_ready; stream_xbar #( .NumInp (NumCoresPerTile ), .NumOut (NumGroups ), .payload_t(tcdm_master_req_t) ) i_remote_req_interco ( .clk_i (clk_i ), .rst_ni (rst_ni ), .flush_i(1'b0 ), // External priority flag .rr_i ('0 ), // Master .data_i (remote_req_interco ), .valid_i(remote_req_interco_valid ), .ready_o(remote_req_interco_ready ), .sel_i (remote_req_interco_tgt_sel ), // Slave .data_o (prereg_tcdm_master_req ), .valid_o(prereg_tcdm_master_req_valid), .ready_i(prereg_tcdm_master_req_ready), .idx_o (/* Unused */ ) ); stream_xbar #( .NumInp (NumGroups ), .NumOut (NumCoresPerTile ), .payload_t(tcdm_master_resp_t) ) i_remote_resp_interco ( .clk_i (clk_i ), .rst_ni (rst_ni ), .flush_i(1'b0 ), // External priority flag .rr_i ('0 ), // Master .data_i (postreg_tcdm_master_resp ), .valid_i(postreg_tcdm_master_resp_valid ), .ready_o(postreg_tcdm_master_resp_ready ), .sel_i (postreg_tcdm_master_resp_ini_sel), // Slave .data_o (remote_resp_interco ), .valid_o(remote_resp_interco_valid ), .ready_i(remote_resp_interco_ready ), .idx_o (/* Unused */ ) ); /********************** * Local Intercos * **********************/ logic [NumCoresPerTile-1:0] local_req_interco_valid; logic [NumCoresPerTile-1:0] local_req_interco_ready; tcdm_slave_req_t [NumCoresPerTile-1:0] local_req_interco_payload; logic [NumCoresPerTile-1:0] local_resp_interco_valid; logic [NumCoresPerTile-1:0] local_resp_interco_ready; tcdm_slave_resp_t [NumCoresPerTile-1:0] local_resp_interco_payload; logic [NumCoresPerTile+NumGroups-1:0][idx_width(NumBanksPerTile)-1:0] local_req_interco_tgt_sel; for (genvar j = 0; unsigned'(j) < NumCoresPerTile; j++) begin: gen_local_req_interco_tgt_sel_local assign local_req_interco_tgt_sel[j] = local_req_interco_payload[j].tgt_addr[idx_width(NumBanksPerTile)-1:0]; end: gen_local_req_interco_tgt_sel_local for (genvar j = 0; unsigned'(j) < NumGroups; j++) begin: gen_local_req_interco_tgt_sel_remote assign local_req_interco_tgt_sel[j + NumCoresPerTile] = postreg_tcdm_slave_req[j].tgt_addr[idx_width(NumBanksPerTile)-1:0]; end: gen_local_req_interco_tgt_sel_remote stream_xbar #( .NumInp (NumCoresPerTile+NumGroups), .NumOut (NumBanksPerTile ), .payload_t(tcdm_slave_req_t ) ) i_local_req_interco ( .clk_i (clk_i ), .rst_ni (rst_ni ), .flush_i(1'b0 ), // External priority flag .rr_i ('0 ), // Master .data_i ({postreg_tcdm_slave_req, local_req_interco_payload} ), .valid_i({postreg_tcdm_slave_req_valid, local_req_interco_valid}), .ready_o({postreg_tcdm_slave_req_ready, local_req_interco_ready}), .sel_i (local_req_interco_tgt_sel ), // Slave .data_o (bank_req_payload ), .valid_o(bank_req_valid ), .ready_i(bank_req_ready ), .idx_o (bank_req_ini_addr ) ); stream_xbar #( .NumInp (NumBanksPerTile ), .NumOut (NumCoresPerTile+NumGroups), .payload_t(tcdm_slave_resp_t ) ) i_local_resp_interco ( .clk_i (clk_i ), .rst_ni (rst_ni ), .flush_i(1'b0 ), // External priority flag .rr_i ('0 ), // Master .data_i (bank_resp_payload ), .valid_i(bank_resp_valid ), .ready_o(bank_resp_ready ), .sel_i (bank_resp_ini_addr ), // Slave .data_o ({prereg_tcdm_slave_resp, local_resp_interco_payload} ), .valid_o({prereg_tcdm_slave_resp_valid, local_resp_interco_valid}), .ready_i({prereg_tcdm_slave_resp_ready, local_resp_interco_ready}), .idx_o (/* Unused */ ) ); /******************* * Core De/mux * *******************/ // SoC requests dreq_t [NumCoresPerTile-1:0] soc_data_q; logic [NumCoresPerTile-1:0] soc_data_qvalid; logic [NumCoresPerTile-1:0] soc_data_qready; dresp_t [NumCoresPerTile-1:0] soc_data_p; logic [NumCoresPerTile-1:0] soc_data_pvalid; logic [NumCoresPerTile-1:0] soc_data_pready; // Address map typedef enum int unsigned { TCDM_EXTERNAL = 0, TCDM_LOCAL, SOC } addr_map_slave_t; address_map_t [2:0] mask_map; assign mask_map = '{ // Lowest priority: send request through the SoC port '{slave_idx: SOC, mask : '0, value : '0 }, // Send request through the external TCDM port '{slave_idx: TCDM_EXTERNAL, mask : TCDMMask, value : TCDMBaseAddr }, // Highest priority: send request through the local TCDM port '{slave_idx: TCDM_LOCAL, mask : TCDMMask | ({idx_width(NumTiles){1'b1}} << (ByteOffset + $clog2(NumBanksPerTile))), value : TCDMBaseAddr | (tile_id_i << (ByteOffset + $clog2(NumBanksPerTile))) } }; for (genvar c = 0; c < NumCoresPerTile; c++) begin: gen_core_mux // Remove tile index from local_req_interco_addr_int, since it will not be used for routing. addr_t local_req_interco_addr_int; assign local_req_interco_payload[c].tgt_addr = tcdm_addr_t'({local_req_interco_addr_int[ByteOffset + idx_width(NumBanksPerTile) + $clog2(NumTiles) +: TCDMAddrMemWidth], // Bank address local_req_interco_addr_int[ByteOffset +: idx_width(NumBanksPerTile)]}); // Bank // Switch tile and bank indexes for correct upper level routing, and remove the group index addr_t prescramble_tcdm_req_tgt_addr; if (NumTilesPerGroup == 1) begin : gen_remote_req_interco_tgt_addr assign remote_req_interco[c].tgt_addr = tcdm_addr_t'({prescramble_tcdm_req_tgt_addr[ByteOffset + idx_width(NumBanksPerTile) + $clog2(NumGroups) +: TCDMAddrMemWidth], // Bank address prescramble_tcdm_req_tgt_addr[ByteOffset +: idx_width(NumBanksPerTile)]}); // Tile end else begin : gen_remote_req_interco_tgt_addr assign remote_req_interco[c].tgt_addr = tcdm_addr_t'({prescramble_tcdm_req_tgt_addr[ByteOffset + idx_width(NumBanksPerTile) + $clog2(NumTilesPerGroup) + $clog2(NumGroups) +: TCDMAddrMemWidth], // Bank address prescramble_tcdm_req_tgt_addr[ByteOffset +: idx_width(NumBanksPerTile)], // Bank prescramble_tcdm_req_tgt_addr[ByteOffset + idx_width(NumBanksPerTile) +: $clog2(NumTilesPerGroup)]}); // Tile end if (NumGroups == 1) begin : gen_remote_req_interco_tgt_sel assign remote_req_interco_tgt_sel[c] = 1'b0; end else begin : gen_remote_req_interco_tgt_sel // Output port depends on both the target and initiator group assign remote_req_interco_tgt_sel[c] = (prescramble_tcdm_req_tgt_addr[ByteOffset + $clog2(NumBanksPerTile) + $clog2(NumTilesPerGroup) +: $clog2(NumGroups)]) ^ group_id; end // We don't care about these assign local_req_interco_payload[c].wdata.core_id = '0; assign local_req_interco_payload[c].ini_addr = '0; assign soc_data_q[c].id = '0; // Constant value assign remote_req_interco[c].wdata.core_id = c[idx_width(NumCoresPerTile)-1:0]; // Scramble address before entering TCDM shim for sequential+interleaved memory map addr_t snitch_data_qaddr_scrambled; address_scrambler #( .AddrWidth (AddrWidth ), .ByteOffset (ByteOffset ), .NumTiles (NumTiles ), .NumBanksPerTile (NumBanksPerTile ), .Bypass (0 ), .SeqMemSizePerTile (SeqMemSizePerTile) ) i_address_scrambler ( .address_i (snitch_data_qaddr[c] ), .address_o (snitch_data_qaddr_scrambled) ); if (!TrafficGeneration) begin: gen_tcdm_shim tcdm_shim #( .AddrWidth (AddrWidth ), .DataWidth (DataWidth ), .MaxOutStandingReads (snitch_pkg::NumIntOutstandingLoads), .NrTCDM (2 ), .NrSoC (1 ), .NumRules (3 ) ) i_tcdm_shim ( .clk_i (clk_i ), .rst_ni (rst_ni ), // to TCDM --> FF Connection to outside of tile .tcdm_req_valid_o ({local_req_interco_valid[c], remote_req_interco_valid[c]} ), .tcdm_req_tgt_addr_o({local_req_interco_addr_int, prescramble_tcdm_req_tgt_addr} ), .tcdm_req_wen_o ({local_req_interco_payload[c].wen, remote_req_interco[c].wen} ), .tcdm_req_wdata_o ({local_req_interco_payload[c].wdata.data, remote_req_interco[c].wdata.data} ), .tcdm_req_amo_o ({local_req_interco_payload[c].wdata.amo, remote_req_interco[c].wdata.amo} ), .tcdm_req_id_o ({local_req_interco_payload[c].wdata.meta_id, remote_req_interco[c].wdata.meta_id} ), .tcdm_req_be_o ({local_req_interco_payload[c].be, remote_req_interco[c].be} ), .tcdm_req_ready_i ({local_req_interco_ready[c], remote_req_interco_ready[c]} ), .tcdm_resp_valid_i ({local_resp_interco_valid[c], remote_resp_interco_valid[c]} ), .tcdm_resp_ready_o ({local_resp_interco_ready[c], remote_resp_interco_ready[c]} ), .tcdm_resp_rdata_i ({local_resp_interco_payload[c].rdata.data, remote_resp_interco[c].rdata.data} ), .tcdm_resp_id_i ({local_resp_interco_payload[c].rdata.meta_id, remote_resp_interco[c].rdata.meta_id}), // to SoC .soc_qaddr_o (soc_data_q[c].addr ), .soc_qwrite_o (soc_data_q[c].write ), .soc_qamo_o (soc_data_q[c].amo ), .soc_qdata_o (soc_data_q[c].data ), .soc_qstrb_o (soc_data_q[c].strb ), .soc_qvalid_o (soc_data_qvalid[c] ), .soc_qready_i (soc_data_qready[c] ), .soc_pdata_i (soc_data_p[c].data ), .soc_perror_i (soc_data_p[c].error ), .soc_pvalid_i (soc_data_pvalid[c] ), .soc_pready_o (soc_data_pready[c] ), // from core .data_qaddr_i (snitch_data_qaddr_scrambled ), .data_qwrite_i (snitch_data_qwrite[c] ), .data_qamo_i (snitch_data_qamo[c] ), .data_qdata_i (snitch_data_qdata[c] ), .data_qstrb_i (snitch_data_qstrb[c] ), .data_qid_i (snitch_data_qid[c] ), .data_qvalid_i (snitch_data_qvalid[c] ), .data_qready_o (snitch_data_qready[c] ), .data_pdata_o (snitch_data_pdata[c] ), .data_perror_o (snitch_data_perror[c] ), .data_pid_o (snitch_data_pid[c] ), .data_pvalid_o (snitch_data_pvalid[c] ), .data_pready_i (snitch_data_pready[c] ), .address_map_i (mask_map ) ); end else begin: gen_traffic_generator traffic_generator #( .NumRules (3 ), .TCDMBaseAddr (TCDMBaseAddr ), .MaxOutStandingReads(snitch_pkg::NumIntOutstandingLoads) ) i_traffic_gen ( .clk_i (clk_i ), .rst_ni (rst_ni ), .core_id_i ({tile_id_i, c[idx_width(NumCoresPerTile)-1:0]} ), // Address map .address_map_i (mask_map ), // To TCDM .tcdm_req_valid_o ({local_req_interco_valid[c], remote_req_interco_valid[c]} ), .tcdm_req_tgt_addr_o({local_req_interco_addr_int, prescramble_tcdm_req_tgt_addr} ), .tcdm_req_wen_o ({local_req_interco_payload[c].wen, remote_req_interco[c].wen}), .tcdm_req_wdata_o ({local_req_interco_payload[c].wdata.data, remote_req_interco[c].wdata.data}), .tcdm_req_amo_o({local_req_interco_payload[c].wdata.amo, remote_req_interco[c].wdata.amo}), .tcdm_req_id_o({local_req_interco_payload[c] .wdata.meta_id, remote_req_interco[c].wdata.meta_id}), .tcdm_req_be_o ({local_req_interco_payload[c].be, remote_req_interco[c].be}), .tcdm_req_ready_i ({local_req_interco_ready[c], remote_req_interco_ready[c]} ), .tcdm_resp_valid_i({local_resp_interco_valid[c], remote_resp_interco_valid[c]}), .tcdm_resp_ready_o({local_resp_interco_ready[c], remote_resp_interco_ready[c]}), .tcdm_resp_rdata_i({local_resp_interco_payload[c].rdata.data, remote_resp_interco[c].rdata.data} ), .tcdm_resp_id_i ({local_resp_interco_payload[c].rdata.meta_id, remote_resp_interco[c].rdata.meta_id}) ); // Tie unused signals assign soc_data_q[c].addr = '0; assign soc_data_q[c].write = '0; assign soc_data_q[c].amo = '0; assign soc_data_q[c].data = '0; assign soc_data_q[c].strb = '0; assign soc_data_qvalid[c] = '0; assign soc_data_pready[c] = '0; assign snitch_data_qready[c] = '0; assign snitch_data_pdata[c] = '0; assign snitch_data_perror[c] = '0; assign snitch_data_pid[c] = '0; assign snitch_data_pvalid[c] = '0; end end /**************** * AXI Plug * ****************/ snitch_pkg::dreq_t soc_req_o; snitch_pkg::dresp_t soc_resp_i; logic soc_qvalid; logic soc_qready; logic soc_pvalid; logic soc_pready; // We don't care about this assign soc_resp_i.id = 'x; snitch_demux #( .NrPorts (NumCoresPerTile ), .req_t (snitch_pkg::dreq_t ), .resp_t (snitch_pkg::dresp_t) ) i_snitch_demux_data ( .clk_i (clk_i ), .rst_ni (rst_ni ), // Inputs .req_payload_i (soc_data_q ), .req_valid_i (soc_data_qvalid), .req_ready_o (soc_data_qready), .resp_payload_o(soc_data_p ), .resp_last_o (/* Unused */ ), .resp_valid_o (soc_data_pvalid), .resp_ready_i (soc_data_pready), // Output .req_payload_o (soc_req_o ), .req_valid_o (soc_qvalid ), .req_ready_i (soc_qready ), .resp_payload_i(soc_resp_i ), .resp_last_i (1'b1 ), .resp_valid_i (soc_pvalid ), .resp_ready_o (soc_pready ) ); // Core request axi_core_req_t axi_cores_req, axi_cache_req; axi_core_resp_t axi_cores_resp, axi_cache_resp; axi_tile_req_t axi_mst_req; axi_tile_resp_t axi_mst_resp; snitch_axi_adapter #( .addr_t (snitch_pkg::addr_t), .data_t (snitch_pkg::data_t), .strb_t (snitch_pkg::strb_t), .axi_mst_req_t (axi_core_req_t ), .axi_mst_resp_t (axi_core_resp_t ) ) i_snitch_core_axi_adapter ( .clk_i (clk_i ), .rst_ni (rst_ni ), .slv_qaddr_i (soc_req_o.addr ), .slv_qwrite_i(soc_req_o.write ), .slv_qamo_i (soc_req_o.amo ), .slv_qdata_i (soc_req_o.data ), .slv_qsize_i (3'b010 ), .slv_qstrb_i (soc_req_o.strb ), .slv_qrlen_i ('0 ), .slv_qvalid_i(soc_qvalid ), .slv_qready_o(soc_qready ), .slv_pdata_o (soc_resp_i.data ), .slv_perror_o(soc_resp_i.error), .slv_plast_o (/* Unused */ ), .slv_pvalid_o(soc_pvalid ), .slv_pready_i(soc_pready ), .axi_req_o (axi_cores_req ), .axi_resp_i (axi_cores_resp ) ); // TODO: Add demux for the case where we have many intruction caches snitch_axi_adapter #( .addr_t (snitch_pkg::addr_t), .data_t (axi_data_t ), .strb_t (axi_strb_t ), .axi_mst_req_t (axi_core_req_t ), .axi_mst_resp_t (axi_core_resp_t ) ) i_snitch_cache_axi_adapter ( .clk_i (clk_i ), .rst_ni (rst_ni ), .slv_qaddr_i (refill_qaddr[0] ), .slv_qwrite_i('0 ), .slv_qamo_i ('0 ), .slv_qdata_i ('0 ), .slv_qsize_i (3'($clog2(AxiDataWidth/8))), .slv_qstrb_i ('0 ), .slv_qrlen_i (refill_qlen[0] ), .slv_qvalid_i(refill_qvalid[0] ), .slv_qready_o(refill_qready[0] ), .slv_pdata_o (refill_pdata[0] ), .slv_perror_o(refill_perror[0] ), .slv_plast_o (refill_plast[0] ), .slv_pvalid_o(refill_pvalid[0] ), .slv_pready_i(refill_pready[0] ), .axi_req_o (axi_cache_req ), .axi_resp_i (axi_cache_resp ) ); axi_mux #( .SlvAxiIDWidth (AxiCoreIdWidth ), .slv_aw_chan_t (axi_core_aw_t ), .mst_aw_chan_t (axi_tile_aw_t ), .w_chan_t (axi_tile_w_t ), .slv_b_chan_t (axi_core_b_t ), .mst_b_chan_t (axi_tile_b_t ), .slv_ar_chan_t (axi_core_ar_t ), .mst_ar_chan_t (axi_tile_ar_t ), .slv_r_chan_t (axi_core_r_t ), .mst_r_chan_t (axi_tile_r_t ), .slv_req_t (axi_core_req_t ), .slv_resp_t (axi_core_resp_t), .mst_req_t (axi_tile_req_t ), .mst_resp_t (axi_tile_resp_t), .NoSlvPorts (2 ), .MaxWTrans (8 ), .FallThrough (1 ) ) i_axi_mux ( .clk_i (clk_i ), .rst_ni (rst_ni ), .test_i (1'b0 ), .slv_reqs_i ({axi_cores_req, axi_cache_req} ), .slv_resps_o({axi_cores_resp, axi_cache_resp}), .mst_req_o (axi_mst_req ), .mst_resp_i (axi_mst_resp ) ); axi_cut #( .aw_chan_t(axi_tile_aw_t ), .w_chan_t (axi_tile_w_t ), .b_chan_t (axi_tile_b_t ), .ar_chan_t(axi_tile_ar_t ), .r_chan_t (axi_tile_r_t ), .req_t (axi_tile_req_t ), .resp_t (axi_tile_resp_t) ) axi_mst_slice ( .clk_i (clk_i ), .rst_ni (rst_ni ), .slv_req_i (axi_mst_req ), .slv_resp_o(axi_mst_resp ), .mst_req_o (axi_mst_req_o ), .mst_resp_i(axi_mst_resp_i) ); /****************** * Assertions * ******************/ // Check invariants. if (BootAddr[1:0] != 2'b00) $fatal(1, "[mempool_tile] Boot address should be aligned in a 4-byte boundary."); if (NumCoresPerTile != 2**$clog2(NumCoresPerTile)) $fatal(1, "[mempool_tile] The number of cores per tile must be a power of two."); if (NumCores != unsigned'(2**$clog2(NumCores))) $fatal(1, "[mempool_tile] The number of cores must be a power of two."); if (NumBanksPerTile < 1) $fatal(1, "[mempool_tile] The number of banks per tile must be larger than one"); if (NumCaches != 1) $error("NumCaches > 1 is not supported!"); if (DataWidth > AxiDataWidth) $error("AxiDataWidth needs to be larger than DataWidth!"); endmodule : mempool_tile /***************** * WRAPPER * *****************/ /*verilator lint_off DECLFILENAME*/ //what is the below file exactly used for ? `include "mempool/mempool.svh" module mempool_tile_wrap import mempool_pkg::*; import cf_math_pkg::idx_width; #( // TCDM parameter addr_t TCDMBaseAddr = 32'b0, // Boot address parameter logic [31:0] BootAddr = 32'h0000_1000, // Dependent parameters. DO NOT CHANGE. parameter int unsigned NumCaches = NumCoresPerTile / NumCoresPerCache ) ( // Clock and reset input logic clk_i, input logic rst_ni, // Scan chain input logic scan_enable_i, input logic scan_data_i, output logic scan_data_o, // Tile ID input logic [idx_width(NumTiles)-1:0] tile_id_i, // TCDM Master interfaces output `STRUCT_PORT(tcdm_master_req_t) tcdm_master_north_req_o, output logic tcdm_master_north_req_valid_o, input logic tcdm_master_north_req_ready_i, input `STRUCT_PORT(tcdm_master_resp_t) tcdm_master_north_resp_i, input logic tcdm_master_north_resp_valid_i, output logic tcdm_master_north_resp_ready_o, output `STRUCT_PORT(tcdm_master_req_t) tcdm_master_northeast_req_o, output logic tcdm_master_northeast_req_valid_o, input logic tcdm_master_northeast_req_ready_i, input `STRUCT_PORT(tcdm_master_resp_t) tcdm_master_northeast_resp_i, input logic tcdm_master_northeast_resp_valid_i, output logic tcdm_master_northeast_resp_ready_o, output `STRUCT_PORT(tcdm_master_req_t) tcdm_master_east_req_o, output logic tcdm_master_east_req_valid_o, input logic tcdm_master_east_req_ready_i, input `STRUCT_PORT(tcdm_master_resp_t) tcdm_master_east_resp_i, input logic tcdm_master_east_resp_valid_i, output logic tcdm_master_east_resp_ready_o, output `STRUCT_PORT(tcdm_master_req_t) tcdm_master_local_req_o, output logic tcdm_master_local_req_valid_o, input logic tcdm_master_local_req_ready_i, input `STRUCT_PORT(tcdm_master_resp_t) tcdm_master_local_resp_i, input logic tcdm_master_local_resp_valid_i, output logic tcdm_master_local_resp_ready_o, // TCDM Slave interfaces input `STRUCT_PORT(tcdm_slave_req_t) tcdm_slave_north_req_i, input logic tcdm_slave_north_req_valid_i, output logic tcdm_slave_north_req_ready_o, output `STRUCT_PORT(tcdm_slave_resp_t) tcdm_slave_north_resp_o, output logic tcdm_slave_north_resp_valid_o, input logic tcdm_slave_north_resp_ready_i, input `STRUCT_PORT(tcdm_slave_req_t) tcdm_slave_northeast_req_i, input logic tcdm_slave_northeast_req_valid_i, output logic tcdm_slave_northeast_req_ready_o, output `STRUCT_PORT(tcdm_slave_resp_t) tcdm_slave_northeast_resp_o, output logic tcdm_slave_northeast_resp_valid_o, input logic tcdm_slave_northeast_resp_ready_i, input `STRUCT_PORT(tcdm_slave_req_t) tcdm_slave_east_req_i, input logic tcdm_slave_east_req_valid_i, output logic tcdm_slave_east_req_ready_o, output `STRUCT_PORT(tcdm_slave_resp_t) tcdm_slave_east_resp_o, output logic tcdm_slave_east_resp_valid_o, input logic tcdm_slave_east_resp_ready_i, input `STRUCT_PORT(tcdm_slave_req_t) tcdm_slave_local_req_i, input logic tcdm_slave_local_req_valid_i, output logic tcdm_slave_local_req_ready_o, output `STRUCT_PORT(tcdm_slave_resp_t) tcdm_slave_local_resp_o, output logic tcdm_slave_local_resp_valid_o, input logic tcdm_slave_local_resp_ready_i, // AXI Interface output `STRUCT_PORT(axi_tile_req_t) axi_mst_req_o, input `STRUCT_PORT(axi_tile_resp_t) axi_mst_resp_i, // Wake up interface input logic [NumCoresPerTile-1:0] wake_up_i ); mempool_tile #( .TCDMBaseAddr(TCDMBaseAddr), .BootAddr (BootAddr ) ) i_tile ( .clk_i (clk_i ), .rst_ni (rst_ni ), .tile_id_i (tile_id_i ), // Scan chain .scan_enable_i (scan_enable_i ), .scan_data_i (scan_data_i ), .scan_data_o (scan_data_o ), // TCDM Master .tcdm_master_req_o ({tcdm_master_northeast_req_o, tcdm_master_north_req_o, tcdm_master_east_req_o, tcdm_master_local_req_o} ), .tcdm_master_req_ready_i ({tcdm_master_northeast_req_ready_i, tcdm_master_north_req_ready_i, tcdm_master_east_req_ready_i, tcdm_master_local_req_ready_i} ), .tcdm_master_req_valid_o ({tcdm_master_northeast_req_valid_o, tcdm_master_north_req_valid_o, tcdm_master_east_req_valid_o, tcdm_master_local_req_valid_o} ), .tcdm_master_resp_i ({tcdm_master_northeast_resp_i, tcdm_master_north_resp_i, tcdm_master_east_resp_i, tcdm_master_local_resp_i} ), .tcdm_master_resp_ready_o({tcdm_master_northeast_resp_ready_o, tcdm_master_north_resp_ready_o, tcdm_master_east_resp_ready_o, tcdm_master_local_resp_ready_o}), .tcdm_master_resp_valid_i({tcdm_master_northeast_resp_valid_i, tcdm_master_north_resp_valid_i, tcdm_master_east_resp_valid_i, tcdm_master_local_resp_valid_i}), // TCDM Slave .tcdm_slave_req_i ({tcdm_slave_northeast_req_i, tcdm_slave_north_req_i, tcdm_slave_east_req_i, tcdm_slave_local_req_i} ), .tcdm_slave_req_ready_o ({tcdm_slave_northeast_req_ready_o, tcdm_slave_north_req_ready_o, tcdm_slave_east_req_ready_o, tcdm_slave_local_req_ready_o} ), .tcdm_slave_req_valid_i ({tcdm_slave_northeast_req_valid_i, tcdm_slave_north_req_valid_i, tcdm_slave_east_req_valid_i, tcdm_slave_local_req_valid_i} ), .tcdm_slave_resp_o ({tcdm_slave_northeast_resp_o, tcdm_slave_north_resp_o, tcdm_slave_east_resp_o, tcdm_slave_local_resp_o} ), .tcdm_slave_resp_ready_i ({tcdm_slave_northeast_resp_ready_i, tcdm_slave_north_resp_ready_i, tcdm_slave_east_resp_ready_i, tcdm_slave_local_resp_ready_i} ), .tcdm_slave_resp_valid_o ({tcdm_slave_northeast_resp_valid_o, tcdm_slave_north_resp_valid_o, tcdm_slave_east_resp_valid_o, tcdm_slave_local_resp_valid_o} ), // AXI interface .axi_mst_req_o (axi_mst_req_o ), .axi_mst_resp_i (axi_mst_resp_i ), // Wake up interface .wake_up_i (wake_up_i ) ); endmodule: mempool_tile_wrap