No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Etage1_LectureInstruction.vhd 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. ----------------------------------------------------------------------------------
  2. -- Company: INSA-Toulouse
  3. -- Engineer: Paul Faure
  4. --
  5. -- Create Date: 18.04.2021 21:19:41
  6. -- Module Name: Etage1_LectureInstruction - Behavioral
  7. -- Project Name: Processeur sécurisé
  8. -- Target Devices: Basys 3 ARTIX7
  9. -- Tool Versions: Vivado 2016.4
  10. -- Description: Etage 1 du processeur
  11. -- - Gestion des instructions, lecture en mémoire
  12. -- - Gestion des aléas sur les registres
  13. -- - Gestion des sauts et appels de fonction
  14. --
  15. -- Dependencies:
  16. -- - MemoireInstruction
  17. -- - MemoireAdressesRetour
  18. ----------------------------------------------------------------------------------
  19. library IEEE;
  20. use IEEE.STD_LOGIC_1164.ALL;
  21. use IEEE.STD_LOGIC_UNSIGNED.ALL;
  22. use IEEE.NUMERIC_STD.ALL;
  23. entity Etage1_LectureInstruction is
  24. Generic (Instruction_size_in_memory : Natural; -- Taille d'une instruction en mémoire (Taille d'un code instruction + 3*Taille d'un mot binaire)
  25. Addr_size_mem_instruction : Natural; -- Nombre de bits pour adresser la mémoire d'instruction
  26. Mem_instruction_size : Natural; -- Taille de la mémoire d'instruction (nombre d'instructions stockées)
  27. Nb_bits : Natural; -- Taille d'un mot binaire
  28. Instruction_bus_size : Natural; -- Nombre de bits du bus d'instruction (Taille d'un code instruction)
  29. Nb_registres : Natural; -- Nombre de registres du processeurs
  30. Mem_adresse_retour_size : Natural; -- Taille de la mémoire des adresses de retour (nombre d'adresse maximum) (profondeur d'appel maximale)
  31. Adresse_size_mem_adresse_retour : Natural; -- Nombre de bits pour adresser la mémoire des adresses de retour
  32. Instructions_critiques_lecture_A : STD_LOGIC_VECTOR; -- Vecteur de bit représentant les instruction critiques sur l'opérande A (si le bit i est a un, l'instruction i lit une valeur dans le registre n°opérandeA)
  33. Instructions_critiques_lecture_B : STD_LOGIC_VECTOR; -- Vecteur de bit représentant les instruction critiques sur l'opérande B (si le bit i est a un, l'instruction i lit une valeur dans le registre n°opérandeB)
  34. Instructions_critiques_lecture_C : STD_LOGIC_VECTOR; -- Vecteur de bit représentant les instruction critiques sur l'opérande C (si le bit i est a un, l'instruction i lit une valeur dans le registre n°opérandeC)
  35. Instructions_critiques_ecriture : STD_LOGIC_VECTOR; -- Vecteur de bit représentant les instruction critiques en écriture (toujours sur l'opérande A) (si le bit i est a un, l'instruction i ecrit une valeur dans le registre n°opérandeA)
  36. -- Exemple 1 : Soit MUL i j k avec pour numéro d'instruction 7 avec le comportement Ri <- Rj*Rk
  37. -- Instructions_critiques_lecture_A(7) = '0' --> MUL ne lit pas dans le registre de l'opérande A
  38. -- Instructions_critiques_lecture_B(7) = '1' --> MUL lit dans le registre de l'opérande B
  39. -- Instructions_critiques_lecture_C(7) = '1' --> MUL lit dans le registre de l'opérande C
  40. -- Instructions_critiques_ecriture(7) = '1' --> MUL ecrit dans le registre de l'opérande A
  41. -- Exemple 2 : Soit AFC i val avec pour numéro d'instruction 5 avec le comportement Ri <- val
  42. -- Instructions_critiques_lecture_A(5) = '0' --> AFC ne lit pas dans le registre de l'opérande A
  43. -- Instructions_critiques_lecture_B(5) = '0' --> AFC ne lit pas dans le registre de l'opérande B (pour AFC, B est directement la valeur, pas un numero de registre, il n'y a donc pas de lecture)
  44. -- Instructions_critiques_lecture_C(5) = '0' --> AFC ne lit pas dans le registre de l'opérande C
  45. -- Instructions_critiques_ecriture(5) = '1' --> AFC ecrit dans le registre de l'opérande A
  46. Code_Instruction_JMP : STD_LOGIC_VECTOR; -- Numéro de l'instruction JMP
  47. Code_Instruction_JMZ : STD_LOGIC_VECTOR; -- Numéro de l'instruction JMZ
  48. Code_Instruction_PRI : STD_LOGIC_VECTOR; -- Numéro de l'instruction PRI
  49. Code_Instruction_PRIC : STD_LOGIC_VECTOR; -- Numéro de l'instruction PRIC
  50. Code_Instruction_CALL : STD_LOGIC_VECTOR; -- Numéro de l'instruction CALL
  51. Code_Instruction_RET : STD_LOGIC_VECTOR; -- Numéro de l'instruction RET
  52. Code_Instruction_STOP : STD_LOGIC_VECTOR); -- Numéro de l'instruction STOP
  53. Port ( CLK : in STD_LOGIC; -- Clock
  54. RST : in STD_LOGIC; -- Reset
  55. Z : in STD_LOGIC; -- Flag Zero de l'ALU (utile pour le JMZ)
  56. STD_IN_Request : in STD_LOGIC;
  57. A : out STD_LOGIC_VECTOR (Nb_bits - 1 downto 0); -- Sortie de l'opérande A
  58. B : out STD_LOGIC_VECTOR (Nb_bits - 1 downto 0); -- Sortie de l'opérande B
  59. C : out STD_LOGIC_VECTOR (Nb_bits - 1 downto 0); -- Sortie de l'opérande C
  60. Instruction : out STD_LOGIC_VECTOR (Instruction_bus_size - 1 downto 0)); -- Sortie du code de l'instruction
  61. end Etage1_LectureInstruction;
  62. architecture Behavioral of Etage1_LectureInstruction is
  63. component MemoireInstructions is
  64. Generic (Nb_bits : Natural;
  65. Addr_size : Natural;
  66. Mem_size : Natural);
  67. Port ( Addr : in STD_LOGIC_VECTOR (Addr_size-1 downto 0);
  68. D_OUT : out STD_LOGIC_VECTOR (Nb_bits-1 downto 0) := (others => '0'));
  69. end component;
  70. component MemoireAdressesRetour is
  71. Generic (Nb_bits : Natural;
  72. Addr_size : Natural;
  73. Mem_size : Natural);
  74. Port ( R : in STD_LOGIC;
  75. W : in STD_LOGIC;
  76. D_IN : in STD_LOGIC_VECTOR (Nb_bits-1 downto 0);
  77. RST : in STD_LOGIC;
  78. CLK : in STD_LOGIC;
  79. D_OUT : out STD_LOGIC_VECTOR (Nb_bits-1 downto 0) := (others => '0');
  80. E : out STD_LOGIC;
  81. F : out STD_LOGIC);
  82. end component;
  83. -- Signaux pour récuperer l'instruction de la mémoire
  84. signal Pointeur_instruction : STD_LOGIC_VECTOR (Addr_size_mem_instruction - 1 downto 0) := (others => '0');
  85. signal Pointeur_instruction_next : STD_LOGIC_VECTOR (Addr_size_mem_instruction - 1 downto 0) := (0 => '1', others => '0');
  86. signal Instruction_courante : STD_LOGIC_VECTOR (Instruction_size_in_memory - 1 downto 0) := (others => '0');
  87. -- Tableau pour gérer les aléas des registres (lecture en étage 2 avant écriture en étage 5)
  88. subtype Registre is integer range -1 to Nb_registres - 1;
  89. type Tab_registres is array (1 to 3) of Registre;
  90. signal Tableau : Tab_registres := (others => - 1);
  91. -- Signaux de gestion pour la mémoire des adresses de retour
  92. signal Adresse_Retour : STD_LOGIC_VECTOR (Addr_size_mem_instruction - 1 downto 0) := (others => '0');
  93. signal E : STD_LOGIC;
  94. signal F : STD_LOGIC;
  95. signal R_Aux : STD_LOGIC := '0';
  96. signal W_Aux : STD_LOGIC := '0';
  97. -- constantes pour injecter des bulles dans le pipeline
  98. constant Instruction_nulle : STD_LOGIC_VECTOR (Instruction_bus_size - 1 downto 0) := (others => '0');
  99. constant Argument_nul : STD_LOGIC_VECTOR (Nb_bits - 1 downto 0) := (others => '0');
  100. -- condition pour detecter si une bulle doit être injectée
  101. signal bulles : boolean := false;
  102. -- Compteur pour attendre lors d'un JMZ que l'instruction d'avant soit a l'ALU, ou lors d'un STOP k
  103. signal compteur : integer := 0;
  104. -- Compteur de protection des collisions entre les prints
  105. signal Compteur_PRI : integer range 0 to Nb_bits/4 + 1 := 0;
  106. -- Signal d'arret (STOP 0)
  107. signal locked : boolean := false;
  108. begin
  109. instance : MemoireInstructions
  110. generic map (Nb_bits => Instruction_size_in_memory,
  111. Addr_size => Addr_size_mem_instruction,
  112. Mem_size => Mem_instruction_size)
  113. port map (Addr => Pointeur_Instruction,
  114. D_OUT => Instruction_courante);
  115. instance_MemoireAdressesRetour : MemoireAdressesRetour
  116. generic map (Nb_bits => Addr_size_mem_instruction,
  117. Addr_size => Adresse_size_mem_adresse_retour,
  118. Mem_size => Mem_adresse_retour_size
  119. )
  120. port map ( R => R_Aux,
  121. W => W_Aux,
  122. D_IN => Pointeur_instruction_next,
  123. RST => RST,
  124. CLK => CLK,
  125. D_OUT => Adresse_Retour,
  126. E => E,
  127. F => F
  128. );
  129. process
  130. begin
  131. -- Synchronisation
  132. wait until CLK'event and CLK = '1';
  133. if (RST = '0') then
  134. -- Reset de l'étage
  135. Tableau <= (others => -1);
  136. Pointeur_Instruction <= (others => '0');
  137. compteur <= 0;
  138. Compteur_PRI <= 0;
  139. locked <= false;
  140. C <= Argument_nul;
  141. B <= Argument_nul;
  142. A <= Argument_nul;
  143. Instruction <= Instruction_nulle;
  144. elsif (STD_IN_Request = '0') then
  145. -- Avancement des instructions en écritures dans le pipeline
  146. Tableau(3) <= Tableau(2);
  147. Tableau(2) <= Tableau(1);
  148. Tableau(1) <= -1;
  149. if (Compteur_PRI > 0) then
  150. Compteur_PRI <= Compteur_PRI - 1;
  151. end if;
  152. if (not bulles) then
  153. -- S'il ne faut pas injecter de bulles ont traite l'instruction (Possible code factorisable sur ce if)
  154. if ((Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_CALL) or (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_JMP)) then
  155. -- CAS PARTICULIER : CALL ou JMP, on transmet et on saute
  156. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  157. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  158. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  159. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  160. Pointeur_Instruction <= Instruction_courante (2 * Nb_bits + Addr_size_mem_instruction - 1 downto 2 * Nb_bits);
  161. elsif (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_RET) then
  162. -- CAS PARTICULIER : RET, on transmet et on revient
  163. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  164. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  165. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  166. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  167. Pointeur_Instruction <= Adresse_Retour;
  168. elsif (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_JMZ) then
  169. -- CAS PARTICULIER : JMZ, on attends que l'instruction précedente arrive sur l'ALU, si le flag Zero est a un on saute, sinon on continue normalement
  170. compteur <= compteur + 1;
  171. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  172. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  173. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  174. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  175. if (compteur = 2) then
  176. if (Z = '1') then
  177. Pointeur_Instruction <= Instruction_courante (2 * Nb_bits + Addr_size_mem_instruction - 1 downto 2 * Nb_bits);
  178. else
  179. Pointeur_Instruction <= Pointeur_Instruction + 1;
  180. end if;
  181. compteur <= 0;
  182. end if;
  183. elsif (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_STOP) then
  184. -- CAS PARTICULIER : STOP, si on est bloqué, on ne fait rien, programme arrété
  185. -- sinon, on regarde si l'on doit se bloquer
  186. -- sinon, on incremente le compteur et on attends
  187. if (not locked) then
  188. if (Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits) = Argument_nul) then
  189. locked <= true;
  190. end if;
  191. compteur <= compteur + 1;
  192. if (compteur + 1 = to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits))) * 1000) then
  193. Pointeur_Instruction <= Pointeur_Instruction + 1;
  194. compteur <= 0;
  195. end if;
  196. end if;
  197. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  198. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  199. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  200. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  201. elsif (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_PRI) then
  202. -- CAS PARTICULIER : PRI, on transmet l'instruction et fixe le compteur pour proteger des collisions
  203. Compteur_PRI <= Nb_bits/4 + 1;
  204. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  205. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  206. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  207. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  208. Pointeur_Instruction <= Pointeur_Instruction + 1;
  209. else
  210. -- CAS GENERAL : On transmet l'instruction et les opérandes, si elle est critique en ecriture, on enregistre le registre associé dans le tableau
  211. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  212. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  213. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  214. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  215. if (Instructions_critiques_ecriture(to_integer(unsigned(Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits)))) = '1') then
  216. Tableau(1) <= to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits)));
  217. end if;
  218. Pointeur_Instruction <= Pointeur_Instruction + 1;
  219. end if;
  220. else
  221. -- Si besoin de bulle, on l'injecte
  222. C <= Argument_nul;
  223. B <= Argument_nul;
  224. A <= Argument_nul;
  225. Instruction <= Instruction_nulle;
  226. end if;
  227. end if;
  228. end process;
  229. -- Condition horrible -> Instruction critique en lecture sur A qui lit dans A=i et Ri dans tableau ou instruction critique en lecture sur B qui lit dans B=j et Rj dans tableau ou instruction critique en lecture sur C qui lit dans C=k et Rk dans tableau
  230. bulles <=
  231. (
  232. (
  233. Instructions_critiques_lecture_A(to_integer(unsigned(Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits)))) = '1' -- Intruction critique sur A
  234. )
  235. and
  236. (
  237. (to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits))) = Tableau(1)) -- A est
  238. or
  239. (to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits))) = Tableau(2)) -- dans le
  240. or
  241. (to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits))) = Tableau(3)) -- tableau
  242. )
  243. )
  244. or
  245. (
  246. (
  247. Instructions_critiques_lecture_B(to_integer(unsigned(Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits)))) = '1'
  248. )
  249. and
  250. (
  251. (to_integer(unsigned(Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits))) = Tableau(1))
  252. or
  253. (to_integer(unsigned(Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits))) = Tableau(2))
  254. or
  255. (to_integer(unsigned(Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits))) = Tableau(3))
  256. )
  257. )
  258. or
  259. (
  260. (
  261. Instructions_critiques_lecture_C(to_integer(unsigned(Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits)))) = '1'
  262. )
  263. and
  264. (
  265. (to_integer(unsigned(Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits))) = Tableau(1))
  266. or
  267. (to_integer(unsigned(Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits))) = Tableau(2))
  268. or
  269. (to_integer(unsigned(Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits))) = Tableau(3))
  270. )
  271. )
  272. or
  273. (
  274. (
  275. (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_PRI)
  276. or
  277. (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_PRIC)
  278. )
  279. and
  280. (
  281. not (Compteur_PRI = 0)
  282. )
  283. );
  284. -- Gestion de l'écriture/lecture dans la mémoire des adresses de retour
  285. R_Aux <= '1' when Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_RET and STD_IN_Request = '0' else
  286. '0';
  287. W_Aux <= '1' when Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_instruction_CALL and STD_IN_Request = '0' else
  288. '0';
  289. Pointeur_instruction_next <= Pointeur_instruction + 1;
  290. end Behavioral;