Leonardo Augusto Casillo Metodologia para adaptação de microarquiteturas microprogramadas soft-core à uma ISA padrão: Estudo do Impacto sobre a complexidade de hardware para o padrão MIPS Tese de doutorado apresentada ao Programa de Pósgraduação em Engenharia Elétrica e de Computação da Universidade Federal do Rio Grande do Norte, como parte dos requisitos necessários para obtenção do grau de Doutor em Ciências. Natal, RN, julho de 2013 II UNIVERSIDADE FEDERAL DO RIO GRANDE DO NORTE- UFRN CENTRO DE TECNOLOGIA – CT PROGRAMA DE PÓS-GRADUAÇÃO EM ENGENHARIA ELÉTRICA E DE COMPUTAÇÃO Metodologia para adaptação de microarquiteturas microprogramadas soft-core à uma ISA padrão: Estudo do Impacto sobre a complexidade de hardware para o padrão MIPS Leonardo Augusto Casillo Orientador: Prof. Dr. Ivan Saraiva Silva Natal, RN, julho de 2013 UFRN / Biblioteca Central Zila Mamede. Catalogação da Publicação na Fonte. Casillo, Leonardo Augusto. Metodologia para adaptação de microarquiteturas microprogramadas soft-core à uma ISA padrão: estudo do impacto sobre a complexidade de hardware para o padrão MIPS. / Leonardo Augusto Casillo. – Natal, RN, 2013. 122 f.: il. Orientador: Prof. Dr. Ivan Saraiva Silva. Tese (Doutorado) – Universidade Federal do Rio Grande do Norte. Centro de Tecnologia. Programa de Pós-Graduação em Engenharia Elétrica e de Computação. 1. RISP - Processadores - Tese. 2. MIPS - Tese. 3. ISA - Tese. 4. Engenharia Elétrica e de Computação - Tese. I. Silva, Ivan Saraiva. II. Universidade Federal do Rio Grande do Norte. III. Título. RN/UF/BCZM CDU 004.23 III IV Agradecimentos Este não é apenas o texto final após um doutorado de 5 anos, mas um capítulo que se encerra de um sonho e parte de um projeto de vida que se iniciou em 1998, após a primeira aula do curso de engenharia de computação e ao final do discurso de motivação do saudoso coordenador Prof. Marcelo Mariano, quando tive a certeza de que queria seguir a vida acadêmica. Sou grato a todos os que me ajudaram, incentivaram e torceram por mim, e a todos os professores e profissionais que contribuíram com minha educação desde o ensino fundamental no Colégio Maristela, ensino médio no Inst. Maria Auxiliadora, graduação na UnP-Natal, mestrado e doutorado na UFRN. Não poderei listar aqui o nome de todos, mas de igual modo não posso deixar de manter impresso os meus profundos agradecimentos a algumas pessoas especiais que contribuíram diretamente para que este momento fosse possível. Agradeço a Deus pelo dom da vida, por ter me dado força, paciência, saúde e motivação quando foi necessário. Por mais que tenha tido algumas faltas, a religião e religiosidade foram extremamente importantes nesta caminhada. Um agradecimento especial ao Padre Lucas, que me acompanha desde minha primeira comunhão. Imagino que o sonho de quase todo pai era ter um filho doutor. Esta até era uma meta, mas a descoberta de não suportar ver sangue me fez procurar outros caminhos. Mas, desculpem a sinceridade, doutor é quem tem doutorado. Então, a meus pais Francisco e Cristina Casillo, que dedicaram sua vida para me dar a melhor saúde e educação possível, ofereço este título, todo o meu amor, carinho e gratidão, embora palavras não sejam suficientes para agradecer por tudo. Aproveito para agradecer a todos os meus familiares próximos por terem aguentado 60 meses de mau-humor em um nível ainda maior do que o habitual. A má notícia é que o stress continuou, apenas os motivos é que são de natureza diferente. Portanto, para minha irmã Lígia, meu cunhado Tarcísio, meus sobrinhos Yasmim e Rafael, meus sogros Danilo e Cícera, minha cunhada Danise e seu marido Emanuel, obrigado pela paciência. V Estudei muito na minha graduação, me esforcei ao máximo, mas sempre exigi que esta dedicação fosse uma via de mão dupla. Admito também que não a pessoa mais fácil para se conviver. Talvez por isso tenha discutido com quase todos os meus professores. Minhas desculpas e agradecimentos aos professores Aarão, Alan, Antônio, Oscar e demais por todos os ensinamentos e conselhos durante minha jornada acadêmica. E foi em uma destas brigas que ganhei uma orientadora e amiga. Professora Nádja Santiago, muito deste título eu devo a você. Muito obrigado por tudo. Nádja também me apresentou a seu orientador após o término de meu TCC. E sem nunca ter me visto anteriormente, me aceitou como aluno de mestrado. E mesmo após algumas dificuldades e tribulações, novamente me aceitou como aluno de doutorado. Novas dificuldades, afastamento de ambos para cidades diferentes, mas ainda assim assumiu os riscos de continuar sendo meu orientador. Portanto, divido esta conquista e agradeço ao Prof. Ivan Saraiva por confiar em mim e por permitir e me ajudar na concretização deste objetivo. Agradeço também a todos os coordenadores e colegas das instituições de ensino em que estive como professor: UFRN, FAL, FATERN e UERN, onde a troca de experiências e convivência profissional reforçou ainda mais minha paixão pela sala de aula. Em 2009 ingressei como professor efetivo da UFERSA / Mossoró, e encarei o desafio de conciliar as pesquisas com atividades de ensino. Agradeço aos coordenadores do curso durante este período, professores Judson e Danniel, e ao corpo docente que compreendeu minha situação, dando suporte e apoio para concluir meu trabalho. Neste período tive muitos alunos. Pela carga de trabalho pesada, nem sempre pude corresponder em sala de aula às expectativas dos alunos e ministrar as disciplinas da melhor maneira possível. O meu agradecimento especial aos meus orientandos de TCC e iniciação científica Álamo, Dênis, Julyana, Cadu, Wilka e Valter. O lado gratificante é constatar que alunos podem se tornar amigos. Deixo para o final meu agradecimento para a maior incentivadora de meu trabalho. A pessoa que me deu forças, sofreu ao meu lado em todos os momentos difíceis, aguentou todas as cargas de stress, não me deixou desistir nas várias vezes em que fraquejei. Foi minha esposa, protetora, professora, revisora, companheira e melhor amiga. Para o meu amor Danielle Simone, também não cabem palavras para agradecer tudo o que você fez por mim. Esta vitória é nossa. Este mérito também é seu. Agora somos um casal de doutores e que sejamos sempre uma família feliz. Te amo e obrigado por tudo. VI Resumo No meio acadêmico, é comum a criação de processadores denominados didáticos, voltados para práticas de disciplinas de hardware na área de Computação e que podem ser utilizados como plataformas em disciplinas de softwares, sistemas operacionais e compiladores. Muitas vezes, tais processadores são descritos sem uma ISA padrão, o que exige a criação de compiladores e outros softwares básicos para prover a interface hardware/software dificultando sua integração com outros processadores e demais dispositivos. Utilizar dispositivos reconfiguráveis descritos em uma linguagem do tipo HDL permitem a criação ou modificação de qualquer componente da microarquitetura, ocasionando a alteração das unidades funcionais do caminho de dados que representa a parte operativa de um processador, bem como da máquina de estados que implementa a unidade de controle do mesmo conforme surgem novas necessidades. Em particular, os processadores RISP possibilitam a alteração das instruções da máquina, permitindo inserir ou modificar instruções, podendo até mesmo se adaptar a uma nova arquitetura. Este trabalho aborda como objeto de estudo dois processadores didáticos soft-core descritos em VHDL com diferentes níveis de complexidade de hardware adaptados a uma ISA padrão a partir de uma metodologia proposta sem provocar aumento no nível de complexidade do hardware, ou seja, sem o acréscimo significativo da área em chip, ao mesmo tempo em que o seu nível de desempenho na execução de aplicações permanece inalterado ou é aprimorado. As modificações também permitem afirmar que, além de ser possível substituir a arquitetura de um processador sem alterar sua organização, um processador RISP pode alternar entre diferentes conjuntos de instrução, o que pode ser expandido para alternância entre diferentes ISAs, permitindo a um mesmo processador se tornar uma arquitetura híbrida adaptativa, passível de ser utilizada em sistemas embarcados e ambientes multiprocessados heterogêneos. Palavras-chave: RISP, MIPS, reconfiguração de instruções, adaptação de ISA VII Abstract In academia, it is common to create didactic processors, facing practical disciplines in the area of Hardware Computer and can be used as subjects in software platforms, operating systems and compilers. Often, these processors are described without ISA standard, which requires the creation of compilers and other basic software to provide the hardware / software interface and hinder their integration with other processors and devices. Using reconfigurable devices described in a HDL language allows the creation or modification of any microarchitecture component, leading to alteration of the functional units of data path processor as well as the state machine that implements the control unit even as new needs arise. In particular, processors RISP enable modification of machine instructions, allowing entering or modifying instructions, and may even adapt to a new architecture. This work, as the object of study addressing educational soft-core processors described in VHDL, from a proposed methodology and its application on two processors with different complexity levels, shows that it’s possible to tailor processors for a standard ISA without causing an increase in the level hardware complexity, ie without significant increase in chip area, while its level of performance in the application execution remains unchanged or is enhanced. The implementations also allow us to say that besides being possible to replace the architecture of a processor without changing its organization, RISP processor can switch between different instruction sets, which can be expanded to toggle between different ISAs, allowing a single processor become adaptive hybrid architecture, which can be used in embedded systems and heterogeneous multiprocessor environments. Keywords: RISP, MIPS, instruction set configurations, ISA adaptation VIII Sumário Capítulo 1 – Introdução .................................................................................................... 1 1.1. Motivação .......................................................................................................... 3 1.2. Objetivos ............................................................................................................ 6 1.3. Estrutura do documento ..................................................................................... 7 Capítulo 2 – Fundamentação Teórica ............................................................................... 8 2.1. Processadores Acadêmicos ................................................................................ 8 2.2. Processadores Reconfiguráveis ........................................................................ 13 2.3. Processadores RISP ......................................................................................... 17 2.4. Processadores soft-core.................................................................................... 18 2.5. Processadores microprogramados .................................................................... 19 2.6. Arquitetura MIPS ............................................................................................. 20 2.7. Processadores MIPS ........................................................................................ 27 2.8. Considerações .................................................................................................. 30 Capítulo 3 – Estado da arte ............................................................................................. 32 3.1. Tradução Binária.............................................................................................. 33 3.2. Considerações .................................................................................................. 39 Capítulo 4 – Microarquiteturas microprogramadas propostas........................................ 40 4.1 Processador CABARE ..................................................................................... 40 4.1.1. Reconfiguração de instruções .............................................................................. 45 4.1.2. Exemplo de funcionamento ................................................................................. 49 4.2. Processador CRASIS ....................................................................................... 51 4.2.1. Modos de funcionamento .................................................................................... 54 4.2.2. Exemplo de funcionamento ................................................................................. 58 4.2.3. Unidade de Reconfiguração ................................................................................ 61 4.2.4. Exemplo de reconfiguração ................................................................................. 63 4.3. Interface com a placa DE2 ............................................................................... 63 Capítulo 5 – Metodologia para adaptação a uma ISA padrão ........................................ 65 5.1. Registradores ................................................................................................... 67 5.2. Unidade Lógica e Aritmética ........................................................................... 68 5.3. Instruções de Branch ....................................................................................... 71 IX 5.4. Comunicação com a memória.......................................................................... 72 5.5. Instruções load/store ........................................................................................ 73 5.6. Considerações .................................................................................................. 73 Capítulo 6 – Aplicações e Resultados ............................................................................ 74 6.1. Adaptação 1: Processador DIMBA .................................................................. 74 6.1.1. Registradores ....................................................................................................... 75 6.1.2. ULA..................................................................................................................... 75 6.1.3. Instruções de Branch ........................................................................................... 76 6.1.4. Comunicação com a memória ............................................................................. 77 6.1.5. Instruções de Load/Store ..................................................................................... 77 6.1.6. Reconfiguração.................................................................................................... 78 6.1.7. Análise Comparativa ........................................................................................... 83 6.2. Adaptação 2: Processador CRASIS II ............................................................. 85 6.2.1. Registradores ....................................................................................................... 85 6.2.2. ULA..................................................................................................................... 86 6.2.3. Instruções de Branch ........................................................................................... 86 6.2.4. Comunicação com a memória ............................................................................. 87 6.2.5. Instruções de Load/Store ..................................................................................... 87 6.2.6. Reconfiguração.................................................................................................... 87 6.2.7. Análise Comparativa ........................................................................................... 89 6.3. Exemplo de uma aplicação .............................................................................. 92 6.4. Considerações .................................................................................................. 95 Capítulo 7 – Conclusões e Perspectivas ......................................................................... 97 7.1. Trabalhos Futuros ............................................................................................ 99 Referências Bibliográficas ............................................................................................ 101 Apêndice A - Codificação dos formatos de Instruções no MIPS-I .............................. 105 Apêndice B - Codificação dos formatos de Operações no CRASIS ............................ 107 X Lista de Figuras Figura 2.1 – Modelo de máquinas multinível ................................................................... 9 Figura 2.2 – Arquitetura MIC-1 ..................................................................................... 11 Figura 2.3 – Configuração básica de um FPGA ............................................................. 14 Figura 2.4 – Exemplo de um modelo de arquitetura RISP ............................................. 17 Figura 2.5 – processador PLASMA ............................................................................... 19 Figura 2.6 – Diagrama de blocos de um pipeline MIPS ................................................. 27 Figura 2.7 –MIPS monociclo ......................................................................................... 27 Figura 2.8 –MIPS multiciclo .......................................................................................... 28 Figura 2.9 –MIPS pipeline.............................................................................................. 29 Figura 3.1 – Mecanismo de tradução binária em dois níve ............................................ 34 Figura 3.2 – Unidades do mecanismo de tradução binária ............................................. 35 Figura 3.3 – Configuração de uma unidade reconfigurável da arquitetura DIM ........... 38 Figura 4.1 - Arquitetura do processador CABARE ........................................................ 41 Figura 4.2 – Distribuição de memória no CABARE ...................................................... 46 Figura 4.3 – Sequência de execução de instruções reconfiguradas no CABARE .......... 48 Figura 4.4 – Diagrama de blocos do processador CRASIS ............................................ 51 Figura 4.5 – Formatos de instrução do CRASIS ............................................................ 52 Figura 4.6 – Arquitetura do processador CRASIS ......................................................... 53 Figura 4.7 – Diagrama de estados simplificado do CRASIS ......................................... 54 Figura 4.8 – Diagrama de estados de um super-estado .................................................. 56 Figura 4.9 – Exemplo de execução de instrução no CRASIS ........................................ 58 Figura 4.10 – Unidade de Reconfiguração do CRASIS ................................................. 61 Figura 4.11 – diagrama de estados de reconfiguração no CRASIS................................ 62 Figura 5.1 - Fluxograma de multiplicação por algoritmo de Booth ............................... 69 Figura 5.2 – Fluxograma de uma divisão por algoritmo de Booth ................................. 70 Figura 6.1 – Visão geral do processador DIMBA .......................................................... 74 Figura 6.2 – Áreas de memória do processador DIMBA ............................................... 79 Figura 6.3 – Codificação da instrução MFHI ................................................................. 81 XI Figura 6.4 – Codificação da instrução ADD .................................................................. 82 Figura 6.5 – Comparação do caminho de dados (a) CABARE x (b) DIMBA ............... 83 Figura 6.6 – Visão geral do CRASIS II .......................................................................... 85 Figura 6.7 – Comparação do caminho de dados (a) CRASIS I x (b) CRASIS II........... 90 Figura 6.8 – Processo de simulação de um algoritmo no CABARE .............................. 94 Figura 6.9 – Processo de simulação de um algoritmo no DIMBA ................................. 95 XII Lista de Tabelas Tabela 2.1 Formato de instruções MIPS ........................................................................ 22 Tabela 2.2 Descrição das convenções de uso dos registradores do MIPS ..................... 24 Tabela 2.3 Conjunto de instruções MIPS-1 .................................................................... 26 Tabela 4.1 – Registradores de uso geral no CABARE ................................................... 42 Tabela 4.2 – Operações da ULA do CABARE .............................................................. 42 Tabela 4.3 – Operações realizadas pelo processador CABARE .................................... 43 Tabela 4.4 – Sinais do controle do CABARE em cada instrução/tempo ....................... 44 Tabela 4.5 - Configuração de uma microinstrução no CABARE .................................. 47 Tabela 4.6 – Formatos de microinstruções do CABARE ............................................... 48 Tabela 4.7 – Código objeto para o exemplo 1 ................................................................ 50 Tabela 4.8 – Operações realizadas pelo processador CRASIS ...................................... 55 Tabela 4.9 – Palavra de uma microinstrução no CRASIS .............................................. 59 Tabela 4.10 – Bits de controle do CRASIS .................................................................... 59 Tabela 4.11 – Chaves para seleção dos displays de 7 segmentos na DE2 ..................... 64 Tabela 6.1 – Operações da ULA do DIMBA ................................................................. 75 Tabela 6.2 – Formatos de microinstruções do DIMBA.................................................. 79 Tabela 6.3 – Formato de uma microinstrução no DIMBA ............................................. 80 Tabela 6.4 – Síntese dos processadores CABARE e DIMBA ....................................... 84 Tabela 6.5 – Palavra de uma microinstrução no CRASIS II .......................................... 88 Tabela 6.6 – Síntese do processador variando conjuntos de instruções ......................... 91 XIII Lista de Abreviaturas ALU – Arithmetic Logic Unit ASIC – Application Specific Integrated Circuit ASIP – Application Specific Instruction set Processor CABARE – Computador Acadêmico Básico com Reconfiguração CISC – Complex Instruction Set Computer CLB – Configurable Logic Blocks CodOp – Código da Instrução CRASIS – Computer with Reconfigurable And Selectable Instruction Set CRIS – Computer with Reconfigurable Instruction Set CRISP – Configurable and Reconfigurable Instruction Set Processor DCM - Digital Clock Manager DIMBA – Didactic MIPS Basic Architecture EEPROM –Electrically-Erasable Programmable Read-Only Memory FFUs – Fixed Functional Units FPGAS – Field Programmable Gate Arrays FSM – Finite State Machine HDL – Linguagens de Descrição de Hardware IOB – Input/Output Blocks IP – Propriedade Intelectual ISA – Instruction Set Architectures IJVM - Integer Java Virtual Machine JTAG - Joint Test Action Group LPM_RAM – Library of Parameterized Modules RAM LUI – Load Upper Immediate MAC – Multiplicador e Acumulador MAR – Memory Address Register MBR – Memory Buffer Register MFHI – Move From HI Register XIV MIF – Memory Initialization File MIPS (ISA) – Microprocessor without Interlocked Pipeline Stages MIPS (Métrica) – Milhões de Instruções Por Segundo MPSoC – Multiprocessor System On Chip MSB – Most Significative Bit OCP – Open Core Protocol PBL – Problem-Based Learning PC – Personal Computer PRISC – PRogrammable Instruction Set Computer PRISM – Processor Reconfigurable through Instruction-Set Metamorphosis RFU – Reconfigurable Functional Unit RISC – Reduced Instruction Set Computer RISP – Reconfigurable Instruction Set Processor RTL – Register Transfer Level SoC – System on Chip SP – Stack Pointer SPARC - Scalable Processor ARChitectures SRC – Shift Right with Carry TIPI – Tiny Instruction Processors and Interconnect ULA – Unidade Lógica e Aritmética US – Microssegundos (unidade) VISC – Variable Instruction Set Communications Architecture VLIW – Very Long Instruction Word XV Capítulo 1 – Introdução Desde a década de 2000 até os dias atuais, a tecnologia aplicada aos processadores está relacionada à era dos multicores [Knight, 2005]. De fato, nos últimos anos a justificativa para se adquirir um novo computador pessoal era o aumento da sua frequência de operação ou uma nova placa-mãe que suportasse maiores quantidades de memória. Com o limite de velocidade de operações praticamente estagnado em virtude das limitações físicas dos equipamentos, por exemplo, quanto à sua dissipação de calor, buscou-se a inserção de diversos núcleos para continuar com o progresso em relação ao desempenho e também continuar a movimentar o mercado financeiro quanto à venda de computadores. Atualmente, é notório que os computadores pessoais do tipo PC (Personal Computer) estão sendo substituídos por versões portáteis como netbooks, ultrabooks, tablets, smartphones e demais dispositivos móveis, que suprem as necessidades de pessoas que querem utilizar recursos simples como aplicativos para escritório e redes sociais, restando aos PCs e notebooks multicores para o nicho de mercado composto por engenheiros, cientistas e demais profissionais que requerem aplicativos que demandem maior desempenho computacional como ferramentas de desenho técnico, computação gráfica e programação. Entretanto, os computadores não são utilizados apenas nos meios industriais e comerciais. A área acadêmica é fundamental para a pesquisa por novas formas de tecnologias e estudos para aprimoramento dos hardwares e softwares necessários para sua utilização. Em cursos como Ciência e Engenharia da Computação ou demais cursos em áreas afins de tecnologia, é fundamental que professores e estudantes conheçam o funcionamento de cada componente eletrônico que compõe a arquitetura de um computador, suas linguagens de programação em vários níveis de abstração e os softwares básicos que proveem sua utilização, tais como compiladores e sistemas operacionais, além de ferramentas para simulação e prototipagem de tais dispositivos 1 para a realização de testes quanto à sua funcionalidade. Nesse sentido, muitas universidades estão propondo a seus alunos a criação de arquiteturas próprias, denominadas arquiteturas didáticas ou processadores acadêmicos. Tais processadores são, em sua maioria, do tipo RISC (Reduced Instruction Set Computer), e são úteis para algumas disciplinas nos cursos de graduação da área de computação, como sistemas digitais, arquitetura de computadores, sistemas operacionais, softwares básicos, compiladores, entre outras disciplinas de hardware e software que envolvam o projeto e construção de circuitos digitais e o suporte para o desenvolvimento de suas aplicações. Atualmente, estas arquiteturas podem ser facilmente descritas devido ao uso de dispositivos reconfiguráveis como FPGAS (Field Programmable Gate Arrays), que surgiram na década de 1980 [Carter et al., 1986] e hoje já está consolidada no meio acadêmico. Tais dispositivos, entre outras vantagens, permitem a descrição, simulação e síntese de circuitos digitais de qualquer nível de complexidade de hardware – desde que respeitando os limites físicos de cada dispositivo – em campo, podendo ser modificado a qualquer momento, sem a necessidade da fabricação do chip como um processador de uso geral ou um processador ASIC (Application Specific Integrated Circuit) [Compton & Hauck, 2002]. Explorar as capacidades de dispositivos reconfiguráveis impulsiona o uso de processadores implementados apenas por meio de Linguagens de Descrição de Hardware (HDL), geralmente chamados de Soft-core. Este modelo permite a projetistas e estudantes criarem novas unidades funcionais e alterar arquiteturas anteriormente criadas [Tong et al., 2006]. A liberdade quanto à descrição dos componentes do caminho de dados de um processador acadêmico, sem a necessidade de seguir determinado padrão, provem a cada processador características próprias que o fazem único. Tais características podem suprir a falta de alguma funcionalidade em um sistema embarcado ou ainda um processador pode ser útil para o desenvolvimento de alguma aplicação ou para a execução de programas específicos atuando no modo stand alone. Mas a falta de padronização de sua arquitetura ou conjunto de instruções pode inviabilizar o uso deste processador em um sistema multiprocessador heterogêneo ou se tornar incompatível com demais sistemas físicos ou ainda outros experimentos microarquiteturais acadêmicos desenvolvidos por outros alunos ou universidades. Com relação ao desenvolvimento e execução de programas, deverão ser desenvolvidos compiladores 2 para permitir a tradução de programas desenvolvidos em linguagens de alto nível como C ou Java para a linguagem assembly adotada por cada microarquitetura e simuladores para verificar o correto funcionamento da execução de suas instruções. Estes problemas de compatibilidade podem ser resolvidos utilizando padrões conhecidos de Arquiteturas de Conjunto de Instruções (ISA – Instruction Set Architectures). Com a adoção de uma ISA, é possível utilizar compiladores já desenvolvidos e inserir o processador em um ambiente MPSoC (Multiprocessor System On Chip) [Kumar, 2005] heterogêneo de ISA única. As modificações para um processador se adaptar ao padrão de uma ISA estão relacionadas à utilização de um conjunto de instruções específico e algumas restrições em seu caminho de dados, como a quantidade mínima de registradores e do tamanho da palavra de dados. 1.1. Motivação No meio acadêmico, processadores sem uma ISA padrão dificultam a sua utilização em aulas práticas, exigindo a criação de compiladores e outros softwares básicos como assemblers, loaders e linkers para prover a interface hardware/software, sendo necessária também a disseminação de tais programas para permitir a outros usuários a utilização da arquitetura. Caso contrário, será necessário escrever programas para tais arquiteturas utilizando a linguagem assembly, com os formatos e instruções específicas criadas para esta arquitetura, sem a opção de reutilização de código em outros processadores. A Computação Reconfigurável, ao propiciar a criação ou modificação de qualquer processador descrito em uma linguagem do tipo HDL, permite que o caminho de dados ou a máquina de estados que implementa a unidade de controle possam ser reescritos e alterados conforme surgem novas necessidades. A Computação Reconfigurável é um paradigma de computação que combina a flexibilidade do software com o alto desempenho do hardware [Compton, 2002]. Por causa de suas duas principais características (desempenho e flexibilidade), dispositivos reconfiguráveis são utilizados para projetar desde um simples circuito lógico contendo apenas alguns elementos lógicos até sistemas complexos como arquiteturas SoC (System on Chip), processadores ASIC, Sistemas Embarcados ou demais arquiteturas adaptativas, não convencionais e acadêmicas. Esses sistemas computacionais podem ser utilizados em uma vasta gama de aplicações, incluindo sistemas embarcados, industriais, pessoais e computação móvel 3 [Ferlin & Pilla, 2006]. Além destas, o uso de FPGAs está em crescimento no suporte às ferramentas de ensino em disciplinas de graduação em Computação. A possibilidade de explorar o desenvolvimento de sistemas digitais em diferentes níveis de complexidade, da especificação à prototipagem, permite aos alunos uma melhor compreensão de requisitos de hardware e software. O processo de criação de uma nova microarquitetura não precisa seguir uma metodologia específica ou conter uma ISA padrão. No entanto, embora permita uma maior liberdade de criação ao projetista de hardware, possibilitando o desenvolvimento de novos circuitos digitais ou mesmo arquiteturas não convencionais, isto dificulta a utilização destes sistemas digitais em MPSoCs ou sistemas embarcados, devido a limitações da sua compatibilidade com outros sistemas de arquiteturas. Já em relação ao meio acadêmico, experimentos genéricos de microarquiteturas sem um padrão de instruções torna o processador um modelo isolado, necessitando de diversas adaptações de hardware e software para que tal modelo possa se comunicar com outros processadores, co-processadores ou demais componentes físicos e executar programas, além de restringir o uso de compiladores e simuladores disponíveis para arquiteturas já fundamentadas como MIPS, SPARC, ARM e x86. Dependendo da quantidade de alterações em seu caminho de dados, este pode se tornar até mesmo um novo processador e perder suas características próprias. Duas técnicas podem ser utilizadas para minimizar este problema. A primeira é a utilização de microprogramas para a descrição de um processador Soft-Core. As arquiteturas microprogramadas fazem com que todo o ciclo de funcionamento de um processador esteja descrito em VHDL como se fosse a sequência de um programa descrito de forma estrutural. Com isso, todas as etapas de busca, decodificação, execução, salvamento e interrupção estão presentes dentro da unidade de controle do processador, que por um lado aumenta sua complexidade em hardware, mas por outro lado torna o caminho de dados do processador - unidade operativa ou Datapath - com sua estrutura preservada ou com poucas modificações caso sejam necessários incluir, remover ou alterar suas funcionalidades. A segunda técnica é um complemento da anterior, que pode tornar o processador ainda mais independente quanto à complexidade de seu caminho de dados, sendo possível aumentar sua capacidade operacional quanto à execução de instruções. Tal técnica se refere à inclusão de uma lógica de reconfiguração, fazendo com que a arquitetura didática se torne um processador do tipo RISP (Reconfigurable Instruction 4 Set Processor). Processadores RISP podem criar ou combinar novas instruções em tempo de execução para serem utilizadas juntamente com o conjunto de instruções de uma ISA padrão [Barat & Lauwereins, 2000]. Uma vez que os processadores didáticos foram descritos utilizando-se HDL’s, tais modificações em sua estrutura física podem ser realizadas a partir do reuso de componentes e estruturas previamente implementadas. Este estudo propõe uma metodologia para adaptação de arquiteturas microprogramadas Soft-Core descritas em VHDL sem um padrão para uma determinada ISA, na qual são identificadas quais as alterações necessárias em suas unidades operativas para que seja possível executar as instruções pertencentes ao seu novo conjunto de instruções, sem perder suas características originais ou aumentar seu nível de complexidade de hardware. Para aplicação desta metodologia, foram utilizadas duas microarquiteturas microprogramadas descritas na linguagem VHDL, com diferentes caminhos de dados, sendo ambas adaptadas à arquitetura MIPS (Microprocessor without Interlocked Pipeline Stages) [MIPS, 2008], e utilizando o conjunto de instruções MIPS-I. O padrão MIPS foi escolhido em virtude de sua vasta utilização acadêmica, sendo sua arquitetura RISC e suas alternativas de implementação com modos monociclo, multiciclo e pipeline utilizadas adotadas como plataformas de ensino em livros de arquitetura de computadores, como em [Patterson, 2008], que permitem transmitir as noções básicas de como um processador é projetado e implementado. Sua arquitetura possui vários níveis ascendentes de conjuntos de instruções, de acordo com o aumento de sua complexidade de hardware, incluindo as versões MIPS I a MIPS V, com versões em 32 e 64 bits [Sweetman, 2006]. Além de sua simplicidade e clareza, a arquitetura base para construção de vários simuladores, como ProcSIM [ProcSIM, 2013], MARS [MARS, 2013], WebSimple [WebSimple, 2013], SPIM [Larus, 2013], entre outros, e influenciou outras ISAs como a SPARC (Scalable Processor ARChitectures), desenvolvida pela Sun Microsystems® [Oracle, 2013]. Em adição, será provado que é possível que uma microarquitetura se torne um processador RISP, possibilitando a utilização de instruções não presentes ao seu conjunto original, ou seja, prover instruções MIPS que não estejam incluídas no conjunto de instruções do processador, aumentando sua gama de aplicações, desde que o caminho de dados do processador possua os componentes e a estrutura necessária para executar corretamente as novas instruções. Por serem arquiteturas microprogramáveis, 5 ao incluir novas unidades de execução como comparadores, multiplicadores ou operações na ULA (Unidade Lógica e Aritmética), são necessárias poucas adaptações no código de descrição de suas unidades de controle, como a inclusão de novos sinais de controle ou a criação de microprogramas que proveem o funcionamento de novas instruções com base nas unidades funcionais anexadas ou a partir da lógica de reconfiguração incorporada ao processador. É importante ressaltar que a metodologia proposta neste trabalho não busca substituir a metodologia de ensino de arquitetura de computadores ou disciplinas correlatas, mas sim apresentar uma forma de adaptar processadores pré-existentes com estrutura genérica ou com uma determinada arquitetura a um novo padrão, preservando as características físicas originais da microarquitetura, propiciando a estudantes e pesquisadores uma nova ferramenta de auxílio durante suas práticas de ensino, além de aumentar a gama de aplicações e exploração de projetos em seus experimentos arquiteturais acadêmicos. Até o momento da finalização deste documento, não foram encontrados na literatura outros trabalhos que tenham por objetivo a adaptação de arquiteturas ou de conjuntos de instruções a uma ISA padrão utilizando dispositivos reconfiguráveis microprogramados. 1.2. Objetivos Esta tese consiste em apresentar uma metodologia para adaptação de processadores microprogramados para o padrão MIPS. Para tanto, foram utilizados dois processadores acadêmicos RISC genéricos microprogramados como estudos de caso para a aplicação dos passos necessários, a fim de que o novo padrão de arquitetura e o conjunto de instruções MIPS-I possam ser executados nas novas versões de suas microarquiteturas. A obtenção de tal objetivo decorre das seguintes etapas: A partir do processador CABARE (Computador Acadêmico Básico com Reconfiguração), criar o processador DIMBA (Didactic MIPS Basic Architecture); A partir do processador CRASIS (Computer with Reconfigurable And Selectable Instruction Set), criar o processador CRASIS II; Comparar cada versão original com sua versão adaptada MIPS, apresentando as modificações quanto a área em chip e alterações na 6 execução de uma aplicação sequencial com relação a quantidade de ciclos de relógio; Mostrar como os processadores DIMBA e CRASIS II podem incorporar e executar instruções MIPS além das que foram previamente inseridas no conjunto de instruções de suas arquiteturas. 1.3. Estrutura do documento Os capítulos foram dispostos da seguinte forma: Capítulo 1: este primeiro capítulo introduziu o assunto, abordou a motivação para a realização do presente trabalho bem como os objetivos deste estudo e apresentou a organização do texto. Capítulo 2: neste capítulo é realizada uma fundamentação teórica abordando conceitos gerais sobre processadores reconfiguráveis, em especial processadores RISP, o que são arquiteturas microprogramadas e uma abordagem sobre o padrão MIPS e o conjunto de instruções MIPS-I. Capítulo 3: será descrito o estado da arte sobre adaptação, conversão ou tradução entre diferentes ISA’s em hardware e software. Capítulo 4: serão apresentadas as características básicas de dois processadores soft-core, RISP sem uma ISA padrão. Capítulo 5: será apresentada a metodologia utilizada para adaptar os processadores anteriormente descritos para uma Arquitetura de Conjunto de Instruções padrão, utilizando como base a arquitetura MIPS. Capítulo 6: apresenta os estudos de caso após as modificações propostas, detalhando o funcionamento das novas arquiteturas e comparando as versões adaptadas com as versões originais. Capítulo 7: são expostas as conclusões e perspectivas futuras sobre as afirmações, processadores e metodologias abordadas. 7 Capítulo 2 – Fundamentação Teórica 2. Neste capítulo são descritos alguns conceitos acerca de processadores reconfiguráveis, soft-core, microprogramados e RISP, além de abordar com mais detalhes o padrão de arquitetura MIPS e seu conjunto de instruções MIPS-I. 2.1. Processadores Acadêmicos Os processadores acadêmicos, também denominados processadores didáticos, são comumente desenvolvidos por alunos e professores da área de hardware de cursos de ciências e engenharia de computação, como exercícios práticos envolvendo os aspectos de arquitetura e organização de computadores ou plataformas de ensino para a execução de programas em linguagens de baixo nível e desenvolvimento de softwares básicos e simuladores. A popularização e redução dos custos de kits de desenvolvimentos em FPGAs propiciam um maior estímulo de estudantes e pesquisadores no projeto e implementação destes experimentos microarquiteturais, por meio da descrição de módulos dos processadores utilizando alguma linguagem de descrição de hardware e simulação e síntese de tais arquivos em dispositivos reconfiguráveis por meio de softwares específicos de acordo com seu fabricante, como por exemplo, o Quartus II da Altera® [Altera, 2013]. A primeira etapa de qualquer curso de arquitetura e organização de computadores é estabelecer a diferença entre os dois conceitos. Por arquitetura, [Stallings, 2010] afirma que são os atributos visíveis para o programador, podendo citar como exemplos o conjunto de instruções da máquina, o conjunto de registradores, as técnicas de endereçamento á memória, mecanismos de Entrada e Saída (E/S) e representação dos dados. A organização de um computador especifica as unidades funcionais e suas formas de interconexão para a implementação de uma determinada arquitetura, ou seja, a organização refere-se à implementação de uma arquitetura. Dentre as características que compõem a organização de um computador estão a estrutura 8 interna do processador, barramentos internos, sinais de controle disponíveis, tecnologias de memória e interface com o sistema de E/S. Portanto, arquiteturas de uma mesma família, como Intel® ou IBM® podem conter diferentes recursos de organização, mas manter uma compatibilidade no que tange aos conjuntos de instruções das máquinas. Na literatura, duas abordagens se destacam quanto ao desenvolvimento de uma microarquitetura. A primeira é apresentada por [Tanenbaum, 2007], na qual um modelo de abstração em camadas ou níveis é definido para o projeto e implementação de arquiteturas de computadores. Em cada uma destes níveis, o computador pode ser programado utilizando os recursos desse nível, que pode ser compreendido como uma máquina virtual para execução de programas descritos no seu nível superior. A Figura 2.1 apresenta um modelo de máquinas multinível proposto pelo autor composto por seis níveis. Figura 2.1 – Modelo de máquinas multinível Fonte: [Tanenbaum, 2007] 9 Cada nível é responsável por interpretar as instruções do nível imediatamente superior. O nível 0 é composto por circuitos lógicos que executam os programas em linguagem de máquina por meio da execução de funções lógicas simples (AND, OR, XOR, NOT, etc). No nível 1, os circuitos lógicos são agrupados a fim de formar elementos mais complexos, como a Unidade Lógica e Aritmética (ULA) e registradores, que formam uma memória local. Estes elementos são conectados formando o caminho de dados do processador (data path). As operações podem ser controladas por um microprograma ou diretamente por hardware, sendo o microprograma um interpretador para as instruções do nível 2, de modo que o microprograma busca, decodifica e executa as instruções provenientes do nível 2 utilizando o caminho de dados como estrutura para realização desta tarefa. Caso seja utilizado um controle via hardware, o ciclo de funcionamento de uma instrução é realizado sem a necessidade de um programa armazenado para interpretar as funções. O nível 2 define a interface entre o hardware e o software. Cada fabricante define uma linguagem própria, conhecida como linguagem Assembly ou linguagem de montagem, para sua estrutura de hardware construída. Esta linguagem determina o conjunto de instruções da máquina executáveis pelo processador, que deve ser documentado em manuais específicos pelo fabricante. Além dos formatos e tipos de instruções, também são definidos os tipos de dados, modelos de memória e tipos de endereçamento. Portanto, este nível define a Arquitetura do Conjunto de Instruções (ISA – Instruction Set Architecture). O nível 3 suporta novas instruções e fornece serviços básicos para as camadas superiores, como escalonamento de processos, gerenciamento de memória, acionamento de dispositivos de E/S, interface com o usuário, etc. A partir deste nível, as camadas superiores são destinadas a programadores de sistema, enquanto as camadas inferiores destinadas a programadores de aplicação. O nível 4 tem o intuito de fornecer uma ferramenta para programadores de aplicativos de uso geral, e os programas desenvolvidos neste nível recebem o nome de montadores ou Assemblers. Uma linguagem de montagem é uma forma simbólica de representar linguagens de mais baixo nível, de modo que os programas nessa linguagem são traduzidos para as linguagens dos níveis 1, 2 e 3 e depois interpretados por uma máquina virtual ou real. No último nível estão os programas desenvolvidos em linguagens de alto nível, voltados para a criação de aplicativos. Estes programas precisam ser traduzidos para os níveis 3 10 e/ou 4 por meio de um tradutor denominado compilador ou por algum interpretador como no caso de linguagens como Java ou Python. Os níveis 0 a 2 são os níveis mais abordados durante a disciplina de arquitetura e organização de computadores, sendo que o nível 0, por ser formado por circuitos lógicos, é visto com mais detalhes em disciplinas de circuitos lógicos / lógica digital. O nível 3 pode ser melhor abordado em disciplinas específicas de Sistemas Operacionais, enquanto que os níveis 4 e 5 são discutidos em disciplinas de Software Básico e Compiladores. Dependendo do projeto de arquitetura, a quantidade e os níveis podem variar, assim como podem ser realizadas outras abordagens para o desenvolvimento de um computador. Para exemplificar sua abordagem, Tanenbaum utilizou uma máquina fictícia chamada MAC para ilustrar o conceito de microprogramação e criou a arquitetura didática multiciclo MIC, implementada em quatro versões (MIC-1, MIC-2, MIC-3 e MIC-4), dedicada a executar um subconjunto das instruções da Máquina Virtual Java chamado IJVM (Integer Java Virtual Machine). A arquitetura MIC-1 pode ser visualizada na Figura 2.2 Figura 2.2 – Arquitetura MIC-1 Fonte: [Tanenbaum, 2007] 11 A metodologia aplicada por [Patterson, 2008] constrói um computador a partir do seu conjunto de instruções. O autor cita que a arquitetura de um computador é formado pela junção dos aspectos de organização de computadores e arquitetura do conjunto de instruções (ISA). Segundo o autor, a ISA de um computador é um nível de abstração que oferece a interface entre o nível de hardware e o software de baixo nível, responsável pela padronização dos tipos e formatos de instrução, quantidade e disposição dos bits que compõem uma instrução, tipos de operandos, quantidade de registradores necessários, modos de endereçamento e de acesso às palavras ou bytes, organização da memória, etc. O conjunto de instruções da arquitetura forma a linguagem de máquina do computador, que é a base para a construção das unidades operativa e de controle do processador. Inicialmente são definidas quais as instruções aritméticas, lógicas, de desvio, transferência de dados, controle e de Entrada/Saída que serão utilizadas pelo computador. Adicionalmente, podem ser inseridas instruções de gerenciamento de memória, ponto flutuante e outras especiais. Após a escolha da quantidade e tipos de instruções, os componentes físicos necessários para a execução das instruções são projetados, inseridos e conectados, como por exemplo, desenvolver uma Unidade Lógica e Aritmética (ULA) para prover as instruções aritméticas presentes no seu conjunto de instruções. Patterson utiliza como base para os conceitos de arquitetura e organização a arquitetura MIPS e o conjunto de instruções MIPS-I. Essa forma de abordagem visa explorar a interface hardware-software de modo a unir os conceitos de programação e circuitos digitais. A metodologia de Patterson sugere que, de acordo com a arquitetura do conjunto de instruções, deva ser definida uma estrutura organizacional macro, composta pelo número de unidades funcionais, sendo esta estrutura refinada para definir os componentes do caminho de dados, sua interconexão e sua unidade de controle. A arquitetura MIPS é apresentada sob três variações: monociclo, multiciclo e pipeline, que serão detalhadas adiante. Existem outras abordagens na literatura, como por exemplo, a metodologia proposta por [Stallings, 2010], a qual utiliza estudos de caso com arquiteturas reais, como Pentium e PowerPC, para tratar os aspectos de arquitetura e organização de computadores, fazendo uma distinção entre estes. Dentre as propostas experimentais existentes, uma abordagem de ensino que está sendo utilizada em algumas universidades utiliza a metodologia de aprendizagem 12 baseada em problemas (PBL – Problem-Based Learning) [Martinez-Mones et al, 2005], [Dos Santos, 2007]. Na fase inicial desta abordagem, denominada etapa de situação, o aluno é apresentado a um determinado problema real, e apresentando fenômenos e objetos que o motive a adquirir novos conhecimentos técnicos para a resolução do problema. Na segunda etapa, ocorre a fundamentação teórica necessária para a resolução do problema identificado na etapa de situação, iniciando uma reflexão crítica sobre o problema aplicado. Na fase final deste ciclo, denominada etapa de realização, o aluno deve utilizar os conceitos teóricos estudados para a produção de um produto final, aproximando a teoria aprendida com a prática, e permitindo ao aluno a compreensão da realidade apresentada. 2.2. Processadores Reconfiguráveis Apesar desta metodologia de adaptação não necessitar de nenhuma reconfiguração no hardware do dispositivo, as microarquiteturas utilizadas neste trabalho são processadores RISP, descritos na linguagem VHDL e sintetizados em dispositivos reconfiguráveis FPGAs (Field Programmable Gate Arrays), fato este que justifica uma breve explanação sobre os conceitos e características gerais de tais processadores. Um FPGA é um dispositivo semicondutor utilizado para o processamento de informações digitais. Foi criado pela Xilinx Inc.® [Xilinx, 2013] em 1985 como um dispositivo que programado de acordo com as aplicações de um usuário programador. Um FPGA é composto basicamente por três tipos de componentes de lógica programável: blocos de entrada e saída (IOB – Input/Output Blocks), blocos lógicos configuráveis (CLB – Configurable Logic Blocks) e chaves de interconexão (Switch Matrix) [Brown, 1992]. Os blocos lógicos são dispostos de forma bidimensional, e as chaves de interconexão são dispostas em formas de trilhas verticais e horizontais entre as linhas e as colunas dos blocos lógicos. Cada um desses blocos pode servir como entrada, saída ou acesso bidirecional a outros pinos de I/O e podem ser programados para efetuar operações lógicas básicas ou combinatórias complexas e podem ser configurados pelo projetista após a fabricação do dispositivo para implementar qualquer função lógica ou circuito complexo em campo [Rose et AL., 1992]. A Figura 2.3 apresenta a configuração básica de um FPGA. 13 Figura 2.3 – Configuração básica de um FPGA Fonte: [Brown, 1992] Para configurar uma FPGA deve ser especificado um diagrama esquemático do circuito ou um código-fonte em uma linguagem HDL (Hardware Description Language) que descreve a lógica com que o dispositivo irá funcionar. Para converter diagramas/HDL para configurações físicas em um FPGA, é necessário enviar o códigofonte por um software disponibilizado pelo fabricante. Este arquivo é transferido para o FPGA por uma interface serial JTAG (Joint Test Action Group) ou para memória externa como uma EEPROM. Além dos recursos padrões (slices), um FPGA pode disponibilizar em seu arranjo bidimensional recursos adicionais como multiplicadores dedicados, MACs (Multiplicador e Acumulador) programáveis, blocos de memória, DCM (Digital Clock Manager), utilizados para multiplicar ou dividir a frequência de um sinal de relógio, microcontroladores (IBM PowerPC), e outras bibliotecas. A utilização de tais recursos embarcados possibilita otimizar a área do dispositivo e desenvolver projetos mais complexos e eficientes [Anderson, 2006] As arquiteturas reconfiguráveis foram sendo desenvolvidas e aprimoradas de acordo com a disponibilidade de tecnologia e visando a resolução de novos problemas e desafios. De acordo com [Mesquita, 2002], a partir do amadurecimento da tecnologia de FPGAs, as arquiteturas reconfiguráveis foram criadas com o intuito principal de aumentar o desempenho de algoritmos que até então eram executados em software. A 14 diferença entre processadores reconfiguráveis é dada por características como: grau de acoplamento entre o processador e a lógica reconfigurável, tipo de instruções a serem executadas pela lógica reconfigurável, formato de codificação e passagem de parâmetros das instruções reconfiguráveis, acesso à memória por parte da lógica reconfigurável entre outras características relevantes para o desempenho de processadores reconfiguráveis [Mooler et al., 2005]. Os processadores reconfiguráveis estendem a capacidade de um processador, otimizando seu conjunto de instruções para uma tarefa específica. Com isto é obtido um aumento de desempenho e flexibilidade, ao mesmo tempo em que a área do núcleo do processador permanece inalterada [Mooler et Al., 2005]. Para fazer uma avaliação a respeito de processadores reconfiguráveis, algumas medidas básicas de avaliação são necessárias, tais como desempenho, custo e tamanho. A medida de desempenho geralmente é associada à velocidade de execução das instruções básicas (MIPS – Milhões de Instruções Por Segundo) ou o tempo gasto em ciclos de relógio para a execução de aplicações como, por exemplo, benchmarks. O custo é geralmente analisado em termos de parâmetros como: número de pinos, área em chip, número de chips por sistema, entre outros. Com relação ao tamanho de programas e dados, este pode ser expresso através da capacidade máxima e a eficiência de ocupação do código gerado. Outras restrições como, peso, volume e consumo de potência podem ser consideradas de acordo com a aplicação. De acordo com [Adário et al., 1997], uma arquitetura reconfigurável possui como principais metas: acréscimo de velocidade e da capacidade de prototipagem, representado pelo número de portas lógicas equivalentes, proporcionando aumento de desempenho; reconfiguração dinâmica; baixo consumo na reconfiguração; granularidade adequada ao problema, entre outros. A melhoria de desempenho de sistemas é uma das principais utilizações das arquiteturas reconfiguráveis devido a possibilidade da implementação de algoritmos complexos nos atuais processadores diretamente no hardware. O primeiro processador de propósito geral acoplado a um FPGA foi denominado PRISM (Processor Reconfigurable through Instruction-Set Metamorphosis), em 1993 por (ATHANAS; SILVERMAN, 1993). Devido à limitação da tecnologia dos FPGAs da época, somente era possível desenvolver um sistema fracamente acoplado, no qual um FPGA comunicava-se com um processador por meio de um barramento. 15 O primeiro processador dito reconfigurável foi denominado PRISC (PRogrammable Instruction Set Computer), em 1994 por [Razdan & Smith, 1994]. PRISC foi o primeiro a explorar na pratica a existência de uma RFU (Reconfigurable Functional Unit) contida em um caminho de dados de um processador MIPS. Neste processador, assim como para os demais representantes da primeira geração de processadores reconfiguráveis, verificou-se a eficiência da utilização de FPGAs para aplicações específicas, aumentando o desempenho com relação a soluções implementadas em software. O problema principal era o gargalo de comunicação entre o processador e os FPGAs e o alto tempo de reconfiguração. O fato da reconfiguração ser estática impunha a interrupção da execução para que o sistema possa ser reconfigurado. Com a evolução da tecnologia de integração, surgiu a segunda geração de processadores reconfiguráveis, tornando possível o desenvolvimento de um sistema composto pelo processador, FPGAs e memória em um único chip, resultando no embrião do que hoje se identifica por SoC. Também foi possível o desenvolvimento de processadores utilizando-se reconfiguração dinâmica. O processador CRISP (Configurable and Reconfigurable Instruction Set Processor), proposto originalmente por [Barat, 2002] possui a característica de ser configurável em tempo de desenvolvimento e reconfigurável em tempo de execução. Consiste em um processador VLIW (Very Long Instruction Word), que executa instruções compostas por operações paralelas, executadas em unidades funcionais fixas (FFUs - Fixed Functional Units) e uma unidade funcional reconfigurável. Em 2003 surgiu a arquitetura VISC (Variable Instruction Set Communications Architecture), apresentado por [Liu et al., 2003]. A característica que diferencia o conjunto de instruções deste processador dos demais é a utilização de um dicionário que define o tipo de cada instrução e permite ao compilador configurar o melhor conjunto de instruções para a execução de um determinado programa. Desde então, diversas versões de FPGAS comerciais e acadêmicos foram e estão sendo desenvolvidos. Alguns destes processadores receberam características específicas, como a possibilidade de modificar ou inserir novas instruções na máquina. Estes processadores são denominados RISP (Reconfigurable Instruction Set Processors – Processador com conjunto de instruções reconfigurável). 16 2.3. Processadores RISP Um processador com conjunto de instruções reconfigurável consiste em um núcleo microprocessado estendido com uma lógica reconfigurável. Este é similar a um ASIP (Application Specific Instruction set Processor), mas em vez de unidades funcionais especializadas, que contém as unidades funcionais reconfiguráveis, esta proporciona a adaptação do processador para a aplicação, enquanto o núcleo do processador fornece programabilidade em software [Barat, 2002]. [Lodi et al., 2003] classificou os Processadores com Conjunto de Instruções Reconfiguráveis RISP como um subconjunto dos processadores reconfiguráveis. Estes processadores não apresentam um custo de hardware para cada nova instrução em hardware, mas sim um custo pré-definido em área onde a lógica reconfigurável pode ser programada em tempo de execução [Mooler et al., 2005]. A Figura 2.4 apresenta um modelo hipotético de uma arquitetura RISP. O processador RISP executa instruções, assim como processadores comuns e ASIPs, embora a principal diferença esteja no conjunto de instruções, o qual é implementado em hardware fixo, e um conjunto de instruções reconfiguráveis implementado na lógica reconfigurável e que pode sofrer alterações durante a execução do processador [Barat 2002]. Este conjunto de instrução reconfigurável é equivalente ao conjunto de instrução especializado de um ASIP, mas com a possibilidade de modificação após o processador ter sido projetado. Figura 2.4 – Exemplo de um modelo de arquitetura RISP Fonte: [Barat 2002] 17 O custo de projeto de um microprocessador com núcleo é reduzido devido à reutilização em diversas aplicações. Em ASIPs o custo de cada nova geração vem da remodelação das unidades funcionais especializadas, que podem ser bastante elevados. Técnicas de prototipagem rápidas são essenciais para reduzir o custo e o tempo necessário para a remodelagem [Barat 2002]. 2.4. Processadores soft-core Um processador soft-core é um microprocessador que pode ser implementado utilizando síntese lógica como, por exemplo, utilizando a linguagem de descrição de hardware VHDL. [Tong, 2006] afirma que tais modelos de processadores possuem diversas vantagens sobre processadores de propósito geral como redução de custos, flexibilidade, plataformas independentes e capacidade de renovação. Diversos fabricantes de FPGAS disponibilizam seus produtos para uso comercial e acadêmico. Dentre estes, destacam-se os processadores Nios II, MicroBlaze, PicoBlaze e Xtensa, dos fabricantes Altera®, Xilinx® e Tensilica®, respectivamente. Além destas arquiteturas, comunidades científicas costumam disponibilizar processadores Open-Cores [Opencores, 2013], que são componentes IP (Propriedade Intelectual) que podem ser utilizadas livremente pela comunidade, para fins não lucrativos. Destacam-se os processadores OpenSPARC [OpenSPARC, 2013], LEON [Leon, 2013] e Plasma [Rhoads, 2013]. Dentre os processadores soft-core MIPS mais utilizados, o PLASMA [Rhoads, 2013] é um dos mais completos. Trata-se de um processador de código fonte aberto, desenvolvido em VHDL, possui os cinco estágios de pipeline e implementa o mesmo conjunto de instruções do MIPS R3000. A Figura 2.5 mostra a topologia lógica da organização do PLASMA. 18 Figura 2.5 – processador PLASMA Fonte: [Opencores, 2013] O PLASMA, assim como o LEON e as versões do processador MIPS original, por possuírem seu código-fonte aberto, estão disponíveis para a comunidade científica para fins acadêmicos. 2.5. Processadores microprogramados Em um processador microprogramado, toda a sua lógica de sua unidade de controle é especificada através de um microprograma. Um microprograma, por sua vez é composto por uma sequência de instruções de uma linguagem de microoperação. A uma sequência de instruções em uma linguagem de microprogramação dá-se o nome de microprograma. [Tanenbaum, 2007]. A ideia de um controle microprogramado surgiu na década de 1950 [Wilkes, 1951], para evitar a complexidade da implementação em hardware em um dispositivo e começou a ser adotada na família i360 da IBM®. O circuito lógico destas unidades é formado por uma sequência de microinstruções, contendo os sinais de controle para executar cada etapa do microprograma e uma lógica de sequenciamento para decisão da próxima microinstrução. Estes sinais de controle são enviados para a unidade operativa (caminho de dados) do dispositivo, indicando o comportamento de cada unidade 19 funcional, como a operação da ULA, a codificação da seleção de multiplexadores ou a habilitação de escrita em registradores. A vantagem de um controle microprogramado sobre uma implementação em hardware, além da redução da complexidade, é o fato de torná-la mais simples, compreensível e menos sujeita a erros. Em contrapartida, sua execução é mais lenta e o consumo de potência gerada pelo dispositivo é maior. O projeto de processadores microprogramados depende da ISA que esta implementada, bem como das metas de custo e desempenho. Das implementações de processadores microprogramados, um trabalho de destaque é o de [Mihal et al., 2006], no qual foi projetado um processador sub-RISC. Este processador é uma classe de um processador ASIP, com arquitetura programável. Além disso, os autores criaram uma ferramenta para gerar um processador sub-RISC de expressões regulares. Para isso foi utilizado um framework denominado TIPI (Tiny Instruction Processors and Interconnect), que auxilia na criação de um circuito sem a necessidade de programar em uma linguagem HDL. Através da interpretação de autômatos, o framework gera o código HDL do circuito e o mesmo é carregado em um FPGA. 2.6. Arquitetura MIPS A arquitetura MIPS foi desenvolvida inicialmente como um projeto acadêmico na Universidade de Stanford em 1981 por uma equipe de doutorandos e de mestrandos chefiada por John Hennessy [Patterson & Hennessy, 2008]. Este projeto se tornou um dos principais precursores da tecnologia RISC. A arquitetura do conjunto de instruções MIPS-1 é regular, todas as instruções possuem o mesmo tamanho. Conforme [Sweetman, 2006], esta característica permitiu que seus conceitos fossem assimilados mais facilmente se comparado a arquiteturas irregulares. Em 1984, foi fundada a empresa MIPS Computer Systems Inc. cujo objetivo foi comercializar a tecnologia desenvolvida no meio acadêmico. As versões iniciais de processadores MIPS usavam arquitetura de 32 bits, como o R2000 e o R3000. Versões posteriores passaram a empregar arquitetura de 64 bits com a introdução do R4000. Durante a evolução da família de processadores diversas revisões do conjunto de instruções (ISA) MIPS foram realizadas, incluindo MIPS-I, MIPS-II, MIPSIII, MIPSIV, MIPS-V, MIPS32 e MIPS64. As duas últimas revisões são as especificações atualmente disponíveis para 32 e 64 bits respectivamente. Em 1992, a MIPS Computer 20 Systems foi adquirida pela Silicon Graphics Computer Systems. Todas as revisões são retroativamente compatíveis [Kane & Heinrich, 1991]. A arquitetura MIPS segue os princípios básicos de um projeto de hardware, para que o processador criado seja simples, eficiente, livre de falhas e de baixo custo. A representação de instruções MIPS segue um formato regular de campos, cada um com uma função específica, seguindo o princípio de que “a simplicidade é favorecida pela regularidade”. Cada instrução possui 32 bits, o mesmo tamanho de uma palavra de memória ou uma palavra de dados. Apesar de possuir um tamanho fixo, são utilizados diferentes formatos para tipos distintos de instruções. Para alcançar o princípio de “quanto menor, mais rápido”, não são utilizadas variáveis em linguagem de montagem, prática presente em linguagens de alto nível. O MIPS utiliza 32 registradores, cada um representando uma palavra da arquitetura. Um número maior de registradores acarreta um aumento na duração do ciclo de relógio, que tornaria o sistema mais lento. Outro princípio de projeto adotado pelo padrão MIPS é “tornar o caso comum mais rápido”, pois a utilização de operandos imediatos ocorre com tal frequência em linguagens de montagem que é preferível tratá-los como um caso comum ao invés de instruções especiais. Os conceitos básicos relacionados à arquitetura MIPS podem ser resumidos pelas seguintes características: execução implementada sobre um pipeline com cinco estágios; conjunto de instruções regular, onde todas as instruções possuem comprimento fixo (32 bits); instruções lógicas e aritméticas compostas de três operandos: fonte, alvo e destino; 32 registradores de propósito geral, cada um com 32 bits; nenhuma instrução complexa, como gerenciamento de pilha ou operações sobre cadeias de caracteres; possibilidade de dar suporte nativo a até quatro co-processadores opcionais, destinados ao gerenciamento do sistema, operações com ponto flutuante e funcionalidades específicas; 21 instruções de acesso à memória exclusivas: load e store, tanto para memória principal como para dispositivos periféricos, o que força o uso do conceito de entrada e saída mapeada em memória; espaço de endereçamento contínuo de 4GB para acesso à memória, alinhado à palavra de 32 bits, com possibilidade de acesso à palavra (32 bits), meia palavra (16 bits) ou byte (8 bits); mapeamento de endereços virtuais para endereços reais; código em linguagem de montagem otimizado pelo compilador, em substituição à intervenção manual ou otimização via hardware; A estrutura de hardware não verifica dependências de instruções. O conjunto de registradores da arquitetura MIPS é constituído por três grupos de registradores de 32 bits distintos: 32 para propósito geral, numerados de 0 a 31, dois para operações de multiplicação e divisão (HI e LO) e um contador de programa (PC). Todos os registradores de propósito geral podem ser usados como fonte ou destino de dados para instruções lógico-aritméticas, acesso à memória e controle de fluxo. A única exceção é o registrador 0 (zero), não alterável, que possui seu valor fixado em zero pelo hardware, e utilizado como constante em operações aritméticas e de transferência de dados. Portanto, operações de leitura deste registrador sempre retornam valor zero e as de escrita são ignoradas, sendo o valor escrito descartado. O conjunto de instruções MIPS-1 divide-se em três formatos básicos, conforme descrito na Tabela 2.1: Tabela 2.1 Formato de instruções MIPS em que: opc: código de operação; rs: endereço do registrador origem; rt: endereço do registrador alvo (origem ou destino, conforme instrução específica); rd: endereço do registrador destino; shamt: quantidade de deslocamento; 22 funct: função; imm-16: constante imediata de 16 bits; addr-26: endereço parcial de 26 bits. As características de cada formato podem ser resumidas como segue. Instruções com formato R (register): inclui instruções lógicas e aritméticas com três registradores, inclusive multiplicação e divisão, instruções de deslocamento de bits, desvio baseados em registrador e instruções de exceções syscall e break. O campo funct atua como um campo adicional de 6 bits para identificação da instrução. O campo shamt é usado para indicar a quantidade de bits a ser deslocada em instruções de deslocamento de bits. Os registradores rs e rt são usados como origem de dados e rd como destino do resultado da operação; Instruções com formato I (immediate): incluem instruções de acesso à memória (alinhado ou não), instruções lógicas e aritméticas que fazem uso de constantes imediatas e instruções de desvio condicional (branches). O registrador rs é usado como origem de dados e o rt como destino do resultado da operação. O campo imm-16 contém um valor imediato de 16 bits usado de uma de duas formas: como valor literal (positivo ou negativo) em instruções lógicas e aritméticas ou como um inteiro com sinal (entre 32678 a +32467) indicando o deslocamento relativo a um registrador (modo de endereçamento base-deslocamento); Instruções com formato J (jump): inclui instruções de salto que usam modo de endereçamento pseudo-direto. O campo addr-26 contém uma constante (imediata) de 26 bits usada no cálculo do endereço absoluto alvo do desvio. Este valor é acrescentado de 2 bits à esquerda, equivalente a uma multiplicação por 4 devido ao uso de alinhamento de todo programa em endereço múltiplo de quatro. Isto gera um endereço de 28 bits, que é então concatenado com os 4 bits superiores do PC, ou seja, addr-26 indica o deslocamento em quantidade de palavras não de bytes dentro da página de memória (de 256 Mbytes) onde se encontra a instrução seguinte à instrução de desvio. 23 Além da classificação das instruções MIPS-I quanto ao formato, também se pode dividir o conjunto de instruções quanto à funcionalidade das instruções. Existem três classes de instruções, conforme este critério: Classe Padrão (Standard): caracterizada pelas instruções que possuem o campo opc diferente de 0 ou 1 (zero ou um). Nesta classe enquadram-se as instruções de acesso à memória (alinhado ou não), instruções lógicas e aritméticas que fazem uso de constantes (imediatas), instruções de salto que usam modo de endereçamento pseudo-direto e instruções de desvio condicional que usam dois registradores; Classe Especial (Special): caracterizada pelas instruções que possuem o valor 0 (zero) no campo opc. Inclui instruções lógicas e aritméticas com três registradores inclusive multiplicação e divisão, instruções de deslocamento de bits, instruções de salto baseadas em registrador e as instruções para tratamento de exceções syscall e break. O campo funct atua como campo complementar ao opc, permitindo selecionar a operação desejada; Classe Registrador-imediato (RegImm): caracterizada pelas instruções que possuem o valor 1 (um) no campo opc. Inclui instruções de desvios condicionais (branches) que comparam valores em relação a 0 (zero), exceto as instruções blez e bgtz. O campo rt define qual o tipo de comparação a ser realizada, portanto é usado em conjunto com o campo opc para decodificar a instrução. Embora os 32 registradores de propósito geral possam ser usados indistintamente para qualquer objetivo (com exceção de $0), existe uma convenção para o uso destes registradores em programação, com o objetivo de padronizar o desenvolvimento de software básico, como montadores, compiladores e carregadores, conforme a sequência exibida na Tabela 2.2. Estas convenções não implicam a existência de qualquer estrutura no hardware que as dê suporte a elas. Tabela 2.2 Descrição das convenções de uso dos registradores do MIPS Número 0 1 2-3 4-7 8-15 Nome Zero At v0-v1 a0-a3 t0-t7 Descrição do uso Valor zero Reservado para uso do montador (assembler temporary) Valores retornados por sub-rotinas (returned value) Primeiros 4 argumentos passados às sub-rotinas (arguments) Uso livre para sub-rotinas (temporaries) 24 16-23 s0-s7 24-25 26-27 t8-t9 k0-k1 28 29 30 31 gp SP Fp Ra Valores preservados entre chamadas de sub-rotina, devem ser restaurados após o retorno (saved) Uso livre para sub-rotinas (temporaries) Reservados para rotina de interrupção, usados pelo sistema operacional (kernel) Acesso às variáveis estáticas ou externs (global pointer) Ponteiro para área de pilha (stack pointer) Ponteiro para área de frame (frame pointer) Endereço de retorno de sub-rotina (return address) A arquitetura pipeline de cinco estágios pressuposta como natural para a implementação do hardware de um processador MIPS inclui: IF – estágio de busca (instruction fetch): busca a próxima instrução a ser executada; ID – estágio de decodificação (instruction decode): realiza a decodificação da instrução e a leitura dos operandos fonte do banco de registradores; EX – estágio de execução (execution): realiza a execução da instrução ou o cálculo de endereço quando aplicável; MEM – estágio de acesso à memória (memory access): realiza o acesso à memória externa; WB – estágio de escrita do resultado (write back): escrita do resultado no banco de registradores. A Tabela 2.3 apresenta o conjunto de instruções MIPS-I contendo a sintaxe e o código de cada instrução. As instruções de tipo R possuem o mesmo CodOp 0x00, sendo sua operação determinada pelo campo Func. Mais informações detalhadas sobre o conjunto MIPS-1 encontram-se no Apêndice A. 25 Tabela 2.3 Conjunto de instruções MIPS-1 Grupo Transferência de informação Operações Aritméticas Operações lógicas e de comparação Operações de deslocamento Instruções de salto Exceção Sintaxe lb Rdest, Imm16 (Rsrc) lw Rdest, Imm16 (Rsrc) lbu Rdest, Imm16 (Rsrc) sb Rsrc2, Imm16 (Rsrc1) sw Rsrc2, Imm16 (Rsrc1) lui Rdest, Imm16 mfhi Rdest mflo Rdest mthi Rdest mtlo Rdest add Rdest, Rsrc1, Rsrc2 addi Rdest, Rsrc1, Imm16 addu Rdest, Rsrc1, Rsrc2 addiu Rdest, Rsrc1, Imm16 sub Rdest, Rsrc1, Rsrc2 subu Rdest, Rsrc1, Rsrc2 mult Rdest, Rsrc1, Rsrc2 multu Rdest, Rsrc1, Rsrc2 div Rdest, Rsrc1, Rsrc2 divu Rdest, Rsrc1, Rsrc2 and Rdest, Rsrc1, Rsrc2 andi Rdest, Rsrc1, Imm16 or Rdest, Rsrc1, Rsrc2 ori Rdest, Rsrc1, Imm16 xor Rdest, Rsrc1, Rsrc2 xori Rdest, Rsrc1, Imm16 nor Rdest, Rsrc1, Rsrc2 slt Rdest, Rsrc1, Rsrc2 slti Rdest, Rsrc1, Imm16 sltu Rdest, Rsrc1, Rsrc2 sltiu Rdest, Rsrc1, Imm16 sll Rdest, Rsrc1, Shamt5 srl Rdest, Rsrc1, Shamt5 sra Rdest, Rsrc1, Shamt5 j address28 jr Rsrc beq Rsrc1, Rsrc2, address18 bne Rsrc1, Rsrc2, address18 bgez Rsrc, address18 bgtz Rsrc, address18 blez Rsrc, address18 bltz Rsrc, address18 jal address18 jalr Rsrc rfe syscall break Tipo I I I I I I R R R R R I R I R R R R R R R R R I R I R R I R I R R R J R I I I I I I J R R R R Op 0x20 0x23 0x24 0x28 0x2b 0x0f 0 0 0 0 0 8 0 9 0 0 0 0 0 0 0 0x0c 0 0x0d 0 0x0e 0 0 0x0a 0 0x0b 0 0 0 2 0 4 5 1 7 6 1 3 0 0x10 0 0 Func 0x10 0x12 0x11 0x13 0x20 0x21 0x22 0x23 0x18 0x19 0x1a 0x1b 0x24 0x25 0x26 0x27 0x2a 0x2b 0 2 3 8 1 0 9 0x20 0x0c 0x0d Significado leitura de byte da memória leitura de palavra da memória leitura de byte sem sinal da memória escreve byte na memória escreve palavra na memória lad upper immediate move de HI move de LO move para HI move para LO adiciona com overflow adiciona Imm com overflow adiciona sem overflow adiciona Imm sem overflow subtrai com overflow subtrai sem overflow multiplica multiplica sem sinal divide divide sem sinal and and com imediato or or com imediato xor xor com imediato nor set if less than set if less than Imm set if less than sem sinal set if less than Imm sem sinal desl. Lógico à esquerda desl. Lógico à direita desl. aritmético à direita desvio incondicional desvio usando registrador desvia se igual (relativo) desvia se diferente (relativo) desvia se maior ou igual a zero (rel) desvia se maior que zero (rel) desvia se menor ou igual a zero (rel) desvia se menor que zero (rel) desvia e link de retorno desvia e link de retorno c/ reg retorno de exceção chamada de sistema break A Figura 2.6 apresenta um diagrama esquemático simplificado de um pipeline típico do MIPS, conforme empregado para dispositivos com os MIPS R2000 e R3000. 26 Figura 2.6 – Diagrama de blocos de um pipeline MIPS Fonte: [Patterson, 2007] 2.7. Processadores MIPS MIPS é acrônimo para Microprocessor without Interlocked Pipeline Stages, ou microprocessador sem estágios de pipeline bloqueados. Tipicamente, arquiteturas MIPS-I empregam um pipeline de 5 estágios: busca, decodificação, execução, acesso à memória e escrita no banco de registradores. Nesta implementação de pipeline,se não houver conflitos entre diferentes instruções executando simultaneamente, a cada ciclo de relógio é realizada a execução de uma destas instruções. Utilizando um conjunto de instruções como ponto de partida, inicialmente é projetada uma implementação simples de caminhos de dados e de controle para prover a execução destas instruções, formando uma arquitetura monociclo, como pode ser visualizado na Figura 2.7. Figura 2.7 –MIPS monociclo Fonte: [Patterson, 2007] 27 Na implementação monociclo, um ciclo de relógio possui mesmo tamanho para todas as instruções implementadas em seu conjunto. Este ciclo é definido pela instrução de maior duração, no caso MIPS-I pela instrução Load Word. Como cada unidade funcional somente pode ser utilizada uma vez por ciclo de relógio, a duplicação de unidades funcionais acarreta em um maior custo de hardware. A segunda alternativa de implementação é a versão MIPS multiciclo. A execução de cada instrução é dividida em etapas, sendo que cada etapa necessita de um ciclo de relógio. Assim, cada unidade funcional da arquitetura pode ser utilizada mais de uma vez por instrução. Nesta versão, são inseridos os conceitos de microprogramação e máquinas de estados finitos. A Figura 2.8 apresenta a versão do MIPS multiciclo. Figura 2.8 –MIPS multiciclo Fonte: [Patterson, 2007] As instruções do MIPS são executadas em ate 5 etapas: 1. Busca da instrução na memória; 2. Leitura dos registradores enquanto uma instrução é decodificada, (o formato das instruções do MIPS permite que a leitura e a codificação ocorram simultaneamente); 3. Execução de uma operação ou cálculo de um endereço; 4. Acesso a um operando de memória; 5. Escrita do resultado em um registrador; 28 Na versão MIPS pipeline, cada uma destas etapas é executada em um estágio do pipeline. Cada estágio é geralmente denominado como: 1. BI ou IF Busca instrução 2. DI ou ID Decodificação da instrução 3. EX Execução ou cálculo de endereço 4. MEM Acesso à memória de dados 5. ER ou WB Escrita no banco de registradores A versão MIPS pipeline contendo os 5 estágios de execução pode ser visualizada na Figura 2.9. Figura 2.9 –MIPS pipeline Fonte: [Patterson, 2007] Pela sua simplicidade, processadores MIPS são muito utilizados em universidades para uso e desenvolvimento de processadores didáticos. muitos projetos MIPS são utilizados em sistemas embarcados como gravadores de DVDs, modems, roteadores Cisco e videogames como o Nintendo 64 e Playstation da Sony e dispositivos móveis com Windows CE. 29 2.8. Considerações Com relação às metodologias acadêmicas para projeto de arquiteturas de computadores, é importante citar que este trabalho não apresenta uma nova metodologia para o desenvolvimento de processadores nem propõe a substituição de qualquer abordagem, visto que o objetivo é realizar uma adaptação de processadores já previamente projetados para uma nova ISA. Contudo, por se tratar de uma metodologia que toma por base o conjunto de instruções do processador para identificar as modificações necessárias para a integração das unidades funcionais de um processador para um novo padrão de instruções, a abordagem proposta por [Patterson, 2008] se apresenta como a mais semelhante e adequada para o projeto e implementação de microarquiteturas, o que não exclui qualquer outra abordagem de desenvolvimento de processadores como procedimento inicial para aplicação desta metodologia de adaptação. Os processadores utilizados como exemplo de aplicação da metodologia proposta foram descritos em VHDL e suas unidades de controle implementadas sob a forma de um microprograma por opção dos autores, que entendem ser a melhor opção para que as modificações necessárias ao processador com relação a alteração de sua ISA sejam efetuadas, assim como a criação das técnicas de modificação de instruções para que o processador possa ser classificado um RISP. A maioria das arquiteturas reconfiguráveis realizam modificações no caminho de dados para adequar-se à lógica reconfigurável, ou seja, a reconfiguração está na modificação de seus blocos lógicos e funções lógicas para adaptar-se a uma nova funcionalidade. No caso destes processadores, não existe uma reconfiguração de blocos lógicos, mas sim uma nova alternativa de inserir, combinar ou modificar instruções durante a execução de uma aplicação, utilizando diferentes técnicas como a áreas de microinstruções em memória RAM ou unidades funcionais dedicadas, as quais serão explicadas posteriormente. Portanto, termos como adaptação, programação ou mesmo configuração de instruções seriam melhor adequados para este trabalho, contudo optouse por utilizar o termo “reconfiguração de instruções”, visto que as arquiteturas projetadas seguem as características de processadores RISP. A arquitetura MIPS é frequentemente lecionada em universidades por permitir aos docentes a escolha do nível de envolvimento frente às restrições de tempo de ensino. Assim, a arquitetura MIPS pode ser apresentada aos alunos desde uma versão 30 simplificada que permita transmitir noções básicas de como um processador é implementado, a uma abordagem mais complexa que permita a demonstração de como atingir melhores desempenhos e maior capacidades de processamento utilizando técnicas como pipeline, coprocessadores de ponto flutuante ou caching. Por se tratar de uma abordagem acadêmica, esta ISA foi utilizada como base para a adaptação dos processadores. Não é o intuito deste trabalho projetar um processador MIPS ou substituir o processador atual por um processador MIPS já existente, visto que já existem versões MIPS descritas em VHDL completamente funcionais. O objetivo principal é adaptar um processador, com sua organização de hardware já definida, para que este possa executar as instruções de uma nova arquitetura de conjunto de instruções, utilizando como aplicação o conjunto MIPS-I. 31 Capítulo 3 – Estado da arte 4. A adaptação entre arquiteturas de conjuntos de instruções significa, em termos de software, diminuir a dificuldade quanto a problemas de compatibilidade binária entre códigos de aplicativos. Já em termos de hardware, significa fornecer uma técnica que contribua para o aproveitamento de softwares básicos como Assemblers e compiladores, e códigos já desenvolvidos e compilados para diferentes microarquiteturas. Algumas técnicas em hardware e software foram propostas para diminuir a dependência entre fabricantes ou arquiteturas a partir de uma adaptação ou compatibilidade entre diferentes ISAs. A solução mais simples e utilizada é a interpretação por software. Esta técnica permite a execução de um código previamente compilado em diferentes conjuntos de instruções em apenas um único processador. O código executado pelo aplicativo é analisado em tempo real pelo interpretador, sendo posteriormente realizada uma conversão entre o conjunto de instruções original do aplicativo e o novo conjunto desejado. Esta técnica permite a execução de um mesmo código binário em diferentes arquiteturas. Porém, o sistema de interpretação por software necessita de uma camada extra de software entre o aplicativo e o processador, tornando sua execução mais lenta comparada com a execução do código nativo. Também é necessário um interpretador implementado no mesmo conjunto de instruções do processador alvo. Outra solução proposta é o emulador por microcódigo, presente em diversas arquiteturas comerciais, desenvolvidas por fabricantes como Intel, IBM e Motorola, para garantir compatibilidade de softwares entre máquinas distintas. Ao contrário do interpretador, o emulador pode ser implementado em hardware, responsável pela decodificação do código original do aplicativo para um novo conjunto de instruções. O mecanismo interno de funcionamento é formado por uma memória ROM para armazenamento do microcódigo e uma máquina de estados para realizar o controle interno do sistema. Existem emuladores que permitem a adição de microcódigo através de uma memória flash ou SRAM (Static Random Access Memory). Esta técnica também 32 permite que instruções CISC sejam executadas em processadores RISC, adicionando uma camada extra de hardware e mantendo assim a compatibilidade binária, e simulando outras dependências específicas de plataforma que façam distinção entre as duas máquinas. 3.1. Tradução Binária Uma técnica em hardware que utiliza dispositivos reconfiguráveis consiste em uma tradução binária, que possui a característica de armazenar as traduções para reuso futuro, e pode ser implementado como uma camada de software ou hardware. O método de tradução binária consiste em converter um código já compilado para um determinado conjunto de instruções apontado pelo processador, no qual o código será realmente executado. Esta tradução permite executar um aplicativo dependente de um hardware proprietário em outro sistema que utiliza um conjunto de instruções diferente. Para o usuário do sistema, esta tradução é abstraída e o aplicativo é executado da mesma forma como se o programa estivesse sendo utilizado no processador nativo. Um tradutor binário pode ser classificado em três tipos diferentes, segundo [Altman, Kaeli e Sheffer, 2000]: emulador, Tradutor Estático e Tradutor Dinâmico. O emulador realiza a interpretação do código em tempo de execução, baseada em acessos a tabelas que contêm as possíveis configurações da arquitetura para qual a instrução será traduzida. Sua tradução não é salva em memória para reutilização futura. O Tradutor Estático realiza a tradução em tempo de compilação, sendo possível utilizar informações extraídas em tempo de execução do aplicativo. Já o Tradutor Dinâmico realiza a tradução do código em tempo de execução (run-time), com a possibilidade de armazenar em memória partes do código para uso futuro, dispensando um conhecimento profundo da arquitetura pelo programador ou usuário. O trabalho de [Fajardo Jr, 2011] propõe um sistema dinâmico de tradução binária de dois níveis, que executa um código compilado para o conjunto de instruções x86 em uma arquitetura reconfigurável, onde este sistema será capaz de executar o conjunto de instruções MIPS. O primeiro nível deste tradutor binário é responsável por traduzir o código nativo para um código genérico, da mesma forma que um tradutor binário convencional. Para tanto, foi desenvolvido um novo mecanismo dinâmico implementado em hardware que funciona como interface entre o processador e a memória de instruções. O segundo 33 nível de tradução é responsável por otimizar ou acelerar sequências de instruções deste código comum já traduzidas para a arquitetura alvo. Este código é, por sua vez, traduzido para ser executado em uma arquitetura reconfigurável, a qual é composta por um processador MIPS fortemente acoplado com um segundo nível de tradução binária e uma unidade reconfigurável fortemente acoplada de granularidade grossa [BECK et al., 2008]. Os trechos traduzidos são chamados agora de “configurações”, e são alocados na TCache para serem executados novamente de acordo com o fluxo do programa, porém agora na unidade de reconfigurável. A Figura 3.1 ilustra uma visão geral de sua proposta. Figura 4.1 – Mecanismo de tradução binária em dois níve Fonte: [Fajardo Jr, 2011] Ainda segundo [Fajardo Jr, 2011], o funcionamento deste mecanismo ocorre da seguinte forma: o primeiro nível do tradutor busca as instruções CISC na memória, como um processador comum. As instruções são traduzidas gerando uma ou mais 34 instruções MIPS equivalentes. A cada envio de uma instrução traduzida para o processador, o tradutor calcula o novo endereço da memória de instruções. O componente de hardware do primeiro nível do tradutor binário é composto por quatro diferentes unidades: Tradução, Montagem, PC (Program Counter) e uma unidade de Controle, formando dois estágios de pipeline, para que seja possível a tradução e o cálculo do novo endereço ao mesmo tempo. Na Figura 3.2 é proposta uma visão geral do mecanismo de tradução. Figura 4.2 – Unidades do mecanismo de tradução binária Fonte: [Fajardo Jr, 2011] A Unidade de Tradução é responsável por buscar as instruções x86 da memória (uma instrução por vez), analisar o seu formato, quantidade de bytes que a compõe e classificá-la de acordo com a operação, operadores e modo de endereçamento, gerando então instruções equivalentes MIPS. Nesta unidade é realizado principalmente operações de acesso a tabelas. Além de realizar a tradução, esta unidade deve fornecer informações para as unidades auxiliares como: a quantidade total de bytes no qual a instrução x86 é formada (importante para o cálculo do endereço da próxima instrução), o número de instruções MIPS geradas para verificar a disponibilidade na fila de instruções da unidade de montagem, e ainda informar o tipo de instrução (operação 35 lógica, saltos condicionais ou incondicionais, flags de estado que poderão ser modificadas pela instrução, etc). Esta unidade possui 4 diferentes tabelas e um hardware especial para manipular valores imediatos. Em cada uma destas tabelas e hardware de imediatos, as saídas são bits de configuração para serem enviadas ao componente de hardware responsável por descartar bits de configuração que não serão utilizados e os colocar em ordem correta. Neste instante são conhecidos a operação da instrução e os operadores que compõem determinada instrução x86. Na sequência, os bits de configuração são enviados para a unidade que decodifica esta informação e a partir dela monta a instrução no formado do conjunto MIPS. As instruções MIPS são geradas dependendo da sua operação: nos formatos R, I ou J. O processador MIPS utilizado busca novas instruções vindas do tradutor binário de forma sequencial, da mesma forma que o processador original busca suas instruções de uma memória regular. A Unidade de Montagem disponibiliza as instruções equivalentes MIPS de forma sequencial como se fosse uma memória comum, e é formada por um banco de registradores de 32 bits, nos quais as instruções provenientes da Unidade de Tradução são alocadas. A cada ciclo é enviado para a Unidade de Controle a quantidade de instruções que estão ocupando os registradores, de forma a garantir que não existirá descontinuidade no processo de fornecimento de instruções MIPS para o processador, reduzindo eventuais bolhas ou paradas na execução do código que possam surgir. A instruções x86 possuem tamanhos variáveis, impossibilitado o reaproveitamento do hardware do processador MIPS para o cálculo do próximo endereço na busca de novas instruções. Desta forma, foi implementada uma Unidade de PC, que calcula o próximo endereço da nova instrução a ser buscada na memória, baseando-se na quantidade de bytes em que é composta a instrução x86 corrente, e somando esse número ao endereço atual, ou calculando o endereço através de um valor imediato contido em uma instrução de salto incondicional. A Unidade de Controle permite que seja mantida a sincronia e a consistência da informação entre as unidades de Tradução, Montagem e de PC. A unidade de controle pode repassar informações como o momento em que a Unidade de Tradução pode buscar uma nova instrução na memória ou como deve ser calculado o endereço de PC. Esta unidade é baseada em uma máquina de estados finitos. 36 A segunda etapa da tradução contém uma arquitetura reconfigurável denominada DIM (Dynamic Instruction Merge), desenvolvida por [Beck e Carro, 2005] [Beck et al., 2008]. A arquitetura DIM é composta por um sistema de tradução binária, uma TCache onde são alocadas as configurações geradas pelo tradutor e uma unidade reconfigurável responsável pela execução das configurações. A unidade reconfigurável é formada por uma matriz dinâmica de grão grosso fortemente acoplada ao processador, o que propicia que a reconfiguração ocorra em unidades funcionais completas. Na fase de execução do código, a unidade reconfigurável funciona como uma extensão do estágio de execução do processador, atuando de forma totalmente independente e sem a necessidade de acesso externo. A matriz de unidades funcionais possui duas dimensões, onde cada instrução é alocada na interseção entre uma linha e uma coluna. As unidades funcionais alocadas lado a lado podem executar operações em paralelo, já as unidades alocadas na mesma coluna se caracterizam por executar as operações de forma combinacional, uma após a outra. Desta forma, se duas instruções não possuem nenhum tipo de dependência de dados entre si, existe a possibilidade de serem alocadas na mesma linha, ou seja, com execução paralela. Caso contrário, serão obrigatoriamente alocadas em linhas diferentes. Cada coluna possui um número pré-determinado de unidades funcionais, podendo ser ULAs, multiplicadores, unidades de load/store, entre outras. Dependendo do tempo de execução de cada unidade funcional, o processador pode executar mais de uma operação por ciclo de relógio. No exemplo da Figura 4.3, o primeiro grupo de unidades funcionais suporta a execução de até 4 operações em paralelo por meio de suas ULAs, o segundo grupo suporta duas unidades de leitura/escrita (load/store) em paralelo e o terceiro grupo oferece uma unidade multiplicadora dedicada. 37 Figura 4.3 – Configuração de uma unidade reconfigurável da arquitetura DIM Fonte: [BECK. e CARRO, 2005] O processo de reconfiguração ocorre da seguinte forma: os valores contidos em um banco de registradores são enviados por um barramento de operadores, de modo que cada linha do barramento é conectada a todas as unidades funcionais por meio de multiplexadores – Fig. 4.3(a). Na sequencia de cada unidade funcional é acoplado um multiplexador de saída – Fig. 4.3(b), que seleciona em qual linha do barramento será destinado o resultado da operação. A partir do quadro da Fig. 4.3(c), a primeira instrução é alocada na primeira unidade lógica (visualizada de baixo para cima), armazenando o resultado da adição. A Figura mostra a sequência de armazenamento de dados das instruções nas linhas e colunas das unidades lógicas de acordo com a dependência verdadeira de dados entre as instruções, definindo a ordem de execução em série ou em paralelo. As instruções 6 e 7 possuem dependência com as instruções 1, 2 e 3, devendo ser executadas no próximo ciclo de relógio e alocadas nas unidades de load/store correspondentes. Já a instrução 8 possui dependência direta com a instrução 7, o que também impossibilita o uso da unidade multiplicadora no mesmo ciclo, ocasionando um terceiro ciclo de relógio. Os blocos básicos desta unidade são sequências de código situadas entre desvios ou chamadas de função. A execução do tradutor se inicia após uma instrução de desvio e finaliza ao encontra outra instrução não suportada ou uma nova instrução de desvio. A implementação do tradutor possui 4 estágios: decodificação, análise de dependências, atualização de tabelas e montagem de configuração. A instrução é decodificada no 38 primeiro estágio, fornecendo para o segundo estágio informações como tipo de operação e operadores. O segundo estágio verifica as dependências para manter a coerência dos dados durante a execução. O terceiro estágio atualiza as tabelas de configurações e o último estágio organiza as tabelas e monta uma nova configuração quando houver uma quebra de configuração ocasionada por uma instrução de desvio ou não suportada. Um conjunto de tabelas é utilizado para manter as informações sobre a sequência de instruções processadas, responsáveis por armazenar dados como configuração dos multiplexadores, operação das ULAs, mapa binário da alocação de cada instrução na matriz, tabela de dados a serem buscados no banco de registradores, entre outros. O processo de tradução ocorre de forma paralela ao processador. Ao finalizar o processo de tradução, é montada uma configuração indexada ao endereço da primeira instrução da sequência do código traduzido, armazenada na TCache para um futuro reuso. Caso uma mesma sequência de código for encontrada pela segunda vez, será encontrada na TCache a configuração com o mesmo endereço e com o código já traduzido e otimizado. Desta forma, ocorre uma execução direta do código na unidade reconfigurável, dispensado o uso do processador MIPS e da tradução binária. 3.2. Considerações A técnica apresentada neste trabalho se diferencia das demais, e até a conclusão deste texto não foram encontrados na literatura trabalhos semelhantes, que utilizem técnicas de reconfiguração de instruções para adaptação de processadores a uma ISA padrão, sem a necessidade de técnicas como interpretação, compilação ou tradução. Apesar da técnica de tradução binária apresentada utilizar dispositivos reconfiguráveis e configurações de instruções, sempre faz-se necessária uma primeira leitura do código e modificação de sua estrutura para prover o novo conjunto de instruções na arquiteturaalvo. Nos capítulos seguintes, será mostrado que esta metodologia possibilita criar novas instruções diretamente na arquitetura por meio de uma unidade de reconfiguração externa ou de um acréscimo no código-fonte no programa armazenado em uma memória RAM, permitindo a execução direta de suas novas instruções como se fossem instruções do conjunto nativo da arquitetura. 39 Capítulo 4 – Microarquiteturas microprogramadas propostas 5. Neste capítulo são apresentados os dois processadores microprogramados genéricos utilizados para adaptação à ISA MIPS. Os processadores foram descritos utilizando a linguagem VHDL e projetados para funcionarem como um processador de propósito geral com possibilidade de reconfiguração de instruções, sendo que cada um destes executa a reconfiguração de modos distintos. 4.1 Processador CABARE O CABARE (Computador Acadêmico BAsico com REconfiguração), desenvolvido por [Silva, 2011], foi projetado para ser um processador RISC de propósito geral de baixa complexidade de hardware, composto por um pequeno conjunto de instruções sem padrão específico e uma lógica reconfigurável capaz de receber e executar instruções que não estão presentes no conjunto de instruções original, sendo tais instruções previamente armazenadas em posições definidas na memória. A arquitetura do CABARE foi baseada em [Altera, 2013] como um exercício didático da fabricante de FPGA’s Altera® para demonstrar o funcionamento do Modelo de Von Neumann [Stallings, 2010] em um processador single-tasking1. Tal estrutura foi modificada para incluir novas instruções, operações, funcionalidades e a lógica de reconfiguração. A organização física de 32 bits do CABARE é formada por um conjunto de 12 registradores de propósito geral (R0 a R11) e um registrador (R12) utilizado como contador de programa (PC), um multiplexador (MUX) de 16 canais de entrada, um registrador de instrução (IR), uma ULA com a primeira entrada ligada exclusivamente a um registrador acumulador (A) e a segunda entrada ligada ao barramento de dados, com 1 Processadores que executam uma única instrução por ciclo de relógio. 40 a saída conectada a um registrador de resultado (G), além de registradores para interface com a memória (DOUT e ADDR). Uma visão geral do CABARE está ilustrada na Figura 4.1. Figura 5.1 - Arquitetura do processador CABARE Fonte: autoria própria A entrada de dados no processador é realizada por meio de um barramento de entrada de 32 bits (DIN), que recebe os dados provenientes da memória externa e os envia para uma das entradas do multiplexador. A saída do multiplexador é chamada de barramento de dados (BUS), e está conectado a quase todos os demais registradores do processador (R0 a R12, A, DOUT, ADDR e a ULA). Todas as instruções lógicas e aritméticas necessitam de, no mínimo, três ciclos de relógio para sua execução, visto que existe apenas um barramento de dados que conecta os registradores à ULA, e um dos operandos de entrada deve ser obrigatoriamente armazenado no registrador acumulador A. Esta configuração demonstra a simplicidade do CABARE. A ordem dos canais de entrada do multiplexador para envio ao barramento de dados está disposta na Tabela 4.1. 41 Tabela 5.1 – Registradores de uso geral no CABARE Entrada do MUX R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 (PC) Mask G DIN Endereço (bin) 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 A ULA é responsável pelas operações lógicas e/ou aritméticas de soma, subtração, E lógico, OU lógico, NÃO lógico, transparência (throughput) e deslocamento de 1 bit à esquerda ou à direita. Também possui alguns flags que indicam se a operação resultou em zero (Z), um número negativo (S) ou se houve uma propagação de carry (Cy) a partir do seu MSB (Most Significative Bit). A relação de operações da ULA está descrita na Tabela 4.2. Tabela 5.2 – Operações da ULA do CABARE Código 000 001 010 011 100 101 110 111 Operação Soma Subtração And Or not A Transparência deslocamento para direita deslocamento para esquerda O CABARE possui um conjunto composto por 20 instruções de 32 bits de palavra, de modo que cada instrução possua um único formato válido, na forma: IIIIIIIIXXXXYYYYZZZZZZZZZZZZZZZZ, onde IIIIIIII (8 bits) representa o código da operação (CodOp), XXXX (4 bits) o registrador RX, YYYY (4 bits) o registrador RY e ZZZZZZZZZZZZZZZZ (16 bits) um valor constante de 16 bits. Caso a instrução 42 utilize apenas dois registradores como operandos, então os 16 bits restantes não são considerados, podendo receber qualquer valor (Don’t Care). Quando a instrução utiliza apenas um registrador, os bits YYYY não são considerados, mas não podem fazer parte do valor constante, ou seja, a constante #D ocupa apenas os 16 bits reservados na palavra da instrução. A cada busca na memória externa, a instrução atual é enviada para o registrador de instrução (IR), que o encaminha à unidade de controle para decodificação. A constante de 16 bits presente na instrução é enviada da unidade de controle para o barramento por meio da entrada Mask, cujo valor de 32 bits contém o valor 0x0000DDDD, obtido após uma operação AND cuja finalidade é eliminar os primeiros 16 bits da instrução contendo o código da operação e o endereço dos registradores, cujos valores não devem fazer parte da constante #D. Este sistema executa as instruções apresentadas na Tabela 4.3. 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, enquanto que a expressão Rx ← #D indica que um valor constante #D de 32 bits é carregado no registrador Rx. Tabela 5.3 – Operações realizadas pelo processador CABARE Código da Operação (Bin) 00000000 00000001 00000010 00000011 00000100 00000101 00000110 00000111 00001000 00001001 00001010 00001011 00001100 00001101 00001110 00001111 Código da Operação (Hexa) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F Operação Função Executada 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 shr Rx, Ry jnc #D 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 Rx ← [Ry] >> 1 IF Cy != 0, PC ← #D 43 00010000 00010001 00010010 00010011 00010100 a 00011110 00011111 1111xxxx 10 11 12 13 14 a 1E 1F --- jns #D jz #D jc #D js #D Reservado IF S != 0, PC ← #D IF Z = 0, PC ← #D IF Cy = 0, PC ← #D IF S = 0, PC ← #D --- PC ← PC (fim) Halt Configuráveis --- A arquitetura pode executar diferentes operações a cada ciclo, controladas pela unidade de controle (control unit). Essa unidade determina quando um dado em particular é enviado ao barramento e qual registrador deve carregá-lo. Por exemplo, se a unidade de controle determinar MUX em 0x0000 e ativar o bit AIn, então o multiplexador transmitirá o conteúdo de R0 para o barramento e esse dado será carregado no acumulador A na próxima subida de relógio. A Tabela 4.4 indica os sinais de controle que devem ser ativados em cada pulso de relógio para cada instrução. Tabela 5.4 – Sinais do controle do CABARE em cada instrução/tempo T0 (mv): IRIn (mvi): IRIn (mvnz): IRIn (add): IRIn (sub): IRIn (and): IRIn (or): IRIn (not): IRIn (ld): IRIn (st): IRIn (ldi): IRIn (jmp): IRIn T1 T2 MUX=Ry, RxIn, Done MUX=Mask, RxIn, Done Se !Z=> MUX=Ry, Gin MUX=G, RxIn, Done Senão => Done MUX=Rx, AIn MUX=Ry, ULA=add, GIn MUX=Rx, AIn MUX=Ry, ULA=sub, GIn MUX=Rx, AIn MUX=Ry, ULA=and, GIn MUX=Rx, AIn MUX=Ry, ULA=or, GIn MUX=Rx, ULA=not, MUX=G, RxIn, Done GIn MUX=Ry, ADDRIn, MUX=DIN, RxIn, R_D Done MUX=Rx, DOUTIn MUX=Ry, ADDRIn, W_D, Done MUX=Rx, ULA=transp, GIn, Done MUX=Mask, R12In, Done T3 MUX=G, RxIn, Done MUX=G, RxIn, Done MUX=G, RxIn, Done MUX=G, RxIn, Done 44 (jnz): IRIn (shl): IRIn (shr): IRIn (jnc): IRIn (jns): IRIn (jz): IRIn (jc): IRIn (js): IRIn (halt): IRIn Se !Z=> MUX=Mask, R12In, Done Senão => Done MUX=Ry, ULA=shl, MUX=G, RxIn, Done GIn MUX=Ry, ULA=shr, MUX=G, RxIn, Done GIn Se !Cy=> MUX=Mask, R12In, Done Senão => Done Se !S=> MUX=Mask, R12In, Done Senão => Done Se Z=> MUX=Mask, R12In, Done Senão => Done Se Cy=> MUX=Mask, R12In, Done Senão => Done Se S=> MUX=Mask, R12In, Done Senão => Done - 4.1.1. Reconfiguração de instruções O CABARE usa uma arquitetura RISC com 20 instruções “fixas” (já presentes no processador durante sua concepção), 10 códigos de operações não utilizados, reservados para uso futuro, e 16 códigos de operações livres para novas instruções. Este tipo especial de código de operação não é definido previamente na unidade de controle, sendo necessária a criação de um conjunto de microinstruções pelo usuário, os quais devem ser armazenados na memória externa juntamente com o restante do programa armazenado (dados e instruções). A fim de simplificar a definição da quantidade de instruções reconfiguradas e sua faixa de representação, todos os códigos de operação (CodOp’s) com os 4 bits iniciais iguais a ‘1’ foram reservados para instruções reconfiguradas (códigos 0xFF00 a 0xFFFF). Ao decodificar o CodOp de uma instrução reconfigurada, a unidade de controle deverá buscá-la na memória em uma região de memória previamente delimitada para armazenar os dados de cada instrução. A memória externa deve ser logicamente dividida em quatro áreas bem definidas: área de instruções, área de dados, armazenamento de microinstruções e área 45 de ponteiros, sendo esta última contendo o endereço de cada primeira microinstrução reconfigurada inicial, conforme mostra a Figura 4.2. A área de ponteiros reserva as últimas 16 células da memória para cada uma das 16 instruções reconfiguradas, independente do tamanho da memória utilizada. Dessa forma, o CodOp 0xF0 deverá ser associado ao endereço de memória 0xFF...F0, o CodOp 0xF1 associado ao endereço 0xFF...F1, e assim sucessivamente. Para inicializar os dados e instruções na memória, é utilizada uma MIF (Memory Initialization File) contendo todas estas áreas em intervalos definidos pelo programador. Figura 5.2 – Distribuição de memória no CABARE Fonte: autoria própria Uma instrução reconfigurável é um conjunto de n palavras de 32 bits, de modo que cada palavra refere-se a uma microinstrução. Os campos desta palavra são os bits de controle de todas as unidades funcionais do caminho de dados do processador, como os bits de escrita dos registradores, os bits de operação da ULA, seleção do multiplexador, dentre outros. Para poder modificar o comportamento do caminho de dados, é preciso que todos os bits de controle do caminho de dados possam ser alterados por meio de uma microinstrução, exigindo total compreensão sobre o funcionamento da organização e arquitetura do processador por parte do programador, incluindo detalhes sobre quantidade e função de cada registrador, a ordem das entradas do multiplexador e o índice de operações da ULA. Como explicado no Cap. 2, o caminho de dados dos processadores RISP não é reconfigurado fisicamente; suas unidades funcionais se comportam conforme especificado em cada nova microinstrução, definindo a cada etapa 46 qual registrador será enviado como operando da ULA, que operação aritmética ou lógica será realizada e o registrador que receberá o resultado da operação. Para criar uma microinstrução, é necessário definir os bits de controle do processador e selecionar um dos formatos de microinstrução, presentes na Tabela 4.5. O formato (a) envia todos os bits de controle para as unidades funcionais correspondentes na unidade operativa, de acordo com a ordem estabelecida. O formato (b) é utilizado para operações de desvio condicional e incondicional dentre as microinstruções reconfiguradas de um mesmo CodOp, por meio do envio do endereço de memória para um registrador de índice de estados reconfiguráveis. O formato (c) envia apenas os sinais de controle de escrita nos registradores, utilizando os 16 bits menos significativos para endereçamento ou operações com valores imediatos. Tabela 5.5 - Configuração de uma microinstrução no CABARE Formato 4 R0In...12In 13 ULA 3 Formato 4 JMP 1 MUX 4 Z 1 Formato 4 IR 1 Z’ 1 A G 1 1 (a) S 1 S’ 1 (b) DOUT 1 CY’ 1 CY 1 R0In...R12In 13 (c) ADDR 1 6 WD 1 RD 1 END 1 END 15 END 15 Os primeiros 4 bits de cada microinstrução alteram o formato da palavra. Com apenas uma configuração, não seria possível realizar uma integração entre os bits que compõem o código da instrução e suas respectivas microinstruções. Como exemplo, caso fosse utilizada uma instrução 0xF067000A, os bits referentes aos campos de registradores X = R6, Y = R7 e endereço ADDR = 0x000A só poderiam ser utilizados em uma única ordem na execução da instrução, já que não haveria como alterar estas informações em diferentes microinstruções. Variando a quantidade de formatos, é possível prover esta alteração de ordem dos dados em diferentes microinstruções, aumentando a gama de possibilidades de reconfiguração. A Tabela 4.6 apresenta os formatos de instrução definidos para este processador. 47 Tabela 5.6 – Formatos de microinstruções do CABARE Formato 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 Utilização da microinstrução microinstrução tipo (a) microinstrução tipo (c) R_In = Rx R_In = Ry MUX = Rx MUX = Ry R_In = Rx se Z = 0 R_In = Ry se Z = 1 R_In = Rx se S = 0 R_In = Ry se S = 1 R_In = Rx se Cy = 0 R_In = Ry se Cy = 1 MUX = Rx se Z = 1 MUX = Rx se S = 1 MUX = Rx se Cy = 1 MUX = ‘-‘ Não foi definido um limite mínimo ou máximo de palavras para cada instrução reconfigurável, sendo este trabalho realizado pelo programador. A única obrigatoriedade está no fato de que a última microinstrução de cada instrução reconfigurada deve ter o valor do seu bit_end setado (‘1’), o que indica para a unidade de controle voltar ao modo de execução normal. A Figura 4.3 apresenta um quadro detalhando as etapas para a execução de uma instrução reconfigurada. Figura 5.3 – Sequência de execução de instruções reconfiguradas no CABARE 48 É possível que uma instrução reconfigurada seja exatamente igual a uma instrução já existente no conjunto de instruções do processador, com exceção das instruções de desvio. Isto permite a uma instrução reconfigurada criar um bloco de instruções ou uma combinação de duas ou mais instruções a partir de um único CodOp, com funcionamento análogo a uma sub-rotina. Embora uma instrução reconfigurada possa substituir uma instrução fixa, tal procedimento não é recomendado para reconfigurar apenas uma única instrução, visto que a quantidade de ciclos de relógio para executar uma instrução reconfigurada é maior do que a quantidade de ciclos para uma instrução existente no conjunto de instruções. A execução de instruções reconfiguradas ocorre de maneira semelhante às instruções fixas, com a inclusão de alguns ciclos adicionais para o endereçamento indireto da primeira microinstrução customizada. O valor de PC somente será atualizado após o término do microprograma da instrução reconfigurada. 4.1.2. Exemplo de funcionamento 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. O exemplo do quadro a seguir 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 Seguindo o formato de instrução já apresentado, a primeira instrução (mvi r5,#9) possui CodOp (IIIIIIII) como 0x01 e o registrador R5 (XXXX) possui o código 0x5. Como essa instrução não utiliza o segundo registrador, então o valor YYYY foi codificado como 0x0. O valor da constante de 16 bits (ZZZZZZZZZZZZZZZZ) recebe o valor 0x0009. Esta e as demais instruções do exemplo são detalhadas na Tabela 4.7. 49 Tabela 5.7 – Código objeto para o exemplo 1 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 Código objeto 0009 0001 0000 0000 000004 0000 01500009 01400001 08650000 04640000 0C000004 1F000000 O próximo exemplo mostra como inserir uma instrução reconfigurada ADDI X, Y, D (X Y + D), que não consta no conjunto de instruções original do CABARE. A instrução 0xF0670005 tem como objetivo fazer com que o registrador R6 (registrador na posição X da instrução) receba o resultado da adição do registrador R7 (registrador na posição Y da instrução) com o valor imediato D = 0x0005. Estas microinstruções devem ser descritas pelo usuário, definindo os sinais de controle de acordo com o comportamento desejado em cada etapa da instrução, e inseridas nas posições correspondentes na memória seguindo configuração de áreas da MIF. Ao decodificar o código de operação desta instrução, os bits 0xF0 informam que a instrução é do tipo reconfigurada, ocasionando uma busca no endereço de memória 0xF...F0, que aponta para o início da sequência das seguintes microinstruções: (1) ACC R7 (Y) Formato 0101 R0In ... R12In 0000000000000 ULA 101 MUX POS2 IR 0 A 1 G 0 DOUT 0 ADDR 0 WD 0 RD 0 END 0 ADDR 0 WD 0 RD 0 END 0 ADR 0 WD 0 RD 0 END 1 (2) MUX END (D), ULA = ADD (G = A + 0x0D) Formato 0001 R0In ... R12In 0000000000000 ULA 000 MUX MASK IR 0 A 0 G 1 DOUT 0 (3) R6 (X) G, fim de procedimento Formato 0010 R0In ... R12In POS1 ULA 101 MUX MUX_G IR 0 A 0 G 0 DOUT 0 Após o final da sequência de microinstruções, o valor do PC é atualizado, continuando a sequência de execução do processador. As instruções reconfiguradas podem ser utilizadas dentro de um programa da mesma forma que uma instrução fixa. 50 4.2. Processador CRASIS O processador CRASIS (Computer with Reconfiguration And Selection of Instruction Set) foi desenvolvido por [Casillo, 2005]. A organização do processador foi inspirada na arquitetura MIC-1, descrito por [Tanembaum, 2007] e sua versão final apresentada em [Casillo, 2005a]. Trata-se de uma arquitetura RISC de 32 bits de palavra desenvolvida como uma prova de conceito de uma microarquitetura genérica que possa conter vários conjuntos de instruções, alternados a qualquer momento em tempo de execução, ajustando o conjunto de instruções que melhor se adapte ou que contenha as melhores instruções para executar um determinado programa, além de prover a criação de novas instruções por meio de uma unidade de reconfiguração dedicada. Sua unidade operativa é composta por um banco de 32 registradores, sendo quatro destinados a funcionalidades específicas, como acumulador e apontador de pilha e o restante para uso geral, um deslocador de 32 bits para a esquerda ou direita, e uma ULA com capacidade para 8 operações distintas: transparência do primeiro operando, AND e OR lógicos, negação do primeiro operando, negação do segundo operando e operações aritméticas de adição, subtração e multiplicação de dois operandos. Para a comunicação com a memória, são utilizados dois registradores de interface, sendo um para endereços (MAR) e um para dados (MBR). A Figura 4.4 ilustra o caminho de dados. Figura 5.4 – Diagrama de blocos do processador CRASIS Fonte: autoria própria 51 Todas as instruções possuem 32 bits de palavra. Existem 5 formatos diferentes de instruções, que utilizam de 0 a 4 operandos. Em todos os formatos de instrução, o primeiro byte é destinado ao CodOp, sendo os demais utilizados para endereçamento ou para determinação do(s) registrador(es) selecionado(s) para a operação. Cada novo formato exclui 5 bits do campo de operando para a seleção de um registrador. Dessa forma, o campo de operando possui 24 bits no primeiro formato, 19 bits no segundo formato, e assim sucessivamente. A Figura 4.5 mostra a disposição de bits para cada formato de instrução. Figura 5.5 – Formatos de instrução do CRASIS Fonte: autoria própria A característica de reconfiguração do CRASIS não está na modificação de sua parte operativa, e sim na possibilidade de criar e reconfigurar instruções em sua unidade de controle, utilizando uma RFU (Reconfiguration Functional Unit) externa. Assim como no CABARE, para efetuar qualquer reconfiguração é necessário o conhecimento de todas as unidades funcionais do processador e seu funcionamento, visto que a RFU terá como funcionalidade armazenar os códigos de operação das novas instruções e os seus respectivos microprogramas, formados por uma sequência de sinais de controle que definem o comportamento de cada uma das unidades funcionais de sua unidade operativa. A Figura 4.6 apresenta uma visão geral do CRASIS contendo todas as suas unidades funcionais. 52 Figura 5.6 – Arquitetura do processador CRASIS Fonte: autoria própria 53 4.2.1. Modos de funcionamento O CRASIS pode atuar sob dois modos de funcionamento: modo de reconfiguração e modo de execução, sendo que o modo de execução pode ser subdividido em execução de instruções fixas (instruções contidas nos conjuntos de instruções) e execução de instruções reconfiguradas (instruções criadas ou combinadas a partir da unidade de reconfiguração). A Figura 4.7 mostra um diagrama simplificado contendo a máquina de estados (FSM – Finite State Machine) destes modos de funcionamento. Figura 5.7 – Diagrama de estados simplificado do CRASIS Fonte: autoria própria A determinação de qual modo de funcionamento será realizado é feita através do estado denominado Verifica_Reconfiguração. Este estado é responsável por verificar se houve um pedido de reconfiguração de uma instrução através do sinal de requisição externo. Caso este sinal contenha um pedido externo de reconfiguração, será iniciada a sequência de reconfiguração de instruções; caso contrário será iniciado o processo de execução normal. Ao iniciar a execução de uma instrução, é verificado se a instrução atual é fixa ou customizada. Caso já seja existente no conjunto de instruções, a unidade de controle envia os comandos correspondentes aos estados que compõe a instrução, tal qual se encontra no conjunto de instruções selecionado. Caso contrário, a unidade de controle 54 busca os estados correspondentes à instrução customizada armazenados na unidade de reconfiguração. Com o intuito de validar a proposta do processador de conter diversos conjuntos de instruções e poder alterná-los durante o seu funcionamento, foram implementados três conjuntos de instruções simples compostos por 32 instruções cada, sendo 30 de propósito geral específicas de cada conjunto, e 2 instruções privilegiadas comuns a todos os conjuntos, para possibilitar a alternância entre os conjuntos. O conjunto de instrução 1 é similar ao conjunto apresentado em [Tanembaum, 2007] para o MIC-1, com o acréscimo de instruções de tratamento de interrupção e Entrada/Saída. Neste conjunto apenas o acumulador e o apontador de pilha (Stack Pointer - SP) são acessíveis ao usuário. O segundo conjunto possui instruções em que todos os 32 registradores são acessíveis ao usuário e o terceiro conjunto é baseado em instruções que utilizam operações envolvendo a pilha. Cada conjunto possui uma quantidade própria de estados necessários para implementar suas instruções, sem interferir em outros conjuntos. A Tabela 4.8 contém as instruções presentes em cada um dos 3 conjuntos implementados. Tabela 5.8 – Operações realizadas pelo processador CRASIS Código da Operação (Bin) 00000000 00000001 00000010 00000011 00000100 00000101 00000110 00000111 00001000 00001001 00001010 00001011 00001100 00001101 00001110 00001111 11110000 11110001 Conjunto 1 Conjunto 2 Conjunto 3 LODD X STOD X LOCO X LODL X STOL X ADDL X SUBL X CALL X JUMP X JNEG X JPOS X JNZE X JZER X ADDD X SUB DX MULL X RETN PSHI LODD X STOD X LOCO X LODL Rx, Y STOL Y, Rx LODR Ra, Rx, Ry STOR Ra, Rx, Ry CALL X JUMP X JNEG X JPOS X JNZE X JZER X ADDR Ra, Rx, Ry SUBR Ra, Rx, Ry MULL Ra, Rx, Ry RETN SHL LODDp X STODp X LOCO X LODLp X STOLp X LODIp X STOIp X CALL X JUMP X JNEG X JPOS X JNZE X JZER X ADDp X SUBp X MULp X RETN SHLp 55 11110010 11110011 11110100 11110101 11110110 11110111 11111000 11111001 11111010 11111011 11111100 11111101 11111110 11111111 POPI PUSH POP SWAP SETI RETI INSP DESP LDIO STIO - SHR PUSH POP SWAP SETI RETI INSP DESP LDIO STIO muda_conj muda_modo SHRp PUSH POP SWAP SETI RETI INSP DESP LDIO STIO - A criação de um CodOp compartilhado exigiu a criação do conceito de “superestados”. Dessa forma, cada uma das 27 instruções presentes no CRASIS pode ser subdividida em até 3 subconjuntos distintos. Por exemplo, o CodOp “00000101” (OP_5) corresponde às instruções ADDL X para o conjunto 1, LODR Ra, Rx, Ry para o conjunto 2 e LODI para o conjunto 3. A instrução ADDL necessita de apenas um operando, a instrução LODR necessita de 3 operandos para identificação dos registradores, e a instrução LODI não requer nenhum operando adicional. A Figura 4.8 ilustra o diagrama de estados desta operação. Figura 5.8 – Diagrama de estados de um super-estado Fonte: autoria própria 56 O primeiro super_estado da instrução OP5 (OP5_1) contém a microinstrução referente ao início da instrução ADDL X do conjunto 1, a microinstrução referente ao início da instrução LODR Ra, Rx, Ry do conjunto 2 e a microinstrução referente ao início da instrução LODI do conjunto 3. O segundo super_estado (OP5_2) contém as microinstruções pertencentes aos conjuntos 2 e 3, enquanto que o terceiro super_estado (OP5_3) contém apenas a microinstrução referente ao conjunto 3. A implementação de super-estados é realizada utilizando estruturas de decisão dentro da unidade de controle, após a decodificação de uma instrução. Como exemplo, a instrução de CodOp 00001101 possui a seguinte implementação: Se conjunto = 1 então instrução = ADD X Estado 13.1: MAR := IR; RD; Próximo estado = 13.2 Senão Se conjunto = 2 então instrução = ADDD Ra, Rx, Ry Estado 13.1: Ra := Rx + Ry; GOTO INT; Próximo estado = verificação de interrupção Senão Se conjunto = 3 então instrução =ADDp Estado 13.1: MAR := SP; RD Próximo estado = 13.2 fimse fimse fimse Isto mostra que um mesmo CodOp podem estar relacionado a diferentes instruções, cada uma cotendo uma quantidade de microinstruções distintas, bem como existe a possibilidade de unir instruções de diferentes conjuntos de instruções em um mesmo estado, compensando a quantidade de linhas de código a mais utilizadas nas estruturas de decisão para a seleção do conjunto. Para que o usuário possa alternar entre os conjuntos de instruções, foram criadas duas instruções, denominadas muda_conj e muda_modo. A função da instrução muda_conj consiste em alterar o conjunto de instruções atualmente utilizado. Foi utilizado um registrador de 8 bits denominado registrador de estado dentro da unidade de controle. Este registrador é responsável por armazenar os bits que informam qual conjunto está selecionado atualmente. 57 A codificação dos dois últimos bits presentes na instrução define qual conjunto será selecionado. O valor “00” seleciona o conjunto 1, o valor “01” seleciona o conjunto 2 e o valor “10” seleciona o conjunto 3. Ao executar a instrução muda_conj, estes bits são enviados ao registrador de estado, indicando qual conjunto deve ser selecionado. O registrador de estado é alterado somente mediante esta instrução, portanto não é possível alternar entre os conjuntos durante a execução de uma instrução. Por definição, a cada reinício do processador, o conjunto de instruções 1 é selecionado. A instrução muda_modo altera o modo de funcionamento do processador. Ao executar esta instrução, os bits 7 e 6 da instrução são enviados ao registrador de estado, codificados da seguinte forma: o valor “00” representa o modo usuário e o valor “01” representa o modo supervisor. Somente é possível utilizar a instrução muda_conj se o processador estiver em modo supervisor. 4.2.2. Exemplo de funcionamento O exemplo apresentado na Figura 4.9 mostra o comportamento dos blocos funcionais da unidade operativa durante a execução da instrução de CodOp “0000010” (0X02). Este CodOp representa a instrução LOCO X (Load Constant X), presente em todos os conjuntos implementados, a qual possui apenas uma microinstrução: Acc := BAND(AMASK, IR); GOTO INT. Figura 5.9 – Exemplo de execução de instrução no CRASIS Fonte: autoria própria 58 O significado desta microinstrução consiste no acumulador (registrador “00001”) receber o resultado de uma operação AND binária entre o valor do registrador de instrução (IR) e da máscara de endereços (AMASK = 0x00FFFFFF). Como resultado, o acumulador receberá uma constante de 32 bits, formada pelos 24 bits menos significativos de IR, ou seja, 0x00XXXXXX. Durante a decodificação, se os quatro primeiros bits do CodOp forem “0000” ou “1111”, significa que a instrução pertence a algum dos conjuntos fixos, dando sequência ao processo. Caso contrário, se a instrução a ser executada for reconfigurável, será iniciado processo de execução de instruções reconfiguradas. Uma instrução reconfigurada é composta por uma ou mais microinstruções que formam um microprograma que modela sua execução, formada por 28 bits de controle, dispostos na Tabela 4.9. Tabela 5.9 – Palavra de uma microinstrução no CRASIS Form 6 bits AMUX 2 bits BMUX 2 bits ULA 3 bits SH 6 bits MBR 1 bit MAR 1 bit ENC 1 bit MUX MUX MAR MBR 2 bits 1 bit WR RD BIT_ END 1 bit 1 bit 1 bit As instruções podem conter 1 a 4 registradores como operandos de entrada ou saída, podendo assumir os formatos “OP A” a “OP A,B,C,D”. Dependendo do formato utilizado e da quantidade de operações que compõe a instrução, um registrador utilizado como destino na microinstrução ‘1’ pode ser utilizado como entrada na microinstrução ’2’, permitindo uma maior integração entre diferentes etapas de uma mesma instrução, como uma realimentação de dados. As possibilidades de cada um dos demais bits de controle são apresentadas na Tabela 4.10: Tabela 5.10 – Bits de controle do CRASIS Nome Função Valores Form Define formato da instrução Vide Apêndice B AMUX Operando esquerdo da ULA 00 – Barramento A 01 – Barramento C 10 – AMASK 11 – MBR BMUX Operando direito da ULA 00 – Barramento B 59 01 – Constante ‘1’ 10 – IR 11 – 0x00 & IR(18-0) ULA 000 – A Operação lógica/aritmética 001 – A AND B 010 – NOT(A) 011 – NOT(B) 100 – A + B 101 – A - B 110 – A * B 111 – A OR B SH Tipo/Quant. de deslocamentos Bit 1 – Direção (esq/dir) Bits 2-6 – quantidade MBR 0 – desativado Carrega buffer de dados 1 - ativado MAR 0 – desativado Carrega buffer de endereço 1 – ativado ENC Habilita MUX_MAR escrita no banco de 0 – desativado registradores 1 – ativado Seleciona entrada de MAR 00 – PC 01 – IR 10 – Latch B 11 – Barramento C MUX_MBR Seleciona entrada de MBR 0 – PC 1 – Barramento C WR Escrita na memória 0 – desativado 1 – ativado RD Leitura na memória 0 – desativado 1 – ativado BIT_END Fim de instrução 0 – não finalizada 1 – finalizada O Apêndice B apresenta todos os formatos possíveis da palavra de configuração. 60 4.2.3. Unidade de Reconfiguração A unidade de reconfiguração foi projetada para o tratamento de instruções customizadas. A Figura 4.10 ilustra, de um modo geral, os blocos funcionais constituintes desta unidade. Esta unidade possibilita criar uma instrução que não se encontra nos conjuntos de instruções já existentes ou combinar duas ou mais instruções reconfiguradas. Figura 5.10 – Unidade de Reconfiguração do CRASIS Fonte: autoria própria A reconfiguração de uma instrução ocorre quando o processador recebe um sinal externo, indicando um pedido de configuração. Neste processo, o processador deve receber um CodOp identificando a instrução customizada e as microinstruções para a configuração da instrução. Durante o processo de reconfiguração, o valor do Contador de Programa (PC) permanece com seu valor atual. Ao ser confirmado o pedido de reconfiguração, deve ser confirmado se a instrução recebida é válida, ou seja, se o CodOp recebido pode ser utilizado por uma instrução customizada. Ao ser confirmado se tratar de um CodOp válido, o processador deverá armazenar este CodOp, associando-o com os valores das palavras de configuração da instrução customizada, que devem ser armazenadas sequencialmente até que seja indicado o final da instrução. O diagrama de estados da Figura 4.11 representa os estados correspondentes ao processo de reconfiguração de uma instrução. 61 Figura 5.11 – diagrama de estados de reconfiguração no CRASIS Fonte: autoria própria A verificação do CodOp recebido é realizada da seguinte forma: os quatro primeiros bits do CodOp são comparados com os valores “0000__ e “1111__. Caso o resultado dessa comparação seja positiva, o CodOp não será considerado válido, e consequentemente a instrução não poderá ser configurada. Como resultado, é gerado um sinal de erro indicando que não é possível realizar esta operação. Caso o resultado da comparação seja negativo, o CodOp recebido encontra-se na faixa de valores reservados para instruções reconfiguráveis, ou seja, entre “0001__ e “1110__, continuando a sequência de execução. Em seguida, o valor do CodOp é armazenado em um módulo de memória RAM (Library of Parameterized Modules RAM), juntamente com um endereço que marca a posição inicial da instrução. Após a gravação do CodOp, em se tratando de uma nova instrução, a primeira microinstrução é armazenada em um novo módulo de memória RAM, no endereço que foi especificado na gravação do CodOp. O processo de armazenamento de microinstruções na memória RAM de dados é realizado até que seja verificado o bit de finalização, indicando o término do processo de gravação da instrução. Como única exceção, o CRASIS não reconfigura instruções de desvio condicional. 62 4.2.4. Exemplo de reconfiguração O exemplo a seguir ilustra uma instrução reconfigurável MAC D, A, B, C (Multiplica e Acumula), em que D = A + (B*C). Esta instrução segue o formato (OP 5, 5, 5, 5, 4) e é composta por 2 microinstruções: (1) 0xA830040 / D = B * C / Bar C = Bar B op Aux Formato AMUX BMUX ULA SH MBR MAR ENC 101010 00 00 110 000000 0 0 1 MUX_ MUX_ WR RD MAR MBR 00 BIT_ 0 0 0 0 MUX_ MUX_ WR RD BIT_ MAR MBR 00 0 0 0 END (2) 0x4C20041 / D = D + A / Bar C = Bar C op Bar A Formato AMUX BMUX ULA SH MBR MAR ENC 010011 00 00 100 000000 0 0 1 END 1 Caso o processador receba da memória uma instrução com valor 0x11390A60, a consulta ao valor de CodOp 0x11 resulta em um código não utilizado pelos conjuntos de instruções existentes, o que resultará em um estado de busca de instrução reconfigurável. Verificando a tabela de CodOp nesta posição, será encontrado o endereço da primeira microinstrução armazenada. Ajustando a instrução ao formato OP 5, 5, 5, 5, 4, tem-se o valor “00010001 00111 00100 00101 00110 0000”, o que resulta em (MAC R7, R4, R5, R6, 0000), com significado R7 R4 + (R5 * R6). 4.3. Interface com a placa DE2 Ambos os processadores foram descritos em duas versões: a primeira versão contém os códigos necessários para seu funcionamento em nível de simulação, enquanto a segunda versão foi adaptada para funcionar como uma arquitetura didática utilizando a plataforma de prototipagem DE2 da Altera®. Foi criado um sistema de funcionamento no qual é executada uma instrução por vez, por meio do acionamento de um botão denominado RUN. A cada acionamento, utilizando as chaves SW0 a SW4, pode ser visualizado nos 8 displays de 7 segmentos o valor (em hexadecimal) de cada um dos registradores do processador. Também foram utilizados leds para indicar fim de programa, erro e flags da ULA e um botão de RESET. A Tabela 4.11 exibe as chaves de seleção do multiplexador CABARE. 63 Tabela 5.11 – Chaves para seleção dos displays de 7 segmentos na DE2 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" Com o uso da DE2, é possível o acompanhamento de parte do funcionamento do processador, como verificar valores dos registradores, PC, registrador de instrução, valores lidos da memória e flags da ULA. Mas o fato de serem arquiteturas diferentes exige que as instruções sejam escritas manualmente, bit-a-bit, ou então sejam criados montadores e/ou compiladores, além de ter que adaptar um mesmo programa em diferentes algoritmos e formas de implementação. 64 Capítulo 5 – Metodologia para adaptação a uma ISA padrão 5. Este capítulo apresenta a metodologia que descreve os passos envolvidos no processo de migração de processadores 32 bits sem uma ISA específica para uma ISA padrão, sendo utilizada para estes estudos de caso a arquitetura MIPS. Para a unidade de controle, em se tratando de processadores soft-core descritos em VHDL, é necessário substituir os estados de decodificação e execução das instruções, de forma que o estado de decodificação contenha a seleção das instruções implementadas, de acordo com o Código de Operação de cada instrução MIPS. Para os estados de execução, cada uma destas conterá o microprograma contendo o comportamento de cada unidade funcional do caminho de dados do processador por ciclo de relógio. O primeiro passo para o projeto de uma adaptação é conhecer os detalhes da arquitetura, quanto ao formato de instruções, tipos de dados e endereçamento, tamanho da palavra de dados e demais características próprias. A unidade de controle do processador adaptado deverá receber as instruções nos formatos MIPS, e enviar os bits de controle correspondentes às unidades funcionais do processador, de acordo com as informações contidas no código da operação. Qualquer modificação no processador poderá afetar a área em chip do dispositivo, o consumo de potência ou seu nível de desempenho na execução de instruções. Por isso, a fim de preservar as características originais de cada processador, mantendo seu nível de complexidade de hardware, cabe ao projetista de hardware realizar apenas as modificações necessárias para que a arquitetura possa executar instruções MIPS. Esta metodologia, por ser acadêmica, não fará privilégio por área ou desempenho, sendo a maior preocupação o correto funcionamento das microarquiteturas na execução das instruções de sua nova ISA. No entanto, as sugestões propostas nos caminhos de dados dos processadores terão informações sobre o possível impacto 65 quanto ao aumento da quantidade de elementos lógicos do dispositivo ou o aumento do número de ciclos de relógio necessários para executar as operações. Apesar de o padrão MIPS ser desenvolvido como uma arquitetura do tipo RISC, atualmente é difícil classificar uma arquitetura como RISC ou CISC (Complex Instruction Set Computer). Conceitualmente, uma arquitetura CISC possui um conjunto de instruções mais complexo, tornando o computador mais versátil na execução de aplicações, contém poucos registradores, utiliza diversos modos de endereçamento e sua complexidade está no microprograma. Já uma arquitetura RISC possui um menor conjunto de instruções, com poucos formatos fixos de instrução e modos de endereçamento, o que torna sua execução mais rápida e os chips mais simples e baratos [Tanembaum, 2007]. Atualmente, muitas arquiteturas são consideradas híbridas, pois possuem processadores CISC com núcleos RISC. Assim, a parte CISC do processador pode cuidar das instruções mais complexas, enquanto que o núcleo RISC pode cuidar das instruções mais simples, nas quais é mais rápido [Calazans, 2008]. Pelo menos uma das características do modelo RISC deve ser seguido por qualquer processador MIPS, que é a de conter vários registradores, visto que o padrão MIPS exige pelo menos 32 registradores.. Não é objetivo desta metodologia seguir todos os parâmetros necessários para que uma arquitetura continue sendo classificado como RISC, como a restrição de executar as instruções do conjunto MIPS em mais de um ciclo de relógio. No entanto, mesmo os processadores MIPS padrão serem considerados arquiteturas RISC e as microarquiteturas adaptadas não possuírem todos os requisitos básicos para esta classificação, os processadores adaptados a esta nova ISA são capazes de compreender e executar as instruções presentes no conjunto de instruções MIPS-I2, podendo ser considerados processadores MIPS. Nas sessões seguintes serão apresentados os passos mínimos necessários para um processador se tornar uma arquitetura MIPS. Esta metodologia não modela um processador para ser a melhor opção para o padrão MIPS, mas sim torna possível a execução de seu conjunto de instruções, de modo a manter seu nível de complexidade de hardware e sua organização original, de modo a processadores acadêmicos criados como experimentos arquiteturais genéricos continuem com suas características básicas preservadas, mas capazes de executar instruções de uma nova ISA. 2 Exceto a instrução syscall, utilizado para chamadas ao sistema operacional. 66 5.1. Registradores Um processador MIPS requer no mínimo 32 registradores de trabalho com 32 bits de palavra cada. Uma descrição VHDL simples é suficiente para realizar esta etapa de adaptação, criando um arquivo registrador e o utilizando-o como um componente, instanciado ao menos 32 vezes. Um registrador simples de 32 bits possui exatos 32 elementos lógicos em dispositivos FPGAs da Altera, e como a arquitetura original já possui uma quantidade mínima de registradores internos, o custo desse acréscimo em área será incluir a quantidade restante de registradores necessários, caso esta não possua 32 registradores. O custo total em área para 32 registradores significa utilizar 1024 elementos lógicos do dispositivo. É necessário seguir uma ordem específica convencionada para os registradores na arquitetura MIPS, como visto no Capítulo 2. Os registradores podem ser alocados nas entradas de um multiplexador de 32 canais de entrada seguindo a convenção MIPS, ou seja, o valor ‘0’ na entrada de seleção do multiplexador é relacionado ao registrador $0, o valor ‘1’ na entrada de seleção é relacionado ao registrador $1, e assim por diante. Caso o processador contenha mais do que 32 registradores utilizados em operações na ULA, será necessário atualizar o multiplexador para 64 canas de entrada ou omitir alguns registradores MIPS. Como alguns registradores possuem sua função específica, como contador de quadro ou apontador de pilha, e caso o processador não disponha de tais funcionalidades, pode-se optar por substituir estes canais de entrada pelos registradores adicionais do processador, com a penalidade de comprometer o funcionamento de algumas instruções. Registradores adicionais são necessários para prover algumas funções ou operações. Para executar corretamente as operações de multiplicação e divisão, cujo resultado é um valor de 64 bits, faz-se necessário incluir dois registradores específicos, HI e LO, para armazenar respectivamente as partes mais e menos significativas do resultado destas operações. Além disso, devem existir registradores que forneçam a comunicação externa entre processador e memória, responsáveis pelo envio e recebimento de dados e endereços. 67 5.2. Unidade Lógica e Aritmética A ULA de um processador adaptado ao padrão MIPS deve conter as operações lógicas e aritméticas necessárias para executar as instruções de mesmo tipo presentes no MIPS-I. A inclusão de mais operações reflete no aumento da quantidade de área em chip, mas também resulta em uma diminuição do número de ciclos de relógio necessários para a sua execução. Portanto, deve ser uma decisão de projeto Área x Desempenho. Para executar as operações lógicas, recomenda-se que todas as funções lógicas básicas e complementares (and, or, nand, nor, xor, xnor, not) estejam disponíveis. Uma operação and de 32 bits utilizará 32 portas lógicas and de duas entradas, sendo a mesma configuração para as demais funções lógicas. Portanto, em virtude da sua simplicidade, tais funções não causam um impacto significativo em área sobre a quantidade de elementos lógicos. As instruções aritméticas MIPS-I são: adição, adição com operando imediato, subtração (todos com ou sem detecção de overflow), multiplicação e divisão (com sinal e sem sinal). É fundamental que a ULA contenha ao menos um circuito somador. Para as demais operações fundamentais, a decisão de projeto é utilizar circuitos específicos para cada operação ou na forma de algoritmos utilizando apenas somadores. A melhor forma de efetuar a subtração é utilizar a técnica de Complemento a 2, pois esta utiliza apenas somas e complementos (utilizando uma porta lógica not) e não necessita de um circuito subtrator, o que reduz a área do dispositivo. Para as instruções de multiplicação e divisão em MIPS, é importante saber que estas exigem a utilização dois registradores HI e LO, e que poderá ser necessário trabalhar com a transferência de dados entre estes registradores dependendo da forma escolhida para sua execução. A operação de multiplicação com sinal pode ser feita por meio de um circuito multiplicador, um algoritmo de sequência de somas, ou seguir a estratégia do algoritmo de Booth, em que apenas as adições e deslocamentos são realizados. Esta última é a que apresenta a melhor vantagem em termos de economia em área, pois ao invés de usar um elemento multiplicador, apenas a ULA é utilizada para estas funções. Por outro lado, toda a lógica de multiplicação é realizada pela unidade de controle através de um algoritmo inserido no microprograma, o que demanda muito mais ciclos de relógio para sua execução, prejudicando o seu desempenho. A Figura 5.1 apresenta um fluxograma de execução do algoritmo de Booth para uma multiplicação com sinal. 68 Figura 5.1 - Fluxograma de multiplicação por algoritmo de Booth Fonte: [Patterson, 2007] Para implementar o algoritmo, são necessários registradores para armazenar o multiplicador (Q) e o multiplicando (M), um somador/subtrator, uma lógica de deslocamento, uma estrutura de decisão e alguns registradores e bits de controle para armazenar as variáveis Q-1 (bit posicionado logicamente à direita do bit menos significativo do multiplicador) e Qin (que concatena os valores de Q0 e Q-1). Como é necessário efetuar um deslocamento no valor do quociente, e este é distribuído entre HI e LO, também é necessário criar um mecanismo de transferência de dados entre os registradores para manter o significado correto do valor resultante. Sugere-se a criação da instrução SRC (Shift Right with Carry), para setar o MSB de um registrador ao deslocar um valor para a direita, necessário para implementar a correta relação entre HI e LO. A operação de divisão, apesar de ser mais complexa, também pode ser realizada usando apenas adições, subtrações e deslocamentos, evitando a adição de um bloco funcional divisor. Esta opção também reduz a complexidade do caminho de dados e 69 aumenta a complexidade do controle. Como procedimentos adicionais, faz-se necessário implementar uma lógica de extensão de sinal (para divisão com sinal) e extensão de zeros à esquerda (para divisão sem sinal) e, se desejado, flags de erros de divisão por zero. A Figura 5.2 detalha o processo de divisão com sinal pela estratégia de Booth. Figura 5.2 – Fluxograma de uma divisão por algoritmo de Booth Fonte: [Patterson, 2007] Em ambos os casos, podem ocorrer iterações em que não são realizadas operações de somas/subtrações, sendo efetuados apenas os deslocamentos. Dependendo de como esta lógica foi projetada no dispositivo, significa que podem ocorrer interações com somas + deslocamentos, necessitando de dois ciclos de relógio, e interações com apenas um ciclo. Isto faz com que não seja possível definir uma quantidade fixa de ciclos de relógio para sua execução, podendo-se se apenas afirmar que são necessários no mínimo 32 ciclos para tais operações. Um circuito multiplicador ou divisor interno na ULA geralmente necessita de 32 ciclos de relógio por operação, enquanto um componente multiplicador ou divisor 70 dedicados pode realizar tais procedimentos em um único ciclo de relógio, o ideal para instruções em máquinas RISC. No entanto, a inclusão de multiplicadores e divisores pode provocar uma alteração na frequência de relógio do processador. Em testes com dispositivos da família Cyclone II Altera®, a frequência de operação de um processador a 50 MHz regrediu para 7 MHz após a inclusão de uma megafunção multiplicador. Também é necessário algum método de deslocamento para esquerda ou direita, para instruções específicas de deslocamento ou como parte de outras instruções. Este deslocamento pode ser realizado usando um componente deslocador específico ou internamente pela ULA. O deslocamento de apenas um bit por ciclo não implica em praticamente nenhum custo adicional em área, mas, consequentemente, um deslocamento de 32 bits precisa de 32 ciclos de relógio. Já um componente deslocador pode deslocar até 32 bits em um único ciclo, mas são necessários mais elementos lógicos, além de bits adicionais para seleção da direção e da quantidade de bits, o que também implica em uma diminuição da frequência de operação, já que aumenta o caminho percorrido por uma palavra de 32 bits no caminho de dados do processador, acarretando também em um tempo maior para que a instrução seja efetuada. 5.3. Instruções de Branch A base para o cálculo de endereço alvo do branch é o endereço da próxima instrução em relação à instrução que ocasionou o branch. Este endereço deve ser ajustado a um valor de offset para calcular o endereço relativo, sendo que o offset deve ser deslocado 2 bits para aumentar o alcance do desvio, o que implica em uma multiplicação por 4. Além do cálculo do endereço do branch, deve-se determinar qual será o endereço utilizado, dependendo do resultado da operação. Para executar estas instruções especiais de desvio relativas ao valor de PC é necessária uma comparação entre registradores – geralmente por meio de operadores relacionais (maior que, menor que, igual, diferente) e em seguida uma lógica de desvio com base no resultado obtido. A primeira etapa pode ser realizada usando circuitos lógicos específicos como comparadores, tornando mais rápido o processamento, mas também mais complexo em área, ou então por meio da operação de subtração da ULA, com o envio de sinalizadores (flags) para a unidade de controle. Esta segunda opção quase não provoca impacto na arquitetura do caminho de dados, mas exige alguns ciclos de relógio adicionais para envio dos operadores para a ULA e obtenção do resultado. 71 5.4. Comunicação com a memória Embora o MIPS possua 32 bits de palavra, o endereçamento de memória no MIPS é orientado a byte. Cada endereço de memória é relacionado a um identificador de uma posição de memória de 1 byte (8 bits). Desta forma, uma palavra do processador armazenada em memória ocupa 4 posições de um byte em endereços consecutivos. Esta configuração provoca um impacto no funcionamento de instruções de leitura da memória (load), em que um valor de base é multiplicado por quatro, ou na atualização do valor do contador de programa (PC), que deverá ser ajustado na forma PC: = PC + 4. Assim, a decisão de projeto sobre a comunicação entre a memória e o processador implica em pelo menos duas possibilidades: definir a quantidade de bits utilizados para o conteúdo da memória, o que provoca alteração na quantidade de registradores e no barramento, e definir a forma como o valor de PC deve ser atualizado, uma vez que o incremento do PC pode ser dado em 1 ou 4. Na primeira opção, a memória pode ser implementada utilizando dados de 8 bits, o que exige que cada operação de leitura em memória seja realizada em quatro buscas de 1 byte cada um, utilizando 4 registradores temporários de 8 bits, e posteriormente concatenar os quatro valores obtidos em um registrador de 32 bits. Na segunda opção, podem ser utilizadas memórias com palavras de 32 bits, o que implica em apenas uma busca na memória para cada dado ou instrução. Esta segunda opção é a que provoca a menor alteração na complexidade da arquitetura, além de poder utilizar um valor padrão de configuração de memória com 32 bits de palavra. Para utilizar a configuração de 32 bits na atualização do contador de programa, deve ser adotado o seguinte procedimento: para cada busca de uma instrução, o valor de PC correspondente a quatro unidades é adicionado, da forma como se encontra no padrão MIPS, mas os dois últimos bits do valor de PC devem ser ignorados na próxima leitura. Por exemplo, considerando PC = 0x000000 (PC = 0) para a instrução 1, ao fazer PC = PC + 4 o valor resultante será PC = 0x000100 (PC = 4) para a instrução 2, PC = 0x001000 (PC = 8) para a instrução 3, e assim sucessivamente. Fazendo com que o barramento de dados que conecta PC aos demais blocos funcionais não considere os últimos dois bits, os valores seriam considerados como PC = 0000 (PC = 0) para a primeira instrução, PC = 0001 (PC = 1) na segunda instrução e PC = 0010 (PC = 2) para a terceira instrução. 72 5.5. Instruções load/store O tratamento de números com e sem sinal (representação em ponto fixo) afeta as operações aritméticas e instruções de leitura / escrita. Uma instrução de carregamento de um byte com sinal (load byte) replica o bit de sinal para os demais espaços de um registrador de 32 bits, enquanto a mesma operação envolvendo um byte sem sinal (load byte unsigned) preenche os demais campos do registrador com zeros à esquerda. Esta funcionalidade requer duas máscaras para realizar uma função lógica com os valores imediatos: uma máscara de inserção dos 32 primeiros bits com '0 'e a outra com '1'. 5.6. Considerações Todas as instruções MIPS possuem um formato regular com palavras 32 bits, ocupando 1 palavra em memória (32 bits), o equivalente a 4 endereços consecutivos em memória. Cada instrução contém o código da operação e o(s) operando(s), caso exista(m), especificando a quantidade de registradores que serão utilizados, de acordo com a categoria em que a instrução se encontre (tipos R, J e I). Estas definições de formato e tipo das instruções são tarefas da unidade de controle de cada processador, onde são inseridos os comportamentos e características de cada instrução de seu conjunto. A forma como as instruções são executadas é dada pela unidade operativa da máquina, através de seu caminho de dados (data path). Para qualquer processador (de 32 bits) que necessite utilizar o formato MIPS, serão necessários obrigatoriamente os registradores PC, IR e mais 32 registradores já especificados, além de uma ULA com operações lógicas e ao menos um somador. Os demais aspectos, como a comunicação com a memória e a forma de execução das etapas do ciclo de vida de uma instrução (busca, decodificação, execução, armazenamento), poderão ser realizadas de diferentes maneiras, desde que possam implementar corretamente todas as instruções existentes. Como alternativa para aprimorar seu desempenho e adicionar novas instruções e funcionalidades, é possível acrescentar uma lógica de reconfiguração quanto à sua unidade de controle, tornando o processador um RISP. No capítulo seguinte, os processadores apresentados como estudos de caso serão adaptados ao formato MIPS seguindo a metodologia aqui apresentada, assim como exemplos de reconfiguração para inserir novas instruções. 73 Capítulo 6 – Aplicações e Resultados 6. Neste capítulo, os processadores utilizados como estudos de caso no Capítulo 4 são adaptados para a arquitetura MIPS, modificando suas unidades de controle para conter o conjunto de instruções MIPS-I e suas unidades operativas para permitir a execução destas novas instruções. 6.1. Adaptação 1: Processador DIMBA Para o processador CABARE, optou-se pela menor quantidade de modificações possíveis em sua unidade operativa, alterando apenas o necessário para que o processador possa executar as instruções MIPS-I. Como a arquitetura já era de 32 bits, não foi necessário alterar tamanho do barramento ou dos registradores. Com as novas adaptações e sua nova arquitetura, o processador foi renomeado para DIMBA (DIdactic MIPS Basic Architecture), cuja visão geral é apresentada na Figura 6.1. Figura 6.1 – Visão geral do processador DIMBA Fonte: autoria própria 74 Nas sessões a seguir serão apresentadas as mudanças efetuadas na arquitetura, segundo a ordem da metodologia descrita no Capítulo 5. 6.1.1. Registradores A arquitetura MIPS necessita de 32 registradores de trabalho, portanto a primeira modificação obrigatória do processador consistiu em aumentar de 13 para 32 registradores. Além dos 32 registradores de trabalho, para manter a organização do processador, os registradores PC, G, Mask e DIN também devem permanecer como entradas do componente MUX. Ao invés de aumentar a quantidade de entradas do MUX de 32 para 64 entradas por 3 registradores, optou-se por substituir o registrador apontador global pelo valor de PC e os registradores reservados para tratamento de interrupção K0 e K1 e o apontador de quadro pelos registradores necessários. 6.1.2. ULA As operações presentes na unidade lógica e aritmética do DIMBA estão dispostas na tabela 6.1. A codificação das operações segue o formato do operando funct presente nas instruções MIPS do tipo R. Tabela 6.1 – Operações da ULA do DIMBA Código 000000 000001 000010 000011 011000 011010 100000 100010 100100 100101 100110 100111 101010 101011 101110 110001 110011 Operação SLL (shift left logic) SLA (shift letf arithmetic) SRL (shift right logic) SRA (shift right arithmetic) MULT DIV ADD SUB AND OR XOR NOR SLT (Set Less Than) SLTU (SLT Unsigned) NOT DEC INC Função C = B << 1 (LSB = 0) C = B << 1 (LSB = 1) C = B >> 1 (MSB = 0) C = B >> 1 (MSB = 1) C=A*B C=A/B C=A+B C=A–B C = A and B C = A or B C = A xor B C = A nor B C = 1 when A > B C = 1 when A > B C = NOT(A) C=A–1 C=A+1 75 Para a multiplicação e divisão, foi adotada a estratégia de Booth para manter sua simplicidade. Desta forma, todas as operações aritméticas são realizadas pela ULA. A organização do CABARE/DIMBA permite a movimentação de apenas um dado por ciclo, além de não ser possível realizar uma soma e um deslocamento ao mesmo tempo. Como os resultados temporários estão divididos nos registradores HI e LO, sendo necessário efetuar 2 deslocamentos. Desta forma, a implementação da técnica de Booth no DIMBA utiliza 32 interações contendo 10 passos, além da etapa inicial de carregamento dos registradores e de uma etapa de verificação de índice, que resulta em aproximadamente 360 ciclos para sua completa execução. A divisão utiliza alguns ciclos devido à necessidade de extensão de zeros ou extensão de sinais. O quadro a seguir apresenta o microprograma utilizado para a multiplicação. I = 0, LO = RS (Q), Q-1 = 0 A = ZERO, HI = ZERO WHILE I <= 31 (START) IF Q0 & Q-1 = 00 OR 11 THEN GOTO DESL0 ELSE IF Q0 & Q-1 = 01 THEN GOTO ADD ELSE IF Q0 & Q-1 = 10 THEN GOTO SUB END IF; I = I + 1 (ADD) G = A + RT (M); HI = G; GOTO DESL1 (SUB) G = A + RT (M); HI = G; GOTO DESL1 (DESL0) G = A or ZERO; GOTO DESL1 (update A) (DESL1) G = G >> 1 (c/ logic right shift) A=G G = LO LO = G >> 1 (update LO31) G = A OR ZERO HI = G; GOTO START 6.1.3. Instruções de Branch Assim como para as demais funcionalidades adicionais, não foi criada uma estrutura específica para a lógica de Branch. Para cada comparação entre registradores, são necessários 3 ciclos para que os valores sejam enviados à ULA e se obtenha o resultado. Em seguida, os flags da ULA são utilizados dentro do microprograma para as 76 estruturas de decisão de acordo com a instrução requerida. Como existem algumas instruções que requerem algum comportamento adicional, como salvar um link de retorno, as instruções de desvio condicional necessitam de 3 ou 9 ciclos antes de iniciar a sequência de Branch. Para implementar a lógica das instruções relativas ao PC, o contador de programa é enviado para o registrador Acumulador, que por sua vez é deslocado duas vezes seguidas para o ajuste de offset (PC = PC + 4), e por último realizar uma soma final para o resultado final. 6.1.4. Comunicação com a memória A memória utilizada possui 32 bits de palavra. Dessa forma, é possível realizar apenas uma busca na memória para buscar dados e instruções no DIMBA. Entretanto, para continuar se adequando ao padrão de organização de memória em bytes no MIPS, na descrição do código do mapeamento de bits entre o processador e a memória, o valor do endereço é enviado sob a forma “endereço (XX downto 2)”, ou seja, excluindo os dois últimos bits de endereço. 6.1.5. Instruções de Load/Store As instruções de escrita devem ser ajustadas no processador antes de serem enviados à memória. Entre as modificações, podem ser citados valores com extensão de sinais (para números inteiros), valores com extensão de zeros (para valores sem sinal), valores em que é necessário excluir os bits referentes ao código da operação e, por último, instruções que requerem apenas um byte de dados. A solução foi criar máscaras de bits. As máscaras para extensão do MSB foram incluídas dentro do microprograma na unidade de controle. Já para instruções que trabalham apenas com bytes, foi criado um registrador especial nomeado mask_pc, situado na saída da ULA, cuja função é considerar apenas o último byte do valor de entrada, alterando o valor dos demais 24 bits para zero. Como exemplo de simplicidade do processador na execução de instruções, a instrução LUI (Load Upper Immediate) determina que um valor de 16 bits seja armazenado nas posições 31-16, completando as demais posições com zero. Como não existe um deslocador no DIMBA, a única forma de efetuar tal operação é utilizar as 77 instruções de deslocamento na ULA, e como esta só efetua o deslocamento de 1 bit por vez, são necessários 16 deslocamentos à esquerda para concluir a instrução. 6.1.6. Reconfiguração Para reconfigurar uma instrução MIPS, é necessário conhecer por completo o caminho de dados do processador para que seja possível escrever o microprograma de cada nova instrução definindo os sinais de controle das unidades funcionais do processador, além da técnica utilizada para possibilitar a inclusão de novas instruções. A diferença neste caso está no fato de que no CABARE é possível utilizar qualquer código de operação que tenha seus 4 primeiros bits iguais a ‘1’, enquanto que no DIMBA os códigos válidos devem ser referentes às instruções presentes na arquitetura MIPS. No DIMBA, as instruções e as microinstruções contendo os bits de controle já vêm inseridas na memória externa, juntamente com as demais instruções do programa, assim como era realizado no CABARE. Outra modificação na reconfiguração diz respeito aos formatos de instrução. O MIPS possui três formatos definidos (tipos R, I e J), sendo que cada formato distribui os bits da instrução de forma particular e não existe uma codificação na instrução que identifique o formato utilizado. A única característica que define as instruções do tipo R é o seu código de operação conter todos os 6 bits iguais a 0, e a operação lógica/aritmética definida pelos últimos 6 bits, que identificam a operação da ULA. Como o código de operação é idêntico para várias instruções, não é possível fazer uma relação do CodOp com uma posição de memória para realizar o endereçamento indireto das microinstruções. A solução adotada foi reservar 128 posições de memória para conter os ponteiros de instruções MIPS. A primeiras 64 posições devem estar no intervalo 0xFF...80 a 0xFF...BF, sendo os 6 últimos bits provenientes dos valores da operação da ULA indicados na instrução se o código da operação for 0. As 64 posições restantes (0xFF...C0 a 0xFF...FF) recebem os 6 últimos bits pelo código da operação das demais instruções MIPS. A Figura 6.2 apresenta um exemplo de divisão de áreas de uma memória RAM para armazenamento de dados, instruções e microprograma no DIMBA. 78 Figura 6.2 – Áreas de memória do processador DIMBA Fonte: autoria própria A tabela de formatos das microinstruções também foi alterada, visto que os registradores podem receber ou salvar o conteúdo indicado pelos registradores rs, rt ou rd. Para tanto, foram criadas variáveis internas na unidade de controle que armazenam os valores de cada registrador provenientes da instrução recebida. A Tabela 6.2 apresenta os formatos suportados pela arquitetura. Tabela 6.2 – Formatos de microinstruções do DIMBA Formato 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 Utilização da microinstrução microinstrução tipo (a) microinstrução tipo (c) R_In = Rs R_In = Rt R_In = Rd Mux = Rs Mux = Rt Mux = Rd Mux = mux_mask(8) Mux = mux_mask(8) ES Mux = mux_mask(16) Mux = mux_mask(16) ES Mux = mux_mask(26) Mux = mux_mask(26) ES Não usado Não usado 79 Como a quantidade de unidades funcionais foi modificada, então a quantidade de bits de controle que formam uma microinstrução reconfigurada também deve ser ajustada à nova arquitetura. O campo referente aos registradores agora contém um decodificador na unidade de controle, reduzindo a quantidade de bits de 13 na versão original para 5 na versão MIPS. O multiplexador aumentou a quantidade de canais de entrada, utilizando agora 5 bits de seleção. A ULA aumentou sua quantidade de operações e também utiliza um bit a mais na versão adaptada. Foram incluídos os bits de controle dos registradores HI e LO e 2 bits de seleção do multiplexador de saída da ULA. Ao todo, são utilizados 32 bits de controle, podendo ser armazenada cada microinstrução em apenas uma posição de uma memória de 32 bits. A Tabela 6.3 contém a configuração final de bits do DIMBA. Tabela 6.3 – Formato de uma microinstrução no DIMBA 31 0 Formato Regs MUX MUX_ULA ULA IR A G DOUT HI LO ADDR WD RD END 4 5 5 2 6 1 1 1 1 1 1 1 1 1 1 Ao receber uma instrução não pertencente ao conjunto original do processador, será efetuada uma busca na memória no endereço especificado pelo código da operação ou pelos bits de função. Esta posição de memória contém o endereço da primeira microinstrução que implementa o comportamento da nova instrução. As microinstruções são executadas até que seja recebido um valor de bit_end igual a ‘1’. As novas instruções são buscadas após o estágio de decodificação de uma instrução, como um estágio de exceção. Por este motivo, não é possível substituir uma instrução já existente por uma de um mesmo CodOp, já que se tal código for existente, a máquina de estados do processador seguirá para os estágios de execução da instrução fixa do processador. Devido à limitação do CABARE/DIMBA, algumas instruções MIPS não podem ser reconfiguradas ou apenas parcialmente reconfiguradas, como por exemplo as instruções de deslocamento. Como a unidade não possui um deslocador, não é possível receber os bits referentes à quantidade de deslocamentos provenientes da instrução sem aumentar a complexidade da unidade de controle. Ainda que fosse possível receber tais valores, convertê-los para o tipo de dado inteiro, utilizá-los como índices de uma estrutura de repetição e fazer com que a ULA deslocasse 1 bit por vez para a esquerda ou direita até atingir a quantidade informada, este procedimento causaria um impacto 80 significativo em área, número da máquina de estados e desempenho em sua execução, o que foge ao escopo do objetivo de simplicidade do processador. Portanto, caso seja desejado reconfigurar uma operação de deslocamento no DIMBA atual, este será de apenas 1 bit. Para todas as instruções, é necessário conhecer o código da instrução, seu formato, modo de funcionamento e configuração de bits. Serão utilizadas como exemplo duas instruções MIPS: MFHI e ADD. De acordo com [MIPS 2008], a instrução MFHI rd (Move From HI Register) copia o valor do registrador HI para o registrador rd, possuindo a configuração de bits apresentada na Figura 6.3. Figura 6.3 – Codificação da instrução MFHI Fonte: [MIPS, 2008] Para MFHI $t0, os 32 bits de código desta instrução são 00000000000000000100000000010000, ou em hexadecimal 0x00004010. Como a instrução não requer uma operação aritmética ou deslocamento, os bits de controle da ULA devem permanecer em ‘0’ ou ‘–’ (don’t care). Como as instruções MIPS possuem posições fixas de registradores, a unidade de controle já previamente copia os bits das posições correspondentes e as reenvia como bits de controle para os barramentos ou multiplexadores de acordo com o formato de cada microinstrução. A instrução MFHI necessita de duas microinstruções, em virtude do tempo necessário para que ocorra a sincronização de dados no nível RTL (Register Transfer Level) do processador. A primeira microinstrução deve fazer com que o valor de HI seja enviado pelo multiplexador de saída da ULA para ser armazenado em G, já que os registradores HI e LO não são entradas de seleção do MUX de 32 canais. A segunda microinstrução deve utilizar o valor de G como saída para o barramento de dados, e posteriormente salvo no registrador indicado na instrução. A configuração final das microinstruções é dada por: 81 (1) G HI Formato Regs MUX MUX_ULA ULA IR A G DOUT HI LO ADDR WD RD END 0 - - HI - 0 0 1 0 0 0 0 0 0 0 (2) R8 G, BIT_END Formato Regs MUX MUX_ULA ULA IR A G DOUT HI LO ADDR WD RD END 4 Rd G - - 0 0 0 0 0 0 0 0 0 1 A instrução ADD rd, rs, rt possui sua codificação apresentada na Figura 6.4. Apesar de ser uma instrução praticamente obrigatória em qualquer processador, será utilizada como exemplo para ilustrar a reconfiguração de qualquer instrução lógica ou aritmética, já que apenas o código da ULA é alterado conforme a operação. Figura 6.4 – Codificação da instrução ADD Fonte: [MIPS, 2008] Esta instrução trabalha com os três registradores enviados pela instrução, sendo cada um deles utilizado em uma microinstrução diferente, o que exige diferentes formatos de microinstruções. A primeira microinstrução deve fazer com que o acumulador A receba o valor de rs, a segunda microinstrução envia para a segunda entrada da ULA o valor identificado por rt, e a última deve armazenar o resultado da operação em rd. A configuração final das microinstruções é dada por: (1) A rs Formato Regs MUX MUX_ULA ULA IR A G DOUT HI LO ADDR WD RD END 5 - rs 0 - 0 1 0 0 0 0 0 0 0 0 (2) G A + rt, ULA = operação Formato Regs MUX MUX_ULA ULA IR A G DOUT HI LO ADDR WD RD END 6 - rt 0 Func 0 0 1 0 0 0 0 0 0 1 (3) rd G, BIT_END Formato Regs MUX MUX_ULA ULA IR A G DOUT HI LO ADDR WD RD END 4 Rd G - - 0 0 0 0 0 0 0 0 0 1 82 6.1.7. Análise Comparativa A Figura 6.5 mostra os dois processadores apresentados nas Figuras 3.1 e 6.1, dispostos lado a lado, a fim de facilitar a visualização das modificações efetuadas no caminho de dados da nova arquitetura. Figura 6.5 – Comparação do caminho de dados (a) CABARE x (b) DIMBA Fonte: autoria própria 83 A Tabela 6.4 apresenta os dados de compilação de cada um dos processadores deste estudo de caso. Os dados foram compilados para o dispositivo EP2C35F672C6 da família de FPGAs Cyclone II da Altera® presente no kit de desenvolvimento DE2 do mesmo fabricante o qual contém 33216 elementos lógicos e 475 pinos. Para a simulação e síntese, foi utilizado o software Quartus II®. Tabela 6.4 – Síntese dos processadores CABARE e DIMBA Elementos Lógicos Combinacionais / Registradores Processador |botao |control_unit:unidade_controle| |men_manager:men_manager1| |parte_operativa:operacoes| |convBCD32:conversor7Seg| |latch_byte:mask_pc| |multiplexador:multiplexador1| |mux4:multiplexador_ula| |registradorComum: registradores |registradorComum:registradorADDR| |registradorComum:registradorA| |registradorComum:registradorDIN| |registradorComum:registradorDOUT| |registradorComum:registradorG| |registradorComum:registradorIR| |registradorComum:registrador_MEM| |registradorHI:registrador_HI| |registradorLO:registrador_LO| |registradorPC| |registradorSP:registrador29| |registradorR:registradorR1| |registradorW:registradorW1| |ula:Ula1| Clock_SETUP CABARE 1487 / 638 (5%) 2 /2 291 / 68 5/5 1155 / 561 56 / 0 -367 / 0 -0 / 384 0 / 13 0 / 32 -0 / 32 0 / 32 0 / 32 ---39 / 32 -0/1 0/1 217 / 3 29.46MHz DIMBA 2841 / 1658 (9%) 2/2 1006 / 474 5/5 1794 / 1175 56 / 0 0/8 648 / 0 16 / 0 0 / 832 0 / 13 0 / 32 0 / 32 0 / 32 25 / 32 0 / 32 0 / 32 1 / 32 1 / 32 32 / 32 11 / 32 0/1 0/1 360 / 0 41.09MHz Considerando que foi preciso adicionar 20 registradores no DIMBA (adicionando 640 elementos lógicos), substituir o formato e o conjunto e de instruções de 21 para 46 instruções, expandir a quantidade de operações da ULA e a capacidade da lógica reconfigurável, houve um acréscimo total de 4% de área em chip no dispositivo utilizado. 84 6.2. Adaptação 2: Processador CRASIS II A adaptação do CRASIS ocorreu sob duas formas: para a primeira versão, não foi considerada a característica de alternância entre conjuntos de instruções. A segunda versão contém o conjunto MIPS-I e um dos conjuntos de instruções originais do MIPS, para possibilitar a seleção entre diferentes arquiteturas. O processador, nomeado CRASIS II, contém o caminho de dados ilustrado na Figura 6.6. Figura 6.6 – Visão geral do CRIS/CRASIS II Fonte: autoria própria 6.2.1. Registradores A organização original do CRASIS já utilizava 32 registradores de trabalho, sendo necessária para esta adaptação somente seguir a ordem convencionada para os registradores $0 a $31. O registrador PC foi alocado no registrador da posição $28, substituindo a função do apontador global. Também foram criados os registradores HI e LO para as operações de multiplicação e divisão, e alguns registradores para serem utilizados como máscaras, explicados posteriormente. 85 6.2.2. ULA Da mesma forma que no CABARE, a ULA de um processador MIPS deve conter no mínimo as operações aritméticas e lógicas descritas na Tabela 5.1. Portanto, utilizou-se o mesmo componente em VHDL em ambos os processadores. Este fato evidencia mais uma característica de componentes descritos em HDLs como Propriedades Intelectuais em processadores soft-core: a possibilidade do reuso de código, funções, componentes ou mesmo unidades funcionais completas entre diferentes arquiteturas. Para as operações de multiplicação e divisão, poderiam ser incluídos circuitos específicos para a realização destas operações, mas para efeitos de comparação de desempenho entre o CRASIS II e o DIMBA, optou-se por seguir a mesma estratégia de Booth, de acordo com os fluxogramas das Figuras 5.1 e 5.2, com algumas modificações na sua implementação. Criou-se uma função em VHDL dentro da ULA denominada mult_div, chamada sempre que a ULA receber o código de operação de uma multiplicação ou divisão. Como a unidade contém um deslocador situado na saída da ULA, são necessários menos ciclos do que para a execução no DIMBA. A multiplicação com sinal necessita de 138 ciclos e a multiplicação sem sinal utiliza 2 ciclos a mais. Já a divisão requer 200 ciclos para a execução completa. Apesar da ULA conter instruções de deslocamento, foi criado um componente deslocador, com capacidade para deslocar até 32 bits por ciclo para esquerda ou direita. O uso desse componente reduz ciclos de execução da máquina, mas requer o envio de mais bits de controle para a unidade operativa, já que são necessários 5 bits para informar a quantidade de deslocamentos e um bit adicional para informar a direção do deslocamento. 6.2.3. Instruções de Branch Foi projetada uma unidade de Branch contendo um comparador e flags para identificar se o operando de entrada e o resultado da operação possuem valores iguais a zero ou um número inteiro negativo. Estes flags são enviados para a unidade de controle decidir pelo valor seguinte do contador de programa (PC). 86 6.2.4. Comunicação com a memória A estratégia para a comunicação com a memória é a mesma adotada anteriormente, alterando-se o valor da sequência de bits de endereços enviada do registrador MAR para a memória, excluindo os dois bits menos significativos, o que garante a lógica MIPS de multiplicação por 4, mas mantém a estrutura de posições consecutivas de 32 bits na memória. 6.2.5. Instruções de Load/Store Foram criados registradores de máscaras para esta adaptação. Os registradores AMAS, OMASK, MBR_MASK e JMASK alteram o conteúdo de determinados bits de um valor de entrada para 0 ou 1, dependendo da necessidade. Dentre estas, podem ser citadas a exclusão dos bits do CodCop, utilizar apenas um byte ou uma palavra do operando e extensão de zeros ou bits de sinal. A instrução LUI pode ser executada em apenas um ciclo devido a presença do componente deslocador, assim como todas as operações de leitura/escrita podem ser realizadas em um ciclo em virtude da utilização das unidades tratadoras de registradores. 6.2.6. Reconfiguração Para reconfigurar uma instrução MIPS no CRASIS, os dados referentes às instruções reconfiguráveis devem ser enviadas ao processador pelo programador via barramento externo de dados e endereços, juntamente com um pedido de reconfiguração. Este envio pode ser realizado através de algum wrapper ou uma entidade externa por hardware ou ainda por software, sendo esta última possibilidade uma sugestão para implementações futuras. As alterações na unidade de reconfiguração no CRASIS para executar uma instrução MIPS foram poucas, visto que a arquitetura anterior já estava preparada para receber instruções em qualquer formato de configuração de bits com até 4 operandos e possui instruções no formato de 3 registradores C = A op B. O CRASIS já continha 32 registradores de uso geral, por isso sua tabela de formatos já foi projetada com 5 bits de código para cada registrador. 87 A unidade denominada tabela_codop, que valida ou não um endereço de instrução, foi pré-configurada setando as posições da tabela relacionadas aos códigos de operação já implementados. Isto resulta em duas características: não é possível substituir instruções pré-existentes no conjunto MIPS e as instruções lógicas e aritméticas não podem ser reconfiguradas, em razão de todas compartilharem o mesmo código de operação com valor 000000. Os bits de controle do CRASIS também precisaram ser adaptados para sua nova versão. Assim como no DIMBA, a ULA precisa de 6 bits para seleção da operação lógica ou aritmética. Como existe um componente deslocador, este pode receber a configuração de shamt da instrução MIPS contendo a direção e a quantidade de deslocamentos, permitindo a reconfiguração deste tipo de instruções. O multiplexador de entrada do buffer de endereços foi substituído pelo multiplexador de saída do barramento C. A unidade de branch não possui nenhum bit de controle, assim como as máscaras de dados, que sempre realizarão a conversão de dados provenientes do registrador IR. Considerando tais alterações, foram incluídos os bits de controle dos registradores HI e LO e um bit para a ULA, o que resulta em uma palavra de reconfiguração com exatos 32 bits, como mostra a Tabela 6.5. Tabela 6.5 – Palavra de uma microinstrução no CRASIS II Form 6 bits A B MUX MUX 2 2 ULA 6 SH 6 MBR 1 MAR 1 ENC 1 MUX MUX C MBR 4 1 HI 1 LO 1 W BIT R END 1 1 Para exemplificar a reconfiguração MIPS, serão utilizadas as mesmas microinstruções da sessão anterior (MFHI e ADD). A instrução MFHI rd necessita de apenas uma palavra de reconfiguração, no qual o multiplexador do barramento C recebe como entrada o valor de HI, que por sua vez é enviado ao conjunto de registradores. A codificação final da microinstrução é: (1) rd HI Form POS2 A B MUX MUX 00 00 ULA 111111 SH 000000 MBR 0 MAR 0 ENC 1 MUX MUX C MBR 01 0 HI LO W END R 0 0 0 1 88 A instrução ADD rd, rs, rt, pode ser criada caso não existissem operações anteriores com código 000000 ou então fosse desejado criar uma instrução com um código diferente, mas com a mesma funcionalidade. Assim como as demais instruções, esta é executada com apenas uma microinstrução. É necessário consultar a tabela de formatos do CRASIS para verificar as posições corretas de rs (C), rd (A) e rt (B), bem como a operação da ULA (funct). Sua codificação final é: (1) rd rs + rt Form POS2 A B MUX MUX 00 00 ULA 100000 SH 000000 MBR 0 MAR 0 ENC 1 MUX MUX C MBR 01 0 HI LO W END R 0 0 0 1 Como o CRASIS II possui uma unidade de reconfiguração dedicada, é possível aumentar o tamanho das memórias de dados e endereços conforme a expansão do processador, o que não irá alterar o padrão de palavras de 32 bits para dados e instruções. A vantagem de uma unidade de reconfiguração específica frente a uma lógica utilizando somente a memória de programa está no fato de que as novas instruções podem ser enviadas a qualquer momento, em tempo de execução do processador, como se fosse realizado um pedido de interrupção por hardware. As novas instruções não precisam estar codificadas juntamente com as demais instruções dentro de um programa, sendo inseridas no processador conforme a necessidade. Em contrapartida, o uso de uma unidade física externa de reconfiguração demanda mais elementos computacionais, influenciando na área em chip e velocidade do processador, e necessita de um wrapper, uso de um barramento padrão tipo OCP ou modificações em sua configuração de Entrada/Saída para se adaptar a diferentes processadores e arquiteturas. Caso seja feita a opção de utilizar diferentes conjuntos de instruções, cada arquitetura deverá ter suas próprias restrições de formatos, para impedir que um formato com 4 registradores seja lido enquanto estiver no modo de operação MIPS. 6.2.7. Análise Comparativa Da mesma forma que na sessão anterior, a Figura 6.7 apresenta os caminhos de dados das duas versões do processador CRASIS. 89 Figura 6.7 – Comparação do caminho de dados (a) CRASIS I x (b) CRASIS II Fonte: autoria própria 90 A Tabela 6.6 mostra a comparação da síntese entre as versões do processador CRASIS original contendo 3 conjuntos de instruções e apenas o segundo conjunto de instruções implementado. Para a compilação e síntese, utilizou-se o dispositivo EP2C35F672C6 da família de FPGAs Cyclone II da Altera®, com 33216 elementos lógicos disponíveis e 475 pinos. Tabela 6.6 – Síntese do processador variando conjuntos de instruções Elementos Lógicos Combinacionais / Registradores Processador |control_unit:unidade_controle| |parte_operativa:operacoes| |deslocador32:unit_shift| |latch32:unit_latch_a| |latch32:unit_latch_b| |latch32:unit_latch_c| |mux32_4_to_1:unit_amux| |mux32_4_to_1:unit_bmux| |mux32_4_to_1:unit_mux_mar| |registrador_32bits:unit_mar| |registrador_mbr:unit_mbr| |reg_file32:unit_regs| |ula32:unit_ula| |registrador_32bits:reg_ir| |mbrmask:unit_mask_mbr| |branch_full:unit_branch| |registradorR:registradorR1| |registradorW:registradorW1| |cpu_rec:reconfiguracao| Clock_SETUP CRASIS I com 3 CRASIS I com 1 conjuntos (11%) conjunto (9%) 3387 / 1642 1249/ 480 2128/ 1120 331 / 0 5 / 32 5 / 32 -720 / 0 659 / 0 64 / 0 0 / 32 35 / 32 40 / 992 2968 / 1547 838 / 410 2120 / 1120 332 / 0 5 / 32 5 / 32 -714 / 0 659 / 0 64 / 0 0 / 32 32 / 32 40 / 992 269 / 0 -----9 / 17 269 / 0 -----9 / 17 65.40MHz 65.40MHz CRASIS II com 1 conjunto (8%) 2366 / 192 195 / 104 2139 / 1186 200 / 0 0 / 32 0 / 32 0 / 32 677 / 0 679 / 0 177 / 0 0 / 32 0 / 32 49 / 992 224 / 0 0 / 32 47 / 0 50 / 0 0/1 0 /1 40MHz Os resultados mostram um aumento da quantidade de elementos lógicos da unidade de controle, o que era esperado não apenas pelo aumento do número de instruções, mas também pela estrutura de decisão para definição do conjunto de instruções utilizado. A utilização dos super-estados apresentados no Capítulo 3 pode diminuir a quantidade de estados da FSM do dispositivo, mas por outro lado aumenta a dificuldade da descrição na linguagem VHDL em encontrar as interseções relativas aos bits de controle, ao mesmo tempo em que a compreensão e sequenciamento do código é prejudicada. No entanto, considerando o total de área em chip, o aumento de 1 para 3 91 conjuntos de instruções acarretou uma diferença de pouco mais de 1% da área do dispositivo. No conjunto de instruções do CRASIS I, algumas instruções necessitam de vários ciclos de relógio para sua execução completa. Utilizando o conjunto MIPS-I, com exceção das instruções de multiplicação e divisão e das instruções de comunicação com a memória, as demais instruções utilizam apenas um ciclo de execução (cada ciclo contendo quatro subciclos de relógio), o que reduziu o tamanho da unidade de controle. A ULA da versão original utilizava funções da biblioteca std_logic da linguagem VHDL para implementar a operação de multiplicação, removida na versão MIPS. Com o acréscimo de algumas unidades funcionais em sua unidade operativa a exclusão dos estados e sinais que fornecem a comunicação com a unidade de reconfiguração em sua unidade de controle (que representam cerca de 1% de aumento de elementos lógicos), o valor total da área em chip reduziu em 3%, além do ganho de desempenho com o aumento da velocidade de execução das aplicações. 6.3. Exemplo de uma aplicação Para validar o funcionamento dos processadores, foi utilizado um exemplo simples que obtém o fatorial de um número, visto que o mesmo contém instruções aritméticas, de desvio condicional e incondicional e de Entrada/Saída. A execução da aplicação foi realizada com base em um algoritmo contendo 11 instruções, definidas conforme o quadro 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) 92 Para adaptar o algoritmo para a linguagem assembly do CABARE, deve ser criado um arquivo .mif ou .hex para ser armazenado em sua memória. Como o CABARE não possui instruções de multiplicação e divisão, foi utilizado um microprograma contendo uma sub-rotina de multiplicação, análoga a uma função em software, sendo desenvolvida como uma instrução reconfigurável com Código de Operação 0xF0, do tipo MUL Rx, Ry. Esta instrução reconfigurável recebe os valores de Rx e Ry na instrução e utiliza obrigatoriamente em R6 e R7 como registradores temporários, armazenando o resultado em Rx. O programa adaptado ao processador possui as instruções do quadro a seguir: 0000 : 01B00020; 0001 : 080B0020; 0002 : 01100001; 0003 : 01200001; 0004 : 01300001; 0005 : 01400001; 0006 : 01500000; 0007 : 04030000; 0008 : 1100000C; 0009 : 03230000; 000A : F0120000; 000B : 04030000; 000C : 0C000009; 000D : 00010000; 000E : 1F000000; [000F..001F] : 00000000; 0020 : 00000005; [0021..002F] : 00000000; 0030 : 40205000; 0031 : 50105000; 0032 : 10040001; 0033 : 00005740; 0034 : 00001920; 0035 : F200003B; 0036 : 00185E00; 0037 : 00005640; 0038 : 40000020; 0039 : 00205E00; 003A : F8000033; 003B : 24005601; [003C..1FEF] : 00000000; 1FF0 : 00000030; [1FF1..1FFF] : 00000000; END; -- carrega em R11 o endereço de FAT -- mv R0, R11 (armazena FAT em R0) -- mvi R1, #1 -- mvi R2, #1 -- mvi R3, #1 -- mvi R4, #1 -- mvi R5, #0 -- sub R0, R3 (Acc = Acc – 1) -- jz, #12 (Se Acc = 0 goto 000C) -- add R2, R3 (B = B + C) -- mul R1, R2 (A = X * Y – inst. reconfiguravel) -- sub R0, R3 (Acc = Acc – 1) -- jnz PC, #7 (Se Acc != 0 goto 0009) -- mv R0, R1 (Acc = A) -- halt -- FAT -- (mul) R6 = X (R1) -- R7 = Y (R2) -- A = 1 -- G = A -- G = G _ R7 -- Se Z = 0, goto 3B -- R7 = G -- A = R6 -- G = R1 + R6 -- R6 = G --jmp 33 -- endereço de mul 93 Como o algoritmo de multiplicação depende dos valores de Rx e Ry, não é possível determinar quantos ciclos de relógio são necessários para sua execução, visto que a multiplicação de X por Y causa a execução da rotina de multiplicação Y vezes. A simulação com FAT = 4 resulta em aproximadamente 20 us para sua execução. Para FAT = 7, a execução completa do programa ocorre em torno de 52 us. A Figura 6.8 mostra que a cada multiplicação (Código de Operação 0x0010), o tempo para sua execução se torna maior. Figura 6.8 – Processo de simulação de um algoritmo no CABARE Fonte: Captura de tela do software Quartus II O quadro a seguir apresenta o código na linguagem assembly MIPS para o fatorial, que pode ser utilizado no CRASIS II e no DIMBA. No caso do CRASIS, devem ser excluídos do arquivo mif as microinstruções reconfiguráveis e os ponteiros de endereços, já que o CRASIS contém uma unidade de reconfiguração externa. 94 Ao utilizar o DIMBA e a estratégia de Booth para a multiplicação, mesmo que este algoritmo também não represente uma boa solução quanto ao desempenho de sua aplicação devido à quantidade de ciclos necessários para o procedimento, existe um limite de passos para sua execução, podendo ser melhor estimado o tempo total para executar o programa. Foram necessários aproximadamente 100 us para a execução dos exemplos de fatorial. A Figura 6.9 mostra um detalhe da tela de simulação contendo o resultado da execução de FAT = 4. Figura 6.9 – Processo de simulação de um algoritmo no DIMBA Fonte: Captura de tela do software Quartus II O programa MIPS utilizou 18 instruções, e a execução do algoritmo foi realizada corretamente em todas as versões. Para este caso, não foi necessário o uso de instruções reconfiguradas. Como o algoritmo de Booth foi utilizado somente para manter o nível de complexidade de hardware do processador, ou seja, sem incluir nenhum elemento funcional, este exemplo apenas valida o correto funcionamento do algoritmo no processador utilizando instruções MIPS e mostra que a aplicação da metodologia para adaptar processador a uma ISA padrão funciona adequadamente. 6.4. Considerações No modo de reconfiguração apresentado no DIMBA, a técnica de reconfiguração de instruções utilizando um microprograma armazenado em memória RAM pode ser utilizada em qualquer processador, sem a necessidade de criar unidades específicas de reconfiguração, sendo necessário apenas incluir mais estados na máquina 95 de estados do processador (desde que a unidade operativa da máquina possa executar as novas operações descritas). A quantidade de microinstruções reconfiguráveis é similar às utilizadas para executar as instruções fixas do processador. A penalidade está em utilizar mais ciclos de relógio para os estágios adicionais de busca e decodificação e mais leituras da memória em virtude do endereçamento indireto. Já o acoplamento de uma Unidade de Reconfiguração Externa (RFU), com funcionamento análogo a um co-processador dedicado, torna o processo de reconfiguração de instruções independente do arquivo contendo o programa armazenado, e o funcionamento desta unidade apresentou o mesmo resultado satisfatório no que tange ao correto funcionamento do armazenamento e execução de instruções MIPS, com a penalidade do aumento da área do dispositivo e expansão de sinais de controle e mapeamento de bits entre as unidades operativa, de controle e de reconfiguração. A inclusão de unidades funcionais como deslocadores, multiplicadores, unidades de ponto flutuante ou demais melhorias em sua estrutura física permite que um processador MIPS-I possa executar instruções de seu conjunto original que não foram implementadas em sua fase de desenvolvimento ou mesmo utilizar instruções MIPS-II ou mais recentes, aumentando a compatibilidade entre dispositivos e de programas executados, sem alterações em compiladores, montadores ou demais softwares básicos. Os resultados também mostram que é possível cada processador executar instruções da arquitetura MIPS apenas alterando o microprograma da unidade de controle, como também executar instruções MIPS mantendo sua estrutura original por meio das técnicas de reconfiguração apresentadas, também sendo possível manter o processador em sua forma original e alternar entre conjuntos de instruções para suportar diferentes arquiteturas, desde que suas unidades operativas possam compreender e executar em todos os formatos desejados. 96 Capítulo 7 – Conclusões e Perspectivas 7. D Considerando que o avanço e a redução de preço da tecnologia de FPGAs permite uma grande disseminação de seu uso no meio acadêmico, o que propicia o surgimento de diversos processadores de diferentes arquiteturas e níveis de complexidade, é interessante que possa haver alguma forma de interação ou comunicação entre tais dispositivos. Apesar de haver uma compatibilidade entre dispositivos de uma mesma família de arquiteturas ISA, como no caso dos processadores MIPS, e do fato de que a maioria das instruções costuma ser de mesmo tipo e classe, tais instruções internas variam de processador para processador e geralmente são incompatíveis entre arquiteturas diferentes. Possibilitar que um processador possa executar instruções de outro dispositivo de sua família, ou mesmo de outra arquitetura, é uma das principais vantagens do uso de processadores com conjunto de instruções reconfiguráveis. As arquiteturas MIPS permitem aos estudantes não apenas realizar práticas de projetos envolvendo arquitetura de computadores e sistemas digitais, mas também o desenvolvimento de IP’s, plug-ins, softwares básicos e técnicas de redução de potência e incremento de desempenho. Também é possível escrever programas utilizando linguagens de programação em alto nível como C/C++ e utilizar compiladores como o Collection GNU Compiler (GCC) e simuladores como o MARS [Mars, 2013] ou SPIM [Larus, 2013] para a geração de arquivos no formato hexadecimal (.hex) contendo o código objeto do programa fonte, e os enviando para a memória dos processadores didáticos. Esta interdisciplinaridade em disciplinas de hardware/software é um dos maiores benefícios no que tange o projeto, desenvolvimento e implementação de processadores didáticos. Para o caso de processadores soft-core descritos em uma linguagem HDL, esta tarefa se torna mais simples, pois os códigos-fontes das unidades operativa e de controle de um processador estão descritas em linguagem de descrição de hardware, sendo suficiente alterar ou acrescentar novos componentes aos arquivos HDL. 97 A partir dos estudos de caso abordados nesta tese, pode-se afirmar que é possível adaptar processadores sem uma ISA definida ou contendo apenas uma parte de uma arquitetura padrão a qualquer arquitetura de conjunto de instruções, com poucas alterações em sua estrutura e organização original, mantendo seu nível de complexidade de hardware. Por estarem inseridos em um universo de dispositivos FPGA, no qual a quantidade de elementos lógicos é fixa para cada processador, em termos de área não importa se uma arquitetura utilize 2% ou 90% da sua capacidade. Investir em processadores simples, com baixo nível de complexidade em hardware, mas que possam executar aplicações da mesma forma que processadores mais robustos, sem perdas significativas de desempenho, mostram que os processadores RISC e FPGAS do tipo RISP podem continuar a ser tema de pesquisas científicas e acadêmicas. Desta forma, é possível alterar a arquitetura de um processador microprogramado mantendo seu nível de organização apenas substituindo o código de sua unidade de controle, analogamente como se o computador sofresse uma atualização no seu firmware. E, adicionalmente, caso o processador seja do tipo RISP, é possível inserir ou atualizar instruções de sua arquitetura em tempo de execução do processador, como se as novas instruções fizessem parte do conjunto original de instruções da máquina. Por último, como prova de conceito, a possibilidade de um processador ser capaz de selecionar diferentes arquiteturas de instruções dentro de um mesmo dispositivo abre uma possibilidade de pesquisas em arquiteturas híbridas adaptativas, contendo dentro de uma mesma estrutura diferentes ISA’s, como MIPS, SPARC e x86. Além disso, tal projeto deve permitir um modo de programar a arquitetura para executar atividades determinadas. Dessa forma, a arquitetura pode ser definida como um conjunto de atributos da máquina que um programador deve compreender para que consiga programar o computador específico com sucesso, ou seja, para que consiga compreender o que o programa irá fazer quando a máquina executar. O estudo sobre organização e arquitetura de computadores faz parte do currículo da maioria dos cursos de computação e a compreensão e aplicação dos conceitos representa um desafio para os discentes, uma vez que as atuais arquiteturas de computadores pessoais são complexas e muitas vezes contêm restrições no que tange ao consumo de energia e espaço em chip. Portanto, a utilização de uma arquitetura simples constituída pelos principais recursos necessários para uma máquina programável, pode servir como uma ferramenta extremamente útil para fins didáticos. 98 A forma como os diversos componentes de um computador são organizados define o conceito de arquitetura de um computador, determinando aspectos relacionados à qualidade, ao desempenho e à aplicação para a qual o computador vai ser orientado. O projeto de uma arquitetura de computador vai além do desenho da estrutura física de um processador, devendo levar em consideração a organização interna dos componentes do processador como registradores, unidades lógica e aritmética, barramentos; o conjunto de instruções; organização e modos de endereçamento da memória; suporte a periféricos ou dispositivos de entrada e saída para comunicação do processador com o mundo externo. 7.1. Trabalhos Futuros Até a finalização deste texto, os temas abordados nesta tese resultaram nas seguintes publicações: (Silva, 2011), (Costa, 2012), (Casillo, 2012) e (Casillo, 2012a), além de um capítulo do livro “Workshop Técnico-Científico de Computação”, abordando o tema “Metodologia para projeto de processadores RISP”, a ser publicado em 2013 pela editora EDUFERSA. Os processadores didáticos projetados foram alvo de estudo ou ferramenta para diversos trabalhos de iniciação científica e artigos em congressos regionais e nacionais. Dentre os trabalhos que exploram as características dos processadores, (Nunes, 2012) propôs uma técnica de implementação de um pipeline para processadores softcore, utilizando como estudo de caso o processador CRASIS I, a partir da replicação de máquinas de estados (FSM). É possível criar várias linhas de execução, possibilitando que mais de uma instrução esteja em execução ao mesmo tempo. As FSMs são sobrepostas de modo similar a um pipeline, sem que o mesmo estado em estados de diferentes unidades fique ativo ao mesmo tempo. A grande maioria das instruções do CRASIS são executadas em um ciclo de relógio. Porém, instruções de acesso à memória e desvios, que são bastante recorrentes em programas comuns, são executadas em mais de um ciclo. No CRASIS, estas instruções podem durar até três ciclos de clock. No entanto, esta proposta não foi implementada neste trabalho para que fosse mantida a simplicidade do processador e sua comparação com o processador DIMBA, visto que este último não contém nenhuma técnica de aumento de desempenho em sua estrutura, sendo indicada a implementação das técnicas de pipeline nos processadores como trabalhos futuros. 99 As versões adaptadas dos processadores não contém operações de suporte ao sistema operacional, interrupção e exceção. Devido a estas limitações, as instruções syscall e break, presentes no conjunto de instruções MIPS-I, não foram implementadas, sendo ideias para futuras modificações em suas estruturas. Este trabalho não considerou o consumo de potência de FPGAs como fator relevante na implementação das técnicas propostas. Segundo [Anderson & Najm, 2006], por carregarem o estigma de consumirem muita energia, os FPGAs geralmente são preteridos por processadores ASIC e de propósito gerais em razão de suas características de alto desempenho energético sem perdas de capacidade de processamento ou velocidade. Por consequência, os FPGAS hoje são utilizados como plataformas de simulação de sistemas digitais e como kits de desenvolvimento de trabalhos acadêmicos. Diversos trabalhos já foram temas de pesquisa acerca de técnicas de redução de potência em processadores reconfiguráveis, para poder expandir sua capacidade de processamento além de seu uso acadêmico. Ao se obter um baixo consumo de potência de um FPGA, juntamente com a característica de alteração ou atualização de uma ISA em um processador reconfigurável, poderá ser possível o desenvolvimento de uma nova gama de utilizações de processadores RISP. Assim como são comumente realizadas atualizações do software via rede, e mais recentemente atualizações de firmware e BIOS de computadores, poderá ser viável atualizar uma unidade de controle como se fosse efetuada a substituição do “kernel” da máquina, atualizando conjuntos de instruções de uma mesma família (como MIPS-I e MIPS-II) ou mesmo adicionando instruções ao inserir novas funcionalidades como uma unidade de ponto flutuante. 100 Referências Bibliográficas Adário, A. M. S.; Bampi, S.; Jacobi, R. P. (1997) Reconfigurable architectures. In: UFRGS MICROELECTRONICS SEMINAR. Porto Alegre, RS, Brasil: UFRGS MICROELECTRONICS SEMINAR, 1997. p. 133–136. ISBN T.I. - 650 – CPGCC. Altera (2013) website. Disponível em: http://www.altera.com Altman, E. R., Kaeli, D., Sheefer, Y. Welcome to the opportunities of binary translation. Computer, v. 33. n. 3. p. 40-45. 2000. Anderson, Jason H.; Najm, Farid N. (2006) Active Leakage Power Optimization for FPGA. IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems. [S.l], p. 423-437. Athanas, P. M., Silverman, H. F. (1993) Processor Reconfiguration Through Instruction-Set Metamorphosis. IEEE Computer, Vol. 26, no. 3 pp.11-18. 1993. Barat, F., Lauwereins, P. (2000) Reconfigurable Instruction Set Processors: A Survey, in: RSP ’00: Proceedings of the 11th IEEE International Workshop on Rapid System Prototyping (RSP 2000). Washington, DC, USA: IEEE Computer Society, 2000. p. 168. ISBN 0-7695-0668-2. Barat, Francisco (2002) Reconfigurable Instruction Set Processors from a Hardware/Software Perspective, IEEE Transactions on Software Engineering, Vol. 28, Nº 9. Beck, A. C. S., Carro, L. Dynamic reconfiguration with binary translation: breaking the ILP barrier with software compatibility. [S.1]:[s.n]. 2005. p. 732-737. Beck, A. C. S., et al (2008) Transparent Reconfigurable Acceleration for Heterogeneous Embedded Applications. [S.1]:[s.n]. 2008. p. 1208-1213. Brown, S., Francis, R., Rose, J., Vranesic, Z. (1992) Field-Programmable Gate Arrays, Kluwer Academic Publishers, Maio, 1992 Calazans, N.(2008) Organização de Computadores. UFRGS. Rio Grande do Sul. 2008. Carter, W., Duong, K., Freeman, R. H. Hsieh, H., Ja, J. Y., Mahoney, J. E., Ngo, L. T., Sze, S. L. (1986) A user programmable reconfiguration gate array, in Proceedings of the IEEE Custom Integrated Circuits Conference, pp. 233–235, May 1986. 101 Casillo, Leonardo A. (2005) Projeto e implementação em FPGA de um processador com conjunto de instrução reconfigurável utilizando VHDL. 126 p. Dissertação (Mestrado). Programa de Pós-Graduação em Sistemas e Computação, Universidade Federal do Rio Grande do Norte, Natal, Maio, 2005. Casillo, L. A., Lima, L. M. P., Souza, G. B., Silva, I. S. (2005a) Projeto e Implementação em FPGA de um Processador com Conjunto de Instrução Reconfigurável Utilizando VHDL. XI Workshop Iberchip. 2005, Salvador, Brasil. Casillo, L. A., Silva, I. S. (2012) Adapting a low complexity datapath to MIPS-1. Programmable Logic (SPL), 2012 VIII Southern Conference on, p. 1 – 6. Casillo, L. A., Silva, I. S. (2012a) A Methodology to Adapt Data Path Architectures to a MIPS-1 Model. Computing System Engineering (SBESC), 2012 Brazilian Symposium on, 2012, p. 172-177. Compton, K., Hauck, S., (2002) “Reconfigurable Computing: A Survey of Systems and Software”, ACM Computing Surveys, v. 34, n. 2, p. 171-210, June 2002. Corporation, Altera (2013) Altera Tutorials and Lab Exercises. Disponível em: ftp://ftp.altera.com/up/pub/Altera_Material/11.0/Laboratory_Exercises/Digital_Logic/D E2/verilog/lab9_Verilog.pdf. Acessado em maio, 2013. Costa, R. V., Fernandes, S. R., Casillo, L. A., Soares, A. Freire, D. (2012) SICXE: Improving Experience with Didactic Processors. Computing System Engineering (SBESC), 2012 Brazilian Symposium on, 2012, pages 83-86. Dos Santos, D. M. B., Pinto, G. R. P. R., Sena, C. P. P., Bertoni, F. C., & Bittencourt, R. A. (2007) Aplicação do método de Aprendizagem Baseada em Problemas no curso de Engenharia da Computação da Universidade Estadual de Feira de Santana. In: Congresso Brasileiro de Educação em Engenharia - COBENGE Fajardo Jr., J. (2011) Sistema de Tradução Binária de Dois Níveis para Execução MultiISA. Dissertação de Mestrado. Porto Alegre. Agosto de 2011. Ferlin, E., Pilla Jr, V., (2006) The Learning of Reconfigurable Computing in the Computer Engineering Program, in: FIE 2006, San Diego, USA Gorder, P. F., (2007) Multicore Processors for Science and Engineering, IEEE CS, March/April 2007. Kane, G.; Heinrich, J. (1991) MIPS RISC Architecture - 2nd Edition. Prentice-Hall, 544 p., 1991. Knight W. (2005) Two Heads Are Better Than One, IEEE Review, September 2005. Kumar, R. et al. (2005) Heterogeneous Chip Multiprocessor, IEEE Computer, Vol. 38, Issue 11, pp. 32-38, 2005. Larus, J. (2013) SPIM MIPS Simulator. Disponível http://www.cs.wisc.edu/~larus/spim.html Acessado em: Maio/2013. em: 102 Leon (2013) LEON2 Processor User’s Manual XST Edition, Gaisler Research. 2013. Liu, J., Chow, F., Kong. T,. Roy, R. (2003) Variable Instruction Set Architecture and Its Compiler Support. IEEE Trans. Comput., IEEE Computer Society, Washington, DC, USA, v. 52, n. 7, p. 881–895, 2003. ISSN 0018-9340. Lodi, A., Toma, M., Campi, F., Cappelli, A., Guerrieri, R (2003) A VLIW Processor Whit Reconfigurable Instruction Set for Embedded Applications. IEEE Journal of solidstate circuits, IEEE Computer Society, Washington, DC, USA, v. 538, n. 11, 2003. Martinez-Mones, A., Gomez-Sanchez, E., Dimitriadis, Y. A., Jorrin-Abellan, I. M., Rubia-Avi, B., & Vega-Gorgojo, G. (2005) Multiple Case Studies to Enhance ProjectBased Learning in a Computer Architecture Course. IEEE Transactions on Education, 48, 482–489. MARS (2013) MIPS Assembly and Runtime Simulator. Disponível http://courses.missouristate.edu/KenVollmar/MARS Acessado em: Junho/2013. em: Mesquita, D. G. (2002) Contribuições para reconfiguração parcial, remota e dinâmica de FPGAs. Dissertação (Tese de Mestrado) — Pontifícia Universidade Católica do Rio Grande do Sul, Porto Alegre, RS, Brasil, Março 2002. Mihal, A. Weber, S., Keutzer K. (2006) Sub-RISC processors. In P. Ienne and R. Leupers, editors, Customizable Embedded Processors: Design Technologies and Applications, chapter 13. Elsevier, 2006 MIPS Technologies (2008) MIPS32 Architecture For Programmers. Vol. II: The MIPS32 Instruction Set, 2008. Mooler, L. H., Moraes, F. G. e Calazans, N. L. V. (2005) Processadores Reconfiguráveis: Estado da Arte, In. XI Workshop Iberchip, 2005, Salvador, Brasil. Nunes, D. F., (2012) Proposta de implementação de um pipeline em um processador reconfigurável baseado em MIPS. Monografia. Mossoró-RN. 70 p. 2012. OpenCores (2013) website. Disponível em: http://www.open-cores.org. OpenSPARC (2013) website. Disponível em: http://www.opensparc.org. Oracle (2013) website. Disponível em: http://www.oracle.com/us/sun/ Patterson, D., Hennessy, J., (2007) Computer Architecture – A quantitative Approach. 4ª. Ed. Morgan-Kaufmann. 2007. Patterson, D., Hennessy, J., (2008) Computer Organization and Design: The Hardware/Software Interface. 4ª. Ed. 2008. PROCSIM (2013), website. Disponível em: http://jamesgart.com/procsim/ 103 Razdan, R.; Smith, M. D. (1994) A high-performance microarchitecture with hardware programmable functional units. In: MICRO 27: Proceedings of the 27th annual international symposium on Microarchitecture. New York, NY, USA: ACM Press, 1994. p. 172–180. ISBN 0-89791-707-3. Rhoads, S. (2013) Plasma CPU Core. website. Disponível em http://www.opencores.org. Rose, J., Gamal, A. El, Sangiovanni-Vincentelli, A. (1993) Architecture of FieldProgrammable Gate Arrays, in Proceedings of the IEEE, Vol. 81, No. 7, July 1993, pp. 1013-1029 Silva, I. S, Fernandes, S. R. , Casillo, L. A. (2011) ZONA -- An adaptable NoCbased multiprocessor addressed to education on system-on-chip design. In MSE '11: Proceedings of the 2011 IEEE International Conference on Microelectronic Systems Education. 2011. Pages 108-111. Stallings, W. (2010) Arquitetura e Organização de Computadores. 8ª ed. 640 p. Editora Prentice-Hall. RJ, Brasil. 2010. Sweetman, D. (2006) See MIPS Run. Morgan Kaufmann Publishers, 513 p., 2006. Tanenbaum, A. S. (2007) Organização Estruturada de Computadores, 5ª Edição, Pearson Prentice Hall, São Paulo, Brasil. Tong, Jason G., Anderson, Ian D. L., Khalid, Mohammed A. S., (2006) Soft-Core Processors for Embedded Systems. 18th International Conference on Microelectronics (ICM). 2006. Websimple – MIPS(2013) Simulador web-based do pipeline do MIPS. Disponível em: http://matheus.ath.cx/simple/ Wilkes, Maurice V. (1951) The preparation of programs for an electronic digital computer. Ed. Addison-Wesley Press. Universidade do Wisconsin – Madison. 1951. Xilinx, Inc (2013) website. Disponível em: http://www.xilinx.com 104 Apêndice A - Codificação dos formatos de Instruções no MIPS-I Nome SLL -- Shift left logical SRL -- Shift right logical SRA -- Shift right arithmetic Form. Instrução R 0000 00-- ---t tttt dddd dhhh hh00 0000 R 0000 00-- ---t tttt dddd dhhh hh00 0010 R 0000 00-- ---t tttt dddd dhhh hh00 0011 R 0000 00ss ssst tttt dddd d--- --00 0100 R R R R 0000 0000 0000 0000 00ss 0000 0000 00ss ssst 0000 0000 ssst tttt 0000 0000 tttt dddd dddd dddd 0000 d--d000 d000 0000 --00 0001 0001 0001 0110 0000 0010 1000 R R R R 0000 0000 0000 0000 00ss 00ss 00ss 00ss ssst ssst ssst ssst tttt tttt tttt tttt 0000 0000 0000 dddd 0000 0000 0000 d000 0001 0001 0001 0010 1001 1010 1011 0000 R R R R R 0000 0000 0000 0000 0000 00ss 00ss 00ss 00ss 00ss ssst ssst ssst ssst ssst tttt tttt tttt tttt tttt dddd dddd dddd dddd dddd d000 d000 d000 d000 d000 0010 0010 0010 0010 0010 0001 0010 0011 0100 0101 R R R R 0000 0000 0000 0000 00ss 00ss 0000 00ss ssst ssst 0000 sss0 tttt tttt 0000 0000 dddd dddd 0000 0000 d--d000 0000 0000 --10 0010 0000 0000 0110 0111 0000 1000 R 0000 00ss ssst tttt dddd d000 0010 1010 R 0000 00ss ssst tttt dddd d000 0010 1011 BGEZ -- Branch on greater than or equal to zero I 0000 01ss sss0 0001 iiii iiii iiii iiii BGEZAL -- Branch on grt. or equ to zero and link I 0000 01ss sss1 0001 iiii iiii iiii iiii SLLV -- Shift left logical variable SRLV -- Shift right logical variable MFHI -- Move from HI MFLO -- Move from LO MULT -- Multiply MULTU -- Multiply unsigned DIV -- Divide DIVU -- Divide unsigned ADD – Add (with overflow) ADDU -- Add unsigned (no overflow) SUB -- Subtract SUBU -- Subtract unsigned AND -- Bitwise and OR -- Bitwise or XOR -- Bitwise exclusive or NOR -- Bitwise nor NOOP -- No Operation JR -- Jump register SLT -- Set on less than (signed) SLTU -- Set on less than unsigned 105 BLTZ -- Branch on less than zero I 0000 01ss sss0 0000 iiii iiii iiii iiii I J J I 0000 0000 0000 0001 I 0001 01ss ssst tttt iiii iiii iiii iiii BLEZ -- Branch on less than or equal to zero I 0001 10ss sss0 0000 iiii iiii iiii iiii BGTZ -- Branch on greater than zero I 0001 11ss sss0 0000 iiii iiii iiii iiii ADDI -- Add immediate (with overflow) I 0010 00ss ssst tttt iiii iiii iiii iiii ADDIU -- Add immediate unsigned (no overflow) I 0010 01ss ssst tttt iiii iiii iiii iiii SLTI -- Set on less than immediate (signed) I 0010 10ss ssst tttt iiii iiii iiii iiii I 0010 11ss ssst tttt iiii iiii iiii iiii I 0011 00ss ssst tttt iiii iiii iiii iiii I 0011 01ss ssst tttt iiii iiii iiii iiii I 0011 10ss ssst tttt iiii iiii iiii iiii I I I I I 0011 1000 1000 1010 1010 BLTZAL -- Branch on less. or eq to zero and link J -- Jump JAL -- Jump and link BEQ -- Branch on equal BNE -- Branch on not equal SLTIU -- Set on less than immediate unsigned ANDI -- Bitwise and immediate ORI -- Bitwise or immediate XORI -- Bitwise exclusive or immediate LUI -- Load upper immediate LB -- Load byte LW -- Load word SB -- Store byte SW -- Store word 01ss 10ii 11ii 00ss 11-00ss 11ss 00ss 11ss sss1 iiii iiii ssst ---t ssst ssst ssst ssst 0000 iiii iiii tttt tttt tttt tttt tttt tttt iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii iiii 106 Apêndice B - Codificação dos formatos de Operações no CRASIS Esta codificação foi descrita para operações do tipo Op C, A, B, D. Os bits da palavra de reconfiguração seguem a sequência Bar C (5 bits), Bar A (5 bits), Bar B (5 bits), Aux (5 bits). Formato 000000 000001 000010 000011 000100 000101 000110 000111 001000 001001 001010 001011 001100 001101 001110 001111 010000 010001 010010 010011 010100 010101 010110 010111 011000 011001 011010 011011 011000 011101 011110 011111 100000 100001 100010 B_C A A A A A A A A A B B B B B B B B B C C C C C C C C C A A A A D D D A B_ A A A B B A C C C B B B A A B C C A C C C A A B C B A B A B C D B C D D B_ B A B A B C A C B C B A B A C B C C A C A C A C B B B A D D D A A A A B Significado A = A op A A = A op A A = A op B A = B op B A = A op C A = C opA A = C op C A = C op B A = B op C B = B op B B = B opA B = A op B B = A opA B = B op C B = C op B B = C op C B = A op C B = C opA C = C op C C = C opA C = A op C C = A opA C = B op C C = C op B C = B op B C = A op B C = B opA A = A op D A = B opD A = C opD A = D op A A = D op B A = D op C A = D op D B = A op D 107 100011 100100 100101 100110 100111 101000 101001 101010 101011 101100 101101 101110 101111 110000 110001 110010 110011 110100 110101 110110 110111 111000 111001 111010 111011 111100 111101 111110 111111 B B B B B B C C C C C C C D D D D D D D D D D D D D D D D D C D D D D A B C D D D D A D B D C D D A B A C B C A B C B D A B C D D D D A B C D D A D B D C D B A C A C B A B C B = B opD B = C opD B = D opA B = D op B B = D op C B = D opD C = A opD C = B opD C = C opD C = D opA C = D op B C = D op C C = D opD D = A op D D = D op A D = B opD D = D op A D = C opD D = X op C D = D op D D = A op B D = B opA D = A op C D = C opA D = B op C D = C op B D = A op A D = B op B D = C op C *No CRIS/CRASIS 2 os formatos com 4 operandos não são suportados. 108