---------------------------------------------------------------------------------- -- 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; --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 : OUT 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); 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 : std_logic_vector(15 downto 0):=(others=>'0'); --état des autres Lib initialisées 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,EquFlag,MainResp,StatAsked,RankAsked,RankSent:std_logic; 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 SpawnCmd :std_logic_vector(Word-1 downto 0); signal SpawnDest :std_logic_vector(3 downto 0); signal IsMain_i,Initialized_i,HCL_init: 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_NextAdress : std_logic_vector(ADRLEN-1 downto 0):=std_logic_vector(to_unsigned(Core_BASE_ADR+CORE_Rank2port_BASE,16)); signal Ram_NExtAdress_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,MyPort : std_logic_vector(3 downto 0); -- signal NocMax : std_logic_vector(3 downto 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 signal Spawn_done:std_logic:='0'; --indique que le Spawn a été effectué signal MainPort : 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 DataToSend : 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 : 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 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 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 signal PeerRTS,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'; 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_NextAdress<=Ram_NextAdress_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; n<=n_i; SpawnNbAck<=SpawnNbAck_i; AppSize<=AppSize_i; Ready<=Rdy; snd_start<=snd_start_i; 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) variable nextr,nextadr : natural :=0;--to_integer(unsigned(Ram_NextAdress)); variable nport : natural range 0 to 15:=0; begin 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 IsMain_i='1' then PortNum_i<=Instruction(3 downto 0); else PortNum_i<=(others=>'-'); end if; EquFlag<='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' ; DataToSend(0)<=X"0" & GETPORTID; DS_ACK<='0'; Send_Ack<='0'; ram_wr<='0'; rdy<='0'; ResultOut<=(others=>'0'); PortNum_i<=(others=>'-'); RankAsked_i<='0'; dma_wr_request<='0'; When DecodeData => EquFlag<=(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<=To_integer(unsigned(Cmdreceived(2)(3 downto 0))); NocMax<=Cmdreceived(2)(7 downto 4); -- et la taille du réseau PortNumFlag<='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:=1; IsMain_i<=EquFlag; MyRank<="0000"; MainPort<="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; DataToSend(0)<=MPI_INIT & MyPort ; DataToSend(1)<="00000100"; -- la longueur du packet =4 DataToSend(2)<="0000" & MyPort; --propose sa propre adresse DataToSend(3)<=INIT_SEEKMAIN & MyPort ; DataLen<=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; -- DataToSend(0)<=INIT_SEEKMAIN & MyPort ; -- DataToSend(1)<="00000011"; -- la longueur du packet =3 -- DataToSend(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<='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<='0'; MainPort<=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; DataToSend(0)<=MPI_INIT & MainPort ; DataToSend(1)<="00000100"; -- la longueur du packet =4 DataToSend(2)<="0000" & MyPort; --indique sa propre adresse DataToSend(3)<=INIT_STAT & MyPort ; DataLen<=4; BCast<='0'; Result_En<='0'; ram_wr<='0'; rdy<='0'; ResultOut<=(others=>'0'); EquFlag<='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<="0000"; PeerStat(0)<='1'; --la main lib est initialisée CTR<='1'; DS_ACK<='0'; ram_wr<='1'; rdy<='0'; ResultOut<=(others=>'0'); EquFlag<='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<= 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<='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<='1'; ResultOut<=(others=>'0'); PortNum_i<=DataReceived(0)(3 downto 0); --adresse du Main Port PeerStat(7 downto 0)<=DataReceived(2); -- état des initialisations EquFlag<='0'; dma_wr_request<=dma_wr; ram_wr<=wr_ok; rdy<='0'; ram_rd<=rd_ok; Ram_NextAdress_i<= STD_logic_vector(to_unsigned(CORE_Init_Adr+2,ADRLEN)); --incr_vec(Ram_NextAdress,'1'); ram_address<=Ram_NextAdress; -- ram_data_in<=DataReceived(2); --enregistrer les ports actifs When NewRank => nport:=to_integer(Unsigned(PortNum_i)); --port ayant sollicité le rang nextr:=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(nextR)<="0000" & PortNum_i; NextAdr:=NextAdr+1; end if; DataToSend(0)<=MPI_INIT & PortNum_i ; DataToSend(1)<="00000100"; DataToSend(2)<="0000" & NextRank; --ici c'est la valeur avant incrémentation ! DataToSend(3)<=INIT_SETRANK & PortNum_i ; PeerStat(nport)<='1'; -- mise à jour du status DataLen<=4; BCast<='0'; DS_ACK<='0'; Result_En<='0'; EquFlag<='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<='1'; RTS_I<='1'; RTS_cmd<='0'; DS_ACK<='0'; Send_Ack<='0'; CTR<='0' ; ram_wr<='0'; Ram_NextAdress_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<='1'; ram_wr<='1'; Ram_NextAdress_i<= STD_logic_vector(to_unsigned(CORE_RANK_ADR+Nextr-1,16)); --incr_vec(Ram_NextAdress,'1'); ram_address<=Ram_NextAdress; -- le rang qui a été envoyé; -- "le motif 0001 indique juste que le port est bien activé ram_data_in<="0001" & PortNum_i; --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<='0'; RTS_I<=PeerRTS; RTS_cmd<='0'; DS_ACK<='0'; DataToSend(0)<=MPI_INIT & PortStat ; DataToSend(1)<="00000100"; DataToSend(2)<=PeerStat(7 downto 0); DataToSend(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<='0'; RTS_I<='0'; CTR<='0'; Result_En<='0'; if ExecTime_out='1' then MainPort<="0000"; MyRank<=MyPort; initialized_i<='0'; else MainPort<=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<='1'; --cette mise à 1 permet de ctrler la fin de réception rdy<='0'; ram_wr<=wr_ok; ram_rd<=rd_ok; Ram_NextAdress_i<= STD_logic_vector(to_unsigned(CORE_BASE_ADR,ADRLEN)); --incr_vec(Ram_NextAdress,'1'); ram_address<=Ram_NextAdress; -- 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 SpawnInit='1' then ResultOut<=("01000000");--spawn completed else ResultOut<=("00000010");--spawn message received end if; When SpawnLoad => RTS_cmd<='0'; --RTS_DAT<='1'; --à tester RTS_I<='1'; -- pour le timing Result_En<='0'; DS_ACK<='0'; BCAST<='0'; CTR<='0'; rdy<='0'; ram_wr<=wr_ok; ram_rd<=rd_ok; DataToSend(0)<=MPI_SPAWN & SpawnDest; DataToSend(1)<="00000100"; DataToSend(2)<=PeerStat(7 downto 0); DataToSend(3)<=SpawnCmd; -- SPAWN_LOAD & MyPort ; Send_Ack<=Send_Rdy; I_Send_Ack<=I_Send_rdy; RankAsked_i<='0'; if SpawnInit='1' then ResultOut<=("01000000"); --spawn completed else ResultOut<=("00000010");--spawn message received 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 IsMain<='0'; Initialized<='0'; Else if ismain_i='1' then IsMain<='1'; end if; if Initialized_i='1' and stInit2=EndInit then Initialized<='1'; HCL_Init<='1'; elsif stInit2=SendApp then HCL_Init<='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, Send_RDY, I_Send_RDY,TimeOut,Dma_rd_grant,Dma_wr_grant,cpt,n,clk_cyl,IsMain_i,SpawnOn) 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 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 case (stInit2) is When Init =>If Instruction_en='1' and AppReq='1' then If PortNumFlag='1' and IsMain_i='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 portNumFlag='1' and IsMain_i='0' then Next_stInit2 <=AskPeerStat; --recevoir les nouvelles données sur l'état d'initialisation else Next_stInit2 <=GetPortNum; -- initialiser la bibliothèque normalement end if; TimeOut_i<=0;PeerRTS<='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<='1'; Next_stInit2 <=StoreMain; -- de la librairie pricipale else MainResp<='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 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'; 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<='1'; n_i<=n+1; else MainResp<='0'; Timeout_i<=0; n_i<=n; end if; elsif TimeOut=800 then --essayer de redemander les statistiques 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 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=200 then 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 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; 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<=PortNum_i; vPortStat:=std_logic_vector(to_unsigned(PeerPort,4)); else PortStat<=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<='1'; end if; else if (PeerStat(cpt)='1') and not(vPortStat=MyPort) then PeerRts<='1'; end if; if cpt -- 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 SpawnNbReq<=to_integer(unsigned(Instruction(3 downto 0))); -- sauver le nombre de HT à créer if IsMain_i='1' and SpawnInit='0' then n_i<=1; 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 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; elsif n=1 then ht_hole:='0'; L1: for i in 0 to 7 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; 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! SpawnCMd<=Spawn_Err & "0001"; --erreur pas assez de ports sur le NoC n_i<=7; else n_i<=n+1; SpawnCmd<=SPAWN_START & MyPort; end if; elsif n=2 then PeerRTS<='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<='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<=6; -- passer au contact du HT suivant end if; elsif n=5 then -- donner le résultat du Spawn Next_stinit2<=SendApp; n_i<=0; elsif n=6 then Ht_hole:='0'; L2: for i in 0 to 7 loop if PeerStat(i)='1' then SpawnDest<=std_logic_vector(to_unsigned(i,4)); -- le port à avertir vPeerStat(i):='1'; Ht_Start:=Ht_Start+1; Ht_Hole:='1'; -- Une tâche doit être avertie n_i<=n+1; else Ht_hole:='0'; -- end if; exit L2 when ht_hole='1'; end loop L2; 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 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; When SpawnApp=> --Mise à jour du bit 6 du registre status du COre. if n <3 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 else n_i<=6; --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 if dma_rd_grant='1' then n_i<=n+1; end if; rd_ok<='1'; wr_ok<='0'; elsif n=2 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=3 then if spawninit='0' then Spawn_done<='1'; end if; Next_stInit2<=EndInit; end if; When ErrSpawn => Next_stInit2<=Init; When EndInit=> 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 rising_edge(clk) then if reset='1' then etrec<=r_wait; destport:=1; rtimeout:=0; bad_paquet:='0'; else 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 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 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 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'; SpawnOn<='0'; -- annuler le signal de Spawn if DS_ACK='1' or rtimeout> 30 or CTR='0' or bad_paquet='1' then DS_RDY<='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'; 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(DataToSend(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(DataToSend(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<=DataToSend(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<=DataToSend(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<=DataToSend(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 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'; 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 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,DataToSend, 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<=DataToSend(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'; end case; end process majetcmd ; i_send_val:process(HCL_Init,Send_RDY,RTS_I,Snd_Ack,I_send_ack,DataToSend,Bcast_rdy,Bcast) begin if HCL_Init='1' then if RTS_I='1' and i_send_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<=DataToSend; 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; end if; end process; end Behavioral;