Die leeren Klammern nach dem Klassenamen in Klassendefinitionen funktionieren erst ab Python 2.5, davor ist das ein Syntaxfehler. Also am besten ganz weglassen oder von `object` erben.
`Cell` und `Port` werden gar nicht wirklich verwendet und haben keine Funktionalität, nur Daten. Erst werden die Objekte erstellt und dann werden ihre Attribute am Ende doch wieder einzeln in ein Dictionary gepackt und das Objekt wird weggeworfen. Dann kann man sich das auch sparen.
Die Daten die den Zustand eines Objekts ausmachen werden normalerweise von der `__init__()`-Methode entgegengenommen. Und was das Objekt selber berechnen kann, sollte man nicht aussen vorberechnen und setzen. Die Position von einem `Port` kann der auch selber ausrechnen.
Code: Alles auswählen
class Port(object):
def __int__(self, name, (llx, lly, urx, ury)):
self.name = name
self.llx = llx #lower left
self.lly = lly
self.urx = urx
self.ury = ury #upper right
self.x = (self.llx + self.urx) / 2 # Wirklich?
self.y = (self.lly + self.ury) / 2
Konstanten werden konventionell in den meisten Programmiersprachen komplett in Grossbuchstaben geschrieben. Dann braucht man auch keinen Kommentar dafür.
Wenn man sowieso nur einen Treffer mit einem regulären Ausdruck erwartet, dann sollte man statt `re.findall()` besser `re.search()` benutzen.
Der `Cell`-Klasse kann man eine `add_port()`-Methode verpassen:
Code: Alles auswählen
class Cell(object):
def __init__(self, name, width, height):
self.name = name
self.width = width
self.height = heigt
self.ports = dict()
def add_port(self, port):
self.ports[port.name] = port
Und die Funktion zum Parsen könnte dann so aussehen:
Code: Alles auswählen
def parse(self, lef_data):
result = dict()
for match in re.finditer(r'^MACRO (mod\d+).+?^END',
lef_data,
re.DOTALL | re.MULTILINE ):
size_match = re.search(r'SIZE (\d+\.\d) BY (\d+\.\d+)',
match.group(0))
cell = Cell(match.group(1),
CONV * Decimal(size_match.group(1)),
CONV * Decimal(size_match.group(2)))
for match_port in re.finditer(r'PIN (P\d+).+?END P\d+',
match.group(0),
re.DOTALL):
for match_point in re.finditer(r'RECT (\d+\.\d+) (\d+\.\d+) (\d+\.\d+) (\d+\.\d+) ;',
match_port.group(0)):
port = Port(match_port.group(1),
(CONV * Decimal(value)
for value in match_point.groups()))
cell.add_port(port)
result[cell.name] = cell
return result
Ich persönlich würde die noch in weitere Funktionen aufteilen. Mindestens in eine, die eine Zelle parst und ein `Cell`-Objekt zurückgibt.
Und dann müsste man überlegen wie ein `Cell`-Objekt benutzt werden soll, also zum Beispiel ob man über den Portnamen als Index auf Ports zugreifen können soll, oder wie man am besten über die `Ports`\s einer Zelle iteriert.
Mit dem Einlesen kann man es sich aber auch umständlich machen…
Code: Alles auswählen
lef_file = open('C:/Python25/interconnect_delay/ibm01e_lef.lef' , 'r')
lef_data = lef_file.read()
lef_file.close()