def __init__(self, conf, cell, clockNet, area): GaugeConfWrapper.__init__(self, conf.gaugeConf) self.minSide = DbU.fromLambda( Cfg.getParamInt('clockTree.minimumSide').asInt()) if self.minSide < DbU.fromLambda(100.0): raise ErrorMessage( 3, 'ClockTree: clockTree.minimumSide (%g) is less than 100 lambda.' \ % DbU.toLambda(self.minSide) ) self.framework = CRL.AllianceFramework.get() self.cell = cell self.area = area self.childs = [] self._getBufferIo() self.tieCell = self.framework.getCell('rowend_x0', CRL.Catalog.State.Views) self.cellGauge = self.framework.getCellGauge() self.topBuffer = Instance.create(self.cell, 'ck_htree', self.bufferCell) self.cloneds = [self.cell] self.usedVTracks = [] self._feedCount = 0 self.masterClock = clockNet if not self.masterClock: for net in cell.getNets(): if net.isClock(): self.masterClock = net break if not self.masterClock: print '[WARNING] Cell %s has no clock net.' % cell.getName() self._createChildNet(self.topBuffer, 'ck_htree') return
def loadCellGaugesTable(cellGaugesTable, fromFile): global allianceFile allianceFile = fromFile af = AllianceFramework.get() for gaugeName in cellGaugesTable.keys(): gaugeDatas = cellGaugesTable[gaugeName] gauge = None try: if len(gaugeDatas) != 4: raise ErrorMessage(1, [ 'Malformed gaugeDatas in <cellGaugesTable[%s]>.' % gaugeName, 'Parameters list must have exactly four fields:', ' (terminal_metal, xy_common_pitch, slice_height, slice_step)', str(gaugeDatas) ]) gauge = CellGauge.create( gaugeName, gaugeDatas[0] # pinLayerName. , DbU.fromLambda(gaugeDatas[1]) # pitch. , DbU.fromLambda(gaugeDatas[2]) # sliceHeight. , DbU.fromLambda(gaugeDatas[3]) # sliceStep. ) except Exception, e: ErrorMessage.wrapPrint( e, 'In %s:<cellGaugesTable> at index %d.' % (allianceFile, gaugeDatasNo)) if gauge: af.addCellGauge(gauge)
def __str__ ( self ): return '<Edge S:%d,%d T:%d,%d len:%d>' % ( DbU.toLambda(self.source.x) , DbU.toLambda(self.source.y) , DbU.toLambda(self.target.x) , DbU.toLambda(self.target.y) , DbU.toLambda(self.length) )
def ScriptMain(cell=None): editor = None if globals().has_key('__editor'): print ' o Editor detected, running in graphic mode.' editor = __editor Cfg.Configuration.pushDefaultPriority(Cfg.Parameter.Priority.CommandLine) Cfg.getParamBool('misc.verboseLevel1').setBool(True) Cfg.getParamBool('misc.verboseLevel2').setBool(True) Cfg.Configuration.popDefaultPriority() errorCode = 0 framework = CRL.AllianceFramework.get() padHeight = DbU.fromLambda(400) # TODO padWidth = DbU.fromLambda(200) # TODO coreSide = DbU.fromLambda(1450) # TODO # Cell must be loaded *before* opening the UpdateSession. print ' o Placing <coeur>.' modelCoeur = framework.getCell('coeur', CRL.Catalog.State.Logical) UpdateSession.open() try: modelCoeur.setAbutmentBox( Hurricane.Box(DbU.fromLambda(0), DbU.fromLambda(0), coreSide, coreSide)) # Cannot place a rail if at least one instance is placed. # (to compute the orientation of the cells rows) #placeandroute.pyAlimVerticalRail( modelCoeur, coreSide/DbU.fromLambda(5.0*2) ) except Exception, e: print e errorCode = 1
def ScriptMain ( cell=None ): editor = None if globals().has_key('__editor'): print ' o Editor detected, running in graphic mode.' editor = __editor Cfg.Configuration.pushDefaultPriority(Cfg.Parameter.Priority.CommandLine) Cfg.getParamBool('misc.verboseLevel1').setBool(True) Cfg.getParamBool('misc.verboseLevel2').setBool(True) Cfg.Configuration.popDefaultPriority() errorCode = 0 framework = CRL.AllianceFramework.get() padHeight = DbU.fromLambda(400) # TODO padWidth = DbU.fromLambda(200) # TODO coreSide = DbU.fromLambda(1500) # TODO # Cell must be loaded *before* opening the UpdateSession. print ' o Placing <coeur>.' modelCoeur = framework.getCell('coeur',CRL.Catalog.State.Logical) UpdateSession.open() try: modelCoeur.setAbutmentBox( Hurricane.Box( DbU.fromLambda(0) , DbU.fromLambda(0) , coreSide , coreSide ) ) # Cannot place a rail if at least one instance is placed. # (to compute the orientation of the cells rows) #placeandroute.pyAlimVerticalRail( modelCoeur, coreSide/DbU.fromLambda(5.0*2) ) except Exception, e: print e; errorCode = 1
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 __init__(self, block): #if not isinstance(block,plugins.chip.BlockPower.Block): # raise ErrorMessage( 1, 'Attempt to create a Corona on a non-Block object.' ) self._railsNb = Cfg.getParamInt('chip.block.rails.count').asInt() self._hRailWidth = DbU.fromLambda( Cfg.getParamInt('chip.block.rails.hWidth').asInt()) self._vRailWidth = DbU.fromLambda( Cfg.getParamInt('chip.block.rails.vWidth').asInt()) self._hRailSpace = DbU.fromLambda( Cfg.getParamInt('chip.block.rails.hSpacing').asInt()) self._vRailSpace = DbU.fromLambda( Cfg.getParamInt('chip.block.rails.vSpacing').asInt()) self._block = block self._innerBb = self._block.bb self._block.path.getTransformation().applyOn(self._innerBb) self._innerBb.inflate(self._hRailSpace / 2, self._vRailSpace / 2) if not self.useClockTree: self._railsNb -= 1 self._southSide = SouthSide(self) self._northSide = NorthSide(self) self._westSide = WestSide(self) self._eastSide = EastSide(self) return
def __str__ ( self ): return '<Node P:%d,%d (realY:%d) d:%d %s>' % ( DbU.toLambda(self.x) , DbU.toLambda(self.y) , DbU.toLambda(self.realY) , DbU.toLambda(self.distance) , str(self.component) )
def loadRoutingGaugesTable(routingGaugesTable, fromFile): global allianceFile allianceFile = fromFile af = AllianceFramework.get() for gaugeName in routingGaugesTable.keys(): gaugeDatas = routingGaugesTable[gaugeName] technology = DataBase.getDB().getTechnology() gauge = RoutingGauge.create(gaugeName) entryNo = 0 for entry in gaugeDatas: entryNo += 1 try: if len(entry) != 2: raise ErrorMessage(1, [ 'Malformed entry in <routingGaugesTable[%s]>.' % gaugeName, 'Must have exactly two fields ("METAL_LAYER", (parameters_list)).', str(entry) ]) if len(entry[1]) != 8: raise ErrorMessage(1, [ 'Malformed entry in <routingGaugesTable[%s]>.' % gaugeName, 'Parameters list must have exactly eight fields:', ' (direction, type, depth, density, offset, pitch, wire_width, via_width)', str(entry) ]) gauge.addLayerGauge( RoutingLayerGauge.create( technology.getLayer(entry[0]), Gauge.toRlGauge(entry[1][0]) # Direction. , Gauge.toRlGauge(entry[1][1]) # Type. , entry[1][2] # Depth. , entry[1][3] # Density. , DbU.fromLambda(entry[1][4]) # Offset. , DbU.fromLambda(entry[1][5]) # Pitch. , DbU.fromLambda(entry[1][6]) # Wire width. , DbU.fromLambda(entry[1][7]) # Via width. )) except Exception, e: ErrorMessage.wrapPrint( e, 'In %s:<routingGaugesTable> at index %d.' % (allianceFile, entryNo)) af.addRoutingGauge(gauge)
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 self.vias.has_key(contact.getY()): return False trace( 550, ',+', '\tVerticalRail.connect() [%s] @%d\n' % (self.order, DbU.toLambda(self.axis))) trace(550, contact) keys = 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 loadViewerConfig ( viewerConfig, confFile ): global symbolicFile symbolicFile = confFile try: if 'precision' in viewerConfig: DbU.setPrecision(viewerConfig['precision']) except Exception as e: ErrorMessage.wrapPrint(e,'In %s:<viewerConfig>.') return
def loadViewerConfig(viewerConfig, confFile): global symbolicFile symbolicFile = confFile try: if viewerConfig.has_key('precision'): DbU.setPrecision(viewerConfig['precision']) except Exception, e: ErrorMessage.wrapPrint(e, 'In %s:<viewerConfig>.')
def _readChipSize( chipConfigDict ): if 'chip.size' not in chipConfigDict: return Box() chipSize = chipConfigDict['chip.size'] if not isinstance(chipSize,tuple): print(ErrorMessage( 1, 'The Chip size parameter is *not* a tuple.' )) return Box() if len(chipSize) != 2: print(ErrorMessage( 1, 'The Chip size parameter is *not* a tuple of exactly two items.' )) return Box() return Box( 0, 0, DbU.fromLambda(chipSize[0]), DbU.fromLambda(chipSize[1]) )
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 _readCoreSize(chipConfigDict): if not chipConfigDict.has_key('core.size'): print ErrorMessage(1, 'The Core size parameter is missing.') return Box() coreSize = chipConfigDict['core.size'] if not isinstance(coreSize, tuple): print ErrorMessage(1, 'The Core size parameter is *not* a tuple.') return Box() if len(coreSize) != 2: print ErrorMessage( 1, 'The Core size parameter is *not* a tuple of exactly two items.' ) return Box() return Box(0, 0, DbU.fromLambda(coreSize[0]), DbU.fromLambda(coreSize[1]))
def Layout ( self ): print 'Cordic_Net.Layout()' Place( self.instances['dp'], NOSYM, XY( 0, 0 ) ) ResizeAb( 0, 0, 0, DbU.fromLambda( 100.0 ) ) return
def doLayout ( self ): if self.side == chip.West: width = 0 x = self.block.bb.getXMin() elif self.side == chip.East: width = 0 x = self.block.bb.getXMax() elif self.side == chip.South: height = 0 y = self.block.bb.getYMin() elif self.side == chip.North: height = 0 y = self.block.bb.getYMax() minWidth = DbU.fromLambda( 6.0 ) for terminal in self.terminals: if self.side == chip.West or self.side == chip.East: center = Point( x, terminal[0].getCenter() ) height = terminal[0].getSize() - self.deltaWidth if height < minWidth: height = minWidth elif self.side == chip.North or self.side == chip.South: center = Point( terminal[0].getCenter(), y ) width = terminal[0].getSize() - self.deltaWidth if width < minWidth: width = minWidth self.block.path.getTransformation().applyOn( center ) contact = Contact.create( self.net, self.metal, center.getX(), center.getY(), width, height ) terminal[ 1 ] = contact 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 loadTechnoConfig ( technoConfig, confFile ): realFile = confFile technology = DataBase.getDB().getTechnology() gridValue = 1 gridUnit = DbU.UnitPowerMicro for key in [ 'gridUnit', 'gridValue', 'gridsPerLambda' ]: try: if key == 'gridUnit': if key in technoConfig: gridUnit = technoConfig[key] if gridUnit != DbU.UnitPowerPico and \ gridUnit != DbU.UnitPowerNano and \ gridUnit != DbU.UnitPowerMicro and \ gridUnit != DbU.UnitPowerMilli and \ gridUnit != DbU.UnitPowerUnity and \ gridUnit != DbU.UnitPowerKilo: raise ErrorMessage(1,'In <technoConfig>, invalid DbU unit power for gridUnit, reseting to Micro.') else: raise ErrorMessage(1,'<technoConfig> has no <gridUnit> defined, assuming Micro.') elif key == 'gridValue': if 'gridValue' in technoConfig: gridValue = technoConfig['gridValue'] if not isinstance(gridUnit,float) and not isinstance(gridUnit,int): raise ErrorMessage(1,['In <technoConfig>, <gridValue> must be of type float (and not: %s).' % helpers.stype(gridValue) ]) DbU.setPhysicalsPerGrid(gridValue,gridUnit) else: raise ErrorMessage(1,'<technoConfig> has no <gridValue> defined.') elif key == 'gridsPerLambda': if 'gridsPerLambda' in technoConfig: gridsPerLambda = technoConfig['gridsPerLambda'] if not isinstance(gridsPerLambda,int): raise ErrorMessage(1,['In <technoConfig>, <gridsPerLambda> must be of type int (and not: %s).' % helpers.stype(gridsPerLambda) ]) DbU.setGridsPerLambda(gridsPerLambda) except Exception as e: ErrorMessage.wrapPrint(e) return
def connect(self, contact): contactBb = contact.getBoundingBox() if contactBb.getXMin() < self.side.innerBb.getXMin() \ or contactBb.getXMax() > self.side.innerBb.getXMax(): raise ErrorMessage(1, [ '%s is outside rail/corona X range,' % str(contact), 'power pad is likely to be to far off west or east.', '(corona:%s)' % str(self.side.innerBb) ]) #print ' HorizontalRail.connect() net:%s contact:%s' % (self.net.getName(),str(contact)) #if self.net != contact.getNet(): return False if self.vias.has_key(contact.getX()): return False keys = self.vias.keys() keys.sort() insertIndex = bisect.bisect_left(keys, contact.getX()) if len(keys) > 0: if insertIndex < len(keys): insertPosition = keys[insertIndex] if contactBb.getXMax( ) >= self.vias[insertPosition][2].getBoundingBox().getXMin(): #print 'Reject contact %s intersect NEXT' % str(contact) return False if insertIndex > 0: if self.vias[keys[insertIndex - 1]][2].getBoundingBox( ).getXMax() >= contactBb.getXMin(): #print 'Reject contact %s intersect PREVIOUS' % str(contact) return False self.vias[contact.getX()] = [ contact.getX(), StackedVia(self.net, self.side.getLayerDepth(self.side.getHLayer()), contact.getX(), self.axis, contact.getWidth() - DbU.fromLambda(1.0), self.side.hRailWidth - DbU.fromLambda(1.0)), contact ] #print ' ADD contact @ [%d %d]' % (DbU.toLambda(contact.getX()), DbU.toLambda(self.axis)) self.vias[contact.getX()][1].mergeDepth( self.side.getLayerDepth(contact.getLayer())) return True
def loadSymbolicRules ( symbolicRulesTable, confFile ): global symbolicFile symbolicFile = confFile technology = DataBase.getDB().getTechnology() entryNo = 0 for rule in symbolicRulesTable: entryNo += 1 try: if len(rule) != 2: raise ErrorMessage(1,['Malformed entry in <symbolicRulesTable>.' ,'Must contains exactly two fields: ( rule_path, value ).' ,str(rule) ]) if not isinstance(rule[1],int) and not isinstance(rule[1],float): raise ErrorMessage(1,['Invalid entry in <symbolicRulesTable>.' ,'Rule value must be of integer or float type.' ,str(rule) ]) value = DbU.fromLambda(rule[1]) elements = rule[0].split('.') if len(elements) < 3: raise ErrorMessage(1,['Invalid entry in <symbolicRulesTable>.' ,'Rule name must contains at least three components: \"LAYER.category.dimension\".' ,str(rule) ]) ruleLayer = layersLUT.lookup( elements[0], LayersLUT.Symbolic|LayersLUT.MissingError ) subLayer = layersLUT.lookup( elements[1], LayersLUT.Real ) if subLayer: ruleTag = ".".join(elements[2:]) else: ruleTag = ".".join(elements[1:]) if ruleTag == 'extention.cap': ruleLayer.setExtentionCap ( subLayer, value ) elif ruleTag == 'extention.width': ruleLayer.setExtentionWidth( subLayer, value ) elif ruleTag == 'enclosure': ruleLayer.setEnclosure ( subLayer, value ) elif ruleTag == 'minimum.width': ruleLayer.setMinimalSize ( value ) elif ruleTag == 'minimum.side': ruleLayer.setMinimalSize ( value ) else: raise ErrorMessage(1,['Invalid entry in <symbolicRulesTable>.' ,'Unknown rule kind: \".%s\", should be any of:' % ruleTag ,' * "RULE_HEAD.extention.cap"' ,' * "RULE_HEAD.extention.width"' ,' * "RULE_HEAD.enclosure"' ,' * "RULE_HEAD.minimum.width"' ,' * "RULE_HEAD.minimum.side"' ,str(rule) ]) except Exception as e: ErrorMessage.wrapPrint(e,'In %s:<symbolicRulesTable> at index %d.' % (symbolicFile,entryNo)) return
def computeAbutmentBox(cell, spaceMargin, aspectRatio, cellGauge): sliceHeight = DbU.toLambda(cellGauge.getSliceHeight()) instancesNb = 0 cellLength = 0 for occurrence in cell.getLeafInstanceOccurrences(): instance = occurrence.getEntity() instancesNb += 1 cellLength += int( DbU.toLambda(instance.getMasterCell().getAbutmentBox().getWidth())) # ar = x/y S = x*y = spaceMargin*SH x=S/y ar = S/y^2 # y = sqrt(S/AR) gcellLength = float(cellLength) * (1 + spaceMargin) / sliceHeight rows = math.sqrt(gcellLength / aspectRatio) if math.trunc(rows) != rows: rows = math.trunc(rows) + 1 else: rows = math.trunc(rows) columns = gcellLength / rows if math.trunc(columns) != columns: columns = math.trunc(columns) + 1 else: columns = math.trunc(columns) print ' o Creating abutment box (margin:%.1f%%, aspect ratio:%.1f%%, g-length:%.1fl)' \ % (spaceMargin*100.0,aspectRatio*100.0,(cellLength/sliceHeight)) print ' - GCell grid: [%dx%d]' % (columns, rows) UpdateSession.open() abutmentBox = Box(DbU.fromLambda(0), DbU.fromLambda(0), DbU.fromLambda(columns * sliceHeight), DbU.fromLambda(rows * sliceHeight)) cell.setAbutmentBox(abutmentBox) UpdateSession.close() return abutmentBox
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 __init__ ( self, component, x, y, flags=0 ): self._component = component self._edges = [ ] self._x = x self._y = y self._realY = y self._back = None self._distance = DbU.fromLambda(1000.0) self._flags = flags if component: self._flags = self._flags|Node.GraphPoint|Node.KeepPoint else: self._flags = self._flags|Node.SteinerPoint 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 _check(self, checkSize, checkName): sideName = 'unknown' chipSize = 0 if self._type == chip.North or self._type == chip.South: chipSize = self._corona.chipSize.getWidth() sideName = 'wide' elif self._type == chip.East or self._type == chip.West: chipSize = self._corona.chipSize.getHeight() sideName = 'tall' if checkSize > chipSize: sliceHeight = self._corona.getSliceHeight() if checkSize % sliceHeight != 0: checkSize += sliceHeight - (checkSize % sliceHeight) print ErrorMessage(1, [ 'Chip is not %s enought to accomodate the %s,' % (sideName, checkName), 'needs %dl, but only has %dl.' % (DbU.toLambda(checkSize), DbU.toLambda(chipSize)) ]) return False return True
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
# For the geometrical modifications to be taken into account, we must # close this UpdateSession now. So the chip will see the core correctly. UpdateSession.close() if errorCode: sys.exit(errorCode) print ' o Placing <chip>.' amd2901 = framework.getCell('amd2901',CRL.Catalog.State.Logical) if editor: editor.setCell(amd2901) UpdateSession.open() try: chipSide = 11*padWidth + 2*padHeight # TODO: Le chip est carre, avec 11 plots par face. abutmentBoxChip = Hurricane.Box( DbU.fromLambda(0.0) , DbU.fromLambda(0.0) , chipSide , chipSide ) amd2901.setAbutmentBox( abutmentBoxChip ) instanceCoeur = amd2901.getInstance( 'core' ) instanceCoeur.setTransformation(Hurricane.Transformation( (chipSide-coreSide)/2 , (chipSide-coreSide)/2 , Hurricane.OrientationID ) ) instanceCoeur.setPlacementStatus( Hurricane.PlacementStatusPLACED ) # TODO: Placing pads southPads = ['p_d0','p_d1','p_d2','p_d3','p_vsseck0','p_vsseck1','p_vssick0','p_y0','p_y1','p_y2','p_y3'] eastPads = ['p_cout','p_r3','p_q3','p_ng','p_np','p_vddick0','p_ovr','p_zero','p_noe','p_ck','p_f3']
def __init__ ( self, chipConfigDict, cell, viewer=None ): if not isinstance(chipConfigDict,dict): raise ErrorMessage( 1, 'The "chip" variable is not a dictionnary.' ) self._validated = True self._cell = cell self._viewer = viewer # Block Corona parameters. self._railsNb = getParameter('chip','chip.block.rails.count').asInt() self._hRailWidth = DbU.fromLambda( getParameter('chip','chip.block.rails.hWidth' ).asInt() ) self._vRailWidth = DbU.fromLambda( getParameter('chip','chip.block.rails.vWidth' ).asInt() ) self._hRailSpace = DbU.fromLambda( getParameter('chip','chip.block.rails.hSpacing').asInt() ) self._vRailSpace = DbU.fromLambda( getParameter('chip','chip.block.rails.vSpacing').asInt() ) # Global Pad names. self._pckName = getParameter('chip', 'chip.pad.pck' ).asString() self._pvddickName = getParameter('chip', 'chip.pad.pvddick').asString() self._pvssickName = getParameter('chip', 'chip.pad.pvssick').asString() self._pvddeckName = getParameter('chip', 'chip.pad.pvddeck').asString() self._pvsseckName = getParameter('chip', 'chip.pad.pvsseck').asString() # Global Net names. self._vddeName = "vdde" self._vddiName = "vddi" self._vsseName = "vsse" self._vssiName = "vssi" self._ckiName = "ck" self._ckoName = "cko" self._ckName = "pad" self._blockageName = "blockagenet" # Global Nets. self._vdde = None self._vddi = None self._vsse = None self._vssi = None self._cki = None self._cko = None self._ck = None self._blockageNet = None self._clockPad = None self._powerPad = None self._cores = [] self._southPads = self._readPads( chipConfigDict, 'pads.south' ) self._northPads = self._readPads( chipConfigDict, 'pads.north' ) self._eastPads = self._readPads( chipConfigDict, 'pads.east' ) self._westPads = self._readPads( chipConfigDict, 'pads.west' ) self._coreSize = ChipConf._readCoreSize( chipConfigDict ) self._chipSize = ChipConf._readChipSize( chipConfigDict ) self._padWidth = 0 self._padHeight = 0 self._useClockTree = ChipConf._readClockTree( chipConfigDict ) minHCorona = self._railsNb*(self._hRailWidth + self._hRailSpace) + self._hRailSpace minVCorona = self._railsNb*(self._vRailWidth + self._vRailSpace) + self._vRailSpace if minHCorona > minVCorona: self._minCorona = minHCorona*2 else: self._minCorona = minVCorona*2 self.checkPads() self.computeChipSize() self.checkChipSize() self.findPowerAndClockNets() return
def Alliance(db): print('\n') print('===========================================================') print('Checking DbU.') print('DbU.fromLamdba(5) :', DbU.fromLambda(5)) print('DbU.toLamdba(12000) :', DbU.toLambda(12000)) print('===========================================================') print('Checking LayerMask.') mask0 = Layer.Mask(0b000101) mask1 = Layer.Mask(0b001110) mask3 = mask0 & mask1 mask4 = mask0 | mask1 print('mask0 :', mask0) print('mask1 :', mask1) print('mask0 & mask1 :', mask3) print('mask0 | mask1 :', mask4) print('mask0.containts(mask1):', mask0.contains(mask1)) print('===========================================================') print('Checking DataBase.') db2 = db.getTechnology().getDataBase() if db == db2: print("OK DataBase is unique.") else: print("KO DATABASE IS DUPLICATED!") print('===========================================================') print("Checking layers.") technology = db.getTechnology() rlayer = technology.getLayer('METAL2') print("METAL2") print(" Minimal size :", DbU.toLambda(rlayer.getMinimalSize())) print(" Minimal spacing :", DbU.toLambda(rlayer.getMinimalSpacing())) print(" Pitch :", DbU.toLambda(rlayer.getPitch())) print(" Cut above :", rlayer.getCutAbove()) print(" isWorking :", rlayer.isWorking()) dlayer = technology.getLayer('NDIF') print('NDIF', dlayer.getMask()) for blayer in dlayer.getBasicLayers(): print(' ', blayer) tlayer = technology.getLayer('NTRANS') print('NTRANS', tlayer.getMask()) for blayer in tlayer.getBasicLayers(): print(' ', blayer) clayer = technology.getLayer('CONT_DIF_N') print('CONT_DIF_N', clayer.getMask()) for blayer in clayer.getBasicLayers(): print(' ', blayer) print('===========================================================') print('Checking RoutingGauge.') layer = technology.getLayer('METAL3') rg = AllianceFramework.get().getRoutingGauge() print('rg.getName() :', rg.getName()) print('rg.getDepth() :', rg.getDepth()) print('rg.getLayerDepth(METAL3) :', rg.getLayerDepth(layer)) print('rg.getLayerGauge(METAL3) :', rg.getLayerGauge(layer)) print('rg.getLayerDirection(2) :', rg.getLayerDirection(2)) print('rg.getRoutingLayer(2) :', rg.getRoutingLayer(2)) rlg = rg.getLayerGauge(2) print('rlg.getLayer() :', rlg.getLayer()) print('rlg.getBlockageLayer() :', rlg.getBlockageLayer()) print('rlg.getDensity() :', rlg.getDensity()) print('rlg.getType() :', rlg.getType()) print('rlg.getPitch() :', DbU.toLambda(rlg.getPitch())) for rlg in rg.getLayerGauges(): print('rlg.getLayer() : ', rlg.getLayer()) #print technology.getName() #for layer in technology.getLayers(): # print 'TECHNO:', layer print('===========================================================') print('\n') return
print e errorCode = 1 # For the geometrical modifications to be taken into account, we must # close this UpdateSession now. So the chip will see the core correctly. UpdateSession.close() if errorCode: sys.exit(errorCode) print ' o Placing <chip>.' amd2901 = framework.getCell('amd2901', CRL.Catalog.State.Logical) if editor: editor.setCell(amd2901) UpdateSession.open() try: chipSide = DbU.fromLambda( 3200) # TODO: Le chip est carre, avec 11 plots par face. abutmentBoxChip = Hurricane.Box(DbU.fromLambda(0), DbU.fromLambda(0), chipSide, chipSide) amd2901.setAbutmentBox(abutmentBoxChip) instanceCoeur = amd2901.getInstance('core') instanceCoeur.setTransformation( Hurricane.Transformation((chipSide - coreSide) / 2, (chipSide - coreSide) / 2, Hurricane.OrientationID)) instanceCoeur.setPlacementStatus(Hurricane.PlacementStatusPLACED) # TODO: Placing pads northPads = [ 'p_a1', 'p_a0', 'p_r0', 'p_r3', 'p_vddeck0', 'p_vddeck1', 'p_b3',
except Exception, e: print e; errorCode = 1 # For the geometrical modifications to be taken into account, we must # close this UpdateSession now. So the chip will see the core correctly. UpdateSession.close() if errorCode: sys.exit(errorCode) print ' o Placing <chip>.' amd2901 = framework.getCell('amd2901',CRL.Catalog.State.Logical) if editor: editor.setCell(amd2901) UpdateSession.open() try: chipSide = DbU.fromLambda(3200) # TODO: Le chip est carre, avec 11 plots par face. abutmentBoxChip = Hurricane.Box( DbU.fromLambda(0) , DbU.fromLambda(0) , chipSide , chipSide ) amd2901.setAbutmentBox( abutmentBoxChip ) instanceCoeur = amd2901.getInstance( 'core' ) instanceCoeur.setTransformation(Hurricane.Transformation( (chipSide-coreSide)/2 , (chipSide-coreSide)/2 , Hurricane.OrientationID ) ) instanceCoeur.setPlacementStatus( Hurricane.PlacementStatusPLACED ) # TODO: Placing pads
# For the geometrical modifications to be taken into account, we must # close this UpdateSession now. So the chip will see the core correctly. UpdateSession.close() if errorCode: sys.exit(errorCode) print ' o Placing <chip>.' amd2901 = framework.getCell('amd2901', CRL.Catalog.State.Logical) if editor: editor.setCell(amd2901) UpdateSession.open() try: chipSide = 11 * padWidth + 2 * padHeight # TODO: Le chip est carre, avec 11 plots par face. abutmentBoxChip = Hurricane.Box(DbU.fromLambda(0.0), DbU.fromLambda(0.0), chipSide, chipSide) amd2901.setAbutmentBox(abutmentBoxChip) instanceCoeur = amd2901.getInstance('core') instanceCoeur.setTransformation( Hurricane.Transformation((chipSide - coreSide) / 2, (chipSide - coreSide) / 2, Hurricane.OrientationID)) instanceCoeur.setPlacementStatus(Hurricane.PlacementStatusPLACED) # TODO: Placing pads southPads = [ 'p_d0', 'p_d1', 'p_d2', 'p_d3', 'p_vsseck0', 'p_vsseck1', 'p_vssick0', 'p_y0', 'p_y1', 'p_y2', 'p_y3'