📄 textio_body.vhdl
字号:
end set_value; begin -- Initialization. val_neg := false; nbr_dec := 1; exp := 0; exp_neg := false; -- By default, parsing has failed. good := false; -- Iterate over all characters of the string. -- Return immediatly in case of parse error. -- Trim L and call SET_VALUE and return in case of success. for i in l'range loop case cur_state is when leading => case l(i) is when ' ' | NBSP --V93 | ht => null; when '+' => cur_state := sign; when '-' => val_neg := true; cur_state := sign; when '0' to '9' => val := real (char_to_nat (l(i))); cur_state := digits; when others => return; end case; when sign => case l(i) is when '0' to '9' => val := real (char_to_nat (l(i))); cur_state := digits; when others => return; end case; when digits => case l(i) is when '0' to '9' => val := val * 10.0 + real (char_to_nat (l(i))); when '.' => cur_state := decimals; when others => -- A "." (dot) is required in the string. return; end case; when decimals => case l(i) is when '0' to '9' => val := val + real (char_to_nat (l(i))) / (10.0 ** nbr_dec); nbr_dec := nbr_dec + 1; when 'e' | 'E' => -- "nnn.E" is erroneous. if nbr_dec = 1 then return; end if; cur_state := exponent_sign; when others => -- "nnn.XX" is erroneous. if nbr_dec = 1 then return; end if; trim (l, i); set_value; return; end case; when exponent_sign => case l(i) is when '+' => cur_state := exponent_1; when '-' => exp_neg := true; cur_state := exponent_1; when '0' to '9' => exp := char_to_nat (l(i)); cur_state := exponent; when others => -- Error. return; end case; when exponent_1 | exponent => case l(i) is when '0' to '9' => exp := exp * 10 + char_to_nat (l(i)); cur_state := exponent; when others => trim (l, i); set_value; return; end case; end case; end loop; -- End of string. case cur_state is when leading | sign | digits => -- Erroneous. return; when decimals => -- "nnn.XX" is erroneous. if nbr_dec = 1 then return; end if; when exponent_sign => -- Erroneous ("NNN.NNNE") return; when exponent_1 => -- "NNN.NNNE-" return; when exponent => null; end case; deallocate (l); l := new string'(""); set_value; end read; procedure read (l: inout line; value: out real) is variable res : boolean; begin read (l, value, res); assert res = true report "real read failure" severity failure; end read; procedure read (l: inout line; value: out time; good: out boolean) is -- The result. variable res : time; -- UNIT is computed from the unit name, the exponent and the number of -- digits before the dot. UNIT is the weight of the current digit. variable unit : time; -- Number of digits before the dot. variable nbr_digits : integer; -- True if a unit name has been found. Used temporaly to know the status -- at the end of the search loop. variable unit_found : boolean; -- True if the number is negative. variable is_neg : boolean; -- Value of the exponent. variable exp : integer; -- True if the exponent is negative. variable exp_neg : boolean; -- Unit name extracted from the string. variable unit_name : string (1 to 3); -- state is the kind of the previous character parsed. -- LEADING: leading blanks -- SIGN: + or - as the first character of the number. -- DIGITS: digit of the integer part of the number. -- DOT: dot (.) after the integer part and before the decimal part. -- DECIMALS: digit of the decimal part. -- EXPONENT_MARK: e or E. -- EXPONENT_SIGN: + or - just after the exponent mark (E). -- EXPONENT: digit of the exponent. -- UNIT_BLANK: blank after the exponent. -- UNIT_1, UNIT_2, UNIT_3: first, second, third character of the unit. type state_type is (leading, sign, digits, dot, decimals, exponent_mark, exponent_sign, exponent, unit_blank, unit_1, unit_2, unit_3); variable state : state_type; -- Used during the second scan of the string, TRUE is digits is being -- scaned. variable has_digits : boolean; -- Position at the end of the string. variable pos : integer; -- Used to compute POS. variable length : integer; begin -- Initialization. -- Fail by default; therefore, in case of error, a return statement is -- ok. good := false; nbr_digits := 0; is_neg := false; exp := 0; exp_neg := false; res := 0 fs; -- Look for exponent and unit name. -- Parse the string: this loop checks the correctness of the format, and -- must return (GOOD has been set to FALSE) in case of error. -- Set: NBR_DIGITS, IS_NEG, EXP, EXP_NEG. state := leading; for i in l'range loop case l (i) is when ' ' | NBSP --V93 | HT => case state is when leading | unit_blank => null; when sign | dot | exponent_mark | exponent_sign => return; when digits | decimals | exponent => state := unit_blank; when unit_1 | unit_2 => exit; when unit_3 => -- Cannot happen, since an exit is performed at unit_3. assert false report "internal error" severity failure; end case; when '+' | '-' => case state is when leading => if l(i) = '-' then is_neg := true; end if; state := sign; when exponent_mark => if l(i) = '-' then exp_neg := true; end if; state := exponent_sign; when others => return; end case; when '0' to '9' => case state is when exponent_mark | exponent_sign | exponent => exp := exp * 10 + char_to_nat (l (i)); state := exponent; when leading | sign | digits => -- Leading "0" are not significant. if nbr_digits > 0 or l (i) /= '0' then nbr_digits := nbr_digits + 1; end if; state := digits; when decimals => null; when dot => state := decimals; when others => return; end case; when 'a' to 'z' | 'A' to 'Z' => case state is when digits | decimals => -- "E" has exponent mark. if l (i) = 'e' or l(i) = 'E' then state := exponent_mark; else return; end if; when unit_blank => unit_name (1) := to_lower (l(i)); state := unit_1; when unit_1 => unit_name (2) := to_lower (l(i)); state := unit_2; pos := i; when unit_2 => unit_name (3) := to_lower (l(i)); state := unit_3; exit; when others => return; end case; when '.' => case state is when digits => state := decimals; when others => return; end case; when others => return; end case; end loop; -- A unit name (2 or 3 letters) must have been found. -- The string may end anywhere. if state /= unit_2 and state /= unit_3 then return; end if; -- Compute EXP with the sign. if exp_neg then exp := -exp; end if; -- Search the unit name in the list of time names. unit_found := false; for i in time_names'range loop -- The first two characters must match (case insensitive). -- The third character must match if: -- * the unit name is a three characters identifier (ie, not a blank). -- * there is a third character in STR. if time_names (i).name (1) = unit_name (1) and time_names (i).name (2) = unit_name (2) and (time_names (i).name (3) = ' ' or time_names (i).name (3) = unit_name (3)) then unit := time_names (i).val; unit_found := true; -- POS is set to the position of the first invalid character. if time_names (i).name (3) = ' ' then length := 1; else length := 2; end if; if l'left < l'right then pos := pos + length; else pos := pos - length; end if; exit; end if; end loop; if not unit_found then return; end if; -- Compute UNIT, the weight of the first non-significant character. nbr_digits := nbr_digits + exp - 1; if nbr_digits < 0 then unit := unit / 10 ** (-nbr_digits); else unit := unit * 10 ** nbr_digits; end if; -- HAS_DIGITS will be set as soon as a digit is found. -- No error is expected here (this has been checked during the first -- pass). has_digits := false; for i in l'range loop case l (i) is when ' ' | NBSP --V93 | HT => if has_digits then exit; end if; when '+' | '-' => if not has_digits then has_digits := true; else assert false report "internal error" severity failure; return; end if; when '0' to '9' => -- Leading "0" are not significant. if l (i) /= '0' or res /= 0 fs then res := res + char_to_nat (l (i)) * unit; unit := unit / 10; end if; has_digits := true; when 'a' to 'z' | 'A' to 'Z' => if has_digits then exit; else assert false report "internal error" severity failure; return; end if; when '.' => if not has_digits then assert false report "internal error" severity failure; return; end if; when others => assert false report "internal error" severity failure; return; end case; end loop; -- Set VALUE. if is_neg then value := -res; else value := res; end if; good := true; trim (l, pos); return; end read; procedure read (l: inout line; value: out time) is variable res : boolean; begin read (l, value, res); assert res = true report "time read failure" severity failure; end read; procedure read (l: inout line; value: out string; good: out boolean) is constant len : natural := value'length; begin if l'length < len then good := false; return; end if; good := true; if len = 0 then return; end if; if l'left < l'right then value := l (l'left to l'left + len - 1); trim (l, l'left + len); else value := l (l'left downto l'left - len + 1); trim (l, l'left - len); end if; end read; procedure read (l: inout line; value: out string) is variable res : boolean; begin read (l, value, res); assert res = true report "string read failure" severity failure; end read;end textio;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -