pascalkuthe / OpenVAF

An innovative Verilog-A compiler
https://openvaf.semimod.de/
GNU General Public License v3.0
113 stars 15 forks source link

Support hidden state variables #65

Open medwatt opened 1 year ago

medwatt commented 1 year ago

I am testing a memristor model from here called "Joglekar Resistance Switch Model in Verilog-A". After some minor modifications, it was able to compile with openvaf. The result produced is not what I was expecting.

This is the current I(V1) plot from ngspice.

image

Of course, there's the possibility that I introduced a mistake when I modified the file. So, I simulated the same verilog-a model in spectre. The plot of the current I(V1) is shown below.

image

The modified verilog-a file is given below.

`include "disciplines.vams"

`define X_BORDER_BUMP 10e-18

module joglekar_memristor (p,n);

    inout p,n;
    electrical p,n;

    parameter real Roff=16000 from (0:inf);
    parameter real Ron=100 from (0:inf);
    parameter real Rinit=11000 from (0:inf);
    parameter real D=10n from (0:inf);
    parameter real uv=10e-15 from (0:inf);
    parameter real p_coeff=1.0 from (0:inf);

    // local variables that should persist over time steps
    real w_last;
    real time_last;

    // local variables that hold temporary values
    real G;
    real window_function;
    real w;
    real dw;
    real R;
    real direction;
    real mem_current;
    real abstime;
    real time_delta;

    analog begin

    @(initial_step)
    begin
        w_last = ((Roff - Rinit) / (Roff - Ron)) * D;
        time_last = 0;
    end

    // calculate conductance
    G = 1 / (Ron * w_last / D + Roff * (1 - w_last / D));
    mem_current = G * V(p,n);

    direction = 0;
    if (mem_current > 0) begin
        if(w_last<=0) begin
            direction=1;
        end
    end
    else
    begin
        if(w_last>=D) begin
            direction=-1;
        end
    end

    abstime = $abstime;
    time_delta = abstime - time_last;
    window_function = (1.0 - (pow(2 * w_last / D - 1, 2 * p_coeff)));
    dw = uv * Ron / D * mem_current * window_function * time_delta;
    w = w_last + dw + direction * `X_BORDER_BUMP;

    if(w >= D) begin
        w = D;
    end

    if(w <= 0) begin
        w = 0;
    end

    // calculate conductance
    G = 1 / (Ron * w / D + Roff * (1 - w / D));

    // set the mem_current
    I(p,n) <+ -1.0*G*V(p,n);

    // persist variables
    w_last = w;
    time_last = abstime;

end
endmodule

The ngspice netlist is given below:

.title Verilog-A memristor test

.model my_memristor joglekar_memristor

V1 1 0 SIN(0V 1.2V 1Hz)
NX1 1 0 my_memristor

.control
*set filetype=ascii
pre_osdi ./joglekar_memristor.osdi
tran 1ms 1s
plot I(V1) retraceplot
*write res.txt
.endc

.end

Here's the plot data from spectre:

time (s),/V0/PLUS (A)
0.000,0.000
1.000E-3,685.4E-9
3.000E-3,2.056E-6
7.000E-3,4.798E-6
15.00E-3,10.28E-6
31.00E-3,21.23E-6
51.00E-3,34.86E-6
71.00E-3,48.34E-6
91.00E-3,61.61E-6
111.0E-3,74.61E-6
131.0E-3,87.28E-6
151.0E-3,99.58E-6
171.0E-3,111.5E-6
191.0E-3,122.9E-6
211.0E-3,133.7E-6
231.0E-3,144.0E-6
251.0E-3,153.6E-6
271.0E-3,162.4E-6
291.0E-3,170.0E-6
311.0E-3,176.1E-6
331.0E-3,180.1E-6
351.0E-3,181.2E-6
371.0E-3,178.4E-6
391.0E-3,170.3E-6
411.0E-3,155.4E-6
431.0E-3,132.6E-6
451.0E-3,101.4E-6
471.0E-3,62.97E-6
491.0E-3,19.88E-6
511.0E-3,-23.93E-6
531.0E-3,-64.43E-6
551.0E-3,-98.59E-6
571.0E-3,-125.0E-6
591.0E-3,-143.6E-6
611.0E-3,-155.5E-6
631.0E-3,-161.9E-6
651.0E-3,-164.1E-6
671.0E-3,-163.1E-6
691.0E-3,-159.9E-6
711.0E-3,-154.9E-6
731.0E-3,-148.6E-6
751.0E-3,-141.3E-6
771.0E-3,-133.1E-6
791.0E-3,-124.2E-6
811.0E-3,-114.6E-6
831.0E-3,-104.3E-6
851.0E-3,-93.56E-6
871.0E-3,-82.23E-6
891.0E-3,-70.41E-6
911.0E-3,-58.16E-6
931.0E-3,-45.53E-6
951.0E-3,-32.58E-6
971.0E-3,-19.39E-6
985.5E-3,-9.719E-6
1.000,-26.17E-21

Here's the plot data from ngspice:

Title: Verilog-A memristor test
Date: Wed May  3 00:44:48  2023
Plotname: Transient Analysis
Flags: real
No. Variables: 3
No. Points: 108
Variables:
    0   time    time
    1   v(1)    voltage
    2   i(v1)   current
Values:
 0  0.000000000000000e+00
    0.000000000000000e+00
    0.000000000000000e+00

 1  1.000000000000000e-04
    7.539821872515087e-04
    6.854383520468261e-08

 2  2.000000000000000e-04
    1.507964076842791e-03
    1.370876784855389e-07

 3  4.000000000000000e-04
    3.015925772404472e-03
    2.741753513080024e-07

 4  8.000000000000000e-04
    6.031832494582635e-03
    5.483506573092273e-07

 5  1.600000000000000e-03
    1.206351258807679e-02
    1.096700952094711e-06

 6  3.200000000000000e-03
    2.412580599054910e-02
    2.193399001774594e-06

 7  6.400000000000000e-03
    4.824185923554385e-02
    4.386774713020286e-06

 8  1.280000000000000e-02
    9.640572016007308e-02
    8.773360821304827e-06

 9  2.280000000000000e-02
    1.713205573769387e-01
    1.563053094602801e-05

 10 3.280000000000000e-02
    2.455592706227552e-01
    2.251014790110941e-05

 11 4.280000000000000e-02
    3.188288736127832e-01
    2.941502580883767e-05

 12 5.280000000000001e-02
    3.908402046977186e-01
    3.635163964851341e-05

 13 6.280000000000001e-02
    4.613090680526169e-01
    4.332542477742161e-05

 14 7.280000000000000e-02
    5.299573552679777e-01
    5.034046306112031e-05

 15 8.280000000000000e-02
    5.965141429165811e-01
    5.739912351675138e-05

 16 9.279999999999999e-02
    6.607167617644818e-01
    6.450164843435150e-05

 17 1.028000000000000e-01
    7.223118334064741e-01
    7.164567625347727e-05

 18 1.128000000000000e-01
    7.810562702348983e-01
    7.882569333347123e-05

 19 1.228000000000000e-01
    8.367182347953729e-01
    8.603240846423267e-05

 20 1.328000000000000e-01
    8.890780547433106e-01
    9.325204690766777e-05

 21 1.428000000000000e-01
    9.379290897903031e-01
    1.004655654207504e-04

 22 1.528000000000000e-01
    9.830785472189348e-01
    1.076477966613794e-04

 23 1.628000000000000e-01
    1.024348242747560e+00
    1.147665412491293e-04

 24 1.728000000000000e-01
    1.061575303742258e+00
    1.217816391646492e-04

 25 1.828000000000000e-01
    1.094612812000709e+00
    1.286440696026849e-04

 26 1.928000000000000e-01
    1.123330383571218e+00
    1.352951499700802e-04

 27 2.028000000000000e-01
    1.147614683318607e+00
    1.416659299029734e-04

 28 2.128000000000000e-01
    1.167369872206216e+00
    1.476769033540473e-04

 29 2.228000000000001e-01
    1.182517985528790e+00
    1.532381878133768e-04

 30 2.328000000000001e-01
    1.192999240603561e+00
    1.582503394432688e-04

 31 2.428000000000001e-01
    1.198772272705179e+00
    1.626059790290636e-04

 32 2.528000000000001e-01
    1.199814298313386e+00
    1.661923870449562e-04

 33 2.628000000000001e-01
    1.196121205029163e+00
    1.688951770734989e-04

 34 2.728000000000001e-01
    1.187707567804489e+00
    1.706030673754343e-04

 35 2.828000000000001e-01
    1.174606591421664e+00
    1.712136380789897e-04

 36 2.928000000000001e-01
    1.156869979449205e+00
    1.706397934031704e-04

 37 3.028000000000001e-01
    1.134567730191479e+00
    1.688164648653120e-04

 38 3.128000000000001e-01
    1.107787860437379e+00
    1.657069266811473e-04

 39 3.228000000000001e-01
    1.076636058098265e+00
    1.613079921509521e-04

 40 3.328000000000002e-01
    1.041235265106064e+00
    1.558538463481697e-04

 41 3.428000000000002e-01
    1.001725192217634e+00
    1.490689431351353e-04

 42 3.528000000000002e-01
    9.582617676402292e-01
    1.412085271979401e-04

 43 3.628000000000002e-01
    9.110165216541070e-01
    1.324084370648376e-04

 44 3.728000000000002e-01
    8.601759096608749e-01
    1.228289398354197e-04

 45 3.828000000000002e-01
    8.059405763292041e-01
    1.126465055841991e-04

 46 3.928000000000002e-01
    7.485245637419874e-01
    1.020448449365426e-04

 47 4.028000000000002e-01
    6.881544666700257e-01
    9.120611439395653e-05

 48 4.128000000000002e-01
    6.250685383059880e-01
    8.030308659462463e-05

 49 4.228000000000002e-01
    5.595157499879083e-01
    6.949286607155171e-05

 50 4.328000000000002e-01
    4.917548086230577e-01
    5.891246217722088e-05

 51 4.428000000000002e-01
    4.220531356899738e-01
    4.867626756043444e-05

 52 4.528000000000003e-01
    3.506858118480581e-01
    3.887527692099191e-05

 53 4.628000000000003e-01
    2.779344913198859e-01
    2.957773972589799e-05

 54 4.728000000000003e-01
    2.040862903306650e-01
    2.083087474433391e-05

 55 4.828000000000003e-01
    1.294326539916660e-01
    1.266327160233257e-05

 56 4.928000000000003e-01
    5.426820609951687e-02
    5.087645824140221e-06

 57 5.028000000000002e-01
    -2.111041360932151e-02
    -1.896321000411765e-06

 58 5.128000000000003e-01
    -9.640572016007502e-02
    -8.299251863822532e-06

 59 5.228000000000003e-01
    -1.713205573769408e-01
    -1.413958364552502e-05

 60 5.328000000000003e-01
    -2.455592706227573e-01
    -1.944138564465301e-05

 61 5.428000000000003e-01
    -3.188288736127849e-01
    -2.423251393653644e-05

 62 5.528000000000003e-01
    -3.908402046977204e-01
    -2.854309720159027e-05

 63 5.628000000000003e-01
    -4.613090680526187e-01
    -3.240432997216986e-05

 64 5.728000000000003e-01
    -5.299573552679795e-01
    -3.584753839242560e-05

 65 5.828000000000003e-01
    -5.965141429165829e-01
    -3.890347918105611e-05

 66 5.928000000000003e-01
    -6.607167617644838e-01
    -4.160183242260780e-05

 67 6.028000000000003e-01
    -7.223118334064761e-01
    -4.514448958790476e-05

 68 6.128000000000003e-01
    -7.810562702349003e-01
    -4.881601688968127e-05

 69 6.228000000000004e-01
    -8.367182347953749e-01
    -5.229488967471093e-05

 70 6.328000000000004e-01
    -8.890780547433124e-01
    -5.556737842145702e-05

 71 6.428000000000004e-01
    -9.379290897903048e-01
    -5.862056811189405e-05

 72 6.528000000000004e-01
    -9.830785472189362e-01
    -6.144240920118352e-05

 73 6.628000000000004e-01
    -1.024348242747562e+00
    -6.402176517172260e-05

 74 6.728000000000004e-01
    -1.061575303742259e+00
    -6.634845648389121e-05

 75 6.828000000000004e-01
    -1.094612812000710e+00
    -6.841330075004437e-05

 76 6.928000000000004e-01
    -1.123330383571219e+00
    -7.020814897320118e-05

 77 7.028000000000004e-01
    -1.147614683318608e+00
    -7.172591770741303e-05

 78 7.128000000000004e-01
    -1.167369872206216e+00
    -7.296061701288850e-05

 79 7.228000000000004e-01
    -1.182517985528790e+00
    -7.390737409554940e-05

 80 7.328000000000005e-01
    -1.192999240603561e+00
    -7.456245253772260e-05

 81 7.428000000000005e-01
    -1.198772272705179e+00
    -7.492326704407370e-05

 82 7.528000000000005e-01
    -1.199814298313386e+00
    -7.498839364458665e-05

 83 7.628000000000005e-01
    -1.196121205029163e+00
    -7.475757531432270e-05

 84 7.728000000000005e-01
    -1.187707567804489e+00
    -7.423172298778055e-05

 85 7.828000000000005e-01
    -1.174606591421664e+00
    -7.341291196385398e-05

 86 7.928000000000005e-01
    -1.156869979449204e+00
    -7.230437371557525e-05

 87 8.028000000000005e-01
    -1.134567730191478e+00
    -7.091048313696740e-05

 88 8.128000000000005e-01
    -1.107787860437378e+00
    -6.923674127733610e-05

 89 8.228000000000005e-01
    -1.076636058098263e+00
    -6.728975363114147e-05

 90 8.328000000000005e-01
    -1.041235265106063e+00
    -6.507720406912893e-05

 91 8.428000000000005e-01
    -1.001725192217633e+00
    -6.260782451360204e-05

 92 8.528000000000006e-01
    -9.582617676402274e-01
    -5.989136047751421e-05

 93 8.628000000000006e-01
    -9.110165216541053e-01
    -5.693853260338158e-05

 94 8.728000000000006e-01
    -8.601759096608728e-01
    -5.376099435380455e-05

 95 8.828000000000006e-01
    -8.059405763292019e-01
    -5.037128602057512e-05

 96 8.928000000000006e-01
    -7.485245637419854e-01
    -4.678278523387409e-05

 97 9.028000000000006e-01
    -6.881544666700231e-01
    -4.300965416687644e-05

 98 9.128000000000006e-01
    -6.250685383059859e-01
    -3.906678364412411e-05

 99 9.228000000000006e-01
    -5.595157499879055e-01
    -3.496973437424410e-05

 100    9.328000000000006e-01
    -4.917548086230554e-01
    -3.073467553894096e-05

 101    9.428000000000006e-01
    -4.220531356899709e-01
    -2.644496734468493e-05

 102    9.528000000000006e-01
    -3.506858118480557e-01
    -2.312509760211469e-05

 103    9.628000000000007e-01
    -2.779344913198829e-01
    -1.938801116901117e-05

 104    9.728000000000007e-01
    -2.040862903306625e-01
    -1.514600586823299e-05

 105    9.828000000000007e-01
    -1.294326539916630e-01
    -1.028423975906868e-05

 106    9.928000000000007e-01
    -5.426820609951436e-02
    -4.649617059142608e-06

 107    1.000000000000000e+00
    -2.939152317953648e-16
    -2.671956652685134e-20

I did these tests on: openvaf 23.2.0 and ngspice 40

pascalkuthe commented 1 year ago

The problem is that OpenVAF does currently not support hidden state.

// local variables that should persist over time steps real w_last; real time_last;

OpenVAF will not persist variables over timestamps as this makes it impossible to optimize a lot of compact models correctly. I want to offer an attribute to mark a variable has hidden (and a cli setting that does so for all variables automatically which can not be proven to be statefree). This is not quite compliant with the Verilog-A standard but sadly a few compact models are written such that it is NP-hard to determine whether some code is operating point dependent because variables are not initialized properly.

I hope to implement this in the not-so-distant future. There is currently a push from the CMC to make sure compact models do initialize all variables correctly so hopefully one day OpenVAF can just assume that all uninitialized variables are hidden state

medwatt commented 1 year ago

Thanks for the clarification. Is there a workaround for this issue at the amount (rewriting the code in some way to avoid the need for variables that persist between timestamps)? A lot of memristor models depend on persistent variables.

I have some minor suggestions if you don't mind:

  1. The user should be notified that the code he's running requires persistent variables and the simulator does not support that at the moment.
  2. I noticed that the simulator failed to warn me when I had a variable defined as one of the keywords in verilog-a. For example, the original code had user-defined variables time and current. The simulator complained about time, but not about current. spectre complained about both.
pascalkuthe commented 1 year ago

The user should be notified that the code he's running requires persistent variables and the simulator does not support that at the moment.

This is actually a bit hard to detect. To the compiler these non-ideal compact models I described earlier are indistinguishable from the cases I described before. So automatically adding a warning (which I had implemented before) caused many of warnings while compiling CMC models. While generating these warnings is more correct the compact model uses is the largest industry use case and I don't want to degrade the experience here. On the other hand such warnings might push model developers to finally fix those issues.

I noticed that the simulator failed to warn me when I had a variable defined as one of the keywords in verilog-a. For example, the original code had user-defined variables time and current. The simulator complained about time, but not about current. spectre complained about both.

OpenVAF only treats the identifiers listed in Table B.1—Reserved keywords of the Verilog-AMS LRM. current is not listed there. current is only used as a nature name in the Verilog-A standard library. OpenVAF fully supports defining custom disciplines/natures and the standard library are just normal files processed as normal by the compiler. So current receives no special casing in the compiler whatsoever. Paramters are defined at the module scoping level so they are allowed to shadow identifier from a parent scope (in this case natures which are defined at the root scope).

Most established Verilog-A compilers don't stick to the LRM as closely as OpenVAF does so I suspect spectre just treats current as a compiler builtin.