-------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 01:27:32 04/20/2012 -- Design Name: -- Module Name: C:/Core MPI/CORE_MPI/MPICORETEST.vhd -- Project Name: MPI_CORE_COMPONENTS -- Target Device: -- Tool versions: -- Description: -- -- VHDL Test Bench Created by ISE for module: MPI_NOC -- -- Dependencies: -- -- Revision: 11 Juillet 2012 -- Revision 0.01 - File Created -- Additional Comments:Permet de tester le composant MPI -- en simulant deux PE qui s'échangent des données. -- Notes: -- -- -------------------------------------------------------------------------------- LIBRARY ieee; USE ieee.std_logic_1164.ALL; library NocLib ; --use IEEE.STD_LOGIC_ARITH.ALL; --use IEEE.STD_LOGIC_UNSIGNED.ALL; use NocLib.CoreTypes.all; use work.Packet_type.all; use work.MPI_RMA.all; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values USE ieee.numeric_std.ALL; ENTITY MPICORETEST IS --port (clkm : in std_logic; --reset : in std_logic; --result : out std_logic_vector(Word-1 downto 0)); END MPICORETEST; ARCHITECTURE behavior OF MPICORETEST IS --constant WORD :positive:=8; constant MEMSIZE:positive:=65535; -- Components declaration COMPONENT RAM_v generic (width : positive;size :positive); PORT( clka : IN std_logic; clkb : IN std_logic; wea : IN std_logic; ena : IN std_logic; enb : IN std_logic; addra : IN std_logic_vector; addrb : IN std_logic_vector; dia : IN std_logic_vector; dob : OUT std_logic_vector ); END COMPONENT; -- Component Declaration for the Unit Under Test (UUT) COMPONENT MPI_NOC generic (NPROC : positive:=2); PORT( MPI_Node_in : IN Ar_MPIPort_in(1 to 2); MPI_Node_Out : OUT Ar_MPIPort_out(1 to 2) ); END COMPONENT; constant clk_period : time := 10 ns; --===================signaux pour l'horloge ============================== signal reset,clkm : std_logic := '0'; --======================================================================== --signaux pour l'interconnexionsignal datain :std_logic_vector(word-1 downto 0):= (others => '0'); signal ram_we ,ram_ena,ram_enb,ramsel: std_logic:='0'; signal pe_ram_we ,pe_ram_ena,pe_ram_enb: std_logic; signal ram_do,ram_din:std_logic_vector(word-1 downto 0):= (others => '0'); signal pe_ram_do,pe_ram_din:std_logic_vector(word-1 downto 0):= (others => '0'); signal ram_addra,ram_addrb :std_logic_vector(ADRLEN-1 downto 0); signal pe_ram_addra,pe_ram_addrb :std_logic_vector(ADRLEN-1 downto 0); signal PE_Instr_en : std_logic:='0'; signal sram : typ_dpram; signal pe_hold_ack,pe_hold_req : std_logic; --signal pe_putadr:std_logic_vector(MEMSIZE-1 downto 0);-- adresse du bloc pour Put --signal pe_getadr:std_logic_vector(MEMSIZE-1 downto 0);-- adresse du bloc pour get signal Lib_Ready:std_logic; --indique que l'exécution de la fonction est terminée signal Lib_instr_ack : std_logic; -- l'instruction est copiée dans le tampon FIFO signal Lib_Init : std_logic; -- l'initialisation est terminée --données du programme PE signal SrcAdr0,SrcAdr1,destAdr0,destAdr1,Datalen:std_logic_vector(word-1 downto 0); signal dpid,dpid_i : natural range 0 to 15:=1; --Inputs signal MPI_Node_in : Ar_MPIPort_in(1 to 2) ; -- Port details -- instruction : STD_LOGIC_VECTOR (Word -1 downto 0); -- instruction_en : STD_LOGIC; -- packet_ack : std_logic; -- ram_data_in : STD_LOGIC_VECTOR (Word-1 downto 0); -- clk : STD_LOGIC; -- reset : STD_LOGIC; --Outputs signal MPI_Node_Out : Ar_MPIPort_out(1 to 2); -- détails des champs de Typ_MPIPORT_Out -- -- -- ram_we : STD_LOGIC; -- ram_en : STD_LOGIC; -- packet_received : STD_LOGIC; -- barrier_completed : STD_LOGIC; -- instruction_fifo_full : STD_LOGIC; -- PushOut : STD_LOGIC_VECTOR (WORD-1 downto 0); -- ram_data_out : STD_LOGIC_VECTOR (WORD-1 downto 0); -- ram_address : STD_LOGIC_VECTOR (ADRLEN-1 downto 0); -- --end record; -- -- a --signaux pour la gestion de la MAE type typ_mae is (start,Fillmem,NextFill,InitApp,InitCompleted,writeptr,InstrCopy, putdata,putdata2,putcompleted,getdata,getdata2,getcompleted,terminate,st_timeout); signal dcount : natural range 0 to 255:=0; --permet de compter le packet de données envoyées signal count,count_i : natural range 0 to 15:=0; --signal adresse,adresse_rd :natural range 0 to 65536; signal etPutGet : typ_mae; signal Ram_busy :std_logic:='0'; BEGIN -- Instantiate the Unit Under Test (UUT) uut: MPI_NOC GENERIC MAP (NPROC=>2) PORT MAP ( MPI_Node_in => MPI_Node_in, MPI_Node_Out => MPI_Node_Out ); Inst_RAM_v: RAM_v generic map(width=>word,size=>ADRLEN) PORT MAP( clka =>clkm, clkb => clkm, wea => ram_we, ena => ram_ena, enb => ram_enb, addra => ram_addra, addrb =>ram_addrb, dia => ram_din, dob => ram_do ); --MUX de la RAM ram_addrb <= MPI_Node_out(1).ram_address_rd WHEN ramsel ='1' ELSE pe_ram_addrb; ram_addra <= MPI_Node_out(1).ram_address_wr WHEN ramsel ='1' ELSE pe_ram_addra; ram_ena <= MPI_Node_out(1).ram_en WHEN ramsel ='1' ELSE pe_ram_ena; ram_enb <= MPI_Node_out(1).ram_en WHEN ramsel ='1' ELSE pe_ram_enb; ram_ena <= MPI_Node_out(1).ram_en WHEN ramsel ='1' ELSE pe_ram_ena; ram_we<= MPI_Node_out(1).ram_we WHEN ramsel ='1' ELSE pe_ram_we; ram_din <= MPI_Node_out(1).ram_data_in WHEN ramsel ='1' ELSE pe_ram_din; MPI_Node_in(1).ram_data_out<=ram_do when ramsel='1' else (others=>'Z'); pe_ram_do<=ram_do when ramsel='0' else (others=>'Z'); pe_hold_req<=MPI_Node_out(1).hold_req; MPI_Node_in(1).hold_ack<=pe_hold_ack; MPI_Node_in(1).reset<=reset; MPI_Node_in(1).clk<=clkm; MPI_Node_in(1).instruction_en<=PE_instr_en; MPI_Node_in(1).instruction<=std_logic_vector(to_unsigned(Core_upper_adr,8)); Lib_Instr_ack<=MPI_Node_out(1).Pushout(0); --l'instruction a été copié Lib_init<=MPI_Node_out(1).Pushout(4); -- Initialized --============================================================= -- Clock process definitions --============================================================= clk_process :process begin clkm <= '0' ; wait for 10 ns;--clk_period/2; clkm <= '1' ; wait for 10 ns;--clk_period/2; end process; stim_proc: process begin -- hold reset state for 100 ns. reset<='0'; wait for 1 ns; reset<='1'; wait for clk_period*10; reset<='0'; wait; end process; --================================================================ dpid<=dpid_i; pPutGet:process(clkm) variable bfill,destrank,pid,mport : natural range 0 to 15; variable fsrc,ret : natural range 0 to 15:=0; variable timeout,dlen,ct : natural range 0 to 255; variable adrToset : std_logic_vector(ADRLEN-1 downto 0); variable iack : std_logic:='0'; variable adresse,adresse_rd :natural range 0 to 65536; begin if (clkm'event and clkm='1') then if reset='1' then etputget<=start; dcount<=0; else case etputget is when start => if bfill=0 then -- si le nombre de bloc de mémoire remplis est vide etputget<=Fillmem; end if; Ram_busy<='0'; PE_Instr_En<='0'; iack:='0'; adresse:=256; adresse_rd:=0; timeout:=0; dcount<=0; when Fillmem => if mpi_node_out(1).hold_req='0' then PE_Ram_din<=std_logic_vector(to_unsigned(dcount,8)); -- x"0f"; PE_Instr_En<='0'; dcount<=dcount+1; if dcount=50 then bfill:=bfill+1; if bfill=4 then etputget<=InitApp; else etputget<=nextfill; end if; else adresse:=adresse+1; etputget<=Fillmem; end if; else -- attente de la libéraion de la mémoire timeout:=timeout+1; if timeout=100 then etputget<=st_timeout; end if; end if; when nextfill => --prépare le prochain bloc mémoire qui sera rempli adresse:=100*bfill; dcount<=0; etputget<=Fillmem; PE_Instr_En<='0'; when InitApp => --code pour Init ici --mettre mpi_init à l'adresse mpi PE_Ram_din<=MPI_INIT & x"0" ; adresse:=core_init_adr; PE_Instr_En<='0'; fsrc:=1; adrToSet:=std_logic_vector(to_unsigned(core_init_adr,ADRLEN)); if ret/=fsrc then dcount<=0; etputget<=writeptr; adresse:=core_base_adr+2; PE_Instr_En<='0'; else if Lib_instr_ack='1' then -- attente de la prise en compte de l'instruction etputget<=InitCompleted; PE_instr_en<='0'; else PE_Instr_en<='1'; end if; end if; when writeptr => PE_Instr_En<='0'; if PE_Hold_req = '0' then --s'assurer que le bus est disponible if dcount=0 then PE_RAM_Din<=AdrToSet(Word-1 downto 0); dcount <=dcount+1; --adresse:=adresse+1; --prépare la prochaine écriture elsif dcount=1 then dcount <=dcount+1; adresse:=adresse+1; --prépare la prochaine écriture PE_RAM_Din<=AdrToSet(15 downto 8); elsif dcount=2 then -- ce cycle permet juste de vider le tampon d'écriture en RAM ret:=fsrc; dcount<=0; timeout:=0; if fsrc=1 then etputget <= InitApp; elsif fsrc=2 then etputget <= putdata; elsif fsrc=3 then etputget <= getdata; else etputget <= start; end if; end if; end if; When InstrCopy => if Lib_instr_ack='1' then etputget<=Writeptr; PE_instr_en<='0'; iack:='1'; else PE_Instr_en<='1'; end if; when InitCompleted => if Lib_Init='1' then etputget<=putdata; PE_Instr_En<='0'; else PE_Instr_En<='0'; end if; when putdata => --construire le packet pour le Put DestRank:=1; adresse_rd:=core_base_adr+Core_Rank2port_base+DestRank; PE_Instr_En<='0'; timeout:=0; dcount<=0; fsrc:=2; adrToSet:=std_logic_vector(to_unsigned(core_put_adr,ADRLEN)); if ret/=fsrc then adresse:=core_base_adr+2; etputget<=writeptr; ret:=0; else if Lib_instr_ack/='1' then etputget<= putdata2; end if; end if; when putdata2 => if ramsel = '0' then --si le PE a accès à la RAM dlen:=to_integer(unsigned(datalen)); pMPI_put(clkm,destrank,SrcAdr1 & Srcadr0,DestAdr1 & DestAdr0,Dlen,sram,ct); adresse:=to_integer(unsigned(sram.addr_wr)); PE_ram_din<=sram.data_in; dcount<=ct; if dcount<=6 then -- -- PE_Instr_En<='0'; -- if dcount=0 then -- adresse:=core_put_adr; -- PE_Ram_din<=MPI_PUT & std_logic_vector(to_unsigned(Dpid,4)); -- elsif dcount=1 then -- adresse:=core_put_adr+dcount; -- PE_Ram_din<=Datalen ; -- elsif dcount=2 then -- adresse:=core_put_adr+dcount; -- PE_Ram_din<=SrcAdr1 ; -- elsif dcount=3 then -- adresse:=core_put_adr+dcount; -- PE_Ram_din<=SrcAdr0 ; -- elsif dcount=4 then -- adresse:=core_put_adr+dcount; -- PE_Ram_din<=DestAdr1 ; -- elsif dcount=5 then -- adresse:=core_put_adr+dcount; -- PE_Ram_din<=DestAdr0 ; elsif dcount=7 then --juste après la valeur 6 en fait -- adresse:=core_base_adr+1; -- adresse_rd:=core_base_adr; -- PE_Ram_din<=x"01"; --instruction pulse enable; PE_Instr_En<='1'; -- end if; -- dcount<=dcount+1; -- end if; elsif PE_instr_En='0' then timeout:=timeout+1; if timeout>=10 then -- reprendre le contrôle du Bus de force si nécessaire ram_busy<='1'; timeout:=0; PE_Instr_En<='0'; end if; end if; if dcount >=6 then Ram_busy<='0';--libérer le bus et attendre la réponse du Core MPI if Lib_instr_ack='1' then -- Instruction ack PE_Instr_En<='0'; if Ramsel='0' then adresse:=core_base_adr+1; PE_Ram_din<=x"00"; --ramener le IPulse à 0; Ram_busy<='0'; etPutGet<=putcompleted; else Ram_busy<='1'; --force la prise du bus end if; else timeout:=timeout+1; if timeout=150 then etputget<=st_timeout; end if; end if; end if; when putcompleted => adresse_rd:=core_put_adr+6; if PE_Ram_do(0)='1' then --Put completed etPutGet<=GetData; end if; PE_Instr_En<='0'; when getdata => --positionnement du mot de longueur des données DestRank:=1; timeout:=0; dcount<=0; fsrc:=3; adrToSet:=std_logic_vector(to_unsigned(core_get_adr,ADRLEN)); if ret/=fsrc then adresse:=core_base_adr+2; etputget<=writeptr; ret:=0; else adresse:=core_get_adr; etputget<= getdata2; end if; PE_Instr_En<='0'; when getdata2 => if ramsel='0' then pMPI_get(clkm,destrank,SrcAdr1 & Srcadr0,DestAdr1 & DestAdr0,Dlen,sram,ct); adresse:=to_integer(unsigned(sram.addr_wr)); PE_ram_din<=sram.data_in; dcount<=ct; if dcount<=6 then -- if dcount<=0 then -- adresse:=core_get_adr; -- PE_Ram_din<=MPI_GET & std_logic_vector(to_unsigned(Dpid,4)); -- elsif dcount=1 then -- adresse:=core_get_adr+dcount; -- PE_Ram_din<=Datalen ; -- elsif dcount=2 then -- adresse:=core_get_adr+dcount; -- PE_Ram_din<=SrcAdr1 ; -- elsif dcount=3 then -- adresse:=core_get_adr+dcount; -- PE_Ram_din<=SrcAdr0 ; -- elsif dcount=4 then -- adresse:=core_get_adr+dcount; -- PE_Ram_din<=DestAdr1 ; -- elsif dcount=5 then -- adresse:=core_get_adr+dcount; -- PE_Ram_din<=DestAdr0 ; elsif dcount=7 then -- adresse:=core_base_adr+1; adresse_rd:=core_base_adr; PE_Instr_En<='1'; -- PE_Ram_din<=x"01"; --instruction pulse enable; timeout:=0; end if; -- dcount<=dcount+1; -- end if; elsif PE_Instr_En='0'then timeout:=timeout+1; if timeout>=10 then -- reprendre le contrôle du Bus de force si nécessaire ram_busy<='1'; timeout:=0; PE_Instr_En<='0'; end if; end if; if dcount >=6 then Ram_busy<='0';--libérer le bus et attendre la réponse du Core MPI if Lib_instr_ack='1' then -- Instruction ack PE_Instr_En<='0'; if Ramsel='0' then adresse:=core_base_adr+1; PE_Ram_din<=x"00"; --ramener le IPulse à 0; Ram_busy<='0'; etPutGet<=getcompleted; else Ram_busy<='1'; --force la prise du bus end if; else timeout:=timeout+1; if timeout=150 then etputget<=st_timeout; end if; end if; end if; when getcompleted => adresse_rd:=core_get_adr+6; PE_Instr_En<='0'; if PE_Ram_do(0)='1' then --Put completed if Ramsel='0' then adresse:=core_base_adr+1; PE_Ram_din<=x"00"; --ramener le IPulse à 0; etPutGet<=Terminate; else timeout:=timeout+1; end if; end if; when terminate => etputget<=start; when st_timeout => --if ram_busy='1' then etputget<=start; --end if etputget<=start; end case; pe_Ram_addra<=STD_LOGIC_VECTOR(to_unsigned(adresse,ADRLEN)); pe_Ram_addrb<=STD_LOGIC_VECTOR(to_unsigned(adresse_rd,ADRLEN)); end if; --reset='1' end if; end process pPutGet; majPutGet:process (etputget) begin case etputget is when start => PE_Ram_we<='0'; PE_Ram_ena<='0'; PE_Ram_enb<='0'; --PE_Instr_En<='0'; when fillmem => PE_Ram_we<='1'; PE_Ram_ena<='1'; PE_Ram_enb<='0'; --PE_Instr_En<='0'; when nextfill => PE_Ram_we<='1'; PE_Ram_ena<='1'; PE_Ram_enb<='0'; --PE_Instr_En<='0'; when InitApp => PE_Ram_we<='1'; PE_Ram_ena<='1'; PE_Ram_enb<='0'; --PE_Instr_En<='0'; when Initcompleted => --PE_Instr_En<='1'; when writeptr => PE_Ram_we <='1'; --écriture dans la RAM PE_Ram_ena <='1'; PE_Ram_enb <='0'; -- dcount<=dcount+1; --PE_Instr_En<='0'; when InstrCopy => --instruction copy PE_Ram_we<='0'; PE_Ram_ena<='0'; PE_Ram_enb<='0'; when putdata => --positionnement du mot de longueur des données --dcount<=0; srcadr0<=X"00"; srcadr1<=X"01"; destadr0<=X"00"; destadr1<=X"02"; PE_Ram_we<='0'; PE_Ram_ena<='0'; --lecture du n° de port de destination PE_Ram_enb<='1'; datalen<=std_logic_vector(to_unsigned(50,8)); dpid_i<=to_integer(unsigned(PE_ram_do(3 downto 0))); --le port est situé ur les 4 bits de poids faible --PE_Instr_En<='0'; when putdata2 => PE_Ram_we <='1'; --écriture dans la RAM PE_Ram_ena <='1'; PE_Ram_enb <='0'; -- dcount<=dcount+1; if dcount>=5 then --PE_Instr_En<='1'; else --PE_Instr_En<='0'; end if; when putcompleted => PE_Ram_we <='1'; PE_Ram_ena <='1'; -- lecture du résultat PE_Ram_enb <='1'; --PE_Instr_En<='1'; when getdata => --dcount<=0; srcadr0<=X"00"; srcadr1<=X"02"; destadr0<=X"00"; destadr1<=X"03"; datalen<=std_logic_vector(to_unsigned(50,8)); --PE_Instr_En<='0'; when getdata2 => PE_Ram_we <='1'; --écriture dans la RAM PE_Ram_ena <='1'; PE_Ram_enb <='0'; --dcount<=dcount+1; if dcount=5 then --PE_Instr_En<='1'; else --PE_Instr_En<='0'; end if; when getcompleted => PE_Ram_we <='1'; PE_Ram_ena <='1'; -- lecture du résultat PE_Ram_enb <='1'; --PE_Instr_En<='1'; when terminate => PE_Ram_we<='0'; PE_Ram_ena<='0'; PE_Ram_enb<='0'; --PE_Instr_En<='0'; when st_timeout => PE_Ram_we<='0'; PE_Ram_ena<='0'; PE_Ram_enb<='0'; --PE_Instr_En<='0'; end case; end process majPutGet ; hold:process (pe_hold_req,clkm,reset) begin if rising_edge(clkm) then if reset='1' then pe_hold_ack<='0'; else if pe_hold_req='1' then ramsel<=not(ram_busy); pe_hold_ack<=not(ram_busy); --si la mémoire est occupé, forcé une libération else pe_hold_ack<='0'; ramsel<='0'; end if; end if; end if; end process hold; END;