blob: 92d38b4949f4ddb74ba37eeed23847fccef111c9 [file] [log] [blame]
"""
Usage:
models_regression.py [--num_cores=<num>]
-h, --help Show help text.
-v, --version Show version.
--num_cores=<num> Number of cores to be used by simulator
"""
from fileinput import filename
from re import T
from docopt import docopt
import pandas as pd
import numpy as np
import os
from jinja2 import Template
import concurrent.futures
import shutil
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)
def call_simulator(file_name):
"""Call simulation commands to perform simulation.
Args:
file_name (str): Netlist file name.
"""
os.system(f"Xyce -hspice-ext all {file_name} -l {file_name}.log")
def ext_measured_a(device,vn,d_in, r_sim, corner):
# Get dimensions used for each device
dirpath = f"{device}_{r_sim}_{corner}"
dimensions = pd.read_csv(f"{dirpath}/{device}.csv",usecols=["w (um)" , "l (um)"])
loops = dimensions["l (um)"].count()
# Extracting measured values for each W & L
for i in range (0,loops):
width = dimensions["w (um)"].iloc[i]
length = dimensions["l (um)"].iloc[i]
# measured r
col_list = [f"{vn}",f"{d_in}_{corner} Rev9 "]
df_measured = pd.read_csv(f"{dirpath}/{device}.csv",usecols=col_list)
df_measured.columns = [f"{vn}","value"]
df_measured.loc[i:i].to_csv(f"{dirpath}/measured_{r_sim}/{i}_measured_w{width}_l{length}.csv", index=False)
def ext_measured_b(device,vn,d_in, r_sim, corner):
# Get dimensions used for each device
dirpath = f"{device}_{r_sim}_{corner}_temp"
dimensions = pd.read_csv(f"{dirpath}/{device}.csv",usecols=["Temperature (C)" , "l (um)"])
if "rm" in device or "tm" in device:
loops = dimensions["l (um)"].count()
else:
loops = 11
# Extracting measured values for each W & L
for i in range (0,loops):
temp = dimensions["Temperature (C)"].iloc[i]
length = dimensions["l (um)"].iloc[i]
if "rm" in device or "tm" in device or "_u" in device:
width = length
else:
width = length/2
# measured r
col_list = [f"{vn}",f"{d_in}_{corner} Rev9 "]
df_measured = pd.read_csv(f"{dirpath}/{device}.csv",usecols=col_list)
df_measured.columns = [f"{vn}","value"]
df_measured.loc[i:i].to_csv(f"{dirpath}/measured_{r_sim}/{i}_measured_w{width}_l{length}.csv", index=False)
def ext_simulated_a(device,vn,d_in,r_sim, corner,sign):
if "rm" in device or "tm" in device:
netlist_tmp = f"./device_netlists/2term_res_a.spice"
else:
netlist_tmp = f"./device_netlists/3term_res_a.spice"
# Get dimensions used for each device
dirpath = f"{device}_{r_sim}_{corner}"
dimensions = pd.read_csv(f"{dirpath}/{device}.csv",usecols=["w (um)" , "l (um)"])
loops = dimensions["l (um)"].count()
temp = 25
# Extracting measured values for each W & L
for i in range (0,loops):
width = dimensions["w (um)"].iloc[i]
length = dimensions["l (um)"].iloc[i]
with open(netlist_tmp) as f:
tmpl = Template(f.read())
os.makedirs(f"{dirpath}/{device}_netlists_{r_sim}",exist_ok=True)
with open(f"{dirpath}/{device}_netlists_{r_sim}/{i}_{device}_netlist_w{width}_l{length}.spice", "w") as netlist:
netlist.write(tmpl.render(device = device, width = width, length = length , corner = corner, i = i , sign = sign))
netlist_path = f"{dirpath}/{device}_netlists_{r_sim}/{i}_{device}_netlist_w{width}_l{length}.spice"
# Running ngspice for each netlist
with concurrent.futures.ProcessPoolExecutor(max_workers=workers_count) as executor:
executor.submit(call_simulator, netlist_path)
# Writing simulated data
df_simulated = pd.read_csv(f"{dirpath}/simulated_r/{i}_simulated_w{width}_l{length}.csv",header=0)
# df_simulated.to_csv(f"{dirpath}/simulated_r/{i}_simulated_w{width}_l{length}.csv",index= False)
# Writing final simulated data
df_simulated.columns = [f"value"]#,"value"]
df_simulated.to_csv(f"{dirpath}/simulated_r/{i}_simulated_w{width}_l{length}.csv",index= False)
def ext_simulated_b(device,vn,d_in,r_sim, corner,sign):
if "rm" in device or "tm" in device:
netlist_tmp = f"./device_netlists/2term_res_b.spice"
else:
netlist_tmp = f"./device_netlists/3term_res_b.spice"
# Get dimensions used for each device
dirpath = f"{device}_{r_sim}_{corner}_temp"
dimensions = pd.read_csv(f"{dirpath}/{device}.csv",usecols=["Temperature (C)" , "l (um)"])
if "rm" in device or "tm" in device:
loops = dimensions["l (um)"].count()
else:
loops = 11
# Extracting measured values for each W & L
for i in range (0,loops):
temp = dimensions["Temperature (C)"].iloc[i]
length = dimensions["l (um)"].iloc[i]
if "rm" in device or "tm" in device or "_u" in device:
width = length
else:
width = length/2
with open(netlist_tmp) as f:
tmpl = Template(f.read())
os.makedirs(f"{dirpath}/{device}_netlists_{r_sim}",exist_ok=True)
with open(f"{dirpath}/{device}_netlists_{r_sim}/{i}_{device}_netlist_w{width}_l{length}.spice", "w") as netlist:
netlist.write(tmpl.render(device = device, temp = temp , width = width, length = length , corner = corner, i = i , sign = sign))
netlist_path = f"{dirpath}/{device}_netlists_{r_sim}/{i}_{device}_netlist_w{width}_l{length}.spice"
# Running ngspice for each netlist
with concurrent.futures.ProcessPoolExecutor(max_workers=workers_count) as executor:
executor.submit(call_simulator, netlist_path)
# Writing simulated data
df_simulated = pd.read_csv(f"{dirpath}/simulated_r/{i}_simulated_w{width}_l{length}.csv",header=0)
df_simulated.to_csv(f"{dirpath}/simulated_r/{i}_simulated_w{width}_l{length}.csv",index= False)
# Writing final simulated data
df_simulated.columns = [f"value"]#,"value"]
df_simulated.to_csv(f"{dirpath}/simulated_r/{i}_simulated_w{width}_l{length}.csv",index= False)
def error_cal_a(device,vn,d_in,r_sim, corner):
df_final = pd.DataFrame()
# Get dimensions used for each device
dirpath = f"{device}_{r_sim}_{corner}"
dimensions = pd.read_csv(f"{dirpath}/{device}.csv",usecols=["w (um)" , "l (um)"])
loops = dimensions["l (um)"].count()
temp = 25
# Extracting measured values for each W & L
for i in range (0,loops):
width = dimensions["w (um)"].iloc[i]
length = dimensions["l (um)"].iloc[i]
measured = pd.read_csv(f"{dirpath}/measured_{r_sim}/{i}_measured_w{width}_l{length}.csv")
simulated = pd.read_csv(f"{dirpath}/simulated_{r_sim}/{i}_simulated_w{width}_l{length}.csv")
error_1 = round (100 * abs((abs(measured.iloc[:, 1]) - abs(simulated.iloc[:, 0]))/abs(measured.iloc[:, 1])),8)
df_error = pd.DataFrame(data=[measured.iloc[:, 0],error_1]).transpose()
df_error.to_csv(f"{dirpath}/error_{r_sim}/{i}_{device}_error_w{width}_l{length}.csv",index= False)
# Mean error
mean_error = (df_error[f"value"].mean())
# Max error
max_error = df_error[f"value"].max()
df_final_ = {'Run no.': f'{i}', 'Device name': f'{dirpath}', 'Temperature': temp, 'Width': f'{width}', 'Length': f'{length}', 'Simulated_Val':f'{r_sim}','Mean error%':f'{"{:.2f}".format(mean_error)}', 'Max error%':f'{"{:.2f}".format(max_error)} '}
df_final = df_final.append(df_final_, ignore_index = True)
# Max mean error
print (df_final)
df_final.to_csv (f"{dirpath}/Final_report_{r_sim}.csv", index = False)
out_report = pd.read_csv (f"{dirpath}/Final_report_{r_sim}.csv")
print ("\n",f"Max. mean error = {out_report['Mean error%'].max()}%")
print ("=====================================================================================================================================================")
def error_cal_b(device,vn,d_in,r_sim, corner):
df_final = pd.DataFrame()
# Get dimensions used for each device
dirpath = f"{device}_{r_sim}_{corner}_temp"
dimensions = pd.read_csv(f"{dirpath}/{device}.csv",usecols=["Temperature (C)" , "l (um)"])
if "rm" in device or "tm" in device:
loops = dimensions["l (um)"].count()
else:
loops = 11
# Extracting measured values for each W & L
for i in range (0,loops):
temp = dimensions["Temperature (C)"].iloc[i]
length = dimensions["l (um)"].iloc[i]
if "rm" in device or "tm" in device or "_u" in device:
width = length
else:
width = length/2
measured = pd.read_csv(f"{dirpath}/measured_{r_sim}/{i}_measured_w{width}_l{length}.csv")
simulated = pd.read_csv(f"{dirpath}/simulated_{r_sim}/{i}_simulated_w{width}_l{length}.csv")
error_1 = round (100 * abs((abs(measured.iloc[:, 1]) - abs(simulated.iloc[:, 0]))/abs(measured.iloc[:, 1])),8)
df_error = pd.DataFrame(data=[measured.iloc[:, 0],error_1]).transpose()
df_error.to_csv(f"{dirpath}/error_{r_sim}/{i}_{device}_error_w{width}_l{length}.csv",index= False)
# Mean error
mean_error = (df_error[f"value"].mean())
# Max error
max_error = df_error[f"value"].max()
df_final_ = {'Run no.': f'{i}', 'Device name': f'{dirpath}', 'Temperature': temp, 'Width': f'{width}', 'Length': f'{length}', 'Simulated_Val':f'{r_sim}','Mean error%':f'{"{:.2f}".format(mean_error)}', 'Max error%':f'{"{:.2f}".format(max_error)} '}
df_final = df_final.append(df_final_, ignore_index = True)
# Max mean error
print (df_final)
df_final.to_csv (f"{dirpath}/Final_report_{r_sim}.csv", index = False)
out_report = pd.read_csv (f"{dirpath}/Final_report_{r_sim}.csv")
print ("\n",f"Max. mean error = {out_report['Mean error%'].max()}%")
print ("=====================================================================================================================================================")
def main():
# res W&L var.
corners_a = ["typical","ff","ss"]
devices_a = ["nplus_u" , "pplus_u" , "nplus_s" , "pplus_s" , "npolyf_u" , "ppolyf_u" , "npolyf_s" , "ppolyf_s" , "ppolyf_u_1k" , "ppolyf_u_2k" , "ppolyf_u_1k_6p0" ,
"ppolyf_u_2k_6p0" , "ppolyf_u_3k" , "rm1" , "rm2" , "rm3" , "tm6k" , "tm9k" , "tm11k" , "tm30k" , "nwell"]
dev_data_a = ["RES01a-wl-nplus_u.nl_out" ,"RES02a-wl-pplus_u.nl_out" ,"RES03a-wl-nplus_s.nl_out" , "RES04a-wl-pplus_s.nl_out" ,
"RES06a-wl-npolyf_u.nl_out" ,"RES07a-wl-ppolyf_u.nl_out" ,"RES08a-wl-npolyf_s.nl_out" , "RES09a-wl-ppolyf_s.nl_out" , "RES10a-wl-ppolyf_u_1k.nl_out",
"RES11a-wl-ppolyf_u_2k.nl_out" ,"RES12a-wl-ppolyf_u_1k_6p0.nl_o" ,"RES13a-wl-ppolyf_u_2k_6p0.nl_o" , "RES14a-wl-ppolyf_u_3k.nl_out" ,
"RES15a-wl-rm1.nl_out" , "RES16a-wl-rm2.nl_out" , "RES17a-wl-rm3.nl_out" , "RES18a-wl-tm6k.nl_out" , "RES19a-wl-tm9k.nl_out" ,
"RES20a-wl-tm11k.nl_out" , "RES21a-wl-tm30k.nl_out" ,"RES05a-wl-nwell.nl_out"]
sign_a = ["+" , "-" , "+" , "-" , "+" , "+" , "-" , "+" , "-" , "-" , "-" , "-" , "-" , "-" , "+" , "+" , "+" , "+" , "+" , "+", "+", ""]
measure_a = ["r","corners", "res"]
for corner in corners_a:
for i,device in enumerate(devices_a):
# Folder structure of measured values
r_sim, res_vn, res_in = measure_a[0], measure_a[1], measure_a[2]
dirpath = f"{device}_{r_sim}_{corner}"
if os.path.exists(dirpath) and os.path.isdir(dirpath):
shutil.rmtree(dirpath)
os.makedirs(f"{dirpath}/measured_{r_sim}",exist_ok=False)
# From xlsx to csv
read_file = pd.read_excel (f"../../180MCU_SPICE_DATA/Resistor/{dev_data_a[i]}.xlsx")
read_file.to_csv (f"{dirpath}/{device}.csv", index = False, header=True)
# Folder structure of simulated values
os.makedirs(f"{dirpath}/simulated_{r_sim}",exist_ok=False)
os.makedirs(f"{dirpath}/error_{r_sim}",exist_ok=False)
ext_measured_a (device,res_vn,res_in, r_sim, corner)
ext_simulated_a(device,res_vn,res_in,r_sim, corner,sign_a[i])
error_cal_a (device,res_vn,res_in,r_sim, corner)
# res temp_var
corners_b = ["typical","ff","ss"]
devices_b = ["nplus_u" , "nplus_s", "pplus_u" , "pplus_s" , "nwell" , "npolyf_u" , "ppolyf_u" , "npolyf_s" , "ppolyf_s" , "ppolyf_u_1k" , "ppolyf_u_2k" , "ppolyf_u_1k_6p0" , "ppolyf_u_2k_6p0" , "ppolyf_u_3k" ,
"rm1" , "rm2", "rm3" , "tm6k" , "tm9k" , "tm11k", "tm30k"]
dev_data_b = ["RES01b-temp-nplus_u.nl_out" , "RES03b-temp-nplus_s.nl_out", "RES02b-temp-pplus_u.nl_out" , "RES04b-temp-pplus_s.nl_out" , "RES05b-temp-nwell.nl_out" ,
"RES06b-temp-npolyf_u.nl_out" , "RES07b-temp-ppolyf_u.nl_out" , "RES08b-temp-npolyf_s.nl_out" , "RES09b-temp-ppolyf_s.nl_out" , "RES10b-temp-ppolyf_u_1k.nl_out" ,
"RES11b-temp-ppolyf_u_2k.nl_out" , "RES12b-temp-ppolyf_u_1k_6p0.nl" , "RES13b-temp-ppolyf_u_2k_6p0.nl" , "RES14b-temp-ppolyf_u_3k.nl_out" ,
"RES15b-temp-rm1.nl_out", "RES16b-temp-rm2.nl_out" , "RES17b-temp-rm3.nl_out" ,
"RES18b-temp-tm6k.nl_out", "RES19b-temp-tm9k.nl_out" , "RES20b-temp-tm11k.nl_out", "RES21b-temp-tm30k.nl_out"]
sign_b = ["+" , "+", "-" , "-" , "+" , "+" , "-" ,"+" , "-" , "-" , "-" , "-" , "-" , "-" , "+" , "+" , "+" , "+" , "+" , "+", "+"]
measure_b = ["r","corners", "res"]
for corner in corners_b:
for i,device in enumerate(devices_b):
# Folder structure of measured values
r_sim, res_vn, res_in = measure_b[0], measure_b[1], measure_b[2]
dirpath = f"{device}_{r_sim}_{corner}_temp"
if os.path.exists(dirpath) and os.path.isdir(dirpath):
shutil.rmtree(dirpath)
os.makedirs(f"{dirpath}/measured_{r_sim}",exist_ok=False)
# From xlsx to csv
read_file = pd.read_excel (f"../../180MCU_SPICE_DATA/Resistor/{dev_data_b[i]}.xlsx")
read_file.to_csv (f"{dirpath}/{device}.csv", index = False, header=True)
# Folder structure of simulated values
os.makedirs(f"{dirpath}/simulated_{r_sim}",exist_ok=False)
os.makedirs(f"{dirpath}/error_{r_sim}",exist_ok=False)
ext_measured_b (device,res_vn,res_in, r_sim, corner)
ext_simulated_b(device,res_vn,res_in,r_sim, corner,sign_b[i])
error_cal_b (device,res_vn,res_in,r_sim, corner)
for corner in corners_a:
for i,device in enumerate(devices_a):
# Folder structure of measured values
r_sim, res_vn, res_in = measure_a[0], measure_a[1], measure_a[2]
error_cal_a (device,res_vn,res_in,r_sim, corner)
for corner in corners_b:
for i,device in enumerate(devices_b):
# Folder structure of measured values
r_sim, res_vn, res_in = measure_b[0], measure_b[1], measure_b[2]
error_cal_b (device,res_vn,res_in,r_sim, corner)
# # ================================================================
# -------------------------- MAIN --------------------------------
# ================================================================
if __name__ == "__main__":
# Args
arguments = docopt(__doc__, version='comparator: 0.1')
workers_count = os.cpu_count()*2 if arguments["--num_cores"] == None else int(arguments["--num_cores"])
# Calling main function
main()