divider: Return 0 for invalid and overflow cases, like P9 does
[microwatt.git] / divider_tb.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.glibc_random.all;
9 use work.ppc_fx_insns.all;
10
11 entity divider_tb is
12 end divider_tb;
13
14 architecture behave of divider_tb is
15 signal clk : std_ulogic;
16 signal rst : std_ulogic;
17 constant clk_period : time := 10 ns;
18
19 signal d1 : Decode2ToDividerType;
20 signal d2 : DividerToWritebackType;
21 begin
22 divider_0: entity work.divider
23 port map (clk => clk, rst => rst, d_in => d1, d_out => d2);
24
25 clk_process: process
26 begin
27 clk <= '0';
28 wait for clk_period/2;
29 clk <= '1';
30 wait for clk_period/2;
31 end process;
32
33 stim_process: process
34 variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0);
35 variable si: std_ulogic_vector(15 downto 0);
36 variable d128: std_ulogic_vector(127 downto 0);
37 variable q128: std_ulogic_vector(127 downto 0);
38 variable q64: std_ulogic_vector(63 downto 0);
39 variable rem32: std_ulogic_vector(31 downto 0);
40 begin
41 rst <= '1';
42 wait for clk_period;
43 rst <= '0';
44
45 d1.valid <= '1';
46 d1.write_reg <= "10001";
47 d1.dividend <= x"0000000010001000";
48 d1.divisor <= x"0000000000001111";
49 d1.is_signed <= '0';
50 d1.is_32bit <= '0';
51 d1.is_extended <= '0';
52 d1.is_modulus <= '0';
53 d1.rc <= '0';
54
55 wait for clk_period;
56 assert d2.valid = '0';
57
58 d1.valid <= '0';
59
60 for j in 0 to 66 loop
61 wait for clk_period;
62 if d2.valid = '1' then
63 exit;
64 end if;
65 end loop;
66
67 assert d2.valid = '1';
68 assert d2.write_reg_enable = '1';
69 assert d2.write_reg_nr = "10001";
70 assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);
71 assert d2.write_cr_enable = '0';
72
73 wait for clk_period;
74 assert d2.valid = '0' report "valid";
75
76 d1.valid <= '1';
77 d1.rc <= '1';
78
79 wait for clk_period;
80 assert d2.valid = '0' report "valid";
81
82 d1.valid <= '0';
83
84 for j in 0 to 66 loop
85 wait for clk_period;
86 if d2.valid = '1' then
87 exit;
88 end if;
89 end loop;
90
91 assert d2.valid = '1';
92 assert d2.write_reg_enable = '1';
93 assert d2.write_reg_nr = "10001";
94 assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);
95 assert d2.write_cr_enable = '1';
96 assert d2.write_cr_mask = "10000000";
97 assert d2.write_cr_data = x"40000000" report "cr data is " & to_hstring(d2.write_cr_data);
98
99 wait for clk_period;
100 assert d2.valid = '0';
101
102 -- test divd
103 report "test divd";
104 divd_loop : for dlength in 1 to 8 loop
105 for vlength in 1 to dlength loop
106 for i in 0 to 100 loop
107 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
108 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
109
110 d1.dividend <= ra;
111 d1.divisor <= rb;
112 d1.is_signed <= '1';
113 d1.valid <= '1';
114
115 wait for clk_period;
116
117 d1.valid <= '0';
118 for j in 0 to 66 loop
119 wait for clk_period;
120 if d2.valid = '1' then
121 exit;
122 end if;
123 end loop;
124 assert d2.valid = '1';
125
126 behave_rt := (others => '0');
127 if rb /= x"0000000000000000" and (ra /= x"8000000000000000" or rb /= x"ffffffffffffffff") then
128 behave_rt := ppc_divd(ra, rb);
129 end if;
130 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
131 report "bad divd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
132 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
133 report "bad CR setting for divd";
134 end loop;
135 end loop;
136 end loop;
137
138 -- test divdu
139 report "test divdu";
140 divdu_loop : for dlength in 1 to 8 loop
141 for vlength in 1 to dlength loop
142 for i in 0 to 100 loop
143 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
144 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
145
146 d1.dividend <= ra;
147 d1.divisor <= rb;
148 d1.is_signed <= '0';
149 d1.valid <= '1';
150
151 wait for clk_period;
152
153 d1.valid <= '0';
154 for j in 0 to 66 loop
155 wait for clk_period;
156 if d2.valid = '1' then
157 exit;
158 end if;
159 end loop;
160 assert d2.valid = '1';
161
162 behave_rt := (others => '0');
163 if rb /= x"0000000000000000" then
164 behave_rt := ppc_divdu(ra, rb);
165 end if;
166 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
167 report "bad divdu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
168 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
169 report "bad CR setting for divdu";
170 end loop;
171 end loop;
172 end loop;
173
174 -- test divde
175 report "test divde";
176 divde_loop : for vlength in 1 to 8 loop
177 for dlength in 1 to vlength loop
178 for i in 0 to 100 loop
179 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
180 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
181
182 d1.dividend <= ra;
183 d1.divisor <= rb;
184 d1.is_signed <= '1';
185 d1.is_extended <= '1';
186 d1.valid <= '1';
187
188 wait for clk_period;
189
190 d1.valid <= '0';
191 for j in 0 to 66 loop
192 wait for clk_period;
193 if d2.valid = '1' then
194 exit;
195 end if;
196 end loop;
197 assert d2.valid = '1';
198
199 behave_rt := (others => '0');
200 if rb /= x"0000000000000000" then
201 d128 := ra & x"0000000000000000";
202 q128 := std_ulogic_vector(signed(d128) / signed(rb));
203 if q128(127 downto 63) = x"0000000000000000" & '0' or
204 q128(127 downto 63) = x"ffffffffffffffff" & '1' then
205 behave_rt := q128(63 downto 0);
206 end if;
207 end if;
208 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
209 report "bad divde expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
210 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
211 report "bad CR setting for divde";
212 end loop;
213 end loop;
214 end loop;
215
216 -- test divdeu
217 report "test divdeu";
218 divdeu_loop : for vlength in 1 to 8 loop
219 for dlength in 1 to vlength loop
220 for i in 0 to 100 loop
221 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
222 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
223
224 d1.dividend <= ra;
225 d1.divisor <= rb;
226 d1.is_signed <= '0';
227 d1.is_extended <= '1';
228 d1.valid <= '1';
229
230 wait for clk_period;
231
232 d1.valid <= '0';
233 for j in 0 to 66 loop
234 wait for clk_period;
235 if d2.valid = '1' then
236 exit;
237 end if;
238 end loop;
239 assert d2.valid = '1';
240
241 behave_rt := (others => '0');
242 if unsigned(rb) > unsigned(ra) then
243 d128 := ra & x"0000000000000000";
244 q128 := std_ulogic_vector(unsigned(d128) / unsigned(rb));
245 behave_rt := q128(63 downto 0);
246 end if;
247 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
248 report "bad divdeu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
249 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
250 report "bad CR setting for divdeu";
251 end loop;
252 end loop;
253 end loop;
254
255 -- test divw
256 report "test divw";
257 divw_loop : for dlength in 1 to 4 loop
258 for vlength in 1 to dlength loop
259 for i in 0 to 100 loop
260 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
261 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
262
263 d1.dividend <= ra;
264 d1.divisor <= rb;
265 d1.is_signed <= '1';
266 d1.is_extended <= '0';
267 d1.is_32bit <= '1';
268 d1.valid <= '1';
269
270 wait for clk_period;
271
272 d1.valid <= '0';
273 for j in 0 to 66 loop
274 wait for clk_period;
275 if d2.valid = '1' then
276 exit;
277 end if;
278 end loop;
279 assert d2.valid = '1';
280
281 behave_rt := (others => '0');
282 if rb /= x"0000000000000000" and (ra /= x"ffffffff80000000" or rb /= x"ffffffffffffffff") then
283 behave_rt := ppc_divw(ra, rb);
284 end if;
285 assert behave_rt = d2.write_reg_data
286 report "bad divw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
287 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
288 report "bad CR setting for divw";
289 end loop;
290 end loop;
291 end loop;
292
293 -- test divwu
294 report "test divwu";
295 divwu_loop : for dlength in 1 to 4 loop
296 for vlength in 1 to dlength loop
297 for i in 0 to 100 loop
298 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
299 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
300
301 d1.dividend <= ra;
302 d1.divisor <= rb;
303 d1.is_signed <= '0';
304 d1.is_extended <= '0';
305 d1.is_32bit <= '1';
306 d1.valid <= '1';
307
308 wait for clk_period;
309
310 d1.valid <= '0';
311 for j in 0 to 66 loop
312 wait for clk_period;
313 if d2.valid = '1' then
314 exit;
315 end if;
316 end loop;
317 assert d2.valid = '1';
318
319 behave_rt := (others => '0');
320 if rb /= x"0000000000000000" then
321 behave_rt := ppc_divwu(ra, rb);
322 end if;
323 assert behave_rt = d2.write_reg_data
324 report "bad divwu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
325 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
326 report "bad CR setting for divwu";
327 end loop;
328 end loop;
329 end loop;
330
331 -- test divwe
332 report "test divwe";
333 divwe_loop : for vlength in 1 to 4 loop
334 for dlength in 1 to vlength loop
335 for i in 0 to 100 loop
336 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 32)) & x"00000000";
337 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
338
339 d1.dividend <= ra;
340 d1.divisor <= rb;
341 d1.is_signed <= '1';
342 d1.is_extended <= '0';
343 d1.is_32bit <= '1';
344 d1.valid <= '1';
345
346 wait for clk_period;
347
348 d1.valid <= '0';
349 for j in 0 to 66 loop
350 wait for clk_period;
351 if d2.valid = '1' then
352 exit;
353 end if;
354 end loop;
355 assert d2.valid = '1';
356
357 behave_rt := (others => '0');
358 if rb /= x"0000000000000000" then
359 q64 := std_ulogic_vector(signed(ra) / signed(rb));
360 if q64(63 downto 31) = x"00000000" & '0' or
361 q64(63 downto 31) = x"ffffffff" & '1' then
362 behave_rt := x"00000000" & q64(31 downto 0);
363 end if;
364 assert behave_rt = d2.write_reg_data
365 report "bad divwe expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
366 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
367 report "bad CR setting for divwe";
368 end if;
369 end loop;
370 end loop;
371 end loop;
372
373 -- test divweu
374 report "test divweu";
375 divweu_loop : for vlength in 1 to 4 loop
376 for dlength in 1 to vlength loop
377 for i in 0 to 100 loop
378 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 32)) & x"00000000";
379 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
380
381 d1.dividend <= ra;
382 d1.divisor <= rb;
383 d1.is_signed <= '0';
384 d1.is_extended <= '0';
385 d1.is_32bit <= '1';
386 d1.valid <= '1';
387
388 wait for clk_period;
389
390 d1.valid <= '0';
391 for j in 0 to 66 loop
392 wait for clk_period;
393 if d2.valid = '1' then
394 exit;
395 end if;
396 end loop;
397 assert d2.valid = '1';
398
399 behave_rt := (others => '0');
400 if unsigned(rb(31 downto 0)) > unsigned(ra(63 downto 32)) then
401 behave_rt := std_ulogic_vector(unsigned(ra) / unsigned(rb));
402 end if;
403 assert behave_rt = d2.write_reg_data
404 report "bad divweu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
405 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
406 report "bad CR setting for divweu";
407 end loop;
408 end loop;
409 end loop;
410
411 -- test modsd
412 report "test modsd";
413 modsd_loop : for dlength in 1 to 8 loop
414 for vlength in 1 to dlength loop
415 for i in 0 to 100 loop
416 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
417 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
418
419 d1.dividend <= ra;
420 d1.divisor <= rb;
421 d1.is_signed <= '1';
422 d1.is_extended <= '0';
423 d1.is_32bit <= '0';
424 d1.is_modulus <= '1';
425 d1.valid <= '1';
426
427 wait for clk_period;
428
429 d1.valid <= '0';
430 for j in 0 to 66 loop
431 wait for clk_period;
432 if d2.valid = '1' then
433 exit;
434 end if;
435 end loop;
436 assert d2.valid = '1';
437
438 behave_rt := (others => '0');
439 if rb /= x"0000000000000000" then
440 behave_rt := std_ulogic_vector(signed(ra) rem signed(rb));
441 end if;
442 assert behave_rt = d2.write_reg_data
443 report "bad modsd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
444 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
445 report "bad CR setting for modsd";
446 end loop;
447 end loop;
448 end loop;
449
450 -- test modud
451 report "test modud";
452 modud_loop : for dlength in 1 to 8 loop
453 for vlength in 1 to dlength loop
454 for i in 0 to 100 loop
455 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
456 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
457
458 d1.dividend <= ra;
459 d1.divisor <= rb;
460 d1.is_signed <= '0';
461 d1.is_extended <= '0';
462 d1.is_32bit <= '0';
463 d1.is_modulus <= '1';
464 d1.valid <= '1';
465
466 wait for clk_period;
467
468 d1.valid <= '0';
469 for j in 0 to 66 loop
470 wait for clk_period;
471 if d2.valid = '1' then
472 exit;
473 end if;
474 end loop;
475 assert d2.valid = '1';
476
477 behave_rt := (others => '0');
478 if rb /= x"0000000000000000" then
479 behave_rt := std_ulogic_vector(unsigned(ra) rem unsigned(rb));
480 end if;
481 assert behave_rt = d2.write_reg_data
482 report "bad modud expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
483 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
484 report "bad CR setting for modud";
485 end loop;
486 end loop;
487 end loop;
488
489 -- test modsw
490 report "test modsw";
491 modsw_loop : for dlength in 1 to 4 loop
492 for vlength in 1 to dlength loop
493 for i in 0 to 100 loop
494 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
495 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
496
497 d1.dividend <= ra;
498 d1.divisor <= rb;
499 d1.is_signed <= '1';
500 d1.is_extended <= '0';
501 d1.is_32bit <= '1';
502 d1.is_modulus <= '1';
503 d1.valid <= '1';
504
505 wait for clk_period;
506
507 d1.valid <= '0';
508 for j in 0 to 66 loop
509 wait for clk_period;
510 if d2.valid = '1' then
511 exit;
512 end if;
513 end loop;
514 assert d2.valid = '1';
515
516 behave_rt := (others => '0');
517 if rb /= x"0000000000000000" then
518 rem32 := std_ulogic_vector(signed(ra(31 downto 0)) rem signed(rb(31 downto 0)));
519 if rem32(31) = '0' then
520 behave_rt := x"00000000" & rem32;
521 else
522 behave_rt := x"ffffffff" & rem32;
523 end if;
524 end if;
525 assert behave_rt = d2.write_reg_data
526 report "bad modsw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
527 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
528 report "bad CR setting for modsw";
529 end loop;
530 end loop;
531 end loop;
532
533 -- test moduw
534 report "test moduw";
535 moduw_loop : for dlength in 1 to 4 loop
536 for vlength in 1 to dlength loop
537 for i in 0 to 100 loop
538 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
539 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
540
541 d1.dividend <= ra;
542 d1.divisor <= rb;
543 d1.is_signed <= '0';
544 d1.is_extended <= '0';
545 d1.is_32bit <= '1';
546 d1.is_modulus <= '1';
547 d1.valid <= '1';
548
549 wait for clk_period;
550
551 d1.valid <= '0';
552 for j in 0 to 66 loop
553 wait for clk_period;
554 if d2.valid = '1' then
555 exit;
556 end if;
557 end loop;
558 assert d2.valid = '1';
559
560 behave_rt := (others => '0');
561 if rb /= x"0000000000000000" then
562 behave_rt := x"00000000" & std_ulogic_vector(unsigned(ra(31 downto 0)) rem unsigned(rb(31 downto 0)));
563 end if;
564 assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
565 report "bad moduw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
566 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
567 report "bad CR setting for moduw";
568 end loop;
569 end loop;
570 end loop;
571
572 assert false report "end of test" severity failure;
573 wait;
574 end process;
575 end behave;