-- Package File Template -- -- Purpose: This package defines supplemental types, subtypes, -- constants, and functions library IEEE; use IEEE.STD_LOGIC_1164.all; use ieee.numeric_std.all; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; Library NocLib; use NocLib.CoreTypes.all; use work.PACKET_TYPE.all; package Mpi_Rma is procedure WritePtr(AdrVect:in std_logic_vector; count: inout natural;signal SysRam :out typ_dpram); procedure pMPI_INIT(NextCtx : inout natural;signal Interf:inout Core_io;signal clkin:std_logic;signal SysRam :inout typ_dpram); procedure pMPI_PUT(NextCtx : inout natural;signal Interf:inout Core_io;signal clkin:std_logic;signal SysRam :inout typ_dpram; Orig_Addr: std_logic_vector;Orig_Count : natural; Orig_DataType: natural; Target_Rank : natural; Target_disp : std_logic_vector; Target_Count : natural; Target_Datatype :natural; Win : natural); procedure pMPI_GET(NextCtx : inout natural;signal Interf:inout Core_io;signal clkin:std_logic;signal SysRam :inout typ_dpram; Orig_Addr: std_logic_vector;Orig_Count : natural; Orig_DataType: natural; Target_Rank : natural; Target_disp : std_logic_vector; Target_Count : natural; Target_Datatype :natural; Win : natural); procedure pMPI_Comm_Rank(NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; COMM :in natural; signal Rank : out std_logic_vector ); procedure pMPI_Win_create(NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; base :std_logic_vector; size : Mpi_Aint;disp_unit:natural; info:natural; comm:Mpi_Comm; Win: inout MPI_Win ); procedure pMPI_Win_start( NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; pgroup:MPI_group;asser : natural; Win :MPI_Win); procedure pMPI_Win_wait( NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; Win :MPI_Win); procedure pMPI_Comm_Spawn(NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; command : natural; argv :natural; maxprocs : natural; info : natural; root : natural; comm : natural; signal intercomm :out natural; signal array_of_errcodes : out natural); -- declare functions and procedure procedure ReadMem( NextCtx : inout natural range 0 to 255;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; AdrVect:in std_logic_vector; data: out std_logic_vector); procedure WriteMem(NextCtx : inout natural range 0 to 255;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; AdrVect:in std_logic_vector; Data:in std_logic_vector); end MPI_Rma; package body MPI_Rma is ----int MPI_Put( -- void *origin_addr, -- int origin_count, -- MPI_Datatype origin_datatype, -- int target_rank, -- MPI_Aint target_disp, -- int target_count, -- MPI_Datatype target_datatype, -- MPI_Win win --); -- Example 1 procedure pMPI_PUT(NextCtx : inout natural;signal Interf:inout Core_io;signal clkin:std_logic;signal SysRam :inout typ_dpram; Orig_Addr: std_logic_vector;Orig_Count : natural; Orig_DataType: natural; Target_Rank : natural; Target_disp : std_logic_vector; Target_Count : natural; Target_Datatype :natural; Win : natural) is variable i,dcount : natural:=0; variable adresse :natural; variable addr1 :std_logic_vector(Orig_Addr'length-1 downto 0):=Orig_Addr; variable addr2 :std_logic_vector(Target_Disp'length-1 downto 0):=Target_Disp; variable put_adr : std_logic_vector (ADRLEN-1 downto 0); variable config_reg: std_logic_vector (Word-1 downto 0); constant LeftZero: std_logic_vector(2*Word-ADRLEN to 0):=(others=>'0'); begin put_adr:=Std_logic_vector(to_unsigned(Core_put_adr,ADRLEN)); addr1:=Orig_Addr; addr2:=Target_Disp; if NextCtx /=0 then --préserver la valeur de count entre les appels dcount:=NextCtx; end if; -- if rising_edge(clkin) then if dcount>=0 and dcount <=3 then if interf.I.ramsel='0' then Interf.O.membusy<='0'; SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; WritePtr (put_adr,dcount,SysRam); if dcount =4 then -- fin de l'écriture du pointeur en mémoire end if; end if; elsif dcount=4 then if interf.I.ramsel='0' then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; Interf.O.membusy<='1'; adresse:=core_put_adr; SysRam.O.Data_in<=MPI_PUT & std_logic_vector(to_unsigned(Target_Rank,4)); --code fonction SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); dcount:=dcount+1; end if; elsif dcount=5 then if interf.I.ramsel='0' then adresse:=core_put_adr+1; SysRam.O.Data_in<=std_logic_vector(to_unsigned(Orig_Count,8)) ;--la longueur SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); dcount:=dcount+1; Interf.O.Instruction<=x"06"; -- nombre de mots de l'instruction end if; elsif dcount=6 then if interf.I.ramsel='0' then adresse:=core_put_adr+2; SysRam.O.Data_in<= Addr1(ADRLEN-1 downto Word) ; --source Haut SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); dcount:=dcount+1; end if; elsif dcount=7 then if interf.I.ramsel='0' then adresse:=core_put_adr+3; SysRam.O.Data_in<=Addr1(Word-1 downto 0); --source Bas SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); dcount:=dcount+1; end if; elsif dcount=8 then if interf.I.ramsel='0' then adresse:=core_put_adr+4; SysRam.O.Data_in<= Addr2(ADRLEN-1 downto Word) ; -- destination haut SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); dcount:=dcount+1; end if; elsif dcount=9 then if interf.I.ramsel='0' then adresse:=core_put_adr+5; SysRam.O.Data_in<=Addr2(Word-1 downto 0); -- destination bas SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); dcount:=dcount+1; end if; elsif dcount=10 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='1'; if interf.I.ramsel='0' then adresse:=core_base_adr+1; SysRam.O.addr_rd<=std_logic_vector(to_unsigned(core_base_adr+1,ADRLEN)); SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); SysRam.O.Data_in<=x"01"; --instruction pulse enable via la mémoire; Interf.O.Instr_En<='1'; --active la prise en compte de l'instruction Interf.O.membusy<='0'; dcount:=dcount+1; end if; elsif dcount=11 then if Interf.I.Instr_ack='1' then -- le Core a reçu l'instruction ? Interf.O.Instr_En<='0'; --désactiver la prise en compte de l'instruction dcount:=dcount+1; config_reg:=SysRam.I.Data_out and x"f6"; SysRam.O.Data_in<=config_reg ; --ramener le IPulse à 0; else Interf.O.Instr_En<='1'; end if; adresse:=core_base_adr+1; SysRam.O.addr_rd<=std_logic_vector(to_unsigned(core_base_adr+1,ADRLEN)); SysRam.O.addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); --SysRam.O.Ram_busy<='0'; --?? SysRam.O.we<='0'; SysRam.O.ena<='0'; -- préparer la lecture du résultat du Put SysRam.O.enb<='1'; elsif dcount=12 then adresse:=core_base_adr+1; SysRam.O.we<='1'; SysRam.O.ena<='1'; -- préparer l'écriture du résultat du Put SysRam.O.enb<='1'; if interf.I.ramsel='0' then config_reg:=SysRam.I.Data_out and x"f6"; SysRam.O.Data_in<=config_reg ; --ramener le IPulse à 0; dcount:=dcount+1; Interf.O.membusy<='1'; end if; SysRam.O.addr_rd<=std_logic_vector(to_unsigned(core_base_adr+1,ADRLEN)); SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); elsif dcount=13 then SysRam.O.we<='1'; SysRam.O.ena<='1'; -- préparer l'écriture du résultat du Put SysRam.O.enb<='0'; config_reg:=SysRam.I.Data_out and x"f6"; SysRam.O.Data_in<=config_reg ; --ramener le IPulse à 0; dcount:=dcount+1; adresse:=core_base_adr+1; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); elsif dcount=14 then SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; Interf.O.membusy<='0'; if interf.I.ramsel='0' then SysRam.O.addr_rd<=Std_logic_vector(to_unsigned(Core_put_adr+6,Adrlen)); if SysRam.I.Data_out(0)='1' then --fin du MPI PUT ici pour l'envoie ! dcount:=dcount+1; SysRam.O.addr_rd<=Std_logic_vector(to_unsigned(Core_put_adr+7,Adrlen)); Interf.S.Intstate2<=255; --timer pour la réception end if; end if; elsif dcount=15 then dcount:=dcount+1; -- ce cycle permet d'attendre la donnée en sortie après le changement d'adresse elsif dcount=16 then if interf.I.ramsel='0' then dcount:=dcount+1; -- ce cycle permet d'attendre la donnée en sortie après le changement d'adresse end if; elsif dcount=17 then SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; Interf.O.membusy<='0'; if interf.I.ramsel='0' then SysRam.O.addr_rd<=Std_logic_vector(to_unsigned(Core_put_adr+7,Adrlen)); if SysRam.I.Data_out(5)='1' then --Message du MPI PUT bien reçu ! dcount:=dcount+1; SysRam.O.addr_rd<=Std_logic_vector(to_unsigned(Core_put_adr+7,Adrlen)); elsif Interf.S.Intstate2>0 then Interf.S.Intstate2<=Interf.S.Intstate2-1; else -- dcount:=1;--recommencer l'envoi end if; end if; elsif dcount=18 then dcount:=0; --fin normale de la fonction Interf.O.membusy<='0'; end if; NExtCtx:=dcount; end if; end procedure; procedure pMPI_GET(NextCtx : inout natural;signal Interf:inout Core_io;signal clkin:std_logic;signal SysRam :inout typ_dpram; Orig_Addr: std_logic_vector;Orig_Count : natural; Orig_DataType: natural; Target_Rank : natural; Target_disp : std_logic_vector; Target_Count : natural; Target_Datatype :natural; Win : natural) is variable i,wcount,dcount : natural range 0 to 255:=0; variable adresse :natural; variable addr1 :std_logic_vector(Orig_Addr'length-1 downto 0):=Orig_Addr; variable addr2 :std_logic_vector(Target_Disp'length-1 downto 0):=Target_Disp; variable get_adr : std_logic_vector (ADRLEN-1 downto 0); variable config_reg,win_reg: std_logic_vector (Word-1 downto 0); constant LeftZero: std_logic_vector(2*Word-ADRLEN to 0):=(others=>'0'); begin get_adr:=Std_logic_vector(to_unsigned(Core_get_adr,ADRLEN)); addr1:=Orig_Addr; addr2:=Target_Disp; if NextCtx /=0 then --préserver la valeur de count entre les appels dcount:=NextCtx; end if; -- if rising_edge(clkin) then if dcount =0 then dcount:=dcount+1; elsif dcount>=1 and dcount <=3 then if interf.I.ramsel='0' then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; wcount:=Interf.S.IntState1; WritePtr (get_adr,wcount,SysRam); Interf.S.IntState1<=wcount; Interf.O.membusy<='1'; if wcount =0 then dcount:=4; end if; end if; elsif dcount=4 then if interf.I.ramsel='0' then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; adresse:=core_get_adr; SysRam.O.Data_in<=MPI_GET & std_logic_vector(to_unsigned(Target_Rank,4)); --code fonction SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); Interf.O.membusy<='1'; dcount:=dcount+1; end if; elsif dcount=5 then if interf.I.ramsel='0' then SysRam.O.we<='1'; SysRam.O.ena<='1'; adresse:=core_get_adr+1; SysRam.O.Data_in<=std_logic_vector(to_unsigned(Orig_Count,8)) ;--la longueur SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); interf.O.Instruction<=x"06"; --le nbre de mots de l'intstruction dcount:=dcount+1; end if; elsif dcount=6 then if interf.I.ramsel='0' then SysRam.O.we<='1'; SysRam.O.ena<='1'; adresse:=core_get_adr+2; SysRam.O.Data_in<= Addr1(ADRLEN-1 downto Word) ; --source Haut SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); dcount:=dcount+1; else dcount:=dcount-1; end if; elsif dcount=7 then if interf.I.ramsel='0' then SysRam.O.we<='1'; SysRam.O.ena<='1'; adresse:=core_get_adr+3; SysRam.O.Data_in<=Addr1(Word-1 downto 0); --source Bas SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); dcount:=dcount+1; else dcount:=dcount-1; end if; elsif dcount=8 then if interf.I.ramsel='0' then SysRam.O.we<='1'; SysRam.O.ena<='1'; adresse:=core_get_adr+4; SysRam.O.Data_in<= Addr2(ADRLEN-1 downto Word) ; -- destination haut SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); Interf.O.membusy<='1'; dcount:=dcount+1; else dcount:=dcount-1; end if; elsif dcount=9 then if interf.I.ramsel='0' then SysRam.O.we<='1'; SysRam.O.ena<='1'; adresse:=core_get_adr+5; SysRam.O.Data_in<=Addr2(Word-1 downto 0); -- destination bas SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); Interf.O.membusy<='0'; dcount:=dcount+1; end if; elsif dcount=10 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='1'; adresse:=core_base_adr+1; SysRam.O.addr_rd<=std_logic_vector(to_unsigned(core_base_adr+1,ADRLEN)); SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); SysRam.O.Data_in<=x"01"; --instruction pulse enable via la mémoire; Interf.O.Instr_En<='1'; --active la prise en compte de l'instruction if interf.I.ramsel='0' then dcount:=dcount+1; end if; elsif dcount=11 then if Interf.I.Instr_ack='1' then -- le Core a reçu l'instruction ? Interf.O.Instr_En<='0'; --désactiver la prise en compte de l'instruction dcount:=dcount+1; config_reg:=SysRam.I.Data_out and x"f6"; SysRam.O.Data_in<=config_reg ; --ramener le IPulse à 0; end if; adresse:=core_base_adr+1; SysRam.O.addr_rd<=std_logic_vector(to_unsigned(core_base_adr+1,ADRLEN)); SysRam.O.addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); --SysRam.O.Ram_busy<='0'; --?? SysRam.O.we<='0'; SysRam.O.ena<='0'; -- préparer la lecture du résultat du get SysRam.O.enb<='1'; Interf.O.membusy<='0'; elsif dcount=12 then adresse:=core_base_adr+1; SysRam.O.we<='1'; SysRam.O.ena<='1'; -- préparer l'écriture du résultat du get SysRam.O.enb<='1'; if interf.I.ramsel='0' then config_reg:=SysRam.I.Data_out and x"f6"; SysRam.O.Data_in<=config_reg ; --ramener le IPulse à 0; dcount:=dcount+1; Interf.O.membusy<='1'; end if; SysRam.O.addr_rd<=std_logic_vector(to_unsigned(core_base_adr+1,ADRLEN)); SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); elsif dcount=13 then SysRam.O.we<='1'; SysRam.O.ena<='1'; -- préparer l'écriture du résultat du GET SysRam.O.enb<='0'; adresse:=core_base_adr+1; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); if interf.I.ramsel='0' then config_reg:=SysRam.I.Data_out and x"f6"; SysRam.O.Data_in<=config_reg ; --ramener le IPulse à 0; dcount:=dcount+1; Interf.O.membusy<='0'; end if; elsif dcount=14 then SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; Interf.O.membusy<='0'; if interf.I.ramsel='0' then SysRam.O.addr_rd<=Std_logic_vector(to_unsigned(Core_get_adr+6,Adrlen)); if SysRam.I.Data_out(0)='1' then --fin du MPI get ici pour l'envoie ! dcount:=dcount+1; end if; end if; elsif dcount=15 then dcount:=0; --fin normale de la fonction Interf.O.membusy<='0'; end if; NExtCtx:=dcount; end if; end procedure; Procedure pMPI_Comm_group(NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam : inout typ_dpram; COMM :in MPI_Comm; signal grp : out Mpi_group ) is Begin --cette procédure permet de récupérer le groupe qui est associé à un communicateur --dans notre cas c'est la récupération du groupe associé à COMM_WORLD end procedure; --int MPI_Group_incl(MPI_Group group, int n, int *ranks, -- MPI_Group *newgroup) Procedure pMPI_group_incl(NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam : inout typ_dpram; GRP: Mpi_group; n:natural;ranks :natural; newgroup: out Mpi_group) is Begin -- cette procedure a pour algo de parcourir les rangs qui sont dans la mémoire pointée par ranks -- et d'activer l'un des bits de position de newgroup. -- -- end procedure; procedure pMPI_Comm_Rank(NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; COMM :in natural; signal Rank : out std_logic_vector ) is variable adresse_rd : natural range 0 to 2**ADRLEN-1; begin if NextCtx =0 then SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; adresse_rd:=CORE_INIT_ADR+1; SysRam.O.Addr_rd<=Std_logic_vector(to_unsigned(adresse_rd,ADRLEN)); NextCtx:=1; elsif NextCtx=1 then SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; adresse_rd:=CORE_INIT_ADR+1; SysRam.O.Addr_rd<=Std_logic_vector(to_unsigned(adresse_rd,ADRLEN)); if interf.I.ramsel='0' then Rank<=SysRam.I.Data_out(3 downto 0); NextCtx:=2; Interf.O.membusy<='1'; end if; elsif NextCtx=2 then SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; adresse_rd:=CORE_INIT_ADR+1; SysRam.O.Addr_rd<=Std_logic_vector(to_unsigned(adresse_rd,ADRLEN)); if interf.I.ramsel='0' then Rank<=SysRam.I.Data_out(3 downto 0); NextCtx:=3; Interf.O.membusy<='1'; end if; elsif NextCtx=3 then SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; adresse_rd:=CORE_INIT_ADR+1; SysRam.O.Addr_rd<=Std_logic_vector(to_unsigned(adresse_rd,ADRLEN)); if interf.I.ramsel='0' then Rank<=SysRam.I.Data_out(3 downto 0); NextCtx:=4; Interf.O.membusy<='1'; end if; elsif NextCtx=4 then SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; adresse_rd:=CORE_INIT_ADR+1; SysRam.O.Addr_rd<=Std_logic_vector(to_unsigned(adresse_rd,ADRLEN)); if interf.I.ramsel='0' then Rank<=SysRam.I.Data_out(3 downto 0); NextCtx:=0; Interf.O.membusy<='0'; end if; end if; end procedure; --int MPI_Win_create( -- void *base, -- MPI_Aint size, -- int disp_unit, -- MPI_Info info, -- MPI_Comm comm, -- MPI_Win *win --); procedure pMPI_Win_create(NextCtx : inout natural ;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; base :std_logic_vector; size : Mpi_Aint;disp_unit:natural; info:natural; comm:Mpi_Comm; Win: inout MPI_Win ) is -- parcours de la liste des fenêtres existantes à la recherche d'un emplacement libre -- si fenêtre libre trouvée, et -- mise à 1 du Bit WCreate du registre status type wtype is array (1 to 4 ) of natural range 0 to 255; variable AdrWin: std_logic_vector(ADRLEN-1 downto 0); variable adresse : std_logic_vector(ADRLEN-1 downto 0); variable clkin : std_logic:='1'; variable wcreate_adr : std_logic_vector(ADRLEN-1 downto 0):=std_logic_vector(to_unsigned(Core_wcreate_adr,ADRLEN)); variable w0 : std_logic_vector(Word-1 downto 0); variable adrnat : natural; variable sizewin : std_logic_vector(Word-1 downto 0); variable count : natural range 0 to 255; variable wdisp :wtype:=(4,14,24,34); --stocke l'adresse de la prochaine Win libre begin -- création d'une fenêtre il s'agit d'affecter l'objet Win et de retourner -- le pointeur qui permet de le décrire If NextCtx=0 then NExtCtx:=NextCtx+1; count:=0; Interf.O.membusy<='0'; Interf.S.IntState1<=count; elsif NextCtx>=1 and NextCtx <= 4 then count:=Interf.S.IntState1; AdrWin:=std_logic_vector(to_unsigned(Core_base_adr+Wdisp(NextCtx),16)); readmem(count,interf,sysRam,AdrWin,w0); if count=0 then if w0(0)/='1' then -- cette fenêtre est libre NextCtx:=6; --étape de la création de la fenêtre Win.addr:=base; --l'adresse de la fenêtre Win.id:=NextCtx; -- la référence provisoire de la fenêtre Win.size:=Size; -- la taille de la fenêtre else NextCtx:=NextCtx+1; end if; end if; Interf.S.IntState1<=count;--sauvegarde du statut de la sous-procédure elsif NextCtx=5 then -- Plus de fenêtre disponible erreur NextCtx:=1; -- boucle sans fin :) Win.id:=0; Win.addr:=x"0000"; elsif NextCtx=6 then --Affectation de l'objet Windows car une place est disponible count:=Interf.S.IntState1; AdrWin:=std_logic_vector(to_unsigned(Core_base_adr+Wdisp(Win.id),16)); Writemem(count,interf,SysRam,AdrWin,x"01"); --signal status pour created Interf.S.IntState1<=count; if count=0 then NextCtx:=NextCtx+1; end if; elsif NextCtx=8 then AdrWin:=std_logic_vector(to_unsigned(Core_base_adr+Wdisp(Win.id),16)); interf.S.winid<=interf.S.winid+1; count:=Interf.S.IntState1; Writemem(count,interf,SysRam,AdrWin+1,stdlv(interf.S.winid,8)); --win id de la fenêtre Interf.S.IntState1<=count; if count=0 then NextCtx:=NextCtx+1; end if; elsif NextCtx=9 then adrnat:=Core_base_adr+Wdisp(Win.id); AdrWin:=std_logic_vector(to_unsigned(Core_base_adr+Wdisp(Win.id),16)); count:=Interf.S.IntState1; Writemem(count,interf,SysRam,AdrWin+2,base(7 downto 0)); --adresse basse Interf.S.IntState1<=count; if count=0 then NextCtx:=NextCtx+1; end if; elsif NextCtx=10 then AdrWin:=std_logic_vector(to_unsigned(Core_base_adr+Wdisp(Win.id),16)); count:=Interf.S.IntState1; Writemem(count,interf,SysRam,AdrWin+3,base(15 downto 8)); --adresse haute Interf.S.IntState1<=count; if count=0 then NextCtx:=NextCtx+1; end if; elsif NextCtx=11 then AdrWin:=std_logic_vector(to_unsigned(Core_base_adr+Wdisp(Win.id),16)); sizewin:=std_logic_vector(to_unsigned(size,8)); count:=Interf.S.IntState1; Writemem(count,interf,SysRam,AdrWin+4,sizewin); -- taille de la fenêtre Interf.S.IntState1<=count; if count=0 then NextCtx:=NextCtx+1; end if; elsif NextCtx=12 then --cette étape consiste à envoyer le message WINCREATE Sur le réseau et à récupérer -- les informations donnant le numéro de la fenêtre W0:=MPI_WINCREATE & std_logic_vector(to_unsigned(0,4)); --code fonction count:=Interf.S.IntState1; Writemem(count,interf,SysRam,wcreate_adr,w0); Interf.S.IntState1<=count; if count=0 then NextCtx:=NextCtx+1; end if; elsif NextCtx=13 then w0:=std_logic_vector(to_unsigned(Win.Id,8)); -- id proposé pour la fenêtre en création count:=Interf.S.IntState1; Writemem(count,interf,SysRam,wcreate_adr+1,w0); Interf.S.IntState1<=count; if count=0 then NextCtx:=NextCtx+1; end if; elsif NextCtx=14 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; count:=Interf.S.IntState1; if interf.I.ramsel='0' then WritePtr (wcreate_adr,count,SysRam); --écriture du pointeur d'instruction Interf.S.IntState1<=count; if count=0 then NextCtx:=NextCtx+1; end if; end if; elsif NextCtx=15 then -- il faut mettre instruction_en à 1 SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='1'; adresse:=stdlv(core_base_adr+1); SysRam.O.addr_rd<=adresse; SysRam.O.Addr_wr<=adresse; SysRam.O.Data_in<=x"01"; --instruction pulse enable via la mémoire; Writemem(count,interf,SysRam,adresse,x"01"); Interf.S.IntState1<=count; if count=0 then NextCtx:=NextCtx+1; end if; Interf.O.Instr_En<='1'; adresse:=stdlv(core_base_adr); SysRam.O.Addr_rd<=adresse; NextCtx:=NextCtx+1; elsif NextCtx=16 then --acquittement de la copie des données dans le tampon de la lib if Interf.I.Instr_ack='1' then Interf.O.Instr_En<='0'; NextCtx:=NextCtx+1; end if; SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; elsif NextCtx=17 then -- lecture du résultat de l'instruction else end if; end procedure; --int MPI_Win_start( -- MPI_Group group, -- int assert, -- MPI_Win win --); procedure pMPI_Win_start( NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; pgroup:MPI_group;asser : natural; Win :MPI_Win) is --cette fonction active les bits WStart pour chaque processus avec lequel -- la source veut communiquer et par la suite envoie un message de synchro sur le réseau à --chacune de ces cibles variable dcount : natural range 0 to 255:=0; variable cstatus : std_logic_vector(Word-1 downto 0); begin -- retour de l'adresse de de la fenêtre dans la structure Win -- initialisation des bits concernant if NextCtx =0 then NextCtx:=NextCtx+1; elsif NextCtx=1 then if interf.I.ramsel='0' then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; SysRam.O.addr_wr<=Std_logic_vector(to_unsigned(core_base_adr+4,Adrlen)); SysRam.O.Data_in<=x"01"; --mise à 1 du bit WSTART et remise à zero de tous les autres Bits NextCtx:=NextCtx+1; Interf.O.membusy<='1'; end if; elsif NextCtx=2 then if interf.I.ramsel='0' then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; SysRam.O.addr_wr<=Std_logic_vector(to_unsigned(core_base_adr+4,Adrlen)); SysRam.O.Data_in<=x"01"; NextCtx:=NextCtx+1; Interf.O.membusy<='0'; end if; elsif NextCtx=3 then NextCtx:=0; Interf.O.membusy<='0'; end if; end procedure; procedure pMPI_Win_complete( NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; Win :MPI_Win) is begin end procedure; procedure pMPI_Win_post( NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; pgroup:MPI_group;asser : natural; Win :MPI_Win) is --cette fonction active les bits WStart pour chaque processus avec lequel -- la source veut communiquer et par la suite envoie un message de synchro sur le réseau à --chacune de ces cibles begin end procedure; procedure pMPI_Win_wait( NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; Win :MPI_Win) is --permet de synchroniser la fin des opérations sur une fenêtre variable dcount : natural range 0 to 255:=0; variable cstatus : std_logic_vector(Word-1 downto 0); begin if NextCtx =0 then NextCtx:=NextCtx+1; elsif NextCtx=1 then if interf.I.ramsel='0' then SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; SysRam.O.addr_rd<=Std_logic_vector(to_unsigned(core_base_adr+4,Adrlen)); if (SysRam.I.Data_out(5)='1' and SysRam.I.Data_out(4)='1') and SysRam.I.Data_out(2)='0' and SysRam.I.Data_out(1)='0' then NextCtx:=NextCtx+1; end if; end if; elsif NextCtx=2 then NextCtx:=0; end if; end procedure; Procedure pMPI_Finalize(NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam :inout typ_dpram) is begin end procedure; procedure pMPI_Comm_Spawn(NextCtx : inout natural;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; command : natural; argv :natural; maxprocs : natural; info : natural; root : natural; comm : natural; signal intercomm :out natural; signal array_of_errcodes : out natural) is variable i,dcount : natural:=0; variable adresse :natural; variable spawn_adr : std_logic_vector(adrlen-1 downto 0):=Std_logic_vector(to_unsigned(Core_spawn_adr,ADRLEN)); begin spawn_adr:=Std_logic_vector(to_unsigned(Core_spawn_adr,ADRLEN)); if NextCtx =0 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; NextCtx:=1; elsif NextCtx=1 then if interf.I.ramsel='0' then NextCtx:=2; adresse:=core_spawn_adr; SysRam.O.Data_in<=MPI_SPAWN & x"0" ; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); Interf.O.membusy<='1'; Interf.O.Instr_En<='0'; Interf.S.IntState2<=1; -- préparation de la destination du spawn end if; elsif NextCtx=2 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; if interf.I.ramsel='0' then NextCtx:=NextCtx+1; Interf.O.membusy<='1'; adresse:=core_spawn_adr; if interf.I.ismain='1' then ---déclanche l'éxécution de la commande SysRam.O.Data_in<=MPI_spawn & x"0";--Std_logic_vector(to_unsigned(Interf.S.IntState2+2,4)) ; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); else -- envoie d'une commande spawn à la main lib SysRam.O.Data_in<=MPI_spawn & x"0" ; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); Interf.O.Instr_En<='0'; Interf.O.membusy<='1'; end if; end if; elsif NextCtx=3 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; adresse:=core_spawn_adr; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); NextCtx:=NextCtx+1; elsif NextCtx=4 then if interf.I.ramsel='0' then adresse:=core_spawn_adr+1; SysRam.O.Data_in<=std_logic_vector(to_unsigned(4,8)) ;--la longueur SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); Interf.O.Instruction<=x"04"; NextCtx:=NextCtx+1; end if; elsif NextCtx=5 then if interf.I.ramsel='0' then adresse:=core_spawn_adr+2; SysRam.O.Data_in<=std_logic_vector(to_unsigned(maxprocs,8)) ;--le nombre de processus SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); NextCtx:=NextCtx+1; end if; elsif NextCtx=6 then if interf.I.ramsel='0' then adresse:=core_spawn_adr+3; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); SysRam.O.Data_in<=SPAWN_LOAD & std_logic_vector(to_unsigned(maxprocs,4)) ;--l'instruction NextCtx:=NextCtx+1; end if; elsif NextCtx=7 then if interf.I.ramsel='0' then adresse:=core_spawn_adr+3; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); SysRam.O.Data_in<=SPAWN_LOAD & std_logic_vector(to_unsigned(maxprocs,4)) ;--l'instruction NextCtx:=NextCtx+1; report "MPV SPAWN activé " & integer'image(interf.I.Rank); end if; elsif NextCtx=8 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; dcount:=Interf.S.IntState1; if interf.I.ramsel='0' then SysRam.O.Addr_rd<=Std_logic_vector(to_unsigned(Core_base_adr,ADRLEN)); WritePtr (spawn_adr,dcount,SysRam); Interf.O.Instr_En<='0'; Interf.O.membusy<='1'; Interf.S.IntState1<=dcount; if dcount =0 then NextCtx:=NextCtx+1; end if; end if; elsif NextCtx=9 then --fin de la fonction SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; dcount:=0; Interf.O.membusy<='0'; Interf.O.Instr_En<='1'; SysRam.O.Addr_rd<=Std_logic_vector(to_unsigned(Core_base_adr,AdrLen)); NextCtx:=NextCtx+1; elsif NextCtx=10 then --acquittement de la copie des données dans le tampon if Interf.I.Instr_ack='1' then Interf.O.Instr_En<='0'; NextCtx:=NextCtx+1; end if; SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; elsif NextCtx=11 then --lecture de la fin de l'initialisation SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; if interf.I.ramsel='0' then SysRam.O.addr_rd<=Std_logic_vector(to_unsigned(Core_base_adr,Adrlen)); if SysRam.I.Data_out(6)='1' then --spawned NextCtx:=NextCtx+1; intercomm<=1; end if; Interf.O.membusy<='0'; end if; elsif NextCtx =12 then Interf.O.Instr_En<='0'; Interf.O.membusy<='0'; SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='0'; NextCtx:=0; --array_of_errcodes<=0; end if; array_of_errcodes<=NextCtx; end procedure; procedure pMPI_INIT(NextCtx : inout natural;signal Interf:inout Core_io;signal clkin:std_logic;signal SysRam :inout typ_dpram) is variable i,dcount,wcount : natural range 0 to 255:=0; variable adresse :natural; variable LRam : typ_dpRam; variable W0 :std_logic_vector(Word-1 downto 0); variable init_adr : std_logic_vector(adrlen-1 downto 0):=Std_logic_vector(to_unsigned(Core_init_adr,ADRLEN)); begin init_adr:=Std_logic_vector(to_unsigned(Core_init_adr,ADRLEN)); LRam:=SysRam; -- nécessaire pour le débogage if NextCtx =0 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; Interf.S.IntState1<=0; NextCtx:=1; adresse:=core_init_adr; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); Interf.O.Instr_En<='0'; elsif NextCtx=1 then --écriture du ptr d'intruction SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; if interf.I.ramsel='0' then adresse:=core_init_adr; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); Interf.O.Instr_En<='0'; Interf.O.membusy<='1'; wcount:=Interf.S.IntState1; WritePtr (Init_adr,wcount,SysRam); Interf.S.IntState1<=wcount; if wcount =4 then NextCtx:=2; Interf.S.IntState1<=0; adresse:=core_init_adr; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); end if; end if; elsif NextCtx=2 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; adresse:=core_init_adr; SysRam.O.Data_in<=MPI_INIT & x"0" ; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); NextCtx:=3; elsif NextCtx=3 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; adresse:=core_init_adr+1; SysRam.O.Data_in<= x"04" ; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); NextCtx:=NextCtx+1; elsif NextCtx=4 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; adresse:=core_init_adr+2; Interf.O.Instruction<=x"04"; SysRam.O.Data_in<=x"00" ;--longueur de l'instruction SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); NextCtx:=5; elsif NextCtx=5 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; adresse:=core_init_adr+3; SysRam.O.Data_in<= x"00" ; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); NextCtx:=6; elsif NextCtx=6 then SysRam.O.we<='1'; SysRam.O.ena<='1'; SysRam.O.enb<='0'; adresse:=core_init_adr+3; SysRam.O.Data_in<=x"00" ; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); NextCtx:=7; elsif NextCtx=7 then --fin de la fonction SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; dcount:=0; Interf.O.membusy<='0'; Interf.O.Instruction(6)<=Interf.I.Spawned; --- préciser que la HT est dynamique Interf.O.Instr_En<='1'; SysRam.O.Addr_rd<=Std_logic_vector(to_unsigned(Core_base_adr,AdrLen)); NextCtx:=8; elsif NextCtx=8 then --acquittement de la copie des données dans le tampon if Interf.I.Instr_ack='1' then Interf.O.Instr_En<='0'; NextCtx:=9; end if; SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; elsif NextCtx=9 then --lecture de la fin de l'initialisation SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='1'; if interf.I.ramsel='0' then SysRam.O.addr_rd<=Std_logic_vector(to_unsigned(Core_base_adr,Adrlen)); if SysRam.I.Data_out(4)='1' then NextCtx:=10; Interf.S.IntState1<=0; -- initialisation du compteur d'état end if; Interf.O.membusy<='0'; end if; elsif NextCtx =10 then dcount:=Interf.S.IntState1; --permet de sauvegarder l'état interne du compteur readmem(dcount,interf,sysRam,init_Adr,w0); Interf.S.IntState1<=dcount; w0:=SysRam.I.Data_out; if dcount=0 then Interf.I.ismain<=all_zeros(SysRam.I.Data_out(3 downto 0));--Rank=0 -> MainLib NextCtx:=NextCtx+1; end if; elsif NextCtx =11 then Interf.O.Instr_En<='0'; Interf.O.membusy<='0'; SysRam.O.we<='0'; SysRam.O.ena<='0'; SysRam.O.enb<='0'; NextCtx:=0; end if; end procedure; procedure WriteMem(NextCtx : inout natural range 0 to 255;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; AdrVect:in std_logic_vector; Data:in std_logic_vector) is --cette procédure permet d'écrire un mot dans la mémoire du PE(tâche matérielle) --en ayant vérifié que le bus est bien disponible pour l'écriture variable i,dcount : natural:=0; variable adresse :natural; variable AdrToSet :std_logic_vector(AdrVect'length-1 downto 0):=AdrVect; begin if NextCtx /=0 then --préserver la valeur de count entre les appels dcount:=NextCtx; else end if; if dcount=0 then if interf.I.ramsel='0' then dcount :=dcount+1; Interf.O.membusy<='1'; end if; SysRam.O.Data_in<=AdrToSet(Word-1 downto 0); SysRam.O.Addr_wr<=adrToSet; elsif dcount=1 then if interf.I.ramsel='0' then Interf.O.membusy<='1'; dcount :=dcount+1; end if; SysRam.O.Data_in<=data; SysRam.O.Addr_wr<=adrToSet; elsif dcount=2 then SysRam.O.Data_in<=data; dcount :=dcount+1; SysRam.O.Addr_wr<=AdrToSet; elsif dcount=3 then Interf.O.membusy<='1'; dcount :=dcount+1; SysRam.O.Addr_wr<=adrToSet; SysRam.O.Data_in<=data; elsif dcount=4 then -- ce cycle permet juste de vider le tampon d'écriture en RAM dcount:=0; Interf.O.membusy<='0'; SysRam.O.Addr_wr<=AdrToSet; end if; NextCtx:=dcount; end procedure; -- écriture dans la mémoire procedure ReadMem( NextCtx : inout natural range 0 to 255;signal Interf:inout Core_io;signal SysRam :inout typ_dpram; AdrVect:in std_logic_vector; data: out std_logic_vector) is --cette procédure permet d'écrire un mot dans la mémoire du PE(tâche matérielle) --en ayant vérifié que le bus est bien disponible pour l'écriture variable i,dcount : natural:=0; variable adresse :natural; variable AdrToSet :std_logic_vector(AdrVect'length-1 downto 0):=AdrVect; begin if NextCtx /=0 then --préserver la valeur de count entre les appels dcount:=NextCtx; else end if; if dcount=0 then if interf.I.ramsel='0' then dcount :=dcount+1; Interf.O.membusy<='1'; end if; SysRam.O.Addr_rd<=adrToSet; elsif dcount=1 then data:=SysRam.I.Data_out; dcount :=dcount+1; SysRam.O.Addr_rd<=adrToSet; elsif dcount=2 then data:=SysRam.I.Data_out; dcount :=dcount+1; SysRam.O.Addr_rd<=adrToSet; elsif dcount=3 then if interf.I.ramsel='0' then dcount :=dcount+1; SysRam.O.Addr_rd<=adrToSet; data:=SysRam.I.Data_out; Interf.O.membusy<='0'; end if; elsif dcount=4 then -- ce cycle permet juste de vider le tampon d'écriture en RAM dcount:=0; Interf.O.membusy<='0'; data:=SysRam.I.Data_out; end if; data:=SysRam.I.Data_out; NextCtx:=dcount; end procedure; procedure WritePtr(AdrVect:in std_logic_vector; count: inout natural;signal SysRam :out typ_dpram) is --cette procédure permet d'écrire dans la mémoire du PE(tâche matérielle) --les données de l'appel de la procédure variable i,dcount : natural:=0; variable adresse :natural; variable AdrToSet :std_logic_vector(AdrVect'length-1 downto 0):=AdrVect; begin if count /=0 then --préserver la valeur de count entre les appels dcount:=count; else end if; adresse:=Core_base_adr+2; if dcount=0 then SysRam.O.Data_in<=AdrToSet(Word-1 downto 0); dcount :=dcount+1; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); elsif dcount=1 then SysRam.O.Data_in<=AdrToSet(Word-1 downto 0); dcount :=dcount+1; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse,ADRLEN)); elsif dcount=2 then SysRam.O.Data_in<=AdrToSet(ADRLEN-1 downto Word); dcount :=dcount+1; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse+1,ADRLEN)); elsif dcount=3 then dcount :=dcount+1; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse+1,ADRLEN)); SysRam.O.Data_in<=AdrToSet(ADRLEN-1 downto Word); elsif dcount=4 then -- ce cycle permet juste de vider le tampon d'écriture en RAM dcount:=0; SysRam.O.Addr_wr<=Std_logic_vector(to_unsigned(adresse+1,ADRLEN)); end if; count:=dcount; end procedure; end MPI_Rma;