• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Custom IC SKILL
  3. Calculating the std deviation and mean along the y axis...

Stats

  • Locked Locked
  • Replies 8
  • Subscribers 144
  • Views 20459
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Calculating the std deviation and mean along the y axis on a family of waveform

ericsu1220
ericsu1220 over 5 years ago

I have a family of waveform from ADE-XL runing monte carlo simulation with 10 runs plotting the inl of a DAC, the x axis is the code and the y axis is the inl in LSB.

I want to calculate the standard deviation and mean of the inl(along the yaxis) at a particular code(xaxis) and plot it into a single waveform like shown in the figure below. each code has the mean + standard deviation of 10 monte carlo runs

I tried the std function in the calculator but it seems to be taking all the waveforms and calculating the std along the xaxis into a single value, and convert the x axis to the monte carlo run which is not what I want.

Is it possible to use the calculator to calculate what I need? If not, what's an easier approach to plot what I need or if I need to write skill code?

My virtuoso version is IC6.1.7-64b.500.7 

Thanks,

  • Cancel
Parents
  • henker
    henker over 5 years ago

    The SwapSweep function from the calculator works fine to produce a waveform from values of all sweep elements, however it only processes a single x-value; it does not fully transpose sweep and x-values.

    As I assume that you want the statistics at all available x-values, you can try the attached script. It should be able to produce the waveforms you want. It is however only a fast hack, not really elegant and might also not work on every input. If you do not need the third and forth moments, you can also remove alot.
    Call from calculator with:
    icFamStat(<option> <list of waveforms or families>)

    You can fill in arbitrary waveforms and families, the first processed wave will determine the x-values and unit of the y-values.

    The function can be registered with the calculator using the fx button in the function panel (IC617 and later). It can then be found under "Custom function". A GUI builder is at the end, so the function will be available automtically when loaded appropriately.

    Example output:

    Fullscreen 4201.icFamStat.il.txt Download
    ;====================================================================
    ;; icFamStatCore
    ;; collect non-central moments of 1st..4th order
    ;====================================================================
    procedure( icFamStatCore(wave work)
    	let( (xVec yVec len y1 y2 y3 y4 N v p s)
    
    		xVec = drGetWaveformXVec(wave)
    		yVec = drGetWaveformYVec(wave)
    		len  = drVectorLength(xVec)
    
    		if( !work->xVec then
    			;; initialize
    						
    			y1= drCreateVec('double len)
    			y2= drCreateVec('double len)
    			y3= drCreateVec('double len)
    			y4= drCreateVec('double len)
    						
    			for(i 0 len-1
    				v = drGetElem(yVec i)
    
    				p = v
    				drAddElem(y1 p)
    				p = p*v
    				drAddElem(y2 p)
    				p = p*v
    				drAddElem(y3 p)
    				p = p*v
    				drAddElem(y4 p)
    			)
    			y1->units  = yVec->units
    			y1->name   = "mean"
    			y2->units  = yVec->units
    			y2->name   = "sqr"
    			y3->units  = yVec->units
    			y3->name   = "cub"
    			y4->units  = yVec->units
    			y4->name   = "quad"
    
    			work->xVec = xVec
    			work->y1   = y1
    			work->y2   = y2
    			work->y3   = y3
    			work->y4   = y4
    			work->N    = makeVector(len 1)
    			work->len  = len
    		else
    			when( xVec!=work->xVec
    				error("icFamStat: different x-axis in %L\n" wave)
    			)
    
    			for(i 0 len-1
    				v = drGetElem(yVec i)
    				when(v 
    					N = work->N[i] + 1
    					work->N[i] = N
    
    					p = v
    					;; recurrence formulae (mean of y)
    					s = drGetElem(work->y1 i)
    					s = s + (p - s) / float(N)
    					drSetElem(work->y1 i s)
    
    					p = p*v
    					;; recurrence formulae (mean of y^2)
    					s = drGetElem(work->y2 i)
    					s = s + (p - s) / float(N)
    					drSetElem(work->y2 i s)
    
    					p = p*v
    					;; recurrence formulae (mean of y^3)
    					s = drGetElem(work->y3 i)
    					s = s + (p - s) / float(N)
    					drSetElem(work->y3 i s)
    
    					p = p*v
    					;; recurrence formulae (mean of y^4)
    					s = drGetElem(work->y4 i)
    					s = s + (p - s) / float(N)
    					drSetElem(work->y4 i s)
    				)
    			)
    		); if
    	); let
    )
    ;====================================================================
    
    ;====================================================================
    ;; icFamStatHop
    ;; iterate over families, call core with single waveforms
    ;; collect data in work
    ;====================================================================
    procedure( icFamStatHop(wave work)
    	let( (wf)
    		cond(
    			( drIsWaveform(wave)
    				 icFamStatCore(wave work)
    			)
    			( famIsFamily(wave)
    				;; call self with all family members
    				foreach(sv famGetSweepValues(wave)
    					wf = famValue(wave sv)
    					icFamStatHop(wf work)
    				)
    			)
    			( t
    				error("icFamStat: cannot handle %L\n" wave)
    			)
    		); cond
    	); let
    )
    ;====================================================================
    
    ;====================================================================
    ;; icFamStat(type wave(s))
    ;; do statistic over a collection of waves/families
    ;====================================================================
    procedure( icFamStat(type @rest waves)
    	let( (work wf fm m v s k N scale)
    		work = ncons(nil)
    		
    		;; run over all input waveforms
    		foreach(wave waves
    			icFamStatHop(wave work)
    		)
    
    		;; build result from collected data
    		if( type=="non-central moments" then
    			;; EX + non-central moments EX^2, EX^3, EX^4
    			fm = famCreateFamily("statistics" 'string)
    			wf = drCreateWaveform(work->xVec work->y1)
    			famAddValue(fm "1st" wf)
    			wf = drCreateWaveform(work->xVec work->y2)
    			famAddValue(fm "2nd" wf)
    			wf = drCreateWaveform(work->xVec work->y3)
    			famAddValue(fm "3rd" wf)
    			wf = drCreateWaveform(work->xVec work->y4)
    			famAddValue(fm "4th" wf)
    
    		else
    			;; central/standardized moments
    			;; sigma^2 = variance = E(X^2-u^2) = E(X^2) - E(X)^2
    			;; skew     = E( ((X-u)/sigma)^3 ) = ( E(X^3) - 3*u*sigma^2 - u^3 ) / sigma^3
    			;; kurtosis = E( ((X-u)/sigma)^4 ) = (E(X^4) - 4*u*sigma^3*skew - 6*u^2*sigma^2 - u^4) / sigma^4
    
    			for(i 0 work->len-1
    
    				; for unbiased variance: rescale from 1/N to 1/N-1 
    				; better estimate for N>6, otherwise use biased variance
    				N = work->N[i]
    				scale = if(N<6 then 1.0 else N / float(N-1) )
    				
    				m = drGetElem(work->y1 i)
    				v = drGetElem(work->y2 i)
    				s = drGetElem(work->y3 i)
    				k = drGetElem(work->y4 i)
    
    				v = (v - m*m) * scale 
    				if( v<=0 then
    					v = 0
    					s = 0
    					k = 0
    				else
    					s = s - 3*m*v - m*m*m
    					k = k - 4*m*s - 6*m*m*v - m*m*m*m
    					
    					unless( type=="central moments"
    						v = sqrt(v)
    						s = s / (v*v*v)
    						k = k / (v*v*v*v)
    					)
    				)
    
    				drSetElem(work->y2 i v)
    				drSetElem(work->y3 i s)
    				drSetElem(work->y4 i k)
    			); for
    			
    			if( type=="central moments" then
    				work->y2->name  = "variance"
    				work->y3->name  = "u3"
    				work->y4->name  = "u4"
    			else
    				;; standardized moments
    				work->y2->name  = "stdev"
    				work->y3->name  = "skew"
    				work->y4->name  = "kurtosis"
    			)
    			
    			fm = famCreateFamily("statistics" 'string)
    			wf = drCreateWaveform(work->xVec work->y1)
    			famAddValue(fm work->y1->name wf)
    			wf = drCreateWaveform(work->xVec work->y2)
    			famAddValue(fm work->y2->name wf)
    			wf = drCreateWaveform(work->xVec work->y3)
    			famAddValue(fm work->y3->name wf)
    			wf = drCreateWaveform(work->xVec work->y4)
    			famAddValue(fm work->y4->name wf)
    		); if
    		fm
    	); let
    )
    ;====================================================================
    
    
    ;====================================================================
    ;; GUI builder information
    ;====================================================================
    ocnmRegGUIBuilder(
     '(nil
      function icFamStat
      name icFamStat
      description "Statistics over family graphs"
      category ("Custom Functions")
      analysis (nil
    	general (nil
    		args (type wave)
    		signals (nil
    			wave (nil
    				prompt "Signal"
    				tooltip "Signal"
    			)
    		)
    		params(nil
    			type (nil
    				prompt "type"
    				tooltip "statistics"
    				guiRowHint 1
    				default "standardized moments"
    				type (
    					"standardized moments"
    					"central moments"
    					"non-central moments"
    				)
    				required nil
    			)
    		)
    		inputrange t
    	)
      )
      outputs(result)
     )
    )
    ;====================================================================
    

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
Reply
  • henker
    henker over 5 years ago

    The SwapSweep function from the calculator works fine to produce a waveform from values of all sweep elements, however it only processes a single x-value; it does not fully transpose sweep and x-values.

    As I assume that you want the statistics at all available x-values, you can try the attached script. It should be able to produce the waveforms you want. It is however only a fast hack, not really elegant and might also not work on every input. If you do not need the third and forth moments, you can also remove alot.
    Call from calculator with:
    icFamStat(<option> <list of waveforms or families>)

    You can fill in arbitrary waveforms and families, the first processed wave will determine the x-values and unit of the y-values.

    The function can be registered with the calculator using the fx button in the function panel (IC617 and later). It can then be found under "Custom function". A GUI builder is at the end, so the function will be available automtically when loaded appropriately.

    Example output:

    Fullscreen 4201.icFamStat.il.txt Download
    ;====================================================================
    ;; icFamStatCore
    ;; collect non-central moments of 1st..4th order
    ;====================================================================
    procedure( icFamStatCore(wave work)
    	let( (xVec yVec len y1 y2 y3 y4 N v p s)
    
    		xVec = drGetWaveformXVec(wave)
    		yVec = drGetWaveformYVec(wave)
    		len  = drVectorLength(xVec)
    
    		if( !work->xVec then
    			;; initialize
    						
    			y1= drCreateVec('double len)
    			y2= drCreateVec('double len)
    			y3= drCreateVec('double len)
    			y4= drCreateVec('double len)
    						
    			for(i 0 len-1
    				v = drGetElem(yVec i)
    
    				p = v
    				drAddElem(y1 p)
    				p = p*v
    				drAddElem(y2 p)
    				p = p*v
    				drAddElem(y3 p)
    				p = p*v
    				drAddElem(y4 p)
    			)
    			y1->units  = yVec->units
    			y1->name   = "mean"
    			y2->units  = yVec->units
    			y2->name   = "sqr"
    			y3->units  = yVec->units
    			y3->name   = "cub"
    			y4->units  = yVec->units
    			y4->name   = "quad"
    
    			work->xVec = xVec
    			work->y1   = y1
    			work->y2   = y2
    			work->y3   = y3
    			work->y4   = y4
    			work->N    = makeVector(len 1)
    			work->len  = len
    		else
    			when( xVec!=work->xVec
    				error("icFamStat: different x-axis in %L\n" wave)
    			)
    
    			for(i 0 len-1
    				v = drGetElem(yVec i)
    				when(v 
    					N = work->N[i] + 1
    					work->N[i] = N
    
    					p = v
    					;; recurrence formulae (mean of y)
    					s = drGetElem(work->y1 i)
    					s = s + (p - s) / float(N)
    					drSetElem(work->y1 i s)
    
    					p = p*v
    					;; recurrence formulae (mean of y^2)
    					s = drGetElem(work->y2 i)
    					s = s + (p - s) / float(N)
    					drSetElem(work->y2 i s)
    
    					p = p*v
    					;; recurrence formulae (mean of y^3)
    					s = drGetElem(work->y3 i)
    					s = s + (p - s) / float(N)
    					drSetElem(work->y3 i s)
    
    					p = p*v
    					;; recurrence formulae (mean of y^4)
    					s = drGetElem(work->y4 i)
    					s = s + (p - s) / float(N)
    					drSetElem(work->y4 i s)
    				)
    			)
    		); if
    	); let
    )
    ;====================================================================
    
    ;====================================================================
    ;; icFamStatHop
    ;; iterate over families, call core with single waveforms
    ;; collect data in work
    ;====================================================================
    procedure( icFamStatHop(wave work)
    	let( (wf)
    		cond(
    			( drIsWaveform(wave)
    				 icFamStatCore(wave work)
    			)
    			( famIsFamily(wave)
    				;; call self with all family members
    				foreach(sv famGetSweepValues(wave)
    					wf = famValue(wave sv)
    					icFamStatHop(wf work)
    				)
    			)
    			( t
    				error("icFamStat: cannot handle %L\n" wave)
    			)
    		); cond
    	); let
    )
    ;====================================================================
    
    ;====================================================================
    ;; icFamStat(type wave(s))
    ;; do statistic over a collection of waves/families
    ;====================================================================
    procedure( icFamStat(type @rest waves)
    	let( (work wf fm m v s k N scale)
    		work = ncons(nil)
    		
    		;; run over all input waveforms
    		foreach(wave waves
    			icFamStatHop(wave work)
    		)
    
    		;; build result from collected data
    		if( type=="non-central moments" then
    			;; EX + non-central moments EX^2, EX^3, EX^4
    			fm = famCreateFamily("statistics" 'string)
    			wf = drCreateWaveform(work->xVec work->y1)
    			famAddValue(fm "1st" wf)
    			wf = drCreateWaveform(work->xVec work->y2)
    			famAddValue(fm "2nd" wf)
    			wf = drCreateWaveform(work->xVec work->y3)
    			famAddValue(fm "3rd" wf)
    			wf = drCreateWaveform(work->xVec work->y4)
    			famAddValue(fm "4th" wf)
    
    		else
    			;; central/standardized moments
    			;; sigma^2 = variance = E(X^2-u^2) = E(X^2) - E(X)^2
    			;; skew     = E( ((X-u)/sigma)^3 ) = ( E(X^3) - 3*u*sigma^2 - u^3 ) / sigma^3
    			;; kurtosis = E( ((X-u)/sigma)^4 ) = (E(X^4) - 4*u*sigma^3*skew - 6*u^2*sigma^2 - u^4) / sigma^4
    
    			for(i 0 work->len-1
    
    				; for unbiased variance: rescale from 1/N to 1/N-1 
    				; better estimate for N>6, otherwise use biased variance
    				N = work->N[i]
    				scale = if(N<6 then 1.0 else N / float(N-1) )
    				
    				m = drGetElem(work->y1 i)
    				v = drGetElem(work->y2 i)
    				s = drGetElem(work->y3 i)
    				k = drGetElem(work->y4 i)
    
    				v = (v - m*m) * scale 
    				if( v<=0 then
    					v = 0
    					s = 0
    					k = 0
    				else
    					s = s - 3*m*v - m*m*m
    					k = k - 4*m*s - 6*m*m*v - m*m*m*m
    					
    					unless( type=="central moments"
    						v = sqrt(v)
    						s = s / (v*v*v)
    						k = k / (v*v*v*v)
    					)
    				)
    
    				drSetElem(work->y2 i v)
    				drSetElem(work->y3 i s)
    				drSetElem(work->y4 i k)
    			); for
    			
    			if( type=="central moments" then
    				work->y2->name  = "variance"
    				work->y3->name  = "u3"
    				work->y4->name  = "u4"
    			else
    				;; standardized moments
    				work->y2->name  = "stdev"
    				work->y3->name  = "skew"
    				work->y4->name  = "kurtosis"
    			)
    			
    			fm = famCreateFamily("statistics" 'string)
    			wf = drCreateWaveform(work->xVec work->y1)
    			famAddValue(fm work->y1->name wf)
    			wf = drCreateWaveform(work->xVec work->y2)
    			famAddValue(fm work->y2->name wf)
    			wf = drCreateWaveform(work->xVec work->y3)
    			famAddValue(fm work->y3->name wf)
    			wf = drCreateWaveform(work->xVec work->y4)
    			famAddValue(fm work->y4->name wf)
    		); if
    		fm
    	); let
    )
    ;====================================================================
    
    
    ;====================================================================
    ;; GUI builder information
    ;====================================================================
    ocnmRegGUIBuilder(
     '(nil
      function icFamStat
      name icFamStat
      description "Statistics over family graphs"
      category ("Custom Functions")
      analysis (nil
    	general (nil
    		args (type wave)
    		signals (nil
    			wave (nil
    				prompt "Signal"
    				tooltip "Signal"
    			)
    		)
    		params(nil
    			type (nil
    				prompt "type"
    				tooltip "statistics"
    				guiRowHint 1
    				default "standardized moments"
    				type (
    					"standardized moments"
    					"central moments"
    					"non-central moments"
    				)
    				required nil
    			)
    		)
    		inputrange t
    	)
      )
      outputs(result)
     )
    )
    ;====================================================================
    

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
Children
  • ericsu1220
    ericsu1220 over 5 years ago in reply to henker

    Hi henker:

    Thanks for the code, it works.
    Just have a quick question on <list of waveforms or families> for icFamStat(<option> <list of waveforms or families>)

    Currently I have 4 corner runs with 200 monte carlo runs, I only want to process the list of waveforms on C0_0 column shown in the red box.
    However if I use icFamStat("standardized moments" inlEndpoint(iout_sink)) in the calculator, I feel like it's processing all the corners shown in the blue box.
    Is there a way to know which kind of waveforms i'm processing? How do I force the waveform group in a single column like the red box? I'm not familiar with the difference of list of waveforms or families.
    Of course a workaround is just to have 1 corner simulation for the monte carlo run to make sure it's getting the correct list of waveform and use the function but it's a bit tiresome.

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel
  • henker
    henker over 5 years ago in reply to ericsu1220

    You can limit a multidimentional sweep  to a subset by using leafValue. Application is basically:
    leafValue(<sweep bundle> <parameter name> <parameter value> ...)

    You can find the actual documentation in the Virtuoso Visualization and Analysis XL manual.

    However, the most easy way to get the proper naming is to plot your complete sweep, then rightclick a single wave in the waveform viewer (preferably one which you want to include in the subset) and choose "send to calculator". There you get the full expression to select this single wave out of the sweep. From this you can remove the unnecessary parameter restrictions to construct your desired subset.
    Plotting this expression as is will also show you what waves the icFamStat will be working on when passed to it.

    Additionally, you can also add the single waveforms one by one as list in the icFamStat call, so you can also calculate on parts of the actual sweep, but be aware that multiple entries of the same wave is not checked, these then just get higher weight in the calculation.

    • Cancel
    • Vote Up +1 Vote Down
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information