---------------------------------------------------------------------------------- -- Company: -- Engineer: GAMOM -- -- Create Date: 14:44:36 03/07/2012 -- Design Name: -- Module Name: EX4_FSM - Behavioral -- Project Name: MPI_CORE_COMPONENTS -- Target Devices: SPARTAN 3E xc3s1200e -- Tool versions: -- Description: Ce module renferme les fonctions permettant d'initialiser la -- bibliothèque matériel MPI -- Dependencies: -- -- Revision: 25/juin/2012 au 24/Octobre/2012 -- Revision 0.03 - File updated -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values use IEEE.NUMERIC_STD.ALL; Library NocLib; use NoCLib.CoreTypes.all; use work.packet_type.all; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity EX4_FSM is Port ( Instruction : in STD_LOGIC_VECTOR (Word-1 downto 0); Instruction_En : in STD_LOGIC; clk : in STD_LOGIC; reset : in STD_LOGIC; ResultOut : out STD_LOGIC_VECTOR (Word-1 downto 0):=(others=>'0'); Result_En : out STD_LOGIC:='0'; Ready : out STD_LOGIC; --indique que le module est disponible NocSize : out STD_LOGIC_VECTOR(3 downto 0); PortId : out STD_LOGIC_VECTOR(3 downto 0):=(others=>'0'); AppRank : out STD_LOGIC_VECTOR(3 downto 0):=(others=>'0'); AppSize : out STD_LOGIC_VECTOR(3 downto 0):=(others=>'0'); IsMain : out STD_LOGIC; I_fifo_full :in STD_LOGIC; --instruction fifo I_fifo_wr_en: out STD_LOGIC;--instruction fifo Write enable I_fifo_data_in :out STD_LOGIC_vector(Word-1 downto 0); --instruction fifo data Initialized : out STD_LOGIC; Snd_Ack : IN std_logic; Rec_Rdy : IN std_logic; Rec_Data : IN Typ_PortIO(0 to 3); Snd_data : OUT Typ_PortIO(0 to 3); Snd_Start : buffer std_logic; Rec_Ack : OUT std_logic; dma_wr_grant : in STD_LOGIC; dma_wr_request : out STD_LOGIC; dma_rd_grant : in STD_LOGIC; dma_rd_request : out STD_LOGIC; ram_rd : out std_logic; ram_wr : out std_logic; ram_address : out std_logic_vector(ADRLEN-1 downto 0);--accès au stockage Ram_data_in : out STD_LOGIC_VECTOR (Word-1 downto 0); Ram_data_out : in STD_LOGIC_VECTOR (Word-1 downto 0); AppAck : in STD_LOGIC; AppReq : in STD_LOGIC; port_in_cmd_en : out STD_LOGIC:='0'; port_in_wr_en : out STD_LOGIC:='0'; port_in_empty : in STD_LOGIC; port_in_full : in STD_LOGIC; port_in_data : out STD_LOGIC_VECTOR (Word-1 downto 0):=(others=>'-'); port_out_data : in STD_LOGIC_VECTOR (Word-1 downto 0); port_out_rd_en : out STD_LOGIC:='0'; port_out_data_available : in STD_LOGIC); end EX4_FSM; architecture Behavioral of EX4_FSM is COMPONENT SetBit PORT( clk : IN std_logic; reset : IN std_logic; BitNum : IN std_logic_vector(0 to 2); BitVal : IN std_logic; dma_wr_grant : IN std_logic; dma_rd_grant : IN std_logic; Ram_data_in : IN std_logic_vector(7 downto 0); dma_wr_request : OUT std_logic; dma_rd_request : OUT std_logic; ram_rd : OUT std_logic; ram_wr : OUT std_logic; ram_address : OUT std_logic_vector(15 downto 0); Ram_data_out : OUT std_logic_vector(7 downto 0) ); END COMPONENT; Type Ar_MPIPort_In is array (positive range <>) of Typ_MPIPort_in; Type Ar_MPIPort_out is array (positive range <>) of Typ_MPIPort_out; --MAE pour emission de init --type init1_type is (init,NocSize,InitToNoc,NextPort,EndBCast); -- MAE pour affectation des rangs aux différentes librairies MPI type init2_type is (init,GetPortNum,DecodeData,IsPortZero,SeekMain1,SeekMain2,StoreMain,SetMainFlag,ReadNoc,GetMainReq,StoreRank,NewRank,SendRank,RegRank,SendPeerStat,AskPeerStat,GetPeerStat,SendApp,SpawnApp,SpawnLoad,ErrSpawn,EndInit); -- MAE pour réception de init depuis le réseau; type init3_type is (init,GetNocSize,ReadInitHead,StorePort,EndInit); type typ_send is (s_init,s_head,s_len,s_len2,s_data,s_end); 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 signal etcmd :typ_cmd; --pour la machine à état de commande signal IS_state,next_Is_state : natural range 0 to 3:=0; -- signal stInit1, next_stInit1 : init1_type; signal stInit2, next_stInit2 : init2_type; --signal stInit3, next_stInit3 : init3_type; --signaux pour l'interface avec les ports signal cport_in_wr_en,sport_in_wr_en:std_logic; signal cport_out_rd_en,rport_out_rd_en:std_logic; signal rdy:std_logic:='0'; --signal busy/ready signal tosend,tosend4 :std_logic_vector(Word-1 downto 0); signal PeerStat,PeerStat_i : 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 signal NocSizeOk,PortCountFlag : std_logic; signal PortNumFlag,PortNumFlag_i,EquFlag,EquFlag_i,MainResp: std_logic:='0'; signal StatAsked,RankAsked,RankSent:std_logic; signal nextr,nextr_i : natural :=0; signal RTS_cmd,RTS_dat,RTS_I,CTR,BCast,Send_Ack,DS_Ack,CM_Ack:std_logic:='0'; signal I_Send_Ack,I_Send_Rdy:std_logic:='0'; signal Rcv_On,Snd_On,Cmd_On : std_logic:='0'; --status des MAE d'envoie et de réception 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 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,IsMain1,Initialized_i,HCL_init,HCL_Init_i: std_logic:='0'; signal DS_RDY ,BCast_Rdy,Send_RDY,CM_RDY:std_logic:='0'; signal ExecTime_out:std_logic; --signaux de gestion de la RAM signal Ram_Next_Address : std_logic_vector(ADRLEN-1 downto 0):=std_logic_vector(to_unsigned(Core_BASE_ADR+CORE_Rank2port_BASE,16)); signal Ram_NExt_Address_i :std_logic_vector(ADRLEN-1 downto 0):=std_logic_vector(to_unsigned(Core_BASE_ADR+CORE_Rank2port_BASE,16)); signal n,n_i:natural range 0 to 15 :=0; signal n0,n0_i:natural range 0 to 7:=0; signal DataToRam : std_logic_vector(Word-1 downto 0) ; signal dma_rd,dma_wr,rd_ok ,wr_ok:std_logic:='0'; --Signaux des résultats et de l'état signal PortNum_i,PortNum,MyPort : std_logic_vector(3 downto 0); -- signal NocMax ,NocMax_i: 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,AppSize1:std_logic_vector(3 downto 0) ;--taille de l'application signal Spawn_done,Spawn_done_i:std_logic:='0'; --indique que le Spawn a été effectué signal MainPort,MainPort_i : std_logic_vector(3 downto 0) ; --Port de la lib main signal NextRank,NextRank_i : std_logic_vector(3 downto 0):=(others=>'0'); --utiliser pour gérer les affectations de rangs MPI signal Data_To_Send,Data_to_send_i : Typ_PortIo(0 to 3):=((others=>'0'),(others=>'0'),(others=>'0'),(others=>'0')); -- permet d'empiler les données à envoyer signal RankToPort :Typ_PortIo(0 to 15);--permet d'associer un port réseau à chaque rang signal CmdReceived : Typ_PortIO(0 to 3):=((others=>'0'),(others=>'0'),(others=>'0'),(others=>'0')); signal DataReceived : Typ_PortIO(0 to 3):=((others=>'0'),(others=>'0'),(others=>'0'),(others=>'0')); signal Datalen,DataLen_i : natural range 0 to 7:=0; --indique la longueur des données --other outputs signal StatAsked_i,RankAsked_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 4095:=0; signal PortStat,PortStat_i : std_logic_vector(3 downto 0):=(others=>'0'); signal PeerPort,PeerPort_i : natural range 0 to 15:=0; -- désigne le port qui emet une requête signal PeerRTS,PeerRTS_i,PeerCTR:std_logic:='0'; signal cpt,cpt_peer : natural range 0 to 31:=0; --compteur pour le nombre de HT initialisés signal clk_cyl,clk_cyl_i : natural range 0 to 15:=0; begin --======================================================================================= --fonctions du module --======================================================================================= --======================================================================================= -- Inst_SetBit: SetBit PORT MAP( -- clk => clk, -- reset => reset , -- ce => cmd, -- BitNum => , -- BitVal => '1', -- dma_wr_grant => dma_wr_grant , -- dma_wr_request => dma_wr_request, -- dma_rd_grant => dma_rd_grant, -- dma_rd_request => dma_rd_request, -- ram_rd => ram_rd, -- ram_wr => ram_wr, -- ram_address => , -- Ram_data_in => Ram_data_in, -- Ram_data_out => Ram_data_out -- ); -- Gestion de l'initialisation du Core MPI sync_Init2 : process (clk,reset) begin if reset='1' then stinit2<=init; StatAsked<='0'; MyPort<=(others=>'0'); NextRank<=(others =>'0'); elsif rising_edge(clk) then stinit2<=next_stinit2; IS_State<=Next_IS_State; n0<=n0_i; --ajout des autres affectations ici Ram_Next_Address<=Ram_Next_Address_i; PortNumFlag<=PortNumFlag_i; RankAsked<=RankAsked_i; RankSent<=RankSent_i; AppRank<=MyRank; timeout<=timeout_i; cpt<=cpt_peer; clk_cyl<=clk_cyl_i; NextRank<=NextRank_i; StatAsked<=StatAsked_i; MainResp<=MainResp_i; AppSize1<=AppSize_i; n<=n_i; Ht_Start<=Ht_Start_i; Grp_Id<=Grp_Id_i; vPeerStat<=vPeerStat_i; SpawnNbAck<=SpawnNbAck_i; PortStat<=PortStat_i; EquFlag<=EquFlag_i; --IsMain1<=IsMain_i; if ismain_i='1' then IsMain1<='1'; else IsMain1<=IsMain1; end if; if stInit2=DecodeData then MyPort<=Cmdreceived(2)(3 downto 0); end if; if stInit2=StoreRank and ExecTime_Out='1' then MyRank<=MyPort; elsif stInit2=StoreRank then MyRank<=DataReceived(2)(3 downto 0); elsif stInit2=SetMainFlag then MyRank<=MyPort; end if; 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; PeerRTS<=PeerRTS_i; PortNum<=PortNum_i; Spawn_done<=Spawn_done_i; HCL_init<=Hcl_init_i; PeerStat<=PeerStat_i; DataLen<=DataLen_i; MainPort<=MainPort_i; Nextr<=NextR_i; NocMax<=NoCMax_i; PeerPort<=PeerPort_i; grp_id<=grp_id_i; for i in 0 to 3 loop data_to_send(i)<=data_to_send_i(i); end loop; end if; end process; AppSize<=AppSize1; Init2_DECODE: process (stinit2,n, CmdReceived, EquFlag, MyPort, DS_RDY, MainResp, DataReceived, SpawnOn,Ram_Next_Address,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 nextadr : natural :=0;--to_integer(unsigned(Ram_Next_Address)); variable nport : natural range 0 to 15:=0; begin for i in 0 to 3 loop data_to_send_i(i)<=data_to_send(i); end loop; PortNum_i<=PortNum; PortNumFlag_i<=PortNumFlag; PortID<=MyPort; PeerPort_i<=PeerPort; NocMax_i<=NoCMax; NextRank_i<=NextRank; MainPort_i<=MainPort; PeerStat_i<=PeerStat; EquFlag_i<=EquFlag; RankAsked_i<=RankAsked; NextR_i<=NextR; Ram_Next_Address_i<=Ram_Next_Address; Ram_address<=(others=>'1'); Ram_data_in<=(others=>'1'); dma_rd_request<='0'; dma_wr_request<='0'; Initialized_i<='0'; rdy<='0'; ram_rd<='0'; ram_wr<='0'; I_Send_ack<='0'; IsMain_i<='0'; send_ack<='0'; DataLen_i<=0; Case stInit2 is When Init => RTS_cmd<='0'; --RTS_dat<='0'; RTS_I<='0'; BCast<='0'; Result_En<='0'; Initialized_i<='0'; CM_Ack <='0'; CTR<='0' ; DS_ACK<='0'; Send_Ack<='0'; ram_wr<='0'; rdy<='1';--le module est disponible ResultOut<=(others=>'0'); if PortNumFlag='1' and IsMain1='1' then PortNum_i<=Instruction(3 downto 0); else PortNum_i<=(others=>'-'); end if; EquFlag_i<='0'; RankAsked_i<='0'; dma_wr_request<='0'; dma_rd_request<='0'; When GetPortNum => RTS_cmd<='1'; RTS_I<='0'; Result_En<='0'; Initialized_i<='0'; BCast<='0'; --réalise un envoie non collectif CM_Ack<='0'; -- les données sont maintenant attendues CTR<='0' ; data_to_send_i(0)<=X"0" & GETPORTID; DS_ACK<='0'; Send_Ack<='0'; ram_wr<='0'; rdy<='0'; IsMain_i<='0'; ResultOut<=(others=>'0'); PortNum_i<=(others=>'-'); RankAsked_i<='0'; dma_wr_request<='0'; When DecodeData => EquFlag_i<=(All_zeros(Cmdreceived(2)(3 downto 0))); RTS_cmd<='0'; RTS_I<='0'; BCast<='0'; Result_En<='0'; CM_Ack <='1'; --les données ont été reçues --MyPort<=Cmdreceived(2)(3 downto 0); PortNum_i<=Cmdreceived(2)(3 downto 0); --récupère les valeurs de port PeerPort_i<=To_integer(unsigned(Cmdreceived(2)(3 downto 0))); NocMax_i<=Cmdreceived(2)(7 downto 4); -- et la taille du réseau PortNumFlag_i<='1'; -- le numéro du port est maintenant connu CTR<='0' ; DS_ACK<='0'; Send_Ack<='0'; ram_wr<='0'; rdy<='0'; RankAsked_i<='0'; ResultOut<=(others=>'0'); dma_wr_request<='0'; When IsPortZero => --Ce port est-il le n° 0 du NoC ? BCast<='0'; Result_En<='0'; RTS_cmd<='0'; RTS_I<='0'; NextRank_i<="0001"; -- le prochain rang à affecter sera le n° 1 nextr_i<=1; IsMain_i<=EquFlag; --MyRank<="0000"; MainPort_i<="0000"; --MainAdr<="0000"; -- le port 0 est le main Lib par défaut; CTR<='0' ; DS_ACK<='0'; ram_wr<='0'; rdy<='0'; RankAsked_i<='0'; ResultOut<=(others=>'0'); dma_wr_request<='0'; When SeekMain1 => -- recherche de la lib main RTS_cmd<='0'; --RTS_DAT<='1'; RTS_I<='1'; CTR<='1' ; -- prêt à recevoir les données Clear To Receive DS_ACK<='0'; --les données sont attendus Send_Ack<=BCast_rdy; I_Send_Ack<=BCAst_rdy; data_to_send_i(0)<=MPI_INIT & MyPort ; data_to_send_i(1)<="00000100"; -- la longueur du packet =4 data_to_send_i(2)<="0000" & MyPort; --propose sa propre adresse data_to_send_i(3)<=INIT_SEEKMAIN & MyPort ; DataLen_i<=4; BCast<='1'; Result_En<='0'; Initialized_i<='0'; ram_wr<='0'; rdy<='0'; ResultOut<=(others=>'0'); RankAsked_i<='0'; dma_wr_request<='0'; When SeekMain2 => -- recherche de la lib main RTS_cmd<='0'; RTS_I<='0'; CTR<='1' ; -- prêt à recevoir les données Clear To Receive DS_ACK<= DS_RDY; --les données sont acquittées aussitôt reçues Send_Ack<=BCast_rdy; -- data_to_send_i(0)<=INIT_SEEKMAIN & MyPort ; -- data_to_send_i(1)<="00000011"; -- la longueur du packet =3 -- data_to_send_i(2)<="0000" & MyPort; --propose sa propre adresse -- DataLen<=3; BCast<='0'; Result_En<='0'; Initialized_i<='0'; ram_wr<='0'; rdy<='0'; ResultOut<=(others=>'0'); EquFlag_i<='0'; RankAsked_i<='0'; dma_wr_request<='0'; When StoreMain => -- la Main Lib est une autre BCAST<='0'; Result_En<='0'; IsMain_i<='0'; Initialized_i<='0'; DS_ACK<=DS_RDY; Send_Ack<='0'; RTS_cmd<='0'; RTS_I<='0'; CTR<=not(MainResp); -- essayer de recevoir tant que le main n'a pas répondu ram_wr<='1'; rdy<='0'; ResultOut<=(others=>'0'); RankAsked_i<='0'; EquFlag_i<='0'; MainPort_i<=DataReceived(0)(3 downto 0); ram_address<= STD_logic_vector(to_unsigned(Core_init_adr+1,16)); ram_data_in<=DataReceived(0)(3 downto 0)& DataReceived(2)(3 downto 0); --MainPort & MyRank dma_wr_request<= '0'; ---pas très sûr When AskPeerStat => -- Interroge les données d'initialisation RTS_cmd<='0'; if n=0 then --RTS_DAT<='0'; --on peut envoyer les données RTS_I<='1'; else --RTS_DAT<='0'; --on désactive l'envoie des données RTS_I<='0'; end if; CTR<='0' ; -- prêt à recevoir les données Clear To Receive DS_ACK<='0'; --les données sont attendus I_Send_Ack<=I_Send_rdy; Send_Ack<=Send_rdy; data_to_send_i(0)<=MPI_INIT & MainPort ; data_to_send_i(1)<="00000100"; -- la longueur du packet =4 data_to_send_i(2)<="0000" & MyPort; --indique sa propre adresse data_to_send_i(3)<=INIT_STAT & MyPort ; DataLen_i<=4; BCast<='0'; Result_En<='0'; ram_wr<='0'; rdy<='0'; ResultOut<=(others=>'0'); EquFlag_i<='0'; RankAsked_i<='0'; dma_wr_request<='0'; When SetMainFlag => -- Cette Lib est la Main Lib if (Datareceived(3)(7 downto 4) = INIT_SEEKMAIN) then RankAsked_i<='1'; else RankAsked_i<='0'; end if; RTS_cmd<='0'; Initialized_i<='0'; RTS_I<='0'; BCast<='0'; IsMain_i<='1'; Result_En<='0'; --MyRank<="0000"; MainPort_i<="0000"; PeerStat_i(0)<='1'; --la main lib est initialisée CTR<='1'; DS_ACK<='0'; ram_wr<='1'; rdy<='0'; ResultOut<=(others=>'0'); EquFlag_i<='0'; ram_address<= STD_logic_vector(to_unsigned(Core_init_adr+1,16)); ram_data_in<=(others =>'0'); -- le port vaut 0 et la mainlib est aussi à 0 dma_wr_request<='1'; When ReadNoc => if (Datareceived(3)(7 downto 4) = INIT_SEEKMAIN) then RankAsked_i<='1' ; else RankAsked_i<='0'; end if; ram_wr<='0'; -- pas d'écriture en RAM rdy<='0'; BCast<='0'; DS_ACK<='0'; --IsMain<='0'; Result_En<='0'; RTS_cmd<='0'; RTS_I<='0'; CTR<='1'; ResultOut<=(others=>'0'); PortNum_i<=DataReceived(2)(3 downto 0); -- le port qui demande un rang; PeerPort_i<= To_integer(unsigned(DataReceived(2)(3 downto 0))); --EquFlag<='1'; dma_wr_request<='0'; When GetMainReq => --RankAsked_i<='1'; ram_wr<='0'; -- pas BCast<='0'; DS_ACK<='1'; Result_En<='0'; RTS_cmd<='0'; RTS_I<='0'; CTR<='1'; ResultOut<=(others=>'0'); PortNum_i<=DataReceived(0)(3 downto 0); -- le port qui demande un rang; EquFlag_i<='1'; dma_wr_request<='0'; When GetPeerStat => --RankAsked_i<='1'; ram_wr<='0'; -- pas BCast<='0'; DS_ACK<=DS_RDY; Result_En<='0'; RTS_cmd<='0'; RTS_I<='0'; CTR<=not MainResp; ResultOut<=(others=>'0'); PortNum_i<=DataReceived(0)(3 downto 0); --adresse du Main Port PeerStat_i(7 downto 0)<=DataReceived(2); -- état des initialisations EquFlag_i<='0'; dma_wr_request<=dma_wr; ram_wr<=wr_ok; rdy<='0'; ram_rd<=rd_ok; Ram_Next_Address_i<= STD_logic_vector(to_unsigned(CORE_Init_Adr+2,ADRLEN)); --incr_vec(Ram_Next_Address,'1'); ram_address<=Ram_Next_Address; -- ram_data_in<=DataReceived(2); --enregistrer les ports actifs When NewRank => nport:=to_integer(Unsigned(PortNum)); --port ayant sollicité le rang nextr_i<=to_integer(unsigned(nextrank)); if PeerStat(nport)='0' then -- si le rang n'a pas encore été affecté à ce port nextrank_i<=incr_vec(nextrank,'1'); RankToPort(to_integer(unsigned(nextrank)))<="0000" & PortNum; NextAdr:=NextAdr+1; end if; data_to_send_i(0)<=MPI_INIT & PortNum ; data_to_send_i(1)<="00000100"; data_to_send_i(2)<="0000" & NextRank; --ici c'est la valeur avant incrémentation ! data_to_send_i(3)<=INIT_SETRANK & PortNum ; PeerStat_i(nport)<='1'; -- mise à jour du status DataLen_i<=4; BCast<='0'; DS_ACK<='0'; Result_En<='0'; EquFlag_i<='1'; RTS_cmd<='0'; RTS_I<='1'; CTR<='0' ; ram_wr<='0'; rdy<='0'; RankAsked_i<='1'; ResultOut<=(others=>'0'); dma_wr_request<='0'; When SendRank => BCast<='0'; Result_En<='0'; EquFlag_i<='1'; RTS_I<='1'; DataLen_i<=4; RTS_cmd<='0'; DS_ACK<='0'; Send_Ack<='0'; CTR<='0' ; ram_wr<='0'; Ram_Next_Address_i<= STD_logic_vector(to_unsigned(CORE_RANK_ADR+Nextr-1,16)); ResultOut<=(others=>'0'); RankAsked_i<='1'; dma_wr_request<='0'; When RegRank => RankAsked_i<='0'; CTR<='1' ; -- continuer à recevoir les données du NoC Result_En<='0'; RTS_cmd<='0'; DS_ACK<='0'; Send_Ack<=Send_RDY; I_Send_ack<=i_send_rdy; Rts_I<='0'; BCast<='0'; EquFlag_i<='1'; ram_wr<='1'; Ram_Next_Address_i<= STD_logic_vector(to_unsigned(CORE_RANK_ADR+Nextr-1,16)); --incr_vec(Ram_Next_Address,'1'); ram_address<=Ram_Next_Address; -- le rang qui a été envoyé; -- "le motif 0001 indique juste que le port est bien activé ram_data_in<="0001" & PortNum; --enregistrer le port qui a fait la demande en RAM ResultOut<=(others=>'0'); dma_wr_request<='1'; When SendPeerStat => BCast<='0'; Result_En<='0'; EquFlag_i<='0'; RTS_I<=PeerRTS; RTS_cmd<='0'; DS_ACK<='0'; data_to_send_i(0)<=MPI_INIT & PortStat ; data_to_send_i(1)<="00000100"; data_to_send_i(2)<=PeerStat(7 downto 0); data_to_send_i(3)<=INIT_REGISTER & MyPort ; Send_Ack<=Send_Rdy; I_Send_Ack<=I_Send_Rdy; CTR<='0' ; ram_wr<='0'; rdy<='0'; ResultOut<=(others=>'0'); RankAsked_i<='1'; dma_wr_request<='0'; Initialized_i<='1'; When StoreRank => --le processus qui écoute le Port et qui --stoke les adresses des autres bib va gérer le stockage du rang BCAST<='0'; DS_ACK<='1'; Send_Ack<='0'; RTS_cmd<='0'; EquFlag_i<='0'; RTS_I<='0'; CTR<='0'; Result_En<='0'; if ExecTime_out='1' then MainPort_i<="0000"; --MyRank<=MyPort; initialized_i<='0'; else MainPort_i<=DataReceived(0)(3 downto 0); --MyRank<=DataReceived(2)(3 downto 0); Initialized_i<='1'; end if; ram_wr<='1'; --ram_address<=DataReceived(2); -- le rang qui a été envoyé; ram_address<= STD_logic_vector(to_unsigned(Core_init_adr+1,16)); ram_data_in<=DataReceived(0)(3 downto 0)& DataReceived(2)(3 downto 0); --MainPort & MyRank ResultOut<=(others=>'0'); RankAsked_i<='0'; dma_wr_request<='1'; When SendApp => --ajouter du code pour recevoir l'adr du reg status Initialized_i<='1'; ResultOut<="00000001"; -- Init Ok Result_En<='1'; PortId<=MyPort; BCAST<='0'; DS_ACK<='1'; Send_Ack<='0'; RTS_cmd<='0'; RTS_I<='0'; CTR<='0'; ram_wr<='0'; rdy<='0'; RankAsked_i<='0'; dma_wr_request<='0'; When SpawnApp => RTS_cmd<='0'; RTS_I<='0'; Result_En<='0'; DS_ACK<=DS_RDY; BCAST<='0'; CTR<='0'; --cette mise à 1 permet de ctrler la fin de réception rdy<='0'; ram_wr<=wr_ok; ram_rd<=rd_ok; Ram_Next_Address_i<= STD_logic_vector(to_unsigned(CORE_BASE_ADR,ADRLEN)); --incr_vec(Ram_Next_Address,'1'); ram_address<=Ram_Next_Address; -- le rang qui a été envoyé; -- "le motif 0001 indique juste que le port est bien activé ram_data_in<=DataToRam; --enregistrer le port qui a fait la demande en RAM dma_rd_request <= dma_rd; dma_wr_request <=dma_wr; RankAsked_i<='0'; if n>=3 then ResultOut<=("00000010");--spawn completed else ResultOut<=("00000000");--spawn message received end if; When SpawnLoad => RTS_cmd<='0'; --RTS_DAT<='1'; --à tester RTS_I<=PeerRTS; -- pour le timing Result_En<='0'; DS_ACK<='0'; BCAST<='0'; CTR<='0'; rdy<='0'; ram_wr<=wr_ok; ram_rd<=rd_ok; data_to_send_i(0)<=SpawnCmd0; data_to_send_i(1)<="00000100"; data_to_send_i(2)<=SpawnCmd1; data_to_send_i(3)<=SpawnCmd2; -- SPAWN_LOAD & MyPort ; Send_Ack<=Send_Rdy; I_Send_Ack<=I_Send_rdy; RankAsked_i<='0'; if SpawnInit='1' then ResultOut<=("10000000"); --spawn completed else ResultOut<=("01000000");--spawn in progress end if; When ErrSpawn => RTS_cmd<='0'; RTS_I<='0'; Result_En<='1'; DS_ACK<='0'; Send_Ack<='0'; BCAST<='0'; CTR<='0'; ram_wr<='0'; rdy<='0'; RankAsked_i<='0'; ResultOut<=(others=>'0'); dma_wr_request<='0'; dma_rd_request<='0'; When EndInit => RTS_cmd<='0'; RTS_I<='0'; Result_En<='0'; DS_ACK<='0'; Send_Ack<='0'; BCAST<='0'; CTR<='0'; ram_wr<='0'; rdy<='0'; RankAsked_i<='0'; ResultOut<=(others=>'0'); dma_wr_request<='0'; dma_rd_request<='0'; end case; end process; result_proc:process (ISMain_i,Initialized_i,stInit2,reset) begin if reset='1' then --IsMain1<='0'; Initialized<='0'; HCL_Init_i<='0'; Else HCL_init_i<=HCl_init; Initialized<=Hcl_init; -- if ismain_i='1' then -- IsMain1<='1'; -- end if; if Initialized_i='1' and stInit2=EndInit then Initialized<='1'; HCL_Init_i<='1'; elsif stInit2=SendApp then HCL_Init_i<='1'; end if; end if; end process result_proc; --================ --Traitement du Spawn --=================== --================== NEXT_STInit2_DECODE: process (stInit2,AppReq,Instruction_en, AppAck,PortNumFlag,EquFlag,MainResp,StatAsked,RankAsked,RankSent,CM_RDY, CmdReceived, BCast_Rdy, DS_RDY, DataReceived,Ht_Start,vPeerStat, Send_RDY, I_Send_RDY,TimeOut,Dma_rd_grant,Dma_wr_grant,cpt,n,clk_cyl,IsMain1,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,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); begin --declare default state for next_state to avoid latches next_stInit2 <= stInit2; --default is to stay in current state --insert statements to decode next_state --below is a simple example vPeerStat_i<=vPeerStat; SpawnNbReq<=SpawnNbReq_q; StatAsked_i<=StatAsked; MainResp_i<=MainResp; AppSize_i<=AppSize1; PortStat_i<=PortStat; grp_id_i<=grp_id; PeerRTS_i<=PeerRTS; --PortNumFlag_i<=PortNumFlag; SpawnReq<=SpawnReq_q; Spawn_done_i<=Spawn_done; Ht_Start_i<=Ht_Start; SpawnCmd0<=SpawnCmd0_Q; SpawnCmd1<=SpawnCmd1_Q; SpawnCmd2<=SpawnCmd2_Q; Timeout_i<=Timeout; clk_cyl_i<=clk_cyl; n_i<=n; Cpt_peer<=cpt; DataToRam<=(others=>'0');--A revoir dma_rd<='0'; dma_wr<='0'; rd_ok<='0'; wr_ok<='0'; for i in 0 to 3 loop Spawn_grp(i)<=Spawn_grp_q(i); end loop; case (stInit2) is When Init =>If Instruction_en='1' and AppReq='1' then If PortNumFlag='1' and IsMain1='1' then if instruction(7 downto 4)=INIT_SEEKMAIN and (instruction(3 downto 0)/=MyRank) then Next_stInit2 <=NewRank;--affecter un rang au demandeur. elsif instruction(7 downto 4)=INIT_STAT then StatASked_i<='1'; Next_stInit2 <=SendPeerStat; --envoyer des stat au demandeur elsif instruction(7 downto 4)=SPAWN_LOAD then SpawnInit<='0'; -- indique le debut du Spawn Next_stInit2 <=SpawnLoad; elsif instruction(7 downto 4)=INIT_SPAWN then SpawnInit<='1'; -- indique la fin du Next_stInit2 <=SpawnLoad; --dans ce cas il s'agit de terminer le spawn else --ignorer ce message Next_stInit2 <=SendApp; end if; elsif HCL_Init='1' and IsMain1='0' then Next_stInit2 <=SendApp; --ignorer ce message simplement else Next_stInit2 <=GetPortNum; -- initialiser la bibliothèque normalement end if; TimeOut_i<=0;PeerRTS_i<='0'; elsif SpawnOn='1' and Spawn_done='0' then Next_stInit2 <=SpawnApp; TimeOut_i<=0; end if; cpt_peer<=0;LastPort:='0';n_i<=0; When GetPortNum => -- récupérer le numéro du port if CM_RDY='1' then Next_stInit2 <=DecodeData; end if; When DecodeData => -- cet état permet de lire les données reçues du port --if CM_RDY='1' then if ((Cmdreceived(2)(3 downto 0) or nulvect)=nulvect) then -- teste si le n° du port est zero --EquFlag<='1'; else --EquFlag<='0'; end if; Next_stInit2 <=IsPortZero; --end if; When IsPortZero => if PortNumFlag='1' then End if; if EquFlag='0' then --tester le numéro de port obtenu Next_stInit2 <=SeekMain1; -- chercher le numéro de port sur le réseau else Next_stInit2<=SetMainFlag; -- enregistrer le numéro de port End If; TimeOut_i<=0; When SeekMain1 =>If BCast_RDY='1' then -- si tous les envois ont été postés Next_stInit2<=SeekMain2; End if; When SeekMain2 => If DS_RDY='1' then -- Si un jeu de données a été reçu if (Datareceived(3)(7 downto 4) = INIT_SETRANK) then MainResp_i<='1'; Next_stInit2 <=StoreMain; -- de la librairie pricipale else MainResp_i<='0'; Timeout_i<=0; end if; elsif (ExecTime_Out='1') then -- le Noc ne répond pas -- affecter un numéro en raport avec le port Next_stInit2 <=SeekMain2; elsif TimeOut=800 then --essayer de redemander l'initialisation assert true report "Ex4:seekmain ->redemander l'initialisation" severity failure; Timeout_i<=0; Next_stInit2 <=SeekMain1; else Timeout_i<=TimeOut+1; End if; When StoreMain => if DataReceived(3)(7 downto 4)= INIT_SETRANK then -- enregistrer le Main Adresse et les adresses des autres processus -- dans la variable prévue à cet effet Next_stInit2 <=StoreRank; elsif Datareceived(3)(7 downto 4) = INIT_SEEKMAIN then -- ignorer ce message Next_stInit2 <=StoreMain; --essayer de recevoir le rang end if; When StoreRank => --il faut prévoir du code pour s'assurer que la RAM a bien enregistrer -- la donnée ... if dma_wr_grant = '1' then if clk_cyl=2 then --prévoir deux cycle d'horloge pour lire en RAM Next_stInit2 <=AskPeerStat; TimeOut_i<=0; clk_cyl_i<=0; else clk_cyl_i<=clk_cyl+1; end if; else Next_stInit2 <=StoreRank; TimeOut_i<=0; clk_cyl_i<=0; end if; When AskPeerStat =>if n=0 then If I_SEND_RDY='1' then -- si tous les envois ont été postés n_i<=1; StatAsked_i<='0'; End if; elsif n=1 then If I_SEND_RDY='0' then -- si tous les envois ont été postés Next_stInit2<=GetPeerStat; StatAsked_i<='1'; MainResp_i<='0'; n_i<=0; End if; end if; When GetPeerStat => if n=0 then If DS_RDY='1' then -- Si un jeu de données a été reçu if (Datareceived(3) = INIT_REGISTER & MainPort ) then MainResp_i<='1'; n_i<=n+1; else MainResp_i<='0'; Timeout_i<=0; n_i<=n; end if; elsif TimeOut=1800 then --essayer de redemander les statistiques assert true report "Ex4:GetPeerStat timeout ->Les statistiques n'ont pas été reçu" severity failure; Timeout_i<=0; If StatAsked='1' then Next_stInit2 <=AskPeerStat; -- ceci n'est pas sûr else Next_stInit2 <=GetPeerStat; end if; else Timeout_i<=TimeOut+1; End if; elsif n=1 then --écrire le résultat de l'initialisation dma_wr<='1'; if dma_wr_grant='1' then n_i<=n+1; wr_ok<='1'; end if; elsif n=2 then n_i<=n+1; --écriture dans la RAM elsif n=3 then n_i<=0; dma_wr<='0'; Next_stInit2 <=SendApp; -- de la librairie pricipale end if; When SetMainFlag => if dma_wr_grant='1' then TimeOut_i<=0; Next_stInit2 <=ReadNoc; elsif Timeout=800 then assert true report "Ex4:SetMainFlag timeout ->La mémoire n'est pas dispo dma_wr_grant=0" severity failure; Next_stInit2 <=SendApp; else TimeOut_i<=TimeOut+1; -- end if; -- il est envisagée de terminer le programme à ce point end if; when ReadNoc => if DS_RDY='1' then if (Datareceived(3)(7 downto 4) = INIT_STAT) then StatAsked_i<='1' ; Next_stInit2 <=SendPeerStat; LastPort:='0'; else StatAsked_i<='0'; Next_stInit2 <=GetMainReq; end if; Timeout_i<=0; elsif Timeout=400 then assert true report "Ex4:ReadNoc timeout pas de données lues sur le NoC après 200 cycles" severity failure; Timeout_i<=0; --if StatAsked = '1' then --Next_stInit2 <=ErrSpawn; --il y a eu une erreur Next_stInit2 <=SendApp; -- else -- Next_stInit2 <=SendPeerStat; -- end if; else TimeOut_i<=TimeOut+1; end if; When GetMainReq => if RankAsked='1' and PeerStat(PeerPort)='0' then Next_stInit2 <=NewRank; -- un nouveau rang est demandé else Next_stInit2 <=ReadNoC; -- sinon essayer encore de lire un jeu de données. end if; When NewRank => Next_stInit2 <=SendRank; When SendRank => if I_Send_RDY='1' then --RankSent Next_stInit2 <=RegRank; RankSent_i<='1'; -- le rang a été envoyé 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 => --il faut prévoir du code pour s'assurer que la RAM a bien enregistrer -- la donnée ... if dma_wr_grant = '1' then -- if DS_RDY='1' then RankSent_i<='0'; if DS_RDY='0' then Next_stInit2 <=ReadNoc; end if; elsif Timeout=800 then Next_stInit2 <=SendApp; assert true report "Ex4:RegRank Timeout dma_wr_grant=0 " severity failure; else TimeOut_i<=TimeOut+1; -- end if; -- il est envisagée end if; --calcul de la taille de l'appli HtLoc:=0; for i in 0 to 7 loop if peerStat(i)='1' then --trouve le prochai rang libre HtLoc:=HtLoc+1; end if; end loop; AppSize_i<=std_logic_vector(to_unsigned(HtLoc,4)); When SendPeerStat => if cpt<=unsigned(NoCMax)and LastPort='0' then if peerRts='0' then -- pas encore envoyer les données alors les préparer if StatAsked='1' then PortStat_i<=PortNum; vPortStat:=std_logic_vector(to_unsigned(PeerPort,4)); else PortStat_i<=std_logic_vector(to_unsigned(cpt,4));--Port à contacter vPortStat:=std_logic_vector(to_unsigned(cpt,4)); end if; if StatAsked='1' then LastPort:='1'; -- on traite u seul port celui qui en a fait la demande if PeerStat(PeerPort)='1' then PeerRts_i<='1'; end if; else if (PeerStat(cpt)='1') and not(vPortStat=MyPort) then PeerRts_i<='1'; end if; if cpt Impossible d'envoyer sur le NoC" severity failure; else TimeOut_i<=TimeOut+1; end if; end if; elsif PeerRTS='1' then -- le dernier port est il activé ? if I_Send_RDY='1' then RankSent_i<='1'; -- les stat ont été envoyé TimeOut_i<=0; -- prépare le traitement de la prochaine requête PeerRts_i<='0'; if statAsked='1' then -- Next_stInit2<=ReadNoc; Next_stInit2<=SendApp; --terminer l'application end if; elsif TimeOut=100 then Next_stInit2 <=EndInit; assert true report "Ex4:SendPeerStat Timeout -> Impossible d'envoyer sur le NoC" severity failure; else TimeOut_i<=TimeOut+1; end if; else Next_stInit2<=SendApp; end if; When SendApp => -- envoyer au programme un signal -- et attendre un acquittement et l'adresse de base If AppAck='1' then Next_stInit2 <=EndInit; end if; When SpawnLoad => if n=0 then 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 IsMain1='1' and SpawnInit='0' then 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 IsMain1='1' and SpawnInit='1' then -- il faut envoyer les acquittements 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; assert true Report "SpawnLoad : Cas non prévu !" severity failure; end if; elsif n=1 then 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 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 Ht_hole:='0'; -- pas de place trouvé end if; exit L1 when ht_hole='1'; end loop L1; if Ht_hole='0' then -- toutes les tâches n'ont pas été créés -- aller à la fin ! en signalant une erreur! SpawnCMd2<=Spawn_Err & "0001"; --erreur pas assez de ports sur le NoC n_i<=9; else n_i<=n+1; 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 PeerRTS_i<='1'; -- envoyer les données du Spawn n_i<=n+1; elsif n=3 then if I_Send_RDy='1' then n_i<=n+1; PeerRts_i<='0'; end if; elsif n=4 then if SpawnInit='0' then if Ht_Start>=SpawnNbReq then n_i<=n+1; else n_i<=1; -- passer à la création du HT suivant end if; else n_i<=7; -- passer au contact du HT suivant end if; elsif n=5 then -- 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 --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 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 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 -- -- 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<=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>=0 and n <4 then dma_wr<='1'; --demander un accès exclusif au bus dma_rd<='1'; -- pour éviter une mauvaise mise à jour des données else dma_wr<='0'; dma_rd<='0'; end if; if n=0 then if DS_RDY='1' then --- if Datareceived(3)(7 downto 4)=SPAWN_START then n_i<=n+1; else Next_stInit2<=ErrSpawn; n_i<=0; --erreur instruction incorrecte end if; rd_ok<='1'; wr_ok<='0'; end if; 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=3 then if dma_rd_grant='1' and dma_wr_grant='1' then n_i<=n+1; tempval:=Ram_data_out; tempval(6):='1'; dataToram<=tempval; rd_ok<='0'; wr_ok<='1'; else rd_ok<='1'; wr_ok<='0'; end if; elsif n=4 then if spawninit='0' then Spawn_done_i<='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; end process; --================================================ --sauvegarde du rang et du main port à l'adresse de retour de la fonction Init --================================================== --==================================================== --envoie des données sur le port --=================================================== selector<=(Rcv_on,Cmd_on,Snd_on); process (selector,Rport_out_rd_en,cport_out_rd_en,sPort_in_wr_en ,cPort_in_wr_en, tosend ,tosend4) begin case selector is when "000" => port_in_data<=(others=>'-'); Port_in_wr_en<='0'; Port_out_rd_en<='0'; when "001" => port_in_data<=tosend; --envoie de données Port_in_wr_en<=sPort_in_wr_en ; Port_out_rd_en<='0'; when "101" => port_in_data<=tosend; --envoie de données Port_in_wr_en<=sPort_in_wr_en ; Port_out_rd_en<=Rport_out_rd_en ; when "010" | "110" | "011" | "111" => port_in_data<=tosend4; --envoie de commande GetPort Port_in_wr_en<=cPort_in_wr_en; Port_out_rd_en<=cport_out_rd_en; when "100" => port_in_data<=(others=>'-'); -- réception de données Port_in_wr_en<='0'; Port_out_rd_en<=Rport_out_rd_en ; when others => port_in_data<=(others=>'-'); Port_in_wr_en<='0'; Port_out_rd_en<='0'; end case; end process; --================================================== --=============================================================== --processus d'accès au réseau --=============================================================== preceiv:process(clk,reset) variable origport,destport : natural range 0 to 15; variable dcount,dlen ,rtimeout:natural range 0 to 1023; variable ptype : std_logic_vector(3 downto 0); variable bad_paquet :std_logic:='0'; begin -- if reset='1' then etrec<=r_wait; destport:=1; rtimeout:=0; bad_paquet:='0'; else if rising_edge(clk) then case etrec is when r_wait => rtimeout:=0; bad_paquet:='0'; --modifier le 01-08-pour gérer le Spawn if Port_out_data_available='1' and Cmd_on='0' then ptype:=port_out_data(7 downto 4); origport:=to_integer(unsigned(port_out_data(3 downto 0))); if ptype=MPI_SPAWN and not(portnumflag='1') then etrec<=r_dlen; --identification de la signature d'en tête valide Datareceived(0)<=Port_out_data; --stocker l'entête 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 etrec<=r_dlen; --identification de la signature d'en tête valide Datareceived(0)<=Port_out_data; --stocker l'entête bad_paquet:='0'; else --une donnée non attendue est présente sur le port etrec<=r_dlen; --il faut ignorer cette donnée et quitter dcount:=1; bad_paquet:='1'; Datareceived(0)<=(others=>'0'); end if; end if; --elsif Port_out_data_available='1' and CTR='0' then -- etrec<=r_drop; else etrec<=r_wait; end if; DS_RDY<='0'; When r_drop => -- ignorer les messages qui arrivent à ce noeud tant que --l'application n'a pas été initialisée if port_out_data_available='0' then etrec<=r_end; dcount:=0; end if; --Rport_out_rd_en<='1'; --lire les données qui sont dans le tampon de sortie DS_RDY<='0'; when r_Dlen => --positionnement du mot de longueur des données if Port_out_data_available ='1' then --Rport_out_rd_en<='1'; etrec<=r_glen; rtimeout:=0; else rtimeout:=rtimeout+1; if rtimeout>=30 then assert true report "Ex4:etrec r_glen Timeout -> Impossible de recevoir du NoC" severity failure; Exectime_out<='0'; --read Noc time out etrec<=r_end; -- données pas prêtes end if; end if; DS_RDY<='0'; -- when r_glen => --lecture effective de la longueur des données if port_out_data_available='1' then dlen:=to_integer(unsigned(port_out_data(Word-1 downto 0))); Datareceived(1)<=Port_out_data; --RPort_out_rd_en<='0'; etrec<=r_data; dcount:=2; -- initialisation du compteur de reception (il y a -- déjà deux mots reçues else rtimeout:=rtimeout+1; if rtimeout>=30 then assert true report "Ex4:etrec Timeout -> Impossible de recevoir sur le NoC" severity failure; ExecTime_out<='0'; etrec<=r_end; -- données pas prêtes end if; end if; DS_RDY<='0'; when r_data => -- lecture des données if port_out_data_available='1' then --Rport_out_rd_en<='1'; --autoriser la lecture if bad_paquet='0' then DataReceived(dcount)<=Port_out_data; --récupération des données else DataReceived(2)<=(others=>'0'); --ignorer ces données end if; --assert true report "Donnée lue :"; --& string(unsigned(port4_out(Word-1 downto 0))) DS_RDY<='0'; dcount:=dcount+1; --severity note; if dlen <=dcount then -- ce doit être égale ici et non <= ??? etrec<=r_end; DS_RDY<= not bad_paquet; -- jeu de données disponibles elsif dcount=255 then --dépassement de la capacité DS_RDY<='0'; etrec<=r_end; end if; else rtimeout:=rtimeout+1; if rtimeout>=30 then ExecTime_out<='0'; etrec<=r_end; -- données pas prêtes end if; DS_RDY<='0'; end if; when r_pulse => etrec<=r_end; DS_RDY<=not bad_paquet; when r_end => --rPort_out_rd_en <='0'; 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 case; end if;--reset='1' end if; end process preceiv; val_preceiv: process (etrec) begin case etrec is when r_wait => -- DS_RDY<='0'; rcv_on<='0'; Rport_out_rd_en <='0'; when r_dlen => -- DS_RDY<='0'; Rport_out_rd_en <='1'; rcv_On<='1'; when r_drop => -- DS_RDY<='0'; Rport_out_rd_en <='1'; rcv_On<='1'; when r_glen => Rport_out_rd_en <='1'; -- DS_RDY<='0'; rcv_On<='1'; when r_data => Rport_out_rd_en <='1'; -- DS_RDY<='0'; rcv_On<='1'; when r_pulse => Rport_out_rd_en <='0'; rcv_On<='1'; -- DS_RDY<='1'; when r_end => Rport_out_rd_en <='0'; -- DS_RDY<='0'; rcv_On<='0'; when others => Rport_out_rd_en <='0'; -- DS_RDY<='0'; rcv_On<='0'; end case; end process; psend:process(clk,reset) --génération des paquets à partir du port courant variable pactype :natural range 0 to 15; variable destport : natural range 0 to 15:=0; variable realdlen, i,i_pair : natural range 0 to 255; variable MaxPort : natural :=4; -- en fait ne doit pas être 0 begin if rising_edge(clk) then if reset='1' then etsnd<=s_init; else -- le process s'exécute sur chaque front -- montant de l'horloge case etsnd is when s_init => tosend<=(others=>'-'); MaxPort :=to_integer(unsigned(NOCMAX)); sPort_in_wr_en<='0'; if port_in_full='0' and Rts_dat='1' then --on peut aussi tester si le port est vide BCast_RDY<='0'; -- pas la fin de du Broadcasting Send_RDY<='0'; Snd_on<='1'; if Bcast='1' then -- envoyer à tous les ports le même message ? DestPort :=0; else DestPort:=to_integer(unsigned(data_to_send(0)(3 downto 0))); end if; etsnd<=s_head; end if; when s_head => -- construction et envoie de l'en-tête Send_RDY<='0'; --l'envoi commence BCast_RDY<='0'; Snd_on<='1'; --pactype:=to_integer(MPI_INIT);-- pactype:=to_integer(unsigned(data_to_send(0)(7 downto 4))); --realdlen:=to_integer(unsigned(Datalen)); --? destport:=MAXPORT; -- le port de destination tosend <=STD_LOGIC_VECTOR(to_unsigned(pactype,4)) & STD_LOGIC_VECTOR(to_unsigned(destport,4)); sPort_in_wr_en<='1'; -- i:=1; etsnd<=s_len2; -- passer à l'état suivant when s_len => BCast_RDY<='0'; Send_RDY<='0'; Snd_on<='1'; --tosend<=(STD_LOGIC_VECTOR(to_unsigned(Realdlen,8))); tosend<=data_to_send(1); sPort_in_wr_en <='1'; --port1_in<=tosend1; --copie directe sur le port etsnd<=s_len2; when s_len2 => --tosend<=(STD_LOGIC_VECTOR(to_unsigned(realdlen,8))); sPort_in_wr_en<='1'; tosend<=data_to_send(1); --port1_in<=tosend1; --copie directe sur le port etsnd<=s_data; BCast_RDY<='0'; Send_RDY<='0'; Snd_on<='1'; i:=i+1; when s_data => Snd_on<='1'; if Port_in_full='0' and RTS_dat='1' then sPort_in_wr_en<='1'; --envoie des données sur le port tosend<=data_to_send(i); if i+1>=datalen then etsnd<=s_end; Send_RDY<='1'; --l'envoi est terminé if BCast='1' and destport=MAXPort then BCAST_RDY<='1'; --l'envoi collectif aussi else BCast_RDY<='0'; end if; else BCast_RDY<='0'; Send_RDY<='0'; i:=i+1; end if; elsif port_in_full='1' then sPort_in_wr_en<='0'; else sPort_in_wr_en<='0'; BCast_RDY<='0'; Send_RDY<='0'; end if; when s_end => tosend<=(others=>'-'); sPort_in_wr_en<='0'; if Bcast='1' then if destPort if Port_in_empty='1' and RTS_Cmd='1' then etcmd<=cmdpost; end if; destport:=0; ctimeout:=0; origport:=1; when cmdpost => if Port_in_empty='1' then etcmd<=cmdread; end if; when cmdpostidle => --permet juste la prise en compte de la commande etcmd<=cmdread; dcount<=0;-- initialisation du compteur de reception when cmdread => ctimeout:=0; if Port_out_data_available='1' then mport:=to_integer(unsigned(port_out_data(7 downto 4))); pid:=to_integer(unsigned(port_out_data(3 downto 0)))+1; CmdReceived(dcount)<=port_out_data; --cdata_out_en(origport)<='1'; -- if pid=origport then --le port a été bien identifié etcmd<=cmdglen; -- dcount<=dcount+1; -- else -- etcmd<=cmdtimeout; -- end if; else etcmd<=cmdread; end if; when cmdlen => --positionnement du mot de longueur des données if Port_out_data_available='1' then etcmd<=cmdglen; ctimeout:=0; else ctimeout:=ctimeout+1; if ctimeout>=30 then assert true report "Ex4:etcmd Timeout -> impossible de recevoir du le NoC" severity failure; etcmd<=cmdtimeout; -- données pas prêtes end if; end if; when cmdglen => --lecture effective de la longueur des données if Port_out_data_available='1' then cdlen<=to_integer(unsigned(port_out_data(Word-1 downto 0))); CmdReceived(dcount)<=port_out_data; etcmd<=cmddata; dcount<=dcount+1; else ctimeout:=ctimeout+1; if ctimeout>=30 then --time_out(destport)<='1'; assert true report "Ex4:etcmd Timeout -> impossible de recevoir du le NoC" severity failure; etcmd<=cmdtimeout; -- données pas prêtes end if; end if; when cmddata => if (port_out_data_available='1' and ctimeout<30) then --cdata_out_en(origport)<='1'; mport:=to_integer(unsigned(port_out_data(7 downto 4))); --attention les ports sont numérotés à partir de 0 pid:=to_integer(unsigned(port_out_data(3 downto 0)))+1; CmdReceived(dcount)<=port_out_data; if (dcount>=cdlen-1 ) then--attention le compteur de données commence à 0 etcmd<=cmdend; --CM_RDY<='1'; else dcount<=dcount+1; end if; Else if ctimeout>=30 then --time_out(destport)<='1'; etcmd<=cmdtimeout; -- données pas prêtes assert true report "Ex4:etcmd. cmddata Timeout -> impossible de recevoir du le NoC" severity failure; else ctimeout:=ctimeout+1; etcmd<=cmdend; end if; end if; when cmdend => etcmd<=cmdstart; when cmdtimeout => etcmd<=cmdstart; end case; --sorigport<=origport; end if; --reset='1' end if; end process pcmd; majetcmd: process (etcmd,data_to_send, port_out_data_available, dcount,port_out_data) variable origport : natural; variable i:natural:=0; begin case etcmd is when cmdstart => i:=0; Port_in_cmd_en<='0'; tosend4<=(others=>'-'); cport_out_rd_en<='0'; cport_in_wr_en<='0'; CM_RDY<='0'; Cmd_on<='0'; when cmdpost | cmdpostidle => cport_in_wr_en<='1'; tosend4<=data_to_send(0); ---code pour getportid Port_in_cmd_en<='1'; cport_out_rd_en<='0'; CM_RDY<='0'; Cmd_on<='1'; when cmdread => tosend4<=(others=>'-'); cPort_in_wr_en<='0'; cport_out_rd_en<=port_out_data_available; --CmdReceived(dcount)<=port_out_data; --mettre les données dans le tampon Port_in_cmd_en<='1'; CM_RDY<='0'; Cmd_on<='1'; when cmdlen |cmdglen => --positionnement du mot de longueur des données tosend4<=(others=>'-'); cport_in_wr_en<='0'; cport_out_rd_en<=port_out_data_available; Port_in_cmd_en<='1'; --CmdReceived(dcount)<= port_out_data; CM_RDY<='0'; Cmd_on<='1'; when cmddata => tosend4<=(others=>'-'); cport_in_wr_en<='0'; cport_out_rd_en<=Port_out_data_available; Port_in_cmd_en<='1'; --CmdReceived(dcount)<=port_out_data; --mettre les données dans le tampon i:=i+1; CM_RDY<='0'; Cmd_on<='1'; when cmdend => tosend4<=(others=>'-'); cport_in_wr_en<='0'; cport_out_rd_en<='0'; --CmdReceived(dcount)<=port_out_data; Port_in_cmd_en<='0'; CM_RDY<='1'; Cmd_on<='0'; when cmdtimeout => tosend4<=(others=>'-'); cport_in_wr_en<='0'; cport_out_rd_en<='0'; Port_in_cmd_en<='0'; Cmd_on<='1'; cm_rdy<='0'; end case; end process majetcmd ; i_send_val:process(HCL_Init,Send_RDY,RTS_I,Snd_Ack,I_send_ack,data_to_send,Bcast_rdy,Bcast) begin snd_start_i<=snd_start; RTS_DAT<='0'; if HCL_Init='1' then if RTS_I='1' and snd_ack='0' then snd_start_i<='1'; elsif i_send_ack='1' then snd_start_i<='0'; end if; i_send_rdy<=snd_ack; Snd_data<=data_to_send; else if RTS_I='1' and i_send_ack='0' then RTS_DAT<='1'; elsif i_send_ack='1' then RTS_DAT<='0'; 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; end Behavioral;