{{{ #!html

TP10 VLSI : Vue physique de l'AM2901

}}} [[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 cellules du 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 }}} visualiser le résultat obtenu à l'aide de '''graal'''. ==== 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 en dehors de graal''' {{{ > druc amd_route }}} . 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 '''vst'''. ==== Question 3 ==== Comparez la ''netlist'' extraite à celle d'origine (avnt routage) en utilisant l'outil '''lvx''' le routage n'est valide que si vous obtenez le message '''Les deux netlists sont identiques '''