Merge pull request #104 from paulusmack/master
[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 Execute1ToExecute2Type;
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 : Execute1ToExecute2Type;
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 : integer;
112 variable crnum : integer;
113 variable scrnum : integer;
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 := Execute1ToExecute2Init;
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
147 case_0: case e_in.insn_type is
148
149 when OP_ILLEGAL =>
150 terminate_out <= '1';
151 report "illegal";
152 when OP_NOP =>
153 -- Do nothing
154 when OP_ADD =>
155 if e_in.invert_a = '0' then
156 a_inv := e_in.read_data1;
157 else
158 a_inv := not e_in.read_data1;
159 end if;
160 result_with_carry := ppc_adde(a_inv, e_in.read_data2, decode_input_carry(e_in.input_carry, ctrl.carry));
161 result := result_with_carry(63 downto 0);
162 if e_in.output_carry then
163 ctrl_tmp.carry <= result_with_carry(64);
164 end if;
165 result_en := 1;
166 when OP_AND | OP_OR | OP_XOR =>
167 result := logical_result;
168 result_en := 1;
169 when OP_B =>
170 f_out.redirect <= '1';
171 if (insn_aa(e_in.insn)) then
172 f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
173 else
174 f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
175 end if;
176 when OP_BC =>
177 bo := insn_bo(e_in.insn);
178 bi := insn_bi(e_in.insn);
179 if bo(4-2) = '0' then
180 ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
181 end if;
182 if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then
183 f_out.redirect <= '1';
184 if (insn_aa(e_in.insn)) then
185 f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
186 else
187 f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
188 end if;
189 end if;
190 when OP_BCREG =>
191 -- bits 10 and 6 distinguish between bclr, bcctr and bctar
192 bo := insn_bo(e_in.insn);
193 bi := insn_bi(e_in.insn);
194 if bo(4-2) = '0' and e_in.insn(10) = '0' then
195 ctrl_tmp.ctr <= std_ulogic_vector(unsigned(ctrl.ctr) - 1);
196 end if;
197 if ppc_bc_taken(bo, bi, e_in.cr, ctrl.ctr) = 1 then
198 f_out.redirect <= '1';
199 if e_in.insn(10) = '0' then
200 f_out.redirect_nia <= ctrl.lr(63 downto 2) & "00";
201 else
202 f_out.redirect_nia <= ctrl.ctr(63 downto 2) & "00";
203 end if;
204 end if;
205 when OP_CMPB =>
206 result := ppc_cmpb(e_in.read_data3, e_in.read_data2);
207 result_en := 1;
208 when OP_CMP =>
209 bf := insn_bf(e_in.insn);
210 l := insn_l(e_in.insn);
211 v.e.write_cr_enable := '1';
212 crnum := to_integer(unsigned(bf));
213 v.e.write_cr_mask := num_to_fxm(crnum);
214 for i in 0 to 7 loop
215 lo := i*4;
216 hi := lo + 3;
217 v.e.write_cr_data(hi downto lo) := ppc_cmp(l, e_in.read_data1, e_in.read_data2);
218 end loop;
219 when OP_CMPL =>
220 bf := insn_bf(e_in.insn);
221 l := insn_l(e_in.insn);
222 v.e.write_cr_enable := '1';
223 crnum := to_integer(unsigned(bf));
224 v.e.write_cr_mask := num_to_fxm(crnum);
225 for i in 0 to 7 loop
226 lo := i*4;
227 hi := lo + 3;
228 v.e.write_cr_data(hi downto lo) := ppc_cmpl(l, e_in.read_data1, e_in.read_data2);
229 end loop;
230 when OP_CNTZ =>
231 result := countzero_result;
232 result_en := 1;
233 when OP_EXTSB =>
234 result := ppc_extsb(e_in.read_data3);
235 result_en := 1;
236 when OP_EXTSH =>
237 result := ppc_extsh(e_in.read_data3);
238 result_en := 1;
239 when OP_EXTSW =>
240 result := ppc_extsw(e_in.read_data3);
241 result_en := 1;
242 when OP_ISEL =>
243 crnum := to_integer(unsigned(insn_bc(e_in.insn)));
244 if e_in.cr(31-crnum) = '1' then
245 result := e_in.read_data1;
246 else
247 result := e_in.read_data2;
248 end if;
249 result_en := 1;
250 when OP_MCRF =>
251 bf := insn_bf(e_in.insn);
252 bfa := insn_bfa(e_in.insn);
253 v.e.write_cr_enable := '1';
254 crnum := to_integer(unsigned(bf));
255 scrnum := to_integer(unsigned(bfa));
256 v.e.write_cr_mask := num_to_fxm(crnum);
257 for i in 0 to 7 loop
258 lo := (7-i)*4;
259 hi := lo + 3;
260 if i = scrnum then
261 newcrf := e_in.cr(hi downto lo);
262 end if;
263 end loop;
264 for i in 0 to 7 loop
265 lo := i*4;
266 hi := lo + 3;
267 v.e.write_cr_data(hi downto lo) := newcrf;
268 end loop;
269 when OP_MFSPR =>
270 if std_match(e_in.insn(20 downto 11), "0100100000") then
271 result := ctrl.ctr;
272 result_en := 1;
273 elsif std_match(e_in.insn(20 downto 11), "0100000000") then
274 result := ctrl.lr;
275 result_en := 1;
276 elsif std_match(e_in.insn(20 downto 11), "0110001000") then
277 result := ctrl.tb;
278 result_en := 1;
279 end if;
280 when OP_MFCR =>
281 if e_in.insn(20) = '0' then
282 -- mfcr
283 result := x"00000000" & e_in.cr;
284 else
285 -- mfocrf
286 crnum := fxm_to_num(insn_fxm(e_in.insn));
287 result := (others => '0');
288 for i in 0 to 7 loop
289 lo := (7-i)*4;
290 hi := lo + 3;
291 if crnum = i then
292 result(hi downto lo) := e_in.cr(hi downto lo);
293 end if;
294 end loop;
295 end if;
296 result_en := 1;
297 when OP_MTCRF =>
298 v.e.write_cr_enable := '1';
299 if e_in.insn(20) = '0' then
300 -- mtcrf
301 v.e.write_cr_mask := insn_fxm(e_in.insn);
302 else
303 -- mtocrf: We require one hot priority encoding here
304 crnum := fxm_to_num(insn_fxm(e_in.insn));
305 v.e.write_cr_mask := num_to_fxm(crnum);
306 end if;
307 v.e.write_cr_data := e_in.read_data3(31 downto 0);
308 when OP_MTSPR =>
309 if std_match(e_in.insn(20 downto 11), "0100100000") then
310 ctrl_tmp.ctr <= e_in.read_data3;
311 elsif std_match(e_in.insn(20 downto 11), "0100000000") then
312 ctrl_tmp.lr <= e_in.read_data3;
313 end if;
314 when OP_POPCNTB =>
315 result := ppc_popcntb(e_in.read_data3);
316 result_en := 1;
317 when OP_POPCNTW =>
318 result := ppc_popcntw(e_in.read_data3);
319 result_en := 1;
320 when OP_POPCNTD =>
321 result := ppc_popcntd(e_in.read_data3);
322 result_en := 1;
323 when OP_PRTYD =>
324 result := ppc_prtyd(e_in.read_data3);
325 result_en := 1;
326 when OP_PRTYW =>
327 result := ppc_prtyw(e_in.read_data3);
328 result_en := 1;
329 when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR =>
330 result := rotator_result;
331 if e_in.output_carry = '1' then
332 ctrl_tmp.carry <= rotator_carry;
333 end if;
334 result_en := 1;
335 when OP_SIM_CONFIG =>
336 -- bit 0 was used to select the microwatt console, which
337 -- we no longer support.
338 if SIM = true then
339 result := x"0000000000000000";
340 else
341 result := x"0000000000000000";
342 end if;
343 result_en := 1;
344
345 when OP_TDI =>
346 -- Keep our test cases happy for now, ignore trap instructions
347 report "OP_TDI FIXME";
348
349 when others =>
350 terminate_out <= '1';
351 report "illegal";
352 end case;
353
354 if e_in.lr = '1' then
355 ctrl_tmp.lr <= std_ulogic_vector(unsigned(e_in.nia) + 4);
356 end if;
357
358 if result_en = 1 then
359 v.e.write_data := result;
360 v.e.write_enable := '1';
361 v.e.rc := e_in.rc;
362 end if;
363 end if;
364
365 -- Update registers
366 rin <= v;
367
368 -- update outputs
369 --f_out <= r.f;
370 e_out <= r.e;
371 flush_out <= f_out.redirect;
372 end process;
373 end architecture behaviour;