;---- Jul 4 19:49 95 sasha 15863 -------------------------------------- ;;;######################################################## ;;;# ;;;# SUNY at Stony Brook RSFQ Laboratory ;;;# Authors: A. Rylyakov and S.Polonsky ;;;# Date: Nov 21, 1994 ;;;# Description: ;;;# ;;;# L-Meter user interface and various layout tools ;;;# ;;;# Project: "lm.il" ;;;# Project group: S.Polonsky and A.Rylyakov ;;;# ;;;######################################################### ;;; ;;; RCS:$Header: /home/rsfq1/cdsuser/RCS/lm.il,v 1.21 1996/11/09 20:31:12 sasha Exp sasha $ ;;; ;;; All settings, i.e ;;; layers, fonts, fontsizes, keybindings ..., etc ;;; are defined immediately after the headers of the sections ;; ;;; (encrypt "~cdsuser/lm.il" "~cdsuser/lm.ile") ;;; (load "~cdsuser/lm.il") (load "~cdsuser/lm.ile") ;;; for all shell scripts to run successfully ;;; starting Cadence with an xterm for its output is recommended ;;; example: xterm -e layoutPlus & ;;;#################################### ;;;# ;;;# General Configuration Variables ;;;# ;;;#################################### (setq lmTerminalLayer "term") (setq lmTextLayer "text") ;;;######################################################## ;;;# ;;;# create a pulldown menu to run RSFQ specific commands ;;;# ;;;######################################################### ;... lmAddLMeterMenu .......... Nov 7 94 sasha 0 (procedure lmAddLMeterMenu(dummy) lmInitItem = hiCreateMenuItem( ?name 'initializeItem ?itemText "Initialize L-Meter" ?callback "lmInit(LMmenu)" ) lmeterItem = hiCreateMenuItem( ?name 'lmeterItem ?itemText "Run L-Meter" ?callback "lext()" ) rbiasItem = hiCreateMenuItem( ?name 'rbiasItem ?itemText "Generate Bias Resistor" ?callback "lmResistorData()" ) lmterminalItem = hiCreateMenuItem( ?name 'lmterminalItem ?itemText "Draw Terminal" ?callback "lmDrawTerminal()" ) lminductanceItem = hiCreateMenuItem( ?name 'lminductanceItem ?itemText "Generate Inductance" ?callback "lmEnterInductancePath()" ) LMmenu = hiCreatePulldownMenu( 'LMmenu "RSFQ Layout" list('lmInitItem 'lmeterItem 'rbiasItem 'lmterminalItem 'lminductanceItem) ) hiDisableMenuItem( LMmenu 'lmeterItem ) winid = hiGetCurrentWindow() hiInsertBannerMenu(winid 'LMmenu 10) ) ; ** defun ** (procedure avrCopyrightLMString() ;;; returns the copyright string to be ;;; printed to the console every time ;;; lm.il is loaded strcat("\n*********************************************************\n*\tSUNY at Stony Brook RSFQ Laboratory\n" "*\tLayout extraction for L-Meter\n" "*\tCopyright (c) 1995- by A.Rylyakov, S.Polonsky and P.Bunyk\n" "*********************************************************\n\n") ) printf("Loading lm.il\n") printf(avrCopyrightLMString()) ; register LMeterMenu: (cond ( deGetAppInfo("maskLayout")->userPostInstallTrigger != 'lmAddLMeterMenu deRegUserTriggers("maskLayout" nil nil 'lmAddLMeterMenu ) ) );dnoc ;;;#################################### ;;;# ;;;# Set Up Working Directory, ;;;# Host where to run L-Meter, which lm.dfl to use ;;;# (Initialize...) ;;;# ;;;#################################### (setq lmHome getShellEnvVar("HOME")) (setq lmCurrentHost getShellEnvVar("HOST")) (setq lmRunHost lmCurrentHost) ;; L-Meter working directory initially offered in the ;; Initialize... menu is the directory where you started Cadence (setq lmWorkingDir getWorkingDir()) ; here we change "~" to full path (cond (lmWorkingDir == "~" lmWorkingDir = lmHome) (t lmWorkingDir = strcat(lmHome substring(lmWorkingDir 2 strlen(lmWorkingDir)-1)) ) );dnoc ;; unless you have set up the variable ;; lmeterWorkingDirPostfix in your .cdsinit file. ;; Example: if your $HOME is "/home/rsfq1/sasha" and ;; lmeterWorkingDirPostfix="/cadence/lmeter" then ;; the offered directory will be "/home/rsfq1/sasha/cadence/lmeter" (cond ( boundp('lmeterWorkingDirPostfix) (setq lmWorkingDir strcat(lmHome lmeterWorkingDirPostfix)) ) ) ;; Of course, it can be overridden by the path you type in the menu. ;; If, however, you would like the pathname to be generated in the form of ;; lmWorkingDir+_ then ;; press the "Default" button on the Initialze... menu ;... lmSetUpWorkingDir ........ Oct 7 94 sasha 11 (procedure lmSetUpWorkingDir() cellid = geGetEditCellView() thisLibName = cellid->libName thisCellName = cellid->cellName (setq lmDefWorkingDir sprintf(result "%s/%s_%s" lmWorkingDir thisLibName thisCellName)) ) ; ** procedure lmSetUpWorkingDir** ;; The lm.dfl used by L-Meter is the first found in the ;; 1. current directory ( current value of lmWorkingDir ) ;; 2. LM_DEFAULTS environment variable ;; !!! NOTE that if you want to set up LM_DEFAULTS automatically ;; use .cshrc NOT .login !!! ;; 3. $HOME+lmDflPathPostfix if the variable ;; lmDflPathPostfix is set in the .cdsinit file ;; all of the above can be overridden by: ;; 4. the one you typed in the Initialize... menu ;; 5. the system lm.dfl if the path in the Initialize... menu is empty ;; 6. May 22 1995 new addition : from now on if the ;; "rsfqLMTechFile" property in the current library is set ;; it's value is lmDflPathValue and it wins over lmDflPathPostfix ;; but not over LM_DEFAULTS or lm.dfl in the current directory ;; ;; in your .cdsinit file you may have the following lines: ;;lmDflPathPostfix = "/cadence/user/lm.dfl" ;<- your own lm.dfl ;;lmeterWorkingDirPostfix="/cadence/lmeter" ;<- L-Meter run directory ;;load("~/cadence/SKILL/lm-5.il") ;; ;; this is a small perl script , it will ;; be used for checking if LM_DEFAULTS is tuned on ;; the remote host (i.e. if it is in the .cshrc) ;; ;... lmCreateCheckEnvScript ... Nov 22 94 sasha 542 (procedure lmCreateCheckEnvScript() lmCheckEnvFileName = strcat(lmHome makeTempFileName("/chckenv")) lmCheckEnvFile = outfile(lmCheckEnvFileName "w") lmPerlFoundp = nil ;;;######################################################################### ;;;!!!!!!! THIS IS THE ONLY LINE YOU !!!!!!!!!!!!!!!!!!!!!!!!!!! ;;;!!!!!!! HAVE TO COMMENT OUT IF YOU DON'T WANT !!!!!!!!!!!!!!!!!!!!!!!!!!! ;;;!!!!!!! LM_DEFAULTS ON THE REMOTE HOST TO BE CHECKED !!!!!!!!!!!!!!!!!!!! ; lmPerlFoundp = t ; until rsh becomes quicker ;;;######################################################################### ;;; lmDefaultsOnRunHost will be assumed to be the same as on current host ;;; (cond (isFile("/usr/local/bin/perl") lmPerlPath = "/usr/local/bin/perl" ) (isFile("/usr/bin/perl") lmPerlPath = "/usr/bin/perl" ) (t lmPerlFoundp = nil printf("Perl not found in /usr/local/bin/perl or /usr/bin/perl\n checking of LM_DEFAULTS on remote host is disabled\n") ) ) ; ** cond isFile ** (cond (lmPerlFoundp == t fprintf(lmCheckEnvFile "#! %s \n open(ENV,\"printenv |\");\n while(){if(/^LM_DEFAULTS=(\\S*)$/){print \"$1\\n\";}}\n" lmPerlPath ) close(lmCheckEnvFile) (sh sprintf(result "chmod a+x %s" lmCheckEnvFileName )) ) ) ; ** cond lmPerlFoundp ** );procedure lmScriptAlreadyRunp = nil (procedure lmRunCheckEnvScript() lmCreateCheckEnvScript() lmCheckEnvOutFileName = strcat(lmHome makeTempFileName("/envout")) (cond (lmPerlFoundp == t (sh sprintf(result "rsh %s \" %s > %s \" " lmRunHost lmCheckEnvFileName lmCheckEnvOutFileName )) lmCheckEnvOutFile = infile(lmCheckEnvOutFileName) result = fscanf(lmCheckEnvOutFile "%s" lmDefaultsOnRunHost) close(lmCheckEnvOutFile) (cond (result == nil lmDefaultsOnRunHost = "" printf("Note : LM_DEFAULTS on %s is %s\n" lmRunHost "not found") ) (t printf("Note : LM_DEFAULTS on %s is %s\n" lmRunHost lmDefaultsOnRunHost) ) ) ; ** cond result ** lmScriptAlreadyRunp = t (cond ( isFile(lmCheckEnvOutFileName) deleteFile(lmCheckEnvOutFileName) ) );dnoc (cond ( isFile(lmCheckEnvFileName) deleteFile(lmCheckEnvFileName) ) );dnoc ) ) ; ** cond lmPerlFoundp ** );procedure ;... lmFindLmDfl .............. Jun 15 95 sasha 1586 (procedure lmFindLmDfl() ;_Jan 14 00 paul 617 ;; lmDflPathValue is set in the following order: ;; 1. "" ;; 2. lmDflPathPostfix ;; 3. tcGetLibProp "rsfqLMTechFile" ;; 4. LM_DEFAULTS ;; 5. isFile("lm.dfl" list(lmWorkingDir)) ;; wins the latest non-nil ;; 2 and 3 (in any order) should be put before 4, 4 should be before 5 ;; 2 and 3 would work only if both 4 and 5 are nil (setq lmDflPathValue "") (cond ( boundp('lmDflPathPostfix) (setq lmDflPathValue strcat(lmHome lmDflPathPostfix )) )) (cond (lmDflPathValue = (dbSearchPropByName (ddGetObj geGetEditCellView()->libName) "rsfqLMTechFile")->value ; tcGetLibProp("rsfqLMTechFile" geGetEditCellView()->libName) nil) (t lmDflPathValue = "" printf("Note: property rsfqLMTechFile is not set in the library %L\n You may be using wrong or outdated technology file. Contact your Cadence Manager.\n" geGetEditCellView()->libName) )) (cond (lmRunHost == lmCurrentHost && stringp( getShellEnvVar("LM_DEFAULTS")) (setq lmDflPathValue getShellEnvVar("LM_DEFAULTS")) ) (lmRunHost != lmCurrentHost && lmScriptAlreadyRunp == nil && lmPerlFoundp == t lmRunCheckEnvScript() (cond (lmDefaultsOnRunHost != "" (setq lmDflPathValue lmDefaultsOnRunHost)))) (lmRunHost != lmCurrentHost && lmScriptAlreadyRunp == t && lmPerlFoundp == t (cond (lmDefaultsOnRunHost != "" (setq lmDflPathValue lmDefaultsOnRunHost))) ) (lmRunHost != lmCurrentHost && lmPerlFoundp == nil && stringp( getShellEnvVar("LM_DEFAULTS")) (setq lmDflPathValue getShellEnvVar("LM_DEFAULTS")) ) );dnoc (cond (isFile("lm.dfl" list(lmWorkingDir)) (setq lmDflPathValue strcat(lmWorkingDir "/lm.dfl")) ) );dnoc ); procedure lmFindLmDfl() ;;; oklmInitCB - procedure that is called when the OK or Apply ;;; button on the lmWorkingDirForm is pressed (procedure oklmInitCB(form "r") lmWorkingDir = form->lmWorkingDirField->value lmDflPathValue = form ->lmDflPathField -> value lmRunHost = form ->lmRunHostField -> value (cond ( ! isDir(lmWorkingDir) createDir(lmWorkingDir))) (cond ( ! isDir(lmWorkingDir) printf("%s not created!\n" lmWorkingDir) printf("check if the parent directory exists\n") ));cond (cond ( isDir(lmWorkingDir) hiEnableMenuItem( LMmenu 'lmeterItem ) lmDflFieldNotEditedp == t )); cond ); procedure ; cancellmInitCB - procedure that is called when the Cancel ; button is pressed on the lmWorkingDirForm (procedure cancellmInitCB(form "r") nil ) ;;; ;;; lmInit is the procedure which creates lmWorkingDirForm ;;; ;... lmInit ................... May 22 95 sasha 72 (procedure lmInit(LMmenu) ;_Jan 14 00 paul 704 lmDflFieldNotEditedp = t lmSetUpWorkingDir() lmFindLmDfl() lmWorkingDirForm = hiCreateAppForm( ?name 'lmWorkingDirForm ?formTitle "L-Meter Initialization Form" ?callback list('oklmInitCB 'cancellmInitCB) ?fields list( list( hiCreateStringField( ?name 'lmWorkingDirField ?prompt "L-Meter Working Directory:" ?value lmWorkingDir ?defValue lmDefWorkingDir ?callback "lmWorkingDirFieldCB()" ) 10:10 750:30 200 ) list( hiCreateCyclicField( ?name 'lmRunHostField ?choices list(lmRunHost "rsfq1" "matilda" "elsa" "irina" "frida") ?prompt "Run L-Meter on" ?value lmRunHost ?callback "lmRunHostFieldCB()" ) 10:50 300:30 100 ) list( hiCreateStringField( ?name 'lmDflPathField ?prompt "File to use as lm.dfl:" ?value lmDflPathValue ?callback "lmDflPathFieldCB()" ) 10:100 750:30 200 ) ) ?help "" ?unmapAfterCB t ?initialSize 800:250 ) hiDisplayForm(lmWorkingDirForm) hiMoveInsBarToEnd(lmWorkingDirForm 'lmWorkingDirField) hiMoveInsBarToEnd(lmWorkingDirForm 'lmDflPathField) ) ; ** procedure lmInit ** (procedure lmDflPathFieldCB() lmDflCurrPath = lmWorkingDirForm->lmDflPathField->value (cond ( lmDflCurrPath != lmDflPathValue lmDflFieldNotEditedp = nil ) );cond (cond ( (! isFile(lmDflCurrPath)) && lmDflCurrPath != "" hiDisplayAppDBox( ?name 'lmDflNotFoundBox ?dboxText sprintf(result "file %s not found; reenter data\n " lmDflCurrPath ) ) lmDflPathValue = lmDflCurrPath lmDflFieldNotEditedp = t ) ) ; ** cond isFile ** );procedure (procedure lmRunHostFieldCB() lmRunHost =lmWorkingDirForm ->lmRunHostField -> value (cond (lmRunHost != lmCurrentHost lmRunCheckEnvScript() ) ) ; ** cond lmRunHost ** lmWorkingDirFieldCB() );procedure (procedure lmWorkingDirFieldCB() lmWorkingDir =lmWorkingDirForm ->lmWorkingDirField->value (cond (! isDir(lmWorkingDir) hiDisplayAppDBox( ?name 'lmWorkingDirNotFoundBox ?dboxText sprintf(result "%s directory not found; create it?" lmWorkingDir) ?callback "createDir(lmWorkingDir)" ) ) ) ; ** cond isDir ** (cond (lmDflFieldNotEditedp == t lmFindLmDfl() lmWorkingDirForm -> lmDflPathField ->value = lmDflPathValue ) );cond );procedure ;;;############################################################ ;;;# ;;;# Extract inductances ;;;# ;;;############################################################ ;... lext ..................... Oct 7 94 sasha 0 (procedure lext() ;_Feb 11 00 paul 1556 cellid = geGetEditCellView() thisLibName = cellid->libName thisCellName = cellid->cellName libid = thisLibName printf("****************************************************************\n") printf("Extracting inductances of %s from %s\n" thisCellName thisLibName) printf("****************************************************************\n") printf("Creating flat workview...\n") workviewName="lmeter" lmCreateFlatWorkview(cellid workviewName) printf("Writing LMETER input files...\n") lmCreateLmeterInputData(thisLibName thisCellName workviewName) ;;;######################################################################### ;;;!!!!!!! THIS IS THE ONLY LINE YOU !!!!!!!!!!!!!!!!!!!!!!!!!!! ;;;!!!!!!! HAVE TO COMMENT OUT IF YOU DON'T WANT !!!!!!!!!!!!!!!!!!!!!!!!!!! ;;;!!!!!!! L_METER TO BE RUN AUTOMATICALLY !!!!!!!!!!!!!!!!!!!!!!!!!!! ; lmRunLMeter() ;;;######################################################################### ;;;######################################################################### ;;;!!!!!!! THIS IS THE ONLY LINE YOU !!!!!!!!!!!!!!!!!!!!!!!!!!! ;;;!!!!!!! HAVE TO CHANGE IF YOU DON'T WANT !!!!!!!!!!!!!!!!!!!!!!!!!!! ;;;!!!!!!! CELLVIEW "lmeter" TO BE ERASED !!!!!!!!!!!!!!!!!!!!!!!!!!! (cond (! boundp('lmLmeterViewErasep) lmLmeterViewErasep= nil )) ;;; change it to nil ;;;######################################################################### ; (cond ( boundp('lmLmeterViewErasep) && lmLmeterViewErasep ; ddDeleteObj(ddGetObj(libid thisCellName workviewName)) )) ) ; ** procedure lext ** ;... lmCreateFlatWorkview ..... Oct 7 94 sasha 0 (procedure lmCreateFlatWorkview(cellid viewname) ;------------------------- ; Create workview ;------------------------- thisLibName=cellid->libName thisCellName=cellid->cellName geWriteCellView(cellid thisLibName thisCellName viewname) workid= dbOpenCellView(thisLibName thisCellName viewname "" "a") ;------------------------- ; Flatten workview ;------------------------- foreach(inst workid~>instances printf("%s of %s " inst~>objType inst~>cellName) qq=leFlattenInst( inst 20 t ) println(qq) ) lmCleanUpWorkview(workid) dbSave(workid) dbClose(workid) ) ;... lmCleanUpWorkview ........ Jul 4 95 sasha 307 (procedure lmCleanUpWorkview(cellviewid) ;_Feb 11 00 paul 507 ;; DRC seemingly has problems with nets, green dots ;; and, generally, with things written in a physical layer over same layer (let (shape area box) foreach(shape cellviewid->shapes box = shape -> bBox (cond (shape->layerName == "r2" && box area = abs( caar(box) - caadr(box) )*abs( car( cdar(box)) - cadr( cadr(box)) ) (cond ( area <= 4.0 dbDeleteObject(shape) )) )) ) dbDeleteAllNet(cellviewid) ivDRC( ?cell cellviewid ?full t ?set "lmeter?") ) ; ** let ** ) ; ** procedure lmCleanUpWorkview ** ;... lmCreateLmeterInputData .. Oct 7 94 sasha 0 (procedure lmCreateLmeterInputData(thisLibName thisCellName viewname) cellid = dbOpenCellView(thisLibName thisCellName viewname "" "a") ;----------------------------- ; Convert shapes to polygons ;(modified by kolya 30.07.2000 for the new "10" Cadence) ;----------------------------- foreach(shape cellid~>shapes ; shapeLayer = get_string(shape~>layerName) ; shapeType = get_string(shape~>objType) shapeLayer = shape~>layerName shapeType = shape~>objType ; isTextLabelLinep= ; shapeLayer==lmTextLayer||shapeType=="label"||shapeType=="line"||shapeType=="" ; (cond ( ! isTextLabelLinep leConvertShapeToPolygon(shape) )) (cond ( shapeType=="rect" leConvertShapeToPolygon(shape) )) (cond ( shapeType=="polygon" leConvertShapeToPolygon(shape) )) ); foreach ; -- this table will store info on terminals as a list ; (termName termUp termDown) termInfo = makeTable("termInfo" 0) ;------------------------------ ; Write to DXC file ;----------------------------- nterm=0 dxc=outfile(sprintf(result "%s/%s" lmWorkingDir "lmeter.dxc") "w") fprintf(dxc "$ENTITIES\n") foreach(shape setof(dummy cellid~>shapes dummy~>objType=="polygon"||dummy~>objType=="line" ) thisLayer=shape~>layerName if(equal(thisLayer lmTerminalLayer ) then nterm=nterm+1 elev=nterm ; -- get terminal info termInfo[nterm]=cons( lmtermName(shape) lmtermUpDown(shape)) ; printf("%s %d\n" tname nterm) else elev=0 ) ; -- write polyline header fprintf(dxc "$POLYLINE\n%s\n%d\n" thisLayer elev) plist=shape~>points ; -- write polyline points foreach(mapc point plist fprintf(dxc "%12.4f %12.4f\n" car(point) cadr(point)) );foreach (cond (shape~>objType != "line" fprintf(dxc "%12.4f %12.4f\n" car(car(plist)) cadr(car(plist))) ) );cond ); foreach fprintf(dxc "$EOF\n") close(dxc) ;------------------------------------------ ; Write additional lmeter and lm2cir files ;------------------------------------------ writeTable(sprintf(result "%s/%s" lmWorkingDir "lext.log") termInfo) writeLMeterTermInfo(termInfo) dbClose(cellid) ) ; ** procedure ** ;... writeLMeterTermInfo ...... Oct 7 94 sasha 11 (procedure writeLMeterTermInfo(termInfo) ;_Feb 13 00 paul 470 nterm=length(termInfo) printf("\nFound %d terminals\n" nterm) for( iterm 1 nterm printf("%L: %L %L %L\n" iterm car(termInfo[iterm]) nthelem(2 termInfo[iterm]) nthelem(3 termInfo[iterm]) ) ) termfile=outfile(sprintf(result "%s/%s" lmWorkingDir "lmeter.term") "w") fprintf(termfile "nterm %d\n" nterm) fprintf(termfile "termname\t") for( iterm 1 nterm fprintf(termfile "%s\t" nthelem(1 termInfo[iterm])) ) fprintf(termfile "\ntermtype\t") for( iterm 1 nterm fprintf(termfile "I\t") ) fprintf(termfile "\ntermup \t") for( iterm 1 nterm fprintf(termfile "%s\t" nthelem(2 termInfo[iterm])) ) fprintf(termfile "\ntermdown\t") for( iterm 1 nterm fprintf(termfile "%s\t" nthelem(3 termInfo[iterm])) ) fprintf( termfile "\n") close(termfile) lm2cirFile=outfile(sprintf(result "%s/%s" lmWorkingDir "term.name") "w") for(iterm 1 nterm fprintf(lm2cirFile "%s %d\n" car(termInfo[iterm]) iterm) ) close(lm2cirFile) ) (procedure lmtermUpDown(shape) ; get info on up/down plates of the terminal UP=car(setof(p shape~>prop equal(p~>name "lmUP"))) UPstr=UP~>value DN=car(setof(p shape~>prop equal(p~>name "lmDOWN"))) DNstr=DN~>value UpDown=cons(DNstr nil) UpDown=cons(UPstr UpDown) ) (procedure lmtermName(shape) lmLabel = car(setof(p shape~>prop equal(p~>name "label")))~>value ) ;;;################################################ ;;;# ;;;# Run L-Meter ;;;# ;;;################################################ (setq lmLMeterPath "/home/rsfq1/cad/bin/lmeter") (cond (getShellEnvVar("LOGNAME") == "sasha" (setq lmUserHomeDir getShellEnvVar("HOME")) (setq lmLMeterPath strcat(lmUserHomeDir "/cadence/lmeter/lmeter")))) (setq lmXtermNameString "L-Meter running on ") (setq lmLMeterOutFileName "lmeter.out") (procedure lmRunLMeter() cdcommand = strcat("cd " lmWorkingDir) lmruncommand = sprintf(result "%s lmeter.term %s < lmeter.dxc > %s" lmLMeterPath lmDflPathValue lmLMeterOutFileName) lmScriptFilePath = strcat(lmWorkingDir "/L-Meter.script") lmScriptFile=outfile(lmScriptFilePath "w") (cond (lmRunHost != lmCurrentHost fprintf(lmScriptFile "rsh %s \" %s ; %s \" \n" lmRunHost cdcommand lmruncommand) ) (t fprintf(lmScriptFile "/bin/csh -c \" %s ; %s \" \n" cdcommand lmruncommand ) ) ) ; ** cond lmRunHost ** fprintf(lmScriptFile "(cd %s ; /usr/bin/tcsh )\n" lmWorkingDir) close(lmScriptFile) lmchmodcommand = strcat("chmod a+x " lmScriptFilePath) (sh lmchmodcommand) lmXtermName = strcat( lmXtermNameString lmRunHost ) lmxtermcommand = sprintf(result "xterm -T '%s' -e %s &" lmXtermName lmScriptFilePath ) (csh lmxtermcommand) ); procedure ;;;################################################ ;;;# ;;;# General purpose functions ;;;# ;;;################################################ (procedure lmGetNumber(string) (let (num numstring file port dummy) ;; ------ convert string of type "AAA 123wewe -r 45" to integer 123 --------- rexMatchp("^[^0-9]*\\([0-9]*\\)[^0-9]*" string) numstring = rexSubstitute("\\1") file = makeTempFileName("/tmp/foo_foo_") port = outfile(file) fprintf(port "%s\n" numstring) close(port) port = infile(file) (cond ( fscanf(port "%d\n" dummy) num = dummy ) ( t num = 0 )) close(port) deleteFile(file) ;; ---------------------------------------------------- num ) ; ** let ** ) ; ** procedure ** ;;;############################################################ ;;;# ;;;# Create bias resistor ;;;# ;;;############################################################ hiSetBindKey("Layout" "Altr" "lmResistorData()") ;;; Feb 25, 1995 addition: ;;; Prof. V. Semenov requested 5 um and (get this!) 4 um resistor widths. ;;; 4 um contradicts DRC so we will draw it in another layer, say, "r2a". (setq lmResistorLayer "r2") ; HYPRES (setq lmAnotherResistorLayer "r2") ; for 4 um resistors ;;; instead of introducing a new layer ( r2a or smth ) ;;; drc rules checking the width of the r2 layer were modified (setq lmDefaultBiasCurrent 3.00) ; PSCAN units (setq lmBiasCurrentValue 2.8 ) ; PSCAN units (setq lmBiasVoltage 2.6) ; mV (setq lmPSCANunitOfCurrent 0.1250000) ; mA (setq lmPSCANunitOfResistance 2.40000) ; Ohm ;; see also lmResistorData() lmPSCANunitOfVoltage = lmPSCANunitOfCurrent*lmPSCANunitOfResistance; 0.3000 mV lmOhmResistorValue = lmBiasVoltage / (lmDefaultBiasCurrent * lmPSCANunitOfCurrent) lmEndContactResistanceTable = makeTable("lmEndContactResistanceTable" nil) ;;; these are new values of end contact resistors, given by Prof. V. Semenov lmEndContactResistanceTable[4.0] = 0.330 ; Ohm, for 4 um width lmEndContactResistanceTable[5.0] = 0.306 ; Ohm, for 5 um width lmEndContactResistanceTable[6.0] = 0.296 ; Ohm, for 6 um width ; (setq lmEndContactResistance 0.32) ; Ohm, for 6 um width (old value) lmResistorWidthString= "6" ; um lmResistorWidth = float(lmGetNumber( lmResistorWidthString )) lmContactSquareWidth = 6.0 ; um (setq lmContactMargins list( 0.5 0.5 )) ; um (setq lmMaxCurrent lmBiasVoltage / (2 * lmEndContactResistanceTable[4.0] * lmPSCANunitOfCurrent) ) (setq lmResistorLabelFont "roman") (setq lmResistorLabelSize 2) (setq lmNumPcsValue 1) (setq lmNumPcsDefaultValue 1) (setq maxnumpcs 15) ;... lmResistorLength ......... Feb 25 95 sasha 555 (procedure lmResistorLength(current numpcs) (cond (numberp(current) (cond (current >= lmMaxCurrent hiDisplayAppDBox( ?name 'lmBiasCurrentTooBigBox ?dboxText "Bias current is too big" ?callback "lmResistorData()") printf("Bias current never exceeds %f !!\n" lmMaxCurrent )) (current < lmMaxCurrent && current > 0 lmResistorLength = lmResistorWidth * ( (lmBiasVoltage / (current * lmPSCANunitOfCurrent * numpcs)) - 2 * lmEndContactResistanceTable[lmResistorWidth] ) xSnap = hiGetCurrentWindow() -> xSnapSpacing ySnap = hiGetCurrentWindow() -> ySnapSpacing snap = max(xSnap ySnap) lmResistorLength = snap * round( lmResistorLength / snap )) (current <= 0 hiDisplayAppDBox( ?name 'lmBiasCurrentNotPosBox ?dboxText "Bias current should be positive" ?callback "lmResistorData()" ))))) ; ** cond current ** ) ; ** procedure ** (procedure lmGetInitialPoint(w done pts) xy = car(pts) x = car(xy) y = car(cdr(xy)) ) ;... lmGenerateResistor ....... Jul 2 95 sasha 3063 (procedure lmGenerateResistor(current numpcs) (let (wr wc hwr hwc l xm ym xc yc cellid mastercellid contact1 contact2 actualcurrent actualOhmTotalResistance actualResistancePerPiece dummy labeltext label labelLVS layer) wr = lmResistorWidth wc = lmContactSquareWidth hwr = wr / 2 hwc = wc / 2 l = lmResistorLength(current numpcs) (cond (l < 0 hiDisplayAppDBox( ?name 'lmBiasCurrentTooBig ?dboxText "Current Too Big, Reenter Data" ?callback "lmResistorData()") )) ; ** cond l ** xm = car(lmContactMargins) ym = cadr(lmContactMargins) (cond (numberp(l) enterPoint(?prompts list("Point at the bottom left corner of the resistor") ?doneProc "lmGetInitialPoint") xc = x + hwc + xm ; coords of the center of yc = y + hwc + ym ; the 1st contact cellid = geGetEditCellView() cancelEnterFun() geDeselectAllFig(cellid) mastercellid = dbOpenCellView("hypres012" "ubm2r2" "layout" "" "r") contact1 = dbCreateInst(cellid mastercellid nil list(xc yc) "R0") geSelectFig(contact1) contact2 = dbCreateInst(cellid mastercellid nil list(xc yc+wc+l) "R0") geSelectFig(contact2) dbClose(mastercellid) (cond (l > 0 actualResistancePerPiece =(l/wr + 2*lmEndContactResistanceTable[lmResistorWidth])/lmPSCANunitOfResistance (cond (lmResistorWidth >= 5.0 layer = lmResistorLayer ) (t layer = lmAnotherResistorLayer )) rectangle = dbCreateRect(cellid layer list((xc+hwr):(yc+hwc) (xc-hwr):(yc+hwc+l))) dbCreateProp( rectangle "Resistance (PSCAN units)" "float" actualResistancePerPiece ) geSelectFig(rectangle))) actualcurrent = lmBiasVoltage / ( lmPSCANunitOfCurrent * (l / wr + 2 * lmEndContactResistanceTable[lmResistorWidth]) * numpcs ) actualOhmTotalResistance = lmBiasVoltage / (actualcurrent * lmPSCANunitOfCurrent) dbCreateProp( rectangle "Resistance (Ohm)" "float" actualOhmTotalResistance / float(numpcs)) dbCreateProp( rectangle "Bias Current (PSCAN units)" "float" actualcurrent * float(numpcs) ) (cond ( ! lmOhmResistorValueFieldOnp (cond (numpcs==1 labeltext = sprintf(dummy "I=%4.2f" actualcurrent)) (numpcs> 1 labeltext = sprintf(dummy "I=%4.2f*%d" actualcurrent numpcs)))) ( lmOhmResistorValueFieldOnp (cond (numpcs==1 labeltext = sprintf(dummy "R=%4.2f" actualOhmTotalResistance)) (numpcs> 1 labeltext = sprintf(dummy "R=%4.2f/%d" actualOhmTotalResistance numpcs))))) label = dbCreateLabel(cellid lmTextLayer xc:(yc+hwc+l/2-5) labeltext "centerLeft" "R90" lmResistorLabelFont lmResistorLabelSize) (cond (l > 0 leAttachFig( label rectangle )) (l == 0 leAttachFig( label contact1 ))) ;; labelLVS marks resistor for extraction labelLVS = dbCreateLabel(cellid lmResistorLayer xc:(yc+hwc+l/2-5) "." "centerLeft" "R90" lmResistorLabelFont lmResistorLabelSize) (cond (l > 0 leAttachFig( labelLVS rectangle )) (l == 0 leAttachFig( labelLVS contact1 ))) (cond (numpcs == 1 leHiMove()) (numpcs>1 for(dummy 1 numpcs-1 leHiCopy()) )) )) ; ** cond numberp ** ) ; ** let ** ) ; ** procedure ** ;... oklmResistorDataCB ....... Feb 27 95 sasha 624 (procedure oklmResistorDataCB(form "r") hiFormUnmap(lmResistorDataForm) lmBiasCurrentValue = form->lmBiasCurrentValueField->value lmOhmResistorValue = form->lmOhmResistorValueField->value lmNumPcsValue = form->lmNumPcsField ->value lmResistorWidthString = form->lmResistorWidthField ->value lmResistorWidth = float(lmGetNumber( lmResistorWidthString )) (cond (lmNumPcsValue <= maxnumpcs && lmNumPcsValue >= 1 lmGenerateResistor(lmBiasCurrentValue lmNumPcsValue) ) (lmNumPcsValue > maxnumpcs hiDisplayAppDBox( ?name 'lmNumberOfPiecesTooBigBox ?dboxText "Too many resistors")) (t hiDisplayAppDBox( ?name 'lmNumberOfPiecesStrange ?dboxText "Number of pieces should not be less than 1")));cond ); procedure ;... cancellmResistorDataCB ... Feb 25 95 sasha 0 (procedure cancellmResistorDataCB(form "r") nil) ;... lmResistorData ........... Feb 27 95 sasha 692 lmOhmResistorValueFieldOnp = nil (procedure lmEnablelmOhmResistorValueField() lmOhmResistorValueFieldOnp = ! lmOhmResistorValueFieldOnp hiSetFieldEditable( lmOhmResistorValueField lmOhmResistorValueFieldOnp ) hiSetFieldEditable( lmBiasCurrentValueField ! lmOhmResistorValueFieldOnp ) ) ;... lmResistorData ........... Feb 27 95 sasha 1552 (procedure lmResistorData() ;_Jan 14 00 paul 324 ;; June 6, 1996: read the rsfqBiasVoltage property if it exists (cond ( (cellview = geGetEditCellView()) && (libName = cellview->libName) && (libId = libName) && (lmBiasVoltageLibProp = (dbSearchPropByName (ddGetObj libName) "rsfqBiasVoltage")->value ; tcGetLibProp("rsfqBiasVoltage" libId) ) lmBiasVoltage = lmBiasVoltageLibProp * lmPSCANunitOfVoltage) ( t lmBiasVoltage = 2.6 )) lmOhmResistorValue = lmBiasVoltage / (lmDefaultBiasCurrent * lmPSCANunitOfCurrent) lmResistorDataForm = hiCreateAppForm( ?name 'lmResistorDataForm ?formTitle "Resistor Generation Input Data Form" ?callback list('oklmResistorDataCB 'cancellmResistorDataCB ) ?fields list( list( lmBiasCurrentValueField = hiCreateFloatField( ?name 'lmBiasCurrentValueField ?prompt "Bias Current (PSCAN units)" ?value lmBiasCurrentValue ?defValue lmDefaultBiasCurrent ?callback "lmUpdateOhmAndBias()") 10:10 250:30 170) list( hiCreateButton( ?name 'lmOhmOrBiasButton ?buttonText "Toggle between I and R fields" ?callback "lmEnablelmOhmResistorValueField()") 10:50 250:30 170) list( lmOhmResistorValueField = hiCreateFloatField( ?name 'lmOhmResistorValueField ?prompt "Resistance (Ohm)" ?value lmOhmResistorValue ?callback "lmUpdateOhmAndBias()") 10:100 250:30 170) list( hiCreateIntField( ?name 'lmNumPcsField ?prompt "Number of pieces" ?value lmNumPcsValue ?defValue lmNumPcsDefaultValue ) 10:150 250:30 170) list( hiCreateCyclicField( ?name 'lmResistorWidthField ?choices list("6" "5" "4") ?prompt "Resistor width (um)" ?value lmResistorWidthString ) 10:200 250:30 170 ) ) ?help "" ?unmapAfterCB t) hiSetFieldEditable( lmBiasCurrentValueField ! lmOhmResistorValueFieldOnp ) hiSetFieldEditable( lmOhmResistorValueField lmOhmResistorValueFieldOnp ) hiDisplayForm(lmResistorDataForm) ) ; ** procedure ** (procedure lmUpdateOhmAndBias() lmBiasCurrentValue = lmResistorDataForm -> lmBiasCurrentValueField -> value lmOhmResistorValue = lmResistorDataForm -> lmOhmResistorValueField -> value (cond (lmBiasCurrentValue > 0 && lmBiasCurrentValue <= lmMaxCurrent && ! lmOhmResistorValueFieldOnp lmOhmResistorValue = lmBiasVoltage / ( lmBiasCurrentValue * lmPSCANunitOfCurrent ))) (cond (lmOhmResistorValue >= lmBiasVoltage /( lmMaxCurrent * lmPSCANunitOfCurrent ) && lmOhmResistorValueFieldOnp lmBiasCurrentValue = lmBiasVoltage / (lmOhmResistorValue * lmPSCANunitOfCurrent ))) lmResistorDataForm -> lmBiasCurrentValueField -> value = lmBiasCurrentValue lmResistorDataForm -> lmOhmResistorValueField -> value = lmOhmResistorValue ) ; ** procedure ** ;;;################################################ ;;;# ;;;# Draw a terminal ;;;# ;;;################################################ hiSetBindKey("Layout" "Altt" "lmDrawTerminal()") (setq lmUPValue "*") (setq lmUPDefaultValue "*") (setq lmDOWNValue "*") (setq lmDOWNDefaultValue "*") (setq lmlabelValue "P") (setq lmlabelDefaultValue "P") (setq lmLabelPosValue "left") (setq lmLabelPosDefaultValue "right") (setq lmTerminalLabelFont "roman") (setq lmTerminalLabelSize 2) ;... lmDrawTerminal ........... Oct 7 94 sasha 11 (procedure lmDrawTerminal() cellid = geGetEditCellView() cancelEnterFun() geDeselectAllFig(cellid) x1y1x2y2 = enterBox( ?prompts list("Point at the first corner of the terminal" "Point at the opposite corner of the terminal" ) ?alwaysMap t ) x1y1 = car(x1y1x2y2) x1 = car(x1y1) y1 = car(cdr(x1y1)) x2y2 = car(cdr(x1y1x2y2)) x2 = car(x2y2) y2 = car(cdr(x2y2)) xtc = (x1 + x2)/2 ytc=(y1+y2)/2 ; center of terminal thwx = abs(x1-x2)/2 thwy = abs(y1-y2)/2; terminal halfwidths isAreaZerop = (x1 == x2 || y1 == y2) (cond ( isAreaZerop lmLine = dbCreateLine(cellid lmTerminalLayer list(x1:y1 x2:y2)) lmTerminal = lmLine ) ( ! isAreaZerop lmRect = dbCreateRect(cellid lmTerminalLayer list(x1:y1 x2:y2)) lmTerminal = lmRect ) ) ; ** cond ** lmTerminalData() ) ; ** procedure ** xshift = 3.5 yshift = 3.5 ;... oklmTerminalDataCB ....... Oct 7 94 sasha 11 (procedure oklmTerminalDataCB(form "r") dbCreateProp(lmTerminal "lmUP" "string" lmUPValue = form ->lmUPField->value ) dbCreateProp(lmTerminal "lmDOWN" "string" lmDOWNValue = form->lmDOWNField->value ) dbCreateProp(lmTerminal "label" "string" lmlabelValue = form->lmlabelField->value ) lmLabelPosValue = form -> lmLabelPosField -> value (cond (lmLabelPosValue == "right" labelcoords = list(xtc+thwx+xshift ytc)) (lmLabelPosValue == "left" labelcoords = list(xtc-thwx-xshift ytc)) (lmLabelPosValue == "top" labelcoords = list(xtc ytc+thwy+yshift)) (lmLabelPosValue == "bottom" labelcoords = list(xtc ytc-thwy-yshift)) );cond propid = car(setof(dummy lmTerminal~>prop dummy~>name == "label")) dbCreateTextDisplay(propid lmTerminal lmTextLayer t labelcoords "centerCenter" "R0" lmTerminalLabelFont lmTerminalLabelSize t nil t nil) ) ; ** procedure ** (procedure cancelTerminalDataCB(form "r") dbDeleteObject(lmTerminal) ) ;... lmTerminalData ........... Oct 7 94 sasha 0 (procedure lmTerminalData() ;_Feb 13 00 paul 181 xUP = 10 yUP = 10 xDOWN = 200 yDOWN = 10 xlabel = 10 ylabel = 50 xlpos = 10 ylpos = 100 width = 81 height = 20 promptWidth = 80 width2 = 300 height2 = 30 promptWidth2 = 70 lmTerminalDataForm = hiCreateAppForm( ?name 'lmTerminalDataForm ?formTitle "Terminal Properties Form" ?callback list('oklmTerminalDataCB 'cancelTerminalDataCB ) ?fields list( list( hiCreateCyclicField( ?name 'lmUPField ?choices list("*" "m1" "m2" "m3" "gnde" "triw" "wira" "wirb") ?prompt "lmUP" ?value lmUPValue ?defValue lmUPDefaultValue ) xUP:yUP width:height promptWidth ) list( hiCreateCyclicField( ?name 'lmDOWNField ?choices list("*" "m0" "m1" "m2" "gnde" "triw" "wira" "wirb") ?prompt "lmDOWN" ?value lmDOWNValue ?defValue lmDOWNDefaultValue ) xDOWN:yDOWN width:height promptWidth ) list( hiCreateStringField( ?name 'lmlabelField ?prompt "label" ?value lmlabelValue ?defValue lmlabelDefaultValue ) xlabel:ylabel width2:height2 promptWidth2 ) list( hiCreateCyclicField( ?name 'lmLabelPosField ?choices list("right" "left" "top" "bottom") ?prompt "Put label on" ?value lmLabelPosValue ?defValue lmLabelPosDefaultValue ) xlpos:ylpos width:height promptWidth ) ) ?help "" ?unmapAfterCB t ) hiDisplayForm(lmTerminalDataForm) ) ; ** procedure ** ;;;################################################ ;;;# ;;;# Draw an Inductance ;;;# ;;;################################################ hiSetBindKey("Layout" "Alti" "lmEnterInductancePath()") (setq lmInductanceValue 1.) (setq lmNumberOfGroundsValue "m0") (setq lmLVSpairs '( ("m1" "m1l") ("m2" "m2l") )) (setq layer1 "m2") (setq layer2 "m1") (setq lmDPW 6.) (setq lmInductanceLabelFont "roman") (setq lmInductanceLabelSize 2) (procedure lmEnterInductancePath() enterPath( ?prompts list( "Point at the first point of the inductance." "Point at the next point of the inductance." ) ?doneProc "lmEnterInductancePathDone" ?pathWidth lmDPW ?pathStyle "Truncate" ?alwaysMap t );enterpath ); ** procedure ** ;... lmEnterInductancePathDone . Oct 7 94 sasha 0 (procedure lmEnterInductancePathDone(windind inddone pts) cellviewid = geGetEditCellView() (cond (inddone lmRawPathId = dbCreatePath( cellviewid "m2" pts lmDPW ) lmInductanceData() ) );cond ) ; ** procedure ** ;... lmInductanceData ......... Oct 7 94 sasha 0 (procedure lmInductanceData() ;_Jan 14 00 paul 930 cellviewid = geGetEditCellView() thisLibName = cellviewid->libName libid = thisLibName lmInductanceDataForm = hiCreateAppForm( ?name 'lmInductanceDataForm ?formTitle "Iductance Drawing Form" ?callback list('oklmInductanceDataCB 'cancellmInductanceDataCB ) ?fields list( list( hiCreateFloatField( ?name 'lmInductanceValueField ?value lmInductanceValue ?prompt "Inductance (PSCAN units)" ) 10:10 250:30 170 ) list( hiCreateRadioField( ?name 'lmNumberOfGroundsField ?choices list("m0" "m0&m3" "m3" "m1") ?prompt "Ground is" ?value lmNumberOfGroundsValue ) 10:35 30:70 70 ) list( hiCreateLayerCyclicField( techGetTechFile(ddGetObj(libid)) "Layer" "" list( list(layer1 "drawing") list(layer2 "drawing") ) ) 10:120 250:30 120 ) ) ?help "" ?unmapAfterCB t ) hiDisplayForm(lmInductanceDataForm) ) ; ** procedure ** ;... oklmInductanceDataCB ..... Oct 7 94 sasha 11 (procedure oklmInductanceDataCB(form "r") lmInductanceValue = form->lmInductanceValueField->value lmNumberOfGroundsValue = form->lmNumberOfGroundsField->value lmInductanceLayer = nth(3 form->hiLayerField->value) lmDrawInductance(lmNumberOfGroundsValue lmInductanceLayer pts) );procedure (procedure cancellmInductanceDataCB(form "r") dbDeleteObject( lmRawPathId ) ) ;;;--------------------------------------------------------------- ;;; ;;; L-Meter Internal Parameters ;;; ;;;--------------------------------------------------------------- Y1=1.45 ; one ground /edge inductances/ Y2=1.1 ; two grounds bulklambda=0.085 ; ;;; Apr 18, 1995 filmshift 0.25 introduced into m1 ;;; in compliance with the new standard lm.dfl filmshift1=0.45 ; cutoffs filmshift2=0.25 ; d01=0.336 ; M0M1 d02=0.535 ; M0M2 d13=0.871 ; M1M3 d23=0.67 ; M2M3 d013=0.242 ; M0M1M3 d023=0.297 ; M0M2M3 d12=0.371 ; M1M2 mu0=1.2566 ; 4\pi/10 pH/um ;;;--------------------------------------------------------------- ;;; ;;; Formula : ;;; ;;; L=mu0*w/( ((w-2*(bulklambda+filmshift))/d)+2*Y) ;;; ;;;--------------------------------------------------------------- ;... lmDrawInductance ......... Jun 21 95 sasha 1546 (procedure lmDrawInductance(grounds layer pts) ;_Jan 19 00 paul 1677 lmTotalLength(pts) (cond ( layer == "m1 (drawing)" layer1 = "m1" layer2 = "m2") ( layer == "m2 (drawing)" layer1 = "m2" layer2 = "m1") ); cond (cond (grounds == "m0" (cond (layer1 == "m1" lmFormula(Y1 d01 filmshift1 numturns ltot)) (layer1 == "m2" lmFormula(Y1 d02 filmshift2 numturns ltot)) ) ) (grounds == "m0&m3" (cond (layer1 == "m1" lmFormula(Y2 d013 filmshift1 numturns ltot)) (layer1 == "m2" lmFormula(Y2 d023 filmshift2 numturns ltot)) ) ) (grounds == "m3" (cond (layer1 == "m1" lmFormula(Y1 d13 filmshift1 numturns ltot)) (layer1 == "m2" lmFormula(Y1 d23 filmshift2 numturns ltot)) ) ) (grounds == "m1" (cond (layer1 == "m1" printf("ERROR: attempt to draw inductance in m1 over m1 detected !\n") widthTooSmallp=t ) (layer1 == "m2" lmFormula(Y1 d12 filmshift2 numturns ltot)) ) ) ); cond grounds (cond (widthTooSmallp == t hiFormUnmap(lmInductanceDataForm) lmInductanceData() ) (widthTooSmallp == nil dbDeleteObject( lmRawPathId ) lmInductanceId = dbCreatePath( cellviewid layer1 pts lmIndWidth ) (cond ( assoc(layer1 lmLVSpairs) && techGetLayerNum(techGetTechFile(cellviewid) cadr(assoc(layer1 lmLVSpairs)) ; geGetEditCellView()->libName ) ;; the marking shape is wider by 1.0 lmIndMarkerId = dbCreatePath( cellviewid cadr(assoc(layer1 lmLVSpairs)) pts lmIndWidth + 1.0 ) leAttachFig( lmIndMarkerId lmInductanceId ) )) ; Commented out by Paul --- clone view does not work :( ; lmInductanceDRC(layer1 pts lmIndWidth) lmInductanceLabel() dbCreateProp(lmInductanceId "Ground is" "string" lmNumberOfGroundsValue) ) ) ; ** cond widthTooSmallp ** ) ; ** procedure ** lmPSCANUnitOfInd = 2.63 ; pH per PSCAN unit lmMinIndWidth = 3.00 ; um ;... lmFormula ................ Feb 25 95 sasha 33 (procedure lmFormula(Y d f n l) widthTooSmallp = nil alpha = mu0 * d beta = 2 * (Y * d - bulklambda - f) L = lmInductanceValue * lmPSCANUnitOfInd lmIndWidth = (alpha * l - L * beta) / ( L + alpha * n * 0.45 ) xSnap = hiGetCurrentWindow() -> xSnapSpacing ySnap = hiGetCurrentWindow() -> ySnapSpacing snap = max(xSnap ySnap) lmIndWidth = 2 * snap * round(lmIndWidth / (2 * snap)) (cond (lmIndWidth < lmMinIndWidth hiDisplayAppDBox( ?name 'lmWidthTooSmallBox ?dboxText "Width too small - reenter data " ); hiD..Box widthTooSmallp = t );lmIndWidth );cond ); procedure ;... lmTotalLength ............ Feb 25 95 sasha 503 (procedure lmTotalLength(pts) numpts = length(pts) numturns = numpts - 2 ltot = 0 ptscurlist = pts while( length(ptscurlist) >= 2 pa = car(ptscurlist) paX = car(pa) paY = cadr(pa) ptscurlist = cdr(ptscurlist) pb = car(ptscurlist) pbX = car(pb) pbY = cadr(pb) (cond (paX == pbX ltot = ltot + abs(paY - pbY)) (paY == pbY ltot = ltot + abs(paX - pbX)) );cond (cond (pa == pb numturns = numturns - 1) );cond );while );procedure ;... lmInductanceDRC .......... Oct 7 94 sasha 0 (procedure lmInductanceDRC(layer1 pts lmIndWidth) ;_Jan 14 00 paul 388 cellviewid = geGetEditCellView() thisLibName = cellviewid->libName thisCellName = cellviewid->cellName libid = thisLibName layoutViewId = ddGetObj(libid cellviewid->cellName "layout") (cond ( ddGetObj(libid cellviewid->cellName "layouttmp") == nil dbCopyCellView(layoutViewId thisLibName thisCellName "layouttmp" )) );cond tmpcellview = dbOpenCellView(thisLibName thisCellName "layouttmp" "" "a") dbCreatePath(tmpcellview layer1 pts lmIndWidth) dbSave(tmpcellview) ivDRC( ?cell tmpcellview ?full t ?set "drc?") dbClose(tmpcellview) ddDeleteObj(libid thisCellName "layouttmp") );procedure ;... lmInductanceLabel ........ Feb 25 95 sasha 0 (procedure lmInductanceLabel() lmActualInductanceValue = alpha * (ltot - 0.45 * numturns * lmIndWidth) / ((lmIndWidth + beta) * lmPSCANUnitOfInd) numpts = length(pts) nmiddle = round(numpts / 2) indlabelpoint = nthelem(nmiddle pts) indlabeltext = sprintf(dummy "L=%4.2f" lmActualInductanceValue) indLabelId = dbCreateLabel( cellviewid lmTextLayer indlabelpoint indlabeltext "centerLeft" "R0" lmInductanceLabelFont lmInductanceLabelSize ) leAttachFig( indLabelId lmInductanceId ) );procedure ;;;;;;;;deUnRegUserTriggers("maskLayout") ;;;################################################ ;;;# ;;;# Additional functions ;;;# ;;;################################################ hiSetBindKey("Layout" "Altq" "lmLSWPopUpDown()") (procedure lmLSWPopUpDown() (cond ( leIsLSWIconified() leDeiconifyLSW() ) ( t leIconifyLSW() hiRaiseWindow( hiGetCurrentWindow()) )) )