Pages

2012-12-27

For the loop will set you free!


One thing I forgot to mention in the previous post is that if you can get it to work, we're just one tiny step away from the ultimate purpose of OCEAN Script which is automation - run multiple simulations with different settings and/or design values, automatically. We will master that step in this post.

The loop ...

The basic concept for simulation loop, in OCEAN Script, can be broken down in few following sub-steps:
  • Firstly, we'll need to define a list of values that would be applied to the simulation.
  • Secondly, set up a "foreach" loop to access and get one value a time from the defined list. Then, the acquired value is applied to the design parameter.
  • Finally, we'll run the simulation with new value for the parameter, with in the loop.
Below is simplified example for commonly used loops which sweep values of design parameter (ib) and different temperatures, respectively.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
; ...
; Run simulation with various values for "ib"
; List declaration with 3 values to be swept
ibias_list = list(8.5u 10u 11.5u)   

; Loop declaration and start
foreach(
    ; Get a value in list and store in ibias_val
    ibias_val ibias_list
    ; Assign ibias_val to design parameter "ib"
    desVar("ib" ibias_val)

    ; Code for other setups, loops run simulation is here
)   ; Stop loop for "ib" values

; Run simulation with different temperature values
temp_list = list(-40 25 90)

foreach(
    ; Get a value in list and store in temp_val
    temp_val temp_list
    ; Set temperature of temp_val for simulation
    temp(temp_val)

    ; ...
)   ; Stop loop for temperature values
; ...

Looping for corner takes a little bit more work but still very much manageable. Below is the code sample for it. Again, it's always the best practice to check model file and corner settings with your CAD support.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
; ...
; Run simulation with different corner values
corner_list = list("TYP" "SLOW" "FAST" "SLOWFAST" "FASTSLOW") 

foreach(
    ; Get value in list and store in corner_val              
    corner_val corner_list
    ; Set new corner value                               
    modelFile(list("~/corner.scs" strcat(corner_val)))    
 
    ; ...
)
; ...

and the freedom it brings.

At this point, you might think that this is pretty good to have all of the above loops running. If so, I'm glad to let you know that thing is still looking up from here, since OCEAN allows nested loops which means you can set up loop inside another loop. 

This alone enables simulation running with a lot of combinations of values from different parameters and settings. For example, nesting three above implemented loops into each other yields  a script that would run 45(3*3*5) simulations, automatically! Imagine if you have to run all that manually would give you a sense of the freedom OCEAN Script brings - Once setup properly, it works diligently so that you're free to do other stuffs. 

The large number of simulations would run in the new script yields in a large number of  result sets. Thus, it raises a pleasant challenge that is we need to be able to discern between one result set and another. One way to achieve this is writing the condition applied to the simulation with its results. Below is the full code for the opamp characterization.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
; File: Opamp_tb.ocn
; Author: Pham Duy Dong
; Purpose: Operation amplifier characterization
; License: Creative Commons Attribution 3.0 Unported License

simulator('spectre)
design("OceanScriptLib" "Opamp_tb" "schematic")
createNetlist(?recreateAll t)

analysis('ac ?start "0.1"  ?stop "1G")
analysis('dc ?saveOppoint t)

desVar("CL" 5p)

; Define, create the output file and write the first line into it. 
out = outfile("~/Opamp.txt" "w")
fprintf(out, "Corner IBias Temp. GBW PM GM OLGain IDC FOM\n")
close(out)

; List definitions
ibias_list = list(8.5u 10u 11.5u)
temp_list = list(-40 25 90)
corner_list = list("NOM" "SLOW" "FAST" "SLOWFAST" "FASTSLOW")

foreach(
    corner_val corner_list
    ; Set new corner value
    modelFile(list("~/corner.scs" strcat(corner_val)))

    foreach(
        ibias_val ibias_list
        desVar("ib" ibias_val)

        foreach(
            temp_val temp_list
            temp(temp_val) 

            ; Save the current going through port VDD of component I1,
            ; for estimating current consumption of the opamp.
            saveOption('save "selected")
            save('v "/OUT")
            save('i "/I1/VDD")

            ; Execute the simulation
            run()

            ; Calculate Gain-Bandwidth, Phase Margin, Gain Margin, Open Loop Gain, 
            ; and DC current using built-in functions and store results in variables.
            GBW = gainBwProd(VF("/OUT"))
            PM = phaseMargin(VF("/OUT"))
            GM = gainMargin(VF("/OUT"))
            OLGain = ymax(dB20(real(VF("/OUT"))))
            IDC = IDC("/I1/VDD")

            CL = evalstring(desVar("CL"))

            ; Calculate Figure-of-Merit of opamp. FOM = GBW(MHz) * CL(pF) / IDC(mA)
            ; GBW(MHz) = GBW * 1e-6; CL(pF) = CL * 1e12; IDC(mA) = IDC * 1e3.
            FOM = 1e3 * GBW * CL / IDC
   
            ; Open ouput file in append mode.
            out = outfile("~/Opamp.txt" "a")
            ; Print out the simulation condition.
            fprintf(out,"%8s %8.2e %3d",corner_val,ibias_val,temp_val)
            ; Print out the calculated results.
            fprintf(out," %8.2e %8.2e %8.2e %8.2e %8.2e %8.2e\n",GBW,PM,GM,OLGain,IDC,FOM)
            close(out)

        ) ; End of temperature loop
    ) ; End of biasing current loop
) ; End of corner loop

Happy designing!

2012-12-25

Son asked: Why does fireman splash water into a fire?

Here is our exchange.

PDD: Can you breath when you are under water?

Pham Duy Khoi(PDK): No, I can't!

PDD: See, a fire has to breath just like you. When fireman splashs water into the fire, it can't breathe. So it will faint and stop burning.

I saw PDK nodded and I'm happy that I didn't give him the "That’s the way it is" cliche.

2012-12-04

Dive into OCEAN Script

I’ve been prepared this post with the original title of “Data and variables” with the structure of a list of frequently used commands and settings in a OCEAN Script. It’s been a very slow and boring process then I realized that I was essentially doing a language reference which is not what I did to jump start my simulation. So let’s scratch that and do it the right way, instead.

Let’s dive right into OCEAN Script!

Extending the script we built in previous post, we get a new script as below. The script will configure the simulation, run it, store data it generated, calculate the specifications of the opamp, and then write the result to an output file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
; This is a comment line. 
; The comment starts from ";" character and ends at the end of the line.

; 1. Setups for simulator, targeted design, model file,
; simulation type and parameters.
simulator( 'spectre )
design( "OceanScriptLib" "Opamp_tb" "schematic" )
createNetlist(?recreateAll t)
; 1.1. Check model file setting with your CAD support, if any.
modelFile( '("~/model.scs" "TYP") )
analysis('ac ?start "0.1"  ?stop "1G"  )

; 2. Set value of load capacitor at 5pF, bias current at 10uA. 
; "CL" and "IB" are the values declared in schematic. desVar = design variable.
desVar( "CL" 5p )
desVar( "IB" 10u )

; 3. Save the current going through port VDD of component I1,
; for estimating current consumption of the opamp.
saveOption('save "selected")
save( 'v "/OUT" )
save( 'i "/I1/VDD" )

; 4. Execute the simulation
run()

; 5.1. Calculate GBW, PM, GM, OLGain, and IDC
; using built-in functions and store results in variables.
GBW = gainBwProd(VF("/OUT"))
PM = phaseMargin(VF("/OUT"))
GM = gainMargin(VF("/OUT"))
OLGain = ymax(dB20(real(VF("/OUT"))))
IDC = average(mag(IF("/I1/VDD")))

; 5.2. Read design variable CL and assign the result to calculation parameter Cl.
Cl = evalstring( desVar("CL") )

; 5.3. Calculate Figure-of-Merit of the opamp. FOM = GBW(MHz) * CL(pF) / IDC(mA)
; GBW(MHz) = GBW * 1e-6; CL(pF) = CL * 1e12; IDC(mA) = IDC * 1e3.
FOM = 1e3 * GBW * CL / IDC

; 6.1. Define, create the output file and write the first line into it. 
out = outfile("~/Opamp.txt" "w")
fprintf(out, "GBW PM GM OLGain IDC FOM\n")
close(out)

; 6.2. Open ouput file and append calculated results into it.
out = outfile("~/Opamp.txt" "a")
fprintf(out,"%10.2e %10.2e %10.2e %10.2e %10.2e %10.2e\n",GBW,PM,GM,OLGain,IDC,FOM)
close(out)

I hope the explanation given in the code is clear enough. After reading the script, you may try to modify the code to your particular setup and put it to work. Remember to check out the simulation result in the output file, see how well your opamp performs.

P.S. It may seem that writing the script from scratch is an overwhelming task. Luckily, there is a faster way to dive into OCEAN Script, thanks to a built-in feature in ADE.

Once the evaluation bench for Opamp is done. Go to your ADE window to configure for your simulation. Then, in ADE go to Session > Save Ocean Script > a new window titled "Save Ocean Script to File" would pop-up. Enter path and file name for .ocn file.

I'm sure you get the idea.