{{{ #!html

TP10 VLSI : Vue physique de l'AMD2901

}}} [[PageOutline]] == Objectifs == * Utiliser les outils de placement et routage. * Vérifier la validité du routage. == Exercice(s) == === Exercice 1-Placement === La première étape consiste à générer le '''coeur''' du circuit en exécutant le fichier '''coeur.py''' afin de prévoir un bon routage des alim il est nécessaire de prendre en compte ce qui suit dans l'écriture du fichier '''coeur.py''' {{{ - dans la netlist (méthode Netlist) : def Netlist ( self ) : self.tie = Inst ("tie_x0", "tie", map = {'vdd' : self.vdd, 'vss' : self.vss } ) - dans la méthode Layout : def Layout ( self ): DefAb(XY(0,0),XY(1500,1500)) Place(self.tie, NOSYM, XY(0,0)) AlimConnectors() }}} Ensuite Le '''Placement du circuit''' est possible en éxecutant le script donné plus bas, on place 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.vddi = VddIn ( "vddi" ) self.vssi = VssIn ( "vssi" ) 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 COMPLETER ##### 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 pour former le '''coeur''' et relier les connecteurs du coeur aux plots. 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'''