Module 10: Capstone Projects · Project 5: Debugging a Broken Flow

Project 5, Part 3: Fixes and Lessons Learned

In the previous article we traced three failing reports to two causes. The way each is fixed matters as much as the fix. It would be easy to make every report go quiet without fixing anything real, and I want to show why each of those quick fixes is wrong before doing the right one.

Fix one: the manual ECO (DRC and LVS)

There are two tempting wrong fixes here. The first is to nudge the hand-drawn wire until it clears 0.14 µm. That silences the DRC report, but the wire is still outside the router’s knowledge, and the LVS mismatch is untouched. The second is to delete _eco_buf_9 so the instance counts match again. That silences LVS, but if the buffer was there to fix a real hold problem on rx_valid, you have just removed the fix and put an unverified timing failure back into the design.

The right fix is to make the change the way Project 2 did: inside the flow, where the netlist, the placement and the routing are all updated together.

  1. Throw away the manual edits: go back to the routed design as the flow left it, before the buffer and the wire were added.
  2. Find out whether the buffer was needed at all. Run the post-CTS hold check from Project 2. In this run it shows a hold violation of −0.021 ns at the fast corner on the path into rx_valid’s capturing flop, so the person who added the buffer was right that something was needed.
  3. Let the flow fix it: make sure the post-CTS timing repair is enabled, and re-run from CTS. The resizer inserts a hold buffer on that path, the router routes it with proper clearance, and OpenLane writes the final netlist from the same database.
openlane --flow Classic --run-tag uart_fixed --from OpenROAD.CTS designs/uart/config.json

The DRC report on the new GDS:

COUNT: 0

And LVS against the new final netlist:

Final result: Circuits match uniquely.

The hold fix is still there, now as a flow-generated buffer that the router placed wires to and the netlist knows about. That is Project 2’s rule seen from the other side: any change to the physical design has to go through the flow, or at least into the netlist, before signoff.

If for some reason a manual edit really must stay, the minimum is to make it in the OpenROAD database, not in the GDS or DEF text, route the change with the router, and write the netlist from the same database (write_verilog in OpenROAD) before LVS. Every check then sees the same design.

Fix two: the fanout

The wrong fix is to buffer baud_tick by hand and leave the configuration as it is. That fixes this net and leaves the same condition waiting to create another, identical problem on some other net in a future run. The right fix restores the constraint and the step that enforces it:

"MAX_FANOUT_CONSTRAINT": 10,
"RUN_POST_GPL_DESIGN_REPAIR": true

Re-running from placement, the design repair step buffers baud_tick into a small tree of buffers, each driving about ten loads, and the multi-corner STA reports:

Corner Worst setup slack Worst hold slack
tt_025C_1v80 +2.31 ns +0.16 ns
ss_100C_1v60 +0.44 ns +0.09 ns
ff_n40C_1v95 +3.02 ns +0.05 ns

All three corners pass. The slow corner, the one that failed, improves the most, which is what you expect when the problem was a weak driver on a heavy load: the flop now drives two buffers instead of 42 pins and a long wire.

Final re-check

After both fixes, from the final run:

DRC (Magic):   COUNT: 0
LVS:           Circuits match uniquely
Antenna:       0 violating nets
Setup, all corners: worst +0.44 ns (ss)
Hold, all corners:  worst +0.05 ns (ff)
GDS:           runs/uart_fixed/final/gds/uart_top.gds

Every check that failed is clean, and just as important, nothing that was passing has broken. That second part is not automatic; it is why each fix was followed by the full set of checks rather than trusting that a targeted change could have no side effects.

These three failure modes, a hand-patched piece of geometry, an ECO that never reached the netlist, and a relaxed constraint that only bites at one corner, are not exaggerated for teaching. All three turn up in real tapeout post-mortems, and they nearly always trace back to the same behaviour: a step done outside the normal, tool-checked flow, under time pressure, without going back to update everything that depended on it.

The course, one habit per stage

Ten modules and five capstones end here. Not with new material, but with the one habit each stage of the flow is built around:

  • Synthesis and constraints. Say what you mean, explicitly: clocks, I/O timing, fanout and load limits. Whatever you leave unconstrained, the tools are free to ignore.
  • Floorplanning. Die size, utilisation, macro placement and the power grid become facts every later stage has to live with. Get them right before routing and timing have to work around them.
  • Placement. Watch congestion locally, not just utilisation globally. A comfortable average can hide an overloaded region, as Project 4 showed.
  • Clock tree synthesis. Check hold as soon as the real clock tree exists. Paths that were fine with an ideal clock can fail the moment real skew appears.
  • Routing. Trust the router’s clearance checks over a hand edit, every time. A wire you drew yourself can look right and still not know what else is nearby.
  • Timing closure. A pass at the typical corner proves nothing about the slow one, and a pass at the slow corner proves nothing about hold at the fast one. Signoff means every corner, with margin.
  • Physical verification. DRC, LVS and timing are different views of the same object. A problem introduced in one place often shows up in more than one of them, as the manual ECO did here.
  • Signoff. Never let the layout and the netlist drift apart. Every change, a buffer, a resize, a wire, has to go through the flow, or signoff is checking a fiction.

Practice Exercise

Of the eight habits above, which one is most likely to prevent a problem before it ever produces a bad report, rather than helping you diagnose it afterwards? Justify your choice.

Solution

Several have a case, but the first, stating constraints explicitly, has a strong claim, because it is the only one that acts before any later stage runs. With the fanout limit and design repair left at their defaults, this project’s timing problem would never have existed, so there would have been nothing to diagnose. Most of the other habits, checking congestion, checking hold after CTS, trusting the router, checking every corner, are about catching a problem that an earlier decision has already introduced. This one is about not introducing it.

A real flow needs both kinds of habit, prevention and detection. But if you had to keep only one, front-loaded, explicit constraints are a defensible choice for the one with the most leverage.

Every planted problem was found, traced to its cause from the tools’ own reports, and fixed at that cause rather than at the symptom. That closes Project 5, Module 10 and the course. We started with an RTL file and a promise that it would end as a signed-off GDSII. Five capstones later that promise has been kept five times, on five designs that each exposed a different class of physical design problem, and the habits you built along the way are what you take with you.

← Project 5, Part 2: Diagnosing Each Violation From the Reports Alone