# Datapath e controlo

Sinais de controlo do monociclo, ALU, decisão do próximo PC e o custo de um ciclo por instrução.

Página: https://resumos.rgo.pt/cadeiras/fsc/datapath-controlo/

O **datapath** é o conjunto de componentes por onde os dados passam: registos, ALU, memória e os multiplexadores que escolhem as entradas de cada um. A **unidade de controlo** lê o opcode da instrução e gera os **sinais de controlo** que configuram o datapath para essa instrução. Esta página mostra o datapath **monociclo**, onde cada instrução se executa inteiramente num só ciclo de relógio.

![Datapath monociclo: o PC alimenta a memória de instruções, que alimenta o banco de registos, que alimenta a ALU, que alimenta a memória de dados, cujo resultado volta ao banco de registos. Um MUX comandado por PCSrc escolhe entre PC mais 4 e o endereço de salto.](https://resumos.rgo.pt/cadeiras/fsc/datapath-controlo/figura-1.svg)

Segue o desenho da esquerda para a direita: é o caminho que qualquer instrução percorre, com o MUX do PC a decidir no fim se continua em sequência ou salta.

[Vídeo: dr. P. Píša: Computer Architectures - 2022 - 03 - Processor (Single Cycle CPU)](https://www.youtube.com/watch?v=dGWzpEulIMY)

A miniatura vem do YouTube. O vídeo só carrega quando clicas. [Abrir no YouTube](https://www.youtube.com/watch?v=dGWzpEulIMY)

A aula segue instruções num simulador monociclo parecido com este desenho e é útil para veres a `LDUR` atravessar cada bloco.

## Os sinais de controlo

Cada instrução precisa de uma combinação de sinais. A tabela seguinte resume o que a unidade de controlo gera para as famílias da cadeira, incluindo o salto incondicional:

| Instrução | Reg2Loc | ALUSrc | MemtoReg | RegWrite | MemRead | MemWrite | Branch | ALUOp |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Tipo R | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 10 |
| LDUR | X | 1 | 1 | 1 | 1 | 0 | 0 | 00 |
| STUR | 1 | 1 | X | 0 | 0 | 1 | 0 | 00 |
| CBZ | 1 | X | X | 0 | 0 | 0 | 1 | 01 |
| B | X | X | X | 0 | 0 | 0 | 0 | XX |

A linha do `B` é quase toda `X`: o salto incondicional não lê registos para a ALU, não toca na memória de dados e não escreve registos. O seu único efeito é no PC, sempre tomado. Repara que com `Branch = 0` a equação `PCSrc = Branch · Zero` dá sempre 0, por isso o datapath precisa de um termo a mais para os saltos incondicionais: `PCSrc = Branch · Zero + SaltoIncondicional`, com `SaltoIncondicional = 1` nas instruções `B` e `BL`.

Lê cada coluna como uma pergunta sobre o datapath. **Reg2Loc** escolhe qual o segundo registo lido do banco de registos. **ALUSrc** escolhe entre registo (0) e imediato com extensão de sinal (1) como segundo operando da ALU. **MemtoReg** escolhe entre a saída da ALU (0) e o dado vindo da memória (1) para escrever no registo destino. **RegWrite** autoriza a escrita no banco de registos. **MemRead** e **MemWrite** autorizam ler e escrever na memória de dados. **Branch** marca as instruções de salto condicional. **ALUOp** diz à ALU que operação fazer: `10` significa usar o campo de função (tipo R), `00` significa somar (cálculo de endereço) e `01` significa subtrair para testar o zero (CBZ). O `X` significa tanto faz: esse sinal não influencia esta instrução.

Segue a `LDUR` pela tabela: o segundo operando da ALU é o imediato (`ALUSrc = 1`), a ALU soma (`ALUOp = 00`), lê-se a memória (`MemRead = 1`), o valor lido volta para o registo (`MemtoReg = 1`, `RegWrite = 1`) e nada se escreve (`MemWrite = 0`).

Segue a `STUR` pela tabela: o endereço calcula-se igual (`ALUSrc = 1`, `ALUOp = 00`), mas nada se escreve em registos (`RegWrite = 0`) e escreve-se na memória (`MemWrite = 1`, com `MemtoReg` tanto faz). O dado a escrever vem do segundo registo lido (`Reg2Loc = 1`).

## O próximo PC

A seguir a cada instrução, o PC avança 4 bytes, exceto quando um salto condicional se confirma. A seleção faz-se com um multiplexador comandado por **PCSrc**:

$$
\text{PCSrc} = \text{Branch} \cdot \text{Zero}
$$

`Branch` vem da unidade de controlo e `Zero` vem da ALU, que o ativa quando o seu resultado é zero. Só quando ambos são 1, isto é, é uma instrução de salto **e** a condição verificou-se, é que o PC recebe o endereço de salto em vez de `PC + 4`.

![Grafo da decisão do próximo PC: os sinais Branch e Zero entram numa porta E, cuja saída PCSrc comanda o MUX entre PC mais 4 e o endereço de salto.](https://resumos.rgo.pt/cadeiras/fsc/datapath-controlo/figura-2.svg)

O grafo é a equação desenhada: dois sinais entram no E, e a saída decide o MUX.

## O preço do monociclo

No datapath monociclo, cada instrução ocupa exatamente um ciclo, por isso o CPI (_cycles per instruction_) é 1. Mas o período de relógio tem de acomodar a instrução mais lenta, que é a `LDUR`: atravessa a memória de instruções, o banco de registos, a ALU, a memória de dados e ainda o caminho de escrita no registo.

O resultado é um relógio com um período longo, ditado pelo pior caso. Esta abordagem não é viável para CPUs com instruções de complexidade muito diferente, porque as instruções simples ficam a pagar o tempo das lentas. A resposta da arquitetura a este problema é o **pipeline**, que vais conhecer em Arquitetura de Computadores: em vez de uma instrução de cada vez, várias instruções atravessam o datapath em simultâneo, em fases diferentes.

Como ler a tabela numa prova

Tapa uma linha e reconstrói-a a pensar no percurso dos dados: de onde vêm os operandos da ALU, o resultado vai para onde, há leitura ou escrita de memória. Se o percurso estiver certo, os sinais saem sozinhos.

## Para saber mais

*   [Simulador gráfico de microarquitetura](https://github.com/arm-education/Graphical-Micro-Architecture-Simulator): simulador ARM no navegador com monociclo e pipeline, para veres a `LDUR` a atravessar os blocos do diagrama acima.
