cosa succede se la CU genera segnali errati? dobbiamo individuare:
- quale combinazione di segnali venga generate
- quali istruzioni vengano influenzate dalle nuove combinazioni, e cosa facciano e successivamente possiamo scrivere un programma che ci mostri se la CPU è malfunzionante o meno.
segnali CU
RegWrite ← Branch
se ho il dubbio che il segnale RegWrite
sia determinato dal segnale Branch
(ossia abbia lo stesso valore)
tip
si assumano i delta come:
MemToReg
= 1 solo per lalw
,RegDest
= 1 solo per le istruzioni di tipo R (altrimenti zero).
- quali istruzioni sono affette?
- tutte le istruzioni che modificano un registro (tipo
r
elw
) lo lasceranno invece invariato - branch - oltre a saltare, modificherà uno dei registri:
rt
verrà sovrascritto (perchéRegDst
= 0)- il valore scritto sarà la differenza tra i due registri confrontati dalla ALU (assumiamo
MemToReg = 0
)
branch errato
- programma per mostrarlo
scriviamo un programma che lasci il valore 0 nel registro $s0
se la CPU è malfunzionante, e scriva 1 se funziona correttamente.
- ricordiamo che non possiamo caricare un valore in un registro perché
RegWrite = 0
basta una qualsiasi istruzione che generi un valore diverso da 0:
li $s0, 1
addi $s0, $zero, 1
oppure una beq
che calcoli la differenza tra due valori uguali ($s0
e se stesso), ma assumendo che inizialmente $s0 = 1
beq $s0, $s0, ...
visto che il risultato del confronto tra i due registri (sub della ALU verrà caricato erroneamente nel registro, $s0
varrà 0).
MemWrite ← not(RegWrite)
- istruzioni affette:
j
ebeq
saltano correttamente, ma scrivono in memoria
branch e jump errati
- codice:
ci conviene usare la beq
, perché memorizzerà il valore del registro $rt
all’indirizzo calcolato dalla ALU come differenza tra $rs
e $rt
.
move $s0, $zero // mettiamo 0 dentro $s0
sw $s0, 0 // scriviamo il valore di $s0 (0) all'indirizzo 0
li $s1, 1
beq $s1, $s1, on // *
on:
lw $s0, 0 // caricando il contenuto
* branch apparentemente inutile (compara due registri uguali e salta all’istruzione successiva), ma che serve a vedere se scrive all’indirizzo zero (la ALU fa sub tra due registri uguali, fa 0, e se la CPU è rotta va a scrivere $s1
(1) in 0, sovrascrivendo lo 0)