SKILL Corner generator

20 August 2019 Link



Understanding the GUI

  • On the title bar of the GUI you can directly see the version of the tool. This is useful to know if you encounter problems using the tool or if you want to report any bugs in the tool.
  • Below the title bar are 3 buttons
    • The 1st folder icon button is to open a saved configuration
    • The second disk icon button is to save the current configuration to disk
    • The third Info icon button is to get the basic About information of the tool

The GUI has 4 tabs.

Script Info


At the bottom is a Generate! button which generates the corners file and prompts you to save it.
This tab has the following entries:
  1. Run Name - This is the name by which this whole configuration is known. The physical significance is that this is the directory name where the results of all the runs will be saved
  2. ADE Script - This is the ADE Ocean script that you saved from your typical run. You cannot edit this field manually instead click the browse button to point to the right file.
  3. Corner Def - This is the Corners definition file for your process. YOu can either type the path to that file manually or point to it using the browse button.
  4. Results Dir - This is the path where you want the results directory to be created. The results directory by the name given in Run Name will be created on this path and each run results will be written in a sub-directory with the name cornerX where X is a sequential number starting from 1.
    NOTE: If the directory with the same name already exists the corner script will delete it without any warning, so be sure to rename it if you want to keep it.
  5. User Functions File - This is OPTIONAL field. This entry points to a script file with Lua code which has any functions that you may be using to generate variable values using the advanced call backs in the variable values.
  6. Run Code End Marker - By default it contains run(). The tool will pick code from the design("...") command up till this string and use it as it is in every corner run. Anything after this string will be considered to have measurement statements and variables will be extracted from the rest of the string. Normally you don't have to change it. This is useful if we modify the original ocean script to add some code to run the simulation multiple times to search for some value at every corner. For example I may replace the run() command with a for loop that sweeps the supply voltage from normal operation voltage down to 0V and run the simulation at every step and check when the circuit stops functioning. Something like this:
    1. cont = 1
    2. i = 1
    3. while(cont==1 and i<21
    4. vdd=5-i*0.25
    5. desVar("vdd" vdd)
    6. run()
    7. ;; Take measurement here
    8. x = nth(0 errset(cross(clip(VT("/Nand0/restore") 30e-6 31e-6) 1 1 "rising" t "time")))
    9. if(x == nil then ;; The previous one was the minimum voltage
    10. minV = vdd+0.25
    11. cont = 0
    12. )
    13. i = i + 1
    14. )
    15. ;; Now use minV to write in the results
    16.  
    17. ;; --- END MARKER
    Now here in this case I can replace the end marker from run() to ;; --- END MARKER and now my whole loop will be carried over in every corner and I will be able to get the minimum operating voltage of the circuit at every corner.
  7. Generation Log - This is the place where any errors etc. are displayed when the Generation is done.

Corners Info


This tab has the following entries:
  1. Sequence selection - This drop down list allows you to choose in which sequence you would like the corners to run. For example vars->cor->temp means that it will cycle all the temperatures, do this for each corner and then do this for each variable set given to it.
  2. Corners String - This is the string which specifies which process corners to run. It consists of a set of strings, each of same number of letters, each letter corresponding to the process definition file letters in the same sequence. This string can include '|' characters to improve readability. Those characters are ignored.
  3. Temperatures - Here you enter the temperatures you want to run the corners at. Each temperature is separated by a space.
  4. Variables - Here you enter the variable variations you want to enter. Each run uses the variable definitions specified here until it finds a semi colon (;). So each set of variables are separated by semi colons while multiple variable values for a single run are separated by a space as seen in the picture. Variable names can also be generated at run time by calling custom code if a custom code file was linked in the User Functions File entry in the Script Info tab. The code file should have lua functions written which need to be called. If a variable value is set as var=@myfunc then the script generator expects the function myfunc to be defined in the file. The program calls the function as:
       myfunc(varString,cornerString,tempString,runDAT,ADEscript)
    
    where:
    varstring is the variable name whose value is being requested passed as a string
    cornerString contains the string representing the process corner for which this run is called for example ttttttt
    tempString contains the temperature for which the run is called ecample -40.
    runDAT has corLetters, temperature string and variables all separated by spaces only for the current run. Sample runDat is:
    , "vsup=1.65 vi=0.4 iout=2.7286902286902e-005 ttttttt -40"
    ADEscript contains the full ADE input script from which the corner script is being generated
    The function returns one or more strings containing the variable values. If more than 1 value is returned then it generates runs for all values returned (NOTE: In this case it is like a variables are being sweeped for the same corner and temperature so it partially overrides the sequencing of the runs selection)
    If the variable runs have multiple functions returning multiple values then all permutation corners are created.
  5. Selective Runs - This box allows you to bypass the permutations of the corners generation and run the corners selectively. The image shows a good example how it is done. Pasted below is the same structure but with comments for better understanding:
    1. { -- This is the main table
    2. { -- Each table inside the main table corresponds to a run sequence
    3. -- corners can be a table with multiple corner strings or a single string
    4. corners = {"ttttttt","ffftfff"},
    5. -- temps can be a table with multiple temperature numbers or a single number
    6. temps = {-40, 27},
    7. -- vars can be a table with multiple variable chunks or a single variable chunk string
    8. vars = {"vsup=5.25 gt=5n","vsup=1.5 gt=10n" }
    9. },
    10. {
    11. corners = "sssssss",
    12. temps = 125,
    13. vars = "vsup=5.25 gt=3n"
    14. }
    15. }

Data Tab


This tab is where you select what measurements from your ADE script you want to see in a CSV file
This tab just has 2 lists. One on the left will not be in the CSV file while the one on the right will be on the CSV file. The order of the items can be changed by selecting the item(s) and pressing the UP/DN buttons.

CSV Tab


This tab allows you to condition the csv created by the corners script to include your measurement parameter names from the setup so that when you import the CSV into excel all the parameter names are already there and need not be typed again. (Saves a lot of time tracking the measurements!)
Just Browse for the output CSV file and click Transform to save the final csv.
NOTE: Newer versions of the tool does not have this tab since the CSV is conditioned automatically by the corner script

The whole flow

  1. Get your typical simulation running in ADE
  2. Go to Session->Save Ocean Script to save the ADE script in the local cds directory
  3. Copy this generated .ocn file to the machine where you have this tool available.
  4. Point to this script on this tool
  5. Setup all the entries if this is the 1st time you are setting up the test bench corners or just load a previous saved state.
  6. Make sure you have all the measurements you need in a spreadsheet on the right column in the Data Tab.
  7. Hit the Generate! button and save the generated .ocn file
  8. If any Errors/Warnings resolve them accordingly.
  9. Copy the ocn file back to your cds directory
  10. Run the script (Myscript.ocn) by typing load("Myscript.ocn") in the icfb window

Now it will run all the corners. Once the corner runs have completed there would be a data.csv file in the results directory (directory with the same name as Run Name at path Results Dir)
  1. Copy the csv file to the machine you have this tool on.
  2. Point to this CSV in the CSV tab and click the Transform button to save the final CSV which can be imported in Excel.
  3. To import in Excel go to Excel's Data tab and click From text button. Then press next and select comma as the delimiter and then do Finish and OK to get the result table in Excel.

Knowing your generated Corner File

The generated corner file looks something like this:
  1. simulator( 'spectre )
  2.  
  3. system(sprintf(nil "rm -rf /camsim/gupta/TB_DELAY"))
  4. system(sprintf(nil "mkdir /camsim/gupta/TB_DELAY"))
  5. system(sprintf(nil "cp -r /n/bsim/gupta/simulation/TB_delay/spectre/schematic/netlist /camsim/gupta/TB_DELAY"))
  6. design( "/camsim/gupta/TB_DELAY/netlist/netlist")
  7. runTimes=list(0) ;; To store the run time of each corner
  8.  
  9. ;; -- CORNER 1
  10. system(sprintf(nil "mkdir /camsim/gupta/TB_DELAY/corner1"))
  11. startTime=getCurrentTime()
  12. resultsDir( "/camsim/gupta/TB_DELAY/corner1")
  13. modelFile(
  14. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "lv_mos_cap_tt" )
  15. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "mv_hv_fet_tt" )
  16. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rnnet_typ" )
  17. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rnw_typ" )
  18. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rpolyhr_typ" )
  19. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rppoly_typ" )
  20. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rpbur_typ" )
  21. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rptop_typ" )
  22. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rptopf_typ" )
  23. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "metcap_typ" )
  24. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "bip_typ" )
  25. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "jfet_typ" )
  26. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "dio_typ" )
  27. '( "/d0/spectre_model/vts/models_vts12_release.scs" "tt" )
  28. )
  29. analysis('tran ?stop "80u" ?errpreset "conservative" ?infotimes list("50u" "50.5u") )
  30. desVar( "vdd" "5" )
  31. envOption(
  32. 'analysisOrder list("tran")
  33. )
  34. option( 'additionalArgs "inlinesubcktcurrent=subckt"
  35. 'temp "-40"
  36. )
  37. save( 'i "/I2/MP0/S" "/I2/Q0/C" "/I2/Q0/E" "/I2/MP0/D" "/I2/I31/A" "/I2/MP7/S" "/I2/MP2/S" "/I2/MP1/S" "/I2/vdda" "/I2/vssa" )
  38. temp( -40 )
  39. run()
  40. endTime=getCurrentTime()
  41. runTimes=append(runTimes list(compareTime(endTime startTime)))
  42.  
  43. .......
  44. .......
  45. .......
  46.  
  47. ;; -- CORNER 255
  48. system(sprintf(nil "mkdir /camsim/gupta/TB_DELAY/corner255"))
  49. startTime=getCurrentTime()
  50. resultsDir( "/camsim/gupta/TB_DELAY/corner255")
  51. modelFile(
  52. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "lv_mos_cap_fs" )
  53. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "mv_hv_fet_fs" )
  54. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rnnet_fast" )
  55. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rnw_fast" )
  56. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rpolyhr_fast" )
  57. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rppoly_fast" )
  58. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rpbur_fast" )
  59. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rptop_fast" )
  60. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "rptopf_fast" )
  61. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "metcap_fast" )
  62. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "bip_fast" )
  63. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "jfet_typ" )
  64. '( "/d0/spectre_model/dx2.0/dx2.0_corners.scs" "dio_typ" )
  65. '( "/d0/spectre_model/vts/models_vts12_release.scs" "tt" )
  66. )
  67. analysis('tran ?stop "80u" ?errpreset "conservative" ?infotimes list("50u" "50.5u") )
  68. desVar( "vdd" "5.2" )
  69. envOption(
  70. 'analysisOrder list("tran")
  71. )
  72. option( 'additionalArgs "inlinesubcktcurrent=subckt"
  73. 'temp "125"
  74. )
  75. save( 'i "/I2/MP0/S" "/I2/Q0/C" "/I2/Q0/E" "/I2/MP0/D" "/I2/I31/A" "/I2/MP7/S" "/I2/MP2/S" "/I2/MP1/S" "/I2/vdda" "/I2/vssa" )
  76. temp( 125 )
  77. run()
  78. endTime=getCurrentTime()
  79. runTimes=append(runTimes list(compareTime(endTime startTime)))
  80.  
  81. __foutSTR = ""
  82. for(i 1 length(runTimes)-1
  83. sprintf(__foutSTR "%s\n%d" __foutSTR nth(i runTimes))
  84. )
  85. fileHandle = outfile("/camsim/gupta/TB_DELAY/runTimes.txt" "w")
  86. fprintf(fileHandle "%s" __foutSTR)
  87. close(fileHandle)
  88. ;;---MEASUREMENT EXTRACTION
  89.  
  90.  
  91. runData=list("Variable,Corner,Temp,Run Times,Fall_Delay,IGND_INHI,IGND_INLO,RAMP_AT_CROSS", "vdd=5,ttttttttttt,-40", "vdd=5,ttttttttttt,0", "vdd=5,ttttttttttt,27", "vdd=5,ttttttttttt,80", "vdd=5,ttttttttttt,125", "vdd=5,ssssssstttt,-40", "vdd=5,ssssssstttt,0", "vdd=5,ssssssstttt,27", "vdd=5,ssssssstttt,80", "vdd=5,ssssssstttt,125", "vdd=5,ssssffstttt,-40", "vdd=5,ssssffstttt,0", "vdd=5,ssssffstttt,27", "vdd=5,ssssffstttt,80", "vdd=5,ssssffstttt,125", "vdd=5,ssssssftttt,-40", "vdd=5,ssssssftttt,0", "vdd=5,ssssssftttt,27", "vdd=5,ssssssftttt,80", "vdd=5,ssssssftttt,125", "vdd=5,ssssffftttt,-40", "vdd=5,ssssffftttt,0", "vdd=5,ssssffftttt,27", "vdd=5,ssssffftttt,80", "vdd=5,ssssffftttt,125", "vdd=5,ffffssstttt,-40", "vdd=5,ffffssstttt,0", "vdd=5,ffffssstttt,27", "vdd=5,ffffssstttt,80", "vdd=5,ffffssstttt,125", "vdd=5,ffffffstttt,-40", "vdd=5,ffffffstttt,0", "vdd=5,ffffffstttt,27", "vdd=5,ffffffstttt,80", "vdd=5,ffffffstttt,125", "vdd=5,ffffssftttt,-40", "vdd=5,ffffssftttt,0", "vdd=5,ffffssftttt,27", "vdd=5,ffffssftttt,80", "vdd=5,ffffssftttt,125", "vdd=5,ffffffftttt,-40", "vdd=5,ffffffftttt,0", "vdd=5,ffffffftttt,27", "vdd=5,ffffffftttt,80", "vdd=5,ffffffftttt,125", "vdd=5,sfsfssstttt,-40", "vdd=5,sfsfssstttt,0", "vdd=5,sfsfssstttt,27", "vdd=5,sfsfssstttt,80", "vdd=5,sfsfssstttt,125", "vdd=5,sfsfffstttt,-40", "vdd=5,sfsfffstttt,0", "vdd=5,sfsfffstttt,27", "vdd=5,sfsfffstttt,80", "vdd=5,sfsfffstttt,125", "vdd=5,sfsfssftttt,-40", "vdd=5,sfsfssftttt,0", "vdd=5,sfsfssftttt,27", "vdd=5,sfsfssftttt,80", "vdd=5,sfsfssftttt,125", "vdd=5,sfsfffftttt,-40", "vdd=5,sfsfffftttt,0", "vdd=5,sfsfffftttt,27", "vdd=5,sfsfffftttt,80", "vdd=5,sfsfffftttt,125", "vdd=5,fsfsssstttt,-40", "vdd=5,fsfsssstttt,0", "vdd=5,fsfsssstttt,27", "vdd=5,fsfsssstttt,80", "vdd=5,fsfsssstttt,125", "vdd=5,fsfsffstttt,-40", "vdd=5,fsfsffstttt,0", "vdd=5,fsfsffstttt,27", "vdd=5,fsfsffstttt,80", "vdd=5,fsfsffstttt,125", "vdd=5,fsfsssftttt,-40", "vdd=5,fsfsssftttt,0", "vdd=5,fsfsssftttt,27", "vdd=5,fsfsssftttt,80", "vdd=5,fsfsssftttt,125", "vdd=5,fsfsffftttt,-40", "vdd=5,fsfsffftttt,0", "vdd=5,fsfsffftttt,27", "vdd=5,fsfsffftttt,80", "vdd=5,fsfsffftttt,125", "vdd=4.7,ttttttttttt,-40", "vdd=4.7,ttttttttttt,0", "vdd=4.7,ttttttttttt,27", "vdd=4.7,ttttttttttt,80", "vdd=4.7,ttttttttttt,125", "vdd=4.7,ssssssstttt,-40", "vdd=4.7,ssssssstttt,0", "vdd=4.7,ssssssstttt,27", "vdd=4.7,ssssssstttt,80", "vdd=4.7,ssssssstttt,125", "vdd=4.7,ssssffstttt,-40", "vdd=4.7,ssssffstttt,0", "vdd=4.7,ssssffstttt,27", "vdd=4.7,ssssffstttt,80", "vdd=4.7,ssssffstttt,125", "vdd=4.7,ssssssftttt,-40", "vdd=4.7,ssssssftttt,0", "vdd=4.7,ssssssftttt,27", "vdd=4.7,ssssssftttt,80", "vdd=4.7,ssssssftttt,125", "vdd=4.7,ssssffftttt,-40", "vdd=4.7,ssssffftttt,0", "vdd=4.7,ssssffftttt,27", "vdd=4.7,ssssffftttt,80", "vdd=4.7,ssssffftttt,125", "vdd=4.7,ffffssstttt,-40", "vdd=4.7,ffffssstttt,0", "vdd=4.7,ffffssstttt,27", "vdd=4.7,ffffssstttt,80", "vdd=4.7,ffffssstttt,125", "vdd=4.7,ffffffstttt,-40", "vdd=4.7,ffffffstttt,0", "vdd=4.7,ffffffstttt,27", "vdd=4.7,ffffffstttt,80", "vdd=4.7,ffffffstttt,125", "vdd=4.7,ffffssftttt,-40", "vdd=4.7,ffffssftttt,0", "vdd=4.7,ffffssftttt,27", "vdd=4.7,ffffssftttt,80", "vdd=4.7,ffffssftttt,125", "vdd=4.7,ffffffftttt,-40", "vdd=4.7,ffffffftttt,0", "vdd=4.7,ffffffftttt,27", "vdd=4.7,ffffffftttt,80", "vdd=4.7,ffffffftttt,125", "vdd=4.7,sfsfssstttt,-40", "vdd=4.7,sfsfssstttt,0", "vdd=4.7,sfsfssstttt,27", "vdd=4.7,sfsfssstttt,80", "vdd=4.7,sfsfssstttt,125", "vdd=4.7,sfsfffstttt,-40", "vdd=4.7,sfsfffstttt,0", "vdd=4.7,sfsfffstttt,27", "vdd=4.7,sfsfffstttt,80", "vdd=4.7,sfsfffstttt,125", "vdd=4.7,sfsfssftttt,-40", "vdd=4.7,sfsfssftttt,0", "vdd=4.7,sfsfssftttt,27", "vdd=4.7,sfsfssftttt,80", "vdd=4.7,sfsfssftttt,125", "vdd=4.7,sfsfffftttt,-40", "vdd=4.7,sfsfffftttt,0", "vdd=4.7,sfsfffftttt,27", "vdd=4.7,sfsfffftttt,80", "vdd=4.7,sfsfffftttt,125", "vdd=4.7,fsfsssstttt,-40", "vdd=4.7,fsfsssstttt,0", "vdd=4.7,fsfsssstttt,27", "vdd=4.7,fsfsssstttt,80", "vdd=4.7,fsfsssstttt,125", "vdd=4.7,fsfsffstttt,-40", "vdd=4.7,fsfsffstttt,0", "vdd=4.7,fsfsffstttt,27", "vdd=4.7,fsfsffstttt,80", "vdd=4.7,fsfsffstttt,125", "vdd=4.7,fsfsssftttt,-40", "vdd=4.7,fsfsssftttt,0", "vdd=4.7,fsfsssftttt,27", "vdd=4.7,fsfsssftttt,80", "vdd=4.7,fsfsssftttt,125", "vdd=4.7,fsfsffftttt,-40", "vdd=4.7,fsfsffftttt,0", "vdd=4.7,fsfsffftttt,27", "vdd=4.7,fsfsffftttt,80", "vdd=4.7,fsfsffftttt,125", "vdd=5.2,ttttttttttt,-40", "vdd=5.2,ttttttttttt,0", "vdd=5.2,ttttttttttt,27", "vdd=5.2,ttttttttttt,80", "vdd=5.2,ttttttttttt,125", "vdd=5.2,ssssssstttt,-40", "vdd=5.2,ssssssstttt,0", "vdd=5.2,ssssssstttt,27", "vdd=5.2,ssssssstttt,80", "vdd=5.2,ssssssstttt,125", "vdd=5.2,ssssffstttt,-40", "vdd=5.2,ssssffstttt,0", "vdd=5.2,ssssffstttt,27", "vdd=5.2,ssssffstttt,80", "vdd=5.2,ssssffstttt,125", "vdd=5.2,ssssssftttt,-40", "vdd=5.2,ssssssftttt,0", "vdd=5.2,ssssssftttt,27", "vdd=5.2,ssssssftttt,80", "vdd=5.2,ssssssftttt,125", "vdd=5.2,ssssffftttt,-40", "vdd=5.2,ssssffftttt,0", "vdd=5.2,ssssffftttt,27", "vdd=5.2,ssssffftttt,80", "vdd=5.2,ssssffftttt,125", "vdd=5.2,ffffssstttt,-40", "vdd=5.2,ffffssstttt,0", "vdd=5.2,ffffssstttt,27", "vdd=5.2,ffffssstttt,80", "vdd=5.2,ffffssstttt,125", "vdd=5.2,ffffffstttt,-40", "vdd=5.2,ffffffstttt,0", "vdd=5.2,ffffffstttt,27", "vdd=5.2,ffffffstttt,80", "vdd=5.2,ffffffstttt,125", "vdd=5.2,ffffssftttt,-40", "vdd=5.2,ffffssftttt,0", "vdd=5.2,ffffssftttt,27", "vdd=5.2,ffffssftttt,80", "vdd=5.2,ffffssftttt,125", "vdd=5.2,ffffffftttt,-40", "vdd=5.2,ffffffftttt,0", "vdd=5.2,ffffffftttt,27", "vdd=5.2,ffffffftttt,80", "vdd=5.2,ffffffftttt,125", "vdd=5.2,sfsfssstttt,-40", "vdd=5.2,sfsfssstttt,0", "vdd=5.2,sfsfssstttt,27", "vdd=5.2,sfsfssstttt,80", "vdd=5.2,sfsfssstttt,125", "vdd=5.2,sfsfffstttt,-40", "vdd=5.2,sfsfffstttt,0", "vdd=5.2,sfsfffstttt,27", "vdd=5.2,sfsfffstttt,80", "vdd=5.2,sfsfffstttt,125", "vdd=5.2,sfsfssftttt,-40", "vdd=5.2,sfsfssftttt,0", "vdd=5.2,sfsfssftttt,27", "vdd=5.2,sfsfssftttt,80", "vdd=5.2,sfsfssftttt,125", "vdd=5.2,sfsfffftttt,-40", "vdd=5.2,sfsfffftttt,0", "vdd=5.2,sfsfffftttt,27", "vdd=5.2,sfsfffftttt,80", "vdd=5.2,sfsfffftttt,125", "vdd=5.2,fsfsssstttt,-40", "vdd=5.2,fsfsssstttt,0", "vdd=5.2,fsfsssstttt,27", "vdd=5.2,fsfsssstttt,80", "vdd=5.2,fsfsssstttt,125", "vdd=5.2,fsfsffstttt,-40", "vdd=5.2,fsfsffstttt,0", "vdd=5.2,fsfsffstttt,27", "vdd=5.2,fsfsffstttt,80", "vdd=5.2,fsfsffstttt,125", "vdd=5.2,fsfsssftttt,-40", "vdd=5.2,fsfsssftttt,0", "vdd=5.2,fsfsssftttt,27", "vdd=5.2,fsfsssftttt,80", "vdd=5.2,fsfsssftttt,125", "vdd=5.2,fsfsffftttt,-40", "vdd=5.2,fsfsffftttt,0", "vdd=5.2,fsfsffftttt,27", "vdd=5.2,fsfsffftttt,80", "vdd=5.2,fsfsffftttt,125")
  92. fileHandle=infile("/camsim/gupta/TB_DELAY/runTimes.txt")
  93. runTimes = list(0)
  94. while(fscanf(fileHandle "%s" time)
  95. runTimes = append(runTimes list(time))
  96. )
  97. close(fileHandle)
  98. procedure( writeFile()
  99. fileHandle = outfile("/camsim/gupta/TB_DELAY/data.csv" "w")
  100. fprintf(fileHandle "%s" __foutSTR)
  101. close(fileHandle)
  102. )
  103. ;; Use cW instead of currentWindow to have optimized graphics performance
  104. procedure( cW(wid)
  105. currentWindow(wid)
  106. graphicsOff()
  107. )
  108.  
  109. __foutSTR = nth(0,runData)
  110. for(i 1 255
  111. graphicsOff()
  112. sprintf(corDir "%s%d/psf" "/camsim/gupta/TB_DELAY/corner" i)
  113. openResults(corDir )
  114.  
  115. selectResult( 'tran )
  116.  
  117. IGND_INHI = nth(0 errset(value((- IT("/I2/vssa")) 5e-05)))
  118.  
  119. if(IGND_INHI==nil then IGND_INHI=9999e9999 printf("\nIGND_INHI is nil in corner %d",i) )
  120. RAMP_AT_CROSS = nth(0 errset(value(VT("/I2/ramp") cross(clip((IT("/I2/MP2/S") - (0.98 * value(IT("/I2/MP1/S") cross(clip(VT("/OUT") 6e-05 8e-05) (VAR("vdd") / 2) 2 "falling" nil nil)))) root(clip(VT("/IN") 6e-05 cross(clip(VT("/OUT") 6e-05 8e-05) (VAR("vdd") / 2) 2 "falling" nil nil)) (VAR("vdd") / 2) -1) cross(clip(VT("/OUT") 6e-05 8e-05) (VAR("vdd") / 2) 2 "falling" nil nil)) 0 1 "rising" nil nil))))
  121.  
  122. if(RAMP_AT_CROSS==nil then RAMP_AT_CROSS=9999e9999 printf("\nRAMP_AT_CROSS is nil in corner %d",i) )
  123. IGND_INLO = nth(0 errset(value((- IT("/I2/vssa")) 5.05e-05)))
  124.  
  125. if(IGND_INLO==nil then IGND_INLO=9999e9999 printf("\nIGND_INLO is nil in corner %d",i) )
  126. Fall_Delay = nth(0 errset((cross(clip(VT("/OUT") 6e-05 8e-05) (VAR("vdd") / 2) 2 "falling" nil nil) - root(clip(VT("/IN") 6e-05 cross(clip(VT("/OUT") 6e-05 8e-05) (VAR("vdd") / 2) 2 "falling" nil nil)) (VAR("vdd") / 2) -1))))
  127.  
  128. if(Fall_Delay==nil then Fall_Delay=9999e9999 printf("\nFall_Delay is nil in corner %d",i) )
  129.  
  130. ;;-- Plot Statements
  131.  
  132. plot(getData("/IN") )
  133.  
  134. sprintf(__foutSTR "%s\n%s,%s,%e,%e,%e,%e" __foutSTR nth(i,runData) nth(i runTimes) float(Fall_Delay) float(IGND_INHI) float(IGND_INLO) float(RAMP_AT_CROSS) )
  135.  
  136. if(i==255 then
  137. writeFile()
  138. )
  139. ) ;; for i ends here
  140. ;; Now to turn Graphics ON for all existing windows
  141. foreach(wid awvGetWindowList()
  142. currentWindow(wid)
  143. graphicsOn()
  144. )


So each corner run is separated and is sequential. In the end after the line ;;---MEASUREMENT EXTRACTION Is all the SKILL code to extract the measurements from all the run Data. You may find it useful to familiarize with the Measurement extraction section since sometimes by running just that part with tweaks can give you a whole lot of data about the simulations. I can help with that if anyone is interested.

Creating a corner definition file

This is best understood by looking at an example file:
  1. corners =
  2. {
  3. -- All 1.8V MOS devices
  4. {
  5. {
  6. "tt",
  7. {
  8. {file,"tt_svt018"},
  9. {file,"tt_hvt018"},
  10. {file,"tt_lvt018"}
  11. }
  12. },
  13. {
  14. "ss",
  15. {
  16. {file,"ss_svt018"},
  17. {file,"ss_hvt018"},
  18. {file,"ss_lvt018"}
  19. }
  20. },
  21. {
  22. "ff",
  23. {
  24. {file,"ff_svt018"},
  25. {file,"ff_hvt018"},
  26. {file,"ff_lvt018"}
  27. }
  28. },
  29. },
  30. -- 5.0V Standard VT CMOS Devices Lib.
  31. {
  32. {
  33. "tt",
  34. {
  35. {file,"tt_svt050"},
  36. {file,"tt_lvt050"}
  37. }
  38. },
  39. {
  40. "ss",
  41. {
  42. {file,"ss_svt050"},
  43. {file,"ss_lvt050"}
  44. }
  45. },
  46. {
  47. "ff",
  48. {
  49. {file,"ff_svt050"},
  50. {file,"ff_lvt050"}
  51. }
  52. },
  53. }
  54. }
  55. includeFiles =
  56. {
  57. {file,"tt_eecel"},
  58. {file,"tt_ecel"}
  59. }


As can be seen the file has 2 variables: corners and includeFiles. In all the above file is to be replaced by the process model file and the optional string following it like tt_eecel needs to be set to the section from the file that needs to be included.
corners is defined by tabulating the corner strings that will be placed in the GUI to map them to what files need to be placed in the corner ocean script when that string is encountered. So for example when the corner string is ssff then the oceanscript will have the following files and sections:
file,"ss_svt018"
file,"ss_hvt018"
file,"ss_lvt018"
file,"ff_svt050"
file,"ff_lvt050"
file,"tt_eecel"
file,"tt_ecel"

Note that the files in the includeFiles variable section are always included irrespective of the corner. includeFiles is optional and may not have any files in it.

Advanced plotting

The plotting and results saving section of the script looks something like:
  1. ;;---MEASUREMENT EXTRACTION
  2.  
  3.  
  4. runData=list("Variable,Corner,Temp,Run Times,Fall_Delay,IGND_INHI,IGND_INLO,RAMP_AT_CROSS", "vdd=5,ttttttttttt,-40", "vdd=5,ttttttttttt,0", "vdd=5,ttttttttttt,27", "vdd=5,ttttttttttt,80", "vdd=5,ttttttttttt,125", "vdd=5,ssssssstttt,-40", "vdd=5,ssssssstttt,0", "vdd=5,ssssssstttt,27", "vdd=5,ssssssstttt,80", "vdd=5,ssssssstttt,125", "vdd=5,ssssffstttt,-40", "vdd=5,ssssffstttt,0", "vdd=5,ssssffstttt,27", "vdd=5,ssssffstttt,80", "vdd=5,ssssffstttt,125", "vdd=5,ssssssftttt,-40", "vdd=5,ssssssftttt,0", "vdd=5,ssssssftttt,27", "vdd=5,ssssssftttt,80", "vdd=5,ssssssftttt,125", "vdd=5,ssssffftttt,-40", "vdd=5,ssssffftttt,0", "vdd=5,ssssffftttt,27", "vdd=5,ssssffftttt,80", "vdd=5,ssssffftttt,125", "vdd=5,ffffssstttt,-40", "vdd=5,ffffssstttt,0", "vdd=5,ffffssstttt,27", "vdd=5,ffffssstttt,80", "vdd=5,ffffssstttt,125", "vdd=5,ffffffstttt,-40", "vdd=5,ffffffstttt,0", "vdd=5,ffffffstttt,27", "vdd=5,ffffffstttt,80", "vdd=5,ffffffstttt,125", "vdd=5,ffffssftttt,-40", "vdd=5,ffffssftttt,0", "vdd=5,ffffssftttt,27", "vdd=5,ffffssftttt,80", "vdd=5,ffffssftttt,125", "vdd=5,ffffffftttt,-40", "vdd=5,ffffffftttt,0", "vdd=5,ffffffftttt,27", "vdd=5,ffffffftttt,80", "vdd=5,ffffffftttt,125", "vdd=5,sfsfssstttt,-40", "vdd=5,sfsfssstttt,0", "vdd=5,sfsfssstttt,27", "vdd=5,sfsfssstttt,80", "vdd=5,sfsfssstttt,125", "vdd=5,sfsfffstttt,-40", "vdd=5,sfsfffstttt,0", "vdd=5,sfsfffstttt,27", "vdd=5,sfsfffstttt,80", "vdd=5,sfsfffstttt,125", "vdd=5,sfsfssftttt,-40", "vdd=5,sfsfssftttt,0", "vdd=5,sfsfssftttt,27", "vdd=5,sfsfssftttt,80", "vdd=5,sfsfssftttt,125", "vdd=5,sfsfffftttt,-40", "vdd=5,sfsfffftttt,0", "vdd=5,sfsfffftttt,27", "vdd=5,sfsfffftttt,80", "vdd=5,sfsfffftttt,125", "vdd=5,fsfsssstttt,-40", "vdd=5,fsfsssstttt,0", "vdd=5,fsfsssstttt,27", "vdd=5,fsfsssstttt,80", "vdd=5,fsfsssstttt,125", "vdd=5,fsfsffstttt,-40", "vdd=5,fsfsffstttt,0", "vdd=5,fsfsffstttt,27", "vdd=5,fsfsffstttt,80", "vdd=5,fsfsffstttt,125", "vdd=5,fsfsssftttt,-40", "vdd=5,fsfsssftttt,0", "vdd=5,fsfsssftttt,27", "vdd=5,fsfsssftttt,80", "vdd=5,fsfsssftttt,125", "vdd=5,fsfsffftttt,-40", "vdd=5,fsfsffftttt,0", "vdd=5,fsfsffftttt,27", "vdd=5,fsfsffftttt,80", "vdd=5,fsfsffftttt,125", "vdd=4.7,ttttttttttt,-40", "vdd=4.7,ttttttttttt,0", "vdd=4.7,ttttttttttt,27", "vdd=4.7,ttttttttttt,80", "vdd=4.7,ttttttttttt,125", "vdd=4.7,ssssssstttt,-40", "vdd=4.7,ssssssstttt,0", "vdd=4.7,ssssssstttt,27", "vdd=4.7,ssssssstttt,80", "vdd=4.7,ssssssstttt,125", "vdd=4.7,ssssffstttt,-40", "vdd=4.7,ssssffstttt,0", "vdd=4.7,ssssffstttt,27", "vdd=4.7,ssssffstttt,80", "vdd=4.7,ssssffstttt,125", "vdd=4.7,ssssssftttt,-40", "vdd=4.7,ssssssftttt,0", "vdd=4.7,ssssssftttt,27", "vdd=4.7,ssssssftttt,80", "vdd=4.7,ssssssftttt,125", "vdd=4.7,ssssffftttt,-40", "vdd=4.7,ssssffftttt,0", "vdd=4.7,ssssffftttt,27", "vdd=4.7,ssssffftttt,80", "vdd=4.7,ssssffftttt,125", "vdd=4.7,ffffssstttt,-40", "vdd=4.7,ffffssstttt,0", "vdd=4.7,ffffssstttt,27", "vdd=4.7,ffffssstttt,80", "vdd=4.7,ffffssstttt,125", "vdd=4.7,ffffffstttt,-40", "vdd=4.7,ffffffstttt,0", "vdd=4.7,ffffffstttt,27", "vdd=4.7,ffffffstttt,80", "vdd=4.7,ffffffstttt,125", "vdd=4.7,ffffssftttt,-40", "vdd=4.7,ffffssftttt,0", "vdd=4.7,ffffssftttt,27", "vdd=4.7,ffffssftttt,80", "vdd=4.7,ffffssftttt,125", "vdd=4.7,ffffffftttt,-40", "vdd=4.7,ffffffftttt,0", "vdd=4.7,ffffffftttt,27", "vdd=4.7,ffffffftttt,80", "vdd=4.7,ffffffftttt,125", "vdd=4.7,sfsfssstttt,-40", "vdd=4.7,sfsfssstttt,0", "vdd=4.7,sfsfssstttt,27", "vdd=4.7,sfsfssstttt,80", "vdd=4.7,sfsfssstttt,125", "vdd=4.7,sfsfffstttt,-40", "vdd=4.7,sfsfffstttt,0", "vdd=4.7,sfsfffstttt,27", "vdd=4.7,sfsfffstttt,80", "vdd=4.7,sfsfffstttt,125", "vdd=4.7,sfsfssftttt,-40", "vdd=4.7,sfsfssftttt,0", "vdd=4.7,sfsfssftttt,27", "vdd=4.7,sfsfssftttt,80", "vdd=4.7,sfsfssftttt,125", "vdd=4.7,sfsfffftttt,-40", "vdd=4.7,sfsfffftttt,0", "vdd=4.7,sfsfffftttt,27", "vdd=4.7,sfsfffftttt,80", "vdd=4.7,sfsfffftttt,125", "vdd=4.7,fsfsssstttt,-40", "vdd=4.7,fsfsssstttt,0", "vdd=4.7,fsfsssstttt,27", "vdd=4.7,fsfsssstttt,80", "vdd=4.7,fsfsssstttt,125", "vdd=4.7,fsfsffstttt,-40", "vdd=4.7,fsfsffstttt,0", "vdd=4.7,fsfsffstttt,27", "vdd=4.7,fsfsffstttt,80", "vdd=4.7,fsfsffstttt,125", "vdd=4.7,fsfsssftttt,-40", "vdd=4.7,fsfsssftttt,0", "vdd=4.7,fsfsssftttt,27", "vdd=4.7,fsfsssftttt,80", "vdd=4.7,fsfsssftttt,125", "vdd=4.7,fsfsffftttt,-40", "vdd=4.7,fsfsffftttt,0", "vdd=4.7,fsfsffftttt,27", "vdd=4.7,fsfsffftttt,80", "vdd=4.7,fsfsffftttt,125", "vdd=5.2,ttttttttttt,-40", "vdd=5.2,ttttttttttt,0", "vdd=5.2,ttttttttttt,27", "vdd=5.2,ttttttttttt,80", "vdd=5.2,ttttttttttt,125", "vdd=5.2,ssssssstttt,-40", "vdd=5.2,ssssssstttt,0", "vdd=5.2,ssssssstttt,27", "vdd=5.2,ssssssstttt,80", "vdd=5.2,ssssssstttt,125", "vdd=5.2,ssssffstttt,-40", "vdd=5.2,ssssffstttt,0", "vdd=5.2,ssssffstttt,27", "vdd=5.2,ssssffstttt,80", "vdd=5.2,ssssffstttt,125", "vdd=5.2,ssssssftttt,-40", "vdd=5.2,ssssssftttt,0", "vdd=5.2,ssssssftttt,27", "vdd=5.2,ssssssftttt,80", "vdd=5.2,ssssssftttt,125", "vdd=5.2,ssssffftttt,-40", "vdd=5.2,ssssffftttt,0", "vdd=5.2,ssssffftttt,27", "vdd=5.2,ssssffftttt,80", "vdd=5.2,ssssffftttt,125", "vdd=5.2,ffffssstttt,-40", "vdd=5.2,ffffssstttt,0", "vdd=5.2,ffffssstttt,27", "vdd=5.2,ffffssstttt,80", "vdd=5.2,ffffssstttt,125", "vdd=5.2,ffffffstttt,-40", "vdd=5.2,ffffffstttt,0", "vdd=5.2,ffffffstttt,27", "vdd=5.2,ffffffstttt,80", "vdd=5.2,ffffffstttt,125", "vdd=5.2,ffffssftttt,-40", "vdd=5.2,ffffssftttt,0", "vdd=5.2,ffffssftttt,27", "vdd=5.2,ffffssftttt,80", "vdd=5.2,ffffssftttt,125", "vdd=5.2,ffffffftttt,-40", "vdd=5.2,ffffffftttt,0", "vdd=5.2,ffffffftttt,27", "vdd=5.2,ffffffftttt,80", "vdd=5.2,ffffffftttt,125", "vdd=5.2,sfsfssstttt,-40", "vdd=5.2,sfsfssstttt,0", "vdd=5.2,sfsfssstttt,27", "vdd=5.2,sfsfssstttt,80", "vdd=5.2,sfsfssstttt,125", "vdd=5.2,sfsfffstttt,-40", "vdd=5.2,sfsfffstttt,0", "vdd=5.2,sfsfffstttt,27", "vdd=5.2,sfsfffstttt,80", "vdd=5.2,sfsfffstttt,125", "vdd=5.2,sfsfssftttt,-40", "vdd=5.2,sfsfssftttt,0", "vdd=5.2,sfsfssftttt,27", "vdd=5.2,sfsfssftttt,80", "vdd=5.2,sfsfssftttt,125", "vdd=5.2,sfsfffftttt,-40", "vdd=5.2,sfsfffftttt,0", "vdd=5.2,sfsfffftttt,27", "vdd=5.2,sfsfffftttt,80", "vdd=5.2,sfsfffftttt,125", "vdd=5.2,fsfsssstttt,-40", "vdd=5.2,fsfsssstttt,0", "vdd=5.2,fsfsssstttt,27", "vdd=5.2,fsfsssstttt,80", "vdd=5.2,fsfsssstttt,125", "vdd=5.2,fsfsffstttt,-40", "vdd=5.2,fsfsffstttt,0", "vdd=5.2,fsfsffstttt,27", "vdd=5.2,fsfsffstttt,80", "vdd=5.2,fsfsffstttt,125", "vdd=5.2,fsfsssftttt,-40", "vdd=5.2,fsfsssftttt,0", "vdd=5.2,fsfsssftttt,27", "vdd=5.2,fsfsssftttt,80", "vdd=5.2,fsfsssftttt,125", "vdd=5.2,fsfsffftttt,-40", "vdd=5.2,fsfsffftttt,0", "vdd=5.2,fsfsffftttt,27", "vdd=5.2,fsfsffftttt,80", "vdd=5.2,fsfsffftttt,125")
  5. fileHandle=infile("/camsim/gupta/TB_DELAY/runTimes.txt")
  6. runTimes = list(0)
  7. while(fscanf(fileHandle "%s" time)
  8. runTimes = append(runTimes list(time))
  9. )
  10. close(fileHandle)
  11. procedure( writeFile()
  12. fileHandle = outfile("/camsim/gupta/TB_DELAY/data.csv" "w")
  13. fprintf(fileHandle "%s" __foutSTR)
  14. close(fileHandle)
  15. )
  16. ;; Use cW instead of currentWindow to have optimized graphics performance
  17. procedure( cW(wid)
  18. currentWindow(wid)
  19. graphicsOff()
  20. )
  21.  
  22. __foutSTR = nth(0,runData)
  23. for(i 1 255
  24. graphicsOff()
  25. sprintf(corDir "%s%d/psf" "/camsim/gupta/TB_DELAY/corner" i)
  26. openResults(corDir )
  27.  
  28. selectResult( 'tran )
  29.  
  30. IGND_INHI = nth(0 errset(value((- IT("/I2/vssa")) 5e-05)))
  31.  
  32. if(IGND_INHI==nil then IGND_INHI=9999e9999 printf("\nIGND_INHI is nil in corner %d",i) )
  33. RAMP_AT_CROSS = nth(0 errset(value(VT("/I2/ramp") cross(clip((IT("/I2/MP2/S") - (0.98 * value(IT("/I2/MP1/S") cross(clip(VT("/OUT") 6e-05 8e-05) (VAR("vdd") / 2) 2 "falling" nil nil)))) root(clip(VT("/IN") 6e-05 cross(clip(VT("/OUT") 6e-05 8e-05) (VAR("vdd") / 2) 2 "falling" nil nil)) (VAR("vdd") / 2) -1) cross(clip(VT("/OUT") 6e-05 8e-05) (VAR("vdd") / 2) 2 "falling" nil nil)) 0 1 "rising" nil nil))))
  34.  
  35. if(RAMP_AT_CROSS==nil then RAMP_AT_CROSS=9999e9999 printf("\nRAMP_AT_CROSS is nil in corner %d",i) )
  36. IGND_INLO = nth(0 errset(value((- IT("/I2/vssa")) 5.05e-05)))
  37.  
  38. if(IGND_INLO==nil then IGND_INLO=9999e9999 printf("\nIGND_INLO is nil in corner %d",i) )
  39. Fall_Delay = nth(0 errset((cross(clip(VT("/OUT") 6e-05 8e-05) (VAR("vdd") / 2) 2 "falling" nil nil) - root(clip(VT("/IN") 6e-05 cross(clip(VT("/OUT") 6e-05 8e-05) (VAR("vdd") / 2) 2 "falling" nil nil)) (VAR("vdd") / 2) -1))))
  40.  
  41. if(Fall_Delay==nil then Fall_Delay=9999e9999 printf("\nFall_Delay is nil in corner %d",i) )
  42.  
  43. ;;-- Plot Statements
  44.  
  45. plot(getData("/IN") getData("/OUT"))
  46.  
  47. sprintf(__foutSTR "%s\n%s,%s,%e,%e,%e,%e" __foutSTR nth(i,runData) nth(i runTimes) float(Fall_Delay) float(IGND_INHI) float(IGND_INLO) float(RAMP_AT_CROSS) )
  48.  
  49. if(i==255 then
  50. writeFile()
  51. )
  52. ) ;; for i ends here
  53. ;; Now to turn Graphics ON for all existing windows
  54. foreach(wid awvGetWindowList()
  55. currentWindow(wid)
  56. graphicsOn()
  57. )


We can do specific plotting easily by changing the plotting commands after the ;;-- Plot Statements line as follows:
  1. ;;-- Plot Statements
  2. if(i==1 then
  3. wid1 = newWindow()
  4. cW(wid1)
  5. addTitle("Vdd=5V")
  6. wid2 = newWindow()
  7. cW(wid2)
  8. addTitle("Vdd=4.7V")
  9. wid3= newWindow()
  10. cW(wid3)
  11. addTitle("Vdd=5.2V")
  12. )
  13. if(i==1 then
  14. selectResult( 'tran )
  15. cW(wid1)
  16. plot(getData("/IN") )
  17. )
  18.  
  19. if(i==86 then
  20. selectResult( 'tran )
  21. cW(wid2)
  22. plot(getData("/IN") )
  23. )
  24.  
  25. if(i==171 then
  26. selectResult( 'tran )
  27. cW(wid3)
  28. plot(getData("/IN") )
  29. )
  30.  
  31. if(i<86 then
  32. selectResult( 'tran )
  33. cW(wid1)
  34. plot(getData("/OUT") )
  35. )
  36. if(i>85 && i<171 then ;; && is the conditional 'and' operator. The OR operator is ||
  37. selectResult( 'tran )
  38. cW(wid2)
  39. plot(getData("/OUT") )
  40. )
  41.  
  42. if(i>170 then
  43. selectResult( 'tran )
  44. cW(wid3)
  45. plot(getData("/OUT") )
  46. )

Here are some notes that explain the above section:
  • The cW function is already defined the Measurement Extraction section of the corner script and is used to select the current window to draw on when multiple plotting windows are open.
  • When the first corner is measured then all the different plotting windows are created in the variables wid1, wid2, wid3 and titles are given to them.
  • Depending on the value of i the right window is selected and data is added to it.

Advantages of the tool

  1. Easily and quickly generate complex sequence of corners
  2. Does not use ADE-XL license to run corners
  3. Append scripts generated for different test benches into 1 big file and submit it as a night job
  4. Automatically generate the full result table with measurement headings and corner settings to look in excel
  5. Even if some corners have errors like non convergence or bad measurements it does not stop the whole thing but shows those corners as bad data.
  6. If you have the nodes saved in the simulation you can generate more measurement data or waves without running the simulations again by just running the measurement part of the script.
  7. The tool is cross platform and can run on Linux, Windows, Mac. although I have just tested it on Windows.