3fd6ebab5472b2928409bf8b5b63618723e4c3fc
[microwatt.git] / execute1.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.decode_types.all;
7 use work.common.all;
8 use work.helpers.all;
9 use work.crhelpers.all;
10 use work.insn_helpers.all;
11 use work.ppc_fx_insns.all;
12
13 entity execute1 is
14 generic (
15 SIM : boolean := false
16 );
17 port (
18 clk : in std_logic;
19
20 -- asynchronous
21 flush_out : out std_ulogic;
22
23 e_in : in Decode2ToExecute1Type;
24
25 -- asynchronous
26 f_out : out Execute1ToFetch1Type;
27
28 e_out : out Execute1ToWritebackType;
29
30 terminate_out : out std_ulogic
31 );
32 end entity execute1;
33
34 architecture behaviour of execute1 is
35 type reg_type is record
36 --f : Execute1ToFetch1Type;
37 e : Execute1ToWritebackType;
38 end record;
39
40 signal r, rin : reg_type;
41
42 signal ctrl: ctrl_t := (carry => '0', others => (others => '0'));
43 signal ctrl_tmp: ctrl_t := (carry => '0', others => (others => '0'));
44
45 signal right_shift, rot_clear_left, rot_clear_right: std_ulogic;
46 signal rotator_result: std_ulogic_vector(63 downto 0);
47 signal rotator_carry: std_ulogic;
48 signal logical_result: std_ulogic_vector(63 downto 0);
49 signal countzero_result: std_ulogic_vector(63 downto 0);
50
51 function decode_input_carry (carry_sel : carry_in_t; ca_in : std_ulogic) return std_ulogic is
52 begin
53 case carry_sel is
54 when ZERO =>
55 return '0';
56 when CA =>
57 return ca_in;
58 when ONE =>
59 return '1';
60 end case;
61 end;
62 begin
63
64 rotator_0: entity work.rotator
65 port map (
66 rs => e_in.read_data3,
67 ra => e_in.read_data1,
68 shift => e_in.read_data2(6 downto 0),
69 insn => e_in.insn,
70 is_32bit => e_in.is_32bit,
71 right_shift => right_shift,
72 arith => e_in.is_signed,
73 clear_left => rot_clear_left,
74 clear_right => rot_clear_right,
75 result => rotator_result,
76 carry_out => rotator_carry
77 );
78
79 logical_0: entity work.logical
80 port map (
81 rs => e_in.read_data3,
82 rb => e_in.read_data2,
83 op => e_in.insn_type,
84 invert_in => e_in.invert_a,
85 invert_out => e_in.invert_out,
86 result => logical_result
87 );
88
89 countzero_0: entity work.zero_counter
90 port map (
91 rs => e_in.read_data3,
92 count_right => e_in.insn(10),
93 is_32bit => e_in.is_32bit,
94 result => countzero_result
95 );
96
97 execute1_0: process(clk)
98 begin
99 if rising_edge(clk) then
100 r <= rin;
101 ctrl <= ctrl_tmp;
102 end if;
103 end process;
104
105 execute1_1: process(all)
106 variable v : reg_type;
107 variable a_inv : std_ulogic_vector(63 downto 0);
108 variable result : std_ulogic_vector(63 downto 0);
109 variable newcrf : std_ulogic_vector(3 downto 0);
110 variable result_with_carry : std_ulogic_vector(64 downto 0);
111 variable result_en : std_ulogic;
112 variable crnum : crnum_t;
113 variable scrnum : crnum_t;
114 variable lo, hi : integer;
115 variable sh, mb, me : std_ulogic_vector(5 downto 0);
116 variable sh32, mb32, me32 : std_ulogic_vector(4 downto 0);
117 variable bo, bi : std_ulogic_vector(4 downto 0);
118 variable bf, bfa : std_ulogic_vector(2 downto 0);
119 variable l : std_ulogic;
120 begin
121 result := (others => '0');
122 result_with_carry := (others => '0');
123 result_en := '0';
124 newcrf := (others => '0');
125
126 v := r;
127 v.e := Execute1ToWritebackInit;
128 --v.f := Execute1ToFetch1TypeInit;
129
130 ctrl_tmp <= ctrl;
131 -- FIXME: run at 512MHz not core freq
132 ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1);
133
134 terminate_out <= '0';
135 f_out <= Execute1ToFetch1TypeInit;
136
137 -- rotator control signals
138 right_shift <= '1' when e_in.insn_type = OP_SHR else '0';
139 rot_clear_left <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCL else '0';
140 rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0';
141
142 if e_in.valid = '1' then
143
144 v.e.valid := '1';
145 v.e.write_reg := e_in.write_reg;
146 v.e.write_len := x"8";
147 v.e.sign_extend := '0';
148
149 case_0: case e_in.insn_type is
150
151 when OP_ILLEGAL =>
152 terminate_out <= '1';
153 report "illegal";
154 when OP_NOP =>
155 -- Do nothing
156 when OP_ADD =>
157 if e_in.invert_a = '0' then
158 a_inv := e_in.read_data1;
159 else
160 a_inv := not e_in.read_data1;
161 end if;
162 result_with_carry := ppc_adde(a_inv, e_in.read_data2, decode_input_carry(e_in.input_carry, ctrl.carry));
163 result := result_with_carry(63 downto 0);
164 if e_in.output_carry then
165 ctrl_tmp.carry <= result_with_carry(64);
166 end if;
167 result_en := '1';
168 when OP_AND | OP_OR | OP_XOR =>
169 result := logical_result;
170 result_en := '1';
171 when OP_B =>
172 f_out.redirect <= '1';
173 if (insn_aa(e_in.insn)) then
174 f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
175 else
176 f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
177 end if;
178 when OP_BC =>
179 bo := insn_bo(e_in.insn);
180 bi := insn_bi(e_in.insn);
181 if bo(4-2) = '0' then
182 ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
183 end if;
184 if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then
185 f_out.redirect <= '1';
186 if (insn_aa(e_in.insn)) then
187 f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
188 else
189 f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
190 end if;
191 end if;
192 when OP_BCREG =>
193 -- bits 10 and 6 distinguish between bclr, bcctr and bctar
194 bo := insn_bo(e_in.insn);
195 bi := insn_bi(e_in.insn);
196 if bo(4-2) = '0' and e_in.insn(10) = '0' then
197 ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
198 end if;
199 if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then
200 f_out.redirect <= '1';
201 if e_in.insn(10) = '0' then
202 f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00";
203 else
204 f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00";
205 end if;
206 end if;
207 when OP_CMPB =>
208 result := ppc_cmpb(e_in.read_data3, e_in.read_data2);
209 result_en := '1';
210 when OP_CMP =>
211 bf := insn_bf(e_in.insn);
212 l := insn_l(e_in.insn);
213 v.e.write_cr_enable := '1';
214 crnum := to_integer(unsigned(bf));
215 v.e.write_cr_mask := num_to_fxm(crnum);
216 for i in 0 to 7 loop
217 lo := i*4;
218 hi := lo + 3;
219 v.e.write_cr_data(hi downto lo) := ppc_cmp(l, e_in.read_data1, e_in.read_data2);
220 end loop;
221 when OP_CMPL =>
222 bf := insn_bf(e_in.insn);
223 l := insn_l(e_in.insn);
224 v.e.write_cr_enable := '1';
225 crnum := to_integer(unsigned(bf));
226 v.e.write_cr_mask := num_to_fxm(crnum);
227 for i in 0 to 7 loop
228 lo := i*4;
229 hi := lo + 3;
230 v.e.write_cr_data(hi downto lo) := ppc_cmpl(l, e_in.read_data1, e_in.read_data2);
231 end loop;
232 when OP_CNTZ =>
233 result := countzero_result;
234 result_en := '1';
235 when OP_EXTS =>
236 v.e.write_len := e_in.data_len;
237 v.e.sign_extend := '1';
238 result := e_in.read_data3;
239 result_en := '1';
240 when OP_ISEL =>
241 crnum := to_integer(unsigned(insn_bc(e_in.insn)));
242 if e_in.cr(31-crnum) = '1' then
243 result := e_in.read_data1;
244 else
245 result := e_in.read_data2;
246 end if;
247 result_en := '1';
248 when OP_MCRF =>
249 bf := insn_bf(e_in.insn);
250 bfa := insn_bfa(e_in.insn);
251 v.e.write_cr_enable := '1';
252 crnum := to_integer(unsigned(bf));
253 scrnum := to_integer(unsigned(bfa));
254 v.e.write_cr_mask := num_to_fxm(crnum);
255 for i in 0 to 7 loop
256 lo := (7-i)*4;
257 hi := lo + 3;
258 if i = scrnum then
259 newcrf := e_in.cr(hi downto lo);
260 end if;
261 end loop;
262 for i in 0 to 7 loop
263 lo := i*4;
264 hi := lo + 3;
265 v.e.write_cr_data(hi downto lo) := newcrf;
266 end loop;
267 when OP_MFSPR =>
268 if std_match(e_in.insn(20 downto 11), "0100100000") then
269 result := ctrl.ctr;
270 result_en := '1';
271 elsif std_match(e_in.insn(20 downto 11), "0100000000") then
272 result := ctrl.lr;
273 result_en := '1';
274 elsif std_match(e_in.insn(20 downto 11), "0110001000") then
275 result := ctrl.tb;
276 result_en := '1';
277 end if;
278 when OP_MFCR =>
279 if e_in.insn(20) = '0' then
280 -- mfcr
281 result := x"00000000" & e_in.cr;
282 else
283 -- mfocrf
284 crnum := fxm_to_num(insn_fxm(e_in.insn));
285 result := (others => '0');
286 for i in 0 to 7 loop
287 lo := (7-i)*4;
288 hi := lo + 3;
289 if crnum = i then
290 result(hi downto lo) := e_in.cr(hi downto lo);
291 end if;
292 end loop;
293 end if;
294 result_en := '1';
295 when OP_MTCRF =>
296 v.e.write_cr_enable := '1';
297 if e_in.insn(20) = '0' then
298 -- mtcrf
299 v.e.write_cr_mask := insn_fxm(e_in.insn);
300 else
301 -- mtocrf: We require one hot priority encoding here
302 crnum := fxm_to_num(insn_fxm(e_in.insn));
303 v.e.write_cr_mask := num_to_fxm(crnum);
304 end if;
305 v.e.write_cr_data := e_in.read_data3(31 downto 0);
306 when OP_MTSPR =>
307 if std_match(e_in.insn(20 downto 11), "0100100000") then
308 ctrl_tmp.ctr <= e_in.read_data3;
309 elsif std_match(e_in.insn(20 downto 11), "0100000000") then
310 ctrl_tmp.lr <= e_in.read_data3;
311 end if;
312 when OP_POPCNTB =>
313 result := ppc_popcntb(e_in.read_data3);
314 result_en := '1';
315 when OP_POPCNTW =>
316 result := ppc_popcntw(e_in.read_data3);
317 result_en := '1';
318 when OP_POPCNTD =>
319 result := ppc_popcntd(e_in.read_data3);
320 result_en := '1';
321 when OP_PRTYD =>
322 result := ppc_prtyd(e_in.read_data3);
323 result_en := '1';
324 when OP_PRTYW =>
325 result := ppc_prtyw(e_in.read_data3);
326 result_en := '1';
327 when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR =>
328 result := rotator_result;
329 if e_in.output_carry = '1' then
330 ctrl_tmp.carry <= rotator_carry;
331 end if;
332 result_en := '1';
333 when OP_SIM_CONFIG =>
334 -- bit 0 was used to select the microwatt console, which
335 -- we no longer support.
336 if SIM = true then
337 result := x"0000000000000000";
338 else
339 result := x"0000000000000000";
340 end if;
341 result_en := '1';
342
343 when OP_TDI =>
344 -- Keep our test cases happy for now, ignore trap instructions
345 report "OP_TDI FIXME";
346
347 when others =>
348 terminate_out <= '1';
349 report "illegal";
350 end case;
351
352 if e_in.lr = '1' then
353 ctrl_tmp.lr <= std_ulogic_vector(unsigned(e_in.nia) + 4);
354 end if;
355
356 end if;
357
358 v.e.write_data := result;
359 v.e.write_enable := result_en;
360 v.e.rc := e_in.rc;
361
362 -- Update registers
363 rin <= v;
364
365 -- update outputs
366 --f_out <= r.f;
367 e_out <= r.e;
368 flush_out <= f_out.redirect;
369 end process;
370 end architecture behaviour;