def place ( self ): UpdateSession.open() center = self.area.getCenter() self.placeInstance( self.topBuffer, center.getX(), center.getY() ) trace( 550, '\rplace top level\n' ) self.usedVTracks += [ getRpBb(self.topBuffer, self.bufferIn).getCenter().getX() ] self.childs[0].place() UpdateSession.close() return
def _RSMTtoLayout(self, mst, net): for node in mst.nodes: if not node.component: x = node.realX if node.realX in self.usedVTracks: x += self.routingGauge.getLayerGauge( self.verticalDeepDepth).getPitch() # This is a Steiner point. node.component = self.createContact( net, x, node.y + self.cellGauge.getSliceHeight() / 2 - self.routingGauge.getLayerGauge( self.horizontalDeepDepth).getPitch(), GaugeConf.DeepDepth) trace( 550, '\tCreate (Steiner) node.component: @Y%d (y:%d - %d) %s\n' \ % (DbU.toLambda(node.realY) ,DbU.toLambda(node.y) ,DbU.toLambda(self.routingGauge.getLayerGauge(self.horizontalDeepDepth).getPitch()) ,node.component) ) else: # This a terminal (graph) point for edge in node.edges: flags = GaugeConf.HAccess | GaugeConf.DeepDepth if not edge.isHorizontal(): if node.isSame(edge.source) or edge.isVertical(): flags &= ~GaugeConf.HAccess break flags |= GaugeConf.OffsetTop1 if node.realX in self.usedVTracks: flags |= GaugeConf.OffsetRight1 node.component = self.rpAccess(node.component, flags) for edge in mst.edges: sourceContact = edge.source.component targetContact = edge.target.component if edge.isHorizontal(): self.createHorizontal(sourceContact, targetContact, targetContact.getY(), GaugeConf.DeepDepth) elif edge.isVertical(): self.createVertical(sourceContact, targetContact, sourceContact.getX(), GaugeConf.DeepDepth) else: turn = self.createContact(edge.source.component.getNet(), sourceContact.getX(), targetContact.getY(), GaugeConf.DeepDepth) self.createVertical(sourceContact, turn, sourceContact.getX(), GaugeConf.DeepDepth) self.createHorizontal(turn, targetContact, targetContact.getY(), GaugeConf.DeepDepth) return
def _createVertical ( self, source, target, x, flags ): if flags & GaugeConf.DeepDepth: depth = self._verticalDeepDepth else: depth = self._verticalDepth layer = self._routingGauge.getRoutingLayer(depth) if flags & GaugeConf.UseContactWidth: width = source.getBoundingBox(layer.getBasicLayer()).getWidth() else: width = self._routingGauge.getLayerGauge(depth).getWireWidth() if flags & GaugeConf.ExpandWidth: width += DbU.fromLambda( 1.0 ) segment = Vertical.create( source, target, layer, x, width ) trace( 550, segment ) return segment
def _getBufferIo(self): self.bufferCell = self.framework.getCell( Cfg.getParamString('clockTree.buffer').asString(), CRL.Catalog.State.Views) for net in self.bufferCell.getNets(): if not net.isExternal(): continue if net.isGlobal(): continue if net.getDirection() & Net.Direction.IN: self.bufferIn = net.getName() elif net.getDirection() & Net.Direction.OUT: self.bufferOut = net.getName() trace(550, '\tbufferIn :<%s>\n' % self.bufferIn) trace(550, '\tbufferOut:<%s>\n' % self.bufferOut) return
def connectLeafs ( self ): if not self.hasLeafs(): trace( 550, '\tHTreeNode.connectLeafs() %s has no leafs\n' % self.sourceBuffer.getName() ) if self.childs: self.childs[0].connectLeafs() self.childs[1].connectLeafs() self.childs[2].connectLeafs() self.childs[3].connectLeafs() return if len(self.blLeafs): self.topTree._connectLeafs( self.blBuffer, self.blLeafs ) if len(self.brLeafs): self.topTree._connectLeafs( self.brBuffer, self.brLeafs ) if len(self.tlLeafs): self.topTree._connectLeafs( self.tlBuffer, self.tlLeafs ) if len(self.trLeafs): self.topTree._connectLeafs( self.trBuffer, self.trLeafs ) return
def power_method(matrixA, initial_guess, tolerance, max_iterations): matrixA = numpy.array(matrixA) initial_guess = numpy.array(initial_guess) last_eigenvalue = 0 u = numpy.dot(matrixA, initial_guess) current_eigenvalue = u.item(0) u /= float(current_eigenvalue) initial_guess = u num_iterations = 1 while abs(current_eigenvalue - last_eigenvalue) > tolerance: last_eigenvalue = current_eigenvalue u = numpy.dot(matrixA, initial_guess) current_eigenvalue = u[0] initial_guess = u num_iterations += 1 if num_iterations > max_iterations: return None return { "eigenvalue": current_eigenvalue, "eigenvector": u, "#iterations": num_iterations, "trace(A)": trace(matrixA), "det(A)": determinant(matrixA) }
def _getBufferIo ( self ): self.bufferCell = self.framework.getCell( Cfg.getParamString('clockTree.buffer').asString() , CRL.Catalog.State.Views ) if not self.bufferCell: raise ErrorMessage( 3, [ 'ClockTree: Buffer cell "%s" not found in library,' \ % Cfg.getParamString('clockTree.buffer').asString() , ' please check the "clockTree.buffer" configuration parameter in "plugins.conf".' ] ) for net in self.bufferCell.getNets(): if not net.isExternal(): continue if net.isGlobal(): continue if net.getDirection() & Net.Direction.IN: self.bufferIn = net.getName() elif net.getDirection() & Net.Direction.OUT: self.bufferOut = net.getName() trace( 550, '\tbufferIn :<%s>\n' % self.bufferIn ) trace( 550, '\tbufferOut:<%s>\n' % self.bufferOut ) return
def place ( self ): trace( 550, '\rplace HTreeNode %s\n' % self.ckNet.getName() ) x = self.area.getXMin() + self.area.getWidth ()/4 y = self.area.getYMin() + self.area.getHeight()/4 halfWidth = self.area.getHalfWidth () halfHeight = self.area.getHalfHeight() self.topTree.placeInstance( self.blBuffer, x , y ) self.topTree.placeInstance( self.brBuffer, x+halfWidth, y ) self.topTree.placeInstance( self.tlBuffer, x , y+halfHeight ) self.topTree.placeInstance( self.trBuffer, x+halfWidth, y+halfHeight ) self.topTree.usedVTracks += \ [ self.topTree.rpAccessByPlugName( self.blBuffer, self.topTree.bufferIn, self.ckNet ).getX() , self.topTree.rpAccessByPlugName( self.brBuffer, self.topTree.bufferIn, self.ckNet ).getX() ] for child in self.childs: child.place() return
def _connectLeafs ( self, leafBuffer, leafs ): trace( 550, ',+', '\tBuffer <%s> has %i leafs.\n' % (leafBuffer.getName(),len(leafs)) ) #if len(leafs) == 0: return # #leafCk = getPlugByName(leafBuffer,self.bufferOut).getNet() #bufferRp = self.rpByPlugName( leafBuffer, self.bufferOut, leafCk ) # #rsmt = RSMT( leafCk.getName() ) #rsmt.addNode( bufferRp, bufferRp.getX(), self.toYCellGrid(bufferRp.getY()) ) #for leaf in leafs: # registerRp = self.rpByOccurrence( leaf, leafCk ) # rsmt.addNode( registerRp, registerRp.getX(), self.toYCellGrid(registerRp.getY()) ) # #rsmt.runI1S() #self._RSMTtoLayout( rsmt, leafCk ) trace( 550, '-' ) return
def connectLeaf(self): trace(550, '\tConnecting leafs.\n') UpdateSession.open() leafsByBuffer = {} hyperMasterClock = HyperNet.create(Occurrence(self.masterClock)) for plugOccurrence in hyperMasterClock.getLeafPlugOccurrences(): trace(550, '\tAdding leaf <%s>.\n' % plugOccurrence) position = plugOccurrence.getBoundingBox().getCenter() self.addLeaf(position, plugOccurrence) self.childs[0].connectLeafs() sys.stdout.flush() getPlugByName(self.topBuffer, self.bufferIn).setNet(self.masterClock) UpdateSession.close() return
def route ( self ): trace( 550, '\tHTreeNode.route() %s\n' % self.sourceBuffer.getName() ) leftSourceContact = self.topTree.rpAccessByPlugName( self.sourceBuffer, self.topTree.bufferOut, self.ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 ) rightSourceContact = self.topTree.rpAccessByPlugName( self.sourceBuffer, self.topTree.bufferOut, self.ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 ) blContact = self.topTree.rpAccessByPlugName( self.blBuffer , self.topTree.bufferIn , self.ckNet ) brContact = self.topTree.rpAccessByPlugName( self.brBuffer , self.topTree.bufferIn , self.ckNet ) tlContact = self.topTree.rpAccessByPlugName( self.tlBuffer , self.topTree.bufferIn , self.ckNet ) trContact = self.topTree.rpAccessByPlugName( self.trBuffer , self.topTree.bufferIn , self.ckNet ) leftContact = self.topTree.createContact( self.ckNet, blContact.getX(), leftSourceContact.getY() ) rightContact = self.topTree.createContact( self.ckNet, brContact.getX(), rightSourceContact.getY() ) self.topTree.createHorizontal( leftContact , leftSourceContact, leftSourceContact.getY() , 0 ) self.topTree.createHorizontal( rightSourceContact, rightContact , rightSourceContact.getY(), 0 ) self.topTree.createVertical ( leftContact , blContact , leftContact.getX() , 0 ) self.topTree.createVertical ( tlContact , leftContact , leftContact.getX() , 0 ) self.topTree.createVertical ( rightContact , brContact , rightContact.getX() , 0 ) self.topTree.createVertical ( trContact , rightContact , rightContact.getX() , 0 ) for child in self.childs: child.route() return
def connectPads ( self, padSide ): for terminal in padSide._powerContacts: #print ' Connect to [-%i] @%d' % (0, DbU.toLambda(self.getOuterRail(0).axis)) self.getOuterRail( 0 ).connect( terminal ) halfRails = (len(self._rails)-1)/2 trace( 550, 'halfRails:%i' % halfRails ) for terminal in padSide._powerContacts: trace( 550, ',+', '\tConnect pad terminal %s\n' % terminal ) for i in range(halfRails): trace( 550, '\tConnect to [-%i] @%d\n' % (i+1, DbU.toLambda(self.getOuterRail(i+1).axis)) ) self.getOuterRail(i+1).connect( terminal ) trace( 550, '-' ) return
def create ( conf, cell, clockNet, clockBox ): if clockBox.isEmpty(): raise ErrorMessage( 3, 'ClockTree: The clock area is empty.' ) aspectRatio = DbU.toLambda( clockBox.getWidth() ) / DbU.toLambda( clockBox.getHeight() ) if aspectRatio > 1.5 or aspectRatio < 0.5: raise ErrorMessage( 3, 'ClockTree: aspect ratio %f is disproportionate, must be between 0.5 and 1.5.' \ % aspectRatio ) ht = HTree( conf, cell, clockNet, clockBox ) print(' o Creating Clock H-Tree for <%s>.' % cell.getName()) ht.build() trace( 550, '\tht.build() OK\n' ) ht.place() trace( 550, '\tht.place() OK\n' ) #ht.route() print(' - H-Tree depth: %d' % ht.getTreeDepth()) trace( 550, '\tusedVTracks: %s\n' % str(ht.usedVTracks) ) return ht
def _rpAccess ( self, rp, flags ): trace( 550, ',+', '\t_rpAccess() %s\n' % str(rp) ) if flags & GaugeConf.DeepDepth: hdepth = self._horizontalDeepDepth vdepth = self._verticalDeepDepth else: hdepth = self._horizontalDepth vdepth = self._verticalDepth hpitch = self._routingGauge.getLayerGauge(hdepth).getPitch() hoffset = self._routingGauge.getLayerGauge(hdepth).getOffset() contact1 = Contact.create( rp, self._routingGauge.getContactLayer(0), 0, 0 ) midSliceY = contact1.getY() - (contact1.getY() % self._cellGauge.getSliceHeight()) \ + self._cellGauge.getSliceHeight() / 2 midTrackY = midSliceY - ((midSliceY - hoffset) % hpitch) dy = midSliceY - contact1.getY() if flags & GaugeConf.OffsetBottom1: dy += hpitch if flags & GaugeConf.OffsetTop1: dy -= hpitch contact1.setDy( dy ) trace( 550, contact1 ) if flags & GaugeConf.HAccess: stopDepth = hdepth else: stopDepth = vdepth for depth in range(1,stopDepth): xoffset = 0 if flags & GaugeConf.OffsetRight1 and depth == 1: xoffset = self._routingGauge.getLayerGauge(depth+1).getPitch() contact2 = Contact.create( rp.getNet() , self._routingGauge.getContactLayer(depth) , contact1.getX() + xoffset , contact1.getY() , self._routingGauge.getLayerGauge(depth).getViaWidth() , self._routingGauge.getLayerGauge(depth).getViaWidth() ) trace( 550, contact2 ) if self._routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal: segment = Horizontal.create( contact1 , contact2 , self._routingGauge.getRoutingLayer(depth) , contact1.getY() , self._routingGauge.getLayerGauge(depth).getWireWidth() ) trace( 550, segment ) else: segment = Vertical.create( contact1 , contact2 , self._routingGauge.getRoutingLayer(depth) , contact1.getX() , self._routingGauge.getLayerGauge(depth).getWireWidth() ) trace( 550, segment ) contact1 = contact2 trace( 550, '-' ) return contact1
def showNodes ( level, nodes ): for node in nodes: trace( level, node ) return
def runI1S ( self ): self._edges = [ ] self._length = 0 if len(self._nodes) < 2: return if len(self._nodes) == 2: self._edges.append( Edge( self._nodes[0], self._nodes[1] ) ) self._length = self._edges[0].length return self._computeHanan() count = 0 trace( 550, '++' ) minMST = RMST( 'MST[%i]' % count ) minMST.setNodes( self._nodes ) minMST.runPrim() trace( 550, '-,+', '\tInitial %s length %d\n' % (minMST.name,DbU.toLambda(len(minMST))) ) minMST.showEdges( 550 ) trace( 550, '-' ) addedSteiner = True while addedSteiner: addedSteiner = False for steinerNode in self._hananNodes: count += 1 trace( 550, '\tTrying with Steiner point H:%d,%d\n' \ % (DbU.toLambda(steinerNode.x),DbU.toLambda(steinerNode.y)) ) mst = RMST( 'MST[%i]' % count ) mst.setNodes( self._nodes ) mst.copyNode( steinerNode ) mst.runPrim() trace( 550, '\tCurrent %s length %d\n' % (mst.name,DbU.toLambda(len(mst))) ) mst.showEdges( 550 ) if len(mst) < len(minMST): trace( 550, '\tAccept min RST.\n' ) minMST = mst addedSteiner = True if addedSteiner: self.copyNode( minMST.nodes[-1] ) self.nodes[-1].setFlags( Node.KeepPoint ) i = 0 while i < len(self._edges): if self._nodes[i].flags & Node.SteinerPoint \ and self._nodes[i].degree < 3: trace( 550, 'Deleting unused Steiner point H:%d,%d' \ % (DbU.toLambda(self._nodes[i].x),DbU.toLambda(self._nodes[i].y)) ) del self._nodes[i] else: i += 1 self._nodes = minMST.nodes self._edges = minMST.edges self._length = minMST.length trace( 550, '-' ) return
def addNode ( self, component, x, y ): node = Graph.addNode( self, component, x, y ) trace( 550, '\t New Node: %s\n' % node ) return
def _computeHanan ( self ): xs = [ ] ys = [ ] realYs = { } for node in self._nodes: if not node.x in xs: xs.append( node.x ) if not node.y in xs: ys.append( node.y ) realYs[ node.y ] = node.component.getY() xs.sort() ys.sort() trace( 550, '+,+', '\tHanan matrix: %ix%i' % (len(xs),len(ys)) ) self._hananNodes = [ ] for x in xs: trace( 550, '\n' ) trace( 550, '\t' ) for y in ys: isNode = False for node in self._nodes: if node.x == x and node.y == y: isNode = True if isNode: trace( 550, ' -:%04.2d,%04.2d' % (DbU.toLambda(x),DbU.toLambda(y)) ) continue trace( 550, ' H:%04.2d,%04.2d' % (DbU.toLambda(x),DbU.toLambda(y)) ) self._hananNodes.append( Node( None, x, y ) ) self._hananNodes[-1].realY = realYs[ y ] trace( 550, ',--', "\n" ) return
def runPrim ( self ): self._edges = [ ] self._length = 0 if len(self._nodes) < 2: return if len(self._nodes) == 2: self._edges.append( Edge( self._nodes[0], self._nodes[1] ) ) self._length = self._edges[0].length return trace(500, '+') toReach = [ ] self._nodes[0]._distance = 0 for node in self._nodes[1:]: node.update( self._nodes[0] ) toReach.append( node ) toReach.sort() trace( 500, '+' , '\tPrim (initial stack)\n' ) trace( 500, '+,+', '\tS %s\n' % self._nodes[0] ) Node.showNodes( 500, toReach ) trace( 500, '---' ) while len(toReach): nearest = toReach.pop(0) self._edges.append( Edge( nearest, nearest.back ) ) trace( 500, '++,--', '\tAdding %s\n' % self._edges[-1] ) for node in toReach: node.update( nearest ) toReach.sort() trace( 500, '+' , '\tPrim (current stack)\n' ) trace( 500, '+,+', '\tS %s\n' % self._nodes[0] ) Node.showNodes( 500, toReach ) trace( 500, '---' ) for edge in self._edges: self._length += edge.length trace( 500, '-' ) return
def showEdges ( self, level ): trace( level, '+,+', '\tGraph Edges:\n' ) for edge in self._edges: trace( level, edge ) trace(level, '--') return
def showNodes ( self, level ): trace( level, '+,+', '\tGraph Nodes:\n' ) for node in self._nodes: trace( level, node ) trace(level, '--') return
def connect ( self, contact ): contactBb = contact.getBoundingBox() if contactBb.getYMin() < self.side.innerBb.getYMin() \ or contactBb.getYMax() > self.side.innerBb.getYMax(): raise ErrorMessage( 1, [ '%s is outside rail/corona Y range' % str(contact) , 'power pad is likely to be to far off north or south.' , '(corona:%s)' % str(self.side.innerBb) ] ) #if self.net != contact.getNet(): return False if contact.getY() in self.vias: return False trace( 550, ',+', '\tVerticalRail.connect() [%s] @%d\n' % (self.order,DbU.toLambda(self.axis)) ) trace( 550, contact ) keys = list(self.vias.keys()) keys.sort() insertIndex = bisect.bisect_left( keys, contact.getY() ) trace( 550, ',+', '\tkeys:' ) for key in keys: trace( 550, ' %d' % DbU.toLambda(key) ) trace( 550, '\n' ) if len(keys) > 0: if insertIndex < len(keys): insertPosition = keys[ insertIndex ] trace( 550, '\tinsertIndex:%d' % insertIndex ) trace( 550, '\tCheck NEXT contactBb:%s via:%s\n' \ % ( contactBb , self.vias[insertPosition][2].getBoundingBox()) ) if contactBb.getYMax() >= self.vias[insertPosition][2].getBoundingBox().getYMin(): trace( 550, ',--', '\tReject %s intersect NEXT\n' % contact ) return False if insertIndex > 0: trace( 550, '\tcheck PREVIOUS contactBb:%s via:%s\n' \ % ( contactBb , self.vias[keys[insertIndex-1]][2].getBoundingBox()) ) if self.vias[keys[insertIndex-1]][2].getBoundingBox().getYMax() >= contactBb.getYMin(): trace( 550, ',--', '\tReject %s intersect PREVIOUS\n' % contact ) return False self.vias[ contact.getY() ] = [ contact.getY() , StackedVia( self.net , self.side.getLayerDepth(self.side.getVLayer()) , self.axis , contact.getY() , self.side.vRailWidth - DbU.fromLambda(1.0) , contact.getHeight() - DbU.fromLambda(1.0) ) , contact ] trace(550, ',--' '\tADD %s\n' % contact ) self.vias[ contact.getY() ][1].mergeDepth( self.side.getLayerDepth(contact.getLayer()) ) return True
def _createPowerContacts(self, pad, net): if self._type == chip.North or self._type == chip.South: hvDepth = self._corona.padVDepth elif self._type == chip.East or self._type == chip.West: hvDepth = self._corona.padHDepth trace(550, ',+', '\t_createPowerContacts() for %s\n' % net.getName()) components = None masterCell = pad.getMasterCell() trace(550, '\tLooking for global net %s\n' % net.getName()) for plug in net.getPlugs(): if plug.getInstance() == pad: trace(550, '\tFound Plug on %s\n' % pad) components = plug.getMasterNet().getExternalComponents() if not components: masterNet = masterCell.getNet(net.getName()) if masterNet: components = masterCell.getNet( net.getName()).getExternalComponents() if not components: raise ErrorMessage(1, [ 'PadsCorona.Side._createPowerContact():', 'Pad model <%s> of instance <%s> neither have global net <%s>' % (pad.getName(), masterCell.getName(), net.getName()), 'for implicit connection nor is it explicitly connected.', 'The power/clock nets *names* in the chip must match those of the pads models.' ]) connecteds = False trace(550, '\t %s\n' % str(masterCell.getAbutmentBox())) for component in components: if component.getBoundingBox().getYMin( ) > masterCell.getAbutmentBox().getYMin(): continue if self._corona.routingGauge.getLayerDepth( component.getLayer()) != hvDepth: continue if not isinstance(component, Vertical): continue if self._type == chip.North or self._type == chip.South: width = component.getWidth() height = 0 else: width = 0 height = component.getWidth() position = Point(component.getX(), masterCell.getAbutmentBox().getYMin()) pad.getTransformation().applyOn(position) connecteds = True self._powerContacts.append( Contact.create(net, component.getLayer(), position.getX(), position.getY(), width, height)) if not connecteds: print WarningMessage( 'Cannot find a suitable connector for <%s> on pad <%s>' % (net.getName(), pad.getName())) trace(550, '-') return