#!/usr/bin/env python3 # Copyright 2020 Efabless Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ takes a lef file and a rectangle => trims all RECT statements within the area """ import re import sys ARGV = sys.argv if len(ARGV) < 5: print("Usage " + ARGV[0] + " llx lly urx ury") sys.exit(-1) LLX = float(ARGV[1]) LLY = float(ARGV[2]) URX = float(ARGV[3]) URY = float(ARGV[4]) LAYERS = ["li1", "met1", "met2", "met3", "met4", "met5"] RECT_REGEX = ( r"^\s*RECT\s+(-?\d+\.?\d*)\s+(-?\d+\.?\d*)\s+(-?\d+\.?\d*)\s+(-?\d+\.?\d*)\s+;$" ) # SIZE_REGEX = r"^\s*SIZE\s+(-?\d+\.?\d*)\s+BY\s+\s+(-?\d+\.?\d*);$" def get_cut_rect_x(rect, axis): """ cuts one rect about an x axis """ rects = [rect] llx, lly, urx, ury = rect if llx < axis and urx > axis: rects = [(llx, lly, axis, ury), (axis, lly, urx, ury)] return rects def get_cut_rect_y(rect, axis): """ cuts one rect about an y axis """ rects = [rect] llx, lly, urx, ury = rect if lly < axis and ury > axis: rects = [(llx, lly, urx, axis), (llx, axis, urx, ury)] return rects def rects2cutrects(rects, axis, direction): """ cut a list of rects (4-tuple) and returns another list of of rects (4-tuple) cut by an x or y axis axix is a position direction is either 'x' or 'y' """ rects_cut = [] if direction == "x": for rect in rects: rects_cut += get_cut_rect_x(rect, axis) else: for rect in rects: rects_cut += get_cut_rect_y(rect, axis) return rects_cut def get_all_cut_rects(rect): """ cut a rect about the 4 axis LLX, LLY, URX, URY """ rects = [rect] rects = rects2cutrects(rects, LLX, "x") rects = rects2cutrects(rects, URX, "x") rects = rects2cutrects(rects, LLY, "y") rects = rects2cutrects(rects, URY, "y") return rects def rectify(rects): """ gets a list of already cut rects (4-tuple) and returns another list of of rects (4-tuple) that are not within LLX, LLY, URX, URY """ rect_outside = [] for rect in rects: llx, lly, urx, ury = rect if ( llx < LLX or llx > URX or urx > URX or urx < LLX or lly < LLY or lly > URY or ury > URY or ury < LLY ): rect_outside += [rect] return rect_outside def print_rects(prefix, rects): for rect in rects: llx, lly, urx, ury = rect print(prefix + "RECT %f %f %f %f ;" % (llx, lly, urx, ury)) layer = "" for line in sys.stdin: if line.isspace(): continue rect_match = re.search(RECT_REGEX, line) if rect_match: llx, lly, urx, ury = ( float(rect_match.group(1)), float(rect_match.group(2)), float(rect_match.group(3)), float(rect_match.group(4)), ) if ( (lly < LLY and ury < LLY) or (lly > URY and ury > URY) or (llx < LLX and urx < LLX) or (llx > URX and urx > URX) ): # outside the whole thing rects = [(llx, lly, urx, ury)] else: rects = rectify(get_all_cut_rects((llx, lly, urx, ury))) if len(rects) > 0: print(layer) if layer != "": # LAYER printed, clear it layer = "" print_rects(line[: line.find("R")], rects) else: if line.find("LAYER") != -1: # print it only if there're RECTs layer = line else: print(line, end="")