Hello All, I hope ya’ll are having a nice day. I a...
# analog-design
m
Hello All, I hope ya’ll are having a nice day. I am working on a simple miss match Monte Carlo simulation on an inverter, but it isn’t working correctly; all of the runs are identical. I’ve read a bunch of previous posts (including one from @Stefan Schippers that mentions it might be broken) and I am not sure what I’m doing wrong. Does anyone have any ideas? I would appreciate any help or thoughts. Thanks a lot!
t
Try
.option SEED=random
.
m
@Tim Edwards thanks for the quick reply. I have that on line 33
t
Sorry, missed that. At a glance, it looks right to me.
m
@Tim Edwards No worries 🙂. I’m glad it isn’t obvious, but I’m quite puzzled. I even checked the value of
mc_mm_switch
parameter after loading the libraries to make sure nothing in there set it a different value using `csparam`and it is still 1.
Thanks for your help! I really appriciate it
t
I think the problem is just one of understanding how the mismatch computations are done. They are computed as the netlist is read in. If you run the above netlist through ngspice multiple times, you get different results between each run. Within the program, though, inside a loop, you get the same devices with the same parameters, which don't get calculated again.
m
Ah, Interesting!
t
The only solution that I know of is to take data from multiple ngspice runs and aggregate data in another application like octave or python/numpy. There might be a better solution that I don't know about.
m
@Tim Edwards That makes sense now. After reading the ngspice example and an example from bminch on youtube more closely, I noticed now the
reset
command (https://sourceforge.net/p/ngspice/ngspice/ci/master/tree/examples/Monte_Carlo/MC_ring.sp#l49 and

https://www.youtube.com/watch?v=fXaXTALecr8

). I think that’s the key, but now I’m running into an issue where reset (and
mc_source
) are loosing net names in the circuit. You’ve helped a lot. Thank you. I may just write a python script.
Though there is probably another user error here 🙂
You don’t by any chances have any thoughts about ngspice’s
reset
command do you? I feel like I’m close.
Ah, I figured it out. Two things: 1. both
reset
and
mc_source
reloads the circuit so it also reloads which nets it saves. You have to call
save
after reset or
mc_source
2. both
reset
and
mc_source
calls reloads the circuit which also reloads
set SEED=random
to the original sample of the unix clock. So you can’t use
set SEED=random
. I’m not entirely sure what’s happening under the hood (the manual isn’t clear), but not calling
set SEED=random
works.
s
you need to add a
reset
instruction after run = run + 1
🌍 1
This is the setup I do to have a working mismatch sim with repeatable set of random variables (meaning: start from a specific seed).
Copy code
.control
  setseed 9
  reset
  let run=0
  dowhile run <= 100
    save all
    tran 1n 4000n uic
    print run
    print @m.x1.xml.msky130_fd_pr__pfet_01v8_lvt[vth]
    print @m.x1.xmr.msky130_fd_pr__pfet_01v8_lvt[vth]
    remzerovec
    write tb_bandgap_opamp.raw
    set appendwrite
    reset
    let run = run + 1
  end
.endc
When I start a new circuit I copy paste from this working circuit. It is impossible to remember where to put all the reset instructions and the precise order of statements to have a working simulation.
🌍 2
m
@Stefan Schippers thank you so much! That's perfect!
🌍 1
t
@Holger Vogt: Can I please implore you to change
src/frontend/inp.c
lines 434 to 442 from
Copy code
/* option seed=random [seed='random'] */
            if (eq(token, "random") || eq(token, "{random}")) {
                time_t acttime = time(NULL);
                /* get random value from time in seconds since 1.1.1970 */
                int rseed = (int)(acttime - 1600000000);
                cp_vset("rndseed", CP_NUM, &rseed);
                com_sseed(NULL);
                has_seed = TRUE;
            }
to
Copy code
/* option seed=random [seed='random'] */
            if (eq(token, "random") || eq(token, "{random}")) {
                struct timeval tv;
                gettimeofday(&tv, NULL);
                /* get random value from current timestamp microseconds */
                int rseed = (int)(tv.tv_usec);
                cp_vset("rndseed", CP_NUM, &rseed);
                com_sseed(NULL);
                has_seed = TRUE;
            }
? Using
.option SEED=random
has the unfortunate property of asserting a new random value based on
time()
every time
reset
is called or every time the program is run (even overriding the use of
setseed
within a control block), and using
time()
to generate the seed has the very unfortunate property of returning a value in seconds which is a long, long time on a computer. If I am trying to do a mismatch analysis on a simple circuit using a
DC
analysis, then it can end up running 30 or 40 analyses with the exact same random seed. There are really multiple issues here: (1)
.option SEED
should not be able to override `setseed`; and (2) random seeds should be based on microseconds or even CPU clock tick counts. If you want to be pedantic and avoid the case where an analysis takes exactly one second, then I would suppose that
int rseed = (int)(<http://tv.tv|tv.tv>_usec) + (int)random();
would be a reasonable solution.
h
Thanks for the patch. I will have a look.
There is a patch uploaded to ngspice git branch pre-master-42. A little tricky, as MS Windows does not know about gettimeofday. Will you have a chance to look at it?
t
@Holger Vogt: Does Windows support
clock_gettime()
? That would be even better because it uses
struct timespec
with field
tv_nsec
for a timestamp in nanoseconds.