mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-08-22 14:17:35 +02:00
make code clean
This commit is contained in:
@@ -144,16 +144,16 @@ class channel_route(design):
|
|||||||
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
|
||||||
# For debug
|
# For debug
|
||||||
|
|
||||||
debug.warning("layer horizontal: {0}".format(self.horizontal_layer))
|
debug.warning("layer horizontal: {0}".format(self.horizontal_layer))
|
||||||
debug.warning("horizontal_nonpref_pitch: {0}".format(self.horizontal_nonpref_pitch))
|
debug.warning("horizontal_nonpref_pitch: {0}".format(self.horizontal_nonpref_pitch))
|
||||||
debug.warning("horizontal_pitch: {0}".format(self.horizontal_pitch))
|
debug.warning("horizontal_pitch: {0}".format(self.horizontal_pitch))
|
||||||
debug.warning("horizontal_space: {0}".format(self.horizontal_space))
|
debug.warning("horizontal_space: {0}".format(self.horizontal_space))
|
||||||
debug.warning("layer vertical: {0}".format(self.vertical_layer))
|
debug.warning("layer vertical: {0}".format(self.vertical_layer))
|
||||||
debug.warning("vertiacl_nonpref_pitch: {0}".format(self.vertical_pitch))
|
debug.warning("vertiacl_nonpref_pitch: {0}".format(self.vertical_pitch))
|
||||||
debug.warning("vertical_pitch: {0}".format(self.vertical_pitch))
|
debug.warning("vertical_pitch: {0}".format(self.vertical_pitch))
|
||||||
debug.warning("vertical_space: {0}".format(self.vertical_space))
|
debug.warning("vertical_space: {0}".format(self.vertical_space))
|
||||||
|
|
||||||
self.route()
|
self.route()
|
||||||
|
|
||||||
def remove_net_from_graph(self, pin, g):
|
def remove_net_from_graph(self, pin, g):
|
||||||
@@ -233,7 +233,7 @@ class channel_route(design):
|
|||||||
real_channel_offset = vector(self.offset.x, min(self.min_value, self.offset.y))
|
real_channel_offset = vector(self.offset.x, min(self.min_value, self.offset.y))
|
||||||
else:
|
else:
|
||||||
real_channel_offset = vector(min(self.min_value, self.offset.x), self.offset.y)
|
real_channel_offset = vector(min(self.min_value, self.offset.x), self.offset.y)
|
||||||
|
|
||||||
if self.dff_area == False:
|
if self.dff_area == False:
|
||||||
current_offset = real_channel_offset
|
current_offset = real_channel_offset
|
||||||
else: # special handle for dff area
|
else: # special handle for dff area
|
||||||
@@ -241,7 +241,7 @@ class channel_route(design):
|
|||||||
|
|
||||||
if self.layer_stack == self.m2_stack:
|
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
|
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:
|
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
|
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
|
if real_channel_offset.y > 0: # which means this is channnel router for coldff at the top
|
||||||
@@ -326,8 +326,8 @@ class channel_route(design):
|
|||||||
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_with_jog(self,
|
def add_horizontal_trunk_with_jog(self,
|
||||||
pins,
|
pins,
|
||||||
trunk_offset,
|
trunk_offset,
|
||||||
pitch):
|
pitch):
|
||||||
@@ -346,7 +346,7 @@ class channel_route(design):
|
|||||||
non_preferred_route = max_x - min_x <= pitch
|
non_preferred_route = max_x - min_x <= 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)]
|
||||||
if port == 0: # bottom need shift
|
if port == 0: # bottom need shift
|
||||||
if non_preferred_route:
|
if non_preferred_route:
|
||||||
# Add the horizontal trunk on the vertical layer!
|
# Add the horizontal trunk on the vertical layer!
|
||||||
self.add_path(self.vertical_layer,
|
self.add_path(self.vertical_layer,
|
||||||
[vector(min_x - half_layer_width, trunk_offset.y),
|
[vector(min_x - half_layer_width, trunk_offset.y),
|
||||||
@@ -368,7 +368,7 @@ class channel_route(design):
|
|||||||
self.add_path(self.vertical_layer, [pin_pos, mid])
|
self.add_path(self.vertical_layer, [pin_pos, mid])
|
||||||
self.add_via_stack_center(from_layer=pin.layer,
|
self.add_via_stack_center(from_layer=pin.layer,
|
||||||
to_layer=self.vertical_layer,
|
to_layer=self.vertical_layer,
|
||||||
offset=pin.bc())
|
offset=pin.bc())
|
||||||
else:
|
else:
|
||||||
# Add the horizontal trunk
|
# Add the horizontal trunk
|
||||||
self.add_path(self.horizontal_layer,
|
self.add_path(self.horizontal_layer,
|
||||||
@@ -399,7 +399,7 @@ class channel_route(design):
|
|||||||
to_layer=self.vertical_layer,
|
to_layer=self.vertical_layer,
|
||||||
offset=pin.bc())
|
offset=pin.bc())
|
||||||
else: # port 1, situation different, top need shift
|
else: # port 1, situation different, top need shift
|
||||||
if non_preferred_route:
|
if non_preferred_route:
|
||||||
# Add the horizontal trunk on the vertical layer!
|
# Add the horizontal trunk on the vertical layer!
|
||||||
self.add_path(self.vertical_layer,
|
self.add_path(self.vertical_layer,
|
||||||
[vector(min_x - half_layer_width, trunk_offset.y),
|
[vector(min_x - half_layer_width, trunk_offset.y),
|
||||||
@@ -411,7 +411,7 @@ class channel_route(design):
|
|||||||
pin_pos = pin.uc()
|
pin_pos = pin.uc()
|
||||||
# No bend needed here
|
# No bend needed here
|
||||||
mid = vector(pin_pos.x, trunk_offset.y)
|
mid = vector(pin_pos.x, trunk_offset.y)
|
||||||
self.add_path(self.vertical_layer, [pin_pos, mid])
|
self.add_path(self.vertical_layer, [pin_pos, mid])
|
||||||
self.add_via_stack_center(from_layer=pin.layer,
|
self.add_via_stack_center(from_layer=pin.layer,
|
||||||
to_layer=self.vertical_layer,
|
to_layer=self.vertical_layer,
|
||||||
offset=pin.uc())
|
offset=pin.uc())
|
||||||
@@ -440,7 +440,7 @@ class channel_route(design):
|
|||||||
directions=self.directions)
|
directions=self.directions)
|
||||||
self.add_via_stack_center(from_layer=pin.layer,
|
self.add_via_stack_center(from_layer=pin.layer,
|
||||||
to_layer=self.vertical_layer,
|
to_layer=self.vertical_layer,
|
||||||
offset=pin.uc())
|
offset=pin.uc())
|
||||||
else:
|
else:
|
||||||
pin_pos = pin.center()
|
pin_pos = pin.center()
|
||||||
mid = vector(pin_pos.x - 0.1, trunk_offset.y)
|
mid = vector(pin_pos.x - 0.1, trunk_offset.y)
|
||||||
@@ -451,7 +451,7 @@ class channel_route(design):
|
|||||||
self.add_via_stack_center(from_layer=pin.layer,
|
self.add_via_stack_center(from_layer=pin.layer,
|
||||||
to_layer=self.vertical_layer,
|
to_layer=self.vertical_layer,
|
||||||
offset=pin_pos)
|
offset=pin_pos)
|
||||||
|
|
||||||
def add_horizontal_trunk_route(self,
|
def add_horizontal_trunk_route(self,
|
||||||
pins,
|
pins,
|
||||||
trunk_offset,
|
trunk_offset,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ from openram.base import lef
|
|||||||
from openram.sram_factory import factory
|
from openram.sram_factory import factory
|
||||||
from openram.tech import spice
|
from openram.tech import spice
|
||||||
from openram import OPTS, print_time
|
from openram import OPTS, print_time
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
class sram_1bank(design, verilog, lef):
|
class sram_1bank(design, verilog, lef):
|
||||||
@@ -206,8 +207,8 @@ class sram_1bank(design, verilog, lef):
|
|||||||
|
|
||||||
if not OPTS.is_unit_test:
|
if not OPTS.is_unit_test:
|
||||||
print_time("Submodules", datetime.datetime.now(), start_time)
|
print_time("Submodules", datetime.datetime.now(), start_time)
|
||||||
|
|
||||||
def create_layout(self, position_add=0, mod=0):
|
def create_layout(self, position_add=0, mod=0, route_option="classic"):
|
||||||
""" Layout creation """
|
""" Layout creation """
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
self.place_instances_changeable(position_add=position_add)
|
self.place_instances_changeable(position_add=position_add)
|
||||||
@@ -215,7 +216,7 @@ class sram_1bank(design, verilog, lef):
|
|||||||
print_time("Placement", datetime.datetime.now(), start_time)
|
print_time("Placement", datetime.datetime.now(), start_time)
|
||||||
|
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
self.route_layout(mod=mod)
|
self.route_layout(mod=mod, route_option=route_option)
|
||||||
|
|
||||||
if not OPTS.is_unit_test:
|
if not OPTS.is_unit_test:
|
||||||
print_time("Routing", datetime.datetime.now(), start_time)
|
print_time("Routing", datetime.datetime.now(), start_time)
|
||||||
@@ -239,7 +240,7 @@ class sram_1bank(design, verilog, lef):
|
|||||||
# Only run this if not a unit test, because unit test will also verify it.
|
# Only run this if not a unit test, because unit test will also verify it.
|
||||||
self.DRC_LVS(final_verification=OPTS.route_supplies, force_check=OPTS.check_lvsdrc)
|
self.DRC_LVS(final_verification=OPTS.route_supplies, force_check=OPTS.check_lvsdrc)
|
||||||
print_time("Verification", datetime.datetime.now(), start_time)
|
print_time("Verification", datetime.datetime.now(), start_time)
|
||||||
|
|
||||||
def create_modules(self):
|
def create_modules(self):
|
||||||
debug.error("Must override pure virtual function.", -1)
|
debug.error("Must override pure virtual function.", -1)
|
||||||
|
|
||||||
@@ -319,7 +320,7 @@ class sram_1bank(design, verilog, lef):
|
|||||||
# Grid is left with many top level pins
|
# Grid is left with many top level pins
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def route_escape_pins(self, bbox=None, mod=0):
|
def route_escape_pins(self, bbox=None, mod=0, route_option="classic"):
|
||||||
"""
|
"""
|
||||||
Add the top-level pins for a single bank SRAM with control.
|
Add the top-level pins for a single bank SRAM with control.
|
||||||
"""
|
"""
|
||||||
@@ -361,17 +362,29 @@ class sram_1bank(design, verilog, lef):
|
|||||||
else:
|
else:
|
||||||
for bit in range(self.num_spare_cols):
|
for bit in range(self.num_spare_cols):
|
||||||
pins_to_route.append("spare_wen{0}[{1}]".format(port, bit))
|
pins_to_route.append("spare_wen{0}[{1}]".format(port, bit))
|
||||||
|
|
||||||
from openram.router import signal_escape_router as router
|
if route_option == "classic":
|
||||||
# mod Use for control which edge/position the pins(dout) will be placed
|
from openram.router import signal_escape_router as router
|
||||||
# 0 -> default
|
# mod Use for control which edge/position the pins(dout) will be placed
|
||||||
# 1 -> all top/bottom
|
# 0 -> default
|
||||||
# 2 -> all left/right
|
# 1 -> all top/bottom
|
||||||
rtr = router(layers=self.m3_stack,
|
# 2 -> all left/right
|
||||||
bbox=bbox,
|
rtr = router(layers=self.m3_stack,
|
||||||
design=self,
|
bbox=bbox,
|
||||||
mod=mod)
|
design=self,
|
||||||
rtr.route(pins_to_route)
|
mod=mod)
|
||||||
|
rtr.route(pins_to_route)
|
||||||
|
elif route_option == "fast":
|
||||||
|
# use io_pin_placer
|
||||||
|
# put the IO pins at the edge
|
||||||
|
from openram.router.io_pin_placer import io_pin_placer as placer
|
||||||
|
pl = placer(layers=self.m3_stack,
|
||||||
|
bbox=bbox,
|
||||||
|
design=self)
|
||||||
|
for name in pins_to_route:
|
||||||
|
debug.warning("pins_to_route pins -> {0}".format(name))
|
||||||
|
pl.add_io_pins_connected(pins_to_route)
|
||||||
|
#pl.add_io_pins(pins_to_route)
|
||||||
|
|
||||||
def compute_bus_sizes(self):
|
def compute_bus_sizes(self):
|
||||||
""" Compute the independent bus widths shared between two and four bank SRAMs """
|
""" Compute the independent bus widths shared between two and four bank SRAMs """
|
||||||
@@ -784,7 +797,7 @@ class sram_1bank(design, verilog, lef):
|
|||||||
self.spare_wen_dff_insts = self.create_spare_wen_dff()
|
self.spare_wen_dff_insts = self.create_spare_wen_dff()
|
||||||
else:
|
else:
|
||||||
self.num_spare_cols = 0
|
self.num_spare_cols = 0
|
||||||
|
|
||||||
def place_instances_changeable(self, position_add=0):
|
def place_instances_changeable(self, position_add=0):
|
||||||
"""
|
"""
|
||||||
This places the instances for a single bank SRAM with control
|
This places the instances for a single bank SRAM with control
|
||||||
@@ -849,11 +862,10 @@ class sram_1bank(design, verilog, lef):
|
|||||||
self.add_layout_pins(add_vias=False)
|
self.add_layout_pins(add_vias=False)
|
||||||
self.route_dffs(add_routes=False)
|
self.route_dffs(add_routes=False)
|
||||||
self.remove_layout_pins()
|
self.remove_layout_pins()
|
||||||
|
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
# Add the extra position
|
# Add the extra position
|
||||||
self.data_bus_size[port] += position_add
|
self.data_bus_size[port] += position_add
|
||||||
|
|
||||||
# Re-place with the new channel size
|
# Re-place with the new channel size
|
||||||
self.place_dffs()
|
self.place_dffs()
|
||||||
|
|
||||||
@@ -866,7 +878,7 @@ class sram_1bank(design, verilog, lef):
|
|||||||
x_offset = self.control_logic_insts[port].rx() - self.row_addr_dff_insts[port].width
|
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
|
# 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 = 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_pos[port] = vector(x_offset, y_offset)
|
||||||
self.row_addr_dff_insts[port].place(self.row_addr_pos[port])
|
self.row_addr_dff_insts[port].place(self.row_addr_pos[port])
|
||||||
|
|
||||||
@@ -875,7 +887,7 @@ class sram_1bank(design, verilog, lef):
|
|||||||
# The row address bits are placed above the control logic aligned on the left.
|
# 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
|
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
|
# If it can be placed above the predecoder and below the control logic, do it
|
||||||
y_offset = self.bank.predecoder_bottom
|
y_offset = min(self.control_logic_insts[port].by(), self.bank.predecoder_top)
|
||||||
self.row_addr_pos[port] = vector(x_offset, y_offset)
|
self.row_addr_pos[port] = vector(x_offset, y_offset)
|
||||||
self.row_addr_dff_insts[port].place(self.row_addr_pos[port], mirror="XY")
|
self.row_addr_dff_insts[port].place(self.row_addr_pos[port], mirror="XY")
|
||||||
|
|
||||||
@@ -1061,7 +1073,7 @@ class sram_1bank(design, verilog, lef):
|
|||||||
"spare_wen{0}[{1}]".format(port, bit),
|
"spare_wen{0}[{1}]".format(port, bit),
|
||||||
start_layer=pin_layer)
|
start_layer=pin_layer)
|
||||||
|
|
||||||
def route_layout(self, mod=0):
|
def route_layout(self, mod=0, route_option="classic"):
|
||||||
""" Route a single bank SRAM """
|
""" Route a single bank SRAM """
|
||||||
|
|
||||||
self.route_clk()
|
self.route_clk()
|
||||||
@@ -1085,12 +1097,11 @@ class sram_1bank(design, verilog, lef):
|
|||||||
if OPTS.perimeter_pins:
|
if OPTS.perimeter_pins:
|
||||||
# We now route the escape routes far enough out so that they will
|
# We now route the escape routes far enough out so that they will
|
||||||
# reach past the power ring or stripes on the sides
|
# reach past the power ring or stripes on the sides
|
||||||
self.route_escape_pins(bbox=init_bbox, mod=mod)
|
self.route_escape_pins(bbox=init_bbox, mod=mod, route_option=route_option)
|
||||||
|
|
||||||
if OPTS.route_supplies:
|
if OPTS.route_supplies:
|
||||||
self.route_supplies(init_bbox)
|
self.route_supplies(init_bbox)
|
||||||
|
|
||||||
|
|
||||||
def route_dffs(self, add_routes=True):
|
def route_dffs(self, add_routes=True):
|
||||||
|
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@ class io_pin_placer(router):
|
|||||||
|
|
||||||
# New pins are the side supply pins
|
# New pins are the side supply pins
|
||||||
self.new_pins = {}
|
self.new_pins = {}
|
||||||
|
|
||||||
# added_io_pins
|
# added_io_pins
|
||||||
self.io_pins_added_left = []
|
self.io_pins_added_left = []
|
||||||
self.io_pins_added_right = []
|
self.io_pins_added_right = []
|
||||||
@@ -30,7 +30,7 @@ class io_pin_placer(router):
|
|||||||
|
|
||||||
# fake_pins, use for rename
|
# fake_pins, use for rename
|
||||||
self.io_pins_fake =[]
|
self.io_pins_fake =[]
|
||||||
|
|
||||||
|
|
||||||
def get_closest_edge(self, point):
|
def get_closest_edge(self, point):
|
||||||
""" Return a point's the closest edge and the edge's axis direction. """
|
""" Return a point's the closest edge and the edge's axis direction. """
|
||||||
@@ -52,9 +52,9 @@ class io_pin_placer(router):
|
|||||||
return "right", True
|
return "right", True
|
||||||
return "top", False
|
return "top", False
|
||||||
|
|
||||||
|
|
||||||
def initial_position(self, pins): # pins is list []
|
def initial_position(self, pins): # pins is list []
|
||||||
""" Set the IO pin center at the perimeter """
|
""" Set the IO pin center at the perimeter """
|
||||||
pattern_clk = r'^clk'
|
pattern_clk = r'^clk'
|
||||||
pattern_addr0 = r'^addr0'
|
pattern_addr0 = r'^addr0'
|
||||||
pattern_addr1 = r'^addr1'
|
pattern_addr1 = r'^addr1'
|
||||||
@@ -82,14 +82,14 @@ class io_pin_placer(router):
|
|||||||
vertical = True
|
vertical = True
|
||||||
elif edge == "bottom": # but for big sram, addr0[] may have pins at bottom, which is allowed
|
elif edge == "bottom": # but for big sram, addr0[] may have pins at bottom, which is allowed
|
||||||
vertical = False
|
vertical = False
|
||||||
self.store_position(pin, edge, vertical)
|
self.store_position(pin, edge, vertical)
|
||||||
if re.match(pattern_addr1, pin.name): # all the addr1[] should be placed at right edge
|
if re.match(pattern_addr1, pin.name): # all the addr1[] should be placed at right edge
|
||||||
if edge == "bottom" or edge == "right":
|
if edge == "bottom" or edge == "right":
|
||||||
edge = "right"
|
edge = "right"
|
||||||
vertical = True
|
vertical = True
|
||||||
elif edge == "top": # but for big sram, addr1[] may have pins at top, which is allowed
|
elif edge == "top": # but for big sram, addr1[] may have pins at top, which is allowed
|
||||||
vertical = False
|
vertical = False
|
||||||
self.store_position(pin, edge, vertical)
|
self.store_position(pin, edge, vertical)
|
||||||
if re.match(pattern_din, pin.name): # din
|
if re.match(pattern_din, pin.name): # din
|
||||||
self.store_position(pin, edge, vertical)
|
self.store_position(pin, edge, vertical)
|
||||||
if re.match(pattern_wmask, pin.name): # wmask
|
if re.match(pattern_wmask, pin.name): # wmask
|
||||||
@@ -100,7 +100,7 @@ class io_pin_placer(router):
|
|||||||
self.store_position(pin, edge, vertical)
|
self.store_position(pin, edge, vertical)
|
||||||
if re.match(pattern_web, pin.name): # web
|
if re.match(pattern_web, pin.name): # web
|
||||||
self.store_position(pin, edge, vertical)
|
self.store_position(pin, edge, vertical)
|
||||||
# special handle the dout pins, if r/rw ports
|
# special handle the dout pins, if r/rw ports
|
||||||
for pin in pins:
|
for pin in pins:
|
||||||
if re.match(pattern_dout0, pin.name):
|
if re.match(pattern_dout0, pin.name):
|
||||||
edge = "bottom"
|
edge = "bottom"
|
||||||
@@ -115,7 +115,7 @@ class io_pin_placer(router):
|
|||||||
def check_overlap(self, pin_position, edge):
|
def check_overlap(self, pin_position, edge):
|
||||||
""" Return the suggested position to aviod overlap """
|
""" Return the suggested position to aviod overlap """
|
||||||
ll, ur = self.bbox
|
ll, ur = self.bbox
|
||||||
c = pin_position # original source pin center
|
c = pin_position # original source pin center
|
||||||
offset = 0.95 + 0.19 # FIX: this is the magic number to overcome the ovetflow problem at the boundary, may need a method
|
offset = 0.95 + 0.19 # FIX: this is the magic number to overcome the ovetflow problem at the boundary, may need a method
|
||||||
add_distance = 0
|
add_distance = 0
|
||||||
|
|
||||||
@@ -124,26 +124,26 @@ class io_pin_placer(router):
|
|||||||
pin_to_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_down)
|
pin_to_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_down)
|
||||||
via_to_close = False
|
via_to_close = False
|
||||||
# if cannot direct place below the source pin, need move towards right, and ensure the min. distance between vias
|
# if cannot direct place below the source pin, need move towards right, and ensure the min. distance between vias
|
||||||
while pin_to_close or via_to_close:
|
while pin_to_close or via_to_close:
|
||||||
debug.warning("overlap, changing position")
|
debug.warning("overlap, changing position")
|
||||||
add_distance = add_distance + 0.1
|
add_distance = add_distance + 0.1
|
||||||
fake_center = vector(c.x + add_distance, ll.y - self.track_wire * 2 + offset)
|
fake_center = vector(c.x + add_distance, ll.y - self.track_wire * 2 + offset)
|
||||||
pin_to_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_down)
|
pin_to_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_down)
|
||||||
via_to_close = abs(fake_center.x - c.x) < 0.6
|
via_to_close = abs(fake_center.x - c.x) < 0.6
|
||||||
if edge == "top":
|
if edge == "top":
|
||||||
fake_center = vector(c.x, ur.y + self.track_wire * 2 - offset)
|
fake_center = vector(c.x, ur.y + self.track_wire * 2 - offset)
|
||||||
pin_to_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_up)
|
pin_to_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_up)
|
||||||
via_to_close = False
|
via_to_close = False
|
||||||
# if cannot direct place below the source pin, need move towards right, and ensure the min. distance between vias
|
# if cannot direct place below the source pin, need move towards right, and ensure the min. distance between vias
|
||||||
while pin_to_close or via_to_close:
|
while pin_to_close or via_to_close:
|
||||||
debug.warning("overlap, changing position")
|
debug.warning("overlap, changing position")
|
||||||
add_distance = add_distance + 0.1
|
add_distance = add_distance + 0.1
|
||||||
fake_center = vector(c.x + add_distance, ur.y + self.track_wire * 2 - offset)
|
fake_center = vector(c.x + add_distance, ur.y + self.track_wire * 2 - offset)
|
||||||
pin_to_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_up)
|
pin_to_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_up)
|
||||||
via_to_close = abs(fake_center.x - c.x) < 0.6
|
via_to_close = abs(fake_center.x - c.x) < 0.6
|
||||||
|
|
||||||
|
return fake_center
|
||||||
|
|
||||||
return fake_center
|
|
||||||
|
|
||||||
|
|
||||||
def store_dout_position(self, pin, edge, vertical):
|
def store_dout_position(self, pin, edge, vertical):
|
||||||
pin_position = pin.center()
|
pin_position = pin.center()
|
||||||
@@ -151,14 +151,14 @@ class io_pin_placer(router):
|
|||||||
# store the center position, rect, layer of fake pin, here make sure the pin in the gds will be big enough
|
# store the center position, rect, layer of fake pin, here make sure the pin in the gds will be big enough
|
||||||
layer = self.get_layer(int(not vertical))
|
layer = self.get_layer(int(not vertical))
|
||||||
half_wire_vector = vector([self.half_wire] * 2)
|
half_wire_vector = vector([self.half_wire] * 2)
|
||||||
nll = pin_position - half_wire_vector - half_wire_vector
|
nll = pin_position - half_wire_vector - half_wire_vector
|
||||||
nur = pin_position + half_wire_vector + half_wire_vector
|
nur = pin_position + half_wire_vector + half_wire_vector
|
||||||
rect = [nll, nur]
|
rect = [nll, nur]
|
||||||
#fake_pin = [pin.name() + "_" + "fake", pin_position, rect, layer]
|
#fake_pin = [pin.name() + "_" + "fake", pin_position, rect, layer]
|
||||||
fake_pin = graph_shape(name=pin.name + "_" + "fake",
|
fake_pin = graph_shape(name=pin.name + "_" + "fake",
|
||||||
rect=rect,
|
rect=rect,
|
||||||
layer_name_pp=layer)
|
layer_name_pp=layer)
|
||||||
|
|
||||||
if edge == "left":
|
if edge == "left":
|
||||||
self.io_pins_added_left.append(fake_pin)
|
self.io_pins_added_left.append(fake_pin)
|
||||||
elif edge == "bottom":
|
elif edge == "bottom":
|
||||||
@@ -168,10 +168,10 @@ class io_pin_placer(router):
|
|||||||
elif edge == "top":
|
elif edge == "top":
|
||||||
self.io_pins_added_up.append(fake_pin)
|
self.io_pins_added_up.append(fake_pin)
|
||||||
|
|
||||||
self.io_pins_fake.append(fake_pin)
|
self.io_pins_fake.append(fake_pin)
|
||||||
debug.warning("pin added: {0}".format(fake_pin))
|
debug.warning("pin added: {0}".format(fake_pin))
|
||||||
|
|
||||||
|
|
||||||
def store_position(self, pin, edge, vertical): # also need to store the source pin
|
def store_position(self, pin, edge, vertical): # also need to store the source pin
|
||||||
ll, ur = self.bbox
|
ll, ur = self.bbox
|
||||||
c = pin.center()
|
c = pin.center()
|
||||||
@@ -197,14 +197,14 @@ class io_pin_placer(router):
|
|||||||
# store the center position, rect, layer of fake pin, here make sure the pin in the gds will be big enough
|
# store the center position, rect, layer of fake pin, here make sure the pin in the gds will be big enough
|
||||||
layer = self.get_layer(int(not vertical))
|
layer = self.get_layer(int(not vertical))
|
||||||
half_wire_vector = vector([self.half_wire] * 2)
|
half_wire_vector = vector([self.half_wire] * 2)
|
||||||
nll = fake_center - half_wire_vector - half_wire_vector
|
nll = fake_center - half_wire_vector - half_wire_vector
|
||||||
nur = fake_center + half_wire_vector + half_wire_vector
|
nur = fake_center + half_wire_vector + half_wire_vector
|
||||||
rect = [nll, nur]
|
rect = [nll, nur]
|
||||||
#fake_pin = [pin.name() + "_" + "fake", fake_center, rect, layer]
|
#fake_pin = [pin.name() + "_" + "fake", fake_center, rect, layer]
|
||||||
fake_pin = graph_shape(name=pin.name + "_" + "fake",
|
fake_pin = graph_shape(name=pin.name + "_" + "fake",
|
||||||
rect=rect,
|
rect=rect,
|
||||||
layer_name_pp=layer)
|
layer_name_pp=layer)
|
||||||
|
|
||||||
if edge == "left":
|
if edge == "left":
|
||||||
self.io_pins_added_left.append(fake_pin)
|
self.io_pins_added_left.append(fake_pin)
|
||||||
elif edge == "bottom":
|
elif edge == "bottom":
|
||||||
@@ -213,111 +213,9 @@ class io_pin_placer(router):
|
|||||||
self.io_pins_added_right.append(fake_pin)
|
self.io_pins_added_right.append(fake_pin)
|
||||||
elif edge == "top":
|
elif edge == "top":
|
||||||
self.io_pins_added_up.append(fake_pin)
|
self.io_pins_added_up.append(fake_pin)
|
||||||
|
|
||||||
self.io_pins_fake.append(fake_pin)
|
self.io_pins_fake.append(fake_pin)
|
||||||
debug.warning("pin added: {0}".format(fake_pin))
|
debug.warning("pin added: {0}".format(fake_pin))
|
||||||
|
|
||||||
|
|
||||||
def create_fake_pin(self, pin):
|
|
||||||
""" Create a fake pin on the perimeter orthogonal to the given pin. """
|
|
||||||
|
|
||||||
ll, ur = self.bbox
|
|
||||||
c = pin.center()
|
|
||||||
print("inside pin name")
|
|
||||||
print("----------------------------------------------------------")
|
|
||||||
print(pin.name)
|
|
||||||
# Find the closest edge
|
|
||||||
edge, vertical = self.get_closest_edge(c)
|
|
||||||
# Relocate the pin position of addr/dout
|
|
||||||
pattern_addr = r'^addr'
|
|
||||||
pattern_dout = r'^dout'
|
|
||||||
if re.match(pattern_addr, pin.name):# all the addr[] should be placed at vertical edge
|
|
||||||
if edge == "top" or edge == "left":
|
|
||||||
edge = "left"
|
|
||||||
vertical = True
|
|
||||||
elif edge == "bottom" or edge == "right":
|
|
||||||
edge = "right"
|
|
||||||
vertical = True
|
|
||||||
|
|
||||||
if re.match(pattern_dout, pin.name):# all the dout[] should be placed at horizontal edge
|
|
||||||
if edge == "bottom" or edge == "right":
|
|
||||||
edge = "bottom"
|
|
||||||
vertical = False
|
|
||||||
elif edge == "top" or edge == "left":
|
|
||||||
edge = "top"
|
|
||||||
vertical = False
|
|
||||||
|
|
||||||
offset = 0.95 + 0.19 # FIX: this is the magic number to overcome the ovetflow problem at the boundary, may need a method
|
|
||||||
add_distance = 0
|
|
||||||
# Keep the fake pin out of the SRAM layout are so that they won't be
|
|
||||||
# blocked by previous signals if they're on the same orthogonal line
|
|
||||||
if edge == "left":
|
|
||||||
fake_center = vector(ll.x - self.track_wire * 2 + offset, c.y)
|
|
||||||
is_too_close = any(abs(pin_added.center().y - fake_center.y) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_left)
|
|
||||||
while is_too_close:
|
|
||||||
debug.warning("overlap, changing position")
|
|
||||||
add_distance = add_distance + 0.1#+ 0.4 + self.half_wire * 4
|
|
||||||
fake_center = vector(ll.x - self.track_wire * 2 + offset, c.y + add_distance)
|
|
||||||
is_too_close = any(abs(pin_added.center().y - fake_center.y) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_left)
|
|
||||||
|
|
||||||
if edge == "bottom":
|
|
||||||
fake_center = vector(c.x, ll.y - self.track_wire * 2 + offset)
|
|
||||||
is_too_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_down)
|
|
||||||
while is_too_close:
|
|
||||||
debug.warning("overlap, changing position")
|
|
||||||
add_distance = add_distance + 0.1#0.4 + self.half_wire * 4
|
|
||||||
fake_center = vector(c.x + add_distance, ll.y - self.track_wire * 2 + offset)
|
|
||||||
is_too_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_down)
|
|
||||||
|
|
||||||
if edge == "right":
|
|
||||||
fake_center = vector(ur.x + self.track_wire * 2 - offset, c.y)
|
|
||||||
is_too_close = any(abs(pin_added.center().y - fake_center.y) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_right)
|
|
||||||
while is_too_close:
|
|
||||||
debug.warning("overlap, changing position")
|
|
||||||
add_distance = add_distance + 0.1#0.4 + self.half_wire * 4
|
|
||||||
fake_center = vector(ur.x + self.track_wire * 2 - offset, c.y + add_distance)
|
|
||||||
# debug
|
|
||||||
for pin_added in self.io_pins_added_right:
|
|
||||||
dis = abs(pin_added.center().y - fake_center.y)
|
|
||||||
debug.warning("current position is {0}".format(fake_center))
|
|
||||||
debug.warning("distance from {0} is {1}".format(pin_added, dis))
|
|
||||||
debug.warning("must disrance is {0}".format(0.4 + self.half_wire * 4))
|
|
||||||
is_too_close = any(abs(pin_added.center().y - fake_center.y) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_right)
|
|
||||||
|
|
||||||
if edge == "top":
|
|
||||||
fake_center = vector(c.x, ur.y + self.track_wire * 2 - offset)
|
|
||||||
is_too_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_up)
|
|
||||||
while is_too_close:
|
|
||||||
debug.warning("overlap, changing position")
|
|
||||||
add_distance = add_distance + 0.1#0.4 + self.half_wire * 4
|
|
||||||
fake_center = vector(c.x + add_distance, ur.y + self.track_wire * 2 - offset)
|
|
||||||
is_too_close = any(abs(pin_added.center().x - fake_center.x) < (0.4 + self.half_wire * 4)for pin_added in self.io_pins_added_up)
|
|
||||||
|
|
||||||
# Create the fake pin shape, here make sure the pin in the gds will be big enough
|
|
||||||
layer = self.get_layer(int(not vertical))
|
|
||||||
half_wire_vector = vector([self.half_wire] * 2)
|
|
||||||
nll = fake_center - half_wire_vector - half_wire_vector
|
|
||||||
nur = fake_center + half_wire_vector + half_wire_vector
|
|
||||||
|
|
||||||
rect = [nll, nur]
|
|
||||||
pin = graph_shape(name=pin.name + "_" + "fake",
|
|
||||||
rect=rect,
|
|
||||||
layer_name_pp=layer)
|
|
||||||
print("this create_fake_pin")
|
|
||||||
print(pin.name)
|
|
||||||
print(pin.center)
|
|
||||||
|
|
||||||
if edge == "left":
|
|
||||||
self.io_pins_added_left.append(pin)
|
|
||||||
elif edge == "bottom":
|
|
||||||
self.io_pins_added_down.append(pin)
|
|
||||||
elif edge == "right":
|
|
||||||
self.io_pins_added_right.append(pin)
|
|
||||||
elif edge == "top":
|
|
||||||
self.io_pins_added_up.append(pin)
|
|
||||||
debug.warning("pin added: {0}".format(pin))
|
|
||||||
|
|
||||||
return pin, vertical, add_distance
|
|
||||||
|
|
||||||
|
|
||||||
def add_io_pins(self, pin_names):
|
def add_io_pins(self, pin_names):
|
||||||
@@ -336,13 +234,13 @@ class io_pin_placer(router):
|
|||||||
for name in self.pins:
|
for name in self.pins:
|
||||||
pin = next(iter(self.pins[name]))
|
pin = next(iter(self.pins[name]))
|
||||||
pin_list.append(pin)
|
pin_list.append(pin)
|
||||||
|
|
||||||
self.initial_position(pin_list)
|
self.initial_position(pin_list)
|
||||||
|
|
||||||
# Change IO pin names, which means "internal name" will be used, and internal io pins will not have label such as "dout0[0]"
|
# Change IO pin names, which means "internal name" will be used, and internal io pins will not have label such as "dout0[0]"
|
||||||
self.replace_layout_pins(pin_names)
|
self.replace_layout_pins(pin_names)
|
||||||
|
|
||||||
|
|
||||||
def add_io_pins_connected(self, pin_names):
|
def add_io_pins_connected(self, pin_names):
|
||||||
""" Add IO pins on the edges WITH routing them. """
|
""" Add IO pins on the edges WITH routing them. """
|
||||||
debug.info(1, "Adding IO pins on the perimeter...")
|
debug.info(1, "Adding IO pins on the perimeter...")
|
||||||
@@ -361,9 +259,9 @@ class io_pin_placer(router):
|
|||||||
pin = next(iter(self.pins[name]))
|
pin = next(iter(self.pins[name]))
|
||||||
pin_list.append(pin)
|
pin_list.append(pin)
|
||||||
debug.warning("the pins in self.pins -> {0}".format(name))
|
debug.warning("the pins in self.pins -> {0}".format(name))
|
||||||
|
|
||||||
self.initial_position(pin_list)
|
self.initial_position(pin_list)
|
||||||
|
|
||||||
# add fake io pins at the perimeter, which will be used for routing
|
# add fake io pins at the perimeter, which will be used for routing
|
||||||
for fake_pin in self.io_pins_fake:
|
for fake_pin in self.io_pins_fake:
|
||||||
self.design.add_layout_pin(text=fake_pin.name,
|
self.design.add_layout_pin(text=fake_pin.name,
|
||||||
@@ -372,7 +270,7 @@ class io_pin_placer(router):
|
|||||||
width=fake_pin.width(),
|
width=fake_pin.width(),
|
||||||
height=fake_pin.height())
|
height=fake_pin.height())
|
||||||
|
|
||||||
# connect the source_pin and io_pin(target)
|
# connect the source_pin and io_pin(target)
|
||||||
self.connect_pins(pin_names)
|
self.connect_pins(pin_names)
|
||||||
|
|
||||||
# remove the fake pin before change the name, in order to avoid possible problem
|
# remove the fake pin before change the name, in order to avoid possible problem
|
||||||
@@ -381,8 +279,8 @@ class io_pin_placer(router):
|
|||||||
|
|
||||||
# Change IO pin names, which means "internal name" will be used, and internal io pins will not have label such as "dout0[0]"
|
# Change IO pin names, which means "internal name" will be used, and internal io pins will not have label such as "dout0[0]"
|
||||||
self.replace_layout_pins(pin_names)
|
self.replace_layout_pins(pin_names)
|
||||||
|
|
||||||
|
|
||||||
def connect_pins(self, pin_names): # pin_names should be a list
|
def connect_pins(self, pin_names): # pin_names should be a list
|
||||||
""" Add IO pins on the edges, and connect them to the internal one, not-graph like process """
|
""" Add IO pins on the edges, and connect them to the internal one, not-graph like process """
|
||||||
debug.info(1, "connecting to io pins...")
|
debug.info(1, "connecting to io pins...")
|
||||||
@@ -392,18 +290,18 @@ class io_pin_placer(router):
|
|||||||
source_pin = next(iter(self.pins[pin_name]))
|
source_pin = next(iter(self.pins[pin_name]))
|
||||||
for fake_pin in self.io_pins_fake:
|
for fake_pin in self.io_pins_fake:
|
||||||
if pin_name + "_" + "fake" == fake_pin.name:
|
if pin_name + "_" + "fake" == fake_pin.name:
|
||||||
target_pin = fake_pin
|
target_pin = fake_pin
|
||||||
break
|
break
|
||||||
# special hanlde dout pins
|
# special hanlde dout pins
|
||||||
if re.match(pattern_dout, pin_name):
|
if re.match(pattern_dout, pin_name):
|
||||||
number_str = re.findall(r'\[(\d+)\]', pin_name)
|
number_str = re.findall(r'\[(\d+)\]', pin_name)
|
||||||
if number_str:
|
if number_str:
|
||||||
number = int(number_str[0])
|
number = int(number_str[0])
|
||||||
if number % 2 == 0:
|
if number % 2 == 0:
|
||||||
is_up = True
|
is_up = True
|
||||||
else:
|
else:
|
||||||
is_up = False
|
is_up = False
|
||||||
point_list = self.decide_point(source_pin, target_pin, is_up)
|
point_list = self.decide_point(source_pin, target_pin, is_up)
|
||||||
self.add_wire(point_list)
|
self.add_wire(point_list)
|
||||||
# other pins
|
# other pins
|
||||||
else:
|
else:
|
||||||
@@ -414,7 +312,7 @@ class io_pin_placer(router):
|
|||||||
self.add_wire(point_list)
|
self.add_wire(point_list)
|
||||||
|
|
||||||
|
|
||||||
def add_wire(self, point_list):
|
def add_wire(self, point_list):
|
||||||
if len(point_list) == 2:
|
if len(point_list) == 2:
|
||||||
# direct connect
|
# direct connect
|
||||||
self.add_line(point_list[0], point_list[1])
|
self.add_line(point_list[0], point_list[1])
|
||||||
@@ -425,32 +323,32 @@ class io_pin_placer(router):
|
|||||||
self.add_line(point_list[1], point_list[2])
|
self.add_line(point_list[1], point_list[2])
|
||||||
self.add_via(point_list[2])
|
self.add_via(point_list[2])
|
||||||
self.add_line(point_list[2], point_list[3])
|
self.add_line(point_list[2], point_list[3])
|
||||||
|
|
||||||
|
|
||||||
def add_line(self, point_1, point_2):
|
def add_line(self, point_1, point_2):
|
||||||
if round(point_1.y, 3) == round(point_2.y, 3):
|
if round(point_1.y, 3) == round(point_2.y, 3):
|
||||||
# horizontal m3
|
# horizontal m3
|
||||||
self.design.add_path(self.get_layer(False), [point_1, point_2])
|
self.design.add_path(self.get_layer(False), [point_1, point_2])
|
||||||
else:
|
else:
|
||||||
# vertical m4
|
# vertical m4
|
||||||
self.design.add_path(self.get_layer(True), [point_1, point_2])
|
self.design.add_path(self.get_layer(True), [point_1, point_2])
|
||||||
|
|
||||||
|
|
||||||
def add_via(self, point):
|
def add_via(self, point):
|
||||||
# currently only m3-m4 vias are supported in this method
|
# currently only m3-m4 vias are supported in this method
|
||||||
# usd in order to make "z" shape routing only
|
# usd in order to make "z" shape routing only
|
||||||
self.design.add_via_stack_center(from_layer=self.get_layer(False),
|
self.design.add_via_stack_center(from_layer=self.get_layer(False),
|
||||||
to_layer=self.get_layer(True),
|
to_layer=self.get_layer(True),
|
||||||
offset=point)
|
offset=point)
|
||||||
|
|
||||||
|
|
||||||
def add_start_via(self, point):
|
def add_start_via(self, point):
|
||||||
# currently only m3-m4 vias are supported in this method
|
# currently only m3-m4 vias are supported in this method
|
||||||
# used in source_pin only
|
# used in source_pin only
|
||||||
self.design.add_via_stack_center(from_layer=self.get_layer(False),
|
self.design.add_via_stack_center(from_layer=self.get_layer(False),
|
||||||
to_layer=self.get_layer(True),
|
to_layer=self.get_layer(True),
|
||||||
offset=point)
|
offset=point)
|
||||||
|
|
||||||
|
|
||||||
def add_big_plate(self, layer, offset, width, height):
|
def add_big_plate(self, layer, offset, width, height):
|
||||||
# add rectagle at internal source pin, which avoid jog/non-preferred routing, but could implement shift-routing
|
# add rectagle at internal source pin, which avoid jog/non-preferred routing, but could implement shift-routing
|
||||||
@@ -460,19 +358,19 @@ class io_pin_placer(router):
|
|||||||
offset=offset,
|
offset=offset,
|
||||||
width=width,
|
width=width,
|
||||||
height=height)
|
height=height)
|
||||||
|
|
||||||
|
|
||||||
def decide_point(self, source_pin, target_pin, is_up=False):
|
def decide_point(self, source_pin, target_pin, is_up=False):
|
||||||
ll, ur = self.bbox
|
ll, ur = self.bbox
|
||||||
offset = 0.95 + 0.19 # FIX: this is the magic number to overcome the ovetflow problem at the boundary, may need a method
|
offset = 0.95 + 0.19 # FIX: this is the magic number to overcome the ovetflow problem at the boundary, may need a method
|
||||||
pattern_clk = r'^clk'
|
pattern_clk = r'^clk'
|
||||||
pattern_csb = r'^csb'
|
pattern_csb = r'^csb'
|
||||||
# internal -> left
|
# internal -> left
|
||||||
if round(target_pin.center().x, 3) == round(ll.x - self.track_wire * 2 + offset, 3):
|
if round(target_pin.center().x, 3) == round(ll.x - self.track_wire * 2 + offset, 3):
|
||||||
# special handle clk0
|
# special handle clk0
|
||||||
if re.match(pattern_clk, source_pin.name):
|
if re.match(pattern_clk, source_pin.name):
|
||||||
return [vector(source_pin.rc().x, source_pin.rc().y + 0.32), target_pin.lc()]# 0.32 should be same in initial_position
|
return [vector(source_pin.rc().x, source_pin.rc().y + 0.32), target_pin.lc()]# 0.32 should be same in initial_position
|
||||||
# special handel csb0
|
# special handel csb0
|
||||||
elif re.match(pattern_csb, source_pin.name):
|
elif re.match(pattern_csb, source_pin.name):
|
||||||
return [vector(source_pin.rc().x, source_pin.rc().y - 0.32), target_pin.lc()]# 0.32 should be same in initial_position
|
return [vector(source_pin.rc().x, source_pin.rc().y - 0.32), target_pin.lc()]# 0.32 should be same in initial_position
|
||||||
else:
|
else:
|
||||||
@@ -482,11 +380,11 @@ class io_pin_placer(router):
|
|||||||
if round(target_pin.center().x, 3) == round(ur.x + self.track_wire * 2 - offset, 3):
|
if round(target_pin.center().x, 3) == round(ur.x + self.track_wire * 2 - offset, 3):
|
||||||
# special handel clk1
|
# special handel clk1
|
||||||
if re.match(pattern_clk, source_pin.name):
|
if re.match(pattern_clk, source_pin.name):
|
||||||
return [vector(source_pin.lc().x, source_pin.lc().y - 0.32), target_pin.rc()]# 0.32 should be same in initial_position
|
return [vector(source_pin.lc().x, source_pin.lc().y - 0.32), target_pin.rc()]# 0.32 should be same in initial_position
|
||||||
# special handle csb0
|
# special handle csb0
|
||||||
elif re.match(pattern_csb, source_pin.name):
|
elif re.match(pattern_csb, source_pin.name):
|
||||||
return [vector(source_pin.lc().x, source_pin.lc().y + 0.32), target_pin.rc()]# 0.32 should be same in initial_position
|
return [vector(source_pin.lc().x, source_pin.lc().y + 0.32), target_pin.rc()]# 0.32 should be same in initial_position
|
||||||
else:
|
else:
|
||||||
# direct connect possible
|
# direct connect possible
|
||||||
return [source_pin.lc(), target_pin.rc()]
|
return [source_pin.lc(), target_pin.rc()]
|
||||||
# internal -> top, need to add start_via m3->m4
|
# internal -> top, need to add start_via m3->m4
|
||||||
@@ -499,13 +397,13 @@ class io_pin_placer(router):
|
|||||||
# need intermediate point
|
# 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
|
||||||
is_up = not is_up# Be attention, for channel at the top, the is_up should be inverted! Otherwise will cause overlap!
|
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:
|
if is_up:
|
||||||
via_basic_y = via_basic_y + 0.5
|
via_basic_y = via_basic_y + 0.5
|
||||||
else:
|
else:
|
||||||
via_basic_y = via_basic_y - 0.5
|
via_basic_y = via_basic_y - 0.5
|
||||||
point_1 = vector(source_pin.center().x, via_basic_y)
|
point_1 = vector(source_pin.center().x, via_basic_y)
|
||||||
point_2 = vector(target_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()]
|
return [source_pin.bc(), point_1, point_2, target_pin.uc()]
|
||||||
# internal -> bottom, need to add start_via m3->m4
|
# internal -> bottom, need to add start_via m3->m4
|
||||||
if round(target_pin.center().y, 3) == round(ll.y - self.track_wire * 2 + offset, 3):
|
if round(target_pin.center().y, 3) == round(ll.y - self.track_wire * 2 + offset, 3):
|
||||||
self.add_start_via(source_pin.center())
|
self.add_start_via(source_pin.center())
|
||||||
@@ -521,14 +419,14 @@ class io_pin_placer(router):
|
|||||||
via_basic_y = via_basic_y - 0.5
|
via_basic_y = via_basic_y - 0.5
|
||||||
point_1 = vector(source_pin.center().x, via_basic_y)
|
point_1 = vector(source_pin.center().x, via_basic_y)
|
||||||
point_2 = vector(target_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()]
|
return [source_pin.uc(), point_1, point_2, target_pin.bc()]
|
||||||
|
|
||||||
|
|
||||||
def remove_io_pins(self, pin_name):
|
def remove_io_pins(self, pin_name):
|
||||||
# remove io pin in gds, so we could reroute
|
# remove io pin in gds, so we could reroute
|
||||||
self.design.remove_layout_pin(pin_name)
|
self.design.remove_layout_pin(pin_name)
|
||||||
|
|
||||||
|
|
||||||
def replace_layout_pins(self, pin_names):
|
def replace_layout_pins(self, pin_names):
|
||||||
""" Change the IO pin names with new ones around the perimeter. """
|
""" Change the IO pin names with new ones around the perimeter. """
|
||||||
for pin_name in pin_names:
|
for pin_name in pin_names:
|
||||||
@@ -537,8 +435,7 @@ class io_pin_placer(router):
|
|||||||
if pin.name == perimeter_pin_name:
|
if pin.name == perimeter_pin_name:
|
||||||
perimeter_pin = pin
|
perimeter_pin = pin
|
||||||
self.design.replace_layout_pin(pin_name, perimeter_pin)
|
self.design.replace_layout_pin(pin_name, perimeter_pin)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ class signal_escape_router(router):
|
|||||||
|
|
||||||
# New pins are the side supply pins
|
# New pins are the side supply pins
|
||||||
self.new_pins = {}
|
self.new_pins = {}
|
||||||
|
|
||||||
# Use for add distance of dout pins at the perimeter
|
# Use for add distance of dout pins at the perimeter
|
||||||
self.distance_right = 0
|
self.distance_right = 0
|
||||||
|
|
||||||
self.distance_left = 0
|
self.distance_left = 0
|
||||||
|
|
||||||
# Use for control which edge/position the pins(dout) will be placed
|
# Use for control which edge/position the pins(dout) will be placed
|
||||||
# 0 -> default
|
# 0 -> default
|
||||||
# 1 -> all top/bottom
|
# 1 -> all top/bottom
|
||||||
# 2 -> all left/right
|
# 2 -> all left/right
|
||||||
@@ -206,16 +206,16 @@ class signal_escape_router(router):
|
|||||||
fake_center = vector(ur.x + self.track_wire * 2, c.y)
|
fake_center = vector(ur.x + self.track_wire * 2, c.y)
|
||||||
if edge == "top":
|
if edge == "top":
|
||||||
fake_center = vector(c.x, ur.y + self.track_wire * 2)
|
fake_center = vector(c.x, ur.y + self.track_wire * 2)
|
||||||
|
|
||||||
# relocate the pin position
|
# relocate the pin position
|
||||||
pattern = r'^dout'
|
pattern = r'^dout'
|
||||||
if re.match(pattern, pin.name):
|
if re.match(pattern, pin.name):
|
||||||
|
|
||||||
if self.state_mod == 0:
|
if self.state_mod == 0:
|
||||||
pass# do not change, default
|
pass# do not change, default
|
||||||
|
|
||||||
elif self.state_mod == 1: # all top/bottom
|
elif self.state_mod == 1: # all top/bottom
|
||||||
if edge == "right":
|
if edge == "right":
|
||||||
vertical = False
|
vertical = False
|
||||||
fake_center = vector(c.x, ll.y - self.track_wire * 2)
|
fake_center = vector(c.x, ll.y - self.track_wire * 2)
|
||||||
self.distance_right += 1
|
self.distance_right += 1
|
||||||
@@ -223,8 +223,8 @@ class signal_escape_router(router):
|
|||||||
if edge == "left":
|
if edge == "left":
|
||||||
vertical = False
|
vertical = False
|
||||||
fake_center = vector(c.x, ll.y + self.track_wire * 2)
|
fake_center = vector(c.x, ll.y + self.track_wire * 2)
|
||||||
self.distance_left += 1
|
self.distance_left += 1
|
||||||
|
|
||||||
elif self.state_mod == 2: # all left/right
|
elif self.state_mod == 2: # all left/right
|
||||||
if (edge == "bottom") or (edge == "right"):# change to the east
|
if (edge == "bottom") or (edge == "right"):# change to the east
|
||||||
vertical = True
|
vertical = True
|
||||||
@@ -234,10 +234,10 @@ class signal_escape_router(router):
|
|||||||
if (edge == "top") or (edge == "left"):# change to the west
|
if (edge == "top") or (edge == "left"):# change to the west
|
||||||
vertical = True
|
vertical = True
|
||||||
fake_center = vector(ll.x - self.track_wire * 2, ur.y - 30 - self.distance_left)
|
fake_center = vector(ll.x - self.track_wire * 2, ur.y - 30 - self.distance_left)
|
||||||
self.distance_left += 1
|
self.distance_left += 1
|
||||||
else:
|
else:
|
||||||
debug.error("wrong state mod!", -1)
|
debug.error("wrong state mod!", -1)
|
||||||
|
|
||||||
# Create the fake pin shape
|
# Create the fake pin shape
|
||||||
layer = self.get_layer(int(not vertical))
|
layer = self.get_layer(int(not vertical))
|
||||||
half_wire_vector = vector([self.half_wire] * 2)
|
half_wire_vector = vector([self.half_wire] * 2)
|
||||||
|
|||||||
+64
-57
@@ -20,7 +20,7 @@ class sram():
|
|||||||
results.
|
results.
|
||||||
We can later add visualizer and other high-level functions as needed.
|
We can later add visualizer and other high-level functions as needed.
|
||||||
"""
|
"""
|
||||||
def __init__(self, sram_config=None, name=None):
|
def __init__(self, sram_config=None, name=None, route_option="classic"):
|
||||||
|
|
||||||
# Create default configs if custom config isn't provided
|
# Create default configs if custom config isn't provided
|
||||||
if sram_config is None:
|
if sram_config is None:
|
||||||
@@ -48,67 +48,74 @@ class sram():
|
|||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.route_option = route_option # "classic" or "fast"
|
||||||
|
|
||||||
from openram.modules.sram_1bank import sram_1bank as sram
|
from openram.modules.sram_1bank import sram_1bank as sram
|
||||||
|
|
||||||
num_ports = OPTS.num_rw_ports + OPTS.num_r_ports + OPTS.num_w_ports
|
num_ports = OPTS.num_rw_ports + OPTS.num_r_ports + OPTS.num_w_ports
|
||||||
self.s = sram(name, sram_config)
|
self.s = sram(name, sram_config)
|
||||||
self.s.create_netlist()# not placed & routed jet
|
self.s.create_netlist()# not placed & routed jet
|
||||||
cur_state = "IDLE"
|
|
||||||
if not OPTS.netlist_only:
|
|
||||||
i = 0
|
|
||||||
while i < (OPTS.word_size + 100):
|
|
||||||
|
|
||||||
debug.warning("current state: state = {0}".format(cur_state))
|
|
||||||
|
|
||||||
if cur_state == "IDLE":# default, fisrt try
|
|
||||||
try:
|
|
||||||
self.s.create_layout(position_add=i)
|
|
||||||
except AssertionError as e:
|
|
||||||
cur_state = "ALL_TOP_BOTTOM"
|
|
||||||
del self.s
|
|
||||||
self.s = sram(name, sram_config)
|
|
||||||
self.s.create_netlist()
|
|
||||||
if num_ports > 1:
|
|
||||||
i = 16
|
|
||||||
else:
|
|
||||||
i = 0
|
|
||||||
continue
|
|
||||||
cur_state = "FINISH"
|
|
||||||
break
|
|
||||||
|
|
||||||
elif cur_state == "ALL_TOP_BOTTOM":
|
# choose the routung method, maze router or constructive
|
||||||
try:
|
if self.route_option == "classic":
|
||||||
self.s.create_layout(position_add=i, mod=1)
|
cur_state = "IDLE"
|
||||||
except AssertionError as e:
|
if not OPTS.netlist_only:
|
||||||
cur_state = "ALL_LEFT_RIGHT"
|
i = 0
|
||||||
i = OPTS.word_size + 24
|
while i < (OPTS.word_size + 100):
|
||||||
del self.s
|
|
||||||
self.s = sram(name, sram_config)
|
debug.warning("current state: state = {0}".format(cur_state))
|
||||||
self.s.create_netlist()
|
|
||||||
continue
|
if cur_state == "IDLE":# default, fisrt try
|
||||||
cur_state = "FINISH"
|
try:
|
||||||
break
|
self.s.create_layout(position_add=i)
|
||||||
|
except AssertionError as e:
|
||||||
elif cur_state == "ALL_LEFT_RIGHT":
|
cur_state = "ALL_TOP_BOTTOM"
|
||||||
try:
|
del self.s
|
||||||
self.s.create_layout(position_add=i, mod=2)
|
self.s = sram(name, sram_config)
|
||||||
except AssertionError as e:
|
self.s.create_netlist()
|
||||||
cur_state = "ALL_LEFT_RIGHT"
|
if num_ports > 1:
|
||||||
i = i + 1
|
i = 16
|
||||||
if i == (99 + OPTS.word_size):# failed in rounting
|
else:
|
||||||
debug.error("Failed in rounting", -1)
|
i = 0
|
||||||
break
|
continue
|
||||||
del self.s
|
cur_state = "FINISH"
|
||||||
self.s = sram(name, sram_config)
|
break
|
||||||
self.s.create_netlist()
|
|
||||||
continue
|
elif cur_state == "ALL_TOP_BOTTOM":
|
||||||
cur_state = "FINISH"
|
try:
|
||||||
break
|
self.s.create_layout(position_add=i, mod=1)
|
||||||
else:
|
except AssertionError as e:
|
||||||
cur_state = "FINISH"
|
cur_state = "ALL_LEFT_RIGHT"
|
||||||
break
|
i = OPTS.word_size + 24
|
||||||
|
del self.s
|
||||||
|
self.s = sram(name, sram_config)
|
||||||
|
self.s.create_netlist()
|
||||||
|
continue
|
||||||
|
cur_state = "FINISH"
|
||||||
|
break
|
||||||
|
|
||||||
|
elif cur_state == "ALL_LEFT_RIGHT":
|
||||||
|
try:
|
||||||
|
self.s.create_layout(position_add=i, mod=2)
|
||||||
|
except AssertionError as e:
|
||||||
|
cur_state = "ALL_LEFT_RIGHT"
|
||||||
|
i = i + 1
|
||||||
|
if i == (99 + OPTS.word_size):# failed in rounting
|
||||||
|
debug.error("Failed in rounting", -1)
|
||||||
|
break
|
||||||
|
del self.s
|
||||||
|
self.s = sram(name, sram_config)
|
||||||
|
self.s.create_netlist()
|
||||||
|
continue
|
||||||
|
cur_state = "FINISH"
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
cur_state = "FINISH"
|
||||||
|
break
|
||||||
|
elif self.route_option == "fast":
|
||||||
|
if not OPTS.netlist_only:
|
||||||
|
self.s.create_layout(route_option=route_option)
|
||||||
|
|
||||||
if not OPTS.is_unit_test:
|
if not OPTS.is_unit_test:
|
||||||
print_time("SRAM creation", datetime.datetime.now(), start_time)
|
print_time("SRAM creation", datetime.datetime.now(), start_time)
|
||||||
|
|
||||||
@@ -162,7 +169,7 @@ class sram():
|
|||||||
spname = OPTS.output_path + self.s.name + ".sp"
|
spname = OPTS.output_path + self.s.name + ".sp"
|
||||||
debug.print_raw("SP: Writing to {0}".format(spname))
|
debug.print_raw("SP: Writing to {0}".format(spname))
|
||||||
self.sp_write(spname)
|
self.sp_write(spname)
|
||||||
''' #comment the following state when generating big sram, and then disable drc/lvs, because maigc_ext stuck
|
#''' #comment the following state when generating big sram, and then disable drc/lvs, because maigc_ext stuck
|
||||||
# Save a functional simulation file with default period
|
# Save a functional simulation file with default period
|
||||||
functional(self.s,
|
functional(self.s,
|
||||||
spname,
|
spname,
|
||||||
@@ -184,7 +191,7 @@ class sram():
|
|||||||
d.targ_write_ports = [self.s.write_ports[0]]
|
d.targ_write_ports = [self.s.write_ports[0]]
|
||||||
d.write_delay_stimulus()
|
d.write_delay_stimulus()
|
||||||
print_time("DELAY", datetime.datetime.now(), start_time)
|
print_time("DELAY", datetime.datetime.now(), start_time)
|
||||||
''' #comment the above when generating big sram, and then disable drc/lvs, bevause magic_ext stuck
|
#''' #comment the above when generating big sram, and then disable drc/lvs, bevause magic_ext stuck
|
||||||
# Save trimmed spice file
|
# Save trimmed spice file
|
||||||
temp_trim_sp = "{0}trimmed.sp".format(OPTS.output_path)
|
temp_trim_sp = "{0}trimmed.sp".format(OPTS.output_path)
|
||||||
self.sp_write(temp_trim_sp, lvs=False, trim=True)
|
self.sp_write(temp_trim_sp, lvs=False, trim=True)
|
||||||
|
|||||||
@@ -1,247 +0,0 @@
|
|||||||
# See LICENSE for licensing information.
|
|
||||||
#
|
|
||||||
# Copyright (c) 2016-2024 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 os
|
|
||||||
import shutil
|
|
||||||
import datetime
|
|
||||||
from openram import debug
|
|
||||||
from openram import sram_config as config
|
|
||||||
from openram import OPTS, print_time
|
|
||||||
|
|
||||||
|
|
||||||
class sram():
|
|
||||||
"""
|
|
||||||
This is not a design module, but contains an SRAM design instance.
|
|
||||||
It could later try options of number of banks and organization to compare
|
|
||||||
results.
|
|
||||||
We can later add visualizer and other high-level functions as needed.
|
|
||||||
"""
|
|
||||||
def __init__(self, sram_config=None, name=None):
|
|
||||||
|
|
||||||
# Create default configs if custom config isn't provided
|
|
||||||
if sram_config is None:
|
|
||||||
sram_config = config(word_size=OPTS.word_size,
|
|
||||||
num_words=OPTS.num_words,
|
|
||||||
write_size=OPTS.write_size,
|
|
||||||
num_banks=OPTS.num_banks,
|
|
||||||
words_per_row=OPTS.words_per_row,
|
|
||||||
num_spare_rows=OPTS.num_spare_rows,
|
|
||||||
num_spare_cols=OPTS.num_spare_cols)
|
|
||||||
|
|
||||||
if name is None:
|
|
||||||
name = OPTS.output_name
|
|
||||||
|
|
||||||
sram_config.set_local_config(self)
|
|
||||||
|
|
||||||
# reset the static duplicate name checker for unit tests
|
|
||||||
# in case we create more than one SRAM
|
|
||||||
from openram.base import design
|
|
||||||
design.name_map=[]
|
|
||||||
|
|
||||||
debug.info(2, "create sram of size {0} with {1} num of words {2} banks".format(self.word_size,
|
|
||||||
self.num_words,
|
|
||||||
self.num_banks))
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
from openram.modules.sram_openroad import sram_1bank as sram
|
|
||||||
#from openram.modules.sram_new import sram_1bank as sram
|
|
||||||
self.s = sram(name, sram_config)
|
|
||||||
|
|
||||||
self.s.create_netlist()
|
|
||||||
if not OPTS.netlist_only:
|
|
||||||
self.s.create_layout_openroad()
|
|
||||||
|
|
||||||
if not OPTS.is_unit_test:
|
|
||||||
print_time("SRAM creation", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
def get_sp_name(self):
|
|
||||||
if OPTS.use_pex:
|
|
||||||
# Use the extracted spice file
|
|
||||||
return self.pex_name
|
|
||||||
else:
|
|
||||||
# Use generated spice file for characterization
|
|
||||||
return self.sp_name
|
|
||||||
|
|
||||||
def sp_write(self, name, lvs=False, trim=False):
|
|
||||||
self.s.sp_write(name, lvs, trim)
|
|
||||||
|
|
||||||
def lef_write(self, name):
|
|
||||||
self.s.lef_write(name)
|
|
||||||
|
|
||||||
def gds_write(self, name):
|
|
||||||
self.s.gds_write(name)
|
|
||||||
|
|
||||||
def verilog_write(self, name):
|
|
||||||
self.s.verilog_write(name)
|
|
||||||
if self.num_banks != 1:
|
|
||||||
from openram.modules.sram_multibank import sram_multibank
|
|
||||||
mb = sram_multibank(self.s)
|
|
||||||
mb.verilog_write(name[:-2] + '_top.v')
|
|
||||||
|
|
||||||
def extended_config_write(self, name):
|
|
||||||
"""Dump config file with all options.
|
|
||||||
Include defaults and anything changed by input config."""
|
|
||||||
f = open(name, "w")
|
|
||||||
var_dict = dict((name, getattr(OPTS, name)) for name in dir(OPTS) if not name.startswith('__') and not callable(getattr(OPTS, name)))
|
|
||||||
for var_name, var_value in var_dict.items():
|
|
||||||
if isinstance(var_value, str):
|
|
||||||
f.write(str(var_name) + " = " + "\"" + str(var_value) + "\"\n")
|
|
||||||
else:
|
|
||||||
f.write(str(var_name) + " = " + str(var_value)+ "\n")
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
def save_only(self):
|
|
||||||
if not OPTS.netlist_only:
|
|
||||||
# Write the layout
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
gdsname = OPTS.output_path + self.s.name + ".gds"
|
|
||||||
debug.print_raw("GDS: Writing to {0}".format(gdsname))
|
|
||||||
self.gds_write(gdsname)
|
|
||||||
if OPTS.check_lvsdrc:
|
|
||||||
verify.write_drc_script(cell_name=self.s.name,
|
|
||||||
gds_name=os.path.basename(gdsname),
|
|
||||||
extract=True,
|
|
||||||
final_verification=True,
|
|
||||||
output_path=OPTS.output_path)
|
|
||||||
print_time("GDS", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Create a LEF physical model
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
lefname = OPTS.output_path + self.s.name + ".lef"
|
|
||||||
debug.print_raw("LEF: Writing to {0}".format(lefname))
|
|
||||||
self.lef_write(lefname)
|
|
||||||
print_time("LEF", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
""" Save all the output files while reporting time to do it as well. """
|
|
||||||
|
|
||||||
# Import this at the last minute so that the proper tech file
|
|
||||||
# is loaded and the right tools are selected
|
|
||||||
from openram import verify
|
|
||||||
from openram.characterizer import functional
|
|
||||||
from openram.characterizer import delay
|
|
||||||
|
|
||||||
# Save the spice file
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
spname = OPTS.output_path + self.s.name + ".sp"
|
|
||||||
debug.print_raw("SP: Writing to {0}".format(spname))
|
|
||||||
self.sp_write(spname)
|
|
||||||
|
|
||||||
# Save a functional simulation file with default period
|
|
||||||
functional(self.s,
|
|
||||||
spname,
|
|
||||||
cycles=200,
|
|
||||||
output_path=OPTS.output_path)
|
|
||||||
print_time("Spice writing", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Save stimulus and measurement file
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
debug.print_raw("DELAY: Writing stimulus...")
|
|
||||||
d = delay(self.s, spname, ("TT", 5, 25), output_path=OPTS.output_path)
|
|
||||||
if (self.s.num_spare_rows == 0):
|
|
||||||
probe_address = "1" * self.s.addr_size
|
|
||||||
else:
|
|
||||||
probe_address = "0" + "1" * (self.s.addr_size - 1)
|
|
||||||
probe_data = self.s.word_size - 1
|
|
||||||
d.analysis_init(probe_address, probe_data)
|
|
||||||
d.targ_read_ports.extend(self.s.read_ports)
|
|
||||||
d.targ_write_ports = [self.s.write_ports[0]]
|
|
||||||
d.write_delay_stimulus()
|
|
||||||
print_time("DELAY", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Save trimmed spice file
|
|
||||||
temp_trim_sp = "{0}trimmed.sp".format(OPTS.output_path)
|
|
||||||
self.sp_write(temp_trim_sp, lvs=False, trim=True)
|
|
||||||
|
|
||||||
if not OPTS.netlist_only:
|
|
||||||
# Write the layout
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
gdsname = OPTS.output_path + self.s.name + ".gds"
|
|
||||||
debug.print_raw("GDS: Writing to {0}".format(gdsname))
|
|
||||||
self.gds_write(gdsname)
|
|
||||||
if OPTS.check_lvsdrc:
|
|
||||||
verify.write_drc_script(cell_name=self.s.name,
|
|
||||||
gds_name=os.path.basename(gdsname),
|
|
||||||
extract=True,
|
|
||||||
final_verification=True,
|
|
||||||
output_path=OPTS.output_path)
|
|
||||||
print_time("GDS", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Create a LEF physical model
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
lefname = OPTS.output_path + self.s.name + ".lef"
|
|
||||||
debug.print_raw("LEF: Writing to {0}".format(lefname))
|
|
||||||
self.lef_write(lefname)
|
|
||||||
print_time("LEF", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Save the LVS file
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
lvsname = OPTS.output_path + self.s.name + ".lvs.sp"
|
|
||||||
debug.print_raw("LVS: Writing to {0}".format(lvsname))
|
|
||||||
self.sp_write(lvsname, lvs=True)
|
|
||||||
if not OPTS.netlist_only and OPTS.check_lvsdrc:
|
|
||||||
verify.write_lvs_script(cell_name=self.s.name,
|
|
||||||
gds_name=os.path.basename(gdsname),
|
|
||||||
sp_name=os.path.basename(lvsname),
|
|
||||||
final_verification=True,
|
|
||||||
output_path=OPTS.output_path)
|
|
||||||
print_time("LVS writing", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Save the extracted spice file
|
|
||||||
if OPTS.use_pex:
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
# Output the extracted design if requested
|
|
||||||
pexname = OPTS.output_path + self.s.name + ".pex.sp"
|
|
||||||
spname = OPTS.output_path + self.s.name + ".sp"
|
|
||||||
verify.run_pex(self.s.name, gdsname, spname, output=pexname)
|
|
||||||
sp_file = pexname
|
|
||||||
print_time("Extraction", datetime.datetime.now(), start_time)
|
|
||||||
else:
|
|
||||||
# Use generated spice file for characterization
|
|
||||||
sp_file = spname
|
|
||||||
|
|
||||||
# Characterize the design
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
from openram.characterizer import lib
|
|
||||||
debug.print_raw("LIB: Characterizing... ")
|
|
||||||
lib(out_dir=OPTS.output_path, sram=self.s, sp_file=sp_file)
|
|
||||||
print_time("Characterization", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Write the config file
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
try:
|
|
||||||
from shutil import copyfile
|
|
||||||
copyfile(OPTS.config_file, OPTS.output_path + OPTS.output_name + '.py')
|
|
||||||
except shutil.SameFileError:
|
|
||||||
pass
|
|
||||||
debug.print_raw("Config: Writing to {0}".format(OPTS.output_path + OPTS.output_name + '.py'))
|
|
||||||
print_time("Config", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Write the datasheet
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
from openram.datasheet import datasheet_gen
|
|
||||||
dname = OPTS.output_path + self.s.name + ".html"
|
|
||||||
debug.print_raw("Datasheet: Writing to {0}".format(dname))
|
|
||||||
datasheet_gen.datasheet_write(dname)
|
|
||||||
print_time("Datasheet", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Write a verilog model
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
vname = OPTS.output_path + self.s.name + '.v'
|
|
||||||
debug.print_raw("Verilog: Writing to {0}".format(vname))
|
|
||||||
self.verilog_write(vname)
|
|
||||||
print_time("Verilog", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Write out options if specified
|
|
||||||
if OPTS.output_extended_config:
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
oname = OPTS.output_path + OPTS.output_name + "_extended.py"
|
|
||||||
debug.print_raw("Extended Config: Writing to {0}".format(oname))
|
|
||||||
self.extended_config_write(oname)
|
|
||||||
print_time("Extended Config", datetime.datetime.now(), start_time)
|
|
||||||
@@ -1,268 +0,0 @@
|
|||||||
# See LICENSE for licensing information.
|
|
||||||
#
|
|
||||||
# Copyright (c) 2016-2024 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.
|
|
||||||
#
|
|
||||||
# This file generate sram part, aiming at using openroad to do the P&R
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import datetime
|
|
||||||
from openram import debug
|
|
||||||
from openram import sram_config as config
|
|
||||||
from openram import OPTS, print_time
|
|
||||||
|
|
||||||
|
|
||||||
class sram():
|
|
||||||
"""
|
|
||||||
This is not a design module, but contains an SRAM design instance.
|
|
||||||
It could later try options of number of banks and organization to compare
|
|
||||||
results.
|
|
||||||
We can later add visualizer and other high-level functions as needed.
|
|
||||||
"""
|
|
||||||
def __init__(self, sram_config=None, name=None, mod=0):
|
|
||||||
|
|
||||||
# Create default configs if custom config isn't provided
|
|
||||||
if sram_config is None:
|
|
||||||
sram_config = config(word_size=OPTS.word_size,
|
|
||||||
num_words=OPTS.num_words,
|
|
||||||
write_size=OPTS.write_size,
|
|
||||||
num_banks=OPTS.num_banks,
|
|
||||||
words_per_row=OPTS.words_per_row,
|
|
||||||
num_spare_rows=OPTS.num_spare_rows,
|
|
||||||
num_spare_cols=OPTS.num_spare_cols)
|
|
||||||
# maybe this part should be put after set_local_config, so we could calculate the number of port and define file name
|
|
||||||
if name is None:
|
|
||||||
#name = OPTS.output_name
|
|
||||||
if mod == 0:
|
|
||||||
name = OPTS.output_name + "_bank_" + "0"
|
|
||||||
elif mod == 1:# not consider multi-port yet!!!!!!
|
|
||||||
name = OPTS.output_name + "_control_" + "0"
|
|
||||||
elif mod == 2:
|
|
||||||
name = OPTS.output_name + "_row_addr_dff_" + "0"
|
|
||||||
elif mod == 3:
|
|
||||||
name = OPTS.output_name + "_col_addr_dff_" + "0"
|
|
||||||
elif mod == 4:
|
|
||||||
name = OPTS.output_name + "_data_dff_" + "0"
|
|
||||||
elif mod == 5:
|
|
||||||
name = OPTS.output_name + "_wmask_dff_" + "0"
|
|
||||||
elif mod == 6:
|
|
||||||
name = OPTS.output_name + "_spare_wen_dff_" + "0"
|
|
||||||
|
|
||||||
|
|
||||||
sram_config.set_local_config(self)
|
|
||||||
|
|
||||||
# reset the static duplicate name checker for unit tests
|
|
||||||
# in case we create more than one SRAM
|
|
||||||
from openram.base import design
|
|
||||||
design.name_map=[]
|
|
||||||
|
|
||||||
debug.info(2, "create sram of size {0} with {1} num of words {2} banks".format(self.word_size,
|
|
||||||
self.num_words,
|
|
||||||
self.num_banks))
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
#from openram.modules.sram_1bank import sram_1bank as sram
|
|
||||||
from openram.modules.sram_for_road import sram_for_road as sram
|
|
||||||
|
|
||||||
self.s = sram(name, sram_config)
|
|
||||||
|
|
||||||
def get_sp_name(self):
|
|
||||||
if OPTS.use_pex:
|
|
||||||
# Use the extracted spice file
|
|
||||||
return self.pex_name
|
|
||||||
else:
|
|
||||||
# Use generated spice file for characterization
|
|
||||||
return self.sp_name
|
|
||||||
|
|
||||||
def sp_write(self, name, lvs=False, trim=False):
|
|
||||||
self.s.sp_write(name, lvs, trim)
|
|
||||||
|
|
||||||
def lef_write(self, name):
|
|
||||||
self.s.lef_write(name)
|
|
||||||
|
|
||||||
def gds_write(self, name):
|
|
||||||
self.s.gds_write(name)
|
|
||||||
|
|
||||||
def verilog_write(self, name):
|
|
||||||
self.s.verilog_write(name)
|
|
||||||
if self.num_banks != 1:
|
|
||||||
from openram.modules.sram_multibank import sram_multibank
|
|
||||||
mb = sram_multibank(self.s)
|
|
||||||
mb.verilog_write(name[:-2] + '_top.v')
|
|
||||||
|
|
||||||
def extended_config_write(self, name):
|
|
||||||
"""Dump config file with all options.
|
|
||||||
Include defaults and anything changed by input config."""
|
|
||||||
f = open(name, "w")
|
|
||||||
var_dict = dict((name, getattr(OPTS, name)) for name in dir(OPTS) if not name.startswith('__') and not callable(getattr(OPTS, name)))
|
|
||||||
for var_name, var_value in var_dict.items():
|
|
||||||
if isinstance(var_value, str):
|
|
||||||
f.write(str(var_name) + " = " + "\"" + str(var_value) + "\"\n")
|
|
||||||
else:
|
|
||||||
f.write(str(var_name) + " = " + str(var_value)+ "\n")
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
def generate_files(self):
|
|
||||||
"""use to generate gds, lef files for one certain layout"""
|
|
||||||
# Import this at the last minute so that the proper tech file
|
|
||||||
# is loaded and the right tools are selected
|
|
||||||
from openram import verify
|
|
||||||
from openram.characterizer import functional
|
|
||||||
from openram.characterizer import delay
|
|
||||||
|
|
||||||
# Save the spice file
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
spname = OPTS.output_path + self.s.name + ".sp"
|
|
||||||
debug.print_raw("SP: Writing to {0}".format(spname))
|
|
||||||
self.sp_write(spname)
|
|
||||||
|
|
||||||
print_time("Spice writing", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Save trimmed spice file
|
|
||||||
temp_trim_sp = "{0}trimmed.sp".format(OPTS.output_path)
|
|
||||||
self.sp_write(temp_trim_sp, lvs=False, trim=True)
|
|
||||||
|
|
||||||
if not OPTS.netlist_only:
|
|
||||||
# Write the layout
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
gdsname = OPTS.output_path + self.s.name + ".gds"
|
|
||||||
debug.print_raw("GDS: Writing to {0}".format(gdsname))
|
|
||||||
self.gds_write(gdsname)
|
|
||||||
if OPTS.check_lvsdrc:
|
|
||||||
verify.write_drc_script(cell_name=self.s.name,
|
|
||||||
gds_name=os.path.basename(gdsname),
|
|
||||||
extract=True,
|
|
||||||
final_verification=True,
|
|
||||||
output_path=OPTS.output_path)
|
|
||||||
print_time("GDS", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Create a LEF physical model
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
lefname = OPTS.output_path + self.s.name + ".lef"
|
|
||||||
debug.print_raw("LEF: Writing to {0}".format(lefname))
|
|
||||||
self.lef_write(lefname)
|
|
||||||
print_time("LEF", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Save the LVS file
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
lvsname = OPTS.output_path + self.s.name + ".lvs.sp"
|
|
||||||
debug.print_raw("LVS: Writing to {0}".format(lvsname))
|
|
||||||
self.sp_write(lvsname, lvs=True)
|
|
||||||
if not OPTS.netlist_only and OPTS.check_lvsdrc:
|
|
||||||
verify.write_lvs_script(cell_name=self.s.name,
|
|
||||||
gds_name=os.path.basename(gdsname),
|
|
||||||
sp_name=os.path.basename(lvsname),
|
|
||||||
final_verification=True,
|
|
||||||
output_path=OPTS.output_path)
|
|
||||||
print_time("LVS writing", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Save the extracted spice file
|
|
||||||
if OPTS.use_pex:
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
# Output the extracted design if requested
|
|
||||||
pexname = OPTS.output_path + self.s.name + ".pex.sp"
|
|
||||||
spname = OPTS.output_path + self.s.name + ".sp"
|
|
||||||
verify.run_pex(self.s.name, gdsname, spname, output=pexname)
|
|
||||||
sp_file = pexname
|
|
||||||
print_time("Extraction", datetime.datetime.now(), start_time)
|
|
||||||
else:
|
|
||||||
# Use generated spice file for characterization
|
|
||||||
sp_file = spname
|
|
||||||
|
|
||||||
# Write the config file
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
try:
|
|
||||||
from shutil import copyfile
|
|
||||||
copyfile(OPTS.config_file, OPTS.output_path + OPTS.output_name + '.py')
|
|
||||||
except shutil.SameFileError:
|
|
||||||
pass
|
|
||||||
debug.print_raw("Config: Writing to {0}".format(OPTS.output_path + OPTS.output_name + '.py'))
|
|
||||||
print_time("Config", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
|
|
||||||
# Write a verilog model
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
vname = OPTS.output_path + self.s.name + '.v'
|
|
||||||
debug.print_raw("Verilog: Writing to {0}".format(vname))
|
|
||||||
self.verilog_write(vname)
|
|
||||||
print_time("Verilog", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Write out options if specified
|
|
||||||
if OPTS.output_extended_config:
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
oname = OPTS.output_path + OPTS.output_name + "_extended.py"
|
|
||||||
debug.print_raw("Extended Config: Writing to {0}".format(oname))
|
|
||||||
self.extended_config_write(oname)
|
|
||||||
print_time("Extended Config", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
|
|
||||||
def save(self, mod=0):
|
|
||||||
""" Save all the output files while reporting time to do it as well. """
|
|
||||||
if mod == 0:
|
|
||||||
self.s.create_netlist_bank()
|
|
||||||
if not OPTS.netlist_only:
|
|
||||||
self.s.create_layout_bank_only()
|
|
||||||
self.generate_files()
|
|
||||||
elif mod == 1:
|
|
||||||
self.s.create_netlist_control()
|
|
||||||
if not OPTS.netlist_only:
|
|
||||||
for port in self.s.all_ports:
|
|
||||||
self.s.create_layout_control_only(instance_index=port)
|
|
||||||
self.generate_files()
|
|
||||||
else:
|
|
||||||
for port in self.s.all_ports:
|
|
||||||
self.generate_files()
|
|
||||||
elif mod == 2:
|
|
||||||
self.s.create_netlist_row_addr_dff()
|
|
||||||
if not OPTS.netlist_only:
|
|
||||||
for port in self.s.all_ports:
|
|
||||||
self.s.create_layout_row_addr_dff_only(instance_index=port)
|
|
||||||
self.generate_files()
|
|
||||||
else:
|
|
||||||
for port in self.s.all_ports:
|
|
||||||
self.generate_files()
|
|
||||||
elif mod == 3:
|
|
||||||
if self.s.create_netlist_col_addr_dff() == False:
|
|
||||||
pass#continue # do not need col addr dff
|
|
||||||
elif not OPTS.netlist_only:
|
|
||||||
for port in self.s.all_ports:
|
|
||||||
self.create_layout_col_addr_dff_only(instance_index=port)
|
|
||||||
self.generate_files()
|
|
||||||
else:
|
|
||||||
self.generate_files()
|
|
||||||
elif mod == 4:
|
|
||||||
self.s.create_netlist_data_dff()
|
|
||||||
if not OPTS.netlist_only:
|
|
||||||
for port in self.s.all_ports:
|
|
||||||
self.s.create_layout_data_dff_only(instance_index=port)
|
|
||||||
self.generate_files()
|
|
||||||
else:
|
|
||||||
for port in self.s.all_ports:
|
|
||||||
self.generate_files()
|
|
||||||
elif mod == 5:
|
|
||||||
if self.s.create_netlist_wmask_dff() == False:
|
|
||||||
pass#continue # do not need wmask dff
|
|
||||||
elif not OPTS.netlist_only:
|
|
||||||
for port in self.s.all_ports:
|
|
||||||
self.s.create_layout_wmask_dff_only(instance_index=port)
|
|
||||||
self.generate_files()
|
|
||||||
else:
|
|
||||||
for port in self.s.all_ports:
|
|
||||||
self.generate_files()
|
|
||||||
elif mod == 6:
|
|
||||||
if self.s.create_netlist_spare_wen_dff() == False:
|
|
||||||
pass#continue # do not need spare wen dff
|
|
||||||
elif not OPTS.netlist_only:
|
|
||||||
for port in self.s.all_ports:
|
|
||||||
self.s.create_layout_spare_wen_dff_only(instance_index=port)
|
|
||||||
self.generate_files()
|
|
||||||
else:
|
|
||||||
for port in self.s.all_ports:
|
|
||||||
self.generate_files()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+1
-31
@@ -70,40 +70,10 @@ for path in output_files:
|
|||||||
|
|
||||||
# Create an SRAM (we can also pass sram_config, see documentation/tutorials for details)
|
# Create an SRAM (we can also pass sram_config, see documentation/tutorials for details)
|
||||||
from openram import sram
|
from openram import sram
|
||||||
s = sram()
|
s = sram(route_option="classic")# "classic" or "fast"
|
||||||
#from openram import sram_openroad_test
|
|
||||||
#s = sram_openroad_test.sram()
|
|
||||||
# Output the files for the resulting SRAM
|
# Output the files for the resulting SRAM
|
||||||
s.save()
|
s.save()
|
||||||
#s.save_only()
|
|
||||||
'''
|
|
||||||
from openram import sram_road
|
|
||||||
s = sram_road.sram(mod=0)
|
|
||||||
s.save(mod=0)
|
|
||||||
del s
|
|
||||||
s = sram_road.sram(mod=1)
|
|
||||||
s.save(mod=1)
|
|
||||||
|
|
||||||
del s
|
|
||||||
s = sram_road.sram(mod=2)
|
|
||||||
s.save(mod=2)
|
|
||||||
|
|
||||||
del s
|
|
||||||
s = sram_road.sram(mod=3)
|
|
||||||
s.save(mod=3)
|
|
||||||
|
|
||||||
del s
|
|
||||||
s = sram_road.sram(mod=4)
|
|
||||||
s.save(mod=4)
|
|
||||||
|
|
||||||
del s
|
|
||||||
s = sram_road.sram(mod=5)
|
|
||||||
s.save(mod=5)
|
|
||||||
|
|
||||||
del s
|
|
||||||
s = sram_road.sram(mod=6)
|
|
||||||
s.save(mod=6)
|
|
||||||
'''
|
|
||||||
# Delete temp files etc.
|
# Delete temp files etc.
|
||||||
openram.end_openram()
|
openram.end_openram()
|
||||||
openram.print_time("End", datetime.datetime.now(), start_time)
|
openram.print_time("End", datetime.datetime.now(), start_time)
|
||||||
|
|||||||
Reference in New Issue
Block a user