From 27c9670ed41bd1d234c325380433cefd57d2cadc Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Wed, 12 May 2010 01:04:29 +0200 Subject: [PATCH] parser: / und mod in hardware --- src/beh_parser_tb.do | 2 + src/beh_parser_tb.vhd | 14 +++--- src/gen_pkg.vhd | 1 + src/parser.vhd | 102 +++++++++++++++++++++++------------------- 4 files changed, 67 insertions(+), 52 deletions(-) diff --git a/src/beh_parser_tb.do b/src/beh_parser_tb.do index b7e63b6..4f70701 100644 --- a/src/beh_parser_tb.do +++ b/src/beh_parser_tb.do @@ -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 diff --git a/src/beh_parser_tb.vhd b/src/beh_parser_tb.vhd index 61d2544..663e1bd 100644 --- a/src/beh_parser_tb.vhd +++ b/src/beh_parser_tb.vhd @@ -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; diff --git a/src/gen_pkg.vhd b/src/gen_pkg.vhd index 10f1389..0121290 100644 --- a/src/gen_pkg.vhd +++ b/src/gen_pkg.vhd @@ -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); diff --git a/src/parser.vhd b/src/parser.vhd index 74c4661..1d75398 100644 --- a/src/parser.vhd +++ b/src/parser.vhd @@ -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 => -- 2.25.1