Capacitor extraction issue

I'm writing a LVS script to check my layout and I want to see if someone can help with this issue.
I try to extract a capacitor in my layout. I can extract the capacitor successfully, but both terminals are short. I don't know why.
The following is the structure of the capacitor, my coding and gds file for reference.

# Enable hierarchical mode deep # Produce LVS report report_lvs # Drawing layers nwell = input(1, 0) active = input(2, 0) #pplus = input(3, 0) poly1 = input(3, 0) pplus = input(4, 0) nplus = input(5, 0) poly2 = input(14, 0) contact = input(6, 0) metal1 = input(7, 0) # includes labels via1 = input(93, 0) metal2 = input(86, 0) # includes labels cap_ID = input(132, 0) #cpip5v_ono device extraction area_cap = 1.65e-15 model_name = "CAP" Cap_P1 = cap_ID & poly1 Cap_P2 = cap_ID & poly2 #P1_contact = (cap_ID & poly1 - poly2) #mask out poly2 P1_contact = Cap_P1 - Cap_P2 Cap_P2.output(187, 0) P1_contact.output(188, 0) extract_devices(capacitor(model_name, area_cap), { "P1" => Cap_P1 , "P2" => Cap_P2, "tB" =>P1_contact, "tA" => Cap_P2 }) #Cap connect ===================== connect(Cap_P2, contact) connect(P1_contact, contact) ###metal connection connect(contact, metal1) connect(metal1, via1) connect(via1, metal2) # Netlist and compare # Netlist normalization netlist.simplify target_netlist("layout_simply.cir", write_spice, "Extracted by KLayout") # Hierarchy alignment (flatten out unmatched cells) align # Netlist vs. netlist compare

gds file:


  • It's seem that the contacts placed on the overlap area of the two plans of the capacitor will short the two terminals.

  • Could anyone can help to solve the above issue? Thanks!

  • edited October 2021

    Thanks for the analysis and the test case! Very good! :)

    This time (I think) it's not a bug :)

    Here is my working code:

    area_cap = 1.65e-15
    model_name = "CAP"
    Cap_P1 = cap_ID & poly1
    Cap_P2 = cap_ID & poly2
    # classify contacts into P1 and P2 contacts for Caps and others
    P1_contact = contact & (Cap_P1 - Cap_P2)
    P2_contact = contact & Cap_P2
    # not used here, but provides another class for use in other devices
    other_contacts = contact - Cap_P1 
    # extract caps
    extract_devices(capacitor(model_name, area_cap), { "P1" => Cap_P1 , "P2" => Cap_P2 })
    # connect the caps and the respective contacts
    connect(Cap_P2, P2_contact)
    connect(Cap_P1, P1_contact)
    # metal connections
    connect(P1_contact, metal1)
    connect(P2_contact, metal1)
    connect(other_contacts, metal1)
    connect(metal1,     via1)
    connect(via1,       metal2)

    And the explanation:

    The cap devices generate terminals over the full area of the plates ("tA" will receive a copy of "P1" and "tB" a copy of "P2"). So when they push the terminals on "P1_contact", the full plate - more precisely the overlap of P1 and P2 - will appear there and because it will participate in "connect(P1_contact, contact)", it will short the contacts from P2 (see the description here: In other words,

    The solution I propose is not the simplest one, but I'd like to advertise a general concept: The idea is to classify a physical layer (in this case contact) into discrete sets of shapes - in this case, contacts landing on cap P1, contacts landing on cap P2 and others. This scheme also applies for example when you classify poly into resistor (blocked) and gate (silicided).

    With these contact classes you connect to the respective bottom layers. On the other end you need to combine all classes by connecting them to metal1 each.

    "extract_devices" does not contain "tA" or "tB" here because by default, the terminals are attached to the inputs P1 and P2 which is sufficient here.

    Hope this helps.

    Kind regards,


  • Is the problem that, in a system where "contact" could
    stop on either P2, P1 or Active, that there is no logic
    that says -which-? That is, looks like contactP2,
    and contact
    P1 would both be valid as written, maybe
    there should be (contact & P2), (contact & P1 andnot P2),
    (contact & active andnot P1 andnot P2) formulations to
    address the possibility of "stacking" contactable layers?

  • Hi Jim,

    I saw in some design systems that the contacts are logically separated in different layers, but physically joined on the mask.

    If that is not the case, one needs to define the priority and the "stopping nature" of certain layers: in this case P2 stops the contact from etching through to P1. So you can build a kind of priority. When you sort the stop layers from top to bottom (S1, S2, ... which S1 being the topmost), the logical operations are:

    S1_contacts = contact & S1
    contacts -= S1
    S2_contacts = contact & S2
    contacts -= S2

    But you do not always need that. If you have a stop layer which is logically partitioned anyway (e.g. diffusion into p-MOS source/drain, n-MOS source/drain, gate, n-Well tie down, etc.), then you don't need to separate the contacts and just connect them:

    # partitioning of the contact lower-end area into different, non-overlapping estates
    pmos_source_drain = nwell & pplus - gate
    pmos_gate = nwell & pplus & gate
    nmos_source_drain = (nplus - nwell) - gate
    ... etc.
    connect(pmos_source_drain, contact)
    connect(nmos_source_drain, contact)
    connact(pmos_gate, contact)
    ... etc.

    BTW: in KLayout there is a more efficient "partitioning operation" which selects the inside and outside part in a single operation:

    # what: the layer to partition
    # mask: selects parts
    (inside, outside) = what.andnot(mask)
    # this is equivalent to
    inside = what & mask
    outside = what - mask


  • Hi Matthias,

    Thanks for your support. The capacitor can be extracted correctly. The short circuit is due to connection between the poly1 and contact in other devices!

  • Thanks ... but I could reproduce the problem in the cap cell inside your sample layout. So no external connection. I still think the analysis is correct.

    But if you found a short the LVS did it's job :)


Sign In or Register to comment.