Skip to content

Commit 48cdbb5

Browse files
Merge pull request google#72 from mabrains/ngspice_regression
Ngspice regression
2 parents 0d645fc + 811758b commit 48cdbb5

File tree

98 files changed

+1915
-4099
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+1915
-4099
lines changed

models/ngspice/testing/Makefile

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ Add_run-dir:
4444
smoke-test:
4545
@echo "========== Runing models_xyce SMOKE TEST regression =========="
4646
@cd $(Testing_DIR)/smoke_test
47-
@python3 ng_smoke_test.py
4847

4948
#================================
5049
# ---------- models-MOS----------
@@ -60,7 +59,6 @@ models-MOS-vgs:Add_run-dir
6059
@cd $(Testing_DIR)/$(run_folder)/mos_iv_vgs
6160
@echo "========== Runing models_ngspice-MOS-VGS regression ==========" |& tee -a ../run_log.log
6261
@python3 models_regression.py |& tee -a ../run_log.log
63-
@python3 plotting.py
6462

6563
.ONESHELL:
6664
models-MOS-vbs:Add_run-dir
@@ -69,7 +67,6 @@ models-MOS-vbs:Add_run-dir
6967
@cd $(Testing_DIR)/$(run_folder)/mos_iv_vbs
7068
@echo "========== Runing models_ngspice-MOS-VBS regression ==========" |& tee -a ../run_log.log
7169
@python3 models_regression.py |& tee -a ../run_log.log
72-
@python3 plotting.py
7370

7471
.ONESHELL:
7572
models-MOS-cv:Add_run-dir
@@ -78,7 +75,6 @@ models-MOS-cv:Add_run-dir
7875
@cd $(Testing_DIR)/$(run_folder)/mos_cv
7976
@echo "========== Runing models_ngspice-MOS-CV regression ==========" |& tee -a ../run_log.log
8077
@python3 models_regression.py |& tee -a ../run_log.log
81-
@python3 plotting.py
8278

8379
#================================
8480
# ---------- models-BJT----------
@@ -94,7 +90,6 @@ models-BJT-cj:Add_run-dir
9490
@cd $(Testing_DIR)/$(run_folder)/bjt_cj
9591
@echo "========== Runing models_ngspice-BJT-cj regression ==========" |& tee -a ../run_log.log
9692
@python3 models_regression.py |& tee -a ../run_log.log
97-
@python3 plotting.py
9893

9994
.ONESHELL:
10095
models-BJT-beta:Add_run-dir
@@ -103,7 +98,6 @@ models-BJT-beta:Add_run-dir
10398
@cd $(Testing_DIR)/$(run_folder)/bjt_beta
10499
@echo "========== Runing models_ngspice-BJT-beta regression ==========" |& tee -a ../run_log.log
105100
@python3 models_regression.py |& tee -a ../run_log.log
106-
@python3 plotting.py
107101

108102
.ONESHELL:
109103
models-BJT-iv:Add_run-dir
@@ -112,7 +106,6 @@ models-BJT-iv:Add_run-dir
112106
@cd $(Testing_DIR)/$(run_folder)/bjt_iv
113107
@echo "========== Runing models_ngspice-BJT-iv regression ==========" |& tee -a ../run_log.log
114108
@python3 models_regression.py |& tee -a ../run_log.log
115-
@python3 plotting.py
116109

117110
#================================
118111
# --------- models-diode --------
@@ -125,7 +118,6 @@ models-diode: Add_run-dir
125118
@cd $(Testing_DIR)/$(run_folder)/diode
126119
@echo "========== Runing models_ngspice-didoe regression ==========" |& tee -a ../run_log.log
127120
@python3 models_regression.py |& tee -a ../run_log.log
128-
@python3 plotting.py
129121

130122
#================================
131123
# -------- models-MOSCAP --------
@@ -138,7 +130,6 @@ models-MOSCAP: Add_run-dir
138130
@cd $(Testing_DIR)/$(run_folder)/moscap_c
139131
@echo "========== Runing models_ngspice-MOSCAP regression ==========" |& tee -a ../run_log.log
140132
@python3 models_regression.py |& tee -a ../run_log.log
141-
@python3 plotting.py
142133

143134
#================================
144135
# -------- models-MIMCAP --------
@@ -151,7 +142,6 @@ models-MIMCAP: Add_run-dir
151142
@cd $(Testing_DIR)/$(run_folder)/mimcap_c
152143
@echo "========== Runing models_ngspice-MIMCAP regression ==========" |& tee -a ../run_log.log
153144
@python3 models_regression.py |& tee -a ../run_log.log
154-
@python3 plotting.py
155145

156146
#================================
157147
# --------- models-RES ----------
@@ -164,7 +154,6 @@ models-RES: Add_run-dir
164154
@cd $(Testing_DIR)/$(run_folder)/resistor_r
165155
@echo "========== Runing models_ngspice-RES regression ==========" |& tee -a ../run_log.log
166156
@python3 models_regression.py |& tee -a ../run_log.log
167-
@python3 plotting.py
168157

169158
#===============================
170159
# --------- Clean ALL ----------

models/ngspice/testing/regression/bjt_beta/device_netlists/npn.spice

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ xq1 c b 0 0 {{device}}
1717

1818
.control
1919
set filetype=ascii
20-
20+
set wr_singlescale
21+
set wr_vecnames
2122
dc Vbp 0.2 1.2 0.01 Vcp 1 3 1
22-
wrdata bjt_beta_regr/npn/ic_simulated/simulated_{{device}}_t{{temp}}.csv -i(Vcp)
23-
wrdata bjt_beta_regr/npn/ib_simulated/simulated_{{device}}_t{{temp}}.csv -i(Vbp)
23+
wrdata bjt_beta_regr/npn/npn_netlists/ic_simulated_{{device}}_t{{temp}}.csv -i(Vcp) v(c)
24+
wrdata bjt_beta_regr/npn/npn_netlists/ib_simulated_{{device}}_t{{temp}}.csv -i(Vbp) v(c)
2425
.endc
2526

2627
.include "../../../design.ngspice"

models/ngspice/testing/regression/bjt_beta/device_netlists/pnp.spice

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ xq1 c b 0 {{device}}
1717

1818
.control
1919
set filetype=ascii
20-
20+
set wr_singlescale
21+
set wr_vecnames
2122
dc Vbp -0.2 -1.2 -0.01 Vcp -1 -3 -1
22-
wrdata bjt_beta_regr/pnp/ic_simulated/simulated_{{device}}_t{{temp}}.csv -i(Vcp)
23-
wrdata bjt_beta_regr/pnp/ib_simulated/simulated_{{device}}_t{{temp}}.csv -i(Vbp)
23+
wrdata bjt_beta_regr/pnp/pnp_netlists/ic_simulated_{{device}}_t{{temp}}.csv i(Vcp) v(c)
24+
wrdata bjt_beta_regr/pnp/pnp_netlists/ib_simulated_{{device}}_t{{temp}}.csv i(Vbp) v(c)
2425
.endc
2526

2627
.include "../../../design.ngspice"

models/ngspice/testing/regression/bjt_beta/models_regression.py

Lines changed: 91 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -269,12 +269,10 @@ def run_sim(char, dirpath, device, temp):
269269

270270
netlist_path = f"{dirpath}/{dev}_netlists" + f"/netlist_{device}_t{temp_str}.spice"
271271

272-
result_path_ib = f"{dirpath}/ib_simulated/" + f"simulated_{device}_t{temp_str}.csv"
273-
result_path_ic = f"{dirpath}/ic_simulated/" + f"simulated_{device}_t{temp_str}.csv"
274-
275-
for c in char:
276-
os.makedirs(f"{dirpath}/{c}_simulated", exist_ok=True)
272+
result_path_ib = f"{dirpath}/{dev}_netlists/" + f"ib_simulated_{device}_t{temp_str}.csv"
273+
result_path_ic = f"{dirpath}/{dev}_netlists/" + f"ic_simulated_{device}_t{temp_str}.csv"
277274

275+
278276
with open(netlist_tmp) as f:
279277
tmpl = Template(f.read())
280278
os.makedirs(f"{dirpath}/{dev}_netlists", exist_ok=True)
@@ -325,43 +323,44 @@ def run_sims(char, df, dirpath, num_workers=mp.cpu_count()):
325323
logging.info(f"Test case generated an exception: {exc}")
326324

327325
for c in char:
328-
sf = glob.glob(f"{dirpath}/{c}_simulated/*.csv") # stored simulated data files
326+
sf = glob.glob(f"{dirpath}/*_netlists/{c}*.csv") # stored simulated data files
329327

330328
for i in range(len(sf)):
331-
sdf = pd.read_csv(
329+
df = pd.read_csv(
332330
sf[i],
333-
header=None,
334331
delimiter=r"\s+",
335332
)
336333

337-
sweep = len(pd.read_csv(glob.glob(f"{dirpath}/{c}_measured/*.csv")[1]))
338-
339-
new_array = np.empty((sweep, 1 + int(sdf.shape[0] / sweep)))
340-
new_array[:, 0] = sdf.iloc[:sweep, 0]
341-
times = int(sdf.shape[0] / sweep)
342-
343-
for j in range(times):
344-
new_array[:, (j + 1)] = sdf.iloc[j * sweep : (j + 1) * sweep, 1]
345-
346-
# Writing final simulated data 1
347-
sdf = pd.DataFrame(new_array)
348-
sdf.to_csv(
349-
sf[i],
350-
index=False,
351-
)
352-
353-
sdf.rename(
354-
columns={
355-
0: "simulated_base_volt",
356-
1: f"simulated_{c}_vcp_step1",
357-
2: f"simulated_{c}_vcp_step2",
358-
3: f"simulated_{c}_vcp_step3",
359-
},
360-
inplace=True,
361-
)
362-
363-
sdf.to_csv(sf[i])
364-
334+
if c == "ib" and dirpath == "bjt_beta_regr/npn":
335+
i_vds = "-i(Vbp)"
336+
elif c == "ic" and dirpath == "bjt_beta_regr/npn":
337+
i_vds = "-i(Vcp)"
338+
elif c == "ib" and dirpath == "bjt_beta_regr/pnp":
339+
i_vds = "i(Vbp)"
340+
else:
341+
i_vds = "i(Vcp)"
342+
sdf = df.pivot(index="v-sweep", columns="v(c)", values=i_vds)
343+
if dirpath == "bjt_beta_regr/npn":
344+
sdf.rename(
345+
columns={
346+
1.0: f"simulated_{c}_vcp_step1",
347+
2.0: f"simulated_{c}_vcp_step2",
348+
3.0: f"simulated_{c}_vcp_step3",
349+
},
350+
inplace=True,
351+
)
352+
else:
353+
sdf.rename(
354+
columns={
355+
-1.0: f"simulated_{c}_vcp_step1",
356+
-2.0: f"simulated_{c}_vcp_step2",
357+
-3.0: f"simulated_{c}_vcp_step3",
358+
},
359+
inplace=True,
360+
)
361+
# reverse the rows
362+
sdf = sdf.iloc[::-1]
363+
sdf.to_csv(sf[i], index=True, header=True, sep=",")
365364
df = pd.DataFrame(results)
366365

367366
df = df[["device", "temp", "beta_sim_ib_unscaled", "beta_sim_ic_unscaled"]]
@@ -456,7 +455,7 @@ def main():
456455
sim_df = run_sims(char, meas_df, dev_path, 3)
457456

458457
sim_len = len(
459-
pd.read_csv(glob.glob(f"{dev_path}/{char[1]}_simulated/*.csv")[1])
458+
pd.read_csv(glob.glob(f"{dev_path}/{dev}_netlists/{char[1]}*.csv")[1])
460459
)
461460

462461
logging.info(
@@ -469,15 +468,25 @@ def main():
469468

470469
merged_all = []
471470
for c in char:
472-
471+
# create a new dataframe for rms error
472+
rms_df = pd.DataFrame(columns=["device", "temp","corner", "rms_error"])
473+
473474
merged_dfs = []
474475

475476
for i in range(len(merged_df)):
476477

477478
measured_data = pd.read_csv(merged_df[f"{c}_measured"][i])
478479
simulated_data = pd.read_csv(merged_df[f"beta_{c}_sim"][i])
479-
480+
measured_data["v-sweep"] = simulated_data["v-sweep"]
480481
result_data = simulated_data.merge(measured_data, how="left")
482+
# clipping all the values to lowest_curr
483+
lowest_curr = 5e-12
484+
result_data[f"simulated_{c}_vcp_step1"] = result_data[f"simulated_{c}_vcp_step1"].clip(lower=lowest_curr)
485+
result_data[f"simulated_{c}_vcp_step2"] = result_data[f"simulated_{c}_vcp_step2"].clip(lower=lowest_curr)
486+
result_data[f"simulated_{c}_vcp_step3"] = result_data[f"simulated_{c}_vcp_step3"].clip(lower=lowest_curr)
487+
result_data[f"measured_{c}_vcp_step1"] = result_data[f"measured_{c}_vcp_step1"].clip(lower=lowest_curr)
488+
result_data[f"measured_{c}_vcp_step2"] = result_data[f"measured_{c}_vcp_step2"].clip(lower=lowest_curr)
489+
result_data[f"measured_{c}_vcp_step3"] = result_data[f"measured_{c}_vcp_step3"].clip(lower=lowest_curr)
481490

482491
result_data["corner"] = "typical"
483492
result_data["device"] = (
@@ -529,7 +538,18 @@ def main():
529538
)
530539
/ 3
531540
)
532-
541+
# get rms error
542+
result_data["rms_error"] = np.sqrt(
543+
np.mean(result_data["error"] ** 2)
544+
)
545+
# fill rms dataframe
546+
rms_df.loc[i] = [
547+
result_data["device"][0],
548+
result_data["temp"][0],
549+
result_data["corner"][0],
550+
result_data["rms_error"][0],
551+
]
552+
533553
result_data = result_data[
534554
[
535555
"device",
@@ -554,56 +574,40 @@ def main():
554574
merged_out = pd.concat(merged_dfs)
555575

556576
merged_out.to_csv(f"{dev_path}/error_analysis_{c}.csv", index=False)
557-
558-
merged_all.append(merged_out)
559-
560-
merged_all = pd.concat(merged_all)
561-
list_dev = npn_devices
562-
if dev == "pnp":
563-
list_dev = pnp_devices
564-
# calculating the error of each device and reporting it
565-
for dev in list_dev:
566-
min_error_total = float()
567-
max_error_total = float()
568-
error_total = float()
569-
number_of_existance = int()
570-
571-
# number of rows in the final excel sheet
572-
num_rows = merged_all["device"].count()
573-
574-
for n in range(num_rows):
575-
if dev == merged_all["device"].iloc[n]:
576-
number_of_existance += 1
577-
error_total += merged_all["error"].iloc[n]
578-
if merged_all["error"].iloc[n] > max_error_total:
579-
max_error_total = merged_all["error"].iloc[n]
580-
elif merged_all["error"].iloc[n] < min_error_total:
581-
min_error_total = merged_all["error"].iloc[n]
582-
583-
mean_error_total = error_total / number_of_existance
584-
585-
# Making sure that min, max, mean errors are not > 100%
586-
if min_error_total > 100:
587-
min_error_total = 100
588-
589-
if max_error_total > 100:
590-
max_error_total = 100
591-
592-
if mean_error_total > 100:
593-
mean_error_total = 100
594-
595-
# logging.infoing min, max, mean errors to the consol
596-
logging.info(
597-
f"# Device {dev} min error: {min_error_total:.2f}, max error: {max_error_total:.2f}, mean error {mean_error_total:.2f}"
598-
)
599-
600-
if max_error_total < PASS_THRESH:
601-
logging.info(f"# Device {dev} has passed regression.")
602-
else:
577+
rms_df.to_csv(f"{dev_path}/finalerror_analysis_{c}.csv", index=False)
578+
579+
# calculating the error of each device and reporting it
580+
for dev in list_dev:
581+
min_error_total = float()
582+
max_error_total = float()
583+
mean_error_total = float()
584+
# number of rows in the final excel sheet
585+
rms_df=pd.read_csv(f"{dev_path}/finalerror_analysis_{c}.csv")
586+
min_error_total = rms_df["rms_error"].min()
587+
max_error_total = rms_df["rms_error"].max()
588+
mean_error_total = rms_df["rms_error"].mean()
589+
# Making sure that min, max, mean errors are not > 100%
590+
if min_error_total > 100:
591+
min_error_total = 100
592+
593+
if max_error_total > 100:
594+
max_error_total = 100
595+
596+
if mean_error_total > 100:
597+
mean_error_total = 100
598+
599+
# logging.infoing min, max, mean errors to the consol
603600
logging.info(
604-
f"# Device {dev} has failed regression. Needs more analysis."
601+
f"# Device {dev} {c} min error: {min_error_total:.2f}, max error: {max_error_total:.2f}, mean error {mean_error_total:.2f}"
605602
)
606603

604+
if max_error_total < PASS_THRESH:
605+
logging.info(f"# Device {dev} {c} has passed regression.")
606+
else:
607+
logging.error(
608+
f"# Device {dev} {c} has failed regression. Needs more analysis."
609+
)
610+
607611

608612
# # ================================================================
609613
# -------------------------- MAIN --------------------------------

models/ngspice/testing/regression/bjt_beta/plotting.ipynb

Lines changed: 262 additions & 21 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)