]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blob - hw/exeq.vhd
Add back support for delay slot, but with writing PC+4 when linking and using delay...
[fpga/lx-cpu1/tumbl.git] / hw / exeq.vhd
1 ---------------------------------------------------------------------------------
2 --
3 --  Entity:       exeq
4 --  Filename:     exeq.vhd
5 --  Description:  the Execution (EX) unit for the TUD MB-Lite implementation
6 --
7 --  Author:       Huib Lincklaen Arriens
8 --                Delft University of Technology
9 --                Faculty EEMCS, Department ME&CE, Circuits and Systems
10 --  Date:         September, 2010
11 --
12 --  Modified:     Septemper, 2013: FSL scratched, core customized (Meloun)
13 --                 December, 2010: FSL added (Huib)
14 --                     June, 2011: added code for MUL and BARREL (Huib)
15 --                                 Adapted to work with separate fsl_M-
16 --                                 and fsl_S selectors and automatic
17 --                                 tumbl<_jtag><_fsl>.vhd generation (Huib)
18 --  Remarks:
19 --
20 --------------------------------------------------------------------------------
21
22 LIBRARY IEEE;
23
24 USE IEEE.std_logic_1164.all;
25 USE IEEE.numeric_std.all;
26 USE WORK.mbl_Pkg.all;
27
28
29 ----------------------------------------------------------
30 ENTITY exeq IS
31 ----------------------------------------------------------
32         GENERIC
33         (
34                 USE_HW_MUL_g : BOOLEAN := TRUE;
35                 USE_BARREL_g : BOOLEAN := TRUE;
36                 COMPATIBILITY_MODE_g : BOOLEAN := FALSE
37         );
38         PORT
39         (
40                 IF2ID_i      :  IN IF2ID_Type;
41                 --
42                 ID2EX_i      :  IN ID2EX_Type;
43                 delayBit_i   :  IN STD_LOGIC;
44                 GPRF2EX_i    :  IN GPRF2EX_Type;
45                 EX2IF_o      : OUT EX2IF_Type;
46                 EX2CTRL_o    : OUT EX2CTRL_Type;
47                 HALT_o       : OUT HALT_Type;
48                 --
49                 EX_WRB_i     :  IN WRB_Type;
50                 EX_WRB_o     : OUT WRB_Type;
51                 MEM_WRB_i    :  IN WRB_Type;
52                 --
53                 HAZARD_WRB_i :  IN HAZARD_WRB_Type;
54                 HAZARD_WRB_o : OUT HAZARD_WRB_Type;
55                 --
56                 IMM_LOCK_i   :  IN IMM_LOCK_Type;
57                 IMM_LOCK_o   : OUT IMM_LOCK_Type;
58                 --
59                 MSR_i        :  IN MSR_Type;
60                 MSR_o        : OUT MSR_Type;
61                 --
62                 EX2MEM_o     : OUT EX2MEM_Type
63         );
64 END ENTITY exeq;
65
66 ----------------------------------------------------------
67 ARCHITECTURE rtl OF exeq IS
68 ----------------------------------------------------------
69
70 BEGIN
71
72 p_exeq:
73         PROCESS (ID2EX_i, GPRF2EX_i, EX_WRB_i, MEM_WRB_i,
74                                                 IF2ID_i, delayBit_i, IMM_LOCK_i, MSR_i, HAZARD_WRB_i)
75
76                 -- function needed by BSLL (only if USE_BARREL_g = TRUE)
77                 FUNCTION reverse_bits ( word32 : STD_LOGIC_VECTOR (31 DOWNTO 0) )
78                         RETURN STD_LOGIC_VECTOR IS
79                                 VARIABLE reversed_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
80                 BEGIN
81                 f_rev:
82                         FOR i IN 0 TO 31 LOOP
83                                 reversed_v(31-i) := word32(i);
84                         END LOOP;
85                         RETURN reversed_v;
86                 END;
87
88                 VARIABLE data_rA_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
89                 VARIABLE data_rB_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
90                 VARIABLE data_rD_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
91                 VARIABLE in1_v         : STD_LOGIC_VECTOR (31 DOWNTO 0);
92                 VARIABLE in2_v         : STD_LOGIC_VECTOR (31 DOWNTO 0);
93                 VARIABLE hi16_v        : STD_LOGIC_VECTOR (15 DOWNTO 0);
94                 VARIABLE IMM32_v       : STD_LOGIC_VECTOR (31 DOWNTO 0);
95                 VARIABLE carry_i_v     : STD_LOGIC;
96                 VARIABLE result_v      : STD_LOGIC_VECTOR (31 DOWNTO 0);
97                 VARIABLE carry_o_v     : STD_LOGIC;
98                 VARIABLE isZero_v      : STD_LOGIC;
99                 VARIABLE signBit_in1_v : STD_LOGIC;
100                 VARIABLE signBit_in2_v : STD_LOGIC;
101                 VARIABLE signBit_r_v   : STD_LOGIC;
102                 VARIABLE rA_eq_ex_rD_v : STD_LOGIC;
103                 VARIABLE rB_eq_ex_rD_v : STD_LOGIC;
104                 VARIABLE hazard_v      : STD_LOGIC;
105                 VARIABLE save_rX_v     : SAVE_REG_Type;
106                 VARIABLE data_rX_v     : STD_LOGIC_VECTOR (31 DOWNTO 0);
107                 VARIABLE do_branch_v   : STD_LOGIC;
108                 VARIABLE byte_Enable_v : STD_LOGIC_VECTOR ( 3 DOWNTO 0);
109                 VARIABLE tmp64_v       : STD_LOGIC_VECTOR (63 DOWNTO 0);
110                 VARIABLE padVec_v      : STD_LOGIC_VECTOR (15 DOWNTO 0);
111                 VARIABLE do_cond_v     : STD_LOGIC;
112
113         BEGIN
114
115                 rA_eq_ex_rD_v := '0';
116                 rB_eq_ex_rD_v := '0';
117                 hazard_v      := '0';
118                 save_rX_v     := NO_SAVE;
119                 data_rX_v     := data_rB_v;         -- default value for data_rX_v
120                 result_v      := (OTHERS => '0');
121                 carry_o_v     := '0';
122                 do_branch_v   := '0';
123                 byte_Enable_v := (OTHERS => '0');
124                 do_cond_v     := '0';
125                 --
126     MSR_o         <= MSR_i;             -- pass MSR by default
127
128                 -- create some helper variables
129                 IF (ID2EX_i.rdix_rA = EX_WRB_i.wrix_rD) THEN
130                         rA_eq_ex_rD_v := '1';
131                 END IF;
132                 IF (ID2EX_i.rdix_rB = EX_WRB_i.wrix_rD) THEN
133                         rB_eq_ex_rD_v := '1';
134                 END IF;
135                 -- test where to obtain data_rA from
136                 IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rA_eq_ex_rD_v = '1')) THEN
137                         data_rA_v := EX_WRB_i.data_rD;
138                 ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rA = MEM_WRB_i.wrix_rD)) THEN
139                         data_rA_v := MEM_WRB_i.data_rD;
140                 ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RA)) THEN
141                         data_rA_v := HAZARD_WRB_i.data_rX;
142                 ELSE
143                         data_rA_v := GPRF2EX_i.data_rA;
144                 END IF;
145                 -- test where to obtain data_rB from
146                 IF ((EX_WRB_i.wrb_Action = WRB_EX) AND (rB_eq_ex_rD_v = '1')) THEN
147                         data_rB_v := EX_WRB_i.data_rD;
148                 ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.rdix_rB = MEM_WRB_i.wrix_rD)) THEN
149                         data_rB_v := MEM_WRB_i.data_rD;
150                 ELSIF ((HAZARD_WRB_i.hazard = '1') AND (HAZARD_WRB_i.save_rX = SAVE_RB)) THEN
151                         data_rB_v := HAZARD_WRB_i.data_rX;
152                 ELSE
153                         data_rB_v := GPRF2EX_i.data_rB;
154                 END IF;
155                 -- .... or, isn't all necessary data available yet being still in the pipeline ?
156                 data_rX_v := data_rB_v;                 -- default value for data_rX_v
157                 IF (EX_WRB_i.wrb_Action = WRB_MEM) THEN
158                         IF ((rA_eq_ex_rD_v = '1') OR (rB_eq_ex_rD_v = '1')) THEN
159                                 hazard_v  := '1';
160                                 IF (rA_eq_ex_rD_v = '1') THEN
161                                         save_rX_v := SAVE_RB;   -- already by default data_rX_v = data_rB_v
162                                 ELSE
163                                         save_rX_v := SAVE_RA;
164                                         data_rX_v := data_rA_v;
165                                 END IF;
166                         END IF;
167                 END IF;
168
169                 IF (IMM_LOCK_i.locked = '1') THEN
170                         hi16_v := IMM_LOCK_i.IMM_hi16;
171                 ELSIF (ID2EX_i.IMM16(15) = '0') THEN
172                         hi16_v := C_16_ZEROS;
173                 ELSE
174                         hi16_v :=  C_16_ONES;
175                 END IF;
176                 IMM32_v := hi16_v & ID2EX_i.IMM16;
177
178                 CASE ID2EX_i.alu_Op1 IS
179                         WHEN ALU_IN_REGA      =>  in1_v := data_rA_v;
180                         WHEN ALU_IN_NOT_REGA  =>  in1_v := NOT data_rA_v;
181                         WHEN ALU_IN_PC        =>  in1_v := ID2EX_i.program_counter;
182                         WHEN ALU_IN_ZERO      =>  in1_v := C_32_ZEROS;
183                         WHEN OTHERS           =>  NULL;
184                 END CASE;
185
186                 CASE ID2EX_i.alu_Op2 IS
187                         WHEN ALU_IN_REGB     =>  in2_v := data_rB_v;
188                         WHEN ALU_IN_NOT_REGB =>  in2_v := NOT data_rB_v;
189                         WHEN ALU_IN_IMM      =>  in2_v := IMM32_v;
190                         WHEN ALU_IN_NOT_IMM  =>  in2_v := NOT IMM32_v;
191                         WHEN OTHERS          =>  NULL;
192                 END CASE;
193
194                 signBit_in1_v := in1_v(31);
195                 signBit_in2_v := in2_v(31);
196                 signBit_r_v   := data_rA_v(31); -- Init with Op1, then possibly override
197
198                 CASE ID2EX_i.alu_Cin IS
199                         WHEN CIN_ZERO  =>   carry_i_v := '0';
200                         WHEN CIN_ONE   =>   carry_i_v := '1';
201                         WHEN FROM_MSR  =>   carry_i_v := MSR_i.C;
202                         WHEN FROM_IN1  =>   carry_i_v := in1_v(31);
203                         WHEN OTHERS    =>   carry_i_v := '0';
204                 END CASE;
205
206                 IF (data_rA_v = C_32_ZEROS) THEN
207                         isZero_v := '1';
208                 ELSE
209                         isZero_v := '0';
210                 END IF;
211
212                 CASE ID2EX_i.alu_Action IS
213
214                         WHEN A_ADD | A_CMP | A_CMPU =>
215                                 ep_add32 ( in1_v, in2_v, carry_i_v, result_v, carry_o_v);
216                                 CASE ID2EX_i.alu_Action IS
217
218                                         WHEN A_CMPU  =>
219                                                 IF (signBit_in1_v = signBit_in2_v) THEN
220                                                         signBit_r_v := NOT signBit_in1_v;
221                                                 END IF;
222                                                 IF (COMPATIBILITY_MODE_g = FALSE) AND (ID2EX_i.it_Action /= NO_IT) THEN
223                                                         -- have to update zero flag with current result
224                                                         IF (result_v = C_32_ZEROS) THEN
225                                                                 isZero_v := '1';
226                                                         ELSE
227                                                                 isZero_v := '0';
228                                                         END IF;
229                                                 END IF;
230
231                                         WHEN A_CMP  =>
232                                                 IF (signBit_in1_v = signBit_in2_v) THEN
233                                                         signBit_r_v := signBit_in1_v;
234                                                 END IF;
235                                                 IF (COMPATIBILITY_MODE_g = FALSE) AND (ID2EX_i.it_Action /= NO_IT) THEN
236                                                         -- have to update zero flag with current result
237                                                         IF (result_v = C_32_ZEROS) THEN
238                                                                 isZero_v := '1';
239                                                         ELSE
240                                                                 isZero_v := '0';
241                                                         END IF;
242                                                 END IF;
243
244                                         WHEN OTHERS =>
245                                                 NULL;
246
247                                 END CASE;
248
249                         WHEN A_OR     =>
250                                 result_v  := in1_v  OR in2_v;
251
252                         WHEN A_AND    =>
253                                 result_v  := in1_v AND in2_v;
254
255                         WHEN A_XOR    =>
256                                 result_v  := in1_v XOR in2_v;
257
258                         WHEN A_SHIFT  =>
259                                 result_v  := carry_i_v & in1_v(31 DOWNTO 1);
260                                 carry_o_v := in1_v(0);
261
262                         WHEN A_SEXT8  =>
263                                 IF (in1_v(7) = '0') THEN
264                                         result_v := C_24_ZEROS & in1_v( 7 DOWNTO 0);
265                                 ELSE
266                                         result_v :=  C_24_ONES & in1_v( 7 DOWNTO 0);
267                                 END IF;
268
269                         WHEN A_SEXT16 =>
270                                 IF (in1_v(15) = '0') THEN
271                                         result_v := C_16_ZEROS & in1_v(15 DOWNTO 0);
272                                 ELSE
273                                         result_v :=  C_16_ONES & in1_v(15 DOWNTO 0);
274                                 END IF;
275
276                         WHEN A_MFS    =>
277                                 result_v := MSR_i.C & C_24_ZEROS & "0000" & MSR_i.C & MSR_i.IE & '0';
278
279                         WHEN A_MTS    =>
280                                 MSR_o.IE  <= data_Ra_v(1);
281                                 MSR_o.C   <= data_Ra_v(2);
282
283                         WHEN A_MUL    =>
284                                 IF (USE_HW_MUL_g = TRUE) THEN
285                                         tmp64_v  := STD_LOGIC_VECTOR( UNSIGNED(in1_v) * UNSIGNED(in2_v) );
286                                         result_v := tmp64_v(31 DOWNTO 0);
287                                 END IF;
288
289                         WHEN A_BSLL | A_BSRL | A_BSRA  =>
290                                 IF (USE_BARREL_g = TRUE) THEN
291                                         IF (ID2EX_i.alu_Action = A_BSLL) THEN
292                                                 result_v := reverse_bits (in1_v);
293                                         ELSE
294                                                 result_v := in1_v;
295                                         END IF;
296                                         IF (ID2EX_i.alu_Action = A_BSRA) THEN
297                                                 padVec_v := (OTHERS => in1_v(31));
298                                         ELSE
299                                                 padVec_v := (OTHERS => '0');
300                                         END IF;
301                                         IF (in2_v(4) = '1') THEN
302                                                 result_v := padVec_v (15 DOWNTO 0) & result_v (31 DOWNTO 16);
303                                         END IF;
304                                         IF (in2_v(3) = '1') THEN
305                                                 result_v := padVec_v ( 7 DOWNTO 0) & result_v (31 DOWNTO  8);
306                                         END IF;
307                                         IF (in2_v(2) = '1') THEN
308                                                 result_v := padVec_v ( 3 DOWNTO 0) & result_v (31 DOWNTO  4);
309                                         END IF;
310                                         IF (in2_v(1) = '1') THEN
311                                                 result_v := padVec_v ( 1 DOWNTO 0) & result_v (31 DOWNTO  2);
312                                         END IF;
313                                         IF (in2_v(0) = '1') THEN
314                                                 result_v := padVec_v ( 0 DOWNTO 0) & result_v (31 DOWNTO  1);
315                                         END IF;
316                                         IF (ID2EX_i.alu_Action = A_BSLL) THEN
317                                                 result_v := reverse_bits (result_v);
318                                         END IF;
319                                 END IF;     -- (USE_BARREL_g = TRUE)
320
321                         WHEN OTHERS    =>
322                                 NULL;
323
324     END CASE;
325
326                 CASE ID2EX_i.condition IS
327                         WHEN COND_EQ  => do_cond_v := isZero_v;
328                         WHEN COND_NE  => do_cond_v := NOT isZero_v;
329                         WHEN COND_LT  => do_cond_v := signBit_r_v;
330                         WHEN COND_LE  => do_cond_v := signBit_r_v OR isZero_v;
331                         WHEN COND_GT  => do_cond_v := NOT (signBit_r_v OR isZero_v);
332                         WHEN COND_GE  => do_cond_v := NOT signBit_r_v;
333                         WHEN COND_ALL => do_cond_v := '1';
334                         WHEN OTHERS   => NULL;
335                 END CASE;
336
337                 CASE ID2EX_i.branch_Action IS
338                         WHEN BR     => do_branch_v := do_cond_v;
339                         WHEN BRL    => do_branch_v := '1';
340                         WHEN OTHERS => NULL;
341                 END CASE;
342
343                 IF (do_branch_v = '1') THEN
344                         EX2IF_o.take_branch   <= '1';
345                         EX2IF_o.branch_target <= result_v;
346                 ELSE
347                         EX2IF_o.take_branch   <= '0';
348                         EX2IF_o.branch_target <= C_32_ZEROS;
349                 END IF;
350
351                 -- IT / ITE / ITT conditioning
352                 IF (COMPATIBILITY_MODE_g = FALSE) THEN
353                         CASE ID2EX_i.it_Action IS
354                                 WHEN IT     =>
355                                         EX2CTRL_o.flush_first  <= not do_cond_v;
356                                         EX2CTRL_o.flush_second <= '0';
357                                         EX2CTRL_o.ignore_state <= '1';
358                                 WHEN ITT    =>
359                                         EX2CTRL_o.flush_first  <= not do_cond_v;
360                                         EX2CTRL_o.flush_second <= not do_cond_v;
361                                         EX2CTRL_o.ignore_state <= '1';
362                                 WHEN ITE    =>
363                                         EX2CTRL_o.flush_first  <= not do_cond_v;
364                                         EX2CTRL_o.flush_second <= do_cond_v;
365                                         EX2CTRL_o.ignore_state <= '1';
366                                 WHEN OTHERS =>
367                                         EX2CTRL_o.flush_first  <= '0';
368                                         EX2CTRL_o.flush_second <= '0';
369                                         EX2CTRL_o.ignore_state <= '0';
370                         END CASE;
371                 END IF;
372
373                 -- Halting, the instruction parsing is separate
374                 HALT_o.halt        <= ID2EX_i.halt;
375                 IF (ID2EX_i.halt = '1') THEN
376                         HALT_o.halt_code <= ID2EX_i.IMM16(4 DOWNTO 0);
377                 ELSE
378                         HALT_o.halt_code <= (others => '0');
379                 END IF;
380
381                 -- WR_MEM/RD_MEM:      result_v --> exeq_result --> mem_address,
382                 --        WR_MEM:                       data_rD --> data_out_to_mem
383                 --           BRL:  prog_counter --> exeq_result
384                 --          else       result_v --> exeq_result (data_rD not used)
385                 EX2MEM_o.wrix_rD <= ID2EX_i.curr_rD;
386                 IF (ID2EX_i.branch_Action = BRL) THEN
387                         EX2MEM_o.wrb_Action  <= WRB_EX;
388                         IF (COMPATIBILITY_MODE_g = TRUE) OR (delayBit_i = '0') THEN
389                                 EX2MEM_o.exeq_result <= ID2EX_i.program_counter;
390                                 EX2MEM_o.data_rD     <= ID2EX_i.program_counter;
391                         ELSE
392                                 EX2MEM_o.exeq_result <= IF2ID_i.program_counter;
393                                 EX2MEM_o.data_rD     <= IF2ID_i.program_counter;
394                         END IF;
395                         -- set data_rD_v, although unused, to prevent an inferred latch
396                         data_rD_v := GPRF2EX_i.data_rD;
397                 ELSE
398                         EX2MEM_o.wrb_Action  <= ID2EX_i.wrb_Action;
399                         EX2MEM_o.exeq_result <= result_v;
400                         -- test where to obtain data_rD from
401                         IF (HAZARD_WRB_i.hazard = '1') THEN
402                                 data_rD_v := HAZARD_WRB_i.data_rD;
403                         ELSIF ((EX_WRB_i.wrb_Action = WRB_EX) AND (ID2EX_i.curr_rD = EX_WRB_i.wrix_rD)) THEN
404                         -- forward rD_data just calculated, to handle e.g. addi rD,rA,Imm; sw rD,mem[y]; ...
405                                 data_rD_v := EX_WRB_i.data_rD;
406                         ELSIF ((MEM_WRB_i.wrb_Action /= NO_WRB) AND (ID2EX_i.curr_rD = MEM_WRB_i.wrix_rD)) THEN
407                                 data_rD_v := MEM_WRB_i.data_rD;
408                         ELSE
409                                 data_rD_v := GPRF2EX_i.data_rD;
410                         END IF;
411                 END IF;
412
413                 IF (ID2EX_i.mem_Action /= NO_MEM) THEN
414                         CASE ID2EX_i.transfer_Size IS
415
416                                 WHEN BYTE     =>
417                                         CASE result_v( 1 DOWNTO 0) IS
418                                                 WHEN "00"   => byte_Enable_v := "1000";
419                                                 WHEN "01"   => byte_Enable_v := "0100";
420                                                 WHEN "10"   => byte_Enable_v := "0010";
421                                                 WHEN "11"   => byte_Enable_v := "0001";
422                                                 WHEN OTHERS => NULL;
423                                         END CASE;
424
425                                 WHEN HALFWORD =>
426                                         CASE result_v( 1 DOWNTO 0) IS
427                                                 WHEN "00"   => byte_Enable_v := "1100";
428                                                 WHEN "10"   => byte_Enable_v := "0011";
429                                                 WHEN OTHERS => NULL;
430                                         END CASE;
431
432                                 WHEN OTHERS     => byte_Enable_v := "1111";
433
434                         END CASE;
435                 END IF;
436
437                 -- update MSR[C] if needed
438                 IF (ID2EX_i.msr_Action = UPDATE_CARRY) THEN
439                         MSR_o.C <= carry_o_v;
440                 END IF;
441
442                 -- pass remaining data to mem
443                 EX2MEM_o.mem_Action  <= ID2EX_i.mem_Action;
444                 EX2MEM_o.data_rD     <= data_rD_v;
445                 EX2MEM_o.byte_Enable <= byte_Enable_v;
446                 EX2MEM_o.wrix_rD     <= ID2EX_i.curr_rD;
447                 --
448                 IMM_LOCK_o.locked    <= ID2EX_i.IMM_Lock;
449                 IMM_LOCK_o.IMM_hi16  <= ID2EX_i.IMM16;
450                 --
451                 EX_WRB_o.wrb_Action  <= ID2EX_i.wrb_Action;
452                 EX_WRB_o.wrix_rD     <= ID2EX_i.curr_rD;
453                 EX_WRB_o.data_rD     <= result_v;
454                 --
455                 HAZARD_WRB_o.hazard  <= hazard_v;
456                 HAZARD_WRB_o.save_rX <= save_rX_v;
457                 HAZARD_WRB_o.data_rX <= data_rX_v;
458                 HAZARD_WRB_o.data_rD <= data_rD_v;
459
460         END PROCESS;
461
462 END ARCHITECTURE rtl;
463