mirror of https://github.com/VLSIDA/OpenRAM.git
make code clean
This commit is contained in:
parent
1f1f064036
commit
f56460bb94
|
|
@ -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):
|
||||
|
|
@ -207,7 +208,7 @@ 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)
|
||||
|
|
@ -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.
|
||||
"""
|
||||
|
|
@ -362,6 +363,7 @@ class sram_1bank(design, verilog, lef):
|
|||
for bit in range(self.num_spare_cols):
|
||||
pins_to_route.append("spare_wen{0}[{1}]".format(port, bit))
|
||||
|
||||
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
|
||||
|
|
@ -372,6 +374,17 @@ class sram_1bank(design, verilog, lef):
|
|||
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 """
|
||||
|
|
@ -853,7 +866,6 @@ class sram_1bank(design, verilog, lef):
|
|||
for port in self.all_ports:
|
||||
# Add the extra position
|
||||
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
|
|
@ -218,108 +218,6 @@ class io_pin_placer(router):
|
|||
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):
|
||||
""" Add IO pins on the edges WITHOUT routing them. """
|
||||
debug.info(1, "Adding IO pins on the perimeter...")
|
||||
|
|
@ -543,4 +441,3 @@ class io_pin_placer(router):
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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,12 +48,16 @@ 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
|
||||
|
||||
# choose the routung method, maze router or constructive
|
||||
if self.route_option == "classic":
|
||||
cur_state = "IDLE"
|
||||
if not OPTS.netlist_only:
|
||||
i = 0
|
||||
|
|
@ -108,6 +112,9 @@ class sram():
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue