.. _design-miller-evaluation:
	
Evaluation of opamp's performance
=================================

We are going to set up the evaluation of a Miller opamp. For now we are not 
going to use any of the :mod:`pyopus.design` module's facilities. The script 
from file `01-evaluator.py <../../../demo/design/miller/01-evaluator.py>`_ 
in folder `demo/design/miller/ <../../../demo/design/miller/>`_

.. literalinclude:: ../demo/design/miller/01-evaluator.py
   :language: python

The script first prepares dictionaries with nominal statistical parameter 
values (0), nominal operating parameter values and initial design parameter 
values. The nominal corner named ``nom`` is defined. This corner adds the 
'tm' module to the input netlist for the simulator and specifies the nominal 
values of operating parameters. 

Next, the cooperative multitasking OS is initialized. It uses MPI as the 
backend and starts every task in its own local folder which contains 
the copies of all files from the current folder (mirrorMap argument
to MPI). 

Finally, a :class:`pyopus.evaluator.performance.PerformanceEvaluator` 
object is created from ``heads``, ``analyses``, ``measures``, and 
``variables`` defined in 
`definitions.py <../../../demo/design/miller/definitions.py>`_ 
and the ``corners`` variable constructed in this script. The evaluator 
will store the waveforms produced by the simulator in the local temporary 
folder of the machine where the results were computed by a simulator. 
The performance evaluator is then called (``pe()``) and the values of the 
initial design parameters and nominal statistical parameters are passed. 
These parameters are added to the input netlist for the simulator. 

When the evaluation is finished the performance measures are printed

.. code-block:: none

      area |             nom:    1.179e-09
      cmrr |             nom:    5.796e+01
      gain |             nom:    6.624e+01
  gain_com |             nom:    8.277e+00
  gain_vdd |             nom:   -2.624e+01
  gain_vss |             nom:    3.777e+00
   in1kmn2 |             nom:    1.581e-16
 in1kmn2id |             nom:    1.581e-16
 in1kmn2rd |             nom:    0.000e+00
  inoise1k |             nom:    3.344e-14
      isup |             nom:    3.010e-04
  onoise1k |             nom:    3.337e-14
    out_op |             nom:    6.979e-03
  overshdn |             nom:    7.176e-02
  overshup |             nom:    8.924e-02
        pm |             nom:    7.004e+01
  psrr_vdd |             nom:    9.247e+01
  psrr_vss |             nom:    6.246e+01
    slewdn |             nom:    1.082e+07
    slewup |             nom:    1.006e+07
     swing |             nom:    1.474e+00
    tsetdn |             nom:    1.925e-07
    tsetup |             nom:    2.094e-07
      ugbw |             nom:    6.641e+06
   vds_drv |             nom: [0.58454814 0.8205568  0.433882   0.11164392 0.82752772 0.55567868 0.32221448 0.80099198]
   vgs_drv |             nom: [0.2121875  0.20869958 0.02675759 0.02674103 0.02677772 0.39175785 0.39175785 0.10682108]
   
Next, the list of stored waveform files and hosts where they are stored is 
printed
	
.. code-block:: none

  Result files across hosts
  {(None, ('nom', 'ac')): '/tmp/restemp.calypso_7967_2.nom.ac.s8xost1h',
   (None, ('nom', 'accom')): '/tmp/restemp.calypso_7967_6.nom.accom.fe5in9c1',
   (None, ('nom', 'acvdd')): '/tmp/restemp.calypso_7967_5.nom.acvdd.j5xqaicj',
   (None, ('nom', 'acvss')): '/tmp/restemp.calypso_7967_3.nom.acvss.qny1pj8d',
   (None, ('nom', 'blank')): '/tmp/restemp.calypso_7967_1.nom.blank.1dgn84hu',
   (None, ('nom', 'dc')): '/tmp/restemp.calypso_7967_2.nom.dc.9oion0n5',
   (None, ('nom', 'noise')): '/tmp/restemp.calypso_7967_2.nom.noise.otzdr6la',
   (None, ('nom', 'op')): '/tmp/restemp.calypso_7967_2.nom.op.ynjjg7io',
   (None, ('nom', 'tran')): '/tmp/restemp.calypso_7967_2.nom.tran.0w17d3qc',
   (None, ('nom', 'translew')): '/tmp/restemp.calypso_7967_4.nom.translew.u5d0kmli'}


A call to :meth:`pyopus.evaluator.performance.PerformanceEvaluator.collectResultFiles` 
is made. This moves the result files from temporary storage on respective hosts to the 
current folder of the host that invoked the evaluator. The list of collected 
files is printed
	
.. code-block:: none

  Collected result files
  {('nom', 'ac'): 'res.nom.ac.pck',
   ('nom', 'accom'): 'res.nom.accom.pck',
   ('nom', 'acvdd'): 'res.nom.acvdd.pck',
   ('nom', 'acvss'): 'res.nom.acvss.pck',
   ('nom', 'blank'): 'res.nom.blank.pck',
   ('nom', 'dc'): 'res.nom.dc.pck',
   ('nom', 'noise'): 'res.nom.noise.pck',
   ('nom', 'op'): 'res.nom.op.pck',
   ('nom', 'tran'): 'res.nom.tran.pck',
   ('nom', 'translew'): 'res.nom.translew.pck'}

The file holding the environment in which the performance measures without 
an analysis were evaluated is loaded and the environment is printed

.. code-block:: none

  'blank' analysis measure evaluation environment
  {'isNmos': [1, 1, 1, 1, 1, 0, 0, 0],
   'm': <module 'pyopus.evaluator.measure' from '/home/arpadb/pytest/pyopus/evaluator/measure.py'>,
   'mosList': ['xmn1', 'xmn2', 'xmn3', 'xmn4', 'xmn5', 'xmp1', 'xmp2', 'xmp3'],
   'np': <module 'numpy' from '/usr/local/lib/python3.5/dist-packages/numpy/__init__.py'>,
   'param': {'c_out': 8.21e-12,
             'cload': 1e-12,
             'diff_l': 1.08e-06,
             'diff_w': 7.73e-06,
             'gu0nmm': 0.0,
             'gu0pmm': 0.0,
             'gvtnmm': 0.0,
             'gvtpmm': 0.0,
             'ibias': 0.0001,
             'lev1': -0.5,
             'lev2': 0.5,
             'load_l': 2.57e-06,
             'load_w': 3.49e-05,
             'mirr_l': 5.63e-07,
             'mirr_ld': 5.63e-07,
             'mirr_w': 7.46e-05,
             'mirr_wd': 7.46e-05,
             'mirr_wo': 7.46e-05,
             'mn1u0': 0.0,
             'mn1vt': 0.0,
             'mn2u0': 0.0,
             'mn2vt': 0.0,
             'mn3u0': 0.0,
             'mn3vt': 0.0,
             'mn4u0': 0.0,
             'mn4vt': 0.0,
             'mn5u0': 0.0,
             'mn5vt': 0.0,
             'mp1u0': 0.0,
             'mp1vt': 0.0,
             'mp2u0': 0.0,
             'mp2vt': 0.0,
             'mp3u0': 0.0,
             'mp3vt': 0.0,
             'out_l': 3.75e-07,
             'out_w': 4.8e-05,
             'pw': 1e-05,
             'r_out': 19.7,
             'rfb': 1000000.0,
             'rin': 1000000.0,
             'rload': 100000000.0,
             'temperature': 25,
             'tf': 1e-09,
             'tr': 1e-09,
             'tstart': 1e-05,
             'vdd': 1.8},
   'result': {'gain': {'nom': 66.24103484725208},
              'gain_com': {'nom': 8.276939732033867},
              'gain_vdd': {'nom': -26.235135394608754},
              'gain_vss': {'nom': 3.776680236411179},
              'in1kmn2': {'nom': 1.5814509234426575e-16},
              'in1kmn2id': {'nom': 1.5814509234426575e-16},
              'in1kmn2rd': {'nom': 0.0},
              'inoise1k': {'nom': 3.343611882428561e-14},
              'isup': {'nom': 0.0003009768725819436},
              'onoise1k': {'nom': 3.3371018439855986e-14},
              'out_op': {'nom': 0.00697923487611618},
              'overshdn': {'nom': 0.07176477049919334},
              'overshup': {'nom': 0.08923807202380866},
              'pm': {'nom': 70.04010745060916},
              'slewdn': {'nom': 10818342.824614132},
              'slewup': {'nom': 10059147.304855734},
              'swing': {'nom': 1.474471744100907},
              'tsetdn': {'nom': 1.9248788635101697e-07},
              'tsetup': {'nom': 2.0939194104629665e-07},
              'ugbw': {'nom': 6641299.6248098845},
              'vds_drv': {'nom': array([0.58454814, 0.8205568 , 0.433882  , 0.11164392, 0.826805  , 0.55567868, 0.32221448, 0.80172834])},
              'vgs_drv': {'nom': array([0.2121875 , 0.20869958, 0.02675759, 0.02674103, 0.02677769, 0.39175785, 0.39175785, 0.10679811])}}}	    

.. figure:: design-miller-init-nom-gain.png
	:scale: 80%
	
	Gain of the initial Miller amplifier in nominal corner.

Next, the file holding the waveforms produced by the ``ac`` analysis is 
loaded. The frequency scale and the gain in dB are extracted and plotted. 

The script cleans up all temporary files. Only the collected result files 
(.pck) remain on disk. 

If we start the script on multiple local CPUs with

.. code-block:: none

  mpirun -n 5 python3 01-evaluator.py
  
we can see that the evaluation runs faster because analyses are distributed
across multiple CPUs. The part of the output that lists the remotely stored 
result files changes to

.. code-block:: none

  Result files across hosts
  {(MPIHostID('calypso'), ('nom', 'ac')): '/tmp/restemp.calypso_7a50_1.nom.ac.r0hhsg4f',
   (MPIHostID('calypso'), ('nom', 'accom')): '/tmp/restemp.calypso_7a4e_1.nom.accom.advjsa_v',
   (MPIHostID('calypso'), ('nom', 'acvdd')): '/tmp/restemp.calypso_7a4e_1.nom.acvdd.9nz70aco',
   (MPIHostID('calypso'), ('nom', 'acvss')): '/tmp/restemp.calypso_7a4f_1.nom.acvss.5k4b2czs',
   (None, ('nom', 'blank')): '/tmp/restemp.calypso_7a4d_1.nom.blank.ny6qsqz3',
   (MPIHostID('calypso'), ('nom', 'dc')): '/tmp/restemp.calypso_7a50_1.nom.dc.5pe13zzs',
   (MPIHostID('calypso'), ('nom', 'noise')): '/tmp/restemp.calypso_7a50_1.nom.noise.d283cnzi',
   (MPIHostID('calypso'), ('nom', 'op')): '/tmp/restemp.calypso_7a50_1.nom.op.4lwpkitq',
   (MPIHostID('calypso'), ('nom', 'tran')): '/tmp/restemp.calypso_7a50_1.nom.tran.9jl8tkra',
   (MPIHostID('calypso'), ('nom', 'translew')): '/tmp/restemp.calypso_7a51_1.nom.translew.x0o3fm8o'}

  
We can see that only the ('nom', None) corner-analysis pair is stored locally 
because the corresponding performance measures were evaluated on the local machine 
(the one that invoked the evaluator). 

