From 82a09be026be5382bac6fc4b8d027be4f75750df Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 30 Jan 2019 08:42:25 -0800 Subject: [PATCH 1/7] Move inspect into if statement for runtime --- compiler/debug.py | 4 ++-- compiler/example_configs/big_config_scn4m_subm.py | 2 +- compiler/run_profile.sh | 2 +- compiler/view_profile.py | 8 +++++--- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/debug.py b/compiler/debug.py index 271b874b..e6c6a1bd 100644 --- a/compiler/debug.py +++ b/compiler/debug.py @@ -11,9 +11,9 @@ import sys def check(check, str): - (frame, filename, line_number, function_name, lines, - index) = inspect.getouterframes(inspect.currentframe())[1] if not check: + (frame, filename, line_number, function_name, lines, + index) = inspect.getouterframes(inspect.currentframe())[1] sys.stderr.write("ERROR: file {0}: line {1}: {2}\n".format( os.path.basename(filename), line_number, str)) log("ERROR: file {0}: line {1}: {2}\n".format( diff --git a/compiler/example_configs/big_config_scn4m_subm.py b/compiler/example_configs/big_config_scn4m_subm.py index 0f71169b..4fa4de8d 100644 --- a/compiler/example_configs/big_config_scn4m_subm.py +++ b/compiler/example_configs/big_config_scn4m_subm.py @@ -1,4 +1,4 @@ -word_size = 8 +word_size = 32 num_words = 128 tech_name = "scn4m_subm" diff --git a/compiler/run_profile.sh b/compiler/run_profile.sh index 1b8df3ae..37a130a4 100755 --- a/compiler/run_profile.sh +++ b/compiler/run_profile.sh @@ -1,3 +1,3 @@ #!/bin/bash -python3 -m cProfile -o profile.dat ./openram.py example_config_scn4m_subm.py -v +python3 -m cProfile -o profile.dat ./openram.py example_configs/medium_config_scn4m_subm.py -v | tee -i medium.log echo "Run view_profile.py to view results" diff --git a/compiler/view_profile.py b/compiler/view_profile.py index 5a522b8a..cb5a0cfd 100755 --- a/compiler/view_profile.py +++ b/compiler/view_profile.py @@ -1,6 +1,8 @@ +#!/usr/bin/env python3 import pstats -p = pstats.Stats(‘profile.dat’) +p = pstats.Stats("profile.dat") p.strip_dirs() -p.sort_stats(‘cumulative’) -p.print_stats(50) +p.sort_stats("cumulative") +#p.print_stats(50) +p.print_stats() From aaf028cacf2e2418cd9a2c9f966d5b2f26de12fa Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 30 Jan 2019 08:49:47 -0800 Subject: [PATCH 2/7] Optimize hpwl runtime. Fix error in via cost when L shape. --- compiler/router/signal_grid.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/router/signal_grid.py b/compiler/router/signal_grid.py index 0f8d6315..2cee04a1 100644 --- a/compiler/router/signal_grid.py +++ b/compiler/router/signal_grid.py @@ -142,10 +142,9 @@ class signal_grid(grid): Either point can have positive or negative coordinates. Include the via penalty if there is one. """ - hpwl = max(abs(src.x-dest.x),abs(dest.x-src.x)) - hpwl += max(abs(src.y-dest.y),abs(dest.y-src.y)) - hpwl += max(abs(src.z-dest.z),abs(dest.z-src.z)) - if src.x!=dest.x or src.y!=dest.y: + hpwl = abs(src.x-dest.x) + hpwl += abs(src.y-dest.y) + if src.x!=dest.x and src.y!=dest.y: hpwl += grid.VIA_COST return hpwl From 7836929db268f27d3e3502c39f44e631f992e268 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 30 Jan 2019 10:03:07 -0800 Subject: [PATCH 3/7] Use hash of tuples instead of checking rectangle in list --- compiler/gdsMill/gdsMill/vlsiLayout.py | 31 +++++++++----------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/compiler/gdsMill/gdsMill/vlsiLayout.py b/compiler/gdsMill/gdsMill/vlsiLayout.py index 8d4816f6..626ea501 100644 --- a/compiler/gdsMill/gdsMill/vlsiLayout.py +++ b/compiler/gdsMill/gdsMill/vlsiLayout.py @@ -732,25 +732,18 @@ class VlsiLayout: Return all gshapes on a given layer in [llx, lly, urx, ury] format and user units. """ - boundaries = [] + boundaries = set() for TreeUnit in self.xyTree: #print(TreeUnit[0]) - boundaries.extend(self.getShapesInStructure(layer,TreeUnit)) + boundaries.update(self.getShapesInStructure(layer,TreeUnit)) - # Remove duplicates without defining a hash - # (could be sped up by creating hash and using list(set()) - new_boundaries = [] - for boundary in boundaries: - if boundary not in new_boundaries: - new_boundaries.append(boundary) - # Convert to user units - boundaries = [] - for boundary in new_boundaries: - boundaries.append([boundary[0]*self.units[0],boundary[1]*self.units[0], - boundary[2]*self.units[0],boundary[3]*self.units[0]]) + user_boundaries = [] + for boundary in boundaries: + user_boundaries.append([boundary[0]*self.units[0],boundary[1]*self.units[0], + boundary[2]*self.units[0],boundary[3]*self.units[0]]) - return boundaries + return user_boundaries def getShapesInStructure(self,layer,structure): @@ -764,9 +757,7 @@ class VlsiLayout: boundaries = [] for boundary in self.structures[str(structureName)].boundaries: # FIXME: Right now, this only supports rectangular shapes! - #debug.check(len(boundary.coordinates)==5,"Non-rectangular shape.") - if len(boundary.coordinates)!=5: - continue + debug.check(len(boundary.coordinates)==5,"Non-rectangular shapes are not supported.") if layer==boundary.drawingLayer: left_bottom=boundary.coordinates[0] right_top=boundary.coordinates[2] @@ -774,9 +765,9 @@ class VlsiLayout: boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]] # perform the rotation boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector) - # add the offset - boundaryRect=[boundaryRect[0]+structureOrigin[0].item(),boundaryRect[1]+structureOrigin[1].item(), - boundaryRect[2]+structureOrigin[0].item(),boundaryRect[3]+structureOrigin[1].item()] + # add the offset and make it a tuple + boundaryRect=(boundaryRect[0]+structureOrigin[0].item(),boundaryRect[1]+structureOrigin[1].item(), + boundaryRect[2]+structureOrigin[0].item(),boundaryRect[3]+structureOrigin[1].item()) boundaries.append(boundaryRect) return boundaries From 07f4d639eb09078109406132e8685e45f343598a Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 30 Jan 2019 10:25:01 -0800 Subject: [PATCH 4/7] Remove non-rectangular error and just skip them. --- compiler/gdsMill/gdsMill/vlsiLayout.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/gdsMill/gdsMill/vlsiLayout.py b/compiler/gdsMill/gdsMill/vlsiLayout.py index 626ea501..03873ed4 100644 --- a/compiler/gdsMill/gdsMill/vlsiLayout.py +++ b/compiler/gdsMill/gdsMill/vlsiLayout.py @@ -757,7 +757,11 @@ class VlsiLayout: boundaries = [] for boundary in self.structures[str(structureName)].boundaries: # FIXME: Right now, this only supports rectangular shapes! - debug.check(len(boundary.coordinates)==5,"Non-rectangular shapes are not supported.") + # We should trigger an error but some FreePDK45 library cells contain paths. + # These get saved fine, but we cannot parse them as blockages... + #debug.check(len(boundary.coordinates)==5,"Non-rectangular shapes are not supported.") + if len(boundary.coordinates)!=5: + continue if layer==boundary.drawingLayer: left_bottom=boundary.coordinates[0] right_top=boundary.coordinates[2] From 74fbe8fe63ef6b2e7b43a71c8119a5b187ac0d80 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 30 Jan 2019 11:15:47 -0800 Subject: [PATCH 5/7] Convert source and target lists to sets for faster contains check. --- compiler/router/grid.py | 8 ++++---- compiler/router/signal_grid.py | 6 ++++-- compiler/router/supply_grid.py | 4 ++-- compiler/view_profile.py | 3 ++- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/compiler/router/grid.py b/compiler/router/grid.py index b43c36b2..c938f4e7 100644 --- a/compiler/router/grid.py +++ b/compiler/router/grid.py @@ -21,8 +21,8 @@ class grid: """ Initialize the map and define the costs. """ # list of the source/target grid coordinates - self.source = [] - self.target = [] + self.source = set() + self.target = set() self.track_width = track_width self.track_widths = [self.track_width, self.track_width, 1.0] @@ -80,7 +80,7 @@ class grid: else: self.add_map(n) self.map[n].source=value - self.source.append(n) + self.source.add(n) def set_target(self,n,value=True): if isinstance(n, (list,tuple,set,frozenset)): @@ -89,7 +89,7 @@ class grid: else: self.add_map(n) self.map[n].target=value - self.target.append(n) + self.target.add(n) def add_source(self,track_list,value=True): diff --git a/compiler/router/signal_grid.py b/compiler/router/signal_grid.py index 2cee04a1..59d75c7a 100644 --- a/compiler/router/signal_grid.py +++ b/compiler/router/signal_grid.py @@ -62,7 +62,8 @@ class signal_grid(grid): # We set a cost bound of the HPWL for run-time. This can be # 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 + any_source_element = next(iter(self.source)) + cost_bound = detour_scale*self.cost_to_target(any_source_element)*grid.PREFERRED_COST # Check if something in the queue is already a source and a target! for s in self.source: @@ -153,7 +154,8 @@ class signal_grid(grid): Find the cheapest HPWL distance to any target point ignoring blockages for A* search. """ - cost = self.hpwl(source,self.target[0]) + any_target_element = next(iter(self.target)) + cost = self.hpwl(source,any_target_element) for t in self.target: cost = min(self.hpwl(source,t),cost) diff --git a/compiler/router/supply_grid.py b/compiler/router/supply_grid.py index bd9dab87..88b436af 100644 --- a/compiler/router/supply_grid.py +++ b/compiler/router/supply_grid.py @@ -20,8 +20,8 @@ class supply_grid(signal_grid): def reinit(self): """ Reinitialize everything for a new route. """ - self.source = [] - self.target = [] + self.source = set() + self.target = set() # Reset all the cells in the map for p in self.map.values(): p.reset() diff --git a/compiler/view_profile.py b/compiler/view_profile.py index cb5a0cfd..aadcd459 100755 --- a/compiler/view_profile.py +++ b/compiler/view_profile.py @@ -2,7 +2,8 @@ import pstats p = pstats.Stats("profile.dat") p.strip_dirs() -p.sort_stats("cumulative") +#p.sort_stats("cumulative") +p.sort_stats("tottime") #p.print_stats(50) p.print_stats() From ec1fb087b5ec5f3962a17284ea54dbbb2b1b089b Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 30 Jan 2019 13:02:34 -0800 Subject: [PATCH 6/7] Check membership of keys without using keys() list --- compiler/router/grid.py | 5 +++-- compiler/router/router.py | 15 +++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/router/grid.py b/compiler/router/grid.py index c938f4e7..245bcb68 100644 --- a/compiler/router/grid.py +++ b/compiler/router/grid.py @@ -71,7 +71,8 @@ class grid: self.map[n].path=value def clear_blockages(self): - self.set_blocked(set(self.map.keys()),False) + for k in self.map: + self.map[k].blocked=False def set_source(self,n,value=True): if isinstance(n, (list,tuple,set,frozenset)): @@ -121,7 +122,7 @@ class grid: for item in n: self.add_map(item) else: - if n not in self.map.keys(): + if n not in self.map: self.map[n]=grid_cell() diff --git a/compiler/router/router.py b/compiler/router/router.py index 35650994..3654e8df 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -204,7 +204,7 @@ class router(router_tech): continue # Combine if at least 1 grid cell is adjacent if pg1.adjacent(pg2): - if not index1 in adjacent_pins.keys(): + if not index1 in adjacent_pins: adjacent_pins[index1] = set([index2]) else: adjacent_pins[index1].add(index2) @@ -341,7 +341,7 @@ class router(router_tech): # Block all of the pin components (some will be unblocked if they're a source/target) # Also block the previous routes - for name in self.pin_groups.keys(): + for name in self.pin_groups: 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} @@ -745,7 +745,7 @@ class router(router_tech): group_map = {} for pin in pin_list: gid = group_id[pin] - if gid not in group_map.keys(): + if gid not in group_map: group_map[gid] = pin_group(name=pin_name, pin_set=[], router=self) # We always add it to the first set since they are touching group_map[gid].pins[0].add(pin) @@ -803,7 +803,7 @@ class router(router_tech): put a rectangle over it. It does not enclose grid squares that are blocked by other shapes. """ - for pin_name in self.pin_groups.keys(): + for pin_name in self.pin_groups: debug.info(1,"Enclosing pins for {}".format(pin_name)) for pg in self.pin_groups[pin_name]: pg.enclose_pin() @@ -1091,7 +1091,7 @@ class router(router_tech): if show_all_grids: self.rg.add_all_grids() - for g in self.rg.map.keys(): + for g in self.rg.map: self.annotate_grid(g) if show_blockages: @@ -1105,12 +1105,11 @@ class router(router_tech): height=ur.y-ll.y) if show_blockage_grids: self.set_blockages(self.blocked_grids,True) - grid_keys=self.rg.map.keys() - for g in grid_keys: + for g in self.rg.map: self.annotate_grid(g) if show_enclosures: - for key in self.pin_groups.keys(): + for key in self.pin_groups: for pg in self.pin_groups[key]: if not pg.enclosed: continue From 3ffcf63e006d4cef31e031bac2d9c7587d0bda26 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 30 Jan 2019 13:09:26 -0800 Subject: [PATCH 7/7] Rename LICENSE file to README for github license detection --- technology/scn3me_subm/tech/{LICENSE.txt => README} | 0 technology/scn4m_subm/tech/{LICENSE.txt => README} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename technology/scn3me_subm/tech/{LICENSE.txt => README} (100%) rename technology/scn4m_subm/tech/{LICENSE.txt => README} (100%) diff --git a/technology/scn3me_subm/tech/LICENSE.txt b/technology/scn3me_subm/tech/README similarity index 100% rename from technology/scn3me_subm/tech/LICENSE.txt rename to technology/scn3me_subm/tech/README diff --git a/technology/scn4m_subm/tech/LICENSE.txt b/technology/scn4m_subm/tech/README similarity index 100% rename from technology/scn4m_subm/tech/LICENSE.txt rename to technology/scn4m_subm/tech/README