• Nenhum resultado encontrado

3.6 Desenvolvimento dos Módulos de Suporte

3.6.8 Softcore: Funções Base e Menu de Testes

Após a integração do MicroBlaze na FPGA foi necessário escrever em C a biblioteca de fun- ções realizadas em parceria com o FSL Interpreter. Essas funções são bastante simples, bastando na maioria dos casos uma escrita e leitura do barramento FSL. Outras merecem mais atenção, como é o caso da de cálculo das Raízes Quadradas.

Como vimos na secção anterior, a função implementada com o algoritmo CORDIC para calcu- lar Raízes Quadradas tem como entrada e saída um número inteiro. Como os cálculos no Softcore são realizados utilizando variáveis de vírgula flutuante, de 32 bits, foi necessário proceder a uma transformação destes números para inteiros e vice-versa. Esta transformação tem também de ter em conta que é necessário realizar duas escritas no barramento FSL para transmitir todos os 48 bits a calcular: uma escrita de 16bits+12 de comando e outra de 32 bits. Assim, a transformação de vírgula flutuante para inteiro sem sinal de 48bits e posterior transformação de 24 bits para vírgula flutuante, é realizada com os seguintes procedimentos:

1. Iterativa divisão do valor a calcular por 4.0 até este se tornar menor que 4.0. O número de iterações necessárias é guardado. Este passo coloca valores superiores a 4.0 no intervalo [1.0, 4.0[.

2. Iterativa multiplicação do valor a calcular por 4.0 até este se tornar maior ou igual a 1.0. O número de iterações necessárias é também guardado. Este passo coloca valores inferiores a 1.0 no intervalo [1.0, 4.0[. Todas as seguintes operações serão realizadas sobre este valor. Estes cálculos não introduzem perda de precisão por serem realizados numa variável de vírgula flutuante.

3. Multiplicação do valor obtido por 0x4000 e retipagem do resultado para inteiro, colocando assim a parte inteira do valor nos bits 16 e 15, e a parte decimal nos restantes 14 bits. Este

36 Plataforma de Desenvolvimento

4. Realização da mesma multiplicação em vírgula flutuante e subtracção do resultado ao valor original.

5. Multiplicação do valor obtido no passo anterior por 0x100000000 e retipagem do resultado para inteiro. Este passo produz uma variável de 32 bits correspondentes aos bits [15 a 46] da parte decimal do valor a calcular.

6. Envio por FSL dos dois inteiros obtidos nos passos anteriores.

7. Leitura do barramento FSL. Os 24 bits menos significativos contêm o resultado da operação. Como foi enviado um valor no formato [2 bits inteiros, 46 decimais], o resultado obtido está no formato [1 bit inteiro, 23 decimais].

8. É então realizada uma divisão em vírgula flutuante do valor obtido por 0x800000 e o resul- tado guardado numa variável de vírgula flutuante.

9. O valor é multiplicado então por 2i e dividido por 2j, em que i e j foram o número de iterações necessários nos passos 1 e 2, respectivamente.

Outra funcionalidade que mereceu mais cuidado foi a leitura de um grupo de pixéis da memó- ria. Um grupo de pixéis consiste num bloco de 5 x 5 pixéis. Como a memória está organizada em sectores com 4 bytes/pixéis de tamanho, a operação de ler um grupo necessita sempre de 10 opera- ções de leitura. Assim, ao analisar-se a imagem toda, tem de se realizar 640 · 480 · 10 = 3.072.000 operações de leitura da memória. Para diminuir o número de leituras existem duas soluções: ana- lisar a imagem horizontalmente linha a linha, lendo só os 5 pixéis da direita em cada ciclo, ou verticalmente coluna a coluna, analisando os 5 pixéis inferiores. Como uma leitura dos 5 pixéis inferiores representa só duas operações de leitura, ficou assim decidido que a imagem seria anali- sada verticalmente, coluna por coluna.

Após a implementação da optimização descrita, para a análise integral da imagem são neces- sários cerca de 640 · 480 · 2 = 614.400 operações de leitura.

De notar que por ser realizado varrimento vertical, este não pode ser realizado enquanto as câmaras estão a gravar imagens nas memórias, pois assim estaríamos a observar partes de um frame recente na parte superior e a parte inferior seria do frame anterior. Como o algoritmo de análise das imagens deverá correr em imagens estáticas, com as câmaras desligadas, este factor não é limitativo.

Foi também escrita uma biblioteca de funções para tratamento matricial. As funções simples de multiplicar e de inverter matrizes foram escritas de base, enquanto que a de calcular a SVD foi retirada de [7]. Esta última requer algumas funções, que foram escritas de base da forma mais simples possível para poupar espaço na memória de programas. As invocações às funções de cálculo da raiz quadrada foram substituídas pela função com o mesmo fim implementada em hardware com o algoritmo CORDIC

3.6 Desenvolvimento dos Módulos de Suporte 37

Todas as funções utilizadas foram alteradas para incluírem a escrita no barramento série de informação de depuração. Com o intuito de poupar memória, estas funções de escrita no barra- mento estão condicionadas a uma variável chamada DEBUG. Caso seja declarada como 0, todas as funcionalidades de depuração e teste não são incluídas, permitindo utilizar a memória libertada para outros fins.

A interface série permite ao utilizador controlar e visualizar em Runtime a execução dos al- goritmos, através de um menu. Este menu recebe comandos do utilizador, executando a função correspondente e mostrando todas as mensagens de depuração e é descrito no capítulo 5. Este menu foi constantemente alterado ao longo do desenvolvimento do capítulo seguinte, de forma a permitir o teste das funções e algoritmos implementados. No fim do desenvolvimento este menu

Capítulo 4

Solução Proposta

Este capítulo descreve a implementação dos módulos e funções que fazem parte da solução proposta. Será dada uma breve descrição geral da solução e de seguida é explicado cada módulo e função detalhadamente.

Documentos relacionados