library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_misc.all;
library Unisim;
use Unisim.all;
---------------------------------------------------------------------------
-- Thread Manager Entity section
---------------------------------------------------------------------------
entity user_logic_hwtul is
port (
clock : in std_logic;
intrfc2thrd_status : in std_logic_vector(0 to 3);
intrfc2thrd_result : in std_logic_vector(0 to 31);
thrd2intrfc_opcode : out std_logic_vector(0 to 7);
thrd2intrfc_argument_one : out std_logic_vector(0 to 31);
thrd2intrfc_argument_two : out std_logic_vector(0 to 31)
);
end entity user_logic_hwtul;
---------------------------------------------------------------------------
-- Architecture section
---------------------------------------------------------------------------
architecture IMP of user_logic_hwtul is
---------------------------------------------------------------------------
-- Signal declarations
---------------------------------------------------------------------------
type hwtul_state is (
START,
IDLE,
WRITE_MEMORY_1,
WRITE_MEMORY_2,
WRITE_MEMORY_3,
WRITE_MEMORY_4,
EXIT_INIT,
EXIT_WAIT
);
signal current_state, next_state : hwtul_state := START;
signal argument, argument_next : std_logic_vector(0 to 31);
signal threadID, threadID_next : std_logic_vector(0 to 31);
signal argVal, argVal_next : std_logic_vector(0 to 31);
signal opcode, opcode_next : std_logic_vector(0 to 7);
signal argOne, argOne_next : std_logic_vector(0 to 31);
signal argTwo, argTwo_next : std_logic_vector(0 to 31);
-- user_status Constants
constant USER_STATUS_RESET : std_logic_vector(0 to 3) := x"1";
constant USER_STATUS_RUN : std_logic_vector(0 to 3) := x"2";
constant USER_STATUS_ACK : std_logic_vector(0 to 3) := x"4";
constant USER_STATUS_PAUSE : std_logic_vector(0 to 3) := x"8";
-- user_opcode Constants
constant OPCODE_NOOP : std_logic_vector(0 to 7) := x"00";
constant OPCODE_HTHREAD_EXIT : std_logic_vector(0 to 7) := x"01";
constant OPCODE_READ : std_logic_vector(0 to 7) := x"02";
constant OPCODE_WRITE : std_logic_vector(0 to 7) := x"03";
constant OPCODE_HTHREAD_SELF : std_logic_vector(0 to 7) := x"04";
constant OPCODE_HTHREAD_YIELD : std_logic_vector(0 to 7) := x"05";
constant OPCODE_HTHREAD_MUTEX_LOCK : std_logic_vector(0 to 7) := x"06";
constant OPCODE_HTHREAD_MUTEX_UNLOCK : std_logic_vector(0 to 7) := x"07";
constant OPCODE_HTHREAD_INTRASSOC : std_logic_vector(0 to 7) := x"08";
-- misc constants
constant Z32 : std_logic_vector(0 to 31) := (others => '0');
constant H32 : std_logic_vector(0 to 31) := (others => '1');
---------------------------------------------------------------------------
-- Begin architecture
---------------------------------------------------------------------------
begin -- architecture IMP
HWTUL_STATE_PROCESS : process (clock, argument_next,
opcode_next, argOne_next,
argTwo_next) is
begin
if (clock'event and (clock = '1')) then
argument <= argument_next;
opcode <= opcode_next;
argOne <= argOne_next;
argTwo <= argTwo_next;
argVal <= argVal_next;
threadID <= threadID_next;
thrd2intrfc_opcode <= opcode_next;
thrd2intrfc_argument_one <= argOne_next;
thrd2intrfc_argument_two <= argTwo_next;
if ( intrfc2thrd_status = USER_STATUS_RESET ) then
current_state <= IDLE;
else
current_state <= next_state;
end if;
end if;
end process HWTUL_STATE_PROCESS;
HWTUL_STATE_MACHINE : process (clock) is
begin
-- Default register assignments
next_state <= current_state;
opcode_next <= opcode;
argOne_next <= argOne;
argTwo_next <= argTwo;
argument_next <= argument;
threadID_next <= threadID;
argVal_next <= argVal;
-- The state machine
case current_state is
when START =>
--Set default values
opcode_next <= OPCODE_NOOP;
argOne_next <= Z32;
argTwo_next <= Z32;
next_state <= IDLE;
when IDLE =>
case intrfc2thrd_status is
when USER_STATUS_RUN =>
argument_next <= intrfc2thrd_result;
next_state <= WRITE_MEMORY_1;
when others =>
next_state <= IDLE;
end case;
---------------------------------------------------------
-- Write a zero value at argument + 4
---------------------------------------------------------
when WRITE_MEMORY_1 =>
--Prepare the data to write, and the address to write too
argTwo_next <= x"00000001";
argOne_next <= (argument + 4);
next_state <= WRITE_MEMORY_2;
when WRITE_MEMORY_2 =>
--Tell the HWTI to do the write
opcode_next <= OPCODE_WRITE;
next_state <= WRITE_MEMORY_3;
when WRITE_MEMORY_3 =>
--Wait for the HWTI to ACK the write request
if ( intrfc2thrd_status = USER_STATUS_ACK ) then
opcode_next <= OPCODE_NOOP;
next_state <= WRITE_MEMORY_4;
else
next_state <= WRITE_MEMORY_3;
end if;
when WRITE_MEMORY_4 =>
--Wait for the HWTI to tell us to RUN again
if ( intrfc2thrd_status = USER_STATUS_RUN ) then
next_state <= EXIT_INIT;
else
next_state <= WRITE_MEMORY_4;
end if;
---------------------------------------------------------
-- Exit
-- Initiate the call to the Thread Manager to indicate
-- this thread is done doing its work.
---------------------------------------------------------
when EXIT_INIT =>
argOne_next <= argVal;
opcode_next <= OPCODE_HTHREAD_EXIT;
next_state <= EXIT_WAIT_ACK;
when EXIT_WAIT_ACK =>
case intrfc2thrd_status is
when USER_STATUS_ACK =>
opcode_next <= OPCODE_NOOP;
next_state <= EXIT_WAIT;
when others =>
next_state <= EXIT_WAIT_ACK;
end case;
when EXIT_WAIT =>
next_state <= EXIT_WAIT;
when others =>
next_state <= IDLE;
end case;
end process HWTUL_STATE_MACHINE;
end architecture IMP;