A volte, l’informazione necessaria per una fase di esecuzione di un’istruzione è già presente nella pipeline prima del Write Back. In questi casi si usa il forwarding (detto anche propagazione o bypassing), cioè l’inserimento di scorciatoie nel datapath, ovvero dei cavi che danno il dato all’unità funzionale che ne ha bisogno senza aspettare la fase di Write Back.

Esempio:

add s0, t0, t1   IF  ID  EX  MEM  [WB]
[stallo]             -   -   -    -     -
[stallo]                 -   -    -     -   -
sub t2, s0, t3               IF   [ID]  EX  MEM  WB

Al posto di risolvere così il data hazard, aspettando 2 colpi di clock, possiamo usare le unità di forwarding per portare il risultato di EX di add come uno dei due input di EX di sub, saltando ID per quel dato (visto che non è ancora stato scritto in memoria con il WB).

add s0, t0, t1   IF >| ID >| EX >| MEM >| WB >|
                                 |
                                 v
sub t2, s0, t3         IF >| ID >| EX  >| MEM>| WB >|

Non è sempre possibile risolvere un data hazard direttamente con il forwarding, ma a volte è necessario inserire uno stallo (detto anche attesa o bubble).

Esempio:

lw x1, 0(x2)   IF >| ID >| EX >| MEM>| WB >|
                                     |
[stallo]             -     -     -   v -      -    
sub x4, x1, x5             IF >| ID >| EX  >| MEM>| WB >|

CPU con unitĂ  di forwarding per data hazard

(senza stalli) (niente forwarding tra MEM e MEM)