X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fparser.vhd;h=616555e21ef154677c5f92fe67c931c963c2f176;hb=b5f4c3b9738dc7a08fac9e1f99057f6b44569588;hp=c622fc40082ad8e909837b30f88ad466e50aa751;hpb=fb5613455df85a807ac6ea674cf82d921e348985;p=hwmod.git diff --git a/src/parser.vhd b/src/parser.vhd index c622fc4..616555e 100644 --- a/src/parser.vhd +++ b/src/parser.vhd @@ -9,8 +9,6 @@ entity parser is sys_clk : in std_logic; sys_res_n : in std_logic; -- History - p_rw : out std_logic; - p_spalte : out hspalte; p_rget : out std_logic; p_rdone : in std_logic; p_read : in hbyte; @@ -18,14 +16,6 @@ entity parser is p_wdone : in std_logic; p_write : out hbyte; p_finished : out std_logic; - -- ALU - opcode : out alu_ops; - op1 : out csigned; - op2 : out csigned; - op3 : in csigned; - do_calc : out std_logic; - calc_done : in std_logic; - calc_error : in std_logic; -- Scanner do_it : in std_logic; finished : out std_logic @@ -35,8 +25,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_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; @@ -45,18 +36,49 @@ architecture beh of parser is 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 finished_int, 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; - 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; + 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; + -- ALU + signal opcode : alu_ops; + signal op1 : csigned; + signal op2 : csigned; + signal op3 : csigned; + signal opM : csigned; + signal do_calc : std_logic; + signal calc_done : std_logic; + signal calc_error : std_logic; begin + instalu : entity work.alu(beh) + port map + ( + sys_clk => sys_clk, + sys_res_n => sys_res_n, + do_calc => do_calc, + calc_done => calc_done, + calc_error => calc_error, + op1 => op1, + op2 => op2, + op3 => op3, + opM => opM, + opcode => opcode + ); + p_write <= p_write_int; p_rget <= p_rget_int; p_wtake <= p_wtake_int; p_finished <= p_finished_int; + finished <= finished_int; opcode <= opcode_int; op1 <= op1_int; @@ -68,39 +90,48 @@ 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'); rbyte_int <= (others => '0'); aktop_int <= ALU_NOP; opp_int <= ALU_NOP; + err_int <= 0; + errc_int <= 71; + errc_tmp_int <= 0; + firstz_int <= true; -- out ports - p_rw <= '0'; - p_spalte <= (others => '0'); p_rget_int <= '0'; p_write_int <= (others => '0'); p_wtake_int <= '0'; p_finished_int <= '0'; + finished_int <= '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; + z_sign_int <= z_sign_next; strich_int <= strich_next; punkt_int <= punkt_next; wtmp_int <= wtmp_next; rbyte_int <= rbyte_next; aktop_int <= aktop_next; opp_int <= opp_next; + err_int <= err_next; + errc_int <= errc_next; + errc_tmp_int <= errc_tmp_next; + firstz_int <= firstz_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; + finished_int <= finished_next; opcode_int <= opcode_next; op1_int <= op1_next; op2_int <= op2_next; @@ -111,7 +142,8 @@ 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, err_int, errc_int, calc_error, + op2_int) begin state_next <= state_int; @@ -131,21 +163,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 @@ -156,7 +198,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 => @@ -168,7 +210,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 => @@ -193,57 +235,89 @@ 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 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; end if; when SERROR1 => if p_wdone = '1' then - -- TODO - if strich_int < 10 then + if errc_int <= 2 then state_next <= SDONE; else - state_next <= SWRITE_CHAR2; + state_next <= SERROR2; end if; end if; - when SWRITE_CHAR2 | SERROR2 => + when SERROR2 => if p_wdone = '0' then - state_next <= SWRITE_CHAR1; + 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, - do_calc_int, wtmp_int, punkt_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) 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; @@ -268,22 +342,36 @@ begin return y; end function csigned2hbyte; + variable multmp : signed(((2*CBITS)-1) downto 0); variable tmp : csigned; + + type errstrings is array (natural range 1 to 3) of hstring; + constant error_str : errstrings := ( + 1 => " > Fehler: Division durch Null " & nul, + 2 => " > Fehler: Syntax " & nul, + 3 => " > Fehler: Over- bzw. Underflow " & nul + ); begin -- internal z_next <= z_int; + z_sign_next <= z_sign_int; strich_next <= strich_int; punkt_next <= punkt_int; wtmp_next <= wtmp_int; rbyte_next <= rbyte_int; aktop_next <= aktop_int; opp_next <= opp_int; + err_next <= err_int; + errc_next <= errc_int; + errc_tmp_next <= errc_tmp_int; + firstz_next <= firstz_int; -- signals p_rget_next <= '0'; p_write_next <= p_write_int; p_wtake_next <= '0'; p_finished_next <= '0'; + finished_next <= '0'; opcode_next <= opcode_int; op1_next <= op1_int; op2_next <= op2_int; @@ -291,6 +379,7 @@ begin goto_calcn1 <= '0'; goto_op1 <= '0'; goto_space3 <= '0'; + goto_sign <= '0'; case state_int is when SIDLE => @@ -299,6 +388,8 @@ begin opp_next <= ALU_NOP; when SREAD_NEWNUMBER => z_next <= (others => '0'); + z_sign_next <= '0'; + firstz_next <= true; rbyte_next <= (others => '0'); p_write_next <= (others => '0'); aktop_next <= ALU_NOP; @@ -308,6 +399,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'; @@ -317,8 +414,12 @@ begin case p_read is -- '+', '-', '*', '/' when x"2B" | x"2D" | x"2A" | x"2F" | x"00" => - goto_op1 <= '1'; - p_rget_next <= '1'; + if firstz_int then + err_next <= 2; + else + goto_op1 <= '1'; + p_rget_next <= '1'; + end if; -- ' ' when x"20" => @@ -326,43 +427,44 @@ 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_CALCNUMBER2 | SREAD_OP2 => + when SREAD_SIGN1 => + z_sign_next <= '1'; + 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" => - -- TODO: sign check beim ersten byte lesen! - 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' - -- TODO: err! - when others => assert(false) report "TODO: ..."; + when others => err_next <= 2; end case; 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 +481,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 +507,14 @@ 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; + 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; when others => assert (false) report "SCALC_2/1: shouldn't happen!"; @@ -415,23 +524,55 @@ 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; - when SERROR1 => - -- TODO + 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 => + 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 => - -- TODO - null; + errc_next <= errc_tmp_int; when SDONE => + err_next <= 0; + errc_next <= 71; p_finished_next <= '1'; + finished_next <= '1'; + end case; + + -- fehlerbehandlung + case state_int is + when SERROR1 | SERROR2 | SDONE => null; + when others => + if calc_error = '1' then + if op2_int = 0 then + err_next <= 1; + else + err_next <= 3; + end if; + end if; end case; end process; end architecture beh;