wiki:ToolsCourseTp10

Version 9 (modified by anne, 18 years ago) (diff)

--

TP10 VLSI : Vue physique de l'AMD2901

Objectifs

  • Utiliser les outils de placement et routage.
  • Vérifier la validité du routage.

Exercice(s)

Exercice 1-Placement

La première étape consiste à placer les plots puis le coeur.

Question 1

Exécutez le script suivant amd_chip.py en ayant pris soin de comprendre le contenu de ce fichier

#!/usr/bin/python

from stratus import *

class amd_chip ( Model ) :

  def Interface ( self ) :

    self.cke     = CkIn       ( "cke")
    self.cin     = SignalIn  ( "cin",   1 )
    self.cout    = SignalOut  ( "cout",  1 )
    self.np      = SignalOut      ( "np",    1 )
    self.ng      = SignalOut      ( "ng",    1 )
    self.ovr     = SignalOut      ( "ovr",   1 )
    self.zero    = SignalOut      ( "zero",  1 )
    self.signe   = SignalOut  ( "signe", 1 )
    self.r0      = TriState  ( "r0",    1 )
    self.r3      = TriState  ( "r3",    1 )
    self.q0      = TriState  ( "q0",    1 )
    self.q3      = TriState  ( "q3",    1 )
    self.a       = SignalIn       ( "a",     4 )
    self.b       = SignalIn       ( "b",     4 )
    self.d       = SignalIn       ( "d",     4 )
    self.i       = SignalIn       ( "i",     9 )
    self.noe     = SignalIn       ( "noe",   1 )
    self.y       = TriState  ( "y",     4 )

    self.vdd     = VddIn ( "vdd"  )
    self.vss     = VssIn ( "vss"  )
    self.vdde    = VddIn ( "vdde" )
    self.vsse    = VssIn ( "vsse" )


  def Netlist ( self ) :

    cin_from_pads    = Signal ( "cin_from_pads",    1 )
    cout_to_pads     = Signal ( "cout_to_pads",     1 )
    np_to_pads       = Signal ( "np_to_pads",       1 )
    ng_to_pads       = Signal ( "ng_to_pads",       1 )
    ovr_to_pads      = Signal ( "ovr_to_pads",      1 )
    zero_to_pads     = Signal ( "zero_to_pads",     1 )
    shift_r          = Signal ( "shift_r",          1 )
    shift_l          = Signal ( "shift_l",          1 )
    signe_to_pads    = Signal ( "signe_to_pads",    1 )
    r0_to_pads       = Signal ( "r0_to_pads",       1 )
    r3_to_pads       = Signal ( "r3_to_pads",       1 )
    r0_from_pads     = Signal ( "r0_from_pads",     1 )
    r3_from_pads     = Signal ( "r3_from_pads",     1 )
    q0_to_pads       = Signal ( "q0_to_pads",       1 )
    q3_to_pads       = Signal ( "q3_to_pads",       1 )
    q0_from_pads     = Signal ( "q0_from_pads",     1 )
    q3_from_pads     = Signal ( "q3_from_pads",     1 )
    ck_ring          = Signal ( "ck_ring",          1 )
    a_from_pads      = Signal ( "a_from_pads",      4 )
    b_from_pads      = Signal ( "b_from_pads",      4 )
    d_from_pads      = Signal ( "d_from_pads",      4 )
    i_from_pads      = Signal ( "i_from_pads",      9 )
    y_to_pads        = Signal ( "y_to_pads",        4 )
    noe_from_pads    = Signal ( "noe_from_pads",    1 )
    y_oe             = Signal ( "y_oe",             1 )
    self.ckc         = Signal ( "ckc",              1 )


    self.coeur = Inst ( "coeur"
                     , "coeur"
                     , map = { 'cin_from_pads' : cin_from_pads
                             , 'cout_to_pads'  : cout_to_pads
                             , 'np_to_pads'    : np_to_pads
                             , 'ng_to_pads'    : ng_to_pads
                             , 'ovr_to_pads'   : ovr_to_pads
                             , 'signe_to_pads' : signe_to_pads
                             , 'zero_to_pads'  : zero_to_pads
                             , 'shift_r'       : shift_r
                             , 'shift_l'       : shift_l
                             , 'r0_to_pads'    : r0_to_pads
                             , 'r3_to_pads'    : r3_to_pads
                             , 'r0_from_pads'  : r0_from_pads
                             , 'r3_from_pads'  : r3_from_pads
                             , 'q0_to_pads'    : q0_to_pads
                             , 'q3_to_pads'    : q3_to_pads
                             , 'q0_from_pads'  : q0_from_pads
                             , 'q3_from_pads'  : q3_from_pads
                             , 'ck'            : self.ckc
                             , 'a_from_pads'   : a_from_pads
                             , 'b_from_pads'   : b_from_pads
                             , 'd_from_pads'   : d_from_pads
                             , 'i_from_pads'   : i_from_pads
                             , 'y_to_pads'     : y_to_pads
                             , 'noe_from_pads' : noe_from_pads
                             , 'y_oe'          : y_oe
                             , 'vdd'           : self.vdd
                             , 'vss'           : self.vss
                             }
                     )

    self.p_ck = Inst ( "pck_px", "p_ck"
         , map = { 'pad'  : self.cke
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_cin = Inst ( "pi_px", "p_cin"
         , map = { 'pad'  : self.cin
                 , 't'    : cin_from_pads
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_noe = Inst ( "pi_px", "p_noe"
         , map = { 'pad'  : self.noe
                 , 't'    : noe_from_pads
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_a = {}
    self.p_b = {}
    self.p_d = {}
    for i in range ( 4 ) :
      self.p_a[i] = Inst ( "pi_px", "p_a%d" % i
           , map = { 'pad'  : self.a[i]
                   , 't'    : a_from_pads[i]
                   , 'ck'   : ck_ring
                   , 'vddi' : self.vdd
                   , 'vssi' : self.vss
                   , 'vdde' : self.vdde
                   , 'vsse' : self.vsse
                   }
           )

      self.p_b[i] = Inst ( "pi_px", "p_b%d" % i
           , map = { 'pad'  : self.b[i]
                   , 't'    : b_from_pads[i]
                   , 'ck'   : ck_ring
                   , 'vddi' : self.vdd
                   , 'vssi' : self.vss
                   , 'vdde' : self.vdde
                   , 'vsse' : self.vsse
                   }
           )

      self.p_d[i] = Inst ( "pi_px", "p_d%d" % i
           , map = { 'pad'  : self.d[i]
                   , 't'    : d_from_pads[i]
                   , 'ck'   : ck_ring
                   , 'vddi' : self.vdd
                   , 'vssi' : self.vss
                   , 'vdde' : self.vdde
                   , 'vsse' : self.vsse
                   }
           )

    self.p_i = {}
    for i in range ( 9 ) :
      self.p_i[i] = Inst ( "pi_px", "p_i%d" % i
           , map = { 'pad'  : self.i[i]
                   , 't'    : i_from_pads[i]
                   , 'ck'   : ck_ring
                   , 'vddi' : self.vdd
                   , 'vssi' : self.vss
                   , 'vdde' : self.vdde
                   , 'vsse' : self.vsse
                   }
           )

    self.p_cout = Inst ( "po_px", "p_cout"
         , map = { 'i'    : cout_to_pads
                 , 'pad'  : self.cout
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_np = Inst ( "po_px", "p_np"
         , map = { 'i'    : np_to_pads
                 , 'pad'  : self.np
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_ng = Inst ( "po_px", "p_ng"
         , map = { 'i'    : ng_to_pads
                 , 'pad'  : self.ng
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_ovr = Inst ( "po_px", "p_ovr"
         , map = { 'i'    : ovr_to_pads
                 , 'pad'  : self.ovr
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_zero = Inst ( "po_px", "p_zero"
         , map = { 'i'    : zero_to_pads
                 , 'pad'  : self.zero
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_signe = Inst ( "po_px", "p_signe"
         , map = { 'i'    : signe_to_pads
                 , 'pad'  : self.signe
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                  , 'vdde' : self.vdde
                  , 'vsse' : self.vsse
                  }
         )

    self.p_y = {}
    for i in range ( 4 ) :
      self.p_y[i] = Inst ( "pot_px", "p_y%d" % i
           , map = { 'i'    : y_to_pads[i]
                   , 'b'    : y_oe
                   , 'pad'  : self.y[i]
                   , 'ck'   : ck_ring
                   , 'vddi' : self.vdd
                   , 'vssi' : self.vss
                   , 'vdde' : self.vdde
                   , 'vsse' : self.vsse
                   }
           )

    self.p_q0 = Inst ( "piot_px", "p_q0"
         , map = { 'i'    : q0_to_pads
                 , 'b'    : shift_r
                 , 't'    : q0_from_pads
                 , 'pad'  : self.q0
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_q3 = Inst ( "piot_px", "p_q3"
         , map = { 'i'    : q3_to_pads
                 , 'b'    : shift_l
                 , 't'    : q3_from_pads
                 , 'pad'  : self.q3
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_r0 = Inst ( "piot_px", "p_r0"
         , map = { 'i'    : r0_to_pads
                 , 'b'    : shift_r
                 , 't'    : r0_from_pads
                 , 'pad'  : self.r0
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_r3 = Inst ( "piot_px", "p_r3"
         , map = { 'i'    : r3_to_pads
                 , 'b'    : shift_l
                 , 't'    : r3_from_pads
                 , 'pad'  : self.r3
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_vddick0 = Inst ( "pvddick_px", "p_vddick0"
         , map = { 'cko'  : self.ckc
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                  , 'vdde' : self.vdde
                  , 'vsse' : self.vsse
                  }
         )

    self.p_vssick0 = Inst ( "pvssick_px", "p_vssick0"
         , map = { 'cko'  : self.ckc
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_vddeck0 = Inst ( "pvddeck_px", "p_vddeck0"
         , map = { 'cko'  : self.ckc
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_vddeck1 = Inst ( "pvddeck_px", "p_vddeck1"
         , map = { 'cko'  : self.ckc
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )

    self.p_vsseck0 = Inst ( "pvsseck_px", "p_vsseck0"
         , map = { 'cko'  : self.ckc
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                  , 'vdde' : self.vdde
                  , 'vsse' : self.vsse
                  }
         )

    self.p_vsseck1 = Inst ( "pvsseck_px", "p_vsseck1"
         , map = { 'cko'  : self.ckc
                 , 'ck'   : ck_ring
                 , 'vddi' : self.vdd
                 , 'vssi' : self.vss
                 , 'vdde' : self.vdde
                 , 'vsse' : self.vsse
                 }
         )


  def Layout ( self ) :

    ##### A COMLPETER #####
    DefAb(XY(0,0),XY(3000,3000))

    PlaceCentric(self.coeur)

    PadNorth(self.p_i[3],self.p_i[4],self.p_i[5],self.p_b[0],self.p_b[1],self.p_b[2],self.p_b[3]
                ,self.p_q0,self.p_q3,self.p_i[6],self.p_i[7])


    PadWest(self.p_ck,self.p_d[0],self.p_d[1],self.p_d[2],self.p_zero,self.p_vsseck0,self.p_ovr
                ,self.p_d[3],self.p_i[0],self.p_i[1],self.p_i[2])


    PadSouth(self.p_cin,self.p_np,self.p_ng,self.p_vssick0,self.p_vddeck0,self.p_vsseck1,self.p_vddeck1
                ,self.p_cout,self.p_y[0],self.p_y[1],self.p_y[2])


    PadEast(self.p_y[3],self.p_signe,self.p_noe,self.p_a[0],self.p_a[1],self.p_vddick0
                ,self.p_a[2],self.p_a[3],self.p_r0,self.p_r3,self.p_i[8])





    PowerRing(3)

    PlaceGlue(self.coeur)

    FillCell(self.coeur)

    RouteCk(self.ckc)


mon_chip = amd_chip ( "amd_2901_dpt" )

mon_chip.Interface ()
mon_chip.Netlist ()
#mon_chip.Layout ()
mon_chip.View ()
mon_chip.Save (LAYOUT)

Quels sont les fichiers obtenus? regardez en utilisant graal le résultat du placement.

Question 2

Faites varier la taille de la boite d'aboutement, qu'observez-vous ? Avez vous rencontré une limite ? peut-on en déduire la largeur des plots.

Exercice 2-Routage

Cette seconde étape consiste à relier les cellulesdu coeur entre elles. Vous allez pour cela utiliser l'outil nero . Consultez le man de nero

>nero -v -3 -p amd_chip_pl amd amd_route

Question 1

A quoi correspondent les options utilisées dans la commande ci-dessus? Faites varier le nombre de couches de métal utilisés pour le routage.

Exercice 3-Validation du routage

Cette étape consiste à vérifier que le routage a été effectué sans erreur. Il y a deux types de vérifications à réaliser

  • Vérifier le respect des règles de dessin
  • Vérifier les interconnexions réalisées

Question 1

Vérifiez le respect des règles de dessin en utilisant Druc . Vous aurez pris soin au préalable de vérifier que vous utilisez la technologie symbolique

Question 2

Utilisez l'outil cougar pour extraire la netlist de votre circuit au niveau "cellules de base ". Vous aurez au préalable pris soin de positionner la variable d'environnement MBK_OUT_LO au format al.

Question 3

Comparez la netlist extraite à celle d'origine (avnt routage) en utilisant l'outil lvx