diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index b766b1af..33bcaaa2 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -147,8 +147,12 @@ class instance(geometry): self.width = 0 self.height = 0 else: - self.width = round_to_grid(mod.width) - self.height = round_to_grid(mod.height) + if mirror in ["R90","R270"] or rotate in [90,270]: + self.width = round_to_grid(mod.height) + self.height = round_to_grid(mod.width) + else: + self.width = round_to_grid(mod.width) + self.height = round_to_grid(mod.height) self.compute_boundary(offset,mirror,rotate) debug.info(4, "creating instance: " + self.name) diff --git a/compiler/base/pin_layout.py b/compiler/base/pin_layout.py index 7565c6ce..c5434246 100644 --- a/compiler/base/pin_layout.py +++ b/compiler/base/pin_layout.py @@ -2,6 +2,7 @@ import debug from tech import GDS, drc from vector import vector from tech import layer +import math class pin_layout: """ @@ -18,6 +19,10 @@ class pin_layout: self.rect = [vector(rect[0]),vector(rect[1])] # snap the rect to the grid self.rect = [x.snap_to_grid() for x in self.rect] + + debug.check(self.width()>0,"Zero width pin.") + debug.check(self.height()>0,"Zero height pin.") + # if it's a layer number look up the layer name. this assumes a unique layer number. if type(layer_name_num)==int: self.layer = list(layer.keys())[list(layer.values()).index(layer_name_num)] @@ -113,24 +118,45 @@ class pin_layout: return y_overlaps + def xcontains(self, other): + """ Check if shape contains the x overlap """ + (ll,ur) = self.rect + (oll,our) = other.rect + + return (oll.x >= ll.x and our.x <= ur.x) + + def ycontains(self, other): + """ Check if shape contains the y overlap """ + (ll,ur) = self.rect + (oll,our) = other.rect + + return (oll.y >= ll.y and our.y <= ur.y) + def contains(self, other): """ Check if a shape contains another rectangle """ + # If it is the same shape entirely, it is contained! + if self == other: + return True + # Can only overlap on the same layer if self.layer != other.layer: return False - (ll,ur) = self.rect - (oll,our) = other.rect - - - if not (oll.y >= ll.y and oll.y <= ur.y): + if not self.xcontains(other): return False - if not (oll.x >= ll.x and oll.x <= ur.x): + if not self.ycontains(other): return False return True - + + def contained_by_any(self, shape_list): + """ Checks if shape is contained by any in the list """ + for shape in shape_list: + if shape.contains(self): + return True + return False + def overlaps(self, other): """ Check if a shape overlaps with a rectangle """ @@ -274,3 +300,127 @@ class pin_layout: magnification=GDS["zoom"], rotate=None) + + def compute_overlap(self, other): + """ Calculate the rectangular overlap of two rectangles. """ + (r1_ll,r1_ur) = self.rect + (r2_ll,r2_ur) = other.rect + + #ov_ur = vector(min(r1_ur.x,r2_ur.x),min(r1_ur.y,r2_ur.y)) + #ov_ll = vector(max(r1_ll.x,r2_ll.x),max(r1_ll.y,r2_ll.y)) + + dy = min(r1_ur.y,r2_ur.y)-max(r1_ll.y,r2_ll.y) + dx = min(r1_ur.x,r2_ur.x)-max(r1_ll.x,r2_ll.x) + + if dx>=0 and dy>=0: + return [dx,dy] + else: + return [0,0] + + def overlap_length(self, other): + """ + Calculate the intersection segment and determine its length + """ + + if self.contains(other): + return math.inf + elif other.contains(self): + return math.inf + else: + intersections = self.compute_overlap_segment(other) + # This is the common case where two pairs of edges overlap + # at two points, so just find the distance between those two points + if len(intersections)==2: + (p1,p2) = intersections + return math.sqrt(pow(p1[0]-p2[0],2) + pow(p1[1]-p2[1],2)) + else: + # This is where we had a corner intersection or none + return 0 + + + def compute_overlap_segment(self, other): + """ + Calculate the intersection segment of two rectangles + (if any) + """ + (r1_ll,r1_ur) = self.rect + (r2_ll,r2_ur) = other.rect + + # The other corners besides ll and ur + r1_ul = vector(r1_ll.x, r1_ur.y) + r1_lr = vector(r1_ur.x, r1_ll.y) + r2_ul = vector(r2_ll.x, r2_ur.y) + r2_lr = vector(r2_ur.x, r2_ll.y) + + from itertools import tee + def pairwise(iterable): + "s -> (s0,s1), (s1,s2), (s2, s3), ..." + a, b = tee(iterable) + next(b, None) + return zip(a, b) + + # R1 edges CW + r1_cw_points = [r1_ll, r1_ul, r1_ur, r1_lr, r1_ll] + r1_edges = [] + for (p,q) in pairwise(r1_cw_points): + r1_edges.append([p,q]) + + # R2 edges CW + r2_cw_points = [r2_ll, r2_ul, r2_ur, r2_lr, r2_ll] + r2_edges = [] + for (p,q) in pairwise(r2_cw_points): + r2_edges.append([p,q]) + + # There are 4 edges on each rectangle + # so just brute force check intersection of each + # Two pairs of them should intersect + intersections = [] + for r1e in r1_edges: + for r2e in r2_edges: + i = self.segment_intersection(r1e, r2e) + if i: + intersections.append(i) + + return intersections + + def on_segment(self, p, q, r): + """ + Given three co-linear points, determine if q lies on segment pr + """ + if q[0] <= max(p[0], r[0]) and \ + q[0] >= min(p[0], r[0]) and \ + q[1] <= max(p[1], r[1]) and \ + q[1] >= min(p[1], r[1]): + return True + + return False + + def segment_intersection(self, s1, s2): + """ + Determine the intersection point of two segments + Return the a segment if they overlap. + Return None if they don't. + """ + (a,b) = s1 + (c,d) = s2 + # Line AB represented as a1x + b1y = c1 + a1 = b.y - a.y + b1 = a.x - b.x + c1 = a1*a.x + b1*a.y + + # Line CD represented as a2x + b2y = c2 + a2 = d.y - c.y + b2 = c.x - d.x + c2 = a2*c.x + b2*c.y + + determinant = a1*b2 - a2*b1 + + if determinant!=0: + x = (b2*c1 - b1*c2)/determinant + y = (a1*c2 - a2*c1)/determinant + + r = [x,y] + if self.on_segment(a, r, b) and self.on_segment(c, r, d): + return [x, y] + + return None diff --git a/compiler/base/route.py b/compiler/base/route.py index 0397e383..09925e07 100644 --- a/compiler/base/route.py +++ b/compiler/base/route.py @@ -62,14 +62,10 @@ class route(design): plist = list(pairwise(self.path)) for p0,p1 in plist: if p0.z != p1.z: # via - # offset if not rotated - #via_offset = vector(p0.x+0.5*self.c.width,p0.y+0.5*self.c.height) - # offset if rotated - via_offset = vector(p0.x+0.5*self.c.height,p0.y-0.5*self.c.width) via_size = [self.num_vias]*2 - self.obj.add_via(self.layer_stack,via_offset,size=via_size,rotate=90) + self.obj.add_via_center(self.layer_stack,vector(p0.x,p0.y),size=via_size,rotate=90) elif p0.x != p1.x and p0.y != p1.y: # diagonal! - debug.error("Non-changing direction!") + debug.error("Diagonal route! {}".format(self.path),-3) else: # this will draw an extra corner at the end but that is ok self.draw_corner_wire(p1) diff --git a/compiler/base/utils.py b/compiler/base/utils.py index 28c5f997..f9597f39 100644 --- a/compiler/base/utils.py +++ b/compiler/base/utils.py @@ -66,7 +66,7 @@ def get_gds_size(name, gds_filename, units, layer): Open a GDS file and return the size from either the bounding box or a border layer. """ - debug.info(2,"Creating VLSI layout for {}".format(name)) + debug.info(4,"Creating VLSI layout for {}".format(name)) cell_vlsi = gdsMill.VlsiLayout(units=units) reader = gdsMill.Gds2reader(cell_vlsi) reader.loadFromFile(gds_filename) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index d6579ab5..a777437d 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -20,6 +20,10 @@ class functional(simulation): def __init__(self, sram, spfile, corner): simulation.__init__(self, sram, spfile, corner) + + # Seed the characterizer with a constant seed for unit tests + if OPTS.is_unit_test: + random.seed(12345) self.set_corner(corner) self.set_spice_constants() diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 3d156d2d..d4fb210e 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -3,7 +3,6 @@ from design import design import debug import math import tech -import random from .stimuli import * from .trim_spice import * from .charutils import * diff --git a/compiler/router/direction.py b/compiler/router/direction.py index 95980618..8a6681a7 100644 --- a/compiler/router/direction.py +++ b/compiler/router/direction.py @@ -1,4 +1,5 @@ from enum import Enum +from vector3d import vector3d class direction(Enum): NORTH = 1 @@ -7,3 +8,60 @@ class direction(Enum): WEST = 4 UP = 5 DOWN = 6 + NORTHEAST = 7 + NORTHWEST = 8 + SOUTHEAST = 9 + SOUTHWEST = 10 + + + def get_offset(direct): + """ + Returns the vector offset for a given direction. + """ + if direct==direction.NORTH: + offset = vector3d(0,1,0) + elif direct==direction.SOUTH: + offset = vector3d(0,-1,0) + elif direct==direction.EAST: + offset = vector3d(1,0,0) + elif direct==direction.WEST: + offset = vector3d(-1,0,0) + elif direct==direction.UP: + offset = vector3d(0,0,1) + elif direct==direction.DOWN: + offset = vector3d(0,0,-1) + elif direct==direction.NORTHEAST: + offset = vector3d(1,1,0) + elif direct==direction.NORTHWEST: + offset = vector3d(-1,1,0) + elif direct==direction.SOUTHEAST: + offset = vector3d(1,-1,0) + elif direct==direction.SOUTHWEST: + offset = vector3d(-1,-1,0) + else: + debug.error("Invalid direction {}".format(direct)) + + return offset + + def cardinal_directions(up_down_too=False): + temp_dirs = [direction.NORTH, direction.EAST, direction.SOUTH, direction.WEST] + if up_down_too: + temp_dirs.extend([direction.UP, direction.DOWN]) + return temp_dirs + + def cardinal_offsets(up_down_too=False): + return [direction.get_offset(d) for d in direction.cardinal_directions(up_down_too)] + + def all_directions(): + return [direction.NORTH, direction.EAST, direction.SOUTH, direction.WEST, + direction.NORTHEAST, direction.NORTHWEST, direction.SOUTHEAST, direction.SOUTHWEST] + + def all_offsets(): + return [direction.get_offset(d) for d in direction.all_directions()] + + def all_neighbors(cell): + return [cell+x for x in direction.all_offsets()] + + def cardinal_neighbors(cell): + return [cell+x for x in direction.cardinal_offsets()] + diff --git a/compiler/router/grid_cell.py b/compiler/router/grid_cell.py index 3f145ef4..cb78116c 100644 --- a/compiler/router/grid_cell.py +++ b/compiler/router/grid_cell.py @@ -22,6 +22,11 @@ class grid_cell: self.source=False self.target=False + def get_cost(self): + # We can display the cost of the frontier + if self.min_cost > 0: + return self.min_cost + def get_type(self): if self.blocked: @@ -36,8 +41,4 @@ class grid_cell: if self.path: return "P" - # We can display the cost of the frontier - if self.min_cost > 0: - return self.min_cost - return None diff --git a/compiler/router/grid_path.py b/compiler/router/grid_path.py index 437b6acb..cbe739ef 100644 --- a/compiler/router/grid_path.py +++ b/compiler/router/grid_path.py @@ -150,7 +150,7 @@ class grid_path: return cost - def expand_dirs(self,up_down_too=True): + def expand_dirs(self): """ Expand from the end in each of the four cardinal directions plus up or down but not expanding to blocked cells. Expands in all @@ -162,9 +162,7 @@ class grid_path: """ neighbors = [] - for d in list(direction): - if not up_down_too and (d==direction.UP or d==direction.DOWN): - continue + for d in direction.cardinal_directions(True): n = self.neighbor(d) if n: neighbors.append(n) @@ -172,20 +170,7 @@ class grid_path: return neighbors def neighbor(self, d): - if d==direction.EAST: - offset = vector3d(1,0,0) - elif d==direction.WEST: - offset = vector3d(-1,0,0) - elif d==direction.NORTH: - offset = vector3d(0,1,0) - elif d==direction.SOUTH: - offset = vector3d(0,-1,0) - elif d==direction.UP: - offset = vector3d(0,0,1) - elif d==direction.DOWN: - offset = vector3d(0,0,-1) - else: - debug.error("Invalid direction {}".format(d),-1) + offset = direction.get_offset(d) newwave = [point + offset for point in self.pathlist[-1]] diff --git a/compiler/router/grid_utils.py b/compiler/router/grid_utils.py index 62caebe9..23fe23ea 100644 --- a/compiler/router/grid_utils.py +++ b/compiler/router/grid_utils.py @@ -6,31 +6,20 @@ import debug from direction import direction from vector3d import vector3d -def increment_set(curset, direct): - """ - Return the cells incremented in given direction - """ - if direct==direction.NORTH: - offset = vector3d(0,1,0) - elif direct==direction.SOUTH: - offset = vector3d(0,-1,0) - elif direct==direction.EAST: - offset = vector3d(1,0,0) - elif direct==direction.WEST: - offset = vector3d(-1,0,0) - elif direct==direction.UP: - offset = vector3d(0,0,1) - elif direct==direction.DOWN: - offset = vector3d(0,0,-1) - else: - debug.error("Invalid direction {}".format(dirct)) - - newset = set() - for c in curset: - newc = c+offset - newset.add(newc) - return newset +def increment_set(curset, direct): + """ + Return the cells incremented in given direction + """ + offset = direction.get_offset(direct) + + newset = set() + for c in curset: + newc = c+offset + newset.add(newc) + + return newset + def remove_border(curset, direct): """ @@ -38,7 +27,7 @@ def remove_border(curset, direct): """ border = get_border(curset, direct) curset.difference_update(border) - + def get_upper_right(curset): ur = None @@ -55,48 +44,48 @@ def get_lower_left(curset): return ll def get_border( curset, direct): - """ - Return the furthest cell(s) in a given direction. - """ - - # find direction-most cell(s) - maxc = [] - if direct==direction.NORTH: - for c in curset: - if len(maxc)==0 or c.y>maxc[0].y: - maxc = [c] - elif c.y==maxc[0].y: - maxc.append(c) - elif direct==direct.SOUTH: - for c in curset: - if len(maxc)==0 or c.ymaxc[0].x: - maxc = [c] - elif c.x==maxc[0].x: - maxc.append(c) - elif direct==direct.WEST: - for c in curset: - if len(maxc)==0 or c.xmaxc[0].y: + maxc = [c] + elif c.y==maxc[0].y: + maxc.append(c) + elif direct==direct.SOUTH: + for c in curset: + if len(maxc)==0 or c.ymaxc[0].x: + maxc = [c] + elif c.x==maxc[0].x: + maxc.append(c) + elif direct==direct.WEST: + for c in curset: + if len(maxc)==0 or c.x=pin.uy(): + above_item = item + else: + break + + # There was nothing + if above_item==None: + return None + # If it already overlaps, no connector needed + if above_item.overlaps(pin): + return None + + # Otherwise, make a connector to the item + p = self.compute_connector(pin, above_item) + return p + + def find_below_connector(self, pin, enclosures): + """ + Find the enclosure that is below the pin + and make a connector to it's upper edge. + """ + # Create the list of shapes that contain the pin edge + edge_list = [] + for shape in enclosures: + if shape.xcontains(pin): + edge_list.append(shape) + + # Sort them by their upper edge + edge_list.sort(key=lambda x: x.uy()) + + # Find the upper edge that is next to the pin's bottom edge + bottom_item = None + for item in edge_list: + if item.uy()<=pin.by(): + bottom_item = item + else: + break + + # There was nothing to the left + if bottom_item==None: + return None + # If it already overlaps, no connector needed + if bottom_item.overlaps(pin): + return None + + # Otherwise, make a connector to the item + p = self.compute_connector(pin, bottom_item) + return p + + def find_left_connector(self, pin, enclosures): + """ + Find the enclosure that is to the left of the pin + and make a connector to it's right edge. + """ + # Create the list of shapes that contain the pin edge + edge_list = [] + for shape in enclosures: + if shape.ycontains(pin): + edge_list.append(shape) + + # Sort them by their right edge + edge_list.sort(key=lambda x: x.rx()) + + # Find the right edge that is to the pin's left edge + left_item = None + for item in edge_list: + if item.rx()<=pin.lx(): + left_item = item + else: + break + + # There was nothing to the left + if left_item==None: + return None + # If it already overlaps, no connector needed + if left_item.overlaps(pin): + return None + + # Otherwise, make a connector to the item + p = self.compute_connector(pin, left_item) + return p + + def find_right_connector(self, pin, enclosures): + """ + Find the enclosure that is to the right of the pin + and make a connector to it's left edge. + """ + # Create the list of shapes that contain the pin edge + edge_list = [] + for shape in enclosures: + if shape.ycontains(pin): + edge_list.append(shape) + + # Sort them by their right edge + edge_list.sort(key=lambda x: x.lx(), reverse=True) + + # Find the left edge that is next to the pin's right edge + right_item = None + for item in edge_list: + if item.lx()>=pin.rx(): + right_item = item + else: + break + + # There was nothing to the right + if right_item==None: + return None + # If it already overlaps, no connector needed + if right_item.overlaps(pin): + return None + + # Otherwise, make a connector to the item + p = self.compute_connector(pin, right_item) + return p + + def find_smallest_connector(self, pin_list, shape_list): + """ + Compute all of the connectors between the overlapping pins and enclosure shape list.. + Return the smallest. + """ + smallest = None + for pin in pin_list: + for enclosure in shape_list: + new_enclosure = self.compute_connector(pin, enclosure) + if smallest == None or new_enclosure.area() min_width: + if smallest_shape == None or other.area() biggest.area(): + biggest = pin + + return pin + + def enclose_pin_grids(self, ll, dir1=direction.NORTH, dir2=direction.EAST): + """ + This encloses a single pin component with a rectangle + starting with the seed and expanding right until blocked + and then up until blocked. + dir1 and dir2 should be two orthogonal directions. + """ + + offset1= direction.get_offset(dir1) + offset2= direction.get_offset(dir2) + + # We may have started with an empty set + if not self.grids: + return None + + # Start with the ll and make the widest row + row = [ll] + # Move in dir1 while we can + while True: + next_cell = row[-1] + offset1 + # Can't move if not in the pin shape + if next_cell in self.grids and next_cell not in self.router.blocked_grids: + row.append(next_cell) + else: + break + # Move in dir2 while we can + while True: + next_row = [x+offset2 for x in row] + for cell in next_row: + # Can't move if any cell is not in the pin shape + if cell not in self.grids or cell in self.router.blocked_grids: + break + else: + row = next_row + # Skips the second break + continue + # Breaks from the nested break + break + + # Add a shape from ll to ur + ur = row[-1] + return (ll,ur) + + + def enclose_pin(self): + """ + If there is one set of connected pin shapes, + this will find the smallest rectangle enclosure that overlaps with any pin. + If there is not, it simply returns all the enclosures. + """ + self.enclosed = True + + # Compute the enclosure pin_layout list of the set of tracks + self.enclosures = self.compute_enclosures() + + for pin_list in self.pins: + for pin in pin_list: + + # If it is contained, it won't need a connector + if pin.contained_by_any(self.enclosures): + continue + + left_connector = self.find_left_connector(pin, self.enclosures) + right_connector = self.find_right_connector(pin, self.enclosures) + above_connector = self.find_above_connector(pin, self.enclosures) + below_connector = self.find_below_connector(pin, self.enclosures) + for connector in [left_connector, right_connector, above_connector, below_connector]: + if connector: + self.enclosures.append(connector) + + # Now, make sure each pin touches an enclosure. If not, add a connector. + # This could only happen when there was no enclosure in any cardinal direction from a pin + for pin_list in self.pins: + if not self.overlap_any_shape(pin_list, self.enclosures): + connector = self.find_smallest_connector(pin_list, self.enclosures) + debug.check(connector!=None, "Could not find a connector for {} with {}".format(pin_list, self.enclosures)) + self.enclosures.append(connector) + + + debug.info(3,"Computed enclosure(s) {0}\n {1}\n {2}\n {3}".format(self.name, + self.pins, + self.grids, + self.enclosures)) + + def combine_groups(self, pg1, pg2): + """ + Combine two pin groups into one. + """ + self.pins = [*pg1.pins, *pg2.pins] # Join the two lists of pins + self.grids = pg1.grids | pg2.grids # OR the set of grid locations + self.secondary_grids = pg1.secondary_grids | pg2.secondary_grids + + def add_enclosure(self, cell): + """ + Add the enclosure shape to the given cell. + """ + for enclosure in self.enclosures: + debug.info(2,"Adding enclosure {0} {1}".format(self.name, enclosure)) + cell.add_rect(layer=enclosure.layer, + offset=enclosure.ll(), + width=enclosure.width(), + height=enclosure.height()) + + + def perimeter_grids(self): + """ + Return a list of the grids on the perimeter. + This assumes that we have a single contiguous shape. + """ + perimeter_set = set() + cardinal_offsets = direction.cardinal_offsets() + for g1 in self.grids: + neighbor_grids = [g1 + offset for offset in cardinal_offsets] + neighbor_count = sum([x in self.grids for x in neighbor_grids]) + # If we aren't completely enclosed, we are on the perimeter + if neighbor_count < 4: + perimeter_set.add(g1) + + return perimeter_set + + def adjacent(self, other): + """ + Chck if the two pin groups have at least one adjacent pin grid. + """ + # We could optimize this to just check the boundaries + for g1 in self.perimeter_grids(): + for g2 in other.perimeter_grids(): + if g1.adjacent(g2): + return True + + return False + + + def adjacent_grids(self, other, separation): + """ + Determine the sets of grids that are within a separation distance + of any grid in the other set. + """ + # We could optimize this to just check the boundaries + g1_grids = set() + g2_grids = set() + for g1 in self.grids: + for g2 in other.grids: + if g1.distance(g2) <= separation: + g1_grids.add(g1) + g2_grids.add(g2) + + return g1_grids,g2_grids + + def convert_pin(self): + """ + Convert the list of pin shapes into sets of routing grids. + The secondary set of grids are "optional" pin shapes that could be + should be either blocked or part of the pin. + """ + pin_set = set() + blockage_set = set() + + for pin_list in self.pins: + for pin in pin_list: + debug.info(2," Converting {0}".format(pin)) + # Determine which tracks the pin overlaps + pin_in_tracks=self.router.convert_pin_to_tracks(self.name, pin) + + pin_set.update(pin_in_tracks) + # Blockages will be a super-set of pins since it uses the inflated pin shape. + blockage_in_tracks = self.router.convert_blockage(pin) + + blockage_set.update(blockage_in_tracks) + + # If we have a blockage, we must remove the grids + # Remember, this excludes the pin blockages already + shared_set = pin_set & self.router.blocked_grids + if len(shared_set)>0: + debug.info(2,"Removing pins {}".format(shared_set)) + pin_set.difference_update(self.router.blocked_grids) + + shared_set = blockage_set & self.router.blocked_grids + if len(shared_set)>0: + debug.info(2,"Removing blocks {}".format(shared_set)) + blockage_set.difference_update(self.router.blocked_grids) + + # At least one of the groups must have some valid tracks + if (len(pin_set)==0 and len(blockage_set)==0): + self.write_debug_gds("blocked_pin.gds") + debug.error("Unable to find unblocked pin on grid.") + + # We need to route each of the components, so don't combine the groups + self.grids = pin_set | blockage_set + # Remember the secondary grids for removing adjacent pins in wide metal spacing + self.secondary_grids = blockage_set - pin_set + + debug.info(2," pins {}".format(self.grids)) + debug.info(2," secondary {}".format(self.secondary_grids)) + + def recurse_simple_overlap_enclosure(self, start_set, direct): + """ + Recursive function to return set of tracks that connects to + the actual supply rail wire in a given direction (or terminating + when any track is no longer in the supply rail. + """ + next_set = grid_utils.expand_border(start_set, direct) + + supply_tracks = self.router.supply_rail_tracks[self.name] + supply_wire_tracks = self.router.supply_rail_wire_tracks[self.name] + + supply_overlap = next_set & supply_tracks + wire_overlap = next_set & supply_wire_tracks + + # If the rail overlap is the same, we are done, since we connected to the actual wire + if len(wire_overlap)==len(start_set): + new_set = start_set | wire_overlap + # If the supply overlap is the same, keep expanding unti we hit the wire or move out of the rail region + elif len(supply_overlap)==len(start_set): + recurse_set = self.recurse_simple_overlap_enclosure(supply_overlap, direct) + new_set = start_set | supply_overlap | recurse_set + else: + # If we got no next set, we are done, can't expand! + new_set = set() + + return new_set + + def create_simple_overlap_enclosure(self, start_set): + """ + This takes a set of tracks that overlap a supply rail and creates an enclosure + that is ensured to overlap the supply rail wire. + It then adds rectangle(s) for the enclosure. + """ + + additional_set = set() + # Check the layer of any element in the pin to determine which direction to route it + e = next(iter(start_set)) + new_set = start_set.copy() + if e.z==0: + new_set = self.recurse_simple_overlap_enclosure(start_set, direction.NORTH) + if not new_set: + new_set = self.recurse_simple_overlap_enclosure(start_set, direction.SOUTH) + else: + new_set = self.recurse_simple_overlap_enclosure(start_set, direction.EAST) + if not new_set: + new_set = self.recurse_simple_overlap_enclosure(start_set, direction.WEST) + + # Expand the pin grid set to include some extra grids that connect the supply rail + self.grids.update(new_set) + + # Add the inflated set so we don't get wide metal spacing issues (if it exists) + self.blockages.update(grid_utils.inflate_set(new_set,self.router.supply_rail_space_width)) + + # Add the polygon enclosures and set this pin group as routed + self.set_routed() + self.enclosures = self.compute_enclosures() + diff --git a/compiler/router/router.py b/compiler/router/router.py index 2cb9fb71..b9aa2518 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -1,17 +1,18 @@ import sys import gdsMill -from tech import drc,GDS,layer -from contact import contact +from tech import drc,GDS import math import debug +from router_tech import router_tech from pin_layout import pin_layout +from pin_group import pin_group from vector import vector from vector3d import vector3d from globals import OPTS from pprint import pformat import grid_utils -class router: +class router(router_tech): """ A router class to read an obstruction map from a gds and plan a route on a given layer. This is limited to two layer routes. @@ -23,6 +24,8 @@ class router: This will instantiate a copy of the gds file or the module at (0,0) and route on top of this. The blockages from the gds/module will be considered. """ + router_tech.__init__(self, layers) + self.cell = design # If didn't specify a gds blockage file, write it out to read the gds @@ -37,22 +40,15 @@ class router: self.reader.loadFromFile(gds_filename) self.top_name = self.layout.rootStructureName - # Set up layers and track sizes - self.set_layers(layers) - ### The pin data structures - # A map of pin names to pin structures + # A map of pin names to a set of pin_layout structures self.pins = {} - # This is a set of all pins so that we don't create blockages for these shapes. + # This is a set of all pins (ignoring names) so that can quickly not create blockages for pins + # (They will be blocked based on the names we are routing) self.all_pins = set() - # This is a set of pin groups. Each group consists of overlapping pin shapes on the same layer. + # A map of pin names to a list of pin groups self.pin_groups = {} - # These are the corresponding pin grids for each pin group. - self.pin_grids = {} - # The corresponding set of partially blocked grids for each pin group. - # These are blockages for other nets but unblocked for this component. - self.pin_blockages = {} ### The blockage data structures # A list of metal shapes (using the same pin_layout structure) that are not pins but blockages. @@ -63,6 +59,8 @@ class router: ### The routed data structures # A list of paths that have been "routed" self.paths = [] + # A list of path blockages (they might be expanded for wide metal DRC) + self.path_blockages = [] # The boundary will determine the limits to the size of the routing grid self.boundary = self.layout.measureBoundary(self.top_name) @@ -78,8 +76,6 @@ class router: self.pins = {} self.all_pins = set() self.pin_groups = {} - self.pin_grids = {} - self.pin_blockages = {} # DO NOT clear the blockages as these don't change self.rg.reinit() @@ -88,19 +84,6 @@ class router: """ If we want to route something besides the top-level cell.""" self.top_name = top_name - def get_zindex(self,layer_num): - if layer_num==self.horiz_layer_number: - return 0 - else: - return 1 - - def get_layer(self, zindex): - if zindex==1: - return self.vert_layer_name - elif zindex==0: - return self.horiz_layer_name - else: - debug.error("Invalid zindex {}".format(zindex),-1) def is_wave(self,path): """ @@ -108,40 +91,6 @@ class router: """ return len(path[0])>1 - def set_layers(self, layers): - """ - Allows us to change the layers that we are routing on. First layer - is always horizontal, middle is via, and last is always - vertical. - """ - self.layers = layers - (self.horiz_layer_name, self.via_layer_name, self.vert_layer_name) = self.layers - - # This is the minimum routed track spacing - via_connect = contact(self.layers, (1, 1)) - self.max_via_size = max(via_connect.width,via_connect.height) - - self.vert_layer_minwidth = drc("minwidth_{0}".format(self.vert_layer_name)) - self.vert_layer_spacing = drc(str(self.vert_layer_name)+"_to_"+str(self.vert_layer_name)) - self.vert_layer_number = layer[self.vert_layer_name] - - self.horiz_layer_minwidth = drc("minwidth_{0}".format(self.horiz_layer_name)) - self.horiz_layer_spacing = drc(str(self.horiz_layer_name)+"_to_"+str(self.horiz_layer_name)) - self.horiz_layer_number = layer[self.horiz_layer_name] - - self.horiz_track_width = self.max_via_size + self.horiz_layer_spacing - self.vert_track_width = self.max_via_size + self.vert_layer_spacing - - # We'll keep horizontal and vertical tracks the same for simplicity. - self.track_width = max(self.horiz_track_width,self.vert_track_width) - debug.info(1,"Track width: "+str(self.track_width)) - - self.track_widths = [self.track_width] * 2 - self.track_factor = [1/self.track_width] * 2 - debug.info(1,"Track factor: {0}".format(self.track_factor)) - - # When we actually create the routes, make them the width of the track (minus 1/2 spacing on each side) - self.layer_widths = [self.track_width - self.horiz_layer_spacing, 1, self.track_width - self.vert_layer_spacing] def retrieve_pins(self,pin_name): """ @@ -151,11 +100,16 @@ class router: pin_set = set() for shape in shape_list: (name,layer,boundary)=shape - rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])] + # GDSMill boundaries are in (left, bottom, right, top) order + # so repack and snap to the grid + ll = vector(boundary[0],boundary[1]).snap_to_grid() + ur = vector(boundary[2],boundary[3]).snap_to_grid() + rect = [ll,ur] pin = pin_layout(pin_name, rect, layer) pin_set.add(pin) debug.check(len(pin_set)>0,"Did not find any pin shapes for {0}.".format(str(pin_name))) + self.pins[pin_name] = pin_set self.all_pins.update(pin_set) @@ -183,24 +137,13 @@ class router: self.retrieve_blockages(layer) - # # def reinit(self): - # # """ - # # Reset the source and destination pins to start a new routing. - # # Convert the source/dest pins to blockages. - # # Convert the routed path to blockages. - # # Keep the other blockages unchanged. - # # """ - # # self.clear_pins() - # # # DO NOT clear the blockages as these don't change - # # self.rg.reinit() - - def find_pins_and_blockages(self, pin_list): """ Find the pins and blockages in the design """ # This finds the pin shapes and sorts them into "groups" that are connected - # This must come before the blockages, so we can ignore metal shapes that are blockages. + # This must come before the blockages, so we can not count the pins themselves + # as blockages. for pin in pin_list: self.find_pins(pin) @@ -216,9 +159,158 @@ class router: for pin in pin_list: self.convert_pins(pin) + for pin in pin_list: + self.combine_adjacent_pins(pin) + #self.write_debug_gds("debug_combine_pins.gds",stop_program=True) + + # Separate any adjacent grids of differing net names to prevent wide metal DRC violations + # Must be done before enclosing pins + self.separate_adjacent_pins(self.supply_rail_space_width) + # For debug + #self.separate_adjacent_pins(1) + # Enclose the continguous grid units in a metal rectangle to fix some DRCs self.enclose_pins() + #self.write_debug_gds("debug_enclose_pins.gds",stop_program=True) + + def combine_adjacent_pins_pass(self, pin_name): + """ + Find pins that have adjacent routing tracks and merge them into a + single pin_group. The pins themselves may not be touching, but + enclose_pis in the next step will ensure they are touching. + """ + + # Make a copy since we are going to add to (and then reduce) this list + pin_groups = self.pin_groups[pin_name].copy() + + # Start as None to signal the first iteration + remove_indices = set() + + for index1,pg1 in enumerate(self.pin_groups[pin_name]): + # Cannot combine more than once + if index1 in remove_indices: + continue + for index2,pg2 in enumerate(self.pin_groups[pin_name]): + # Cannot combine with yourself + if index1==index2: + continue + # Cannot combine more than once + if index2 in remove_indices: + continue + + # Combine if at least 1 grid cell is adjacent + if pg1.adjacent(pg2): + combined = pin_group(pin_name, [], self) + combined.combine_groups(pg1, pg2) + debug.info(2,"Combining {0} {1} {2}:".format(pin_name, index1, index2)) + debug.info(2, " {0}\n {1}".format(pg1.pins, pg2.pins)) + debug.info(2," --> {0}\n {1}".format(combined.pins,combined.grids)) + remove_indices.update([index1,index2]) + pin_groups.append(combined) + break + + # Remove them in decreasing order to not invalidate the indices + debug.info(2,"Removing {}".format(sorted(remove_indices))) + for i in sorted(remove_indices, reverse=True): + del pin_groups[i] + + # Use the new pin group! + self.pin_groups[pin_name] = pin_groups + + removed_pairs = int(len(remove_indices)/2) + debug.info(1, "Combined {0} pin pairs for {1}".format(removed_pairs,pin_name)) + + return removed_pairs + + def combine_adjacent_pins(self, pin_name): + """ + Make multiple passes of the combine adjacent pins until we have no + more combinations or hit an iteration limit. + """ + + # Start as None to signal the first iteration + num_removed_pairs = None + + # Just used in case there's a circular combination or something weird + for iteration_count in range(10): + num_removed_pairs = self.combine_adjacent_pins_pass(pin_name) + if num_removed_pairs==0: + break + else: + debug.warning("Did not converge combining adjacent pins in supply router.") + + def separate_adjacent_pins(self, separation): + """ + This will try to separate all grid pins by the supplied number of separation + tracks (default is to prevent adjacency). + """ + # Commented out to debug with SCMOS + #if separation==0: + # return + + pin_names = self.pin_groups.keys() + for pin_name1 in pin_names: + for pin_name2 in pin_names: + if pin_name1==pin_name2: + continue + self.separate_adjacent_pin(pin_name1, pin_name2, separation) + + def separate_adjacent_pin(self, pin_name1, pin_name2, separation): + """ + Go through all of the pin groups and check if any other pin group is + within a separation of it. + If so, reduce the pin group grid to not include the adjacent grid. + Try to do this intelligently to keep th pins enclosed. + """ + debug.info(1,"Comparing {0} and {1} adjacency".format(pin_name1, pin_name2)) + for index1,pg1 in enumerate(self.pin_groups[pin_name1]): + for index2,pg2 in enumerate(self.pin_groups[pin_name2]): + # FIXME: Use separation distance and edge grids only + grids_g1, grids_g2 = pg1.adjacent_grids(pg2, separation) + # These should have the same length, so... + if len(grids_g1)>0: + debug.info(1,"Adjacent grids {0} {1} {2} {3}".format(index1,grids_g1,index2,grids_g2)) + self.remove_adjacent_grid(pg1, grids_g1, pg2, grids_g2) + + def remove_adjacent_grid(self, pg1, grids1, pg2, grids2): + """ + Remove one of the adjacent grids in a heuristic manner. + """ + # Determine the bigger and smaller group + if pg1.size()>pg2.size(): + bigger = pg1 + bigger_grids = grids1 + smaller = pg2 + smaller_grids = grids2 + else: + bigger = pg2 + bigger_grids = grids2 + smaller = pg1 + smaller_grids = grids1 + + # First, see if we can remove grids that are in the secondary grids + # i.e. they aren't necessary to the pin grids + if bigger_grids.issubset(bigger.secondary_grids): + debug.info(1,"Removing {} from bigger {}".format(str(bigger_grids), bigger)) + bigger.grids.difference_update(bigger_grids) + self.blocked_grids.update(bigger_grids) + return + elif smaller_grids.issubset(smaller.secondary_grids): + debug.info(1,"Removing {} from smaller {}".format(str(smaller_grids), smaller)) + smaller.grids.difference_update(smaller_grids) + self.blocked_grids.update(smaller_grids) + return + + # If that fails, just randomly remove from the bigger one and give a warning. + # This might fail later. + debug.warning("Removing arbitrary grids from a pin group {} {}".format(bigger, bigger_grids)) + debug.check(len(bigger.grids)>len(bigger_grids),"Zero size pin group after adjacency removal {} {}".format(bigger, bigger_grids)) + bigger.grids.difference_update(bigger_grids) + self.blocked_grids.update(bigger_grids) + + + def prepare_blockages(self, pin_name): """ Reset and add all of the blockages in the design. @@ -236,28 +328,34 @@ class router: self.set_supply_rail_blocked(True) # Block all of the pin components (some will be unblocked if they're a source/target) - for name in self.pin_grids.keys(): - self.set_blockages(self.pin_grids[name],True) + # Also block the previous routes + for name in self.pin_groups.keys(): + blockage_grids = {y for x in self.pin_groups[name] for y in x.grids} + self.set_blockages(blockage_grids,True) + blockage_grids = {y for x in self.pin_groups[name] for y in x.blockages} + self.set_blockages(blockage_grids,True) + # FIXME: These duplicate a bit of work + # These are the paths that have already been routed. + self.set_blockages(self.path_blockages) # Don't mark the other components as targets since we want to route # directly to a rail, but unblock all the source components so we can # route over them - self.set_blockages(self.pin_grids[pin_name],False) + blockage_grids = {y for x in self.pin_groups[pin_name] for y in x.grids} + self.set_blockages(blockage_grids,False) - # These are the paths that have already been routed. - self.set_path_blockages() - def translate_coordinates(self, coord, mirr, angle, xyShift): - """ - Calculate coordinates after flip, rotate, and shift - """ - coordinate = [] - for item in coord: - x = (item[0]*math.cos(angle)-item[1]*mirr*math.sin(angle)+xyShift[0]) - y = (item[0]*math.sin(angle)+item[1]*mirr*math.cos(angle)+xyShift[1]) - coordinate += [(x, y)] - return coordinate + # def translate_coordinates(self, coord, mirr, angle, xyShift): + # """ + # Calculate coordinates after flip, rotate, and shift + # """ + # coordinate = [] + # for item in coord: + # x = (item[0]*math.cos(angle)-item[1]*mirr*math.sin(angle)+xyShift[0]) + # y = (item[0]*math.sin(angle)+item[1]*mirr*math.cos(angle)+xyShift[1]) + # coordinate += [(x, y)] + # return coordinate def convert_shape_to_units(self, shape): """ @@ -295,16 +393,6 @@ class router: # z direction return 2 - - def add_path_blockages(self): - """ - Go through all of the past paths and add them as blockages. - This is so we don't have to write/reload the GDS. - """ - for path in self.paths: - for grid in path: - self.rg.set_blocked(grid) - def clear_blockages(self): """ Clear all blockages on the grid. @@ -316,15 +404,8 @@ class router: """ Flag the blockages in the grid """ self.rg.set_blocked(blockages, value) - def set_path_blockages(self,value=True): - """ Flag the paths as blockages """ - # These are the paths that have already been routed. - # This adds the initial blockges of the design - for p in self.paths: - p.set_blocked(value) - def get_blockage_tracks(self, ll, ur, z): - debug.info(4,"Converting blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z)) + debug.info(3,"Converting blockage ll={0} ur={1} z={2}".format(str(ll),str(ur),z)) block_list = [] for x in range(int(ll[0]),int(ur[0])+1): @@ -458,9 +539,9 @@ class router: best_coord = None best_overlap = -math.inf for coord in insufficient_list: - full_rect = self.convert_track_to_pin(coord) + full_pin = self.convert_track_to_pin(coord) # Compute the overlap with that rectangle - overlap_rect=self.compute_overlap(pin.rect,full_rect) + overlap_rect=pin.compute_overlap(full_pin) # Determine the min x or y overlap min_overlap = min(overlap_rect) if min_overlap>best_overlap: @@ -470,23 +551,6 @@ class router: return set([best_coord]) - def get_layer_width_space(self, zindex, width=0, length=0): - """ - Return the width and spacing of a given layer - and wire of a given width and length. - """ - if zindex==1: - layer_name = self.vert_layer_name - elif zindex==0: - layer_name = self.horiz_layer_name - else: - debug.error("Invalid zindex for track", -1) - - min_width = drc("minwidth_{0}".format(layer_name), width, length) - min_spacing = drc(str(layer_name)+"_to_"+str(layer_name), width, length) - - return (min_width,min_spacing) - def convert_pin_coord_to_tracks(self, pin, coord): """ Given a pin and a track coordinate, determine if the pin overlaps enough. @@ -497,144 +561,21 @@ class router: (width, spacing) = self.get_layer_width_space(coord.z) # This is the rectangle if we put a pin in the center of the track - track_rect = self.convert_track_to_pin(coord) - overlap_width = self.compute_overlap_width(pin.rect, track_rect) + track_pin = self.convert_track_to_pin(coord) + overlap_length = pin.overlap_length(track_pin) - debug.info(3,"Check overlap: {0} {1} . {2} = {3}".format(coord, pin.rect, track_rect, overlap_width)) + debug.info(3,"Check overlap: {0} {1} . {2} = {3}".format(coord, pin.rect, track_pin, overlap_length)) # If it overlaps by more than the min width DRC, we can just use the track - if overlap_width==math.inf or snap_val_to_grid(overlap_width) >= snap_val_to_grid(width): - debug.info(3," Overlap: {0} >? {1}".format(overlap_width,spacing)) + if overlap_length==math.inf or snap_val_to_grid(overlap_length) >= snap_val_to_grid(width): + debug.info(3," Overlap: {0} >? {1}".format(overlap_length,spacing)) return (coord, None) # Otherwise, keep track of the partial overlap grids in case we need to patch it later. else: - debug.info(3," Partial/no overlap: {0} >? {1}".format(overlap_width,spacing)) + debug.info(3," Partial/no overlap: {0} >? {1}".format(overlap_length,spacing)) return (None, coord) - def compute_overlap(self, r1, r2): - """ Calculate the rectangular overlap of two rectangles. """ - (r1_ll,r1_ur) = r1 - (r2_ll,r2_ur) = r2 - - #ov_ur = vector(min(r1_ur.x,r2_ur.x),min(r1_ur.y,r2_ur.y)) - #ov_ll = vector(max(r1_ll.x,r2_ll.x),max(r1_ll.y,r2_ll.y)) - - dy = min(r1_ur.y,r2_ur.y)-max(r1_ll.y,r2_ll.y) - dx = min(r1_ur.x,r2_ur.x)-max(r1_ll.x,r2_ll.x) - - if dx>0 and dy>0: - return [dx,dy] - else: - return [0,0] - - def compute_overlap_width(self, r1, r2): - """ - Calculate the intersection segment and determine its width. - """ - intersections = self.compute_overlap_segment(r1,r2) - - if len(intersections)==2: - (p1,p2) = intersections - return math.sqrt(pow(p1[0]-p2[0],2) + pow(p1[1]-p2[1],2)) - else: - # we either have no overlap or complete overlap - # Compute the width of the overlap of the two rectangles - overlap_rect=self.compute_overlap(r1, r2) - # Determine the min x or y overlap - min_overlap = min(overlap_rect) - if min_overlap>0: - return math.inf - else: - return 0 - - - def compute_overlap_segment(self, r1, r2): - """ - Calculate the intersection segment of two rectangles - (if any) - """ - (r1_ll,r1_ur) = r1 - (r2_ll,r2_ur) = r2 - - # The other corners besides ll and ur - r1_ul = vector(r1_ll.x, r1_ur.y) - r1_lr = vector(r1_ur.x, r1_ll.y) - r2_ul = vector(r2_ll.x, r2_ur.y) - r2_lr = vector(r2_ur.x, r2_ll.y) - - from itertools import tee - def pairwise(iterable): - "s -> (s0,s1), (s1,s2), (s2, s3), ..." - a, b = tee(iterable) - next(b, None) - return zip(a, b) - - # R1 edges CW - r1_cw_points = [r1_ll, r1_ul, r1_ur, r1_lr, r1_ll] - r1_edges = [] - for (p,q) in pairwise(r1_cw_points): - r1_edges.append([p,q]) - - # R2 edges CW - r2_cw_points = [r2_ll, r2_ul, r2_ur, r2_lr, r2_ll] - r2_edges = [] - for (p,q) in pairwise(r2_cw_points): - r2_edges.append([p,q]) - - # There are 4 edges on each rectangle - # so just brute force check intersection of each - # Two pairs of them should intersect - intersections = [] - for r1e in r1_edges: - for r2e in r2_edges: - i = self.segment_intersection(r1e, r2e) - if i: - intersections.append(i) - - return intersections - - def on_segment(self, p, q, r): - """ - Given three co-linear points, determine if q lies on segment pr - """ - if q[0] <= max(p[0], r[0]) and \ - q[0] >= min(p[0], r[0]) and \ - q[1] <= max(p[1], r[1]) and \ - q[1] >= min(p[1], r[1]): - return True - - return False - - def segment_intersection(self, s1, s2): - """ - Determine the intersection point of two segments - Return the a segment if they overlap. - Return None if they don't. - """ - (a,b) = s1 - (c,d) = s2 - # Line AB represented as a1x + b1y = c1 - a1 = b.y - a.y - b1 = a.x - b.x - c1 = a1*a.x + b1*a.y - - # Line CD represented as a2x + b2y = c2 - a2 = d.y - c.y - b2 = c.x - d.x - c2 = a2*c.x + b2*c.y - - determinant = a1*b2 - a2*b1 - - if determinant!=0: - x = (b2*c1 - b1*c2)/determinant - y = (a1*c2 - a2*c1)/determinant - - r = [x,y] - if self.on_segment(a, r, b) and self.on_segment(c, r, d): - return [x, y] - - return None @@ -659,7 +600,8 @@ class router: y = track.y*self.track_width + 0.5*self.track_width - space ur = snap_to_grid(vector(x,y)) - return [ll,ur] + p = pin_layout("", [ll, ur], self.get_layer(track[2])) + return p def convert_track_to_shape(self, track): """ @@ -680,7 +622,8 @@ class router: Analyze the shapes of a pin and combine them into groups which are connected. """ pin_set = self.pins[pin_name] - local_debug=False + local_debug = False + # Put each pin in an equivalence class of it's own equiv_classes = [set([x]) for x in pin_set] if local_debug: @@ -711,6 +654,8 @@ class router: def combine_classes(equiv_classes): """ Recursive function to combine classes. """ + local_debug = False + if local_debug: debug.info(0,"\nRECURSE:\n",pformat(equiv_classes)) if len(equiv_classes)==1: @@ -733,178 +678,16 @@ class router: reduced_classes = combine_classes(equiv_classes) if local_debug: debug.info(0,"FINAL ",reduced_classes) - self.pin_groups[pin_name]=reduced_classes + self.pin_groups[pin_name] = [pin_group(name=pin_name, pin_set=x, router=self) for x in reduced_classes] def convert_pins(self, pin_name): """ Convert the pin groups into pin tracks and blockage tracks. """ - try: - self.pin_grids[pin_name] - except: - self.pin_grids[pin_name] = [] - - found_pin = False for pg in self.pin_groups[pin_name]: - #print("PG ",pg) - # Keep the same groups for each pin - pin_set = set() - blockage_set = set() - for pin in pg: - debug.info(2," Converting {0}".format(pin)) - # Determine which tracks the pin overlaps - pin_in_tracks=self.convert_pin_to_tracks(pin_name, pin) - pin_set.update(pin_in_tracks) - # Blockages will be a super-set of pins since it uses the inflated pin shape. - blockage_in_tracks = self.convert_blockage(pin) - blockage_set.update(blockage_in_tracks) - - # If we have a blockage, we must remove the grids - # Remember, this excludes the pin blockages already - shared_set = pin_set & self.blocked_grids - if shared_set: - debug.info(2,"Removing pins {}".format(shared_set)) - shared_set = blockage_set & self.blocked_grids - if shared_set: - debug.info(2,"Removing blocks {}".format(shared_set)) - pin_set.difference_update(self.blocked_grids) - blockage_set.difference_update(self.blocked_grids) - debug.info(2," pins {}".format(pin_set)) - debug.info(2," blocks {}".format(blockage_set)) - - # At least one of the groups must have some valid tracks - if (len(pin_set)==0 and len(blockage_set)==0): - self.write_debug_gds("blocked_pin.gds") - debug.error("Unable to find unblocked pin on grid.") - - # We need to route each of the components, so don't combine the groups - self.pin_grids[pin_name].append(pin_set | blockage_set) - - # Add all of the partial blocked grids to the set for the design - # if they are not blocked by other metal - #partial_set = blockage_set - pin_set - #self.pin_blockages[pin_name].append(partial_set) - - # We should not have added the pins to the blockages, - # but remove them just in case - # Partial set may still be in the blockages if there were - # other shapes disconnected from the pins that were also overlapping - #self.blocked_grids.difference_update(pin_set) + pg.convert_pin() - def enclose_pin_grids(self, grids, seed): - """ - This encloses a single pin component with a rectangle - starting with the seed and expanding right until blocked - and then up until blocked. - """ - - # We may have started with an empty set - if not grids: - return None - - # Start with the seed - ll = seed - - # Start with the ll and make the widest row - row = [ll] - # Move right while we can - while True: - right = row[-1] + vector3d(1,0,0) - # Can't move if not in the pin shape - if right in grids and right not in self.blocked_grids: - row.append(right) - else: - break - # Move up while we can - while True: - next_row = [x+vector3d(0,1,0) for x in row] - for cell in next_row: - # Can't move if any cell is not in the pin shape - if cell not in grids or cell in self.blocked_grids: - break - else: - row = next_row - # Skips the second break - continue - # Breaks from the nested break - break - - # Add a shape from ll to ur - ur = row[-1] - return self.compute_pin_enclosure(ll, ur, ll.z) - - def remove_redundant_shapes(self, pin_list): - """ - Remove any pin layout that is contained within another. - """ - local_debug = False - if local_debug: - debug.info(0,"INITIAL:",pin_list) - - # Make a copy of the list to start - new_pin_list = pin_list.copy() - - # This is n^2, but the number is small - for pin1 in pin_list: - for pin2 in pin_list: - # Can't contain yourself - if pin1 == pin2: - continue - if pin2.contains(pin1): - # It may have already been removed by being enclosed in another pin - if pin1 in new_pin_list: - new_pin_list.remove(pin1) - - if local_debug: - debug.info(0,"FINAL :",new_pin_list) - return new_pin_list - - def compute_enclosures(self, tracks): - """ - Find the minimum rectangle enclosures of the given tracks. - """ - pin_list = [] - for seed in tracks: - pin_list.append(self.enclose_pin_grids(tracks, seed)) - - return self.remove_redundant_shapes(pin_list) - - def overlap_any_shape(self, pin_list, shape_list): - """ - Does the given pin overlap any of the shapes in the pin list. - """ - for pin in pin_list: - for other in shape_list: - if pin.overlaps(other): - return True - - return False - - def max_pin_layout(self, pin_list): - """ - Return the max area pin_layout - """ - biggest = pin_list[0] - for pin in pin_list: - if pin.area() > biggest.area(): - biggest = pin - - return pin - - def find_smallest_connector(self, pin_list, enclosure_list): - """ - Compute all of the connectors between non-overlapping pins and enclosures. - Return the smallest. - """ - smallest = None - for pin in pin_list: - for enclosure in enclosure_list: - new_enclosure = self.compute_enclosure(pin, enclosure) - if smallest == None or new_enclosure.area()0: + pg.set_routed() + continue + + # Else, if we overlap some of the space track, we can patch it with an enclosure + common_set = supply_tracks & pg.grids + if len(common_set)>0: + pg.create_simple_overlap_enclosure(common_set) + pg.add_enclosure(self.cell) - def create_simple_overlap_enclosure(self, pin_name, start_set): - """ - This takes a set of tracks that overlap a supply rail and creates an enclosure - that is ensured to overlap the supply rail wire. - It then adds rectangle(s) for the enclosure. - """ - additional_set = set() - # Check the layer of any element in the pin to determine which direction to route it - e = next(iter(start_set)) - new_set = start_set.copy() - if e.z==0: - new_set = self.recurse_simple_overlap_enclosure(pin_name, start_set, direction.NORTH) - if not new_set: - new_set = self.recurse_simple_overlap_enclosure(pin_name, start_set, direction.SOUTH) - else: - new_set = self.recurse_simple_overlap_enclosure(pin_name, start_set, direction.EAST) - if not new_set: - new_set = self.recurse_simple_overlap_enclosure(pin_name, start_set, direction.WEST) - - enclosure_list = self.compute_enclosures(new_set) - for pin in enclosure_list: - debug.info(2,"Adding simple overlap enclosure {0} {1}".format(pin_name, pin)) - self.cell.add_rect(layer=pin.layer, - offset=pin.ll(), - width=pin.width(), - height=pin.height()) - @@ -228,9 +184,8 @@ class supply_router(router): # the overlap area for placement of a via overlap = new_r1 & new_r2 if len(overlap) >= self.supply_rail_wire_width**2: - debug.info(2,"Via overlap {0} {1} {2}".format(len(overlap),self.supply_rail_wire_width**2,overlap)) - connections.add(i1) - connections.add(i2) + debug.info(3,"Via overlap {0} {1} {2}".format(len(overlap),self.supply_rail_wire_width**2,overlap)) + connections.update([i1,i2]) via_areas.append(overlap) # Go through and add the vias at the center of the intersection @@ -241,11 +196,12 @@ class supply_router(router): self.add_via(center,self.rail_track_width) # Determien which indices were not connected to anything above - all_indices = set([x for x in range(len(self.supply_rails[name]))]) - missing_indices = all_indices ^ connections + missing_indices = set([x for x in range(len(self.supply_rails[name]))]) + missing_indices.difference_update(connections) + # Go through and remove those disconnected indices # (No via was added, so that doesn't need to be removed) - for rail_index in missing_indices: + for rail_index in sorted(missing_indices, reverse=True): ll = grid_utils.get_lower_left(all_rails[rail_index]) ur = grid_utils.get_upper_right(all_rails[rail_index]) debug.info(1,"Removing disconnected supply rail {0} .. {1}".format(ll,ur)) @@ -331,11 +287,12 @@ class supply_router(router): # While we can keep expanding east in this horizontal track while wave and wave[0].x < self.max_xoffset: added_rail = self.find_supply_rail(name, wave, direction.EAST) - if added_rail: - wave = added_rail.neighbor(direction.EAST) + if not added_rail: + # Just seed with the next one + wave = [x+vector3d(1,0,0) for x in wave] else: - wave = None - + # Seed with the neighbor of the end of the last rail + wave = added_rail.neighbor(direction.EAST) # Vertical supply rails max_offset = self.rg.ur.x @@ -345,10 +302,12 @@ class supply_router(router): # While we can keep expanding north in this vertical track while wave and wave[0].y < self.max_yoffset: added_rail = self.find_supply_rail(name, wave, direction.NORTH) - if added_rail: - wave = added_rail.neighbor(direction.NORTH) + if not added_rail: + # Just seed with the next one + wave = [x+vector3d(0,1,0) for x in wave] else: - wave = None + # Seed with the neighbor of the end of the last rail + wave = added_rail.neighbor(direction.NORTH) def find_supply_rail(self, name, seed_wave, direct): """ @@ -356,15 +315,18 @@ class supply_router(router): to contain a via, and, if so, add it. """ start_wave = self.find_supply_rail_start(name, seed_wave, direct) + + # This means there were no more unblocked grids in the row/col if not start_wave: return None - + wave_path = self.probe_supply_rail(name, start_wave, direct) - if self.approve_supply_rail(name, wave_path): - return wave_path - else: - return None + self.approve_supply_rail(name, wave_path) + + # Return the rail whether we approved it or not, + # as it will be used to find the next start location + return wave_path def find_supply_rail_start(self, name, seed_wave, direct): """ @@ -432,9 +394,6 @@ class supply_router(router): Must be done with lower left at 0,0 """ - # Compute the grid dimensions - self.compute_supply_rail_dimensions() - # Compute the grid locations of the supply rails self.compute_supply_rails(name, supply_number) @@ -460,23 +419,27 @@ class supply_router(router): self.supply_rail_wire_tracks[pin_name] = wire_set - def route_pins_to_rails(self, pin_name, remaining_component_indices): + def route_pins_to_rails(self, pin_name): """ This will route each of the remaining pin components to the supply rails. After it is done, the cells are added to the pin blockage list. """ - + remaining_components = sum(not x.is_routed() for x in self.pin_groups[pin_name]) debug.info(1,"Pin {0} has {1} remaining components to route.".format(pin_name, - len(remaining_component_indices))) + remaining_components)) - recent_paths = [] - # For every component - for index in remaining_component_indices: + for index,pg in enumerate(self.pin_groups[pin_name]): + if pg.is_routed(): + continue + debug.info(2,"Routing component {0} {1}".format(pin_name, index)) - + + # Clear everything in the routing grid. self.rg.reinit() - + + # This is inefficient since it is non-incremental, but it was + # easier to debug. self.prepare_blockages(pin_name) # Add the single component of the pin as the source @@ -487,16 +450,9 @@ class supply_router(router): # Don't add the other pins, but we could? self.add_supply_rail_target(pin_name) - # Add the previous paths as targets too - #self.add_path_target(recent_paths) - - #print(self.rg.target) - # Actually run the A* router if not self.run_router(detour_scale=5): self.write_debug_gds() - - recent_paths.append(self.paths[-1]) def add_supply_rail_target(self, pin_name): diff --git a/compiler/router/vector3d.py b/compiler/router/vector3d.py index 42bc35d4..a6e61078 100644 --- a/compiler/router/vector3d.py +++ b/compiler/router/vector3d.py @@ -163,3 +163,21 @@ class vector3d(): """ Min of both values """ return vector3d(min(self.x,other.x),min(self.y,other.y),min(self.z,other.z)) + def distance(self, other): + """ Return the planar distance between two values """ + return abs(self.x-other.x)+abs(self.y-other.y) + + + def adjacent(self, other): + """ Is the one grid adjacent in any planar direction to the other """ + if self == other + vector3d(1,0,0): + return True + elif self == other + vector3d(-1,0,0): + return True + elif self == other + vector3d(0,1,0): + return True + elif self == other + vector3d(0,-1,0): + return True + else: + return False + diff --git a/compiler/tests/00_code_format_check_test.py b/compiler/tests/00_code_format_check_test.py index 026f7e2b..869e81bd 100755 --- a/compiler/tests/00_code_format_check_test.py +++ b/compiler/tests/00_code_format_check_test.py @@ -116,7 +116,7 @@ def check_print_output(file_name): return(count) -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/01_library_drc_test.py b/compiler/tests/01_library_drc_test.py index b809c14d..046e6378 100755 --- a/compiler/tests/01_library_drc_test.py +++ b/compiler/tests/01_library_drc_test.py @@ -39,7 +39,7 @@ def setup_files(): return (gds_dir, gds_files) -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/02_library_lvs_test.py b/compiler/tests/02_library_lvs_test.py index 0b35f159..0367c5f2 100755 --- a/compiler/tests/02_library_lvs_test.py +++ b/compiler/tests/02_library_lvs_test.py @@ -59,7 +59,7 @@ def setup_files(): return (gds_dir, sp_dir, allnames) -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/03_contact_test.py b/compiler/tests/03_contact_test.py index 2fab1c4e..33aa45ae 100755 --- a/compiler/tests/03_contact_test.py +++ b/compiler/tests/03_contact_test.py @@ -43,7 +43,7 @@ class contact_test(openram_test): -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/03_path_test.py b/compiler/tests/03_path_test.py index f70d00be..915c5c78 100755 --- a/compiler/tests/03_path_test.py +++ b/compiler/tests/03_path_test.py @@ -84,7 +84,7 @@ class path_test(openram_test): -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/03_ptx_1finger_nmos_test.py b/compiler/tests/03_ptx_1finger_nmos_test.py index 727c24f0..9a81810e 100755 --- a/compiler/tests/03_ptx_1finger_nmos_test.py +++ b/compiler/tests/03_ptx_1finger_nmos_test.py @@ -25,7 +25,7 @@ class ptx_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/03_ptx_1finger_pmos_test.py b/compiler/tests/03_ptx_1finger_pmos_test.py index 04b9ab64..a3ed99ff 100755 --- a/compiler/tests/03_ptx_1finger_pmos_test.py +++ b/compiler/tests/03_ptx_1finger_pmos_test.py @@ -25,7 +25,7 @@ class ptx_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/03_ptx_3finger_nmos_test.py b/compiler/tests/03_ptx_3finger_nmos_test.py index 20343b2e..e1febdbc 100755 --- a/compiler/tests/03_ptx_3finger_nmos_test.py +++ b/compiler/tests/03_ptx_3finger_nmos_test.py @@ -27,7 +27,7 @@ class ptx_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/03_ptx_3finger_pmos_test.py b/compiler/tests/03_ptx_3finger_pmos_test.py index 37933702..af9a5d42 100755 --- a/compiler/tests/03_ptx_3finger_pmos_test.py +++ b/compiler/tests/03_ptx_3finger_pmos_test.py @@ -27,7 +27,7 @@ class ptx_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/03_ptx_4finger_nmos_test.py b/compiler/tests/03_ptx_4finger_nmos_test.py index 09788a5e..08a20898 100755 --- a/compiler/tests/03_ptx_4finger_nmos_test.py +++ b/compiler/tests/03_ptx_4finger_nmos_test.py @@ -27,7 +27,7 @@ class ptx_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/03_ptx_4finger_pmos_test.py b/compiler/tests/03_ptx_4finger_pmos_test.py index f43d7dc7..01857eda 100755 --- a/compiler/tests/03_ptx_4finger_pmos_test.py +++ b/compiler/tests/03_ptx_4finger_pmos_test.py @@ -27,7 +27,7 @@ class ptx_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/03_wire_test.py b/compiler/tests/03_wire_test.py index 557fee5b..1b18e14b 100755 --- a/compiler/tests/03_wire_test.py +++ b/compiler/tests/03_wire_test.py @@ -121,7 +121,7 @@ class wire_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/04_pbitcell_test.py b/compiler/tests/04_pbitcell_test.py index 0b6bd8f5..e5dbbc5e 100755 --- a/compiler/tests/04_pbitcell_test.py +++ b/compiler/tests/04_pbitcell_test.py @@ -94,7 +94,7 @@ class pbitcell_test(openram_test): -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/04_pinv_10x_test.py b/compiler/tests/04_pinv_10x_test.py index 3a7f846a..d457d2a9 100755 --- a/compiler/tests/04_pinv_10x_test.py +++ b/compiler/tests/04_pinv_10x_test.py @@ -25,7 +25,7 @@ class pinv_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/04_pinv_1x_beta_test.py b/compiler/tests/04_pinv_1x_beta_test.py index c1bb6aba..77ff5454 100755 --- a/compiler/tests/04_pinv_1x_beta_test.py +++ b/compiler/tests/04_pinv_1x_beta_test.py @@ -24,7 +24,7 @@ class pinv_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/04_pinv_1x_test.py b/compiler/tests/04_pinv_1x_test.py index 555aa0e5..49cb1cb1 100755 --- a/compiler/tests/04_pinv_1x_test.py +++ b/compiler/tests/04_pinv_1x_test.py @@ -23,7 +23,7 @@ class pinv_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/04_pinv_2x_test.py b/compiler/tests/04_pinv_2x_test.py index 6882a719..84bc55ee 100755 --- a/compiler/tests/04_pinv_2x_test.py +++ b/compiler/tests/04_pinv_2x_test.py @@ -25,7 +25,7 @@ class pinv_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/04_pinvbuf_test.py b/compiler/tests/04_pinvbuf_test.py index 9c55ebe3..d35f1ec7 100755 --- a/compiler/tests/04_pinvbuf_test.py +++ b/compiler/tests/04_pinvbuf_test.py @@ -23,7 +23,7 @@ class pinvbuf_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/04_pnand2_test.py b/compiler/tests/04_pnand2_test.py index b6739e4e..a2ac9288 100755 --- a/compiler/tests/04_pnand2_test.py +++ b/compiler/tests/04_pnand2_test.py @@ -27,7 +27,7 @@ class pnand2_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/04_pnand3_test.py b/compiler/tests/04_pnand3_test.py index db3817f5..f6daedda 100755 --- a/compiler/tests/04_pnand3_test.py +++ b/compiler/tests/04_pnand3_test.py @@ -27,7 +27,7 @@ class pnand3_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/04_pnor2_test.py b/compiler/tests/04_pnor2_test.py index 978c03ad..ce4b19ae 100755 --- a/compiler/tests/04_pnor2_test.py +++ b/compiler/tests/04_pnor2_test.py @@ -26,7 +26,7 @@ class pnor2_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/04_precharge_test.py b/compiler/tests/04_precharge_test.py index 02de2efd..e5419dab 100755 --- a/compiler/tests/04_precharge_test.py +++ b/compiler/tests/04_precharge_test.py @@ -39,7 +39,7 @@ class precharge_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/04_replica_pbitcell_test.py b/compiler/tests/04_replica_pbitcell_test.py index 7a803d1c..ce9f00b9 100755 --- a/compiler/tests/04_replica_pbitcell_test.py +++ b/compiler/tests/04_replica_pbitcell_test.py @@ -37,7 +37,7 @@ class replica_pbitcell_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/04_single_level_column_mux_test.py b/compiler/tests/04_single_level_column_mux_test.py index 3a7d6399..c43b15fd 100755 --- a/compiler/tests/04_single_level_column_mux_test.py +++ b/compiler/tests/04_single_level_column_mux_test.py @@ -41,7 +41,7 @@ class single_level_column_mux_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/05_bitcell_1rw_1r_array_test.py b/compiler/tests/05_bitcell_1rw_1r_array_test.py index 68dcc409..1223085e 100755 --- a/compiler/tests/05_bitcell_1rw_1r_array_test.py +++ b/compiler/tests/05_bitcell_1rw_1r_array_test.py @@ -29,7 +29,7 @@ class bitcell_1rw_1r_array_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/05_bitcell_array_test.py b/compiler/tests/05_bitcell_array_test.py index 4ea5c65a..93668e05 100755 --- a/compiler/tests/05_bitcell_array_test.py +++ b/compiler/tests/05_bitcell_array_test.py @@ -25,7 +25,7 @@ class array_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/05_pbitcell_array_test.py b/compiler/tests/05_pbitcell_array_test.py index 4fc75ac5..4da5bec9 100755 --- a/compiler/tests/05_pbitcell_array_test.py +++ b/compiler/tests/05_pbitcell_array_test.py @@ -44,7 +44,7 @@ class pbitcell_array_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/06_hierarchical_decoder_test.py b/compiler/tests/06_hierarchical_decoder_test.py index 513e07a8..09201149 100755 --- a/compiler/tests/06_hierarchical_decoder_test.py +++ b/compiler/tests/06_hierarchical_decoder_test.py @@ -69,7 +69,7 @@ class hierarchical_decoder_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/06_hierarchical_predecode2x4_test.py b/compiler/tests/06_hierarchical_predecode2x4_test.py index bcfd207a..e16916d6 100755 --- a/compiler/tests/06_hierarchical_predecode2x4_test.py +++ b/compiler/tests/06_hierarchical_predecode2x4_test.py @@ -35,7 +35,7 @@ class hierarchical_predecode2x4_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/06_hierarchical_predecode3x8_test.py b/compiler/tests/06_hierarchical_predecode3x8_test.py index b89f4bea..ed5da57c 100755 --- a/compiler/tests/06_hierarchical_predecode3x8_test.py +++ b/compiler/tests/06_hierarchical_predecode3x8_test.py @@ -35,7 +35,7 @@ class hierarchical_predecode3x8_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/07_single_level_column_mux_array_test.py b/compiler/tests/07_single_level_column_mux_array_test.py index 63f69bc5..800292b6 100755 --- a/compiler/tests/07_single_level_column_mux_array_test.py +++ b/compiler/tests/07_single_level_column_mux_array_test.py @@ -54,7 +54,7 @@ class single_level_column_mux_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/08_precharge_array_test.py b/compiler/tests/08_precharge_array_test.py index be8fc9d7..5ea9931b 100755 --- a/compiler/tests/08_precharge_array_test.py +++ b/compiler/tests/08_precharge_array_test.py @@ -39,7 +39,7 @@ class precharge_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/08_wordline_driver_test.py b/compiler/tests/08_wordline_driver_test.py index 7f0ca275..369b6774 100755 --- a/compiler/tests/08_wordline_driver_test.py +++ b/compiler/tests/08_wordline_driver_test.py @@ -37,7 +37,7 @@ class wordline_driver_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/09_sense_amp_array_test.py b/compiler/tests/09_sense_amp_array_test.py index af2c974c..a18631f9 100755 --- a/compiler/tests/09_sense_amp_array_test.py +++ b/compiler/tests/09_sense_amp_array_test.py @@ -42,7 +42,7 @@ class sense_amp_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/10_write_driver_array_test.py b/compiler/tests/10_write_driver_array_test.py index ab9dc615..fa374181 100755 --- a/compiler/tests/10_write_driver_array_test.py +++ b/compiler/tests/10_write_driver_array_test.py @@ -42,7 +42,7 @@ class write_driver_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/11_dff_array_test.py b/compiler/tests/11_dff_array_test.py index a55c6407..eed41dda 100755 --- a/compiler/tests/11_dff_array_test.py +++ b/compiler/tests/11_dff_array_test.py @@ -31,7 +31,7 @@ class dff_array_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/11_dff_buf_array_test.py b/compiler/tests/11_dff_buf_array_test.py index f0b75552..d2932cac 100755 --- a/compiler/tests/11_dff_buf_array_test.py +++ b/compiler/tests/11_dff_buf_array_test.py @@ -31,7 +31,7 @@ class dff_buf_array_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/11_dff_buf_test.py b/compiler/tests/11_dff_buf_test.py index f434f768..c9c25f16 100755 --- a/compiler/tests/11_dff_buf_test.py +++ b/compiler/tests/11_dff_buf_test.py @@ -23,7 +23,7 @@ class dff_buf_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/11_dff_inv_array_test.py b/compiler/tests/11_dff_inv_array_test.py index 2196a3f2..ed03e6bc 100755 --- a/compiler/tests/11_dff_inv_array_test.py +++ b/compiler/tests/11_dff_inv_array_test.py @@ -31,7 +31,7 @@ class dff_inv_array_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/11_dff_inv_test.py b/compiler/tests/11_dff_inv_test.py index 43d49246..53a92852 100755 --- a/compiler/tests/11_dff_inv_test.py +++ b/compiler/tests/11_dff_inv_test.py @@ -23,7 +23,7 @@ class dff_inv_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/12_tri_gate_array_test.py b/compiler/tests/12_tri_gate_array_test.py index 4f9cfa3e..cb789155 100755 --- a/compiler/tests/12_tri_gate_array_test.py +++ b/compiler/tests/12_tri_gate_array_test.py @@ -27,7 +27,7 @@ class tri_gate_array_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/13_delay_chain_test.py b/compiler/tests/13_delay_chain_test.py index 2cc745c2..1052f0de 100755 --- a/compiler/tests/13_delay_chain_test.py +++ b/compiler/tests/13_delay_chain_test.py @@ -23,7 +23,7 @@ class delay_chain_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/14_replica_bitline_test.py b/compiler/tests/14_replica_bitline_test.py index 6797bc65..9853b581 100755 --- a/compiler/tests/14_replica_bitline_test.py +++ b/compiler/tests/14_replica_bitline_test.py @@ -70,7 +70,7 @@ class replica_bitline_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index 7a4ff768..ef435c4c 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -53,7 +53,7 @@ class control_logic_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/19_bank_select_test.py b/compiler/tests/19_bank_select_test.py index 23b7ec46..1245926b 100755 --- a/compiler/tests/19_bank_select_test.py +++ b/compiler/tests/19_bank_select_test.py @@ -40,7 +40,7 @@ class bank_select_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/19_multi_bank_test.py b/compiler/tests/19_multi_bank_test.py index 4fceafec..9bf32423 100755 --- a/compiler/tests/19_multi_bank_test.py +++ b/compiler/tests/19_multi_bank_test.py @@ -49,7 +49,7 @@ class multi_bank_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/19_pmulti_bank_test.py b/compiler/tests/19_pmulti_bank_test.py index 03544587..32d3917a 100755 --- a/compiler/tests/19_pmulti_bank_test.py +++ b/compiler/tests/19_pmulti_bank_test.py @@ -54,7 +54,7 @@ class multi_bank_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/19_psingle_bank_test.py b/compiler/tests/19_psingle_bank_test.py index d45283e0..dee59175 100755 --- a/compiler/tests/19_psingle_bank_test.py +++ b/compiler/tests/19_psingle_bank_test.py @@ -137,7 +137,7 @@ class psingle_bank_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/19_single_bank_test.py b/compiler/tests/19_single_bank_test.py index 3c32b30d..da411d1f 100755 --- a/compiler/tests/19_single_bank_test.py +++ b/compiler/tests/19_single_bank_test.py @@ -48,7 +48,7 @@ class single_bank_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/20_psram_1bank_nomux_test.py b/compiler/tests/20_psram_1bank_nomux_test.py index 6106763c..a2992cba 100755 --- a/compiler/tests/20_psram_1bank_nomux_test.py +++ b/compiler/tests/20_psram_1bank_nomux_test.py @@ -128,7 +128,7 @@ class sram_1bank_test(openram_test): """ globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/20_sram_1bank_2mux_test.py b/compiler/tests/20_sram_1bank_2mux_test.py index db018f1e..2c8e28f0 100755 --- a/compiler/tests/20_sram_1bank_2mux_test.py +++ b/compiler/tests/20_sram_1bank_2mux_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 20_sram_1bank_2mux_test") +#@unittest.skip("SKIPPING 20_sram_1bank_2mux_test") class sram_1bank_2mux_test(openram_test): def runTest(self): @@ -29,7 +29,7 @@ class sram_1bank_2mux_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/20_sram_1bank_4mux_test.py b/compiler/tests/20_sram_1bank_4mux_test.py index 35416bbe..489ff354 100755 --- a/compiler/tests/20_sram_1bank_4mux_test.py +++ b/compiler/tests/20_sram_1bank_4mux_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 20_sram_1bank_2mux_test") +#@unittest.skip("SKIPPING 20_sram_1bank_4mux_test") class sram_1bank_4mux_test(openram_test): def runTest(self): @@ -29,7 +29,7 @@ class sram_1bank_4mux_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/20_sram_1bank_8mux_test.py b/compiler/tests/20_sram_1bank_8mux_test.py index d09165a2..2595582f 100755 --- a/compiler/tests/20_sram_1bank_8mux_test.py +++ b/compiler/tests/20_sram_1bank_8mux_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 20_sram_1bank_8mux_test") +#@unittest.skip("SKIPPING 20_sram_1bank_8mux_test") class sram_1bank_8mux_test(openram_test): def runTest(self): @@ -29,7 +29,7 @@ class sram_1bank_8mux_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/20_sram_1bank_nomux_test.py b/compiler/tests/20_sram_1bank_nomux_test.py index 26f5e9ba..783bcad2 100755 --- a/compiler/tests/20_sram_1bank_nomux_test.py +++ b/compiler/tests/20_sram_1bank_nomux_test.py @@ -11,7 +11,8 @@ import globals from globals import OPTS import debug -class sram_1bank_test(openram_test): +#@unittest.skip("SKIPPING 20_sram_1bank_nomux_test") +class sram_1bank_nomux_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) @@ -28,7 +29,7 @@ class sram_1bank_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/20_sram_2bank_test.py b/compiler/tests/20_sram_2bank_test.py index ff9fbaea..ab8c6ec2 100755 --- a/compiler/tests/20_sram_2bank_test.py +++ b/compiler/tests/20_sram_2bank_test.py @@ -48,7 +48,7 @@ class sram_2bank_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/20_sram_4bank_test.py b/compiler/tests/20_sram_4bank_test.py index fb34d3b0..25649e8e 100755 --- a/compiler/tests/20_sram_4bank_test.py +++ b/compiler/tests/20_sram_4bank_test.py @@ -47,7 +47,7 @@ class sram_4bank_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index a5aca3e8..5facb482 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -81,7 +81,7 @@ class timing_sram_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/21_hspice_setuphold_test.py b/compiler/tests/21_hspice_setuphold_test.py index 9bfdb24b..faa8617d 100755 --- a/compiler/tests/21_hspice_setuphold_test.py +++ b/compiler/tests/21_hspice_setuphold_test.py @@ -52,7 +52,7 @@ class timing_setup_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index 45a9b7f6..3ef27fc5 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -81,7 +81,7 @@ class timing_sram_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/21_ngspice_setuphold_test.py b/compiler/tests/21_ngspice_setuphold_test.py index d58bfc50..924d05a5 100755 --- a/compiler/tests/21_ngspice_setuphold_test.py +++ b/compiler/tests/21_ngspice_setuphold_test.py @@ -53,7 +53,7 @@ class timing_setup_test(openram_test): reload(characterizer) globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/22_psram_1bank_2mux_func_test.py b/compiler/tests/22_psram_1bank_2mux_func_test.py index d8233d08..1e1367ed 100755 --- a/compiler/tests/22_psram_1bank_2mux_func_test.py +++ b/compiler/tests/22_psram_1bank_2mux_func_test.py @@ -49,7 +49,7 @@ class psram_1bank_2mux_func_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index 1ae684d9..d62e2855 100755 --- a/compiler/tests/22_psram_1bank_4mux_func_test.py +++ b/compiler/tests/22_psram_1bank_4mux_func_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 22_psram_1bank_4mux_func_test") +#@unittest.skip("SKIPPING 22_psram_1bank_4mux_func_test") class psram_1bank_4mux_func_test(openram_test): def runTest(self): @@ -49,7 +49,7 @@ class psram_1bank_4mux_func_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/22_psram_1bank_8mux_func_test.py b/compiler/tests/22_psram_1bank_8mux_func_test.py index d81e76f9..02ea2f3b 100755 --- a/compiler/tests/22_psram_1bank_8mux_func_test.py +++ b/compiler/tests/22_psram_1bank_8mux_func_test.py @@ -37,6 +37,7 @@ class psram_1bank_8mux_func_test(openram_test): c.words_per_row, c.num_banks)) s = sram(c, name="sram") + tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) @@ -48,7 +49,7 @@ class psram_1bank_8mux_func_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/22_psram_1bank_nomux_func_test.py b/compiler/tests/22_psram_1bank_nomux_func_test.py index 681e24d5..ce852dff 100755 --- a/compiler/tests/22_psram_1bank_nomux_func_test.py +++ b/compiler/tests/22_psram_1bank_nomux_func_test.py @@ -49,7 +49,7 @@ class psram_1bank_nomux_func_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/22_sram_1bank_2mux_func_test.py b/compiler/tests/22_sram_1bank_2mux_func_test.py index 7779ed4f..8b195c95 100755 --- a/compiler/tests/22_sram_1bank_2mux_func_test.py +++ b/compiler/tests/22_sram_1bank_2mux_func_test.py @@ -47,7 +47,7 @@ class sram_1bank_2mux_func_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/22_sram_1bank_4mux_func_test.py b/compiler/tests/22_sram_1bank_4mux_func_test.py index c16b86fe..0df3ff0e 100755 --- a/compiler/tests/22_sram_1bank_4mux_func_test.py +++ b/compiler/tests/22_sram_1bank_4mux_func_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 22_sram_1bank_4mux_func_test") +#@unittest.skip("SKIPPING 22_sram_1bank_4mux_func_test") class sram_1bank_4mux_func_test(openram_test): def runTest(self): @@ -47,7 +47,7 @@ class sram_1bank_4mux_func_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/22_sram_1bank_8mux_func_test.py b/compiler/tests/22_sram_1bank_8mux_func_test.py index be8e538f..9f910ca3 100755 --- a/compiler/tests/22_sram_1bank_8mux_func_test.py +++ b/compiler/tests/22_sram_1bank_8mux_func_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 22_sram_1bank_8mux_func_test") +#@unittest.skip("SKIPPING 22_sram_1bank_8mux_func_test") class sram_1bank_8mux_func_test(openram_test): def runTest(self): @@ -38,6 +38,7 @@ class sram_1bank_8mux_func_test(openram_test): c.words_per_row, c.num_banks)) s = sram(c, name="sram") + tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) @@ -49,7 +50,7 @@ class sram_1bank_8mux_func_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/22_sram_1bank_nomux_func_test.py b/compiler/tests/22_sram_1bank_nomux_func_test.py index 52d63f4a..e6a5bcda 100755 --- a/compiler/tests/22_sram_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1bank_nomux_func_test.py @@ -39,7 +39,7 @@ class sram_1bank_nomux_func_test(openram_test): s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) - + f = functional(s.s, tempspice, corner) f.num_cycles = 10 (fail, error) = f.run() @@ -47,7 +47,7 @@ class sram_1bank_nomux_func_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/23_lib_sram_model_test.py b/compiler/tests/23_lib_sram_model_test.py index 8d5064d5..b111a57d 100755 --- a/compiler/tests/23_lib_sram_model_test.py +++ b/compiler/tests/23_lib_sram_model_test.py @@ -44,7 +44,7 @@ class lib_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/23_lib_sram_prune_test.py b/compiler/tests/23_lib_sram_prune_test.py index 952072aa..7f0a9c47 100755 --- a/compiler/tests/23_lib_sram_prune_test.py +++ b/compiler/tests/23_lib_sram_prune_test.py @@ -55,7 +55,7 @@ class lib_test(openram_test): reload(characterizer) globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/23_lib_sram_test.py b/compiler/tests/23_lib_sram_test.py index 1b2d317c..5534598e 100755 --- a/compiler/tests/23_lib_sram_test.py +++ b/compiler/tests/23_lib_sram_test.py @@ -54,7 +54,7 @@ class lib_test(openram_test): reload(characterizer) globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/24_lef_sram_test.py b/compiler/tests/24_lef_sram_test.py index f66104b6..d4bf2619 100755 --- a/compiler/tests/24_lef_sram_test.py +++ b/compiler/tests/24_lef_sram_test.py @@ -42,7 +42,7 @@ class lef_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/25_verilog_sram_test.py b/compiler/tests/25_verilog_sram_test.py index 48ba29e8..eebeb258 100755 --- a/compiler/tests/25_verilog_sram_test.py +++ b/compiler/tests/25_verilog_sram_test.py @@ -38,7 +38,7 @@ class verilog_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/26_pex_test.py b/compiler/tests/26_pex_test.py index edb344f9..d374e485 100755 --- a/compiler/tests/26_pex_test.py +++ b/compiler/tests/26_pex_test.py @@ -306,7 +306,7 @@ class sram_func_test(openram_test): sti_file.file.close() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/27_worst_case_delay_test.py b/compiler/tests/27_worst_case_delay_test.py index 42a07bef..52dd3422 100755 --- a/compiler/tests/27_worst_case_delay_test.py +++ b/compiler/tests/27_worst_case_delay_test.py @@ -73,7 +73,7 @@ class worst_case_timing_sram_test(openram_test): globals.end_openram() -# instantiate a copdsay of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/compiler/tests/30_openram_test.py b/compiler/tests/30_openram_test.py index 038a2e15..7450dfba 100755 --- a/compiler/tests/30_openram_test.py +++ b/compiler/tests/30_openram_test.py @@ -83,7 +83,7 @@ class openram_test(openram_test): globals.end_openram() -# instantiate a copy of the class to actually run the test +# run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] diff --git a/technology/freepdk45/tf/FreePDK45.tf b/technology/freepdk45/tf/FreePDK45.tf index 0021e644..f0bfc606 100644 --- a/technology/freepdk45/tf/FreePDK45.tf +++ b/technology/freepdk45/tf/FreePDK45.tf @@ -172,9 +172,9 @@ layerDefinitions( ( align drawing ) ( hardFence drawing ) ( softFence drawing ) - ( text drawing ) - ( text drawing1 ) - ( text drawing2 ) + ( comment drawing ) + ( comment drawing1 ) + ( comment drawing2 ) ( border drawing ) ( device drawing ) ( device label ) @@ -379,9 +379,9 @@ layerDefinitions( ( align drawing align t t t t nil ) ( hardFence drawing hardFence t t t t nil ) ( softFence drawing softFence t t t t nil ) - ( text drawing text t t t t t ) - ( text drawing1 text1 t t t t nil ) - ( text drawing2 text2 t t t t nil ) + ( comment drawing comment t t t t t ) + ( comment drawing1 comment1 t t t t nil ) + ( comment drawing2 comment2 t t t t nil ) ( border drawing border t t t t nil ) ( device drawing device t t t t nil ) ( device label deviceLbl t t t t nil ) diff --git a/technology/freepdk45/tf/layers.map b/technology/freepdk45/tf/layers.map index 8c0c18d2..1bc4d413 100644 --- a/technology/freepdk45/tf/layers.map +++ b/technology/freepdk45/tf/layers.map @@ -27,4 +27,4 @@ via8 drawing 26 0 metal9 drawing 27 0 via9 drawing 28 0 metal10 drawing 29 0 -text drawing 239 0 +comment drawing 239 0