mirror of https://github.com/VLSIDA/OpenRAM.git
merge conflict
This commit is contained in:
commit
9a6b38b67e
|
|
@ -42,14 +42,14 @@ class layout():
|
||||||
self.visited = [] # List of modules we have already visited
|
self.visited = [] # List of modules we have already visited
|
||||||
self.is_library_cell = False # Flag for library cells
|
self.is_library_cell = False # Flag for library cells
|
||||||
self.gds_read()
|
self.gds_read()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from tech import power_grid
|
from tech import power_grid
|
||||||
self.pwr_grid_layer = power_grid[0]
|
self.pwr_grid_layer = power_grid[0]
|
||||||
except ImportError:
|
except ImportError:
|
||||||
self.pwr_grid_layer = "m3"
|
self.pwr_grid_layer = "m3"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# GDS layout
|
# GDS layout
|
||||||
|
|
@ -465,7 +465,7 @@ class layout():
|
||||||
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.")
|
||||||
|
|
||||||
if layer in layer_stacks:
|
if layer in layer_stacks:
|
||||||
self.add_wire(layer, [start, mid1, mid2, end])
|
self.add_wire(layer, [start, mid1, mid2, end])
|
||||||
elif layer in techlayer:
|
elif layer in techlayer:
|
||||||
|
|
@ -480,7 +480,7 @@ class layout():
|
||||||
mid1 = vector(0.5 * start.x + 0.5 * end.x, start.y)
|
mid1 = vector(0.5 * start.x + 0.5 * end.x, start.y)
|
||||||
mid2 = vector(mid1, end.y)
|
mid2 = vector(mid1, end.y)
|
||||||
self.add_path(layer, [start, mid1, mid2, end])
|
self.add_path(layer, [start, mid1, mid2, end])
|
||||||
|
|
||||||
def add_wire(self, layers, coordinates, widen_short_wires=True):
|
def add_wire(self, layers, coordinates, widen_short_wires=True):
|
||||||
"""Connects a routing path on given layer,coordinates,width.
|
"""Connects a routing path on given layer,coordinates,width.
|
||||||
The layers are the (horizontal, via, vertical). """
|
The layers are the (horizontal, via, vertical). """
|
||||||
|
|
@ -620,7 +620,7 @@ class layout():
|
||||||
last_via=via,
|
last_via=via,
|
||||||
size=size)
|
size=size)
|
||||||
return via
|
return via
|
||||||
|
|
||||||
def add_ptx(self, offset, mirror="R0", rotate=0, width=1, mults=1, tx_type="nmos"):
|
def add_ptx(self, offset, mirror="R0", rotate=0, width=1, mults=1, tx_type="nmos"):
|
||||||
"""Adds a ptx module to the design."""
|
"""Adds a ptx module to the design."""
|
||||||
import ptx
|
import ptx
|
||||||
|
|
@ -973,7 +973,7 @@ class layout():
|
||||||
self.add_via_stack_center(from_layer=vlayer,
|
self.add_via_stack_center(from_layer=vlayer,
|
||||||
to_layer=dest_pin.layer,
|
to_layer=dest_pin.layer,
|
||||||
offset=out_pos)
|
offset=out_pos)
|
||||||
|
|
||||||
def get_layer_pitch(self, layer):
|
def get_layer_pitch(self, layer):
|
||||||
""" Return the track pitch on a given layer """
|
""" Return the track pitch on a given layer """
|
||||||
try:
|
try:
|
||||||
|
|
@ -985,7 +985,7 @@ class layout():
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
debug.error("Cannot find layer pitch.", -1)
|
debug.error("Cannot find layer pitch.", -1)
|
||||||
return (nonpref_pitch, pitch, pitch - space, space)
|
return (nonpref_pitch, pitch, pitch - space, space)
|
||||||
|
|
||||||
def add_horizontal_trunk_route(self,
|
def add_horizontal_trunk_route(self,
|
||||||
pins,
|
pins,
|
||||||
trunk_offset,
|
trunk_offset,
|
||||||
|
|
@ -998,8 +998,13 @@ class layout():
|
||||||
max_x = max([pin.center().x for pin in pins])
|
max_x = max([pin.center().x for pin in pins])
|
||||||
min_x = min([pin.center().x for pin in pins])
|
min_x = min([pin.center().x for pin in pins])
|
||||||
|
|
||||||
|
# max_x_lc & min_x_rc are for routing to/from the edge of the pins
|
||||||
|
# to increase spacing between contacts of different nets
|
||||||
|
max_x_lc = max([pin.lc().x for pin in pins])
|
||||||
|
min_x_rc = min([pin.rc().x for pin in pins])
|
||||||
|
|
||||||
# if we are less than a pitch, just create a non-preferred layer jog
|
# if we are less than a pitch, just create a non-preferred layer jog
|
||||||
if max_x - min_x <= pitch:
|
if max_x_lc - min_x_rc <= pitch:
|
||||||
half_layer_width = 0.5 * drc["minwidth_{0}".format(self.vertical_layer)]
|
half_layer_width = 0.5 * drc["minwidth_{0}".format(self.vertical_layer)]
|
||||||
|
|
||||||
# Add the horizontal trunk on the vertical layer!
|
# Add the horizontal trunk on the vertical layer!
|
||||||
|
|
@ -1020,7 +1025,15 @@ class layout():
|
||||||
|
|
||||||
# Route each pin to the trunk
|
# Route each pin to the trunk
|
||||||
for pin in pins:
|
for pin in pins:
|
||||||
mid = vector(pin.center().x, trunk_offset.y)
|
# If there is sufficient space, Route from the edge of the pins
|
||||||
|
# Otherwise, route from the center of the pins
|
||||||
|
if max_x_lc - min_x_rc > pitch:
|
||||||
|
if pin.center().x == max_x:
|
||||||
|
mid = vector(pin.lc().x, trunk_offset.y)
|
||||||
|
else:
|
||||||
|
mid = vector(pin.rc().x, trunk_offset.y)
|
||||||
|
else:
|
||||||
|
mid = vector(pin.center().x, trunk_offset.y)
|
||||||
self.add_path(self.vertical_layer, [pin.center(), mid])
|
self.add_path(self.vertical_layer, [pin.center(), mid])
|
||||||
self.add_via_center(layers=layer_stack,
|
self.add_via_center(layers=layer_stack,
|
||||||
offset=mid)
|
offset=mid)
|
||||||
|
|
@ -1037,8 +1050,13 @@ class layout():
|
||||||
max_y = max([pin.center().y for pin in pins])
|
max_y = max([pin.center().y for pin in pins])
|
||||||
min_y = min([pin.center().y for pin in pins])
|
min_y = min([pin.center().y for pin in pins])
|
||||||
|
|
||||||
|
# max_y_bc & min_y_uc are for routing to/from the edge of the pins
|
||||||
|
# to reduce spacing between contacts of different nets
|
||||||
|
max_y_bc = max([pin.bc().y for pin in pins])
|
||||||
|
min_y_uc = min([pin.uc().y for pin in pins])
|
||||||
|
|
||||||
# if we are less than a pitch, just create a non-preferred layer jog
|
# if we are less than a pitch, just create a non-preferred layer jog
|
||||||
if max_y - min_y <= pitch:
|
if max_y_bc - min_y_uc <= pitch:
|
||||||
|
|
||||||
half_layer_width = 0.5 * drc["minwidth_{0}".format(self.horizontal_layer)]
|
half_layer_width = 0.5 * drc["minwidth_{0}".format(self.horizontal_layer)]
|
||||||
|
|
||||||
|
|
@ -1060,7 +1078,15 @@ class layout():
|
||||||
|
|
||||||
# Route each pin to the trunk
|
# Route each pin to the trunk
|
||||||
for pin in pins:
|
for pin in pins:
|
||||||
mid = vector(trunk_offset.x, pin.center().y)
|
# If there is sufficient space, Route from the edge of the pins
|
||||||
|
# Otherwise, route from the center of the pins
|
||||||
|
if max_y_bc - min_y_uc > pitch:
|
||||||
|
if pin.center().y == max_y:
|
||||||
|
mid = vector(trunk_offset.x, pin.bc().y)
|
||||||
|
else:
|
||||||
|
mid = vector(trunk_offset.x, pin.uc().y)
|
||||||
|
else:
|
||||||
|
mid = vector(trunk_offset.x, pin.center().y)
|
||||||
self.add_path(self.horizontal_layer, [pin.center(), mid])
|
self.add_path(self.horizontal_layer, [pin.center(), mid])
|
||||||
self.add_via_center(layers=layer_stack,
|
self.add_via_center(layers=layer_stack,
|
||||||
offset=mid)
|
offset=mid)
|
||||||
|
|
@ -1103,7 +1129,7 @@ class layout():
|
||||||
pitch = self.horizontal_nonpref_pitch
|
pitch = self.horizontal_nonpref_pitch
|
||||||
else:
|
else:
|
||||||
pitch = self.vertical_nonpref_pitch
|
pitch = self.vertical_nonpref_pitch
|
||||||
|
|
||||||
for pin1 in net1:
|
for pin1 in net1:
|
||||||
for pin2 in net2:
|
for pin2 in net2:
|
||||||
if vcg_pin_overlap(pin1, pin2, vertical, pitch):
|
if vcg_pin_overlap(pin1, pin2, vertical, pitch):
|
||||||
|
|
@ -1113,7 +1139,7 @@ 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 extra comparison *shouldn't* matter.
|
# for example, so the extra comparison *shouldn't* matter.
|
||||||
|
|
@ -1147,7 +1173,7 @@ class layout():
|
||||||
|
|
||||||
layer_stuff = self.get_layer_pitch(self.vertical_layer)
|
layer_stuff = self.get_layer_pitch(self.vertical_layer)
|
||||||
(self.vertical_nonpref_pitch, self.vertical_pitch, self.vertical_width, self.vertical_space) = layer_stuff
|
(self.vertical_nonpref_pitch, self.vertical_pitch, self.vertical_width, self.vertical_space) = layer_stuff
|
||||||
|
|
||||||
layer_stuff = self.get_layer_pitch(self.horizontal_layer)
|
layer_stuff = self.get_layer_pitch(self.horizontal_layer)
|
||||||
(self.horizontal_nonpref_pitch, self.horizontal_pitch, self.horizontal_width, self.horizontal_space) = layer_stuff
|
(self.horizontal_nonpref_pitch, self.horizontal_pitch, self.horizontal_width, self.horizontal_space) = layer_stuff
|
||||||
|
|
||||||
|
|
@ -1172,7 +1198,7 @@ class layout():
|
||||||
# print("Nets:")
|
# print("Nets:")
|
||||||
# for net_name in nets:
|
# for net_name in nets:
|
||||||
# print(net_name, [x.name for x in nets[net_name]])
|
# print(net_name, [x.name for x in nets[net_name]])
|
||||||
|
|
||||||
# Find the vertical pin conflicts
|
# Find the vertical pin conflicts
|
||||||
# FIXME: O(n^2) but who cares for now
|
# FIXME: O(n^2) but who cares for now
|
||||||
for net_name1 in nets:
|
for net_name1 in nets:
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class port_data(design.design):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, sram_config, port, name=""):
|
def __init__(self, sram_config, port, name=""):
|
||||||
|
|
||||||
sram_config.set_local_config(self)
|
sram_config.set_local_config(self)
|
||||||
self.port = port
|
self.port = port
|
||||||
if self.write_size is not None:
|
if self.write_size is not None:
|
||||||
|
|
@ -444,7 +444,7 @@ class port_data(design.design):
|
||||||
|
|
||||||
def route_sense_amp_out(self, port):
|
def route_sense_amp_out(self, port):
|
||||||
""" Add pins for the sense amp output """
|
""" Add pins for the sense amp output """
|
||||||
|
|
||||||
for bit in range(self.word_size):
|
for bit in range(self.word_size):
|
||||||
data_pin = self.sense_amp_array_inst.get_pin("data_{}".format(bit))
|
data_pin = self.sense_amp_array_inst.get_pin("data_{}".format(bit))
|
||||||
self.add_layout_pin_rect_center(text="dout_{0}".format(bit),
|
self.add_layout_pin_rect_center(text="dout_{0}".format(bit),
|
||||||
|
|
@ -521,10 +521,10 @@ class port_data(design.design):
|
||||||
|
|
||||||
insn2_start_bit = 1 if self.port == 0 else 0
|
insn2_start_bit = 1 if self.port == 0 else 0
|
||||||
|
|
||||||
self.connect_bitlines(inst1=inst1,
|
self.channel_route_bitlines(inst1=inst1,
|
||||||
inst2=inst2,
|
inst2=inst2,
|
||||||
num_bits=self.num_cols,
|
num_bits=self.num_cols,
|
||||||
inst2_start_bit=insn2_start_bit)
|
inst2_start_bit=insn2_start_bit)
|
||||||
|
|
||||||
def route_sense_amp_to_column_mux_or_precharge_array(self, port):
|
def route_sense_amp_to_column_mux_or_precharge_array(self, port):
|
||||||
""" Routing of BL and BR between sense_amp and column mux or precharge array """
|
""" Routing of BL and BR between sense_amp and column mux or precharge array """
|
||||||
|
|
@ -703,7 +703,7 @@ class port_data(design.design):
|
||||||
bitline_dirs = ("H", "V")
|
bitline_dirs = ("H", "V")
|
||||||
elif bottom_names[0].layer == "m1":
|
elif bottom_names[0].layer == "m1":
|
||||||
bitline_dirs = ("V", "H")
|
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, bitline_dirs)
|
||||||
|
|
||||||
|
|
@ -717,7 +717,7 @@ class port_data(design.design):
|
||||||
This assumes that they have sufficient space to create a jog
|
This assumes that they have sufficient space to create a jog
|
||||||
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,
|
||||||
|
|
@ -738,9 +738,8 @@ class port_data(design.design):
|
||||||
vector(bot_br.x, yoffset),
|
vector(bot_br.x, yoffset),
|
||||||
vector(top_br.x, yoffset),
|
vector(top_br.x, yoffset),
|
||||||
top_br])
|
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"""
|
||||||
if self.precharge_array_inst:
|
if self.precharge_array_inst:
|
||||||
self.graph_inst_exclude.add(self.precharge_array_inst)
|
self.graph_inst_exclude.add(self.precharge_array_inst)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ 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
|
||||||
|
from utils import round_to_grid
|
||||||
|
|
||||||
class single_level_column_mux(pgate.pgate):
|
class single_level_column_mux(pgate.pgate):
|
||||||
"""
|
"""
|
||||||
|
|
@ -75,6 +75,17 @@ class single_level_column_mux(pgate.pgate):
|
||||||
bl_pos = vector(bl_pin.lx(), 0)
|
bl_pos = vector(bl_pin.lx(), 0)
|
||||||
br_pos = vector(br_pin.lx(), 0)
|
br_pos = vector(br_pin.lx(), 0)
|
||||||
|
|
||||||
|
# The bitline input/output pins must be a least as wide as the metal pitch
|
||||||
|
# so that there is enough space to route to/from the pins.
|
||||||
|
# FIXME: bitline_metal_pitch should be greater than the horizontal metal pitch used in port_data
|
||||||
|
bitline_metal_pitch = self.width / 2
|
||||||
|
bitline_width = br_pos.x - bl_pos.x
|
||||||
|
if bitline_width < bitline_metal_pitch:
|
||||||
|
bitline_width_increase_bl = round_to_grid((bitline_metal_pitch - bitline_width) / 2)
|
||||||
|
bitline_width_increase_br = round_to_grid((bitline_metal_pitch - bitline_width) - bitline_width_increase_bl)
|
||||||
|
bl_pos = bl_pos + vector(-bitline_width_increase_bl, 0)
|
||||||
|
br_pos = br_pos + vector( bitline_width_increase_br, 0)
|
||||||
|
|
||||||
# bl and br
|
# bl and br
|
||||||
self.add_layout_pin(text="bl",
|
self.add_layout_pin(text="bl",
|
||||||
layer=bl_pin.layer,
|
layer=bl_pin.layer,
|
||||||
|
|
@ -133,7 +144,7 @@ class single_level_column_mux(pgate.pgate):
|
||||||
|
|
||||||
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 exists, use li and m1 for the mux, otherwise use m1 and m2
|
||||||
if "li" in layer:
|
if "li" in layer:
|
||||||
self.col_mux_stack = self.li_stack
|
self.col_mux_stack = self.li_stack
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue