Escolar Documentos
Profissional Documentos
Cultura Documentos
Soluções
4.1
4.1.1 O valor dos sinais é o seguinte:
4.2 Reg2Loc para ld: Ao executar ld, não importa qual valor é passado para
“Read register 2”, porque o ALUSrc mux ignora a saída resultante “Read
data 2” e seleciona o valor imediato estendido de sinal.
MemToReg para sd e beq: Nem sd nem beq gravam um valor no
arquivo de registro. Não importa qual valor o mux MemToReg passa para
o arquivo de registro porque o arquivo de registro ignora esse valor.
4,3
4.3.1 25 + 10 = 35%. Somente Carregar e Armazenar usam a memória de dados.
4.3.2 100% Cada instrução deve ser buscada na memória de instruções antes de
poder ser executada.
4.3.3 28 + 25 + 10 + 11 + 2 = 76%. Apenas instruções do tipo R não usam o
extensor de sinal.
4.3.4 A extensão do sinal produz uma saída durante cada ciclo. Se sua saída não
for necessária, ela será simplesmente ignorada.
4.4
4.4.1 Apenas loads são quebradas. MemToReg é 1 ou “não me importo” para
todas as outras instruções.
4.4.2 I-type, loads, stores estão todas quebradas.
4.6
4.6.1 Não são necessários blocos lógicos adicionais.
4.6.2 Ramificação: false
MemRead: false (Veja nota de rodapé da solução para o problema 4.1.1.)
MemToReg: 0
ALUop: 10 (ou simplesmente dizer “adicionar” é suficiente para este
problema)
MemWrite:
false ALUsrc:
1
RegWrite: 1
4.7
4.7.1 Tipo R: 30 + 250 + 150 + 25 + 200 + 25 + 20 = 700ps
4.7.2 ld: 30 + 250 + 150 + 25 + 200 + 250 + 25 + 20 = 950 ps
4.7.3 sd: 30 + 250 + 150 + 200 + 25 + 250 = 905
4,7,4 beq: 30 + 250 + 150 + 25 + 200 + 5 + 25 + 20 = 705
4,7,5 Tipo I: 30 + 250 + 150 + 25 + 200 + 25 + 20 = 700ps 4,7,6
950ps 4,8
Usando os resultados do Problema 4.7, vemos que o tempo médio por instrução
é
0,52*700 + 0,25*950 + 0,11*905 + 0,12 * 705 = 785,6 ps
Em contraste, uma CPU de ciclo único com um clock “normal” exigiria um
tempo de ciclo de clock de 950.
Assim, o aumento de velocidade seria 925/787,6 = 1,174
4,9
4.9.1 Sem melhoria: 950; Com melhorias: 1250
4.9.2 O tempo de execução de um programa na CPU original é 950*n. O
tempo de execução na CPU aprimorada é 1250*(0,95)*n = 1187,5.
Assim, o “speedup” é 0,8. (Assim, esta CPU “melhorada” é realmente
mais lenta que a original).
4.9.3 Como a adição de uma instrução de multiplicação removerá 5% das
instruções, o tempo de ciclo pode crescer até 950/(0,95) = 1000. Assim,
o tempo da ALU pode aumentar em até 50 (de 200 para 250).
4.10
4.10.1 Os registros adicionais nos permitirão remover 12% das loads e
armazenamentos, ou (0,12)*(0,25 + 0,1) = 4,2% de todas as instruções.
Assim, o tempo para executar n instruções diminuirá de 950*n para
960*.958*n = 919,68*n. Isso corresponde a uma aceleração de
950/895,73 = 1,03.
4.10.2 O custo da CPU original é 4507; o custo da CPU melhorada é 4707. PC:
5
I-Mem: 1000
Arquivo de registro: 200
ALU: 100
D-Mem: 2000
Sign Extend: 1002
Controles: 10002
somadores: 30*24
muxes: 4*102
portas simples: 2
*1
Assim, para um aumento de 3% no desempenho, o custo da CPU aumenta em
cerca de 4,4%.
4.10.3 Do ponto de vista estritamente matemático não faz sentido adicionar
mais registradores porque a nova CPU custa mais por unidade de
desempenho. No entanto, esse cálculo simples não leva em conta a
utilidade do desempenho. Por exemplo, em um sistema em tempo real,
um desempenho de 3% pode fazer a diferença entre cumprir ou perder
prazos. Nesse caso, a melhoria valeria o custo adicional de 4,4%.
4.11
4.11.1 Não são necessários novos blocos funcionais.
4.11.2 Apenas a unidade de controle precisa ser modificada.
4.11.3 Não são necessários novos caminhos de dados.
4.11.4 Não são necessários novos sinais.
4.12
4.12.1 Não são necessários novos blocos funcionais.
4.12.2 O arquivo de registradores precisa ser modificado para que possa
escrever em dois registradores no mesmo ciclo. A ALU também
precisaria ser modificada para permitir que os dados de leitura 1 ou 2
fossem passados para escrever os dados 1.
4.12.3 A resposta depende da resposta dada em 4.12.2: qualquer entrada que
não tenha permissão para passar pela ALU acima deve agora ter um
caminho de dados para gravar dados 2.
4.12.4 Seria necessário haver um segundo fio de controle RegWrite.
4.12.5 Muitas soluções possíveis.
4.13
4.13.1 Precisamos de alguns muxes adicionais para conduzir os caminhos de dados
discutidos em 4.13.3.
4.13.2 Nenhum bloco funcional precisa ser modificado.
4.13.3 É necessário haver um caminho da saída da ALU para a porta de dados
de gravação da memória de dados. Também precisa haver um caminho
dos dados lidos 2 diretamente para a entrada de endereço da memória de
dados.
4.13.4 Esses novos caminhos de dados precisarão ser controlados por muxes.
Esses muxes exigirão fios de controle para o seletor.
4.13.5 Muitas soluções possíveis.
4.14 Nenhum: todas as instruções que usam sign extend também usam o
arquivo de registro, que é mais lento.
4.15
4.15.1 O novo tempo do ciclo de clock seria 750. A ALU e a Memória de
Dados agora funcionarão em paralelo, então removemos efetivamente o
mais rápido dos dois (a ALU com tempo de 200) do caminho crítico.
4.15.2 Mais devagar. A CPU original leva 950*n picossegundos para executar
n instruções. O mesmo programa terá aproximadamente 1,35*n
instruções quando compilado para a nova máquina. Assim, o tempo na
nova máquina será 750*1,35n = 1012,5*n. Isso representa uma
“aceleração” de 0,93.
4.15.3 O número de loads e stores é o fator principal. A forma como as loads e
as stores são usadas também pode ter um efeito. Por exemplo, um
programa cujos carregamentos e armazenamentos tendem a ser apenas
alguns endereços diferentes também pode ser executado mais
rapidamente na nova máquina.
4.15.4 Esta resposta é uma questão de opinião.
4.16
4.16.1 Canalizado: 350; não canalizado: 1250 canalizado:
4.16.2 1250; sem pipeline: 1250
4.16.3 Divida o estágio de ID. Isso reduz o tempo do ciclo de clock para 300ps.
4.16.4 35%.
4.16.5 65%
)
4.21.1 .O pipeline com encaminhamento requer 1,05*n*300ps. A aceleração é,
portanto, (1,4*250)/ (1,05*300) = 1,11.
4.21.2 Nosso objetivo é que o pipeline com encaminhamento seja mais rápido
do que o pipeline sem encaminhamento. Seja y o número de baias
restantes como porcentagem de instruções de “código”. Nossa meta é
300*(1+y)*n
< 250*1,4*n. Assim, y deve ser inferior a 16,7%.
4.21.3 Desta vez, nosso objetivo é 300(1 + y)*n < 250(1 + x)*n. Isso acontece
quando y < (250x − 50)/300.
4.21.4 Eu não posso. Na melhor das hipóteses, onde o encaminhamento elimina
a necessidade de cada NOP, o programa levará 300*n para ser executado
no pipeline com encaminhamento. Isso é mais lento do que os
250*1,075*n necessários no pipeline sem encaminhamento.
4.21.5 A aceleração não é possível quando a solução para 4.21.3 é menor que 0.
Resolvendo 0< (250x − 50)/300 para x dá que x deve ser pelo menos
0,2.
4.22
4.22.1 As barracas são marcadas com **:
sd x29, 12(x16) IF ID EX ME WB
ld x29, 8(x16) IF ID EX ME WB
sub x17, x15, x14 IF ID EX ME WB
bez x17, label ** * * IF ID EX ME WB
adicionar x15, x11, x14 IF ID EX ME WB
sub x15,x30,x14 IF ID EX ME WB
4.22.2 O código de reordenação não ajudará. Cada instrução deve ser buscada;
assim, todo acesso a dados causa um travamento. Reordenar o código
apenas mudará o par de instruções que estão em conflito.
4.22.3 Você não pode resolver esse risco estrutural com NOPs, porque mesmo
os NOPs devem ser buscados na memória de instruções.
4.22.4 35%. Todo acesso a dados causará uma parada.
4.23
4.23.1 O período do relógio não mudará porque não estamos fazendo nenhuma
alteração no estágio mais lento.
4.23.2 Mover o estágio MEM em paralelo com o estágio EX eliminará a
necessidade de um ciclo entre loads e operações que utilizam o resultado
das loads. Isso pode potencialmente reduzir o número de stalls em um
programa.
4.23.3 Remover o deslocamento de ld e sd pode aumentar o número total de
instruções porque algumas instruções ld e sd precisarão ser
substituídas por um par addi/ld ou addi/sd .
4.24 O segundo. Um exame cuidadoso da Figura 4.59 mostra que a necessidade
de um estol é detectada durante o estágio de ID. É este estágio que
impede a busca de uma nova instrução, efetivamente fazendo com que o
add repita seu estágio de ID.
4.25
4.25.1 … indica uma parada. ! indica um estágio que não faz trabalho útil.
ld x10, 0(x13) SE ID EX ME | WB
ld x11, 8(x13) SE ID EX | ME WB
adicionar x12, x10, x11 IF ID | .. EX EU! WB
adiciona x13, x13, -16 SE | .. ID EX EU! WB
bnez x12, LOOP | .. SE ID EX ME! WB!
ld x10, 0(x13) IF ID EX ME WB
ld x11, 8(x13) IF ID EX ME WB
adicionar x12, x10, x11 IF ID .. EX | MIM! WB
adiciona x13, x13, -16 SE .. ID | EX EU! WB
bnez x12, LOOP SE | ID EX EU! WB!
Completamente ocupado | NNN N N N NN |
// EX ao 1º e EX ao 2º:
adiciona x11, x12, x13
adiciona x5, x11,
x15 adiciona x16,
x11, x12
4.26.2 // EX apenas ao 1º: 2
nops adiciona x11, x12,
x13 nop nop
adi
cio
na
x14 , x11, x15
add x5, x6, x7
// EX para 2º apenas: 1
nop add x11, x12, x13
adiciona x5,
x6, x7 não
adiciona x14, x11, x12
// MEM apenas para 2º: 1
não ld x11, 0(x12)
adiciona x5,
x6, x7 não
adiciona x14, x11, x13
4.26.4 Tomando uma média ponderada das respostas de 4,26 .2 dá 0,05*2 + 0,2*2
+ 0,05*1 + 0,1*1 + 0,1*2 = 0,85 stalls por instrução (em média) para
um CPI de 1,85. Isso significa que 0,85/1,85 ciclos, ou 46%, são
paralisações.
4.26.5 A única dependência que não pode ser tratada pelo encaminhamento é
do estágio MEM para a próxima instrução. Assim, 20% das instruções
irão gerar um stall para um CPI de 1,2. Isso significa que 0,2 de 1,2
ciclos, ou 17%, são paralisações.
4.26.6 Se encaminharmos apenas do registro EX/MEM, teremos as seguintes
barracas/NOPs
EX para 1º: 0
MEM para 1º: 2
EX para 2º: 1
MEM para 2º: 1
EX para 1º e 2º: 1
Isso representa uma média de 0,05*0 + 0,2*2 + 0,05*1 + 0,10*1 + 0,10*1
=
0,65 baias/instrução. Assim, o CPI é de 1,65
SE encaminharmos apenas de MEM/WB, temos as seguintes barracas/NOPs
EX para 1º: 1
MEM para 1º: 1
EX para 2º: 0
MEM para 2º: 0
EX para 1º e 2º: 1
Este representa uma média de 0,05*1 + 0,2*1 + 0,1*1 = 0,35
baias/instrução. Assim, o IPC é de 1,35.
4.26.7
4.27
4.27.1 add x15, x12,
x11 nop
nop
ld x13, 4(x15)
ld x12,
0(x2) nop
ou x13, x15,
x13 nop
nop
sd x13, 0(x15)
4.27.2 Não é possível reduzir o número de NOPs.
4.27.3 O código é executado corretamente. Precisamos da detecção de perigo
apenas para inserir um estol quando a instrução que segue uma carga usa
o resultado da carga. Isso não acontece neste caso.
4.27.4
4,28
4,28,1 O IPC aumenta de 1 para 1,4125.
Um desvio previsto incorretamente fará com que três instruções sejam
liberadas: as instruções atualmente nos estágios IF, ID e EX. (Neste
ponto, a instrução de desvio atinge o estágio MEM e atualiza o PC com
a próxima instrução correta.) Em outras palavras, 55% dos desvios
resultarão na liberação de três instruções, nos dando um CPI de 1 + (1 −
0,45)(0,25)3 = 1,4125. (Só para
ficar claro: o preditor sempre obtido está correto 45% das vezes, o que
significa,
é claro, que está incorreto 1 − 0,45 = 55% das vezes.)
4.28.2 O IPC aumenta de 1 para 1,3375 . (1 + (.25)(1 − .55) = 1,1125)
4.28.3 O IPC aumenta de 1 para 1,1125. (1 + (.25)(1 − .85) = 1,0375)
4.28.4 A aceleração é de aproximadamente 1,019.
Alterar metade das instruções de desvio para uma instrução ALU reduz
a porcentagem de instruções que são desvios de 25% para 12,5%. Como
as ramificações previstas e incorretas são substituídas igualmente, a taxa
de previsão incorreta permanece em 15%. Assim, a nova CPU é 1 +
(0,125)(1 − 0,85)
= 1,01875. Isso representa uma aceleração de 1,0375 / 1,01875 = 1,0184
4.28.5 A “aceleração” é 0,91.
Há duas maneiras de olhar para este problema. Uma maneira é olhar
para as duas instruções ADD como uma ramificação com um ciclo
“extra”. Assim, metade dos ramos tem 1 ciclo extra; 15% da outra
metade tem 1 ciclo extra (o enxágue do pipeline); e os ramos restantes
(aqueles corretamente previstos) não têm ciclos extras. Isso nos dá um
CPI de 1 + (.5)(.25)*1 +
(.5)(.25)(.15)*1 = 1.14375 e uma aceleração de 1.0375 / 1.14375 = .91.
Também podemos tratar as instruções ADD como instruções separadas.
O programa modificado agora tem 1.125n instruções (metade de 25%
produz
uma instrução extra). .125n dessas instruções 1.125n (ou 11,1%) são
ramificações. O CPI para este novo programa é 1 + (0,111)(0,15)*1 =
1,01665. Quando consideramos o aumento de 12,5% nas instruções,
obtemos uma aceleração de 1,0375 / (1,125 * 1,01665) = 0,91.
4.28.6 O preditor tem 25% de precisão nas ramificações restantes. Sabemos
que 80% das ramificações são sempre previstas corretamente e a
precisão geral é
de 0,85. Assim, 0,8*1 + 0,2*x = 0,85. Resolvendo para x mostra que x = 0,25.
4,29
4.29.1
4.29.2
4.29.3 As primeiras recorrências deste padrão não têm a mesma precisão que as
posteriores porque o preditor ainda está aquecendo. Para determinar a
precisão no “estado estacionário”, devemos trabalhar nas previsões de
ramificação até que os valores do preditor comecem a se repetir (ou seja,
até que o preditor tenha o mesmo valor no início da corrente e na
próxima recorrência do padrão).
4.30.2 O Mux que seleciona o próximo PC deve ter entradas adicionadas a ele.
Cada entrada é um endereço constante de um manipulador de exceção.
Os detectores de exceção devem ser adicionados ao estágio de pipeline
apropriado e as saídas desses detectores devem ser usadas para controlar
o Mux pré-PC e também para converter em instruções NOPs que já
estão no pipeline por trás da instrução de disparo de exceção.
4.30.5 Precisamos de uma instrução especial que nos permita mover um valor
do registrador Cause (exceção) para um registrador de uso geral.
Devemos primeiro salvar o registrador de propósito geral (para que
possamos restaurá-lo mais tarde), carregar o registrador Cause nele,
adicionar o endereço da tabela de vetores a ele, usar o resultado como
um endereço para um carregamento que obtém o endereço do
manipulador de exceção direito da memória e, finalmente, pule para esse
manipulador.
4.31.1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
li x12, 0 IF ID EX ME WB
jal ENT IF ID .. EX ME WB
ld x29, 8(x6) SE .. ID EX ME WB
sub x30, x7, x29 SE .. ID .. .. EX ME WB
slli x5 , x12, 3 IF .. ID EX ME WB
adicionar x6, x10, x5 IF .. ID .. EX ME WB
ld x7, 0(x6) IF .. ID EX ME WB
ld x29, 8(x6) IF .. ID .. EX ME WB
sd x30, 0(x31) IF .. .. ID EX ME WB
addi x12, x12, 2 IF .. .. ID .. EX ME WB
4.31.5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 beqz
x13, DONE IF ID EX ME WB
li x12, 0 IF ID .. EX ME WB
ld x7, 0(x6) IF .. ID EX ME WB
adiciona x31, x11, x5 IF .. ID EX ME WB
ld x29, 8(x6) IF ID EX ME WB
addi x12, x12, 2 IF ID EX ME WB
sd x30, 0(x31) IF .. ID EX ME WB
bne x12, x13, TOP IF .. ID EX ME WB
4.31.6 O código de 4.31.3 requer 9 ciclos por iteração em. O código de 4.31.5
requer 7,5 ciclos por iteração. Assim, a aceleração é 1,2.
4.31.7 Aqui está uma
possibilidade: beqz
x13, DONE li
x12, 0
TOP:
slli x5, x12, 3
add x6, x10, x5
add x31, x11,
x5 ld x7, 0(x6)
ld x29, 8(x6)
ld x5, 16(x6)
ld x15,
24(x6)
addi x12, x12,
4 sub x30, x7,
x29 sub x14,
x5, x15 sd x30,
0(x31) sd x14,
16(x31)
bne x12, x13,
TOP DONE :
4.31.8 Aqui está uma possibilidade:
beqz x13,
DONE li x12,
0
addi x6, x10,
0 TOP:
ld x7, 0(x6)
add x31, x11, x5
ld x29, 8(x6)
addi x12, x12, 4
ld x16 , 16(x6)
slli x5, x12, 3
ld x15, 24(x6)
sub x30, x7, x29
sd x30, 0(x31)
sub x14, x16,
x15 sd x14,
16(x31)
adicionar x6,
x10, x5 bne
x12,x13,TOP
DONE:
4.31.9 O código de 4.31.7 requer 13 ciclos por iteração desenrolada. Isso é equivalente a 6,5 ciclos por
iteração original. O código de 4.30.4 requer 7,5 ciclos por iteração desenrolada. Isso é
equivalente a 3,75 ciclos por iteração original. Assim, a aceleração é de 1,73.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
beqz x13, DONE IF ID EX ME WB
li x12, 0 IF ID .. EX ME WB
addi x6, x10, 0 SE .. ID EX ME WB
ld x7, 0(x6) SE .. ID .. EX ME WB
adicionar x31, x11, SE .. ID EX ME WB
x5
ld x29, 8(x6) SE .. ID EX ME WB
addi x12, x12, 4 IF ID EX ME WB
ld x16, 16(x6) IF ID EX ME WB
slli x5, x12, 3 IF ID EX ME WB
ld x15, 24(x6) IF ID EX ME WB
sub x30, x7 , x29 IF ID EX ME WB
sd x30, 0(x31) IF ID .. EX ME WB
sub x14, x16, x15 IF .. ID EX ME WB
sd x14, 16(x31) IF .. ID EX ME WB
add x6 , x10, x5 IF ID EX ME WB
bne x12,x13,TOP IF ID EX ME WB
ld x7, 0(x6) IF ID EX ME WB
adicionar x31, x11, x5 IF ID EX ME WB
ld x29, 8(x6) IF ID EX ME WB
addi x12, x12, 4 IF ID EX ME WB
ld x16, 16(x6) IF ID EX ME WB
slli x5, x12, 3 IF ID EX ME WB
ld x15, 24(x6) IF ID EX ME WB
sub x30, x7, x29 IF ID EX ME WB
sd x30, 0(x31) IF ID EX ME WB
sub x14, x16, x15 IF ID .. EX ME WB
sd x14, 16(x31) IF .. ID EX ME WB
add x6, x10, x5 IF .. ID EX ME WB
bne x12,x13,TOP IF ID EX ME WB
ld x7, 0(x6) IF ID EX ME WB
4.31.10 Usando o mesmo código da versão 4.31.8, o novo caminho de dados
não oferece nenhuma melhoria de rede, pois não há travamentos
devido a riscos estruturais.
4.32
4.32.1 A energia para os dois projetos é a mesma: I-Mem é lido, dois
registradores são lidos e um registrador é escrito. Temos: 140pJ +
2*70pJ + 60j = 340pJ.
4.32.2 A memória de instruções é lida para todas as instruções. Cada instrução
também resulta em duas leituras de registradores (mesmo que apenas um
desses valores seja realmente usado). Uma instrução de carregamento
resulta em uma leitura de memória e uma escrita de registrador; uma
instrução de armazenamento resulta em uma gravação na memória;
todas as outras instruções resultam em, no máximo, uma única gravação
de registro. Como a soma da energia de leitura de memória e de
gravação de registrador é maior que a energia de gravação de memória,
a instrução de pior caso é uma instrução de carregamento. Para a energia
gasta por uma carga, temos:
140pJ + 2*70pJ + 60pJ + 140pJ = 480pJ.
4.32.3 A memória de instruções deve ser lida para cada instrução. No entanto,
podemos evitar a leitura de registradores cujos valores não serão
utilizados. Para fazer isso, devemos adicionar as entradas de controle
RegRead1 e RegRead2 à unidade de Registros para habilitar ou
desabilitar cada leitura de registro. Devemos gerar esses sinais de
controle rapidamente para evitar prolongar o tempo do ciclo de clock.
Com esses novos sinais de controle, uma instrução de carregamento
resulta em apenas um registrador lido (ainda precisamos ler o registrador
usado para gerar o endereço), então nossa alteração economiza
70pJ (um registrador lido) por carga. Esta é uma economia de 70/480 = 14,6%.
4.32.4 jal se beneficiará, porque não precisa ler nenhum registro. As
instruções do tipo I também serão beneficiadas porque precisam ler
apenas um registrador. Se adicionarmos lógica para detectar x0 como
um registrador de origem, então instruções como beqz (ou seja beq
x0, …) e li (addi xn, x0, …) também podem se beneficiar.
4.32.5 Antes da mudança, a unidade de controle decodifica a instrução
enquanto as leituras de registro estão acontecendo. Após a alteração, as
latências de Controle e Leitura de Registro não podem ser sobrepostas.
Isso aumenta a latência do estágio de ID e pode afetar o tempo do ciclo
de clock do processador se o estágio de ID se tornar o estágio de maior
latência. No entanto, a soma das latências do registrador lido (90ps) e da
unidade de controle (150ps) é menor que o tempo de ciclo atual de
250ps.
4.32.6 Se a memória for lida em cada ciclo, o valor é necessário (para uma
instrução de carga) ou não passa pelo WB Mux (para uma instrução sem
carga que grava em um registrador) ou não é gravado em qualquer
registro (todas as outras instruções, incluindo filiais e bancas). Essa
alteração não afeta o tempo de ciclo do relógio porque o tempo de ciclo
do relógio já deve permitir tempo suficiente para que a memória seja
lida no estágio MEM. Isso pode afetar o desempenho geral se as leituras
de memória não utilizadas causarem faltas de cache.
S-24 Capítulo 4 Soluções
4.33.2 oo teste para travado em zero requer uma instrução que define o sinal
como 1; e o teste para preso em 1 requer uma instrução que define o
sinal como 0. Como o sinal não pode ser 0 e 1 no mesmo ciclo, não
podemos testar o mesmo sinal simultaneamente para preso em 0 e preso
em -1 usando apenas uma instrução.
O teste para preso em 1 é análogo ao teste preso em 0: (1) Coloque um
valor de 10 em x1, 35 em x2e 45 em x3, então (2) execute add x2,
x1, x1. O valor de x2 deve ser 20. Se o bit 0 da entrada Write
Register para a unidade de registradores estiver preso em 1, o valor será
escrito em x3 que significa que x3 será 40 e x2 permanecerá em 35.
4.33.4 Para testar essa falha, precisamos de uma instrução para a qual
MemRead seja definido como 1, portanto, deve ser ld. A instrução
também precisa ter branch definido como 0, que é o caso de ld.
Finalmente, a instrução precisa ter um resultado diferente MemRead
está incorretamente definido como 0. Para uma carga, definir MemRead
como 0 resulta em não ler a memória. Quando isso acontece, o valor
colocado no registrador é “aleatório” (o que quer que esteja na
saída da unidade de memória). Infelizmente, esse valor “aleatório” pode
ser o mesmo que já está no registro, portanto este teste não é conclusivo.
4.33.5 Only R-type instructions set RegRd to 1. Most R-type instructions would
fail to detect this error because reads are non-destructive—the erroneous
read would simply be ignored. However, suppose we issued this
instruction: add x1, x0, x0. In this case, if MemRead were
incorrectly set to 1, the data memory would attempt to read the value in
memory location 0. In many operating systems, address 0 can only be
accessed by a process running in protected/kernel mode. If this is the
case, then this instruction would cause a segmentation fault in the
presence of this error.