"Fossies" - the Fresh Open Source Software Archive

Member "pocl-1.8/examples/accel/rtl/platform/almaif_mc_arbiter.vhdl" (12 Oct 2021, 10318 Bytes) of package /linux/misc/pocl-1.8.tar.gz:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 -- Copyright (c) 2016 Tampere University.
    2 --
    3 -- This file is part of TTA-Based Codesign Environment (TCE).
    4 -- 
    5 -- Permission is hereby granted, free of charge, to any person obtaining a
    6 -- copy of this software and associated documentation files (the "Software"),
    7 -- to deal in the Software without restriction, including without limitation
    8 -- the rights to use, copy, modify, merge, publish, distribute, sublicense,
    9 -- and/or sell copies of the Software, and to permit persons to whom the
   10 -- Software is furnished to do so, subject to the following conditions:
   11 -- 
   12 -- The above copyright notice and this permission notice shall be included in
   13 -- all copies or substantial portions of the Software.
   14 -- 
   15 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   16 -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   17 -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   18 -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   19 -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   20 -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   21 -- DEALINGS IN THE SOFTWARE.
   22 -------------------------------------------------------------------------------
   23 -- Title      : AlmaIF memory arbiter between multicore TTAs
   24 -- Project    : Almarvi
   25 -------------------------------------------------------------------------------
   26 -- File       : almaif_mc_arbiter.vhdl
   27 -- Author     : Aleksi Tervo  <aleksi.tervo@tut.fi>
   28 -- Company    : TUT/CPC
   29 -- Created    : 2016-11-22
   30 -- Last update: 2016-11-22
   31 -- Platform   :
   32 -- Standard   : VHDL'87
   33 -------------------------------------------------------------------------------
   34 -- Description: Acts as a memory arbiter for multicore TTAs
   35 --              Static arbiter: lower core ID has precedence
   36 -------------------------------------------------------------------------------
   37 -- Revisions  :
   38 -- Date        Version  Author  Description
   39 -- 2016-11-22  1.0      tervoa  Created
   40 -- 2017-04-26  1.1      tervoa  Sensitivity list fix
   41 -- 2017-06-01  1.2      tervoa  Converted to memory buses with handshaking
   42 -- 2017-06-27  1.3      tervoa  Split arbiter in two parts: between TTA cores
   43 --                              and between the multicore TTA and AXI
   44 -- 2018-07-30  1.4      tervoa   Support for optional sync reset
   45 -------------------------------------------------------------------------------
   46 
   47 library IEEE;
   48 use IEEE.std_logic_1164.all;
   49 use IEEE.numeric_std.all;
   50 use work.tce_util.all;
   51 
   52 entity almaif_mc_arbiter is
   53 
   54   generic (
   55     mem_dataw_g  : integer;
   56     mem_addrw_g  : integer;
   57     core_count_g : integer;
   58     sync_reset_g : integer
   59   ); port (
   60     clk                : in std_logic;
   61     rstx               : in std_logic;
   62     tta_sync_nreset_in : in std_logic_vector(core_count_g-1 downto 0);
   63     -- Buses to cores
   64     tta_avalid_in  : in  std_logic_vector(core_count_g-1 downto 0);
   65     tta_aready_out : out std_logic_vector(core_count_g-1 downto 0);
   66     tta_aaddr_in   : in  std_logic_vector(core_count_g*mem_addrw_g-1 downto 0);
   67     tta_awren_in   : in  std_logic_vector(core_count_g-1 downto 0);
   68     tta_astrb_in   : in std_logic_vector(core_count_g*mem_dataw_g/8-1 downto 0);
   69     tta_adata_in   : in  std_logic_vector(core_count_g*mem_dataw_g-1 downto 0);
   70     tta_rvalid_out : out std_logic_vector(core_count_g-1 downto 0);
   71     tta_rready_in  : in  std_logic_vector(core_count_g-1 downto 0);
   72     tta_rdata_out  : out std_logic_vector(core_count_g*mem_dataw_g-1 downto 0);
   73     -- Bus to memory
   74     mem_avalid_out : out std_logic;
   75     mem_aready_in  : in  std_logic;
   76     mem_aaddr_out  : out std_logic_vector(mem_addrw_g-1 downto 0);
   77     mem_awren_out  : out std_logic;
   78     mem_astrb_out  : out std_logic_vector(mem_dataw_g/8-1 downto 0);
   79     mem_adata_out  : out std_logic_vector(mem_dataw_g-1 downto 0);
   80     mem_rvalid_in  : in  std_logic;
   81     mem_rready_out : out std_logic;
   82     mem_rdata_in   : in  std_logic_vector(mem_dataw_g-1 downto 0)
   83   );
   84 end almaif_mc_arbiter;
   85 
   86 architecture rtl of almaif_mc_arbiter is
   87 
   88   constant sync_reset_c : boolean := sync_reset_g /= 0;
   89 
   90   constant mem_bytes_c       : integer := mem_dataw_g/8;
   91   constant fifo_depth_log2_c : integer := 2;
   92   constant core_count_log2_c : integer := bit_width(core_count_g);
   93 
   94   -- Breakout signals to arrays corewise
   95   type addr_array_t is array (natural range 0 to core_count_g-1)
   96                        of std_logic_vector(mem_addrw_g-1 downto 0);
   97   type data_array_t is array (natural range 0 to core_count_g-1)
   98                        of std_logic_vector(mem_dataw_g-1 downto 0);
   99   type mask_array_t is array (natural range 0 to core_count_g-1)
  100                        of std_logic_vector(mem_dataw_g/8-1 downto 0);
  101   signal cores_aaddr : addr_array_t;
  102   signal cores_astrb : mask_array_t;
  103   signal cores_adata : data_array_t;
  104   signal cores_rdata : data_array_t;
  105 
  106   -- FIFO implemented as a shifted register array
  107   type fifo_array_t is array (natural range <>)
  108                        of std_logic_vector(core_count_log2_c-1 downto 0);
  109   signal fifo_data_r : fifo_array_t(2**fifo_depth_log2_c-1 downto 0);
  110   signal fifo_iter_r : unsigned(fifo_depth_log2_c-1 downto 0);
  111 
  112   signal dst_sel         : std_logic_vector(core_count_log2_c-1 downto 0);
  113   signal fifo_dst_sel    : std_logic_vector(core_count_log2_c-1 downto 0);
  114   signal mem_awren       : std_logic;
  115   signal mem_avalid      : std_logic;
  116   signal mem_rready      : std_logic;
  117 begin
  118   ------------------------------------------------------------------------------
  119   -- Memory interface logic: breakout the concatenated memory buses to arrays
  120   ------------------------------------------------------------------------------
  121   signal_breakout : for I in core_count_g-1 downto 0 generate
  122     cores_aaddr(I) <= tta_aaddr_in(mem_addrw_g*(I+1)-1 downto I*mem_addrw_g);
  123     cores_astrb(I) <= tta_astrb_in(mem_bytes_c*(I+1)-1 downto I*mem_bytes_c);
  124     cores_adata(I) <= tta_adata_in(mem_dataw_g*(I+1)-1 downto I*mem_dataw_g);
  125 
  126     tta_rdata_out((I+1)*mem_dataw_g-1 downto I*mem_dataw_g) <= mem_rdata_in;
  127   end generate;
  128 
  129   arbit_logic : process (tta_avalid_in)
  130   variable active_core     : integer range 0 to core_count_g-1;
  131   variable active_core_slv : std_logic_vector(core_count_log2_c-1 downto 0);
  132   begin
  133     active_core  := 0;
  134     for I in core_count_g-1  downto 0 loop
  135       if (tta_avalid_in(I) = '1') then
  136         active_core  := I;
  137       end if;
  138     end loop;
  139     dst_sel <= std_logic_vector(to_unsigned(active_core, core_count_log2_c));
  140   end process arbit_logic;
  141 
  142 
  143   ------------------------------------------------------------------------------
  144   -- Access channel mux:
  145   ------------------------------------------------------------------------------
  146   amux : process (mem_aready_in, dst_sel, tta_avalid_in, tta_awren_in,
  147                   cores_aaddr, cores_adata, cores_astrb)
  148     variable core_sel_int : integer;
  149   begin
  150       core_sel_int                 := to_integer(unsigned(dst_sel));
  151       mem_avalid                   <= tta_avalid_in(core_sel_int);
  152       tta_aready_out               <= (others => '0');
  153       tta_aready_out(core_sel_int) <= mem_aready_in;
  154       mem_awren                    <= tta_awren_in(core_sel_int);
  155       mem_aaddr_out                <= cores_aaddr(core_sel_int);
  156       mem_adata_out                <= cores_adata(core_sel_int);
  157       mem_astrb_out                <= cores_astrb(core_sel_int);
  158   end process amux;
  159   mem_avalid_out <= mem_avalid;
  160   mem_awren_out  <= mem_awren;
  161 
  162   ----------------------------------------------------------------------------
  163   -- FIFO to keep track of reads' destinations
  164   -- TODO: Handle FIFO filling up (not an issue with current mem model/alu?)
  165   ----------------------------------------------------------------------------
  166   fifo_sync : process(clk, rstx)
  167     variable fifo_data_v : fifo_array_t(fifo_data_r'range);
  168     variable fifo_iter_v : unsigned(fifo_iter_r'range);
  169   begin
  170     if not sync_reset_c and rstx = '0' then
  171       fifo_data_r <= (others => (others => '0'));
  172       fifo_iter_r <= (others => '0');
  173     elsif rising_edge(clk) then
  174       if sync_reset_c and rstx = '0' then
  175         fifo_data_r <= (others => (others => '0'));
  176         fifo_iter_r <= (others => '0');
  177       else
  178         fifo_data_v := fifo_data_r;
  179         fifo_iter_v := fifo_iter_r;
  180         if mem_rvalid_in = '1' and mem_rready = '1' and fifo_iter_r > 0 then
  181           fifo_data_v(fifo_data_v'high-1 downto 0) :=
  182               fifo_data_v(fifo_data_v'high downto 1);
  183           fifo_data_v(fifo_data_v'high) := (others => '0');
  184           fifo_iter_v := fifo_iter_v - 1;
  185         end if;
  186 
  187         if mem_avalid = '1' and mem_aready_in = '1' and mem_awren = '0' then
  188           fifo_data_v(to_integer(fifo_iter_v)) := dst_sel;
  189           fifo_iter_v := fifo_iter_v + 1;
  190         end if;
  191 
  192         fifo_iter_r <= fifo_iter_v;
  193         fifo_data_r <= fifo_data_v;
  194       end if;
  195 
  196     end if;
  197   end process fifo_sync;
  198   fifo_dst_sel <= fifo_data_r(0);
  199 
  200   ------------------------------------------------------------------------------
  201   -- Response channel mux:
  202   -- TODO: Handle reset better; works with local memory but will cause issues
  203   --       w/ axi
  204   ------------------------------------------------------------------------------
  205   rmux : process (fifo_dst_sel, mem_rvalid_in, tta_rready_in,
  206                   tta_sync_nreset_in)
  207     variable dst_sel_int : integer;
  208   begin
  209     dst_sel_int      := to_integer(unsigned(
  210                                 fifo_dst_sel(core_count_log2_c-1 downto 0)));
  211     -- If the core is in reset, discard reads to avoid possible deadlock
  212     mem_rready     <=        tta_rready_in(dst_sel_int)
  213                       or not tta_sync_nreset_in(dst_sel_int);
  214     tta_rvalid_out <= (others => '0');
  215     tta_rvalid_out(dst_sel_int) <= mem_rvalid_in;
  216   end process rmux;
  217   cores_rdata    <= (others => mem_rdata_in);
  218   mem_rready_out <= mem_rready;
  219 
  220 
  221   ------------------------------------------------------------------------------
  222   -- Design-wide checks:
  223   ------------------------------------------------------------------------------
  224   -- coverage off
  225   -- pragma translate_off
  226   assert (mem_dataw_g/8)*8 = mem_dataw_g
  227     report "Data width must be divisible by 8"
  228     severity failure;
  229   -- pragma translate_on
  230   -- coverage on
  231 
  232 end architecture rtl;