Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Suggestion] This package may be highly benefitted from SystemC fixed-point arithmetics #252

Open
danilo-bc opened this issue Jul 29, 2021 · 15 comments
Labels
add-on Making add-ons helps enhancement

Comments

@danilo-bc
Copy link

I've been using SystemC for modelling systems with fixed-point arithmetics for a while. It focuses on describing hardware systems with C++ language and it's been pretty mature, with an IEEE Standard (https://standards.ieee.org/standard/1666-2011.html)

Section 7.10 of the standard approaches fixed-point types and their characteristics. In general, a fixed-point number can be represented and used as:

sc_fixed_fast<8, 1, SC_RND, SC_SAT> x = 0.5; //round and saturate 
sc_fixed_fast<9, 2, SC_TRN, SC_WRAP> y = 0.5; //truncate and wraparound overflow

One of the useful applications of this type system is you can have 'wide' variables to do a series of calculations and store a given value, then create a <8, 1> type to round and saturate the input to your interface. The error from converting a wide type (for example, <32, 8> storing some multiplication) to a smaller type is expected and is part of the whole analysis for the system application.

Apparently, sc_fixed_fast types always store 32/64 bit numbers, but only operate on their given number of bits. They are fast because they don't try to store and odd number of bits (such as 9) in the memory, although they obviously use more memory than necessary.

A bunch of useful operations are defined, such as bitwise AND and OR and bitshift operators (<<, >>, <<<, >>>).

Although this type system from SystemC is pretty useful, I think Julia could offer a much wider world of opportunities.

If all this sounds reasonable, I'd be glad to help. If it's not the scope of the project, it's understandable.

@kimikage
Copy link
Collaborator

I am not familiar with SystemC, but I think it is a good idea to comply with the standards of the technology used in industry.

We might need to consider the following points:

  • Currently, FixedPointNumbers is mainly used to represent colors, so incompatibilities with the downstream packages for visualization and image processing should be minimized.
  • There is no definite design consensus on whether arithmetic and rounding properties should be held by data types or by functions. However, it will be difficult to extend existing types while maintaining compatibility.
  • This package has a long cycle of minor version updates. This is not only a problem of insufficient development resources for this package, but also a problem with the downstream packages.

IMO, if you are considering taking the approach of adding new types, it might be a good idea to create them in an add-on package. Of course, that does not mean that this project is out of the scope of this package.

@danilo-bc
Copy link
Author

I think it's a bit unfortunate that the package is called FixedPointNumbers, but focuses on image processing.

I had a problem a long time ago where I used an entropy function in Matlab in the global scope not knowing it specifically calculated the entropy of an 8-bit greyscale image.

The same problem may happen here if decisions are made for images only. Take FixedPointDecimals.jl which uses the same fixed-point arithmetics basis as this package, but applies to finances.

Maybe a FixedPointBase.jl can be thought out and branched into FixedPointImages and FixedPointFinances?

That said, I'm currently unable to help with these issues, but I'm very interesting by the consequences which would come from them (I'll check with my local and web community if someone also thinks the idea is interesting & would have the time to help).

@kimikage
Copy link
Collaborator

I agree that some parts of the type hierarchy are not ideal, but I don't think it is a fatal problem for practical use.

I believe that basic data types should be identified by the properties that the types themselves should have, not by their applications.

@timholy
Copy link
Member

timholy commented Aug 2, 2021

All of the arithmetic in this package is fixed-point arithmetic. It's just that in addition to the "standard" fixed-point numbers (normalized by 2^n) there are some additional types (normalized by 2^n - 1) that are useful for image-processing, and it so happens that these are far more widely used in practice than the "standard" ones. But there's nothing misleading about calling these fixed-point.

@danilo-bc
Copy link
Author

Thanks for the input! My major problem with using this package (which, don't get me wrong, I find very useful) is that I can't do things like x = Fixed{Int8, 7}(1.3) because I get an ArgumentError, when what I really needed was for the variable to silently either overflow (and become negative) or saturate (to 0.992). This doesn't count for the truncate/round portion that I mention is present on SystemC as well, which could take 0.3 to 0.25, for example.

Am I missing some other type which doesn't throw an error in this situation?

@kimikage
Copy link
Collaborator

kimikage commented Aug 2, 2021

There is no all-around solution, but you can do something like:

julia> 1.3 % Q0f7
-0.703Q0f7

julia> clamp(1.3, Q0f7)
0.992Q0f7

@danilo-bc
Copy link
Author

Thanks for the proposal, this may help me explore my use case a bit more.

When using sc_fixed_fast in SystemC (basically writing C++ code), I'm able to do operations with <8, 1> numbers (Q0f7 if I understand your notation properly), store their results in <18, 4>, then simply do
my_8_1_result = my_18_4_var
and have the <18, 4> result be rounded and saturated the way I configure my my_8_1_result type (possibly with Traits?).

From what I understand this type of automatic type conversion is not supported and I'd always have to do attributions like
my_8_1_result = clamp(my_18_4_var, Q0f7)
as you've just shown me.

In terms of calculation performance, the sc_fixed_fast type stores things as 64-bit variables. I'm pretty sure Julia does the same approach for, say, Int8, Int16, Int32. If so, they both shouldn't have a performance penalty unless some higher-order bit-width is required (like 128-bit fixed-point numbers).

@timholy
Copy link
Member

timholy commented Aug 2, 2021

I'm pretty sure Julia does the same approach for, say, Int8, Int16, Int32.

Julia preserves the precision and uses overflow behavior. You're getting the error on initial creation but then:

julia> x = 0.6Q0f7
0.602Q0f7

julia> x + x
-0.797Q0f7

@danilo-bc
Copy link
Author

Julia preserves the precision and uses overflow behavior.

Thanks, Tim, I understand how this is implemented. My final comment there was in terms of how the variables are stored in the memory (the physical memory). SystemC has sc_fixed_fast and sc_fixed types. The _fast type provides a faster runtime by always allocating 64 bits to store values (even if the required notation uses only 8 bits).

If the suggestion of taking SystemC's fixed-point system methodology doesn't fit this particular project (since it seems widely used in the Image Processing area), I may try to fork the project and try to implement some of the automatic round/truncate, overflow/saturate functionality from SystemC.

@kimikage kimikage added enhancement add-on Making add-ons helps labels Apr 28, 2024
@kimikage
Copy link
Collaborator

kimikage commented May 3, 2024

The following might have a little to do with this issue.
https://discourse.julialang.org/t/vaporware-rfc-width-qualified-fixedpointnumbers/113774

@rekabrnalla
Copy link

This thread is like 3 years old but I was very interested in the system c comment and following ieee standards.

I would be interested in this use case.

I have a signal processing or some type of controller algorithm i'm simulating in Julia. I need to give the algorithm to a VHDL firmware engineer. I want to run and simulate it in fixed point to understand the quantization problems or other weaknesses in the algo when converted to fixed point.

But I would also like use automatic differentiation and global optimization function to tune the fixed point parameters to best match the floating point algorithm performance but also minimize fixed point resources.

Could I use this toolbox to do such a thing, or would I need to start from something like an ieee standard of system-C?

Thanks. Sorry if I broke etiquette by tagging an old thread. Blame google for showing me it.

Cheers.

@kimikage
Copy link
Collaborator

kimikage commented Jun 11, 2024

The overflow handling is expected to be resolved to some extent in the next version 0.9 with OverflowContexts.jl.
However, there is still no systematic method for rounding modes other than for integer division (3-arg div).

For such reasons, I do not think that FixedPointNumbers.jl will provide SystemC-compatible fixed-point numbers in the near future.

On the other hand, Julia's language features are sufficient to implement it. Also, Julia's ecosystem is already rich with packages for automatic differentiation, optimization, visualization, etc., and it would surely be attractive if there was a package for fixed-point numbers that could work with them.

The WideQualifiedFixedPointNumbers.jl mentioned above could be a first step, but unfortunately no one has the resources to put into its development for now.

Perhaps we should focus a little more on outreach activities.

@danilo-bc
Copy link
Author

@kimikage @rekabrnalla There's a great Python library which can bridge this gap for the time being: https://github.com/ZZZZzzzzac/numfi. It implements fixed-point arithmetic on top of floating point numbers. Although not perfect, we can create a numfi environment in Julia and use its features.

I can't find the reference article for it, but it should be similar to the sc_fixed_fast type in SystemC, where it can store up to 50ish fixed-point bits in a floating-point container and the operations will be correctly calculated as long as the exponents are not too different from each other and don't exceed that size.

@kimikage
Copy link
Collaborator

kimikage commented Jun 11, 2024

If you don't care about bit widths and rounding modes, I think Fixed already has enough functionality. (I'm planning to support bit shifting in v0.9. cf. #250)

Support for specifying bit widths and rounding modes is not technically very difficult, but it requires a lot of work (including tests with downstream packages and documentation).

@danilo-bc
Copy link
Author

@kimikage firstly, I want to thank for your attention and contribution to this repository (and
WidthQualifiedFixedPointNumbers.jl!). I haven't been able to use it, but I see the amount of work put into it.

We do care a lot about controlling bit widths, rounding modes and saturation modes. The fxpmath Python library is another example of library which implements these features in another way.

A small pet example of what we'd want to adopt this library in Verilog/VHDL contexts is:

> using FixedPointNumbers
> x = Fixed{Int8, 7}(0.5)
> x + x
-1.0Q0f7 OR 0.9921875Q0f7 OR 1.0Q1f7

Depending on settings.

Again, recalling the discussion from 2021, I understand this package is incredibly useful for image processing, but there are a few limitations from our context, better suited to another package. At this point, I think it would be fair to close this discussion with this conclusion, and point users towards the other package and the discourse post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
add-on Making add-ons helps enhancement
Projects
None yet
Development

No branches or pull requests

4 participants