----------------------------------------------------------------------------------
-- Company: 
-- Engineer:  GAMOM NGOUNOU
-- 
-- Create Date:    05:52:25 06/21/2011 
-- Design Name: 
-- Module Name:    CORE_MPI - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
Library NocLib;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use NocLib.CoreTypes.all;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity CORE_MPI is
    Port ( 
				clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
	         clkout : out std_logic;
				instruction : in  STD_LOGIC_VECTOR (Word-1 downto 0);
           instruction_en : in  STD_LOGIC; --valide l'instruction
			  instruction_fifo_full : out  STD_LOGIC;
           ram_data_in : out  STD_LOGIC_VECTOR (Word-1 downto 0);
           barrier_completed : out  STD_LOGIC;
           packet_received : out  STD_LOGIC;
			  packet_ack : in std_logic;
           PushOut : out  STD_LOGIC_VECTOR (Word-1 downto 0); --le resultat de l'exécution
           ram_we : out  STD_LOGIC;
           ram_en : out  STD_LOGIC;
			  ram_address_rd : out  STD_LOGIC_VECTOR (15 downto 0);
			  ram_address_wr : out  STD_LOGIC_VECTOR (15 downto 0);
           ram_data_out : in  STD_LOGIC_VECTOR (Word-1 downto 0);
			  hold_req       : out STD_Logic;  --requete vers application
			  hold_ack       : in  STD_Logic;  --autorisation par l'application
           switch_port_in_cmd_en : out std_logic;
			  switch_port_out_data : in  STD_LOGIC_VECTOR (Word-1 downto 0);
			  switch_port_in_wr_en : out  STD_LOGIC;
           switch_port_in_full : in  STD_LOGIC;
           switch_port_in_data : out  STD_LOGIC_VECTOR (Word-1 downto 0);
           switch_port_out_rd_en : out  STD_LOGIC;
           switch_port_in_empty : in STD_LOGIC;
			  switch_port_out_data_vailaible : in  STD_LOGIC
			  
           
           );
           
end CORE_MPI;

architecture Structural of CORE_MPI is
--déclaration des types
type Type_Noc is
record
 port_in_cmd_en :  std_logic;
 port_out_data :   STD_LOGIC_VECTOR (Word-1 downto 0);
 port_in_wr_en :   STD_LOGIC;
 port_in_empty : STD_LOGIC;
 port_in_full :  STD_LOGIC;
 port_in_data :  STD_LOGIC_VECTOR (Word-1 downto 0);
 port_out_rd_en :  STD_LOGIC;
 port_out_data_available :  STD_LOGIC;
end record;
-- déclaration des composants MPI

COMPONENT FIFO_64_FWFT
	PORT(
		clk : IN std_logic;
		din : IN std_logic_vector(Word-1 downto 0);
		rd_en : IN std_logic;
		srst : IN std_logic;
		wr_en : IN std_logic;          
		dout : OUT std_logic_vector(Word-1 downto 0);
		empty : OUT std_logic;
		full : OUT std_logic
		);
END COMPONENT;
COMPONENT load_instr 
    Port ( Instruction : in  STD_LOGIC_VECTOR (Word-1 downto 0);
           Instruction_en : in  STD_LOGIC;
           clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           dma_rd_grant : in  STD_LOGIC;
           dma_rd_request : out  STD_LOGIC;
           instruction_ack : out  STD_LOGIC;
           fifo_din : out  STD_LOGIC_VECTOR (Word-1 downto 0);
			  fifo_wr :out std_logic;
           fifo_full : in  STD_LOGIC;
			  copying : out std_logic;
			  Ram_rd_en : out STD_LOGIC;
           ram_address_rd : out  STD_LOGIC_VECTOR (ADRLEN-1 downto 0);
           ram_data : in  STD_LOGIC_VECTOR (WORD-1 downto 0));
end component;
COMPONENT DMA_ARBITER
	PORT(
		
		clk : IN std_logic;
		reset : IN std_logic;
		dma_rd_request : IN std_logic_vector(3 downto 0);
		data_wr_in : IN std_logic_vector(Word-1 downto 0);
		data_rd_out : out std_logic_vector(Word-1 downto 0);
		address_rd : IN std_logic_vector(15 downto 0);
		address_wr : IN std_logic_vector(15 downto 0);
		
		dma_wr_request : IN std_logic_vector(3 downto 0);          
		address_out_rd : OUT std_logic_vector(15 downto 0);
		address_out_wr : OUT std_logic_vector(15 downto 0);
		ram_en : OUT std_logic;
		ram_we : OUT std_logic;
		hold_req       : out STD_Logic;  --requete vers application
		hold_ack       : in  STD_Logic;  --autorisation par l'application
		data_wr_mem  : OUT std_logic_vector(Word-1 downto 0); 
		data_rd_mem  : IN std_logic_vector(Word-1 downto 0);
		dma_wr_grant : OUT std_logic_vector(3 downto 0);
		dma_rd_grant : OUT std_logic_vector(3 downto 0)
		);
END COMPONENT;

COMPONENT EX1_FSM
	PORT(
		clk : IN std_logic;
		reset : IN std_logic;
		
		pid : in std_logic_vector (3 downto 0); --port id
		nprocs : in std_logic_vector (3 downto 0); -- la taille du Noc
		instruction_en : in std_logic;
		fifo_empty : IN std_logic;
		fifo_data_out : IN std_logic_vector(Word-1 downto 0);
		fifo_rd_en : OUT std_logic;
		fifo_src : IN STD_LOGIC;
		ram_data_in : IN std_logic_vector(Word-1 downto 0);
		ram_data_out : out std_logic_vector(Word-1 downto 0);
		dma_rd_grant : IN std_logic;   
		dma_wr_grant : IN std_logic;   		
		dma_wr_request : OUT std_logic;
		dma_rd_request : OUT std_logic;
		ram_address : OUT std_logic_vector(15 downto 0);
		ram_rd,ram_wr : out std_logic;
				
		priority_rotation : OUT std_logic;
		
		switch_port_in_data : OUT std_logic_vector(Word-1 downto 0);
		switch_port_in_wr_en : OUT std_logic;
		switch_port_in_full : IN std_logic;
		Result :out std_logic_vector(Word-1 downto 0);
		AppInitReq :out  STD_LOGIC; -- requête d'initialisation de l'application
		AppInitAck :in  STD_LOGIC; -- Acquitement d'initialisation
		Initialized:in   std_logic  -- état de la Lib
		);
	END COMPONENT;	
	
COMPONENT EX2_FSM
	PORT(
		clk : IN std_logic;
		reset : IN std_logic;
		
		instruction_en: in std_logic;
		Initialized : in std_logic;
		
		switch_port_out_rd_en : OUT std_logic ;
		switch_data_available : IN std_logic;
		switch_port_out_data : IN std_logic_vector(Word-1 downto 0);
		AppRank : in  STD_LOGIC_VECTOR;
      AppSize : in  STD_LOGIC_VECTOR;		  
		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_address : OUT std_logic_vector(15 downto 0);
		ram_rd,ram_wr : out std_logic;
		Ram_data_out : out STD_LOGIC_VECTOR (Word-1 downto 0);
		Ram_data_in : in STD_LOGIC_VECTOR (Word-1 downto 0);
		fifo_full : IN std_logic;
		fifo_data : OUT std_logic_vector(Word-1 downto 0);
		fifo_wr_en : OUT std_logic;
		--fifo_out : out std_logic_vector;
		
		packet_received : OUT std_logic;
		packet_ack : IN std_logic;
		barrier_completed : OUT std_logic;
		Ready : Out std_logic;
		AppInitAck : in std_logic;
		AppInitReq : out std_logic
		);
	END COMPONENT;


	COMPONENT EX3_FSM
	PORT(
		instruction : IN std_logic_vector(Word-1 downto 0);
		clk : IN std_logic;
		reset : IN std_logic;     
		Ismain :in std_logic;
		ResOut : OUT std_logic_vector(Word-1 downto 0)
		
		);
	END COMPONENT;
	
	COMPONENT EX4_FSM
	PORT(
    		  Instruction : in  STD_LOGIC_VECTOR (Word-1 downto 0); --permet de lire le FIFO
           Instruction_En : in  STD_LOGIC;
           clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           ResultOut : out  STD_LOGIC_VECTOR (Word-1 downto 0);
           Result_En : out  STD_LOGIC; 
           NocSize : out  STD_LOGIC_VECTOR;
           AppRank : out  STD_LOGIC_VECTOR;
           AppSize : out  STD_LOGIC_VECTOR;
           IsMain : out  STD_LOGIC;
			  Initialized : out STD_LOGIC;
			  dma_wr_req : out std_logic;
			  dma_wr_grant : in std_logic;
           AdrRam : out  STD_LOGIC_VECTOR (15 downto 0); --accès au stockage
           WeRam : out  STD_LOGIC; --activation de l'écriture en RAM
           DataRam : out  STD_LOGIC_VECTOR (Word-1 downto 0);--données des ports
           AppAck : in  STD_LOGIC;
           AppReq : in  STD_LOGIC;
			  PortId : out  STD_LOGIC_VECTOR(3 downto 0);
			  port_in_cmd_en : out  STD_LOGIC;
			  port_in_wr_en : out  STD_LOGIC;
			  port_in_empty : in  STD_LOGIC;
           port_in_full : in  STD_LOGIC;
           port_in_data : out  STD_LOGIC_VECTOR (Word-1 downto 0);
			  port_out_data : in  STD_LOGIC_VECTOR (Word-1 downto 0);
           port_out_rd_en : out  STD_LOGIC;
           port_out_data_available : in  STD_LOGIC);
	END COMPONENT;
	
	COMPONENT EX0_FSM
	PORT(	
			clk : in  STD_LOGIC;
         reset : in  STD_LOGIC;
	
			Initialized : in  STD_LOGIC;
         Instruction : in  STD_LOGIC_VECTOR (Word-1 downto 0);
			instruction_en: in STD_LOGIC;
         
         ClkRate : in  STD_LOGIC_VECTOR ;
			uTimeResult : out  STD_LOGIC_VECTOR; 
			TickResult : out STD_LOGIC_VECTOR
			  );
	END COMPONENT;


COMPONENT MPI_CORE_SCHEDULER
	PORT(
		clk : IN std_logic;
		reset : IN std_logic;
		priority_rotation : IN std_logic;
		instruction_fifo_empty : IN std_logic;
		instruction_fifo_rd_en : OUT std_logic;
		instruction_fifo_data : IN std_logic_vector(Word-1 downto 0);
		instruction_available : OUT std_logic;
		
		get_request_fifo_empty : IN std_logic;
		get_request_fifo_rd_en : OUT std_logic;
		get_request_fifo_data : IN std_logic_vector(Word-1 downto 0);
		
		fifo_rd_en : IN std_logic;          
		fifo_empty : OUT std_logic;
		fifo_selected : OUT std_logic;
		
		data_out : OUT std_logic_vector(Word-1 downto 0)
		
		
		);
	END COMPONENT;
	
-- declaration des signaux d'interconnexion entre les modules du coresignal fifo_sel: std_logic;  -- indique l'un des deux fifos d'instructions qui sont prêts
signal fifo_instr : std_logic;  -- une instruction est prête dans les fifos d'instruction


signal scheduler_fifo_empty : std_logic;
signal scheduler_data_out : std_logic_vector(Word-1 downto 0);
signal dma_arbiter_data_rd_out : std_logic_vector(Word-1 downto 0);

signal scheduler_priority_rotation : std_logic;
signal scheduler_rd_en : std_logic;

signal dma_data_rd,dma_data_wr : std_logic_vector(Word-1 downto 0); -- bus à 3 états
signal dma_rd_address,dma_rd_address1,dma_rd_address2 : std_logic_vector(15 downto 0);  -- ces bus doivent être gérés en logique 3 états!
signal dma_rd_address3 : std_logic_vector(15 downto 0);
signal dma_wr_address1,dma_wr_address3 : std_logic_vector(15 downto 0);
signal dma_wr_address2,dma_wr_address4 : std_logic_vector(15 downto 0);
signal dma_wr_address : std_logic_vector(15 downto 0);
signal switch_port_in_data_signal : std_logic_vector(Word-1 downto 0);
signal ram_data_out_signal : std_logic_vector(Word-1 downto 0);
signal weram,rdram,ram_wev,ram_env :std_logic:='0';

signal instruction_fifo2_signal : std_logic_vector(Word-1 downto 0);
signal Ex_EN : std_logic_vector(4 downto 1):=(others=>'0'); --active les sous MAE permettant de décoder les instructions MPI
signal Ex1_RDY,Ex2_RDY,EX3_RDY,EX4_RDY : std_logic; -- indique la fin de l'exécution de la MAE
signal ex1_ram_rd,ex2_ram_rd,ex4_ram_rd ,Exi_ram_rd: std_logic ; -- validation lecture des données en RAM
signal ex1_ram_wr,ex2_ram_wr,ex4_ram_wr,Exi_ram_wr : std_logic ; -- validation écriture des données en RAM
signal Exi_busy : std_logic;
signal Ex1_Result,Ex4_result : std_logic_vector(Word-1 downto 0);

--================interface DMA avec les modules ======================================
signal dma_data_in,Dma_data_in1,dma_data_in2,dma_data_in4   : std_logic_vector(Word-1 downto 0);
signal dma_data_out  : std_logic_vector(Word-1 downto 0);
signal dma_rd_request :std_logic_vector(4 downto 1):=(others=>'0');
signal dma_wr_request :std_logic_vector(4 downto 1):=(others=>'0');
signal dma_wr_grant,dma_rd_grant:std_logic_vector(4 downto 1);
--
--======================================================================================
--connexion au switch

signal Noc1,NOC2,NOC3 : Type_Noc; -- regroupement des signaux qui vont au Noc

--================================================================
--déclaration des signaux d'état du Core
signal IsMain,SizeSet,RankSet,Initialized,AppReq,AppAck:std_logic;
signal InitReq,InitReq1,InitReq2   :std_logic; -- demande d'initialisation
signal InitAck,IAck,Ilatch : std_logic;
signal MPISize,MyRank : std_logic_vector(3 downto 0);
signal LibState: std_logic_vector(Word-1 downto 0); --ready,receiving,sending,spawning,rwaiting,swaiting,...
signal NocSize :std_logic_vector(3 downto 0);
Signal PortId : std_logic_vector(3 downto 0);
Signal uClkRate : std_logic_vector(Word-1 downto 0):="00011010"; --50 Mhz
signal uTimeCount :std_logic_vector(31 downto 0);
signal TickCount : std_logic_vector(31 downto 0);
signal RankSize: std_logic_vector(Word-1 downto 0);
--========================================================
--déclaration des signaux permettant d'activer le module
signal AdrSelect : std_logic_vector(ADRLEN-1 downto 0);
--========================================================
--signal PushOut_d,RankSize,TickUsOut:std_logic_vector; --résultat de l'execution des commandes mpi
--========================================================
--connexion avec les FIFO instructions
signal fifo1_wr : std_logic;
signal fifo1_din : std_logic_vector (Word-1 downto 0);
signal fifo_sel : std_logic;   --permet d'arbitrer la priorité de lecture entre les deux fifos
signal instruction_fifo1_rd_en : std_logic;
signal fifo1_full : std_logic;
signal instruction_fifo1_empty : std_logic;
signal instruction_fifo1_data_out : std_logic_vector(Word-1 downto 0);
signal instruction_fifo2_rd_en : std_logic;
signal instruction_fifo2_data_out : std_logic_vector(Word-1 downto 0);
signal instruction_fifo2_data_in : std_logic_vector(Word-1 downto 0);
signal instruction_fifo2_wr_en : std_logic;
signal instruction_fifo2_empty : std_logic;
signal instruction_fifo2_full : std_logic;

--===========================================================

begin
--switch_port_in_data_signal <= ;
--switch_port_out_data_signal <= ;
-- istanciation des composants du core MPI
Instruction_Fifo1: FIFO_64_FWFT PORT MAP(
		clk =>clk,
		din =>fifo1_din,
		rd_en => instruction_fifo1_rd_en,
		srst => reset,
		wr_en => fifo1_wr,
		dout =>instruction_fifo1_data_out,
		empty => instruction_fifo1_empty,
		full => fifo1_full
	);

Instruction_Fifo2: FIFO_64_FWFT PORT MAP(
		clk =>clk,
		din => instruction_fifo2_data_in ,
		rd_en =>instruction_fifo2_rd_en,
		srst =>reset,
		wr_en =>instruction_fifo2_wr_en,
		dout =>instruction_fifo2_data_out,
		empty =>instruction_fifo2_empty,
		full => instruction_fifo2_full 
	);
LD_instr:load_instr PORT MAP (

			  Instruction =>Instruction,
           Instruction_en =>Instruction_en,
           clk =>clk,
           reset =>reset,
           dma_rd_grant =>dma_rd_grant(3),
           dma_rd_request =>dma_rd_request(3), 
			  copying=> Exi_busy,
           instruction_ack =>iack,    --indique la fin de la copie d'une instruction dans le FIFO
           fifo_din => fifo1_din,
			  fifo_wr =>  fifo1_wr,
           fifo_full =>fifo1_full,
			  Ram_rd_en=> Exi_ram_rd,
           ram_address_rd => dma_rd_address3,
           ram_data =>dma_data_out    --sortie DMA
);

pushout(0)<=ILatch;
pushout(1)<=IsMain;
pushout(2)<=SizeSet;
pushout(3)<=RankSet;
pushout(4)<=Initialized;
pushout(5)<=Ex1_result(1); --


MPI_CORE_EX0_FSM: EX0_FSM PORT MAP(
		instruction => instruction_fifo1_data_out,
		instruction_en=> '1',
		uTimeResult => uTimeCount,
		TickResult => TickCount,
		Initialized => Initialized,  -- indique si la l'appel à init a été concluant
		ClkRate => uClkRate,
		clk =>clk ,
		reset => reset 
	);
MPI_CORE_EX1_FSM: EX1_FSM PORT MAP(
		clk =>clk ,
		reset =>reset,
		pid => MyRank,  --port Id
		nprocs=>MPISize,      -- à revoir dans certains cas ou tous les PEs ne sont pas connectés
		fifo_empty => scheduler_fifo_empty ,
		fifo_data_out =>scheduler_data_out,
		fifo_rd_en =>scheduler_rd_en,
		fifo_src =>fifo_sel,
		priority_rotation => scheduler_priority_rotation,
		
		instruction_en=>Ex_en(1),  			 --active le module
		
		switch_port_in_full =>Noc1.port_in_full, --ces signaux doivent être contrôlés en 3 state logic
		switch_port_in_data =>Noc1.port_in_data,
		switch_port_in_wr_en =>Noc1.Port_in_wr_en ,
							          
		Ram_rd => ex1_ram_rd,
		Ram_wr =>ex1_ram_wr,
		ram_data_in =>dma_data_out,
		Ram_data_out =>dma_data_in1,
		ram_address=>dma_wr_address1,
		--ram_address =>dma_rd_address2,  --la même adresse sert pour la lecture ou l'écriture
		dma_rd_request =>dma_rd_request(1),
		dma_wr_request =>dma_wr_request(1),
		dma_rd_grant =>dma_rd_grant(1) ,
		dma_wr_grant =>dma_wr_grant(1) ,
		
		AppInitReq => InitReq1, -- requête d'initialisation de l'application
		AppInitAck =>Ex4_rdy  , -- Acquitement d'initialisation
		Initialized=>Initialized,  -- état de la Lib
		Result => Ex1_Result     -- le résultat de l'exécution
	);
instruction_fifo_full<=fifo1_full;
dma_rd_address1<=dma_wr_address1;  --la même adresse sert pour la lecture ou l'écriture en RAM

-- détermination de l'activation des module
--scheduler_priority_rotation<=not(Ex1_rdy);
Instr_Rdy:process(Iack,fifo_instr,fifo_sel)--A qoui sert encore ce processus (26/10/12) ????
begin
	case fifo_sel is
			when '0' =>
			
				if rising_edge(Iack) then
					Ex_en(1)<= fifo_instr; 
					
				end if;
				--Ex_en(2)<='0';	
			
			when '1' =>
				Ex_en(1)<=fifo_instr;	
				--Ex_en(2)<= fifo_instr;
			when others =>
				Ex_en(1)<='0';	
				--Ex_en(2)<= '0';
			
	end case;
end process;

Active_proc:Process(Ex1_Result) --active la réception lorsqu' Put ou un Get ou un Init a été effectué
begin
	if Ex1_result(0)='1' or Ex1_result(1)='1' or Ex1_result(2)='1' then
		Ex_en(2)<='1';
	else
		--Ex_en(2)<='0';
	end if;
	
end process;
						
Latch_instr:process (clk,Iack,Exi_busy)
begin
				if rising_edge(clk) then
				 
					Ilatch<=IAck;
					
				end if;
				
end process;
--Ex_en(2)<=Initialized; --- Me pose des soucis en ce moment ???
Ex_en(3)<='0';
Ex_en(4)<= '1' when InitReq='1'  else '0';
Appreq<=Ex_en(4);  --signal d'activation de la MAE Init
InitReq<=(not(Initialized) and InitReq1) or InitReq2; -- deux cas permettent d'activer l'initialisation
AppAck<=Ex1_result(0); -- signal init completed
-- soit une requête du PE soit une requête du Core


MPI_CORE_EX2_FSM: EX2_FSM PORT MAP(
		
		clk =>clk,
		reset =>reset,
		instruction_en=>Ex_en(2),
		Ready =>Ex2_rdy,      				--signale que le module est disponible
		fifo_full =>instruction_fifo2_full,
		
		fifo_wr_en => instruction_fifo2_wr_en,
		fifo_data => instruction_fifo2_data_in,
		
		switch_port_out_rd_en => Noc2.port_out_rd_en, 
		switch_data_available =>Noc2.port_out_data_available,
		switch_port_out_data =>Noc2.port_out_data ,
													-- il manque un signal pour valider l'accès à la RAM
		dma_wr_request =>dma_wr_request(2),
		dma_wr_grant =>dma_wr_grant(2),
		dma_rd_request =>dma_rd_request(2),
		dma_rd_grant =>dma_rd_grant(2),
		ram_address =>dma_wr_address2,
		Ram_rd => ex2_ram_rd,
		Ram_wr =>ex2_ram_wr,
		Ram_data_out=> Dma_data_in2,
		Ram_data_in => Dma_data_out,
		packet_received =>packet_received,
		packet_ack => packet_ack,
		barrier_completed =>barrier_completed,
		AppRank =>MyRank,
      AppSize =>MPISize,
		AppInitReq => InitReq2, -- requête d'initialisation de l'application
		AppInitAck =>Ex4_rdy  , -- Acquitement d'initialisation
		Initialized=>Initialized 
		
	);
Dma_rd_address2<=Dma_wr_address2;	
ICI_MPI_CORE_EX3_FSM: EX3_FSM PORT MAP(
		instruction => instruction,
		ResOut => RankSize,
		clk =>clk ,
		IsMain=>IsMain,
		reset => reset 
	);
MPI_CORE_EX4_FSM :EX4_FSM PORT MAP (
			  Instruction => Instruction,  --STD_LOGIC_VECTOR (Word-1 downto 0);
           Instruction_En =>Ex_en(4),  -- ='1' lorsque ce module est sollicité
           clk  =>clk,
           reset =>reset,
           ResultOut =>Ex4_Result, --STD_LOGIC_VECTOR (Word-1 downto 0);
           Result_En =>Ex4_Rdy, -- ='1' lorsque fin de l'exécution du module
           NocSize =>NocSize,
           AppRank =>MyRank,
           AppSize =>MPISize,
           IsMain =>IsMain,
			  Initialized =>Initialized,
           AdrRam =>dma_wr_Address4, 	--accès au stockage
           WeRam =>Ex4_Ram_wr, 			--activation de l'écriture en RAM
           DataRam =>Dma_data_in4,	   --données à écrire en RAM
			  DMA_wr_Req => dma_wr_request(4),
			  DMA_wr_grant => dma_wr_grant(4),
           AppAck =>AppAck,
           AppReq =>AppReq,
			  PortId=>PortId,
			  port_in_cmd_en => Noc3.port_in_cmd_en,
			  port_in_wr_en =>Noc3.port_in_wr_en,
			  port_in_empty =>Noc3.port_in_empty,
           port_in_full =>Noc3.port_in_full,
           port_in_data =>Noc3.port_in_data,
			  port_out_data =>Noc3.port_out_data,
           port_out_rd_en =>Noc3.port_out_rd_en,
           port_out_data_available =>Noc3.port_out_data_available


);
--=============Mux des signaux d'accès à la RAM=========
ram_we<='1' when (weram='1' and ram_wev ='1') else '0'; -- le contrôleur DMA contrôle directement
Ram_en<= '1' when (rdram ='1' or weram='1')  else '0'; -- les signaux qui vont vers la RAM 

 --dma_data_in <=dma_data_in1 or dma_data_in2;
 --dma_data_out <=dma_data_out1 or dma_data_out2;
 mux_ad_ram_rd:process (dma_rd_grant,dma_rd_address1,dma_rd_address2,dma_rd_address3,
								ex1_ram_rd, Ex2_ram_rd, Exi_ram_rd )
begin
   case dma_rd_grant is
      when "0001" => dma_rd_address <= dma_rd_address1;
							rdram<= ex1_ram_rd;
      when "0010" => dma_rd_address <= dma_rd_address2;
							rdram<= ex2_ram_rd;
      when "0100" => dma_rd_address <= dma_rd_address3;
							rdram<= exi_ram_rd;
--      when "1000" => dma_rd_address <= <input4>;
      when others => dma_rd_address <= (others =>'Z');
							rdram<='0';
   end case;
end process;
 mux_ad_ram_wr:process (dma_wr_grant,dma_wr_address1,dma_wr_address2,dma_wr_address4,Dma_data_in1,Dma_data_in2,Dma_data_in4,ex2_ram_wr,ex4_ram_wr)
begin
   case dma_wr_grant is
      
		when "0001" => dma_wr_address <= dma_wr_address1;
							weram<=ex1_ram_wr ;
							Dma_data_in<=Dma_data_in1;
		when "0010" => dma_wr_address <= dma_wr_address2;
							weram<=ex2_ram_wr ;
							Dma_data_in<=Dma_data_in2;
      when "1000" => dma_wr_address <= dma_wr_address4;
							weram<=ex4_ram_wr;
							Dma_data_in<=Dma_data_in4;
--      when "0100" => dma_rd_address <= <input3>;
--      when "1000" => dma_rd_address <= <input4>;
      when others => dma_wr_address <= (others =>'Z');
							weram<='0';
   end case;
end process;
--======================================================

--=================Mux des signaux qui vont au switch============  
 clkout<=clk;   -- permettra le lien avec le module du switch 

 NOC1.port_out_data<=switch_port_out_data; 
 NOC1.port_out_data_available<=switch_port_out_data_vailaible;
 NOC1.port_in_empty<=switch_port_in_empty;
 NOC1.port_in_full<=switch_port_in_full;
 
 NOC2.port_out_data<=switch_port_out_data; 
 NOC2.port_out_data_available<=switch_port_out_data_vailaible;
 NOC2.port_in_empty<=switch_port_in_empty;
 NOC2.port_in_full<=switch_port_in_full;
 
 NOC3.port_out_data<=switch_port_out_data; 
 NOC3.port_out_data_available<=switch_port_out_data_vailaible;
 NOC3.port_in_empty<=switch_port_in_empty;
 NOC3.port_in_full<=switch_port_in_full;
 mux_Noc:process (Ex_en,Noc1,Noc2,Noc3)

begin
		
     case Ex_en is 
	  
	  when"0001" =>
			   switch_port_in_data <=Noc1.port_in_data;
			   switch_port_out_rd_en<=NOC2.port_out_rd_en;
			   switch_port_in_wr_en <=NOC1.port_in_wr_en;
			   switch_port_in_cmd_en <='0';
	  when "0010" =>
				switch_port_in_data <=Noc1.port_in_data;
				switch_port_out_rd_en<=NOC2.port_out_rd_en;
				switch_port_in_wr_en <=NOC1.port_in_wr_en;
				switch_port_in_cmd_en <='0';
	 when"0011" =>
			   switch_port_in_data <=Noc1.port_in_data;
			   switch_port_out_rd_en<=NOC2.port_out_rd_en;
			   switch_port_in_wr_en <=NOC1.port_in_wr_en;
			   switch_port_in_cmd_en <='0';		
	  when "1001" | "1010" =>   --ca où un appel à init est effectué
				switch_port_in_data <=Noc3.port_in_data;
				switch_port_out_rd_en<=NOC3.port_out_rd_en;
				switch_port_in_wr_en <=NOC3.port_in_wr_en;
				switch_port_in_cmd_en <=NOC3.port_in_cmd_en;
	  
	  when others =>
			   switch_port_in_data <=(others=>'0');
			   switch_port_out_rd_en<='0';
			   switch_port_in_wr_en <='0';
			   switch_port_in_cmd_en <='0';
		end  case;  
	end process;


--===============================================================
MPI_CORE_DMA_ARBITER: DMA_ARBITER PORT MAP(
		clk =>clk,
		reset =>reset,
		
		data_wr_mem => ram_data_in, --vers RAM
		  
		data_rd_mem => Ram_data_out, --- Vers RAM 
		address_rd =>dma_rd_address,
		address_wr =>dma_wr_address,
		address_out_rd =>ram_address_rd,
		address_out_wr =>ram_address_wr,
		ram_en => ram_env,  --validation lecture
		ram_we =>ram_wev,  --validation écriture
		hold_req=>hold_req,--demande de bus à l'application
		hold_ack=>hold_ack, -- libération du bus RAM par l'application
		
		data_rd_out => Dma_data_out, --vers périphérique
		data_wr_in =>Dma_data_in,   --vers périphérique
		dma_wr_grant =>dma_wr_grant,
		dma_rd_request => dma_rd_request,
		dma_rd_grant => dma_rd_grant,
		dma_wr_request => dma_wr_request 
	);
	

CORE_SCHEDULER: MPI_CORE_SCHEDULER PORT MAP( -- permet de sélectionner la source de l'instruction 
														-- qui sera exécutée par la MAE EX1
		clk => clk,
		reset => reset,
		priority_rotation =>scheduler_priority_rotation,
		instruction_fifo_empty =>instruction_fifo1_empty,
		get_request_fifo_empty => instruction_fifo2_empty,
		instruction_fifo_rd_en =>instruction_fifo1_rd_en,
		get_request_fifo_rd_en =>instruction_fifo2_rd_en ,
		instruction_fifo_data =>instruction_fifo1_data_out,
		get_request_fifo_data =>instruction_fifo2_data_out,
		fifo_selected =>fifo_sel,
		instruction_available => fifo_instr,
		fifo_empty => scheduler_fifo_empty,
		fifo_rd_en =>scheduler_rd_en,
		data_out => scheduler_data_out
	);

end structural;

