KLayout / klayout

KLayout Main Sources
http://www.klayout.org
GNU General Public License v3.0
809 stars 206 forks source link

Flat LVS OK and deep failing #1813

Open FatsieFS opened 3 months ago

FatsieFS commented 3 months ago

Need some help to change a LVS deck to be compatible with hierarchical LVS checking. In testcase_deep.zip you can find the testcase I made for this case. When I run lvs_Sky130 in the directory I get the following:

~/eda/Chips4Makers/test/testcase_deep$ ./lvs_Sky130 
Running flat LVS
Flat LVS OK
Running deep LVS
Deep LVS Failed!

I zipped the directory with the output files of the runs included. This is a LVS deck automatically generated. Similar LVS decks are generated for all PDKs I support in project Arrakeen (see FSiC2024) and thus complementary to the upstream PDK ones.

klayoutmatthias commented 3 months ago

Hi Staf,

that is a classic one.

The following happens:

The substrate is created as a large layer through "extent":

substrate__Sky130 = (extent.sized(0.34)-nwm)

later, the body connections for the NMOS devices are made to this layer through the "W" target (which is essentially a "connect" of the device pin shapes to the substrate__Sky130 layer):

extract_devices(mos4("sky130_fd_pr__nfet_01v8__model"), {
    "SD" => difftap__conn, "G" => gate__mosfet__nfet_01v8, "tG" => poly__conn, "W" => substrate__Sky130,
})

Now, when you extract in deep mode, the substrate layer is flat, because

  1. "extent" is a flat layer
  2. the golden rule of "first layer determines hierarchy" in "substrate - nwell"

So eventually you make a connection of devices inside the hierarchy (NMOS) to a flat layer upwards in the hierarchy.

This creates pins as one can see here:

image

With these pins, the buf_x1 subcircuits do not match the schematic which does not have these pins.

About the solutions

The first solution is to use a local "extent" for every cell - this creates a local boundary in every cell. However, the "sized" operation will spoil that again, because it merges. I do not really see the need for the size as it only participates in connect statements and everything relevant is included in "extent" already - even without "sized":

substrate__Sky130 = (extent("*")-nwm)

A better solution IMHO however is to use a global net. This reflects the physical nature of a (non-SOI) substrate which is "below everything" - i.e. also connecting islands inside nwell rings with the outside. To implement this, you need to substitute "substrate__Sky130" by a global net. Here is my patch for deep mode LVS:

  1. substrate__Sky130 becomes an empty layer

    63c63
    < substrate__Sky130 = polygons # empty layer, we will do a connect_global later
    ---
    > substrate__Sky130 = (extent.sized(0.34)-nwm)
  2. As difftap__conn__psdm also contains the NMOS source/drains we need to extract the taps:

68d67
< difftap__conn__psub = difftap__conn__psdm-nwm
  1. We connect substrate__Sky130 to a new global "PSUB" net:
98c97
< connect_global(substrate__Sky130, "PSUB")
---
> connect(substrate__Sky130, extent.sized(0.34))
  1. We replace difftap__conn__psdm by difftap__conn__psub:
108c107
< connect(difftap__conn, difftap__conn__psub)
---
> connect(difftap__conn, difftap__conn__psdm)
  1. Finally difftap__conn__psub is also connected to the global "PSUB" net:
110c109
< connect_global(difftap__conn__psub, "PSUB")
---
> connect(difftap__conn__psdm, substrate__Sky130)

With this patch, the LVS also passes in deep mode.

Matthias

FatsieFS commented 3 months ago

Thanks @klayoutmatthias for prompt and good support. I assumed the name used in global net needed to be a net used in the layout indicated with labels and I didn't want restrict my deck to force use of specific name for the ground net. I'll see if more questions pop up when I implement this, otherwise I'll close this issue when I've updated my LVS deck generation script.

klayoutmatthias commented 3 months ago

Hi Staf,

Of course, please feel free to raise questions :)

Actually, the name of the global net is just an identifier. You can basically create multiple global nets, and the identifier tells which one to use. You could even use "VSS", but I'd not advise to do so. KLayout does not consider nets with the same name connected by default, so you may get two nets with the same name. "PSUB" or anything like that is a better choice for the global net.

As you connect "VSS" physically to the "PSUB" substrate (ties included, very good :) ), the net names will be joined and the result is a new name like "VSS,PSUB". KLayout LVS (mostly) does not care about net names, so it will happily match this net to "VSS" from the schematic.

Best regards,

Matthias