Sunteți pe pagina 1din 121

Haller Piroska

Arhitectura
sistemelor de calcul
Haller Piroska

Arhitectura
sistemelor de calcul

2021
Cuprins
1. Introducere ...................................................................................................................... 3
2. Fundamentele sistemelor digitale ................................................................................... 9
2.1 Funcții logice .............................................................................................................. 9
2.2 Elemente de selectare a semnalelor ........................................................................ 12
2.3 Elemente de sincronizare și stocare ........................................................................ 14
3. Setul de instrucțiuni al sistemelor de calcul .................................................................. 16
3.1 Principii de proiectare .............................................................................................. 16
3.2 Set minimal de instrucțiuni ...................................................................................... 20
3.3 Extinderea setului de instrucțiuni ............................................................................ 24
3.4 Moduri de adresare ................................................................................................. 25
3.5 Extinderea instrucțiunilor de control ....................................................................... 27
3.6 Compararea modelului RISC vs. CISC ....................................................................... 32
4. Unitatea aritmetică și logică .......................................................................................... 34
4.1 Unitatea aritmetică .................................................................................................. 34
4.2 Reprezentarea numerelor ........................................................................................ 35
4.3 Circuite de adunare .................................................................................................. 41
4.4 Extinderea unității aritmetice și logice .................................................................... 43
4.4.1 Circuite de înmulțire ......................................................................................... 43
4.4.2 Proiectarea unui circuit de înmulțire secvențial ............................................... 44
4.4.2 Unitatea de control cablată .............................................................................. 46
4.4. 3 Unitatea de control microprogramată ............................................................. 48
4.5 Unitatea aritmetică în virgulă flotantă..................................................................... 50
4.6 Procesare paralelă.................................................................................................... 53
4.6.1 Operații aritmetice și logice pe vectori ............................................................. 53
5. Unitatea de control al unității centrale de prelucrare ................................................... 55
5.1 Transfer registre ....................................................................................................... 55
5.2 Unitatea de control .................................................................................................. 56
5.3 Proiectarea unității de control microprogramate ................................................... 59
5.4 Tehnici pipeline în proiectarea unității centrale de prelucrare ............................... 62
6. Organizarea memoriei ................................................................................................... 68
6.1 Tipuri de memorie.................................................................................................... 68
6.1.1 Indicatori de performanță................................................................................. 68
6.1.2 SRAM ................................................................................................................. 69
6. 1. 3 DRAM .............................................................................................................. 72
6. 1. 4 Memorii nevolatile .......................................................................................... 74
6.1.5 Memorii asociative............................................................................................ 74
6.2 Organizarea modulelor de memorie........................................................................ 76
6.2.1 Tehnici de selecție ............................................................................................. 76
6.2.2 Organizare întrețesută ...................................................................................... 78
6.2.3 Module suprapuse ............................................................................................ 80
6.3 Memorii cache ......................................................................................................... 83
6.3.1 Metode de implementare ................................................................................. 84
7. Sistemul de intrare ieșire ............................................................................................... 92
7.1 Operații de intrare - ieșire ........................................................................................ 92
7.1.1 Magistrala simplă controlată de o singură unitate de control ......................... 92
7.1.2 Conectarea unui port de intrare – ieșire pe magistrală .................................... 94
7.1.3 Interfață de intrare-ieșire, modul de lucru prin interogare .............................. 98
7.2 Întreruperi .............................................................................................................. 102
7.3 Transfer de date cu acces direct la memorie (DMA) ............................................. 106
8. Suport pentru sisteme de operare ............................................................................... 111
8.1 Adresare virtuală .................................................................................................... 111
8.2 Adresare virtuală prin paginare ............................................................................. 112
8.3 Adresare virtuală prin segmentare ........................................................................ 115
8.4 Mașini virtuale........................................................................................................ 117
Bibliografie ....................................................................................................................... 119

2
1. Introducere
Vom începe prin a defini fiecare termen din titlul disciplinei. Un sistem reprezintă o
mulțime de componente interconectate cu scopul de a forma o unitate. O componentă nu
poate fi la rândul ei sistem? Poate. Unde ne oprim în descompunerea unui sistem depinde de
setul de funcții de bază la care raportăm descrierea, depinde de disciplina studiată. Orice
sistem interacționează cu mediul înconjurător prin intrări și ieșiri bine definite, realizând un
set de transformări (funcții, operații) între ele (Figura 1.1). Putem studia sistemele din punct
de vedere al structurii lor interne, sau din punct de vedere funcțional, comportamental. Din
punct de vedere funcțional sistemele pot fi:
• cu funcții fixe stabilite la proiectare;
• cu funcții ce pot fi modificate prin intrările speciale ale sistemului;
• cu funcții adaptive care se schimbă determinist sau probabilistic în funcție de
intrări și starea sistemului.
Arhitectura unui sistem este o descriere formală a acestuia, un model, care va pune în
evidență structura dar și comportamentul sistemului. Ca orice model este doar o aproximare
a sistemului real, o simplificare a acestuia cu scopul de a defini, explica, înțelege aspectele
importante, principiile generale ale sistemelor de calcul. Înțelegând principii vom fi capabili de
a folosi eficient sistemul de a propune unele îmbunătățiri, sau de a crea sisteme noi, chiar și
principii noi.
Calculatorul este un sistem care transformă un set de date de intrare în date de ieșire
folosind un set de instrucțiuni predefinite, dar ordinea de execuție a instrucțiunilor va fi
stabilită dinamic prin intrări speciale.

Figura 1.1: Reprezentarea generală a unui sistem

În acest moment verificați dacă calculatorul, telefonul, tableta folosită se


poate încadra în definițiile de mai sus, sau trebuie extinsă și cu alte noțiuni.
Încercați să identificați noțiunile de bază ale modelului descris!

3
Noi vom folosi în curs noțiunea de sistem de calcul în sensul general, care include senzori
inteligenți; calculatoare încorporate din mașini, frigidere sau mașini de spălat; telefoane
mobile; echipamente de rețea; calculatoare de proces; calculatoare de uz personal.
Descrierea unui sistem de calcul poate fi realizat pe mai multe nivele de abstractizare cum
ar fi:
• algoritm;
• limbaje de programare;
• ISA - setul de instrucțiuni al sistemului de calcul;
• micro-arhitectură;
• transfer registre;
• porți;
• circuite;
• fenomene fizice.
Un nivel superior poate utiliza funcțiile nivelului inferior(denumit și interfața) fără a
cunoaște detaliile de implementare al nivelului inferior.
Majoritatea nivelelor vor fi studiate la alte discipline, iar cursul de față va include noțiunile
și detaliile de implementare ale nivelelor ISA, micro arhitectură și transfer registre dar și
legăturile cu nivelele superioare și inferioare.
Un algoritm este o secvență de instrucțiuni executate după un set de reguli predefinit. Un
calculator de uz general permite introducerea și rularea algoritmilor definiți de utilizator
(denumit și program). Putem compara pentru început executarea unui algoritm de calcul
manual (a) şi cel al sistemului de calcul (b) (Figura 1.2).
Putem distinge clar cele două etape ale procesării manuale: interpretarea informației și
executarea diverselor instrucțiuni, aceasta din urmă putând fi preluată de diferite
echipamente ajutătoare (abac, calculatoare mecanice, calculatoare de buzunar etc).
Elementele caracteristice ale calculatoarelor sunt similare. Unitatea de memorie
stochează instrucțiuni și date. Unitatea centrală de prelucrare conține o unitate de control,
care interpretează și realizează secvențierea instrucțiunilor, și o unitate aritmetică și logică,
care execută instrucțiuni.
Diferența majoră dintre cele două sisteme constă în reprezentarea informației. Omul
folosește un limbaj natural cu număr foarte mare de simboluri pentru reprezentare, şi
reprezintă numerele (în mod uzual) în baza 10. Calculatoarele moderne, pornind de la natura
fizică a elementelor electronice, reprezintă informația în baza 2, reducând numărul
simbolurilor. Comunicarea dintre mașina și om, conversia informației din limbajul natural în
limbaj mașină și invers este realizat de echipamentele de intrare-ieșire.
Din punctul de vedere al programatorului există mai multe metode de a descrie
transformarea datelor de intrare în date de ieșire folosind diferite paradigme de programare
cum ar fi programarea imperativă sau programare declarativă, care la rândul ei poate fi
programare funcțională, programare logică, programare flux de date. Scopul nostru nu este

4
de a analiza toate paradigmele de programare, vrem să extragem cerințele comune pentru
proiectarea și implementarea nivelelor de abstractizare inferioare.

Figura 1.2 Executarea unui algoritm a) manual, b) cu un sistem de calcul

Toate limbajele imperative au elemente comune cum ar fi setul de instrucțiuni,


introducerea datelor și al instrucțiunilor, prezentarea rezultatelor, stocarea datelor și al
instrucțiunilor, controlul explicit al secvenței de execuție al instrucțiunilor.
Limbajele imperative reprezintă o abstractizare de nivel înalt a conceptelor din sistemul
de calcul, variabile stocate în locații predefinite, în urma instrucțiunilor executate variabilele
își schimbă valoarea (starea sistemului se schimbă), secvența următoare de instrucțiuni
depinde de starea curentă și de instrucțiunea de control ce urmează să fie executată. La
proiectarea arhitecturii calculatoarelor s-a ținut cont de abstractizare optimizând performanța
sistemelor pentru această formă de descriere.
Cel mai simplu model de calcul pentru aceste limbaje reprezintă mașina Turing.
Orice funcție matematică calculabilă, orice algoritm poate fi implementată pe mașina
Turing (Figura 1.3). Conform teoremei Church-Turing toate limbajele de programare pot
rezolva aceeași tip de probleme indiferent chiar de paradigma de programare.

5
Figura 1.3 Mașina abstractă Turing

Dacă un algoritm general poate fi descris ca o combinație între evaluarea expresiilor și


controlul fluxului, în limbajele de programare declarative, controlul fluxului explicit de către
programator lipsește în limbajele declarative, și va fi generat automat de mașina abstractă ce
va evalua expresiile. Acest aspect permite verificarea formală și automată a corectitudinii
programelor scrise în limbaje declarative.
Programarea funcțională bazată pe teoria funcțiilor nu operează cu stări și cu variabile
stocate, ele se bazează pe compunerea funcțiilor fără atribuiri și iterații (ex. Haskell). Sistemele
de calcul pot executa și programele în această paradigmă.
Programarea logica se bazează pe expresii logice și pe demonstrații automate ale
expresiilor (ex. PROLOG).
Analizând modelul arhitectural al mașinii Turing, memoria calculatorului este o bandă
magnetică fără capete, împărțita în unități de dimensiuni egale, capabilă de a stoca simboluri.
Procesorul este un circuit secvențial cu număr finit de stări. Instrucțiunile pe care le poate
efectua și care alcătuiesc setul de instrucțiuni, sunt următoarele:
• schimbă simbolul de pe bandă de la poziția curentă;
• poziționează capul de citire cu o poziție la dreapta;
• poziționează capul de citire cu o poziție la stânga;
• oprește sistemul.
Pentru a realiza un calcul cu această mașina, se înscriu datele într-un cod convenabil, și se
descompune algoritmul de calcul în funcție de modul de reprezentare a datelor într-o secvență
de instrucțiuni ale mașinii. Ultima instrucțiune este cea de oprire a mașinii, la care banda
trebuie să conțină rezultatul calculului.

Exemplu: Adunarea a două numere naturale cu mașină Turing.


Orice număr natural n poate fi reprezentat cu un șir alcătuit din n unități. Numerele sunt
separate de spatii. Cele două numere ce urmează a fi adunate sunt stocate unul după altul pe
banda magnetică. Adunarea lor constă în înlocuirea spațiului delimitator dintre ele cu o
unitate, iar ultima unitate va fi înlocuită de un spațiu.
Din studiul acestui model abstract rezultă următoarele limitări ale sistemelor de calcul
reale față de mașina abstractă Turing:
• mașina nu poate stoca răspunsul la toate problemele posibile, are un număr finit
de stări;
• spațiul de stocare al datelor este finit;

6
• timpul de execuție trebuie să fie finit.

La nivelul de abstractizare studiat la acest curs sistemul de calcul primește la intrare date
și instrucțiuni și generează date de ieșire toate fiind reprezentate cu ajutorul numerelor
binare, numere scrise în baza 2. La acest nivel vom avea nevoie doar de 2 simboluri (notate
uzual cu 0, și 1 ) pentru a reprezenta date și instrucțiuni, așa cum vom vedea în cursurile
următoare. O singură cifră binară este unitatea de bază al sistemelor digitale și este denumit
bit.
Motivul pentru care s-a ales baza 2 este unul foarte simplu, la nivelul fizic trebuie să
construim sistemul din circuite care au doar două stări (puteți încerca să construiți un
calculator doar din întrerupătoare și becuri - se poate). Numărul binar este doar o
reprezentare abstractă a semnalelor fizice care au două stări, în cazul semnalelor electrice 2
tensiuni posibile. În realitate orice semnal este continuu în timp și are o viteză de variație
finită, ea nu va fi un semnal digital pur. Un semnal analogic este un semnal continuu care
variază în timp, iar tensiunea va avea un număr infinit de valori reale (Figura 1.4).

Figura 1.4 Compararea unui semnal analog și digital

Dacă analizăm forma de undă a semnalelor digitale (măsurând sau vizualizând cu un


osciloscop) vom putea evidenția o serie de distorsiuni, zgomote, interferențe datorate
componentelor electrice de care se va ține cont la proiectarea sistemului la nivelul circuitelor
electrice (Figura 1.5). Dacă analizăm însă starea semnalului la momente de timp discrete
(suficient de rar față de viteza de variație a semnalului) atunci ea va avea totdeauna una din
cele 2 stări. Ambele stări corespund unor intervale de valori de tensiune. Această aproximare
ne permite utilizarea algebrei booleene și a logici matematice pentru descrierea și verificarea
funcționalității sistemelor de calcul. Problema timpului, al semnalelor continue va fi tratată
numai în cazurile când acesta este indispensabilă pentru descrierea corectă a componentei
studiate.

7
Figura 1.5 Forma de undă reală a semnalului digital periodic

Scopul principal al cursului este:


• de a înțelege din perspectiva programatorului interfața dintre soft și hard;
• de a înțelege cum influențează componentele hard performanța unui program;
• de a dezvolta aplicații având performantă mai bună;
• de a înțelege cum a influențat dezvoltarea soft arhitectura sistemelor noi;
• de a proiecta componente noi, de a interfața sistemele existente cu echipamente;
• de a propune noi principii de funcționare a sistemelor de calcul.

8
2. Fundamentele sistemelor digitale

2.1 Funcții logice

O variabilă booleană (variabilă logică) poate avea două valori, reprezentată prin
simbolurile 0 și 1, care corespund valorilor logice de FALS (FALSE) sau ADEVĂRAT (TRUE).
Algebra booleană (numită și logica matematică) definește operațiile de bază definite pe
mulțimea variabilelor booleene și studiază proprietățile acestora.
• Operatorul SAU (OR) aplicat pe două variabile booleene va genera un răspuns
adevărat dacă cel puțin una din variabile are valoarea de ADEVĂRAT.
• Operatorul ȘI (AND) aplicat pe două variabile booleene va genera un răspuns
adevărat dacă toate variabilele au valoarea de ADEVĂRAT.
• Operatorul de NEGARE (NOT) va schimba valoarea variabilei din ADEVĂRAT în FALS
și invers.
Algebra booleană fiind folosită în domenii foarte diferite de la filozofie la inginerie există
un număr mare de notații în literatura de specialitate pentru notarea și definirea operațiilor
de bază (Figura 2.1).

Figura 2.1 Operatori logici

Cu ajutorul operatorilor de bază definite mai sus putem definii orice funcție logică definită
pe două sau mai multe variabile booleene din acest motiv ele sunt denumite și mulțime
completă de operatori logici.
Tabela de adevăr este cea mai simplă formă de a descrie o funcție logică, care va conține
toate combinațiile posibile ale intrărilor, și valoarea funcției pentru fiecare combinație.

9
Funcția logică AND pe două variabile are proprietatea de a avea o si singură valoare 1 în
tabela de adevăr, pentru cazul în care ambele variabile de intrare au valoarea 1. Pornind de la
această proprietate dacă funcția f are o singură valoare de 1 în tabela de adevăr pentru
combinația de intrare X=0, Y=1 ea poate fi scrisă formal folosind simbolurile algebrice:
𝑓 = 𝑋̅ ∙ 𝑌 (f este egal cu X negat ȘI Y).
Dacă funcția f1 are două valori de 1 în tabela de adevăr, pentru combinațiile intrărilor X=0,
Y=1 respectiv X=1, Y=0, fiecare termen se va scrie cu ajutorul funcției ȘI iar termenii vor fi
combinați folosind funcția logică SAU. Astfel funcția f1 denumită și SAU-Exclusiv (XOR) poate
fi scrisă formal:
𝑓1 = 𝑋̅ ∙ 𝑌 + 𝑋 ∙ 𝑌̅ (f1 este egal cu X negat ȘI Y SAU X ȘI Y negat) și va fi adevărat dacă
intrările sunt diferite.
Pentru două variabile booleene există 4 combinații posibile de valori și putem defini 16
funcții booleene (Figura 2.2).

Z N N N
E A X Y X N E O X O Y A O
R N > > O O O Q T ≤ T ≤ N N
XY O D Y X X Y R R R U Y Y X X D E
00 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
01 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
10 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
11 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
Figura 2.2 Toate funcțiile logice pentru 2 variabile

Este interesant de remarcat că pornind de la proprietățile operatorilor logici, mulțimea


completă de operatori cu ajutorul căreia putem defini orice funcție logică poate fi redusă la
{OR, NOT}, {AND, NOT}, {NAND}, {NOR}...
Opertorii NAND, și NOR se pot obține prin negarea valorii obținute în urma aplicării
operatorilor AND și OR. Ele au semnificație în inginerie deoarece funcția logică nu se schimbă,
dar ieșirea va fi inversată. Noi vom folosi forma canonică de scriere a funcțiilor folosind
mulțimea completă de operatori { AND, OR, NOT} prezentată mai sus.
Circuitele logice corespunzătoare funcțiilor logice (porți logice) pot avea mai multe intrări,
de exemplu o poartă ȘI cu n intrări va avea la ieșire valoarea 1 dacă toate intrările vor avea
simultan valoarea l. Formal putem scrie funcția 𝑓 = 𝑋1 ∙ 𝑋2 ∙ … 𝑋𝑛. Poarta SAU cu n intrări va
genera valoarea 1 la ieșire dacă cel puțin una din intrările sale are valoarea 1. Ce funcție
implementează o poartă SAU-EXCLUSIV cu n intrări, 𝑓 = 𝑋1⨁𝑋2 ⨁ … 𝑋𝑛 ?

10
Presupunem că avem un bec (alarmă) care poate fi activat dacă semnalul de
comandă are valoarea 1, și n senzori de mișcare care vor genera la ieșire un
semnal cu valoarea 1 când detectează mișcare. Folosind o poartă SAU cu n
intrări vom putea acționa becul (alarma). Ce se întâmplă dacă senzorul de
mișcare lucrează în logica negativă si generează la ieșire valoarea 0, când
detectează mișcare?

Vom analiza în continuare modul de funcționare al porților logice utilizând diagrame de


timp, pentru a pune în evidență transformarea, propagarea semnalelor prin aceste circuite
(Figura 2.3). Vom lucra cu forma ideală a semnalelor (viteză de variație infinită) de fiecare dată
când nu este necesar să punem în evidență caracteristicile semnalelor reale din punct de
vedere al modelului studiat. Analizând diagramele de timp, este extrem de important să
înțelegem corect noțiunea de simultaneitate a intrărilor. În limbajul natural când descriem
condiții logice legate de evenimente evocăm simultaneitatea lor, fără ca să ne gândim prea
mult la forma semnalelor generate. Un semnal care este în starea 1 pentru o durată de timp
predefinită este numită impuls dreptunghiular, sau simplu impuls, dacă este vorba de circuite
digitale. Exemplu: dacă ambele butoane sunt acționate simultan se schimbă starea sistemului.
Înainte de a conecta ieșirea celor două butoane la o poartă ȘI va trebui să analizăm dacă
butoanele generează la ieșire impulsuri suficient de lungi pentru a îndeplini condiția de
simultaneitate la nivel de semnale, în caz contrar, se poate întâmpla ca ele să genereze
impulsuri, care sunt decalate în timp (probabil nesesizabile omului) dar la nivelul porții ȘI
intrările să nu aibă valoarea 1 simultan.

Figura 2.3 (a) poarta ȘI (b) poarta SAU

Folosind o poartă ȘI putem controla propagarea unui semnal periodic denumit tact (ceas)
modificând starea intrării de control; dacă intrarea de control are starea 0, semnalul nu apare
la ieșire, starea ieșirii fiind 0; dacă starea intrării de control este 1 la ieșire vom avea semnalul
de la intrare nemodificat (Figura 2.4).

11
Figura 2.4 Activarea/ dezactivarea unui semnal

2.2 Elemente de selectare a semnalelor

Transmiterea semnalelor provenite de la mai multe surse, sau distribuirea acestora la mai
multe destinații este elementul de bază în comunicațiile interne și externe ale sistemelor de
calcul.
Dacă avem un număr mare de componente ce vor fi controlate la distanță prin semnale
digitale pentru fiecare componentă avem nevoie de o linie de comunicație între sursă
(elementul de comandă) și destinație elementul acționat. Folosind tehnica codificării binare
putem atribui fiecărei componente un identificator unic denumit adresă. Pentru a codifica 2 n
numere vom folosi doar n biți, deci transmiterea adreselor la distanță necesită doar n linii de
semnal. Ex. cu 16 linii de adresă vom putea selecta 65536 componente distincte și prin
construcția circuitului asigură condiția de a selecta o singură componentă.
În același timp avem nevoie de un circuit specializat, denumit decodificator care va selecta
componente corespunzătoare în funcție de adresa primită. Decodificatorul are n intrări și 2n
ieșiri, cu o singură ieșire în starea 1 la un moment dat în funcție de codul de intrare. Pentru un
decodificator de 3 biți putem descrie modul de funcționare prin tabela de adevăr (Figura 2.5).
Dacă se dorește transmiterea datelor binare de la mai multe surse la o destinație este
nevoie de un circuit selector (comutator digital) care va permite transmiterea datelor de la
sursa selectată la ieșire. Selectarea intrărilor se va realiza pe baza adreselor (numărul de
ordine) acestora. Multiplexorul este un circuit care are n linii de selecție și 2n intrări, iar
intrarea selectată va fi conectată la ieșire. Adresa, numărul de ordine al intrării va fi codificată,
astfel pentru a transmite la distanță date de la 2n surse este nevoie de 1 linie de date și n linii
de selecție ce vor fi transmise. Timpul total de transmisie fiind egală cu suma timpilor de
transmisie de la fiecare sursă. Această formă de transmisie date care reduce numărul de linii

12
de comunicație poate fi utilizată dacă rata de generare a datelor de la o intrare este mai mică
decât rata de transmisie a datelor de la intrarea respectivă, având în vedere că avem un canal
de comunicare partajat de mai multe surse (Figura 2.6).

A2 A1 A0 D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 0 0 0 0 0 0 1
0 0 1 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 1 0 0
0 1 1 0 0 0 0 1 0 0 0
1 0 0 0 0 0 1 0 0 0 0
1 0 1 0 0 1 0 0 0 0 0
1 1 0 0 1 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0 0

Figura 2.5 Decodificator 3:8

Dacă datele binare recepționate vor ti distribuite către mai multe destinații se va utiliza
un circuit demultiplexor. Circuitul demultiplexor, are o linie de date n linii de selecție și 2 n
ieșiri. Selectarea liniei de ieșire la care se trimit datele de intrare se va realiza în funcție de
numărul codificat binar de pe liniile de selecție (adresa).

C1 C0 Y C1 C0 Y0 Y1 Y2 Y3
0 0 X0 0 0 X 0 0 0
0 1 X1 0 1 0 X 0 0
1 0 X2 1 0 0 0 X 0
1 1 X3 1 1 0 0 0 X

Figura 2.6 Multiplexor, demultiplexor

13
2.3 Elemente de sincronizare și stocare

În toate sistemele de calcul presupunem că biții unui operand, instrucțiune se vor schimba
simultan, transmiterea lor între componente se va realiza sincron. Ținând cont de forma reală
a semnalelor, de întârzierile diferite a semnalelor transmise pe diferite linii de comunicare,
introducerea și stocarea semnalelor în sisteme de calcul se va realiza utilizând bistabil de tip
D (Figura 2.7). Aceste circuite cu două stări stabile sunt capabile de a stoca informația de un
bit, iar starea lor se va modifica sincron cu semnalul de tact. Modificarea ieșirii are loc pe
frontul căzător (trecerea semnalului de la starea 1 la starea 0) respectiv pe frontul crescător
(trecerea semnalului de la starea 0 la starea 1) al semnalului de tact după tipul ales. Orice
modificare a semnalului de date nu va modifica ieșirea, valoarea acestuia fiind luată în
considerare doar pe frontul activ al semnalului de tact. În acest sens circuitul realizează
sincronizarea semnalului aplicat pe intrarea D cu tactul T și memorarea valorii acestuia. Pentru
funcționarea corectă a circuitului de memorare se presupune că semnalul de date este stabil
pe frontul activ al semnalului de tact. Datele trebuie să fie valide înainte de frontul activ al
semnalului de tact cu un timp de prestabilire și trebuie să rămână active după front un pentru
o durată egală cu timpul de menținere pentru funcționarea corectă a circuitului.

Figura 2.7 Bistabil de tip D

Aplicând aceeași semnale de tact pe mai multe bistabili vom obține o serie de ieșiri
sincronizate. La toate nivele de abstractizare studiate de noi vom presupune că toate datele
sunt sincronizate, iar transferul intern și procesarea datelor se va realiza sincron. În acest sens
un număr de n bistabili de tip D cu tact comun vor alcătui un registru, capabil de a stoca n biți
(Figura 2.8). Pentru a fi utilizat în stocarea datelor am adăugat 2 proprietăți. Intrarea de Reset
va aduce toate ieșirile în starea 0 în mod asincron, indiferent de starea tactului. În mod normal
ieșirile unui circuit digital vor avea unul din cele 2 stări logice 0, sau 1, respectiv tensiunile
corespunzătoare stărilor. În mod special, există și circuite care pe lângă cele 2 stări definesc
un al treilea, și anume impedanță ridicată (H.Z.). Această stare permite conectarea împreună
a mai multor ieșiri dacă la un moment de timp toate vor fi în impedanță ridicată exceptând cel
selectat. Intrarea de validare EN al circuitului permite schimbarea stării tuturor ieșirilor în
impedanță ridicată, dacă valoarea semnalului EN = 0.

14
Reset clk EN Reg_out
0 X X 0
1 X 0 H.Z.
1 0 1 Reg anterior
1 1 1 Reg anterior
1 ↑ 1 Reg_in

Figura 2.8 Registru cu 8 biți

Nu este necesar ca toate registrele din sistem să modifice starea la fiecare tact. Semnalul
de tact poate fi dezactivat în anumite condiții logice, utilizând circuite de activare/ dezactivare
(Figura 2.4). Sistemul nostru de calcul poate fi văzut ca un sistem secvențial în care starea
sistemului actual împreună cu intrările va determina starea următoare și ieșirile sistemului
prin condițiile logice impuse (Figura 2.9), iar schimbarea de stare se va realiza totdeauna
sincron cu tactul.

Figura 2.9 Un sistem de calcul - sistem secvențial

15
3. Setul de instrucțiuni al sistemelor de calcul

3.1 Principii de proiectare

Acest nivel de abstractizare reprezintă una din cele mai mari provocări, de ea depinzând
succesul implementării fizice a sistemelor. Unul din cei mai renumiți matematicieni János
Neumann (1903-1957) cu contribuții multiple în diferite domenii ale matematicii, a definit
principiile fundamentale ale arhitecturii sistemelor de calcul, și a realizat prima descriere
abstractă a sistemelor de calcul la nivelul setului de instrucțiuni. Ingeniozitatea lui este
confirmat de faptul, că până la ora actuală sistemele de calcul folosesc aceeași principii
indiferent de complexitatea acestora, iar modelul arhitectural general al sistemelor de calcul
poartă numele de arhitectura von Neumann. Publicațiile lui numai în domeniul sistemelor de
calcul cuprind domenii cum ar fi:
• arhitectura și principiile de proiectare ale sistemelor de calcul;
• programare și diagrame de flux de date;
• sisteme de procesare paralelă și de viteze mari;
• teoria automatelor și constructorul universal.
A contribuit activ la proiectarea și realizarea primului calculator electronic (IAS), proiect
în care a stabilit arhitectura care îi poartă numele și principiile, care reprezintă punctul de
pornire și astăzi al proiectării sistemelor .
Vom studia aceste principii în continuare și vom arăta care sunt avantajele, dezavantajele,
care sunt modificările majore aduse în arhitecturile sistemelor de calcul actuale.
Vom porni de la un sistem simplificat, un set de instrucțiuni redus și vom adăuga treptat
componentele și instrucțiunile justificând de fiecare dată care au fost argumentele
introducerii acestor noi componente, și ce efecte au avut asupra performanței sistemelor din
perspectiva nivelelor superioare.
Arhitectura de bază propusă va conține trei componente mari: unitatea centrală de
prelucrare, memorie și echipamentele de intrare ieșire. Unitatea centrală de prelucrare
execută instrucțiunile, va controla transferul datelor între componentele sistemului și va
controla ordinea de execuție a instrucțiunilor. Setul de instrucțiuni al acestui este fix și
prestabilit la proiectare și va determina structura unității aritmetice și logice, care
implementează aceste operații. Memoria va stoca datele și instrucțiunile, fiecare unitate de
stocare are un identificator unic denumit adresă. În mod uzual considerăm capacitatea unității
de stocare ca fiind de 8 biți, denumit octet sau byte. Există două modele distincte de conectare
a memoriilor (Figura 3.1).
În modelul arhitectural Harvard unitatea centrală de prelucrare are conexiuni separate
pentru memoria de date și cea de instrucțiuni. Acest lucru permite accesarea simultană a lor
reducând astfel timpul de extragere date și instrucțiuni, dar numărul liniilor de conexiuni se
dublează. In modelul arhitectural Neumann nu există diferențe între memoria de date și cea
pentru instrucțiuni, existând o singură memorie. În acest caz citirea instrucțiunilor și a datelor

16
se va realiza secvențial. Argumentația lui Neumann pentru acest model a fost extinderea
posibilităților ca un program să poată modifica propria secvență de instrucțiuni oferind astfel
posibilitate de autoadaptare algoritmilor. Spațiul de stocare al unui algoritm (program) se
reduce foarte mult, ea nu trebuie să conțină toate combinațiile posibile de secvență de cod
pentru toate combinațiile posibile ale intrărilor, numărul lor fiind foarte mare, iar majoritatea
lor nu va fi întâlnită pe durata de execuție a programului. Totuși această arhitectură a devenit
răspândită datorită numărului mai mic de linii de conexiuni pentru sisteme cu capacitate mare
de adresare, oferind posibilitatea ca un program să modifice secvența de cod al altui program,
denumit uzual virus.

(a)

(b)

Figura 3.1 Arhitectura (a) Neumann ȘI (b) Harvard

Pentru sisteme încorporate în care întreg sistemul de calcul cu toate componentele


acestuia (unitatea centrală de prelucrare, memorie, diferite interfețe de intrare ieșire) sunt
incluse într-un singur circuit, iar spațiul de memorie este redus, arhitectura Harvard oferă

17
performanțe de calcul mai bune. Echipamentele de intrare - ieșire permit introducerea datelor
și a instrucțiunilor în sistem precum și reprezentarea datelor într-un format accesibil omului.
Ele vor realiza transformarea semnalelor fizice în formatul de reprezentare intern al
sistemului, precum și interconectarea acestor echipamente la magistrala sistemului prin
interfețe, care permit accesul la aceste date într-un mod unitar. La nivelul de abstractizare al
setului de instrucțiuni orice echipament de intrare - ieșire va fi accesat print-un set de porturi,
fiecare port având atașat o adresă unică.
Fiecare instrucțiune (Figura 3.2) trebuie să conțină tipul operației ce urmează a fi
executat, adresele operanzilor, adresa de depozitare a rezultatului, precum și adresa
instrucțiunii care urmează. În acest fel fiecare instrucțiune va determina următoarea
instrucțiune ce va fi executată în funcție de starea curentă a sistemului.

Adresa Adresa Adresa Adresa inst.


Tip operație
operand1 operand2 rezultat următoare
Figura 3.2 Formatul instrucțiunilor

Pornind de la arhitectura de bază (Figura 3.3) și din analiza algoritmilor, Neumann a definit
o serie de principii de proiectare indicând în același timp și impactul lor asupra performanței
sistemului. În continuare vom descrie forma actualizată a acestor principii introducându-le
gradual în acest curs.
1. Din analiza algoritmilor rezultă în general că operanzii și rezultatul operației
curente vor fi folosite în operațiile succesive astfel se propune ca operanzii și
rezultatul instrucțiunilor aritmetice și logice să fie stocate în interiorul unității
centrale de prelucrare în registre pentru a crește viteza de procesare. Acest lucru
reduce timpul de execuție, deoarece timpul de acces la datele din registre interne
este mult mai mic decât timpul de acces la memorie. Numărul biților de adresă din
instrucțiune pentru selectarea operanzilor se reduce și ea, deoarece spațiul de
adresare al memoriei este mult mai mare decât cel a registrelor. Neumann a mers
chiar mai departe și a propus o formă compactă a instrucțiunilor, adăugând o
convenție de proiectare: unul din operanzii și rezultatul operației va fi stocat
totdeauna într-un registru special denumit acumulator (A), iar instrucțiunea va
conține doar adresa unui singur operand.
2. Majoritatea instrucțiunilor dintr-un algoritm se vor executa în ordinea succesivă a
scrierii lor, și trebuie să existe instrucțiuni speciale care permit saltul la o altă
secvență de instrucțiuni la îndeplinirea anumitor condiții. Un circuit specializat,
care ține evidența adreselor secvențiale ale instrucțiunilor, și are posibilitatea de
a fi încărcat cu o valoare nouă permite excluderea câmpului de adresa instrucțiunii
următoare din instrucțiunea curentă. Acest circuit care și-a păstrat denumirea
arhaică de numărător de program (PC) dar este prezent în orice sistem modern,
este un circuit numărător cu încărcare paralelă și intrare de RESET.

18
Figura 3.3 Arhitectura de bază

Întregul sistem este organizat în jurul magistralei, care va conecta toate componentele.
Magistrala reprezintă o serie de conexiuni comune mai multor componente, care comunică
între ele, dar o singură sursă transmite la un moment de timp dat.
Poate realiza comunicații punct la punct sau de tip difuzare, și în funcție de numărul liniilor
de date poate fi:
• paralel – toți biții unui cuvânt se transmit simultan și sincronizat;
• serial – biții unui cuvânt se transmit secvențial.
Trebuie să includă un mecanism de arbitrare, pentru selecția sursei, care în cazul unui
sistem de calcul este adresa, care va fi totdeauna transmisă de către unitatea centrală de
prelucrare împreună cu semnalele de selecție al direcției transferului (citire, scriere).
Execuția instrucțiunilor se realizează în unitatea aritmetică și logică, care primește
operanzii din acumulator (A), din registrul de date (RD), iar rezultatul va fi stocat în
acumulator. Operațiile aritmetice și logice setează un set de indicatori de stare (Flags)
conectat la unitatea aritmetică și logică. Din punct de vedere al memoriei nu există diferențe
dintre date și instrucțiuni, dar în interior instrucțiunile vor fi stocate separat (RI). Circuitul de
control primește date din registrul de instrucțiuni (RI) pe care le decodifică. Operațiile din
sistem sunt sincronizate de un ceas intern.
Unitatea centrală de procesare va controla transferul datelor prin magistrala de date,
adrese și control. Registrul de adrese (RA) conține adresa operandului, valoarea operandului
va fi transferat totdeauna prin intermediul registrului de date (RD) iar direcția transferului va
fi stabilită pe baza semnalelor de control setate în registrul de control (RC). Numărătorul de
program (PC) conține adresa instrucțiunii următoare, care în mod normal este incrementat
după fiecare instrucțiune, dar în cazul instrucțiunilor de control, va fi suprascris cu adresa
instrucțiunii următoare din registrul de instrucțiune.
Această arhitectură de bază poate fi extinsă cu registre de uz general asemănător
acumulatorului care vor conține operanzii. Timpul de execuție al instrucțiunii se reduce
considerabil, dacă operanzii sunt in unitatea centrală de prelucrare față de transferul lor din

19
memorie la fiecare operație. Dacă lățimea magistralei de date permite extragerea a două
instrucțiuni simultan se reduce numărul de accese la memorie, dar instrucțiunea care nu va fi
imediat executată se stochează în registrul buffer instrucțiuni (RBI), iar cealaltă instrucțiune în
registrul de instrucțiuni, unde va fi decodificată.

3.2 Set minimal de instrucțiuni

Vom porni de la un set de instrucțiuni suficient de simple, ușor de implementat cu


următoarele tipuri de instrucțiuni (Figura 3.4):
• aritmetice și logice;
• de transfer;
• de control.
Cod Tip Operand Descriere
0 AND A, adr și logic între conținutul acumulatorului și operandul de la adresa dată
1 OR A, adr sau logic între conținutul acumulatorului și operandul de la adresa dată
2 NOT A negare conținut acumulator
3 ADD A, adr adună conținutul acumulatorului și operandul de la adresa dată
4 SUB A, adr scade din conținutul acumulatorului operandul de la adresa dată
5 MUL A, adr înmulțirea conținutul acumulatorului cu operandul de la adresa dată
6 SHL A deplasare stânga conținut acumulator
7 SHR A deplasare dreapta conținut acumulator
8 LOAD A, adr încarcă acumulatorul din memorie de la adresa dată
9 STORE A, adr salvează conținutul acumulatorului în memorie la adresa dată
a IN A, adr citește de la portul de intrare de la adresa dată în acumulator
b OUT A, adr scrie conținutul acumulatorului la portul de ieșire de la adresa dată
c JMP adr salt la adresa dată
d JZ adr salt la adresa dată, dacă conținutul acumulatorului este zero
e JC adr salt la adresa dată, dacă în urma operației aritmetice s-a generat
transport (împrumut)
f NOP nici o operație

Figura 3.4 Set simplificat de instrucțiuni

Formatul simplificat al instrucțiunilor (Figura 3.5) pentru această arhitectură de bază


conține un singur câmp de adresă, care va reprezenta adresa operandului pentru instrucțiunile
aritmetice, logice, respectiv instrucțiunile de transfer, și adresa instrucțiunii următoare pentru
instrucțiunile de control.

Tip operație Adresa

Figura 3.5 Formatul simplificat al instrucțiunilor

20
Limbajul cod mașină este forma de reprezentare prin numere binare a instrucțiunilor, iar
limbajul de asamblare este reprezentarea simbolică a instrucțiunilor. Fiecare instrucțiune
poate fi descompusă într-o secvență de microoperații. O microoperație poate fi implementată
ca un transfer condiționat între registre. Unitatea de control realizează secvențierea
instrucțiunilor în funcție de tipul acestora (elaborează secvența corespunzătoare de
microoperații) și generează semnale de control pentru fiecare microoperație. Un ciclu
instrucțiune se descompune în două faze: faza de extragere și faza de execuție. Faza de
extragere este comună tuturor instrucțiunilor, fiind alcătuită din următoarele microoperații:

Microoperație Descriere
RA  PC se transferă adresa instrucțiunii următoare din numărătorul de
program pe magistrala de adresă prin registrul de adrese
RC  MEMR se activează linia MEMR (citire din memorie) pe magistrala de
control prin registrul de control
RD  M(RA) se citesc datele din memorie de la adresa activă pe magistrala de
adrese în registrul de date
RI  RD instrucțiunea citită se transferă din registrul de date în registrul de
instrucțiuni și se decodifică
PC  PC+l se incrementează valoarea numărătorului de program cu lungimea
l a instrucțiunii curente (va conține adresa instrucțiunii următoare)

Faza de execuție diferă la fiecare instrucțiune, în continuare vom prezenta


descompunerea în microoperații a celor mai reprezentative tipuri de instrucțiuni.

ADD A, adr

Microoperație Descriere
RA  RIadr se transferă adresa operandului din registrul de instrucțiuni pe
magistrala de adresă prin registrul de adrese
RC  MEMR se activează linia MEMR (citire din memorie) pe magistrala de
control prin registrul de control
RD  M(RA) se citesc datele din memorie de la adresa activă pe magistrala de
adrese în registrul de date
A  RD + A se adună conținutul acumulatorului cu operandul extras și
rezultatul se înscrie în acumulator

LOAD A, adr

Microoperație Descriere
RA  RIadr se transferă adresa operandului din registrul de instrucțiuni pe
magistrala de adresă prin registrul de adrese
RC  MEMR se activează linia MEMR (citire din memorie) pe magistrala de
control prin registrul de control

21
RD  M(RA) se citesc datele din memorie de la adresa activă pe magistrala de
adrese în registrul de date
A  RD se transferă operandul extras în acumulator

STORE A, adr

Microoperație Descriere
RD  A se transferă operandul din acumulator pe magistrala de date prin
registrul de date
RA  RIadr se transferă adresa operandului din registrul de instrucțiuni pe
magistrala de adresă prin registrul de adrese
RC  MEMW se activează linia MEMW (scriere în memorie) pe magistrala de
control prin registrul de control
M(RA)  RD se scriu datele de pe magistrala de date în memorie la adresa
activă pe magistrala de adrese

JMP adr

Microoperație Descriere
PC  RIadr se transferă adresa instrucțiunii următoare din registrul de
instrucțiuni în numărătorul de program

JZ adr

Microoperație Descriere
PC  RIadr se transferă adresa instrucțiunii următoare din registrul de
instrucțiuni în numărătorul de program, dacă condiția este
îndeplinită;
rămâne valoarea veche, adică adresa instrucțiunii de după JZ,
dacă condiția nu este îndeplinită

De ce s-a incrementat valoare lui PC în faza de extragere, dacă ea se va


suprascrie în faza de execuție?

22
În continuare vom include două exemple de transformare a programului din limbaj de
nivel înalt (C) în limbaj de asamblare pentru setul simplificat de instrucțiuni.

unsigned char a,b,c; LOAD A, 101


a=b+c; ADD A, 102
c=c+2; STORE A, 100
LOAD A, 102
toate variabilele sunt de un byte, și ADD A, 103
sunt stocate la adresele consecutive STORE A,102
a la adresa 100
b la adresa 101
c la adresa 102
constanta 2 la adresa 103

unsigned char i, a; LOAD A, 200


if (i == 5) SUB A, 203
a=0; JZ Et1
else LOAD A, 201
a=a+1; ADD A, 204
STORE A, 201
datele vor fi stocate în memorie: JMP Et2
variabila i la adresa 200 Et1: LOAD A, 202
variabila a la 201 STORE A, 201
constanta 0 la adresa 202 Et2: orice instrucțiune
constanta 5 la adresa 203
constanta 1 la adresa 204

Ce modificări propuneți în setul de instrucțiuni? suprascrie în faza de


execuție? Optimizați codul propus!

23
3.3 Extinderea setului de instrucțiuni

Din analiza arhitecturii de bază, și al setului de instrucțiuni, respectiv din analiza timpilor
de execuție și al frecvenței de apariție al diferitelor instrucțiuni în limbajul cod mașină, rezultă
mai multe alternative de extindere a setului de instrucțiuni și al arhitecturii de bază.
Criteriile pentru extinderea setului de instrucțiuni pot fi definite pe baza următoarelor
parametrii:
• lungimea codului stocat;
• timpul de execuție al instrucțiunii;
• complexitatea unității de control;
• posibilitatea de executare pe bandă rulantă;
• posibilitatea de executare paralelă;
• compatibilitate cu arhitecturi vechi;
• posibilitatea de optimizare a compilatorului;
• posibilitatea de a schimba ordinea de execuție a instrucțiunilor cu scopul de a
reduce operațiile de transfer între memorie și unitatea centrală de prelucrare.
Cea mai importantă modificare structurală este legată de alegerea numărului și a tipurilor
de registre utilizate, iar implementările existente pot fi grupate în următoarele categorii:
• toate să fie de uz general;
• să fie specializate cu funcții speciale adăugate cum ar fi autoincrementarea;
• să fie mai multe seturi identice care se schimbă între ele în cazul apelului de funcții;
• instrucțiunile aritmetice și logice vor definii operanzii în memorie și acumulator;
• instrucțiunile aritmetice și logice vor definii operanzii numai în registre.
În continuare vom compara și analiza avantajele și dezavantajele pentru cele 2 modele de
organizare ale operanzilor în UCP.

Modelul registru – registru presupune executarea operațiilor cu toți operanzii încărcați


în registre, fără operanzi stocați în memorie. Poate avea 1-3 operanzi în registre (sursă,
destinație, rezultat) și instrucțiunea nu conține nici un câmp de adresă, doar biți de selecție ai
registrelor. Încărcarea registrelor din memorie se va realiza cu instrucțiuni speciale, LOAD,
STORE.
Avantaje:
Instrucțiunile sunt simple, scurte, fiecare câmp are lungime fixă și poate fi decodificat
direct. Timpul de execuție este mai mic, nu necesită transferul operanzilor. Timpul de execuție
este fix, conține aceeași număr de microoperații, facilitând modelul de execuție pe bandă
rulantă.
Dezavantaje:
Compilarea programelor de limbaj înalt generează mai multe instrucțiuni cod mașină, și
lungimea codului devine mai mare.

24
Modelul memorie – registru permite executarea instrucțiunilor cu operanzi stocați în
memorie. Dacă unul din operanzi se află în memorie, adresa acestuia este inclusă în
instrucțiune, în caz contrar câmpul respectiv poate selecta un alt registru. Pentru a reduce
numărul de câmpuri (lungimea instrucțiunii) registrul selectat va conține unul din operanzi și
rezultatul operației. Formatul instrucțiunii poate fi cu lungime variabilă.
Avantaje:
Se poate obține un cod mașină mai compact în urma compilării. Nu se va executa o
instrucțiune în plus pentru încărcarea operandului pentru fiecare instrucțiune aritmetică și
logică.
Dezavantaje:
Timpul de execuție variază în funcție de timpul de acces al operandului, memorie sau
registru. Unitatea de control este mai complexă din cauza numărului variabil de microoperații.

Pentru a realiza un compromis între numărul de registre și stocarea operanzilor în


memorie, arhitecturile moderne au extins setul de instrucțiuni cu diferite moduri de adresare.
Astfel instrucțiunile pot avea lungime variabilă cu număr de câmpuri variabil, care pot fi
interpretate ca date, selectoare de registre sau adrese. Bazat pe analiza anterioară putem
diversifica modul în care este interpretat câmpul de adresă din instrucțiune. Introducând
diferite moduri de adresare compilatorul va optimiza codul mașină generat din limbajele de
nivel înalt, reducând în aceeași timp lungimea și timpul de execuție al programului. În
continuare vom analiza câteva din modurile de adresare disponibile în diferite procesoare,
fără a epuiza lista disponibilă.

3.4 Moduri de adresare

adresare directă – este metoda prezentată în modelul simplificat, în care instrucțiunea


conține adresa operandului.
ADD A, 100H – adună conținutul acumulatorului cu operandul de la adresa 100H

adresare imediată - codul instrucțiunii conține operandul care va fi extras împreună cu


instrucțiunea și nu necesită încă un acces la memorie, dar nici nu va ocupa un registru.
ADDI A, #2 – adună valoarea doi la conținutul acumulatorului
MOV R0, #7 – încarcă valoarea 7 în registrul R0

Un număr mare de secvențe de cod conțin incrementări, decrementări, pentru care


putem adăuga instrucțiuni noi, dar care se încadrează tot în modul de adresare imediată,
având posibilitatea de a specifica valoarea incrementului.
INC A – incrementează conținutul acumulatorului
DEC A – decrementează conținutul acumulatorului

25
adresare prin registre - operandul este stocat într-un registru intern al procesorului, iar
instrucțiunea va specifica registrele implicate în operația dorită. Presupunând că am notat
regiștrii cu R0 – Rn o singură instrucțiune poate conține 3 câmpuri de selecție registru pentru
sursă, destinație și rezultat
ADD R5, R0 – adună conținutul registrului R5 cu conținutul registrului R0, iar rezultatul va
fi înscris în R5

adresare indirectă prin registru – instrucțiunea va conține selectorul unui registru, care
la rândul ei conține adresa operandului. Această modalitate de adresare este echivalentă cu
noțiunea de pointer din limbajul C, și permite definirea unei operații pe toate elementele unui
tablou cu o singură instrucțiune. În cazul adresării directe pentru fiecare element trebuie să
avem o altă instrucțiune, deoarece instrucțiunea conține adresa operandului.
ADD R1, (R2) – adună conținutul registrului R1 cu conținutul locației de memorie a cărei
adresă este înscrisă în registrul R2, iar rezultatul va fi înscris în R1

adresare indexată – instrucțiunea va conține selectorul unui registru, care la rândul ei


conține adresa operandului, dar care se incrementează sau decrementează automat. Această
modalitate simplifică și mai mult operațiile cu tablouri, deoarece nu necesită adăugarea unei
instrucțiuni de incrementare (decrementare) în secvența de cod, și astfel nu se adaugă și
timpul de extragere al instrucțiunii de incrementare. Vom nota registrul utilizat cu Rind+ dacă
este cu autoincrementare, și cu RInd- cu autodecrementare.

În continuare vom compara secvența de cod în limbaj de asamblare rezultat în urma


compilării unei secvențe de cod C folosind tehnica adresării indirecte prin registru și cea a
adresării indexate.

unsigned char i, s=0, a[10];


for ( i=0; i<10 ; i++) MOV R0, #10 MOV R0, #10
s = s | a[i]; MOV R1. #0 MOV R1. #0
MOV R2, #102 MOV RInd+, #102
i la adresa 100H ET: OR R1, (R2) ET: OR R1, (RInd+)
s la adresa 101H INC R2 DEC R0
tabloul a 102H –10BH DEC R0 JNZ ET
JNZ ET
R0 valoarea lui i
R1 valoarea lui s
R2 adresa tabloului

26
adresare relativ la bază - adresa efectivă a operandului se calculează adunând conținutul
registrului de bază (BP) cu deplasamentul specificat în codul instrucțiunii.
MOV R3, BP+200H încarcă conținutul locației de memorie de la adresa calculată ca fiind
suma dintre conținutul registrului de bază și valoarea 200H (considerată deplasament), în
registrul R3. Un exemplu de utilizare ar fi accesul rapid la același câmp din înregistrările unei
tabele.
Modificând conținutul registrului de bază, avem acces la același câmp al diferitelor
înregistrări. Poate fi combinată cu adresare indexată, astfel parcurgerea unor structuri mai
complexe devine mai simplă.

adresare pe bit - se realizează prin instrucțiuni speciale. Instrucțiuni de manipulare bit au


fost adăugate în sistemele încorporate, pentru accesul rapid la biții de intrare și ieșire
individuali.

3.5 Extinderea instrucțiunilor de control

Pe baza reprezentării numerelor și al operațiilor putem defini următorii biți indicatori de


stare modificați în urma execuției instrucțiunilor aritmetice și logice:
Z – zero (Zero), are valoarea 1 dacă rezultatul înscris în registrul destinație este 0
S – semn (Sign), 0 pozitiv, 1 negativ
C – transport (Carry) – are valoarea 1 dacă există transport sau împrumut pe cel mai
semnificativ bit
V – depășire (Overflow) - depășirea de capacitate la operații cu semn

Setul de instrucțiuni de control condiționat poate fi extins pentru toți biții indicatori de
stare.

BP Et – salt la adresa Et, dacă bitul de semn este setat pe 0 de operația precedentă.

Adăugarea unor instrucțiuni de execuție condiționată a instrucțiunilor aritmetice, logice


și de transfer va genera un cod mai compact și reduce timpul de execuție prin eliminarea
timpilor de încărcare al instrucțiunilor de control:

ADDLE R1, R0, #48 operația de adunare între R0 și valoarea 48 cu rezultatul depus în R1
va fi executată dacă în urma operației precedente bitul de transport (C) nu este setat. LE este
prescurtarea de la mai mic sau egal (Les or Equal).

MOVEQ R2, R3 - mută conținutul registrului R3 în registrul R2, dacă bitul indicator Z este
setat de operația precedentă.

27
Atenție operația precedentă nu înseamnă instrucțiunea precedentă, biții
indicatori de stare nu sunt modificați de toate instrucțiunile (de exemplu de
cele de transfer)! Pentru fiecare instrucțiune trebuie verificat cu atenție cum
se modifică indicatorii de stare.

Apelul de procedură
Procedura este o secvență de instrucțiuni ce poate fi refolosit pe durata de viață a
programului în care se schimbă eventual valorile de intrare.
Cerințe de proiectare pentru apelul de procedură:
1. Definirea locației pentru parametrii de intrare. Secvența de instrucțiuni executată
înainte de apelul procedurii va stoca datele în această zonă.
2. Salvarea adresei instrucțiunii la care se va reveni la terminarea procedurii.
3. Transferul controlului la prima instrucțiune din procedură.
4. Executarea instrucțiunilor din procedură, care vor citi, scrie parametrii transmiși.
5. Stocarea rezultatului într-o locație unde poate fi accesat după terminarea
procedurii.
6. Revenirea la instrucțiunea a cărei adresă a fost salvată.
Forma instrucțiunii: CALL adr
Cea mai simpla soluție pentru implementarea instrucțiunii este adăugarea în unitatea
centrală de prelucrare a registrului RS, în care se va salva adresa de revenire, iar parametrii și
rezultatul vor fi transferați de registre de uz general, după o convenție stabilită de compilator.
Problema cu această soluție este, că nu permite apelul unei proceduri noi într-o procedură
în execuție, deoarece adresa de revenire s-ar suprascrie.
Descompunerea instrucțiunii în faze:

Microoperație Descriere
RA  PC se transferă adresa instrucțiunii următoare din numărătorul de
program pe magistrala de adresă prin registrul de adrese
RC  MEMR se activează linia MEMR (citire din memorie) pe magistrala de
control prin registrul de control
RD  M(RA) se citesc datele din memorie de la adresa activă pe magistrala de
adrese în registrul de date
RI  RD instrucțiunea citită se transferă din registrul de date în registrul de
instrucțiuni și se decodifică
PC  PC+l se incrementează valoarea numărătorului de program cu lungimea l
a instrucțiunii curente (va conține adresa instrucțiunii următoare)
RS  PC se salvează conținutul numărătorului de program (care conține deja
adresa instrucțiunii de după CALL, deoarece a fost incrementat) în
registrul de salvare
PC  RIadr se transferă adresa instrucțiunii următoare din registrul de
instrucțiuni în numărătorul de program

28
Revenirea din subrutină se va executa cu instrucțiunea RETURN.

Microoperație Descriere
RA  PC se transferă adresa instrucțiunii următoare din numărătorul de
program pe magistrala de adresă prin registrul de adrese
RC  MEMR se activează linia MEMR (citire din memorie) pe magistrala de
control prin registrul de control
RD  M(RA) se citesc datele din memorie de la adresa activă pe magistrala de
adrese în registrul de date
RI  RD instrucțiunea citită se transferă din registrul de date în registrul de
instrucțiuni și se decodifică
PC  PC+l se incrementează valoarea numărătorului de program cu lungimea l
a instrucțiunii curente (va conține adresa instrucțiunii următoare)
PC  RS se transferă adresa salvată din registrul RS în PC, astfel
următoarea instrucțiune ce va fi executată este cea de după
instrucțiunea CALL

Dacă este nevoie de apeluri de proceduri pe mai multe nivele (apel în apel) trebuie să
extindem spațiul de stocare al adreselor de revenire, și trebuie să contorizăm nivelul actual.
Cea mai simplă structură de implementare este stiva. Stiva este o structură de date în
care scoaterea elementelor se va realiza în ordinea inversă depunerii lor (Last In First Out).
Scrierea (stocarea) și citirea (scoaterea) se va realiza pe vârful stivei, iar adresa (poziția)
acestuia va fi stocată într-un registru al UCP separat denumit indicatorul de stivă (SP). Tot din
motive istorice stiva “crește” de la adrese mari spre adrese mici. Indicatorul de stivă va arăta
totdeauna locația unde se depune următorul element, iar după depunerea unui element se
va decrementa. Înainte de citirea unui element de pe vârful stivei, indicatorul de stivă trebuie
incrementat.
Utilizarea stivei organizate în memorie permite un număr foarte mare de apeluri
recursive, limita superioara a nivelurilor de apel poate fi schimbată prin inițializarea
indicatorului de stivă.
Faza de execuție a instrucțiunilor CALL adr și RETURN se va modifica în felul următor:
CALL adr

Microoperație Descriere
RD  PC se transferă conținutul numărătorului de program (adresa de
revenire) pe magistrala de date prin registrul de date
RA  SP se transferă adresa stivei din indicatorul de stivă pe magistrala
de adresă prin registrul de adrese
RC  MEMW se activează linia MEMW (scriere în memorie) pe magistrala de
control prin registrul de control
M(RA)  RD se scriu în stivă (organizat în memorie) datele (adresa de
revenire) de pe magistrala de date, la adresa activă pe
magistrala de adrese

29
SP  SP-1 se decrementează indicatorul de stivă, pentru a conține adresa
următoarei poziții libere
PC  RIadr se transferă adresa instrucțiunii următoare din registrul de
instrucțiuni în numărătorul de program

RETURN

Microoperație Descriere
SP  SP+1 se incrementează indicatorul de stivă, pentru a conține adresa
ultimei poziții scrise
RA  SP se transferă adresa stivei din indicatorul de stivă pe magistrala
de adresă prin registrul de adrese
RC  MEMR se activează linia MEMR (citire din memorie) pe magistrala de
control prin registrul de control
RD  M(RA) se citesc din stivă (organizat în memorie) datele (adresa de
revenire) de la adresa activă pe magistrala de adrese în registrul
de date
PC  RD se transferă adresa instrucțiunii următoare din registrul de date
în numărătorul de program

Timpul de execuție crește datorită accesului la memorie, dar oferă posibilitatea apelurilor
imbricate pe mai multe nivele. Modificarea a numărătorului de program, a indicatorului de
stivă și a stivei pentru apeluri imbricate poate fi urmărită pe Figura 3.6.
Stiva poate fi utilizată și pentru transmiterea parametrilor și pentru definirea variabilelor
locale din funcțiile C, care au durata de viață și vizibilitatea egală cu cea a funcției. În momentul
terminării funcției C variabilele locale dispa, vor fi eliberate. Acest lucru poate fi ușor
implementat prin modificarea indicatorului de stivă. În acest sens au fost adăugate 2
instrucțiuni speciale pentru operații pe stivă:

PUSH R0 – depune conținutul registrului R0 pe vârful stivei


POP R0 – scoate o valoare de pe vârful stivei și o stochează în registrul R0.

Odată cu creșterea dimensiunii adreselor, includerea adreselor complete în instrucțiune


crește dimensiunea instrucțiunilor. În majoritatea cazurilor dimensiunea unui program este
mult mai mică decât spațiul de adresare. Pentru a reduce dimensiunea instrucțiunilor
instrucțiunile de control vor conține doar un deplasament și nu valoarea absolută a adreselor,
iar saltul se va efectua relativ la valoarea curentă a numărătorului de program.

30
Figura 3.6 Apeluri pe mai multe nivele

Faza de execuție pentru instrucțiunea JMPShort deplasament se va modifica:

Microoperație Descriere
PC  PC + RIadr se calculează adresa instrucțiunii următoare ca fiind suma între
valoarea actuală a numărătorului de program și deplasamentul din
registrul de instrucțiuni, iar rezultatul se transferă în numărătorul de
program

Adresarea relativ la bază poate fi activată și pentru calculul instrucțiunilor. În acest caz
fiecare program poate fi compilat (transformat în cod mașină) începând cu adresa 0, iar
ulterior încărcat în memorie la orice adresă, permițând încărcarea simultană a mai multor
programe în memorie. În momentul rulării programului adresa instrucțiunii următoare se va
calcula adunând valoare registrului de bază, la fel se va calcula și adresa operandului.

31
3.6 Compararea modelului RISC vs. CISC

Sisteme cu set redus de instrucțiuni – RISC

Sistemele RISC sunt caracterizate de un set de instrucțiuni cu lungime fixă și cu câmpuri


de lungime fixă. Pentru a reduce complexitatea unității de control și al unității aritmetice și
logice, setul de instrucțiuni conține un număr redus de instrucțiuni aritmetice și logice cu
durată de execuție aproximativ egală folosind operanzi în registre sau constante din
instrucțiune. Timpul de execuție al instrucțiunilor se reduce foarte mult datorită operanzilor
stocate în registre, iar accesul la memorie se va realiza doar de instrucțiunile de transfer, care
pot avea un timp de execuție mai mare. Implementarea operațiilor mai complexe și al
funcțiilor speciale este sarcina programatorului. Pentru operații complexe timpul de execuție
crește datorită numărului mare de instrucțiuni ce trebuie extrase din memorie și executate.
Transferul datelor între două zone de memorie se va executa cu multe instrucțiuni, deoarece
fiecare cuvânt trebuie citit în UCP și apoi transferat înapoi în memorie, iar adresele sursă și
destinație trebuie incrementate (decrementate). Un registru trebuie încărcat cu lungimea
blocului ce urmează a fi transferat, decrementat și testat după fiecare transfer. Fiecare
operație va fi o instrucțiune separată ce trebuie extrasă și executată de un număr de ori egal
cu lungimea blocului.

Exemplu: ADD R0, R5 - fază de execuție cu o singură microoperație

Microoperație Descriere
RA  PC se transferă adresa instrucțiunii următoare din numărătorul de
program pe magistrala de adresă prin registrul de adrese
RC  MEMR se activează linia MEMR (citire din memorie) pe magistrala de
control prin registrul de control
RD  M(RA) se citesc datele din memorie de la adresa activă pe magistrala de
adrese în registrul de date
RI  RD instrucțiunea citită se transferă din registrul de date în registrul de
instrucțiuni și se decodifică
PC  PC+l se incrementează valoarea numărătorului de program cu lungimea l
a instrucțiunii curente (va conține adresa instrucțiunii următoare)
R0  R0+R5 se adună conținutul registrului R0, cu conținutul registrului R5, iar
rezultatul va fi înscris în registrul R0

Sisteme cu set complex de instrucțiuni – CICS

Sistemele CISC sunt caracterizate de extinderea setului de instrucțiuni cu multe


instrucțiuni complexe pe structuri de date cum ar fi șiruri de caractere, tablouri, date
multimedia. Formatul instrucțiunilor și modurile de adresare variază foarte mult. Timpul de
execuție a instrucțiunilor variază cu complexitatea. Unitatea de execuție are o structură
complexă, cu multe microoperații și multe registre specializate. Implementarea operațiilor

32
complexe și funcțiilor speciale este optimizat, nu depinde de alegerile făcute de programator
pentru organizarea datelor și de algoritmul de calcul ales. Avantajul este evident doar dacă
programatorul lucrează în limbaj de asamblare, în caz contrar eficiența codului generat
depinde de compilator.
S-a adăugat noțiunea de prefix, care permite repetarea unei instrucțiuni fără extragerea
instrucțiunii de repetate ori până când un contor prestabilit devine 0. Transferul datelor între
zone de memorie poate fi implementată cu o singură instrucțiune utilizând prefixul de
repetare.

Exemplu: ADD R0, BP+(Rind+) adunare cu adresare relativ la bază indexat. Adresa de
bază din registrul BP se adună atât la adresa instrucțiunii cât și la cel al operandului.

Microoperație Descriere
RA  BP+PC se transferă adresa instrucțiunii următoare (suma numărătorului de
program și al registrului de bază) pe magistrala de adresă prin
registrul de adrese
RC  MEMR se activează linia MEMR (citire din memorie) pe magistrala de
control prin registrul de control
RD  M(RA) se citesc datele din memorie de la adresa activă pe magistrala de
adrese în registrul de date
RI  RD instrucțiunea citită se transferă din registrul de date în registrul de
instrucțiuni și se decodifică
PC  PC+l se incrementează valoarea numărătorului de program cu lungimea l
a instrucțiunii curente (va conține adresa instrucțiunii următoare)
RA  BP+Rind se transferă adresa operandului (suma dintre registrul de bază și
conținutul registrului index) pe magistrala de adresă prin registrul de
adrese
RC  MEMR se activează linia MEMR (citire din memorie) pe magistrala de
control prin registrul de control
RD  M(RA) se citesc datele din memorie de la adresa activă pe magistrala de
adrese în registrul de date
R0  R0+RD se adună conținutul registrului R0 cu operandul extras din memorie
(RD) și se depune rezultatul în R0
Rind  Rind+1 se incrementează valoarea registrului index pentru a indica
următorul element memorie (pentru a conține următoarea adresă
din vector)

33
4. Unitatea aritmetică și logică

4.1 Unitatea aritmetică

Unitatea logică va implementa toate funcțiile logice din setul de instrucțiuni ales. Primește
codul instrucțiunilor logice din registrul de instrucțiuni, decodifică instrucțiunile și efectuează
operația dorită bit cu bit pe operanzii de intrare. În continuare prezentăm implementarea
unității logice cu patru operații pentru un bit, în care operanzii sunt stocați în registrul X, Y, iar
rezultatul se depune în registrul Z (Figura 4.1). Implementarea exemplu s-a realizat doar cu
porți logice de tip NAND, dar este doar o exemplificare, ea poate fi implementat cu orice set
de circuite logice.

Figura 4.1 Unitatea logică pe un bit pentru 4 funcții logice

Dacă structura internă a unității centrale de prelucrare conține registre de n biți, unitatea
logică, va implementa toate funcțiile logice pentru toții biții în paralel. În urma operațiilor
logice bitul indicator de stare Z este modificat, ea poate fi utilizat în continuare în instrucțiuni
de salt condiționat (Figura 4.2).

34
Figura 4.2 Implementarea indicatorului Z și al saltului condiționat

4.2 Reprezentarea numerelor

Orice număr natural se poate scrie formal ca sume puterilor baze:

xkxk-1xk-2...x1x0=xk⦁bk+xk-1⦁b(k-1)+xk-2⦁b(k-2)+....x1⦁b1+x0⦁b0

Dacă baza este 10 numărul se va scrie: 2378 = 2⦁103+3⦁102+7⦁101+8⦁100, iar dacă baza
este 2 numărul se va scrie: 1011 = 1⦁23+0⦁22+1⦁21+1⦁20 .
Astfel cu n biți putem reprezenta 2n numere naturale cu valoarea între 0 – 2n-1.
Folosim forma de scriere în care bitul din dreapta este cel mai puțin semnificativ, are cea
mai mică putere a bazei. Acesta este doar o convenție putem alege și altă convenție.
În momentul în care avem un număr de 32, 64 de biți pe registru definirea lor în cod
devine greoaie. În limbajul de asamblare preferăm să definim valorile, constantele, adresele
în baza 16. S-a ales baza 16 pentru transformarea simplă a numerelor din această bază în baza
2. Patru cifre binare vor defini o cifra hexazecimală (Tabela 4.1). Pentru scrierea unei adrese
de 32 de biți vom avea nevoie de 8 cifre hexazecimale. Simbolurile folosite în baza 16 sunt: {0,
1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F}. În limbajul C valorile hexazecimale vor fi prefixate de 0x,
iar in limbajul de asamblare numerele hexazecimale vor fi urmate de litera H.

35
Exemplu: 2C4H = 0010 1100 0100 binar

Tabela 4.1 Conversia numerelor din hexazecimal în binar


H B B B B H B B B B H B B B B H B B B B
0 0 0 0 0 4 0 1 0 0 8 1 0 0 0 C 1 1 0 0
1 0 0 0 1 5 0 1 0 1 9 1 0 0 1 D 1 1 0 1
2 0 0 1 0 6 0 1 1 0 A 1 0 1 0 E 1 1 1 0
3 0 0 1 1 7 0 1 1 1 B 1 0 1 1 F 1 1 1 1

Adunarea și înmulțirea numerelor binare pot fi exprimate cu funcții logice simple.

Y X X+Y Y X X⦁Y
0 0 0 0 0 0
0 1 1 0 1 0
1 0 1 1 0 0
1 1 0 1 1 1

Pentru a aduna un număr cu n biți trebuie să introducem noțiunea de transport (Carry),


astfel un sumator complet are 3 intrări, 2 numere și transportul de la rangul inferior (bitul de
la poziția inferioară), și generează două ieșiri suma și transportul către rangul superior.

Tabela de adevăr pentru sumatorul complet de un bit


Ci-1 Yi Xi Zi Ci
0 0 0 0 0
0 0 1 1 0
0 1 0 1 0
0 1 1 0 1
1 0 0 1 0
1 0 1 0 1
1 1 0 0 1
1 1 1 1 1

Putem scrie funcțiile logice pentru acest circuit.


Adunarea tuturor biților din registru se poate efectua secvențial sau paralel și este o
decizie de proiectare.

Exemplu: 1010 + 0111 = 0001 și transport 1


(10) + (7) = (1) și transport 1

Tipul variabilei va limita capacitatea maximă de stocare, și există posibilitatea de a obține


un rezultat “eronat”, deoarece transportul de la ultimul bit trebuie ignorat.

36
Exemplu de cod în limbajul C:
unsigned char i =255;
i=i+1;
În forma de reprezentare binară obținem a variabilei i pe un octet efectuăm următoare
operație: 11111111 + 00000001 = 00000000, deci rezultatul va fi i = 0.
Cel mai important aspect este capacitatea finită al unității aritmetice și logice. Având în
vedere că dimensiunea variabilelor în limbaje de nivel înalt variază, o instrucțiune de adunare
la nivel înalt se va transforma într-o secvență de instrucțiuni de adunare în cod mașină. În
acest sens transportul generat de instrucțiunea curentă trebuie utilizat în instrucțiunea
următoare din acest motiv se va salva în registrul de biți indicatori (FLAG).
La reprezentarea numerelor întregi avem două opțiuni dintre care putem alege:
• Folosim reprezentarea numerelor naturale și adăugăm un bit care va reprezenta
semnul.
• Căutăm a reprezentare pentru care putem folosi circuitul de adunare nemodificat,
dar să obținem rezultatul corect.

Nu uitați în baza 10 nu folosim numai 10 semne, setul de simboluri a fost extins


cu semnul – pentru reprezentarea numerelor negative și cu punctul zecimal!

Presupunem că alegem prima versiune:


Dacă avem registre cu capacitatea de stocare de 4 biți din care rezervăm 1 bit pentru
semn, putem reprezenta numerele între -7 și 7. Vom ajunge la următorul tabel de
reprezentare:
Semn X2 X1 X0 Număr
zecimal
0 0 0 0 0
0 0 0 1 1
0 0 1 0 2
0 0 1 1 3
0 1 0 0 4
0 1 0 1 5
0 1 1 0 6
0 1 1 1 7
1 0 0 0 ????
1 0 0 1 -1
1 0 1 0 -2
1 0 1 1 -3
1 1 0 0 -4
1 1 0 1 -5
1 1 1 0 -6
1 1 1 1 -7

37
Pornind de la această reprezentare verificăm corectitudinea operației de adunare.
0100 + 1100 = 0000
(4) + (-4) = (0)

0101 + 1101 = 0010


(5) + (-5) = (2)

Se poate observa că avem o problemă cu reprezentarea numărului 0, care nu este unic, și


trebuie să redefinim funcția de adunare.
În versiunea doi putem să definim numerele negative prin negarea bit cu bit a numerelor
pozitive. Dacă spațiul de stocare este de 4 biți, vom restricționa mulțimea numerelor pozitive
ce pot fi reprezentate la [ 0 - 7]. Al patrulea bit va fi semnul, și în acest caz rezultă din algoritm,
că numerele pozitive au bitul de semn egal cu 0, iar cele negative 1.

Semn X2 X1 X0 Număr
zecimal
0 0 0 0 0
0 0 0 1 1
0 0 1 0 2
0 0 1 1 3
0 1 0 0 4
0 1 0 1 5
0 1 1 0 6
0 1 1 1 7
1 1 1 1 0 ?????
1 1 1 0 -1
1 1 0 1 -2
1 1 0 0 -3
1 0 1 1 -4
1 0 1 0 -5
1 0 0 1 -6
1 0 0 0 -7

În urma negării bit cu bit numărul 1111 este un număr negativ -0, sau putem atribui
valoarea -8, astfel domeniul de definiție devine [-8, 7].
Pornind de la această reprezentare verificăm corectitudinea operației de adunare.

0100 + 1011 = 1111


(4) + (-4) = (0?)

0101 + 1010 = 1111


(5) + (-5) = (0?)

38
0100 + 1001 = 1101
(4) + (-6) = (-2)

Rezultatul nu este tocmai cel așteptat totdeauna, deoarece orice număr trebuie să aibă
reprezentare unică, deci varianta 1111, ca formă de reprezentare al lui 0 nu este acceptabilă.
Pornind de la reprezentarea de mai sus putem corecta algoritmul de reprezentarea a
numerelor negative, astfel încât rezultatul adunării să fie corect totdeauna. Algoritmul folosit
la scară largă astăzi, denumită și forma de reprezentare în complementul față de 2, generează
numerele negative prin negarea bit cu bit a numerelor pozitive corespunzătoare și adăugare
1. Bitul de semn nu se adaugă separat, ea rezultă din algoritm, și din mulțimea de definiție a
reprezentării [-8, 7].
Pornind de la această reprezentare verificăm corectitudinea operației de adunare.

0100 + 1100 = 0000


(4) + (-4) = (0)

0100 + 1010 = 1110


(4) + (-6) = (-2)

Semn X2 X1 X0 Număr
zecimal
0 0 0 0 0
0 0 0 1 1
0 0 1 0 2
0 0 1 1 3
0 1 0 0 4
0 1 0 1 5
0 1 1 0 6
0 1 1 1 7
1 1 1 1 -1
1 1 1 0 -2
1 1 0 1 -3
1 1 0 0 -4
1 0 1 1 -5
1 0 1 0 -6
1 0 0 1 -7
1 0 0 0 -8

Folosind circuitul de adunare și bitul de transport, putem realiza adunarea numerelor


întregi, dar există cazuri speciale, când rezultatul nu va fi corect, datorită mulțimii de definiție.

39
Exemplu:
0100 + 0110 = 1010
(4) + (6) = (-6) !!!!!!!!!!

Circuitul de adunare funcționează corect, dar numărul rezultatul (10) est în afara mulțimii
de definiție. Deși nu s-a dorit modificarea sumatorului pentru numere negative, în unitatea
aritmetică și logică s-a adăugat un bit indicator de depășire (Overflow).
Pentru adunare dacă numerele au semne diferite nu se generează depășire, dar dacă
numerele au aceeași semn se va genera depășire dacă la sumatorul corespunzător bitului de
semn transportul care intră și care iese diferă. La se poate defini condiția de depășire și pentru
scădere.

Tabela 4.2 Condiția de generare depășire și setare bit V


Operația Operand A Operand B Rezultat
A+B >= 0 >= 0 <0
A+B <0 <0 >= 0
A-B >= 0 <0 <0
A-B <0 >= 0 >= 0

Rețineți unitatea aritmetică și logică este un circuit logic, nu interpretează


date, și lucrează cu o succesiune de biți stocați în circuite cu număr de biți
fixat! Interpretarea rezultatelor este problema programatorului.

Dacă un număr reprezentat pe 8 biți trebuie extinsă (reprezentată) pe un număr mai mare
de biți (conversie de la char la int în C) biții existenți se copiază în partea dreaptă a registrului,
iar restul biților vor fi completați cu bitul de semn.

Exemple:
fie reprezentarea lui 2 pe 8 biți 00000010
convertirea lui pe 16 biți 00000000 00000010
fie reprezentarea lui -2 pe 8 biți 1111 1110
convertirea lui pe 16 biți 1111 1111 1111 1110

Numerele reale se pot reprezenta folosind reprezentarea numerelor întregi. Cea mai
simplă formă de reprezentare este cea în virgulă fixă, în care capacitatea de stocare de n biți
este împărțită prin convenție în două părți de lungime fixă prestabilită, partea întreagă având
k biți și partea fracționară având n-k biți. Numărul de biți din partea întreagă va limita numărul
maxim ce poate fi stocat, iar numărul de biți din partea fracționară va limita precizia. În
această reprezentare nu se poate crește precizia, decât prin reducerea valorii maxime ce

40
poate fi reprezentat. Forma de scriere exponențială este o soluție de compromis pentru a
crește domeniul numerelor reale ce pot fi stocate și precizia lor în același timp.

nr = I.F

31 30 29 28 27 26 25 24 23 22 21 20 ... 2 1 0
S partea întreagă (I) partea fracționară (F)

Reprezentarea numerelor în virgulă flotantă poate fi realizat prin transformarea lor în


formatul exponențial. Se scrie numărul ca fiind egal cu partea fracționară având cel mai
semnificativ bit egal cu unu înmulțit cu 2 la puterea corespunzătoare. Se va stoca separat
partea fracționară ca un întreg și exponentul tot ca un întreg. F este mantisa în complementul
față de 2 în formă normalizată, E exponentul în complementul față de 2.

nr = (-1)S x (1+F) x 2E

31 30 29 28 27 26 25 24 23 22 21 20 ... 2 1 0
S exponent (E) mantisă (F)

Astfel operațiile aritmetice de bază definite pe numere reprezentate în virgulă flotantă se


pot scrie:
X + Y = (XMx2(XE – YE) + YM) x 2YE
X - Y = (XMx2(XE – YE) - YM) x 2YE
X x Y = (XM x YM) x 2(XE + YE)
X : Y = (XM : YM) x 2(XE – YE)

4.3 Circuite de adunare

Pornind de la sumatorul complet de 1 bit, a cărei funcții logice pot fi scrise sub forma :
zi = xi ⊕ yi ⊕ ci-1; ci = xiyi + xici-1 + yici-1; în care ieșirile sunt suma (zi) și transportul (ci), iar
intrările datele (xi, yi), și transportul de la rangul inferior (ci-1).

Figura 4.3 Sumator complet pe 1 bit

41
Pentru a aduna două numere de lungime arbitrară, putem folosi sumatoare seriale (Figura
4.4). Biții de intrare se aplică sumatorului la fiecare semnal de tact, începând cu rangul cel mai
puțin semnificativ. Transportul generat se stochează într-un bistabil D, şi se aplică la sumator
în tactul următor.

Figura 4.4 Sumator serial

Pentru adunarea a două numere de n biți vom avea nevoie de o durată de timp egală cu
n ⦁ perioada semnalului de tact. Pentru a realiza o adunare mai rapidă, se folosesc sumatoare
paralele (Figura 4.5). Transportul generat de un sumator reprezintă intrare în următorul
element, din care motiv timpul de calcul este egal cu timpul de propagare al transportului prin
întregul lanț de sumatoare.

Figura 4.5 Sumator paralel

Pentru a mării viteza de calcul, se folosesc circuite speciale de calcul al transportului


anticipat, alcătuite din circuite combinaționale, care generează simultan transportul pentru
mai multe sumatoare. Aceste circuite se bazează pe următoarele ecuații:

42
gi = xiyi ; pi = xi ⊕ yi
c0 = g0 + p0cin
c1 = g1 + p1g0 + p1p0cin
c2 = g2 + p2g1 + p2p1g0 + p2p1p0cin
c3 = g3 + p3g2 + p3p2g1 + p3p2p1g0 + p3p2p1p0cin

4.4 Extinderea unității aritmetice și logice

4.4.1 Circuite de înmulțire

Pornim de la un exemplu de înmulțire pentru a defini algoritmul de înmulțire.

1 1 0 1 1310 Multiplicand
1 0 1 1 1110 Multiplicator
1 1 0 1
0 0 0 0 Produs
1 1 0 1 parțial
1 1 0 1
1 0 0 0 1 1 1 1 14310 Produs

x2 x1 x0 Multiplicand
y2 y1 y0 Multiplicator
X2Y3 X1Y3 X0Y3
X3Y2 X2Y2 X1Y2 X0Y2 Produs
X3Y1 X2Y1 X1Y1 X0Y1 parțial
X3Y0 X2Y0 X1Y0 X0Y0
Produs

Pentru un număr redus de biți, circuitele de înmulțire pot fi realizate cu circuite


combinaționale, obținând astfel viteze mari de calcul. Pornind de la circuitul de înmulțire pe
un bit (poarta ȘI) se poate construi un circuit de înmulțire folosind sumatoare. Un exemplu
pentru un circuit de înmulțire pe 3 biți este prezentată în Figura 4.6.

43
Figura 4.6 Circuit de înmulțire pe 3 biți

4.4.2 Proiectarea unui circuit de înmulțire secvențial

Pentru a realiza un circuit de înmulțire pe mai mulți biți, se folosește o structură


secvențială, care are o construcție mai simplă, dar o viteză de calcul mai redusă față de
implementarea cu circuite combinaționale.
Înmulțirea este realizată prin adunări și deplasări repetate, analog cu calculul manual.
Registrul M conține multiplicandul, iar registrul Q multiplicatorul. Acumulatorul(A) este
inițializat cu 0, și la fiecare pas se adună multiplicandul dacă bitul cel mai semnificativ al
multiplicatorului Q(7) este egal cu 1. Acumulatorul (A) este conectat cu registrul Q, și împreună
se deplasează stânga pentru a stoca rezultatul intermediar. Astfel bitul care iese din
acumulator se înscrie în poziția cel mai puțin semnificativă a registrului Q, Bitul care se pierde
(iese) din registrul Q în urma deplasării stânga Q(7), nu mai este necesar deoarece ea a fost
testată înainte de deplasare. Unitatea de control primește un semnal de START de la UCP
pentru a iniția procesul de înmulțire, precum și un semnal de TACT. Unitatea de control va
genera semnalele de control interne, conform diagramei de stare din Figura 4.7 b.
Registrele M și Q vor fi încărcate succesiv, deoarece lățimea magistralei este de 8 biți, la
fel și citirea rezultatului se va efectua în doi pași prin magistrală, prima dată se citește din A
partea mai puțin semnificativă a rezultatului, apoi partea mai semnificativă din Q în pasul
următor.
Această structură poate fi folosită pentru operații de adunare, scădere, înmulțire și
împărțire fără nici o modificare, dar unitatea de control trebuie să conțină implementarea
algoritmilor și pentru aceste operații. În acest caz UCP va trimite către unitatea de control, în
afara liniilor START și TACT, patru linii, prin care se va selecta operația dorită.

44
Figura 4.7 Structura (a) și diagrama de stare (b) a circuitului de înmulțire

Proiectarea circuitului de control pentru circuitul de înmulțire urmărește metodele


specifice proiectării circuitelor secvențiale (Figura 4.8). Pornim de la diagrama de stare și vom
identifica în prima etapă elementele de procesare. Se identifică stările și se vor defini
următoarele tipuri de semnale:
• semnale de intrare de la alte unități de control sau de la sistemul supervizor - dacă
există (semnalele de tip START, și cele de sincronizare cu alte componente);
• semnale de ieșire spre alte unități de control, (operație în curs BUSY, operație
terminată STOP);
• semnale de intrare de la unitatea de procesare, care influențează direct semnalele
de ieșire (semnale din blocurile de decizie);
• semnale de ieșire care controlează fluxul de date şi selectează operația prin
unitatea de procesare.

45
Figura 4.8 Componentele principale ale circuitului de înmulțire

Diagrama de stare va fi modificată cu numerotarea stărilor (Si), și se completează cu


semnalele de ieșiri Ci.

Figura 4.9 Diagrama de stare pentru înmulțire modificată

4.4.2 Unitatea de control cablată

Una dintre metodele de implementare se bazează pe numărătoare secvențiale, care se va


implementa cu un numărător modulo k, având ieșirile conectate la un decodificator.
Decodificatorul generează la ieșiri k impulsuri consecutive, decalate cu o perioadă de tact,
denumite faze. Există posibilitatea de pornire a numărătorului prin semnalul Start (începând

46
cu faza Φ1), și de oprire prin semnalul Stop, care cauzează ștergerea numărătorului (Figura
4.10).

Figura 4.10 Numărător secvenţial

Deoarece bucla cea mai lungă conține trei stări, care vor fi repetate de opt ori, se va folosi
un numărător secvențial modulo 3, care generează trei faze. Pașii care nu sunt incluși în buclă,
vor fi sincronizați tot cu aceeași faze. Cei trei bistabili FFi vor face distincția dintre pași la un
moment dat numai unul dintre le fiind activ (setat) și vor implementa trecerea de la un pas la
altul. Toate semnalele care apar în blocurile de decizie, reprezintă intrări de la unitatea de
procesare. Funcțiile logice ale semnalelor de control Ci, vor fi determinate din diagrama de
stare pe baza pasului și a stării în care sunt generate (Figura 4.11).

47
Figura 4.11 Unitatea de control cablată pentru circuitul de înmulțire

În cazul în care dorim să implementăm un circuit de înmulțire pe un număr mai mare de


biți (dacă n se schimbă) doar circuitul de procesare se schimbă, circuitul de control rămâne
nemodificat.

4.4. 3 Unitatea de control microprogramată

Varianta microprogramată a unității de control al circuitului de înmulțire conține o


memorie nevolatilă în care se înscriu pentru fiecare stare codurile semnalelor de control
codurile evenimentelor ce condiționează trecerea la starea următoare și numărul stării
următoare din diagrama de stare. O astfel de înregistrare reprezintă o microinstrucțiune.
Pentru circuitul de control al multiplicatorului există câteva elemente specifice, care
permit reducerea dimensiunii microcodului. Majoritatea tranzițiilor de stare se vor efectua pe
stări consecutive, și majoritatea tranzițiilor nu au atașate evenimente care vor condiționa
tranziția. Din acest motiv introducem numărătorului de microprogram (PC), care se va
incrementa automat după fiecare microinstrucțiune. Astfel adresa instrucțiunii următoare va
fi generată de PC, și nu trebuie specificată în mod explicit, decât la microinstrucțiunile de
salt. Selectarea condițiilor în cazul microinstrucțiunilor de salt condiționat se realizează cu
ajutorul unui multiplexor (MUX), condiția de selectare fiind înscrisă în microinstrucțiune.

48
Vom defini două tipuri de microinstrucțiune (Figura 4.12):
• operaționale - care conțin codul semnalelor de control;
• salt condiționat – care conțin adresa de salt.

Figura 4.12 Formatul microinstrucțiunilor operaționale (a) și de salt (b)

Semnalele de selecție condiție (S1, S0) vor selecta condițiile de salt după cum urmează:

S1 S0 Condiție
0 0 0, instrucțiune de control
0 1 bitul 7 al multiplicatorului
1 0 numărătorul a ajuns la 7
1 1 1, salt necondiționat

Semnalul de START primit de la UCP va reseta numărătorului de microprogram (PC),


astfel prima microinstrucțiune executată este la adresa 0, iar semnalul de TACT primit de la
UCP va incrementa PC. Când sistemul ajunge la starea STOP, rămâne în această stare, din
care numai resetarea o aduce în starea inițială.

Figura 4.13 Structura unității de control microprogramate

49
Conținutul memoriei de microprogram împreună cu semnificația câmpurilor este
prezentată în tabela următoare.

Adresă Control/
S1S0 Microoperație
instr. adr. urm.
0000 00 0001 Încarcă A cu 0, încarcă M cu multiplicand de pe magistrală
0001 00 0010 Încarcă Num cu 0, încarcă Q cu multiplicator de pe magistrală
0010 01 0100 Salt dacă Q(7) = 0
0011 00 0011 A=A+M
0100 00 0100 Deplasare stânga A, Q
0101 10 1000 Salt dacă Num = 7
0110 00 0101 Num = Num + 1
0111 11 0010 Salt necondiționat
1000 00 0110 Transmite conținutul lui A pe magistrală
rezultat partea mai puțin semnificativă
1001 00 0111 Transmite conținutul lui Q pe magistrală
rezultat partea mai semnificativă
1010 11 1010 Oprire

4.5 Unitatea aritmetică în virgulă flotantă

Una din modalitățile de extindere ale UCP reprezintă includerea unităților aritmetice în
virgulă flotantă.
Pornind de la reprezentarea normalizată în virgulă flotantă (virgulă mobilă) nr = (-1)S ⦁
(1+F) ⦁ 2E , putem defini operația de adunare (scădere):
XE - YE YE
X + Y = (XM ⦁ 2 + YM) ⦁ 2
XE - YE YE
X - Y = (XM ⦁ 2 - YM) ⦁ 2
Datorită faptului că numerele sunt stocate în forma normalizată, după efectuarea
operației cerute trebuie normalizat rezultatul. Astfel operația de adunare poate fi descompusă
în următorii pași:
a) compararea exponenților prin scădere pentru a obține exponentul mai mic;
b) alinierea mantiselor prin deplasare, astfel ca exponenții să fie egali;
c) adunarea mantiselor;
d) normalizarea rezultatului.
Exponenții stocați în registrele E1, E2 vor fi comparați prin scădere, exponentul mai mic va
fi păstrat ca fiind cel comun, iar mantisa corespunzătoare exponentului mai mare va fi
deplasată cu E1-E2 poziții. Mantisa astfel obținută va fi însumată cu cealaltă mantisă,
nemodificată. Rezultatul sumei este depus în registrul temporar R, și un circuit special,
denumit detector de zerouri, va număra zerourile nesemnificative de la începutul mantisei (R).
Acest număr este folosit pentru deplasarea mantisei (aducerea în formă normalizată), și se
scade din exponent. În caz că R=0 se setează și exponentul pe zero (Figura 4.14).

50
Figura 4.14 Sumator în virgulă flotantă

Pentru a mării viteza de calcul, se folosesc pipeline-uri aritmetice. Astfel apare


posibilitatea de a prelucra simultan mai mulți operanzi prin executarea unei faze al operației
pe un operand în timpul execuției unei alte faze pe alt operand. Această metodă reduce
considerabil timpul de execuție. Operația de adunare se descompune în faze iar unitățile de
prelucrare se descompun în segmente. În fiecare segment se realizează o procesare parțială,
iar rezultatul final se obține după ce data a parcurs toate segmentele pipeline-ului.
Aceste structuri devin rentabile, dacă sunt alimentate continuu cu operanzi, de exemplu
în cazul prelucrării vectorilor. Cele patru faze ale adunării pot fi implementați ca patru
segmente ale unui structuri pipeline. Diferența fată de structura precedentă reprezintă setul
de registre care au fost introduși pentru a separa segmentele. Această structură permite
prelucrarea simultană a patru perechi de operanzi (pe fiecare pereche se efectuează o altă
fază a adunării), și stocarea rezultatelor parțiale obținute în fiecare fază (Figura 4.15). Trecerea
de la un segment la altul se realizează comandat de un semnal de tact, obținându-se un
pipeline sincron. Frecvența semnalului de tact este determinat de timpul cel mai lung de
parcurgere al unui segment, motiv pentru care sumatoarele, circuitele de deplasare și circuitul
detector de zero trebuie implementate în versiunea cea mai rapidă și pe cât posibil cu timp de
parcurgere egal, pentru a reduce timpii de așteptare.

51
În tabela de mai jos am exemplificat modul de funcționare al sumatorului în structura
pipeline pentru adunarea a doi vectori, a câte 4 elemente:

Tact x[0], y[0] x[1], y[1] x[2], y[2] x[3], y[3]


Compararea
1
exponenților
Alinierea Compararea
2
mantisei exponenților
Adunarea Alinierea Compararea
3
mantiselor mantisei exponenților
Normalizarea Adunarea Alinierea Compararea
4
rezultatului mantiselor mantisei exponenților
Normalizarea Adunarea
5 Alinierea mantisei
rezultatului mantiselor
Normalizarea Adunarea
6
rezultatului mantiselor
Normalizarea
7
rezultatului

Se poate observa că timpul total de execuție se reduce la 7 perioade de tact, față de 16


perioade (4⦁4) pentru procesarea secvențială a elementelor din vectori.
Dacă numărul de elemente al tabloului este mai mare atunci în tactul 5 se poate executa
prima fază (Compararea exponenților) pentru elementele x[5], y[5], iar în tactul 6 pentru
elementele x[6], y[6].

52
Figura 4.15 Sumator în virgulă flotantă cu structură pipeline

4.6 Procesare paralelă

4.6.1 Operații aritmetice și logice pe vectori

Procesare datelor multimedia, și al imaginilor presupune executarea aceleași instrucțiuni


pe mai multe date. Pentru a reduce timpul de extragere în repetate rânduri al instrucțiunii s-
au adăugat instrucțiuni vectoriale. Astfel s-a ajuns la arhitecturi de ALU de tip SIMD (single
instruction multiple data). În cele mai multe cazuri ALU a fost proiectat modular astfel încât să
permită conectarea serie a modulelor pentru operanzi de 128 bit, dar și utilizarea aceleași
structuri în paralel pentru 16 operanzi de 8 biți sau 8 operanzi de 16 bit. (ex. ARM V8) Registrul
va fi împărțiți în benzi independente (Figura 4.16).

53
Figura 4.16 Structura de registre al procesorului ARM V8

Exemplu: instrucțiunea ADD V10.4S, V8.4S, V9.4S adună simultan 4 operanzi de 32 de biți
folosind regiștrii de 128 biți V8 și V9, iar rezultatul va fi înscris în V10.
Cele 4 unități for lucra independent fără propagarea transportului între benzi.

Figura 4.17 Adunarea simultană a 4 operanzi de 32 biți pe un ALU de 128 biți

54
5. Unitatea de control al unității centrale de prelucrare

5.1 Transfer registre

Funcția principală a unității centrale de prelucrare (UCP) este de a executa o secvență de


instrucțiuni, stocată în memorie. Un ciclu instrucțiune poate fi definit ca o secvență de
microoperații, fiecare dintre ele reprezentând un transfer între registre. UCP-ul poate fi
divizată în două părți componente: cea de procesare și cea de control. Partea de procesare
constă dintr-un set de registre interconectate și circuitele de procesare date din unitățile
aritmetice și logice. Partea de control trebuie să asigure secvența semnalelor de control (C),
corespunzătoare instrucțiunii descompuse în microoperații. Aceste semnale de control
selectează căile de date și operația cerută din unitatea de procesare. Semnalele de control
acționează prin blocarea-deschiderea căilor de date în punctele de control pentru selectarea
sursei și destinației transferului între registre ( indicate prin cerc pe Figura 5.1).

Figura 5.1 Semnale de control pentru realizarea transferului între registre

Fiecare microoperație de tip transfer între registre va fi controlat de semnale de control


(C0 – C7) pentru activarea sursei și al destinației, restul semnalelor de control (C8-C11) vor
selecta operația dorită. Microoperațiile pot fi codificate la rândul lor reducând semnificativ
numărul semnalelor de selecție (S0-S1).
În continuare prezentăm codificarea semnalelor de control pentru semnalele de control
din figura 5.1.

SEMNALE DE CONTROL
MICROOPERAȚIE S1 S0
ACTIVE
R3  R1 0 0 C1, C7
R4  R1 0 1 C1, C6
R3  R2 1 0 C3, C7
R4  R2 1 1 C3, C6

55
Implementarea fizică a transferului dintre registre poate folosi multiplexoare sau registre
cu ieșiri cu trei stări (Figura 5.2). În cazul implementării cu multiplexoare semnalul de selecție
S1 va controla sursa prin selectarea intrării în multiplexor, iar destinația va fi selectată prin
aplicarea semnalului S0 pe intrarea de Tact al registrului în care se va realiza înscrierea datelor.
În cazul implementării cu registre cu intrări de validare, semnalul S1 va activa ieșirea
corespunzătoare, iar ieșirea celuilalt registru va fi în impedanță ridicată.

Figura 5.2 Implementarea transferului între registre

5.2 Unitatea de control

Proiectăm unitatea de control pentru o unitate centrală de procesare care interpretează


următorul set simplificat de instrucțiuni:

LOAD X - transferă conținutul locației de memorie de la adresa X în acumulator;


STORE X - transferă conținutul acumulatorului în memorie la adresa X;
ADD X - A = A + M(X);
AND X - A = A  M(X);
JMP X - salt necondiționat la adresa X;
JZ X - salt la adresa X dacă conținutul acumulatorului este 0;
NOT - complementarea conținutului acumulatorului;
RSHIFT - deplasare spre dreapta a conținutului acumulatorului.

Pentru a realiza unitatea de control, se descompune fiecare instrucțiune în microoperații,


se determină semnalele de control și numărul de stări pe baza diagramei de stare din Figura
5.3. Se presupune că durata fiecărei microoperații este egală cu o perioadă de tact, exceptând
READ M și WRITE M, care au lungimea de două perioade, în prima se trimite semnalul de
control corespunzător citire sau scriere iar în a doua se va realiza transferul datelor pe
magistrală. Instrucțiunea cea mai lungă are 8 faze.

56
Figura 5.3 Descompunerea setului de instrucțiuni în faze

Semnalele de control care rezultă din descompunerea în faze sunt:

C0 A  A + RD;
C1 A  A  RD;
C2 A  NOT A;
C3 SHIFT A.
C4 READ M;
C5 WRITE M;
C6 RD  A;
C7 A  RD;
C8 RA  RI(ADR);
C9 PC  RI(ADR);
C10 PC  PC + 1; RI  RD;
C11 RA  PC;

Pornind de la descompunerea instrucțiunilor în faze, și de la schema generală a


arhitecturii de bază, vom identifica toate componentele necesare, vom stabili legăturile dintre
componente și vom identifica semnalele de control care controlează transferul între
registre(Figura 5.4).

57
Figura 5.4 Arhitectura unității centrale de prelucrare

Unitatea de control în varianta cablată este realizată cu un numărător secvențial modulo


8, care va genera 8 semnale de fază decalate cu câte o perioadă. Va fi resetat după i faze în
cazul instrucțiunilor care sunt mai scurte decât 8 faze (i < 8). Numărătorul va fi incrementat de
semnalul de Tact al unității centrale de prelucrare. Pe baza diagramei de stare se scriu ecuațiile
pentru fiecare semnal de control care vor fi implementate de circuitul combinațional.

Exemplu: determinarea funcției logice pentru semnalul de citire din memorie (C4)
C4 = Φ2 + Φ6 (LOAD + ADD + AND).

Figura 5.5 Implementarea cablată a unității de control al UCP

Unitatea de control primește la intrare codul instrucțiunii pe care o decodifică, starea


registrului indicator de stare (în varianta simplificată bitul Z) și generează secvența semnalelor
de control conform diagramei de stare.

58
5.3 Proiectarea unității de control microprogramate

Dacă setul de instrucțiuni este foarte mare, și numărul de faze al instrucțiunilor diferă
foarte mult se poate implementa unitatea de control în varianta microprogramată. Orice
modificare ulterioară în setul de instrucțiuni sau moduri de adresare (pentru a corecta o
eroare sau a extinde setul de instrucțiuni) cere reproiectarea completă a unității de control în
varianta cablată.
Microprogramarea înseamnă stocarea semnalelor de control și de secvențiere într-o
memorie de control nevolatilă (care nu-și pierde conținutul, când nu este alimentat).
Semnalele de control care sunt activate la un moment dat, formează o microinstrucțiune, și
sunt extrase din memoria de control în mod asemănător extragerii instrucțiunilor unui
program din memoria principală. Un set de microinstrucțiuni alcătuiesc un microprogram.
Sistemele astfel realizate sunt mult mai flexibile, permițând modificări ulterioare, dar sunt mai
lente decât varianta cablată. Fiecare instrucțiune al UCP poate fi considerat un microprogram,
și este interpretat în timp real.
Cea mai simplă formă a unei microinstrucțiuni conține două câmpuri: câmpul de control
(totalitatea liniilor de control care se activează) și câmpul de adresă (adresa următoarei
microinstrucțiuni). Fiecare bit al câmpului de control corespunde unui semnal de control, și
are valoarea 1 dacă semnalul de control corespunzător trebuie să fie activă în microoperația
respectivă.
Pornind de la diagrama de stare care urmează să fie implementată, se numără și se
codifică stările. Acestea vor reprezenta biții de adresă din microinstrucțiune. Numărul liniilor
de date este suma liniilor de stare și a celor de control. Se alege o memorie de dimensiune
corespunzătoare și un registru de adrese care asigură secvențierea instrucțiunilor.
Există două căi de a reduce dimensiunea memoriei de microinstrucțiuni:
• prin codificarea semnalelor de control;
• prin schimbarea modului de adresare.
Formatul necodificat, denumit microinstrucțiune orizontală, are avantajul de a genera
direct semnalul de control, dar dimensiunea câmpului de control este egală cu numărul
semnalelor de control, care poate fi foarte mare. Prin codificarea completă a câmpului de
control se reduce considerabil numărul liniilor de date al memoriei de stocare. Astfel se obțin
microinstrucțiuni verticale; semnalele de control vor fi decodificate, adică la un moment dat
un singur semnal de control poate fi activ. În majoritatea situațiilor mai multe semnale de
control vor fi active simultan, deci codificarea lor completă nu este posibilă. Se vor grupa
semnalele de control care nu se activează simultan și fiecare grup se codifica separat. Această
codificare parțială permite activarea simultană a semnalelor de control, dar și reducerea
dimensiunii câmpului de control. Pornind de la diagrama de stare, se identifică numărul maxim
de semnale de control care apar simultan, formând tot atâtea grupuri distincte, în așa fel încât
în cadrul unui grup să nu existe semnale care apar simultan. La fiecare grup se atașează un
decodificator, la ieșirea căruia vom obține semnalele de control (Figura 5.6).

59
Figura 5.6 Microinstrucțiuni necodificate (a), complet codificate (b) și parțial codificate (c)

În mod asemănător cu circuitul de control al unității de înmulțire cu mici excepții stările


sunt consecutive deci vom folosi numărătorului de microprogram (PC), care se va incrementa
automat după fiecare microinstrucțiune și se va încărca cu o adresă diferită în cazul
instrucțiunilor de salt. Vom folosi două tipuri de instrucțiuni de tip operațional, care
generează semnalele de control și de tip salt care poate fi condiționat sau nu (Figura 5.7).

Figura 5.7 Formatul microinstrucțiunilor operaționale (a) și de salt (b)

Pornim de la setul de instrucțiuni și de la descompunerea lor în faze din diagrama de stare,


și descriem fiecare instrucțiune ca o succesiune de microoperații. Fiecare microoperație va fi
transformată în microinstrucțiune conform formatului prezentat în capitolul 4.4.3.
Fiecare instrucțiune are o parte comună de extragere, care va și descris de un
microprogramul separat (FETCH). Toate secvențele de microprogram obținute astfel vor fi
stocate succesiv în memorie începând cu microprogramul pentru FETCH. Într-un circuit
combinațional se va stoca tabela de corespondență dintre codul instrucțiunii și adresa de
început a microprogramului corespunzător din memorie. Se poate folosi pentru
implementarea acestui circuit o arie logică programabilă (PLA), care generează adresa de
intrare a microprogramului, în funcție de tipul instrucțiunii.
Vom include în microinstrucțiune un bit selector de adresă (SA), care va fi conectat la linia
de selecție al multiplexorului de adresă. Pentru valoarea 0 numărătorul de microprogram se
va încărca cu adresa din microinstrucțiune, pentru valoarea 1 se va încărca cu adresa primei
microinstrucțiuni corespunzătoare instrucțiunii din registrul de instrucțiuni (Figura 5.8).
Semnalele de selecție condiție (S1, S0) vor selecta condițiile de salt după cum urmează:

S1 S0 Condiție
0 0 0, instrucțiune de control
0 1 Flagul Z negat (A ≠ 0)
1 0 Neutilizat
1 1 1, salt necondiționat

60
Conținutul memoriei de microprogram împreună cu semnificația câmpurilor este
prezentată în tabela 5.1

Tabela 5.1 Memoria microprogram


Conținut memorie
Adresă Semnal
Control/ Instr. Microoperație
memorie SA S1S0 contr
adr. urm.
00000 0 00 01011 FETCH RA  PC; C11
00001 0 00 00100 READ M; C4
00010 0 00 01010 PC  PC + 1, IRDR; C10
00011 1 11 xxxxx salt la IR;
00100 0 00 01000 LOAD RA  RI(ADR); C8
00101 0 00 00100 READ M; C4
00110 0 00 00111 A  RD; C7
00111 0 11 00000 salt la FETCH;
01000 0 00 01000 STORE RA  RI(ADR); C8
01001 0 00 00110 RD  A; C6
01010 0 00 00101 WRITE M; C5
01011 0 11 00000 salt la FETCH;
01100 0 00 01000 ADD RA  RI(ADR); C8
01101 0 00 00100 READ M; C4
01110 0 00 00000 A  A + RD; C0
01111 0 11 00000 salt la FETCH;
10000 0 00 01000 AND AR  RI(ADR); C8
10001 0 00 00100 READ M; C4
10010 0 00 00001 A  A  RD; C1
10011 0 11 00000 salt la FETCH;
10100 0 00 01001 JMP PC  RI(ADR); C9
10101 0 11 00000 salt la FETCH;
10110 0 01 00000 JZ dacă A ≠ 0, salt la FETCH;
10111 0 00 01001 PC  RI(ADR); C9
11000 0 11 00000 salt la FETCH;
11001 0 00 00010 NOT A  NOT A; C2
11010 0 11 00000 salt la FETCH;
11011 0 00 00011 RSHIFT RIGHT-SHIFT (A); C3
11100 0 11 00000 salt la FETCH;

61
Figura 5.8 Structura unității de control microprogramate

5.4 Tehnici pipeline în proiectarea unității centrale de prelucrare

Pornind de la analiza setului de instrucțiuni putem identifica patru faze distincte în


executarea instrucțiunilor:

Durata Durata
Faza instrucțiunii
în ns pipeline
Extragerea instrucțiunii din memorie 40 40
Decodificarea instrucțiunii, și extragerea microoperațiilor 25 40
Extragerea operandului 40 40
Executarea operației 20 40
Total 125 160

62
Durata de execuție a fiecărei faze este diferită, accesul la memorie necesită mai multe
microoperații, dar nu există totuși diferențe semnificative între durata fazelor.
Putem aplica și în această situație tehnica executării pe bandă rulantă a fazelor. Astfel o
instrucțiune extrasă din memorie va trece în faza de decodificare și extragere
microinstrucțiuni iar simultan cu ea instrucțiunea următoare poate fi extrasă.
În continuare vom compara timpii de execuție în varianta secvențială și pe bandă rulantă
(Figura 5.9). În varianta secvențială extragerea instrucțiunii următoare se va efectua după
terminarea executării instrucțiunii curente. În varianta pipeline ( bandă rulantă) trecerea de
la o fază la alta va fi realizată sincron cu un semnal de tact a cărei perioadă trebuie să fie egală
cu durata cea mai lungă. Astfel durata de execuție pentru o instrucțiune crește, dar durata
totală de execuție al unei secvențe de instrucțiuni este mult mai mică.

Figura 5.9 Compararea timpilor de execuție al instrucțiunilor pentru varianta secvențială și


cea pe bandă rulantă

Structura internă a UCP se schimbă în varianta pipeline, la fiecare fază se vor introduce
elemente de stocare, registre pentru stocarea elementelor obținute în faza respectivă (Figura
5.10). Astfel instrucțiunea extrasă din memorie va fi stocat în registru intermediar, iar registrul
de instrucțiuni va fi folosit pentru extragerea instrucțiunii următoarele.

63
Figura 5.10 Arhitectura UCP în varianta pipeline

Setul de microinstrucțiuni extrase vor fi stocate în registre din nivelul 2 al pipeline-ului,


operanzii în registre din nivelul 3, iar rezultatul obținut în nivelul 4. Înscrierea în registre
pipeline de stocare intermediară va fi controlat de tactul care va controla trecerea de la o fază
la alta.
Fiecare instrucțiune avansează la semnalul de tact dintr-un registru pipeline la următorul.
Registrul numărător de program va conține adresa instrucțiunii care urmează a fi extrasă la
următorul tact, indiferent de faza în care se află instrucțiunea care a fost extrasă și este în
execuție. Circuitul de control al UCP trebuie extinsă cu semnale care controlează scrierea și
citirea din registre pipeline.
Chiar dacă arhitectura pipeline are multe avantaje, există situații când va genera conflict
iar rezultatul ar fi imprevizibil, conduce la hazard.
Conflictul pe date va fi generat de situația când instrucțiunea următoare va folosi ca și
operand variabila stocată într-un registru, care a fost actualizat de instrucțiunea precedentă.
Cum arhitectura pipeline este transparentă programatorului, acesta presupune că utilizarea
aceleași variabile în instrucțiuni consecutive nu este o problema, din contră crește
performanța aplicației (permite optimizarea codului de către compilator), deoarece reduce
numărul de transferuri la memorie. În figura 5.11 sunt prezentate două instrucțiuni aritmetice
consecutive primul are ca și destinație registrul X1, care este registrul sursă pentru
instrucțiunea următoare. Conflictul poate fi soluționat prin întârzierea instrucțiunii de scădere
până când variabila din registrul sursă este disponibil (2 tact). O soluție poate însemna
detectarea conflictului la nivel de cod mașină de către programator sau compilator,
rearanjarea instrucțiunilor dacă acest lucru este posibil, sau inserarea de instrucțiuni NOP.
Soluția cealaltă presupune că circuitul de control va anticipa conflictul și va întârzia execuția
instrucțiunii următoare și va trimite în avans rezultatul în momentul în care este disponibil la
ieșirea din unitatea aritmetică.

64
Figura 5.11 Conflictul pe date (a) și soluția propusă (b)

Există situații când conflictul pe date nu este atât de evident, deoarece elementele de
procesare sau stocare utilizate nu sunt specificate explicit. O situație de conflict apare la
executarea instrucțiunilor de salt condiționat. Indicatorii de stare sunt modificați de
instrucțiunile precedente (nu totdeauna cel anterior) instrucțiunii de salt, dar în momentul
executării instrucțiunii de salt indicatorul de stare trebuie să conțină deja rezultatul de la faza
de execuție a instrucțiunii alese de către programator. În figura 5.12 instrucțiunea de salt pe
zero trebuie să folosească valoarea indicatorului de stare setat de instrucțiunea de adunare.
Dacă acesta nu este disponibil în faza de execuție a instrucțiunii de salt, ea trebuie întârziată.
Și în acest caz pot fi inserate alte instrucțiuni, dar numai dacă ele nu vor modifica indicatorii
de stare.

Figura 5.12 Conflictul pe biții indicatori de stare (a) și soluția propusă (b)

Incluzând și modurile de adresare în setul de instrucțiuni, numărul de faze și respectiv


numărul de nivele pipeline crește (Figura 5.13). Realizarea arhitecturii pipeline presupune
existența unităților aritmetice separate pentru calculul adreselor instrucțiunilor și al
operanzilor, respectiv pentru executarea operațiilor aritmetice, astfel încât ele să poate
efectua aceste operații în paralel pentru diferite instrucțiuni.

65
Durata Durata
Faza instrucțiunii
în ns pipeline
Calculul adresei instrucțiunii 20 40
Extragerea instrucțiunii din memorie 40 40
Decodificarea instrucțiunii, și extragerea microoperațiilor 25 40
Calculul adresei operandului 20 40
Extragerea operandului 40 40
Executarea operației 20 40
Înscrierea rezultatului în registrul selectat 20 40
Total 185 280

Figura 5.13 Instrucțiune cu 7 faze

Una din problemele majore ale structurilor pipeline reprezintă hazardul datorat
instrucțiunilor de control. În acest caz până la momentul executării instrucțiunilor de salt
condiționat (salt necondiționat, apel subrutină, sau revenire subrutină) un număr considerabil
de instrucțiuni au fost extrase și executate diferite faze conform structurii pipeline (Figura
5.14). În momentul executării instrucțiunii de control, se va cunoaște adresa exactă a
instrucțiunii următoare, care poate fi diferită de cele extrase și introduse în pipeline. Toate
structurile de stocare registre, indicatori de stare, structuri de stocare intermediari din
pipeline trebuie “golite”, aduse înapoi în starea în care erau la momentul începerii execuției
instrucțiunii de control. La fel acest lucru poate fi realizat la nivelul compilării prin intercalarea
de instrucțiuni NOP după instrucțiunile de control, sau la nivelul circuitului de control al UCP.
Majoritatea procesoarelor conțin circuite complexe de predicție a saltului și calculul anticipat
al adreselor de salt, sau structuri de stocare dublate care vor efectua extragerea instrucțiunilor
pe ambele ramuri pentru instrucțiunile de salt condiționat. Având în vedere numărul mare de
faze întârzierea încărcării instrucțiunii următoare pentru fiecare instrucțiune de control nu
poate fi acceptabil, în cele mai multe cazuri se folosesc circuite de predicție pentru a decide
care să fie adresa următoarei instrucțiuni extrase de structura de execuție pipeline. Ca orice
circuit de predicție ea se poate baza pe deciziile anterioare în momentul executării
instrucțiunii de control respective. Eventual pot fi adăugate memorii asociative care vor
conține adresa următoare de la execuția precedentă. Având în vedere structura repetitivă a
programelor (majoritatea limbajelor de programare de nivel înalt conțin instrucțiuni care vor
defini buclă) sistemul va funcționa eficient deoarece va prezice corect adresa următoare de
un număr de ori egal cu numărul de repetiții a buclei și va greși o singură dată la ieșirea din
buclă.

66
Figura 5.14 Hazardul în cazul instrucțiunilor de control

67
6. Organizarea memoriei

6.1 Tipuri de memorie

6.1.1 Indicatori de performanță

Memorie este componenta care stochează datele și instrucțiunile, iar stabilirea capacității
de maxime de adresare este totdeauna rezultatul unui compromis. Creșterea capacității de
adresare presupune extinderea dimensiunii instrucțiunilor, care conțin adrese de instrucțiuni
sau operanzi, iar adăugarea diferitelor moduri de adresare crește complexitatea unității de
control și a unității aritmetice și logice. Din punct de vedere al programatorului dimensiunea
finită a memoriei, organizarea ei internă trebuie să fie invizibilă. Programatorul lucrează cu
structuri de date mari și algoritmi de procesare, care trebuie să fie independente de
dimensiunea fizică a memoriei pe un sistem specific.
Structura care corespunde cel mai bine acestui compromis, este o structură ierarhică, iar
dezvoltarea tehnologică a memoriilor facilitează implementarea acestei structuri ierarhice. S-
au dezvoltat memorii foarte rapide, dar a căror costuri sunt mari și memorii lente, dar cu
capacitate de stocare foarte mare a căror costuri pe unitatea de stocare sunt foarte mici.
Organizarea ierarhică oferă iluzia unei capacități de stocare foarte mare, care oferă timp de
răspuns foarte mic în majoritatea situațiilor. Această iluzie se bazează pe o premisă simplă, la
un moment dat nu este nevoie de întreg spațiul de adresare, doar de o porțiune mică din ea.
Din analiza programelor putem deduce două principii de proximitate, cea temporală și
cea spațială. Proximitatea (localitatea) temporală înseamnă, că datele (instrucțiunile) utilizate
recent vor fi reutilizate într-un viitor apropiat. Proximitatea (localitatea) spațială indică faptul
că datele care au adrese apropiate de cele accesate vor fi accesate cu o probabilitate mai
mare, decât cele cu adrese la distanțe mai mari.
Pornind de la aceste principii putem construi o structură ierarhică pe mai multe nivele. La
primul nivel se va conecta o memorie rapidă, de dimensiune mică, care va conține datele și
instrucțiunile de la adresele apropiate celor utilizate în mod uzual acesta este memoria cache.
La nivelul doi este memoria operativă, de dimensiune suficient de mare, ca să conțină toate
procesele și sistemul de operare care rulează la un moment dat. Când se accesează o locație
de memorie operativă, conținutul acesteia împreună cu locațiile de la adresele vecine (linie)
va fi copiată în memoria cache. În viitor dacă se va accesa aceeași locație sau vecinii de pe
linie, ele vor fi disponibile mult mai repede din cache (cache hit), timpul de acces astfel se va
reduce considerabil. Dacă nu se găsesc în cache (miss cache) operația de citire scriere va
continua și va accesa datele în memoria operativă, copiind în același timp linia și în cache. În
situațiile excepționale, când volumul de date procesat este foarte mare, ea nu va încape în
memoria operativă, și va fi stocată în memoria secundară, de unde se va încărca pe blocuri în
memoria operativă atunci când va fi accesată, înlocuind un bloc care nu este utilizat. Indiferent
de numărul de nivele numai nivelele adiacente comunică între ele.

68
Figura 6.1 Structura ierarhică a memoriei

Având în vedere structura unității centrale de calcul și modul de executare al


instrucțiunilor performanța unui program depinde în mare măsură de performanța memoriei
și de organizarea acestuia. La nivelul programatorului memoria este văzută ca un spațiu de
stocare pe un singur nivel cu timp de acces egal pentru orice locație. Estimarea performanței
unui program pe baza unui eșantion mic de date și extrapolarea rezultatelor la un volum foarte
mare de date poate duce la concluzii false. Cunoașterea arhitecturii exacte al memoriei pentru
un anumit sistem, poate ajuta la îmbunătățirea performanței aplicației prin reorganizarea
datelor.
Din punct de vedere tehnologic putem distinge memorii statice (SRAM), memorii
dinamice (DRAM) și memorii nevolatile (FLASH). Din punct de vedere al timpului de acces
memoriile pot fi cu acces aleator (RAM), adică timpul de acces la orice locație este egal sau cu
acces serial, dacă timpul de acces depinde de poziția fizică a locației cum ar fi în cazul stocării
pe benzi magnetice. Timpul de acces se măsoară de la momentul în care se transmit adresele
până la momentul în care sunt disponibile datele. Vom vedea că structura internă a memoriilor
a devenit atât de complexă, că timpul de acces nu va fi egal pe toate locațiile ele datorită
tehnicilor de citire în bloc, sau în rafală a locațiilor adiacente ca și adresă, dar și al construcțiilor
interne paralele.

6.1.2 SRAM

Memoriile statice pot fi construite din bistabili sau registre, ele își păstrează conținutul
dacă sunt alimentate, dar își pierd conținutul dacă nu sunt alimentate.

69
SRAM-ul este organizat pe cuvinte (8, 16, 32 de biți). Citirea și scrierea datelor se
realizează simultan la toți biții care formează cuvântul. O structură posibilă pentru SRAM este
prezentată în figura 6.2 Semnalul de selecție (CS), condiționează operațiile de citire și scriere
pentru întreaga memorie dacă nu este activă toate ieșirile vot fi în impedanță ridicată. Liniile
de intrare de adrese (A0, A1) selectează cuvântul dorit. Liniile de date sunt și intrări și ieșiri,
dar sunt realizate cu circuite cu trei stări, astfel pot fi cuplate direct pe magistrala de date.
Semnalele de citire și scriere (RD, WR) sunt generate de procesor la executarea instrucțiunilor
corespunzătoare.

Figura 6.2 Organizarea SRAM-ului

Adresa locației ce urmează a fi citită sau scrisă trebuie trimisă pe magistrala de adrese de
către UCP înainte de a genera semnalele de comandă corespunzătoare, pentru a putea fi
decodificate. Datorită diferenței vitezei de lucru dintre UCP și memorii, există situații când
memoria nu poate fi citită, scrisă pe durata unui tact procesor. În aceste cazuri memoria poate
cere intercalarea unor stări de așteptare prin activarea liniei READY. Această linie este testată
de UCP în T2. Dacă este activă, se intercalează o stare de așteptare (TW), la sfârșitul căreia

70
linia este din nou testată. Ciclul se repetă până când memoria dezactivează această linie, după
care urmează citirea propriu-zisă.

Figura 6.3 Ciclu de citire (a.), ciclu de scriere (b.) și ciclu de citire cu stări de așteptare (c.)

Memoriile SRAM pot fi folosite pentru implementarea memoriilor cache, a memoriilor


rapide de pe plăcile grafice, în cazul sistemelor încorporate, sau pot fi incluse în procesoare
sau microcontrolere. Există posibilitatea ca două procesoare să aibă acces la aceeași locație
de memorie printr-o organizare specială, denumită memorii SRAM dublu port. Numai unul
dintre ele va efectua operația de scriere/ citire, celălalt va fi în așteptare. Terminarea operației
la un procesor poate genera întrerupere la celălalt.

71
Figura 6.4 Memorii dublu port

6. 1. 3 DRAM

Folosește condensatori pentru stocare, iar scrierea înseamnă încărcare. Din cauza
descărcării circuitul nu-și poate păstra starea dacă nu este reîncărcat periodic. Termenul de
memorie dinamică se referă la operația de reîmprospătare periodică. Pe lângă ciclul de citire
și de scriere trebuie să existe și o secvență de reîmprospătare, care citește și rescrie datele.
Dimensiunea mică a circuitului permite o densitate mare și prețuri mici chiar și pentru o
capacitate de stocare mare.

Figura 6.5 Organizarea DRAM-ului

Pentru a reduce numărul de lini de adresă celulele de memorie sunt organizate matricial,
pe linii și coloane, iar adresele de linii (RAS) și coloane (CAS) sunt conectate la aceeași intrări,
trimise succesiv și stocate și decodificate intern separat. Reîmprospătarea se va realiza pe linia
selectată pentru toate locațiile de pe linie simultan folosind buffer intern. Varianta
îmbunătățită permite extragerea locațiilor succesive în rafală folosind intern tehnica pipeline

72
fără a transmite adresele de linie din nou. Dacă datele accesate sunt la adrese consecutive se
transmite adresa de linie o singură dată și adresele de coloană consecutiv, fără a aștepta
terminarea ciclului de citire, iar pe magistrala de date vor apare datele consecutiv.

Figura 6.6 Ciclu de citire / scriere (a.) și ciclu de citire / scriere în rafală (b.)

73
6. 1. 4 Memorii nevolatile

Istoric ele au pornit ca și tipuri de memorie ce pot fi doar citite (ROM) și au un rol extrem
de important în sisteme de calcul, deoarece ele conțin secvența de instrucțiuni ce va fi
executata la pornirea sistemului. Numărătorul de program la pornirea sistemului va fi încărcat
cu adresa prestabilită a memoriei ROM, cu adresa primei instrucțiuni ce va fi executat.
Memoria ROM nu poate fi înscrisă în sistem, ea trebuie înscrisă în procesul de fabricație.
Pentru ca producătorul să poată înscrie o memorie nevolatilă, sau eventual să o poate
suprascrie, memoriile ROM au evoluat foarte mult și pot fi șterse și rescrise. Memoriile FLASH
permit scrierea multiplă, dar ștergerea se va realiza pentru un bloc întreg. Operația de scriere
diferă de cel RAM-urilor și durează mult mai mult.
Dezvoltarea tehnologică a permis apariția noilor memorii volatile, care oferă o combinație
a caracteristicilor memoriilor nevolatile cu timpul de acces aleator al memoriilor statice.
Memoriile RAM (MRAM) magnetice utilizează spinul electronului pentru stocare, oferă o
densitate foarte mare de stocare pe unitatea de suprafață, păstrează conținutul când nu sunt
alimentate, și oferă un timp de acces egal la toate locațiile. Poate rezista la temperaturi
extreme și nu este alterat de radiații. Varianta îmbunătățită este STT-RAM , care se bazează
pe aceeași principiu de schimbare spin print-un curent ce traversează un tunel magnetic.
O altă tehnologie creează memorii nevolatile prin schimbare de fază (Phase-change RAM)
în sticlă calcogenică și va transforma structura amorfă a materialului în una cristalină.
Tot pe schimbare de fază se bazează și memoriile ReRAM, care vor crea rezistențe în urma
schimbării de fază în loc să stocheze sarcini ca memoriile nevolatile clasice.

6.1.5 Memorii asociative

Una din problemele importante este căutarea unei date în memorie. La memoriile clasice,
aceasta se realizează prin citirea succesivă a fiecărei locații de memorie, și compararea lui cu
data căutată. Memoriile asociative, adresabile prin conținut, asigură căutarea simultană a
datelor cerute în întreaga zonă de memorie. De obicei, numai o parte a conținutului (câmpul
cheie) este folosită în căutare, restul informației poate fi citită după ce s-au găsit locațiile. Un
circuit de selectare va asigura citirea secvențială a locațiilor la care s-a constatat coincidența
câmpului cheie.
Înscrierea se realizează prin aplicarea adresei (A), a datelor de intrare (I), activarea liniilor
de validare înscriere (WR) și validare intrare (C). La citire se aplică adresa și se dezactivează
liniile de validare intrare și validare înscriere, și se obține data la ieșire (O). Data căutată se
aplică la intrare, se activează linia de validare intrare, adresele și validare înscriere sunt
dezactivate, iar la ieșirea de coincidență (M) se obține 0 dacă conținutul celulei corespunde cu
cea căutată. Pentru a realiza din celule pe 1 bit o memorie asociată organizată pe cuvinte de
lungime fixă, liniile de adresă, de validare înscriere și de coincidență al unui cuvânt vor fi legate
împreună; la fel și liniile de validare intrare, de intrare și de ieșire de același rang de la toate
locațiile memoriei.

74
Figura 6.7 Memorie asociativă 2 cuvinte x 3 biți

Liniile de validare intrare C0, C1, C2 (denumiți și mască de căutare) vor fi activați numai
pentru bitul care intervine în căutare. Liniile de coincidență vor fi în zero logic numai dacă toți
biții unui cuvânt care intervin în căutare vor coincide cu conținutul locației.
Căutarea unui cuvânt se realizează simultan la toate cuvintele memoriei. Registrul mască
va activa liniile de validare intrare numai la biții corespunzători cuvântului cheie. Circuitul de
selecție are rolul de a genera adrese succesive în cazul în care există mai multe locații a cu un
conținut identic cu cel căutat. Registrul de ieșire va avea înscris, pe rând, conținutul complet
al locațiilor la care s-a găsit potrivire exactă pe mască.

75
Figura 6.8 Căutare în memorii asociative

Memoriile asociative sunt folosite pentru implementarea tabelelor de pagini sau de


segmente în adresarea virtuală pentru implementarea memoriilor cache.

6.2 Organizarea modulelor de memorie

6.2.1 Tehnici de selecție

În continuare vom prezenta prin exemple modul în care se va construi memoria unui
sistem de calcul din module de memorie.

Problema:
Capacitatea de adresare a unui sistem este de 16 Kbyte. Proiectați schema de selecție a
modulelor de memorie, folosind harta memoriei pentru următoarele module:
1 modul de 2 Kbyte conectat la adresa 0H, 2 module de memorie de câte 4 Kbyte fiecare,
conectate consecutiv, începând cu adresa de mijloc.
Rezolvare:
Pornind de la datele problemei determinăm numărul liniilor de adresă al sistemului și al
modulelor.
16 K = 214, de undă rezultă că magistrala de adresă are 14 linii de adrese,
2 K = 211, primul modul are 11 linii de adrese,

76
4 K = 212, următoarele module au 12 linii de adrese.

Putem completa harta memoriei stabilind pentru fiecare modul adresa de început și de
sfârșit, conform enunțului problemei.
Pentru fiecare modul determinăm funcția logică pentru linia de selecție a modului (CS),
care va fi activă pentru toate operațiile de citire și scriere a locațiilor din modulul respectiv. De
fiecare dată când pe magistrala de adresă apare o valoare care aparține modului I, linia de
selecție a modulului trebuie să fie activată, dar ea nu trebuie să fie activă pentru nici o adresă
din afara domeniului stabilit pentru acest modul.
Pentru modulul I putem determina condiția de activare a semnalului de selecție din harta
memorie, și anume linia de adresă A13 = 0, și A12 = 0 și A11 = 0. În mod asemănător modulul
II va fi selectat, dacă A13 = 1, și A12 = 0. Modulul III va fi selectat, dacă A13 = 1, și A12 = 1

𝐶𝑆(𝐼) = ̅̅̅̅̅
𝐴13 ∙ ̅̅̅̅̅
𝐴12 ∙ ̅̅̅̅̅
𝐴11
̅̅̅̅̅
𝐶𝑆(𝐼𝐼) = 𝐴13 ∙ 𝐴12
𝐶𝑆(𝐼𝐼𝐼) = 𝐴13 ∙ 𝐴12

A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 Adresa


0 0 0 0 0 0 0 0 0 0 0 0 0 0 0H înc.

0 0 0 1 1 1 1 1 1 1 1 1 1 1 7FFH sf.

1 0 0 0 0 0 0 0 0 0 0 0 0 0 2000H înc.

1 0 1 1 1 1 1 1 1 1 1 1 1 1 2FFFH sf.
1 1 0 0 0 0 0 0 0 0 0 0 0 0 3000H înc

1 1 1 1 1 1 1 1 1 1 1 1 1 1 3FFFH sf.

77
Figura 6.9 Harta memorie și schema de selecție a modulelor de memorie

6.2.2 Organizare întrețesută

În cazul în care memoria este lentă, magistrala poate fi folosită mai eficient, dacă
conectăm două module de memorie de dimensiuni egale și le accesăm alternativ. Datele de la
adrese pare și cele impare vor fi distribuite în cele două memorii, astfel citirea de la adrese
consecutive va selecta alternativ cele două module, reducând timpii de așteptare.
În continuare vom prezenta prin exemplu modul de organizare întrețesut al modulelor de
memorie.

Problema:
Capacitatea de adresare a unui sistem este de 8 Kbyte organizat din două module de câte
4 Kbyte fiecare conectat întrețesut. Proiectați schema de selecție a modulelor de memorie,
folosind harta memoriei.
Rezolvare:
Pornind de la datele problemei determinăm numărul liniilor de adresă al sistemului și al
modulelor.
8 K = 213, de undă rezultă că magistrala de adresă are 13 linii de adrese,
4 K = 212, modulele au 12 linii de adrese.

78
A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 Modul
0 0 0 0 0 0 0 0 0 0 0 0 0 I
0 0 0 0 0 0 0 0 0 0 0 0 1 II
0 0 0 0 0 0 0 0 0 0 0 1 0 I
0 0 0 0 0 0 0 0 0 0 0 1 1 II
0 0 0 0 0 0 0 0 0 0 1 0 0 I
0 0 0 0 0 0 0 0 0 0 1 0 1 II
0 0 0 0 0 0 0 0 0 0 1 1 0 I
0 0 0 0 0 0 0 0 0 0 1 1 1 II

1 1 1 1 1 1 1 1 1 1 0 1 0 I
1 1 1 1 1 1 1 1 1 1 0 1 1 II
1 1 1 1 1 1 1 1 1 1 1 0 0 I
1 1 1 1 1 1 1 1 1 1 1 0 1 II
1 1 1 1 1 1 1 1 1 1 1 1 0 I
1 1 1 1 1 1 1 1 1 1 1 1 1 II

Din analiza hărții memoriei putem scrie condiția de selecție pentru modulul I, A0 = 0, iar
linia de selecție a modulului II va fi activă dacă A0 = 1. Ca să asigurăm continuitatea locațiilor
de memorie din module (adresa pare în prima și adrese impare în a doua) va trebui să decalăm
cu o poziție toate liniile de adresă de pe magistrală când le conectăm la module.

79
Figura 6.10 Schema de selecție a modulelor de memorie

6.2.3 Module suprapuse

Există situații când capacitatea de adresare este redusă, sau nu avem nevoie simultan de
toată memoria fizică existentă cum ar fi cazul memoriei de pe placa grafică. Din punctul de
vedere al UCP de prelucrare se poate folosi o fereastră de adresare ( un interval de adrese)
dar fizic să existe mai multă memorie decât dimensiunea ferestrei. Memoria fizică va fi
organizată pe mai multe blocuri toate cuplate la aceeași adrese. O logică de selectare a
blocurilor va asigura selectarea doar unui singur bloc de memorie la un moment dat. Acest
circuit de selectare este cuplat de UCP ca un periferic, adică operația de selectare este
realizată de o instrucțiune de scriere la periferic. UCP trimite o adresă pe magistrala de adrese
iar operația de scriere, citire se va realiza în blocul selectat în funcție de valoare înscrisă într-
un registru (port de ieșire). Dacă se dorește schimbarea blocului se va înscrie o nouă valoare
în registru, modificând biții de selecție. Metoda permite creșterea capacității de stocare fără
a crește numărul liniilor de adresă. Stocarea valorilor jurnalizate (loguri) la un microsistem
poate fi organizat în blocuri suprapuse deoarece scrierea și citirea lor presupune accesul la o
cantitate mică de date la un moment dat.
Conținutul memoriei nevolatile dintr-un sistem de calcul (UEFI, BIOS) care are un timp de
acces mare, poate fi suprapus cu memoria RAM în care se va copia conținutul acestuia după
pornire și va fi accesat din acest bloc la utilizările ulterioare.

80
Problema:
Capacitatea de adresare a unui sistem este de 64 Kbyte. La adresa 0H se va conecta un
modul de 32 Kbyte, iar la capătul zonei de adresare se vor conecta 4 module de câte 16 Kbyte
fiecare, suprapuse și selectabile prin biții D2, D3 ai portului de ieșire de la adresa A000H.
Proiectați schema de selecție a modulelor de memorie, folosind harta memoriei și scrieți
secvența de operații pentru selectarea fiecărui modul. La operațiile de modificare a valorii
portului de ieșire numai biții de selecție se vor modifica, având în vedere că restul biților pot
avea alte funcționalități în sistem.
Rezolvare:
Pornind de la datele problemei determinăm numărul liniilor de adresă al sistemului și al
modulelor.
64 K = 216, de undă rezultă că magistrala de adresă are 16 linii de adrese,
32 K = 215, primul modul are 15 linii de adrese,
16 K = 214, următoarele module au 14 linii de adrese.

A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 Adresa


0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0H înc.

0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7FFFH sf.

1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 C000H înc

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 FFFFH sf.

81
Primul modul va fi selectat, când linia de adresă A15 = 0. Restul modulelor sunt suprapuse
din punct de vedere al UCP, deci toate vor avea condiția de selecție A15 = 1 și A14 = 1.
Valoare înscrisă în registrul de selecție ( portul de la adresa A000H) pe biții D3 și D2 vor
determina care va fi modulul selectat după următoarea condiție:

D3 D2 Modul
0 0 I
0 1 II
1 0 III
1 1 IV

Pentru a selecta pagina III vom înscrie D3 = 1 și D2 = 0 în registru, fără a modifica ceilalți
biți, vom aplica succesiv următoarele operații (x pe poziția unui bit înseamnă orice valoare):

valoare veche operația operand valoarea nouă


xxxxxxxx ȘI 11111011 xxxxx0xx
xxxxx0xx SAU 00001000 xxxx10xx

Figura 6.11 Schema de selecție a modulelor de memorie

82
6.3 Memorii cache

Memoriile cache vor fi conectate între unitatea centrală de prelucrare și memoriile


operative, și pot fi organizate la rândul lor pe mai multe nivele. Fizic ele pot fi incluse în
procesor, sau atașate modulelor de memorie. Memoria cache, de dimensiune mult redusă
față de dimensiunea operativă, conține copia datelor din memoria operativă, care sunt cele
mai frecvent folosite. Memoria operativă are 2n cuvinte iar memoria cache este mult mai mică.
Deoarece pentru o locație din cache concurează mai multe locații din memoria operativă,
trebuie să stocăm adresa locației de memorie care se află la un moment dat în cache denumit
în continuare marcaj. Dacă lungimea cuvântului este mai mic sau egal cu dimensiunea
adreselor (n) stocarea adreselor pentru fiecare cuvânt este extrem de ineficient. Soluția ar fi
organizarea memoriei cache pe linii (Figura 6.12), fiecare linie având K cuvinte de memorie un
număr de m biți de marcaj care identifică unic adresa liniei din memoria operativă stocați în
memorie asociativă, și biți de control. Un bit de control (v) arată dacă linia este validă, a fost
încărcată din memoria operativă sau intrarea respectivă nu este validă, încă nu a fost încărcată
nimic din memoria operativă pe acea poziție, sau linia a fost invalidată deoarece linia
corespunzătoare din memoria operativă a fost modificată de un alt procesor. Bitul de control
de modificare (m), indică faptul că datele din memoria cache au fost modificate și încă nu au
fost copiate înapoi în memoria operativă. Operația de citire este mai simplă, operația de
scriere poate fi realizată mai întâi numai în cache, ulterior când magistrala este liberă se vor
scrie înapoi în memorie operativă liniile modificate care au fost stocate într-un buffer
intermediar (write back) sau operația de scriere poate fi realizată totdeauna în memoria
operativă, și în cache simultan (write through), în acest caz se pierd beneficiile cache-ului la
scriere. În cazul în care toate locațiile sunt ocupate în cache trebuie să existe un circuit care
implementează un algoritm de înlocuire. Algoritmul de înlocuire va determina linia victimă,
care va fi suprascrisă de valoarea mai recentă ce trebuie să fie stocată în cache.
Dacă lungimea liniei din cache crește. eficiența acestuia crește, dar transferul liniei
necesită mai multe operații pe magistrală. În acest sens majoritatea implementărilor
realizează o conexiune directă, magistrală secundară cu memoria operativă. Controlerul de
cache are responsabilitatea de urmării magistrala sistemului, de a iniția operația de căutare a
cuvântului cerut în memoria asociativă, de a transmite/ recepționa datele pe magistrala de
date în caz de potrivire. În cazul în care datele nu sunt în cache controlerul va iniția înscrierea
tuturor cuvintelor de pe linia corespunzătoare din memoria operativă în cache. Ea va
determina linia victimă în cazul în care nu există linii goale, și va copia conținutul liniei înapoi
în memoria operativă dacă este cazul.

83
Figura 6.12 Conectarea memoriilor cache pe magistrală

Într-un sistem pot apare două tipuri de memorii cache: una pentru instrucțiuni și una
pentru date. Memoria cache pentru instrucțiuni nu se modifică, deci controlerul ei nu va
urmării conținutul ei, ci doar instrucțiunile da salt, când cache-ul trebuie golit, și reîncărcat de
la adresa nouă de salt. În cazul operațiilor de scriere în sisteme cu mai multe procesoare având
memorii cache comune pot apare inconsistențe între cele două memorii care poate fi
rezolvată prin:
- transcrierea imediată a modificărilor apărute în una din memorii în cealaltă;
- transcrierea prin intermediul unui buffer (modificarea apărută este rapid transcrisă
în buffer, din care va fi ulterior transferată, când magistrala este liberă - orice
cerere venită de la un alt procesor va fi interzisă în timpul transferului);
- transcrierea condiționată de o cerere venită de la un alt procesor pentru o locație
care a fost modificată, sau de înlocuirea blocului modificat din cache.
UCP transmite pe magistrala adresa cuvântului citit (scris), adresa va fi comparată în mod
paralel cu biții de marcaj din memorie cache. Dacă există potrivire, cuvântul cătat este în
memoria cache și va fi transmisă (preluată) pe magistrala de date. Dacă nu există potrivire
memoria cache nu răspunde cu date, iar ciclul de citire continuă și datele vor fi transmise pe
magistrala de date din memoria operativă.

6.3.1 Metode de implementare

Memorii cache cu mapare directă

Pentru a reduce numărul biților de marcaj și a simplifica înlocuirea datelor din cache,
introducem o convenție: fiecare locație de memorie operativă poate fi adusă în cache la o
singură poziție. Memoria operativă este împărțită în blocuri de lungimea egală cu dimensiunea
cache-ului. Împărțirea nu este una fizică, ea este o grupare logică obținută prin gruparea biților

84
de adresă. Poziția unei linii în cadrul unui bloc din memoria operativă se va păstra la copierea
ei în memoria cache.
Avantaje:
• În acest fel numai adresa blocului va fi înscrisă în memoria de marcaje pentru
fiecare linie încărcată, care înseamnă un număr redus de biți.
• Algoritmul de înlocuire linie este și ea mai simplă, deoarece linia victimă este unică,
nu necesită nici o decizie.
Dezavantaje:
• Există posibilitatea ca să avem poziții libere în cache, dar linia care trebuie copiată
va înlocui o linie recent utilizată și care va fi utilizată din nou în viitorul apropiat.
Exemplu parcurgerea unui vector cu pasul egal cu dimensiunea cache-ului sau
parcurgerea unui tablou bidimensional în ordinea greșită a indicelor (nu se
parcurge în ordinea de stocare a elementelor în memorie).
• Dacă programul accesează frecvent două zone de memorie care vor fi mapate în
memoria cache pe aceeași linie, doar una din ele va fi prezentă la un moment date,
iar dacă ele sunt accesate alternativ, datele căutate nu vor fi prezente în cache (nu
există potrivire).
Pentru calculul biților de marcaj pornim de la numărul biților de adresă (n), scădem biții
de adresă pentru selectarea cuvântului pe linie (w), poziția ei fiind aceeași în memoria
operativă și cache. În continuare scădem numărul biților de selecție a liniei în cadrul blocului
(l) din numărul de biți de adresă, dat fiind faptul că poziția liniei în bloc se păstrează să în
cache. Numărul de biți rămași reprezintă marcajul, care indică numărul blocului din care
provine linia respectivă din cache. În momentul când UCP accesează o locație de memorie,
trimite pe magistrala de adresă adresa de n biți. Controlerul de cache extrage adresa de bloc,
de linie și de cuvânt separat. Adresa de linie este folosită pentru a accesa linia corespunzătoare
din cache și va compara marcajul liniei respective cu câmpul de adresă de bloc. Dacă ele sunt
egale însemnă că linia din cache provine din blocul căutat și folosind adresa de cuvânt va
selecta cuvântul respectiv din zona de date din cache și o trimite pe magistrala de date. Dacă
nu există potrivire între marcaj și adresa de bloc linia respectivă din cache nu este din blocul
căutat și cache-ul nu returnează nimic. Controlerul de cache urmărește în continuare
magistrala de date, iar în momentul când memoria operativă va returna cuvântul cerut ea va
fi înscrisă și în memoria cache. Se copiază în cache întreaga linie în care se află cuvântul,
suprascriind linia corespunzătoare, iar marcajul liniei va fi suprascrisă cu noua adresă de bloc
(Figura 6.13).

85
Figura 6.13 Organizarea memoriei cache cu mapare directă

Problemă:
Proiectați o memorie cache cu mapare directă de 1024 de linii cu 256 biți pe fiecare linie
(32 cuvinte de 8 biți), dacă capacitatea maximă de adresare a sistemului este de 1 Gbyte.
Calculați necesarul maxim de memorie pentru date și marcaje.
Determinați eficiența memoriei utilizate.
Rezolvare:
Capacitatea de adresare se poate scrie în forma 1 Gbyte = 230 byte, deci numărul liniilor
de adresă pentru memoria operativă este de n = 30.
Numărul de cuvinte pe o linie este de 256/8 = 32 de byte = 2 5 byte, numărul biților de
selecție a cuvântului pe linie w=5.
Numărul liniilor dint-un bloc 1024 = 210, numărul biților de selecție a liniei din cache (bloc)
l=10.

86
Adresa fizică poate fi descompusă după cum se vede în figură:

29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

bloc(b) linie (l) cuvânt (w)


15 10 5
Numărul biților din marcaj m = n – w – l = 30 – 5 – 10 = 15.
Numărul biților de date d = 256.

Necesarul total de memorie cache se va calcula ca fiind suma dintre numărul biților de
date și al biților de marcaj înmulțit cu numărul de linii din cache. Dacă memoria cache este
organizată pe octeți (byte) se împarte la 8 și se va rotunji la un număr întreg de octeți.
dimensiune = 1024 ⦁ (256 + 15) biți = 1024 ⦁ 34 byte = 34 Kbyte.
Eficiența cache-ului se poate calcula ca raportul dintre numărul de octeți de date și cel
total: eficiența = 32/34 = 0.9411.

Memorii cache asociative

La această organizare orice linie de date din memoria operativă poate fi încărcată în cache
la orice poziție, dar deplasamentul în cadrul liniei se păstrează.
Avantaje:
• Cât timp există poziții libere în cache datele pot di aduse din memoria operativă la
orice poziție.
• În general numărul conflictelor scade comparativ cu maparea directă.
Dezavantaje:
• Numărul biților din marcaj este mai mare ea va conține toți biții de adresă mai
puțin deplasamentul pe linie.
• Algoritmul de selectare a poziției libere presupune verificarea simultană a bitului
valid pentru toate liniile.
• Algoritmul de înlocuire linie este mai complicat, trebuie să țină cont de bitul de
modificare a liniei, dar și să găsească linia care nu a fost accesată curând. Asta
înseamnă adăugarea de biți de stare, care sunt setate, incrementate la orice
operație și șterse periodic. Liniile care au contorul (biții) de acces pe 0 sunt
considerate vechi și pot fi înlocuite.
Pentru calculul biților de marcaj pornim de la numărul biților de adresă (n), scădem biții
de adresă pentru selectarea cuvântului pe linie (w), poziția ei fiind aceeași în memoria
operativă și cache. Numărul de biți rămași reprezintă marcajul, care indică adresa din care
provine linia respectivă din cache. În momentul când UCP accesează o locație de memorie,
trimite pe magistrala de adresă adresa de n biți. Controlerul de cache extrage adresa de linie
și de cuvânt separat. Adresa de linie este comparată cu toate marcajele din memoria cache
asociativă. Timpul de căutare poate fi redus considerabil dacă stocarea marcajelor se va realiza
în memorii asociative (adresabile prin conținut). Dacă există potrivire se returnează indexul

87
liniei, care conține adresa căutată și împreună cu adresa cuvântului va determina adresa
locației din cache a cărei conținut va fi trimis pe magistrala de date. (Figura 6.14)
Dacă nu există potrivire cache-ul nu returnează nimic. Controlerul de cache urmărește în
continuare magistrala de date, iar în momentul când memoria operativă va returna cuvântul
cerut se inițiază algoritmul de copiere a liniei în memoria cache. Cu o căutare paralelă pe bitul
indicator valid se determină dacă există poziție liberă în cache sau nu. Dacă există linie liberă
se copiază în cache întreaga linie, iar marcajul liniei va fi suprascrisă cu noua adresă. Dacă nu
există poziție liberă se determină adresa liniei victimă care va fi suprascrisă.

Figura 6.14 Organizarea memoriei cache asociative

Problemă:
Proiectați o memorie cache asociativă de 1024 de linii cu 256 biți pe fiecare linie (32
cuvinte de 8 biți), dacă capacitatea maximă de adresare a sistemului este de 1 Gbyte.
Calculați necesarul maxim de memorie pentru date și marcaje.
Determinați eficiența memoriei utilizate.

88
Rezolvare:
Capacitatea de adresare se poate scrie în forma 1 Gbyte = 230 byte, deci numărul liniilor
de adresă pentru memoria operativă este de n = 30.
Numărul de cuvinte pe o linie este de 256/8 = 32 de byte = 2 5 byte, numărul biților de
selecție a cuvântului pe linie w=5.
Adresa fizică poate fi descompusă după cum se vede în figură:

29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
bloc(b) w
25 5

Numărul biților din marcaj m = n – w = 30 – 5 = 25.


Numărul biților de date d = 256.

Necesarul total de memorie cache se va calcula ca fiind suma dintre numărul biților de
date și al biților de marcaj înmulțit cu numărul de linii din cache. Dacă memoria cache este
organizată pe octeți (byte) se împarte la 8 și se va rotunji la un număr întreg de octeți.
dimensiune = 1024 ⦁(256 + 25) biți = 1024 ⦁ 36 byte = 36 Kbyte.
Eficiența cache-ului se poate calcula ca raportul dintre numărul de octeți de date și cel
total: eficiența = 32/36 = 0.8888.

Comparând cele două soluții rezultă că ele reprezintă cele două extreme, dar se poate
realiza un compromis între ele, care reduce numărul conflictelor, dar și numărul mare de
comparatoare necesare pentru căutarea în memoria asociativă. Memoriile cache cu n (2,4,8)
căi (Figura 6.15), vor combina avantajele celor două metode. Ea va fi organizată în mod
asemănător ca și memoria cache cu mapare directă dar vor exista n tabele în care se poate
încărca o linie. O adresă va și împărțită în câmpuri de bloc, linie și cuvânt. Adresa de linie este
folosită ca un index pentru a compara simultan în cele n tabele marcajul de la linia
corespunzătoare și adresa de bloc. Dacă există potrivire, un circuit suplimentar de selecție va
determina tabela exactă din care se va citi operandul dorit. Dacă o linie nu este prezentă în
cache, și poziția în care trebuie adusă este ocupată de o linie dint-un alt bloc, linia respectivă
poate fi adusă în oricare dintre cele n tabele. Dacă nici o tabelă nu are poziția corespunzătoare
liberă se alege una din ele ( preferabil cel care nu a fost accesat recent) și se va înlocui cu noua
linie. Pentru a determina dacă o pagină a fost accesată recent vom avea nevoi și în acest caz
de un bit suplimentar care este setat la orice operație (citire, scriere) și este șters periodic.
Numărul de conflicte se reduce astfel considerabil, chiar dacă liniile ce urmează a fi accesate
se află la distanța de un bloc.

89
Figura 6.15 Organizarea memoriei cache cu mapare directă de 2 căi

Problemă:
Proiectați o memorie cache cu mapare directă 4 căi de 256 de linii cu 32 biți pe fiecare
linie, dacă capacitatea maximă de adresare a sistemului este de 4 Gbyte.
Calculați necesarul maxim de memorie pentru date și marcaje.
Determinați eficiența memoriei utilizate.
Rezolvare:
Capacitatea de adresare se poate scrie în forma 4 Gbyte = 232 byte, deci numărul liniilor
de adresă pentru memoria operativă este de n = 32.
Numărul de cuvinte pe o linie este de 32/8 = 4 de byte = 2 2 byte, numărul biților de
selecție a cuvântului pe linie w=2.
Numărul liniilor dint-un bloc 256 = 28, numărul biților de selecție a liniei din cache (bloc)
l=8.

90
Adresa fizică poate fi descompusă după cum se vede în figură:

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
bloc(b) Linie(l) w
22 8 2

Numărul biților din marcaj m = n – w – l = 32 – 2 – 8 = 22.


Numărul biților de date d = 32.

Necesarul total de memorie cache se va calcula ca fiind suma dintre numărul biților de
date și al biților de marcaj înmulțit cu numărul de linii din cache și înmulțit cu numărul de
tabele cache. Dacă memoria cache este organizată pe octeți (byte) se împarte la 8 și se va
rotunji la un număr întreg de octeți.
dimensiune = 4⦁256 ⦁(32 + 22) biți = 1024 ⦁ 7 byte = 7 Kbyte.
Eficiența cache-ului se poate calcula ca raportul dintre numărul de octeți de date și cel
total: eficiența = 4/7 = 0.5714.

91
7. Sistemul de intrare ieșire

7.1 Operații de intrare - ieșire

7.1.1 Magistrala simplă controlată de o singură unitate de control

În varianta cea mai simplă, pornind de la arhitectura de bază conectarea tuturor


componentelor se va realiza prin magistrala unică a sistemului. Magistrala sistem conține
liniile de adrese, de date și de control. Fiecare componentă va avea asignată un set unic de
adrese și urmărește magistrala de adrese. În cazul în care decodifică propriile adrese,
transmite sau recepționează date, în funcție de semnalele de control generate de UCP.
În varianta în care există doar 2 semnale de control citire (RD) și scriere (WR) și un set de
adrese, determinat de numărul liniilor de adrese, o submulțime de adrese va fi rezervată
pentru conectarea echipamentelor de intrare ieșire pe magistrală. În acest caz vorbim de
periferice mapate în memorie. Spațiul de adrese al perifericelor nu va fi ocupat de module de
memorie. Accesul la periferice se va realiza cu instrucțiunile de citire scriere memorie, iar
perifericele lente pot prelungii ciclul de citire scriere prin intercalarea stărilor de așteptare
activând semnalul de control READY.
Dacă setul de instrucțiuni conține instrucțiuni dedicate pentru periferice (IN adresa, OUT
adresa), și magistrala de control va avea semnale de control dedicate, cum ar fi citire de la
periferic (IOR), scriere la periferic (IOW), practic spațiul de adresă se dublează, fiecare adresa
poate indica o locație de memorie, sau o unitate de stocare la un periferic denumit în
continuare port (Figura 7.1).

Figura 7.1 Structura magistralei și semnalele de control

92
Cea mai simplă metodă de comunicare se realizează prin instrucțiuni de intrare - ieșire
(IN, OUT). Procesorul selectează perifericul prin liniile de adrese, generează semnalele de
control corespunzătoare direcției de transfer (IOR, IOW) și realizează comunicarea prin
magistrala de date. Perifericul trebuie să fie totdeauna pregătit pentru transfer; dacă
instrucțiunea dorită nu se poate realiza într-un ciclu, perifericul, asemănător memoriilor,
poate cere intercalarea unor stări de așteptare prin semnalul READY.
Modelul acesta este mult simplificat, dar permite să înțelegem modul în care UCP poate
trata în mod unitar o varietate foarte mare de periferice. Exceptând microsistemele de calcul,
sau sistemele încorporate la care conectăm direct echipamente simple de intrare cum ar fi
senzori digitali, comutatoare sau echipamente de ieșire cum ar fi relee, diode, afișaje; la
sistemele de calcul de uz general conectarea perifericelor se va realiza prin interfețe dedicate
sau prin procesoare dedicate de intrare ieșire. Interesant este totuși că orice interfață, sau
procesor de intrare - ieșire din punct de vedere al UCP este o colecție de porturi, prin care se
va realiza comunicarea între ele. Acest model are dezavantajul de a reduce rata de utilizare a
magistralei sistemului din cauza perifericelor lente, care vor ocupa magistrala pe durata
ciclului de transfer.
Orice echipament periferic poate fi conectat dacă respectă un protocol impus, definit prin
diagrama de timp a comunicației, prin diagrama de stare sau orice metodă formală care poate
descrie o secvență de operații pe un set finit, predefinit de date. Protocolul poate fi una
predefinită, caz în care pot exista interfețe standarde implementate de un sistem, sau pot fi
dedicate, caz în care se va proiecta o interfață, care va fi conectată la sistem. Interfața sau
procesorul de intrare-ieșire poate implementa un protocol implementând mașina de stare,
poate avea elemente de stocare intermediare, dar este conectată la magistrala sistemului și
comunică cu UCP prin porturile de la adrese unice asignate interfeței. Astfel UCP nu va rula
secvența de cod necesară pentru a comunica cu perifericul. În același timp interfața poate
realiza conversia între diferite forme de reprezentare a datelor, dar și adaptarea semnalelor
electrice la cerințele perifericului. UCP are rolul de a iniția transferul, de a stabili parametrii și
de a controla schimbul de date, toate aceste operații realizându-se prin scrierea, citirea unor
porturi. Pot coexista mai multe magistrale standarde de intrare ieșire în sistem organizate
chiar pe mai multe nivele, dar această organizare va fi transparentă UCP (Figura 7.2).

93
Figura 7.2 Conectarea perifericelor prin procesoare de intrare-ieșire

7.1.2 Conectarea unui port de intrare – ieșire pe magistrală

În varianta cea mai simplă putem alege registre cu ieșiri cu impedanță ridicată, pe care le
conectăm direct la magistrala sistemului. În modul de lucru prin interogare toate operațiile
de intrare ieșire vor fi inițiate de UCP prin apelarea instrucțiunilor IN, OUT. Datele de la
periferice vor fi înscrise în portul de intrare în momentul în care se activează semnalul de tact
și vor fi citite în momentul în care UCP execută instrucțiunea IN. Datele de ieșire vor fi trimise
la periferic în momentul în care UCP execută instrucțiunea OUT, și vor fi preluate de periferic,
când acesta activează semnalul OE al portului de ieșire. În cazul în care perifericele de intrare
sunt simple comutatoare un semnal de tact periodic poate controla înscrierea în registre, sau
chiar semnalul de activare al ieșirilor poate controla și înscrierea, dacă timpul de propagare
prin registru permite acest lucru. Dacă perifericul de ieșire este un releu, sau un LED, ieșirile
portului de ieșire pot fi active permanent prin conectarea la valoarea ‘1’. Vom prezenta
modul de conectare al porturilor și modul de lucru prin interogare prin următorul exemplu
(Figura 7.3).

94
Figura 7.3 Conectare porturi de intrare ieșire

Exemplu: La un microsistem se conectează un port de intrare la adresa 2A00H, și un port


de ieșire la adresa 2A01H. La portul de intrare se vor conecta 8 butoane, iar la portul de ieșire
8 LED-uri. Se cere conectarea porturilor la magistrală considerând magistrala de date de 8 biți
și magistrala de adresă de 14 biți. Aplicația va citi starea întrerupătoarelor periodic și va
aprinde un număr de LED-uri egal cu numărul întrerupătoarelor acționate simultan.
Pornim de la forma binară a adreselor:

A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 Adresa


1 0 1 0 1 0 0 0 0 0 0 0 0 0 2A00H
1 0 1 0 1 0 0 0 0 0 0 0 0 1 2A01H

Conectarea portului de intrare:


T1 = se poate aplica un semnal de tact periodic, care va înscrie valoarea momentană
̅̅̅̅̅ ∙ A11 ∙ A10
OE1 = A13 ∙ A12 ̅̅̅̅̅ ∙ A9 ∙ A8
̅̅̅̅ ∙ ̅̅̅̅ A6 ∙ ̅̅̅̅
A7 ∙ ̅̅̅̅ A5 ∙ ̅̅̅̅
A4 ∙ ̅̅̅̅
A3 ∙ ̅̅̅̅
A2 ∙ ̅̅̅̅
A1 ∙ ̅̅̅̅
A0 ∙ IOR

Conectarea portului de ieșire:


T2 = A13 ∙ ̅̅̅̅̅
A12 ∙ A11 ∙ ̅̅̅̅̅
A10 ∙ A9 ∙ ̅̅̅̅
A8 ∙ ̅̅̅̅ A6 ∙ ̅̅̅̅
A7 ∙ ̅̅̅̅ A5 ∙ ̅̅̅̅
A4 ∙ ̅̅̅̅
A3 ∙ ̅̅̅̅
A2 ∙ ̅̅̅̅
A1 ∙ A0 ∙ IOW
OE2 = '1'

Scrierea și citirea porturilor se va realiza pe 8 biți simultan. Testarea unui singur bit de
intrare poate fi implementată folosind operația de mascare, adică aplicarea operației ȘI cu
valoarea mască. Masca va fi completat cu '1' pe poziția corespunzătoare intrării care urmează
a fi testată, și '0' pe restul pozițiilor. Astfel în pozițiile testate valoarea bitului va rămâne cea
citită, iar restul biților vor fi setați pe '0'.

95
Exemplu: testarea stării întrerupătorului de pe poziția 3.

operații cod în limbaj C


citește valoarea portului de la adresa 2A00H x = inportb(0x2A00)
maschează biții care nu vor fi testați y=x&8
testează dacă valoarea bitului este egală cu '1' if ( y != 0) sau if (y == 8)

Următoarea diagramă de stare prezintă secvența de operații pentru problema de mai sus
(Figura 7.4).

96
Figura 7.4 Diagrama de stare pentru citirea întrerupătoarelor și comanda LED-urilor

97
7.1.3 Interfață de intrare-ieșire, modul de lucru prin interogare

În cazul în care perifericul este un alt sistem, care nu poate trimite recepționa date în orice
moment ( ex. imprimantă, sistem de stocare, ...) trebuie implementat un protocol care
permite sincronizarea celor două sisteme (handshake). Schimbul de date se va realiza în
continuare prin liniile de date, dar echipamentul sursă va transmite un semnal de control de
validare date (STROBE). Dacă semnalul este activ, datele sunt stabile pe magistrala de ieșire și
pot fi preluate. Echipamentul destinație va transmite un semnal de confirmare a preluării
datelor (ACKNOWLEDGE), astfel sursa va cunoaște momentul terminării unui ciclu de transfer
și poate iniția următorul transfer. Chiar dacă acest protocol permite schimbul de date între
două sisteme ea are un neajuns major. Echipamentul sursă va transmite datele împreună cu
semnalul de validare și va intra în bucla de așteptare pentru confirmare, dar există
posibilitatea ca destinația să nu fie conectată, pornită sau să nu fie pregătită pentru preluarea
datelor din cauza unei erori (ex. lipsă de hârtie la imprimantă, sau buffer de citire plin). Pentru
a evita acest blocaj, putem adăuga un semnal de stare (READY) care va fi activat dacă
destinația este pregătită (Figura 7.5).

Figura 7.5 Protocol de sincronizare între două sisteme

Schema bloc a interfeței de intrare ieșire va conține elemente de stocare date, logica de
control pentru conectarea la magistrala sistemului și va transmite sau recepționa date de la
perifericul conectat va genera semnalele de control și va prelua semnalele de stare de la
periferic.

98
Figura 7.6 Schema bloc a interfeței de intrare-ieșire

Exemplu: În continuare se va proiecta o interfață simplificată pentru componenta sursă


a protocolului prezentat în figura 7.5. Adresele unice alocate interfeței vor fi 278H pentru
portul de date (ieșire), 279H pentru portul de stare (intrare), respectiv 27AH pentru portul de
control (ieșire). Semnalul STROBE va fi conectat pe bitul 0 al portului de control, semnalul
ACKNOWLEDGE pe bitul 6 iar semnalul READY pe bitul 7 al portului de stare. Se cere
conectarea porturilor la magistrală considerând magistrala de date de 8 biți și magistrala de
adresă de 10 biți.

Figura 7.7 Schema de conectare a porturilor

Pentru schema de selecție a porturilor pornim de la forma binară a adreselor (Figura 7.7):

A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 Adresa
1 0 0 1 1 1 1 0 0 0 278H
1 0 0 1 1 1 1 0 0 1 279H
1 0 0 1 1 1 1 0 1 0 27AH

Conectarea portului de date:


T1 = A9 ∙ ̅̅̅̅
A8 ∙ ̅̅̅̅
A7 ∙ A6 ∙ A5 ∙ A4 ∙ A3 ∙ ̅̅̅̅
A2 ∙ ̅̅̅̅
A1 ∙ ̅̅̅̅
A0 ∙ IOW
OE1 = activat de sistemul destinație

99
Conectarea portului de stare:
T2 = activat de sistemul destinație
OE2 = A9 ∙ ̅̅̅̅
A8 ∙ ̅̅̅̅
A7 ∙ A6 ∙ A5 ∙ A4 ∙ A3 ∙ ̅̅̅̅
A2 ∙ ̅̅̅̅
A1 ∙ A0 ∙ IOR
Conectarea portului de ieșire:
T3 = A9 ∙ ̅̅̅̅
A8 ∙ ̅̅̅̅
A7 ∙ A6 ∙ A5 ∙ A4 ∙ A3 ∙ ̅̅̅̅
A2 ∙ A1 ∙ ̅̅̅̅
A0 ∙ IOW
OE3 = activat de sistemul destinație
Scrierea și citirea porturilor se va realiza pe 8 biți simultan. Setarea unui bit se ieșire pe
'1' se va realiza cu ajutorul operației SAU. Se execută instrucțiunea între valoarea veche a
registrului și operandul care va avea pe '1' bitul de la poziția care trebuie setat și '0' pe restul
biților. Setarea unui bit se ieșire pe '0' se va realiza cu ajutorul operației ȘI. Se execută
instrucțiunea între valoarea veche a registrului și operandul care va avea pe '0' bitul de la
poziția care trebuie setat și '1' pe restul biților.

Exemplu: setarea bitului 4 pe '1' urmat de setarea lui pe '0'.

operații cod în limbaj C


citește valoarea portului de la adresa 27AH x = inportb(0x27A)
setează bitul 4 pe '1', SAU cu 10H x = x | 0x10
setează bitul 4 pe '0', ȘI cu EFH x = x & 0xEF

Următoarea diagramă de stare prezintă secvența de operații pentru problema de mai sus
(Figura 7.4).

100
Figura 7.8 Diagrama de stare a protocolului pentru sursă

Analizând implementările de mai sus observăm că modul de lucru prin interogare


înseamnă executarea secvenței de instrucțiuni care citește portul de intrare, testează un bit
de stare și repetă instrucțiunile până când starea bitului va fi cel așteptat. În acest timp UCP
nu poate executa alte instrucțiuni, sau dacă vor fi interogate mai multe periferice simultan
perioada de interogare pentru un periferic crește, cu posibilitatea de a pierde un impuls de la
intrare a cărei durată este mai mică decât perioada de interogare. Pentru rezolvarea
problemei s-au propus două metode de operare cu periferice: modul de lucru în întreruperi
cu posibilitatea executării de alte instrucțiuni în timp ce așteaptă pentru schimbarea de stare
al perifericului și modul de lucru cu transfer direct în memorie (DMA), cu posibilitatea de a
transfera date direct pe magistrala de date între periferic și memorie fără controlul UCP.

101
7.2 Întreruperi

În cazul unei întreruperi provenite de la o sursă internă sau externă, UCP transferă
temporar controlul de la programul în curs de execuție la o secvență specială de instrucțiuni
de tratare a întreruperii. Întreruperile externe provenite de la echipamentele de intrare-ieșire
eliberează procesorul de urmărirea stării lor, și vor iniția un transfer de fiecare dată când sunt
pregătite. Ele pot indica terminarea unei operații inițiate de UCP, apariția unei erori la
echipamentul de intrare-ieșire sau inițierea unui nou transfer. Generarea întreruperii se
realizează prin activarea liniei de control corespunzătoare (INT), legat de un registru al UCP-
ului (figura 7.9). Unitatea centrală de prelucrare la terminarea fiecărui ciclu de instrucțiune
testează starea registrului de întrerupere.

Figura 7.9 Generare semnal de întrerupere

Etapele prelucrării unei întreruperi sunt:


• acceptarea întreruperii prin activarea semnalului INTA pe magistrala de control;
• identificarea sursei cererii de întreruperi, perifericul va trimite pe magistrala de
date un număr unic de identificare (vector de întrerupere);
• obținerea adresei rutinei de servire din tabela de întrerupere, folosind vectorul
primit ca un index în tabelă;
• salvarea numărătorului de program (adresă de revenire) și a informațiilor de stare
al UCP;
• executarea rutinei de tratare a întreruperii până la instrucțiunea de revenire din
întrerupere (RETURN);
• refacerea numărătorului de program și a stării salvate, revenirea la programul
întrerupt.

102
Modul de executare al rutinei de tratare al întreruperii este similar cu apelul de
procedură, dar momentul în care se va executa procedura nu este cunoscută de programator
la dezvoltarea programului. Acesta poate crea dificultăți în dezvoltarea aplicațiilor, deoarece
toate resursele procesor utilizate în rutina de tratare întrerupere (registre, biți indicatori de
stare) trebuie salvate în mod explicit de programator în rutina de tratare a întreruperii la
începutul rutinei și refăcute înainte de revenire. În acest scop pot fi utilizate instrucțiunile de
depunere și scoatere din stivă, sau pot fi definite zone speciale de salvare în memorie. Există
arhitecturi speciale de UCP, care lucrează cu set de registre separate pentru rutina de tratare
întrerupere, iar UCP va face schimbul de registre automat la acceptarea cererii de întrerupere.
În timpul execuției rutinei de întrerupere poate fi recepționat o nouă cerere de
întrerupere (Figura 7.10). Dacă sistemul a fost proiectat să comute automat pe un set de
registre auxiliar, întreruperea întreruperii nu va fi permis automat. UCP-urile sunt prevăzute,
de regulă, cu instrucțiuni speciale pentru activarea, dezactivarea și mascarea întreruperilor.
Acestea sunt necesare în secțiunile critice ale programului, când apariția unei întreruperi ar
afecta funcționarea întregului sistem (de ex. în cazul programării unei componente a
sistemului). Sistemele de calcul pot fi prevăzute și cu linii speciale de cerere de întrerupere
care nu pot fi dezactivate, denumite întreruperi nemascabile. Acestea se folosesc pentru
detectarea unor erori critice (de ex. scăderea tensiunii de alimentare).

Figura 7.10 Întreruperea rutinei de tratare a întreruperii

Există situații când executarea unei instrucțiuni generează o situație specială care necesită
întreruperea instrucțiunii în curs de execuție, ea generează o excepție care declanșează
executarea unei secvențe de tratare a excepției, după care se revine la executarea instrucțiunii
care a generat excepția(Figura 7.11).
Tipuri de excepții: depășire capacitate la operații cu virgulă flotantă, adresă invalidă care
nu este încărcată în memoria operativă, instrucțiune invalidă.

103
Figura 7.11 Excepții

Metodele de determinare al priorităților în cazul întreruperilor multiple (provenite de la


mai multe echipamente simultan ) pot fi rezolvate de procesor sau de un circuit dedicat
controler de întrerupere. Cea mai simplă metodă în cazul implementării de către procesor,
constă dintr-o linie unică de cerere de întrerupere la care procesorul va răspunde cu
acceptarea întreruperii (INTA) la care echipamentul corespunzător trebuie să trimită un număr
unic de identificare (vector de întrerupere) prin magistrala de date. Arbitrarea poate fi
realizată bit cu bit pe identificator, iar echipamentul care detectează un conflict între valoarea
bitului transmis și cel recepționat se va opri din transmisie și va abandona cererea, pe care o
repetă ulterior. UCP va determina adresa rutinei de tratare a întreruperii în funcție de numărul
unic de identificare a sursei întreruperii pe baza unei tabele de întreruperi stocată în UCP sau
în memorie. Dacă tabela este stocată în UCP nu poate fi modificată și va mapa adrese fixe la
fiecare vector. Dacă programatorul dorește să schimbe rutina de tratare a întreruperii la
adresa fixă va înscrie instrucțiunea de apel de subrutină cu adresa rutinei ce va fi executat.
Dacă tabela este organizată în memorie atunci programatorul poate modifica conținutul
locațiilor de memorie ce conțin adresa rutinei de tratare a întreruperii, modificând astfel
rutina de tratare a întreruperii. Având în vedere că memoria nu-și păstrează conținutul când
nu este alimentat, această tabelă trebuie inițializată în faza de pornire a sistemului
(bootloader) din memoria nevolatilă. Adresele din tabela de întrerupere trebuie să arată către
locații care conțin prima instrucțiune din rutina de tratare a întreruperii corespunzătoare.
Modificarea neautorizată a tabelei de întrerupere poate conduce la executarea unor rutine de
tratare a întreruperii care nu au fost înregistrate de către sistemul de operare, sau de către
proiectantul sistemului și reprezenta surse de atac a sistemului (ex. înregistrarea oricărei taste
apăsate).
UCP poate implementa o schemă cu linii de întreruperi multiple, în care fiecare
echipament este conectat la propria linie de cerere a întreruperii (Figura 7.12). Adresa rutinei
de întrerupere va fi generată de UCP în funcție de linia de cerere activată. Determinarea
priorităților se realizează tot de UCP. În acest caz realizarea interfețelor de intrare ieșire este
mai simplă ele vor genera condiția de întrerupere, dar nu trebuie să stocheze și să trimită
vectorul de întrerupere. Nu trebuie să implementeze metoda de arbitrare bit cu bit pe
transmiterea vectorului de întrerupere.

104
Figura 7.12 Sistem de întreruperi cu semnale multiple de cerere

Metoda de arbitrare și generarea vectorilor de întrerupere corespunzătoare liniilor


individuale de întrerupere poate fi implementată și de un circuit dedicate, denumit controler
de întrerupere (Figura 7.13). Circuitul poate deservi mai multe linii de cerere întrerupere
provenite de la diferite echipamente de intrare-ieșire. Cererile vor fi stocate într-un registru
de întrerupere. Registrul mască de întrerupere permite sau interzice trecerea unei întreruperi.
Dacă bitul corespunzător din mască este setat pe '1' cererea de întrerupere trimisă pe linia
corespunzătoare nu va fi validată și nu va fi transmisă mai departe spre UCP. Dacă bitul
corespunzător este setat pe '0' cererile recepționate vor fi transmise mai departe.
Codificatorul prioritar generează o unică întrerupere către UCP, și formează vectorul de
întrerupere corespunzător cererii deservite. În cazul în care există mai multe cereri simultane,
mai mulți biți ai registrului de întrerupere au fost setați pe '1', codificatorul prioritar va genera
vectorul de întrerupere corespunzător liniei cu prioritatea cea mai mare, dar nu șterge din
registrul de întreruperi cererea care nu a fost transmisă mai departe. Sistemul de întreruperi
va fi dezactivat automat dacă a fost acceptată o întrerupere. Ea poate fi reactivată prin
program. Programatorul are posibilitatea de a decide momentul când va fi reactivat, la prima
instrucțiune din rutina de tratare a întreruperii sau la orice pas. Programatorul poate activa
selectiv liniile de întrerupere folosind registrul mască. În momentul în care controlerul de
întrerupere a fost reactivat va testa starea registrului de întrerupere și inițiază un ciclu de
cerere de întrerupere dacă există biți setați pe '1' în registrul de întrerupere. Modul în care se
va stabili prioritatea cererilor de întrerupere poate fi modificat de UCP, la fel și valoarea
vectorului de întrerupere transmis. Din punct de vedere al UCP controlerul de întrerupere este
un echipament de intrare-ieșire (periferic), care are un set de porturi prin care comunică cu
UCP. La stabilirea priorităților există două moduri de lucru. În modul cu prioritate fixă fiecare
linie are un nivel de prioritate prestabilit și în cazul în care avem mai mulți biți setați pe '1' în
registrul de întrerupere se va transmite vectorul celui care are prioritatea cea mai mare. Există

105
posibilitatea de a întârzia foarte mult o cerere venită de la un echipament cu prioritate mică,
deoarece apar cereri noi de la echipamente cu prioritate mai mare în timpul deservirii unei
cereri. Există posibilitatea de a seta prioritate rotativă, care oferă șanse egale fiecărei linii de
întrerupere. În acest caz linia care a fost deservită va avea prioritatea cea mai mică, iar
numărul de ordine următor acestuia va avea prioritatea cea mai mare. În sisteme de calcul de
uz general folosim prioritate fixă, deoarece diferite componente au frecvența de apariție a
evenimentelor și lungimea rutinei de tratare a întreruperii diferite, și timpul de răspuns impus
diferitelor evenimente externe este diferit.

Figura 7.13 Structura controlerului de întrerupere

7.3 Transfer de date cu acces direct la memorie (DMA)

În mod obișnuit, transferul de date dintre memorie și periferic se realizează prin


intermediul UCP-ului cu două instrucțiuni: se citesc datele din memorie în UCP de unde se
transmit la echipamentul de intrare-ieșire sau invers se citesc datele de la periferic și se înscrie
în memorie. Transferul unui octet va însemna 4 cicluri de transfer pe magistrală, două pentru
extragerea celor două instrucțiuni și două pentru transferul operandului. Dacă perifericul sau
memoria sunt mai lente UCP-ul trebuie să testeze linia de stare (READY) a perifericului, pentru
a realiza sincronizarea cu aceasta.
Există posibilitatea ca un circuit special să realizeze transferul direct al datelor denumit în
continuare controler DMA.

106
Figura 7.14 Conectarea controlerului DMA

Controlerul DMA este un echipament de intrare-ieșire din punct de vedere al UCP, cu care
comunică prin porturile ei de intrare-ieșire. Controlerul DMA va avea un număr de n canale
(1-8) de comunicare dedicate cu echipamente de intrare ieșire, pentru care poate efectua
transferul datelor în memorie fără intervenția UCP, adică fără executarea secvenței specifice
de instrucțiuni de transfer. Pe durata transferului controlerul va prelua controlul asupra
magistralei, procesorul va fi practic deconectat de la ea prin setarea ieșirilor în impedanță
ridicată. Pe durata unui ciclu pot fi transferate un cuvânt sau un bloc de date. Înainte de orice
operație de transfer controlerul DMA trebuie programat. Programatorul (sistemul de operare)
va alege momentul când se va executa secvența de instrucțiuni corespunzătoare programării.
Procesorul trimite adresa de început și lungimea blocului ce urmează să fie transferat, precum
și direcția transferului, din periferic în memorie sau invers. Toate datele de programare vor fi
înscrise în registre speciale. Controlerul DMA va incrementa adresa de memorie automat după
fiecare transfer, și va decrementa numărătorul de cuvinte care a fost înscris inițial cu lungimea
blocului. La terminarea unui ciclu de transfer controlerul înscrie un registru de stare ce poate
fi interogat de UCP sau poate fi programat să genereze o întrerupere. Se poate reprograma
controlerul în rutina de tratare a întreruperii dacă acest lucru este necesar.
Transferul de date dintre memorie și echipamentul de intrare-ieșire se realizează direct,
datele nu trec prin circuitul DMA. Fiecare periferic are un canal propriu de DMA. Când un
periferic inițiază un transfer activând linia dedicată de cerere (DRQ), circuitul DMA care este
deja programat va cere accesul la magistrală de la UCP activând linia de cerere pe magistrala
de control (HOLD). UCP va semnala acceptarea cererii prin activarea liniei de răspuns (HOLDA)
și prin setarea ieșirilor (magistrala de adrese, date și control) în impedanță ridicată.
Controlerul DMA va realiza legătura directă între periferic și memorie trimițând semnalul de

107
acceptarea cererii la periferic (DACK), adresa locației de memorie pe magistrala de adrese,
semnalele control corespunzătoare direcției transferului pe magistrala de control (IOR și
MEMW sau IOW și MEMR) iar prin magistrala de date se realizează transferul de date între
locația de memorie selectată și perifericul legat la canalul respectiv. Un controler DMA poate
avea mai multe canale a căror prioritate este programabilă prin portul de ieșire corespunzător
în faza de programare. Canalele pot fi folosite și pentru transferul dintr-o zonă de memorie în
alta, dar această operație se realizează cu două accese la magistrală, iar data citită va fi stocată
temporar în registrul de date al controlerului DMA. În acest caz transferul este inițiat de
procesor prin executarea unei instrucțiuni ce va scrie în portul de control al circuitului DMA.
Există două moduri de transfer:
• în rafală - UCP suspendă operațiile în timpul transferului unui bloc, după care preia
ciclul de instrucțiune din punctul în care s-a suspendat;
• prin furt de ciclu - DMA are acces la memorie tot timpul când UCP nu folosește
magistrala.

Figura 7.15 Suspendarea executării unei instrucțiuni pentru DMA sau întrerupere

În figura 7.15 sunt indicate momentele în care UCP poate preda magistrala controlerului
DMA la terminarea fazei unei instrucțiuni. Testarea liniei de întrerupere poate fi realizată
numai la terminarea completă a fazelor instrucțiunii, deoarece acceptarea unei întreruperi
presupune executarea unei secvențe de instrucțiuni.
În continuare vom compara secvența de cod corespunzătoare implementării unui
protocol de comunicare cu un periferic de intrare (Figura 7.16) care transmite un bloc de date
(ex. camera web).
În modul de lucru cu interogare UCP trimite un semnal de cerere date, după care citește
portul de stare al perifericului și testează dacă acesta a trimis date și a activat semnalul de
date valide. UCP va executa în buclă secvența de citire port și testare, până când semnalul
testat va fi activ. UCP va citi datele disponibile și le înscrie în memorie, după care reia întreaga
secvență de cerere așteptare de n ori.
În modul de lucru prin întrerupere vom defini două secvențe distincte de cod. Programul
principal setează adresa de tratare a întreruperii pentru rutina de citire date și inițiază prima

108
cerere prin activarea semnalului de cerere. Semnalul de date valide de la periferic va fi
conectat pe linia de cerere întrerupere. În rutina de întrerupere se citesc datele se înscriu
datele în memorie și se trimite cerere pentru următorul cuvânt din bloc dacă nu s-au transferat
toate datele din bloc. UCP nu mai așteaptă după perifericul lent, poate executa orice altă
secvență de instrucțiuni.
În modul de lucru cu transfer direct în memorie vom avea din nou două secvențe de cod.
Programul principal setează adresa de tratare a întreruperii pentru rutina de programare a
noului transfer dacă cel precedent s-a finalizat cu succes și programează controlerul DMA cu
adresa de memorie unde se va efectua transferul, cu lungimea blocului și cu direcția
transferului (citire de la periferic, scriere în memorie). În continuare va fi ales modul de lucru
pentru controlerul DMA de transfer în rafală cu generarea întreruperii la terminarea
transferului. În rutina de întrerupere care se va apela la terminarea transferului de bloc, se
verifică starea transferului și se poate reprograma controlerul DMA, dacă orice parametru
programat anterior trebuie schimbat.

109
Figura 7.16 Compararea celor 3 moduri de lucru cu periferice

110
8. Suport pentru sisteme de operare

8.1 Adresare virtuală

Pornind de la formatul instrucțiunilor putem afirma, că în momentul dezvoltării


aplicațiilor trebuie să fie cunoscut dimensiunea și organizarea memorie fizice de către
programator. Acest lucru este posibil dacă sistemul este simplu și rulează o singură aplicație
la un moment dat, care este încărcată de fiecare dată la aceeași adresă cunoscută în momentul
compilării aplicației. În cazul în care rulează mai multe aplicații simultan, când aplicațiile pot fi
încărcate dinamic la diferite adrese, când programatorul, compilatorul nu cunoaște
organizarea exactă a memoriei (harta memoriei) compilarea programelor nu poate genera
instrucțiuni cod mașină care pot fi executate direct, deoarece adresele fizice pot fi
determinate numai în momentul încărcării programelor sau chiar numai în momentul
execuției lor. Pentru separarea spațiului de adresă programelor, de spațiul de adresă fizic al
memoriei s-a introdus adresarea virtuală în UCP. În momentul dezvoltării aplicațiilor
programatorul va avea la dispoziție un spațiu de memorie liniar determinat de spațiul de
adrese al instrucțiunilor cod mașină, care poate fi mai mică sau mai mare decât spațiul de
memorie fizic (memoria operativă) al sistemului. Fiecare aplicație va avea aceeași spațiu de
memorie liniar virtual indiferent de numărul de aplicații ce vor rula pe sistemul respectiv la un
moment dat. Adresarea virtuală este un mecanism de transformare a adreselor din
instrucțiuni în adrese fizice (Figura 8.1), care este parțial rezolvat de UCP, dar care presupune
crearea și actualizarea unor structuri de date executând o secvență de instrucțiuni specifice
parte al sistemului de operare.

Figura 8.1 Adresarea virtuală

111
Rolul adresării virtuale poate fi văzută ca separarea spațiilor de adresă al programelor, ca
extinderea spațiului de adresă, ca protecția spațiului de adresă. UCP are rolul de a implementa
funcția de transformare în momentul executării instrucțiunilor, bazată pe o tabelă de mapare
stocată în memorie. Dacă tabela de mapare nu conține încă valoarea adresei fizice, deoarece
elementul adresat (instrucțiune sau operand) nu a fost încărcată în memoria operativă
(memoria fizică) UCP va genera o excepție (page fault). Rutina de tratare a excepției trebuie
să încarce datele lipsă de pe suportul de stocare secundar în memoria operativă dacă este
spațiu liber în memoria operativă și să completeze tabela de mapare a adreselor. Dacă nu
există spațiu liber în memoria operativă trebuie să înlocuiască date existente prin
suprascrierea lor. Dacă datele ce urmează a fi suprascrise au fost modificate ele trebuie salvate
în prealabil în memoria secundară. Sistemul de operare poate implementa diferite metode de
determinare a zonei de date ce urmează a fi înlocuită (victima), dar la terminarea rutinei de
tratare a excepției datele noi trebuie să fie încărcate în memoria operativă și tabela de mapare
trebuie să fie modificată corespunzător. La revenirea din excepție se va executa din nou
instrucțiunea care a generat excepția, dar în acest caz transformarea adreselor virtuale în
adrese fizice se va realiza cu succes. Dacă fiecare adresă virtuală are o intrare în tabela de
mapare, dimensiunea acesteia va deveni foarte mare și nu va încape în final în memoria
operativă. pentru a reduce dimensiunea tabelei de mapare memoria va fi organizată în blocuri,
iar maparea se va aplica adreselor de bloc, păstrând constantă poziția unui octet în interiorul
blocului în memoria virtuală și cea operativă.

8.2 Adresare virtuală prin paginare

Baza adresării virtuale prin paginare este împărțirea spațiului de adrese virtuale, care
înseamnă de fapt memoria secundară, și a celei fizice, memoria operativă în pagini de
dimensiuni egale. În memoria operativă există un tabel de pagini, care conține informații
despre fiecare pagină: adresa paginii din memoria operativă (B), un bit care indică dacă pagina
a fost încărcată în memoria operativă (L) și biții de stare (C) (drepturile de acces la pagină,
existența modificărilor, numărul accesări al paginilor).

Structura unei înregistrări în tabela de pagini:

Structura înregistrărilor
Adresa de bază B Locația L Biți de control C

O adresă virtuală (cea văzută de utilizator) este formată din numărul paginii și un
deplasament. Procesorul, prin unitatea de gestionare a memoriei, caută în tabela de pagini
datele corespunzătoare numărului de pagină virtual. Dacă pagina este prezentă în memoria
operativă (bitul L este setat pe 1), scoate adresa de început al paginii, și, adăugând
deplasamentul, formează adresa fizică a datei cerute. Totodată modifică biții de stare,

112
incrementând numărul de accese al paginii, iar dacă operația cerută este una de scriere
setează bitul care indică faptul că pagina respectivă a fost modificată. Pentru a reduce
dimensiunea tabelei de pagină se pot împărții adresa virtuală pe mai multe nivele organizând
structuri de tabele pe mai multe nivele. Astfel tabela de pagini de la un nivel are o dimensiune
mult mai mică. La organizarea pe 2 nivele adresa liniară virtuală va fi compusă din trei câmpuri:
directorul, pagina, deplasamentul în cadrul paginii (Figura 8.2) . Adresa de început al tabelei
directorilor poate fi stocată într-un registru al procesorului iar directorul corespunzător va fi
selectat din această tabelă folosind câmpul corespunzător ca un indice în tablou. Fiecare
director are definit o tabelă de pagini, de unde se selectează înregistrarea pentru pagina
corespunzătoare și se obține adresa de bază a paginii fizice. Deplasamentul va identifica locul
operandului în pagina astfel obținută.
La un moment dat doar tabela de directoare și câteva tabele de pagini (cele utilizate în
instrucțiunile recente) trebuie să fie încărcată în memoria operativă, reducând considerabil
necesarul de memorie pentru stocarea tabelelor de mapare.

Figura 8.2 Adresare virtuală prin paginare

Pentru implementarea mecanismului de adresare prin paginare pe două nivele avem


nevoie de trei operații de acces la memoria operativă, pentru a citi înregistrarea din tabela de
directoare cu adresa de început a tabelei de pagini corespunzătoare, pentru a citi înregistrarea
din tabela de pagini cu adresa de început a paginii dorite și pentru a citi datele din pagina
selectată. Dacă pagina dorită nu este încărcată în memoria operativă numărul de operații este
mult mai mare. Pentru a reduce numărul de operații efectuat pentru extragerea oricărei
instrucțiuni și operand, pornind de la localitatea temporară și spațială a instrucțiunilor și a
datelor, UCP este prevăzut de cache-uri interne care vor stoca un număr de înregistrări din
tabela de directoare și de pagini utilizate recent (Figura 8.3). Accesul la datele a cărei
înregistrări de translatare sunt stocate în cache poate fie realizat direct cu o singură operație.

113
Figura 8.3 Numărul de operații cu memoria

Întreaga operație este realizată de unitatea de gestionare a memoriei al UCP, fără


intervenția utilizatorului, care simte doar încetinirea rulării programului.
Posibilități de a reduce timpul de acces la o dată care nu se află în memoria operativă:
• realizarea tabelei de pagini în unitatea de gestionare a memoriei, sau cel puțin a
unei părți a tabelei, care conține informațiile despre paginile din memoria
operativă;
• introducerea unei tehnici mai complicate în alegerea paginii care va fi înlocuită,
pentru a alege, pe cât posibil, o pagină care nu a fost modificată, evitând astfel
scrierea ei înapoi în memoria secundară.
Unitatea de gestionare a memoriei (MMU) poate conține o memorie cache asociativă în
care se va realiza căutarea simultană a numărului paginii virtuale pentru a obține adresa fizică
a paginii fără acces la memoria operativă (translation lookaside buffer TLB). În cazul în care ea
nu se găsește în acest cache (buffer) căutarea va continua în tabela de pagini din memoria
operativă ( Figura 8.4).

114
Figura 8.4 Utilizarea memoriilor asociative pentru translatarea paginilor

8.3 Adresare virtuală prin segmentare

În cazul în care fiecare unitate de program, cod, date, stivă, biblioteci trebuie să aibă
atașat diferite drepturi de acces putem defini segmente de date care vor avea atașate o serie
de drepturi și nivele de protecție. Instrucțiunile vor rula la diferite nivele de protecție, iar
accesul la structurile de date atașate segmentelor, și al translatării adreselor va fi posibil numai
prin instrucțiuni speciale și numai la nivelul de privilegiu cel mai mare. UCP va trebui să
implementeze mecanisme de verificare a drepturilor și de gestionare a nivelelor de privilegiu.
Executarea unei instrucțiuni va fi condiționată de îndeplinirea tuturor condițiilor în caz contrar
se va genera o excepție.
La această metodă memoria virtuală este împărțită în segmente de lungimi variabile.
Împărțirea este executată de sistemul de operare și de compilator, urmărind mai flexibil
structura programului. Adresa logică este formată dintr-un selector și un deplasament.
Selectorul poate fi inclus în instrucțiune sau poate fi încărcat într-un registru al procesorului
asemănător adresării relativ la bază.

115
Figura 8.5 Adresare virtuală prin segmentare

Cu ajutorul selectorului (ca index), din tabela descriptorilor de segment se citește


înregistrarea care va conține adresa de început al segmentului, lungimea lui, precum și
drepturile de acces la segmentul respectiv. Deplasamentul reprezintă adresa operandului în
cadrul segmentului selectat (Figura 8.5).
Structura unui descriptor de segment:

Structura descriptor segment


Adresa de bază Lungimea Drepturi Nivel protecție

În cazul adresării virtuale prin segmentare pot exista mai multe registre pentru selector,
și cache pentru fiecare segment atașat registrului corespunzător, asigurând posibilitatea de
utiliza mai multe segmente simultan pentru cod, date, stivă și alte module, reducând numărul
de schimbări de segmente în cache.
Problema apare la înlocuirea unui segment din memoria operativă dacă nu există spațiu
suficient pentru încărcarea unui segment, datorită diferențelor de lungimi. Dacă segmentul
care trebuie încărcat este mai mic decât cel înlocuit, în memoria operativă rămâne un gol. În
cazul în care nu există un segment mai mare care poate fi înlocuit, se înlocuiesc mai multe
segmente. După o serie de înlocuiri, memoria principală devine fragmentată datorită
multitudinii de goluri. Relocare dinamică a segmentelor pentru reducerea golurilor necesită
și actualizarea tabelei de segmente. Această reorganizare durează în timp, dar poate fi evitată
dacă segmentele sunt de lungime fixă. În noile arhitecturi se utilizează adresarea virtuală cu
paginare dar la fiecare pagină în tabela de pagini vor fi atașate drepturi. Astfel avantajele celor
două funcții de protecție și extinderea capacității de adresare vor fi combinate.
La proiectarea unității de gestionare a memoriei trebuie stabilită poziția, dimensiunea și
tipul memoriilor cache utilizate (Figura 8.6). Memoria cache plasată între UCP și unitatea de
gestionare a memoriei va folosi adresele virtuale pentru căutare și poate returna adresa fizică

116
foarte repede fără translatarea acestora în adrese fizice de MMU. Problema apare dacă
sistemul permite utilizarea aceleași adrese virtuale de mai multe aplicații care trebuie mapate
în adrese fizice diferite. În acest caz memoria cache trebuie golită la fiecare schimbare de
aplicație (schimbare de task). Memoria cache plasată după unitatea de gestionare a memoriei
va folosi pentru căutare adresa fizică calculată în urma operațiilor de transformare a adreselor.
Memoriile cache conectate pe magistrala de adresă a sistemului au fost studiate în capitole
anterioare.

Figura 8.6 Conectarea memoriilor cache pentru sisteme cu adresare virtuală

8.4 Mașini virtuale

Odată cu creșterea performanțelor sistemelor de calcul numărul de aplicații care rulau pe


un sistem a crescut și ea. Adresarea virtuală permite izolarea memoriei între aplicații și un
nivel de protecție a blocurilor de memorie, dar în continuare rămâne o problemă majoră
separarea perifericelor și accesul controlat la ele. La nivelul sistemului de operare există mai
multe posibilități de virtualizare, dar acest lucru depășește cadrul cursului de arhitectura
sistemelor de calcul. În continuare vom studia doar aspectele de virtualizare al sistemului de
calcul, din punct de vedere al proiectării hard al sistemului. O componentă soft specială,
denumită monitor al mașinii virtuale (VMM) sau hypervisor va controla toate operațiile de
translatare al spațiului de adrese al mașinii virtuale pe sistemul real sau sistem gazdă. Toate
instrucțiunile care accesează resurse în mașina virtuală vor fi interceptate de hypervisor, care
va implementa mecanisme de protecție și separare a resurselor, eventual emularea
instrucțiunilor reale, creând instanțe virtuale separate, iar instrucțiunile reale de acces la
resurse vor fi executate în spațiul de adrese al hypervisor-ului.

117
Figura 8.7 Translatarea adreselor pentru mașini virtuale

Aplicațiile vor rula în mașina virtuală, nemodificate, exact așa cum ar rula pe un sistem
real. Adresele din spațiul de adrese al aplicației sunt în continuare adrese virtuale și vor fi
transformate în adrese fizice pentru sistemul oaspete prin mecanismul de translatare al
paginilor prezentate anterior. Mai multe aplicații pot rula simultan într-o mașină virtuală și vor
partaja spațiul de adrese al sistemului oaspete, ele fiind izolate și protejate prin mecanismul
de adresare virtuală prin paginare (Figura 8.7).
Mai multe mașini virtuale vor utiliza resursele reale ale sistemului gazdă prin hypervisor,
dar nu vor putea accesa direct. Acest hypervisor va translata adresele fizice ale sistemului
oaspete în adrese fizice reale ale sistemului gazdă folosind tabele de pagini extinse. Va
intercepta toate întreruperile și excepțiile de la procesor, și va executa instrucțiunile de
transfer între procesor, memorii și porturi. Hypervisor-ul este singura componentă software
care are acces și va modifica tabela de pagini extinsă. Ea va rula totdeauna la nivelul de
privilegii cel mai mare, iar setul de instrucțiuni speciale de gestionare a memoriei și de
protecție vor rula numai în această componentă.

118
Bibliografie
Aspray, W. and Burks, A. (1986). Papers of John von Neumann on computing and
computer theory. MIT Press.
Baruch Z. F.(2004). Structura sistemelor de calcul, Editura Albastră, Cluj-Napoca.
Donzellini, G., Oneto, L., Ponta, D., and Anguita, D. (2018). Introduction to Digital Systems
Design. Springer.
Gabbrielli, M. and Martini, S. (2010). Programming languages: principles and paradigms.
Springer Science & Business Media.
Gorgan D., Sebestyen Gh.(2008). Proiectarea calculatoarelor, Editura Albastră, Cluj-
Napoca.
Hennessy, J. L. and Patterson, D. A. (2017). Computer architecture: a quantitative
approach. Morgan Kaufmann.
Ledin, J.(2020). Modern Computer Architecture and Organization: Learn x86, ARM, and
RISC-V architectures and the design of smartphones, PCs, and cloud servers, Packt
Publishing
LaMeres, B. J. (2019). Introduction to logic circuits & logic design with VHDL. Springer.
Nisan, N. and Schocken, S. (2008). The elements of computing systems: building a modern
computer from _first principles. MIT press.
Von Neumann, J. and Brucks, G. (1946). Preliminary discussion of the logical design of an
electronic computing instrument.
Patterson, D. A. and Hennessy, J. L. (2020). Computer Organization and Design MIPS
Edition: The Hardware/Software Interface. Morgan Kaufmann.
Shen, J. P. and Lipasti, M. H. (2013). Modern processor design: fundamentals of
superscalar processors. Waveland Press.
Stallings, W. (2019). Computer Organization and Architecture, 11th Edition. Pearson
Education.
Tanenbaum, A. S. (2016). Structured computer organization. Pearson Education.
Turing, A. M. (1995). Computing machinery and intelligence. Computers and Thought.
Turing, A. M. (1937). On computable numbers, with an application to the
Entscheidungsproblem, Proceedings of the London mathematical society.

119

S-ar putea să vă placă și