| /*============================================================================== |
| File: S130padPcell.il |
| Purpose: Pcell code for layout and/or symbols, and cdf setup for the pads |
| for Skywater S130 Pcell |
| |
| Created: June 21, 2020 Madek Graham |
| Description: Pcell code to create pad devices |
| |
| Devices/views: pad_bond / symbol auCdl auLvs layout |
| pad_probe / symbol auCdl auLvs layout |
| pad_microprobe / symbol auCdl auLvs layout |
| |
| ------------------------------------------------------------ |
| Modifications: |
| - Nov 2, 2020 MSG |
| Added marker layers for I/O, Power, or Ground pad type, as well as new CDF |
| parameter to flag the pad type. |
| |
| ==============================================================================*/ |
| |
| /*============================================================================== |
| |
| This file only needs to be loaded once to create the pcells and cdf information |
| for the dioDevices set within the S130techData.il file |
| |
| ==============================================================================*/ |
| |
| let( ( libName ) |
| |
| libName = "S130" |
| |
| foreach( device padDevices |
| |
| printf("Creating device %s in %s library\n" device->deviceName libName ) |
| |
| ;=========================================================== |
| ;***** Define Layout Pcell ***** |
| ;=========================================================== |
| |
| pcDefinePCell( list( ddGetObj(libName) device->deviceName "layout" ) |
| ; formal parameters name value pairs |
| ( |
| ( devInfo "ilList" device ) |
| ( rules "ilList" designRules ) |
| ( grid "float" techGetMfgGridResolution(techGetTechFile(ddGetObj(libName))) ) |
| ( w "float" device->defW ) |
| ( l "float" device->defL ) |
| ( metalOL "float" max(designRules->pad->minBotMetOL designRules->pad->minTopMetOL) ) |
| ( padType "string" "I/O" ) |
| ) |
| |
| let(( cv adj45 pt0x pt1x pt2x pt3x pt0y pt1y pt2y pt3y ) |
| |
| cv = pcCellView |
| dbReplaceProp(cv "instNamePrefix" "string" "PAD") |
| |
| ; figure out the points since all pads need 45 degree corners |
| ; origin will always be the center of the pad |
| |
| ; create the pad |
| if( devInfo->minLbevel then |
| adj45 = ceiling(sqrt(0.5*expt(rules->pad->minLbevel 2))/grid)*grid |
| else |
| adj45 = ceiling(min(w l)*0.1/grid)*grid |
| ) |
| pt0x = pt0y = 0.0 |
| pt1x = adj45 |
| pt2x = w - adj45 |
| pt3x = w |
| pt1y = adj45 |
| pt2y = l - adj45 |
| pt3y = l |
| rodCreatePolygon( |
| ?cvId cv |
| ?name "pad" |
| ?layer devInfo->padLay->layer |
| ?pts list( pt1x:pt0y pt2x:pt0y pt3x:pt1y pt3x:pt2y pt2x:pt3y |
| pt1x:pt3y pt0x:pt2y pt0x:pt1y ) |
| ) |
| ; create pad type marking layer |
| rodCreatePolygon( |
| ?cvId cv |
| ?name "padType" |
| ?layer case( padType |
| ("I/O" list( "areaid" "pad_io" ) ) |
| ("Power" list( "areaid" "pad_pwr" ) ) |
| ("Ground" list( "areaid" "pad_gnd" ) ) |
| ) |
| ?fromObj rodGetObj("pad" cv) |
| ) |
| |
| ; create length LVS marking layer |
| rodCreateRect( |
| ?cvId cv |
| ?name "lvsLengthMrk" |
| ?layer list("areaid" "padLength") |
| ?width w |
| ?length grid |
| ?origin list(0.0 round(0.5*l/grid)*grid) |
| ) |
| |
| ; create marking layer if any |
| when( devInfo->mrkLay |
| rodCreatePolygon( |
| ?cvId cv |
| ?name "mrkLay" |
| ?layer devInfo->mrkLay |
| ?pts list( pt1x:pt0y pt2x:pt0y pt3x:pt1y pt3x:pt2y pt2x:pt3y |
| pt1x:pt3y pt0x:pt2y pt0x:pt1y ) |
| ) |
| ); when mrkLay |
| |
| ; create identifier label if any |
| when( devInfo->label |
| dbCreateLabel( cv list(devInfo->padLay->layer "label") rodGetObj("pad" cv)->centerCenter devInfo->label |
| "centerCenter" "R0" "stick" min(0.5 min(w l)*0.01) ) |
| ); when label |
| |
| /* |
| ; create the module cut layer |
| modcutOL = rules->pad->minModcutOL |
| pt0x = pt0y = -modcutOL |
| pt1x = round((adj45 - 0.5*modcutOL)/grid)*grid |
| pt2x = ceiling((w - adj45 + 0.5*modcutOL)/grid)*grid |
| pt3x = w + modcutOL |
| pt1y = round((adj45 - 0.5*modcutOL)/grid)*grid |
| pt2y = ceiling((l - adj45 + 0.5*modcutOL)/grid)*grid |
| pt3y = l + modcutOL |
| rodCreatePolygon( |
| ?cvId cv |
| ?name "modCut" |
| ?layer list("areaid" "moduleCut") |
| ?pts list( pt1x:pt0y pt2x:pt0y pt3x:pt1y pt3x:pt2y pt2x:pt3y |
| pt1x:pt3y pt0x:pt2y pt0x:pt1y ) |
| ) |
| */ |
| |
| ; create the top metal |
| adj45 = round((adj45 - 0.5*metalOL)/grid)*grid |
| pt0x = pt0y = -metalOL |
| pt1x = adj45 |
| pt2x = w - adj45 |
| pt3x = w + metalOL |
| pt1y = adj45 |
| pt2y = l - adj45 |
| pt3y = l + metalOL |
| rodCreatePolygon( |
| ?cvId cv |
| ?name "topMet" |
| ?layer devInfo->topMetLay->layer |
| ?pts list( pt1x:pt0y pt2x:pt0y pt3x:pt1y pt3x:pt2y pt2x:pt3y |
| pt1x:pt3y pt0x:pt2y pt0x:pt1y ) |
| ) |
| |
| ; create the bottom metal |
| dbLayerAndNot( cv devInfo->botMetLay->layer list( rodGetObj("topMet" cv)->dbId ) |
| list( rodGetObj("pad" cv)->dbId )) |
| |
| ; create the vias |
| ; create a keepout to ensure proper metal overlap for bot metal |
| rodCreatePolygon( |
| ?cvId cv |
| ?name "keepOut" |
| ?layer list( "text" "drawing" ) |
| ?fromObj rodGetObj("pad" cv) |
| ?size devInfo->botMetLay->minOLSviaU |
| ) |
| rodFillWithRects( |
| ?shapeId rodGetObj("topMet" cv)->dbId |
| ?keepOut list( rodGetObj("keepOut" cv)->dbId->points ) |
| ?fillShapeLPP list(devInfo->viaLay->layer devInfo->viaLay->purpose) |
| ?fillShapeWidth devInfo->viaLay->minW |
| ?fillShapeLength devInfo->viaLay->minW |
| ?justification "centerCenter" |
| ?spaceX devInfo->viaLay->minSP |
| ?spaceY devInfo->viaLay->minSP |
| ?enclosureX max( |
| devInfo->botMetLay->minOLSviaU |
| devInfo->topMetLay->minOLSviaL |
| ) |
| ?enclosureY max( |
| devInfo->botMetLay->minOLSviaU |
| devInfo->topMetLay->minOLSviaL |
| ) |
| ?grid grid |
| ) |
| dbDeleteObject(rodGetObj("keepOut" cv)->dbId) |
| |
| ; create the pins |
| rodCreatePolygon( |
| ?cvId cv |
| ?name "padPin" |
| ?layer list( devInfo->topMetLay->pinlayer devInfo->topMetLay->pinpurpose ) |
| ?pts rodGetObj("pad" cv)->dbId->points |
| ?netName "PAD" |
| ?termName "PAD" |
| ?termIOType "inputOutput" |
| ?pin t |
| ?pinLabel t |
| ?pinLabelHeight 0.1*min(w l) |
| ?pinLabelLayer list( devInfo->topMetLay->layer "label") |
| ?pinLabelFont "stick" |
| ?pinLabelJust "centerCenter" |
| ) |
| |
| ); let |
| ); pcDefinePCell layout |
| printf(" ...layout view created\n") |
| |
| ;=========================================================== |
| ;***** Define Symbol Pcell ***** |
| ;=========================================================== |
| |
| foreach( view list("symbol" "auCdl" "auLvs") |
| let( (cv instLabel labelT labelM netp pad termP sizeFactor) |
| when( cv = dbOpenCellViewByType( ddGetObj(libName) device->deviceName view "schematicSymbol" "w" ) |
| |
| case( device->deviceName |
| ("pad_bond" |
| dbReplaceProp(cv "instNamePrefix" "string" "PAD") |
| sizeFactor = 0.0 |
| ) |
| ("pad_probe" |
| dbReplaceProp(cv "instNamePrefix" "string" "PROBE") |
| sizeFactor = 0.0625 |
| ) |
| ("pad_microprobe" |
| dbReplaceProp(cv "instNamePrefix" "string" "MPROBE") |
| sizeFactor = 0.125 |
| ) |
| ); end case |
| |
| ; only need this for auCdl and auLvs, not for simulation |
| dbReplaceProp(cv "nlIgnore" "string" "ams hspiceD spectre spectreS verilog vhdl") |
| |
| ; pad drawing and main labels |
| ;----------------------------- |
| dbCreateRect(cv list("instance" "drawing") list(-0.375+sizeFactor:-0.5+sizeFactor |
| 0.375-sizeFactor:0.375-sizeFactor)) |
| dbCreateRect(cv list("device" "drawing") list(-0.375+sizeFactor:-0.375+sizeFactor |
| 0.375-sizeFactor:0.375-sizeFactor)) |
| dbCreateRect(cv list("device" "drawing2") list(-0.25+sizeFactor:-0.25+sizeFactor |
| 0.25-sizeFactor:0.25-sizeFactor)) |
| dbCreateLine(cv list("device" "drawing2") list(-0.25+sizeFactor:-0.25+sizeFactor |
| 0.25-sizeFactor:0.25-sizeFactor)) |
| dbCreateLine(cv list("device" "drawing2") list(-0.25+sizeFactor:0.25-sizeFactor |
| 0.25-sizeFactor:-0.25+sizeFactor)) |
| dbCreateLine(cv list("device" "drawing") list(0:-0.375+sizeFactor 0:-0.5+sizeFactor)) |
| |
| instLabel = dbCreateLabel( cv list("annotate" "drawing7") 0:0.40625-sizeFactor |
| "[@instanceName]" "lowerCenter" "R0" "stick" 0.0625 ) |
| instLabel~>labelType = "NLPLabel" |
| |
| labelT = dbCreateLabel(cv list("text" "drawing") 0:0.3125-sizeFactor |
| "[@lvsModel:%]" "centerCenter" "R0" "stick" 0.05625-0.2*sizeFactor) |
| labelT->labelType = "NLPLabel" |
| labelM = dbCreateLabel(cv list("annotate" "drawing") 0:-0.3125+sizeFactor |
| "[@m:M=%]" "centerCenter" "R0" "stick" 0.03125) |
| labelM->labelType = "NLPLabel" |
| |
| ; create net and pin |
| ;----------------------------- |
| netp = dbMakeNet(cv "PAD") |
| dbCreateTerm(netp "PAD" "inputOutput") |
| pad = dbCreateRect(cv list("pin" "drawing") |
| list(-0.01875:-0.01875 0.01875:0.01875) ) |
| dbMoveShape(pad cv list(0:-0.5+sizeFactor "R0")) |
| dbCreatePin(netp pad) |
| termP = dbCreateLabel( cv list("annotate" "drawing8") 0.0125+sizeFactor:-0.48125+sizeFactor |
| "cdsTerm(\"PAD\")" "lowerLeft" "R0" "stick" 0.01875 ) |
| termP~>labelType = "ILLabel" |
| termP->parent = pad |
| |
| dbSave(cv) |
| dbClose(cv) |
| ); when cv |
| ); let |
| printf(" ...%s view created\n" view ) |
| ); foreach view |
| |
| ;=========================================================== |
| ;***** CDF definition ***** |
| ;=========================================================== |
| |
| let( ( cellName cellId cdf tfId ) |
| |
| cellName = device->deviceName |
| |
| unless( cellId = ddGetObj( libName cellName ) |
| error( "Could not get cell object Lib: %s, Cell:%s" libName cellName ) |
| ); unless |
| |
| when( cdf = cdfGetBaseCellCDF( cellId ) |
| cdfDeleteCDF( cdf ) |
| ); when |
| cdf = cdfCreateBaseCellCDF( cellId ) |
| |
| tfId = techGetTechFile(cellId) |
| |
| cdfCreateParam( cdf |
| ?name "model" |
| ?prompt "Model Name" |
| ?type "string" |
| ?defValue device->modelName |
| ?storeDefault "yes" |
| ?parseAsCEL "yes" |
| ?editable "nil" |
| ?display "nil" |
| ) |
| cdfCreateParam( cdf |
| ?name "lvsModel" |
| ?prompt "LVS Model Name" |
| ?type "string" |
| ?defValue device->lvsModel |
| ?storeDefault "yes" |
| ?parseAsCEL "yes" |
| ?editable "nil" |
| ?display "hiGetCurrentWindow()~>cellView~>cellViewType == \"maskLayout\"" |
| ) |
| when( device->label == "e-test" |
| cdfCreateParam( cdf |
| ?name "padSize" |
| ?prompt "Size" |
| ?type "radio" |
| ?defValue sprintf(nil "%g" device->minW) |
| ?storeDefault "yes" |
| ?choices list(sprintf(nil "%g" device->minW) sprintf(nil "%g" device->maxW)) |
| ?callback "cdfgData->w->value = cdfgData->l->value = cdfParseFloatString(cdfgData->padSize->value)" |
| ) |
| ); when etest pad |
| cdfCreateParam( cdf |
| ?name "w" |
| ?prompt "Width (um)" |
| ?type "float" |
| ?defValue device->defW |
| ?storeDefault "yes" |
| ?callback strcat(device->paramCB "('w)") |
| ?editable "if( cdfgData->padSize then nil else t)" |
| ) |
| cdfCreateParam( cdf |
| ?name "l" |
| ?prompt "Length (um)" |
| ?type "float" |
| ?defValue device->defL |
| ?storeDefault "yes" |
| ?callback strcat(device->paramCB "('l)") |
| ?editable "if( cdfgData->padSize then nil else t)" |
| ) |
| cdfCreateParam( cdf |
| ?name "m" |
| ?prompt "Multiples" |
| ?type "int" |
| ?defValue 1 |
| ?storeDefault "yes" |
| ?callback strcat(device->paramCB "('m)") |
| ?display "hiGetCurrentWindow()~>cellView~>cellViewType != \"maskLayout\"" |
| ) |
| cdfCreateParam( cdf |
| ?name "metalOL" |
| ?prompt "Metal Overlap Pad" |
| ?type "float" |
| ?defValue device->minTopMetOL |
| ?storeDefault "yes" |
| ?callback strcat(device->paramCB "('metalOL)") |
| ?display "hiGetCurrentWindow()~>cellView~>cellViewType == \"maskLayout\"" |
| ) |
| cdfCreateParam( cdf |
| ?name "padType" |
| ?prompt "Type" |
| ?type "radio" |
| ?defValue "I/O" |
| ?storeDefault "yes" |
| ?choices list("I/O" "Power" "Ground") |
| ) |
| cdfCreateParam( cdf |
| ?name "minW" |
| ?prompt "minimum width" |
| ?type "float" |
| ?defValue device->minW |
| ?storeDefault "yes" |
| ?parseAsCEL "no" |
| ?display "nil" |
| ) |
| cdfCreateParam( cdf |
| ?name "maxW" |
| ?prompt "maximum width" |
| ?type "float" |
| ?defValue device->maxW |
| ?storeDefault "yes" |
| ?parseAsCEL "no" |
| ?display "nil" |
| ) |
| cdfCreateParam( cdf |
| ?name "minTopMetOL" |
| ?prompt "minimum Top Metal overlap" |
| ?type "float" |
| ?defValue device->minTopMetOL |
| ?storeDefault "yes" |
| ?parseAsCEL "no" |
| ?display "nil" |
| ) |
| |
| cdf->simInfo = list( nil) |
| cdf->simInfo->auCdl = '( nil |
| dollarEqualParams nil |
| dollarParams nil |
| otherParameters nil |
| netlistProcedure ansCdlSubcktCallExtended |
| instParameters (model m w l) |
| propMapping (nil model lvsModel) |
| componentName nil |
| termOrder (PAD) |
| namePrefix "X" |
| ) |
| cdf->simInfo->auLvs = '( nil |
| dollarEqualParams nil |
| dollarParams nil |
| otherParameters nil |
| netlistProcedure ansLvsCompParamPrim |
| instParameters (model m w l ) |
| propMapping (nil model lvsModel) |
| termOrder (PAD) |
| namePrefix "X" |
| ) |
| |
| ;;; Properties |
| cdf->formInitProc = "S130disablePcellChange" |
| cdf->doneProc = "" |
| cdf->buttonFieldWidth = 250 |
| cdf->fieldHeight = 35 |
| cdf->fieldWidth = 250 |
| cdf->promptWidth = 120 |
| cdf->modelLabelSet = "" |
| cdf->opPointLabelSet = "" |
| cdf->paramLabelSet = "" |
| cdf->instDisplayMode = "instName" |
| cdf->instNameType = "schematic" |
| cdf->termDisplayMode = "netName" |
| cdf->netNameType = "schematic" |
| |
| cdfSaveCDF(cdf) |
| |
| ); let |
| ); foreach device |
| |
| ); let |
| |
| /*================================== EOF ===================================*/ |