make code clean

This commit is contained in:
FriedrichWu 2024-11-12 17:02:02 +01:00
parent 1f1f064036
commit f56460bb94
11 changed files with 196 additions and 7312 deletions

View File

@ -144,16 +144,16 @@ class channel_route(design):
layer_stuff = self.get_layer_pitch(self.horizontal_layer)
(self.horizontal_nonpref_pitch, self.horizontal_pitch, self.horizontal_width, self.horizontal_space) = layer_stuff
# For debug
debug.warning("layer horizontal: {0}".format(self.horizontal_layer))
debug.warning("horizontal_nonpref_pitch: {0}".format(self.horizontal_nonpref_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("vertiacl_nonpref_pitch: {0}".format(self.vertical_pitch))
debug.warning("vertical_pitch: {0}".format(self.vertical_pitch))
debug.warning("vertical_space: {0}".format(self.vertical_space))
self.route()
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))
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
@ -241,7 +241,7 @@ class channel_route(design):
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
@ -326,8 +326,8 @@ class channel_route(design):
except AttributeError:
debug.error("Cannot find layer pitch.", -1)
return (nonpref_pitch, pitch, pitch - space, space)
def add_horizontal_trunk_with_jog(self,
def add_horizontal_trunk_with_jog(self,
pins,
trunk_offset,
pitch):
@ -346,7 +346,7 @@ class channel_route(design):
non_preferred_route = max_x - min_x <= pitch
half_layer_width = 0.5 * drc["minwidth_{0}".format(self.vertical_layer)]
if port == 0: # bottom need shift
if non_preferred_route:
if non_preferred_route:
# Add the horizontal trunk on the vertical layer!
self.add_path(self.vertical_layer,
[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_via_stack_center(from_layer=pin.layer,
to_layer=self.vertical_layer,
offset=pin.bc())
offset=pin.bc())
else:
# Add the horizontal trunk
self.add_path(self.horizontal_layer,
@ -399,7 +399,7 @@ class channel_route(design):
to_layer=self.vertical_layer,
offset=pin.bc())
else: # port 1, situation different, top need shift
if non_preferred_route:
if non_preferred_route:
# Add the horizontal trunk on the vertical layer!
self.add_path(self.vertical_layer,
[vector(min_x - half_layer_width, trunk_offset.y),
@ -411,7 +411,7 @@ class channel_route(design):
pin_pos = pin.uc()
# No bend needed here
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,
to_layer=self.vertical_layer,
offset=pin.uc())
@ -440,7 +440,7 @@ class channel_route(design):
directions=self.directions)
self.add_via_stack_center(from_layer=pin.layer,
to_layer=self.vertical_layer,
offset=pin.uc())
offset=pin.uc())
else:
pin_pos = pin.center()
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,
to_layer=self.vertical_layer,
offset=pin_pos)
def add_horizontal_trunk_route(self,
pins,
trunk_offset,

View File

@ -18,6 +18,7 @@ from openram.base import lef
from openram.sram_factory import factory
from openram.tech import spice
from openram import OPTS, print_time
import re
class sram_1bank(design, verilog, lef):
@ -206,8 +207,8 @@ class sram_1bank(design, verilog, lef):
if not OPTS.is_unit_test:
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 """
start_time = datetime.datetime.now()
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)
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:
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.
self.DRC_LVS(final_verification=OPTS.route_supplies, force_check=OPTS.check_lvsdrc)
print_time("Verification", datetime.datetime.now(), start_time)
def create_modules(self):
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
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.
"""
@ -361,17 +362,29 @@ class sram_1bank(design, verilog, lef):
else:
for bit in range(self.num_spare_cols):
pins_to_route.append("spare_wen{0}[{1}]".format(port, bit))
from openram.router import signal_escape_router as router
# mod Use for control which edge/position the pins(dout) will be placed
# 0 -> default
# 1 -> all top/bottom
# 2 -> all left/right
rtr = router(layers=self.m3_stack,
bbox=bbox,
design=self,
mod=mod)
rtr.route(pins_to_route)
if route_option == "classic":
from openram.router import signal_escape_router as router
# mod Use for control which edge/position the pins(dout) will be placed
# 0 -> default
# 1 -> all top/bottom
# 2 -> all left/right
rtr = router(layers=self.m3_stack,
bbox=bbox,
design=self,
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):
""" 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()
else:
self.num_spare_cols = 0
def place_instances_changeable(self, position_add=0):
"""
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.route_dffs(add_routes=False)
self.remove_layout_pins()
for port in self.all_ports:
# 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
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
# 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])
@ -875,7 +887,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 = 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_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),
start_layer=pin_layer)
def route_layout(self, mod=0):
def route_layout(self, mod=0, route_option="classic"):
""" Route a single bank SRAM """
self.route_clk()
@ -1085,12 +1097,11 @@ class sram_1bank(design, verilog, lef):
if OPTS.perimeter_pins:
# We now route the escape routes far enough out so that they will
# 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:
self.route_supplies(init_bbox)
def route_dffs(self, add_routes=True):
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

View File

@ -21,7 +21,7 @@ class io_pin_placer(router):
# New pins are the side supply pins
self.new_pins = {}
# added_io_pins
self.io_pins_added_left = []
self.io_pins_added_right = []
@ -30,7 +30,7 @@ class io_pin_placer(router):
# fake_pins, use for rename
self.io_pins_fake =[]
def get_closest_edge(self, point):
""" 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 "top", False
def initial_position(self, pins): # pins is list []
""" Set the IO pin center at the perimeter """
def initial_position(self, pins): # pins is list []
""" Set the IO pin center at the perimeter """
pattern_clk = r'^clk'
pattern_addr0 = r'^addr0'
pattern_addr1 = r'^addr1'
@ -82,14 +82,14 @@ class io_pin_placer(router):
vertical = True
elif edge == "bottom": # but for big sram, addr0[] may have pins at bottom, which is allowed
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 edge == "bottom" or edge == "right":
edge = "right"
vertical = True
elif edge == "top": # but for big sram, addr1[] may have pins at top, which is allowed
vertical = False
self.store_position(pin, edge, vertical)
self.store_position(pin, edge, vertical)
if re.match(pattern_din, pin.name): # din
self.store_position(pin, edge, vertical)
if re.match(pattern_wmask, pin.name): # wmask
@ -100,7 +100,7 @@ class io_pin_placer(router):
self.store_position(pin, edge, vertical)
if re.match(pattern_web, pin.name): # web
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:
if re.match(pattern_dout0, pin.name):
edge = "bottom"
@ -115,7 +115,7 @@ class io_pin_placer(router):
def check_overlap(self, pin_position, edge):
""" Return the suggested position to aviod overlap """
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
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)
via_to_close = False
# 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:
debug.warning("overlap, changing position")
add_distance = add_distance + 0.1
while pin_to_close or via_to_close:
debug.warning("overlap, changing position")
add_distance = add_distance + 0.1
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)
via_to_close = abs(fake_center.x - c.x) < 0.6
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
if edge == "top":
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)
via_to_close = False
# 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:
via_to_close = False
# 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:
debug.warning("overlap, changing position")
add_distance = add_distance + 0.1
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)
via_to_close = abs(fake_center.x - c.x) < 0.6
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
return fake_center
return fake_center
def store_dout_position(self, pin, edge, vertical):
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
layer = self.get_layer(int(not vertical))
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
rect = [nll, nur]
#fake_pin = [pin.name() + "_" + "fake", pin_position, rect, layer]
fake_pin = graph_shape(name=pin.name + "_" + "fake",
rect=rect,
layer_name_pp=layer)
if edge == "left":
self.io_pins_added_left.append(fake_pin)
elif edge == "bottom":
@ -168,10 +168,10 @@ class io_pin_placer(router):
elif edge == "top":
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))
def store_position(self, pin, edge, vertical): # also need to store the source pin
ll, ur = self.bbox
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
layer = self.get_layer(int(not vertical))
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
rect = [nll, nur]
#fake_pin = [pin.name() + "_" + "fake", fake_center, rect, layer]
fake_pin = graph_shape(name=pin.name + "_" + "fake",
rect=rect,
layer_name_pp=layer)
if edge == "left":
self.io_pins_added_left.append(fake_pin)
elif edge == "bottom":
@ -213,111 +213,9 @@ class io_pin_placer(router):
self.io_pins_added_right.append(fake_pin)
elif edge == "top":
self.io_pins_added_up.append(fake_pin)
self.io_pins_fake.append(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):
@ -336,13 +234,13 @@ class io_pin_placer(router):
for name in self.pins:
pin = next(iter(self.pins[name]))
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]"
self.replace_layout_pins(pin_names)
def add_io_pins_connected(self, pin_names):
""" Add IO pins on the edges WITH routing them. """
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_list.append(pin)
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
for fake_pin in self.io_pins_fake:
self.design.add_layout_pin(text=fake_pin.name,
@ -372,7 +270,7 @@ class io_pin_placer(router):
width=fake_pin.width(),
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)
# 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]"
self.replace_layout_pins(pin_names)
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 """
debug.info(1, "connecting to io pins...")
@ -392,18 +290,18 @@ class io_pin_placer(router):
source_pin = next(iter(self.pins[pin_name]))
for fake_pin in self.io_pins_fake:
if pin_name + "_" + "fake" == fake_pin.name:
target_pin = fake_pin
break
target_pin = fake_pin
break
# special hanlde dout pins
if re.match(pattern_dout, pin_name):
number_str = re.findall(r'\[(\d+)\]', pin_name)
if number_str:
number = int(number_str[0])
if number % 2 == 0:
is_up = True
is_up = True
else:
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)
# other pins
else:
@ -414,7 +312,7 @@ class io_pin_placer(router):
self.add_wire(point_list)
def add_wire(self, point_list):
def add_wire(self, point_list):
if len(point_list) == 2:
# direct connect
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_via(point_list[2])
self.add_line(point_list[2], point_list[3])
def add_line(self, point_1, point_2):
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])
else:
# vertical m4
self.design.add_path(self.get_layer(True), [point_1, point_2])
def add_via(self, point):
# currently only m3-m4 vias are supported in this method
# usd in order to make "z" shape routing only
self.design.add_via_stack_center(from_layer=self.get_layer(False),
to_layer=self.get_layer(True),
self.design.add_via_stack_center(from_layer=self.get_layer(False),
to_layer=self.get_layer(True),
offset=point)
def add_start_via(self, point):
# currently only m3-m4 vias are supported in this method
# used in source_pin only
self.design.add_via_stack_center(from_layer=self.get_layer(False),
to_layer=self.get_layer(True),
self.design.add_via_stack_center(from_layer=self.get_layer(False),
to_layer=self.get_layer(True),
offset=point)
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
@ -460,19 +358,19 @@ class io_pin_placer(router):
offset=offset,
width=width,
height=height)
def decide_point(self, source_pin, target_pin, is_up=False):
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
pattern_clk = r'^clk'
pattern_csb = r'^csb'
# internal -> left
# internal -> left
if round(target_pin.center().x, 3) == round(ll.x - self.track_wire * 2 + offset, 3):
# special handle clk0
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
# special handel csb0
# special handel csb0
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
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):
# special handel clk1
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
# special handle csb0
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
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
else:
return [vector(source_pin.lc().x, source_pin.lc().y + 0.32), target_pin.rc()]# 0.32 should be same in initial_position
else:
# direct connect possible
return [source_pin.lc(), target_pin.rc()]
# internal -> top, need to add start_via m3->m4
@ -499,13 +397,13 @@ class io_pin_placer(router):
# need intermediate point
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!
if is_up:
if is_up:
via_basic_y = via_basic_y + 0.5
else:
via_basic_y = via_basic_y - 0.5
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()]
return [source_pin.bc(), point_1, point_2, target_pin.uc()]
# 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):
self.add_start_via(source_pin.center())
@ -521,14 +419,14 @@ class io_pin_placer(router):
via_basic_y = via_basic_y - 0.5
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()]
return [source_pin.uc(), point_1, point_2, target_pin.bc()]
def remove_io_pins(self, pin_name):
# remove io pin in gds, so we could reroute
self.design.remove_layout_pin(pin_name)
def replace_layout_pins(self, pin_names):
""" Change the IO pin names with new ones around the perimeter. """
for pin_name in pin_names:
@ -537,8 +435,7 @@ class io_pin_placer(router):
if pin.name == perimeter_pin_name:
perimeter_pin = pin
self.design.replace_layout_pin(pin_name, perimeter_pin)
break
break

View File

@ -24,13 +24,13 @@ class signal_escape_router(router):
# New pins are the side supply 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_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
# 1 -> all top/bottom
# 2 -> all left/right
@ -206,16 +206,16 @@ class signal_escape_router(router):
fake_center = vector(ur.x + self.track_wire * 2, c.y)
if edge == "top":
fake_center = vector(c.x, ur.y + self.track_wire * 2)
# relocate the pin position
pattern = r'^dout'
if re.match(pattern, pin.name):
if self.state_mod == 0:
pass# do not change, default
elif self.state_mod == 1: # all top/bottom
if edge == "right":
if edge == "right":
vertical = False
fake_center = vector(c.x, ll.y - self.track_wire * 2)
self.distance_right += 1
@ -223,8 +223,8 @@ class signal_escape_router(router):
if edge == "left":
vertical = False
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
if (edge == "bottom") or (edge == "right"):# change to the east
vertical = True
@ -234,10 +234,10 @@ class signal_escape_router(router):
if (edge == "top") or (edge == "left"):# change to the west
vertical = True
fake_center = vector(ll.x - self.track_wire * 2, ur.y - 30 - self.distance_left)
self.distance_left += 1
self.distance_left += 1
else:
debug.error("wrong state mod!", -1)
debug.error("wrong state mod!", -1)
# Create the fake pin shape
layer = self.get_layer(int(not vertical))
half_wire_vector = vector([self.half_wire] * 2)

View File

@ -20,7 +20,7 @@ class sram():
results.
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
if sram_config is None:
@ -48,67 +48,74 @@ class sram():
start_time = datetime.datetime.now()
self.name = name
self.route_option = route_option # "classic" or "fast"
from openram.modules.sram_1bank import sram_1bank as sram
num_ports = OPTS.num_rw_ports + OPTS.num_r_ports + OPTS.num_w_ports
self.s = sram(name, sram_config)
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":
try:
self.s.create_layout(position_add=i, mod=1)
except AssertionError as e:
cur_state = "ALL_LEFT_RIGHT"
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
# choose the routung method, maze router or constructive
if self.route_option == "classic":
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":
try:
self.s.create_layout(position_add=i, mod=1)
except AssertionError as e:
cur_state = "ALL_LEFT_RIGHT"
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:
print_time("SRAM creation", datetime.datetime.now(), start_time)
@ -162,7 +169,7 @@ class sram():
spname = OPTS.output_path + self.s.name + ".sp"
debug.print_raw("SP: Writing to {0}".format(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
functional(self.s,
spname,
@ -184,7 +191,7 @@ class sram():
d.targ_write_ports = [self.s.write_ports[0]]
d.write_delay_stimulus()
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
temp_trim_sp = "{0}trimmed.sp".format(OPTS.output_path)
self.sp_write(temp_trim_sp, lvs=False, trim=True)

View File

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

View File

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

View File

@ -70,40 +70,10 @@ 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()
#from openram import sram_openroad_test
#s = sram_openroad_test.sram()
s = sram(route_option="classic")# "classic" or "fast"
# Output the files for the resulting SRAM
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.
openram.end_openram()
openram.print_time("End", datetime.datetime.now(), start_time)