Merge remote-tracking branch 'private/dev' into dev

This commit is contained in:
mrg 2020-12-08 10:50:02 -08:00
commit ebe19abf60
13 changed files with 119 additions and 48 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

14
compiler/printGDS.py Executable file
View File

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

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

View File

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

View File

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