1-- -------------------------------------------------------------------- 2-- "float_pkg" package contains functions for floating point math. 3-- Please see the documentation for the floating point package. 4-- This package should be compiled into "ieee_proposed" and used as follows: 5-- use ieee.std_logic_1164.all; 6-- use ieee.numeric_std.all; 7-- use ieee_proposed.fixed_float_types.all; 8-- use ieee_proposed.fixed_pkg.all; 9-- use ieee_proposed.float_pkg.all; 10-- 11-- This verison is designed to work with the VHDL-93 compilers. Please 12-- note the "%%%" comments. These are where we diverge from the 13-- VHDL-200X LRM. 14-- 15-- -------------------------------------------------------------------- 16-- Version : $Revision: 1.1 $ 17-- Date : $Date: 2012/03/09 20:36:50 $ 18-- -------------------------------------------------------------------- 19 20use STD.TEXTIO.all; 21library IEEE; 22use IEEE.STD_LOGIC_1164.all; 23use IEEE.NUMERIC_STD.all; 24use work.fixed_float_types.all; 25use work.fixed_pkg.all; 26--use ieee.fixed_pkg.all; 27 28package float_pkg is 29-- generic ( 30 -- Defaults for sizing routines, when you do a "to_float" this will be 31 -- the default size. Example float32 would be 8 and 23 (8 downto -23) 32 constant float_exponent_width : NATURAL := 8; 33 constant float_fraction_width : NATURAL := 23; 34 -- Rounding algorithm, "round_nearest" is default, other valid values 35 -- are "round_zero" (truncation), "round_inf" (round up), and 36 -- "round_neginf" (round down) 37 constant float_round_style : round_type := round_nearest; 38 -- Denormal numbers (very small numbers near zero) true or false 39 constant float_denormalize : BOOLEAN := true; 40 -- Turns on NAN processing (invalid numbers and overflow) true of false 41 constant float_check_error : BOOLEAN := true; 42 -- Guard bits are added to the bottom of every operation for rounding. 43 -- any natural number (including 0) are valid. 44 constant float_guard_bits : NATURAL := 3; 45 -- If TRUE, then turn off warnings on "X" propagation 46 constant no_warning : BOOLEAN := (false 47 ); 48 49 -- Author David Bishop (dbishop@vhdl.org) 50 51 -- Note that the size of the vector is not defined here, but in 52 -- the package which calls this one. 53 type UNRESOLVED_float is array (INTEGER range <>) of STD_ULOGIC; -- main type 54 subtype U_float is UNRESOLVED_float; 55 56 subtype float is UNRESOLVED_float; 57 ----------------------------------------------------------------------------- 58 -- Use the float type to define your own floating point numbers. 59 -- There must be a negative index or the packages will error out. 60 -- Minimum supported is "subtype float7 is float (3 downto -3);" 61 -- "subtype float16 is float (6 downto -9);" is probably the smallest 62 -- practical one to use. 63 ----------------------------------------------------------------------------- 64 65 -- IEEE 754 single precision 66 subtype UNRESOLVED_float32 is UNRESOLVED_float (8 downto -23); 67 alias U_float32 is UNRESOLVED_float32; 68 subtype float32 is float (8 downto -23); 69 ----------------------------------------------------------------------------- 70 -- IEEE-754 single precision floating point. This is a "float" 71 -- in C, and a FLOAT in Fortran. The exponent is 8 bits wide, and 72 -- the fraction is 23 bits wide. This format can hold roughly 7 decimal 73 -- digits. Infinity is 2**127 = 1.7E38 in this number system. 74 -- The bit representation is as follows: 75 -- 1 09876543 21098765432109876543210 76 -- 8 76543210 12345678901234567890123 77 -- 0 00000000 00000000000000000000000 78 -- 8 7 0 -1 -23 79 -- +/- exp. fraction 80 ----------------------------------------------------------------------------- 81 82 -- IEEE 754 double precision 83 subtype UNRESOLVED_float64 is UNRESOLVED_float (11 downto -52); 84 alias U_float64 is UNRESOLVED_float64; 85 subtype float64 is float (11 downto -52); 86 ----------------------------------------------------------------------------- 87 -- IEEE-754 double precision floating point. This is a "double float" 88 -- in C, and a FLOAT*8 in Fortran. The exponent is 11 bits wide, and 89 -- the fraction is 52 bits wide. This format can hold roughly 15 decimal 90 -- digits. Infinity is 2**2047 in this number system. 91 -- The bit representation is as follows: 92 -- 3 21098765432 1098765432109876543210987654321098765432109876543210 93 -- 1 09876543210 1234567890123456789012345678901234567890123456789012 94 -- S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 95 -- 11 10 0 -1 -52 96 -- +/- exponent fraction 97 ----------------------------------------------------------------------------- 98 99 -- IEEE 854 & C extended precision 100 subtype UNRESOLVED_float128 is UNRESOLVED_float (15 downto -112); 101 alias U_float128 is UNRESOLVED_float128; 102 subtype float128 is float (15 downto -112); 103 ----------------------------------------------------------------------------- 104 -- The 128 bit floating point number is "long double" in C (on 105 -- some systems this is a 70 bit floating point number) and FLOAT*32 106 -- in Fortran. The exponent is 15 bits wide and the fraction is 112 107 -- bits wide. This number can handle approximately 33 decimal digits. 108 -- Infinity is 2**32,767 in this number system. 109 ----------------------------------------------------------------------------- 110 111 -- purpose: Checks for a valid floating point number 112 type valid_fpstate is (nan, -- Signaling NaN (C FP_NAN) 113 quiet_nan, -- Quiet NaN (C FP_NAN) 114 neg_inf, -- Negative infinity (C FP_INFINITE) 115 neg_normal, -- negative normalized nonzero 116 neg_denormal, -- negative denormalized (FP_SUBNORMAL) 117 neg_zero, -- -0 (C FP_ZERO) 118 pos_zero, -- +0 (C FP_ZERO) 119 pos_denormal, -- Positive denormalized (FP_SUBNORMAL) 120 pos_normal, -- positive normalized nonzero 121 pos_inf, -- positive infinity 122 isx); -- at least one input is unknown 123 124 -- This deferred constant will tell you if the package body is synthesizable 125 -- or implemented as real numbers. 126 constant fphdlsynth_or_real : BOOLEAN; -- deferred constant 127 128 -- Returns the class which X falls into 129 function Classfp ( 130 x : UNRESOLVED_float; -- floating point input 131 check_error : BOOLEAN := float_check_error) -- check for errors 132 return valid_fpstate; 133 134 -- Arithmetic functions, these operators do not require parameters. 135 function "abs" (arg : UNRESOLVED_float) return UNRESOLVED_float; 136 function "-" (arg : UNRESOLVED_float) return UNRESOLVED_float; 137 138 -- These allows the base math functions to use the default values 139 -- of their parameters. Thus they do full IEEE floating point. 140 141 function "+" (l, r : UNRESOLVED_float) return UNRESOLVED_float; 142 function "-" (l, r : UNRESOLVED_float) return UNRESOLVED_float; 143 function "*" (l, r : UNRESOLVED_float) return UNRESOLVED_float; 144 function "/" (l, r : UNRESOLVED_float) return UNRESOLVED_float; 145 function "rem" (l, r : UNRESOLVED_float) return UNRESOLVED_float; 146 function "mod" (l, r : UNRESOLVED_float) return UNRESOLVED_float; 147 148 -- Basic parameter list 149 -- round_style - Selects the rounding algorithm to use 150 -- guard - extra bits added to the end if the operation to add precision 151 -- check_error - When "false" turns off NAN and overflow checks 152 -- denormalize - When "false" turns off denormal number processing 153 154 function add ( 155 l, r : UNRESOLVED_float; -- floating point input 156 constant round_style : round_type := float_round_style; -- rounding option 157 constant guard : NATURAL := float_guard_bits; -- number of guard bits 158 constant check_error : BOOLEAN := float_check_error; -- check for errors 159 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 160 return UNRESOLVED_float; 161 162 function subtract ( 163 l, r : UNRESOLVED_float; -- floating point input 164 constant round_style : round_type := float_round_style; -- rounding option 165 constant guard : NATURAL := float_guard_bits; -- number of guard bits 166 constant check_error : BOOLEAN := float_check_error; -- check for errors 167 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 168 return UNRESOLVED_float; 169 170 function multiply ( 171 l, r : UNRESOLVED_float; -- floating point input 172 constant round_style : round_type := float_round_style; -- rounding option 173 constant guard : NATURAL := float_guard_bits; -- number of guard bits 174 constant check_error : BOOLEAN := float_check_error; -- check for errors 175 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 176 return UNRESOLVED_float; 177 178 function divide ( 179 l, r : UNRESOLVED_float; -- floating point input 180 constant round_style : round_type := float_round_style; -- rounding option 181 constant guard : NATURAL := float_guard_bits; -- number of guard bits 182 constant check_error : BOOLEAN := float_check_error; -- check for errors 183 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 184 return UNRESOLVED_float; 185 186 function remainder ( 187 l, r : UNRESOLVED_float; -- floating point input 188 constant round_style : round_type := float_round_style; -- rounding option 189 constant guard : NATURAL := float_guard_bits; -- number of guard bits 190 constant check_error : BOOLEAN := float_check_error; -- check for errors 191 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 192 return UNRESOLVED_float; 193 194 function modulo ( 195 l, r : UNRESOLVED_float; -- floating point input 196 constant round_style : round_type := float_round_style; -- rounding option 197 constant guard : NATURAL := float_guard_bits; -- number of guard bits 198 constant check_error : BOOLEAN := float_check_error; -- check for errors 199 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 200 return UNRESOLVED_float; 201 202 -- reciprocal 203 function reciprocal ( 204 arg : UNRESOLVED_float; -- floating point input 205 constant round_style : round_type := float_round_style; -- rounding option 206 constant guard : NATURAL := float_guard_bits; -- number of guard bits 207 constant check_error : BOOLEAN := float_check_error; -- check for errors 208 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 209 return UNRESOLVED_float; 210 211 function dividebyp2 ( 212 l, r : UNRESOLVED_float; -- floating point input 213 constant round_style : round_type := float_round_style; -- rounding option 214 constant guard : NATURAL := float_guard_bits; -- number of guard bits 215 constant check_error : BOOLEAN := float_check_error; -- check for errors 216 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 217 return UNRESOLVED_float; 218 219 -- Multiply accumulate result = l*r + c 220 function mac ( 221 l, r, c : UNRESOLVED_float; -- floating point input 222 constant round_style : round_type := float_round_style; -- rounding option 223 constant guard : NATURAL := float_guard_bits; -- number of guard bits 224 constant check_error : BOOLEAN := float_check_error; -- check for errors 225 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 226 return UNRESOLVED_float; 227 228 -- Square root (all 754 based implementations need this) 229 function sqrt ( 230 arg : UNRESOLVED_float; -- floating point input 231 constant round_style : round_type := float_round_style; 232 constant guard : NATURAL := float_guard_bits; 233 constant check_error : BOOLEAN := float_check_error; 234 constant denormalize : BOOLEAN := float_denormalize) 235 return UNRESOLVED_float; 236 237 function Is_Negative (arg : UNRESOLVED_float) return BOOLEAN; 238 239 ----------------------------------------------------------------------------- 240 -- compare functions 241 -- =, /=, >=, <=, <, >, maximum, minimum 242 243 function eq ( -- equal = 244 l, r : UNRESOLVED_float; -- floating point input 245 constant check_error : BOOLEAN := float_check_error; 246 constant denormalize : BOOLEAN := float_denormalize) 247 return BOOLEAN; 248 249 function ne ( -- not equal /= 250 l, r : UNRESOLVED_float; -- floating point input 251 constant check_error : BOOLEAN := float_check_error; 252 constant denormalize : BOOLEAN := float_denormalize) 253 return BOOLEAN; 254 255 function lt ( -- less than < 256 l, r : UNRESOLVED_float; -- floating point input 257 constant check_error : BOOLEAN := float_check_error; 258 constant denormalize : BOOLEAN := float_denormalize) 259 return BOOLEAN; 260 261 function gt ( -- greater than > 262 l, r : UNRESOLVED_float; -- floating point input 263 constant check_error : BOOLEAN := float_check_error; 264 constant denormalize : BOOLEAN := float_denormalize) 265 return BOOLEAN; 266 267 function le ( -- less than or equal to <= 268 l, r : UNRESOLVED_float; -- floating point input 269 constant check_error : BOOLEAN := float_check_error; 270 constant denormalize : BOOLEAN := float_denormalize) 271 return BOOLEAN; 272 273 function ge ( -- greater than or equal to >= 274 l, r : UNRESOLVED_float; -- floating point input 275 constant check_error : BOOLEAN := float_check_error; 276 constant denormalize : BOOLEAN := float_denormalize) 277 return BOOLEAN; 278 279 -- Need to overload the default versions of these 280 function "=" (l, r : UNRESOLVED_float) return BOOLEAN; 281 function "/=" (l, r : UNRESOLVED_float) return BOOLEAN; 282 function ">=" (l, r : UNRESOLVED_float) return BOOLEAN; 283 function "<=" (l, r : UNRESOLVED_float) return BOOLEAN; 284 function ">" (l, r : UNRESOLVED_float) return BOOLEAN; 285 function "<" (l, r : UNRESOLVED_float) return BOOLEAN; 286 287 function \?=\ (l, r : UNRESOLVED_float) return STD_ULOGIC; 288 function \?/=\ (l, r : UNRESOLVED_float) return STD_ULOGIC; 289 function \?>\ (l, r : UNRESOLVED_float) return STD_ULOGIC; 290 function \?>=\ (l, r : UNRESOLVED_float) return STD_ULOGIC; 291 function \?<\ (l, r : UNRESOLVED_float) return STD_ULOGIC; 292 function \?<=\ (l, r : UNRESOLVED_float) return STD_ULOGIC; 293 294 function std_match (l, r : UNRESOLVED_float) return BOOLEAN; 295 function find_rightmost (arg : UNRESOLVED_float; y : STD_ULOGIC) 296 return INTEGER; 297 function find_leftmost (arg : UNRESOLVED_float; y : STD_ULOGIC) 298 return INTEGER; 299 function maximum (l, r : UNRESOLVED_float) return UNRESOLVED_float; 300 function minimum (l, r : UNRESOLVED_float) return UNRESOLVED_float; 301 302 -- conversion functions 303 -- Converts one floating point number into another. 304 305 function resize ( 306 arg : UNRESOLVED_float; -- Floating point input 307 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 308 constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction 309 constant round_style : round_type := float_round_style; -- rounding option 310 constant check_error : BOOLEAN := float_check_error; 311 constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP 312 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 313 return UNRESOLVED_float; 314 315 function resize ( 316 arg : UNRESOLVED_float; -- Floating point input 317 size_res : UNRESOLVED_float; 318 constant round_style : round_type := float_round_style; -- rounding option 319 constant check_error : BOOLEAN := float_check_error; 320 constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP 321 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 322 return UNRESOLVED_float; 323 324 function to_float32 ( 325 arg : UNRESOLVED_float; 326 constant round_style : round_type := float_round_style; -- rounding option 327 constant check_error : BOOLEAN := float_check_error; 328 constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP 329 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 330 return UNRESOLVED_float32; 331 332 function to_float64 ( 333 arg : UNRESOLVED_float; 334 constant round_style : round_type := float_round_style; -- rounding option 335 constant check_error : BOOLEAN := float_check_error; 336 constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP 337 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 338 return UNRESOLVED_float64; 339 340 function to_float128 ( 341 arg : UNRESOLVED_float; 342 constant round_style : round_type := float_round_style; -- rounding option 343 constant check_error : BOOLEAN := float_check_error; 344 constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP 345 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 346 return UNRESOLVED_float128; 347 348 -- Converts an fp into an SLV (needed for synthesis) 349 function to_slv (arg : UNRESOLVED_float) return STD_LOGIC_VECTOR; 350 alias to_StdLogicVector is to_slv [UNRESOLVED_float return STD_LOGIC_VECTOR]; 351 alias to_Std_Logic_Vector is to_slv [UNRESOLVED_float return STD_LOGIC_VECTOR]; 352 353 -- Converts an fp into an std_ulogic_vector (sulv) 354 function to_sulv (arg : UNRESOLVED_float) return STD_ULOGIC_VECTOR; 355 alias to_StdULogicVector is to_sulv [UNRESOLVED_float return STD_ULOGIC_VECTOR]; 356 alias to_Std_ULogic_Vector is to_sulv [UNRESOLVED_float return STD_ULOGIC_VECTOR]; 357 358 -- std_ulogic_vector to float 359 function to_float ( 360 arg : STD_ULOGIC_VECTOR; 361 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 362 constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction 363 return UNRESOLVED_float; 364 365 -- Integer to float 366 function to_float ( 367 arg : INTEGER; 368 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 369 constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction 370 constant round_style : round_type := float_round_style) -- rounding option 371 return UNRESOLVED_float; 372 373 -- real to float 374 function to_float ( 375 arg : REAL; 376 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 377 constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction 378 constant round_style : round_type := float_round_style; -- rounding option 379 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 380 return UNRESOLVED_float; 381 382 -- unsigned to float 383 function to_float ( 384 arg : UNSIGNED; 385 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 386 constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction 387 constant round_style : round_type := float_round_style) -- rounding option 388 return UNRESOLVED_float; 389 390 -- signed to float 391 function to_float ( 392 arg : SIGNED; 393 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 394 constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction 395 constant round_style : round_type := float_round_style) -- rounding option 396 return UNRESOLVED_float; 397 398 -- unsigned fixed point to float 399 function to_float ( 400 arg : UNRESOLVED_ufixed; -- unsigned fixed point input 401 constant exponent_width : NATURAL := float_exponent_width; -- width of exponent 402 constant fraction_width : NATURAL := float_fraction_width; -- width of fraction 403 constant round_style : round_type := float_round_style; -- rounding 404 constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions 405 return UNRESOLVED_float; 406 407 -- signed fixed point to float 408 function to_float ( 409 arg : UNRESOLVED_sfixed; 410 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 411 constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction 412 constant round_style : round_type := float_round_style; -- rounding 413 constant denormalize : BOOLEAN := float_denormalize) -- rounding option 414 return UNRESOLVED_float; 415 416 -- size_res functions 417 -- Integer to float 418 function to_float ( 419 arg : INTEGER; 420 size_res : UNRESOLVED_float; 421 constant round_style : round_type := float_round_style) -- rounding option 422 return UNRESOLVED_float; 423 424 -- real to float 425 function to_float ( 426 arg : REAL; 427 size_res : UNRESOLVED_float; 428 constant round_style : round_type := float_round_style; -- rounding option 429 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 430 return UNRESOLVED_float; 431 432 -- unsigned to float 433 function to_float ( 434 arg : UNSIGNED; 435 size_res : UNRESOLVED_float; 436 constant round_style : round_type := float_round_style) -- rounding option 437 return UNRESOLVED_float; 438 439 -- signed to float 440 function to_float ( 441 arg : SIGNED; 442 size_res : UNRESOLVED_float; 443 constant round_style : round_type := float_round_style) -- rounding option 444 return UNRESOLVED_float; 445 446 -- sulv to float 447 function to_float ( 448 arg : STD_ULOGIC_VECTOR; 449 size_res : UNRESOLVED_float) 450 return UNRESOLVED_float; 451 452 -- unsigned fixed point to float 453 function to_float ( 454 arg : UNRESOLVED_ufixed; -- unsigned fixed point input 455 size_res : UNRESOLVED_float; 456 constant round_style : round_type := float_round_style; -- rounding 457 constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions 458 return UNRESOLVED_float; 459 460 -- signed fixed point to float 461 function to_float ( 462 arg : UNRESOLVED_sfixed; 463 size_res : UNRESOLVED_float; 464 constant round_style : round_type := float_round_style; -- rounding 465 constant denormalize : BOOLEAN := float_denormalize) -- rounding option 466 return UNRESOLVED_float; 467 468 -- float to unsigned 469 function to_unsigned ( 470 arg : UNRESOLVED_float; -- floating point input 471 constant size : NATURAL; -- length of output 472 constant round_style : round_type := float_round_style; -- rounding option 473 constant check_error : BOOLEAN := float_check_error) -- check for errors 474 return UNSIGNED; 475 476 -- float to signed 477 function to_signed ( 478 arg : UNRESOLVED_float; -- floating point input 479 constant size : NATURAL; -- length of output 480 constant round_style : round_type := float_round_style; -- rounding option 481 constant check_error : BOOLEAN := float_check_error) -- check for errors 482 return SIGNED; 483 484 -- purpose: Converts a float to unsigned fixed point 485 function to_ufixed ( 486 arg : UNRESOLVED_float; -- fp input 487 constant left_index : INTEGER; -- integer part 488 constant right_index : INTEGER; -- fraction part 489 constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate 490 constant round_style : fixed_round_style_type := fixed_round_style; -- rounding 491 constant check_error : BOOLEAN := float_check_error; -- check for errors 492 constant denormalize : BOOLEAN := float_denormalize) 493 return UNRESOLVED_ufixed; 494 495 -- float to signed fixed point 496 function to_sfixed ( 497 arg : UNRESOLVED_float; -- fp input 498 constant left_index : INTEGER; -- integer part 499 constant right_index : INTEGER; -- fraction part 500 constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate 501 constant round_style : fixed_round_style_type := fixed_round_style; -- rounding 502 constant check_error : BOOLEAN := float_check_error; -- check for errors 503 constant denormalize : BOOLEAN := float_denormalize) 504 return UNRESOLVED_sfixed; 505 506 -- size_res versions 507 -- float to unsigned 508 function to_unsigned ( 509 arg : UNRESOLVED_float; -- floating point input 510 size_res : UNSIGNED; 511 constant round_style : round_type := float_round_style; -- rounding option 512 constant check_error : BOOLEAN := float_check_error) -- check for errors 513 return UNSIGNED; 514 515 -- float to signed 516 function to_signed ( 517 arg : UNRESOLVED_float; -- floating point input 518 size_res : SIGNED; 519 constant round_style : round_type := float_round_style; -- rounding option 520 constant check_error : BOOLEAN := float_check_error) -- check for errors 521 return SIGNED; 522 523 -- purpose: Converts a float to unsigned fixed point 524 function to_ufixed ( 525 arg : UNRESOLVED_float; -- fp input 526 size_res : UNRESOLVED_ufixed; 527 constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate 528 constant round_style : fixed_round_style_type := fixed_round_style; -- rounding 529 constant check_error : BOOLEAN := float_check_error; -- check for errors 530 constant denormalize : BOOLEAN := float_denormalize) 531 return UNRESOLVED_ufixed; 532 533 -- float to signed fixed point 534 function to_sfixed ( 535 arg : UNRESOLVED_float; -- fp input 536 size_res : UNRESOLVED_sfixed; 537 constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate 538 constant round_style : fixed_round_style_type := fixed_round_style; -- rounding 539 constant check_error : BOOLEAN := float_check_error; -- check for errors 540 constant denormalize : BOOLEAN := float_denormalize) 541 return UNRESOLVED_sfixed; 542 543 -- float to real 544 function to_real ( 545 arg : UNRESOLVED_float; -- floating point input 546 constant check_error : BOOLEAN := float_check_error; -- check for errors 547 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 548 return REAL; 549 550 -- float to integer 551 function to_integer ( 552 arg : UNRESOLVED_float; -- floating point input 553 constant round_style : round_type := float_round_style; -- rounding option 554 constant check_error : BOOLEAN := float_check_error) -- check for errors 555 return INTEGER; 556 557 -- For Verilog compatability 558 function realtobits (arg : REAL) return STD_ULOGIC_VECTOR; 559 function bitstoreal (arg : STD_ULOGIC_VECTOR) return REAL; 560 561 -- Maps metalogical values 562 function to_01 ( 563 arg : UNRESOLVED_float; -- floating point input 564 XMAP : STD_LOGIC := '0') 565 return UNRESOLVED_float; 566 567 function Is_X (arg : UNRESOLVED_float) return BOOLEAN; 568 function to_X01 (arg : UNRESOLVED_float) return UNRESOLVED_float; 569 function to_X01Z (arg : UNRESOLVED_float) return UNRESOLVED_float; 570 function to_UX01 (arg : UNRESOLVED_float) return UNRESOLVED_float; 571 572 -- These two procedures were copied out of the body because they proved 573 -- very useful for vendor specific algorithm development 574 -- Break_number converts a floating point number into it's parts 575 -- Exponent is biased by -1 576 577 procedure break_number ( 578 arg : in UNRESOLVED_float; 579 denormalize : in BOOLEAN := float_denormalize; 580 check_error : in BOOLEAN := float_check_error; 581 fract : out UNSIGNED; 582 expon : out SIGNED; -- NOTE: Add 1 to get the real exponent! 583 sign : out STD_ULOGIC); 584 585 procedure break_number ( 586 arg : in UNRESOLVED_float; 587 denormalize : in BOOLEAN := float_denormalize; 588 check_error : in BOOLEAN := float_check_error; 589 fract : out ufixed; -- a number between 1.0 and 2.0 590 expon : out SIGNED; -- NOTE: Add 1 to get the real exponent! 591 sign : out STD_ULOGIC); 592 593 -- Normalize takes a fraction and and exponent and converts them into 594 -- a floating point number. Does the shifting and the rounding. 595 -- Exponent is assumed to be biased by -1 596 597 function normalize ( 598 fract : UNSIGNED; -- fraction, unnormalized 599 expon : SIGNED; -- exponent - 1, normalized 600 sign : STD_ULOGIC; -- sign bit 601 sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) 602 constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent 603 constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction 604 constant round_style : round_type := float_round_style; -- rounding option 605 constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP 606 constant nguard : NATURAL := float_guard_bits) -- guard bits 607 return UNRESOLVED_float; 608 609 -- Exponent is assumed to be biased by -1 610 function normalize ( 611 fract : ufixed; -- unsigned fixed point 612 expon : SIGNED; -- exponent - 1, normalized 613 sign : STD_ULOGIC; -- sign bit 614 sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) 615 constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent 616 constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction 617 constant round_style : round_type := float_round_style; -- rounding option 618 constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP 619 constant nguard : NATURAL := float_guard_bits) -- guard bits 620 return UNRESOLVED_float; 621 622 function normalize ( 623 fract : UNSIGNED; -- unsigned 624 expon : SIGNED; -- exponent - 1, normalized 625 sign : STD_ULOGIC; -- sign bit 626 sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) 627 size_res : UNRESOLVED_float; -- used for sizing only 628 constant round_style : round_type := float_round_style; -- rounding option 629 constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP 630 constant nguard : NATURAL := float_guard_bits) -- guard bits 631 return UNRESOLVED_float; 632 633 -- Exponent is assumed to be biased by -1 634 function normalize ( 635 fract : ufixed; -- unsigned fixed point 636 expon : SIGNED; -- exponent - 1, normalized 637 sign : STD_ULOGIC; -- sign bit 638 sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) 639 size_res : UNRESOLVED_float; -- used for sizing only 640 constant round_style : round_type := float_round_style; -- rounding option 641 constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP 642 constant nguard : NATURAL := float_guard_bits) -- guard bits 643 return UNRESOLVED_float; 644 645 -- overloaded versions 646 function "+" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; 647 function "+" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; 648 function "+" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; 649 function "+" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; 650 function "-" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; 651 function "-" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; 652 function "-" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; 653 function "-" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; 654 function "*" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; 655 function "*" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; 656 function "*" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; 657 function "*" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; 658 function "/" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; 659 function "/" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; 660 function "/" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; 661 function "/" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; 662 function "rem" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; 663 function "rem" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; 664 function "rem" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; 665 function "rem" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; 666 function "mod" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; 667 function "mod" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; 668 function "mod" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; 669 function "mod" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; 670 671 -- overloaded compare functions 672 function "=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN; 673 function "/=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN; 674 function ">=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN; 675 function "<=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN; 676 function ">" (l : UNRESOLVED_float; r : REAL) return BOOLEAN; 677 function "<" (l : UNRESOLVED_float; r : REAL) return BOOLEAN; 678 function "=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN; 679 function "/=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN; 680 function ">=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN; 681 function "<=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN; 682 function ">" (l : REAL; r : UNRESOLVED_float) return BOOLEAN; 683 function "<" (l : REAL; r : UNRESOLVED_float) return BOOLEAN; 684 function "=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN; 685 function "/=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN; 686 function ">=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN; 687 function "<=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN; 688 function ">" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN; 689 function "<" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN; 690 function "=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN; 691 function "/=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN; 692 function ">=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN; 693 function "<=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN; 694 function ">" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN; 695 function "<" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN; 696 function \?=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC; 697 function \?/=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC; 698 function \?>\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC; 699 function \?>=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC; 700 function \?<\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC; 701 function \?<=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC; 702 function \?=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC; 703 function \?/=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC; 704 function \?>\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC; 705 function \?>=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC; 706 function \?<\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC; 707 function \?<=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC; 708 function \?=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC; 709 function \?/=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC; 710 function \?>\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC; 711 function \?>=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC; 712 function \?<\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC; 713 function \?<=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC; 714 function \?=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC; 715 function \?/=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC; 716 function \?>\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC; 717 function \?>=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC; 718 function \?<\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC; 719 function \?<=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC; 720 -- minimum and maximum overloads 721 function maximum (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; 722 function minimum (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float; 723 function maximum (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; 724 function minimum (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float; 725 function maximum (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; 726 function minimum (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float; 727 function maximum (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; 728 function minimum (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float; 729---------------------------------------------------------------------------- 730 -- logical functions 731 ---------------------------------------------------------------------------- 732 733 function "not" (l : UNRESOLVED_float) return UNRESOLVED_float; 734 function "and" (l, r : UNRESOLVED_float) return UNRESOLVED_float; 735 function "or" (l, r : UNRESOLVED_float) return UNRESOLVED_float; 736 function "nand" (l, r : UNRESOLVED_float) return UNRESOLVED_float; 737 function "nor" (l, r : UNRESOLVED_float) return UNRESOLVED_float; 738 function "xor" (l, r : UNRESOLVED_float) return UNRESOLVED_float; 739 function "xnor" (l, r : UNRESOLVED_float) return UNRESOLVED_float; 740 -- Vector and std_ulogic functions, same as functions in numeric_std 741 function "and" (l : STD_ULOGIC; r : UNRESOLVED_float) 742 return UNRESOLVED_float; 743 function "and" (l : UNRESOLVED_float; r : STD_ULOGIC) 744 return UNRESOLVED_float; 745 function "or" (l : STD_ULOGIC; r : UNRESOLVED_float) 746 return UNRESOLVED_float; 747 function "or" (l : UNRESOLVED_float; r : STD_ULOGIC) 748 return UNRESOLVED_float; 749 function "nand" (l : STD_ULOGIC; r : UNRESOLVED_float) 750 return UNRESOLVED_float; 751 function "nand" (l : UNRESOLVED_float; r : STD_ULOGIC) 752 return UNRESOLVED_float; 753 function "nor" (l : STD_ULOGIC; r : UNRESOLVED_float) 754 return UNRESOLVED_float; 755 function "nor" (l : UNRESOLVED_float; r : STD_ULOGIC) 756 return UNRESOLVED_float; 757 function "xor" (l : STD_ULOGIC; r : UNRESOLVED_float) 758 return UNRESOLVED_float; 759 function "xor" (l : UNRESOLVED_float; r : STD_ULOGIC) 760 return UNRESOLVED_float; 761 function "xnor" (l : STD_ULOGIC; r : UNRESOLVED_float) 762 return UNRESOLVED_float; 763 function "xnor" (l : UNRESOLVED_float; r : STD_ULOGIC) 764 return UNRESOLVED_float; 765 -- Reduction operators, same as numeric_std functions 766 function and_reduce (l : UNRESOLVED_float) return STD_ULOGIC; 767 function nand_reduce (l : UNRESOLVED_float) return STD_ULOGIC; 768 function or_reduce (l : UNRESOLVED_float) return STD_ULOGIC; 769 function nor_reduce (l : UNRESOLVED_float) return STD_ULOGIC; 770 function xor_reduce (l : UNRESOLVED_float) return STD_ULOGIC; 771 function xnor_reduce (l : UNRESOLVED_float) return STD_ULOGIC; 772 773 -- Note: "sla", "sra", "sll", "slr", "rol" and "ror" not implemented. 774 775 ----------------------------------------------------------------------------- 776 -- Recommended Functions from the IEEE 754 Appendix 777 ----------------------------------------------------------------------------- 778 779 -- returns x with the sign of y. 780 function Copysign (x, y : UNRESOLVED_float) return UNRESOLVED_float; 781 782 -- Returns y * 2**n for integral values of N without computing 2**n 783 function Scalb ( 784 y : UNRESOLVED_float; -- floating point input 785 N : INTEGER; -- exponent to add 786 constant round_style : round_type := float_round_style; -- rounding option 787 constant check_error : BOOLEAN := float_check_error; -- check for errors 788 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 789 return UNRESOLVED_float; 790 791 -- Returns y * 2**n for integral values of N without computing 2**n 792 function Scalb ( 793 y : UNRESOLVED_float; -- floating point input 794 N : SIGNED; -- exponent to add 795 constant round_style : round_type := float_round_style; -- rounding option 796 constant check_error : BOOLEAN := float_check_error; -- check for errors 797 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 798 return UNRESOLVED_float; 799 800 -- returns the unbiased exponent of x 801 function Logb (x : UNRESOLVED_float) return INTEGER; 802 function Logb (x : UNRESOLVED_float) return SIGNED; 803 804 -- returns the next representable neighbor of x in the direction toward y 805 function Nextafter ( 806 x, y : UNRESOLVED_float; -- floating point input 807 constant check_error : BOOLEAN := float_check_error; -- check for errors 808 constant denormalize : BOOLEAN := float_denormalize) 809 return UNRESOLVED_float; 810 811 -- Returns TRUE if X is unordered with Y. 812 function Unordered (x, y : UNRESOLVED_float) return BOOLEAN; 813 function Finite (x : UNRESOLVED_float) return BOOLEAN; 814 function Isnan (x : UNRESOLVED_float) return BOOLEAN; 815 816 -- Function to return constants. 817 function zerofp ( 818 constant exponent_width : NATURAL := float_exponent_width; -- exponent 819 constant fraction_width : NATURAL := float_fraction_width) -- fraction 820 return UNRESOLVED_float; 821 function nanfp ( 822 constant exponent_width : NATURAL := float_exponent_width; -- exponent 823 constant fraction_width : NATURAL := float_fraction_width) -- fraction 824 return UNRESOLVED_float; 825 function qnanfp ( 826 constant exponent_width : NATURAL := float_exponent_width; -- exponent 827 constant fraction_width : NATURAL := float_fraction_width) -- fraction 828 return UNRESOLVED_float; 829 function pos_inffp ( 830 constant exponent_width : NATURAL := float_exponent_width; -- exponent 831 constant fraction_width : NATURAL := float_fraction_width) -- fraction 832 return UNRESOLVED_float; 833 function neg_inffp ( 834 constant exponent_width : NATURAL := float_exponent_width; -- exponent 835 constant fraction_width : NATURAL := float_fraction_width) -- fraction 836 return UNRESOLVED_float; 837 function neg_zerofp ( 838 constant exponent_width : NATURAL := float_exponent_width; -- exponent 839 constant fraction_width : NATURAL := float_fraction_width) -- fraction 840 return UNRESOLVED_float; 841 -- size_res versions 842 function zerofp ( 843 size_res : UNRESOLVED_float) -- variable is only use for sizing 844 return UNRESOLVED_float; 845 function nanfp ( 846 size_res : UNRESOLVED_float) -- variable is only use for sizing 847 return UNRESOLVED_float; 848 function qnanfp ( 849 size_res : UNRESOLVED_float) -- variable is only use for sizing 850 return UNRESOLVED_float; 851 function pos_inffp ( 852 size_res : UNRESOLVED_float) -- variable is only use for sizing 853 return UNRESOLVED_float; 854 function neg_inffp ( 855 size_res : UNRESOLVED_float) -- variable is only use for sizing 856 return UNRESOLVED_float; 857 function neg_zerofp ( 858 size_res : UNRESOLVED_float) -- variable is only use for sizing 859 return UNRESOLVED_float; 860 861 -- =========================================================================== 862 -- string and textio Functions 863 -- =========================================================================== 864-- rtl_synthesis off 865-- pragma synthesis_off 866 -- writes S:EEEE:FFFFFFFF 867 procedure WRITE ( 868 L : inout LINE; -- access type (pointer) 869 VALUE : in UNRESOLVED_float; -- value to write 870 JUSTIFIED : in SIDE := right; -- which side to justify text 871 FIELD : in WIDTH := 0); -- width of field 872 873 -- Reads SEEEEFFFFFFFF, "." and ":" are ignored 874 procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float); 875 procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float; 876 GOOD : out BOOLEAN); 877 878 alias BREAD is READ [LINE, UNRESOLVED_float, BOOLEAN]; 879 alias BREAD is READ [LINE, UNRESOLVED_float]; 880 alias BWRITE is WRITE [LINE, UNRESOLVED_float, SIDE, WIDTH]; 881 alias BINARY_READ is READ [LINE, UNRESOLVED_FLOAT, BOOLEAN]; 882 alias BINARY_READ is READ [LINE, UNRESOLVED_FLOAT]; 883 alias BINARY_WRITE is WRITE [LINE, UNRESOLVED_float, SIDE, WIDTH]; 884 885 procedure OWRITE ( 886 L : inout LINE; -- access type (pointer) 887 VALUE : in UNRESOLVED_float; -- value to write 888 JUSTIFIED : in SIDE := right; -- which side to justify text 889 FIELD : in WIDTH := 0); -- width of field 890 891 -- Octal read with padding, no separators used 892 procedure OREAD (L : inout LINE; VALUE : out UNRESOLVED_float); 893 procedure OREAD (L : inout LINE; VALUE : out UNRESOLVED_float; 894 GOOD : out BOOLEAN); 895 alias OCTAL_READ is OREAD [LINE, UNRESOLVED_FLOAT, BOOLEAN]; 896 alias OCTAL_READ is OREAD [LINE, UNRESOLVED_FLOAT]; 897 alias OCTAL_WRITE is OWRITE [LINE, UNRESOLVED_FLOAT, SIDE, WIDTH]; 898 899 -- Hex write with padding, no separators 900 procedure HWRITE ( 901 L : inout LINE; -- access type (pointer) 902 VALUE : in UNRESOLVED_float; -- value to write 903 JUSTIFIED : in SIDE := right; -- which side to justify text 904 FIELD : in WIDTH := 0); -- width of field 905 906 -- Hex read with padding, no separators used 907 procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float); 908 procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float; 909 GOOD : out BOOLEAN); 910 alias HEX_READ is HREAD [LINE, UNRESOLVED_FLOAT, BOOLEAN]; 911 alias HEX_READ is HREAD [LINE, UNRESOLVED_FLOAT]; 912 alias HEX_WRITE is HWRITE [LINE, UNRESOLVED_FLOAT, SIDE, WIDTH]; 913 914 -- returns "S:EEEE:FFFFFFFF" 915 function to_string (value : UNRESOLVED_float) return STRING; 916 alias TO_BSTRING is TO_STRING [UNRESOLVED_FLOAT return STRING]; 917 alias TO_BINARY_STRING is TO_STRING [UNRESOLVED_FLOAT return STRING]; 918 919 -- Returns a HEX string, with padding 920 function to_hstring (value : UNRESOLVED_float) return STRING; 921 alias TO_HEX_STRING is TO_HSTRING [UNRESOLVED_FLOAT return STRING]; 922 923 -- Returns and octal string, with padding 924 function to_ostring (value : UNRESOLVED_float) return STRING; 925 alias TO_OCTAL_STRING is TO_OSTRING [UNRESOLVED_FLOAT return STRING]; 926 927 function from_string ( 928 bstring : STRING; -- binary string 929 constant exponent_width : NATURAL := float_exponent_width; 930 constant fraction_width : NATURAL := float_fraction_width) 931 return UNRESOLVED_float; 932 alias from_bstring is from_string [STRING, NATURAL, NATURAL 933 return UNRESOLVED_float]; 934 alias from_binary_string is from_string [STRING, NATURAL, NATURAL 935 return UNRESOLVED_float]; 936 function from_ostring ( 937 ostring : STRING; -- Octal string 938 constant exponent_width : NATURAL := float_exponent_width; 939 constant fraction_width : NATURAL := float_fraction_width) 940 return UNRESOLVED_float; 941 alias from_octal_string is from_ostring [STRING, NATURAL, NATURAL 942 return UNRESOLVED_float]; 943 944 function from_hstring ( 945 hstring : STRING; -- hex string 946 constant exponent_width : NATURAL := float_exponent_width; 947 constant fraction_width : NATURAL := float_fraction_width) 948 return UNRESOLVED_float; 949 alias from_hex_string is from_hstring [STRING, NATURAL, NATURAL 950 return UNRESOLVED_float]; 951 952 function from_string ( 953 bstring : STRING; -- binary string 954 size_res : UNRESOLVED_float) -- used for sizing only 955 return UNRESOLVED_float; 956 alias from_bstring is from_string [STRING, UNRESOLVED_float 957 return UNRESOLVED_float]; 958 alias from_binary_string is from_string [STRING, UNRESOLVED_float 959 return UNRESOLVED_float]; 960 961 function from_ostring ( 962 ostring : STRING; -- Octal string 963 size_res : UNRESOLVED_float) -- used for sizing only 964 return UNRESOLVED_float; 965 alias from_octal_string is from_ostring [STRING, UNRESOLVED_float 966 return UNRESOLVED_float]; 967 968 function from_hstring ( 969 hstring : STRING; -- hex string 970 size_res : UNRESOLVED_float) -- used for sizing only 971 return UNRESOLVED_float; 972 alias from_hex_string is from_hstring [STRING, UNRESOLVED_float 973 return UNRESOLVED_float]; 974-- rtl_synthesis on 975-- pragma synthesis_on 976 -- IN VHDL-2006 std_logic_vector is a subtype of std_ulogic_vector, so these 977 -- extra functions are needed for compatability. 978 function to_float ( 979 arg : STD_LOGIC_VECTOR; 980 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 981 constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction 982 return UNRESOLVED_float; 983 984 function to_float ( 985 arg : STD_LOGIC_VECTOR; 986 size_res : UNRESOLVED_float) 987 return UNRESOLVED_float; 988 989 -- For Verilog compatability 990 function realtobits (arg : REAL) return STD_LOGIC_VECTOR; 991 function bitstoreal (arg : STD_LOGIC_VECTOR) return REAL; 992 993end package float_pkg; 994------------------------------------------------------------------------------- 995-- Proposed package body for the VHDL-200x-FT float_pkg package 996-- This version is optimized for Synthesis, and not for simulation. 997-- Note that there are functional differences between the synthesis and 998-- simulation packages bodies. The Synthesis version is preferred. 999-- This package body supplies a recommended implementation of these functions 1000-- Version : $Revision: 1.1 $ 1001-- Date : $Date: 2012/03/09 20:36:50 $ 1002-- 1003-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) 1004------------------------------------------------------------------------------- 1005 1006package body float_pkg is 1007 1008 -- Author David Bishop (dbishop@vhdl.org) 1009 ----------------------------------------------------------------------------- 1010 -- type declarations 1011 ----------------------------------------------------------------------------- 1012 1013 -- This deferred constant will tell you if the package body is synthesizable 1014 -- or implemented as real numbers, set to "true" if synthesizable. 1015 constant fphdlsynth_or_real : BOOLEAN := true; -- deferred constant 1016 1017 -- types of boundary conditions 1018 type boundary_type is (normal, infinity, zero, denormal); 1019 1020 -- null range array constant 1021 constant NAFP : UNRESOLVED_float (0 downto 1) := (others => '0'); 1022 constant NSLV : STD_ULOGIC_VECTOR (0 downto 1) := (others => '0'); 1023 1024 -- %%% Replicated functions 1025 -- These functions are replicated so that we don't need to reference the new 1026 -- 2006 package std.standard, std_logic_1164 and numeric_std. 1027 function maximum ( 1028 l, r : INTEGER) -- inputs 1029 return INTEGER is 1030 begin -- function max 1031 if l > r then return l; 1032 else return r; 1033 end if; 1034 end function maximum; 1035 1036 function minimum ( 1037 l, r : INTEGER) -- inputs 1038 return INTEGER is 1039 begin -- function min 1040 if l > r then return r; 1041 else return l; 1042 end if; 1043 end function minimum; 1044 1045 function or_reduce (arg : STD_ULOGIC_VECTOR) 1046 return STD_LOGIC is 1047 variable Upper, Lower : STD_ULOGIC; 1048 variable Half : INTEGER; 1049 variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); 1050 variable Result : STD_ULOGIC; 1051 begin 1052 if (arg'length < 1) then -- In the case of a NULL range 1053 Result := '0'; 1054 else 1055 BUS_int := to_ux01 (arg); 1056 if (BUS_int'length = 1) then 1057 Result := BUS_int (BUS_int'left); 1058 elsif (BUS_int'length = 2) then 1059 Result := BUS_int (BUS_int'right) or BUS_int (BUS_int'left); 1060 else 1061 Half := (BUS_int'length + 1) / 2 + BUS_int'right; 1062 Upper := or_reduce (BUS_int (BUS_int'left downto Half)); 1063 Lower := or_reduce (BUS_int (Half - 1 downto BUS_int'right)); 1064 Result := Upper or Lower; 1065 end if; 1066 end if; 1067 return Result; 1068 end function or_reduce; 1069 1070 function or_reduce (arg : UNSIGNED) 1071 return STD_ULOGIC is 1072 begin 1073 return or_reduce (STD_ULOGIC_VECTOR (arg)); 1074 end function or_reduce; 1075 1076 function or_reduce (arg : SIGNED) 1077 return STD_ULOGIC is 1078 begin 1079 return or_reduce (STD_ULOGIC_VECTOR (arg)); 1080 end function or_reduce; 1081 1082 function or_reduce (arg : STD_LOGIC_VECTOR) 1083 return STD_ULOGIC is 1084 begin 1085 return or_reduce (STD_ULOGIC_VECTOR (arg)); 1086 end function or_reduce; 1087 1088 -- purpose: AND all of the bits in a vector together 1089 -- This is a copy of the proposed "and_reduce" from 1076.3 1090 function and_reduce (arg : STD_ULOGIC_VECTOR) 1091 return STD_LOGIC is 1092 variable Upper, Lower : STD_ULOGIC; 1093 variable Half : INTEGER; 1094 variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); 1095 variable Result : STD_ULOGIC; 1096 begin 1097 if (arg'length < 1) then -- In the case of a NULL range 1098 Result := '1'; 1099 else 1100 BUS_int := to_ux01 (arg); 1101 if (BUS_int'length = 1) then 1102 Result := BUS_int (BUS_int'left); 1103 elsif (BUS_int'length = 2) then 1104 Result := BUS_int (BUS_int'right) and BUS_int (BUS_int'left); 1105 else 1106 Half := (BUS_int'length + 1) / 2 + BUS_int'right; 1107 Upper := and_reduce (BUS_int (BUS_int'left downto Half)); 1108 Lower := and_reduce (BUS_int (Half - 1 downto BUS_int'right)); 1109 Result := Upper and Lower; 1110 end if; 1111 end if; 1112 return Result; 1113 end function and_reduce; 1114 1115 function and_reduce (arg : UNSIGNED) 1116 return STD_ULOGIC is 1117 begin 1118 return and_reduce (STD_ULOGIC_VECTOR (arg)); 1119 end function and_reduce; 1120 1121 function and_reduce (arg : SIGNED) 1122 return STD_ULOGIC is 1123 begin 1124 return and_reduce (STD_ULOGIC_VECTOR (arg)); 1125 end function and_reduce; 1126 1127 function xor_reduce (arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is 1128 variable Upper, Lower : STD_ULOGIC; 1129 variable Half : INTEGER; 1130 variable BUS_int : STD_ULOGIC_VECTOR (arg'length - 1 downto 0); 1131 variable Result : STD_ULOGIC := '0'; -- In the case of a NULL range 1132 begin 1133 if (arg'length >= 1) then 1134 BUS_int := to_ux01 (arg); 1135 if (BUS_int'length = 1) then 1136 Result := BUS_int (BUS_int'left); 1137 elsif (BUS_int'length = 2) then 1138 Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); 1139 else 1140 Half := (BUS_int'length + 1) / 2 + BUS_int'right; 1141 Upper := xor_reduce (BUS_int (BUS_int'left downto Half)); 1142 Lower := xor_reduce (BUS_int (Half - 1 downto BUS_int'right)); 1143 Result := Upper xor Lower; 1144 end if; 1145 end if; 1146 return Result; 1147 end function xor_reduce; 1148 1149 function nand_reduce(arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is 1150 begin 1151 return not and_reduce (arg); 1152 end function nand_reduce; 1153 1154 function nor_reduce(arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is 1155 begin 1156 return not or_reduce (arg); 1157 end function nor_reduce; 1158 1159 function xnor_reduce(arg : STD_ULOGIC_VECTOR) return STD_ULOGIC is 1160 begin 1161 return not xor_reduce (arg); 1162 end function xnor_reduce; 1163 1164 function find_leftmost (ARG : UNSIGNED; Y : STD_ULOGIC) 1165 return INTEGER is 1166 begin 1167 for INDEX in ARG'range loop 1168 if ARG(INDEX) = Y then 1169 return INDEX; 1170 end if; 1171 end loop; 1172 return -1; 1173 end function find_leftmost; 1174 1175 -- Match table, copied form new std_logic_1164 1176 type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; 1177 constant match_logic_table : stdlogic_table := ( 1178 ----------------------------------------------------- 1179 -- U X 0 1 Z W L H - | | 1180 ----------------------------------------------------- 1181 ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1'), -- | U | 1182 ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | X | 1183 ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | 0 | 1184 ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | 1 | 1185 ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | Z | 1186 ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | W | 1187 ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | L | 1188 ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | H | 1189 ('1', '1', '1', '1', '1', '1', '1', '1', '1') -- | - | 1190 ); 1191 1192 1193 ------------------------------------------------------------------- 1194 -- ?= functions, Similar to "std_match", but returns "std_ulogic". 1195 ------------------------------------------------------------------- 1196 -- %%% FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic IS 1197 function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC is 1198 begin 1199 return match_logic_table (l, r); 1200 end function \?=\; 1201 -- %%% END FUNCTION "?="; 1202 1203 -- %%% FUNCTION "?/=" ( l, r : std_ulogic ) RETURN std_ulogic is 1204 function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is 1205 begin 1206 return not match_logic_table (l, r); 1207 end function \?/=\; 1208 -- %%% END FUNCTION "?/="; 1209 1210 function \?=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is 1211 alias lv : STD_ULOGIC_VECTOR(1 to l'length) is l; 1212 alias rv : STD_ULOGIC_VECTOR(1 to r'length) is r; 1213 variable result, result1 : STD_ULOGIC; 1214 begin 1215 -- Logically identical to an "=" operator. 1216 if ((l'length < 1) and (r'length < 1)) then 1217 -- VHDL-2008 LRM 9.2.3 Two NULL arrays of the same type are equal 1218 return '1'; 1219 elsif lv'length /= rv'length then 1220 -- Two arrays of different lengths are false 1221 return '0'; 1222 else 1223 result := '1'; 1224 for i in lv'low to lv'high loop 1225 result1 := match_logic_table(lv(i), rv(i)); 1226 result := result and result1; 1227 end loop; 1228 return result; 1229 end if; 1230 end function \?=\; 1231 1232 function Is_X (s : UNSIGNED) return BOOLEAN is 1233 begin 1234 return Is_X (STD_LOGIC_VECTOR (s)); 1235 end function Is_X; 1236 1237 function Is_X (s : SIGNED) return BOOLEAN is 1238 begin 1239 return Is_X (STD_LOGIC_VECTOR (s)); 1240 end function Is_X; 1241-- %%% END replicated functions 1242 1243 -- Special version of "minimum" to do some boundary checking 1244 function mine (L, R : INTEGER) 1245 return INTEGER is 1246 begin -- function minimum 1247 if (L = INTEGER'low or R = INTEGER'low) then 1248 report float_pkg'instance_name 1249 & " Unbounded number passed, was a literal used?" 1250 severity error; 1251 return 0; 1252 end if; 1253 return minimum (L, R); 1254 end function mine; 1255 1256 -- Generates the base number for the exponent normalization offset. 1257 function gen_expon_base ( 1258 constant exponent_width : NATURAL) 1259 return SIGNED is 1260 variable result : SIGNED (exponent_width-1 downto 0); 1261 begin 1262 result := (others => '1'); 1263 result (exponent_width-1) := '0'; 1264 return result; 1265 end function gen_expon_base; 1266 1267 -- Integer version of the "log2" command (contributed by Peter Ashenden) 1268 function log2 (A : NATURAL) return NATURAL is 1269 variable quotient : NATURAL; 1270 variable result : NATURAL := 0; 1271 begin 1272 quotient := A / 2; 1273 while quotient > 0 loop 1274 quotient := quotient / 2; 1275 result := result + 1; 1276 end loop; 1277 return result; 1278 end function log2; 1279 1280 -- Function similar to the ILOGB function in MATH_REAL 1281 function log2 (A : REAL) return INTEGER is 1282 variable Y : REAL; 1283 variable N : INTEGER := 0; 1284 begin 1285 if (A = 1.0 or A = 0.0) then 1286 return 0; 1287 end if; 1288 Y := A; 1289 if(A > 1.0) then 1290 while Y >= 2.0 loop 1291 Y := Y / 2.0; 1292 N := N + 1; 1293 end loop; 1294 return N; 1295 end if; 1296 -- O < Y < 1 1297 while Y < 1.0 loop 1298 Y := Y * 2.0; 1299 N := N - 1; 1300 end loop; 1301 return N; 1302 end function log2; 1303 1304 -- purpose: Test the boundary conditions of a Real number 1305 procedure test_boundary ( 1306 arg : in REAL; -- Input, converted to real 1307 constant fraction_width : in NATURAL; -- length of FP output fraction 1308 constant exponent_width : in NATURAL; -- length of FP exponent 1309 constant denormalize : in BOOLEAN := true; -- Use IEEE extended FP 1310 variable btype : out boundary_type; 1311 variable log2i : out INTEGER 1312 ) is 1313 constant expon_base : SIGNED (exponent_width-1 downto 0) := 1314 gen_expon_base(exponent_width); -- exponent offset 1315 constant exp_min : SIGNED (12 downto 0) := 1316 -(resize(expon_base, 13)) + 1; -- Minimum normal exponent 1317 constant exp_ext_min : SIGNED (12 downto 0) := 1318 exp_min - fraction_width; -- Minimum for denormal exponent 1319 variable log2arg : INTEGER; -- log2 of argument 1320 begin -- function test_boundary 1321 -- Check to see if the exponent is big enough 1322 -- Note that the argument is always an absolute value at this point. 1323 log2arg := log2(arg); 1324 if arg = 0.0 then 1325 btype := zero; 1326 elsif exponent_width > 11 then -- Exponent for Real is 11 (64 bit) 1327 btype := normal; 1328 else 1329 if log2arg < to_integer(exp_min) then 1330 if denormalize then 1331 if log2arg < to_integer(exp_ext_min) then 1332 btype := zero; 1333 else 1334 btype := denormal; 1335 end if; 1336 else 1337 if log2arg < to_integer(exp_min)-1 then 1338 btype := zero; 1339 else 1340 btype := normal; -- Can still represent this number 1341 end if; 1342 end if; 1343 elsif exponent_width < 11 then 1344 if log2arg > to_integer(expon_base)+1 then 1345 btype := infinity; 1346 else 1347 btype := normal; 1348 end if; 1349 else 1350 btype := normal; 1351 end if; 1352 end if; 1353 log2i := log2arg; 1354 end procedure test_boundary; 1355 1356 -- purpose: Rounds depending on the state of the "round_style" 1357 -- Logic taken from 1358 -- "What Every Computer Scientist Should Know About Floating Point Arithmetic" 1359 -- by David Goldberg (1991) 1360 function check_round ( 1361 fract_in : STD_ULOGIC; -- input fraction 1362 sign : STD_ULOGIC; -- sign bit 1363 remainder : UNSIGNED; -- remainder to round from 1364 sticky : STD_ULOGIC := '0'; -- Sticky bit 1365 constant round_style : round_type) -- rounding type 1366 return BOOLEAN is 1367 variable result : BOOLEAN; 1368 variable or_reduced : STD_ULOGIC; 1369 begin -- function check_round 1370 result := false; 1371 if (remainder'length > 0) then -- if remainder in a null array 1372 or_reduced := or_reduce (remainder & sticky); 1373 rounding_case : case round_style is 1374 when round_nearest => -- Round Nearest, default mode 1375 if remainder(remainder'high) = '1' then -- round 1376 if (remainder'length > 1) then 1377 if ((or_reduce (remainder(remainder'high-1 1378 downto remainder'low)) = '1' 1379 or sticky = '1') 1380 or fract_in = '1') then 1381 -- Make the bottom bit zero if possible if we are at 1/2 1382 result := true; 1383 end if; 1384 else 1385 result := (fract_in = '1' or sticky = '1'); 1386 end if; 1387 end if; 1388 when round_inf => -- round up if positive, else truncate. 1389 if or_reduced = '1' and sign = '0' then 1390 result := true; 1391 end if; 1392 when round_neginf => -- round down if negative, else truncate. 1393 if or_reduced = '1' and sign = '1' then 1394 result := true; 1395 end if; 1396 when round_zero => -- round toward 0 Truncate 1397 null; 1398 end case rounding_case; 1399 end if; 1400 return result; 1401 end function check_round; 1402 1403 -- purpose: Rounds depending on the state of the "round_style" 1404 -- unsigned version 1405 procedure fp_round ( 1406 fract_in : in UNSIGNED; -- input fraction 1407 expon_in : in SIGNED; -- input exponent 1408 fract_out : out UNSIGNED; -- output fraction 1409 expon_out : out SIGNED) is -- output exponent 1410 begin -- procedure fp_round 1411 if and_reduce (fract_in) = '1' then -- Fraction is all "1" 1412 expon_out := expon_in + 1; 1413 fract_out := to_unsigned(0, fract_out'high+1); 1414 else 1415 expon_out := expon_in; 1416 fract_out := fract_in + 1; 1417 end if; 1418 end procedure fp_round; 1419 1420 -- This version of break_number doesn't call "classfp" 1421 procedure break_number ( -- internal version 1422 arg : in UNRESOLVED_float; 1423 fptyp : in valid_fpstate; 1424 denormalize : in BOOLEAN := true; 1425 fract : out UNSIGNED; 1426 expon : out SIGNED) is 1427 constant fraction_width : NATURAL := -arg'low; -- length of FP output fraction 1428 constant exponent_width : NATURAL := arg'high; -- length of FP output exponent 1429 constant expon_base : SIGNED (exponent_width-1 downto 0) := 1430 gen_expon_base(exponent_width); -- exponent offset 1431 variable exp : SIGNED (expon'range); 1432 begin 1433 fract (fraction_width-1 downto 0) := 1434 UNSIGNED (to_slv(arg(-1 downto -fraction_width))); 1435 breakcase : case fptyp is 1436 when pos_zero | neg_zero => 1437 fract (fraction_width) := '0'; 1438 exp := -expon_base; 1439 when pos_denormal | neg_denormal => 1440 if denormalize then 1441 exp := -expon_base; 1442 fract (fraction_width) := '0'; 1443 else 1444 exp := -expon_base - 1; 1445 fract (fraction_width) := '1'; 1446 end if; 1447 when pos_normal | neg_normal | pos_inf | neg_inf => 1448 fract (fraction_width) := '1'; 1449 exp := SIGNED(arg(exponent_width-1 downto 0)); 1450 exp (exponent_width-1) := not exp(exponent_width-1); 1451 when others => 1452 assert NO_WARNING 1453 report float_pkg'instance_name 1454 & "BREAK_NUMBER: " & 1455 "Meta state detected in fp_break_number process" 1456 severity warning; 1457 -- complete the case, if a NAN goes in, a NAN comes out. 1458 exp := (others => '1'); 1459 fract (fraction_width) := '1'; 1460 end case breakcase; 1461 expon := exp; 1462 end procedure break_number; 1463 1464 -- purpose: floating point to UNSIGNED 1465 -- Used by to_integer, to_unsigned, and to_signed functions 1466 procedure float_to_unsigned ( 1467 arg : in UNRESOLVED_float; -- floating point input 1468 variable sign : out STD_ULOGIC; -- sign of output 1469 variable frac : out UNSIGNED; -- unsigned biased output 1470 constant denormalize : in BOOLEAN; -- turn on denormalization 1471 constant bias : in NATURAL; -- bias for fixed point 1472 constant round_style : in round_type) is -- rounding method 1473 constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction 1474 constant exponent_width : INTEGER := arg'high; -- length of FP output exponent 1475 variable fract : UNSIGNED (frac'range); -- internal version of frac 1476 variable isign : STD_ULOGIC; -- internal version of sign 1477 variable exp : INTEGER; -- Exponent 1478 variable expon : SIGNED (exponent_width-1 downto 0); -- Vectorized exp 1479 -- Base to divide fraction by 1480 variable frac_shift : UNSIGNED (frac'high+3 downto 0); -- Fraction shifted 1481 variable shift : INTEGER; 1482 variable remainder : UNSIGNED (2 downto 0); 1483 variable round : STD_ULOGIC; -- round BIT 1484 begin 1485 isign := to_x01(arg(arg'high)); 1486 -- exponent /= '0', normal floating point 1487 expon := to_01(SIGNED(arg (exponent_width-1 downto 0)), 'X'); 1488 expon(exponent_width-1) := not expon(exponent_width-1); 1489 exp := to_integer (expon); 1490 -- Figure out the fraction 1491 fract := (others => '0'); -- fill with zero 1492 fract (fract'high) := '1'; -- Add the "1.0". 1493 shift := (fract'high-1) - exp; 1494 if fraction_width > fract'high then -- Can only use size-2 bits 1495 fract (fract'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto 1496 -fract'high))); 1497 else -- can use all bits 1498 fract (fract'high-1 downto fract'high-fraction_width) := 1499 UNSIGNED (to_slv (arg(-1 downto -fraction_width))); 1500 end if; 1501 frac_shift := fract & "000"; 1502 if shift < 0 then -- Overflow 1503 fract := (others => '1'); 1504 else 1505 frac_shift := shift_right (frac_shift, shift); 1506 fract := frac_shift (frac_shift'high downto 3); 1507 remainder := frac_shift (2 downto 0); 1508 -- round (round_zero will bypass this and truncate) 1509 case round_style is 1510 when round_nearest => 1511 round := remainder(2) and 1512 (fract (0) or (or_reduce (remainder (1 downto 0)))); 1513 when round_inf => 1514 round := remainder(2) and not isign; 1515 when round_neginf => 1516 round := remainder(2) and isign; 1517 when others => 1518 round := '0'; 1519 end case; 1520 if round = '1' then 1521 fract := fract + 1; 1522 end if; 1523 end if; 1524 frac := fract; 1525 sign := isign; 1526 end procedure float_to_unsigned; 1527 1528 -- purpose: returns a part of a vector, this function is here because 1529 -- or (fractr (to_integer(shiftx) downto 0)); 1530 -- can't be synthesized in some synthesis tools. 1531 function smallfract ( 1532 arg : UNSIGNED; 1533 shift : NATURAL) 1534 return STD_ULOGIC is 1535 variable orx : STD_ULOGIC; 1536 begin 1537 orx := arg(shift); 1538 for i in arg'range loop 1539 if i < shift then 1540 orx := arg(i) or orx; 1541 end if; 1542 end loop; 1543 return orx; 1544 end function smallfract; 1545 --------------------------------------------------------------------------- 1546 -- Visible functions 1547 --------------------------------------------------------------------------- 1548 1549 -- purpose: converts the negative index to a positive one 1550 -- negative indices are illegal in 1164 and 1076.3 1551 function to_sulv ( 1552 arg : UNRESOLVED_float) -- fp vector 1553 return STD_ULOGIC_VECTOR is 1554 variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0); 1555 begin -- function to_std_ulogic_vector 1556 if arg'length < 1 then 1557 return NSLV; 1558 end if; 1559 result := STD_ULOGIC_VECTOR (arg); 1560 return result; 1561 end function to_sulv; 1562 1563 -- Converts an fp into an SLV 1564 function to_slv (arg : UNRESOLVED_float) return STD_LOGIC_VECTOR is 1565 begin 1566 return to_stdlogicvector (to_sulv (arg)); 1567 end function to_slv; 1568 1569 -- purpose: normalizes a floating point number 1570 -- This version assumes an "unsigned" input with 1571 function normalize ( 1572 fract : UNSIGNED; -- fraction, unnormalized 1573 expon : SIGNED; -- exponent, normalized by -1 1574 sign : STD_ULOGIC; -- sign BIT 1575 sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) 1576 constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent 1577 constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction 1578 constant round_style : round_type := float_round_style; -- rounding option 1579 constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP 1580 constant nguard : NATURAL := float_guard_bits) -- guard bits 1581 return UNRESOLVED_float is 1582 variable sfract : UNSIGNED (fract'high downto 0); -- shifted fraction 1583 variable rfract : UNSIGNED (fraction_width-1 downto 0); -- fraction 1584 variable exp : SIGNED (exponent_width+1 downto 0); -- exponent 1585 variable rexp : SIGNED (exponent_width+1 downto 0); -- result exponent 1586 variable rexpon : UNSIGNED (exponent_width-1 downto 0); -- exponent 1587 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); -- result 1588 variable shiftr : INTEGER; -- shift amount 1589 variable stickyx : STD_ULOGIC; -- version of sticky 1590 constant expon_base : SIGNED (exponent_width-1 downto 0) := 1591 gen_expon_base(exponent_width); -- exponent offset 1592 variable round, zerores, infres : BOOLEAN; 1593 begin -- function normalize 1594 zerores := false; 1595 infres := false; 1596 round := false; 1597 shiftr := find_leftmost (to_01(fract), '1') -- Find the first "1" 1598 - fraction_width - nguard; -- subtract the length we want 1599 exp := resize (expon, exp'length) + shiftr; 1600 if (or_reduce (fract) = '0') then -- Zero 1601 zerores := true; 1602 elsif ((exp <= -resize(expon_base, exp'length)-1) and denormalize) 1603 or ((exp < -resize(expon_base, exp'length)-1) and not denormalize) then 1604 if (exp >= -resize(expon_base, exp'length)-fraction_width-1) 1605 and denormalize then 1606 exp := -resize(expon_base, exp'length)-1; 1607 shiftr := -to_integer (expon + expon_base); -- new shift 1608 else -- return zero 1609 zerores := true; 1610 end if; 1611 elsif (exp > expon_base-1) then -- infinity 1612 infres := true; 1613 end if; 1614 if zerores then 1615 result := zerofp (fraction_width => fraction_width, 1616 exponent_width => exponent_width); 1617 elsif infres then 1618 result := pos_inffp (fraction_width => fraction_width, 1619 exponent_width => exponent_width); 1620 else 1621 sfract := fract srl shiftr; -- shift 1622 if shiftr > 0 then 1623-- stickyx := sticky or (or_reduce(fract (shiftr-1 downto 0))); 1624 stickyx := sticky or smallfract (fract, shiftr-1); 1625 else 1626 stickyx := sticky; 1627 end if; 1628 if nguard > 0 then 1629 round := check_round ( 1630 fract_in => sfract (nguard), 1631 sign => sign, 1632 remainder => sfract(nguard-1 downto 0), 1633 sticky => stickyx, 1634 round_style => round_style); 1635 end if; 1636 if round then 1637 fp_round(fract_in => sfract (fraction_width-1+nguard downto nguard), 1638 expon_in => exp(rexp'range), 1639 fract_out => rfract, 1640 expon_out => rexp); 1641 else 1642 rfract := sfract (fraction_width-1+nguard downto nguard); 1643 rexp := exp(rexp'range); 1644 end if; 1645 -- result 1646 rexpon := UNSIGNED (rexp(exponent_width-1 downto 0)); 1647 rexpon (exponent_width-1) := not rexpon(exponent_width-1); 1648 result (rexpon'range) := UNRESOLVED_float(rexpon); 1649 result (-1 downto -fraction_width) := UNRESOLVED_float(rfract); 1650 end if; 1651 result (exponent_width) := sign; -- sign BIT 1652 return result; 1653 end function normalize; 1654 1655 -- purpose: normalizes a floating point number 1656 -- This version assumes a "ufixed" input 1657 function normalize ( 1658 fract : ufixed; -- unsigned fixed point 1659 expon : SIGNED; -- exponent, normalized by -1 1660 sign : STD_ULOGIC; -- sign bit 1661 sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) 1662 constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent 1663 constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction 1664 constant round_style : round_type := float_round_style; -- rounding option 1665 constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP 1666 constant nguard : NATURAL := float_guard_bits) -- guard bits 1667 return UNRESOLVED_float is 1668 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 1669 variable arguns : UNSIGNED (fract'high + fraction_width + nguard 1670 downto 0) := (others => '0'); 1671 begin -- function normalize 1672 arguns (arguns'high downto maximum (arguns'high-fract'length+1, 0)) := 1673 UNSIGNED (to_slv (fract)); 1674 result := normalize (fract => arguns, 1675 expon => expon, 1676 sign => sign, 1677 sticky => sticky, 1678 fraction_width => fraction_width, 1679 exponent_width => exponent_width, 1680 round_style => round_style, 1681 denormalize => denormalize, 1682 nguard => nguard); 1683 return result; 1684 end function normalize; 1685 1686 -- purpose: normalizes a floating point number 1687 -- This version assumes a "ufixed" input with a "size_res" input 1688 function normalize ( 1689 fract : ufixed; -- unsigned fixed point 1690 expon : SIGNED; -- exponent, normalized by -1 1691 sign : STD_ULOGIC; -- sign bit 1692 sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) 1693 size_res : UNRESOLVED_float; -- used for sizing only 1694 constant round_style : round_type := float_round_style; -- rounding option 1695 constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP 1696 constant nguard : NATURAL := float_guard_bits) -- guard bits 1697 return UNRESOLVED_float is 1698 constant fraction_width : NATURAL := -size_res'low; 1699 constant exponent_width : NATURAL := size_res'high; 1700 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 1701 variable arguns : UNSIGNED (fract'high + fraction_width + nguard 1702 downto 0) := (others => '0'); 1703 begin -- function normalize 1704 arguns (arguns'high downto maximum (arguns'high-fract'length+1, 0)) := 1705 UNSIGNED (to_slv (fract)); 1706 result := normalize (fract => arguns, 1707 expon => expon, 1708 sign => sign, 1709 sticky => sticky, 1710 fraction_width => fraction_width, 1711 exponent_width => exponent_width, 1712 round_style => round_style, 1713 denormalize => denormalize, 1714 nguard => nguard); 1715 return result; 1716 end function normalize; 1717 1718 -- Regular "normalize" function with a "size_res" input. 1719 function normalize ( 1720 fract : UNSIGNED; -- unsigned 1721 expon : SIGNED; -- exponent - 1, normalized 1722 sign : STD_ULOGIC; -- sign bit 1723 sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) 1724 size_res : UNRESOLVED_float; -- used for sizing only 1725 constant round_style : round_type := float_round_style; -- rounding option 1726 constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP 1727 constant nguard : NATURAL := float_guard_bits) -- guard bits 1728 return UNRESOLVED_float is 1729 begin 1730 return normalize (fract => fract, 1731 expon => expon, 1732 sign => sign, 1733 sticky => sticky, 1734 fraction_width => -size_res'low, 1735 exponent_width => size_res'high, 1736 round_style => round_style, 1737 denormalize => denormalize, 1738 nguard => nguard); 1739 end function normalize; 1740 1741 -- Returns the class which X falls into 1742 function Classfp ( 1743 x : UNRESOLVED_float; -- floating point input 1744 check_error : BOOLEAN := float_check_error) -- check for errors 1745 return valid_fpstate is 1746 constant fraction_width : INTEGER := -mine(x'low, x'low); -- length of FP output fraction 1747 constant exponent_width : INTEGER := x'high; -- length of FP output exponent 1748 variable arg : UNRESOLVED_float (exponent_width downto -fraction_width); 1749 begin -- classfp 1750 if (arg'length < 1 or fraction_width < 3 or exponent_width < 3 1751 or x'left < x'right) then 1752 report float_pkg'instance_name 1753 & "CLASSFP: " & 1754 "Floating point number detected with a bad range" 1755 severity error; 1756 return isx; 1757 end if; 1758 -- Check for "X". 1759 arg := to_01 (x, 'X'); 1760 if (arg(0) = 'X') then 1761 return isx; -- If there is an X in the number 1762 -- Special cases, check for illegal number 1763 elsif check_error and 1764 (and_reduce (STD_ULOGIC_VECTOR (arg (exponent_width-1 downto 0))) 1765 = '1') then -- Exponent is all "1". 1766 if or_reduce (to_slv (arg (-1 downto -fraction_width))) 1767 /= '0' then -- Fraction must be all "0" or this is not a number. 1768 if (arg(-1) = '1') then -- From "W. Khan - IEEE standard 1769 return nan; -- 754 binary FP Signaling nan (Not a number) 1770 else 1771 return quiet_nan; 1772 end if; 1773 -- Check for infinity 1774 elsif arg(exponent_width) = '0' then 1775 return pos_inf; -- Positive infinity 1776 else 1777 return neg_inf; -- Negative infinity 1778 end if; 1779 -- check for "0" 1780 elsif or_reduce (STD_LOGIC_VECTOR (arg (exponent_width-1 downto 0))) 1781 = '0' then -- Exponent is all "0" 1782 if or_reduce (to_slv (arg (-1 downto -fraction_width))) 1783 = '0' then -- Fraction is all "0" 1784 if arg(exponent_width) = '0' then 1785 return pos_zero; -- Zero 1786 else 1787 return neg_zero; 1788 end if; 1789 else 1790 if arg(exponent_width) = '0' then 1791 return pos_denormal; -- Denormal number (ieee extended fp) 1792 else 1793 return neg_denormal; 1794 end if; 1795 end if; 1796 else 1797 if arg(exponent_width) = '0' then 1798 return pos_normal; -- Normal FP number 1799 else 1800 return neg_normal; 1801 end if; 1802 end if; 1803 end function Classfp; 1804 1805 procedure break_number ( 1806 arg : in UNRESOLVED_float; 1807 denormalize : in BOOLEAN := float_denormalize; 1808 check_error : in BOOLEAN := float_check_error; 1809 fract : out UNSIGNED; 1810 expon : out SIGNED; 1811 sign : out STD_ULOGIC) is 1812 constant fraction_width : NATURAL := -mine(arg'low, arg'low); -- length of FP output fraction 1813 variable fptyp : valid_fpstate; 1814 begin 1815 fptyp := Classfp (arg, check_error); 1816 sign := to_x01(arg(arg'high)); 1817 break_number ( 1818 arg => arg, 1819 fptyp => fptyp, 1820 denormalize => denormalize, 1821 fract => fract, 1822 expon => expon); 1823 end procedure break_number; 1824 1825 procedure break_number ( 1826 arg : in UNRESOLVED_float; 1827 denormalize : in BOOLEAN := float_denormalize; 1828 check_error : in BOOLEAN := float_check_error; 1829 fract : out ufixed; -- 1 downto -fraction_width 1830 expon : out SIGNED; -- exponent_width-1 downto 0 1831 sign : out STD_ULOGIC) is 1832 constant fraction_width : NATURAL := -mine(arg'low, arg'low); -- length of FP output fraction 1833 variable fptyp : valid_fpstate; 1834 variable ufract : UNSIGNED (fraction_width downto 0); -- unsigned fraction 1835 begin 1836 fptyp := Classfp (arg, check_error); 1837 sign := to_x01(arg(arg'high)); 1838 break_number ( 1839 arg => arg, 1840 fptyp => fptyp, 1841 denormalize => denormalize, 1842 fract => ufract, 1843 expon => expon); 1844 fract (0 downto -fraction_width) := ufixed (ufract); 1845 end procedure break_number; 1846 1847 -- Arithmetic functions 1848 function "abs" ( 1849 arg : UNRESOLVED_float) -- floating point input 1850 return UNRESOLVED_float is 1851 variable result : UNRESOLVED_float (arg'range); -- result 1852 begin 1853 if (arg'length > 0) then 1854 result := to_01 (arg, 'X'); 1855 result (arg'high) := '0'; -- set the sign bit to positive 1856 return result; 1857 else 1858 return NAFP; 1859 end if; 1860 end function "abs"; 1861 1862 -- IEEE 754 "negative" function 1863 function "-" ( 1864 arg : UNRESOLVED_float) -- floating point input 1865 return UNRESOLVED_float is 1866 variable result : UNRESOLVED_float (arg'range); -- result 1867 begin 1868 if (arg'length > 0) then 1869 result := to_01 (arg, 'X'); 1870 result (arg'high) := not result (arg'high); -- invert sign bit 1871 return result; 1872 else 1873 return NAFP; 1874 end if; 1875 end function "-"; 1876 1877 -- Addition, adds two floating point numbers 1878 function add ( 1879 l, r : UNRESOLVED_float; -- floating point input 1880 constant round_style : round_type := float_round_style; -- rounding option 1881 constant guard : NATURAL := float_guard_bits; -- number of guard bits 1882 constant check_error : BOOLEAN := float_check_error; -- check for errors 1883 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 1884 return UNRESOLVED_float is 1885 constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction 1886 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 1887 constant addguard : NATURAL := guard; -- add one guard bit 1888 variable lfptype, rfptype : valid_fpstate; 1889 variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); 1890 variable fractl, fractr : UNSIGNED (fraction_width+1+addguard downto 0); -- fractions 1891 variable fractc, fracts : UNSIGNED (fractl'range); -- constant and shifted variables 1892 variable urfract, ulfract : UNSIGNED (fraction_width downto 0); 1893 variable ufract : UNSIGNED (fraction_width+1+addguard downto 0); 1894 variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents 1895 variable rexpon : SIGNED (exponent_width downto 0); -- result exponent 1896 variable shiftx : SIGNED (exponent_width downto 0); -- shift fractions 1897 variable sign : STD_ULOGIC; -- sign of the output 1898 variable leftright : BOOLEAN; -- left or right used 1899 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 1900 variable sticky : STD_ULOGIC; -- Holds precision for rounding 1901 begin -- addition 1902 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 1903 lfptype := isx; 1904 else 1905 lfptype := classfp (l, check_error); 1906 rfptype := classfp (r, check_error); 1907 end if; 1908 if (lfptype = isx or rfptype = isx) then 1909 fpresult := (others => 'X'); 1910 elsif (lfptype = nan or lfptype = quiet_nan or 1911 rfptype = nan or rfptype = quiet_nan) 1912 -- Return quiet NAN, IEEE754-1985-7.1,1 1913 or (lfptype = pos_inf and rfptype = neg_inf) 1914 or (lfptype = neg_inf and rfptype = pos_inf) then 1915 -- Return quiet NAN, IEEE754-1985-7.1,2 1916 fpresult := qnanfp (fraction_width => fraction_width, 1917 exponent_width => exponent_width); 1918 elsif (lfptype = pos_inf or rfptype = pos_inf) then -- x + inf = inf 1919 fpresult := pos_inffp (fraction_width => fraction_width, 1920 exponent_width => exponent_width); 1921 elsif (lfptype = neg_inf or rfptype = neg_inf) then -- x - inf = -inf 1922 fpresult := neg_inffp (fraction_width => fraction_width, 1923 exponent_width => exponent_width); 1924 elsif (lfptype = neg_zero and rfptype = neg_zero) then -- -0 + -0 = -0 1925 fpresult := neg_zerofp (fraction_width => fraction_width, 1926 exponent_width => exponent_width); 1927 else 1928 lresize := resize (arg => to_x01(l), 1929 exponent_width => exponent_width, 1930 fraction_width => fraction_width, 1931 denormalize_in => denormalize, 1932 denormalize => denormalize); 1933 lfptype := classfp (lresize, false); -- errors already checked 1934 rresize := resize (arg => to_x01(r), 1935 exponent_width => exponent_width, 1936 fraction_width => fraction_width, 1937 denormalize_in => denormalize, 1938 denormalize => denormalize); 1939 rfptype := classfp (rresize, false); -- errors already checked 1940 break_number ( 1941 arg => lresize, 1942 fptyp => lfptype, 1943 denormalize => denormalize, 1944 fract => ulfract, 1945 expon => exponl); 1946 fractl := (others => '0'); 1947 fractl (fraction_width+addguard downto addguard) := ulfract; 1948 break_number ( 1949 arg => rresize, 1950 fptyp => rfptype, 1951 denormalize => denormalize, 1952 fract => urfract, 1953 expon => exponr); 1954 fractr := (others => '0'); 1955 fractr (fraction_width+addguard downto addguard) := urfract; 1956 shiftx := (exponl(exponent_width-1) & exponl) - exponr; 1957 if shiftx < -fractl'high then 1958 rexpon := exponr(exponent_width-1) & exponr; 1959 fractc := fractr; 1960 fracts := (others => '0'); -- add zero 1961 leftright := false; 1962 sticky := or_reduce (fractl); 1963 elsif shiftx < 0 then 1964 shiftx := - shiftx; 1965 fracts := shift_right (fractl, to_integer(shiftx)); 1966 fractc := fractr; 1967 rexpon := exponr(exponent_width-1) & exponr; 1968 leftright := false; 1969-- sticky := or_reduce (fractl (to_integer(shiftx) downto 0)); 1970 sticky := smallfract (fractl, to_integer(shiftx)); 1971 elsif shiftx = 0 then 1972 rexpon := exponl(exponent_width-1) & exponl; 1973 sticky := '0'; 1974 if fractr > fractl then 1975 fractc := fractr; 1976 fracts := fractl; 1977 leftright := false; 1978 else 1979 fractc := fractl; 1980 fracts := fractr; 1981 leftright := true; 1982 end if; 1983 elsif shiftx > fractr'high then 1984 rexpon := exponl(exponent_width-1) & exponl; 1985 fracts := (others => '0'); -- add zero 1986 fractc := fractl; 1987 leftright := true; 1988 sticky := or_reduce (fractr); 1989 elsif shiftx > 0 then 1990 fracts := shift_right (fractr, to_integer(shiftx)); 1991 fractc := fractl; 1992 rexpon := exponl(exponent_width-1) & exponl; 1993 leftright := true; 1994-- sticky := or_reduce (fractr (to_integer(shiftx) downto 0)); 1995 sticky := smallfract (fractr, to_integer(shiftx)); 1996 end if; 1997 -- add 1998 fracts (0) := fracts (0) or sticky; -- Or the sticky bit into the LSB 1999 if l(l'high) = r(r'high) then 2000 ufract := fractc + fracts; 2001 sign := l(l'high); 2002 else -- signs are different 2003 ufract := fractc - fracts; -- always positive result 2004 if leftright then -- Figure out which sign to use 2005 sign := l(l'high); 2006 else 2007 sign := r(r'high); 2008 end if; 2009 end if; 2010 if or_reduce (ufract) = '0' then 2011 sign := '0'; -- IEEE 854, 6.3, paragraph 2. 2012 end if; 2013 -- normalize 2014 fpresult := normalize (fract => ufract, 2015 expon => rexpon, 2016 sign => sign, 2017 sticky => sticky, 2018 fraction_width => fraction_width, 2019 exponent_width => exponent_width, 2020 round_style => round_style, 2021 denormalize => denormalize, 2022 nguard => addguard); 2023 end if; 2024 return fpresult; 2025 end function add; 2026 2027 -- Subtraction, Calls "add". 2028 function subtract ( 2029 l, r : UNRESOLVED_float; -- floating point input 2030 constant round_style : round_type := float_round_style; -- rounding option 2031 constant guard : NATURAL := float_guard_bits; -- number of guard bits 2032 constant check_error : BOOLEAN := float_check_error; -- check for errors 2033 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 2034 return UNRESOLVED_float is 2035 variable negr : UNRESOLVED_float (r'range); -- negative version of r 2036 begin 2037 negr := -r; 2038 return add (l => l, 2039 r => negr, 2040 round_style => round_style, 2041 guard => guard, 2042 check_error => check_error, 2043 denormalize => denormalize); 2044 end function subtract; 2045 2046 -- Floating point multiply 2047 function multiply ( 2048 l, r : UNRESOLVED_float; -- floating point input 2049 constant round_style : round_type := float_round_style; -- rounding option 2050 constant guard : NATURAL := float_guard_bits; -- number of guard bits 2051 constant check_error : BOOLEAN := float_check_error; -- check for errors 2052 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 2053 return UNRESOLVED_float is 2054 constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction 2055 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 2056 constant multguard : NATURAL := guard; -- guard bits 2057 variable lfptype, rfptype : valid_fpstate; 2058 variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); 2059 variable fractl, fractr : UNSIGNED (fraction_width downto 0); -- fractions 2060 variable rfract : UNSIGNED ((2*(fraction_width))+1 downto 0); -- result fraction 2061 variable sfract : UNSIGNED (fraction_width+1+multguard downto 0); -- result fraction 2062 variable shifty : INTEGER; -- denormal shift 2063 variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents 2064 variable rexpon : SIGNED (exponent_width+1 downto 0); -- result exponent 2065 variable fp_sign : STD_ULOGIC; -- sign of result 2066 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 2067 variable sticky : STD_ULOGIC; -- Holds precision for rounding 2068 begin -- multiply 2069 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 2070 lfptype := isx; 2071 else 2072 lfptype := classfp (l, check_error); 2073 rfptype := classfp (r, check_error); 2074 end if; 2075 if (lfptype = isx or rfptype = isx) then 2076 fpresult := (others => 'X'); 2077 elsif ((lfptype = nan or lfptype = quiet_nan or 2078 rfptype = nan or rfptype = quiet_nan)) then 2079 -- Return quiet NAN, IEEE754-1985-7.1,1 2080 fpresult := qnanfp (fraction_width => fraction_width, 2081 exponent_width => exponent_width); 2082 elsif (((lfptype = pos_inf or lfptype = neg_inf) and 2083 (rfptype = pos_zero or rfptype = neg_zero)) or 2084 ((rfptype = pos_inf or rfptype = neg_inf) and 2085 (lfptype = pos_zero or lfptype = neg_zero))) then -- 0 * inf 2086 -- Return quiet NAN, IEEE754-1985-7.1,3 2087 fpresult := qnanfp (fraction_width => fraction_width, 2088 exponent_width => exponent_width); 2089 elsif (lfptype = pos_inf or rfptype = pos_inf 2090 or lfptype = neg_inf or rfptype = neg_inf) then -- x * inf = inf 2091 fpresult := pos_inffp (fraction_width => fraction_width, 2092 exponent_width => exponent_width); 2093 -- figure out the sign 2094 fp_sign := l(l'high) xor r(r'high); -- figure out the sign 2095 fpresult (exponent_width) := fp_sign; 2096 else 2097 fp_sign := l(l'high) xor r(r'high); -- figure out the sign 2098 lresize := resize (arg => to_x01(l), 2099 exponent_width => exponent_width, 2100 fraction_width => fraction_width, 2101 denormalize_in => denormalize, 2102 denormalize => denormalize); 2103 lfptype := classfp (lresize, false); -- errors already checked 2104 rresize := resize (arg => to_x01(r), 2105 exponent_width => exponent_width, 2106 fraction_width => fraction_width, 2107 denormalize_in => denormalize, 2108 denormalize => denormalize); 2109 rfptype := classfp (rresize, false); -- errors already checked 2110 break_number ( 2111 arg => lresize, 2112 fptyp => lfptype, 2113 denormalize => denormalize, 2114 fract => fractl, 2115 expon => exponl); 2116 break_number ( 2117 arg => rresize, 2118 fptyp => rfptype, 2119 denormalize => denormalize, 2120 fract => fractr, 2121 expon => exponr); 2122 if (rfptype = pos_denormal or rfptype = neg_denormal) then 2123 shifty := fraction_width - find_leftmost(fractr, '1'); 2124 fractr := shift_left (fractr, shifty); 2125 elsif (lfptype = pos_denormal or lfptype = neg_denormal) then 2126 shifty := fraction_width - find_leftmost(fractl, '1'); 2127 fractl := shift_left (fractl, shifty); 2128 else 2129 shifty := 0; 2130 -- Note that a denormal number * a denormal number is always zero. 2131 end if; 2132 -- multiply 2133 -- add the exponents 2134 rexpon := resize (exponl, rexpon'length) + exponr - shifty + 1; 2135 rfract := fractl * fractr; -- Multiply the fraction 2136 sfract := rfract (rfract'high downto 2137 rfract'high - (fraction_width+1+multguard)); 2138 sticky := or_reduce (rfract (rfract'high-(fraction_width+1+multguard) 2139 downto 0)); 2140 -- normalize 2141 fpresult := normalize (fract => sfract, 2142 expon => rexpon, 2143 sign => fp_sign, 2144 sticky => sticky, 2145 fraction_width => fraction_width, 2146 exponent_width => exponent_width, 2147 round_style => round_style, 2148 denormalize => denormalize, 2149 nguard => multguard); 2150 end if; 2151 return fpresult; 2152 end function multiply; 2153 2154 function short_divide ( 2155 lx, rx : UNSIGNED) 2156 return UNSIGNED is 2157 -- This is a special divider for the floating point routines. 2158 -- For a true unsigned divider, "stages" needs to = lx'high 2159 constant stages : INTEGER := lx'high - rx'high; -- number of stages 2160 variable partial : UNSIGNED (lx'range); 2161 variable q : UNSIGNED (stages downto 0); 2162 variable partial_argl : SIGNED (rx'high + 2 downto 0); 2163 variable partial_arg : SIGNED (rx'high + 2 downto 0); 2164 begin 2165 partial := lx; 2166 for i in stages downto 0 loop 2167 partial_argl := resize ("0" & SIGNED (partial(lx'high downto i)), 2168 partial_argl'length); 2169 partial_arg := partial_argl - SIGNED ("0" & rx); 2170 if (partial_arg (partial_arg'high) = '1') then -- negative 2171 q(i) := '0'; 2172 else 2173 q(i) := '1'; 2174 partial (lx'high+i-stages downto lx'high+i-stages-rx'high) := 2175 UNSIGNED (partial_arg(rx'range)); 2176 end if; 2177 end loop; 2178 -- to make the output look like that of the unsigned IEEE divide. 2179 return resize (q, lx'length); 2180 end function short_divide; 2181 2182 -- 1/X function. Needed for algorithm development. 2183 function reciprocal ( 2184 arg : UNRESOLVED_float; 2185 constant round_style : round_type := float_round_style; -- rounding option 2186 constant guard : NATURAL := float_guard_bits; -- number of guard bits 2187 constant check_error : BOOLEAN := float_check_error; -- check for errors 2188 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 2189 return UNRESOLVED_float is 2190 constant fraction_width : NATURAL := -mine(arg'low, arg'low); -- length of FP output fraction 2191 constant exponent_width : NATURAL := arg'high; -- length of FP output exponent 2192 constant divguard : NATURAL := guard; -- guard bits 2193 function onedivy ( 2194 arg : UNSIGNED) 2195 return UNSIGNED is 2196 variable q : UNSIGNED((2*arg'high)+1 downto 0); 2197 variable one : UNSIGNED (q'range); 2198 begin 2199 one := (others => '0'); 2200 one(one'high) := '1'; 2201 q := short_divide (one, arg); -- Unsigned divide 2202 return resize (q, arg'length+1); 2203 end function onedivy; 2204 variable fptype : valid_fpstate; 2205 variable expon : SIGNED (exponent_width-1 downto 0); -- exponents 2206 variable denorm_offset : NATURAL range 0 to 2; 2207 variable fract : UNSIGNED (fraction_width downto 0); 2208 variable fractg : UNSIGNED (fraction_width+divguard downto 0); 2209 variable sfract : UNSIGNED (fraction_width+1+divguard downto 0); -- result fraction 2210 variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); 2211 begin -- reciprocal 2212 fptype := classfp(arg, check_error); 2213 classcase : case fptype is 2214 when isx => 2215 fpresult := (others => 'X'); 2216 when nan | quiet_nan => 2217 -- Return quiet NAN, IEEE754-1985-7.1,1 2218 fpresult := qnanfp (fraction_width => fraction_width, 2219 exponent_width => exponent_width); 2220 when pos_inf | neg_inf => -- 1/inf, return 0 2221 fpresult := zerofp (fraction_width => fraction_width, 2222 exponent_width => exponent_width); 2223 when neg_zero | pos_zero => -- 1/0 2224 report float_pkg'instance_name 2225 & "RECIPROCAL: Floating Point divide by zero" 2226 severity error; 2227 fpresult := pos_inffp (fraction_width => fraction_width, 2228 exponent_width => exponent_width); 2229 when others => 2230 if (fptype = pos_denormal or fptype = neg_denormal) 2231 and ((arg (-1) or arg(-2)) /= '1') then 2232 -- 1/denormal = infinity, with the exception of 2**-expon_base 2233 fpresult := pos_inffp (fraction_width => fraction_width, 2234 exponent_width => exponent_width); 2235 fpresult (exponent_width) := to_x01 (arg (exponent_width)); 2236 else 2237 break_number ( 2238 arg => arg, 2239 fptyp => fptype, 2240 denormalize => denormalize, 2241 fract => fract, 2242 expon => expon); 2243 fractg := (others => '0'); 2244 if (fptype = pos_denormal or fptype = neg_denormal) then 2245 -- The reciprocal of a denormal number is typically zero, 2246 -- except for two special cases which are trapped here. 2247 if (to_x01(arg (-1)) = '1') then 2248 fractg (fractg'high downto divguard+1) := 2249 fract (fract'high-1 downto 0); -- Shift to not denormal 2250 denorm_offset := 1; -- add 1 to exponent compensate 2251 else -- arg(-2) = '1' 2252 fractg (fractg'high downto divguard+2) := 2253 fract (fract'high-2 downto 0); -- Shift to not denormal 2254 denorm_offset := 2; -- add 2 to exponent compensate 2255 end if; 2256 else 2257 fractg (fractg'high downto divguard) := fract; 2258 denorm_offset := 0; 2259 end if; 2260 expon := - expon - 3 + denorm_offset; 2261 sfract := onedivy (fractg); 2262 -- normalize 2263 fpresult := normalize (fract => sfract, 2264 expon => expon, 2265 sign => arg(exponent_width), 2266 sticky => '1', 2267 fraction_width => fraction_width, 2268 exponent_width => exponent_width, 2269 round_style => round_style, 2270 denormalize => denormalize, 2271 nguard => divguard); 2272 end if; 2273 end case classcase; 2274 return fpresult; 2275 end function reciprocal; 2276 2277 -- floating point division 2278 function divide ( 2279 l, r : UNRESOLVED_float; -- floating point input 2280 constant round_style : round_type := float_round_style; -- rounding option 2281 constant guard : NATURAL := float_guard_bits; -- number of guard bits 2282 constant check_error : BOOLEAN := float_check_error; -- check for errors 2283 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 2284 return UNRESOLVED_float is 2285 constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction 2286 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 2287 constant divguard : NATURAL := guard; -- division guard bits 2288 variable lfptype, rfptype : valid_fpstate; 2289 variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); 2290 variable ulfract, urfract : UNSIGNED (fraction_width downto 0); 2291 variable fractl : UNSIGNED ((2*(fraction_width+divguard)+1) downto 0); -- left 2292 variable fractr : UNSIGNED (fraction_width+divguard downto 0); -- right 2293 variable rfract : UNSIGNED (fractl'range); -- result fraction 2294 variable sfract : UNSIGNED (fraction_width+1+divguard downto 0); -- result fraction 2295 variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents 2296 variable rexpon : SIGNED (exponent_width+1 downto 0); -- result exponent 2297 variable fp_sign, sticky : STD_ULOGIC; -- sign of result 2298 variable shifty, shiftx : INTEGER; -- denormal number shift 2299 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 2300 begin -- divide 2301 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 2302 lfptype := isx; 2303 else 2304 lfptype := classfp (l, check_error); 2305 rfptype := classfp (r, check_error); 2306 end if; 2307 classcase : case rfptype is 2308 when isx => 2309 fpresult := (others => 'X'); 2310 when nan | quiet_nan => 2311 -- Return quiet NAN, IEEE754-1985-7.1,1 2312 fpresult := qnanfp (fraction_width => fraction_width, 2313 exponent_width => exponent_width); 2314 when pos_inf | neg_inf => 2315 if lfptype = pos_inf or lfptype = neg_inf -- inf / inf 2316 or lfptype = quiet_nan or lfptype = nan then 2317 -- Return quiet NAN, IEEE754-1985-7.1,4 2318 fpresult := qnanfp (fraction_width => fraction_width, 2319 exponent_width => exponent_width); 2320 else -- x / inf = 0 2321 fpresult := zerofp (fraction_width => fraction_width, 2322 exponent_width => exponent_width); 2323 fp_sign := l(l'high) xor r(r'high); -- sign 2324 fpresult (fpresult'high) := fp_sign; -- sign 2325 end if; 2326 when pos_zero | neg_zero => 2327 if lfptype = pos_zero or lfptype = neg_zero -- 0 / 0 2328 or lfptype = quiet_nan or lfptype = nan then 2329 -- Return quiet NAN, IEEE754-1985-7.1,4 2330 fpresult := qnanfp (fraction_width => fraction_width, 2331 exponent_width => exponent_width); 2332 else 2333 report float_pkg'instance_name 2334 & "DIVIDE: Floating Point divide by zero" 2335 severity error; 2336 -- Infinity, define in 754-1985-7.2 2337 fpresult := pos_inffp (fraction_width => fraction_width, 2338 exponent_width => exponent_width); 2339 fp_sign := l(l'high) xor r(r'high); -- sign 2340 fpresult (fpresult'high) := fp_sign; -- sign 2341 end if; 2342 when others => 2343 classcase2 : case lfptype is 2344 when isx => 2345 fpresult := (others => 'X'); 2346 when nan | quiet_nan => 2347 -- Return quiet NAN, IEEE754-1985-7.1,1 2348 fpresult := qnanfp (fraction_width => fraction_width, 2349 exponent_width => exponent_width); 2350 when pos_inf | neg_inf => -- inf / x = inf 2351 fpresult := pos_inffp (fraction_width => fraction_width, 2352 exponent_width => exponent_width); 2353 fp_sign := l(l'high) xor r(r'high); -- sign 2354 fpresult(exponent_width) := fp_sign; 2355 when pos_zero | neg_zero => -- 0 / X = 0 2356 fpresult := zerofp (fraction_width => fraction_width, 2357 exponent_width => exponent_width); 2358 fp_sign := l(l'high) xor r(r'high); -- sign 2359 fpresult(exponent_width) := fp_sign; 2360 when others => 2361 fp_sign := l(l'high) xor r(r'high); -- sign 2362 lresize := resize (arg => to_x01(l), 2363 exponent_width => exponent_width, 2364 fraction_width => fraction_width, 2365 denormalize_in => denormalize, 2366 denormalize => denormalize); 2367 lfptype := classfp (lresize, false); -- errors already checked 2368 rresize := resize (arg => to_x01(r), 2369 exponent_width => exponent_width, 2370 fraction_width => fraction_width, 2371 denormalize_in => denormalize, 2372 denormalize => denormalize); 2373 rfptype := classfp (rresize, false); -- errors already checked 2374 break_number ( 2375 arg => lresize, 2376 fptyp => lfptype, 2377 denormalize => denormalize, 2378 fract => ulfract, 2379 expon => exponl); 2380 -- right side 2381 break_number ( 2382 arg => rresize, 2383 fptyp => rfptype, 2384 denormalize => denormalize, 2385 fract => urfract, 2386 expon => exponr); 2387 -- Compute the exponent 2388 rexpon := resize (exponl, rexpon'length) - exponr - 2; 2389 if (rfptype = pos_denormal or rfptype = neg_denormal) then 2390 -- Do the shifting here not after. That way we have a smaller 2391 -- shifter, and need a smaller divider, because the top 2392 -- bit in the divisor will always be a "1". 2393 shifty := fraction_width - find_leftmost(urfract, '1'); 2394 urfract := shift_left (urfract, shifty); 2395 rexpon := rexpon + shifty; 2396 end if; 2397 fractr := (others => '0'); 2398 fractr (fraction_width+divguard downto divguard) := urfract; 2399 if (lfptype = pos_denormal or lfptype = neg_denormal) then 2400 shiftx := fraction_width - find_leftmost(ulfract, '1'); 2401 ulfract := shift_left (ulfract, shiftx); 2402 rexpon := rexpon - shiftx; 2403 end if; 2404 fractl := (others => '0'); 2405 fractl (fractl'high downto fractl'high-fraction_width) := ulfract; 2406 -- divide 2407 rfract := short_divide (fractl, fractr); -- unsigned divide 2408 sfract := rfract (sfract'range); -- lower bits 2409 sticky := '1'; 2410 -- normalize 2411 fpresult := normalize (fract => sfract, 2412 expon => rexpon, 2413 sign => fp_sign, 2414 sticky => sticky, 2415 fraction_width => fraction_width, 2416 exponent_width => exponent_width, 2417 round_style => round_style, 2418 denormalize => denormalize, 2419 nguard => divguard); 2420 end case classcase2; 2421 end case classcase; 2422 return fpresult; 2423 end function divide; 2424 2425 -- division by a power of 2 2426 function dividebyp2 ( 2427 l, r : UNRESOLVED_float; -- floating point input 2428 constant round_style : round_type := float_round_style; -- rounding option 2429 constant guard : NATURAL := float_guard_bits; -- number of guard bits 2430 constant check_error : BOOLEAN := float_check_error; -- check for errors 2431 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 2432 return UNRESOLVED_float is 2433 constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction 2434 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 2435 variable lfptype, rfptype : valid_fpstate; 2436 variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); 2437 variable ulfract, urfract : UNSIGNED (fraction_width downto 0); 2438 variable exponl, exponr : SIGNED(exponent_width-1 downto 0); -- exponents 2439 variable rexpon : SIGNED(exponent_width downto 0); -- result exponent 2440 variable fp_sign : STD_ULOGIC; -- sign of result 2441 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 2442 begin -- divisionbyp2 2443 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 2444 lfptype := isx; 2445 else 2446 lfptype := classfp (l, check_error); 2447 rfptype := classfp (r, check_error); 2448 end if; 2449 classcase : case rfptype is 2450 when isx => 2451 fpresult := (others => 'X'); 2452 when nan | quiet_nan => 2453 -- Return quiet NAN, IEEE754-1985-7.1,1 2454 fpresult := qnanfp (fraction_width => fraction_width, 2455 exponent_width => exponent_width); 2456 when pos_inf | neg_inf => 2457 if lfptype = pos_inf or lfptype = neg_inf then -- inf / inf 2458 -- Return quiet NAN, IEEE754-1985-7.1,4 2459 fpresult := qnanfp (fraction_width => fraction_width, 2460 exponent_width => exponent_width); 2461 else -- x / inf = 0 2462 fpresult := zerofp (fraction_width => fraction_width, 2463 exponent_width => exponent_width); 2464 fp_sign := l(l'high) xor r(r'high); -- sign 2465 fpresult (fpresult'high) := fp_sign; -- sign 2466 end if; 2467 when pos_zero | neg_zero => 2468 if lfptype = pos_zero or lfptype = neg_zero then -- 0 / 0 2469 -- Return quiet NAN, IEEE754-1985-7.1,4 2470 fpresult := qnanfp (fraction_width => fraction_width, 2471 exponent_width => exponent_width); 2472 else 2473 report float_pkg'instance_name 2474 & "DIVIDEBYP2: Floating Point divide by zero" 2475 severity error; 2476 -- Infinity, define in 754-1985-7.2 2477 fpresult := pos_inffp (fraction_width => fraction_width, 2478 exponent_width => exponent_width); 2479 fp_sign := l(l'high) xor r(r'high); -- sign 2480 fpresult (fpresult'high) := fp_sign; -- sign 2481 end if; 2482 when others => 2483 classcase2 : case lfptype is 2484 when isx => 2485 fpresult := (others => 'X'); 2486 when nan | quiet_nan => 2487 -- Return quiet NAN, IEEE754-1985-7.1,1 2488 fpresult := qnanfp (fraction_width => fraction_width, 2489 exponent_width => exponent_width); 2490 when pos_inf | neg_inf => -- inf / x = inf 2491 fpresult := pos_inffp (fraction_width => fraction_width, 2492 exponent_width => exponent_width); 2493 fp_sign := l(l'high) xor r(r'high); -- sign 2494 fpresult (exponent_width) := fp_sign; -- sign 2495 when pos_zero | neg_zero => -- 0 / X = 0 2496 fpresult := zerofp (fraction_width => fraction_width, 2497 exponent_width => exponent_width); 2498 fp_sign := l(l'high) xor r(r'high); -- sign 2499 fpresult (exponent_width) := fp_sign; -- sign 2500 when others => 2501 fp_sign := l(l'high) xor r(r'high); -- sign 2502 lresize := resize (arg => to_x01(l), 2503 exponent_width => exponent_width, 2504 fraction_width => fraction_width, 2505 denormalize_in => denormalize, 2506 denormalize => denormalize); 2507 lfptype := classfp (lresize, false); -- errors already checked 2508 rresize := resize (arg => to_x01(r), 2509 exponent_width => exponent_width, 2510 fraction_width => fraction_width, 2511 denormalize_in => denormalize, 2512 denormalize => denormalize); 2513 rfptype := classfp (rresize, false); -- errors already checked 2514 break_number ( 2515 arg => lresize, 2516 fptyp => lfptype, 2517 denormalize => denormalize, 2518 fract => ulfract, 2519 expon => exponl); 2520 -- right side 2521 break_number ( 2522 arg => rresize, 2523 fptyp => rfptype, 2524 denormalize => denormalize, 2525 fract => urfract, 2526 expon => exponr); 2527 assert (or_reduce (urfract (fraction_width-1 downto 0)) = '0') 2528 report float_pkg'instance_name 2529 & "DIVIDEBYP2: " 2530 & "Dividebyp2 called with a non power of two divisor" 2531 severity error; 2532 rexpon := (exponl(exponl'high)&exponl) 2533 - (exponr(exponr'high)&exponr) - 1; 2534 -- normalize 2535 fpresult := normalize (fract => ulfract, 2536 expon => rexpon, 2537 sign => fp_sign, 2538 sticky => '1', 2539 fraction_width => fraction_width, 2540 exponent_width => exponent_width, 2541 round_style => round_style, 2542 denormalize => denormalize, 2543 nguard => 0); 2544 end case classcase2; 2545 end case classcase; 2546 return fpresult; 2547 end function dividebyp2; 2548 2549 -- Multiply accumulate result = l*r + c 2550 function mac ( 2551 l, r, c : UNRESOLVED_float; -- floating point input 2552 constant round_style : round_type := float_round_style; -- rounding option 2553 constant guard : NATURAL := float_guard_bits; -- number of guard bits 2554 constant check_error : BOOLEAN := float_check_error; -- check for errors 2555 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 2556 return UNRESOLVED_float is 2557 constant fraction_width : NATURAL := 2558 -mine (mine(l'low, r'low), c'low); -- length of FP output fraction 2559 constant exponent_width : NATURAL := 2560 maximum (maximum(l'high, r'high), c'high); -- length of FP output exponent 2561 variable lfptype, rfptype, cfptype : valid_fpstate; 2562 variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); 2563 variable fractl, fractr : UNSIGNED (fraction_width downto 0); -- fractions 2564 variable fractx : UNSIGNED (fraction_width+guard downto 0); 2565 variable fractc, fracts : UNSIGNED (fraction_width+1+guard downto 0); 2566 variable rfract : UNSIGNED ((2*(fraction_width))+1 downto 0); -- result fraction 2567 variable sfract, ufract : UNSIGNED (fraction_width+1+guard downto 0); -- result fraction 2568 variable exponl, exponr, exponc : SIGNED (exponent_width-1 downto 0); -- exponents 2569 variable rexpon, rexpon2 : SIGNED (exponent_width+1 downto 0); -- result exponent 2570 variable shifty : INTEGER; -- denormal shift 2571 variable shiftx : SIGNED (rexpon'range); -- shift fractions 2572 variable fp_sign : STD_ULOGIC; -- sign of result 2573 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 2574 variable cresize : UNRESOLVED_float (exponent_width downto -fraction_width - guard); 2575 variable leftright : BOOLEAN; -- left or right used 2576 variable sticky : STD_ULOGIC; -- Holds precision for rounding 2577 begin -- multiply 2578 if (fraction_width = 0 or l'length < 7 or r'length < 7 or c'length < 7) then 2579 lfptype := isx; 2580 else 2581 lfptype := classfp (l, check_error); 2582 rfptype := classfp (r, check_error); 2583 cfptype := classfp (c, check_error); 2584 end if; 2585 if (lfptype = isx or rfptype = isx or cfptype = isx) then 2586 fpresult := (others => 'X'); 2587 elsif (lfptype = nan or lfptype = quiet_nan or 2588 rfptype = nan or rfptype = quiet_nan or 2589 cfptype = nan or cfptype = quiet_nan) then 2590 -- Return quiet NAN, IEEE754-1985-7.1,1 2591 fpresult := qnanfp (fraction_width => fraction_width, 2592 exponent_width => exponent_width); 2593 elsif (((lfptype = pos_inf or lfptype = neg_inf) and 2594 (rfptype = pos_zero or rfptype = neg_zero)) or 2595 ((rfptype = pos_inf or rfptype = neg_inf) and 2596 (lfptype = pos_zero or lfptype = neg_zero))) then -- 0 * inf 2597 -- Return quiet NAN, IEEE754-1985-7.1,3 2598 fpresult := qnanfp (fraction_width => fraction_width, 2599 exponent_width => exponent_width); 2600 elsif (lfptype = pos_inf or rfptype = pos_inf 2601 or lfptype = neg_inf or rfptype = neg_inf -- x * inf = inf 2602 or cfptype = neg_inf or cfptype = pos_inf) then -- x + inf = inf 2603 fpresult := pos_inffp (fraction_width => fraction_width, 2604 exponent_width => exponent_width); 2605 -- figure out the sign 2606 fpresult (exponent_width) := l(l'high) xor r(r'high); 2607 else 2608 fp_sign := l(l'high) xor r(r'high); -- figure out the sign 2609 lresize := resize (arg => to_x01(l), 2610 exponent_width => exponent_width, 2611 fraction_width => fraction_width, 2612 denormalize_in => denormalize, 2613 denormalize => denormalize); 2614 lfptype := classfp (lresize, false); -- errors already checked 2615 rresize := resize (arg => to_x01(r), 2616 exponent_width => exponent_width, 2617 fraction_width => fraction_width, 2618 denormalize_in => denormalize, 2619 denormalize => denormalize); 2620 rfptype := classfp (rresize, false); -- errors already checked 2621 cresize := resize (arg => to_x01(c), 2622 exponent_width => exponent_width, 2623 fraction_width => -cresize'low, 2624 denormalize_in => denormalize, 2625 denormalize => denormalize); 2626 cfptype := classfp (cresize, false); -- errors already checked 2627 break_number ( 2628 arg => lresize, 2629 fptyp => lfptype, 2630 denormalize => denormalize, 2631 fract => fractl, 2632 expon => exponl); 2633 break_number ( 2634 arg => rresize, 2635 fptyp => rfptype, 2636 denormalize => denormalize, 2637 fract => fractr, 2638 expon => exponr); 2639 break_number ( 2640 arg => cresize, 2641 fptyp => cfptype, 2642 denormalize => denormalize, 2643 fract => fractx, 2644 expon => exponc); 2645 if (rfptype = pos_denormal or rfptype = neg_denormal) then 2646 shifty := fraction_width - find_leftmost(fractr, '1'); 2647 fractr := shift_left (fractr, shifty); 2648 elsif (lfptype = pos_denormal or lfptype = neg_denormal) then 2649 shifty := fraction_width - find_leftmost(fractl, '1'); 2650 fractl := shift_left (fractl, shifty); 2651 else 2652 shifty := 0; 2653 -- Note that a denormal number * a denormal number is always zero. 2654 end if; 2655 -- multiply 2656 rfract := fractl * fractr; -- Multiply the fraction 2657 -- add the exponents 2658 rexpon := resize (exponl, rexpon'length) + exponr - shifty + 1; 2659 shiftx := rexpon - exponc; 2660 if shiftx < -fractl'high then 2661 rexpon2 := resize (exponc, rexpon2'length); 2662 fractc := "0" & fractx; 2663 fracts := (others => '0'); 2664 sticky := or_reduce (rfract); 2665 elsif shiftx < 0 then 2666 shiftx := - shiftx; 2667 fracts := shift_right (rfract (rfract'high downto rfract'high 2668 - fracts'length+1), 2669 to_integer(shiftx)); 2670 fractc := "0" & fractx; 2671 rexpon2 := resize (exponc, rexpon2'length); 2672 leftright := false; 2673 sticky := or_reduce (rfract (to_integer(shiftx)+rfract'high 2674 - fracts'length downto 0)); 2675 elsif shiftx = 0 then 2676 rexpon2 := resize (exponc, rexpon2'length); 2677 sticky := or_reduce (rfract (rfract'high - fractc'length downto 0)); 2678 if rfract (rfract'high downto rfract'high - fractc'length+1) > fractx 2679 then 2680 fractc := "0" & fractx; 2681 fracts := rfract (rfract'high downto rfract'high 2682 - fracts'length+1); 2683 leftright := false; 2684 else 2685 fractc := rfract (rfract'high downto rfract'high 2686 - fractc'length+1); 2687 fracts := "0" & fractx; 2688 leftright := true; 2689 end if; 2690 elsif shiftx > fractx'high then 2691 rexpon2 := rexpon; 2692 fracts := (others => '0'); 2693 fractc := rfract (rfract'high downto rfract'high - fractc'length+1); 2694 leftright := true; 2695 sticky := or_reduce (fractx & rfract (rfract'high - fractc'length 2696 downto 0)); 2697 else -- fractx'high > shiftx > 0 2698 rexpon2 := rexpon; 2699 fracts := "0" & shift_right (fractx, to_integer (shiftx)); 2700 fractc := rfract (rfract'high downto rfract'high - fractc'length+1); 2701 leftright := true; 2702 sticky := or_reduce (fractx (to_integer (shiftx) downto 0) 2703 & rfract (rfract'high - fractc'length downto 0)); 2704 end if; 2705 fracts (0) := fracts (0) or sticky; -- Or the sticky bit into the LSB 2706 if fp_sign = to_X01(c(c'high)) then 2707 ufract := fractc + fracts; 2708 fp_sign := fp_sign; 2709 else -- signs are different 2710 ufract := fractc - fracts; -- always positive result 2711 if leftright then -- Figure out which sign to use 2712 fp_sign := fp_sign; 2713 else 2714 fp_sign := c(c'high); 2715 end if; 2716 end if; 2717 -- normalize 2718 fpresult := normalize (fract => ufract, 2719 expon => rexpon2, 2720 sign => fp_sign, 2721 sticky => sticky, 2722 fraction_width => fraction_width, 2723 exponent_width => exponent_width, 2724 round_style => round_style, 2725 denormalize => denormalize, 2726 nguard => guard); 2727 end if; 2728 return fpresult; 2729 end function mac; 2730 2731 -- "rem" function 2732 function remainder ( 2733 l, r : UNRESOLVED_float; -- floating point input 2734 constant round_style : round_type := float_round_style; -- rounding option 2735 constant guard : NATURAL := float_guard_bits; -- number of guard bits 2736 constant check_error : BOOLEAN := float_check_error; -- check for errors 2737 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 2738 return UNRESOLVED_float is 2739 constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction 2740 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 2741 constant divguard : NATURAL := guard; -- division guard bits 2742 variable lfptype, rfptype : valid_fpstate; 2743 variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); 2744 variable ulfract, urfract : UNSIGNED (fraction_width downto 0); 2745 variable fractr, fractl : UNSIGNED (fraction_width+divguard downto 0); -- right 2746 variable rfract : UNSIGNED (fractr'range); -- result fraction 2747 variable sfract : UNSIGNED (fraction_width+divguard downto 0); -- result fraction 2748 variable exponl, exponr : SIGNED (exponent_width-1 downto 0); -- exponents 2749 variable rexpon : SIGNED (exponent_width downto 0); -- result exponent 2750 variable fp_sign : STD_ULOGIC; -- sign of result 2751 variable shifty : INTEGER; -- denormal number shift 2752 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 2753 begin -- remainder 2754 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 2755 lfptype := isx; 2756 else 2757 lfptype := classfp (l, check_error); 2758 rfptype := classfp (r, check_error); 2759 end if; 2760 if (lfptype = isx or rfptype = isx) then 2761 fpresult := (others => 'X'); 2762 elsif (lfptype = nan or lfptype = quiet_nan) 2763 or (rfptype = nan or rfptype = quiet_nan) 2764 -- Return quiet NAN, IEEE754-1985-7.1,1 2765 or (lfptype = pos_inf or lfptype = neg_inf) -- inf rem x 2766 -- Return quiet NAN, IEEE754-1985-7.1,5 2767 or (rfptype = pos_zero or rfptype = neg_zero) then -- x rem 0 2768 -- Return quiet NAN, IEEE754-1985-7.1,5 2769 fpresult := qnanfp (fraction_width => fraction_width, 2770 exponent_width => exponent_width); 2771 elsif (rfptype = pos_inf or rfptype = neg_inf) then -- x rem inf = 0 2772 fpresult := zerofp (fraction_width => fraction_width, 2773 exponent_width => exponent_width); 2774 elsif (abs(l) < abs(r)) then 2775 fpresult := l; 2776 else 2777 fp_sign := to_X01(l(l'high)); -- sign 2778 lresize := resize (arg => to_x01(l), 2779 exponent_width => exponent_width, 2780 fraction_width => fraction_width, 2781 denormalize_in => denormalize, 2782 denormalize => denormalize); 2783 lfptype := classfp (lresize, false); -- errors already checked 2784 rresize := resize (arg => to_x01(r), 2785 exponent_width => exponent_width, 2786 fraction_width => fraction_width, 2787 denormalize_in => denormalize, 2788 denormalize => denormalize); 2789 rfptype := classfp (rresize, false); -- errors already checked 2790 fractl := (others => '0'); 2791 break_number ( 2792 arg => lresize, 2793 fptyp => lfptype, 2794 denormalize => denormalize, 2795 fract => ulfract, 2796 expon => exponl); 2797 fractl (fraction_width+divguard downto divguard) := ulfract; 2798 -- right side 2799 fractr := (others => '0'); 2800 break_number ( 2801 arg => rresize, 2802 fptyp => rfptype, 2803 denormalize => denormalize, 2804 fract => urfract, 2805 expon => exponr); 2806 fractr (fraction_width+divguard downto divguard) := urfract; 2807 rexpon := (exponr(exponr'high)&exponr); 2808 shifty := to_integer(exponl - rexpon); 2809 if (shifty > 0) then 2810 fractr := shift_right (fractr, shifty); 2811 rexpon := rexpon + shifty; 2812 end if; 2813 if (fractr /= 0) then 2814 -- rem 2815 rfract := fractl rem fractr; -- unsigned rem 2816 sfract := rfract (sfract'range); -- lower bits 2817 -- normalize 2818 fpresult := normalize (fract => sfract, 2819 expon => rexpon, 2820 sign => fp_sign, 2821 fraction_width => fraction_width, 2822 exponent_width => exponent_width, 2823 round_style => round_style, 2824 denormalize => denormalize, 2825 nguard => divguard); 2826 else 2827 -- If we shift "fractr" so far that it becomes zero, return zero. 2828 fpresult := zerofp (fraction_width => fraction_width, 2829 exponent_width => exponent_width); 2830 end if; 2831 end if; 2832 return fpresult; 2833 end function remainder; 2834 2835 -- "mod" function 2836 function modulo ( 2837 l, r : UNRESOLVED_float; -- floating point input 2838 constant round_style : round_type := float_round_style; -- rounding option 2839 constant guard : NATURAL := float_guard_bits; -- number of guard bits 2840 constant check_error : BOOLEAN := float_check_error; -- check for errors 2841 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 2842 return UNRESOLVED_float is 2843 constant fraction_width : NATURAL := - mine(l'low, r'low); -- length of FP output fraction 2844 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 2845 variable lfptype, rfptype : valid_fpstate; 2846 variable fpresult : UNRESOLVED_float (exponent_width downto -fraction_width); 2847 variable remres : UNRESOLVED_float (exponent_width downto -fraction_width); 2848 begin -- remainder 2849 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 2850 lfptype := isx; 2851 else 2852 lfptype := classfp (l, check_error); 2853 rfptype := classfp (r, check_error); 2854 end if; 2855 if (lfptype = isx or rfptype = isx) then 2856 fpresult := (others => 'X'); 2857 elsif (lfptype = nan or lfptype = quiet_nan) 2858 or (rfptype = nan or rfptype = quiet_nan) 2859 -- Return quiet NAN, IEEE754-1985-7.1,1 2860 or (lfptype = pos_inf or lfptype = neg_inf) -- inf rem x 2861 -- Return quiet NAN, IEEE754-1985-7.1,5 2862 or (rfptype = pos_zero or rfptype = neg_zero) then -- x rem 0 2863 -- Return quiet NAN, IEEE754-1985-7.1,5 2864 fpresult := qnanfp (fraction_width => fraction_width, 2865 exponent_width => exponent_width); 2866 elsif (rfptype = pos_inf or rfptype = neg_inf) then -- x rem inf = 0 2867 fpresult := zerofp (fraction_width => fraction_width, 2868 exponent_width => exponent_width); 2869 else 2870 remres := remainder (l => abs(l), 2871 r => abs(r), 2872 round_style => round_style, 2873 guard => guard, 2874 check_error => false, 2875 denormalize => denormalize); 2876 -- MOD is the same as REM, but you do something different with 2877 -- negative values 2878 if (is_negative (l)) then 2879 remres := - remres; 2880 end if; 2881 if (is_negative (l) = is_negative (r) or remres = 0) then 2882 fpresult := remres; 2883 else 2884 fpresult := add (l => remres, 2885 r => r, 2886 round_style => round_style, 2887 guard => guard, 2888 check_error => false, 2889 denormalize => denormalize); 2890 end if; 2891 end if; 2892 return fpresult; 2893 end function modulo; 2894 2895 -- Square root of a floating point number. Done using Newton's Iteration. 2896 function sqrt ( 2897 arg : UNRESOLVED_float; -- floating point input 2898 constant round_style : round_type := float_round_style; 2899 constant guard : NATURAL := float_guard_bits; 2900 constant check_error : BOOLEAN := float_check_error; 2901 constant denormalize : BOOLEAN := float_denormalize) 2902 return UNRESOLVED_float is 2903 constant fraction_width : NATURAL := guard-arg'low; -- length of FP output fraction 2904 constant exponent_width : NATURAL := arg'high; -- length of FP output exponent 2905 variable sign : STD_ULOGIC; 2906 variable fpresult : float (arg'range); 2907 variable fptype : valid_fpstate; 2908 variable iexpon : SIGNED(exponent_width-1 downto 0); -- exponents 2909 variable expon : SIGNED(exponent_width downto 0); -- exponents 2910 variable ufact : ufixed (0 downto arg'low); 2911 variable fact : ufixed (2 downto -fraction_width); -- fraction 2912 variable resb : ufixed (fact'high+1 downto fact'low); 2913 begin -- square root 2914 fptype := Classfp (arg, check_error); 2915 classcase : case fptype is 2916 when isx => 2917 fpresult := (others => 'X'); 2918 when nan | quiet_nan | 2919 -- Return quiet NAN, IEEE754-1985-7.1,1 2920 neg_normal | neg_denormal | neg_inf => -- sqrt (neg) 2921 -- Return quiet NAN, IEEE754-1985-7.1.6 2922 fpresult := qnanfp (fraction_width => fraction_width-guard, 2923 exponent_width => exponent_width); 2924 when pos_inf => -- Sqrt (inf), return infinity 2925 fpresult := pos_inffp (fraction_width => fraction_width-guard, 2926 exponent_width => exponent_width); 2927 when pos_zero => -- return 0 2928 fpresult := zerofp (fraction_width => fraction_width-guard, 2929 exponent_width => exponent_width); 2930 when neg_zero => -- IEEE754-1985-6.3 return -0 2931 fpresult := neg_zerofp (fraction_width => fraction_width-guard, 2932 exponent_width => exponent_width); 2933 when others => 2934 break_number (arg => arg, 2935 denormalize => denormalize, 2936 check_error => false, 2937 fract => ufact, 2938 expon => iexpon, 2939 sign => sign); 2940 expon := resize (iexpon+1, expon'length); -- get exponent 2941 fact := resize (ufact, fact'high, fact'low); 2942 if (expon(0) = '1') then 2943 fact := fact sla 1; -- * 2.0 2944 end if; 2945 expon := shift_right (expon, 1); -- exponent/2 2946 -- Newton's iteration - root := (1 + arg) / 2 2947 resb := (fact + 1) sra 1; 2948 for j in 0 to fraction_width/4 loop 2949 -- root := (root + (arg/root))/2 2950 resb := resize (arg => (resb + (fact/resb)) sra 1, 2951 left_index => resb'high, 2952 right_index => resb'low, 2953 round_style => fixed_truncate, 2954 overflow_style => fixed_wrap); 2955 end loop; 2956 fpresult := normalize (fract => resb, 2957 expon => expon-1, 2958 sign => '0', 2959 exponent_width => arg'high, 2960 fraction_width => -arg'low, 2961 round_style => round_style, 2962 denormalize => denormalize, 2963 nguard => guard); 2964 end case classcase; 2965 return fpresult; 2966 end function sqrt; 2967 2968 function Is_Negative (arg : UNRESOLVED_float) return BOOLEAN is 2969 -- Technically -0 should return "false", but I'm leaving that case out. 2970 begin 2971 return (to_x01(arg(arg'high)) = '1'); 2972 end function Is_Negative; 2973 2974 -- compare functions 2975 -- =, /=, >=, <=, <, > 2976 2977 function eq ( -- equal = 2978 l, r : UNRESOLVED_float; -- floating point input 2979 constant check_error : BOOLEAN := float_check_error; 2980 constant denormalize : BOOLEAN := float_denormalize) 2981 return BOOLEAN is 2982 variable lfptype, rfptype : valid_fpstate; 2983 variable is_equal, is_unordered : BOOLEAN; 2984 constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction 2985 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 2986 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 2987 begin -- equal 2988 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 2989 return false; 2990 else 2991 lfptype := classfp (l, check_error); 2992 rfptype := classfp (r, check_error); 2993 end if; 2994 if (lfptype = neg_zero or lfptype = pos_zero) and 2995 (rfptype = neg_zero or rfptype = pos_zero) then 2996 is_equal := true; 2997 else 2998 lresize := resize (arg => to_x01(l), 2999 exponent_width => exponent_width, 3000 fraction_width => fraction_width, 3001 denormalize_in => denormalize, 3002 denormalize => denormalize); 3003 rresize := resize (arg => to_x01(r), 3004 exponent_width => exponent_width, 3005 fraction_width => fraction_width, 3006 denormalize_in => denormalize, 3007 denormalize => denormalize); 3008 is_equal := (to_slv(lresize) = to_slv(rresize)); 3009 end if; 3010 if (check_error) then 3011 is_unordered := Unordered (x => l, 3012 y => r); 3013 else 3014 is_unordered := false; 3015 end if; 3016 return is_equal and not is_unordered; 3017 end function eq; 3018 3019 function lt ( -- less than < 3020 l, r : UNRESOLVED_float; -- floating point input 3021 constant check_error : BOOLEAN := float_check_error; 3022 constant denormalize : BOOLEAN := float_denormalize) 3023 return BOOLEAN is 3024 constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction 3025 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 3026 variable lfptype, rfptype : valid_fpstate; 3027 variable expl, expr : UNSIGNED (exponent_width-1 downto 0); 3028 variable fractl, fractr : UNSIGNED (fraction_width-1 downto 0); 3029 variable is_less_than, is_unordered : BOOLEAN; 3030 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 3031 begin 3032 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 3033 is_less_than := false; 3034 else 3035 lresize := resize (arg => to_x01(l), 3036 exponent_width => exponent_width, 3037 fraction_width => fraction_width, 3038 denormalize_in => denormalize, 3039 denormalize => denormalize); 3040 rresize := resize (arg => to_x01(r), 3041 exponent_width => exponent_width, 3042 fraction_width => fraction_width, 3043 denormalize_in => denormalize, 3044 denormalize => denormalize); 3045 if to_x01(l(l'high)) = to_x01(r(r'high)) then -- sign bits 3046 expl := UNSIGNED(lresize(exponent_width-1 downto 0)); 3047 expr := UNSIGNED(rresize(exponent_width-1 downto 0)); 3048 if expl = expr then 3049 fractl := UNSIGNED (to_slv(lresize(-1 downto -fraction_width))); 3050 fractr := UNSIGNED (to_slv(rresize(-1 downto -fraction_width))); 3051 if to_x01(l(l'high)) = '0' then -- positive number 3052 is_less_than := (fractl < fractr); 3053 else 3054 is_less_than := (fractl > fractr); -- negative 3055 end if; 3056 else 3057 if to_x01(l(l'high)) = '0' then -- positive number 3058 is_less_than := (expl < expr); 3059 else 3060 is_less_than := (expl > expr); -- negative 3061 end if; 3062 end if; 3063 else 3064 lfptype := classfp (l, check_error); 3065 rfptype := classfp (r, check_error); 3066 if (lfptype = neg_zero and rfptype = pos_zero) then 3067 is_less_than := false; -- -0 < 0 returns false. 3068 else 3069 is_less_than := (to_x01(l(l'high)) > to_x01(r(r'high))); 3070 end if; 3071 end if; 3072 end if; 3073 if check_error then 3074 is_unordered := Unordered (x => l, 3075 y => r); 3076 else 3077 is_unordered := false; 3078 end if; 3079 return is_less_than and not is_unordered; 3080 end function lt; 3081 3082 function gt ( -- greater than > 3083 l, r : UNRESOLVED_float; -- floating point input 3084 constant check_error : BOOLEAN := float_check_error; 3085 constant denormalize : BOOLEAN := float_denormalize) 3086 return BOOLEAN is 3087 constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction 3088 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 3089 variable lfptype, rfptype : valid_fpstate; 3090 variable expl, expr : UNSIGNED (exponent_width-1 downto 0); 3091 variable fractl, fractr : UNSIGNED (fraction_width-1 downto 0); 3092 variable is_greater_than : BOOLEAN; 3093 variable is_unordered : BOOLEAN; 3094 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 3095 begin -- greater_than 3096 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 3097 is_greater_than := false; 3098 else 3099 lresize := resize (arg => to_x01(l), 3100 exponent_width => exponent_width, 3101 fraction_width => fraction_width, 3102 denormalize_in => denormalize, 3103 denormalize => denormalize); 3104 rresize := resize (arg => to_x01(r), 3105 exponent_width => exponent_width, 3106 fraction_width => fraction_width, 3107 denormalize_in => denormalize, 3108 denormalize => denormalize); 3109 if to_x01(l(l'high)) = to_x01(r(r'high)) then -- sign bits 3110 expl := UNSIGNED(lresize(exponent_width-1 downto 0)); 3111 expr := UNSIGNED(rresize(exponent_width-1 downto 0)); 3112 if expl = expr then 3113 fractl := UNSIGNED (to_slv(lresize(-1 downto -fraction_width))); 3114 fractr := UNSIGNED (to_slv(rresize(-1 downto -fraction_width))); 3115 if to_x01(l(l'high)) = '0' then -- positive number 3116 is_greater_than := fractl > fractr; 3117 else 3118 is_greater_than := fractl < fractr; -- negative 3119 end if; 3120 else 3121 if to_x01(l(l'high)) = '0' then -- positive number 3122 is_greater_than := expl > expr; 3123 else 3124 is_greater_than := expl < expr; -- negative 3125 end if; 3126 end if; 3127 else 3128 lfptype := classfp (l, check_error); 3129 rfptype := classfp (r, check_error); 3130 if (lfptype = pos_zero and rfptype = neg_zero) then 3131 is_greater_than := false; -- 0 > -0 returns false. 3132 else 3133 is_greater_than := to_x01(l(l'high)) < to_x01(r(r'high)); 3134 end if; 3135 end if; 3136 end if; 3137 if check_error then 3138 is_unordered := Unordered (x => l, 3139 y => r); 3140 else 3141 is_unordered := false; 3142 end if; 3143 return is_greater_than and not is_unordered; 3144 end function gt; 3145 3146 -- purpose: /= function 3147 function ne ( -- not equal /= 3148 l, r : UNRESOLVED_float; 3149 constant check_error : BOOLEAN := float_check_error; 3150 constant denormalize : BOOLEAN := float_denormalize) 3151 return BOOLEAN is 3152 variable is_equal, is_unordered : BOOLEAN; 3153 begin 3154 is_equal := eq (l => l, 3155 r => r, 3156 check_error => false, 3157 denormalize => denormalize); 3158 if check_error then 3159 is_unordered := Unordered (x => l, 3160 y => r); 3161 else 3162 is_unordered := false; 3163 end if; 3164 return not (is_equal and not is_unordered); 3165 end function ne; 3166 3167 function le ( -- less than or equal to <= 3168 l, r : UNRESOLVED_float; -- floating point input 3169 constant check_error : BOOLEAN := float_check_error; 3170 constant denormalize : BOOLEAN := float_denormalize) 3171 return BOOLEAN is 3172 variable is_greater_than, is_unordered : BOOLEAN; 3173 begin 3174 is_greater_than := gt (l => l, 3175 r => r, 3176 check_error => false, 3177 denormalize => denormalize); 3178 if check_error then 3179 is_unordered := Unordered (x => l, 3180 y => r); 3181 else 3182 is_unordered := false; 3183 end if; 3184 return not is_greater_than and not is_unordered; 3185 end function le; 3186 3187 function ge ( -- greater than or equal to >= 3188 l, r : UNRESOLVED_float; -- floating point input 3189 constant check_error : BOOLEAN := float_check_error; 3190 constant denormalize : BOOLEAN := float_denormalize) 3191 return BOOLEAN is 3192 variable is_less_than, is_unordered : BOOLEAN; 3193 begin 3194 is_less_than := lt (l => l, 3195 r => r, 3196 check_error => false, 3197 denormalize => denormalize); 3198 if check_error then 3199 is_unordered := Unordered (x => l, 3200 y => r); 3201 else 3202 is_unordered := false; 3203 end if; 3204 return not is_less_than and not is_unordered; 3205 end function ge; 3206 3207 function \?=\ (L, R : UNRESOLVED_float) return STD_ULOGIC is 3208 constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction 3209 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 3210 variable lfptype, rfptype : valid_fpstate; 3211 variable is_equal, is_unordered : STD_ULOGIC; 3212 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 3213 begin -- ?= 3214 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 3215 return 'X'; 3216 else 3217 lfptype := classfp (l, float_check_error); 3218 rfptype := classfp (r, float_check_error); 3219 end if; 3220 if (lfptype = neg_zero or lfptype = pos_zero) and 3221 (rfptype = neg_zero or rfptype = pos_zero) then 3222 is_equal := '1'; 3223 else 3224 lresize := resize (arg => l, 3225 exponent_width => exponent_width, 3226 fraction_width => fraction_width, 3227 denormalize_in => float_denormalize, 3228 denormalize => float_denormalize); 3229 rresize := resize (arg => r, 3230 exponent_width => exponent_width, 3231 fraction_width => fraction_width, 3232 denormalize_in => float_denormalize, 3233 denormalize => float_denormalize); 3234 is_equal := \?=\ (to_sulv(lresize), to_sulv(rresize)); 3235 end if; 3236 if (float_check_error) then 3237 if (lfptype = nan or lfptype = quiet_nan or 3238 rfptype = nan or rfptype = quiet_nan) then 3239 is_unordered := '1'; 3240 else 3241 is_unordered := '0'; 3242 end if; 3243 else 3244 is_unordered := '0'; 3245 end if; 3246 return is_equal and not is_unordered; 3247 end function \?=\; 3248 3249 function \?/=\ (L, R : UNRESOLVED_float) return STD_ULOGIC is 3250 constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction 3251 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 3252 variable lfptype, rfptype : valid_fpstate; 3253 variable is_equal, is_unordered : STD_ULOGIC; 3254 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 3255 begin -- ?/= 3256 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 3257 return 'X'; 3258 else 3259 lfptype := classfp (l, float_check_error); 3260 rfptype := classfp (r, float_check_error); 3261 end if; 3262 if (lfptype = neg_zero or lfptype = pos_zero) and 3263 (rfptype = neg_zero or rfptype = pos_zero) then 3264 is_equal := '1'; 3265 else 3266 lresize := resize (arg => l, 3267 exponent_width => exponent_width, 3268 fraction_width => fraction_width, 3269 denormalize_in => float_denormalize, 3270 denormalize => float_denormalize); 3271 rresize := resize (arg => r, 3272 exponent_width => exponent_width, 3273 fraction_width => fraction_width, 3274 denormalize_in => float_denormalize, 3275 denormalize => float_denormalize); 3276 is_equal := \?=\ (to_sulv(lresize), to_sulv(rresize)); 3277 end if; 3278 if (float_check_error) then 3279 if (lfptype = nan or lfptype = quiet_nan or 3280 rfptype = nan or rfptype = quiet_nan) then 3281 is_unordered := '1'; 3282 else 3283 is_unordered := '0'; 3284 end if; 3285 else 3286 is_unordered := '0'; 3287 end if; 3288 return not (is_equal and not is_unordered); 3289 end function \?/=\; 3290 3291 function \?>\ (L, R : UNRESOLVED_float) return STD_ULOGIC is 3292 constant fraction_width : NATURAL := -mine(l'low, r'low); 3293 variable founddash : BOOLEAN := false; 3294 begin 3295 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 3296 return 'X'; 3297 else 3298 for i in L'range loop 3299 if L(i) = '-' then 3300 founddash := true; 3301 end if; 3302 end loop; 3303 for i in R'range loop 3304 if R(i) = '-' then 3305 founddash := true; 3306 end if; 3307 end loop; 3308 if founddash then 3309 report float_pkg'instance_name 3310 & " ""?>"": '-' found in compare string" 3311 severity error; 3312 return 'X'; 3313 elsif is_x(l) or is_x(r) then 3314 return 'X'; 3315 elsif l > r then 3316 return '1'; 3317 else 3318 return '0'; 3319 end if; 3320 end if; 3321 end function \?>\; 3322 3323 function \?>=\ (L, R : UNRESOLVED_float) return STD_ULOGIC is 3324 constant fraction_width : NATURAL := -mine(l'low, r'low); 3325 variable founddash : BOOLEAN := false; 3326 begin 3327 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 3328 return 'X'; 3329 else 3330 for i in L'range loop 3331 if L(i) = '-' then 3332 founddash := true; 3333 end if; 3334 end loop; 3335 for i in R'range loop 3336 if R(i) = '-' then 3337 founddash := true; 3338 end if; 3339 end loop; 3340 if founddash then 3341 report float_pkg'instance_name 3342 & " ""?>="": '-' found in compare string" 3343 severity error; 3344 return 'X'; 3345 elsif is_x(l) or is_x(r) then 3346 return 'X'; 3347 elsif l >= r then 3348 return '1'; 3349 else 3350 return '0'; 3351 end if; 3352 end if; 3353 end function \?>=\; 3354 3355 function \?<\ (L, R : UNRESOLVED_float) return STD_ULOGIC is 3356 constant fraction_width : NATURAL := -mine(l'low, r'low); 3357 variable founddash : BOOLEAN := false; 3358 begin 3359 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 3360 return 'X'; 3361 else 3362 for i in L'range loop 3363 if L(i) = '-' then 3364 founddash := true; 3365 end if; 3366 end loop; 3367 for i in R'range loop 3368 if R(i) = '-' then 3369 founddash := true; 3370 end if; 3371 end loop; 3372 if founddash then 3373 report float_pkg'instance_name 3374 & " ""?<"": '-' found in compare string" 3375 severity error; 3376 return 'X'; 3377 elsif is_x(l) or is_x(r) then 3378 return 'X'; 3379 elsif l < r then 3380 return '1'; 3381 else 3382 return '0'; 3383 end if; 3384 end if; 3385 end function \?<\; 3386 3387 function \?<=\ (L, R : UNRESOLVED_float) return STD_ULOGIC is 3388 constant fraction_width : NATURAL := -mine(l'low, r'low); 3389 variable founddash : BOOLEAN := false; 3390 begin 3391 if (fraction_width = 0 or l'length < 7 or r'length < 7) then 3392 return 'X'; 3393 else 3394 for i in L'range loop 3395 if L(i) = '-' then 3396 founddash := true; 3397 end if; 3398 end loop; 3399 for i in R'range loop 3400 if R(i) = '-' then 3401 founddash := true; 3402 end if; 3403 end loop; 3404 if founddash then 3405 report float_pkg'instance_name 3406 & " ""?<="": '-' found in compare string" 3407 severity error; 3408 return 'X'; 3409 elsif is_x(l) or is_x(r) then 3410 return 'X'; 3411 elsif l <= r then 3412 return '1'; 3413 else 3414 return '0'; 3415 end if; 3416 end if; 3417 end function \?<=\; 3418 3419 function std_match (L, R : UNRESOLVED_float) return BOOLEAN is 3420 begin 3421 if (L'high = R'high and L'low = R'low) then 3422 return std_match(to_sulv(L), to_sulv(R)); 3423 else 3424 report float_pkg'instance_name 3425 & "STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" 3426 severity warning; 3427 return false; 3428 end if; 3429 end function std_match; 3430 3431 function find_rightmost (arg : UNRESOLVED_float; y : STD_ULOGIC) return INTEGER is 3432 begin 3433 for_loop : for i in arg'reverse_range loop 3434 if \?=\ (arg(i), y) = '1' then 3435 return i; 3436 end if; 3437 end loop; 3438 return arg'high+1; -- return out of bounds 'high 3439 end function find_rightmost; 3440 3441 function find_leftmost (arg : UNRESOLVED_float; y : STD_ULOGIC) return INTEGER is 3442 begin 3443 for_loop : for i in arg'range loop 3444 if \?=\ (arg(i), y) = '1' then 3445 return i; 3446 end if; 3447 end loop; 3448 return arg'low-1; -- return out of bounds 'low 3449 end function find_leftmost; 3450 3451 -- These override the defaults for the compare operators. 3452 function "=" (l, r : UNRESOLVED_float) return BOOLEAN is 3453 begin 3454 return eq(l, r); 3455 end function "="; 3456 3457 function "/=" (l, r : UNRESOLVED_float) return BOOLEAN is 3458 begin 3459 return ne(l, r); 3460 end function "/="; 3461 3462 function ">=" (l, r : UNRESOLVED_float) return BOOLEAN is 3463 begin 3464 return ge(l, r); 3465 end function ">="; 3466 3467 function "<=" (l, r : UNRESOLVED_float) return BOOLEAN is 3468 begin 3469 return le(l, r); 3470 end function "<="; 3471 3472 function ">" (l, r : UNRESOLVED_float) return BOOLEAN is 3473 begin 3474 return gt(l, r); 3475 end function ">"; 3476 3477 function "<" (l, r : UNRESOLVED_float) return BOOLEAN is 3478 begin 3479 return lt(l, r); 3480 end function "<"; 3481 3482 -- purpose: maximum of two numbers (overrides default) 3483 function maximum ( 3484 L, R : UNRESOLVED_float) 3485 return UNRESOLVED_float is 3486 constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction 3487 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 3488 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 3489 begin 3490 if ((L'length < 1) or (R'length < 1)) then return NAFP; 3491 end if; 3492 lresize := resize (l, exponent_width, fraction_width); 3493 rresize := resize (r, exponent_width, fraction_width); 3494 if lresize > rresize then return lresize; 3495 else return rresize; 3496 end if; 3497 end function maximum; 3498 3499 function minimum ( 3500 L, R : UNRESOLVED_float) 3501 return UNRESOLVED_float is 3502 constant fraction_width : NATURAL := -mine(l'low, r'low); -- length of FP output fraction 3503 constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent 3504 variable lresize, rresize : UNRESOLVED_float (exponent_width downto -fraction_width); 3505 begin 3506 if ((L'length < 1) or (R'length < 1)) then return NAFP; 3507 end if; 3508 lresize := resize (l, exponent_width, fraction_width); 3509 rresize := resize (r, exponent_width, fraction_width); 3510 if lresize > rresize then return rresize; 3511 else return lresize; 3512 end if; 3513 end function minimum; 3514 3515 ----------------------------------------------------------------------------- 3516 -- conversion functions 3517 ----------------------------------------------------------------------------- 3518 3519 -- Converts a floating point number of one format into another format 3520 function resize ( 3521 arg : UNRESOLVED_float; -- Floating point input 3522 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 3523 constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction 3524 constant round_style : round_type := float_round_style; -- rounding option 3525 constant check_error : BOOLEAN := float_check_error; 3526 constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP 3527 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 3528 return UNRESOLVED_float is 3529 constant in_fraction_width : NATURAL := -arg'low; -- length of FP output fraction 3530 constant in_exponent_width : NATURAL := arg'high; -- length of FP output exponent 3531 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 3532 -- result value 3533 variable fptype : valid_fpstate; 3534 variable expon_in : SIGNED (in_exponent_width-1 downto 0); 3535 variable fract_in : UNSIGNED (in_fraction_width downto 0); 3536 variable round : BOOLEAN; 3537 variable expon_out : SIGNED (exponent_width-1 downto 0); -- output fract 3538 variable fract_out : UNSIGNED (fraction_width downto 0); -- output fract 3539 variable passguard : NATURAL; 3540 begin 3541 fptype := classfp(arg, check_error); 3542 if ((fptype = pos_denormal or fptype = neg_denormal) and denormalize_in 3543 and (in_exponent_width < exponent_width 3544 or in_fraction_width < fraction_width)) 3545 or in_exponent_width > exponent_width 3546 or in_fraction_width > fraction_width then 3547 -- size reduction 3548 classcase : case fptype is 3549 when isx => 3550 result := (others => 'X'); 3551 when nan | quiet_nan => 3552 result := qnanfp (fraction_width => fraction_width, 3553 exponent_width => exponent_width); 3554 when pos_inf => 3555 result := pos_inffp (fraction_width => fraction_width, 3556 exponent_width => exponent_width); 3557 when neg_inf => 3558 result := neg_inffp (fraction_width => fraction_width, 3559 exponent_width => exponent_width); 3560 when pos_zero | neg_zero => 3561 result := zerofp (fraction_width => fraction_width, -- hate -0 3562 exponent_width => exponent_width); 3563 when others => 3564 break_number ( 3565 arg => arg, 3566 fptyp => fptype, 3567 denormalize => denormalize_in, 3568 fract => fract_in, 3569 expon => expon_in); 3570 if fraction_width > in_fraction_width and denormalize_in then 3571 -- You only get here if you have a denormal input 3572 fract_out := (others => '0'); -- pad with zeros 3573 fract_out (fraction_width downto 3574 fraction_width - in_fraction_width) := fract_in; 3575 result := normalize ( 3576 fract => fract_out, 3577 expon => expon_in, 3578 sign => arg(arg'high), 3579 fraction_width => fraction_width, 3580 exponent_width => exponent_width, 3581 round_style => round_style, 3582 denormalize => denormalize, 3583 nguard => 0); 3584 else 3585 result := normalize ( 3586 fract => fract_in, 3587 expon => expon_in, 3588 sign => arg(arg'high), 3589 fraction_width => fraction_width, 3590 exponent_width => exponent_width, 3591 round_style => round_style, 3592 denormalize => denormalize, 3593 nguard => in_fraction_width - fraction_width); 3594 end if; 3595 end case classcase; 3596 else -- size increase or the same size 3597 if exponent_width > in_exponent_width then 3598 expon_in := SIGNED(arg (in_exponent_width-1 downto 0)); 3599 if fptype = pos_zero or fptype = neg_zero then 3600 result (exponent_width-1 downto 0) := (others => '0'); 3601 elsif expon_in = -1 then -- inf or nan (shorts out check_error) 3602 result (exponent_width-1 downto 0) := (others => '1'); 3603 else 3604 -- invert top BIT 3605 expon_in(expon_in'high) := not expon_in(expon_in'high); 3606 expon_out := resize (expon_in, expon_out'length); -- signed expand 3607 -- Flip it back. 3608 expon_out(expon_out'high) := not expon_out(expon_out'high); 3609 result (exponent_width-1 downto 0) := UNRESOLVED_float(expon_out); 3610 end if; 3611 result (exponent_width) := arg (in_exponent_width); -- sign 3612 else -- exponent_width = in_exponent_width 3613 result (exponent_width downto 0) := arg (in_exponent_width downto 0); 3614 end if; 3615 if fraction_width > in_fraction_width then 3616 result (-1 downto -fraction_width) := (others => '0'); -- zeros 3617 result (-1 downto -in_fraction_width) := 3618 arg (-1 downto -in_fraction_width); 3619 else -- fraction_width = in_fraciton_width 3620 result (-1 downto -fraction_width) := 3621 arg (-1 downto -in_fraction_width); 3622 end if; 3623 end if; 3624 return result; 3625 end function resize; 3626 3627 function resize ( 3628 arg : UNRESOLVED_float; -- floating point input 3629 size_res : UNRESOLVED_float; 3630 constant round_style : round_type := float_round_style; -- rounding option 3631 constant check_error : BOOLEAN := float_check_error; 3632 constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP 3633 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 3634 return UNRESOLVED_float is 3635 variable result : UNRESOLVED_float (size_res'left downto size_res'right); 3636 begin 3637 if (result'length < 1) then 3638 return result; 3639 else 3640 result := resize (arg => arg, 3641 exponent_width => size_res'high, 3642 fraction_width => -size_res'low, 3643 round_style => round_style, 3644 check_error => check_error, 3645 denormalize_in => denormalize_in, 3646 denormalize => denormalize); 3647 return result; 3648 end if; 3649 end function resize; 3650 3651 function to_float32 ( 3652 arg : UNRESOLVED_float; 3653 constant round_style : round_type := float_round_style; -- rounding option 3654 constant check_error : BOOLEAN := float_check_error; 3655 constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP 3656 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 3657 return UNRESOLVED_float32 is 3658 begin 3659 return resize (arg => arg, 3660 exponent_width => float32'high, 3661 fraction_width => -float32'low, 3662 round_style => round_style, 3663 check_error => check_error, 3664 denormalize_in => denormalize_in, 3665 denormalize => denormalize); 3666 end function to_float32; 3667 3668 function to_float64 ( 3669 arg : UNRESOLVED_float; 3670 constant round_style : round_type := float_round_style; -- rounding option 3671 constant check_error : BOOLEAN := float_check_error; 3672 constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP 3673 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 3674 return UNRESOLVED_float64 is 3675 begin 3676 return resize (arg => arg, 3677 exponent_width => float64'high, 3678 fraction_width => -float64'low, 3679 round_style => round_style, 3680 check_error => check_error, 3681 denormalize_in => denormalize_in, 3682 denormalize => denormalize); 3683 end function to_float64; 3684 3685 function to_float128 ( 3686 arg : UNRESOLVED_float; 3687 constant round_style : round_type := float_round_style; -- rounding option 3688 constant check_error : BOOLEAN := float_check_error; 3689 constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP 3690 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 3691 return UNRESOLVED_float128 is 3692 begin 3693 return resize (arg => arg, 3694 exponent_width => float128'high, 3695 fraction_width => -float128'low, 3696 round_style => round_style, 3697 check_error => check_error, 3698 denormalize_in => denormalize_in, 3699 denormalize => denormalize); 3700 end function to_float128; 3701 3702 -- to_float (Real) 3703 -- typically not Synthesizable unless the input is a constant. 3704 function to_float ( 3705 arg : REAL; 3706 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 3707 constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction 3708 constant round_style : round_type := float_round_style; -- rounding option 3709 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 3710 return UNRESOLVED_float is 3711 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 3712 variable arg_real : REAL; -- Real version of argument 3713 variable validfp : boundary_type; -- Check for valid results 3714 variable exp : INTEGER; -- Integer version of exponent 3715 variable expon : UNSIGNED (exponent_width - 1 downto 0); 3716 -- Unsigned version of exp. 3717 constant expon_base : SIGNED (exponent_width-1 downto 0) := 3718 gen_expon_base(exponent_width); -- exponent offset 3719 variable fract : UNSIGNED (fraction_width-1 downto 0); 3720 variable frac : REAL; -- Real version of fraction 3721 constant roundfrac : REAL := 2.0 ** (-2 - fract'high); -- used for rounding 3722 variable round : BOOLEAN; -- to round or not to round 3723 begin 3724 result := (others => '0'); 3725 arg_real := arg; 3726 if arg_real < 0.0 then 3727 result (exponent_width) := '1'; 3728 arg_real := - arg_real; -- Make it positive. 3729 else 3730 result (exponent_width) := '0'; 3731 end if; 3732 test_boundary (arg => arg_real, 3733 fraction_width => fraction_width, 3734 exponent_width => exponent_width, 3735 denormalize => denormalize, 3736 btype => validfp, 3737 log2i => exp); 3738 if validfp = zero then 3739 return result; -- Result initialized to "0". 3740 elsif validfp = infinity then 3741 result (exponent_width - 1 downto 0) := (others => '1'); -- Exponent all "1" 3742 -- return infinity. 3743 return result; 3744 else 3745 if validfp = denormal then -- Exponent will default to "0". 3746 expon := (others => '0'); 3747 frac := arg_real * (2.0 ** (to_integer(expon_base)-1)); 3748 else -- Number less than 1. "normal" number 3749 expon := UNSIGNED (to_signed (exp-1, exponent_width)); 3750 expon(exponent_width-1) := not expon(exponent_width-1); 3751 frac := (arg_real / 2.0 ** exp) - 1.0; -- Number less than 1. 3752 end if; 3753 for i in 0 to fract'high loop 3754 if frac >= 2.0 ** (-1 - i) then 3755 fract (fract'high - i) := '1'; 3756 frac := frac - 2.0 ** (-1 - i); 3757 else 3758 fract (fract'high - i) := '0'; 3759 end if; 3760 end loop; 3761 round := false; 3762 case round_style is 3763 when round_nearest => 3764 if frac > roundfrac or ((frac = roundfrac) and fract(0) = '1') then 3765 round := true; 3766 end if; 3767 when round_inf => 3768 if frac /= 0.0 and result(exponent_width) = '0' then 3769 round := true; 3770 end if; 3771 when round_neginf => 3772 if frac /= 0.0 and result(exponent_width) = '1' then 3773 round := true; 3774 end if; 3775 when others => 3776 null; -- don't round 3777 end case; 3778 if (round) then 3779 if and_reduce (fract) = '1' then -- fraction is all "1" 3780 expon := expon + 1; 3781 fract := (others => '0'); 3782 else 3783 fract := fract + 1; 3784 end if; 3785 end if; 3786 result (exponent_width-1 downto 0) := UNRESOLVED_float(expon); 3787 result (-1 downto -fraction_width) := UNRESOLVED_float(fract); 3788 return result; 3789 end if; 3790 end function to_float; 3791 3792 -- to_float (Integer) 3793 function to_float ( 3794 arg : INTEGER; 3795 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 3796 constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction 3797 constant round_style : round_type := float_round_style) -- rounding option 3798 return UNRESOLVED_float is 3799 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 3800 variable arg_int : NATURAL; -- Natural version of argument 3801 variable expon : SIGNED (exponent_width-1 downto 0); 3802 variable exptmp : SIGNED (exponent_width-1 downto 0); 3803 -- Unsigned version of exp. 3804 constant expon_base : SIGNED (exponent_width-1 downto 0) := 3805 gen_expon_base(exponent_width); -- exponent offset 3806 variable fract : UNSIGNED (fraction_width-1 downto 0) := (others => '0'); 3807 variable fracttmp : UNSIGNED (fraction_width-1 downto 0); 3808 variable round : BOOLEAN; 3809 variable shift : NATURAL; 3810 variable shiftr : NATURAL; 3811 variable roundfrac : NATURAL; -- used in rounding 3812 begin 3813 if arg < 0 then 3814 result (exponent_width) := '1'; 3815 arg_int := -arg; -- Make it positive. 3816 else 3817 result (exponent_width) := '0'; 3818 arg_int := arg; 3819 end if; 3820 if arg_int = 0 then 3821 result := zerofp (fraction_width => fraction_width, 3822 exponent_width => exponent_width); 3823 else 3824 -- If the number is larger than we can represent in this number system 3825 -- we need to return infinity. 3826 shift := log2(arg_int); 3827 if shift > to_integer(expon_base) then 3828 -- worry about infinity 3829 if result (exponent_width) = '0' then 3830 result := pos_inffp (fraction_width => fraction_width, 3831 exponent_width => exponent_width); 3832 else 3833 -- return negative infinity. 3834 result := neg_inffp (fraction_width => fraction_width, 3835 exponent_width => exponent_width); 3836 end if; 3837 else -- Normal number (can't be denormal) 3838 -- Compute Exponent 3839 expon := to_signed (shift-1, expon'length); -- positive fraction. 3840 -- Compute Fraction 3841 arg_int := arg_int - 2**shift; -- Subtract off the 1.0 3842 shiftr := shift; 3843 for I in fract'high downto maximum (fract'high - shift + 1, 0) loop 3844 shiftr := shiftr - 1; 3845 if (arg_int >= 2**shiftr) then 3846 arg_int := arg_int - 2**shiftr; 3847 fract(I) := '1'; 3848 else 3849 fract(I) := '0'; 3850 end if; 3851 end loop; 3852 -- Rounding routine 3853 round := false; 3854 if arg_int > 0 then 3855 roundfrac := 2**(shiftr-1); 3856 case round_style is 3857 when round_nearest => 3858 if arg_int > roundfrac or 3859 ((arg_int = roundfrac) and fract(0) = '1') then 3860 round := true; 3861 end if; 3862 when round_inf => 3863 if arg_int /= 0 and result (exponent_width) = '0' then 3864 round := true; 3865 end if; 3866 when round_neginf => 3867 if arg_int /= 0 and result (exponent_width) = '1' then 3868 round := true; 3869 end if; 3870 when others => 3871 null; 3872 end case; 3873 end if; 3874 if round then 3875 fp_round(fract_in => fract, 3876 expon_in => expon, 3877 fract_out => fracttmp, 3878 expon_out => exptmp); 3879 fract := fracttmp; 3880 expon := exptmp; 3881 end if; 3882 -- Put the number together and return 3883 expon(exponent_width-1) := not expon(exponent_width-1); 3884 result (exponent_width-1 downto 0) := UNRESOLVED_float(expon); 3885 result (-1 downto -fraction_width) := UNRESOLVED_float(fract); 3886 end if; 3887 end if; 3888 return result; 3889 end function to_float; 3890 3891 -- to_float (unsigned) 3892 function to_float ( 3893 arg : UNSIGNED; 3894 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 3895 constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction 3896 constant round_style : round_type := float_round_style) -- rounding option 3897 return UNRESOLVED_float is 3898 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 3899 constant ARG_LEFT : INTEGER := ARG'length-1; 3900 alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; 3901 variable sarg : SIGNED (ARG_LEFT+1 downto 0); -- signed version of arg 3902 begin 3903 if arg'length < 1 then 3904 return NAFP; 3905 end if; 3906 sarg (XARG'range) := SIGNED (XARG); 3907 sarg (sarg'high) := '0'; 3908 result := to_float (arg => sarg, 3909 exponent_width => exponent_width, 3910 fraction_width => fraction_width, 3911 round_style => round_style); 3912 return result; 3913 end function to_float; 3914 3915 -- to_float (signed) 3916 function to_float ( 3917 arg : SIGNED; 3918 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 3919 constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction 3920 constant round_style : round_type := float_round_style) -- rounding option 3921 return UNRESOLVED_float is 3922 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 3923 constant ARG_LEFT : INTEGER := ARG'length-1; 3924 alias XARG : SIGNED(ARG_LEFT downto 0) is ARG; 3925 variable arg_int : UNSIGNED(xarg'range); -- Real version of argument 3926 variable argb2 : UNSIGNED(xarg'high/2 downto 0); -- log2 of input 3927 variable rexp : SIGNED (exponent_width - 1 downto 0); 3928 variable exp : SIGNED (exponent_width - 1 downto 0); 3929 -- signed version of exp. 3930 variable expon : UNSIGNED (exponent_width - 1 downto 0); 3931 -- Unsigned version of exp. 3932 constant expon_base : SIGNED (exponent_width-1 downto 0) := 3933 gen_expon_base(exponent_width); -- exponent offset 3934 variable round : BOOLEAN; 3935 variable fract : UNSIGNED (fraction_width-1 downto 0); 3936 variable rfract : UNSIGNED (fraction_width-1 downto 0); 3937 variable sign : STD_ULOGIC; -- sign bit 3938 begin 3939 if arg'length < 1 then 3940 return NAFP; 3941 end if; 3942 if Is_X (xarg) then 3943 result := (others => 'X'); 3944 elsif (xarg = 0) then 3945 result := zerofp (fraction_width => fraction_width, 3946 exponent_width => exponent_width); 3947 else -- Normal number (can't be denormal) 3948 sign := to_X01(xarg (xarg'high)); 3949 arg_int := UNSIGNED(abs (to_01(xarg))); 3950 -- Compute Exponent 3951 argb2 := to_unsigned(find_leftmost(arg_int, '1'), argb2'length); -- Log2 3952 if argb2 > UNSIGNED(expon_base) then 3953 result := pos_inffp (fraction_width => fraction_width, 3954 exponent_width => exponent_width); 3955 result (exponent_width) := sign; 3956 else 3957 exp := SIGNED(resize(argb2, exp'length)); 3958 arg_int := shift_left (arg_int, arg_int'high-to_integer(exp)); 3959 if (arg_int'high > fraction_width) then 3960 fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width)); 3961 round := check_round ( 3962 fract_in => fract (0), 3963 sign => sign, 3964 remainder => arg_int((arg_int'high-fraction_width-1) 3965 downto 0), 3966 round_style => round_style); 3967 if round then 3968 fp_round(fract_in => fract, 3969 expon_in => exp, 3970 fract_out => rfract, 3971 expon_out => rexp); 3972 else 3973 rfract := fract; 3974 rexp := exp; 3975 end if; 3976 else 3977 rexp := exp; 3978 rfract := (others => '0'); 3979 rfract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) := 3980 arg_int (arg_int'high-1 downto 0); 3981 end if; 3982 result (exponent_width) := sign; 3983 expon := UNSIGNED (rexp-1); 3984 expon(exponent_width-1) := not expon(exponent_width-1); 3985 result (exponent_width-1 downto 0) := UNRESOLVED_float(expon); 3986 result (-1 downto -fraction_width) := UNRESOLVED_float(rfract); 3987 end if; 3988 end if; 3989 return result; 3990 end function to_float; 3991 3992 -- std_logic_vector to float 3993 function to_float ( 3994 arg : STD_ULOGIC_VECTOR; 3995 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 3996 constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction 3997 return UNRESOLVED_float is 3998 variable fpvar : UNRESOLVED_float (exponent_width downto -fraction_width); 3999 begin 4000 if arg'length < 1 then 4001 return NAFP; 4002 end if; 4003 fpvar := UNRESOLVED_float(arg); 4004 return fpvar; 4005 end function to_float; 4006 4007 -- purpose: converts a ufixed to a floating point 4008 function to_float ( 4009 arg : UNRESOLVED_ufixed; -- unsigned fixed point input 4010 constant exponent_width : NATURAL := float_exponent_width; -- width of exponent 4011 constant fraction_width : NATURAL := float_fraction_width; -- width of fraction 4012 constant round_style : round_type := float_round_style; -- rounding 4013 constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions 4014 return UNRESOLVED_float is 4015 variable sarg : sfixed (arg'high+1 downto arg'low); -- Signed version of arg 4016 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 4017 begin -- function to_float 4018 if (arg'length < 1) then 4019 return NAFP; 4020 end if; 4021 sarg (arg'range) := sfixed (arg); 4022 sarg (sarg'high) := '0'; 4023 result := to_float (arg => sarg, 4024 exponent_width => exponent_width, 4025 fraction_width => fraction_width, 4026 round_style => round_style, 4027 denormalize => denormalize); 4028 return result; 4029 end function to_float; 4030 4031 function to_float ( 4032 arg : UNRESOLVED_sfixed; -- signed fixed point 4033 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 4034 constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction 4035 constant round_style : round_type := float_round_style; -- rounding 4036 constant denormalize : BOOLEAN := float_denormalize) -- rounding option 4037 return UNRESOLVED_float is 4038 constant integer_width : INTEGER := arg'high; 4039 constant in_fraction_width : INTEGER := arg'low; 4040 variable xresult : sfixed (integer_width downto in_fraction_width); 4041 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 4042 variable arg_int : UNSIGNED(integer_width - in_fraction_width 4043 downto 0); -- unsigned version of argument 4044 variable argx : SIGNED (integer_width - in_fraction_width downto 0); 4045 variable exp, exptmp : SIGNED (exponent_width + 1 downto 0); 4046 variable expon : UNSIGNED (exponent_width - 1 downto 0); 4047 -- Unsigned version of exp. 4048 constant expon_base : SIGNED (exponent_width-1 downto 0) := 4049 gen_expon_base(exponent_width); -- exponent offset 4050 variable fract, fracttmp : UNSIGNED (fraction_width-1 downto 0) := 4051 (others => '0'); 4052 variable round : BOOLEAN := false; 4053 begin 4054 if (arg'length < 1) then 4055 return NAFP; 4056 end if; 4057 xresult := to_01(arg, 'X'); 4058 argx := SIGNED(to_slv(xresult)); 4059 if (Is_X (arg)) then 4060 result := (others => 'X'); 4061 elsif (argx = 0) then 4062 result := (others => '0'); 4063 else 4064 result := (others => '0'); -- zero out the result 4065 if argx(argx'left) = '1' then -- toss the sign bit 4066 result (exponent_width) := '1'; -- Negative number 4067 arg_int := UNSIGNED(to_x01(not STD_LOGIC_VECTOR (argx))) + 1; -- Make it positive with two's complement 4068 else 4069 result (exponent_width) := '0'; 4070 arg_int := UNSIGNED(to_x01(STD_LOGIC_VECTOR (argx))); -- new line: direct conversion to unsigned 4071 end if; 4072 -- Compute Exponent 4073 exp := to_signed(find_leftmost(arg_int, '1'), exp'length); -- Log2 4074 if exp + in_fraction_width > expon_base then -- return infinity 4075 result (-1 downto -fraction_width) := (others => '0'); 4076 result (exponent_width -1 downto 0) := (others => '1'); 4077 return result; 4078 elsif (denormalize and 4079 (exp + in_fraction_width <= -resize(expon_base, exp'length))) then 4080 exp := -resize(expon_base, exp'length); 4081 -- shift by a constant 4082 arg_int := shift_left (arg_int, 4083 (arg_int'high + to_integer(expon_base) 4084 + in_fraction_width - 1)); 4085 if (arg_int'high > fraction_width) then 4086 fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width)); 4087 round := check_round ( 4088 fract_in => arg_int(arg_int'high-fraction_width), 4089 sign => result(result'high), 4090 remainder => arg_int((arg_int'high-fraction_width-1) 4091 downto 0), 4092 round_style => round_style); 4093 if (round) then 4094 fp_round (fract_in => arg_int (arg_int'high-1 downto 4095 (arg_int'high-fraction_width)), 4096 expon_in => exp, 4097 fract_out => fract, 4098 expon_out => exptmp); 4099 exp := exptmp; 4100 end if; 4101 else 4102 fract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) := 4103 arg_int (arg_int'high-1 downto 0); 4104 end if; 4105 else 4106 arg_int := shift_left (arg_int, arg_int'high-to_integer(exp)); 4107 exp := exp + in_fraction_width; 4108 if (arg_int'high > fraction_width) then 4109 fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width)); 4110 round := check_round ( 4111 fract_in => fract(0), 4112 sign => result(result'high), 4113 remainder => arg_int((arg_int'high-fraction_width-1) 4114 downto 0), 4115 round_style => round_style); 4116 if (round) then 4117 fp_round (fract_in => fract, 4118 expon_in => exp, 4119 fract_out => fracttmp, 4120 expon_out => exptmp); 4121 fract := fracttmp; 4122 exp := exptmp; 4123 end if; 4124 else 4125 fract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) := 4126 arg_int (arg_int'high-1 downto 0); 4127 end if; 4128 end if; 4129 expon := UNSIGNED (resize(exp-1, exponent_width)); 4130 expon(exponent_width-1) := not expon(exponent_width-1); 4131 result (exponent_width-1 downto 0) := UNRESOLVED_float(expon); 4132 result (-1 downto -fraction_width) := UNRESOLVED_float(fract); 4133 end if; 4134 return result; 4135 end function to_float; 4136 4137 -- size_res functions 4138 -- Integer to float 4139 function to_float ( 4140 arg : INTEGER; 4141 size_res : UNRESOLVED_float; 4142 constant round_style : round_type := float_round_style) -- rounding option 4143 return UNRESOLVED_float is 4144 variable result : UNRESOLVED_float (size_res'left downto size_res'right); 4145 begin 4146 if (result'length < 1) then 4147 return result; 4148 else 4149 result := to_float (arg => arg, 4150 exponent_width => size_res'high, 4151 fraction_width => -size_res'low, 4152 round_style => round_style); 4153 return result; 4154 end if; 4155 end function to_float; 4156 4157 -- real to float 4158 function to_float ( 4159 arg : REAL; 4160 size_res : UNRESOLVED_float; 4161 constant round_style : round_type := float_round_style; -- rounding option 4162 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 4163 return UNRESOLVED_float is 4164 variable result : UNRESOLVED_float (size_res'left downto size_res'right); 4165 begin 4166 if (result'length < 1) then 4167 return result; 4168 else 4169 result := to_float (arg => arg, 4170 exponent_width => size_res'high, 4171 fraction_width => -size_res'low, 4172 round_style => round_style, 4173 denormalize => denormalize); 4174 return result; 4175 end if; 4176 end function to_float; 4177 4178 -- unsigned to float 4179 function to_float ( 4180 arg : UNSIGNED; 4181 size_res : UNRESOLVED_float; 4182 constant round_style : round_type := float_round_style) -- rounding option 4183 return UNRESOLVED_float is 4184 variable result : UNRESOLVED_float (size_res'left downto size_res'right); 4185 begin 4186 if (result'length < 1) then 4187 return result; 4188 else 4189 result := to_float (arg => arg, 4190 exponent_width => size_res'high, 4191 fraction_width => -size_res'low, 4192 round_style => round_style); 4193 return result; 4194 end if; 4195 end function to_float; 4196 4197 -- signed to float 4198 function to_float ( 4199 arg : SIGNED; 4200 size_res : UNRESOLVED_float; 4201 constant round_style : round_type := float_round_style) -- rounding 4202 return UNRESOLVED_float is 4203 variable result : UNRESOLVED_float (size_res'left downto size_res'right); 4204 begin 4205 if (result'length < 1) then 4206 return result; 4207 else 4208 result := to_float (arg => arg, 4209 exponent_width => size_res'high, 4210 fraction_width => -size_res'low, 4211 round_style => round_style); 4212 return result; 4213 end if; 4214 end function to_float; 4215 4216 -- std_ulogic_vector to float 4217 function to_float ( 4218 arg : STD_ULOGIC_VECTOR; 4219 size_res : UNRESOLVED_float) 4220 return UNRESOLVED_float is 4221 variable result : UNRESOLVED_float (size_res'left downto size_res'right); 4222 begin 4223 if (result'length < 1) then 4224 return result; 4225 else 4226 result := to_float (arg => arg, 4227 exponent_width => size_res'high, 4228 fraction_width => -size_res'low); 4229 return result; 4230 end if; 4231 end function to_float; 4232 4233 -- unsigned fixed point to float 4234 function to_float ( 4235 arg : UNRESOLVED_ufixed; -- unsigned fixed point input 4236 size_res : UNRESOLVED_float; 4237 constant round_style : round_type := float_round_style; -- rounding 4238 constant denormalize : BOOLEAN := float_denormalize) -- use ieee extensions 4239 return UNRESOLVED_float is 4240 variable result : UNRESOLVED_float (size_res'left downto size_res'right); 4241 begin 4242 if (result'length < 1) then 4243 return result; 4244 else 4245 result := to_float (arg => arg, 4246 exponent_width => size_res'high, 4247 fraction_width => -size_res'low, 4248 round_style => round_style, 4249 denormalize => denormalize); 4250 return result; 4251 end if; 4252 end function to_float; 4253 4254 -- signed fixed point to float 4255 function to_float ( 4256 arg : UNRESOLVED_sfixed; 4257 size_res : UNRESOLVED_float; 4258 constant round_style : round_type := float_round_style; -- rounding 4259 constant denormalize : BOOLEAN := float_denormalize) -- rounding option 4260 return UNRESOLVED_float is 4261 variable result : UNRESOLVED_float (size_res'left downto size_res'right); 4262 begin 4263 if (result'length < 1) then 4264 return result; 4265 else 4266 result := to_float (arg => arg, 4267 exponent_width => size_res'high, 4268 fraction_width => -size_res'low, 4269 round_style => round_style, 4270 denormalize => denormalize); 4271 return result; 4272 end if; 4273 end function to_float; 4274 4275 -- to_integer (float) 4276 function to_integer ( 4277 arg : UNRESOLVED_float; -- floating point input 4278 constant round_style : round_type := float_round_style; -- rounding option 4279 constant check_error : BOOLEAN := float_check_error) -- check for errors 4280 return INTEGER is 4281 variable validfp : valid_fpstate; -- Valid FP state 4282 variable frac : UNSIGNED (-arg'low downto 0); -- Fraction 4283 variable fract : UNSIGNED (1-arg'low downto 0); -- Fraction 4284 variable expon : SIGNED (arg'high-1 downto 0); 4285 variable isign : STD_ULOGIC; -- internal version of sign 4286 variable round : STD_ULOGIC; -- is rounding needed? 4287 variable result : INTEGER; 4288 variable base : INTEGER; -- Integer exponent 4289 begin 4290 validfp := classfp (arg, check_error); 4291 classcase : case validfp is 4292 when isx | nan | quiet_nan | pos_zero | neg_zero | pos_denormal | neg_denormal => 4293 result := 0; -- return 0 4294 when pos_inf => 4295 result := INTEGER'high; 4296 when neg_inf => 4297 result := INTEGER'low; 4298 when others => 4299 break_number ( 4300 arg => arg, 4301 fptyp => validfp, 4302 denormalize => false, 4303 fract => frac, 4304 expon => expon); 4305 fract (fract'high) := '0'; -- Add extra bit for 0.6 case 4306 fract (fract'high-1 downto 0) := frac; 4307 isign := to_x01 (arg (arg'high)); 4308 base := to_integer (expon) + 1; 4309 if base < -1 then 4310 result := 0; 4311 elsif base >= frac'high then 4312 result := to_integer (fract) * 2**(base - frac'high); 4313 else -- We need to round 4314 if base = -1 then -- trap for 0.6 case. 4315 result := 0; 4316 else 4317 result := to_integer (fract (frac'high downto frac'high-base)); 4318 end if; 4319 -- rounding routine 4320 case round_style is 4321 when round_nearest => 4322 if frac'high - base > 1 then 4323 round := fract (frac'high - base - 1) and 4324 (fract (frac'high - base) 4325 or (or_reduce (fract (frac'high - base - 2 downto 0)))); 4326 else 4327 round := fract (frac'high - base - 1) and 4328 fract (frac'high - base); 4329 end if; 4330 when round_inf => 4331 round := fract(frac'high - base - 1) and not isign; 4332 when round_neginf => 4333 round := fract(frac'high - base - 1) and isign; 4334 when others => 4335 round := '0'; 4336 end case; 4337 if round = '1' then 4338 result := result + 1; 4339 end if; 4340 end if; 4341 if isign = '1' then 4342 result := - result; 4343 end if; 4344 end case classcase; 4345 return result; 4346 end function to_integer; 4347 4348 -- to_unsigned (float) 4349 function to_unsigned ( 4350 arg : UNRESOLVED_float; -- floating point input 4351 constant size : NATURAL; -- length of output 4352 constant round_style : round_type := float_round_style; -- rounding option 4353 constant check_error : BOOLEAN := float_check_error) -- check for errors 4354 return UNSIGNED is 4355 variable validfp : valid_fpstate; -- Valid FP state 4356 variable frac : UNSIGNED (size-1 downto 0); -- Fraction 4357 variable sign : STD_ULOGIC; -- not used 4358 begin 4359 validfp := classfp (arg, check_error); 4360 classcase : case validfp is 4361 when isx | nan | quiet_nan => 4362 frac := (others => 'X'); 4363 when pos_zero | neg_inf | neg_zero | neg_normal | pos_denormal | neg_denormal => 4364 frac := (others => '0'); -- return 0 4365 when pos_inf => 4366 frac := (others => '1'); 4367 when others => 4368 float_to_unsigned ( 4369 arg => arg, 4370 frac => frac, 4371 sign => sign, 4372 denormalize => false, 4373 bias => 0, 4374 round_style => round_style); 4375 end case classcase; 4376 return (frac); 4377 end function to_unsigned; 4378 4379 -- to_signed (float) 4380 function to_signed ( 4381 arg : UNRESOLVED_float; -- floating point input 4382 constant size : NATURAL; -- length of output 4383 constant round_style : round_type := float_round_style; -- rounding option 4384 constant check_error : BOOLEAN := float_check_error) -- check for errors 4385 return SIGNED is 4386 variable sign : STD_ULOGIC; -- true if negative 4387 variable validfp : valid_fpstate; -- Valid FP state 4388 variable frac : UNSIGNED (size-1 downto 0); -- Fraction 4389 variable result : SIGNED (size-1 downto 0); 4390 begin 4391 validfp := classfp (arg, check_error); 4392 classcase : case validfp is 4393 when isx | nan | quiet_nan => 4394 result := (others => 'X'); 4395 when pos_zero | neg_zero | pos_denormal | neg_denormal => 4396 result := (others => '0'); -- return 0 4397 when pos_inf => 4398 result := (others => '1'); 4399 result (result'high) := '0'; 4400 when neg_inf => 4401 result := (others => '0'); 4402 result (result'high) := '1'; 4403 when others => 4404 float_to_unsigned ( 4405 arg => arg, 4406 sign => sign, 4407 frac => frac, 4408 denormalize => false, 4409 bias => 0, 4410 round_style => round_style); 4411 result (size-1) := '0'; 4412 result (size-2 downto 0) := SIGNED(frac (size-2 downto 0)); 4413 if sign = '1' then 4414 -- Because the most negative signed number is 1 less than the most 4415 -- positive signed number, we need this code. 4416 if frac(frac'high) = '1' then -- return most negative number 4417 result := (others => '0'); 4418 result (result'high) := '1'; 4419 else 4420 result := -result; 4421 end if; 4422 else 4423 if frac(frac'high) = '1' then -- return most positive number 4424 result := (others => '1'); 4425 result (result'high) := '0'; 4426 end if; 4427 end if; 4428 end case classcase; 4429 return result; 4430 end function to_signed; 4431 4432 -- purpose: Converts a float to ufixed 4433 function to_ufixed ( 4434 arg : UNRESOLVED_float; -- fp input 4435 constant left_index : INTEGER; -- integer part 4436 constant right_index : INTEGER; -- fraction part 4437 constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate 4438 constant round_style : fixed_round_style_type := fixed_round_style; -- rounding 4439 constant check_error : BOOLEAN := float_check_error; -- check for errors 4440 constant denormalize : BOOLEAN := float_denormalize) 4441 return UNRESOLVED_ufixed is 4442 constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction 4443 constant exponent_width : INTEGER := arg'high; -- length of FP output exponent 4444 constant size : INTEGER := left_index - right_index + 4; -- unsigned size 4445 variable expon_base : INTEGER; -- exponent offset 4446 variable validfp : valid_fpstate; -- Valid FP state 4447 variable exp : INTEGER; -- Exponent 4448 variable expon : UNSIGNED (exponent_width-1 downto 0); -- Vectorized exponent 4449 -- Base to divide fraction by 4450 variable frac : UNSIGNED (size-1 downto 0) := (others => '0'); -- Fraction 4451 variable frac_shift : UNSIGNED (size-1 downto 0); -- Fraction shifted 4452 variable shift : INTEGER; 4453 variable result_big : UNRESOLVED_ufixed (left_index downto right_index-3); 4454 variable result : UNRESOLVED_ufixed (left_index downto right_index); -- result 4455 begin -- function to_ufixed 4456 validfp := classfp (arg, check_error); 4457 classcase : case validfp is 4458 when isx | nan | quiet_nan => 4459 frac := (others => 'X'); 4460 when pos_zero | neg_inf | neg_zero | neg_normal | neg_denormal => 4461 frac := (others => '0'); -- return 0 4462 when pos_inf => 4463 frac := (others => '1'); -- always saturate 4464 when others => 4465 expon_base := 2**(exponent_width-1) -1; -- exponent offset 4466 -- Figure out the fraction 4467 if (validfp = pos_denormal) and denormalize then 4468 exp := -expon_base +1; 4469 frac (frac'high) := '0'; -- Remove the "1.0". 4470 else 4471 -- exponent /= '0', normal floating point 4472 expon := UNSIGNED(arg (exponent_width-1 downto 0)); 4473 expon(exponent_width-1) := not expon(exponent_width-1); 4474 exp := to_integer (SIGNED(expon)) +1; 4475 frac (frac'high) := '1'; -- Add the "1.0". 4476 end if; 4477 shift := (frac'high - 3 + right_index) - exp; 4478 if fraction_width > frac'high then -- Can only use size-2 bits 4479 frac (frac'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto 4480 -frac'high))); 4481 else -- can use all bits 4482 frac (frac'high-1 downto frac'high-fraction_width) := 4483 UNSIGNED (to_slv (arg(-1 downto -fraction_width))); 4484 end if; 4485 frac_shift := frac srl shift; 4486 if shift < 0 then -- Overflow 4487 frac := (others => '1'); 4488 else 4489 frac := frac_shift; 4490 end if; 4491 end case classcase; 4492 result_big := to_ufixed ( 4493 arg => STD_ULOGIC_VECTOR(frac), 4494 left_index => left_index, 4495 right_index => (right_index-3)); 4496 result := resize (arg => result_big, 4497 left_index => left_index, 4498 right_index => right_index, 4499 round_style => round_style, 4500 overflow_style => overflow_style); 4501 return result; 4502 end function to_ufixed; 4503 4504 -- purpose: Converts a float to sfixed 4505 function to_sfixed ( 4506 arg : UNRESOLVED_float; -- fp input 4507 constant left_index : INTEGER; -- integer part 4508 constant right_index : INTEGER; -- fraction part 4509 constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate 4510 constant round_style : fixed_round_style_type := fixed_round_style; -- rounding 4511 constant check_error : BOOLEAN := float_check_error; -- check for errors 4512 constant denormalize : BOOLEAN := float_denormalize) 4513 return UNRESOLVED_sfixed is 4514 constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction 4515 constant exponent_width : INTEGER := arg'high; -- length of FP output exponent 4516 constant size : INTEGER := left_index - right_index + 4; -- unsigned size 4517 variable expon_base : INTEGER; -- exponent offset 4518 variable validfp : valid_fpstate; -- Valid FP state 4519 variable exp : INTEGER; -- Exponent 4520 variable sign : BOOLEAN; -- true if negative 4521 variable expon : UNSIGNED (exponent_width-1 downto 0); -- Vectorized exponent 4522 -- Base to divide fraction by 4523 variable frac : UNSIGNED (size-2 downto 0) := (others => '0'); -- Fraction 4524 variable frac_shift : UNSIGNED (size-2 downto 0); -- Fraction shifted 4525 variable shift : INTEGER; 4526 variable rsigned : SIGNED (size-1 downto 0); -- signed version of result 4527 variable result_big : UNRESOLVED_sfixed (left_index downto right_index-3); 4528 variable result : UNRESOLVED_sfixed (left_index downto right_index) 4529 := (others => '0'); -- result 4530 begin -- function to_sfixed 4531 validfp := classfp (arg, check_error); 4532 classcase : case validfp is 4533 when isx | nan | quiet_nan => 4534 result := (others => 'X'); 4535 when pos_zero | neg_zero => 4536 result := (others => '0'); -- return 0 4537 when neg_inf => 4538 result (left_index) := '1'; -- return smallest negative number 4539 when pos_inf => 4540 result := (others => '1'); -- return largest number 4541 result (left_index) := '0'; 4542 when others => 4543 expon_base := 2**(exponent_width-1) -1; -- exponent offset 4544 if arg(exponent_width) = '0' then 4545 sign := false; 4546 else 4547 sign := true; 4548 end if; 4549 -- Figure out the fraction 4550 if (validfp = pos_denormal or validfp = neg_denormal) 4551 and denormalize then 4552 exp := -expon_base +1; 4553 frac (frac'high) := '0'; -- Add the "1.0". 4554 else 4555 -- exponent /= '0', normal floating point 4556 expon := UNSIGNED(arg (exponent_width-1 downto 0)); 4557 expon(exponent_width-1) := not expon(exponent_width-1); 4558 exp := to_integer (SIGNED(expon)) +1; 4559 frac (frac'high) := '1'; -- Add the "1.0". 4560 end if; 4561 shift := (frac'high - 3 + right_index) - exp; 4562 if fraction_width > frac'high then -- Can only use size-2 bits 4563 frac (frac'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto 4564 -frac'high))); 4565 else -- can use all bits 4566 frac (frac'high-1 downto frac'high-fraction_width) := 4567 UNSIGNED (to_slv (arg(-1 downto -fraction_width))); 4568 end if; 4569 frac_shift := frac srl shift; 4570 if shift < 0 then -- Overflow 4571 frac := (others => '1'); 4572 else 4573 frac := frac_shift; 4574 end if; 4575 if not sign then 4576 rsigned := SIGNED("0" & frac); 4577 else 4578 rsigned := -(SIGNED("0" & frac)); 4579 end if; 4580 result_big := to_sfixed ( 4581 arg => STD_LOGIC_VECTOR(rsigned), 4582 left_index => left_index, 4583 right_index => (right_index-3)); 4584 result := resize (arg => result_big, 4585 left_index => left_index, 4586 right_index => right_index, 4587 round_style => round_style, 4588 overflow_style => overflow_style); 4589 end case classcase; 4590 return result; 4591 end function to_sfixed; 4592 4593 -- size_res versions 4594 -- float to unsigned 4595 function to_unsigned ( 4596 arg : UNRESOLVED_float; -- floating point input 4597 size_res : UNSIGNED; 4598 constant round_style : round_type := float_round_style; -- rounding option 4599 constant check_error : BOOLEAN := float_check_error) -- check for errors 4600 return UNSIGNED is 4601 variable result : UNSIGNED (size_res'range); 4602 begin 4603 if (SIZE_RES'length = 0) then 4604 return result; 4605 else 4606 result := to_unsigned ( 4607 arg => arg, 4608 size => size_res'length, 4609 round_style => round_style, 4610 check_error => check_error); 4611 return result; 4612 end if; 4613 end function to_unsigned; 4614 4615 -- float to signed 4616 function to_signed ( 4617 arg : UNRESOLVED_float; -- floating point input 4618 size_res : SIGNED; 4619 constant round_style : round_type := float_round_style; -- rounding option 4620 constant check_error : BOOLEAN := float_check_error) -- check for errors 4621 return SIGNED is 4622 variable result : SIGNED (size_res'range); 4623 begin 4624 if (SIZE_RES'length = 0) then 4625 return result; 4626 else 4627 result := to_signed ( 4628 arg => arg, 4629 size => size_res'length, 4630 round_style => round_style, 4631 check_error => check_error); 4632 return result; 4633 end if; 4634 end function to_signed; 4635 4636 -- purpose: Converts a float to unsigned fixed point 4637 function to_ufixed ( 4638 arg : UNRESOLVED_float; -- fp input 4639 size_res : UNRESOLVED_ufixed; 4640 constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate 4641 constant round_style : fixed_round_style_type := fixed_round_style; -- rounding 4642 constant check_error : BOOLEAN := float_check_error; -- check for errors 4643 constant denormalize : BOOLEAN := float_denormalize) 4644 return UNRESOLVED_ufixed is 4645 variable result : UNRESOLVED_ufixed (size_res'left downto size_res'right); 4646 begin 4647 if (result'length < 1) then 4648 return result; 4649 else 4650 result := to_ufixed ( 4651 arg => arg, 4652 left_index => size_res'high, 4653 right_index => size_res'low, 4654 overflow_style => overflow_style, 4655 round_style => round_style, 4656 check_error => check_error, 4657 denormalize => denormalize); 4658 return result; 4659 end if; 4660 end function to_ufixed; 4661 4662 -- float to signed fixed point 4663 function to_sfixed ( 4664 arg : UNRESOLVED_float; -- fp input 4665 size_res : UNRESOLVED_sfixed; 4666 constant overflow_style : fixed_overflow_style_type := fixed_overflow_style; -- saturate 4667 constant round_style : fixed_round_style_type := fixed_round_style; -- rounding 4668 constant check_error : BOOLEAN := float_check_error; -- check for errors 4669 constant denormalize : BOOLEAN := float_denormalize) 4670 return UNRESOLVED_sfixed is 4671 variable result : UNRESOLVED_sfixed (size_res'left downto size_res'right); 4672 begin 4673 if (result'length < 1) then 4674 return result; 4675 else 4676 result := to_sfixed ( 4677 arg => arg, 4678 left_index => size_res'high, 4679 right_index => size_res'low, 4680 overflow_style => overflow_style, 4681 round_style => round_style, 4682 check_error => check_error, 4683 denormalize => denormalize); 4684 return result; 4685 end if; 4686 end function to_sfixed; 4687 4688 -- to_real (float) 4689 -- typically not Synthesizable unless the input is a constant. 4690 function to_real ( 4691 arg : UNRESOLVED_float; -- floating point input 4692 constant check_error : BOOLEAN := float_check_error; -- check for errors 4693 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 4694 return REAL is 4695 constant fraction_width : INTEGER := -mine(arg'low, arg'low); -- length of FP output fraction 4696 constant exponent_width : INTEGER := arg'high; -- length of FP output exponent 4697 variable sign : REAL; -- Sign, + or - 1 4698 variable exp : INTEGER; -- Exponent 4699 variable expon_base : INTEGER; -- exponent offset 4700 variable frac : REAL := 0.0; -- Fraction 4701 variable validfp : valid_fpstate; -- Valid FP state 4702 variable expon : UNSIGNED (exponent_width - 1 downto 0) 4703 := (others => '1'); -- Vectorized exponent 4704 begin 4705 validfp := classfp (arg, check_error); 4706 classcase : case validfp is 4707 when isx | pos_zero | neg_zero | nan | quiet_nan => 4708 return 0.0; 4709 when neg_inf => 4710 return REAL'low; -- Negative infinity. 4711 when pos_inf => 4712 return REAL'high; -- Positive infinity 4713 when others => 4714 expon_base := 2**(exponent_width-1) -1; 4715 if to_X01(arg(exponent_width)) = '0' then 4716 sign := 1.0; 4717 else 4718 sign := -1.0; 4719 end if; 4720 -- Figure out the fraction 4721 for i in 0 to fraction_width-1 loop 4722 if to_X01(arg (-1 - i)) = '1' then 4723 frac := frac + (2.0 **(-1 - i)); 4724 end if; 4725 end loop; -- i 4726 if validfp = pos_normal or validfp = neg_normal or not denormalize then 4727 -- exponent /= '0', normal floating point 4728 expon := UNSIGNED(arg (exponent_width-1 downto 0)); 4729 expon(exponent_width-1) := not expon(exponent_width-1); 4730 exp := to_integer (SIGNED(expon)) +1; 4731 sign := sign * (2.0 ** exp) * (1.0 + frac); 4732 else -- exponent = '0', IEEE extended floating point 4733 exp := 1 - expon_base; 4734 sign := sign * (2.0 ** exp) * frac; 4735 end if; 4736 return sign; 4737 end case classcase; 4738 end function to_real; 4739 4740 -- For Verilog compatability 4741 function realtobits (arg : REAL) return STD_ULOGIC_VECTOR is 4742 variable result : float64; -- 64 bit floating point 4743 begin 4744 result := to_float (arg => arg, 4745 exponent_width => float64'high, 4746 fraction_width => -float64'low); 4747 return to_sulv (result); 4748 end function realtobits; 4749 4750 function bitstoreal (arg : STD_ULOGIC_VECTOR) return REAL is 4751 variable arg64 : float64; -- arg converted to float 4752 begin 4753 arg64 := to_float (arg => arg, 4754 exponent_width => float64'high, 4755 fraction_width => -float64'low); 4756 return to_real (arg64); 4757 end function bitstoreal; 4758 4759 -- purpose: Removes meta-logical values from FP string 4760 function to_01 ( 4761 arg : UNRESOLVED_float; -- floating point input 4762 XMAP : STD_LOGIC := '0') 4763 return UNRESOLVED_float is 4764 variable result : UNRESOLVED_float (arg'range); 4765 begin -- function to_01 4766 if (arg'length < 1) then 4767 assert NO_WARNING 4768 report float_pkg'instance_name 4769 & "TO_01: null detected, returning NULL" 4770 severity warning; 4771 return NAFP; 4772 end if; 4773 result := UNRESOLVED_float (STD_LOGIC_VECTOR(to_01(UNSIGNED(to_slv(arg)), XMAP))); 4774 return result; 4775 end function to_01; 4776 4777 function Is_X 4778 (arg : UNRESOLVED_float) 4779 return BOOLEAN is 4780 begin 4781 return Is_X (to_slv(arg)); 4782 end function Is_X; 4783 4784 function to_X01 (arg : UNRESOLVED_float) return UNRESOLVED_float is 4785 variable result : UNRESOLVED_float (arg'range); 4786 begin 4787 if (arg'length < 1) then 4788 assert NO_WARNING 4789 report float_pkg'instance_name 4790 & "TO_X01: null detected, returning NULL" 4791 severity warning; 4792 return NAFP; 4793 else 4794 result := UNRESOLVED_float (to_X01(to_slv(arg))); 4795 return result; 4796 end if; 4797 end function to_X01; 4798 4799 function to_X01Z (arg : UNRESOLVED_float) return UNRESOLVED_float is 4800 variable result : UNRESOLVED_float (arg'range); 4801 begin 4802 if (arg'length < 1) then 4803 assert NO_WARNING 4804 report float_pkg'instance_name 4805 & "TO_X01Z: null detected, returning NULL" 4806 severity warning; 4807 return NAFP; 4808 else 4809 result := UNRESOLVED_float (to_X01Z(to_slv(arg))); 4810 return result; 4811 end if; 4812 end function to_X01Z; 4813 4814 function to_UX01 (arg : UNRESOLVED_float) return UNRESOLVED_float is 4815 variable result : UNRESOLVED_float (arg'range); 4816 begin 4817 if (arg'length < 1) then 4818 assert NO_WARNING 4819 report float_pkg'instance_name 4820 & "TO_UX01: null detected, returning NULL" 4821 severity warning; 4822 return NAFP; 4823 else 4824 result := UNRESOLVED_float (to_UX01(to_slv(arg))); 4825 return result; 4826 end if; 4827 end function to_UX01; 4828 4829 -- These allows the base math functions to use the default values 4830 -- of their parameters. Thus they do full IEEE floating point. 4831 function "+" (l, r : UNRESOLVED_float) return UNRESOLVED_float is 4832 begin 4833 return add (l, r); 4834 end function "+"; 4835 4836 function "-" (l, r : UNRESOLVED_float) return UNRESOLVED_float is 4837 begin 4838 return subtract (l, r); 4839 end function "-"; 4840 4841 function "*" (l, r : UNRESOLVED_float) return UNRESOLVED_float is 4842 begin 4843 return multiply (l, r); 4844 end function "*"; 4845 4846 function "/" (l, r : UNRESOLVED_float) return UNRESOLVED_float is 4847 begin 4848 return divide (l, r); 4849 end function "/"; 4850 4851 function "rem" (l, r : UNRESOLVED_float) return UNRESOLVED_float is 4852 begin 4853 return remainder (l, r); 4854 end function "rem"; 4855 4856 function "mod" (l, r : UNRESOLVED_float) return UNRESOLVED_float is 4857 begin 4858 return modulo (l, r); 4859 end function "mod"; 4860 4861 -- overloaded versions 4862 function "+" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is 4863 variable r_float : UNRESOLVED_float (l'range); 4864 begin 4865 r_float := to_float (r, l'high, -l'low); 4866 return add (l, r_float); 4867 end function "+"; 4868 4869 function "+" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is 4870 variable l_float : UNRESOLVED_float (r'range); 4871 begin 4872 l_float := to_float(l, r'high, -r'low); 4873 return add (l_float, r); 4874 end function "+"; 4875 4876 function "+" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is 4877 variable r_float : UNRESOLVED_float (l'range); 4878 begin 4879 r_float := to_float (r, l'high, -l'low); 4880 return add (l, r_float); 4881 end function "+"; 4882 4883 function "+" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is 4884 variable l_float : UNRESOLVED_float (r'range); 4885 begin 4886 l_float := to_float(l, r'high, -r'low); 4887 return add (l_float, r); 4888 end function "+"; 4889 4890 function "-" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is 4891 variable r_float : UNRESOLVED_float (l'range); 4892 begin 4893 r_float := to_float (r, l'high, -l'low); 4894 return subtract (l, r_float); 4895 end function "-"; 4896 4897 function "-" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is 4898 variable l_float : UNRESOLVED_float (r'range); 4899 begin 4900 l_float := to_float(l, r'high, -r'low); 4901 return subtract (l_float, r); 4902 end function "-"; 4903 4904 function "-" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is 4905 variable r_float : UNRESOLVED_float (l'range); 4906 begin 4907 r_float := to_float (r, l'high, -l'low); 4908 return subtract (l, r_float); 4909 end function "-"; 4910 4911 function "-" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is 4912 variable l_float : UNRESOLVED_float (r'range); 4913 begin 4914 l_float := to_float(l, r'high, -r'low); 4915 return subtract (l_float, r); 4916 end function "-"; 4917 4918 function "*" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is 4919 variable r_float : UNRESOLVED_float (l'range); 4920 begin 4921 r_float := to_float (r, l'high, -l'low); 4922 return multiply (l, r_float); 4923 end function "*"; 4924 4925 function "*" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is 4926 variable l_float : UNRESOLVED_float (r'range); 4927 begin 4928 l_float := to_float(l, r'high, -r'low); 4929 return multiply (l_float, r); 4930 end function "*"; 4931 4932 function "*" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is 4933 variable r_float : UNRESOLVED_float (l'range); 4934 begin 4935 r_float := to_float (r, l'high, -l'low); 4936 return multiply (l, r_float); 4937 end function "*"; 4938 4939 function "*" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is 4940 variable l_float : UNRESOLVED_float (r'range); 4941 begin 4942 l_float := to_float(l, r'high, -r'low); 4943 return multiply (l_float, r); 4944 end function "*"; 4945 4946 function "/" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is 4947 variable r_float : UNRESOLVED_float (l'range); 4948 begin 4949 r_float := to_float (r, l'high, -l'low); 4950 return divide (l, r_float); 4951 end function "/"; 4952 4953 function "/" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is 4954 variable l_float : UNRESOLVED_float (r'range); 4955 begin 4956 l_float := to_float(l, r'high, -r'low); 4957 return divide (l_float, r); 4958 end function "/"; 4959 4960 function "/" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is 4961 variable r_float : UNRESOLVED_float (l'range); 4962 begin 4963 r_float := to_float (r, l'high, -l'low); 4964 return divide (l, r_float); 4965 end function "/"; 4966 4967 function "/" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is 4968 variable l_float : UNRESOLVED_float (r'range); 4969 begin 4970 l_float := to_float(l, r'high, -r'low); 4971 return divide (l_float, r); 4972 end function "/"; 4973 4974 function "rem" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is 4975 variable r_float : UNRESOLVED_float (l'range); 4976 begin 4977 r_float := to_float (r, l'high, -l'low); 4978 return remainder (l, r_float); 4979 end function "rem"; 4980 4981 function "rem" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is 4982 variable l_float : UNRESOLVED_float (r'range); 4983 begin 4984 l_float := to_float(l, r'high, -r'low); 4985 return remainder (l_float, r); 4986 end function "rem"; 4987 4988 function "rem" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is 4989 variable r_float : UNRESOLVED_float (l'range); 4990 begin 4991 r_float := to_float (r, l'high, -l'low); 4992 return remainder (l, r_float); 4993 end function "rem"; 4994 4995 function "rem" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is 4996 variable l_float : UNRESOLVED_float (r'range); 4997 begin 4998 l_float := to_float(l, r'high, -r'low); 4999 return remainder (l_float, r); 5000 end function "rem"; 5001 5002 function "mod" (l : UNRESOLVED_float; r : REAL) return UNRESOLVED_float is 5003 variable r_float : UNRESOLVED_float (l'range); 5004 begin 5005 r_float := to_float (r, l'high, -l'low); 5006 return modulo (l, r_float); 5007 end function "mod"; 5008 5009 function "mod" (l : REAL; r : UNRESOLVED_float) return UNRESOLVED_float is 5010 variable l_float : UNRESOLVED_float (r'range); 5011 begin 5012 l_float := to_float(l, r'high, -r'low); 5013 return modulo (l_float, r); 5014 end function "mod"; 5015 5016 function "mod" (l : UNRESOLVED_float; r : INTEGER) return UNRESOLVED_float is 5017 variable r_float : UNRESOLVED_float (l'range); 5018 begin 5019 r_float := to_float (r, l'high, -l'low); 5020 return modulo (l, r_float); 5021 end function "mod"; 5022 5023 function "mod" (l : INTEGER; r : UNRESOLVED_float) return UNRESOLVED_float is 5024 variable l_float : UNRESOLVED_float (r'range); 5025 begin 5026 l_float := to_float(l, r'high, -r'low); 5027 return modulo (l_float, r); 5028 end function "mod"; 5029 5030 function "=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is 5031 variable r_float : UNRESOLVED_float (l'range); 5032 begin 5033 r_float := to_float (r, l'high, -l'low); 5034 return eq (l, r_float); 5035 end function "="; 5036 5037 function "/=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is 5038 variable r_float : UNRESOLVED_float (l'range); 5039 begin 5040 r_float := to_float (r, l'high, -l'low); 5041 return ne (l, r_float); 5042 end function "/="; 5043 5044 function ">=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is 5045 variable r_float : UNRESOLVED_float (l'range); 5046 begin 5047 r_float := to_float (r, l'high, -l'low); 5048 return ge (l, r_float); 5049 end function ">="; 5050 5051 function "<=" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is 5052 variable r_float : UNRESOLVED_float (l'range); 5053 begin 5054 r_float := to_float (r, l'high, -l'low); 5055 return le (l, r_float); 5056 end function "<="; 5057 5058 function ">" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is 5059 variable r_float : UNRESOLVED_float (l'range); 5060 begin 5061 r_float := to_float (r, l'high, -l'low); 5062 return gt (l, r_float); 5063 end function ">"; 5064 5065 function "<" (l : UNRESOLVED_float; r : REAL) return BOOLEAN is 5066 variable r_float : UNRESOLVED_float (l'range); 5067 begin 5068 r_float := to_float (r, l'high, -l'low); 5069 return lt (l, r_float); 5070 end function "<"; 5071 5072 function "=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is 5073 variable l_float : UNRESOLVED_float (r'range); 5074 begin 5075 l_float := to_float(l, r'high, -r'low); 5076 return eq (l_float, r); 5077 end function "="; 5078 5079 function "/=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is 5080 variable l_float : UNRESOLVED_float (r'range); 5081 begin 5082 l_float := to_float(l, r'high, -r'low); 5083 return ne (l_float, r); 5084 end function "/="; 5085 5086 function ">=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is 5087 variable l_float : UNRESOLVED_float (r'range); 5088 begin 5089 l_float := to_float(l, r'high, -r'low); 5090 return ge (l_float, r); 5091 end function ">="; 5092 5093 function "<=" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is 5094 variable l_float : UNRESOLVED_float (r'range); 5095 begin 5096 l_float := to_float(l, r'high, -r'low); 5097 return le (l_float, r); 5098 end function "<="; 5099 5100 function ">" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is 5101 variable l_float : UNRESOLVED_float (r'range); 5102 begin 5103 l_float := to_float(l, r'high, -r'low); 5104 return gt (l_float, r); 5105 end function ">"; 5106 5107 function "<" (l : REAL; r : UNRESOLVED_float) return BOOLEAN is 5108 variable l_float : UNRESOLVED_float (r'range); 5109 begin 5110 l_float := to_float(l, r'high, -r'low); 5111 return lt (l_float, r); 5112 end function "<"; 5113 5114 function "=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is 5115 variable r_float : UNRESOLVED_float (l'range); 5116 begin 5117 r_float := to_float (r, l'high, -l'low); 5118 return eq (l, r_float); 5119 end function "="; 5120 5121 function "/=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is 5122 variable r_float : UNRESOLVED_float (l'range); 5123 begin 5124 r_float := to_float (r, l'high, -l'low); 5125 return ne (l, r_float); 5126 end function "/="; 5127 5128 function ">=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is 5129 variable r_float : UNRESOLVED_float (l'range); 5130 begin 5131 r_float := to_float (r, l'high, -l'low); 5132 return ge (l, r_float); 5133 end function ">="; 5134 5135 function "<=" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is 5136 variable r_float : UNRESOLVED_float (l'range); 5137 begin 5138 r_float := to_float (r, l'high, -l'low); 5139 return le (l, r_float); 5140 end function "<="; 5141 5142 function ">" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is 5143 variable r_float : UNRESOLVED_float (l'range); 5144 begin 5145 r_float := to_float (r, l'high, -l'low); 5146 return gt (l, r_float); 5147 end function ">"; 5148 5149 function "<" (l : UNRESOLVED_float; r : INTEGER) return BOOLEAN is 5150 variable r_float : UNRESOLVED_float (l'range); 5151 begin 5152 r_float := to_float (r, l'high, -l'low); 5153 return lt (l, r_float); 5154 end function "<"; 5155 5156 function "=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is 5157 variable l_float : UNRESOLVED_float (r'range); 5158 begin 5159 l_float := to_float(l, r'high, -r'low); 5160 return eq (l_float, r); 5161 end function "="; 5162 5163 function "/=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is 5164 variable l_float : UNRESOLVED_float (r'range); 5165 begin 5166 l_float := to_float(l, r'high, -r'low); 5167 return ne (l_float, r); 5168 end function "/="; 5169 5170 function ">=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is 5171 variable l_float : UNRESOLVED_float (r'range); 5172 begin 5173 l_float := to_float(l, r'high, -r'low); 5174 return ge (l_float, r); 5175 end function ">="; 5176 5177 function "<=" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is 5178 variable l_float : UNRESOLVED_float (r'range); 5179 begin 5180 l_float := to_float(l, r'high, -r'low); 5181 return le (l_float, r); 5182 end function "<="; 5183 5184 function ">" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is 5185 variable l_float : UNRESOLVED_float (r'range); 5186 begin 5187 l_float := to_float(l, r'high, -r'low); 5188 return gt (l_float, r); 5189 end function ">"; 5190 5191 function "<" (l : INTEGER; r : UNRESOLVED_float) return BOOLEAN is 5192 variable l_float : UNRESOLVED_float (r'range); 5193 begin 5194 l_float := to_float(l, r'high, -r'low); 5195 return lt (l_float, r); 5196 end function "<"; 5197 5198 -- ?= overloads 5199 function \?=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is 5200 variable r_float : UNRESOLVED_float (l'range); 5201 begin 5202 r_float := to_float (r, l'high, -l'low); 5203 return \?=\ (l, r_float); 5204 end function \?=\; 5205 5206 function \?/=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is 5207 variable r_float : UNRESOLVED_float (l'range); 5208 begin 5209 r_float := to_float (r, l'high, -l'low); 5210 return \?/=\ (l, r_float); 5211 end function \?/=\; 5212 5213 function \?>\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is 5214 variable r_float : UNRESOLVED_float (l'range); 5215 begin 5216 r_float := to_float (r, l'high, -l'low); 5217 return \?>\ (l, r_float); 5218 end function \?>\; 5219 5220 function \?>=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is 5221 variable r_float : UNRESOLVED_float (l'range); 5222 begin 5223 r_float := to_float (r, l'high, -l'low); 5224 return \?>=\ (l, r_float); 5225 end function \?>=\; 5226 5227 function \?<\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is 5228 variable r_float : UNRESOLVED_float (l'range); 5229 begin 5230 r_float := to_float (r, l'high, -l'low); 5231 return \?<\ (l, r_float); 5232 end function \?<\; 5233 5234 function \?<=\ (l : UNRESOLVED_float; r : REAL) return STD_ULOGIC is 5235 variable r_float : UNRESOLVED_float (l'range); 5236 begin 5237 r_float := to_float (r, l'high, -l'low); 5238 return \?<=\ (l, r_float); 5239 end function \?<=\; 5240 5241 -- real and float 5242 function \?=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is 5243 variable l_float : UNRESOLVED_float (r'range); 5244 begin 5245 l_float := to_float (l, r'high, -r'low); 5246 return \?=\ (l_float, r); 5247 end function \?=\; 5248 5249 function \?/=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is 5250 variable l_float : UNRESOLVED_float (r'range); 5251 begin 5252 l_float := to_float (l, r'high, -r'low); 5253 return \?/=\ (l_float, r); 5254 end function \?/=\; 5255 5256 function \?>\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is 5257 variable l_float : UNRESOLVED_float (r'range); 5258 begin 5259 l_float := to_float (l, r'high, -r'low); 5260 return \?>\ (l_float, r); 5261 end function \?>\; 5262 5263 function \?>=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is 5264 variable l_float : UNRESOLVED_float (r'range); 5265 begin 5266 l_float := to_float (l, r'high, -r'low); 5267 return \?>=\ (l_float, r); 5268 end function \?>=\; 5269 5270 function \?<\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is 5271 variable l_float : UNRESOLVED_float (r'range); 5272 begin 5273 l_float := to_float (l, r'high, -r'low); 5274 return \?<\ (l_float, r); 5275 end function \?<\; 5276 5277 function \?<=\ (l : REAL; r : UNRESOLVED_float) return STD_ULOGIC is 5278 variable l_float : UNRESOLVED_float (r'range); 5279 begin 5280 l_float := to_float (l, r'high, -r'low); 5281 return \?<=\ (l_float, r); 5282 end function \?<=\; 5283 5284 -- ?= overloads 5285 function \?=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is 5286 variable r_float : UNRESOLVED_float (l'range); 5287 begin 5288 r_float := to_float (r, l'high, -l'low); 5289 return \?=\ (l, r_float); 5290 end function \?=\; 5291 5292 function \?/=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is 5293 variable r_float : UNRESOLVED_float (l'range); 5294 begin 5295 r_float := to_float (r, l'high, -l'low); 5296 return \?/=\ (l, r_float); 5297 end function \?/=\; 5298 5299 function \?>\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is 5300 variable r_float : UNRESOLVED_float (l'range); 5301 begin 5302 r_float := to_float (r, l'high, -l'low); 5303 return \?>\ (l, r_float); 5304 end function \?>\; 5305 5306 function \?>=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is 5307 variable r_float : UNRESOLVED_float (l'range); 5308 begin 5309 r_float := to_float (r, l'high, -l'low); 5310 return \?>=\ (l, r_float); 5311 end function \?>=\; 5312 5313 function \?<\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is 5314 variable r_float : UNRESOLVED_float (l'range); 5315 begin 5316 r_float := to_float (r, l'high, -l'low); 5317 return \?<\ (l, r_float); 5318 end function \?<\; 5319 5320 function \?<=\ (l : UNRESOLVED_float; r : INTEGER) return STD_ULOGIC is 5321 variable r_float : UNRESOLVED_float (l'range); 5322 begin 5323 r_float := to_float (r, l'high, -l'low); 5324 return \?<=\ (l, r_float); 5325 end function \?<=\; 5326 5327 -- integer and float 5328 function \?=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is 5329 variable l_float : UNRESOLVED_float (r'range); 5330 begin 5331 l_float := to_float (l, r'high, -r'low); 5332 return \?=\ (l_float, r); 5333 end function \?=\; 5334 5335 function \?/=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is 5336 variable l_float : UNRESOLVED_float (r'range); 5337 begin 5338 l_float := to_float (l, r'high, -r'low); 5339 return \?/=\ (l_float, r); 5340 end function \?/=\; 5341 5342 function \?>\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is 5343 variable l_float : UNRESOLVED_float (r'range); 5344 begin 5345 l_float := to_float (l, r'high, -r'low); 5346 return \?>\ (l_float, r); 5347 end function \?>\; 5348 5349 function \?>=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is 5350 variable l_float : UNRESOLVED_float (r'range); 5351 begin 5352 l_float := to_float (l, r'high, -r'low); 5353 return \?>=\ (l_float, r); 5354 end function \?>=\; 5355 5356 function \?<\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is 5357 variable l_float : UNRESOLVED_float (r'range); 5358 begin 5359 l_float := to_float (l, r'high, -r'low); 5360 return \?<\ (l_float, r); 5361 end function \?<\; 5362 5363 function \?<=\ (l : INTEGER; r : UNRESOLVED_float) return STD_ULOGIC is 5364 variable l_float : UNRESOLVED_float (r'range); 5365 begin 5366 l_float := to_float (l, r'high, -r'low); 5367 return \?<=\ (l_float, r); 5368 end function \?<=\; 5369 5370 -- minimum and maximum overloads 5371 function minimum (l : UNRESOLVED_float; r : REAL) 5372 return UNRESOLVED_float is 5373 variable r_float : UNRESOLVED_float (l'range); 5374 begin 5375 r_float := to_float (r, l'high, -l'low); 5376 return minimum (l, r_float); 5377 end function minimum; 5378 5379 function maximum (l : UNRESOLVED_float; r : REAL) 5380 return UNRESOLVED_float is 5381 variable r_float : UNRESOLVED_float (l'range); 5382 begin 5383 r_float := to_float (r, l'high, -l'low); 5384 return maximum (l, r_float); 5385 end function maximum; 5386 5387 function minimum (l : REAL; r : UNRESOLVED_float) 5388 return UNRESOLVED_float is 5389 variable l_float : UNRESOLVED_float (r'range); 5390 begin 5391 l_float := to_float (l, r'high, -r'low); 5392 return minimum (l_float, r); 5393 end function minimum; 5394 5395 function maximum (l : REAL; r : UNRESOLVED_float) 5396 return UNRESOLVED_float is 5397 variable l_float : UNRESOLVED_float (r'range); 5398 begin 5399 l_float := to_float (l, r'high, -r'low); 5400 return maximum (l_float, r); 5401 end function maximum; 5402 5403 function minimum (l : UNRESOLVED_float; r : INTEGER) 5404 return UNRESOLVED_float is 5405 variable r_float : UNRESOLVED_float (l'range); 5406 begin 5407 r_float := to_float (r, l'high, -l'low); 5408 return minimum (l, r_float); 5409 end function minimum; 5410 5411 function maximum (l : UNRESOLVED_float; r : INTEGER) 5412 return UNRESOLVED_float is 5413 variable r_float : UNRESOLVED_float (l'range); 5414 begin 5415 r_float := to_float (r, l'high, -l'low); 5416 return maximum (l, r_float); 5417 end function maximum; 5418 5419 function minimum (l : INTEGER; r : UNRESOLVED_float) 5420 return UNRESOLVED_float is 5421 variable l_float : UNRESOLVED_float (r'range); 5422 begin 5423 l_float := to_float (l, r'high, -r'low); 5424 return minimum (l_float, r); 5425 end function minimum; 5426 5427 function maximum (l : INTEGER; r : UNRESOLVED_float) 5428 return UNRESOLVED_float is 5429 variable l_float : UNRESOLVED_float (r'range); 5430 begin 5431 l_float := to_float (l, r'high, -r'low); 5432 return maximum (l_float, r); 5433 end function maximum; 5434 5435 ---------------------------------------------------------------------------- 5436 -- logical functions 5437 ---------------------------------------------------------------------------- 5438 function "not" (L : UNRESOLVED_float) return UNRESOLVED_float is 5439 variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto 5440 begin 5441 RESULT := not to_sulv(L); 5442 return to_float (RESULT, L'high, -L'low); 5443 end function "not"; 5444 5445 function "and" (L, R : UNRESOLVED_float) return UNRESOLVED_float is 5446 variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto 5447 begin 5448 if (L'high = R'high and L'low = R'low) then 5449 RESULT := to_sulv(L) and to_sulv(R); 5450 else 5451 assert NO_WARNING 5452 report float_pkg'instance_name 5453 & """and"": Range error L'RANGE /= R'RANGE" 5454 severity warning; 5455 RESULT := (others => 'X'); 5456 end if; 5457 return to_float (RESULT, L'high, -L'low); 5458 end function "and"; 5459 5460 function "or" (L, R : UNRESOLVED_float) return UNRESOLVED_float is 5461 variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto 5462 begin 5463 if (L'high = R'high and L'low = R'low) then 5464 RESULT := to_sulv(L) or to_sulv(R); 5465 else 5466 assert NO_WARNING 5467 report float_pkg'instance_name 5468 & """or"": Range error L'RANGE /= R'RANGE" 5469 severity warning; 5470 RESULT := (others => 'X'); 5471 end if; 5472 return to_float (RESULT, L'high, -L'low); 5473 end function "or"; 5474 5475 function "nand" (L, R : UNRESOLVED_float) return UNRESOLVED_float is 5476 variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto 5477 begin 5478 if (L'high = R'high and L'low = R'low) then 5479 RESULT := to_sulv(L) nand to_sulv(R); 5480 else 5481 assert NO_WARNING 5482 report float_pkg'instance_name 5483 & """nand"": Range error L'RANGE /= R'RANGE" 5484 severity warning; 5485 RESULT := (others => 'X'); 5486 end if; 5487 return to_float (RESULT, L'high, -L'low); 5488 end function "nand"; 5489 5490 function "nor" (L, R : UNRESOLVED_float) return UNRESOLVED_float is 5491 variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto 5492 begin 5493 if (L'high = R'high and L'low = R'low) then 5494 RESULT := to_sulv(L) nor to_sulv(R); 5495 else 5496 assert NO_WARNING 5497 report float_pkg'instance_name 5498 & """nor"": Range error L'RANGE /= R'RANGE" 5499 severity warning; 5500 RESULT := (others => 'X'); 5501 end if; 5502 return to_float (RESULT, L'high, -L'low); 5503 end function "nor"; 5504 5505 function "xor" (L, R : UNRESOLVED_float) return UNRESOLVED_float is 5506 variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto 5507 begin 5508 if (L'high = R'high and L'low = R'low) then 5509 RESULT := to_sulv(L) xor to_sulv(R); 5510 else 5511 assert NO_WARNING 5512 report float_pkg'instance_name 5513 & """xor"": Range error L'RANGE /= R'RANGE" 5514 severity warning; 5515 RESULT := (others => 'X'); 5516 end if; 5517 return to_float (RESULT, L'high, -L'low); 5518 end function "xor"; 5519 5520 function "xnor" (L, R : UNRESOLVED_float) return UNRESOLVED_float is 5521 variable RESULT : STD_ULOGIC_VECTOR(L'length-1 downto 0); -- force downto 5522 begin 5523 if (L'high = R'high and L'low = R'low) then 5524 RESULT := to_sulv(L) xnor to_sulv(R); 5525 else 5526 assert NO_WARNING 5527 report float_pkg'instance_name 5528 & """xnor"": Range error L'RANGE /= R'RANGE" 5529 severity warning; 5530 RESULT := (others => 'X'); 5531 end if; 5532 return to_float (RESULT, L'high, -L'low); 5533 end function "xnor"; 5534 5535 -- Vector and std_ulogic functions, same as functions in numeric_std 5536 function "and" (L : STD_ULOGIC; R : UNRESOLVED_float) 5537 return UNRESOLVED_float is 5538 variable result : UNRESOLVED_float (R'range); 5539 begin 5540 for i in result'range loop 5541 result(i) := L and R(i); 5542 end loop; 5543 return result; 5544 end function "and"; 5545 5546 function "and" (L : UNRESOLVED_float; R : STD_ULOGIC) 5547 return UNRESOLVED_float is 5548 variable result : UNRESOLVED_float (L'range); 5549 begin 5550 for i in result'range loop 5551 result(i) := L(i) and R; 5552 end loop; 5553 return result; 5554 end function "and"; 5555 5556 function "or" (L : STD_ULOGIC; R : UNRESOLVED_float) 5557 return UNRESOLVED_float is 5558 variable result : UNRESOLVED_float (R'range); 5559 begin 5560 for i in result'range loop 5561 result(i) := L or R(i); 5562 end loop; 5563 return result; 5564 end function "or"; 5565 5566 function "or" (L : UNRESOLVED_float; R : STD_ULOGIC) 5567 return UNRESOLVED_float is 5568 variable result : UNRESOLVED_float (L'range); 5569 begin 5570 for i in result'range loop 5571 result(i) := L(i) or R; 5572 end loop; 5573 return result; 5574 end function "or"; 5575 5576 function "nand" (L : STD_ULOGIC; R : UNRESOLVED_float) 5577 return UNRESOLVED_float is 5578 variable result : UNRESOLVED_float (R'range); 5579 begin 5580 for i in result'range loop 5581 result(i) := L nand R(i); 5582 end loop; 5583 return result; 5584 end function "nand"; 5585 5586 function "nand" (L : UNRESOLVED_float; R : STD_ULOGIC) 5587 return UNRESOLVED_float is 5588 variable result : UNRESOLVED_float (L'range); 5589 begin 5590 for i in result'range loop 5591 result(i) := L(i) nand R; 5592 end loop; 5593 return result; 5594 end function "nand"; 5595 5596 function "nor" (L : STD_ULOGIC; R : UNRESOLVED_float) 5597 return UNRESOLVED_float is 5598 variable result : UNRESOLVED_float (R'range); 5599 begin 5600 for i in result'range loop 5601 result(i) := L nor R(i); 5602 end loop; 5603 return result; 5604 end function "nor"; 5605 5606 function "nor" (L : UNRESOLVED_float; R : STD_ULOGIC) 5607 return UNRESOLVED_float is 5608 variable result : UNRESOLVED_float (L'range); 5609 begin 5610 for i in result'range loop 5611 result(i) := L(i) nor R; 5612 end loop; 5613 return result; 5614 end function "nor"; 5615 5616 function "xor" (L : STD_ULOGIC; R : UNRESOLVED_float) 5617 return UNRESOLVED_float is 5618 variable result : UNRESOLVED_float (R'range); 5619 begin 5620 for i in result'range loop 5621 result(i) := L xor R(i); 5622 end loop; 5623 return result; 5624 end function "xor"; 5625 5626 function "xor" (L : UNRESOLVED_float; R : STD_ULOGIC) 5627 return UNRESOLVED_float is 5628 variable result : UNRESOLVED_float (L'range); 5629 begin 5630 for i in result'range loop 5631 result(i) := L(i) xor R; 5632 end loop; 5633 return result; 5634 end function "xor"; 5635 5636 function "xnor" (L : STD_ULOGIC; R : UNRESOLVED_float) 5637 return UNRESOLVED_float is 5638 variable result : UNRESOLVED_float (R'range); 5639 begin 5640 for i in result'range loop 5641 result(i) := L xnor R(i); 5642 end loop; 5643 return result; 5644 end function "xnor"; 5645 5646 function "xnor" (L : UNRESOLVED_float; R : STD_ULOGIC) 5647 return UNRESOLVED_float is 5648 variable result : UNRESOLVED_float (L'range); 5649 begin 5650 for i in result'range loop 5651 result(i) := L(i) xnor R; 5652 end loop; 5653 return result; 5654 end function "xnor"; 5655 5656 -- Reduction operator_reduces, same as numeric_std functions 5657 5658 function and_reduce (l : UNRESOLVED_float) return STD_ULOGIC is 5659 begin 5660 return and_reduce (to_sulv(l)); 5661 end function and_reduce; 5662 5663 function nand_reduce (l : UNRESOLVED_float) return STD_ULOGIC is 5664 begin 5665 return nand_reduce (to_sulv(l)); 5666 end function nand_reduce; 5667 5668 function or_reduce (l : UNRESOLVED_float) return STD_ULOGIC is 5669 begin 5670 return or_reduce (to_sulv(l)); 5671 end function or_reduce; 5672 5673 function nor_reduce (l : UNRESOLVED_float) return STD_ULOGIC is 5674 begin 5675 return nor_reduce (to_sulv(l)); 5676 end function nor_reduce; 5677 5678 function xor_reduce (l : UNRESOLVED_float) return STD_ULOGIC is 5679 begin 5680 return xor_reduce (to_sulv(l)); 5681 end function xor_reduce; 5682 5683 function xnor_reduce (l : UNRESOLVED_float) return STD_ULOGIC is 5684 begin 5685 return xnor_reduce (to_sulv(l)); 5686 end function xnor_reduce; 5687 5688 ----------------------------------------------------------------------------- 5689 -- Recommended Functions from the IEEE 754 Appendix 5690 ----------------------------------------------------------------------------- 5691 -- returns x with the sign of y. 5692 function Copysign ( 5693 x, y : UNRESOLVED_float) -- floating point input 5694 return UNRESOLVED_float is 5695 begin 5696 return y(y'high) & x (x'high-1 downto x'low); 5697 end function Copysign; 5698 5699 -- Returns y * 2**n for integral values of N without computing 2**n 5700 function Scalb ( 5701 y : UNRESOLVED_float; -- floating point input 5702 N : INTEGER; -- exponent to add 5703 constant round_style : round_type := float_round_style; -- rounding option 5704 constant check_error : BOOLEAN := float_check_error; -- check for errors 5705 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 5706 return UNRESOLVED_float is 5707 constant fraction_width : NATURAL := -mine(y'low, y'low); -- length of FP output fraction 5708 constant exponent_width : NATURAL := y'high; -- length of FP output exponent 5709 variable arg, result : UNRESOLVED_float (exponent_width downto -fraction_width); -- internal argument 5710 variable expon : SIGNED (exponent_width-1 downto 0); -- Vectorized exp 5711 variable exp : SIGNED (exponent_width downto 0); 5712 variable ufract : UNSIGNED (fraction_width downto 0); 5713 constant expon_base : SIGNED (exponent_width-1 downto 0) 5714 := gen_expon_base(exponent_width); -- exponent offset 5715 variable fptype : valid_fpstate; 5716 begin 5717 -- This can be done by simply adding N to the exponent. 5718 arg := to_01 (y, 'X'); 5719 fptype := classfp(arg, check_error); 5720 classcase : case fptype is 5721 when isx => 5722 result := (others => 'X'); 5723 when nan | quiet_nan => 5724 -- Return quiet NAN, IEEE754-1985-7.1,1 5725 result := qnanfp (fraction_width => fraction_width, 5726 exponent_width => exponent_width); 5727 when others => 5728 break_number ( 5729 arg => arg, 5730 fptyp => fptype, 5731 denormalize => denormalize, 5732 fract => ufract, 5733 expon => expon); 5734 exp := resize (expon, exp'length) + N; 5735 result := normalize ( 5736 fract => ufract, 5737 expon => exp, 5738 sign => to_x01 (arg (arg'high)), 5739 fraction_width => fraction_width, 5740 exponent_width => exponent_width, 5741 round_style => round_style, 5742 denormalize => denormalize, 5743 nguard => 0); 5744 end case classcase; 5745 return result; 5746 end function Scalb; 5747 5748 -- Returns y * 2**n for integral values of N without computing 2**n 5749 function Scalb ( 5750 y : UNRESOLVED_float; -- floating point input 5751 N : SIGNED; -- exponent to add 5752 constant round_style : round_type := float_round_style; -- rounding option 5753 constant check_error : BOOLEAN := float_check_error; -- check for errors 5754 constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP 5755 return UNRESOLVED_float is 5756 variable n_int : INTEGER; 5757 begin 5758 n_int := to_integer(N); 5759 return Scalb (y => y, 5760 N => n_int, 5761 round_style => round_style, 5762 check_error => check_error, 5763 denormalize => denormalize); 5764 end function Scalb; 5765 5766 -- returns the unbiased exponent of x 5767 function Logb ( 5768 x : UNRESOLVED_float) -- floating point input 5769 return INTEGER is 5770 constant fraction_width : NATURAL := -mine (x'low, x'low); -- length of FP output fraction 5771 constant exponent_width : NATURAL := x'high; -- length of FP output exponent 5772 variable result : INTEGER; -- result 5773 variable arg : UNRESOLVED_float (exponent_width downto -fraction_width); -- internal argument 5774 variable expon : SIGNED (exponent_width - 1 downto 0); 5775 variable fract : UNSIGNED (fraction_width downto 0); 5776 constant expon_base : INTEGER := 2**(exponent_width-1) -1; -- exponent 5777 -- offset +1 5778 variable fptype : valid_fpstate; 5779 begin 5780 -- Just return the exponent. 5781 arg := to_01 (x, 'X'); 5782 fptype := classfp(arg); 5783 classcase : case fptype is 5784 when isx | nan | quiet_nan => 5785 -- Return quiet NAN, IEEE754-1985-7.1,1 5786 result := 0; 5787 when pos_denormal | neg_denormal => 5788 fract (fraction_width) := '0'; 5789 fract (fraction_width-1 downto 0) := 5790 UNSIGNED (to_slv(arg(-1 downto -fraction_width))); 5791 result := find_leftmost (fract, '1') -- Find the first "1" 5792 - fraction_width; -- subtract the length we want 5793 result := -expon_base + 1 + result; 5794 when others => 5795 expon := SIGNED(arg (exponent_width - 1 downto 0)); 5796 expon(exponent_width-1) := not expon(exponent_width-1); 5797 expon := expon + 1; 5798 result := to_integer (expon); 5799 end case classcase; 5800 return result; 5801 end function Logb; 5802 5803 -- returns the unbiased exponent of x 5804 function Logb ( 5805 x : UNRESOLVED_float) -- floating point input 5806 return SIGNED is 5807 constant exponent_width : NATURAL := x'high; -- length of FP output exponent 5808 variable result : SIGNED (exponent_width - 1 downto 0); -- result 5809 begin 5810 -- Just return the exponent. 5811 result := to_signed (Logb (x), exponent_width); 5812 return result; 5813 end function Logb; 5814 5815 -- returns the next representable neighbor of x in the direction toward y 5816 function Nextafter ( 5817 x, y : UNRESOLVED_float; -- floating point input 5818 constant check_error : BOOLEAN := float_check_error; -- check for errors 5819 constant denormalize : BOOLEAN := float_denormalize) 5820 return UNRESOLVED_float is 5821 constant fraction_width : NATURAL := -mine(x'low, x'low); -- length of FP output fraction 5822 constant exponent_width : NATURAL := x'high; -- length of FP output exponent 5823 function "=" ( 5824 l, r : UNRESOLVED_float) -- inputs 5825 return BOOLEAN is 5826 begin -- function "=" 5827 return eq (l => l, 5828 r => r, 5829 check_error => false); 5830 end function "="; 5831 function ">" ( 5832 l, r : UNRESOLVED_float) -- inputs 5833 return BOOLEAN is 5834 begin -- function ">" 5835 return gt (l => l, 5836 r => r, 5837 check_error => false); 5838 end function ">"; 5839 variable fract : UNSIGNED (fraction_width-1 downto 0); 5840 variable expon : UNSIGNED (exponent_width-1 downto 0); 5841 variable sign : STD_ULOGIC; 5842 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 5843 variable validfpx, validfpy : valid_fpstate; -- Valid FP state 5844 begin -- fp_Nextafter 5845 -- If Y > X, add one to the fraction, otherwise subtract. 5846 validfpx := classfp (x, check_error); 5847 validfpy := classfp (y, check_error); 5848 if validfpx = isx or validfpy = isx then 5849 result := (others => 'X'); 5850 return result; 5851 elsif (validfpx = nan or validfpy = nan) then 5852 return nanfp (fraction_width => fraction_width, 5853 exponent_width => exponent_width); 5854 elsif (validfpx = quiet_nan or validfpy = quiet_nan) then 5855 return qnanfp (fraction_width => fraction_width, 5856 exponent_width => exponent_width); 5857 elsif x = y then -- Return X 5858 return x; 5859 else 5860 fract := UNSIGNED (to_slv (x (-1 downto -fraction_width))); -- Fraction 5861 expon := UNSIGNED (x (exponent_width - 1 downto 0)); -- exponent 5862 sign := x(exponent_width); -- sign bit 5863 if (y > x) then 5864 -- Increase the number given 5865 if validfpx = neg_inf then 5866 -- return most negative number 5867 expon := (others => '1'); 5868 expon (0) := '0'; 5869 fract := (others => '1'); 5870 elsif validfpx = pos_zero or validfpx = neg_zero then 5871 -- return smallest denormal number 5872 sign := '0'; 5873 expon := (others => '0'); 5874 fract := (others => '0'); 5875 fract(0) := '1'; 5876 elsif validfpx = pos_normal then 5877 if and_reduce (fract) = '1' then -- fraction is all "1". 5878 if and_reduce (expon (exponent_width-1 downto 1)) = '1' 5879 and expon (0) = '0' then 5880 -- Exponent is one away from infinity. 5881 assert NO_WARNING 5882 report float_pkg'instance_name 5883 & "FP_NEXTAFTER: NextAfter overflow" 5884 severity warning; 5885 return pos_inffp (fraction_width => fraction_width, 5886 exponent_width => exponent_width); 5887 else 5888 expon := expon + 1; 5889 fract := (others => '0'); 5890 end if; 5891 else 5892 fract := fract + 1; 5893 end if; 5894 elsif validfpx = pos_denormal then 5895 if and_reduce (fract) = '1' then -- fraction is all "1". 5896 -- return smallest possible normal number 5897 expon := (others => '0'); 5898 expon(0) := '1'; 5899 fract := (others => '0'); 5900 else 5901 fract := fract + 1; 5902 end if; 5903 elsif validfpx = neg_normal then 5904 if or_reduce (fract) = '0' then -- fraction is all "0". 5905 if or_reduce (expon (exponent_width-1 downto 1)) = '0' and 5906 expon (0) = '1' then -- Smallest exponent 5907 -- return the largest negative denormal number 5908 expon := (others => '0'); 5909 fract := (others => '1'); 5910 else 5911 expon := expon - 1; 5912 fract := (others => '1'); 5913 end if; 5914 else 5915 fract := fract - 1; 5916 end if; 5917 elsif validfpx = neg_denormal then 5918 if or_reduce (fract(fract'high downto 1)) = '0' 5919 and fract (0) = '1' then -- Smallest possible fraction 5920 return zerofp (fraction_width => fraction_width, 5921 exponent_width => exponent_width); 5922 else 5923 fract := fract - 1; 5924 end if; 5925 end if; 5926 else 5927 -- Decrease the number 5928 if validfpx = pos_inf then 5929 -- return most positive number 5930 expon := (others => '1'); 5931 expon (0) := '0'; 5932 fract := (others => '1'); 5933 elsif validfpx = pos_zero 5934 or classfp (x) = neg_zero then 5935 -- return smallest negative denormal number 5936 sign := '1'; 5937 expon := (others => '0'); 5938 fract := (others => '0'); 5939 fract(0) := '1'; 5940 elsif validfpx = neg_normal then 5941 if and_reduce (fract) = '1' then -- fraction is all "1". 5942 if and_reduce (expon (exponent_width-1 downto 1)) = '1' 5943 and expon (0) = '0' then 5944 -- Exponent is one away from infinity. 5945 assert NO_WARNING 5946 report float_pkg'instance_name 5947 & "FP_NEXTAFTER: NextAfter overflow" 5948 severity warning; 5949 return neg_inffp (fraction_width => fraction_width, 5950 exponent_width => exponent_width); 5951 else 5952 expon := expon + 1; -- Fraction overflow 5953 fract := (others => '0'); 5954 end if; 5955 else 5956 fract := fract + 1; 5957 end if; 5958 elsif validfpx = neg_denormal then 5959 if and_reduce (fract) = '1' then -- fraction is all "1". 5960 -- return smallest possible normal number 5961 expon := (others => '0'); 5962 expon(0) := '1'; 5963 fract := (others => '0'); 5964 else 5965 fract := fract + 1; 5966 end if; 5967 elsif validfpx = pos_normal then 5968 if or_reduce (fract) = '0' then -- fraction is all "0". 5969 if or_reduce (expon (exponent_width-1 downto 1)) = '0' and 5970 expon (0) = '1' then -- Smallest exponent 5971 -- return the largest positive denormal number 5972 expon := (others => '0'); 5973 fract := (others => '1'); 5974 else 5975 expon := expon - 1; 5976 fract := (others => '1'); 5977 end if; 5978 else 5979 fract := fract - 1; 5980 end if; 5981 elsif validfpx = pos_denormal then 5982 if or_reduce (fract(fract'high downto 1)) = '0' 5983 and fract (0) = '1' then -- Smallest possible fraction 5984 return zerofp (fraction_width => fraction_width, 5985 exponent_width => exponent_width); 5986 else 5987 fract := fract - 1; 5988 end if; 5989 end if; 5990 end if; 5991 result (-1 downto -fraction_width) := UNRESOLVED_float(fract); 5992 result (exponent_width -1 downto 0) := UNRESOLVED_float(expon); 5993 result (exponent_width) := sign; 5994 return result; 5995 end if; 5996 end function Nextafter; 5997 5998 -- Returns True if X is unordered with Y. 5999 function Unordered ( 6000 x, y : UNRESOLVED_float) -- floating point input 6001 return BOOLEAN is 6002 variable lfptype, rfptype : valid_fpstate; 6003 begin 6004 lfptype := classfp (x); 6005 rfptype := classfp (y); 6006 if (lfptype = nan or lfptype = quiet_nan or 6007 rfptype = nan or rfptype = quiet_nan or 6008 lfptype = isx or rfptype = isx) then 6009 return true; 6010 else 6011 return false; 6012 end if; 6013 end function Unordered; 6014 6015 function Finite ( 6016 x : UNRESOLVED_float) 6017 return BOOLEAN is 6018 variable fp_state : valid_fpstate; -- fp state 6019 begin 6020 fp_state := Classfp (x); 6021 if (fp_state = pos_inf) or (fp_state = neg_inf) then 6022 return true; 6023 else 6024 return false; 6025 end if; 6026 end function Finite; 6027 6028 function Isnan ( 6029 x : UNRESOLVED_float) 6030 return BOOLEAN is 6031 variable fp_state : valid_fpstate; -- fp state 6032 begin 6033 fp_state := Classfp (x); 6034 if (fp_state = nan) or (fp_state = quiet_nan) then 6035 return true; 6036 else 6037 return false; 6038 end if; 6039 end function Isnan; 6040 6041 -- Function to return constants. 6042 function zerofp ( 6043 constant exponent_width : NATURAL := float_exponent_width; -- exponent 6044 constant fraction_width : NATURAL := float_fraction_width) -- fraction 6045 return UNRESOLVED_float is 6046 constant result : UNRESOLVED_float (exponent_width downto -fraction_width) := 6047 (others => '0'); -- zero 6048 begin 6049 return result; 6050 end function zerofp; 6051 6052 function nanfp ( 6053 constant exponent_width : NATURAL := float_exponent_width; -- exponent 6054 constant fraction_width : NATURAL := float_fraction_width) -- fraction 6055 return UNRESOLVED_float is 6056 variable result : UNRESOLVED_float (exponent_width downto -fraction_width) := 6057 (others => '0'); -- zero 6058 begin 6059 result (exponent_width-1 downto 0) := (others => '1'); 6060 -- Exponent all "1" 6061 result (-1) := '1'; -- MSB of Fraction "1" 6062 -- Note: From W. Khan "IEEE Standard 754 for Binary Floating Point" 6063 -- The difference between a signaling NAN and a quiet NAN is that 6064 -- the MSB of the Fraction is a "1" in a Signaling NAN, and is a 6065 -- "0" in a quiet NAN. 6066 return result; 6067 end function nanfp; 6068 6069 function qnanfp ( 6070 constant exponent_width : NATURAL := float_exponent_width; -- exponent 6071 constant fraction_width : NATURAL := float_fraction_width) -- fraction 6072 return UNRESOLVED_float is 6073 variable result : UNRESOLVED_float (exponent_width downto -fraction_width) := 6074 (others => '0'); -- zero 6075 begin 6076 result (exponent_width-1 downto 0) := (others => '1'); 6077 -- Exponent all "1" 6078 result (-fraction_width) := '1'; -- LSB of Fraction "1" 6079 -- (Could have been any bit) 6080 return result; 6081 end function qnanfp; 6082 6083 function pos_inffp ( 6084 constant exponent_width : NATURAL := float_exponent_width; -- exponent 6085 constant fraction_width : NATURAL := float_fraction_width) -- fraction 6086 return UNRESOLVED_float is 6087 variable result : UNRESOLVED_float (exponent_width downto -fraction_width) := 6088 (others => '0'); -- zero 6089 begin 6090 result (exponent_width-1 downto 0) := (others => '1'); -- Exponent all "1" 6091 return result; 6092 end function pos_inffp; 6093 6094 function neg_inffp ( 6095 constant exponent_width : NATURAL := float_exponent_width; -- exponent 6096 constant fraction_width : NATURAL := float_fraction_width) -- fraction 6097 return UNRESOLVED_float is 6098 variable result : UNRESOLVED_float (exponent_width downto -fraction_width) := 6099 (others => '0'); -- zero 6100 begin 6101 result (exponent_width downto 0) := (others => '1'); -- top bits all "1" 6102 return result; 6103 end function neg_inffp; 6104 6105 function neg_zerofp ( 6106 constant exponent_width : NATURAL := float_exponent_width; -- exponent 6107 constant fraction_width : NATURAL := float_fraction_width) -- fraction 6108 return UNRESOLVED_float is 6109 variable result : UNRESOLVED_float (exponent_width downto -fraction_width) := 6110 (others => '0'); -- zero 6111 begin 6112 result (exponent_width) := '1'; 6113 return result; 6114 end function neg_zerofp; 6115 6116 -- size_res versions 6117 function zerofp ( 6118 size_res : UNRESOLVED_float) -- variable is only use for sizing 6119 return UNRESOLVED_float is 6120 begin 6121 return zerofp ( 6122 exponent_width => size_res'high, 6123 fraction_width => -size_res'low); 6124 end function zerofp; 6125 6126 function nanfp ( 6127 size_res : UNRESOLVED_float) -- variable is only use for sizing 6128 return UNRESOLVED_float is 6129 begin 6130 return nanfp ( 6131 exponent_width => size_res'high, 6132 fraction_width => -size_res'low); 6133 end function nanfp; 6134 6135 function qnanfp ( 6136 size_res : UNRESOLVED_float) -- variable is only use for sizing 6137 return UNRESOLVED_float is 6138 begin 6139 return qnanfp ( 6140 exponent_width => size_res'high, 6141 fraction_width => -size_res'low); 6142 end function qnanfp; 6143 6144 function pos_inffp ( 6145 size_res : UNRESOLVED_float) -- variable is only use for sizing 6146 return UNRESOLVED_float is 6147 begin 6148 return pos_inffp ( 6149 exponent_width => size_res'high, 6150 fraction_width => -size_res'low); 6151 end function pos_inffp; 6152 6153 function neg_inffp ( 6154 size_res : UNRESOLVED_float) -- variable is only use for sizing 6155 return UNRESOLVED_float is 6156 begin 6157 return neg_inffp ( 6158 exponent_width => size_res'high, 6159 fraction_width => -size_res'low); 6160 end function neg_inffp; 6161 6162 function neg_zerofp ( 6163 size_res : UNRESOLVED_float) -- variable is only use for sizing 6164 return UNRESOLVED_float is 6165 begin 6166 return neg_zerofp ( 6167 exponent_width => size_res'high, 6168 fraction_width => -size_res'low); 6169 end function neg_zerofp; 6170 6171-- rtl_synthesis off 6172-- pragma synthesis_off 6173 6174 --%%% these functions are copied from std_logic_1164 (VHDL-200X edition) 6175 -- Textio functions 6176 -- purpose: writes float into a line (NOTE changed basetype) 6177 type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', error); 6178 type char_indexed_by_MVL9 is array (STD_ULOGIC) of CHARACTER; 6179 type MVL9_indexed_by_char is array (CHARACTER) of STD_ULOGIC; 6180 type MVL9plus_indexed_by_char is array (CHARACTER) of MVL9plus; 6181 6182 constant NBSP : CHARACTER := CHARACTER'val(160); -- space character 6183 constant MVL9_to_char : char_indexed_by_MVL9 := "UX01ZWLH-"; 6184 constant char_to_MVL9 : MVL9_indexed_by_char := 6185 ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', 6186 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U'); 6187 constant char_to_MVL9plus : MVL9plus_indexed_by_char := 6188 ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', 6189 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => error); 6190 constant NUS : STRING(2 to 1) := (others => ' '); 6191 6192 -- purpose: Skips white space 6193 procedure skip_whitespace ( 6194 L : inout LINE) is 6195 variable readOk : BOOLEAN; 6196 variable c : CHARACTER; 6197 begin 6198 while L /= null and L.all'length /= 0 loop 6199 if (L.all(1) = ' ' or L.all(1) = NBSP or L.all(1) = HT) then 6200 read (l, c, readOk); 6201 else 6202 exit; 6203 end if; 6204 end loop; 6205 end procedure skip_whitespace; 6206 6207-- %%% Replicated textio functions 6208 function to_ostring (value : STD_LOGIC_VECTOR) return STRING is 6209 constant ne : INTEGER := (value'length+2)/3; 6210 variable pad : STD_LOGIC_VECTOR(0 to (ne*3 - value'length) - 1); 6211 variable ivalue : STD_LOGIC_VECTOR(0 to ne*3 - 1); 6212 variable result : STRING(1 to ne); 6213 variable tri : STD_LOGIC_VECTOR(0 to 2); 6214 begin 6215 if value'length < 1 then 6216 return NUS; 6217 else 6218 if value (value'left) = 'Z' then 6219 pad := (others => 'Z'); 6220 else 6221 pad := (others => '0'); 6222 end if; 6223 ivalue := pad & value; 6224 for i in 0 to ne-1 loop 6225 tri := To_X01Z(ivalue(3*i to 3*i+2)); 6226 case tri is 6227 when o"0" => result(i+1) := '0'; 6228 when o"1" => result(i+1) := '1'; 6229 when o"2" => result(i+1) := '2'; 6230 when o"3" => result(i+1) := '3'; 6231 when o"4" => result(i+1) := '4'; 6232 when o"5" => result(i+1) := '5'; 6233 when o"6" => result(i+1) := '6'; 6234 when o"7" => result(i+1) := '7'; 6235 when "ZZZ" => result(i+1) := 'Z'; 6236 when others => result(i+1) := 'X'; 6237 end case; 6238 end loop; 6239 return result; 6240 end if; 6241 end function to_ostring; 6242 ------------------------------------------------------------------- 6243 function to_hstring (value : STD_LOGIC_VECTOR) return STRING is 6244 constant ne : INTEGER := (value'length+3)/4; 6245 variable pad : STD_LOGIC_VECTOR(0 to (ne*4 - value'length) - 1); 6246 variable ivalue : STD_LOGIC_VECTOR(0 to ne*4 - 1); 6247 variable result : STRING(1 to ne); 6248 variable quad : STD_LOGIC_VECTOR(0 to 3); 6249 begin 6250 if value'length < 1 then 6251 return NUS; 6252 else 6253 if value (value'left) = 'Z' then 6254 pad := (others => 'Z'); 6255 else 6256 pad := (others => '0'); 6257 end if; 6258 ivalue := pad & value; 6259 for i in 0 to ne-1 loop 6260 quad := To_X01Z(ivalue(4*i to 4*i+3)); 6261 case quad is 6262 when x"0" => result(i+1) := '0'; 6263 when x"1" => result(i+1) := '1'; 6264 when x"2" => result(i+1) := '2'; 6265 when x"3" => result(i+1) := '3'; 6266 when x"4" => result(i+1) := '4'; 6267 when x"5" => result(i+1) := '5'; 6268 when x"6" => result(i+1) := '6'; 6269 when x"7" => result(i+1) := '7'; 6270 when x"8" => result(i+1) := '8'; 6271 when x"9" => result(i+1) := '9'; 6272 when x"A" => result(i+1) := 'A'; 6273 when x"B" => result(i+1) := 'B'; 6274 when x"C" => result(i+1) := 'C'; 6275 when x"D" => result(i+1) := 'D'; 6276 when x"E" => result(i+1) := 'E'; 6277 when x"F" => result(i+1) := 'F'; 6278 when "ZZZZ" => result(i+1) := 'Z'; 6279 when others => result(i+1) := 'X'; 6280 end case; 6281 end loop; 6282 return result; 6283 end if; 6284 end function to_hstring; 6285 procedure Char2TriBits (C : CHARACTER; 6286 RESULT : out STD_LOGIC_VECTOR(2 downto 0); 6287 GOOD : out BOOLEAN; 6288 ISSUE_ERROR : in BOOLEAN) is 6289 begin 6290 case c is 6291 when '0' => result := o"0"; good := true; 6292 when '1' => result := o"1"; good := true; 6293 when '2' => result := o"2"; good := true; 6294 when '3' => result := o"3"; good := true; 6295 when '4' => result := o"4"; good := true; 6296 when '5' => result := o"5"; good := true; 6297 when '6' => result := o"6"; good := true; 6298 when '7' => result := o"7"; good := true; 6299 when 'Z' => result := "ZZZ"; good := true; 6300 when 'X' => result := "XXX"; good := true; 6301 when others => 6302 assert not ISSUE_ERROR 6303 report float_pkg'instance_name 6304 & "OREAD Error: Read a '" & c & 6305 "', expected an Octal character (0-7)." 6306 severity error; 6307 result := "UUU"; 6308 good := false; 6309 end case; 6310 end procedure Char2TriBits; 6311 6312 procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; 6313 GOOD : out BOOLEAN) is 6314 variable ok : BOOLEAN; 6315 variable c : CHARACTER; 6316 constant ne : INTEGER := (VALUE'length+2)/3; 6317 constant pad : INTEGER := ne*3 - VALUE'length; 6318 variable sv : STD_LOGIC_VECTOR(0 to ne*3 - 1); 6319 variable i : INTEGER; 6320 variable lastu : BOOLEAN := false; -- last character was an "_" 6321 begin 6322 VALUE := (VALUE'range => 'U'); -- initialize to a "U" 6323 Skip_whitespace (L); 6324 if VALUE'length > 0 then 6325 read (l, c, ok); 6326 i := 0; 6327 while i < ne loop 6328 -- Bail out if there was a bad read 6329 if not ok then 6330 good := false; 6331 return; 6332 elsif c = '_' then 6333 if i = 0 then 6334 good := false; -- Begins with an "_" 6335 return; 6336 elsif lastu then 6337 good := false; -- "__" detected 6338 return; 6339 else 6340 lastu := true; 6341 end if; 6342 else 6343 Char2TriBits(c, sv(3*i to 3*i+2), ok, false); 6344 if not ok then 6345 good := false; 6346 return; 6347 end if; 6348 i := i + 1; 6349 lastu := false; 6350 end if; 6351 if i < ne then 6352 read(L, c, ok); 6353 end if; 6354 end loop; 6355 if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" 6356 good := false; -- vector was truncated. 6357 else 6358 good := true; 6359 VALUE := sv (pad to sv'high); 6360 end if; 6361 else 6362 good := true; -- read into a null array 6363 end if; 6364 end procedure OREAD; 6365 6366 -- Hex Read and Write procedures for STD_ULOGIC_VECTOR. 6367 -- Modified from the original to be more forgiving. 6368 6369 procedure Char2QuadBits (C : CHARACTER; 6370 RESULT : out STD_LOGIC_VECTOR(3 downto 0); 6371 GOOD : out BOOLEAN; 6372 ISSUE_ERROR : in BOOLEAN) is 6373 begin 6374 case c is 6375 when '0' => result := x"0"; good := true; 6376 when '1' => result := x"1"; good := true; 6377 when '2' => result := x"2"; good := true; 6378 when '3' => result := x"3"; good := true; 6379 when '4' => result := x"4"; good := true; 6380 when '5' => result := x"5"; good := true; 6381 when '6' => result := x"6"; good := true; 6382 when '7' => result := x"7"; good := true; 6383 when '8' => result := x"8"; good := true; 6384 when '9' => result := x"9"; good := true; 6385 when 'A' | 'a' => result := x"A"; good := true; 6386 when 'B' | 'b' => result := x"B"; good := true; 6387 when 'C' | 'c' => result := x"C"; good := true; 6388 when 'D' | 'd' => result := x"D"; good := true; 6389 when 'E' | 'e' => result := x"E"; good := true; 6390 when 'F' | 'f' => result := x"F"; good := true; 6391 when 'Z' => result := "ZZZZ"; good := true; 6392 when 'X' => result := "XXXX"; good := true; 6393 when others => 6394 assert not ISSUE_ERROR 6395 report float_pkg'instance_name 6396 & "HREAD Error: Read a '" & c & 6397 "', expected a Hex character (0-F)." 6398 severity error; 6399 result := "UUUU"; 6400 good := false; 6401 end case; 6402 end procedure Char2QuadBits; 6403 6404 procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; 6405 GOOD : out BOOLEAN) is 6406 variable ok : BOOLEAN; 6407 variable c : CHARACTER; 6408 constant ne : INTEGER := (VALUE'length+3)/4; 6409 constant pad : INTEGER := ne*4 - VALUE'length; 6410 variable sv : STD_LOGIC_VECTOR(0 to ne*4 - 1); 6411 variable i : INTEGER; 6412 variable lastu : BOOLEAN := false; -- last character was an "_" 6413 begin 6414 VALUE := (VALUE'range => 'U'); -- initialize to a "U" 6415 Skip_whitespace (L); 6416 if VALUE'length > 0 then 6417 read (l, c, ok); 6418 i := 0; 6419 while i < ne loop 6420 -- Bail out if there was a bad read 6421 if not ok then 6422 good := false; 6423 return; 6424 elsif c = '_' then 6425 if i = 0 then 6426 good := false; -- Begins with an "_" 6427 return; 6428 elsif lastu then 6429 good := false; -- "__" detected 6430 return; 6431 else 6432 lastu := true; 6433 end if; 6434 else 6435 Char2QuadBits(c, sv(4*i to 4*i+3), ok, false); 6436 if not ok then 6437 good := false; 6438 return; 6439 end if; 6440 i := i + 1; 6441 lastu := false; 6442 end if; 6443 if i < ne then 6444 read(L, c, ok); 6445 end if; 6446 end loop; 6447 if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" 6448 good := false; -- vector was truncated. 6449 else 6450 good := true; 6451 VALUE := sv (pad to sv'high); 6452 end if; 6453 else 6454 good := true; -- Null input string, skips whitespace 6455 end if; 6456 end procedure HREAD; 6457 6458-- %%% END replicated textio functions 6459 6460 -- purpose: Checks the punctuation in a line 6461 procedure check_punctuation ( 6462 arg : in STRING; 6463 colon : out BOOLEAN; -- There was a colon in the line 6464 dot : out BOOLEAN; -- There was a dot in the line 6465 good : out BOOLEAN; -- True if enough characters found 6466 chars : in INTEGER) is 6467 -- Examples. Legal inputs are "0000000", "0000.000", "0:000:000" 6468 alias xarg : STRING (1 to arg'length) is arg; -- make it downto range 6469 variable icolon, idot : BOOLEAN; -- internal 6470 variable j : INTEGER := 0; -- charters read 6471 begin 6472 good := false; 6473 icolon := false; 6474 idot := false; 6475 for i in 1 to arg'length loop 6476 if xarg(i) = ' ' or xarg(i) = NBSP or xarg(i) = HT or j = chars then 6477 exit; 6478 elsif xarg(i) = ':' then 6479 icolon := true; 6480 elsif xarg(i) = '.' then 6481 idot := true; 6482 elsif xarg (i) /= '_' then 6483 j := j + 1; 6484 end if; 6485 end loop; 6486 if j = chars then 6487 good := true; -- There are enough charactes to read 6488 end if; 6489 colon := icolon; 6490 if idot and icolon then 6491 dot := false; 6492 else 6493 dot := idot; 6494 end if; 6495 end procedure check_punctuation; 6496 6497 -- purpose: Searches a line for a ":" and replaces it with a ".". 6498 procedure fix_colon ( 6499 arg : inout STRING; 6500 chars : in integer) is 6501 alias xarg : STRING (1 to arg'length) is arg; -- make it downto range 6502 variable j : INTEGER := 0; -- charters read 6503 begin 6504 for i in 1 to arg'length loop 6505 if xarg(i) = ' ' or xarg(i) = NBSP or xarg(i) = HT or j > chars then 6506 exit; 6507 elsif xarg(i) = ':' then 6508 xarg (i) := '.'; 6509 elsif xarg (i) /= '_' then 6510 j := j + 1; 6511 end if; 6512 end loop; 6513 end procedure fix_colon; 6514 6515 procedure WRITE ( 6516 L : inout LINE; -- input line 6517 VALUE : in UNRESOLVED_float; -- floating point input 6518 JUSTIFIED : in SIDE := right; 6519 FIELD : in WIDTH := 0) is 6520 variable s : STRING(1 to value'high - value'low +3); 6521 variable sindx : INTEGER; 6522 begin -- function write 6523 s(1) := MVL9_to_char(STD_ULOGIC(VALUE(VALUE'high))); 6524 s(2) := ':'; 6525 sindx := 3; 6526 for i in VALUE'high-1 downto 0 loop 6527 s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i))); 6528 sindx := sindx + 1; 6529 end loop; 6530 s(sindx) := ':'; 6531 sindx := sindx + 1; 6532 for i in -1 downto VALUE'low loop 6533 s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i))); 6534 sindx := sindx + 1; 6535 end loop; 6536 WRITE (L, s, JUSTIFIED, FIELD); 6537 end procedure WRITE; 6538 6539 procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float) is 6540 -- Possible data: 0:0000:0000000 6541 -- 000000000000 6542 variable c : CHARACTER; 6543 variable mv : UNRESOLVED_float (VALUE'range); 6544 variable readOk : BOOLEAN; 6545 variable lastu : BOOLEAN := false; -- last character was an "_" 6546 variable i : INTEGER; -- index variable 6547 begin -- READ 6548 VALUE := (VALUE'range => 'U'); -- initialize to a "U" 6549 Skip_whitespace (L); 6550 READ (l, c, readOk); 6551 if VALUE'length > 0 then 6552 i := value'high; 6553 readloop : loop 6554 if readOk = false then -- Bail out if there was a bad read 6555 report float_pkg'instance_name 6556 & "READ(float): " 6557 & "Error end of file encountered." 6558 severity error; 6559 return; 6560 elsif c = ' ' or c = CR or c = HT then -- reading done. 6561 if (i /= value'low) then 6562 report float_pkg'instance_name 6563 & "READ(float): " 6564 & "Warning: Value truncated." 6565 severity warning; 6566 return; 6567 end if; 6568 elsif c = '_' then 6569 if i = value'high then -- Begins with an "_" 6570 report float_pkg'instance_name 6571 & "READ(float): " 6572 & "String begins with an ""_""" severity error; 6573 return; 6574 elsif lastu then -- "__" detected 6575 report float_pkg'instance_name 6576 & "READ(float): " 6577 & "Two underscores detected in input string ""__""" 6578 severity error; 6579 return; 6580 else 6581 lastu := true; 6582 end if; 6583 elsif c = ':' or c = '.' then -- separator, ignore 6584 if not (i = -1 or i = value'high-1) then 6585 report float_pkg'instance_name 6586 & "READ(float): " 6587 & "Warning: Separator point does not match number format: '" 6588 & c & "' encountered at location " & INTEGER'image(i) & "." 6589 severity warning; 6590 end if; 6591 lastu := false; 6592 elsif (char_to_MVL9plus(c) = error) then 6593 report float_pkg'instance_name 6594 & "READ(float): " 6595 & "Error: Character '" & c & "' read, expected STD_ULOGIC literal." 6596 severity error; 6597 return; 6598 else 6599 mv (i) := char_to_MVL9(c); 6600 i := i - 1; 6601 if i < value'low then 6602 VALUE := mv; 6603 return; 6604 end if; 6605 lastu := false; 6606 end if; 6607 READ (l, c, readOk); 6608 end loop readloop; 6609 end if; 6610 end procedure READ; 6611 6612 procedure READ (L : inout LINE; VALUE : out UNRESOLVED_float; GOOD : out BOOLEAN) is 6613 -- Possible data: 0:0000:0000000 6614 -- 000000000000 6615 variable c : CHARACTER; 6616 variable mv : UNRESOLVED_float (VALUE'range); 6617 variable lastu : BOOLEAN := false; -- last character was an "_" 6618 variable i : INTEGER; -- index variable 6619 variable readOk : BOOLEAN; 6620 begin -- READ 6621 VALUE := (VALUE'range => 'U'); -- initialize to a "U" 6622 Skip_whitespace (L); 6623 READ (l, c, readOk); 6624 if VALUE'length > 0 then 6625 i := value'high; 6626 good := false; 6627 readloop : loop 6628 if readOk = false then -- Bail out if there was a bad read 6629 return; 6630 elsif c = ' ' or c = CR or c = HT then -- reading done 6631 return; 6632 elsif c = '_' then 6633 if i = 0 then -- Begins with an "_" 6634 return; 6635 elsif lastu then -- "__" detected 6636 return; 6637 else 6638 lastu := true; 6639 end if; 6640 elsif c = ':' or c = '.' then -- separator, ignore 6641 -- good := (i = -1 or i = value'high-1); 6642 lastu := false; 6643 elsif (char_to_MVL9plus(c) = error) then 6644 return; 6645 else 6646 mv (i) := char_to_MVL9(c); 6647 i := i - 1; 6648 if i < value'low then 6649 good := true; 6650 VALUE := mv; 6651 return; 6652 end if; 6653 lastu := false; 6654 end if; 6655 READ (l, c, readOk); 6656 end loop readloop; 6657 else 6658 good := true; -- read into a null array 6659 end if; 6660 end procedure READ; 6661 6662 procedure OWRITE ( 6663 L : inout LINE; -- access type (pointer) 6664 VALUE : in UNRESOLVED_float; -- value to write 6665 JUSTIFIED : in SIDE := right; -- which side to justify text 6666 FIELD : in WIDTH := 0) is -- width of field 6667 begin 6668 WRITE (L => L, 6669 VALUE => to_ostring(VALUE), 6670 JUSTIFIED => JUSTIFIED, 6671 FIELD => FIELD); 6672 end procedure OWRITE; 6673 6674 procedure OREAD (L : inout LINE; VALUE : out UNRESOLVED_float) is 6675 constant ne : INTEGER := ((value'length+2)/3) * 3; -- pad 6676 variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv 6677 variable slvu : ufixed (VALUE'range); -- Unsigned fixed point 6678 variable c : CHARACTER; 6679 variable ok : BOOLEAN; 6680 variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits 6681 variable colon, dot : BOOLEAN; 6682 begin 6683 VALUE := (VALUE'range => 'U'); -- initialize to a "U" 6684 Skip_whitespace (L); 6685 if VALUE'length > 0 then 6686 check_punctuation (arg => L.all, 6687 colon => colon, 6688 dot => dot, 6689 good => ok, 6690 chars => ne/3); 6691 if not ok then 6692 report float_pkg'instance_name & "OREAD: " 6693 & "short string encounted: " & L.all 6694 & " needs to have " & integer'image (ne/3) 6695 & " valid octal characters." 6696 severity error; 6697 return; 6698 elsif dot then 6699 OREAD (L, slvu, ok); -- read it like a UFIXED number 6700 if not ok then 6701 report float_pkg'instance_name & "OREAD: " 6702 & "error encounted reading STRING " & L.all 6703 severity error; 6704 return; 6705 else 6706 VALUE := UNRESOLVED_float (slvu); 6707 end if; 6708 elsif colon then 6709 OREAD (L, nybble, ok); -- read the sign bit 6710 if not ok then 6711 report float_pkg'instance_name & "OREAD: " 6712 & "End of string encountered" 6713 severity error; 6714 return; 6715 elsif nybble (2 downto 1) /= "00" then 6716 report float_pkg'instance_name & "OREAD: " 6717 & "Illegal sign bit STRING encounted " 6718 severity error; 6719 return; 6720 end if; 6721 read (l, c, ok); -- read the colon 6722 fix_colon (L.all, ne/3); -- replaces the colon with a ".". 6723 OREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number 6724 if not ok then 6725 report float_pkg'instance_name & "OREAD: " 6726 & "error encounted reading STRING " & L.all 6727 severity error; 6728 return; 6729 else 6730 slvu (slvu'high) := nybble (0); 6731 VALUE := UNRESOLVED_float (slvu); 6732 end if; 6733 else 6734 OREAD (L, slv, ok); 6735 if not ok then 6736 report float_pkg'instance_name & "OREAD: " 6737 & "Error encounted during read" 6738 severity error; 6739 return; 6740 end if; 6741 if (or_reduce (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then 6742 report float_pkg'instance_name & "OREAD: " 6743 & "Vector truncated." 6744 severity error; 6745 return; 6746 end if; 6747 VALUE := to_float (slv(VALUE'high-VALUE'low downto 0), 6748 VALUE'high, -VALUE'low); 6749 end if; 6750 end if; 6751 end procedure OREAD; 6752 6753 procedure OREAD(L : inout LINE; VALUE : out UNRESOLVED_float; GOOD : out BOOLEAN) is 6754 constant ne : INTEGER := ((value'length+2)/3) * 3; -- pad 6755 variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv 6756 variable slvu : ufixed (VALUE'range); -- Unsigned fixed point 6757 variable c : CHARACTER; 6758 variable ok : BOOLEAN; 6759 variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits 6760 variable colon, dot : BOOLEAN; 6761 begin 6762 VALUE := (VALUE'range => 'U'); -- initialize to a "U" 6763 GOOD := false; 6764 Skip_whitespace (L); 6765 if VALUE'length > 0 then 6766 check_punctuation (arg => L.all, 6767 colon => colon, 6768 dot => dot, 6769 good => ok, 6770 chars => ne/3); 6771 if not ok then 6772 return; 6773 elsif dot then 6774 OREAD (L, slvu, ok); -- read it like a UFIXED number 6775 if not ok then 6776 return; 6777 else 6778 VALUE := UNRESOLVED_float (slvu); 6779 end if; 6780 elsif colon then 6781 OREAD (L, nybble, ok); -- read the sign bit 6782 if not ok then 6783 return; 6784 elsif nybble (2 downto 1) /= "00" then 6785 return; 6786 end if; 6787 read (l, c, ok); -- read the colon 6788 fix_colon (L.all, ne/3); -- replaces the colon with a ".". 6789 OREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number 6790 if not ok then 6791 return; 6792 else 6793 slvu (slvu'high) := nybble (0); 6794 VALUE := UNRESOLVED_float (slvu); 6795 end if; 6796 else 6797 OREAD (L, slv, ok); 6798 if not ok then 6799 return; 6800 end if; 6801 if (or_reduce (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then 6802 return; 6803 end if; 6804 VALUE := to_float (slv(VALUE'high-VALUE'low downto 0), 6805 VALUE'high, -VALUE'low); 6806 end if; 6807 GOOD := true; 6808 end if; 6809 end procedure OREAD; 6810 6811 procedure HWRITE ( 6812 L : inout LINE; -- access type (pointer) 6813 VALUE : in UNRESOLVED_float; -- value to write 6814 JUSTIFIED : in SIDE := right; -- which side to justify text 6815 FIELD : in WIDTH := 0) is -- width of field 6816 begin 6817 WRITE (L => L, 6818 VALUE => to_hstring(VALUE), 6819 JUSTIFIED => JUSTIFIED, 6820 FIELD => FIELD); 6821 end procedure HWRITE; 6822 6823 procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float) is 6824 constant ne : INTEGER := ((value'length+3)/4) * 4; -- pad 6825 variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv 6826 variable slvu : ufixed (VALUE'range); -- Unsigned fixed point 6827 variable c : CHARACTER; 6828 variable ok : BOOLEAN; 6829 variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits 6830 variable colon, dot : BOOLEAN; 6831 begin 6832 VALUE := (VALUE'range => 'U'); -- initialize to a "U" 6833 Skip_whitespace (L); 6834 if VALUE'length > 0 then 6835 check_punctuation (arg => L.all, 6836 colon => colon, 6837 dot => dot, 6838 good => ok, 6839 chars => ne/4); 6840 if not ok then 6841 report float_pkg'instance_name & "HREAD: " 6842 & "short string encounted: " & L.all 6843 & " needs to have " & integer'image (ne/4) 6844 & " valid hex characters." 6845 severity error; 6846 return; 6847 elsif dot then 6848 HREAD (L, slvu, ok); -- read it like a UFIXED number 6849 if not ok then 6850 report float_pkg'instance_name & "HREAD: " 6851 & "error encounted reading STRING " & L.all 6852 severity error; 6853 return; 6854 else 6855 VALUE := UNRESOLVED_float (slvu); 6856 end if; 6857 elsif colon then 6858 HREAD (L, nybble, ok); -- read the sign bit 6859 if not ok then 6860 report float_pkg'instance_name & "HREAD: " 6861 & "End of string encountered" 6862 severity error; 6863 return; 6864 elsif nybble (3 downto 1) /= "000" then 6865 report float_pkg'instance_name & "HREAD: " 6866 & "Illegal sign bit STRING encounted " 6867 severity error; 6868 return; 6869 end if; 6870 read (l, c, ok); -- read the colon 6871 fix_colon (L.all, ne/4); -- replaces the colon with a ".". 6872 HREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number 6873 if not ok then 6874 report float_pkg'instance_name & "HREAD: " 6875 & "error encounted reading STRING " & L.all 6876 severity error; 6877 return; 6878 else 6879 slvu (slvu'high) := nybble (0); 6880 VALUE := UNRESOLVED_float (slvu); 6881 end if; 6882 else 6883 HREAD (L, slv, ok); 6884 if not ok then 6885 report float_pkg'instance_name & "HREAD: " 6886 & "Error encounted during read" 6887 severity error; 6888 return; 6889 end if; 6890 if (or_reduce (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then 6891 report float_pkg'instance_name & "HREAD: " 6892 & "Vector truncated." 6893 severity error; 6894 return; 6895 end if; 6896 VALUE := to_float (slv(VALUE'high-VALUE'low downto 0), 6897 VALUE'high, -VALUE'low); 6898 end if; 6899 end if; 6900 end procedure HREAD; 6901 6902 procedure HREAD (L : inout LINE; VALUE : out UNRESOLVED_float; GOOD : out BOOLEAN) is 6903 constant ne : INTEGER := ((value'length+3)/4) * 4; -- pad 6904 variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv 6905 variable slvu : ufixed (VALUE'range); -- Unsigned fixed point 6906 variable c : CHARACTER; 6907 variable ok : BOOLEAN; 6908 variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits 6909 variable colon, dot : BOOLEAN; 6910 begin 6911 VALUE := (VALUE'range => 'U'); -- initialize to a "U" 6912 GOOD := false; 6913 Skip_whitespace (L); 6914 if VALUE'length > 0 then 6915 check_punctuation (arg => L.all, 6916 colon => colon, 6917 dot => dot, 6918 good => ok, 6919 chars => ne/4); 6920 if not ok then 6921 return; 6922 elsif dot then 6923 HREAD (L, slvu, ok); -- read it like a UFIXED number 6924 if not ok then 6925 return; 6926 else 6927 VALUE := UNRESOLVED_float (slvu); 6928 end if; 6929 elsif colon then 6930 HREAD (L, nybble, ok); -- read the sign bit 6931 if not ok then 6932 return; 6933 elsif nybble (3 downto 1) /= "000" then 6934 return; 6935 end if; 6936 read (l, c, ok); -- read the colon 6937 fix_colon (L.all, ne/4); -- replaces the colon with a ".". 6938 HREAD (L, slvu (slvu'high-1 downto slvu'low), ok); -- read it like a UFIXED number 6939 if not ok then 6940 return; 6941 else 6942 slvu (slvu'high) := nybble (0); 6943 VALUE := UNRESOLVED_float (slvu); 6944 end if; 6945 else 6946 HREAD (L, slv, ok); 6947 if not ok then 6948 return; 6949 end if; 6950 if (or_reduce (slv(ne-1 downto VALUE'high-VALUE'low+1)) = '1') then 6951 return; 6952 end if; 6953 VALUE := to_float (slv(VALUE'high-VALUE'low downto 0), 6954 VALUE'high, -VALUE'low); 6955 end if; 6956 GOOD := true; 6957 end if; 6958 end procedure HREAD; 6959 6960 function to_string (value : UNRESOLVED_float) return STRING is 6961 variable s : STRING(1 to value'high - value'low +3); 6962 variable sindx : INTEGER; 6963 begin -- function write 6964 s(1) := MVL9_to_char(STD_ULOGIC(VALUE(VALUE'high))); 6965 s(2) := ':'; 6966 sindx := 3; 6967 for i in VALUE'high-1 downto 0 loop 6968 s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i))); 6969 sindx := sindx + 1; 6970 end loop; 6971 s(sindx) := ':'; 6972 sindx := sindx + 1; 6973 for i in -1 downto VALUE'low loop 6974 s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i))); 6975 sindx := sindx + 1; 6976 end loop; 6977 return s; 6978 end function to_string; 6979 6980 function to_hstring (value : UNRESOLVED_float) return STRING is 6981 variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); 6982 begin 6983 floop : for i in slv'range loop 6984 slv(i) := to_X01Z (value(i + value'low)); 6985 end loop floop; 6986 return to_hstring (slv); 6987 end function to_hstring; 6988 6989 function to_ostring (value : UNRESOLVED_float) return STRING is 6990 variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); 6991 begin 6992 floop : for i in slv'range loop 6993 slv(i) := to_X01Z (value(i + value'low)); 6994 end loop floop; 6995 return to_ostring (slv); 6996 end function to_ostring; 6997 6998 function from_string ( 6999 bstring : STRING; -- binary string 7000 constant exponent_width : NATURAL := float_exponent_width; 7001 constant fraction_width : NATURAL := float_fraction_width) 7002 return UNRESOLVED_float is 7003 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 7004 variable L : LINE; 7005 variable good : BOOLEAN; 7006 begin 7007 L := new STRING'(bstring); 7008 READ (L, result, good); 7009 deallocate (L); 7010 assert (good) 7011 report float_pkg'instance_name 7012 & "from_string: Bad string " & bstring 7013 severity error; 7014 return result; 7015 end function from_string; 7016 7017 function from_ostring ( 7018 ostring : STRING; -- Octal string 7019 constant exponent_width : NATURAL := float_exponent_width; 7020 constant fraction_width : NATURAL := float_fraction_width) 7021 return UNRESOLVED_float is 7022 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 7023 variable L : LINE; 7024 variable good : BOOLEAN; 7025 begin 7026 L := new STRING'(ostring); 7027 OREAD (L, result, good); 7028 deallocate (L); 7029 assert (good) 7030 report float_pkg'instance_name 7031 & "from_ostring: Bad string " & ostring 7032 severity error; 7033 return result; 7034 end function from_ostring; 7035 7036 function from_hstring ( 7037 hstring : STRING; -- hex string 7038 constant exponent_width : NATURAL := float_exponent_width; 7039 constant fraction_width : NATURAL := float_fraction_width) 7040 return UNRESOLVED_float is 7041 variable result : UNRESOLVED_float (exponent_width downto -fraction_width); 7042 variable L : LINE; 7043 variable good : BOOLEAN; 7044 begin 7045 L := new STRING'(hstring); 7046 HREAD (L, result, good); 7047 deallocate (L); 7048 assert (good) 7049 report float_pkg'instance_name 7050 & "from_hstring: Bad string " & hstring 7051 severity error; 7052 return result; 7053 end function from_hstring; 7054 7055 function from_string ( 7056 bstring : STRING; -- binary string 7057 size_res : UNRESOLVED_float) -- used for sizing only 7058 return UNRESOLVED_float is 7059 begin 7060 return from_string (bstring => bstring, 7061 exponent_width => size_res'high, 7062 fraction_width => -size_res'low); 7063 end function from_string; 7064 7065 function from_ostring ( 7066 ostring : STRING; -- Octal string 7067 size_res : UNRESOLVED_float) -- used for sizing only 7068 return UNRESOLVED_float is 7069 begin 7070 return from_ostring (ostring => ostring, 7071 exponent_width => size_res'high, 7072 fraction_width => -size_res'low); 7073 end function from_ostring; 7074 7075 function from_hstring ( 7076 hstring : STRING; -- hex string 7077 size_res : UNRESOLVED_float) -- used for sizing only 7078 return UNRESOLVED_float is 7079 begin 7080 return from_hstring (hstring => hstring, 7081 exponent_width => size_res'high, 7082 fraction_width => -size_res'low); 7083 end function from_hstring; 7084-- rtl_synthesis on 7085-- pragma synthesis_on 7086 function to_float ( 7087 arg : STD_LOGIC_VECTOR; 7088 constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent 7089 constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction 7090 return UNRESOLVED_float is 7091 begin 7092 return to_float ( 7093 arg => to_stdulogicvector (arg), 7094 exponent_width => exponent_width, 7095 fraction_width => fraction_width); 7096 end function to_float; 7097 7098 function to_float ( 7099 arg : STD_LOGIC_VECTOR; 7100 size_res : UNRESOLVED_float) 7101 return UNRESOLVED_float is 7102 begin 7103 return to_float ( 7104 arg => to_stdulogicvector (arg), 7105 size_res => size_res); 7106 end function to_float; 7107 7108 -- For Verilog compatability 7109 function realtobits (arg : REAL) return STD_LOGIC_VECTOR is 7110 variable result : float64; -- 64 bit floating point 7111 begin 7112 result := to_float (arg => arg, 7113 exponent_width => float64'high, 7114 fraction_width => -float64'low); 7115 return to_slv (result); 7116 end function realtobits; 7117 7118 function bitstoreal (arg : STD_LOGIC_VECTOR) return REAL is 7119 variable arg64 : float64; -- arg converted to float 7120 begin 7121 arg64 := to_float (arg => arg, 7122 exponent_width => float64'high, 7123 fraction_width => -float64'low); 7124 return to_real (arg64); 7125 end function bitstoreal; 7126 7127end package body float_pkg; 7128