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
|
(horizontal_layer, via_layer, vertical_layer) = layer_stack
|
||||||
if horizontal:
|
if horizontal:
|
||||||
route_layer = vertical_layer
|
route_layer = vertical_layer
|
||||||
bys_layer = horizontal_layer
|
bus_layer = horizontal_layer
|
||||||
else:
|
else:
|
||||||
route_layer = horizontal_layer
|
route_layer = horizontal_layer
|
||||||
bus_layer = vertical_layer
|
bus_layer = vertical_layer
|
||||||
|
|
|
||||||
|
|
@ -379,6 +379,14 @@ class pin_layout:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
label_purpose = purpose
|
label_purpose = purpose
|
||||||
|
|
||||||
|
newLayout.addBox(layerNumber=layer_num,
|
||||||
|
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,
|
newLayout.addBox(layerNumber=layer_num,
|
||||||
purposeNumber=pin_purpose,
|
purposeNumber=pin_purpose,
|
||||||
offsetInMicrons=self.ll(),
|
offsetInMicrons=self.ll(),
|
||||||
|
|
|
||||||
|
|
@ -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
|
recordLength = struct.unpack(">h",recordLengthAscii) #gives us a tuple with a short int inside
|
||||||
offset_int = int(recordLength[0]) # extract length
|
offset_int = int(recordLength[0]) # extract length
|
||||||
offset += offset_int # count offset
|
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)
|
record = self.fileHandle.read(recordLength[0]-2) #read the rest of it (first 2 bytes were already read)
|
||||||
return record
|
return record
|
||||||
|
|
||||||
|
|
@ -176,7 +177,7 @@ class Gds2reader:
|
||||||
def readBoundary(self):
|
def readBoundary(self):
|
||||||
##reads in a boundary type structure = a filled polygon
|
##reads in a boundary type structure = a filled polygon
|
||||||
if(self.debugToTerminal==1):
|
if(self.debugToTerminal==1):
|
||||||
print("\t\t\tBeginBoundary")
|
print("\t\tBeginBoundary")
|
||||||
thisBoundary=GdsBoundary()
|
thisBoundary=GdsBoundary()
|
||||||
while 1:
|
while 1:
|
||||||
record = self.readNextRecord()
|
record = self.readNextRecord()
|
||||||
|
|
@ -214,13 +215,13 @@ class Gds2reader:
|
||||||
print("\t\t\tXY Point: "+str(x)+","+str(y))
|
print("\t\t\tXY Point: "+str(x)+","+str(y))
|
||||||
elif(idBits==b'\x11\x00'): #End Of Element
|
elif(idBits==b'\x11\x00'): #End Of Element
|
||||||
if(self.debugToTerminal==1):
|
if(self.debugToTerminal==1):
|
||||||
print("\t\t\tEndBoundary")
|
print("\t\tEndBoundary")
|
||||||
break;
|
break;
|
||||||
return thisBoundary
|
return thisBoundary
|
||||||
|
|
||||||
def readPath(self): #reads in a path structure
|
def readPath(self): #reads in a path structure
|
||||||
if(self.debugToTerminal==1):
|
if(self.debugToTerminal==1):
|
||||||
print("\t\t\tBeginPath")
|
print("\t\tBeginPath")
|
||||||
|
|
||||||
thisPath=GdsPath()
|
thisPath=GdsPath()
|
||||||
while 1:
|
while 1:
|
||||||
|
|
@ -274,7 +275,7 @@ class Gds2reader:
|
||||||
print("\t\t\tXY Point: "+str(x)+","+str(y))
|
print("\t\t\tXY Point: "+str(x)+","+str(y))
|
||||||
elif(idBits==b'\x11\x00'): #End Of Element
|
elif(idBits==b'\x11\x00'): #End Of Element
|
||||||
if(self.debugToTerminal==1):
|
if(self.debugToTerminal==1):
|
||||||
print("\t\t\tEndPath")
|
print("\t\tEndPath")
|
||||||
break;
|
break;
|
||||||
return thisPath
|
return thisPath
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -362,16 +362,8 @@ def end_openram():
|
||||||
verify.print_pex_stats()
|
verify.print_pex_stats()
|
||||||
|
|
||||||
|
|
||||||
def cleanup_paths():
|
def purge_temp():
|
||||||
"""
|
""" Remove the temp directory. """
|
||||||
We should clean up the temp directory after execution.
|
|
||||||
"""
|
|
||||||
global OPTS
|
|
||||||
if OPTS.keep_temp:
|
|
||||||
debug.info(0,
|
|
||||||
"Preserving temp directory: {}".format(OPTS.openram_temp))
|
|
||||||
return
|
|
||||||
elif os.path.exists(OPTS.openram_temp):
|
|
||||||
debug.info(1,
|
debug.info(1,
|
||||||
"Purging temp directory: {}".format(OPTS.openram_temp))
|
"Purging temp directory: {}".format(OPTS.openram_temp))
|
||||||
# This annoyingly means you have to re-cd into
|
# This annoyingly means you have to re-cd into
|
||||||
|
|
@ -385,6 +377,19 @@ def cleanup_paths():
|
||||||
shutil.rmtree(i)
|
shutil.rmtree(i)
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup_paths():
|
||||||
|
"""
|
||||||
|
We should clean up the temp directory after execution.
|
||||||
|
"""
|
||||||
|
global OPTS
|
||||||
|
if OPTS.keep_temp:
|
||||||
|
debug.info(0,
|
||||||
|
"Preserving temp directory: {}".format(OPTS.openram_temp))
|
||||||
|
return
|
||||||
|
elif os.path.exists(OPTS.openram_temp):
|
||||||
|
purge_temp()
|
||||||
|
|
||||||
|
|
||||||
def setup_paths():
|
def setup_paths():
|
||||||
""" Set up the non-tech related paths. """
|
""" Set up the non-tech related paths. """
|
||||||
debug.info(2, "Setting up paths...")
|
debug.info(2, "Setting up paths...")
|
||||||
|
|
@ -435,7 +440,9 @@ def find_exe(check_exe):
|
||||||
|
|
||||||
def init_paths():
|
def init_paths():
|
||||||
""" Create the temp and output directory if it doesn't exist """
|
""" Create the temp and output directory if it doesn't exist """
|
||||||
|
if os.path.exists(OPTS.openram_temp):
|
||||||
|
purge_temp()
|
||||||
|
else:
|
||||||
# make the directory if it doesn't exist
|
# make the directory if it doesn't exist
|
||||||
try:
|
try:
|
||||||
debug.info(1,
|
debug.info(1,
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ class col_cap_array(bitcell_base_array):
|
||||||
inst = self.cell_inst[row, col]
|
inst = self.cell_inst[row, col]
|
||||||
for pin_name in ["vdd", "gnd"]:
|
for pin_name in ["vdd", "gnd"]:
|
||||||
for pin in inst.get_pins(pin_name):
|
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(),
|
loc=pin.center(),
|
||||||
start_layer=pin.layer)
|
start_layer=pin.layer)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -390,20 +390,19 @@ class replica_bitcell_array(bitcell_base_array):
|
||||||
# These grow up, away from the array
|
# These grow up, away from the array
|
||||||
for bit in range(self.rbl[1]):
|
for bit in range(self.rbl[1]):
|
||||||
dummy_offset = self.bitcell_offset.scale(0, bit + bit % 2) + self.bitcell_array_inst.ul()
|
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,
|
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):
|
def add_end_caps(self):
|
||||||
""" Add dummy cells or end caps around the array """
|
""" 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 if even number of rows)
|
||||||
# Far top dummy row (first row above array is NOT flipped)
|
flip_dummy = (self.row_size + self.rbl[1]) % 2
|
||||||
flip_dummy = self.rbl[1] % 2
|
|
||||||
dummy_row_offset = self.bitcell_offset.scale(0, self.rbl[1] + flip_dummy) + self.bitcell_array_inst.ul()
|
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,
|
self.dummy_row_insts[1].place(offset=dummy_row_offset,
|
||||||
mirror="MX" if flip_dummy else "R0")
|
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)
|
# Far bottom dummy row (first row below array IS flipped)
|
||||||
flip_dummy = (self.rbl[0] + 1) % 2
|
flip_dummy = (self.rbl[0] + 1) % 2
|
||||||
dummy_row_offset = self.bitcell_offset.scale(0, -self.rbl[0] - 1 + flip_dummy) + self.unused_offset
|
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):
|
def add_layout_pins(self):
|
||||||
""" Add the layout pins """
|
""" Add the layout pins """
|
||||||
|
|
||||||
#All wordlines
|
# All wordlines
|
||||||
#Main array wl and bl/br
|
# Main array wl and bl/br
|
||||||
|
|
||||||
for pin_name in self.all_wordline_names:
|
for pin_name in self.all_wordline_names:
|
||||||
pin_list = self.bitcell_array_inst.get_pins(pin_name)
|
pin_list = self.bitcell_array_inst.get_pins(pin_name)
|
||||||
for pin in pin_list:
|
for pin in pin_list:
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ class row_cap_array(bitcell_base_array):
|
||||||
inst = self.cell_inst[row, col]
|
inst = self.cell_inst[row, col]
|
||||||
for pin_name in ["vdd", "gnd"]:
|
for pin_name in ["vdd", "gnd"]:
|
||||||
for pin in inst.get_pins(pin_name):
|
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(),
|
loc=pin.center(),
|
||||||
start_layer=pin.layer)
|
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()
|
factory.reset()
|
||||||
debug.info(2, "Testing 4x4 array for bitcell")
|
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)
|
self.local_check(a)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
|
||||||
|
|
@ -104,9 +104,9 @@ def write_lvs_script(cell_name, gds_name, sp_name, final_verification=False, out
|
||||||
'lvsRecognizeGates': 'NONE',
|
'lvsRecognizeGates': 'NONE',
|
||||||
}
|
}
|
||||||
# FIXME: Remove when vdd/gnd connected
|
# FIXME: Remove when vdd/gnd connected
|
||||||
#'cmnVConnectNamesState' : 'ALL', #connects all nets with the same namee
|
# 'cmnVConnectNamesState' : 'ALL', #connects all nets with the same namee
|
||||||
# FIXME: Remove when vdd/gnd connected
|
# FIXME: Remove when vdd/gnd connected
|
||||||
#'lvsAbortOnSupplyError' : 0
|
# 'lvsAbortOnSupplyError' : 0
|
||||||
|
|
||||||
if not final_verification or not OPTS.route_supplies:
|
if not final_verification or not OPTS.route_supplies:
|
||||||
lvs_runset['cmnVConnectReport']=1
|
lvs_runset['cmnVConnectReport']=1
|
||||||
|
|
@ -115,8 +115,6 @@ def write_lvs_script(cell_name, gds_name, sp_name, final_verification=False, out
|
||||||
else:
|
else:
|
||||||
lvs_runset['lvsAbortOnSupplyError']=1
|
lvs_runset['lvsAbortOnSupplyError']=1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# write the runset file
|
# write the runset file
|
||||||
f = open(output_path + "lvs_runset", "w")
|
f = open(output_path + "lvs_runset", "w")
|
||||||
for k in sorted(iter(lvs_runset.keys())):
|
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 warning default\n")
|
||||||
f.write("gds flatten true\n")
|
f.write("gds flatten true\n")
|
||||||
f.write("gds readonly true\n")
|
f.write("gds readonly true\n")
|
||||||
|
f.write("gds ordering true\n")
|
||||||
f.write("gds read {}\n".format(gds_name))
|
f.write("gds read {}\n".format(gds_name))
|
||||||
f.write('puts "Finished reading gds {}"\n'.format(gds_name))
|
f.write('puts "Finished reading gds {}"\n'.format(gds_name))
|
||||||
f.write("load {}\n".format(cell_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 = open(run_file, "w")
|
||||||
f.write("#!/bin/sh\n")
|
f.write("#!/bin/sh\n")
|
||||||
f.write('export OPENRAM_TECH="{}"\n'.format(os.environ['OPENRAM_TECH']))
|
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("{} -noconsole << EOF\n".format(OPTS.lvs_exe[1]))
|
||||||
# f.write("readnet spice {0}.spice\n".format(cell_name))
|
# f.write("readnet spice {0}.spice\n".format(cell_name))
|
||||||
# f.write("readnet spice {0}\n".format(sp_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("quit\n")
|
||||||
f.write("EOF\n")
|
f.write("EOF\n")
|
||||||
f.write("magic_retcode=$?\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.write("exit $magic_retcode\n")
|
||||||
f.close()
|
f.close()
|
||||||
os.system("chmod u+x {}".format(run_file))
|
os.system("chmod u+x {}".format(run_file))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue