From: Bernhard Urban Date: Mon, 24 May 2010 13:49:38 +0000 (+0200) Subject: parser: refactor (von drei auf zwei prozess-modell) X-Git-Tag: abgabe~53 X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=hwmod.git;a=commitdiff_plain;h=015d6f47ccc5122822f9409e273ff97ffce1f842 parser: refactor (von drei auf zwei prozess-modell) logic elements: 3029 -> 3002 --- diff --git a/spartan3e/.gitignore b/spartan3e/.gitignore index 9118e9d..58b0ee8 100644 --- a/spartan3e/.gitignore +++ b/spartan3e/.gitignore @@ -27,3 +27,4 @@ generated/ smartpreview.twr xlnx_auto_0_xdb/ *.log +_xmsgs/ diff --git a/src/parser.vhd b/src/parser.vhd index b4b9593..2bf4e95 100644 --- a/src/parser.vhd +++ b/src/parser.vhd @@ -4,8 +4,7 @@ use ieee.numeric_std.all; use work.gen_pkg.all; entity parser is - port - ( + port ( sys_clk : in std_logic; sys_res_n : in std_logic; -- History @@ -23,11 +22,11 @@ entity parser is 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_SIGN1, SREAD_NEXTBYTE, SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1, - SCALC_14, SCALC_15, SCALC_2, SWRITE_CHAR0, SWRITE_CHAR1, SWRITE_CHAR2, - SWRITE_SIGN1, SWRITE_SIGN2, SDONE, SERROR1, SERROR2); + type PARSER_STATE is (SIDLE, SREAD_NEWNUMBER, SREAD_SPACE_GET, + SREAD_SPACE_GET_SIGN, SREAD_SPACE_PROC, SREAD_SPACE_PROC_SIGN, SREAD_OP1, SREAD_OP2, + SREAD_SIGN, SREAD_NEXTBYTE, SREAD_CALCNUMBER1, SREAD_CALCNUMBER2, SCALC_1, + 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; @@ -43,7 +42,6 @@ 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, goto_sign : std_logic; signal z_sign_next, z_sign_int : std_logic; signal firstz_next, firstz_int : boolean; signal err_next, err_int : hstr_int; @@ -140,172 +138,11 @@ begin end process; -- 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_sign, z_sign_int, err_int, errc_int, calc_error, - op2_int) - begin - state_next <= state_int; - - case state_int is - when SIDLE => - if do_it = '1' then - state_next <= SREAD_NEWNUMBER; - end if; - when SREAD_NEWNUMBER => - state_next <= SREAD_SPACE1_2; - when SREAD_SPACE1_2 => - if p_rdone = '1' then - state_next <= SREAD_SPACE2; - end if; - when SREAD_SPACE1_3 => - if p_rdone = '1' then - 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 @ state1"; - end case; - end if; - end if; - when SREAD_SIGN1 => - if p_rdone = '0' then - state_next <= SREAD_NEXTBYTE; - end if; - when SREAD_NEXTBYTE => - if p_rdone = '1' then - state_next <= SREAD_CALCNUMBER1; - end if; - when SREAD_CALCNUMBER1 => - if goto_op1 = '1' then - state_next <= SREAD_OP1; - elsif goto_space3 = '1' then - state_next <= SREAD_SPACE3; - elsif calc_done = '1' then - state_next <= SREAD_CALCNUMBER2; - end if; - when SREAD_OP1 => - state_next <= SREAD_OP2; - when SREAD_OP2 => - if p_rdone = '0' then - if aktop_int /= ALU_NOP then - state_next <= SCALC_1; - end if; - end if; - when SREAD_CALCNUMBER2 => - if p_rdone = '0' and calc_done = '0' then - state_next <= SREAD_NEXTBYTE; - end if; - when SCALC_1 => - if calc_done = '1' then - case opp_int is - -- spezialfall: eine zwischenberechnung wird fuer diese - -- kombination benoetigt - when ALU_MUL | ALU_DIV => - case aktop_int is - when ALU_ADD | ALU_SUB | ALU_DONE => state_next <= SCALC_14; - when others => state_next <= SCALC_2; - end case; - when others => state_next <= SCALC_2; - end case; - end if; - when SCALC_14 => - if calc_done = '0' then - state_next <= SCALC_15; - end if; - when SCALC_15 => - if calc_done = '1' then - state_next <= SCALC_2; - end if; - when SCALC_2 => - 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; - end if; - when SWRITE_CHAR1 => - if p_wdone = '1' then - -- ueberpruefung auf -2147483648 fuer testfall 39 und 40 - -- x"80000000": xst (xilinx) workaround - if strich_int < 10 and strich_int /= x"80000000" then - if z_sign_int = '1' then - state_next <= SWRITE_SIGN1; - else - state_next <= SDONE; - end if; - else - state_next <= SWRITE_CHAR2; - end if; - end if; - when SERROR1 => - if p_wdone = '1' then - if errc_int <= 2 then - state_next <= SDONE; - else - state_next <= SERROR2; - end if; - end if; - when SERROR2 => - if p_wdone = '0' then - state_next <= SERROR1; - end if; - when SWRITE_CHAR2 => - if p_wdone = '0' and calc_done = '0' then - state_next <= SWRITE_CHAR0; - 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; - end if; - end case; - - -- fehlerbehandlung - case state_int is - when SERROR1 | SERROR2 | SDONE => null; - when others => - if err_int > 0 then - state_next <= SERROR1; - end if; - end case; - end process; - - -- 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, opM, - do_calc_int, wtmp_int, punkt_int, z_sign_int, err_int, errc_int, - errc_tmp_int, firstz_int, calc_done, calc_error) + process(do_it, p_rdone, p_wdone, p_read, aktop_int, strich_int, punkt_int, + calc_done, wtmp_int, opp_int, z_sign_int, err_int, errc_int, + calc_error, op2_int, state_int, p_write_int, z_int, rbyte_int, + p_rget_int, opcode_int, op1_int, op3, opM, do_calc_int, + errc_tmp_int, firstz_int) function hbyte2csigned (x : hbyte) return csigned is variable y : csigned; begin @@ -344,7 +181,6 @@ begin return y; end function csigned2hbyte; - variable multmp : signed(((2*CBITS)-1) downto 0); variable tmp : csigned; @@ -355,6 +191,7 @@ begin 3 => " Fehler: Over- bzw. Underflow " & nul ); begin + state_next <= state_int; -- internal z_next <= z_int; z_sign_next <= z_sign_int; @@ -378,16 +215,16 @@ begin op1_next <= op1_int; op2_next <= op2_int; do_calc_next <= '0'; - goto_calcn1 <= '0'; - goto_op1 <= '0'; - goto_space3 <= '0'; - goto_sign <= '0'; case state_int is when SIDLE => strich_next <= (others => '0'); punkt_next <= (0 => '1', others => '0'); opp_next <= ALU_NOP; + if do_it = '1' then + state_next <= SREAD_NEWNUMBER; + end if; + when SREAD_NEWNUMBER => z_next <= (others => '0'); z_sign_next <= '0'; @@ -395,23 +232,65 @@ begin rbyte_next <= (others => '0'); p_write_next <= (others => '0'); aktop_next <= ALU_NOP; - when SREAD_NEXTBYTE | SREAD_SPACE1_2 | SREAD_SPACE1_3 => + state_next <= SREAD_SPACE_GET; + + when SREAD_SPACE_GET => p_rget_next <= '1'; - when SREAD_SPACE2 | SREAD_SPACE3 => + if p_rdone = '1' then + state_next <= SREAD_SPACE_PROC; + end if; + when SREAD_SPACE_GET_SIGN => + p_rget_next <= '1'; + if p_rdone = '1' then + state_next <= SREAD_SPACE_PROC_SIGN; + end if; + when SREAD_SPACE_PROC | SREAD_SPACE_PROC_SIGN => case p_read is - when x"20" => - null; + 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"; + when SREAD_SPACE_PROC => + case state_int is + when SREAD_SPACE_PROC => state_next <= SREAD_SIGN; + when others => assert(false) report "wtf @ state3"; + end case; + + when SREAD_SPACE_PROC_SIGN => + p_rget_next <= '1'; + case state_int is + when SREAD_SPACE_PROC => state_next <= SREAD_NEXTBYTE; + when SREAD_SPACE_PROC_SIGN => state_next <= SREAD_OP1; + when others => assert(false) report "wtf @ state2"; + end case; + + when others => assert(false) report "SREAD_SPACE_PROC/3: shouldn't happen"; end case; when others => - goto_calcn1 <= '1'; p_rget_next <= '1'; + case state_int is + when SREAD_SPACE_PROC => state_next <= SREAD_NEXTBYTE; + when SREAD_SPACE_PROC_SIGN => state_next <= SREAD_OP1; + when others => assert(false) report "wtf @ state2"; + end case; end case; + if p_rdone = '0' then + case state_int is + when SREAD_SPACE_PROC => state_next <= SREAD_SPACE_GET; + when SREAD_SPACE_PROC_SIGN => state_next <= SREAD_SPACE_GET_SIGN; + when others => assert(false) report "wtf @ state1"; + end case; + end if; + when SREAD_SIGN => + z_sign_next <= '1'; + if p_rdone = '0' then + state_next <= SREAD_NEXTBYTE; + end if; + when SREAD_NEXTBYTE => + p_rget_next <= '1'; + if p_rdone = '1' then + state_next <= SREAD_CALCNUMBER1; + end if; when SREAD_CALCNUMBER1 => case p_read is -- '+', '-', '*', '/' @@ -419,13 +298,13 @@ begin if firstz_int then err_next <= 2; else - goto_op1 <= '1'; + state_next <= SREAD_OP1; p_rget_next <= '1'; end if; -- ' ' when x"20" => - goto_space3 <= '1'; + state_next <= SREAD_SPACE_PROC_SIGN; p_rget_next <= '1'; when others => @@ -435,12 +314,15 @@ begin firstz_next <= false; do_calc_next <= '1'; end case; - when SREAD_SIGN1 => - z_sign_next <= '1'; + if calc_done = '1' then + state_next <= SREAD_CALCNUMBER2; + end if; when SREAD_CALCNUMBER2 => z_next <= op3 + hbyte2csigned(p_read); - when SREAD_OP2 => - null; + if p_rdone = '0' and calc_done = '0' then + state_next <= SREAD_NEXTBYTE; + end if; + when SREAD_OP1 => case p_read is when x"2B" => aktop_next <= ALU_ADD; -- '+' @@ -451,7 +333,13 @@ begin when others => err_next <= 2; end case; - + state_next <= SREAD_OP2; + when SREAD_OP2 => + if p_rdone = '0' then + if aktop_int /= ALU_NOP then + state_next <= SCALC_1; + end if; + end if; when SCALC_1 => if z_sign_int = '1' then @@ -498,12 +386,27 @@ begin end case; do_calc_next <= '1'; + if calc_done = '1' then + case opp_int is + -- spezialfall: eine zwischenberechnung wird fuer diese + -- kombination benoetigt + when ALU_MUL | ALU_DIV => + case aktop_int is + when ALU_ADD | ALU_SUB | ALU_DONE => state_next <= SCALC_14; + when others => state_next <= SCALC_2; + end case; + when others => state_next <= SCALC_2; + end case; + end if; when SCALC_14 => -- ueberpruefung kann man sich sparen, da diese ohnehin in -- nextstate gemacht wird. op1_next <= op3; do_calc_next <= '0'; + if calc_done = '0' then + state_next <= SCALC_15; + end if; when SCALC_15 => -- ueberpruefung kann man sich sparen, da diese ohnehin in -- nextstate gemacht wird. @@ -512,6 +415,9 @@ begin punkt_next <= (0 => '1', others => '0'); do_calc_next <= '1'; + if calc_done = '1' then + state_next <= SCALC_2; + end if; when SCALC_2 => case opp_int is when ALU_NOP | ALU_ADD | ALU_SUB | ALU_MUL | ALU_DIV => @@ -535,6 +441,14 @@ begin -- aktuelle rechenoperation fuer naechste 'runde' uebernehmen opp_next <= aktop_int; + 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 => -- fuer testfall 39 und 40 if strich_int = to_signed(-214748364,CBITS) then @@ -546,17 +460,40 @@ begin opcode_next <= ALU_DIV; op2_next <= to_signed(10,CBITS); do_calc_next <= '1'; + + if calc_done = '1' then + state_next <= SWRITE_CHAR1; + end if; when SWRITE_CHAR1 => do_calc_next <= '1'; p_wtake_next <= '1'; tmp := opM; p_write_next <= csigned2hbyte(tmp); wtmp_next <= op3; + + if p_wdone = '1' then + -- ueberpruefung auf -2147483648 fuer testfall 39 und 40 + -- x"80000000": xst (xilinx) workaround + if strich_int < 10 and strich_int /= x"80000000" then + if z_sign_int = '1' then + state_next <= SWRITE_SIGN1; + else + state_next <= SDONE; + end if; + else + state_next <= SWRITE_CHAR2; + end if; + end if; when SWRITE_CHAR2 => strich_next <= wtmp_int; + if p_wdone = '0' and calc_done = '0' then + state_next <= SWRITE_CHAR0; + end if; when SWRITE_SIGN1 => - null; + if p_wdone = '0' then + state_next <= SWRITE_SIGN2; + end if; when SWRITE_SIGN2 => if z_sign_int = '1' then p_wtake_next <= '1'; @@ -565,23 +502,43 @@ begin assert(false) report "SWRITE_SIGN: shouldn't happen!"; end if; + if p_wdone = '1' then + state_next <= SDONE; + end if; + when SERROR1 => - p_wtake_next <= '1'; - p_write_next <= hbyte(to_unsigned (character'pos(error_str(err_int)(errc_int)),8)); - errc_tmp_next <= errc_int - 1; + if p_wdone = '1' then + if errc_int <= 2 then + state_next <= SDONE; + else + state_next <= SERROR2; + end if; + end if; when SERROR2 => - errc_next <= errc_tmp_int; + if p_wdone = '0' then + state_next <= SERROR1; + end if; when SDONE => err_next <= 0; errc_next <= 71; p_finished_next <= '1'; finished_next <= '1'; + + if p_wdone = '0' and do_it = '0' then + state_next <= SIDLE; + end if; end case; -- fehlerbehandlung case state_int is - when SERROR1 | SERROR2 | SDONE => null; + when SERROR1 => + p_wtake_next <= '1'; + p_write_next <= hbyte(to_unsigned (character'pos(error_str(err_int)(errc_int)),8)); + errc_tmp_next <= errc_int - 1; + when SERROR2 => + errc_next <= errc_tmp_int; + when SDONE => null; when others => if calc_error = '1' then if op2_int = 0 then @@ -590,6 +547,10 @@ begin err_next <= 3; end if; end if; + + if err_int > 0 then + state_next <= SERROR1; + end if; end case; end process; end architecture beh;