This is an old revision of the document!
În acest laborator vom continua dezvoltarea calculatorului nostru, SOC-1, și vom detalia unitatea de control, etapele de execuție a instrucțiunilor, instrucțiunile pe care le suportă calculatorul nostru și cum putem scrie cod pe care să îl execute.
Execuția instrucțiunilor este de regulă - mai ales în arhitecturile RISC - împărțită în 5 etape:
La fiecare front negativ de ceas, deci la finalul fiecărui ciclu, controller-ul vaverifica semnalul de reset, care va reseta orice instrucțiune se execută și va trece înapoi în stage 0 (IF).
În orice alt caz el va trece circular (deci de la WB vom trece înapoi în IF) la următorul stagiu de execuție a instrucțiunii curente:
IF → ID → EX → MEM → WB
De asemenea, din memoria ROM a controller-ului, la fiecare modificare a stagiului de execuție sau a operației curente, acesta va verifica dacă este cazul unei operații de jump (JZ - Jump Zero, JNZ - Jump Not Zero, JM - Jump Minus)
Acest lucru este posibil deoarece controller-ul folosește o memorie ROM pentru a decide ce semnale de control trebuie activate, în funcție de instrucțiunea curentă și stagiul de execuție. Fiecare instrucțiune are 8 biți, iar stagiul are 4 biți, deci ele sunt combinate într-o adresa de 12 biți sub formă IIIIIIII TTTT. De exemplu, pentru instrucțiunea ADD B (codul 80) aflată în stagiul 3, adresa calculată este 803. În acea poziție din ROM este stocat un cuvânt de control de 35 de biți, care indică exact ce semnale trebuie activate în acel moment – cum ar fi B_EN și ALU_LOAD pentru a realiza adunarea. Astfel, ROM-ul acționează că o “harta” pentru execuția fiecărei instrucțiuni, eliminând nevoia unui cod complicat și greu de întreținut, și permițând controller-ului să execute eficient și clar pașii necesari pentru orice instrucțiune, inclusiv verificarea și gestionarea condițiilor de jump.
Avem 39 de instrucțiuni, ce folosesc opcode-urile instrucțiunilor procesoarelor Intel 8080 (https://deramp.com/downloads/intel/8080%20Data%20Sheet.pdf)
Instrucțiunile pot fi împărțite în 4 categorii în funcție de modul în care adresează memoria în opcode: * Direct - Primește adresa de memorie pe care se operează în instrucțiune - ex. STA addr (Store la o anumită adresa) * Immediate - Primește o valoare constantă direct folosită în instrucțiune - ex. ORI byte (Aplica operatia de OR logic între registrul A și o valoare primită) * Register - Funcționează pe datele dintr-un registru - ex. DCR A - Decrementează valoare registrului A * Implied - Adresa/Registrul pe care se efectuează instrucțiunea este implicită și nu se modifică - ex. RAL (Shiftează la stânga valoarea din registrul A și o salvează înapoi tot în acesta)
Sistemul nostru - SOC-1 - ia 3 ciclii de ceas pentru aducerea instrucțiunii de executat din memorie, deci cea mai scurtă instrucțiune va dura 3 ciclii (NOP). Cele mai lungi instrucțiuni sunt cele care lucrează cu adrese din memoria ROM și ajung până la 9-10 ciclii de ceas (STA - 9 ciclii, CALL - 9 ciclii, LDA - 10 ciclii)
Instrucțiunile de jump durează 4 sau 8 ciclii de ceas în funcție de rezultatul comparației din controller. Dacă în controller condiția eșuează și jump-ul nu este executat, acesta durează 4 ciclii de ceas. În schimb, dacă acesta este executat, instrucțiunea de jump durează 8 ciclii.
După cum v-a fost zis la începutul anului, sistemul acesta de calcul este capabil să execute și cod. Deoarece SOC-1 funcționează pe o parte din ISA-ul (Instruction Set Architecture - pe scurt, cum sunt definite instrucțiunile) de la Intel 8080, putem scrie o secvență simplă de cod pentru acest procesor pe care să o executăm:
MVI A, 0 ; A = 0 MVI B, 12 ; B = 12 MVI C, 8 ; C = 8 REPEAT: ADD B ; A += B DCR C ; C-- JZ DONE ; if (C == 0) go to DONE JMP REPEAT ; else go to REPEAT DONE: HLT
IF → ID → EX → MEM → WB
Task 0: Analizati pe baza sheet-ului de instructiuni cu asistentul/asistenta de laborator secventa de mai sus pentru a determina ce se va intampla de-alungul executiei acesteia.
Task 1 (Branch Group Instructions): Observati cum este implementata instructiunea de JM (Jump Minus) si implementati similar si operatia de JP (Jump Positive)
Task 2 (Arithmetic Group Instructions): Implementati instrucțiunile CMP B si CMP C, care compara valoarea lui A cu a lui B, respectiv C si modifica flag-urile pe baza acestor operatii.
Task 2.1: Cum va usureaza munca instrucțiunile implementate la task 2 fata de utilizarea unor operatii normale de SUB
Task 3: Implementare XCHG A B: Interschimba valorile din registre A si B.
Task 4 (I/O Group Instructions): Implementati instructiunea de I/O IN data, care se va primi prin intermediul switch-urilor o valoare pe 4 biti pe care o veti stoca in sectiunea LOW a registrului A.
Task 5 (BONUS): Implementarea POPCNT A. Numara numarul de biti setati pe 1 din registrul A.
Pentru mai multe detalii cu privire la instructiunile de mai sus, va recomandam sa cititi din datasheet-ul de mai jos paginile 34-45