diff --git a/compiler/base/pin_layout.py b/compiler/base/pin_layout.py index bb65f771..66f61402 100644 --- a/compiler/base/pin_layout.py +++ b/compiler/base/pin_layout.py @@ -54,11 +54,24 @@ class pin_layout: newur = ur + spacing return (newll, newur) - + + def intersection(self, other): + """ Check if a shape overlaps with a rectangle """ + (ll,ur) = self.rect + (oll,our) = other.rect + + min_x = max(ll.x, oll.x) + max_x = min(ll.x, oll.x) + min_y = max(ll.y, oll.y) + max_y = min(ll.y, oll.y) + + return [vector(min_x,min_y),vector(max_x,max_y)] + def overlaps(self, other): """ Check if a shape overlaps with a rectangle """ (ll,ur) = self.rect (oll,our) = other.rect + # Start assuming no overlaps x_overlaps = False y_overlaps = False @@ -77,6 +90,7 @@ class pin_layout: y_overlaps = True return x_overlaps and y_overlaps + def height(self): """ Return height. Abs is for pre-normalized value.""" return abs(self.rect[1].y-self.rect[0].y) diff --git a/compiler/router/router.py b/compiler/router/router.py index 10b4d824..b68b756f 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -43,7 +43,6 @@ class router: # all the paths we've routed so far (to supplement the blockages) self.paths = [] - self.wave_paths = [] # The boundary will determine the limits to the size of the routing grid self.boundary = self.layout.measureBoundary(self.top_name) @@ -562,15 +561,15 @@ class router: # convert the path back to absolute units from tracks abs_path = [self.convert_wave_to_units(i) for i in path] - debug.info(1,str(abs_path)) - if self.is_wave(path): - ur = abs_path[-1][-1] - ll = abs_path[0][0] - self.cell.add_layout_pin(name, - layer=self.get_layer(ll.z), - offset=vector(ll.x,ll.y), - width=ur.x-ll.x, - height=ur.y-ll.y) + #debug.info(1,str(abs_path)) + ur = abs_path[-1][-1] + ll = abs_path[0][0] + pin = self.cell.add_layout_pin(name, + layer=self.get_layer(ll.z), + offset=vector(ll.x,ll.y), + width=ur.x-ll.x, + height=ur.y-ll.y) + return pin def get_inertia(self,p0,p1): diff --git a/compiler/router/supply_grid.py b/compiler/router/supply_grid.py index a3d4cc0d..cee95fac 100644 --- a/compiler/router/supply_grid.py +++ b/compiler/router/supply_grid.py @@ -24,10 +24,10 @@ class supply_grid(grid.grid): p.reset() - def start_wave(self, loc, width): + def find_horizontal_start_wave(self, loc, width): """ Finds the first loc starting at loc and to the right that is open. - Returns false if it reaches max size first. + Returns None if it reaches max size first. """ wave = [loc+vector3d(0,i,0) for i in range(width)] self.width = width @@ -37,13 +37,37 @@ class supply_grid(grid.grid): return None # Increment while the wave is blocked - while self.is_wave_blocked(wave): - # Or until we cannot increment further - if not self.increment_wave(wave): - return None - + if self.is_wave_blocked(wave): + while wave: + wave=self.increment_east_wave(wave) + if not self.is_wave_blocked(wave): + return wave + + # This may return None return wave - + + def find_vertical_start_wave(self, loc, width): + """ + Finds the first loc starting at loc and up that is open. + Returns None if it reaches max size first. + """ + wave = [loc+vector3d(i,0,1) for i in range(width)] + self.width = width + + # Don't expand outside the bounding box + if wave[0].x > self.ur.x: + return None + + # Increment while the wave is blocked + if self.is_wave_blocked(wave): + while wave: + wave=self.increment_up_wave(wave) + if not self.is_wave_blocked(wave): + return wave + + # This may return None + return wave + def is_wave_blocked(self, wave): """ @@ -57,7 +81,7 @@ class supply_grid(grid.grid): - def increment_wave(self, wave): + def increment_east_wave(self, wave): """ Increment the head by moving one step right. Return new wave if successful. @@ -68,11 +92,22 @@ class supply_grid(grid.grid): if new_wave[0].x>self.ur.x: return None - if not self.is_wave_blocked(new_wave): - return new_wave - return None + return new_wave + + def increment_up_wave(self, wave): + """ + Increment the head by moving one step up. Return + new wave if successful. + """ + new_wave = [v+vector3d(0,1,0) for v in wave] + + # Don't expand outside the bounding box + if new_wave[0].y>self.ur.y: + return None - def probe_wave(self, wave): + return new_wave + + def probe_east_wave(self, wave): """ Expand the wave until there is a blockage and return the wave path. @@ -80,7 +115,19 @@ class supply_grid(grid.grid): wave_path = [] while wave and not self.is_wave_blocked(wave): wave_path.append(wave) - wave = self.increment_wave(wave) + wave = self.increment_east_wave(wave) return wave_path - + + def probe_up_wave(self, wave): + """ + Expand the wave until there is a blockage and return + the wave path. + """ + wave_path = [] + while wave and not self.is_wave_blocked(wave): + wave_path.append(wave) + wave = self.increment_up_wave(wave) + + return wave_path + diff --git a/compiler/router/supply_router.py b/compiler/router/supply_router.py index 71e2f240..d9a46767 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_router.py @@ -22,6 +22,7 @@ class supply_router(router): layers for the layers to route on """ router.__init__(self, gds_name, module) + def create_routing_grid(self): """ @@ -89,25 +90,100 @@ class supply_router(router): Add supply rails for vdd and gnd alternating in both layers. Connect cross-over points with vias. """ - # vdd will be the odd grids - vdd_rails = self.route_supply_rail(name="vdd",offset=0,width=2) - - # gnd will be the even grids (0 + width) - gnd_rails = self.route_supply_rail(name="gnd",offset=0,width=2) + # width in grid units + width = 2 + + # List of all the rails + self.rails = [] + self.wave_paths = [] + + # vdd will be the even grids every 2 widths + for offset in range(0, self.rg.ur.y, 2*width): + loc = vector3d(0,offset,0) + # While we can keep expanding east + while loc and loc.x < self.rg.ur.x: + loc = self.route_horizontal_supply_rail("vdd",loc,width) + + # gnd will be the odd grids every 2 widths + for offset in range(width, self.rg.ur.y, 2*width): + loc = vector3d(0,offset,0) + # While we can keep expanding east + while loc and loc.x < self.rg.ur.x: + loc = self.route_horizontal_supply_rail("gnd",loc,width) + + # vdd will be the even grids every 2 widths + for offset in range(0, self.rg.ur.x, 2*width): + loc = vector3d(offset,0,0) + # While we can keep expanding up + while loc and loc.y < self.rg.ur.y: + loc = self.route_vertical_supply_rail("vdd",loc,width) + + # gnd will be the odd grids every 2 widths + for offset in range(width, self.rg.ur.x, 2*width): + loc = vector3d(offset,0,0) + # While we can keep expanding up + while loc and loc.y < self.rg.ur.y: + loc = self.route_vertical_supply_rail("gnd",loc,width) + - pass - def route_supply_rail(self, name, offset=0, width=1): + def route_horizontal_supply_rail(self, name, loc, width): """ Add supply rails alternating layers. + Return the final wavefront for seeding the next wave. """ - wave = self.rg.start_wave(loc=vector3d(0,offset,0), width=width) - wave_path = self.rg.probe_wave(wave) - self.add_wave(name, wave_path) - - - - + # Sweep to find an initial wave + start_wave = self.rg.find_horizontal_start_wave(loc, width) + if not start_wave: + return None + + # Expand the wave to the right + wave_path = self.rg.probe_east_wave(start_wave) + if not wave_path: + return None + + # Filter single unit paths + # FIXME: Should we filter bigger sizes? + if len(wave_path)>1: + new_pin = self.add_wave(name, wave_path) + self.rails.append(new_pin) + self.wave_paths.append(wave_path) + + # seed the next start wave location + wave_end = wave_path[-1] + next_seed = wave_end[0]+vector3d(1,0,0) + return next_seed + + def route_vertical_supply_rail(self, name, loc, width): + """ + Add supply rails alternating layers. + Return the final wavefront for seeding the next wave. + """ + # Sweep to find an initial wave + start_wave = self.rg.find_vertical_start_wave(loc, width) + if not start_wave: + return None + + # Expand the wave to the right + wave_path = self.rg.probe_up_wave(start_wave) + if not wave_path: + return None + + # Filter single unit paths + # FIXME: Should we filter bigger sizes? + if len(wave_path)>1: + new_pin = self.add_wave(name, wave_path) + self.rails.append(new_pin) + self.wave_paths.append(wave_path) + + # seed the next start wave location + wave_end = wave_path[-1] + next_seed = wave_end[0]+vector3d(0,1,0) + return next_seed + + + + def route_supply_pins(self, pin): """ @@ -129,31 +205,31 @@ class supply_router(router): pass - def add_route(self,path): - """ - Add the current wire route to the given design instance. - """ - debug.info(3,"Set path: " + str(path)) + # def add_route(self,path): + # """ + # Add the current wire route to the given design instance. + # """ + # debug.info(3,"Set path: " + str(path)) - # Keep track of path for future blockages - self.paths.append(path) + # # Keep track of path for future blockages + # self.paths.append(path) - # This is marked for debug - self.rg.add_path(path) + # # This is marked for debug + # self.rg.add_path(path) - # For debugging... if the path failed to route. - if False or path==None: - self.write_debug_gds() + # # For debugging... if the path failed to route. + # if False or path==None: + # self.write_debug_gds() - # First, simplify the path for - #debug.info(1,str(self.path)) - contracted_path = self.contract_path(path) - debug.info(1,str(contracted_path)) + # # First, simplify the path for + # #debug.info(1,str(self.path)) + # contracted_path = self.contract_path(path) + # debug.info(1,str(contracted_path)) - # convert the path back to absolute units from tracks - abs_path = map(self.convert_point_to_units,contracted_path) - debug.info(1,str(abs_path)) - self.cell.add_route(self.layers,abs_path) + # # convert the path back to absolute units from tracks + # abs_path = map(self.convert_point_to_units,contracted_path) + # debug.info(1,str(abs_path)) + # self.cell.add_route(self.layers,abs_path)