Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new experimental data #23

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ Experimental Data

The experimental data in this repository is currently stored in the `.mdm` file format.

**Other data**

* (2022-Nov-1) New experimental data by EPFL is stored in the `.csv` format at `sky130_fd_pr_epfl/cells <./sky130_fd_pr_epfl/cells>`_. The corresponded notebook can be found at `notebooks/sky130_plot_first_meas.ipynb <./notebooks/sky130_plot_first_meas.ipynb>`_.
* (2022-Feb-17) Additional measurement on nfet(2602), pfet(2605), and nshort(5290), stored at `sky130_fd_pr_epfl/cells <./sky130_fd_pr_epfl/cells>`_. The corresponding notebook can be found at `notebooks/sky130_plot_general.ipynb <./notebooks/sky130_plot_general.ipynb>`_. The measurement was performed with the homemade software and probe card.
**Current** proprietary SkyWater Test Tile
------------------------------------------

Expand Down
1,426 changes: 1,426 additions & 0 deletions notebooks/sky130_plot_epfl_data_first_meas.ipynb

Large diffs are not rendered by default.

210 changes: 210 additions & 0 deletions notebooks/sky130_plot_epfl_data_general.ipynb

Large diffs are not rendered by default.

79 changes: 79 additions & 0 deletions notebooks/utils/plot_iv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from matplotlib import pyplot as plt
from matplotlib.pyplot import Axes
from pandas import DataFrame
from typing import Union, Tuple


def plot_idvg(
df: DataFrame,
axes: Union[Tuple[Axes, Axes], None] = None,
dev_type='n',
**kwargs
) -> Tuple[Axes, Axes]:

if axes is None:
ax = plt.gca()
axt = ax.twinx()
else:
ax, axt = axes

try:
df.VS
except AttributeError:
df['VS'] = 0
print("Can't find VS in data, set VS = 0 V")

if dev_type == 'n':
x = df.VG - df.VS
y = df.ID
ax.set_xlabel('$V_{GS}$ (V)')
ax.set_ylabel('$I_D$ (A)')
axt.set_ylabel('$I_D$ (A)')
else:
x = df.VS - df.VG
y = -df.ID
ax.set_xlabel('$V_{SG}$ (V)')
ax.set_ylabel('$-I_D$ (A)')
axt.set_ylabel('$-I_D$ (A)')

ax.plot(x, y, marker='o', mfc='w', markevery=0.1, **kwargs)
ax.set_yscale('log')

axt.plot(x, y, marker='o', mfc='w', markevery=0.1)

ax.legend(loc=2)

return ax, axt


def plot_idvd(
df: DataFrame,
ax: Union[Axes, None] = None,
dev_type='n',
**kwargs
) -> Tuple[Axes, Axes]:
if ax is None:
ax = plt.gca()

try:
df.VS
except AttributeError:
df['VS'] = 0
print("Can't find VS in data, set VS = 0 V")

if dev_type == 'n':
x = df.VD - df.VS
y = df.ID
ax.set_xlabel('$V_{DS}$ (V)')
ax.set_ylabel('$I_D$ (A)')
else:
x = df.VS - df.VD
y = -df.ID
ax.set_xlabel('$V_{SD}$ (V)')
ax.set_ylabel('$-I_D$ (A)')

ax.plot(x, y, marker='o', mfc='w', markevery=0.1, **kwargs)

ax.legend(loc=0)

return ax
40 changes: 40 additions & 0 deletions notebooks/utils/plot_sty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from matplotlib.pyplot import rcParams

default = {
'axes.formatter.limits': (-3, 3),
'axes.labelsize': 9,
'axes.titlesize': 20,
'axes.titleweight': 'bold',
'axes.formatter.use_mathtext': True,
'axes.linewidth': 1.,
'axes.autolimit_mode': "round_numbers",
'axes.xmargin': 0.,
'axes.ymargin': .0,
"figure.dpi": 100,
'savefig.dpi': 1200,
'xtick.labelsize': 8,
'ytick.labelsize': 8,
'font.size': 8,
'legend.fontsize': 8,
'legend.framealpha': 0.5,
'legend.frameon': False,
'figure.figsize': [4, 3],
'lines.linestyle': '-',
'lines.markersize': 4,
'lines.markerfacecolor': "white",
'xtick.direction': "in",
'ytick.direction': "in",
'figure.autolayout': False,
'figure.constrained_layout.use': False,
}


def rcParams_update(kwargs: dict = None, theme: str = None):
if theme is None:
d = default
else:
raise ValueError
if kwargs:
for key, val in kwargs.items():
d[key] = val
rcParams.update(d)
113 changes: 113 additions & 0 deletions notebooks/utils/read_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import os
import os.path as op
import pandas as pd
import numpy as np
from pandas import DataFrame
from typing import Union, List, Tuple
from strenum import StrEnum
from collections import namedtuple
import re

DUTinfo = namedtuple('DUTinfo', 'die mod idx flavor W L meas_mode VG VD VB T')
IDVGpattern = r'Die(\d+)_(\d+)-(\d+)_(\w+)_W(\d+)_L(\d+)_(\w+)_Vd(.+)Vb(.+)_T(\d+)K.csv'
IDVDpattern = r'Die(\d+)_(\d+)-(\d+)_(\w+)_W(\d+)_L(\d+)_(\w+)_Vg(.+)Vb(.+)_T(\d+)K.csv'
DATApath = op.join(op.abspath(__file__), '..', '..', '..', 'sky130_fd_pr', 'epfl')


class MeasureentMode(StrEnum):
IDVG = 'idvg'
IDVD = 'idvd'


def decode_iv_file_name(
filename: str) -> DUTinfo:
"""Decode IV measurement filename."""
if MeasureentMode.IDVG in filename:
res = re.findall(IDVGpattern, filename)[0]
die, mod, idx, flavor, w, l, meas_mode, vd, vb, temp = res
return DUTinfo(
die=int(die), mod=mod, idx=int(idx), flavor=flavor,
W=np.round(float(w)*1e-9, 9), L=np.round(float(l)*1e-9, 9), meas_mode=meas_mode,
VD=float(vd.replace('V', '.')), VB=float(vb.replace('V', '.')),
T=float(temp), VG=None
)
elif MeasureentMode.IDVD in filename:
res = re.findall(IDVDpattern, filename)[0]
die, mod, idx, flavor, w, l, meas_mode, vg, vb, temp = res
return DUTinfo(
die=int(die), mod=mod, idx=int(idx), flavor=flavor,
W=np.round(float(w)*1e-9, 9), L=np.round(float(l)*1e-9, 9), meas_mode=meas_mode,
VG=float(vg.replace('V', '.')), VB=float(vb.replace('V', '.')),
T=float(temp), VD=None
)
else:
raise ValueError(f"Filename {filename} can not be decoded.")


def read_iv(
mod: Union[int, str],
idx: Union[list, int],
meas_mode: Union[MeasureentMode, str],
vg: Union[float, list, None] = None,
vd: Union[float, list, None] = None,
vb: Union[float, list, None] = None,
temp: Union[float, list, None] = None
) -> List[Tuple[DUTinfo, DataFrame]]:
"""Read IV measurement.

:param mod: Module index.
:param idx: DUT index
:param meas_mode: Measurement mode.
:param vg: Gate voltage.
:param vd: Drain voltage.
:param vb: Bulk voltage.
:param temp: Temperature.
"""
out = []
folder = None
mod = str(mod)
idx = [idx] if isinstance(idx, int) else idx
vg = [vg] if isinstance(vg, float) else vg
vd = [vd] if isinstance(vd, float) else vd
vb = [vb] if isinstance(vb, float) else vb
temp = [temp] if isinstance(temp, float) else temp

for f in os.listdir(DATApath):
if f.endswith(mod):
folder = f
break

filename_list = os.listdir(op.join(DATApath, folder))
for file in filename_list.copy():
info = decode_iv_file_name(filename=file)
if info.idx not in idx:
filename_list.remove(file)
continue

if info.meas_mode != meas_mode:
filename_list.remove(file)
continue

if vg:
if info.VG not in vg:
filename_list.remove(file)
continue
if vd:
if info.VD not in vd:
filename_list.remove(file)
continue
if vb:
if info.VB not in vb:
filename_list.remove(file)
continue

if temp:
if info.T not in temp:
filename_list.remove(file)
continue

for f in filename_list:
f_info = decode_iv_file_name(f)
df = pd.read_csv(op.join(DATApath, folder, f), index_col=0)
out.append((f_info, df))
return out
Loading