Salta al contenuto
Note per Studenti Un semplice microprocessore - datapath, ALU e register file

Un semplice microprocessore - datapath, ALU e register file

In questa pagina 4

Questa nota e la successiva (Un semplice microprocessore - istruzioni, ciclo singolo e cicli multipliIstruzioni a 16 bit: opcode (7 bit) + DR, SA, SB/OP (3 bit ciascuno) oppure formato di salto con offset a 6 bit (AD sinistro + AD destro, relativo al PC e con estensione di segno). Insieme di istruzioni load/store (solo LD e ST accedono ai dati): MOVA, INC, ADD, SUB, ..., LDI, ADI, LD, ST, BRZ, BRN, JMP. Nel computer a ciclo singolo (due memorie separate) il decoder combinatorio ricava MB, MD, RW, MW, PL, JB, BC dai bit 15, 14, 13, 9 dell'istruzione e $FS$ dai bit 12–9; il periodo di clock è la somma dei ritardi lungo il cammino peggiore (9,8 ns nell'esempio). Nel computer a cicli multipli (memoria unica) servono IR, registri interni R8–R15 e un decoder sequenziale: fetch (INF) + uno o più stati di esecuzione.Un semplice microprocessore - istruzioni, ciclo singolo e cicli multipli →) progettano un computer semplificato ma completamente funzionale, mettendo insieme blocchi già visti: registri, sommatori, multiplexer, decoder, memorie, macchine a stati. Per il quadro architetturale generale: Datapath e microarchitetturaMicroarchitettura come realizzazione dell'ISA; elementi del datapath (PC, memoria istruzioni e dati, banco dei registri, ALU, estensione del segno, multiplexer); percorso di un'istruzione aritmetica, di una load, di una store e di un salto; datapath a ciclo singolo e suo periodo di clock; datapath multiciclo.Datapath e microarchitettura →, Unità aritmetico-logica (ALU)Ruolo dell'ALU, ingressi, uscite e flag; ALU a 1 bit con AND, OR e sommatore selezionati da un multiplexer; estensione a 32 bit, sottrazione, confronto set-less-than e rilevazione dello zero e dell'overflow; tabella dei segnali di controllo; unità di moltiplicazione e virgola mobile.Unità aritmetico-logica (ALU) →, Struttura interna della CPU e registriComponenti interni della CPU (ALU, unità di controllo, banco dei registri, bus interno); registri visibili all'utente e registri di controllo e stato; flag e parola di stato (PSW) con bit di supervisore; quanti registri conviene avere; segmentazione della memoria.Struttura interna della CPU e registri →.

Un elaboratore è formato da:

  • un datapath, capace di eseguire le operazioni usate negli algoritmi (somme, operazioni logiche, ecc.);
  • una unità di controllo, che comanda il datapath in base al "programma";
  • una memoria, che contiene programma e dati.

Si parte dall'Instruction Set Architecture (ISA), l'interfaccia verso il programmatore (le operazioni di base di cui dispone). Il datapath è definito da un insieme di registri, una lista di microoperazioni e una interfaccia di controllo.

Struttura del datapath

Il datapath generico è costruito con elementi di base: registri, bus, multiplexer, decoder. Elementi:

  • register file (registri sorgente e destinazione);
  • ALU (circuito combinatorio aritmetico-logico) e shifter; insieme formano la unità funzionale (function unit);
  • multiplexer per scegliere gli operandi e il dato in uscita;
  • bit di segnalazione (status): V overflow, C carry, N negativo, Z zero.

Le operazioni richiedono un singolo ciclo di clock: per esempio R1←R2+R3R_1\leftarrow R_2+R_3 legge R2R_2 e R3R_3, calcola la somma e la scrive in R1R_1 al fronte di clock successivo.

Register file

Un datapath ha tipicamente più di quattro registri (32 o più sono comuni): si realizzano con un register file, memoria veloce che permette un accesso simultaneo a più locazioni. Contiene 2m⋅n2^m\cdot n bit, dove mm = numero di bit di indirizzo e nn = bit di ogni locazione. Qui m=3m=3 (88 registri R0…R7R_0\dots R_7) e n=16n=16. Ha:

  • due porte di lettura con indirizzi AAAA e BABA (uscite bus A e bus B);
  • una porta di scrittura con indirizzo DADA, dato D data e abilitazione RWRW (write).

Il dato sul bus A è anche l'indirizzo della memoria dati (address out), il bus B è il dato da scrivere in memoria (data out). Il secondo operando della unità funzionale passa per un MUX B: con MB=0MB=0 è il registro (bus B), con MB=1MB=1 una costante (constant in). All'uscita, un MUX D sceglie con MDMD tra il risultato FF della unità funzionale (MD=0MD=0) e il dato letto dalla memoria (data in, MD=1MD=1).

ALU

La ALU (Arithmetic Logic Unit, Unità aritmetico-logica (ALU)Ruolo dell'ALU, ingressi, uscite e flag; ALU a 1 bit con AND, OR e sommatore selezionati da un multiplexer; estensione a 32 bit, sottrazione, confronto set-less-than e rilevazione dello zero e dell'overflow; tabella dei segnali di controllo; unità di moltiplicazione e virgola mobile.Unità aritmetico-logica (ALU) →) è un circuito combinatorio che esegue un insieme di operazioni aritmetiche e logiche di base, scelte da linee di selezione (S2S_2 = selezione del modo, S1S0S_1S_0 = operazione, più CinC_{in}). Si progetta dividendola in parte aritmetica e parte logica, poi collegate da un MUX 2-to-1 comandato da S2S_2 (S2=0S_2=0 aritmetica, S2=1S_2=1 logica).

Circuito aritmetico. Un sommatore (nn full adder in cascata, Sommatori binari - half adder, full adder e ripple carryHalf adder (2 ingressi): $S=X\oplus Y$, $C=XY$. Full adder (3 ingressi, con riporto in ingresso $Z$): $S=X\oplus Y\oplus Z$, $C=XY+XZ+YZ=G+PZ$ con $P=X\oplus Y$, $G=XY$; si realizza con due half adder e una OR. Il ripple carry adder a $n$ bit concatena $n$ full adder: il riporto "ondeggia" dal LSB al MSB, quindi il ritardo cresce linearmente con $n$. È un circuito iterativo (gerarchico e regolare). Il moltiplicatore a 2 bit usa 4 AND e 2 half adder.Sommatori binari - half adder, full adder e ripple carry →) con una logica di ingresso su BB che produce YY e con riporto in ingresso CinC_{in}: G=A+Y+CinG=A+Y+C_{in}.

S1S_1 S0S_0 YY Cin=0C_{in}=0 Cin=1C_{in}=1
0 0 tutti 0 G=AG=A (trasferimento) G=A+1G=A+1 (incremento)
0 1 BB G=A+BG=A+B (somma) G=A+B+1G=A+B+1
1 0 B‾\overline B G=A+B‾G=A+\overline B G=A+B‾+1G=A+\overline B+1 (sottrazione)
1 1 tutti 1 G=A−1G=A-1 (decremento) G=AG=A (trasferimento)

Si ricordi che "tutti 1" è −1-1 in complemento a 2, quindi A+(−1)=A−1A+(-1)=A-1, e che A+B‾+1=A−BA+\overline B+1=A-B (Numeri con segno, complemento a 2, sottrazione e overflowSottrazione senza segno: se $M\ge N$ nessun prestito in uscita, altrimenti il risultato $M-N+2^n$ è scorretto. Complemento a 1: $2^n-1-N$ (inversione bit a bit); complemento a 2: $2^n-N=$ complemento a 1 $+1$. Numeri con segno: segno e modulo (due zeri, intervallo simmetrico) oppure complemento a 2 (un solo zero, da $-2^{n-1}$ a $2^{n-1}-1$, MSB di peso $-2^{n-1}$). In complemento a 2 somma e sottrazione sono la stessa addizione: $A-B=A+\overline B+1$, riporto in uscita scartato. Overflow: senza segno $\Leftrightarrow C_{out}=1$ nella somma; con segno $\Leftrightarrow C_{in,MSB}\ne C_{out,MSB}$ (due operandi dello stesso segno con risultato di segno opposto).Numeri con segno, complemento a 2, sottrazione e overflow →). Perché sono possibili solo queste quattro operazioni aritmetiche con due linee: YY vale 00, BB, B‾\overline B o 1…11\dots1 ed è l'unico ingresso che cambia.

La logica di ingresso può essere un multiplexer, ma conviene una sintesi dedicata. Dalla tabella di verità (YiY_i in funzione di S1,S0,BiS_1,S_0,B_i) con la mappa di Karnaugh: Yi=Bi S0+Bi‾ S1.Y_i=B_i\,S_0+\overline{B_i}\,S_1 . Controllo: S1S0=00⇒Yi=0S_1S_0=00\Rightarrow Y_i=0; 01⇒Yi=Bi01\Rightarrow Y_i=B_i; 10⇒Yi=Bi‾10\Rightarrow Y_i=\overline{B_i}; 11⇒Bi+Bi‾=111\Rightarrow B_i+\overline{B_i}=1 ✓.

Circuito logico. Per ogni bit un MUX 4-to-1, comandato da un codice a 2 bit, sceglie tra le porte AND, OR, XOR, NOT:

codice 00 01 10 11
GiG_i Ai∧BiA_i\wedge B_i Ai∨BiA_i\vee B_i Ai⊕BiA_i\oplus B_i Ai‾\overline{A_i}

Singolo stadio della ALU = stadio aritmetico + stadio logico + MUX 2-to-1 di uscita.

Funzionalità complessiva (le colonne sono S2 S1 S0 CinS_2\,S_1\,S_0\,C_{in}):

S2S_2 S1S_1 S0S_0 CinC_{in} operazione funzione
0 0 0 0 G=AG=A trasferisci AA
0 0 0 1 G=A+1G=A+1 incrementa AA
0 0 1 0 G=A+BG=A+B somma
0 0 1 1 G=A+B+1G=A+B+1 somma con riporto 1
0 1 0 0 G=A+B‾G=A+\overline B AA più complemento a 1 di BB
0 1 0 1 G=A+B‾+1G=A+\overline B+1 sottrazione
0 1 1 0 G=A−1G=A-1 decremento
0 1 1 1 G=AG=A trasferisci AA
1 X 0 0 G=A∧BG=A\wedge B AND
1 X 0 1 G=A∨BG=A\vee B OR
1 X 1 0 G=A⊕BG=A\oplus B XOR
1 X 1 1 G=A‾G=\overline A NOT (complemento a 1)

Per la parte logica (S2=1S_2=1) bastano due bit di codice (00 AND, 01 OR, 10 XOR, 11 NOT) e la colonna S1S_1 è indifferente (X), come nella tabella del corso.

Bit di stato. Dal risultato della unità funzionale: NN = bit di segno (MSB del risultato); Z=1Z=1 se tutti i bit del risultato sono 0 (NOR di tutti i bit); CC = riporto in uscita dal sommatore; VV = overflow = riporto entrante nel bit di segno XOR riporto uscente (Numeri con segno, complemento a 2, sottrazione e overflowSottrazione senza segno: se $M\ge N$ nessun prestito in uscita, altrimenti il risultato $M-N+2^n$ è scorretto. Complemento a 1: $2^n-1-N$ (inversione bit a bit); complemento a 2: $2^n-N=$ complemento a 1 $+1$. Numeri con segno: segno e modulo (due zeri, intervallo simmetrico) oppure complemento a 2 (un solo zero, da $-2^{n-1}$ a $2^{n-1}-1$, MSB di peso $-2^{n-1}$). In complemento a 2 somma e sottrazione sono la stessa addizione: $A-B=A+\overline B+1$, riporto in uscita scartato. Overflow: senza segno $\Leftrightarrow C_{out}=1$ nella somma; con segno $\Leftrightarrow C_{in,MSB}\ne C_{out,MSB}$ (due operandi dello stesso segno con risultato di segno opposto).Numeri con segno, complemento a 2, sottrazione e overflow →). Esempio a 8 bit: 70+8070+80 dà G=10010110G=10010110 (150, letto come −106-106) con V=1V=1, C=0C=0, N=1N=1, Z=0Z=0; 255+1255+1 dà G=0G=0 con C=1C=1, Z=1Z=1, V=0V=0, N=0N=0.

Shifter

Di solito lo scorrimento è eseguito da un blocco separato dalla ALU (ma può essere integrato). Shifter a 4 bit con multiplexer: per ogni uscita HiH_i un MUX 3-to-1 con S=0S=0 nessuno shift (passa BiB_i), S=1S=1 shift a destra (passa Bi+1B_{i+1}, con ingresso IRI_R per il bit entrante), S=2S=2 shift a sinistra (passa Bi−1B_{i-1}, ingresso ILI_L). Serial output L e R per i bit uscenti.

Barrel shifter a 4 bit: uno shifter con rotazione (i bit che escono da una parte rientrano dall'altra). Ogni uscita è un MUX 4-to-1 le cui ingressi sono i 4 bit dell'operando in ordine ruotato; la selezione S1S0S_1S_0 determina l'ampiezza della rotazione:

S1S0S_1S_0 Y3Y2Y1Y0Y_3Y_2Y_1Y_0 operazione
00 D3D2D1D0D_3D_2D_1D_0 nessuna rotazione
01 D2D1D0D3D_2D_1D_0D_3 rotazione di 1 posizione
10 D1D0D3D2D_1D_0D_3D_2 rotazione di 2 posizioni
11 D0D3D2D1D_0D_3D_2D_1 rotazione di 3 posizioni

Pregio: lo spostamento di qualsiasi numero di posizioni in un solo ciclo.

Unità funzionale e codici delle microoperazioni

L'unità funzionale = ALU + shifter, con un MUX F che sceglie il risultato (MFMF: 0 ALU, 1 shifter). Le microoperazioni possibili sono 15, quindi bastano codici FS a 4 bit invece di far pilotare tutti i 7 segnali di controllo (MFMF, G3…G0G_3\dots G_0, H1H0H_1H_0) alla unità di controllo: si aggiunge una piccola rete combinatoria che ricava i 7 segnali dal codice FSFS.

FS operazione FS operazione
0000 F=AF=A 1000 F=A∧BF=A\wedge B
0001 F=A+1F=A+1 1001 F=A∨BF=A\vee B
0010 F=A+BF=A+B 1010 F=A⊕BF=A\oplus B
0011 F=A+B+1F=A+B+1 1011 F=A‾F=\overline A
0100 F=A+B‾F=A+\overline B 1100 F=BF=B
0101 F=A+B‾+1F=A+\overline B+1 1101 F=sr BF=sr\,B
0110 F=A−1F=A-1 1110 F=sl BF=sl\,B
0111 F=AF=A

(FS=0111FS=0111 ripete il trasferimento di AA con GG diverso; FS=1111FS=1111 non è usato.)

Control word del datapath

La control word raccoglie tutti i segnali di controllo del datapath: 16 bit.

campo DA AA BA MB FS MD RW
bit 3 3 3 1 4 1 1
significato registro destinazione registro sorgente A registro sorgente B 0: registro, 1: costante funzione 0: funzione, 1: data in 0: niente, 1: scrive

Codici dei registri: R0…R7=000…111R_0\dots R_7=000\dots111.

Esempi di microoperazioni (notazione simbolica e codifica, X = indifferente):

microoperazione DA AA BA MB FS MD RW
R1←R2−R3R_1\leftarrow R_2-R_3 001 010 011 0 0101 0 1
R4←sl R6R_4\leftarrow sl\,R_6 100 XXX 110 0 1110 0 1
R7←R7+1R_7\leftarrow R_7+1 111 111 XXX X 0001 0 1
R1←R0+2R_1\leftarrow R_0+2 001 000 XXX 1 0010 0 1
Data out ←R3\leftarrow R_3 XXX XXX 011 0 XXXX X 0
R4←R_4\leftarrow Data in 100 XXX XXX X XXXX 1 1
R5←0R_5\leftarrow0 (R0⊕R0R_0\oplus R_0) 101 000 000 0 1010 0 1

La prima, scritta su 16 bit, è 0010100110010101. Nell'ultima si ottiene lo 00 con uno XOR di un registro con se stesso (X⊕X=0X\oplus X=0). Una sequenza di microoperazioni si simula applicando una control word per ciclo: a ogni fronte il register file memorizza il risultato della microoperazione con RW=1RW=1.

VHDL: una ALU behavioral

vhdl
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity alu8 is
  port ( A, B : in  std_logic_vector(7 downto 0);
         FS   : in  std_logic_vector(3 downto 0);
         F    : out std_logic_vector(7 downto 0);
         Z    : out std_logic );
end alu8;

architecture beh of alu8 is
  signal r : std_logic_vector(7 downto 0);
begin
  process (A, B, FS)
    variable ua, ub : unsigned(7 downto 0);
  begin
    ua := unsigned(A);  ub := unsigned(B);
    case FS is
      when "0000" => r <= A;
      when "0001" => r <= std_logic_vector(ua + 1);
      when "0010" => r <= std_logic_vector(ua + ub);
      when "0011" => r <= std_logic_vector(ua + ub + 1);
      when "0100" => r <= std_logic_vector(ua + not ub);
      when "0101" => r <= std_logic_vector(ua + not ub + 1);
      when "0110" => r <= std_logic_vector(ua - 1);
      when "0111" => r <= A;
      when "1000" => r <= A and B;
      when "1001" => r <= A or B;
      when "1010" => r <= A xor B;
      when "1011" => r <= not A;
      when "1100" => r <= B;
      when "1101" => r <= '0' & B(7 downto 1);        -- shift a destra
      when "1110" => r <= B(6 downto 0) & '0';        -- shift a sinistra
      when others => r <= (others => '0');
    end case;
  end process;
  F <= r;
  Z <= '1' when r = "00000000" else '0';
end beh;

Il case copre tutti i valori (others): la ALU è puramente combinatoria (VHDL - istruzioni concorrenti, process e testbenchLe istruzioni concorrenti VHDL sono l'assegnazione di segnale, when-else (logica prioritaria, condizioni valutate in ordine) e with-select (logica parallela: tutti i casi coperti da una sola scelta, others obbligatorio). Un process è un'istruzione concorrente il cui corpo è sequenziale (if, case, loop); parte quando cambia un segnale della sensitivity list (per la logica combinatoria: tutti gli ingressi); i segnali si aggiornano alla sospensione e vince l'ultima assegnazione. Un if senza else (o un caso non coperto) crea memoria non voluta. Il testbench è codice di simulazione con entity vuota, DUT istanziato e un process di stimoli con wait.VHDL - istruzioni concorrenti, process e testbench →).

Errori comuni

  • Dimenticare che sottrarre significa A+B‾+1A+\overline B+1 (il +1+1 è il CinC_{in}).
  • Scambiare bus A e bus B: il bus A è anche l'indirizzo di memoria, il bus B il dato da scrivere.
  • Confondere shift (perde bit) e rotazione (barrel shifter).
  • Credere che la ALU sia sequenziale: è combinatoria, il risultato arriva al registro al fronte di clock.
  • Scrivere nella control word i codici dei registri con la numerazione sbagliata (R1=001R_1=001, non R0R_0).

Versione ripasso

Teoria collegata