Most designs will contain some dead code or unreachable code at some point in development, and in many cases this code will survive into production. Why is that? When complex designs evolve during development, RTL code changes as bugs are fixed, features are added, reusable blocks are integrated, or code is optimized to achieve power and performance objectives. Sometimes there is a build-up of technical debt for which there is insufficient time to clean up code due to product delivery timescale pressure.
For example, late in the cycle, some designers might decide they are too late in the process to make changes and decide to leave dead code; overall the code is functional, but it may end up containing a lot of dead code. Not exactly a clean design.
Alternatively, what happens when the designer is unsure whether to trust the tool to identify dead code? If the conclusion is that they don’t trust it to do so, they may leave the code in “just in case.” In practice, this is not very likely as most users follow a zero violations policy which says, “Fix a lint message, or waive it.” This practice helps get around the issue; however, it is important to be able to identify dead code and decide how to deal with it.
Static linting tools that leverage formal engines, such as the Synopsys VC SpyGlass™ Lint, are highly efficient at identifying these areas of concern. Designers then have a number of options:
- Update the RTL code to remove dead code. While this is the cleanest solution, it may require some effort to re-factor the code followed by functional verification. This approach provides a clean lint result and removes coverage holes from coverage analysis.
- Comment out dead code with informative comments for future reference. This approach may still require functional verification, but provides a clean lint result and removes coverage holes.
- Waive the dead code in the lint waiver file. The dead code is acknowledged but deemed to be safe and the RTL codebase remains unchanged. Coverage holes would persist.