parser/alu: extrem mega super sonderfall bugfix
[hwmod.git] / src / beh_alu_tb.vhd
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4 use work.gen_pkg.all;
5
6 entity beh_alu_tb is
7 end entity beh_alu_tb;
8
9 architecture sim of beh_alu_tb is
10         signal sys_clk, sys_res_n, do_calc, calc_done, calc_error : std_logic;
11         signal opcode : alu_ops;
12         signal op1, op2, op3, opM : csigned;
13         signal stop : boolean := false;
14 begin
15         inst : entity work.alu(beh)
16         port map
17         (
18                 sys_clk => sys_clk,
19                 sys_res_n => sys_res_n,
20                 do_calc => do_calc,
21                 calc_done => calc_done,
22                 op1 => op1,
23                 op2 => op2,
24                 op3 => op3,
25                 opM => opM,
26                 opcode => opcode,
27                 calc_error => calc_error
28         );
29
30         process
31         begin
32                 sys_clk <= '0';
33                 wait for 15 ns;
34                 sys_clk <= '1';
35                 wait for 15 ns;
36                 if stop = true then
37                         wait;
38                 end if;
39         end process;
40
41         process
42                 type alu_testv is record
43                         o1 : cinteger;
44                         o : alu_ops;
45                         o2 : cinteger;
46                         om : cinteger;
47                         expected : cinteger;
48                         errcase : boolean;
49                 end record alu_testv;
50
51                 -- ggf. groesse des arrays erhoehen
52                 type alu_testv_array is array (natural range 0 to 65) of alu_testv;
53
54                 variable testmatrix : alu_testv_array :=
55                         ( 0 => (-5, ALU_DIV, 3, 2, -1, false),
56                           1 => (7, ALU_ADD, 3, 0, 10, false),
57                           2 => (7, ALU_SUB, 1, 0, 6, false),
58                           3 => (7, ALU_DIV, 1, 0, 7, false),
59                           4 => (7, ALU_DIV, 3, 1, 2, false),
60                           5 => (7, ALU_ADD, 1, 0, 8, false),
61                           6 => (7, ALU_MUL, 3, 0, 21, false),
62                           7 => (-7, ALU_MUL, 3, 0, -21, false),
63                           8 => (268435456, ALU_MUL, -2, 0, -536870912, false),
64                           9 => (268435456, ALU_MUL, 2**5, 0, 0, false), -- um fuenf nach links shiften
65                           10 => (268435456 + 5, ALU_MUL, 2**5, 0, 160, false), -- = 5 * (2^5)
66                           11 => (100, ALU_DIV, 10, 0, 10, false),
67                           12 => (100, ALU_DIV, 51, 49, 1, false),
68                           13 => (100, ALU_DIV, 49, 2, 2, false),
69                           14 => (153156, ALU_DIV, 3543, 807, 43, false),
70                           15 => (-153156, ALU_DIV, 3543, 807, -43, false),
71                           16 => (153156, ALU_DIV, -3543, 807, -43, false),
72                           17 => (-153156, ALU_DIV, -3543, 807, 43, false),
73                           -- add: sign and under-/overflow check
74                           18 => (2147483647, ALU_ADD, -1, 0, 2147483646, false),
75                           19 => (2147483647, ALU_ADD, 1, 0, 0, true),
76                           20 => (-2147483645, ALU_ADD, -100, 0, 0, true),
77                           21 => (7, ALU_ADD, 1, 0, 8, false),
78                           22 => (7, ALU_ADD, -1, 0, 6, false),
79                           23 => (-7, ALU_ADD, 1, 0, -6, false),
80                           24 => (-7, ALU_ADD, -1, 0, -8, false),
81                           -- sub: sign and under-/overflow check
82                           25 => (-7, ALU_SUB, 1, 0, -8, false),
83                           26 => (-7, ALU_SUB, -1, 0, -6, false),
84                           27 => (7, ALU_SUB, 1, 0, 6, false),
85                           28 => (7, ALU_SUB, -1, 0, 8, false),
86                           29 => (-2147483645, ALU_SUB, 1000, 0, 0, true),
87                           30 => (2147483645, ALU_SUB, -1000, 0, 0, true),
88                           31 => (-1000, ALU_SUB, 2147483645, 0, 0, true),
89                           32 => (1000, ALU_SUB, -2147483645, 0, 0, true),
90                           -- mul: sign and under-/overflow check
91                           33 => (3, ALU_MUL, 2, 0, 6, false),
92                           34 => (3, ALU_MUL, -2, 0, -6, false),
93                           35 => (-3, ALU_MUL, 2, 0, -6, false),
94                           36 => (-3, ALU_MUL, -2, 0, 6, false),
95                           37 => (90000, ALU_MUL, 100000, 0, 0, true),
96                           38 => (90000, ALU_MUL, -100000, 0, 0, true),
97                           39 => (-90000, ALU_MUL, 100000, 0, 0, true),
98                           40 => (-90000, ALU_MUL, -100000, 0, 0, true),
99                           -- div: overflow check und division durch null
100                           41 => (-2147483648, ALU_DIV, -1, 0, 0, true),
101                           42 => (-2147483648, ALU_DIV, 0, 0, 0, true),
102                           43 => (-4, ALU_DIV, 2, 0, -2, false),
103                           -- div/mod:
104                           44 => (1234, ALU_DIV, 3, 1, 411, false),
105                           45 => (1, ALU_DIV, 10, 1, 0, false),
106                           46 => (2, ALU_DIV, 10, 2, 0, false),
107                           47 => (3, ALU_DIV, 10, 3, 0, false),
108                           48 => (4, ALU_DIV, 10, 4, 0, false),
109                           49 => (5, ALU_DIV, 10, 5, 0, false),
110                           50 => (6, ALU_DIV, 10, 6, 0, false),
111                           51 => (7, ALU_DIV, 10, 7, 0, false),
112                           52 => (8, ALU_DIV, 10, 8, 0, false),
113                           53 => (9, ALU_DIV, 10, 9, 0, false),
114                           54 => (0, ALU_DIV, 10, 0, 0, false),
115                           55 => (10, ALU_DIV, 10, 0, 1, false),
116                           56 => (5134123, ALU_DIV, 358015, 121913, 14, false),
117                           -- extra
118                           60 => (5, ALU_SUB, -2147483648, 0, 0, true),
119                           61 => (-2147483647, ALU_SUB, 1, 0, -2147483648, false),
120                           62 => (-2147483647, ALU_ADD, -1, 0, -2147483648, false),
121                           63 => (-2147483648, ALU_DIV, 10, 8, -214748364, false),
122                           others => (0, ALU_ADD, 0, 0, 0, false)
123                         );
124                 variable checkall : boolean := true;
125         begin
126                 -- init & reset
127                 sys_res_n <= '0';
128                 do_calc <= '0';
129                 opcode <= ALU_NOP;
130                 op1 <= (others => '0');
131                 op2 <= (others => '0');
132
133                 icwait(sys_clk, 30);
134                 sys_res_n <= '1';
135
136                 for i in testmatrix'range loop
137                         icwait(sys_clk, 10);
138                         op1 <= to_signed(testmatrix(i).o1,CBITS);
139                         opcode <= testmatrix(i).o;
140                         op2 <= to_signed(testmatrix(i).o2,CBITS);
141
142                         -- berechnung kann los gehen
143                         do_calc <= '1';
144
145                         -- warten auf die alu einheit
146                         wait on calc_done;
147                         icwait(sys_clk, 1);
148
149                         if testmatrix(i).errcase then
150                                 if (calc_error = '0') then
151                                         assert(false) report "sollte ein error sein";
152                                         assert op3 = to_signed(testmatrix(i).expected,CBITS)
153                                                 report "" & cinteger'image(testmatrix(i).o1) & 
154                                                 " " & integer'image(to_integer(signed(opcode))) &
155                                                 " " & cinteger'image(testmatrix(i).o2) &
156                                                 " /= " & integer'image(to_integer(op3)) &
157                                                 " ( " & integer'image(to_integer(opM)) & " ) " &
158                                                 " -- erwartet: " & cinteger'image(testmatrix(i).expected) &
159                                                 " ( " & cinteger'image(testmatrix(i).om) & " ) ";
160                                         checkall := false;
161                                 else
162                                         assert(false) report "testfall war ein error (passt)";
163                                 end if;
164                         else
165                                 assert ((op3 = to_signed(testmatrix(i).expected,CBITS)) and (opM = to_signed(testmatrix(i).om,CBITS)))
166                                         report "" & cinteger'image(testmatrix(i).o1) & 
167                                         " " & integer'image(to_integer(signed(opcode))) &
168                                         " " & cinteger'image(testmatrix(i).o2) &
169                                         " /= " & integer'image(to_integer(op3)) &
170                                         " ( " & integer'image(to_integer(opM)) & " ) " &
171                                         " -- erwartet: " & cinteger'image(testmatrix(i).expected) &
172                                         " ( " & cinteger'image(testmatrix(i).om) & " ) ";
173
174                                 if not((op3 = to_signed(testmatrix(i).expected,CBITS)) and (opM = to_signed(testmatrix(i).om,CBITS))) then
175                                         checkall := false;
176                                 end if;
177                         end if;
178
179                         icwait(sys_clk, 2);
180                         -- ack it!
181                         do_calc <= '0';
182                 end loop;
183
184                 if checkall then
185                         report "alle testfaelle der ALU waren erfolgreich!";
186                 else
187                         report "einige testfaelle schlugen fehl";
188                 end if;
189                 stop <= true;
190                 wait;
191         end process;
192 end architecture sim;