paicore_behavioral/arbiter/arbiter_functions.vhdl
2025-07-15 14:39:47 -05:00

119 lines
No EOL
4.7 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.router_types.all;
package arbiter_functions is
function single_packet_rout_dir_det (
level : in integer;
pack_dest : in t_pos_addr;
chip_pos : in t_chip_addr;
core_pos : in t_core_addr;
is_upstream : in boolean
) return std_logic_vector;
function single_packet_parent_rout_dir_det (
level : in integer;
pack_dest : in t_pos_addr;
chip_pos : in t_chip_addr;
core_pos : in t_core_addr
) return std_logic_vector;
end package;
package body arbiter_functions is
function single_packet_parent_rout_dir_det(
level : in integer;
pack_dest : in t_pos_addr;
chip_pos : in t_chip_addr;
core_pos : in t_core_addr
) return std_logic_vector is
variable chip_d_x, chip_d_y : std_logic_vector(CHIP_ADDR_SIZE-1 downto 0);
variable chip_r_x, chip_r_y : std_logic_vector(CHIP_ADDR_SIZE-1 downto 0);
variable is_upstream : boolean;
begin
is_upstream := true;
chip_r_x := chip_pos.x;
chip_r_y := chip_pos.y;
chip_d_x := pack_dest.chip_pos.x;
chip_d_y := pack_dest.chip_pos.y;
if to_integer(unsigned(chip_d_y)) < to_integer(unsigned(chip_r_y)) then
return "10000000"; -- north
elsif to_integer(unsigned(chip_d_y)) > to_integer(unsigned(chip_r_y)) then
return "01000000"; -- south
elsif to_integer(unsigned(chip_d_x)) < to_integer(unsigned(chip_r_x)) then
return "00100000"; -- west
elsif to_integer(unsigned(chip_d_x)) > to_integer(unsigned(chip_r_x)) then
return "00010000"; -- east
else
return "000" & single_packet_rout_dir_det(
level, pack_dest, chip_pos, core_pos, is_upstream);
end if;
end function;
function single_packet_rout_dir_det (
level : in integer;
pack_dest : in t_pos_addr;
chip_pos : in t_chip_addr;
core_pos : in t_core_addr;
is_upstream : in boolean
) return std_logic_vector is
variable dest_x, dest_y, copy_x, copy_y : std_logic;
variable is_other_chip : boolean;
variable is_cousin_core : boolean;
variable needs_multicast : boolean;
begin
dest_x := pack_dest.core_pos.x(level-1);
dest_y := pack_dest.core_pos.y(level-1);
copy_x := pack_dest.copy_pos.x(level-1);
copy_y := pack_dest.copy_pos.y(level-1);
if level /= TOP_LEVEL then
is_other_chip := pack_dest.chip_pos.x /= chip_pos.x or
pack_dest.chip_pos.y /= chip_pos.y;
is_cousin_core := (pack_dest.core_pos.x(DEST_ADDR_SIZE-1 downto level) /=
core_pos.x(DEST_ADDR_SIZE-1 downto level)) or
(pack_dest.core_pos.y(DEST_ADDR_SIZE-1 downto level) /=
core_pos.y(DEST_ADDR_SIZE-1 downto level));
needs_multicast := FALSE;
for i in level to DEST_ADDR_SIZE-1 loop
needs_multicast := needs_multicast or (
pack_dest.copy_pos.x(i) = '1') or (
pack_dest.copy_pos.y(i) = '1');
end loop;
else
is_other_chip := FALSE;
needs_multicast := FALSE;
is_cousin_core := FALSE;
end if;
-- if it comes from upstream, it shouldn't go back to upstream
if (not is_upstream) and (is_other_chip or is_cousin_core or needs_multicast) then
return "10000";
elsif copy_x = '0' and copy_y = '0' then --unicast
if dest_x = '0' and dest_y = '0' then
return "01000";
elsif dest_x = '0' and dest_y = '1' then
return "00100";
elsif dest_x = '1' and dest_y = '0' then
return "00010";
else
return "00001";
end if;
elsif copy_x = '1' and copy_y = '0' then -- X 1 to 2 multicast
if dest_y = '0' then
return "01010";
else
return "00101";
end if;
elsif copy_x = '0' and copy_y = '1' then -- Y 1 to 2 multicast
if dest_x = '0' then
return "01100";
else
return "00011";
end if;
else -- 1 to 4 multicast
return "01111";
end if;
end function;
end package body;