From 8d2804b9cbd19b9494d39c7adff5dbe51d8cdce7 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 18 Sep 2018 12:57:39 -0700 Subject: [PATCH] Supply router working except: Off grid pins. Some pins do now span enough of the routing track and must be patched. Route track width. Instead of minimum width route, it should be the track width. --- compiler/base/pin_layout.py | 25 ++- compiler/router/grid.py | 6 +- compiler/router/grid_cell.py | 2 - compiler/router/router.py | 209 +++++++++++------- compiler/router/signal_grid.py | 10 +- compiler/router/signal_router.py | 8 +- compiler/router/supply_grid.py | 3 +- compiler/router/supply_router.py | 142 +++++++----- compiler/router/tests/10_supply_grid_test.py | 2 +- compiler/router/tests/config_scn4m_subm.py | 2 +- compiler/verify/magic.py | 6 +- technology/scn4m_subm/tf/display.drf | 3 +- ...ade_scn4me_subm.py => glade_scn4m_subm.py} | 2 +- technology/scn4m_subm/tf/mosis.tf | 9 + 14 files changed, 265 insertions(+), 164 deletions(-) rename technology/scn4m_subm/tf/{glade_scn4me_subm.py => glade_scn4m_subm.py} (64%) diff --git a/compiler/base/pin_layout.py b/compiler/base/pin_layout.py index 66f61402..78b2a7dd 100644 --- a/compiler/base/pin_layout.py +++ b/compiler/base/pin_layout.py @@ -30,9 +30,26 @@ class pin_layout: return "({} layer={} ll={} ur={})".format(self.name,self.layer,self.rect[0],self.rect[1]) def __repr__(self): - """ override print function output """ - return "({} layer={} ll={} ur={})".format(self.name,self.layer,self.rect[0],self.rect[1]) + """ + override repr function output (don't include + name since pin shapes could have same shape but diff name e.g. blockage vs A) + """ + return "(layer={} ll={} ur={})".format(self.layer,self.rect[0],self.rect[1]) + def __hash__(self): + """ Implement the hash function for sets etc. """ + return hash(repr(self)) + + def __lt__(self, other): + """ Provide a function for ordering items by the ll point """ + (ll, ur) = self.rect + (oll, our) = other.rect + + if ll.x < oll.x and ll.y < oll.y: + return True + + return False + def __eq__(self, other): """ Check if these are the same pins for duplicate checks """ if isinstance(other, self.__class__): @@ -71,6 +88,10 @@ class pin_layout: """ Check if a shape overlaps with a rectangle """ (ll,ur) = self.rect (oll,our) = other.rect + + # Can only overlap on the same layer + if self.layer != other.layer: + return False # Start assuming no overlaps x_overlaps = False diff --git a/compiler/router/grid.py b/compiler/router/grid.py index 8f38b7ec..18a51b61 100644 --- a/compiler/router/grid.py +++ b/compiler/router/grid.py @@ -87,15 +87,15 @@ class grid: self.target.append(n) - def add_source(self,track_list): + def add_source(self,track_list,value=True): debug.info(3,"Adding source list={0}".format(str(track_list))) for n in track_list: debug.info(4,"Adding source ={0}".format(str(n))) - self.set_source(n) + self.set_source(n,value) self.set_blocked(n,False) - def set_target(self,track_list,value=True): + def add_target(self,track_list,value=True): debug.info(3,"Adding target list={0}".format(str(track_list))) for n in track_list: debug.info(4,"Adding target ={0}".format(str(n))) diff --git a/compiler/router/grid_cell.py b/compiler/router/grid_cell.py index c0948382..3f145ef4 100644 --- a/compiler/router/grid_cell.py +++ b/compiler/router/grid_cell.py @@ -4,7 +4,6 @@ class grid_cell: visited, etc. """ def __init__(self): - self.visited = False self.path = False self.blocked = False self.source = False @@ -17,7 +16,6 @@ class grid_cell: Reset the dynamic info about routing. The pins/blockages are not reset so that they can be reused. """ - self.visited=False self.min_cost=-1 self.min_path=None self.blocked=False diff --git a/compiler/router/router.py b/compiler/router/router.py index 5b2b845f..1a955318 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -40,18 +40,18 @@ class router: self.pins = {} # A set of connected pin groups self.pin_groups = {} - # The corresponding sets of grids for each pin - self.pin_grids = {} - # The set of partially covered pins to avoid for each pin - self.pin_partials = {} + # The corresponding sets (components) of grids for each pin + self.pin_components = {} # A set of blocked grids self.blocked_grids = set() # A list of pin layout shapes that are blocked self.blockages=[] - # A list of paths that are blocked + # A list of paths that have been "routed" self.paths = [] + # The list of supply rails that may be routed + self.supply_rails = [] # The boundary will determine the limits to the size of the routing grid self.boundary = self.layout.measureBoundary(self.top_name) @@ -134,16 +134,16 @@ class router: Retrieve the pin shapes from the layout. """ shape_list=self.layout.getAllPinShapesByLabel(str(pin_name)) - pin_list = [] + pin_set = set() for shape in shape_list: (name,layer,boundary)=shape rect = [vector(boundary[0],boundary[1]),vector(boundary[2],boundary[3])] pin = pin_layout(pin_name, rect, layer) debug.info(2,"Found pin {}".format(str(pin))) - pin_list.append(pin) + pin_set.add(pin) - debug.check(len(pin_list)>0,"Did not find any pin shapes for {0}.".format(str(pin))) - self.pins[pin_name] = pin_list + debug.check(len(pin_set)>0,"Did not find any pin shapes for {0}.".format(str(pin_name))) + self.pins[pin_name] = pin_set def find_pins(self,pin_name): """ @@ -175,8 +175,7 @@ class router: """ self.pins = {} self.pin_groups = {} - self.pin_grids = {} - self.pin_partials = {} + self.pin_components = {} # DO NOT clear the blockages as these don't change self.rg.reinit() @@ -409,7 +408,7 @@ class router: track in the track and leaves half a DRC space in each direction. """ # space depends on which layer it is - if track[2]==0: + if self.get_layer(track[2])==self.horiz_layer_name: space = 0.5*self.horiz_layer_spacing else: space = 0.5*self.vert_layer_spacing @@ -444,34 +443,40 @@ class router: """ Analyze the shapes of a pin and combine them into groups which are connected. """ - pin_list = self.pins[pin_name] - + pin_set = self.pins[pin_name] + local_debug=False # Put each pin in an equivalence class of it's own - equiv_classes = [[x] for x in pin_list] - #print("INITIAL\n",equiv_classes) + equiv_classes = [set([x]) for x in pin_set] + if local_debug: + print("INITIAL\n",equiv_classes) def compare_classes(class1, class2): """ Determine if two classes should be combined and if so return the combined set. Otherwise, return None. """ - #print("CL1:\n",class1) - #print("CL2:\n",class2) + if local_debug: + print("CLASS1:\n",class1) + print("CLASS2:\n",class2) # Compare each pin in each class, # and if any overlap, return the combined the class for p1 in class1: for p2 in class2: if p1.overlaps(p2): - combined_class = class1+class2 - #print("COM:",pformat(combined_class)) + combined_class = class1 | class2 + if local_debug: + print("COMBINE:",pformat(combined_class)) return combined_class - + + if local_debug: + print("NO COMBINE") return None def combine_classes(equiv_classes): """ Recursive function to combine classes. """ - #print("\nRECURSE:\n",pformat(equiv_classes)) + if local_debug: + print("\nRECURSE:\n",pformat(equiv_classes)) if len(equiv_classes)==1: return(equiv_classes) @@ -490,111 +495,128 @@ class router: return(equiv_classes) reduced_classes = combine_classes(equiv_classes) - #print("FINAL ",reduced_classes) - self.pin_groups[pin_name] = reduced_classes + if local_debug: + print("FINAL ",reduced_classes) + self.pin_groups[pin_name]=reduced_classes def convert_pins(self, pin_name): """ Convert the pin groups into pin tracks and blockage tracks """ try: - self.pin_grids[pin_name] + self.pin_components[pin_name] except: - self.pin_grids[pin_name] = [] - try: - self.pin_partials[pin_name] - except: - self.pin_partials[pin_name] = [] + self.pin_components[pin_name] = [] found_pin = False for pg in self.pin_groups[pin_name]: + print("PG ",pg) # Keep the same groups for each pin - self.pin_grids[pin_name].append(set()) - self.pin_partials[pin_name].append(set()) - pin_set = set() - partial_set = set() + blockage_set = set() for pin in pg: - debug.info(2,"Converting {0}".format(pin)) + debug.info(2," Converting {0}".format(pin)) (pin_in_tracks,partial_in_tracks)=self.convert_pin_to_tracks(pin) - # In the blockages, what did this shape expand as? blockage_in_tracks = self.convert_blockage(pin) - # At least one of the groups must have some valid tracks - if (len(pin_in_tracks)>0): - found_pin = True pin_set.update(pin_in_tracks) - partial_set.update(partial_in_tracks) - partial_set.update(blockage_in_tracks) + pin_set.update(partial_in_tracks) + + blockage_set.update(blockage_in_tracks) - debug.info(2," grids {}".format(pin_set)) - debug.info(2," parts {}".format(partial_set)) + debug.info(2," pins {}".format(pin_set)) + debug.info(2," blocks {}".format(blockage_set)) - # We can just block all of the partials, so combine the groups - self.pin_partials[pin_name][-1].add(frozenset(partial_set)) - # We need to route each of the classes, so don't combine the groups - self.pin_grids[pin_name][-1].add(frozenset(pin_set)) - - # This happens when a shape is covered partially by one shape and fully by another - self.pin_partials[pin_name][-1].difference_update(pin_set) + # At least one of the groups must have some valid tracks + if (len(pin_set) == 0): + self.write_debug_gds() + debug.error("Unable to find pin on grid.",-1) + + # We need to route each of the components, so don't combine the groups + self.pin_components[pin_name].append(pin_set) - # These will be blocked depending on what we are routing + # Add all of the blocked grids to the set for the design + self.blocked_grids.update(blockage_set) + + # Remove the pins from the blockages since we didn't know + # they were pins when processing blockages self.blocked_grids.difference_update(pin_set) - self.blocked_grids.difference_update(partial_set) - if not found_pin: - self.write_debug_gds() - debug.error("Unable to find pin on grid.",-1) - def add_pin(self, pin_name, is_source=False): + def add_source(self, pin_name): """ - This will mark the grids for all pin components as a source or a target. + This will mark the grids for all pin components as a source. Marking as source or target also clears blockage status. """ for i in range(self.num_pin_components(pin_name)): - self.add_pin_component(pin_name, i, is_source) + self.add_pin_component_source(pin_name, i) + def add_target(self, pin_name): + """ + This will mark the grids for all pin components as a target. + Marking as source or target also clears blockage status. + """ + for i in range(self.num_pin_components(pin_name)): + self.add_pin_component_target(pin_name, i) + def num_pin_components(self, pin_name): """ This returns how many disconnected pin components there are. """ - debug.check(len(self.pin_grids[pin_name]) == len(self.pin_partials[pin_name]), - "Pin grid and partial blockage component sizes don't match.") - return len(self.pin_grids[pin_name]) + return len(self.pin_components[pin_name]) - def add_pin_component(self, pin_name, index, is_source=False): + def add_pin_component_source(self, pin_name, index): """ - This will mark only the pin tracks from the indexed pin component as a source/target. + This will mark only the pin tracks from the indexed pin component as a source. It also unsets it as a blockage. """ debug.check(index1: + self.cell.add_route(self.layers,abs_path) + self.add_enclosure(abs_path[-1]) + + def add_enclosure(self, loc): + """ + Add a metal enclosure that is the size of the routing grid minus a spacing on each side. + """ + (ll,ur) = self.convert_track_to_pin(loc) + self.cell.add_rect_center(layer=self.get_layer(loc.z), + offset=vector(loc.x,loc.y), + width=ur.x-ll.x, + height=ur.y-ll.y) + + + def add_via(self,loc,size=1): """ Add a via centered at the current location @@ -761,8 +800,9 @@ class router: if prev_inertia!=next_inertia: newpath.append(path[i]) - # always add the last path - newpath.append(path[-1]) + # always add the last path unless it was a single point + if len(path)>1: + newpath.append(path[-1]) return newpath @@ -783,6 +823,7 @@ class router: if path: debug.info(1,"Found path: cost={0} ".format(cost)) debug.info(2,str(path)) + self.paths.append(path) self.add_route(path) else: self.write_debug_gds() diff --git a/compiler/router/signal_grid.py b/compiler/router/signal_grid.py index d5d38bcb..5c88d74d 100644 --- a/compiler/router/signal_grid.py +++ b/compiler/router/signal_grid.py @@ -64,15 +64,21 @@ class signal_grid(grid): # over-ridden if the route fails due to pruning a feasible solution. cost_bound = detour_scale*self.cost_to_target(self.source[0])*grid.PREFERRED_COST + # Check if something in the queue is already a source and a target! + for s in self.source: + if self.is_target(s): + return((grid_path([vector3d(s)]),0)) + # Make sure the queue is empty if we run another route while len(self.q)>0: heappop(self.q) - + # Put the source items into the queue self.init_queue() cheapest_path = None cheapest_cost = None - + + # Keep expanding and adding to the priority queue until we are done while len(self.q)>0: # should we keep the path in the queue as well or just the final node? diff --git a/compiler/router/signal_router.py b/compiler/router/signal_router.py index 7acc61a1..664f8305 100644 --- a/compiler/router/signal_router.py +++ b/compiler/router/signal_router.py @@ -67,16 +67,16 @@ class signal_router(router): # Now add the blockages self.set_blockages(self.blocked_grids,True) - self.set_blockages(self.pin_partial[src],True) - self.set_blockages(self.pin_partial[dest],True) + #self.set_blockages(self.pin_partials[src],True) + #self.set_blockages(self.pin_partials[dest],True) # Add blockages from previous paths self.set_path_blockages() # Now add the src/tgt if they are not blocked by other shapes - self.add_pin(src,True) - self.add_pin(dest,False) + self.add_source(src) + self.add_target(dest) if not self.run_router(detour_scale): return False diff --git a/compiler/router/supply_grid.py b/compiler/router/supply_grid.py index c584e5ae..bd9dab87 100644 --- a/compiler/router/supply_grid.py +++ b/compiler/router/supply_grid.py @@ -20,7 +20,8 @@ class supply_grid(signal_grid): def reinit(self): """ Reinitialize everything for a new route. """ - + self.source = [] + self.target = [] # Reset all the cells in the map for p in self.map.values(): p.reset() diff --git a/compiler/router/supply_router.py b/compiler/router/supply_router.py index 28ecc044..37b9ff76 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_router.py @@ -65,21 +65,29 @@ class supply_router(router): self.find_pins(self.gnd_name) # Add the supply rails in a mesh network and connect H/V with vias - self.prepare_blockages(block_names=[self.vdd_name],unblock_names=[self.gnd_name]) + # Block everything + self.prepare_blockages() + # Clear the rail we're routing + self.set_blockages(self.pin_components[self.gnd_name],False) + # Determine the rail locations self.route_supply_rails(self.gnd_name,0) - self.prepare_blockages(block_names=[self.gnd_name],unblock_names=[self.vdd_name]) + # Block everything + self.prepare_blockages() + # Clear the rail we're routing + self.set_blockages(self.pin_components[self.vdd_name],False) + # Determine the rail locations self.route_supply_rails(self.vdd_name,1) # Route the supply pins to the supply rails - #self.route_pins_to_rails(gnd_name) - #self.route_pins_to_rails(vdd_name) + self.route_pins_to_rails(gnd_name) + self.route_pins_to_rails(vdd_name) self.write_debug_gds() - return False + return True - def prepare_blockages(self, block_names=None, unblock_names=None): + def prepare_blockages(self): """ Reset and add all of the blockages in the design. Names is a list of pins to add as a blockage. @@ -87,55 +95,72 @@ class supply_router(router): # Start fresh. Not the best for run-time, but simpler. self.clear_blockages() # This adds the initial blockges of the design - print("BLOCKING:",self.blocked_grids) + #print("BLOCKING:",self.blocked_grids) self.set_blockages(self.blocked_grids,True) - # This is conservative to prevent DRC violations on partially blocked tracks - if block_names: - for name in block_names: - # These are the partially blocked tracks around supply pins. - print("BLOCKING PARTIALS:",name,self.pin_partials[name]) - self.set_blockages(self.pin_partials[name],True) - # These are the actual supply pins - self.set_blockages(self.pin_grids[name],True) - print("BLOCKING GRIDS:",name,self.pin_grids[name]) - # This will unblock - if unblock_names: - for name in unblock_names: - # These are the partially blocked tracks around supply pins. - self.set_blockages(self.pin_partials[name],False) - print("UNBLOCKING PARTIALS:",name,self.pin_partials[name]) - # These are the actual supply pins - self.set_blockages(self.pin_grids[name],False) - print("UNBLOCKING GRIDS:",name,self.pin_grids[name]) - + + # Block all of the supply rails (some will be unblocked if they're a target) + 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_components.keys(): + self.set_blockages(self.pin_components[name],True) + # These are the paths that have already been routed. self.set_path_blockages() def connect_supply_rails(self, name): """ - Add vias between overlapping supply rails. + Determine which supply rails overlap and can accomodate a via. + Remove any paths that do not have a via since they are disconnected. """ - paths = [x for x in self.paths if x.name == name] - + # Split into horizontal and vertical - vertical_paths = [x for x in paths if x[0][0].z==1] - horizontal_paths = [x for x in paths if x[0][0].z==0] - - shared_areas = [] - for v in vertical_paths: - for h in horizontal_paths: + vertical_paths = [(i,x) for i,x in enumerate(self.supply_rails) if x[0][0].z==1 and x.name==name] + horizontal_paths = [(i,x) for i,x in enumerate(self.supply_rails) if x[0][0].z==0 and x.name==name] + + # Flag to see if the paths have a via + via_flag = [False] * len(self.supply_rails) + # Ignore the other nets that we aren't considering + for i,p in enumerate(self.supply_rails): + if p.name != name: + via_flag[i]=True + + # Compute a list of "shared areas" that are bigger than a via + via_areas = [] + for vindex,v in vertical_paths: + for hindex,h in horizontal_paths: + # Compute the overlap of the two paths, None if no overlap overlap = v.overlap(h) if overlap: (ll,ur) = overlap - # Only add if the overlap is wide enough + # We can add a via only if it is a full track width in each dimension if ur.x-ll.x >= self.rail_track_width-1 and ur.y-ll.y >= self.rail_track_width-1: - shared_areas.append(overlap) + via_flag[vindex]=True + via_flag[hindex]=True + via_areas.append(overlap) - for (ll,ur) in shared_areas: + # Go through and add the vias at the center of the intersection + for (ll,ur) in via_areas: center = (ll + ur).scale(0.5,0.5,0) self.add_via(center,self.rail_track_width) + + # Remove the paths that have not been connected by any via + remove_indices = [i for i,x in enumerate(via_flag) if not x] + for index in remove_indices: + debug.info(1,"Removing disconnected supply rail {}".format(self.supply_rails[index])) + del self.supply_rails[index] + def add_supply_rails(self, name): + """ + Add the shapes that represent the routed supply rails. + This is after the paths have been pruned and only include rails that are + connected with vias. + """ + for wave_path in self.supply_rails: + if wave_path.name == name: + self.add_wavepath(name, wave_path) + def route_supply_rails(self, name, supply_number): @@ -154,7 +179,7 @@ class supply_router(router): wave = [vector3d(0,offset+i,0) for i in range(self.rail_track_width)] # While we can keep expanding east in this horizontal track while wave and wave[0].x < max_xoffset: - wave = self.route_supply_rail(name, wave, direction.EAST) + wave = self.find_supply_rail(name, wave, direction.EAST) # Vertical supply rails @@ -164,16 +189,14 @@ class supply_router(router): wave = [vector3d(offset+i,0,1) for i in range(self.rail_track_width)] # While we can keep expanding north in this vertical track while wave and wave[0].y < max_yoffset: - wave = self.route_supply_rail(name, wave, direction.NORTH) + wave = self.find_supply_rail(name, wave, direction.NORTH) - # Remember index of path size which is how many rails we had at the start - self.num_rails = len(self.paths) - - # Add teh supply rail vias + # Add the supply rail vias (and prune disconnected rails) self.connect_supply_rails(name) + # Add the rails themselves + self.add_supply_rails(name) - - def route_supply_rail(self, name, seed_wave, direct): + def find_supply_rail(self, name, seed_wave, direct): """ This finds the first valid starting location and routes a supply rail in the given direction. @@ -191,12 +214,9 @@ class supply_router(router): if not wave_path: return None - # Filter any path that won't span 2 rails - # so that we can guarantee it is connected if len(wave_path)>=2*self.rail_track_width: - self.add_wavepath(name, wave_path) wave_path.name = name - self.paths.append(wave_path) + self.supply_rails.append(wave_path) # seed the next start wave location wave_end = wave_path[-1] @@ -206,26 +226,27 @@ class supply_router(router): - def route_pins_to_rails(self,pin_name): + def route_pins_to_rails(self, pin_name): """ This will route each of the pin components to the supply rails. After it is done, the cells are added to the pin blockage list. """ + + num_components = self.num_pin_components(pin_name) + debug.info(0,"Pin {0} has {1} components to route.".format(pin_name, num_components)) # For every component - for index in range(self.num_pin_components(pin_name)): + for index in range(num_components): + debug.info(0,"Routing component {0} {1}".format(pin_name, index)) self.rg.reinit() - self.prepare_blockages(block_names=None,unblock_names=[pin_name]) - - # Block all the pin components first - self.set_component_blockages(pin_name, True) - + self.prepare_blockages() + # Add the single component of the pin as the source # which unmarks it as a blockage too - self.add_pin_component(pin_name,index,is_source=True) + self.add_pin_component_source(pin_name,index) # Add all of the rails as targets # Don't add the other pins, but we could? @@ -234,7 +255,10 @@ class supply_router(router): # Actually run the A* router self.run_router(detour_scale=5) - + #if index==1: + # self.write_debug_gds() + # import sys + # sys.exit(1) diff --git a/compiler/router/tests/10_supply_grid_test.py b/compiler/router/tests/10_supply_grid_test.py index 2fa5cb7b..792e6956 100755 --- a/compiler/router/tests/10_supply_grid_test.py +++ b/compiler/router/tests/10_supply_grid_test.py @@ -42,7 +42,7 @@ class no_blockages_test(openram_test): self.connect_inst(cell.pin_map.keys()) r=router(module=cell) - layer_stack =("metal3","via2","metal2") + layer_stack =("metal3","via3","metal4") self.assertTrue(r.route(self,layer_stack)) r=routing("10_supply_grid_test_{0}".format(OPTS.tech_name)) diff --git a/compiler/router/tests/config_scn4m_subm.py b/compiler/router/tests/config_scn4m_subm.py index 40addd69..ca112a97 100755 --- a/compiler/router/tests/config_scn4m_subm.py +++ b/compiler/router/tests/config_scn4m_subm.py @@ -2,7 +2,7 @@ word_size = 1 num_words = 16 num_banks = 1 -tech_name = "scn3me_subm" +tech_name = "scn4m_subm" process_corners = ["TT"] supply_voltages = [5.0] temperatures = [25] diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 0cb93582..55e803b4 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -43,9 +43,9 @@ def write_magic_script(cell_name, gds_name, extract=False): # (e.g. with routes) f.write("flatten {}_new\n".format(cell_name)) f.write("load {}_new\n".format(cell_name)) - #f.write("cellname rename {0}_new {0}\n".format(cell_name)) - #f.write("load {}\n".format(cell_name)) - f.write("writeall force {0}_new\n".format(cell_name)) + f.write("cellname rename {0}_new {0}\n".format(cell_name)) + f.write("load {}\n".format(cell_name)) + f.write("writeall force\n") f.write("drc check\n") f.write("drc catchup\n") f.write("drc count total\n") diff --git a/technology/scn4m_subm/tf/display.drf b/technology/scn4m_subm/tf/display.drf index aeeefe2c..39349998 100644 --- a/technology/scn4m_subm/tf/display.drf +++ b/technology/scn4m_subm/tf/display.drf @@ -546,7 +546,7 @@ drDefinePacket( ( display background stipple1 lineStyle0 black black outlineStipple) ( display y9 stipple0 solid silver silver solid ) ( display Metal3Net dots4 solid navy navy outlineStipple) - ( display Metal3Net dots4 solid tan tan outlineStipple) + ( display Metal4Net dots4 solid tan tan outlineStipple) ( display A1 stipple0 lineStyle0 winBack winBack solid ) ( display pin solid lineStyle0 red red solid ) ( display XPNet blank solid yellow yellow outline ) @@ -640,6 +640,7 @@ drDefinePacket( ( display Canplace blank solid cyan cyan outline ) ( display annotate7 stipple0 solid red red solid ) ( display Via2 solid solid navy navy solid ) + ( display Via3 solid solid tan tan solid ) ( display Metal2Pin stipple0 lineStyle0 magenta magenta solid ) ( display annotate4 stipple0 solid yellow yellow solid ) ( display device1 stipple1 lineStyle0 green green outlineStipple) diff --git a/technology/scn4m_subm/tf/glade_scn4me_subm.py b/technology/scn4m_subm/tf/glade_scn4m_subm.py similarity index 64% rename from technology/scn4m_subm/tf/glade_scn4me_subm.py rename to technology/scn4m_subm/tf/glade_scn4m_subm.py index d2f9aa7e..314727c3 100644 --- a/technology/scn4m_subm/tf/glade_scn4me_subm.py +++ b/technology/scn4m_subm/tf/glade_scn4m_subm.py @@ -1,5 +1,5 @@ import os -CWD = os.environ.get("OPENRAM_TECH") + "/scn3me_subm/tf" +CWD = os.environ.get("OPENRAM_TECH") + "/scn4m_subm/tf" ui().importCds("default", CWD+"/display.drf", CWD+"/mosis.tf", 1000, 1, CWD+"/layers.map") diff --git a/technology/scn4m_subm/tf/mosis.tf b/technology/scn4m_subm/tf/mosis.tf index e48d76a0..bae7f07a 100644 --- a/technology/scn4m_subm/tf/mosis.tf +++ b/technology/scn4m_subm/tf/mosis.tf @@ -147,6 +147,8 @@ layerDefinitions( ( Metal2 drawing ) ( Via2 drawing ) ( Metal3 drawing ) + ( Via3 drawing ) + ( Metal4 drawing ) ( annotate drawing ) ( annotate drawing1 ) ( annotate drawing2 ) @@ -161,6 +163,7 @@ layerDefinitions( ( Metal1 pin ) ( Metal2 pin ) ( Metal3 pin ) + ( Metal4 pin ) ( Glass drawing ) ( XP drawing ) ( prBoundary drawing ) @@ -203,6 +206,8 @@ layerDefinitions( ( Via net ) ( Metal3 net ) ( Via2 net ) + ( Metal4 net ) + ( Via3 net ) ( pin label ) ( text drawing ) ( pin drawing ) @@ -313,11 +318,14 @@ layerDefinitions( ( annotate drawing9 annotate9 t t nil t nil ) ( Via2 drawing Via2 t t t t t ) ( Metal3 drawing Metal3 t t t t t ) + ( Via3 drawing Via3 t t t t t ) + ( Metal4 drawing Metal4 t t t t t ) ( Glass drawing Glass t t t nil t ) ( XP drawing XP t t t nil t ) ( Metal1 pin Metal1Pin t t t nil t ) ( Metal2 pin Metal2Pin t t t nil t ) ( Metal3 pin Metal3Pin t t t nil t ) + ( Metal4 pin Metal4Pin t t t nil t ) ( Poly1 pin Poly1Pin t t t nil t ) ( prBoundary drawing prBoundary t t nil t nil ) ( prBoundary boundary prBoundaryBnd t t nil t nil ) @@ -356,6 +364,7 @@ layerDefinitions( ( device annotate deviceAnt t t t t nil ) ( Metal2 net Metal2Net t t t nil nil ) ( Metal3 net Metal3Net t t t nil nil ) + ( Metal4 net Metal4Net t t t nil nil ) ( device label deviceLbl t t t t nil ) ( Via net ViaNet t t t nil nil ) ( Via2 net Via2Net t t t nil nil )