Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LVS unexpectedly failing #1021

Closed
FatsieFS opened this issue Mar 9, 2022 · 4 comments · Fixed by #1026
Closed

LVS unexpectedly failing #1021

FatsieFS opened this issue Mar 9, 2022 · 4 comments · Fixed by #1026
Assignees
Milestone

Comments

@FatsieFS
Copy link

FatsieFS commented Mar 9, 2022

Here is a test case of an SRAM array: sramlvs.tar.gz
There is a run script to run the lvs on a 2X2 and a 2X4 array; in the 2X4 array the 2X2 array is a subcell.
For the 2X2 array the lvs is OK but for the 2X4 array it fails and I don't see why.
I am using klayout version 0.27.8

@FatsieFS
Copy link
Author

FatsieFS commented Mar 9, 2022

Also tried now without the flat line but it gives the same result: 2X2 OK, 2X4 fails.

@klayoutmatthias
Copy link
Collaborator

I had a brief look an reproduce the problem.

The LVS script has a couple of problems that prevent true hierarchical mode. I was able to modify it so I can achieve match in deep mode (I will tell you how), but the flat problem remains (BTW: "flat" is the default, so adding it does not make a difference).

I need to debug the issue.

Matthias

@klayoutmatthias
Copy link
Collaborator

I have fixed the problem: "consider net names" wasn't fully effective in that case and this created a conflict. This is going to be released in version 0.27.9.

If you use "consider_net_names(false)" the LVS matches. However I'd not recommend that as a workaround as then LVS assignes the wrong bitline polarities due to the symmetry of the latter. Using labels is much better in fact.

Another workaround is to use deep mode and hierarchical matching. As mentioned, several issues prevent the current LVS from running in deep mode and some changes are required:

  1. The substrate does not need to be a solid plate. This will only force flat evaluation. There is "connect_global" for the purpose of generating "overall" nets. Still, "substrate__Sky130" is required as a receiver for the device terminals. It can be empty however:
substrate__Sky130 = polygon_layer
  1. Using the substrate in booleans is not required and forces flat evaluation, so these booleans can be rewritten:

From:

gate__mosgate = (difftap&poly__conn&(extent.sized(0.34)-hvi))
gate__mosfet__nfet_01v8 = (gate__mosgate&substrate__Sky130&nsdm)
gate__mosfet__nfet_01v8_lvt = (gate__mosgate&substrate__Sky130&nsdm&lvtn)
gate__mosfet__nfet_g5v0d10v5 = (gate__hvmosgate&substrate__Sky130&nsdm)

To:

gate__mosgate = (difftap&poly__conn-hvi)
gate__mosfet__nfet_01v8 = (gate__mosgate&nsdm)
gate__mosfet__nfet_01v8_lvt = (gate__mosgate&nsdm&lvtn)
gate__mosfet__nfet_g5v0d10v5 = (gate__hvmosgate&nsdm)
  1. The following connect statements are converted into global ones:
connect(substrate__Sky130, extent.sized(0.34))

into:

connect_global(substrate__Sky130, "vss")

and

connect(difftap__conn__psdm, substrate__Sky130)

into:

connect_global(difftap__conn__psdm, "vss")
  1. The SP6TArray_2X1 cell has two vdd pins in layout, but one in schematic, so this implicit connect is required to fix that:
connect_implicit("SP6TArray_2X1", "vdd")

(without a cell, "connect_implicit" is only effective at top level)

  1. The SRAM cell's drains overlap across cell instances, so we need to introduce that cheat to tell KLayout not to propagate the devices up in the hierarchy (see https://www.klayout.de/doc-qt5/about/drc_ref_global.html#k_17 about cheats):
cheat("SP6TCell") do
    extract_devices(mos4("sky130_fd_pr__nfet_01v8__model"), {
        "SD" => difftap__conn, "G" => gate__mosfet__nfet_01v8, "tG" => poly__conn, "W" => substrate__Sky130,
    })
end

and

cheat("SP6TCell") do
    extract_devices(mos4("sky130_fd_pr__pfet_01v8__model"), {
        "SD" => difftap__conn, "G" => gate__mosfet__pfet_01v8, "tG" => poly__conn, "W" => nwm,
    })
end
  1. The difftap_pin should be connected to difftap__conn. Otherwise difftap will form undesired connections:
connect(difftap__conn, difftap_pin)
  1. difftap__conn__nsdm and difftap__conn__psdm should include the n well to separate source/drain from tap areas:
difftap__conn__nsdm = (difftap__conn&nsdm&nwm)
difftap__conn__psdm = (difftap__conn&psdm-nwm)

This is the full version of LVS which works for me in hierarchical mode:

source("SP6TArray_2X4.gds")
schematic("SP6TArray_2X4.spi")
report_lvs("SP6TArray_2X4.rep")

deep

# Define layers
nwm = input(64, 20)
nsdm = input(93, 44)
psdm = input(94, 20)
hvi = input(75, 20)
difftap_pin = input(65, 16)
difftap_block = input(100, 10)
difftap = input(65, 20)
poly_pin = input(66, 16)
poly_block = input(100, 20)
poly = input(66, 20)
li_pin = input(67, 16)
li_block = input(100, 40)
li = input(67, 20)
m1_pin = input(68, 16)
m1_block = input(100, 60)
m1 = input(68, 20)
m2_pin = input(69, 16)
m2_block = input(100, 80)
m2 = input(69, 20)
m3_pin = input(70, 16)
m3_block = input(100, 100)
m3 = input(70, 20)
m4_pin = input(71, 16)
m4_block = input(100, 120)
m4 = input(71, 20)
m5_pin = input(72, 16)
m5_block = input(100, 140)
m5 = input(72, 20)
licon_block = input(100, 30)
mcon_block = input(100, 50)
via_block = input(100, 70)
via2_block = input(100, 90)
via3_block = input(100, 110)
via4_block = input(100, 130)
licon = input(66, 44)
mcon = input(67, 44)
via = input(68, 44)
via2 = input(69, 44)
via3 = input(70, 44)
via4 = input(71, 44)
hvtp = input(78, 44)
lvtn = input(125, 44)
pad = input(76, 20)
areaid_diode = input(81, 23)
polyres = input(66, 13)
diffres = input(65, 13)
prBoundary = input(235, 4)
substrate__Sky130 = polygon_layer

difftap__conn = (difftap-(poly+diffres))
difftap__conn__nsdm = (difftap__conn&nsdm&nwm)
difftap__conn__psdm = (difftap__conn&psdm-nwm)
poly__conn = (poly-polyres)
gate__hvmosgate = (difftap&poly__conn&hvi)
gate__mosgate = (difftap&poly__conn-hvi)
gate__mosfet__nfet_01v8 = (gate__mosgate&nsdm)
gate__mosfet__nfet_01v8_lvt = (gate__mosgate&nsdm&lvtn)
gate__mosfet__nfet_g5v0d10v5 = (gate__hvmosgate&nsdm)
gate__mosfet__pfet_01v8 = (gate__mosgate&nwm&psdm)
gate__mosfet__pfet_01v8_hvt = (gate__mosgate&nwm&psdm&hvtp)
gate__mosfet__pfet_01v8_lvt = (gate__mosgate&nwm&psdm&lvtn)
gate__mosfet__pfet_g5v0d10v5 = (gate__hvmosgate&nwm&psdm)
resistor__active_res = (difftap&diffres)
resistor__poly_res = (poly&polyres)
diode__ndiode = (difftap&areaid_diode&nsdm)
diode__pdiode = (difftap&areaid_diode&psdm)

# Connectivity
connect_global(substrate__Sky130, "vss")
# connect(difftap,difftap.pin)
connect(difftap__conn, difftap_pin)
# connect(difftap__conn,difftap__conn:nsdm)
connect(difftap__conn, difftap__conn__nsdm)
# connect(difftap__conn:nsdm,nwm)
connect(difftap__conn__nsdm, nwm)
# connect(difftap__conn,difftap__conn:psdm)
connect(difftap__conn, difftap__conn__psdm)
# connect(difftap__conn:psdm,substrate:Sky130)
connect_global(difftap__conn__psdm, "vss")
# connect(poly,poly.pin)
connect(poly, poly_pin)
# connect(li,li.pin)
connect(li, li_pin)
# connect(m1,m1.pin)
connect(m1, m1_pin)
# connect(m2,m2.pin)
connect(m2, m2_pin)
# connect(m3,m3.pin)
connect(m3, m3_pin)
# connect(m4,m4.pin)
connect(m4, m4_pin)
# connect(m5,m5.pin)
connect(m5, m5_pin)
# connect((difftap__conn,poly__conn),licon)
connect(difftap__conn, licon)
connect(poly__conn, licon)
# connect(licon,li)
connect(licon, li)
# connect(li,mcon)
connect(li, mcon)
# connect(mcon,m1)
connect(mcon, m1)
# connect(m1,via)
connect(m1, via)
# connect(via,m2)
connect(via, m2)
# connect(m2,via2)
connect(m2, via2)
# connect(via2,m3)
connect(via2, m3)
# connect(m3,via3)
connect(m3, via3)
# connect(via3,m4)
connect(via3, m4)
# connect(m4,via4)
connect(m4, via4)
# connect(via4,m5)
connect(via4, m5)

connect_implicit("vss*")
connect_implicit("vcc*")
connect_implicit("vdd*")
connect_implicit("SP6TArray_2X1", "vdd")

# Resistors
# active_res
extract_devices(resistor("active_res", 200.0), {
    "R" => resistor__active_res, "C" => difftap__conn,
})
same_device_classes("active_res", "RES")
# poly_res
extract_devices(resistor("poly_res", 300.0), {
    "R" => resistor__poly_res, "C" => poly__conn,
})
same_device_classes("poly_res", "RES")

# Diodes
# ndiode
extract_devices(diode("sky130_fd_pr__diode_pw2nd_05v5"), {
    "P" => substrate__Sky130, "N" => diode__ndiode, "tC" => difftap__conn
})
# pdiode
extract_devices(diode("sky130_fd_pr__diode_pd2nw_05v5"), {
    "P" => diode__pdiode, "N" => nwm, "tA" => difftap__conn
})

# Transistors
# nfet_01v8
cheat("SP6TCell") do
    extract_devices(mos4("sky130_fd_pr__nfet_01v8__model"), {
        "SD" => difftap__conn, "G" => gate__mosfet__nfet_01v8, "tG" => poly__conn, "W" => substrate__Sky130,
    })
end

# nfet_01v8_lvt
extract_devices(mos4("sky130_fd_pr__nfet_01v8_lvt__model"), {
    "SD" => difftap__conn, "G" => gate__mosfet__nfet_01v8_lvt, "tG" => poly__conn, "W" => substrate__Sky130,
})
# nfet_g5v0d10v5
extract_devices(mos4("sky130_fd_pr__nfet_g5v0d10v5__model"), {
    "SD" => difftap__conn, "G" => gate__mosfet__nfet_g5v0d10v5, "tG" => poly__conn, "W" => substrate__Sky130,
})
# pfet_01v8
cheat("SP6TCell") do
    extract_devices(mos4("sky130_fd_pr__pfet_01v8__model"), {
        "SD" => difftap__conn, "G" => gate__mosfet__pfet_01v8, "tG" => poly__conn, "W" => nwm,
    })
end

# pfet_01v8_hvt
extract_devices(mos4("sky130_fd_pr__pfet_01v8_hvt__model"), {
    "SD" => difftap__conn, "G" => gate__mosfet__pfet_01v8_hvt, "tG" => poly__conn, "W" => nwm,
})
# pfet_01v8_lvt
extract_devices(mos4("sky130_fd_pr__pfet_01v8_lvt__model"), {
    "SD" => difftap__conn, "G" => gate__mosfet__pfet_01v8_lvt, "tG" => poly__conn, "W" => nwm,
})
# pfet_g5v0d10v5
extract_devices(mos4("sky130_fd_pr__pfet_g5v0d10v5__model"), {
    "SD" => difftap__conn, "G" => gate__mosfet__pfet_g5v0d10v5, "tG" => poly__conn, "W" => nwm,
})

netlist

align
ok = compare
if ok then
    print("LVS OK\n")
else
    abort "LVS Failed!"
end

Matthias

@klayoutmatthias klayoutmatthias self-assigned this Mar 12, 2022
@klayoutmatthias klayoutmatthias added this to the 0.27.9 milestone Mar 12, 2022
@klayoutmatthias klayoutmatthias linked a pull request Mar 16, 2022 that will close this issue
@klayoutmatthias
Copy link
Collaborator

Solution released with 0.27.9

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

Successfully merging a pull request may close this issue.

2 participants