05.+Unitatea+centrala+de+prelucrare

= CAPITOLUL 5: UNITATEA CENTRALĂ DE PRELUCRARE  =

5.1. Procesoare
Munca esenţială a unui calculator are loc într-o parte a maşinii pe care nu o putem vedea: un centru de control care prelucrează şi converteşte datele de intrare în informaţie pentru ieşire. Acest centru de control poartă denumirea de **Unitatea Centrală de Prelucrare** – **UCP. UCP** este alcătuită dintr-un set de circuite electronice de complexitate ridicată care execută instrucţiunile programelor memorate. Toate calculatoarele, mai mici sau mai mari, trebuie să aibă cel puţin o unitate centrală de prelucrare. **UCP** este alcătuită din mai multe părţi distincte. **Unitatea de control** – **UC** – conţine circuite ce utilizează semnale electrice pentru a coordona funcţionarea întregului sistem de calcul. **UC** nu execută instrucţiunile programului, ci, coordonează celelalte părţi ale sistemului în acest scop. **Unitatea de control** răspunde de extragerea instrucţiunilor din memoria principală şi de determinarea tipului lor. Unitatea de control trebuie să comunice atât cu **Unitatea aritmetică şi logică**, cât şi cu memoria.

Figura 18. Organizarea unui calculator simplu cu o UCP şi două dispozitive de I/E

**Unitatea aritmetică şi logică** - **UAL** conţine circuite electronice care execută toate operaţiile aritmetice şi logice. **UAL** poate efectua calcule aritmetice: adunare, scădere, înmulţire şi împărţire, dar şi operaţii logice sau comparaţii. Operaţiile logice elementare executate sunt: Negarea logică - **NOT**, Şi logic – **AND**, respectiv Sau logic – **OR**. Din punct de vedere al comparaţiilor sunt testate trei condiţii elementare: condiţia de egalitate, condiţia mai mic decât, respectiv condiţia mai mare decât, ca şi combinaţii ale acestora.

**UCP** mai conţine şi o memorie mică, foarte rapidă, folosită pentru depozitarea rezultatelor temporare şi a anumitor informaţii de control.

Această memorie este formată dintr-un număr de **registre**, fiecare având o anumită dimensiune şi funcţie caracteristică. De obicei, toate registrele au aceeaşi dimensiune. Fiecare registru poate memora un număr, valoarea maximă a acestuia fiind determinată de dimensiunea registrului. Registrele pot fi citite şi scrise cu mare viteză deoarece ele se află în interiorul **UCP**.

Cel mai important registru este **contorul de program** (**PC, Program Counter**), care indică instrucţiunea următoare care va fi extrasă pentru execuţie. Numele "contor de program" poate fi întrucâtva înşelător, pentru că nu are nici o legătură cu numărarea, dar termenul este folosit universal. De asemenea important este şi **registrul de instrucţiuni** (**IR, Instruction Register**), în el se păstrează instrucţiunea în curs de execuţie. Majoritatea calculatoarelor dispun de multe alte registre, unele de uz general şi altele pentru scopuri bine determinate.

5.2. Organizarea UCP
Organizarea internă a unei părţi dintr-o UCP von Neumann tipică este prezentată mai în detaliu în Figura 19. Această parte se numeşte **cale de date** - **data path** şi include registre (de obicei între 1 şi 32), **UAL – Unitatea aritmetică şi logică (ALU, Arithmetic Logic Unit)** şi mai multe magistrale de legătură. Registrele trimit datele în cele două registre de intrare ale **UAL**, notate în figură cu **A** şi **B**. Aceste registre păstrează datele de intrare ale **UAL** în timp ce aceasta calculează. Calea de date este foarte importantă pentru orice maşină Figura 19. Calea de date ale unei maşini von Neumann

**UAL** execută asupra datelor sale de intrare adunări, scăderi şi alte operaţii simple, al căror rezultat este depus în registrul de ieşire. Conţinutul registrului de ieşire poate fi memorat înapoi într-unul din registrele de intrare. Mai târziu, dacă se doreşte, registrul poate fi scris în memorie.

Majoritatea instrucţiunilor fac parte dintr-una din următoarele două categorii: registru-memorie sau registru-registru. Instrucţiunile registru-memorie permit cuvintelor din memorie să fie încărcate în registre, de unde pot fi folosite ca date de intrare pentru **UAL** în instrucţiunile următoare. Alte instrucţiuni registru-memorie permit depozitarea conţinutului registrelor înapoi în memorie.

Alt tip de instrucţiune este registru-registru. O instrucţiune registru-registru tipică extrage operanzi din registre, îi aduce în registrele de intrare ale **UAL**, execută o operaţie oarecare asupra lor, de exemplu adunare sau ŞI logic, şi depune rezultatul înapoi într-unul din registre. Procesul prin care cei doi operanzi sunt trecuţi prin **UAL** şi rezultatul este depozitat se numeşte **ciclul căii de date** - **data path cycle** şi este inima celor mai multe **UCP**. El defineşte în mare măsură ce poate face maşina. Cu cât ciclul căii de date este mai rapid, cu atât maşina merge mai repede.

5.3. Execuţia instrucţiunilor
Să examinăm modul în care **UCP**, împreună cu memoria, execută o instrucţiune dintr-un program. Multe calculatoare personale pot executa o instrucţiune în mai puţin de o milionime de secundă, în timp ce supercalculatoarele pot executa o instrucţiune în mai puţin de o miliardime de secundă.

Înainte ca o instrucţiune să poată fi executată, instrucţiunea programului şi datele trebuie plasate în memorie dintr-un dispozitiv de intrare sau dintr-o memorie secundară. De îndată ce datele necesare şi instrucţiunea sunt plasate în memorie, UCP va trece la executarea următorilor paşi:

1. Transferă instrucţiunea următoare din memorie în registrul de instrucţiuni.

2. Schimbă contorul de program astfel încât să indice următoarea instrucţiune.

3. Determină tipul instrucţiunii proaspăt extrase.

4. Dacă instrucţiunea are nevoie de un cuvânt din memorie, determină unde se găseşte acesta.

5. Extrage cuvântul dintr-unul din registrele UCP, dacă este cazul.

6. Execută instrucţiunea.

7. Rezultatele sunt depozitate într-un registru sau în memorie

Reia de la pasul 1 pentru a începe execuţia instrucţiunii următoare.

Deseori această secvenţă de paşi este denumită ciclul **extrage – decodifică – execută - memorează** (**fetch – decode – execute - store**). Acest ciclu este esenţial în funcţionarea oricărui calculator.


 * Unitatea de control UC **extrage** – **fetch** instrucţiunea din memorie şi o pune într-un registru
 * Unitatea de control UC **decodifică** – **decode** instrucţiunea şi determină locaţia de memorie a datelor necesare.

Aceşti doi paşi împreună sunt denumiţi **timpul instrucţiune** – **instruction time**, sau **I-time.**


 * Unitatea de control UC mută datele din memorie în registrele UAL. Aceasta **execută** – **execute** instrucţiunea aritmetică sau logică. Astfel, UAL preia controlul şi execută operaţia curentă asupra datelor.
 * Unitatea de control UC preia rezultatele acestei operaţii şi le depune în memorie sau într-un registru, adică **memorează** - **store**.

Aceşti ultimi doi paşi împreună sunt denumiţi **timpul execuţie** – **execution time**, sau **E – time.** Unitatea de control mai comandă eventual memoria să trimită rezultatul unui dispozitiv de ieşire sau unei memorii secundare.

Combinarea celor două etape, timpul instrucţiune şi timpul de execuţie poartă denumirea de **ciclu maşină** – **machine cycle.**

Fiecare UCP are un **ceas intern** care produce impulsuri cu o frecvenţă dată pentru a sincroniza toate operaţiile calculatorului. Ceasul intern este reprezentat de un cristal de cuarţ, care vibrează la aplicarea unei tensiuni electrice. Vibraţiile sunt emise sub forma unor impulsuri, ce poartă denumirea de **semnal de ceas** sau **tact.** Frecvenţa ceasului intern este exprimată în cicluri (perioade) pe secundă, unitatea de măsură fiind Hz (hertz). Calculatoarele actuale au frecvenţe de ordinul sutelor de milioane de cicluri pe secundă (200, 300, 500, 1000 MHz).

Observaţie: acest ceas nu este acelaşi cu ceasul calculatorului utilizat pentru păstrarea datei curente şi orei; acesta este un alt circuit integrat.

O singură instrucţiune a unui program poate fi alcătuită dintr-un număr substanţial de sub-instrucţiuni, fiecare din ele durând cel puţin un ciclu maşină. Fiecare tip de UCP poate înţelege un set specific de instrucţiuni, cum ar fi ADD – adună sau MOVE – mută, denumite **setul de microinstrucţiuni.** Aşa cum există o multitudine de limbaje pe care le înţeleg oamenii, aşa există o multitudine de seturi de instrucţiuni pentru diverse tipuri de UCP.

Această descriere a funcţionării **UCP** seamănă foarte mult cu un program scris în limba română. Acest pseudo-program poate fi rescris ca o metodă Java, adică o procedură cu numele //interpret.// Însuşi faptul că este posibil să se scrie un program care să imite funcţionarea UCP demonstrează că un program nu trebuie executat de o UCP "hardware", adică o cutie plină de componente electronice. În loc de asta, un program poate fi executat de către un alt program, care să-i extragă, examineze şi execute instrucţiunile.

Un program care extrage, examinează şi execută instrucţiunile altui program se numeşte **interpretor** - **interpreter**. Această echivalenţă dintre procesoarele hardware şi interpretoare are consecinţe foarte importante pentru structurarea şi proiectarea sistemelorde calcul. După specificarea limbajului maşină **L** pentru un nou calculator, echipa de proiectare poate decide dacă va construi un procesor hardware care să execute direct programele scrise în **L** sau dacă va scrie un interpretor care să interpreteze programele scrise în **L**//.// Sunt posibile şi construcţii hibride, cu o parte de execuţie hardware şi o parte de interpretare software.

Un interpretor descompune instrucţiunile maşinii pentru care este scris (maşina ţintă) într-o serie de paşi mici. În consecinţă, maşina pe care rulează interpretorul poate fi mult mai simplă şi mai ieftină decât dacă ar fi avut nevoie de procesorul hardware corespunzător. Această economie este importantă în special în cazul în care maşina ţintă are un număr mare de instrucţiuni şi instrucţiunile sunt complicate, cu multe opţiuni. Economia se obţine în principal din înlocuirea hardware-ului cu software-ul (interpretorul).

Calculatoarele mai vechi aveau seturi de instrucţiuni restrânse şi simple. Încercările de a construi calculatoare tot mai puternice au condus, printre altele, la instrucţiuni individuale tot mai puternice. Foarte curând s-a descoperit că instrucţiunile mai complexe conduc adesea la o execuţie mai rapidă a programelor, chiar dacă instrucţiunile individuale se execută mai lent. Un exemplu de instrucţiune complexă este o instrucţiune în virgulă mobilă. Un alt exemplu este mecanismul de acces direct la elementele unui vector. Uneori a fost suficient să se observe că aceleaşi două instrucţiuni apăreau deseori consecutiv, astfel încât o singură instrucţiune poate să realizeze aceeaşi prelucrare:

Instrucţiunile mai complicate au fost mai bune deoarece uneori execuţiile unor operaţii individuale se pot suprapune sau pot fi executate în paralel, folosind echipamente diferite.

Pentru calculatoarele scumpe, de înaltă performanţă, costul hardware-ului suplimentar putea fi justificat imediat. De aceea calculatoarele scumpe, de înaltă performanţă, au ajuns să aibă mult mai multe instrucţiuni decât cele cu cost redus. Cu toate acestea, creşterea costului dezvoltării de software şi cerinţele de compatibilitate la nivelul instrucţiunilor au făcut să se simtă nevoia implementării de instrucţiuni complexe chiar şi pe calculatoarele ieftine, unde preţul era mai important decât viteza.

Calculatoarele simple cu instrucţiuni interpretate mai aveau şi alte avantaje, dintre care cele mai importante erau:

1. Posibilitatea de a corecta pe loc instrucţiunile incorect implementate, sau chiar de a rezolva deficienţe de proiectare ale hardware-ului de bază.

2. Posibilitatea de a adăuga noi instrucţiuni la un cost minim, chiar după livrarea maşinii.

3. Proiectarea structurată, ce permitea dezvoltarea, testarea şi documentarea eficientă a instrucţiunilor complexe.

Ţinând cont de explozia pieţei de calculatoare din anii '70 şi de creşterea rapidă a capacităţilor de calcul, sporirea cererii pentru calculatoare ieftine a favorizat proiectarea calculatoarelor ce foloseau interpretoare. Capacitatea de a ajusta hardware-ul şi interpretorul pentru un anumit set de instrucţiuni a devenit un mod de proiectare a procesoarelor foarte eficient din punct de vedere economic. Cum tehnologia semiconductoarelor (baza fizică a calculatoarelor) avansa rapid, avantajele costului au cântărit mai mult decât posibilităţile de creştere a performanţei, şi arhitecturile bazate pe interpretoare au devenit standardul proiectării calculatoarelor. Aproape toate calculatoarele noi, proiectate în anii 1970, de la minicalculatoare la calculatoare mari, se bazau pe interpretare.

Spre sfârşitul anilor 1970 folosirea unor procesoare simple, ce rulau interpretoare, era extrem de răspândită, cu excepţia modelelor celor mai scumpe, de cea mai înaltă performanţă, cum ar fi seriile Cray-1 sau Control Data Cyber. Folosirea interpretorului elimina limitările inerente costului instrucţiunilor complexe, iar arhitecturile începeau să exploreze instrucţiuni mult mai complexe, în particular modul de specificare a operanzilor.

Acest curent a ajuns la apogeu odată cu calculatorul VAX al firmei Digital Equipment Corporation, care dispunea de câteva sute de instrucţiuni şi peste 200 de moduri diferite de specificare a operanzilor pentru fiecare instrucţiune. Din păcate, arhitectura VAX a fost concepută de la bun început pentru a fi implementată cu un interpretor, fără a se avea în vedere şi un model cu performanţe sporite. Această abordare a condus la includerea unui număr foarte mare de instrucţiuni cu utilitate marginală, ce erau greu de executat direct.

Cu toate că microprocesoarele de început, pe 8 biţi, erau maşini foarte simple cu setul de instrucţiuni foarte simple, spre sfârşitul anilor 1970 chiar şi microprocesoarele ajunseseră să fie proiectate pe baza interpretoarelor. În această perioadă una dintre provocările majore adresate proiectanţilor de microprocesoare se referea la posibilitatea creşterii complexităţii datorită circuitelor integrate. Un avantaj major al abordării bazate pe interpretor era capacitatea de a proiecta un procesor simplu, complexitatea fiind încredinţată memoriei în care se păstra interpretorul. În acest mod, proiectarea unui hardware complex putea fi înlocuită cu proiectarea unui software complex.

Succesul procesorului Motorola 68000, care avea un set mare de instrucţiuni interpretate, şi eşecul concomitent al procesorului Zilog Z8000 (care avea un set de instrucţiuni la fel de mare, dar fără un interpretor) a demonstrat avantajele interpretorului în lansarea rapidă pe piaţă a unui nou microprocesor. Acest succes a fost cu atât mai surprinzător cu cât Zilog luase un start mai bun (predecesorul lui Z8000, Z80, fusese mult mai popular decât predecesorul lui 68000, 6800). Bineînţeles, şi alţi factori au jucat aici un rol important, nu în ultimul rând trecutul bogat de producător de cipuri al firmei Motorola şi trecutul bogat de companie petrolieră, nu de producător de cipuri al firmei Exxon (proprietara Zilog).

Un alt factor favorizant al dezvoltării interpretării în acea epocă a fost existenţa memoriilor rapide numai pentru citire, denumite **memorii de control** - **control stores**, memorii în care erau depozitate interpretoarele. Să presupunem că o instrucţiune interpretată tipică 68000 necesita 10 instrucţiuni ale interpretorului, numite **microinstrucţiuni** - **microinstructions**, fiecare durând 100 nsec, şi două adresări la memoria principală, fiecare durând 500 nsec. Timpul total de execuţie era în acest caz de 2000 nsec, numai de două ori mai prost decât cel mai bun timp posibil de obţinut prin execuţia directă a instrucţiunilor. Dacă nu ar fi fost disponibilă memoria de control, instrucţiunea ar fi durat 6000 nsec. Un factor de penalizare 6 este mult mai greu de acceptat decât un factor de penalizare//2.// Figura 20. Ciclul maşină în acţiune

Presupunem că un program trebuie să găsească media aritmetică a cinci rezultate ale unui test. Pentru a face acest lucru, trebuie mai întâi să totalizeze cele cinci rezultate şi apoi rezultatul să-l împartă la cinci.

Programul începe prin a iniţializa valoarea sumei cu zero. Apoi adaugă fiecare din cele cinci numere, câte unul pe rând, la sumă. Presupune că cele cinci numere sunt: 88,76,91, 83 şi 87. La început suma este zero, apoi 88, primul rezultat, este adăugat la sumă.. Să vedem cum se adună următorul rezultat, 76, la sumă, de către ciclul maşină. Urmăreşte cei patru paşi ai ciclului maşină: 1 – Unitatea de control extrage instrucţiunea de adunare din memorie; 2 – UC decodifică instrucţiunea de adunare.

Determină că trebuie făcută o operaţie de adunare şi dă instrucţiuni pentru ca următorul număr, 76, să fie plasat într-un registru pentru a putea face adunarea. Valoarea totală 88 se află deja în registrul acumulator.

3 – Execută: următorul număr, 76, este plasat în registru. UAL efectuează adunarea, crescând valoarea sumei la 164. 4 – Memorează: în acest caz, UAL păstrează rezultatul în acumulator, şi nu în memorie, deoarece acest număr va fi folosit în continuare pentru a se adăuga un nou număr la sumă.

Noua valoare 164 înlocuieşte valoarea precedentă a sumei, 88.

Microprocesorul nu "înţelege" decât limbajul maşină, adică o succesiune de 0 şi 1. Pentru a executa instrucţiunile programelor, microprocesorul dispune de un set de //microinstrucţiuni.// În funcţie de setul de microinstrucţiuni utilizat, calculatoarele se pot clasifica astfel:


 * Calculatoare **CISC** – **C**omplex **I**nstruction **S**et Computer
 * Calculatoare **RISC** – **R**educed **I**nstruction **S**et Computer.

Calculatoarele **CISC** (de exemplu, cele care utilizează microprocesoare //Intel// 286, 386, 486, Pentium) au set complex de microinstrucţiuni, existând multe microinstrucţiuni specializate, care îndeplinesc o sarcină particulară.

Microprocesoarele **RISC** au set redus de microinstrucţiuni, instrucţiunile mai complexe fiind recreate cu ajutorul instrucţiunilor primare. Sistemele **RISC** sunt mai rapide şi mai eficiente. Cele mai reprezentative microprocesoare **RISC** sunt **SPARC**, utilizate de staţiile //Sun,// **MIPS**, utilizate de staţiile //Silicon Graphics,// PowerPC din noile calculatoare //Apple// şi **IBM PC**, **Alpha**, utilizate pentru staţiile //Digital Equipment.// Paradoxal, calculatoarele **CISC** sunt mult mai răspândite. Principalul motiv îl constituie marea cantitate şi varietate de software dezvoltat pentru calculatoarele **CISC**, care nu este compatibil cu microprocesoarele **RISC**.

O ultimă metodă pentru creşterea vitezei este **procesarea paralelă** – **parallel processing**, o soluţie care utilizează mai multe procesoare în acelaşi timp. Pentru a creşte performanţele, proiectanţii de UCP au abandonat de mult modelul simplu alcătuit din citirea, decodificarea şi executarea unei singure instrucţiuni la un moment dat. Multe unităţi de procesare moderne pot executa mai multe instrucţiuni în acelaşi timp. De exemplu, o UCP poate avea unităţi separate pentru citire, decodificare şi execuţie, aşa încât în timp ce execută instrucţiunea **//n//** poate decodifica instrucţiunea **//n+1//** şi poate citi instrucţiunea **//n+2//**. O astfel de organizare este numită **banda de asamblare** (**pipeline**). În majoritatea soluţiilor de acest tip, odată ce o instrucţiune a fost introdusă în banda de asamblare, ea trebuie executată chiar dacă instrucţiunea precedentă a fost un salt condiţional care s-a executat. Benzile de asamblare provoacă multe dureri de cap celor care scriu compilatoare şi sisteme de operare pentru că ele evidenţiază complexitatea maşinii pentru care se scrie.

Unele calculatoare care folosesc procesarea paralelă sunt capabile să opereze la o viteză de ordinul **teraflop,** ceea ce înseamnă miliarde de instrucţiuni în virgulă mobilă pe secundă.

Mai avansat decât varianta cu banda de asamblare este o UCP **superscalară**. În acest caz sunt prezente mai multe unităţi de execuţie, cum ar fi una pentru aritmetica numerelor întregi, una pentru aritmetica în virguIă mobilă şi una pentru operaţii booleene (logice). Două sau mai multe instrucţiuni sunt citite în acelaşi timp, sunt decodificate şi plasate într-o zonă de memorie tampon până când pot fi executate. De îndată ce o unitate de execuţie este liberă, ea verifică dacă în tampon se află vreo instrucţiune pe care să o poată executa. Dacă ea există, atunci unitatea preia instrucţiunea din tampon şi o execută. O consecinţă a acestei soluţii este că instrucţiunile programului sunt adesea executate în altă ordine.

Pentru majoritatea cazurilor structura hard este aceea care garantează că rezultatele obţinute sunt aceleaşi cu cele generate de o unitate secvenţială.