Re: [vhdl-200x-ft] Re: floating point, thinking out loud

From: Jim Lewis <Jim@SynthWorks.com>
Date: Tue Dec 07 2004 - 13:34:49 PST

David,
I have a few embedded comments below.

> Jim Lewis wrote:
>
>> David,
>> > What do you think about this?
>> As far as I can see, the exponent and mantissa width
>> are specified with generics. Is there something I am
>> missing? I am not excited about this.
>>
>> Does having width of exponent and mantissa constrained
>> buy us anything? One thing I think you mentioned in the
>> meeting is that if fp32 is a constrained type and there
>> are specific subprograms that only handle fp32, then one
>> can do:
>> Y_fp32 <= A_fp32 + "11000000110100000000000000000000" ;
>
>
> It also means that you can say:
> Y_fp32 <= to_fp(7.5);
> If the fraction and exponent were not in the generics you would
> have to say:
> Y_fp32 <= to_fp(7.5, Y_fp32'high, -Y_fp32'low);

or change to_fp to take an object and let the function
use 'high and 'low on the object:

   function to_fp (arg : real; obj : fp) ;

   Y_fp32 <= to_fp(7.5, Y_fp32) ;

>> On the other hand, lets suppose that I have fp32 defined
>> as a subtype of fp and all math operations are implemented
>> for the type fp.
>> subtype fp32 is fp(8 downto -23) ;
>>
>> Can't I coerce the string literal using a type qualifier
>> as follows?
>> Y_fp32 <= A_fp32 + fp32'("11000000110100000000000000000000") ;
>
>
> Yes, this would work, and it is the same model as we have to use
> for fixed point.
>
> The issue is that the typical user will select ONE format for
> floating point, and convert to and from it.
I would expect fp_round_style, fp_denormal, and fp_check_error
to stay the same. I was wondering if people change the number
of bits they use and perhaps even the number of guard bits they
use depending on the precision they need.

For example do I want more guard bits for a multiply than
for an add/subtract?

I would really like to see some of the FP experts who have
joined the reflector to comment on this.

>> > Will this fill your need for a user definable floating point?
>> I need to see the trade-offs to really get a handle on the
>> situation. I am still of the opinion that if we leave exponent
>> and mantissa unconstrained, we will end up with less package
>> instantiations and perhaps be able to instantiate most/all
>> of them in the IEEE library.
>>
>> Part of my concern is that these packages are the start of
>> floating point. As silicon area increases, what we do on a
>> chip will increase. The use model needs to be basic and easy
>> to do, as with increased silicon area, we will be building
>> things like complex numbers and matrix math on top of them.
>
>
> That is exactly the way I see it as well.
>
>> --------------------------------------------------------------
>> Here is one area I would like to explore. I need to put more
>> time into it and will not be able to until after the next meeting.
>> If we use the subtype approach, I speculate that we will also
>> need a package which defines aliases. For example we will
>> need to create an alias that points to the IEEE 754/854
>> standard version of fp32:
>>
>> Package fphdl_alias is
>> alias ieee_fp32 is ieee.fphdl_w_x_y_z.fp32 ;
>> . . .
>> end fphdl_alias ;
>>
>> Then I am thinking that we can knit it all together
>> so that using fphdl looks as simple as a package reference:
>>
>> context fphdl_ctx is
>> library ieee ;
>>
>> use ieee.fphdl_types.all ;
>> -- make all parameterized fphdl packages visible for usage:
>> use ieee.fphdl_xxx.all ;
>> use ieee.fphdl_yyy.all ;
>> ...
>> use ieee.fphdl_zzz.all ;
>>
>> use ieee.fphdl_alias.all ;
>> end context ;
>>
>> Even without the exponent and mantissa widths
>> specified, this still looks like a large number
>> permutations for the fphdl package.
>>
>> Computer based numeric representations are ment to get
>> good results with fixed width objects. Hence we have
>> standard definitions for 32 and 64 bit floating point.
>> Hardware is not constrained to word widths. In
>> hardware we can use 38 bits if we wish.
>>
>> Are guard bits extra bits for the ?mantissa? that are
>> needed to maintain precision for some operations?
>
>
> Yes. My pet example is 1/3. In fixed point the answer
> is 0.101010101010.....
> Which rounds to 0.1010101011. You need 3 bits to make this work.
> Thus:
> 0.101010101010|101
> Rounds to:
> 0.101010101011
> Because the bottom bit is a "0" you need the "101" to bump it up to
> the next binary state.
> I had to do this to match the IEEE-754 result.
>
>> Is
>> there some way to take advantage of this and reduce
>> the number of package permutations we need? After
>> synthesis if the LSBs of an array always get set to
>> 0, then effectively they are not part of the
>> logic and this effect will be propagated to simplify
>> other hardware.
>
>
> This is why they are package generics, and not constants.
>
>> ------------------------------------
>> Going in an entirely different direction, are there
>> any language enhancements we need to make this more
>> work able? It sure would be nice if we had a
>> way to augument a type or subtype with the "other" things
>> we are specifying with generics, fp_round_style,
>> fp_denormalize, fp_check_error, and fp_guard_bits.
>> Effectively this would become an attribute that can
>> maintains its value through a call to subprogram.
>
>
> Yes, but it makes the use model much more complicated
> than it needs to be.

>
>> It is really an ironic shame about the attributes
>> on signals not being passed into the subprogram.
>> They are not passed because the LRM allows constant
>> parameters to be passed by value, however, for
>> array parameters, the LRM also allows them to be
>> passed by reference. So the bottom line seems to
>> be that the attributes are not available because
>> the object may be passed by value although it is
>> probably passed by reference.
>>
>> ------------------------------------
>>
>> I should be able to do a more detailed review of what you
>> are proposing sometime after the next meeting and perhaps
>> then be able to propose an alternative.
>
>
>
> Think about this use model:
>
> package fphdl_types is
> .....
> type float is array (INTEGER range <>) of STD_LOGIC;
> subtype fp32 is float (8 downto -23);
> subtype fp64 ....
>
> end package fphdl_types;

Why do we need a separate types package?

I suspect that if we define float, fp32, fp64 in a
separate package from fphdl_pkg, then if we instantiate
the package more than once (probably rare with the
modified interface) it will create homographs
of the operators and functions.

I think we either need all of these types in the fphdl_pkg
or we need a float type in the types package and an
identically defined fp type in the fphdl_pkg. I think
this is similar to the package architecture you had before.

I like what you are proposing with the fphdl_pkg interface
and use model below:

> package fphdl_pkg is
> generic (
> -- NO fraction_width and exponet_width generics
> fp_round_style : round_type;
> fp_denormalize : BOOLEAN;
> fp_check_error : BOOLEAN;
> fp_guard_bits : NATURAL
> );
>
> function to_fp (arg : real;
> exponent_width : natural;
> fraction_width : natural);
> function to_fp32 (arg : real);
> function to_fp64 (arg : real);
> function to_fp128 (arg : real); -- For all standard widths
> .....
> end package body fphdl_pkg;
>
> package fphdl_IEEE is new IEEE.fphdl_pkg
> generic map (
> fp_round_style := round_nearest;
> fp_denormal := true;
> fp_check_error := true;
> fp_guard_bits := 3);
>
>
> Then the use model would be:
>
> use ieee.fphdl_types.all;
> use ieee.fphdl_ieee.all;
> signal xxx, yyy : fp32;
> begin
> yyy <= to_fp32(3.14);
> xxx <= xxx + yyy;
>
> IF the user wanted to create their own type they could do this:
>
> use ieee.fphdl_types.all;
> use ieee.fphdl_ieee.all;
> subtype fp18 is float (7 downto -10);
> signal xxx, yyy : fp18;
> begin
> yyy <= to_fp18(3.14, yyy'high, -yyy'low);
> xxx <= xxx + yyy;
>
> IF a user doesn't want IEEE rounding and denormal numbers, they can
> do this:
>
> use ieee.fphdl_types.all;
> package fphdl_small is new IEEE.fphdl_pkg
> fp_round_style := round_zero;
> fp_denormal := false;
> fp_check_error := false;
> fp_guard_bits := 0);
>
> use work.fphdl_small.all;
> signal xxx, yyy : fp32;
> begin
> yyy <= to_fp32(3.14);
> xxx <= xxx + yyy;

Does the use model need to allow a user to be able
to switch (while doing trade-offs) between floating point
and fixed point? Granted this would complicate the
package design.

Cheers,
Jim

-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jim Lewis
Director of Training             mailto:Jim@SynthWorks.com
SynthWorks Design Inc.           http://www.SynthWorks.com
1-503-590-4787
Expert VHDL Training for Hardware Design and Verification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Received on Tue Dec 7 13:35:01 2004

This archive was generated by hypermail 2.1.8 : Tue Dec 07 2004 - 13:36:08 PST