• Nenhum resultado encontrado

FPGA e CPLD

No documento Máquina virtual Java em FPGA (páginas 95-102)

4.4 Comparação entre FPGA, ASIC e CPLD

4.4.2 FPGA e CPLD

Um CPLD é a combinação de um array AND/OR completamente programável com um bloco de macro-células. O array é re-programável e desempenha uma grande variedade de funções lógicas, enquanto que as macro-células são blocos funcionais que desempenham lógica sequencial e combinatorial. É, tal como a FPGA, um dispositivo que permite alterar o design de um projeto instantanea- mente e sem custos [42]. Enquanto que os CPLD oferecem recursos lógicos com um maior número de inputs, as FPGA uma maior proporção de flip-flops para os recursos lógicos do que os CPLD. Portanto, as FPGA possuem uma capacidade lógica maior, sendo usadas em projetos maiores e complexos. São também mais apropriadas ao desenvolvimento de circuitos lógicos porque têm mais registos, enquanto que os CPLD são mais apropriados para aplicações de controlo. Estes dois tipos de dispositivos pertencem à classe de dispositivos FPD, que mudaram a forma como se desenvolve hardware, oferecendo baixos custos de implementa-

ção, baixo risco financeiro e possibilidade de realizar mudanças numa implemen- tação sempre que o programador desejar4[43].

4Deste conjunto de dispositivos também fazem parte os PLA, que contêm dois níveis de lógica,

um nível AND e um nível OR, ambos programáveis. Surgiram nos anos 70 do século XX, sendo os predecessores dos CPLD e FPGA.

Conceção, Implementação e Testes

A conceção deste projeto envolveu várias fases, estando este capítulo organizado de acordo com essas fases. No início procedeu-se ao estudo da máquina vir- tual Java, implementando um protótipo em linguagem C para se ter a noção de problemas ou das características inerentes à implementação desta esta máquina virtual. No decorrer dessa implementação desenvolveu-se um módulo de pré- -processamento do projeto que visa simplificar a execução da máquina virtual Java dentro da FPGA, nomeadamente no processo de comparação de strings. Posteriormente, foram implementados vários programas na FPGA Spartan-3E, para testar a melhor forma de transferir dados do computador para a FPGA, ar- mazenar esses dados dentro do dispositivo, conceber máquinas de estados efici- entes, em suma, testar os recursos da própria FPGA.

A primeira fase de implementação da máquina virtual Java em linguagem Veri- log traduziu-se em simulações, adaptando o código de acordo com os resultados simulados obtidos até obter uma máquina virtual funcional. No entanto, para se poder compilar o projeto dessa máquina virtual, foram feitas modificações ao código que possibilitaram a obtenção de um código sintetizável e a conse- quente programação da FPGA, e a implementação final da máquina virtual Java na FPGA.

O Spartan-3A Starter Kit foi introduzido durante a fase de implementação da máquina virtual Java na FPGA pois esta placa contém mais recursos que a da Spartan-3E (a placa Nexys2), nomeadamente um ecrã LCD que permite fazer de- bug ao código em execução, ajudando assim a melhorar o projeto. O ecrã LCD

também é importante para a execução de algumas instruções, nomeadamente para imprimir valores, pois fornece o meio necessário para essas instruções se- rem executadas com sucesso.

Note-se que o ponto de partida para a implementação desta máquina virtual Java é executar ficheiros class que pertencem a programas Java que contêm essen- cialmente operações sobre inteiros e operações de imprimir valores, resultados e strings.

5.1

Estudo inicial e módulo de pré-processamento

O primeiro passo deste projeto foi estudar a The Java Virtual Machine Specification [19] e perceber em que se transforma o código de um ficheiro Java depois de ser compilado. Criou-se um ficheiro de teste simples Teste.java, representado na figura 5.1, onde existem duas variáveis do tipo int que são somadas e é feito um print do resultado.

Figura 5.1: Ficheiro de teste Teste.java.

De acordo com a The Java Virtual Machine Specification, durante a compilação foi criado o ficheiro Teste.class, que contém os bytecodes associados a esse ficheiro Java. Através de um leitor de ficheiros binários, é possível visualizar o conteúdo do ficheiro class, parte deste ficheiro está ilustrado na figura 5.2.

Para se visualizar apenas os bytecodes e sem ser em formato binário é possível usar o comando “javap -c Teste.class” na linha de comandos, obtendo-se o output da figura 5.3.

Constata-se que existem dois métodos, o método de inicialização <init> e o método void main (String[]). Os opcodes presentes neste ficheiro class têm as seguintes funções:

Figura 5.2: Parte do ficheiro class resultante.

• <init>

aload_0(0x2a) - carrega uma referência para a stack a partir da vari- ável local 0;

invokespecial #1(0xb7) - invoca a instância do método no objeto objectref, onde o método é identificado por um índice de referência ao método na constant_pool (indexbyte1 < < 8 + indexbyte2), neste caso é 0001;

return(0xb1) - volta para a linha de execução do chamador sem de- volver um valor.

• void main (String[])

iconst_2(0x05) - guarda o valor inteiro (int) 2 na stack;

istore_1(0x3c) - guarda o valor do tipo int na variável local 1; iconst_4(0x07) - guarda o valor inteiro (int) 4 na stack;

istore_1(0x3d) - guarda o valor do tipo int na variável local 2; iload_1 (0x1b) - carrega um valor do tipo int a partir da variável local 1;

iload_2 (0x1c) - carrega um valor do tipo int a partir da variável local 2;

iadd(0x60) - adiciona dois inteiros;

istore_3(0x3e) - guarda o valor do tipo inteiro na variável local 3; getstatic #2(0xb2) - obtém o valor de um campo static de uma classe, onde o campo é identificado por uma referência do campo no índice (index1 < < 8 + index2) da constant_pool, neste caso é 0002;

iload_3 (0x1d) - carrega um valor do tipo int a partir da variável local 3;

invokevirtual #3 (0xb6) - este bytecode invoca o método virtual no objeto objectref, onde o método é identificado por um índice de referência ao método na constant_pool (indexbyte1 < < 8 + indexbyte2), neste caso é 0003;

return(0xb1) - volta para a linha de execução do chamador sem de- volver um valor.

Junto da designação de cada opcode está a sua representação numérica em formato hexadecimal, estando também os opcodes destacados na figura 5.4, para ilustrar a sua localização no ficheiro Teste.class.

Figura 5.4: Localização dos opcodes no ficheiro class.

De acordo com [19] e como já foi referido no Capítulo 3, a implementação correta da máquina virtual Java baseia-se em ser capaz de ler o ficheiro class e executar corretamente as operações nele contidas. A partir deste ponto desenvolveu-se um programa em linguagem C para ler corretamente o ficheiro class, imprimindo o resultado no ecrã. Os primeiros quatro bytes lidos são os do magic number CA- FEBABE, os quatro a seguir a minor_version e major_version, seguindo-se os dois bytes que indicam a constant_pool_count. Este número indica que existem 36 − 1 entradas na tabela constant_pool. A seguir, lê-se a informação contida nesta tabela. Um porção do output resultante está representado na figura

5.5 (note-se que o print “numero” não faz parte da constant_pool, só serve para fazer debug quanto à posição da tabela em que se está a ler).

Figura 5.5: Output da leitura do ficheiro class.

Então, o processo para descodificar o ficheiro class consiste em ler a quantidade de bytes definida na [19] para cada parâmetro presente nesse ficheiro. Para saber quais são os métodos a ser invocados ou quais os atributos presentes nas tabelas fields, methods ou attributes, é necessário comparar strings.

No documento Máquina virtual Java em FPGA (páginas 95-102)

Documentos relacionados