allgemein: konstanten verwenden
[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 <= HSPALTE_MAX;
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                                 if p_rdone = '0' then
249                                         case state_int is
250                                                 when SREAD_SPACE_PROC => state_next <= SREAD_SPACE_GET;
251                                                 when SREAD_SPACE_PROC_SIGN => state_next <= SREAD_SPACE_GET_SIGN;
252                                                 when others => assert(false) report "wtf @ state1";
253                                         end case;
254                                 else
255                                         if p_read = x"2d" and state_int = SREAD_SPACE_PROC then
256                                                 -- vorzeichen?
257                                                 state_next <= SREAD_SIGN;
258                                         elsif p_read /= x"20" then
259                                                 -- leerzeichen sollen ignoriert werden
260                                                 p_rget_next <= '1';
261                                                 case state_int is
262                                                         when SREAD_SPACE_PROC => state_next <= SREAD_NEXTBYTE;
263                                                         when SREAD_SPACE_PROC_SIGN => state_next <= SREAD_OP1;
264                                                         when others => assert(false) report "SREAD_SPACE_PROC{,_SIGN}: shouldn't happen";
265                                                 end case;
266                                         end if;
267                                 end if;
268
269                         when SREAD_SIGN =>
270                                 z_sign_next <= '1';
271                                 if p_rdone = '0' then
272                                         state_next <= SREAD_NEXTBYTE;
273                                 end if;
274                         when SREAD_NEXTBYTE =>
275                                 p_rget_next <= '1';
276                                 if p_rdone = '1' then
277                                         state_next <= SREAD_CALCNUMBER1;
278                                 end if;
279                         when SREAD_CALCNUMBER1 =>
280                                 case p_read is
281                                         -- '+', '-', '*', '/'
282                                         when x"2B" | x"2D" | x"2A" | x"2F" | x"00" =>
283                                                 if firstz_int then
284                                                         err_next <= 2;
285                                                 else
286                                                         state_next <= SREAD_OP1;
287                                                         p_rget_next <= '1';
288                                                 end if;
289
290                                         -- ' '
291                                         when x"20" =>
292                                                 state_next <= SREAD_SPACE_PROC_SIGN;
293                                                 p_rget_next <= '1';
294
295                                         when others =>
296                                                 op1_next <= z_int;
297                                                 opcode_next <= ALU_MUL;
298                                                 op2_next <= to_signed(10,CBITS);
299                                                 firstz_next <= false;
300                                                 do_calc_next <= '1';
301                                 end case;
302                                 if calc_done = '1' then
303                                         state_next <= SREAD_CALCNUMBER2;
304                                 end if;
305                         when SREAD_CALCNUMBER2 =>
306                                 z_next <= op3 + hbyte2csigned(p_read);
307                                 if p_rdone = '0' and calc_done = '0' then
308                                         state_next <= SREAD_NEXTBYTE;
309                                 end if;
310
311                         when SREAD_OP1 =>
312                                 case p_read is
313                                         when x"2B" => aktop_next <= ALU_ADD; -- '+'
314                                         when x"2D" => aktop_next <= ALU_SUB; -- '-'
315                                         when x"2A" => aktop_next <= ALU_MUL; -- '*'
316                                         when x"2F" => aktop_next <= ALU_DIV; -- '/'
317                                         when x"00" => aktop_next <= ALU_DONE; -- '\0'
318
319                                         when others => err_next <= 2;
320                                 end case;
321                                 state_next <= SREAD_OP2;
322                         when SREAD_OP2 =>
323                                 if p_rdone = '0' then
324                                         state_next <= SCALC_1;
325                                 end if;
326
327                         when SCALC_1 =>
328                                 if z_sign_int = '1' then
329                                         tmp := (not z_int) + 1;
330                                         z_next <= tmp;
331                                         z_sign_next <= '0';
332                                 else
333                                         tmp := z_int;
334                                 end if;
335
336                                 case opp_int is
337                                         when ALU_NOP | ALU_ADD | ALU_SUB =>
338                                                 case opp_int  is
339                                                         when ALU_SUB =>
340                                                                 -- xst (xilinx) workaround
341                                                                 if x"80000000" = tmp then
342                                                                         -- vgl. testfall 37 und 38
343                                                                         err_next <= 3;
344                                                                         op1_next <= tmp;
345                                                                 else
346                                                                         op1_next <= (not tmp) + 1;
347                                                                 end if;
348                                                         when others => op1_next <= tmp;
349                                                 end case;
350                                                 case aktop_int is
351                                                         when ALU_ADD | ALU_SUB | ALU_DONE =>
352                                                                 opcode_next <= ALU_ADD;
353                                                                 op2_next <= strich_int;
354                                                         when ALU_MUL | ALU_DIV =>
355                                                                 opcode_next <= ALU_MUL;
356                                                                 op2_next <= punkt_int;
357                                                         when others => assert(false) report "SCALC_1/1: shouldn't happen!";
358                                                 end case;
359
360                                         when ALU_MUL | ALU_DIV =>
361                                                 case aktop_int is
362                                                         when ALU_ADD | ALU_SUB | ALU_DONE | ALU_MUL | ALU_DIV =>
363                                                                 op1_next <= punkt_int;
364                                                                 opcode_next <= opp_int;
365                                                                 op2_next <= tmp;
366                                                         when others => assert(false) report "SCALC_1/2: shouldn't happen!";
367                                                 end case;
368                                         when others => assert(false) report "SCALC_1/3: shouldn't happen!";
369                                 end case;
370                                 do_calc_next <= '1';
371
372                                 if calc_done = '1' then
373                                         case opp_int is
374                                                 -- spezialfall: eine zwischenberechnung wird fuer diese
375                                                 -- kombination benoetigt
376                                                 when ALU_MUL | ALU_DIV =>
377                                                         case aktop_int is
378                                                                 when ALU_ADD | ALU_SUB | ALU_DONE => state_next <= SCALC_14;
379                                                                 when others => state_next <= SCALC_2;
380                                                         end case;
381                                                 when others => state_next <= SCALC_2;
382                                         end case;
383                                 end if;
384                         when SCALC_14 =>
385                                 -- ueberpruefung kann man sich sparen, da diese ohnehin in
386                                 -- nextstate gemacht wird.
387                                 op1_next <= op3;
388                                 do_calc_next <= '0';
389
390                                 if calc_done = '0' then
391                                         state_next <= SCALC_15;
392                                 end if;
393                         when SCALC_15 =>
394                                 -- ueberpruefung kann man sich sparen, da diese ohnehin in
395                                 -- nextstate gemacht wird.
396                                 opcode_next <= ALU_ADD;
397                                 op2_next <= strich_int;
398                                 punkt_next <= (0 => '1', others => '0');
399                                 do_calc_next <= '1';
400
401                                 if calc_done = '1' then
402                                         state_next <= SCALC_2;
403                                 end if;
404                         when SCALC_2 =>
405                                 case opp_int is
406                                         when ALU_NOP | ALU_ADD | ALU_SUB | ALU_MUL | ALU_DIV =>
407                                                 case aktop_int is
408                                                         when ALU_ADD | ALU_SUB | ALU_DONE =>
409                                                                 if aktop_int = ALU_DONE and op3 < 0 then
410                                                                         strich_next <= (not op3) + 1;
411                                                                         wtmp_next <= (not op3) + 1;
412                                                                         z_sign_next <= '1';
413                                                                 else
414                                                                         strich_next <= op3;
415                                                                         wtmp_next <= op3;
416                                                                 end if;
417                                                         when ALU_MUL | ALU_DIV =>
418                                                                 punkt_next <= op3;
419                                                         when others => assert (false) report "SCALC_2/1: shouldn't happen!";
420                                                 end case;
421                                         when ALU_DONE => null;
422                                         when others => assert (false) report "SCALC_2/2: shouldn't happen!";
423                                 end case;
424                                 -- aktuelle rechenoperation fuer naechste 'runde' uebernehmen
425                                 opp_next <= aktop_int;
426
427                                 if calc_done = '0' then
428                                         if aktop_int = ALU_DONE then
429                                                 state_next <= SWRITE_CHAR2;
430                                         else
431                                                 state_next <= SREAD_NEWNUMBER;
432                                         end if;
433                                 end if;
434
435                         when SWRITE_CHAR0 =>
436                                 -- fuer testfall 39 und 40
437                                 if strich_int = to_signed(-214748364,CBITS) then
438                                         op1_next <= to_signed(214748364,CBITS);
439                                         strich_next <= to_signed(214748364,CBITS);
440                                 else
441                                         op1_next <= strich_int;
442                                 end if;
443                                 opcode_next <= ALU_DIV;
444                                 op2_next <= to_signed(10,CBITS);
445                                 do_calc_next <= '1';
446
447                                 if calc_done = '1' then
448                                         state_next <= SWRITE_CHAR1;
449                                 end if;
450                         when SWRITE_CHAR1 =>
451                                 do_calc_next <= '1';
452                                 p_wtake_next <= '1';
453                                 tmp := opM;
454                                 p_write_next <= csigned2hbyte(tmp);
455                                 wtmp_next <= op3;
456
457                                 if p_wdone = '1' then
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 <= SDONE;
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                                         state_next <= SDONE;
490                                 end if;
491
492                         when SERROR1 =>
493                                 p_wtake_next <= '1';
494                                 p_write_next <= hbyte(to_unsigned (character'pos(error_str(err_int)(errc_int)),8));
495                                 errc_tmp_next <= errc_int - 1;
496                                 if p_wdone = '1' then
497                                         if errc_int <= 2 then
498                                                 state_next <= SDONE;
499                                         else
500                                                 state_next <= SERROR2;
501                                         end if;
502                                 end if;
503                         when SERROR2 =>
504                                 errc_next <= errc_tmp_int;
505                                 if p_wdone = '0' then
506                                         state_next <= SERROR1;
507                                 end if;
508
509                         when SDONE =>
510                                 err_next <= 0;
511                                 errc_next <= HSPALTE_MAX;
512                                 p_finished_next <= '1';
513                                 finished_next <= '1';
514
515                                 if p_wdone = '0' and do_it = '0' then
516                                         state_next <= SIDLE;
517                                 end if;
518                 end case;
519
520                 -- fehlerbehandlung
521                 case state_int is
522                         -- diese states sind ausgenommen vom "pokemon-exception-handling"
523                         when SERROR1 | SERROR2 | SDONE => null;
524                         when others =>
525                                 if calc_error = '1' then
526                                         if op2_int = 0 then
527                                                 err_next <= 1;
528                                         else
529                                                 err_next <= 3;
530                                         end if;
531                                 end if;
532
533                                 if err_int > 0 then
534                                         state_next <= SERROR1;
535                                 end if;
536                 end case;
537         end process;
538 end architecture beh;