Skip to content

[Buffers] fix non-CFDFC paths having non-zero occupancy - #979

Open
ziadomalik wants to merge 16 commits into
mainfrom
fix/ziad/non-zero-occ-at-non-cfc-channels
Open

ziadomalik wants to merge 16 commits into
mainfrom
fix/ziad/non-zero-occ-at-non-cfc-channels

Conversation

@ziadomalik

Copy link
Copy Markdown
Collaborator

Problem: The implementation of the FPGA24 MILP's were missing constraint (10) and (11) described in this paper, resulting in patterns that are not in CFC's have a non-zero occupancy, which makes no sense, because occupancy tries to cater for incoming tokens in a loop body. (Initiation Interval).

This PR: Adds the missing constraints and re-works the rest of the code to adapt, as well as explicitly ignore patterns in the occupancy LP that have forks that are not part of a CFC.

@ziadomalik
ziadomalik requested a review from Jiahui17 June 15, 2026 15:27
auto latOrFail =
timingDB.getLatency(node.op, SignalType::DATA, targetPeriod);
if (succeeded(latOrFail) && *latOrFail > 0.0)
constPart += *latOrFail;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is II in the original constraint?

Comment thread lib/Transforms/BufferPlacement/Utils/BufferPlacementMILP.cpp
@Jiahui17

Copy link
Copy Markdown
Member

@ziadomalik

Another thing that came across: could you generate a ONE_SLOT_BREAK_DV instead of a counter buffer if lat == 1 and slots == 1?

@Jiahui17

Copy link
Copy Markdown
Member

Not related to the PR but we should remember to check if it helps

@ziadomalik

Copy link
Copy Markdown
Collaborator Author

Hi, turns out I thought adding the filtering was going to be enough so I kept the style where I formulated the constraint for all channels in a CFDFC. This is bad, since we emit one global equality per path pair, instead of one per CFDFC and a path shared by two CFDFCs with different IIs needs a separate constraint under each II, and the code was disregarding that. Also good catch on missing the II division, I think it was indirectly caused by the above. Now that we do per-CFDFC we can use the entries in computedCFDFCIIs that we already computed, the way we did it before wouldn't have made it possible. Like what II would I even pick. I think this should be fine now, no major improvements in terms of FF and LUT's.

Also tried the setting of ONE_SLOT_BREAK_DV for the case you mentioned above, nothing has changed, I will keep investigating though...

Comment thread lib/Transforms/BufferPlacement/FPGA24Buffers.cpp Outdated
Comment thread lib/Transforms/BufferPlacement/FPGA24Buffers.cpp Outdated
Comment thread lib/Transforms/BufferPlacement/Utils/BufferPlacementMILP.cpp Outdated
@ziadomalik

ziadomalik commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

I revisited the paper, found some mistakes I had made and now made sure to be a lot more faithful to its description of the constraints. I also added more comments to clarify the way I am enumerating relevant patterns and structs to add the variables and constraints needed for LP2.

Where I am covering what constraints of LP2

Equation 8

Computes minimum occupancy needed based on the extra latency we need to add $(L^c)$ and the amount of cycles it takes for a new token to arrive on that CFC $(II_{CFC_{i}})$:

$\frac{L^c}{II_{CFC_{i}}} \leq N^c_{CFC_{i}}$

It is implemented in BufferPlacementMILP::addMinOccupancyConstraints

Equation 9

Analogous for Equation 8, we set for each unit, here $D^u$ being the units inherent latency.
We just set an upper bound of the units capacity.

Important

QUESTION: What is Capacity supposed to be in C++ terms? When I initially created the variables, I assigned it to a constant, but I can not remember why we agreed to set it to that. We need to confirm how to get the unit Capacity.

$\frac{D^u}{II_{CFC_{i}}} \leq N^u_{CFC_{i}} \leq \text{Capacity}^u$

It is implemented in BufferPlacementMILP::addUnitOccupancyConstraints

Equation 11

Makes sure that for pair of reconvergent paths in a CFC, the total occupancy is identical.
(Total being the sum of the unit and channel occupancies).

It is implemented in BufferPlacementMILP::addPathOccupancyEqualityConstraints

Equation 12

This constraint just ensures there's no more than $B$ tokens per cyclic path during the steady-state of the CFC, idk what that means, but it says for each cycle l of the CFC, this needs to be satisfied: $\text{Occupancy}_{CFCi}(l) \leq B$

Important

QUESTION: What do we set B as? Right now I am just assuming we're doing sequential programs, so I am hardcoding this to be 1, as per this section here in the paper: "For dataflow circuits generated from sequential programs, 𝐵 = 1"

It is implemented at the very end of BufferPlacementMILP::addCycleOccupancyConstraints

Equation 13

Let there be two CFC's that both share a channel $c$, they may have two different occupancies, meaning $N^c_{CFC_{i}} \neq N^c_{CFC_{j}}$, so we introduce $N^c_\text{max}$ that defines for the channel $c$ the maximum occupancy accross all the CFCs that contain $c$:

$N^c_{\text{max}} \geq N^c_{CFC_{i}}$

It is implemented at BufferPlacementMILP::addMaxOccupancyConstraints

Equation 14

Is the objective function that minimizes every channel max occupancy weighted with the bitwidth.
The only extra thing I am doing here is setting 1 as a default bitwidth if it's 0.

It is implemented in BufferPlacementMILP::setOccupancyBalancingObjective

Note on LP1

Before, every simple cycle in a CFC was forced to latency exactly $II$, but the paper in Equation 5, it's actually $1 \leq latency \leq II$. I think this was deliberate in the beginning since we're doing the same as what's happening in Section 7, but I ran out of ideas, so I tried matching the paper 1 to 1.

@Jiahui17

Jiahui17 commented Sep 3, 2026

Copy link
Copy Markdown
Member

Thanks for addressing the comments! Regarding the questions:

  • We can set the capacity B to the latency of the unit, because the latency (or the number of pipeline stages) is the reason why we have capacity
  • B = 1 is correct, yes!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants