Source code for ACG.Track

from ACG.XY import XY
from typing import Dict, TYPE_CHECKING
if TYPE_CHECKING:
    from bag.layout.routing.grid import RoutingGrid


[docs]class TrackManager: """ A class that enables users to create tracks and use them as references for routing """ def __init__(self): self.tracks: Dict[Track] = {} def __getitem__(self, item) -> 'Track': """ Use dictionary syntax to access a specific track instance """ return self.tracks[item] def __str__(self): track_str = "" for name, track in self.tracks.items(): track_str += str(name) + ' ' + str(track) return track_str
[docs] @classmethod def from_routing_grid(cls, grid: 'RoutingGrid'): """ Generates a track manager object from the current grid Parameters ---------- grid RoutingGrid object used as reference to build all of the desired tracks Returns ------- TrackManager Generated TrackManager object from the provided RoutingGrid """ track_manager = cls() for layer_id in grid.sp_tracks: name = grid.tech_info.get_layer_name(layer_id) spacing = grid.sp_tracks[layer_id] * grid.resolution dim = grid.dir_tracks[layer_id] track_manager.add_track(name=name, dim=dim, spacing=spacing) return track_manager
[docs] def add_track(self, name, dim, spacing, origin=0): """ Adds a track to the database. Parameters ---------- name name to associate with the added track dim 'x' or 'y' for the desired routing direction spacing space between tracks origin coordinate to place the zero track """ if name in self.tracks: raise ValueError(f"Track {name} already exists in the db") else: self.tracks[name] = Track(dim=dim, spacing=spacing, origin=origin)
[docs]class Track: """ A class for creating consistently spaced reference lines """ def __init__(self, dim, spacing, origin=0): """ dim: str x or y. Refers to the direction that the tracks span spacing: float the amount of space between any two tracks origin: float the single x or y coordinate that determines the location of Track.get_track(0) """ # Init local property variables self._dim = None self._spacing = None self._origin = None self._res = .001 # Store provided params with property setters self.dim = dim # refers to the direction that the tracks span self.origin = origin # coordinate of track 0 self.spacing = spacing # distance between tracks """ Magic Methods """ def __call__(self, num): return self.get_track(num) def __str__(self): return f"Track:\n\tdim: {self.dim}\n\tspacing: {self.spacing}\n" """ Properties """ @property def dim(self): return self._dim @dim.setter def dim(self, direction): if direction is 'x': self._dim = 'x' elif direction is 'y': self._dim = 'y' else: raise ValueError('Provided direction is invalid, must be x or y') @property def spacing(self): return self._spacing * self._res @spacing.setter def spacing(self, value): temp = round(value / self._res) # Find location of provided spacing on grid self._spacing = int(temp) # Force the coordinate to be an int @property def origin(self): return self._origin * self._res @origin.setter def origin(self, value): temp = round(value / self._res) # Find location of provided spacing on grid self._origin = int(temp) # Force the coordinate to be an int """ Utility Methods """
[docs] def get_track(self, num) -> XY: """ Returns [x, y] coordinates of desired track # """ distance = self.spacing * num if self.dim is 'x': return XY([self.origin + distance, 0]) elif self.dim is 'y': return XY([0, self.origin + distance])
[docs] def align(self, ref_rect, ref_handle, num=0, offset=0): """ Aligns the provided track number to handle of reference rectangle """ ref_loc = ref_rect.loc[ref_handle] # grab coordinates of reference location curr_loc = self.get_track(num) # grab coordinates of track location if self.dim is 'x': diff_x = curr_loc.x - ref_loc.x - offset # calculate x dimension difference self.origin -= diff_x elif self.dim is 'y': diff_y = curr_loc.y - ref_loc.x - offset # calculate y dimension difference self.origin -= diff_y
[docs] def stretch(self, track_num, ref_rect, ref_handle, offset=0): """ Stretches the track spacing to co-locate track and handle """ ref_loc = ref_rect[ref_handle] curr_loc = self.get_track(track_num) if self.dim is 'x': diff_x = curr_loc.x - ref_loc.x - offset self.spacing -= diff_x elif self.dim is 'y': diff_y = curr_loc.y - ref_loc.y - offset self.spacing -= diff_y