parser: / und mod in hardware
authorBernhard Urban <lewurm@gmail.com>
Tue, 11 May 2010 23:04:29 +0000 (01:04 +0200)
committerBernhard Urban <lewurm@gmail.com>
Tue, 11 May 2010 23:04:29 +0000 (01:04 +0200)
src/beh_parser_tb.do
src/beh_parser_tb.vhd
src/gen_pkg.vhd
src/parser.vhd

index b7e63b6058d8f0efb05397cdaaa633b298289db0..4f70701dbb57fb6fe59cb13a9b15ca2c38690423 100644 (file)
@@ -16,6 +16,8 @@ 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/opM
+add wave -radix decimal inst/opM
 
 delete wave /beh_parser_tb/inst/z_int
 delete wave /beh_parser_tb/inst/z_next
index 61d25447fed37a482cd15c77ae97f7d64149dc66..663e1bda455d58e5d1c0c500fa1d5168bb199adb 100644 (file)
@@ -16,7 +16,7 @@ architecture sim of beh_parser_tb is
 
        -- alu
        signal opcode : alu_ops;
-       signal op1, op2, op3 : csigned;
+       signal op1, op2, op3, opM : csigned;
        signal do_calc, calc_done, calc_error : std_logic;
 
        --scanner
@@ -44,6 +44,7 @@ begin
                op1 => op1,
                op2 => op2,
                op3 => op3,
+               opM => opM,
                do_calc => do_calc,
                calc_done => calc_done,
                calc_error => calc_error,
@@ -64,6 +65,7 @@ begin
                op1 => op1,
                op2 => op2,
                op3 => op3,
+               opM => opM,
                opcode => opcode
        );
 
@@ -105,11 +107,11 @@ begin
 
                i := 1;
                f_loop : while not endfile(f) loop
-                       realresult := (71 => character'val(0), others => character'val(32));
+                       realresult := (71 => nul, others => ' ');
 
                        f1_loop : while not endfile(f) loop
                                readline (f, l);
-                               input := (others => character'val(0));
+                               input := (others => nul);
                                if (l'length <= 72) then
                                        input(1 to l'length) := l.all;
                                        if (input(1) = '#') then
@@ -125,7 +127,7 @@ begin
 
                        f2_loop : while not endfile(f) loop
                                readline (f, l);
-                               expectedresult := (others => character'val(0));
+                               expectedresult := (others => nul);
                                if (l'length <= 72) then
                                        expectedresult(1 to l'length) := l.all;
                                        if (expectedresult(1) = '#') then
@@ -142,9 +144,9 @@ begin
 
                        -- ergebnis string richtig formatieren
                        hstrtmp := expectedresult;
-                       expectedresult := (71 => character'val(0), others => character'val(32));
+                       expectedresult := (71 => nul, others => ' ');
                        for x in 1 to 70 loop
-                               if hstrtmp(x) /= character'val(0) then
+                               if hstrtmp(x) /= nul then
                                        expectedresult((70-y) + x) := hstrtmp(x);
                                end if;
                        end loop;
index 10f1389d3ec57bd05794adeca381271eeb1c44cb..0121290ea83713e69ca9dcf0598ed72ec171e775 100644 (file)
@@ -21,6 +21,7 @@ package gen_pkg is
        subtype hzeile is std_logic_vector(4 downto 0);
        subtype hbyte is std_logic_vector(7 downto 0);
        subtype hstring is string(1 to 71);
+       subtype hstr_int is integer range 0 to 72;
 
        function find_msb(a : csigned) return divinteger;
        procedure icwait(signal clk_i : IN std_logic; cycles: natural);
index 74c4661cd9f6ec04ab2e1bd67387f97273e10075..1d75398bfc87454dbc5694abba14d4844d40722d 100644 (file)
@@ -23,6 +23,7 @@ entity parser is
                op1 : out csigned;
                op2 : out csigned;
                op3 : in csigned;
+               opM : in csigned;
                do_calc : out std_logic;
                calc_done : in std_logic;
                calc_error : in std_logic;
@@ -36,8 +37,8 @@ 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_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);
+       SCALC_14, SCALC_15, SCALC_2, SWRITE_CHAR0, 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;
@@ -54,10 +55,10 @@ architecture beh of parser is
        signal do_calc_int, do_calc_next : std_logic;
        signal goto_calcn1, goto_op1, goto_space3, goto_sign : std_logic;
        signal z_sign_next, z_sign_int : std_logic;
-       signal err_next, err_int : natural;
-       signal errc_next, errc_int : natural;
-       signal errc_tmp_next, errc_tmp_int : natural;
        signal firstz_next, firstz_int : boolean;
+       signal err_next, err_int : hstr_int;
+       signal errc_next, errc_int : hstr_int;
+       signal errc_tmp_next, errc_tmp_int : hstr_int;
 begin
        p_write <= p_write_int;
        p_rget <= p_rget_int;
@@ -183,7 +184,7 @@ begin
                                        state_next <= SREAD_OP1;
                                elsif goto_space3 = '1' then
                                        state_next <= SREAD_SPACE3;
-                               else
+                               elsif calc_done = '1' then
                                        state_next <= SREAD_CALCNUMBER2;
                                end if;
                        when SREAD_OP1 =>
@@ -195,7 +196,7 @@ begin
                                        end if;
                                end if;
                        when SREAD_CALCNUMBER2 =>
-                               if p_rdone = '0' then
+                               if p_rdone = '0' and calc_done = '0' then
                                        state_next <= SREAD_NEXTBYTE;
                                end if;
                        when SCALC_1 =>
@@ -220,10 +221,16 @@ begin
                                        state_next <= SCALC_2;
                                end if;
                        when SCALC_2 =>
-                               if aktop_int = ALU_DONE then
+                               if calc_done = '0' then
+                                       if aktop_int = ALU_DONE then
+                                               state_next <= SWRITE_CHAR2;
+                                       else
+                                               state_next <= SREAD_NEWNUMBER;
+                                       end if;
+                               end if;
+                       when SWRITE_CHAR0 =>
+                               if calc_done = '1' then
                                        state_next <= SWRITE_CHAR1;
-                               else
-                                       state_next <= SREAD_NEWNUMBER;
                                end if;
                        when SWRITE_CHAR1 =>
                                if p_wdone = '1' then
@@ -250,8 +257,8 @@ begin
                                        state_next <= SERROR1;
                                end if;
                        when SWRITE_CHAR2 =>
-                               if p_wdone = '0' then
-                                       state_next <= SWRITE_CHAR1;
+                               if p_wdone = '0' and calc_done = '0' then
+                                       state_next <= SWRITE_CHAR0;
                                end if;
                        when SWRITE_SIGN1 =>
                                if p_wdone = '0' then
@@ -280,23 +287,23 @@ 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,
+               strich_int, aktop_int, opp_int, opcode_int, op1_int, op2_int, op3, opM,
                do_calc_int, wtmp_int, punkt_int, z_sign_int, err_int, errc_int,
                errc_tmp_int, firstz_int, calc_done, calc_error)
                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 x"30" => y := x"00000000";
+                               when x"31" => y := x"00000001";
+                               when x"32" => y := x"00000002";
+                               when x"33" => y := x"00000003";
+                               when x"34" => y := x"00000004";
+                               when x"35" => y := x"00000005";
+                               when x"36" => y := x"00000006";
+                               when x"37" => y := x"00000007";
+                               when x"38" => y := x"00000008";
+                               when x"39" => y := x"00000009";
                                when others => assert(false) report "hbyte2csigned: shouldn't happen";
                        end case;
                        return y;
@@ -326,11 +333,10 @@ begin
                variable tmp : csigned;
 
                type errstrings is array (natural range 1 to 3) of hstring;
-               variable error_str : errstrings := (
-                       --1 => (71 => character'val(0), 50 to 70 => "    Division durch 0", others => character'val(20)),
-                       1 => "                                                   Division durch Null ",
-                       2 => "                                                                Syntax ",
-                       3 => "                                                  Over- bzw. Underflow "
+               constant error_str : errstrings := (
+                       1 => "                                                   Division durch Null" & nul,
+                       2 => "                                                                Syntax" & nul,
+                       3 => "                                                  Over- bzw. Underflow" & nul
                );
        begin
                -- internal
@@ -406,27 +412,25 @@ begin
                                                p_rget_next <= '1';
 
                                        when others =>
-                                               -- TODO: check auf overflow
-                                               multmp := (z_int * 10) + hbyte2csigned(p_read);
-                                               z_next <= multmp((CBITS-1) downto 0);
+                                               op1_next <= z_int;
+                                               opcode_next <= ALU_MUL;
+                                               op2_next <= to_signed(10,CBITS);
                                                firstz_next <= false;
+                                               do_calc_next <= '1';
                                end case;
                        when SREAD_SIGN1 =>
                                z_sign_next <= '1';
-                       when SREAD_CALCNUMBER2 | SREAD_OP2 =>
+                       when SREAD_CALCNUMBER2 =>
+                               z_next <= op3 + hbyte2csigned(p_read);
+                       when SREAD_OP2 =>
                                null;
                        when SREAD_OP1 =>
                                case p_read is
-                                       -- '+'
-                                       when x"2B" => aktop_next <= ALU_ADD;
-                                       -- '-'
-                                       when x"2D" => aktop_next <= ALU_SUB;
-                                       -- '*'
-                                       when x"2A" => aktop_next <= ALU_MUL;
-                                       -- '/'
-                                       when x"2F" => aktop_next <= ALU_DIV;
-                                       -- '\0'
-                                       when x"00" => aktop_next <= ALU_DONE;
+                                       when x"2B" => aktop_next <= ALU_ADD; -- '+'
+                                       when x"2D" => aktop_next <= ALU_SUB; -- '-'
+                                       when x"2A" => aktop_next <= ALU_MUL; -- '*'
+                                       when x"2F" => aktop_next <= ALU_DIV; -- '/'
+                                       when x"00" => aktop_next <= ALU_DONE; -- '\0'
 
                                        when others => err_next <= 2;
                                end case;
@@ -490,9 +494,11 @@ begin
                                                        when ALU_ADD | ALU_SUB | ALU_DONE =>
                                                                if aktop_int = ALU_DONE and op3 < 0 then
                                                                        strich_next <= (not op3) + 1;
+                                                                       wtmp_next <= (not op3) + 1;
                                                                        z_sign_next <= '1';
                                                                else
                                                                        strich_next <= op3;
+                                                                       wtmp_next <= op3;
                                                                end if;
                                                        when ALU_MUL | ALU_DIV =>
                                                                punkt_next <= op3;
@@ -503,11 +509,17 @@ begin
                                -- aktuelle rechenoperation fuer naechste 'runde' uebernehmen
                                opp_next <= aktop_int;
 
+                       when SWRITE_CHAR0 =>
+                               op1_next <= strich_int;
+                               opcode_next <= ALU_DIV;
+                               op2_next <= to_signed(10,CBITS);
+                               do_calc_next <= '1';
                        when SWRITE_CHAR1 =>
+                               do_calc_next <= '1';
                                p_wtake_next <= '1';
-                               tmp := strich_int mod 10;
+                               tmp := opM;
                                p_write_next <= csigned2hbyte(tmp);
-                               wtmp_next <= strich_int / 10;
+                               wtmp_next <= op3;
                        when SWRITE_CHAR2 =>
                                strich_next <= wtmp_int;
 
@@ -523,8 +535,6 @@ begin
 
                        when SERROR1 =>
                                p_wtake_next <= '1';
-                               -- workaround
-                               error_str(err_int)(71) := character'val(0);
                                p_write_next <= hbyte(to_unsigned (character'pos(error_str(err_int)(errc_int)),8));
                                errc_tmp_next <= errc_int - 1;
                        when SERROR2 =>