Home
  • Products
  • Solutions
  • Support
  • Company
  • Products
  • Solutions
  • Support
  • Company
Community Custom IC SKILL Error while using LVS on a Schematic PCell

Stats

  • Replies 6
  • Subscribers 143
  • Views 909
  • Members are here 0

Error while using LVS on a Schematic PCell

KHaas
KHaas 2 months ago

Hello,

I have a question regarding an error that appears when trying to create a netlist of a schematic PCell while running LVS.

I created a schematic PCell and the respective layout of this schematic. When running an LVS on the created PCells everything seems to work and the netlisting for the LVS completes. But when I use the PCell inside another cell the netlisting at the start of the LVS returns following error.

*Error* Could not determine the node name for terminal '"PLUS"'. This may be caused by an error in the CDF specified on:
component : res
named : /R2<0:511>
in cellview : TEST/schematic
of library : examplelib
"ERROR (OSSHNL-524): Netlisting failed because the function 'hnlNetNameOnTerm' was called with a non-existent terminal 'PLUS' on the current instance 'R2<0:511>' in the design 'examplelib/TEST/schematic'. Provide a valid terminal name with this function and regenerate the netlist.\n\n"

*Error* Could not determine the node name for terminal '"PLUS"'. This may be caused by an error in the CDF specified on:
component : res
named : /R2<0:511>
in cellview : TEST/schematic
of library : examplelib
End netlisting Sep 26 14:19:30 2023
ERROR (OSSHNL-514): Netlist generation failed because of the errors reported above. The netlist might not have been generated at all, or the generated netlist could be corrupt. Fix the reported errors and regenerate the netlist.

I then tried to create the schematics by hand using the schematic editor and everything worked as expected, meaning the netlisting completes. Even just copying the schematics the PCell created into a new cell and using this cell to create a symbol works. I also took a look at this post from the past which seems to have similar problems: https://community.cadence.com/cadence_technology_forums/f/custom-ic-skill/56643/pcell-error-faulty-pcell-schematic 
Using the answers there, I tried different methods of connecting the instance terminals, dbCreateConnByName(), dbCreateInstTerm() and dbCreateConn(). Sadly, none of these functions worked. I also tried to reload the analogLib following this guide: https://community.cadence.com/cadence_technology_forums/f/rf-design/31091/error-osshnl-524-while-using-nport and had a look at the OSS Troubleshooting guide https://support.cadence.com/apex/ArticleAttachmentPortal?id=a1O0V000006Al6NUAS&pageName=ArticleContent .

I then looked at the schematics that are created when inserting the symbol of the PCell, so descending in read mode, and it seems as if the terminals of the resistors that are not connected to an outside net are getting detached from the instance. Meaning, when performing a leftklick on the resistor creating the error and taking a look at the "Property Editor" it only shows one instance pin. When descending into the schematic drawn by hand the same resistor shows two pins.

I also created a small code example that lets me recreate the error. As layout you can use anything as an example. The code used looks like this:

examplecode.txt
let((library cell PCellSchematicId PCellSymbolId)
; library/cell of PCell
library = ddGetObj("examplelib")
cell = "TEST"


; define the schematic
PCellSchematicId = pcDefinePCell(
    list(library cell "schematic" "schematic")
    ()

    let((cv PatchCordMaster ResistorMaster patchcord1 patchcord2 Resistor1 Resistor2 Resistor3 net wire text)
    cv = pcCellView
    ; load symbols for instantiation
    PatchCordMaster = dbOpenCellViewByType("basic" "patch" "symbol")
    ResistorMaster = dbOpenCellViewByType("analogLib" "res" "symbol")

    patchcord1 = dbCreateParamInst(cv PatchCordMaster nil 3.5:0 "MY" 1 list(
        list("schPatchExpr" "string" "0:255=0:255")))

    patchcord2 = dbCreateParamInst(cv PatchCordMaster nil 3.5:-0.25 "MY" 1 list(
        list("schPatchExpr" "string" "256:511=0:255")))

    Resistor1 = dbCreateParamInst(cv ResistorMaster nil 3:0 "R90" 256 list(
        list("r" "string" "0")))
    Resistor2 = dbCreateParamInst(cv ResistorMaster nil 3:-0.25 "R90" 256 list(
        list("r" "string" "0")))
    Resistor3 = dbCreateParamInst(cv ResistorMaster nil 4.875:-0.25 "R90" 512 list(
        list("r" "string" "0")))

    
    net = dbCreateNet(cv "input<0:255>")
    wire = dbCreateLine(cv list("wire" "drawing") list(2:0 3:0))
    text = dbCreateLabel(cv '("wire" "label") 2:0 "input<0:255>" "lowerLeft" "R0" "stick" 0.0625)
    text~>parent = wire
    dbAddFigToNet(wire net)
    dbCreateConnByName(net Resistor1 "PLUS")

    net = dbCreateNet(cv "input<256:511>")
    wire = dbCreateLine(cv list("wire" "drawing") list(2:-0.25 3:-0.25))
    text = dbCreateLabel(cv '("wire" "label") 2:-0.25 "input<256:511>" "lowerLeft" "R0" "stick" 0.0625)
    text~>parent = wire
    dbAddFigToNet(wire net)
    dbCreateConnByName(net Resistor2 "PLUS")

    net = dbCreateNet(cv "internet1")
    wire = dbCreateLine(cv list("wire" "drawing") list(3.375:0 3.5:0))
    dbAddFigToNet(wire net)
    dbCreateConnByName(net Resistor1 "MINUS")
    dbCreateConnByName(net patchcord1 "dst")

    net = dbCreateNet(cv "internet2")
    wire = dbCreateLine(cv list("wire" "drawing") list(3.375:-0.25 3.5:-0.25))
    dbAddFigToNet(wire net)
    dbCreateConnByName(net Resistor2 "MINUS")
    dbCreateConnByName(net patchcord2 "dst")
 
    net = dbCreateNet(cv "internet")
    wire = dbCreateLine(cv list("wire" "drawing") list(3.6:0 4.15:0))
    dbAddFigToNet(wire net)
    wire = dbCreateLine(cv list("wire" "drawing") list(3.6:-0.25 4.875:-0.25))
    dbAddFigToNet(wire net)
    wire = dbCreateLine(cv list("wire" "drawing") list(4.15:0 4.15:-0.25))
    dbAddFigToNet(wire net)
    dbCreateConnByName(net patchcord1 "src")
    dbCreateConnByName(net patchcord2 "src")
    dbCreateConnByName(net Resistor3 "PLUS")

    net = dbCreateNet(cv "output<0:511>")
    wire = dbCreateLine(cv list("wire" "drawing") list(5.25:-0.25 6:-0.25))
    text = dbCreateLabel(cv '("wire" "label") 5.25:-0.25 "output<0:511>" "lowerLeft" "R0" "stick" 0.0625)
    text~>parent = wire
    dbAddFigToNet(wire net)
    dbCreateConnByName(net Resistor3 "MINUS")

    )
)
dbSave(PCellSchematicId)
dbClose(PCellSchematicId)


PCellSymbolId = pcDefinePCell(
    list( library cell "symbol" "schematicSymbol")
    (
    )

	let(()
		dbCreateRect(pcCellView '("device" "drawing") list(0:1 1:0)) 
		dbCreateRect(pcCellView '("instance" "drawing") list(0:0 1:1))
        	dbCreateLabel(pcCellView '("wire" "label") 0.5:0.5 "TEST" "centerCenter" "R0" "stick" 0.0625)
	)
)

dbSave(PCellSymbolId)
dbClose(PCellSymbolId)
)

For the LVS I use Calibre, which calls SPICE to generate the netlist.

Any help is appreciated.

Thanks,

KHaas

  • Reply
  • Cancel
  • Cancel
Parents
  • Andrew Beckett
    Andrew Beckett 2 months ago

    When loading the code, you see these warnings:

    *WARNING* (DB-221309): dbCreateConnByName: Net width does not match instance/terminal width.
    *WARNING* (DB-221309): dbCreateConnByName: Net width does not match instance/terminal width.
    *WARNING* (DB-221309): dbCreateConnByName: Net width does not match instance/terminal width.

    This is because you are creating nets called internet1 and internet2 but these don't have widths - so that's not going to work. It's not clear what you are actually trying to do here (I'm not sure why the patch cords are needed other than you've given the nets different names either side).

    I think if you call the nets:

    net = dbCreateNet(cv "internet1<0:255>")
    ; later in the code
    net = dbCreateNet(cv "internet2<0:255>")
    ; later in the code
    net = dbCreateNet(cv "internet<0:511>")

    and then comment out the connections to the patch cord instances (these are not real instances; they are special components that the schematic extractor uses to figure out aliasing in net names; if you look at them in a schematic extracted by VSE you'll see that the pins are not connected) - then it will compile and netlist. It won't be correct (because the resistors on the left won't be connected to the resistors on the right). The simplest would be to just set the connections to be called "internet<0:255>", "internet<256:511>" and "internet<0:511>" - as that avoids aliasing. Creating aliasing is a little more complicated - I can explain how to do that with a bit more time if you really need to do that.

    Andrew

    • Cancel
    • Up +1 Down
    • Reply
    • Cancel
  • KHaas
    KHaas 2 months ago in reply to Andrew Beckett

    Hello Andrew,

    thanks a lot, it seems as if this solution is solving my problem. With the modifications to the net names and the patchcord connections the netlisting finishes. The patchcords are needed, because this is just a simplification of a much more complex design. I will have a look into the possibility of getting rid of the patchcords in the other design as well.

    Cheers

    KHaas

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Andrew Beckett
    Andrew Beckett 2 months ago in reply to KHaas

    I've updated the code to preserve the separate names that you had and create the aliased names (the trick is to use dbMergeSignal). The patch cords are just cosmetic of course in this case. (note, I changed the lib/cell name at the top in case you miss that bit)

    6204.examplecode.txt
    let((library cell PCellSchematicId PCellSymbolId)
    ; library/cell of PCell
    library = ddGetObj("mylib")
    cell = "forumSchPCell"
    
    
    ; define the schematic
    PCellSchematicId = pcDefinePCell(
        list(library cell "schematic" "schematic")
        ()
    
        let((cv PatchCordMaster ResistorMaster patchcord1 patchcord2 Resistor1 Resistor2 Resistor3 net wire text internet internet1 internet2)
        cv = pcCellView
        ; load symbols for instantiation
        PatchCordMaster = dbOpenCellViewByType("basic" "patch" "symbol")
        ResistorMaster = dbOpenCellViewByType("analogLib" "res" "symbol")
    
        patchcord1 = dbCreateParamInst(cv PatchCordMaster nil 3.5:0 "MY" 1 list(
            list("schPatchExpr" "string" "0:255=0:255")))
    
        patchcord2 = dbCreateParamInst(cv PatchCordMaster nil 3.5:-0.25 "MY" 1 list(
            list("schPatchExpr" "string" "256:511=0:255")))
    
        Resistor1 = dbCreateParamInst(cv ResistorMaster nil 3:0 "R90" 256 list(
            list("r" "string" "0")))
        Resistor2 = dbCreateParamInst(cv ResistorMaster nil 3:-0.25 "R90" 256 list(
            list("r" "string" "0")))
        Resistor3 = dbCreateParamInst(cv ResistorMaster nil 4.875:-0.25 "R90" 512 list(
            list("r" "string" "0")))
    
        
        net = dbCreateNet(cv "input<0:255>")
        wire = dbCreateLine(cv list("wire" "drawing") list(2:0 3:0))
        text = dbCreateLabel(cv '("wire" "label") 2:0 "input<0:255>" "lowerLeft" "R0" "stick" 0.0625)
        text~>parent = wire
        dbAddFigToNet(wire net)
        dbCreateConnByName(net Resistor1 "PLUS")
    
        net = dbCreateNet(cv "input<256:511>")
        wire = dbCreateLine(cv list("wire" "drawing") list(2:-0.25 3:-0.25))
        text = dbCreateLabel(cv '("wire" "label") 2:-0.25 "input<256:511>" "lowerLeft" "R0" "stick" 0.0625)
        text~>parent = wire
        dbAddFigToNet(wire net)
        dbCreateConnByName(net Resistor2 "PLUS")
    
        net = dbCreateNet(cv "internet1<0:255>")
        internet1 = net
        wire = dbCreateLine(cv list("wire" "drawing") list(3.375:0 3.5:0))
        dbAddFigToNet(wire net)
        dbCreateConnByName(net Resistor1 "MINUS")
    ;    dbCreateConnByName(net patchcord1 "dst")
    
        net = dbCreateNet(cv "internet2<0:255>")
        internet2 = net
        wire = dbCreateLine(cv list("wire" "drawing") list(3.375:-0.25 3.5:-0.25))
        dbAddFigToNet(wire net)
        dbCreateConnByName(net Resistor2 "MINUS")
    ;    dbCreateConnByName(net patchcord2 "dst")
     
        net = dbCreateNet(cv "internet<0:511>")
        internet = net
        wire = dbCreateLine(cv list("wire" "drawing") list(3.6:0 4.15:0))
        dbAddFigToNet(wire net)
        wire = dbCreateLine(cv list("wire" "drawing") list(3.6:-0.25 4.875:-0.25))
        dbAddFigToNet(wire net)
        wire = dbCreateLine(cv list("wire" "drawing") list(4.15:0 4.15:-0.25))
        dbAddFigToNet(wire net)
    ;    dbCreateConnByName(net patchcord1 "src")
    ;    dbCreateConnByName(net patchcord2 "src")
        dbCreateConnByName(net Resistor3 "PLUS")
    
    ; now create the aliases (in other words, do what the patchcord does)
        foreach((s1 s2) internet~>signals append(internet1~>signals internet2~>signals)
    	dbMergeSignal(s1 s2)
        )
    
        net = dbCreateNet(cv "output<0:511>")
        wire = dbCreateLine(cv list("wire" "drawing") list(5.25:-0.25 6:-0.25))
        text = dbCreateLabel(cv '("wire" "label") 5.25:-0.25 "output<0:511>" "lowerLeft" "R0" "stick" 0.0625)
        text~>parent = wire
        dbAddFigToNet(wire net)
        dbCreateConnByName(net Resistor3 "MINUS")
    
        )
    )
    dbSave(PCellSchematicId)
    dbClose(PCellSchematicId)
    
    
    PCellSymbolId = pcDefinePCell(
        list( library cell "symbol" "schematicSymbol")
        (
        )
    
    	let(()
    		dbCreateRect(pcCellView '("device" "drawing") list(0:1 1:0)) 
    		dbCreateRect(pcCellView '("instance" "drawing") list(0:0 1:1))
            	dbCreateLabel(pcCellView '("wire" "label") 0.5:0.5 "TEST" "centerCenter" "R0" "stick" 0.0625)
    	)
    )
    
    dbSave(PCellSymbolId)
    dbClose(PCellSymbolId)
    )
    

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
Reply
  • Andrew Beckett
    Andrew Beckett 2 months ago in reply to KHaas

    I've updated the code to preserve the separate names that you had and create the aliased names (the trick is to use dbMergeSignal). The patch cords are just cosmetic of course in this case. (note, I changed the lib/cell name at the top in case you miss that bit)

    6204.examplecode.txt
    let((library cell PCellSchematicId PCellSymbolId)
    ; library/cell of PCell
    library = ddGetObj("mylib")
    cell = "forumSchPCell"
    
    
    ; define the schematic
    PCellSchematicId = pcDefinePCell(
        list(library cell "schematic" "schematic")
        ()
    
        let((cv PatchCordMaster ResistorMaster patchcord1 patchcord2 Resistor1 Resistor2 Resistor3 net wire text internet internet1 internet2)
        cv = pcCellView
        ; load symbols for instantiation
        PatchCordMaster = dbOpenCellViewByType("basic" "patch" "symbol")
        ResistorMaster = dbOpenCellViewByType("analogLib" "res" "symbol")
    
        patchcord1 = dbCreateParamInst(cv PatchCordMaster nil 3.5:0 "MY" 1 list(
            list("schPatchExpr" "string" "0:255=0:255")))
    
        patchcord2 = dbCreateParamInst(cv PatchCordMaster nil 3.5:-0.25 "MY" 1 list(
            list("schPatchExpr" "string" "256:511=0:255")))
    
        Resistor1 = dbCreateParamInst(cv ResistorMaster nil 3:0 "R90" 256 list(
            list("r" "string" "0")))
        Resistor2 = dbCreateParamInst(cv ResistorMaster nil 3:-0.25 "R90" 256 list(
            list("r" "string" "0")))
        Resistor3 = dbCreateParamInst(cv ResistorMaster nil 4.875:-0.25 "R90" 512 list(
            list("r" "string" "0")))
    
        
        net = dbCreateNet(cv "input<0:255>")
        wire = dbCreateLine(cv list("wire" "drawing") list(2:0 3:0))
        text = dbCreateLabel(cv '("wire" "label") 2:0 "input<0:255>" "lowerLeft" "R0" "stick" 0.0625)
        text~>parent = wire
        dbAddFigToNet(wire net)
        dbCreateConnByName(net Resistor1 "PLUS")
    
        net = dbCreateNet(cv "input<256:511>")
        wire = dbCreateLine(cv list("wire" "drawing") list(2:-0.25 3:-0.25))
        text = dbCreateLabel(cv '("wire" "label") 2:-0.25 "input<256:511>" "lowerLeft" "R0" "stick" 0.0625)
        text~>parent = wire
        dbAddFigToNet(wire net)
        dbCreateConnByName(net Resistor2 "PLUS")
    
        net = dbCreateNet(cv "internet1<0:255>")
        internet1 = net
        wire = dbCreateLine(cv list("wire" "drawing") list(3.375:0 3.5:0))
        dbAddFigToNet(wire net)
        dbCreateConnByName(net Resistor1 "MINUS")
    ;    dbCreateConnByName(net patchcord1 "dst")
    
        net = dbCreateNet(cv "internet2<0:255>")
        internet2 = net
        wire = dbCreateLine(cv list("wire" "drawing") list(3.375:-0.25 3.5:-0.25))
        dbAddFigToNet(wire net)
        dbCreateConnByName(net Resistor2 "MINUS")
    ;    dbCreateConnByName(net patchcord2 "dst")
     
        net = dbCreateNet(cv "internet<0:511>")
        internet = net
        wire = dbCreateLine(cv list("wire" "drawing") list(3.6:0 4.15:0))
        dbAddFigToNet(wire net)
        wire = dbCreateLine(cv list("wire" "drawing") list(3.6:-0.25 4.875:-0.25))
        dbAddFigToNet(wire net)
        wire = dbCreateLine(cv list("wire" "drawing") list(4.15:0 4.15:-0.25))
        dbAddFigToNet(wire net)
    ;    dbCreateConnByName(net patchcord1 "src")
    ;    dbCreateConnByName(net patchcord2 "src")
        dbCreateConnByName(net Resistor3 "PLUS")
    
    ; now create the aliases (in other words, do what the patchcord does)
        foreach((s1 s2) internet~>signals append(internet1~>signals internet2~>signals)
    	dbMergeSignal(s1 s2)
        )
    
        net = dbCreateNet(cv "output<0:511>")
        wire = dbCreateLine(cv list("wire" "drawing") list(5.25:-0.25 6:-0.25))
        text = dbCreateLabel(cv '("wire" "label") 5.25:-0.25 "output<0:511>" "lowerLeft" "R0" "stick" 0.0625)
        text~>parent = wire
        dbAddFigToNet(wire net)
        dbCreateConnByName(net Resistor3 "MINUS")
    
        )
    )
    dbSave(PCellSchematicId)
    dbClose(PCellSchematicId)
    
    
    PCellSymbolId = pcDefinePCell(
        list( library cell "symbol" "schematicSymbol")
        (
        )
    
    	let(()
    		dbCreateRect(pcCellView '("device" "drawing") list(0:1 1:0)) 
    		dbCreateRect(pcCellView '("instance" "drawing") list(0:0 1:1))
            	dbCreateLabel(pcCellView '("wire" "label") 0.5:0.5 "TEST" "centerCenter" "R0" "stick" 0.0625)
    	)
    )
    
    dbSave(PCellSymbolId)
    dbClose(PCellSymbolId)
    )
    

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
Children
  • KHaas
    KHaas 2 months ago in reply to Andrew Beckett

    Hey,

    I now have had a deeper look into the patch cords that I was using and actually found a way to get rid of them completely. The schematic I was trying to implement looked like this.

    I followed your tip in your first reply and just renamed the nets on the left and right side of the patch cords accordingly. Resulting in something like this.

    Now when performing a check and save everything seems to work and my design is LVS clean. But when using the PCell in another cell, it seems like I still have missed some connections, because then the comparison returns false. Is there any way to get an output of the check and save telling me what was changed while performing it, or do I have to check every connection manually? The number of Nets and Instances as well as the number of pins does not change when performing the check.

    Thanks again for your patch cord explanation

    KHaas

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel
  • Andrew Beckett
    Andrew Beckett 2 months ago in reply to KHaas

    It's a bit hard to see from the pictures how exactly they are connected, but what I'd do is poke around in the resulting database (using SKILL functions to interrogate the instances, nets and instTerms) to see what is going on after check-and-save. The output of check-and-save is the resulting database connectivity - it doesn't print that in some other form. 

    Of course, you could also use File->Export->CDL and look at the output that way too and compare what you get manually (in essence a visual LVS).

    Andrew

    • Cancel
    • Up +1 Down
    • Reply
    • Cancel
  • KHaas
    KHaas 2 months ago in reply to Andrew Beckett

    I followed your instructions for creating the CDL files. I then was able to compare them and found my problem. Apart from some signaltypes and input-output directions, which I was able to fix, it seems like the schematics are the same and I have some mistakes in the layout generation. But these should hopefully be quite easy to fix.

    So again thank you very much for your help.

    KHaas

    • Cancel
    • Up 0 Down
    • Reply
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2023 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information