Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pt fiecare instructiune contorul de program se incrementeaza pe 4 (o instructiune este pe 4 octeti) si memoria se adreseaza pe octet
- toate fazele de executie pentru o instructiune (IF, ID, EX, MEM, WB) se petrec pe o singura perioada de ceas. (pt mips ciclu unic)
- instr de tip R :
- op $rd, $rs, $rt
- RF[rd] <- RF[rs] op RF[rt]
- (31-26) opcode (25-21) rs (20-16) rt (15-11) rd (10-6) sa (5-0) funct
- opcode este tot timpul 0 pentru R.
- exemple la funct :
- 100000 = add
- 100010 = sub
- 100101 = or
- 100100 = and
- (coduri standard, petterson)
- resurse necesare pt faze de executie :
- IF -> PC, Memoria de instructiuni, sumator.
- ID -> Bloc de registri, Unitatea de control
- EX -> ALU
- MEM -> No op (nu se face nicio operatie pt instructiunile de tip R)
- WB -> Bloc de registri
- instr de tip I :
- ori $rt, $rs, imm
- RF[rt] <- RF[rs] + S_Ext(imm)
- (31-26) opcode (25-21) rs (21-16) rt (15-0) imm
- resurse necesare pt faze de executie :
- IF -> PC, Memoria de instructiuni, sumator
- ID -> Bloc de registri, Unitatea de control, unitate de extensie
- EX -> ALU
- MEM -> No op
- WB -> Bloc de registri
- lw $rt, offset($rs)
- opcode 100011
- incarca un cuvant de 32 de biti din memoria de date intr-un registru.
- apare in plus blocul de memorie.
- RF[rt] <- M[RF[rs] + S_Ext(imm)]
- sw $rt, offset($rs)
- opcode 101001
- M[RF[rs] + S_Ext(imm)] <- RF[rt]
- pe partea de scriere a rezultatului (nu avem nevoie) (daca ne gandim la sw am spune ca rezultatul este scrierea in memorie) dar ca terminologie la mips se considera accesul din baza de memorie ca fiind scrierea efectiva.
- beq $rt, $rs, imm
- opcode 000100
- compara doi registri, apoi face salt conditionat la PC.
- if(RF[rs] == RF[rt]) then PC <- PC + 4 + S_Ext(imm) << 2 (inmultirea cu 4 este datorata reprezentarii instructiunilor pe 4 octeti)
- resurse necesare : sumator aditional pentru al doilea plus din instructiune + S_Ext(imm) si un circuit de deplasare, un mux.
- MEM, WB -> no operation
- j target_addr
- salt neconditionat la o adresa psuedoabsoluta (in zona de 256MB unde e programul)
- (31-26) J (25-0) target_addr
- PC <- PC + 4 [31:28] & target_addr & 00
- ID, MEM, WB -> no operation
- EX -> circuit de deplasare
- lw si sw trebuie sa furnizeze memoriei pe o perioada de ceas adresa efectiva a datelor pe care le doreste (fie unde vrea sa scrie fie de unde vrea sa citesca) dar pe aceiasi perioada citim din memorie combinational instructiunea (apare conflict ca nu poti pe durata unei perioada de ceas sa furnizezi 2 valori difertie pe campul de adresa de la memorie) din cauza asta avem 1 memorie separata de instructiuni si una de date.
- blocul de registri (ra1 si ra2) (read data 1 -> rs) (read data 2 -> rt)
- in partea de scriere avem camp de adrese (in ce registru vrem sa scriem)
- si datele pe care vrem sa le scriem in registrul respectiv
- pentru ca nu vrem sa scriem in toate instructiunile (avem un semnal de validare a scrierii) (RegWrite)
- RegWrite = 0 (nu se fac scrieri)
- Memorie de date e o memorie RAM, citirea se face pe iesirea read data (ce e pe campul write data se scrie in campul de adresa, cu conditia ca MemWrite = 1)
- pentru toate elementele de stocare (PC, Bloc de registri, memoria de date) -> scrierea se face pe acelasi front de ceas.
- etapa a citirii a instructiunii din memorie (IF)
- pc, sumator si rom
- avem la iesirea rom, codul masina al instructiunii. (partea e comuna la toate)
- rezultatul de ex: instructiune de tip r (RF[rs] op RF[rt]) se va gasi la iesirea ALU)
- trebuie dus inapoi in blocul de registre pe campul de scriere (writeData)
- rt poate fi citit fie la scriere fie la citire (I,R)
- intrarea a doua a alu este unitatea de extensie (cu semn sau cu zero)
- rezultatul RF[rs] op Ext(imm) se va furniza la iesirea AluRes
- pt LOADWORD STOREWORD
- in ambele rtl-uri la lw si sw avem suma intre registrul rs si ext_imm deci intrarea b de la alu este s_ext(imm) si rf[rs] este intrarea a de la alu. rezultatul din alu va fi suma dintre cei doi operanzi. iesirea va fi adresa efectiva (iesirea alures e legata pe campul de adrese la memoria ram)
- pt store word luam read data 2 si il legam la write data (aceste date trebuie sa ajunga pe intrarea memoriei ca sa scriem acolo acele date)
- Multiplexorul cu register destination (regDst)
- Multiplexorul cu ALUSrc (sursa b de la alu)
- Multiplexorul de scriere inapoi (writeback) cu (memtoreg)
- beq
- comparatia intre cei doi registri o va face alu
- rezultatul comparatiei va fi in steguletul de 0 (zero)
- imediatul extins e legat la unitarea de deplasare care intra in sumator cu PC+4 -> se rezolva rtl
- se pune un mux pt ca pe then si else trebuie legate lucruri diferite. la semnalul de selectie spunem pcsrc de la sursa de selectie a lui pc.
- jump
- cei 28 de biti sunt concatenati cu primii 4 biti din pc (31-28)
- mai trebuie un mux nou cu semnalul jump (branch si pc-ul nou construit)
- analiza semnalelor de control :
- regWrite, memWrite (activare a scrieri) (punem 1 -> permitem scriere sincrona)
- regDst (ne selecteaza ce vrem sa trimitem pe adresa de scriere din blocul de registri (rt sau rd))
- punem 1 => merge rd altfel trece rt (dar nu conteaza daca le punem invers)
- extOp (1 -> semn, 0 -> zero)
- ALUSrc (sursa lui alu, pe 0 trece read data 2 si daca e 1 alusrc trece extins (greu de gasit o regula)
- MemToReg (alege daca sa treaca memorie spre registru sau alu) (1 din memorie, 0 din alu)
- PCSrc, Jump (daca punem 0 trece PC+4)
- pcsrc depinde de 0 (doar in scenariul in care exista beq) (se pune un semnal nou de branch care e pus pe 1 stric cand avem beq) (zero e pus pe 1 cand rezultatul in alu este nul) => punem un si intre branch si zero.
- ALUCTRL (se pot propune valori adhoc)
- 000 adunare
- 100 scadere
- 001 si
- 010 sau
- flux de date pt instrucitune de adunare de tip r:
- pornim cu iesirea de la pc (branch si jump sunt 0 sa se execute pc + 4)
- pc-ul merge spre adresa de la memoria rom, se selecteaza combinationala cei 32 biti din instr.
- regdst = 1 (avem registrul d, e instr de tip r)
- alusrc = 0 (nu avem imediat extins)
- pt adunare (aluctrl = 000)
- rezultatul trebuie sa ajunga inapoi la blocul de reg (in memtoreg punem 0) (nu in memorie)
- vrem sa scriem, deci regwrite = 1 (mereu se scrie in blocul de reg)
- memwrite mereu 0 pt r (nu scriem in memorie)
- semnalul de extensie nu conteaza (iesirea din unitatea de extensie nu produce efecte)
- deci : regdst este 1 pt r (add, sub, or, and)
- regwrite este 1 pt majoritatea instr (fara jump, beq si sw) (la sw nu se scrie in blocul de registrii)
- alusrc este 1 pt instr cu imediat extins (i) (este 0 pt cele de tip r si x pt jump)
- extop este 1 pt lw,sw si alte instr cu extindere cu semn si 0 pt ori,andi etc (cele logice) si x pt tip r si jump.
- memwrite este 1 doar in sw
- memtoreg este 1 doar in lw
- branch este 1 doar in beq
- jump este 1 doar in j
- unitatea de control mips ciclu unic :
- este combinationala (ea codul de operatie si seteaza valorile corecte pt semnalele de control)
- are o structura ierarhica main control (master) si alu control (slave) se introduce un semnal intermediar aluop (din cauza codificarii mai speciale la instructiunile de tip r)
- opcode = 0 plus funct
- maincontrol da comenzi lui aluctrl pt ca acesta sa seteze comanda efectiva.
- ALUOP ESTE :
- tip r -> 10 (foloseste funct)
- ori -> 11 (comanda sau)
- addi / lw / sw -> 00 (comanda +)
- beq -> 01 (comanda -)
- pt j -> xx
- pt instr de tip r aluop are mereu 10 si dupa in functie de funct se genereaza un aluctrl
- pot fi unele identice, add de tip r are acelasi aluctrl ca si addi sau lw/sw
- deci I(5-0) se duce in alucontrol si semnalul aluop din memoria master (main)
- implementarea alu unitatii de comanda se face cu PLA (programmable logic array)
- pt fiecare instructiune principala adaugam cate o poarta si care ne va detecta aparitia strict ale acelei instructiuni
- la tip r de ex codul de operatie este 0 (sunt negate toate)
- opcode-uri :
- r (000000)
- ori (001101)
- addi (001000)
- lw (100011)
- sw (101011)
- beq (000100)
- j (000010)
- la jump sunt negate toate in afara de a 5-a (pe acel 1 nu il negam)
- la un moment dat o singura poarta va fi 1 pe iesire (pt anumite instructiuni)
- acel 1 de la anumite porti trebuie legat la semnalele de control.
- (nu e necesar un mux) regwrite de ex este activat daca cel putin una din cele 4 porti de iesire (r, addi ,ori, lw) este activata pe 1 (deci avem nevoie de o poarta sau)
- calea critica = load word (cea mai defavorabila instructiune)
- (suntem obligati sa punem o frecventa unica, defavorabila care acopera cea mai lunga instructiune)
- (timpul inactiv care apare, de ex la instructiunea j, se elimina in pipeline / multiciclu)
- PIPELINE
- PE IF
- se citeste instructiunea de executat
- adresa pc este incrementata cu 4
- se scrie in pc adresa pc incrementata sau adresa de ramificare
- PE ID
- se citesc operanzii din blocul de registri (in jumatatea a doua a perioadei de ceas)
- campul imediat se extinde cu semn sau cu zero
- se transmit adresele care pot fi folosite ca adrese de scriere in blocul de registri
- pc incrementat se transmite la etajul urmator.
- PE EX
- se calculeaza adresa efectiva pentru instructiunile care acceseaza memoria.
- se transmite data de stocat pentru instructiunea sw
- operatii pe alu
- instructiuni de ramificare, test de egalitate in alu
- adresa de ramificare se calculeaza in sumatorul suplimentar
- se transmite mai departe adresa potentiala de scriere in blocul de registri.
- PE MEM
- se citeste din memoria de date
- se scrie in memoria de date
- se transmite mai departe adresa de scriere in blocul de registri
- se transmit rezultatele operatiilor ALU / adresa de ramificare
- PE WB
- operatii tip alu pt instr de tip R si I (rezultatul obtinut in alu se scrie inapoi in blocul de registri)
- deci scriere in blocul de registri, pe frontul descrescator al ciclului de ceas
- IN IF SI ID SUNT IDENTICE PT TOATE, dar in restul sunt particularizate.
- ordinea etajelor practic if id ex mem wb (cand avem o instr care trece prin pipeline, ea va fi la un moment dat intr-un singur etaj)
- ar trebui sa transmitem impreuna cu datele instructiunii si valorile pt semnalele de control.
- de ex regwrite trebuie plimbat prin etajele de pipeline.
- hazard structural (pe aceeasi perioada de ceas, instructiuni diferte vor sa foloseasca aceeasi resursa)
- (nu e nicio problema in cazul mips pentru ca folosim memorii diferite de date si de instructiuni)
- (dar daca am folosi o singura memorie, ar trebui sa asteptam o perioada de ceas)
- solutia uzuala e sa folosim memorii independente pt instructiuni si date
- chiar daca exista o memorie ram principala, mai sunt niste memorii mai micute foarte rapide (cele cache)
- hazard structural (acces simultan la blocul de registri)
- add $1, .... -> se scrie in blocul de reg in instr 5
- inst1
- inst2
- add $2, $1 -> se citeste din blocul de reg in instr2
- solutie? intarziere suplimentara sau un artificiu (sa scriem in blocul de registri pe front descrescator)
- asta inseamna ca in perioada 5 la mijlocul perioadei se executa scrierea, si pe a doua se citeste combinational.
- dar acest artificiu ne rezolva cel mult o intarziere suplimentare
- HAZARD DE DATE (TEHNICA DE FORWARDING)
- prima instructiune calculeaza $2 iar restul il preluceaza
- sub $2, $1, $3
- cine produce noua valoare in sub (in ALU)
- pe perioada 3 de ceas de fapt -20 apare in calea de date la iesirea ALU
- cand va fi necesar aceasta valoare sa fie folosita de instr imediat urmatoare?
- pe periaoda 4 la instr urmatoare
- RAW HAZARD (operatie de citire dupa operatie de scriere)
- ca sa nu inseram instructiuni noop (putem face forwarding)
- deci la iesirea alu avem de fapt valoarea actualizata si o ducem in intrarea alu a urmatoarei instructiuni -> avem legaturi noi
- interpunem niste multiplexoare.
- legam iesirile coresp de la alu din registrii intermediari de duap ex si dupa mem.
- 2 mux-uri
- cei 32 biti asociati cu iesirea alu se leaga pe cele 2 mux-uri (pt ca putem pune pe fiecare intrare alu)
- in mux vine iesirea alu dupa primul registrul intermediar si iesirea din wb dupa al doilea registru intermediar si de asemenea ramane intrarea veche (rd1,rd2)
- apare un forwarding unit (cum spunem ca este hazard)
- ne uitam la registru destinatie si daca la instructiunea urmatoare unul din cei 2 registrii sursa este registrul destinatie anterior.
- in unitatea de forwarding se pot citi cele 3 adrese de registri (rs rt si rd) si trebuie sa le compare
- ca sa folosim rezultatul corect, in forwarding unit trebuie implementata o logica combinationala de control.
- MEM HAZARD (intre instructiuni consecutive, distanta 1)
- WB HAZARD(intre instructiuni de distanta 2)
- pt MEM HAZARD
- daca instr care este in etajul mem scrie in blocul de registrii
- if(ex/mem.regwrite and ex/mem.register !=0)
- in cazul in care se scrie in registrul 0 ca oricum nu ne intereseaza scrierea ca e protejat la scriere)
- and ex/mem.register rd == id/ex.register rs
- forwardA = 10
- aceiasi logica si pt multiplexorul 2 numai cca are id/ex.register rt
- aceiasi logica si pt etajul wb
- hazardul mem daca exista, are prioritate la rezolvare.
- aceiasi logica ca la hazard mem la wb numai ca avem o linie in plus
- ex/mem.register rd != id/ex register rs (nu avem hazard mem)
- mem/wb .register rd = id/ex register rs (avem wb)
- exista si hazarduri care nu se pot rezolva decat prin asteptare
- daca vrem sa incarcam intr-un registru o valoarea din memorie si pe urma vrem s-o folosim in instr urmatoare.
- suntem obligati sa introducem o intarziere
- in hardware e o instructiune no operation
- ramanere intr-un etaj (pc constant intre 2 perioade de ceas sa ramana in if aceiasi instructiune)
- unitate de detectare de hazard.
- verifica daca in etajul ex este lw.
- memread e 1 doar cand lw este in acel etaj
- daca este 1 atunci se compara (id/ex rt cu if/id rs sau id/ex rt cu id/id rt) -> stall daca sunt egali.
- noop in hardware -> se seteaza pe 0 toate semnalele de control care ar activa scriere (regwrite, memwrite, branch, jump) pt ca nici nu scriem in memorie/blocul de reg si nu executa niciun salt.
- in mod standard in mips noop este sll $0 $0 $0 (opcode si func sunt toate 0) (avem 32 de biti de 0)
- HAZARD DE CONTROL
- (instr de salt)
- decizia de salt are loc in etajul mem (se da comanda la mux daca sarim sau nu)
- instr urmatoare de dupa beq sunt transformate in noop pt ca ele au intrat deja in pipeline
- (nu ar trebui sa fie executate conform fluxului de program)
- o solutie ar fi sa reducem nr de instructiuni incerte dupa un salt conditionat.
- transformam urmatoare instructiune in noop sau (semnal de control care permite sa anulam continutul registrului if/id) (in felul acesta daca avem o instr beq, unitatea de hazard detection o sa dea o comanda de anulare a registrului if/id (noop)
- flush (anulare)
- stall (asteptare)
- SIMULARE COLOCVIU
- SW $6, -229($0)
- ce valoare (in baza 10) va avea iesirea ALU ?
- -229 (suma dintre -229 si 0)
- sub $5 $5 $6
- 000_101_110_101_101
- paint style :
- pas 2.a - conexiuni noi :
- de la campul RT I(9-7) legat la write address de la rf
- iesirea ext imm se leaga la intrarea b din alu
- iesirea sumatorului pc + 1 se leaga la intrarea 0 de la mux jump
- iesirea alu result se leaga la write data de la rf
- muxul alusrc se elimina deoarece in alu pe intrarea b intra doar imm extins (e doar instructiunea addi)
- sumatorul pentru branch addres nu mai este necesar (nu exista beq in varianta simplificata)
- PC <- PC + I(15-13) | I(12-0) ; jump = 1 , regwrite = 0, restul x
- addi : RF[rt] <- RF[rs] + s_ext(imm); regwrite = 1, aluop = 00 ; extop = 1; jump = 0
- se considera descrierea in vhdl a unui circuit format din 2 registre de 1 bit (flip flop d, sincron front crescator cu semnal de validare/activare a scrierii) iesirile din registre sunt legate la intrarile unui mux 2:1, iesirea muxului este legata la intrarile altor 2 registre. ambele registre functioneaza la acelasi semnal de ceas (clk) si sunt legate la acelasi semnal de activare a scrierii care vine la un monoimpuls (semnalul en). Semnalul de selectie pt mux este sw(0). Semnalele clk, en si sw(0) se presupun declarate.
- -- zona semnale (2 registre de 1 bit)
- signal q1,q2 : std_logic;
- signal muxo : std_logic;
- process(clk)
- begin
- if(rising_edge(clk) then
- if en = '1' then
- q1 <= muxo;
- q2 <= muxo;
- end if;
- end if;
- end process;
- process (sw(0))
- begin
- if sw(0) = '0' then
- muxo <= q1;
- else
- muxo <= q2;
- end process;
Add Comment
Please, Sign In to add comment