blob: 23527c2f5502f84cdc3afe4ec99b33621998a44f [file] [log] [blame]
;;;
;;; $Id: CDFcallbacks.il 10 2018/06/18 21:10:40 GMT jszemiot Exp $
;;;
;;; CDFcallbacks.il
;;;
;;; Copyright (c) 1998 by Cypress Semiconductor
;;;
;;; Date : Aug 04, 1998
;;; Author: David Roberts/CAD (dlr) @ CSDC
;;;
;;; Description:
;;;
;;; Revision History:
;;; dlr 08/10/98 Adding NPN and PNP callbacks for current monitoring
;;; gtc 08/11/98 Adding CDFfetGetFetDevice, CDFfetSetDefaultLength,
;;; and CDFfetToggleNative
;;; akr 08/20/98 added resistor models for met4 and met5 met6
;;; gtc 08/28/98 fixing where it rounded the length of R driven resistors
;;; gtc 09/04/98 added CDFcreateHideProps and CDFcreateAsymProps & called
;;; them in the fet & logic callbacks
;;; dlr 10/06/98 Adding CDFverilogTrTfDoneCheck to the logic elements
;;; dgn 10/22/98 Changed calculation of rl/R for subckt res
;;; dgn 11/05/98 Changed CDFfetSetDefaultLength() to leave property value if correct
;;; dgn 12/02/98 Tweaked constant width resistors callback
;;; akr 12/08/98 Adding Capability to select cap model on rescap device
;;; gtc 01/15/99 added functions to check range of mfactor
;;; gtc 02/08/99 adding check for "isParasitic" property on resistors
;;; gtc 02/23/99 added CDFsetCapSpaceProps
;;; gtc 03/08/99 first entry in a cap's spacing may not be min space
;;; gtc 03/22/99 rcon updates
;;; dgn 05/07/99 Added threshold types (ttype) to CDFfetGetFetDevice()
;;; axg 08/25/99 Added CDFsetRconModelInfo, CDFrconInit, CDFrconDone
;;; gtc 08/31/99 Updated CDFsetRconModelInfo to use new TECHgetRconDevices
;;; gtc 08/31/99 tweaks for rcon
;;; dgn 10/13/99 Updates for sonos
;;; dgn 10/19/99 Added CDFgetToggleSonos() to ensure correct vtype
;;; xgs 11/11/99 Added capability to choose cap segments for rescap
;;; dgn 01/13/99 Fixed CDFgetCapTechrepDevice() to handle user def. rescap
;;; gtc 02/29/00 added manual spice model specification for fets
;;; akg 02/29/00 added latch property for sonos fet
;;; akg 03/30/00 added esd property for fets - changed to deepNwell (04/17)
;;; gtc 08/24/00 AEL updates38424
;;; kgr 08/25/00 Modified CDFfetToggleSonos to force all sonos devices to have deepNwell true
;;; gtc 09/01/00 updated fet m-factor check to enforce >= 1
;;; mzy 09/11/00 added pwell resistor support (respw)
;;; gtc 09/20/00 added CDFcswDone
;;; gtc 09/26/00 duct tape kludge for csw_p callback
;;; gtc 09/26/00 duct tape kludge for einv_p callback
;;; gtc 09/26/00 tweaking cap callback for setting the spacing values
;;; regarding thinox caps
;;; gtc 10/26/00 added CDFdiodeMethodMap
;;; gtc 11/09/00 added CDFdMM wrapper around CDFdiodeMethodMap
;;; gtc 12/12/00 updating cap2 callback to create/delete the isSubckt prop
;;; gtc 01/29/01 support for AELs in xtor & logic gate widths & lengths
;;; gtc 02/01/01 moved in callback functions from CDFtools, and did a
;;; minor tweak to CDFcapbnCalculateDiodes
;;; gtc 02/15/01 Updates to mfactor check to handle AEL numbers, but it will
;;; insist on it being an integer, not an equation/expression
;;; dxj 02/19/01 Updates for SONOS TDR *G
;;; gtc 03/02/01 fixing asym props when m-factor is a string on logic gates
;;; gtc 03/12/01 Temporarily commenting out dxj's last change until he is
;;; ready to maprel.
;;; Updates to support string/parameterized rw, rl, rm for res
;;; dxj 03/13/01 SONOS TDR *G changes ready for maprel. Putting them back.
;;; gtc 03/13/01 fixed one bug for w,l based resistors
;;; gtc 03/15/01 updates to handle AEL parameters in a couple of more places
;;; gtc 03/16/01 removed bcdiode callback
;;; gtc 03/30/01 absolute caps now delete isSubckt property, and some
;;; elements now use CDFverInit initialiaztion function
;;; gtc 04/06/01 fixed references from cdf vtype and ttype to vtype2, ttype2
;;; gtc 04/09/01 Splitting CDFfetGetFetDevice into two functions: one that
;;; is called from CDF props, another from instance props.
;;; gtc 04/10/01 fixing rescap cw/cl bug when mfactor > 1
;;; gtc 04/10/01 fixed false warning about constant width resistors
;;; gtc 04/11/01 fixed cap of rescap when using R driven resistors
;;; gtc 04/12/01 logic gate subcktMult properties -> m
;;; gtc 04/12/01 updating capbn_b callback to derive either cw or cl when
;;; given a total cap and one dimension
;;; gtc 04/19/01 moving CDFevalString in here
;;; gtc 04/24/01 not doing CDFcommonDone for icecaps; SPR 8788
;;; dxj 04/27/01 Modified nfet device (tsmc25, kept for future use in ram7?)
;;; gtc 05/14/01 enhancements to capbn_b device
;;; gtc 07/27/01 adding capacitor width lookup table support
;;; gtc 08/31/01 adjusting init CDF call for inductor to change the old
;;; "Initial Current" indType to "Normal"
;;; dxj 09/19/01 added code for d17ld-3 flow
;;; lpn 12/11/01 added code for res3
;;; dxj 12/10/01 Added code for T013 flow
;;; cry 01/24/02 Updated npn4 (and pnp4 for free) to allow subckt models
;;; cry 02/21/02 Added CDfmtjInit and CDFmtjDone and CDFmtjCallback
;;; dxj 02/28/02 Allow use of general res device with subckt
;;; gtc 03/27/02 added CDFcalculateCapacitors for cmimc, and rearranged
;;; how it is called for the capbn_b
;;; cry 03/28/02 added ltype (leakage type) to CDFfetDeviceFromParams
;;; may need to add a toggle
;;; gtc 05/03/02 removed lsim features
;;; jtv 05/10/02 updated CDFfetSetDefaultLength to also get default width
;;; gtc 05/10/02 not creating the "hide_" properties anymore.
;;; kgr 05/24/02 Updated CDFnpn4Done to update pnp params based on modelName
;;; gtc 05/28/02 updated capbn_b diode calculations to include nwell
;;; kgr 05/31/02 Added threeTermNetlist, mim3c, and ind3
;;; kgr 06/19/02 Added CDFcmim3cDone, CDFcapbn_bDone, and CDFind4Done
;;; kmi 08/02/02 Added CDFfetToggleRam7
;;; kmi 08/23/02 Corrected CDFfetToggleTech() (SPR 13124)
;;; ymx 08/23/02 Added CDFfetToggleC8Q
;;; gtc 11/01/02 Added delta width support for resistor callbacks
;;; dxj 11/12/02 Update T013 callbacks for SPR 13391
;;; gtc 12/17/02 including contact res. in calculation of poly resistors
;;; dxj 02/25/03 T013 ggnmos made legal
;;; dxj 02/27/03 Add metd as a new resType
;;; gtc 03/27/03 Added minimum fet width/length check (optional)
;;; gtc 05/16/03 Added CDFhitCallbacks
;;; cva 06/13/03 c9fp updates ddli/litr parasitic res, diff res3
;;; gtc 08/21/03 Updated minimum fet width/length check when w/l is empty
;;; kmi 08/21/03 Adding CDFfetToggleC9F
;;; cva 09/03/03 added resnw resistor
;;; gtc 11/26/03 fet mfactor callback, resetting to "1" if it is empty
;;; cva 12/11/03 iglv updates lm1/lmcon
;;; kgr 03/22/04 added extendedDrain to fets
;;; gtc 03/31/04 looking at resistor width for width interpolation of caps
;;; gtc 04/09/04 handling isSubckt creation/deletion for fets and diodes
;;; sti 06/02/04 Added CDfmtj5Init and CDFmtj5Done and CDFmtj5Callback
;;; sti 06/28/04 Added CDFfetToggleLvNative
;;; vun 07/01/04 added resnd, respd, and resnw to res3
;;; sti 07/18/04 add Cap_int3
;;; sti 08/15/04 update Cap_int3
;;; akg 09/07/04 added CDFafuseDone
;;; pvn 10/14/04 Added code for gres3 element
;;; pvn 11/12/04 Modified code for gres3 to mimic GR process
;;; gtc 11/17/04 added verilog tr/tf support for einv_p
;;; cva 03/09/05 added isHV hv diff res
;;; dxj 05/26/05 Fix the capbn calculation for variables (SPR 22916)
;;; vun 07/21/05 added refCell and memCell
;;; bae 08/11/05 added CDF functionality for discrete FET models
;;; rnh 08/24/05 Added CDFupdateDiscreteWchoice functionality for layout Pcells.
;;; bae 08/26/05 added CDF functionality for logic gates
;;; bae 09/20/05 updated CDFfetDiscContactsCallback,
;;; added CDFupdateFetDiscContactNum and CDFupdateManualWL
;;; bae 09/23/05 allowed deepNwell to devices other than sonos
;;; rnh 10/06/05 Updated CDFupdateDiscreteWchoice to accept default Width values.
;;; bub 10/06/05 changed ToggleSonos function
;;; bub 10/14/05 added CDFcondiodeDone
;;; rnh 10/20/05 Updated CDFupdateRadioID CDFradioUpdateDiscreteWchoice for radio
;;; button selected devies from the form.
;;; bae 10/28/05 added CDFfetToggleHighVt and updated CDFfetToggleESD
;;; bub 11/04/05 updated CDF for res3
;;; kuc 11/16/05 Added CDFvaractorDone
;;; bae 12/01/05 added CDF functionality/callbacks for discrete pcells
;;; kuc 12/02/05 Added CDFmExtDrainTranDone
;;; txi 12/20/05 Added CDFfetgateresvalue callback. Update CDFupdateFetLengthParameter
;;; and CDFupdateFetWidthParameter callbacks
;;; txi 01/02/06 fixed the bug in CDFfetgateresvalue callback.
;;; bae 01/12/06 Added CDFfetextdCallback and CDFfetextdDone
;;; osd 02/03/06 updated CDFfetToggleHighVt,CDFfetToggleNlowVt
;;; bae 05/04/06 updated CDFupdateFetDiscContactNum, CDFfetDiscContactsCallback
;;; fixed CDFfetToggleNlowVt
;;; bae 05/11/06 added CDFsetFetDeviceParams CDFupdateDeviceInfo
;;; removed CDFfetToggleNative CDFfetToggleLvNative CDFfetToggleNtvNative
;;; CDFfetToggleESD CDFfetToggleNlowVt CDFfetToggleHighVt CDFfetToggleSonos
;;; CDFfetToggleExtendedDrain CDFupdateDiscreteWchoice CDFupdateRadioID
;;; CDFradioUpdateDiscreteWchoice
;;; ipr 07/19/06 fixes related to rfDeviceInfo (SPR 31232)
;;; kuc 07/27/06 updated CDFvaractorDone for new varactor device
;;; bae 09/25/06 added CDFupdateDiscreteFetWL
;;; bae 10/27/06 modified CDFsetFetDeviceParams
;;; bae 03/05/07 updated CDFfetDiscContactsCallback to set offsets if needed
;;; kuc 04/03/07 updated condiode callbacks
;;; cry 04/03/07 updated discrete fet callback code to handle flows without licon/ddlicon
;;; updated resistor code to handle rdl resistors
;;; cry 05/16/07 updates for LOD/WPE and for NRD/NRS (SPR 36742)
;;; vun 06/21/07 updates NRD/NRS
;;; cry 06/21/07 updates for RESCAP3
;;; vun 08/30/07 added CDFefuseDone
;;; cry 09/04/07 RC fix for SPR 38271 and others - ensuring tech lib cells are not renamed.
;;; xba 10/17/07 Updating CDFfetCallback for resetting enableLOD based on hspiceModel.
;;; cry 10/18/07 updates for absolute resistor with a model,
;;; added isSubckt setting to CDFcmim3cDone so CDFhitCallbacks can set it
;;; kuc 10/25/07 added accurate calculations for varactors in CDFcalculateCapacitors
;;; cry 10/26/07 added isSubckt to CDFcapbn_bDone, updated how it's done in CDFcmim3cDone
;;; xba 11/20/07 Fxing calculateCapacitors for varactors. SPR 40756
;;; kuc 12/12/07 updated number of contacts calculation when using parameterized w
;;; kuc 01/22/08 added Mult callback
;;; kuc 01/24/08 added deltaL for resistors
;;; osd 04/17/08 added vppcap
;;; kuc 04/22/08 added CDFconstantCcap2Callback, CDFgetCapSpaceProps,
;;; CDFgetCapWidthProps, CDFinterpolate
;;; kuc 08/11/08 fixed CDFconstantCcap2Callback to handle parameterized inputs
;;; vun 12/05/08 fixed cap_int3 and vppcap cap display.
;;; cva 04/15/09 added callback for pnp4 to use userDefined model
;;; osd 08/14/09 added callback for npn4 to use userDefined model
;;; vun 08/21/09 added reslocsub
;;; cry 12/15/09 renamed CDFinterpolate to CDFinterpolateS to avoid conflict with CDFlabels (SPR 61979)
;;;
(putpropqq CDFcallbacks "$Id: CDFcallbacks.il 10 2018/06/18 21:10:40 GMT jszemiot Exp $" SCCS)
;;;
;;; CDFsetPnp4DeviceParams --
;;; This function will set the device parameters based on the techrep fet definition for the selected model
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFsetPnp4DeviceParams (cellName "t")
(let (thePNPdevice)
(cond
((and cdfgData~>hspiceModelMenu (equal cdfgData~>hspiceModelMenu~>value "userDefined"))
;;manualSpiceModel is always defined and should be true when model selection is "userDefined"
cdfgData->manualSpiceModel->value = t
)
(t
;; get the device that matches the hspiceModel as defined in TECHrep
(setq thePNPdevice cdfgData->hspiceModelMenu->value)
cdfgData->modelName->value = cdfgData~>hspiceModelMenu~>value
;;manualSpiceModel is always defined and should be false when model selection is not "userDefined"
cdfgData->manualSpiceModel->value = nil
(unless thePNPdevice
(warn "CDFsetPNP4DeviceParams: the %L model is defined in TECHrep \n" cdfgData~>hspiceModelMenu~>value)
)
)
)
;;Update the device information field based on the new model selection
(CDFupdateDeviceInfo cellName)
)
)
;;;
;;; CDFsetFetDeviceParams --
;;; This function will set the device parameters based on the techrep fet definition for the selected model
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFsetFetDeviceParams (cellName "t")
(let (theFetDevice (fetTypes '(vtype ttype ltype))
(fetPropNames '(sonos latch ptype native lvNative ntvNative deepNwell extendedDrain nlowVt highVt
pullType array isSubckt isESD rfDeviceInfo enableLOD))
)
(when (and (nequal cdfgData~>topography~>value "normal") cdfgData~>hspiceModelMenu)
(warn "CDFsetFetDeviceParams: Topographies are not supported in TECHrep \n")
(warn "CDFsetFetDeviceParams: Forcing model to userDefined \n")
(warn "CDFsetFetDeviceParams: Please type model in \"Spice model name\" field \n")
cdfgData~>hspiceModelMenu~>value = "userDefined"
)
(cond
((and cdfgData~>hspiceModelMenu (equal cdfgData~>hspiceModelMenu~>value "userDefined"))
;;manualSpiceModel is always defined and should be true when model selection is "userDefined"
cdfgData->manualSpiceModel->value = t
;;manualWL is only defined for discrete fets
(when (cdfgData~>manualWL) cdfgData~>manualWL~>value = t)
;;When userDefined models are used, the W/L menus should be disabled and manual entry of W/L is required
(CDFupdateManualWL)
)
(t
;; get the device that matches the hspiceModel as defined in TECHrep
(setq theFetDevice (TECHgetDeviceWithModel cellName cdfgData~>hspiceModelMenu~>value))
;;manualSpiceModel is always defined and should be false when model selection is not "userDefined"
cdfgData->manualSpiceModel->value = nil
;;manualWL is only defined for discrete fets
(when (cdfgData~>manualWL) cdfgData~>manualWL~>value = nil)
(unless theFetDevice
(warn "CDFsetFetDeviceParams: the %L model is defined in TECHrep \n" cdfgData~>hspiceModelMenu~>value)
)
(foreach fetType fetTypes
(setq typeValue (TECHgetDeviceParam theFetDevice fetType))
;;For some reason the types' names differ between TECHrep and CDFs
;;CDFs has types with a "2" appended to the end of the symbol
;;i.e. TECHrep has vtype while CDFs has vtype2
(when (get cdfgData (concat fetType '2))
(putprop (get cdfgData (concat fetType '2)) typeValue 'value)
)
)
(foreach propName fetPropNames
(setq propValue (TECHgetDeviceParam theFetDevice propName))
(when (get cdfgData propName)
(putprop (get cdfgData propName) propValue 'value)
)
)
)
);; end of cond
;;Update the device information field based on the new model selection
(CDFupdateDeviceInfo cellName)
;;Update the widths and length values at this stage
(CDFupdateFetLengthParameter (strcat (concat cdfgData~>hspiceModelMenu~>value "_l")))
)
)
;;;
;;; CDFfetDeviceFromParams --
;;; This function will return the techrep fet device for the fet described
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFfetDeviceFromParams
;; these parameters are all the things it uses to match against the
;; techrep device
(cellName vtype nlowVt highVt isESD native lvNative ntvNative ttype sonos ptype
latch deepNwell extendedDrain pullType array ltype rfDeviceInfo)
(let (fetDevices targetVoltage targetNlowVt targetESD targetNative targetLvNative targetNtvNative
targetHighVt targetThreshold targetLeakage targetdnw targetArray targetExtendedDrain targetRfFet)
;; first, get the devices that match the cellname
(setq fetDevices (TECHgetDevice ?cellName cellName))
;; second, match the voltage type
(setq targetVoltage vtype)
(when (equal "normal" targetVoltage)
(setq targetVoltage nil)
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'vtype) targetVoltage)
)
)
;; third, match the native boolean
(setq targetNative
;; double negative to get a t or a nil
(null (null (and native (nequal "FALSE" native))))
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'native) targetNative)
)
)
;; thirdB, match the lvNative boolean
(setq targetLvNative
;; double negative to get a t or a nil
(null (null (and lvNative (nequal "FALSE" lvNative))))
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'lvNative) targetLvNative)
)
)
;; thirdC, match the ntvNative boolean
(setq targetNtvNative
;; double negative to get a t or a nil
(null (null (and ntvNative (nequal "FALSE" ntvNative))))
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'ntvNative) targetNtvNative)
)
)
;; fourth, match the threshold type
(setq targetThreshold ttype)
(when (equal "normal" targetThreshold)
(setq targetThreshold nil)
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'ttype) targetThreshold)
)
)
;; fifth, match the ptype & latch type
(cond
((and sonos (nequal "FALSE" sonos))
(setq targetPtype ptype)
(setq latchType nil)
)
((and latch (nequal "FALSE" latch))
(setq latchType (null (null (and latch (nequal "FALSE" latch)))))
(setq targetPtype ptype)
)
(t
(setq targetPtype nil)
(setq latchType nil)
)
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'ptype) targetPtype)
)
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'latch) latchType)
)
)
;; sixth, match deep nwell property
(setq targetdnw
;; double negative to get a t or a nil
(null (null (and deepNwell (nequal "FALSE" deepNwell))))
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'deepNwell) targetdnw)
)
)
;; seventh, match the npass and npulldown devices (pullType property)
(setq targetPullType pullType)
(when (equal "normal" targetPullType)
(setq targetPullType nil))
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'pullType) targetPullType)
)
)
;; eighth, match the array fet devices
(setq targetArray
(null (null (and array (nequal "FALSE" array))))
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'array) targetArray)
)
)
;; ninth, match the leakage type
(setq targetLeakage ltype)
(when (equal "normal" targetLeakage)
(setq targetLeakage nil)
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'ltype) targetLeakage)
)
)
;; tenth, match the extendedDrain boolean
(setq targetExtendedDrain
;; double negative to get a t or a nil
(null (null (and extendedDrain (nequal "FALSE" extendedDrain))))
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'extendedDrain) targetExtendedDrain)
)
)
;; eleventh, match the nlowVt boolean
(setq targetNlowVt
;; double negative to get a t or a nil
(null (null (and nlowVt (nequal "FALSE" nlowVt))))
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'nlowVt) targetNlowVt)
)
)
;; twelveth, match the isESD boolean
(setq targetESD
;; double negative to get a t or a nil
(null (null (and isESD (nequal "FALSE" isESD))))
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'isESD) targetESD)
)
)
;; thirteenth, match the highVt boolean
(setq targetHighVt
;; double negative to get a t or a nil
(null (null (and highVt (nequal "FALSE" highVt))))
)
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'highVt) targetHighVt)
)
)
;;fourteenth, match an rf fet
;;an RF fet is distinguished by the presence of string
;;which is the modelname of the RF Fet.
;;This string is in the RF Fet field of the
;;CDFproperty of the FET
;;This string is matched against the rfDeviceInfo stored in the
;;techrep to pick up the correct type of RFdevice.
(when (equal rfDeviceInfo "") (setq rfDeviceInfo nil))
(setq fetDevices
(setof x fetDevices
(equal (TECHgetDeviceParam x 'rfDeviceInfo) rfDeviceInfo)
)
)
(cond
((null fetDevices)
(warn "CDFfetDeviceFromParams: failed to match CDF to a techrep device\n")
nil
)
((greaterp (length fetDevices) 1)
(warn "CDFfetDeviceFromParams: multiple matches of CDF to techrep devices.\n")
(warn "CDFfetDeviceFromParams: picking first one found\n")
(car fetDevices)
)
(t (car fetDevices))
)
)
)
;;;
;;; CDFfetGetFetDevice --
;;; This function will get the CY techrep device for a fet for the current
;;; CDF as defined by cdfgData
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFfetGetFetDevice (cellName "t")
(CDFfetDeviceFromParams cellName
cdfgData->vtype2->value
cdfgData->nlowVt->value
cdfgData->highVt->value
cdfgData->isESD->value
cdfgData->native->value
cdfgData->lvNative->value
cdfgData->ntvNative->value
cdfgData->ttype2->value
cdfgData->sonos->value
cdfgData->ptype->value
cdfgData->latch->value
cdfgData->deepNwell->value
cdfgData->extendedDrain->value
cdfgData->pullType->value
cdfgData->array->value
cdfgData->ltype2->value
cdfgData->rfDeviceInfo->value
)
)
;;; ;;; CDFfetDeviceFromDbid --
;;; This is very similar to CDFfetGetFetDevice, except that it will get the
;;; CY techrep device for a fet for a given instance.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFfetDeviceFromDbid (dbid cellName "dt")
(CDFfetDeviceFromParams cellName
dbid~>vtype
dbid~>nlowVt
dbid~>highVt
dbid~>isESD
dbid~>native
dbid~>lvNative
dbid~>ntvNative
dbid~>ttype
dbid~>sonos
dbid~>ptype
dbid~>latch
dbid~>deepNwell
dbid~>extendedDrain
dbid~>pullType
dbid~>array
dbid~>ltype
dbid~>rfDeviceInfo
)
)
;;;
;;; CDFfetSetDefaultLength --
;;; This function will set the length/width to the default minimum gate
;;; length/width as defined by the techrep device for the fet. This is
;;; called when changing the voltage type property.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFfetSetDefaultLength (cellName "t")
;; property based on isESD type
(CDFfetToggleESD)
(let (fetDevice fetLength fetWidth discreteWLs)
(setq fetDevice (CDFfetGetFetDevice cellName))
(setq discreteWLs (TECHgetDeviceParam fetDevice 'discreteWLs))
(when fetDevice
(setq fetLength (aelNumber cdfgData->l->value))
(when (numberp fetLength)
(cond
(discreteWLs
(setq fetLength (TECHgetDeviceParam fetDevice 'minGateLength))
)
(t
(setq fetLength (max fetLength (TECHgetDeviceParam fetDevice
'minGateLength)))
)
)
(cond
((equal "float" cdfgData->l->paramType)
cdfgData->l->value = fetLength
)
((equal "string" cdfgData->l->paramType)
cdfgData->l->value = (sprintf nil "%g" fetLength)
)
)
)
(setq fetWidth (aelNumber cdfgData->w->value))
(when (numberp fetWidth)
(cond
(discreteWLs
(setq fetWidth (TECHgetDeviceParam fetDevice 'minGateWidth))
)
(t
(setq fetWidth (max fetWidth (TECHgetDeviceParam fetDevice
'minGateWidth)))
)
)
(cond
((equal "float" cdfgData->w->paramType)
cdfgData->w->value = fetWidth
)
((equal "string" cdfgData->w->paramType)
cdfgData->w->value = (sprintf nil "%g" fetWidth)
)
)
)
)
)
)
;;;
;;; CDFupdateGateLengthParameter --
;;;
;;; Input: The name of the discrete length parameter to be updated
;;; Output:
;;; Globals:
;;; Side Effects: Updates the golden W and L values, and rederives the Area and Perimeter
;;; Return:
;;;
(defun CDFupdateGateLengthParameter (Ln Wn nLength @key NSCprop NDCprop)
(let (lengthValue lengthChoices lengthIndex nWidth priorLengthValue)
(setq priorLengthValue (get (get cdfgData Ln) 'value))
(putprop (get cdfgData Ln) (get (get cdfgData nLength) 'value) 'value)
(setq lengthValue (get (get cdfgData nLength) 'value))
(setq lengthChoices (get (get cdfgData nLength) 'choices))
(setq lengthIndex (difference (length lengthChoices) (length (member lengthValue lengthChoices))))
;;The proper modelName_l=Value_w and the golden w needs to be updated.
(setq nWidth (strcat (concat nLength lengthIndex "_w")))
;;Updating the golden W
(putprop (get cdfgData Wn) (get (get cdfgData nWidth) 'value) 'value)
;;If the length value has been updated, then the width would be updated and
;;therefore, we have to update NSC & NDC
(when (and (TECHisPropSet doNrdNrsOhms) (TECHgetProp doNrdNrsOhms))
(unless (equal priorLengthValue lengthValue)
(CDFupdateFetDiscContactNum ?wProp Wn ?NSCprop NSCprop ?NDCprop NDCprop)
)
)
)
)
;;;
;;; CDFupdateFetLengthParameter --
;;;
;;; Input: The name of the discrete length parameter to be updated
;;; Output:
;;; Globals:
;;; Side Effects: Updates the golden W and L values, and rederives the Area and Perimeter
;;; Return:
;;;
(defun CDFupdateFetLengthParameter (nLength)
(let (fetDevice discreteWLs priorLengthValue lengthValue lengthChoices nWidth)
priorLengthValue = cdfgData~>l->value
(unless (cdfgData~>manualWL~>value)
cdfgData~>l->value = (get (get cdfgData nLength) 'value)
(setq lengthValue cdfgData~>l->value)
(setq lengthChoices (get (get cdfgData nLength) 'choices))
(setq lengthIndex (difference (length lengthChoices) (length (member lengthValue lengthChoices))))
;;The proper modelName_l=Value_w and the golden w needs to be updated.
(setq nWidth (strcat (concat nLength lengthIndex "_w")))
;;Updating the golden W
cdfgData~>w->value = (get (get cdfgData nWidth) 'value)
(when cdfgData~>totalW
cdfgData~>totalW->value = (sprintf nil "%L" (evalstring (get (get cdfgData 'w) 'value)) * (evalstring (get (get cdfgData 'm) 'value)))
)
;;If the length value has been updated, then the width would be updated and
;;therefore, we have to update NSC & NDC
(when (and (TECHisPropSet doNrdNrsOhms) (TECHgetProp doNrdNrsOhms))
(unless (equal priorLengthValue lengthValue)
(CDFupdateFetDiscContactNum)
)
)
;;If the manualWL is turned on then the "w" and "l" callbacks will call CDFderiveAreaAndPerim
(CDFderiveAreaAndPerim cdfgData)
;;update gate resistance value as well
(CDFfetgateresvalue)
)
)
)
;;;
;;; CDFupdateDeviceInfo --
;;;
;;; Input:
;;; Output:
;;; Globals: cdfgData
;;; Side Effects: Updates the device information as defined in TECHrep
;;; Return: String containing the new device information
;;;
(defun CDFupdateDeviceInfo (cellName)
(let (theDevice theDeviceInfo)
(cond
((equal cdfgData~>hspiceModelMenu~>value "userDefined")
cdfgData~>deviceInfo~>value = "user defined model"
)
(t
(setq theDevice (TECHgetDeviceWithModel cellName cdfgData~>hspiceModelMenu~>value))
(setq theDeviceInfo (TECHgetDeviceParam theDevice 'deviceInfo))
cdfgData~>deviceInfo~>value = (or theDeviceInfo "No info available")
)
)
)
)
;;;
;;; CDFupdateLdisplay --
;;;
;;; Input: The name of the discrete length parameter to be display, and the cellName (i.e. nfet)
;;; Output:
;;; Globals:
;;; Side Effects: Toggles the proper length parameter to be displayed and calls CDFupdateFetLengthParameter
;;; Return:
;;;
(defun CDFupdateLdisplay (nLength cellName)
(let (fetDevice hspiceModel modelName)
;;This cannot be a simple parse to prevent mis-reading models that have "_" in their name
;;So, parse using "_" then get rid of the last element which is "l" and rebuild the string
(setq modelName (buildString (reverse (cdr (reverse (parseString nLength "_")))) "_"))
(setq fetDevice (CDFfetGetFetDevice cellName))
;; get the correct hspice model from the technology representation
(setq hspiceModel (TECHgetDeviceParam fetDevice 'hspiceModel))
(when (equal modelName hspiceModel)
;;Need to update the Golden "l" parameter every time the length is updated
(CDFupdateFetLengthParameter nLength)
)
(and (equal modelName hspiceModel) !(cdfgData~>manualWL~>value))
)
)
;;;
;;; CDFupdateFetWidthParameter --
;;;
;;; Input: The name of the discrete width parameter to be updated
;;; Output:
;;; Globals:
;;; Side Effects: Rederives the Area and Perimeter, and defaults NDC and NSC parameters to max
;;; Return:
;;;
(defun CDFupdateFetWidthParameter (nWidth)
(unless (cdfgData~>manualWL~>value)
cdfgData~>w->value = (get (get cdfgData nWidth) 'value)
(when (and (get cdfgData nWidth) (get cdfgData 'm))
(when cdfgData~>totalW
cdfgData~>totalW->value = (sprintf nil "%L" (evalstring (get (get cdfgData 'w) 'value)) * (evalstring (get (get cdfgData 'm) 'value)))
)
)
;;If the manualWL is turned on then the "w" and "l" callbacks will call CDFderiveAreaAndPerim
(CDFderiveAreaAndPerim cdfgData)
(CDFfetgateresvalue)
)
(when (and (TECHisPropSet doNrdNrsOhms) (TECHgetProp doNrdNrsOhms))
(CDFupdateFetDiscContactNum)
)
)
;;;
;;; CDFupdateWdisplay --
;;;
;;; Input: The model name, the value of the discrete length parameter, and the cellName (i.e. nfet)
;;; Output:
;;; Globals:
;;; Side Effects: displays the proper width parameter
;;; Return:
;;;
(defun CDFupdateWdisplay (modelName nLengthValue cellName)
(let (fetDevice hspiceModel widthString widthFunc nWidthValue)
(setq fetDevice (CDFfetGetFetDevice cellName))
;; get the correct hspice model from the technology representation
(setq hspiceModel (TECHgetDeviceParam fetDevice 'hspiceModel))
(and
!(cdfgData~>manualWL~>value)
(equal nLengthValue cdfgData->l->value)
(equal modelName hspiceModel))
)
)
;;;
;;; CDFupdateManualWL --
;;;
;;; Input: The model name, the value of the discrete length parameter, and the cellName (i.e. nfet)
;;; Output:
;;; Globals:
;;; Side Effects: displays the proper width parameter
;;; Return:
;;;
(defun CDFupdateManualWL ()
;;When the model is manually specified, then all properties that
;;are model specific should be reset to nil
;;i.e. "native" is model specific but "deepNwell" may not necessarily be so
(when (and (cdfgData->manualWL) (cdfgData->manualSpiceModel->value))
cdfgData->manualWL->value = t
(when cdfgData->manualWL->value
(when (and cdfgData->sonos cdfgData->sonos->value)
cdfgData->sonos->value = nil
)
(when (and cdfgData->deepNwell cdfgData->deepNwell->value)
cdfgData->deepNwell->value = nil
)
(when (and cdfgData->lvNative cdfgData->native->value)
cdfgData->lvNative->value = nil
)
(when (and cdfgData->native cdfgData->native->value)
cdfgData->native->value = nil
)
(when (and cdfgData->ntvNative cdfgData->native->value)
cdfgData->ntvNative->value = nil
)
(when (and cdfgData->nlowVt cdfgData->nlowVt->value)
cdfgData->nlowVt->value = nil
)
(when (and cdfgData->highVt cdfgData->highVt->value)
cdfgData->highVt->value = nil
)
)
)
)
;;;
;;; CDFupdateTranModelParameter --
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects: model name parameter is updated and CDFupdateTranLengthParameter is called
;;; Return:
;;;
(defun CDFupdateTranModelParameter (cdfgData)
(let (Lparam modelNameParam modelNameValue)
;;The model name needs to be determined based on the
;;idLayer and modelName parameter values
(setq modelNameParam cdfgData~>idLayer->value)
(setq modelNameValue (get (get cdfgData modelNameParam) 'value))
(setq Lparam (strcat modelNameValue "_l"))
;;Update the L and W values
(CDFupdateTranLengthParameter cdfgData Lparam)
)
)
;;;
;;; CDFupdateTranModelDisplay --
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects: Turns the display on for the matching model parameter based on
;;; the selection of the idLayer. Updates the value of model parameter.
;;; Return:
;;;
(defun CDFupdateTranModelDisplay (cdfgData idLayerName)
(when (equal idLayerName cdfgData~>idLayer->value)
;;Need to update the model name every time the idLayer is updated
(CDFupdateTranModelParameter cdfgData)
)
(equal idLayerName cdfgData~>idLayer->value)
)
;;;
;;; CDFupdateTranLengthParameter --
;;;
;;; Input: The name of the discrete length parameter to be updated
;;; Output:
;;; Globals:
;;; Side Effects: Updates the golden W and L values
;;; Return:
;;;
(defun CDFupdateTranLengthParameter (cdfgData nLength)
(let (lengthValue lengthChoices nWidth)
;;The value in the "l" field must be of dataType float
cdfgData~>l->value = (aelNumber (get (get cdfgData nLength) 'value))
(setq lengthValue (get (get cdfgData nLength) 'value))
(setq lengthChoices (get (get cdfgData nLength) 'choices))
(setq lengthIndex (difference (length lengthChoices) (length (member lengthValue lengthChoices))))
;;The proper modelName_l=Value_w and the golden w needs to be updated.
(setq nWidth (strcat (concat nLength lengthIndex "_w")))
;;Updating the golden W
cdfgData~>w->value = (aelNumber (get (get cdfgData nWidth) 'value))
)
)
;;;
;;; CDFupdateTranLdisplay --
;;;
;;; Input: The name of the discrete length parameter to be display
;;; Output:
;;; Globals:
;;; Side Effects: Toggles the proper length parameter to be displayed and
;;; calls CDFupdateTranLengthParameter
;;; Return:
;;;
(defun CDFupdateTranLdisplay (cdfgData nLength)
(let (nLengthModelName modelParamName modelName)
;;This cannot be a simple parse to prevent mis-reading idLayers that have "_" in their name
;;So, parse using "_" then get rid of the last element which is "l" and rebuild the string
(setq nLengthModelName (buildString (reverse (cdr (reverse (parseString nLength "_")))) "_"))
(setq modelParamName cdfgData~>idLayer->value)
(setq modelName (get (get cdfgData modelParamName) 'value))
(when (equal modelName nLengthModelName)
;;Need to update the Golden "l" parameter every time the length is updated
(CDFupdateTranLengthParameter cdfgData nLength)
)
(equal modelName nLengthModelName)
)
)
;;;
;;; CDFupdateTranWidthParameter --
;;;
;;; Input: The name of the discrete width parameter to be updated
;;; Output:
;;; Globals:
;;; Side Effects: Updates the golden W
;;; Return:
;;;
(defun CDFupdateTranWidthParameter (cdfgData nWidth)
cdfgData~>w->value = (aelNumber (get (get cdfgData nWidth) 'value))
)
;;;
;;; CDFupdateTranWdisplay --
;;;
;;; Input: The model name, the value of the discrete length parameter
;;; Output:
;;; Globals:
;;; Side Effects: displays the proper width parameter
;;; Return:
;;;
(defun CDFupdateTranWdisplay (cdfgData modelName nLengthValue)
(let (modelParamName modelNameValue)
(setq modelParamName cdfgData~>idLayer->value)
(setq modelNameValue (get (get cdfgData modelParamName) 'value))
(and
(equal (aelNumber nLengthValue) cdfgData->l->value)
(equal modelName modelNameValue))
)
)
;;;
;;; CDFupdateFetDiscContactNum --
;;; This function checks that the number of conacts is a valid entry.
;;; If the entered value is invalid, the parameters will be reset to the default value.
;;; Input:
;;; Output: Updates the number of the Drain and Source contacts based on the Width of the FET
;;; Globals:
;;; Side Effects: NDC and NSC parameters will be updated
;;; Return:
;;;
(defun CDFupdateFetDiscContactNum (@key (wProp 'w) (NSCprop 'NSC) (NDCprop 'NDC))
(let (fetWidth fetWidthEff contactNum contactWidth contactSpace contactEnclosure contactPitch contactLayer
(wp (get cdfgData wProp)) (NDCp (get cdfgData NDCprop)) (NSCp (get cdfgData NSCprop))
)
(cond
((TECHresolveLayer "licon1")
(setq contactLayer "licon1")
)
((TECHresolveLayer "ddlicon1")
(setq contactLayer "ddlicon1")
)
((TECHresolveLayer "mcon")
(setq contactLayer "mcon")
)
(t
(error "CDFupdateFetDiscContactNum: unable to resolve contact layer for discrete fets..\n")
)
)
(setq contactWidth (TECHgetRuleWith "minWidth" contactLayer))
(unless contactWidth
(error "CDFupdateFetDiscContactNum: %s width must be defined in TECHrep using minWidth parameter" contactLayer))
(setq contactSpace (TECHgetRuleWith "minSpacing" contactLayer))
(unless contactSpace
(error "CDFupdateFetDiscContactNum: %s space must be defined in TECHrep using minSpace parameter" contactLayer))
(setq contactEnclosure
(TECHgetRuleWith "minEnclosureAdj" "diff" contactLayer))
(unless contactEnclosure
(error "CDFupdateFetDiscContactNum: %s enclosure by diff must be defined in TECHrep using minSpace parameter" contactLayer))
(setq contactPitch (plus contactWidth contactSpace))
(setq fetWidth (aelNumber (get wp 'value)))
(cond
((and (numberp (aelNumber fetWidth)) (and (TECHisPropSet doNrdNrsOhms) (TECHgetProp doNrdNrsOhms)))
(setq fetWidthEff (difference (plus fetWidth contactSpace) (times 2.0 contactEnclosure)))
(setq contactNum (fix (plus (quotient fetWidthEff contactPitch) 1e-6)))
(putprop NSCp (sprintf nil "%d" contactNum) 'value)
(putprop NDCp (sprintf nil "%d" contactNum) 'value)
)
(t ;;if the width is parameterized then give equation for contacts
(setq fetWidth (get wp 'value))
(setq fetWidth (strcat "(" fetWidth ")"))
(setq fetWidthEff `(difference (plus ,fetWidth ,contactSpace) (times 2.0 ,contactEnclosure)))
(setq contactNum `(int (quotient ,fetWidthEff ,contactPitch)))
(putprop NDCp (sprintf nil "%s" (SCHprefixToInfix contactNum)) 'value)
(putprop NSCp (sprintf nil "%s" (SCHprefixToInfix contactNum)) 'value)
)
)
)
)
;;;
;;; CDFfetDiscContactsCallback --
;;; This function checks that the number of conacts is a valid entry.
;;; If the entered value is invalid, the parameters will be reset to the default value.
;;; Input:
;;; Output: Updates the number of the Drain and Source contacts based on the Width of the FET
;;; Globals:
;;; Side Effects: NDC and NSC parameters will be updated
;;; Return:
;;;
(defun CDFfetDiscContactsCallback (@key (wProp 'w) (NDCprop 'NDC) (NSCprop 'NSC))
(let (fetWidth fetWidthEff contactLayer contactNum contactWidth contactSpace contactEnclosure contactPitch NDCvalue NSCvalue
cellName drnOffsetVal srcOffsetVal
(wp (get cdfgData wProp)) (NDCp (get cdfgData NDCprop)) (NSCp (get cdfgData NSCprop))
)
(cond
((TECHresolveLayer "licon1")
(setq contactLayer "licon1")
)
((TECHresolveLayer "ddlicon1")
(setq contactLayer "ddlicon1")
)
((TECHresolveLayer "mcon")
(setq contactLayer "mcon")
)
(t
(error "CDFfetDiscContactsCallback: unable to resolve contact layer for discrete fets..\n")
)
)
(setq cellName cdfgData~>id~>name)
(setq contactWidth (TECHgetRuleWith "minWidth" contactLayer))
(setq contactSpace (TECHgetRuleWith "minSpacing" contactLayer))
(setq contactEnclosure (TECHgetRuleWith "minEnclosureAdj" "diff" contactLayer))
(setq contactPitch (plus contactWidth contactSpace))
(setq fetWidth (aelNumber (get wp 'value)))
(when (numberp (aelNumber fetWidth))
(setq fetWidthEff (difference (plus fetWidth contactSpace) (times 2.0 contactEnclosure)))
(setq contactNum (fix (plus (quotient fetWidthEff contactPitch) 1e-6)))
;;Verify validity of "Number of Drain Contacts"
(cond
((numberp (aelNumber (get NDCp 'value)))
(putprop NDCp (sprintf nil "%d" (atoi (get NDCp 'value))) 'value)
(setq NDCvalue (fix (aelNumber (get NDCp 'value))))
(when (minusp NDCvalue)
(putprop NDCp (sprintf nil "%d" (minus NDCvalue)) 'value)
(warn "Negative Number of Drain Contacts entered: %d is invalid. Setting to %d\n"
NDCvalue (minus NDCvalue))
)
)
(t
(warn "Number of Drain Contacts entered: %s is invalid. Setting to %d\n" (get NDCp 'value) contactNum)
(putprop NDCp (sprintf nil "%d" contactNum) 'value)
)
)
(when (greaterp (aelNumber (get NDCp 'value)) contactNum)
(warn "Number of Drain Contacts entered: %s exceeds maximum. Setting to %d\n" (get NDCp 'value) contactNum)
(warn "Max contact number allowed is determined by the device width and contact size/space\n")
(putprop NDCp (sprintf nil "%d" contactNum) 'value)
)
(when (and cdfgData~>hspiceModel cdfgData~>drnOffset (equal (aelNumber (get NDCp 'value)) 0))
;; logic gates won't have a top level hspiceModel or drnOffset, and it's not worth the trouble to adjust drnOffset for them
(setq drnOffsetVal (times 0.5
(TECHgetDeviceParam
(TECHgetDeviceWithModel cellName cdfgData~>hspiceModel~>value)
'fetGateSpacing)))
(warn "Number of Drain Contacts entered is %s . Setting drain offset to %3.3f\n" (get NDCp 'value) drnOffsetVal)
cdfgData->drnOffset->value = (sprintf nil "%3.3f" drnOffsetVal)
)
;;Verify validity of "Number of Source Contacts"
(cond
((numberp (aelNumber (get NSCp 'value)))
(putprop NSCp (sprintf nil "%d" (atoi (get NSCp 'value))) 'value)
(setq NSCvalue (fix (aelNumber (get NSCp 'value))))
(when (minusp NSCvalue)
(putprop NSCp (sprintf nil "%d" (minus NSCvalue)) 'value)
(warn "Negative Number of Source Contacts entered: %d is invalid. Setting to %d\n"
NSCvalue (minus NSCvalue))
)
)
(t
(warn "Number of Drain Contacts entered: %s is invalid. Setting to %d\n" (get NSCp 'value) contactNum)
(putprop NSCp (sprintf nil "%d" contactNum) 'value)
)
)
(when (greaterp (aelNumber (get NSCp 'value)) contactNum)
(warn "Number of Source Contacts entered: %s exceeds maximum. Setting to %d\n" (get NSCp 'value) contactNum)
(warn "Max contact number allowed is determined by the device width and contact size/space\n")
(putprop NSCp (sprintf nil "%d" contactNum) 'value)
)
(when (and cdfgData~>hspiceModel cdfgData~>srcOffset (equal (aelNumber (get NSCp 'value)) 0))
;; logic gates won't have a top level hspiceModel or srcOffset, and it's not worth the trouble to adjust srcOffset for them
(setq srcOffsetVal (times 0.5
(TECHgetDeviceParam
(TECHgetDeviceWithModel cellName cdfgData~>hspiceModel~>value)
'fetGateSpacing)))
(warn "Number of Source Contacts entered is %s . Setting source offset to %3.3f\n" (get NSCp 'value) srcOffsetVal)
cdfgData->srcOffset->value = (sprintf nil "%3.3f" srcOffsetVal)
)
)
;; place # of contacts equation in form
(unless (numberp (aelNumber fetWidth))
(setq fetWidth (get wp 'value))
(setq fetWidth (strcat "(" fetWidth ")"))
(setq fetWidthEff `(difference (plus ,fetWidth ,contactSpace) (times 2.0 ,contactEnclosure)))
(setq contactNum `(int (quotient ,fetWidthEff ,contactPitch)))
(putprop NDCp (sprintf nil "%s" (SCHprefixToInfix contactNum)) 'value)
(putprop NSCp (sprintf nil "%s" (SCHprefixToInfix contactNum)) 'value)
)
)
)
;;;
;;; CDFfetToggleESD --
;;; This function does a sanity check to only allow the ESD toggle
;;; to be turned on if the voltage type is maxv.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFfetToggleESD ()
(let ((isESD t) theDevices cellName)
(setq theDevices (TECHgetMosDevices))
(setq cellName cdfgData~>id~>name)
(cond
((and cdfgData->vtype2 (equal "maxv" cdfgData->vtype2->value))
(setq isESD
(car (remq nil (mapcar (lambda (x)
(when (and (TECHgetDeviceParam x 'isESD)
(equal (TECHgetDeviceParam x 'vtype) "maxv")
(equal (TECHgetDeviceParam x 'cellName) cellName))
(TECHgetDeviceParam x 'isESD)))
theDevices))))
)
(t
(setq isESD
(car (remq nil (mapcar (lambda (x)
(when (and (TECHgetDeviceParam x 'isESD)
(or (equal (TECHgetDeviceParam x 'vtype) "normal")
(equal (TECHgetDeviceParam x 'vtype) nil))
(equal (TECHgetDeviceParam x 'cellName) cellName))
(TECHgetDeviceParam x 'isESD)))
theDevices))))
)
)
(when !isESD
(when (and cdfgData->isESD cdfgData->isESD->value)
cdfgData->isESD->value = nil
)
)
(when (and cdfgData->sonos cdfgData->isESD)
(when (and cdfgData->sonos->value cdfgData->isESD->value)
(info "Info: The \"Is sonos array?\" option must be turned off to select a different device\n")
cdfgData->isESD->value = nil
)
)
(when (and cdfgData->isESD cdfgData->native)
(when (and cdfgData->isESD->value cdfgData->native->value)
(info "Info: The \"Is ESD?\" option must be turned off to select a different device\n")
cdfgData->native->value = nil
)
)
(when (and cdfgData->isESD cdfgData->highVt)
(when (and cdfgData->isESD->value cdfgData->highVt->value)
(info "Info: The \"Is ESD?\" option must be turned off to select a different device\n")
cdfgData->highVt->value = nil
)
)
)
)
;;;
;;; CDFfetCallback --
;;; This is the CDF callback for the fet devices. It will create/update
;;; the hspiceModel and diodeModel properties on the fet instance. This will
;;; also update the enableLOD prop depending on the hspiceModel value.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFfetCallback (CDFdbid "d")
(let (fetDevice hspiceModel diodeModel minWidth minLength enableLOD)
(cond
;; if they manually specify the spice model
((and CDFdbid~>manualSpiceModel
(nequal "FALSE" CDFdbid~>manualSpiceModel))
(setq hspiceModel CDFdbid~>hspiceModel)
;; find the techrep device by model name
(foreach mosDev (TECHgetMosDevices)
(when (equal hspiceModel (TECHgetDeviceParam mosDev 'hspiceModel))
(setq fetDevice mosDev)
)
)
(when fetDevice
;; get the correct diode model from the technology representation
(setq diodeModel
(TECHgetDeviceParam
(TECHgetDevice ?name (TECHgetDeviceParam fetDevice 'diode))
'hspiceModel)
)
)
)
;; if they don't manually specify the spice model
(t
;; get the techrep device
(setq fetDevice (CDFfetGetFetDevice CDFdbid~>cellName))
;; get the correct hspice model from the technology representation
(setq hspiceModel (TECHgetDeviceParam fetDevice 'hspiceModel))
;; get the minimum gate width and length
(setq minWidth (TECHgetDeviceParam fetDevice 'minGateWidth))
(setq minLength (TECHgetDeviceParam fetDevice 'minGateLength))
;; This could be slightly dangerous by overwriting a property that
;; the user manually defined.
(when hspiceModel
(dbReplaceProp CDFdbid "hspiceModel" "string" hspiceModel)
)
;; get the correct diode model from the technology representation
(setq diodeModel
(TECHgetDeviceParam
(TECHgetDevice ?name (TECHgetDeviceParam fetDevice 'diode))
'hspiceModel)
)
;; make sure the isSubckt property is set or deleted
(cond
((TECHgetDeviceParam fetDevice 'isSubckt)
(dbReplaceProp CDFdbid "isSubckt" "boolean" "TRUE")
)
(t
(dbDeletePropByName CDFdbid "isSubckt")
)
)
)
)
;;resolve enableLOD based on the fetDevice. The last (cond) should set fetDevice.
(when fetDevice
(setq enableLOD (TECHgetDeviceParam fetDevice 'enableLOD))
(dbReplaceProp CDFdbid "enableLOD" "boolean" enableLOD)
)
(cond
(diodeModel
;; ShowAll will not work correctly if this does not exist.
;; Also, the hvacell & hvscell use this property because they
;; netlist discrete diodes.
(dbReplaceProp CDFdbid "diodeModel" "string" diodeModel)
)
(t
(warn "Failed to find diodeModel associated with '%L'. ShowAll will not work with this xtor.\n" hspiceModel)
;; this is so that the previous warn will actually print
(warn "Foo...this is just to get the previous warning to print\n")
(dbDeletePropByName CDFdbid "diodeModel")
)
)
;; for those who need training wheels, sanity check the minimum
;; device size
(when (ENVgetVal "schematic" "checkFetMinSize")
(when minWidth
(cond
((aelIsNumberP CDFdbid~>w)
(when (lessp (aelNumber CDFdbid~>w) minWidth)
(warn "Instance %L: Width (%L) is less than minimum (%L); increasing to minimum\n"
CDFdbid~>name CDFdbid~>w minWidth
)
(dbReplaceProp CDFdbid "w" "float" minWidth)
)
)
;; if it is an empty string, set it to min
((and (stringp CDFdbid~>w)
(null (parseString CDFdbid~>w " \t\n")))
(warn "Instance %L: Empty width is illegal; setting to minimum (%L)\n"
CDFdbid~>name minWidth
)
(dbReplaceProp CDFdbid "w" "float" minWidth)
)
;; if it is an expression that is not directly a number,
;; do nothing
(t nil)
)
)
(when minLength
(cond
((aelIsNumberP CDFdbid~>l)
(when (lessp (aelNumber CDFdbid~>l) minLength)
(warn "Instance %L: Length (%L) is less than minimum (%L); increasing to minimum\n"
CDFdbid~>name CDFdbid~>l minLength
)
(dbReplaceProp CDFdbid "l" "float" minLength)
)
)
((and (stringp CDFdbid~>l)
(null (parseString CDFdbid~>l " \t\n")))
(warn "Instance %L: Empty length is illegal; setting to minimum (%L)\n"
CDFdbid~>name minLength
)
(dbReplaceProp CDFdbid "l" "float" minLength)
)
;; if it is an expression that is not directly a number,
;; do nothing
(t nil)
)
)
)
(CDFcreateHideProps CDFdbid)
)
)
;;;
;;; CDFfetextdCallback --
;;; This is the CDF callback for the fetextd devices. It will create/update
;;; the hspiceModel and diodeModel properties on the fet instance.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFfetextdCallback (CDFdbid "d")
(let (fetDevice hspiceModel srcDiodeModel drnDiodeModel minWidth minLength)
(cond
;; if they manually specify the spice model
((and CDFdbid~>manualSpiceModel
(nequal "FALSE" CDFdbid~>manualSpiceModel))
(setq hspiceModel CDFdbid~>hspiceModel)
;; find the techrep device by model name
(foreach extdDev (TECHgetExtDrainDevices)
(when (equal hspiceModel (TECHgetDeviceParam extdDev 'hspiceModel))
(setq fetDevice extdDev)
)
)
(when fetDevice
;; get the correct source diode model from the technology representation
(setq srcDiodeModel
(TECHgetDeviceParam
(TECHgetDevice ?name (TECHgetDeviceParam fetDevice 'srcdiode))
'hspiceModel)
)
;; get the correct drain diode model from the technology representation
(setq drnDiodeModel
(TECHgetDeviceParam
(TECHgetDevice ?name (TECHgetDeviceParam fetDevice 'drndiode))
'hspiceModel)
)
)
)
;; if they don't manually specify the spice model
(t
;; get the techrep device
(setq fetDevice (CDFfetGetFetDevice CDFdbid~>cellName))
;; get the correct hspice model from the technology representation
(setq hspiceModel (TECHgetDeviceParam fetDevice 'hspiceModel))
;; get the minimum gate width and length
(setq minWidth (TECHgetDeviceParam fetDevice 'minGateWidth))
(setq minLength (TECHgetDeviceParam fetDevice 'minGateLength))
;; This could be slightly dangerous by overwriting a property that
;; the user manually defined.
(when hspiceModel
(dbReplaceProp CDFdbid "hspiceModel" "string" hspiceModel)
)
;; get the correct source diode model from the technology representation
(setq srcDiodeModel
(TECHgetDeviceParam
(TECHgetDevice ?name (TECHgetDeviceParam fetDevice 'srcdiode))
'hspiceModel)
)
;; get the correct drain diode model from the technology representation
(setq drnDiodeModel
(TECHgetDeviceParam
(TECHgetDevice ?name (TECHgetDeviceParam fetDevice 'drndiode))
'hspiceModel)
)
;; ;; make sure the isSubckt property is set or deleted
;; (cond
;; ((TECHgetDeviceParam fetDevice 'isSubckt)
;; (dbReplaceProperty CDFdbid "isSubckt" "boolean" "TRUE")
;; )
;; (t
;; (dbDeletePropByName CDFdbid "isSubckt")
;; )
;; )
)
)
(cond
(srcDiodeModel
;; ShowAll will not work correctly if this does not exist.
(dbReplaceProp CDFdbid "srcDiodeModel" "string" srcDiodeModel)
)
(t
(warn "Failed to find source diodeModel associated with '%L'. ShowAll will not work with this xtor.\n" hspiceModel)
;; this is so that the previous warn will actually print
(warn "Foo...this is just to get the previous warning to print\n")
(dbDeletePropByName CDFdbid "srcDiodeModel")
)
)
(cond
(drnDiodeModel
;; ShowAll will not work correctly if this does not exist.
;; Also, the hvacell & hvscell use this property because they
;; netlist discrete diodes.
(dbReplaceProp CDFdbid "drnDiodeModel" "string" drnDiodeModel)
)
(t
(warn "Failed to find drain diodeModel associated with '%L'. ShowAll will not work with this xtor.\n" hspiceModel)
;; this is so that the previous warn will actually print
(warn "Foo...this is just to get the previous warning to print\n")
(dbDeletePropByName CDFdbid "drnDiodeModel")
)
)
;; for those who need training wheels, sanity check the minimum
;; device size
(when (ENVgetVal "schematic" "checkFetMinSize")
(when minWidth
(cond
((aelIsNumberP CDFdbid~>w)
(when (lessp (aelNumber CDFdbid~>w) minWidth)
(warn "Instance %L: Width (%L) is less than minimum (%L); increasing to minimum\n"
CDFdbid~>name CDFdbid~>w minWidth
)
(dbReplaceProp CDFdbid "w" "float" minWidth)
)
)
;; if it is an empty string, set it to min
((and (stringp CDFdbid~>w)
(null (parseString CDFdbid~>w " \t\n")))
(warn "Instance %L: Empty width is illegal; setting to minimum (%L)\n"
CDFdbid~>name minWidth
)
(dbReplaceProp CDFdbid "w" "float" minWidth)
)
;; if it is an expression that is not directly a number,
;; do nothing
(t nil)
)
)
(when minLength
(cond
((aelIsNumberP CDFdbid~>l)
(when (lessp (aelNumber CDFdbid~>l) minLength)
(warn "Instance %L: Length (%L) is less than minimum (%L); increasing to minimum\n"
CDFdbid~>name CDFdbid~>l minLength
)
(dbReplaceProp CDFdbid "l" "float" minLength)
)
)
((and (stringp CDFdbid~>l)
(null (parseString CDFdbid~>l " \t\n")))
(warn "Instance %L: Empty length is illegal; setting to minimum (%L)\n"
CDFdbid~>name minLength
)
(dbReplaceProp CDFdbid "l" "float" minLength)
)
;; if it is an expression that is not directly a number,
;; do nothing
(t nil)
)
)
)
(CDFcreateHideProps CDFdbid)
)
)
;;;
;;; CDFlogicCallback --
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFlogicCallback (CDFdbid "d")
(let (diodeModel propId)
;; the hspice model is not needed now that we hardcode default
;; fet model names in the hspice netlister. It will see an nlp
;; expression for the hspiceModel prop of each fet in the logic
;; schematic, and then use the fet's default hspice model
;; get the correct diode model from the technology representation.
;; ShowAll will not work correctly if these do not exist.
(setq diodeModel
(TECHgetDeviceParam
(TECHgetDevice ?name (TECHgetDeviceParam
(TECHgetDevice ?name 'nfet)
'diode))
'hspiceModel)
)
(when diodeModel
(dbReplaceProp CDFdbid "nfetDiodeModel" "string" diodeModel)
)
;; get the correct diode model from the technology representation.
;; ShowAll will not work correctly if these do not exist
(setq diodeModel
(TECHgetDeviceParam
(TECHgetDevice ?name (TECHgetDeviceParam
(TECHgetDevice ?name 'pfet)
'diode))
'hspiceModel)
)
(when diodeModel
(dbReplaceProp CDFdbid "pfetDiodeModel" "string" diodeModel)
)
;; we have changed the property "subcktMult" to now be "m".
;; Purge away the old subcktMult properties. It is unnecessary
;; to create the "m" properties here because "m" is now in the
;; CDF, and the CDF initialization procedure will grab the value
;; of the subcktMult property and stuff it into the m field
;;
(when (setq propId (dbFindProp CDFdbid "subcktMult"))
(dbDeleteObject propId)
)
;; create the current monitor property HSPmonitorTerms if the
;; currentMonitor boolean is set for this logic gate
(cond (
(and CDFdbid~>currentMonitor
(nequal "FALSE" CDFdbid~>currentMonitor))
(cond
((equal "csw_p" CDFdbid~>cellName)
(dbReplaceProp CDFdbid "HSPmonitorTerms" "ILList"
(list "vpb" "vnb"))
)
(t
(dbReplaceProp CDFdbid "HSPmonitorTerms" "ILList"
(list "vpwr" "vpb" "vnb" "vgnd"))
)
)
)
(t
(dbDeletePropByName CDFdbid "HSPmonitorTerms")
)
)
(CDFcreateHideProps CDFdbid)
(CDFcreateAsymProps CDFdbid)
;; if we have parameters named <something>NSC<something> or <something>NDC<something>,
;; we need to hit the callback for CDFhitCallbacks to store the desired properties
(foreach param cdfgData~>parameters
(when (and (rexMatchp "N[SD]C" param~>name) param~>callback)
(CDFevalString param~>callback)
)
)
t
)
)
;;;
;;; CDFhspiceStringToFloat --
;;; Converts a string to a floating point, comprehending hspice unit
;;; abbreviations.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFhspiceStringToFloat (str)
(cond
;; if AEL knows how do deal with this number, deal with it
((aelIsNumberP str)
(aelNumber str)
)
(t
(let (upstr numPart lenNumPart suffixPart suffix)
(setq upstr (upperCase str))
(setq numPart (car (parseString upstr "ABCDEFGHIJKLMNOPQRSTUVWXYZ")))
(cond
(numPart
(setq lenNumPart (strlen numPart))
(setq suffixPart (substring upstr (xplus 1 lenNumPart)
(xdifference (strlen upstr) lenNumPart)
)
)
(when (member suffixPart '(nil "MEG" "MI" "F" "P"
"N" "U" "M" "K" "G"))
(setq suffix
(cond
((null suffixPart) 1)
((zerop (strncmp suffixPart "MEG" 3)) 1e6)
((zerop (strncmp suffixPart "MI" 2)) 25.4e-6)
((zerop (strncmp suffixPart "F" 1)) 1e-15)
((zerop (strncmp suffixPart "P" 1)) 1e-12)
((zerop (strncmp suffixPart "N" 1)) 1e-9)
((zerop (strncmp suffixPart "U" 1)) 1e-6)
((zerop (strncmp suffixPart "M" 1)) 1e-3)
((zerop (strncmp suffixPart "K" 1)) 1e3)
((zerop (strncmp suffixPart "G" 1)) 1e9)
(t 1.0)
)
)
)
)
)
(cond
((and numPart (aelIsNumberP numPart) suffix)
(times (aelNumber numPart) suffix)
)
(t str)
)
)
)
)
)
;;;
;;; CDFhspiceFloatToString --
;;; Converts a floating point to a string, setting hspice unit abbreviations
;;; in the string.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFhspiceFloatToString (flt "f")
(let ((absFlt (abs flt))
suffixPair
)
(setq suffixPair
(cond
((lessp absFlt 1e-12) '("F" 1e-15))
((and (lessp absFlt 1e-9) (geqp absFlt 1e-12)) '("p" 1e-12))
((and (lessp absFlt 1e-6) (geqp absFlt 1e-9)) '("n" 1e-9))
((and (lessp absFlt 1e-3) (geqp absFlt 1e-6)) '("u" 1e-6))
((and (lessp absFlt 1) (geqp absFlt 1e-3)) '("m" 1e-3))
((and (lessp absFlt 1e3) (geqp absFlt 1)) '("" 1))
((and (lessp absFlt 1e6) (geqp absFlt 1e3)) '("K" 1e3))
((and (lessp absFlt 1e9) (geqp absFlt 1e6)) '("M" 1e6))
((geqp absFlt 1e9) '("G" 1e9))
)
)
(sprintf nil "%g%s" (quotient flt (cadr suffixPair)) (car suffixPair))
)
)
;;;
;;; CDFgetResTechrepDevice --
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFgetResTechrepDevice (cellName cdfgData "to")
(let (resLayer doping cdf_well1 cdf_diff1 cdf_diff2 cdf_diff3 cdf_poly1
cdf_li1 cdf_nwell cdf_ddli cdf_lm1 cdf_litr cdf_met1 cdf_met2)
(setq cdf_well1 (car (TECHresolveLayer "cdf_well1")))
(setq cdf_diff1 (car (TECHresolveLayer "cdf_diff1")))
(setq cdf_diff2 (car (TECHresolveLayer "cdf_diff2")))
(setq cdf_diff3 (car (TECHresolveLayer "cdf_diff3")))
(setq cdf_poly1 (car (TECHresolveLayer "cdf_poly1")))
(setq cdf_li1 (car (TECHresolveLayer "cdf_li1")))
(setq cdf_nwell (car (TECHresolveLayer "cdf_nwell")))
(setq cdf_ddli (car (TECHresolveLayer "cdf_ddli")))
(setq cdf_lm1 (car (TECHresolveLayer "cdf_lm1")))
(setq cdf_litr (car (TECHresolveLayer "cdf_litr")))
(setq cdf_met1 (car (TECHresolveLayer "cdf_met1")))
(setq cdf_met2 (car (TECHresolveLayer "cdf_met2")))
(car
(remq nil
(mapcar
(lambda (x)
(when
;; when we find a res that matches the layer
;; do further conditions per layer
(equal cdfgData->resistorType->value
(setq resLayer
(TECHgetDeviceParam x 'layer)))
(cond
((equal resLayer "diff")
(setq doping
(TECHgetDeviceParam
(TECHgetDevice
?name (TECHgetDeviceParam x 'diode))
'doping))
(setq hv (TECHgetDeviceParam x 'isHV))
;; 1. when it is a resn & doping is n
;; 2. when it is a res & isPtype is nil
;; 3. when it is a resp & doping is p
;; 4. when it is a res & isPtype is t
;; then this device matches!
(when (or (and (equal doping "n")
(equal cellName "resn")
(equal hv cdfgData->isHV->value))
(and (equal doping "n")
(equal cellName "res")
(or (null cdfgData->isPtype->value)
(equal cdfgData->isPtype->value "FALSE")))
(and (equal doping "p")
(equal cellName "resp")
(equal hv cdfgData->isHV->value))
(and (equal doping "p")
(equal cellName "res")
(and cdfgData->isPtype->value
(nequal "FALSE" cdfgData->isPtype->value)))
)
x
)
)
;; match the model name for diff1
((and cdfgData->diff1mod->use
(evalstring cdfgData->diff1mod->use)
(equal resLayer cdf_diff1))
(when (equal cdfgData->diff1mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for diff2
((and cdfgData->diff2mod->use
(evalstring cdfgData->diff2mod->use)
(equal resLayer cdf_diff2))
(when (equal cdfgData->diff2mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for diff3
((and cdfgData->diff3mod->use
(evalstring cdfgData->diff3mod->use)
(equal resLayer cdf_diff3))
(when (equal cdfgData->diff3mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for well1
((and cdfgData->well1mod->use
(evalstring cdfgData->well1mod->use)
(equal resLayer cdf_well1))
(when (equal cdfgData->well1mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for poly
((and cdfgData->rpmod->use
(evalstring cdfgData->rpmod->use)
(member resLayer `("poly" ,cdf_poly1)))
(when (equal cdfgData->rpmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for rpoly
((and cdfgData->rpolymod->use
(evalstring cdfgData->rpolymod->use)
(equal resLayer "rpoly"))
(when (equal cdfgData->rpolymod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for ad
((and cdfgData->admod->use
(evalstring cdfgData->admod->use)
(equal resLayer "ad"))
(when (equal cdfgData->admod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for nd
((and cdfgData->ndmod->use
(evalstring cdfgData->ndmod->use)
(equal resLayer "nd"))
(when (equal cdfgData->ndmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for pd
((and cdfgData->pdmod->use
(evalstring cdfgData->pdmod->use)
(equal resLayer "pd"))
(when (equal cdfgData->pdmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for nw
((and cdfgData->nwmod->use
(evalstring cdfgData->nwmod->use)
(equal resLayer "wn"))
(when (equal cdfgData->nwmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for tfr
((and cdfgData->tfrmod->use
(evalstring cdfgData->tfrmod->use)
(equal resLayer "tfr"))
(when (equal cdfgData->tfrmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for pwell
((and cdfgData->pwellmod->use
(evalstring cdfgData->pwellmod->use)
(equal resLayer "pwell"))
(when (equal cdfgData->pwellmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for li1
((and cdfgData->limod->use
(evalstring cdfgData->limod->use)
(member resLayer `("li1" ,cdf_li1)))
(when (equal cdfgData->limod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for nwell
((and cdfgData->nwellmod->use
(evalstring cdfgData->nwellmod->use)
(member resLayer `("nwell" ,cdf_nwell)))
(when (and
(equal cdfgData->nwellmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
(equal cdfgData->isHV->value (TECHgetDeviceParam x 'isHV))
)
x
)
)
;; match the model name for ddli
((and cdfgData->ddlimod->use
(evalstring cdfgData->ddlimod->use)
(member resLayer `("ddli" ,cdf_ddli)))
(when (equal cdfgData->ddlimod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for lm1
((and cdfgData->lm1mod->use
(evalstring cdfgData->lm1mod->use)
(member resLayer `("lm1" ,cdf_lm1)))
(when (equal cdfgData->lm1mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for litr
((and cdfgData->litrmod->use
(evalstring cdfgData->litrmod->use)
(member resLayer `("litr" ,cdf_litr)))
(when (equal cdfgData->litrmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for met1
((and cdfgData->met1mod->use
(evalstring cdfgData->met1mod->use)
(member resLayer `("met1" ,cdf_met1)))
(when (equal cdfgData->met1mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for met2
((and cdfgData->met2mod->use
(evalstring cdfgData->met2mod->use)
(member resLayer `("met2" ,cdf_met2)))
(when (equal cdfgData->met2mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for met3
((and cdfgData->met3mod->use
(evalstring cdfgData->met3mod->use)
(equal resLayer "met3"))
(when (equal cdfgData->met3mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for met4
((and cdfgData->met4mod->use
(evalstring cdfgData->met4mod->use)
(equal resLayer "met4"))
(when (equal cdfgData->met4mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for met5
((and cdfgData->met5mod->use
(evalstring cdfgData->met5mod->use)
(equal resLayer "met5"))
(when (equal cdfgData->met5mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for met6
((and cdfgData->met6mod->use
(evalstring cdfgData->met6mod->use)
(equal resLayer "met6"))
(when (equal cdfgData->met6mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for met7
((and cdfgData->met7mod->use
(evalstring cdfgData->met7mod->use)
(equal resLayer "met7"))
(when (equal cdfgData->met7mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for met8
((and cdfgData->met8mod->use
(evalstring cdfgData->met8mod->use)
(equal resLayer "met8"))
(when (equal cdfgData->met8mod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for metd
((and cdfgData->metdmod->use
(evalstring cdfgData->metdmod->use)
(equal resLayer "metd"))
(when (equal cdfgData->metdmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for rdl
((and cdfgData->rdlmod->use
(evalstring cdfgData->rdlmod->use)
(equal resLayer "rdl"))
(when (equal cdfgData->rdlmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
) ; closing cond on layers
) ; closing when layer matches
) ; closing lambda
;; apply all the resistor devices to the lambda function
(TECHgetResistorDevices)
)
)
)
)
)
;;;
;;; CDFgetRes3TechrepDevice --
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFgetRes3TechrepDevice (cellName cdfgData "to")
(let (resLayer)
(car
(remq nil
(mapcar
(lambda (x)
(when
;; when we find a res that matches the layer
;; do further conditions per layer
(equal cdfgData->resistorType->value
(setq resLayer
(TECHgetDeviceParam x 'layer)))
(cond
;; match the model name for diff
((and cdfgData->diffmod->use
(evalstring cdfgData->diffmod->use)
(equal resLayer "diff"))
(when (equal cdfgData->diffmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for rpoly
((and cdfgData->rpolymod->use
(evalstring cdfgData->rpolymod->use)
(equal resLayer "rpoly"))
(when (equal cdfgData->rpolymod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for rpoly
((and cdfgData->polymod->use
(evalstring cdfgData->polymod->use)
(equal resLayer "poly"))
(when (equal cdfgData->polymod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for ad
((and cdfgData->admod->use
(evalstring cdfgData->admod->use)
(equal resLayer "ad"))
(when (equal cdfgData->admod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for nd
((and cdfgData->ndmod->use
(evalstring cdfgData->ndmod->use)
(equal resLayer "nd"))
(when (equal cdfgData->ndmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for pd
((and cdfgData->pdmod->use
(evalstring cdfgData->pdmod->use)
(equal resLayer "pd"))
(when (equal cdfgData->pdmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for nw
((and cdfgData->nwmod->use
(evalstring cdfgData->nwmod->use)
(equal resLayer "wn"))
(when (equal cdfgData->nwmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
;; match the model name for tfr
((and cdfgData->tfrmod->use
(evalstring cdfgData->tfrmod->use)
(equal resLayer "tfr"))
(when (equal cdfgData->tfrmod->value
(TECHgetDeviceParam x 'hspiceModel)
)
x
)
)
) ; closing cond on layers
) ; closing when layer matches
) ; closing lambda
;; apply all the resistor devices to the lambda function
(TECHgetRes3Devices)
)
)
)
)
)
;;;
;;; CDFgetCapTechrepDevice --
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFgetCapTechrepDevice (cellName cdfgData "to")
(let (resLayer doping cdf_well1 cdf_diff1 cdf_diff2 cdf_diff3 cdf_poly1
cdf_li1 cdf_nwell cdf_ddli cdf_lm1 cdf_litr cdf_met1 cdf_met2)
(setq cdf_well1 (car (TECHresolveLayer "cdf_well1")))
(setq cdf_diff1 (car (TECHresolveLayer "cdf_diff1")))
(setq cdf_nwell (car (TECHresolveLayer "cdf_nwell")))
(setq cdf_diff2 (car (TECHresolveLayer "cdf_diff2")))
(setq cdf_diff3 (car (TECHresolveLayer "cdf_diff3")))
(setq cdf_poly1 (car (TECHresolveLayer "cdf_poly1")))
(setq cdf_li1 (car (TECHresolveLayer "cdf_li1")))
(setq cdf_ddli (car (TECHresolveLayer "cdf_ddli")))
(setq cdf_lm1 (car (TECHresolveLayer "cdf_lm1")))
(setq cdf_litr (car (TECHresolveLayer "cdf_litr")))
(setq cdf_met1 (car (TECHresolveLayer "cdf_met1")))
(setq cdf_met2 (car (TECHresolveLayer "cdf_met2")))
(car
(remq nil
(mapcar
(lambda (x)
(when
;; when we find a res that matches the layer
;; do further conditions per layer
(or
(equal cdfgData->resistorType->value
(setq resLayer
(TECHgetDeviceParam x 'layer)))
(equal cdfgData->resistorType->value
(setq resLayer "User"))
)
(cond
;; match the model name for poly
((member resLayer `("poly" ,cdf_poly1))
cdfgData->rpcmod->value
)
;; match the model name for rpoly
((equal resLayer "rpoly")
cdfgData->rpolycmod->value
)
;; match the model name for ad
((equal resLayer "ad")
cdfgData->admod->value
)
;; match the model name for nd
((equal resLayer "nd")
cdfgData->ndmod->value
)
;; match the model name for pd
((equal resLayer "pd")
cdfgData->pdmod->value
)
;; match the model name for nw
((equal resLayer "wn")
cdfgData->nwmod->value
)
;; match the model name for tfr
((equal resLayer "tfr")
cdfgData->tfrcmod->value
)
;; match the model name for li1
((member resLayer `("li1" ,cdf_li1))
cdfgData->licmod->value
)
;; match the model name for nwell
((member resLayer `("nwell" ,cdf_nwell))
cdfgData->nwellcmod->value
)
;; match the model name for ddli
((member resLayer `("ddli" ,cdf_ddli))
cdfgData->ddlicmod->value
)
;; match the model name for lm1
((member resLayer `("lm1" ,cdf_lm1))
cdfgData->lm1cmod->value
)
;; match the model name for litr
((member resLayer `("litr" ,cdf_litr))
cdfgData->litrcmod->value
)
;; match the model name for met1
((member resLayer `("met1" ,cdf_met1))
cdfgData->met1cmod->value
)
;; match the model name for met2
((member resLayer `("met2" ,cdf_met2))
cdfgData->met2cmod->value
)
;; match the model name for met3
((equal resLayer "met3")
cdfgData->met3cmod->value
)
;; match the model name for met4
((equal resLayer "met4")
cdfgData->met4cmod->value
)
;; match the model name for met5
((equal resLayer "met5")
cdfgData->met5cmod->value
)
;; match the model name for met6
((equal resLayer "met6")
cdfgData->met6cmod->value
)
;; match the model name for met7
((equal resLayer "met7")
cdfgData->met7cmod->value
)
;; match the model name for met8
((equal resLayer "met8")
cdfgData->met8cmod->value
)
;; match the model name for metd
((equal resLayer "metd")
cdfgData->metdcmod->value
)
;; match the model name for rdl
((equal resLayer "rdl")
cdfgData->rdlcmod->value
)
;; match the model name for User defined res
((equal resLayer "User")
cdfgData->userRcapModel->value
)
) ; closing cond on layers
) ; closing when layer matches
) ; closing lambda
;; apply all the resistor devices to the lambda function
(TECHgetResistorDevices)
)
)
)
)
)
;;;
;;; CDFcalculateRes --
;;; This is the callback function that will actually calculate the
;;; resistance or resistor length when a resistor is placed.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcalculateRes (isRdriven r rm rw rl resDevice cdfgData
@optional rcon0m rcon1m)
(let (R
sheetResistance
(resGrid (or (TECHgetLayerProp
(TECHgetDeviceParam resDevice 'layer) 'snapGrid)
(TECHgetProp snapGrid)))
(isSubcktRes (TECHgetDeviceParam resDevice 'isSubckt))
(headRes (TECHgetDeviceParam resDevice 'headRes))
(deltaW (TECHgetDeviceParam resDevice 'deltaW))
(deltaL (TECHgetDeviceParam resDevice 'deltaL))
(contactRes 0.0)
rconDevice contactModel
)
;; try to get the properties as floats, not strings
(when (nequal r "")
(setq R (CDFhspiceStringToFloat r))
)
(foreach x '(rm rw rl rcon0m rcon1m)
(when (and (stringp (eval x)) (aelIsNumberP (eval x)))
(set x (aelNumber (eval x)))
)
)
(when (and (equal "poly" (TECHgetDeviceParam resDevice 'layer))
(setq contactModel
(TECHgetDeviceParam resDevice 'contactModel))
)
(foreach x (TECHgetRconDevices)
(when (equal contactModel (TECHgetDeviceParam x 'hspiceModel))
(setq contactRes (TECHgetDeviceParam x 'contactRes))
)
)
(unless rcon0m (setq rcon0m 0))
(unless rcon1m (setq rcon1m 0))
(cond
;; if the contact resistance was not a number
((null contactRes)
(setq contactRes 0.0)
)
;; if all the contact resistances are numbers
((and (numberp contactRes) (numberp rcon0m) (numberp rcon1m))
(setq contactRes (times contactRes (plus rcon0m rcon1m)))
)
;; if some of the contact resistances are parameters
(t
(foreach x '(contactRes rcon0m rcon1m)
(when (numberp (eval x))
(set x (sprintf nil "%L" (eval x)))
)
)
(setq contactRes (sprintf nil "(%s*(%s+%s))"))
)
)
)
;; make sure that the width delta is defined. In the spice
;; world, dw is assumed to be per side. However, the EDR has
;; the total deltaW. Therefore, there is not a need to multiply
;; by two here. However, the spice models should have half of
;; this deltaW. (Also, positive deltaW means that the actual
;; fabbed line is smaller, and a negative deltaW means that the
;; fabbed line is larger.)
;;
(unless deltaW (setq deltaW 0.0))
(unless deltaL (setq deltaL 0.0))
;; get the sheet resistance. User defined resistors have a
;; separate field for the user to specify the sheetres.
;; Regular devices have their sheet res defined in the techrep.
;; Also, see if there is a high or low resistance sheetres.
;;
(cond
((and cdfgData->usermod->value
(evalstring cdfgData->usermod->use))
(setq sheetResistance cdfgData->userSheetRes->value)
)
(t
(setq sheetResistance (TECHgetDeviceParam resDevice 'sheet))
)
)
(cond
;; when resistance driven, calculate resistor length
(isRdriven
(cond
((and isSubcktRes headRes)
(cond
;; if everything is a number, do real math
((and (numberp R)
(numberp rm)
(numberp headRes)
(numberp rw)
(numberp sheetResistance))
(setq rl (plus (quotient (times (difference (times R rm) headRes) (difference rw deltaW)) sheetResistance) deltaL))
)
(t
;; otherwise, if at least one thing was a string, make
;; sure that everything is a string, and build an equation
;;
(when (numberp R) (setq R (sprintf nil "%g" R)))
(when (floatp rm) (setq rm (sprintf nil "%g" rm)))
(when (integerp rm) (setq rm (sprintf nil "%d" rm)))
(when (numberp headRes)
(setq headRes (sprintf nil "%g" headRes)))
(when (numberp rw) (setq rw (sprintf nil "%g" rw)))
(when (numberp sheetResistance)
(setq sheetResistance (sprintf nil "%g" sheetResistance)))
(when (numberp deltaW)
(setq deltaW (sprintf nil "%g" deltaW)))
(when (numberp deltaL)
(setq deltaL (sprintf nil "%g" deltaL)))
(setq rl (sprintf nil "(((((%s*%s)-%s)*(%s-%s))/%s)+%s)"
R rm headRes rw deltaW sheetResistance deltaL)
)
)
)
)
;; if it is not a subckt resistor
(t
(cond
;; if everything is a number, do real math
((and (numberp R)
(numberp rm)
(numberp rw)
(numberp sheetResistance)
(numberp contactRes))
(setq rl (plus (quotient (times (difference (times R rm) contactRes) (difference rw deltaW))
sheetResistance) deltaL))
)
(t
;; otherwise, if at least one thing was a string, make
;; sure that everything is a string, and build an equation
;;
(foreach x '(R rm rw sheetResistance deltaW deltaL contactRes)
(when (numberp (eval x))
(set x (sprintf nil "%L" (eval x)))
)
)
(setq rl (sprintf nil "(((((%s*%s)-%s)*(%s-%s))/%s)+%s)"
R rm contactRes rw deltaW
sheetResistance deltaL))
)
)
)
)
;; snap it to a grid if it is a number. If it is an expression,
;; we have no chance of snapping it to grid
(when (numberp rl)
(setq rl (times (round (quotient rl resGrid)) resGrid))
)
;; return the length
rl
)
;; when length driven, calculate resistor resistance
(t
(cond
((and isSubcktRes headRes)
(cond
((and (numberp headRes)
(numberp rm)
(numberp rl)
(numberp sheetResistance)
(numberp rw))
(setq R (plus
(quotient headRes rm)
(quotient (times (difference rl deltaL) sheetResistance)
(difference rw deltaW)
rm)
)
)
)
(t
(when (numberp headRes)
(setq headRes (sprintf nil "%g" headRes)))
(when (floatp rm) (setq rm (sprintf nil "%g" rm)))
(when (integerp rm) (setq rm (sprintf nil "%d" rm)))
(when (numberp rl) (setq rl (sprintf nil "%g" rl)))
(when (numberp sheetResistance)
(setq sheetResistance (sprintf nil "%g" sheetResistance)))
(when (numberp rw) (setq rw (sprintf nil "%g" rw)))
(when (numberp deltaW)
(setq deltaW (sprintf nil "%g" deltaW)))
(when (numberp deltaL)
(setq deltaL (sprintf nil "%g" deltaL)))
(setq R (sprintf nil "((%s/%s)+(((%s-%s)*%s)/((%s-%s)*%s)))"
headRes rm rl deltaL sheetResistance
rw deltaW rm))
)
)
)
(t
(cond
((and (numberp rm)
(numberp rl)
(numberp sheetResistance)
(numberp rw)
(numberp contactRes))
(setq R (plus (quotient (times (difference rl deltaL) sheetResistance) (times rm (difference rw deltaW))) contactRes))
)
(t
(foreach x '(rm rl rw sheetResistance deltaW deltaL contactRes)
(when (numberp (eval x))
(set x (sprintf nil "%L" (eval x)))
)
)
(setq R (sprintf nil "((((%s-%s)*%s)/(%s*(%s-%s)))+)"
rl deltaL sheetResistance rm rw deltaW
contactRes))
)
)
)
)
(when (numberp R)
(CDFhspiceFloatToString R)
)
R
)
)
)
)
;;;
;;; CDFresRconModel --
;;; This function returns the rcon model name for the resistor currently
;;; being edited in the cdf editor.
;;; Input:
;;; Output:
;;; Globals: cdfgData
;;; Side Effects:
;;; Return: string rcon model name
;;;
(defun CDFresRconModel ()
(let (instmod hspmod rconmod resdevice cdf_this)
(setq cdf_this (car (TECHresolveLayer cdfgData->resistorType->value)))
(cond
((equal "diff" cdfgData->resistorType->value)
(setq resdevice
(TECHgetDevice ?name (or (and cdfgData->isPtype->value "rdp")
"rdn")))
(setq rconmod (TECHgetDeviceParam resdevice 'contactModel))
)
((equal "User" cdfgData->resistorType->value)
(setq rconmod cdfgData->userRconModel->value)
)
(t
(setq instmod
(case cdfgData->resistorType->value
("poly" cdfgData->rpmod->value)
("li1" cdfgData->limod->value)
("nwell" cdfgData->nwellmod->value)
("ddli" cdfgData->ddlimod->value)
("lm1" cdfgData->lm1mod->value)
("litr" cdfgData->litrmod->value)
("met1" cdfgData->met1mod->value)
("met2" cdfgData->met2mod->value)
("met3" cdfgData->met3mod->value)
("met4" cdfgData->met4mod->value)
("met5" cdfgData->met5mod->value)
("met6" cdfgData->met6mod->value)
("met7" cdfgData->met7mod->value)
("met8" cdfgData->met8mod->value)
("metd" cdfgData->metdmod->value)
("rdl" cdfgData->rdlmod->value )
)
)
(when (exists x (TECHgetLayerProp cdf_this 'aliases)
((strncmp x "cdf_" 4) == 0))
(setq instmod
(case (car (exists x (TECHgetLayerProp cdf_this 'aliases)
((strncmp x "cdf_" 4) == 0)))
("cdf_poly1" cdfgData->rpmod->value)
("cdf_nwell" cdfgData->nwellmod->value)
("cdf_li1" cdfgData->limod->value)
("cdf_ddli" cdfgData->ddlimod->value)
("cdf_lm1" cdfgData->lm1mod->value)
("cdf_litr" cdfgData->litrmod->value)
("cdf_met1" cdfgData->met1mod->value)
("cdf_met2" cdfgData->met2mod->value)
("cdf_met3" cdfgData->met3mod->value)
("cdf_met4" cdfgData->met4mod->value)
("cdf_met5" cdfgData->met5mod->value)
("cdf_met6" cdfgData->met6mod->value)
("cdf_met7" cdfgData->met7mod->value)
("cdf_met8" cdfgData->met8mod->value)
("cdf_metd" cdfgData->metdmod->value)
("cdf_rdl" cdfgData->rdlmod->value)
)
)
)
(foreach x (TECHgetResistorDevices)
(setq hspmod (TECHgetDeviceParam x 'hspiceModel))
(when (equal hspmod instmod)
(setq rconmod (TECHgetDeviceParam x 'contactModel))
)
)
)
)
rconmod
)
)
;;;
;;; CDFresEnableRcons --
;;; This function returns nil if rcons are not currently enabled.
;;; Otherwise it returns a non-nil value.
;;; Input:
;;; Output:
;;; Globals: cdfgData
;;; Side Effects:
;;; Return: t or nil
;;;
(defun CDFresEnableRcons ()
(case cdfgData->resistorType->value
("User"
(nequal "" cdfgData->userRconModel->value)
)
("Absolute" nil)
(t
(null (null (CDFresRconModel)))
)
)
)
;;;
;;; CDFresCallback --
;;; This function is the CDF callback for when it needs to calculate
;;; the resistance for the resistor. Depending upon if it is resistance
;;; driven or length driven, it will calculate and set either the "rl" or
;;; the "r" parameter.
;;; It will also update the parasitics if the res has parasitics.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFresCallback (CDFdbid cdfgData)
(let (
resDevice
isRdriven
(r cdfgData->r->value)
(rm (or cdfgData->rm->value 1))
(rw cdfgData->rw->value)
(rl cdfgData->rl->value)
; (rcon0m cdfgData->rcon0m->value)
; (rcon1m cdfgData->rcon1m->value)
parasiticDevice
parasiteModel
nlSegNum
tmprw tmprl tmprm
cwtype cwval cltype clval
cdf_well1 cdf_diff1 cdf_diff2 cdf_diff3 cdf_poly1
cdf_li1 cdf_nwell cdf_ddli cdf_lm1 cdf_litr cdf_met1 cdf_met2)
(setq cdf_well1 (car (TECHresolveLayer "cdf_well1")))
(setq cdf_diff1 (car (TECHresolveLayer "cdf_diff1")))
(setq cdf_diff2 (car (TECHresolveLayer "cdf_diff2")))
(setq cdf_diff3 (car (TECHresolveLayer "cdf_diff3")))
(setq cdf_poly1 (car (TECHresolveLayer "cdf_poly1")))
(setq cdf_nwell (car (TECHresolveLayer "cdf_nwell")))
(setq cdf_li1 (car (TECHresolveLayer "cdf_li1")))
(setq cdf_ddli (car (TECHresolveLayer "cdf_ddli")))
(setq cdf_lm1 (car (TECHresolveLayer "cdf_lm1")))
(setq cdf_litr (car (TECHresolveLayer "cdf_litr")))
(setq cdf_met1 (car (TECHresolveLayer "cdf_met1")))
(setq cdf_met2 (car (TECHresolveLayer "cdf_met2")))
(setq cdf_this (car (TECHresolveLayer cdfgData->resistorType->value)))
(when cdfgData->nlSegNum
(setq nlSegNum cdfgData->nlSegNum->value)
)
;; try to work with numbers, not strings
(when (stringp r)
(cond ((aelIsNumberP r)
(setq r (aelNumber r))
)
(t (setq r (strcat "(" r ")")))
)
)
(when (stringp rm)
(cond ((aelIsNumberP rm)
(setq rm (evalstring rm))
)
(t (setq rm (strcat "(" rm ")")))
)
)
(when (stringp rw)
(cond ((aelIsNumberP rw)
(setq rw (aelNumber rw))
)
(t (setq rw (strcat "(" rw ")")))
)
)
(when (stringp rl)
(cond ((aelIsNumberP rl)
(setq rl (aelNumber rl))
)
(t (setq rl (strcat "(" rl ")")))
)
)
;; we may need these values as strings
(when (numberp rl) (setq tmprl (sprintf nil "%g" rl)))
(when (numberp rw) (setq tmprw (sprintf nil "%g" rw)))
(when (numberp rm) (setq tmprm (sprintf nil "%d" rm)))
(setq resDevice
(CDFgetResTechrepDevice CDFdbid~>master~>cellName cdfgData))
(when (member CDFdbid~>master~>cellName '("resn" "resp" "resnw"))
(setq parasiticDevice
(TECHgetDevice ?name (TECHgetDeviceParam resDevice 'diode)))
)
(when (member CDFdbid~>master~>cellName '("rescap"))
(setq parasiticDevice
(TECHgetDevice ?name
(concat (CDFgetCapTechrepDevice CDFdbid~>master~>cellName cdfgData))))
(CDFsetCapSpaceProps CDFdbid parasiticDevice)
)
(when (member CDFdbid~>master~>cellName '("rescap" "res" "resn" "resp"))
(CDFsetResSpaceProps CDFdbid resDevice)
)
(when parasiticDevice
(setq parasiteModel
(or (TECHgetDeviceParam parasiticDevice 'hspiceModel) ""))
)
;; Update the resistance or resistor length, depending upon whether
;; the resistor is resistance driven or length driven.
;;
(when (nequal cdfgData->resistorType->value "Absolute")
(dbDeletePropByName CDFdbid "isAbsoluteRes")
(dbDeletePropByName CDFdbid "hide_rlwm")
(setq isRdriven (equal cdfgData->lrDriven->value "R Driven"))
(cond (isRdriven
(setq rl (CDFcalculateRes isRdriven r rm rw rl resDevice cdfgData CDFdbid~>rcon0m CDFdbid~>rcon1m))
(cond
((equal "string" cdfgData->rl->paramType)
(unless (stringp rl)
(setq rl (sprintf nil "%g" rl))
)
(dbReplaceProp CDFdbid "rl" "string" rl)
cdfgData->rl->value = rl
)
;; the old floating point case
(t
;; it should not get a string for rl if the CDF
;; has not been updated to be a string
(unless (numberp rl)
(warn "Resistor CDF type screwup\n")
)
(dbReplaceProp CDFdbid "rl" "float" rl)
cdfgData->rl->value = rl
)
)
;; now that we have an updated rl, make sure that the
;; tmprl does not override it with old data
(setq tmprl nil)
(when (and (stringp rl) (aelIsNumberP rl))
(setq tmprl rl)
(setq rl (aelNumber rl))
)
)
(t ; is length driven
(setq r (CDFcalculateRes isRdriven r rm rw rl resDevice cdfgData CDFdbid~>rcon0m CDFdbid~>rcon1m))
(cond
((equal "string" cdfgData->r->paramType)
(unless (stringp r)
(setq r (sprintf nil "%g" r))
)
(dbReplaceProp CDFdbid "r" "string" r)
cdfgData->r->value = r
)
(t
(unless (numberp r)
(warn "Resistor CDF type screwup\n")
)
(dbReplaceProp CDFdbid "r" "float" r)
cdfgData->r->value = r
)
)
)
)
)
;; Diff resistors "resn" and "resp" have diode parasitics.
;; Nwell resistors "resnw" have diode parasitics also.
;; Calculate the diode parasitics
(when (or (equal "resn" CDFdbid~>master~>cellName)
(equal "resp" CDFdbid~>master~>cellName)
(equal "resnw" CDFdbid~>master~>cellName))
;; resistor model
(dbReplaceProp CDFdbid "model" "string"
(TECHgetDeviceParam resDevice 'hspiceModel))
;; diode area
(cond
((and (numberp rl) (numberp rw) (numberp rm))
(dbReplaceProp CDFdbid "area" "float" (rl / 2.0 * rw * rm))
)
(t
(dbReplaceProp CDFdbid "area" "string"
(sprintf nil "(%s*%s*%s/2.0)"
(or tmprw rw)
(or tmprm rm)
(or tmprl rl)
)
)
)
)
;; diode perimeter
(cond
((and (numberp rl) (numberp rm))
(dbReplaceProp CDFdbid "perim" "float" (times rl rm))
)
(t
(dbReplaceProp CDFdbid "perim" "string"
(sprintf nil "(%s*%s)"
(or tmprl rl)
(or tmprm rm))
)
)
)
;; parasitic diode model
(dbReplaceProp CDFdbid "parasiteModel" "string" parasiteModel)
)
(when (and (equal "res" CDFdbid~>master~>cellName)
(exists x (TECHgetLayerProp cdf_this 'aliases)
((strncmp x "cdf_well" 8) == 0)))
(dbReplaceProp CDFdbid "model" "string"
(case (car (exists x (TECHgetLayerProp cdf_this 'aliases)
((strncmp x "cdf_well" 8) == 0)))
("cdf_well1" cdfgData->well1mod->value)
))
)
;; diff resistor with no parasitic diodes
(when (and (equal "res" CDFdbid~>master~>cellName)
(equal "diff" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string"
(TECHgetDeviceParam resDevice 'hspiceModel))
)
(when (and (equal "res" CDFdbid~>master~>cellName)
(exists x (TECHgetLayerProp cdf_this 'aliases)
((strncmp x "cdf_diff" 8) == 0)))
(dbReplaceProp CDFdbid "model" "string"
(case (car (exists x (TECHgetLayerProp cdf_this 'aliases)
((strncmp x "cdf_diff" 8) == 0)))
("cdf_diff1" cdfgData->diff1mod->value)
("cdf_diff2" cdfgData->diff2mod->value)
("cdf_diff3" cdfgData->diff3mod->value)
))
)
(when (and (equal "resnw" CDFdbid~>master~>cellName)
(exists x (TECHgetLayerProp cdf_this 'aliases)
((strncmp x "cdf_nwell" 8) == 0)))
(dbReplaceProp CDFdbid "model" "string"
(case (car (exists x (TECHgetLayerProp cdf_this 'aliases)
((strncmp x "cdf_nwell" 8) == 0)))
("cdf_nwell" cdfgData->nwellmod->value)
))
)
;; if it is a rescap, calculate the common cw and cl properties
(when (equal "rescap" CDFdbid~>master~>cellName)
;; first, the cl. We do not multiply the mfactor by the length
;; because we only multiply it by the width
(cond
((numberp rl)
(setq cltype "float")
(setq clval (quotient rl 2.0))
)
(t
(setq cltype "string")
(setq clval (sprintf nil "(%s/2.0)"
(or tmprl rl)
)
)
)
)
;; second, the cw
(cond
((and (numberp rm) (numberp rw))
(setq cwtype "float")
(setq cwval (times rm rw))
)
(t
(setq cwtype "string")
(setq cwval (sprintf nil "(%s*%s)"
(or tmprm rm)
(or tmprw rw)
)
)
)
)
)
;; If it is a poly resistor with capacitor parasitics
(when (and (equal "rescap" CDFdbid~>master~>cellName)
(member cdfgData->resistorType->value `("poly" ,cdf_poly1)))
;; cap segments
(when cdfgData->nlSegNum
(dbReplaceProp CDFdbid "cSegNum" "int" nlSegNum)
)
;; cap length
(dbReplaceProp CDFdbid "cl" cltype clval)
;; cap width
(dbReplaceProp CDFdbid "cw" cwtype cwval)
;; parasitic cap model
(dbReplaceProp CDFdbid "parasiteModel" "string" parasiteModel)
(dbReplaceProp CDFdbid "model" "string" cdfgData->rpmod->value)
)
;; poly resistor with no parasitic caps
(when (and (equal "res" CDFdbid~>master~>cellName)
(member cdfgData->resistorType->value `("poly" ,cdf_poly1)))
(dbReplaceProp CDFdbid "model" "string" cdfgData->rpmod->value)
)
;; If it is a rpoly resistor with capacitor parasitics
(when (and (equal "rescap" CDFdbid~>master~>cellName)
(equal "rpoly" cdfgData->resistorType->value))
;; cap length
(dbReplaceProp CDFdbid "cl" cltype clval)
;; cap width
(dbReplaceProp CDFdbid "cw" cwtype cwval)
;; parasitic cap model
(dbReplaceProp CDFdbid "parasiteModel" "string" parasiteModel)
(dbReplaceProp CDFdbid "model" "string" cdfgData->rpolymod->value)
)
;; rpoly resistor with no parasitic caps
(when (and (equal "res" CDFdbid~>master~>cellName)
(equal "rpoly" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string" cdfgData->rpolymod->value)
)
;; ad resistor with no parasitic caps
(when (and (equal "res3" CDFdbid~>master~>cellName)
(equal "ad" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string" cdfgData->rpolymod->value)
)
;; If it is a tfr resistor with capacitor parasitics
(when (and (equal "rescap" CDFdbid~>master~>cellName)
(equal "tfr" cdfgData->resistorType->value))
;; cap length
(dbReplaceProp CDFdbid "cl" cltype clval)
;; cap width
(dbReplaceProp CDFdbid "cw" cwtype cwval)
;; parasitic cap model
(dbReplaceProp CDFdbid "parasiteModel" "string" parasiteModel)
(dbReplaceProp CDFdbid "model" "string" cdfgData->tfrmod->value)
)
;; tfr resistor with no parasitic caps
(when (and (equal "res" CDFdbid~>master~>cellName)
(equal "tfr" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string" cdfgData->tfrmod->value)
)
;; pwell resistor
(when (equal "respw" CDFdbid~>master~>cellName)
(dbReplaceProp CDFdbid "model" "string" cdfgData->pwellmod->value)
)
;; If it is a li1 resistor with capacitor parasitics
(when (and (equal "rescap" CDFdbid~>master~>cellName)
(member cdfgData->resistorType->value `("li1" ,cdf_li1)))
;; cap segments
(when cdfgData->nlSegNum
(dbReplaceProp CDFdbid "cSegNum" "int" nlSegNum)
)
;; cap length
(dbReplaceProp CDFdbid "cl" cltype clval)
;; cap width
(dbReplaceProp CDFdbid "cw" cwtype cwval)
;; parasitic cap model
(dbReplaceProp CDFdbid "parasiteModel" "string" parasiteModel)
(dbReplaceProp CDFdbid "model" "string" cdfgData->limod->value)
)
;; li1 resistor with no parasitic caps
(when (and (equal "res" CDFdbid~>master~>cellName)
(member cdfgData->resistorType->value `("li1" ,cdf_li1)))
(dbReplaceProp CDFdbid "model" "string" cdfgData->limod->value)
)
;; If it is a nwell resistor with capactor parasitics
(when (and (equal "rescap" CDFdbid~>master~>cellName)
(member cdfgData->resistorType->value `("nwell" ,cdf_nwell)))
;; cap segments
(when cdfgData->nlSegNum
(dbReplaceProp CDFdbid "cSegNum" "int" nlSegNum)
)
;; cap length
(dbReplaceProp CDFdbid "cl" cltype clval)
;; cap width
(dbReplaceProp CDFdbid "cw" cwtype cwval)
;; parasitic cap model
(dbReplaceProp CDFdbid "parasiteModel" "string" parasiteModel)
(dbReplaceProp CDFdbid "model" "string" cdfgData->nwellmod->value)
)
;; nwell resistor with no parasitic caps
(when (and (equal "res" CDFdbid~>master~>cellName)
(member cdfgData->resistorType->value `("nwell" ,cdf_nwell)))
(dbReplaceProp CDFdbid "model" "string" cdfgData->nwellmod->value)
)
;; If it is a ddli resistor with capacitor parasitics
(when (and (equal "rescap" CDFdbid~>master~>cellName)
(member cdfgData->resistorType->value `("ddli" ,cdf_ddli)))
;; cap segments
(when cdfgData->nlSegNum
(dbReplaceProp CDFdbid "cSegNum" "int" nlSegNum)
)
;; cap length
(dbReplaceProp CDFdbid "cl" cltype clval)
;; cap width
(dbReplaceProp CDFdbid "cw" cwtype cwval)
;; parasitic cap model
(dbReplaceProp CDFdbid "parasiteModel" "string" parasiteModel)
(dbReplaceProp CDFdbid "model" "string" cdfgData->ddlimod->value)
)
;; ddli resistor with no parasitic caps
(when (and (equal "res" CDFdbid~>master~>cellName)
(member cdfgData->resistorType->value `("ddli" ,cdf_ddli)))
(dbReplaceProp CDFdbid "model" "string" cdfgData->ddlimod->value)
)
;; If it is a lm1 resistor with capacitor parasitics
(when (and (equal "rescap" CDFdbid~>master~>cellName)
(member cdfgData->resistorType->value `("lm1" ,cdf_lm1)))
;; cap segments
(when cdfgData->nlSegNum
(dbReplaceProp CDFdbid "cSegNum" "int" nlSegNum)
)
;; cap length
(dbReplaceProp CDFdbid "cl" cltype clval)
;; cap width
(dbReplaceProp CDFdbid "cw" cwtype cwval)
;; parasitic cap model
(dbReplaceProp CDFdbid "parasiteModel" "string" parasiteModel)
(dbReplaceProp CDFdbid "model" "string" cdfgData->lm1mod->value)
)
;; lm1 resistor with no parasitic caps
(when (and (equal "res" CDFdbid~>master~>cellName)
(member cdfgData->resistorType->value `("lm1" ,cdf_lm1)))
(dbReplaceProp CDFdbid "model" "string" cdfgData->lm1mod->value)
)
;; If it is a litr resistor with capacitor parasitics
(when (and (equal "rescap" CDFdbid~>master~>cellName)
(member cdfgData->resistorType->value `("litr" ,cdf_litr)))
;; cap segments
(when cdfgData->nlSegNum
(dbReplaceProp CDFdbid "cSegNum" "int" nlSegNum)
)
;; cap length
(dbReplaceProp CDFdbid "cl" cltype clval)
;; cap width
(dbReplaceProp CDFdbid "cw" cwtype cwval)
;; parasitic cap model
(dbReplaceProp CDFdbid "parasiteModel" "string" parasiteModel)
(dbReplaceProp CDFdbid "model" "string" cdfgData->litrmod->value)
)
;; litr resistor with no parasitic caps
(when (and (equal "res" CDFdbid~>master~>cellName)
(member cdfgData->resistorType->value `("litr" ,cdf_litr)))
(dbReplaceProp CDFdbid "model" "string" cdfgData->litrmod->value)
)
;; If it is a metal resistor with capacitor parasitics
(when (and (equal "rescap" CDFdbid~>master~>cellName)
(equal 0 (strncmp "met" cdfgData->resistorType->value 3)))
;; cap segments
(when cdfgData->nlSegNum
(dbReplaceProp CDFdbid "cSegNum" "int" nlSegNum)
)
;; cap length
(dbReplaceProp CDFdbid "cl" cltype clval)
;; cap width
(dbReplaceProp CDFdbid "cw" cwtype cwval)
;; parasitic cap model
(dbReplaceProp CDFdbid "parasiteModel" "string" parasiteModel)
(dbReplaceProp CDFdbid "model" "string"
(case cdfgData->resistorType->value
("met1" cdfgData->met1mod->value)
("met2" cdfgData->met2mod->value)
("met3" cdfgData->met3mod->value)
("met4" cdfgData->met4mod->value)
("met5" cdfgData->met5mod->value)
("met6" cdfgData->met6mod->value)
("met7" cdfgData->met7mod->value)
("met8" cdfgData->met8mod->value)
("metd" cdfgData->metdmod->value)
)
)
)
;; If it is a metal resistor with capacitor parasitics
(when (and (equal "rescap" CDFdbid~>master~>cellName)
(equal 0 (strncmp "m" cdfgData->resistorType->value 1))
(exists x (TECHgetLayerProp cdf_this 'aliases)
((strncmp x "cdf_met" 7) == 0)))
;; cap segments
(when cdfgData->nlSegNum
(dbReplaceProp CDFdbid "cSegNum" "int" nlSegNum)
)
;; cap length
(dbReplaceProp CDFdbid "cl" cltype clval)
;; cap width
(dbReplaceProp CDFdbid "cw" cwtype cwval)
;; parasitic cap model
(dbReplaceProp CDFdbid "parasiteModel" "string" parasiteModel)
(dbReplaceProp CDFdbid "model" "string"
(case (car (exists x (TECHgetLayerProp cdf_this 'aliases)
((strncmp x "cdf_met" 7) == 0)))
("cdf_met1" cdfgData->met1mod->value)
("cdf_met2" cdfgData->met2mod->value)
("cdf_met3" cdfgData->met3mod->value)
("cdf_met4" cdfgData->met4mod->value)
("cdf_met5" cdfgData->met5mod->value)
("cdf_met6" cdfgData->met6mod->value)
("cdf_met7" cdfgData->met7mod->value)
("cdf_met8" cdfgData->met8mod->value)
("cdf_metd" cdfgData->metdmod->value)
)
)
)
;; metal resistor with no parasitic caps
(when (and (equal "res" CDFdbid~>master~>cellName)
(equal 0 (strncmp "met" cdfgData->resistorType->value 3)))
(dbReplaceProp CDFdbid "model" "string"
(case cdfgData->resistorType->value
("met1" cdfgData->met1mod->value)
("met2" cdfgData->met2mod->value)
("met3" cdfgData->met3mod->value)
("met4" cdfgData->met4mod->value)
("met5" cdfgData->met5mod->value)
("met6" cdfgData->met6mod->value)
("met7" cdfgData->met7mod->value)
("met8" cdfgData->met8mod->value)
("metd" cdfgData->metdmod->value)
)
)
)
;; metal resistor with no parasitic caps
(when (and (equal "res" CDFdbid~>master~>cellName)
(equal 0 (strncmp "m" cdfgData->resistorType->value 1))
(exists x (TECHgetLayerProp cdf_this 'aliases)
((strncmp x "cdf_met" 7) == 0)))
(dbReplaceProp CDFdbid "model" "string"
(case (car (exists x (TECHgetLayerProp cdf_this 'aliases)
((strncmp x "cdf_met" 7) == 0)))
("cdf_met1" cdfgData->met1mod->value)
("cdf_met2" cdfgData->met2mod->value)
("cdf_met3" cdfgData->met3mod->value)
("cdf_met4" cdfgData->met4mod->value)
("cdf_met5" cdfgData->met5mod->value)
("cdf_met6" cdfgData->met6mod->value)
("cdf_met7" cdfgData->met7mod->value)
("cdf_met8" cdfgData->met8mod->value)
("cdf_metd" cdfgData->metdmod->value)
(t (warn "Unidentified metal layer"))
)
)
)
;; If it is a rdl resistor with capacitor parasitics
(when (and (equal "rescap" CDFdbid~>master~>cellName)
(equal "rdl" cdfgData->resistorType->value))
;; cap segments
(when cdfgData->nlSegNum
(dbReplaceProp CDFdbid "cSegNum" "int" nlSegNum)
)
;; cap length
(dbReplaceProp CDFdbid "cl" cltype clval)
;; cap width
(dbReplaceProp CDFdbid "cw" cwtype cwval)
;; parasitic cap model
(dbReplaceProp CDFdbid "parasiteModel" "string" parasiteModel)
(dbReplaceProp CDFdbid "model" "string" cdfgData->rdlmod->value)
)
;; rdl resistor with no parasitic caps
(when (and (equal "res" CDFdbid~>master~>cellName)
(equal "rdl" cdfgData->resistorType->value)
)
(dbReplaceProp CDFdbid "model" "string" cdfgData->rdlmod->value)
)
;; If it is a user defined resistor with capacitor parasitics
(when (and (equal "rescap" CDFdbid~>master~>cellName)
(equal "User" cdfgData->resistorType->value))
;; cap segments
(when cdfgData->nlSegNum
(dbReplaceProp CDFdbid "cSegNum" "int" nlSegNum)
)
;; cap length
(dbReplaceProp CDFdbid "cl" cltype clval)
;; cap width
(dbReplaceProp CDFdbid "cw" cwtype cwval)
;; parasitic cap model
(dbReplaceProp CDFdbid "parasiteModel" "string" cdfgData->userRcapModel->value)
(dbReplaceProp CDFdbid "model" "string" cdfgData->usermod->value)
(dbReplaceProp CDFdbid "rconUserValue" "string" cdfgData->userRconModel->value)
)
;; user defined resistor with no parasitic caps
(when (and (equal "res" CDFdbid~>master~>cellName)
(equal "User" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string" cdfgData->usermod->value)
)
(when (equal "Absolute" cdfgData->resistorType->value)
(dbDeletePropByName CDFdbid "rconUserValue")
(dbDeletePropByName CDFdbid "rl")
(dbDeletePropByName CDFdbid "rw")
(dbDeletePropByName CDFdbid "isPtype")
(dbDeletePropByName CDFdbid "perim")
(dbDeletePropByName CDFdbid "parasiteModel")
(if (and cdfgData->usermod->value
(stringp cdfgData->usermod->value)
(rexMatchp "[A-Za-z0-9]" cdfgData->usermod->value)
) then
(dbReplaceProp CDFdbid "model" "string" cdfgData->usermod->value)
else
(dbReplaceProp CDFdbid "model" "string" "res_abs")
)
(dbReplaceProp CDFdbid "isAbsoluteRes" "boolean" t)
(dbReplaceProp CDFdbid "hide_rlwm" "boolean" t)
)
(cond ((and (CDFresEnableRcons)
(or CDFdbid~>rcon0m CDFdbid~>rcon1m)
)
CDFdbid~>rconModel=(CDFresRconModel)
)
;; Get rid of the rcon properties when they aren't needed
(t
(dbDeletePropByName CDFdbid "rcon0m")
(dbDeletePropByName CDFdbid "rcon1m")
(dbDeletePropByName CDFdbid "userRconModel")
(dbDeletePropByName CDFdbid "rconModel")
)
)
(when (and (equal CDFdbid~>cellView~>viewName "schematic")
CDFdbid~>isParasitic
(nequal "FALSE" CDFdbid~>isParasitic)
)
(dbDeletePropByName CDFdbid "isParasitic")
(warn (sprintf nil "CDFresCallback: isParasitic property is illegal inside 'schematic'. Deleting property.\n"))
)
;; after it may have adjusted the cw and cl properties, adjust the
;; cw1 and cw2 properties for those caps that use width value lookup
;; tables in the spice simulator.
(when (member CDFdbid~>master~>cellName '("rescap"))
(CDFsetCapWidthProps CDFdbid parasiticDevice)
)
(when (member CDFdbid~>master~>cellName '("rescap" "res" "resn" "resp"))
;; some resistors have formulas - if so, we set rw1 and rw2
(CDFsetResWidthProps CDFdbid resDevice)
)
)
)
;;;
;;; CDFgres3Callback --
;;; This function is the CDF callback for when it needs to calculate
;;; the resistance for the resistor. Depending upon if it is resistance
;;; driven or length driven, series/parallel it will calculate and set
;;; either the "rl" or the "r" parameter.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFgres3Callback ()
(let (
(res cdfgData->res->value)
(seriesSegment cdfgData->seriesSegment->value)
(parallelSegment cdfgData->parallelSegment->value)
(contRes cdfgData->contRes->value)
(rl cdfgData->rl->value)
(rw cdfgData->rw->value)
(sheetR cdfgData->sheetR->value)
(deltaW cdfgData->deltaW->value) resGrid edgeCap areaCap )
(setq dev ,(TECHgetDevice ?name stringToSymbol(lowerCase(cdfgData->rtype->value))))
(setq resGrid ,(TECHgetLayerProp "rpoly" 'snapGrid))
;; (setq sheetR ,(TECHgetDeviceParam dev 'sheet))
(setq edgeCap ,(TECHgetRule "rpoly_nsub_cp"))
(setq areaCap ,(TECHgetRule "rpoly_nsub_ca"))
(unless deltaW (setq deltaW 0.0))
(if cdfgData->ser_par->value == "Series" then
cdfgData->invseriesSegment->value = (quotient 1.0 cdfgData->seriesSegment->value)
cdfgData->parallelSegment->value = 1
else
cdfgData->seriesSegment->value = 1
cdfgData->invseriesSegment->value = (quotient 1.0 cdfgData->seriesSegment->value)
)
(if cdfgData->res_len_dr->value == "Resistance" then
;; rl = (R*rm - headRes)*(rw - deltaW)/sheetResistance
(setq rle (quotient (times (difference (times (quotient res seriesSegment) parallelSegment)
contRes) (difference rw deltaW)) sheetR))
(setq rle (times (round (quotient rle resGrid)) resGrid))
cdfgData->rl->value = rle
(setq Res (quotient (times (plus (quotient (times rle sheetR) (difference rw deltaW)) contRes) seriesSegment) parallelSegment))
cdfgData->cres->value = Res
cdfgData->segRes->value = (quotient (times Res parallelSegment) seriesSegment)
cdfgData->TcontRes->value = quotient( times(contRes seriesSegment) parallelSegment)
cdfgData->area_cap->value = (times areaCap (difference rw deltaW) rle parallelSegment seriesSegment)
cdfgData->edge_cap->value = (times edgeCap rle parallelSegment seriesSegment)
cdfgData->total_cap->value = (plus (times 2 cdfgData->edge_cap->value) cdfgData->area_cap->value)
else
;; R = (headRes/rm)+(rl*sheetR)/(( rw - deltaW)*rm)
;; Res = (((rl*sheetR)/(rw - deltaW) + contRes)*seriesSegment)/parallelSegment
(setq Res (quotient (times (plus (quotient (times rl sheetR) (difference rw deltaW)) contRes) seriesSegment) parallelSegment))
cdfgData->cres->value = Res
cdfgData->res->value = Res
cdfgData->segRes->value = (quotient (times Res parallelSegment) seriesSegment)
cdfgData->TcontRes->value = (quotient (times contRes seriesSegment) parallelSegment)
cdfgData->area_cap->value = (times areaCap (difference rw deltaW) rl parallelSegment seriesSegment)
cdfgData->edge_cap->value = (times edgeCap rl parallelSegment seriesSegment)
cdfgData->total_cap->value = (plus (times 2 cdfgData->edge_cap->value) cdfgData->area_cap->value)
)
)
)
;;;
;;; CDFres3Callback --
;;; This function is the CDF callback for when it needs to calculate
;;; the resistance for the resistor. Depending upon if it is resistance
;;; driven or length driven, it will calculate and set either the "rl" or
;;; the "r" parameter.
;;; It will also update the parasitics if the res has parasitics.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFres3Callback (CDFdbid cdfgData)
(let (res3Device
isRdriven
(r cdfgData->r->value)
(rm (or cdfgData->rm->value 1))
(rw cdfgData->rw->value)
(rl cdfgData->rl->value)
nlSegNum
tmprw tmprl tmprm
cwtype cwval cltype clval
)
(when cdfgData->nlSegNum
(setq nlSegNum cdfgData->nlSegNum->value)
)
;; try to work with numbers, not strings
(when (stringp r)
(cond ((aelIsNumberP r)
(setq r (aelNumber r))
)
(t (setq r (strcat "(" r ")")))
)
)
(when (stringp rm)
(cond ((aelIsNumberP rm)
(setq rm (evalstring rm))
)
(t (setq rm (strcat "(" rm ")")))
)
)
(when (stringp rw)
(cond ((aelIsNumberP rw)
(setq rw (aelNumber rw))
)
(t (setq rw (strcat "(" rw ")")))
)
)
(when (stringp rl)
(cond ((aelIsNumberP rl)
(setq rl (aelNumber rl))
)
(t (setq rl (strcat "(" rl ")")))
)
)
;; we may need these values as strings
(when (numberp rl) (setq tmprl (sprintf nil "%g" rl)))
(when (numberp rw) (setq tmprw (sprintf nil "%g" rw)))
(when (numberp rm) (setq tmprm (sprintf nil "%d" rm)))
(setq res3Device
(CDFgetRes3TechrepDevice CDFdbid~>master~>cellName cdfgData))
;; Update the resistance or resistor length, depending upon whether
;; the resistor is resistance driven or length driven.
;;
(setq isRdriven (equal cdfgData->lrDriven->value "R Driven"))
(cond (isRdriven
(setq rl (CDFcalculateRes isRdriven r rm rw rl res3Device cdfgData CDFdbid~>rcon0m CDFdbid~>rcon1m))
(cond
((equal "string" cdfgData->rl->paramType)
(unless (stringp rl)
(setq rl (sprintf nil "%g" rl))
)
(dbReplaceProp CDFdbid "rl" "string" rl)
cdfgData->rl->value = rl
)
;; the old floating point case
(t
;; it should not get a string for rl if the CDF
;; has not been updated to be a string
(unless (numberp rl)
(warn "Resistor CDF type screwup\n")
)
(dbReplaceProp CDFdbid "rl" "float" rl)
cdfgData->rl->value = rl
)
)
;; now that we have an updated rl, make sure that the
;; tmprl does not override it with old data
(setq tmprl nil)
(when (and (stringp rl) (aelIsNumberP rl))
(setq tmprl rl)
(setq rl (aelNumber rl))
)
)
(t ; is length driven
(setq r (CDFcalculateRes isRdriven r rm rw rl res3Device cdfgData CDFdbid~>rcon0m CDFdbid~>rcon1m))
(cond
((equal "string" cdfgData->r->paramType)
(unless (stringp r)
(setq r (sprintf nil "%g" r))
)
(dbReplaceProp CDFdbid "r" "string" r)
cdfgData->r->value = r
)
(t
(unless (numberp r)
(warn "Resistor CDF type screwup\n")
)
(dbReplaceProp CDFdbid "r" "float" r)
cdfgData->r->value = r
)
)
)
)
;; rpoly resistor with no parasitic caps
(when (and (equal "res3" CDFdbid~>master~>cellName)
(equal "diff" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string" cdfgData->diffmod->value)
)
(when (and (equal "res3" CDFdbid~>master~>cellName)
(equal "poly" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string" cdfgData->polymod->value)
)
(when (and (equal "res3" CDFdbid~>master~>cellName)
(equal "rpoly" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string" cdfgData->rpolymod->value)
)
(when (and (equal "res3" CDFdbid~>master~>cellName)
(equal "ad" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string" cdfgData->admod->value)
)
(when (and (equal "res3" CDFdbid~>master~>cellName)
(equal "nd" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string" cdfgData->ndmod->value)
)
(when (and (equal "res3" CDFdbid~>master~>cellName)
(equal "pd" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string" cdfgData->pdmod->value)
)
(when (and (equal "res3" CDFdbid~>master~>cellName)
(equal "wn" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string" cdfgData->nwmod->value)
)
(when (and (equal "res3" CDFdbid~>master~>cellName)
(equal "tfr" cdfgData->resistorType->value))
(dbReplaceProp CDFdbid "model" "string" cdfgData->tfrmod->value)
)
(cond ((and (CDFresEnableRcons)
(or CDFdbid~>rcon0m CDFdbid~>rcon1m)
)
CDFdbid~>rconModel=(CDFresRconModel)
)
;; Get rid of the rcon properties when they aren't needed
(t
(dbDeletePropByName CDFdbid "rcon0m")
(dbDeletePropByName CDFdbid "rcon1m")
(dbDeletePropByName CDFdbid "userRconModel")
(dbDeletePropByName CDFdbid "rconModel")
)
)
(when (and (equal CDFdbid~>cellView~>viewName "schematic")
CDFdbid~>isParasitic
(nequal "FALSE" CDFdbid~>isParasitic)
)
(dbDeletePropByName CDFdbid "isParasitic")
(warn (sprintf nil "CDFres3Callback: isParasitic property is illegal inside 'schematic'. Deleting property.\n"))
)
)
)
;;;
;;; CDFsetCapSpaceProps --
;;; Some of our capacitor models have different values for the coefficients
;;; of the capacitor equation based on the space to the neighbor. This
;;; function will look at the techrep device for a capacitor and get the
;;; values of "space" for which we have discrete datapoints.
;;; It will then create or delete the properties "capSpace1" and "capSpace2".
;;; If neither get defined, this cap model does not support space values.
;;; If only capSpace1 is defined, it is the datapoint closest to this value.
;;; If both capSpace1 and capSpace2 are defined, this capacitor falls somewhere
;;; between the values for these two discrete datapoints.
;;;
;;; Input: CDFdbid - dbid of the instance to create/delete props on
;;; capDevice - techrep device for this capacitor
;;; Output:
;;; Globals:
;;; Side Effects: creates/deletes "capSpace1" and "capSpace2" values
;;; Return: t
;;;
(defun CDFsetCapSpaceProps (CDFdbid capDevice "dl")
(let
(spaceVals
prevSpace
thisSpace
targetSpace
thisLayer
)
(setq spaceVals (TECHgetDeviceParam capDevice 'spacings))
(setq thisLayer (TECHgetDeviceParam capDevice 'layers))
(cond
;; if it is a triple layer cap, the main layer is the middle one
((equal 3 (length thisLayer))
(setq thisLayer (cadr thisLayer))
)
;; if it is a two layer cap, the main layer is the first one
((equal 2 (length thisLayer))
(setq thisLayer (car thisLayer))
)
)
(setq targetSpace
(or CDFdbid~>space (TECHgetRuleWith "minSpacing" thisLayer) 0.0))
(when (and (stringp targetSpace) (aelIsNumberP targetSpace))
(setq targetSpace (aelNumber targetSpace))
)
(cond
;; if this cap does not support multiple values for different
;; spaces, delete the properties that store the spaces
((null spaceVals)
(dbDeletePropByName CDFdbid "capSpace1")
(dbDeletePropByName CDFdbid "capSpace2")
)
;; we do support various spaces for this cap model
(t
;; the spaceVals parameter should be sorted in increasing order.
(setq thisSpace (car spaceVals))
(setq spaceVals (cdr spaceVals))
(while (and spaceVals
(greaterp targetSpace
(plus thisSpace 1e-5)))
(setq prevSpace thisSpace)
(setq thisSpace (car spaceVals))
(setq spaceVals (cdr spaceVals))
)
(cond
;; 1. if this is > the last space value in the list, or
;; 2. if this is <= the first space value in the list, or
;; 3. if this is close enough to the current value in the list
;; use last space value it saw
((or (greaterp targetSpace thisSpace)
(null prevSpace)
(null (greaterp (abs (difference targetSpace thisSpace))
1e-5)))
(dbReplaceProp CDFdbid "capSpace1" "float" thisSpace)
(dbDeletePropByName CDFdbid "capSpace2")
)
;; if this is between two spacing values
(t
(dbReplaceProp CDFdbid "capSpace1" "float" thisSpace)
(dbReplaceProp CDFdbid "capSpace2" "float" prevSpace)
;; with two space values, it will use an equation and it is
;; required to have the "space" property
(unless CDFdbid~>space
(dbReplaceProp CDFdbid "space" "float" targetSpace)
)
)
)
)
)
)
;; be happy?
t
)
;;;
;;; CDFsetCapWidthProps --
;;; Very similar to CDFsetCapSpaceProps, but it works on the cap width.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFsetCapWidthProps (CDFdbid capDevice "dl")
(let
(thisLayer
widthVals
prevWidth
thisWidth
targetWidth
)
(setq widthVals (TECHgetDeviceParam capDevice 'widths))
(setq thisLayer (TECHgetDeviceParam capDevice 'layers))
(cond
;; if it is a triple layer cap, the main layer is the middle one
((equal 3 (length thisLayer))
(setq thisLayer (cadr thisLayer))
)
;; if it is a two layer cap, the main layer is the first one
((equal 2 (length thisLayer))
(setq thisLayer (car thisLayer))
)
)
;; unfortunately, they may have tried to optimize the width. If they
;; did, the cw property is not a number, but a parameterized equation.
;; Just default to the more inaccurate min width if they tried that.
;; It will interpolate from the evaluated width in the spice sim.
;;
(setq targetWidth (or CDFdbid~>rw CDFdbid~>cw))
(when (and (stringp targetWidth) (aelIsNumberP targetWidth))
(setq targetWidth (aelNumber targetWidth))
)
(when (or (null targetWidth) (stringp targetWidth))
(setq targetWidth (or (TECHgetRuleWith "minWidth" thisLayer) 0.0))
)
(cond
;; if this cap does not support multiple values for different
;; widths, delete the properties that store the widths
((null widthVals)
(dbDeletePropByName CDFdbid "cw1")
(dbDeletePropByName CDFdbid "cw2")
)
;; we do support various widths for this cap model
(t
;; the widthVals parameter should be sorted in increasing order.
(setq thisWidth (car widthVals))
(setq widthVals (cdr widthVals))
(while (and widthVals
(greaterp targetWidth
(plus thisWidth 1e-5)))
(setq prevWidth thisWidth)
(setq thisWidth (car widthVals))
(setq widthVals (cdr widthVals))
)
(cond
;; 1. if this is > the last width value in the list, or
;; 2. if this is <= the first width value in the list, or
;; 3. if this is close enough to the current value in the list
;; use last width value it saw
((or (greaterp targetWidth thisWidth)
(null prevWidth)
(null (greaterp (abs (difference targetWidth thisWidth))
1e-5)))
(dbReplaceProp CDFdbid "cw1" "float" thisWidth)
(dbDeletePropByName CDFdbid "cw2")
)
;; if this is between two spacing values
(t
(dbReplaceProp CDFdbid "cw1" "float" thisWidth)
(dbReplaceProp CDFdbid "cw2" "float" prevWidth)
;; with two width values, it will use an equation and it is
;; required to have the "width" property
(unless CDFdbid~>cw
(dbReplaceProp CDFdbid "cw" "float" targetWidth)
)
)
)
)
)
)
;; be happy?
t
)
;;;
;;; CDFsetResSpaceProps --
;;; Some of our resistor models have different values for the coefficients
;;; of the resistor equation based on the space to the neighbor. This
;;; function will look at the techrep device for a resistor and get the
;;; values of "space" for which we have discrete datapoints.
;;; It will then create or delete the properties "resSpace1" and "resSpace2".
;;; If neither get defined, this res model does not support space values.
;;; If only resSpace1 is defined, it is the datapoint closest to this value.
;;; If both resSpace1 and resSpace2 are defined, this resistor falls somewhere
;;; between the values for these two discrete datapoints.
;;;
;;; Input: CDFdbid - dbid of the instance to create/delete props on
;;; resDevice - techrep device for this resistor
;;; Output:
;;; Globals:
;;; Side Effects: creates/deletes "resSpace1" and "resSpace2" values
;;; Return: t
;;;
(defun CDFsetResSpaceProps (CDFdbid resDevice "dl")
(let
(spaceVals
prevSpace
thisSpace
targetSpace
thisLayer
)
(setq spaceVals (TECHgetDeviceParam resDevice 'spacings))
(setq thisLayer (TECHgetDeviceParam resDevice 'layer))
(setq targetSpace
(or CDFdbid~>space (TECHgetRuleWith "minSpacing" thisLayer) 0.0))
(when (and (stringp targetSpace) (aelIsNumberP targetSpace))
(setq targetSpace (aelNumber targetSpace))
)
(cond
;; if this res does not support multiple values for different
;; spaces, delete the properties that store the spaces
((null spaceVals)
(dbDeletePropByName CDFdbid "resSpace1")
(dbDeletePropByName CDFdbid "resSpace2")
)
;; we do support various spaces for this res model
(t
;; the spaceVals parameter should be sorted in increasing order.
(setq thisSpace (car spaceVals))
(setq spaceVals (cdr spaceVals))
(while (and spaceVals
(greaterp targetSpace
(plus thisSpace 1e-5)))
(setq prevSpace thisSpace)
(setq thisSpace (car spaceVals))
(setq spaceVals (cdr spaceVals))
)
(cond
;; 1. if this is > the last space value in the list, or
;; 2. if this is <= the first space value in the list, or
;; 3. if this is close enough to the current value in the list
;; use last space value it saw
((or (greaterp targetSpace thisSpace)
(null prevSpace)
(null (greaterp (abs (difference targetSpace thisSpace))
1e-5)))
(dbReplaceProp CDFdbid "resSpace1" "float" thisSpace)
(dbDeletePropByName CDFdbid "resSpace2")
)
;; if this is between two spacing values
(t
(dbReplaceProp CDFdbid "resSpace1" "float" thisSpace)
(dbReplaceProp CDFdbid "resSpace2" "float" prevSpace)
;; with two space values, it will use an equation and it is
;; required to have the "space" property
(unless CDFdbid~>space
(dbReplaceProp CDFdbid "space" "float" targetSpace)
)
)
)
)
)
)
;; be happy?
t
)
;;;
;;; CDFsetResWidthProps --
;;; Very similar to CDFsetResSpaceProps, but it works on the res width.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFsetResWidthProps (CDFdbid resDevice "dl")
(let
(thisLayer
widthVals
prevWidth
thisWidth
targetWidth
)
(setq widthVals (TECHgetDeviceParam resDevice 'widths))
(setq thisLayer (TECHgetDeviceParam resDevice 'layer))
;; unfortunately, they may have tried to optimize the width. If they
;; did, the cw property is not a number, but a parameterized equation.
;; Just default to the more inaccurate min width if they tried that.
;; It will interpolate from the evaluated width in the spice sim.
;;
(setq targetWidth CDFdbid~>rw)
(when (and (stringp targetWidth) (aelIsNumberP targetWidth))
(setq targetWidth (aelNumber targetWidth))
)
(when (or (null targetWidth) (stringp targetWidth))
(setq targetWidth (or (TECHgetRuleWith "minWidth" thisLayer) 0.0))
)
(cond
;; if this res does not support multiple values for different
;; widths, delete the properties that store the widths
((null widthVals)
(dbDeletePropByName CDFdbid "rw1")
(dbDeletePropByName CDFdbid "rw2")
)
;; we do support various widths for this res model
(t
;; the widthVals parameter should be sorted in increasing order.
(setq thisWidth (car widthVals))
(setq widthVals (cdr widthVals))
(while (and widthVals
(greaterp targetWidth
(plus thisWidth 1e-5)))
(setq prevWidth thisWidth)
(setq thisWidth (car widthVals))
(setq widthVals (cdr widthVals))
)
(cond
;; 1. if this is > the last width value in the list, or
;; 2. if this is <= the first width value in the list, or
;; 3. if this is close enough to the current value in the list
;; use last width value it saw
((or (greaterp targetWidth thisWidth)
(null prevWidth)
(null (greaterp (abs (difference targetWidth thisWidth))
1e-5)))
(dbReplaceProp CDFdbid "rw1" "float" thisWidth)
(dbDeletePropByName CDFdbid "rw2")
)
;; if this is between two spacing values
(t
(dbReplaceProp CDFdbid "rw1" "float" thisWidth)
(dbReplaceProp CDFdbid "rw2" "float" prevWidth)
)
)
)
)
)
;; be happy?
t
)
(defun CDFcapCallback (CDFdbid cdfgData "do")
(cond
;; if it is an absolute cap, make sure the isSubckt is blown away
((and CDFdbid~>isAbsoluteCap (nequal "FALSE" CDFdbid~>isAbsoluteCap))
(dbDeletePropByName CDFdbid "isSubckt")
(dbDeletePropByName CDFdbid "capSpace1")
(dbDeletePropByName CDFdbid "capSpace2")
)
;; if it is not an absolute cap, get the cap spacing and isSubckt
;; properties squared away
(t
(let (capDevices thisCap)
(setq capDevices (TECHgetCapDevices))
(setq thisCap (car capDevices))
;; loop through all the caps looking for the one with this model
(while (and thisCap
(nequal CDFdbid~>ctype
(TECHgetDeviceParam thisCap 'hspiceModel))
)
(setq thisCap (car capDevices))
(setq capDevices (cdr capDevices))
)
(cond
(thisCap
;; set the "space" properties if applicable
(CDFsetCapSpaceProps CDFdbid thisCap)
(CDFsetCapWidthProps CDFdbid thisCap)
;; see if this is a subckt cap model, and create or delete
;; the isSubckt property accordingly
(cond
((TECHgetDeviceParam thisCap 'isSubckt)
(dbReplaceProp CDFdbid "isSubckt" "boolean" t)
)
(t
(dbDeletePropByName CDFdbid "isSubckt")
)
)
)
(t
(dbDeletePropByName CDFdbid "capSpace1")
(dbDeletePropByName CDFdbid "capSpace2")
(dbDeletePropByName CDFdbid "isSubckt")
)
)
)
)
)
)
;;;
;;; CDFthinoxCapCallback --
;;; This function is for the thinoxide capacitor devices (ncap2/pcap2).
;;; It will calculate the w & l based on the area and perimeter.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFthinoxCapCallback (CDFdbid cdfgData "do")
;; call the CDFcapCallback callback
(CDFcapCallback CDFdbid cdfgData)
;; Derive missing parameters. When deriving w/l from a/p, we solve
;; quadratic if possible, assigning larger dimension to length. If
;; no solution, we make up something the same way extraction does.
(cond
((cdfgData->apMode->value == "Width & Length")
(let (wval lval)
(setq wval cdfgData->cw->value)
(setq lval cdfgData->cl->value)
(cond
((and (aelIsNumberP wval) (aelIsNumberP lval))
(setq wval (aelNumber wval))
(setq lval (aelNumber lval))
(dbReplaceProp CDFdbid "a" "float" (times wval lval))
(dbReplaceProp CDFdbid "p" "float"
(times 2 (plus wval lval))
)
)
(t
(cond
((numberp wval) (setq wval (sprintf nil "%g" wval)))
((null (aelIsNumberP wval) (setq wval (strcat "(" wval ")"))))
(t t)
)
(cond
((numberp lval) (setq lval (sprintf nil "%g" lval)))
((null (aelIsNumberP lval) (setq lval (strcat "(" lval ")"))))
(t t)
)
(dbReplaceProp CDFdbid "a" "string"
(sprintf nil "(%s*%s)" wval lval))
(dbReplaceProp CDFdbid "p" "string"
(sprintf nil "((2*%s)+(2*%s))" wval lval))
)
)
)
)
(t
(let ((a cdfgData->a->value)
(p cdfgData->p->value)
(w 0.0)
(l 0.0)
det)
(when (and (stringp a) (aelIsNumberP a))
(setq a (aelNumber a))
)
(when (and (stringp p) (aelIsNumberP p))
(setq p (aelNumber p))
)
(cond
;; if they are both numbers, do what we always have done
((and (numberp a) (numberp p))
det = p ** 2.0 - 16.0 * a
(cond
((and (det >= 0) ((setq det (sqrt det)) < p)) ; quadratic has real solutions
w = (p - det) / 4.0
l = (p + det) / 4.0)
((p > 0) ; bogus derivation, matches extraction algorthim
l = p / 6.0
w = a / l))
(dbReplaceProp CDFdbid "cw" "float" w)
(dbReplaceProp CDFdbid "cl" "float" l)
)
;; if one or both of a/p are params, do it as an equation
(t
;; make sure a and p are strings
(when (numberp a)
(setq a (sprintf nil "%g" a))
)
(when (numberp p)
(setq p (sprintf nil "%g" p))
)
;; taking a sqrt of what may be a negative number, but
;; let the users shoot themselves in the foot
(setq det (sprintf nil "sqrt((%s*%s)-(16.0*%s))" p p a))
(setq w (sprintf nil "((%s-%s)/4.0)" p det))
(setq l (sprintf nil "((%s+%s)/4.0)" p det))
(dbReplaceProp CDFdbid "cw" "string" w)
(dbReplaceProp CDFdbid "cl" "string" l)
)
)
)
)
)
)
;;;
;;; CDFshowNameKludge --
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFshowNameKludge (cdfDbid showName "dg")
(cond (showName
(dbReplaceProp cdfDbid "showName" "boolean" t)
)
(t
(dbDeletePropByName cdfDbid "showName")
)
)
)
;;;
;;; CDFsetAllResModelInfo --
;;; This function is called when the restype/model has changed for
;;; a resistor without parasitics. It will update the model description
;;; field with the correct description of the resistor chosen.
;;; It will also check if the model has a constant width. It will
;;; make the "rw" field editable/noneditable accordingly.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFsetAllResModelInfo (resCellName cdfgData "to")
(let (resDevice res3Device resModelDescription tmpW constantW)
;; get the tech rep resistor device
(setq resDevice (CDFgetResTechrepDevice resCellName cdfgData))
(setq res3Device (CDFgetRes3TechrepDevice resCellName cdfgData))
(cond
(resDevice
(setq resModelDescription
(or (TECHgetDeviceParam resDevice 'description)
"No description available"))
(setq constantW (TECHgetDeviceParam resDevice 'constantWidth))
)
(res3Device
(setq resModelDescription
(or (TECHgetDeviceParam res3Device 'description)
"No description available"))
(setq constantW (TECHgetDeviceParam res3Device 'constantWidth))
)
((equal "Absolute" cdfgData->resistorType->value)
(setq resModelDescription "Absolute resistor")
)
(t
(setq resModelDescription "Error: cannot find resistor")
)
)
;; set the resistor model description into the cdf form
cdfgData->resistorModelInfo->value = resModelDescription
;; If the resistor selected is a constant width resistor,
;; set the rw and make the field default to only one value.
(when constantW
(when (aelIsNumberP cdfgData->rw->value)
(setq tmpW (aelNumber cdfgData->rw->value))
)
(when (nequal tmpW constantW)
; (warn "Value of the constant width resistor can not be changed\n")
;; rw field is a string now that we have AEL expressions,
;; but still support it if it is a float field
(cond
((equal "float" cdfgData->rw->paramType)
cdfgData->rw->value = (aelNumber constantW)
)
((equal "string" cdfgData->rw->paramType)
cdfgData->rw->value = (sprintf nil "%g" (aelNumber constantW))
)
)
)
)
(cond
((TECHgetDeviceParam resDevice 'isSubckt)
cdfgData->isSubckt->value = t
)
((TECHgetDeviceParam res3Device 'isSubckt)
cdfgData->isSubckt->value = t
)
(t
cdfgData->isSubckt->value = nil
)
)
)
)
(defun CDFsetResModelInfo (cdfgData "o")
(CDFsetAllResModelInfo "res" cdfgData)
)
(defun CDFsetRescapModelInfo (cdfgData "o")
(CDFsetAllResModelInfo "rescap" cdfgData)
)
(defun CDFsetResnModelInfo (cdfgData "o")
(CDFsetAllResModelInfo "resn" cdfgData)
)
(defun CDFsetResnwModelInfo (cdfgData "o")
(CDFsetAllResModelInfo "resnw" cdfgData)
)
(defun CDFsetRespModelInfo (cdfgData "o")
(CDFsetAllResModelInfo "resp" cdfgData)
)
(defun CDFsetRespwModelInfo (cdfgData "o")
(CDFsetAllResModelInfo "respw" cdfgData)
)
(defun CDFsetReslocsubModelInfo (cdfgData "o")
(CDFsetAllResModelInfo "reslocsub" cdfgData)
)
(defun CDFsetRes3ModelInfo (cdfgData "o")
(CDFsetAllResModelInfo "res3" cdfgData)
)
;; Hardcoding sheetR, deltaW & contactRes to mimic b53d-3GR process
;; Eventually will be removed when the templates are in place
(defun CDFsetGres3ModelInfo ()
let((dev)
case( cdfgData->rtype->value
("RA1"
dev = (TECHgetDevice ?name stringToSymbol(lowerCase(cdfgData->rtype->value)))
cdfgData->rw->value = (TECHgetDeviceParam dev 'constantWidth)
;;cdfgData->contRes->value = (TECHgetDeviceParam dev 'headRes)
cdfgData->rpolymod->value = (TECHgetDeviceParam dev 'hspiceModel)
;;cdfgData->deltaW->value = (TECHgetDeviceParam dev 'deltaW)
cdfgData->contRes->value = 120.0
cdfgData->deltaW->value = 0.4518
cdfgData->sheetR->value = 270.0
cdfgData->isSubckt->value = (TECHgetDeviceParam dev 'isSubckt)
cdfgData->contactNames->value = "RAconRPL1 RAconL1M1"
)
("RA2"
dev = (TECHgetDevice ?name stringToSymbol(lowerCase(cdfgData->rtype->value)))
cdfgData->rw->value = (TECHgetDeviceParam dev 'constantWidth)
;;cdfgData->contRes->value = (TECHgetDeviceParam dev 'headRes)
cdfgData->rpolymod->value = (TECHgetDeviceParam dev 'hspiceModel)
;;cdfgData->deltaW->value = (TECHgetDeviceParam dev 'deltaW)
cdfgData->isSubckt->value = (TECHgetDeviceParam dev 'isSubckt)
cdfgData->contRes->value = 60.0
cdfgData->deltaW->value = 0.8358
cdfgData->sheetR->value = 270.0
cdfgData->contactNames->value = "RAconRPL1 RAconL1M1"
)
("RD1"
dev = (TECHgetDevice ?name stringToSymbol(lowerCase(cdfgData->rtype->value)))
cdfgData->rw->value = (TECHgetDeviceParam dev 'constantWidth)
;;cdfgData->contRes->value = (TECHgetDeviceParam dev 'headRes)
cdfgData->rpolymod->value = (TECHgetDeviceParam dev 'hspiceModel)
;;cdfgData->deltaW->value = (TECHgetDeviceParam dev 'deltaW)
cdfgData->isSubckt->value = (TECHgetDeviceParam dev 'isSubckt)
cdfgData->contactNames->value = "RDconRPL1 RDconL1M1"
cdfgData->contRes->value = 200.0
cdfgData->deltaW->value = 0.25
cdfgData->sheetR->value = 270.0
)
)
CDFgres3Callback()
)
)
(defun CDFsetRconModelInfo (cdfgData "o")
(let (rconModel doping tmpParse layerDown layerUp)
(setq rconModel
(car
(remq nil
(mapcar
(lambda (x)
(setq tmpParse (parseString (or cdfgData->resistorType->value "") " -"))
(when (equal 2 (length tmpParse))
(setq layerDown (car tmpParse))
(setq layerUp (cadr tmpParse))
(when (and (equal layerDown
(TECHgetDeviceParam x 'layerDown))
(equal layerUp
(TECHgetDeviceParam x 'layerUp)))
(cond
((equal layerDown "diff")
(setq doping
(TECHgetDeviceParam x 'doping))
(when (or (and (equal doping "n")
(or (null cdfgData->isPtype->value)
(equal cdfgData->isPtype->value "FALSE")))
(and (equal doping "p")
(and cdfgData->isPtype->value
(nequal "FALSE" cdfgData->isPtype->value)))
)
(TECHgetDeviceParam x 'hspiceModel)
)
)
(t (TECHgetDeviceParam x 'hspiceModel))
)
) ; closing when layers match
) ; closing when parse returned two layers
) ;closing lambda
(TECHgetRconDevices)
)
)
)
)
cdfgData->model->value = rconModel
)
)
;;;
;;; CDFrconCallback --
;;; This function is the callback for the rcon device. If it is in a simsch,
;;; everything is ok. If it is in a schematic, have a cow, because it will
;;; never lvs.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFrconCallback (CDFdbid)
(when (or (null CDFdbid~>isParasitic)
(equal "FALSE" CDFdbid~>isParasitic)
)
(dbReplaceProp CDFdbid "isParasitic" "boolean" "TRUE")
(warn (sprintf nil "CDFrconCallback: isParasitic must be set for a rcon. Resetting property.\n"))
)
(when (and (equal CDFdbid~>cellView~>viewName "schematic")
CDFdbid~>isParasitic
(nequal "FALSE" CDFdbid~>isParasitic)
)
(dbDeleteObject CDFdbid)
(warn (sprintf nil "CDFrconCallback: rcon instances are illegal inside 'schematic'. Deleting instance.\n"))
)
)
;;;
;;; CDFadjustHspiceToAel --
;;; This is an ugly kludgy transition function between the ol Hspice days
;;; and the newer CDF AEL expression days. It will look at old string values
;;; that probably represented numbers. Because Hspice is an antique case
;;; insensitive program, it could not distinguish between the unit suffixes
;;; of "m" or "M". Therefore, it treated either "m" or "M" as milli-units,
;;; and "Meg" (and permutations) as mega-units.
;;; We had let the users manually type in these values, but now as we
;;; move some of the CDF fields to do the AEL parseAsNumber and parseAsCel
;;; dance, we have to correctly distinguish between "m" and "M". This is
;;; a hassle for preexisting instances. This should be called as a part of
;;; the CDF init procedures to automagically update the CDF fields to have
;;; the new syntax, and to store a property that will tell the Hspice
;;; netlister that it should replace the "M" with "Meg".
;;; In order to prevent the update happening repeatedly for the same
;;; instance, it will remember if it has already adjusted this instance
;;; with the "updatedForAel" property.
;;;
;;; Input: cdfId and the symbols of properties to be examined/updated
;;; Output:
;;; Globals:
;;; Side Effects: nothing if "updatedForAel" is already set
;;; Return:
;;;
(defun CDFadjustHspiceToAel (cdfId theProps)
(let
(propVal doneit value tmpStr tmpNum)
(setq doneit cdfgData->updatedForAel->value)
(when (equal "FALSE" doneit) (setq doneit nil))
(unless doneit
(unless (listp theProps)
(setq theProps (list theProps))
)
(foreach prop theProps
(setq propVal (get (get cdfgData prop) 'value))
(when (stringp propVal)
;; update the old "M" suffix to be "m"
(when (aelIsNumberP propVal)
(when (setq tmpStr (index propVal "M"))
(setq propVal (strcat (substring propVal 1 (difference (strlen propVal) (strlen tmpStr))) "m" (or (substring tmpStr 2) "")))
(get cdfgData prop)->value = propVal
)
)
;; update the old "meg" suffix to be "M"
(foreach meg '("meg" "Meg" "mEg" "meG" "MEg" "MeG" "mEG" "MEG")
(when (setq tmpStr (index propVal meg))
(setq propVal (strcat (substring propVal 1 (difference (strlen propVal) (strlen tmpStr))) "M" (or (substring tmpStr 4) "")))
(get cdfgData prop)->value = propVal
)
)
;; update the old mils suffix to be a number
(foreach mi '("mi" "Mi" "mI" "MI")
(when (setq tmpStr (index propVal mi))
(setq tmpNum (atof (substring propVal 1 (difference (strlen propVal) (strlen tmpStr)))))
(when tmpNum
(setq tmpNum (times 25.4e-6 tmpNum))
(setq propVal (sprintf nil "%g" tmpNum))
(get cdfgData prop)->value = propVal
)
)
)
)
)
cdfgData->updatedForAel->value = t
)
)
)
(defun CDFcap2Init (cdfId "o")
(CDFadjustHspiceToAel cdfId 'c)
(CDFcommonInit cdfId)
)
(defun CDFcap_int3Init (cdfId "o")
(CDFadjustHspiceToAel cdfId 'c)
(CDFcommonInit cdfId)
)
(defun CDFvppcapInit (cdfId "o")
(CDFadjustHspiceToAel cdfId 'c)
(CDFcommonInit cdfId)
)
(defun CDFsoiInit (cdfId "o")
(CDFadjustHspiceToAel cdfId '(DCValue ACMag ACPhase))
(CDFcommonInit cdfId)
)
(defun CDFsovInit (cdfId "o")
(CDFadjustHspiceToAel cdfId '(DCValue ACMag ACPhase))
(CDFcommonInit cdfId)
)
(defun CDFtransLineInit (cdfId "o")
(CDFadjustHspiceToAel cdfId '(TD L Z0))
(CDFcommonInit cdfId)
)
(defun CDFinductorInit (cdfId "o")
(CDFadjustHspiceToAel cdfId '(l k ic))
;; we're obsoleting initial current as a separate type, and allowing
;; ic to be set for all the basic inductors. If it was ic, set it
;; to type "Normal"
(when (equal "Initial Current" cdfgForm~>objId~>indType)
cdfgData->indType->value = "Normal"
)
(CDFcommonInit cdfId)
)
(defun CDFresInit (cdfId "o")
(CDFsetResModelInfo cdfId)
(CDFadjustHspiceToAel cdfId 'r)
(CDFverInit cdfId)
(CDFcommonInit cdfId)
)
(defun CDFrconInit (cdfId "o")
(CDFsetRconModelInfo cdfId)
(CDFverInit cdfId)
(CDFcommonInit cdfId)
)
(defun CDFrescapInit (cdfId "o")
(CDFsetRescapModelInfo cdfId)
(CDFverInit cdfId)
(CDFcommonInit cdfId)
)
(defun CDFresnwInit (cdfId "o")
(CDFsetResnwModelInfo cdfId)
(CDFverInit cdfId)
(CDFcommonInit cdfId)
)
(defun CDFresnInit (cdfId "o")
(CDFsetResnModelInfo cdfId)
(CDFverInit cdfId)
(CDFcommonInit cdfId)
)
(defun CDFrespInit (cdfId "o")
(CDFsetRespModelInfo cdfId)
(CDFverInit cdfId)
(CDFcommonInit cdfId)
)
(defun CDFrespwInit (cdfId "o")
(CDFsetRespwModelInfo cdfId)
(CDFverInit cdfId)
(CDFcommonInit cdfId)
)
(defun CDFreslocsubInit (cdfId "o")
(CDFsetReslocsubModelInfo cdfId)
(CDFverInit cdfId)
(CDFcommonInit cdfId)
)
(defun CDFres3Init (cdfId "o")
(CDFsetRes3ModelInfo cdfId)
(CDFverInit cdfId)
(CDFcommonInit cdfId)
)
(defun CDFgres3Init (cdfId "o")
(CDFsetGres3ModelInfo)
;;(CDFverInit cdfId)
(CDFcommonInit cdfId)
)
(defun CDFresDone (CDFdbid "d")
(CDFresCallback CDFdbid cdfgData)
(CDFverilogTrTfDoneCheck CDFdbid)
(CDFcommonDone CDFdbid)
)
(defun CDFres3Done (CDFdbid "d")
(CDFres3Callback CDFdbid cdfgData)
(CDFverilogTrTfDoneCheck CDFdbid)
(CDFcommonDone CDFdbid)
)
(defun CDFgres3Done (CDFdbid "d")
nil
;;(CDFres3Callback CDFdbid cdfgData) ;; Removed since has field callback
;;(CDFverilogTrTfDoneCheck CDFdbid)
;;(CDFcommonDone CDFdbid) ;; Removed since does not have preShowName field
)
(defun CDFrconDone (CDFdbid "d")
(CDFverilogTrTfDoneCheck CDFdbid)
(CDFcommonDone CDFdbid)
(CDFrconCallback CDFdbid)
)
;;;
;;; CDFdiodeModelChange --
;;; When the model changes, update other fields on the form
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFdiodeModelChange ()
(let ((device (TECHgetDevice ?cellName "diode" ?name
(concat cdfgData->model->value)
)
)
)
cdfgData->isPtype->value = (equal "p" (TECHgetDeviceParam device 'doping))
)
)
;;;
;;; CDFcondiodeModelChange --
;;; When the model changes, update other fields on the form
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcondiodeModelChange ()
(let ((device (TECHgetDevice ?cellName "diode" ?name
(concat cdfgData->simmodel->value)
)
)
)
cdfgData->isPtype->value = (equal "p" (TECHgetDeviceParam device 'doping))
)
)
;;;
;;; CDFdiodeCallback --
;;; The diode has cases where the device name and the hspice model name
;;; are not equal. When this happens, an hspiceModel property is created.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFdiodeCallback (CDFdbid "d")
(let ((device (TECHgetDevice ?cellName "diode" ?name
(concat cdfgData->model->value)
)
)
isSubckt
)
(cond
((equal (strcat (TECHgetDeviceParam device 'name))
(TECHgetDeviceParam device 'hspiceModel)
)
;; Remove any hspice specific model property
(dbDeletePropByName CDFdbid "hspiceModel")
)
(t
CDFdbid~>hspiceModel=(TECHgetDeviceParam device 'hspiceModel)
)
)
;; create or delete the isSubckt property
(setq isSubckt (TECHgetDeviceParam device 'isSubckt))
(cond
(isSubckt
(dbReplaceProp CDFdbid "isSubckt" "boolean" "TRUE")
)
(t (dbDeletePropByName CDFdbid "isSubckt"))
)
)
)
;;;
;;; CDFconDiodeCallback --
;;; The diode has cases where the device name and the hspice model name
;;; are not equal. When this happens, an hspiceModel property is created.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFconDiodeCallback (CDFdbid "d")
(let ((device (TECHgetDevice ?cellName "diode" ?name
(concat cdfgData->simmodel->value)
)
)
isSubckt
)
(cond
((equal (strcat (TECHgetDeviceParam device 'name))
(TECHgetDeviceParam device 'hspiceModel)
)
;; Remove any hspice specific model property
(dbDeletePropByName CDFdbid "hspiceModel")
)
(t
CDFdbid~>hspiceModel=(TECHgetDeviceParam device 'hspiceModel)
)
)
;; create or delete the isSubckt property
(setq isSubckt (TECHgetDeviceParam device 'isSubckt))
(cond
(isSubckt
(dbReplaceProp CDFdbid "isSubckt" "boolean" "TRUE")
)
(t (dbDeletePropByName CDFdbid "isSubckt"))
)
)
)
(defun CDFdiodeDone (CDFdbid "d")
(CDFdiodeCallback CDFdbid)
(CDFcommonDone CDFdbid)
)
(defun CDFcondiodeDone (CDFdbid "d")
(CDFconDiodeCallback CDFdbid)
(CDFcommonDone CDFdbid)
)
(defun CDFthinoxCapDone (CDFdbid "d")
(CDFthinoxCapCallback CDFdbid cdfgData)
(CDFcommonDone CDFdbid)
)
(defun CDFcapDone (CDFdbid "d")
(CDFcapCallback CDFdbid cdfgData)
(CDFcommonDone CDFdbid)
)
(defun CDFfetDone (CDFdbid "d")
(CDFfetCallback CDFdbid)
(CDFverilogTrTfDoneCheck CDFdbid)
(CDFcommonDone CDFdbid)
)
(defun CDFfetextdDone (CDFdbid "d")
(CDFfetextdCallback CDFdbid)
(CDFverilogTrTfDoneCheck CDFdbid)
(CDFcommonDone CDFdbid)
)
(defun CDFlogicDone (CDFdbid "d")
(CDFlogicCallback CDFdbid)
(cond
((null (member CDFdbid~>cellName '("csw_p" "bkeep_p" "einv_p")))
(CDFverilogTrTfDoneCheck CDFdbid)
)
((member CDFdbid~>cellName '("einv_p"))
(CDFverilogTrTfDoneCheckBehavioral CDFdbid)
)
)
(CDFcommonDone CDFdbid)
)
(defun CDFcswDone (CDFdbid "d")
(CDFlogicCallback CDFdbid)
(CDFcommonDone CDFdbid)
)
(defun CDFbcdiodeDone (CDFdbid "d")
(CDFbcdiodeCallback CDFdbid)
(CDFcommonDone CDFdbid)
)
;;;
;;; CDFmNormTranDone --
;;; This callback is applied to the CDFs for the mNormTranClass
;;; device library elements. It sets the contact fields based off
;;; the descriptive names given in the CDFs.
;;;
(defun CDFmNormTranDone (cdfDbId)
(let ((techFileId (techGetTechFile cdfDbId~>master~>lib)))
(dbReplaceProp cdfDbId "firstContact" "string"
(DLgetSDcontactWithDescription techFileId
cdfgData->firstContactParam->value))
(dbReplaceProp cdfDbId "lastContact" "string"
(DLgetSDcontactWithDescription techFileId
cdfgData->lastContactParam->value))
(dbReplaceProp cdfDbId "sharedSource" "string"
(DLgetSDcontactWithDescription techFileId
cdfgData->shSrcParam->value))
(dbReplaceProp cdfDbId "sharedDrain" "string"
(DLgetSDcontactWithDescription techFileId
cdfgData->shDrnParam->value))
t
)
)
;;;
;;; CDFmNormTranInit --
;;; This callback is applied to intialize the CDFs for the mNormTranClass
;;; device library elements when used in disctret modes.
;;; It sets the model name, and W/L pull down menu based on the
;;; idLayer, length and width values.
;;;
(defun CDFmNormTranInit (cdfgData)
(let ((techFileId (techGetTechFile cdfgData~>id~>lib)) (cellName cdfgData~>id~>name)
modelName modelChoices idLayerName Lparam Wparam lengthIndex
lengthValue lengthChoices widthValue widthChoices)
(setq idLayerName cdfgData~>idLayer->value)
(setq modelChoices
(parseString
(techGetDeviceProp techFileId cellName "symbolic"
(strcat idLayerName "Models")) " "))
(foreach model modelChoices
;;Construct the Lparam name
(setq Lparam (strcat (concat model "_l")))
(setq lengthChoices (get (get cdfgData Lparam) 'choices))
;;Need to do this to grab the values with the decimal precision as stored
(mapcar (lambda (x) (when (equal (atof x) cdfgData->l->value)
(setq lengthValue x)))
lengthChoices)
(when (member lengthValue lengthChoices)
(setq lengthIndex (difference (length lengthChoices) (length (member lengthValue lengthChoices))))
;;Construct the Wparam name
(setq Wparam (strcat (concat Lparam lengthIndex "_w")))
(setq widthChoices (get (get cdfgData Wparam) 'choices))
(mapcar (lambda (x) (when (equal (atof x) cdfgData->w->value)
(setq widthValue x)))
widthChoices)
(when (member widthValue widthChoices)
(putprop (get cdfgData idLayerName) model 'value)
(putprop (get cdfgData Lparam) lengthValue 'value)
(putprop (get cdfgData Wparam) widthValue 'value)
)
)
)
t
)
)
;;;
;;; CDFmExtDrainTranDone --
;;; This callback is applied to the CDFs for the mExtDrainTranClass
;;; device library elements. It sets the contact fields based off
;;; the descriptive names given in the CDFs.
;;;
(defun CDFmExtDrainTranDone (cdfDbId)
(let ((techFileId (techGetTechFile cdfDbId~>master~>lib)))
(dbReplaceProp cdfDbId "contacts" "string" cdfgData->contactParam->value)
t
)
)
;;;
;;; CDFvaractorDone --
;;; This callback is applied to the CDFs for the varactorClass
;;; device library elements. It sets the contact fields based off
;;; the descriptive names given in the CDFs.
;;;
(defun CDFvaractorDone (cdfDbId)
(let ((techFileId (techGetTechFile cdfDbId~>master~>lib)))
(dbReplaceProp cdfDbId "contacts" "string"
(DLgetSDcontactWithDescription techFileId
cdfgData->contactParam->value))
(dbReplaceProp cdfDbId "gateContact" "string"
(DLgetSDcontactWithDescription techFileId
cdfgData->gateParam->value))
t
)
)
;;;
;;; CDFdrainOnlyDone --
;;; This callback is applied to the CDFs for the drainOnlyClass
;;; device library elements. It sets the contact fields based off
;;; the descriptive names given in the CDFs.
;;;
(defun CDFdrainOnlyDone (cdfDbId)
(let ((techFileId (techGetTechFile cdfDbId~>master~>lib)))
(dbReplaceProp cdfDbId "drainContact" "string"
(DLgetSDcontactWithDescription techFileId
cdfgData->drnContactParam->value))
(dbReplaceProp cdfDbId "sourceContact" "string"
(DLgetSDcontactWithDescription techFileId
cdfgData->srcContactParam->value))
t
)
)
;;;
;;; CDFind3Done --
;;; This function
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFind3Done (CDFdbid "d")
;; create isSubckt property when the model calls for it
(let ( thisInd3 ind3Devices )
(setq ind3Devices (TECHgetInd3Devices CDFdbid~>cellName))
(setq thisInd3 (car ind3Devices))
;; loop through all the ind3s looking for the one with this model
(while (and thisInd3
(nequal CDFdbid~>modelName
(TECHgetDeviceParam thisInd3 'hspiceModel))
)
(setq thisInd3 (car ind3Devices))
(setq ind3Devices (cdr ind3Devices))
)
(cond
((TECHgetDeviceParam thisInd3 'isSubckt)
(dbReplaceProp CDFdbid "isSubckt" "boolean" t)
)
(t
(dbDeletePropByName CDFdbid "isSubckt")
)
)
)
(CDFcommonDone CDFdbid)
)
;;;
;;; CDFind4Done --
;;; This function
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFind4Done (CDFdbid "d")
;; create isSubckt property when the model calls for it
(let ( thisInd4 ind4Devices )
(setq ind4Devices (TECHgetInd4Devices CDFdbid~>cellName))
(setq thisInd4 (car ind4Devices))
;; loop through all the ind4s looking for the one with this model
(while (and thisInd4
(nequal CDFdbid~>modelName
(TECHgetDeviceParam thisInd4 'hspiceModel))
)
(setq thisInd4 (car ind4Devices))
(setq ind4Devices (cdr ind4Devices))
)
(cond
((TECHgetDeviceParam thisInd4 'isSubckt)
(dbReplaceProp CDFdbid "isSubckt" "boolean" t)
)
(t
(dbDeletePropByName CDFdbid "isSubckt")
)
)
)
(CDFcommonDone CDFdbid)
)
;;;
;;; CDFcapbn_bDone --
;;; This function
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcapbn_bDone (cdfId )
(foreach
cap (TECHgetCapDevices "capbn_b")
(when (equal cdfId->ctype
(TECHgetDeviceParam cap 'hspiceModel) )
;; see if this is a 3 term netlist, and create or delete
;; the threeTermNetlist property accordingly
cdfId->threeTermNetlist = (TECHgetDeviceParam cap 'threeTermNetlist)
cdfId->isSubckt = (TECHgetDeviceParam cap 'isSubckt)
)
) ;;end foreach
(CDFcommonDone cdfId)
)
;;;
;;; CDFcapbn_bDone --
;;; This function
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcmim3cDone (cdfId )
(foreach
cap (TECHgetCapDevices "cmim3c")
(when (equal cdfId->ctype (TECHgetDeviceParam cap 'hspiceModel))
;; see if this is a 3 term netlist, and create or delete
;; the threeTermNetlist property accordingly
cdfId->threeTermNetlist = (TECHgetDeviceParam cap 'threeTermNetlist)
cdfId->isSubckt = (TECHgetDeviceParam cap 'isSubckt)
) ;; when
) ;;end foreach
(CDFcommonDone cdfId)
)
;;;
;;; CDFnpn4Done --
;;; This function places current monitoring properties on the npn and pnp
;;; library elements.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFnpn4Done (CDFdbid "d")
(let ((oldMonitorTerms CDFdbid~>HSPmonitorTerms)
monitorTerms
)
(foreach (propName termName) '("cvs" "bvs" "evs") '("c" "b" "e")
(when (get cdfgData propName)->value
(setq monitorTerms (cons termName monitorTerms))
)
)
(cond ((and monitorTerms
(nequal monitorTerms oldMonitorTerms)
)
(dbReplaceProp CDFdbid "HSPmonitorTerms" "ILList"
monitorTerms
)
)
((and oldMonitorTerms (null monitorTerms))
(dbDeletePropByName CDFdbid "HSPmonitorTerms")
)
)
)
;; create isSubckt property when the model calls for it
(let ( thisBjt bjtDevices )
(setq bjtDevices (TECHgetBjtDevices CDFdbid~>cellName))
(setq thisBjt (car bjtDevices))
;; loop through all the bjts looking for the one with this model
(while (and thisBjt
(nequal CDFdbid~>modelName
(TECHgetDeviceParam thisBjt 'hspiceModel))
)
(setq thisBjt (car bjtDevices))
(setq bjtDevices (cdr bjtDevices))
)
(cond
((TECHgetDeviceParam thisBjt 'isSubckt)
(dbReplaceProp CDFdbid "isSubckt" "boolean" t)
)
(t
(dbDeletePropByName CDFdbid "isSubckt")
)
)
)
;; update pnp params based on model
(foreach dev (TECHgetBjtDevices "pnp4")
(when (equal CDFdbid~>modelName (TECHgetDeviceParam dev 'hspiceModel))
(cond
((TECHgetDeviceParam dev 'baseArea)
(dbReplaceProp CDFdbid "bArea" "float" (TECHgetDeviceParam dev 'baseArea))
)
(t
(dbDeletePropByName CDFdbid "bArea")
)
)
(cond
((TECHgetDeviceParam dev 'basePerim)
(dbReplaceProp CDFdbid "bPeri" "float" (TECHgetDeviceParam dev 'basePerim))
)
(t
(dbDeletePropByName CDFdbid "bPeri")
)
)
(cond
((TECHgetDeviceParam dev 'emitterArea)
(dbReplaceProp CDFdbid "eArea" "float" (TECHgetDeviceParam dev 'emitterArea))
)
(t
(dbDeletePropByName CDFdbid "eArea")
)
)
(cond
((TECHgetDeviceParam dev 'emitterPerim)
(dbReplaceProp CDFdbid "ePeri" "float" (TECHgetDeviceParam dev 'emitterPerim))
)
(t
(dbDeletePropByName CDFdbid "ePeri")
)
)
)) ;;end when/foreach
(foreach dev (TECHgetBjtDevices "npn4")
(when (equal CDFdbid~>modelName (TECHgetDeviceParam dev 'hspiceModel))
(cond
((TECHgetDeviceParam dev 'baseArea)
(dbReplaceProp CDFdbid "bArea" "float" (TECHgetDeviceParam dev 'baseArea))
)
(t
(dbDeletePropByName CDFdbid "bArea")
)
)
(cond
((TECHgetDeviceParam dev 'basePerim)
(dbReplaceProp CDFdbid "bPeri" "float" (TECHgetDeviceParam dev 'basePerim))
)
(t
(dbDeletePropByName CDFdbid "bPeri")
)
)
(cond
((TECHgetDeviceParam dev 'emitterArea)
(dbReplaceProp CDFdbid "eArea" "float" (TECHgetDeviceParam dev 'emitterArea))
)
(t
(dbDeletePropByName CDFdbid "eArea")
)
)
(cond
((TECHgetDeviceParam dev 'emitterPerim)
(dbReplaceProp CDFdbid "ePeri" "float" (TECHgetDeviceParam dev 'emitterPerim))
)
(t
(dbDeletePropByName CDFdbid "ePeri")
)
)
))
(CDFcommonDone CDFdbid)
)
(defun CDFpnp4Done (CDFdbid "d")
(CDFnpn4Done CDFdbid)
)
;;;
;;; CDFafuseDone --
;;; This function sets the model name based off the cyclic
;;; modelList selection.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFafuseDone (CDFdbid "d")
(CDFcommonDone CDFdbid)
)
;;;
;;; CDFefuseDone --
;;; This function sets the model name based off the cyclic
;;; modelList selection.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFefuseDone (CDFdbid "d")
(CDFcommonDone CDFdbid)
)
;;;
;;; CDFmtjInit --
;;; This function doesn't do much of anything, just
;;; calls the shared init function
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFmtjInit (cdfId "o")
(CDFcommonInit cdfId)
)
;;;
;;; CDFmtjDone --
;;; This function sets the isSubckt and the model description
;;; on a mtj instance.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFmtjDone (CDFdbid "d")
;; create isSubckt property when the model calls for it (probably always)
;; create model information
(let ( thisMtj mtjDevices mtjModelDescription )
(setq mtjDevices (TECHgetMtjDevices CDFdbid~>cellName))
(setq thisMtj (car mtjDevices))
;; loop through all the mtjs looking for the one with this model
(while (and thisMtj
(nequal CDFdbid~>model
(TECHgetDeviceParam thisMtj 'hspiceModel))
)
(setq thisMtj (car mtjDevices))
(setq mtjDevices (cdr mtjDevices))
)
;; now that we know which device we have, set
;; the isSubckt property or delete it, as needed
(cond
((TECHgetDeviceParam thisMtj 'isSubckt)
(dbReplaceProp CDFdbid "isSubckt" "boolean" t)
)
(t
(dbDeletePropByName CDFdbid "isSubckt")
)
) ;; cond
;; set the model description
;; although already done dynamically in the callback,
;; there are reasons to do it again.
(setq mtjModelDescription
(or (TECHgetDeviceParam thisMtj 'description)
"No description available"))
;; set the mtj model description into the cdf form
cdfgData->mtjModelInfo->value = mtjModelDescription
) ;; let
(CDFcommonDone CDFdbid)
)
;;;
;;; CDFmtj5Init --
;;; This function doesn't do much of anything, just
;;; calls the shared init function
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFmtj5Init (cdfId "o")
(CDFcommonInit cdfId)
)
;;;
;;; CDFmtj5Done --
;;; This function sets the isSubckt and the model description
;;; on a mtj5 instance.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFmtj5Done (CDFdbid "d")
;; create isSubckt property when the model calls for it (probably always)
;; create model information
(let ( thisMtj5 mtj5Devices mtj5ModelDescription )
(setq mtj5Devices (TECHgetMtj5Devices CDFdbid~>cellName))
(setq thisMtj5 (car mtj5Devices))
;; loop through all the mtj5s looking for the one with this model
(while (and thisMtj5
(nequal CDFdbid~>model
(TECHgetDeviceParam thisMtj5 'hspiceModel))
)
(setq thisMtj5 (car mtj5Devices))
(setq mtj5Devices (cdr mtj5Devices))
)
;; ;; now that we know which device we have, set
;; ;; the isSubckt property or delete it, as needed
;; (cond
;; ((TECHgetDeviceParam thisMtj5 'isSubckt)
;; (dbReplaceProp CDFdbid "isSubckt" "boolean" t)
;; )
;; (t
;; (dbDeletePropByName CDFdbid "isSubckt")
;; )
;; ) ;; cond
;; set the model description
;; although already done dynamically in the callback,
;; there are reasons to do it again.
(setq mtj5ModelDescription
(or (TECHgetDeviceParam thisMtj5 'description)
"No description available"))
;; set the mtj5 model description into the cdf form
cdfgData->mtj5ModelInfo->value = mtj5ModelDescription
) ;; let
(CDFcommonDone CDFdbid)
)
;;;
;;; CDFrefCellInit --
;;; This function doesn't do much of anything, just
;;; calls the shared init function
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFrefCellInit (cdfId "o")
(CDFcommonInit cdfId)
)
;;;
;;; CDFrefCellDone --
;;; This function sets the isSubckt and the model description
;;; on a refCell instance.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFrefCellDone (CDFdbid "d")
;; create isSubckt property when the model calls for it (probably always)
;; create model information
(let ( thisrefCell refCellDevices refCellModelDescription )
(setq refCellDevices (TECHgetrefCellDevices CDFdbid~>cellName))
(setq thisrefCell (car refCellDevices))
;; loop through all the refCels looking for the one with this model
(while (and thisrefCell
(nequal CDFdbid~>model
(TECHgetDeviceParam thisrefCell 'hspiceModel))
)
(setq thisrefCell (car refCellDevices))
(setq refCellDevices (cdr refCellDevices))
)
) ;; let
(CDFcommonDone CDFdbid)
)
;;;
;;; CDFmemCellInit --
;;; This function doesn't do much of anything, just
;;; calls the shared init function
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFmemCellInit (cdfId "o")
(CDFcommonInit cdfId)
)
;;;
;;; CDFmemCellDone --
;;; This function sets the isSubckt and the model description
;;; on a memCell instance.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFmemCellDone (CDFdbid "d")
;; create isSubckt property when the model calls for it (probably always)
;; create model information
(let ( thismemCell memCellDevices memCellModelDescription )
(setq memCellDevices (TECHgetmemCellDevices CDFdbid~>cellName))
(setq thismemCell (car memCellDevices))
;; loop through all the memCells looking for the one with this model
(while (and thismemCell
(nequal CDFdbid~>model
(TECHgetDeviceParam thismemCell 'hspiceModel))
)
(setq thismemCell (car memCellDevices))
(setq memCellDevices (cdr memCellDevices))
)
) ;; let
(CDFcommonDone CDFdbid)
)
;;;
;;; CDFsetInd3ModelName --
;;; This function sets the model name based off the cyclic
;;; modelList selection.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFsetInd3ModelName (cdfgData "o")
(when cdfgData->modelList->value
cdfgData->modelName->value = cdfgData->modelList->value
)
)
;;;
;;; CDFsetInd4ModelName --
;;; This function sets the model name based off the cyclic
;;; modelList selection.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFsetInd4ModelName (cdfgData "o")
(when cdfgData->modelList->value
cdfgData->modelName->value = cdfgData->modelList->value
)
)
;;;
;;; CDFmtjCallback --
;;; This function sets the model description dynamically
;;; on a mtj instance as the model is changed.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFmtjCallback (mtjCellName cdfgData "to")
(let (mtjModelDescription mtjDevices thisMtj)
(setq mtjDevices (TECHgetMtjDevices mtjCellName))
(setq thisMtj (car mtjDevices))
;; loop through all the mtjs looking for the one with this model
(while (and thisMtj
(nequal cdfgData->model->value
(TECHgetDeviceParam thisMtj 'hspiceModel))
)
(setq thisMtj (car mtjDevices))
(setq mtjDevices (cdr mtjDevices))
)
;; set the model description
(setq mtjModelDescription
(or (TECHgetDeviceParam thisMtj 'description)
"No description available"))
;; set the mtj model description into the cdf form
cdfgData->mtjModelInfo->value = mtjModelDescription
)
)
;;;
;;; CDFmtj5Callback --
;;; This function sets the model description dynamically
;;; on a mtj5 instance as the model is changed.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFmtj5Callback (mtj5CellName cdfgData "to")
(let (mtj5ModelDescription mtj5Devices thisMtj5)
(setq mtj5Devices (TECHgetMtj5Devices mtj5CellName))
(setq thisMtj5 (car mtj5Devices))
;; loop through all the mtj5s looking for the one with this model
(while (and thisMtj5 (nequal cdfgData->modelName->value
(TECHgetDeviceParam thisMtj5 'hspiceModel)))
(setq thisMtj5 (car mtj5Devices))
(setq mtj5Devices (cdr mtj5Devices))
)
;; set the model description
(setq mtj5ModelDescription (or (TECHgetDeviceParam thisMtj5 'description)
"No description available"))
;; set the mtj5 model description into the cdf form
cdfgData->mtj5ModelInfo->value = mtj5ModelDescription
;;(printf "value -- %L\n" mtj5ModelDescription)
)
)
;;;
;;; CDFcommonInit --
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcommonInit (cdfId "o")
; (foreach x cdfgData->cyInit
; (errset (LISTeval x) t))
nil
)
;;;
;;; CDFcommonDone --
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcommonDone (cdfDbid "d")
(unless (equal cdfDbid~>cellName cdfDbid~>techLibCellName)
(warn "Instance %L of %L was originally placed as an instance of %L. Delete and re-place the instance.\n"
cdfDbid~>name cdfDbid~>cellName cdfDbid~>techLibCellName)
)
;; do not do anything for icecaps
(unless (equal "icecap" cdfDbid~>cellName)
;; kludge around the "showName" parameter
(CDFshowNameKludge cdfDbid cdfgData->preShowName->value)
)
)
;;;
;;; CDFcreateHideProps --
;;; This function used to create the "hide_XXX" properties that were
;;; used by the NLP expressions of the tech lib element symbols to prevent
;;; the display of parameters which were default values. This function
;;; should have been called by the CDF callback for the elements.
;;; The cdf for the element has the property CDFhideProps, which is a list
;;; of symbols of the property names that can be hidden.
;;; Now, the symbols displays are ILLabels, which dynamically determine
;;; what needs to be displayed without the use of the "hide_XXX" properties.
;;; Therefore, if old properties are lingering, delete them.
;;;
;;; Input: dbid: database id of the instance that was just modified
;;; Output:
;;; Globals: cdfgData
;;; Side Effects: deletes "hide_XXX" properties
;;; Return:
;;;
(defun CDFcreateHideProps (dbid "d")
(let (propVal defVal actVal)
(foreach prop cdfgData->CDFhideProps
;; Labels have been updated to dynamically determine this.
;; Therefore, blow away the bloat of these excess properties
;; if they exist.
(when (dbGet dbid (concat "hide_" prop))
(dbDeletePropByName dbid (strcat "hide_" prop))
)
)
)
)
;;;
;;; CDFcreateAsymProps --
;;; This function used to create the "asymX" properties that were
;;; used by the NLP expressions of the logic gate tech lib element symbols.
;;; If the property existed, it means that the w/l/m properties were not
;;; consistent for all of the pfets in a logic gate, for example. The
;;; NLP expressions would have printed out a w/l*m entry for each pfet if
;;; the properties are asymmetric, or only one.
;;; Now, the symbols displays are ILLabels, which dynamically determine
;;; what needs to be displayed without the use of the "asymX" properties.
;;; Therefore, if old properties are lingering, delete them.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcreateAsymProps (dbid "d")
(let (suffix pname)
(foreach prefix cdfgData->CDFasymPrefixes
(cond
((listp prefix)
(setq suffix (cadr prefix))
(setq prefix (car prefix))
)
(t (setq suffix ""))
)
(setq pname (strcat "asym" (upperCase (strcat prefix suffix))))
(when (dbGet dbid pname)
(dbDeletePropByName dbid pname)
)
)
)
)
;;;
;;; CDFfetMfactorCallback --
;;; This function will verify that the mfactor is >= 1
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFfetMfactorCallback ()
(let (theNum)
(setq theNum atoi(cdfgData->m->value))
;; don't let them specify an empty string for the mfactor.
;; that would introduce equation errors for diodes during
;; schematic extraction, but won't be caught until
;; simulation
; ((null (parseString theNum " \t\n"))
; (get cdfgData param)->value = "1"
; (setq theNum 1)
; )
(when (or (null (integerp theNum))
(lessp theNum 1))
(warn (sprintf nil "CDFmfactorCallback: m has illegal value %L; you are begging for trouble.\n" (cdfgData->m->value)))
cdfgData->m->value = "1"
)
)
)
;;;
;;; CDFfetMultCallback --
;;; This function will verify that mult is >= 1
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFfetMultCallback ()
(let (theNum)
(setq theNum atoi(cdfgData->mult->value))
;; don't let them specify an empty string for the mfactor.
;; that would introduce equation errors for diodes during
;; schematic extraction, but won't be caught until
;; simulation
; ((null (parseString theNum " \t\n"))
; (get cdfgData param)->value = "1"
; (setq theNum 1)
; )
(when (or (null (integerp theNum))
(lessp theNum 1))
(warn (sprintf nil "CDFfetMultCallback: mult has illegal value %L; you are begging for trouble.\n" (cdfgData->mult->value)))
cdfgData->mult->value = "1"
)
)
)
;;;
;;; CDFrmfactorCallback --
;;; This function will verify that the mfactor is >= 1
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFrmfactorCallback ()
(let (aNum)
(setq aNum atoi(cdfgData->rm->value))
;; don't let them specify an empty string for the mfactor.
;; that would introduce equation errors for diodes during
;; schematic extraction, but won't be caught until
;; simulation
; ((null (parseString theNum " \t\n"))
; (get cdfgData param)->value = "1"
; (setq theNum 1)
; )
(when (or (null (integerp aNum))
(lessp aNum 1))
(warn (sprintf nil "CDFmfactorCallback: rm has illegal value %L; you are begging for trouble.\n" (cdfgData->rm->value)))
cdfgData->rm->value = "1"
)
)
)
;;;
;;; CDFcmfactorCallback --
;;; This function will verify that the mfactor is >= 1
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcmfactorCallback ()
(let (theNum)
(setq theNum atoi(cdfgData->cm->value))
;; don't let them specify an empty string for the mfactor.
;; that would introduce equation errors for diodes during
;; schematic extraction, but won't be caught until
;; simulation
; ((null (parseString theNum " \t\n"))
; (get cdfgData param)->value = "1"
; (setq theNum 1)
; )
(when (or (null (integerp theNum))
(lessp theNum 1))
(warn (sprintf nil "CDFmfactorCallback: cm has illegal value %L; you are begging for trouble.\n" (cdfgData->cm->value)))
cdfgData->cm->value = "1"
)
)
)
;;;
;;; CDFdiodeMethodMap --
;;; This function will map a diode method name into something shorter.
;;; For example, "insideContact" will be abbreviated "iC", etc.
;;;
;;; Input: a string or nil
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return: abbreviated string or nil
;;;
(defun CDFdiodeMethodMap (diodeMethod)
(cond
((null diodeMethod)
nil
)
((equal "insideContact" diodeMethod)
(or (ENVgetVal "schematic" "diodeInsideContact") "insideContact")
)
((equal "insideNoContact" diodeMethod)
(or (ENVgetVal "schematic" "diodeInsideNoContact") "insideNoContact")
)
((equal "outsideContact" diodeMethod)
(or (ENVgetVal "schematic" "diodeOutsideContact") "outsideContact")
)
((equal "none" diodeMethod)
(or (ENVgetVal "schematic" "diodeNone") "none")
)
(t nil)
)
)
;; just a shorter alias for CDFdiodeMethodMap
(defun CDFdMM (diodeMethod)
(CDFdiodeMethodMap diodeMethod)
)
;;;
;;; CDFcapbnCanParamModel --
;;; When they are trying to toggle on the "constantCap" field of a capbn_b
;;; instance, make sure that we know the ca and cp (or alternatively c0 to c3)
;;; parameters in order to support deriving the cw and cl.
;;; This has been extended to support the cmimc devices in an identical
;;; method.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcapbnCanParamModel (cdfId)
(let (ca cp c0 c1 c2 c3 varactor)
;; if they are trying to turn it on, make sure that we know the
;; ca and cp parameters for this cap
(when cdfId->constantCap->value
(foreach cap (append (append (TECHgetCapDevices "capbn_b")
(TECHgetCapDevices "cmimc"))
(TECHgetCapDevices "cmim3c"))
(when
(equal
(TECHgetDeviceParam cap 'hspiceModel)
cdfId->ctype->value
)
(setq ca (TECHgetDeviceParam cap 'areaCap))
(setq cp (TECHgetDeviceParam cap 'perimCap))
(setq c0 (TECHgetDeviceParam cap 'c0))
(setq c1 (TECHgetDeviceParam cap 'c1))
(setq c2 (TECHgetDeviceParam cap 'c2))
(setq c3 (TECHgetDeviceParam cap 'c3))
(setq varactor (TECHgetDeviceParam cap 'varactor))
)
)
(unless varactor
(unless (and ca cp)
cdfId->constantCap->value = nil
(warn "Unknown ca and cp parameters for this cap model\n")
)
)
(when varactor
(unless (and c0 c1 c2 c3)
cdfId->constantCap->value = nil
(warn "Unknown c0, c1, c2, and c3 parameters for this cap model\n")
)
)
)
)
)
;;;
;;; CDFcalculateCapacitors --
;;; This function does some neat calculations on capacitors. When it is
;;; an constant cap, it will calculate the width, or the length, or a square
;;; width and length that closest comes to the specified cap value. If they
;;; specify the width and length, it will calculate the total cap value.
;;; Currently, this can work for capbn_b and cmimc capacitors
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcalculateCapacitors (cdfId @optional changedParam)
(let (capName cw cl ca cp c cm scale grid calcDimension c0 c1 c2 c3 varactor deltaW deltaL hsp)
(setq deltaL 0)
(setq deltaW 0)
;; when it is a constant capacitor, determine whether the fixed
;; dimension is width, length, or square (equal w & l)
;;
(when (and cdfId->constantCap->value
(nequal "FALSE" cdfId->constantCap->value))
(setq calcDimension cdfId->calcDimension->value)
)
(foreach cap (append (append (TECHgetCapDevices "capbn_b")
(TECHgetCapDevices "cmimc"))
(TECHgetCapDevices "cmim3c"))
(setq hsp (TECHgetDeviceParam cap 'hspiceModel))
(when
(equal
(TECHgetDeviceParam cap 'hspiceModel)
cdfId->ctype->value
)
; (warn "TECHgetDeviceParam hspiceModel: hspiceModel = %L ctype = %L\n" hsp cdfId->ctype->value)
(setq capName (TECHgetDeviceParam cap 'name))
(setq ca (TECHgetDeviceParam cap 'areaCap))
(setq cp (TECHgetDeviceParam cap 'perimCap))
(setq c0 (TECHgetDeviceParam cap 'c0))
(setq c1 (TECHgetDeviceParam cap 'c1))
(setq c2 (TECHgetDeviceParam cap 'c2))
(setq c3 (TECHgetDeviceParam cap 'c3))
(setq varactor (TECHgetDeviceParam cap 'varactor)) ;; use c0, c1, c2, c3 for
;; cap calculation when true
(setq deltaW (TECHgetDeviceParam cap 'deltaW))
(unless deltaW
(setq deltaW 0)
)
(setq deltaL (TECHgetDeviceParam cap 'deltaL))
(unless deltaL
(setq deltaL 0)
)
; ;; see if this is a 3 term netlist, and create or delete
; ;; the threeTermNetlist property accordingly
; (cond
; ((TECHgetDeviceParam cap 'threeTermNetlist)
; cdfId->threeTermNetlist->value = t
; )
; (t
; cdfId->threeTermNetlist->value = nil
; )
; )
)
)
;; try to get the cw, cl, and c cdf fields as numbers. Apply the
;; shrink factors to cw and cl. When deriving cw and cl, round it
;; to the snap grid
(setq scale (or (TECHgetProp scaleFactor) 1.0))
(setq grid (TECHgetProp snapGrid))
(setq cw cdfId->cw->value)
(cond
((and (stringp cw) (aelIsNumberP cw))
(setq cw (times scale (difference (aelNumber cw) deltaW)))
)
((and (stringp cw) (nequal "" cw))
(setq cw (sprintf nil "(((%s)-%g)*%g)" cw deltaW scale))
)
((numberp cw)
(setq cw (times scale (difference cw deltaW)))
)
)
(setq cl cdfId->cl->value)
(cond
((and (stringp cl) (aelIsNumberP cl))
(setq cl (times scale (difference (aelNumber cl) deltaL)))
)
((and (stringp cl) (nequal "" cl))
(setq cl (sprintf nil "(((%s)-%g)*%g)" cl deltaL scale))
)
((numberp cl)
(setq cl (times scale (difference cl deltaL)))
)
)
;; the total C is cm * (cap for w & l). Because we do our
;; calculations for the w and l, divide the C by cm. Also, the
;; parameters defined in the edr assume fF, but the cdf should work
;; with plain F. Therefore, multiply the C by 1e15 here.
(setq cm cdfId->cm->value)
(cond
((and (stringp cm) (aelIsNumberP cm))
(setq cm (aelNumber cm))
)
((and (stringp cm) (nequal "" cm))
(setq cm (sprintf nil "(%s)" cm))
)
((equal "" cm)
(setq cm 1.0)
)
)
(setq c cdfId->c->value)
(when (and (stringp c) (aelIsNumberP c))
(setq c (aelNumber c))
)
;; if the number > 1e-3, assume that they meant to enter it in pF
(when (and (numberp c) (greaterp c 1e-3))
(setq c (times 1e-12 c))
)
(cond
;; if c and cm are numbers, divide c by cm
((and (numberp c) (numberp cm))
(setq c (quotient (times c 1e15) cm))
)
;; if c or cm are strings, set c to an expression
((or (and (stringp c) (nequal "" c))
(and (stringp cm) (nequal "" cm)))
;; get both c and cm as strings
(cond
((numberp c) (setq c (sprintf nil "%g" c)))
((stringp c) (setq c (strcat "(" c ")" "*1e-12")))
)
(when (numberp cm) (setq cm (sprintf nil "%g" cm)))
(setq c (sprintf nil "(%s*1e15/%s)" c cm))
)
)
;; first, get the cap width and length under control. We may have
;; to derive them if they specify the capacitance
(cond
;; if this is a constant capacitance capbn, derive the correct
;; cw or cl parameter and stuff it back into the CDF
;;
((or (and cdfId->constantCap->value ca cp c (nequal "" c))
(and cdfId->constantCap->value c0 c1 c2 c3 c (nequal "" c)))
(cond
;; if c is a number, try to derive the cw and cl as numbers
((numberp c)
(cond
;; if they changed the cap value, calculate derived
;; cw=cl to satisfy the equation
((and (equal changedParam 'cap)
(equal calcDimension "Square"))
(unless varactor
(setq cl (quotient (plus (times -4.0 cp) (sqrt (plus (times 16 cp cp) (times 4.0 ca c))))
(times 2.0 ca scale)
)
)
)
(when varactor
(let (a b c_) ;; have to use goofy c_ because c is taken
(setq a (aelNumber c3))
(setq b (plus (aelNumber c1) (aelNumber c2)))
(setq c_ (difference (aelNumber c0) (aelNumber c)))
(setq cl (quotient (plus -b (sqrt (difference (times b b) (times 4 a c_))))
(times 2.0 a scale)
)
)
)
)
;; round it onto grid
(setq cw (times (round (quotient (plus cl deltaW) grid)) grid))
(setq cl (times (round (quotient (plus cl deltaL) grid)) grid))
;; cdf field should always be a string now
(setq cl (sprintf nil "%g" cl))
(setq cw (sprintf nil "%g" cw))
cdfId->cl->value = cl
cdfId->cw->value = cw
)
;; if they changed the cw, adjust the length
;; correspondingly
((or (equal calcDimension "Length")
(equal changedParam 'cw))
(cond
;; if cw is a number, calculate cl
((numberp cw)
(unless varactor
(setq cl
(quotient (difference c (times 2 cp (difference cw deltaW)))
(times scale (plus (times ca (difference cw deltaW)) (times 2 cp)))))
)
(when varactor
(setq cl (quotient (difference c c0 (times c2 (difference cw deltaW)))
(times scale (plus c1 (times c3 (difference cw deltaW))))
)
)
)
;; round it onto grid
(setq cl (times (round (quotient (plus cl deltaL) grid)) grid))
;; cdf field should always be a string now
(setq cl (sprintf nil "%g" cl))
cdfId->cl->value = cl
)
;; if cw is a param, do cl as an equation
((and (stringp cw) (nequal "" cw))
(unless varactor
(setq cl (sprintf nil "((%g-(2*%g*(%s-%g)))/(%g*(%g*(%s-%g)+2*%g)))+%g"
c cp cw deltaW scale ca cw deltaW cp deltaL)
)
)
(when varactor
(setq cl (sprintf nil "((%g-%g-(%g*(%s-%g)))/(%g*(%g+(%g*(%s-%g)))))+%g"
c c0 c2 cw deltaW scale c1 c3 cw deltaW deltaL)
)
)
cdfId->cl->value = cl
)
)
)
;; if they changed the cl, adjust the cw
((or (equal calcDimension "Width")
(equal changedParam 'cl))
(cond
;; if cl is a number, calculate cw
((numberp cl)
(unless varactor
(setq cw
(quotient (difference c (times 2 cp (difference cl deltaL)))
(times scale (plus (times ca (difference cl deltaL)) (times 2 cp)))))
)
(when varactor
(setq cw (quotient (difference c c0 (times c1 (difference cl deltaL)))
(times scale (plus c2 (times c3 (difference cl deltaL))))
)
)
)
;; round it onto grid
(setq cw (times (round (quotient (plus cw deltaW) grid)) grid))
;; cdf field should always be a string now
(setq cw (sprintf nil "%g" cw))
cdfId->cw->value = cw
)
((and (stringp cl) (nequal "" cl))
(unless varactor
(setq cw (sprintf nil "((%g-(2*%g*(%s-%g)))/(%g*(%g*(%s-%g)+2*%g)))+%g"
c cp cl deltaL scale ca cl deltaL cp deltaW)
)
)
(when varactor
(setq cw (sprintf nil "((%g-%g-(%g*(%s-%g)))/(%g*(%g+(%g*(%s-%g)))))+%g"
c c0 c1 cl deltaL scale c2 c3 cl deltaL deltaW)
)
)
cdfId->cw->value = cw
)
)
)
(t nil) ; should not get here; I dunno what changed
)
)
;;
;; else, if c is a parameter, derive equations
;;
((and (stringp c) (nequal "" c))
;; for simplicity, get cw, cl, ca, cp, and scale as strings
(unless varactor
(foreach param '(cw cl ca cp scale)
(when (numberp (eval param))
(set param (sprintf nil "%g" (eval param)))
)
)
)
(when varactor
(foreach param '(c0 c1 c2 c3 scale)
(when (numberp (eval param))
(set param (sprintf nil "%g" (eval param)))
)
)
)
(cond
;; if they changed the cap value, calculate derived
;; cw=cl to satisfy the equation
((and (equal changedParam 'cap)
(equal calcDimension "Square"))
(unless varactor
(setq cl (sprintf nil "(((-4*%s)+sqrt((16*%s*%s)+(4*%s*%s)))/(2*%s*%s))+%g"
cp cp cp ca c ca scale deltaL
)
)
(setq cw (sprintf nil "(((-4*%s)+sqrt((16*%s*%s)+(4*%s*%s)))/(2*%s*%s))+%g"
cp cp cp ca c ca scale deltaW
)
)
)
(when varactor
(let (a b c_)
(setq a (aelNumber c3))
(setq b (plus (aelNumber c1) (aelNumber c2)))
;;SPR 40756. 'c' is a param so build a string
(setq c_ (sprintf nil "(%s-%s)" c0 c))
;;SPR 40756. As far as I can see a, b and deltL and deltaW are numbers and c_ and scale are strings
;;But the format descriptors are a problem down the road for the varactor case and I am not sure of
;;all the possible cases that may cause a variable to be a string or a number.
;;So for now I will use the catch all %L.
(setq cl (sprintf nil "((-%L+sqrt((%L*%L)-(4*%L*%L)))/(2*%L*%L))+%L"
b b b a c_ a scale deltaL
)
)
(setq cw (sprintf nil "((-%L+sqrt((%L*%L)-(4*%L*%L)))/(2*%L*%L))+%L"
b b b a c_ a scale deltaW
)
)
)
)
cdfId->cl->value = cl
cdfId->cw->value = cw
)
;; if they changed the cw, adjust the length
;; correspondingly
((or (equal calcDimension "Length")
(equal changedParam 'cw))
(when (nequal "" cw)
(unless varactor
(setq cl (sprintf nil "((%s-(2*%s*%s))/(%s*(%s*%s+2*%s)))+%g"
c cp cw scale ca cw cp deltaL)
)
)
(when varactor
;;SPR 40756. Changing %s to %L
(setq cl (sprintf nil "((%L-%L-(%L*(%L-%L)))/(%L*(%L+(%L*(%L-%L)))))+%L"
c c0 c2 cw deltaW scale c1 c3 cw deltaW deltaL
)
)
)
cdfId->cl->value = cl
)
)
;; if they changed the cl, adjust the cw
((or (equal calcDimension "Width")
(equal changedParam 'cl))
(when (nequal "" cl)
(unless varactor
(setq cw (sprintf nil "((%s-(2*%s*%s))/(%s*(%s*%s+2*%s)))+%g"
c cp cl scale ca cl cp deltaW)
)
)
(when varactor
;;SPR 40756. Changing %s to %L
(setq cw (sprintf nil "((%L-%L-(%L*(%L-%L)))/(%L*(%L+(%L*(%L-%L)))))+%L"
c c0 c1 cl deltaL scale c2 c3 cl deltaL deltaW
)
)
)
cdfId->cw->value = cw
)
)
(t nil) ; should not get here; I dunno what changed
)
)
)
)
)
;; start fresh with the cw and cl fields from the CDF. They will
;; have to be scaled if we can calculate the total capacitance.
;; Get the cw and cl fields as numbers.
;;
(setq cw cdfId->cw->value)
(setq cl cdfId->cl->value)
(when (and (stringp cw) (aelIsNumberP cw)) (setq cw (aelNumber cw)))
(when (and (stringp cl) (aelIsNumberP cl)) (setq cl (aelNumber cl)))
(cond
;; if we have the ca and cp fields, and the cw and cl are numbers,
;; update the capacitance field. Remember to divide the c by 1e15
;; because the field is in F, but ca and cf are in terms of fF
;;
((or (and ca cp (numberp cw) (numberp cl) (numberp cm))
(and c0 c1 c2 c3 (numberp cw) (numberp cl) (numberp cm)))
(setq cw (difference cw deltaW))
(setq cl (difference cl deltaL))
(unless varactor
(setq c (plus (times cw scale cl scale ca)
(times 2.0 cp scale (plus cw cl))))
)
(when varactor
(setq c (plus c0
(times c1 cl)
(times c2 cw)
(times c3 cl cw)
)
)
)
(setq c (quotient (times cm c) 1e15))
cdfId->actualC->value = (sprintf nil "%g" c)
;; If they specified a constant capacitance, do not change the
;; constant capacitance that they specify.
(when (null cdfgData->constantCap->value)
cdfId->c->value = (sprintf nil "%g" c)
)
)
;; otherwise, clear out the cap field, but not when they have
;; entered a parameter for C
((null cdfId->constantCap->value)
cdfId->c->value = ""
cdfId->actualC->value = ""
)
)
cdfId->isSubckt->value = (TECHgetDeviceParam (TECHgetDevice ?name capName) 'isSubckt)
)
)
;;;
;;; CDFcalculateCap_int3 --
;;; This function does some neat calculations on capacitors. When it is
;;; an constant cap, it will calculate the width, or the length, or a square
;;; width and length that closest comes to the specified cap value. If they
;;; specify the width and length, it will calculate the total cap value.
;;; Currently, this can work for capbn_b and cmimc capacitors
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcalculateCap_int3 ()
(let (capName c cm cap_type)
(foreach cap (TECHgetCapNotInListDevices "cap_int3")
(when (equal (TECHgetDeviceParam cap 'hspiceModel) cdfgData->ctype->value)
(setq capName (TECHgetDeviceParam cap 'name))
; (warn "cap name is %L\n" capName)
)
)
;; the parameters defined in the edr assume fF, but the cdf should work
;; with plain F. Therefore, multiply the C by 1e15 here.
(setq cm cdfgData->cm->value)
(cond
((and (stringp cm) (aelIsNumberP cm))
(setq cm (aelNumber cm))
)
((and (stringp cm) (nequal "" cm))
(setq cm (sprintf nil "(%s)" cm))
)
((equal "" cm)
(setq cm 1.0)
)
)
(setq c (sprintf nil "%L" (TECHgetRule (sprintf nil "%s" capName))))
(when (and (stringp c) (aelIsNumberP c))
(setq c (aelNumber c))
)
;; if the number > 1e-3, assume that they meant to enter it in fF
(cond
((and (numberp c) (greaterp c 1e-3))
(setq c (times 1e-15 c))
)
(t (setq c (times 1e-12 c))
)
)
(cond
;; if c and cm are numbers, divide c by cm
;; if c or cm are strings, set c to an expression
((or (and (stringp c) (nequal "" c)) (and (stringp cm) (nequal "" cm)))
;; get both c and cm as strings
(cond
((numberp c) (setq c (sprintf nil "%g" c)))
((stringp c) (setq c (strcat "(" c ")")))
)
(when (numberp cm) (setq cm (sprintf nil "%g" cm)))
(setq c (sprintf nil "(%s)" c))
)
)
cdfgData->c->value = (sprintf nil "%g" c)
;;(printf "value -- %L\n" c)
)
)
;;;
;;; CDFcalculatevppcap --
;;; This function does some neat calculations on capacitors. When it is
;;; an constant cap, it will calculate the width, or the length, or a square
;;; width and length that closest comes to the specified cap value. If they
;;; specify the width and length, it will calculate the total cap value.
;;; Currently, this can work for capbn_b and cmimc capacitors
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcalculatevppcap ()
(let (capName c cm cap_type)
(foreach cap (TECHgetCapNotInListDevices "vppcap")
(when (equal (TECHgetDeviceParam cap 'hspiceModel) cdfgData->ctype->value)
(setq capName (TECHgetDeviceParam cap 'name))
)
)
;; the parameters defined in the edr assume fF, but the cdf should work
;; with plain F. Therefore, multiply the C by 1e15 here.
(setq cm cdfgData->cm->value)
(cond
((and (stringp cm) (aelIsNumberP cm))
(setq cm (aelNumber cm))
)
((and (stringp cm) (nequal "" cm))
(setq cm (sprintf nil "(%s)" cm))
)
((equal "" cm)
(setq cm 1.0)
)
)
(setq c (sprintf nil "%L" (TECHgetRule (sprintf nil "%s" capName))))
(when (and (stringp c) (aelIsNumberP c))
(setq c (aelNumber c))
)
;; if the number > 1e-3, assume that they meant to enter it in fF
;;(when (and (numberp c) (greaterp c 1e-3))
;; (setq c (times 1e-12 c))
;;)
(cond
((and (numberp c) (greaterp c 1e-3))
(setq c (times 1e-15 c))
)
(t (setq c (times 1e-12 c))
)
)
(cond
;; if c and cm are numbers, divide c by cm
;; if c or cm are strings, set c to an expression
((or (and (stringp c) (nequal "" c)) (and (stringp cm) (nequal "" cm)))
;; get both c and cm as strings
(cond
((numberp c) (setq c (sprintf nil "%g" c)))
((stringp c) (setq c (strcat "(" c ")")))
)
(when (numberp cm) (setq cm (sprintf nil "%g" cm)))
(setq c (sprintf nil "(%s)" c))
)
)
cdfgData->c->value = (sprintf nil "%g" c)
;;(printf "value -- %L\n" c)
)
)
;;;
;;; CDFcapbnCalculateDiodes --
;;; This function has grown to be greater than its namesake. Originally,
;;; this would calculate the diode area and perimeter properties from the
;;; capacitor's width and length.
;;; From SPR 8287, this will also allow the total capacitance to be specified
;;; and it will derive the cap width and length from it.
;;; The diode area/perim that it calculates is for the nwell. This is
;;; quite a bit different from the normal schxtr way of having the diode
;;; area/perim be for the diffusion.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFcapbnCalculateDiodes (cdfId @optional changedParam)
(let (cw cl diodeWidth diodeLength diodeArea diodePerimeter
diodeName additionalWidth additionalLength contactLayer)
(CDFcalculateCapacitors cdfId changedParam)
(foreach cap (TECHgetCapDevices "capbn_b")
(when
(equal
(TECHgetDeviceParam cap 'hspiceModel)
cdfId->ctype->value
)
(setq diodeName (TECHgetDeviceParam cap 'diode))
;; see if this is a 3 term netlist, and create or delete
;; the threeTermNetlist property accordingly
; (cond
; ((TECHgetDeviceParam cap 'threeTermNetlist)
; ;(dbReplaceProp cdfId "threeTermNetlist" "boolean" t)
; cdfId->threeTermNetlist->value = t
; )
; (t
; ;(dbDeletePropByName cdfId "threeTermNetlist")
; cdfId->threeTermNetlist->value = nil
; )
; )
)
)
;; after we have the cap width and length under control, get the
;; diode width and length in shape
;;
(cond
((or (null cdfId->manualDiode->value)
(equal "FALSE" cdfId->manualDiode->value))
(cond
((TECHresolveLayer "litr")
(setq contactLayer "litr")
)
((TECHresolveLayer "ddlicon")
(setq contactLayer "ddlicon")
)
((TECHresolveLayer "lmcon")
(setq contactLayer "lmcon")
)
((TECHresolveLayer "licon1")
(setq contactLayer "licon1")
)
(t (setq contactLayer "mcon"))
)
(cond
;; the cpwc has a tap thrown into the nwell separate from diff
((equal "xcpwc" cdfId->ctype->value)
(setq additionalLength
(plus
(TECHgetRuleWith "minEnclosure" "nwell" "diff")
(times 2.0
(plus
(TECHgetRuleWith "minEnclosure"
"diff" contactLayer)
(TECHgetRuleWith "minWidth" contactLayer)
(TECHgetRuleWith "minGateSpacing"
contactLayer "poly")
)
)
(TECHgetRuleWith "minSpacing" "diff" "tap")
(times 2.0 (TECHgetRuleWith "minEnclosure"
"tap" contactLayer))
(TECHgetRuleWith "minWidth" contactLayer)
(TECHgetRuleWith "minEnclosure" "nwell" "tap")
)
)
(setq additionalWidth
(times 2.0 (TECHgetRuleWith "minEnclosure"
"nwell" "diff"))
)
)
;; the cpnc cap has the tap enclose the poly on all 4 sides,
;; and has an odd enclosure of nwell
((equal "xcpnc" cdfId->ctype->value)
(setq additionalLength
(times 2.0
(plus
(or (TECHgetRuleWith "tap_nwell_1a")
(TECHgetRuleWith "minEnclosure"
"nwell" "tap")
)
(TECHgetRuleWith "minEnclosure"
"tap" contactLayer)
(TECHgetRuleWith "minWidth" contactLayer)
(TECHgetRuleWith "minEnclosure" "tap" "rpoly")
)
)
)
(setq additionalWidth
(times 2.0
(plus
(or (TECHgetRuleWith "tap_nwell_1a")
(TECHgetRuleWith "minEnclosure"
"nwell" "tap")
)
(TECHgetRuleWith "minEnclosure" "tap" "rpoly")
)
)
)
)
;; for the other types of capbn devices
(t
(setq additionalLength
(times 2.0
(plus
(TECHgetRuleWith "minEnclosure" "nwell" "tap")
(TECHgetRuleWith "minEnclosure"
"tap" contactLayer)
(TECHgetRuleWith "minWidth" contactLayer)
(TECHgetRuleWith "minGateSpacing"
contactLayer "poly")
)
)
)
(setq additionalWidth
(times 2.0 (TECHgetRuleWith "minEnclosure"
"nwell" "tap"))
)
)
)
;; get a fresh start of the cw and cl fields from the CDF
(setq cw cdfId->cw->value)
(when (and (stringp cw) (aelIsNumberP cw))
(setq cw (aelNumber cw))
)
(setq cl cdfId->cl->value)
(when (and (stringp cl) (aelIsNumberP cl))
(setq cl (aelNumber cl))
)
(cond
;; if they are both numbers, great
((and (numberp cw) (numberp cl))
(setq diodeWidth (plus cw additionalWidth))
(setq diodeLength (plus cl additionalLength))
)
;; else, use equations
(t
(when (numberp cw) (setq cw (sprintf nil "%g" cw)))
(when (numberp cl) (setq cl (sprintf nil "%g" cl)))
(setq additionalWidth (sprintf nil "%g" additionalWidth))
(setq additionalLength (sprintf nil "%g" additionalLength))
(setq diodeWidth (sprintf nil "%s+%s" cw additionalWidth))
(setq diodeLength (sprintf nil "%s+%s" cl additionalLength))
)
)
)
;; if they did manually specify the diode manually
(t
(setq diodeWidth cdfId->dw->value)
(setq diodeLength cdfId->dl->value)
;; try to work with numbers
(when (and (stringp diodeWidth) (aelIsNumberP diodeWidth))
(setq diodeWidth (aelNumber diodeWidth))
)
(when (and (stringp diodeLength) (aelIsNumberP diodeLength))
(setq diodeLength (aelNumber diodeLength))
)
)
)
(cond
;; if they manually specify the diode area and perimeter,
;; do not do anything
((equal "Area & Perim" cdfId->manDiodeMethod->value)
t
)
;; if working with numbers
((and (numberp diodeWidth) (numberp diodeLength))
(setq diodeArea (times diodeWidth diodeLength))
(setq diodePerimeter (times 2 (plus diodeWidth diodeLength)))
(when (equal "string" cdfId->area->paramType)
(setq diodeArea (sprintf nil "%g" diodeArea))
)
cdfId->area->value = diodeArea
(when (equal "string" cdfId->perim->paramType)
(setq diodePerimeter (sprintf nil "%g" diodePerimeter))
)
cdfId->perim->value = diodePerimeter
)
;; if working with expressions
(t
(when (numberp diodeWidth)
(setq diodeWidth (sprintf nil "%g" diodeWidth)))
(when (numberp diodeLength)
(setq diodeLength (sprintf nil "%g" diodeLength)))
(setq diodeArea (sprintf nil "((%s)*(%s))"
diodeWidth diodeLength))
(setq diodePerimeter (sprintf nil "(2*((%s)+(%s)))"
diodeWidth diodeLength))
(cond
((nequal "string" cdfId->area->paramType)
(warn "Capbn CDF type screwup\n")
)
(t cdfId->area->value = diodeArea)
)
(cond
((nequal "string" cdfId->perim->paramType)
(warn "Capbn CDF type screwup\n")
)
(t cdfId->perim->value = diodePerimeter)
)
)
)
cdfId->model->value = (TECHgetDeviceParam
(TECHgetDevice ?name (or diodeName 'bndiode))
'hspiceModel
)
)
)
;;;
;;; CDFsetModSubckt --
;;;
;;; Input: cdfId - the cdfId of the device
;;; devname - string with the cell name of the device
;;; Output:
;;; Globals:
;;; Side Effects: sets the isSubckt cdf parameter based on cellname passed
;;; and device declaration
;;; Return:
;;;
;;; Algorithm:
;;; Finds the device name associated with the hspice model currently selected
;;; on the cell name passed as an argument, and uses the isSubckt paramter of that
;;; device to set the isSubckt cdf property. Written for cppc element, but
;;; should be general enough for other elements with a ctype parameter.
;;;
(defun CDFsetModSubckt (cdfId devname "ot")
(let (capName isSubckt)
(foreach cap (TECHgetDevice ?cellName devname)
(when
(equal
(TECHgetDeviceParam cap 'hspiceModel)
cdfId->ctype->value
)
(setq capName (TECHgetDeviceParam cap 'name))
)
)
cdfId->isSubckt->value = (TECHgetDeviceParam (TECHgetDevice ?name capName) 'isSubckt)
)
)
;;;
;;; CDFderiveAreaAndPerim --
;;; This is the width and length field callback for a transistor.
;;; Check the minimum gate width and length if that check is enabled.
;;; Also, for drain only topography transistors, it will calculate the
;;; area and perimiter properties "area" and "perim" for LVS.
;;;
;;; Input: cdfId - the cdfId of the transistor
;;; Output:
;;; Globals:
;;; Side Effects: For "drainOnly" topography transistors, it will update
;;; the "area" and "perim" properties if derivAP is true
;;; Return:
;;;
(defun CDFderiveAreaAndPerim (cdfId)
;; for those who need training wheels, sanity check the minimum
;; device size
(when (ENVgetVal "schematic" "checkFetMinSize")
(let (fetDevice minWidth minLength adjustSize)
(setq fetDevice (CDFfetGetFetDevice cdfId->id->name))
;; get the minimum gate width and length
(setq minWidth (TECHgetDeviceParam fetDevice 'minGateWidth))
(setq minLength (TECHgetDeviceParam fetDevice 'minGateLength))
(when (and minWidth (floatp minWidth))
(setq adjustSize nil)
(cond
((aelIsNumberP cdfId->w->value)
(when (lessp (aelNumber cdfId->w->value) minWidth)
(warn "Width (%L) is less than minimum (%L); increasing to minimum\n"
cdfId->w->value minWidth
)
(setq adjustSize t)
)
)
((and (stringp cdfId->w->value)
(null (parseString cdfId->w->value " \t\n")))
(warn "Empty width is illegal; setting to minimum (%L)\n"
minWidth)
(setq adjustSize t)
)
;; if it is an expression that is not directly a number,
;; do nothing
(t nil)
)
(when adjustSize
(cond
((equal "string" cdfId->w->paramType)
cdfId->w->value = (sprintf nil "%g" minWidth)
)
(t cdfId->w->value = minWidth)
)
)
)
(when (and minLength (floatp minLength))
(setq adjustSize nil)
(cond
((aelIsNumberP cdfId->l->value)
(when (lessp (aelNumber cdfId->l->value) minLength)
(warn "Length (%L) is less than minimum (%L); increasing to minimum\n"
cdfId->l->value minLength
)
(setq adjustSize t)
)
)
((and (stringp cdfId->l->value)
(null (parseString cdfId->l->value " \t\n")))
(warn "Empty length is illegal; setting to minimum (%L)\n"
minLength)
(setq adjustSize t)
)
;; if it is an expression that is not directly a number,
;; do nothing
(t nil)
)
(when adjustSize
(cond
((equal "string" cdfId->l->paramType)
cdfId->l->value = (sprintf nil "%g" minLength)
)
(t cdfId->l->value = minLength)
)
)
)
)
)
(case cdfId->topography->value
("normal" t
)
("ring" t
)
("fieldless" t
)
("halfFieldless" t
)
("drainOnly"
(when (and cdfId->deriveAP->value
(nequal "FALSE" cdfId->deriveAP->value)
)
(let (w l area perim)
(setq w cdfId->w->value)
(setq l cdfId->l->value)
(when (and (stringp w) (aelIsNumberP w))
(setq w (aelNumber w))
)
(when (and (stringp l) (aelIsNumberP l))
(setq l (aelNumber l))
)
(cond
((and (numberp w) (numberp l))
(setq area (times w l))
(setq perim (times 2.0 (plus w l)))
)
(t
(when (numberp w) (setq w (sprintf nil "%g" w)))
(when (numberp l) (setq l (sprintf nil "%g" l)))
(setq area (sprintf nil "((%s)*(%s))" w l))
(setq perim (sprintf nil "(2.0*((%s)+(%s)))" w l))
)
)
;; store the area
(cond
((equal "string" cdfId->area->paramType)
(when (numberp area) (setq area (sprintf nil "%g" area)))
cdfId->area->value = area
)
((null (numberp area))
(warn "xtor CDF type screwup\n")
)
(t cdfId->area->value = area)
)
;; store the perim
(cond
((equal "string" cdfId->perim->paramType)
(when (numberp perim)
(setq perim (sprintf nil "%g" perim))
)
cdfId->perim->value = perim
)
((null (numberp perim))
(warn "xtor CDF type screwup\n")
)
(t cdfId->perim->value = perim)
)
)
)
)
(t nil)
)
)
;;;
;;; CDFbuildNpnModelName --
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFbuildNpnModelName (cdfgData "o")
cdfgData->modelName->value = (sprintf nil "q%dc%db%de%fx%f"
cdfgData->numCollectors->value
cdfgData->baseLocation->value
cdfgData->numEmitters->value
cdfgData->emitterWidth->value
cdfgData->emitterLength->value)
)
;;;
;;; CDFreverseNpnModelName --
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFreverseNpnModelName (cdfId "o")
; (let (nc bl ne ew el parsed)
; (setq parsed (parseString cdfId->modelName->value "qcbex"))
;; this could get real recursive real fast.
t
; )
)
;;;
;;; CDFupdateDiscreteFetWL --
;;;
;;; Input: instance Id and CDF data
;;; Output:
;;; Globals: None
;;; Side Effects: Update the discrete width/length CDF parameters if W/L are valid choices
;;; Print warnings if W/L values are not valid choices
;;; Return:
;;;
(defun CDFupdateDiscreteFetWL (instCDF instId)
(let (
(widthChoices nil) (widthChoicesNumbers nil)
(widthIndex nil) (lengthChoices nil) (lengthChoicesNumbers nil)
(lengthIndex nil) (Lparam nil) (Wparam nil)
(length (aelNumber instId~>l)) (width (aelNumber instId~>w))
)
(setq Lparam (strcat (concat instId~>hspiceModel "_l")))
(setq lengthChoices (get (get instCDF Lparam) 'choices))
(foreach Li lengthChoices
(setq lengthChoicesNumbers (cons (atof Li) lengthChoicesNumbers))
)
(setq lengthChoicesNumbers (reverse lengthChoicesNumbers))
(cond
((member length lengthChoicesNumbers)
(setq lengthIndex (difference (length lengthChoicesNumbers) (length (member length lengthChoicesNumbers))))
(putprop (get instCDF Lparam) (nth lengthIndex lengthChoices) 'value)
(setq Wparam (strcat (concat Lparam lengthIndex "_w")))
)
(t
(warn "Length value %L of instance %L is not a valid choice\n" instId~>l instId~>name)
)
)
(when (member length lengthChoicesNumbers)
(setq widthChoices (get (get instCDF Wparam) 'choices))
(foreach Wi widthChoices
(setq widthChoicesNumbers (cons (atof Wi) widthChoicesNumbers))
)
(setq widthChoicesNumbers (reverse widthChoicesNumbers))
)
(cond
((member width widthChoicesNumbers)
(setq widthIndex (difference (length widthChoicesNumbers) (length (member width widthChoicesNumbers))))
(putprop (get instCDF Wparam) (nth widthIndex widthChoices) 'value)
)
(t
(warn "Width value %L of instance %L is not a valid choice\n" instId~>w instId~>name)
)
)
)
)
;;;
;;; CDFevalString --
;;;
;;; This function reads a string (converts to a list form), appends the args
;;; if any, and then evals the resultant list. I wish I can find the Cadence
;;; function that does this for all of their callbacks but I had no luck. This
;;; routine is breakable in many ways but it currently works as long as only
;;; the first form in the string is expected to be evaled.
;;;
;;; Input:
;;; str - A string or nil
;;; rest - arguments to a function name in str if str is a function name
;;; Side Effects:
;;; Determined by the evaluation of the callback
;;;
(procedure (CDFevalString str @rest args)
(when (stringp str)
;; This returns a list containing the contents of str
(setq str (linereadstring str))
(when (and str (dtpr str))
;; str can be either a list containing a symbol, or a list
;; containing a list which is a function symbol with
;; arguments.
(when (dtpr (car str))
(setq str (car str))
)
(eval (append str args))
)
)
)
;;;
;;; CDFhitCallbacks --
;;; This function will hit the CDF callbacks for all of the instances in
;;; a given cellview.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFhitCallbacks (schDbid)
(cond
;; if it is a valid database object
((and (dbobjectp schDbid) (dbValidP schDbid) schDbid~>mode)
(cond
((equal "r" schDbid~>mode)
(warn "CDFhitCallbacks: cell is not writable, %L %L %L\n"
schDbid~>libName schDbid~>cellName schDbid~>viewName)
)
(t
;; must have cdfgForm listed and set to nil, even though it is
;; unused. Some tech lib CDF callbacks require this.
(let (cdfgData cdfgForm)
;; loop through all of the instance headers
(foreach instH schDbid~>instHeaders
;; if there is at least one instance and it has a CDF
(when (and (car instH~>instances)
(setq cdfgData (cdfGetInstCDF (car instH~>instances))))
(foreach inst instH~>instances
;; get the CDF info for this particular instance
(when (setq cdfgData (cdfGetInstCDF inst))
(CDFevalString cdfgData->formInitProc cdfgData)
(CDFevalString cdfgData->doneProc inst)
)
)
)
)
)
)
)
)
(t
(warn "CDFhitCallbacks: Invalid database object '%L' passed in; ignored\n" schDbid)
nil
)
)
)
;;; CDFfetgateresvalue --
;;; This function is a callback to determine the gate resistance
;;;
(defun CDFfetgateresvalue ()
(let (W L M RSP1)
(if (nequal cdfgData->resType->value "custom")
then
(setq W (atof cdfgData->w->value))
(setq L (atof cdfgData->l->value))
(setq M (atof cdfgData->m->value))
(setq RSP1 (TECHgetDeviceParam (TECHgetDevice ?name 'nfet) 'gateSheetRes))
(cond
((equal cdfgData->resType->value "single")
cdfgData->gateresValue->value = (sprintf nil "%g" RSP1*W/L/M/3))
((equal cdfgData->resType->value "double")
cdfgData->gateresValue->value = (sprintf nil "%g" RSP1*W/L/M/12))
)
)
)
)
;;;
;;; CDFconstantCcap2Callback --
;;; This function calculates values given a constant C
;;; for the cap2 tech element.
;;;
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFconstantCcap2Callback (cdfgData "o")
;; copy a pile of this from CDFcapCallback
;; we can ignore checking for absolute cap as this callback
;; is only called when constant C is selected (hopefully)
(let (capDevices thisCap subCkt ctype cw cm space capSpaceData capWidthData coupling temp
width1 width2 space1 space2 capModel Ca Cc1 Cc2 Cf1 Cf2 Cc3 Cf3 Cc4 Cf4 linearCc linearCf
scale localKswitch globalCoupling scale L)
(setq capDevices (TECHgetCapDevices))
(setq thisCap (car capDevices))
;; loop through all the caps looking for the one with this model
(while (and thisCap
(nequal cdfgData~>ctype~>value
(TECHgetDeviceParam thisCap 'hspiceModel))
)
(setq thisCap (car capDevices))
(setq capDevices (cdr capDevices))
)
(setq subCkt (TECHgetDeviceParam thisCap 'isSubckt))
(when (and thisCap (not subCkt) (boundp 'TECHcapParams))
;; set the "space" properties if applicable
(setq capSpaceData (CDFgetCapSpaceProps cdfgData thisCap))
(setq capWidthData (CDFgetCapWidthProps cdfgData thisCap))
(setq c cdfgData~>c~>value)
(setq width1 capWidthData->cw1)
(setq width2 capWidthData->cw2)
(setq ctype cdfgData~>ctype~>value)
(setq cw (or cdfgData~>cw~>value capWidthData->cw))
(setq cm (or cdfgData~>cm~>value 1))
(setq space (or cdfgData~>space~>value capSpaceData->space))
(setq space1 capSpaceData->capSpace1)
(setq space2 capSpaceData->capSpace2)
(setq coupling (or cdfgData~>coupling~>value 1.0))
;; these parameters are the same across all rescap models
;; (if these eventually change bad things will happen)
(setq localKswitch "1")
(setq globalCoupling "1")
(setq scale "1e-06")
(setq capModel thisCap->hspiceModel)
;; this part ripped out of hspice.il
(cond
(width1
(setq temp (TECHcapParams[(list capModel space1 width1)]))
(setq Ca (car temp))
(setq Cc1 (cadr temp))
(setq Cf1 (caddr temp))
(when space2
(setq temp (TECHcapParams[(list capModel space2 width1)]))
(setq Cc2 (cadr temp))
(setq Cf2 (caddr temp))
)
(when (and (null space2) width2)
(setq temp (TECHcapParams[(list capModel space1 width2)]))
(setq Cc2 (cadr temp))
(setq Cf2 (caddr temp))
)
(when (and space2 width2)
(setq temp (TECHcapParams[(list capModel space1 width2)]))
(setq Cc3 (cadr temp))
(setq Cf3 (caddr temp))
(setq temp (TECHcapParams[(list capModel space2 width2)]))
(setq Cc4 (cadr temp))
(setq Cf4 (caddr temp))
)
)
;; if we do not use width as a table lookup (only space)
(t
(setq temp (TECHcapParams[(list capModel space1)]))
(setq Ca (car temp))
(setq Cc1 (cadr temp))
(setq Cf1 (caddr temp))
(when space2
(setq temp (TECHcapparams[(list capModel space2)]))
(setq Cc2 (cadr temp))
(setq Cf2 (caddr temp))
)
)
)
(foreach var '(Ca Cc1 Cf1 Cc2 Cf2 Cc3 Cf3 Cc4 Cf4 cw globalCoupling coupling localKswitch scale)
(unless (or (stringp (eval var)) (null (eval var)))
(set var (sprintf nil "%L" (eval var)))
)
)
(cond
;; if there are 4 data points to do a 2D interpolation between
;; both width and space
;;
(Cc4
(setq linearCc
(CDFinterpolateS cw
width1
(CDFinterpolateS space space1 Cc1 space2 Cc2)
width2
(CDFinterpolateS space space1 Cc3 space2 Cc4)
)
)
(setq linearCf
(CDFinterpolateS cw
width1
(CDFinterpolateS space space1 Cf1 space2 Cf2)
width2
(CDFinterpolateS space space1 Cf3 space2 Cf4)
)
)
)
;; if there are 2 data points, and it is width based
((and Cc2 width2)
(setq linearCc (CDFinterpolateS cw width1 Cc1 width2 Cc2))
(setq linearCf (CDFinterpolateS cw width1 Cf1 width2 Cf2))
)
;; if there are 2 data points, and it is space based
((and Cc2 space2)
(setq linearCc (CDFinterpolateS space space1 Cc1 space2 Cc2))
(setq linearCf (CDFinterpolateS space space1 Cf1 space2 Cf2))
)
;; if it is an exact match on both width and space
(t
(setq linearCc Cc1)
(setq linearCf Cf1)
)
)
;; solve for L
(sprintf neighborFringeBuffer
"(%s * (%s * (%s + 1) / 2 + (2 - %s) * (1 - %s) / 2) * %s)"
globalCoupling
coupling
localKswitch
coupling
localKswitch
linearCc)
(sprintf perimCapTemp
"(%s + %s)"
neighborFringeBuffer linearCf)
(sprintf Lequation_top
"((%s / %s) - (2 * %s * %s * %s))"
c cm scale perimCapTemp cw)
(sprintf Lequation_bottom
"((%s * %s * %s * %s) + (2 * %s * %s))"
cw scale scale Ca scale perimCapTemp)
(sprintf Lequation
"(%s / %s)"
Lequation_top Lequation_bottom)
(unless (errset (setq L (evalstring Lequation)))
(setq L Lequation))
(when (equal (type L) 'string)
(sprintf L "%s" L)
)
(when (nequal (type L) 'string)
(sprintf L "%L" L)
)
cdfgData~>cl~>value=L
;; end hspice.il section
)
(unless (boundp 'TECHcapParams)
(info "Info: Rescap data missing or in wrong format. Constant C option not available\n")
)
(when subCkt
(info "Info: Constant C option does not work for subcircuit model \"%s\"\n" thisCap->hspiceModel)
cdfgData->isConstantC->value=nil
)
) ;; let
)
;;;
;;; CDFgetCapSpaceProps --
;;;
;;; Description: Returns cap space props for cap2 callback.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFgetCapSpaceProps (cdfgData capDevice)
(let
(spaceVals
prevSpace
thisSpace
targetSpace
thisLayer
returnVals
)
(setq returnVals (list nil))
(setq spaceVals (TECHgetDeviceParam capDevice 'spacings))
(setq thisLayer (TECHgetDeviceParam capDevice 'layers))
(cond
;; if it is a triple layer cap, the main layer is the middle one
((equal 3 (length thisLayer))
(setq thisLayer (cadr thisLayer))
)
;; if it is a two layer cap, the main layer is the first one
((equal 2 (length thisLayer))
(setq thisLayer (car thisLayer))
)
)
(setq targetSpace
(or cdfgData~>space~>value (TECHgetRuleWith "minSpacing" thisLayer) 0.0))
(when (and (stringp targetSpace) (aelIsNumberP targetSpace))
(setq targetSpace (aelNumber targetSpace))
)
(when spaceVals
;; the spaceVals parameter should be sorted in increasing order.
(setq thisSpace (car spaceVals))
(setq spaceVals (cdr spaceVals))
(while (and spaceVals
(greaterp targetSpace
(plus thisSpace 1e-5)))
(setq prevSpace thisSpace)
(setq thisSpace (car spaceVals))
(setq spaceVals (cdr spaceVals))
)
(cond
;; 1. if this is > the last space value in the list, or
;; 2. if this is <= the first space value in the list, or
;; 3. if this is close enough to the current value in the list
;; use last space value it saw
((or (greaterp targetSpace thisSpace)
(null prevSpace)
(null (greaterp (abs (difference targetSpace thisSpace))
1e-5)))
(setq returnVals (append returnVals (list 'capSpace1 thisSpace)))
)
;; if this is between two spacing values
(t
(setq returnVals (append returnVals (list 'capSpace1 thisSpace 'capSpace2 prevSpace)))
;; with two space values, it will use an equation and it is
;; required to have the "space" property
(unless cdfgData~>space~>value
(setq returnVals (append returnVals (list 'space targetSpace)))
)
)
)
)
returnVals
)
)
;;;
;;; CDFgetCapWidthProps --
;;;
;;; Description: Returns cap width props for cap2 callback.
;;; Input:
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return:
;;;
(defun CDFgetCapWidthProps (cdfgData capDevice)
(let
(thisLayer
widthVals
prevWidth
thisWidth
targetWidth
returnVals
)
(setq returnVals (list nil))
(setq widthVals (TECHgetDeviceParam capDevice 'widths))
(setq thisLayer (TECHgetDeviceParam capDevice 'layers))
(cond
;; if it is a triple layer cap, the main layer is the middle one
((equal 3 (length thisLayer))
(setq thisLayer (cadr thisLayer))
)
;; if it is a two layer cap, the main layer is the first one
((equal 2 (length thisLayer))
(setq thisLayer (car thisLayer))
)
)
;; unfortunately, they may have tried to optimize the width. If they
;; did, the cw property is not a number, but a parameterized equation.
;; Just default to the more inaccurate min width if they tried that.
;; It will interpolate from the evaluated width in the spice sim.
;;
(setq targetWidth cdfgData~>cw~>value)
(when (and (stringp targetWidth) (aelIsNumberP targetWidth))
(setq targetWidth (aelNumber targetWidth))
)
(when (or (null targetWidth) (stringp targetWidth))
(setq targetWidth (or (TECHgetRuleWith "minWidth" thisLayer) 0.0))
)
(when widthVals
;; the widthVals parameter should be sorted in increasing order.
(setq thisWidth (car widthVals))
(setq widthVals (cdr widthVals))
(while (and widthVals
(greaterp targetWidth
(plus thisWidth 1e-5)))
(setq prevWidth thisWidth)
(setq thisWidth (car widthVals))
(setq widthVals (cdr widthVals))
)
(cond
;; 1. if this is > the last width value in the list, or
;; 2. if this is <= the first width value in the list, or
;; 3. if this is close enough to the current value in the list
;; use last width value it saw
((or (greaterp targetWidth thisWidth)
(null prevWidth)
(null (greaterp (abs (difference targetWidth thisWidth))
1e-5)))
(setq returnVals (append returnVals (list 'cw1 thisWidth)))
)
;; if this is between two spacing values
(t
(setq returnVals (append returnVals (list 'cw1 thisWidth 'cw2 prevWidth)))
;; with two width values, it will use an equation and it is
;; required to have the "width" property
(unless cdfgData~>cw~>value
(setq returnVals (append returnVals (list 'cw targetWidth)))
)
)
)
)
returnVals
)
)
;;;
;;; CDFinterpolateS --
;;; This function will return a string equation of a linear interpolation.
;;; Copied from hspice.il
;;;
;;; Input: xi - x axis point between x1 and x2 for which it should
;;; interpolate a y value
;;; x1 - x axis value of first point
;;; y1 - y axis value of first point
;;; x2 - x axis value of second point
;;; y2 - y axis value of second point
;;; Output:
;;; Globals:
;;; Side Effects:
;;; Return: string equation of interpolated value
;;;
(defun CDFinterpolateS (xi x1 y1 x2 y2)
;; get everything as a string
(foreach param '(xi x1 y1 x2 y2)
(when (floatp (eval param))
(set param (sprintf nil "%g" (eval param)))
)
)
(cond
;; do not divide by 0
((or (null x2) (equal x1 x2)) y1)
(t
(sprintf nil "(%s + (%s - %s) * (%s - %s) / (%s - %s))"
y1
xi
x1
y2
y1
x2
x1
)
)
)
)
;;;
;;; res3Max
;;; This function checks the range of res3.
(procedure res3Max()
(let ( length lengthF)
(setq lengthF atof(cdfgData->rl->value))
(setq length (cdfgData->rl->value))
if( (lengthF < 0.35) then
artError("Resistor length minimum is 0.35um. Snapped length to 0.35um.")
length = "0.35"
)
if( (lengthF > 1000) then
artError("Resistor length maximum is 1000um. Snapped length to 1000um.")
length = "1000"
)
cdfgData->rl->value = length
)
)
;;;
;;; resMax
;;; This function checks the range of res.
(procedure resMax()
(let ( length lengthF widthF width resT)
(setq lengthF atof(cdfgData->rl->value))
(setq widthF atof(cdfgData->rw->value))
(setq length (cdfgData->rl->value))
(setq width (cdfgData->rw->value))
(setq resT (cdfgData->resistorType->value))
if( (resT == "li1") then
if( (widthF < 0.72) then
artError("Resistor width minimum is 0.72um. Snapped width to 0.72um.")
width = "0.72"
)
if( (widthF > 1000) then
artError("Resistor width maximum is 1000um. Snapped width to 1000um.")
width = "1000"
)
if( (lengthF < 0.29) then
artError("Resistor length minimum is 0.29um. Snapped length to 0.29um.")
length = "0.29"
)
if( (lengthF > 1000) then
artError("Resistor length maximum is 1000um. Snapped length to 1000um.")
length = "1000"
)
)
if( (resT == "poly") then
if( (widthF < 0.33) then
artError("Resistor width minimum is 0.33um. Snapped width to 0.33um.")
width = "0.33"
)
if( (widthF > 1000) then
artError("Resistor width maximum is 1000um. Snapped width to 1000um.")
width = "1000"
)
if( (lengthF < 0.47) then
artError("Resistor length minimum is 0.47um. Snapped length to 0.47um.")
length = "0.47"
)
if( (lengthF > 1000) then
artError("Resistor length maximum is 1000um. Snapped length to 1000um.")
length = "1000"
)
)
cdfgData->rl->value = length
cdfgData->rw->value = width
)
)
;;;
;;; resnpMax
;;; This function checks the range of resn and resp.
(procedure resnpMax()
(let ( length lengthF widthF width)
(setq lengthF atof(cdfgData->rl->value))
(setq length (cdfgData->rl->value))
(setq widthF atof(cdfgData->rw->value))
(setq width (cdfgData->rw->value))
if( (widthF < 0.15) then
artError("Resistor width minimum is 0.15um. Snapped width to 0.15um.")
width = "0.15"
)
if( (widthF > 1000) then
artError("Resistor width maximum is 1000um. Snapped width to 1000um.")
width = "1000"
)
if( (lengthF < 0.27) then
artError("Resistor length minimum is 0.27um. Snapped length to 0.27um.")
length = "0.27"
)
if( (lengthF > 1000) then
artError("Resistor length maximum is 1000um. Snapped length to 1000um.")
length = "1000"
)
cdfgData->rl->value = length
cdfgData->rw->value = width
)
)
;;;
;;; respwMax
;;; This function checks the range of respw.
(procedure respwMax()
(let ( length lengthF)
(setq lengthF atof(cdfgData->rl->value))
(setq length (cdfgData->rl->value))
if( (lengthF < 26.5) then
artError("Resistor length minimum is 26.5um. Snapped length to 26.5um.")
length = "26.5"
)
if( (lengthF > 1000) then
artError("Resistor length maximum is 1000um. Snapped length to 1000um.")
length = "1000"
)
cdfgData->rl->value = length
)
)
;;;
;;; mfactorMiM
;;; This function calculates the MiM mfactor from the product of rows and columns.
(procedure mfactorMiM()
(let ( ro col )
(setq ro cdfgData->nrow->value)
(setq col cdfgData->ncol->value)
cdfgData->cm->value = (sprintf nil "%d" ro*col)
)
)
;;; AsPsPdAdNr --
;;; This function calculates the area and perimeter of source and drain of an NFET and PFET using approximations for simulation of parasitics. It also calculates the number of squares.
(procedure AsPsPdAdNr(cellName "t")
(let (cell width lengthS lengthD nf p even odd internal internalS internalD right leftS rightS rightD sourceExt drainExt sourceExtF drainExtF eso edo rcn rcp nc rsn rsp)
(if (equal cdfgData->manualDiodes->value t)
then
(setq width atof(cdfgData->w->value))
(setq nf atoi(cdfgData->m->value))
p = 0.17 ;; LICON pitch on diffusion
internal = 0.28
rightS = 0
rightD = 0
;;; Edge effects
; (cond ((equal cdfgData->bodyContact->value "none")
leftS = 0.265
right = 0.265
; )
; ((equal cdfgData->bodyContact->value "leftDetached")
; leftS = 0.195
; right = 0.195
; )
; ((equal cdfgData->bodyContact->value "rightDetached")
; leftS = 0.195
; right = 0.195
; )
; ((equal cdfgData->bodyContact->value "leftAttached")
; leftS = 0.26
; right = 0.195
; )
; ((equal cdfgData->bodyContact->value "rightAttached")
; leftS = 0.195
; right = 0.26
; )
; )
even = evenp(nf)
odd = oddp(nf)
if( even then
rightS=right
internalD = (nf/2)
internalS = (nf/2)-1
)
if( odd then
rightD=right
internalD = (nf-1)/2
internalS = (nf-1)/2
)
nc = (floor width/(2*p))
lengthS = leftS + internal*internalS + rightS
lengthD = internal*internalD + rightD
sourceExt = cdfgData->srcOffset->value
sourceExtF = atof(cdfgData->srcOffset->value)
eso = sourceExtF
drainExt = cdfgData->drnOffset->value
drainExtF = atof(cdfgData->drnOffset->value)
edo = drainExtF
(if (equal cellName "pfet")
then
(if (equal cdfgData->hspiceModelMenu->value "pshort")
then
rsp = 197
rcp = 600
)
(if (equal cdfgData->hspiceModelMenu->value "phighvt")
then
rsp = 197
rcp = 600
)
(if (equal cdfgData->hspiceModelMenu->value "plowvt")
then
rsp = 197
rcp = 600
)
(if (equal cdfgData->hspiceModelMenu->value "phv")
then
rsp = 191
rcp = 600
)
(if (equal cdfgData->hspiceModelMenu->value "phvesd")
then
rsp = 191
rcp = 600
)
cdfgData->nrs->value = (sprintf nil "%g" eso*rsp+rcp/nc)
cdfgData->nrd->value = (sprintf nil "%g" edo*rsp+rcp/nc)
)
(if (equal cellName "nfet")
then
(if (equal cdfgData->hspiceModelMenu->value "nshort")
then
rsn = 120
rcn = 182
)
(if (equal cdfgData->hspiceModelMenu->value "nlowvt")
then
rsn = 120
rcn = 182
)
(if (equal cdfgData->hspiceModelMenu->value "nhv")
then
rsn = 114
rcn = 182
)
(if (equal cdfgData->hspiceModelMenu->value "nhvesd")
then
rsn = 114
rcn = 182
)
(if (equal cdfgData->hspiceModelMenu->value "nhvnative")
then
rsn = 114
rcn = 182
)
(if (equal cdfgData->hspiceModelMenu->value "ntvnative")
then
rsn = 114
rcn = 182
)
(if (equal cdfgData->hspiceModelMenu->value "nhvnativeesd")
then
rsn = 114
rcn = 182
)
(if (equal cdfgData->hspiceModelMenu->value "sonos_e")
then
rsn = 114
rcn = 182
)
(if (equal cdfgData->hspiceModelMenu->value "sonos_p")
then
rsn = 114
rcn = 182
)
cdfgData->nrs->value = (sprintf nil "%g" eso*rsn+rcn/nc)
cdfgData->nrd->value = (sprintf nil "%g" edo*rsn+rcn/nc)
)
cdfgData->as->value = (sprintf nil "%g" lengthS*width)
cdfgData->ps->value = (sprintf nil "%g" 2*(lengthS+width))
cdfgData->ad->value = (sprintf nil "%g" lengthD*width)
cdfgData->pd->value = (sprintf nil "%g" 2*(lengthD+width))
)
)
)