Tópicos:
Formato das instruções;
Codificação das instruções;
Análise do funcionamento das instruções;
Esboço de fluxo de dados que execute essas instruções;
Simulação manual do funcionamento do FD;
Implementação do FD em VHDL.
Vale relembrar que cada instrução é composta de um vetor de bits (32 bits no nosso caso). Esse vetor possui todas as informações necessárias para a execução da instrução codificadas em seus bits. Basicamente, essas informações são:
A localização dos dados utilizados na operação;
A operação a ser executada;
A localização onde será armazenado o resultado da operação.
Para organizar a codificação dessas instruções, a palavra de 32 bits foi dividida em campos bem definidos, confome mostrado abaixo. De acordo com o tipo da instrução, esses campos podem ser modificados através da união de dois campos vizinhos, formando um novo campo com uma quantidade maior de bits.
| funct7 | Rs2 | Rs1 | funct3 | Rd | opcode |
|---|---|---|---|---|---|
| 7 bits | 5 bits | 5 bits | 3 bits | 5 bits | 7 bits |
| MSB (b31) | LSB (b0) |
O significado dos nomes dos campos:
Opcode: Contém o código, com 7 bits, da instrução a ser executada;
Rs1: O endereço (número em binário de 5 bits) do registrador com o primeiro operando da instrução definida em opcode;
Rs2: O endereço (número em binário de 5 bits) do registrador com o segundo operando da instrução definida em opcode;
Rd: O endereço (número em binário de 5 bits) do registrador de destino para o resultado da instrução definida em opcode;
funct3: Seleciona a operação, código de 3 bits, que será aplicada aos operandos. O opcode só define que a instrução é do tipo R, deixando a definição da operação para o funct3 e funct7.
funct7: Seleciona a operação, código de 7 bits, que será aplicada aos operandos. O opcode só define que a instrução é do tipo R, deixando a definição da operação para o funct3 e funct7.
Os detalhes de funcionamento das instruções, códigos de opcode e funct, estão no greencard (disponível nos links úteis).
Este é o grupo das instruções, lógicas e aritméticas, que operam somente com registradores. O uso dos registradores permite uma velocidade de execução maior do que se utilizasse a memória externa ao processador.
Todas instruções do tipo R utilizam 3 registradores, o campo opcode é sempre igual a 0x33 (33h ou 0110011b) e os campos funct3 e funct7 definem a operação a ser realizada. Os valores que esses campos podem assumir estão explicados no greencard.
A sintaxe desse grupo de instruções é do tipo:
O funcionamento desse tipo de instrução:
A detecção do conteúdo do opcode igual ao valor 0x33 (33h ou 0110011b), indica que é uma instrução do tipo R.
Para esse tipo de instrução, o registrador com endereço igual ao conteúdo do campo Rd (destino do resultado da operação) da instrução terá seu conteúdo modificado para o resultado da operação indicada pelo conteúdo dos campos funct3 e funct7.
Essa operação é realizada entre os conteúdos dos registradores indicados (indexados) pelos conteúdos dos campos Rs1 e Rs2 da instrução (operandos da operação).
Essa classe de instruções tem somente um modo de endereçamento: endereçamento em registrador.
Para compreender melhor esse tipo de codificação, faremos a codificação para a soma mostrada abaixo (utilize o greencard):
| funct7 | Rs2 | Rs1 | funct3 | Rd | opcode |
|---|---|---|---|---|---|
| 7 bits | 5 bits | 5 bits | 3 bits | 5 bits | 7 bits |
| 31~25 | 24~20 | 19~15 | 14~12 | 11~7 | 6~0 |
Solução:
Pela consulta ao greencard, para a instrução add, temos:
add: x[rd] = x[rs1] + x[rs2]
Opcode: 0b011_0011;
Rs1: x3 = 0b0_0011;
Rs2: x7 = 0b0_0111;
Rd: x8 = 0b0_1000;
funct3: 0b000 (0x0);
funct7: 0b000_0000 (0x00).
| funct7 | Rs2 | Rs1 | funct3 | Rd | opcode |
|---|---|---|---|---|---|
| 7 bits | 5 bits | 5 bits | 3 bits | 5 bits | 7 bits |
| 0000000 | 00111 | 00011 | 000 | 01000 | 0110011 |
| 31~25 | 24~20 | 19~15 | 14~12 | 11~7 | 6~0 |
Caso a instrução seja uma subtração, como ficaria a sua codificação?
| funct7 | Rs2 | Rs1 | funct3 | Rd | opcode |
|---|---|---|---|---|---|
| 7 bits | 5 bits | 5 bits | 3 bits | 5 bits | 7 bits |
| 31~25 | 24~20 | 19~15 | 14~12 | 11~7 | 6~0 |
Solução:
Pela consulta ao greencard, para a instrução sub, temos:
sub: R[rd] = R[rs1] - R[rs2]
Opcode: 0b011_0011;
Rs1: x17 = 0b1_0001;
Rs2: x22 = 0b1_0110;
Rd: x31 = 0b1_1111;
funct3: 0b000 (0x0);
funct7: 0b010_0000 (0x20).
| funct7 | Rs2 | Rs1 | funct3 | Rd | opcode |
|---|---|---|---|---|---|
| 7 bits | 5 bits | 5 bits | 3 bits | 5 bits | 7 bits |
| 0100000 | 10110 | 10001 | 000 | 11111 | 0110011 |
| 31~25 | 24~20 | 19~15 | 14~12 | 11~7 | 6~0 |
Responder o quiz de participação, no blackboard, em:
Conteúdos > Participação > Aula_12_Quiz-P1
Agora que a codificação das instruções do tipo R já é conhecida, vamos analisar o seu funcionamento.
Devemos mapear o funcionamento das cinco etapas do processador para as instruções do tipo R. Para cada etapa, execute os passos a seguir.
O primeiro passo é a definição dos recursos que pretende utilizar, os blocos construtivos necessários para executar a instrução.
O segundo passo é a descrição do fluxo entre esses blocos. Para tanto, pode-se usar uma forma de pseudocódigo que detalhe o funcionamento da instrução assembly.
O terceiro passo é o esboço do projeto, usando com base a descrição do funcionamento da instrução (pseudocódigo):
Conecte os blocos construtivos necessários para que a instrução execute;
Anote os pontos de controle utilizados e seus valores;
Faça um rascunho do fluxo de dados e simule manualmente (papel e caneta).
Volte aos passos anteriores sempre que for necessário fazer ajustes ou redefinir algumas escolhas.
Quando o FD estiver pronto, verifique se ele atende o funcionamento de todas as outras instruções, do tipo R, que implementaremos:
Subtração (sub);
E lógico (and);
OU lógico (or);
Comparação Menor Que (set if less than: slt). Essa instrução só poderá ser testada após implementarmos a ULA definitiva.
A cada instrução, anote os estados dos pontos de controle.
Consolide todos os seus resultado em uma tabela contendo as instruções e os pontos de controle. Isso facilitará a criação da simulação ou da UC temporária.
Utilizando a instrução add, defina o fluxo de dados necessário para executar as instruções do tipo R em um ciclo de clock.
Como vimos, essas instruções possuem a seguinte expressão geral:
Utilizaremos como base a arquitetura Registrador-Registrador, vista anteriormente, que está mostrada abaixo.
Considerando as instruções do tipo R não utilizam memória RAM e que estamos trabalhando com memórias separadas para instruções e dados, podemos definir que necessitamos das unidades funcionais:
Registrador PC;
Memoria ROM;
Banco de registradores;
ULA (utilizaremos o modelo ULASomaSub);
Unidade de Controle.
A interligação final, para atender exclusivamente às instruções do Tipo R, está mostrada abaixo.
Simule, no papel, todas as instruções comentadas anteriormente, para garantir que o fluxo de dados está correto.
Agora que o FD foi criado e simulado no papel: implemente em VHDL, utilizando os componentes disponíveis nos Modelos VHDL, simule e faça os testes no kit de desenvolvimento.
Para a implementação, utilize a ULA com Soma e Subtração utilizada nas aulas iniciais do semestre.
Para a simulação, faça uma instrução de soma e outra de subtração. Como não temos acesso a dados externos, utilize o Banco de Registradores do RV32I com inicialização em VHDL e faça os cálculos com registradores já inicializados.
Na simulação, não se esqueça de ativar os pontos de controle nos momentos adequados. Ou, se preferir, faça uma unidade de controle específica para essas duas instruções (isso facilita a simulação).
Para ver os resultados, será necessário conectar a saída da ULA a um port de saída.
Esta Atividade deverá ser entregue através do Blackboard!