parser/alu: extrem mega super sonderfall bugfix
[hwmod.git] / src / parser.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 parser is
7         port
8         (
9                 sys_clk : in std_logic;
10                 sys_res_n : in std_logic;
11                 -- History
12                 p_rget : out std_logic;
13                 p_rdone : in std_logic;
14                 p_read : in hbyte;
15                 p_wtake : out std_logic;
16                 p_wdone : in std_logic;
17                 p_write : out hbyte;
18                 p_finished : out std_logic;
19                 -- Scanner
20                 do_it : in std_logic;
21                 finished : out std_logic
22         );
23 end entity parser;
24
25 architecture beh of parser is
26         type PARSER_STATE is (SIDLE, SREAD_NEWNUMBER, SREAD_SPACE1_2,
27         SREAD_SPACE1_3, SREAD_SPACE2, SREAD_SPACE3, SREAD_OP1, SREAD_OP2,
28         SREAD_SIGN1, SREAD_NEXTBYTE, SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1,
29         SCALC_14, SCALC_15, SCALC_2, SWRITE_CHAR0, SWRITE_CHAR1, SWRITE_CHAR2,
30         SWRITE_SIGN1, SWRITE_SIGN2, SDONE, SERROR1, SERROR2);
31         signal state_int, state_next : PARSER_STATE;
32         signal z_int, z_next, strich_int, strich_next, wtmp_int, wtmp_next : csigned;
33         signal punkt_int, punkt_next : csigned;
34         signal rbyte_int, rbyte_next : hbyte;
35         signal p_write_int, p_write_next : hbyte;
36         signal p_rget_int, p_rget_next : std_logic;
37         signal p_wtake_int, p_wtake_next : std_logic;
38         signal p_finished_int, p_finished_next : std_logic;
39         signal finished_int, finished_next : std_logic;
40         signal aktop_int, aktop_next : alu_ops;
41         signal opp_int, opp_next : alu_ops;
42         signal opcode_int, opcode_next : alu_ops;
43         signal op1_int, op1_next : csigned;
44         signal op2_int, op2_next : csigned;
45         signal do_calc_int, do_calc_next : std_logic;
46         signal goto_calcn1, goto_op1, goto_space3, goto_sign : std_logic;
47         signal z_sign_next, z_sign_int : std_logic;
48         signal firstz_next, firstz_int : boolean;
49         signal err_next, err_int : hstr_int;
50         signal errc_next, errc_int : hstr_int;
51         signal errc_tmp_next, errc_tmp_int : hstr_int;
52         -- ALU
53         signal opcode : alu_ops;
54         signal op1 : csigned;
55         signal op2 : csigned;
56         signal op3 : csigned;
57         signal opM : csigned;
58         signal do_calc : std_logic;
59         signal calc_done : std_logic;
60         signal calc_error : std_logic;
61 begin
62         instalu : entity work.alu(beh)
63         port map
64         (
65                 sys_clk => sys_clk,
66                 sys_res_n => sys_res_n,
67                 do_calc => do_calc,
68                 calc_done => calc_done,
69                 calc_error => calc_error,
70                 op1 => op1,
71                 op2 => op2,
72                 op3 => op3,
73                 opM => opM,
74                 opcode => opcode
75         );
76
77         p_write <= p_write_int;
78         p_rget <= p_rget_int;
79         p_wtake <= p_wtake_int;
80         p_finished <= p_finished_int;
81         finished <= finished_int;
82
83         opcode <= opcode_int;
84         op1 <= op1_int;
85         op2 <= op2_int;
86         do_calc <= do_calc_int;
87
88         process(sys_clk, sys_res_n)
89         begin
90                 if sys_res_n = '0' then
91                         state_int <= SIDLE;
92                         z_int <= (others => '0');
93                         z_sign_int <= '0';
94                         strich_int <= (others => '0');
95                         punkt_int <= (others => '0');
96                         wtmp_int <= (others => '0');
97                         rbyte_int <= (others => '0');
98                         aktop_int <= ALU_NOP;
99                         opp_int <= ALU_NOP;
100                         err_int <= 0;
101                         errc_int <= 71;
102                         errc_tmp_int <= 0;
103                         firstz_int <= true;
104                         -- out ports
105                         p_rget_int <= '0';
106                         p_write_int <= (others => '0');
107                         p_wtake_int <= '0';
108                         p_finished_int <= '0';
109                         finished_int <= '0';
110                         opcode_int <= ALU_NOP;
111                         op1_int <= (others => '0');
112                         op2_int <= (others => '0');
113                         do_calc_int <= '0';
114                 elsif rising_edge(sys_clk) then
115                         -- internal
116                         state_int <= state_next;
117                         z_int <= z_next;
118                         z_sign_int <= z_sign_next;
119                         strich_int <= strich_next;
120                         punkt_int <= punkt_next;
121                         wtmp_int <= wtmp_next;
122                         rbyte_int <= rbyte_next;
123                         aktop_int <= aktop_next;
124                         opp_int <= opp_next;
125                         err_int <= err_next;
126                         errc_int <= errc_next;
127                         errc_tmp_int <= errc_tmp_next;
128                         firstz_int <= firstz_next;
129                         -- out ports
130                         p_rget_int <= p_rget_next;
131                         p_write_int <= p_write_next;
132                         p_wtake_int <= p_wtake_next;
133                         p_finished_int <= p_finished_next;
134                         finished_int <= finished_next;
135                         opcode_int <= opcode_next;
136                         op1_int <= op1_next;
137                         op2_int <= op2_next;
138                         do_calc_int <= do_calc_next;
139                 end if;
140         end process;
141
142         -- next state
143         process(state_int, do_it, p_rdone, p_wdone, p_read, aktop_int, strich_int,
144                 punkt_int, calc_done, wtmp_int, opp_int, goto_calcn1, goto_op1,
145                 goto_space3, goto_sign, z_sign_int, err_int, errc_int, calc_error,
146                 op2_int)
147         begin
148                 state_next <= state_int;
149
150                 case state_int is
151                         when SIDLE =>
152                                 if do_it = '1' then
153                                         state_next <= SREAD_NEWNUMBER;
154                                 end if;
155                         when SREAD_NEWNUMBER =>
156                                 state_next <= SREAD_SPACE1_2;
157                         when SREAD_SPACE1_2 =>
158                                 if p_rdone = '1' then
159                                         state_next <= SREAD_SPACE2;
160                                 end if;
161                         when SREAD_SPACE1_3 =>
162                                 if p_rdone = '1' then
163                                         state_next <= SREAD_SPACE3;
164                                 end if;
165                         when SREAD_SPACE2 | SREAD_SPACE3 =>
166                                 if goto_calcn1 = '1' then
167                                         case state_int is
168                                                 when SREAD_SPACE2 => state_next <= SREAD_NEXTBYTE;
169                                                 when SREAD_SPACE3 => state_next <= SREAD_OP1;
170                                                 when others => assert(false) report "wtf @ state2";
171                                         end case;
172                                 end if;
173                                 if goto_sign = '1' then
174                                         case state_int is
175                                                 when SREAD_SPACE2 => state_next <= SREAD_SIGN1;
176                                                 when others => assert(false) report "wtf @ state3";
177                                         end case;
178                                 end if;
179                                 if p_rdone = '0' then
180                                         if goto_calcn1 = '0' then
181                                                 case state_int is
182                                                         when SREAD_SPACE2 => state_next <= SREAD_SPACE1_2;
183                                                         when SREAD_SPACE3 => state_next <= SREAD_SPACE1_3;
184                                                         when others => assert(false) report "wtf @ state1";
185                                                 end case;
186                                         end if;
187                                 end if;
188                         when SREAD_SIGN1 =>
189                                 if p_rdone = '0' then
190                                         state_next <= SREAD_NEXTBYTE;
191                                 end if;
192                         when SREAD_NEXTBYTE =>
193                                 if p_rdone = '1' then
194                                         state_next <= SREAD_CALCNUMBER1;
195                                 end if;
196                         when SREAD_CALCNUMBER1 =>
197                                 if goto_op1 = '1' then
198                                         state_next <= SREAD_OP1;
199                                 elsif goto_space3 = '1' then
200                                         state_next <= SREAD_SPACE3;
201                                 elsif calc_done = '1' then
202                                         state_next <= SREAD_CALCNUMBER2;
203                                 end if;
204                         when SREAD_OP1 =>
205                                 state_next <= SREAD_OP2;
206                         when SREAD_OP2 =>
207                                 if p_rdone = '0' then
208                                         if aktop_int /= ALU_NOP then
209                                                 state_next <= SCALC_1;
210                                         end if;
211                                 end if;
212                         when SREAD_CALCNUMBER2 =>
213                                 if p_rdone = '0' and calc_done = '0' then
214                                         state_next <= SREAD_NEXTBYTE;
215                                 end if;
216                         when SCALC_1 =>
217                                 if calc_done = '1' then
218                                         case opp_int is
219                                                 -- spezialfall: eine zwischenberechnung wird fuer diese
220                                                 -- kombination benoetigt
221                                                 when ALU_MUL | ALU_DIV =>
222                                                         case aktop_int is
223                                                                 when ALU_ADD | ALU_SUB | ALU_DONE => state_next <= SCALC_14;
224                                                                 when others => state_next <= SCALC_2;
225                                                         end case;
226                                                 when others => state_next <= SCALC_2;
227                                         end case;
228                                 end if;
229                         when SCALC_14 =>
230                                 if calc_done = '0' then
231                                         state_next <= SCALC_15;
232                                 end if;
233                         when SCALC_15 =>
234                                 if calc_done = '1' then
235                                         state_next <= SCALC_2;
236                                 end if;
237                         when SCALC_2 =>
238                                 if calc_done = '0' then
239                                         if aktop_int = ALU_DONE then
240                                                 state_next <= SWRITE_CHAR2;
241                                         else
242                                                 state_next <= SREAD_NEWNUMBER;
243                                         end if;
244                                 end if;
245                         when SWRITE_CHAR0 =>
246                                 if calc_done = '1' then
247                                         state_next <= SWRITE_CHAR1;
248                                 end if;
249                         when SWRITE_CHAR1 =>
250                                 if p_wdone = '1' then
251                                         -- ueberpruefung auf -2147483648 fuer testfall 39 und 40
252                                         -- x"80000000": xst (xilinx) workaround
253                                         if strich_int < 10 and strich_int /= x"80000000" then
254                                                 if z_sign_int = '1' then
255                                                         state_next <= SWRITE_SIGN1;
256                                                 else
257                                                         state_next <= SDONE;
258                                                 end if;
259                                         else
260                                                 state_next <= SWRITE_CHAR2;
261                                         end if;
262                                 end if;
263                         when SERROR1 =>
264                                 if p_wdone = '1' then
265                                         if errc_int <= 2 then
266                                                 state_next <= SDONE;
267                                         else
268                                                 state_next <= SERROR2;
269                                         end if;
270                                 end if;
271                         when SERROR2 =>
272                                 if p_wdone = '0' then
273                                         state_next <= SERROR1;
274                                 end if;
275                         when SWRITE_CHAR2 =>
276                                 if p_wdone = '0' and calc_done = '0' then
277                                         state_next <= SWRITE_CHAR0;
278                                 end if;
279                         when SWRITE_SIGN1 =>
280                                 if p_wdone = '0' then
281                                         state_next <= SWRITE_SIGN2;
282                                 end if;
283                         when SWRITE_SIGN2 =>
284                                 if p_wdone = '1' then
285                                         state_next <= SDONE;
286                                 end if;
287
288                         when SDONE =>
289                                 if p_wdone = '0' and do_it = '0' then
290                                         state_next <= SIDLE;
291                                 end if;
292                 end case;
293
294                 -- fehlerbehandlung
295                 case state_int is
296                         when SERROR1 | SERROR2 | SDONE => null;
297                         when others =>
298                                 if err_int > 0 then
299                                         state_next <= SERROR1;
300                                 end if;
301                 end case;
302         end process;
303
304         -- out
305         process(state_int, p_read, p_write_int, z_int, rbyte_int, p_rget_int,
306                 strich_int, aktop_int, opp_int, opcode_int, op1_int, op2_int, op3, opM,
307                 do_calc_int, wtmp_int, punkt_int, z_sign_int, err_int, errc_int,
308                 errc_tmp_int, firstz_int, calc_done, calc_error)
309                 function hbyte2csigned (x : hbyte) return csigned is
310                         variable y : csigned;
311                 begin
312                         case x is
313                                 when x"30" => y := x"00000000";
314                                 when x"31" => y := x"00000001";
315                                 when x"32" => y := x"00000002";
316                                 when x"33" => y := x"00000003";
317                                 when x"34" => y := x"00000004";
318                                 when x"35" => y := x"00000005";
319                                 when x"36" => y := x"00000006";
320                                 when x"37" => y := x"00000007";
321                                 when x"38" => y := x"00000008";
322                                 when x"39" => y := x"00000009";
323                                 when others => assert(false) report "hbyte2csigned: shouldn't happen";
324                         end case;
325                         return y;
326                 end function hbyte2csigned;
327
328                 function csigned2hbyte (x : csigned) return hbyte is
329                         variable y : hbyte;
330                 begin
331                         case x is
332                                 when x"00000000" => y := x"30";
333                                 when x"00000001" => y := x"31";
334                                 when x"00000002" => y := x"32";
335                                 when x"00000003" => y := x"33";
336                                 when x"00000004" => y := x"34";
337                                 when x"00000005" => y := x"35";
338                                 when x"00000006" => y := x"36";
339                                 when x"00000007" => y := x"37";
340                                 when x"00000008" => y := x"38";
341                                 when x"00000009" => y := x"39";
342                                 when others => assert(false) report "csigned2hbyte: shouldn't happen";
343                         end case;
344                         return y;
345                 end function csigned2hbyte;
346
347
348                 variable multmp : signed(((2*CBITS)-1) downto 0);
349                 variable tmp : csigned;
350
351                 type errstrings is array (natural range 1 to 3) of hstring;
352                 constant error_str : errstrings := (
353                         1 => " > Fehler:                             Division durch Null             " & nul,
354                         2 => " > Fehler:                             Syntax                          " & nul,
355                         3 => " > Fehler:                             Over- bzw. Underflow            " & nul
356                 );
357         begin
358                 -- internal
359                 z_next <= z_int;
360                 z_sign_next <= z_sign_int;
361                 strich_next <= strich_int;
362                 punkt_next <= punkt_int;
363                 wtmp_next <= wtmp_int;
364                 rbyte_next <= rbyte_int;
365                 aktop_next <= aktop_int;
366                 opp_next <= opp_int;
367                 err_next <= err_int;
368                 errc_next <= errc_int;
369                 errc_tmp_next <= errc_tmp_int;
370                 firstz_next <= firstz_int;
371                 -- signals
372                 p_rget_next <= '0';
373                 p_write_next <= p_write_int;
374                 p_wtake_next <= '0';
375                 p_finished_next <= '0';
376                 finished_next <= '0';
377                 opcode_next <= opcode_int;
378                 op1_next <= op1_int;
379                 op2_next <= op2_int;
380                 do_calc_next <= '0';
381                 goto_calcn1 <= '0';
382                 goto_op1 <= '0';
383                 goto_space3 <= '0';
384                 goto_sign <= '0';
385
386                 case state_int is
387                         when SIDLE =>
388                                 strich_next <= (others => '0');
389                                 punkt_next <= (0 => '1', others => '0');
390                                 opp_next <= ALU_NOP;
391                         when SREAD_NEWNUMBER =>
392                                 z_next <= (others => '0');
393                                 z_sign_next <= '0';
394                                 firstz_next <= true;
395                                 rbyte_next <= (others => '0');
396                                 p_write_next <= (others => '0');
397                                 aktop_next <= ALU_NOP;
398                         when SREAD_NEXTBYTE | SREAD_SPACE1_2 | SREAD_SPACE1_3 =>
399                                 p_rget_next <= '1';
400                         when SREAD_SPACE2 | SREAD_SPACE3 =>
401                                 case p_read is
402                                         when x"20" =>
403                                                 null;
404                                         when x"2D" =>
405                                                 case state_int is
406                                                         when SREAD_SPACE2 => goto_sign <= '1';
407                                                         when SREAD_SPACE3 => goto_calcn1 <= '1'; p_rget_next <= '1';
408                                                         when others => assert(false) report "SREAD_SPACE2/3: shouldn't happen";
409                                                 end case;
410                                         when others =>
411                                                 goto_calcn1 <= '1';
412                                                 p_rget_next <= '1';
413                                 end case;
414
415                         when SREAD_CALCNUMBER1 =>
416                                 case p_read is
417                                         -- '+', '-', '*', '/'
418                                         when x"2B" | x"2D" | x"2A" | x"2F" | x"00" =>
419                                                 if firstz_int then
420                                                         err_next <= 2;
421                                                 else
422                                                         goto_op1 <= '1';
423                                                         p_rget_next <= '1';
424                                                 end if;
425
426                                         -- ' '
427                                         when x"20" =>
428                                                 goto_space3 <= '1';
429                                                 p_rget_next <= '1';
430
431                                         when others =>
432                                                 op1_next <= z_int;
433                                                 opcode_next <= ALU_MUL;
434                                                 op2_next <= to_signed(10,CBITS);
435                                                 firstz_next <= false;
436                                                 do_calc_next <= '1';
437                                 end case;
438                         when SREAD_SIGN1 =>
439                                 z_sign_next <= '1';
440                         when SREAD_CALCNUMBER2 =>
441                                 z_next <= op3 + hbyte2csigned(p_read);
442                         when SREAD_OP2 =>
443                                 null;
444                         when SREAD_OP1 =>
445                                 case p_read is
446                                         when x"2B" => aktop_next <= ALU_ADD; -- '+'
447                                         when x"2D" => aktop_next <= ALU_SUB; -- '-'
448                                         when x"2A" => aktop_next <= ALU_MUL; -- '*'
449                                         when x"2F" => aktop_next <= ALU_DIV; -- '/'
450                                         when x"00" => aktop_next <= ALU_DONE; -- '\0'
451
452                                         when others => err_next <= 2;
453                                 end case;
454
455
456                         when SCALC_1 =>
457                                 if z_sign_int = '1' then
458                                         tmp := (not z_int) + 1;
459                                         z_next <= tmp;
460                                         z_sign_next <= '0';
461                                 else
462                                         tmp := z_int;
463                                 end if;
464
465                                 case opp_int is
466                                         when ALU_NOP | ALU_ADD | ALU_SUB =>
467                                                 case opp_int  is
468                                                         when ALU_SUB =>
469                                                                 -- xst (xilinx) workaround
470                                                                 if x"80000000" = tmp then
471                                                                         -- vgl. testfall 37 und 38
472                                                                         err_next <= 3;
473                                                                         op1_next <= tmp;
474                                                                 else
475                                                                         op1_next <= (not tmp) + 1;
476                                                                 end if;
477                                                         when others => op1_next <= tmp;
478                                                 end case;
479                                                 case aktop_int is
480                                                         when ALU_ADD | ALU_SUB | ALU_DONE =>
481                                                                 opcode_next <= ALU_ADD;
482                                                                 op2_next <= strich_int;
483                                                         when ALU_MUL | ALU_DIV =>
484                                                                 opcode_next <= ALU_MUL;
485                                                                 op2_next <= punkt_int;
486                                                         when others => assert(false) report "SCALC_1/1: shouldn't happen!";
487                                                 end case;
488
489                                         when ALU_MUL | ALU_DIV =>
490                                                 case aktop_int is
491                                                         when ALU_ADD | ALU_SUB | ALU_DONE | ALU_MUL | ALU_DIV =>
492                                                                 op1_next <= punkt_int;
493                                                                 opcode_next <= opp_int;
494                                                                 op2_next <= tmp;
495                                                         when others => assert(false) report "SCALC_1/2: shouldn't happen!";
496                                                 end case;
497                                         when others => assert(false) report "SCALC_1/3: shouldn't happen!";
498                                 end case;
499                                 do_calc_next <= '1';
500
501                         when SCALC_14 =>
502                                 -- ueberpruefung kann man sich sparen, da diese ohnehin in
503                                 -- nextstate gemacht wird.
504                                 op1_next <= op3;
505                                 do_calc_next <= '0';
506
507                         when SCALC_15 =>
508                                 -- ueberpruefung kann man sich sparen, da diese ohnehin in
509                                 -- nextstate gemacht wird.
510                                 opcode_next <= ALU_ADD;
511                                 op2_next <= strich_int;
512                                 punkt_next <= (0 => '1', others => '0');
513                                 do_calc_next <= '1';
514
515                         when SCALC_2 =>
516                                 case opp_int is
517                                         when ALU_NOP | ALU_ADD | ALU_SUB | ALU_MUL | ALU_DIV =>
518                                                 case aktop_int is
519                                                         when ALU_ADD | ALU_SUB | ALU_DONE =>
520                                                                 if aktop_int = ALU_DONE and op3 < 0 then
521                                                                         strich_next <= (not op3) + 1;
522                                                                         wtmp_next <= (not op3) + 1;
523                                                                         z_sign_next <= '1';
524                                                                 else
525                                                                         strich_next <= op3;
526                                                                         wtmp_next <= op3;
527                                                                 end if;
528                                                         when ALU_MUL | ALU_DIV =>
529                                                                 punkt_next <= op3;
530                                                         when others => assert (false) report "SCALC_2/1: shouldn't happen!";
531                                                 end case;
532                                         when ALU_DONE => null;
533                                         when others => assert (false) report "SCALC_2/2: shouldn't happen!";
534                                 end case;
535                                 -- aktuelle rechenoperation fuer naechste 'runde' uebernehmen
536                                 opp_next <= aktop_int;
537
538                         when SWRITE_CHAR0 =>
539                                 -- fuer testfall 39 und 40
540                                 if strich_int = to_signed(-214748364,CBITS) then
541                                         op1_next <= to_signed(214748364,CBITS);
542                                         strich_next <= to_signed(214748364,CBITS);
543                                 else
544                                         op1_next <= strich_int;
545                                 end if;
546                                 opcode_next <= ALU_DIV;
547                                 op2_next <= to_signed(10,CBITS);
548                                 do_calc_next <= '1';
549                         when SWRITE_CHAR1 =>
550                                 do_calc_next <= '1';
551                                 p_wtake_next <= '1';
552                                 tmp := opM;
553                                 p_write_next <= csigned2hbyte(tmp);
554                                 wtmp_next <= op3;
555                         when SWRITE_CHAR2 =>
556                                 strich_next <= wtmp_int;
557
558                         when SWRITE_SIGN1 =>
559                                 null;
560                         when SWRITE_SIGN2 =>
561                                 if z_sign_int = '1' then
562                                         p_wtake_next <= '1';
563                                         p_write_next <= x"2D";
564                                 else
565                                         assert(false) report "SWRITE_SIGN: shouldn't happen!";
566                                 end if;
567
568                         when SERROR1 =>
569                                 p_wtake_next <= '1';
570                                 p_write_next <= hbyte(to_unsigned (character'pos(error_str(err_int)(errc_int)),8));
571                                 errc_tmp_next <= errc_int - 1;
572                         when SERROR2 =>
573                                 errc_next <= errc_tmp_int;
574
575                         when SDONE =>
576                                 err_next <= 0;
577                                 errc_next <= 71;
578                                 p_finished_next <= '1';
579                                 finished_next <= '1';
580                 end case;
581
582                 -- fehlerbehandlung
583                 case state_int is
584                         when SERROR1 | SERROR2 | SDONE => null;
585                         when others =>
586                                 if calc_error = '1' then
587                                         if op2_int = 0 then
588                                                 err_next <= 1;
589                                         else
590                                                 err_next <= 3;
591                                         end if;
592                                 end if;
593                 end case;
594         end process;
595 end architecture beh;