mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into discrete_models
This commit is contained in:
commit
5666e79287
|
|
@ -8,3 +8,5 @@
|
||||||
*.toc
|
*.toc
|
||||||
*.synctex.gz
|
*.synctex.gz
|
||||||
**/model_data
|
**/model_data
|
||||||
|
outputs
|
||||||
|
technology/freepdk45/ncsu_basekit
|
||||||
|
|
|
||||||
|
|
@ -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) + " )"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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"]
|
||||||
|
|
|
||||||
|
|
@ -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"""
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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}",
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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 """
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"]
|
||||||
|
|
|
||||||
|
|
@ -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. """
|
||||||
|
|
|
||||||
|
|
@ -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 """
|
||||||
|
|
|
||||||
|
|
@ -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"])
|
||||||
|
|
|
||||||
|
|
@ -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 """
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
@ -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__":
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
@ -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())
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue