mirror of https://github.com/VLSIDA/OpenRAM.git
more stable
This commit is contained in:
parent
4fe635a05f
commit
bda3adf9f9
|
|
@ -233,19 +233,10 @@ class channel_route(design):
|
|||
real_channel_offset = vector(self.offset.x, min(self.min_value, self.offset.y))
|
||||
else:
|
||||
real_channel_offset = vector(min(self.min_value, self.offset.x), self.offset.y)
|
||||
|
||||
if self.dff_area == False:
|
||||
current_offset = real_channel_offset
|
||||
else: # special handle for dff area
|
||||
current_offset = vector(real_channel_offset.x, real_channel_offset.y + 5) # make route out of dffs area
|
||||
|
||||
current_offset = real_channel_offset
|
||||
if self.dff_area == True:
|
||||
if self.layer_stack == self.m2_stack:
|
||||
self.vertical_nonpref_pitch = self.horizontal_pitch + 0.1 # 0.1 make sure even if via at same col, fulfill m3-m3 spacing
|
||||
|
||||
if self.layer_stack == self.m1_stack:
|
||||
current_offset = vector(real_channel_offset.x, current_offset.y + 14) # make sure no overlap between col_dffs & data_dffs
|
||||
if real_channel_offset.y > 0: # which means this is channnel router for coldff at the top
|
||||
current_offset = real_channel_offset # no offset to avoid overlap problem at the top
|
||||
# Sort nets by left edge value
|
||||
nets.sort()
|
||||
while len(nets) > 0:
|
||||
|
|
|
|||
|
|
@ -280,10 +280,6 @@ class sram_1bank(design, verilog, lef):
|
|||
rtr.route_outside(io_pin_names=self.pins_to_route)
|
||||
# route moat vdds
|
||||
#rtr.route_moat(self.pins_to_route)
|
||||
|
||||
# route to the outside
|
||||
#rtr.prepare_escape_pins()
|
||||
|
||||
|
||||
def route_supplies(self, bbox=None):
|
||||
""" Route the supply grid and connect the pins to them. """
|
||||
|
|
@ -916,7 +912,6 @@ class sram_1bank(design, verilog, lef):
|
|||
x_offset = self.control_logic_insts[port].rx() - self.row_addr_dff_insts[port].width
|
||||
# It is above the control logic and the predecoder array
|
||||
y_offset = max(self.control_logic_insts[port].uy(), self.bank.predecoder_top)
|
||||
y_offset = y_offset + 0.4 # fix, maigc number
|
||||
self.row_addr_pos[port] = vector(x_offset, y_offset)
|
||||
self.row_addr_dff_insts[port].place(self.row_addr_pos[port])
|
||||
|
||||
|
|
@ -925,7 +920,7 @@ class sram_1bank(design, verilog, lef):
|
|||
# The row address bits are placed above the control logic aligned on the left.
|
||||
x_offset = self.control_pos[port].x - self.control_logic_insts[port].width + self.row_addr_dff_insts[port].width
|
||||
# If it can be placed above the predecoder and below the control logic, do it
|
||||
y_offset = min(self.control_logic_insts[port].by(), self.bank.predecoder_top)
|
||||
y_offset = min(self.control_logic_insts[port].by(), self.bank.predecoder_bottom)
|
||||
self.row_addr_pos[port] = vector(x_offset, y_offset)
|
||||
self.row_addr_dff_insts[port].place(self.row_addr_pos[port], mirror="XY")
|
||||
|
||||
|
|
@ -1138,8 +1133,10 @@ class sram_1bank(design, verilog, lef):
|
|||
self.route_escape_pins(bbox=init_bbox, mod=mod, route_option=route_option)
|
||||
|
||||
if OPTS.route_supplies:
|
||||
#self.route_supplies(init_bbox)
|
||||
self.route_supplies_constructive(init_bbox)
|
||||
if route_option == "classic":
|
||||
self.route_supplies(init_bbox)
|
||||
else: # fast
|
||||
self.route_supplies_constructive(init_bbox)
|
||||
|
||||
def route_dffs(self, add_routes=True):
|
||||
|
||||
|
|
@ -1175,7 +1172,7 @@ class sram_1bank(design, verilog, lef):
|
|||
|
||||
if port == 0:
|
||||
offset = vector(self.control_logic_insts[port].rx() + self.dff.width,
|
||||
- self.data_bus_size[port] + 2 * self.m3_pitch)
|
||||
self.bank_inst.by() - self.col_addr_size * self.m3_pitch)# higher offset to avoid possible overlap with data dffs channel routing
|
||||
cr = channel_route(netlist=route_map,
|
||||
offset=offset,
|
||||
layer_stack=layer_stack,
|
||||
|
|
@ -1228,17 +1225,11 @@ class sram_1bank(design, verilog, lef):
|
|||
route_map.extend(list(zip(bank_pins, dff_pins)))
|
||||
|
||||
if len(route_map) > 0:
|
||||
|
||||
# This layer stack must be different than the column addr dff layer stack
|
||||
layer_stack = self.m2_stack
|
||||
if port == 0:
|
||||
# This is relative to the bank at 0,0 or the s_en which is routed on M3 also
|
||||
if "s_en" in self.control_logic_insts[port].mod.pin_map:
|
||||
y_bottom = min(0, self.control_logic_insts[port].get_pin("s_en").by())
|
||||
else:
|
||||
y_bottom = 0
|
||||
|
||||
y_offset = y_bottom - self.data_bus_size[port] + 2 * self.m3_pitch
|
||||
# for port 0, the offset of first track in channel router is fixed
|
||||
y_offset = self.data_dff_insts[port].uy() + 6 * self.m3_pitch
|
||||
offset = vector(self.control_logic_insts[port].rx() + self.dff.width,
|
||||
y_offset)
|
||||
cr = channel_route(netlist=route_map,
|
||||
|
|
@ -1253,13 +1244,77 @@ class sram_1bank(design, verilog, lef):
|
|||
self.connect_inst([])
|
||||
# self.add_flat_inst(cr.name, cr)
|
||||
else:
|
||||
self.data_bus_size[port] = max(cr.height, self.col_addr_bus_size[port]) + self.data_bus_gap
|
||||
# return the real channel width that min. should be
|
||||
# the bottom of w_en or s_en
|
||||
if ("s_en" in self.control_logic_insts[port].mod.pin_map) and ("w_en" in self.control_logic_insts[port].mod.pin_map):# rw
|
||||
y_bottom = min(0, self.control_logic_insts[port].get_pin("s_en").by(), self.control_logic_insts[port].get_pin("w_en").by())
|
||||
elif "w_en" in self.control_logic_insts[port].mod.pin_map:# w
|
||||
y_bottom = min(0, self.control_logic_insts[port].get_pin("w_en").by())
|
||||
else:
|
||||
y_bottom = 0
|
||||
|
||||
if len(self.all_ports) == 1: # only 1 port at bottom
|
||||
extra_offset = 6 * self.m3_pitch + (self.bank_inst.by() - (y_bottom - self.m4_nonpref_pitch))
|
||||
else: # 2 ports, row address decoder needs to be considered
|
||||
# for port 0
|
||||
# determine the most right dffs
|
||||
if self.num_spare_cols: # if we have spare regs
|
||||
dff_right_x = self.spare_wen_dff_insts[0].rx()
|
||||
else: # data dffs
|
||||
dff_right_x = self.data_dff_insts[0].rx()
|
||||
# check if row address dffs are overlaped with dff area, bank position as reference
|
||||
if self.bank_inst.rx() < (dff_right_x + 2 * self.m4_pitch):
|
||||
debug.warning("m4 pitch ----> {0}".format(self.m4_pitch))
|
||||
debug.warning("m3 pitch ----> {0}".format(self.m3_pitch))
|
||||
debug.warning("m4_non_pref pitch ----> {0}".format(self.m4_nonpref_pitch))
|
||||
debug.warning("lower row addr dff: {0}".format(self.row_addr_dff_insts[1].by()))
|
||||
debug.warning("higher row addr dff: {0}".format(self.row_addr_dff_insts[1].uy()))
|
||||
# check the most lower one betwenn control signal and address dff
|
||||
if y_bottom < self.row_addr_dff_insts[1].by():
|
||||
y_bottom_most = y_bottom
|
||||
else:
|
||||
y_bottom_most = self.row_addr_dff_insts[1].by()
|
||||
# the upper track should below the lower one
|
||||
extra_offset = 6 * self.m3_pitch + (self.bank_inst.by() - (y_bottom_most - self.m4_nonpref_pitch))
|
||||
else: # do not need take care of address dff 1, since it's far away
|
||||
extra_offset = 6 * self.m3_pitch + (self.bank_inst.by() - (y_bottom - self.m4_nonpref_pitch))
|
||||
debug.warning("extra_offset->{0}".format(extra_offset))
|
||||
debug.warning("channel_height->{0}".format(cr.height))
|
||||
debug.warning("self.col_addr_bus_size->{0}".format(self.col_addr_bus_size[port]))
|
||||
debug.warning("self.databusgap->{0}".format(self.data_bus_gap))
|
||||
self.data_bus_size[port] = max((cr.height + extra_offset), self.col_addr_bus_size[port]) + self.data_bus_gap
|
||||
else:
|
||||
if "s_en" in self.control_logic_insts[port].mod.pin_map:
|
||||
y_top = max(self.bank.height, self.control_logic_insts[port].get_pin("s_en").uy())
|
||||
# for port1, the offset of first track in channel router needs to check first, make sure no overlap with control signal & address dff
|
||||
if ("s_en" in self.control_logic_insts[port].mod.pin_map) and ("w_en" in self.control_logic_insts[port].mod.pin_map):
|
||||
y_top = max(self.bank.height, self.control_logic_insts[port].get_pin("s_en").uy(), self.control_logic_insts[port].get_pin("w_en").uy())
|
||||
y_offset = y_top + 6 * self.m3_pitch
|
||||
elif "w_en" in self.control_logic_insts[port].mod.pin_map:
|
||||
y_top = max(self.bank.height, self.control_logic_insts[port].get_pin("w_en").uy())
|
||||
y_offset = y_top + self.m3_pitch# it's fine, since w port doesn't have dout signals
|
||||
else:
|
||||
y_top = self.bank.height
|
||||
y_offset = y_top + self.m3_pitch
|
||||
y_offset = y_top + 6 * self.m3_pitch
|
||||
# check the offset overlap with address dff 0 or not
|
||||
if self.num_spare_cols: # if we have spare regs
|
||||
dff_left_x = self.spare_wen_dff_insts[1].lx()
|
||||
else: # data dffs
|
||||
dff_left_x = self.data_dff_insts[1].lx()
|
||||
# check if row address dffs are overlaped with dff area
|
||||
if self.bank_inst.lx() > (dff_left_x - 2 * self.m4_pitch):
|
||||
debug.warning("m4 pitch ----> {0}".format(self.m4_pitch))
|
||||
debug.warning("m3 pitch ----> {0}".format(self.m3_pitch))
|
||||
debug.warning("m4_non_pref pitch ----> {0}".format(self.m4_nonpref_pitch))
|
||||
# the bottom track should also above row address decoder
|
||||
if y_offset > self.row_addr_dff_insts[0].uy() + self.m4_nonpref_pitch:
|
||||
# do not need change since first track is high enough
|
||||
extra_offset = y_offset - self.bank.height # height could be use since bank at 0,0
|
||||
else: # make it higher tham row address decoder
|
||||
extra_offset = self.row_addr_dff_insts[0].uy() + self.m4_nonpref_pitch - self.bank_inst.height
|
||||
# update the new y_offset
|
||||
y_offset = self.row_addr_dff_insts[0].uy() + self.m4_nonpref_pitch
|
||||
else: # do not need to take care address dff0, since it's far away
|
||||
extra_offset = y_offset - self.bank.height # height could be use since bank at 0,0
|
||||
|
||||
offset = vector(0,
|
||||
y_offset)
|
||||
cr = channel_route(netlist=route_map,
|
||||
|
|
@ -1274,7 +1329,10 @@ class sram_1bank(design, verilog, lef):
|
|||
self.connect_inst([])
|
||||
# self.add_flat_inst(cr.name, cr)
|
||||
else:
|
||||
self.data_bus_size[port] = max(cr.height, self.col_addr_bus_size[port]) + self.data_bus_gap
|
||||
# return the real channel width that min. should be
|
||||
# 2 ports, row address decoder needs to be considered
|
||||
# for port 1
|
||||
self.data_bus_size[port] = max((cr.height + extra_offset), self.col_addr_bus_size[port]) + self.data_bus_gap
|
||||
|
||||
def route_clk(self):
|
||||
""" Route the clock network """
|
||||
|
|
|
|||
|
|
@ -395,12 +395,15 @@ class io_pin_placer(router):
|
|||
return [source_pin.bc(), target_pin.uc()]
|
||||
else:
|
||||
# need intermediate point
|
||||
via_basic_y = self.design.bank.height + 3 # 3 is magic number, make sure out of bank area
|
||||
#via_basic_y = self.design.bank.height + 3 # 3 is magic number, make sure out of bank area
|
||||
via_basic_y = self.design.bank_inst.uy() + 3 * self.design.m3_pitch
|
||||
is_up = not is_up# Be attention, for channel at the top, the is_up should be inverted! Otherwise will cause overlap!
|
||||
if is_up:
|
||||
via_basic_y = via_basic_y + 0.5
|
||||
#via_basic_y = via_basic_y + 0.5
|
||||
via_basic_y = via_basic_y + self.design.m3_pitch
|
||||
else:
|
||||
via_basic_y = via_basic_y - 0.5
|
||||
#via_basic_y = via_basic_y - 0.5
|
||||
via_basic_y = via_basic_y - self.design.m3_pitch
|
||||
point_1 = vector(source_pin.center().x, via_basic_y)
|
||||
point_2 = vector(target_pin.center().x, via_basic_y)
|
||||
return [source_pin.bc(), point_1, point_2, target_pin.uc()]
|
||||
|
|
@ -412,11 +415,14 @@ class io_pin_placer(router):
|
|||
return [source_pin.uc(), target_pin.bc()]
|
||||
else:
|
||||
# need intermediate point
|
||||
via_basic_y = ll.y + 22 # 22 is magic number, make sure out of dff area
|
||||
#via_basic_y = ll.y + 22 # 22 is magic number, make sure out of dff area
|
||||
via_basic_y = self.design.data_dff_insts[0].uy() + 3 * self.design.m3_pitch
|
||||
if is_up:
|
||||
via_basic_y = via_basic_y + 0.5
|
||||
#via_basic_y = via_basic_y + 0.5
|
||||
via_basic_y = via_basic_y + self.design.m3_pitch
|
||||
else:
|
||||
via_basic_y = via_basic_y - 0.5
|
||||
#via_basic_y = via_basic_y - 0.5
|
||||
via_basic_y = via_basic_y - self.design.m3_pitch
|
||||
point_1 = vector(source_pin.center().x, via_basic_y)
|
||||
point_2 = vector(target_pin.center().x, via_basic_y)
|
||||
return [source_pin.uc(), point_1, point_2, target_pin.bc()]
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class supply_placer(router):
|
|||
selected_moat_pins = self.prepare_selected_moat_pins()
|
||||
# Route vdd and gnd
|
||||
routed_count = 0
|
||||
routed_max = len(self.pins[vdd_name]) + len(self.pins[gnd_name])
|
||||
routed_max = len(self.pins[vdd_name]) + len(self.pins[gnd_name]) + len(self.moat_pins) + len(self.new_pins["gnd"])
|
||||
for pin_name in [vdd_name, gnd_name]:
|
||||
if pin_name == gnd_name: # otherwise will not recognaize the moat blocakge
|
||||
self.prepare_gds_reader()
|
||||
|
|
@ -206,7 +206,7 @@ class supply_placer(router):
|
|||
pin.ll(),
|
||||
pin.width(),
|
||||
pin.height())
|
||||
|
||||
|
||||
|
||||
def prepare_selected_moat_pins(self):
|
||||
""" Selcet the possibe moat pins, feed into the MST, where will decide which of these pin should be connected to which pin """
|
||||
|
|
@ -256,57 +256,6 @@ class supply_placer(router):
|
|||
return selected_moat_pins
|
||||
|
||||
|
||||
def prepare_escape_pins(self):
|
||||
# clear all the inside "vdd " "gnd" at sram module level
|
||||
# Copy the pin shape(s) to rectangles
|
||||
for pin_name in ["vdd", "gnd"]:
|
||||
# Copy the pin shape(s) to rectangles
|
||||
for pin in self.design.get_pins(pin_name):
|
||||
self.design.add_rect(pin.layer,
|
||||
pin.ll(),
|
||||
pin.width(),
|
||||
pin.height())
|
||||
|
||||
# Remove the pin shape(s)
|
||||
self.design.remove_layout_pin(pin_name)
|
||||
|
||||
# prepare pins for every instances
|
||||
for pin_name in ["vdd"]:
|
||||
count =0
|
||||
for pin in self.design.control_logic_insts[0].get_pins(pin_name):
|
||||
debug.warning("vdd pin shape -> ll:{0} ur:{1}".format(pin.ll(), pin.ur()))
|
||||
"""
|
||||
count = count + 1
|
||||
new_pin = graph_shape("gnd", pin.rect, pin.layer)
|
||||
source = new_pin
|
||||
source_center_x = pin.center().x
|
||||
target_ur_y = self.new_pins[self.ext_gnd_name][1].center().y + 0.5 * self.new_pins[self.ext_gnd_name][1].height()
|
||||
ll = vector(source_center_x - 2.6 - 0.5 * self.track_wire, pin.center().y - 0.5 * self.track_wire)#target_ur_y - self.track_wire)
|
||||
ur = vector(source_center_x - 2.6 + 0.5 * self.track_wire, pin.center().y + 0.5 * self.track_wire)#target_ur_y)
|
||||
target = graph_shape("fake", [ll,ur], pin.layer)
|
||||
# Create the graph
|
||||
g = graph(self)
|
||||
g.create_graph(source, target)
|
||||
# Find the shortest path from source to target
|
||||
path = g.find_shortest_path()
|
||||
# If no path is found, throw an error
|
||||
if path is None:
|
||||
self.write_debug_gds(gds_name="{}error.gds".format(OPTS.openram_temp), g=g, source=source, target=target)
|
||||
debug.error("Couldn't route from {} to {}.".format(source, target), -1)
|
||||
# Create the path shapes on layout
|
||||
new_wires, new_vias = self.add_path(path)
|
||||
# Find the recently added shapes
|
||||
self.find_blockages(pin_name, new_wires)
|
||||
self.find_vias(new_vias)
|
||||
"""
|
||||
debug.warning("vdd of wmask number -> {0}".format(count))
|
||||
debug.warning("instance postion -> {0} {1}".format(self.design.control_logic_insts[0].lx(), self.design.control_logic_insts[0].by()))
|
||||
|
||||
# print pins_all
|
||||
for pin in self.all_pins:
|
||||
debug.warning("all_pins -> {0}".format(pin))
|
||||
|
||||
|
||||
def check_overlap(self, moat_pin, io_pin_names):
|
||||
# use all the IO pins(at correspoding edge) to check overlap, check 1 moat vdd pin, give the corresponding target/source position as list, and connect them
|
||||
add_distance = 0
|
||||
|
|
@ -361,7 +310,7 @@ class supply_placer(router):
|
|||
self.moat_pins_bottom.append(moat_pin_route)
|
||||
elif edge == "top":
|
||||
add_distance = self.via2_via3_pitch # if shift, need to fulfill via2-via3 spacing, top/bottom only
|
||||
pin_too_close = any(abs(io_pin.center().x - source_center.x) < self.track_width for io_pin in self.io_pins_top)
|
||||
pin_too_close = any(abs(io_pin.center().x - source_center.x) < (self.track_width + 0.1) for io_pin in self.io_pins_top)
|
||||
tmp_center = vector(source_center.x, source_center.y)
|
||||
while pin_too_close:
|
||||
tmp_center = vector(source_center.x, source_center.y)
|
||||
|
|
@ -370,7 +319,7 @@ class supply_placer(router):
|
|||
tmp_center = vector((tmp_center.x + add_distance), tmp_center.y)
|
||||
else: # left shift
|
||||
tmp_center = vector((tmp_center.x - add_distance), tmp_center.y)
|
||||
pin_too_close = any(abs(io_pin.center().x - tmp_center.x) < self.track_width for io_pin in self.io_pins_top)
|
||||
pin_too_close = any(abs(io_pin.center().x - tmp_center.x) < (self.track_width + 0.1) for io_pin in self.io_pins_top)
|
||||
direction = - direction
|
||||
# the nearst vdd ring
|
||||
vdd_ring = self.new_pins["vdd"][0] # order in list -> "top", "bottom", "right", "left"]
|
||||
|
|
@ -628,7 +577,7 @@ class supply_placer(router):
|
|||
return "right"
|
||||
return "top"
|
||||
|
||||
|
||||
|
||||
def find_closest_edge(self, pin):
|
||||
""" Use to find the edge, where the io pin locats """
|
||||
|
||||
|
|
@ -796,7 +745,7 @@ class supply_placer(router):
|
|||
# Prepare the pins that are allowed to connect to the moat pins.
|
||||
# Specical handle gnd ring
|
||||
candidate_pins = []
|
||||
max_distance = 13
|
||||
max_distance = 20#13
|
||||
if pin_name == "gnd":
|
||||
ring_pins = []
|
||||
ring_pins = self.new_pins[pin_name]
|
||||
|
|
|
|||
|
|
@ -114,7 +114,21 @@ class sram():
|
|||
break
|
||||
elif self.route_option == "fast":
|
||||
if not OPTS.netlist_only:
|
||||
self.s.create_layout(route_option=route_option)
|
||||
i = 0
|
||||
while i < 10:
|
||||
debug.warning("current i: i = {0}".format(i))
|
||||
try:
|
||||
self.s.create_layout(position_add=i, route_option=route_option)
|
||||
except AssertionError as e:
|
||||
i = i + 1
|
||||
if i == 9: #failed in routing
|
||||
debug.error("Failed in routing", -1)
|
||||
break
|
||||
del self.s
|
||||
self.s = sram(name, sram_config)
|
||||
self.s.create_netlist()
|
||||
continue
|
||||
break
|
||||
|
||||
if not OPTS.is_unit_test:
|
||||
print_time("SRAM creation", datetime.datetime.now(), start_time)
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ for path in output_files:
|
|||
|
||||
# Create an SRAM (we can also pass sram_config, see documentation/tutorials for details)
|
||||
from openram import sram
|
||||
s = sram(route_option="fast")# "classic" or "fast"
|
||||
s = sram(route_option="classic")# "classic" or "fast"
|
||||
# Output the files for the resulting SRAM
|
||||
s.save()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue