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