Exemple #1
0
 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)
                                            )
Exemple #2
0
 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)
                                                )
Exemple #3
0
    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
Exemple #4
0
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
Exemple #5
0
    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
Exemple #6
0
    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
Exemple #7
0
    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
Exemple #8
0
  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
Exemple #9
0
    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
Exemple #10
0
    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
Exemple #11
0
    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
Exemple #12
0
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
Exemple #13
0
    def Layout(self):

        #HCELL = 50
        HCELL = DbU.toLambda(
            self.Prech[0]._hur_masterCell.getAbutmentBox().getHeight())

        # Lignes de bit
        bottom = 0

        for i in range(self._nbit):
            if i % 2:  # lignes impaires
                sym1 = SYM_Y
                sym2 = SYMXY
            else:  # lignes paires
                sym1 = NOSYM
                sym2 = SYM_X

            Place(self.Prech[i], sym1, XY(0, bottom + i * HCELL))

            for j in range(0, self._nmot, 4):
                PlaceRight(self.Bit[i][j], sym2)
                PlaceRight(self.Bit[i][j + 2], sym1)

            PlaceRight(self.Sense[i], sym1)

        # Premiere ligne de la zone des buffers
        bottom = self._nbit * HCELL

        Place(self.PrechBuf0, NOSYM, XY(0, bottom))

        for j in range(0, self._nmot, 4):
            PlaceRight(self.Buf0[j], SYM_X)
            PlaceRight(self.Buf0[j + 2], NOSYM)

        PlaceRight(self.SenseBuf0, NOSYM)

        # Deuxieme ligne de la zone des buffers
        bottom = (self._nbit + 1) * HCELL

        Place(self.PrechBuf1, SYM_Y, XY(0, bottom))

        for j in range(0, self._nmot, 4):
            PlaceRight(self.Buf1[j], SYMXY)
            PlaceRight(self.Buf1[j + 2], SYM_Y)

        PlaceRight(self.SenseBuf1, SYM_Y)

        # Premiere ligne de la zone du decodeur
        bottom = (self._nbit + 2) * HCELL

        Place(self.PrechDecB, NOSYM, XY(0, bottom))

        for j in range(0, self._nmot, 8):
            PlaceRight(self.Dec[j], SYM_X)
            PlaceRight(self.Dec[j + 2], NOSYM)
            PlaceRight(self.Dec[j + 4], SYM_X)
            PlaceRight(self.Dec[j + 6], NOSYM)

        PlaceRight(self.SenseDecAd12, NOSYM)

        # Deuxieme ligne de la zone du decodeur
        bottom = (self._nbit + 3) * HCELL

        if adrange == 8:  # adresse sur 8 bits  : on decode 5 bits
            Place(self.PrechDecU, SYM_Y, XY(0, bottom))
            for j in range(0, self._nmot, 8):
                PlaceRight(self.MemDec[j], SYM_Y)
            PlaceRight(self.SenseDecAd, SYM_Y)

        if adrange == 7:  # adresse sur 7 bits : on decode 4 bits
            Place(self.PrechDecU, SYM_Y, XY(0, bottom))
            for j in range(0, self._nmot, 8):
                PlaceRight(self.MemDec[j], SYM_Y)
            PlaceRight(self.SenseDecAd, SYM_Y)

        if adrange == 6:  # adresse sur 6 bits : on decode 3 bits
            Place(self.PrechDecU, SYM_Y, XY(0, bottom))
            for j in range(0, self._nmot, 8):
                PlaceRight(self.MemDec[j], SYM_Y)
            PlaceRight(self.SenseDecAd, SYM_Y)

        if adrange == 5:  # adresse sur 5 bits : on decode 2 bits
            Place(self.PrechDecU, SYM_Y, XY(0, bottom))
            for j in range(0, self._nmot, 8):
                PlaceRight(self.MemDec[j], SYM_Y)
            PlaceRight(self.SenseDecAd, SYM_Y)