mirror of https://github.com/VLSIDA/OpenRAM.git
Merge remote-tracking branch 'private/dev' into dev
This commit is contained in:
commit
ebe19abf60
|
|
@ -976,7 +976,7 @@ class layout():
|
|||
(horizontal_layer, via_layer, vertical_layer) = layer_stack
|
||||
if horizontal:
|
||||
route_layer = vertical_layer
|
||||
bys_layer = horizontal_layer
|
||||
bus_layer = horizontal_layer
|
||||
else:
|
||||
route_layer = horizontal_layer
|
||||
bus_layer = vertical_layer
|
||||
|
|
|
|||
|
|
@ -380,11 +380,19 @@ class pin_layout:
|
|||
label_purpose = purpose
|
||||
|
||||
newLayout.addBox(layerNumber=layer_num,
|
||||
purposeNumber=pin_purpose,
|
||||
purposeNumber=purpose,
|
||||
offsetInMicrons=self.ll(),
|
||||
width=self.width(),
|
||||
height=self.height(),
|
||||
center=False)
|
||||
# Draw a second pin shape too
|
||||
if pin_purpose != purpose:
|
||||
newLayout.addBox(layerNumber=layer_num,
|
||||
purposeNumber=pin_purpose,
|
||||
offsetInMicrons=self.ll(),
|
||||
width=self.width(),
|
||||
height=self.height(),
|
||||
center=False)
|
||||
# Add the tet in the middle of the pin.
|
||||
# This fixes some pin label offsetting when GDS gets
|
||||
# imported into Magic.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2019 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 debug
|
||||
from tech import cell_properties as props
|
||||
import bitcell_base
|
||||
|
||||
|
||||
class col_cap_bitcell_1port(bitcell_base.bitcell_base):
|
||||
"""
|
||||
Column end cap cell.
|
||||
"""
|
||||
|
||||
def __init__(self, name="col_cap_bitcell_1port"):
|
||||
bitcell_base.bitcell_base.__init__(self, name, prop=props.col_cap_1port)
|
||||
debug.info(2, "Create col_cap bitcell 1 port object")
|
||||
|
||||
self.no_instances = True
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2019 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 debug
|
||||
from tech import cell_properties as props
|
||||
import bitcell_base
|
||||
|
||||
|
||||
class row_cap_bitcell_1port(bitcell_base.bitcell_base):
|
||||
"""
|
||||
Row end cap cell.
|
||||
"""
|
||||
|
||||
def __init__(self, name="row_cap_bitcell_1port"):
|
||||
bitcell_base.bitcell_base.__init__(self, name, prop=props.row_cap_1port)
|
||||
debug.info(2, "Create row_cap bitcell 1 port object")
|
||||
|
||||
self.no_instances = True
|
||||
|
|
@ -79,7 +79,8 @@ class Gds2reader:
|
|||
recordLength = struct.unpack(">h",recordLengthAscii) #gives us a tuple with a short int inside
|
||||
offset_int = int(recordLength[0]) # extract length
|
||||
offset += offset_int # count offset
|
||||
#print(offset) #print out the record numbers for de-bugging
|
||||
if(self.debugToTerminal==1):
|
||||
print("Offset: " + str(offset)) #print out the record numbers for de-bugging
|
||||
record = self.fileHandle.read(recordLength[0]-2) #read the rest of it (first 2 bytes were already read)
|
||||
return record
|
||||
|
||||
|
|
@ -176,7 +177,7 @@ class Gds2reader:
|
|||
def readBoundary(self):
|
||||
##reads in a boundary type structure = a filled polygon
|
||||
if(self.debugToTerminal==1):
|
||||
print("\t\t\tBeginBoundary")
|
||||
print("\t\tBeginBoundary")
|
||||
thisBoundary=GdsBoundary()
|
||||
while 1:
|
||||
record = self.readNextRecord()
|
||||
|
|
@ -214,13 +215,13 @@ class Gds2reader:
|
|||
print("\t\t\tXY Point: "+str(x)+","+str(y))
|
||||
elif(idBits==b'\x11\x00'): #End Of Element
|
||||
if(self.debugToTerminal==1):
|
||||
print("\t\t\tEndBoundary")
|
||||
print("\t\tEndBoundary")
|
||||
break;
|
||||
return thisBoundary
|
||||
|
||||
def readPath(self): #reads in a path structure
|
||||
if(self.debugToTerminal==1):
|
||||
print("\t\t\tBeginPath")
|
||||
print("\t\tBeginPath")
|
||||
|
||||
thisPath=GdsPath()
|
||||
while 1:
|
||||
|
|
@ -274,7 +275,7 @@ class Gds2reader:
|
|||
print("\t\t\tXY Point: "+str(x)+","+str(y))
|
||||
elif(idBits==b'\x11\x00'): #End Of Element
|
||||
if(self.debugToTerminal==1):
|
||||
print("\t\t\tEndPath")
|
||||
print("\t\tEndPath")
|
||||
break;
|
||||
return thisPath
|
||||
|
||||
|
|
|
|||
|
|
@ -361,6 +361,21 @@ def end_openram():
|
|||
verify.print_lvs_stats()
|
||||
verify.print_pex_stats()
|
||||
|
||||
|
||||
def purge_temp():
|
||||
""" Remove the temp directory. """
|
||||
debug.info(1,
|
||||
"Purging temp directory: {}".format(OPTS.openram_temp))
|
||||
# This annoyingly means you have to re-cd into
|
||||
# the directory each debug iteration
|
||||
# shutil.rmtree(OPTS.openram_temp, ignore_errors=True)
|
||||
contents = [os.path.join(OPTS.openram_temp, i) for i in os.listdir(OPTS.openram_temp)]
|
||||
for i in contents:
|
||||
if os.path.isfile(i) or os.path.islink(i):
|
||||
os.remove(i)
|
||||
else:
|
||||
shutil.rmtree(i)
|
||||
|
||||
|
||||
def cleanup_paths():
|
||||
"""
|
||||
|
|
@ -372,19 +387,9 @@ def cleanup_paths():
|
|||
"Preserving temp directory: {}".format(OPTS.openram_temp))
|
||||
return
|
||||
elif os.path.exists(OPTS.openram_temp):
|
||||
debug.info(1,
|
||||
"Purging temp directory: {}".format(OPTS.openram_temp))
|
||||
# This annoyingly means you have to re-cd into
|
||||
# the directory each debug iteration
|
||||
# shutil.rmtree(OPTS.openram_temp, ignore_errors=True)
|
||||
contents = [os.path.join(OPTS.openram_temp, i) for i in os.listdir(OPTS.openram_temp)]
|
||||
for i in contents:
|
||||
if os.path.isfile(i) or os.path.islink(i):
|
||||
os.remove(i)
|
||||
else:
|
||||
shutil.rmtree(i)
|
||||
|
||||
purge_temp()
|
||||
|
||||
|
||||
def setup_paths():
|
||||
""" Set up the non-tech related paths. """
|
||||
debug.info(2, "Setting up paths...")
|
||||
|
|
@ -413,7 +418,7 @@ def setup_paths():
|
|||
OPTS.openram_temp += "/"
|
||||
debug.info(1, "Temporary files saved in " + OPTS.openram_temp)
|
||||
|
||||
|
||||
|
||||
def is_exe(fpath):
|
||||
""" Return true if the given is an executable file that exists. """
|
||||
return os.path.exists(fpath) and os.access(fpath, os.X_OK)
|
||||
|
|
@ -435,15 +440,17 @@ def find_exe(check_exe):
|
|||
|
||||
def init_paths():
|
||||
""" Create the temp and output directory if it doesn't exist """
|
||||
|
||||
# make the directory if it doesn't exist
|
||||
try:
|
||||
debug.info(1,
|
||||
"Creating temp directory: {}".format(OPTS.openram_temp))
|
||||
os.makedirs(OPTS.openram_temp, 0o750)
|
||||
except OSError as e:
|
||||
if e.errno == 17: # errno.EEXIST
|
||||
os.chmod(OPTS.openram_temp, 0o750)
|
||||
if os.path.exists(OPTS.openram_temp):
|
||||
purge_temp()
|
||||
else:
|
||||
# make the directory if it doesn't exist
|
||||
try:
|
||||
debug.info(1,
|
||||
"Creating temp directory: {}".format(OPTS.openram_temp))
|
||||
os.makedirs(OPTS.openram_temp, 0o750)
|
||||
except OSError as e:
|
||||
if e.errno == 17: # errno.EEXIST
|
||||
os.chmod(OPTS.openram_temp, 0o750)
|
||||
|
||||
# Don't delete the output dir, it may have other files!
|
||||
# make the directory if it doesn't exist
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class col_cap_array(bitcell_base_array):
|
|||
inst = self.cell_inst[row, col]
|
||||
for pin_name in ["vdd", "gnd"]:
|
||||
for pin in inst.get_pins(pin_name):
|
||||
self.add_power_pin(name=pin.name,
|
||||
self.add_power_pin(name=pin_name,
|
||||
loc=pin.center(),
|
||||
start_layer=pin.layer)
|
||||
|
||||
|
|
|
|||
|
|
@ -390,20 +390,19 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
# These grow up, away from the array
|
||||
for bit in range(self.rbl[1]):
|
||||
dummy_offset = self.bitcell_offset.scale(0, bit + bit % 2) + self.bitcell_array_inst.ul()
|
||||
import pdb; pdb.set_trace()
|
||||
self.dummy_row_replica_insts[self.rbl[0] + bit].place(offset=dummy_offset,
|
||||
mirror="MX" if bit % 2 else "R0")
|
||||
mirror="MX" if (self.row_size + bit) % 2 else "R0")
|
||||
|
||||
def add_end_caps(self):
|
||||
""" Add dummy cells or end caps around the array """
|
||||
|
||||
# FIXME: These depend on the array size itself
|
||||
# Far top dummy row (first row above array is NOT flipped)
|
||||
flip_dummy = self.rbl[1] % 2
|
||||
# Far top dummy row (first row above array is NOT flipped if even number of rows)
|
||||
flip_dummy = (self.row_size + self.rbl[1]) % 2
|
||||
dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul()
|
||||
self.dummy_row_insts[1].place(offset=dummy_row_offset,
|
||||
mirror="MX" if flip_dummy else "R0")
|
||||
|
||||
# FIXME: These depend on the array size itself
|
||||
# Far bottom dummy row (first row below array IS flipped)
|
||||
flip_dummy = (self.rbl[0] + 1) % 2
|
||||
dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - 1 + flip_dummy) + self.unused_offset
|
||||
|
|
@ -422,9 +421,8 @@ class replica_bitcell_array(bitcell_base_array):
|
|||
def add_layout_pins(self):
|
||||
""" Add the layout pins """
|
||||
|
||||
#All wordlines
|
||||
#Main array wl and bl/br
|
||||
|
||||
# All wordlines
|
||||
# Main array wl and bl/br
|
||||
for pin_name in self.all_wordline_names:
|
||||
pin_list = self.bitcell_array_inst.get_pins(pin_name)
|
||||
for pin in pin_list:
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ class row_cap_array(bitcell_base_array):
|
|||
inst = self.cell_inst[row, col]
|
||||
for pin_name in ["vdd", "gnd"]:
|
||||
for pin in inst.get_pins(pin_name):
|
||||
self.add_power_pin(name=pin.name,
|
||||
self.add_power_pin(name=pin_name,
|
||||
loc=pin.center(),
|
||||
start_layer=pin.layer)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from gdsMill import gdsMill
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: {0} file.gds".format(sys.argv[0]))
|
||||
sys.exit(1)
|
||||
|
||||
gds_file = sys.argv[1]
|
||||
arrayCellLayout = gdsMill.VlsiLayout()
|
||||
reader = gdsMill.Gds2reader(arrayCellLayout,debugToTerminal = 1)
|
||||
reader.loadFromFile(gds_file)
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ class replica_bitcell_array_test(openram_test):
|
|||
|
||||
factory.reset()
|
||||
debug.info(2, "Testing 4x4 array for bitcell")
|
||||
a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, rbl=[1, 0])
|
||||
a = factory.create(module_type="replica_bitcell_array", cols=7, rows=5, rbl=[1, 0])
|
||||
self.local_check(a)
|
||||
|
||||
globals.end_openram()
|
||||
|
|
|
|||
|
|
@ -103,10 +103,10 @@ def write_lvs_script(cell_name, gds_name, sp_name, final_verification=False, out
|
|||
'cmnTranscriptEchoToFile': 1,
|
||||
'lvsRecognizeGates': 'NONE',
|
||||
}
|
||||
# FIXME: Remove when vdd/gnd connected
|
||||
#'cmnVConnectNamesState' : 'ALL', #connects all nets with the same namee
|
||||
# FIXME: Remove when vdd/gnd connected
|
||||
#'lvsAbortOnSupplyError' : 0
|
||||
# FIXME: Remove when vdd/gnd connected
|
||||
# 'cmnVConnectNamesState' : 'ALL', #connects all nets with the same namee
|
||||
# FIXME: Remove when vdd/gnd connected
|
||||
# 'lvsAbortOnSupplyError' : 0
|
||||
|
||||
if not final_verification or not OPTS.route_supplies:
|
||||
lvs_runset['cmnVConnectReport']=1
|
||||
|
|
@ -115,8 +115,6 @@ def write_lvs_script(cell_name, gds_name, sp_name, final_verification=False, out
|
|||
else:
|
||||
lvs_runset['lvsAbortOnSupplyError']=1
|
||||
|
||||
|
||||
|
||||
# write the runset file
|
||||
f = open(output_path + "lvs_runset", "w")
|
||||
for k in sorted(iter(lvs_runset.keys())):
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ def write_drc_script(cell_name, gds_name, extract, final_verification, output_pa
|
|||
f.write("gds warning default\n")
|
||||
f.write("gds flatten true\n")
|
||||
f.write("gds readonly true\n")
|
||||
f.write("gds ordering true\n")
|
||||
f.write("gds read {}\n".format(gds_name))
|
||||
f.write('puts "Finished reading gds {}"\n'.format(gds_name))
|
||||
f.write("load {}\n".format(cell_name))
|
||||
|
|
@ -218,7 +219,7 @@ def write_lvs_script(cell_name, gds_name, sp_name, final_verification=False, out
|
|||
f = open(run_file, "w")
|
||||
f.write("#!/bin/sh\n")
|
||||
f.write('export OPENRAM_TECH="{}"\n'.format(os.environ['OPENRAM_TECH']))
|
||||
f.write('echo "$(date): Starting LVS using Magic {}"\n'.format(OPTS.drc_exe[1]))
|
||||
f.write('echo "$(date): Starting LVS using Netgen {}"\n'.format(OPTS.lvs_exe[1]))
|
||||
f.write("{} -noconsole << EOF\n".format(OPTS.lvs_exe[1]))
|
||||
# f.write("readnet spice {0}.spice\n".format(cell_name))
|
||||
# f.write("readnet spice {0}\n".format(sp_name))
|
||||
|
|
@ -226,7 +227,7 @@ def write_lvs_script(cell_name, gds_name, sp_name, final_verification=False, out
|
|||
f.write("quit\n")
|
||||
f.write("EOF\n")
|
||||
f.write("magic_retcode=$?\n")
|
||||
f.write('echo "$(date): Finished ($magic_retcode) LVS using Magic {}"\n'.format(OPTS.drc_exe[1]))
|
||||
f.write('echo "$(date): Finished ($magic_retcode) LVS using Netgen {}"\n'.format(OPTS.lvs_exe[1]))
|
||||
f.write("exit $magic_retcode\n")
|
||||
f.close()
|
||||
os.system("chmod u+x {}".format(run_file))
|
||||
|
|
|
|||
Loading…
Reference in New Issue