mirror of https://github.com/VLSIDA/OpenRAM.git
merge conflict 2 - port data
This commit is contained in:
commit
84021c9ccb
|
|
@ -450,7 +450,7 @@ class layout():
|
||||||
path=coordinates,
|
path=coordinates,
|
||||||
layer_widths=layer_widths)
|
layer_widths=layer_widths)
|
||||||
|
|
||||||
def add_zjog(self, layer, start, end, first_direction="H"):
|
def add_zjog(self, layer, start, end, first_direction="H", fixed_offset=None):
|
||||||
"""
|
"""
|
||||||
Add a simple jog at the halfway point.
|
Add a simple jog at the halfway point.
|
||||||
If layer is a single value, it is a path.
|
If layer is a single value, it is a path.
|
||||||
|
|
@ -459,11 +459,17 @@ class layout():
|
||||||
|
|
||||||
# vertical first
|
# vertical first
|
||||||
if first_direction == "V":
|
if first_direction == "V":
|
||||||
mid1 = vector(start.x, 0.5 * start.y + 0.5 * end.y)
|
if fixed_offset:
|
||||||
|
mid1 = vector(start.x, fixed_offset)
|
||||||
|
else:
|
||||||
|
mid1 = vector(start.x, 0.5 * start.y + 0.5 * end.y)
|
||||||
mid2 = vector(end.x, mid1.y)
|
mid2 = vector(end.x, mid1.y)
|
||||||
# horizontal first
|
# horizontal first
|
||||||
elif first_direction == "H":
|
elif first_direction == "H":
|
||||||
mid1 = vector(0.5 * start.x + 0.5 * end.x, start.y)
|
if fixed_offset:
|
||||||
|
mid1 = vector(fixed_offset, start.y)
|
||||||
|
else:
|
||||||
|
mid1 = vector(0.5 * start.x + 0.5 * end.x, start.y)
|
||||||
mid2 = vector(mid1, end.y)
|
mid2 = vector(mid1, end.y)
|
||||||
else:
|
else:
|
||||||
debug.error("Invalid direction for jog -- must be H or V.")
|
debug.error("Invalid direction for jog -- must be H or V.")
|
||||||
|
|
|
||||||
|
|
@ -7,22 +7,28 @@
|
||||||
#
|
#
|
||||||
import debug
|
import debug
|
||||||
from vector import vector
|
from vector import vector
|
||||||
import pgate
|
import design
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
|
from tech import layer
|
||||||
|
|
||||||
|
|
||||||
class pand2_dec(pgate.pgate):
|
class and2_dec(design.design):
|
||||||
"""
|
"""
|
||||||
This is an AND with configurable drive strength.
|
This is an AND with configurable drive strength.
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, size=1, height=None, add_wells=True):
|
def __init__(self, name, size=1, height=None, add_wells=True):
|
||||||
debug.info(1, "Creating pand2_dec {}".format(name))
|
|
||||||
|
design.design.__init__(self, name)
|
||||||
|
|
||||||
|
debug.info(1, "Creating and2_dec {}".format(name))
|
||||||
self.add_comment("size: {}".format(size))
|
self.add_comment("size: {}".format(size))
|
||||||
|
|
||||||
self.size = size
|
self.size = size
|
||||||
|
self.height = height
|
||||||
|
|
||||||
pgate.pgate.__init__(self, name, height, add_wells)
|
self.create_netlist()
|
||||||
|
if not OPTS.netlist_only:
|
||||||
|
self.create_layout()
|
||||||
|
|
||||||
def create_netlist(self):
|
def create_netlist(self):
|
||||||
self.add_pins()
|
self.add_pins()
|
||||||
|
|
@ -30,11 +36,8 @@ class pand2_dec(pgate.pgate):
|
||||||
self.create_insts()
|
self.create_insts()
|
||||||
|
|
||||||
def create_modules(self):
|
def create_modules(self):
|
||||||
if OPTS.tech_name == "s8":
|
self.nand = factory.create(module_type="nand2_dec",
|
||||||
self.nand = factory.create(module_type="nand2_dec")
|
height=self.height)
|
||||||
else:
|
|
||||||
self.nand = factory.create(module_type="nand2_dec",
|
|
||||||
height=self.height)
|
|
||||||
|
|
||||||
self.inv = factory.create(module_type="inv_dec",
|
self.inv = factory.create(module_type="inv_dec",
|
||||||
height=self.height,
|
height=self.height,
|
||||||
|
|
@ -44,7 +47,13 @@ class pand2_dec(pgate.pgate):
|
||||||
self.add_mod(self.inv)
|
self.add_mod(self.inv)
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
|
|
||||||
|
if "li" in layer:
|
||||||
|
self.route_layer = "li"
|
||||||
|
else:
|
||||||
|
self.route_layer = "m1"
|
||||||
self.width = self.nand.width + self.inv.width
|
self.width = self.nand.width + self.inv.width
|
||||||
|
self.height = self.nand.height
|
||||||
|
|
||||||
self.place_insts()
|
self.place_insts()
|
||||||
self.add_wires()
|
self.add_wires()
|
||||||
|
|
@ -7,22 +7,26 @@
|
||||||
#
|
#
|
||||||
import debug
|
import debug
|
||||||
from vector import vector
|
from vector import vector
|
||||||
import pgate
|
import design
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
|
from tech import layer
|
||||||
|
|
||||||
|
|
||||||
class pand3_dec(pgate.pgate):
|
class and3_dec(design.design):
|
||||||
"""
|
"""
|
||||||
This is an AND with configurable drive strength.
|
This is an AND with configurable drive strength.
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, size=1, height=None, add_wells=True):
|
def __init__(self, name, size=1, height=None, add_wells=True):
|
||||||
debug.info(1, "Creating pand3_dec {}".format(name))
|
design.design.__init__(self, name)
|
||||||
|
debug.info(1, "Creating and3_dec {}".format(name))
|
||||||
self.add_comment("size: {}".format(size))
|
self.add_comment("size: {}".format(size))
|
||||||
|
|
||||||
self.size = size
|
self.size = size
|
||||||
|
self.height = height
|
||||||
|
|
||||||
pgate.pgate.__init__(self, name, height, add_wells)
|
self.create_netlist()
|
||||||
|
if not OPTS.netlist_only:
|
||||||
|
self.create_layout()
|
||||||
|
|
||||||
def create_netlist(self):
|
def create_netlist(self):
|
||||||
self.add_pins()
|
self.add_pins()
|
||||||
|
|
@ -30,11 +34,8 @@ class pand3_dec(pgate.pgate):
|
||||||
self.create_insts()
|
self.create_insts()
|
||||||
|
|
||||||
def create_modules(self):
|
def create_modules(self):
|
||||||
if OPTS.tech_name == "s8":
|
self.nand = factory.create(module_type="nand3_dec",
|
||||||
self.nand = factory.create(module_type="nand3_dec")
|
height=self.height)
|
||||||
else:
|
|
||||||
self.nand = factory.create(module_type="nand3_dec",
|
|
||||||
height=self.height)
|
|
||||||
|
|
||||||
self.inv = factory.create(module_type="inv_dec",
|
self.inv = factory.create(module_type="inv_dec",
|
||||||
height=self.height,
|
height=self.height,
|
||||||
|
|
@ -44,7 +45,13 @@ class pand3_dec(pgate.pgate):
|
||||||
self.add_mod(self.inv)
|
self.add_mod(self.inv)
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
|
if "li" in layer:
|
||||||
|
self.route_layer = "li"
|
||||||
|
else:
|
||||||
|
self.route_layer = "m1"
|
||||||
|
|
||||||
self.width = self.nand.width + self.inv.width
|
self.width = self.nand.width + self.inv.width
|
||||||
|
self.height = self.nand.height
|
||||||
|
|
||||||
self.place_insts()
|
self.place_insts()
|
||||||
self.add_wires()
|
self.add_wires()
|
||||||
|
|
@ -7,22 +7,28 @@
|
||||||
#
|
#
|
||||||
import debug
|
import debug
|
||||||
from vector import vector
|
from vector import vector
|
||||||
import pgate
|
import design
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
|
from tech import layer
|
||||||
|
|
||||||
|
|
||||||
class pand4_dec(pgate.pgate):
|
class and4_dec(design.design):
|
||||||
"""
|
"""
|
||||||
This is an AND with configurable drive strength.
|
This is an AND with configurable drive strength.
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, size=1, height=None, add_wells=True):
|
def __init__(self, name, size=1, height=None, add_wells=True):
|
||||||
debug.info(1, "Creating pand4_dec {}".format(name))
|
|
||||||
|
design.design.__init__(self, name)
|
||||||
|
|
||||||
|
debug.info(1, "Creating and4_dec {}".format(name))
|
||||||
self.add_comment("size: {}".format(size))
|
self.add_comment("size: {}".format(size))
|
||||||
|
|
||||||
self.size = size
|
self.size = size
|
||||||
|
self.height = height
|
||||||
|
|
||||||
pgate.pgate.__init__(self, name, height, add_wells)
|
self.create_netlist()
|
||||||
|
if not OPTS.netlist_only:
|
||||||
|
self.create_layout()
|
||||||
|
|
||||||
def create_netlist(self):
|
def create_netlist(self):
|
||||||
self.add_pins()
|
self.add_pins()
|
||||||
|
|
@ -30,20 +36,24 @@ class pand4_dec(pgate.pgate):
|
||||||
self.create_insts()
|
self.create_insts()
|
||||||
|
|
||||||
def create_modules(self):
|
def create_modules(self):
|
||||||
if OPTS.tech_name == "s8":
|
self.nand = factory.create(module_type="nand4_dec",
|
||||||
self.nand = factory.create(module_type="nand4_dec")
|
height=self.height)
|
||||||
else:
|
|
||||||
self.nand = factory.create(module_type="nand4_dec",
|
|
||||||
height=self.height)
|
|
||||||
|
|
||||||
self.inv = factory.create(module_type="inv_dec",
|
self.inv = factory.create(module_type="inv_dec",
|
||||||
|
height=self.height,
|
||||||
size=self.size)
|
size=self.size)
|
||||||
|
|
||||||
self.add_mod(self.nand)
|
self.add_mod(self.nand)
|
||||||
self.add_mod(self.inv)
|
self.add_mod(self.inv)
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
|
if "li" in layer:
|
||||||
|
self.route_layer = "li"
|
||||||
|
else:
|
||||||
|
self.route_layer = "m1"
|
||||||
|
|
||||||
self.width = self.nand.width + self.inv.width
|
self.width = self.nand.width + self.inv.width
|
||||||
|
self.height = self.nand.height
|
||||||
|
|
||||||
self.place_insts()
|
self.place_insts()
|
||||||
self.add_wires()
|
self.add_wires()
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
import design
|
import design
|
||||||
from tech import GDS, layer, spice, parameter
|
from tech import GDS, layer, spice, parameter, drc
|
||||||
import logical_effort
|
import logical_effort
|
||||||
import utils
|
import utils
|
||||||
|
|
||||||
|
|
@ -32,6 +32,14 @@ class nand2_dec(design.design):
|
||||||
self.pin_map = nand2_dec.pin_map
|
self.pin_map = nand2_dec.pin_map
|
||||||
self.add_pin_types(self.type_list)
|
self.add_pin_types(self.type_list)
|
||||||
|
|
||||||
|
# FIXME: For now...
|
||||||
|
size = 1
|
||||||
|
self.size = size
|
||||||
|
self.nmos_size = 2 * size
|
||||||
|
self.pmos_size = parameter["beta"] * size
|
||||||
|
self.nmos_width = self.nmos_size * drc("minwidth_tx")
|
||||||
|
self.pmos_width = self.pmos_size * drc("minwidth_tx")
|
||||||
|
|
||||||
def analytical_power(self, corner, load):
|
def analytical_power(self, corner, load):
|
||||||
"""Returns dynamic and leakage power. Results in nW"""
|
"""Returns dynamic and leakage power. Results in nW"""
|
||||||
c_eff = self.calculate_effective_capacitance(load)
|
c_eff = self.calculate_effective_capacitance(load)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
import design
|
import design
|
||||||
from tech import GDS, layer, spice, parameter
|
from tech import GDS, layer, spice, parameter, drc
|
||||||
import logical_effort
|
import logical_effort
|
||||||
import utils
|
import utils
|
||||||
|
|
||||||
|
|
@ -32,6 +32,14 @@ class nand3_dec(design.design):
|
||||||
self.pin_map = nand3_dec.pin_map
|
self.pin_map = nand3_dec.pin_map
|
||||||
self.add_pin_types(self.type_list)
|
self.add_pin_types(self.type_list)
|
||||||
|
|
||||||
|
# FIXME: For now...
|
||||||
|
size = 1
|
||||||
|
self.size = size
|
||||||
|
self.nmos_size = 2 * size
|
||||||
|
self.pmos_size = parameter["beta"] * size
|
||||||
|
self.nmos_width = self.nmos_size * drc("minwidth_tx")
|
||||||
|
self.pmos_width = self.pmos_size * drc("minwidth_tx")
|
||||||
|
|
||||||
def analytical_power(self, corner, load):
|
def analytical_power(self, corner, load):
|
||||||
"""Returns dynamic and leakage power. Results in nW"""
|
"""Returns dynamic and leakage power. Results in nW"""
|
||||||
c_eff = self.calculate_effective_capacitance(load)
|
c_eff = self.calculate_effective_capacitance(load)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
import design
|
import design
|
||||||
from tech import GDS, layer, spice, parameter
|
from tech import GDS, layer, spice, parameter, drc
|
||||||
import logical_effort
|
import logical_effort
|
||||||
import utils
|
import utils
|
||||||
|
|
||||||
|
|
@ -32,6 +32,14 @@ class nand4_dec(design.design):
|
||||||
self.pin_map = nand4_dec.pin_map
|
self.pin_map = nand4_dec.pin_map
|
||||||
self.add_pin_types(self.type_list)
|
self.add_pin_types(self.type_list)
|
||||||
|
|
||||||
|
# FIXME: For now...
|
||||||
|
size = 1
|
||||||
|
self.size = size
|
||||||
|
self.nmos_size = 2 * size
|
||||||
|
self.pmos_size = parameter["beta"] * size
|
||||||
|
self.nmos_width = self.nmos_size * drc("minwidth_tx")
|
||||||
|
self.pmos_width = self.pmos_size * drc("minwidth_tx")
|
||||||
|
|
||||||
def analytical_power(self, corner, load):
|
def analytical_power(self, corner, load):
|
||||||
"""Returns dynamic and leakage power. Results in nW"""
|
"""Returns dynamic and leakage power. Results in nW"""
|
||||||
c_eff = self.calculate_effective_capacitance(load)
|
c_eff = self.calculate_effective_capacitance(load)
|
||||||
|
|
|
||||||
|
|
@ -57,21 +57,15 @@ class hierarchical_decoder(design.design):
|
||||||
self.DRC_LVS()
|
self.DRC_LVS()
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
if OPTS.tech_name == "s8":
|
self.and2 = factory.create(module_type="and2_dec",
|
||||||
self.and2 = factory.create(module_type="pand2_dec")
|
height=self.cell_height)
|
||||||
else:
|
|
||||||
self.and2 = factory.create(module_type="pand2_dec",
|
|
||||||
height=self.cell_height)
|
|
||||||
self.add_mod(self.and2)
|
self.add_mod(self.and2)
|
||||||
if OPTS.tech_name == "s8":
|
|
||||||
self.and3 = factory.create(module_type="pand3_dec")
|
|
||||||
else:
|
|
||||||
self.and3 = factory.create(module_type="pand3_dec",
|
|
||||||
height=self.cell_height)
|
|
||||||
|
|
||||||
|
self.and3 = factory.create(module_type="and3_dec",
|
||||||
|
height=self.cell_height)
|
||||||
self.add_mod(self.and3)
|
self.add_mod(self.and3)
|
||||||
# TBD
|
# TBD
|
||||||
# self.and4 = factory.create(module_type="pand4_dec")
|
# self.and4 = factory.create(module_type="and4_dec")
|
||||||
# self.add_mod(self.and4)
|
# self.add_mod(self.and4)
|
||||||
|
|
||||||
self.add_decoders()
|
self.add_decoders()
|
||||||
|
|
@ -180,6 +174,7 @@ class hierarchical_decoder(design.design):
|
||||||
# Two extra pitches between modules on left and right
|
# Two extra pitches between modules on left and right
|
||||||
self.internal_routing_width = self.total_number_of_predecoder_outputs * self.bus_pitch + self.bus_pitch
|
self.internal_routing_width = self.total_number_of_predecoder_outputs * self.bus_pitch + self.bus_pitch
|
||||||
self.row_decoder_height = self.and2.height * self.num_outputs
|
self.row_decoder_height = self.and2.height * self.num_outputs
|
||||||
|
|
||||||
# Extra bus space for supply contacts
|
# Extra bus space for supply contacts
|
||||||
self.input_routing_width = self.num_inputs * self.bus_pitch + self.bus_space
|
self.input_routing_width = self.num_inputs * self.bus_pitch + self.bus_space
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,13 @@ class hierarchical_predecode(design.design):
|
||||||
|
|
||||||
# FIXME: Default parms are required for hard cells for now.
|
# FIXME: Default parms are required for hard cells for now.
|
||||||
if self.number_of_inputs == 2:
|
if self.number_of_inputs == 2:
|
||||||
self.and_mod = factory.create(module_type="pand2_dec",
|
self.and_mod = factory.create(module_type="and2_dec",
|
||||||
height=self.cell_height)
|
height=self.cell_height)
|
||||||
elif self.number_of_inputs == 3:
|
elif self.number_of_inputs == 3:
|
||||||
self.and_mod = factory.create(module_type="pand3_dec",
|
self.and_mod = factory.create(module_type="and3_dec",
|
||||||
height=self.cell_height)
|
height=self.cell_height)
|
||||||
elif self.number_of_inputs == 4:
|
elif self.number_of_inputs == 4:
|
||||||
self.and_mod = factory.create(module_type="pand4_dec",
|
self.and_mod = factory.create(module_type="and4_dec",
|
||||||
height=self.cell_height)
|
height=self.cell_height)
|
||||||
else:
|
else:
|
||||||
debug.error("Invalid number of predecode inputs: {}".format(self.number_of_inputs), -1)
|
debug.error("Invalid number of predecode inputs: {}".format(self.number_of_inputs), -1)
|
||||||
|
|
|
||||||
|
|
@ -534,6 +534,8 @@ class port_data(design.design):
|
||||||
else:
|
else:
|
||||||
start_bit=0
|
start_bit=0
|
||||||
|
|
||||||
|
# This could be a channel route, but in some techs the bitlines
|
||||||
|
# are too close together.
|
||||||
self.channel_route_bitlines(inst1=inst1,
|
self.channel_route_bitlines(inst1=inst1,
|
||||||
inst1_bls_template=inst1_bls_templ,
|
inst1_bls_template=inst1_bls_templ,
|
||||||
inst2=inst2,
|
inst2=inst2,
|
||||||
|
|
@ -558,6 +560,8 @@ class port_data(design.design):
|
||||||
else:
|
else:
|
||||||
start_bit=0
|
start_bit=0
|
||||||
|
|
||||||
|
# This could be a channel route, but in some techs the bitlines
|
||||||
|
# are too close together.
|
||||||
self.channel_route_bitlines(inst1=inst1, inst2=inst2,
|
self.channel_route_bitlines(inst1=inst1, inst2=inst2,
|
||||||
num_bits=self.word_size,
|
num_bits=self.word_size,
|
||||||
inst1_bls_template=inst1_bls_templ,
|
inst1_bls_template=inst1_bls_templ,
|
||||||
|
|
@ -569,11 +573,11 @@ class port_data(design.design):
|
||||||
inst1 = self.write_driver_array_inst
|
inst1 = self.write_driver_array_inst
|
||||||
inst2 = self.sense_amp_array_inst
|
inst2 = self.sense_amp_array_inst
|
||||||
|
|
||||||
# These should be pitch matched in the cell library,
|
# This could be a channel route, but in some techs the bitlines
|
||||||
# but just in case, do a channel route.
|
# are too close together.
|
||||||
self.channel_route_bitlines(inst1=inst1,
|
self.connect_bitlines(inst1=inst1,
|
||||||
inst2=inst2,
|
inst2=inst2,
|
||||||
num_bits=self.word_size)
|
num_bits=self.word_size)
|
||||||
|
|
||||||
def route_bitline_pins(self):
|
def route_bitline_pins(self):
|
||||||
""" Add the bitline pins for the given port """
|
""" Add the bitline pins for the given port """
|
||||||
|
|
@ -676,10 +680,9 @@ class port_data(design.design):
|
||||||
Route the bl and br of two modules using the channel router.
|
Route the bl and br of two modules using the channel router.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
bot_inst_group, top_inst_group = self._group_bitline_instances(
|
bot_inst_group, top_inst_group = self._group_bitline_instances(inst1, inst2, num_bits,
|
||||||
inst1, inst2, num_bits,
|
inst1_bls_template, inst1_start_bit,
|
||||||
inst1_bls_template, inst1_start_bit,
|
inst2_bls_template, inst2_start_bit)
|
||||||
inst2_bls_template, inst2_start_bit)
|
|
||||||
|
|
||||||
# Channel route each mux separately since we don't minimize the number
|
# Channel route each mux separately since we don't minimize the number
|
||||||
# of tracks in teh channel router yet. If we did, we could route all the bits at once!
|
# of tracks in teh channel router yet. If we did, we could route all the bits at once!
|
||||||
|
|
@ -688,13 +691,8 @@ 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, bitline_dirs)
|
self.create_horizontal_channel_route(route_map, offset, self.m1_stack)
|
||||||
|
|
||||||
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}",
|
||||||
|
|
@ -707,10 +705,9 @@ class port_data(design.design):
|
||||||
in the middle between the two modules (if needed).
|
in the middle between the two modules (if needed).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
bot_inst_group, top_inst_group = self._group_bitline_instances(
|
bot_inst_group, top_inst_group = self._group_bitline_instances(inst1, inst2, num_bits,
|
||||||
inst1, inst2, num_bits,
|
inst1_bls_template, inst1_start_bit,
|
||||||
inst1_bls_template, inst1_start_bit,
|
inst2_bls_template, inst2_start_bit)
|
||||||
inst2_bls_template, inst2_start_bit)
|
|
||||||
|
|
||||||
for col in range(num_bits):
|
for col in range(num_bits):
|
||||||
bot_bl_pin, bot_br_pin = self._get_bitline_pins(bot_inst_group, col)
|
bot_bl_pin, bot_br_pin = self._get_bitline_pins(bot_inst_group, col)
|
||||||
|
|
@ -718,15 +715,9 @@ class port_data(design.design):
|
||||||
bot_bl, bot_br = bot_bl_pin.uc(), bot_br_pin.uc()
|
bot_bl, bot_br = bot_bl_pin.uc(), bot_br_pin.uc()
|
||||||
top_bl, top_br = top_bl_pin.bc(), top_br_pin.bc()
|
top_bl, top_br = top_bl_pin.bc(), top_br_pin.bc()
|
||||||
|
|
||||||
yoffset = 0.5 * (top_bl.y + bot_bl.y)
|
layer_pitch = getattr(self, "{}_pitch".format(top_bl_pin.layer))
|
||||||
self.add_path("m2", [bot_bl,
|
self.add_zjog(bot_bl_pin.layer, bot_bl, top_bl, "V", top_bl_pin.by() - layer_pitch)
|
||||||
vector(bot_bl.x, yoffset),
|
self.add_zjog(bot_br_pin.layer, bot_br, top_br, "V", top_bl_pin.by() - 2 * layer_pitch)
|
||||||
vector(top_bl.x, yoffset),
|
|
||||||
top_bl])
|
|
||||||
self.add_path("m2", [bot_br,
|
|
||||||
vector(bot_br.x, yoffset),
|
|
||||||
vector(top_br.x, yoffset),
|
|
||||||
top_br])
|
|
||||||
|
|
||||||
def graph_exclude_precharge(self):
|
def graph_exclude_precharge(self):
|
||||||
"""Precharge adds a loop between bitlines, can be excluded to reduce complexity"""
|
"""Precharge adds a loop between bitlines, can be excluded to reduce complexity"""
|
||||||
|
|
|
||||||
|
|
@ -105,21 +105,16 @@ class precharge(design.design):
|
||||||
|
|
||||||
# center of vdd rail
|
# center of vdd rail
|
||||||
pmos_vdd_pos = vector(pmos_pin.cx(), vdd_position.y)
|
pmos_vdd_pos = vector(pmos_pin.cx(), vdd_position.y)
|
||||||
self.add_path("m1", [pmos_pin.uc(), pmos_vdd_pos])
|
self.add_path(self.en_layer, [pmos_pin.center(), pmos_vdd_pos])
|
||||||
|
|
||||||
# if enable is not on M1, the supply can be
|
|
||||||
if self.en_layer != "m1":
|
|
||||||
self.add_via_center(layers=self.m1_stack,
|
|
||||||
offset=pmos_vdd_pos)
|
|
||||||
|
|
||||||
self.add_power_pin("vdd",
|
self.add_power_pin("vdd",
|
||||||
self.well_contact_pos,
|
self.well_contact_pos,
|
||||||
directions=("V", "V"))
|
directions=("V", "V"))
|
||||||
|
|
||||||
# Hack for li layers
|
self.add_via_stack_center(from_layer=pmos_pin.layer,
|
||||||
if hasattr(self, "li_stack"):
|
to_layer=self.en_layer,
|
||||||
self.add_via_center(layers=self.li_stack,
|
offset=pmos_pin.center(),
|
||||||
offset=self.well_contact_pos)
|
directions=("V", "V"))
|
||||||
|
|
||||||
def create_ptx(self):
|
def create_ptx(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -199,14 +194,9 @@ class precharge(design.design):
|
||||||
# midway in the 4 M2 tracks
|
# midway in the 4 M2 tracks
|
||||||
offset = self.lower_pmos_inst.get_pin("G").ul() \
|
offset = self.lower_pmos_inst.get_pin("G").ul() \
|
||||||
+ vector(0, 0.5 * self.m2_pitch)
|
+ vector(0, 0.5 * self.m2_pitch)
|
||||||
self.add_via_center(layers=self.poly_stack,
|
self.add_via_stack_center(from_layer="poly",
|
||||||
offset=offset)
|
to_layer=self.en_layer,
|
||||||
if self.en_layer == "m2":
|
offset=offset)
|
||||||
self.add_via_center(layers=self.m1_stack,
|
|
||||||
offset=offset)
|
|
||||||
if hasattr(self, "li_stack"):
|
|
||||||
self.add_via_center(layers=self.li_stack,
|
|
||||||
offset=offset)
|
|
||||||
|
|
||||||
# adds the en rail on metal1
|
# adds the en rail on metal1
|
||||||
self.add_layout_pin_segment_center(text="en_bar",
|
self.add_layout_pin_segment_center(text="en_bar",
|
||||||
|
|
@ -225,13 +215,13 @@ class precharge(design.design):
|
||||||
self.nwell_extend_active
|
self.nwell_extend_active
|
||||||
self.well_contact_pos = self.upper_pmos1_inst.get_pin("D").center().scale(1, 0) + \
|
self.well_contact_pos = self.upper_pmos1_inst.get_pin("D").center().scale(1, 0) + \
|
||||||
vector(0, offset_height)
|
vector(0, offset_height)
|
||||||
self.add_via_center(layers=self.active_stack,
|
self.well_contact = self.add_via_center(layers=self.active_stack,
|
||||||
offset=self.well_contact_pos,
|
offset=self.well_contact_pos,
|
||||||
implant_type="n",
|
implant_type="n",
|
||||||
well_type="n")
|
well_type="n")
|
||||||
if hasattr(self, "li_stack"):
|
self.add_via_stack_center(from_layer=self.active_stack[2],
|
||||||
self.add_via_center(layers=self.li_stack,
|
to_layer=self.bitline_layer,
|
||||||
offset=self.well_contact_pos)
|
offset=self.well_contact_pos)
|
||||||
|
|
||||||
self.height = self.well_contact_pos.y + contact.active_contact.height + self.m1_space
|
self.height = self.well_contact_pos.y + contact.active_contact.height + self.m1_space
|
||||||
|
|
||||||
|
|
@ -288,31 +278,19 @@ class precharge(design.design):
|
||||||
Adds contacts/via from metal1 to metal2 for bit-lines
|
Adds contacts/via from metal1 to metal2 for bit-lines
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# No contacts needed if M1
|
|
||||||
if self.bitline_layer == "m1":
|
|
||||||
return
|
|
||||||
|
|
||||||
# BL
|
# BL
|
||||||
lower_pin = self.lower_pmos_inst.get_pin("S")
|
for lower_pin in [self.lower_pmos_inst.get_pin("S"), self.lower_pmos_inst.get_pin("D")]:
|
||||||
self.lower_via = self.add_via_center(layers=self.m1_stack,
|
self.add_via_stack_center(from_layer=lower_pin.layer,
|
||||||
offset=lower_pin.center(),
|
to_layer=self.bitline_layer,
|
||||||
directions=("V", "V"))
|
offset=lower_pin.center(),
|
||||||
|
directions=("V", "V"))
|
||||||
lower_pin = self.lower_pmos_inst.get_pin("D")
|
|
||||||
self.lower_via = self.add_via_center(layers=self.m1_stack,
|
|
||||||
offset=lower_pin.center(),
|
|
||||||
directions=("V", "V"))
|
|
||||||
|
|
||||||
# BR
|
# BR
|
||||||
upper_pin = self.upper_pmos1_inst.get_pin("S")
|
for upper_pin in [self.upper_pmos1_inst.get_pin("S"), self.upper_pmos2_inst.get_pin("D")]:
|
||||||
self.upper_via2 = self.add_via_center(layers=self.m1_stack,
|
self.add_via_stack_center(from_layer=upper_pin.layer,
|
||||||
offset=upper_pin.center(),
|
to_layer=self.bitline_layer,
|
||||||
directions=("V", "V"))
|
offset=upper_pin.center(),
|
||||||
|
directions=("V", "V"))
|
||||||
upper_pin = self.upper_pmos2_inst.get_pin("D")
|
|
||||||
self.upper_via2 = self.add_via_center(layers=self.m1_stack,
|
|
||||||
offset=upper_pin.center(),
|
|
||||||
directions=("V", "V"))
|
|
||||||
|
|
||||||
def connect_pmos(self, pmos_pin, bit_xoffset):
|
def connect_pmos(self, pmos_pin, bit_xoffset):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,8 @@ class wordline_driver(design.design):
|
||||||
self.create_insts()
|
self.create_insts()
|
||||||
|
|
||||||
def create_modules(self):
|
def create_modules(self):
|
||||||
if OPTS.tech_name == "s8":
|
self.nand = factory.create(module_type="nand2_dec",
|
||||||
self.nand = factory.create(module_type="nand2_dec")
|
height=self.height)
|
||||||
self.height = self.nand.height
|
|
||||||
else:
|
|
||||||
self.nand = factory.create(module_type="nand2_dec",
|
|
||||||
height=self.height)
|
|
||||||
|
|
||||||
self.driver = factory.create(module_type="inv_dec",
|
self.driver = factory.create(module_type="inv_dec",
|
||||||
size=self.size,
|
size=self.size,
|
||||||
|
|
|
||||||
|
|
@ -111,11 +111,12 @@ class sram_factory:
|
||||||
return obj_item
|
return obj_item
|
||||||
|
|
||||||
# If no prefered module name is provided, we generate one.
|
# If no prefered module name is provided, we generate one.
|
||||||
if module_name is None:
|
if not module_name:
|
||||||
# Use the default name if there are default arguments
|
# Use the default name for the first cell.
|
||||||
# This is especially for library cells so that the
|
# This is especially for library cells so that the
|
||||||
# spice and gds files can be found.
|
# spice and gds files can be found.
|
||||||
if len(kwargs) > 0:
|
# Subsequent objects will get unique names to help with GDS limitation.
|
||||||
|
if len(self.objects[real_module_type]) > 0:
|
||||||
# Create a unique name and increment the index
|
# Create a unique name and increment the index
|
||||||
module_name = "{0}_{1}".format(real_module_type,
|
module_name = "{0}_{1}".format(real_module_type,
|
||||||
self.module_indices[real_module_type])
|
self.module_indices[real_module_type])
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ from globals import OPTS
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
class pand3_dec_test(openram_test):
|
class and2_dec_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"))
|
||||||
|
|
@ -23,10 +23,10 @@ class pand3_dec_test(openram_test):
|
||||||
global verify
|
global verify
|
||||||
import verify
|
import verify
|
||||||
|
|
||||||
import pand3_dec
|
import and2_dec
|
||||||
|
|
||||||
debug.info(2, "Testing pand3 gate 4x")
|
debug.info(2, "Testing and2 gate 4x")
|
||||||
a = pand3_dec.pand3_dec(name="pand3x4", size=4)
|
a = and2_dec.and2_dec(name="and2x4", size=4)
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
@ -15,7 +15,7 @@ from globals import OPTS
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
class pand3_dec_test(openram_test):
|
class and3_dec_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"))
|
||||||
|
|
@ -23,10 +23,10 @@ class pand3_dec_test(openram_test):
|
||||||
global verify
|
global verify
|
||||||
import verify
|
import verify
|
||||||
|
|
||||||
import pand3_dec
|
import and3_dec
|
||||||
|
|
||||||
debug.info(2, "Testing pand3 gate 4x")
|
debug.info(2, "Testing and3 gate 4x")
|
||||||
a = pand3_dec.pand3_dec(name="pand3x4", size=4)
|
a = and3_dec.and3_dec(name="and3x4", size=4)
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
@ -15,7 +15,7 @@ from globals import OPTS
|
||||||
from sram_factory import factory
|
from sram_factory import factory
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
class pand2_dec_test(openram_test):
|
class and3_dec_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"))
|
||||||
|
|
@ -23,10 +23,10 @@ class pand2_dec_test(openram_test):
|
||||||
global verify
|
global verify
|
||||||
import verify
|
import verify
|
||||||
|
|
||||||
import pand2_dec
|
import and3_dec
|
||||||
|
|
||||||
debug.info(2, "Testing pand2 gate 4x")
|
debug.info(2, "Testing and3 gate 4x")
|
||||||
a = pand2_dec.pand2_dec(name="pand2x4", size=4)
|
a = and3_dec.and3_dec(name="and3x4", size=4)
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
@ -6,7 +6,7 @@ equate class {-circuit1 pfet} {-circuit2 p}
|
||||||
flatten class {-circuit1 dummy_cell_6t}
|
flatten class {-circuit1 dummy_cell_6t}
|
||||||
flatten class {-circuit1 dummy_cell_1rw_1r}
|
flatten class {-circuit1 dummy_cell_1rw_1r}
|
||||||
flatten class {-circuit1 dummy_cell_1w_1r}
|
flatten class {-circuit1 dummy_cell_1w_1r}
|
||||||
flatten class {-circuit1 bitcell_array_0}
|
flatten class {-circuit1 pbitcell}
|
||||||
flatten class {-circuit1 pbitcell_0}
|
flatten class {-circuit1 pbitcell_0}
|
||||||
flatten class {-circuit1 pbitcell_1}
|
flatten class {-circuit1 pbitcell_1}
|
||||||
property {-circuit1 nfet} remove as ad ps pd
|
property {-circuit1 nfet} remove as ad ps pd
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue