mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into tech_migration
This commit is contained in:
commit
0bb4a7f93d
|
|
@ -34,6 +34,10 @@ class stimuli():
|
|||
self.sf = stim_file
|
||||
|
||||
(self.process, self.voltage, self.temperature) = corner
|
||||
try:
|
||||
self.device_libraries = tech.spice["fet_libraries"][self.process]
|
||||
except:
|
||||
debug.info(2, "Not using spice library")
|
||||
self.device_models = tech.spice["fet_models"][self.process]
|
||||
|
||||
self.sram_name = "Xsram"
|
||||
|
|
@ -247,8 +251,17 @@ class stimuli():
|
|||
|
||||
def write_include(self, circuit):
|
||||
"""Writes include statements, inputs are lists of model files"""
|
||||
|
||||
includes = self.device_models + [circuit]
|
||||
self.sf.write("* {} process corner\n".format(self.process))
|
||||
if OPTS.tech_name == "s8":
|
||||
libraries = self.device_libraries
|
||||
for item in list(libraries):
|
||||
if os.path.isfile(item[0]):
|
||||
self.sf.write(".lib \"{0}\" {1}\n".format(item[0], item[1]))
|
||||
else:
|
||||
debug.error("Could not find spice library: {0}\nSet SPICE_MODEL_DIR to over-ride path.\n".format(item[0]))
|
||||
|
||||
for item in list(includes):
|
||||
if os.path.isfile(item):
|
||||
self.sf.write(".include \"{0}\"\n".format(item))
|
||||
|
|
|
|||
|
|
@ -8,10 +8,14 @@
|
|||
import contact
|
||||
import design
|
||||
import debug
|
||||
from tech import layer
|
||||
import math
|
||||
from bisect import bisect_left
|
||||
from tech import layer, drc
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
if(OPTS.tech_name == "s8"):
|
||||
from tech import nmos_bins, pmos_bins, accuracy_requirement
|
||||
|
||||
class pgate(design.design):
|
||||
"""
|
||||
|
|
@ -282,5 +286,61 @@ class pgate(design.design):
|
|||
self.width = max(self.nwell_contact.rx(), self.pwell_contact.rx()) + self.m1_space + 0.5 * contact.m1_via.width
|
||||
self.well_width = self.width + 2 * self.nwell_enclose_active
|
||||
# Height is an input parameter, so it is not recomputed.
|
||||
|
||||
def bin_width(self, tx_type, target_width):
|
||||
|
||||
if tx_type == "nmos":
|
||||
bins = nmos_bins[drc("minwidth_poly")]
|
||||
elif tx_type == "pmos":
|
||||
bins = pmos_bins[drc("minwidth_poly")]
|
||||
else:
|
||||
debug.error("invalid tx type")
|
||||
|
||||
bins = bins[0:bisect_left(bins, target_width) + 1]
|
||||
if len(bins) == 1:
|
||||
selected_bin = bins[0]
|
||||
scaling_factor = math.ceil(target_width / selected_bin)
|
||||
scaled_bin = bins[0] * scaling_factor
|
||||
|
||||
else:
|
||||
scaled_bins = []
|
||||
scaling_factors = []
|
||||
scaled_bins.append(bins[-1])
|
||||
scaling_factors.append(1)
|
||||
for width in bins[0:-1]:
|
||||
m = math.ceil(target_width / width)
|
||||
scaling_factors.append(m)
|
||||
scaled_bins.append(m * width)
|
||||
|
||||
select = bisect_left(scaled_bins, target_width)
|
||||
scaling_factor = scaling_factors[select]
|
||||
scaled_bin = scaled_bins[select]
|
||||
select = (select + 1) % len(scaled_bins)
|
||||
selected_bin = bins[select]
|
||||
|
||||
debug.info(2, "binning {0} tx, target: {4}, found {1} x {2} = {3}".format(tx_type, selected_bin, scaling_factor, scaled_bin, target_width))
|
||||
|
||||
return(selected_bin, scaling_factor)
|
||||
|
||||
def permute_widths(self, tx_type, target_width):
|
||||
|
||||
if tx_type == "nmos":
|
||||
bins = nmos_bins[drc("minwidth_poly")]
|
||||
elif tx_type == "pmos":
|
||||
bins = pmos_bins[drc("minwidth_poly")]
|
||||
else:
|
||||
debug.error("invalid tx type")
|
||||
bins = bins[0:bisect_left(bins, target_width) + 1]
|
||||
if len(bins) == 1:
|
||||
scaled_bins = [(bins[0], math.ceil(target_width / bins[0]))]
|
||||
else:
|
||||
scaled_bins = []
|
||||
scaled_bins.append((bins[-1], 1))
|
||||
for width in bins[:-1]:
|
||||
m = math.ceil(target_width / width)
|
||||
scaled_bins.append((m * width, m))
|
||||
|
||||
return(scaled_bins)
|
||||
|
||||
def bin_accuracy(self, ideal_width, width):
|
||||
return abs(1-(ideal_width - width)/ideal_width)
|
||||
|
|
@ -8,15 +8,19 @@
|
|||
import contact
|
||||
import pgate
|
||||
import debug
|
||||
import operator
|
||||
from tech import drc, parameter, spice
|
||||
from vector import vector
|
||||
from math import ceil
|
||||
from globals import OPTS
|
||||
from utils import round_to_grid
|
||||
from bisect import bisect_left
|
||||
import logical_effort
|
||||
from sram_factory import factory
|
||||
from errors import drc_error
|
||||
|
||||
if(OPTS.tech_name == "s8"):
|
||||
from tech import nmos_bins, pmos_bins, accuracy_requirement
|
||||
|
||||
class pinv(pgate.pgate):
|
||||
"""
|
||||
|
|
@ -83,6 +87,9 @@ class pinv(pgate.pgate):
|
|||
self.tx_mults = 1
|
||||
self.nmos_width = self.nmos_size * drc("minwidth_tx")
|
||||
self.pmos_width = self.pmos_size * drc("minwidth_tx")
|
||||
if OPTS.tech_name == "s8":
|
||||
(self.nmos_width, self.tx_mults) = self.bin_width("nmos", self.nmos_width)
|
||||
(self.pmos_width, self.tx_mults) = self.bin_width("pmos", self.pmos_width)
|
||||
return
|
||||
|
||||
# Do a quick sanity check and bail if unlikely feasible height
|
||||
|
|
@ -132,30 +139,62 @@ class pinv(pgate.pgate):
|
|||
|
||||
# Determine the number of mults for each to fit width
|
||||
# into available space
|
||||
self.nmos_width = self.nmos_size * drc("minwidth_tx")
|
||||
self.pmos_width = self.pmos_size * drc("minwidth_tx")
|
||||
nmos_required_mults = max(int(ceil(self.nmos_width / nmos_height_available)), 1)
|
||||
pmos_required_mults = max(int(ceil(self.pmos_width / pmos_height_available)), 1)
|
||||
# The mults must be the same for easy connection of poly
|
||||
self.tx_mults = max(nmos_required_mults, pmos_required_mults)
|
||||
if OPTS.tech_name != "s8":
|
||||
self.nmos_width = self.nmos_size * drc("minwidth_tx")
|
||||
self.pmos_width = self.pmos_size * drc("minwidth_tx")
|
||||
nmos_required_mults = max(int(ceil(self.nmos_width / nmos_height_available)), 1)
|
||||
pmos_required_mults = max(int(ceil(self.pmos_width / pmos_height_available)), 1)
|
||||
# The mults must be the same for easy connection of poly
|
||||
self.tx_mults = max(nmos_required_mults, pmos_required_mults)
|
||||
|
||||
# Recompute each mult width and check it isn't too small
|
||||
# This could happen if the height is narrow and the size is small
|
||||
# User should pick a bigger size to fix it...
|
||||
# We also need to round the width to the grid or we will end up
|
||||
# with LVS property mismatch errors when fingers are not a grid
|
||||
# length and get rounded in the offset geometry.
|
||||
self.nmos_width = round_to_grid(self.nmos_width / self.tx_mults)
|
||||
# debug.check(self.nmos_width >= drc("minwidth_tx"),
|
||||
# "Cannot finger NMOS transistors to fit cell height.")
|
||||
if self.nmos_width < drc("minwidth_tx"):
|
||||
raise drc_error("Cannot finger NMOS transistors to fit cell height.")
|
||||
# Recompute each mult width and check it isn't too small
|
||||
# This could happen if the height is narrow and the size is small
|
||||
# User should pick a bigger size to fix it...
|
||||
# We also need to round the width to the grid or we will end up
|
||||
# with LVS property mismatch errors when fingers are not a grid
|
||||
# length and get rounded in the offset geometry.
|
||||
self.nmos_width = round_to_grid(self.nmos_width / self.tx_mults)
|
||||
# debug.check(self.nmos_width >= drc("minwidth_tx"),
|
||||
# "Cannot finger NMOS transistors to fit cell height.")
|
||||
if self.nmos_width < drc("minwidth_tx"):
|
||||
raise drc_error("Cannot finger NMOS transistors to fit cell height.")
|
||||
|
||||
self.pmos_width = round_to_grid(self.pmos_width / self.tx_mults)
|
||||
#debug.check(self.pmos_width >= drc("minwidth_tx"),
|
||||
# "Cannot finger PMOS transistors to fit cell height.")
|
||||
if self.pmos_width < drc("minwidth_tx"):
|
||||
raise drc_error("Cannot finger NMOS transistors to fit cell height.")
|
||||
self.pmos_width = round_to_grid(self.pmos_width / self.tx_mults)
|
||||
#debug.check(self.pmos_width >= drc("minwidth_tx"),
|
||||
# "Cannot finger PMOS transistors to fit cell height.")
|
||||
if self.pmos_width < drc("minwidth_tx"):
|
||||
raise drc_error("Cannot finger NMOS transistors to fit cell height.")
|
||||
else:
|
||||
self.nmos_width = self.nmos_size * drc("minwidth_tx")
|
||||
self.pmos_width = self.pmos_size * drc("minwidth_tx")
|
||||
nmos_bins = self.permute_widths("nmos", self.nmos_width)
|
||||
pmos_bins = self.permute_widths("pmos", self.pmos_width)
|
||||
|
||||
valid_pmos = []
|
||||
for bin in pmos_bins:
|
||||
if self.bin_accuracy(self.pmos_width, bin[0]) > accuracy_requirement:
|
||||
valid_pmos.append(bin)
|
||||
valid_pmos.sort(key = operator.itemgetter(1))
|
||||
|
||||
valid_nmos = []
|
||||
for bin in nmos_bins:
|
||||
if self.bin_accuracy(self.nmos_width, bin[0]) > accuracy_requirement:
|
||||
valid_nmos.append(bin)
|
||||
valid_nmos.sort(key = operator.itemgetter(1))
|
||||
|
||||
for bin in valid_pmos:
|
||||
if bin[0]/bin[1] < pmos_height_available:
|
||||
self.pmos_width = bin[0]/bin[1]
|
||||
pmos_mults = valid_pmos[0][1]
|
||||
break
|
||||
|
||||
for bin in valid_nmos:
|
||||
if bin[0]/bin[1] < nmos_height_available:
|
||||
self.nmos_width = bin[0]/bin[1]
|
||||
nmos_mults = valid_pmos[0][1]
|
||||
break
|
||||
|
||||
self.tx_mults = max(pmos_mults, nmos_mults)
|
||||
|
||||
def add_ptx(self):
|
||||
""" Create the PMOS and NMOS transistors. """
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import contact
|
|||
import pgate
|
||||
import debug
|
||||
from tech import drc, parameter, spice
|
||||
from globals import OPTS
|
||||
from vector import vector
|
||||
import logical_effort
|
||||
from sram_factory import factory
|
||||
|
|
@ -37,6 +38,10 @@ class pnand2(pgate.pgate):
|
|||
debug.check(size == 1, "Size 1 pnand2 is only supported now.")
|
||||
self.tx_mults = 1
|
||||
|
||||
if OPTS.tech_name == "s8":
|
||||
(self.nmos_width, self.tx_mults) = self.bin_width("nmos", self.nmos_width)
|
||||
(self.pmos_width, self.tx_mults) = self.bin_width("pmos", self.pmos_width)
|
||||
|
||||
# Creates the netlist and layout
|
||||
pgate.pgate.__init__(self, name, height)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import logical_effort
|
|||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
|
||||
class pnand3(pgate.pgate):
|
||||
"""
|
||||
This module generates gds of a parametrically sized 2-input nand.
|
||||
|
|
@ -41,6 +40,10 @@ class pnand3(pgate.pgate):
|
|||
"Size 1 pnand3 is only supported now.")
|
||||
self.tx_mults = 1
|
||||
|
||||
if OPTS.tech_name == "s8":
|
||||
(self.nmos_width, self.tx_mults) = self.bin_width("nmos", self.nmos_width)
|
||||
(self.pmos_width, self.tx_mults) = self.bin_width("pmos", self.pmos_width)
|
||||
|
||||
# Creates the netlist and layout
|
||||
pgate.pgate.__init__(self, name, height)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
import contact
|
||||
import pgate
|
||||
import debug
|
||||
from globals import OPTS
|
||||
from tech import drc, parameter, spice
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
|
|
@ -36,6 +37,10 @@ class pnor2(pgate.pgate):
|
|||
debug.check(size==1, "Size 1 pnor2 is only supported now.")
|
||||
self.tx_mults = 1
|
||||
|
||||
if OPTS.tech_name == "s8":
|
||||
(self.nmos_width, self.tx_mults) = self.bin_width("nmos", self.nmos_width)
|
||||
(self.pmos_width, self.tx_mults) = self.bin_width("pmos", self.pmos_width)
|
||||
|
||||
# Creates the netlist and layout
|
||||
pgate.pgate.__init__(self, name, height)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
import contact
|
||||
import design
|
||||
import debug
|
||||
from pgate import pgate
|
||||
from tech import parameter
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
|
@ -28,6 +29,7 @@ class precharge(design.design):
|
|||
self.bitcell = factory.create(module_type="bitcell")
|
||||
self.beta = parameter["beta"]
|
||||
self.ptx_width = self.beta * parameter["min_tx_size"]
|
||||
self.ptx_mults = 1
|
||||
self.width = self.bitcell.width
|
||||
self.bitcell_bl = bitcell_bl
|
||||
self.bitcell_br = bitcell_br
|
||||
|
|
@ -78,8 +80,11 @@ class precharge(design.design):
|
|||
"""
|
||||
Initializes the upper and lower pmos
|
||||
"""
|
||||
if(OPTS.tech_name == "s8"):
|
||||
(self.ptx_width, self.ptx_mults) = pgate.bin_width(self, "pmos", self.ptx_width)
|
||||
self.pmos = factory.create(module_type="ptx",
|
||||
width=self.ptx_width,
|
||||
mults=self.ptx_mults,
|
||||
tx_type="pmos")
|
||||
self.add_mod(self.pmos)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue