First working version of the Flexlib + P&R flow for the ls180+SRAM.
[soclayout.git] / experiments5 / ringoscillator.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import sys
5 import re
6 import traceback
7 import shutil
8 import os.path
9 import optparse
10 import Cfg
11 import Hurricane
12 from Hurricane import DbU
13 from Hurricane import DataBase
14 from Hurricane import UpdateSession
15 from Hurricane import Breakpoint
16 from Hurricane import Box
17 from Hurricane import Transformation
18 from Hurricane import Instance
19 from Hurricane import Contact
20 from Hurricane import Vertical
21 from Hurricane import Horizontal
22 from Hurricane import Pin
23 from Hurricane import Net
24 from Hurricane import NetExternalComponents
25 import Viewer
26 import CRL
27 import Etesian
28 import Anabatic
29 import Katana
30 import Unicorn
31 from helpers import l, u, n
32 import clocktree.ClockTree
33 import plugins.RSavePlugin
34 import plugins.ClockTreePlugin
35 import symbolic.cmos
36
37 af = CRL.AllianceFramework.get()
38
39
40 def build_crosstrace(net, via, layer, x, x1, y):
41
42 contacts = \
43 [ Contact.create( net, via, l(x), l(y), l(1.0), l(1.0) )
44 , Contact.create( net, via, l(x1), l(y), l(1.0), l(1.0) )
45 ]
46
47 createHorizontal( contacts, l(y), layer )
48 print "slaves", contacts[-1].getSlaveComponents()
49 for component in contacts[-1].getSlaveComponents():
50 NetExternalComponents.setExternal(component)
51
52 def build_downtrace(net, via, layer, x, y, y1):
53
54 contacts = \
55 [ Contact.create( net, via, l(x), l(y), l(1.0), l(1.0) )
56 , Contact.create( net, via, l(x), l(y1), l(1.0), l(1.0) )
57 ]
58
59 createVertical( contacts, l(x), layer )
60 print "slaves", contacts[-1].getSlaveComponents()
61 for component in contacts[-1].getSlaveComponents():
62 NetExternalComponents.setExternal(component)
63
64 #print "af", dir(af)
65 #sys.exit(0)
66
67 Cfg.Configuration.pushDefaultPriority( Cfg.Parameter.Priority.UserFile )
68
69 cellsTop = '~/alliance-check-toolkit/cells'
70 env = af.getEnvironment()
71 env.addSYSTEM_LIBRARY( library=cellsTop+'/nsxlib', mode=CRL.Environment.Prepend )
72 env.addSYSTEM_LIBRARY( library=cellsTop+'/mpxlib', mode=CRL.Environment.Prepend )
73
74
75 Cfg.getParamBool ( 'misc.catchCore' ).setBool ( False )
76 Cfg.getParamBool ( 'misc.info' ).setBool ( False )
77 Cfg.getParamBool ( 'misc.paranoid' ).setBool ( False )
78 Cfg.getParamBool ( 'misc.bug' ).setBool ( False )
79 Cfg.getParamBool ( 'misc.logMode' ).setBool ( True )
80 Cfg.getParamBool ( 'misc.verboseLevel1' ).setBool ( True )
81 Cfg.getParamBool ( 'misc.verboseLevel2' ).setBool ( True )
82 Cfg.getParamInt ( 'misc.minTraceLevel' ).setInt ( 159 )
83 #Cfg.getParamInt ( 'misc.maxTraceLevel' ).setInt ( 160 )
84 Cfg.getParamEnumerate ( 'etesian.effort' ).setInt ( 2 )
85 Cfg.getParamPercentage( 'etesian.spaceMargin' ).setPercentage( 20.0 )
86 Cfg.getParamPercentage( 'etesian.aspectRatio' ).setPercentage( 100.0 )
87 Cfg.getParamBool ( 'etesian.uniformDensity' ).setBool ( True )
88 Cfg.getParamInt ( 'anabatic.edgeLenght' ).setInt ( 24 )
89 Cfg.getParamInt ( 'anabatic.edgeWidth' ).setInt ( 8 )
90 Cfg.getParamString ( 'anabatic.topRoutingLayer' ).setString ( 'METAL5')
91 Cfg.getParamInt ( 'katana.eventsLimit' ).setInt ( 1000000 )
92 Cfg.getParamInt ( 'katana.hTracksReservedLocal' ).setInt ( 7 )
93 Cfg.getParamInt ( 'katana.vTracksReservedLocal' ).setInt ( 6 )
94 #Cfg.getParamInt ( 'clockTree.minimumSide' ).setInt ( l(1000) )
95
96 env = af.getEnvironment()
97 env.setCLOCK( '^clk$|m_clock' )
98 env.setPOWER( 'vdd' )
99 env.setGROUND( 'vss' )
100
101 Cfg.Configuration.popDefaultPriority()
102
103 ###################
104 # add
105
106 def add ( cell, **kw ):
107 editor = None
108 if kw.has_key('editor') and kw['editor']:
109 editor = kw['editor']
110
111 db = DataBase.getDB()
112 print db, dir(db)
113 metal2 = DataBase.getDB().getTechnology().getLayer( 'metal2' )
114 metal3 = DataBase.getDB().getTechnology().getLayer( 'metal3' )
115 metal5 = DataBase.getDB().getTechnology().getLayer( 'metal5' )
116
117 #cell = af.getCell( 'add', CRL.Catalog.State.Logical )
118 print cell.getNet('a(0)')
119
120 if not cell:
121 print '[ERROR] Unable to load cell "alu16.vst", aborting .'
122 return False
123 kw[ 'cell' ] = cell
124
125 width = 350.0
126 height = 405.0
127
128 ab = Box( l( 0.0 )
129 , l( 0.0 )
130 , l( width )
131 , l( height ) )
132
133 cellGauge = af.getCellGauge()
134 spaceMargin = (Cfg.getParamPercentage('etesian.spaceMargin').asPercentage()+5) / 100.0
135 aspectRatio = Cfg.getParamPercentage('etesian.aspectRatio').asPercentage() / 100.0
136 clocktree.ClockTree.computeAbutmentBox( cell,
137 spaceMargin, aspectRatio, cellGauge )
138 ab2 = cell.getAbutmentBox()
139 print "box", ab, ab.getHeight(), ab.getWidth()
140 print "calc box", ab2, ab2.getHeight(), ab2.getWidth()
141
142 #height = ab.getHeight()
143 #width = ab.getWidth()
144
145 #UpdateSession.open()
146 cell.setAbutmentBox( ab )
147
148 for i in range(16):
149 if True:
150 x = 20.0*i + 10.0
151 y = height
152 net = cell.getNet('a(%d)' % i)
153 print "net", net
154 Pin.create( net
155 , 'a(%d).0' % i
156 , Pin.Direction.NORTH
157 , Pin.PlacementStatus.FIXED
158 , metal3
159 , l( x ), l( y - 0 ) # Position.
160 , l( 2.0 ) , l( 2.0 ) # Size.
161 )
162 for i in range(16):
163 if True:
164 Pin.create( cell.getNet('o(%d)' % i)
165 , 'o(%d).0' % i
166 , Pin.Direction.SOUTH
167 , Pin.PlacementStatus.FIXED
168 , metal3
169 , l( 10.0*i + 100.0 ), l( 0) # Position.
170 , l( 2.0 ) , l( 2.0 ) # Size.
171 )
172
173 for i in range(16):
174 if True:
175 net = cell.getNet('b(%d)' % i)
176 x = 20.0*i + 10.0 + 10
177 y = height - 0
178 #build_downtrace(net, metal3, x, y+11, y)
179 #continue
180 Pin.create( net
181 , 'b(%d).0' % i
182 , Pin.Direction.NORTH
183 , Pin.PlacementStatus.FIXED
184 , metal3
185 , l( x ), l( y - 0 ) # Position.
186 , l( 2.0 ) , l( 2.0 ) # Size.
187 )
188 if False:
189 Pin.create( cell.getNet('rst')
190 , 'p_reset.0'
191 , Pin.Direction.WEST
192 , Pin.PlacementStatus.FIXED
193 , metal2
194 , l( 0.0 )
195 , l( 140.0 )
196 , l( 2.0 )
197 , l( 2.0 )
198 )
199 #UpdateSession.close()
200
201 if True:
202 if editor: editor.setCell( cell )
203
204 etesian = Etesian.EtesianEngine.create(cell)
205 etesian.place()
206
207 katana = Katana.KatanaEngine.create(cell)
208 katana.digitalInit ()
209 #katana.runNegociatePreRouted()
210 print dir(katana)
211 katana.runGlobalRouter (0)
212 katana.loadGlobalRouting ( Anabatic.EngineLoadGrByNet )
213 katana.layerAssign ( Anabatic.EngineNoNetLayerAssign )
214 katana.runNegociate ( Katana.Flags.NoFlags )
215 katana.finalizeLayout ()
216 print dir(katana)
217 success = katana.getSuccessState()
218 katana.destroy()
219
220 if False:
221 VIA23 = DataBase.getDB().getTechnology().getLayer( 'VIA23' )
222 #UpdateSession.open()
223 #net = cell.getNet('b(%d)' % 0)
224 net = cell.getNet('vdd')
225 build_downtrace(net, VIA23, metal2, -5, -10, -20)
226 build_downtrace(net, VIA23, metal2, -10, -10, -20)
227 build_crosstrace(net, VIA23, metal2, -5, -10, -10)
228 build_crosstrace(net, VIA23, metal2, -5, -10, -20)
229 for i in range(16):
230 if False:
231 net = cell.getNet('b(%d)' % i)
232 x = 20.0*i + 10.0 + 10
233 y = height-10
234 build_downtrace(net, metal2, x, y, y+10)
235 ab.inflate ( l(30.0) )
236 cell.setAbutmentBox( ab )
237 #UpdateSession.close()
238
239 #af.saveCell( cell, CRL.Catalog.State.Views )
240 #plugins.RSavePlugin.ScriptMain( **kw )
241
242
243 ###################
244 # sub
245
246 def sub ( cell, **kw ):
247 editor = None
248 if kw.has_key('editor') and kw['editor']:
249 editor = kw['editor']
250
251 db = DataBase.getDB()
252 print db, dir(db)
253 metal2 = DataBase.getDB().getTechnology().getLayer( 'metal2' )
254 metal3 = DataBase.getDB().getTechnology().getLayer( 'metal3' )
255 metal5 = DataBase.getDB().getTechnology().getLayer( 'metal5' )
256
257 #cell = af.getCell( 'sub', CRL.Catalog.State.Logical )
258 print cell.getNet('a(0)')
259
260 if not cell:
261 print '[ERROR] Unable to load cell "alu16.vst", aborting .'
262 return False
263 kw[ 'cell' ] = cell
264
265 width = 350.0
266 height = 405.0
267
268 ab = Box( l( 0.0 )
269 , l( 0.0 )
270 , l( width )
271 , l( height ) )
272
273 cellGauge = af.getCellGauge()
274 spaceMargin = (Cfg.getParamPercentage('etesian.spaceMargin').asPercentage()+5) / 100.0
275 aspectRatio = Cfg.getParamPercentage('etesian.aspectRatio').asPercentage() / 100.0
276 clocktree.ClockTree.computeAbutmentBox( cell, spaceMargin, aspectRatio, cellGauge )
277 ab2 = cell.getAbutmentBox()
278 print "box", ab, ab.getHeight(), ab.getWidth()
279 print "calc box", ab2, ab2.getHeight(), ab2.getWidth()
280
281 #height = ab.getHeight()
282 #width = ab.getWidth()
283
284 #UpdateSession.open()
285 cell.setAbutmentBox( ab )
286
287 for i in range(16):
288 if True:
289 x = 20.0*i + 10.0
290 y = height
291 Pin.create( cell.getNet('a(%d)' % i)
292 , 'a(%d).0' % i
293 , Pin.Direction.NORTH
294 , Pin.PlacementStatus.FIXED
295 , metal3
296 , l( x ), l( y - 0 ) # Position.
297 , l( 2.0 ) , l( 2.0 ) # Size.
298 )
299 for i in range(16):
300 if True:
301 Pin.create( cell.getNet('o(%d)' % i)
302 , 'o(%d).0' % i
303 , Pin.Direction.SOUTH
304 , Pin.PlacementStatus.FIXED
305 , metal3
306 , l( 10.0*i + 100.0 ), l( 0) # Position.
307 , l( 2.0 ) , l( 2.0 ) # Size.
308 )
309
310 for i in range(16):
311 if True:
312 net = cell.getNet('b(%d)' % i)
313 x = 20.0*i + 10.0 + 10
314 y = height - 0
315 #build_downtrace(net, metal3, x, y+11, y)
316 #continue
317 Pin.create( net
318 , 'b(%d).0' % i
319 , Pin.Direction.NORTH
320 , Pin.PlacementStatus.FIXED
321 , metal3
322 , l( x ), l( y - 0 ) # Position.
323 , l( 2.0 ) , l( 2.0 ) # Size.
324 )
325 if False:
326 Pin.create( cell.getNet('rst')
327 , 'p_reset.0'
328 , Pin.Direction.WEST
329 , Pin.PlacementStatus.FIXED
330 , metal2
331 , l( 0.0 )
332 , l( 140.0 )
333 , l( 2.0 )
334 , l( 2.0 )
335 )
336 #UpdateSession.close()
337
338 if True:
339 if editor: editor.setCell( cell )
340
341 etesian = Etesian.EtesianEngine.create(cell)
342 etesian.place()
343
344 katana = Katana.KatanaEngine.create(cell)
345 katana.digitalInit ()
346 #katana.runNegociatePreRouted()
347 print dir(katana)
348 katana.runGlobalRouter (0)
349 katana.loadGlobalRouting ( Anabatic.EngineLoadGrByNet )
350 katana.layerAssign ( Anabatic.EngineNoNetLayerAssign )
351 katana.runNegociate ( Katana.Flags.NoFlags )
352 katana.finalizeLayout ()
353 print dir(katana)
354 success = katana.getSuccessState()
355 katana.destroy()
356
357 #af.saveCell( cell, CRL.Catalog.State.Views )
358 #plugins.RSavePlugin.ScriptMain( **kw )
359
360
361 #def toDbU(v): return DbU.fromLambda(v)
362 def toDbU(v): return l(v)
363
364
365
366 def doBreak(level, message):
367 UpdateSession.close()
368 Breakpoint.stop(level, message)
369 UpdateSession.open()
370
371
372 class Model (object):
373
374 HorizontalAccess = 1
375 VerticalAccess = 2
376
377 def __init__(self, modelName, session=True, views=False):
378 if session:
379 UpdateSession.open()
380 self.fillerCount = 0
381 self.af = CRL.AllianceFramework.get()
382 #self.cell = af.createCell(modelName)
383 if not views:
384 self.cell = self.af.getCell( modelName, CRL.Catalog.State.Logical )
385 else:
386 self.cell = self.af.getCell( modelName, CRL.Catalog.State.Views )
387 self.createNet('vss', direction=Net.Direction.IN,
388 isExternal=True, isGlobal=True, type=Net.Type.POWER)
389 self.createNet('vdd', direction=Net.Direction.IN,
390 isExternal=True, isGlobal=True, type=Net.Type.GROUND)
391
392 self.build()
393 if session:
394 UpdateSession.close()
395 return
396
397 def createNet(self, netName, **attributes):
398 net = self.cell.getNet(netName)
399 if not net:
400 net = Net.create(self.cell, netName)
401
402 if 'direction' in attributes:
403 net.setDirection(attributes['direction'])
404 if 'isExternal' in attributes:
405 net.setExternal(attributes['isExternal'])
406 if 'isGlobal' in attributes:
407 net.setGlobal(attributes['isGlobal'])
408 if 'type' in attributes:
409 net.setType(attributes['type'])
410 return net
411
412 def getNet(self, netName):
413 return self.createNet(netName)
414
415 def connect(self, instanceRef, pin, netRef):
416 if isinstance(instanceRef, str):
417 instance = self.getInstance(instanceRef)
418 else:
419 instance = instanceRef
420
421 if isinstance(netRef, str):
422 net = self.getNet(netRef)
423 else:
424 net = netRef
425
426 masterNet = instance.getMasterCell().getNet(pin)
427 if not masterNet:
428 print '[ERROR] Master cell "%s" of instance "%s" ' \
429 'has no connector named "%s".' \
430 % (instance.getMasterCell().getName(), instance.getName(), pin)
431
432 instance.getPlug(instance.getMasterCell().getNet(pin)).setNet(net)
433 return
434
435 def place(self, instanceRef, x, y, orient):
436 if isinstance(instanceRef, str):
437 instance = self.getInstance(instanceRef)
438 else:
439 instance = instanceRef
440
441 instance.setTransformation(Transformation(x, y, orient))
442 instance.setPlacementStatus(Instance.PlacementStatus.PLACED)
443 return
444
445 def createInstance(self, instanceName, modelRef, portmap={}, transf=None):
446 instance = self.cell.getInstance(instanceName)
447 if not instance:
448 if isinstance(modelRef, str):
449 model = self.af.getCell(modelRef, CRL.Catalog.State.Views)
450 else:
451 model = modelRef
452 instance = Instance.create(self.cell, instanceName, model)
453 for pin, net in portmap.items():
454 self.connect(instance, pin, net)
455
456 if transf:
457 self.place(instance, transf[0], transf[1], transf[2])
458 return instance
459
460 def createAccess(self, termPath, x, y, flags):
461 insName, pinName = termPath.split('.')
462 instance = self.cell.getInstance(insName)
463 if not instance:
464 print '[ERROR] Model "%s" has no instance named "%s"' \
465 % (self.cell.getName(), insName)
466 try:
467 plug = instance.getPlug(instance.getMasterCell().getNet(pinName))
468 except BaseException:
469 print '[ERROR] Model "%s" of instance "%s" has ' \
470 'no terminal named "%s"' \
471 % (instance.getMasterCell().getName(),
472 instance.getName(), pinName)
473
474 net = plug.getNet()
475 VIA12 = self.getLayer('VIA12')
476 VIA23 = self.getLayer('VIA23')
477 METAL2 = self.getLayer('METAL2')
478
479 rp = RoutingPad.create(
480 net, Occurrence(plug), RoutingPad.BiggestArea)
481 rpCenter = rp.getPosition()
482
483 if y is None:
484 y = rpCenter.getY()
485 contact1 = Contact.create(rp, VIA12, toDbU(0.0), y - rpCenter.getY())
486
487 if flags & Model.VerticalAccess:
488 contact2 = contact1
489 contact1 = Contact.create(net, VIA23, x, y)
490 Horizontal.create(contact2, contact1, METAL2, y, toDbU(2.0))
491 return contact1
492
493 def createVertical(self, contacts, x, width=None, layer=None):
494 def yincrease(lhs, rhs): return int(lhs.getY() - rhs.getY())
495
496 contacts.sort(yincrease)
497
498 if width is None:
499 width = toDbU(2.0)
500
501 if layer is None:
502 layer = self.getLayer("METAL3")
503 for i in range(1, len(contacts)):
504 Vertical.create(contacts[i - 1], contacts[i], layer, x, width)
505 return
506
507 def createHorizontal(self, contactPaths, y, width=None, layer=None):
508 def xincrease(lhs, rhs): return int(lhs.getX() - rhs.getX())
509
510 if isinstance(contactPaths[0], str):
511 contacts = []
512 for termPath in contactPaths:
513 contacts.append(self.createAccess(
514 termPath, None, y, Model.HorizontalAccess))
515 else:
516 contacts = contactPaths
517
518 if width is None:
519 width = toDbU(2.0)
520
521 contacts.sort(xincrease)
522
523 if layer is None:
524 layer = self.getLayer("METAL2")
525 for i in range(1, len(contacts)):
526 Horizontal.create(contacts[i - 1], contacts[i], layer, y, width)
527 return
528
529 def createSerpentine(
530 self, contactPaths, ymin, ymax, width=None, layer=None):
531 def xincrease(lhs, rhs): return int(lhs.getX() - rhs.getX())
532
533 if isinstance(contactPaths[0], str):
534 contacts = []
535 for termPath in contactPaths:
536 contacts.append(self.createAccess(
537 termPath, None, None, Model.HorizontalAccess))
538 else:
539 contacts = contactPaths
540
541 if len(contacts) != 2:
542 print '[ERROR] Model.createSerpentine() takes exactly ' \
543 'two points, not %d.' % len( contacts)
544
545 if layer is None:
546 layer = self.getLayer("METAL2")
547 if width is None:
548 width = toDbU(2.0)
549
550 contacts.sort(xincrease)
551
552 turn0 = contacts[0]
553 trackPitch = toDbU(5.0)
554 for i in range((contacts[1].getX() - contacts[0].getX()) / trackPitch):
555 y = ymin
556 if i % 2:
557 y = ymax
558
559 x = turn0.getX()
560 turn1 = Contact.create(
561 turn0.getNet(), layer, x, y, width, width)
562 turn2 = Contact.create(
563 turn0.getNet(), layer, x + trackPitch, y, width, width)
564 Vertical .create(turn0, turn1, layer, x, width)
565 Horizontal.create(turn1, turn2, layer, y, width)
566
567 turn0 = turn2
568
569 Vertical.create(turn0, contacts[1], layer, contacts[1].getX(), width)
570
571 return
572
573 def addFillersRow(self, x, y, orient, length):
574 tieWidth = self.getMasterCell("tie_x0").getAbutmentBox().getWidth()
575 i = 0
576 for i in range(length / tieWidth):
577 self.createInstance(
578 "filler_%d_i" %
579 self. fillerCount, "tie_x0", transf=(
580 x + tieWidth * i, y, orient))
581 self.fillerCount += 1
582 if length % tieWidth:
583 delta = 0
584 if length > tieWidth:
585 delta = 1
586 self.createInstance("filler_%d_i" % self.fillerCount, "rowend_x0",
587 transf=(x + tieWidth * (i + delta), y, orient))
588 self.fillerCount += 1
589 return
590
591 def getLayer(self, name):
592 return DataBase.getDB().getTechnology().getLayer(name)
593
594 def getCell(self): return self.cell
595
596 def getMasterCell( self, name):
597 return self.af.getCell(name, CRL.Catalog.State.Views)
598
599 def setAbutmentBox(self, ab): self.cell.setAbutmentBox(ab)
600
601 def getAbutmentBox(self): return self.cell.getAbutmentBox()
602
603 def getCellWidth(self, name):
604 return self.getMasterCell(name).getAbutmentBox().getWidth()
605
606 def save(self):
607 plugins.RSavePlugin.ScriptMain( cell=self.cell )
608 #self.af.saveCell(self.cell, CRL.Catalog.State.Views)
609
610 def build(self):
611 print '[ERROR] Model.build() base class method should never be called.'
612
613
614 class Ringed (Model):
615
616 def addFillers(self):
617 self.addFillersRow(toDbU(1580.0), toDbU(0.0),
618 Transformation.Orientation.ID, toDbU(15.0))
619 self.addFillersRow(toDbU(1570.0), toDbU(100.0),
620 Transformation.Orientation.MY, toDbU(5.0))
621 self.addFillersRow(toDbU(1570.0), toDbU(100.0),
622 Transformation.Orientation.ID, toDbU(25.0))
623 self.addFillersRow(toDbU(1530.0), toDbU(200.0),
624 Transformation.Orientation.MY, toDbU(45.0))
625 self.addFillersRow(toDbU(1550.0), toDbU(200.0),
626 Transformation.Orientation.ID, toDbU(10.0))
627 self.addFillersRow(toDbU(1550.0), toDbU(300.0),
628 Transformation.Orientation.MY, toDbU(25.0))
629 self.addFillersRow(toDbU(1570.0), toDbU(300.0),
630 Transformation.Orientation.ID, toDbU(25.0))
631 self.addFillersRow(toDbU(1550.0), toDbU(400.0),
632 Transformation.Orientation.MY, toDbU(25.0))
633
634 def buildPower(self):
635 METAL1 = self.getLayer("METAL1")
636 METAL2 = self.getLayer("METAL2")
637 METAL3 = self.getLayer("METAL3")
638 METAL4 = self.getLayer("METAL3")
639 VIA12 = self.getLayer("VIA12")
640 VIA23 = self.getLayer("VIA23")
641 powerWidth = toDbU(2.0)
642 powerSpacing = toDbU(5.0)
643 ab = self.getAbutmentBox()
644 vdd = self.getNet("vdd")
645 vss = self.getNet("vss")
646 vddAxis = Box(ab).inflate(powerSpacing + powerWidth / 2)
647 vssAxis = Box(ab).inflate(
648 powerSpacing + powerWidth / 2 + powerWidth + toDbU(5.0))
649
650 # Building "vdd" power ring.
651 westContactsVdd = [
652 Contact.create( vdd, VIA23, vddAxis.getXMin(), vddAxis.getYMin(),
653 powerWidth, powerWidth),
654 Contact.create( vdd, VIA23, vddAxis.getXMin(), vddAxis.getYMax(),
655 powerWidth, powerWidth)]
656 eastContactsVdd = [
657 Contact.create( vdd, VIA23, vddAxis.getXMax(), vddAxis.getYMin(),
658 powerWidth, powerWidth),
659 Contact.create( vdd, VIA23, vddAxis.getXMax(), vddAxis.getYMax(),
660 powerWidth, powerWidth)]
661
662 for i in range(0):
663 ywidth = toDbU(12.0)
664 if i == 4:
665 ywidth = toDbU(6.0)
666 yaxis = ab.getXMin() + toDbU(50.0) * (1 + i * 2)
667
668 westContact = Contact.create( vdd, VIA12, vddAxis.getXMin(),
669 yaxis, powerWidth, ywidth)
670 eastContact = Contact.create( vdd, VIA12, vddAxis.getXMax(),
671 yaxis, powerWidth, ywidth)
672 self.createHorizontal( [westContact, eastContact],
673 yaxis, ywidth, layer=METAL1)
674
675 westContact = Contact.create(
676 vdd, VIA23, vddAxis.getXMin(), yaxis, powerWidth, ywidth)
677 eastContact = Contact.create(
678 vdd, VIA23, vddAxis.getXMax(), yaxis, powerWidth, ywidth)
679
680 westContactsVdd.insert(-1, westContact)
681 eastContactsVdd.insert(-1, eastContact)
682
683 for layer in [METAL2, METAL3]:
684 self.createVertical(westContactsVdd, vddAxis.getXMin(), powerWidth,
685 layer=layer)
686 self.createVertical(eastContactsVdd, vddAxis.getXMax(), powerWidth,
687 layer=layer)
688
689 xcenter = vddAxis.getCenter().getX() + powerWidth / 2 + toDbU(5.0)
690 if False:
691 accessContactsVdd = [
692 Contact.create(
693 vdd,
694 VIA23,
695 xcenter,
696 vddAxis.getYMax(),
697 powerWidth,
698 powerWidth),
699 Contact.create(
700 vdd,
701 METAL3,
702 xcenter,
703 toDbU(528.0),
704 powerWidth,
705 toDbU(2.0))]
706
707 northContactsVdd = \
708 [westContactsVdd[-1],
709 #accessContactsVdd[0],
710 eastContactsVdd[-1]
711 ]
712 southContactsVdd = \
713 [westContactsVdd[0], eastContactsVdd[0]
714 ]
715 self.createHorizontal(
716 southContactsVdd, vddAxis.getYMin(), powerWidth)
717 self.createHorizontal(
718 northContactsVdd, vddAxis.getYMax(), powerWidth)
719 #self.createVertical(
720 #accessContactsVdd, xcenter, powerWidth)
721 #for component in accessContactsVdd[-1].getSlaveComponents():
722 #NetExternalComponents.setExternal(component)
723
724 # Building "vss" power ring.
725 westContactsVss = [
726 Contact.create(
727 vss,
728 VIA23,
729 vssAxis.getXMin(),
730 vssAxis.getYMin(),
731 powerWidth,
732 powerWidth),
733 Contact.create(
734 vss,
735 VIA23,
736 vssAxis.getXMin(),
737 vssAxis.getYMax(),
738 powerWidth,
739 powerWidth)]
740 eastContactsVss = [
741 Contact.create(
742 vss,
743 VIA23,
744 vssAxis.getXMax(),
745 vssAxis.getYMin(),
746 powerWidth,
747 powerWidth),
748 Contact.create(
749 vss,
750 VIA23,
751 vssAxis.getXMax(),
752 vssAxis.getYMax(),
753 powerWidth,
754 powerWidth)]
755
756 for i in range(5):
757 ywidth = toDbU(12.0)
758 if i == 0:
759 ywidth = toDbU(6.0)
760 yaxis = ab.getXMin() + toDbU(50.0) * (i * 2)
761
762 westContact = Contact.create(
763 vss, VIA12, vssAxis.getXMin(), yaxis, powerWidth, ywidth)
764 eastContact = Contact.create(
765 vss, VIA12, vssAxis.getXMax(), yaxis, powerWidth, ywidth)
766 self.createHorizontal(
767 [westContact, eastContact], yaxis, ywidth, layer=METAL1)
768
769 westContact = Contact.create(
770 vss, VIA23, vssAxis.getXMin(), yaxis, powerWidth, ywidth)
771 eastContact = Contact.create(
772 vss, VIA23, vssAxis.getXMax(), yaxis, powerWidth, ywidth)
773
774 westContactsVss.insert(-1, westContact)
775 eastContactsVss.insert(-1, eastContact)
776
777 for layer in [METAL2, METAL3]:
778 self.createVertical(westContactsVss, vssAxis.getXMin(), powerWidth,
779 layer=layer)
780 self.createVertical(eastContactsVss, vssAxis.getXMax(), powerWidth,
781 layer=layer)
782
783 xcenter = vssAxis.getCenter().getX() - powerWidth / 2 - toDbU(5.0)
784 if False:
785 accessContactsVss = [
786 Contact.create(
787 vss,
788 VIA23,
789 xcenter,
790 vssAxis.getYMax(),
791 powerWidth,
792 powerWidth),
793 Contact.create(
794 vss,
795 METAL3,
796 xcenter,
797 toDbU(528.0),
798 powerWidth,
799 toDbU(2.0))]
800 northContactsVss = \
801 [westContactsVss[-1],
802 # accessContactsVss[0],
803 eastContactsVss[-1]
804 ]
805 southContactsVss = \
806 [westContactsVss[0], eastContactsVss[0]
807 ]
808
809 self.createHorizontal(
810 southContactsVss, vssAxis.getYMin(), powerWidth)
811 self.createHorizontal(
812 northContactsVss, vssAxis.getYMax(), powerWidth)
813 #self.createVertical(
814 # accessContactsVss, xcenter, powerWidth)
815 #for component in accessContactsVss[-1].getSlaveComponents():
816 #NetExternalComponents.setExternal(component)
817
818 ab.inflate(powerSpacing + powerWidth * 2 + toDbU(20.0))
819 self.setAbutmentBox(ab)
820
821 return
822
823 class Add(Ringed):
824
825 def build(self):
826 add(self.cell)
827 self.buildPower()
828
829
830 class Sub(Ringed):
831
832 def build(self):
833 sub(self.cell)
834 self.buildPower()
835
836
837 class AddSubPlace(Ringed):
838
839 def build(self):
840 self.alu_hier_place()
841
842 def alu_hier_place(self, **kw):
843
844 cell = self.cell
845 editor = None
846 if kw.has_key('editor') and kw['editor']:
847 editor = kw['editor']
848
849 db = DataBase.getDB()
850 print db, dir(db)
851 metal2 = DataBase.getDB().getTechnology().getLayer( 'metal2' )
852 metal3 = DataBase.getDB().getTechnology().getLayer( 'metal3' )
853
854 add = self.af.getCell( 'add', CRL.Catalog.State.Views )
855 sub = self.af.getCell( 'sub', CRL.Catalog.State.Views )
856 #cell = self.af.getCell( 'alu_hier', CRL.Catalog.State.Logical )
857 if not cell:
858 print '[ERROR] Unable to load cell "snx.vst", aborting .'
859 return False
860 kw[ 'cell' ] = cell
861
862 ab = Box( l( 0.0 )
863 , l( 0.0 )
864 , l( 850.0 )
865 , l( 700.0 ) )
866
867 #UpdateSession.open()
868 cell.setAbutmentBox( ab )
869
870 transf = (l(25.0), l(250.0), Transformation.Orientation.ID)
871 subi = self.createInstance("subckt_49_sub", sub, transf=transf)
872 print "sub place", subi
873
874 transf = (l(450.0), l(250.0), Transformation.Orientation.ID)
875 addi = self.createInstance("subckt_48_add", add, transf=transf)
876 print "add place", addi
877
878 if False:
879 for i in range(16):
880 Pin.create( cell.getNet('a(%d)' % i)
881 , 'a(%d).0' % i
882 , Pin.Direction.SOUTH
883 , Pin.PlacementStatus.FIXED
884 , metal3
885 , l( 100.0*i + 50.0 ) , l( 0.0 ) # Position.
886 , l( 2.0 ) , l( 2.0 ) # Size.
887 )
888 Pin.create( cell.getNet('b(%d)' % i)
889 , 'b(%d).0' % i
890 , Pin.Direction.SOUTH
891 , Pin.PlacementStatus.FIXED
892 , metal3
893 , l( 100.0*i + 50.0 ) , l( 0.0 ) # Position.
894 , l( 2.0 ) , l( 2.0 ) # Size.
895 )
896 Pin.create( cell.getNet('o(%d)' % i)
897 , 'o(%d).0' % i
898 , Pin.Direction.NORTH
899 , Pin.PlacementStatus.FIXED
900 , metal3
901 , l( 100.0*i + 25.0 ) , l( 0.0 ) # Position.
902 , l( 2.0 ) , l( 2.0 ) # Size.
903 )
904
905 Pin.create( cell.getNet('rst')
906 , 'p_reset.0'
907 , Pin.Direction.WEST
908 , Pin.PlacementStatus.FIXED
909 , metal2
910 , l( 0.0 )
911 , l( 140.0 )
912 , l( 2.0 )
913 , l( 2.0 )
914 )
915 #UpdateSession.close()
916
917 if editor: editor.setCell( cell )
918
919 print "editor", editor, dir(editor)
920
921 #self.af.saveCell( cell, CRL.Catalog.State.Views )
922 #plugins.RSavePlugin.ScriptMain( **kw )
923
924 return 0
925
926
927 class AddSubEtesian(Ringed):
928
929 def build(self):
930 self.alu_hier_route()
931
932 def alu_hier_route(self, **kw):
933
934 cell = self.cell
935 editor = None
936 if kw.has_key('editor') and kw['editor']:
937 editor = kw['editor']
938
939 db = DataBase.getDB()
940 print db, dir(db)
941 metal2 = DataBase.getDB().getTechnology().getLayer( 'metal2' )
942 metal3 = DataBase.getDB().getTechnology().getLayer( 'metal3' )
943
944 #cell = self.af.getCell( 'alu_hier', CRL.Catalog.State.Logical )
945 if not cell:
946 print '[ERROR] Unable to load cell "snx.vst", aborting .'
947 return False
948 kw[ 'cell' ] = cell
949
950 ab = Box( l( 0.0 )
951 , l( 0.0 )
952 , l( 850.0 )
953 , l( 175.0 ) )
954
955 cell.setAbutmentBox( ab )
956
957 if editor: editor.setCell( cell )
958
959 print "editor", editor, dir(editor)
960
961 success = 0
962
963 etesian = Etesian.EtesianEngine.create(cell)
964 etesian.place()
965
966 print "cell", cell, dir(cell)
967 c = cell.getComponents()
968 print "components", c, dir(c)
969 for child in cell.getInstances():
970 print "child", child
971
972 return success
973
974
975 class AddSubRoute(Ringed):
976
977 def build(self):
978 self.alu_hier_route()
979
980 def alu_hier_route(self, **kw):
981
982 cell = self.cell
983 editor = None
984 if kw.has_key('editor') and kw['editor']:
985 editor = kw['editor']
986
987 db = DataBase.getDB()
988 print db, dir(db)
989 metal2 = DataBase.getDB().getTechnology().getLayer( 'metal2' )
990 metal3 = DataBase.getDB().getTechnology().getLayer( 'metal3' )
991
992 #cell = self.af.getCell( 'alu_hier', CRL.Catalog.State.Logical )
993 if not cell:
994 print '[ERROR] Unable to load cell "snx.vst", aborting .'
995 return False
996 kw[ 'cell' ] = cell
997
998 ab = Box( l( 0.0 )
999 , l( 0.0 )
1000 , l( 850.0 )
1001 , l( 700.0 ) )
1002
1003 cell.setAbutmentBox( ab )
1004
1005 if editor: editor.setCell( cell )
1006
1007 print "editor", editor, dir(editor)
1008
1009 success = 0
1010
1011 if True:
1012 katana = Katana.KatanaEngine.create(cell)
1013 katana.digitalInit ()
1014 katana.runNegociatePreRouted()
1015 print dir(katana)
1016 katana.runGlobalRouter (0)
1017 katana.loadGlobalRouting ( Anabatic.EngineLoadGrByNet )
1018 katana.layerAssign ( Anabatic.EngineNoNetLayerAssign )
1019 katana.runNegociate ( Katana.Flags.NoFlags )
1020 katana.finalizeLayout ()
1021 print dir(katana)
1022 success = katana.getSuccessState()
1023 katana.destroy()
1024 success = 0
1025
1026 #self.af.saveCell( cell, CRL.Catalog.State.Views )
1027 #plugins.RSavePlugin.ScriptMain( **kw )
1028
1029 print "cell", cell, dir(cell)
1030 c = cell.getComponents()
1031 print "components", c, dir(c)
1032 for child in cell.getInstances():
1033 print "child", child
1034
1035 return success
1036
1037
1038
1039 def ScriptMain(**kw):
1040 #editor = None
1041 #if "editor" in kw and kw["editor"]:
1042 # editor = kw["editor"]
1043
1044 add = Add('add')
1045 add.save()
1046 sub = Sub('sub')
1047 sub.save()
1048 # create blank ap
1049 print ("Create alu_hier.ap")
1050 cell = af.getCell( "alu_hier", CRL.Catalog.State.Views )
1051 plugins.RSavePlugin.ScriptMain( cell=cell )
1052
1053 print ("copying alu_hier to altered")
1054 with open("alu_hier.ap") as f:
1055 x = f.read()
1056 x = x.replace("alu_hier", "alu_hier_altered")
1057 with open("alu_hier_altered.ap", "w") as f:
1058 f.write(x)
1059
1060 print ("AddSubEtesian")
1061 addsub = AddSubEtesian('alu_hier_altered', True, True)
1062 addsub.save()
1063
1064 print ("copying altered to alu_hier ")
1065 with open("alu_hier_altered.ap") as f:
1066 x = f.read()
1067 x = x.replace("alu_hier_altered", "alu_hier_altered2")
1068 with open("alu_hier_altered2.ap", "w") as f:
1069 f.write(x)
1070
1071 with open("alu_hier.vst") as f:
1072 x = f.read()
1073 x = x.replace("alu_hier", "alu_hier_altered2")
1074 with open("alu_hier_altered2.vst", "w") as f:
1075 f.write(x)
1076
1077 print ("AddSubPlace")
1078 addsub = AddSubPlace('alu_hier_altered2', True, True)
1079 addsub.save()
1080
1081 print ("AddSubRoute")
1082 addsub = AddSubRoute('alu_hier_altered2', True, True)
1083 addsub.save()
1084
1085 #if editor:
1086 # editor.setCell(ringo.getCell())
1087 # editor.fit()
1088 return True
1089
1090
1091 if __name__ == "__main__":
1092 ScriptMain()
1093 sys.exit(0)