Optimization
Setting up an optimization run
Objective, effort and target device; the three choices that shape the whole run.
"Make it better" is not one request. Area and logic depth trade against each other, and both trade against readability, so the run asks what you are optimising for before it starts rather than reporting whichever number happened to move.
Objective
| Objective | What it goes after |
|---|---|
| Smaller | Fewer cells, LUTs and flip-flops. The right default when you are running out of fabric, or fitting a design into a smaller part. |
| Shallower logic | Less combinational depth between registers. The right choice when you are missing timing and the critical path is combinational. |
| Balanced | Take the wins that do not cost much on the other axis. Good for a design nobody has been through in a while. |
The objective is what the verdict is computed against. A rewrite that cuts logic depth while the objective was area does not count as a win, and it does not get reported as one; it shows up as a change with its trade-off stated.
Effort
Effort controls how much exploring the run may do: how many steps it can take and how much it may spend. It does not change the rules, the measurement or the proof.
| Effort | Roughly |
|---|---|
| Low | A quick pass. Finds the obvious wins on a small module and stops. Cheapest and fastest. |
| Medium | The default. Enough room to try several transformations and measure each one properly. |
| High | For a large or dense design where the first three ideas are unlikely to be the good ones. |
Tip
Start at Medium. If the answer comes back as nothing worth changing on a design you are sure has slack in it, raising the effort is the right next move; raising it on a design that has already been optimised will mostly buy you a longer explanation of why not.
Target device
This genuinely changes the answer, which is why it is asked rather than assumed. Logic that costs three four-input lookup tables costs one six-input lookup table, so a win measured against a generic library can be a regression on the part you are actually using.
| Target | Measured as |
|---|---|
| Xilinx | AMD / Xilinx 7-series primitives |
| Intel | Intel / Altera MAX 10 primitives |
| Lattice | Lattice ECP5 primitives |
| Gowin | Gowin primitives |
| Generic | Abstract gates. Useful for comparing structure, misleading as a resource estimate for a real part. |
Pick the family you are actually building for. If you do not know yet, Generic is honest about being approximate, which is better than a precise number for a chip you will not use.
The optional fields
| Field | When to fill it in |
|---|---|
| Top module | When the project has more than one candidate. Everything is measured through this module, so naming the wrong one measures the wrong design. |
| Focus | When you already know where the cost is. “The address decoder in mem_ctrl” saves the run from measuring its way there. |
| Constraints | Anything that must not change: a module another team owns, an interface timing contract, a coding standard you have to keep to. |
Note
The interface is preserved in every case, whether or not you say so. Changing ports would break every instantiation of the module and would also make the equivalence check impossible to run, so it is not an option that can be switched off.
How the run proceeds
- 1
Measure the original
Before anything is touched, the design as you supplied it is synthesised and recorded. Every later number is a comparison against this, and the sources it was measured from are pinned so the reference cannot drift.
- 2
One transformation at a time
A single change, then a measurement, then an equivalence check. Five changes applied together and then proved wrong tell you nothing about which one broke it.
- 3
Keep it or revert it, on the evidence
A change that does not improve the objective, or that fails the proof, is reverted rather than left in. A neutral rewrite is pure cost to whoever reviews it.
- 4
Measure and prove last
The final measurement and the final proof both come after the last edit. Evidence gathered before the last change says nothing about that change, and this is tracked rather than trusted.