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