-- © IBM Corp. 2020
-- Licensed under the Apache License, Version 2.0 (the "License"), as modified by
-- the terms below; you may not use the files in this repository except in
-- compliance with the License as modified.
-- You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
--
-- Modified Terms:
--
--    1) For the purpose of the patent license granted to you in Section 3 of the
--    License, the "Work" hereby includes implementations of the work of authorship
--    in physical form.
--
--    2) Notwithstanding any terms to the contrary in the License, any licenses
--    necessary for implementation of the Work that are available from OpenPOWER
--    via the Power ISA End User License Agreement (EULA) are explicitly excluded
--    hereunder, and may be obtained from OpenPOWER under the terms and conditions
--    of the EULA.  
--
-- Unless required by applicable law or agreed to in writing, the reference design
-- 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.
-- 
-- Additional rights, including the ability to physically implement a softcore that
-- is compliant with the required sections of the Power ISA Specification, are
-- available at no cost under the terms of the OpenPOWER Power ISA EULA, which can be
-- obtained (along with the Power ISA) here: https://openpowerfoundation.org. 


LIBRARY IEEE;
USE ieee.std_logic_1164.ALL ;
LIBRARY IBM;
USE ibm.std_ulogic_support.ALL;
USE ibm.std_ulogic_function_support.ALL;
library support;
use support.power_logic_pkg.all;


entity mmq_tlb_lrat_matchline is
  generic (real_addr_width      : integer := 42;
             lpid_width           : integer := 8;
             lrat_maxsize_log2    : integer := 40;  
             lrat_minsize_log2    : integer := 20;  
             have_xbit            : integer := 1;
             num_pgsizes          : integer := 8;
             have_cmpmask         : integer := 1;
             cmpmask_width        : integer := 7); 

port( 
    vdd                              : inout power_logic;
    gnd                              : inout power_logic;
    addr_in                          : in std_ulogic_vector(64-real_addr_width to 64-lrat_minsize_log2-1);
    addr_enable                      : in std_ulogic;
    entry_size                       : in std_ulogic_vector(0 to 3);
    entry_cmpmask                    : in std_ulogic_vector(0 to cmpmask_width-1);
    entry_xbit                       : in std_ulogic;
    entry_xbitmask                   : in std_ulogic_vector(0 to cmpmask_width-1);
    entry_lpn                        : in std_ulogic_vector(64-real_addr_width to 64-lrat_minsize_log2-1);
    entry_lpid                       : in std_ulogic_vector(0 to lpid_width-1);
    comp_lpid                        : in std_ulogic_vector(0 to lpid_width-1);
    lpid_enable                      : in std_ulogic;
    entry_v                          : in std_ulogic;

    match                            : out std_ulogic;

    dbg_addr_match       : out  std_ulogic;
    dbg_lpid_match       : out  std_ulogic
    
);

  -- synopsys translate_off
  -- synopsys translate_on

end mmq_tlb_lrat_matchline;

architecture mmq_tlb_lrat_matchline of mmq_tlb_lrat_matchline is



  signal entry_lpn_b             : std_ulogic_vector(64-lrat_maxsize_log2 to 64-lrat_minsize_log2-1);
  signal function_24_43     : std_ulogic;
  signal function_26_43     : std_ulogic;
  signal function_30_43     : std_ulogic;
  signal function_32_43     : std_ulogic;
  signal function_34_43     : std_ulogic;
  signal function_36_43     : std_ulogic;
  signal function_40_43     : std_ulogic;
  signal pgsize_eq_16M  : std_ulogic;  
  signal pgsize_eq_256M : std_ulogic;  
  signal pgsize_eq_1G   : std_ulogic; 
  signal pgsize_eq_4G   : std_ulogic; 
  signal pgsize_eq_16G  : std_ulogic; 
  signal pgsize_eq_256G : std_ulogic; 
  signal pgsize_eq_1T   : std_ulogic; 
  signal pgsize_gte_16M  : std_ulogic;  
  signal pgsize_gte_256M : std_ulogic;  
  signal pgsize_gte_1G   : std_ulogic; 
  signal pgsize_gte_4G   : std_ulogic; 
  signal pgsize_gte_16G  : std_ulogic; 
  signal pgsize_gte_256G : std_ulogic; 
  signal pgsize_gte_1T   : std_ulogic; 
  
  signal comp_or_24_25      : std_ulogic;
  signal comp_or_26_29      : std_ulogic;
  signal comp_or_30_31      : std_ulogic;
  signal comp_or_32_33      : std_ulogic;
  signal comp_or_34_35      : std_ulogic;
  signal comp_or_36_39      : std_ulogic;
  signal comp_or_40_43      : std_ulogic;
  
  signal match_line         : std_ulogic_vector(64-real_addr_width to 64-lrat_minsize_log2+lpid_width-1);
  signal addr_match         : std_ulogic;
  signal lpid_match         : std_ulogic;

signal unused_dc  :  std_ulogic;  
-- synopsys translate_off
-- synopsys translate_on

begin

  match_line(64-real_addr_width to 64-lrat_minsize_log2+lpid_width-1) <= not(
      (entry_lpn(64-real_addr_width to 64-lrat_minsize_log2-1) & entry_lpid(0 to lpid_width-1)) xor
        (addr_in(64-real_addr_width to 64-lrat_minsize_log2-1) & comp_lpid(0 to lpid_width-1))
                               );

numpgsz8 : if num_pgsizes = 8 generate

  entry_lpn_b(64-lrat_maxsize_log2 to 64-lrat_minsize_log2-1) <= not(entry_lpn(64-lrat_maxsize_log2 to 64-lrat_minsize_log2-1));


gen_nocmpmask80 : if have_cmpmask = 0 generate
  pgsize_eq_16M  <= '1' when (entry_size="0111")  
                   else '0'; 
  pgsize_eq_256M <= '1' when (entry_size="1001")  
                   else '0'; 
  pgsize_eq_1G   <= '1' when (entry_size="1010")  
                   else '0'; 
  pgsize_eq_4G   <= '1' when (entry_size="1011")  
                   else '0'; 
  pgsize_eq_16G  <= '1' when (entry_size="1100")  
                   else '0'; 
  pgsize_eq_256G <= '1' when (entry_size="1110")  
                   else '0'; 
  pgsize_eq_1T   <= '1' when (entry_size="1111")  
                   else '0'; 

  pgsize_gte_16M  <= '1' when (entry_size="0111"  or  
                              pgsize_gte_256M='1')
                   else '0'; 
  pgsize_gte_256M <= '1' when (entry_size="1001"  or  
                              pgsize_gte_1G='1')
                   else '0'; 
  pgsize_gte_1G   <= '1' when (entry_size="1010"  or  
                              pgsize_gte_4G='1')
                   else '0'; 
  pgsize_gte_4G   <= '1' when (entry_size="1011"  or  
                              pgsize_gte_16G='1')
                   else '0'; 
  pgsize_gte_16G  <= '1' when (entry_size="1100"  or  
                              pgsize_gte_256G='1')
                   else '0'; 
  pgsize_gte_256G <= '1' when (entry_size="1110"  or  
                              pgsize_gte_1T='1')
                   else '0'; 
  pgsize_gte_1T   <= '1' when (entry_size="1111")  
                   else '0'; 
                   
end generate gen_nocmpmask80;

gen_cmpmask80 : if have_cmpmask = 1 generate
  pgsize_gte_1T   <= entry_cmpmask(0);
  pgsize_gte_256G <= entry_cmpmask(1);
  pgsize_gte_16G  <= entry_cmpmask(2);
  pgsize_gte_4G   <= entry_cmpmask(3);
  pgsize_gte_1G   <= entry_cmpmask(4);
  pgsize_gte_256M <= entry_cmpmask(5);
  pgsize_gte_16M  <= entry_cmpmask(6);

  pgsize_eq_1T   <= entry_xbitmask(0);
  pgsize_eq_256G <= entry_xbitmask(1);
  pgsize_eq_16G  <= entry_xbitmask(2);
  pgsize_eq_4G   <= entry_xbitmask(3);
  pgsize_eq_1G   <= entry_xbitmask(4);
  pgsize_eq_256M <= entry_xbitmask(5);
  pgsize_eq_16M  <= entry_xbitmask(6);
end generate gen_cmpmask80;



gen_noxbit80 : if have_xbit = 0 generate
  function_24_43 <= '0';
  function_26_43 <= '0';
  function_30_43 <= '0';
  function_32_43 <= '0';
  function_34_43 <= '0';
  function_36_43 <= '0';
  function_40_43 <= '0';
end generate gen_noxbit80;
 
gen_xbit80 : if (have_xbit /= 0 and real_addr_width=42) generate
  function_24_43 <= not(entry_xbit) or
                    not(pgsize_eq_1T) or
                    or_reduce(entry_lpn_b(24 to 43) and addr_in(24 to 43));
  function_26_43 <= not(entry_xbit) or
                    not(pgsize_eq_256G) or
                    or_reduce(entry_lpn_b(26 to 43) and addr_in(26 to 43));
  function_30_43 <= not(entry_xbit) or
                    not(pgsize_eq_16G) or
                    or_reduce(entry_lpn_b(30 to 43) and addr_in(30 to 43));
  function_32_43 <= not(entry_xbit) or
                    not(pgsize_eq_4G) or
                    or_reduce(entry_lpn_b(32 to 43) and addr_in(32 to 43));
  function_34_43 <= not(entry_xbit) or
                    not(pgsize_eq_1G) or
                    or_reduce(entry_lpn_b(34 to 43) and addr_in(34 to 43));
  function_36_43 <= not(entry_xbit) or
                    not(pgsize_eq_256M) or
                    or_reduce(entry_lpn_b(36 to 43) and addr_in(36 to 43));
  function_40_43 <= not(entry_xbit) or
                    not(pgsize_eq_16M) or
                    or_reduce(entry_lpn_b(40 to 43) and addr_in(40 to 43));
end generate gen_xbit80; 
                    
gen_xbit81 : if (have_xbit /= 0 and real_addr_width=32) generate
  function_24_43 <= '1';
  function_26_43 <= '1';
  function_30_43 <= '1';
  function_32_43 <= '1';
  function_34_43 <= not(entry_xbit) or
                    not(pgsize_eq_1G) or
                    or_reduce(entry_lpn_b(34 to 43) and addr_in(34 to 43));
  function_36_43 <= not(entry_xbit) or
                    not(pgsize_eq_256M) or
                    or_reduce(entry_lpn_b(36 to 43) and addr_in(36 to 43));
  function_40_43 <= not(entry_xbit) or
                    not(pgsize_eq_16M) or
                    or_reduce(entry_lpn_b(40 to 43) and addr_in(40 to 43));
end generate gen_xbit81; 
                    
gen_comp80 : if real_addr_width=42 generate
  comp_or_24_25 <=  and_reduce(match_line(24 to 25)) or pgsize_gte_1T;
  comp_or_26_29 <=  and_reduce(match_line(26 to 29)) or pgsize_gte_256G;
  comp_or_30_31 <=  and_reduce(match_line(30 to 31)) or pgsize_gte_16G;
  comp_or_32_33 <=  and_reduce(match_line(32 to 33)) or pgsize_gte_4G;
  comp_or_34_35 <=  and_reduce(match_line(34 to 35)) or pgsize_gte_1G;
  comp_or_36_39 <=  and_reduce(match_line(36 to 39)) or pgsize_gte_256M;
  comp_or_40_43 <=  and_reduce(match_line(40 to 43)) or pgsize_gte_16M;
end generate gen_comp80; 

gen_comp81 : if real_addr_width=32 generate
  comp_or_24_25 <=  '1';
  comp_or_26_29 <=  '1';
  comp_or_30_31 <=  '1';
  comp_or_32_33 <=  '1';
  comp_or_34_35 <=  and_reduce(match_line(34 to 35)) or pgsize_gte_1G;
  comp_or_36_39 <=  and_reduce(match_line(36 to 39)) or pgsize_gte_256M;
  comp_or_40_43 <=  and_reduce(match_line(40 to 43)) or pgsize_gte_16M;
end generate gen_comp81; 

gen_noxbit81 : if (have_xbit = 0 and real_addr_width=42) generate
  addr_match <=    ( and_reduce(match_line(22 to 23)) and 
                    comp_or_24_25  and               
                    comp_or_26_29  and
                    comp_or_30_31  and
                    comp_or_32_33  and
                    comp_or_34_35  and
                    comp_or_36_39  and
                    comp_or_40_43 ) or  
                    not(addr_enable);   
end generate gen_noxbit81;
 
gen_noxbit82 : if (have_xbit = 0 and real_addr_width=32) generate
  addr_match <=    ( and_reduce(match_line(32 to 33)) and 
                    comp_or_34_35  and 
                    comp_or_36_39  and
                    comp_or_40_43 ) or  
                    not(addr_enable);   
end generate gen_noxbit82;
 
gen_xbit82 : if (have_xbit /= 0 and real_addr_width=42) generate
  addr_match <=  (and_reduce(match_line(22 to 23)) and 
                    comp_or_24_25  and               
                    comp_or_26_29  and
                    comp_or_30_31  and
                    comp_or_32_33  and
                    comp_or_34_35  and
                    comp_or_36_39  and
                    comp_or_40_43  and
                    function_24_43 and               
                    function_26_43 and
                    function_30_43 and
                    function_32_43 and
                    function_34_43 and
                    function_36_43 and
                    function_40_43) or  
                    not(addr_enable);  
end generate gen_xbit82; 

gen_xbit83 : if (have_xbit /= 0 and real_addr_width=32) generate
  addr_match <=  (and_reduce(match_line(32 to 33)) and 
                    comp_or_34_35  and          
                    comp_or_36_39  and
                    comp_or_40_43  and
                    function_34_43 and          
                    function_36_43 and
                    function_40_43) or  
                    not(addr_enable);  
end generate gen_xbit83; 

end generate numpgsz8; 


  lpid_match <=     and_reduce(match_line(64-lrat_minsize_log2 to 64-lrat_minsize_log2+lpid_width-1)) or
                    not(or_reduce(entry_lpid(0 to 7))) or  
                    not(lpid_enable);              

  match <=          addr_match and                       
                    lpid_match and                       
                    entry_v;                             

    dbg_addr_match       <= addr_match;  
    dbg_lpid_match       <= lpid_match;  

gen_unused0 : if have_cmpmask = 0 generate
  unused_dc <= '0';
end generate gen_unused0;
gen_unused1 : if have_cmpmask = 1 generate
  unused_dc <= or_reduce(entry_size);
end generate gen_unused1;

end mmq_tlb_lrat_matchline;

