parser: ausdruecke wie "x+y+z" koennen schon ausgewertet werden
authorBernhard Urban <lewurm@gmail.com>
Sun, 9 May 2010 21:38:01 +0000 (23:38 +0200)
committerBernhard Urban <lewurm@gmail.com>
Mon, 10 May 2010 16:18:30 +0000 (18:18 +0200)
src/beh_parser_tb.do
src/beh_parser_tb.vhd
src/parser.test
src/parser.vhd

index 2f52a4c1ca2bb9432ee6ceae7c7615665405734b..35fed77b6df4960c670c2c46b50e3e8812af1a78 100644 (file)
@@ -4,6 +4,41 @@ alias rr "restart -f"
 #signale hinzufuegen
 add wave inst/*
 
+delete wave /beh_parser_tb/inst/op1_int
+delete wave /beh_parser_tb/inst/op1
+delete wave /beh_parser_tb/inst/op1_next
+add wave -radix decimal inst/op1_int
+
+delete wave /beh_parser_tb/inst/op2_int
+delete wave /beh_parser_tb/inst/op2
+delete wave /beh_parser_tb/inst/op2_next
+add wave -radix decimal inst/op2_int
+
+delete wave /beh_parser_tb/inst/op3
+add wave -radix decimal inst/op3
+
+delete wave /beh_parser_tb/inst/z_int
+delete wave /beh_parser_tb/inst/z_next
+add wave -radix decimal inst/z_int
+add wave -radix decimal inst/z_next
+
+delete wave /beh_parser_tb/inst/strich_int
+delete wave /beh_parser_tb/inst/strich_next
+add wave -radix decimal inst/strich_int
+add wave -radix decimal inst/strich_next
+
+delete wave /beh_parser_tb/inst/wtmp_int
+delete wave /beh_parser_tb/inst/wtmp_next
+add wave -radix decimal inst/wtmp_int
+add wave -radix decimal inst/wtmp_next
+
+delete wave /beh_parser_tb/inst/p_write_int
+delete wave /beh_parser_tb/inst/p_write_next
+delete wave /beh_parser_tb/inst/p_write
+add wave -hex inst/p_write_int
+add wave -hex inst/p_write_next
+
+
 #rauszoomen
 wave zoomout 500.0
 
index fc43bcf5303bc5dbdc2b155a8f6f12490de51d5f..70ed098ad03a685d6df3353048ed4a47148bdc06 100644 (file)
@@ -85,10 +85,11 @@ begin
                variable input : hstring;
                variable expectedresult : hstring;
                variable realresult : hstring;
+               variable hstrtmp : hstring;
 
                variable checkall : boolean := true;
                variable run_tc : boolean := true;
-               variable i, j, k : natural;
+               variable i, j, k, y : natural;
        begin
                -- init & reset
                sys_res_n <= '0';
@@ -102,7 +103,7 @@ begin
 
                i := 1;
                f_loop : while not endfile(f) loop
-                       realresult := (others => character'val(0));
+                       realresult := (71 => character'val(0), others => character'val(32));
 
                        f1_loop : while not endfile(f) loop
                                readline (f, l);
@@ -128,6 +129,7 @@ begin
                                        if (expectedresult(1) = '#') then
                                                next f2_loop;
                                        else
+                                               y := l'length;
                                                exit f2_loop;
                                        end if;
                                else
@@ -136,6 +138,16 @@ begin
                                end if;
                        end loop f2_loop;
 
+                       -- ergebnis string richtig formatieren
+                       hstrtmp := expectedresult;
+                       expectedresult := (71 => character'val(0), others => character'val(32));
+                       for x in 1 to 70 loop
+                               if hstrtmp(x) /= character'val(0) then
+                                       expectedresult((70-y) + x) := hstrtmp(x);
+                               end if;
+                       end loop;
+
+
                        report "testcase(" & natural'image(i) & ").input: " & input;
                        report "testcase(" & natural'image(i) & ").expectedresult: " & expectedresult;
                        i := i + 1;
@@ -143,7 +155,7 @@ begin
                        icwait(sys_clk, 5);
                        do_it <= '1';
                        run_tc := true;
-                       j := 1; k := 1;
+                       j := 1; k := 70;
 
                        while run_tc loop
                                wait on p_rget, p_wtake, p_finished, finished;
@@ -161,7 +173,7 @@ begin
                                if p_wtake = '1' then
                                        realresult(k) := character'val(to_integer(unsigned(p_write)));
                                        p_wdone <= '1';
-                                       k := k + 1;
+                                       k := k - 1;
                                end if;
                                if p_wtake = '0' then
                                        p_wdone <= '0';
@@ -173,7 +185,7 @@ begin
                        end loop;
                        
                        do_it <= '0';
-                       report "realresult: " & realresult;
+                       report "realresult                : " & realresult;
                        if realresult /= expectedresult then
                                checkall := false;
                        end if;
index c3501c7e2afd1fca0f6f206b69ec8a0627098ae0..f27bc3a09f918a3020bb25d274a5fa4d1ed8b2c7 100644 (file)
@@ -6,3 +6,15 @@
 # testfall 2: 
 12345
 12345
+# t3:
+12+5
+17
+# t4:
+1337+124
+1461
+# t5:
+1+1+1
+3
+# t6:
+98+123+531511+131
+531863
index 6e41837ade3e3eaf1783d3a84df288b6de2845e1..e9778da86dc854f58c84f4016e1727e92fa7f2e5 100644 (file)
@@ -33,26 +33,42 @@ entity parser is
 end entity parser;
 
 architecture beh of parser is
-       type PARSER_STATE is (SIDLE, SREAD_CHAR1, SREAD_CHAR2, SWRITE_CHAR);
+       type PARSER_STATE is (SIDLE, SREAD_NEWNUMBER, SREAD_NEXTBYTE,
+       SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1, SCALC_2, SWRITE_CHAR1, SWRITE_CHAR2, SDONE);
        signal state_int, state_next : PARSER_STATE;
-       signal z_int, z_next : csigned;
+       signal z_int, z_next, strich_int, strich_next, wtmp_int, wtmp_next : csigned;
        signal rbyte_int, rbyte_next : hbyte;
        signal p_write_int, p_write_next : hbyte;
        signal p_rget_int, p_rget_next : std_logic;
        signal p_wtake_int, p_wtake_next : std_logic;
        signal p_finished_int, p_finished_next : std_logic;
+       signal aktop_int, aktop_next : alu_ops;
+       signal opp_int, opp_next : alu_ops;
+       signal opcode_int, opcode_next : alu_ops;
+       signal op1_int, op1_next : csigned;
+       signal op2_int, op2_next : csigned;
+       signal do_calc_int, do_calc_next : std_logic;
 begin
        p_write <= p_write_int;
        p_rget <= p_rget_int;
        p_wtake <= p_wtake_int;
        p_finished <= p_finished_int;
 
+       opcode <= opcode_int;
+       op1 <= op1_int;
+       op2 <= op2_int;
+       do_calc <= do_calc_int;
+
        process(sys_clk, sys_res_n)
        begin
                if sys_res_n = '0' then
                        state_int <= SIDLE;
                        z_int <= (others => '0');
+                       strich_int <= (others => '0');
+                       wtmp_int <= (others => '0');
                        rbyte_int <= (others => '0');
+                       aktop_int <= ALU_NOP;
+                       opp_int <= ALU_NOP;
                        -- out ports
                        p_rw <= '0';
                        p_spalte <= (others => '0');
@@ -60,80 +76,211 @@ begin
                        p_write_int <= (others => '0');
                        p_wtake_int <= '0';
                        p_finished_int <= '0';
-                       opcode <= ALU_NOP;
-                       op1 <= (others => '0');
-                       op2 <= (others => '0');
-                       do_calc <= '0';
+                       opcode_int <= ALU_NOP;
+                       op1_int <= (others => '0');
+                       op2_int <= (others => '0');
+                       do_calc_int <= '0';
                        finished <= '0';
                elsif rising_edge(sys_clk) then
                        -- internal
                        state_int <= state_next;
                        z_int <= z_next;
+                       strich_int <= strich_next;
+                       wtmp_int <= wtmp_next;
                        rbyte_int <= rbyte_next;
+                       aktop_int <= aktop_next;
+                       opp_int <= opp_next;
                        -- out ports
                        p_rget_int <= p_rget_next;
                        p_write_int <= p_write_next;
                        p_wtake_int <= p_wtake_next;
                        p_finished_int <= p_finished_next;
+                       opcode_int <= opcode_next;
+                       op1_int <= op1_next;
+                       op2_int <= op2_next;
+                       do_calc_int <= do_calc_next;
                end if;
        end process;
 
        -- next state
-       process(state_int, do_it, p_rdone, p_wdone, p_read)
+       process(state_int, do_it, p_rdone, p_wdone, p_read, aktop_int, strich_int,
+               strich_next, calc_done, wtmp_int)
        begin
                state_next <= state_int;
 
                case state_int is
                        when SIDLE =>
                                if do_it = '1' then
-                                       state_next <= SREAD_CHAR1;
+                                       state_next <= SREAD_NEWNUMBER;
                                end if;
-                       when SREAD_CHAR1 =>
+                       when SREAD_NEWNUMBER =>
+                               state_next <= SREAD_NEXTBYTE;
+                       when SREAD_NEXTBYTE =>
                                if p_rdone = '1' then
-                                       state_next <= SREAD_CHAR2;
+                                       state_next <= SREAD_CALCNUMBER1;
                                end if;
-                       when SREAD_CHAR2 =>
-                               if p_wdone = '1' then
-                                       state_next <= SWRITE_CHAR;
+                       when SREAD_CALCNUMBER1 =>
+                               state_next <= SREAD_CALCNUMBER2;
+                       when SREAD_CALCNUMBER2 =>
+                               if aktop_int /= ALU_NOP then
+                                       state_next <= SCALC_1;
+                               else
+                                       state_next <= SREAD_NEXTBYTE;
                                end if;
-                       when SWRITE_CHAR =>
-                               if rbyte_int = hbyte(to_unsigned(character'pos(character'val(0)), 8)) then
-                                       if do_it = '0' then
-                                               state_next <= SIDLE;
-                                       end if;
+                       when SCALC_1 =>
+                               if calc_done = '1' then
+                                       state_next <= SCALC_2;
+                               end if;
+                       when SCALC_2 =>
+                               if aktop_int = ALU_DONE then
+                                       state_next <= SWRITE_CHAR1;
                                else
-                                       state_next <= SREAD_CHAR1;
+                                       state_next <= SREAD_NEWNUMBER;
+                               end if;
+                       when SWRITE_CHAR1 =>
+                               if p_wdone = '1' then
+                                       if strich_int < 10 then
+                                               state_next <= SDONE;
+                                       else
+                                               state_next <= SWRITE_CHAR2;
+                                       end if;
+                               end if;
+                       when SWRITE_CHAR2 =>
+                               if p_wdone = '0' then
+                                       state_next <= SWRITE_CHAR1;
+                               end if;
+                       when SDONE =>
+                               if p_wdone = '0' and do_it = '0' then
+                                       state_next <= SIDLE;
                                end if;
                end case;
        end process;
 
-       process(state_int, p_read, p_write_int, z_int, rbyte_int, p_rget_int)
+       -- 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)
+               function hbyte2csigned (x : hbyte) return csigned is
+                       variable y : csigned;
+               begin
+                       case x is
+                               when x"30" => y := to_signed(0, CBITS);
+                               when x"31" => y := to_signed(1, CBITS);
+                               when x"32" => y := to_signed(2, CBITS);
+                               when x"33" => y := to_signed(3, CBITS);
+                               when x"34" => y := to_signed(4, CBITS);
+                               when x"35" => y := to_signed(5, CBITS);
+                               when x"36" => y := to_signed(6, CBITS);
+                               when x"37" => y := to_signed(7, CBITS);
+                               when x"38" => y := to_signed(8, CBITS);
+                               when x"39" => y := to_signed(9, CBITS);
+                               when others => assert(false) report "hbyte2csigned: shouldn't happen";
+                       end case;
+                       return y;
+               end function hbyte2csigned;
+
+               function csigned2hbyte (x : csigned) return hbyte is
+                       variable y : hbyte;
+               begin
+                       case x is
+                               when x"00000000" => y := x"30";
+                               when x"00000001" => y := x"31";
+                               when x"00000002" => y := x"32";
+                               when x"00000003" => y := x"33";
+                               when x"00000004" => y := x"34";
+                               when x"00000005" => y := x"35";
+                               when x"00000006" => y := x"36";
+                               when x"00000007" => y := x"37";
+                               when x"00000008" => y := x"38";
+                               when x"00000009" => y := x"39";
+                               when others => assert(false) report "csigned2hbyte: shouldn't happen";
+                       end case;
+                       return y;
+               end function csigned2hbyte;
+
+               variable multmp : signed(((2*CBITS)-1) downto 0);
+               variable tmp : csigned;
        begin
                -- internal
                z_next <= z_int;
+               strich_next <= strich_int;
+               wtmp_next <= wtmp_int;
                rbyte_next <= rbyte_int;
+               aktop_next <= aktop_int;
+               opp_next <= opp_int;
                -- signals
                p_rget_next <= '0';
                p_write_next <= p_write_int;
                p_wtake_next <= '0';
                p_finished_next <= '0';
+               opcode_next <= opcode_int;
+               op1_next <= op1_int;
+               op2_next <= op2_int;
+               do_calc_next <= '0';
 
                case state_int is
                        when SIDLE =>
+                               strich_next <= (others => '0');
+                               opp_next <= ALU_NOP;
+                       when SREAD_NEWNUMBER =>
                                z_next <= (others => '0');
                                rbyte_next <= (others => '0');
                                p_write_next <= (others => '0');
-                       when SREAD_CHAR1 =>
+                               aktop_next <= ALU_NOP;
+                       when SREAD_NEXTBYTE =>
                                p_rget_next <= '1';
-                               p_write_next <= (others => '0');
-                       when SREAD_CHAR2 =>
-                               rbyte_next <= p_read;
+                       when SREAD_CALCNUMBER1 =>
+                               case p_read is
+                                       -- '+'
+                                       when x"2B" =>
+                                               aktop_next <= ALU_ADD;
+
+                                       -- '\0'
+                                       when x"00" =>
+                                               aktop_next <= ALU_DONE;
+
+                                       when others =>
+                                               -- TODO: check auf overflow
+                                               multmp := (z_int * 10) + hbyte2csigned(p_read);
+                                               z_next <= multmp((CBITS-1) downto 0);
+                               end case;
+                       when SREAD_CALCNUMBER2 =>
+                               null;
+
+                       when SCALC_1 =>
+                               case opp_int is
+                                       when ALU_NOP | ALU_ADD =>
+                                               op1_next <= z_int;
+                                               case aktop_int is
+                                                       when ALU_ADD | ALU_SUB | ALU_NOP | ALU_DONE =>
+                                                               opcode_next <= ALU_ADD;
+                                                               op2_next <= strich_int;
+                                                       when ALU_MUL | ALU_DIV =>
+                                                               opcode_next <= ALU_MUL;
+                                                               op2_next <= strich_int;
+                                                       when others => assert(false) report "SCALC_1/ALU_NOP: not implemented yet";
+                                               end case;
+                                               do_calc_next <= '1';
+                                       when others => assert(false) report "SCALC_1: not implemented yet";
+                               end case;
+                       when SCALC_2 =>
+                               case opp_int is
+                                       when ALU_NOP | ALU_ADD =>
+                                               strich_next <= op3;
+                                       when others => assert (false) report "SCALC_2: not implemented yet";
+                               end case;
+                               opp_next <= aktop_int;
+
+                       when SWRITE_CHAR1 =>
                                p_wtake_next <= '1';
-                               p_write_next <= p_read;
-                       when SWRITE_CHAR =>
-                               if rbyte_int = hbyte(to_unsigned(character'pos(character'val(0)), 8)) then
-                                       p_finished_next <= '1';
-                               end if;
+                               tmp := strich_int mod 10;
+                               p_write_next <= csigned2hbyte(tmp);
+                               wtmp_next <= strich_int / 10;
+                       when SWRITE_CHAR2 =>
+                               strich_next <= wtmp_int;
+
+                       when SDONE =>
+                               p_finished_next <= '1';
                end case;
        end process;
 end architecture beh;