tópicos avançados em sistemas integrados e distribuídos ii

Propaganda
Computador Acadêmico Básico Reconfigurável
Por: Sílvio Fernandes e Leonardo Casillo
Processador Simples
A Figura 1 mostra um sistema digital que contem vários registradores de 32 bits
(um deles, o R12, além de registrador também é um contador – usado para prover o
endereço de memória de onde as instruções são lidas, comumente chamado de program
counter (PC)), um multiplexador (multiplexers), uma ULA – Unidade Lógica e
Aritmética (ALU), e uma unidade de controle (control unit). A entrada de dados desse
sistema é feita via entrada DIN de 32 bits, que se comunica com a memória externa. Os
dados podem ser carregados através do multiplexador, de 32 bits de largura, para vários
registradores da arquitetura, tais como R0, ..., R12, A, G, DOUT, ADDR. Os endereços
dos registradores de uso geral são mostrados na Tabela 1. A saída do multiplexador é
chamada de barramento (bus) na figura pois esse termo é geralmente usado para os
sinais que permitem transferir os dados de um sistema para outro.
Bus
32
Incr_PC
...
R0
R12
(PC)
Mask
A
...
DIN
ALU
MUX
G
ADDR
32
IR
3
R12_In
MUX
R0_In
3
4
32
SEL
DOUT
G_In
A_In
...
Z,S,Cy
DOUT_In
ADDR_In
Control Unit
RUN
RESET
W
R
DONE
Figura 1 - Esquema do processador simples
Tabela 1. Registradores de uso geral
REGISTRADOR
R0
R1
R2
R3
R4
R5
R6
R7
R8
R9
R10
R11
R12 (PC)
ENDEREÇO (Bin)
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
ENDEREÇO (Hexa)
0
1
2
3
4
5
6
7
8
9
A
B
C
A ULA é responsável por operações lógicas e/ou aritméticas: soma, subtração, E
lógico, OU lógico, NÃO lógico, transparência e deslocamento de acordo com a Tabela
2.
Tabela 2 - Operações da ULA
SINAL PARA ULA
OPERAÇÃO
000
soma
001
subtração
010
and
011
or
100
not A
101
transparência
110
deslocamento para direita
111 deslocamento para esquerda
Isso é determinado para a ULA através do sinal Alu após a decodificação da
instrução pela unidade do controle. A ULA utiliza os dados vindos do barramento
diretamente ou indiretamente (do registrador A). A quantidade de dado depende do tipo
de instrução. Por exemplo, a instrução que realiza a soma de dois termos, o primeiro
dado vem do barramento e é armazenado no registrador A e o segundo dado vem do
barramento direto para a ULA. O resultado da operação é armazenado no registrador G.
O dado em G pode ser transferido para um dos outros registradores caso seja necessário.
A ULA ainda possui flags que indicam se o resultado da operação resultou em zero (Z),
se resultou em um número negativo (S) e se houve uma propagação de carry (CY).
Os dados podem ser transferidos de um registrador para outro através do
multiplexador. Esse multiplexador recebe um sinais de 4 bits (Mux) que seleciona quais
das entradas é passada para a saída do multiplexador (barramento). O valor do sinal de
seleção do multiplexador e a entrada correspondente transmitida para o barramento é
mostrada na Tabela 3.
Tabela 3 - Seleção do Multiplexador
Seleção do
Multiplexador
0000
0001
...
1100
1101
1110
1111
Valor na saída do
multiplexador
R0
R1
...
R12
Mask
G
DIN
O sistema pode executar diferentes operações a cada ciclo, controladas pela
unidade de controle (control unit). Essa unidade determina quando um dado em
particular é colocado no barramento e qual registrador deve carregá-lo. Por exemplo, se
a unidade de controle coloca Mux em “0000” e liga o Ain então o multiplexador
transmitirá o conteúdo de R0 para o barramento e esse dado será carregado na próxima
subida do clock no registrador A.
Este sistema executa as instruções mostrada na Tabela 4. As 2 primeiras colunas
mostram o código da operação (codop), em binário e em hexadecimal respectivamente,
a terceira coluna mostra o nome da instrução e seus operandos e a última coluna o
significado. A sintaxe RX ← [RY] significa que o conteúdo do registrador RY é
carregado no registrador RX.
A instrução mv (move) permite que o dado de um registrador possa ser copiado
para outro. Para a instrução mvi (move immediate) a expressão RX ← #D indica que um
valor constante D de 32 bits é carregado no registrador RX. A instrução ld (load)
carrega um dado para o registrador RX a partir do endereço da memória externa
especificado no RY. A instrução st (store) armazena o dado contido no registrador RX
no endereço de memória encontrado no RY. A instrução mvnz (move if not zero)
permite uma operação de mv ser executada apenas sob a condição do conteúdo atual do
registrador G não ser igual a zero.
Tabela 4 – Operações realizadas pelo processador
Código da
Operação (Bin)
00000000
00000001
00000010
00000011
00000100
00000101
00000110
00000111
00001000
00001001
00001010
00001011
00001100
00001101
Código da
Operação (Hexa)
0
1
2
3
4
5
6
7
8
9
A
B
C
D
Operação
mv Rx, Ry
mvi Rx, #D
mvnz Rx, Ry
add Rx, Ry
sub Rx, Ry
and Rx, Ry
or Rx, Ry
not Rx
ld Rx, [Ry]
st Rx, [Ry]
ldi Rx
jmp #D
jnz #D
shl Rx, Ry
Função Executada
Rx ← [Ry]
Rx ← D
IF G != 0, Rx ← Ry
Rx ← [Rx] + [Ry]
Rx ← [Rx] – [Ry]
Rx ← [Rx] and [Ry]
Rx ← [Rx] or [Ry]
Rx ← not[Rx]
Rx ← [[Ry]]
[Ry] ← [Rx]
G ← Rx
PC ← D
IF G != 0, PC ← D
Rx ← [Ry] << 1
00001110
00001111
00010000
00010001
00010010
00010011
00011111
00010100 a
00011110
1111xxxx
E
F
10
11
12
13
1F
14 a 1E
---
shr Rx, Ry
jnc #D
jns #D
jz #D
jc #D
js #D
halt
Reservado
Rx ← [Ry] >> 1
IF Cy != 0, PC ← D
IF S != 0, PC ← D
IF Z = 0, PC ← D
IF Cy = 0, PC ← D
IF S = 0, PC ← D
PC ← PC
---
Configuráveis
???
As instruções e dados são transferidas de/para a memória através da entrada
DIN. A comunicação entre o processador e a memória é feita passando o endereço
(ADDR) e/ou dado (DOUT) para a memória. A saída W do processador, quando ativa,
indica escrita do dado DOUT no endereço ADDR. A saída R do processador, quando
ativa, indica leitura do dado no endereço ADDR. A Figura 2 representa essa
comunicação.
ADDR
Read_Address
Saída
Write_Address
W
Write
R
Read
DIN
Memory
DOUT
Data
Clock
Figura 2 - Comunicação processador/memória
Cada instrução pode ser codificada e armazenada no registrador IR usando
formato de 32 bits IIIIIIIIXXXXYYYYZZZZZZZZZZZZZZZZ, onde IIIIIIII (8 bits)
representa o código da instrução (codop), XXXX (4 bits) o registrador RX, YYYY (8
bits) o registrador RY e ZZZZZZZZZZZZZZZZ (16 bits) pode representar o valor
constante. Caso a instrução utilize como operandos 2 registradores, então os bits
ZZZZZZZZZZZZZZZZ (16 bits) não são usados, podem ser deixados em zero. Quando
a instrução utiliza apenas 1 registrador, como na instrução mvi, os bits YYYY não tem
significado, o valor da constante #D ocupa os outros 16 bits na palavra da instrução,
representado por ZZZZZZZZZZZZZZZZ. Esse valor é enviado para o barramento
através do multiplexador por meio da saída Mask, cujo valor é (em hexadecimal)
“0000DDDD”. Nas instruções jmp e jnz os bits XXXX e YYYY e os outros 16 bits na
palavra da instrução correspondem ao endereço do salto da instrução que será enviado
para o PC.
A instrução especial HALT indica o fim do programa, então o processador ficará
parado aguardando um sinal de RESET.
Algumas instruções, como adição e subtração, levam mais que um ciclo de clock
para ser completada, por causa de várias transferências de dados através do barramento.
A unidade de controle deve implementar uma máquina de estados, onde a ordem dos
estados é determinada por cada instrução, ou seja, é o passo-a-passo da instrução. O
processador começa executando a instrução na entrada DIN quando o sinal Run é
acionado e o processador liga o sinal Done quando a instrução é finalizada. A Tabela 5
indica os sinais de controle que devem ser ligados em cada passo para implementar as
instruções da Tabela 4. Perceba que no passo 0 de cada instrução, apenas o sinal de
controle IRin é ligado (para receber a instrução).
Tabela 5 - Sinais do controle ligados em cada instrução/tempo
T0
(mv): IRin
(mvi): IRin
(mvnz): IRin
(add): IRin
T1
Mux=RY, RXin, Done
Mux=Mask, RXin, Done
Se !Z=> Mux=RY, Gin
Senão => Done
Mux=RX, Ain
(sub): IRin
T2
T3
Mux=G, RXin, Done
Mux=RY, Alu=add, Gin
Mux=G, RXin, Done
Mux=RX, Ain
Mux=RY, Alu=sub, Gin
Mux=G, RXin, Done
(and): IRin
Mux=RX, Ain
Mux=RY, Alu=and, Gin
Mux=G, RXin, Done
(or): IRin
Mux=RX, Ain
Mux=RY, Alu=or, Gin
Mux=G, RXin, Done
Mux=RX, Alu=not, Gin
Mux=G, RXin, Done
(ld): IRin
Mux=RY, ADDRin
Mux=DIN, RXin, Done
(st): IRin
Mux=RX, DOUTin
Mux=RY, ADDRin, W_D, Done
(not): IRin
(ldi): IRin
(shl): IRin
Mux=RX, Alu=transp,
Gin, Done
Mux=Mask,
R12in,
Done
Se !Z=>
Mux=Mask,
R12in, Done
Senão => Done
Mux=Ry, Alu=shl, Gin
Mux=G, RXin, Done
(shr): IRin
Mux=Ry, Alu=shr, Gin
(jmp): IRin
(jnz): IRin
Mux=G, RXin, Done
O registrador R12 é o contador de programa (PC), o qual provê o endereço de
memória de onde as instruções são lidas. Quando o Reseten é ativado o PC é colocado
em zero. No início de cada instrução (T0) o conteúdo de PC é usado como endereço de
uma instrução que está na memória. A instrução é armazenada em IR e o PC é
automaticamente incrementado para o ponto da próxima instrução (no caso da instrução
mvi o PC prove o endereço do dado imediato e é então incrementado novamente).
A unidade de controle utiliza o sinal incr_PC para indicar o incremento de PC, o
qual apenas habilita esse contador. Também é possível carregar diretamente um
endereço dentro de PC (R12) usando mv ou mvi tendo como destino o registrador R12.
Um exemplo de código que usa PC para implementar um loop é mostrado a seguir,
onde o texto depois de % em cada linha é apenas um comentário. A instrução mv
R2,R12 move para R2 o endereço de memória da instrução sub R1,R0. Então, a
instrução mvnz R12,R2 provoca a execução da instrução sub repetidamente até que R1
se torne zero.
mvi R0,#1
mvi R1,#10000000
mv R2,R12
sub R1,R0
mvnz R12,R2
% binary delay value
% save address of next instruction
% decrement delay count
% continue subtracting until delay count gets to 0
Reconfiguração de instruções:
Para configurar os estados de uma instrução é necessário configurar os 26 bits de
controle do datapath do processador conforme a seqüência abaixo.
ULA
3
R0in ... R12in
13
Mux
4
IR
1
A
1
G
1
Dout
1
Addr
1
wd
1
end
1
Todos os codops que possuem seus 8 bits iniciais iguais a „1‟ foram reservados
para executar instruções reconfiguradas (16 instruções ao todo). Ao decodificar o codop
da instrução atual, a unidade de controle deverá identificar se este é utilizado para
executar uma instrução presente no processador, ou se irá buscá-la na memória em um
endereço específico para cada instrução reconfigurável. Os codops reconfiguráveis
devem
Para diminuir a complexidade da configuração de instruções, a quantidade de
estados suportados por cada instrução foi limitada a 6. Com isso, é possível buscar cada
instrução reconfigurada, sabendo-se exatamente qual seu endereço inicial e a quantidade
total de estados utilizados. Isto evita que a unidade de reconfiguração necessite alterar a
tabela dinamicamente a cada vez que uma instrução é inserida ou removida.
Para inserir o programa contendo as instruções e os estados de cada instrução,
deve-se utilizar uma memória RAM, do tipo LPMRAM, de 32 bits de palavra,
disponível na biblioteca de componentes da ferramenta Quartus II, da Altera. Sugere-se
utilizar uma memória de 216 ou 232 endereços.
As instruções reconfiguradas serão inseridas no processador juntamente com o
restante do programa de execução. A memória deverá receber um arquivo .mif
(Memory Initialization File), que contém as instruções, dados e estados de configuração
utilizados no programa. As instruções de como utilizar um arquivo .mif podem ser
encontradas no help do Quartus II. Deve-se definir no .mif 3 áreas distintas: uma área de
instruções, uma área de dados e uma área de estados de configuração. As duas primeiras
serão definidas de acordo com o tamanho da LPM_RAM criada. A terceira área deverá
ter no mínimo 96 palavras (6 estados para cada uma das 16 instruções). Ao decodificar
uma instrução reconfigurada, a unidade de controle precisa saber qual o endereço do
primeiro estado de cada instrução. Desse modo, a unidade de controle deverá conter
uma tabela com os respectivos endereços de busca para cada codop. Exemplo: o codop
1111111100000000 (X”FF00”) poderá ser associado ao endereço de memória
X”E000”. O codop X”FF01” associado ao endereço X”E006”, e assim sucessivamente.
Caso a instrução não ocupe os 6 estados disponíveis, deve-se obrigatoriamente
setar o bit end da palavra de estado de configuração, que indica ao processador que a
instrução reconfigurável está concluída. Ao executar uma instrução reconfigurada, cada
vez que ocorre a busca de um estado, deve-se verificar o valor do bit end. Se positivo, a
instrução é terminada. Senão, verifica-se se foi atingido o limite de 6 estados. Quando o
limite for atendido, identificar o final da instrução.
Interface com a placa DE2.
- Utilização de 1 led (LEDG8) para indicar o fim da execução de 1 instrução.
- Utilização de 1 led (LEDR0) para indicar o fim da execução da instrução
HALT, ou seja, o fim do programa.
- Utilização de 2 botões: 1 para a função RESET (botão KEY3) e 1 para a
função RUN (botão KEY2).
- Utilização de 8 displays de 7 segmentos para exibir (em hexadecimal) o
conteúdo de partes do processador.
- Uso das chaves (SW0 a SW4) para selecionar qual parte deve ser exibido no
display de 7 segmentos. A Tabela 6 abaixo exibe as possíveis seleções.
Tabela 6. Chaves DE2 para selecionar o que será exigido no disply 7 segmentos
Chave
00000
00001
00010
00011
00100
00101
00110
00111
01000
01001
01010
01011
01100
01101
01111
10000
10101
10110
Outros
Valor Exibido
R0
R1
R2
R3
R4
R5
R6
R7
R8
R9
R10
R11
R12
Barramento
A
G
Saída do Mux
Saída da ULA
X"FFFFFFFF"
A Figura 3 representa o mecanismo de seleção através das chaves (SW0 a SW4)
para exibição dos conteúdos no display 7-segmengos.
MUX
32
Chaves da DE2
Barramento
Saída da ULA
...
Saída do Mux
R12
G
...
A
R0
56
Decoder:
7-Segmentos
FFFFFFFF
Figura 3. Interface Display de 7 Segmentos
Programando
No momento da compilação do código VHDL, um arquivo no formato .mif
inicializa a memória do processador com o programa que será executado. Desse modo,
a cada novo programa o projeto deve ser recompilado junto com o novo programa.
Também há uma restrição com relação ao nome do arquivo com o programa que
inicializará a memória, o qual deve está com o nome “programa.mif” para seja
carregado corretamente na memória.
Como ilustração vejamos um pequeno exemplo, que carrega um valor do
endereço #9 da memória e faz um laço de repetição até atingir o valor que foi carregado.
(1) mvi r5,#9 //armazena #9 em R5 (será endereço de memória)
(2) mvi r4,#1 //armazena #1 em R4
(3) ld r6,r5 //carrega da memória o valor do endereço em R5 e armazena em R6
(4) sub r6,r4 //subtrai valor de R6 por R4 e armazena em R6
(5) jnz #4
//se o resultado da subtração não for zero pula para endereço 4
(6) halt
//fim de programa
Para que esse programa seja executado no processador antes é necessário criar
seu código objeto equivalente e salvá-lo como “programa.mif”. Para cada instrução
temos
que
escrever
um
código
no
formato
(IIIIIIIIXXXXYYYYZZZZZZZZZZZZZZZZ) apresentado no início desse texto.
Então para a primeira instrução (mvi r5,#9) temos o codop ou IIIIIIII como 0x01
(utilizamos “0x” para indicar que estamos escrevendo um valor em hexadecimal). Para
indicar o registrador R5 (XXXX) temos o código 0x5. Como essa instrução não utiliza
um 2º. registrador então o valor YYYY fica em zero 0x0. E o valor constante do campo
ZZZZZZZZZZZZZZZZ fica com 0x0009. O resumo dessa instrução e das demais desse
exemplo são apresentadas na Tabela 7. Código objeto para o exemplo do laço, com os
valores em hexadecimal.
Tabela 7. Código objeto para o exemplo do laço
Instrução
mnemônica
mvi r5,#9
mvi r4,#1
ld r6,r5
sub r6,r4
jnz #4
halt
Codop
(IIIIIIII)
01
01
08
04
0C
1F
RX
(XXXX)
5
4
6
6
0
RY
(YYYY)
0
0
5
4
0
#D
0009
0001
0000
0000
000004
0000
Código
objeto
01500009
01400001
08650000
04640000
0C000004
1F000000
Agora vejamos um exemplo com um pouco mais de complexidade: um fatorial.
O algoritmo é apresentado a seguir.
Algoritmo Fatorial:
Início: Leia Acc;
A <= 1;
B <= 1;
C <= 1;
Acc <= Acc - C;
Se Acc = 0 Então
vá para Fim;
Fim Se;
Loop: B <= B + C;
A <= A * B;
Acc <= Acc - C;
Se Acc != 0 Então
vá para Loop;
Fim Se;
Fim: Acc <= A;
(01)
(02)
(03)
(04)
(05)
(06)
(07)
(08)
(09)
(10)
(11)
A implementação desse algoritmo utilizando o conjunto de instruções do
processador, considerando:
R0 = Acc
R1 = A
R2 = B
R3 = C
R4 = 1
R5 = 0
(0) mvi R11, End(FAT)
(1) ld R0, R11
(2) mvi R1, #1
(3) mvi R2, #1
(4) mvi R3, #1
(5) mvi R4, #1
(6) mvi R5, #0
(7) sub R0, R3
(Acc = Acc – C)
(8) jz #19
(Se Acc = 0 goto 19)
(9) add R2, R3
(B = B + C)
(10) mv R6, R1
(rotina para multiplicação)
(11) mv R7, R2
(12) sub R7, 1
(B = B – 1)
(13) jz PC #16
(Se B = 0, goto 16 )
(14) add R6, R1
(A = A + A)
(15) jmp PC#12
(va para 12)
(16) mv R1, R6
(17) sub R0, R3
(Acc = Acc – C)
(18) jnz PC, #9
(Se Acc != 0 goto 9)
(19) mv R0, R1
(Acc = A)
(20) halt
O código objeto equivalente para o exemplo do fatorial é o seguinte:
(0) mvi R11, End(FAT)
(1) ld R0, R11
(2) mvi R1, #1
(3) mvi R2, #1
(4) mvi R3, #1
(5) mvi R4, #1
(6) mvi R5, #0
(7) sub R0, R3
(8) jz #19
(9) add R2, R3
(10) mv R6, R1
(11) mv R7, R2
(12) sub R7, R4
(13) jz #16
(14) add R6, R1
(15) jmp #12
(16) mv R6, R1
(17) sub R0, R3
(18) jnz PC #9
(19) mv R0, R1
(20) halt
01B00020
080B0000
01100001
01200001
01300001
01400001
01500000
04030000
11000013
03230000
00610000
00720000
04740000
11000010
03610000
0B00000C
00160000
04030000
0C000009
00010000
1F000000
O formato do arquivo .mif possui um cabeçalho que informa a largura das
palavras da memória (WIDTH) e a quantidade de palavras (DEPTH), qual a base (ex:
HEX para hexadecimal) de representação dos endereços (ADDRESS_RADIX) e dos
dados (DATA_RADIX). Em seguida o conteúdo da memória deve está entre os
marcadores “CONTENT BEGIN” e “END;”. Cada palavra da memória é representada
pelo endereço (na base indicada antes) seguida por dois pontos e o valor (na base
indicada antes) terminado com um ponto-e-vígula. Para o exemplo do laço de repetição
o arquivo no formato .mif é mostrado a seguir.
WIDTH=32;
DEPTH=8192;
ADDRESS_RADIX=HEX;
DATA_RADIX=HEX;
CONTENT BEGIN
0000 : 0B000001;
0001 : 0150000A;
0002 : 01600001;
0003 : 00000000;
0004 : 04560000;
0005 : 0C000004;
0006 : 1F000000;
[0007 .. 1FFF] : 00000000;
END;
Referências
ALTERA.
Altera
Tutorials
and
Lab
Exercises.
Disponível
em:
http://www.altera.com/education/univ/materials/manual/unv-lab-manual.html. Acessado
em: set. de 2008.
ALTERA. DE2 Development and Education Board. Disponível em:
http://www.altera.com/education/univ/materials/boards/unv-de2-board.html. Acessado
em: set. de 2008.
Download