Hello, am having some trouble with LVS. In short...
# analog-design
p
Hello, am having some trouble with LVS. In short, the L side has less nets than the S--I'm assuming a short somewhere. But where? I'm drowning in information in the lvs report, how do I get netgen to just spit out everything connected in nets for which it can't find a correspondence on the other side?
t
Can you paste the report ? It should show for the non matched nets the devices it connects to.
p
Here it is... must say there's still a lot I don't get in this but I can't figure out where the issue actually lies. It has crazy deltas, like
VPWR = 114                               |  VPWR = 4
but then tells me the difference in nets is like 5.
Yeah, it ends up saying:
Circuit 1 contains 58 devices, Circuit 2 contains 58 devices.
Circuit 1 contains 60 nets,    Circuit 2 contains 65 nets. *** MISMATCH ***
in the terminal.
Oddly, what comes out in the term doesn't seem to be in the report. So attached here.
t
Gimme a sec to look that over.
p
All the sub cells used within pass LVS. One of them is verilog (passes too), only the top level fails... have been stumped.
t
I think the power connections are not correct.
Both VPWR and VGND seem "split".
Possibly between a standard cell layout part and an analog part.
p
Yes, exactly that. But they're connected. Does it matter? Also, the side with the least nets is on the "left" (the first, layout, side)... does that mean that I shouldn't be connecting these domains or something?
t
Maybe the issue is in the schematic part ...
p
(also, how can you tell they are split? I mean they have the same names and are electrically connected.
Mk, I am using std cells in there. Alone, that block passes LVS.
t
In line 864 you can see that it finds a net
VPWR
with a bunch of stuff on one side and much less on the other.
And then all the stuff it didn't find to be connected it put on net
dummy_22
I'd need to see the actual layout and the netlist it's being compared to to be able to say more ...
t
@Pat Deegan: The output is saying that the circuit
ringtest
contains a handful of subcells (
ring
,
driver
, and
mux4onehot_b
) which have power and ground properly connected, and a bunch of standard cells, which seem to all have power and ground connected together (on unnamed net that have been named
dummy_*
), but apparently disconnected from the power and ground for the subcells and pins. Side note: If you're running netgen locally and can update, I suggest using the most recent version (1.5.282) because I found a bug a few days ago that causes netgen, under some circumstances, to dump more output than necessary, making the output harder to read. There is a
debug on
command that you can add to the script, but that outputs a huge amount of information, so not recommended unless you just cannot see the error in the output (and it's likely that previous times I had to resort to
debug on
were probably caused by the bug that I just mentioned and just fixed). That is probably not relevant in this case.
t
@Pat Deegan Did you find/fix the issue ?
m
@Pat Deegan unfortunately, the version of netgen that you are using
1.5.270
does not work when you have spice that calls verilog modules. The terminal log is showing
Copy code
Subcircuit pins:
Circuit 1: _PLACEHOLDER_                   |Circuit 2: simplecounter
-------------------------------------------|-------------------------------------------
(no matching pin)                          |1
(no matching pin)                          |2
(no matching pin)                          |3
(no matching pin)                          |4
(no matching pin)                          |5
(no matching pin)                          |6
(no matching pin)                          |7
(no matching pin)                          |8
(no matching pin)                          |9
(no matching pin)                          |10
(no matching pin)                          |11
(no matching pin)                          |12
(no matching pin)                          |13
(no matching pin)                          |14
VGND                                       |(no matching pin)
VPWR                                       |(no matching pin)
clk                                        |(no matching pin)
enable                                     |(no matching pin)
counter[9]                                 |(no matching pin)
counter[8]                                 |(no matching pin)
counter[7]                                 |(no matching pin)
counter[6]                                 |(no matching pin)
counter[5]                                 |(no matching pin)
counter[4]                                 |(no matching pin)
counter[3]                                 |(no matching pin)
counter[2]                                 |(no matching pin)
counter[1]                                 |(no matching pin)
counter[0]                                 |(no matching pin)
---------------------------------------------------------------------------------------
Treating empty subcircuits as black-box cells
You’ll probably have better luck with the latest version
1.5.282
or the last known version that worked with spice calling verilog modules
1.5.269
. When you do call verilog modules from spice, there are a couple things that need to be considered. 1. Since spice calls are by position, the verilog symbols should be created with the ports in the same order as the the verilog module. This may be a manual process. I find it easiest to open the
*.sym
file in an editor and rearrange the physical order of the pins there (if there is no schematic). I also add a
type=primitive
property to the symbol to prevent the creation of an empty subckt. If you do have an empty subcircuit, the symbol pins will be output in the order of the pins in the schematic (with a recent version of xschem). 2. Spice is case insensitive, verilog is case sensitive. The default for netgen is to follow what ever is read first. You might consider using the LVS system in the
caravel_user_project/Makefile
. For any
lvs/<cellname>/lvs_config.json
file, you can simply run
make lvs-cellname
. All the extraction and LVS parameters are in the
lvs_config.json
file and you can include the lower level config files in the upper level hierarchy. The
lvs_config.json
options are explained here.
👍 1
p
Hello, thanks for your input... sorry for the delay, was away at a con. @tnt still no success but some progress. @Tim Edwards and @Mitch Bailey: I thought netgen was happy with the verilog, since it was passing my simplecounter.v checks when run standalone, but it does look like there was some issue when combining everything together. I've updated to latest netgen, have changed all analog circuits to use VDD/VSS and left anything with std cells as VPWR/VGND to attempt to disambiguate, and the output still isn't an LVS pass but is looking more clear. I wind up with a failure around
---------------------------------------------------------------------------------------
Instance: simplecounter:x4                 |Instance: simplecounter:4
VPWR = 5                                 |  2 = 5
clk = 3                                  |  3 = 3
enable = 1                               |  4 = 1
counter[0] = 1                           |  14 = 1
counter[1] = 1                           |  13 = 1
counter[2] = 1                           |  12 = 2
counter[3] = 2                           |  11 = 1
counter[4] = 1                           |  10 = 1
counter[5] = 1                           |  9 = 1
counter[6] = 1                           |  8 = 2
counter[7] = 2                           |  7 = 1
counter[8] = 1                           |  6 = 1
counter[9] = 1                           |  5 = 1
VGND = 4                                 |  1 = 4
---------------------------------------------------------------------------------------
Netlists do not match.
Port matching may fail to disambiguate symmetries.
which, but for the ordering, looks like a match to me (full report attached here). I've played with the ordering of ports a good deal to no avail, but will give Mitch's lvs_config system a try. If you see anything obvious in the report, please let me know.
t
@Pat Deegan Could you post also the verilog netlist (and/or schematic spic) you're comparing against and the extracted spice ?
p
Yeah, am going to push everything to github... will ping.
t
This looks like a failure to read in all the verilog components when setting up the input to netgen. The
simplecounter
module is being treated as a black box, so netgen has not seen the module definition.
p
@Tim Edwards that's odd... I have a
readnet verilog ../verilog/gl/simplecounter.v $source
line, which barfs if I change the path to something invalid, and outputs
Verilog placeholder module simplecounter replaced by module definition
when running (log attached).
t
@Pat Deegan: Try reading
simplecounter.v
before you read the top level verilog. And keep the existing files because I may need to use them to debug.
p
ACK. will be pushing everything in 5 mins.
ok, I've just pushed everything, including a bunch of derivatives/extracted files. Have been running LVS with some modified versions of Matt's scripts, doing
cd mag; PROJECT_NAME=ringtest make clean lvs
and it's all up (and a bit messy) at https://github.com/psychogenic/tt09-analogmux
changing PROJECT_NAME to any of the components (inverter, driver, passgatesCtrlManual, mux4onehot_b, simplecounter) has LVS passing. Only the top level dies unhappy.
m
@Pat Deegan Can you check the bus order for the counter signal? Looks like it might be reversed from verilog to spice.
Copy code
counter[0] = 1                           |  14 = 1                                   
  counter[1] = 1                           |  13 = 1                                   
  counter[2] = 1                           |  12 = 2                                   
  counter[3] = 2                           |  11 = 1                                   
  counter[4] = 1                           |  10 = 1                                   
  counter[5] = 1                           |  9 = 1                                    
  counter[6] = 1                           |  8 = 2                                    
  counter[7] = 2                           |  7 = 1                                    
  counter[8] = 1                           |  6 = 1                                    
  counter[9] = 1                           |  5 = 1
So the verilog has descending bus indices
Copy code
module simplecounter (VGND,
    VPWR,
    clk,
    enable,
    counter);
 inout VGND;
 inout VPWR;
 input clk;
 input enable;
 output [9:0] counter;
While the spice has
Copy code
x4 VSS VDD drv_out enable_counter net2 net3 net4 counter3 net5 net6 net7 counter7 net8 net9 simplecounter
which looks like the ports are in ascending order. From the
xschem/simplecounter.sym
file
Copy code
B 5 17.5 -32.5 22.5 -27.5 {name=VGND dir=in}
B 5 17.5 -62.5 22.5 -57.5 {name=VPWR dir=in}
B 5 17.5 -202.5 22.5 -197.5 {name=clk dir=in}
B 5 17.5 -182.5 22.5 -177.5 {name=enable dir=in}
B 5 177.5 -202.5 182.5 -197.5 {name=counter[0] dir=out}
B 5 177.5 -182.5 182.5 -177.5 {name=counter[1] dir=out}
B 5 177.5 -162.5 182.5 -157.5 {name=counter[2] dir=out}
B 5 177.5 -142.5 182.5 -137.5 {name=counter[3] dir=out}
B 5 177.5 -122.5 182.5 -117.5 {name=counter[4] dir=out}
B 5 177.5 -102.5 182.5 -97.5 {name=counter[5] dir=out}
B 5 177.5 -82.5 182.5 -77.5 {name=counter[6] dir=out}
B 5 177.5 -62.5 182.5 -57.5 {name=counter[7] dir=out}
B 5 177.5 -42.5 182.5 -37.5 {name=counter[8] dir=out}
B 5 177.5 -22.5 182.5 -17.5 {name=counter[9] dir=out}
You should be ok with just changing the order of the lines in this file (not just the indices!).
Copy code
B 5 17.5 -32.5 22.5 -27.5 {name=VGND dir=in}
B 5 17.5 -62.5 22.5 -57.5 {name=VPWR dir=in}
B 5 17.5 -202.5 22.5 -197.5 {name=clk dir=in}
B 5 17.5 -182.5 22.5 -177.5 {name=enable dir=in}
B 5 177.5 -22.5 182.5 -17.5 {name=counter[9] dir=out}
B 5 177.5 -42.5 182.5 -37.5 {name=counter[8] dir=out}
B 5 177.5 -62.5 182.5 -57.5 {name=counter[7] dir=out}
B 5 177.5 -82.5 182.5 -77.5 {name=counter[6] dir=out}
B 5 177.5 -102.5 182.5 -97.5 {name=counter[5] dir=out}
B 5 177.5 -122.5 182.5 -117.5 {name=counter[4] dir=out}
B 5 177.5 -142.5 182.5 -137.5 {name=counter[3] dir=out}
B 5 177.5 -162.5 182.5 -157.5 {name=counter[2] dir=out}
B 5 177.5 -182.5 182.5 -177.5 {name=counter[1] dir=out}
B 5 177.5 -202.5 182.5 -197.5 {name=counter[0] dir=out}
t
Yeah, I found that too but that doesn't seem to be the only issue.
p
@Mitch Bailey I played with it a ton, manual style in the spice, and never got good results. Weirdly, when I run extraction/lvs on just the simplecounter, the extracted spice matches the "correct" port order from xschem, but not when I get it from top level.
But will try, after this meet.
m
Weirdly, when I run extraction/lvs on just the simplecounter, the extracted spice matches the “correct” port order from xschem, but not when I get it from top level.
The port order between the schematic and extracted layout is irrelevant. It’s the port order between the schematic and verilog that’s important.
Reversing the port order on the symbol looks like it yields a match.
Copy code
Contents of circuit 1:  Circuit: 'ringtest'
Circuit ringtest contains 4 device instances.
  Class: driver                instances:   1
  Class: mux4onehot_b          instances:   1
  Class: ring                  instances:   1
  Class: simplecounter         instances:   1
Circuit contains 20 nets.
Contents of circuit 2:  Circuit: 'ringtest'
Circuit ringtest contains 4 device instances.
  Class: driver                instances:   1
  Class: mux4onehot_b          instances:   1
  Class: ring                  instances:   1
  Class: simplecounter         instances:   1
Circuit contains 20 nets.

Circuit 1 contains 4 devices, Circuit 2 contains 4 devices.
Circuit 1 contains 20 nets,    Circuit 2 contains 20 nets.


Final result: 
Circuits match uniquely.
.
Logging to file "lvs.report" disabled
LVS Done.
p
@Mitch Bailey !! Was just playing with that, and it failed... must've done it wrong. You did this in symplecounter.sym ?
m
Right, I opened the file in
vi
and changed the order of the lines.
I added the missing pdk files too.
Copy code
puts "Reading layout mag/ringtest.lvs.spice..."
set layout [readnet spice mag/ringtest.lvs.spice]
set source [readnet spice /dev/null]
puts "Reading source $env(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_ef_sc_hd__decap_12.spice..."
readnet spice $env(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_ef_sc_hd__decap_12.spice $source
puts "Reading source $env(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_ef_sc_hd__fill_12.spice..."
readnet spice $env(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_ef_sc_hd__fill_12.spice $source
puts "Reading source $env(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_ef_sc_hd__fill_4.spice..."
readnet spice $env(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_ef_sc_hd__fill_4.spice $source
puts "Reading source $env(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_ef_sc_hd__fill_8.spice..."
readnet spice $env(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_ef_sc_hd__fill_8.spice $source
puts "Reading source $env(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice..."
readnet spice $env(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice $source
puts "Reading source xschem/simulation/driver.spice..."
readnet spice xschem/simulation/driver.spice $source
puts "Reading source xschem/simulation/ring.spice..."
readnet spice xschem/simulation/ring.spice $source
puts "Reading source xschem/simulation/ringtest.spice..."
readnet spice xschem/simulation/ringtest.spice $source
puts "Reading source verilog/gl/simplecounter.v..."
readnet verilog verilog/gl/simplecounter.v $source
lvs "$layout ringtest" "$source ringtest" $env(PDK_ROOT)/sky130A/libs.tech/netgen/sky130A_setup.tcl lvs.report -blackbox -json
Copy code
v {xschem version=3.4.5 file_version=1.2
}
G {}
K {type=primitive
format="@name @pinlist @symname"
booya="VGND VPWR clk enable counter[0]  counter[1]  counter[2]  counter[3]  counter[4]  counter[5]  counter[6]  counter[7]  counter[8]  counter[9] "
template="name=x1"
}
V {}
S {}
E {}
L 4 20 -180 40 -180 {}
L 4 20 -200 40 -200 {}
L 4 160 -200 180 -200 {}
L 4 160 -180 180 -180 {}
L 4 160 -160 180 -160 {}
L 4 160 -140 180 -140 {}
L 4 160 -120 180 -120 {}
L 4 160 -100 180 -100 {}
L 4 160 -80 180 -80 {}
L 4 160 -60 180 -60 {}
L 4 160 -40 180 -40 {}
L 4 160 -20 180 -20 {}
L 4 40 -210 40 -10 {}
L 4 40 -10 160 -10 {}
L 4 160 -210 160 -10 {}
L 4 40 -210 160 -210 {}
L 4 20 -60 40 -60 {}
L 4 20 -30 40 -30 {}
B 5 17.5 -32.5 22.5 -27.5 {name=VGND dir=in}
B 5 17.5 -62.5 22.5 -57.5 {name=VPWR dir=in}
B 5 17.5 -202.5 22.5 -197.5 {name=clk dir=in}
B 5 17.5 -182.5 22.5 -177.5 {name=enable dir=in}
B 5 177.5 -22.5 182.5 -17.5 {name=counter[9] dir=out}
B 5 177.5 -42.5 182.5 -37.5 {name=counter[8] dir=out}
B 5 177.5 -62.5 182.5 -57.5 {name=counter[7] dir=out}
B 5 177.5 -82.5 182.5 -77.5 {name=counter[6] dir=out}
B 5 177.5 -102.5 182.5 -97.5 {name=counter[5] dir=out}
B 5 177.5 -122.5 182.5 -117.5 {name=counter[4] dir=out}
B 5 177.5 -142.5 182.5 -137.5 {name=counter[3] dir=out}
B 5 177.5 -162.5 182.5 -157.5 {name=counter[2] dir=out}
B 5 177.5 -182.5 182.5 -177.5 {name=counter[1] dir=out}
B 5 177.5 -202.5 182.5 -197.5 {name=counter[0] dir=out}
T {enable} 45 -184 0 0 0.2 0.2 {}
T {clk} 45 -204 0 0 0.2 0.2 {}
T {counter[0]} 155 -204 0 1 0.2 0.2 {}
T {counter[1]} 155 -184 0 1 0.2 0.2 {}
T {counter[2]} 155 -164 0 1 0.2 0.2 {}
T {counter[3]} 155 -144 0 1 0.2 0.2 {}
T {counter[4]} 155 -124 0 1 0.2 0.2 {}
T {counter[5]} 155 -104 0 1 0.2 0.2 {}
T {counter[6]} 155 -84 0 1 0.2 0.2 {}
T {counter[7]} 155 -64 0 1 0.2 0.2 {}
T {counter[8]} 155 -44 0 1 0.2 0.2 {}
T {counter[9]} 155 -24 0 1 0.2 0.2 {}
T {@name} 40 -230 0 0 0.2 0.2 {}
T {@symname} 90 -120 1 0 0.2 0.2 {}
T {VPWR} 45 -64 0 0 0.2 0.2 {}
T {VGND} 45 -34 0 0 0.2 0.2 {}
p
@Mitch Bailey ok, wait, there's something I'm not getting. Running this same set of scripts for LVS on the mux4onehot_b component, which includes sub-cells and, in there, bunch of standard cells, without including all these manual additional reads into $source works fine. Does this mean the LVS OK result in this case is illusory?
Will give the .sym a go right now.
m
netgen, by default, will blackbox and port match missing subcircuits. So, yes, you could have an LVS error in a sub block that may pass if the source netlist for that block is missing. The precheck LVS looks for the string
will not flatten
in the
lvs.report
and the strings
Matching pins
and
contains no devices
in the
lvs.log
(stdout). These will flag all the primitive devices, so those are filtered out. Anything else causes LVS to fail even if the
Circuits match uniquely
.
p
though I was blind, now I see
m
All the
sky130_ef_sc_hd
cells may not be necessary.
I think the only one I actually saw used was
decap_12
.
p
Ok, I have to start from the bottom, I think. BTW, a paste of the .sym and the lvs script still didn't pass... Thanks for your assistance, will dig in a try to validate every step up the chain. I wish I could get xschem to dump out a full hierarchy (like the extracted spice from magic's side)--adding the underlying/included spice into the LVS script seems dumb.
Oh, no... this is my fault.
t
You have a bunch of absolute path in xschem files btw.
p
I have the driver as primitive... ugh. Ok, will fix and investigate.
will also check the abs paths -- not sure why that's happening.
m
Did you recreate the spice netlist from the schematic? You can see the
decap_12
cell being blackboxed in the original log file.
Copy code
Creating placeholder cell definition for module sky130_ef_sc_hd__decap_12.
...
Circuit sky130_ef_sc_hd__decap_12 contains no devices.
and the original report file
Copy code
Circuit 2 cell sky130_ef_sc_hd__decap_12 is a black box; will not flatten Circuit 1

Subcircuit pins:
Circuit 1: sky130_ef_sc_hd__decap_12       |Circuit 2: sky130_ef_sc_hd__decap_12       
-------------------------------------------|-------------------------------------------
VGND                                       |VGND                                       
VPWR                                       |VPWR                                       
VPB                                        |VPB                                        
VNB                                        |VNB                                        
---------------------------------------------------------------------------------------
Cell pin lists are equivalent.
Device classes sky130_ef_sc_hd__decap_12 and sky130_ef_sc_hd__decap_12 are equivalent.
Here’s a diff (ignoring comments) of the
ringtest.spice
before and after after and before the
simplecounter.sym
change.
Copy code
5c5
< x4 VSS VDD drv_out enable_counter net2 net3 counter7 net4 net5 net6 counter3 net7 net8 net9 simplecounter
---
> x4 VSS VDD drv_out enable_counter net2 net3 net4 counter3 net5 net6 net7 counter7 net8 net9 simplecounter
p
Yes, I did regen the spice. On one hand, I have bugs because I was forcing the driver/inverter symbols to be primitive (it's a Matt project and I originally didn't want to duplicate in my repo). So I have to fix that before going again. Then I'll check the simplecounter port order again, see that it comes out like you. As for the decap and all that, I'm not sure why I should care that standard cells are blackboxed since I trust their guts.
m
The driver and ring as primitives are fine as long as you include the respective spice in the lvs.script.
p
Ok. I'd just prefer not doing that so I can have one lvs_netgen.tcl script to rule them all.
And it's a weird artifact that bites you without warning, as xschem will let you descend into the hierarchy even if marked primitive, if the .sch is around--you can only know by looking at the spice or symbol.
Yep! All I did was change them to subcircuit, regen the spice from xschem (the equivalent of your readnets) and:
Circuit 1 contains 4 devices, Circuit 2 contains 4 devices.
Circuit 1 contains 20 nets,    Circuit 2 contains 20 nets.
Final result:
Circuits match uniquely.
.
Logging to file "lvs.report" disabled
LVS Done.
LVS OK
oof! Thanks, can finally move on!
t
@Pat Deegan As a side note, to pass pre-check you'll need the pin area for the power stripes to extend to the whole length vertically and not just small squares.
m
Congratulations! The latest version of xshcem is supposed to pick up the pin order from the schematic (if it exists) even with primitive symbols. Don’t know if that’s related to what you’re seeing.
p
@tnt The project is something like attached--are you referring to something you saw in there? And If so, am not clear on what you mean (about to push it up and see what the prechecks say, but if you've seen a prob, your output is a lot easier on the brain that what I've dealt with from the scripts, so would like to know).
@Mitch Bailey yay! Well, it's thanks to you and @tnt (and Tim)... really glad, was getting a bit flummoxed. Am using xschem 3.4.5 which I think is latest.
👍 1
t
On your
met4
power strips, you see the defined pas area as a small cyan outline on them in the upper part with the label written on it.
p
Oh, you mean the label/port square thingies? Ok.