Examples¶
This wrapper lets us run any ADE-L simulation from Python. This enables us to run multiple algorithms, AI/ML models and optimization techniques native to Python by encapsulating the ADE-L simulation as a function call with a return value. The use cases are:
Running multiple simulations with different parameters
Storing the results of the simulation in a structured format or directly loading into Python variables/arrays
Run AI/ML algorithms by using the simulation as just an objective function in Python
Allows for the use of various Python libraries for data analysis and visualization on the simulation results
This wrapper allows us to run simulations in jupyter notebooks and other Python environments
The following examples demonstrate how to use the PyCadence wrapper to run simulations from Python.
Example 1: Running a Monte Carlo simulation¶
Consider a simple setup for a Monte Carlo simulation observing the phasenoise of a LC tank oscillator. The template ocn file generated is as follows.
simulator( 'spectre )
design( "/home/ABC/simulation/lc_tank_oscillator/spectre/schematic/netlist/netlist")
resultsDir( "/home/ABC/simulation/lc_tank_oscillator/spectre/schematic" )
modelFile(
'Some model files
)
analysis('pss ?fund "2.4G" ?harms "5" ?errpreset "conservative"
?oscana t ?p "/net017" ?n "/net3" ?oscic "lin"
?ppv "" )
analysis('pnoise ?relharmnum "1" ?start "10" ?stop "1M"
?p "/net017" ?n "/net3" ?oprobe "" ?noisetype "timeaverage"
?noiseout list("usb") ?noisetypeUI "" ?osc_version "" ?osc_accuracy ""
?ppv "" )
desVar( "C" {value}p ) # {value} is the placeholder for the value to be substituted
desVar( "L" {value}n )
desVar( "W1" {value}u )
desVar( "W2" {value}u )
desVar( "W3" {value}u )
desVar( "W4" {value}u )
desVar( "W5" {value}u )
envOption(
'analysisOrder list("pss" "pnoise")
)
temp( 27 )
run()
phsns = db20((getData("out" ?resultsDir "/home/joelthomas/simulation/lc_tank_oscillator/spectre/schematic" ?result "pnoise") / complex(0.000279621 -0.000983934)))
ocnPrint( ?output {output_log_path} phsns ?numSpaces 1 ?numberNotation 'scientific) # {output_log_path} is the placeholder to be used. It will automtically insert the 'output_file' argument passed in th simulate() function.
The following Python code demonstrates how to run the simulation using the PyCadence wrapper. Note: it is just an example implementation.
from pycadence.pycadence import Connector
import numpy as np
p = Connector(screen_name="session1")
def generate_monte_carlo_samples( N, X):
'''
Function to generate monte carlo samples
--------------------------------
N: int
number of samples to generate
X: list
list of default values of design variables
'''
lower_bound = X - 0.1*X
upper_bound = X + 0.1*X
samples=[]
for i in range(len(lower_bound)):
samples.append(np.random.uniform(lower_bound[i],upper_bound[i],N)) # Assumed variance of 10% of the mean
samples=np.array(samples)
return samples.T
def outputReader(output_log_path):
'''
Helper function to parse the output file and return the data. Customize this as per need with reference to the output file format.
The default implementation can be found Connector().read_output()
--------------------------------
output_log_path: str
path to the output file
'''
with open(output_log_path, 'r+') as fp:
# read an store all lines into list
lines = fp.readlines()
data=[]
for line in lines[2:]:
try:
temp = line.strip().split(" ")
# print(temp)
data.append([float(temp[0]),float(temp[-1])])
except Exception as e:
# print("Error in reading output file")
# print(e)
pass
data = np.array(data)
return data
def objective_function(x):
'''
Objective function to be optimized
--------------------------------
x: list
list of values to be passed to the simulation
'''
default = [0.1, 0.1, 0.1, 0.1, 0.1] # some default values
data = p.simulate(x,default, "init.ocn", "monte_simulation.ocn", "output.txt", read_output = outputReader)
return data[54][1] # I am only interested in the 55th data point not the whole series. Note: This is just an example
if __name__ == "__main__":
N = 1000 # number of samples
X = [0.1, 0.1, 0.1, 0.1, 0.1] # default values of design variables
samples = generate_monte_carlo_samples(N, X)
evaluations = []
for sample in samples:
evaluations.append(objective_function(sample))
evaluations = np.array(evaluations)
print(evaluations)
print("Mean: ", np.mean(evaluations))
print("Variance: ", np.var(evaluations))
print("Standard Deviation: ", np.std(evaluations))
print("Max: ", np.max(evaluations))
print("Min: ", np.min(evaluations))