Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
28 changes: 24 additions & 4 deletions compiler/modules/ptx.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,32 @@ def create_layout(self):
# but this may be uncommented for debug purposes
# self.DRC()

def get_model_name(self):
"""
Return the device model name for this transistor's width.

Some technologies model narrow devices with a separate model. In
sky130, an nfet narrower than 0.42um is extracted as
sky130_fd_pr__special_nfet_01v8 rather than sky130_fd_pr__nfet_01v8
(see the "device msubcircuit" rules in sky130A.tech), so the netlist
must use the same name or LVS reports a device class mismatch on
every gate built from a minimum-width device.
"""
narrow_model = spice.get("{}_narrow".format(self.tx_type))
narrow_width = spice.get("{}_narrow_max_width".format(self.tx_type))
if narrow_model and narrow_width and self.tx_width < narrow_width:
return narrow_model

return spice[self.tx_type]

def create_netlist(self):
pin_list = ["D", "G", "S", "B"]
if self.tx_type == "nmos":
body_dir = "GROUND"
else:
body_dir = "POWER"

self.model_name = self.get_model_name()
dir_list = ["INOUT", "INPUT", "INOUT", body_dir]
self.add_pin_list(pin_list, dir_list)

Expand All @@ -133,7 +153,7 @@ def create_netlist(self):
self.channel_length = drc("minlength_channel")
if cell_props.ptx.model_is_subckt:
# sky130
main_str = "X{{0}} {{1}} {0} m={1} w={2} l={3} ".format(spice[self.tx_type],
main_str = "X{{0}} {{1}} {0} m={1} w={2} l={3} ".format(self.model_name,
self.mults,
self.tx_width,
self.channel_length)
Expand All @@ -142,7 +162,7 @@ def create_netlist(self):
area_str = "pd={0:.2f} ps={0:.2f} as={1:.2f}u ad={1:.2f}u".format(perimeter_sd,
area_sd)
else:
main_str = "M{{0}} {{1}} {0} m={1} w={2}u l={3}u ".format(spice[self.tx_type],
main_str = "M{{0}} {{1}} {0} m={1} w={2}u l={3}u ".format(self.model_name,
self.mults,
self.tx_width,
self.channel_length)
Expand All @@ -164,12 +184,12 @@ def create_netlist(self):
self.tx_width,
self.channel_length)
elif cell_props.ptx.model_is_subckt:
self.lvs_device = "X{{0}} {{1}} {0} m={1} w={2}u l={3}u".format(spice[self.tx_type],
self.lvs_device = "X{{0}} {{1}} {0} m={1} w={2}u l={3}u".format(self.model_name,
self.mults,
self.tx_width,
self.channel_length)
else:
self.lvs_device = "M{{0}} {{1}} {0} m={1} w={2}u l={3}u ".format(spice[self.tx_type],
self.lvs_device = "M{{0}} {{1}} {0} m={1} w={2}u l={3}u ".format(self.model_name,
self.mults,
self.tx_width,
self.channel_length)
Expand Down
8 changes: 8 additions & 0 deletions technology/sky130/tech/tech.py
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,14 @@
spice = {}
spice["nmos"] = "sky130_fd_pr__nfet_01v8"
spice["pmos"] = "sky130_fd_pr__pfet_01v8"

# An nfet narrower than 0.42um is a different device in sky130: magic
# extracts it as sky130_fd_pr__special_nfet_01v8, so the netlist has to use
# that name below the threshold or netgen reports a device class mismatch.
# See the "device msubcircuit" lines in sky130A.tech. There is no equivalent
# split for pfets, so only the nmos is declared here.
spice["nmos_narrow"] = "sky130_fd_pr__special_nfet_01v8"
spice["nmos_narrow_max_width"] = 0.42
spice["power"]="vccd1"
spice["ground"]="vssd1"

Expand Down