Intel® Hyperflex™ Architecture High-Performance Design Handbook

ID 683353
Date 12/08/2023
Public
Document Table of Contents

2.4.1.5. Precomputation

Precomputation is one of the easiest and most beneficial techniques for optimizing overall design speed. When confronted with critical logic, verify whether the signals the computation implies are available earlier. Always compute signals as early as possible to keep these computations outside of critical logic.

When trying to keep critical logic outside your loops, try precomputation first. The Compiler cannot optimize logic within a loop easily using retiming only. The Compiler cannot move registers inside the loop to the outside of the loop. The Compiler cannot retime registers outside the loop into the loop. Therefore, keep the logic inside the loop as small as possible so that the logic does not negatively impact fMAX.

After precomputation, logic is minimized in the loop and the design precomputes the encodings. The calculation is outside of the loop, and you can optimize the calculation with pipelining or retiming. You cannot remove the loop, but can better control the effect of the loop on the design speed.

Figure 58. Restructuring a Design with an Expensive Loop

The following code example shows a similar problem. The original loop contains comparison operators.

StateJam:if
        (RetryCnt <=MaxRetry&&JamCounter==16)
            Next_state=StateBackOff;
        else if (RetryCnt>MaxRetry)
            Next_state=StateJamDrop;
        else
            Next_state=Current_state;

Precomputing the values of RetryCnt<=MaxRetry and JamCounter==16 removes the expensive computation from the StateJam loop and replaces the computation with simple boolean operations. The modified code is:

reg RetryCntGTMaxRetry;
reg JamCounterEqSixteen; 
StateJam:if
        (!RetryCntGTMaxRetry && JamCounterEqSixteen)
            Next_state=StateBackOff;
        else if (RetryCntGTMaxRetry)
            Next_state=StateJamDrop;
        else
            Next_state=Current_state; 
        always @ (posedge Clk or posedge Reset)
        if (Reset)
            JamCounterEqSixteen <= 0;
        else if (Current_state!=StateJam)
            JamCounterEqSixteen <= 0;
        else 
            JamCounterEqSixteen <= (JamCounter == 15) ? 1:0; 
        always @ (posedge Clk or posedge Reset)
        if (Reset)
            RetryCntGTMaxRetry <= 0;
        else if (Current_state==StateSwitchNext)
            RetryCntGTMaxRetry <= 0;
        else if (Current_state==StateJam&&Next_state==StateBackOff)
            RetryCntGTMaxRetry <= (RetryCnt >= MaxRetry) ? 1: 0;