Preamble¶

SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-or-later OR CERN-OHL-S-2.0+ OR Apache-2.0

If you are reading a html or other static output version of this python notebook you can find the source python notebook on the c4m-pdk-ihpsg13g2 repository

Setup¶

In [1]:
import sys
import numpy as np
from matplotlib import pyplot as plt

from c4m import flexio as _io
from c4m.pdk import ihpsg13g2

from corners import corner_spec

Simulation¶

We set up a simulation on the IOPadIn cell with varying frequency and rise and fall time, to verify if 100MHz input frequency can be reached and what the duty ratio is on the p2c output to the core.

In [2]:
# Determine the order of the corner simulation and output to file
corners = ("NOM", "FAST", "FAST_COMM", "FAST_ROOM", "SLOW", "SLOW_COMM", "SLOW_ROOM")

_iofab = ihpsg13g2.ihpsg13g2_iofab
iospec = _iofab.spec
strengths = iospec.clampdrive
assert isinstance(strengths, dict)
cells = (
    *(_iofab.out(drivestrength=s) for s in strengths.keys()),
    *(_iofab.triout(drivestrength=s) for s in strengths.keys()),
    *(_iofab.inout(drivestrength=s) for s in strengths.keys()),
)


n_corners = len(corners)
n_cells = len(cells)
n_sims = n_corners*n_cells
i_source = np.ndarray((n_corners, n_cells))
i_sink = np.ndarray((n_corners, n_cells))
for i_corner, corner in enumerate(corners):
    print(corner, file=sys.stderr)
    v_vdd, v_iovdd, temp, tc = corner_spec[corner]
    s_tc = ", ".join(tc)

    for i_cell, cell in enumerate(cells):
        ckt = cell.circuit
        tb = ihpsg13g2.pyspicefab.new_pyspicecircuit(corner=tc, top=ckt)

        tb.V("vss", "vss", tb.gnd, 0.0)
        tb.V("vdd", "vdd", tb.gnd, v_vdd)
        tb.V("iovss", "iovss", tb.gnd, 0.0)
        tb.V("iovdd", "iovdd", tb.gnd, v_iovdd)

        tb.PieceWiseLinearVoltageSource("c2p", "c2p", "vss", dc=0.0, values=(
            (0.0, 0.0),
            (1e-3, 0.0),
            (1.1e-3, v_vdd),
        ))
        if isinstance(cell, (_io.PadTriOutT, _io.PadInOutT)):
            tb.V("c2p_en", "c2p_en", "vss", v_vdd)
        if isinstance(cell, _io.PadInOutT):
            tb.C("p2c", "p2c", "vss", 10e-15)
        tb.PieceWiseLinearVoltageSource("pad", "pad", "iovss", dc=0.0, values=(
            (0.0, 0.0),
            (0.1e-3, v_iovdd),
            (1.0e-3, v_iovdd),
            (1.1e-3, 0.0),
        ))

        sim = tb.simulator(temperature=temp, gmin=1e-9)

        try:
            trans = sim.transient(step_time=0.1e-3, end_time=2e-3)
        except:
            sink = np.nan
            source = np.nan
        else:
            time = np.array(trans.time)
            i_pad = np.array(trans.vpad)

            sink = -np.interp(0.5e-3, time, i_pad)
            source = np.interp(1.5e-3, time, i_pad)

        print(f"{i_corner*n_cells + i_cell + 1}/{n_sims}")
        i_sink[i_corner, i_cell] = sink
        i_source[i_corner, i_cell] = source
NOM
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
1/63
2/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
3/63
4/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
5/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
6/63
7/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
8/63
FAST
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
9/63
10/63
11/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
12/63
13/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
14/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
15/63
16/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
17/63
FAST_COMM
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
18/63
19/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
20/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
21/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
22/63
23/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
24/63
25/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
26/63
FAST_ROOM
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
27/63
28/63
29/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
30/63
31/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
32/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
33/63
34/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
35/63
SLOW
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
36/63
37/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
38/63
39/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
40/63
41/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
42/63
43/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
44/63
SLOW_COMM
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
45/63
46/63
47/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
48/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
49/63
50/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
51/63
52/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
53/63
SLOW_ROOM
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
54/63
55/63
56/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
57/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
58/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
59/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
60/63
61/63
Warning: m=xx on .subckt line will override multiplier m hierarchy!
Warning: m=xx on .subckt line will override multiplier m hierarchy!
62/63
63/63

The simulations at elevated temperatures are failing. This has been reported on the PDK github as IHP-Open-PDK:#24

In [3]:
from IPython.display import Markdown

_s = "# Sink current\n"
_s += "| | *" + "* | *".join(corners) + "* |\n"
_s += "|-"*(n_corners + 1) + " |\n"
for i_cell in range(n_cells):
    _s += f"| *{cells[i_cell].name}* | "
    _s += " | ".join(
        f"{1000*i_sink[i_corner, i_cell]:.1f} mA" for i_corner in range(n_corners)
    )
    _s += " |\n"
_s += "# Source current\n"
_s += "| | *" + "* | *".join(corners) + "* |\n"
_s += "|-"*(n_corners + 1) + " |\n"
for i_cell in range(n_cells):
    _s += f"| *{cells[i_cell].name}* | "
    _s += " | ".join(
        f"{1000*i_source[i_corner, i_cell]:.1f} mA" for i_corner in range(n_corners)
    )
    _s += " |\n"
Markdown(_s)
Out[3]:

Sink current¶

NOM FAST FAST_COMM FAST_ROOM SLOW SLOW_COMM SLOW_ROOM
sg13g2_IOPadOut4mA 4.0 mA 6.1 mA 5.5 mA 5.2 mA 2.3 mA 2.6 mA 3.0 mA
sg13g2_IOPadOut16mA 16.0 mA 24.5 mA 22.2 mA 20.9 mA 9.3 mA 10.6 mA 11.9 mA
sg13g2_IOPadOut30mA 30.0 mA 46.0 mA 41.6 mA 39.1 mA 17.4 mA 19.9 mA 22.2 mA
sg13g2_IOPadTriOut4mA 4.0 mA 6.1 mA 5.5 mA 5.2 mA 2.3 mA 2.6 mA 3.0 mA
sg13g2_IOPadTriOut16mA 16.0 mA 24.5 mA 22.2 mA 20.9 mA 9.3 mA 10.6 mA 11.9 mA
sg13g2_IOPadTriOut30mA 30.0 mA 46.0 mA 41.6 mA 39.1 mA 17.4 mA 19.9 mA 22.2 mA
sg13g2_IOPadInOut4mA 4.0 mA 6.1 mA 5.5 mA 5.2 mA 2.3 mA 2.6 mA 3.0 mA
sg13g2_IOPadInOut16mA 16.0 mA 24.5 mA 22.2 mA 20.9 mA 9.3 mA 10.6 mA 11.9 mA
sg13g2_IOPadInOut30mA 30.0 mA 46.0 mA 41.6 mA 39.1 mA 17.4 mA 19.9 mA 22.2 mA

Source current¶

NOM FAST FAST_COMM FAST_ROOM SLOW SLOW_COMM SLOW_ROOM
sg13g2_IOPadOut4mA 4.0 mA 6.4 mA 5.9 mA 5.6 mA 2.3 mA 2.5 mA 2.8 mA
sg13g2_IOPadOut16mA 16.0 mA 25.5 mA 23.4 mA 22.2 mA 9.2 mA 10.2 mA 11.1 mA
sg13g2_IOPadOut30mA 30.0 mA 47.8 mA 43.9 mA 41.6 mA 17.3 mA 19.1 mA 20.7 mA
sg13g2_IOPadTriOut4mA 4.0 mA 6.4 mA 5.9 mA 5.6 mA 2.3 mA 2.5 mA 2.8 mA
sg13g2_IOPadTriOut16mA 16.0 mA 25.5 mA 23.4 mA 22.2 mA 9.2 mA 10.2 mA 11.1 mA
sg13g2_IOPadTriOut30mA 30.0 mA 47.8 mA 43.9 mA 41.6 mA 17.3 mA 19.1 mA 20.7 mA
sg13g2_IOPadInOut4mA 4.0 mA 6.4 mA 5.9 mA 5.6 mA 2.3 mA 2.5 mA 2.8 mA
sg13g2_IOPadInOut16mA 16.0 mA 25.5 mA 23.4 mA 22.2 mA 9.2 mA 10.2 mA 11.1 mA
sg13g2_IOPadInOut30mA 30.0 mA 47.8 mA 43.9 mA 41.6 mA 17.3 mA 19.1 mA 20.7 mA

Simulated values of the sink and source current of the IO cells in the NOM corner match the one specified in the cell name