Skip to content

Rework DRC structure#10

Open
Scafir wants to merge 74 commits intofossi-foundation:mainfrom
Scafir:drc_structure
Open

Rework DRC structure#10
Scafir wants to merge 74 commits intofossi-foundation:mainfrom
Scafir:drc_structure

Conversation

@Scafir
Copy link
Copy Markdown
Contributor

@Scafir Scafir commented Mar 21, 2026

Why rework the DRC?

Currently, the DRC stack is hard to work with or not ideal for various reasons:

  • Work is shared (but not always) between run_drc.py, and ruby API
  • All DRC rules execute in the same context, back to back
    • Risk of a rule modifying a base layer for subsequent rules
    • Selecting which rule to run when is not straigthforward, as they are injected by a preprocessor
    • The table name from the .drc scripts are not properly supported
  • The way klayout implements drc, the only other solution to run the rules to the preprocessor is by using eval, making multi-threaded approach in the ruby APU cumbersome
  • Only way to implement parallel processing / rule selection is by going through an external python script
    • rule section that way can only be done at a file level
  • Antenna and density checks are not implemented in the same manner as the other rules

What does this PR do?

This work extends on the gf180mcu.drc introduction. Extraction and general layer definition are made in their own functions/files. A context object is made to hold runtime options (like FEOL, ...), as well as a hash containing all the generic layers.
A registry is defined at a global level (due to klayout implementation) to hold all rule files available. Rule filtering is implemented at that level (and can be easily extended).

Rule files are lightly edited to be loaded. This means that they execute a function to register themselves with the registry.
In order to avoid manual work, or cumbersome logic, if a symbol is not found during the execution of the file's rule, the generic layer hash is consulted, and then the drc function exposed by klayout. This is implemented through the DeckEnv object.
While this is not the most elegant approach, it allows a smooth transition without needing heavy modifications on every single rule file.

Tests and CI were updated to run the new deck.

Extras

  • rule_decks now only contain rules files
  • antaenna and density rules are implemented as any other rule
  • Deprecated options (like gold, wedge, ...) were removed from gf180mcu.drc

Outlook

In my opinion, this work not only improves the current maintainability of the PDK, but also paves the way for implementing functionality a lot more easily. More advanced DRC runners could be made, such as a simple parallel forking one, or a dependency-based one.
It also simplifies the current approach of needing to deal with run_drc.py, which is not ideal from a klayout point of view (e.g: some missing python packages prevent running the DRC check with klayout flatpak) and complexifies the stack for minimal improvements.

What is left to be done?

  • Review
  • Benchmark

@Scafir
Copy link
Copy Markdown
Contributor Author

Scafir commented Mar 26, 2026

Discussed with @mole99 . More precise feedback will come later, but there is need to:

  • Look at what is IHP approach/how they might be able to use this
  • Ensure feature parity with run_drc.py before deprecating it -> we cannot presently merge this PR.

@mole99
Copy link
Copy Markdown
Contributor

mole99 commented Mar 30, 2026

@Scafir Hi Clyde,

Thanks again for the PR. I gave it a high-level overview and tried to understand all the trade-offs between load vs eval vs require, block.call vs instance_exec etc.
I think I have pretty good understanding of the whole flow now: load is used to first register the rule decks, while instance_exec is used to execute their block under a different context to prevent polluting the main context.

Yes, it does require some boilerplate, but creating a new rule deck does not seem to be much work at all.
So, to me, this looks like the way to go!

Two more things from our last call:

  • Please add a priority key to register(). This way we can run important and long-running rule decks first.
  • By always running each rule deck in their own process we can prevent rule decks from interacting with each other through the ctx variable.

Once multiprocessing is implemented, I'll try this out with LibreLane to see the speed-up of wafer.space designs :)

@Scafir Scafir force-pushed the drc_structure branch 6 times, most recently from a8b7b0c to aeaad3b Compare April 8, 2026 16:19
Copy link
Copy Markdown
Contributor

@mole99 mole99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! I completed a full run on my gf180mcu FABulous FPGA (with KLayout patch):

DRC Total Run time 461.170021382 seconds

🥳

I found one minor issue, and now that run_drc.py is non-functional, we should remove it.

Comment thread klayout/drc/gf180mcu.drc Outdated
current = RBA::Application.instance.version.split('.').map(&:to_i)

if (current <=> required_parallel).negative? && (opts.workers > 1)
warn('Running parallel workers with klayout smaller than 0.30.8 is likely to fail due ' /
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The / should probably be \?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, run_drc.py removed, documentation updated and end report implemented.
The script will also now exit with non-zero return code if the layout is not DRC clean

@mole99
Copy link
Copy Markdown
Contributor

mole99 commented May 1, 2026

After the changes have been made and this PR has been merged, there's still some work to do.

Writing this down so I don't forget about it. I need to port the changes over from wafer.space:

  • custom antenna checks
  • rule deck fixes (e.g. PP.5di sealring exception)
  • metal slot rules
  • metal slot generation
  • filler generation
  • anything missing?

One more thing that would be great as part of the DRC is a short summary at the end: I think you can query the number of DRC items of the RDB object? It would be great to print the total number of DRC violations as a summary, and maybe even the number of violations per category.
But this is something that we can add later :)

Scafir added 2 commits May 6, 2026 14:47
Klayout will no return nonzero return code if the check is not DRC clean
This improves the rules on:
* Printed messages to report are now correct
* Rules are not copy pasted between layers, but created with a loop
@Scafir
Copy link
Copy Markdown
Contributor Author

Scafir commented May 6, 2026

The things I want to still add in the release is a clean isosub implementation. Some issues were found with the sscs chipathon, and I'm in talks with KLayout/klayout#2345

One thing to add to a later release is proper resistor extraction in lvs. Currently the resistors are extracted, but the actual resistance is not.

The pr repository will also need to be updated to implement the drc changes exposed in this PR

@mole99
Copy link
Copy Markdown
Contributor

mole99 commented May 6, 2026

Interesting read! And great that there seems to be a proper solution to the problem in the future.

Good point about resistance extraction. Could you open an issue so that we don't forget about it?

I think we should go ahead and merge this PR as soon as _pr has been updated. Then I can start integrating the new DRC method into LibreLane.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants