The next generation: P6

Microprocesorul Intel P6, cel mai tînăr vlăstar al dinastiei x86, este la ora actuală cel mai performant microprocesor CISC. Sau e deja RISC?

Attila Darvas

Reusind să treacă cu succes momentul dificil reprezentat de "the Pentium bug" si învătînd putin nu numai din greseli, ci si de la concurentă, Intel prezintă cel mai performant microprocesor compatibil x86, comparabil ca performante cu procesoarele din categoria RISC.

P6, prezentat la CeBIT '95, se remarcă de la prima vedere prin forma deosebită - datorată memoriei cache de nivel 2, integrată în capsulă, dar ca un al doilea cip - si numărului mare de pini: 387. Performantele duble fată de un PENTIUM la 100 Mhz - 200 SPECint92 si 200 SPECfp92 - sînt efectul integrării a 21 de milioane de tranzistori, pusi să "lucreze" la un ritm de 133 MHz. Tehnologia pentru prima versiune de P6 este BiCMOS 0,5microni 4M (patru straturi metalice), dar deja pentru anul viitor se prevede un model realizat în tehnologie de 0,35 microni care va putea lucra la 200MHz.

Magistrala sistem (System Bus) are la bază o conceptie nouă si permite transferuri mult mai rapide. Mai mult decît atît, este posibilă realizarea unor sisteme multiprocesor, prin conectarea a patru procesoare la magistrală - nota bene, fără alte componente auxiliare.

Instructiunile de tip x86 sînt traduse intern în micro-operatii de lungime fixă, denumite de Intel uops (pronuntia fiind "iuops") si executate de unitatea de executie superscalară, decuplată; aceasta are la bază o conceptie de lucru nouă - "executia dinamică" - bazată însă pe tehnici care s-au mai văzut, fie la concurentă (Cyrix, NexGen, AMD), fie prin procesoare de clasă RISC; printre acestea, redenumirea registrelor si posibilitatea de executie într-o ordine diferită a instructiunilor.

Microarhitectura internă la P6, rupînd traditia arhitecturilor Intel x86, desi prezintă pe alocuri asemănări cu cea a concurentei, realizează performante superioare acestora.

Unitatea centrală poate fi privită ca fiind alcătuită din două părti mari: partea de prelucrare în ordinea dată a instructiunilor si partea de executie într-o ordine diferită a lor (in-order si respectiv out-of-order). Instructiunile sînt aduse în ordine în unitatea centrală, dar pot fi executate apoi într-o ordine diferită. Rezultatele se depun în memoria tampon de reordonare (ROB - reorder buffer, cu 40 de intrări), unde se reface ordinea corectă. (Un mod de lucru asemănător se regăseste în microprocesorul K5, proiectat si produs de AMD). P6 nu face numai ceea ce trebuie; utilizînd o tehnică numită "executie speculativă" - executia anticipată a unor instructiuni, care s-ar putea să ajungă la rînd - viteza de procesare mai cunoaste un spor. Unitatea de executie "în afara rîndului" a microinstructiunilor este un alt element care contribuie la îmbunătătirea esentială a performantelor unitătii centrale fată de Pentium, unde instructiunile cu cicluri multiple de executie provocau suspendarea activitătii procesorului pînă la terminarea lor. Redenumirea registrelor (solutie tehnică existentă si în procesorul M1, proiectat si produs de Cyrix) permite eliminarea problemelor datorate unui număr relativ redus de registre generale la arhitecturile x86. Implementarea acestei tehnici este realizată cu ajutorul a două structuri, tabela de registre alternative (RAT - register alias table) si setul de registre reale (RRF - real register file). Integrarea memoriei cache de nivel 2 (Level-2 cache) în aceeasi capsulă cu unitatea centrală si accesarea ei prin intermediul unei magistrale dedicate este o altă noutate. Să trecem toate acestea încă odată în revistă, ceva mai amănuntit.

Micro-operatii

Memoria cache pentru instructiuni permite încărcarea (fetch) a 16 octeti aliniati la fiecare ciclu - spre deosebire de Pentium, care permitea si încărcarea unor octeti nealiniati si îngreuna astfel procesul de decodificare. Octetii de instructiune sînt transferati într-un buffer de unde ajung în trei decodificatoare diferite. Dintre acestea, primul, situat la începutul bufferului, poate decodifica orice instructiune x86; următoarele două "se descurcă" numai cu instructiuni simple, de tip registru-registru. Instructiunile sînt decodificate în ordine, deci o instructiune complexă ce ajunge la un decodificator simplu - care nu o poate decodifica - va trebui să "astepte", blocînd si instructiunile următoare, pînă ce ajunge la început de buffer si va fi tratată de primul decodificator. Acest mecanism face ca, atunci cînd există instructiuni de decodificat, numărul de instructiuni decodificate si deci "lansate" simultan să varieze între cel putin una - în cazul nefericit cînd există secvente de instructiuni complexe - si cel mult trei - în cazul fericit cînd o instructiune complexă este urmată de două simple.

Decodificatoarele transformă instructiunile în secvente de microoperatii (uops) de lungime fixă de 118 biti. În cadrul acestora, atît cîmpul pentru operandul sursă si cîmpul pentru operandul destinatie au lungime fixă - 32 de biti. Modul de lucru load/store specific RISC face ca instructiunile cu referintă către memorie să genereze o secventă de microinstructiuni de tipul încărcare - executie în unitatea aritmetica/logică ALU - memorare. Deoarece numai decodificatorul general poate furniza pînă la patru uop, el este singurul care poate decodifica instructiunile complexe. Si tot el este singurul secondat de un secventiator - pentru a permite decodificarea în mai multe cicluri a instructiunilor complexe, cele care generează si mai mult de patru uop.

ROB (reorder buffer) este memoria tampon de reordonare; aici se depun rezultatele executiei microinstructiunilor, care sînt marcate pentru a putea restabili ordinea corectă după executie. Fiecare din cele 40 de pozitii în ROB oferă loc pentru rezultatul unei uop de incărcare sau de calcul. În strînsă corelatie cu ROB se află tabela de registre alternative RAT si setul de registre reale RRF. La introducerea unei microinstructiuni în ROB, RAT determină dacă operandul sursă trebuie luat din RRF sau tot din ROB; această din urmă situatie are loc de exemplu atunci cînd registrul destinatie al unei uop anterioare coincide cu cel specificat ca registru sursă în microinstructiunea curentă. În acest caz, numărul registrului sursă este înlocuit cu un pointer către intrarea corespunzătoare din ROB, iar tabela RAT este actualizată corespunzător. Prin acest mecanism este realizată redenumirea dinamică a registrelor, ROB dispunînd de 40 de pozitii - registre generalizate - care pot contine informatiile din orice registru, întreg sau de virgulă flotantă.

Un efect imediat al acestei tehnici constă în faptul că instructiunea FXCH (floating point exchange) este executată în ROB si nu în FPU, cum ar părea normal. Instructiunea - una din cele mai des utilizate instructiuni de virgulă mobilă, care interschimbă între ele continutul vîrfului stivei de registre FP cu cel al unui alt registru din stivă - este tratată de P6 prin simpla redenumire a două registre.

RS (reservation station) - "statia de rezervare" - primeste microinstructiunile din ROB (cel mult trei pe ciclu). Pot fi în asteptarea executiei cel mult douăzeci de uops; acestea trebuie să astepte ca operanzii sursă să fie disponibili în ROB si, cînd acest lucru se întîmplă, sînt marcate ca fiind pregătite de executie.

Executia out-of-order

Din statia de rezervare, microinstructiunile sînt dispecerizate către cinci unităti de executie distincte: două de calcul, una de încărcare si două de memorare (una pentru date si una pentru adrese). Memorările necesită o microoperatie aditională pentru transferul datei de memorat. Deoarece fiecare subunitate din unitatea de executie are doar o intrare, există restrictii în gruparea uops pentru executia în acelasi ciclu, si evident numai cîteodată toate cele cinci unităti de executie vor putea lucra în paralel. Repartizarea instructiunilor spre executie se face după un algoritm pe care Intel nu l-a făcut public, dar care în principiu tine cont de felul de uops si de durata prezentei în RS.

Cele două ALU - una complexă, avînd si unitate de virgulă flotantă FP, si una simplă - efectuează majoritatea calculelor. Faptul că cea de-a doua unitate aritmetico-logică este mult simplificată, neputînd efectua deplasări, înmultiri sau împărtiri, nu diminuează semnificativ performantele P6.

Cele două unităti de generare a adresei contin fiecare sumatoare cu patru intrări pentru lucrul cu toate componentele de adresă x86 (segment, bază, index, imediat) si de asemenea cîte un sumator secundar pentru a putea face în paralel verificarea de depăsire limită segment. Adresa rezultată este transferată în bufferul de reordonare memorie MOB pentru a astepta aici pînă ce memoria cache de date devine disponibilă.

ROB poate primi pînă la trei rezultate pe ciclu, si anume de la ALU principal, de la ALU simplificat si ca rezultat al unei microoperatii de încărcare. După scrierea rezultatului în ROB (sau MOB, după caz) microoperatia este pregătită spre a fi retrasă ("pensionată"). ROB va retrage maxim 3 uops per ciclu, totdeauna în ordinea dată de program, după ce a scris rezultatele în RRF. Microoperatiile nu sînt retrase decît după ce toate microoperatiile precedente au fost executate cu succes. La aparitia unei erori sau exceptii rezultatele neconfirmate din ROB sînt sterse iar unitatea centrală este readusă la starea corespunzătoare situatiei în care toate instructiunile pînă la instructiunea care a generat eroarea sau exceptia s-ar fi executat normal.

Memoriile cache

Procesoarele moderne nu ar putea obtine performantele actuale fără existenta unei memorii cache integrate. Datorită setului redus de registre generale disponibile pentru x86 - care din această cauză trebuie să acceseze deseori memoria - problema este si mai acută. P6 are - ca si Pentium - o memorie cache pentru date si una pentru instructiuni, fiecare cu o capacitate de 8K si avînd lungimea liniei de 32 bytes. Cache-ul de instructiuni este de patru ori asociativ si are o magistrală de 128 biti, iar cache-ul de date este dublu asociativ si are două porturi de date, pentru două magistrale, fiecare de lătime de 64 biti. Cache-ul de date lucrează în modul fără-blocare (non blocking), adică poate satisface alte cereri de date chiar si după ce una din cereri a "esuat" (miss - dată neprezentă in cache), urmînd ca cererea respectivă să fie servită abia după ce datele au fost aduse - cu o probabilitate destul de mare, din cache-ul de pe al doilea nivel, evitînd încă odată memoria externă, extrem de lentă fată de ce se întîmplă în procesor. Tehnica aceasta este utilizată de foarte mult timp în arhitecturile Hewlett-Packard PA-RISC, pentru evitarea blocajelor. P6 are - ca si NexGen - un controller de cache de nivel 2, dar în plus are - ca si MIPS R4000 - memoria cache integrată în aceeasi capsulă cu procesorul. Acest al doilea cache intern, de 256 KB SRAM (static RAM), este realizat cu ajutorul a 15,5 milioane de tranzistori. Două lucruri ar trebui să surprindă la acest număr: a) de ce asa de multi tranzistori pentru atît de putină memorie si b) de ce e totusi mai mic fizic cipul de memorie decît cel de unitate centrală, cînd acesta din urmă e realizat cu "numai" 5,5 milioane de tranzistori. Răspunsurile sînt simple: memoria cache e SRAM, nu DRAM, diferenta esentială fiind că un bit DRAM este realizat cu un singur tranzistor si are nevoie de refresh, pe cînd un bit SRAM este realizat din 6 tranzistori (la P6) si nu are nevoie de refresh - ceea ce-l face mai rapid si mai scump. Iar diferenta de mărime între cele două cipuri se explică prin faptul că tranzistorii pentru memorii pot fi realizati la o desime mult mai mare decît cei pentru componentele logice, chiar dacă se foloseste aceasi tehnologie.

Cache-ul de nivel 2 este de patru ori asociativ si este utilizat atît pentru instructiuni cît si pentru date; se află pe acelasi suport ceramic ca si procesorul propriu-zis si este legat de acesta prin intermediul unei magistrale distincte, lată de 64 de biti. O linie în memoria cache de nivel 2 are 32 bytes, ca si memoria cache de date. Combinatia cache principal fără blocare - cache secundar rapid, integrat în aceeasi capsulă, reprezintă o noutate si se constituie într-unul din avantajele procesorului P6 fată de produsele competitorilor.

Pipeline cu 12 faze

Pentru a accelera executia programelor s-a realizat la P6 un mecanism pipeline cu mai multe faze. În prima fază se calculează următoarea adresă de încărcare (fetch), prin accesarea unitătii BTB (branch target buffer), unde se caută adresa instructiunii următoare. Dacă aceasta este deja pregătită acolo, atunci procesul de încărcare instructiune este orientat către locatia de memorie indicată. Dacă nu, procesorul continuă cu următoarea adresă în secventă. Calculul adresei următoare nu este decît uneori o simplă incrementare: poate că trebuie făcută o ramificare a programului, poate că o întrerupere trebuie tratată... Accesul la memoria cache de instructiuni se întinde pe două cicluri si jumătate, ceea ce permite ca ceasul procesorului să lucreze la o frecventă mai mare. P6 preia două linii de cache, de cîte 32 de bytes fiecare, marchează limitele fiecărei instructiuni si pasează în final 16 octeti aliniati către decodificatoare. Trebuie preluate două linii de cache pentru că instructiunile x86 pot fi lungi, astfel încît e foarte posibil ca o instructiune să treacă de pe o linie cache si pe următoarea. Iar marcarea limitelor este importantă pentru că instructiunile x86 au lungime diferite - între 8 si 120 de biti - astfel încît nu este evident unde începe si unde se termină o instructiune (instructiunile RISC sînt mai usor de încărcat pentru că au o lungime fixă - 32 de biti). Instructiunile trec apoi la decodificare si generarea de microinstructiuni, ceea ce poate dura alte două faze si jumătate. La terminarea celei de-a sasea faze, instructiunile sînt transformate în uops - mult mai usor de manevrat decît instructiunile din care provin, pentru că au o structură si o lungime fixă. Marea majoritate a instructiunilor x86 pot fi transformate într-o singură microinstructiune - nu însă si cele mai complexe. În cel mai defavorabil caz - exceptînd prefixele de repetare, buclele sau operatiile pe siruri - o instructiune este transformată într-o secventă de 204 microinstructiuni. În faza 7 are loc (eventuala) redenumire a registrelor; în faza 8 are loc scrierea în statia de rezervare RS, după care pot să apară eventual întîrzieri, în functie de operanzi (s-ar putea ca acestia să nu fie încă pregătiti). În faza 9, RS decide dacă există microinstructiuni care să poată fi repartizate către una din unitătile de executie. La P6 este posibilă transmiterea operanzilor (operand bypass) astfel încît acestia să fie disponibili în ciclul imediat următor. RS va încerca aducerea următoarei uop la unitatea corespunzătoare de executie în ciclul următor. Executia are loc în faza 10, într-un singur ciclu pentru microin-

structiuni simple si pe mai multe cicluri la microinstructiuni complexe sau de virgulă flotantă. Microinstructiunile de încărcare si memorare îsi generează adresele într-un singur ciclu si sînt înscrise în MOB; dacă MOB este gol, o încărcare va ajunge direct la cache-ul de date, dar vor fi necesare cel putin alte trei cicluri pînă ce datele vor fi disponibile - în cazul fericit cînd ele se află în cache. După executia din faza 10 are loc scrierea rezultatelor în bufferul de reordonare, ROB. "Retragerea" uops are loc în fazele 11 si 12.

Lungimea mare a pipeline-ului prin care trec instructiunile P6 - cele douăsprezece faze (minim) prin care trece fiecare instructiune - duce la cresterea importantei "prezicerii" corecte a instructiunii următoare.

Cum instructiunea "următoare" - a cărei prelucrare desigur nu asteaptă terminarea instructiunii precedente, ci începe imediat după ea, la distantă de o singură fază - poate să nu fie cea care trebuia făcută, iar acest lucru devine evident abia în faza 10 - deci cu două faze înainte de final - sanctiunea în timp pentru o previziune gresită este majoră: cel putin 11 cicluri masină executate "în vînt". Din această cauză, rolul BTB (branch target buffer) este esential; acesta are 512 intrări organizate ca o memorie cache de patru ori asociativă, dimensiunea dublă fată de Pentium si un algoritm (Yeh) de anticipare adaptiv, mai performant, ce utilizează 4 biti pentru un "istoric" al ramificărilor si poate recunoaste si prevedea secvente repetabile de ramificări, de genul TRUE-TRUE -FALSE.

Evitarea anticipării eronate este sprijinită si de introducerea unei noi instructiuni (una din extrem de putinele modificări aduse setului de instructiuni, aproape identic cu cel al unui 386) si anume de deplasare conditionată, CMOV. Această instructiune permite copierea continutului unui registru într-altul numai dacă un anumit indicator de conditie (Flag) este pozitionat, evitînd în felul acesta o secventă de tipul testează-si-ramifică programul. Este poate interesant de stiut că, în medie, programele au la fiecare 5 instructiuni o ramificare - dacă sînteti programator si vă surprinde acest lucru, nu uitati că nu numai instructiunile conditionale se transformă în ramificări, ci si buclele de orice fel.

Noua interfată de magistrală

Legătura lui P6 cu exteriorul este asigurată printr-o magistrală de 64 biti (frontside bus) care poate lucra la maximum 66 MHz - exact ca la Pentium. Dar transferul informatiilor poate avea loc la viteze mult mai mari la P6 decît la Pentium datorită protocolului de bus complet modificat - "split-transaction protocol". Dacă Pentium-ul, atunci cînd citeste de pe bus, trimite adresele, asteaptă ca datele să fie pregătite si apoi le citeste - ocupînd magistrala pe toată durata tranzactiei - P6 permite efectuarea de transferuri simultan cu asteptarea rezultatelor. Pînă la 8 tranzactii pot fi lansate simultan. Arbitrarea se face cu semnale separate, în paralel cu transferul de date. Pentru a garanta coerenta datelor între memorie si cache-uri, P6 implementeză protocolul de coerentă cunoscut sub numele de MESI (modified, exclusive, shared, invalid). Acesta garantează coerenta memoriei cache atît în sisteme cu un singur procesor, cît si în sisteme multiprocesor; evită deasemenea necazurile pe care le poate provoca un program ce contine cod care se automodifică - gînditi-vă la ce se întîmplă dacă un program modifică secvente care deja sînt "duse" în cache. P6 detectează astfel de situatii si, chiar mai mult, dedică un registru special pentru a contoriza de cîte ori se întîmplă acest lucru. Un sistem de operare ar putea verifica ce se întîmplă, generînd eventual avertismente corespunzătoare. Adresele sint trimise pe un bus separat de 36 de biti, astfel încît transferul de date poate avea loc la 528 Mbyte/sec o perioadă nedefinit de lungă. Deoarece există în plus o magistrală distinctă pentru cache-ul de nivel 2 (backside bus), întreaga capacitate de transfer a magistralei sistem poate fi utilizată pentru operatii de I/E si acces la memorie. (La această oră, Intel încă nu a făcut publice detaliile de functionare ale noii magistrale, acest lucru urmînd să se întîmple la o dată încă neprecizată).

Noua magistrală sistem a lui P6 permite interconectarea directă, pin la pin, a pînă la patru procesoare P6, pentru realizarea de sisteme multiprocesor performante, ideale ca servere în retele sau ca statii de lucru. Ca si la Pentium, P6 incorporează un controller de priorităti la întreruperi avansat (APIC), simplificînd proiectarea sistemelor multiprocesor. Iar capacitatea magistralei - sustine Intel - este suficientă pentru a permite conlucrarea a patru procesoare P6 fără o diminuare semnificativă a performantelor individuale. Iar clustere de cîte patru procesoare pot fi folosite pentru realizarea unor sisteme multiprocesor mai complexe.

Specificatiile pentru nivelele de semnal pe magistrală s-au modificat si sînt de 1,5 V, corespunzînd asa-numitului GTL (Gunning Transceiver Logic). Nivelul mai mic reduce timpii de stabilizare a semnalelor - si deschide calea functionării la frecvente mari.

Consumul de putere

Cu toate că s-a reusit realizarea procesorului pe o pastilă de siliciu doar cu 4% mai mare ca cea pe care este realizat un Pentium, totusi cele 4,5 milioane de tranzistoare pentru logică, 1 milion pentru cache si alte 15,5 milioane pentru cache L2 au un consum ridicat deocamdată în comparatie cu celelalte microprocesoare compatibile x86. Alimentarea lui P6 se face la 2,9V si nu la 3,3 ca la PENTIUM. Puterea disipată - maxim 20W si tipic 15W - este totusi foarte mică tinînd cont de faptul că procesoarele RISC comparabile ca performante consumă peste 30W. Capsula folosită este de tip "dual-cavity PGA" (Pin Grid Array) - asa spune Intel, în timp ce alte companii numesc capsulele de acest gen MCM (multichip module) - si este prevăzută cu un radiator de 2 cm înăltime pentru a ajuta disiparea.

Performante - si previziuni

În comparatie cu concurenta, Intel si-a demonstrat încă o dată forta, plasîndu-se cu degajare în fruntea plutonului producătorilor de microprocesoare x86-compatibile. Dar că la Intel nimeni nu se culcă pe lauri si că a rămîne în frunte este mult mai dificil decît a ajunge acolo, o dovedeste printre altele si colaborarea pe care Intel a angajat-o anul trecut cu Hewlett-Packard. Microprocesorul proiectat a rezulta din această colaborare - P7? - este asteptat cîndva în 1997 sau 1998. Nu s-a spus încă mare lucru despre proiect - în afara faptului că va reprezenta un plonjon în tehnologia RISC si că va fi compatibil cu toate softurile existente pentru procesoare x86 sau PA-RISC. În afară de aceste două seturi de instructiuni "mostenite", probabil că va avea si un set de instructiuni proprii. Pentru cazul în care acest proiect nu ar avea succesul scontat - lucru perfect posibil, date fiind multele necunoscute implicate în modul de abordare radical diferit, tehnologia cu care se experimentează, VLIW - Very Long Instruction Format, fiind oarecum exact opusul celei înspre care P6 a făcut un pas - Intel desigur pregăteste în paralel si un P7 mai conventional. În asteptarea lui P7 - indiferent cum va fi el - vă doresc tuturor măcar un Pentium.

Casetele Spectrate: SPECint92, SPECfp92 si Cei 5magnifici de pe piata PC-ului


(C) Copyright Computer Press Agora