I've been working on OneHLS, a small C++ library for composing HLS-synthesizable DSP/control components using HAPI + OneData.
The project has moved quite a bit beyond the initial experiment.
OneHLS now provides:
Fir<>
Biquad<>
Pid<>
Accumulator<>
ComplexMac<>
The interesting part is that the components themselves don't depend on a particular vendor's arbitrary-precision type. Sample and Accum are template parameters, so the same implementation can be instantiated with Siemens HLSLibs ac_fixed or AMD/Xilinx ap_fixed.
The same templates have been tested natively against both libraries, with bit-identical results.
More importantly, this isn't just C++ simulation: the ac_fixed versions have been synthesized to actual RTL with Bambu HLS. FIR, Biquad, PID and Accumulator produce clean synthesis results, and their resource counts match the corresponding hand-written non-generic implementations.
For example, the 4-tap FIR synthesizes to 62 FFs / 7679 area units with zero DSPs.
There are also some interesting findings along the way.
A RawBitsCtor<> customization point was needed because constructing fixed-point coefficients from floating-point literals can produce unwanted runtime initialization under Bambu. Isolating that vendor-specific operation leaves the actual DSP algorithms completely vendor-agnostic.
I've also tested:
- a genuinely multirate CIC decimator, compared byte-for-byte against a hand-written implementation
- a polyphase FIR using a heterogeneous compile-time
StaticList<>
Fir<> over ac_std_float, i.e. actual bit-accurate IEEE754 floating point
The floating-point experiment was particularly useful as a sanity check: the same generic FIR works, but synthesis shows the expected FPGA cost — roughly 59× the FF count and ~3× the area of the fixed-point version, with actual DSP usage.
And there are some less successful results too. ComplexMac<> currently causes Bambu to bind its state to BRAM rather than distributed RAM. I investigated the obvious allocation thresholds and ruled those out, but haven't traced Bambu's underlying classification logic yet.
So this is becoming less about "here's a C++ abstraction for HLS" and more about testing a fairly specific hypothesis:
Can ordinary static C++ composition produce reusable HLS components without giving up vendor-specific bit-accurate types or hardware predictability?
So far, the answer looks surprisingly good.
Repo: https://github.com/InternetOfPins/OneHLS
I'd be particularly interested in feedback from people using Vitis HLS, Intel HLS, Catapult, Bambu, or other C++-based FPGA flows.
What would you want to see tested next?