5
Creating SKILL++ Parameterized Cells
The Pcell source is typically written in SKILL, which is a multi-paradigm language. However, you can also write the Pcell source in SKILL++ along with the existing APIs.
Advantages of SKILL++ Pcells
You can create individual Pcells using SKILL++ classes and methods that leverage the Object Oriented Programming (OOP) concepts. Using multiple class inheritance, it is possible to create a new Pcell by inheriting from other Pcell classes.
Using SKILL++ Pcells renders the following advantages of OOP:
- A clear modular structure for programs – You can define abstract data types with hidden implementation details and using a well-defined interface of the unit.
- Quick maintenance and modification of the existing code – You can reuse the existing code to create new objects.
- A good framework for code libraries – The supplied software components can be quickly adapted and modified by the programmer.
Recommended and Supported SKILL++ Functions for Pcells
The following pc functions can be used for SKILL++ Pcells.
- pcSetParamSlotsFromMaster
- pcDefineParamSlot
- pcGetParamSlotType
- pcGetParamSlotValue
- pcSetParamSlotValue
- pcIsParamSlot
- pcGetDefaultParamsFromClass
Steps to Create SKILL++ Pcell
The following steps illustrate creation of a simple SKILL++ Pcell using the existing pcDefinePCell API, which has the Pcell source body implemented in SKILL++. To view the complete sample code, see the SKILL++ Pcell Samples section.
-
Define a base class (
PcellParam) with a single slot for holding the Pcell master ID, which is the same as thepcCellViewvariable used in SKILL Pcell. -
Define a class to represent the Pcell. This class is defined by inheriting from
PcellParam(or usingPcellParamas its superclass). -
Define a method (
setPcellParams) to transfer the Pcell parameter values to the slots of the Pcell class. This ensures that the Pcell code written in SKILL++ has full access to the same set of Pcell parameters. -
Define a method (
draw) to construct the Pcell. -
Implement the code to call
pcDefinePCellto create the supermaster.
SKILL++ Pcell Samples
You need to perform the following steps to setup SKILL++ Pcells:
-
Load
generic.ils,PcellParam.ils,CORE.ils,RING.ils, andWRAP.ils. These files are required for successful Pcell evaluation. -
Load
genPcell.il. This file is only needed to create the Pcell supermasters. -
Load
genPcDef.ilonly if you need to create thepcDefinePCellcode from Pcell class.
Refer to the following sample code to setup SKILL++ Pcell.
; Start of file - generic.ils
; Defines the generic function for draw.
; This is placed in its own file as this should be loaded
; once as redefining a generic function will remove all methods
; defined by previous defgeneric form
(defgeneric draw (device)
t
)
; End of file - generic.ils
; Start of file - PcellParam.ils
; Base class for all Pcells.
; cvId will hold the pcCellView value
defclass( PcellParam ()
(
(cvId @initarg cvId)
)
)
; A simple method to populate the Pcell parameters from the supermaster to
; a Pcell device's slots
defmethod( setPcellParams ((device PcellParam) cv)
when( cv && dbIsId(cv)
setSlotValue(device 'cvId cv)
foreach( param cv~>parameters~>value
setParamValue(device concat(param~>name) param~>value)
)
)
)
; A function to define a Pcell parameter stored as a Pcell class' slot.
; The optional argument _isParam is set to 't to indicate this parameter is
; a Pcell parameter
defun( defineParam (g_type g_value @optional (_isParam t))
list(nil 'type g_type 'value g_value 'isParam _isParam)
)
; A method to get Pcell parameter's type
defmethod( getParamType ((device PcellParam) (propName symbol))
slotValue(device propName)->type
)
; A method to get Pcell parameter's value
defmethod( getParamValue ((device PcellParam) (propName symbol))
slotValue(device propName)->value
)
; A method to set Pcell parameter's value
defmethod( setParamValue ((device PcellParam) (propName symbol) val)
slotValue(device propName)->value = val
)
; A method to check is the given name a Pcell parameter or not. This is
; based on the setting of the isParam attribute
defmethod( isParam ((device PcellParam) (propName symbol))
slotValue(device propName)->isParam
)
; A method to get a list of Pcell parameters with their names, types and
; values
defmethod( getPcellParams ((device PcellParam))
let((params)
params = setof( p device->? isParam(device p ))
params = foreach( mapcar p params
list( p
getParamType(device p)
getParamValue(device p)
)
)
)
)
; End of file - PcellParam.ils
; Start of file - CORE.ils
; Defines a CORE class inheriting from PcellParam
; Note, parameter created via defineParam will be treated
; as a Pcell parameter; otherwise it is treated as a normal
; class slot (e.g. coreBBox is not a Pcell parameter)
; You can replace the library name mentioned here with your own library.
defclass( CORE (PcellParam)
(
(cyanW @initform defineParam("float" 0.6))
(cyanL @initform defineParam("float" 0.2))
(greenW @initform defineParam("float" 0.2))
(greenL @initform defineParam("float" 0.8))
(coreBBox @initarg coreBBox)
)
)
; Draw a simple cross represented by two rectangles
defmethod( draw ((device CORE))
let((cv cyanW cyanL greenW greenL rectId llx lly urx ury)
cyanW = getParamValue(device 'cyanW)
cyanL = getParamValue(device 'cyanL)
greenW = getParamValue(device 'greenW)
greenL = getParamValue(device 'greenL)
; layers are choosen for their color's visibility
; You can replace the layer names mentioned here with the layer names
; present in your library.
cv = slotValue(device 'cvId)
rectId = dbCreateRect(cv
list("Poly" "drawing") list(0:0 greenL:greenW))
llx = 0.5 * greenL - 0.5 * cyanL
lly = 0.5 * greenW - 0.5 * cyanW
urx = 0.5 * greenL + 0.5 * cyanL
ury = 0.5 * greenW + 0.5 * cyanW
rectId = dbCreateRect(cv
list("Via1" "drawing") list(llx:lly urx:ury))
setSlotValue(device 'coreBBox list( 0.0:lly greenL:ury))
callNextMethod()
)
)
; Returns CORE's bounding box which is stored in the coreBBox slot
defmethod( getCoreBBox ((device CORE))
slotValue(device 'coreBBox)
)
; End of file - CORE.ils
; Start of file - RING.ils
; Defines a RING class inheriting from PcellParam
defclass( RING (PcellParam)
(
(ringW @initform defineParam("float" 0.1))
(ringS @initform defineParam("float" 0.1))
)
)
; Draw a polygon that wraps around the device's coreBBox with a given
; spacing value and width of the polygon
defmethod( draw ((device RING))
let((cv ringS ringW coreBBox llx lly urx ury pts ring)
ringS = getParamValue(device 'ringS)
ringW = getParamValue(device 'ringW)
coreBBox = getCoreBBox(device)
llx = xCoord( lowerLeft(coreBBox))
lly = yCoord( lowerLeft(coreBBox))
urx = xCoord( upperRight(coreBBox))
ury = yCoord( upperRight(coreBBox))
pts = list(
llx-ringS:lly-ringS ; points on inner edges
urx+ringS:lly-ringS
urx+ringS:ury+ringS
llx-ringS:ury+ringS
llx-ringS:lly-ringS-ringW ; extending to outer edge
llx-ringS-ringW:lly-ringS-ringW ; points on outer edges
llx-ringS-ringW:ury+ringS+ringW
urx+ringS+ringW:ury+ringS+ringW
urx+ringS+ringW:lly-ringS-ringW
llx-ringS:lly-ringS-ringW)
; layer is chosen for its color's visibility
; You can replace the layer names mentioned here with the layer names
; present in your library.
cv = slotValue(device 'cvId)
ring = dbCreatePolygon( cv list("Via2" "drawing") pts)
callNextMethod()
)
)
; This method is called when RING is used on its own.
; Just return a empty box
defmethod(getCoreBBox ((device RING))
list(0:0 0:0)
)
; End of file - RING.ils
; Start of file - WRAP.ils
; Defines a wrapped core class that inheriting both CORE and RING classes
defclass( WRAP (CORE RING)
())
; The draw method for WRAP is just a simple call to callNextMethod and due
; to the specifity of WRAP's superclasses, the draw methods for CORE and RING
; will be called in this order
defmethod(draw ((device WRAP) )
callNextMethod()
)
; End of file - WRAP.ils
; Start of file - genPcell.il
; Code to create a Pcell supermaster for CORE
pcDefinePCell(
list(ddGetObj("PDK_devices") "CORE" "layout")
(
( cyanW "float" 0.6 )
( greenL "float" 0.8 )
( greenW "float" 0.2 )
( cyanL "float" 0.2 )
)
let((pcell)
pcell = makeInstance('CORE)
setPcellParams(pcell pcCellView)
draw(pcell)
)
)
; Code to create a Pcell supermaster for RING.
pcDefinePCell(
list(ddGetObj("PDK_devices") "RING" "layout")
(
( ringW "float" 0.1 )
( ringS "float" 0.1 )
)
let((pcell)
pcell = makeInstance('RING)
setPcellParams(pcell pcCellView)
draw(pcell)
)
)
; Code to create a Pcell supermaster
pcDefinePCell(
list(ddGetObj("PDK_devices") "WRAP" "layout")
(
( ringW "float" 0.1 )
( greenL "float" 0.8 )
( greenW "float" 0.2 )
( cyanL "float" 0.2 )
( cyanW "float" 0.6 )
( ringS "float" 0.1 )
)
let((pcell)
pcell = makeInstance('WRAP)
setPcellParams(pcell pcCellView)
draw(pcell)
)
)
; End of file - genPcell.il
; Start of file - genPcDef.il
; Based on specified class name, lib name, cell name, view name, and draw
; function name to generate Pcell definition file in user specified directory.
; genPcellCodeFromClass(
; s_className t_libName t_cellName t_viewName t_pcFilename t_drawFuncName)
; For example,
; genPcellCodeFromClass(
; 'WRAP "PDK_devices" "WRAP" "layout" "./pcWrap.il" "draw")
procedure( genPcellCodeFromClass(
_className libN cellN viewN filePathName drawFuncName)
let((oport params device str dirpath)
when( !filePathName || filePathName == ""
warn("File path name is empty.\n")
return()
)
str = rindex(filePathName "/")
when( str
dirpath = substring(filePathName 1 strlen(filePathName) - strlen(str))
when( !isDir(dirpath)
warn("Directory( %s ) does not exists.\n")
return()
)
)
oport = outfile(filePathName "w")
fprintf(oport "pcDefinePCell(\n\tlist(ddGetObj(\"%s\") \"%s\" \"%s\")\n"
libN cellN viewN)
; Output parameters section
device = makeInstance(concat(_className))
fprintf(oport "\t(\n")
params = getPcellParams(device)
foreach( param params
case( cadr(param)
("int"
fprintf(oport "\t\t( %s \"int\" %d )\n" car(param) caddr(param))
)
("float"
fprintf(oport "\t\t( %s \"float\" %f )\n" car(param) caddr(param))
)
("string"
fprintf(oport "\t\t( %s \"string\" \"%s\" )\n" car(param) caddr(param))
)
("boolean"
fprintf(oport "\t\t( %s \"string\" %L )\n" car(param) caddr(param))
)
(("ILList" "ilList")
fprintf(oport "\t\t( %s \"ILList\" %L )\n" car(param) caddr(param))
)
(t
warn("Unsupported type %s on parameter %s skipped\n" cadr(param) car(param))
)
)
)
fprintf(oport "\t)\n")
; Output the standard Pcell code section
fprintf(oport "\tlet((pcell)\n")
fprintf(oport "\t\tpcell = makeInstance('%s)\n" _className)
fprintf(oport "\t\tsetPcellParams(pcell pcCellView)\n")
fprintf(oport "\t\t%s(pcell)\n" drawFuncName)
fprintf(oport "\t)\n")
fprintf(oport ")\n")
close(oport)
; Auto generate Pcell superMaster by user defined Pcell class
; load(filePathName)
)
)
; End of file - genPcDef.il
Return to top