CPU uniciclo: datapath e controlo

Seguir R, lw, sw e beq, escolher sinais de controlo e diagnosticar falhas.

TLDR

Perguntar sobre esta página

ChatGPTClaudePerplexityGrokGeminiCopiar e abrirDeepSeekCopiar e abrir

lw x5,12(x8) exige calcular um endereço, ler memória e escrever x5, enquanto sw x5,12(x8) calcula o mesmo endereço, mas escreve memória. O datapath contém os caminhos dos dados e o controlo escolhe as fontes e habilita a escrita adequada; o CPU didático de 32 bits desta lição suporta add, sub, and, or, lw, sw e beq, um subconjunto das instruções usadas nos programas RARS.

Caminho dos dados

O PC endereça a memória de instruções. Os campos rs1 e rs2 escolhem duas leituras do banco de registos, enquanto rd escolhe uma possível escrita; o gerador de imediatos reconstrói e estende o imediato segundo o formato da instrução.

A ALU recebe sempre o primeiro operando do banco. O segundo vem de um MUX: registo rs2 para operações R e comparação, ou imediato para calcular endereços de memória. O resultado da ALU pode ir diretamente para escrita num registo ou servir de endereço da memória de dados.

Uma soma separada calcula PC+4 e outra calcula PC+d para o branch. PCSrc=Branch AND Zero escolhe o destino de branch quando a instrução é beq e a comparação indica igualdade; o d já está em bytes, com o bit 0 implícito reconstruído, por isso não o multipliques novamente por 4.

Sinais de controlo

ClasseRegWriteALUSrcMemReadMemWriteMemtoRegBranchALUOp
R10000010
lw11101000
sw0101X000
beq0000X101

Um sinal de controlo é um bit, ou um pequeno código, produzido a partir da instrução. ALUSrc=0 escolhe rs2; ALUSrc=1 escolhe o imediato. MemRead habilita a leitura de dados. MemtoReg escolhe o dado da memória se 1 e o resultado da ALU se 0. RegWrite e MemWrite autorizam alterações de estado: têm de estar a 0 quando a instrução não escreve nesse destino.

Branch=1 identifica beq; PCSrc=Branch AND Zero decide se o salto é tomado.

ALUOp=00 pede soma; 01 pede subtração para a comparação; 10 usa f3 e f7 da instrução R. Neste modelo, ALUControl é 0000 para AND, 0001 para OR, 0010 para ADD e 0110 para SUB. ALUOp e ALUControl são sinais diferentes.

O campo que ocuparia rs2 numa instrução I contém bits do imediato. O banco pode lê-los fisicamente, mas lw não usa essa segunda leitura. Por isso uma falha nesse porto pode afetar sw, R e beq sem afetar lw.

Tomado e não tomado

Segue beq x5,x6,-8 em PC=0x00400010. A ALU subtrai x6 a x5 e produz Zero; se x5=x6, PCSrc=1 e o PC seguinte é 0x00400008, enquanto se diferirem, PCSrc=0 e segue 0x00400014. Um teste só com branches falsos nunca exercita o caminho de salto.

Seguir um load completo

Suponhamos lw x5,12(x8) em PC=0x00400020, x8=0x10010000, e memória em 0x1001000C contendo 42. O fetch lê a instrução. O banco entrega x8 e o gerador entrega 12. Com ALUSrc=1, a ALU soma e produz 0x1001000C.

Com MemRead=1, a memória devolve 42. Com MemtoReg=1, os 42 chegam à entrada de escrita; com RegWrite=1, o flanco guarda-os em x5. Com Branch=0, o PC seguinte é 0x00400024. O registo recebe 42, não o endereço calculado.

Num sw x5,12(x8), a mesma soma calcula o endereço, mas o dado de escrita vem da segunda leitura do banco, x5. RegWrite=0 evita alterar registos; MemWrite=1 altera memória.

No branch, a ALU usada para comparar não calcula o destino: esse caminho usa o somador do PC. Os dois resultados precisam de estar disponíveis no mesmo ciclo.

Falhas e extensões

Se MemtoReg ficar preso em 0, um load escreve o endereço em vez do conteúdo. Para o detetar, escolhe um teste em que endereço e conteúdo diferem: com o mesmo valor nos dois lados, a falha seria invisível. Se PCSrc ficar sempre em 0, só falham os branches que deveriam ser tomados. Um teste só com branches falsos nunca exercita o caminho de salto.

Se RegWrite ficar em 0, operações R e loads deixam de escrever. Stores e branches ainda podem funcionar. Se o bit alto de ALUOp ficar em 0, instruções R passam a pedir ADD: add ainda pode estar correto, mas sub, and e or precisam de testes que produzam resultados diferentes da soma.

addi pode reutilizar o datapath: ALUSrc=1, ALUOp=00, MemtoReg=0, RegWrite=1. jalr exige mais: escrever PC+4, escolher um destino calculado pela ALU e limpar o seu bit 0. Não chega mudar uma linha da tabela se o caminho físico ainda não existe.

Acrescentar jalr

jalr rd,d(rs1) faz duas escritas no mesmo flanco: coloca PC+4 em rd e coloca o destino calculado a partir de rs1 no PC. A ALU existente pode somar rs1 ao imediato I estendido com sinal. Falta encaminhar os dois resultados para os destinos corretos.

Uma opção conserva o MUX MemtoReg e acrescenta dois MUX de 32 bits:

  1. Na entrada de escrita do banco, um novo MUX escolhe a saída de MemtoReg quando Link=0, ou PC+4 quando Link=1.
  2. Na entrada do PC, outro MUX escolhe a saída do MUX PCSrc habitual quando JumpReg=0, ou o resultado da ALU com bit 0 limpo quando JumpReg=1.

Limpar o bit 0 não precisa de uma segunda operação da ALU: liga o bit inferior dessa entrada do MUX a 0 e os outros 31 à saída da ALU. O somador PC+4 que já existe fornece o retorno enquanto a ALU calcula o alvo.

Controlo em jalrValorEfeito
ALUSrc, ALUOp1, 00Soma rs1 ao imediato I
RegWrite, Link1, 1Escreve PC+4 em rd
JumpReg1Encaminha o alvo da ALU para PC
MemRead, MemWrite, Branch0, 0, 0Não lê nem escreve dados, nem testa beq
MemtoRegXA sua saída é ignorada por Link=1

Nesta organização, Link=JumpReg=0 nas instruções anteriores conserva os seus caminhos. Em jalr, PCSrc também é irrelevante para o PC, porque JumpReg escolhe a outra entrada. O descodificador deve reconhecer opcode 1100111 e funct3 000, e ImmGen deve produzir o imediato I. Estes nomes de sinais são uma escolha deste circuito, não campos da ISA.

Para jalr ra,0(ra) em PC=0x00400020, com ra antigo=0x00400081, a ALU produz 0x00400081. O novo MUX do PC recebe 0x00400080; o novo MUX do banco recebe 0x00400024. As leituras usam o estado antigo, por isso escrever ra no mesmo flanco não altera a base usada para o salto.

Sem instruções comprimidas, limpar só o bit 0 não garante alinhamento a 4: um alvo terminado em 10 binário continua desalinhado. Neste modelo didático consideramos destinos válidos; implementar exceções exige também a lógica de deteção e tratamento.

Um ciclo e o seu custo

Todas as instruções terminam num período. O relógio tem de acomodar a instrução com maior atraso, normalmente o load neste modelo: leitura de instrução, banco, ALU, memória de dados e setup de escrita. Uma operação curta não termina num período mais curto num relógio fixo.

Com atrasos de 2, 1, 2 e 3 ns nestes módulos, mais 1 ns para o destino, o caminho do load demora 9 ns. Soma só os módulos percorridos em série e inclui os MUX relevantes se o enunciado lhes atribuir atraso. CPI=1 não implica tempo mínimo de execução, porque o período pode ser longo.

Exercícios

Controlo de um store

Para sw x7,-8(x8), dá RegWrite,ALUSrc,MemRead,MemWrite,Branch e a operação da ALU. Explica de onde vem o dado escrito.

Pista

O store calcula endereço e altera só memória.

Mais uma pista

rs2 fornece o dado; o imediato fornece o offset.

Solução

RegWrite=0, ALUSrc=1, MemRead=0, MemWrite=1, Branch=0, ALUOp=00 para soma. Endereço=x8−8 e dado=x7 pela segunda leitura do banco. MemtoReg é X porque não há escrita em registo. A ALU calcula o endereço, não o conteúdo a escrever.

Confere a tua resposta:

  • RegWrite0, ALUSrc1, MemRead0, MemWrite1, Branch0 e ADD.
  • O dado vem de x7, o endereço de x8−8.

Erros frequentes

Não ligues a entrada de dados da memória ao imediato.

Voltar à explicação
Segunda leitura presa em zero

A segunda saída do banco de registos está sempre em zero. Que classes R,lw,sw,beq podem ser afetadas? Escolhe um teste para cada classe que deve falhar.

Pista

Verifica quem usa a segunda leitura.

Mais uma pista

O load usa base e imediato, sem esse valor.

Solução

lw continua a usar rs1+imediato. R pode falhar: add com rs2=3 perde esse 3. sw pode falhar: guardar x7=9 escreve 0. beq pode falhar: duas fontes iguais a 5 passam a comparar 5 com 0, deixando de saltar. Casos em que a segunda fonte já era zero podem esconder a falha.

Confere a tua resposta:

  • lw não usa a segunda leitura.
  • Dá valores que evidenciem erros em R, sw e beq.

Erros frequentes

Não concluas que toda execução de uma classe falha; depende dos valores do teste.

Voltar à explicação
Dado ou endereço

MemtoReg fica preso em zero. Executamos lw em endereço 0x10010020 contendo 0x10010020. Esse teste deteta a falha? Propõe um que a detete.

Pista

O resultado correto e o errado podem coincidir, por isso escolhe conteúdos que distingam dado e endereço.

Solução

O teste não deteta: a ALU produz o endereço e a memória contém exatamente esse mesmo valor. Escolhe, por exemplo, conteúdo 42 no endereço 0x10010020. O correto é escrever 42; o defeituoso escreve 0x10010020. As habilitações e o acesso têm de ser válidos para isolar a falha.

Confere a tua resposta:

  • O primeiro teste esconde a falha.
  • Conteúdo 42 distingue dado e endereço.

Erros frequentes

Uma execução sem diferença observável não prova que o MUX funciona.

Voltar à explicação
Uma instrução e o caminho necessário

O CPU uniciclo suporta R,lw,sw,beq. Para acrescentar addi, são necessários novos recursos de datapath? Indica o controlo.

Depois projeta a extensão para jalr. Conserva o MUX MemtoReg e acrescenta um MUX de writeback controlado por Link, com 0 para o caminho antigo e 1 para PC+4. Acrescenta outro MUX antes de PC, controlado por JumpReg, com 0 para o caminho antigo e 1 para o alvo da ALU. Indica as ligações, o tratamento do bit 0, todos os controlos necessários em jalr e como conservas as quatro classes anteriores.

Segue jalr ra,0(ra) em PC=0x00400020, com ra antigo=0x00400081. Supõe destinos alinhados a 4 depois de limpar o bit 0 e não acrescentes tratamento de exceções.

Pista

addi combina o imediato do load com o writeback das operações R. jalr precisa de dois valores diferentes no mesmo flanco.

Solução

addi usa RegWrite=1, ALUSrc=1, ALUOp=00, MemtoReg=0, MemRead=MemWrite=Branch=0 e Link=JumpReg=0. Precisa de nova descodificação, mas não de novo caminho de dados.

Em jalr, a ALU soma rs1 antigo ao imediato I estendido com sinal: ALUSrc=1 e ALUOp=00. Liga PC+4 à entrada 1 do novo MUX de writeback e escolhe Link=1, RegWrite=1. Liga a saída da ALU à entrada 1 do novo MUX de PC, com o bit 0 dessa entrada fixo a 0; escolhe JumpReg=1. MemRead=MemWrite=Branch=0. MemtoReg e o PCSrc antigo são X porque os novos MUX ignoram as suas saídas. ImmGen deve fornecer I e o controlo reconhecer opcode 1100111, funct3 000.

Nas quatro classes antigas, Link=JumpReg=0 deixa MemtoReg e PCSrc funcionar como antes. Não precisamos de outra ALU: o somador PC+4 produz o retorno em paralelo com o cálculo do alvo.

No exemplo, a ALU usa ra antigo e produz 0x00400081; PC recebe 0x00400080 e ra recebe 0x00400024. Os dois destinos capturam no mesmo flanco. Limpar bit 0 não garante por si só o alinhamento a 4; essa validade é uma hipótese do enunciado.

Confere a tua resposta:

  • addi reutiliza o datapath com imediato e writeback ALU.
  • jalr recebe caminhos PC+4→rd e ALU com bit 0 limpo→PC.
  • Defini os novos MUX, os controlos e a compatibilidade com R, lw, sw e beq.
  • O exemplo usa ra antigo e produz PC=00400080, ra=00400024.

Erros frequentes

Encaminhar a ALU para o PC sem acrescentar PC+4 ao writeback deixa o salto sem o retorno correto. Em rd=rs1, a fonte continua a ser o valor antigo.

Voltar à explicação
Tomado e não tomado

No CPU uniciclo, beq x5,x6,-8 está em PC=0x00400030. Analisa duas execuções: x5=x6=7; x5=7 e x6=9. Em cada uma, dá Branch, Zero, PCSrc e o PC seguinte. Se PCSrc estivesse preso em 0, qual dos testes detetaria a falha?

Pista

Calcula PCSrc=Branch AND Zero nos dois casos.

Mais uma pista

Com Branch=1: Zero=1 dá PC+d; Zero=0 dá PC+4.

Solução

Branch=1 nos dois casos, porque a instrução é beq. Com as fontes iguais, a subtração dá zero, Zero=1 e PCSrc=1: PC seguinte=0x00400028. Com 7 e 9, a subtração dá -2, Zero=0 e PCSrc=0: PC seguinte=0x00400034. Se PCSrc ficar preso em 0, só o primeiro teste deteta a falha, pois o CPU avançaria para 0x00400034 em vez de saltar. O segundo já devia avançar para esse endereço.

Confere a tua resposta:

  • Distinguistes Branch de Zero nos dois casos
  • Obtiveste os PCs 0x00400028 e 0x00400034
  • Identificaste o teste de igualdade como detetor da falha

Erros frequentes

Branch=1 em beq, não 0.

Voltar à explicação

À tua maneira

Aparência

Modo de cor
Tema
Cor de destaque

Leitura

Fonte de leitura

Álgebra, lógica e uma ideia de cada vez.

Código

Fonte do código

Navegação

Cursor de leitura, sem edição. h, j, k, l movem; / pesquisa nesta página. v seleciona caracteres; V seleciona linhas; y copia. Tab permite destacar ou comentar. Espaço ou Enter abre blocos recolhíveis. Nos cartões, h, j, k, l mudam o foco.

CSS personalizado

Ativa uma sugestão ou guarda o teu CSS. Só muda este navegador.

Usa --page, --text e --accent para acompanhar o tema.

Seletores e recuperação

.site-header, .prose, .course-card, [data-reading-history], [data-playground] e .page-actions.

Abre a aparência com a tecla vírgula ou no rodapé. Se o CSS esconder os controlos, abre esta página sem CSS personalizado.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Copiar fórmula

A cópia automática não está disponível. Copia o LaTeX abaixo.

Pesquisar nesta página

Enter procura · n / N repetem · Esc cancela. Ctrl / Cmd K pesquisa todo o site.

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.