more stable

This commit is contained in:
FriedrichWu 2024-12-16 00:13:40 +01:00
parent 4fe635a05f
commit bda3adf9f9
6 changed files with 116 additions and 98 deletions

View File

@ -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:

View File

@ -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 """

View File

@ -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()]

View File

@ -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]

View File

@ -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)

View File

@ -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()