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 |
|---|---|
| Area | Fewer cells, LUTs and flip-flops. The right default when you are running out of fabric, or fitting a design into a smaller part. |
| Timing | Less combinational depth between registers — the proxy we can measure, not a timing report. 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.
What to expect from a run
An optimize run measures your design as you supplied it before it changes anything, and every number you see afterwards is a comparison against that starting point. Changes are made and checked one at a time, so a rewrite that does not actually help is dropped rather than left in the diff for you to argue with.
The consequence worth knowing is that the final measurement and the final behaviour check both come after the last edit. That is what makes the badge on the proposal card mean something; evidence gathered before the last change says nothing about that change.
Tip
An optimize run takes longer than a build of the same design, because measuring and checking are most of the work. If you are exploring rather than committing, start with a single module and the Medium effort setting.