(1/4) CTS recovery case study: when clean timing reports hid a failing backend

Over the next few posts, I’m going to walk through a real CTS recovery from a 28nm tapeout programme we worked on recently. This was an actual backend convergence failure that came uncomfortably close to derailing tapeout.

What made this case difficult was that the timing reports never looked catastrophic. Underneath, though, the backend was quietly destabilising.

The dangerous part

About six weeks before tapeout, we were brought in to help with a struggling 28nm block. The internal team had already rerun clock tree synthesis several times trying to recover setup timing, but each rerun seemed to amplify instability somewhere else in the backend.

The reports themselves still looked fine:

  • Setup WNS: +0.045 ns
  • Hold WNS: +0.032 ns
  • Skew: 18 ps
  • Status: acceptable

That was the dangerous part. Nothing in the numbers pointed to a problem, yet physically the block looked unhealthy.

The moment that triggered the investigation

I remember one of my engineers opening the latest implementation database late one evening and saying, “Something about this density map looks wrong.” One look changed the direction of the entire programme.

Near two SRAM boundaries, CTS had inserted a large concentration of buffers, chasing skew targets that no longer made physical sense. One routing corridor had become so congested that signal nets were detouring halfway around the block just to get past the clock congestion.

Symptoms kept getting worse

  • Hold violations exploded after every optimisation pass
  • ECO routes kept disturbing previously stable regions
  • Runtime crossed 70+ hours per iteration
  • Dynamic power jumped unexpectedly after CTS
  • Confidence in the implementation flow started collapsing internally

The backend was destabilising long before the reports clearly showed it, which is what makes clock-related convergence failures so dangerous.

What we discovered

We spent the next two days dissecting the block and eventually realised the issue wasn’t routing. It was the clock strategy itself.

What surprised us was that this wasn’t down to one catastrophic mistake. Several smaller CTS decisions were quietly compounding, amplifying instability across the backend.

The first root cause only became obvious once we stopped treating CTS as a timing optimisation problem and started treating it as a physical stability problem. That shift changed how we approached the block entirely, and, as it turned out, the first issue we found wasn’t even the most dangerous one.

Part two next….

This entry was posted in Blogs. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *