parser: vorzeichen werden nun auch beachtet
authorBernhard Urban <lewurm@gmail.com>
Tue, 11 May 2010 14:21:57 +0000 (16:21 +0200)
committerBernhard Urban <lewurm@gmail.com>
Tue, 11 May 2010 14:21:57 +0000 (16:21 +0200)
src/parser.test
src/parser.vhd

index caee21e6a0688faaa6173d231967688b20a78ab7..a0098f11eea875ee8b42c8899ad12ae3b989eabd 100644 (file)
 # t19
 50+1      
 51
+# t20
+40-100
+-60
+# t21
+-40*2
+-80
+# t22
+4/-2
+-2
+# t23
+-2 * -1 --1
+3
+# t24
+-2 * -2 --2 * -1 * -1 - 100
+-94
+# t25
+     -1234 / -500
+2
index c622fc40082ad8e909837b30f88ad466e50aa751..d0f523ae2b83ca85e8707d4595e4fa7e10ebae3a 100644 (file)
@@ -35,8 +35,9 @@ end entity parser;
 architecture beh of parser is
        type PARSER_STATE is (SIDLE, SREAD_NEWNUMBER, SREAD_SPACE1_2,
        SREAD_SPACE1_3, SREAD_SPACE2, SREAD_SPACE3, SREAD_OP1, SREAD_OP2,
-       SREAD_NEXTBYTE, SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1, SCALC_14,
-       SCALC_15, SCALC_2, SWRITE_CHAR1, SWRITE_CHAR2, SDONE, SERROR1, SERROR2);
+       SREAD_SIGN1, SREAD_NEXTBYTE, SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1,
+       SCALC_14, SCALC_15, SCALC_2, SWRITE_CHAR1, SWRITE_CHAR2, SWRITE_SIGN1,
+       SWRITE_SIGN2, SDONE, SERROR1, SERROR2);
        signal state_int, state_next : PARSER_STATE;
        signal z_int, z_next, strich_int, strich_next, wtmp_int, wtmp_next : csigned;
        signal punkt_int, punkt_next : csigned;
@@ -51,7 +52,8 @@ architecture beh of parser is
        signal op1_int, op1_next : csigned;
        signal op2_int, op2_next : csigned;
        signal do_calc_int, do_calc_next : std_logic;
-       signal goto_calcn1, goto_op1, goto_space3 : std_logic;
+       signal goto_calcn1, goto_op1, goto_space3, goto_sign : std_logic;
+       signal z_sign_next, z_sign_int : std_logic;
 begin
        p_write <= p_write_int;
        p_rget <= p_rget_int;
@@ -68,6 +70,7 @@ begin
                if sys_res_n = '0' then
                        state_int <= SIDLE;
                        z_int <= (others => '0');
+                       z_sign_int <= '0';
                        strich_int <= (others => '0');
                        punkt_int <= (others => '0');
                        wtmp_int <= (others => '0');
@@ -90,6 +93,7 @@ begin
                        -- internal
                        state_int <= state_next;
                        z_int <= z_next;
+                       z_sign_int <= z_sign_next;
                        strich_int <= strich_next;
                        punkt_int <= punkt_next;
                        wtmp_int <= wtmp_next;
@@ -111,7 +115,7 @@ begin
        -- next state
        process(state_int, do_it, p_rdone, p_wdone, p_read, aktop_int, strich_int,
                punkt_int, calc_done, wtmp_int, opp_int, goto_calcn1, goto_op1,
-               goto_space3)
+               goto_space3, goto_sign, z_sign_int)
        begin
                state_next <= state_int;
 
@@ -131,21 +135,31 @@ begin
                                        state_next <= SREAD_SPACE3;
                                end if;
                        when SREAD_SPACE2 | SREAD_SPACE3 =>
+                               if goto_calcn1 = '1' then
+                                       case state_int is
+                                               when SREAD_SPACE2 => state_next <= SREAD_NEXTBYTE;
+                                               when SREAD_SPACE3 => state_next <= SREAD_OP1;
+                                               when others => assert(false) report "wtf @ state2";
+                                       end case;
+                               end if;
+                               if goto_sign = '1' then
+                                       case state_int is
+                                               when SREAD_SPACE2 => state_next <= SREAD_SIGN1;
+                                               when others => assert(false) report "wtf @ state3";
+                                       end case;
+                               end if;
                                if p_rdone = '0' then
                                        if goto_calcn1 = '0' then
                                                case state_int is
                                                        when SREAD_SPACE2 => state_next <= SREAD_SPACE1_2;
                                                        when SREAD_SPACE3 => state_next <= SREAD_SPACE1_3;
-                                                       when others => assert(false) report "wtf @ state2";
+                                                       when others => assert(false) report "wtf @ state1";
                                                end case;
                                        end if;
                                end if;
-                               if goto_calcn1 = '1' then
-                                       case state_int is
-                                               when SREAD_SPACE2 => state_next <= SREAD_NEXTBYTE;
-                                               when SREAD_SPACE3 => state_next <= SREAD_OP1;
-                                               when others => assert(false) report "wtf @ state1";
-                                       end case;
+                       when SREAD_SIGN1 =>
+                               if p_rdone = '0' then
+                                       state_next <= SREAD_NEXTBYTE;
                                end if;
                        when SREAD_NEXTBYTE =>
                                if p_rdone = '1' then
@@ -201,7 +215,11 @@ begin
                        when SWRITE_CHAR1 =>
                                if p_wdone = '1' then
                                        if strich_int < 10 then
-                                               state_next <= SDONE;
+                                               if z_sign_int = '1' then
+                                                       state_next <= SWRITE_SIGN1;
+                                               else
+                                                       state_next <= SDONE;
+                                               end if;
                                        else
                                                state_next <= SWRITE_CHAR2;
                                        end if;
@@ -219,6 +237,15 @@ begin
                                if p_wdone = '0' then
                                        state_next <= SWRITE_CHAR1;
                                end if;
+                       when SWRITE_SIGN1 =>
+                               if p_wdone = '0' then
+                                       state_next <= SWRITE_SIGN2;
+                               end if;
+                       when SWRITE_SIGN2 =>
+                               if p_wdone = '1' then
+                                       state_next <= SDONE;
+                               end if;
+
                        when SDONE =>
                                if p_wdone = '0' and do_it = '0' then
                                        state_next <= SIDLE;
@@ -229,7 +256,7 @@ begin
        -- out
        process(state_int, p_read, p_write_int, z_int, rbyte_int, p_rget_int,
                strich_int, aktop_int, opp_int, opcode_int, op1_int, op2_int, op3,
-               do_calc_int, wtmp_int, punkt_int)
+               do_calc_int, wtmp_int, punkt_int, z_sign_int)
                function hbyte2csigned (x : hbyte) return csigned is
                        variable y : csigned;
                begin
@@ -273,6 +300,7 @@ begin
        begin
                -- internal
                z_next <= z_int;
+               z_sign_next <= z_sign_int;
                strich_next <= strich_int;
                punkt_next <= punkt_int;
                wtmp_next <= wtmp_int;
@@ -291,6 +319,7 @@ begin
                goto_calcn1 <= '0';
                goto_op1 <= '0';
                goto_space3 <= '0';
+               goto_sign <= '0';
 
                case state_int is
                        when SIDLE =>
@@ -299,6 +328,7 @@ begin
                                opp_next <= ALU_NOP;
                        when SREAD_NEWNUMBER =>
                                z_next <= (others => '0');
+                               z_sign_next <= '0';
                                rbyte_next <= (others => '0');
                                p_write_next <= (others => '0');
                                aktop_next <= ALU_NOP;
@@ -308,6 +338,12 @@ begin
                                case p_read is
                                        when x"20" =>
                                                null;
+                                       when x"2D" =>
+                                               case state_int is
+                                                       when SREAD_SPACE2 => goto_sign <= '1';
+                                                       when SREAD_SPACE3 => goto_calcn1 <= '1'; p_rget_next <= '1';
+                                                       when others => assert(false) report "SREAD_SPACE2/3: shouldn't happen";
+                                               end case;
                                        when others =>
                                                goto_calcn1 <= '1';
                                                p_rget_next <= '1';
@@ -330,6 +366,8 @@ begin
                                                multmp := (z_int * 10) + hbyte2csigned(p_read);
                                                z_next <= multmp((CBITS-1) downto 0);
                                end case;
+                       when SREAD_SIGN1 =>
+                               z_sign_next <= '1';
                        when SREAD_CALCNUMBER2 | SREAD_OP2 =>
                                null;
                        when SREAD_OP1 =>
@@ -358,11 +396,19 @@ begin
 
 
                        when SCALC_1 =>
+                               if z_sign_int = '1' then
+                                       tmp := (not z_int) + 1;
+                                       z_next <= tmp;
+                                       z_sign_next <= '0';
+                               else
+                                       tmp := z_int;
+                               end if;
+
                                case opp_int is
                                        when ALU_NOP | ALU_ADD | ALU_SUB =>
                                                case opp_int  is
-                                                       when ALU_SUB => op1_next <= (not z_int) + 1;
-                                                       when others => op1_next <= z_int;
+                                                       when ALU_SUB => op1_next <= (not tmp) + 1;
+                                                       when others => op1_next <= tmp;
                                                end case;
                                                case aktop_int is
                                                        when ALU_ADD | ALU_SUB | ALU_DONE =>
@@ -379,7 +425,7 @@ begin
                                                        when ALU_ADD | ALU_SUB | ALU_DONE | ALU_MUL | ALU_DIV =>
                                                                op1_next <= punkt_int;
                                                                opcode_next <= opp_int;
-                                                               op2_next <= z_int;
+                                                               op2_next <= tmp;
                                                        when others => assert(false) report "SCALC_1/2: shouldn't happen!";
                                                end case;
                                        when others => assert(false) report "SCALC_1/3: shouldn't happen!";
@@ -405,7 +451,12 @@ begin
                                        when ALU_NOP | ALU_ADD | ALU_SUB | ALU_MUL | ALU_DIV =>
                                                case aktop_int is
                                                        when ALU_ADD | ALU_SUB | ALU_DONE =>
-                                                               strich_next <= op3;
+                                                               if aktop_int = ALU_DONE and op3 < 0 then
+                                                                       strich_next <= (not op3) + 1;
+                                                                       z_sign_next <= '1';
+                                                               else
+                                                                       strich_next <= op3;
+                                                               end if;
                                                        when ALU_MUL | ALU_DIV =>
                                                                punkt_next <= op3;
                                                        when others => assert (false) report "SCALC_2/1: shouldn't happen!";
@@ -423,6 +474,16 @@ begin
                        when SWRITE_CHAR2 =>
                                strich_next <= wtmp_int;
 
+                       when SWRITE_SIGN1 =>
+                               null;
+                       when SWRITE_SIGN2 =>
+                               if z_sign_int = '1' then
+                                       p_wtake_next <= '1';
+                                       p_write_next <= x"2D";
+                               else
+                                       assert(false) report "SWRITE_SIGN: shouldn't happen!";
+                               end if;
+
                        when SERROR1 =>
                                -- TODO
                                null;