Index: PROJECT_CORE_MPI/CORE_MPI/BRANCHES/v1.00/EX4_FSM.vhd
===================================================================
--- PROJECT_CORE_MPI/CORE_MPI/BRANCHES/v1.00/EX4_FSM.vhd	(revision 72)
+++ PROJECT_CORE_MPI/CORE_MPI/BRANCHES/v1.00/EX4_FSM.vhd	(revision 74)
@@ -55,5 +55,5 @@
 		Rec_Data : IN Typ_PortIO(0 to 3);
 		Snd_data : OUT Typ_PortIO(0 to 3);
-		Snd_Start : OUT std_logic;
+		Snd_Start : buffer std_logic;
 		Rec_Ack : OUT std_logic;       
 				   dma_wr_grant : in  STD_LOGIC;
@@ -111,5 +111,5 @@
 	type typ_receiv is (r_wait,r_dlen,r_drop,r_glen,r_data,r_pulse,r_end);
 	type typ_cmd is (cmdstart,cmdpost,cmdpostidle,cmdread,cmdlen,cmdglen,cmddata,cmdend,cmdtimeout);
-
+  type typ_mem16 is array(natural range <>) of std_logic_vector(15 downto 0);--
 		signal etsnd : typ_send;
 		signal etrec:typ_receiv;   --pour la machine à état de réception
@@ -126,4 +126,7 @@
 	signal tosend,tosend4 :std_logic_vector(Word-1 downto 0);
 	signal PeerStat : std_logic_vector(15 downto 0):=(others=>'0'); --état des autres Lib initialisées
+  signal SpawnReq,SpawnReq_Q : std_logic_vector(15 downto 0):=(others=>'0'); --état des autres HT qui ont appelés le Spawn	
+	signal Spawn_grp,Spawn_grp_Q :typ_mem16(0 to 3):=((others=>'0'),(others=>'0'),(others=>'0'),(others=>'0')); --un max de quatre groupes de fils est prévu
+	signal Grp_id,grp_id_i :natural range 0 to 3:=0; --id du groupe des HT fils
 	signal selector : std_logic_vector (2 downto 0); -- pour le MUX des signaux vers le port
 	--signaux pour les états des MAE
@@ -136,6 +139,10 @@
 	signal SpawnOn,SpawnInit :std_logic:='0'; --indique que le Spawn est activé
 	signal SpawnNbReq,SpawnNbAck,SpawnNBAck_i : natural range 0 to 15 :=0; --compte le nombre de requêtes et le nombre d'acquitement
-	signal SpawnCmd  :std_logic_vector(Word-1 downto 0);
+	signal SpawnNbReq_Q : natural range 0 to 15 :=0; --compte le nombre de requêtes et le nombre d'acquitement
+	signal SpawnCmd0,SpawnCmd1, SpawnCmd2 :std_logic_vector(Word-1 downto 0):=(others=>'0');
+	signal SpawnCmd0_Q,SpawnCmd1_Q, SpawnCmd2_Q :std_logic_vector(Word-1 downto 0):=(others=>'0');
 	signal SpawnDest :std_logic_vector(3 downto 0);
+	Signal Ht_Start,Ht_Start_i : natural range 0 to 15:=0;
+	Signal vPeerStat,vPeerStat_i : std_logic_vector(15 downto 0):=(others=>'0');
 	signal IsMain_i,Initialized_i,HCL_init: std_logic:='0';
 	signal DS_RDY ,BCast_Rdy,Send_RDY,CM_RDY:std_logic:='0';
@@ -150,5 +157,5 @@
 	--Signaux des résultats et de l'état
   signal PortNum_i,MyPort : std_logic_vector(3 downto 0);  -- 
-	signal NocMax : std_logic_vector(3 downto 0); -- Nombre de ports du réseau -1 ?
+	signal NocMax : std_logic_vector(3 downto 0):=(others=>'0'); -- Nombre de ports du réseau -1 ?
 	signal MyRank : std_logic_vector(3 downto 0) ; --rang du PE
 	signal AppSize_i:std_logic_vector(3 downto 0) ;--taille de l'application
@@ -162,9 +169,9 @@
 	signal Datalen : natural range 0 to 7:=0; --indique la longueur des données
 	--other outputs
-	signal StatAsked_i,RankAsked_i,EquFlag_i,MainResp_i,RankSent_i,Result_i:std_logic;
-	signal snd_start_i:std_logic;--version interne des signaux de sortie
+	signal StatAsked_i,RankAsked_i,EquFlag_i,MainResp_i,RankSent_i,Result_i:std_logic:='0';
+	signal snd_start_i:std_logic:='0';--version interne des signaux de sortie
    --signal BCast_Rdy_i : std_logic;
 	signal cdlen,dcount : natural range 0 to 255:=0; --longueur du paquet reçu par le process pcmd
-	signal timeout,timeout_i : natural range 0 to 1023:=0;
+	signal timeout,timeout_i : natural range 0 to 4095:=0;
 	signal PortStat : std_logic_vector(3 downto 0):=(others=>'0');
 	signal PeerPort : natural range 0 to 15:=0; -- désigne le port qui emet une requête
@@ -219,13 +226,23 @@
 		StatAsked<=StatAsked_i;
 		n<=n_i;
+		Ht_Start<=Ht_Start_i;
+		Grp_Id<=Grp_Id_i;
+		vPeerStat<=vPeerStat_i;
 		SpawnNbAck<=SpawnNbAck_i;
 		AppSize<=AppSize_i;
 		Ready<=Rdy;
 		snd_start<=snd_start_i;
+		SpawnNbReq_q<=SpawnNbReq;
+		SpawnReq_Q<=SpawnReq;
+		SpawnCmd0_Q<=SpawnCmd0;
+		SpawnCmd1_Q<=SpawnCmd1;
+		SpawnCmd2_Q<=SpawnCmd2;
+		Spawn_grp_q<=Spawn_grp;
 	end if;
 end process;
 
-  Init2_DECODE: process (stinit2, CmdReceived, EquFlag, MyPort, DS_RDY, MainResp, DataReceived, 
-  SpawnOn,Ram_NextAdress,PeerRTS,PortSTAT,dma_rd,dma_wr,Send_rdy,I_Send_rdy,rd_ok,wr_ok,Instruction)
+  Init2_DECODE: process (stinit2,n, CmdReceived, EquFlag, MyPort, DS_RDY, MainResp, DataReceived, 
+  SpawnOn,Ram_NextAdress,PeerRTS,PortSTAT,dma_rd,dma_wr,Send_rdy,I_Send_rdy,rd_ok,wr_ok,Instruction,
+  MainPort,PeerStat,SpawnCmd0,SpawnCmd1,SpawnCmd2,SpawnInit,BCast_rdy)
    variable nextr,nextadr : natural :=0;--to_integer(unsigned(Ram_NextAdress));
 	variable nport : natural range 0 to 15:=0;
@@ -466,5 +483,5 @@
 				RTS_cmd<='0';
 				RTS_I<='0';
-				CTR<='1';
+				CTR<=not MainResp;
 				ResultOut<=(others=>'0');
 				PortNum_i<=DataReceived(0)(3 downto 0); --adresse du Main Port
@@ -609,5 +626,5 @@
 				DS_ACK<=DS_RDY;
 				BCAST<='0';
-				CTR<='1';  --cette mise à 1 permet de ctrler la fin de réception
+				CTR<='0';  --cette mise à 1 permet de ctrler la fin de réception
 				rdy<='0';
 				ram_wr<=wr_ok;
@@ -620,8 +637,8 @@
 				dma_wr_request <=dma_wr;
 				RankAsked_i<='0';
-				if SpawnInit='1' then
-					ResultOut<=("01000000");--spawn completed
+				if n>=3 then
+					ResultOut<=("00000010");--spawn completed
 				else
-					ResultOut<=("00000010");--spawn message received 
+					ResultOut<=("00000000");--spawn message received 
 				end if;
 				
@@ -629,5 +646,5 @@
 		    RTS_cmd<='0';
 				--RTS_DAT<='1'; --à tester
-				RTS_I<='1'; -- pour le timing
+				RTS_I<=PeerRTS; -- pour le timing
 				Result_En<='0';
 				DS_ACK<='0';
@@ -637,15 +654,15 @@
 				ram_wr<=wr_ok;
 				ram_rd<=rd_ok;
-		      DataToSend(0)<=MPI_SPAWN & SpawnDest;
+		      DataToSend(0)<=SpawnCmd0;
           DataToSend(1)<="00000100";
-          DataToSend(2)<=PeerStat(7 downto 0);
-          DataToSend(3)<=SpawnCmd; -- SPAWN_LOAD & MyPort ;
+          DataToSend(2)<=SpawnCmd1;
+          DataToSend(3)<=SpawnCmd2; -- SPAWN_LOAD & MyPort ;
           Send_Ack<=Send_Rdy;
     				I_Send_Ack<=I_Send_rdy;
           RankAsked_i<='0';
 				if SpawnInit='1' then
-					ResultOut<=("01000000"); --spawn completed
+					ResultOut<=("10000000"); --spawn completed
 				else
-					ResultOut<=("00000010");--spawn message received 
+					ResultOut<=("01000000");--spawn in progress
 				end if;
 		When ErrSpawn =>
@@ -705,9 +722,10 @@
  --==================
    NEXT_STInit2_DECODE: process (stInit2,AppReq,Instruction_en, AppAck,PortNumFlag,EquFlag,MainResp,StatAsked,RankAsked,RankSent,CM_RDY, CmdReceived, 
-	BCast_Rdy, DS_RDY, DataReceived, Send_RDY,	I_Send_RDY,TimeOut,Dma_rd_grant,Dma_wr_grant,cpt,n,clk_cyl,IsMain_i,SpawnOn)
+	BCast_Rdy, DS_RDY, DataReceived,Ht_Start,vPeerStat, Send_RDY,	I_Send_RDY,TimeOut,Dma_rd_grant,Dma_wr_grant,cpt,n,clk_cyl,IsMain_i,SpawnOn,
+	Instruction,Hcl_Init,Spawn_done,mainport,PeerStat,PeerRTS,Rec_Data,SpawnInit,grp_id,SpawnNbReq,Ram_data_out,Spawn_grp,MyPort)
    variable InitTimeOut :natural:=0;
 	variable LastPort,Ht_hole : std_logic:='0';
-	variable i,htloc,ht_Start : natural range 0 to 15:=0;
-	variable vPeerStat : std_logic_vector(15 downto 0);
+	variable i,nbSpawn,htloc,Ht_Id : natural range 0 to 15:=0;
+	--variable vPeerStat : std_logic_vector(15 downto 0);
    variable vPortStat,nulvect : std_logic_vector(3 downto 0):="0000";	
 	variable tempval : std_logic_vector(Word-1 downto 0);
@@ -717,4 +735,14 @@
       --insert statements to decode next_state
       --below is a simple example
+		vPeerStat_i<=vPeerStat;
+		SpawnNbReq<=SpawnNbReq_q;
+		SpawnReq<=SpawnReq_q;
+		Ht_Start_i<=Ht_Start;
+		SpawnCmd0<=SpawnCmd0_Q;
+		SpawnCmd1<=SpawnCmd1_Q;
+		SpawnCmd2<=SpawnCmd2_Q;
+		for i in 0 to 3 loop
+		Spawn_grp(i)<=Spawn_grp_q(i);
+		end loop;
       case (stInit2) is
          
@@ -736,6 +764,6 @@
 							Next_stInit2 <=SendApp;
 						end if;
-					 elsif portNumFlag='1' and IsMain_i='0' then 
-						Next_stInit2 <=AskPeerStat; --recevoir les nouvelles données sur l'état d'initialisation
+					 elsif HCL_Init='1' and IsMain_i='0' then 
+						Next_stInit2 <=SendApp; --ignorer ce message simplement
 					else 
 						Next_stInit2 <=GetPortNum; -- initialiser la bibliothèque normalement
@@ -841,4 +869,5 @@
 									Next_stInit2<=GetPeerStat;
 									StatAsked_i<='1';
+									MainResp<='0';
 							   n_i<=0;
 							End if;		
@@ -857,5 +886,5 @@
 									 end if;	
 										
-							elsif TimeOut=800 then
+							elsif TimeOut=1800 then
 												--essayer de redemander les statistiques
 									Timeout_i<=0;	
@@ -927,4 +956,10 @@
 						TimeOut_i<=0;   -- prépare le traitement de la prochaine requête
 												-- d'attente des ports
+				  elsif Timeout=800 then
+				    assert true report "Impossible d'envoyer le rang"
+				    severity failure;
+				    timeout_i<=0;
+				  else 
+				    TimeOut_i<=TimeOut+1; 
 					end if;
 		When RegRank =>
@@ -1005,12 +1040,12 @@
 							if statAsked='1' then 
 							 -- Next_stInit2<=ReadNoc;
-							--  else
+							
 							Next_stInit2<=SendApp; --terminer l'application
 						  end if;
 						
-						elsif TimeOut_i=100 then
+						elsif TimeOut=100 then
 							Next_stInit2 <=EndInit;
 						else 
-							TimeOut_i<=TimeOut_i+1; 
+							TimeOut_i<=TimeOut+1; 
 						end if;
 					else
@@ -1026,23 +1061,34 @@
 		
 				if n=0 then
-					SpawnNbReq<=to_integer(unsigned(Instruction(3 downto 0))); -- sauver le nombre de HT à créer
+					ht_id:=to_integer(unsigned(rec_data(0)(3 downto 0)));
+					vPeerStat_i<=PeerStat; --récupérer la situation actuelle des tâches créées
 					if IsMain_i='1' and SpawnInit='0' then 
-							n_i<=1;
+					 SpawnNbReq<=to_integer(unsigned(Instruction(3 downto 0))); -- sauver le nombre de HT à créer
+ 
+					n_i<=1;
+					SpawnReq(ht_id)<='1'; --Note l'id de HT qui a appelé le Spawn
 					elsif IsMain_i='1' and SpawnInit='1'  then -- il faut envoyer les acquittements
-					vPeerStat:=PeerStat; --récupérer la situation actuelle des tâches créées
-					Ht_start:=0; --compte le nombre de tâches chargées
+					ht_id:=to_integer(unsigned(rec_data(0)(3 downto 0)));
+					Spawn_grp(grp_id)(ht_id)<='1'; --noter le port du Fils Spawné dans ce groupe
+					Ht_start_i<=0; --compte le nombre de tâches chargées
 							n_i<=6;
+					
 					else 
 					   if SpawnOn='1' then --if IsMain_i='0' then  -- il faut juste charger puis activer la tâche
 					     n_i<=7;
-					   end if;
+					    end if;
+					    assert true
+					   Report "SpawnLoad : Cas non prévu !"
+					  severity failure;
 					end if;
 				elsif n=1 then
-				ht_hole:='0';
-	L1:			for i in 0 to 7 loop
+				if PeerStat=SpawnReq then --tous les Hts ont appelés Spawn ?
+				ht_hole:='0';		
+	L1:			for i in 0 to 15 loop
 						if vPeerStat(i)='0' then
 							SpawnDest<=std_logic_vector(to_unsigned(i,4)); -- le port à activer
-							vPeerStat(i):='1';
-							Ht_Start:=Ht_Start+1;
+							SpawnCmd0<=MPI_SPAWN & std_logic_vector(to_unsigned(i,4));
+							vPeerStat_i(i)<='1';
+							Ht_Start_i<=Ht_Start+1;
 							Ht_Hole:='1'; -- une place a été trouvé
 						else
@@ -1053,9 +1099,14 @@
 					if Ht_hole='0' then -- toutes les tâches n'ont pas été créés
 						-- aller à la fin ! en signalant une erreur!
-						SpawnCMd<=Spawn_Err & "0001"; --erreur pas assez de ports sur le NoC
-						n_i<=7;
+						SpawnCMd2<=Spawn_Err & "0001"; --erreur pas assez de ports sur le NoC
+						n_i<=9;
 					else
 						n_i<=n+1;
-						SpawnCmd<=SPAWN_START & MyPort;
+						SpawnCmd1<=PeerStat(7 downto 0);
+						SpawnCmd2<=SPAWN_START & MyPort;
+					end if;
+					else --Tous les Hts n'ont pas appelé Spawn encore
+					  Next_stInit2<=SendApp; --on termine normalement
+					  n_i<=0;
 					end if;
 				elsif n=2 then
@@ -1069,5 +1120,5 @@
 				elsif n=4 then
 					if SpawnInit='0' then
-					if Ht_Start=SpawnNbReq then
+					if Ht_Start>=SpawnNbReq then
 						n_i<=n+1;
 					else
@@ -1075,47 +1126,68 @@
 					end if;
 					else
-						n_i<=6; -- passer au contact du HT suivant
+						n_i<=7; -- passer au contact du HT suivant
 					end if;
 				elsif n=5 then
-								-- donner le résultat du Spawn
-				Next_stinit2<=SendApp;
-				n_i<=0;
+								-- Aller à la fin le résultat du Spawn
+				
+				n_i<=10;
 				elsif n=6 then
+				  nbSpawn:=0;
+				  for i in 0 to 15 loop
+				      if Spawn_grp(grp_id)(i)='1' then
+				         nbSpawn:=nbSpawn+1;
+				       end if;
+				   end loop;
+				  if nbSpawn=SpawnNbReq then
+				  n_i<=n+1; --aller renvoyer les réponses
+				  else
+				    n_i<=10; --fin du Spawn
+				    
+				   end if;
+				elsif n=7 then
 				Ht_hole:='0';
-L2:			for i in 0 to 7 loop
-						if PeerStat(i)='1' then
+L2:			for i in 0 to 7 loop --for i in Ht_start to 7 loop
+						if i>=Ht_start then
+						if vPeerStat(i)='1' and Spawn_grp(grp_id)(i)='0' then  --on avertit les membres du groupe parent
+						  --mais pas ceux du groupe Fils !
 							SpawnDest<=std_logic_vector(to_unsigned(i,4)); -- le port à avertir
-							vPeerStat(i):='1';
-							Ht_Start:=Ht_Start+1;
+							SpawnCmd0<=MPI_ACK & std_logic_vector(to_unsigned(i,4));
+							vPeerStat_i(i)<='0';
+							Ht_Start_i<=i+1; -- le prochain Ht à prévenir 
 							Ht_Hole:='1'; -- Une tâche doit être avertie
-							n_i<=n+1;
 						else
 							Ht_hole:='0'; -- 
 						end if;
+						end if;
 						exit L2 when ht_hole='1';
 					end loop L2;
+					n_i<=n+1;
+			elsif n=8 then
 				 if Ht_hole='1' then --
-						-- aller à la fin ! en signalant une erreur!
-						SpawnCMd<=Spawn_COMP & "0001"; -- fin du Spawn
-						n_i<=2; --envoyer la la donnée sur le réseau
+						-- un HT existant à prévenir ! 
+						SpawnCmd1<=Spawn_grp(grp_id)(7 downto 0);
+						SpawnCMd2<=MPI_SPAWN & MyRank; -- fin du Spawn
+						n_i<=2; --envoyer la  donnée sur le réseau
+					elsif vpeerstat /=spawn_grp(grp_id) then --il ne reste plus de membres à prévenir ?
+              n_i<=7; --on est sorti mais ce n'est pas la fin
+
 					else -- fin du Spawn car tous ont été averti
-						n_i<=8;
-						
-					end if;
-				
-				
-		elsif Ismain_i='1' and SpawnInit='1' then
-			if SpawnNbAck+1=SpawnNbReq then
-					-- il faut envoyer un message à tous les noeuds pour avertir de la fin du Spawn
-					
-			else
-					SpawnNbAck_i<=SpawnNbAck+1;
-					Next_stInit2<=SendApp; --on attend le suivant
-			end if;
-		end if;
+						n_i<=10;
+						SpawnNbReq<=0;
+						SpawnReq<=(others=>'0');
+						vPeerStat_i<=(others=>'0');
+						grp_id_i<=grp_id+1; --incrementer le compteur de groupes************
+					end if;
+				elsif n=9 then
+				  assert true report "error in Spawn command"
+				   severity failure;
+				elsif n=10 then
+				  n_i<=0;
+				  Next_stInit2<=SendApp;
+				 end if;
 		
 	When SpawnApp=>
 	  	--Mise à jour du bit 6 du registre status du COre.
-		if n <3 then     
+		if n>=0 and n <4 then     
 			
 			dma_wr<='1';  --demander un accès exclusif au bus
@@ -1129,22 +1201,22 @@
 		  if DS_RDY='1' then ---
 		      if Datareceived(3)(7 downto 4)=SPAWN_START then
+		        n_i<=n+1;
 		       else
-		         n_i<=6; --erreur instruction incorrecte
+		         Next_stInit2<=ErrSpawn;
+		         n_i<=0; --erreur instruction incorrecte
 		        end if;
-			   if dma_rd_grant='1' then
-			       n_i<=n+1;
-			   end if;
+			   
 			   rd_ok<='1';
 			   wr_ok<='0';
 			end if;
-		elsif n=1 then
+		elsif n=1 or n=2 then
 			if dma_rd_grant='1' then
 				n_i<=n+1;
-				
+				tempval:=Ram_data_out;
 			end if;
 				rd_ok<='1';
 				wr_ok<='0';
-			
-		elsif n=2 then
+			 
+		elsif n=3 then
 				if dma_rd_grant='1' and dma_wr_grant='1' then
 					n_i<=n+1;
@@ -1159,16 +1231,22 @@
 					wr_ok<='0';
 				end if;
-		elsif n=3 then
+		elsif n=4 then
 		if spawninit='0' then
 		  Spawn_done<='1';
 		end if;
+		rd_ok<='0';
+		wr_ok<='0';
+		n_i<=0;
 		Next_stInit2<=EndInit;
 		end if;
 			
 		When ErrSpawn =>
+		  assert true
+		  report "Ex4/stInit2/SpawnApp:Erreur lors de Spawn"
+		  severity failure;
 			Next_stInit2<=Init;
 		When EndInit=>
 		  
-			
+			StatAsked_i<='0'; --reset de ces variables
 			Next_stInit2<=Init;
       end case;      
@@ -1232,5 +1310,5 @@
 	begin
 --				
-	if  rising_edge(clk) then 
+	
 	if reset='1' then
 		etrec<=r_wait;
@@ -1239,4 +1317,5 @@
 		bad_paquet:='0';
 	else
+	if  rising_edge(clk) then 
 			case  etrec is
 			when r_wait =>
@@ -1254,4 +1333,9 @@
 						bad_paquet:='0';
 						SpawnOn<='1'; --le spawn est actif
+				elsif Instruction_en='0' and CTR='0' and Hcl_init= '0' then
+				  --il faut éliminer ce paquet qui est inoportun !
+				  Bad_paquet:='1';
+				  etrec<=r_dlen; --il faut ignorer cette donnée et quitter
+					dcount:=1;
 				elsif CTR='1' then
 				if ptype=MPI_INIT or ptype=INIT_SETRANK or ptype=INIT_SEEKMAIN or ptype=INIT_REGISTER then 
@@ -1356,14 +1440,12 @@
 						
 			--rPort_out_rd_en <='0';
-			SpawnOn<='0'; -- annuler le signal de Spawn
-			if DS_ACK='1' or rtimeout> 30 or CTR='0' or bad_paquet='1' then 
+			
+			if DS_ACK='1' or rtimeout> 30 or (CTR='0' and SpawnOn='0') or bad_paquet='1' then 
 				DS_RDY<='0';
+				SpawnOn<='0';
 				etrec<=r_wait;
 			else
 				DS_RDY<=DS_RDY;
-			end if;
-			
-			
-			
+			end if;			
 			end case;
 		 end if;--reset='1'
@@ -1548,5 +1630,5 @@
 	begin
 	
-	if  rising_edge(clk) then
+	
 		if reset='1' then
 			etcmd<=cmdstart;
@@ -1554,4 +1636,5 @@
 	--		sorigport<=origport;
 		else
+		if  rising_edge(clk) then
 					case  etcmd is
 					when cmdstart =>
@@ -1723,6 +1806,7 @@
 i_send_val:process(HCL_Init,Send_RDY,RTS_I,Snd_Ack,I_send_ack,DataToSend,Bcast_rdy,Bcast)
 begin
+snd_start_i<=snd_start;
 if HCL_Init='1' then
- if RTS_I='1' and i_send_ack='0' then
+ if RTS_I='1' and snd_ack='0' then
   snd_start_i<='1';
  elsif i_send_ack='1' then
@@ -1741,4 +1825,7 @@
  end if;
  i_send_rdy<=send_rdy;
+ for i in 0 to 3 loop 
+ Snd_data(i)<=(others=>'0');
+ end loop;
 end if;
 end process;
