blob: 4c38897c2b5b5a3da5f5a034f7e4ca78be3554a4 [file] [log] [blame]
# SPDX-License-Identifier: GPL-2.0-or-later
import sys
from termios import TIOCPKT_FLUSHREAD
from typing import List, Tuple, cast
from pdkmaster.technology import geometry as _geo, primitive as _prm
from pdkmaster.design import circuit as _ckt, layout as _lay, library as _lbry
from c4m.pdk import sky130
_prims = sky130.tech.primitives
from . import frame as _frm
__all__ = ["ConnectedBandGap"]
class ConnectedBandGap(_lbry._Cell[_lbry.Library]):
def __init__(self, *, lib: _lbry.Library):
super().__init__(lib=lib, name="ConnectedBandGap")
ckt = self.new_circuit()
layouter = self.new_circuitlayouter()
layout = layouter.layout
li = cast(_prm.MetalWire, _prims.li)
assert li.pin is not None
lipin = li.pin[0]
mcon = cast(_prm.Via, _prims.mcon)
m1 = cast(_prm.MetalWire, _prims.m1)
assert m1.pin is not None
m1pin = m1.pin[0]
via = cast(_prm.Via, _prims.via)
m2 = cast(_prm.MetalWire, _prims.m2)
via2 = cast(_prm.Via, _prims.via2)
m3 = cast(_prm.MetalWire, _prims.m3)
assert m3.pin is not None
m3pin = m3.pin[0]
bnd = cast(_prm.Auxiliary, _prims.prBoundary)
nmos3v3 = cast(_prm.MOSFET, _prims.nfet_g5v0d10v5)
nmos1v8lvt = cast(_prm.MOSFET, _prims.nfet_01v8_lvt)
nmos1v8 = cast(_prm.MOSFET, _prims.nfet_01v8)
pmos3v3 = cast(_prm.MOSFET, _prims.pfet_g5v0d10v5)
pmos1v8lvt = cast(_prm.MOSFET, _prims.pfet_01v8_lvt)
pmos1v8 = cast(_prm.MOSFET, _prims.pfet_01v8)
pnp = sky130.macrolib.cells.PNP_05v5_W3u40L3u40
res = cast(_prm.Resistor, _prims.poly_res)
# Create the bandgap subcells
bg3v3_cell = sky130.BandgapCell(
lib=lib, name="Bandgap3V3",
nmos=nmos3v3, nmos_l=25.0, nmos_w=40.0,
pmos=pmos3v3, pmos_l=7.75, pmos_w=40.0,
pnp=pnp, pnp_ratio=2,
resistor=res, r1_height=13.055, r2_height=329.85,
)
lib.cells += bg3v3_cell
_bg3v3_bb = bg3v3_cell.layout.bounds()
assert _bg3v3_bb is not None
_bg3v3vref = bg3v3_cell.circuit.nets.vref
_bg3v3vref_m1pinbb = bg3v3_cell.layout.bounds(mask=m1pin.mask, net=_bg3v3vref)
bg1v8lvt_cell = sky130.BandgapCell(
lib=lib, name="Bandgap1V8lvt",
nmos=nmos1v8lvt, nmos_l=1.0, nmos_w=40.0,
pmos=pmos1v8lvt, pmos_l=25.0, pmos_w=40.0,
pnp=pnp, pnp_ratio=2,
resistor=res, r1_height=62.85, r2_height=1091.20,
)
lib.cells += bg1v8lvt_cell
_bg1v8lvt_bb = bg1v8lvt_cell.layout.bounds()
assert _bg1v8lvt_bb is not None
_bg1v8lvtvref = bg1v8lvt_cell.circuit.nets.vref
_bg1v8lvtvref_m1pinbb = bg1v8lvt_cell.layout.bounds(mask=m1pin.mask, net=_bg1v8lvtvref)
bg1v8_cell = sky130.BandgapCell(
lib=lib, name="Bandgap1V8",
nmos=nmos1v8, nmos_l=25.0, nmos_w=40.0,
pmos=pmos1v8, pmos_l=0.5, pmos_w=40.0,
pnp=pnp, pnp_ratio=2,
resistor=res, r1_height=32.14, r2_height=458.46,
)
lib.cells += bg1v8_cell
_bg1v8_bb = bg1v8_cell.layout.bounds()
assert _bg1v8_bb is not None
_bg1v8vref = bg1v8_cell.circuit.nets.vref
_bg1v8vref_m1pinbb = bg1v8_cell.layout.bounds(mask=m1pin.mask, net=_bg1v8vref)
# Instantiate the bandgap cells
bg3v3 = ckt.instantiate(bg3v3_cell, name="bg3v3")
bg1v8lvt = ckt.instantiate(bg1v8lvt_cell, name="bg1v8lvt")
bg1v8 = ckt.instantiate(bg1v8_cell, name="bg1v8")
# Add pins + nets for the io signals of the bandgap
vss3v3_pinname = "io_analog[7]"
vss3v3_m3pinbb = _frm.toppins[vss3v3_pinname]
vss3v3 = ckt.new_net(name=vss3v3_pinname, external=True, childports=bg3v3.ports.vss)
layouter.add_wire(net=vss3v3, wire=m3, pin=m3pin, shape=vss3v3_m3pinbb)
vdd3v3_pinname = "io_analog[9]"
vdd3v3_m3pinbb = _frm.toppins[vdd3v3_pinname]
vdd3v3 = ckt.new_net(name=vdd3v3_pinname, external=True, childports=bg3v3.ports.vdd)
layouter.add_wire(net=vdd3v3, wire=m3, pin=m3pin, shape=vdd3v3_m3pinbb)
vref3v3_pinname = "io_analog[8]"
vref3v3_m3pinbb = _frm.toppins[vref3v3_pinname]
vref3v3 = ckt.new_net(name=vref3v3_pinname, external=True, childports=bg3v3.ports.vref)
layouter.add_wire(net=vref3v3, wire=m3, pin=m3pin, shape=vref3v3_m3pinbb)
# vss and vdd are shared between bg1v8lvt and bg1v8
vss1v8_pinname = "io_analog[0]"
vss1v8_m3pinbb = _frm.toppins[vss1v8_pinname]
vss1v8 = ckt.new_net(name=vss1v8_pinname, external=True, childports=(
bg1v8.ports.vss, bg1v8lvt.ports.vss,
))
layouter.add_wire(net=vss1v8, wire=m3, pin=m3pin, shape=vss1v8_m3pinbb)
vdd1v8_pinname = "io_analog[3]"
vdd1v8_m3pinbb = _frm.toppins[vdd1v8_pinname]
vdd1v8 = ckt.new_net(name=vdd1v8_pinname, external=True, childports=(
bg1v8.ports.vdd, bg1v8lvt.ports.vdd,
))
layouter.add_wire(net=vdd1v8, wire=m3, pin=m3pin, shape=vdd1v8_m3pinbb)
vref1v8lvt_pinname = "io_analog[2]"
vref1v8lvt_m3pinbb = _frm.toppins[vref1v8lvt_pinname]
vref1v8lvt = ckt.new_net(
name=vref1v8lvt_pinname, external=True, childports=bg1v8lvt.ports.vref,
)
layouter.add_wire(net=vref1v8lvt, wire=m3, pin=m3pin, shape=vref1v8lvt_m3pinbb)
vref1v8_pinname = "io_analog[1]"
vref1v8_m3pinbb = _frm.toppins[vref1v8_pinname]
vref1v8 = ckt.new_net(
name=vref1v8_pinname, external=True, childports=bg1v8.ports.vref,
)
layouter.add_wire(net=vref1v8, wire=m3, pin=m3pin, shape=vref1v8_m3pinbb)
# Boundary
layout.boundary = _frm.boundary
layouter.add_portless(prim=bnd, shape=_frm.boundary)
# Place bg3v3, align vref pin with top pin
x = vref3v3_m3pinbb.center.x - _bg3v3vref_m1pinbb.center.x
y = vref3v3_m3pinbb.bottom - 5.0 - _bg3v3_bb.top
bg3v3_lay = layouter.place(bg3v3, x=x, y=y)
bg3v3vss_m1pinbb = bg3v3_lay.bounds(mask=m1pin.mask, net=vss3v3, depth=1)
bg3v3vss_m1pinbb = _geo.Rect.from_rect(
rect=bg3v3vss_m1pinbb, top=(bg3v3vss_m1pinbb.top + 5.0),
)
bg3v3vdd_m1pinbb = bg3v3_lay.bounds(mask=m1pin.mask, net=vdd3v3, depth=1)
bg3v3vdd_m1pinbb = _geo.Rect.from_rect(
rect=bg3v3vdd_m1pinbb, bottom=(bg3v3vdd_m1pinbb.bottom - 5.0),
)
bg3v3vref_m1pinbb = bg3v3_lay.bounds(mask=m1pin.mask, net=vref3v3, depth=1)
bg3v3vref_m1pinbb = _geo.Rect.from_rect(
rect=bg3v3vref_m1pinbb, right=(bg3v3vref_m1pinbb.right + 5.0),
)
# Place bg1v8lvt, align vref pin with top pin
x = vref1v8lvt_m3pinbb.center.x - _bg1v8lvtvref_m1pinbb.center.x
y = vref1v8lvt_m3pinbb.bottom - 10.0 - _bg1v8lvt_bb.top
bg1v8lvt_lay = layouter.place(bg1v8lvt, x=x, y=y)
bg1v8lvtvss_m1pinbb = bg1v8lvt_lay.bounds(mask=m1pin.mask, net=vss1v8, depth=1)
bg1v8lvtvss_m1pinbb = _geo.Rect.from_rect(
rect=bg1v8lvtvss_m1pinbb, top=(bg1v8lvtvss_m1pinbb.top + 5.0),
)
bg1v8lvtvss_m2pinbb = _geo.Rect.from_rect(
rect=bg1v8lvtvss_m1pinbb, bottom=vss1v8_m3pinbb.bottom,
)
bg1v8lvtvss_m3pinbb = _geo.Rect.from_rect(
rect=bg1v8lvtvss_m2pinbb, top=vss1v8_m3pinbb.top,
)
bg1v8lvtvdd_m1pinbb = bg1v8lvt_lay.bounds(mask=m1pin.mask, net=vdd1v8, depth=1)
bg1v8lvtvdd_m1pinbb = _geo.Rect.from_rect(
rect=bg1v8lvtvdd_m1pinbb, top=(bg1v8lvtvdd_m1pinbb.top + 6.0),
)
bg1v8lvtvdd_m2pinbb = _geo.Rect.from_rect(
rect=bg1v8lvtvdd_m1pinbb, bottom=(bg1v8lvtvdd_m1pinbb.top - 5.0),
)
bg1v8lvtvref_m1pinbb = bg1v8lvt_lay.bounds(mask=m1pin.mask, net=vref1v8lvt, depth=1)
bg1v8lvtvref_m1pinbb = _geo.Rect.from_rect(
rect=bg1v8lvtvref_m1pinbb, right=(bg1v8lvtvref_m1pinbb.right + 5.0),
)
# Place bg1v8 below bg1v8lvt
x = vref1v8_m3pinbb.center.x - _bg1v8vref_m1pinbb.center.x
y = vref1v8_m3pinbb.bottom - 10.0 - _bg1v8_bb.top
bg1v8_lay = layouter.place(bg1v8, x=x, y=y)
bg1v8vss_m1pinbb = bg1v8_lay.bounds(mask=m1pin.mask, net=vss1v8, depth=1)
bg1v8vss_m1pinbb = _geo.Rect.from_rect(
rect=bg1v8vss_m1pinbb, top=(bg1v8vss_m1pinbb.top + 5.0),
)
bg1v8vss_m2pinbb = _geo.Rect.from_rect(
rect=bg1v8vss_m1pinbb, bottom=vss1v8_m3pinbb.bottom,
)
bg1v8vss_m3pinbb = _geo.Rect.from_rect(
rect=bg1v8vss_m2pinbb, top=vss1v8_m3pinbb.top,
)
bg1v8vdd_m1pinbb = bg1v8_lay.bounds(mask=m1pin.mask, net=vdd1v8, depth=1)
bg1v8vdd_m1pinbb = _geo.Rect.from_rect(
rect=bg1v8vdd_m1pinbb, top=(bg1v8vdd_m1pinbb.top + 6.0),
)
bg1v8vdd_m2pinbb = _geo.Rect.from_rect(
rect=bg1v8vdd_m1pinbb, bottom=(bg1v8vdd_m1pinbb.top - 5.0),
)
bg1v8vref_m1pinbb = bg1v8_lay.bounds(mask=m1pin.mask, net=vref1v8, depth=1)
bg1v8vref_m1pinbb = _geo.Rect.from_rect(
rect=bg1v8vref_m1pinbb, right=(bg1v8vref_m1pinbb.right + 5.0),
)
# vss3v3
net = vss3v3
layouter.add_wire(
net=net, wire=via, bottom_shape=bg3v3vss_m1pinbb, top_shape=bg3v3vss_m1pinbb,
)
lay = layouter.add_wire(
net=net, wire=via2, bottom_shape=bg3v3vss_m1pinbb, top_shape=bg3v3vss_m1pinbb,
)
m3bb = lay.bounds(mask=m3.mask)
shape = _geo.Rect.from_rect(rect=m3bb, right=vss3v3_m3pinbb.right)
layouter.add_wire(net=net, wire=m3, shape=shape)
shape = _geo.Rect.from_rect(rect=vss3v3_m3pinbb, bottom=m3bb.bottom)
layouter.add_wire(net=net, wire=m3, shape=shape)
# vdd3v3
net = vdd3v3
layouter.add_wire(
net=net, wire=via, bottom_shape=bg3v3vdd_m1pinbb, top_shape=bg3v3vdd_m1pinbb,
)
lay = layouter.add_wire(
net=net, wire=via2, bottom_shape=bg3v3vdd_m1pinbb, top_shape=bg3v3vdd_m1pinbb,
)
m3bb = lay.bounds(mask=m3.mask)
shape = _geo.Rect.from_rect(rect=m3bb, left=vdd3v3_m3pinbb.left)
layouter.add_wire(net=net, wire=m3, shape=shape)
shape = _geo.Rect.from_rect(rect=vdd3v3_m3pinbb, bottom=m3bb.bottom)
layouter.add_wire(net=net, wire=m3, shape=shape)
# vref3v3
net = vref3v3
layouter.add_wire(
net=net, wire=via, bottom_shape=bg3v3vref_m1pinbb, top_shape=bg3v3vref_m1pinbb,
)
lay = layouter.add_wire(
net=net, wire=via2, bottom_shape=bg3v3vref_m1pinbb, top_shape=bg3v3vref_m1pinbb,
)
m3bb = lay.bounds(mask=m3.mask)
shape = _geo.Rect.from_rect(rect=m3bb, top=vref3v3_m3pinbb.bottom)
layouter.add_wire(net=net, wire=m3, shape=shape)
# vss1v8
net = vss1v8
layouter.add_wire(
net=net, wire=via,
bottom_shape=bg1v8lvtvss_m1pinbb, top_shape=bg1v8lvtvss_m2pinbb,
)
layouter.add_wire(
net=net, wire=via,
bottom_shape=bg1v8vss_m1pinbb, top_shape=bg1v8vss_m2pinbb,
)
layouter.add_wire(
net=net, wire=via2,
bottom_shape=bg1v8lvtvss_m3pinbb, top_shape=bg1v8lvtvss_m3pinbb,
)
layouter.add_wire(
net=net, wire=via2,
bottom_shape=bg1v8vss_m3pinbb, top_shape=bg1v8vss_m3pinbb,
)
shape = _geo.Rect.from_rect(rect=bg1v8lvtvss_m3pinbb, right=vss1v8_m3pinbb.right)
layouter.add_wire(net=net, wire=m3, shape=shape)
# vdd1v8
net = vdd1v8
layouter.add_wire(
net=net, wire=via,
bottom_shape=bg1v8lvtvdd_m1pinbb, top_shape=bg1v8lvtvdd_m2pinbb,
)
layouter.add_wire(
net=net, wire=via,
bottom_shape=bg1v8vdd_m1pinbb, top_shape=bg1v8vdd_m2pinbb,
)
via2bb = _geo.Rect.from_rect(
rect=bg1v8vdd_m2pinbb, left=vdd1v8_m3pinbb.left, right=vdd1v8_m3pinbb.right,
)
layouter.add_wire(
net=net, wire=via2, bottom_shape=via2bb, top_shape=via2bb,
)
shape = _geo.Rect.from_rect(rect=via2bb, right=bg1v8vdd_m2pinbb.right)
layouter.add_wire(net=net, wire=m2, shape=shape)
shape = _geo.Rect.from_rect(rect=via2bb, top=vdd1v8_m3pinbb.top)
layouter.add_wire(net=net, wire=m3, shape=shape)
# vref1v8lvt
net = vref1v8lvt
layouter.add_wire(
net=net, wire=via,
bottom_shape=bg1v8lvtvref_m1pinbb, top_shape=bg1v8lvtvref_m1pinbb,
)
lay = layouter.add_wire(
net=net, wire=via2,
bottom_shape=bg1v8lvtvref_m1pinbb, top_shape=bg1v8lvtvref_m1pinbb,
)
m3bb = lay.bounds(mask=m3.mask)
shape = _geo.Rect.from_rect(rect=m3bb, top=vref1v8lvt_m3pinbb.bottom)
layouter.add_wire(net=net, wire=m3, shape=shape)
# vref1v8
net = vref1v8
layouter.add_wire(
net=net, wire=via,
bottom_shape=bg1v8vref_m1pinbb, top_shape=bg1v8vref_m1pinbb,
)
lay = layouter.add_wire(
net=net, wire=via2,
bottom_shape=bg1v8vref_m1pinbb, top_shape=bg1v8vref_m1pinbb,
)
m3bb = lay.bounds(mask=m3.mask)
shape = _geo.Rect.from_rect(rect=m3bb, top=vref1v8_m3pinbb.bottom)
layouter.add_wire(net=net, wire=m3, shape=shape)