JulianKemmerer / PipelineC

A C-like hardware description language (HDL) adding high level synthesis(HLS)-like automatic pipelining as a language construct/compiler feature.
https://github.com/JulianKemmerer/PipelineC/wiki
GNU General Public License v3.0
569 stars 46 forks source link

Synthesis timing loops (rarely only w/ Vivado so far) #172

Open JulianKemmerer opened 11 months ago

JulianKemmerer commented 11 months ago

Code like below, but only for Vivado synthesis seen so far (2019.2, tried a few syn strategy options, didnt help)...

#pragma PART "xc7a100tcsg324-1"
//#pragma PART "5CEBA4F23C8"
//#pragma PART "LFE5U-85F-6BG381C"

#include "uintN_t.h"
#pragma MAIN main
float main(float a, float b, uint16_t x)
{
  float fconst = 1.23;
  float fx = (float)x;
  float mults = (fx * fconst) * a;
  float rv = mults + b;
  return rv;
}

Will result with synthesis warnings like

CRITICAL WARNING: [Synth 8-326] inferred exception to break timing loop: 'set_false_path -through main_0CLK_1ad76fbfi_0/i_255/O'
CRITICAL WARNING: [Synth 8-326] inferred exception to break timing loop: 'set_false_path -through main_0CLK_1ad76fbfi_0/i_254/O'
CRITICAL WARNING: [Synth 8-326] inferred exception to break timing loop: 'set_false_path -through i_200/O'

No other tools seem to find combinatorial loops (tried Quartus and yosys+nextpnr). Getting Vivado to report loops after syn completes reports no loops in the design - can't find those nets from the error messages.

Changing float mults = (fx * fconst) * a; to float mults = fx * (fconst * a); makes it so Vivado no longer sees a timing loop.

I have not ruled out that somehow this is in the HDL - maybe simulating more will help...

I have reason to believe this is a serious issue where needed functionality is being flagged as a loop and optimizing away incorrectly.

Best work around for now is as above - start commenting out / trimming down your design until you find the problem function and subtly rewrite it maintaining the original functionality.

I know - it's F'd.

JulianKemmerer commented 11 months ago

Confirmed this does break the implemented hardware after synthesis - without the timing loop bitstream behaves as expected...