PCell Generators
From EDA Wiki
Jump to navigationJump to search
PCell generators are created to draw layouts of various circuit components. These are written in SKILL and can be modified based on a given technology or specifications. See this How to install a PCell for instructions on how to install a PCell generator into the Cadence environment.
Capacitor PCell
This PCell generator draws a capacitor in AMI C5N 0.5u technology using the scalable CMOS rules in the NCSU CDK.
pcDefinePCell(list(ddGetObj("AMI_06_Layout") "cap" "layout") ((Width float 2.4) (Length float 2.4) (numRows int 1) (numCols int 1) (DrawPOLY1 boolean "TRUE") (DrawM1 boolean "TRUE") (AbutM1 boolean "TRUE") (ShieldWithM2 boolean "FALSE") (ShieldWithNWELL boolean "FALSE") (CapSeparation float 0.9) ) let( (Width Length numRows numCols DrawPOLY1 DrawM1 AbutM1 ShieldWithM2 ShieldWithNWELL CapSeparation pcLib pcParameters pcParamProp pcLayer pcPurpose pcList Ox Oy stepX stepY cntStepX cntStepY totalContactsX totalContactsY POLY2W PLY2SP P2EOCT BCEOTC CNTW CNTSP layerM1 layerM2 layerPOLY1 layerPOLY2 layerCNT layerNFIELD layerTUB layerCAPM ) ; Technology Rules POLY2W = 2.4 ; Min POLY2 Width PLY2SP = 0.90 ; Min POLY2 SPacing P2EOCT = 0.90 ; Min POLY2 Enclosure of CnT (DRC rules do not really tell what this should be) BCEOTC = 1.5 ; Min BotCap plate Enclosure Of TopCap plate CNTW = 0.60 ; Min CNT Width CNTSP = 0.90 ; Min CNT Spacing ; Calculations pcLib = pcCellView->lib pcParameters = (pcCellView->parameters)->value Ox = 0.0 Oy = 0.0 ; Get the PCell parameters. pcParamProp = car(exists(prop pcParameters ((prop->name) == "Width"))) Width = pcParamProp->value pcParamProp = car(exists(prop pcParameters ((prop->name) == "Length"))) Length = pcParamProp->value pcParamProp = car(exists(prop pcParameters ((prop->name) == "numRows"))) numRows = pcParamProp->value pcParamProp = car(exists(prop pcParameters ((prop->name) == "numCols"))) numCols = pcParamProp->value pcParamProp = car(exists(prop pcParameters ((prop->name) == "DrawPOLY1"))) DrawPOLY1 = (pcParamProp->value == "TRUE") pcParamProp = car(exists(prop pcParameters ((prop->name) == "DrawM1"))) DrawM1 = (pcParamProp->value == "TRUE") pcParamProp = car(exists(prop pcParameters ((prop->name) == "AbutM1"))) AbutM1 = (pcParamProp->value == "TRUE") pcParamProp = car(exists(prop pcParameters ((prop->name) == "ShieldWithM2"))) ShieldWithM2 = (pcParamProp->value == "TRUE") pcParamProp = car(exists(prop pcParameters ((prop->name) == "ShieldWithNWELL"))) ShieldWithNWELL = (pcParamProp->value == "TRUE") pcParamProp = car(exists(prop pcParameters ((prop->name) == "CapSeparation"))) CapSeparation = pcParamProp->value ; Check the parameter values and make adjustments if((Length < POLY2W) then Length = POLY2W) if((Width < POLY2W) then Width = POLY2W) if((CapSeparation < PLY2SP) then CapSeparation = PLY2SP) stepX = Width + CapSeparation stepY = Length + CapSeparation C5N = nil SCMOS = t ; Define layer constants if((C5N == t) then layerM1 = 9 layerM2 = 11 layerCNT = 8 layerPOLY1 = 4 layerPOLY2 = 37 ; 26 layerNFIELD = 3 layerTUB = 1 layerCAPM = 56 else if((SCMOS == t) then layerM1 = 45 layerM2 = 50 layerCNT = 59 layerPOLY1 = 35 layerPOLY2 = 37 layerNFIELD = nil layerTUB = 12 layerCAPM = nil )) ; Draw POLY1 for the bottom plate of the capacitor. if((DrawPOLY1 == t) then pcLayer = layerPOLY1 pcPurpose = "drawing" pcList = list((Ox-BCEOTC:Oy+BCEOTC) (Ox+(numCols-1)*stepX+Width+BCEOTC:Oy-(numRows-1)*stepY-Length-BCEOTC)) pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList) ) ; Draw CAPM pseudo layer. if((layerCAPM != nil) then pcLayer = layerCAPM pcPurpose = "drawing" pcList = list((Ox-BCEOTC:Oy+BCEOTC) (Ox+(numCols-1)*stepX+Width+BCEOTC:Oy-(numRows-1)*stepY-Length-BCEOTC)) pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList) ) ; Draw POLY2 for the top plate of the capacitor. pcLayer = layerPOLY2 pcPurpose = "drawing" for(j 0 numRows-1 for(i 0 numCols-1 pcList = list((Ox+i*stepX:Oy-j*stepY) (Ox+i*stepX+Width:Oy-j*stepY-Length)) pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList) ) ) ; Draw M1 over the top plate of the capacitor. if((DrawM1 == t) then pcLayer = layerM1 pcPurpose = "drawing" if((AbutM1 == t) then pcList = list((Ox:Oy) (Ox+(numCols-1)*stepX+Width:Oy-(numRows-1)*stepY-Length)) pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList) else for(j 0 numRows-1 for(i 0 numCols-1 pcList = list((Ox+i*stepX:Oy-j*stepY) (Ox+i*stepX+Width:Oy-j*stepY-Length)) pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList) ) ) ) ) ; Draw M2 over the capacitor for shielding. if((ShieldWithM2 == t) then pcLayer = layerM2 pcPurpose = "drawing" pcList = list((Ox-BCEOTC:Oy+BCEOTC) (Ox+(numCols-1)*stepX+Width+BCEOTC:Oy-(numRows-1)*stepY-Length-BCEOTC)) pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList) ) ; Draw NWELL under the capacitor for shielding. if((ShieldWithNWELL == t) then pcLayer = layerTUB pcPurpose = "drawing" pcList = list((Ox-BCEOTC:Oy+BCEOTC) (Ox+(numCols-1)*stepX+Width+BCEOTC:Oy-(numRows-1)*stepY-Length-BCEOTC)) pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList) if((layerNFIELD != nil) then pcLayer = layerNFIELD pcPurpose = "drawing" pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList) ) ) ; Draw contacts from POLY2 to M1. pcLayer = layerCNT pcPurpose = "drawing" for(j 0 numRows-1 for(i 0 numCols-1 cntStepX = cntStepY = CNTW + CNTSP totalContactsX = fix((Width-(2*P2EOCT+CNTW)+cntStepX+0.00001)/cntStepX) offsetX = (Width - (cntStepX*(totalContactsX-1.0)+(2*P2EOCT+CNTW))) / 2.0 totalContactsY = fix((Length-(2*P2EOCT+CNTW)+cntStepY+0.00001)/cntStepY) offsetY = (Length - (cntStepY*(totalContactsY-1.0)+(2*P2EOCT+CNTW))) / 2.0 for(k 0 totalContactsX-1 for(l 0 totalContactsY-1 pcList = list((Ox+P2EOCT+i*stepX+k*cntStepX+offsetX:Oy-P2EOCT-j*stepY-l*cntStepY-offsetY) (Ox+P2EOCT+CNTW+i*stepX+k*cntStepX+offsetX:Oy-P2EOCT-CNTW-j*stepY-l*cntStepY-offsetY)) pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList) ) ) ) ) t ) )