Merge branch 'dev' into discrete_models

This commit is contained in:
jcirimel 2020-05-08 03:13:16 -07:00
commit 5666e79287
66 changed files with 1577 additions and 964 deletions

2
.gitignore vendored
View File

@ -8,3 +8,5 @@
*.toc *.toc
*.synctex.gz *.synctex.gz
**/model_data **/model_data
outputs
technology/freepdk45/ncsu_basekit

View File

@ -296,11 +296,11 @@ class path(geometry):
def __str__(self): def __str__(self):
""" override print function output """ """ override print function output """
return "path: layer=" + self.layerNumber + " w=" + self.width return "path: layer=" + self.layerNumber + " purpose=" + str(self.layerPurpose) + " w=" + self.width
def __repr__(self): def __repr__(self):
""" override print function output """ """ override print function output """
return "( path: layer=" + self.layerNumber + " w=" + self.width + " coords=" + str(self.coordinates) + " )" return "( path: layer=" + self.layerNumber + " purpose=" + str(self.layerPurpose) + " w=" + self.width + " coords=" + str(self.coordinates) + " )"
class label(geometry): class label(geometry):
@ -340,11 +340,11 @@ class label(geometry):
def __str__(self): def __str__(self):
""" override print function output """ """ override print function output """
return "label: " + self.text + " layer=" + str(self.layerNumber) return "label: " + self.text + " layer=" + str(self.layerNumber) + " purpose=" + str(self.layerPurpose)
def __repr__(self): def __repr__(self):
""" override print function output """ """ override print function output """
return "( label: " + self.text + " @" + str(self.offset) + " layer=" + str(self.layerNumber) + " )" return "( label: " + self.text + " @" + str(self.offset) + " layer=" + str(self.layerNumber) + " purpose=" + str(self.layerPurpose) + " )"
class rectangle(geometry): class rectangle(geometry):
@ -391,4 +391,4 @@ class rectangle(geometry):
def __repr__(self): def __repr__(self):
""" override print function output """ """ override print function output """
return "( rect: @" + str(self.offset) + " WxH=" + str(self.width) + "x" + str(self.height) + " layer=" + str(self.layerNumber) + " )" return "( rect: @" + str(self.offset) + " WxH=" + str(self.width) + "x" + str(self.height) + " layer=" + str(self.layerNumber) + " purpose=" + str(self.layerPurpose) + " )"

View File

@ -17,6 +17,7 @@ import os
from globals import OPTS from globals import OPTS
from vector import vector from vector import vector
from pin_layout import pin_layout from pin_layout import pin_layout
from utils import round_to_grid
class layout(): class layout():
@ -325,7 +326,7 @@ class layout():
file_name = "non_rectilinear.gds" file_name = "non_rectilinear.gds"
self.gds_write(file_name) self.gds_write(file_name)
debug.error("Cannot have a non-manhatten layout pin: {}".format(file_name), -1) debug.error("Cannot have a non-manhatten layout pin: {}".format(file_name), -1)
minwidth_layer = drc["minwidth_{}".format(layer)] minwidth_layer = drc["minwidth_{}".format(layer)]
# one of these will be zero # one of these will be zero
@ -974,6 +975,7 @@ class layout():
def create_channel_route(self, netlist, def create_channel_route(self, netlist,
offset, offset,
layer_stack, layer_stack,
layer_dirs=None,
vertical=False): vertical=False):
""" """
The net list is a list of the nets. Each net is a list of pins The net list is a list of the nets. Each net is a list of pins
@ -1012,25 +1014,38 @@ class layout():
def vcg_pin_overlap(pin1, pin2, vertical, pitch): def vcg_pin_overlap(pin1, pin2, vertical, pitch):
""" Check for vertical or horizontal overlap of the two pins """ """ Check for vertical or horizontal overlap of the two pins """
# FIXME: If the pins are not in a row, this may break. # FIXME: If the pins are not in a row, this may break.
# However, a top pin shouldn't overlap another top pin, # However, a top pin shouldn't overlap another top pin,
# for example, so the # for example, so the
# extra comparison *shouldn't* matter. # extra comparison *shouldn't* matter.
# Pin 1 must be in the "BOTTOM" set # Pin 1 must be in the "BOTTOM" set
x_overlap = pin1.by() < pin2.by() and abs(pin1.center().x-pin2.center().x)<pitch x_overlap = pin1.by() < pin2.by() and abs(pin1.center().x - pin2.center().x) < pitch
# Pin 1 must be in the "LEFT" set # Pin 1 must be in the "LEFT" set
y_overlap = pin1.lx() < pin2.lx() and abs(pin1.center().y-pin2.center().y)<pitch y_overlap = pin1.lx() < pin2.lx() and abs(pin1.center().y - pin2.center().y) < pitch
overlaps = (not vertical and x_overlap) or (vertical and y_overlap) overlaps = (not vertical and x_overlap) or (vertical and y_overlap)
return overlaps return overlaps
if self.get_preferred_direction(layer_stack[0]) == "V": if not layer_dirs:
self.vertical_layer = layer_stack[0] # Use the preferred layer directions
self.horizontal_layer = layer_stack[2] if self.get_preferred_direction(layer_stack[0]) == "V":
self.vertical_layer = layer_stack[0]
self.horizontal_layer = layer_stack[2]
else:
self.vertical_layer = layer_stack[2]
self.horizontal_layer = layer_stack[0]
else: else:
self.vertical_layer = layer_stack[2] # Use the layer directions specified to the router rather than
self.horizontal_layer = layer_stack[0] # the preferred directions
debug.check(layer_dirs[0] != layer_dirs[1], "Must have unique layer directions.")
if layer_dirs[0] == "V":
self.vertical_layer = layer_stack[0]
self.horizontal_layer = layer_stack[2]
else:
self.horizontal_layer = layer_stack[0]
self.vertical_layer = layer_stack[2]
layer_stuff = self.get_layer_pitch(self.vertical_layer) layer_stuff = self.get_layer_pitch(self.vertical_layer)
(self.vertical_pitch, self.vertical_width, self.vertical_space) = layer_stuff (self.vertical_pitch, self.vertical_width, self.vertical_space) = layer_stuff
@ -1113,17 +1128,17 @@ class layout():
self.horizontal_pitch) self.horizontal_pitch)
offset += vector(0, self.horizontal_pitch) offset += vector(0, self.horizontal_pitch)
def create_vertical_channel_route(self, netlist, offset, layer_stack): def create_vertical_channel_route(self, netlist, offset, layer_stack, layer_dirs=None):
""" """
Wrapper to create a vertical channel route Wrapper to create a vertical channel route
""" """
self.create_channel_route(netlist, offset, layer_stack, vertical=True) self.create_channel_route(netlist, offset, layer_stack, layer_dirs, vertical=True)
def create_horizontal_channel_route(self, netlist, offset, layer_stack): def create_horizontal_channel_route(self, netlist, offset, layer_stack, layer_dirs=None):
""" """
Wrapper to create a horizontal channel route Wrapper to create a horizontal channel route
""" """
self.create_channel_route(netlist, offset, layer_stack, vertical=False) self.create_channel_route(netlist, offset, layer_stack, layer_dirs, vertical=False)
def add_boundary(self, ll=vector(0, 0), ur=None): def add_boundary(self, ll=vector(0, 0), ur=None):
""" Add boundary for debugging dimensions """ """ Add boundary for debugging dimensions """
@ -1213,7 +1228,8 @@ class layout():
else: else:
# Hack for min area # Hack for min area
if OPTS.tech_name == "s8": if OPTS.tech_name == "s8":
height = width = sqrt(drc["minarea_m3"]) width = round_to_grid(sqrt(drc["minarea_m3"]))
height = round_to_grid(drc["minarea_m3"]/width)
else: else:
width = via.width width = via.width
height = via.height height = via.height

View File

@ -59,7 +59,8 @@ class delay(simulation):
""" Create measurement names. The names themselves currently define the type of measurement """ """ Create measurement names. The names themselves currently define the type of measurement """
self.delay_meas_names = ["delay_lh", "delay_hl", "slew_lh", "slew_hl"] self.delay_meas_names = ["delay_lh", "delay_hl", "slew_lh", "slew_hl"]
self.power_meas_names = ["read0_power", "read1_power", "write0_power", "write1_power"] self.power_meas_names = ["read0_power", "read1_power", "write0_power", "write1_power",
"disabled_read0_power", "disabled_read1_power", "disabled_write0_power", "disabled_write1_power"]
# self.voltage_when_names = ["volt_bl", "volt_br"] # self.voltage_when_names = ["volt_bl", "volt_br"]
# self.bitline_delay_names = ["delay_bl", "delay_br"] # self.bitline_delay_names = ["delay_bl", "delay_br"]
@ -108,6 +109,11 @@ class delay(simulation):
self.read_lib_meas.append(power_measure("read0_power", "FALL", measure_scale=1e3)) self.read_lib_meas.append(power_measure("read0_power", "FALL", measure_scale=1e3))
self.read_lib_meas[-1].meta_str = sram_op.READ_ZERO self.read_lib_meas[-1].meta_str = sram_op.READ_ZERO
self.read_lib_meas.append(power_measure("disabled_read1_power", "RISE", measure_scale=1e3))
self.read_lib_meas[-1].meta_str = "disabled_read1"
self.read_lib_meas.append(power_measure("disabled_read0_power", "FALL", measure_scale=1e3))
self.read_lib_meas[-1].meta_str = "disabled_read0"
# This will later add a half-period to the spice time delay. Only for reading 0. # This will later add a half-period to the spice time delay. Only for reading 0.
for obj in self.read_lib_meas: for obj in self.read_lib_meas:
if obj.meta_str is sram_op.READ_ZERO: if obj.meta_str is sram_op.READ_ZERO:
@ -156,6 +162,11 @@ class delay(simulation):
self.write_lib_meas.append(power_measure("write0_power", "FALL", measure_scale=1e3)) self.write_lib_meas.append(power_measure("write0_power", "FALL", measure_scale=1e3))
self.write_lib_meas[-1].meta_str = sram_op.WRITE_ZERO self.write_lib_meas[-1].meta_str = sram_op.WRITE_ZERO
self.write_lib_meas.append(power_measure("disabled_write1_power", "RISE", measure_scale=1e3))
self.write_lib_meas[-1].meta_str = "disabled_write1"
self.write_lib_meas.append(power_measure("disabled_write0_power", "FALL", measure_scale=1e3))
self.write_lib_meas[-1].meta_str = "disabled_write0"
write_measures = [] write_measures = []
write_measures.append(self.write_lib_meas) write_measures.append(self.write_lib_meas)
write_measures.append(self.create_write_bit_measures()) write_measures.append(self.create_write_bit_measures())
@ -665,7 +676,7 @@ class delay(simulation):
if not success: if not success:
feasible_period = 2 * feasible_period feasible_period = 2 * feasible_period
continue continue
# Positions of measurements currently hardcoded. First 2 are delays, next 2 are slews # Positions of measurements currently hardcoded. First 2 are delays, next 2 are slews
feasible_delays = [results[port][mname] for mname in self.delay_meas_names if "delay" in mname] feasible_delays = [results[port][mname] for mname in self.delay_meas_names if "delay" in mname]
feasible_slews = [results[port][mname] for mname in self.delay_meas_names if "slew" in mname] feasible_slews = [results[port][mname] for mname in self.delay_meas_names if "slew" in mname]
@ -1198,6 +1209,9 @@ class delay(simulation):
write_port) write_port)
self.measure_cycles[write_port][sram_op.WRITE_ZERO] = len(self.cycle_times)-1 self.measure_cycles[write_port][sram_op.WRITE_ZERO] = len(self.cycle_times)-1
self.add_noop_clock_one_port(write_port)
self.measure_cycles[write_port]["disabled_write0"] = len(self.cycle_times)-1
# This also ensures we will have a H->L transition on the next read # This also ensures we will have a H->L transition on the next read
self.add_read("R data 1 address {} to set dout caps".format(inverse_address), self.add_read("R data 1 address {} to set dout caps".format(inverse_address),
inverse_address, inverse_address,
@ -1208,6 +1222,10 @@ class delay(simulation):
read_port) read_port)
self.measure_cycles[read_port][sram_op.READ_ZERO] = len(self.cycle_times)-1 self.measure_cycles[read_port][sram_op.READ_ZERO] = len(self.cycle_times)-1
self.add_noop_clock_one_port(read_port)
self.measure_cycles[read_port]["disabled_read0"] = len(self.cycle_times) - 1
self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)") self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)")
self.add_write("W data 1 address {} to write value".format(self.probe_address), self.add_write("W data 1 address {} to write value".format(self.probe_address),
@ -1217,12 +1235,19 @@ class delay(simulation):
write_port) write_port)
self.measure_cycles[write_port][sram_op.WRITE_ONE] = len(self.cycle_times)-1 self.measure_cycles[write_port][sram_op.WRITE_ONE] = len(self.cycle_times)-1
self.add_noop_clock_one_port(write_port)
self.measure_cycles[write_port]["disabled_write1"] = len(self.cycle_times)-1
self.add_write("W data 0 address {} to clear din caps".format(inverse_address), self.add_write("W data 0 address {} to clear din caps".format(inverse_address),
inverse_address, inverse_address,
data_zeros, data_zeros,
wmask_ones, wmask_ones,
write_port) write_port)
self.add_noop_clock_one_port(read_port)
self.measure_cycles[read_port]["disabled_read1"] = len(self.cycle_times) - 1
# This also ensures we will have a L->H transition on the next read # This also ensures we will have a L->H transition on the next read
self.add_read("R data 0 address {} to clear dout caps".format(inverse_address), self.add_read("R data 0 address {} to clear dout caps".format(inverse_address),
inverse_address, inverse_address,

View File

@ -181,17 +181,20 @@ class lib:
self.lib.write(" dont_touch : true;\n") self.lib.write(" dont_touch : true;\n")
self.lib.write(" area : {};\n\n".format(self.sram.width * self.sram.height)) self.lib.write(" area : {};\n\n".format(self.sram.width * self.sram.height))
#Build string of all control signals. self.write_pg_pin()
#Build string of all control signals.
control_str = 'csb0' #assume at least 1 port control_str = 'csb0' #assume at least 1 port
for i in range(1, self.total_port_num): for i in range(1, self.total_port_num):
control_str += ' & csb{0}'.format(i) control_str += ' & csb{0}'.format(i)
# Leakage is included in dynamic when macro is enabled # Leakage is included in dynamic when macro is enabled
self.lib.write(" leakage_power () {\n") self.lib.write(" leakage_power () {\n")
self.lib.write(" when : \"{0}\";\n".format(control_str)) # 'when' condition unnecessary when cs pin does not turn power to devices
# self.lib.write(" when : \"{0}\";\n".format(control_str))
self.lib.write(" value : {};\n".format(self.char_sram_results["leakage_power"])) self.lib.write(" value : {};\n".format(self.char_sram_results["leakage_power"]))
self.lib.write(" }\n") self.lib.write(" }\n")
self.lib.write(" cell_leakage_power : {};\n".format(0)) self.lib.write(" cell_leakage_power : {};\n".format(self.char_sram_results["leakage_power"]))
def write_units(self): def write_units(self):
@ -240,6 +243,9 @@ class lib:
self.lib.write(" default_max_fanout : 4.0 ;\n") self.lib.write(" default_max_fanout : 4.0 ;\n")
self.lib.write(" default_connection_class : universal ;\n\n") self.lib.write(" default_connection_class : universal ;\n\n")
self.lib.write(" voltage_map ( VDD, {} );\n".format(tech.spice["nom_supply_voltage"]))
self.lib.write(" voltage_map ( GND, 0 );\n\n")
def create_list(self,values): def create_list(self,values):
""" Helper function to create quoted, line wrapped list """ """ Helper function to create quoted, line wrapped list """
list_values = ", ".join(str(v) for v in values) list_values = ", ".join(str(v) for v in values)
@ -516,42 +522,69 @@ class lib:
if port in self.write_ports: if port in self.write_ports:
if port in self.read_ports: if port in self.read_ports:
web_name = " & !web{0}".format(port) web_name = " & !web{0}".format(port)
avg_write_power = np.mean(self.char_port_results[port]["write1_power"] + self.char_port_results[port]["write0_power"]) write1_power = np.mean(self.char_port_results[port]["write1_power"])
write0_power = np.mean(self.char_port_results[port]["write0_power"])
self.lib.write(" internal_power(){\n") self.lib.write(" internal_power(){\n")
self.lib.write(" when : \"!csb{0} & clk{0}{1}\"; \n".format(port, web_name)) self.lib.write(" when : \"!csb{0}{1}\"; \n".format(port, web_name))
self.lib.write(" rise_power(scalar){\n") self.lib.write(" rise_power(scalar){\n")
self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0)) self.lib.write(" values(\"{0:.6e}\");\n".format(write1_power))
self.lib.write(" }\n") self.lib.write(" }\n")
self.lib.write(" fall_power(scalar){\n") self.lib.write(" fall_power(scalar){\n")
self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0)) self.lib.write(" values(\"{0:.6e}\");\n".format(write0_power))
self.lib.write(" }\n")
self.lib.write(" }\n")
# Disabled power.
disabled_write1_power = np.mean(self.char_port_results[port]["disabled_write1_power"])
disabled_write0_power = np.mean(self.char_port_results[port]["disabled_write0_power"])
self.lib.write(" internal_power(){\n")
self.lib.write(" when : \"csb{0}{1}\"; \n".format(port, web_name))
self.lib.write(" rise_power(scalar){\n")
self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_write1_power))
self.lib.write(" }\n")
self.lib.write(" fall_power(scalar){\n")
self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_write0_power))
self.lib.write(" }\n") self.lib.write(" }\n")
self.lib.write(" }\n") self.lib.write(" }\n")
if port in self.read_ports: if port in self.read_ports:
if port in self.write_ports: if port in self.write_ports:
web_name = " & web{0}".format(port) web_name = " & web{0}".format(port)
avg_read_power = np.mean(self.char_port_results[port]["read1_power"] + self.char_port_results[port]["read0_power"]) read1_power = np.mean(self.char_port_results[port]["read1_power"])
read0_power = np.mean(self.char_port_results[port]["read0_power"])
self.lib.write(" internal_power(){\n") self.lib.write(" internal_power(){\n")
self.lib.write(" when : \"!csb{0} & !clk{0}{1}\"; \n".format(port, web_name)) self.lib.write(" when : \"!csb{0}{1}\"; \n".format(port, web_name))
self.lib.write(" rise_power(scalar){\n") self.lib.write(" rise_power(scalar){\n")
self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0)) self.lib.write(" values(\"{0:.6e}\");\n".format(read1_power))
self.lib.write(" }\n") self.lib.write(" }\n")
self.lib.write(" fall_power(scalar){\n") self.lib.write(" fall_power(scalar){\n")
self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0)) self.lib.write(" values(\"{0:.6e}\");\n".format(read0_power))
self.lib.write(" }\n") self.lib.write(" }\n")
self.lib.write(" }\n") self.lib.write(" }\n")
# Have 0 internal power when disabled, this will be represented as leakage power. # Disabled power.
self.lib.write(" internal_power(){\n") disabled_read1_power = np.mean(self.char_port_results[port]["disabled_read1_power"])
self.lib.write(" when : \"csb{0}\"; \n".format(port)) disabled_read0_power = np.mean(self.char_port_results[port]["disabled_read0_power"])
self.lib.write(" rise_power(scalar){\n") self.lib.write(" internal_power(){\n")
self.lib.write(" values(\"0\");\n") self.lib.write(" when : \"csb{0}{1}\"; \n".format(port, web_name))
self.lib.write(" }\n") self.lib.write(" rise_power(scalar){\n")
self.lib.write(" fall_power(scalar){\n") self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read1_power))
self.lib.write(" values(\"0\");\n") self.lib.write(" }\n")
self.lib.write(" }\n") self.lib.write(" fall_power(scalar){\n")
self.lib.write(" }\n") self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read0_power))
self.lib.write(" }\n")
self.lib.write(" }\n")
def write_pg_pin(self):
self.lib.write(" pg_pin(vdd) {\n")
self.lib.write(" voltage_name : VDD;\n")
self.lib.write(" pg_type : primary_power;\n")
self.lib.write(" }\n\n")
self.lib.write(" pg_pin(gnd) {\n")
self.lib.write(" voltage_name : GND;\n")
self.lib.write(" pg_type : primary_ground;\n")
self.lib.write(" }\n\n")
def compute_delay(self): def compute_delay(self):
"""Compute SRAM delays for current corner""" """Compute SRAM delays for current corner"""
self.d = delay(self.sram, self.sp_file, self.corner) self.d = delay(self.sram, self.sp_file, self.corner)

View File

@ -279,6 +279,23 @@ class simulation():
except: except:
self.add_wmask("0"*self.num_wmasks, port) self.add_wmask("0"*self.num_wmasks, port)
def add_noop_clock_one_port(self, port):
""" Add the control values for a noop to a single port. Increments the period. """
debug.info(2, 'Clock only on port {}'.format(port))
self.fn_cycle_comments.append('Clock only on port {}'.format(port))
self.append_cycle_comment(port, 'Clock only on port {}'.format(port))
self.cycle_times.append(self.t_current)
self.t_current += self.period
self.add_noop_one_port(port)
#Add noops to all other ports.
for unselected_port in self.all_ports:
if unselected_port != port:
self.add_noop_one_port(unselected_port)
def append_cycle_comment(self, port, comment): def append_cycle_comment(self, port, comment):
"""Add comment to list to be printed in stimulus file""" """Add comment to list to be printed in stimulus file"""
#Clean up time before appending. Make spacing dynamic as well. #Clean up time before appending. Make spacing dynamic as well.

View File

@ -19,7 +19,7 @@ import re
import copy import copy
import importlib import importlib
VERSION = "1.1.4" VERSION = "1.1.5"
NAME = "OpenRAM v{}".format(VERSION) NAME = "OpenRAM v{}".format(VERSION)
USAGE = "openram.py [options] <config file>\nUse -h for help.\n" USAGE = "openram.py [options] <config file>\nUse -h for help.\n"

View File

@ -28,7 +28,6 @@ class bitcell_array(bitcell_base_array):
# the replica bitcell in the control logic # the replica bitcell in the control logic
# self.offset_all_coordinates() # self.offset_all_coordinates()
def create_netlist(self): def create_netlist(self):
""" Create and connect the netlist """ """ Create and connect the netlist """
self.add_modules() self.add_modules()
@ -56,22 +55,21 @@ class bitcell_array(bitcell_base_array):
for col in range(self.column_size): for col in range(self.column_size):
for row in range(self.row_size): for row in range(self.row_size):
name = "bit_r{0}_c{1}".format(row, col) name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row,col]=self.add_inst(name=name, self.cell_inst[row, col]=self.add_inst(name=name,
mod=self.cell) mod=self.cell)
self.connect_inst(self.get_bitcell_pins(col, row)) self.connect_inst(self.get_bitcell_pins(col, row))
def analytical_power(self, corner, load): def analytical_power(self, corner, load):
"""Power of Bitcell array and bitline in nW.""" """Power of Bitcell array and bitline in nW."""
from tech import drc, parameter
# Dynamic Power from Bitline # Dynamic Power from Bitline
bl_wire = self.gen_bl_wire() bl_wire = self.gen_bl_wire()
cell_load = 2 * bl_wire.return_input_cap() cell_load = 2 * bl_wire.return_input_cap()
bl_swing = OPTS.rbl_delay_percentage bl_swing = OPTS.rbl_delay_percentage
freq = spice["default_event_frequency"] freq = spice["default_event_frequency"]
bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing) bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing)
# Calculate the bitcell power which currently only includes leakage # Calculate the bitcell power which currently only includes leakage
cell_power = self.cell.analytical_power(corner, load) cell_power = self.cell.analytical_power(corner, load)
# Leakage power grows with entire array and bitlines. # Leakage power grows with entire array and bitlines.
@ -85,7 +83,7 @@ class bitcell_array(bitcell_base_array):
else: else:
width = self.width width = self.width
wl_wire = self.generate_rc_net(int(self.column_size), width, drc("minwidth_m1")) wl_wire = self.generate_rc_net(int(self.column_size), width, drc("minwidth_m1"))
wl_wire.wire_c = 2*spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell wl_wire.wire_c = 2 * spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell
return wl_wire return wl_wire
def gen_bl_wire(self): def gen_bl_wire(self):
@ -94,26 +92,26 @@ class bitcell_array(bitcell_base_array):
else: else:
height = self.height height = self.height
bl_pos = 0 bl_pos = 0
bl_wire = self.generate_rc_net(int(self.row_size-bl_pos), height, drc("minwidth_m1")) bl_wire = self.generate_rc_net(int(self.row_size - bl_pos), height, drc("minwidth_m1"))
bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell
return bl_wire return bl_wire
def get_wordline_cin(self): def get_wordline_cin(self):
"""Get the relative input capacitance from the wordline connections in all the bitcell""" """Get the relative input capacitance from the wordline connections in all the bitcell"""
#A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns # A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns
bitcell_wl_cin = self.cell.get_wl_cin() bitcell_wl_cin = self.cell.get_wl_cin()
total_cin = bitcell_wl_cin * self.column_size total_cin = bitcell_wl_cin * self.column_size
return total_cin return total_cin
def graph_exclude_bits(self, targ_row, targ_col): def graph_exclude_bits(self, targ_row, targ_col):
"""Excludes bits in column from being added to graph except target""" """Excludes bits in column from being added to graph except target"""
#Function is not robust with column mux configurations # Function is not robust with column mux configurations
for row in range(self.row_size): for row in range(self.row_size):
for col in range(self.column_size): for col in range(self.column_size):
if row == targ_row and col == targ_col: if row == targ_row and col == targ_col:
continue continue
self.graph_inst_exclude.add(self.cell_inst[row,col]) self.graph_inst_exclude.add(self.cell_inst[row, col])
def get_cell_name(self, inst_name, row, col): def get_cell_name(self, inst_name, row, col):
"""Gets the spice name of the target bitcell.""" """Gets the spice name of the target bitcell."""
return inst_name+'.x'+self.cell_inst[row,col].name, self.cell_inst[row,col] return inst_name + '.x' + self.cell_inst[row, col].name, self.cell_inst[row, col]

View File

@ -90,7 +90,7 @@ class control_logic(design.design):
self.add_mod(self.ctrl_dff_array) self.add_mod(self.ctrl_dff_array)
self.and2 = factory.create(module_type="pand2", self.and2 = factory.create(module_type="pand2",
size=4, size=12,
height=dff_height) height=dff_height)
self.add_mod(self.and2) self.add_mod(self.and2)

View File

@ -7,12 +7,11 @@
# #
import debug import debug
import design import design
from tech import drc
from contact import contact
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from sram_factory import factory from sram_factory import factory
class delay_chain(design.design): class delay_chain(design.design):
""" """
Generate a delay chain with the given number of stages and fanout. Generate a delay chain with the given number of stages and fanout.
@ -28,7 +27,7 @@ class delay_chain(design.design):
# Two fanouts are needed so that we can route the vdd/gnd connections # Two fanouts are needed so that we can route the vdd/gnd connections
for f in fanout_list: for f in fanout_list:
debug.check(f>=2,"Must have >=2 fanouts for each stage.") debug.check(f>=2, "Must have >=2 fanouts for each stage.")
# number of inverters including any fanout loads. # number of inverters including any fanout loads.
self.fanout_list = fanout_list self.fanout_list = fanout_list
@ -36,7 +35,6 @@ class delay_chain(design.design):
self.create_netlist() self.create_netlist()
if not OPTS.netlist_only: if not OPTS.netlist_only:
self.create_layout() self.create_layout()
def create_netlist(self): def create_netlist(self):
self.add_modules() self.add_modules()
@ -45,12 +43,13 @@ class delay_chain(design.design):
def create_layout(self): def create_layout(self):
# Each stage is a a row # Each stage is a a row
self.height = len(self.fanout_list)*self.inv.height self.height = len(self.fanout_list) * self.inv.height
# The width is determined by the largest fanout plus the driver # The width is determined by the largest fanout plus the driver
self.width = (max(self.fanout_list)+1) * self.inv.width self.width = (max(self.fanout_list) + 1) * self.inv.width
self.place_inverters() self.place_inverters()
self.route_inverters() self.route_inverters()
self.route_supplies()
self.add_layout_pins() self.add_layout_pins()
self.add_boundary() self.add_boundary()
self.DRC_LVS() self.DRC_LVS()
@ -69,9 +68,8 @@ class delay_chain(design.design):
def create_inverters(self): def create_inverters(self):
""" Create the inverters and connect them based on the stage list """ """ Create the inverters and connect them based on the stage list """
self.driver_inst_list = [] self.driver_inst_list = []
self.rightest_load_inst = {}
self.load_inst_map = {} self.load_inst_map = {}
for stage_num,fanout_size in zip(range(len(self.fanout_list)),self.fanout_list): for stage_num, fanout_size in zip(range(len(self.fanout_list)), self.fanout_list):
# Add the inverter # Add the inverter
cur_driver=self.add_inst(name="dinv{}".format(stage_num), cur_driver=self.add_inst(name="dinv{}".format(stage_num),
mod=self.inv) mod=self.inv)
@ -79,40 +77,37 @@ class delay_chain(design.design):
self.driver_inst_list.append(cur_driver) self.driver_inst_list.append(cur_driver)
# Hook up the driver # Hook up the driver
if stage_num+1==len(self.fanout_list): if stage_num + 1 == len(self.fanout_list):
stageout_name = "out" stageout_name = "out"
else: else:
stageout_name = "dout_{}".format(stage_num+1) stageout_name = "dout_{}".format(stage_num + 1)
if stage_num == 0: if stage_num == 0:
stagein_name = "in" stagein_name = "in"
else: else:
stagein_name = "dout_{}".format(stage_num) stagein_name = "dout_{}".format(stage_num)
self.connect_inst([stagein_name, stageout_name, "vdd", "gnd"]) self.connect_inst([stagein_name, stageout_name, "vdd", "gnd"])
# Now add the dummy loads to the right # Now add the dummy loads to the right
self.load_inst_map[cur_driver]=[] self.load_inst_map[cur_driver]=[]
for i in range(fanout_size): for i in range(fanout_size):
cur_load=self.add_inst(name="dload_{0}_{1}".format(stage_num,i), cur_load=self.add_inst(name="dload_{0}_{1}".format(stage_num, i),
mod=self.inv) mod=self.inv)
# Fanout stage is always driven by driver and output is disconnected # Fanout stage is always driven by driver and output is disconnected
disconnect_name = "n_{0}_{1}".format(stage_num,i) disconnect_name = "n_{0}_{1}".format(stage_num, i)
self.connect_inst([stageout_name, disconnect_name, "vdd", "gnd"]) self.connect_inst([stageout_name, disconnect_name, "vdd", "gnd"])
# Keep track of all the loads to connect their inputs as a load # Keep track of all the loads to connect their inputs as a load
self.load_inst_map[cur_driver].append(cur_load) self.load_inst_map[cur_driver].append(cur_load)
else:
# Keep track of the last one so we can add the the wire later
self.rightest_load_inst[cur_driver]=cur_load
def place_inverters(self): def place_inverters(self):
""" Place the inverters and connect them based on the stage list """ """ Place the inverters and connect them based on the stage list """
for stage_num,fanout_size in zip(range(len(self.fanout_list)),self.fanout_list): for stage_num, fanout_size in zip(range(len(self.fanout_list)), self.fanout_list):
if stage_num % 2: if stage_num % 2:
inv_mirror = "MX" inv_mirror = "MX"
inv_offset = vector(0, (stage_num+1)* self.inv.height) inv_offset = vector(0, (stage_num + 1) * self.inv.height)
else: else:
inv_mirror = "R0" inv_mirror = "R0"
inv_offset = vector(0, stage_num * self.inv.height) inv_offset = vector(0, stage_num * self.inv.height)
# Add the inverter # Add the inverter
cur_driver=self.driver_inst_list[stage_num] cur_driver=self.driver_inst_list[stage_num]
@ -122,10 +117,9 @@ class delay_chain(design.design):
# Now add the dummy loads to the right # Now add the dummy loads to the right
load_list = self.load_inst_map[cur_driver] load_list = self.load_inst_map[cur_driver]
for i in range(fanout_size): for i in range(fanout_size):
inv_offset += vector(self.inv.width,0) inv_offset += vector(self.inv.width, 0)
load_list[i].place(offset=inv_offset, load_list[i].place(offset=inv_offset,
mirror=inv_mirror) mirror=inv_mirror)
def add_route(self, pin1, pin2): def add_route(self, pin1, pin2):
""" This guarantees that we route from the top to bottom row correctly. """ """ This guarantees that we route from the top to bottom row correctly. """
@ -134,9 +128,9 @@ class delay_chain(design.design):
if pin1_pos.y == pin2_pos.y: if pin1_pos.y == pin2_pos.y:
self.add_path("m2", [pin1_pos, pin2_pos]) self.add_path("m2", [pin1_pos, pin2_pos])
else: else:
mid_point = vector(pin2_pos.x, 0.5*(pin1_pos.y+pin2_pos.y)) mid_point = vector(pin2_pos.x, 0.5 * (pin1_pos.y + pin2_pos.y))
# Written this way to guarantee it goes right first if we are switching rows # Written this way to guarantee it goes right first if we are switching rows
self.add_path("m2", [pin1_pos, vector(pin1_pos.x,mid_point.y), mid_point, vector(mid_point.x,pin2_pos.y), pin2_pos]) self.add_path("m2", [pin1_pos, vector(pin1_pos.x, mid_point.y), mid_point, vector(mid_point.x, pin2_pos.y), pin2_pos])
def route_inverters(self): def route_inverters(self):
""" Add metal routing for each of the fanout stages """ """ Add metal routing for each of the fanout stages """
@ -145,7 +139,7 @@ class delay_chain(design.design):
inv = self.driver_inst_list[i] inv = self.driver_inst_list[i]
for load in self.load_inst_map[inv]: for load in self.load_inst_map[inv]:
# Drop a via on each A pin # Drop a via on each A pin
a_pin = load.get_pin("A") a_pin = load.get_pin("A")
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.m1_stack,
offset=a_pin.center()) offset=a_pin.center())
self.add_via_center(layers=self.m2_stack, self.add_via_center(layers=self.m2_stack,
@ -154,54 +148,42 @@ class delay_chain(design.design):
# Route an M3 horizontal wire to the furthest # Route an M3 horizontal wire to the furthest
z_pin = inv.get_pin("Z") z_pin = inv.get_pin("Z")
a_pin = inv.get_pin("A") a_pin = inv.get_pin("A")
a_max = self.rightest_load_inst[inv].get_pin("A") a_max = self.load_inst_map[inv][-1].get_pin("A")
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.m1_stack,
offset=a_pin.center()) offset=a_pin.center())
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.m1_stack,
offset=z_pin.center()) offset=z_pin.center())
self.add_via_center(layers=self.m2_stack, self.add_via_center(layers=self.m2_stack,
offset=z_pin.center()) offset=z_pin.center())
self.add_path("m3",[z_pin.center(), a_max.center()]) self.add_path("m3", [z_pin.center(), a_max.center()])
# Route Z to the A of the next stage # Route Z to the A of the next stage
if i+1 < len(self.driver_inst_list): if i + 1 < len(self.driver_inst_list):
z_pin = inv.get_pin("Z") z_pin = inv.get_pin("Z")
next_inv = self.driver_inst_list[i+1] next_inv = self.driver_inst_list[i + 1]
next_a_pin = next_inv.get_pin("A") next_a_pin = next_inv.get_pin("A")
y_mid = (z_pin.cy() + next_a_pin.cy())/2 y_mid = (z_pin.cy() + next_a_pin.cy()) / 2
mid1_point = vector(z_pin.cx(), y_mid) mid1_point = vector(z_pin.cx(), y_mid)
mid2_point = vector(next_a_pin.cx(), y_mid) mid2_point = vector(next_a_pin.cx(), y_mid)
self.add_path("m2",[z_pin.center(), mid1_point, mid2_point, next_a_pin.center()]) self.add_path("m2", [z_pin.center(), mid1_point, mid2_point, next_a_pin.center()])
def add_layout_pins(self):
""" Add vdd and gnd rails and the input/output. Connect the gnd rails internally on
the top end with no input/output to obstruct. """
def route_supplies(self):
# Add power and ground to all the cells except: # Add power and ground to all the cells except:
# the fanout driver, the right-most load # the fanout driver, the right-most load
# The routing to connect the loads is over the first and last cells # The routing to connect the loads is over the first and last cells
# We have an even number of drivers and must only do every other # We have an even number of drivers and must only do every other
# supply rail # supply rail
for i in range(0,len(self.driver_inst_list),2):
inv = self.driver_inst_list[i]
for load in self.load_inst_map[inv]:
if load==self.rightest_load_inst[inv]:
continue
for pin_name in ["vdd", "gnd"]:
pin = load.get_pin(pin_name)
self.add_power_pin(pin_name, pin.rc())
else:
# We have an even number of rows, so need to get the last gnd rail
inv = self.driver_inst_list[-1]
for load in self.load_inst_map[inv]:
if load==self.rightest_load_inst[inv]:
continue
pin_name = "gnd"
pin = load.get_pin(pin_name)
self.add_power_pin(pin_name, pin.rc())
for inst in self.driver_inst_list:
load_list = self.load_inst_map[inst]
for pin_name in ["vdd", "gnd"]:
pin = load_list[0].get_pin(pin_name)
self.add_power_pin(pin_name, pin.rc() - vector(self.m1_pitch, 0))
pin = load_list[-1].get_pin(pin_name)
self.add_power_pin(pin_name, pin.rc() - vector(0.5 * self.m1_pitch, 0))
def add_layout_pins(self):
# input is A pin of first inverter # input is A pin of first inverter
a_pin = self.driver_inst_list[0].get_pin("A") a_pin = self.driver_inst_list[0].get_pin("A")
@ -209,36 +191,36 @@ class delay_chain(design.design):
offset=a_pin.center()) offset=a_pin.center())
self.add_layout_pin(text="in", self.add_layout_pin(text="in",
layer="m2", layer="m2",
offset=a_pin.ll().scale(1,0), offset=a_pin.ll().scale(1, 0),
height=a_pin.cy()) height=a_pin.cy())
# output is A pin of last load inverter # output is A pin of last load inverter
last_driver_inst = self.driver_inst_list[-1] last_driver_inst = self.driver_inst_list[-1]
a_pin = self.rightest_load_inst[last_driver_inst].get_pin("A") a_pin = self.load_inst_map[last_driver_inst][-1].get_pin("A")
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.m1_stack,
offset=a_pin.center()) offset=a_pin.center())
mid_point = vector(a_pin.cx()+3*self.m2_width,a_pin.cy()) mid_point = vector(a_pin.cx() + 3 * self.m2_width, a_pin.cy())
self.add_path("m2",[a_pin.center(), mid_point, mid_point.scale(1,0)]) self.add_path("m2", [a_pin.center(), mid_point, mid_point.scale(1, 0)])
self.add_layout_pin_segment_center(text="out", self.add_layout_pin_segment_center(text="out",
layer="m2", layer="m2",
start=mid_point, start=mid_point,
end=mid_point.scale(1,0)) end=mid_point.scale(1, 0))
def get_cin(self): def get_cin(self):
"""Get the enable input ralative capacitance""" """Get the enable input ralative capacitance"""
#Only 1 input to the delay chain which is connected to an inverter. # Only 1 input to the delay chain which is connected to an inverter.
dc_cin = self.inv.get_cin() dc_cin = self.inv.get_cin()
return dc_cin return dc_cin
def determine_delayed_en_stage_efforts(self, ext_delayed_en_cout, inp_is_rise=True): def determine_delayed_en_stage_efforts(self, ext_delayed_en_cout, inp_is_rise=True):
"""Get the stage efforts from the en to s_en. Does not compute the delay for the bitline load.""" """Get the stage efforts from the en to s_en. Does not compute the delay for the bitline load."""
stage_effort_list = [] stage_effort_list = []
#Add a stage to the list for every stage in delay chain. Stages only differ in fanout except the last which has an external cout. # Add a stage to the list for every stage in delay chain.
# Stages only differ in fanout except the last which has an external cout.
last_stage_is_rise = inp_is_rise last_stage_is_rise = inp_is_rise
for stage_fanout in self.fanout_list: for stage_fanout in self.fanout_list:
stage_cout = self.inv.get_cin()*(stage_fanout+1) stage_cout = self.inv.get_cin() * (stage_fanout + 1)
if len(stage_effort_list) == len(self.fanout_list)-1: #last stage if len(stage_effort_list) == len(self.fanout_list) - 1:
stage_cout+=ext_delayed_en_cout stage_cout+=ext_delayed_en_cout
stage = self.inv.get_stage_effort(stage_cout, last_stage_is_rise) stage = self.inv.get_stage_effort(stage_cout, last_stage_is_rise)
stage_effort_list.append(stage) stage_effort_list.append(stage)

View File

@ -35,7 +35,7 @@ class dff_buf(design.design):
# This causes a DRC in the pinv which assumes min width rails. This ensures the output # This causes a DRC in the pinv which assumes min width rails. This ensures the output
# contact does not violate spacing to the rail in the NMOS. # contact does not violate spacing to the rail in the NMOS.
debug.check(inv1_size>=2, "Inverter must be greater than two for rail spacing DRC rules.") debug.check(inv1_size>=2, "Inverter must be greater than two for rail spacing DRC rules.")
debug.check(inv2_size>=2, "Inverter must be greater than two for rail spacing DRC rules.") debug.check(inv2_size>=2, "Inverter must be greater than two for rail spacing DRC rules.")
self.inv1_size=inv1_size self.inv1_size=inv1_size
self.inv2_size=inv2_size self.inv2_size=inv2_size
@ -52,14 +52,13 @@ class dff_buf(design.design):
def create_layout(self): def create_layout(self):
self.place_instances() self.place_instances()
self.width = self.inv2_inst.rx() self.width = self.inv2_inst.rx()
self.height = self.dff.height self.height = self.dff.height
self.route_wires() self.route_wires()
self.add_layout_pins() self.add_layout_pins()
self.add_boundary() self.add_boundary()
self.DRC_LVS() self.DRC_LVS()
def add_modules(self): def add_modules(self):
self.dff = factory.create(module_type="dff") self.dff = factory.create(module_type="dff")
self.add_mod(self.dff) self.add_mod(self.dff)
@ -73,8 +72,6 @@ class dff_buf(design.design):
size=self.inv2_size, size=self.inv2_size,
height=self.dff.height) height=self.dff.height)
self.add_mod(self.inv2) self.add_mod(self.inv2)
def add_pins(self): def add_pins(self):
self.add_pin("D", "INPUT") self.add_pin("D", "INPUT")
@ -96,17 +93,19 @@ class dff_buf(design.design):
self.inv1_inst=self.add_inst(name="dff_buf_inv1", self.inv1_inst=self.add_inst(name="dff_buf_inv1",
mod=self.inv1) mod=self.inv1)
self.connect_inst(["qint", "Qb", "vdd", "gnd"]) self.connect_inst(["qint", "Qb", "vdd", "gnd"])
self.inv2_inst=self.add_inst(name="dff_buf_inv2", self.inv2_inst=self.add_inst(name="dff_buf_inv2",
mod=self.inv2) mod=self.inv2)
self.connect_inst(["Qb", "Q", "vdd", "gnd"]) self.connect_inst(["Qb", "Q", "vdd", "gnd"])
def place_instances(self): def place_instances(self):
# Add the DFF # Add the DFF
self.dff_inst.place(vector(0,0)) self.dff_inst.place(vector(0, 0))
# Add INV1 to the right # Add INV1 to the right
# The INV needs well spacing because the DFF is likely from a library
# with different well construction rules
well_spacing = 0 well_spacing = 0
try: try:
well_spacing = max(well_spacing, self.nwell_space) well_spacing = max(well_spacing, self.nwell_space)
@ -129,7 +128,7 @@ class dff_buf(design.design):
# Route dff q to inv1 a # Route dff q to inv1 a
q_pin = self.dff_inst.get_pin("Q") q_pin = self.dff_inst.get_pin("Q")
a1_pin = self.inv1_inst.get_pin("A") a1_pin = self.inv1_inst.get_pin("A")
mid_x_offset = 0.5*(a1_pin.cx() + q_pin.cx()) mid_x_offset = 0.5 * (a1_pin.cx() + q_pin.cx())
mid1 = vector(mid_x_offset, q_pin.cy()) mid1 = vector(mid_x_offset, q_pin.cy())
mid2 = vector(mid_x_offset, a1_pin.cy()) mid2 = vector(mid_x_offset, a1_pin.cy())
self.add_path("m3", [q_pin.center(), mid1, mid2, a1_pin.center()]) self.add_path("m3", [q_pin.center(), mid1, mid2, a1_pin.center()])
@ -143,7 +142,7 @@ class dff_buf(design.design):
# Route inv1 z to inv2 a # Route inv1 z to inv2 a
z1_pin = self.inv1_inst.get_pin("Z") z1_pin = self.inv1_inst.get_pin("Z")
a2_pin = self.inv2_inst.get_pin("A") a2_pin = self.inv2_inst.get_pin("A")
mid_x_offset = 0.5*(z1_pin.cx() + a2_pin.cx()) mid_x_offset = 0.5 * (z1_pin.cx() + a2_pin.cx())
self.mid_qb_pos = vector(mid_x_offset, z1_pin.cy()) self.mid_qb_pos = vector(mid_x_offset, z1_pin.cy())
mid2 = vector(mid_x_offset, a2_pin.cy()) mid2 = vector(mid_x_offset, a2_pin.cy())
self.add_path("m1", [z1_pin.center(), self.mid_qb_pos, mid2, a2_pin.center()]) self.add_path("m1", [z1_pin.center(), self.mid_qb_pos, mid2, a2_pin.center()])
@ -181,8 +180,8 @@ class dff_buf(design.design):
height=din_pin.height()) height=din_pin.height())
dout_pin = self.inv2_inst.get_pin("Z") dout_pin = self.inv2_inst.get_pin("Z")
mid_pos = dout_pin.center() + vector(self.m1_pitch,0) mid_pos = dout_pin.center() + vector(self.m1_pitch, 0)
q_pos = mid_pos - vector(0,self.m2_pitch) q_pos = mid_pos - vector(0, self.m2_pitch)
self.add_layout_pin_rect_center(text="Q", self.add_layout_pin_rect_center(text="Q",
layer="m2", layer="m2",
offset=q_pos) offset=q_pos)
@ -190,7 +189,7 @@ class dff_buf(design.design):
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.m1_stack,
offset=q_pos) offset=q_pos)
qb_pos = self.mid_qb_pos + vector(0,self.m2_pitch) qb_pos = self.mid_qb_pos + vector(0, self.m2_pitch)
self.add_layout_pin_rect_center(text="Qb", self.add_layout_pin_rect_center(text="Qb",
layer="m2", layer="m2",
offset=qb_pos) offset=qb_pos)
@ -200,7 +199,7 @@ class dff_buf(design.design):
def get_clk_cin(self): def get_clk_cin(self):
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff""" """Return the total capacitance (in relative units) that the clock is loaded by in the dff"""
#This is a handmade cell so the value must be entered in the tech.py file or estimated. # This is a handmade cell so the value must be entered in the tech.py file or estimated.
#Calculated in the tech file by summing the widths of all the gates and dividing by the minimum width. # Calculated in the tech file by summing the widths of all the gates and dividing by the minimum width.
#FIXME: Dff changed in a past commit. The parameter need to be updated. # FIXME: Dff changed in a past commit. The parameter need to be updated.
return parameter["dff_clk_cin"] return parameter["dff_clk_cin"]

View File

@ -7,13 +7,12 @@
# #
import debug import debug
import design import design
from tech import drc
from tech import cell_properties as props from tech import cell_properties as props
from math import log
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS
from sram_factory import factory from sram_factory import factory
class dff_buf_array(design.design): class dff_buf_array(design.design):
""" """
This is a simple row (or multiple rows) of flops. This is a simple row (or multiple rows) of flops.
@ -49,18 +48,19 @@ class dff_buf_array(design.design):
self.width = self.columns * self.dff.width self.width = self.columns * self.dff.width
self.height = self.rows * self.dff.height self.height = self.rows * self.dff.height
self.place_dff_array() self.place_dff_array()
self.route_supplies()
self.add_layout_pins() self.add_layout_pins()
self.add_boundary() self.add_boundary()
self.DRC_LVS() self.DRC_LVS()
def add_pins(self): def add_pins(self):
for row in range(self.rows): for row in range(self.rows):
for col in range(self.columns): for col in range(self.columns):
self.add_pin(self.get_din_name(row,col), "INPUT") self.add_pin(self.get_din_name(row, col), "INPUT")
for row in range(self.rows): for row in range(self.rows):
for col in range(self.columns): for col in range(self.columns):
self.add_pin(self.get_dout_name(row,col), "OUTPUT") self.add_pin(self.get_dout_name(row, col), "OUTPUT")
self.add_pin(self.get_dout_bar_name(row,col), "OUTPUT") self.add_pin(self.get_dout_bar_name(row, col), "OUTPUT")
self.add_pin("clk", "INPUT") self.add_pin("clk", "INPUT")
self.add_pin("vdd", "POWER") self.add_pin("vdd", "POWER")
self.add_pin("gnd", "GROUND") self.add_pin("gnd", "GROUND")
@ -75,17 +75,16 @@ class dff_buf_array(design.design):
inv2_size=self.inv2_size) inv2_size=self.inv2_size)
self.add_mod(self.dff) self.add_mod(self.dff)
def create_dff_array(self): def create_dff_array(self):
self.dff_insts={} self.dff_insts={}
for row in range(self.rows): for row in range(self.rows):
for col in range(self.columns): for col in range(self.columns):
name = "dff_r{0}_c{1}".format(row,col) name = "dff_r{0}_c{1}".format(row, col)
self.dff_insts[row,col]=self.add_inst(name=name, self.dff_insts[row, col]=self.add_inst(name=name,
mod=self.dff) mod=self.dff)
inst_ports = [self.get_din_name(row,col), inst_ports = [self.get_din_name(row, col),
self.get_dout_name(row,col), self.get_dout_name(row, col),
self.get_dout_bar_name(row,col), self.get_dout_bar_name(row, col),
"clk", "clk",
"vdd", "vdd",
"gnd"] "gnd"]
@ -96,23 +95,33 @@ class dff_buf_array(design.design):
def place_dff_array(self): def place_dff_array(self):
well_spacing = max(self.nwell_space, well_spacing = 0
self.pwell_space, try:
self.pwell_to_nwell) well_spacing = max(self.nwell_space, well_spacing)
except AttributeError:
pass
try:
well_spacing = max(self.pwell_space, well_spacing)
except AttributeError:
pass
try:
well_spacing = max(self.pwell_to_nwell, well_spacing)
except AttributeError:
pass
dff_pitch = self.dff.width + well_spacing + self.well_extend_active dff_pitch = self.dff.width + well_spacing + self.well_extend_active
for row in range(self.rows): for row in range(self.rows):
for col in range(self.columns): for col in range(self.columns):
name = "Xdff_r{0}_c{1}".format(row,col) # name = "Xdff_r{0}_c{1}".format(row, col)
if (row % 2 == 0): if (row % 2 == 0):
base = vector(col*dff_pitch,row*self.dff.height) base = vector(col * dff_pitch, row * self.dff.height)
mirror = "R0" mirror = "R0"
else: else:
base = vector(col*dff_pitch,(row+1)*self.dff.height) base = vector(col * dff_pitch, (row + 1) * self.dff.height)
mirror = "MX" mirror = "MX"
self.dff_insts[row,col].place(offset=base, self.dff_insts[row, col].place(offset=base,
mirror=mirror) mirror=mirror)
def get_din_name(self, row, col): def get_din_name(self, row, col):
if self.columns == 1: if self.columns == 1:
@ -120,7 +129,7 @@ class dff_buf_array(design.design):
elif self.rows == 1: elif self.rows == 1:
din_name = "din_{0}".format(col) din_name = "din_{0}".format(col)
else: else:
din_name = "din_{0}_{1}".format(row,col) din_name = "din_{0}_{1}".format(row, col)
return din_name return din_name
@ -130,7 +139,7 @@ class dff_buf_array(design.design):
elif self.rows == 1: elif self.rows == 1:
dout_name = "dout_{0}".format(col) dout_name = "dout_{0}".format(col)
else: else:
dout_name = "dout_{0}_{1}".format(row,col) dout_name = "dout_{0}_{1}".format(row, col)
return dout_name return dout_name
@ -140,75 +149,84 @@ class dff_buf_array(design.design):
elif self.rows == 1: elif self.rows == 1:
dout_bar_name = "dout_bar_{0}".format(col) dout_bar_name = "dout_bar_{0}".format(col)
else: else:
dout_bar_name = "dout_bar_{0}_{1}".format(row,col) dout_bar_name = "dout_bar_{0}_{1}".format(row, col)
return dout_bar_name return dout_bar_name
def add_layout_pins(self): def route_supplies(self):
for row in range(self.rows): for row in range(self.rows):
for col in range(self.columns): vdd0_pin=self.dff_insts[row, 0].get_pin("vdd")
vddn_pin=self.dff_insts[row, self.columns - 1].get_pin("vdd")
self.add_path(vdd0_pin.layer, [vdd0_pin.lc(), vddn_pin.rc()], width=vdd0_pin.height())
gnd0_pin=self.dff_insts[row, 0].get_pin("gnd")
gndn_pin=self.dff_insts[row, self.columns - 1].get_pin("gnd")
self.add_path(gnd0_pin.layer, [gnd0_pin.lc(), gndn_pin.rc()], width=gnd0_pin.height())
for row in range(self.rows):
for col in range(self.columns):
# Continous vdd rail along with label. # Continous vdd rail along with label.
vdd_pin=self.dff_insts[row,col].get_pin("vdd") vdd_pin=self.dff_insts[row, col].get_pin("vdd")
self.add_power_pin("vdd", vdd_pin.lc()) self.add_power_pin("vdd", vdd_pin.lc())
# Continous gnd rail along with label. # Continous gnd rail along with label.
gnd_pin=self.dff_insts[row,col].get_pin("gnd") gnd_pin=self.dff_insts[row, col].get_pin("gnd")
self.add_power_pin("gnd", gnd_pin.lc()) self.add_power_pin("gnd", gnd_pin.lc())
def add_layout_pins(self):
for row in range(self.rows):
for row in range(self.rows): for col in range(self.columns):
for col in range(self.columns): din_pin = self.dff_insts[row, col].get_pin("D")
din_pin = self.dff_insts[row,col].get_pin("D") debug.check(din_pin.layer=="m2", "DFF D pin not on metal2")
debug.check(din_pin.layer=="m2","DFF D pin not on metal2") self.add_layout_pin(text=self.get_din_name(row, col),
self.add_layout_pin(text=self.get_din_name(row,col),
layer=din_pin.layer, layer=din_pin.layer,
offset=din_pin.ll(), offset=din_pin.ll(),
width=din_pin.width(), width=din_pin.width(),
height=din_pin.height()) height=din_pin.height())
dout_pin = self.dff_insts[row,col].get_pin("Q") dout_pin = self.dff_insts[row, col].get_pin("Q")
debug.check(dout_pin.layer=="m2","DFF Q pin not on metal2") debug.check(dout_pin.layer=="m2", "DFF Q pin not on metal2")
self.add_layout_pin(text=self.get_dout_name(row,col), self.add_layout_pin(text=self.get_dout_name(row, col),
layer=dout_pin.layer, layer=dout_pin.layer,
offset=dout_pin.ll(), offset=dout_pin.ll(),
width=dout_pin.width(), width=dout_pin.width(),
height=dout_pin.height()) height=dout_pin.height())
dout_bar_pin = self.dff_insts[row,col].get_pin("Qb") dout_bar_pin = self.dff_insts[row, col].get_pin("Qb")
debug.check(dout_bar_pin.layer=="m2","DFF Qb pin not on metal2") debug.check(dout_bar_pin.layer=="m2", "DFF Qb pin not on metal2")
self.add_layout_pin(text=self.get_dout_bar_name(row,col), self.add_layout_pin(text=self.get_dout_bar_name(row, col),
layer=dout_bar_pin.layer, layer=dout_bar_pin.layer,
offset=dout_bar_pin.ll(), offset=dout_bar_pin.ll(),
width=dout_bar_pin.width(), width=dout_bar_pin.width(),
height=dout_bar_pin.height()) height=dout_bar_pin.height())
# Create vertical spines to a single horizontal rail # Create vertical spines to a single horizontal rail
clk_pin = self.dff_insts[0,0].get_pin("clk") clk_pin = self.dff_insts[0, 0].get_pin("clk")
clk_ypos = 2*self.m3_pitch+self.m3_width clk_ypos = 2 * self.m3_pitch + self.m3_width
debug.check(clk_pin.layer=="m2","DFF clk pin not on metal2") debug.check(clk_pin.layer=="m2", "DFF clk pin not on metal2")
if self.columns==1: if self.columns==1:
self.add_layout_pin(text="clk", self.add_layout_pin(text="clk",
layer="m2", layer="m2",
offset=clk_pin.ll().scale(1,0), offset=clk_pin.ll().scale(1, 0),
width=self.m2_width, width=self.m2_width,
height=self.height) height=self.height)
else: else:
self.add_layout_pin_segment_center(text="clk", self.add_layout_pin_segment_center(text="clk",
layer="m3", layer="m3",
start=vector(0,clk_ypos), start=vector(0, clk_ypos),
end=vector(self.width,clk_ypos)) end=vector(self.width, clk_ypos))
for col in range(self.columns): for col in range(self.columns):
clk_pin = self.dff_insts[0,col].get_pin("clk") clk_pin = self.dff_insts[0, col].get_pin("clk")
# Make a vertical strip for each column # Make a vertical strip for each column
self.add_rect(layer="m2", self.add_rect(layer="m2",
offset=clk_pin.ll().scale(1,0), offset=clk_pin.ll().scale(1, 0),
width=self.m2_width, width=self.m2_width,
height=self.height) height=self.height)
# Drop a via to the M3 pin # Drop a via to the M3 pin
self.add_via_center(layers=self.m2_stack, self.add_via_center(layers=self.m2_stack,
offset=vector(clk_pin.cx(),clk_ypos)) offset=vector(clk_pin.cx(), clk_ypos))
def get_clk_cin(self): def get_clk_cin(self):
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff array""" """Return the total capacitance (in relative units) that the clock is loaded by in the dff array"""

View File

@ -32,7 +32,6 @@ class hierarchical_decoder(design.design):
self.cell_multiple = cell_properties.bitcell.decoder_bitcell_multiple self.cell_multiple = cell_properties.bitcell.decoder_bitcell_multiple
except AttributeError: except AttributeError:
self.cell_multiple = 1 self.cell_multiple = 1
# For debugging
self.cell_height = self.cell_multiple * b.height self.cell_height = self.cell_multiple * b.height
self.num_outputs = num_outputs self.num_outputs = num_outputs

View File

@ -699,8 +699,13 @@ class port_data(design.design):
bottom_names = self._get_bitline_pins(bot_inst_group, bit) bottom_names = self._get_bitline_pins(bot_inst_group, bit)
top_names = self._get_bitline_pins(top_inst_group, bit) top_names = self._get_bitline_pins(top_inst_group, bit)
if bottom_names[0].layer == "m2":
bitline_dirs = ("H", "V")
elif bottom_names[0].layer == "m1":
bitline_dirs = ("V", "H")
route_map = list(zip(bottom_names, top_names)) route_map = list(zip(bottom_names, top_names))
self.create_horizontal_channel_route(route_map, offset, self.m1_stack) self.create_horizontal_channel_route(route_map, offset, self.m1_stack, bitline_dirs)
def connect_bitlines(self, inst1, inst2, num_bits, def connect_bitlines(self, inst1, inst2, num_bits,
inst1_bls_template="{inst}_{bit}", inst1_bls_template="{inst}_{bit}",

View File

@ -5,17 +5,15 @@
# (acting for and on behalf of Oklahoma State University) # (acting for and on behalf of Oklahoma State University)
# All rights reserved. # All rights reserved.
# #
from math import log
import design import design
import contact
from tech import drc
import debug import debug
import math from tech import layer
from vector import vector from vector import vector
from sram_factory import factory from sram_factory import factory
from globals import OPTS from globals import OPTS
import logical_effort import logical_effort
class single_level_column_mux_array(design.design): class single_level_column_mux_array(design.design):
""" """
Dynamically generated column mux array. Dynamically generated column mux array.
@ -26,13 +24,20 @@ class single_level_column_mux_array(design.design):
design.design.__init__(self, name) design.design.__init__(self, name)
debug.info(1, "Creating {0}".format(self.name)) debug.info(1, "Creating {0}".format(self.name))
self.add_comment("cols: {0} word_size: {1} bl: {2} br: {3}".format(columns, word_size, bitcell_bl, bitcell_br)) self.add_comment("cols: {0} word_size: {1} bl: {2} br: {3}".format(columns, word_size, bitcell_bl, bitcell_br))
self.columns = columns self.columns = columns
self.word_size = word_size self.word_size = word_size
self.words_per_row = int(self.columns / self.word_size) self.words_per_row = int(self.columns / self.word_size)
self.bitcell_bl = bitcell_bl self.bitcell_bl = bitcell_bl
self.bitcell_br = bitcell_br self.bitcell_br = bitcell_br
if "li" in layer:
self.col_mux_stack = self.li_stack
self.col_mux_stack_pitch = self.li_pitch
else:
self.col_mux_stack = self.m1_stack
self.col_mux_stack_pitch = self.m1_pitch
self.create_netlist() self.create_netlist()
if not OPTS.netlist_only: if not OPTS.netlist_only:
self.create_layout() self.create_layout()
@ -49,20 +54,20 @@ class single_level_column_mux_array(design.design):
self.add_modules() self.add_modules()
self.add_pins() self.add_pins()
self.create_array() self.create_array()
def create_layout(self): def create_layout(self):
self.setup_layout_constants() self.setup_layout_constants()
self.place_array() self.place_array()
self.add_routing() self.add_routing()
# Find the highest shapes to determine height before adding well # Find the highest shapes to determine height before adding well
highest = self.find_highest_coords() highest = self.find_highest_coords()
self.height = highest.y self.height = highest.y
self.add_layout_pins() self.add_layout_pins()
self.add_enclosure(self.mux_inst, "pwell") if "pwell" in layer:
self.add_enclosure(self.mux_inst, "pwell")
self.add_boundary() self.add_boundary()
self.DRC_LVS() self.DRC_LVS()
def add_pins(self): def add_pins(self):
for i in range(self.columns): for i in range(self.columns):
self.add_pin("bl_{}".format(i)) self.add_pin("bl_{}".format(i))
@ -74,23 +79,19 @@ class single_level_column_mux_array(design.design):
self.add_pin("br_out_{}".format(i)) self.add_pin("br_out_{}".format(i))
self.add_pin("gnd") self.add_pin("gnd")
def add_modules(self): def add_modules(self):
self.mux = factory.create(module_type="single_level_column_mux", self.mux = factory.create(module_type="single_level_column_mux",
bitcell_bl=self.bitcell_bl, bitcell_bl=self.bitcell_bl,
bitcell_br=self.bitcell_br) bitcell_br=self.bitcell_br)
self.add_mod(self.mux) self.add_mod(self.mux)
def setup_layout_constants(self): def setup_layout_constants(self):
self.column_addr_size = num_of_inputs = int(self.words_per_row / 2) self.column_addr_size = int(self.words_per_row / 2)
self.width = self.columns * self.mux.width self.width = self.columns * self.mux.width
# one set of metal1 routes for select signals and a pair to interconnect the mux outputs bl/br # one set of metal1 routes for select signals and a pair to interconnect the mux outputs bl/br
# one extra route pitch is to space from the sense amp # one extra route pitch is to space from the sense amp
self.route_height = (self.words_per_row + 3)*self.m1_pitch self.route_height = (self.words_per_row + 3) * self.col_mux_stack_pitch
def create_array(self): def create_array(self):
self.mux_inst = [] self.mux_inst = []
# For every column, add a pass gate # For every column, add a pass gate
@ -98,11 +99,11 @@ class single_level_column_mux_array(design.design):
name = "XMUX{0}".format(col_num) name = "XMUX{0}".format(col_num)
self.mux_inst.append(self.add_inst(name=name, self.mux_inst.append(self.add_inst(name=name,
mod=self.mux)) mod=self.mux))
self.connect_inst(["bl_{}".format(col_num), self.connect_inst(["bl_{}".format(col_num),
"br_{}".format(col_num), "br_{}".format(col_num),
"bl_out_{}".format(int(col_num/self.words_per_row)), "bl_out_{}".format(int(col_num / self.words_per_row)),
"br_out_{}".format(int(col_num/self.words_per_row)), "br_out_{}".format(int(col_num / self.words_per_row)),
"sel_{}".format(col_num % self.words_per_row), "sel_{}".format(col_num % self.words_per_row),
"gnd"]) "gnd"])
@ -117,32 +118,31 @@ class single_level_column_mux_array(design.design):
else: else:
mirror = "" mirror = ""
name = "XMUX{0}".format(col_num)
offset = vector(xoffset, self.route_height) offset = vector(xoffset, self.route_height)
self.mux_inst[col_num].place(offset=offset, mirror=mirror) self.mux_inst[col_num].place(offset=offset, mirror=mirror)
def add_layout_pins(self): def add_layout_pins(self):
""" Add the pins after we determine the height. """ """ Add the pins after we determine the height. """
# For every column, add a pass gate # For every column, add a pass gate
for col_num in range(self.columns): for col_num in range(self.columns):
mux_inst = self.mux_inst[col_num] mux_inst = self.mux_inst[col_num]
offset = mux_inst.get_pin("bl").ll() bl_pin = mux_inst.get_pin("bl")
offset = bl_pin.ll()
self.add_layout_pin(text="bl_{}".format(col_num), self.add_layout_pin(text="bl_{}".format(col_num),
layer="m2", layer=bl_pin.layer,
offset=offset, offset=offset,
height=self.height-offset.y) height=self.height - offset.y)
offset = mux_inst.get_pin("br").ll() br_pin = mux_inst.get_pin("br")
offset = br_pin.ll()
self.add_layout_pin(text="br_{}".format(col_num), self.add_layout_pin(text="br_{}".format(col_num),
layer="m2", layer=br_pin.layer,
offset=offset, offset=offset,
height=self.height-offset.y) height=self.height - offset.y)
for inst in self.mux_inst: for inst in self.mux_inst:
self.copy_layout_pin(inst, "gnd") self.copy_layout_pin(inst, "gnd")
def add_routing(self): def add_routing(self):
self.add_horizontal_input_rail() self.add_horizontal_input_rail()
self.add_vertical_poly_rail() self.add_vertical_poly_rail()
@ -151,15 +151,15 @@ class single_level_column_mux_array(design.design):
def add_horizontal_input_rail(self): def add_horizontal_input_rail(self):
""" Create address input rails on M1 below the mux transistors """ """ Create address input rails on M1 below the mux transistors """
for j in range(self.words_per_row): for j in range(self.words_per_row):
offset = vector(0, self.route_height + (j-self.words_per_row)*self.m1_pitch) offset = vector(0, self.route_height + (j - self.words_per_row) * self.col_mux_stack_pitch)
self.add_layout_pin(text="sel_{}".format(j), self.add_layout_pin(text="sel_{}".format(j),
layer="m1", layer=self.col_mux_stack[0],
offset=offset, offset=offset,
width=self.mux.width * self.columns) width=self.mux.width * self.columns)
def add_vertical_poly_rail(self): def add_vertical_poly_rail(self):
""" Connect the poly to the address rails """ """ Connect the poly to the address rails """
# Offset to the first transistor gate in the pass gate # Offset to the first transistor gate in the pass gate
for col in range(self.columns): for col in range(self.columns):
# which select bit should this column connect to depends on the position in the word # which select bit should this column connect to depends on the position in the word
@ -167,11 +167,12 @@ class single_level_column_mux_array(design.design):
# Add the column x offset to find the right select bit # Add the column x offset to find the right select bit
gate_offset = self.mux_inst[col].get_pin("sel").bc() gate_offset = self.mux_inst[col].get_pin("sel").bc()
# height to connect the gate to the correct horizontal row # height to connect the gate to the correct horizontal row
sel_height = self.get_pin("sel_{}".format(sel_index)).by() # sel_height = self.get_pin("sel_{}".format(sel_index)).by()
# use the y offset from the sel pin and the x offset from the gate # use the y offset from the sel pin and the x offset from the gate
offset = vector(gate_offset.x,self.get_pin("sel_{}".format(sel_index)).cy()) offset = vector(gate_offset.x,
self.get_pin("sel_{}".format(sel_index)).cy())
# Add the poly contact with a shift to account for the rotation # Add the poly contact with a shift to account for the rotation
self.add_via_center(layers=("m1", "contact", "poly"), self.add_via_center(layers=self.poly_stack,
offset=offset) offset=offset)
self.add_path("poly", [offset, gate_offset]) self.add_path("poly", [offset, gate_offset])
@ -182,11 +183,11 @@ class single_level_column_mux_array(design.design):
bl_offset = self.mux_inst[j].get_pin("bl_out").bc() bl_offset = self.mux_inst[j].get_pin("bl_out").bc()
br_offset = self.mux_inst[j].get_pin("br_out").bc() br_offset = self.mux_inst[j].get_pin("br_out").bc()
bl_out_offset = bl_offset - vector(0,(self.words_per_row+1)*self.m1_pitch) bl_out_offset = bl_offset - vector(0, (self.words_per_row + 1) * self.col_mux_stack_pitch)
br_out_offset = br_offset - vector(0,(self.words_per_row+2)*self.m1_pitch) br_out_offset = br_offset - vector(0, (self.words_per_row + 2) * self.col_mux_stack_pitch)
bl_out_offset_end = bl_out_offset + vector(0,self.route_height) bl_out_offset_end = bl_out_offset + vector(0, self.route_height)
br_out_offset_end = br_out_offset + vector(0,self.route_height) br_out_offset_end = br_out_offset + vector(0, self.route_height)
if cell_properties.bitcell.mirror.y and j % 2: if cell_properties.bitcell.mirror.y and j % 2:
tmp_bl_out_end = br_out_offset_end tmp_bl_out_end = br_out_offset_end
@ -208,43 +209,41 @@ class single_level_column_mux_array(design.design):
else: else:
dist = 0 dist = 0
self.add_path("m1", [bl_out_offset, bl_out_offset+vector(width+dist,0)]) self.add_path(self.col_mux_stack[0], [bl_out_offset, bl_out_offset + vector(width + dist, 0)])
self.add_path("m1", [br_out_offset, br_out_offset+vector(width-dist,0)]) self.add_path(self.col_mux_stack[0], [br_out_offset, br_out_offset + vector(width - dist, 0)])
# Extend the bitline output rails and gnd downward on the first bit of each n-way mux # Extend the bitline output rails and gnd downward on the first bit of each n-way mux
self.add_layout_pin_segment_center(text="bl_out_{}".format(int(j/self.words_per_row)), self.add_layout_pin_segment_center(text="bl_out_{}".format(int(j / self.words_per_row)),
layer="m2", layer=self.col_mux_stack[2],
start=bl_out_offset, start=bl_out_offset,
end=tmp_bl_out_end) end=tmp_bl_out_end)
self.add_layout_pin_segment_center(text="br_out_{}".format(int(j/self.words_per_row)), self.add_layout_pin_segment_center(text="br_out_{}".format(int(j / self.words_per_row)),
layer="m2", layer=self.col_mux_stack[2],
start=br_out_offset, start=br_out_offset,
end=tmp_br_out_end) end=tmp_br_out_end)
# This via is on the right of the wire # This via is on the right of the wire
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.col_mux_stack,
offset=bl_out_offset) offset=bl_out_offset)
# This via is on the left of the wire # This via is on the left of the wire
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.col_mux_stack,
offset=br_out_offset) offset=br_out_offset)
else: else:
self.add_path(self.col_mux_stack[2], [bl_out_offset, bl_offset])
self.add_path("m2", [ bl_out_offset, tmp_bl_out_end]) self.add_path(self.col_mux_stack[2], [br_out_offset, br_offset])
self.add_path("m2", [ br_out_offset, tmp_br_out_end])
# This via is on the right of the wire # This via is on the right of the wire
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.col_mux_stack,
offset=bl_out_offset) offset=bl_out_offset)
# This via is on the left of the wire # This via is on the left of the wire
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.col_mux_stack,
offset=br_out_offset) offset=br_out_offset)
def get_drain_cin(self): def get_drain_cin(self):
"""Get the relative capacitance of the drain of the NMOS pass TX""" """Get the relative capacitance of the drain of the NMOS pass TX"""
from tech import parameter from tech import parameter
#Bitcell drain load being used to estimate mux NMOS drain load # Bitcell drain load being used to estimate mux NMOS drain load
drain_load = logical_effort.convert_farad_to_relative_c(parameter['bitcell_drain_cap']) drain_load = logical_effort.convert_farad_to_relative_c(parameter['bitcell_drain_cap'])
return drain_load return drain_load

View File

@ -7,10 +7,12 @@
# #
import debug import debug
import design import design
import math
import contact import contact
from vector import vector from vector import vector
from sram_factory import factory from sram_factory import factory
from globals import OPTS from globals import OPTS
from tech import cell_properties
class wordline_driver(design.design): class wordline_driver(design.design):
@ -26,6 +28,13 @@ class wordline_driver(design.design):
self.rows = rows self.rows = rows
self.cols = cols self.cols = cols
b = factory.create(module_type="bitcell")
try:
self.cell_multiple = cell_properties.bitcell.decoder_bitcell_multiple
except AttributeError:
self.cell_multiple = 1
self.cell_height = self.cell_multiple * b.height
self.create_netlist() self.create_netlist()
if not OPTS.netlist_only: if not OPTS.netlist_only:
@ -37,6 +46,7 @@ class wordline_driver(design.design):
self.create_drivers() self.create_drivers()
def create_layout(self): def create_layout(self):
self.setup_layout_constants()
self.place_drivers() self.place_drivers()
self.route_layout() self.route_layout()
self.route_vdd_gnd() self.route_vdd_gnd()
@ -56,17 +66,10 @@ class wordline_driver(design.design):
self.add_pin("gnd", "GROUND") self.add_pin("gnd", "GROUND")
def add_modules(self): def add_modules(self):
b = factory.create(module_type="bitcell") self.and2 = factory.create(module_type="pand2",
height=self.cell_height,
self.inv = factory.create(module_type="pdriver", size=self.cols)
fanout=self.cols, self.add_mod(self.and2)
neg_polarity=True,
height=b.height)
self.add_mod(self.inv)
self.nand2 = factory.create(module_type="pnand2",
height=b.height)
self.add_mod(self.nand2)
def route_vdd_gnd(self): def route_vdd_gnd(self):
""" """
@ -75,68 +78,64 @@ class wordline_driver(design.design):
""" """
# Find the x offsets for where the vias/pins should be placed # Find the x offsets for where the vias/pins should be placed
a_xoffset = self.nand_inst[0].lx() xoffset_list = [self.and_inst[0].lx()]
for num in range(self.rows): for num in range(self.rows):
# this will result in duplicate polygons for rails, but who cares # this will result in duplicate polygons for rails, but who cares
# use the inverter offset even though it will be the nand's too # use the inverter offset even though it will be the and's too
(gate_offset, y_dir) = self.get_gate_offset(0, (gate_offset, y_dir) = self.get_gate_offset(0,
self.inv.height, self.and2.height,
num) num)
# Route both supplies # Route both supplies
for name in ["vdd", "gnd"]: for name in ["vdd", "gnd"]:
supply_pin = self.inv2_inst[num].get_pin(name) supply_pin = self.and_inst[num].get_pin(name)
# Add pins in two locations # Add pins in two locations
for xoffset in [a_xoffset]: for xoffset in xoffset_list:
pin_pos = vector(xoffset, supply_pin.cy()) pin_pos = vector(xoffset, supply_pin.cy())
self.add_power_pin(name, pin_pos) self.add_power_pin(name, pin_pos)
def create_drivers(self): def create_drivers(self):
self.nand_inst = [] self.and_inst = []
self.inv2_inst = []
for row in range(self.rows): for row in range(self.rows):
name_nand = "wl_driver_nand{}".format(row) name_and = "wl_driver_and{}".format(row)
name_inv2 = "wl_driver_inv{}".format(row)
# add nand 2 # add and2
self.nand_inst.append(self.add_inst(name=name_nand, self.and_inst.append(self.add_inst(name=name_and,
mod=self.nand2)) mod=self.and2))
self.connect_inst(["en", self.connect_inst(["en",
"in_{0}".format(row), "in_{0}".format(row),
"wl_bar_{0}".format(row),
"vdd", "gnd"])
# add inv2
self.inv2_inst.append(self.add_inst(name=name_inv2,
mod=self.inv))
self.connect_inst(["wl_bar_{0}".format(row),
"wl_{0}".format(row), "wl_{0}".format(row),
"vdd", "gnd"]) "vdd", "gnd"])
def setup_layout_constants(self):
# We may have more than one bitcell per decoder row
self.num_rows = math.ceil(self.rows / self.cell_multiple)
# We will place this many final decoders per row
self.decoders_per_row = math.ceil(self.rows / self.num_rows)
def place_drivers(self): def place_drivers(self):
nand2_xoffset = 2 * self.m1_width + 5 * self.m1_space and2_xoffset = 2 * self.m1_width + 5 * self.m1_space
inv2_xoffset = nand2_xoffset + self.nand2.width
self.width = inv2_xoffset + self.inv.width self.width = and2_xoffset + self.and2.width
self.height = self.inv.height * self.rows self.height = self.and2.height * self.num_rows
for row in range(self.rows): for row in range(self.rows):
#row = math.floor(inst_index / self.decoders_per_row)
#dec = inst_index % self.decoders_per_row
if (row % 2): if (row % 2):
y_offset = self.inv.height * (row + 1) y_offset = self.and2.height * (row + 1)
inst_mirror = "MX" inst_mirror = "MX"
else: else:
y_offset = self.inv.height * row y_offset = self.and2.height * row
inst_mirror = "R0" inst_mirror = "R0"
nand2_offset = [nand2_xoffset, y_offset] # x_off = self.internal_routing_width + dec * and_mod.width
inv2_offset = [inv2_xoffset, y_offset] and2_offset = [and2_xoffset, y_offset]
# add nand 2 # add and2
self.nand_inst[row].place(offset=nand2_offset, self.and_inst[row].place(offset=and2_offset,
mirror=inst_mirror)
# add inv2
self.inv2_inst[row].place(offset=inv2_offset,
mirror=inst_mirror) mirror=inst_mirror)
def route_layout(self): def route_layout(self):
@ -151,11 +150,10 @@ class wordline_driver(design.design):
height=self.height) height=self.height)
for row in range(self.rows): for row in range(self.rows):
nand_inst = self.nand_inst[row] and_inst = self.and_inst[row]
inv2_inst = self.inv2_inst[row]
# en connection # en connection
a_pin = nand_inst.get_pin("A") a_pin = and_inst.get_pin("A")
a_pos = a_pin.lc() a_pos = a_pin.lc()
clk_offset = vector(en_pin.bc().x, a_pos.y) clk_offset = vector(en_pin.bc().x, a_pos.y)
self.add_segment_center(layer="m1", self.add_segment_center(layer="m1",
@ -164,18 +162,10 @@ class wordline_driver(design.design):
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.m1_stack,
offset=clk_offset) offset=clk_offset)
# Nand2 out to 2nd inv # connect the decoder input pin to and2 B
zr_pos = nand_inst.get_pin("Z").rc() b_pin = and_inst.get_pin("B")
al_pos = inv2_inst.get_pin("A").lc()
# ensure the bend is in the middle
mid1_pos = vector(0.5 * (zr_pos.x + al_pos.x), zr_pos.y)
mid2_pos = vector(0.5 * (zr_pos.x + al_pos.x), al_pos.y)
self.add_path("m1", [zr_pos, mid1_pos, mid2_pos, al_pos])
# connect the decoder input pin to nand2 B
b_pin = nand_inst.get_pin("B")
b_pos = b_pin.lc() b_pos = b_pin.lc()
# needs to move down since B nand input is # needs to move down since B and input is
# nearly aligned with A inv input # nearly aligned with A inv input
up_or_down = self.m2_space if row % 2 else -self.m2_space up_or_down = self.m2_space if row % 2 else -self.m2_space
input_offset = vector(0, b_pos.y + up_or_down) input_offset = vector(0, b_pos.y + up_or_down)
@ -192,7 +182,7 @@ class wordline_driver(design.design):
offset=mid_via_offset, offset=mid_via_offset,
directions=("V", "V")) directions=("V", "V"))
# now connect to the nand2 B # now connect to the and2 B
self.add_path("m2", [mid_via_offset, b_pos]) self.add_path("m2", [mid_via_offset, b_pos])
contact_offset = b_pos - vector(0.5 * contact.m1_via.height, 0) contact_offset = b_pos - vector(0.5 * contact.m1_via.height, 0)
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.m1_stack,
@ -200,7 +190,7 @@ class wordline_driver(design.design):
directions=("H", "H")) directions=("H", "H"))
# output each WL on the right # output each WL on the right
wl_offset = inv2_inst.get_pin("Z").rc() wl_offset = and_inst.get_pin("Z").rc()
self.add_layout_pin_segment_center(text="wl_{0}".format(row), self.add_layout_pin_segment_center(text="wl_{0}".format(row),
layer="m1", layer="m1",
start=wl_offset, start=wl_offset,
@ -213,13 +203,8 @@ class wordline_driver(design.design):
""" """
stage_effort_list = [] stage_effort_list = []
stage1_cout = self.inv.get_cin() stage1 = self.and2.get_stage_effort(external_cout, inp_is_rise)
stage1 = self.nand2.get_stage_effort(stage1_cout, inp_is_rise)
stage_effort_list.append(stage1) stage_effort_list.append(stage1)
last_stage_is_rise = stage1.is_rise
stage2 = self.inv.get_stage_efforts(external_cout, last_stage_is_rise)
stage_effort_list.extend(stage2)
return stage_effort_list return stage_effort_list
@ -228,6 +213,6 @@ class wordline_driver(design.design):
Get the relative capacitance of all Get the relative capacitance of all
the enable connections in the bank the enable connections in the bank
""" """
# The enable is connected to a nand2 for every row. # The enable is connected to a and2 for every row.
total_cin = self.nand2.get_cin() * self.rows total_cin = self.and2.get_cin() * self.rows
return total_cin return total_cin

View File

@ -30,13 +30,12 @@ class pand2(pgate.pgate):
self.create_insts() self.create_insts()
def create_modules(self): def create_modules(self):
# Shield the cap, but have at least a stage effort of 4
self.nand = factory.create(module_type="pnand2", height=self.height) self.nand = factory.create(module_type="pnand2", height=self.height)
self.add_mod(self.nand) self.add_mod(self.nand)
self.inv = factory.create(module_type="pdriver", self.inv = factory.create(module_type="pdriver",
neg_polarity=True, neg_polarity=True,
fanout=3*self.size, fanout=self.size,
height=self.height) height=self.height)
self.add_mod(self.inv) self.add_mod(self.inv)
@ -45,6 +44,7 @@ class pand2(pgate.pgate):
self.place_insts() self.place_insts()
self.add_wires() self.add_wires()
self.add_layout_pins() self.add_layout_pins()
self.add_boundary()
self.DRC_LVS() self.DRC_LVS()
def add_pins(self): def add_pins(self):

View File

@ -44,6 +44,7 @@ class pand3(pgate.pgate):
self.place_insts() self.place_insts()
self.add_wires() self.add_wires()
self.add_layout_pins() self.add_layout_pins()
self.add_boundary()
self.DRC_LVS() self.DRC_LVS()
def add_pins(self): def add_pins(self):

View File

@ -37,6 +37,7 @@ class pbuf(pgate.pgate):
self.place_insts() self.place_insts()
self.add_wires() self.add_wires()
self.add_layout_pins() self.add_layout_pins()
self.add_boundary()
def add_pins(self): def add_pins(self):
self.add_pin("A", "INPUT") self.add_pin("A", "INPUT")

View File

@ -76,6 +76,7 @@ class pdriver(pgate.pgate):
self.width = self.inv_inst_list[-1].rx() self.width = self.inv_inst_list[-1].rx()
self.height = self.inv_inst_list[0].height self.height = self.inv_inst_list[0].height
self.add_boundary()
def add_pins(self): def add_pins(self):
self.add_pin("A", "INPUT") self.add_pin("A", "INPUT")

View File

@ -68,6 +68,7 @@ class pinv(pgate.pgate):
"A", "A",
position="farleft") position="farleft")
self.route_outputs() self.route_outputs()
self.add_boundary()
def add_pins(self): def add_pins(self):
""" Adds pins for spice netlist """ """ Adds pins for spice netlist """

View File

@ -47,6 +47,7 @@ class pinvbuf(pgate.pgate):
self.place_modules() self.place_modules()
self.route_wires() self.route_wires()
self.add_layout_pins() self.add_layout_pins()
self.add_boundary()
self.offset_all_coordinates() self.offset_all_coordinates()

View File

@ -62,7 +62,8 @@ class pnand2(pgate.pgate):
self.extend_wells() self.extend_wells()
self.route_inputs() self.route_inputs()
self.route_output() self.route_output()
self.add_boundary()
def add_pins(self): def add_pins(self):
""" Adds pins for spice netlist """ """ Adds pins for spice netlist """
pin_list = ["A", "B", "Z", "vdd", "gnd"] pin_list = ["A", "B", "Z", "vdd", "gnd"]

View File

@ -70,6 +70,7 @@ class pnand3(pgate.pgate):
self.extend_wells() self.extend_wells()
self.route_inputs() self.route_inputs()
self.route_output() self.route_output()
self.add_boundary()
def add_ptx(self): def add_ptx(self):
""" Create the PMOS and NMOS transistors. """ """ Create the PMOS and NMOS transistors. """

View File

@ -61,6 +61,7 @@ class pnor2(pgate.pgate):
self.extend_wells() self.extend_wells()
self.route_inputs() self.route_inputs()
self.route_output() self.route_output()
self.add_boundary()
def add_pins(self): def add_pins(self):
""" Adds pins for spice netlist """ """ Adds pins for spice netlist """

View File

@ -70,7 +70,8 @@ class precharge(design.design):
self.route_vdd_rail() self.route_vdd_rail()
self.route_bitlines() self.route_bitlines()
self.connect_to_bitlines() self.connect_to_bitlines()
self.add_boundary()
def add_pins(self): def add_pins(self):
self.add_pin_list(["bl", "br", "en_bar", "vdd"], self.add_pin_list(["bl", "br", "en_bar", "vdd"],
["OUTPUT", "OUTPUT", "INPUT", "POWER"]) ["OUTPUT", "OUTPUT", "INPUT", "POWER"])

View File

@ -56,6 +56,7 @@ class ptristate_inv(pgate.pgate):
self.connect_rails() self.connect_rails()
self.route_inputs() self.route_inputs()
self.route_outputs() self.route_outputs()
self.add_boundary()
def add_pins(self): def add_pins(self):
""" Adds pins for spice netlist """ """ Adds pins for spice netlist """

View File

@ -52,6 +52,7 @@ class pwrite_driver(design.design):
self.place_modules() self.place_modules()
self.route_wires() self.route_wires()
self.route_supplies() self.route_supplies()
self.add_boundary()
def add_pins(self): def add_pins(self):
self.add_pin("din", "INPUT") self.add_pin("din", "INPUT")

View File

@ -7,7 +7,7 @@
# #
import pgate import pgate
import debug import debug
from tech import drc from tech import drc, layer
from vector import vector from vector import vector
from sram_factory import factory from sram_factory import factory
import logical_effort import logical_effort
@ -22,13 +22,13 @@ class single_level_column_mux(pgate.pgate):
for optimal speed for optimal speed
""" """
def __init__(self, name, tx_size=8, bitcell_bl="bl", bitcell_br="br"): def __init__(self, name, tx_size=8, bitcell_bl="bl", bitcell_br="br"):
debug.info(2, "creating single column mux cell: {0}".format(name)) debug.info(2, "creating single column mux cell: {0}".format(name))
self.tx_size = int(tx_size) self.tx_size = int(tx_size)
self.bitcell_bl = bitcell_bl self.bitcell_bl = bitcell_bl
self.bitcell_br = bitcell_br self.bitcell_br = bitcell_br
pgate.pgate.__init__(self, name) pgate.pgate.__init__(self, name)
def get_bl_names(self): def get_bl_names(self):
@ -41,9 +41,9 @@ class single_level_column_mux(pgate.pgate):
self.add_modules() self.add_modules()
self.add_pins() self.add_pins()
self.add_ptx() self.add_ptx()
def create_layout(self): def create_layout(self):
self.pin_height = 2 * self.m2_width self.pin_height = 2 * self.m2_width
self.width = self.bitcell.width self.width = self.bitcell.width
self.height = self.nmos_upper.uy() + self.pin_height self.height = self.nmos_upper.uy() + self.pin_height
@ -57,41 +57,47 @@ class single_level_column_mux(pgate.pgate):
# Adds nmos_lower,nmos_upper to the module # Adds nmos_lower,nmos_upper to the module
self.ptx_width = self.tx_size * drc("minwidth_tx") self.ptx_width = self.tx_size * drc("minwidth_tx")
self.nmos = factory.create(module_type="ptx", width=self.ptx_width) self.nmos = factory.create(module_type="ptx",
width=self.ptx_width,
add_source_contact=False,
add_drain_contact=False)
self.add_mod(self.nmos) self.add_mod(self.nmos)
def add_pins(self): def add_pins(self):
self.add_pin_list(["bl", "br", "bl_out", "br_out", "sel", "gnd"]) self.add_pin_list(["bl", "br", "bl_out", "br_out", "sel", "gnd"])
def add_bitline_pins(self): def add_bitline_pins(self):
""" Add the top and bottom pins to this cell """ """ Add the top and bottom pins to this cell """
bl_pos = vector(self.bitcell.get_pin(self.bitcell_bl).lx(), 0) bl_pin=self.bitcell.get_pin(self.bitcell_bl)
br_pos = vector(self.bitcell.get_pin(self.bitcell_br).lx(), 0) br_pin=self.bitcell.get_pin(self.bitcell_br)
bl_pos = vector(bl_pin.lx(), 0)
br_pos = vector(br_pin.lx(), 0)
# bl and br # bl and br
self.add_layout_pin(text="bl", self.add_layout_pin(text="bl",
layer="m2", layer=bl_pin.layer,
offset=bl_pos + vector(0, self.height - self.pin_height), offset=bl_pos + vector(0, self.height - self.pin_height),
height=self.pin_height) height=self.pin_height)
self.add_layout_pin(text="br", self.add_layout_pin(text="br",
layer="m2", layer=br_pin.layer,
offset=br_pos + vector(0, self.height - self.pin_height), offset=br_pos + vector(0, self.height - self.pin_height),
height=self.pin_height) height=self.pin_height)
# bl_out and br_out # bl_out and br_out
self.add_layout_pin(text="bl_out", self.add_layout_pin(text="bl_out",
layer="m2", layer=bl_pin.layer,
offset=bl_pos, offset=bl_pos,
height=self.pin_height) height=self.pin_height)
self.add_layout_pin(text="br_out", self.add_layout_pin(text="br_out",
layer="m2", layer=br_pin.layer,
offset=br_pos, offset=br_pos,
height=self.pin_height) height=self.pin_height)
def add_ptx(self): def add_ptx(self):
""" Create the two pass gate NMOS transistors to switch the bitlines""" """ Create the two pass gate NMOS transistors to switch the bitlines"""
# Space it in the center # Space it in the center
nmos_lower_position = self.nmos.active_offset.scale(0,1) \ nmos_lower_position = self.nmos.active_offset.scale(0,1) \
+ vector(0.5 * self.bitcell.width- 0.5 * self.nmos.active_width, 0) + vector(0.5 * self.bitcell.width- 0.5 * self.nmos.active_width, 0)
@ -102,7 +108,7 @@ class single_level_column_mux(pgate.pgate):
# This aligns it directly above the other tx with gates abutting # This aligns it directly above the other tx with gates abutting
nmos_upper_position = nmos_lower_position \ nmos_upper_position = nmos_lower_position \
+ vector(0, self.nmos.active_height + self.poly_space) + vector(0, self.nmos.active_height + max(self.active_space,self.poly_space))
self.nmos_upper = self.add_inst(name="mux_tx2", self.nmos_upper = self.add_inst(name="mux_tx2",
mod=self.nmos, mod=self.nmos,
offset=nmos_upper_position) offset=nmos_upper_position)
@ -110,15 +116,30 @@ class single_level_column_mux(pgate.pgate):
def connect_poly(self): def connect_poly(self):
""" Connect the poly gate of the two pass transistors """ """ Connect the poly gate of the two pass transistors """
height = self.nmos_upper.get_pin("G").uy() - self.nmos_lower.get_pin("G").by() # offset is the top of the lower nmos' diffusion
# height is the distance between the nmos' diffusions, which depends on max(self.active_space,self.poly_space)
offset = self.nmos_lower.get_pin("G").ul() - vector(0,self.poly_extend_active)
height = self.nmos_upper.get_pin("G").by() + self.poly_extend_active - offset.y
self.add_rect(layer="poly",
offset=offset,
height=height)
# Add the sel pin to the bottom of the mux
self.add_layout_pin(text="sel", self.add_layout_pin(text="sel",
layer="poly", layer="poly",
offset=self.nmos_lower.get_pin("G").ll(), offset=self.nmos_lower.get_pin("G").ll(),
height=height) height=self.poly_extend_active)
def connect_bitlines(self): def connect_bitlines(self):
""" Connect the bitlines to the mux transistors """ """ Connect the bitlines to the mux transistors """
# If li exists, use li and m1 for the mux, otherwise use m1 and m2
if "li" in layer:
self.col_mux_stack = self.li_stack
else:
self.col_mux_stack = self.m1_stack
# These are on metal2 # These are on metal2
bl_pin = self.get_pin("bl") bl_pin = self.get_pin("bl")
br_pin = self.get_pin("br") br_pin = self.get_pin("br")
@ -132,35 +153,60 @@ class single_level_column_mux(pgate.pgate):
nmos_upper_d_pin = self.nmos_upper.get_pin("D") nmos_upper_d_pin = self.nmos_upper.get_pin("D")
# Add vias to bl, br_out, nmos_upper/S, nmos_lower/D # Add vias to bl, br_out, nmos_upper/S, nmos_lower/D
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.col_mux_stack,
offset=bl_pin.bc(), offset=bl_pin.bc(),
directions=("V", "V")) directions=("V", "V"))
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.col_mux_stack,
offset=br_out_pin.uc(), offset=br_out_pin.uc(),
directions=("V", "V")) directions=("V", "V"))
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.col_mux_stack,
offset=nmos_upper_s_pin.center(), offset=nmos_upper_s_pin.center(),
directions=("V", "V")) directions=("V", "V"))
self.add_via_center(layers=self.m1_stack, self.add_via_center(layers=self.col_mux_stack,
offset=nmos_lower_d_pin.center(), offset=nmos_lower_d_pin.center(),
directions=("V", "V")) directions=("V", "V"))
# Add diffusion contacts
# These were previously omitted with the options: add_source_contact=False, add_drain_contact=False
# They are added now and not previously so that they do not include m1 (which is usually included by default)
# This is only a concern when the local interconnect (li) layer is being used
self.add_via_center(layers=self.active_stack,
offset=nmos_upper_d_pin.center(),
directions=("V", "V"),
implant_type="n",
well_type="nwell")
self.add_via_center(layers=self.active_stack,
offset=nmos_lower_s_pin.center(),
directions=("V", "V"),
implant_type="n",
well_type="nwell")
self.add_via_center(layers=self.active_stack,
offset=nmos_upper_s_pin.center(),
directions=("V", "V"),
implant_type="n",
well_type="nwell")
self.add_via_center(layers=self.active_stack,
offset=nmos_lower_d_pin.center(),
directions=("V", "V"),
implant_type="n",
well_type="nwell")
# bl -> nmos_upper/D on metal1 # bl -> nmos_upper/D on metal1
# bl_out -> nmos_upper/S on metal2 # bl_out -> nmos_upper/S on metal2
self.add_path("m1", self.add_path(self.col_mux_stack[0],
[bl_pin.ll(), vector(nmos_upper_d_pin.cx(), bl_pin.by()), [bl_pin.ll(), vector(nmos_upper_d_pin.cx(), bl_pin.by()),
nmos_upper_d_pin.center()]) nmos_upper_d_pin.center()])
# halfway up, move over # halfway up, move over
mid1 = bl_out_pin.uc().scale(1, 0.4) \ mid1 = bl_out_pin.uc().scale(1, 0.4) \
+ nmos_upper_s_pin.bc().scale(0, 0.4) + nmos_upper_s_pin.bc().scale(0, 0.4)
mid2 = bl_out_pin.uc().scale(0, 0.4) \ mid2 = bl_out_pin.uc().scale(0, 0.4) \
+ nmos_upper_s_pin.bc().scale(1, 0.4) + nmos_upper_s_pin.bc().scale(1, 0.4)
self.add_path("m2", self.add_path(self.col_mux_stack[2],
[bl_out_pin.uc(), mid1, mid2, nmos_upper_s_pin.bc()]) [bl_out_pin.uc(), mid1, mid2, nmos_upper_s_pin.center()])
# br -> nmos_lower/D on metal2 # br -> nmos_lower/D on metal2
# br_out -> nmos_lower/S on metal1 # br_out -> nmos_lower/S on metal1
self.add_path("m1", self.add_path(self.col_mux_stack[0],
[br_out_pin.uc(), [br_out_pin.uc(),
vector(nmos_lower_s_pin.cx(), br_out_pin.uy()), vector(nmos_lower_s_pin.cx(), br_out_pin.uy()),
nmos_lower_s_pin.center()]) nmos_lower_s_pin.center()])
@ -169,9 +215,9 @@ class single_level_column_mux(pgate.pgate):
+ nmos_lower_d_pin.uc().scale(0,0.5) + nmos_lower_d_pin.uc().scale(0,0.5)
mid2 = br_pin.bc().scale(0,0.5) \ mid2 = br_pin.bc().scale(0,0.5) \
+ nmos_lower_d_pin.uc().scale(1,0.5) + nmos_lower_d_pin.uc().scale(1,0.5)
self.add_path("m2", self.add_path(self.col_mux_stack[2],
[br_pin.bc(), mid1, mid2, nmos_lower_d_pin.uc()]) [br_pin.bc(), mid1, mid2, nmos_lower_d_pin.center()])
def add_wells(self): def add_wells(self):
""" """
Add a well and implant over the whole cell. Also, add the Add a well and implant over the whole cell. Also, add the
@ -186,17 +232,22 @@ class single_level_column_mux(pgate.pgate):
implant_type="p", implant_type="p",
well_type="p") well_type="p")
# If there is a li layer, include it in the power stack
self.add_via_center(layers=self.col_mux_stack,
offset=active_pos)
# Add the M1->..->power_grid_layer stack # Add the M1->..->power_grid_layer stack
self.add_power_pin(name = "gnd", self.add_power_pin(name = "gnd",
loc = active_pos, loc = active_pos,
start_layer="m1") start_layer="m1")
# Add well enclosure over all the tx and contact # Add well enclosure over all the tx and contact
self.add_rect(layer="pwell", if "pwell" in layer:
offset=vector(0, 0), self.add_rect(layer="pwell",
width=self.bitcell.width, offset=vector(0, 0),
height=self.height) width=self.bitcell.width,
height=self.height)
def get_stage_effort(self, corner, slew, load): def get_stage_effort(self, corner, slew, load):
""" """
Returns relative delay that the column mux. Returns relative delay that the column mux.
@ -211,4 +262,3 @@ class single_level_column_mux(pgate.pgate):
load, load,
parasitic_delay, parasitic_delay,
False) False)

View File

@ -15,12 +15,12 @@ from globals import OPTS
from sram_factory import factory from sram_factory import factory
import debug import debug
class precharge_test(openram_test): class precharge_pbitcell_test(openram_test):
def runTest(self): def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file) globals.init_openram(config_file)
# check precharge in multi-port # check precharge in multi-port
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1 OPTS.num_rw_ports = 1
@ -36,14 +36,14 @@ class precharge_test(openram_test):
debug.info(2, "Checking precharge for pbitcell (innermost connections)") debug.info(2, "Checking precharge for pbitcell (innermost connections)")
tx = factory.create(module_type="precharge", size=1, bitcell_bl="bl1", bitcell_br="br1") tx = factory.create(module_type="precharge", size=1, bitcell_bl="bl1", bitcell_br="br1")
self.local_check(tx) self.local_check(tx)
factory.reset() factory.reset()
debug.info(2, "Checking precharge for pbitcell (outermost connections)") debug.info(2, "Checking precharge for pbitcell (outermost connections)")
tx = factory.create(module_type="precharge", size=1, bitcell_bl="bl2", bitcell_br="br2") tx = factory.create(module_type="precharge", size=1, bitcell_bl="bl2", bitcell_br="br2")
self.local_check(tx) self.local_check(tx)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line
if __name__ == "__main__": if __name__ == "__main__":
(OPTS, args) = globals.parse_args() (OPTS, args) = globals.parse_args()

View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
#@unittest.skip("SKIPPING 04_driver_test")
class single_level_column_mux_pbitcell_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
# check single level column mux in multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_r_ports = 1
OPTS.num_w_ports = 1
factory.reset()
debug.info(2, "Checking column mux for pbitcell (innermost connections)")
tx = factory.create(module_type="single_level_column_mux", tx_size=8, bitcell_bl="bl0", bitcell_br="br0")
self.local_check(tx)
factory.reset()
debug.info(2, "Checking column mux for pbitcell (outermost connections)")
tx = factory.create(module_type="single_level_column_mux",tx_size=8, bitcell_bl="bl2", bitcell_br="br2")
self.local_check(tx)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -22,30 +22,14 @@ class single_level_column_mux_test(openram_test):
def runTest(self): def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file) globals.init_openram(config_file)
# check single level column mux in single port # check single level column mux in single port
debug.info(2, "Checking column mux") debug.info(2, "Checking column mux")
tx = factory.create(module_type="single_level_column_mux", tx_size=8) tx = factory.create(module_type="single_level_column_mux", tx_size=8)
self.local_check(tx) self.local_check(tx)
# check single level column mux in multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_r_ports = 1
OPTS.num_w_ports = 1
factory.reset()
debug.info(2, "Checking column mux for pbitcell (innermost connections)")
tx = factory.create(module_type="single_level_column_mux", tx_size=8, bitcell_bl="bl0", bitcell_br="br0")
self.local_check(tx)
factory.reset()
debug.info(2, "Checking column mux for pbitcell (outermost connections)")
tx = factory.create(module_type="single_level_column_mux",tx_size=8, bitcell_bl="bl2", bitcell_br="br2")
self.local_check(tx)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line
if __name__ == "__main__": if __name__ == "__main__":
(OPTS, args) = globals.parse_args() (OPTS, args) = globals.parse_args()

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# See LICENSE for licensing information. # See LICENSE for licensing information.
# #
# Copyright (c) 2016-2019 Regents of the University of California # Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved. # All rights reserved.
# #
import unittest import unittest
@ -13,7 +13,7 @@ from globals import OPTS
from sram_factory import factory from sram_factory import factory
import debug import debug
class replica_bitcell_array_test(openram_test): class replica_pbitcell_array_test(openram_test):
def runTest(self): def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
@ -41,7 +41,7 @@ class replica_bitcell_array_test(openram_test):
debug.info(2, "Testing 4x4 array for pbitcell") debug.info(2, "Testing 4x4 array for pbitcell")
a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=1, right_rbl=0, bitcell_ports=[0]) a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=1, right_rbl=0, bitcell_ports=[0])
self.local_check(a) self.local_check(a)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line

View File

@ -15,7 +15,7 @@ from globals import OPTS
from sram_factory import factory from sram_factory import factory
import debug import debug
class hierarchical_decoder_test(openram_test): class hierarchical_decoder_pbitcell_test(openram_test):
def runTest(self): def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
@ -64,7 +64,7 @@ class hierarchical_decoder_test(openram_test):
self.local_check(a) self.local_check(a)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line
if __name__ == "__main__": if __name__ == "__main__":
(OPTS, args) = globals.parse_args() (OPTS, args) = globals.parse_args()

View File

@ -15,7 +15,7 @@ from globals import OPTS
from sram_factory import factory from sram_factory import factory
import debug import debug
class hierarchical_predecode2x4_test(openram_test): class hierarchical_predecode2x4_pbitcell_test(openram_test):
def runTest(self): def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
@ -26,13 +26,13 @@ class hierarchical_predecode2x4_test(openram_test):
OPTS.num_rw_ports = 1 OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0 OPTS.num_w_ports = 0
OPTS.num_r_ports = 0 OPTS.num_r_ports = 0
debug.info(1, "Testing sample for hierarchy_predecode2x4 (multi-port case)") debug.info(1, "Testing sample for hierarchy_predecode2x4 (multi-port case)")
a = factory.create(module_type="hierarchical_predecode2x4") a = factory.create(module_type="hierarchical_predecode2x4")
self.local_check(a) self.local_check(a)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line
if __name__ == "__main__": if __name__ == "__main__":
(OPTS, args) = globals.parse_args() (OPTS, args) = globals.parse_args()

View File

@ -27,7 +27,7 @@ class hierarchical_predecode2x4_test(openram_test):
self.local_check(a) self.local_check(a)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line
if __name__ == "__main__": if __name__ == "__main__":
(OPTS, args) = globals.parse_args() (OPTS, args) = globals.parse_args()

View File

@ -15,7 +15,7 @@ from globals import OPTS
from sram_factory import factory from sram_factory import factory
import debug import debug
class hierarchical_predecode3x8_test(openram_test): class hierarchical_predecode3x8_pbitcell_test(openram_test):
def runTest(self): def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
@ -26,7 +26,7 @@ class hierarchical_predecode3x8_test(openram_test):
OPTS.num_rw_ports = 1 OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0 OPTS.num_w_ports = 0
OPTS.num_r_ports = 0 OPTS.num_r_ports = 0
debug.info(1, "Testing sample for hierarchy_predecode3x8 (multi-port case)") debug.info(1, "Testing sample for hierarchy_predecode3x8 (multi-port case)")
a = factory.create(module_type="hierarchical_predecode3x8") a = factory.create(module_type="hierarchical_predecode3x8")
self.local_check(a) self.local_check(a)

View File

@ -25,7 +25,7 @@ class hierarchical_predecode3x8_test(openram_test):
debug.info(1, "Testing sample for hierarchy_predecode3x8") debug.info(1, "Testing sample for hierarchy_predecode3x8")
a = factory.create(module_type="hierarchical_predecode3x8") a = factory.create(module_type="hierarchical_predecode3x8")
self.local_check(a) self.local_check(a)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line

View File

@ -0,0 +1,55 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class single_level_column_mux_pbitcell_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
import single_level_column_mux_array
# check single level column mux array in multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_r_ports = 1
OPTS.num_w_ports = 1
factory.reset()
debug.info(1, "Testing sample for 2-way column_mux_array in multi-port")
a = factory.create(module_type="single_level_column_mux_array", columns=16, word_size=8, bitcell_bl="bl0", bitcell_br="br0")
self.local_check(a)
debug.info(1, "Testing sample for 4-way column_mux_array in multi-port")
a = factory.create(module_type="single_level_column_mux_array", columns=16, word_size=4, bitcell_bl="bl0", bitcell_br="br0")
self.local_check(a)
debug.info(1, "Testing sample for 8-way column_mux_array in multi-port (innermost connections)")
a = factory.create(module_type="single_level_column_mux_array", columns=32, word_size=4, bitcell_bl="bl0", bitcell_br="br0")
self.local_check(a)
debug.info(1, "Testing sample for 8-way column_mux_array in multi-port (outermost connections)")
a = factory.create(module_type="single_level_column_mux_array", columns=32, word_size=4, bitcell_bl="bl2", bitcell_br="br2")
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -20,7 +20,7 @@ class single_level_column_mux_test(openram_test):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file) globals.init_openram(config_file)
import single_level_column_mux_array import single_level_column_mux_array
# check single level column mux array in single port # check single level column mux array in single port
debug.info(1, "Testing sample for 2-way column_mux_array") debug.info(1, "Testing sample for 2-way column_mux_array")
a = factory.create(module_type="single_level_column_mux_array", columns=16, word_size=8) a = factory.create(module_type="single_level_column_mux_array", columns=16, word_size=8)
@ -33,32 +33,9 @@ class single_level_column_mux_test(openram_test):
debug.info(1, "Testing sample for 8-way column_mux_array") debug.info(1, "Testing sample for 8-way column_mux_array")
a = factory.create(module_type="single_level_column_mux_array", columns=32, word_size=4) a = factory.create(module_type="single_level_column_mux_array", columns=32, word_size=4)
self.local_check(a) self.local_check(a)
# check single level column mux array in multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_r_ports = 1
OPTS.num_w_ports = 1
factory.reset()
debug.info(1, "Testing sample for 2-way column_mux_array in multi-port")
a = factory.create(module_type="single_level_column_mux_array", columns=16, word_size=8, bitcell_bl="bl0", bitcell_br="br0")
self.local_check(a)
debug.info(1, "Testing sample for 4-way column_mux_array in multi-port")
a = factory.create(module_type="single_level_column_mux_array", columns=16, word_size=4, bitcell_bl="bl0", bitcell_br="br0")
self.local_check(a)
debug.info(1, "Testing sample for 8-way column_mux_array in multi-port (innermost connections)")
a = factory.create(module_type="single_level_column_mux_array", columns=32, word_size=4, bitcell_bl="bl0", bitcell_br="br0")
self.local_check(a)
debug.info(1, "Testing sample for 8-way column_mux_array in multi-port (outermost connections)")
a = factory.create(module_type="single_level_column_mux_array", columns=32, word_size=4, bitcell_bl="bl2", bitcell_br="br2")
self.local_check(a)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -0,0 +1,44 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
#@unittest.skip("SKIPPING 04_driver_test")
class wordline_driver_pbitcell_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
# check wordline driver for multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
factory.reset()
debug.info(2, "Checking driver (multi-port case)")
tx = factory.create(module_type="wordline_driver", rows=8, cols=64)
self.local_check(tx)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -28,19 +28,8 @@ class wordline_driver_test(openram_test):
tx = factory.create(module_type="wordline_driver", rows=8, cols=32) tx = factory.create(module_type="wordline_driver", rows=8, cols=32)
self.local_check(tx) self.local_check(tx)
# check wordline driver for multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
factory.reset()
debug.info(2, "Checking driver (multi-port case)")
tx = factory.create(module_type="wordline_driver", rows=8, cols=64)
self.local_check(tx)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line
if __name__ == "__main__": if __name__ == "__main__":
(OPTS, args) = globals.parse_args() (OPTS, args) = globals.parse_args()

View File

@ -34,21 +34,6 @@ class sense_amp_test(openram_test):
a = factory.create(module_type="sense_amp_array", word_size=4, words_per_row=4) a = factory.create(module_type="sense_amp_array", word_size=4, words_per_row=4)
self.local_check(a) self.local_check(a)
# check sense amp array for multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
factory.reset()
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=2 (multi-port case)")
a = factory.create(module_type="sense_amp_array", word_size=4, words_per_row=2)
self.local_check(a)
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=4 (multi-port case)")
a = factory.create(module_type="sense_amp_array", word_size=4, words_per_row=4)
self.local_check(a)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line

View File

@ -0,0 +1,46 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class sense_amp_pbitcell_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
#check sense amp array for multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
factory.reset()
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=2 (multi-port case)")
a = factory.create(module_type="sense_amp_array", word_size=4, words_per_row=2)
self.local_check(a)
debug.info(2, "Testing sense_amp_array for word_size=4, words_per_row=4 (multi-port case)")
a = factory.create(module_type="sense_amp_array", word_size=4, words_per_row=4)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -0,0 +1,46 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class write_driver_pbitcell_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
# check write driver array for multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
factory.reset()
debug.info(2, "Testing write_driver_array for columns=8, word_size=8 (multi-port case)")
a = factory.create(module_type="write_driver_array", columns=8, word_size=8)
self.local_check(a)
debug.info(2, "Testing write_driver_array for columns=16, word_size=8 (multi-port case)")
a = factory.create(module_type="write_driver_array", columns=16, word_size=8)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -29,22 +29,7 @@ class write_driver_test(openram_test):
debug.info(2, "Testing write_driver_array for columns=16, word_size=8") debug.info(2, "Testing write_driver_array for columns=16, word_size=8")
a = factory.create(module_type="write_driver_array", columns=16, word_size=8) a = factory.create(module_type="write_driver_array", columns=16, word_size=8)
self.local_check(a) self.local_check(a)
# check write driver array for multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
factory.reset()
debug.info(2, "Testing write_driver_array for columns=8, word_size=8 (multi-port case)")
a = factory.create(module_type="write_driver_array", columns=8, word_size=8)
self.local_check(a)
debug.info(2, "Testing write_driver_array for columns=16, word_size=8 (multi-port case)")
a = factory.create(module_type="write_driver_array", columns=16, word_size=8)
self.local_check(a)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line

View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import unittest
from testutils import *
import sys, os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class write_driver_pbitcell_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
# check write driver array for multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
factory.reset()
debug.info(2, "Testing write_driver_array for columns=8, word_size=8, write_size=4 (multi-port case)")
a = factory.create(module_type="write_driver_array", columns=8, word_size=8, write_size=4)
self.local_check(a)
debug.info(2, "Testing write_driver_array for columns=16, word_size=8, write_size=4 (multi-port case)")
a = factory.create(module_type="write_driver_array", columns=16, word_size=8, write_size=4)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -36,21 +36,6 @@ class write_driver_test(openram_test):
a = factory.create(module_type="write_driver_array", columns=16, word_size=8, write_size=4) a = factory.create(module_type="write_driver_array", columns=16, word_size=8, write_size=4)
self.local_check(a) self.local_check(a)
# check write driver array for multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
factory.reset()
debug.info(2, "Testing write_driver_array for columns=8, word_size=8, write_size=4 (multi-port case)")
a = factory.create(module_type="write_driver_array", columns=8, word_size=8, write_size=4)
self.local_check(a)
debug.info(2, "Testing write_driver_array for columns=16, word_size=8, write_size=4 (multi-port case)")
a = factory.create(module_type="write_driver_array", columns=16, word_size=8, write_size=4)
self.local_check(a)
globals.end_openram() globals.end_openram()

View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import unittest
from testutils import *
import sys, os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class write_mask_and_array_pbitcell_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
# check write driver array for multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
factory.reset()
debug.info(2, "Testing write_mask_and_array for columns=8, word_size=8, write_size=4 (multi-port case)")
a = factory.create(module_type="write_mask_and_array", columns=8, word_size=8, write_size=4)
self.local_check(a)
debug.info(2, "Testing write_mask_and_array for columns=16, word_size=8, write_size=2 (multi-port case)")
a = factory.create(module_type="write_mask_and_array", columns=16, word_size=8, write_size=2)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -36,21 +36,6 @@ class write_mask_and_array_test(openram_test):
a = factory.create(module_type="write_mask_and_array", columns=16, word_size=8, write_size=2) a = factory.create(module_type="write_mask_and_array", columns=16, word_size=8, write_size=2)
self.local_check(a) self.local_check(a)
# check write driver array for multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0
OPTS.num_r_ports = 0
factory.reset()
debug.info(2, "Testing write_mask_and_array for columns=8, word_size=8, write_size=4 (multi-port case)")
a = factory.create(module_type="write_mask_and_array", columns=8, word_size=8, write_size=4)
self.local_check(a)
debug.info(2, "Testing write_mask_and_array for columns=16, word_size=8, write_size=2 (multi-port case)")
a = factory.create(module_type="write_mask_and_array", columns=16, word_size=8, write_size=2)
self.local_check(a)
globals.end_openram() globals.end_openram()

View File

@ -0,0 +1,78 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class port_data_1rw_1r_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
from sram_config import sram_config
OPTS.bitcell = "bitcell_1w_1r"
OPTS.num_rw_ports = 0
OPTS.num_r_ports = 1
OPTS.num_w_ports = 1
c = sram_config(word_size=4,
num_words=16)
c.words_per_row=1
factory.reset()
c.recompute_sizes()
debug.info(1, "No column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.num_words=32
c.words_per_row=2
factory.reset()
c.recompute_sizes()
debug.info(1, "Two way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.num_words=64
c.words_per_row=4
factory.reset()
c.recompute_sizes()
debug.info(1, "Four way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.word_size=2
c.num_words=128
c.words_per_row=8
factory.reset()
c.recompute_sizes()
debug.info(1, "Eight way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -55,52 +55,6 @@ class port_data_test(openram_test):
a = factory.create("port_data", sram_config=c, port=0) a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a) self.local_check(a)
OPTS.bitcell = "bitcell_1w_1r"
OPTS.num_rw_ports = 0
OPTS.num_r_ports = 1
OPTS.num_w_ports = 1
c.num_words=16
c.words_per_row=1
factory.reset()
c.recompute_sizes()
debug.info(1, "No column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.num_words=32
c.words_per_row=2
factory.reset()
c.recompute_sizes()
debug.info(1, "Two way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.num_words=64
c.words_per_row=4
factory.reset()
c.recompute_sizes()
debug.info(1, "Four way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.word_size=2
c.num_words=128
c.words_per_row=8
factory.reset()
c.recompute_sizes()
debug.info(1, "Eight way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line

View File

@ -0,0 +1,48 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class bank_select_test(openram_test):
def runTest(self):
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
globals.init_openram(config_file)
OPTS.bitcell = "pbitcell"
debug.info(1, "No column mux, rw control logic")
a = factory.create(module_type="bank_select", port="rw")
self.local_check(a)
OPTS.num_rw_ports = 0
OPTS.num_w_ports = 1
OPTS.num_r_ports = 1
debug.info(1, "No column mux, w control logic")
a = factory.create(module_type="bank_select", port="w")
self.local_check(a)
debug.info(1, "No column mux, r control logic")
a = factory.create(module_type="bank_select", port="r")
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -24,26 +24,9 @@ class bank_select_test(openram_test):
debug.info(1, "No column mux, rw control logic") debug.info(1, "No column mux, rw control logic")
a = factory.create(module_type="bank_select", port="rw") a = factory.create(module_type="bank_select", port="rw")
self.local_check(a) self.local_check(a)
OPTS.bitcell = "pbitcell"
debug.info(1, "No column mux, rw control logic")
a = factory.create(module_type="bank_select", port="rw")
self.local_check(a)
OPTS.num_rw_ports = 0
OPTS.num_w_ports = 1
OPTS.num_r_ports = 1
debug.info(1, "No column mux, w control logic")
a = factory.create(module_type="bank_select", port="w")
self.local_check(a)
debug.info(1, "No column mux, r control logic")
a = factory.create(module_type="bank_select", port="r")
self.local_check(a)
globals.end_openram() globals.end_openram()
# run the test from the command line # run the test from the command line
if __name__ == "__main__": if __name__ == "__main__":
(OPTS, args) = globals.parse_args() (OPTS, args) = globals.parse_args()

View File

@ -60,29 +60,36 @@ class timing_sram_test(openram_test):
data, port_data = d.analyze(probe_address, probe_data, slews, loads) data, port_data = d.analyze(probe_address, probe_data, slews, loads)
#Combine info about port into all data #Combine info about port into all data
data.update(port_data[0]) data.update(port_data[0])
if OPTS.tech_name == "freepdk45": if OPTS.tech_name == "freepdk45":
golden_data = {'delay_hl': [0.2383338], golden_data = {'min_period': 0.898,
'delay_lh': [0.2383338], 'write1_power': [0.2659137999999999],
'leakage_power': 0.0014532999999999998, 'disabled_write0_power': [0.1782495],
'min_period': 0.898, 'disabled_read0_power': [0.14490679999999997],
'read0_power': [0.30059800000000003], 'write0_power': [0.3330119],
'read1_power': [0.30061810000000005], 'disabled_write1_power': [0.1865223],
'slew_hl': [0.25358420000000004], 'leakage_power': 0.0014532,
'slew_lh': [0.25358420000000004], 'disabled_read1_power': [0.1627516],
'write0_power': [0.34616749999999996], 'slew_lh': [0.25367799999999996],
'write1_power': [0.2792924]} 'slew_hl': [0.25367799999999996],
'delay_lh': [0.23820930000000004],
'delay_hl': [0.23820930000000004],
'read1_power': [0.3005756],
'read0_power': [0.3005888]}
elif OPTS.tech_name == "scn4m_subm": elif OPTS.tech_name == "scn4m_subm":
golden_data = {'delay_hl': [1.7448], golden_data = {'leakage_power': 0.0006356576000000001,
'delay_lh': [1.7448], 'write1_power': [11.292700000000002],
'leakage_power': 0.0006356744000000001, 'read0_power': [12.98],
'disabled_write1_power': [8.3707],
'write0_power': [14.4447], 'delay_hl': [1.7445000000000002],
'disabled_read0_power': [6.4325],
'slew_hl': [1.7437],
'disabled_write0_power': [8.1307],
'slew_lh': [1.7437],
'read1_power': [12.9869],
'disabled_read1_power': [7.706],
'min_period': 6.25, 'min_period': 6.25,
'read0_power': [12.9846], 'delay_lh': [1.7445000000000002]}
'read1_power': [12.9722],
'slew_hl': [1.7433],
'slew_lh': [1.7433],
'write0_power': [14.8772],
'write1_power': [11.7217]}
else: else:
self.assertTrue(False) # other techs fail self.assertTrue(False) # other techs fail
# Check if no too many or too few results # Check if no too many or too few results

View File

@ -55,27 +55,35 @@ class timing_sram_test(openram_test):
data.update(port_data[0]) data.update(port_data[0])
if OPTS.tech_name == "freepdk45": if OPTS.tech_name == "freepdk45":
golden_data = {'delay_hl': [0.2264205], golden_data = {'slew_lh': [0.2592187],
'delay_lh': [0.2264205], 'slew_hl': [0.2592187],
'leakage_power': 0.0021017429999999997, 'delay_lh': [0.2465583],
'min_period': 0.859, 'disabled_write0_power': [0.1924678],
'read0_power': [0.3339161], 'disabled_read0_power': [0.152483],
'read1_power': [0.31329440000000003], 'write0_power': [0.3409064],
'slew_hl': [0.2590786], 'disabled_read1_power': [0.1737818],
'slew_lh': [0.2590786], 'read0_power': [0.3096708],
'write0_power': [0.36360849999999995], 'read1_power': [0.3107916],
'write1_power': [0.3486931]} 'delay_hl': [0.2465583],
'write1_power': [0.26915849999999997],
'leakage_power': 0.002044307,
'min_period': 0.898,
'disabled_write1_power': [0.201411]}
elif OPTS.tech_name == "scn4m_subm": elif OPTS.tech_name == "scn4m_subm":
golden_data = {'delay_hl': [1.85985], golden_data = {'read1_power': [12.11658],
'delay_lh': [1.85985], 'write1_power': [10.52653],
'read0_power': [11.956710000000001],
'disabled_write0_power': [7.673665],
'disabled_write1_power': [7.981922000000001],
'slew_lh': [1.868836],
'slew_hl': [1.868836],
'delay_hl': [1.8598510000000001],
'delay_lh': [1.8598510000000001],
'leakage_power': 0.008613619, 'leakage_power': 0.008613619,
'disabled_read0_power': [5.904712],
'min_period': 6.875, 'min_period': 6.875,
'read0_power': [12.656310000000001], 'disabled_read1_power': [7.132159],
'read1_power': [12.11682], 'write0_power': [13.406400000000001]}
'slew_hl': [1.868942],
'slew_lh': [1.868942],
'write0_power': [13.978110000000001],
'write1_power': [11.437930000000001]}
else: else:
self.assertTrue(False) # other techs fail self.assertTrue(False) # other techs fail

View File

@ -35,11 +35,14 @@ library (sram_2_16_1_freepdk45_FF_1p0V_25C_lib){
default_max_fanout : 4.0 ; default_max_fanout : 4.0 ;
default_connection_class : universal ; default_connection_class : universal ;
voltage_map ( VDD, 1.0 );
voltage_map ( GND, 0 );
lu_table_template(CELL_TABLE){ lu_table_template(CELL_TABLE){
variable_1 : input_net_transition; variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance; variable_2 : total_output_net_capacitance;
index_1("0.00125, 0.005, 0.04"); index_1("0.00125, 0.005, 0.04");
index_2("0.052275, 0.2091, 1.6728"); index_2("5.2275e-05, 0.0002091, 0.0008364");
} }
lu_table_template(CONSTRAINT_TABLE){ lu_table_template(CONSTRAINT_TABLE){
@ -78,17 +81,26 @@ cell (sram_2_16_1_freepdk45){
dont_use : true; dont_use : true;
map_only : true; map_only : true;
dont_touch : true; dont_touch : true;
area : 1124.88; area : 0;
pg_pin(vdd) {
voltage_name : VDD;
pg_type : primary_power;
}
pg_pin(gnd) {
voltage_name : GND;
pg_type : primary_ground;
}
leakage_power () { leakage_power () {
when : "csb0"; value : 0.000198;
value : 0.000167;
} }
cell_leakage_power : 0; cell_leakage_power : 0.000198;
bus(din0){ bus(din0){
bus_type : data; bus_type : data;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
memory_write(){ memory_write(){
address : addr0; address : addr0;
clocked_on : clk0; clocked_on : clk0;
@ -127,8 +139,8 @@ cell (sram_2_16_1_freepdk45){
bus(dout0){ bus(dout0){
bus_type : data; bus_type : data;
direction : output; direction : output;
max_capacitance : 1.6728; max_capacitance : 0.0008364000000000001;
min_capacitance : 0.052275; min_capacitance : 5.2275000000000003e-05;
memory_read(){ memory_read(){
address : addr0; address : addr0;
} }
@ -138,14 +150,14 @@ cell (sram_2_16_1_freepdk45){
related_pin : "clk0"; related_pin : "clk0";
timing_type : falling_edge; timing_type : falling_edge;
cell_rise(CELL_TABLE) { cell_rise(CELL_TABLE) {
values("0.088, 0.088, 0.088",\ values("0.193, 0.193, 0.194",\
"0.088, 0.088, 0.088",\ "0.193, 0.193, 0.194",\
"0.088, 0.088, 0.088"); "0.193, 0.193, 0.194");
} }
cell_fall(CELL_TABLE) { cell_fall(CELL_TABLE) {
values("0.088, 0.088, 0.088",\ values("0.193, 0.193, 0.194",\
"0.088, 0.088, 0.088",\ "0.193, 0.193, 0.194",\
"0.088, 0.088, 0.088"); "0.193, 0.193, 0.194");
} }
rise_transition(CELL_TABLE) { rise_transition(CELL_TABLE) {
values("0.001, 0.001, 0.001",\ values("0.001, 0.001, 0.001",\
@ -164,7 +176,7 @@ cell (sram_2_16_1_freepdk45){
bus(addr0){ bus(addr0){
bus_type : addr; bus_type : addr;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
max_transition : 0.04; max_transition : 0.04;
pin(addr0[3:0]){ pin(addr0[3:0]){
timing(){ timing(){
@ -200,7 +212,7 @@ cell (sram_2_16_1_freepdk45){
pin(csb0){ pin(csb0){
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
@ -233,7 +245,7 @@ cell (sram_2_16_1_freepdk45){
pin(web0){ pin(web0){
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
@ -267,52 +279,61 @@ cell (sram_2_16_1_freepdk45){
pin(clk0){ pin(clk0){
clock : true; clock : true;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
internal_power(){ internal_power(){
when : "!csb0 & clk0 & !web0"; when : "!csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("0.033101244168888884"); values("9.240667e-02");
} }
fall_power(scalar){ fall_power(scalar){
values("0.033101244168888884"); values("9.240667e-02");
} }
} }
internal_power(){ internal_power(){
when : "!csb0 & !clk0 & web0"; when : "csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("0.033101244168888884"); values("9.240667e-02");
} }
fall_power(scalar){ fall_power(scalar){
values("0.033101244168888884"); values("9.240667e-02");
} }
} }
internal_power(){ internal_power(){
when : "csb0"; when : "!csb0 & web0";
rise_power(scalar){ rise_power(scalar){
values("0"); values("9.240667e-02");
} }
fall_power(scalar){ fall_power(scalar){
values("0"); values("9.240667e-02");
}
}
internal_power(){
when : "csb0 & web0";
rise_power(scalar){
values("9.240667e-02");
}
fall_power(scalar){
values("9.240667e-02");
} }
} }
timing(){ timing(){
timing_type :"min_pulse_width"; timing_type :"min_pulse_width";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.009"); values("0.0195");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.009"); values("0.0195");
} }
} }
timing(){ timing(){
timing_type :"minimum_period"; timing_type :"minimum_period";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.018"); values("0.039");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.018"); values("0.039");
} }
} }
} }

View File

@ -35,11 +35,14 @@ library (sram_2_16_1_freepdk45_SS_1p0V_25C_lib){
default_max_fanout : 4.0 ; default_max_fanout : 4.0 ;
default_connection_class : universal ; default_connection_class : universal ;
voltage_map ( VDD, 1.0 );
voltage_map ( GND, 0 );
lu_table_template(CELL_TABLE){ lu_table_template(CELL_TABLE){
variable_1 : input_net_transition; variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance; variable_2 : total_output_net_capacitance;
index_1("0.00125, 0.005, 0.04"); index_1("0.00125, 0.005, 0.04");
index_2("0.052275, 0.2091, 1.6728"); index_2("5.2275e-05, 0.0002091, 0.0008364");
} }
lu_table_template(CONSTRAINT_TABLE){ lu_table_template(CONSTRAINT_TABLE){
@ -78,17 +81,26 @@ cell (sram_2_16_1_freepdk45){
dont_use : true; dont_use : true;
map_only : true; map_only : true;
dont_touch : true; dont_touch : true;
area : 1124.88; area : 0;
pg_pin(vdd) {
voltage_name : VDD;
pg_type : primary_power;
}
pg_pin(gnd) {
voltage_name : GND;
pg_type : primary_ground;
}
leakage_power () { leakage_power () {
when : "csb0"; value : 0.000198;
value : 0.000167;
} }
cell_leakage_power : 0; cell_leakage_power : 0.000198;
bus(din0){ bus(din0){
bus_type : data; bus_type : data;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
memory_write(){ memory_write(){
address : addr0; address : addr0;
clocked_on : clk0; clocked_on : clk0;
@ -127,8 +139,8 @@ cell (sram_2_16_1_freepdk45){
bus(dout0){ bus(dout0){
bus_type : data; bus_type : data;
direction : output; direction : output;
max_capacitance : 1.6728; max_capacitance : 0.0008364000000000001;
min_capacitance : 0.052275; min_capacitance : 5.2275000000000003e-05;
memory_read(){ memory_read(){
address : addr0; address : addr0;
} }
@ -138,14 +150,14 @@ cell (sram_2_16_1_freepdk45){
related_pin : "clk0"; related_pin : "clk0";
timing_type : falling_edge; timing_type : falling_edge;
cell_rise(CELL_TABLE) { cell_rise(CELL_TABLE) {
values("0.107, 0.107, 0.107",\ values("0.236, 0.236, 0.237",\
"0.107, 0.107, 0.107",\ "0.236, 0.236, 0.237",\
"0.107, 0.107, 0.107"); "0.236, 0.236, 0.237");
} }
cell_fall(CELL_TABLE) { cell_fall(CELL_TABLE) {
values("0.107, 0.107, 0.107",\ values("0.236, 0.236, 0.237",\
"0.107, 0.107, 0.107",\ "0.236, 0.236, 0.237",\
"0.107, 0.107, 0.107"); "0.236, 0.236, 0.237");
} }
rise_transition(CELL_TABLE) { rise_transition(CELL_TABLE) {
values("0.001, 0.001, 0.001",\ values("0.001, 0.001, 0.001",\
@ -164,7 +176,7 @@ cell (sram_2_16_1_freepdk45){
bus(addr0){ bus(addr0){
bus_type : addr; bus_type : addr;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
max_transition : 0.04; max_transition : 0.04;
pin(addr0[3:0]){ pin(addr0[3:0]){
timing(){ timing(){
@ -200,7 +212,7 @@ cell (sram_2_16_1_freepdk45){
pin(csb0){ pin(csb0){
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
@ -233,7 +245,7 @@ cell (sram_2_16_1_freepdk45){
pin(web0){ pin(web0){
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
@ -267,52 +279,61 @@ cell (sram_2_16_1_freepdk45){
pin(clk0){ pin(clk0){
clock : true; clock : true;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
internal_power(){ internal_power(){
when : "!csb0 & clk0 & !web0"; when : "!csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("0.033101244168888884"); values("7.560546e-02");
} }
fall_power(scalar){ fall_power(scalar){
values("0.033101244168888884"); values("7.560546e-02");
} }
} }
internal_power(){ internal_power(){
when : "!csb0 & !clk0 & web0"; when : "csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("0.033101244168888884"); values("7.560546e-02");
} }
fall_power(scalar){ fall_power(scalar){
values("0.033101244168888884"); values("7.560546e-02");
} }
} }
internal_power(){ internal_power(){
when : "csb0"; when : "!csb0 & web0";
rise_power(scalar){ rise_power(scalar){
values("0"); values("7.560546e-02");
} }
fall_power(scalar){ fall_power(scalar){
values("0"); values("7.560546e-02");
}
}
internal_power(){
when : "csb0 & web0";
rise_power(scalar){
values("7.560546e-02");
}
fall_power(scalar){
values("7.560546e-02");
} }
} }
timing(){ timing(){
timing_type :"min_pulse_width"; timing_type :"min_pulse_width";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.0105"); values("0.0235");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.0105"); values("0.0235");
} }
} }
timing(){ timing(){
timing_type :"minimum_period"; timing_type :"minimum_period";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.021"); values("0.047");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.021"); values("0.047");
} }
} }
} }

View File

@ -35,11 +35,14 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){
default_max_fanout : 4.0 ; default_max_fanout : 4.0 ;
default_connection_class : universal ; default_connection_class : universal ;
voltage_map ( VDD, 1.0 );
voltage_map ( GND, 0 );
lu_table_template(CELL_TABLE){ lu_table_template(CELL_TABLE){
variable_1 : input_net_transition; variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance; variable_2 : total_output_net_capacitance;
index_1("0.00125, 0.005, 0.04"); index_1("0.00125, 0.005, 0.04");
index_2("0.052275, 0.2091, 1.6728"); index_2("5.2275e-05, 0.0002091, 0.0008364");
} }
lu_table_template(CONSTRAINT_TABLE){ lu_table_template(CONSTRAINT_TABLE){
@ -78,17 +81,26 @@ cell (sram_2_16_1_freepdk45){
dont_use : true; dont_use : true;
map_only : true; map_only : true;
dont_touch : true; dont_touch : true;
area : 977.4951374999999; area : 0;
pg_pin(vdd) {
voltage_name : VDD;
pg_type : primary_power;
}
pg_pin(gnd) {
voltage_name : GND;
pg_type : primary_ground;
}
leakage_power () { leakage_power () {
when : "csb0"; value : 0.00163;
value : 0.0011164579999999999;
} }
cell_leakage_power : 0; cell_leakage_power : 0.00163;
bus(din0){ bus(din0){
bus_type : data; bus_type : data;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
memory_write(){ memory_write(){
address : addr0; address : addr0;
clocked_on : clk0; clocked_on : clk0;
@ -98,9 +110,9 @@ cell (sram_2_16_1_freepdk45){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("0.033, 0.033, 0.039",\ values("0.033, 0.033, 0.033",\
"0.033, 0.033, 0.039",\ "0.033, 0.033, 0.033",\
"0.033, 0.033, 0.039"); "0.033, 0.033, 0.033");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("0.027, 0.027, 0.033",\ values("0.027, 0.027, 0.033",\
@ -112,14 +124,14 @@ cell (sram_2_16_1_freepdk45){
timing_type : hold_rising; timing_type : hold_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("-0.01, -0.016, -0.022",\ values("-0.01, -0.01, 0.021",\
"-0.01, -0.016, -0.022",\ "-0.01, -0.01, 0.021",\
"-0.01, -0.016, -0.022"); "-0.01, -0.01, 0.021");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("-0.016, -0.016, -0.016",\ values("-0.016, -0.01, -0.016",\
"-0.016, -0.016, -0.016",\ "-0.016, -0.01, -0.016",\
"-0.016, -0.016, -0.016"); "-0.016, -0.01, -0.016");
} }
} }
} }
@ -127,8 +139,8 @@ cell (sram_2_16_1_freepdk45){
bus(dout0){ bus(dout0){
bus_type : data; bus_type : data;
direction : output; direction : output;
max_capacitance : 1.6728; max_capacitance : 0.0008364000000000001;
min_capacitance : 0.052275; min_capacitance : 5.2275000000000003e-05;
memory_read(){ memory_read(){
address : addr0; address : addr0;
} }
@ -138,24 +150,24 @@ cell (sram_2_16_1_freepdk45){
related_pin : "clk0"; related_pin : "clk0";
timing_type : falling_edge; timing_type : falling_edge;
cell_rise(CELL_TABLE) { cell_rise(CELL_TABLE) {
values("0.235, 0.235, 0.239",\ values("0.226, 0.227, 0.232",\
"0.235, 0.236, 0.24",\ "0.227, 0.228, 0.233",\
"0.241, 0.242, 0.246"); "0.232, 0.234, 0.238");
} }
cell_fall(CELL_TABLE) { cell_fall(CELL_TABLE) {
values("2.583, 2.585, 2.612",\ values("0.226, 0.227, 0.232",\
"2.584, 2.585, 2.613",\ "0.227, 0.228, 0.233",\
"2.59, 2.592, 2.62"); "0.232, 0.234, 0.238");
} }
rise_transition(CELL_TABLE) { rise_transition(CELL_TABLE) {
values("0.022, 0.022, 0.03",\ values("0.256, 0.256, 0.257",\
"0.022, 0.023, 0.03",\ "0.256, 0.256, 0.257",\
"0.022, 0.022, 0.03"); "0.256, 0.256, 0.257");
} }
fall_transition(CELL_TABLE) { fall_transition(CELL_TABLE) {
values("0.078, 0.079, 0.083",\ values("0.256, 0.256, 0.257",\
"0.078, 0.079, 0.083",\ "0.256, 0.256, 0.257",\
"0.079, 0.079, 0.083"); "0.256, 0.256, 0.257");
} }
} }
} }
@ -164,16 +176,16 @@ cell (sram_2_16_1_freepdk45){
bus(addr0){ bus(addr0){
bus_type : addr; bus_type : addr;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
max_transition : 0.04; max_transition : 0.04;
pin(addr0[3:0]){ pin(addr0[3:0]){
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("0.033, 0.033, 0.039",\ values("0.033, 0.033, 0.033",\
"0.033, 0.033, 0.039",\ "0.033, 0.033, 0.033",\
"0.033, 0.033, 0.039"); "0.033, 0.033, 0.033");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("0.027, 0.027, 0.033",\ values("0.027, 0.027, 0.033",\
@ -185,14 +197,14 @@ cell (sram_2_16_1_freepdk45){
timing_type : hold_rising; timing_type : hold_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("-0.01, -0.016, -0.022",\ values("-0.01, -0.01, 0.021",\
"-0.01, -0.016, -0.022",\ "-0.01, -0.01, 0.021",\
"-0.01, -0.016, -0.022"); "-0.01, -0.01, 0.021");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("-0.016, -0.016, -0.016",\ values("-0.016, -0.01, -0.016",\
"-0.016, -0.016, -0.016",\ "-0.016, -0.01, -0.016",\
"-0.016, -0.016, -0.016"); "-0.016, -0.01, -0.016");
} }
} }
} }
@ -200,14 +212,14 @@ cell (sram_2_16_1_freepdk45){
pin(csb0){ pin(csb0){
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("0.033, 0.033, 0.039",\ values("0.033, 0.033, 0.033",\
"0.033, 0.033, 0.039",\ "0.033, 0.033, 0.033",\
"0.033, 0.033, 0.039"); "0.033, 0.033, 0.033");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("0.027, 0.027, 0.033",\ values("0.027, 0.027, 0.033",\
@ -219,28 +231,28 @@ cell (sram_2_16_1_freepdk45){
timing_type : hold_rising; timing_type : hold_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("-0.01, -0.016, -0.022",\ values("-0.01, -0.01, 0.021",\
"-0.01, -0.016, -0.022",\ "-0.01, -0.01, 0.021",\
"-0.01, -0.016, -0.022"); "-0.01, -0.01, 0.021");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("-0.016, -0.016, -0.016",\ values("-0.016, -0.01, -0.016",\
"-0.016, -0.016, -0.016",\ "-0.016, -0.01, -0.016",\
"-0.016, -0.016, -0.016"); "-0.016, -0.01, -0.016");
} }
} }
} }
pin(web0){ pin(web0){
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("0.033, 0.033, 0.039",\ values("0.033, 0.033, 0.033",\
"0.033, 0.033, 0.039",\ "0.033, 0.033, 0.033",\
"0.033, 0.033, 0.039"); "0.033, 0.033, 0.033");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("0.027, 0.027, 0.033",\ values("0.027, 0.027, 0.033",\
@ -252,14 +264,14 @@ cell (sram_2_16_1_freepdk45){
timing_type : hold_rising; timing_type : hold_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("-0.01, -0.016, -0.022",\ values("-0.01, -0.01, 0.021",\
"-0.01, -0.016, -0.022",\ "-0.01, -0.01, 0.021",\
"-0.01, -0.016, -0.022"); "-0.01, -0.01, 0.021");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("-0.016, -0.016, -0.016",\ values("-0.016, -0.01, -0.016",\
"-0.016, -0.016, -0.016",\ "-0.016, -0.01, -0.016",\
"-0.016, -0.016, -0.016"); "-0.016, -0.01, -0.016");
} }
} }
} }
@ -267,52 +279,61 @@ cell (sram_2_16_1_freepdk45){
pin(clk0){ pin(clk0){
clock : true; clock : true;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
internal_power(){ internal_power(){
when : "!csb0 & clk0 & !web0"; when : "!csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("0.03599689694444445"); values("3.069977e-01");
} }
fall_power(scalar){ fall_power(scalar){
values("0.03599689694444445"); values("3.686680e-01");
} }
} }
internal_power(){ internal_power(){
when : "!csb0 & !clk0 & web0"; when : "csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("0.029906643888888886"); values("2.055845e-01");
} }
fall_power(scalar){ fall_power(scalar){
values("0.029906643888888886"); values("1.933561e-01");
} }
} }
internal_power(){ internal_power(){
when : "csb0"; when : "!csb0 & web0";
rise_power(scalar){ rise_power(scalar){
values("0"); values("3.315565e-01");
} }
fall_power(scalar){ fall_power(scalar){
values("0"); values("3.314553e-01");
}
}
internal_power(){
when : "csb0 & web0";
rise_power(scalar){
values("1.777355e-01");
}
fall_power(scalar){
values("1.615044e-01");
} }
} }
timing(){ timing(){
timing_type :"min_pulse_width"; timing_type :"min_pulse_width";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("2.422"); values("0.449");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("2.422"); values("0.449");
} }
} }
timing(){ timing(){
timing_type :"minimum_period"; timing_type :"minimum_period";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("4.844"); values("0.898");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("4.844"); values("0.898");
} }
} }
} }

View File

@ -35,11 +35,14 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){
default_max_fanout : 4.0 ; default_max_fanout : 4.0 ;
default_connection_class : universal ; default_connection_class : universal ;
voltage_map ( VDD, 1.0 );
voltage_map ( GND, 0 );
lu_table_template(CELL_TABLE){ lu_table_template(CELL_TABLE){
variable_1 : input_net_transition; variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance; variable_2 : total_output_net_capacitance;
index_1("0.00125, 0.005, 0.04"); index_1("0.00125, 0.005, 0.04");
index_2("0.052275, 0.2091, 1.6728"); index_2("5.2275e-05, 0.0002091, 0.0008364");
} }
lu_table_template(CONSTRAINT_TABLE){ lu_table_template(CONSTRAINT_TABLE){
@ -78,17 +81,26 @@ cell (sram_2_16_1_freepdk45){
dont_use : true; dont_use : true;
map_only : true; map_only : true;
dont_touch : true; dont_touch : true;
area : 977.4951374999999; area : 0;
pg_pin(vdd) {
voltage_name : VDD;
pg_type : primary_power;
}
pg_pin(gnd) {
voltage_name : GND;
pg_type : primary_ground;
}
leakage_power () { leakage_power () {
when : "csb0"; value : 0.000198;
value : 0.000179;
} }
cell_leakage_power : 0; cell_leakage_power : 0.000198;
bus(din0){ bus(din0){
bus_type : data; bus_type : data;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
memory_write(){ memory_write(){
address : addr0; address : addr0;
clocked_on : clk0; clocked_on : clk0;
@ -127,8 +139,8 @@ cell (sram_2_16_1_freepdk45){
bus(dout0){ bus(dout0){
bus_type : data; bus_type : data;
direction : output; direction : output;
max_capacitance : 1.6728; max_capacitance : 0.0008364000000000001;
min_capacitance : 0.052275; min_capacitance : 5.2275000000000003e-05;
memory_read(){ memory_read(){
address : addr0; address : addr0;
} }
@ -138,14 +150,14 @@ cell (sram_2_16_1_freepdk45){
related_pin : "clk0"; related_pin : "clk0";
timing_type : falling_edge; timing_type : falling_edge;
cell_rise(CELL_TABLE) { cell_rise(CELL_TABLE) {
values("0.098, 0.098, 0.098",\ values("0.215, 0.215, 0.216",\
"0.098, 0.098, 0.098",\ "0.215, 0.215, 0.216",\
"0.098, 0.098, 0.098"); "0.215, 0.215, 0.216");
} }
cell_fall(CELL_TABLE) { cell_fall(CELL_TABLE) {
values("0.098, 0.098, 0.098",\ values("0.215, 0.215, 0.216",\
"0.098, 0.098, 0.098",\ "0.215, 0.215, 0.216",\
"0.098, 0.098, 0.098"); "0.215, 0.215, 0.216");
} }
rise_transition(CELL_TABLE) { rise_transition(CELL_TABLE) {
values("0.001, 0.001, 0.001",\ values("0.001, 0.001, 0.001",\
@ -164,7 +176,7 @@ cell (sram_2_16_1_freepdk45){
bus(addr0){ bus(addr0){
bus_type : addr; bus_type : addr;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
max_transition : 0.04; max_transition : 0.04;
pin(addr0[3:0]){ pin(addr0[3:0]){
timing(){ timing(){
@ -200,7 +212,7 @@ cell (sram_2_16_1_freepdk45){
pin(csb0){ pin(csb0){
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
@ -233,7 +245,7 @@ cell (sram_2_16_1_freepdk45){
pin(web0){ pin(web0){
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
@ -267,52 +279,61 @@ cell (sram_2_16_1_freepdk45){
pin(clk0){ pin(clk0){
clock : true; clock : true;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.00020910000000000001;
internal_power(){ internal_power(){
when : "!csb0 & clk0 & !web0"; when : "!csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("0.0747594982142222"); values("8.316600e-02");
} }
fall_power(scalar){ fall_power(scalar){
values("0.0747594982142222"); values("8.316600e-02");
} }
} }
internal_power(){ internal_power(){
when : "!csb0 & !clk0 & web0"; when : "csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("0.0747594982142222"); values("8.316600e-02");
} }
fall_power(scalar){ fall_power(scalar){
values("0.0747594982142222"); values("8.316600e-02");
} }
} }
internal_power(){ internal_power(){
when : "csb0"; when : "!csb0 & web0";
rise_power(scalar){ rise_power(scalar){
values("0"); values("8.316600e-02");
} }
fall_power(scalar){ fall_power(scalar){
values("0"); values("8.316600e-02");
}
}
internal_power(){
when : "csb0 & web0";
rise_power(scalar){
values("8.316600e-02");
}
fall_power(scalar){
values("8.316600e-02");
} }
} }
timing(){ timing(){
timing_type :"min_pulse_width"; timing_type :"min_pulse_width";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.0"); values("0.0215");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.0"); values("0.0215");
} }
} }
timing(){ timing(){
timing_type :"minimum_period"; timing_type :"minimum_period";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0"); values("0.043");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0"); values("0.043");
} }
} }
} }

View File

@ -35,11 +35,14 @@ library (sram_2_16_1_scn4m_subm_FF_5p0V_25C_lib){
default_max_fanout : 4.0 ; default_max_fanout : 4.0 ;
default_connection_class : universal ; default_connection_class : universal ;
voltage_map ( VDD, 5.0 );
voltage_map ( GND, 0 );
lu_table_template(CELL_TABLE){ lu_table_template(CELL_TABLE){
variable_1 : input_net_transition; variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance; variable_2 : total_output_net_capacitance;
index_1("0.0125, 0.05, 0.4"); index_1("0.0125, 0.05, 0.4");
index_2("2.45605, 9.8242, 78.5936"); index_2("0.00245605, 0.0098242, 0.0392968");
} }
lu_table_template(CONSTRAINT_TABLE){ lu_table_template(CONSTRAINT_TABLE){
@ -78,17 +81,26 @@ cell (sram_2_16_1_scn4m_subm){
dont_use : true; dont_use : true;
map_only : true; map_only : true;
dont_touch : true; dont_touch : true;
area : 73068.14000000001; area : 0;
pg_pin(vdd) {
voltage_name : VDD;
pg_type : primary_power;
}
pg_pin(gnd) {
voltage_name : GND;
pg_type : primary_ground;
}
leakage_power () { leakage_power () {
when : "csb0"; value : 0.000198;
value : 0.000167;
} }
cell_leakage_power : 0; cell_leakage_power : 0.000198;
bus(din0){ bus(din0){
bus_type : data; bus_type : data;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
memory_write(){ memory_write(){
address : addr0; address : addr0;
clocked_on : clk0; clocked_on : clk0;
@ -127,8 +139,8 @@ cell (sram_2_16_1_scn4m_subm){
bus(dout0){ bus(dout0){
bus_type : data; bus_type : data;
direction : output; direction : output;
max_capacitance : 78.5936; max_capacitance : 0.0392968;
min_capacitance : 2.45605; min_capacitance : 0.00245605;
memory_read(){ memory_read(){
address : addr0; address : addr0;
} }
@ -138,24 +150,24 @@ cell (sram_2_16_1_scn4m_subm){
related_pin : "clk0"; related_pin : "clk0";
timing_type : falling_edge; timing_type : falling_edge;
cell_rise(CELL_TABLE) { cell_rise(CELL_TABLE) {
values("0.241, 0.241, 0.241",\ values("1.183, 1.199, 1.264",\
"0.241, 0.241, 0.241",\ "1.183, 1.199, 1.264",\
"0.241, 0.241, 0.241"); "1.183, 1.199, 1.264");
} }
cell_fall(CELL_TABLE) { cell_fall(CELL_TABLE) {
values("0.241, 0.241, 0.241",\ values("1.183, 1.199, 1.264",\
"0.241, 0.241, 0.241",\ "1.183, 1.199, 1.264",\
"0.241, 0.241, 0.241"); "1.183, 1.199, 1.264");
} }
rise_transition(CELL_TABLE) { rise_transition(CELL_TABLE) {
values("0.004, 0.004, 0.004",\ values("0.006, 0.007, 0.014",\
"0.004, 0.004, 0.004",\ "0.006, 0.007, 0.014",\
"0.004, 0.004, 0.004"); "0.006, 0.007, 0.014");
} }
fall_transition(CELL_TABLE) { fall_transition(CELL_TABLE) {
values("0.004, 0.004, 0.004",\ values("0.006, 0.007, 0.014",\
"0.004, 0.004, 0.004",\ "0.006, 0.007, 0.014",\
"0.004, 0.004, 0.004"); "0.006, 0.007, 0.014");
} }
} }
} }
@ -164,7 +176,7 @@ cell (sram_2_16_1_scn4m_subm){
bus(addr0){ bus(addr0){
bus_type : addr; bus_type : addr;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
max_transition : 0.4; max_transition : 0.4;
pin(addr0[3:0]){ pin(addr0[3:0]){
timing(){ timing(){
@ -200,7 +212,7 @@ cell (sram_2_16_1_scn4m_subm){
pin(csb0){ pin(csb0){
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
@ -233,7 +245,7 @@ cell (sram_2_16_1_scn4m_subm){
pin(web0){ pin(web0){
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
@ -267,52 +279,61 @@ cell (sram_2_16_1_scn4m_subm){
pin(clk0){ pin(clk0){
clock : true; clock : true;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
internal_power(){ internal_power(){
when : "!csb0 & clk0 & !web0"; when : "!csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("4.99880645"); values("7.797263e+00");
} }
fall_power(scalar){ fall_power(scalar){
values("4.99880645"); values("7.797263e+00");
} }
} }
internal_power(){ internal_power(){
when : "!csb0 & !clk0 & web0"; when : "csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("4.99880645"); values("7.797263e+00");
} }
fall_power(scalar){ fall_power(scalar){
values("4.99880645"); values("7.797263e+00");
} }
} }
internal_power(){ internal_power(){
when : "csb0"; when : "!csb0 & web0";
rise_power(scalar){ rise_power(scalar){
values("0"); values("7.797263e+00");
} }
fall_power(scalar){ fall_power(scalar){
values("0"); values("7.797263e+00");
}
}
internal_power(){
when : "csb0 & web0";
rise_power(scalar){
values("7.797263e+00");
}
fall_power(scalar){
values("7.797263e+00");
} }
} }
timing(){ timing(){
timing_type :"min_pulse_width"; timing_type :"min_pulse_width";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.024"); values("0.1265");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.024"); values("0.1265");
} }
} }
timing(){ timing(){
timing_type :"minimum_period"; timing_type :"minimum_period";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.048"); values("0.253");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.048"); values("0.253");
} }
} }
} }

View File

@ -35,11 +35,14 @@ library (sram_2_16_1_scn4m_subm_SS_5p0V_25C_lib){
default_max_fanout : 4.0 ; default_max_fanout : 4.0 ;
default_connection_class : universal ; default_connection_class : universal ;
voltage_map ( VDD, 5.0 );
voltage_map ( GND, 0 );
lu_table_template(CELL_TABLE){ lu_table_template(CELL_TABLE){
variable_1 : input_net_transition; variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance; variable_2 : total_output_net_capacitance;
index_1("0.0125, 0.05, 0.4"); index_1("0.0125, 0.05, 0.4");
index_2("2.45605, 9.8242, 78.5936"); index_2("0.00245605, 0.0098242, 0.0392968");
} }
lu_table_template(CONSTRAINT_TABLE){ lu_table_template(CONSTRAINT_TABLE){
@ -78,17 +81,26 @@ cell (sram_2_16_1_scn4m_subm){
dont_use : true; dont_use : true;
map_only : true; map_only : true;
dont_touch : true; dont_touch : true;
area : 73068.14000000001; area : 0;
pg_pin(vdd) {
voltage_name : VDD;
pg_type : primary_power;
}
pg_pin(gnd) {
voltage_name : GND;
pg_type : primary_ground;
}
leakage_power () { leakage_power () {
when : "csb0"; value : 0.000198;
value : 0.000167;
} }
cell_leakage_power : 0; cell_leakage_power : 0.000198;
bus(din0){ bus(din0){
bus_type : data; bus_type : data;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
memory_write(){ memory_write(){
address : addr0; address : addr0;
clocked_on : clk0; clocked_on : clk0;
@ -127,8 +139,8 @@ cell (sram_2_16_1_scn4m_subm){
bus(dout0){ bus(dout0){
bus_type : data; bus_type : data;
direction : output; direction : output;
max_capacitance : 78.5936; max_capacitance : 0.0392968;
min_capacitance : 2.45605; min_capacitance : 0.00245605;
memory_read(){ memory_read(){
address : addr0; address : addr0;
} }
@ -138,24 +150,24 @@ cell (sram_2_16_1_scn4m_subm){
related_pin : "clk0"; related_pin : "clk0";
timing_type : falling_edge; timing_type : falling_edge;
cell_rise(CELL_TABLE) { cell_rise(CELL_TABLE) {
values("0.294, 0.294, 0.294",\ values("1.446, 1.466, 1.545",\
"0.294, 0.294, 0.294",\ "1.446, 1.466, 1.545",\
"0.294, 0.294, 0.294"); "1.446, 1.466, 1.545");
} }
cell_fall(CELL_TABLE) { cell_fall(CELL_TABLE) {
values("0.294, 0.294, 0.294",\ values("1.446, 1.466, 1.545",\
"0.294, 0.294, 0.294",\ "1.446, 1.466, 1.545",\
"0.294, 0.294, 0.294"); "1.446, 1.466, 1.545");
} }
rise_transition(CELL_TABLE) { rise_transition(CELL_TABLE) {
values("0.004, 0.004, 0.004",\ values("0.007, 0.009, 0.017",\
"0.004, 0.004, 0.004",\ "0.007, 0.009, 0.017",\
"0.004, 0.004, 0.004"); "0.007, 0.009, 0.017");
} }
fall_transition(CELL_TABLE) { fall_transition(CELL_TABLE) {
values("0.004, 0.004, 0.004",\ values("0.007, 0.009, 0.017",\
"0.004, 0.004, 0.004",\ "0.007, 0.009, 0.017",\
"0.004, 0.004, 0.004"); "0.007, 0.009, 0.017");
} }
} }
} }
@ -164,7 +176,7 @@ cell (sram_2_16_1_scn4m_subm){
bus(addr0){ bus(addr0){
bus_type : addr; bus_type : addr;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
max_transition : 0.4; max_transition : 0.4;
pin(addr0[3:0]){ pin(addr0[3:0]){
timing(){ timing(){
@ -200,7 +212,7 @@ cell (sram_2_16_1_scn4m_subm){
pin(csb0){ pin(csb0){
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
@ -233,7 +245,7 @@ cell (sram_2_16_1_scn4m_subm){
pin(web0){ pin(web0){
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
@ -267,52 +279,61 @@ cell (sram_2_16_1_scn4m_subm){
pin(clk0){ pin(clk0){
clock : true; clock : true;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
internal_power(){ internal_power(){
when : "!csb0 & clk0 & !web0"; when : "!csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("4.99880645"); values("6.379579e+00");
} }
fall_power(scalar){ fall_power(scalar){
values("4.99880645"); values("6.379579e+00");
} }
} }
internal_power(){ internal_power(){
when : "!csb0 & !clk0 & web0"; when : "csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("4.99880645"); values("6.379579e+00");
} }
fall_power(scalar){ fall_power(scalar){
values("4.99880645"); values("6.379579e+00");
} }
} }
internal_power(){ internal_power(){
when : "csb0"; when : "!csb0 & web0";
rise_power(scalar){ rise_power(scalar){
values("0"); values("6.379579e+00");
} }
fall_power(scalar){ fall_power(scalar){
values("0"); values("6.379579e+00");
}
}
internal_power(){
when : "csb0 & web0";
rise_power(scalar){
values("6.379579e+00");
}
fall_power(scalar){
values("6.379579e+00");
} }
} }
timing(){ timing(){
timing_type :"min_pulse_width"; timing_type :"min_pulse_width";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.0295"); values("0.1545");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.0295"); values("0.1545");
} }
} }
timing(){ timing(){
timing_type :"minimum_period"; timing_type :"minimum_period";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.059"); values("0.309");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.059"); values("0.309");
} }
} }
} }

View File

@ -35,11 +35,14 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){
default_max_fanout : 4.0 ; default_max_fanout : 4.0 ;
default_connection_class : universal ; default_connection_class : universal ;
voltage_map ( VDD, 5.0 );
voltage_map ( GND, 0 );
lu_table_template(CELL_TABLE){ lu_table_template(CELL_TABLE){
variable_1 : input_net_transition; variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance; variable_2 : total_output_net_capacitance;
index_1("0.0125, 0.05, 0.4"); index_1("0.0125, 0.05, 0.4");
index_2("2.45605, 9.8242, 78.5936"); index_2("0.00245605, 0.0098242, 0.0392968");
} }
lu_table_template(CONSTRAINT_TABLE){ lu_table_template(CONSTRAINT_TABLE){
@ -78,17 +81,26 @@ cell (sram_2_16_1_scn4m_subm){
dont_use : true; dont_use : true;
map_only : true; map_only : true;
dont_touch : true; dont_touch : true;
area : 60774.3; area : 0;
pg_pin(vdd) {
voltage_name : VDD;
pg_type : primary_power;
}
pg_pin(gnd) {
voltage_name : GND;
pg_type : primary_ground;
}
leakage_power () { leakage_power () {
when : "csb0"; value : 0.000198;
value : 0.0009813788999999999;
} }
cell_leakage_power : 0; cell_leakage_power : 0.000198;
bus(din0){ bus(din0){
bus_type : data; bus_type : data;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
memory_write(){ memory_write(){
address : addr0; address : addr0;
clocked_on : clk0; clocked_on : clk0;
@ -98,28 +110,28 @@ cell (sram_2_16_1_scn4m_subm){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("0.167, 0.167, 0.228",\ values("0.009, 0.009, 0.009",\
"0.167, 0.167, 0.228",\ "0.009, 0.009, 0.009",\
"0.167, 0.167, 0.228"); "0.009, 0.009, 0.009");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("0.131, 0.125, 0.137",\ values("0.009, 0.009, 0.009",\
"0.131, 0.125, 0.137",\ "0.009, 0.009, 0.009",\
"0.131, 0.125, 0.137"); "0.009, 0.009, 0.009");
} }
} }
timing(){ timing(){
timing_type : hold_rising; timing_type : hold_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("-0.065, -0.071, -0.114",\ values("0.001, 0.001, 0.001",\
"-0.065, -0.071, -0.114",\ "0.001, 0.001, 0.001",\
"-0.065, -0.071, -0.114"); "0.001, 0.001, 0.001");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("-0.089, -0.089, -0.089",\ values("0.001, 0.001, 0.001",\
"-0.089, -0.089, -0.089",\ "0.001, 0.001, 0.001",\
"-0.089, -0.089, -0.089"); "0.001, 0.001, 0.001");
} }
} }
} }
@ -127,8 +139,8 @@ cell (sram_2_16_1_scn4m_subm){
bus(dout0){ bus(dout0){
bus_type : data; bus_type : data;
direction : output; direction : output;
max_capacitance : 78.5936; max_capacitance : 0.0392968;
min_capacitance : 2.45605; min_capacitance : 0.00245605;
memory_read(){ memory_read(){
address : addr0; address : addr0;
} }
@ -138,24 +150,24 @@ cell (sram_2_16_1_scn4m_subm){
related_pin : "clk0"; related_pin : "clk0";
timing_type : falling_edge; timing_type : falling_edge;
cell_rise(CELL_TABLE) { cell_rise(CELL_TABLE) {
values("1.556, 1.576, 1.751",\ values("1.314, 1.332, 1.404",\
"1.559, 1.579, 1.754",\ "1.314, 1.332, 1.404",\
"1.624, 1.643, 1.819"); "1.314, 1.332, 1.404");
} }
cell_fall(CELL_TABLE) { cell_fall(CELL_TABLE) {
values("3.445, 3.504, 3.926",\ values("1.314, 1.332, 1.404",\
"3.448, 3.507, 3.93",\ "1.314, 1.332, 1.404",\
"3.49, 3.549, 3.972"); "1.314, 1.332, 1.404");
} }
rise_transition(CELL_TABLE) { rise_transition(CELL_TABLE) {
values("0.13, 0.169, 0.574",\ values("0.006, 0.008, 0.015",\
"0.13, 0.169, 0.574",\ "0.006, 0.008, 0.015",\
"0.13, 0.169, 0.574"); "0.006, 0.008, 0.015");
} }
fall_transition(CELL_TABLE) { fall_transition(CELL_TABLE) {
values("0.467, 0.49, 0.959",\ values("0.006, 0.008, 0.015",\
"0.467, 0.49, 0.959",\ "0.006, 0.008, 0.015",\
"0.47, 0.493, 0.96"); "0.006, 0.008, 0.015");
} }
} }
} }
@ -164,35 +176,35 @@ cell (sram_2_16_1_scn4m_subm){
bus(addr0){ bus(addr0){
bus_type : addr; bus_type : addr;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
max_transition : 0.4; max_transition : 0.4;
pin(addr0[3:0]){ pin(addr0[3:0]){
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("0.167, 0.167, 0.228",\ values("0.009, 0.009, 0.009",\
"0.167, 0.167, 0.228",\ "0.009, 0.009, 0.009",\
"0.167, 0.167, 0.228"); "0.009, 0.009, 0.009");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("0.131, 0.125, 0.137",\ values("0.009, 0.009, 0.009",\
"0.131, 0.125, 0.137",\ "0.009, 0.009, 0.009",\
"0.131, 0.125, 0.137"); "0.009, 0.009, 0.009");
} }
} }
timing(){ timing(){
timing_type : hold_rising; timing_type : hold_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("-0.065, -0.071, -0.114",\ values("0.001, 0.001, 0.001",\
"-0.065, -0.071, -0.114",\ "0.001, 0.001, 0.001",\
"-0.065, -0.071, -0.114"); "0.001, 0.001, 0.001");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("-0.089, -0.089, -0.089",\ values("0.001, 0.001, 0.001",\
"-0.089, -0.089, -0.089",\ "0.001, 0.001, 0.001",\
"-0.089, -0.089, -0.089"); "0.001, 0.001, 0.001");
} }
} }
} }
@ -200,66 +212,66 @@ cell (sram_2_16_1_scn4m_subm){
pin(csb0){ pin(csb0){
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("0.167, 0.167, 0.228",\ values("0.009, 0.009, 0.009",\
"0.167, 0.167, 0.228",\ "0.009, 0.009, 0.009",\
"0.167, 0.167, 0.228"); "0.009, 0.009, 0.009");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("0.131, 0.125, 0.137",\ values("0.009, 0.009, 0.009",\
"0.131, 0.125, 0.137",\ "0.009, 0.009, 0.009",\
"0.131, 0.125, 0.137"); "0.009, 0.009, 0.009");
} }
} }
timing(){ timing(){
timing_type : hold_rising; timing_type : hold_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("-0.065, -0.071, -0.114",\ values("0.001, 0.001, 0.001",\
"-0.065, -0.071, -0.114",\ "0.001, 0.001, 0.001",\
"-0.065, -0.071, -0.114"); "0.001, 0.001, 0.001");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("-0.089, -0.089, -0.089",\ values("0.001, 0.001, 0.001",\
"-0.089, -0.089, -0.089",\ "0.001, 0.001, 0.001",\
"-0.089, -0.089, -0.089"); "0.001, 0.001, 0.001");
} }
} }
} }
pin(web0){ pin(web0){
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("0.167, 0.167, 0.228",\ values("0.009, 0.009, 0.009",\
"0.167, 0.167, 0.228",\ "0.009, 0.009, 0.009",\
"0.167, 0.167, 0.228"); "0.009, 0.009, 0.009");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("0.131, 0.125, 0.137",\ values("0.009, 0.009, 0.009",\
"0.131, 0.125, 0.137",\ "0.009, 0.009, 0.009",\
"0.131, 0.125, 0.137"); "0.009, 0.009, 0.009");
} }
} }
timing(){ timing(){
timing_type : hold_rising; timing_type : hold_rising;
related_pin : "clk0"; related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) { rise_constraint(CONSTRAINT_TABLE) {
values("-0.065, -0.071, -0.114",\ values("0.001, 0.001, 0.001",\
"-0.065, -0.071, -0.114",\ "0.001, 0.001, 0.001",\
"-0.065, -0.071, -0.114"); "0.001, 0.001, 0.001");
} }
fall_constraint(CONSTRAINT_TABLE) { fall_constraint(CONSTRAINT_TABLE) {
values("-0.089, -0.089, -0.089",\ values("0.001, 0.001, 0.001",\
"-0.089, -0.089, -0.089",\ "0.001, 0.001, 0.001",\
"-0.089, -0.089, -0.089"); "0.001, 0.001, 0.001");
} }
} }
} }
@ -267,52 +279,61 @@ cell (sram_2_16_1_scn4m_subm){
pin(clk0){ pin(clk0){
clock : true; clock : true;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
internal_power(){ internal_power(){
when : "!csb0 & clk0 & !web0"; when : "!csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("9.972790277777777"); values("7.017537e+00");
} }
fall_power(scalar){ fall_power(scalar){
values("9.972790277777777"); values("7.017537e+00");
} }
} }
internal_power(){ internal_power(){
when : "!csb0 & !clk0 & web0"; when : "csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("8.899322499999998"); values("7.017537e+00");
} }
fall_power(scalar){ fall_power(scalar){
values("8.899322499999998"); values("7.017537e+00");
} }
} }
internal_power(){ internal_power(){
when : "csb0"; when : "!csb0 & web0";
rise_power(scalar){ rise_power(scalar){
values("0"); values("7.017537e+00");
} }
fall_power(scalar){ fall_power(scalar){
values("0"); values("7.017537e+00");
}
}
internal_power(){
when : "csb0 & web0";
rise_power(scalar){
values("7.017537e+00");
}
fall_power(scalar){
values("7.017537e+00");
} }
} }
timing(){ timing(){
timing_type :"min_pulse_width"; timing_type :"min_pulse_width";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("2.344"); values("0.1405");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("2.344"); values("0.1405");
} }
} }
timing(){ timing(){
timing_type :"minimum_period"; timing_type :"minimum_period";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("4.688"); values("0.281");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("4.688"); values("0.281");
} }
} }
} }

View File

@ -35,11 +35,14 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){
default_max_fanout : 4.0 ; default_max_fanout : 4.0 ;
default_connection_class : universal ; default_connection_class : universal ;
voltage_map ( VDD, 5.0 );
voltage_map ( GND, 0 );
lu_table_template(CELL_TABLE){ lu_table_template(CELL_TABLE){
variable_1 : input_net_transition; variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance; variable_2 : total_output_net_capacitance;
index_1("0.0125, 0.05, 0.4"); index_1("0.0125, 0.05, 0.4");
index_2("2.45605, 9.8242, 78.5936"); index_2("0.00245605, 0.0098242, 0.0392968");
} }
lu_table_template(CONSTRAINT_TABLE){ lu_table_template(CONSTRAINT_TABLE){
@ -78,17 +81,26 @@ cell (sram_2_16_1_scn4m_subm){
dont_use : true; dont_use : true;
map_only : true; map_only : true;
dont_touch : true; dont_touch : true;
area : 60774.3; area : 0;
pg_pin(vdd) {
voltage_name : VDD;
pg_type : primary_power;
}
pg_pin(gnd) {
voltage_name : GND;
pg_type : primary_ground;
}
leakage_power () { leakage_power () {
when : "csb0"; value : 0.000198;
value : 0.000179;
} }
cell_leakage_power : 0; cell_leakage_power : 0.000198;
bus(din0){ bus(din0){
bus_type : data; bus_type : data;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
memory_write(){ memory_write(){
address : addr0; address : addr0;
clocked_on : clk0; clocked_on : clk0;
@ -127,8 +139,8 @@ cell (sram_2_16_1_scn4m_subm){
bus(dout0){ bus(dout0){
bus_type : data; bus_type : data;
direction : output; direction : output;
max_capacitance : 78.5936; max_capacitance : 0.0392968;
min_capacitance : 2.45605; min_capacitance : 0.00245605;
memory_read(){ memory_read(){
address : addr0; address : addr0;
} }
@ -138,24 +150,24 @@ cell (sram_2_16_1_scn4m_subm){
related_pin : "clk0"; related_pin : "clk0";
timing_type : falling_edge; timing_type : falling_edge;
cell_rise(CELL_TABLE) { cell_rise(CELL_TABLE) {
values("0.268, 0.268, 0.268",\ values("1.314, 1.332, 1.404",\
"0.268, 0.268, 0.268",\ "1.314, 1.332, 1.404",\
"0.268, 0.268, 0.268"); "1.314, 1.332, 1.404");
} }
cell_fall(CELL_TABLE) { cell_fall(CELL_TABLE) {
values("0.268, 0.268, 0.268",\ values("1.314, 1.332, 1.404",\
"0.268, 0.268, 0.268",\ "1.314, 1.332, 1.404",\
"0.268, 0.268, 0.268"); "1.314, 1.332, 1.404");
} }
rise_transition(CELL_TABLE) { rise_transition(CELL_TABLE) {
values("0.004, 0.004, 0.004",\ values("0.006, 0.008, 0.015",\
"0.004, 0.004, 0.004",\ "0.006, 0.008, 0.015",\
"0.004, 0.004, 0.004"); "0.006, 0.008, 0.015");
} }
fall_transition(CELL_TABLE) { fall_transition(CELL_TABLE) {
values("0.004, 0.004, 0.004",\ values("0.006, 0.008, 0.015",\
"0.004, 0.004, 0.004",\ "0.006, 0.008, 0.015",\
"0.004, 0.004, 0.004"); "0.006, 0.008, 0.015");
} }
} }
} }
@ -164,7 +176,7 @@ cell (sram_2_16_1_scn4m_subm){
bus(addr0){ bus(addr0){
bus_type : addr; bus_type : addr;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
max_transition : 0.4; max_transition : 0.4;
pin(addr0[3:0]){ pin(addr0[3:0]){
timing(){ timing(){
@ -200,7 +212,7 @@ cell (sram_2_16_1_scn4m_subm){
pin(csb0){ pin(csb0){
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
@ -233,7 +245,7 @@ cell (sram_2_16_1_scn4m_subm){
pin(web0){ pin(web0){
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk0"; related_pin : "clk0";
@ -267,52 +279,61 @@ cell (sram_2_16_1_scn4m_subm){
pin(clk0){ pin(clk0){
clock : true; clock : true;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 0.0098242;
internal_power(){ internal_power(){
when : "!csb0 & clk0 & !web0"; when : "!csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("11.3049604371"); values("7.017537e+00");
} }
fall_power(scalar){ fall_power(scalar){
values("11.3049604371"); values("7.017537e+00");
} }
} }
internal_power(){ internal_power(){
when : "!csb0 & !clk0 & web0"; when : "csb0 & !web0";
rise_power(scalar){ rise_power(scalar){
values("11.3049604371"); values("7.017537e+00");
} }
fall_power(scalar){ fall_power(scalar){
values("11.3049604371"); values("7.017537e+00");
} }
} }
internal_power(){ internal_power(){
when : "csb0"; when : "!csb0 & web0";
rise_power(scalar){ rise_power(scalar){
values("0"); values("7.017537e+00");
} }
fall_power(scalar){ fall_power(scalar){
values("0"); values("7.017537e+00");
}
}
internal_power(){
when : "csb0 & web0";
rise_power(scalar){
values("7.017537e+00");
}
fall_power(scalar){
values("7.017537e+00");
} }
} }
timing(){ timing(){
timing_type :"min_pulse_width"; timing_type :"min_pulse_width";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.0"); values("0.1405");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.0"); values("0.1405");
} }
} }
timing(){ timing(){
timing_type :"minimum_period"; timing_type :"minimum_period";
related_pin : clk0; related_pin : clk0;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0"); values("0.281");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0"); values("0.281");
} }
} }
} }

View File

@ -51,9 +51,9 @@ class openram_test(unittest.TestCase):
drc_result=verify.run_drc(a.name, tempgds, extract=True, final_verification=final_verification) drc_result=verify.run_drc(a.name, tempgds, extract=True, final_verification=final_verification)
# Always run LVS if we are using magic # Always run LVS if we are using magic
if "magic" in OPTS.drc_exe: if "magic" in OPTS.drc_exe or drc_result == 0:
lvs_result=verify.run_lvs(a.name, tempgds, tempspice, final_verification=final_verification) lvs_result=verify.run_lvs(a.name, tempgds, tempspice, final_verification=final_verification)
# Only allow DRC to fail and LVS to pass if we are using magic # Only allow DRC to fail and LVS to pass if we are using magic
if "magic" in OPTS.drc_exe and lvs_result == 0 and drc_result != 0: if "magic" in OPTS.drc_exe and lvs_result == 0 and drc_result != 0:
#zip_file = "/tmp/{0}_{1}".format(a.name,os.getpid()) #zip_file = "/tmp/{0}_{1}".format(a.name,os.getpid())

View File

@ -89,7 +89,7 @@ power_grid = m3_stack
################################################### ###################################################
# create the GDS layer map # create the GDS layer map
layer={} layer={}
layer["pwell"] = (41, 0) layer["pwell"] = (41, 0)
layer["nwell"] = (42, 0) layer["nwell"] = (42, 0)
layer["active"] = (43, 0) layer["active"] = (43, 0)
@ -98,9 +98,9 @@ layer["nimplant"] = (45, 0)
layer["poly"] = (46, 0) layer["poly"] = (46, 0)
layer["poly_contact"] = (47, 0) layer["poly_contact"] = (47, 0)
layer["active_contact"] = (48, 0) layer["active_contact"] = (48, 0)
layer["m1"] = (49, 0) layer["m1"] = (49, 0)
layer["via1"] = (50, 0) layer["via1"] = (50, 0)
layer["m2"] = (51, 0) layer["m2"] = (51, 0)
layer["via2"] = (61, 0) layer["via2"] = (61, 0)
layer["m3"] = (62, 0) layer["m3"] = (62, 0)
layer["via3"] = (30, 0) layer["via3"] = (30, 0)