mirror of https://github.com/VLSIDA/OpenRAM.git
Make purposes argument to gdsMill. Create prefixGDS.py script.
This commit is contained in:
parent
a0921b4afc
commit
8d71a98ce9
|
|
@ -20,6 +20,10 @@ from globals import OPTS
|
||||||
from vector import vector
|
from vector import vector
|
||||||
from pin_layout import pin_layout
|
from pin_layout import pin_layout
|
||||||
from utils import round_to_grid
|
from utils import round_to_grid
|
||||||
|
try:
|
||||||
|
from tech import special_purposes
|
||||||
|
except ImportError:
|
||||||
|
special_purposes = {}
|
||||||
|
|
||||||
|
|
||||||
class layout():
|
class layout():
|
||||||
|
|
@ -36,9 +40,9 @@ class layout():
|
||||||
# This gets set in both spice and layout so either can be called first.
|
# This gets set in both spice and layout so either can be called first.
|
||||||
self.name = name
|
self.name = name
|
||||||
self.cell_name = cell_name
|
self.cell_name = cell_name
|
||||||
|
|
||||||
self.gds_file = OPTS.openram_tech + "gds_lib/" + cell_name + ".gds"
|
self.gds_file = OPTS.openram_tech + "gds_lib/" + cell_name + ".gds"
|
||||||
|
|
||||||
self.width = None
|
self.width = None
|
||||||
self.height = None
|
self.height = None
|
||||||
self.bounding_box = None # The rectangle shape
|
self.bounding_box = None # The rectangle shape
|
||||||
|
|
@ -58,7 +62,7 @@ class layout():
|
||||||
self.visited = []
|
self.visited = []
|
||||||
# Flag for library cells
|
# Flag for library cells
|
||||||
self.is_library_cell = False
|
self.is_library_cell = False
|
||||||
|
|
||||||
self.gds_read()
|
self.gds_read()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -66,7 +70,7 @@ class layout():
|
||||||
self.pwr_grid_layer = power_grid[0]
|
self.pwr_grid_layer = power_grid[0]
|
||||||
except ImportError:
|
except ImportError:
|
||||||
self.pwr_grid_layer = "m3"
|
self.pwr_grid_layer = "m3"
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# GDS layout
|
# GDS layout
|
||||||
############################################################
|
############################################################
|
||||||
|
|
@ -118,7 +122,7 @@ class layout():
|
||||||
if len(self.objs) > 0:
|
if len(self.objs) > 0:
|
||||||
lowestx = min(min(obj.lx() for obj in self.objs if obj.name != "label"), lowestx)
|
lowestx = min(min(obj.lx() for obj in self.objs if obj.name != "label"), lowestx)
|
||||||
lowesty = min(min(obj.by() for obj in self.objs if obj.name != "label"), lowesty)
|
lowesty = min(min(obj.by() for obj in self.objs if obj.name != "label"), lowesty)
|
||||||
|
|
||||||
if len(self.insts) > 0:
|
if len(self.insts) > 0:
|
||||||
lowestx = min(min(inst.lx() for inst in self.insts), lowestx)
|
lowestx = min(min(inst.lx() for inst in self.insts), lowestx)
|
||||||
lowesty = min(min(inst.by() for inst in self.insts), lowesty)
|
lowesty = min(min(inst.by() for inst in self.insts), lowesty)
|
||||||
|
|
@ -129,7 +133,7 @@ class layout():
|
||||||
continue
|
continue
|
||||||
lowestx = min(min(pin.lx() for pin in pin_set), lowestx)
|
lowestx = min(min(pin.lx() for pin in pin_set), lowestx)
|
||||||
lowesty = min(min(pin.by() for pin in pin_set), lowesty)
|
lowesty = min(min(pin.by() for pin in pin_set), lowesty)
|
||||||
|
|
||||||
return vector(lowestx, lowesty)
|
return vector(lowestx, lowesty)
|
||||||
|
|
||||||
def find_highest_coords(self):
|
def find_highest_coords(self):
|
||||||
|
|
@ -138,7 +142,7 @@ class layout():
|
||||||
this layout
|
this layout
|
||||||
"""
|
"""
|
||||||
highestx = highesty = -sys.maxsize - 1
|
highestx = highesty = -sys.maxsize - 1
|
||||||
|
|
||||||
if len(self.objs) > 0:
|
if len(self.objs) > 0:
|
||||||
highestx = max(max(obj.rx() for obj in self.objs if obj.name != "label"), highestx)
|
highestx = max(max(obj.rx() for obj in self.objs if obj.name != "label"), highestx)
|
||||||
highesty = max(max(obj.uy() for obj in self.objs if obj.name != "label"), highesty)
|
highesty = max(max(obj.uy() for obj in self.objs if obj.name != "label"), highesty)
|
||||||
|
|
@ -153,7 +157,7 @@ class layout():
|
||||||
continue
|
continue
|
||||||
highestx = max(max(pin.rx() for pin in pin_set), highestx)
|
highestx = max(max(pin.rx() for pin in pin_set), highestx)
|
||||||
highesty = max(max(pin.uy() for pin in pin_set), highesty)
|
highesty = max(max(pin.uy() for pin in pin_set), highesty)
|
||||||
|
|
||||||
return vector(highestx, highesty)
|
return vector(highestx, highesty)
|
||||||
|
|
||||||
def find_highest_layer_coords(self, layer):
|
def find_highest_layer_coords(self, layer):
|
||||||
|
|
@ -234,7 +238,7 @@ class layout():
|
||||||
# This is commented out for runtime reasons
|
# This is commented out for runtime reasons
|
||||||
# debug.info(4, "instance list: " + ",".join(x.name for x in self.insts))
|
# debug.info(4, "instance list: " + ",".join(x.name for x in self.insts))
|
||||||
return self.insts[-1]
|
return self.insts[-1]
|
||||||
|
|
||||||
def get_inst(self, name):
|
def get_inst(self, name):
|
||||||
""" Retrieve an instance by name """
|
""" Retrieve an instance by name """
|
||||||
for inst in self.insts:
|
for inst in self.insts:
|
||||||
|
|
@ -332,7 +336,7 @@ class layout():
|
||||||
Return the pin or list of pins
|
Return the pin or list of pins
|
||||||
"""
|
"""
|
||||||
name = self.get_pin_name(text)
|
name = self.get_pin_name(text)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if len(self.pin_map[name]) > 1:
|
if len(self.pin_map[name]) > 1:
|
||||||
debug.error("Should use a pin iterator since more than one pin {}".format(text), -1)
|
debug.error("Should use a pin iterator since more than one pin {}".format(text), -1)
|
||||||
|
|
@ -349,7 +353,7 @@ class layout():
|
||||||
Return a pin list (instead of a single pin)
|
Return a pin list (instead of a single pin)
|
||||||
"""
|
"""
|
||||||
name = self.get_pin_name(text)
|
name = self.get_pin_name(text)
|
||||||
|
|
||||||
if name in self.pin_map.keys():
|
if name in self.pin_map.keys():
|
||||||
return self.pin_map[name]
|
return self.pin_map[name]
|
||||||
else:
|
else:
|
||||||
|
|
@ -360,12 +364,12 @@ class layout():
|
||||||
Create a mapping from internal pin names to external pin names.
|
Create a mapping from internal pin names to external pin names.
|
||||||
"""
|
"""
|
||||||
self.pin_names = pin_dict
|
self.pin_names = pin_dict
|
||||||
|
|
||||||
self.original_pin_names = {y: x for (x, y) in self.pin_names.items()}
|
self.original_pin_names = {y: x for (x, y) in self.pin_names.items()}
|
||||||
|
|
||||||
def get_pin_name(self, text):
|
def get_pin_name(self, text):
|
||||||
""" Return the custom cell pin name """
|
""" Return the custom cell pin name """
|
||||||
|
|
||||||
if text in self.pin_names:
|
if text in self.pin_names:
|
||||||
return self.pin_names[text]
|
return self.pin_names[text]
|
||||||
else:
|
else:
|
||||||
|
|
@ -373,7 +377,7 @@ class layout():
|
||||||
|
|
||||||
def get_original_pin_names(self):
|
def get_original_pin_names(self):
|
||||||
""" Return the internal cell pin name """
|
""" Return the internal cell pin name """
|
||||||
|
|
||||||
# This uses the hierarchy_spice pins (in order)
|
# This uses the hierarchy_spice pins (in order)
|
||||||
return [self.get_original_pin_name(x) for x in self.pins]
|
return [self.get_original_pin_name(x) for x in self.pins]
|
||||||
|
|
||||||
|
|
@ -383,7 +387,7 @@ class layout():
|
||||||
return self.original_pin_names[text]
|
return self.original_pin_names[text]
|
||||||
else:
|
else:
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def get_pin_names(self):
|
def get_pin_names(self):
|
||||||
"""
|
"""
|
||||||
Return a pin list of all pins
|
Return a pin list of all pins
|
||||||
|
|
@ -480,7 +484,7 @@ class layout():
|
||||||
offset=s.ll(),
|
offset=s.ll(),
|
||||||
width=s.width(),
|
width=s.width(),
|
||||||
height=s.height())
|
height=s.height())
|
||||||
|
|
||||||
def replace_layout_pin(self, text, pin):
|
def replace_layout_pin(self, text, pin):
|
||||||
"""
|
"""
|
||||||
Remove the old pin and replace with a new one
|
Remove the old pin and replace with a new one
|
||||||
|
|
@ -495,7 +499,7 @@ class layout():
|
||||||
offset=pin.ll(),
|
offset=pin.ll(),
|
||||||
width=pin.width(),
|
width=pin.width(),
|
||||||
height=pin.height())
|
height=pin.height())
|
||||||
|
|
||||||
def add_layout_pin(self, text, layer, offset, width=None, height=None):
|
def add_layout_pin(self, text, layer, offset, width=None, height=None):
|
||||||
"""
|
"""
|
||||||
Create a labeled pin
|
Create a labeled pin
|
||||||
|
|
@ -777,7 +781,7 @@ class layout():
|
||||||
debug.info(3, "opening {}".format(self.gds_file))
|
debug.info(3, "opening {}".format(self.gds_file))
|
||||||
self.gds = gdsMill.VlsiLayout(units=GDS["unit"])
|
self.gds = gdsMill.VlsiLayout(units=GDS["unit"])
|
||||||
reader = gdsMill.Gds2reader(self.gds)
|
reader = gdsMill.Gds2reader(self.gds)
|
||||||
reader.loadFromFile(self.gds_file)
|
reader.loadFromFile(self.gds_file, special_purposes)
|
||||||
else:
|
else:
|
||||||
debug.info(3, "Creating layout structure {}".format(self.name))
|
debug.info(3, "Creating layout structure {}".format(self.name))
|
||||||
self.gds = gdsMill.VlsiLayout(name=self.name, units=GDS["unit"])
|
self.gds = gdsMill.VlsiLayout(name=self.name, units=GDS["unit"])
|
||||||
|
|
@ -789,7 +793,7 @@ class layout():
|
||||||
debug.info(4, "Printing {}".format(gds_file))
|
debug.info(4, "Printing {}".format(gds_file))
|
||||||
arrayCellLayout = gdsMill.VlsiLayout(units=GDS["unit"])
|
arrayCellLayout = gdsMill.VlsiLayout(units=GDS["unit"])
|
||||||
reader = gdsMill.Gds2reader(arrayCellLayout, debugToTerminal=1)
|
reader = gdsMill.Gds2reader(arrayCellLayout, debugToTerminal=1)
|
||||||
reader.loadFromFile(gds_file)
|
reader.loadFromFile(gds_file, special_purposes)
|
||||||
|
|
||||||
def clear_visited(self):
|
def clear_visited(self):
|
||||||
""" Recursively clear the visited flag """
|
""" Recursively clear the visited flag """
|
||||||
|
|
@ -1126,7 +1130,7 @@ class layout():
|
||||||
# self.add_inst(cr.name, cr)
|
# self.add_inst(cr.name, cr)
|
||||||
# self.connect_inst([])
|
# self.connect_inst([])
|
||||||
self.add_flat_inst(cr.name, cr)
|
self.add_flat_inst(cr.name, cr)
|
||||||
|
|
||||||
def create_horizontal_channel_route(self, netlist, offset, layer_stack, directions=None):
|
def create_horizontal_channel_route(self, netlist, offset, layer_stack, directions=None):
|
||||||
"""
|
"""
|
||||||
Wrapper to create a horizontal channel route
|
Wrapper to create a horizontal channel route
|
||||||
|
|
@ -1138,7 +1142,7 @@ class layout():
|
||||||
# self.add_inst(cr.name, cr)
|
# self.add_inst(cr.name, cr)
|
||||||
# self.connect_inst([])
|
# self.connect_inst([])
|
||||||
self.add_flat_inst(cr.name, cr)
|
self.add_flat_inst(cr.name, cr)
|
||||||
|
|
||||||
def add_boundary(self, ll=vector(0, 0), ur=None):
|
def add_boundary(self, ll=vector(0, 0), ur=None):
|
||||||
""" Add boundary for debugging dimensions """
|
""" Add boundary for debugging dimensions """
|
||||||
if OPTS.netlist_only:
|
if OPTS.netlist_only:
|
||||||
|
|
@ -1331,7 +1335,7 @@ class layout():
|
||||||
new_name = pin.name
|
new_name = pin.name
|
||||||
if not loc:
|
if not loc:
|
||||||
loc = pin.center()
|
loc = pin.center()
|
||||||
|
|
||||||
# Hack for min area
|
# Hack for min area
|
||||||
if OPTS.tech_name == "sky130":
|
if OPTS.tech_name == "sky130":
|
||||||
min_area = drc["minarea_{}".format(self.pwr_grid_layer)]
|
min_area = drc["minarea_{}".format(self.pwr_grid_layer)]
|
||||||
|
|
@ -1340,7 +1344,7 @@ class layout():
|
||||||
else:
|
else:
|
||||||
width = None
|
width = None
|
||||||
height = None
|
height = None
|
||||||
|
|
||||||
if pin.layer == self.pwr_grid_layer:
|
if pin.layer == self.pwr_grid_layer:
|
||||||
self.add_layout_pin_rect_center(text=new_name,
|
self.add_layout_pin_rect_center(text=new_name,
|
||||||
layer=self.pwr_grid_layer,
|
layer=self.pwr_grid_layer,
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ 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
|
||||||
if(self.debugToTerminal==1):
|
if(self.debugToTerminal==1):
|
||||||
print("Offset: " + str(offset)) #print out the record numbers for de-bugging
|
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
|
||||||
|
|
@ -669,11 +669,11 @@ class Gds2reader:
|
||||||
else:
|
else:
|
||||||
print("There was an error parsing the GDS header. Aborting...")
|
print("There was an error parsing the GDS header. Aborting...")
|
||||||
|
|
||||||
def loadFromFile(self, fileName):
|
def loadFromFile(self, fileName, special_purposes={}):
|
||||||
self.fileHandle = open(fileName,"rb")
|
self.fileHandle = open(fileName,"rb")
|
||||||
self.readGds2()
|
self.readGds2()
|
||||||
self.fileHandle.close()
|
self.fileHandle.close()
|
||||||
self.layoutObject.initialize()
|
self.layoutObject.initialize(special_purposes)
|
||||||
|
|
||||||
##############################################
|
##############################################
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from datetime import *
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import math
|
import math
|
||||||
import debug
|
import debug
|
||||||
from tech import use_purpose
|
|
||||||
|
|
||||||
class VlsiLayout:
|
class VlsiLayout:
|
||||||
"""Class represent a hierarchical layout"""
|
"""Class represent a hierarchical layout"""
|
||||||
|
|
@ -81,6 +81,12 @@ class VlsiLayout:
|
||||||
coordinatesRotate.extend((newX,newY))
|
coordinatesRotate.extend((newX,newY))
|
||||||
return coordinatesRotate
|
return coordinatesRotate
|
||||||
|
|
||||||
|
def prefixAll(self, prefix):
|
||||||
|
for name in self.structures:
|
||||||
|
if name == self.rootStructureName:
|
||||||
|
continue
|
||||||
|
self.structures[prefix + name] = self.structures[name]
|
||||||
|
|
||||||
def rename(self,newName):
|
def rename(self,newName):
|
||||||
# take the root structure and copy it to a new structure with the new name
|
# take the root structure and copy it to a new structure with the new name
|
||||||
self.structures[newName] = self.structures[self.rootStructureName]
|
self.structures[newName] = self.structures[self.rootStructureName]
|
||||||
|
|
@ -211,17 +217,17 @@ class VlsiLayout:
|
||||||
del transformPath[-1]
|
del transformPath[-1]
|
||||||
return
|
return
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self, special_purposes={}):
|
||||||
self.deduceHierarchy()
|
self.deduceHierarchy()
|
||||||
# self.traverseTheHierarchy()
|
# self.traverseTheHierarchy()
|
||||||
self.populateCoordinateMap()
|
self.populateCoordinateMap()
|
||||||
#only ones with text
|
# only ones with text
|
||||||
for layerNumber in self.layerNumbersInUse:
|
for layerNumber in self.layerNumbersInUse:
|
||||||
#if layerNumber not in no_pin_shape:
|
# if layerNumber not in no_pin_shape:
|
||||||
if layerNumber in use_purpose:
|
if layerNumber in special_purposes:
|
||||||
self.processLabelPins((layerNumber, use_purpose[layerNumber]))
|
self.processLabelPins((layerNumber, special_purposes[layerNumber]))
|
||||||
else:
|
else:
|
||||||
self.processLabelPins((layerNumber, None))
|
self.processLabelPins((layerNumber, None))
|
||||||
|
|
||||||
def populateCoordinateMap(self):
|
def populateCoordinateMap(self):
|
||||||
def addToXyTree(startingStructureName = None,transformPath = None):
|
def addToXyTree(startingStructureName = None,transformPath = None):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from gdsMill import gdsMill
|
||||||
|
|
||||||
|
if len(sys.argv) < 4:
|
||||||
|
print("Script to prefix every instance and structure to create a unique namespace.")
|
||||||
|
print("Usage: {0} prefix in.gds out.gds".format(sys.argv[0]))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
prefix = sys.argv[1]
|
||||||
|
|
||||||
|
gds_file = sys.argv[2]
|
||||||
|
arrayCellLayout = gdsMill.VlsiLayout()
|
||||||
|
gds = gdsMill.Gds2reader(arrayCellLayout,debugToTerminal = 1)
|
||||||
|
gds.loadFromFile(gds_file)
|
||||||
|
|
||||||
|
gds.prefixAll(prefix)
|
||||||
|
|
||||||
|
writer = gdsMill.Gds2writer(gds)
|
||||||
|
writer.writeToFile(sys.argv[3])
|
||||||
Loading…
Reference in New Issue