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