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.
This commit is contained in:
Matt Guthaus 2018-09-18 12:57:39 -07:00
parent bfc8428df7
commit 8d2804b9cb
14 changed files with 265 additions and 164 deletions

View File

@ -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

View File

@ -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)))

View File

@ -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

View File

@ -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(index<self.num_pin_components(pin_name),"Pin component index too large.")
pin_in_tracks = self.pin_grids[pin_name][index]
if is_source:
debug.info(1,"Set source: " + str(pin_name) + " " + str(pin_in_tracks))
self.rg.add_source(pin_in_tracks)
else:
debug.info(1,"Set target: " + str(pin_name) + " " + str(pin_in_tracks))
self.rg.add_target(pin_in_tracks)
pin_in_tracks = self.pin_components[pin_name][index]
debug.info(1,"Set source: " + str(pin_name) + " " + str(pin_in_tracks))
self.rg.add_source(pin_in_tracks)
def add_pin_component_target(self, pin_name, index):
"""
This will mark only the pin tracks from the indexed pin component as a target.
It also unsets it as a blockage.
"""
debug.check(index<self.num_pin_components(pin_name),"Pin component index too large.")
pin_in_tracks = self.pin_components[pin_name][index]
debug.info(1,"Set target: " + str(pin_name) + " " + str(pin_in_tracks))
self.rg.add_target(pin_in_tracks)
def add_supply_rail_target(self, pin_name):
"""
Add the supply rails of given name as a routing target.
"""
for i in range(self.num_rails):
if self.paths[i].name == pin_name:
rail = self.paths[i]
for wave_index in range(len(rail)):
pin_in_tracks = rail[wave_index]
#debug.info(1,"Set target: " + str(pin_name) + " " + str(pin_in_tracks))
self.rg.set_target(pin_in_tracks)
for rail in self.supply_rails:
if rail.name != pin_name:
continue
for wave_index in range(len(rail)):
pin_in_tracks = rail[wave_index]
#debug.info(1,"Set target: " + str(pin_name) + " " + str(pin_in_tracks))
self.rg.set_target(pin_in_tracks)
self.rg.set_blocked(pin_in_tracks,False)
def set_supply_rail_blocked(self, value=True):
"""
Add the supply rails of given name as a routing target.
"""
for rail in self.supply_rails:
for wave_index in range(len(rail)):
pin_in_tracks = rail[wave_index]
#debug.info(1,"Set target: " + str(pin_name) + " " + str(pin_in_tracks))
self.rg.set_blocked(pin_in_tracks,value)
def set_component_blockages(self, pin_name, value=True):
"""
Block all of the pin components.
"""
for component in self.pin_grids[pin_name]:
for component in self.pin_components[pin_name]:
self.set_blockages(component, value)
@ -671,8 +693,7 @@ class router:
debug.info(4,"Set path: " + str(path))
# Keep track of path for future blockages
self.paths.append(path)
path.set_blocked()
#path.set_blocked()
# This is marked for debug
path.set_path()
@ -699,8 +720,26 @@ class router:
# This assumes 1-track wide again
abs_path = [self.convert_point_to_units(x[0]) for x in path]
debug.info(1,str(abs_path))
self.cell.add_route(self.layers,abs_path)
# If we had a single grid route (source was equal to target)
self.add_enclosure(abs_path[0])
# Otherwise, add teh route and final enclosure
if len(abs_path)>1:
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()

View File

@ -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?

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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))

View File

@ -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]

View File

@ -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")

View File

@ -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)

View File

@ -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")

View File

@ -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 )