--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:   01:27:32 04/20/2012
-- Design Name:   
-- Module Name:   C:/Core MPI/CORE_MPI/MPICORETEST.vhd
-- Project Name:  MPI_CORE_COMPONENTS
-- Target Device:  
-- Tool versions:  
-- Description:   
-- 
-- VHDL Test Bench Created by ISE for module: MPI_NOC
-- 
-- Dependencies:
-- 
-- Revision: 11 Juillet 2012
-- Revision 0.01 - File Created
-- Additional Comments : entité de test de l'environement MPSOC il est constitué d'une
--MAE simulant le processeur
-- Notes: 
-- 
-- 
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
library NocLib ;
--use IEEE.STD_LOGIC_ARITH.ALL;
--use IEEE.STD_LOGIC_UNSIGNED.ALL;
use NocLib.CoreTypes.all;
use work.Packet_type.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
USE ieee.numeric_std.ALL;
 
ENTITY PROCESSING_ELEMENT IS
-- entité du processeur du MPI
port (  clk     : in std_logic;
		reset   : in std_logic;
		ram_we  :  in std_logic; 
		ram_ena :  in std_logic;
		ram_enb :  in std_logic;
		ram_do : out std_logic_vector( downto ); --word - 1 downto 0
		ram_din : in std_logic_vector(word - 1 downto 0);--word - 1 downto 0
		ram_addra : out std_logic_vector(ADRLEN - 1  downto 0);-- ADRLEN - 1  downto 0
		ram_addrb : out std_logic_vector(ADRLEN - 1  downto 0);-- ADRLEN - 1  downto 0
		instruction_en : out std_logic;
		hold_request : in std_logic;
		hold_ack : out std_logic;
		ram_sel : out std_logic;
		lib_ready : in std_logic;
		lib_initialized  : in std_logic; 
		);
END PROCESSING_ELEMENT;
 
ARCHITECTURE behavior OF PROCESSING_ELEMENT IS 

	--données du programme PE
	signal SrcAdr0, SrcAdr1, destAdr0, destAdr1, Datalen : std_logic_vector(word - 1downto 0);--
	signal dpid,dpid_i : natural range 0 to 15;
 --signaux pour la gestion de la MAE
	type typ_mae is (InitApp,InitCompleted,writeptr, putdata,putdata2,putcompleted,getdata,getdata2,getcompleted,terminate,st_timeout);
	signal dcount : natural range 0 to 255:= 0; --permet de compter le packet de données envoyées
	signal count,count_i : natural range 0 to 15:=0;
--signal adresse,adresse_rd :natural range 0 to 65536;
	signal etPutGet : typ_mae;
	signal Ram_busy :std_logic:='0';
	--constant pour la construction du fichier
	-- ces lignes devront être commentées lors de l'assemblage final
BEGIN


dpid<=dpid_i;
 pPutGet : process(clk)
	
	variable bfill,destrank,pid,mport : natural range 0 to 15;
	variable fsrc,ret : natural range 0 to 15:=0;
	variable timeout : natural range 0 to 255;
	variable adrToset : std_logic_vector(15 downto 0);
	variable  adresse,adresse_rd :natural range 0 to 65536;
	begin
	 if (clk'event and clk ='1') then 
		if reset='1' then
				etputget<= InitApp;
				adresse:=0;
				adresse_rd:=0;
				timeout:=0;
				dcount<=0;
		else
	     case  etputget is
			
		  when InitApp =>
				--code pour Init ici
				--mettre mpi_init à l'adresse mpi 
				--initialisation du module mpi du pn
				ram_do <=MPI_INIT & x"0" ;
				fsrc:=1;
				adrToSet:=std_logic_vector(to_unsigned(core_init_adr,16));
				if ret/=fsrc then
				    dcount<=0;
					etputget<=writeptr;
					adresse:=core_base_adr+2;
				else
					adresse:=core_init_adr;
					etputget<= InitCompleted;
				end if;
		
		when writeptr =>
		 
				if PE_Hold_req = '0' then --s'assurer que le bus est disponible
					if dcount=0 then 
						ram_do <=AdrToSet(7 downto 0);
						dcount <=dcount+1;
						--adresse:=adresse+1; --prépare la prochaine écriture
					elsif dcount=1 then
						dcount <=dcount+1;
						adresse:=adresse+1; --prépare la prochaine écriture
						ram_do <=AdrToSet(15 downto 8);
					elsif dcount=2 then -- ce cycle permet juste de vider le tampon d'écriture en RAM
						ret:=fsrc;
						dcount<=0;
						timeout:=0;
						if fsrc=1 then
						etputget <= InitApp;
						elsif fsrc=2 then
						etputget <= putdata;
						elsif fsrc=3 then
						etputget <= getdata;
						else
						etputget <= start;
						end if;
						
					end if;
					
				end if;
		when InitCompleted =>
				if Lib_Init='1' then
					etputget <= putdata;
				end if;
		when putdata => --construire le packet pour le Put
				DestRank:=1;
				adresse_rd:=core_base_adr+Core_Rank2port_base+DestRank;
				timeout:=0;
				dcount<=0;
				fsrc:=2;
				adrToSet:=std_logic_vector(to_unsigned(core_put_adr,16));
				if ret/=fsrc then
					etputget<=writeptr;
					ret:=0;
				else
					etputget<= putdata2;
				end if;
				
		when putdata2 =>
		      if dcount<5 then
						dcount<=dcount+1;
						if dcount=0 then 
						adresse:=core_put_adr;
						ram_do <=MPI_PUT & std_logic_vector(to_unsigned(Dpid,4));
						elsif dcount=1 then 
						adresse:=core_put_adr+dcount;
						ram_do <=SrcAdr1 ;
						elsif dcount=2 then
						adresse:=core_put_adr+dcount;
						ram_do <=SrcAdr0 ;
						elsif dcount=3 then
						adresse:=core_put_adr+dcount;
						ram_do <=DestAdr1 ;
						elsif dcount=4 then
						adresse:=core_put_adr+dcount;
						ram_do <=DestAdr0 ;
						elsif dcount=5 then
						adresse:=core_put_adr+dcount;
						ram_do <=Datalen ;
						end if;
				else
						adresse:=core_base_adr+1;
						adresse_rd:=core_base_adr;
						ram_do <=x"01"; --instruction pulse enable;
						if ram_din(1)='1' then -- Instruction ack
							if PE_Hold_Req='0' then
								adresse:=core_base_adr+1;
								ram_do <=x"00"; --ramener le IPulse à 0;
								etPutGet<=putcompleted;
							else
								
							end if;
						end if;
				end if;
			
			when putcompleted =>
				adresse_rd:=core_put_adr+6;
				if ram_din(0)='1' then  --Put completed
					etPutGet<=GetData;
				end if;
			when getdata =>   --positionnement du mot de longueur des données
			   adresse:=core_get_adr;
				DestRank:=1;
				timeout:=0;
				dcount<=0;
					fsrc:=3;
				adrToSet:=std_logic_vector(to_unsigned(core_get_adr,16));
				if ret/=fsrc then
				
					etputget<=writeptr;
					ret:=0;
				else
					etputget<= getdata2;
				end if;
			    
				when getdata2 =>
					if dcount<5 then
						dcount<=dcount+1;
						if dcount=0 then 
							adresse:=core_get_adr;
						ram_do <=MPI_GET & std_logic_vector(to_unsigned(Dpid,4));
						adresse:=core_get_adr+dcount;
						ram_do <=SrcAdr1 ;
						elsif dcount=2 then
						adresse:=core_get_adr+dcount;
						ram_do <=SrcAdr0 ;
						elsif dcount=3 then
						adresse:=core_get_adr+dcount;
						ram_do <=DestAdr1 ;
						elsif dcount=4 then
						adresse:=core_get_adr+dcount;
						ram_do <=DestAdr0 ;
						elsif dcount=5 then
						adresse:=core_get_adr+dcount;
						ram_do <=Datalen;
						end if;
				    else
						adresse:=core_base_adr+1;
						adresse_rd:=core_base_adr;
						ram_do <=x"01"; --instruction pulse enable;
						if ram_din(1)='1' then -- Instruction ack
						etPutGet<=getcompleted;
						else
						
						end if;
				end if;
					
				when getcompleted =>
				adresse_rd:=core_get_adr+6;
				if ram_din(0)='1' then  --Put completed
				   if PE_Hold_Req='0' then
					adresse:=core_base_adr+1;
					ram_do <=x"00"; --ramener le IPulse à 0;
					etPutGet<=Terminate;
					else
						timeout:=timeout+1;
					end if;
				end if;	
					
						
			when terminate =>
			
		
					etputget<=start;
					
			when st_timeout =>
			  
			  --if ram_busy='1' then
				 etputget<=start;
			  --end if		
			  etputget<=start;
			end case;
			ram_addra <=STD_LOGIC_VECTOR(to_unsigned(adresse,16));
			ram_addrb <=STD_LOGIC_VECTOR(to_unsigned(adresse_rd,16));
		end if;   --reset='1'
	end if;
  end process pPutGet;	

majPutGet:process (etputget)

	begin
			case  etputget is
			when start =>
			        ram_we <='0';
					ram_ena<='0';
					ram_enb<='0';
					instruction_en<='0';

		 when fillmem =>
				   ram_we <='1';
					ram_ena<='1';
					
					ram_enb<='0';
					instruction_en<='0';
		 when nextfill =>
					ram_we <='1';
					ram_ena<='1';
					ram_enb<='0';
					instruction_en<='0';
	    when InitApp =>
				   ram_we <='1';
					ram_ena<='1';
					ram_enb<='0';
					instruction_en<='0';
		 when Initcompleted =>
			      instruction_en<='1';
		 when writeptr =>
					ram_we   <='1';   --écriture dans la RAM
					ram_ena <='1';
					
					ram_enb <='0';
			--		dcount<=dcount+1;
					
					instruction_en<='0';
					
			when putdata =>   --positionnement du mot de longueur des données
				--dcount<=0;
				srcadr0<=X"00";
				srcadr1<=X"01";
				destadr0<=X"00";
				destadr1<=X"02";
			    ram_we <='0';
				ram_ena<='0';
				 --lecture du n° de port de destination
				ram_enb<='1';
				datalen<=std_logic_vector(to_unsigned(50,8));
				dpid_i<=to_integer(unsigned(ram_din(3 downto 0))); --le port est situé ur les 4 bits de poids faible
				instruction_en<='0';
			when putdata2 =>
					ram_we   <='1';   --écriture dans la RAM
					ram_ena <='1';
					
					ram_enb <='0';
			--		dcount<=dcount+1;
					if dcount=5 then
					instruction_en<='1';
					else
					instruction_en<='0';
					end if;
			when putcompleted =>			
					ram_we   <='1';
					ram_ena <='1';
					  -- lecture du résultat
					ram_enb  <='1';
					instruction_en<='1';
			when getdata =>
				--dcount<=0;
				srcadr0<=X"00";
				srcadr1<=X"02";
				destadr0<=X"00";
				destadr1<=X"03";
				datalen<=std_logic_vector(to_unsigned(50,8));
				instruction_en<='0';	
			when getdata2 =>
				   ram_we   <='1';   --écriture dans la RAM
					ram_ena <='1';
					
					ram_enb <='0';
				--dcount<=dcount+1;
				   if dcount=5 then
						instruction_en<='1';
					else
						instruction_en<='0';
					end if;
			when getcompleted =>				
					ram_we   <='1';
					ram_ena <='1';
					  -- lecture du résultat
					ram_enb  <='1';
					instruction_en<='1';
			when terminate =>
			
				   ram_we <='0';
					ram_ena<='0';
					ram_enb<='0';
					instruction_en<='0';
			
			when st_timeout =>
				  ram_we <='0';
				  ram_ena<='0';
				  ram_enb<='0';
				  instruction_en <='0';
			end case;
end process majPutGet ;  

 hold:process (clk)
 begin
 if rising_edge(clk) then
	if reset='1' then
		hold_ack<='0';
	else
		if hold_request ='1' then
			ramsel<='1';
			pe_hold_ack<= '1';--not(ram_busy); --si la mémoire est occupé, forcé une libération
		else
			pe_hold_ack<='0';
			ramsel<='0';
		end if;
	end if;
 end if;
 end process hold;
END;
