-- $Id$ 

-- this is not what you'd expect, but rather FAUmachine's own hacked
-- std_logic_1164 implementation. At least it makes a test-case :).
--
-- Copyright (C) 2007-2009 FAUmachine Team <info@faumachine.org>.
-- This program is free software. You can redistribute it and/or modify it
-- under the terms of the GNU General Public License, either version 2 of
-- the License, or (at your option) any later version. See COPYING.

PACKAGE std_logic_1164 IS
	TYPE std_logic IS ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-');
	TYPE std_logic_vector IS array ( integer range <> ) of std_logic;
	
	-- FIXME: functions don't work yet :(
	-- FIXME2: std_logic vs std_ulogic
	--FUNCTION to_bit (CONSTANT s : IN std_logic; 
	--		 CONSTANT xmap : IN bit := '0') 
	--RETURN bit;
	
	-- this is really a dirty hack!
	PROCEDURE to_bit(s : IN std_logic; xmap: IN integer; 
	                 result : out integer);

	--FIXME: we really want this...
	--function to_bitvector (constant s : in std_logic_vector; 
	--                       constant xmap : in bit := '0') 
	--	return bit_vector;

	-- but we get currently only this
	PROCEDURE to_bit_vector32(s : in std_logic_vector(1 to 32); 
				  xmap : in integer;
				  result : integer);

	--FIXME same as above
	--function to_stdlogicvector (constant b : in bit_vector) 
	--	return std_logic_vector;
	
	-- convert s to result
	PROCEDURE to_stdlogic_vector32(s : in integer; 
				       result : out std_logic_vector(1 to 32)
				       );

	-- these shouldn't exist at all
	PROCEDURE to_stdlogic_vector31(s : in integer; 
				       result : out std_logic_vector(31 downto 0)
				       );

	PROCEDURE to_stdlogic_vector3(s : in integer; 
				       result : out std_logic_vector(31 downto 0)
				       );

	PROCEDURE to_bit_vector31(s : in std_logic_vector(31 downto 0); 
				  xmap : in integer;
				  result : integer);

	PROCEDURE to_bit_vector3(s : in std_logic_vector(3 downto 0); 
				  xmap : in integer;
				  result : integer);

	PROCEDURE resolve_1 (s1 : in std_logic; 
			     s2 : in std_logic;
    			     r : out std_logic);

END PACKAGE std_logic_1164;

PACKAGE BODY std_logic_1164 IS
	--FUNCTION to_bit (CONSTANT s : IN std_logic; 
	--		 CONSTANT xmap : IN bit := '0') 
	--	 RETURN bit IS 

 	--BEGIN
	--	if ((s = '1') or (s = 'H')) then
	--		return 1;
	--	else
	--		if (s = '0') or (s = 'L') then
	--			return 0;
	--		else
	--			return xmap;
	--		end if;
	--	end if;
	--END to_bit;
	PROCEDURE to_bit(s : IN std_logic; xmap: IN integer; 
	                 result : out integer) IS 
	BEGIN
		if ((s = '1') or (s = 'H')) then
			result := 1;
		else
			if (s = '0') or (s = 'L') then
				result := 0;
			else
				result := xmap;
			end if;
		end if;
	END to_bit;


	PROCEDURE to_bit_vector32(s : in std_logic_vector(1 to 32); 
				  xmap : in integer;
				  result : integer) IS
	VARIABLE i : integer;
	VARIABLE m : integer := 1;
	BEGIN
		result := 0;
		
		FOR i IN 1 to 32 loop
			CASE s(i) IS
			WHEN 'H' =>
				result := result or m;
			WHEN '1' =>
				result := result or m;
			WHEN '0' =>
				-- don't do anything here :)
				result := result;
			WHEN 'L' =>
				-- don't do anything here :)
				result := result;
			WHEN others =>
				result := result or (m * xmap);
			END CASE;
		m := m * 2;
		END loop;
	END to_bit_vector32;
	

	PROCEDURE to_stdlogic_vector32(s : in integer; 
				       result : out std_logic_vector(1 to 32)
				       ) is
	VARIABLE i : integer;
	VARIABLE m : integer := 1;
	BEGIN
		for i in 1 to 32 loop
			if (s and m) = m then
				result(i) := '1';
			else
				result(i) := '0';
			end if;

		m := m * 2;
		END loop;
	END to_stdlogic_vector32;

	PROCEDURE to_stdlogic_vector31(s : in integer; 
				       result : out std_logic_vector(31 downto 0)
				       ) is
	VARIABLE i : integer;
	VARIABLE m : integer := 1;
	BEGIN
		for i in 0 to 31 loop
			if (s and m) = m then
				result(i) := '1';
			else
				result(i) := '0';
			end if;

		m := m * 2;
		END loop;
	END to_stdlogic_vector31;

	PROCEDURE to_stdlogic_vector3(s : in integer; 
				       result : out std_logic_vector(3 downto 0)
				       ) is
	VARIABLE i : integer;
	VARIABLE m : integer := 1;
	BEGIN
		for i in 0 to 3 loop
			if (s and m) = m then
				result(i) := '1';
			else
				result(i) := '0';
			end if;

		m := m * 2;
		END loop;
	END to_stdlogic_vector3;

	PROCEDURE to_bit_vector31(s : in std_logic_vector(31 downto 0); 
				  xmap : in integer;
				  result : integer) IS
	VARIABLE i : integer;
	VARIABLE m : integer := 1;
	BEGIN
		result := 0;
		
		FOR i IN 0 to 31 loop
			CASE s(i) IS
			WHEN 'H' =>
				result := result or m;
			WHEN '1' =>
				result := result or m;
			WHEN '0' =>
				-- don't do anything here :)
				result := result;
			WHEN 'L' =>
				-- don't do anything here :)
				result := result;
			WHEN others =>
				result := result or (m * xmap);
			END CASE;
		m := m * 2;
		END loop;
	END to_bit_vector31;

	PROCEDURE to_bit_vector3(s : in std_logic_vector(3 downto 0); 
				  xmap : in integer;
				  result : integer) IS
	VARIABLE i : integer;
	VARIABLE m : integer := 1;
	BEGIN
		result := 0;
		
		FOR i IN 0 to 3 loop
			CASE s(i) IS
			WHEN 'H' =>
				result := result or m;
			WHEN '1' =>
				result := result or m;
			WHEN '0' =>
				-- don't do anything here :)
				result := result;
			WHEN 'L' =>
				-- don't do anything here :)
				result := result;
			WHEN others =>
				result := result or (m * xmap);
			END CASE;
		m := m * 2;
		END loop;
	END to_bit_vector3;

   
    PROCEDURE resolve_1 (signal s1 : in std_logic; signal s2 : in std_logic;
    			 signal r : out std_logic) 
    IS
    BEGIN
    	if (s1 = 'U') or (s2 = 'U') then
		r := 'U';
	elsif (s1 = 'X') or (s2 = 'X') then
		r := 'X';
	else 
		case s1 is
		when '0' =>
			case s2 is 
			when '0' =>
				r := '0';
			when '1' =>
				r := 'X';
			when 'Z' =>
				r := '0';
			when 'W' =>
				r := '0';
			when 'L' =>
				r := '0';
			when 'H' =>
				r := '0';
			when '-' =>
				r := 'X';
			end case;
		when '1' =>
			case s2 is 
			when '0' =>
				r := 'X';
			when '1' =>
				r := '1';
			when 'Z' =>
				r := '1';
			when 'W' =>
				r := '1';
			when 'L' =>
				r := '1';
			when 'H' =>
				r := '1';
			when '-' =>
				r := 'X';
			end case;
		when 'Z' =>
			case s2 is 
			when '0' =>
				r := '0';
			when '1' =>
				r := '1';
			when 'Z' =>
				r := 'Z';
			when 'W' =>
				r := 'W';
			when 'L' =>
				r := 'L';
			when 'H' =>
				r := 'H';
			when '-' =>
				r := 'X';
			end case;
		when 'W' =>
			case s2 is 
			when '0' =>
				r := '0';
			when '1' =>
				r := '1';
			when 'W' =>
				r := 'W';
			when 'W' =>
				r := 'W';
			when 'W' =>
				r := 'W';
			when 'W' =>
				r := 'W';
			when 'X' =>
				r := 'X';
			end case;
		when 'L' =>
			case s2 is 
			when '0' =>
				r := '0';
			when '1' =>
				r := '1';
			when 'L' =>
				r := 'L';
			when 'W' =>
				r := 'W';
			when 'L' =>
				r := 'L';
			when 'W' =>
				r := 'W';
			when 'X' =>
				r := 'X';
			end case;
		when 'H' =>
			case s2 is 
			when '0' =>
				r := '0';
			when '1' =>
				r := '1';
			when 'L' =>
				r := 'H';
			when 'W' =>
				r := 'W';
			when 'L' =>
				r := 'W';
			when 'W' =>
				r := 'H';
			when 'X' =>
				r := 'X';
			end case;
		when '-' =>
			r := 'X';
		end case;
	end if;
    END resolve_1;



END std_logic_1164;
