# Monte Carlo verification of yiled

from definitions import *
from pyopus.design.mc import MonteCarlo
from pyopus.design.wc import WorstCase
from pyopus.design.wcd import WorstCaseDistance
from pyopus.evaluator.aggregate import formatParameters
# If MPI is imported an application not using MPI will behave correctly
# (i.e. only slot 0 will run the program) even when started with mpirun/mpiexec
from pyopus.parallel.mpi import MPI
from pyopus.parallel.cooperative import cOS
import sys

# Script arguments 
#   noop computes worst case without operating parameters (assumed initial values)

if __name__=='__main__':
	# Result of yield targeting
	atDesign={
		# Before yield targetting
		#   'c_out':   3.4227551453164880e-13, 
		#  'diff_l':   7.4308192182875534e-07, 
		#  'diff_w':   1.2789110397149770e-06, 
		#  'load_l':   2.1097689639936013e-06, 
		#  'load_w':   2.3180449555941561e-06, 
		#  'mirr_l':   4.0529113121872304e-07, 
		# 'mirr_ld':   1.3311984218957902e-06, 
		#  'mirr_w':   3.4036562767439648e-05, 
		# 'mirr_wd':   2.3745920801687639e-06, 
		# 'mirr_wo':   2.1285465666785311e-05, 
		#   'out_l':   5.3631175887258056e-07, 
		#   'out_w':   2.6406246699146450e-05, 
		#   'r_out':   3.0372450962642072e+00, 

		# After yield targetting (beta=3)
		   'c_out':   6.5735996965011167e-13, 
		  'diff_l':   1.1277590722388212e-06, 
		  'diff_w':   7.4072078256213562e-06, 
		  'load_l':   3.0190507158551772e-06, 
		  'load_w':   7.1447511221840934e-06, 
		  'mirr_l':   3.0463894159204191e-07, 
		 'mirr_ld':   2.6572354878028799e-06, 
		  'mirr_w':   1.7060021214780366e-05, 
		 'mirr_wd':   4.1333975797905747e-06, 
		 'mirr_wo':   2.6823400824029106e-05, 
		   'out_l':   3.2878440134599452e-07, 
		   'out_w':   1.5489295777951712e-05, 
		   'r_out':   3.5673408168082747e+03, 
	}
	
	# Worst case performances (skip area, transistor op conditions, and auxiliary measures)
	wcList=list(measures.keys())
	wcList.sort()
	wcList.remove('area')
	wcList.remove('vgs_drv')
	wcList.remove('vds_drv')
	wcList.remove('gain_com')
	wcList.remove('gain_vdd')
	wcList.remove('gain_vss')
	wcList.remove('ph_slope')
	
	# Prepare parallel environment
	cOS.setVM(MPI(mirrorMap={'*':'.'}))

	# Set up a corner
	corners={
		'mc': {
			'params': {}, 
			'modules': [ 'mc' ]
		},
	}

	if len(sys.argv)>1 and sys.argv[1]=="noop":
		# No operating parameters
		corners['mc']['params'].update({
			name: v['init'] for name, v in opParams.items()
		})
		opParams = {}
	
	# Verify yield with Monte-Carlo 
	mc=MonteCarlo(
		heads, analyses, measures, corners, 
		statParams, opParams, atDesign, 
		variables=variables, debug=2, 
		nSamples=10000, 
		spawnerLevel=1, 
		wcOptions={'evaluatorOptions': {'debug': 0}}
	)
	results, anCount = mc(wcList)
	print(mc.formatResults())
	print(anCount)
	
	# Verify yield with worst case distances
	# wcd=WorstCaseDistance(
	# 	heads, analyses, measures, statParams, opParams, variables=variables, 
	# 	fixedParams=atDesign, 
	# 	debug=1, 
	# 	spawnerLevel=1
	# )
	# res, anCount = wcd(wcList)
	# print(wcd.formatResults())
	# print(anCount)
	
	# Verify yield with worst case analysis
	#wc=WorstCase(
	#	heads, analyses, measures, statParams, opParams, variables=variables, 
	#	fixedParams=atDesign, beta=3.0, 
	#	debug=1, 
	#	spawnerLevel=1
	#)
	#res, anCount = wc(wcList)
	#print(wc.formatResults())
	#print(anCount)
	
	# Finalize cOS parallel environment
	cOS.finalize()

	# Result, before yield targetting, nominal operating point parameters
	#       cmrr >    6.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#       gain >    6.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#       isup <    1.00000e-03 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     out_op <    1.25000e-02 yield=   8.00900e-01 = 1-   1.99100e-01 feasible=8009 failed=   0
	#     out_op >   -1.25000e-02 yield=   9.25500e-01 = 1-   7.45000e-02 feasible=9255 failed=   0
	#   overshdn <    1.50000e-01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#   overshup <    1.50000e-01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#         pm >    5.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#   psrr_vdd >    6.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#   psrr_vss >    6.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     slewdn >    2.00000e+06 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     slewup >    2.00000e+06 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#      swing >    1.00000e+00 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     tsetdn <    1.00000e-06 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     tsetup <    1.00000e-06 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#       ugbw >    1.00000e+07 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	# 
	# total yield=   7.26400e-01 = 1-   2.73600e-01
	#
	# Result, after yield targetting (beta=3), nominal operating point parameters
	#       cmrr >    6.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#       gain >    6.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#       isup <    1.00000e-03 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     out_op <    1.25000e-02 yield=   9.99500e-01 = 1-   5.00000e-04 feasible=9995 failed=   0
	#     out_op >   -1.25000e-02 yield=   9.99500e-01 = 1-   5.00000e-04 feasible=9995 failed=   0
	#   overshdn <    1.50000e-01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#   overshup <    1.50000e-01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#         pm >    5.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#   psrr_vdd >    6.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#   psrr_vss >    6.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     slewdn >    2.00000e+06 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     slewup >    2.00000e+06 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#      swing >    1.00000e+00 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     tsetdn <    1.00000e-06 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     tsetup <    1.00000e-06 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#       ugbw >    1.00000e+07 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	# 
	# total yield=   9.99000e-01 = 1-   1.00000e-03
	#
	# Result, after yield targetting (beta=3)
	# 	    cmrr >    6.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#       gain >    6.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#       isup <    1.00000e-03 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     out_op <    1.25000e-02 yield=   9.99400e-01 = 1-   6.00000e-04 feasible=9994 failed=   0
	#     out_op >   -1.25000e-02 yield=   9.99500e-01 = 1-   5.00000e-04 feasible=9995 failed=   0
	#   overshdn <    1.50000e-01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#   overshup <    1.50000e-01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#         pm >    5.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#   psrr_vdd >    6.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#   psrr_vss >    6.00000e+01 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     slewdn >    2.00000e+06 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     slewup >    2.00000e+06 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#      swing >    1.00000e+00 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     tsetdn <    1.00000e-06 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#     tsetup <    1.00000e-06 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	#       ugbw >    1.00000e+07 yield=   1.00000e+00 = 1-   0.00000e+00 feasible=10000 failed=   0
	# 
	# total yield=   9.98900e-01 = 1-   1.10000e-03
