mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into laptop_checkpoint
This commit is contained in:
commit
d3199ea70e
|
|
@ -69,25 +69,31 @@ class lef:
|
||||||
|
|
||||||
def lef_write(self, lef_name):
|
def lef_write(self, lef_name):
|
||||||
""" Write the entire lef of the object to the file. """
|
""" Write the entire lef of the object to the file. """
|
||||||
|
# Can possibly use magic lef write to create the LEF
|
||||||
|
# if OPTS.drc_exe and OPTS.drc_exe[0] == "magic":
|
||||||
|
# self.magic_lef_write(lef_name)
|
||||||
|
# return
|
||||||
|
|
||||||
|
# To maintain the indent level easily
|
||||||
|
self.indent = ""
|
||||||
|
|
||||||
if OPTS.detailed_lef:
|
if OPTS.detailed_lef:
|
||||||
debug.info(3, "Writing detailed LEF to {0}".format(lef_name))
|
debug.info(3, "Writing detailed LEF to {0}".format(lef_name))
|
||||||
self.detailed_lef_write(lef_name)
|
|
||||||
else:
|
else:
|
||||||
debug.info(3, "Writing abstract LEF to {0}".format(lef_name))
|
debug.info(3, "Writing abstract LEF to {0}".format(lef_name))
|
||||||
# Can possibly use magic lef write to create the LEF
|
self.compute_abstract_blockages()
|
||||||
# if OPTS.drc_exe and OPTS.drc_exe[0] == "magic":
|
|
||||||
# self.magic_lef_write(lef_name)
|
|
||||||
# return
|
|
||||||
self.abstract_lef_write(lef_name)
|
|
||||||
|
|
||||||
def abstract_lef_write(self, lef_name):
|
|
||||||
# To maintain the indent level easily
|
|
||||||
self.indent = ""
|
|
||||||
|
|
||||||
self.lef = open(lef_name, "w")
|
self.lef = open(lef_name, "w")
|
||||||
self.lef_write_header()
|
self.lef_write_header()
|
||||||
|
|
||||||
|
for pin_name in self.pins:
|
||||||
|
self.lef_write_pin(pin_name)
|
||||||
|
|
||||||
|
self.lef_write_obstructions(OPTS.detailed_lef)
|
||||||
|
self.lef_write_footer()
|
||||||
|
self.lef.close()
|
||||||
|
|
||||||
|
def compute_abstract_blockages(self):
|
||||||
# Start with blockages on all layers the size of the block
|
# Start with blockages on all layers the size of the block
|
||||||
# minus the pin escape margin (hard coded to 4 x m3 pitch)
|
# minus the pin escape margin (hard coded to 4 x m3 pitch)
|
||||||
# These are a pin_layout to use their geometric functions
|
# These are a pin_layout to use their geometric functions
|
||||||
|
|
@ -118,23 +124,6 @@ class lef:
|
||||||
new_blockages = blockage.cut(intersection_pin)
|
new_blockages = blockage.cut(intersection_pin)
|
||||||
self.blockages[pin.layer].extend(new_blockages)
|
self.blockages[pin.layer].extend(new_blockages)
|
||||||
|
|
||||||
self.lef_write_pin(pin_name)
|
|
||||||
|
|
||||||
self.lef_write_obstructions(abstracted=True)
|
|
||||||
self.lef_write_footer()
|
|
||||||
self.lef.close()
|
|
||||||
|
|
||||||
def detailed_lef_write(self, lef_name):
|
|
||||||
# To maintain the indent level easily
|
|
||||||
self.indent = ""
|
|
||||||
|
|
||||||
self.lef = open(lef_name, "w")
|
|
||||||
self.lef_write_header()
|
|
||||||
for pin in self.pins:
|
|
||||||
self.lef_write_pin(pin)
|
|
||||||
self.lef_write_obstructions()
|
|
||||||
self.lef_write_footer()
|
|
||||||
self.lef.close()
|
|
||||||
|
|
||||||
def lef_write_header(self):
|
def lef_write_header(self):
|
||||||
""" Header of LEF file """
|
""" Header of LEF file """
|
||||||
|
|
@ -155,8 +144,8 @@ class lef:
|
||||||
self.lef.write("{0}SYMMETRY X Y R90 ;\n".format(self.indent))
|
self.lef.write("{0}SYMMETRY X Y R90 ;\n".format(self.indent))
|
||||||
|
|
||||||
def lef_write_footer(self):
|
def lef_write_footer(self):
|
||||||
self.lef.write("{0}END {1}\n".format(self.indent, self.name))
|
|
||||||
self.indent = self.indent[:-3]
|
self.indent = self.indent[:-3]
|
||||||
|
self.lef.write("{0}END {1}\n".format(self.indent, self.name))
|
||||||
self.lef.write("END LIBRARY\n")
|
self.lef.write("END LIBRARY\n")
|
||||||
|
|
||||||
def lef_write_pin(self, name):
|
def lef_write_pin(self, name):
|
||||||
|
|
@ -188,20 +177,20 @@ class lef:
|
||||||
self.indent = self.indent[:-3]
|
self.indent = self.indent[:-3]
|
||||||
self.lef.write("{0}END {1}\n".format(self.indent, name))
|
self.lef.write("{0}END {1}\n".format(self.indent, name))
|
||||||
|
|
||||||
def lef_write_obstructions(self, abstracted=False):
|
def lef_write_obstructions(self, detailed=False):
|
||||||
""" Write all the obstructions on each layer """
|
""" Write all the obstructions on each layer """
|
||||||
self.lef.write("{0}OBS\n".format(self.indent))
|
self.lef.write("{0}OBS\n".format(self.indent))
|
||||||
for layer in self.lef_layers:
|
for layer in self.lef_layers:
|
||||||
self.lef.write("{0}LAYER {1} ;\n".format(self.indent, layer_names[layer]))
|
self.lef.write("{0}LAYER {1} ;\n".format(self.indent, layer_names[layer]))
|
||||||
self.indent += " "
|
self.indent += " "
|
||||||
if abstracted:
|
if detailed:
|
||||||
blockages = self.blockages[layer]
|
|
||||||
for b in blockages:
|
|
||||||
self.lef_write_shape(b.rect)
|
|
||||||
else:
|
|
||||||
blockages = self.get_blockages(layer, True)
|
blockages = self.get_blockages(layer, True)
|
||||||
for b in blockages:
|
for b in blockages:
|
||||||
self.lef_write_shape(b)
|
self.lef_write_shape(b)
|
||||||
|
else:
|
||||||
|
blockages = self.blockages[layer]
|
||||||
|
for b in blockages:
|
||||||
|
self.lef_write_shape(b.rect)
|
||||||
self.indent = self.indent[:-3]
|
self.indent = self.indent[:-3]
|
||||||
self.lef.write("{0}END\n".format(self.indent))
|
self.lef.write("{0}END\n".format(self.indent))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,3 +70,7 @@ class nand2_dec(design.design):
|
||||||
"""
|
"""
|
||||||
self.add_graph_edges(graph, port_nets)
|
self.add_graph_edges(graph, port_nets)
|
||||||
|
|
||||||
|
def is_non_inverting(self):
|
||||||
|
"""Return input to output polarity for module"""
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
|
||||||
|
|
@ -70,3 +70,7 @@ class nand3_dec(design.design):
|
||||||
"""
|
"""
|
||||||
self.add_graph_edges(graph, port_nets)
|
self.add_graph_edges(graph, port_nets)
|
||||||
|
|
||||||
|
def is_non_inverting(self):
|
||||||
|
"""Return input to output polarity for module"""
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
|
||||||
|
|
@ -70,3 +70,7 @@ class nand4_dec(design.design):
|
||||||
"""
|
"""
|
||||||
self.add_graph_edges(graph, port_nets)
|
self.add_graph_edges(graph, port_nets)
|
||||||
|
|
||||||
|
def is_non_inverting(self):
|
||||||
|
"""Return input to output polarity for module"""
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
"""
|
||||||
|
Pseudo-dual port (independent read and write ports), 8bit word, 1 kbyte SRAM.
|
||||||
|
|
||||||
|
Useful as a byte FIFO between two devices (the reader and the writer).
|
||||||
|
"""
|
||||||
|
word_size = 8 # Bits
|
||||||
|
num_words = 1024
|
||||||
|
human_byte_size = "{:.0f}kbytes".format((word_size * num_words)/1024/8)
|
||||||
|
|
||||||
|
# Allow byte writes
|
||||||
|
write_size = 8 # Bits
|
||||||
|
|
||||||
|
# Dual port
|
||||||
|
num_rw_ports = 0
|
||||||
|
num_r_ports = 1
|
||||||
|
num_w_ports = 1
|
||||||
|
ports_human = '1r1w'
|
||||||
|
|
||||||
|
import os
|
||||||
|
exec(open(os.path.join(os.path.dirname(__file__), 'sky130_sram_common.py')).read())
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
"""
|
||||||
|
Dual port (1 read/write + 1 read only) 1 kbytes SRAM with byte write.
|
||||||
|
|
||||||
|
FIXME: What is this useful for?
|
||||||
|
FIXME: Why would you want byte write on this?
|
||||||
|
"""
|
||||||
|
word_size = 32 # Bits
|
||||||
|
num_words = 256
|
||||||
|
human_byte_size = "{:.0f}kbytes".format((word_size * num_words)/1024/8)
|
||||||
|
|
||||||
|
# Allow byte writes
|
||||||
|
write_size = 8 # Bits
|
||||||
|
|
||||||
|
# Dual port
|
||||||
|
num_rw_ports = 1
|
||||||
|
num_r_ports = 1
|
||||||
|
num_w_ports = 0
|
||||||
|
ports_human = '1rw1r'
|
||||||
|
|
||||||
|
import os
|
||||||
|
exec(open(os.path.join(os.path.dirname(__file__), 'sky130_sram_common.py')).read())
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
"""
|
||||||
|
Dual port (1 read/write + 1 read only) 1 kbytes SRAM with byte write.
|
||||||
|
|
||||||
|
FIXME: What is this useful for?
|
||||||
|
FIXME: Why would you want byte write on this?
|
||||||
|
"""
|
||||||
|
word_size = 8 # Bits
|
||||||
|
num_words = 1024
|
||||||
|
human_byte_size = "{:.0f}kbytes".format((word_size * num_words)/1024/8)
|
||||||
|
|
||||||
|
# Allow byte writes
|
||||||
|
write_size = 8 # Bits
|
||||||
|
|
||||||
|
# Dual port
|
||||||
|
num_rw_ports = 1
|
||||||
|
num_r_ports = 1
|
||||||
|
num_w_ports = 0
|
||||||
|
ports_human = '1rw1r'
|
||||||
|
|
||||||
|
import os
|
||||||
|
exec(open(os.path.join(os.path.dirname(__file__), 'sky130_sram_common.py')).read())
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
"""
|
||||||
|
Single port, 1 kbytes SRAM, with byte write, useful for RISC-V processor main
|
||||||
|
memory.
|
||||||
|
"""
|
||||||
|
word_size = 32 # Bits
|
||||||
|
num_words = 256
|
||||||
|
human_byte_size = "{:.0f}kbytes".format((word_size * num_words)/1024/8)
|
||||||
|
|
||||||
|
# Allow byte writes
|
||||||
|
write_size = 8 # Bits
|
||||||
|
|
||||||
|
# Single port
|
||||||
|
num_rw_ports = 1
|
||||||
|
num_r_ports = 0
|
||||||
|
num_w_ports = 0
|
||||||
|
ports_human = '1rw'
|
||||||
|
|
||||||
|
import os
|
||||||
|
exec(open(os.path.join(os.path.dirname(__file__), 'sky130_sram_common.py')).read())
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
"""
|
||||||
|
Dual port (1 read/write + 1 read only), 2 kbytes SRAM (with byte write).
|
||||||
|
|
||||||
|
FIXME: What is this useful for?
|
||||||
|
FIXME: Why would you want byte write on this?
|
||||||
|
"""
|
||||||
|
word_size = 32 # Bits
|
||||||
|
num_words = 512
|
||||||
|
human_byte_size = "{:.0f}kbytes".format((word_size * num_words)/1024/8)
|
||||||
|
|
||||||
|
# Allow byte writes
|
||||||
|
write_size = 8 # Bits
|
||||||
|
|
||||||
|
# Dual port
|
||||||
|
num_rw_ports = 1
|
||||||
|
num_r_ports = 1
|
||||||
|
num_w_ports = 0
|
||||||
|
ports_human = '1rw1r'
|
||||||
|
|
||||||
|
import os
|
||||||
|
exec(open(os.path.join(os.path.dirname(__file__), 'sky130_sram_common.py')).read())
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
"""
|
||||||
|
Single port, 2 kbytes SRAM, with byte write, useful for RISC-V processor main
|
||||||
|
memory.
|
||||||
|
"""
|
||||||
|
word_size = 32 # Bits
|
||||||
|
num_words = 512
|
||||||
|
human_byte_size = "{:.0f}kbytes".format((word_size * num_words)/1024/8)
|
||||||
|
|
||||||
|
# Allow byte writes
|
||||||
|
write_size = 8 # Bits
|
||||||
|
|
||||||
|
# Single port
|
||||||
|
num_rw_ports = 1
|
||||||
|
num_r_ports = 0
|
||||||
|
num_w_ports = 0
|
||||||
|
ports_human = '1rw'
|
||||||
|
|
||||||
|
import os
|
||||||
|
exec(open(os.path.join(os.path.dirname(__file__), 'sky130_sram_common.py')).read())
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
"""
|
||||||
|
Dual port (1 read/write + 1 read only), 4 kbytes SRAM (with byte write).
|
||||||
|
|
||||||
|
FIXME: What is this useful for?
|
||||||
|
FIXME: Why would you want byte write on this?
|
||||||
|
"""
|
||||||
|
|
||||||
|
word_size = 32 # Bits
|
||||||
|
num_words = 1024
|
||||||
|
human_byte_size = "{:.0f}kbytes".format((word_size * num_words)/1024/8)
|
||||||
|
|
||||||
|
# Allow byte writes
|
||||||
|
write_size = 8 # Bits
|
||||||
|
|
||||||
|
# Dual port
|
||||||
|
num_rw_ports = 1
|
||||||
|
num_r_ports = 1
|
||||||
|
num_w_ports = 0
|
||||||
|
ports_human = '1rw1r'
|
||||||
|
|
||||||
|
import os
|
||||||
|
exec(open(os.path.join(os.path.dirname(__file__), 'sky130_sram_common.py')).read())
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
"""
|
||||||
|
Single port, 4 kbytes SRAM, with byte write, useful for RISC-V processor main
|
||||||
|
memory.
|
||||||
|
"""
|
||||||
|
|
||||||
|
word_size = 32 # Bits
|
||||||
|
num_words = 1024
|
||||||
|
human_byte_size = "{:.0f}kbytes".format((word_size * num_words)/1024/8)
|
||||||
|
|
||||||
|
# Allow byte writes
|
||||||
|
write_size = 8 # Bits
|
||||||
|
|
||||||
|
# Single port
|
||||||
|
num_rw_ports = 1
|
||||||
|
num_r_ports = 0
|
||||||
|
num_w_ports = 0
|
||||||
|
ports_human = '1rw'
|
||||||
|
|
||||||
|
import os
|
||||||
|
exec(open(os.path.join(os.path.dirname(__file__), 'sky130_sram_common.py')).read())
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Include with
|
||||||
|
# import os
|
||||||
|
# exec(open(os.path.join(os.path.dirname(__file__), 'sky130_sram_common.py')).read())
|
||||||
|
|
||||||
|
|
||||||
|
tech_name = "sky130"
|
||||||
|
nominal_corner_only = True
|
||||||
|
|
||||||
|
# Local wordlines have issues with met3 power routing for now
|
||||||
|
#local_array_size = 16
|
||||||
|
|
||||||
|
#route_supplies = False
|
||||||
|
check_lvsdrc = True
|
||||||
|
#perimeter_pins = False
|
||||||
|
#netlist_only = True
|
||||||
|
#analytical_delay = False
|
||||||
|
|
||||||
|
output_name = "{tech_name}_sram_{human_byte_size}_{ports_human}_{word_size}x{num_words}_{write_size}".format(**locals())
|
||||||
|
output_path = "macro/{output_name}".format(**locals())
|
||||||
|
|
@ -329,7 +329,7 @@ def read_config(config_file, is_unit_test=True):
|
||||||
debug.info(1, "Configuration file is " + config_file + ".py")
|
debug.info(1, "Configuration file is " + config_file + ".py")
|
||||||
try:
|
try:
|
||||||
config = importlib.import_module(module_name)
|
config = importlib.import_module(module_name)
|
||||||
except:
|
except ImportError:
|
||||||
debug.error("Unable to read configuration file: {0}".format(config_file), 2)
|
debug.error("Unable to read configuration file: {0}".format(config_file), 2)
|
||||||
|
|
||||||
OPTS.overridden = {}
|
OPTS.overridden = {}
|
||||||
|
|
|
||||||
|
|
@ -117,9 +117,10 @@ class write_mask_and_array(design.design):
|
||||||
for i in range(self.num_wmasks):
|
for i in range(self.num_wmasks):
|
||||||
# Route the A pin over to the left so that it doesn't conflict with the sense
|
# Route the A pin over to the left so that it doesn't conflict with the sense
|
||||||
# amp output which is usually in the center
|
# amp output which is usually in the center
|
||||||
a_pin = self.and2_insts[i].get_pin("A")
|
inst = self.and2_insts[i]
|
||||||
|
a_pin = inst.get_pin("A")
|
||||||
a_pos = a_pin.center()
|
a_pos = a_pin.center()
|
||||||
in_pos = vector(self.and2_insts[i].lx(),
|
in_pos = vector(inst.lx(),
|
||||||
a_pos.y)
|
a_pos.y)
|
||||||
self.add_via_stack_center(from_layer=a_pin.layer,
|
self.add_via_stack_center(from_layer=a_pin.layer,
|
||||||
to_layer="m2",
|
to_layer="m2",
|
||||||
|
|
@ -130,21 +131,31 @@ class write_mask_and_array(design.design):
|
||||||
self.add_path(a_pin.layer, [in_pos, a_pos])
|
self.add_path(a_pin.layer, [in_pos, a_pos])
|
||||||
|
|
||||||
# Copy remaining layout pins
|
# Copy remaining layout pins
|
||||||
self.copy_layout_pin(self.and2_insts[i], "Z", "wmask_out_{0}".format(i))
|
self.copy_layout_pin(inst, "Z", "wmask_out_{0}".format(i))
|
||||||
|
|
||||||
# Add via connections to metal3 for AND array's B pin
|
# Add via connections to metal3 for AND array's B pin
|
||||||
en_pin = self.and2_insts[i].get_pin("B")
|
en_pin = inst.get_pin("B")
|
||||||
en_pos = en_pin.center()
|
en_pos = en_pin.center()
|
||||||
self.add_via_stack_center(from_layer=en_pin.layer,
|
self.add_via_stack_center(from_layer=en_pin.layer,
|
||||||
to_layer="m3",
|
to_layer="m3",
|
||||||
offset=en_pos)
|
offset=en_pos)
|
||||||
|
|
||||||
|
# Add connection to the supply
|
||||||
|
for supply_name in ["gnd", "vdd"]:
|
||||||
|
supply_pin = inst.get_pin(supply_name)
|
||||||
|
self.add_via_stack_center(from_layer=supply_pin.layer,
|
||||||
|
to_layer="m1",
|
||||||
|
offset=supply_pin.center())
|
||||||
|
|
||||||
for supply in ["gnd", "vdd"]:
|
for supply in ["gnd", "vdd"]:
|
||||||
supply_pin = self.and2_insts[0].get_pin(supply)
|
supply_pin = self.and2_insts[0].get_pin(supply)
|
||||||
supply_pin_yoffset = supply_pin.cy()
|
supply_pin_yoffset = supply_pin.cy()
|
||||||
left_loc = vector(0, supply_pin_yoffset)
|
left_loc = vector(0, supply_pin_yoffset)
|
||||||
right_loc = vector(self.width, supply_pin_yoffset)
|
right_loc = vector(self.width, supply_pin_yoffset)
|
||||||
self.add_path(supply_pin.layer, [left_loc, right_loc])
|
self.add_path("m1", [left_loc, right_loc])
|
||||||
self.copy_power_pin(supply_pin, loc=left_loc)
|
for loc in [left_loc, right_loc]:
|
||||||
self.copy_power_pin(supply_pin, loc=right_loc)
|
self.add_via_stack_center(from_layer=supply_pin.layer,
|
||||||
|
to_layer="m1",
|
||||||
|
offset=loc)
|
||||||
|
self.copy_power_pin(supply_pin, loc=loc)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue