Sunteți pe pagina 1din 116

PRINCIPII, MODELE şi STRUCTURI de SISTEME DE CALCUL

Anul I seria 2009-2010


Bibliografie
1. Găitan Vasile, ARHITECTURA SISTEMELOR DE CALCUL, vol.I,
Editura Universităţii din Suceava, 1998.
2. Nicolau Viorel, ARHITECTURA CALCULATOARELOR, Cartea
Universitară, Bucureşti, 2005.
3. Baruch Zoltan Francisc, ARHITECTURA CALCULATOARELOR, Editura
Todesco, Cluj-Napoca, 2000.
4. Baruch Zoltan Francisc, STRUCTURA SISTEMELOR DE CALCUL,
Editura Albastră, Cluj-Napoca, 2004.
5. Baruch Zoltan Francisc, SISTEME DE INTRARE/IESIRE ale
CALCULATOARELOR,Editura Albastră, Cluj-Napoca, 2000.
6. Palade Vasile, Istrate Adrian, CALCULATOARE şi SISTEME DE
OPERARE, Editura Fundaţiei Universitare „Dunărea de Jos”, Galaţi,1999.
7. Toacşe Gheorghe, INTRODUCERE IN MICROPROCESOARE, Editura
Stiinţifică şi Enciclopedică, Bucureşti, 1985.
8. Dancea Ioan, MICROPROCESOARE, ARHITECTURA
INTERNA,PROGRAME, APLICATII, Editura Dacia, Cluj-Napoca,1979.
9. Mureşan T., şa, MICROPROCESORUL 8080 în APLICATII, Editura Facla,
Timişoara,1981.
10. Patrubani Mikloş, TOTUL DESPRE MICROPROCESORUL Z80, Editura
Tehnică, Bucureşti, 1989.
Cap.1. BAZELE ARITMETICE ALE CALCULATOARELOR
Spre deosebire de calculatoarele analogice care operează cu mărimi
continue calculatoarele numerice (digitale) au fost concepute să opereze asupra
numerelor. Numerele permit o evaluare cantitativă a lumii înconjurătoare. Prin
operaţia de numărare se asociază fiecărei mulţimi de obiecte un număr care
reprezintă astfel cantitatea de obiecte care formează respectiva mulţime. In
aproape toate civilizaţiile umane operaţia de numărare a presupus mai întâi
divizarea mulţimii de obiecte în grupe mai mici, punându-se astfel bazele
sistemului de numeraţie. Deoarece la începuturile civilizaţiilor umane aprecierea
cantitativă a unei mulţimi de obiecte se realiza prin compararea acesteia cu
numărul degetelor de la mâni, se utilizează în prezent sistemul de numeraţie
zecimal (cu baza zece). Există însă indicii că au existat civilizaţii care utilizau alte
baze, de exemplu baza 12.
Baza de numeraţie ne indică deci mărimea grupei în care grupăm
obiectele în scopul numărării lor. In procesul de utilizare a calculatorului întâlnim
sistemele de numeraţie cu baza 10, 8, 16, 2. Din punct de vedere matematic
sistemele de numeraţie sunt echivalente. Dacă operatorului uman îi este foarte
comod să lucreze în sistemul zecimal, nu acelaşi lucru îl putem spune despre un
calculator. Din motive de reprezentare a cifrelor, calculatoarele se utilizează
sistemul de numeraţie binar îmbinat cu sistemul hexazecimal sau octal.
1.1. Sisteme de numeraţie
Prin sistem de numeraţie se înţelege totalitatea regulilor de reprezentare
ale numerelor cu ajutorul simbolurilor denumite cifre.
Sistemele de numeraţie pot fi poziţionale sau nepoziţionale. Un exemplu
de sistem poziţional este sistemul zecimal, iar un sistem nepoziţional este cel
roman. Intr-un sistem poziţional, un număr N cu parte întreagă şi parte fracţionară,
separate prin virgulă, se poate scrie sub oricare din următoarele forme:
N = an −1an −2 ...a1a0 , a−1a−2 ...a−( m −1)a−m (1.1)
N = an −1q n −1 + an −2 q n − 2 + ... + a1q 1 + a0 q 0 + a−1q −1 + a−2 q −2 + ... + a−m q −m (1.2)
sau
n −1
∑ ai q i
N= (1.3)
i = −m
unde: q este baza sistemului de numeraţie (întreg pozitiv);
a - reprezintă cifre: 0 ≤ ai ≤ q , i = n − 1, n − 2,...,1,0,−1,−2,...,−m ;
n este numărul de cifre întregi ale numărului;
m este numărul de cifre fracţionare ale numărului.
Intr-un sistem de numeraţie, cifra este un simbol care reprezintă o
cantitate întreagă. Numărul de simboluri permise pentru reprezentarea numerelor
într-un sistem de numeraţie se numeşte baza sau rădăcina sistemului de
numeraţie. Cifrele a, reprezintă coeficienţii cu care se înmulţesc puterile q i ale
bazei q în dezvoltarea polinomială a numărului pentru obţinerea valorii sale.
Cifra an −1 , din relaţiile (1.1) şi (1.2) este cifra cea mai semnificativă
(c.m.s.) a numărului, iar cifra a− m este cifra cea mai puţin semnificativă
(c.m.p.s.). In cazul sistemului de numeraţie binar, pentru cifra binară se
foloseşte prescurtarea de bit. Dacă m = 0, numărul N este întreg. Dacă n = 0,
numărul N este fracţionar şi subunitar. Dacă m şi n sunt întregi şi diferiţi de
zero, numărul N este mixt.
Exemple
263,2710 = 2 ×102 + 6 ×101 + 3 ×100 + 2 ×10−1 + 7 ×10−2
1110001,01 = 1 × 26 + 1 × 25 + 1 × 24 + 1 × 20 + 1 × 2−2
Relaţia (1.2) explică motivul pentru care astfel de sisteme de numeraţie
sunt denumite poziţionale. Fiecare cifră a contribuie la valoarea numărului
respectiv cu o pondere dată de puterea i a bazei q.
Pentru un sistem de numeraţie în baza q trebuie să existe q simboluri.
La sistemele de numeraţie cu baza q > 10 se introduc simboluri noi. De
exemplu, pentru sistemul hexazecimal se introduc literele de la A la F.
Reprezentarea primelor 16 numere în sistemul zecimal, binar şi hexazecimal
este dată în tabelul 1.1.
Tabelul 1.1. Reprezentarea unor numere în sistemul zecimal, binar şi
hexazecimal.
q = 10 q = 2 q = 16
0 0 0
1 1 l
2 10 2
3 11 3
4 100 4
5 101 5
6 110 6
7 111 7
8 1000 8
9 1001 9
10 1010 A
11 1011 B
12 1100 C
13 1101 D
14 1110 E
15 1111 F
1.2. Conversia bazei de numeraţie
Pentru a deduce o metodă sistematică de conversie dintr-un sistem de
numeraţie în altul, folosim rezultatul cunoscut că, dacă N şi q sunt numere
întregi, există întotdeauna un singur întreg r (care nu este negativ) mai mic
decât q şi un singur întreg C, astfel încât:
N r
=C + , 0 ≤ r < q (1.4)
q q
1.2.1. Conversia numerelor întregi
Aplicăm această regulă la conversia unui număr întreg Np din baza p în
echivalentul său în baza q, adică Nq. Trebuie să determinăm valorile întregi
nenegative a0 , a1,..., an −1, fiecare mai mic decât q, astfel ca:
N p = an-1q n -1 + ... + a2q 2 + a1q 1 + a0 q 0 (1.5)
In relaţia de mai sus cunoaştem numărul în vechea bază N p , noua
bază q şi trebuie să aflăm cifrele numărului din noua bază a0 , a1,..., an −1 .
Prin împărţire cu numărul q obţinem:
Np a a
= an -1q n -2 + ... + a2q 1 + a1q 0 + 0 = C0 + 0 (1.6)
q q q
a0
unde C0 este partea întreagă, iar este partea fracţionară, deci a0 este
q
restul împărţirii întregi al numărului N p la q .
Impărţind câtul C0 la q şi utilizând rezultatele de mai sus, obţinem:
C0 a a
= an -1q n -3 + ... + a2q 0 + 1 = C1 + 1 (1.7)
q q q
unde a1 reprezintă acum restul împărţirii întregi dintre C0 şi q .
Operaţia se continuă până când se obţine un cât egal cu zero.
Algoritmul de conversie a numerelor întregi este deci următorul:
1. Se împarte numărul iniţial N p (în baza p) la noua bază q. Se obţine
câtul C 0 şi restul a0 .
2. Se împarte câtul C0 la q. Se obţine câtul C1 şi restul a1 .
3. Se continuă algoritmul până când se obţine câtul C n = 0 . Resturile
obţinute reprezintă cifrele numărului convertit, a0 fiind cifra c.m.p.s.
Exemple
1. Conversia din zecimal în binar. Să considerăm numărul 137. Acesta
trebuie împărţit la 2 şi punem în evidenţă resturile împărţirii întregi dintre 137
şi 2.
137 : 2
68 : 2 → a0 = 1
34 : 2 → a1 = 0
17 : 2 → a2 = 0
8 : 2 → a3 = 1
4 : 2 → a4 = 0
2 : 2 → a5 = 0
1 : 2 → a6 = 0
0 → a7 = 1
S-a obţinut:
13710 = 100010012
2. Conversia din zecimal în octal (baza 8).
137 : 8
17 : 8 → a0 = 1
2 : 8 → a1 = 1
0 → a2 = 2
deci: 13710 = 2118
3. Conversia din zecimal în hexazecimal (baza 16).
137 : 16
8 : 16 → a0 = 9
0 → a1 = 8
deci: 137 10 = 8916
1.2.2. Conversia numerelor fracţionare
Pentru conversia numerelor fracţionare subunitare trebuie
determinaţi coeficienţii întregi nenegativi a-1, a- 2 ,..., a-m . Considerăm numărul
fracţionar N p din baza p care, în noua bază q , are următoarea reprezentare:
N p = a-1q -1 + a-2q -2 + a-3 q -3 + ... + a-mq -m (1.8)
unde a−1, a− 2 , ..., a− m sunt cifrele numărului reprezentat în noua bază.
Prin înmulţire cu baza q obţinem:
qN p = a−1 + a−2q −1 + a−3 q −2 + ... + a−m q − m +1 = a−1 + F1 (1.9)
unde a−1 este partea întreagă, iar F1 este partea fracţionară a valorii obţinute.
Inmulţind partea fracţionară F1 cu q obţinem:
qF1 = a−2 + a−3 q −1 + ... + a−m q − m + 2 = a−2 + F2 (1.10)
Operaţia se continuă până când se obţine o parte fracţionară egală cu
zero sau se ajunge la precizia cerută.
Algoritmul de conversie al numerelor fracţionare este deci următorul:
1. Se înmulţeşte numărul iniţial Np (în baza p ) cu noua bază q. Se obţine
partea fracţionară F1 şi partea întreagă a−1 .
2. Se înmulţeşte partea fracţionară F1 cu q. Se obţine partea fracţionară F2 şi
partea întreagă a− 2 .
3. Se continuă algoritmul până când se obţine partea fracţionară Fm = 0 sau
se ajunge la precizia cerută. Cifrele întregi obţinute reprezintă cifrele
numărului în baza q, a−1 fiind cifra c.m.s.
Exemple
1. Conversia din zecimal în binar.
0,438 × 2
0,064 × 2 → a− 7 = 0
0,876 × 2 → a−1 = 0
0,128 × 2 → a− 8 = 0
0,752 × 2 → a− 2 = 1
0,256 × 2 → a− 9 = 0
0,504 × 2 → a− 3 = 1
0,512 × 2 → a−10 = 0
0,008 × 2 → a− 4 = 1
0,024 → a−11 = 1
0,016 × 2 → a− 5 = 0
0,032 × 2 → a− 6 = 0
Deci 0,438 10 = (0,0111000000 1...) 2
Operaţia se continuă fără a se putea ajunge la Fm = 0 . Deci, un număr
fracţionar finit într-un sistem de numeraţie nu poate fi reprezentat întotdeauna
printr-un număr finit într-un alt sistem de numeraţie.
2) Conversie din zecimal în octal
0,438 × 8
0,504 × 8 → a−1 = 3
0,032 × 8 → a− 2 = 4
0,256 × 8 → a−3 = 0
0,048 × 8 → a− 4 = 2
Rezultă 0,43810 = (0,3402 ...) 8
3) Conversie din zecimal în hexazecimal
0,438 × 16
0,008 × 16 → a−1 = 7
0,128 × 16 → a− 2 = 0
0,048 × 16 → a−3 = 2
0,768 × 16 → a− 4 = 0
0,288 → a− 5 = 12 → C
Numărul rezultat este 0,438 10 = (0,7020C...)16
Pentru numere fracţionare mai mari decât 1, partea întreagă şi cea
fracţionară se calculează separat.
Conversia prin codificare
In cazul particular în care baza finală q este o putere întreagă a bazei iniţiale
p:
q = pr , r ∈ Z
conversia se poate reliza printr-un procedeu mai simplu, deoarece unei cifre în
baza q îi corespund r cifre în baza p. Numărul în baza p se partiţionează în
grupe de câte r cifre şi se înlocuieşte fiecare grup de la dreapta şi de la stânga
virgulei cu echivalentul său în baza q . In tabelul de mai jos sunt prezentate
codurile binare ale cifrelor sistemelor hexazecimal şi octal.
q =8
Cod Cod
q = 16
binar binar
0 0000 0 000
l 0001 1 001
2 0010 2 010
3 0011 3 011
4 0100 4 100
5 0101 5 101
6 0110 6 110
7 0111 7 111
8 1000
9 1001
A 1010
B 1011
C 1100
D 1101
E 1110
F 1111
Această proprietate o au bazele 2 şi 8 şi bazele 2 şi 16. Astfel, conversia
din binar în octal se poate efectua prin înlocuirea fiecărui grup de 3 cifre
binare prin echivalentul său octal, iar conversia din binar in hexazecimal se
poate efectua prin înlocuirea fiecărui grup de 4 cifre binare prin echivalentul
său hexazecimal. Dacă ultima grupă de cifre binare de la stânga sau de la
dreapta virgulei nu este completă, se adaugă zerouri la stânga, respectiv la
dreapta, până la completarea grupei.
Exemple
11100,11012 = 011 100,110 100 2 = 34,64 8
10100011,012 = 1010 0011, 0100 2 = A3,416
Pentru conversia din q în p se înlocuieşte fiecare cifră a numărului din
baza q cu cele r cifre ale echivalentului (codului) din baza p .
Astfel, conversia din octal în binar şi cea din hexazecimal în binar se
efectuează prin înlocuirea cifrelor octale, respectiv hexazecimale, printr-un
grup de 3, respectiv 4 cifre binare, care reprezintă codurile binare ale cifrelor.
Exemple
123,48 = 001 010 011, 100 2 = 1010011,12
53, B16 = 0101 0011,10112 = 1010011,10112
Conversia din octal în hexazecimal şi din hexazecimal în octal se poate
efectua după ce s-a efectuat conversia în binar.
Exemple
123,4 8 = 001 010 011,100 2 = 0 0101 0011,100 0 2 = 53,816
A7, E16 = 1010 0111,1110 2 = 010 100 111, 1112 = 247,7 8
1.2.3. Conversia binar-zecimală
Conversia unui număr binar întreg în echivalentul său zecimal se poate
efectua prin metoda înmulţirii repetate cu 2, precizând faptul că operaţia se
efectuează în sistemul zecimal. Pentru cazul general se consideră numărul:
N = an −1q n −1 + an −2q n −2 + ... + a1q 1 + a0 q 0 (1.11)
care mai poate fi scris sub forma
N = (...((an −1q + an − 2 )q + an −3 )q + ... + a1 )q + a0 (1.12)
Pentru q = 2 rezultă următorul algoritm:
1. Se înmulţeşte cifra c.m.s. a numărului binar cu 2 şi se adună la
rezultat următoarea cifră semnificativă.
2. Se înmulţeşte rezultatul cu 2 şi se adună următoarea cifră semnificativă.
3. Se continuă până când s-a prelucrat şi cifra c.mp.s. a numărului binar.
Rezultatul obţinut este echivalentul zecimal al numărului binar dat.
Exemplu
101112 → 1× 2 + 0 = 2
→ 2× 2 +1= 5
→ 5 × 2 + 1 = 11
→ 11× 2 + 1 = 23
deci 101112 = 2310
Numerele fracţionare (subunitare) a căror formă generală este
N = a−1q −1 + a−2q −2 + ... + a−m q −m (1.13)
pot fi factorizare în modul următor:
1   1
1 1
N =  a−1 +
 a−2 + ... + a−m +1 + a−m  ... (1.14)
q   q
q q
  

Pentru q = 2 rezultă următorul algoritm:
1. Se împarte cifra c.m.p.s. a numărului binar cu 2 şi se adună următoarea
cifră semnificativă.
2. Se împarte rezultatul cu 2 şi se adună următoarea cifră semnificativă.
3. Se continuă până când se efectuează împărţirea care corespunde cifrei
c.m.s. a numărului fracţionar.
Exemplu
0,10112 → 1/ 2 + 1 = 1,5
→ 1.5 / 2 + 0 = 0,75
→ 0,75 / 2 + 1 = 1,375
→ 1,375 / 2 = 0,6875
Deci 0,10112 = 0,6875 10
In calculul manual, operaţiile de conversie a numerelor binare în zecimal se
realizează mai simplu prin adunarea puterilor bazei 2.
Exemple
101112 = 1× 2 4 + 0 × 2 3 + 1× 2 2 + 1× 21 + 1× 2 0 = 16 + 0 + 4 + 2 + 1 = 2310
0,10112 = 1× 2 −1 + 0 × 2 −2 + 1× 2 −3 + 1× 2 −4 = 0,5 + 0 + 0,125 + 0,0625 =
= 0,6875 10
In mod identic se poate proceda pentru conversia unui număr din
hexazecimal în zecimal.
1A816 = 1× 16 2 + 10 × 161 + 8 × 16 0 = 256 + 160 + 8 = 42410
1.3. Operaţii aritmetice cu numere fără semn
1.3.1. Adunarea
Adunarea a două cifre în baza q este o operaţie modulo q, deci cifra cu
valoarea cea mai mare va fi q − 1 (de exemplu, 9 în zecimal, 1 în binar, F în
hexazecimal). Dacă rezultatul adunării a două cifre de rang i depăşeşte această
valoare, va apare un transport către rangul i + 1 , care se va aduna la suma cifrelor
de rang i + 1 . Apariţia unui transport de la cifra c.m.s. indică o depăşire a capacităţii
de reprezentare a rezultatului.
In cazul adunării binare, cifra sumei este 1 dacă unul din termenii adunării
este 1. Cifra de transport este 1 numai dacă ambii termeni ai adunării sunt 1. In
tabelul 1.2 se prezintă regula de adunare a două cifre binare x şi y .
Tabelul 1.2. Adunarea a două cifre binare.
x y Transportul Suma
0 0 0 0
0 1 0 1
1 0 0 1
1 1 1 0
Exemple
3210 +
2910
6110
10110 +
10011
101001
6B3216 +
4DF116
B92316
1.3.2. Scăderea
La scăderea a două cifre de rang i , dacă cifra descăzutului este mai mică
decât cifra scăzătorului, apare un împrumut de la rangul i + 1.
Tabelul 1.3. Scăderea a două cifre binare.
x y Imprumutul Diferenţa
00 0 0
0 1 1 1
10 0 1
1 1 0 0
In cazul scăderii binare, diferenţa este 1 dacă fie descăzutul, fie scăzătorul
este 1. Imprumutul apare numai dacă descăzutul este 0 şi scăzătorul este 1. In
tabelul 1.3 se prezintă regula de scădere a două cifre binare x şi y .
Exemple
3210 −
1910
1310
10110 2 −
100112
000112
6B3216 −
4DF116
1D 4116
1.3.3. Inmulţirea
Inmulţirea se efectuează de obicei prin adunarea repetată a unor produse
parţiale. La înmulţirea a două cifre binare, produsul este 1 numai dacă
deînmulţitul şi înmulţitorul sunt 1. In tabelul 1.4 se prezintă regula de înmulţire a
două cifre binare x şi y .
Tabelul 1.4. Inmulţirea a două cifre binare.
x y Produsul
00 0
0 1 0
10 0
11 1
Exemplu
1100 ×
0110
0000
1100
1100
0000
1001000
1.3.4. Impărţirea
Impărţirea a două numere nu se poate efectua dacă împărţitorul este egal
cu zero. Fiind dat deîmpărţitul x şi împărţitorul y , pentru operaţia de împărţire
trebuie să se determine câtul Q şi restul R , astfel încât să fie satisfăcută relaţia:
X =Q⋅y +R
La împărţirea în zecimal se determină cifrele câtului prin alegerea unei cifre şi
scăderea din restul parţial (care este iniţial o parte a deîmpărţitului) a produsului
dintre această cifră şi împărţitor. Dacă rezultatul scăderii este un număr pozitiv mai
mic decât împărţitorul, cifra aleasă este corectă. In caz contrar, se alege o altă cifră
şi operaţia se repetă. In fiecare etapă a operaţiei se obţine o cifră a câtului.
In cazul împărţirii binare, dacă se alege în mod eronat o cifră a câtului, o
nouă alegere nu mai este necesară, existând numai două cifre. Operaţia de
împărţire se va reduce la o serie de scăderi ale împărţitorului din restul parţial, care
se efectuează numai dacă restul parţial este mai mare decât împărţitorul, caz în
care cifra câtului este 1; în caz contrar, cifra corespunzătoare a câtului este 0.
Exemplu
10010011 : 1011 = 1101
1011
1110 Rest parţial
1011
1111 Rest parţial
1011
100 Rest
1.4. Reprezentarea numerelor în calculator
In funcţie de soluţia aleasă pentru a indica semnul numerelor sau poziţia
virgulei, există mai multe moduri de reprezentare a numerelor în calculator.
Numerele reprezentate în calculator pot fi fără semn sau cu semn.
Numerele fără semn sunt reprezentate în binar sau într-un cod binar zecimal. In
cazul numerelor cu semn, se utilizează o cifră de semn pentru indicarea
semnului. Convenţional, se atribuie cifra 0 pentru semnul plus şi cifra 1 pentru
semnul minus. Cifra de semn este reprezentată pe poziţia c.m.s. a numărului.
Pentru reprezentarea unui număr binar cu semn de n cifre binare, sunt
necesare deci n + 1 poziţii.
In general, un număr are o parte întreagă şi o parte fracţionară, separate
prin virgula binară. Virgula nu se reprezintă fizic, dar trebuie cunoscută localizarea
ei. După modul de amplasare a virgulei binare, există două forme de reprezentare
a numerelor:
• Forma cu virgulă fixă;
• Forma cu virgulă mobilă.
In forma cu virgulă fixă, virgula care separă partea întreagă de cea
fracţionară este aşezată într-o poziţie bine definită a cuvântului binar. Există două
posibilităţi de poziţionare. Dacă virgula este aşezată după cifra de semn, se
operează cu numere fracţionare, subunitare. Dacă virgula este aşezată după
cifra c.m.p.s., se operează cu numere întregi. In continuare se presupune ultima
poziţionare, considerând că se lucrează cu numere întregi.
In forma cu virgulă mobilă, fiecare număr este caracterizat prin două valori:
• Mantisa, care indică mărimea exactă a numărului într-un anumit domeniu;
• Exponentul, care indică ordinul de mărime a numărului, fiind puterea la
care se ridică baza mantisei. Exponentul indică deci implicit poziţia virgulei
binare.
1.5. Reprezentarea numerelor în virgulă fixă
1.5.1. Reprezentarea numerelor cu semn
In continuare vom nota cu x , y numerele în reprezentarea binară
obişnuită, la care se ataşează semnul. Un număr cu n cifre se va scrie sub forma:
n −1
± x = ± x n −1x n −2 ...x1x 0 = ∑ x i × 2i
i =0
De exemplu
± 10110111
Vom nota cu X şi Y numerele exprimate în forma de reprezentare în
calculator. După modul de exprimare a numerelor negative, există trei forme
uzuale de reprezentare a numerelor cu semn în virgulă fixă:
• în mărime şi semn (MS);
• în complement faţă de 1 (C1);
• în complement faţă de 2 (C2).
Pentru toate formele de reprezentare, un număr pozitiv x se exprimă în
acelaşi fel:
n −1
X = 0 × 2n + ∑ x i × 2i = 0 × 2n + x (1.15)
i =0
Numărul pozitiv cu semn se reprezintă deci adăugând cifra 0 , de semn, în
faţa numărului fără semn:
X = 0 x n −1x n −2 ...x1x 0
Considerăm pentru simplitate numere reprezentate pe 4 biţi şi un bit de
semn. De exemplu, numărul fără semn 6 se reprezintă prin:
6 → 0110
iar numărul cu semn + 6 prin:
+ 6 → 0 0110
Reprezentarea numerelor negative depinde de modul de reprezentare
ale acestora.
1. In formă de reprezentare denumită în mărime şi semn (MS ) , un număr
negativ x va avea următoarea expresie:
n −1
∑ x i × 2i
n
= 1× 2n + x
X = 1× 2 + (1.16)
i =0
Deci, numărul negativ se reprezintă prin adăugarea cifrei 1, de semn, în faţa
numărului fără semn:
X = 1x n −1x n − 2 ...x1x 0
De exemplu numărul − 6 va fi reprezentat prin:
− 6 → 1 0110
Acest mod de reprezentate are mai multe dezavantaje. Un prim
dezavantaj este faptul că operaţiile de adunare şi scădere necesită circuite
mai electronice mai complexe. Al doilea dezavantaj constă în faptul că există
două reprezentări distincte pentru cifra 0 :
+ 0 → 0 0000
− 0 → 1 0000
In aceste condiţii este mai dificil să se verifice dacă o valoare este
egală cu 0 .
2. In cazul reprezentării în complement faţă de 1 (C1) , un număr negativ se
reprezintă prin complementul faţă de 1 al numărului pozitiv cu aceeaşi valoare
absolută. Complementul faţă de 1 al unui număr binar se obţine prin înlocuirea
biţilor de 1 cu 0, şi a celor de 0 cu 1. Un număr negativ x reprezentat în
complement faţă de 1 are expresia:
n −1
∑ x i × 2i
X = 1× 2n + (1.17)
i =0
unde x i = 1 − x reprezintă complementul fată de 1 al cifrei x i .
Reprezentarea unui număr negativ se obţine prin complementarea
tuturor cifrelor numărului fără semn şi adăugarea cifrei de semn 1:
_ _ _ _
X = 1x n −1 x n − 2 ... x 1 x 0
De exemplu
+ 6 → 0 0110
− 6 → 1 1001
Si în acest caz există două reprezentari distincte pentru cifra 0 :
+ 0 → 0 0000
− 0 → 1 1111
3. Un număr negativ x reprezentat în complement faţă de 2 (C 2) are
următoarea expresie:
n −1 _
∑ x i × 2i + 1× 20 = 2n +1 − x
X = 1× 2n + (1.18)
i =0
Reprezentarea unui număr negativ se poate obţine în mai multe
moduri. Una dintre posibilităţi este utilizarea relaţiei de definiţie (1.18).
Operaţia de scădere se efectuează luând în considerare şi bitul de
semn. De exemplu, considerând n = 4, reprezentarea numărului - 6 va fi:
100000 −
00110
11010
O altă posibilitate este obţinerea complementului faţă de 2 în două
etape:
1. Se obţine complementul faţă de 1.
2. Se consideră rezultatul ca un întreg fără semn, la care se adună
valoarea 1.
De exemplu:
+ 6 → 00110
− 6(C1) → 11001 +
1
--------
− 6(C 2) → 11010
Practic, complementul faţă de 2 al unui număr se poate determina
pornind de la numărul pozitiv cu semn, astfel:
1. Se scriu cifrele numărului începând cu cifra c.m.p.s., neschimbate,
până la primul 1 inclusiv.
2. Se complementează cifrele întâlnite în continuare.
In reprezentarea C2 există o singură codificare pentru cifra 0 . In plus,
operaţiile de adunare şi scădere se efectuează cel mai simplu în C2.
Să determinăm acum gama numerelor care pot fi exprimate în cele trei
forme de reprezentare.
Pentru toate cele trei forme numărul maxim pozitiv care poate fi
reprezentat pe n biţi este
0 111...11 = 2n − 1
In MS cel mai mare număr negativ care poate fi reprezentat este
1 111...11 = −( 2n − 1)
In C1 numărul negativ maxim este
1 000...00
care corespunde numărului pozitiv
0 111...11 = 2 n − 1
Putem trage concluzia că gama numerelor care pot fi exprimate pe n
biţi în MS şi C1 este
− (2 n − 1) ≤ x ≤ 2 n − 1
Numărul maxim negativ care poate fi reprezentat în C2 este
1 000...00
care corespunde numărului pozitiv
1 000...00 = 2 n
Deci pentru reprezentarea în C2 această gamă este
− 2n ≤ x ≤ 2n − 1
In tabelul 1.5 se prezintă reprezentarea unor numere cu 4 biţi şi un bit de
semn în MS, C1 şi C2.
Tabelul 1.5. Diferite moduri de reprezentare a unor numere cu semn.
MS C1 C2
x
+15 0 1111 0 1111 0 1111
+14 0 1110 0 1110 0 1110
... ... ... ...
+2 0 0010 0 0010 0 0010
+1 0 0001 0 0001 0 0001
0 0 0000 0 0000 0 0000
1 0000 1 1111
-1 1 0001 1 1110 1 1111
-2 1 0010 1 1101 1 1110
... ... ... ...
-14 1 1110 1 0001 1 0010
-15 1 1111 1 0000 1 0001
-16 1 0000
- -
1.5.2. Reguli de deplasare a numerelor cu semn
De multe ori, în regiştrii procesorului, sunt necesare operaţii de deplasare a
numerelor cu semn. Aceste deplasări trebuie efectuate astfel încât să se modifice
numai valoarea numerelor, nu şi semnul. Deplasarea la stânga cu o poziţie este
echivalentă înmulţirii cu 2, iar deplasarea la dreapta este echivalentă împărţirii
cu 2 (înmulţirii cu 2 −1 ).
Pentru stabilirea regulilor de deplasare, se consideră exemplele din tabelul
1.6.
Tabelul 1.6. Stabilirea regulilor de deplasare a numerelor cu semn.
MS C1 C2
+6 0 0110 0 0110 0 0110
X
X ×2 +12 0 1100 0 1100 0 1100
X × 2 −1 + 3 0 0011 0 0011 0 0011
-6 1 0110 1 1001 1 1010
X
X ×2 -12 1 1100 1 0011 1 0100
−1 - 3 1 0011 1 1100 1 1101
X ×2
La deplasare participă numai cifrele numerelor. Din analizarea tabelului
rezultă următoarele:
• In cazul deplasării numerelor pozitive, în poziţiile rămase libere după
deplasarea la stânga sau la dreapta se introduc cifre de 0.
• La numerele negative reprezentate în MS, în poziţiile rămase libere după
o deplasare la stânga sau la dreapta se introduc cifre de 0.
• La numerele negative reprezentate în C1, în poziţiile rămase libere după
o deplasare la stânga sau la dreapta se introduc cifre de 1.
• La numerele negative reprezentate în C2, în poziţiile rămase libere după
o deplasare la stânga se introduc cifre de 0, iar după o deplasare la
dreapta se introduc cifre de 1 (deci, se repetă semnul numărului).

Cap 2. Calculatorul numeric


2.1. Structura unui calculator
In 1945, John von Neumann a stabilit structura logica a calculatorului cu
program memorat. Calculatoarele construite anterior dispuneau doar de
programe cablate, adică pentru a schimba programul care urma să prelucreze
datele trebuiau schimbate conexiunile dintre diverse părţi ale calculatorului.
Majoritatea calculatoarelor actuale respectă această structură (figura 2.1).
Ideea principală a calculatorului cu program memorat constă în faptul că
atât instrucţiunile, cât şi datele sunt păstrate în aceeaşi memorie. Datele sunt
cele asupra cărora se efectuează prelucrări. Instrucţiunile sunt interpretate ca şi
coduri pentru generarea semnalelor de control necesare funcţionării
calculatorului.
Componentele principale ale unui calculator sunt următoarele:
1. Unitatea centrala de prelucrare sau UCP (Central Processing Unit –
CPU). UCP realizează prelucrarea datelor şi controlează funcţionarea
calculatorului. Această unitate este întâlnită de multe ori sub denumirea de
procesor. Dacă procesorul este realizat pe o singură pastilă de siliciu
atunci se numeşte microprocesor ( μP )
2. Unitatea de memorie (memoria principală şi secundară): această unitate
are rolul de a păstra datele şi instrucţiunile.
3. Unitatea de intrare/ieşire (I/E): efectuează transferul datelor între calculator
şi mediul exterior acestuia.
4. Interconexiunile: permit comunicaţia între UCP, memoria internă şi
unitatea de l/E şi poartă denumirea de magistrale.
Figura 2.1. Structura unui calculator.
2.2. Unitatea centrală de prelucrare (UCP)
Componenta cea mai complexă este unitatea centrală de prelucrare, cu
structura din figura 2.2.
Figura 2.2. Structura unităţii centrale de prelucrare (UCP).
Unitatea centrală de prelucrare (UCP) are următoarele funcţii principale:
- Extragerea instrucţiunilor: UCP trebuie să citească instrucţiunile din memo-
rie.
- Interpretarea instrucţiunilor: fiecare instrucţiune trebuie decodificată pentru a
determina operaţia care trebuie executată.
- Citirea datelor: pentru execuţia unor instrucţiuni este necesară citirea
datelor din memorie sau de la un dispozitiv de I/E.
- Prelucrarea datelor: execuţia unei instrucţiuni poate necesita efectuarea
unei operaţii aritmetice sau logice asupra datelor.
- Scrierea datelor: rezultatele execuţiei trebuie scrise în memorie sau trimise
la un dispozitiv de I/E.
Componentele principale ale UCP sunt următoarele:
- Unitatea aritmetică şi logică sau UAL (Arithmetic and Logic Unit – ALU)
execută prelucrările asupra datelor.
- Regiştrii reprezintă o memorie internă pentru UCP.
- Unitatea de comandă şi control (UCC) controlează funcţionarea UCP şi a
celorlalte unităţi ale calculatorului.
- Interconexiunile interne din cadrul UCP asigură comunicaţia dintre UAL,
registri şi UCC. Aceste interconexiuni sunt realizate sub forma unei magistrale,
numită magistrală internă a UCP.
Figura 2.3 prezintă o imagine mai detaliată a UCP. Se pune în evidenţă
magistrala internă a UCP, care este necesară pentru transferul datelor între
diferiţii regiştri ale UAL, deoarece UAL prelucrează doar datele din memoria
internă a UCP. In această figură sunt indicate, de asemenea, elemente
componente tipice ale UAL.
2.2.1. Unitatea aritmetică şi logică
UAL implementează diferite operaţii aritmetice şi logice asupra operanzilor
obţinuţi din memorie. Conţine, în principal, un circuit logic pentru adunare, numit
sumator, toate operaţiile aritmetice reducându-se la o succesiune de operaţii de
adunare.
Fig. 2.3. Structura mai detaliată a UCP.
Operaţiile efectuate de UAL pot fi: transferuri de date între regiştri şi între
aceştia şi memorie; operaţii aritmetice; operaţii logice (Şl, SAU, NU); operaţii de
deplasare a conţinutului unui registru sau locaţie de memorie; operaţii de
comparaţie a doi operanzi.
UAL generează informaţii referitoare la rezultatul ultimei instrucţiuni aritmetice
şi logice executate. Acestea se referă la semnul rezultatului, la paritatea acestuia, la
cazurile în care a apărut un transport sau un împrumut în cursul prelucrării. Fiecare
din aceste informaţii se păstrează în câte un bistabil, bistabilele fiind reunite într-un
registru de stare. Acest registru conţine şi alte informaţii referitoare la starea
programului.
2.2.2. Regiştri
Pentru a putea executa aceste funcţii, UCP necesită memorarea temporară a
unor date într-o memorie internă proprie. Această memorie este formată dintr-un
set de regiştri.
Setul de regiştri din cadrul UCP păstrează temporar operanzii unei operaţii
aritmetice sau logice, rezultatele intermediare şi finale sau adresele acestora.
Utilizarea regiştrilor creşte viteza de prelucrare, eliminând necesitatea accesului
repetat la memorie. Ele reprezintă deci o memorie internă foarte rapidă.
Unii regiştri pot avea funcţii dedicate, altele se pot utiliza pentru orice
operaţii, fiind regiştri generali. Un registru special îl reprezintă registrul acumulator
care păstrează de obicei unul din operanzii care participă la o operaţie şi apoi
rezultatul operaţiei. O parte din regiştri nu sunt accesibili prin program, fiind regiştri
de lucru. Un asemenea registru este, de exemplu, registrul de instrucţiuni, care
păstrează instrucţiunea curentă (cea care se execută la un moment dat).
Regiştri din cadrul UCP sunt de două tipuri:
- Regiştri utilizator: Acestea permit reducerea numărului de accese la memo-
ria principală şi deci creşterea vitezei de execuţie a programelor.
- Regiştri de control şi de stare: Acestea sunt utilizate de unitatea de control
pentru controlul funcţionării UCP şi de programele sistemului de operare pentru
controlul execuţiei programelor.
Regiştri utilizator
Aceşti regiştri sunt accesibili prin instrucţiunile limbajului maşină. Se
deosebesc următoarele categorii de regiştri utilizator:
- Regiştri generali;
- Regiştri de date;
- Regiştri de adrese;
Regiştrii generali sunt implicaţi în majoritatea instrucţiunilor aritmetice şi
logice putând fi utilizaţi în diferite scopuri de către programe. De obicei aceşti
regiştri pot conţine operandul oricărei instrucţiuni. In multe cazuri există însă
restricţii, de exemplu pot exista regiştri dedicaţi pentru anumite operaţii aritmetice.
Uneori, regiştri generali se pot utiliza pentru adresarea operanzilor, prin diverse
moduri de adresare.
Regiştri de date se pot utiliza numai pentru păstrarea datelor.
Regiştri de adrese, utilizaţi pentru adresarea instrucţiunilor sau a datelor, pot
avea o utilizare generală, sau pot fi dedicaţi unui anumit mod de adresare.
Regiştri de control şi de stare
In general, aceşti regiştri nu sunt vizibili programatorilor, sau unii din ei pot fi
vizibili pentru instrucţiunile maşină executate într-un mod special al UCP numit mod
privilegiat (sau protejat). Fiecare tip de calculatoare are organizări proprii ale
regiştrilor şi utilizează terminologii diferite. Totuşi, se pot deosebi următorii regiştri
care sunt esenţiali pentru execuţia instrucţiunilor:
- Contorul de program (PC): Conţine adresa următoarei instrucţiuni care va
fi extrasă din memorie.
- Registrul de instrucţiuni (Rl): conţine ultima instrucţiune extrasă din
memorie.
- Registrul de adrese al memoriei (RA): conţine adresa unei locaţii de
memorie.
- Registrul de date al memoriei (RD): conţine cuvântul de date care se va
înscrie în memorie sau cuvântul citit recent.
- Registrul cuvântului de stare (PSW-Program Status Word).
Contorul de program (PC) conţine adresa instrucţiunii următoare, deoarece de
obicei acest registru este actualizat de UCP imediat după fiecare extragere a
unei instrucţiuni. O instrucţiune de salt va modifica, de asemenea, contorul de
program. Instrucţiunea extrasă din memorie este depusă în registrul de instrucţiuni,
unde ea este analizată (decodificată). Transferul datelor între UCP şi memorie are
loc prin intermediul regiştrilor de adrese şi de date (RA, respectiv RD). Registrul RA
este conectat la magistrala de adrese, iar RD la magistrala de date.
UCP conţine un registru numit cuvânt de stare al programului (PSW-Program
Status Word). Acest registru păstrează indicatori de condiţii şi alte informaţii de
stare. Câmpurile principale ale acestui registru sunt:
- Semn: conţine bitul de semn al rezultatului ultimei operaţii aritmetice.
- Zero: este setat atunci când rezultatul este 0.
- Transport (Carry): este setat dacă a rezultat un transport sau un împrumut
la o operaţie aritmetică.
- Egal: este setat dacă rezultă o egalitate în urma unei operaţii de comparare.
- Depăşire (Overflow): este utilizat pentru a indica o depăşire la o operaţie
aritmetică.
- Validare întreruperi (Interrupt Enable/Disable): este utilizat pentru validarea
sau invalidarea întreruperilor.
- Supervizor (Supervisor): acest indicator arată dacă UCP execută un
program în mod supervizor sau în mod utilizator. Anumite instrucţiuni privilegiate
pot fi executate numai în mod supervizor şi anumite zone de memorie sunt
accesibile numai în acest mod.
Pot exista şi alţi regiştri din această categorie, de exemplu pentru controlul
operaţiilor de l/E.
2.2.3. Unitatea de comandă şi control
UCC coordonează activitatea calculatorului în sensul că extrage instrucţiunile
programului din memorie, le decodifică (le interpretează) şi generează secvenţa
semnalelor de comandă necesare execuţiei.
Pe parcursul execuţiei unei instrucţiuni, unitatea de comandă primeşte de la
unitatea aritmetică şi logică informaţii de stare, în funcţie de care selectează una din
alternativele de continuare a operaţiei. La terminarea execuţiei, se trece la
instrucţiunea următoare. Adresa acestei instrucţiuni este păstrată în registrul PC
(contor de program).
2.2.4. Unitatea de memorie
Memoria reprezintă sursa sau destinaţia tuturor informaţiilor. In memorie
sunt încărcate informaţiile iniţiale (date şi instrucţiuni) prin dispozitivele de
intrare şi de la memorie sunt preluate rezultatele prin intermediul dispozitivelor
de ieşire.
Memoria este organizată ca o colecţie de locaţii de memorie. Fiecărei
locaţii i se asociază o adresă prin intermediul căreia se poate selecta locaţia
respectivă. Adresarea se realizează cu ajutorul unor linii de adresă, numărul
acestor linii determinând capacitatea maximă adresabilă a memoriei. De
exemplu, cu 16 linii de adresă se pot selecta maxim 216 locaţii de memorie.
O locaţie de memorie se caracterizează prin:
- Adresă - poziţia locaţiei în cadrul memoriei.
- Conţinut - valoarea memorată la această adresă.
Cantitatea de informaţie care poate fi memorată într-o locaţie adresabilă
individual, exprimată ca număr de cifre binare (biţi), se numeşte lungime a
cuvântului de memorie. De obicei, memoria este organizată pe cuvinte de 16,
32 sau 64 de biţi, unitatea adresabilă fiind octetul.
Capacitatea memoriei se exprimă în Kocteţi (KB) sau multipli ai acestuia:
1 KB=210B=1024B
1MB=210KB=220B
1GB = 210 MB = 230 B
Memoria trebuie să aibă o capacitate cât mai mare şi o viteză cât mai
ridicată, adică un timp de acces cât mai redus. Viteza este direct proporţională
cu costul. De aceea, majoritatea calculatoarelor au două tipuri de memorii, care
lucrează pe principii diferite:
- O memorie rapidă, numită memorie principală, care comunică direct cu
unitatea de calcul şi cea de comandă, cu un cost pe bit relativ ridicat;
- O memorie mai lentă, numită memorie secundară cu o capacitate mult
mai mare şi cu un cost pe bit mai redus (disc magnetic dur, bandă magnetică,
disc flexibil).
Operaţiile de citire şi de scriere în locaţiile de memorie selectate pe baza
adreselor acestora se realizează cu ajutorul unui ansamblu de circuite care
formează, împreună cu memoria, unitatea de memorie.
2.2.5. Unitatea de intrare/ieşire
Această unitate asigură comunicaţia dintre calculator şi mediul exterior.
Utilizatorii comunică sistemului informaţiile înregistrate pe suporturi externe de
informaţie cum ar fi suporturile magnetice, optice sau memorii flash, iar
rezultatele prelucrărilor sunt furnizate utilizatorilor pe suporturi magnetice, optice
memorii flash sau pe hârtie. Transmiterea informaţiilor de pe suporturile externe
în memorie şi înregistrarea informaţiilor pe asemenea suporturi sunt efectuate
de echipamentele periferice.
Echipamentele periferice de intrare cele mai des întâlnite sunt tastatura,
mouse-ul, scanner-ul, hard disk-ul, CD-Rom-ul, floppy disk-ul, iar cele de ieşire
sunt display-ul, imprimanta, hard disk-ul, CD-Rom-ul, floppy disk-ul.
Acestea sunt conectate la calculator prin interfeţe de I/E, existente în
cadrul unităţilor de l/E, care îndeplinesc două funcţii importante: de conversie de
date şi de memorie tampon.
Conversia este necesară deoarece informaţia este reprezentată diferit şi
pe medii diferite, fiind necesară compatibilizarea dispozitivelor respective.
Funcţia de memorie tampon este necesară pentru că viteza de lucru a
calculatorului (UAL şi UCC) este cu câteva ordine de mărime mai mare decât a
dispozitivelor exterioare. Memoria tampon asigură sincronizarea funcţionării
calculatorului cu aceste dispozitive.
2.2.6. Interconexiuni
Interconectarea unităţilor componente ale calculatorului se realizează prin
una sau mai multe magistrale. O magistrală este formată dintr-un grup de linii
destinate transferului paralel al informaţiilor de la una sau mai multe surse la
una sau mai multe destinaţii. Numărul liniilor magistralei este egal de obicei cu
lungimea cuvântului transferat.
Magistralele pot fi unidirecţionale sau bidirecţionale. La un moment dat, nu
poate fi selectată decât o sursă şi una sau mai multe destinaţii.
Selecţia sursei şi a destinaţiei se realizează cu multiplexoare şi
decodificatoare. Multiplexorul stabileşte sursa care depune informaţia pe
magistrală, iar decodificatorul selectează destinaţiile care vor fi cuplate la
magistrală.
In funcţie de semnalele vehiculate, magistralele pot fi de adrese, de date
şi de control.
2.3. Execuţia instrucţiunilor
Funcţia principală a unui calculator este execuţia programelor. UCP
realizează această funcţie prin execuţia instrucţiunilor specificate de programul
aflat în memorie. UCP citeşte (extrage) câte o instrucţiune din memorie, o execută
şi apoi trece la următoarea instrucţiune. Prelucrarea necesară pentru o
singură instrucţiune reprezintă un ciclu de instrucţiune (figura 2.4).
Fiecare ciclu de instrucţiune constă din două părţi principale: subciclul de
extragere şi subciclul de execuţie. Pe lângă aceste subcicluri, mai poate exista un
ciclu de întrerupere şi subciclul de indirectare. Dintre acestea ciclul de
indirectare va fi studiat într-unul din capitolele următoare. Procesul de execuţie
al instrucţiunilor se opreşte numai la oprirea calculatorului, la apariţia unei erori sau
la întâlnirea unei instrucţiuni de oprire a execuţiei programului.
2.3.1. Subciclul de extragere
In acest subciclu se citeşte din memorie o nouă instrucţiune. UCP păstrează
Fig. 2.4
evidenţa ultimei instrucţiuni extrase din memorie şi, în mod obişnuit, extrage
următoarea instrucţiune, deci cea de la adresa imediat următoare. Această
secvenţă obişnuită poate fi modificată prin instrucţiuni de salt.
Figura 2.5 prezintă transferurile de date din acest subciclu. Registrul PC
conţine adresa instrucţiunii care urmează să fie executată. Această adresă este
depusă în RA şi este plasată pe magistrala de adrese.
Unitatea de comandă solicită o operaţie de citire a memoriei, iar rezultatul
este plasat pe magistrala de date şi reţinut în RD, de unde este apoi transferat în
Rl. In acelaşi timp, PC este incrementat cu 1, fiind pregătit pentru următorul
subciclu de extragere.
Fig.2.5
2.3.2. Subciclul de execuţie
Instrucţiunea citită din memorie se prezintă sub forma unui cod binar care
este interpretat de UCP, executând acţiunea specificată de acest cod. Această
acţiune se poate încadra într-una din următoarele categorii:
- Transfer între UCP şi memorie;
- Transfer între UCP şi dispozitivele de I/E;
- Operaţie aritmetică sau logică;
- Operaţie de control, de exemplu modificarea secvenţei normale de
execuţie a instrucţiunilor.
Subciclul de execuţie diferă în funcţie de tipul instrucţiunii, deci de acţiunea
executată.
Pentru exemplificare să considerăm un calculator ipotetic, cu structura
instrucţiunilor şi a datelor din figura 2.6. Lungimea instrucţiunilor şi a datelor întregi
este de 16 biţi. Memoria este organizată pe locaţii de 16 biţi (cuvinte). Aşa cum se
constată din figură o instrucţiune are un câmp de adresă de 12 biţi şi un câmp
pentru memorarea codului operaţiei de 4 biţi. Din structura instrucţiunilor rezultă că
pot exista 24 = 16 coduri de operaţii (coduri de instrucţiuni) şi se pot adresa până la
212 = 4096 cuvinte de memorie.
(b) Formatul datelor întregi
0001 (1h) = încarcă AC din memorie
0010 (2h) = Memorează AC
0101 (5h) = Adună la AC conţinutul memoriei
(c) Lista parţială a codurilor de operaţie
Fig. 2.6
In Fig. 2.6c se specifică câteva coduri de operaţii care urmează să fie
utilizate în continuare.
Să considerăm un fragment de program pentru adunarea conţinutului a două
cuvinte succesive de memorie, cu adresele 9B0h şi 9B1h şi memorarea rezultatului
în locul cuvântului al doilea. Fragmentul de program se află în memorie, începând
de la adresa 100h. Se notează cu PC contorul de program, cu AC registrul
acumulator şi cu Rl registrul de instrucţiuni.
In figura 2.7 se prezintă execuţia acestui fragment de program, indicându-se
conţinutul relevant al memoriei şi al regiştrilor UCP. Pentru simplificare vom
considera notaţia hexazecimală.
Fig.2.7
Etapele de execuţie ale acestui fragment de program sunt următoarele:
1. Contorul de program PC conţine valoarea 100h, adresa primei instrucţiuni.
Această instrucţiune este depusă în registrul de instrucţiuni Rl.
2. Cei 4 biţi mai semnificativi din Rl care au valoarea 1h determină încărcarea
registrului AC. Ceilalţi biţi specifică adresa locaţiei de memorie 9B0h.
Rezultatul execuţiei acestei instrucţiuni este încărcarea în registrul
acumulator a valorii 0005.
3. Contorul de program PC este incrementat şi se extrage următoarea
instrucţiune.
4. Se execută instrucţiunea care are ca efect adunarea vechiul conţinut al AC
cu conţinutul locaţiei 9B0h şi rezultatul se depune în AC.
5. Contorul de program PC este incrementat şi se extrage următoarea
instrucţiune.
6. Se execută instrucţiunea din RI care are ca efect memorarea conţinutului AC
la adresa 9B1h.
In acest exemplu, sunt necesare trei cicluri de instrucţiune, fiecare constând
dintr-un subciclu de extragere şi unul de execuţie. In cazul unui set de instrucţiuni
mai complex, sunt necesare mai puţine cicluri. De exemplu, pot exista
instrucţiuni care conţin mai multe adrese, care adună conţinutul a două locaţii de
memorie şi memorează rezultatul într-una din aceste locaţii. Astfel, subciclul de
execuţie pentru o instrucţiune poate necesita mai multe referiri la memorie. De
asemenea, în locul unei referiri la memorie, o instrucţiune poate specifica o
operaţie de l/E.
Cu aceste consideraţii, structura mai detaliată a unui ciclu de instrucţiuni este
prezentată în figura 2.8, sub forma unei diagrame de stare. Pentru anumite
instrucţiuni, unele stări nu vor fi executate, iar pentru altele vor fi executate de mai
multe ori.
Fig.3.8
Stările pot fi descrise astfel:
- Determinarea adresei instrucţiunii următoare (AIU): cel mai frecvent această
operaţie implică incrementarea contorului de program PC.
- Extragerea instrucţunii (EI): se citeşte instrucţiunea din memorie şi este
adusă în Rl.
- Decodificarea codului instrucţiunii (DCO): se analizează instrucţiunea pentru
a determina tipul operaţiei de executat şi operanzii care trebuie utilizaţi.
- Calculul adresei operandului (CAO): dacă operaţia implică utilizarea unui
operand din memorie sau care se poate obţine printr-o operaţie de I/E, se de-
termină adresa acestui operand.
- Extragerea operandului (EOP): se citeşte operandul din memorie sau de la
un dispozitiv de I/E.
- Execuţia operaţiei asupra datelor (OD): se execută operaţia indicată.
- Memorarea rezultatului (MR): se înscrie rezultatul în memorie sau se
transmite la un dispozitiv de I/E.
Stările din partea superioară a diagramei implică un transfer între UCP şi
memorie, sau UCP şi un dispozitiv de I/E. Stările din partea inferioară implică numai
operaţii interne UCP. Starea CAO apare de două ori, deoarece o instrucţiune poate
implica o operaţie de citire, de scriere, sau ambele.
La anumite calculatoare, o singură instrucţiune poate specifica o operaţie
asupra unui vector de numere (tablou unidimensional) sau un şir de caractere.
Aceasta se reflectă în diagramă.
2.3.3. Subciclul de întrerupere
Calculatoarele dispun de un mecanism prin care diferite module pot
întrerupe operaţiile executate de UCP. Întreruperile sunt prevăzute în primul
rând pentru a creşte eficienţa UCP. De exemplu, cele mai multe periferice sunt
lente comparativ cu UCP şi aceasta trebuie să rămână inactivă până la
terminarea unei operaţii de transfer. Prin existenţa întreruperilor, UCP poate
executa alte instrucţiuni în timpul unei operaţii de I/E. Atunci când un periferic
este pregătit pentru a accepta date de la UCP, sau pentru a transmite date la
UCP, modulul de I/E al perifericului transmite o cerere de întrerupere către UCP.
UCP răspunde prin suspendarea execuţiei programului curent, executând un
program de servire (de tratare) a întreruperii, după care va relua execuţia
programului.
Pentru recunoaşterea întreruperilor, se adaugă ciclului de instrucţiune un
subciclu de întrerupere (figura 2.9). In acest subciclu, UCP testează dacă a
apărut o cerere de întrerupere.
Dacă semnalul de cerere a întreruperii nu este activat, UCP continuă cu
subciclul de extragere. Dacă a apărut o întrerupere, UCP execută următoarele:
Fig.3.9
1. Salvează contextul programului curent. Aceasta înseamnă salvarea adresei
următoarei instrucţiuni de executat şi a altor date din regiştri, care sunt sem-
nificative pentru programul respectiv.
2. Încarcă în contorul de program adresa programului de servire a întreruperii.
UCP va executa în continuare instrucţiunile din rutina de servire, după care va
reveni la programul întrerupt.
UCP poate dezactiva (invalida) toate sau o parte a semnalelor de
întrerupere. O întrerupere dezactivată are ca efect faptul că UCP va ignora
cererea respectivă de întrerupere. De exemplu, în general este de dorit să se
termine servirea unei întreruperi înaintea acceptării alteia. Pentru acest motiv
alte întreruperile sunt de obicei dezactivate în timpul servirii unei întreruperi.
Dacă apar alte întreruperi în acest timp, ele vor fi servite după validarea
întreruperilor.
Transferurile de date din subciclul de întrerupere se prezintă în figura 2.10.
Fig.2.10
Conţinutul curent al PC trebuie salvat astfel încât UCP să poată relua
programul întrerupt. Adresa unei locaţii speciale de memorie rezervată pentru
memorarea PC este depusă în RA de unitatea de comandă. PC poate fi salvat
în memoria stivă, caz în care în RA se transferă indicatorul de stivă. Conţinutul
PC este transferat în RD pentru a fi înscris în memorie. Adresa rutinei de tratare
a întreruperii se transferă apoi în PC. Ca urmare, următorul ciclu de instrucţiune
va începe prin extragerea primei instrucţiuni din rutina de tratare.

Cap.3. UNITATEA ARITMETICĂ Şl LOGICĂ


Unitatea aritmetică şi logică (UAL) este acea parte a calculatorului care
efectuează asupra datelor operaţiile aritmetice şi logice specificate de instrucţiuni.
Operaţiile aritmetice executate de UAL sunt adunarea, scăderea, înmulţirea şi
împărţirea. Există o mare varietate de tehnici pentru realizarea acestor operaţii, dintre
care unele vor fi prezentate în acest capitol.
Dintre operaţiile logice efectuate de UAL amintim compararea unui număr cu
zero, determinarea semnului unui număr, sau compararea a două numere între ele.
UAL execută, de asemenea, funcţii logice de bază cum ar fi SI, SAU, SAU
EXCLUSIV.
3.1. Circuite pentru adunarea a două cifre binare
Considerăm două numere, A şi B, de câte n biţi fiecare:
A : An −1...Ai Ai −1...A1A0
B : Bn −1...Bi Bi −1...B1B0
Pentru adunarea bit cu bit a numerelor, este nevoie de un circuit de adunare,
care să adune două cifre binare de un anumit rang i , Ai şi Bi şi care să ţină cont de
cifra de transport de la rangul anterior i − 1, fie aceasta Ti −1 . Circuitul trebuie să
genereze cifra sumă Si şi cifra de transport Ti , către rangul următor.
Acest circuit are trei intrări, Ai , Bi , Ti −1 şi două ieşiri, Si şi Ti şi se numeşte
sumator elementar. Reprezentarea simbolică a circuitului este dată în figura 3.1.
.
Fig.3.1
Tabelul de adevăr al circuitului este prezentat în tabelul 3.1
Tabelul 3.1.
AiBiTi-1 Si Ti
000 0 0
001 1 0
010 1 0
011 0 1
100 1 0
101 0 1
110 0 1
111 1 1
Ecuaţiile logice care rezultă sunt următoarele:
(3.1)
Si = Ai BiTi −1 + Ai Bi Ti −1 + Ai Bi Ti −1 + Ai Bi Ti −1
(3.2)
Ti = Ai Bi Ti −1 + Ai BiTi −1 + Ai Bi Ti −1 + Ai BiTi −1
Prin gruparea termenilor celor două expresii obţinem
Si = ( Ai Bi + Ai Bi )Ti −1 + ( Ai Bi + Ai Bi )Ti −1
= ( Ai ⊕ Bi )Ti −1 + ( Ai ⊕ Bi )Ti −1
(3.3)
= ( Ai ⊕ Bi ) ⊕ Ti −1 = Ai ⊕ Bi ⊕ Ti −1
(3.4)
Ti = ( Ai Bi + Ai Bi )Ti −1 + Ai Bi = ( Ai ⊕ Bi )Ti −1 + Ai Bi
Schema corespunzătoare este prezentată în figura 3.2.
Ti-1
Fig. 3.2
Dacă nu se ţine cont de transportul Ti −1 , circuitul se numeşte semisumator
elementar. Acest circuit are două intrări, Ai şi Bi şi două ieşiri, Si şi Ti .
Reprezentarea simbolică este prezentată în figura 3.3.
Fig. 3.3
Pe acelaşi principiu se pot realiza scăzătoare elementare. Un scăzător elementar
primeşte la intrare cei doi biţi care trebuie scăzuţi şi bitul de împrumut de la poziţia mai puţin
semnificativă şi generează la ieşire bitul diferenţă şi împrumutul către bitul din poziţia mai
semnificativă.
3.2. Operaţii cu numere în virgulă fixă
3.2.1. Adunarea
Operaţia de adunare se poate efectua în serie, când biţii celor doi operanzi
sunt prelucraţi succesiv, sau în paralel, când biţii sunt prelucraţi simultan.
Dispozitivele de adunare corespunzătoare sunt sumatorul serie, respectiv sumatorul
paralel.
3.2.1.1. Sumatorul serie
Schema unui sumator serie de n biţi este prezentată în figura 3.4. Sumatorul se
compune din două registre de deplasare A şi B, de câte n biţi fiecare, cu posibilitatea
de încărcare paralelă, un singur sumator elementar S şi un element de întârziere de
un tact, format dintr-un bistabil D. Operanzii de câte n biţi se încarcă în paralel în
registrele A şi B. Bistabilul D este şters, astfel încât iniţial Ti −1 va fi 0.
Fig. 3.4
Biţii operanzilor se aplică la intrările sumatorului în mod secvenţial, iniţial
aplicându-se biţii c.m.p.s. ( A0 , B0 ). In fiecare moment i , sumatorul generează suma
Si şi cifra de transport Ti . La fiecare impuls de ceas, registrele se deplasează la
dreapta cu o poziţie, aplicând la intrările sumatorului următorii biţi, iar suma Si se
introduce în registrul A , pe poziţia care s-a eliberat (se utilizează intrarea serie în
acest scop). In acelaşi timp, transportul Ti se introduce în bistabilul D care realizează
întârzierea semnalului cu un ciclu de ceas. In următorul ciclu de ceas, când Ti se
transformă în cifra Ti −1 a rangului următor, acest semnal este aplicat la intrarea
sumatorului elementar.
Întregul proces are loc în n impulsuri de ceas, obţinându-se rezultatul în
registrul A . După n impulsuri de ceas, bistabilul D conţine transportul de la rangul
cel mai semnificativ. Dacă acest transport este 1, suma are n + 1 biţi, deci are loc o
depăşire a capacităţii registrului sumă A .
Registrul A memorează la început unul din operanzi, iar la sfârşit rezultatul.
Acest registru lucrează deci ca un acumulator, motiv pentru care această structură se
numeşte structură cu acumulator.
3.2.1.2. Sumatorul paralel
Pentru a reduce timpul necesar pentru calcularea sumei adunarea celor doi
operanzi se poate efectua în paralel. Schema unui sumator paralel de n biţi este
prezentată în figura 3.5.
Sumatorul este format din două registre paralele A şi B, pentru cei doi
operanzii de n biţi, un registru R care păstrează suma şi n sumatoare elementare.
Fiecare sumator de rang i primeşte de la rangul i − 1 transportul Ti −1 şi generează
transportul Ti pentru rangul următor.
Primul sumator, cel corespunzător cifrei c.m.p.s., poate fi înlocuit cu un
semisumator, deoarece nu există transport de la rangul precedent. Transportul de
la rangul c.m.s. este folosit pentru a indica depăşirea de capacitate a registrului
sumă. Acest transport se păstrează în bistabilul OV (Overflow). Intrarea T−1 şi ieşirea
Tn −1 se pot utiliza pentru extinderea sumatorului la un număr mai mare de biţi.
Fig. 3.5
La primul impuls de ceas se înscriu operanzii în registrele A şi B. Semnalele de
la ieşirile registrelor A şi B sunt aplicate la intrările celor n sumatoare elementare.
După timpul necesar propagării transportului de la sumatorul S0 spre Sn-1, la
ieşirile sumatoarelor elementare apare suma celor două numere. La următorul
impuls de ceas, rezultatul este înscris în registrul R.
Se poate utiliza şi în acest caz un registru acumulator, pentru a păstra atât
unul din operanzi, cât şi rezultatul. Un asemenea sumator paralel, obţinut prin
interconectarea unor sumatoare elementare, se numeşte sumator cu transport
succesiv.
Sumatorul paralel efectuează adunarea pe un ciclu de ceas, iar cel serie pe n
cicluri de ceas. Totuşi, sumatorul paralel nu este de n ori mai rapid decât cel serie,
deoarece transportul se propagă în serie prin cele n sumatoare. Trebuie deci
prevăzut un timp suficient pentru ca cifra de transport să se propage în cazul cel mai
defavorabil (când acesta se propagă prin toate nivelurile). Frecvenţa ceasului
trebuie aleasă funcţie de acest timp de propagare.
3.2.2. Înmulţirea binară
Există numeroase metode de înmulţire binară. Cele mai importante sunt
următoarele:
• Metoda adunării repetate;
• Înmulţirea într-o bază superioară;
• Înmulţirea prin metoda Booth.
Fiecare din aceste metode are mai multe variante, care ţin cont de modul
reprezentare a numerelor cu semn sau urmăresc creşterea vitezei de execuţie
operaţiei.
3.2.2.2. Înmulţirea prin metoda Booth
Dacă numerele din calculator sunt reprezentate în C2, se preferă o metodă
de înmulţire care operează direct asupra numerelor în această reprezentare.
Avantajul unei asemenea metode constă în eliminarea operaţiei de complementare
a operanzilor şi a rezultatului, dacă aceştia sunt negativi, ceea ce este important în
cazul conversiei din C2 în MS, care este mai dificilă decât cea din C1 în MS.
Pentru rezolvarea acestei probleme s-au elaborat mai multe metode dintre care
amintim metoda Burks-Goldstine-von Neumann, metoda Robertson şi metoda
Booth. Dintre acestea, metoda Booth este cea mai utilizată.
Pentru a înţelege principiul metodei Booth să considerăm două numere X şi
Y , care reprezintă deînmulţitul, respectiv înmulţitorul. Pentru început să
presupunem că în cadrul înmulţitorului există un grup compact de cifre 1
înconjurat de cifre 0. Astfel dacă înmulţitorul este
Y = 00111110
Produsul celor două numere este dat de
X ⋅ Y = X ⋅ (00111110 ) =
= X ⋅ (0 × 2 7 + 0 × 2 6 + 1 × 25 + 1 × 2 4 + 1 × 23 + 1 × 2 2 + 1 × 21 + 0 × 2 0 ) =
= X ⋅ (25 + 2 4 + 23 + 2 2 + 21 ) = X ⋅ 62
Rezultă că pentru calcularea produsului trebuiesc efectuate 5 adunări ale
deînmulţitului.
Să observăm acum că grupul de cifre 1 poate fi scris şi sub forma
25 + 2 4 + 23 + 2 2 + 21 = 1 × 2 6 − 1 × 21 = 2 6 − 21
Înlocuind acum în expresia anterioară obţinem
X ⋅ Y = X ⋅ (2 6 − 21 ) = X ⋅ 62
Această relaţie ne arată că putem calcula acest produs numai printr-o
adunare şi o scădere a deînmulţitului. Această schemă poate fi extinsă la orice
număr de blocuri de 1 din cadrul înmulţitorului, inclusiv la cazul când unele blocuri
conţin o singură cifră 1 . Astfel dacă înmulţitorul este
Y = 00111010
produsul celor două numere poare fi scris ca
X ⋅ Y = X ⋅ ( 2 5 + 2 4 + 2 3 + 21 ) = X ⋅ 58
sau
X ⋅ Y = X ⋅ ( 26 − 23 + 2 2 − 21 ) = X ⋅ 58
Algoritmul lui Booth utilizează această schemă, efectuând o adunare a
deînmulţitului atunci când întâlneşte prima cifră a unui bloc de 1 (01) şi o scădere
a acestuia atunci când întâlneşte sfârşitul acestui bloc (10) . Acest algoritm
lucrează la fel de bine şi în cazul unui înmulţitor negativ.
Generalizând se observă că diferenţa y i −1 − y i a două cifre alăturate poate fi 1,
-1, sau 0. Dacă cele două cifre alăturate y i y i −1 ale înmulţitorului sunt 01, diferenţa
este 1 şi trebuie să se efectueze o adunare a deînmulţitului la produsul parţial. Dacă cele
două cifre sunt 10, diferenţa este -1 şi trebuie să se efectueze o scădere a deînmulţitului
din produsul parţial. Dacă cele două cifre sunt 00 sau 11, diferenţa este 0 şi deci pentru
cifra i a înmulţitorului nu trebuie să se efectueze nici o operaţie.
Rezultă următorul algoritm al metodei Booth: la fiecare pas al operaţiei se testează
doi biţi alăturaţi ai înmulţitorului, y i (bitul curent) şi y i −1 (bitul testat în pasul precedent,
numit şi bit de referinţă). Testarea se efectuează începând cu bitul c.m.p.s. al
înmulţitorului. Bitul de referinţă pentru bitul c.m.p.s. al înmulţitorului este y −1 = 0 . In
funcţie de valoarea biţilor testaţi y i y i −1 , se efectuează operaţiile indicate în tabelul
3.4.
Tabelul 3.4.
Operaţii
yi yi −1
00 Deplasare produs parţial la dreapta
01 Adunare deînmulţit, deplasare produs parţial la dreapta
10 Scădere deînmulţit, deplasare produs parţial la dreapta
11 Deplasare produs parţial la dreapta
Structura unui dispozitiv de înmulţire prin metoda Booth este prezentată în
figura 3.12.
START STOP
Fig. 3.12
Dispozitivul de înmulţire care utilizează această metodă conţine un registru
combinat A _ Q , format din registrul acumulator A şi registrul Q , de câte n + 1
poziţii, care păstrează produsul parţial, respectiv înmulţitorul. In acest caz, toate
poziţiile înmulţitorului inclusiv cea de semn, participă la deplasare. Registrul B , care
păstrează deînmulţitul, are de asemenea n + 1 poziţii. Aceste registre trebuie să
aibă posibilităţi similare cu cele utilizate la metoda de înmulţire directă. Mai este
necesar un bistabil Q−1 , care păstrează bitul de referinţă. Sumatorul utilizat trebuie
să aibă n + 1 poziţii, deoarece se operează cu toate cifrele inclusiv cea de semn.
Blocul de comandă testează biţii Q0 , Q−1 la fiecare pas al operaţiei. In funcţie
de valoarea acestor biţi, se efectuează operaţiile necesare, astfel:
Q0 ⊕ Q−1 = 0 Deplasare la dreapta a registrului A _ Q
Q 0Q−1 = 1 Adunare deînmulţit, deplasare la dreapta a registrului A _ Q
Q0 Q −1 = 1 Scădere deînmulţit, deplasare la dreapta a registrului A _ Q
Observaţii
Fig.3.13
1. Iniţial, bistabilul Q−1 este resetat, pentru ca bitul de referinţă pentru cifra
c.m.p.s. a înmulţitorului să fie zero.
2. La deplasare se tine cont de regula de deplasare pentru numerele cu semn
reprezentate în C2 (Tabelul 1.6). Bitul de semn de pe poziţia An , este deplasat în
An −1 , dar rămâne şi în An (se efectuează o deplasare aritmetică).
3. Se testează toţi biţii înmulţitorului, inclusiv bitul de semn.
4. Rezultatul se formează în registrul A _ Q de 2n+2 poziţii, bitul de semn
repetându-se pe primele două poziţii (rezultatul propriu-zis are 2n+1 biţi).
Organigrama operaţiei de înmulţire prin metoda Booth este prezentată în figura
3.13.
In etapa de iniţializare, se încarcă deînmulţitul şi înmulţitorul în registrul B ,
respectiv Q , bistabilul Q−1 şi registrul acumulator sunt iniţializate cu 0 , iar numărătorul
N este iniţializat cu n + 1 .
In continuare se testează bitul de referinţă Q−1 şi bitul Q0 al înmulţitorului. Dacă
Q0Q−1 = 01, se adună deînmulţitul din registrul B la produsul parţial din registrul A .
Dacă Q0Q−1 = 10 , se scade deînmulţitul din produsul parţial. Pentru celelalte două
combinaţii ale biţilor testaţi, în această etapă nu se efectuează nici o operaţie. In etapa
următoare se deplasează la dreapta registrul combinat A _ Q , astfel încât în poziţia
bitului de semn An să rămână aceeaşi valoare (păstrarea bitului de semn este indicată
în organigramă prin transferul An ← An ). Se decrementează numărătorul N , şi dacă
acesta nu a ajuns la zero, se continuă operaţia cu testarea biţilor Q0Q−1 . Dacă
numărătorul N a ajuns la zero, operaţia se termină.
Exemplul
Considerăm X = 13 , Y = −10 . Exprimarea binară a acestor numere în C2
este următoarea:
X = 0 1101
Y = 1 0110
Scăderea deînmulţitului se efectuează prin adunarea complementului faţă de 2
al acestuia:
X (C2 ) = − X = 1 0011
In tabelul 3.5 este prezentat conţinutul registrelor dispozitivului de înmulţire
la fiecare pas al operaţiei.
Tabelul 3.5. Execuţia operaţiei de înmulţire 13 x (-10) prin metoda Booth.
Pas A Q Q-1 B Q0Q-1 N Operaţii
0 0 0000 1 0110 0 0 1101 00 5 Iniţializare
1 0 0000+ 0 1011 0 0 1101 10 4 Deplasare A_Q la dreapta
2 1 0011 0 1101 Scădere deînmulţit
0 1011 0
1 0011
1 0101 1 11 3 Deplasare A_Q la dreapta
1 1001
3 1 1100+ 1 1010 1 0 1101 01 2 Deplasare A_Q la dreapta
4 0 1101 0 1101 Adunare deînmulţit
1 1010 1
0 1001
10 1 Deplasare A_Q la dreapta
1 1101 0
0 0100+
5 1 0011 0 1101 Scădere deînmulţit
1 1101 0
1 0111
1 1110 1 01 0 Deplasare A_Q la dreapta
1 1011
Rezultatul este: 1 0111 11102 =-1000 00102 =-82h = -(8* 16+2)= -130.
Observaţie. La deplasarea la dreapta a conţinutului registrelor A _ Q se ţine
seama de deplasare a numerelor reprezentate în C2 care cere ca pe poziţia rămasă
liberă să se repete bitul de semn al numărului. Astfel la paşii 2, 3 şi 5 pe locul ras liber s-
a plasat cifra 1, iar la paşii 1 şi 4 cifra 0.
3.2.3. Împărţirea binară
3.2.3.1. Principiul împărţirii binare
Fiind dat deîmpărţitul X şi împărţitorul Y , de câte n cifre de mărime,
împărţirea constă în determinarea câtului Q şi a restului R , astfel încât să fie
satisfăcută relaţia:
(3.19)
X = Q ⋅Y + R
Impărţirea binară se efectuează în mod asemănător cu împărţirea din aritmetica
zecimală. La împărţirea zecimală, se determină cifrele câtului prin alegerea unei cifre
şi scăderea din restul parţial a produsului dintre această cifră şi împărţitor. Dacă
rezultatul scăderii este un număr pozitiv mai mic decât împărţitorul, cifra aleasă este
corectă. In caz contrar, se alege o altă cifră şi operaţia se repetă. La fiecare etapă a
operaţiei, se obţine o cifră a câtului.
In cazul împărţirii binare, dacă se alege în mod eronat o cifră a câtului, o nouă
alegere nu mai este necesară, existând numai două cifre: 0 şi 1. Operaţia de
împărţire se reduce la o serie de scăderi ale împărţitorului din restul parţial, care se
efectuează numai dacă restul parţial este mai mare decât împărţitorul, caz în care
cifra câtului este 1; în caz contrar, cifra corespunzătoare a câtului este 0.
Să considerăm următoarea operaţie 147:11.
In binar avem
147 → 1001 0011
11 → 1011
10010011:1011= 00001101 Cât 13
1011
Rest parţial
1110
1011
1111 Rest parţial
1011
Rest 4
100
Câtul este 13, iar restul este 4. Pentru împărţire se examinează biţii
deîmpărţitului, de la stânga la dreapta, până când setul biţilor examinaţi reprezintă un
număr mai mare sau egal cu împărţitorul. De exemplu, setul biţilor examinaţi este 1,
10, 100, 1001, 10010. Atât timp cât setul biţilor examinaţi este mai mic decât
împărţitorul, se obţin cifre de 0 pentru cât. Atunci când acest set este mai mare sau
egal cu împărţitorul, se obţine o cifră de 1 pentru cât. In continuare împărţitorul este
scăzut din partea corespunzătoare a deîmpărţitului, obţinându-se un rest partial. La
fiecare pas al operaţiei se adaugă câte un bit din deîmpărţit la restul parţial, până
când se obţine un număr mai mare sau egal cu împărţitorul. Se scade apoi
împărţitorul din restul parţial, obţinându-se un nou rest parţial. Operaţia continuă
până când se examinează toţi biţii deîmpărţitului.
In cazul în care împărţitorul este zero, operaţia de împărţire trebuie oprită, ceea
ce impune testarea împărţitorului înaintea operaţiei. Se poate testa şi deîmpărţitul
înaintea operaţiei şi dacă acesta este zero, operaţia se poate termina, rezutatul fiind
zero.
3.2.3.2. Metode de împărţire binară
Există trei metode principale de împărţire:
• Metoda comparaţiei;
• Metoda refacerii restului parţial;
• Metoda fără refacerea restului parţial.
In cazul metodei comparaţiei, dispozitivul de împărţire conţine un circuit
comparator, utilizat pentru compararea restului parţial cu împărţitorul. Circuitele de
comparare fiind destul de complexe, această metodă nu se utilizează în mod obişnuit.
Metoda aleasă depinde de forma de reprezentare a numerelor în calculator.
Metoda comparaţiei şi cea a refacerii restului parţial se pot aplica numai în cazul
reprezentării numerelor în MS. Dacă numerele sunt reprezentate în altă formă, este
necesară conversia formei de reprezentare în MS înaintea aplicării metodei şi conver-
sia rezultatului operaţiei. Metoda fără refacerea restului parţial se poate aplica oricărei
forme de reprezentare, fiind necesare însă unele corecţii ale rezultatului.
3.2.3.3. Metoda refacerii restului parţial
In cazul metodei refacerii restului parţial, în fiecare etapă a operaţiei se
efectuează o scădere a împărţitorului din restul parţial. Dacă rezultatul scăderii este
un număr negativ, deci restul parţial este mai mic decât împărţitorul, se reface restul
parţial la valoarea anterioară, prin adunarea împărţitorului la restul parţial.
Această metodă de împărţire este asemănătoare cu metoda comparaţiei,
comparaţia fiind înlocuită cu o scădere. Fiecare etapă a operaţiei de împărţire începe
cu o deplasare a restului parţial la stânga cu o poziţie. Se efectuează apoi scăderea
împărţitorului din restul parţial, obţinându-se noul rest parţial. Dacă se obţine un
număr pozitiv, cifra corespunzătoare a câtului este 1. Dacă se obţine un număr
negativ, cifra corespunzătoare a câtului este 0, împărţitorul fiind adunat la restul
parţial. Pentru obţinerea unui cât cu n cifre de mărime, aceste operaţii se repetă de n
ori. Procesul de împărţire se poate opri dacă restul parţial devine zero sau mai mic
decât împărţitorul.
Presupunem că se utilizează un registru combinat format din registrul
acumulator şi registrul deîmpărţirului, iar iniţial registrul acumulator este 0.
Structura dispozitivului de împărţire care utilizează metoda refacerii restului
parţial este prezentată în figura 3.17.
Regiştrii A , B şi Q au câte n + 1 poziţii. Regiştrii A şi Q se pot deplasa la
stânga, astfel încât bitul Qn −1 va trece în A0 . Bitul Qn nu participă la deplasare.
Sumatorul este de n biţi. Conţinutul registrului B poate fi adunat sau scăzut din
START STOP
Fig. 3.17
conţinutul registrului acumulator A .
Organigrama operaţiei de împărţire prin metoda refacerii restului parţial este
prezentată în figura 3.18.
Deîmpărţitul X se încarcă în registrul A _ Q . Semnul deîmpărţitului se
păstrează în poziţia Qn a registrului Q . Impărţitorul Y se încarcă în registrul B .
Numărătorul N se iniţializează cu numărul cifrelor de mărime n. In fiecare etapă a
operaţiei, se deplasează registrul combinat A _ Q la stânga cu o poziţie, iar apoi se
efectuează o scădere a împărţitorului (registrul B ) din restul parţial (registrul A ). Dacă
rezultă un număr pozitiv în acumulator ( An = 0 ), cifra câtului este 1, care se introduce
în poziţia Q0 a registrului Q . Dacă rezultă un număr negativ în acumulator ( An = 1),
cifra câtului care se introduce în poziţia Q0 este 0. Valoarea cifrei câtului care se
obţine în această etapă este deci:
Q0 = A n
Dacă în urma scăderii a rezultat un număr negativ, se reface restul parţial prin
adunarea registrului B la acumulator. Se decrementează numărătorul N şi dacă
acesta nu este zero, operaţia continuă cu o nouă etapă. Dacă N este zero, operaţia
este terminată, restul aflându-se în registrul A , iar câtul în registrul Q . In final se
stabileşte semnul restului şi al câtului. Semnul restului este semnul deîmpărţitului:
An = Qn . Semnul câtului se obţine prin operaţia SAU EXCLUSIV între semnele celor
doi operanzi:
Qn = Qn ⊕ Bn
Fig. 3.18
In organigramă nu sunt arătate testele care trebuie efectuate după etapa de
iniţializare. Astfel, trebuie să se testeze dacă împărţitorul este zero; în caz afirmativ,
operaţia se opreşte şi se indică o eroare de împărţire cu zero. De asemenea, se testează
dacă apare o depăşire de capacitate. Depăşirea de capacitate apare în cazul în care
conţinutul registrului A (partea mai semnificativă a deîmpărţitului) este mai mare sau
egal cu conţinutul registrului B (împărţitorul). In plus, se poate testa dacă deîmpărţitul
este mai mic decât împărţitorul; în caz afirmativ, câtul obţinut va fi zero, iar restul va fi
egal cu deîmpărţitul.
Exemplu
Considerăm numerele X = 13 şi Y = 5 . Reprezentarea în MS a acestor numere
este următoarea:
X = 0 1101
Y = 0 0101
Complementul faţă de 2 al împărţitorului este:
Y ( C 2) = 11011
Cifrele de semn fiind tratate separat, în registrele B şi Q se încarcă numai
cifrele de mărime. La operaţia de adunare sau scădere a împărţitorului din acumulator
participă însă toate cifrele. Execuţia operaţiei este prezentată în tabelul 3.7.
Tabelul 3.7 . Execuţia operaţiei de împărţire 13:5 prin metoda refacerii restului parţial.
Pas A Q B Q0 Qn N Operaţii
0 0 0000 1101 0101 0 0 4 Iniţializare
1010
1 0 0001 + Deplasare A_Q la stânga
Scădere împărţitor
11011
1 1100 +
Adunare împărţitor
0 0101
0 0 0 3
101 0
0 0001
2 0 0011 + Deplasare A_Q la stânga
01 0 0
1 1011 Scădere împărţitor
1 1110 +
Adunare împărţitor
0 0101
0101 0 0 2
01 00
0 0011
3 0 0110 + Deplasare A_Q la stânga
100 0
1 1011 Scădere împărţitor
0101 1 0 1
1001
0 0001
Deplasare A_Q la stânga
4 0 0011 + 001 0
Scădere împărţitor
1 1011
1 1110 +
Adunare împărţitor
0 0101
0101 0 0 0
0010
0 0011
Câtul obţinut este 0 0010=2, iar restul este

1.5.3. Operaţii cu numere reprezentate în virgulă fixă


In exemplele care urmează vom considera numai cazul numerelor
reprezentate în C2. Metodele de adunare şi scădere a numerelor reprezentate în
C2 demonstrează avantajele acestei reprezentări. Aceste operaţii se pot efectua
ca şi în cazul numerelor fără semn.
1.5.3.1 Adunarea numerelor reprezentate în C2
Considerăm câteva exemple de adunare a unor numere reprezentate pe
4+1 octeţi. In primele exemple, numerele sunt de acelaşi semn.
+9 01001
+5 00101
+ 14 01110
Rezultatul este corect.
+9 01001
+ 11 01011
+ 20 10100
După cum se constată se obţine un număr negativ, deci rezultatul este
incorect deoarece se depăşeşte capacitatea de reprezentare a
rezultatului: 2 4 = 16 > 20 .
−9 10111
−5 11011
− 14 10010
Rezultatul este corect. Apare un transport de la cifra de semn, care se
neglijează.
−9 10111
− 11 10101
− 20 01100
Rezultatul este incorect deoarece, din nou, s-a depăşit capacitatea de
reprezentare pe 4 cifre binare (biţi).
In exemplele următoare adunăm numere de semne contrare.
+7 00111
−4 11100
+3 00011
−7 11001
+4 00100
−3 11101
In cazul numerelor de semne contrare, rezultatul este întotdeauna corect,
deoarece nu poate apare depăşire de capacitate.
Din exemplele prezentate, se poate formula regula generală de adunare a
două numere reprezentate în C2: Se adună numerele bit cu bit, inclusiv biţii de
semn, care sunt trataţi la fel cu biţii de mărime şi se ignoră eventualul transport de
la bitul de semn.
Dacă rezultatul este mai mare în valoare absolută decât valoarea maximă
care poate fi reprezentată în registru, apare o depăşire, deci rezultatul este
incorect. La apariţia depăşirii, UAL trebuie să semnaleze acest fapt, astfel încât
rezultatul să nu fie utilizat.
Se observă că depăşirea poate apare indiferent dacă există sau nu
transport de la cifra de semn. Pentru detectarea apariţiei depăşirii, se poate aplica
următoarea regulă simplă: La adunarea a două numere de acelaşi semn, a apărut
o depăşire dacă şi numai dacă rezultatul are semn contrar semnului numerelor.
1.5.3.2. Scăderea numerelor reprezentate în C2
Scăderea a două numere reprezentate în C2 se efectuiază prin metoda
scăderii directe, dacă se dispune de scăzătoare elementare, fie prin metoda
adunării complementului faţă de 2, dacă se dispune numai de sumatoare
elementare. Se poate enunţa următoarea regulă de scădere: Pentru scăderea
unui număr (scăzător) dintr-un altul (descăzut), se calculează complementul faţă
de 2 al scăzătorului şi se efectuează adunarea acestuia la descăzut.
Să considerăm următorul exemplu, în care s-a notat cu D descăzutul, cu S
scăzătorul, iar cu S' complementul faţă de 2 al scăzătorului.
D +7 00111
S +4 00100

S −4 11100
D+ +7 + 00111 +
S’ −4 11100
+3 00011
Rezultatul este corect.
+ 11
D 01011
S 10111
-9
S’ +9 01001
D+ + 11 01011
S’ +9 01001
+ 20 10100
Rezultatul este incorect deoarece s-a depăşit capacitatea de
reprezentare pe 4 cifre binare (biţi).
Regula pentru detectarea depăşirii poate fi enunţată astfel: La scăderea a
două numere de semne contrare apare depăşire dacă şi numai dacă rezultatul
are acelaşi semn cu scăzătorul.
1.6. Reprezentarea numerelor în virgulă mobilă
In multe aplicaţii se utilizează numere care nu sunt întregi. Există mai
multe posibilităţi pentru reprezentarea acestor numere. O posibilitate este
reprezentarea în virgulă fixă. In acest caz, se poate utiliza aritmetica pentru
numere întregi, iar apoi se plasează virgula binară în poziţia predefinită, de
exemplu, după bitul de semn. Adunarea a două numere reprezentate într-un
asemenea format poate fi realizată cu un sumator pentru numere întregi în timp ce
înmulţirea necesită operaţii suplimentare de deplasare. In cazul reprezentării
numerelor în virgulă fixă, deşi virgula nu mai este reprezentată fizic în calculator,
poziţia virgulei binare, stabilită prin proiectare, nu mai poate fi schimbată. Pentru
transformarea tuturor numerelor în acest format, trebuie executate o serie de
operaţii de scalare sau de deplasare, ataşând numerelor factori de scală.
Evidenţa acestora trebuie realizată prin program, ceea ce măreşte timpul de
calcul. Alte reprezentări care au fost propuse constau în păstrarea logaritmilor
numerelor şi executarea înmulţirii prin adunarea logaritmilor, sau utilizarea unei
perechi de întregi ( x, y ) pentru a reprezenta fracţia x / y .
O soluţie mai avantajoasă este utilizarea unei tehnici de scalare automată,
cunoscută sub numele de reprezentare în virgulă mobilă - VM (numită şi
reprezentare în virgulă flotantă - floating point). In acest caz, factorul de scală
devine o parte a cuvântului din calculator, poziţia virgulei variind pentru fiecare
număr în mod automat.
1.6.1. Principii
In general, un număr N se poate reprezenta în format ştiinţific sub forma
următoare.
N = ±M ⋅ B±E (1.19)
Un număr reprezentat în format ştiinţific are două componente. Prima
componentă este mantisa (M), care indică valoarea exactă a numărului într-un
anumit domeniu, fiind reprezentată de obicei ca un număr fracţionar cu semn. A
doua componentă este exponentul ( E ), care indică ordinul de mărime al
numărului. In expresia de sus B este baza în care este reprezentat numărul.
De exemplu numărul zecimal 23,6875 poate fi reprezentat în format
ştiinţific prin una din următoarele posibilităţi:
23,6875 × 10 0 = 263,875 × 10 -1 = 0,263875 × 10 2
In binar numărul corespunzător este 10111,1011 care, în format
ştiinţific poate reprezentat astfel:
10111,1011× 20 = 10111101,1× 2-3 = 1,01111011× 24
Acest mod de scriere a numerelor este preluat şi de reprezentarea VM.
De-a lungul timpului au existat, la diferite familii de calculatoare, diferenţe
considerabile în modul de reprezentare a numerelor în VM şi de execuţie a
operaţiilor corespunzătoare. Aceste diferenţe se refereau la numărul de biţi alocaţi
pentru exponent şi pentru mantisă, la gama exponenţilor, la modurile de rotunjire şi
la operaţiile executate la apariţia unor condiţii de excepţie, ca depăşirea
superioară sau cea inferioară. Pentru a facilita portabilitatea programelor de la un
calculator la altul şi pentru a încuraja dezvoltarea programelor complexe orientate
pe calcule numerice, Societatea de Calculatoare a organizaţiei IEEE (Institute of
Electrical and Electronics Engineers) a elaborat standardul IEEE 754, pentru
reprezentarea numerelor în VM şi pentru operaţii aritmetice în această
reprezentare. Acest standard a fost publicat în 1985.
Standardul era destinat în primul rând microprocesoarelor şi microcalcula-
toarelor, unde unii producători puneau la dispoziţie doar posibilităţi limitate pentru
calcule numerice. Ca rezultat al acestui standard, au fost dezvoltate circuite sau
procesoare care implementează standardul. De exemplu, cele mai multe unităţi
de calcul în VM şi coprocesoare matematice, printre care şi coprocesoarele
matematice şi unităţile de calcul în VM ale procesoarelor Intel din familia 80x86, se
conformează acestui standard.
Reprezentarea numerelor în virgulă mobilă poate fi memorată într-un
cuvânt cu trei câmpuri pentru semn, mantisă şi exponent. Baza este considerată
ca fiind, în mod implicit, egală cu 2 şi deci nu mai trebuie memorată. In câmpul
de semn se memorează semnul numărului (mantisei). Pentru memorarea
semnului se utilizează un singur bit, denumit bit de semn acesta având valoarea
0 pentru numerele pozitive şi 1 pentru numerele negative.
In funcţie de numărul de biţi alocaţi pentru memorarea mantisei şi a
exponentului standardul IEEE 754 defineşte următoarele formate sau precizii:
precizie simplă, precizie dublă. Parametrii principali ai acestor formate sunt
prezentaţi în tabelul 1.7.
In conformitate cu standardul IEEE 754, în câmpul rezervat exponentului
nu se memorează de fapt exponentul E al numărului, ci un număr C , denumit
caracteristică, care se calculează cu relaţia
C = E +D
unde D , numit deplasament, este un număr constant, astfel ales încât
caracteristica C să rezulte întotdeauna pozitivă. Astfel, nu este necesar să se
rezerve un câmp separat pentru semnul exponentului.
Conform standardului IEEE 754 în formatul simplă precizie pentru
caracteristică se alocă 8 biţi şi în aceste condiţii deplasamentul este D = 127 .
Astfel dacă exponentul numărului este E = 0 , atunci caracteristica sa este
C = 0 + 127 = 127
In binar caracteristica unui număr de exponent nul este deci:
0111 1111 = 127
Conform standardului caracteristica cea mai mare este
C = 1111 1110 = 254
astfel încât exponentul cel mai mare este
E = C − D = 254 − 127 = +127
Caracteristica cea mai mică este
C = 0000 0001 = 1
deci exponentul cel mai mic este dat de
E = C − D = 1 − 127 = −126
Mantisa se reprezintă întotdeauna sub formă normalizată, în care virgula
zecimală este adusă după prima cifră semnificativă a numărului. In sistemul de
numeraţie binar prima cifră a oricărui număr este întotdeauna 1, deci mantisa
poate fi scrisă sub forma
M = 1,F
unde F reprezintă partea fracţionară a numărului. In aceste condiţii dacă toţi biţii
fracţiei sunt 0, mantisa este 1,0; dacă toţi biţii fracţiei sunt 1, mantisa este cu
puţin mai mică decât 2,0. (1,111111 .) Deci:
10 ≤ M < 11111111 .....
, ,
In formatul simplă precizie pentru mantisă se alocă 23 biţi astfel încât un
număr în virgulă mobilă este memorat în modul următor
31 30 23 22 0
s Caracteristica Mantisă
Deoarece primul bit al mantisei este întotdeauna 1 acesta nu se mai
memorează, motiv pentru care acesta se numeşte bit ascuns. Astfel, în cei 23
de biţi disponibili pentru mantisă se memorează numai partea fracţionară F .
In simplă precizie numărul zecimal 23,687510 = 1,01111011 × 2 4 va avea
deci următoarea reprezentare:
0 10000011 011 1101 1000 0000 0000 0000
Exponentul a fost calculat precum urmează:
127 = 01111111 +
4 = 00000100
131 = 10000011
Tabelul 1.7
Simplă Dublă
precizie precizie
Nr. biţi mantisă 23 52
Exponent maxim +127 +1023
Exponent minim -126 -1022
Deplasament 127 1023
Standardul IEEE 754 rezervă două valori ale caracteristicii pentru cazuri
speciale. Aceste valori sunt
255 = 1111 1111
şi
0 = 0000 0000
In tabelul 1.8 se prezintă semnificaţia acestor valori în funcţie de
valoarea mantisei.
Tabelul 1.8
Caracteristica Mantisa Semnificaţie
0=0000 0000 0 ±0
≠0
0=0000 0000 nr. denormalizat
255=1111 1111 0 ±∞
≠0
255=1111 1111 NaN
≠0
0<C<255 nr. normalizat
Dacă atât caracteristica cât şi mantisa sunt 0 atunci conţinutul locaţiei
de memorie reprezintă cifra 0. In funcţie de valoarea bitului de semn există
două valori ale acestei cifre: +0 şi -0.
Pentru cazul în care apare o depăşire superioară, există o reprezentare
specială pentru infinit, constând din caracteristica cu valoarea maximă pentru
formatul respectiv (255) şi mantisa egală cu 0. In funcţie de bitul de semn, sunt
posibile două reprezentări pentru infinit, + ∞ şi − ∞ . Valoarea infinit se poate utiliza
ca operand, utilizând reguli ca:
∞+n =∞
n/∞ = 0
n/0 = ∞
Astfel, utilizatorul poate decide dacă va trata depăşirea superioară ca o
condiţie de eroare, sau va continua calculele cu valoarea infinit.
Pentru indicarea diferitelor condiţii de excepţie, ca în cazul operaţiilor
nedefinite de forma ∞ / ∞ , ∞ − ∞ , ∞ × 0 , 0 / ∞ , 0 / 0 , sau extragerea rădăcinii
pătrate dintr-un număr negativ, s-a prevăzut un format special, care nu reprezintă
un număr obişnuit, fiind numit NaN (Not a Number). Exponentul are valoarea
maximă posibilă, iar mantisa este diferită de 0 . Astfel, există o clasă întreagă
de valori NaN.
Standardul IEEE 754 specifică faptul că atunci când argumentul unei operaţii
este NaN, rezultatul trebuie să fie NaN. Datorită regulilor de execuţie a operaţiilor
aritmetice cu valori NaN, la scrierea subrutinelor de calcul în VM, care acceptă o
valoare NaN ca argument, nu sunt necesare verificări speciale.
In cazul obţinerii unui rezultat cu o valoare mai mică decât numărul
normalizat cel mai mic posibil, standardul permite utilizarea numerelor care nu
sunt normalizate, acestea fiind numite numere denormalizate. Un număr
denormalizat are caracteristica 0 şi mantisa diferită de 0. In continuare se prezintă
un exemplu de număr denormalizat.
0 0000 0000 100 0000 0000 0000 0000 0000
Pentru această reprezentare avem:
C = 0 deci E = 0 − 127 = −127
Este deci reprezentat numărul
1,0 × 2 −127 = 0,1 × 2 −126
Conform standardului IEEE 754, un număr denormalizat are mantisa de
forma
M = 0, F
motiv pentru care exponentul este decrementat cu o unitate.
1.6.2 Gama numerelor reprezentate în VM
Numărul cel mai mare, în valoare absolută, care poate fi reprezentat
simplă precizie, trebuie să aibă exponentul cel mai mare şi mantisa cea mai
mare, deci este următorul:
0 1111 1110 111 1111 1111 1111 1111 1111
Caracteristica fiind 254 exponentul acestui număr este +127, iar, ţinând
seama de bitul ascuns, mantisa este
M=1,111 1111 1111 1111 1111 1111= (2 − 2 −23 )
Numărul reprezentat este deci
N = (2 − 2 −23 ) × 2127 ≅ 3,4 × 1038
Numărul cel mai mic, în valoare absolută care poate fi reprezentat în
simplă precizie, trebuie să aibă exponentul şi mantisa cele mai mici, deci:
0 0000 0001 000 0000 0000 0000 0000 0000
Exponentul este -126, iar mantisa este
M=1,000...0000=1
deci
N=1 × 2 −126 ≅ 1,18 × 10 −38
In concluzie virgula mobilă, simplă precizie permite reprezentarea
numerelor normalizate în gama de valori
± 1,18 × 10 −38 ≤ N ≤ ±3,4 × 10 +38
Cel mai mare număr denormalizat va fi
0 0000 0000 111 1111 1111 1111 1111 1111
şi va avea deci mantisa
M=0,111 1111 1111 1111 1111 1111=1 − 2 −23
Numărul corespunzător va fi deci:
N = (1 − 2 −23 ) × 2 −126 ≈ 1,18 × 10 −38
Cel mai mic numărul denormalizat va fi
0 0000 0000 000 0000 0000 0000 0000 0001
Acesta va avea deci mantisa
M=1 × 2 −23
iar numărul va fi
N=1 × 2 −23 × 2 −126 = 1 × 2 −149 ≅ 1,4 × 10 −45
Punând cap la cap toate aceste date rezultă gama numerelor
reprezetabile în VM (fig.1.1)
D e pas ire s up erio ara
De pas ire infe rioa ra
De pas ire infe rioa ra
De pas ire s up erio ara
p oz itiva
p oz itiva
n eg ativ a
ne ga tiv a
-1,1 8x10 -3 8 -3 8
+ 1,1 8x10
0
+ 1,4x10 + 45
-1,4x10 -4 5
+ 38 + 38
-3 ,4x1 0 + 3,4 x10
Fig.1.1
In simplă precizie, se obţine o precizie de reprezentate a numerelor de
6-7 cifre semnificative. Dacă această precizie nu este suficientă, se poate
opta pentru dublă precizie, când precizia de reprezentare a numerelor creşte
la 15-16 cifre semnificative.
In dublă precizie gama numerelor care pot fi reprezentate este cuprinsă
între ± 2,23 × 10 −308 şi ± 1,79 × 10308 .
O altă caracteristică a standardului IEEE 754 cu implicaţii asupra circuitelor
din UAL este regula de rotunjire. In urma operaţiilor efectuate între două numere
în VM, de obicei rezultatul nu poate fi reprezentat în mod exact ca un alt număr
în VM. Standardul specifică patru moduri de rotunjire: rotunjire spre 0 , rotunjire
spre + ∞ , rotunjire spre − ∞ şi rotunjire la cel mai apropiat număr reprezentabil.
Ultimul mod de rotunjire este cel implicit şi este prevăzut pentru situaţiile în care
numărul se află în intervalului dintre două reprezentări în VM.
Standardul IEEE 754 defineşte cinci tipuri de excepţii: depăşire inferioară,
depăşire superioară, împărţire la zero, rezultat inexact şi operaţie invalidă. In mod
implicit, la apariţia unei asemenea excepţii, este setat un indicator şi calculele
continuă. Standardul recomandă ca implementările să prevadă un bit de validare
pentru fiecare excepţie. Dacă apare o excepţie cu bitul de validare setat, este
apelată o rutină de tratare a excepţiei.
Excepţiile de depăşire inferioară, depăşire superioară şi împărţire la zero
sunt prevăzute la majoritatea sistemelor de calcul în VM. Excepţia de rezultat
inexact apare atunci când rezultatul unei operaţii trebuie rotunjit. Aceasta nu
este o condiţie excepţională, deoarece apare în mod frecvent şi deci, validarea
rutinei de tratare a acestei excepţii poate avea un impact semnificativ asupra
performanţei.
1.7. Coduri
1.7.1. Coduri binar-zecimale
Aceste coduri se utilizează pentru codificarea cifrelor zecimale.
Pentru codificarea fiecăreia din cele 10 cifre, sunt necesari 4 biţi; din cele 16 valori
posibile, 6 vor fi neutilizate. Prin stabilirea unor corespondenţe între mulţimea
cifrelor zecimale şi mulţimea celor 16 cuvinte de 4 biţi, se obţin numeroase
10
posibilităţi de codificare ( A16 ). Din numeroasele coduri posibile se utilizează
practic doar o mică parte.
Codurile utilizate se împart în coduri ponderate şi neponderate.
In cazul codurilor ponderate, o cifră zecimală este exprimată printr-o
combinaţie de 4 cifre binare, în care fiecărei cifre i se asociază o anumită
pondere. Ponderile pot fi pozitive sau negative. Valoarea cifrei zecimale se
obţine prin suma biţilor din cod, fiecare bit fiind multiplicat cu valoarea ponderii
asociate.
Considerând un cod format din biţii b0 , b1 , b2 , b3 , ponderile asociate
acestora fiind p0 , p1 , p2 respectiv p3 valoarea cifrei zecimale codificate este:
(1.24)
N = p0b0 + p1b1 + p2b2 + p3b3
Ponderile fiecărui bit reprezintă valoarea corespunzătoare din
denumirea codului. Pentru ponderile de sus, codul are denumirea p3 p2 p1 p0 .
In tabelul 1.9 se prezintă exemple de coduri ponderate de 4 biţi mai des
utilizate.
Tabelul 1.9. Coduri binar-zecimale ponderate de 4 biţi.
Nr.
zecimal 8421 2421 6423 8421
0 0000 0000 0000 0000
1 0001 0001 0101 0111
2 0010 0010 0010 0110
3 0011 0011 1001 0101
4 0100 0100 0100 0100
5 0101 1011 1011 1011
6 0110 1100 0110 1010
7 0111 1101 1101 1001
8 1000 1110 1010 1000
9 1001 1111 1111 1111
Exemple
01018421 = 8 ⋅ 0 + 4 ⋅ 1 + 2 ⋅ 0 + 1 ⋅1 = 5
101084 21 = 8 ⋅ 1 + 4 ⋅ 0 + ( −2) ⋅ 1 + (−1) ⋅ 0 = 6
In cazul codului 8421, deoarece fiecare bit are ponderea numărării în
binar (2∞, 21, 22, 23), iar cuvintele de cod reprezintă numerele succesive în
sistemul binar natural, codul se mai numeşte cod binar-zecimal natural
(NBCD - Natural Binary Coded Decimal). In mod obişnuit, acest cod se
numeşte, impropriu, cod BCD.
In cazul codului 2421, numit şi cod Aiken (după numele Prof. Howard
Aiken, care a realizat calculatorul MARK I), primele 5 cifre zecimale (0 - 4) au
aceeaşi exprimare ca şi în codul 8421. Cifra zecimală 5 poate fi exprimată fie
prin 0101, fie prin 1011. Reprezentarea unor cifre zecimale nu este deci
unică, această proprietate fiind valabilă şi pentru alte coduri. Pentru codificare
s-a ales reprezentarea 1011, deoarece codul pentru cifra 5 se poate obţine atunci
prin complementarea codului pentru cifra 4. Aceeaşi regulă se poate aplica pentru
obţinerea codului cifrei 6 din codul cifrei 3, a codului cifrei 7 din codul cifrei 2
etc.
Codurile care au această proprietate se numesc coduri autocomplementare.
Un cod este autocomplementar dacă cuvântul de cod al complementului faţă de 9
al cifrei N (deci 9 - N) se poate obţine din codul cifrei N, prin complementarea
fiecăruia din cei 4 biţi. De exemplu, codul 8421 nu este autocomplementar, iar
codurile 2421, 6423 , 8421 sunt autocomplementare.
Condiţia necesară pentru ca un cod ponderat să fie autocomplementar este
ca suma ponderilor să fie egală cu 9. Autocomplementaritatea constituie un
avantaj în construcţia unui dispozitiv aritmetic care lucrează cu numere zecimale
reprezentate în codul respectiv.
Observaţie. In forma internă, numerele sunt reprezentate şi prelucrate fie
sub formă binară, fie codificate printr-un cod binar-zecimal. Trebuie sesizată
diferenţa dintre conversia unui număr zecimal în echivalentul său binar şi
codificarea binar-zecimală a numărului zecimal. De exemplu:
(4biţi)
1210 = 1100 2
1210 = (0001 0010) BCD (8biţi)
Codurile neponderate pot avea un număr mai mare de 4 biţi. Codurile cele
mai uzuale sunt prezentate în tabelul 1.10.
Tabelul 1.10. Coduri binar-zecimale neponderate.
Nr. zecimal Exces 3 2 din 5 Gray
0 0011 00011 0000
1 0100 00101 0001
2 0101 00110 0011
3 0110 01001 0010
4 0111 01010 0110
5 1000 01100 0111
6 1001 10001 0101
7 1010 10010 0100
8 1011 10100 1100
9 1100 11000 1101
Codul Exces 3 este autocomplementar şi derivă din codul 8421 (BCD) prin
adăugarea la fiecare cifră a valorii 3. Utilizând acest cod, se poate face distincţie
între lipsa unei informaţii înscrise într-un registru sau locaţie de memorie şi
înscrierea valorii zero (0000 reprezintă lipsa unei informaţii, iar zero este codificat
prin 0011).
Codul 2 din 5 se utilizează pentru reprezentarea numerelor zecimale
printr-un grup de 5 biţi. Denumirea derivă din faptul că fiecare cifră zecimală
codificată în binar conţine doi biţi de 1 din cei 5 biţi.
Codul Gray are proprietatea de adiacenţă, adică trecerea de la o cifră
zecimală la următoarea sau precedenta necesită modificarea unui singur bit
din cuvântul de cod. Este util pentru mărimile care cresc sau descresc
succesiv.
1.7.2. Coduri detectoare de erori
Transmiterea informaţiilor prin medii influenţate de zgomote poate fi
însoţită de introducerea unor erori. Verificarea transmiterii corecte a
informaţiilor se poate realiza cu ajutorul unor coduri speciale numite coduri
detectoare de erori.
Una din metodele de detectare a unei erori o constituie detectarea
combinaţiilor interzise. In cazul codurilor binar-zecimale, deoarece se
utilizează 10 din cele 16 combinaţii posibile de 4 biţi, celelalte combinaţii nu
trebuie să apară. Aceste combinaţii interzise se pot utiliza pentru detectarea
erorii. Dacă, de exemplu, în codul 1000 (BCD) apare o singură eroare, codul
poate fi transformat în 0000 , 1100 , 1010 , sau 1001 . Dintre aceste combinaţii,
a doua şi a treia constituie combinaţii interzise, astfel încât în aceste cazuri
eroarea poate fi detectată. Celelalte combinaţii nu sunt interzise, deci în
cazurile respective eroarea nu poate fi detectată.
O modalitate de creştere a probabilităţii de detectare a erorilor constă în
folosirea mai multor combinaţii interzise, care pot fi disponibile dacă codurile
au mai mult de 4 biţi. De exemplu, în codul 2 din 5 apare o eroare ori de câte
ori o cifră codificată are mai mult sau mai puţin de doi biţi de 1. Astfel, se pot
detecta erori multiple.
O altă metodă pentru detectarea erorilor constă în folosirea unor biţi
suplimentari de verificare. De exemplu, un cod de n biţi poate fi format din m
biţi de date şi r biţi redundanţi de verificare ( n = m + r ). Fiind date două
cuvinte de cod, de exemplu 1000 1001 şi 1011 0001 , se poate determina
numărul biţilor care diferă. In acest caz, există 3 biţi care diferă. Pentru
determinarea numărului de biţi care diferă, se efectuează suma modulo 2
între cele două cuvinte de cod şi se calculează numărul biţilor de 1 ai
rezultatului. Numărul poziţiilor în care două cuvinte de cod diferă reprezintă
distanţa Hamming. Dacă între două cuvinte de cod se află o distanţă
Hamming d, sunt necesare d erori de câte un singur bit pentru trecerea de la
un cod la al doilea cod (pentru a confunda un cod cu celălalt cod).
Proprietăţile de detectare a erorilor ale unui cod depind de distanţa sa
Hamming. Pentru detectarea a d erori de câte un singur bit, este necesar un
cod cu distanţa d+1, deoarece cu un asemenea cod nu există posibilitatea ca
d erori de un singur bit să modifice un cuvânt de cod valid într-un alt cuvânt
de cod valid.
Un exemplu simplu de cod detector de erori este un cod care conţine
un bit suplimentar numit bit de paritate. Acest bit se poate alege astfel încât
numărul total al biţilor având valoarea 1 în exprimarea numărului să fie par,
respectiv impar. Să notăm cu x3 x2 x1 x0 biţii cifrei zecimale şi cu p bitul de
paritate. Dacă se utilizează paritatea pară valoarea bitului de paritate,
determinată ca suma modulo 2 a valorii tuturor biţilor, trebuie să fie 0 :
(1.25)
x3 ⊕ x2 ⊕ x1 ⊕ x0 ⊕ p = 0
de unde rezultă
(1.26)
p = x3 ⊕ x2 ⊕ x1 ⊕ x0
Dacă se alege paritatea impară, trebuie ca:
(1.27)
x3 ⊕ x2 ⊕ x1 ⊕ x0 ⊕ p = 1
sau
(1.28)
p = x3 ⊕ x2 ⊕ x1 ⊕ x0 ⊕ 1
Un asemenea cod are distanţa Hamming egală cu 2, deoarece o eroare de
un singur bit produce un cuvânt de cod cu paritatea eronată. La transmisia datelor
se adaugă bitul de paritate pară sau impară, iar la recepţie se determină dacă
paritatea este aceeaşi cu cea de la transmisie. Verificarea parităţii nu poate
detecta apariţia erorilor duble, deoarece aceste erori nu modifică suma modulo 2
a biţilor.
Codurile 8421 cu paritate pară ale cifrelor zecimale sunt indicate în tabelul
1.11.
Tabelul 1.11. Codul 8421 cu paritate pară.
Nr. zecimal Cod
0 0 0000
1 1 0001
2 1 0010
3 0 0011
4 1 0100
5 0 0101
6 0 0110
7 1 0111
8 1 1000
9 1 1001
1.7.3. Coduri corectoare de erori
Există coduri mai complexe, numite coduri corectoare de erori, care permit
şi corectarea unui bit eronat sau a mai multor biţi eronaţi. Aceste coduri sunt
utile atunci când retransmisia informaţiei nu este posibilă, sau necesită un timp
care nu ar fi acceptabil.
Presupunem un cod cu m biţi de date şi r biţi de verificare, cod care
permite corectarea tuturor erorilor de un singur bit. Fiecăruia din cele 2 m cuvinte
de cod valide îi corespund n cuvinte de cod ilegale cu distanţa 1. Acestea se
formează prin inversarea sistematică a fiecăruia din cei n biţi ( n = m + r ) . Astfel
pentru fiecare cuvânt de cod valid există n + 1 combinaţii de biţi posibile. (Cele n
ilegale la care se adună cuvântul valid.)
Deoarece numărul total al combinaţiilor de biţi este 2 n , trebuie ca
(n + 1) × 2 m ≤ 2 n . Tinând seama de relaţia n = m + r , această cerinţă devine
(m + r + 1) × 2 m ≤ 2 m × 2 r
sau
(m + r + 1) ≤ 2 r .
Fiind dat m, această relaţie impune o limită inferioară asupra lui r , care
reprezintă numărului biţilor de verificare necesari pentru corectarea erorilor de un
singur bit. De exemplu, pentru un cuvânt de m = 4 biţi, numărul minim al biţilor de
verificare este r = 3 , iar pentru un cuvânt de m = 8 biţi, numărul minim al biţilor de
verificare este r = 4 .
Aceste limite teoretice pot fi atinse utilizând o metodă datorată lui Richard
Hamming. Metoda poate fi utilizată pentru construirea codurilor corectoare de
erori pentru cuvinte de cod de orice dimensiune. Intr-un cod Hamming, se adaugă
r biţi de paritate la un cuvânt de m biţi, rezultând un nou cuvânt cu lungimea
m + r biţi. Biţii sunt numerotaţi începând cu 1 (şi nu cu 0), bitul 1 fiind bitul c.m.s.
Toţi biţii ai căror număr este o putere a lui 2 sunt biţi de paritate, restul biţilor fiind
utilizaţi pentru date. De exemplu, în cazul unui cuvânt de 4 biţi, biţii 1, 2 şi 4 sunt
biţi de paritate. In total, cuvântul de cod va conţine 7 biţi (4 de date şi 3 de paritate).
In exemplul prezentat se va utiliza în mod arbitrar paritatea pară.
Fiecare bit de paritate verifică anumite poziţii de biţi. Aceste poziţii sunt
ilustrate în figura 1.2, unde prin pătrate s-a indicat poziţia biţilor de paritate, iar prin
cercuri s-a indicat poziţia biţilor de informaţie.
Fig.1.2
Poziţiile de biţi verificate de biţii de paritate sunt următoarele:
- Bitul 1 de paritate verifică biţii 1, 3, 5, 7.
- Bitul 2 de paritate verifică biţii 2, 3, 6, 7.
- Bitul 4 de paritate verifică biţii 4, 5, 6, 7.
In general, bitul b este verificat de acei biţi b1 , b2 ,..., b j astfel încât
b1 + b2 + ... + b j = b . De exemplu, bitul 5 este verificat de biţii 1 şi 4 (1+4 = 5), bitul
6 este verificat de biţii 2 şi 4 (2+4 = 6) şi bitul 7 este verificat de biţii 1, 2 şi 4
astfel încât 1+2+4=7.
Se consideră exprimarea în cod 8421 a cifrei zecimale 5 ( 0101 ). Bitul 1 de
paritate va trebui să determine un număr par de cifre de 1 pentru poziţiile 1, 3, 5
şi 7, deci va avea valoarea 0. Similar se determină valoarea bitului 2 de paritate,
care va avea valoarea 1 şi a bitului 4 de paritate, care va avea valoarea 0.
Dacă transmiterea cifrei zecimale se realizează corect, toţi biţii de paritate
verifică în mod corect paritatea. Dacă apare o eroare de transmisie, fie la un bit
de paritate, fie la un bit de informaţie, acest cod poate corecta o singură eroare.
De exemplu, presupunem că a apărut o eroare la transmiterea bitului de
informaţie din poziţia 6. Codul recepţionat va fi 0100111 în loc de 0100101 . Se
verifică biţii de paritate, cu următoarele rezultate:
- Bitul 1 de paritate este corect (biţii 1, 3, 5, 7 conţin doi biţi de 1)
- Bitul 2 de paritate este incorect (biţii 2, 3, 6, 7 conţin trei biţi de 1)
- Bitul 4 de paritate este incorect (biţii 4, 5, 6, 7 conţin trei biţi de 1)
Bitul incorect trebuie să fie unul din biţii testaţi de bitul 2 de paritate (2, 3, 6
sau 7). Deoarece bitul 4 de paritate este incorect, unul din biţii 4, 5, 6 sau 7
este incorect. Bitul eronat este unul din cei care se află în ambele liste, deci poate
fi bitul 6 sau 7. Bitul 1 de paritate fiind corect, rezultă că şi bitul 7 este corect. Bitul
eronat este deci bitul 6 şi valoarea acestui bit trebuie inversată. In acest fel,
eroarea poate fi corectată.
In mod practic, pentru determinarea bitului se calculează suma biţilor
eronaţi. Această sumă reprezintă poziţia bitului eronat. De exemplu, dacă biţii de
paritate 2 şi 4 sunt eronaţi, bitul eronat este bitul 6.
1.7.4. Coduri alfanumerice
Datele alfanumerice conţin cifre, litere şi semne speciale, numite caractere.
Codurile care pot reprezenta asemenea caractere se numesc coduri alfanumerice.
1.7.4.1. ASCII
Un cod alfanumeric foarte des utilizat este codul ASCII (American Standard
Code for Information Interchange), care codifică literele mari şi mici ale alfabetului
englez, cifrele zecimale, semnele de punctuaţie şi alte caractere speciale. Codul
ASCII utilizează 7 biţi pentru a codifica 128 de caractere. Din cele 128 de
caractere, 94 sunt caractere care pot fi tipărite, iar 34 sunt caractere utilizate
pentru diferite funcţii de control.
In tabelul 1.12 se prezintă codurile ASCII. Cei 7 biţi ai codului sunt notaţi cu
b0 până la b7 , b7 fiind bitul c.m.s. De notat că cei trei biţi mai semnificativi ai
codului determină coloana din tabelă, iar cei patru biţi mai puţin semnificativi
determină linia din tabelă. De exemplu, litera A este reprezentată în ASCII prin
codul binar 100 0001 (coloana 100, linia 0001).
Cele 34 de caractere de control sunt desemnate în tabelul caracterelor
ASCII prin nume abreviate. Caracterele de control se utilizează pentru transmisia
datelor şi pentru aranjarea textului într-un anumit format. Există trei tipuri de
caractere de control: de formatare, de separare a informaţiei şi de control al
comunicaţiei. Dintre caracterele de formatare a textului menţionăm cele pentru
deplasare înapoi BS (Backspace), retur de car CR (Carriage Return) şi tabulare
orizontală HT (Horizontal Tabulation). Separatorii de informaţii se utilizează
pentru separarea datelor în secţiuni, de exemplu în paragrafe şi pagini. Acestea
cuprind caractere cum sunt separatorul de înregistrare RS (Record Separator) şi
separatorul de fişier FS (File Separator). Caracterele de control al comunicaţiei se
utilizează la transmisia textului. Exemple de asemenea caractere sunt STX (Start
of Text) şi ETX (End of Text), care se pot utiliza pentru încadrarea unui mesaj
transmis pe liniile de comunicaţie.
Tabelul 1.12. Codurile ASCII.
b3b2b1b0 b6b5b4
000 001 010 011 100 101 110 111
0000 NULL DLE 0 @ p ’ p
0001 SOH DC1 ! 1 A Q a q
0010 STX DC2 " 2 B R b r
0011 ETX DC3 # 3 C S c s
0100 EOT DC4 $ 4 D T d t
0101 ENQ NAK % 5 E U e u
0110 ACK SYN & 6 F V f v
0111 BEL ETB ‚ 7 G W g w
1000 BS CAN ( 8 H X h x
1001 HT EM ) 9 I Y i y
1010 LF SUB * : JZ i z
1011 VT ESC + ; K [ k {
1100 FF FS „ < L \ 1 I
1101 CR GS - = M ] m }
1110 SO RS . > N ^ n -
1111 SI US / ? O _ o DEL
1.7.4.2. Unicode şi ISO/IEC 10646
Unicode este un set de caractere specificat de un consorţiu de
producători importanţi de calculatoare din SUA, definit cu scopul de a elimina
dificultăţile datorate utilizării seturilor de caractere codificate diferit în
programele elaborate pentru mai multe limbi. Incepând cu versiunea 1.1,
Unicode este compatibil cu standardul 10646, a cărui primă versiune a fost
elaborată în 1993 de organizaţiile ISO (International Standards Organization)
şi IEC (International Electrotechnical Commission). Numele standardului este
„Universal Multiple-Octet Coded Character Set”, întâlnit şi sub forma
acronimului UCS (Universal Character Set). Versiunea curentă a standardului
10646 este 3.0, care a fost publicată în februarie 2000. UCS a fost primul set
de caractere standardizat elaborat cu scopul de a include în final toate
caracterele utilizate în toate limbile scrise din lume, ca şi alte simboluri, cum
sunt cele matematice. UCS este utilizat atât pentru reprezentarea internă a
datelor în sistemele de calcul, cât şi pentru comunicaţiile de date.
In versiunile uzuale ale UCS, codul unui caracter este reprezentat prin
patru cifre hexazecimale; aceasta corespunde formei pe doi octeţi, denumită
UCS-2. A fost definită de asemenea şi o formă pe 4 octeţi, UCS-4, pentru a
garanta faptul că spaţiul de codificare va fi suficient şi în viitor. Primele 128
de caractere reprezintă caracterele ASCII.
In forma pe 4 octeţi, pot fi reprezentate peste 2 miliarde de caractere
diferite.
In forma UCS-2 se găsesc caracterele care formează setul Basic Latin, Latin-
1, Latin Extended-A, Latin Extended-B, alfabetele grec, chirilic, armean, ebraic,
arab, bengali, tamil, georgian, diferite simboluri, săgeţi, operatori matematici, forme
geometrice etc.. Aceste coduri conţin litere suplimentare utilizate în principalele
limbi din Europa de Vest, ca şi semne matematice şi de punctuaţie. Codurile din
setul Latin-1 se bazează pe standardul ISO/IEC 8859-1.
Literele ă, Ă, ş, Ş, ţ, Ţ din limba română fac parte din setul Latin Extended-
A, în timp ce literele â, Â, î, î fac parte din setul Latin-1.

Cap.4. UNITATEA DE COMANDĂ Şl CONTROL


Funcţiile principale ale unităţii de comandă şi control sunt următoarele:
• Decodificarea codului operaţiei;
• Calculul adresei operanzilor care participă la operaţie şi extragerea lor din
memorie;
• Generarea secvenţei de comenzi necesare execuţiei instrucţiunii;
• Generarea secvenţei de comenzi necesare memorării rezultatului şi a
informaţiilor de stare;
• Calculul adresei instrucţiunii următoare şi citirea acesteia din memorie.
4.1. Microoperaţii
Prelucrările efectuate de UCP pentru execuţia unei singure instrucţiuni
reprezintă un ciclu de instrucţiune. Fiecare ciclu de instrucţiune constă din
următoarele subcicluri:
• Subciclul de extragere a instrucţiunii din memorie;
• Subciclul de execuţie;
• Subciclul de întrerupere.
Pe lângă aceste subcicluri prezentate în cadrul capitolului despre UCP, mai
există un subciclu care poate apare la execuţia unei instrucţiuni. Acesta este
subciclul de indirectare.
Execuţia unei instrucţiuni poate necesita extragerea unuia sau a mai multor
operanzi din memorie. După extragerea instrucţiunii, se testează dacă un operandul
necesar este adresat în modul indirect. In caz afirmativ, se încarcă operandul
respectiv utilizând adresarea indirectă.
Ciclul de instrucţiune, completat cu subciclul de indirectare, este reprezentat
simplificat în figura 4.1.
Fig.4.1
Fiecare subciclu al unei instrucţiuni poate fi descompus într-o serie de operaţii
elementare. O asemenea operaţie elementară, care realizează o prelucrare
numerică a informaţiei sau un transfer al acesteia, pe durata unui singur impuls al
generatorului de tact, se numeşte microoperaţie. Aceste microoperaţii sunt
operaţiile fundamentale, indivizibile ale UCP.
Unitatea de comandă şi control are rolul de a genera succesiunea semnalelor
de comandă care asigură secvenţa corectă de execuţie a fiecărei microoperaţii.
Această succesiune este specifică fiecărei instrucţiuni, fiind determinată atât de codul
operaţiei, cât şi de recepţionarea unor semnale de stare de la circuitele controlate,
prin care se verifică îndeplinirea unor condiţii.
In continuare se analizează subciclurile care intră în componenţa unei
instrucţiuni şi microoperaţiile din care se compune fiecare ciclu. Pentru aceasta să
presupunem că UCP utilizează următorii regiştri:
- Registrul de adrese al memoriei (RA). Este conectat la liniile de adresă ale
magistralei sistem. Conţine adresa de memorie pentru o operaţie de citire sau
scriere.
- Registrul de date al memoriei (RD). Este conectat la liniile de date ale ma-
gistralei sistem. Conţine valoarea care trebuie depusă în memorie sau ultima
valoare citită din memorie.
- Contorul de program (PC). Conţine adresa următoarei instrucţiuni care se va
executa.
- Registrul de instrucţiuni (Rl). Conţine ultima instrucţiune citită.
4.1.1. Subciclul de extragere
La începutul subciclului de extragere, adresa instrucţiunii care urmează să fie
executată se află în registrul PC. Primul pas al subciclului de estragere constă în
transferul adresei din PC în registrul de adrese RA. Al doilea pas al acestui subciclu
constă în citirea instrucţiunii. Pentru aceasta, adresa din RA este depusă pe magistrala
de adrese, unitatea de comandă transmite o comandă de citire pe magistrala de co-
menzi, iar rezultatul citirii (codul instrucţiunii) este plasat pe magistrala de date şi
memorat în RD. Urmează apoi incrementarea registrului PC cu 1 pentru a pregăti
citirea următoarei instrucţiuni. Deoarece operaţiile de citire din memorie şi de
incrementare a PC sunt independente, se pot efectua în acelaşi timp. Al treilea pas
constă în transferul conţinutului registrului RD în Rl, fapt care eliberează registrul de
date pentru a putea fi utilizat eventual în subciclul de indirectare.
Operaţiile executate în acest subciclu sunt indicate în figura 4.3.
Fig.4.3
Deci, subciclul de extragere constă din trei paşi şi patru microoperaţii. Fiecare
microoperaţie implică transferul datelor în sau dintr-un registru.
Se presupune că există un semnal de tact (ceas), care generează impulsuri la
intervale constante. Fiecare impuls de ceas defineşte o unitate de timp. Această
unitate de timp este aleasă astfel încât fiecare microinstrucţiune să poată fie
executată pe durata unui singur impuls de ceas. Unităţile de timp sunt notate cu
t1, t 2 , t3 .
Simbolic, secvenţa de microinstrucţiuni care descrie microoperaţiile prezentate
anterior se poate scrie astfel:
RA ← PC
t1 :
t 2 : RD ← Mem
PC ← PC+1
t 3 : RI ← RD
A treia microoperaţie se poate executa şi în unitatea de timp t3, fără a afecta
subciclul de extragere.
4.1.2. Subciclul de indirectare
După extragerea instrucţiunii din memorie, urmează să se încarce operanzii
care participă la operaţie specificată de această instrucţiune. Unitatea de comandă
examinează conţinutul registrului Rl şi, dacă este indicată o adresare directă, aduce în
RD conţinutul locaţiei de memorie a cărei adresă este specificată în câmpul de adresă
a instrucţiunii.
Adresarea directă se referă la situaţia în care câmpul de adresă conţine
adresa efectivă a operandului (Figura 4.4):
Acest mod de adresare presupune o singură referire la memorie şi nu necesită
un calcul de adresă.
Fig. 4.4
In cazul adresării indirecte, urmează un subciclu de indirectare care precede
subciclul de execuţie. Adresarea indirectă se referă la situaţia în care în câmpul de
adresă al instrucţiunii se găseşte o referinţă la un cuvânt de memorie, care conţine
adresa completă a operandului (Figura 4.5.).
Instrucţiune
ADR1
ADR2
Fig. 4.5.
Câmpul de adresă din registrul de instrucţiuni Rl este transferat în RA.
Această adresă este utilizată apoi pentru încărcarea adresei operandului în registrul
de date RD. Câmpul de adresă din Rl este actualizat pentru a conţine adresa directă a
operandului.
Fig.4.6
Registrul Rl conţine în acest moment adresa din memorie a operandului şi este
pregătit pentru subciclul de execuţie. Operaţiile executate în acest subciclu sunt
indicate în figura 4.6.
Descrierea simbolică a microoperaţiilor prezentate este următoarea:
t1 : RA ← RI(ADR1)
t2 : RD ← Mem
t3 : Rl ← RD (ADR2)
4.1.3. Subciclul de execuţie
Subciclurile de extragere şi de indirectare, ca şi subciclul de întrerupere,
implică secvenţe fixe de microinstrucţiuni. Subciclul de execuţie diferă în funcţie de
instrucţiune, pentru fiecare instrucţiune existând o secvenţă proprie de
microinstrucţiuni care trebuiesc executate.
Considerăm ca exemplu instrucţiunea:
ADD R1, X
care adună valoarea variabilei X din memorie la conţinutul registrului R1, rezultatul
fiind memorat tot în R1.
Execuţia acestei instrucţiuni poate fi descrisă prin următoarea secvenţă de
microinstrucţiuni:
RA ← RI(ADR)
t1 :
RD ← Mem
t2 :
R1 ← R1+RD
t3 :
Rl conţine codul instrucţiunii ADD. La primul pas, partea de adresă din Rl, care
reprezintă adresa variabilei X, este încărcată în RA. Apoi, se citeşte din locaţia de
memorie adresată valoarea variabilei X şi se depune în RD. In final, conţinutul
registrului R1 şi al RD sunt adunate de UAL.
Acesta este un exemplu simplificat, fiind necesare microoperaţii suplimentare
pentru adresarea registrului specificat şi pentru a depune operanzii din UAL în regiştri
temporari.
4.1.4. Subciclul de întrerupere
La terminarea subciclului de execuţie, în cazul în care întreruperile sunt validate,
se testează dacă a apărut o cerere de întrerupere. In caz afirmativ, se execută un
subciclu de întrerupere. Secvenţa de operaţii executate variază de la un calculator la
altul. Un exemplu este prezentat în continuare.
La primul pas, conţinutul contorului de program PC este transferat în registrul
de date RD, pentru a fi salvat în memorie, în scopul reluării operaţiei după terminarea
întreruperii. La pasul al doilea, registrul de adrese RA este încărcat cu adresa la care
urmează să fie memorat conţinutul PC. Salvarea se poate face într-o locaţie specială
de memorie sau în stivă; în ultimul caz conţinutul indicatorului de stivă SP este
transferat în RA. In acelaşi pas poate fi încărcat şi contorul de program cu adresa
rutinei de tratare a întreruperii. Deoarece cele mai multe UCP permit mai multe tipuri şi
nivele de întrerupere, sunt necesare microinstrucţiuni suplimentare pentru a obţine
adresa de salvare a registrului PC şi adresa rutinei de tratare. Ultimul pas constă în
memorarea registrului de date RD. Astfel, în următorul subciclu se va încărca prima
instrucţiune a rutinei de tratare.
RD ← PC
t1 :
RA ← Adresa_salvare
t2 :
PC ← Adresa_rutina
Mem ← RD
t3 :
4.2.2. Semnale de control ale UCC
Pentru a-şi realiza funcţiile, unitatea de comandă trebuie să aibă intrări care să
permită determinarea stării sistemului şi ieşiri care să permită controlul funcţionării
sistemului. Intrările şi ieşirile unei unităţi de comandă şi control se prezintă în figura
4.8. Intrările sunt următoarele:
- Ceas: UCC comandă execuţia unei microinstrucţiuni (sau a unui set de
microinstrucţiuni simultane) la fiecare impuls de ceas. Perioada semnalului de ceas
se mai numeşte ciclu de ceas.
- Codul operaţiei: Se citeşte din registrul de instrucţiuni, care păstrează
instrucţiunea curentă şi se utilizează pentru a determina microoperaţiile care trebuie
executate în timpul ciclului de execuţie.
- Indicatori de condiţii: Sunt necesari pentru a determina starea UCP şi rezul-
tatul operaţiei precedente executate de UAL, în scopul executării instrucţiunilor de
salt condiţionat.
- Semnale de control: Magistrala de control din cadrul magistralei sistem
furnizează semnale pentru UCC, ca semnale de întrerupere sau de achitare a unei
întreruperi.
Fig. 4.8
Ieşirile sunt următoarele:
- Semnale prin care se comandă funcţionarea UCP: Acestea sunt de două
tipuri: semnalele care determină transferul datelor dintr-un registru în altul şi
semnalele care activează funcţii specifice ale UAL.
- Semnale de control transmise pe magistrala de control: Acestea sunt tot de
două tipuri: semnale de control la memorie şi semnale de control la modulele de I/E.
Pentru a înţelege funcţionarea UCC să considerăm din nou ciclul de încărcare
al unei instrucţiuni. Adresa instrucţiunii care urmează să fie executată este păstrată
în registrul PC. Primul pas constă în transferul:
RA ← PC
Acest transfer se efectuează prin activarea unui semnal de control care des-
chide (activează) porţile dintre cele două registre.
Următorul pas constă în citirea din memorie a instrucţiunii de la adresa indicată,
aducerea acesteia în registrul de date şi incrementarea contorului de program PC:
RD ← Mem
PC ← PC + 1
Aceste operaţii se efectuează prin activarea simultană de către UCC a
următoarelor semnale de control:
1. un semnal de control care validează depunerea conţinutului RA pe magistrala
de adrese.
2. un semnal de control trimis pe magistrala de control, pentru citirea memoriei.
3. un semnal de control care validează memorarea conţinutului de pe magistrala
de date în registrul de date RD.
4. semnale de control prin care se incrementează cu 1 conţinutul PC şi se depu-
ne rezultatul înapoi în PC.
Ultimul pas constă în transferul:
RI ← RD
pentru care se activează un alt semnal de control care validează transferul.
In continuare UCC trebuie să decidă dacă urmează un ciclu de indirectare
sau un ciclu de execuţie. Pentru aceasta, examinează conţinutul registrului de
instrucţiuni Rl şi testează dacă se utilizează o adresare indirectă, caz în care
stabileşte secvenţa corespunzătoare de microoperaţii.
Pentru ciclul de execuţie, UCC testează codul de operaţie al instrucţiunii, pe
baza căruia decide secvenţa de microoperaţii care va fi executată.
4.2.3. Exemplu de unitate de comandă
Să considerăm o unitate centrală simplă cu un singur registru acumulator. In
figura 4.9 sunt prezentate căile de date dintre elemente şi semnalele de control
corespunzătoare.
UCC primeşte intrări de la generatorul de ceas, registrul de instrucţiuni şi
indicatorii de condiţii. La fiecare ciclu de ceas, UCC citeşte toate intrările sale şi gene-
rează setul corespunzător de semnale de control. Semnalele de control au trei
destinaţii distincte:
Fig. 4.9
- Semnale de control pentru căile de date: UCC controlează fluxul intern al
datelor. Pentru fiecare cale controlată, există o poartă (indicată printr-un cerc în
figură). Un semnal de control deschide (activează) temporar poarta pentru a permite
transferul datei.
- Semnale de control pentru UAL: UCC controlează funcţionarea UAL printr-un
set de semnale de control. Aceste semnale activează diferite circuite din cadrul UAL.
- Semnale de control pentru magistrala sistem: UCC transmite semnale de
control pe liniile de control ale magistralei sistem.
Secvenţierea în timp a operaţiilor este realizată cu ajutorul impulsurilor de
ceas, prevăzându-se un interval de timp între diferitele operaţii pentru stabilizarea
nivelului semnalelor. In tabelul 4.1 se indică semnalele de control care sunt necesare
pentru o parte a secvenţelor de microoperaţii descrise anterior. Pentru simplitate,
căile de date şi semnalele de control pentru incrementarea PC şi pentru încărcarea
adreselor fixe în PC şi MA nu au mai fost indicate.
Tabelul 4.1
Ciclu Microinstrucţiuni Semnale de control active
Extragere C2
RA ← PC
t1 :
C5,CR
RD ← M
t2 :
PC ← PC+1
C4
RI ← RD
t3 :
Indirectare C8
RA ← RI(ADR1)
t1 :
C5,CR
RD ← M
t2 :
C4
RI(ADR2) ← RD(ADR2)
t3 :
Întrerupere C1
RD ← PC
t1 :
RA ← Adresa_salvare
t2 :
PC ← Adresa_rutinei
C12,CW
M ← RD
t3 :
S-a notat cu: CR - semnal de citire de pe magistrala sistem; Cw - semnal de scriere
pe magistrala sistem.
4.4. Implementarea UCC
Pentru implementarea UCC se utilizează diferite metode, care se pot încadra
într-una din următoarele două categorii:
• UCC cablată;
• UCC microprogramată.
O unitate de comandă cablată este, în principiu, un circuit secvenţial care
transformă semnalele logice de intrare într-un set de semnale electrice de ieşire, care
reprezintă semnalele de control. Modificarea funcţiilor unei astfel de unităţi de
comandă necesită modificări ale structurii hardware a circuitului.
In continuare se prezintă câteva tipuri de UCC care utilizează implementarea
cablată.
4.4.2. UCC care utilizează un decodificator
UCC utilizează codul instrucţiunii şi va executa diferite acţiuni pentru fiecare
instrucţiune. Codul instrucţiunii va fi decodificat cu ajutorul unui decodificator care
activează un singur semnal de ieşire.
Generatorul de ceas generează o secvenţă de impulsuri, a căror perioada
trebuie să fie suficientă pentru a permite propagarea semnalelor prin căile de date şi
prin circuitele UCP. Pentru secvenţierea în timp a semnalelor de comandă se
utilizează un generator de faze, care generează semnalele de intrare T1,T2 ,..., Tn . In
fiecare din aceste momente UCC activează semnalele de comandă cerute de codul
instrucţiunii. La sfârşitul fiecărui ciclu de instrucţiune, UCC reiniţializează generatorul
de faze pentru a relua generarea secvenţei T1,T2 ,..., Tn .
Structura unei UCC cu decodificator este prezentată în figura 4.12. Fiecare
semnal ce comandă este precizat de o ecuaţie booleană. Pentru a arăta modul în care
se deduc ecuaţiile booleene ale semnalelor de comandă în funcţie de intrările UCC
vom considera exemplul prezentat în tabelul 4.1. De exemplu semnalul C5 este
activat pentru citirea datelor de pe magistrala de date în registrul de date RD. Din
tabela cu secvenţele de microinstrucţiuni, se observă că acest semnal este utilizat de
două ori, în două subcicluri diferite. Pentru precizarea subciclului în care trebuie să fie
activ un anumit semnal de comandă se definesc două noi semnale de comandă, P şi
Q , cu semnificaţia următoare (vezi figura 4.7):
PQ =00 Subciclul de extragere
PQ =01 Subciclul de indirectare
PQ =10 Subciclul de execuţie
PQ =11 Subciclul de întrerupere
Fig. 4.12
După cum se constată din tabelul 4.1 semnalul C5 este activat în a doua unitate
de timp a subciclului de extragere şi în a doua unitate de timp a celui de indirectare,
deci poate fi definit prin ecuaţia:
C5 = P ⋅ Q ⋅ T2 + P ⋅ Q ⋅ T2
unde T2 este unul dintre semnalele elaborate de generatorul de faze.
Acest semnal trebuie însă activat şi în subciclul de execuţie, pentru citirea
datelor din memorie. Pentru acest exemplu, vom presupune că există numai trei
instrucţiuni care execută citirea memoriei: LDA, ADD şi AND. Notăm semnalele
activate la ieşirea decodificatorului cu numele instrucţiunii respective. Presupunând
că citirea memoriei are loc tot în momentul t2 (după încărcarea adresei în RA), C5
poate fi definit prin ecuaţia:
C5 = P ⋅ Q ⋅ T2 + P ⋅ Q ⋅ T2 + P ⋅ Q ⋅ ( LDA + ADD + AND ) ⋅ T2
In acelaşi mod se scriu ecuaţiile tuturor semnalelor de comandă. Rezultatul va fi
un set de ecuaţii booleene care defineşte funcţionarea UCC.
UCC trebuie să controleze de asemenea starea ciclului de instrucţiune. La
sfârşitul fiecărui subciclu, trebuie să se actualizeze semnalele P şi Q pentru a indica
următorul subciclu care va fi executat.
4.4.3. Unităţi de comandă microprogramate
4.4.3.1. Principiul UCC microprogramate
Semnalele de comandă elaborate de UCC pot fi reunite sub forma unei
succesiuni de cifre binare, formând un cuvânt numit cuvânt de comandă. Fiecare
microoperaţie se caracterizează printr-un cuvânt specific de comandă, iar
succesiunea cuvintelor de comandă prin care se indică secvenţa corectă a
microoperaţiilor, pentru fiecare operaţie, poate fi memorată într-o memorie de
comandă.
O unitate de comandă în care succesiunea cuvintelor de comandă, adică a
valorilor semnalelor de comandă, este memorată, este numită unitate de comandă
microprogramată. Fiecare cuvânt de comandă memorat în memoria de comandă
formează o microinstrucţiune, iar secvenţa de microinstrucţiuni formează un
microprogram.
O unitate de comandă microprogramată are două funcţii principale:
- Funcţia de control propriu-zis, prin care se stabilesc microinstrucţiunile care
trebuiesc executate pentru instrucţiunea decodificată . Această operaţie cuprinde de
obicei selecţia operanzilor, a operaţiei de executat, selecţia destinaţiei rezultatului
etc.
- Funcţia de secvenţiere, prin care se determină adresa microinstrucţiunii
următoare. Această funcţie se referă la identificarea sursei pentru adresa următoarei
microinstrucţiuni în funcţie de valorile de test sau la generarea directă a valorii
adresei.
Fig. 4.13
In conformitate cu aceste funcţii pe care trebuie să le îndeplinească unitatea
ce comandă microprogramată, o microinstrucţiune este formată din următoarele
câmpuri principale (Fig. 4.13):
- Câmpul semnalelor de comandă generate pentru controlul UCP. Acest câmp
conţine câte un bit pentru fiecare semnal de comandă intern al UCP.
- Câmpul semnalelor de comandă pentru magistrala sistem. Acest câmp
conţine câte un bit pentru fiecare semnal de comandă al magistralei sistem.
- Câmpul de condiţii, de care depinde următoarea microinstrucţiune care va fi
executată.
- Câmpul de adresă, care conţine adresa următoarei microinstrucţiuni care se
va executa, dacă o anumită condiţie este adevărată. De exemplu, dacă bitul de
indirectare din codul instrucţiunii este 1 (condiţia aste adevărată), se va executa
secvenţa de microinstrucţiuni pentru calcularea adresei efective a operandului. Dacă
acest bit este 0 (condiţia este falsă), se va executa următoarea microinstrucţiune din
memoria de comandă, a cărei adresă este indicată în câmp.
Acest tip de microinstrucţiune se numeşte microinstrucţiune orizontală. Spre
deosebire de acestea se utilizează şi microinstrucţiuni verticale care utilizează un cod
pentru fiecare operaţie care trebuie executată.
O microinstrucţiune orizontală este interpretată în modul următor:
1. Pentru execuţia microinstrucţiunii, se activează toate semnalele de comanda
cărora le corespunde un bit de 1 în câmpul semnalelor de comandă şi se
dezactivează cele cărora le corespunde un bit de 0. Semnalele de comandă care vor
fi activate vor determina execuţia uneia sau a mai multor microinstrucţiuni.
Fig. 4.14
2. In cazul în care condiţia indicată de câmpul de condiţie este falsă, se trece la
execuţia următoarei microinstrucţiuni din microprogram.
3. In cazul în care condiţia indicată de câmpul de condiţie este adevărată, se
trece la execuţia microinstrucţiunii indicată de câmpul de adresă.
In figura 4.14 se prezintă amplasarea microinstrucţiunilor în memoria de
comandă.
Microinstrucţiunile din fiecare rutină sunt executate secvenţial. Fiecare rutină se
termină cu o instrucţiune de salt care indică următoarea rutină care va fi executată.
Există o rutină specială pentru începutul unui subciclu de execuţie, care după
încărcare şi decodificare indică rutina care va fi executată pentru diferitele instrucţiuni
(ADD, AND, ..., JMP), în funcţie de codul instrucţiunii.
Memoria de comandă reprezintă o descriere completă a funcţionării UCC,
deoarece defineşte secvenţa de microinstrucţiuni care trebuie executate în timpul
fiecărui subciclu (de extragere, de indirectare, de execuţie, de întrerupere) şi
specifică secvenţierea acestor subcicluri.
4.4.3.2. Structura unei UCC microprogramate
In figura 4.15 se prezintă elementele principale ale unei unităţi de comandă
microprogramate.
Registrul de microadrese (RMA) conţine adresa următoarei microinstrucţiuni
care va fi citită din memoria de comandă. După citire, microinstrucţiunea este transfe-
rată în registrul de microinstrucţiuni (RMI). Prin acest registru se activează semnalele
de comandă. Logica de secvenţiere încarcă registrul de microinstrucţiuni şi
activează comanda de citire.
Fig.4.15
Structura mai detaliată a unităţii de comandă este prezentată în figura 4.16
Unitatea microprogramată are aceleaşi intrări (Rl, indicatori de condiţii ai UAL,
ceas) şi ieşiri (semnale de comandă) ca şi o unitate de comandă cablată. Unitatea de
comandă funcţionează astfel:
1. Pentru execuţia instrucţiunii din RI, logica de secvenţiere activează un
semnal de citire a memoriei de comandă.
2. Cuvântul a cărei adresă este specificată în registrul de microadrese va fi
citit şi depus în registrul de microinstrucţiuni.
3. Conţinutul registrului de microinstrucţiuni activează semnalele de comandă şi
generează informaţii despre adresa următoare pentru logica de secvenţiere.
4. Logica de secvenţiere încarcă o nouă adresă în registrul de microadrese, pe
baza informaţiilor despre adresa următoare de la registrul de microinstrucţiuni şi a
indicatorilor de condiţii ai UAL.
In figura 4.16 există două decodificatoare. Primul decodificator translatează
codul operaţiei din registrul de instrucţiuni Rl într-o adresă a memoriei de comandă.
Al doilea decodificator este utilizat doar în cazul microinstrucţiunilor verticale.
Reamintim că într-o microinstrucţiune orizontală, fiecărui bit al câmpului de comandă
îi corespunde un semnal de comandă, în timp ce într-o microinstrucţiune verticală, se
utilizează un cod pentru fiecare microoperaţie care trebuie executată, de exemplu RA
← PC, iar decodificatorul translatează acest cod în semnale de comandă individuale.
Avantajul microinstrucţiunilor verticale constă în faptul că ele sunt mai compacte,
utilizând un număr mai mic de biţi, cu preţul unei logici suplimentare.
Avantajul principal al utilizării microprogramării pentru implementarea unităţilor
de comandă este simplificarea proiectării acestora. O unitate de comandă cablată
trebuie să conţină o logică complexă pentru secvenţierea microinstrucţiunilor din ciclul
de instrucţiune. In schimb, decodificatoarele şi logica de secvenţiere dintr-o unitate
de comandă microprogramată sunt simple.
Fig. 4.16
Dezavantajul principal al unităţilor microprogramate este că sunt mai lente
decât cele cablate realizate într-o tehnologie comparabilă. Cu toate acestea, micro-
programarea este tehnica cea mai utilizată pentru implementarea unităţilor de
comandă.

Cap.5. Magistrale
5.1 Noţiuni generale
Transferul informaţiilor digitale, între subsistemele unui calculator, se
realizează în mod secvenţial, prin intermediul unor linii multiple de legătură, numite
magistrale (bus). Magistralele reprezintă căi electrice de transmitere a semnalelor
intre diferite elemente ale unui sistem de calcul.
Prin magistrală se înţelege un ansamblu de linii conductoare, grupate
funcţional, menite să conecteze două sau mai multe unităţi componente ale unui
sistem de calcul. Pe fiecare linie a unei magistrale se poate transfera, la un
moment dat, o singură valoare logică (asignată unui nivel de tensiune bine definit),
ce reprezintă o cantitate de informaţie de 1 bit. Dacă magistrala are n linii, atunci
pe magistrală se transferă n biţi de informaţie în paralel şi vom spune că
magistrala transferă cuvinte de informaţie de dimensiune n.
Anumite dispozitive conectate la magistrală sunt active şi pot iniţia un transfer, iar
altele sunt pasive şi aşteaptă cererile de transfer. Dispozitivele active se numesc
dispozitive master, iar cele pasive - dispozitive slave. Atunci când UCP solicită unui
controler de disc citirea sau scrierea unui bloc, UCP are rol de master, iar controlerul
are rol de slave. Controlerul de disc poate deveni master, de exemplu atunci când
solicită memoriei acceptarea cuvintelor citite de pe disc. Memoria nu poate deveni
master în nici o situaţie.
Pentru amplificarea semnalelor, dispozitivele master se conectează la magistrală
prin drivere de magistrală (bus driver). Similar, dispozitivele slave sunt conectate prin
receptoare de magistrală (bus receiver). Pentru dispozitivele care pot fi atât emiţătoare
cât şi receptoare, se utilizează circuite emiţătoare/receptoare de magistrală (bus
transceiver).
5.3. Clasificarea magistralelor
După modul de transfer al informaţiilor, magistralele pot fi:
- magistrale unidirecţionale, la care transferul de informaţii se efectuează pe
toate liniile într-un singur sens, de la o unitate emiţătoare către una sau mai multe
unităţi receptoare;
- magistrale bidirecţionale, la care transferul se poate efectua în ambele
sensuri, alternativ prin multiplexare în timp, la un moment dat transferându-se
informaţii într-un singur sens. Astfel, unităţile conectate la o magistrală
bidirecţională pot fi pe rând unităţi emiţătoare sau receptoare de semnale.
După tipul informaţiilor transferate, magistralele pot fi:
- magistrale primare, pe care au loc transferurile informaţiilor utile, ce se
doresc a fi transmise între subsistemele unui calculator. Acestea pot fi: magistrale
de instrucţiuni sau magistrale de date.
- magistrale secundare, pe care au loc transferurile de informaţii
suplimentare, necesare obţinerii informaţiilor primare. Acestea pot fi: magistrale de
adrese, magistrale de comenzi sau magistrale de stări, considerate în general
unidirecţionale.
Deoarece memoria sistemului este comună pentru programe şi date, cele
două tipuri de informaţii primare sunt transferate pe o aceeaşi magistrală
bidirecţională, numită generic magistrală de date.
Cele două magistrale, de comenzi şi de stări transferă informaţii în sensuri
opuse şi formează împreună o magistrală bidirecţională pe linii separate, numită
magistrală de control.
După rata de transfer şi implicit după numărul de unităţi conectate, putem
avea:
- magistrale locale, care sunt amplasate în apropierea unităţilor foarte rapide,
cum este,de exemplu procesorul. Aceste magistrale sunt caracterizate de o rată
mare de transfer şi un număr mic de unităţi ce pot fi conectate la ele. Ca exemple,
pot fi date: magistrala locală a procesorului, magistrala locală a memoriei;
- magistrale de extensie (magistrale I/O), care sunt magistrale accesibile
utilizatorului, fiind terminate cu conectoare de extensie, de unde şi numele
acestora.
Magistralele de extensie sunt amplasate mai departe de procesor şi sunt
caracterizate de o rată mai mică de transfer şi un număr relativ mare de unităţi ce
pot fi conectate la ele. Dimensiunea conectoarelor depinde de standardul
magistralei respective şi în ele pot fi implantate diverse cuploare I/O, ce permit
extensia funcţiilor sistemului de calcul.
După modul de control al transferului de informaţii, magistralele pot fi sincrone
sau asincrone.
- Magistrale sincrone. Toate operaţiile magistralelor sincrone sunt sincronizate
de un semnal de ceas şi orice transfer durează un număr întreg de perioade de ceas,
numite cicluri de magistrala.
In cazul acestor magistrale, dacă un transfer se termină înaintea unui număr întreg
de cicluri, următorul transfer poate începe numai după sfârşitul ciclului în curs de
desfăşurare. Această situaţie conduce la întârzieri inutile.
Dacă la o magistrală sunt conectate dispozitive cu viteze diferite (unele lente,
altele rapide), viteza de transfer trebuie aleasă după dispozitivul cel mai lent, cele
rapide fiind întârziate.
- Magistrale asincrone. O magistrală asincronă elimină dezavantajele
magistralelor sincrone. In locul semnalului de ceas se utilizează un protocol logic
între emiţător şi receptor (numit handshake). In cadrul acestui protocol are loc un
schimb de informaţii între unitatea master şi unitatea slave care permit corelarea şi
coordonarea transferului de date. Fiecare acţiune a celor doi participanţi la transfer
este condiţionată de o acţiune anterioară şi nu de un impuls de ceas.
Magistralele asincrone necesită mai multe linii de semnal şi o logică mai
complexă, fapt care ridică preţul. Pentru acest motiv, în ciuda avantajelor
prezentate de acestea, magistralele sincrone sunt mai des utilizate.
5.4. Arbitrajul de magistrală
La majoritatea sistemelor, există mai multe module care pot prelua controlul
asupra magistralei (care pot deveni module master). Pentru acest motiv, dacă apar
mai multe cereri simultane de magistrală, este necesar să existe un mecanism de
arbitrare prin care să se determine modulul care va deveni master. Modulul master
va putea apoi iniţia un transfer cu un alt modul, care va avea rolul de modul slave
pentru acest transfer.
Metodele de arbitrare pot fi clasificate ca fiind centralizate sau descentralizate
(distribuite).
5.4.1. Arbitrarea centralizată
In cazul arbitrării centralizate, alocarea magistralei este realizată de un dispozitiv
hardware numit arbitru de magistrală. Acest dispozitiv poate fi un modul separat sau
poate face parte din UCP.
In figura 5.1 se prezintă un exemplu simplu de arbitrare centralizată.
In cadrul acestei soluţii există o singură linie de cerere a magistralei, care poate fi
activată de unul sau mai multe dispozitive în orice moment. Arbitrul nu poate distinge
dacă există mai multe cereri simultane sau o singură cerere, ci numai dacă există
sau nu cereri la un moment dat.
Fig. 5.1
Dacă linia de cerere este activată, arbitrul activează linia de acordare a
magistralei, la care sunt conectate în serie toate dispozitivele. Dispozitivul cel mai
apropiat fizic de arbitru detectează semnalul de pe această linie şi, în cazul în care a
efectuat o cerere, preia controlul asupra magistralei. Dacă nu a efectuat o cerere,
transmite semnalul următorului dispozitiv, care procedează la fel, până când un
dispozitiv preia controlul asupra magistralei.
In această schemă de tip daisy chain, prioritatea dispozitivelor este dată de
distanţa la care se află faţă de arbitru. Dispozitivul cel mai apropiat de arbitru are
prioritatea maximă. Pentru a modifica aceste priorităţi implicite, magistralele pot avea
mai multe nivele de prioritate. In acest caz pentru fiecare prioritate există o linie de
cerere şi una de acordare a magistralei.
Unele circuite de arbitrare au o linie suplimentară de achitare, ce este activată de
dispozitivul care a preluat controlul asupra magistralei în urma unui semnal de
acordare a magistralei. Imediat după activarea acestei linii, semnalele de cerere şi de
acordare pot fi dezactivate. In consecinţă, în timpul utilizării magistralei, alte dispozitive
pot solicita magistrala. La terminarea transferului curent va fi deja selectat următorul
dispozitiv master, care poate începe transferul imediat după dezactivarea semnalului
de achitare
5.4.2. Arbitrarea descentralizată
In cazul arbitrării descentralizate, nu există un arbitru de magistrală. Fiecare
modul are o prioritate unică şi conţine o logică pentru controlul accesului la
magistrală care ţine cont de priorităţile celorlalte module. In cazul în care un anumit
modul solicită accesul la magistrală, acesta verifică mai întâi dacă există vreun modul
cu prioritate mai mare care, de asemenea solicită magistrala. In cazul
în care o asemenea cerere nu există iniţiază transferul. Dacă un modul cu
prioritate mai mare iniţiază o cerere în acelaşi ciclu de ceas, acesta menţine cererea
până magistrala este eliberată. In figura 5.2 este prezentată schema unei magistrale
cu control descentralizat.
Fig. 5.2
5.5. Parcarea magistralelor
Anumite dispozitive master ale unui sistem de I/E, ca unităţile centrale, sunt
active în marea majoritate a timpului, în timp ce altele sunt active în mod sporadic. Un
dispozitiv din prima categorie poate păstra controlul asupra magistralei chiar după
terminarea transferului curent, deoarece este probabil că va utiliza magistrala şi în
continuare. Procedura prin care magistrala nu este eliberată automat după terminarea
transferului curent, ci numai în cazul în care există o cerere de magistrală, se
numeşte parcarea magistralei.
Prin utilizarea acestei metode, nu este necesară executarea operaţiilor de
eliberare a magistralei şi de arbitrare pentru fiecare transfer. Executarea arbitrajului de
magistrală pentru fiecare ciclu de transfer este dezavantajoasă. Dacă se utilizează
parcarea magistralei orice alt modul care solicită accesul la magistrală începe cu o
cerere adresată dispozitivului master de a elibera magistrala.
5.6. Magistrale locale
Magistrala procesorului este calea de comunicaţie între UCP şi subsistemele
cu care acesta lucrează direct. Magistrala procesorului este utilizată, de exemplu,
pentru a transfera date între UCP şi magistrala principală a sistemului, sau între
UCP şi memoria externă rapidă (memoria cache). Deoarece de performanţele
acestei magistrale depind în mare măsură performanţele calculatorului această
magistrală lucrează la o viteză mult mai mare decât orice altă magistrală din
sistem.
Magistrala procesorului are în componenţa magistrala de date, magistrala de
adrese şi pe cea de control. De exemplu, magistrala procesorului unui sistem
Pentium are 64 linii de date, 32 linii de adresă şi un număr de linii de control
asociate.
Magistrala memoriei este utilizată la transferul informaţiei între UCP şi
memoria principală - memoria RAM a sistemului. Această magistrală este
implementată printr-un set de circuite dedicate şi este responsabilă cu transferul
informaţiilor între magistrala procesorului şi memorie. In componenţa magistralei
memoriei intră şi o magistrala de adrese utilizată pentru selecţia locaţiei de
memorie în care urmează să se efectueze o operaţie de citire/scriere.
Fig. 5.3
Dimensiunea magistralei de memorie este strâns legată de mărimea
memoriei pe care unitatea centrală o poate adresa direct. In figura 5.3 sunt
prezentate magistralele locale ale unui sistem de calcul.
5.7. Magistrala de extensie
Magistrala de extensie, numită şi magistrală l/O, permite unităţii centrale, să
comunice cu dispozitivele periferice. Magistrala l/O face posibilă, de asemenea,
adăugarea de noi dispozitive pentru a extinde posibilităţile de prelucrare ale
calculatorului. Pot fi introduse în conectorii de extensie componentele de bază,
cum ar fi controlerele de hard disc şi plăcile adaptoare video; de asemenea, se pot
introduce dispozitive mai specializate, cum ar fi plăci de sunet şi plăci de interfaţă
cu unităţi CD-ROM.
De-a lungul evoluţiei sistemelor de calcul s-au dezvoltat mai multe tipuri de
magistrale de I/O. Dintre acestea cele mai importante sunt:
- ISA;
- MCA;
- EISA;
- Magistrala locală;
- Magistrala VESA locală;
- Magistrala PCI;
- Magistrala PCMCIA.
Aceste magistrale se deosebesc în principal prin numărul de informaţii
transferate simultan şi prin viteza cu care se face acest transfer. Arhitectura
magistralei este realizată cu un set de circuite, care este conectat la magistrala
procesorului.
5.7.1 Magistrala ISA
Magistrala ISA (Industry Standard Architecture) este arhitectura de
magistrală introdusă odată cu primul IBM PC, în 1982 şi care a fost mai târziu
îmbunătăţită la modelul IBM PC/AT. Până nu de mult magistrala ISA stătea la
baza calculatorului personal modern şi era principala arhitectură folosită în marea
majoritate a sistemelor PC de pe piaţă. Longevitatea acestei magistrale se
datorează siguranţei, accesibilităţii şi compatibilităţii sale.
Există două versiuni de magistrale ISA, care se deosebesc prin numărul de
biţi de date ce pot fi transferaţi simultan pe magistrală. Versiunea mai veche este
magistrala pe 8 biţi. Versiunea mai nouă este magistrala pe 16 biţi. Ambele
versiuni de magistrală funcţionează la 8 MHz, având nevoie de două până la opt
perioade de ceas pentru transferul datelor.
Magistrala ISA pe 8 biţi a fost utilizată de primele calculatoare IBM PC.
Magistrala ISA pe 16 biţi a devenit necesară odată cu apariţia microprocesoarelor
IA80286 care erau pregătite să transfere simultan 16 biţi pe magistrala de I/E.
Conectorii acestei magistrale erau prevăzuţi cu două secţiuni de câte 8 biţi fiecare.
O placă veche,pe 8 biţi, se putea introduce în una dintre cele două secţiuni, în
timp ce plăcile din generaţia nouă ocupau ambele secţiuni.
5.7.2 Magistrala MCA
Apariţia procesoarelor pe 32 de biţi a făcut ca magistrala ISA să nu mai
corespundă puterii noii generaţii de procesoare. Microprocesoarele 386 transferă
32 de biţi de date simultan, iar magistrala ISA poate transfera doar maxim 16 biţi.
In loc să extindă din nou magistrala ISA, IBM a decis să construiască o nouă
magistrală; aşa a apărut magistrala MCA (Micro Channel Architecture). MCA este
complet diferită de magistrala ISA şi îi este superioară din toate punctele de
vedere.
Magistrala MCA nu este compatibilă cu vechea magistrală ISA, deci plăcile
proiectate pentru magistrala ISA nu funcţionează într-un sistem MCA. MCA
funcţionează asincron cu procesorul central CPU, deci există mai puţine probleme
de sincronizare între plăcile adaptoare, pe magistrală.
MCA admite controlul total al magistralei (bus-mastering). Prin
implementarea tehnologiei bus-mastering, s-au realizat îmbunătăţiri semnificative
ale performanţelor în comparaţie cu magistrala ISA.
Deoarece şi magistrala EISA utilizează tehnologia bus-mastering principiul
acestei metode va fi prezentat la descrierea magistralei EISA.
In implementarea MCA bus-mastering, orice dispozitiv poate cere accesul
exclusiv la magistrală cu scopul de a comunica cu alt dispozitiv conectat şi el la
magistrală. Această cerere se face prin intermediul unui dispozitiv numit Central
Arbitration Control Point (Punct central de arbitrare), pe scurt CACP. CACP
arbitrează competiţia pentru transferul pe magistrală, asigurând accesul tuturor
dispozitivelor la magistrală dar împiedicând, în acelaşi timp, monopolizarea
acesteia de singur dispozitiv.
Sistemul de arbitraj al magistralei are în structura sa 4 linii de prioritate, care
stabilesc 16 nivele de prioritate. Fiecărui dispozitiv master i se atribuie un nivel de
prioritate între 0 şi F, nivelul F fiind cel mai puţin prioritar. Dispozitivul cu nivelul de
prioritate F este numit master implicit. Atunci când nu există nici un alt master sau la
apariţia unei condiţii de excepţie, magistrala este acordată acestui dispozitiv.
Un dispozitiv conectat la magistrala Micro Channel care doreşte să utilizeze
magistrala trimite numărul de prioritate care i-a fost acordat pe cele 4 linii de prioritate:
fiecare dispozitiv sau placă de extensie controlează aceste semnale şi renunţă la
magistrală, dacă detectează existenţa unei cereri de prioritate mai mare. Procesorul
principal (UCP) are prioritatea cea mai mică (F) fiind master implicit.
5.7.3 Magistrala EISA
EISA sunt iniţialele pentru Extended Industry Standard Architecture. Acest
standard a fost anunţat în septembrie 1988. Standardul EISA a fost dezvoltat de
un consorţiu de firme condus de Compaq şi Intel. Scopul acestei acţiuni era extinderea
magistralei ISA, astfel încât să permită arhitecturi de 32 de biţi şi viteze de transfer
superioare, păstrând însă compatibilitatea cu plăcile de extensie existente şi cu
perifericele.
In comparaţie cu arhitectura de sistem ISA pe 16 biţi, EISA permite mai
multe extensii cu mai puţine conflicte intre plăcile adaptoare.
Pentru a mări viteza sistemului, EISA utilizează o tehnologie numită bus
mastering (controlul total al magistralei). In esenţă, un dispozitiv cu opţiunea de
control total al magistralei este un adaptor prevăzut cu un procesor, care poate
executa operaţii independent de UCP. Pentru a funcţiona corespunzător,
tehnologia bus-mastering se bazează pe un circuit de arbitrare EISA (EISA
arbitration unit), numit de obicei cip ISP (Integrated System Peripheral - sistem
periferic integrat). Un controler de disc în tehnologia bus-mastering schimbă un
volum de date mult mai mare cu o unitate rapidă de hard disc, în comparaţie cu un
controler obişnuit.
Unitatea ISP decide care dispozitiv primeşte controlul, printr-un sistem de
patru niveluri de prioritate. Ordinea dată de nivelurile de prioritate este
următoarea:
- Reîmprospătarea memoriei
- Transferuri DMA
- UCP
- Plăci bus-master
Dispozitivul adaptor cu bus-mastering semnalează unităţii ISP că doreşte să
preia controlul sistemului. In cel mai scurt timp posibil (după ce au fost satisfăcute
priorităţile mai mari), ISP predă controlul dispozitivului. Aceste dispozitive au
incluse la rândul lor circuite care le împiedică să păstreze controlul pe perioadele
de timp care sunt necesare operaţiilor cu prioritate mai mare, cum ar fi
împrospătarea memoriei.
5.7.4 Magistrala locală
Magistralele l/O prezentate până acum au în comun o rată de transfer relativ
scăzută. In timp ce rata de transfer magistralei procesorului a crescut, magistrala
l/O a cunoscut doar ajustări neimportante ale acestui parametru, în principal prin
creşterea numărului de căi paralele. Magistrala l/O a trebuit să lucreze la o rată de
transfer scăzută deoarece majoritatea adaptoarelor instalate funcţionau doar la
viteze mai mici.
Figura 5.4 prezintă schema bloc de principiu a magistralelor unui sistem de
calcul.
Dacă pentru majoritatea dispozitivelor periferice cum sunt tastatura,
imprimantele, scannere, etc. această rată de transfer este suficientă, au apărut
dispozitive pentru care era necesar transferul rapid al unor blocuri mari de date.
Această necesitate apare mai ales la următoarele subsisteme:
- Adaptoare grafice. Interfeţele grafice ale sistemelor de operare Windows, OS/2
şi Unix X-Windows necesită actualizarea rapidă a imaginii grafice pentru deplasarea,
redimensionarea şi actualizarea ferestrelor multiple. Acelaşi lucru este valabil pentru
imaginile video în mişcare. Procesorul trebuie să actualizeze şi să transfere blocuri
mari de date în cadrul memoriei video.
- Adaptoare pentru interfaţa SCSI. Interfaţa SCSI este utilizată mai ales pentru
memorii de masă, ca unităţi de disc fix, unităţi CD-ROM şi unităţi de bandă încasetată.
Creşterea vitezei de transfer cu aceste dispozitive influenţează semnificativ
performanţele globale ale sistemului.
Fig. 5.4
O soluţie evidentă a acestei probleme este mutarea unora dintre extensiile
l/O într-o zonă unde pot avea acces la vitezele sporite ale magistralei procesorului,
la fel ca şi cea de care beneficiază şi memoria imediată. Figura 5.5 descrie
această nouă dispunere.
Această dispunere a componentelor a devenit cunoscută sub denumirea de
magistrală locală (local bus), deoarece dispozitivele externe (plăci adaptoare) pot
accesa acea parte a magistralei care aparţinea până acum doar procesorului şi
anume, magistrala procesorului.
Fig. 5.5
Soluţiile local-bus nu înlocuiesc standardele anterioare, cum ar fi ISA şi
EISA, ci sunt proiectate pentru a le îmbunătăţi. Pentru acest motiv, un sistem
uzual este bazat pe standardele ISA sau EISA fiind în acelaşi timp dotat şi cu unul
sau mai mulţi conectori local-bus. Astfel, plăcile mai vechi rămân compatibile cu
sistemul, iar plăcile adaptoare de mare viteză beneficiază acum de conectorii
local-bus.
5.7.5 Magistrala locală VESA
La început, magistrala locală era folosit în principal pentru adaptoarele
grafice. Această magistrală a apărut în sistemele de vârf în care strangulările erau
evidente. Din nefericire, spre sfârşitul anului 1992, mai multe sisteme local-bus
erau în competiţie pe piaţă şi fiecare sistem era brevetat. Această lipsă a
standardizării a stânjenit acceptarea largă a soluţiei local-bus.
Pentru a depăşi această problemă, Video Electronics Standard Association
(VESA) a dezvoltat un standard de magistrală local-bus cunoscut sub numele de
VESA Local-Bus sau, mai simplu, VL-Bus. La fel ca în implementările anterioare,
sistemele VL-Bus oferă accesul direct la memoria sistemului, cu viteza
procesorului. Magistrala VL-Bus transferă 32 de biţi de date simultan şi deci
permite ca transferul datelor între UCP şi un subsistem compatibil video sau un
hard disc, să se facă pe lungimea integrală de 32 de biţi a cuvântului pe care
comunică microprocesorul 486.
Magistrala locală VESA nu a mai fost dezvoltată pentru a fi adaptată la
procesoarele Pentium astfel încât a rămas inevitabil legată de procesorul 486.
5.5.6 Magistrala PCI
La începutul anului 1992, Intel a iniţiat crearea unui grup de lucru care a fost
constituit în aceleaşi scopuri ca şi grupul VESA. Recunoscându-se necesitatea de
a se depăşi slăbiciunile magistralelor ISA şi EISA s-a format grupul de interes PCI
(PCI Special Interest Group).
PCI sunt iniţialele pentru Peripheral Component Interconnect bus.
Documentaţia magistralei PCI, lansată în iunie 1992 şi modificată în aprilie 1993, a
reproiectat structura unui sistem de calcul prin intercalarea unei alte magistrale
între CPU şi magistrala l/O existentă, Această magistrală se conecta la celelalte
magistrale ale sistemului prin intermediul unor circuite bridge (punţi). S-a preferat
ca în loc să se intre direct pe magistrala procesorului, cu problemele sale delicate
de sincronizare (aşa cum s-a făcut în cazul magistralelor VL-bus şi local bus), să
se pună la punct un nou tip de controler pentru a extinde magistrala, ca în figura
5.6.
Magistrala PCI este numită adesea mezzanine bus, deoarece ea adaugă un
alt nivel configuraţiei tradiţionale de magistrală. Sistemele care au inclus
magistrala PCI au apărut pe piaţă la mijlocul anului 1993 şi de atunci au devenit
cele mai sigure sisteme de vârf.
Fig. 5.6
Rata de transfer a magistralei PCI a crescut considerabil. Una dintre cauzele
acestui transfer real mai rapid este faptul că magistrala PCI lucrează în paralel cu
magistrala procesorului, fără să o înlocuiască. Unitatea CPU poate procesa date
în memoria imediată în timp ce magistrala PCI este ocupată cu transferarea
informaţiilor între alte elemente ale sistemului, fapt care constituie un avantaj
major al magistralei PCI.
Magistrala PCI admite transferuri în mod exploziv (burst). Un asemenea
transfer constă dintr-o singură fază de adrese urmată de mai multe faze de date.
Arbitrajul de magistrală trebuie executat o singură dată la începerea fazei de adrese. In
timpul fazei de adrese se transmite adresa de început a blocului de date şi tipul
tranzacţiei care urmează; citire sau scriere. Dispozitivul slave memorează adresa de
început într-un contor de adrese şi va incrementa adresa în fiecare fază de date.
La magistralele EISA şi Micro Channel, posibilitatea de a utiliza modul exploziv
este stabilită printr-o negociere între dispozitivul master şi cel slave. Dacă aceste
dispozitive nu permit transferuri în mod exploziv, blocul de date se va transmite
utilizând o serie de tranzacţii separate şi, în acest caz, este necesar arbitrajul de
magistrală pentru fiecare tranzacţie individuală. In aceste condiţii un alt dispozitiv
master poate obţine magistrala între două tranzacţii şi această situaţie poate limita în
mod sever rata de transfer.
CPU
Slot pentru Front side bus Sloturi pt.
placă grafică Chipset memorie
RAM
Magistrală
AGP sau Magistrala
PCI Expres memoriei
Northbridge
Magistrala
internă
Sloturi
PCI Controler
grafic on
board
Magistrala
Southbridge
Magistrala b
PCI
PCI
Cabluri şi
IDE
porturi
SATA
off board
USB
Magistrala LPC
Porturi seriale
ROM
Porturi paralele
(BIOS)
Floppy disk
Tastatura
Mouse
Fig. 5.7
In cazul magistralei PCI, cele mai multe transferuri se execută în mod exploziv,
dispozitivele fiind proiectate astfel încât să permită asemenea transferuri. Dacă un
dispozitiv slave poate efectua numai tranzacţii singulare, la încercarea dispozitivului
master de a executa o tranzacţie în mod exploziv, dispozitivul slave termină
tranzacţia după prima fază de date. Astfel dispozitivul master va fi obligat să solicite
din nou magistrala printr-un proces de arbitraj. In acest mod performanţele vor fi mai
reduse, dar tranzacţiile singulare se pot utiliza pentru dispozitivele care nu necesită
rate ridicate de transfer.
Dezvoltarea ulterioară a magistralei PCI a condus la apariţia magistralei PCI
X şi aceasta cu diverse variante.
Din cauza tendinţei de dezvoltare a funcţiilor grafice posibilităţile magistralei
PCI au fost repede depăşite, în special pentru motivul că aceasta a fost concepută
pentru a deservi mai multe dispozitive. Această situaţie a condus la dezvoltarea
unei magistrale dedicate pentru adaptoarele grafice numită Accelerated Graphic
Port , sau prescurtat AGP. Magistrala AGP a fost utilizat, în primul rând, pentru a
accelera grafica 3D.
Magistrala AGP a fost înlocuită între anii 2004 – 2007 de magistrala PCI
Express, care avea performanţe îmbunătăţite.
In figura 5.7 sunt prezentate toate magistralele care sunt implicate în
realizarea unui sistem de calcul actual.
Punţile care conectează diverse magistrale între ele au în acest caz denumiri
consacrate. Astfel puntea care conectează magistrala procesorului (FSB) cu
magistrala memoriei şi magistrala plăcii grafice se numeşte Northbridge. Placa
grafică şi magistrala corespunzătoare poate fi de tip AGP sau, mai nou, PCI
Expres. O a doua punte numită Southbridge, conectează magistrala de extensie
care acum este de tip PCI (mezanin) cu porturile rapide (IDE, SATA, USB) şi cu
magistrala perifericelor lente numită LPC.
Magistrala LPC (Low Pin Count) conectează unităţile periferice de viteză
redusă cum sunt tastatura mouse-ul, controlerul de floppy disk, porturile seriale şi
paralele (la care poate fi conectată, de exemplu, o imprimantă), la circuitul
Southbridge. La aceeaşi magistrală este conectată şi memoria ROM în care se
găseşte BIOS-ul (Basic Input/Output Sistem). Această magistrală a fost concepută
pentru a înlocui magistrala ISA şi are avantajul că necesită mai puţine căi pentru
comunicaţia cu perifericele, fapt important pentru plăcile de bază actuale care sunt
în general foarte aglomerate. Punţile Northbridge şi Southbridge sunt conectate
între ele prin magistrala internă şi împreună formează ceea ce se numeşte
chipset.
5.5.7 Magistrala PCMCIA
Din dorinţa de a oferi calculatoarelor laptop şi notebook aceeaşi calitate de a
fi extensibile pe care o au sistemele desktop (de birou), Personal Computer
Memory Card International Association (PCMCIA) a stabilit câteva standarde
pentru plăcile de extensie de dimensiuni reduse (credit-card-size) care se
potrivesc in conectorii mici ai calculatoarelor laptop şi notebook.
Standardele PCMCIA, care au fost elaborate de un consorţiu format din
peste 300 de producători (inclusiv IBM, Toshiba şi Apple), au fost considerate a fi
un progres major în domeniul calculatoarelor portabile, deoarece conectorii
PCMCIA pentru laptop şi notebook admit plăci de extensie de memorie, plăci
fax/modem, adaptoare SCSI, plăci de reţea locală (LAN) şi multe alte tipuri de
dispozitive. Ideea de bază a standardului PCMCIA a fost aceea de a da
posibilitatea ca toate dispozitivele periferice PCMCIA existente la producători să
poată fi utilizate de orice notebook.
Oferta de plăci PCMCIA cu 68 pini şi dimensiuni de 2,1 pe 3,4 inci este
enormă. Furnizorii au în vedere nu numai plăci de extensie a memoriei, hard
discuri mici şi modemuri fără fir (care sunt deja disponibile), dar şi conectori pentru
reţea LAN fără fir, plăci PCMCIA de sunet, controlere de CD-ROM, unităţi de
bandă şi o placă gazdă (host) pentru alte periferice. Dispozitivele PCMCIA
existente costă considerabil mai mult decât dispozitivele analoage din sistemele
desktop ISA.
PCMCIA are un singur dezavantaj: standardul a fost doar vag respectat de
producătorii de calculatoare şi dispozitive periferice. Înainte de a achiziţiona un
calculator compatibil PCMCIA, ar trebui să obţineţi de la producător o listă a
dispozitivelor cu care acesta poate funcţiona.
Dorind să rezolve aceste probleme de compatibilitate, PCMCIA a continuat
să stabilească noi standarde. In urma acestei activităţi au rezultat, de fapt, 4
standarde: PCMCIA tip I până la tip IV. Cu toate acestea, există încă probleme de
compatibilitate, mai ales datorită faptului că standardele PCMCIA sunt opţionale;
unii producători nu le aplică integral înainte de a declara un sistem ca fiind
compatibil PCMCIA. Standardele au făcut totuşi ca sistemele de calcul şi
perifericele PCMCIA să fie din ce în ce mai mult compatibile între ele.

Cap.6. UNITATEA DE MEMORIE


Memoria este partea sistemelor de calcul care se utilizează pentru păstrarea
şi regăsirea ulterioară a datelor şi instrucţiunilor. Operaţiile principale în care este
implicată memoria sunt următoarele:
• Preluarea datelor de intrare în memorie;
• Păstrarea datelor pentru a putea fi prelucrate de către UCP;
• Păstrarea datelor de ieşire pentru a putea fi preluate de echipamentele de
ieşire;
• Transmiterea datelor din memorie la ieşire.
Sistemele de memorie influenţează în mod critic performanţele
calculatoarelor. Deoarece în memorie sunt păstrate atât datele cât şi instrucţiunile,
sistemul de memorie trebuie să satisfacă cererile simultane pentru prelucrarea
datelor, execuţia instrucţiunilor şi transferul între memorie şi exterior.
Există o mare varietate de tipuri, tehnologii, organizări, performanţe şi costuri
ale memoriilor utilizate în sistemele de calcul. Nici una din acestea nu este optimă
pentru satisfacerea tuturor cerinţelor. Ca o consecinţă, sistemele de calcul sunt
echipate cu o ierarhie de subsisteme de memorie, unele interne sistemului
(accesibile direct de UCP), iar altele externe (accesibile de către UCP printr-un
modul de I/E).
6.1. Caracteristicile sistemelor de memorie
Cele mai importante caracteristici sunt următoarele:
- Amplasarea. Sistemele de calcul dispun de memorii interne şi externe. Me-
moria internă este considerată de cele mai multe ori ca memorie principală. Există
însă şi alte forme de memorie internă. UCP necesită o memorie locală proprie, sub
forma registrelor. Unitatea de comandă şi control din cadrul UCP poate necesita de
asemenea o memorie proprie, în cazul unităţilor de comandă microprogramate.
Memoria externă constă din dispozitivele periferice, ca discuri sau benzi magnetice,
care sunt accesibile de către UCP prin controlere (module) de I/E.
- Capacitatea. Se exprimă prin dimensiunea cuvântului de memorie (8, 16, 32,
64 sau 128 de biţi) şi numărul de cuvinte (Kocteţi, Mocteţi, Gocteţi).
- Unitatea transferabilă. Pentru memoria internă, unitatea transferabilă este
egală cu numărul liniilor de date către şi de la modulul de memorie, deci cu
numărul de biţi transferaţi simultan. Unitatea transferabilă nu trebuie să fie egală
neapărat cu un cuvânt de memorie. Pentru memoria externă, datele sunt
transferate de multe ori în unităţi mai mari decât un cuvânt, numite blocuri.
- Metoda de acces. Există următoarele tipuri de acces la unităţile de date:
1. Acces secvenţial. Memoria este organizată în unităţi de date, numite
înregistrări. Accesul trebuie realizat într-o secvenţă liniară. Se utilizează informaţii
de adresare memorate pentru separarea înregistrărilor şi pentru a permite
regăsirea informaţiilor. Timpul de acces la o înregistrare oarecare este variabil şi
depinde de poziţia înregistrării în cadrul fişierului. Unităţile de bandă sunt
echipamente cu acces secvenţial.
2. Acces direct. Blocurile sau înregistrările individuale au o adresă unică pe
baza amplasării fizice a acestora. Timpul de acces este de asemenea variabil şi
depinde de poziţia înregistrării accesată anterior. Unităţile de discuri fixe sunt
echipamente cu acces direct.
3. Acces aleator. Fiecare locaţie adresabilă a memoriei are un mecanism de
adresare încorporat. Timpul de acces a fiecărei locaţii este independent de
secvenţele acceselor anterioare şi este constant. Fiecare locaţie poate fi, deci,
selectată aleator şi poate fi adresată şi accesată direct. Memoria principală este
cu acces aleatoriu (RAM).
4. Acces asociativ. Memoria asociativă este un tip de memorie cu acces
aleator, care permite compararea unor biţi dintr-un cuvânt cu o anumită valoare
specificată şi efectuarea acestei comparări în mod simultan pentru toate cuvintele.
Deci, un cuvânt este regăsit pe baza unei părţi a conţinutului acestuia şi nu pe
baza adresei (memorie adresabilă prin conţinut). Fiecare locaţie are propriul
mecanism de adresare, iar timpul de regăsire este constant, independent de
locaţie sau de secvenţele acceselor anterioare.
- Tipul memoriei. Cele mai utilizate tipuri de memorii sunt memoriile
semiconductoare şi memoriile magnetice.
- Metoda de scriere a informaţiilor într-o memorie poate fi reversibilă sau
permanentă. Memoriile la care citirea şi scrierea pot fi efectuate în timpul
funcţionării sunt numite memorii cu citire-scriere. Toate memoriile utilizate
pentru memorare temporară sunt de acest tip. Memoriile semiconductoare cu
citire-scriere sunt numite de obicei memorii cu acces aleator (RAM), ceea ce
reprezintă o folosire improprie a termenului, deoarece există şi alte tipuri de
memorii care sunt cu acces aleator.
Memoriile al căror conţinut nu poate fi modificat sunt numite memorii
numai cu citire (ROM - Read-Only Memory). O memorie ROM este astfel o
memorie care nu se poate şterge. Aceasta este citită utilizând metode de acces
aleator ca cele pentru o memorie RAM. Memoriile ROM sunt utilizate pe scară
largă pentru memorarea programelor de control cum sunt microprogramele. Alte
aplicaţii cuprind programe de sistem sau subrutine de bibliotecă pentru funcţii
utilizate frecvent. Discurile compacte, cum sunt discurile CD-ROM, reprezintă o
clasă de memorie secundară ROM care utilizează un mecanism de citire-scriere
optic.
O memorie semiconductoare ROM este fabricată ca şi orice altă capsulă
de circuit integrat, datele fiind înscrise în timpul procesului de fabricaţie. Aceasta
are dezavantajul că procesul de includere a datelor are un cost fix relativ ridicat,
ceea ce este acceptabil numai la fabricarea un număr mare de circuite de
acelaşi tip. Atunci când este necesar doar un număr redus de memorii ROM cu
un anumit conţinut, o alternativă mai puţin costisitoare este memoria PROM
(Programmable Read-Only Memory). In cazul memoriei PROM, procesul de
scriere este executat prin semnale electrice de către furnizor sau utilizator într-
un moment ulterior fabricaţiei circuitului. Procesul de scriere, numit
"programare", este executat off-line utilizând un echipament special. Memoria
PROM asigură flexibilitate la un cost moderat, dar are dezavantajul că nu poate
fi ştearsă.
O altă variantă a memoriei ROM este memoria EPROM (Erasable
Programmable Read-Only Memory). Aceasta este citită şi înscrisă electric, ca şi
memoria PROM, însă înaintea unei operaţii de scriere toate celulele de
memorare trebuie şterse pentru a avea aceeaşi stare iniţială prin expunerea
capsulei la o radiaţie ultravioletă. Acest proces de ştergere poate fi executat în
mod repetat.
O formă mai atractivă de memorie ROM este memoria EEPROM
(Electrically Erasable Programmable Read-Only Memory). Această memorie
poate fi înscrisă în orice moment fără a-i şterge conţinutul. Operaţia de scriere
trebuie efectuată pe blocuri şi necesită un timp considerabil mai lung decât
operaţia de citire. Memoria EEPROM are avantajul că poate fi actualizată on-
line, utilizând semnale obişnuite de control, adrese şi date. Acest tip de memorie
este potrivită pentru păstrarea programelor de control şi ca un înlocuitor al
memoriei secundare în anumite aplicaţii.
La anumite tehnologii de memorie, informaţiile memorate se pierd după o
perioadă de timp dacă acestea nu sunt refăcute. Pierderea informaţiilor
memorate poate avea loc în următoarele cazuri: citirea distructivă, memorarea
dinamică şi volatilitatea. La anumite memorii metoda de citire distruge
informaţiile memorate; acest fenomen este numit citire distructivă (DRO -
Destructive Readout). Memoriile la care citirea nu afectează informaţiile
memorate sunt caracterizate prin citire nedistructivă (NDRO -Non-Destructive
Readout). La memoriile DRO fiecare operaţie de citire trebuie urmată de o
operaţie de scriere care reface starea originală a memoriei. Această refacere
este efectuată automat utilizând un registru buffer. Operaţia de citire transferă
cuvântul din locaţia adresată într-un registrul buffer. Conţinutul bufferului este
rescris apoi în locaţia originală.
Anumite memorii au proprietatea că informaţia memorată are tendinţa să
se modifice după un anumit timp, datorită unui proces fizic. De exemplu, la
anumite memorii semiconductoare o sarcină electrică dintr-un condensator
reprezintă valoarea binară 1, iar absenţa sarcinii reprezintă valoarea binară 0. In
timp, condensatorul tinde să se descarce, determinând pierderea informaţiei.
Pentru a evita acest lucru sarcina este refăcută printr-un proces numit
reîmprospătare. Memoriile care necesită o reîmprospătare periodică sunt numite
memorii dinamice, spre deosebire de memoriile statice, care nu necesită
reîmprospătare. Majoritatea memoriilor care utilizează tehnici de memorare
magnetică sau optică sunt statice. O memorie dinamică este reîmprospătată în
acelaşi mod în care sunt refăcute informaţiile într-o memorie cu citire distructivă.
Conţinutul fiecărei locaţii este citit periodic în registre buffer, iar apoi este rescris
sub formă amplificată în locaţia originală.
Conţinutul unei memorii poate fi distrus de asemenea prin deconectarea
sau defectarea sursei sale de alimentare. O memorie este volatilă dacă lipsa
tensiunii de alimentare distruge informaţiile memorate. Memoriile RAM
semiconductoare dinamice şi statice sunt volatile, în timp ce memoriile ROM şi
variantele lor sunt nevolatile. Majoritatea memoriilor secundare magnetice şi
optice sunt nevolatile.
6.2. Indicatori de performanţă ai memoriilor
Din punctul de vedere al utilizatorului, cele mai importante caracteristici ale
unei memorii sunt capacitatea şi performanţa. Performanţa unei memorii este
determinată în principal de viteza cu care informaţiile pot fi citite din memorie
sau scrise în memorie. Cei mai importanţi indicatori de performanţă utilizaţi sunt
timpul de acces, durata ciclului, rata de transfer şi fiabilitatea
1. Timpul de acces al unei memorii cu acces aleator, notat cu t A , este
timpul necesar pentru a executa o operaţie de citire sau scriere pentru o
cantitate fixă de informaţie, de exemplu, un cuvânt. Acest timp este calculat din
momentul în care memoria primeşte o cerere de citire sau scriere până în
momentul în care datele sunt disponibile pentru utilizare sau sunt memorate.
Timpul de acces pentru citire nu este întotdeauna egal cu timpul de acces
pentru scriere. Pentru o memorie cu acces non-aleator, timpul de acces este
timpul necesar pentru a poziţiona mecanismul de citire-scriere la locaţia dorită.
2. Durata ciclului, notată cu t M , se referă în primul rând la memoriile cu
acces aleatoriu. Durata ciclului constă din timpul de acces la care se adaugă
timpul suplimentar necesar înainte de a putea începe un al doilea acces.
Anumite memorii cu citire distructivă nu pot iniţia un nou acces înainte de a fi
executată o operaţie de refacere sau reîmprospătare. De aceea, timpul minim
care trebuie să treacă între începerea a două operaţii de acces consecutive
poate fi mai mare decât timpul de acces t A .
3. Rata de transfer, notată cu rM , este cantitatea maximă de informaţii
care pot fi transferate în sau din memorie în unitatea de timp. Această rată este
măsurată în biţi pe secundă sau cuvinte pe secundă. Dacă w este numărul de
biţi care pot fi transferaţi simultan cu memoria, rata de transfer este rM = w / t M
biţi/s. Dacă t M = t A , atunci rM = w / t A .
4. Fiabilitatea este măsurată prin timpul mediu între defecte (MTBF -Mean
Time Between Failures). In general, memoriile fără părţi în mişcare au o
fiabilitate mult mai ridicată decât memoriile care implică o deplasare mecanică,
precum discurile magnetice. Chiar şi la memoriile fără părţi în mişcare, apar
probleme de fiabilitate, în particular atunci când se utilizează densităţi de
memorare sau rate de transfer foarte ridicate. Codurile detectoare de erori şi
codurile corectoare de erori pot creşte fiabilitatea oricărui tip de memorie.
6.3. Ierarhia de memorii
Principalele caracteristici de care trebuie să se ţină cont la realizarea unui
sistem de memorie sunt capacitatea şi performanţele memoriei, în special timpul
de acces. Pe lângă acestea, trebuie să se ia în considerare şi costul memoriei.
Aceste caracteristici sunt contradictorii. De exemplu, există în general următoarele
relaţii între capacitatea, timpul de acces şi costul pe bit al diferitelor tehnologii
utilizate pentru implementarea sistemelor de memorie:
- O capacitate mai mare implică un timp de acces mai mare;
- O capacitate mai mare implică un cost pe bit mai mic;
- Un timp de acces mai mic implică un cost pe bit mai mare.
Pe de o parte, trebuie utilizate tehnologii de memorie care asigură o
capacitate ridicată, pentru că o asemenea capacitate este necesară şi deoarece
costul pe bit al acestor tehnologii este mai redus. Pe de altă parte, pentru a
satisface cerinţele de performanţă, trebuie utilizate memorii cu un timp de acces
redus, care au un cost ridicat şi o capacitate relativ redusă. Aceste cerinţe
contradictorii se pot asigura dacă se utilizează în cadrul unui sistem de calcul mai
multe componente şi tehnologii de memorie, care formează o ierarhie de memorii.
La ierarhizarea memoriei s-a ţinut seama de modul în care operează
programele. Astfel, prin analize statistice ale unor programe tipice s-a constatat
că în orice interval de timp dat referinţele la memorie tind să se restrângă în
zone locale ale memoriei. Această proprietate este cunoscută sub numele de
localitate a referinţelor. Există trei concepte asociate cu localitatea referinţelor:
localitatea spaţială, temporală şi secvenţială. Aceste concepte sunt definite în
continuare.
- Localitatea spaţială. De multe ori, un program utilizează date şi
instrucţiuni ale căror adrese sunt apropiate unele de altele în spaţiul de adrese.
De exemplu, referinţele la elementele unui tablou apar întotdeauna în cadrul
unei anumite zone limitate din spaţiul de adrese. Similar, dacă UCP face referire
la o instrucţiune I de un cuvânt, memorată la o adresă dată A , instrucţiunea
cea mai probabilă de a fi referenţiată în continuare de către UCP este cea
imediat următoare după I , a cărei adresă este A + 1.
- Localitatea temporală. Datele sau instrucţiunile referite recent au o
probabilitate ridicată de a fi referite din nou în viitorul apropiat. De exemplu, un
grup de instrucţiuni dintr-o buclă iterativă sau o subrutină pot fi executate în mod
repetat, rezultând o frecvenţă ridicată a referinţelor la adresele acestora.
- Localitatea secvenţială. Majoritatea instrucţiunilor dintr-un program sunt
executate într-o ordine secvenţială. Instrucţiunile care pot determina execuţia
într-o ordine diferită de cea secvenţială sunt salturile sau apelurile de proceduri.
Acestea reprezintă însă doar între 20% şi 30% din totalul instrucţiunilor. Pentru
acest motiv între 70% şi 80% din instrucţiuni sunt executate în aceeaşi ordine în
care ele sunt păstrate în memorie.
O ierarhie tipică este ilustrată în figura 6.1.
In mod uzual, se poate considera că diferitele unităţi de memorie dintr-un
sistem tipic formează o ierarhie de memorii ( M 1, M 2 ,..., M n ) , după cum se arată
în figura 6.1. Nivelul cel mai înalt, M 1 este reprezentat de unitatea de memorie
cea mai rapidă, cu dimensiunea cea mai redusă şi cu costul cel mai ridicat, fiind
amplasat cel mai aproape de procesor.
Fig.6.1
Următorul nivel, M 2 , este mai lent, are dimensiuni mai mari şi un cost mai
redus decât nivelul M 1 , fiind amplasat mai departe de procesor. Acelaşi lucru
este valabil pentru nivelele M 3 până la M n . In general, pe măsură ce nivelul
creşte, viteza şi deci costul pe bit cresc în mod proporţional, ceea ce tinde să
micşoreze capacitatea memoriei de la acel nivel.
Componentele sistemului de memorie pot fi plasate în patru grupe,
prezentate în continuare.
Registrele UCP. Registrele de viteză ridicată ale UCP sunt utilizate ca
memorie de lucru pentru păstrarea temporară a instrucţiunilor şi datelor. Ele
formează de obicei un set de registre cu scop general pentru păstrarea datelor.
Fiecare registru poate fi accesat pentru citire sau scriere într-un singur ciclu de
ceas.
Memoria principală (primară). Această memorie externă rapidă păstrează
programe şi date care sunt în uz curent. Locaţiile memoriei principale sunt
adresate direct prin instrucţiunile de încărcare şi memorare ale UCP. Cu toate
că se utilizează o tehnologie similară cu cea a setului de registre al UCP,
accesul este mai lent din cauza faptului că memoria principală este separată
fizic de UCP. Capacitatea memoriei principale poate ajunge în prezent la unităţi
sau zeci de Gocteţi, iar timpii de acces tipici sunt de câteva cicluri de ceas.
Memoria secundară. Acest tip de memorie are o capacitate mult mai mare
dar, în acelaşi timp, este mult mai lentă decât memoria principală. Memoria
secundară păstrează programe şi date care nu sunt solicitate în mod constant
de UCP. Este utilizată de asemenea atunci când capacitatea memoriei
principale este depăşită. Informaţia din memoria secundară este accesată
indirect prin programe de intrare/ieşire care transferă informaţii între memoria
principală şi cea secundară. Tehnologiile reprezentative pentru memoria
secundară sunt discurile magnetice fixe şi discurile optice, ambele având
mecanisme de acces electromecanice relativ lente. Capacităţile de memorare
de zeci sau sute de Gocteţi sunt obişnuite, iar timpii de acces se măsoară în
milisecunde.
Memoria cache. Majoritatea calculatoarelor şi procesoarelor au un alt nivel
de memorie (uneori mai multe asemenea nivele) numită memorie cache. Logic
memoriile cache sunt poziţionate între registrele UCP şi memoria principală.
Capacitatea de memorare a memoriei cache este mai mică decât cea a
memoriei principale, dar poate fi accesată mai rapid decât aceasta. Deoarece o
parte a acesteia sau întreaga memorie cache se poate afla în aceeaşi capsulă
cu UCP, timp de acces de unul la trei cicluri de ceas. Memoriile cache sunt
componente esenţiale ale calculatoarelor cu performanţe ridicate.
Spre deosebire de celelalte trei tipuri de memorii, memoriile cache sunt de
obicei transparente programatorului.
Figura 6.2 prezintă unele exemple de ierarhii de memorie cu două, trei şi
patru nivele. Ierarhia cu două nivele din figura 6.2(a) este tipică pentru
calculatoarele din generaţiile anterioare. La ierarhia din figura 6.2(b) este
adăugată o memorie cache numită memorie cache divizată, deoarece aceasta
are zone separate pentru memorarea instrucţiunilor (Cache I) şi a datelor
(Cache D). Al treilea exemplu din figura 6.2(c) are două nivele de memorii
cache, ambele de tip nedivizat.
Fig.6.2
6.4 Memoria principală semiconductoare
Memoria principală semiconductoare este de obicei o memorie cu acces
aleator (RAM). Acest tip de memorie se distinge prin faptul că fiecare locaţie de
memorare poate fi accesată independent, cu un timp de acces fix care este
independent de poziţia locaţiei accesate.
6.4.1. Celula de memorie şi unitatea de memorie
O unitate de memorie este compusă dintr-un anumit număr de celule de
memorie. Deşi, pentru realizarea celulelor de memorie, se utilizează o
diversitate de tehnologii, toate celulele de memorie semiconductoare prezintă
următoarele proprietăţi:
• Au două stări stabile (sau semi-stabile), care pot fi utilizate pentru a
reprezenta valorile binare 0 şi 1.
• Pot fi înscrise (cel puţin o dată) prin setarea stării.
• Pot fi citite prin sesizarea stării.
O schemă bloc a unei celule care memorează un bit de informaţie este
prezentată în figura 6.3. Linia de selecţie realizează selectarea (validarea)
celulei. Linia R/W (Read/Write) stabileşte dacă trebuie efectuată o operaţie de
citire sau de scriere asupra celulei selectate. Atunci când linia R/W este 0, se
efectuează o operaţie de citire, care determină trecerea datei memorate printr-
un amplificator de detecţie (sense amplifier) şi transmiterea acesteia pe linia de
ieşire. Intr-un mod similar, atunci când linia R/W este 1, se efectuează o
operaţie de scriere, care determină ca data de pe linia de intrare să fie
memorată în celulă.
Fig.6.3
O celulă de memorie poate fi construită, în funcţie de tehnologia utilizată,
dintr-un număr de unul până la şase tranzistoare. Restricţia principală la
proiectarea unei celule este dimensiunea sa. Obiectivul este ca dimensiunea
celulei să fie cât mai redusă, astfel încât să poată fi împachetate mai multe
celule în spaţiul disponibil din cadrul unei capsule.
Există două tipuri de memorii cu acces aleator, statice (SRAM) şi dinamice
(DRAM). Atât memoriile statice cât şi cele dinamice sunt volatile, deci informaţia
memorată este pierdută atunci când alimentarea cu energie este întreruptă.
Memoriile statice constau din celule asemănătoare cu bistabilele utilizate în
proiectarea logică. Celulele memoriilor SRAM diferă de bistabile în principal prin
metodele utilizate pentru adresarea celulelor şi transferul datelor. Memoriile
statice reţin datele atunci când un cuvânt este citit din acestea. De aceea aceste
memorii au proprietatea că citirea este nedistructivă.
Intr-o celulă de memorie DRAM, stările 1 şi 0 corespund prezenţei sau
absenţei unei sarcini memorate într-un condensator controlat de un circuit de
comutare, de obicei un tranzistor. Condensatorul unei celule DRAM trebuie
reîncărcat periodic. Operaţia de reîncărcare a condensatoarelor este numită
reîmprospătare. Deci, o memorie DRAM trebuie să conţină un circuit de
reîmprospătare şi să alterneze operaţiile de reîmprospătare cu accesele
normale la memorie. Datele conţinute în memoriile dinamice trebuie să fie
rescrise în locaţia corespunzătoare de memorie după fiecare operaţie de citire.
De aceea, memoriile dinamice sunt caracterizate prin proprietatea că citirea
este distructivă.
Deoarece o celulă de memorie DRAM poate fi construită utilizând un
singur tranzistor, în timp ce o celulă de memorie SRAM necesită până la şase
tranzistoare, la memoriile dinamice se obţine o densitate de memorare mai
ridicată. In consecinţă, o memorie RAM dinamică este mai puţin costisitoare
decât o memorie RAM statică corespunzătoare. Pe de altă parte, o memorie
RAM dinamică necesită un circuit de reîmprospătare. Pentru memorii de
dimensiuni mari, costul circuitului de reîmprospătare este compensat de costul
mai redus al memoriilor DRAM. Un alt aspect este că memoriile RAM statice
sunt mai rapide decât memoriile RAM dinamice.
O unitate de memorie este o matrice de celule de memorie. Structura
internă a unei unităţi de memorie de m cuvinte cu n biţi pe cuvânt constă din
m ∗ n celule de memorie. Intr-o unitate de memorie, fiecare celulă poate fi
adresată individual sau un grup de celule pot fi adresate simultan. De obicei, un
sistem de calcul are o dimensiune fixă a cuvântului. Dacă un cuvânt are n biţi,
atunci trebuie adresate simultan n celule de memorie, ceea ce permite ca
celulele să aibă o linie de selecţie comună. O unitate de memorie având patru
cuvinte de 2 biţi este ilustrată în figura 6.4.
Oricare cuvânt poate fi selectat cu ajutorul liniilor de adresă A1 şi A0 .
Operaţia care trebuie executată asupra cuvântului selectat este determinată de
linia R / W . De exemplu, dacă liniile de adresă A1 şi A0 sunt setate la 1, şi
respectiv 0, este selectat cuvântul 2. Dacă linia R / W este setată la 1, atunci
datele de pe liniile de intrare X 1 şi X 0 sunt memorate în celulele C2,1 , respectiv
C2,0 . Similar, dacă linia R / W este setată la 0, datele din celulele C2,1 şi C2,0
sunt transmise pe liniile de ieşire Z1 , respectiv Z 0 .
Fig.6.4
6.4.2. Organizarea memoriilor
Fiecare circuit integrat de memorie conţine o matrice de celule de
memorie. Se utilizează mai multe organizări ale celulelor de memorie şi a logicii
funcţionale dintr-o capsulă de memorie semiconductoare. Vom prezenta în
continuare două metode de organizare: 1D şi 2D.
In figura 6.5 este prezentată o memorie cu organizare 1D. Matricea de
memorie este compusă dintr-un număr mare de locaţii adresabile, fiecare din
acestea memorând un cuvânt de w biţi. Cuvântul este cea mai mică unitate
adresabilă. Această memorie funcţionează după cum urmează. Mai întâi,
adresa locaţiei care trebuie accesată este transferată prin magistrala de adrese,
care are m linii, în bufferul de adrese al memoriei. Adresa este apoi decodificată
de către decodificatorul de adresă DCD, care selectează locaţia cerută din
matricea de memorie. O linie de control indică tipul accesului care trebuie
executat. Dacă este cerută o operaţie de citire, conţinutul locaţiei adresate este
transferat de la matricea de memorie în bufferul de date şi de aici pe magistrala
de date. Dacă este cerută o operaţie de scriere cuvântul, care trebuie memorat,
este transferat de pe magistrala de date în locaţia selectată din unitatea de
memorie. Deoarece, de obicei, nu este necesar sau de dorit să se permită
citirea şi scrierea simultană, magistralele de date (de intrare şi de ieşire) sunt
combinate adesea într-o singură magistrală bidirecţională de date.
Figura 6.5
Pe fiecare linie conectată la matricea de memorie, există de obicei un
driver cu rol de amplificator de semnal. In figura 6.5 putem observa mai multe
seturi de drivere pentru liniile de date şi de adrese. Driverele, decodificatoarele
şi circuitele de control formează circuitele de acces ale memoriei şi acestea pot
avea un impact semnificativ asupra dimensiunii şi costului memoriei.
Fig.6.6
Cea mai obişnuită organizare de memorie este organizarea bidimensională (2D)
sau linie-coloană prezentată în figura 6.6, unde, pentru simplitate, circuitele de
date şi de control sunt omise. Cuvântul de adresă de m biţi este divizat în două
părţi, X şi Y , constând din m x , respectiv m y biţi. Celulele sunt aranjate într-o
matrice rectangulară de N x , linii şi N y coloane, astfel că numărul total de
celule este N x N y . Organizarea 2D necesită un număr mult mai redus de circuite
de acces decât organizarea 1D pentru aceeaşi capacitate de memorare. De
asemenea, în locul unui singur decodificator de adresă foarte complex, sunt
suficiente, în cazul organizării 2D, două decodificatoare de adresă mult mai
simple. In plus, organizarea 2D favorizează structurile bidimensionale permise
de tehnologia VLSI.
Un circuit integrat de memorie RAM conţine în mod tipic toate circuitele de
acces, incluzând decodificatoare de adresă, drivere şi circuite de control.
6.7. Memoria virtuală
6.7.1. Principii
Memoria virtuală permite sistemului de calcul utilizarea unei memorii cu o
dimensiune mult mai mare decât dimensiunea reală fizică a memoriei principale.
Intr-un sistem de memorie virtuală, memoria principală şi cea secundară se
prezintă pentru un program al utilizatorului ca o memorie unică, de dimensiuni
mari şi adresabilă direct.
Inaintea apariţiei memoriei virtuale, dacă spaţiul de adrese al unui program
depăşea dimensiunea memoriei principale disponibile, programatorul era
responsabil pentru împărţirea programului în fragmente mai mici, astfel încât
fiecare fragment să poată fi încărcat în memoria principală. Toate aceste
fragmente erau păstrate în memoria secundară, de exemplu, pe disc, fiind
încărcate în memoria principală pe măsură ce erau necesare. Acest proces
necesita cunoaşterea locului în care fragmentele trebuiau stocate pe disc,
cunoaşterea operaţiilor de intrare/ieşire necesare pentru accesul fragmentelor şi
păstrarea evidenţei întregului proces de fragmentare. Acesta reprezenta un
proces foarte complex, ceea ce complica şi mai mult programarea unui
calculator.
Conceptul memoriei virtuale a fost creat în principal pentru a elibera
programatorul de această sarcină. Memoria virtuală permite utilizatorului să
scrie programe care depăşesc limitele fizice ale memoriei principale. De
asemenea, memoria virtuală permite multiprogramarea, prin care memoria
principală este partajată între mai mulţi utilizatori într-un mod dinamic. In cazul
multiprogramării, porţiuni ale mai multor programe sunt plasate în memoria
principală în acelaşi timp, iar procesorul îşi împarte timpul de execuţie între
aceste programe. Procesorul execută un program pentru o perioadă scurtă de
timp (numită o cuantă sau diviziune de timp), iar apoi comută la un alt program;
acest proces continuă până când fiecare program este terminat.
Atunci când se utilizează memoria virtuală, sistemul de memorie este
adresat printr-un set V de adrese logice sau virtuale, fiind numite astfel
deoarece, la execuţia programului, ele sunt translatate, în adrese ale memoriei
fizice. La o altă execuţie a programului adresele fizice pot fi altele.
Un set de adrese fizice sau reale R identifică locaţiile de memorare fizică
din fiecare unitate de memorie. Adresele virtuale sunt generate de obicei în
timpul compilării şi sunt translatate de procesor în adrese fizice în timpul
execuţiei. Un mecanism eficient pentru implementarea translatării adreselor, de
forma f : V → R , este esenţial pentru un sistem de memorie virtuală. Cele două
metode principale pentru implementarea unei memorii virtuale sunt paginarea şi
segmentarea.
6.7.2. Translatarea adreselor
Setul de locaţii abstracte pe care le poate adresa un program reprezintă
spaţiul de adrese virtuale V al programului. Adresele virtuale pot fi specificate
explicit sau implicit de identificatorii pe care programatorul îi asignează
variabilelor şi etichetelor de instrucţiuni. Pentru execuţia unui program pe un
anumit calculator, adresele sale virtuale trebuie translatate în spaţiul de adrese
reale R , definit de memoria care este prezentă fizic în calculator. Acest proces
este numit translatare a adreselor sau mapare a adreselor. Spaţiul de adrese
reale R este o secvenţă liniară de numere 0, 1, 2, ...., n − 1, corespunzând
locaţiilor adresabile de memorie şi este distribuit pe toate nivele ierarhiei de
memorii. Spaţiul de adrese virtuale V este o colecţie de liste, tablouri
multidimensionale şi alte structuri neliniare, astfel încât este mult mai complex
decât R .
Asignarea şi translatarea adreselor poate fi efectuată în diferitele etape ale
unui program şi anume:
• De către programator în timpul scrierii programului;
• De către compilator în timpul compilării programului;
• De către programul încărcător la încărcarea programului;
• De către sistemul hardware şi/sau software de gestiune a memoriei.
Specificarea explicită a adreselor reale de către programator a fost
necesară la primele calculatoare, care nu aveau un sistem hardware sau
software de gestiune a memoriei. In cazul calculatoarelor moderne,
programatorii utilizează în mod normal doar adrese virtuale. Un sistem hardware
sau software specializat determină în mod automat adresele reale cerute de
execuţia programului.
Translatarea adreselor se numeşte statică dacă compilatorul transformă
identificatorii simbolici ai unui program în adrese fizice, sau translatarea
adreselor este efectuată atunci când programul este încărcat pentru prima dată
pentru execuţie.
Translatarea adreselor este dinamică dacă spaţiul adreselor virtuale este
modificat în timpul execuţiei programului şi în consecinţă convertirea acestora în
adrese fizice este, de asemenea, efectuată în timpul execuţiei. Pentru
translatarea adreselor în timpul execuţiei se utilizează unităţi de gestiune a
memoriei (MMU - Memory Management Unit) implementate prin hardware.
Un program executabil cuprinde un set de blocuri de instrucţiuni şi de
date, fiecare din acestea fiind o secvenţă de cuvinte sau octeţi care trebuie
memoraţi în locaţii consecutive de memorie în timpul execuţiei. Considerând că
se utilizează adrese de cuvinte, un cuvânt C dintr-un bloc are propria adresă
reală Ar , utilizată de UCP pentru accesul la acest cuvânt. Adresa virtuală a
cuvântului C este specificată prin adresa de bază B a blocului care conţine
cuvântul, împreună cu adresa relativă sau deplasamentul D (numit şi offset) al
cuvântului din cadrul blocului, după cum se arată în figura 6.18. Adresa efectivă,
reală este:
Ar = B + D
Adesea B furnizează biţii de ordin superior ai adresei efective, în timp ce
D furnizează biţii de ordin inferior. In acest caz, adresa reală este formată
simplu prin concatenarea adresei de bază B şi a deplasamentului D, un proces
care nu creşte în mod semnificativ timpul pentru generarea adresei.
Adresa reala Ar
B
B+1
.
.
B+i
B+m-1
Fig. 6.18
Un mod simplu de implementare a translatării adreselor este de a păstra
adresele de bază ale blocurilor într-o tabelă de adrese ale memoriei controlată
de sistemul de gestiune a memoriei. Tabela poate fi păstrată în memorie, în
registrele UCP, sau în ambele. Logica de generare a adreselor utilizată de UCP
constă în calcularea adresei reale Ar prin combinarea deplasamentului D cu
adresa de bază corespunzătoare Bi .
Blocurile pot fi relocate cu uşurinţă în memorie prin manipularea adreselor
de bază ale acestora. Figura 6.19 ilustrează relocarea blocurilor utilizând
modificarea adreselor de bază. Presupunem că două blocuri sunt alocate în
memoria principală după cum se arată în figura 6.19(a). Se doreşte încărcarea
unui al treilea bloc K 3 în memoria principală, dar nu este disponibil un spaţiu
liber contiguu cu o dimensiune suficientă. O soluţie la această problemă este de
a se muta blocul K 2 , după cum se arată în figura 6.19(b), prin asignarea
acestuia a unei noi adrese de bază B2 şi reîncărcarea blocului în memorie.
Astfel, se crează un spaţiu în care poate fi încărcat blocul K 3 , prin asignarea
acestuia a unei adrese de bază corespunzătoare.
Fig. 6.19
In cazul alocării dinamice a adreselor, unitatea de gestiune a memoriei
trebuie să evite depăşirea limitelor unui bloc în special la scriere. O metodă
obişnuită pentru realizarea acestui deziderat este specificarea adresei maxime
Li , numită adresă limită, pe care o poate accesa blocul. O altă posibilitate este
de a se specifica dimensiunea blocului. Adresa de bază Bi şi adresa limită Li ,
sunt memorate în tabela de adrese ale memoriei. Fiecare adresă reală Ar
generată de bloc este comparată cu Bi şi Li ; accesul la memorie este efectuat
dacă şi numai dacă este satisfăcută următoarea condiţie:
Bi ≤ Ar ≤ Li
Figura 6.20 indică modul în care unitatea de gestiune a memoriei
efectuează translatarea adreselor. Adresa de intrare Av este o adresă virtuală
constând dintr-o adresă de bază virtuală Bv, concatenată cu un deplasament
D . Adresa de bază reală Br = f ( Bv ) asignată adresei virtuale Bv este
memorată într-o tabelă de adrese a memoriei principale. Această tabelă poate
avea dimensiuni mari. Pentru creşterea vitezei procesului de translatare, o parte
a tabelei de adrese ale memoriei este plasată într-o memorie de viteză ridicată
din UCP, numită buffer de translatare (TLB - Translation Look-aside Buffer).
Intrarea în TLB este deci partea adresei de bază Bv a adresei virtuale Av , iar
ieşirea acestuia este adresa de bază reală corespunzătoare Br . Această adresă
este apoi concatenată cu partea de deplasament D din Av pentru a obţine
adresa reală completă Ar .
Fig. 6.20
Dacă adresa virtuală Bv nu este găsită în bufferul de translatare TLB,
atunci partea tabelei de adrese ale memoriei principale, care conţine Bv este
transferată mai întâi din memoria externă în TLB. Deci, bufferul de translatare
are rolul unei memorii cache pentru translatarea adreselor. Din acest motiv,
bufferul de translatare este numit uneori memorie cache de adrese.
6.7.3. Paginarea
Paginarea este tehnica de divizare a unui program (numit în continuare
proces) în blocuri mai mici cu dimensiuni identice şi stocarea acestor blocuri în
memoria secundară sub forma unor pagini. Prin utilizarea avantajului localităţii
referinţelor, aceste pagini pot fi încărcate apoi în memoria principală în blocuri,
de aceeaşi dimensiune cu paginile, numite cadre de pagină.
Adresa de baza
reala a paginii
Fig. 6.21
Pentru ca această metodă să funcţioneze corect, fiecare proces trebuie să
păstreze, în memoria principală, o tabelă de adrese ale memoriei, numită tabelă
de pagini. Fiecărei adrese virtuale de pagină îi corespunde o adresă reală a
unui cadru de pagină. Figura 6.21 ilustrează modul în care funcţionează metoda
paginării.
O adresă virtuală constă din două părţi: o adresă de bază şi un
deplasament. Fiecare proces are un registru de bază, care conţine adresa de
început a tabelei de pagini a procesului. Tabelele de pagini au câte o fişă (entry)
pentru fiecare pagină pe care o conţine procesul. Aceste fişe conţin de obicei un
câmp de prezenţă de un bit, un câmp de acces şi un câmp de adresă. Câmpul
de prezenţă P specifică dacă pagina a fost încărcată în memoria principală.
Câmpul de acces specifică tipul operaţiilor care pot fi executate asupra paginii.
Acest câmp determină dacă pagina poate fi doar citită (R/O - Read Only), citită
şi scrisă (R/W - ReadAVrite), sau doar executată. Câmpul de adresă specifică
numărul cadrului în care aste încărcată pagina. Adresa de început a paginii în
memoria principală este determinată înmulţind numărul cadrului cu dimensiunea
cadrului. Atunci când se întâlneşte un acces la o variabilă sau o instrucţiune
care nu este încărcată în memorie, apare o lipsă de pagină (page fault), iar
pagina care conţine variabila sau instrucţiunea necesară este încărcată în
memorie. Pagina este depusă într-un cadru liber, dacă un asemenea cadru
există. Dacă nu există un cadru liber, trebuie selectată una din paginile
procesului, iar noua pagină va fi memorată în locul acesteia. Criteriul pentru
selectarea paginii care se va înlocui constituie strategia de înlocuire sau
algoritmul de înlocuire.
Fig. 6.22
Ca un exemplu, figura 6.22 prezintă conţinutul tabelelor de pagini pentru
două procese, Proces 1 şi Proces 2. Procesul 1 conţine trei pagini, P0 , P1 şi P2 ,
iar procesul 2 are două pagini, P0 şi P1 . Presupunem că toate paginile
procesului 1 au acces numai pentru citire, iar paginile procesului 2 au acces
pentru citire şi scriere. Deoarece fiecare cadru are o dimensiune de 4 KB,
adresa fizică de început a fiecărui cadru se calculează prin produsul dintre
numărul cadrului şi 4096. Astfel, dat fiind faptul că paginile P0 şi P2 ale
procesului 1 sunt încărcate în cadrele 1 şi 3, adresele de început ale acestora în
memoria principală vor fi 1 * 4096=4096 (4K), respectiv 3 * 4096=12288 (12K).
Procesul de conversie a adreselor virtuale în adrese fizice poate fi efectuat
mai rapid prin utilizarea unui buffer de translatare TLB (Translation Look-aside
Buffer) care va memora o parte dintre fişele conţinute de tabela de pagini a
procesului respectiv.
Pentru micşorarea timpului de răspuns al TLB acesta poate fi implementat
printr-o memorie asociativă. Pentru o anumită adresă de pagină, se caută o fisă
(entry) a bufferului de translatare pentru care există o potrivire cu acest număr
de pagină; această fişă (entry) este utilizată pentru a furniza numărul
corespunzător al cadrului. Dacă nu se găseşte o potrivire în bufferul de
translatare, se va localiza tabela de pagini a procesului corespunzător în
memoria principală, care se va utiliza pentru a furniza numărul cadrului.
Eficienţa unui sistem de memorie virtuală depinde de minimizarea
numărului lipsurilor de pagină. Deoarece timpul de acces al memoriei secundare
este mult mai ridicat decât timpul de acces al memoriei principale, un număr
excesiv al lipsurilor de pagină poate încetini sistemul în mod semnificativ. Atunci
când apare o lipsă de pagină, trebuie identificată o pagină în memoria principală
care nu este necesară în momentul respectiv, astfel încât aceasta poate fi
transferată în memoria secundară. Apoi, pagina cerută poate fi încărcată în
acest cadru eliberat din memoria principală.
Paginarea creşte în mod substanţial timpul de prelucrare necesar unui
proces, deoarece vor fi necesare două accese la disc, pe lângă execuţia unui
algoritm de înlocuire. Există însă o alternativă care, în unele cazuri, poate
reduce numărul accesurilor la disc la unul singur. Această reducere este
obţinută prin adăugarea unui bit suplimentar la fiecare pagină (bit de modificare
sau bit de inconsistenţă). Dacă o anumită pagină a fost modificată, bitul
corespunzător de modificare este setat la 1. Dacă bitul de modificare al unei
pagini este 1 şi această pagină a fost selectată pentru a fi eliminată din
memorie, atunci vor fi necesare două accesuri la disc. Dacă bitul de modificare
este 0 (aceasta însemnând că nu au fost modificări ale acestei pagini din
momentul în care a fost încărcată ultima dată), nu este necesară scrierea paginii
pe disc. Deoarece starea originală a acestei pagini se află pe disc şi nu s-au
efectuat modificări ale paginii, acesta poate fi înlocuită de noua pagină solicitată.
6.7.4. Segmentarea
O altă metodă de implementare a memoriei virtuale este numită
segmentare. In acest caz, un program este împărţit în secţiuni de lungime
variabilă numite segmente. Un segment poate corespunde unei entităţi logice
cum ar fi un set de date sau o funcţie în cadrul unui program. Fiecare proces
păstrează o tabelă de segmente în memoria principală, tabelă care conţine în
principiu aceleaşi informaţii ca şi tabela de pagini, însă, spre deosebire de
pagini, segmentele au lungimi diferite şi ele pot începe în orice zonă din
memorie. Pentru acest motiv, eliminarea unui segment din memoria principală
nu asigură întotdeauna spaţiu suficient pentru un alt segment.
Un segment este un set de cuvinte contigue, asociate logic. Un cuvânt
dintr-un segment este referit specificând o adresă de bază, numită adresă de
segment şi un deplasament în cadrul segmentului. Un program şi datele sale
pot fi considerate ca o colecţie de segmente înlănţuite. Legăturile provin din
faptul că un segment de program utilizează, sau apelează, alte segmente.
Avantajul principal al segmentării constă în faptul că limitele segmentelor
corespund limitelor programului şi ale datelor. In consecinţă, informaţiile care
sunt partajate între diferiţi utilizatori sunt organizate adesea în segmente. Din
cauza independenţei logice între segmente, un segment de program poate fi
modificat şi recompilat în orice moment fără a afecta alte segmente. Anumite
proprietăţi ale programelor, ca domeniul de definiţie al unei variabile sau
drepturile de acces, pot fi specificate în mod natural de către segmente. Aceste
proprietăţi necesită ca accesurile la segmente să fie verificate pentru a preveni
utilizarea lor neautorizată.
Dezavantajul segmentării constă în utilizarea ineficientă a memoriei
principale. La sistemele care utilizează segmentarea, blocurile de dimensiuni
diferite tind să prolifereze în memoria principală, lăsând între ele spaţii
neutilizabile. Acestea pot fi eliminate prin procesul de compactare a memoriei.
Existenţa unui spaţiu inutilizabil între zonele ocupate este numită fragmentare
externă. In cazul paginării, deoarece cadrele de pagină sunt contigue,
fragmentarea externă nu apare.
Comparând paginarea şi segmentarea, paginarea necesită un sistem mai
simplu de alocare a memoriei decât segmentarea, deoarece paginile au aceeaşi
dimensiune. Pe de altă parte, paginile nu au semnificaţie logică, deoarece ele
nu reprezintă elemente de program.
Administrarea memoriei virtuale poate fi simplificată prin combinarea
segmentării cu paginarea. Utilizând această soluţie se obţine şi o mai bună
utilizare a memoriei principale. Totuşi, dacă un bloc de k cuvinte este împărţit în
p pagini de câte n cuvinte, iar k nu este un multiplu de n, ultimul cadru de
pagină căruia îi este asignat blocul nu va fi ocupat complet. Existenţa unui
spaţiu inutilizabil în interiorul unui cadru de pagină ocupat parţial este numită
fragmentare internă.
6.7.5. Paginarea şi segmentarea
Paginarea şi segmentarea pot fi combinate pentru a obţine avantajele
ambelor soluţii. In acest caz, fiecare segment este împărţit în pagini. Avantajul
principal al divizării unui segment în pagini este că se elimină necesitatea de a
plasa segmentul într-o zonă contiguă din memoria principală. In loc de aceasta,
este nevoie doar de un număr de cadre de pagină egal cu numărul paginilor în
care s-a împărţit segmentul. Deoarece aceste cadre de pagină nu trebuie să fie
contigue, este mai uşor de plasat un segment de dimensiuni mari în memoria
principală.
Atunci când paginarea este combinată cu segmentarea, o adresă virtuală
are trei componente: un index de segment SI , un index de pagină PI şi un
deplasament (offset) D . Tabela de adrese ale memoriei constă atunci din una
sau mai multe tabele de segmente şi tabele de pagini. Pentru translatarea
rapidă a adreselor, se pot utiliza două buffere de translatare TLB, unul pentru
tabelele de segmente şi unul pentru tabelele de pagini (figura 6.23).
Fiecare adresă virtuală Av generată de un program este translatată printr-
un proces în două etape. Mai întâi, se utilizează indexul de segment SI pentru a
citi tabela curentă de segmente cu scopul de a obţine adresa de bază PB a
tabelei de pagini necesare.
Fig. 6.23
Această adresă de bază este combinată cu indexul de pagină PI (care
este un deplasament în cadrul tabelei de pagini) pentru a genera o adresă de
pagină, care este utilizată apoi pentru accesul la o tabelă de pagini. Rezultatul
este o adresă reală de pagină, deci, un număr al cadrului de pagină, care poate
fi combinat cu partea de deplasament D a adresei virtuale Av pentru a obţine
adresa reală finală Ar .
6.7.6. Alocarea memoriei
Diferitele niveluri ierarhice ale unui sistem de memorie sunt împărţite în
seturi de pagini sau segmente, care păstrează blocuri de date. Blocurile sunt
transferate în mod automat între aceste niveluri în scopul minimizării timpului de
acces al ierarhiei de memorie. Plasarea blocurilor de informaţii într-un sistem de
memorie se numeşte alocarea memoriei. Metoda de selectare a părţii memoriei
principale M 1 în care trebuie plasat un nou bloc K constituie strategia de
înlocuire. Strategiile simple de înlocuire plasează blocul K în memoria M 1
numai atunci când este disponibilă o regiune neocupată cu o dimensiune
suficientă (alocare non-preemptivă). Alte strategii realizează realocarea
blocurilor existente în memorie pentru a face loc blocului K (alocare
preemptivă). In general, metodele de alocare ale memoriei care sunt eficiente
au ca efect o rată ridicată de succes şi un timp mediu de acces scăzut. O
alocare eficientă a memoriei minimizează de asemenea spaţiul neocupat din
memoria M 1 .
Atunci când un bloc este transferat din memoria M 2 în M 1 , sistemul de
gestiune a memoriei crează o intrare corespunzătoare în lista spaţiilor ocupate.
Atunci când un bloc nu mai este necesar în memoria M 1 , acesta este eliberat
(dealocat) şi regiunea pe care o ocupă este transferată din lista spaţiilor ocupate
în lista spaţiilor disponibile. Un bloc este dealocat atunci când un program care îl
utilizează îşi termină execuţia sau când blocul este înlocuit de către un alt bloc.
6.7.6.1. Alocarea non-preemptivă
Presupunem că un bloc K i , de ni cuvinte trebuie transferat din memoria
M 2 în M 1 . Dacă nici unul din blocurile care ocupă deja memoria M 1 nu poate fi
acaparat (înlocuit) de către blocul K i , atunci este necesar să se găsească sau
să se creeze o regiune disponibilă de ni , sau mai multe cuvinte care permite
plasarea blocului K i . Acest proces este cunoscut ca alocare non-preemptivă a
memoriei.
Alocarea non-preemptivă poate fi implementată mai simplu într-un sistem
cu paginare, unde toate blocurile (paginile) au o dimensiune fixe şi memoria M 1
este divizată în regiuni (cadre de pagină) de aceeaşi dimensiune. Harta
memoriei (tabela de pagini) este parcursă pentru a găsi un cadru de pagină
disponibil; dacă se găseşte unul, acesta este asignat blocului K i . Această
metodă simplă de alocare este motivul principal al utilizării pe scară largă a
paginării. Dacă spaţiul de memorie este divizat în regiuni de lungime variabilă,
devine însă mai dificil să se aloce în mod eficient noi blocuri.
Doi algoritmi utilizaţi pe scară largă pentru alocarea non-preemptivă a
blocurilor de dimensiune variabilă (segmente care nu sunt paginate, de
exemplu) sunt primul potrivit, cel mai potrivit si cel mai nepotrivit.
Primul potrivit. Această metodă plasează blocul dat în prima regiune liberă
cu dimensiunea potrivită. Se parcurge harta memoriei în mod secvenţial până
când se găseşte o regiune disponibilă R j de ni sau mai multe cuvinte, unde n ,
este dimensiunea blocului K i care trebuie plasat, iar apoi se alocă blocul K i
regiunii R j .
Principalul avantaj al acestei metode este că favorizează formarea unor
zone libere la adresele mari de memorie prin plasarea blocurilor la adresele
joase de memorie ori de câte ori este posibil. Totuşi, această metodă produce
zone libere care pot fi prea mici pentru a păstra un bloc. Această problemă este
cunoscută sub numele de fragmentare. Atunci când apare fragmentarea, până
la urmă trebuie rulat un anumit algoritm de compactare pentru a colecta toate
zonele libere de dimensiuni mici într-o zonă cu dimensiunea mai mare. Aceasta
poate reduce performanţele.
Cel mai potrivit. Această metodă alocă regiunea disponibilă cu
dimensiunea cea mai mică care este suficient de mare pentru a păstra blocul
dat. Se parcurge harta memoriei şi se asignează blocul K i unei regiuni de
n j ≥ ni , cuvinte astfel încât n j − ni , să fie minimizat. Pentru a nu fi necesară
căutarea în întreaga hartă a memoriei, lista spaţiului disponibil este sortată în
ordinea crescătoare a dimensiunii regiunilor. Ca şi strategia primului potrivit, şi
strategia celui mai potrivit produce fragmentarea memoriei. Această strategie
poate crea un număr mare de blocuri mici care sunt inutile în majoritatea
cazurilor.
Comparând algoritmii primului potrivit şi celui mai potrivit, algoritmul
primului potrivit are avantajul timpului de execuţie mai redus. Eficienţa relativă a
celor doi algoritmi a fost un subiect de controverse, deoarece ambii au fost
implementaţi cu rezultate satisfăcătoare. Performanţele obţinute într-un mediu
particular depinde de distribuţia dimensiunii blocurilor care trebuie alocate.
Studiile de simulare sugerează că, în practică, algoritmul primului potrivit tinde
să aibă performanţe mai bune decât algoritmul celui mai potrivit.
Cel mai nepotrivit. Această metodă alocă regiunea disponibilă cu
dimensiunea cea mai mare pentru blocul dat. Se caută în harta memoriei
regiunea cea mai mare. Lista spaţiului disponibil este sortată în ordinea
descrescătoare a dimensiunii regiunilor. Această metodă, ca şi celelalte două
metode, produce fragmentarea memoriei. Totuşi, spre deosebire de primele
două metode, metoda celui mai nepotrivit reduce numărul regiunilor mici,
alocând întotdeauna regiunea cea mai mare pentru blocul dat.
6.7.6.2. Alocarea preemptivă
Alocarea non-preemptivă nu poate utiliza eficient memoria în toate
situaţiile. Este posibil să apară refuzarea unei cereri de alocare a memoriei
datorită spaţiului insuficient atunci când memoria M 1 este doar parţial ocupată.
Este posibilă utilizarea mult mai eficientă a spaţiului de memorie disponibil dacă
spaţiul ocupat poate fi realocat pentru a face loc noilor blocuri. Realocarea
poate fi efectuată utilizând două abordări:
- Blocurile aflate deja în memoria M 1 pot fi realocate în cadrul M 1 pentru a
crea un spaţiu suficient de mare pentru noul bloc.
- Una sau mai multe regiuni pot deveni disponibile prin dealocarea blocurilor
pe care le conţin. Această metodă necesită o strategie de înlocuire pentru
selectarea blocurilor care trebuie dealocate şi înlocuite.
Dealocarea necesită stabilirea unei distincţii între blocurile care au fost
modificate de la încărcarea lor în memoria M 1 şi blocurile care nu au fost
modificate. Blocurile de instrucţiuni rămân nemodificate, în timp ce blocurile de
date pot fi modificate. Pentru înlocuirea unui bloc care nu a fost modificat,
sistemul de gestiune a memoriei poate înlocui în mod simplu blocul dealocat cu
noul bloc şi poate actualiza intrarea acestuia în harta memoriei. Inainte ca un
bloc modificat să fie înlocuit, acesta trebuie copiat în memoria M 2 .
6.7.6.3. Strategii de înlocuire
A doua abordare pentru alocarea preemptivă implică acapararea unei
regiuni R ocupate de blocul K şi alocarea acesteia unui nou bloc K ' . Criteriul
pentru selecţia blocului K ca şi bloc care va fi înlocuit constituie strategia de
înlocuire. Principalul scop în alegerea unei strategii de înlocuire este de a
maximiza rata de succes a memoriei mai rapide M 1 .
Majoritatea strategiilor de înlocuire iau în considerare principiul localităţii
atunci când selectează un bloc pentru înlocuire. Principiul localităţii afirmă că pe
o perioadă dată de timp adresele generate se vor încadra într-o porţiune redusă
a spaţiului adreselor virtuale şi aceste adrese generate se vor modifica lent în
timp.
Rata de succes tinde la un maxim dacă intervalele de timp dintre două
lipsuri succesive de memorie sunt maximizate. Doi algoritmi practici de înlocuire
sunt FIFO (First-In, First-Out) şi LRU (Least Recently Used).
FIFO este una din cele mai simple strategii de înlocuire. Blocul selectat
pentru înlocuire este blocul cel mai puţin recent încărcat în memoria M 1 .
Avantajul strategiei FIFO este faptul că este foarte simplu de implementat.
Fiecărui bloc i se asociază un contor în lista spaţiilor ocupate; contoarele
asociate cu blocurile indică secvenţa lor de încărcare. De fiecare dată când un
bloc este transferat în memoria M 1 , contoarele indicând secvenţa de încărcare
sunt actualizate. Prin inspectarea acestor contoare, unitatea de gestiune a
memoriei poate determina cu uşurinţă primul bloc care a fost încărcat.
Dezavantajul strategiei FIFO este că poate mări în mod semnificativ timpul
necesar pentru execuţia unui proces, deoarece nu ia în considerare principiul
localităţii referinţelor şi în consecinţă, poate înlocui cu aceeaşi probabilitate
blocuri utilizate intens şi blocuri utilizate rar. De exemplu, dacă un bloc încărcat
în memorie de mai mult timp conţine o variabilă globală care este utilizată în
mod constant, acest bloc va fi unul din primele care va fi înlocuit. La următorul
acces la variabila globală, va apare o nouă lipsă a blocului, iar blocul va trebui
reîncărcat, înlocuind un alt bloc.
Strategia LRU (Least Recently Used) selectează pentru înlocuire blocul
care nu a fost utilizat de cel mai mult timp. Această strategie se bazează pe
presupunerea rezonabilă că blocul cel mai puţin recent utilizat este cel mai puţin
probabil de a fi utilizat în viitor. Strategia LRU evită înlocuirea blocurilor
încărcate de mai mult timp, dar frecvent utilizate, ca în cazul strategiei FIFO.
Totuşi, strategia LRU este mai dificil de implementat decât FIFO, deoarece sistemul de gestiune a memoriei trebuie să
păstreze informaţii despre
momentele referinţelor la toate blocurile din memoria M 1 . Strategia LRU poate fi
implementată prin asocierea unui contor hardware sau software cu fiecare bloc
din M 1 . De fiecare dată când un bloc este referit, contorul acestuia este setat la
o valoare pozitivă predeterminată. La intervale fixe de timp, contoarele tuturor
blocurilor sunt decrementate. In orice moment, blocul cel mai puţin recent utilizat
este cel al cărui contor conţine valoarea cea mai mică.

6.7. Memoria virtuală


6.7.1. Principii
Memoria virtuală permite sistemului de calcul utilizarea unei memorii cu o
dimensiune mult mai mare decât dimensiunea reală fizică a memoriei principale.
Intr-un sistem de memorie virtuală, memoria principală şi cea secundară se
prezintă pentru un program al utilizatorului ca o memorie unică, de dimensiuni
mari şi adresabilă direct.
Inaintea apariţiei memoriei virtuale, dacă spaţiul de adrese al unui program
depăşea dimensiunea memoriei principale disponibile, programatorul era
responsabil pentru împărţirea programului în fragmente mai mici, astfel încât
fiecare fragment să poată fi încărcat în memoria principală. Toate aceste
fragmente erau păstrate în memoria secundară, de exemplu, pe disc, fiind
încărcate în memoria principală pe măsură ce erau necesare. Acest proces
necesita cunoaşterea locului în care fragmentele trebuiau stocate pe disc,
cunoaşterea operaţiilor de intrare/ieşire necesare pentru accesul fragmentelor şi
păstrarea evidenţei întregului proces de fragmentare. Acesta reprezenta un
proces foarte complex, ceea ce complica şi mai mult programarea unui
calculator.
Conceptul memoriei virtuale a fost creat în principal pentru a elibera
programatorul de această sarcină. Memoria virtuală permite utilizatorului să
scrie programe care depăşesc limitele fizice ale memoriei principale. De
asemenea, memoria virtuală permite multiprogramarea, prin care memoria
principală este partajată între mai mulţi utilizatori într-un mod dinamic. In cazul
multiprogramării, porţiuni ale mai multor programe sunt plasate în memoria
principală în acelaşi timp, iar procesorul îşi împarte timpul de execuţie între
aceste programe. Procesorul execută un program pentru o perioadă scurtă de
timp (numită o cuantă sau diviziune de timp), iar apoi comută la un alt program;
acest proces continuă până când fiecare program este terminat.
Atunci când se utilizează memoria virtuală, sistemul de memorie este
adresat printr-un set V de adrese logice sau virtuale, fiind numite astfel
deoarece, la execuţia programului, ele sunt translatate, în adrese ale memoriei
fizice. La o altă execuţie a programului adresele fizice pot fi altele.
Un set de adrese fizice sau reale R identifică locaţiile de memorare fizică
din fiecare unitate de memorie. Adresele virtuale sunt generate de obicei în
timpul compilării şi sunt translatate de procesor în adrese fizice în timpul
execuţiei. Un mecanism eficient pentru implementarea translatării adreselor, de
forma f : V → R , este esenţial pentru un sistem de memorie virtuală. Cele două
metode principale pentru implementarea unei memorii virtuale sunt paginarea şi
segmentarea.
6.7.2. Translatarea adreselor
Setul de locaţii abstracte pe care le poate adresa un program reprezintă
spaţiul de adrese virtuale V al programului. Adresele virtuale pot fi specificate
explicit sau implicit de identificatorii pe care programatorul îi asignează
variabilelor şi etichetelor de instrucţiuni. Pentru execuţia unui program pe un
anumit calculator, adresele sale virtuale trebuie translatate în spaţiul de adrese
reale R , definit de memoria care este prezentă fizic în calculator. Acest proces
este numit translatare a adreselor sau mapare a adreselor. Spaţiul de adrese
reale R este o secvenţă liniară de numere 0, 1, 2, ...., n − 1, corespunzând
locaţiilor adresabile de memorie şi este distribuit pe toate nivele ierarhiei de
memorii. Spaţiul de adrese virtuale V este o colecţie de liste, tablouri
multidimensionale şi alte structuri neliniare, astfel încât este mult mai complex
decât R .
Asignarea şi translatarea adreselor poate fi efectuată în diferitele etape ale
unui program şi anume:
• De către programator în timpul scrierii programului;
• De către compilator în timpul compilării programului;
• De către programul încărcător la încărcarea programului;
• De către sistemul hardware şi/sau software de gestiune a memoriei.
Specificarea explicită a adreselor reale de către programator a fost
necesară la primele calculatoare, care nu aveau un sistem hardware sau
software de gestiune a memoriei. In cazul calculatoarelor moderne,
programatorii utilizează în mod normal doar adrese virtuale. Un sistem hardware
sau software specializat determină în mod automat adresele reale cerute de
execuţia programului.
Translatarea adreselor se numeşte statică dacă compilatorul transformă
identificatorii simbolici ai unui program în adrese fizice, sau translatarea
adreselor este efectuată atunci când programul este încărcat pentru prima dată
pentru execuţie.
Translatarea adreselor este dinamică dacă spaţiul adreselor virtuale este
modificat în timpul execuţiei programului şi în consecinţă convertirea acestora în
adrese fizice este, de asemenea, efectuată în timpul execuţiei. Pentru
translatarea adreselor în timpul execuţiei se utilizează unităţi de gestiune a
memoriei (MMU - Memory Management Unit) implementate prin hardware.
Un program executabil cuprinde un set de blocuri de instrucţiuni şi de
date, fiecare din acestea fiind o secvenţă de cuvinte sau octeţi care trebuie
memoraţi în locaţii consecutive de memorie în timpul execuţiei. Considerând că
se utilizează adrese de cuvinte, un cuvânt C dintr-un bloc are propria adresă
reală Ar , utilizată de UCP pentru accesul la acest cuvânt. Adresa virtuală a
cuvântului C este specificată prin adresa de bază B a blocului care conţine
cuvântul, împreună cu adresa relativă sau deplasamentul D (numit şi offset) al
cuvântului din cadrul blocului, după cum se arată în figura 6.18. Adresa efectivă,
reală este:
Ar = B + D
Adesea B furnizează biţii de ordin superior ai adresei efective, în timp ce
D furnizează biţii de ordin inferior. In acest caz, adresa reală este formată
simplu prin concatenarea adresei de bază B şi a deplasamentului D, un proces
care nu creşte în mod semnificativ timpul pentru generarea adresei.
Adresa reala Ar
B
B+1
.
.
B+i
B+m-1
Fig. 6.18
Un mod simplu de implementare a translatării adreselor este de a păstra
adresele de bază ale blocurilor într-o tabelă de adrese ale memoriei controlată
de sistemul de gestiune a memoriei. Tabela poate fi păstrată în memorie, în
registrele UCP, sau în ambele. Logica de generare a adreselor utilizată de UCP
constă în calcularea adresei reale Ar prin combinarea deplasamentului D cu
adresa de bază corespunzătoare Bi .
Blocurile pot fi relocate cu uşurinţă în memorie prin manipularea adreselor
de bază ale acestora. Figura 6.19 ilustrează relocarea blocurilor utilizând
modificarea adreselor de bază. Presupunem că două blocuri sunt alocate în
memoria principală după cum se arată în figura 6.19(a). Se doreşte încărcarea
unui al treilea bloc K 3 în memoria principală, dar nu este disponibil un spaţiu
liber contiguu cu o dimensiune suficientă. O soluţie la această problemă este de
a se muta blocul K 2 , după cum se arată în figura 6.19(b), prin asignarea
acestuia a unei noi adrese de bază B2 şi reîncărcarea blocului în memorie.
Astfel, se crează un spaţiu în care poate fi încărcat blocul K 3 , prin asignarea
acestuia a unei adrese de bază corespunzătoare.
Fig. 6.19
In cazul alocării dinamice a adreselor, unitatea de gestiune a memoriei
trebuie să evite depăşirea limitelor unui bloc în special la scriere. O metodă
obişnuită pentru realizarea acestui deziderat este specificarea adresei maxime
Li , numită adresă limită, pe care o poate accesa blocul. O altă posibilitate este
de a se specifica dimensiunea blocului. Adresa de bază Bi şi adresa limită Li ,
sunt memorate în tabela de adrese ale memoriei. Fiecare adresă reală Ar
generată de bloc este comparată cu Bi şi Li ; accesul la memorie este efectuat
dacă şi numai dacă este satisfăcută următoarea condiţie:
Bi ≤ Ar ≤ Li
Figura 6.20 indică modul în care unitatea de gestiune a memoriei
efectuează translatarea adreselor. Adresa de intrare Av este o adresă virtuală
constând dintr-o adresă de bază virtuală Bv, concatenată cu un deplasament
D . Adresa de bază reală Br = f ( Bv ) asignată adresei virtuale Bv este
memorată într-o tabelă de adrese a memoriei principale. Această tabelă poate
avea dimensiuni mari. Pentru creşterea vitezei procesului de translatare, o parte
a tabelei de adrese ale memoriei este plasată într-o memorie de viteză ridicată
din UCP, numită buffer de translatare (TLB - Translation Look-aside Buffer).
Intrarea în TLB este deci partea adresei de bază Bv a adresei virtuale Av , iar
ieşirea acestuia este adresa de bază reală corespunzătoare Br . Această adresă
este apoi concatenată cu partea de deplasament D din Av pentru a obţine
adresa reală completă Ar .
Fig. 6.20
Dacă adresa virtuală Bv nu este găsită în bufferul de translatare TLB,
atunci partea tabelei de adrese ale memoriei principale, care conţine Bv este
transferată mai întâi din memoria externă în TLB. Deci, bufferul de translatare
are rolul unei memorii cache pentru translatarea adreselor. Din acest motiv,
bufferul de translatare este numit uneori memorie cache de adrese.
6.7.3. Paginarea
Paginarea este tehnica de divizare a unui program (numit în continuare
proces) în blocuri mai mici cu dimensiuni identice şi stocarea acestor blocuri în
memoria secundară sub forma unor pagini. Prin utilizarea avantajului localităţii
referinţelor, aceste pagini pot fi încărcate apoi în memoria principală în blocuri,
de aceeaşi dimensiune cu paginile, numite cadre de pagină.
Adresa de baza
reala a paginii
Fig. 6.21
Pentru ca această metodă să funcţioneze corect, fiecare proces trebuie să
păstreze, în memoria principală, o tabelă de adrese ale memoriei, numită tabelă
de pagini. Fiecărei adrese virtuale de pagină îi corespunde o adresă reală a
unui cadru de pagină. Figura 6.21 ilustrează modul în care funcţionează metoda
paginării.
O adresă virtuală constă din două părţi: o adresă de bază şi un
deplasament. Fiecare proces are un registru de bază, care conţine adresa de
început a tabelei de pagini a procesului. Tabelele de pagini au câte o fişă (entry)
pentru fiecare pagină pe care o conţine procesul. Aceste fişe conţin de obicei un
câmp de prezenţă de un bit, un câmp de acces şi un câmp de adresă. Câmpul
de prezenţă P specifică dacă pagina a fost încărcată în memoria principală.
Câmpul de acces specifică tipul operaţiilor care pot fi executate asupra paginii.
Acest câmp determină dacă pagina poate fi doar citită (R/O - Read Only), citită
şi scrisă (R/W - ReadAVrite), sau doar executată. Câmpul de adresă specifică
numărul cadrului în care aste încărcată pagina. Adresa de început a paginii în
memoria principală este determinată înmulţind numărul cadrului cu dimensiunea
cadrului. Atunci când se întâlneşte un acces la o variabilă sau o instrucţiune
care nu este încărcată în memorie, apare o lipsă de pagină (page fault), iar
pagina care conţine variabila sau instrucţiunea necesară este încărcată în
memorie. Pagina este depusă într-un cadru liber, dacă un asemenea cadru
există. Dacă nu există un cadru liber, trebuie selectată una din paginile
procesului, iar noua pagină va fi memorată în locul acesteia. Criteriul pentru
selectarea paginii care se va înlocui constituie strategia de înlocuire sau
algoritmul de înlocuire.
Fig. 6.22
Ca un exemplu, figura 6.22 prezintă conţinutul tabelelor de pagini pentru
două procese, Proces 1 şi Proces 2. Procesul 1 conţine trei pagini, P0 , P1 şi P2 ,
iar procesul 2 are două pagini, P0 şi P1 . Presupunem că toate paginile
procesului 1 au acces numai pentru citire, iar paginile procesului 2 au acces
pentru citire şi scriere. Deoarece fiecare cadru are o dimensiune de 4 KB,
adresa fizică de început a fiecărui cadru se calculează prin produsul dintre
numărul cadrului şi 4096. Astfel, dat fiind faptul că paginile P0 şi P2 ale
procesului 1 sunt încărcate în cadrele 1 şi 3, adresele de început ale acestora în
memoria principală vor fi 1 * 4096=4096 (4K), respectiv 3 * 4096=12288 (12K).
Procesul de conversie a adreselor virtuale în adrese fizice poate fi efectuat
mai rapid prin utilizarea unui buffer de translatare TLB (Translation Look-aside
Buffer) care va memora o parte dintre fişele conţinute de tabela de pagini a
procesului respectiv.
Pentru micşorarea timpului de răspuns al TLB acesta poate fi implementat
printr-o memorie asociativă. Pentru o anumită adresă de pagină, se caută o fisă
(entry) a bufferului de translatare pentru care există o potrivire cu acest număr
de pagină; această fişă (entry) este utilizată pentru a furniza numărul
corespunzător al cadrului. Dacă nu se găseşte o potrivire în bufferul de
translatare, se va localiza tabela de pagini a procesului corespunzător în
memoria principală, care se va utiliza pentru a furniza numărul cadrului.
Eficienţa unui sistem de memorie virtuală depinde de minimizarea
numărului lipsurilor de pagină. Deoarece timpul de acces al memoriei secundare
este mult mai ridicat decât timpul de acces al memoriei principale, un număr
excesiv al lipsurilor de pagină poate încetini sistemul în mod semnificativ. Atunci
când apare o lipsă de pagină, trebuie identificată o pagină în memoria principală
care nu este necesară în momentul respectiv, astfel încât aceasta poate fi
transferată în memoria secundară. Apoi, pagina cerută poate fi încărcată în
acest cadru eliberat din memoria principală.
Paginarea creşte în mod substanţial timpul de prelucrare necesar unui
proces, deoarece vor fi necesare două accese la disc, pe lângă execuţia unui
algoritm de înlocuire. Există însă o alternativă care, în unele cazuri, poate
reduce numărul accesurilor la disc la unul singur. Această reducere este
obţinută prin adăugarea unui bit suplimentar la fiecare pagină (bit de modificare
sau bit de inconsistenţă). Dacă o anumită pagină a fost modificată, bitul
corespunzător de modificare este setat la 1. Dacă bitul de modificare al unei
pagini este 1 şi această pagină a fost selectată pentru a fi eliminată din
memorie, atunci vor fi necesare două accesuri la disc. Dacă bitul de modificare
este 0 (aceasta însemnând că nu au fost modificări ale acestei pagini din
momentul în care a fost încărcată ultima dată), nu este necesară scrierea paginii
pe disc. Deoarece starea originală a acestei pagini se află pe disc şi nu s-au
efectuat modificări ale paginii, acesta poate fi înlocuită de noua pagină solicitată.
6.7.4. Segmentarea
O altă metodă de implementare a memoriei virtuale este numită
segmentare. In acest caz, un program este împărţit în secţiuni de lungime
variabilă numite segmente. Un segment poate corespunde unei entităţi logice
cum ar fi un set de date sau o funcţie în cadrul unui program. Fiecare proces
păstrează o tabelă de segmente în memoria principală, tabelă care conţine în
principiu aceleaşi informaţii ca şi tabela de pagini, însă, spre deosebire de
pagini, segmentele au lungimi diferite şi ele pot începe în orice zonă din
memorie. Pentru acest motiv, eliminarea unui segment din memoria principală
nu asigură întotdeauna spaţiu suficient pentru un alt segment.
Un segment este un set de cuvinte contigue, asociate logic. Un cuvânt
dintr-un segment este referit specificând o adresă de bază, numită adresă de
segment şi un deplasament în cadrul segmentului. Un program şi datele sale
pot fi considerate ca o colecţie de segmente înlănţuite. Legăturile provin din
faptul că un segment de program utilizează, sau apelează, alte segmente.
Avantajul principal al segmentării constă în faptul că limitele segmentelor
corespund limitelor programului şi ale datelor. In consecinţă, informaţiile care
sunt partajate între diferiţi utilizatori sunt organizate adesea în segmente. Din
cauza independenţei logice între segmente, un segment de program poate fi
modificat şi recompilat în orice moment fără a afecta alte segmente. Anumite
proprietăţi ale programelor, ca domeniul de definiţie al unei variabile sau
drepturile de acces, pot fi specificate în mod natural de către segmente. Aceste
proprietăţi necesită ca accesurile la segmente să fie verificate pentru a preveni
utilizarea lor neautorizată.
Dezavantajul segmentării constă în utilizarea ineficientă a memoriei
principale. La sistemele care utilizează segmentarea, blocurile de dimensiuni
diferite tind să prolifereze în memoria principală, lăsând între ele spaţii
neutilizabile. Acestea pot fi eliminate prin procesul de compactare a memoriei.
Existenţa unui spaţiu inutilizabil între zonele ocupate este numită fragmentare
externă. In cazul paginării, deoarece cadrele de pagină sunt contigue,
fragmentarea externă nu apare.
Comparând paginarea şi segmentarea, paginarea necesită un sistem mai
simplu de alocare a memoriei decât segmentarea, deoarece paginile au aceeaşi
dimensiune. Pe de altă parte, paginile nu au semnificaţie logică, deoarece ele
nu reprezintă elemente de program.
Administrarea memoriei virtuale poate fi simplificată prin combinarea
segmentării cu paginarea. Utilizând această soluţie se obţine şi o mai bună
utilizare a memoriei principale. Totuşi, dacă un bloc de k cuvinte este împărţit în
p pagini de câte n cuvinte, iar k nu este un multiplu de n, ultimul cadru de
pagină căruia îi este asignat blocul nu va fi ocupat complet. Existenţa unui
spaţiu inutilizabil în interiorul unui cadru de pagină ocupat parţial este numită
fragmentare internă.
6.7.5. Paginarea şi segmentarea
Paginarea şi segmentarea pot fi combinate pentru a obţine avantajele
ambelor soluţii. In acest caz, fiecare segment este împărţit în pagini. Avantajul
principal al divizării unui segment în pagini este că se elimină necesitatea de a
plasa segmentul într-o zonă contiguă din memoria principală. In loc de aceasta,
este nevoie doar de un număr de cadre de pagină egal cu numărul paginilor în
care s-a împărţit segmentul. Deoarece aceste cadre de pagină nu trebuie să fie
contigue, este mai uşor de plasat un segment de dimensiuni mari în memoria
principală.
Atunci când paginarea este combinată cu segmentarea, o adresă virtuală
are trei componente: un index de segment SI , un index de pagină PI şi un
deplasament (offset) D . Tabela de adrese ale memoriei constă atunci din una
sau mai multe tabele de segmente şi tabele de pagini. Pentru translatarea
rapidă a adreselor, se pot utiliza două buffere de translatare TLB, unul pentru
tabelele de segmente şi unul pentru tabelele de pagini (figura 6.23).
Fiecare adresă virtuală Av generată de un program este translatată printr-
un proces în două etape. Mai întâi, se utilizează indexul de segment SI pentru a
citi tabela curentă de segmente cu scopul de a obţine adresa de bază PB a
tabelei de pagini necesare.
Fig. 6.23
Această adresă de bază este combinată cu indexul de pagină PI (care
este un deplasament în cadrul tabelei de pagini) pentru a genera o adresă de
pagină, care este utilizată apoi pentru accesul la o tabelă de pagini. Rezultatul
este o adresă reală de pagină, deci, un număr al cadrului de pagină, care poate
fi combinat cu partea de deplasament D a adresei virtuale Av pentru a obţine
adresa reală finală Ar .
6.7.6. Alocarea memoriei
Diferitele niveluri ierarhice ale unui sistem de memorie sunt împărţite în
seturi de pagini sau segmente, care păstrează blocuri de date. Blocurile sunt
transferate în mod automat între aceste niveluri în scopul minimizării timpului de
acces al ierarhiei de memorie. Plasarea blocurilor de informaţii într-un sistem de
memorie se numeşte alocarea memoriei. Metoda de selectare a părţii memoriei
principale M 1 în care trebuie plasat un nou bloc K constituie strategia de
înlocuire. Strategiile simple de înlocuire plasează blocul K în memoria M 1
numai atunci când este disponibilă o regiune neocupată cu o dimensiune
suficientă (alocare non-preemptivă). Alte strategii realizează realocarea
blocurilor existente în memorie pentru a face loc blocului K (alocare
preemptivă). In general, metodele de alocare ale memoriei care sunt eficiente
au ca efect o rată ridicată de succes şi un timp mediu de acces scăzut. O
alocare eficientă a memoriei minimizează de asemenea spaţiul neocupat din
memoria M 1 .
Atunci când un bloc este transferat din memoria M 2 în M 1 , sistemul de
gestiune a memoriei crează o intrare corespunzătoare în lista spaţiilor ocupate.
Atunci când un bloc nu mai este necesar în memoria M 1 , acesta este eliberat
(dealocat) şi regiunea pe care o ocupă este transferată din lista spaţiilor ocupate
în lista spaţiilor disponibile. Un bloc este dealocat atunci când un program care îl
utilizează îşi termină execuţia sau când blocul este înlocuit de către un alt bloc.
6.7.6.1. Alocarea non-preemptivă
Presupunem că un bloc K i , de ni cuvinte trebuie transferat din memoria
M 2 în M 1 . Dacă nici unul din blocurile care ocupă deja memoria M 1 nu poate fi
acaparat (înlocuit) de către blocul K i , atunci este necesar să se găsească sau
să se creeze o regiune disponibilă de ni , sau mai multe cuvinte care permite
plasarea blocului K i . Acest proces este cunoscut ca alocare non-preemptivă a
memoriei.
Alocarea non-preemptivă poate fi implementată mai simplu într-un sistem
cu paginare, unde toate blocurile (paginile) au o dimensiune fixe şi memoria M 1
este divizată în regiuni (cadre de pagină) de aceeaşi dimensiune. Harta
memoriei (tabela de pagini) este parcursă pentru a găsi un cadru de pagină
disponibil; dacă se găseşte unul, acesta este asignat blocului K i . Această
metodă simplă de alocare este motivul principal al utilizării pe scară largă a
paginării. Dacă spaţiul de memorie este divizat în regiuni de lungime variabilă,
devine însă mai dificil să se aloce în mod eficient noi blocuri.
Doi algoritmi utilizaţi pe scară largă pentru alocarea non-preemptivă a
blocurilor de dimensiune variabilă (segmente care nu sunt paginate, de
exemplu) sunt primul potrivit, cel mai potrivit si cel mai nepotrivit.
Primul potrivit. Această metodă plasează blocul dat în prima regiune liberă
cu dimensiunea potrivită. Se parcurge harta memoriei în mod secvenţial până
când se găseşte o regiune disponibilă R j de ni sau mai multe cuvinte, unde n ,
este dimensiunea blocului K i care trebuie plasat, iar apoi se alocă blocul K i
regiunii R j .
Principalul avantaj al acestei metode este că favorizează formarea unor
zone libere la adresele mari de memorie prin plasarea blocurilor la adresele
joase de memorie ori de câte ori este posibil. Totuşi, această metodă produce
zone libere care pot fi prea mici pentru a păstra un bloc. Această problemă este
cunoscută sub numele de fragmentare. Atunci când apare fragmentarea, până
la urmă trebuie rulat un anumit algoritm de compactare pentru a colecta toate
zonele libere de dimensiuni mici într-o zonă cu dimensiunea mai mare. Aceasta
poate reduce performanţele.
Cel mai potrivit. Această metodă alocă regiunea disponibilă cu
dimensiunea cea mai mică care este suficient de mare pentru a păstra blocul
dat. Se parcurge harta memoriei şi se asignează blocul K i unei regiuni de
n j ≥ ni , cuvinte astfel încât n j − ni , să fie minimizat. Pentru a nu fi necesară
căutarea în întreaga hartă a memoriei, lista spaţiului disponibil este sortată în
ordinea crescătoare a dimensiunii regiunilor. Ca şi strategia primului potrivit, şi
strategia celui mai potrivit produce fragmentarea memoriei. Această strategie
poate crea un număr mare de blocuri mici care sunt inutile în majoritatea
cazurilor.
Comparând algoritmii primului potrivit şi celui mai potrivit, algoritmul
primului potrivit are avantajul timpului de execuţie mai redus. Eficienţa relativă a
celor doi algoritmi a fost un subiect de controverse, deoarece ambii au fost
implementaţi cu rezultate satisfăcătoare. Performanţele obţinute într-un mediu
particular depinde de distribuţia dimensiunii blocurilor care trebuie alocate.
Studiile de simulare sugerează că, în practică, algoritmul primului potrivit tinde
să aibă performanţe mai bune decât algoritmul celui mai potrivit.
Cel mai nepotrivit. Această metodă alocă regiunea disponibilă cu
dimensiunea cea mai mare pentru blocul dat. Se caută în harta memoriei
regiunea cea mai mare. Lista spaţiului disponibil este sortată în ordinea
descrescătoare a dimensiunii regiunilor. Această metodă, ca şi celelalte două
metode, produce fragmentarea memoriei. Totuşi, spre deosebire de primele
două metode, metoda celui mai nepotrivit reduce numărul regiunilor mici,
alocând întotdeauna regiunea cea mai mare pentru blocul dat.
6.7.6.2. Alocarea preemptivă
Alocarea non-preemptivă nu poate utiliza eficient memoria în toate
situaţiile. Este posibil să apară refuzarea unei cereri de alocare a memoriei
datorită spaţiului insuficient atunci când memoria M 1 este doar parţial ocupată.
Este posibilă utilizarea mult mai eficientă a spaţiului de memorie disponibil dacă
spaţiul ocupat poate fi realocat pentru a face loc noilor blocuri. Realocarea
poate fi efectuată utilizând două abordări:
- Blocurile aflate deja în memoria M 1 pot fi realocate în cadrul M 1 pentru a
crea un spaţiu suficient de mare pentru noul bloc.
- Una sau mai multe regiuni pot deveni disponibile prin dealocarea blocurilor
pe care le conţin. Această metodă necesită o strategie de înlocuire pentru
selectarea blocurilor care trebuie dealocate şi înlocuite.
Dealocarea necesită stabilirea unei distincţii între blocurile care au fost
modificate de la încărcarea lor în memoria M 1 şi blocurile care nu au fost
modificate. Blocurile de instrucţiuni rămân nemodificate, în timp ce blocurile de
date pot fi modificate. Pentru înlocuirea unui bloc care nu a fost modificat,
sistemul de gestiune a memoriei poate înlocui în mod simplu blocul dealocat cu
noul bloc şi poate actualiza intrarea acestuia în harta memoriei. Inainte ca un
bloc modificat să fie înlocuit, acesta trebuie copiat în memoria M 2 .
6.7.6.3. Strategii de înlocuire
A doua abordare pentru alocarea preemptivă implică acapararea unei
regiuni R ocupate de blocul K şi alocarea acesteia unui nou bloc K ' . Criteriul
pentru selecţia blocului K ca şi bloc care va fi înlocuit constituie strategia de
înlocuire. Principalul scop în alegerea unei strategii de înlocuire este de a
maximiza rata de succes a memoriei mai rapide M 1 .
Majoritatea strategiilor de înlocuire iau în considerare principiul localităţii
atunci când selectează un bloc pentru înlocuire. Principiul localităţii afirmă că pe
o perioadă dată de timp adresele generate se vor încadra într-o porţiune redusă
a spaţiului adreselor virtuale şi aceste adrese generate se vor modifica lent în
timp.
Rata de succes tinde la un maxim dacă intervalele de timp dintre două
lipsuri succesive de memorie sunt maximizate. Doi algoritmi practici de înlocuire
sunt FIFO (First-In, First-Out) şi LRU (Least Recently Used).
FIFO este una din cele mai simple strategii de înlocuire. Blocul selectat
pentru înlocuire este blocul cel mai puţin recent încărcat în memoria M 1 .
Avantajul strategiei FIFO este faptul că este foarte simplu de implementat.
Fiecărui bloc i se asociază un contor în lista spaţiilor ocupate; contoarele
asociate cu blocurile indică secvenţa lor de încărcare. De fiecare dată când un
bloc este transferat în memoria M 1 , contoarele indicând secvenţa de încărcare
sunt actualizate. Prin inspectarea acestor contoare, unitatea de gestiune a
memoriei poate determina cu uşurinţă primul bloc care a fost încărcat.
Dezavantajul strategiei FIFO este că poate mări în mod semnificativ timpul
necesar pentru execuţia unui proces, deoarece nu ia în considerare principiul
localităţii referinţelor şi în consecinţă, poate înlocui cu aceeaşi probabilitate
blocuri utilizate intens şi blocuri utilizate rar. De exemplu, dacă un bloc încărcat
în memorie de mai mult timp conţine o variabilă globală care este utilizată în
mod constant, acest bloc va fi unul din primele care va fi înlocuit. La următorul
acces la variabila globală, va apare o nouă lipsă a blocului, iar blocul va trebui
reîncărcat, înlocuind un alt bloc.
Strategia LRU (Least Recently Used) selectează pentru înlocuire blocul
care nu a fost utilizat de cel mai mult timp. Această strategie se bazează pe
presupunerea rezonabilă că blocul cel mai puţin recent utilizat este cel mai puţin
probabil de a fi utilizat în viitor. Strategia LRU evită înlocuirea blocurilor
încărcate de mai mult timp, dar frecvent utilizate, ca în cazul strategiei FIFO.
Totuşi, strategia LRU este mai dificil de implementat decât FIFO, deoarece
sistemul de gestiune a memoriei trebuie să păstreze informaţii despre
momentele referinţelor la toate blocurile din memoria M 1 . Strategia LRU poate fi
implementată prin asocierea unui contor hardware sau software cu fiecare bloc
din M 1 . De fiecare dată când un bloc este referit, contorul acestuia este setat la
o valoare pozitivă predeterminată. La intervale fixe de timp, contoarele tuturor
blocurilor sunt decrementate. In orice moment, blocul cel mai puţin recent utilizat
este cel al cărui contor conţine valoarea cea mai mică.

Cap. 7. SISTEME PIPELINE


Tehnica pipeline reprezintă o metodă de îmbunătăţire a performanţelor
unui procesor sau a unei unităţi aritmetice. Această metodă permite execuţia
simultană a mai multor instrucţiuni sau operaţii. Tehnica pipeline este
transparentă pentru programator; ea utilizează paralelismul prin suprapunerea
fazelor de execuţie ale instrucţiunilor sau a etapelor de execuţie ale unei operaţii
aritmetice. Un sistem pipeline poate fi comparat cu o linie de asamblare a unui
produs, în care există posturi de lucru specializate pentru o anumită operaţie, iar
la capătul benzii este obţinut produsul final.
7.1. Structura unui sistem pipeline
Tehnica pipeline descompune un proces secvenţial în mai multe
subprocese, care sunt executate de unităţi sau etaje diferite. Un etaj execută un
subproces şi produce un rezultat intermediar, care reprezintă o intrare pentru
etajul următor. Rezultatul final este obţinut numai după ce toate subprocesele
au trecut prin întregul sistem pipeline. Figura 7.1 ilustrează structura de bază a
unui sistem pipeline cu m etaje.
Unitate de Control
Date de
Date de
ieşire
intrare
R2
R1 C2 Rm Cm
C1
m
Etaj E1 Etaj E2 Etaj Em
Fig. 7.1
Un etaj Ei constă dintr-un registru de intrare sau latch Ri şi un circuit de
prelucrare Ci , care poate fi secvenţial, combinaţional sau inteligent. Registrele
păstrează rezultatele parţiale pe măsură ce acestea se deplasează prin sistemul
pipeline. Un semnal comun de ceas determină ca registrele să îşi schimbe
starea în mod sincron. In fiecare ciclu de ceas, fiecare etaj transferă rezultatele
sale parţiale la următorul etaj şi calculează un nou set de rezultate. Perioada
semnalului de ceas trebuie să fie suficient de mare pentru ca etajul cel mai lent
să termine execuţia operaţiei sale. In plus, trebuie să existe un timp suficient
pentru ca un registru să memoreze datele sale de intrare. Deci, perioada
ceasului trebuie să fie mai mare decât întârzierea maximă a etajului cel mai lent,
plus timpul necesar pentru memorarea datelor într-un registru.
Avantajul acestei tehnici constă în faptul că un sistem pipeline cu m etaje
poate procesa simultan până la m seturi independente de subprocese. Aceste
subprocese se deplasează prin sistemul pipeline etaj cu etaj, astfel încât atunci
când sistemul pipeline este plin, sunt executate în mod concurent m operaţii
separate, fiecare într-un etaj diferit. Mai mult, un nou rezultat final este generat
la ieşirea sistemului pipeline în fiecare ciclu de ceas.
7.2. Indicatori de performanţă ai sistemelor pipeline
Prin suprapunerea fazelor de execuţie ale unui proces secvenţial pentru
diferite taskuri de intrare (instrucţiuni sau operaţii), se obţine un timp teoretic de
execuţie egal cu:
T pipe = m ∗ P + (n − 1) ∗ P (7.1)
unde m este numărul de etaje, n este numărul taskurilor de intrare, iar P este
perioada ceasului. Termenul m ∗ P , numit întârziere sau latenţă a sistemului
pipeline, este timpul necesar pentru ca primul task de intrare să parcurgă toate
etajele, iar termenul (n − 1) ∗ P este timpul necesar pentru următoarele taskuri.
După întârzierea necesară parcurgerii tuturor etajelor, se va genera o ieşire în
fiecare ciclu de ceas. Ieşirile vor fi generate la intervale de timp care depind de
întârzierea introdusă de etajul cel mai lent. Chiar şi cu această limitare, prin
tehnica pipeline se pot îmbunătăţi performanţele în mod semnificativ faţă de
execuţia obişnuită, în care este necesară terminarea unui task înainte de
începerea execuţiei unui alt task. Atunci când n are o valoare mare, un sistem
pipeline poate genera ieşirile de aproximativ m ori mai rapid faţă de un sistem
care nu utilizează această tehnică.
Pe de altă parte, fără suprapunerea fazelor de execuţie procesul
secvenţial anterior necesită un timp de execuţie egal cu:
m
Tsec = n ∗ ∑ τi (7.2)
i =1
unde τ i , este întârzierea introdusă de etajul i . Perioada ceasului P trebuie să
îndeplinească următoarea condiţie
P ≥ τi + t i
unde t i este timpul necesar pentru memorarea rezultatului în registrul i.
In cazul ideal în care toate etajele au întârzieri egale, τi = τ pentru
i = 1,..., m , Tsec poate fi scris ca:
Tsec = n ∗ m ∗ τ (7.3)
Dacă se ignoră timpul necesar memorării într-un registru ( ti = 0 ), atunci
P=τ
şi se obţine:
Tsec = n ∗ m ∗ P (7.4)
Creşterea vitezei de calcul ( S ) poate fi definită ca:
n∗m∗P n∗m
T
S = sec = = (7.5)
T pipe m ∗ P + (n − 1) ∗ P m + (n − 1)
Valoarea S se apropie de m atunci când n → ∞ . Deci, creşterea maximă a
vitezei unui sistem pipeline cu m etaje faţă de un sistem care nu utilizează
tehnica pipeline este aproximativ m . Cu alte cuvinte, atunci când n (numărul
taskurilor de intrare) este foarte mare, un sistem pipeline poate genera ieşirile
de aproximativ m ori mai rapid faţă de un sistem obişnuit.
Pe lângă creşterea de viteză, se utilizează adesea alţi doi factori pentru
determinarea performanţelor unui sistem pipeline; acestea sunt eficienţa şi rata
de transfer.
Eficienţa E a unui sistem pipeline cu m etaje, care reprezintă creşterea
vitezei pe etaj, este definită ca:
n∗m 1
S n
E= = ∗= (7.6)
m (m + n − 1) m m + n − 1
Eficienţa E , se apropie de valoarea sa maximă 1 atunci când n → ∞ .
Atunci când n = 1 , E va avea valoarea 1 , care este valoarea minimă care se
m
poate obţine.
Rata de transfer R a unui sistem pipeline este definită ca numărul
taskurilor de intrare pe care le poate prelucra în unitatea de timp. Pentru un
sistem pipeline cu m etaje, rata de transfer R este definită ca:
n n
R= =
T pipe m ∗ P + (n − 1) ∗ P
Împărţind atât numărătorul cât şi numitorul cu P se obţine
1E
n S
R= ∗== (7.7)
m + n −1 P P m ∗ P
Atunci când n → ∞ , rata R se apropie de valoarea maximă care este un
task pe ciclu de ceas.
7.3. Tipuri de sisteme pipeline
Sistemele pipeline sunt împărţite, de obicei, în două categorii: de
instrucţiuni şi aritmetice. Un sistem pipeline de instrucţiuni este realizat pentru a
îmbunătăţi performanţele unui calculator prin suprapunerea eficientă a fazelor
de execuţie ale instrucţiunilor. Sistemele pipeline aritmetice implementează
anumite funcţii ale unităţii aritmetice şi logice cum ar fi adunarea, înmulţirea şi
împărţirea în virgulă mobilă.
Un sistem pipeline din oricare categorie poate fi proiectat în două moduri:
static sau dinamic.
Un sistem pipeline static poate executa un singur tip de operaţie la un
moment dat. Operaţia executată de un asemenea sistem poate fi modificată
numai după ce acesta este golit, deci ultimele date de intrare au trecut prin toate
etajele. De exemplu, considerăm un sistem pipeline static care poate executa
operaţiile de adunare şi înmulţire. De fiecare dată când sistemul pipeline comută
de la o operaţie de înmulţire la una de adunare, acesta trebuie golit şi trebuie
setat pentru noua operaţie. Performanţele sistemelor pipeline statice vor fi
reduse în mod semnificativ dacă tipul operaţiilor se modifică în mod frecvent.
Un sistem pipeline dinamic poate executa mai multe tipuri de operaţii la un
moment dat. Pentru a executa o anumită operaţie asupra unor date de intrare,
datele trebuie să parcurgă anumite etaje într-o anumită ordine. De exemplu,
figura 7.2 prezintă un sistem pipeline dinamic cu trei etaje, care poate executa
adunarea şi înmulţirea în acelaşi timp asupra unor date diferite.
Pentru execuţia operaţiei de înmulţire, datele de intrare trebuie să
parcurgă etajele 1, 2 şi 3; pentru execuţia operaţiei de adunare, datele trebuie
să parcurgă numai etajele 1 şi 3.
Intrare
Registru
Etaj 1
Circuit de
prelucrare
Registru
Etaj 2
Circuit de
prelucrare
Registru
Etaj 3
Circuit de
prelucrare
Ieşire
Fig. 7.2
Astfel, prima etapă a operaţiei de adunare poate fi executată asupra
datelor de intrare D1 în etajul 1 şi în acelaşi timp, ultima etapă a operaţiei de
înmulţire poate fi executată în etajul 3 asupra unor date de intrare diferite D2 .
Intervalul de timp dintre aplicarea datelor D1 şi D2 la intrările sistemului pipeline
trebuie să fie astfel ales încât aceste date să nu ajungă în etajul 3 în acelaşi
timp; în caz contrar, apare o coliziune. In general, în cazul sistemelor pipeline
dinamice mecanismul care controlează momentul în care datele trebuie aplicate
la intrare este mult mai complex decât în cazul sistemelor statice.
7.4. Sisteme pipeline de instrucţiuni
7.4.1. Principi
In cazul unei arhitecturi von Neumann, procesul de execuţie a
instrucţiunilor implică mai multe faze. Mai întâi, unitatea de control a
procesorului încarcă instrucţiunea din memoria cache (sau din memoria
principală). Apoi, unitatea de control decodifică instrucţiunea pentru a determina
tipul operaţiei care trebuie executată. Dacă operaţia necesită operanzi, unitatea
de control determină adresa fiecărui operand şi le încarcă pe acestea din
memoria cache (sau din memoria principală). Apoi, operaţia este executată şi,
în sfârşit, rezultatul este memorat în locaţia specificată.
Un sistem pipeline de instrucţiuni îmbunătăţeşte performanţele unui
procesor prin suprapunerea prelucrării mai multor instrucţiuni diferite. Aceasta
se realizează prin divizarea procesului de execuţie a instrucţiunilor în mai multe
faze. Un sistem pipeline de instrucţiuni este în mod normal transparent
programatorilor şi este gestionat automat de către unitatea de control a UCP şi
de către compilatoare.
In general execuţia unei instrucţiuni se poate descompune în următoarele
operaţii simple:
1. Extragerea instrucţiunii (IF - Instruction Fetch): Citirea instrucţiunii din
memoria cache (sau din memoria principală).
2. Decodificarea instrucţiunii (ID - Instruction Decoding): Identificarea
operaţiei care trebuie executată.
3. Încărcarea operanzilor (OF - Operand Fetch): Adresarea şi citirea
operanzilor necesari.
4. Execuţia instrucţiunii (EX - Execution): Execuţia operaţiei specificate
asupra operanzilor.
5. Scrierea rezultatelor (WB - Write-Back): Actualizarea operanzilor
destinaţie.
Figura 7.4 prezintă un sistem pipeline de instrucţiuni cu cinci etaje fiecare
etaj având ca obiectiv executarea uneia dintre aceste operaţii.
Un sistem pipeline de instrucţiuni suprapune operaţiile executate de aceste
etaje asupra unor instrucţiuni diferite pentru a obţine un timp total de execuţie
mult mai redus pentru o secvenţă de instrucţiuni.
Registru
Etaj 1
Extragere instrucţiune IF
Registru
Etaj 2
Decodificare instrucţiune ID
Registru
Etaj 3 Registre, memorii cache,
Încărcare operanzi OF memorie principala
Registru
Etaj 4
Execuţie EX
Registru
Etaj 5
Scriere rezultate WB
Fig. 7.4
Ca un exemplu, se consideră figura 7.5, care prezintă execuţia unei
secvenţe de patru instrucţiuni.
Cicluri → 1 2 3 4 5 6 7 8
i1 IF ID OF EX WB
i2 IF ID OF EX WB
i3 IF ID OF EX WB
i4 IF ID OF EX WB
Fig. 7.5
In timpul primului ciclu, sau perioadă de ceas, instrucţiunea i1 este
încărcată din memorie. In cel de-al doilea ciclu, instrucţiunea i1 este decodificată
în timp ce instrucţiunea i2 este încărcată din memorie. Acest proces continuă
până când toate instrucţiunile sunt executate. Ultima instrucţiune se termină
după opt cicluri de ceas. Presupunând că perioada ceasului este de P = 2,5 ns ,
sunt necesare 8 ∗ 2.5 = 20ns pentru a termina execuţia celor patru instrucţiuni.
Timpul total de execuţie poate fi determinat şi din ecuaţia (7.1). Deci
T pipe = m ∗ P + (n − 1) ∗ P = 5 ∗ 2.5 + (4 − 1) ∗ 2.5 = 20ns
In cazul în care nu se utilizează execuţia suprapusă, timpul de execuţie va
fi mult mai ridicat. Utilizând ecuaţia (7.2), rezultă:
T sec = n ∗ m ∗ P = 4 ∗ 5 ∗ 2.5 = 50ns
Deşi prin utilizarea tehnicii pipeline creşte viteza de execuţie a
instrucţiunilor, această tehnică poate pune anumite probleme. Unele din aceste
probleme şi soluţiile posibile sunt prezentate în secţiunile următoare.
7.4.2. Problema indisponibilităţii instrucţiunilor (The fetching problem)
In general, furnizarea rapidă a instrucţiunilor pentru un sistem pipeline este
costisitoare din punct de vedere al resurselor necesare. O metodă simplă pentru
îmbunătăţirea gradului de utilizare al unui sistem pipeline este utilizarea
bufferelor pentru memorarea instrucţiunilor şi a datelor care vor fi transmise la
intrarea sistemului. Gradul de utilizare al unui sistem pipeline este definit ca
raportul între timpul în care etajele sistemului sunt utilizate şi timpul total. Un
sistem pipeline este utilizat 100% din timp dacă fiecare etaj este utilizat în
fiecare ciclu de ceas.
In unele situaţii, sistemul pipeline trebuie golit şi reîncărcat, de exemplu,
atunci când apare o instrucţiune de salt sau o întrerupere. Timpul necesar
pentru reîncărcare poate fi minimizat prin încărcarea în avans a instrucţiunilor şi
a datelor în anumite buffere (prefetch unit), ca de exemplu, în memoria cache
din cadrul procesorului, fapt care va permite transferul imediat la intrarea
sistemului pipeline. Dacă instrucţiunile şi datele necesare execuţiei pot fi
încărcate şi memorate în buffere înainte ca acestea să fie necesare, sistemul
pipeline va avea o sursă continuă de informaţii. Se utilizează algoritmi de
preîncărcare care asigură ca instrucţiunile potenţial necesare să fie disponibile
în majoritatea timpului. Prin utilizarea acestor algoritmi, întârzierile datorită
conflictelor de acces la memorie pot fi reduse, deoarece timpul necesar pentru
transferul datelor din memorie este semnificativ mai ridicat decât timpul necesar
pentru transferul datelor dintr-un buffer.
7.4.3. Problema întârzierii introduse de etaje (bottleneck problem)
Această problemă se referă la complexitatea operaţiilor executate de un
etaj al sistemului pipeline. Dacă un etaj execută operaţii mai complexe faţă de
alte etaje, timpul necesar pentru terminarea acestor operaţii va creşte. Ca
urmare, perioada ceasului trebuie aleasă în funcţie de acest timp, ceea ce
reduce performanţele întregului sistem. O soluţie posibilă a acestei probleme
este divizarea etajului respectiv în mai multe etaje. O altă soluţie este de a se
realiza mai multe copii ale acestui etaj, care să execute în paralel respectiva
operaţie.
Problema emiterii instrucţiunilor (The issuing problem)
Această problemă apare atunci când o instrucţiune disponibilă nu poate fi
executată. Cauzele care pot genera o astfel de situaţie sunt următoarele:
- resursa necesară nu este disponibilă (hazard structural);
- există o dependenţă de o instrucţiune anterioară (hazard de date);
- intervenţia instrucţiunilor de salt care modifică succesiunea de execuţie a
instrucţiunilor (hazardul de control).
7.4.4. Problema hazardului structural
Hazardul structural se referă la situaţia în care o resursă necesară nu este
disponibilă pentru execuţia instrucţiunii. Un hazard structural apare ca rezultat al
conflictelor la resurse între instrucţiuni. Un tip de hazard structural care poate
apare se datorează modului de proiectare al unităţilor de execuţie. Dacă o
unitate de execuţie, care necesită mai multe cicluri de ceas, nu este de tip
pipeline şi nu există mai multe unităţi de acelaşi tip, atunci nu se pot lansa în
execuţie mai multe instrucţiuni care utilizează această unitate.
Un alt tip de hazard structural care poate apare se datorează proiectării
setului de registre. Dacă un set de registre nu are mai multe porturi de citire
(scriere), atunci operaţiile multiple de citire (scriere) nu pot fi executate simultan.
De exemplu, în anumite situaţii sunt necesare două operaţii de scriere în
registre în acelaşi ciclu de ceas. Aceste operaţii nu sunt posibile dacă setul de
registre are un singur port de scriere.
Efectul unui hazard structural poate fi eliminat în mod simplu prin
implementarea unităţilor de execuţie multiple şi prin utilizarea unui set de
registre cu porturi multiple de citire sau scriere.
7.4.5. Problema hazardului de date
7.4.5.1. Dependenţe de date
Hazardul de date apare atunci când există dependenţe de date între
instrucţiunea curentă şi o instrucţiune precedentă. In cazul unui procesor care
nu utilizează tehnica pipeline, instrucţiunile sunt executate secvenţial, iar
execuţia unei instrucţiuni este terminată înaintea începerii execuţiei următoarei
instrucţiuni. Astfel, instrucţiunile sunt executate în aceeaşi ordine în care apar în
program. Situaţia este diferită în cazul unui procesor care utilizează tehnica
pipeline, la care execuţia instrucţiunilor este suprapusă. O instrucţiune poate fi
lansată în execuţie şi poate fi terminată înaintea terminării instrucţiunii
precedente. Hazardul de date, cunoscut şi sub numele de problema
dependenţei datelor, apare ca rezultat al suprapunerii execuţiei (sau schimbării
ordinii de execuţie) a instrucţiunilor între care există dependenţe de date. Pentru
a înţelege această problemă să considerăm într-un program apare următoarea
secvenţă de instrucţiuni:
i1 : ADD R2, R3, R4 ; R2=R3+R4
i2 : ADD R5, R2, R1 ; R5=R2+R1
Instrucţiunea i2 depinde de i1 , deoarece utilizează rezultatul instrucţiunii i1
(conţinutul registrului R2) ca o dată de intrare. In figura 7.6 este prezentată
execuţia celor două instrucţiuni în sistemul pipeline considerat.
Cicluri → 1 2 3 4 5 6
WB
i1 IF ID OF EX
OF
i2 IF ID EX WB
Fig. 7.6
După cum se constată instrucţiunea i2 ajunge în faza OF înainte ca i1 să
treacă prin faza WB. Această situaţie conduce la utilizarea vechiului conţinut al
registrului R2 pentru calcularea unei noi valori pentru R5 şi deci, la un rezultat
invalid. Pentru a se obţine un rezultat valid, instrucţiunea i2 nu trebuie să ajungă
în faza OF până când i1 nu trece prin faza WB. In timpul execuţiei problema
semnalată poate fi rezolvată în două moduri (figura 7.7):
- execuţia fazei OF a instrucţiunii i2 este întârziată cu două cicluri cu ceas
sau
- lansarea în execuţie a instrucţiunii i2 este întârziată cu două cicluri de
ceas.
In ambele cazuri faza OF a instrucţiunii i2 este executată după ce
conţinutul registrului R2 a fost reactualizat de faza WB a instrucţiunii i1 .
Cicluri → 1 2 3 4 5 6 7 8
WB
i1 IF ID OF EX
OF
i2 IF ID - - EX WB
Cicluri → 1 2 3 4 5 6 7 8
WB
i1 IF ID OF EX
OF
i2 - - IF ID EX WB
Fig. 7.7
Pentru inserarea întârzierilor, se poate adăuga la sistemul pipeline un
circuit suplimentar, numit circuit de interblocare (pipeline interlock). Acest circuit
detectează dependenţele între date şi întârzie instrucţiunile dependente până la
rezolvarea conflictului.
O altă posibilitate constă în rezolvarea acestui tip de hazard în timpul
compilării. Compilatorul detectează dependenţa între date şi instrucţiuni,
rearanjând aceste instrucţiuni astfel încât dependenţa să nu creeze hazarduri
pentru sistem. De exemplu, considerăm cele patru instrucţiuni din figura 7.8.
Aceste instrucţiuni pot fi reordonate astfel încât instrucţiunile i3 şi i4 , care nu
sunt dependente de i1 şi i2 , sunt inserate între acestea din urmă.
i1 : ADD R2, R3, R4 ; R2=R3+R4
i2 : ADD R5, R2, R1 ; R5=R2+R1
i3 : ADD R6, R6, R7 ; R6=R6+R7
i4 : ADD R8, R8, R7 ; R8=R8+R7
Cicluri → 1 2 3 4 5 6 7 8
WB
i1 IF ID OF EX
i3 IF ID OF EX WB
i4 IF ID OF EX WB
OF
i2 IF ID EX WB
Fig. 7.8
Dacă nu este posibilă rearanjarea instrucţiunilor, pentru a se introduce
întârzieri, compilatorul inserează instrucţiuni NOP (No Operation).
Există trei tipuri principale de hazarduri de date: RAW (Read After Write),
WAR (Write After Read) şi WAW (Write After Write). Numele hazardului indică
ordinea de execuţie a operaţiilor pentru a se obţine un rezultat valid; dacă
această ordine nu este respectată, se poate obţine un rezultat invalid. Aceste
hazarduri sunt explicate în continuare. Se presupune că există două instrucţiuni
i1 şi i2 , iar i2 trebuie executată după i1 .
RAW. Acest de hazard indică faptul că i2 trebuie să citească sursa de
date după ce i1 a scris această dată. Dacă această ordine nu este respectată se
produce un rezultat invalid deoarece locaţia citită conţine o dată eronată.
De exemplu, în secvenţa următoare:
i1 : ADD R2, R3, R4 ; R2 = R3 + R4
i2 : ADD R5, R2, R1 ; R5 = R2 + R1
se poate obţine un rezultat invalid dacă i2 citeşte registrul R2 înainte ca i1 să
scrie în acest registru.
WAR. Acest hazard indică faptul că i2 trebuie să scrie într-o anumită
locaţie după ce i1 a citit data conţinută în acea locaţie. Dacă această ordine nu
este păstrată conţinutul acelei locaţii de memorie este alterat. De exemplu, în
secvenţa:
i1 : ADD R2, R3 , R4 ; R2 = R3 + R4
i2 : ADD R4, R5, R6 ; R4 = R5 + R6
se poate obţine un rezultat invalid dacă i2 scrie în registrul R4 înainte ca i1 să
citească acest registru; deci, instrucţiunea i1 poate utiliza conţinutul incorect al
registrului R4.
WAW. Acest hazard indică faptul că i2 trebuie să scrie într-o anumită
locaţie după ce i1 a scris în aceeaşi locaţie. De exemplu, în secvenţa:
i1 : ADD R2, R3, R4 ; R2 = R3 + R4
i2 : ADD R2, R5, R6 ; R2 = R5 + R6
valoarea din registrul R2 este recalculată de către i2 . Dacă ordinea de execuţie
este inversată, iar i2 scrie în registrul R2 înainte ca i1 să scrie în acest registru,
R2 va conţine o valoare incorectă.
Hazardurile de tip WAR şi WAW nu pot apare atunci când ordinea de
execuţie a instrucţiunilor din program este păstrată. O modalitate de a
îmbunătăţi arhitectura unui sistem pipeline de instrucţiuni este de a creşte
gradul de execuţie concurentă a instrucţiunilor prin execuţia mai multor
instrucţiuni independente de către unităţi funcţionale diferite, ca de exemplu,
sumatoare, circuite de înmulţire şi circuite de împărţire. In aceste condiţii
instrucţiunile pot fi executate şi terminate într-o ordine diferită de cea din
program. Pentru acest motiv, în astfel de arhitecturi sunt posibile toate tipurile
de hazarduri de date.
In arhitecturile actuale, dependenţele între instrucţiuni (Data Dependancy)
sunt verificate în mod static de compilator şi/sau în mod dinamic de circuite în
timpul execuţiei. Prin aceasta se păstrează ordinea de execuţie a instrucţiunilor
între care există dependenţe, ceea ce asigură obţinerea unor rezultate valide.
Au fost dezvoltate numeroase tehnici statice de verificare a dependenţelor
pentru a se utiliza avantajul paralelismului dintr-o buclă. Aceste tehnici pot
detecta majoritatea dependenţelor. Totuşi, anumite dependenţe nu pot fi
detectate la compilare. De exemplu, nu este posibil să se determine
întotdeauna adresele efective de memorie utilizate de instrucţiunile de încărcare
şi memorare pentru a rezolva posibilele dependenţe între acestea. In timpul
execuţiei, adresele efective de memorie vor fi cunoscute şi astfel dependenţele
între instrucţiuni pot fi determinate în mod dinamic. In general, verificarea
dinamică a dependenţelor are avantajul că poate detecta dependenţele care
sunt imposibil sau dificil de detectat la compilare. In practică, se utilizează
adesea o verificare combinată a dependenţelor (statică şi dinamică) pentru a se
folosi avantajele ambelor metode.
Două din cele mai des utilizate tehnici pentru verificarea dinamică a
dependenţelor sunt metoda Tomasulo şi metoda tabelei de rezultate
(scoreboard). Ideea de bază a acestor metode este utilizarea unui mecanism
pentru identificarea disponibilităţii operanzilor şi a unităţilor funcţionale în
calculele succesive.
7.4.5.2. Metoda Tomasulo
Metoda Tomasulo a fost elaborată de R. M. Tomasulo pentru a elimina
efectul timpilor mari de acces la memorie la calculatorul IBM Systems/360
Model 91.
Această metodă creşte gradul de execuţie concurentă a instrucţiunilor cu
un efort minim din partea compilatorului sau al programatorului. Metoda
Tomasulo este utilizată în mai multe variante pentru planificarea dinamică a
execuţiei instrucţiunilor la procesoarele superscalare recente. In cazul acestei
metode, se asociază fiecărui registru de date a unităţii aritmetice un bit busy şi
un câmp de marcaj (Tag). Bitul busy al unui anumit registru este setat atunci
când o instrucţiune lansată în execuţie desemnează acest registru ca o
destinaţie. Acest bit este resetat atunci când rezultatul execuţiei este scris în
registru. Câmpul de marcajul al unui registru identifică unitatea a cărei rezultat
urmează să fie înscris în registru.
Fiecare unitate funcţională din cadrul unităţii aritmetice poate avea mai
multe seturi de registre de intrare. In exemplul considerat în figura 7.9 acestea
au două seturi de registre (sursa_1 şi sursa_2). Fiecare set este numit staţie de
rezervare, fiind utilizat pentru păstrarea operanzilor unei instrucţiuni lansate în
execuţie. Un câmp de marcaj este, de asemenea, asociat cu fiecare registru al
unei staţii de rezervare. In plus, o magistrală comună de date (MCD)
conectează ieşirile unităţilor funcţionale cu intrările staţiilor de rezervare şi cu
registrele.
execuţie.
MCD face posibil ca rezultatul unei operaţii să devină disponibil pentru
Fig. 7.9
toate unităţile funcţionale, fără înscrierea prealabilă într-un registru.
Aceasta permite furnizarea directă a unei copii a rezultatului la toate
unităţile funcţionale care aşteaptă acest rezultat. Cu alte cuvinte, o instrucţiune
aflată în curs de execuţie poate avea acces la rezultatul unei instrucţiuni
precedente înainte ca rezultatul instrucţiunii precedente să fie înscris în registrul
destinaţie.
Figura 7.9 prezintă o arhitectură simplă pentru această metodă. In această
arhitectură, există nouă unităţi care comunică printr-o magistrală comună de
date. Aceste unităţi sunt cinci registre de date, două staţii de rezervare pentru
adunare A1 şi A2 şi două staţii de rezervare pentru înmulţire M 1 şi M 2 . Codurile
1 până la 5 sunt asociate cu registrele din setul de registre, 6 şi 7 sunt asociate
cu staţiile de rezervare pentru adunare, iar 8 şi 9 sunt asociate cu staţiile de
rezervare pentru înmulţire. Ca exemplu, considerăm execuţia următoarelor două
instrucţiuni:
i1 : ADD R2, R3, R4 ; R2 = R3 + R4
i2 : ADD R2, R2, R1 ; R2 = R2 + R1
Secvenţa începe cu execuţia instrucţiunii i1 . Conţinutul registrelor R3 şi R4
este încărcat în registrele sursa_1, respectiv sursa_2 ale staţiei de rezervare A1
iar câmpul de marcaje al registrului R2 este setat la 6, care este eticheta staţiei
A1 . După înscrierea operanzilor instrucţiunii i1 în staţia de rezervare pentru
adunare A1 bitul busy al registrului R2 este setat la 1. In continuare, unitatea de
adunare începe execuţia operaţiei specificate de i1 . Simultan, în timpul
procesului de încărcare a operanzilor pentru instrucţiunea i2 , devine cunoscut
faptul că registrul R2 nu poate fi utilizat deoarece instrucţiunea i2 depinde de
rezultatul instrucţiunii i1 . Pentru a permite începerea execuţiei instrucţiunii i2 cât
mai rapid posibil, conţinutul câmpului de marcaje al registrului R2 (care este în
acest moment 6) este înscris în câmpul de marcaje al registrului sursa_1 al
staţiei de rezervare A2 . In acelaşi moment, marcajul registrului R2 este
modificat la 7, ceea ce înseamnă că rezultatul staţiei A2 trebuie transferat în R2.
De asemenea, conţinutul registrului R1 este încărcat în registrul sursa_2 al
staţiei de rezervare A2 . La terminarea operaţiei specificate de i1 şi producerea
rezultatului, unitatea de adunare transmite un semnal de cerere către MCD
pentru preluarea rezultatului. Atunci când MCD achită cererea, unitatea de
adunare transmite rezultatul pe magistrală, de unde rezultatul este transmis
împreună cu eticheta staţiei A1 (cu valoarea 6) tuturor unităţilor. Fiecare staţie
de rezervare, în timp ce aşteaptă datele, compară conţinutul câmpului de
marcaje ale registrelor sale cu eticheta de pe magistrală. Dacă acestea sunt
identice, conţinutul registrului respectiv este actualizat şi bitul său busy este
resetat. In acest caz, datele sunt copiate în registrul sursa_1 al staţiei A2 .
Începe apoi execuţia operaţiei de adunare cu operanzii staţiei A2 .
După efectuarea adunării specificate de i2 pe magistrală este depus
rezultatul adunării dintre R2 şi R1, împreună cu eticheta staţiei de rezervare A2
(care este 7). Acest rezultat va fi preluat de registrul R2 care conţine în câmpul
de marcaj valoarea 7.
După cum rezultă din exemplul precedent, conceptele principale ale
metodei Tomasulo sunt staţiile de rezervare, magistrala comună de date şi
utilizarea marcajelor. Staţiile de rezervare au rolul de a aştepta operanzii şi
astfel, eliberează unităţile funcţionale de această sarcină. Magistrala comună de
date utilizează staţiile de rezervare furnizând acestora rezultatul unei operaţii
direct de la ieşirea unei unităţi funcţionale. Marcajele asigură păstrarea
dependenţelor între operaţiile succesive, favorizând în acelaşi timp concurenţa.
Deşi circuitele suplimentare necesare pentru implementarea metodei
Tomasulo favorizează execuţia concurentă a instrucţiunilor, programatorul
şi/sau compilatorul au o influenţă substanţială asupra gradului de concurenţă.
Aceasta se ilustrează prin următoarele două secvenţe care calculează expresia
(A * B) + (C + D).
O posibilă secvenţă de instrucţiuni care rezolvă această problemă este:
LOAD R1, A
LOAD R2, B
LOAD R3, C
LOAD R4, D
MUL R5, R1, R2 ; R5 = A * B
ADD R5, R5, R3 ; R5 = (A * B) +C
ADD R4, R5, R4 ; R4 = (A *B) + C + D
O alternativă la această secvenţă, care permite un grad mai mare de
concurenţă, este următoarea:
LOAD R1, A
LOAD R2, B
LOAD R3, C
LOAD R4, D
MUL R5, R1, R2 ; R5 = A * B
ADD R4, R3, R4 ; R4 = C + D
ADD R4, R5, R4 ; R4 = A * B + C + D
In cea de-a doua secvenţă, instrucţiunea de înmulţire şi prima instrucţiune
de adunare pot fi executate simultan, ceea ce nu este posibil în cazul primei
secvenţe. In practică, de multe ori se utilizează o combinaţie a tehnicilor
hardware şi software pentru creşterea gradului de concurenţă.

7.4.5.3. Metoda tabelei de rezultate (Scoreboard)


Metoda tabelei de rezultate a fost utilizată pentru prima dată la calculatorul
de înaltă performanţă CDC 6600, la care unităţi funcţionale multiple permit
terminarea execuţiei instrucţiunilor într-o ordine diferită de cea în care apar în
program. Această metodă păstrează informaţii despre starea fiecărei instrucţiuni
lansate în execuţie, fiecare registru şi fiecare unitate funcţională, în anumite
buffere care reprezintă tabela de rezultate. Prin considerarea unui instantaneu
al tabelei de rezultate, se poate determina dacă trebuie să se aştepte pentru
noua instrucţiune. Dacă aşteptarea nu este necesară, unitatea funcţională
corespunzătoare începe imediat execuţia instrucţiunii. Dacă trebuie să se
aştepte (de exemplu, unul din operanzii de intrare nu este încă disponibil),
execuţia noii instrucţiuni este întârziată.
O tabelă de rezultate este fi formată din trei tabele: starea instrucţiunilor,
starea unităţilor funcţionale şi starea registrelor destinaţie.
Figura 7.10 reprezintă un instantaneu al conţinutului acestor tabele pentru
următorul program care calculează expresia C+D+A*B:
LOAD R1, A
LOAD R2, B
LOAD R3, C
LOAD R4, D
MUL R5, R1, R2 ; R5 = A ∗ B
ADD R2, R3, R4 ; R2 = C + D
ADD R2, R2, R5 ; R3 = R2 + R5 = C + D + A * B
Starea instrucţiunilor
Faza OF Faza EX Faza WB
Instrucţiune Lansată
terminată terminată terminată
LOAD R1, A Da Da Da Da
LOAD R2, B Da Da Da Da
LOAD R3, C Da Da Da Da
LOAD R4, D Da Da Da
MUL R5, R1, R2 Da Da
ADD R2, R3, R4 Da
ADD R2, R2, R5
Starea unităţilor funcţionale
ID Nume unitate Ocupată Registre sursă
Registru
Unitate destinaţie
RS1 Liber Rs2 Liber
1 LOAD/STORE Da R4
2 Înmulţire Da R5 R1 Da R2 Da
3 Adunare_1 Da R2 R3 Da R4 Nu
4 Adunare_2 Nu
Starea registrelor destinaţie
R1 R2 R3 R4 R5 R6
ID unitate 3 1 2
Fig. 7.10
Tabela de stare a instrucţiunilor arată dacă o instrucţiune este sau nu
lansată în execuţie. Dacă o instrucţiune este lansată în execuţie, tabela arată în
care fază de execuţie se află instrucţiunea. După ce o instrucţiune este
încărcată din memorie şi decodificată, se va încerca lansarea execuţiei acesteia
utilizând unitatea funcţională corespunzătoare. O instrucţiune va fi lansată în
execuţie dacă unitatea funcţională este disponibilă şi nu există altă instrucţiune
activă care utilizează acelaşi registru destinaţie; în caz contrar, lansarea este
întârziată. Cu alte cuvinte, o instrucţiune este lansată în execuţie atunci când nu
există hazarduri structurale şi hazarduri WAW. Atunci când există asemenea
hazarduri, lansarea execuţiei acestei instrucţiuni şi a instrucţiunilor următoare
este întârziată până când hazardurile sunt eliminate. In acest fel, instrucţiunile
dependente sunt lansate în execuţie în ordinea în care apar în program, în timp
ce instrucţiunile independente pot fi executate într-o ordine diferită.
Tabela de stare a unităţilor funcţionale arată dacă o unitate funcţională
este ocupată sau nu. O unitate funcţională ocupată înseamnă că execuţia unei
instrucţiuni de către această unitate nu a fost încă terminată. Pentru o unitate
ocupată, tabela identifică de asemenea registrul destinaţie şi disponibilitatea
registrelor sursă. Un registru sursă al unei unităţi este disponibil dacă nu apare
ca destinaţie pentru nici o altă unitate anterioară.
Tabela de stare a registrelor destinaţie indică destinaţia registrelor care nu
au fost încă înscrise. Pentru fiecare din aceste registre se identifică unitatea
funcţională activă care va executa scrierea în registru.
In timpul fazei de extragere a operanzilor, tabelele sunt monitorizate
pentru a determina dacă registrele sursă sunt disponibile pentru a fi citite de
către o unitate funcţională activă. Dacă nici unul din registrele sursă nu este
utilizat ca registru destinaţie de către alte unităţi funcţionale active, unitatea
citeşte operanzii din aceste registre şi începe execuţia operaţiei. După
terminarea execuţiei, tabela de rezultate testează dacă există hazarduri WAR
înainte de a permite scrierea rezultatului în registrul destinaţie. Dacă nu există
hazarduri WAR, tabela de rezultate indică unităţii funcţionale să scrie rezultatul
în registrul destinaţie.
In figura 7.10, tabelele indică faptul că execuţia primelor trei instrucţiuni
LOAD a fost terminată şi operanzii acestora au fost înscrişi în registrul
destinaţie. Ultima instrucţiune LOAD a fost lansată în execuţie de către unitatea
LOAD/STORE (unitatea 1). La această instrucţiune, s-a terminat extragerea
operandului, dar nu s-a înscris încă operandul în registrul R4. Unitatea de
înmulţire execută instrucţiunea MUL, iar prima instrucţiune ADD este transmisă
unităţii Adunare_1. Această unitate aşteaptă pentru ca registrul R4 să fie înscris
de către unitatea LOAD/STORE înainte de a începe execuţia. Acest lucru este
necesar deoarece există un hazard RAW între ultima instrucţiune LOAD şi
prima instrucţiune ADD. In acest moment, a doua instrucţiune ADD nu poate fi
lansată în execuţie, deoarece utilizează registrul R2 ca registru sursă şi
destinaţie. Registrul R2 este ocupat în acest moment cu prima instrucţiune
ADD. Atunci când registrul R4 este înscris de unitatea LOAD/STORE, unitatea
Adunare_1 va începe execuţia.
Ulterior conţinutul tabelei de rezultate se modifică. După cum se ilustrează
în figura 7.11, dacă unitatea LOAD/STORE (unitatea 1) a terminat execuţia (a
înscris în R4 valoarea variabilei D), unitatea Adunare_1 poate termina faza de
încărcare a operanzilor şi începe faza de execuţie. După terminarea execuţiei
rezultatul poate fi înscris în registrul R2 deoarece unitatea de înmulţire a
terminat faza de citire a operanzilor şi este acum în faza de execuţie. A doua
instrucţiune ADD va fi transmisă acum unităţii Adunare_2.
Starea instrucţiunilor
Faza OF Faza EX Faza WB
Instrucţiune Lansată
terminată terminată terminată
LOAD R1, A Da Da Da Da
LOAD R2, B Da Da Da Da
LOAD R3, C Da Da Da Da
LOAD R4, D Da Da Da Da
MUL R5, R1, R2 Da Da Da
ADD R2, R3, R4 Da Da Da Da
ADD R2, R2, R5 Da
Starea unităţilor funcţionale
ID Nume Ocupată Registre sursă
Registru
unitate unitate destinaţie Rd Rs Liber Rs Liber
1 2
1 LOAD/STOR Nu
E
2 Înmulţire Da R5 R1 Da R2 Da
3 Adunare_1 NU
4 Adunare_2 Da R2 R2 Da R5 Nu
Starea registrelor destinaţie
R1 R2 R3 R4 R5 R6
ID 4 2
unitate
Fig. 7.11
Cât timp unitatea de înmulţire nu a citit conţinutul registrului R2 unităţii
Adunare_1 nu i se va permite scrierea rezultatului în registrul R2; aceasta
deoarece există un hazard WAR între instrucţiunea MUL şi prima instrucţiune
ADD.
Componenta principală în cazul metodei tabelei de rezultate este tabela
de stare a registrelor destinaţie. Această tabelă este utilizată pentru a soluţiona
hazardurile de date între instrucţiuni. De fiecare dată când o instrucţiune este
lansată în execuţie, registrul destinaţie al instrucţiunii este marcat ca fiind
ocupat. Registrul destinaţie rămâne ocupat până când execuţia instrucţiunii este
terminată. Atunci când se pregăteşte lansarea unei noi instrucţiuni, sunt testaţi
operanzii acesteia pentru a nu exista conflicte între registre cu instrucţiunile
precedente a căror execuţie nu a fost terminată.
7.4.6. Problema hazardului de control
Hazardul de control se referă la situaţia în care o anumită instrucţiune,
cum ar fi o instrucţiune de salt, modifică fluxul execuţiei programului.
7.4.6.1. Instrucţiuni de salt
In orice set de instrucţiuni, salturile permit modificarea ordinii secvenţiale
de execuţie a instrucţiunilor. In general, în jur de 20 - 30% din totalul
instrucţiunilor dintr-un program sunt salturi. Pentru acest motiv, instrucţiunile de
salt executate de un sistem pipeline pot reduce în mod semnificativ rata de
prelucrare. Ori de câte ori un salt este executat, trebuie să se încarce o nouă
adresă în contorul de program, ceea ce poate invalida toate instrucţiunile a
căror execuţie a început sau cele care au fost preîncărcate într-un buffer.
Această golire a etajelor pipeline la fiecare salt reduce performanţele sistemului.
De notat că un salt condiţionat, care nu este executat permite continuarea
execuţiei secvenţiale a instrucţiunilor, deci această problemă apare numai în
cazul în care saltul este executat.
In general, instrucţiunile de salt se pot clasifica în trei categorii:
1) Salturi necondiţionate;
2) Salturi condiţionale;
3) Bucle.
Un salt necondiţionat modifică întotdeauna ordinea secvenţială de
execuţie şi, în loc de a incrementa contorul de program, încarcă adresa
destinaţiei saltului în acesta.
Un salt condiţionat încarcă adresa destinaţiei în contorul de program
numai dacă o anumită condiţie, bazată pe starea unor indicatori de condiţii, este
îndeplinită. In caz contrar, contorul de program este incrementat ca de obicei.
Cu alte cuvinte, un salt condiţionat selectează o cale a instrucţiunilor pe baza
unei condiţii. In cazul în care condiţia este îndeplinită, această cale începe de la
adresa destinaţiei saltului şi este numită cale destinaţie. In caz contrar, această
cale începe de la următoarea instrucţiune şi este numită cale secvenţială. In
sfârşit, o instrucţiune de buclare determină de obicei saltul la începutul buclei,
care este executată de un anumit număr de ori, fix sau variabil.
Dintre aceste tipuri de salturi, salturile condiţionate sunt cel mai dificil de
gestionat. Ca un exemplu, considerăm următoarea secvenţă de instrucţiuni:
i1
i2 (salt condiţionat la ik )
i3
:
ik (destinaţie)
ik +1
Figura 7.12 prezintă execuţia acestei secvenţe de instrucţiuni într-un
sistem pipeline atunci când se selectează calea destinaţie. In această figură, c
indică penalizarea datorită saltului, reprezentând numărul de cicluri pierdute
atunci când este selectată calea destinaţie.
C
Cicluri → 1 2 3 4 5 6 7 8 9 10 11
i1 IF ID OF EX WB
i2 IF ID OF EX WB
i3 IF ID OF EX
i4 IF ID OF
i5 IF ID
ik IF ID OF EX WB
ik+1 IF ID OF EX WB
Fig. 7.12
Pentru a arăta efectul penalizării datorită saltului asupra performanţelor
globale ale sistemului pipeline, trebuie să se determine numărul mediu de cicluri
pe instrucţiune. Fie t med numărul mediu de cicluri necesare pentru execuţia unei
instrucţiuni. Acest număr poate fi exprimat ca:
(7.8)
t med = p s ∗ t s + (1 − p s ) ∗ t n
unde p s indică probabilitatea ca o anumită instrucţiune să fie o instrucţiune de
salt, t s reprezintă numărul mediu de cicluri pentru o instrucţiune de salt, iar t n
reprezintă numărul mediu de cicluri pentru o instrucţiune diferită de una de salt.
Numărul mediu de cicluri pentru o instrucţiune de salt poate fi determinat
considerând două cazuri. Dacă se alege calea destinaţie, sunt necesare 1 + c
cicluri pentru execuţie; în caz contrar, nu există penalizare datorită saltului şi
este necesar un singur ciclu. Deci:
(7.9)
t s = pd (1 + c) + (1 − pd )(1)
unde pd indică probabilitatea să fie aleasă calea destinaţie d . Numărul mediu
de cicluri pentru o instrucţiune diferită de una de salt este 1 ( t n = 1). După
întârzierea iniţială, se termină execuţia unei instrucţiuni diferite de una de salt în
fiecare ciclu. Deci:
(7.10)
t med = p s [ pd (1 + c) + (1 − p d )(1)] + (1 − p s ) ∗ (1) = 1 + p s pd c
După analizarea a numeroase cazuri practice, Lee şi Smith au arătat că
valoarea medie a probabilităţii p s este cuprinsă între 0,1 şi 0,3, iar valoarea
medie a probabilităţii pd este cuprinsă între 0,6 şi 0,7. Presupunând că p s = 0,2 ,
pd = 0,65 şi c = 3 , rezultă:
(7.11)
t med = 1 + 0,2 ∗ 0,65 ∗ 3 = 1,39
Cu alte cuvinte, sistemul pipeline operează la 100/1,39 = 72% din viteza
sa maximă atunci când există instrucţiuni de salt.
Pentru a se reduce efectul salturilor asupra performanţelor unui procesor,
au fost propuse diferite tehnici. Cele mai cunoscute tehnici sunt predicţia
salturilor, întârzierea salturilor şi preîncărcarea multiplă. Aceste tehnici sunt
prezentate în continuare.
7.4.6.2. Predicţia salturilor
In cazul acestei metode, se realizează o predicţie a rezultatului unei decizii
legate de execuţia saltului. Pe baza acestei predicţii, se alege pentru execuţie
calea secvenţială sau calea destinaţie. Deşi prin alegerea căii respective se
reduce adesea penalizarea datorită saltului, penalizarea poate creşte în cazul
unei predicţii eronate.
Există două tipuri de predicţii, statice şi dinamice. In cazul unei predicţii
statice, se decide înaintea execuţiei programului preîncărcarea instrucţiunilor
dintr-una din cele două căi. De exemplu, o tehnică simplă este aceea de a
presupune întotdeauna că saltul trebuie executat. Prin această tehnică, la
întâlnirea unei instrucţiuni de salt se încarcă în contorul de program adresa de
destinaţie a saltului. O altă tehnică este de a alege o anumită cale (secvenţială
sau destinaţie) pentru anumite tipuri de salturi şi cealaltă cale pentru restul
tipurilor. In cazul în care alegerea este eronată, sistemul pipeline este golit şi se
încarcă instrucţiunile corespunzătoare căii corecte.
In cazul predicţiei dinamice, în timpul execuţiei programului procesorul ia o
decizie bazată pe informaţiile despre salturile executate anterior.
Metoda cea mai simplă este predicţia dinamică utilizând un bit, metodă
implementată de exemplu, la unele procesoare RISC.
Această metodă presupune asignarea unui bit de control p fiecărei
instrucţiuni de salt. Dacă la prima execuţie se realizează saltul, p va avea
valoarea 1. In caz contrar p = 0 . La următoarea întâlnire a acestei instrucţiuni
se urmează calea anterioară. Dacă predicţia a fost eronată se schimbă valoarea
bitului de control p . Astfel la următoarea execuţie se va urma cealaltă cale.
O metodă mai eficientă constă în a se asocia un contor de n biţi fiecărei
instrucţiuni de salt. Această metodă este numită metoda de predicţie bazată pe
un contor (counter based branch prediction). In cazul acestei metode, după ce o
instrucţiune de salt a fost executată pentru prima dată, contorul C al acesteia
este setat la o valoare de prag T (10 pentru exemplul din fig. 7.13) dacă a fost
selectată calea destinaţie, sau la valoarea T − 1 (01 pentru exemplul din fig.
7.13) dacă a fost selectată calea secvenţială. In continuare, de fiecare dată
când instrucţiunea de salt trebuie executată, dacă C ≥ T , este selectată calea
destinaţie; în caz contrar, este selectată calea secvenţială. Valoarea contorului
C este actualizată după execuţia saltului. In cazul în care calea corectă este
calea destinaţie, contorul este incrementat cu 1; în caz contrar, contorul este
decrementat cu 1.
Dacă C ajunge !a valoarea maximă 2 n − 1 , contorul nu mai este
incrementat, chiar dacă a fost selectată calea destinaţie şi predicţia a fost
corectă. In mod similar, contorul nu este decrementat la o valoare mai mică de
0.
In practică, pentru n şi T se alege adesea valoarea 2. Studiile au arătat
că metodele de predicţie cu 2 biţi sunt aproape la fel de eficiente ca şi metodele
care utilizează un număr mai mare de biţi. Figura 7.13 prezintă stările posibile în
cazul metodei de predicţie cu 2 biţi.
O altă variantă a metodei precedente este de a se modifica predicţia
numai atunci când aceasta a fost eronată de două ori în mod consecutiv. Figura
7.14 prezintă stările posibile în cazul acestei variante.
Fig. 7.13
Fig. 7.14
Este convenabil să se memoreze statisticile salturilor într-o tabelă numită
tabelă de istorie a salturilor (branch history table), împreună cu adresa
instrucţiunii de salt şi adresa destinaţiei saltului. Pentru accesul rapid,
majoritatea procesoarelor plasează tabela de istorie a salturilor într-o memorie
cache de dimensiuni reduse, numită buffer al destinaţiei salturilor (BTB - Branch
Target Buffer). De obicei, fiecare intrare a acestei memorii cache păstrează
adresa unei instrucţiuni de salt, adresa destinaţiei saltului şi statisticile de
predicţie (figura 7.15).
Fig. 7.15
Atunci când o instrucţiune de salt este executată pentru prima dată,
procesorul alocă o intrare în BTB pentru această instrucţiune. Cererile pentru
încărcarea instrucţiunilor sunt trimise simultan la memoria cache de instrucţiuni
şi la BTB. Dacă se găseşte o potrivire în BTB, adresa anticipată a destinaţiei
saltului este citită din tabel. Execuţia continuă pe calea de instrucţiuni definită de
adresa destinaţiei saltului, toate rezultatele fiind considerate speculative până
când rezultatul testării condiţiei de salt devine disponibil. Atunci când execuţia
instrucţiunii de salt este terminată, adresa destinaţiei acesteia este actualizată în
BTB. Statisticile de predicţie ale instrucţiunii de salt sunt de asemenea
actualizate.
Metodele de predicţie statice necesită de obicei mai puţine circuite, dar pot
determina creşterea complexităţii compilatorului. Spre deosebire de acestea,
metodele de predicţie dinamice determină creşterea complexităţii circuitelor, dar
necesită operaţii mai simple în timpul compilării. In general, prin utilizarea
predicţiei dinamice se pot obţine rezultate mai bune. Predicţia dinamică asigură,
de asemenea, un grad mai ridicat de compatibilitate a codului obiect, deoarece
deciziile sunt luate după compilare.
Pentru a determina efectul predicţiei salturilor asupra performanţelor, este
necesară reevaluarea numărului mediu al ciclurilor de ceas pentru execuţia unei
instrucţiuni. Considerăm ecuaţia (7.8). Există două cazuri posibile: calea
anticipată este corectă sau incorectă. In cazul în care calea este anticipată
corect, penalizarea este d atunci când calea este cea destinaţie (figura 7.16(a))
sau 0 atunci când calea este cea secvenţială. In cazul în care calea este
anticipată incorect, penalizarea este c atât pentru calea destinaţie, cât şi pentru
cea secvenţială (figura 7.12 şi figura 7.16(b)). De notat că în figura 7.16(a),
adresa căii destinaţie este obţinută după faza de decodificare. Atunci când se
utilizează un buffer al destinaţiei saltului, adresa destinaţiei poate fi obţinută în
timpul sau după faza de extragere a instrucţiunii.
d
Cicluri → 1 2 3 4 5 6 7 8 9 10 11
i1 IF ID OF EX WB
ID
i2 IF OF EX WB
i3 IF
i4
i5
IF
ik ID OF EX WB
ik+1 IF ID OF EX WB
a
c
Cicluri → 1 2 3 4 5 6 7 8 9 10 11
i1 IF ID OF EX WB
EX WB
i2 IF ID OF
i3 IF ID OF EX
i4 IF ID OF
i5 IF ID
IF
ik ID OF EX WB
ik+1 IF ID OF EX WB
b
Fig. 7.16
Pe baza acestor observaţii, avem:
t s = pc [ pd (1 + d ) + (1 − pd )(1)] + (1 − pc )[ pd (1 + c) + (1 − pd )(1 + c)]
(7.13)
= pc (1 + pd d ) + (1 − pc )(1 + c)
unde pc este probabilitatea unei predicţii corecte. Înlocuind acest termen în
ecuaţia (7.8), obţinem:
t med = p s [ pc (1 + pd d ) + (1 − pc )(1 + c)] + 1 − p s )(1)
(7.14)
= 1 + p s c − p s pc c + p s pc p d d
Presupunând că p s = 0,2 , p d = 0,65 , pc = 0,7 , c = 3 , şi d = 1 rezultă
(7.15)
t med = 1,27
Deci, sistemul pipeline funcţionează la 100/1,27 = 78% din viteza sa
maximă atunci când se utilizează predicţia salturilor.
7.4.6.3. Întârzierea salturilor
Întârzierea salturilor (delayed branching) elimină sau reduce în mod
semnificativ efectul penalizării datorită salturilor. In cazul acestei metode se
încarcă şi se execută un anumit număr de instrucţiuni după instrucţiunea de salt,
indiferent de calea care va fi selectată pentru salt. De exemplu, un procesor cu
o întârziere a salturilor egală cu k execută următoarele k instrucţiuni
secvenţiale, iar apoi fie continuă pe aceeaşi cale, fie începe execuţia
instrucţiunilor de la adresa destinaţiei saltului. De câte ori este posibil,
compilatorul încearcă să plaseze după instrucţiunea de salt k instrucţiuni care
sunt independente de instrucţiunea de salt. Dacă nu există suficiente instrucţiuni
de acest tip, compilatorul va insera instrucţiuni NOP. Ca un exemplu,
considerăm următoarea secvenţă:
i1 : LOAD R1, A
i2 : LOAD R2, B
i3 : BRZ R2, i7 ; salt la i7 dacă R2 = 0
i4 : LOAD R3, C
i5 : ADD R4, R2, R3 ; R4 = B + C
i6 : MUL R5, R1, R2 ; R5 = A * B
i7 : ADD R4, R1, R2 ; R4 = A + B
Presupunând k = 2 , compilatorul modifică această secvenţă prin mutarea
instrucţiunii i1 şi inserarea unei instrucţiuni NOP după instrucţiunea de salt i3 .
Secvenţa modificată este următoarea:
i2 : LOAD R2, B
i3 : BRZ R2, i7
i1 : LOAD R1, A
NOP
i4 : LOAD R3, C
i5 : ADD R4, R2, R3
i6 : MUL R5, R1, R2
i7 : ADD R4, R1, R2
După cum se observă din secvenţa modificată, instrucţiunea i1 este
executată indiferent de rezultatul evaluării saltului. Pentru a înţelege efectul de
reducere a penalizării prin utilizarea întârzierii salturilor ne vom referi la figura
7.16(b). In cazul în care nu se utilizează metoda întârzierii salturilor, atunci când
predicţia sugerează ca probabilă calea secvenţială, se începe execuţie
instrucţiunilor care urmează după instrucţiunea de salt. Dacă, după execuţia
instrucţiunii de salt de constată că predicţia a fost eronată, sistemul pipeline se
goleşte pentru a începe execuţia instrucţiunilor de pe calea de destinaţie. In
acest caz cele trei perioade de ceas în care se încerca execuţia instrucţiunilor
de pe calea secvenţială au fost irosite. Dacă pe cale secvenţială sunt introduse
instrucţiuni care sunt independente de instrucţiunea de salt, în cazul considerat,
se continuă cu execuţia acestora şi abia după finalizarea acelor instrucţiuni, se
trece la execuţia instrucţiunilor de pe calea destinaţie. In acest mod nu a fost
pierdut nici un ciclu de ceas.
7.4.6.4. Preîncărcarea multiplă (multiple prefetching)
In acest caz, procesorul extrage instrucţiuni din ambele căi posibile. După
ce s-a luat decizia despre execuţia saltului, calea nedorită este abandonată.
Prin extragerea prealabilă a instrucţiunilor din ambele căi posibile, se evită
penalizarea datorită extragerii instrucţiunilor în cazul unei predicţii incorecte.
Pentru extragerea instrucţiunilor din ambele căi, se utilizează două buffere.
La execuţia normală, primul buffer este încărcat cu instrucţiuni aflate după
instrucţiunea de salt. Dacă saltul este executat, conţinutul primului buffer este
invalidat şi cel de-al doilea buffer se utilizează ca buffer primar, care a fost
încărcat cu instrucţiuni aflate la adresa destinaţiei instrucţiunii de salt.
Această metodă de extragere dublă asigură un flux constant de instrucţiuni
şi date pentru sistemul pipeline şi reduce întârzierile datorate golirii şi
reîncărcării sistemului pipeline.
In concluzie, fiecare din tehnicile prezentate anterior reduce înrăutăţirea
ratei de transfer a sistemului pipeline. Alegerea uneia din aceste tehnici pentru
un sistem particular depinde de factori ca cerinţele ratei de transfer şi restricţiile
de cost. In practică, datorită acestor factori, într-un procesor se implementează
de obicei o combinaţie a acestor tehnici.

7.4.7. Îmbunătăţirea ratei de transfer a sistemelor pipeline


Reamintim că rata de transfer a unui sistem pipeline este definită ca numărul
taskurilor de intrare pe care le poate prelucra în unitatea de timp.
O posibilitate de creştere a ratei de transfer a unui sistem pipeline de
instrucţiuni este de a se utiliza paralelismul la nivelul instrucţiunilor (instruction-
level parallelism - ILP). Acest procedeu constă dintr-un set de tehnici ale
procesorului şi compilatorului care îmbunătăţesc performanţa prin executarea
operaţiilor independente în paralel. Sistemele bazate pe paralelismul la nivelul
instrucţiunilor preiau un program convenţional într-un limbaj de nivel înalt scris
pentru procesoare secvenţiale şi utilizează tehnici statice (ale compilatorului) şi
dinamice (implementate în cursul execuţiei) pentru a exploata în mod automat
paralelismul implicit al programului. Aceste tehnici sunt în mare măsură
transparente pentru programatorii de aplicaţii, spre deosebire de paralelismul
tradiţional de tip multiprocesor, care necesită ca programatorii să rescrie
programele de aplicaţii. In prezent, prelucrarea paralelă la nivelul instrucţiunilor
rămâne singura metodă viabilă pentru creşterea continuă a performanţelor unui
sistem de calcul fără a rescrie în mod fundamental programele de aplicaţii.
Metodele obişnuite pentru a exploata paralelismul la nivelul instrucţiunilor
sunt prelucrarea superscalară, prelucrarea superpipeline şi cuvintele foarte lungi
de instrucţiuni (Very Long lnstruction Word — VLIW). O metodă mai nouă este
numită EPIC (Explicitly Parallel lnstruction Computing). Fiecare din aceste metode
încearcă iniţierea mai multor instrucţiuni în acelaşi ciclu de ceas.
7.4.7.1. Prelucrarea superscalară
Metoda de prelucrare superscalară se bazează pe paralelismul spaţial, care
constă în execuţia concurentă a mai multor operaţii în unităţi separate de
prelucrare. Această metodă realizează multiplicarea execuţiei instrucţiunilor într-un
ciclu de ceas prin lansarea mai multor instrucţiuni către diferite unităţi funcţionale.
Un procesor superscalar conţine unităţi multiple de execuţie, fiecare din acestea
fiind de obicei de tip pipeline, astfel încât acestea constituie un set de sisteme
pipeline de instrucţiuni independente. Unitatea de control a unui procesor
superscalar este proiectată pentru a încărca şi a decodifica mai multe instrucţiuni
în mod concurent. Aceasta poate lansa sau expedia până la k instrucţiuni
simultan către diferitele unităţi de execuţie, unde k poate avea o valoare egală cu
şase sau, utilizând tehnologia actuală, mai mare. Necesitatea de a prelucra mai
multe instrucţiuni simultan fără conflicte complică mult proiectarea unităţii de
control. Figura 7.17 prezintă într-o formă ideală diferenţele din punct de vedere al
posibilităţilor de prelucrare ale instrucţiunilor între trei organizări UCP: un procesor
secvenţial (care nu este de tip pipeline), un procesor de tip pipeline şi un procesor
superscalar, fiecare dintre acestea executând acelaşi şir de instrucţiuni I1 , I 2 , I 3 ,... .
Presupunând că fiecare instrucţiune necesită un număr total de cinci cicluri, putem
observa că un singur sistem pipeline (k = 1) cu cinci etaje oferă o creştere a vitezei
de 5 ori, în timp ce un sistem superscalar cu două instrucţiuni lansate simultan
(k = 2) oferă o creştere potenţială a vitezei de 10 ori. La începutul ciclului 15,
procesorul secvenţial a terminat numai două instrucţiuni, în timp ce procesorul de
tip pipeline şi cel superscalar au terminat 10, respectiv 20 de instrucţiuni. Mai mult,
procesorul superscalar a început prelucrarea instrucţiunilor I 21 la I 30 .
Fig. 7.17
După cum se ilustrează în figura 7.17, prezenţa a k unităţi de execuţie de tip
pipeline cu m etaje permite unui UCP superscalar să atingă factori de creştere a
vitezei care se apropie de k × m , comparativ cu un UCP care nu dispune de
paralelism la nivelul instrucţiunilor. Ocuparea a k sisteme pipeline necesită ca
UCP să încarce cel puţin k instrucţiuni în fiecare ciclu de ceas. Volumul ridicat al
traficului de instrucţiuni de la memoria de program la UCP necesită ca sistemul să
dispună de o memorie cache rapidă şi de dimensiuni mari, adesea sub forma unei
memorii cache de instrucţiuni (I-cache) pentru păstrarea programului, completată
cu o memorie cache de date (D-cache) pentru păstrarea operanzilor. Pentru
extragerea instrucţiunilor, există de obicei un buffer sau o coadă de instrucţiuni în
cadrul UCP, care păstrează instrucţiunile preîncărcate şi parţial decodificate.
Unitatea de control expediază instrucţiunile din bufferul de instrucţiuni către
diferitele unităţi de execuţie.
Unitatea de control a unui procesor superscalar este responsabilă pentru
determinarea momentului în care poate fi executată fiecare instrucţiune şi pentru
asigurarea accesului la resursele pe care instrucţiunea le necesită, cum sunt
operanzi din memorie, unităţi de execuţie şi registre UCP. Pentru aceasta,
unitatea de control trebuie să ţină cont de următorii factori:
• Tipul instrucţiunii: De exemplu, o instrucţiune de adunare în virgulă mobilă
trebuie expediată la o unitate de execuţie în virgulă mobilă şi nu la o unitate în
virgulă fixă.
• Disponibilitatea unităţii de execuţie: O instrucţiune poate fi expediată la o
unitate de execuţie de tip pipeline numai dacă nu vor rezulta coliziuni.
• Dependenţe de date: Pentru a evita conflictele la utilizarea registrelor,
trebuie satisfăcute restricţii privind dependenţele de date între operanzii
instrucţiunilor active.
• Dependenţe de control: Pentru a menţine performanţe ridicate, sunt
necesare tehnici pentru a reduce impactul instrucţiunilor de salt asupra eficienţei
sistemelor pipeline.
• Ordinea instrucţiunilor: Instrucţiunile trebuie să genereze rezultatele în
ordinea specificată de programul care se execută. Rezultatele pot fi însă calculate
intern într-o ordine diferită pentru a îmbunătăţi performanţele UCP.
Pentru păstrarea ordinii de execuţie a instrucţiunilor între care există
dependenţe şi pentru a asigura obţinerea unor rezultate valide, un procesor
superscalar trebuie să utilizeze un mecanism de control, care poate fi bazat pe
metoda tabelei de rezultate sau metoda Tomasulo. In practică, majoritatea
procesoarelor se bazează pe tehnica superscalară şi utilizează metoda tabelei de
rezultate.
Pentru a rezolva problema salturilor întârziate se utilizează diferite metode
arhitecturale, cum sunt memorii cache (sau buffere) pentru destinaţia saltului şi
execuţia speculativă, Execuţia speculativă implică predicţia direcţiei unui salt
dependent de date şi execuţia instrucţiunilor corespunzătoare. Cu seturi multiple
de registre virtuale şi utilizând metoda tabelei de rezultate, un procesor poate
urmări ambele căi ale unui salt şi poate alege şirul corect de instrucţiuni.
7.4.7.2. Prelucrarea superpipeline
Metoda superpipeline asigură performanţe ridicate prin suprapunerea
execuţiei unui număr mai mare de instrucţiuni într-un singur sistem pipeline de
instrucţiuni. Un procesor superpipeline conţine de obicei un sistem pipeline de
instrucţiuni cu un număr mai mare de etaje decât un sistem pipeline obişnuit. Cu
alte cuvinte, procesul de execuţie al unei instrucţiuni este divizat în etape cu
complexitate mai redusă. Prin creşterea numărului de etaje ale sistemului pipeline
de instrucţiuni este posibilă creşterea frecvenţei ceasului, deoarece această
frecvenţă depinde de întârzierea introdusă de etajul cel mai lent.
Metoda superpipeline are anumite avantaje. O singură unitate funcţională
necesită un spaţiu mai redus şi circuite mai simple comparativ cu structurile
bazate pe prelucrarea superscalară. Spaţiul suplimentar care rămâne disponibil
permite implementarea unor circuite speciale pentru obţinerea unor viteze mai
ridicate, memorii cache de dimensiuni mai mari şi căi de date cu un număr mai
mare de linii.
Majoritatea procesoarelor actuale utilizează metoda superpipeline. De
exemplu, sistemul pipeline al familiei de procesoare cu arhitectura Intel actuală
constă din 20 etaje, faţă de 5 la procesorul Intel Pentium şi 6 la procesorul Intel
Pentium cu extensiile MMX. Aceasta permite familiei de procesoare cu arhitectura
Intel actuală să ajungă la o frecvenţă cu aproximativ 50% mai ridicată faţă de
procesorul Pentium cu aceeaşi tehnologie de fabricaţie.
Alte exemple de arhitecturi superpipeline sunt procesoarele MIPS R4000 şi
R4400.
Să considerăm un procesor care divizează extragerea instrucţiunilor şi
accesul la memoria cache de date pentru a crea un sistem pipeline cu opt etaje.
Operaţiile executate în fiecare etaj al sistemului pipeline permit un ciclu de ceas cu
o frecvenţă dublă. Cele opt etaje ale sistemului pipeline sunt ilustrate în figura
7.18.
Fig. 7.18.
Faze corespunzătoare celor opt etaje ale sistemului pipeline sunt descrise
mai jos.
1. IF (Instruction Fetch, First Half): Logica de salt selectează o adresă de
instrucţiune şi începe extragerea acestei instrucţiuni din memoria cache de
instrucţiuni. In aceeaşi fază, bufferul de translatare (TLB) pentru instrucţiuni începe
translatarea adresei virtuale într-o adresă fizică.
2. IS (Instruction Fetch, Second Half): Extragerea instrucţiunii din memoria
cache de instrucţiuni şi translatarea adresei virtuale într-o adresă fizică sunt
terminate.
3. RF (Register Fetch): Instrucţiunea este decodificată şi marcajul memoriei
cache de instrucţiuni este comparat cu numărul cadrului de pagină obţinut din
bufferul de translatare pentru instrucţiuni. Operanzii necesari sunt încărcaţi din
setul de registre.
4. EX (Instruction Execution): UAL execută operaţia aritmetică sau logică
pentru instrucţiunile care operează cu registrele. Pentru instrucţiunile de încărcare
şi memorare, UAL calculează adresa virtuală a datelor. Pentru instrucţiunile de
salt, UAL determină dacă condiţia de salt este adevărată şi calculează adresa
virtuală a destinaţiei saltului.
5. DF (Data Fetch, First Half): Pentru instrucţiunile de încărcare şi memorare,
începe extragerea datelor din memoria cache de date şi translatarea adresei
virtuale într-o adresă fizică. Pentru instrucţiunile de salt, începe translatarea
adresei şi actualizarea TLB. Pentru instrucţiunile care operează cu registrele,
nu se execută nici o operaţie în timpul fazelor DF, DS şi TC.
6. DS (Data Fetch, Second Half): Pentru instrucţiunile de încărcare şi
memorare, extragerea datelor din memoria cache de date şi translatarea adresei
virtuale într-o adresă fizică sunt terminate. Pentru instrucţiunile de salt,
translatarea adresei şi actualizarea TLB sunt terminate.
7. TC (Tag Check): Pentru instrucţiunile de încărcare şi memorare, memoria
cache execută testarea marcajului. Adresa fizică din TLB este comparată cu
marcajul memoriei cache pentru a determina dacă există un succes sau un eşec
la accesul memoriei cache.
8. WB (Write Back): Pentru instrucţiunile care operează cu registrele,
rezultatul instrucţiunii este scris în setul de registre. Pentru instrucţiunile de salt, nu
se execută nici o operaţie în timpul acestei faze.
7.6. Controlul sistemelor pipeline
După cum se ştie există două tipuri de sisteme pipeline: statice şi dinamice.
Un sistem pipeline static poate executa o singură operaţie la un moment dat, în
timp ce un sistem pipeline dinamic poate executa mai multe operaţii. Controlul
secvenţierii operaţiilor prezentate pentru execuţie unui sistem pipeline este foarte
important pentru creşterea eficienţei acestuia. Dacă se iniţiază două operaţii care
necesită acelaşi etaj pipeline în acelaşi timp, apare o coliziune. In această
secţiune se prezintă o metodă de control pentru planificarea unui sistem pipeline.
7.6.1. Planificarea
Există mai multe metode pentru controlul planificării sistemelor pipeline.
înaintea descrierii unor asemenea metode, sunt definite conceptele de tabelă de
rezervare şi latenţă.
Tabele de rezervare. O tabelă de rezervare indică momentele în care
etajele unui sistem pipeline sunt utilizate pentru o anumită funcţie. Fiecare etaj
este reprezentat printr-o linie în tabela de rezervare. Fiecare linie este împărţită în
coloane, câte una pentru fiecare ciclu de ceas. Numărul de coloane indică
numărul total al unităţilor de timp necesare pentru execuţia unei anumite funcţii.
Pentru a indica faptul că un anumit etaj E este utilizat la momentul de timp ti este
plasat un semn „x” la intersecţia liniei şi coloanei corespunzătoare etajului şi
momentului de timp respectiv din tabelă.
Fig. 7.24
Figura 7.24 reprezintă o tabelă de rezervare pentru un sistem pipeline static
cu trei etaje. Momentele de timp t0 , t1 , t 2 , t3 şi t 4 indică cinci cicluri de ceas
consecutive. In exemplul considerat poziţia semnelor „x” indică faptul că, pentru a
produce rezultatul scontat datele de intrare trebuie să treacă succesiv prin etajele
1, 2, 2, 3 şi 1. Tabela de rezervare poate fi utilizată pentru a determina diferenţele
de timp între aplicarea datelor la intrare astfel încât să nu apară coliziuni.
Latenţa. Întârzierea, sau numărul unităţilor de timp (ciclurilor de ceas) care
separă aplicarea datelor la intrare, este numită latenţă. Va apare o coliziune dacă
două seturi de date de intrare sunt aplicate cu o latenţă egală cu distanţa între
două semne „x” într-o linie a tabelei de rezervare. De exemplu, în tabela din figura
7.24 există două semne „x” cu o distanţă 1 în a doua linie. Astfel, dacă al doilea
set de date este aplicat la intrare cu o latenţă de o unitate de timp după primul, va
apare o coliziune în etajul 2.
7.6.2. Planificarea sistemelor pipeline statice
Planificarea sistemelor pipeline statice începe prin crearea unui set de liste a
latenţelor interzise pe baza tabelelor de rezervare ale funcţiilor. Se obţin apoi
vectorii de coliziune şi se desenează diagrama stărilor.
Lista latenţelor interzise. Fiecare tabelă de rezervare cu două sau mai
multe semne „x” într-o anumită linie are una sau mai multe latenţe interzise, care,
în cazul în care nu sunt evitate, vor determina coliziunea datelor. Lista latenţelor
interzise F este o listă de numere întregi care corespund acestor latenţe interzise.
In cazul sistemelor pipeline statice, valoarea zero este considerată întotdeauna ca
o latenţă interzisă, deoarece nu este posibilă iniţierea a două taskuri în acelaşi
timp. Un element al acestei liste se poate determina calculând distanţa între două
semne „x” dintr-o anumită linie. De exemplu, lista latenţelor interzise a tabelei de
rezervare din figura 7.24 este (4, 1, 0).
Vectori de coliziune. Un vector de coliziune este un şir de cifre binare de
lungime N + 1 , unde N este latenţa interzisă maximă din lista latenţelor interzise.
Vectorul de coliziune iniţial, C , este creat din lista latenţelor interzise în felul
următor: fiecare element ci din C , pentru i = 1,..., N , este 1 dacă i este un element
al listei latenţelor interzise; în caz contrar, ci este zero. Valorile zero din vectorul
de coliziune indică latenţe permise, sau momente în care aplicarea datelor este
permisă.
Pentru lista precedentă a latenţelor interzise (4, 1, 0), vectorul de coliziune
este:
43 2 1 0
C = c4 c 3 c 2 c1 c 0
= (1 0 0 1 1)
In acest vector de coliziune, latenţele 2 şi 3 sunt permise, în timp ce latenţele
0, 1 şi 4 sunt interzise.
Diagrama stărilor. Diagramele de stări se utilizează pentru a indica diferitele
stări ale unui sistem pipeline pentru un interval de timp dat. După crearea unei
diagrame a stărilor, este mai simplă deducerea unei planificări a datelor de intrare
astfel încât să nu apară coliziuni.
Pentru a crea diagrama stărilor unui sistem pipeline, starea iniţială este
întotdeauna vectorul de coliziune iniţial. Dacă există valoarea 0 în poziţia ci atunci
aplicarea datelor este permisă după i unităţi de timp (cicluri de ceas).
Figura 7.25 reprezintă o diagramă de stări pentru sistemul pipeline din figura
7.24. Vectorul de coliziune 10011 reprezintă starea iniţială. Un nou set de date
poate fi aplicat la intrare după două sau trei cicluri de ceas ( i = 2 sau i = 3 ).
Fig. 7.25
De fiecare dată când este permisă aplicarea unui set de date, vectorul de
coliziune este deplasat la dreapta cu i poziţii, în poziţiile din stânga fiind introduse
zerouri. Aceasta corespunde cu trecerea unui număr de i unităţi de timp. Se
efectuează operaţia SAU logic între acest nou vector şi vectorul de coliziune iniţial
pentru a se genera un nou vector de coliziune şi o nouă stare. Această operaţie
este necesară deoarece aplicarea noilor date forţează o nouă constrângere
asupra stării curente a sistemului pipeline. De fiecare dată când se generează un
nou vector de coliziune de la un vector de coliziune existent în diagrama stărilor,
se trasează un arc între acestea. Arcul este etichetat cu latenţa i . Procesul de
generare a noilor vectori de coliziune continuă până când nu se mai pot genera
noi vectori.
In cadrul unei diagrame a stărilor, aplicarea unui set de date cu o întârziere
de N + 1 cicluri de ceas sau mai mare va determina reîntoarcerea la vectorul de
coliziune iniţial. Aceasta deoarece vectorul de coliziune curent este deplasat la
dreapta cu N + 1 poziţii şi sunt introduse zerouri în stânga. Dacă se efectuează
operaţia SAU logic între un vector de coliziune egal cu zero şi vectorul de coliziune
iniţial, rezultatul este vectorul de coliziune iniţial. In exemplul considerat arcele a2
şi a3 au latenţele i = 3 şi i ≥ 5 . Latenţa i ≥ 5 corespunde situaţiei în care noul set
de date de intrare se aplică după 5 sau mai multe cicluri de ceas. După o perioadă
de timp mai mare sau egala cu 5 cicluri de ceas, sistemul pipeline s-a golit şi este
evident că aplicarea unui nou set de date găseşte sistemul în faza iniţială.
Latenţa medie. Latenţa medie se determină pentru un anumit ciclu din
diagrama stărilor. Un ciclu într-o diagramă a stărilor este o secvenţă alternantă de
vectori de coliziune şi arce, C 0 , a1, C1,..., a n , C 0 , în care fiecare arc ai conectează
vectorul de coliziune Ci −1 cu Ci şi toţi vectorii de coliziune sunt distincţi cu excepţia
primului şi ultimului.
Pentru simplitate, un ciclu poate fi reprezentat printr-o secvenţă de latenţe
ale arcelor sale. De exemplu, în figura 7.25 ciclul C 0 , a1 , C1 , a 2 , C 0 , unde
C 0 = (10011) , C1 = (10111) , a1 este un arc de la C 0 la C1 , iar a2 este un arc de la
C1 , la C 0 , poate fi reprezentat ca ciclul C = (2,3) , unde 2 şi 3 sunt latenţele arcelor
a1 , respectiv a2 . Un arc poate avea mai multe latenţe. De exemplu arcul a2 are
latenţele 3 şi 5.
Latenţa medie pentru un ciclu se determină prin adunarea latenţelor arcelor
ciclului şi împărţirea sumei cu numărul total de arce din ciclu. De exemplu, în
figura 7.25 ciclul C = (2,3) are latenţa medie:
(2 + 3) / 2 = 2,5
Lungimea unui ciclu este dată de numărul arcelor din care este constituit.
Astfel C 0 , a1 , C1 , a 2 , C 0 are lungimea 2, iar ciclul C 0 , a3 , C 0 are lungimea 1.
Latenţa medie minimă. Un sistem pipeline poate avea mai multe latenţe
medii asociate cu diferite cicluri. Latenţa medie minimă este latenţa cu valoarea
cea mai mică din acestea. De exemplu, pentru diagrama din figura 7.25, latenţele
medii sunt următoarele:
(2 + 3)/2 = 2,5 din ciclul C 0 , a1 , C1 , a 2 , C 0
(2 + 5)/2 = 3,5 din ciclul C 0 , a1 , C1 , a 2 , C 0
3/1 = 3 din ciclul C 0 , a3 , C 0
5/1=5 din ciclul C 0 , a3 , C 0
Astfel, latenţa medie minimă (LMM) este 2,5. Deşi ciclul cu latenţa medie
minimă maximizează rata de transfer a sistemului pipeline, uneori se poate alege
un ciclu mai puţin eficient pentru a se reduce complexitatea implementării
circuitului de control. De exemplu, ciclul C = (2, 3), cu valoarea LMM egală cu 2,5,
necesită un circuit care contorizează două unităţi de timp, apoi trei unităţi de timp,
din nou două unităţi de timp şi aşa mai departe. Dacă însă este acceptabil să se
aplice un set de date de intrare la fiecare trei unităţi de timp, complexitatea
circuitului va fi mai redusă. De aceea, uneori este necesară determinarea latenţei
minime care poate fi utilizată pentru aplicarea datelor de intrare în toate situaţiile.
Această latenţă este numită latenţa minimă.
Pentru determinarea latenţei minime se caută în diagrama stărilor ciclul de
lungime 1, care are latenţa cea mai mică. In exemplul considerat acesta este ciclul
C 0 , a3 , C 0 cu latenţa 3. Astfel, latenţa minimă pentru acest sistem pipeline este 3.
7.6.3. Planificarea sistemelor pipeline dinamice
La planificarea unui sistem pipeline static, trebuie evitate doar coliziunile
între diferitele date de intrare pentru o anumită unitate funcţională. In cazul unui
sistem pipeline dinamic, este posibil ca diferitele seturi de date de intrare
necesitând unităţi funcţionale diferite să fie prezente în sistemul pipeline în acelaşi
timp. Pentru acest motiv, trebuie să se ia în considerare şi coliziunile între aceste
date. Ca şi în cazul sistemelor pipeline statice, planificarea sistemelor pipeline
dinamice începe cu determinarea unui set de liste a latenţelor interzise pe baza
tabelelor de rezervare ale funcţiilor. In continuare se obţin vectorii de coliziune, iar
în final se desenează diagrama stărilor.
Fig. 7.26
Listele latenţelor interzise. In cazul unui sistem pipeline dinamic, numărul
de liste ale latenţelor interzise este egal cu pătratul numărului de unităţi funcţionale
care partajează sistemul pipeline. In figura 7.26, numărul de unităţi funcţionale
este 2, notate cu A şi B ; astfel, numărul de liste ale latenţelor interzise este 4,
acestea fiind notate cu AA , AB , BA şi BB . De exemplu, dacă lista AB conţine
valoarea întreagă d , atunci un set de date care necesită unitatea funcţională B nu
poate fi aplicat la intrarea sistemului pipeline la momentul t + d , unde t reprezintă
momentul de timp la care setul de date necesitând unitatea funcţională A a fost
aplicat la intrare. Deci,
AA = (3,0) , AB = ( 4,2,1,0) , BA = (2,1,0) , BB = (3,2,0)
Vectori de coliziune şi matrice de coliziune. Vectorii de coliziune se
determină în acelaşi mod ca şi pentru un sistem pipeline static; 0 indică o latenţă
permisă, iar 1 indică o latenţă interzisă. Pentru exemplul precedent, vectorii de
coliziune sunt următorii:
C AA = (01001) C BA = (00111)
C AB = (10111) C BB = (01101)
Vectorii de coliziune pentru unitatea funcţională A formează matricea de
coliziune M A :
C 
M A =  AA 
 C AB 
Vectorii de coliziune pentru unitatea funcţională B formează matricea de
coliziune M B :
C 
M B =  BA 
 C BB 
Pentru vectorii de coliziune din exemplul precedent, matricele de coliziune
sunt următoarele:
 01001
  
00111
MA =  MB = 
 
 10111  
01101
Diagrama stărilor. Diagrama stărilor pentru un sistem pipeline dinamic este
construită în acelaşi mod ca şi pentru un sistem pipeline static. Diagrama rezultată
este mult mai complexă decât diagrama stărilor unui sistem pipeline static, datorită
numărului mai mare de coliziuni potenţiale.
Ca un exemplu, considerăm diagrama stărilor din figura 7.27. Pentru început,
ne referim la matricea de coliziune M A . Există două tipuri de coliziuni: A cu A
(vectorul de sus) sau A cu B (vectorul de jos). Dacă se alege prima latenţă
permisă pentru vectorul C AA (în acest caz, 1), întreaga matrice este deplasată la
dreapta cu o poziţie, în poziţiile din stânga fiind introduse zerouri. Apoi se execută
o operaţie SAU logic între noua matrice şi matricea de coliziune iniţială M A ,
deoarece latenţele interzise originale pentru unitatea funcţională A trebuie luate în
considerare şi în continuare.
Fig. 7.27
Dacă se alege prima latenţă permisă pentru vectorul C AB din matricea M A
(în acest caz, 3), întreaga matrice este deplasată la dreapta cu trei poziţii, în
poziţiile din stânga fiind introduse zerouri. Apoi se execută o operaţie SAU logic
între noua matrice şi matricea de coliziune iniţială pentru unitatea funcţională B ,
deoarece coliziunile originale pentru unitatea funcţională B sunt încă posibile şi
trebuie luate în considerare. Operaţia de deplasare şi operaţia SAU logic continuă
până când se iau în considerare toate latenţele posibile şi diagrama stărilor va fi
completă.

Cap. 8. Arhitecturi RISC


8.1. Introducere
In general, arhitecturile calculatoarelor au evoluat progresiv spre o
complexitate mai ridicată ca, de exemplu un număr mai mare de instrucţiuni, un
număr mai mare de moduri de adresare, o putere de calcul mai ridicată a
instrucţiunilor individuale, registre mai specializate. Calculatoarele care se
încadrează în asemenea tendinţe sunt numite calculatoare cu set complex de
instrucţiuni (CISC - Complex Instruction Set Computer).
S-a constatat la un moment dat că adăugarea unei instrucţiuni complexe
la un set de instrucţiuni afectează eficienţa şi costul procesorului. Efectele unei
asemenea instrucţiuni trebuie evaluate înainte ca aceasta să fie adăugată la
setul de instrucţiuni. Unele din instrucţiunile puse la dispoziţie de procesoarele
CISC sunt utilizate rareori de compilatoare. Conceptul de bază de a nu se
adăuga instrucţiuni utilizate rar la setul de instrucţiuni reprezintă un concept
inovativ al arhitecturilor de calculatoare, numit calculator cu set redus de
instrucţiuni (RISC - Reduced Instruction Set Computer). Filozofia de proiectare
a arhitecturilor RISC este de a se adăuga la setul de instrucţiuni numai acele
instrucţiuni care determină un câştig de performanţă.
Caracteristicile comune ale majorităţii acestor calculatoare sunt
următoarele:
- Un set de instrucţiuni limitat şi simplu;
- Un număr mare de registre generale sau memorii cache aflate în aceeaşi
capsulă cu procesorul;
- Un compilator care maximizează utilizarea registrelor şi minimizează
astfel accesurile la memoria principală;
- Accentul pus pe optimizarea sistemului pipeline de instrucţiuni.
8.2. Cauze ale complexităţii arhitecturale crescute
Există mai multe motive ale tendinţei spre o complexitate progresivă mai
ridicată a arhitecturilor de calculatoare. Acestea cuprind facilitarea utilizării
limbajelor de nivel înalt, migrarea funcţiilor de la implementarea prin software la
implementarea prin hardware şi compatibilitatea în sus.
Facilitarea utilizării limbajelor de nivel înalt. Pe parcursul anilor, mediul
de programare a evoluat de la programarea în limbaj de asamblare la
programarea în limbaje de nivel înalt, astfel încât proiectanţii au prevăzut
instrucţiuni mai puternice pentru a facilita codificarea eficientă a programelor
scrise în limbaje de nivel înalt. Aceste instrucţiuni au determinat nu numai
creşterea dimensiunii setului de instrucţiuni ci şi creşterea complexităţii
acestuia, datorită puterii de calcul relativ ridicate a instrucţiunilor.
Migrarea funcţiilor de la implementarea prin software la
implementarea prin hardware. O instrucţiune care este implementată prin
hardware va fi mai eficientă decât una realizată printr-o secvenţă de instrucţiuni
mai simple, datorită numărului mare de accesuri la memorie şi a diferenţei
dintre vitezele UCP şi ale memoriei. Pentru a creşte viteza de procesare a
calculatoarelor, a avut loc un fenomen de migrare a funcţiilor de la
implementarea prin software la cea prin firmware şi de la implementarea prin
firmware la cea prin hardware. (Firmware reprezintă o secvenţă de
microinstrucţiuni.) Această migrare a implementării funcţiilor din domeniul
software în domeniul hardware creşte dimensiunea setului de instrucţiuni,
rezultând o complexitate globală crescută a calculatoarelor.
Compatibilitatea în sus. Compatibilitatea în sus este utilizată adesea de
către producători ca o strategie de marketing cu scopul de a prezenta
calculatoarele lor ca fiind mai performante decât alte modele existente. Ca
rezultat al acestei strategii de marketing, uneori producătorii cresc numărul de
instrucţiuni şi puterea de calcul a acestora, indiferent de utilizarea efectivă a
acestui set complex de instrucţiuni. Compatibilitatea în sus este un mod de a
îmbunătăţi un sistem prin adăugarea unor facilităţi noi şi, de obicei, mai
complexe. Ca rezultat, noul set de instrucţiuni este un superset al celui vechi.
8.3. Avantajele arhitecturilor RISC
Există totuşi unele criterii care reprezintă obiective universal acceptate de
către proiectanţii de calculatoare pentru toate sistemele:
1. Maximizarea vitezei de execuţie sau minimizarea timpului de execuţie.
2. Minimizarea costului de proiectare.
O posibilitate de a îndeplini primul obiectiv constă în a îmbunătăţi
tehnologia componentelor, obţinând funcţionarea acestora la frecvenţe mai
ridicate. Viteza mărită poate fi obţinută prin minimizarea numărului mediu al
ciclurilor de ceas pe instrucţiune şi/sau execuţia simultană a mai multor
instrucţiuni. Pentru a îndeplini ambele obiective, proiectanţii arhitecturilor RISC
originale s-au concentrat asupra aspectului implementării circuitelor VLSI. Ca
rezultat al unui număr mai redus de instrucţiuni, moduri de adresare şi formate
de instrucţiuni, s-a obţinut un circuit relativ simplu şi de dimensiuni reduse
pentru unitatea de control. Această relativă reducere a dimensiunii şi
complexităţii circuitelor VLSI conduce la anumite avantaje faţă de arhitecturile
CISC. Acestea sunt prezentate în continuare.
Scopul principal al tehnologiei VLSI este de a implementa întregul
procesor într-o singură capsulă. Aceasta va reduce în mod semnificativ
întârzierea majoră de transmitere a semnalelor de la un circuit integrat la altul.
Arhitecturile cu o complexitate mai mare (set mai complex de instrucţiuni, mai
multe moduri de adresare, formate variabile de instrucţiuni etc.) necesită o
logică mai complexă pentru încărcarea instrucţiunilor, decodificare şi execuţie.
Dacă procesorul este microprogramat, este necesar un microprogram complex,
rezultând o memorie de microprogram de dimensiuni mai mari. Prin urmare,
dacă o arhitectură CISC este dezvoltată utilizând tehnologia VLSI, o parte
substanţială a suprafeţei circuitului poate fi ocupată de memoria de
microprogram. Mărimea suprafeţei circuitului necesară pentru unitatea de
control a unei arhitecturi CISC poate varia de la 40% la 60%, în timp ce numai
10% a suprafeţei este necesară în cazul unei arhitecturi RISC. Suprafaţa
rămasă în cazul unei arhitecturi RISC poate fi utilizată pentru alte componente,
cum sunt memorii cache în aceeaşi capsulă şi seturi mai mari de registre, prin
care performanţele procesorului pot fi îmbunătăţite.
Avantajele arhitecturilor RISC se referă la:
1. Viteza de calcul;
2. Implementarea în circuite VLSI;
8. Timpul de proiectare;
4. Facilitarea utilizării limbajelor de nivel înalt.
1. In ceea ce priveşte viteza de calcul, arhitecturile RISC sunt mai potrivite
pentru utilizarea sistemelor pipeline de instrucţiuni. Aceste arhitecturi
maximizează rata de transfer a sistemului pipeline prin faptul că au o
dimensiune uniformă şi o durată egală a execuţiei pentru majoritatea
instrucţiunilor. Aceste caracteristici reduc perioadele de inactivitate în cadrul
sistemului pipeline.
2. Implementarea în circuite VLSI se referă la faptul că unitatea de control
a arhitecturilor RISC este implementată prin hardware. Un sistem cu o unitate
de control cablată va fi, în general, mai rapid decât unul microprogramat. In
plus, un număr mare de registre şi memoriile cache în cadrul capsulei vor
reduce numărul accesurilor la memorie. Datele mai frecvent utilizate pot fi
păstrate în registre. Registrele pot păstra de asemenea parametrii care trebuie
transmişi altor proceduri. Din cauza progresului tehnologiei VLSI, multe
microprocesoare comerciale au propria memorie cache în cadrul capsulei.
Această memorie cache are, de obicei, o dimensiune mai redusă decât
memoria cache de pe placă şi reprezintă primul nivel al memoriilor cache.
Memoria cache de pe placă, care este apropiată de procesor, reprezintă al
doilea nivel al memoriilor cache. In general, aceste două nivele de memorii
cache îmbunătăţesc performanţele comparativ cu cazul utilizării unui singur
nivel de memorie cache. Mai mult, memoria cache din fiecare nivel poate fi
organizată ca o ierarhie de memorii cache. In sfârşit, uneori fiecare memorie
cache din nivelele superioare este divizată în două memorii cache: o memorie
cache de instrucţiuni şi o memorie cache de date. Procesoarele care au
memorii cache separate pentru instrucţiuni şi date sunt numite arhitecturi
Harvard, după calculatorul Harvard Mark I. Utilizarea a două memorii cache,
una pentru instrucţiuni şi una pentru date, poate îmbunătăţi în mod considerabil
timpul de acces şi, în consecinţă, îmbunătăţeşte performanţele unui procesor, în
special al unuia care utilizează în mod extensiv tehnica pipeline, cum este un
procesor RISC.
3. Un alt avantaj al arhitecturilor RISC este că acestea necesită o
perioadă mai scurtă de proiectare. Timpul necesar pentru proiectarea unei noi
arhitecturi depinde de complexitatea arhitecturii. Timpul de proiectare este mai
lung pentru arhitecturile complexe (CISC). In cazul unei arhitecturi RISC, timpul
necesar pentru testarea şi depanarea circuitelor rezultate este mai redus,
deoarece nu se utilizează microprogramarea şi dimensiunea unităţii de control
este redusă. In cazul unei arhitecturi mai puţin complexe, posibilitatea erorilor
de proiectare este mai redusă. Deci, arhitecturile RISC au avantajul unor costuri
de proiectare mai reduse şi al unei fiabilităţi de proiectare mai ridicate.
4. In sfârşit, arhitecturile RISC oferă anumite caracteristici care facilitează
în mod direct operaţiile obişnuite ale limbajelor de nivel înalt. Mediul de
programare s-a modificat de la programarea în limbaj de asamblare la
programarea în limbaje de nivel înalt, astfel încât arhitecturile trebuiau să
faciliteze această tendinţă, prin instrucţiuni suplimentare care sunt puternice din
punct de vedere funcţional şi apropiate semantic de caracteristicile limbajelor de
nivel înalt. Totuşi, încărcarea unui calculator cu un număr mare de facilităţi
pentru limbajele de nivel înalt poate transforma o arhitectură RISC într-o
arhitectură CISC. De aceea, este de dorit să se investigheze frecvenţa utilizării
facilităţilor pentru limbajele de nivel înalt prin rularea unei serii de programe
benchmark scrise în limbaje de nivel înalt. Pe baza acestor observaţii, sunt
adăugate numai acele facilităţi la setul de instrucţiuni care sunt utilizate
frecvent şi produc o îmbunătăţire a performanţelor.
8.4. Utilizarea unui număr mare de registre
Un grup de cercetători de la Universitatea California din Berkeley, condus
de Patterson şi Sequin, a studiat caracteristicile mai multor programe tipice
Pascal şi C şi a descoperit că, dintre tipurile de instrucţiuni ale limbajelor de
nivel înalt, apelurile de proceduri şi revenirile din acestea consumă cel mai mult
timp. Un calculator CISC cu un set redus de registre necesită un timp ridicat
pentru gestionarea apelurile de proceduri şi revenirile din acestea, din cauza
necesităţii de a salva registrele la un apel şi de a le reface la revenire, ca şi din
cauza necesităţii de a transmite parametri şi rezultate la şi de la procedura
apelată. Această problemă este mai acută la procesoarele RISC, deoarece
instrucţiunile complexe trebuie implementate prin subrutine utilizând
instrucţiunile disponibile. De aceea, unul din principiile de proiectare ale
arhitecturilor RISC este de a pune la dispoziţie un mijloc eficient de gestiune a
mecanismului de apel al procedurilor şi de revenire din acestea.
Aceasta conduce la necesitatea existenţei unui număr mare de registre
care pot fi utilizate pentru mecanismul de apel şi revenire. In plus, pentru
îmbunătăţirea eficienţei, echipa din Berkeley a implementat conceptul
ferestrelor suprapuse de registre. In cazul acestui concept, setul de registre
este împărţit în grupe de registre numite ferestre. Un anumit grup de registre
este desemnat pentru a fi utilizat ca registre globale şi este accesibil oricărei
proceduri în orice moment. Pe de altă parte, fiecărei proceduri i se asignează o
fereastră separată în cadrul setului de registre. Prima fereastră din setul de
registre, baza ferestrei, este adresată de pointerul ferestrei curente (Current
Window Pointer - CWP), plasat de obicei în registrul de stare al UCP. Ferestrele
de registre pot fi utile pentru transmiterea eficientă a parametrilor între
procedura apelantă şi cea apelată prin ferestre parţial suprapuse de registre.
Parametrii pot fi transmişi fără a modifica CWP prin plasarea acestora în partea
care se suprapune din cele două ferestre. Prin această suprapunere parametrii
doriţi vor fi accesibili atât pentru procedura apelantă, cât şi pentru cea apelată.
Ferestrele de registre sunt utilizate atât la arhitecturile CISC, cât şi la cele RISC,
dar unitatea de control a unei arhitecturi CISC nu permite un spaţiu suficient
pentru un număr mare de registre.
Pentru explicarea conceptului ferestrelor suprapuse de registre,
considerăm un calculator RISC cu 100 de registre. Dintre aceste registre, cele
între 0 şi 9 sunt utilizate ca registre globale pentru memorarea variabilelor
partajate de toate procedurile. Ori de câte ori este apelată o procedură, în plus
faţă de registrele globale, se alocă 20 de registre suplimentare pentru această
procedură. Acestea cuprind 5 registre numite registre de intrare, pentru
păstrarea parametrilor care sunt transmişi de procedura apelantă, 10 registre
numite registre locale, pentru păstrarea variabilelor locale şi 5 registre numite
registre de ieşire, pentru păstrarea parametrilor care trebuie transmişi unei alte
proceduri. Figura 8.1 ilustrează registrele alocate pentru trei proceduri X, Y şi Z.
De notat că procedurile X şi Y (Y şi Z) partajează acelaşi set de registre pentru
parametrii de ieşire, respectiv parametrii de intrare.
Fig. 8.1
In concluzie, una din ideile principale ale arhitecturii RISC este de a
simplifica toate aspectele arhitecturale ale proiectării unui calculator, astfel încât
implementarea acestuia poate fi realizată mai eficient. Obiectivul unei arhitecturi
RISC este de a include instrucţiuni simple şi esenţiale în setul de instrucţiuni al
calculatorului.
8.5. Caracteristici ale arhitecturilor RISC
In general, o arhitectură RISC are următoarele caracteristici:
1. Majoritatea instrucţiunilor accesează operanzii din registre, cu excepţia
unui număr redus dintre ele, cum sunt instrucţiunile LOAD şi STORE, care
accesează memoria. Cu alte cuvinte, o arhitectură RISC este un calculator de
tip load/store.
2. Execuţia majorităţii instrucţiunilor necesită un singur ciclu de ceas, cu
excepţia unui număr redus dintre ele, cum sunt instrucţiunile LOAD şi STORE.
Totuşi, în prezenţa memoriilor cache aflate în aceeaşi capsulă, chiar şi
instrucţiunile LOAD şi STORE pot fi executate, în medie, într-un ciclu.
3. Unitatea de control este cablată. Deci, arhitecturile RISC nu sunt
microprogramate. Codul generat de compilator este executat direct prin
hardware şi nu este interpretat prin microprogramare.
4. Există un număr redus de formate ale instrucţiunilor (adesea mai mic
decât 4).
5. UCP are un număr mare de registre. O alternativă la un număr mare
de registre este amplasarea unei memorii cache în aceeaşi capsulă.
Producătorii procesoarelor actuale au amplasat memoria cache în aceeaşi
capsulă cu procesorul pentru a asigura o viteză mai ridicată. Deoarece spaţiul
din capsula procesorului este limitat, în această capsulă poate fi amplasată doar
o memorie cache de dimensiuni reduse. Pe lângă această memorie cache, se
poate amplasa o memorie cache de dimensiuni mari în afara capsulei. In
general, se utilizează o ierarhie de memorii cache. Toate datele de la nivelul
superior (memoria cache din cadrul capsulei) sunt prezente la nivelele inferioare
(memoriile cache din afara capsulei), astfel încât, după o lipsă în memoria
cache, memoria cache din cadrul capsulei poate fi reîncărcată dintr-o memorie
cache de la un nivel inferior, în locul efectuării unui acces la memoria principală.
6. Compilatorul are o complexitate ridicată. De exemplu, compilatorul
trebuie să se ocupe de salturile întârziate. Este posibil să se îmbunătăţească
performanţele sistemului pipeline prin rearanjarea automată a instrucţiunilor din
cadrul unui program astfel încât instrucţiunile de salt să apară mai târziu decât
se intenţiona iniţial.
8. Există relativ puţine instrucţiuni (adesea, mai puţin de 150) şi foarte
puţine moduri de adresare (adesea mai puţin de 4).
9. Arhitecturile RISC facilitează operaţiile limbajelor de nivel înalt printr-o
alegere judicioasă a instrucţiunilor şi prin utilizarea compilatoarelor care
optimizează codul.
10. Arhitecturile RISC utilizează sistemele pipeline de instrucţiuni şi
metode pentru rezolvarea problemei salturilor, cum sunt tehnicile de
preîncărcare multiplă şi de predicţie a salturilor.
8.6. Comparaţie între arhitecturile RISC şi CISC
In general, timpul necesar unui procesor pentru a realiza execuţia unui
program poate fi influenţat de trei factori:
1. Numărul de instrucţiuni din program;
2. Numărul mediu de cicluri de ceas necesare pentru execuţia unei
instrucţiuni;
3. Durata ciclului de ceas.
Arhitecturile CISC reduc numărul de instrucţiuni necesare într-un program
prin furnizarea unor instrucţiuni speciale care pot executa operaţii complexe.
Spre deosebire de acestea, arhitecturile RISC reduc numărul mediu al ciclurilor
de ceas necesare pentru execuţia unei instrucţiuni. Atât arhitecturile CISC cât şi
cele RISC profită de îmbunătăţirile tehnologiei circuitelor integrate pentru a
reduce durata ciclului de ceas.
Arhitecturile RISC sunt calculatoare de tip load/store; acestea pot obţine
un nivel ridicat al concurenţei prin separarea execuţiei instrucţiunilor de
încărcare şi memorare de alte instrucţiuni. Arhitecturile CISC nu pot obţine
întotdeauna acelaşi nivel al concurenţei din cauza setului lor de instrucţiuni de
tip memorie-registru.
Majoritatea aspectelor negative ale arhitecturilor RISC sunt direct legate
de aspectele lor pozitive. Din cauza instrucţiunilor simple, performanţele unei
arhitecturi RISC depind de eficienţa compilatorului. De asemenea, datorită
numărului mare de registre, alocarea registrelor este mai complexă, crescând
astfel complexitatea compilatorului. De aceea, principalul dezavantaj al unei
arhitecturi RISC este necesitatea de a scrie un compilator eficient. In general,
timpul de dezvoltare al sistemelor software pentru calculatoarele RISC este mai
lung decât cel pentru calculatoarele CISC. Un alt dezavantaj este că anumite
instrucţiuni CISC sunt echivalente cu două sau trei instrucţiuni RISC, ceea ce
determină ca programele RISC să fie mai lungi. Deci, considerând avantajele
ambelor arhitecturi CISC şi RISC, proiectarea unui procesor RISC poate fi
îmbunătăţită prin utilizarea unora din principiile CISC care au fost dezvoltate şi
îmbunătăţite de-a lungul anilor.
|Cap.9. Introducere în Multithreading, Superthreading şi Hyperthreading
9.1. Procese şi fire de execuţie
Un sistem de operare execută la un moment dat o multitudine de programe.
Utilizatorul poate să ruleze în acelaşi timp un editor de texte, un browser de
Internet şi un player audio. Toate aceste programe lansate în execuţie poartă
numele de procese şi acestea sunt executate într-o manieră secvenţială,
concurând pentru folosirea resurselor comune ale sistemului de calcul precum
procesor, memorie sau hard-disk.
Un proces este constituit din unul sau mai multe segmente de cod şi
segmente de date mapate într-un spaţiu virtual de adresare. Fiecare proces
deţine un număr de resurse alocate de către sistemul de operare, cum ar fi
fişiere deschise sau zone de memorie alocate dinamic. Resursele alocate
procesului sunt eliberate la terminarea execuţiei procesului. Un aspect
fundamental al proceselor este faptul că două procese diferite au întotdeauna
spaţii de adresă distincte, fiecare rulând ca şi când toată memoria ar fi a sa.
Astfel procesele sunt izolate între ele şi nu pot accesa în mod direct datele
celorlalte procese.
Sistemul de operare şi sistemul hardware cooperează pentru a realiza
mecanismul de multitasking, prin care controlul UCP este comutat pe rând între
diverse programe.
Un fir de execuţie este unitatea de execuţie a unui proces. Acesta poate fi
văzut ca un program în execuţie fără spaţiu de adresă propriu. Firul de execuţie
rulează în cadrul unui proces partajând spaţiul de adresă al acestuia. Fiecărui fir
de execuţie i se asociază o secvenţa de instrucţiuni, un set de registri CPU şi o
stiva. Procesul nu executa instrucţiuni, acesta fiind spaţiu de adresare comun
pentru unul sau mai multe fire de execuţie. Firele de execuţie sunt cele care
execută instrucţiunile.
Fiecare proces are cel puţin un fir de execuţie. Uneori însă apare nevoia să
lucrăm în paralel asupra aceloraşi date şi atunci putem crea mai multe fire de
execuţie în cadrul aceluiaşi proces. De exemplu, în cazul editorului de texte de
care s-a amintit la început, atât utilizatorul cât şi task-ul care salvează o copie
de siguranţă lucrează asupra aceloraşi date, deci vom avea două fire de
execuţie în cadrul aceleiaşi aplicaţii. Cu toate că firele de execuţie partajează
spaţiul de adresă al unui proces, unele resurse sunt individuale, cum ar fi stiva,
regiştrii şi contorul program. Aceasta permite mai multor fire de execuţie din
cadrul aceluiaşi proces să urmeze căi diferite de instrucţiuni.
Considerăm pentru început un program format dintr-un singur fir de
execuţie. In figura 9.1. se prezintă funcţionarea unei CPU cu un singur fir de
execuţie (single-thread CPU).
In CPU au fost evidenţiate unitatea de alimentare cu instrucţiuni formată
din patru sisteme pipeline şi unitatea de execuţie formată din şapte sisteme
pipeline funcţionând în paralel.
Dreptunghiurile colorate din RAM reprezintă instrucţiunile a patru programe
diferite aflate în curs de execuţie. După cum se poate vedea, în acest moment
sunt executate numai instrucţiunile programului „roşu”, în timp ce celelalte
programe îşi aşteaptă rândul.
După cum se observă din această figură, sistemele pipeline conţin o
mulţime de etaje goale, numite pipeline bubbles (bule), care apar deoarece, din
motivele prezentate anterior, CPU nu poate asigura alimentarea continuă a
sistemelor pipeline.
Fig. 9.1.
Evident, această situaţie reduce eficienţa procesorului. Astfel, deşi unitatea
de alimentare cu instrucţiuni, poate emite patru instrucţiuni în fiecare ciclu de
ceas, în situaţia prezentată în figura 9.1, aceasta emite doar două instrucţiuni şi
numai într-un singur ciclu reuşeşte să emită trei instrucţiuni.
Pentru un program lansat în execuţie se utilizează termenul de „proces”.
Fiecărui proces i se asociază un context de execuţie. Prin context de execuţie
se înţeleg toate informaţiile care descriu la un moment dat starea curentă de
execuţie a procesului (de exemplu conţinutul registrelor CPU, program counter,
indicatorii de condiţie, etc.).
Proceselor sau firelor de execuţie li se alocă pe rând câte o cuantă de timp
pentru a fi executate. La momentul potrivit un anumit proces (sau fir de
execuţie) este eliminat din procesor, după ce contextul sau a fost salvat şi un alt
proces (sau fir de execuţie) este adus în procesor. Acţiunea de salvare a
contextului vechiului proces şi încărcarea contextului noului proces se numeşte
comutarea contextului. Comutarea contextului pentru un proces format din mai
multe fire de execuţie, evident, va dura mai mult decât comutare unui singur fir
de execuţie, dar oricum, această operaţie iroseşte un număr de cicluri de ceas.
O modalitate de a reduce numărul de comutări ale contextelor şi de a
asigura mai mult timp CPU pentru fiecare proces este aceea de a construi un
sistem care să poată executa mai multe procese în acelaşi timp. Modul
convenţional de a realiza acest lucru este de a adăuga sistemului încă un CPU,
obţinând un sistem multiprocesor (SMP). Intr-un SMP sistemul de operare
poate programa ca două procese să fie executate exact în acelaşi timp, fiecare
proces fiind executat pe un CPU diferit. Evident că nu i se permite niciunui
proces să monopolizeze CPU şi în acest caz fiecărui proces fiindu-i alocată o
cuantă de timp CPU. Rezultatul final este totuşi că este disponibil un timp de
execuţie mai mare astfel încât într-un, anumit interval de timp, fiecare proces
aşteaptă mai puţin până obţine acces la CPU.
Fig. 9.2
In figura 9.2 este prezentat un single-thread SMP. După cum se constată în
acest moment sunt executate simultan programul „roşu” şi programul „galben”,
fiecare pe câte un procesor. După ce cuanta de timp alocată fiecărui program
expiră, contextul lor este salvat, codul şi datele acestora sunt eliminate din CPU
şi două noi procese vor fi pregătite pentru execuţie.
Se observă din figura 9.2 că, deşi acest sistem poate executa două
procese simultan numărul de bule (pipeline bubbles) s-a dublat, fiecare din cele
două procesoare contribuind cu la aceasta cu gradul sau de ineficienţă.
9.2. Multithreading şi superthreading
O metodă de a creşte performanţele procesorului constă în utilizarea
tehnicii superthreading. Un procesor care utilizează această tehnică se numeşte
procesor multithreaded, şi un astfel de procesor este capabil ca la un moment
dat să execute mai mult de un singur fir. Figura 9.3 explică cum funcţionează
metoda superthreading.
Fig.9.3
După cum se observă din această figură, deoarece procesorul execută
instrucţiuni din ambele fire de execuţie, atât unitatea de alimentare cât şi
unitatea de execuţie au mai puţine etaje neutilizate (mai puţine pipeline bublles).
Săgeţile din stânga arată că, într-un anumit ciclu de ceas, etajele pipeline conţin
instrucţiuni numai dintr-un singur fir de execuţie.
Pentru a înţelege cum funcţionează un procesor multithreaded să analizăm
cum funcţionează CPU din figura 9.3. In cazul procesoarelor prezentate anterior
unitatea de alimentare cu instrucţiuni conţinea la un moment dat un singur fir de
execuţie, care apoi, când se consuma cuanta de timp alocată, era comutat
pentru a face loc altui fir de execuţie.
In acest caz unitatea de alimentare cu instrucţiuni poate furniza în fiecare
ciclu de ceas patru instrucţiuni către oricare dintre cele şapte unităţi funcţionale.
Toate aceste patru instrucţiuni trebuie însă să provină din acelaşi fir de
execuţie. Ca efect fiecare fir de execuţie este limitat la o cuantă de timp, care
acum constă dintr-un singur ciclu de ceas.
Procesoarele multithreaded pot sigura atenuarea unor probleme de latenţă
introduse de încărcarea operanzilor din memorie. De exemplu să consideram
cazul procesorului din figura 9.3, care execută două fire de execuţie, pe cel roşu
şi pe cel galben. Dacă firul roşu necesită încărcarea unei date şi această dată
nu este prezentă în memoria cache, acest fir va fi întârziat multe cicluri de ceas
aşteptând data să sosească. Intre timp, totuşi, procesorul va executa firul
galben, menţinând astfel pipeline-ul plin.
Deşi procedeul superthreading poate reduce substanţial întârzierile
datorate latenţei sistemului de memorie, nu are totuşi efectul scontat în cazul
unui paralelism redus la nivelul instrucţiunilor dintr-un anume fir de execuţie.
Dacă, la un moment dat, blocul de comandă reuşeşte să găsească în firul roşu
numai două instrucţiuni care pot fi încărcate în paralel în unitatea de execuţie,
celelalte două etaje ale unităţii de încărcare vor rămâne neutilizate.
9.3. Simultaneous multithreading
Această problemă este rezolvată de procedeul numit simultaneous
multithreading (SMT) sau cum l-a denumit Intel hyper-threading. Procedeul
hyper-threading elimină restricţia procedeului superthreading de a încărca într-
un anumit ciclu de ceas instrucţiuni care aparţin numai unui singur fir de
execuţie. Această idee este prezentată în figura 9.9.
Fig. 9.4
După cum se poate constata atât unitatea de alimentare cu instrucţiuni cât
şi unitatea funcţională sunt utilizate mult mai eficient. Comparând cu sistemul
multiprocesor din figura 9.2, se constată imediat că cele două fire de execuţie
care ocupau fiecare câte un procesor sunt acum comasate într-un singur
procesor. In acest mod toate etajele unităţii de alimentare cu instrucţiuni sunt
ocupate iar unităţile de execuţie sunt acum mult mai eficient utilizate. De fapt
procesorul hyper-hreading acţionează ca şi cum ar avea două CPU. Evident
exemplul prezentat, în care cele două fire de execuţie sunt în totalitate
complementare, este pur didactic, însă ne permite să ne realizăm eficienţa
procedeului hyper-threading.
Din punct de vedere al sistemului de operare un procesor SMT este
compus din două sau mai multe procesoare logice şi firele de execuţie pot fi
programate să fie executate de oricare din cele două sau mai multe procesoare
logice, exact ca într-un sistem multiprocesor.
Puterea sistemului hyper-threading constă în faptul că permite maximum
de flexibilitate la încărcarea etajelor unităţii de alimentare cu instrucţiuni,
îmbunătăţind astfel gradul de utilizare al resurselor existente. Dacă comparăm
diagramele din figurile 9.2. şi 9.4. constatăm că ambele sisteme execută
aceeaşi cantitate de muncă dar sistemul hyper-threading utilizează mai puţine
resurse şi are mai puţini cicli de ceas pierduţi în comparaţie cu sistemul SMP.
Pentru a înţelege mai bine cum acţionează în practică un sistem hyper-
threading să considerăm următorul exemplu: Să presupunem unitatea de
programare a extras toate instrucţiunile care pot fi executate în paralel din firul
de execuţie roşu şi că acestea sunt numai două. Aceasta înseamnă că în
următorul ciclu de ceas vor fi încărcate numai două instrucţiuni. Trebuie să
remarcăm că acesta este un scenariu foarte comun deoarece cercetările au
stabilit că media instrucţiunilor paralele care pot fi extrase din cele mai multe
coduri este de 2,5 pe ciclu. Pentru acest motiv, Pentium 4, la fel ca şi multe alte
procesoare au fost echipate pentru a putea furniza 3 instrucţiuni în fiecare ciclu
de ceas. Deoarece unitatea de programare din exemplul nostru ştie că ea poate
furniza până la patru instrucţiuni pe ciclu, va căuta instrucţiuni independente în
alt fir de execuţie. In acest mod este eliminată gâtuirea care apare în procesul
de alimentare cu instrucţiuni.
9.4. Implementarea tehnicii hyper-threading.
Deşi s-ar putea părea că implementarea tehnicii, hyper-threading necesită
un mare număr de circuite de comandă suplimentare, în realitate se pare că nu
este chiar aşa. Intel raportează că la procesorul Pentium Xeon circuitele
suplimentare care implementează sistemul hyper-threading nu depăşesc 5%
din suprafaţa pastilei de siliciu.
Pentium Xeon este capabil să execute în paralel cel mult două fire de
execuţie pe două procesoare logice. Pentru a prezenta sistemului de operare
două procesoare logice, procesorul Xeon trebuie să fie capabil să memoreze
informaţiile corespunzătoare a două contexte distincte, corespunzătoare celor
două fire de execuţie. Acest deziderat a fost realizat prin modificarea
microarhitecturii resurselor; unele dintre acestea au fost replicate iar altele
partiţionate.
Pentru a asigura independenţă totală a contextelor pentru fiecare procesor
logic există câteva resurse care trebuie dublate. De exemplu este evident că
fiecare procesor trebuie să aibă propriul său registrul IP (instruction pointer).
In mod similar procesorul Xeon are două tabele de alocare a registrelor,
fiecare dintre acestea ţinând evidenţa celor 8 registre pentru întregi şi a celor 8
registre pentru virgulă mobilă pentru fiecare din cele două procesoare logice.
De asemenea fiecare procesor logic are propriul său TLB (Translation
Look-aside Buffer ).
La procesorul Xeon resursele partiţionate pot fi găsite sub formă de cozi
care decuplează unele de altele majoritatea etajelor pipeline-urilor.
Fig.9.5
De exemplu în figura 9.5. este prezentată una din cele trei cozi de
programare (scheduling queues) ale acestui procesor. Dacă această coadă de
programare are 12 instanţe, 6 dintre acestea sunt alocate procesorului 0
(culoarea roşie), iar celelalte 5, procesorului 1 (culoarea galbenă), în funcţie ce
cerere. Acest tip de partiţionare ar putea fi considerat ca fiind „dinamică”. Spre
deosebire de aceasta cele două cozi din partea de sus a figurii 9.5 sunt
partiţionate „static” în sensul că cele 12 instanţe ale cozii sunt împărţite în două,
câte 6 pentru fiecare procesor logic.
Cozile de programare (scheduling queues) ale procesorului Xeon sunt
partiţionate dinamic pentru a evita ca unul dintre procesoarele logice să le poată
monopliza. Dacă fiecare coadă de programare nu ar limita numărul de instanţe
pe care le poate utiliza fiecare procesor, atunci instrucţiunile unui fir de execuţie
ar putea umple coada, celălalt procesor rămânând fără instrucţiuni de executat.
Dacă procesorul Xeon execută un singur fir toate resursele partiţionate vor
fi combinate astfel încât acel fir de execuţie să obţină performanţa maximă.

Cap. 10. Sisteme Multiprocesor


1.1. Taxonomia arhitecturilor de calculatoare
Una dintre cele mai cunoscute taxonomii (clasificări) ale arhitecturilor de
calculatoare este taxonomia lui Flynn. Michael Flynn a clasificat arhitecturile de
calculatoare în patru categorii, în funcţie de prezenţa unui singur şir sau a mai
multor şiruri de instrucţiuni şi de date. Un şir de instrucţiuni este un set de
instrucţiuni secvenţiale executate de un singur procesor, iar un şir de date este
fluxul secvenţial de date necesar şirului de instrucţiuni. Cele patru categorii ale
lui Flynn sunt următoarele:
1. SISD (Single Instruction stream, Single Data stream). Această categorie
corespunde arhitecturii von Neumann, în care se execută în orice moment o
singură instrucţiune. Calculatoarele SISD sunt numite şi calculatoare seriale
scalare. Aceste calculatoare utilizează un registru numit contor de program,
care determină execuţia serială a instrucţiunilor. Pe măsură ce fiecare
instrucţiune este încărcată din memorie, contorul de program este actualizat
pentru a conţine adresa următoarei instrucţiuni care se va încărca şi se va
executa în ordine secvenţială. Există actualmente doar un număr redus de
calculatoare SISD; chiar şi procesoarele din calculatoarele personale utilizează
paralelismul în scopul creşterii eficienţei. In cele mai multe situaţii, acestea pot
executa două sau mai multe instrucţiuni simultan.
2. MISD (Multiple Instruction stream, Single Data stream). In acest caz,
mai multe instrucţiuni operează asupra unei singure date. Există două posibilităţi
de interpretare a structurii calculatoarelor MISD. Prima posibilitate este de a se
considera o clasă de calculatoare la care mai multe unităţi de prelucrare
distincte primesc instrucţiuni distincte care operează asupra aceloraşi date.
Această clasă de calculatoare este considerată ca nepractică sau imposibilă de
către unii proiectanţi de calculatoare şi în prezent nu există exemple de acest
tip. A doua posibilitate este de a se considera o clasă de calculatoare în care
datele sunt trecute printr-o serie de unităţi de prelucrare.
Unele arhitecturile de tip pipeline, ca de exemplu procesoarele vectoriale
sau arhitecturile sistolice, sunt considerate calculatoare de acest tip.
Arhitecturile de tip pipeline execută o prelucrare vectorială utilizând o serie de
etaje, iar fiecare din acestea execută o anumită funcţie şi produce un rezultat
intermediar. Motivul pentru care asemenea arhitecturi sunt clasificate ca sisteme
MISD este faptul că elementele unui vector pot fi considerate ca aparţinând
aceleiaşi date, iar fiecare etaj pipeline prelucrează mai multe instrucţiuni care
operează asupra acelui vector.
3. SIMD (Single Instruction stream, Multiple Data stream). In acest caz, o
singură instrucţiune prelucrează simultan date diferite. La calculatoarele de
acest tip, există mai multe unităţi de prelucrare şi o singură unitate de control.
Calculatoarele SIMD pot executa de asemenea prelucrări vectoriale. Aceasta se
realizează prin asignarea elementelor vectorilor unor unităţi de prelucrare
diferite pentru o prelucrare concurentă. In această categorie pot fi considerate
procesoarele matriciale.
4. MIMD (Multiple Instruction stream, Multiple Data stream). Această
categorie cuprinde calculatoare cu mai multe unităţi de prelucrare în care mai
multe instrucţiuni pot opera simultan asupra unor date diferite. Calculatoarele
MIMD reprezintă arhitecturile cele mai complexe, obţinând o eficienţă ridicată
prin prelucrare concurentă. In acest caz, concurenţa implică faptul că nu există
doar procesoare multiple care operează în paralel, dar şi faptul că se execută
procese multiple în acelaşi timp.
Taxonomia lui Flynn s-a dovedit o metodă corespunzătoare pentru
clasificarea arhitecturilor de calculatoare. Totuşi, progresele industriei de
calculatoare au creat arhitecturi care nu pot fi clasificate în mod clar prin
taxonomia lui Flynn. De exemplu, această taxonomie nu clasifică în mod
adecvat procesoarele vectoriale (SIMD şi MISD) şi arhitecturile hibride. Pentru a
Fig. 10.1
rezolva această problemă, au fost propuse mai multe taxonomii.
Figura 10.1 prezintă o taxonomie care cuprinde caracteristici ale mai
multor taxonomii propuse. Această taxonomie clasifică arhitecturile mai
recente, dar nu reprezintă o caracterizare completă a arhitecturilor paralele.
După cum se arată în figura 10.1, categoria calculatoarelor MIMD este
împărţită în patru tipuri de arhitecturi paralele: multiprocesoare,
multicalculatoare, multi-multiprocesoare şi calculatoare cu flux de date. In
categoria SIMD, există un singur tip de arhitectură, reprezentată de
procesoarele matriciale. Categoria MISD este împărţită în două tipuri de
arhitecturi: procesoare vectoriale de tip pipeline şi matrice sistolice. Celelalte
arhitecturi sunt grupate în două categorii: calculatoare hibride şi procesoare
speciale. Aceste arhitecturi sunt descrise în secţiunea următoare.
10.2. Prezentare generală calculatoare a arhitecturilor de calculatoare
10.2.1. Sisteme Multiprocesor
Multiprocesorul este un calculator paralel constând din mai multe
procesoare interconectate care partajează un sistem de memorie. Procesoarele
pot fi configurate astfel încât toate să execute câte o parte diferită a aceluiaşi
program, sau astfel încât fiecare să execute simultan mai multe programe
diferite. O schemă bloc a unui multiprocesor este prezentată în figura 10.2.
Fig. 10.2.
In general, un multiprocesor constă din n procesoare şi m module de
memorie ( n > 1 , m > 0 ). Procesoarele sunt notate cu P , P2 ,..., Pn iar modulele de
1
memorie sunt notate cu M 1 , M 2 ,..., M m . Reţeaua de interconectare RI
conectează fiecare procesor la un anumit subset al modulelor de memorie. O
instrucţiune de transfer determină transferul datelor de la un anumit procesor
către memoria cu care este conectat procesorul. Pentru transferul datelor între
două procesoare, trebuie să se execute o secvenţă programată de transferuri
de date, care transferă datele între memorii şi procesoare intermediare.
Pe baza organizării sistemului de memorie, multiprocesoarele pot fi
împărţite în două grupe, cu legătură strânsă şi cu legătură slabă.
In cazul unui multiprocesor cu legătură strânsă, un sistem central de
memorie, numită memorie principală sau memorie globală, asigură acelaşi timp
de acces pentru fiecare procesor. Sistemul central de memorie poate fi
implementat fie ca un singur modul de memorie, fie ca un set de module de
memorie care pot fi accesate în paralel de diferite procesoare. In ultimul caz, se
reduce conflictul la memorie şi astfel sistemul este mai eficient. Conflictul la
memorie se referă la situaţia în care mai multe procesoare solicită acces la
memorie într-un interval scurt de timp, rezultând întârzieri mari de acces la
memorie. Pe lângă sistemul central de memorie, fiecare procesor poate avea şi
o memorie cache de dimensiuni reduse. Aceste memorii cache ajută de
asemenea la reducerea conflictelor la memorie.
In cazul unui multiprocesor cu legătură slabă, pentru a se reduce
conflictele la memorie, sistemul de memorie este partiţionat între procesoare,
deci, fiecărui procesor i se ataşează o memorie locală. Astfel, fiecare procesor
poate accesa în mod direct memoria sa locală şi toate memoriile locale ale
celorlalte procesoare. Timpul de acces la o memorie care nu este locală este
însă mult mai ridicat decât cel la memoria locală.
Indiferent de tipul multiprocesorului, toate procesoarele acestuia utilizează
acelaşi sistem de operare. Sistemul de operare asigură interacţiunea dintre
procesoare şi taskurile acestora. De obicei, procesoarele sunt de acelaşi tip; în
acest caz, multiprocesorul se numeşte omogen. Dacă procesoarele sunt de
tipuri diferite, multiprocesorul se numeşte eterogen. Oricare din procesoare
poate accesa oricare din dispozitivele de I/E.
10.2.2. Sisteme multicalculator
Spre deosebire de un multiprocesor, un multicalculator poate fi considerat
un calculator paralel în care fiecare procesor are o memorie locală proprie. Un
procesor are acces direct doar la memoria sa locală şi nu poate adresa
memoriile locale ale altor procesoare. Această adresabilitate locală este o
caracteristică importantă care deosebeşte multicalculatoarele de
multiprocesoare. O schemă bloc a acestei arhitecturi este prezentată în figura
10.3.
Fig. 10.3
In figura 10.3, există n noduri de procesare şi fiecare nod constă dintr-un
procesor şi o memorie locală. Reţeaua de interconectare (RI) conectează
fiecare nod de procesare la un anumit subset al celorlalte noduri de procesare.
O instrucţiune de transfer determină transferul datelor de la un anumit nod la
unul din nodurile cu care este conectat. Pentru transferul datelor între două
noduri care nu pot fi conectate direct prin reţeaua de interconectare, datele
trebuie transferate prin noduri intermediare utilizând un mecanism cu
transmitere de mesaje.
Intr-un mecanism cu transmitere de mesaje, un procesor poate transmite
(sau recepţiona) un bloc de informaţii la (sau de la) fiecare din celelalte
procesoare prin canale de comunicaţie. Aceste canale sunt conexiuni fizice între
procesoare, aranjate pe baza unei topologii a reţelei de interconectare. Fiecare
procesor este conectat la un canal de comunicaţie printr-un dispozitiv numit
interfaţă de comunicaţie. Acest dispozitiv poate transmite sau recepţiona date
printr-un canal de comunicaţie şi poate executa funcţii pentru a asigura că
datele sunt transmise şi recepţionate corect.
Înainte ca un bloc de informaţii să fie transmis printr-un canal, blocul este
împachetat într-un mesaj cu un câmp al antetului la început şi un câmp al sumei
de control la sfârşit. Câmpul antetului constă din informaţii de identificare,
cuprinzând adresa sursă, adresa destinaţie şi lungimea mesajului. Câmpul
sumei de control constă din mai mulţi biţi de detecţie a erorilor de transmisie. La
anumite implementări, interfaţa de comunicaţie este capabilă de a crea şi a
decodifica câmpul antetului şi al sumei de control.
Comparând multiprocesoarele şi multicalculatoarele, primele pot fi
programate mai uşor decât cele din urmă. Multiprocesoarele reprezintă
arhitectura dominantă în cazul sistemelor paralele de dimensiuni reduse. In
general, pe măsură ce numărul de procesoare creşte, multicalculatoarele devin
mai economice decât multiprocesoarele. Multicalculatoarele sunt arhitecturi
eficiente pentru sistemele paralele de dimensiuni mari. Aceasta se datorează
următoarelor motive:
- Calculele ştiinţifice pot fi partiţionate astfel încât aproape toate
operaţiile pot fi executate local;
- Se obţine o îmbunătăţire semnificativă a performanţelor dacă
majoritatea referinţelor la memorie sunt efectuate la memoriile locale.
10.2.3. Sisteme Multi-multiprocesoare
Odată cu progresele tehnologiei VLSI, a devenit posibilă construirea unor
calculatoare paralele de dimensiuni mari utilizând microprocesoare cu
performanţe ridicate. Pentru proiectarea unor asemenea calculatoare, pot fi
combinate caracteristicile multiprocesoarelor şi multicalculatoarelor, într-o
arhitectură numită multi-multiprocesor (sau multiprocesor distribuit). Deci, un
multi-multiprocesor poate fi considerat un multicalculator în care fiecare nod de
procesare este un multiprocesor. Figura 10.4 prezintă structura generală a unui
multi-multiprocesor.
Fig. 10.4.
Fiecare nod permite ca taskurile cu un grad relativ ridicat de interacţiune
să fie executate local de către un multiprocesor, reducând astfel timpul necesar
comunicaţiei. Dacă fiecare nod este un multiprocesor, complexitatea programării
paralele a unui multicalculator va fi redusă.
10.2.4. Arhitecturi cu flux de date
Intr-o arhitectură cu flux de date (dataflow), o instrucţiune este gata pentru
execuţie atunci când datele care reprezintă operanzii instrucţiunii devin
disponibile. Rezultatele instrucţiunilor executate anterior formează operanzii
instrucţiunilor care aşteaptă să fie executate. Se formează astfel un flux de date,
care declanşează execuţia instrucţiunilor. Astfel, nu este necesar un contor de
program care există într-o arhitectură von Neumann pentru a controla execuţia
instrucţiunilor.
Instrucţiunile unui calculator cu flux de date nu adresează variabile într-o
memorie partajată globală, ci ele conţin valorile variabilelor utilizate. Intr-o
arhitectură cu flux de date, execuţia instrucţiunilor nu afectează alte instrucţiuni
care sunt gata pentru execuţie. Astfel, mai multe instrucţiuni pot fi executate
simultan, ceea ce conduce la posibilitatea unor calcule cu un grad ridicat de
concurenţă.
Figura 10.5 prezintă o schemă bloc a unui calculator cu flux de date.
Instrucţiunile, împreună cu operanzii acestora, sunt păstrate în memoria de
instrucţiuni şi date (I&D). Ori de câte ori o instrucţiune este gata pentru execuţie,
aceasta este transferată la unul din elementele de procesare (EP) prin reţeaua
de arbitrare. Fiecare element de procesare este un simplu procesor cu o
memorie locală limitată. La recepţionarea unei instrucţiuni, elementul de
procesare execută operaţia cerută şi transmite rezultatul la destinaţia din
memorie prin intermediul reţelei de distribuţie.
Fig. 10.5
Arhitecturile cu flux de date pot fi clasificate în două grupe: statice şi
dinamice. Intr-o arhitectură statică, o instrucţiune este validată ori de câte ori toţi
operanzii necesari sunt recepţionaţi şi o altă instrucţiune aşteaptă rezultatul
acestei instrucţiuni; în caz contrar, instrucţiunea rămâne invalidată. Această
constrângere poate fi impusă prin utilizarea semnalelor de achitare. Intr-o
arhitectură dinamică, o instrucţiune este validată ori de câte ori toţi operanzii
necesari sunt recepţionaţi. In acest caz, pot deveni disponibile mai multe seturi
de operanzi ale unei instrucţiuni în acelaşi timp. Comparativ cu arhitecturile
statice cu flux de date, arhitecturile dinamice permit un grad mai ridicat de
paralelism, deoarece o instrucţiune nu trebuie să aştepte după o altă
instrucţiune înainte de a-şi plasa rezultatul. In cazul metodei dinamice trebuie
stabilit însă un mecanism pentru a distinge diferitele seturi de operanzi pentru o
instrucţiune.
10.2.5. Procesoare matriciale
Un procesor matricial (figura 10.6) constă dintr-un set de noduri de
procesare (NP) şi un procesor scalar, care funcţionează sub controlul unei
unităţi de control centralizate. Unitatea de control încarcă instrucţiunile din
memoria principală, le decodifică şi apoi le transmite fie la procesorul scalar, fie
la nodurile de procesare, în funcţie de tipul acestora. Dacă instrucţiunea
încărcată este o instrucţiune vectorială, aceasta este transmisă la toate nodurile
de procesare. Toate nodurile execută simultan aceeaşi instrucţiune asupra
datelor diferite păstrate în memoriile lor locale. Astfel, un procesor matricial
necesită un singur program pentru a controla toate nodurile de procesare din
sistem şi nu este necesară duplicarea codului programului la fiecare nod de
procesare.
Fig. 10.6.
Un procesor matricial poate fi definit, de exemplu, sub forma unei grile în
care fiecare intersecţie reprezintă un NP, iar liniile dintre intersecţii reprezintă căi
de comunicaţie. Fiecare NP din matrice poate transmite (sau recepţiona) date la
(sau de la) cele patru noduri vecine. Unul dintre procesoare, reprezentând
unitatea de control, decide operaţiile care trebuie executate de fiecare NP în
timpul fiecărui ciclu de procesare şi transferurile de date necesare între nodurile
de procesare.
Ideea principală a unui procesor matricial este de a se exploata
paralelismul existent în setul de date al unei anumite probleme şi nu de a se
paraleliza secvenţa de execuţie a instrucţiunilor pentru acea problemă. Calculul
paralel se realizează prin asignarea fiecărui procesor la o partiţie a datelor.
Dacă setul de date este un vector, partiţia va fi un element al vectorului.
Matricele de procesoare îmbunătăţesc performanţele prin operarea simultană
asupra tuturor partiţiilor de date. Aceste procesoare pot executa operaţii
aritmetice sau logice asupra vectorilor. De aceea, ele se numesc şi procesoare
vectoriale.
10.2.6. Procesoare vectoriale de tip pipeline
Un procesor vectorial de tip pipeline poate prelucra în mod eficient
operanzi vectoriali (şiruri continue de date). In timp ce procesoarele matriciale
sunt controlate de instrucţiuni, procesoarele vectoriale de tip pipeline sunt
controlate de şiruri continue de date. Aceasta este diferenţa principală între un
procesor matricial sau vectorial şi un procesor vectorial de tip pipeline. Figura
10.7 prezintă structura de bază a unui procesor vectorial de tip pipeline.
Există două procesoare principale: un procesor scalar şi un procesor
vectorial. Procesorul scalar execută instrucţiunile scalare, iar procesorul
vectorial execută instrucţiunile vectoriale utilizând mai multe etaje de prelucrare.
Unitatea de control încarcă instrucţiunile din memoria principală, le decodifică şi
apoi le transmite fie la procesorul scalar, fie la procesorul vectorial realizat sub
formă de sistem pipeline, în funcţie de tipul acestora.
Fig. 10.7
Procesoarele vectoriale de tip pipeline utilizează mai multe module de
memorie pentru a furniza etajelor de prelucrare un şir continuu de date. Adesea
se utilizează un compilator cu vectorizare pentru a aranja datele într-un şir care
poate fi utilizat apoi de cele două procesoare.
10.2.7. Matrice sistolice
Pentru calculele ştiinţifice, adesea este necesară rezolvarea unor sisteme
de ecuaţii liniare de dimensiuni mari. De obicei, pentru rezolvarea unor
asemenea sisteme de ecuaţii se utilizează algebra matriceală. Datorită
secvenţelor lungi ale calculelor aritmetice, majoritatea operaţiilor algebrice
matriciale sunt executate pe calculatoare digitale cu viteză ridicată utilizând
pachete software dedicate. Un dezavantaj major al execuţiei operaţiilor
algebrice matriciale pe calculatoare generale este timpul de execuţie ridicat. De
asemenea, în cazul unui calculator general memoria principală nu are o
dimensiune suficientă pentru a permite plasarea unor matrice foarte mari. De
aceea, sunt necesare numeroase transferuri de I/E, ceea ce creşte timpul de
execuţie.
Pentru rezolvarea acestei probleme, au fost introduse arhitecturi speciale.
O soluţie constă în utilizarea unei matrice sistolice (figura 10.8). In cazul acestei
arhitecturi, există un număr mare de elemente de procesare (EP) identice.
Fig. 10.8
Fiecare element de procesare are o memorie locală limitată şi, pentru a nu
se limita numărul de elemente de procesare plasate într-o matrice, fiecare EP
poate fi conectat numai cu elementele de procesare vecine prin reţele de
interconectare. Deci, elementele de procesare sunt aranjate într-o structură de
tip pipeline, sub forma unei matrice liniare sau bidimensionale. Intr-o matrice
sistolică elementele de date şi rezultatele parţiale parcurg elementele de
procesare în timpul execuţiei, constând din mai multe cicluri de procesare. In
fiecare ciclu de procesare, anumite elemente de procesare execută aceeaşi
operaţie relativ simplă (de exemplu, adunare sau înmulţire) asupra elementelor
de date şi transmit aceste elemente sau rezultate parţiale la alte elemente de
procesare vecine.
De obicei, o matrice sistolică are o formă rectangulară sau hexagonală,
dar poate avea orice formă. Utilizând tehnologia VLSI, este posibil să se obţină
o putere de calcul foarte ridicată cu un sistem constând dintr-un număr mare de
procesoare identice organizate într-o manieră structurală.
10.2.8. Arhitecturi hibride
Arhitecturile hibride cuprind caracteristici ale unor arhitecturi diferite pentru
a obţine performanţe mai ridicate ale calculelor paralele. In general, există două
tipuri de paralelism care se pot utiliza: paralelism de control şi paralelism de
date. In cazul paralelismului de control, se execută simultan două sau mai multe
operaţii de către procesoare diferite. Calculatoarele MIMD sunt ideale pentru
implementarea paralelismului de control. Acestea sunt adecvate pentru
probleme care necesită executarea simultană a unor operaţii diferite asupra
datelor diferite. In cazul paralelismului de date, se execută aceeaşi operaţie
asupra mai multor partiţii ale datelor de către mai multe procesoare.
Calculatoarele SIMD sunt ideale pentru implementarea paralelismului de date.
Acestea sunt adecvate pentru probleme în care aceeaşi operaţie poate fi
executată simultan asupra unor porţiuni diferite ale datelor. Calculatoarele MISD
sunt de asemenea potrivite pentru paralelismul de date. Aceste calculatoare
permit procesarea vectorilor utilizând tehnica pipeline.
In practică, cele mai mari avantaje se obţin prin utilizarea paralelismului de
date. Aceasta deoarece în acest caz se beneficiază de pe urma paralelismului
în mod proporţional cu cantitatea datelor implicate în calcule. Totuşi, uneori nu
este posibil să se exploateze la maxim paralelismul de date, fiind necesară
utilizarea atât a paralelismului de control cât şi a celui de date. De exemplu, în
cazul unor programe de aplicaţie rezultatele cele mai bune se pot obţine atunci
când aceste programe sunt divizate în mai multe părţi care utilizează
paralelismul de date, iar părţile componente utilizează paralelismul prin tehnica
pipeline. Un grup de procesoare culege datele şi execută anumite prelucrări
preliminare. Procesoarele transmit apoi rezultatele lor la al doilea grup de
procesoare care execută alte calcule asupra rezultatelor. Al doilea grup
transmite rezultatele obţinute la al treilea grup de procesoare, care obţine
rezultatele finale. Deci, un calculator paralel care cuprinde atât caracteristici ale
arhitecturilor MIMD, cât şi cele ale SIMD (sau MISD) poate rezolva în mod
eficient o gamă largă de probleme.
10.2.9. Reţele neuronale artificiale
Un exemplu de arhitectură specială este o reţea neuronală artificială. O
asemenea reţea constă dintr-un număr mare de elemente de procesare (EP)
care funcţionează în paralel. Aceste reţele pot rezolva într-un mod mai eficient
unele probleme pentru care arhitecturile von Neumann sunt ineficiente, ca de
exemplu emularea informaţiilor naturale sau recunoaşterea formelor.
Arhitecturile bazate pe reţele neuronale sunt capabile de învăţare şi sunt
adaptive la schimbările de mediu.
Fig. 10.9
Figura 10.9 prezintă structura generală a unei reţele neuronale artificiale.
Fiecare element de procesare emulează unele caracteristici ale neuronului
biologic. Acesta are un set de intrări şi una sau mai multe ieşiri. Fiecărei intrări i
se asignează o pondere numerică. Această pondere corespunde potenţialului
sinaptic al unui neuron biologic. O sinapsă reprezintă conexiunea dintre un
neuron şi un terminal al altui neuron (terminal numit axon). Transmiterea
informaţiilor de la un neuron la altul are loc prin intermediul sinapselor şi
axonilor. Intrările unui element de procesare sunt multiplicate cu ponderile lor şi
sunt apoi însumate pentru a determina nivelul de activare al neuronului. După
determinarea nivelului de activare, se aplică o funcţie de activare pentru a
produce semnalul de ieşire. Ieşirile combinate ale unui strat (nivel) precedent
devin intrările următorului strat, în care acestea sunt din nou însumate şi
evaluate. Acest proces este repetat până când se traversează reţeaua şi se
ajunge la o anumită decizie.
Spre deosebire de arhitecturile von Neumann, la care elementul primar de
calcul este procesorul, în cazul reţelelor neuronale artificiale acest element este
reprezentat de conexiunile dintre elementele de procesare. Pentru o problemă
dată, trebuie să se determine valorile corecte ale ponderilor astfel încât reţeaua
să poată executa prelucrările necesare. De multe ori, determinarea valorilor
corespunzătoare ale ponderilor se realizează prin ajustarea iterativă a
ponderilor cu scopul de a creşte performanţele reţelei. Regula de ajustare a
ponderilor este numită regulă de învăţare, iar întregul proces de obţinere a
ponderilor corespunzătoare este numit învăţare.
Toate modelele de reţele neuronale artificiale sunt caracterizate prin
operarea paralelă şi interconectarea densă între elementele de procesare. In
acelaşi timp, există diferenţe majore între modelele individuale în ceea ce
priveşte arhitectura lor, regulile de învăţare şi modul de interacţiune cu mediul.
O taxonomie generală a acestor modele este prezentată în continuare.
Distincţia cea mai generală între diferitele modele de reţele neuronale artificiale
este metoda de învăţare. Dacă mediul furnizează exemplele de învăţare sub
forma perechilor de vectori de intrare/ieşire, metoda de învăţare este numită
supervizată. Această metodă este numită şi învăţare cu un profesor, deoarece
mediul are rolul unui profesor pentru reţeaua neuronală, punând la dispoziţie
exemple detaliate despre ceea ce trebuie învăţat. Dacă, din contră, mediul
specifică intrarea dar nu şi ieşirea, învăţarea este nesupervizată. In acest caz,
reţeaua neuronală trebuie să descopere soluţia la problema de învăţare. In
cazul învăţării cu ajutor (reinforcement learning), mediul furnizează anumite
informaţii de ieşire, dar aceste informaţii sunt sub forma evaluării unei
performanţe a reţelei neuronale şi nu sub forma unor exemple de învăţare.
Această metodă este numită şi învăţare cu un critic, spre deosebire de
învăţarea cu un profesor, deoarece mediul nu specifică ceea ce trebuie învăţat,
ci numai dacă ceea ce se învaţă este corect.
O altă distincţie între diferite modele de reţele neuronale artificiale se
bazează pe arhitectura acestora. Arhitectura se referă la tipul de prelucrare
executată de neuronii artificiali şi la interconexiunile dintre aceştia. Modelele de
reţele neuronale artificiale pot fi împărţite în două grupe: deterministe şi
stohastice. Reţelele deterministe produc întotdeauna acelaşi rezultat la ieşire
pentru aceeaşi intrare, în timp ce la reţelele stohastice ieşirea pentru o intrare
dată poate varia în funcţie de o anumită distribuţie a probabilităţii de ieşire.
Modelele stohastice sunt de obicei mai dificil de analizat şi simulat, dar în
acelaşi timp ele sunt mai realiste în numeroase aplicaţii.
Adesea, modelele de reţele neuronale artificiale sunt simulate prin
program. Această metodă este flexibilă, dar este lentă. Metoda cea mai eficientă
pentru implementarea unei reţele neuronale artificiale este implementarea prin
hardware. In ultimii ani, au fost dezvoltate mai multe circuite pentru reţelele
neuronale artificiale. In general, sunt disponibile trei tehnologii diferite pentru
implementarea prin hardware a unei reţele neuronale artificiale: electronică,
optică şi electro-optică.
Tehnologia electronică poate fi împărţită la rândul ei în trei tipuri de
implementări: analogică, digitală şi hibridă. O implementare analogică reduce
complexitatea circuitului, dar este mai puţin precisă şi, de multe ori, nu permite
obţinerea unui grad de precizie de 6 biţi. Aceasta se datorează în principal
nivelului redus de precizie al rezistoarelor. O implementare digitală asigură o
precizie mai ridicată, dar de multe ori necesită un spaţiu mai mare în cadrul
circuitului integrat. O implementare hibridă conţine elemente analogice şi
digitale pentru a obţine avantajele ambelor implementări.
Tehnologia optică poate soluţiona anumite probleme ale tehnologiei
electronice, în special cele legate de conectivitatea între neuroni, din cauza
întârzierilor şi a spaţiului necesar în cadrul circuitului integrat. Prin utilizarea
interconexiunilor optice, nu este necesară nici o izolaţie între traseele
semnalelor, deoarece razele de lumină pot trece unele prin altele fără a
interacţiona între ele. De asemenea, traseele semnalelor pot fi realizate
tridimensional. In sfârşit, ponderile pot fi memorate sub forma unor holograme.
Cu toate aceste avantaje, există numeroase probleme asociate cu tehnologia
optică, în special faptul că unele caracteristici fizice ale dispozitivelor optice nu
sunt compatibile cu cerinţele reţelelor neuronale.
Intr-o implementare electro-optică, interconexiunile sunt realizate optic.
Deoarece reţelele neuronale artificiale sunt puternic interconectate, această
metodă devine o alternativă atractivă de implementare.
10.2.10. Procesoare bazate pe logica fuzzy
Un alt exemplu de arhitectură specială este reprezentată de un procesor
bazat pe logica fuzzy. Logica fuzzy a fost propusă de Lofti Zadeh pentru a
îmbunătăţi utilizarea tehnicilor inteligenţei artificiale în anumite domenii cum este
recunoaşterea vorbirii. In inteligenţa artificială, logica cu două valori reprezintă
semnificaţia unei propoziţii ca adevărată sau falsă, dar nu poate reprezenta o
propoziţie cu o semnificaţie imprecisă. In logica fuzzy, o propoziţie poate fi
adevărată sau falsă, sau poate avea o valoare intermediară (de exemplu, foarte
adevărat).
Logica fuzzy se ocupă de principiile formale ale raţionamentului
aproximativ. Această logică încearcă să trateze în mod eficient complexitatea
procesului cognitiv uman şi elimină unele dezavantaje asociate cu logica clasică
binară, care nu reflectă în mod corespunzător procesele cognitive umane
complexe. Logica clasică binară consideră clase cu limite clare, de exemplu,
negru sau alb. In acest fel, un obiect este fie un membru al unei clase, fie nu.
Spre deosebire de această logică, logica fuzzy consideră clase care nu au limite
clare, o măsură indicând gradul de apartenenţă al unui obiect la o clasă.
Logica fuzzy a fost aplicată în numeroase domenii, cum sunt controlul
proceselor, recunoaşterea imaginilor, robotică şi sisteme expert. Controlul fuzzy
este prima aplicaţie industrială a logicii fuzzy. Un controler fuzzy poate controla
sisteme care puteau fi controlate anterior numai de către operatori
experimentaţi. In Japonia, s-au obţinut progrese semnificative în logica fuzzy, iar
această logică a fost aplicată unei mari varietăţi de produse, cum sunt sisteme
de control al navigaţiei pentru automobile, camere video şi maşini de spălat.
Deşi implementarea prin software a logicii fuzzy asigură rezultate bune pentru
unele aplicaţii, pentru implementarea aplicaţiilor cu performanţe ridicate sunt
necesare procesoare fuzzy dedicate, numite acceleratoare fuzzy.

6.5 Memoria stivă


Memoria stivă este o listă liniară de date elementare, în care inserarea, elimi-
narea şi accesul la elementele de date se efectuează la un singur capăt al
acesteia. Stiva poate fi considerată o listă de tip LIFO (Last-In, First-Out).
In funcţie de modul de implementare, stiva poate fi de mai multe tipuri:
- Stivă software, organizată în memoria internă;
- Stivă cablată (hardware);
- Stivă parţial cablată.
Indiferent de modul de implementare, o stivă trebuie să permită efectuarea
următoarelor operaţii:
- Introducere (inserare): PUSH;
- Extragere (eliminare): POP;
- Acces la elementul din vârful stivei.
6.5.1. Tipuri de memorii stivă
6.5.1.1 Stiva implementată în memorie
Stiva poate fi simulată în memoria internă a calculatorului, utilizându-se
adresarea convenţională. Gestionarea stivei se poate realiza prin software,
existând instrucţiuni speciale şi registre dedicate pentru operaţiile cu stiva (figura
6.7)
Fig.6.7
Stiva poate fi definită cu ajutorul a două registre ale procesorului. Registrul
BP indică baza stivei, iar registrul SP indică vârful stivei. Adresa de bază a stivei
rămâne fixă, în timp ce adresa care indică vârful stivei se modifică la fiecare
operaţie de introducere şi eliminare din stivă. Instrucţiunile speciale de lucru cu stiva
modifică automat conţinutul registrului SP.
De obicei, stivele cresc spre adrese mici, elementul din vârful stivei având
adresa cea mai mică, dar există şi stive care cresc spre adrese mari.
Presupunând că stiva creşte spre adrese mici, iar SP indică elementul din
vârful stivei, instrucţiunea de introducere a unui element în stivă decrementează
registrul SP şi copiază elementul respectiv în stivă. Instrucţiunea de extragere a
unui element din vârful stivei copiază acest element într-un registru de memorie şi
incrementează registrul SP.
In cazul stivei simulate în memorie, pe lângă operaţiile obişnuite cu stiva, se
pot citi sau modifica elemente oarecare din stivă, prin adresarea lor relativă faţă de
registrul de bază al stivei (BP).
6.5.1.2. Stiva cablată
Spre deosebire de stiva simulată în memorie, la care vârful stivei se
deplasează în timp ce informaţiile din stivă rămân fixe, în cazul stivei cablate există
un vârf fix şi informaţiile din stivă sunt translatate la fiecare operaţie de introducere
sau eliminare din stivă.
Stivele cablate pot avea un registru de stare asociat, care indică dacă stiva
este goală (EMPTY) sau plină (FULL). La încercarea de extragere a unui element
din stiva goală se poate activa un semnal de eroare UNDERFLOW, iar la
încercarea de introducere a unui element în stiva plină se poate activa un alt
semnal, OVERFLOW.
Stivele cablate au avantajul unei viteze ridicate de efectuare a operaţiilor,dar
dimensiunea acestora este limitată.
6.5.1.3. Stiva parţial cablată
Fig. 6.8
Dacă dimensiunea stivei cablate este redusă, pentru cazurile de depăşire de
capacitate a stivei cablate, este indicată completarea acesteia cu o stivă simulată
în memoria internă, (Figura 6.8).
6.6 Memoria cache
6.6.1 Principii
Deoarece accesul la memoria principală necesită un timp considerabil mai
mare comparativ cu viteza globală a unui procesor, este important să se
proiecteze un sistem de memorie cu un timp de acces cât mai redus. O
posibilitate de a creşte viteza globală a sistemului de memorie este de a se
reduce numărul de accesuri la memoria principală. Acest deziderat poate fi
realizat prin instalarea unei memorii rapide de mici dimensiuni care să conţină,
în fiecare moment, o parte din program. In acest mod, datorită proprietăţii de
localitate a referinţelor, numărul referinţelor la memoria principală va fi redus în
mod considerabil. O asemenea memorie rapidă, utilizată temporar pentru
păstrarea unei porţiuni a datelor şi instrucţiunilor în vederea utilizării imediate,
este cunoscută sub numele de memorie cache.
Deoarece memoria cache are un preţ ridicat, un sistem de calcul poate
avea doar o memorie cache cu o dimensiune limitată. Pentru acest motiv, un
sistem de calcul conţine o memorie principală mai lentă şi de dimensiuni relativ
mari, împreună cu o memorie cache mai rapidă şi de dimensiuni mai mici.
Memoria cache este amplasată între memoria principală şi UCP şi conţine copii
ale anumitor blocuri ale memoriei principale. Astfel, atunci când UCP solicită un
cuvânt şi acest cuvânt se află în memoria cache rapidă, nu va mai fi necesar
accesul la memoria principală.
Deşi dimensiunea memoriei cache este doar o mică parte din dimensiunea
memoriei principale, datorită proprietăţii de localitate a referinţelor, o mare parte
din cererile de acces la memorie vor fi satisfăcute de memoria cache.
Performanţa unui sistem poate fi îmbunătăţită în mod semnificativ dacă
memoria cache este amplasată în acelaşi circuit integrat cu procesorul. In acest
caz, ieşirile memoriei cache pot fi conectate la UAL şi la registre prin legături
scurte, reducând timpul de acces. Aceasta este soluţia adoptată la majoritatea
procesoarelor actuale.
6.6.2. Organizarea memoriei cache
Figura 6.9 prezintă componentele principale ale unei memorii cache.
Cuvintele de memorie sunt păstrate într-o memorie de date şi sunt grupate în
pagini de dimensiuni reduse, numite blocuri sau linii. Conţinutul memoriei de
date este copia unui set de blocuri ale memoriei principale. Fiecare bloc al
memoriei cache este marcat cu adresa sa de bloc, numită marcaj (tag). Colecţia
adreselor de marcaj asignate momentan memoriei cache, adrese care pot fi
necontigue, este păstrată într-o memorie specială, numită memorie de marcaje
sau director.
Fig. 6.9
Pentru a îmbunătăţi performanţele unui calculator, timpul necesar pentru
testarea adreselor de marcaj şi accesarea memoriei cache de date trebuie să fie
mai redus decât timpul necesar pentru accesarea memoriei principale.
Figura 6.10 prezintă două moduri de plasare a unei memorii cache într-un
sistem de calcul. In organizarea din figura 6.10(a), numită organizare "look-
aside", memoria cache şi memoria principală sunt conectate direct la magistrala
sistem. UCP iniţiază un acces la memorie prin plasarea unei adrese Ai pe
magistrala de adrese la începutul unui ciclu de citire sau de scriere. Memoria
cache M 1 compară adresa Ai , cu adresele de marcaj plasate momentan în
memoria sa de marcaje. Dacă se găseşte o potrivire în memoria cache, deci,
apare un succes, accesul este terminat printr-o operaţie de citire sau de scriere
Fig. 6.10
executată cu memoria cache, care nu implică memoria principală M 2 . Dacă nu
se găseşte o potrivire cu adresa Ai în memoria cache, deci, apare un eşec,
atunci accesul dorit este terminat printr-o operaţie de citire sau de scriere
executată cu memoria principală. Ca răspuns la un eşec, este transferat un bloc
de date B j care conţine adresa destinaţie Ai de la M 2 la M 1 . Acest transfer
este rapid, datorită dimensiunii reduse a blocului şi a metodelor de acces rapide
la memoria RAM, cum este modul pagină. Memoria cache implementează o
anumită strategie de înlocuire pentru a determina unde să se plaseze noul bloc.
Atunci când este necesar, blocul memoriei cache înlocuit de B j este salvat în
M 2 . De notat că, în cazul eşecurilor la accesul memoriei cache, chiar dacă
acestea sunt puţin frecvente, transferurile de blocuri între M 1 şi M 2 ocupă
magistrala sistem, care nu va fi disponibilă pentru alte operaţii, cum sunt
transferurile de I/E.
In figura 6.10(b) se prezintă o altă organizare, care este mai rapidă, dar
mai costisitoare; aceasta este numită organizare "look-through". UCP comunică
cu memoria cache printr-o magistrală separată (locală) care este izolată de
magistrala sistem. In acest mod magistrala sistem este disponibilă pentru
utilizarea de către alte unităţi, cum sunt controlere de I/E, care pot comunica cu
memoria principală. Prin urmare, accesurile la memoria cache şi accesurile la
memoria principală care nu implică UCP se pot desfăşura concurent. UCP
transmite o cerere la memoria principală numai după un eşec la accesul în
memoria cache. Magistrala locală care conectează M 1 şi M 2 poate avea o
lăţime mai mare decât magistrala sistem, crescând astfel viteza transferurilor
între memoria cache şi cea principală.
Dezavantajul principal al organizării "look-through", pe lângă costul său
mai ridicat, constă în faptul că este necesar un timp mai lung pentru ca memoria
principală să răspundă la cererea UCP atunci când apare un eşec la accesul
memoriei cache.
6.6.3 Funcţionarea memoriei cache
Atunci când UCP generează o cerere de citire pentru un cuvânt din
memorie, cererea este trimisă mai întâi la memoria cache pentru a verifica dacă
acest cuvânt se află deja în această memorie. In cazul în care cuvântul nu este
găsit în memoria cache (deci, apare un eşec la citire), cuvântul solicitat este
furnizat de memoria principală. O copie a cuvântului este depusă în memoria
cache pentru referinţele viitoare de către UCP. In cazul în care cuvântul este
găsit în memoria cache (deci, apare un succes la citire), cuvântul este furnizat
de memoria cache. Astfel, în această situaţie, nu este necesar accesul la
memoria principală. Prin aceasta, viteza sistemului creşte considerabil.
Figura 6.11 ilustrează execuţia unei operaţii de citire pentru un sistem
simplu de memorie cache. In acest exemplu, se presupune o dimensiune a
blocului (liniei) memoriei cache de 4 octeţi. Fiecare adresă de memorie are
dimensiunea de 12 biţi, astfel încât cei 10 biţi de ordin superior formează
marcajul sau adresa blocului, iar cei 2 biţi de ordin inferior definesc un
deplasament în cadrul blocului. Atunci când un bloc este adus în memoria
cache de date, marcajul acestuia este plasat în memoria cache de marcaje.
Figura 6.11 prezintă conţinutul a două blocuri aduse în memoria cache de date;
de observat locaţiile aceloraşi blocuri din memoria principală. Pentru citirea
cuvântului indicat de săgeată, adresa acestuia Ai = 1100 0101 0110 este
transmisă la M 1 care compară partea de marcaj a adresei Ai cu marcajele sale
memorate şi găseşte o potrivire. Marcajul memorat adresează blocul
corespunzător din memoria de date, iar deplasamentul de 2 biţi este utilizat
pentru identificarea cuvântului destinaţie din cadrul blocului, care este apoi
transmis la UCP.
Atunci când UCP generează o cerere de scriere pentru un cuvânt în
memorie, cererea este trimisă mai întâi la memoria cache pentru a verifica dacă
locaţia acestui cuvânt se află în memoria cache. In cazul în care locaţia
cuvântului nu este găsită în memoria cache (deci, apare un eşec la scriere), se
încarcă o copie a cuvântului din memoria principală în memoria cache. Apoi, se
execută o operaţie de scriere. De asemenea, în cazul în care cuvântul este găsit
în memoria cache (deci, apare un succes la scriere), se execută o operaţie de
scriere direct în memoria cache.
Fig. 6.11
Execuţia unei operaţii de scriere pentru memoria cache din exemplul
precedent este ilustrată în figura 6.12. Partea de marcaj a adresei destinaţie Ai
este transmisă la M 1 împreună cu cuvântul de date care trebuie memorat.
Atunci când apare un succes, noua dată, în acest caz 55h, este memorată în
locaţia de la adresa Ai în memoria de date din M 1 modificând astfel vechea
dată FFh.
Fig. 6.12
Apare acum o nouă problemă, deoarece data din M 1 cu adresa Ai diferă
de data din M 2 cu aceeaşi adresă. O inconsistenţă temporară de acest tip este
acceptabilă cât timp nici un dispozitiv (un alt procesor sau un dispozitiv de I/E)
nu încearcă citirea datei vechi. Prevenirea utilizării improprii a datei vechi
reprezintă problema coerenţei memoriilor cache sau a consistenţei memoriilor
cache. Aceasta este o problemă de bază la sistemele multiprocesor unde mai
multe procesoare partajează accesul la aceeaşi memorie principală, dar fiecare
dispune de propria memorie cache. Această problemă apare de asemenea în
sistemele uniprocesor atunci când este prezent un controler sau procesor de I/E
care are un acces direct la memoria principală, independent de UCP.
Inconsistenţele din memoriile cache pot fi minimizate prin implementarea unei
strategii care actualizează în mod sistematic datele din M 2 ca răspuns la
modificările efectuate asupra datelor corespunzătoare din M 1 .
Pentru executarea unei operaţii de scriere, există două strategii care pot fi
utilizate: "write-back" şi "write-through".
- In cazul strategiei "write-back", numită şi "copy-back", fiecărui cuvânt din
memoria cache i se asociază un bit, numit bit de modificare (dirty bit) sau bit de
inconsistenţă, care arată dacă acest cuvânt a fost modificat în timpul în care se
afla în memoria cache. Toate modificările asupra unui cuvânt sunt efectuate în
memoria cache. Atunci când un cuvânt trebuie eliminat din memoria cache, se
testează bitul de modificare al cuvântului; dacă bitul este setat, cuvântul este
scris în memoria principală în forma sa actualizată. Avantajul strategiei "write-
back" este că, atât timp cât un cuvânt rămâne în memoria cache, acesta poate fi
modificat de mai multe ori, iar pentru UCP nu are importanţă dacă cuvântul din
memoria principală nu a fost actualizat. Dezavantajul acestei strategii este că
memoria cache şi memoria principală pot fi temporar inconsistente. Aceasta
creează dificultăţi dacă mai multe procesoare cu memorii cache independente
partajează aceeaşi memorie principală, deoarece datele lor pot deveni
inconsistente. Strategia "write-back" complică de asemenea recuperarea în
cazul defectelor de sistem şi, deşi trebuie asociat un singur bit suplimentar cu
fiecare cuvânt, aceasta complică într-o oarecare măsură proiectarea sistemului.
- In cazul strategiei "write-through", cuvântul este modificat atât în
memoria cache, cât şi în memoria principală la fiecare ciclu de scriere.
Avantajele acestei strategii constau în faptul că este uşor de implementat şi
memoria principală are întotdeauna date consistente cu memoria cache. Pe de
altă parte, această strategie are dezavantajul că încetineşte UCP, deoarece
toate operaţiile de scriere necesită accesuri ulterioare la memoria principală.
Totuşi, numai o fracţiune redusă, probabil 10%, din toate accesurile la memorie
sunt operaţii de scriere. Anumite procesoare permit utilizarea ambelor strategii
de scriere, astfel încât utilizatorul poate selecta strategia cea mai avantajoasă
pentru un program particular.
6.6.4. Maparea adreselor
O caracteristică de bază a memoriei cache este funcţia de mapare (de
translatare), care atribuie locaţii din memoria cache blocurilor din memoria
principală.
Se utilizează trei tipuri de mapare a adreselor:
1. Mapare asociativă;
2. Mapare directă;
3. Mapare cu seturi asociative.
Pentru a ilustra aceste trei tipuri de mapare ale adreselor, presupunem că
memoria principală are o capacitate de 64 K cuvinte de câte 16 biţi fiecare, fapt
care înseamnă că magistrala de adrese are 16 biţi. De asemenea, presupunem
că memoria cache care poate păstra maxim 256 de cuvinte. Considerăm că
UCP generează o cerere de citire. Cererea de scriere este gestionată într-un
mod similar. Vom urmări acum strategiile celor trei tipuri de mapare.
6.6.4.1. Memorie cache cu maparea asociativă
In cazul unei memorii cache cu mapare asociativă (numită şi memorie
cache cu asociativitate totală), adresa şi conţinutul sunt memorate ca şi cuvinte
separate în memoria cache. Ca rezultat, un cuvânt de memorie poate fi
memorat în orice locaţie a memoriei cache, ceea ce face ca acest tip de
memorie cache să fie cel mai flexibil. Figura 6.13 prezintă organizarea unei
memorii cache cu mapare asociativă pentru sistemul considerat. De observat
că, indiferent de adresele lor absolute din memoria principală, cuvintele sunt
memorate în locaţii arbitrare.
Fig. 6.13
Deoarece o celulă de memorie asociativă are un cost mult mai mare decât
o celulă de memorie RAM, doar adresele cuvintelor sunt memorate în partea
asociativă, în timp ce datele sunt memorate în partea de memorie RAM a
memoriei cache. Această soluţie nu va creşte timpul de acces al memoriei
cache în mod semnificativ, dar va conduce la un cost semnificativ mai redus.
Astfel, atunci când UCP generează o adresă pentru referinţa la memorie,
aceasta este transferată în registrul argument şi este comparată, în paralel, cu
câmpurile de adresă ale tuturor cuvintelor aflate în memoria cache. Dacă s-a
găsit locaţia cu o adresă care se potriveşte, datele corespunzătoare pot fi
accesate din memoria RAM.
Dezavantajul principal al mapării asociative este că necesită o memorie
asociativă de dimensiuni mari, care este foarte costisitoare.
6.6.4.2. Memorie cache cu maparea directă
Pentru implementarea mapării directe sunt necesare numai memorii RAM.
Memoria cache M 1 este împărţită într-un număr de regiuni numite seturi,
fiecare din acestea memorând un bloc de n cuvinte consecutive. Memoria
principală M 2 este divizată similar în blocuri. In cazul mapării directe, fiecare
bloc din M 2 este mapat într-un set specific din M 1 .
Figura 6.14 reprezintă arhitectura unei memorii cache cu mapare directă.
Considerăm, pentru simplificare, că un set al memoriei cache, ca şi un bloc al
memoriei principale, conţine un singur cuvânt. Pentru implementarea mapării
directe, adresele de memorie de 16 biţi sunt divizate în două părţi: cei 8 biţi de
ordin inferior ai adresei din memoria principală formează un câmp de index,
care identifică setul unic al memoriei cache, unde se poate memora blocul de
memorie. Ceilalţi 8 biţi de ordin superior ai adresei din memoria principală
rămaşi, formează un câmp de marcaj (tag).
Această arhitectură constă din trei componente principale: o memorie de
date, o memorie de marcaje şi un circuit de comparare. Memoria de date
păstrează cuvintele de date ale memoriei cache. Memoria de marcaje păstrează
marcajele asociate cu cuvintele de date şi are câte o intrare pentru fiecare
cuvânt al memoriei de date. Comparatorul activează linia de potrivire, indicând
existenţa cuvântului adresat în memoria cache.
La adresa specificată de index, este memorat un marcaj în memoria de
marcaje şi un bloc de memorie în memoria de date. Dacă marcajul adresei de
memorie cerute se potriveşte cu marcajul din memoria cache, cuvântul din
Fig. 6.14
memoria de date este transmis la UCP. In caz contrar, se accesează memoria
principală, iar cuvântul corespunzător este încărcat şi transmis la UCP. Cuvântul
adresat, împreună cu partea de marcaj a adresei acestuia, înlocuieşte de
asemenea cuvântul şi marcajul cu indexul corespunzător din memoria cache.
Un exemplu care ilustrează funcţionarea unei memorii cache cu mapare
directă este prezentat în figura 6.15. Vom considera memoria principală
prezentată în figura 6.13.
Fig.6.15
In acest exemplu, o adresă de memorie constă din 16 biţi, iar memoria
cache conţine 256 de cuvinte. Cei 8 biţi mai puţin semnificativi ai adresei
constituie câmpul de index, iar cei 8 biţi rămaşi constituie câmpul de marcaj. Biţii
de index determină adresa unui cuvânt în memoriile de marcaje şi de date.
Fiecare cuvânt din memoria de marcaje are 8 biţi, iar fiecare cuvânt din
memoria de date are 16 biţi. Dacă UCP solicită citirea cuvântului de memorie de
la adresa 0900h este atunci indexul va fi 00 iar marcajul 09. Astfel la adresa 00
din memoria de marcaje se găseşte valoarea 09 care corespunde cu marcajul
cuvântului solicitat deci a fost înregistrat un succes la căutare şi conţinutul
memoriei de date de la adresa 00 (care este 3800h) este preluat de UCP.
Dacă apoi, UCP solicită citirea conţinutului adresei 0100h, indexul (00h) se
potriveşte, dar marcajul (01h) este diferit, deci a fost înregistrat un insucces la
căutare şi în consecinţă este accesată memoria principală, iar cuvântul de date
1234h (vezi figura 6.13) este transferat la UCP. Cuvintele din memoria de
marcaje şi memoria de date de la indexul 00h sunt înlocuite apoi cu 01h,
respectiv 1234h.
In cazul real în care fiecare bloc conţine mai multe cuvinte de memorie de,
pe lângă marcaj şi index, utilizează în plus un deplasament care precizează
poziţia cuvântului solicitat în cadrul blocului.
Avantajul mapării directe faţă de maparea asociativă constă în faptul că
necesită un număr mai redus de biţi pentru fiecare cuvânt din memoria cache şi
nu necesită memorie asociativă. Dezavantajul principal este că performanţele
pot fi reduse considerabil dacă două sau mai multe cuvinte având acelaşi index,
dar marcaje diferite, sunt accesate în mod frecvent. De exemplu, cuvintele de
memorie de la adresele 0100h şi 0200h trebuie plasate ambele în memoria
cache la indexul 00h, astfel încât se pierde un timp important pentru
interschimbarea lor. Aceasta încetineşte sistemul, anulând efectul memoriei
cache. Totuşi, considerând proprietatea de localitate a referinţelor,
probabilitatea de a avea două cuvinte cu acelaşi index este redusă.
6.6.4.3. Maparea cu seturi asociative (k-way set associative)
O metodă mai generală de mapare a adreselor pentru memoriile cache
este numită mapare cu seturi asociative. In timp ce la maparea directă fiecare
set, identificat de un anumit index, memorează un singur bloc, la maparea cu
seturi asociative fiecare set memorează un număr de k blocuri. Fiecare set este
o mică memorie asociativă, astfel încât maparea adreselor din cadrul fiecărui
set este asociativă. In practică sunt utilizate doar valori mici ale parametrului k,
cum ar fi de exemplu k=2, sau k=4.
De exemplu, o memorie cache cu seturi asociative cu k blocuri de
memorie, numit set asociativ cu k căi, poate memora k blocuri de date având
acelaşi index, împreună cu marcajele lor. In figura 6.19 se prezintă o arhitectură
pentru o memorie cache cu seturi asociative cu k blocuri de memorie.
Fig. 6.16
Considerăm din nou că un set conţine un singur cuvânt. Fiecare bloc de
memorie are aceeaşi structură ca şi o memorie cache cu mapare directă. Pentru
a determina dacă un cuvânt adresat se află în memoria cache, marcajul
acestuia este comparat în paralel (asociativ) cu marcajele datelor din toate
blocurile de memorie. O potrivire în oricare din blocurile de memorie validează
semnalul de potrivire pentru a indica existenţa cuvântului în memoria cache.
Dacă apare o potrivire, cuvântul corespunzător de date este transferat la
UCP. In caz contrar, cuvântul de date este încărcat din memoria principală şi
este transmis la UCP. Cuvântul de date, împreună cu marcajul acestuia, este
depus apoi într-unul din blocurile de memorie.
Fig. 6.17
Un exemplu ilustrând funcţionarea memoriei cache cu seturi asociative
este prezentat în figura 6.17. Această figură prezintă o memorie cache cu seturi
asociative cu două căi. Conţinutul adresei 0900h (vezi figura 6.13) este depus în
memoria cache la indexul 00h şi marcajul 09h. Dacă UCP solicită accesarea
cuvântului de la adresa 0100h, indexul (00h) se potriveşte, dar marcajul este
acum diferit. De aceea, este accesat conţinutul memoriei principale, iar valoarea
1234h este transferată la UCP. Acest cuvânt de date şi marcajul acestuia (01h)
sunt memorate în al doilea bloc al memoriei cache. Atunci când nu există spaţiu
pentru un anumit index în memoria cache, unul din cele două cuvinte de date
stocate la acel index va fi înlocuit conform unei strategii de înlocuire predefinite.
6.6.5. Strategii de înlocuire
Atunci când nu mai există spaţiu în memoria cache, trebuie să se utilizeze
o strategie pentru a înlocui un cuvânt cu data din memorie care este accesată în
acel moment. In general, există trei strategii principale pentru a determina
cuvântul care va fi eliminat din memoria cache. Acestea sunt strategiile de
înlocuire aleatoare, înlocuirea cuvântului cel mai puţin frecvent utilizat şi
înlocuirea cuvântului cel mai puţin recent utilizat.
Înlocuire aleatoare. Această metodă alege un cuvânt în mod aleator şi
înlocuieşte acel cuvânt cu data nou accesată. Această metodă este uşor de
implementat prin hardware şi este mai rapidă decât alte metode. Dezavantajul
este că acele cuvinte care sunt cel mai probabil de a fi utilizate din nou au
aceeaşi şansă de a fi eliminate ca şi cuvintele care probabil nu vor fi utilizate din
nou. Acest dezavantaj se micşorează pe măsură ce dimensiunea memoriei
cache creşte.
Cel mai puţin frecvent utilizat (LFU - Least Frequently Used). Această
metodă înlocuieşte datele care sunt cel mai puţin utilizate. Metoda presupune că
datele care nu sunt referite frecvent sunt mai puţin necesare. Pentru fiecare
cuvânt, se păstrează un contor al numărului total de utilizări ale cuvântului de la
încărcarea acestuia în memoria cache. Cuvântul cu valoarea cea mai mică a
contorului este cuvântul care va fi eliminat. Avantajul acestei metode este că un
cuvânt utilizat frecvent are o probabilitate mai mare de a rămâne în memoria
cache decât un cuvânt care nu a fost utilizat frecvent. Un dezavantaj este că
acele cuvinte care au fost încărcate recent în memoria cache au o valoare mică
a contorului, în ciuda faptului că este probabil ca ele să fie utilizate din nou. Un
alt dezavantaj este că implementarea acestei metode prin hardware este mai
dificilă şi deci mai costisitoare.
Cel mai puţin recent utilizat (LRU - Least Recently Used). Această metodă
are performanţa cea mai bună raportată la cost comparativ cu celelalte tehnici,
fiind implementată adesea în sistemele reale. Ideea acestei metode de înlocuire
constă în faptul că un cuvânt, care nu a fost utilizat pentru o perioadă lungă de
timp, are o şansă mai redusă de a fi utilizat în viitorul apropiat, conform
proprietăţii de localitate temporală. Astfel, această metodă reţine cuvintele din
memoria cache care au probabilitatea cea mai mare de a fi utilizate din nou. In
acest scop, se utilizează un mecanism pentru a păstra evidenţa acelor cuvinte
care au fost accesate cel mai recent. Cuvântul care va fi eliminat este cuvântul
care nu a fost utilizat pentru perioada cea mai lungă de timp. O posibilitate de a
implementa un asemenea mecanism este de a asigna un contor fiecărui cuvânt
din memoria cache. De fiecare dată când este accesată memoria cache,
contorul fiecărui cuvânt este incrementat, iar contorul cuvântului care a fost
accesat este resetat la zero. In acest fel, cuvântul cu contorul cel mai mare este
cel care a fost utilizat cel mai puţin recent.

Evaluare