@ -54,9 +54,6 @@ architecture behaviour of xics_icp is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    signal r, r_next : reg_internal_t;
 
					 
					 
					 
					    signal r, r_next : reg_internal_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    -- hardwire the hardware IRQ priority
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    constant HW_PRIORITY : std_ulogic_vector(7 downto 0) := x"80";
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    -- 8 bit offsets for each presentation
 
					 
					 
					 
					    -- 8 bit offsets for each presentation
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    constant XIRR_POLL : std_ulogic_vector(7 downto 0) := x"00";
 
					 
					 
					 
					    constant XIRR_POLL : std_ulogic_vector(7 downto 0) := x"00";
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    constant XIRR      : std_ulogic_vector(7 downto 0) := x"04";
 
					 
					 
					 
					    constant XIRR      : std_ulogic_vector(7 downto 0) := x"04";
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -207,12 +204,14 @@ use ieee.numeric_std.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					library work;
 
					 
					 
					 
					library work;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					use work.common.all;
 
					 
					 
					 
					use work.common.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					use work.utils.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					use work.wishbone_types.all;
 
					 
					 
					 
					use work.wishbone_types.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					use work.helpers.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					entity xics_ics is
 
					 
					 
					 
					entity xics_ics is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    generic (
 
					 
					 
					 
					    generic (
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        SRC_NUM    : integer range 1 to 256  := 16;
 
					 
					 
					 
					        SRC_NUM    : integer range 1 to 256  := 16;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        PRIO_BITS  : integer range 1 to 8    := 8
 
					 
					 
					 
					        PRIO_BITS  : integer range 1 to 8    := 3
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        );
 
					 
					 
					 
					        );
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    port (
 
					 
					 
					 
					    port (
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        clk          : in std_logic;
 
					 
					 
					 
					        clk          : in std_logic;
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -228,12 +227,16 @@ end xics_ics;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					architecture rtl of xics_ics is
 
					 
					 
					 
					architecture rtl of xics_ics is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    constant SRC_NUM_BITS : natural := log2(SRC_NUM);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    subtype pri_t is std_ulogic_vector(PRIO_BITS-1 downto 0);
 
					 
					 
					 
					    subtype pri_t is std_ulogic_vector(PRIO_BITS-1 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    type xive_t is record
 
					 
					 
					 
					    type xive_t is record
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        pri : pri_t;
 
					 
					 
					 
					        pri : pri_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    end record;
 
					 
					 
					 
					    end record;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    constant pri_masked : pri_t := (others => '1');
 
					 
					 
					 
					    constant pri_masked : pri_t := (others => '1');
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    subtype pri_vector_t is std_ulogic_vector(2**PRIO_BITS - 1 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    type xive_array_t is array(0 to SRC_NUM-1) of xive_t;
 
					 
					 
					 
					    type xive_array_t is array(0 to SRC_NUM-1) of xive_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    signal xives : xive_array_t;
 
					 
					 
					 
					    signal xives : xive_array_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -262,8 +265,15 @@ architecture rtl of xics_ics is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    end function;
 
					 
					 
					 
					    end function;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    function prio_pack(pri8: std_ulogic_vector(7 downto 0)) return pri_t is
 
					 
					 
					 
					    function prio_pack(pri8: std_ulogic_vector(7 downto 0)) return pri_t is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        variable masked : std_ulogic_vector(7 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    begin
 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        return pri8(PRIO_BITS-1 downto 0);
 
					 
					 
					 
					        masked := x"00";
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        masked(PRIO_BITS - 1 downto 0) := (others => '1');
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        if pri8 >= masked then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            return pri_masked;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            return pri8(PRIO_BITS-1 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    end function;
 
					 
					 
					 
					    end function;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    function prio_unpack(pri: pri_t) return std_ulogic_vector is
 
					 
					 
					 
					    function prio_unpack(pri: pri_t) return std_ulogic_vector is
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -276,8 +286,27 @@ architecture rtl of xics_ics is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            r(PRIO_BITS-1 downto 0) := pri;
 
					 
					 
					 
					            r(PRIO_BITS-1 downto 0) := pri;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        end if;
 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        return r;
 
					 
					 
					 
					        return r;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					   end function;
 
					 
					 
					 
					    end function;
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    function prio_decode(pri: pri_t) return pri_vector_t is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        variable v: pri_vector_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        v := (others => '0');
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        v(to_integer(unsigned(pri))) := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        return v;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    end function;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    -- Assumes nbits <= 6; v is 2^nbits wide
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    function priority_encoder(v: std_ulogic_vector; nbits: natural) return std_ulogic_vector is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        variable h: std_ulogic_vector(2**nbits - 1 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        variable p: std_ulogic_vector(5 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        -- Set the lowest-priority (highest-numbered) bit
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        h := v;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        h(2**nbits - 1) := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        p := count_right_zeroes(h);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        return p(nbits - 1 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    end function;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					-- Register map
 
					 
					 
					 
					-- Register map
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    --     0  : Config
 
					 
					 
					 
					    --     0  : Config
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -391,35 +420,33 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    end process;
 
					 
					 
					 
					    end process;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    irq_gen: process(all)
 
					 
					 
					 
					    irq_gen: process(all)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        variable max_idx : integer range 0 to SRC_NUM-1;
 
					 
					 
					 
					        variable max_idx : std_ulogic_vector(SRC_NUM_BITS - 1 downto 0);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        variable max_pri : pri_t;
 
					 
					 
					 
					        variable max_pri : pri_t;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					        variable pending_pri : pri_vector_t;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					        -- A more favored than b ?
 
					 
					 
					 
					        variable pending_at_pri : std_ulogic_vector(SRC_NUM - 1 downto 0);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					        function a_mf_b(a: pri_t; b: pri_t) return boolean is
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            variable a_i : unsigned(PRIO_BITS-1 downto 0);
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            variable b_i : unsigned(PRIO_BITS-1 downto 0);
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        begin
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            a_i := unsigned(a);
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            b_i := unsigned(b);
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            report "a_mf_b a=" & to_hstring(a) &
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                " b=" & to_hstring(b) &
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                " r=" & boolean'image(a < b);
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            return a_i < b_i;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        end function;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					    begin
 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        -- XXX FIXME: Use a tree
 
					 
					 
					 
					        -- Work out the most-favoured (lowest) priority of the pending interrupts
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					        max_pri := pri_masked;
 
					 
					 
					 
					        pending_pri := (others => '0');
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					        max_idx := 0;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        for i in 0 to SRC_NUM - 1 loop
 
					 
					 
					 
					        for i in 0 to SRC_NUM - 1 loop
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            if int_level_l(i) = '1' and a_mf_b(xives(i).pri, max_pri) then
 
					 
					 
					 
					            if int_level_l(i) = '1' then
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                max_pri := xives(i).pri;
 
					 
					 
					 
					                pending_pri := pending_pri or prio_decode(xives(i).pri);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                max_idx := i;
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					            end if;
 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        end loop;
 
					 
					 
					 
					        end loop;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        max_pri := priority_encoder(pending_pri, PRIO_BITS);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        -- Work out which interrupts are pending at that priority
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        pending_at_pri := (others => '0');
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        for i in 0 to SRC_NUM - 1 loop
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            if int_level_l(i) = '1' and xives(i).pri = max_pri then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					                pending_at_pri(i) := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        end loop;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        max_idx := priority_encoder(pending_at_pri, SRC_NUM_BITS);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        if max_pri /= pri_masked then
 
					 
					 
					 
					        if max_pri /= pri_masked then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            report "MFI: " & integer'image(max_idx) & " pri=" & to_hstring(prio_unpack(max_pri));
 
					 
					 
					 
					            report "MFI: " & integer'image(to_integer(unsigned(max_idx))) & " pri=" & to_hstring(prio_unpack(max_pri));
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        end if;
 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        icp_out_next.src <= std_ulogic_vector(to_unsigned(max_idx, 4));
 
					 
					 
					 
					        icp_out_next.src <= max_idx;
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        icp_out_next.pri <= prio_unpack(max_pri);
 
					 
					 
					 
					        icp_out_next.pri <= prio_unpack(max_pri);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    end process;
 
					 
					 
					 
					    end process;