Skip to content

Commit ac000bb

Browse files
committed
Added bunch of stuff with help of AI, probably needs cleanup for many things
1 parent 01f46af commit ac000bb

File tree

16 files changed

+1102
-98
lines changed

16 files changed

+1102
-98
lines changed

src/cicpy/cic.py

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -274,18 +274,10 @@ def spi2mag(ctx,spi,lib,cell,libdir,techlib,xspace,yspace,gbreak):
274274
"""Translate a SPICE file to Magic"""
275275
_spi2mag(spi,lib,cell,libdir,techlib,xspace,yspace,gbreak)
276276

277-
def _runMethod(lcell,module,method):
278-
if(module is not None):
279-
if(hasattr(module,method)):
280-
fn = getattr(module,method)
281-
log.info("Running " + method + " from " + lcell.name + ".py")
282-
fn(lcell)
283277

284278

285279
def _spi2mag(spi,lib,cell,libdir,techlib,xspace,yspace,gbreak):
286280

287-
288-
289281
techfile = f"../tech/cic/{techlib}.tech"
290282
log.info(f"Loading rules {techfile}")
291283
rules = cic.Rules(techfile)
@@ -316,37 +308,14 @@ def _spi2mag(spi,lib,cell,libdir,techlib,xspace,yspace,gbreak):
316308
lcell.dirname = libdir + lib + os.path.sep
317309

318310
pycell = None
311+
pycellData = None
319312
if(os.path.exists(lcell.dirname + lcell.name + ".py")):
320313
sys.path.append(lcell.dirname)
321314
pycell = importlib.import_module(lcell.name)
322-
dir(pycell)
323-
324-
log.info(f"Assembling layout....")
325-
326-
_runMethod(lcell,pycell,"beforePlace")
327-
328-
329-
#- Place cell
330-
log.info(f"place()")
331-
lcell.place()
332-
333-
_runMethod(lcell,pycell,"afterPlace")
334-
335-
_runMethod(lcell,pycell,"beforeRoute")
336-
337-
log.info(f"route()")
338-
lcell.route()
339-
340-
_runMethod(lcell,pycell,"afterRoute")
341-
342-
_runMethod(lcell,pycell,"beforePaint")
343-
344-
log.info(f"paint()")
345-
346-
_runMethod(lcell,pycell,"afterPaint")
315+
if(hasattr(pycell,"data")):
316+
pycellData = pycell.data
347317

348-
log.info(f"addAllPorts()")
349-
lcell.addAllPorts()
318+
lcell.layout(pycell,pycellData)
350319

351320
obj = cic.MagicPrinter(libdir + lib,rules)
352321
obj.print(design)

src/cicpy/core/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@
1212
from .layoutplacer import *
1313
from .instanceport import *
1414
from .layer import *
15+
from .route import *
16+
from .cut import *
17+
from .guard import *
18+
from .routering import *
19+
from .graph import *

src/cicpy/core/cell.py

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ def __init__ (self,name=""):
5959
self.has_pr = False
6060
self.meta = list()
6161
self.obj = False #- Original JSON obj
62+
self.named_rects = dict()
6263

6364

6465
def getPort(self,name:str):
@@ -70,8 +71,12 @@ def getPort(self,name:str):
7071

7172
# Find the first rectangle in this cell that uses layer
7273
def getRect(self,layer):
73-
raise Exception("Not implemented")
74-
pass
74+
for child in self.children:
75+
if(child is None):
76+
continue
77+
if(child.layer == layer):
78+
return child
79+
return None
7580

7681
# Add a rectangle to the cell, hooks updated() of the child to updateBoundingRect
7782
def add(self, child):
@@ -90,6 +95,8 @@ def add(self, child):
9095
self.children.append(child)
9196
child.connect(self.updateBoundingRect)
9297

98+
self.updateBoundingRect()
99+
93100

94101
# Move this cell, and all children by dx and dy
95102
def translate(self, dx, dy):
@@ -104,7 +111,7 @@ def mirrorX(self,ax):
104111
super().mirrorX(ax)
105112
for child in self.children:
106113
child.mirrorX(ax)
107-
for port in self.ports:
114+
for _, port in self.ports.items():
108115
port.mirrorX(ax)
109116
self.updateBoundingRect()
110117
self.emit_updated()
@@ -115,8 +122,8 @@ def mirrorY(self,ay):
115122
super().mirrorY(ay)
116123
for child in self.children:
117124
child.mirrorY(ay)
118-
for port in self.ports:
119-
port.mirrorY()
125+
for _, port in self.ports.items():
126+
port.mirrorY(ay)
120127
self.updateBoundingRect()
121128
self.emit_updated
122129

@@ -135,28 +142,29 @@ def moveTo(self,ax, ay):
135142
# Center this cell, and all children on ax and ay
136143
def moveCenter(self,ax, ay):
137144
self.updateBoundingRect()
138-
139-
xc1 = self.centerX
140-
yc1 = self.centerY
141-
142-
xpos = self.left - (xc1 - ax)
143-
ypos = self.bottom - (yc1 - ay)
144-
145-
self.moveTo(xpos,ypos)
145+
xc1 = self.centerX()
146+
yc1 = self.centerY()
147+
dx = ax - xc1
148+
dy = ay - yc1
149+
self.translate(dx, dy)
146150

147151
# Shortcut for adding ports
148152
def addPort(name, rect):
149-
raise Exception("Not implemented")
150-
pass
153+
if(rect is None):
154+
return None
155+
p = Port(name)
156+
p.setRect(rect)
157+
self.add(p)
158+
return p
151159

152160
# Mirror this cell, and all children around horizontal center point (basically flip horizontal)
153161
def mirrorCenterX(self):
154-
self.mirrorX(self.centerY)
162+
self.mirrorX(self.centerY())
155163
pass
156164

157165

158166
def mirrorCenterY(self):
159-
self.mirrorY(self.centerX)
167+
self.mirrorY(self.centerX())
160168
pass
161169

162170
def updateBoundingRect(self):
@@ -404,9 +412,34 @@ def updatePort(self,name:str,r:Rect):
404412

405413

406414
# //! Find all rectangles by regular expression
407-
# virtual QList<Rect *> findRectanglesByRegex(QString regex,QString layer);
408-
# virtual void findRectangles(QList<Rect*> &rects,QString name,QString layer);
409-
# virtual QList<Rect *> findAllRectangles(QString regex, QString layer);
415+
def findRectanglesByRegex(self, regex:str, layer:str):
416+
rects = list()
417+
self.findRectangles(rects, regex, layer)
418+
return rects
419+
420+
def findRectangles(self, rects:list, name:str, layer:str):
421+
for child in self.children:
422+
if child is None:
423+
continue
424+
if layer and child.layer != layer:
425+
continue
426+
if re.search(name, getattr(child,'name', '')):
427+
rects.append(child)
428+
# Also include plain rects on layer when name matches empty or wildcard
429+
elif name == "" and (hasattr(child,'isRect') and child.isRect()):
430+
rects.append(child)
431+
432+
def findAllRectangles(self, regex:str, layer:str):
433+
rects = list()
434+
for child in self.children:
435+
if child is None:
436+
continue
437+
if layer and child.layer != layer:
438+
continue
439+
cname = getattr(child,'name','')
440+
if re.search(regex, cname) or (hasattr(child,'isRect') and child.isRect() and re.search(regex, layer)):
441+
rects.append(child)
442+
return rects
410443

411444
# QJsonObject toJson();
412445
# void fromJson(QJsonObject o);

src/cicpy/core/cut.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from .cell import Cell
2+
from .rect import Rect
3+
from .rules import Rules
4+
5+
class Cut(Cell):
6+
7+
def __init__(self, startlayer:str, stoplayer:str, hcuts:int, vcuts:int):
8+
super().__init__(f"Cut_{startlayer}_{stoplayer}")
9+
self.startlayer = startlayer
10+
self.stoplayer = stoplayer
11+
self.hcuts = hcuts
12+
self.vcuts = vcuts
13+
self._build_placeholder_geometry()
14+
15+
def _build_placeholder_geometry(self):
16+
try:
17+
rw = Rules.getInstance().get(self.stoplayer, "width")
18+
except Exception:
19+
rw = 0
20+
r = Rect(self.stoplayer, 0, 0, rw, rw)
21+
self.add(r)
22+
23+
@staticmethod
24+
def getInstance(startlayer:str, stoplayer:str, hcuts:int, vcuts:int):
25+
return Cut(startlayer, stoplayer, hcuts, vcuts)
26+
27+
@staticmethod
28+
def getCutsForRects(routeLayer:str, rects:list, cuts:int, vcuts:int, leftAlignCut:bool=True):
29+
rules = Rules.getInstance()
30+
cuts_out = []
31+
try:
32+
cw = rules.get(routeLayer, "width")
33+
cs = rules.get(routeLayer, "space")
34+
except Exception:
35+
cw = 0
36+
cs = 0
37+
for r in rects:
38+
if r is None:
39+
continue
40+
total_width = cuts*cw + (cuts-1)*cs if cuts > 0 else 0
41+
if leftAlignCut:
42+
x0 = r.x1
43+
else:
44+
x0 = r.x2 - total_width
45+
y0 = r.centerY() - (vcuts*cw + (vcuts-1)*cs)//2
46+
for iv in range(max(1, vcuts)):
47+
for ih in range(max(1, cuts)):
48+
x = x0 + ih*(cw+cs)
49+
y = y0 + iv*(cw+cs)
50+
cuts_out.append(Rect(routeLayer, x, y, cw, cw))
51+
return cuts_out
52+

src/cicpy/core/design.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ def __init__(self):
4747
self.prefix = ""
4848

4949

50+
51+
5052
def fromJsonFile(self,fname):
5153
jobj = None
5254

@@ -97,6 +99,7 @@ def cellNames(self):
9799
def getCell(self,name):
98100
return self.cells[name]
99101

102+
100103
def read(self,filename):
101104
import cicspi as spi
102105
#Read JSON

src/cicpy/core/graph.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,31 @@ def __init__(self):
66
self.ports = list()
77
self.name = ""
88

9-
def append(p:Port):
10-
if(not self.ports.contains(p)):
9+
def append(self,p):
10+
if p not in self.ports:
1111
self.ports.append(p)
1212

13-
def getRectangles(excludeInstances:str,includeInstances:str,layer:str):
13+
def getRectangles(self,excludeInstances:str,includeInstances:str,layer:str):
1414
rects = list()
1515
for p in self.ports:
16-
i = p.parent()
17-
if(i is None):continue
18-
if(not i.isInstance()): continue
16+
i = p.parent
17+
if(i is None):
18+
continue
19+
if(not i.isInstance()):
20+
continue
1921

20-
if(excludeInstances is not None):
21-
if( re.search(excludeInstances,i.instanceName) \
22-
or re.search(excludeInstances,i.name)): continue
22+
if(excludeInstances):
23+
if( re.search(excludeInstances,getattr(i,'instanceName','')) \
24+
or re.search(excludeInstances,getattr(i,'name',''))):
25+
continue
2326

24-
if(includeInstances is not None):
25-
if(not ( re.search(includeInstances,i.instanceName) \
26-
or re.search(includeInstances,i.name))): continue
27+
if(includeInstances):
28+
if(not ( re.search(includeInstances,getattr(i,'instanceName','')) \
29+
or re.search(includeInstances,getattr(i,'name','')))):
30+
continue
2731
rp = p.get(layer)
2832

2933
if(rp is None): rp = p.get()
3034
if(rp is not None):
3135
rects.append(rp)
36+
return rects

src/cicpy/core/guard.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from .cell import Cell
2+
from .rect import Rect
3+
from .rules import Rules
4+
5+
class Guard(Cell):
6+
7+
def __init__(self, rect:Rect, layers:list):
8+
super().__init__("Guard")
9+
self.layers = list(layers or [])
10+
if rect:
11+
base = rect.getCopy()
12+
encx = Rules.getInstance().get("ROUTE","verticalgrid") if Rules.getInstance() else 0
13+
ency = encx
14+
base.adjust(encx)
15+
self.add(base)
16+
# For each requested layer, copy a rect
17+
for layer in self.layers:
18+
gr = base.getCopy(layer)
19+
self.add(gr)
20+
21+
def getRect(self, layer:str):
22+
for c in self.children:
23+
if c.layer == layer:
24+
return c
25+
return None
26+

src/cicpy/core/instance.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ def setSubcktInstance(self,inst:spi.SubcktInstance):
7979
cellPort = self.layoutcell.getPort(cktNode)
8080
if(cellPort):
8181
instPort = InstancePort(instNode,cellPort,self)
82+
# Track in instance port collections
83+
self.instancePorts[instNode] = instPort
84+
self.instancePortsList.append(instNode)
8285
self.add(instPort)
8386
else:
8487
log.warning(f"Could not find {cktNode} on {ckt.name}")
@@ -115,14 +118,15 @@ def isLayoutCell(self):
115118
def findRectanglesByNode(self,node:str,filterChild:str):
116119
rects = list()
117120
for pi in self.children:
118-
if(pi is None): continue
119-
if(not pi.isInstancePort()): continue
120-
121-
if(re.search(pi.name,node) and ((filterChild is None) or not re.search(pi.childName,filterChild))):
122-
r = pi.get()
123-
if(r is not None):
124-
r.parent = self
125-
rects.append(r)
121+
if(pi is None):
122+
continue
123+
if(not pi.isInstancePort()):
124+
continue
125+
if(re.search(node, pi.name) and ((filterChild is None) or not re.search(filterChild, getattr(pi, 'childName', '')))):
126+
r = pi.get()
127+
if(r is not None):
128+
r.parent = self
129+
rects.append(r)
126130
return rects
127131

128132

src/cicpy/core/instanceport.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def __init__(self,name,port:Port,parent:Cell):
1010
super().__init__(name)
1111
self.childport = port
1212
self.parent = parent
13+
self.childName = port.name
1314
r = port.get()
1415
rules = Rules.getInstance()
1516
if(r):

0 commit comments

Comments
 (0)