UNIVERSIDADE FEDERAL DO RIO GRANDE DO NORTE CENTRO DE CIÊNCIAS EXATAS E DA TERRA
DEPARTAMENTO DE INFORMÁTICA E MATEMÁTICA APLICADA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO
Sistema Multiprocessado MIPS em VHDL
Elisio Breno Garcia Cardoso
Natal-RN Novembro/2017
Sistema Multiprocessado MIPS em VHDL
Monografia de Graduação apresentada ao Departamento de Informática e Matemática Aplicada do Centro de Ciências Exatas e da Terra da Universidade Federal do Rio Grande do Norte como requisito parcial para a obtenção do grau de bacharel em Ciência da Computação.
Orientadora
Profª. Dra. Monica Magalhães Pereira
Universidade Federal do Rio Grande do Norte – UFRN Departamento de Informática e Matemática Aplicada – DIMAp
Natal-RN Novembro/2017
Departamento de Informática e Matemática Aplicada do Centro de Ciências Exatas e da Terra da Universidade Federal do Rio Grande do Norte, sendo aprovada por todos os membros da banca examinadora abaixo especificada:
__________________________________________
Prof. Dra. Monica Magalhães Pereira Orientadora
Departamento de Informática e Matemática Aplicada Universidade Federal do Rio Grande do Norte
__________________________________________
Prof. Dr. Edgard de Faria Corrêa
Departamento de Informática e Matemática Aplicada Universidade Federal do Rio Grande do Norte
__________________________________________ Prof. Dr. Márcio Eduardo Kreutz
Departamento de Informática e Matemática Aplicada Universidade Federal do Rio Grande do Norte
Agradecimentos
Agradeço a Deus pelo Dom da Vida e por ter concedido a mim toda a força necessária para o enfrentamento de todos os desafios.
Aos meus pais e avós por me transmitirem os bons valores que nortearam toda a minha vida e por me darem todo o incentivo e o suporte nos bons momentos e principalmente nos difíceis.
Aos amigos de Ciência da Computação Victor Santiago, Bruno Leite, Cassio Sarmento, Vinícius Petch pela boa amizade que construímos, por cada resenha, cada discussão, cada trabalho, cada batalha que enfrentamos e superamos juntos durante todos esses anos. Que permaneçam sempre as boas lembranças.
À Professora Mônica, por toda a receptividade desde a nossa primeira reunião. Agradeço por toda a atenção e cuidado na orientação deste trabalho.
Aos professores do DIMAp dos quais eu tive a oportunidade de ser aluno por contribuírem para a minha formação cada um em sua respectiva área de conhecimento.
But it's been no bed of roses No pleasure cruise I consider it a challenge before The whole human race And I ain't gonna lose
Sistema Multiprocessado MIPS em VHDL
Autor: Elisio Breno Garcia Cardoso Orientadora: Profª. Dra. Monica Magalhães Pereira
R
ESUMO
Segundo a Lei de Moore, a capacidade de integração de transistores dobra a cada 18 meses. Essa previsão permitiu o aumento da complexidade em projetos dos sistemas embarcados e o surgimento dos sistemas em chip, em que todos os componentes básicos de um computador são integrados num único chip. A redução da área necessária para condensar bilhões de transistores num único chip permitiu um avanço com o surgimento dos sistemas multiprocessados em um único chip (MPSoC - Multiprocessor System on Chip). Nessa abordagem, vários processadores (núcleos) estão presentes dentro de um mesmo chip. Este trabalho descreve o projeto e desenvolvimento em VHDL de um sistema multiprocessado com 2 núcleos baseados no MIPS Pipeline com 5 estágios com um conjunto de instruções reduzido. Os resultados apresentam uma avaliação de diferentes aspectos de hardware relacionados à área, memória, desempenho, comunicação, dentre outros.
MIPS Multiprocessing System in VHDL
Author: Elisio Breno Garcia Cardoso Advisor: Profª. Dra. Monica Magalhães Pereira
A
BSTRACT
According to Moore's Law, transistor integration capacity doubles every 18 months. This prediction has allowed increased complexity in embedded systems designs and the emergence of System-on-Chip, where all the basic components of a computer are integrated into a single chip. The reduction of the area required to condense billions of transistors into a single chip allowed an advance with the emergence of multiprocessor systems on a single chip (MPSoC). In this approach, several processors (cores) are present inside the same chip. This monography describes the VHDL development of a MPSoC integrating two cores based on five stage MIPS pipeline processors with a reduced set of instructions. The results present an evaluation of different aspects of hardware related to the area, memory, performance, communication, and others.
Lista de figuras
Figura 1: Campos de uma instrução Formato R ... 24
Figura 2: Campos de uma instrução Formato I ... 24
Figura 3: Campos de instrução Formato J ... 25
Figura 4: Funcionamento básico de um circuito sequencial. Em uma das bordas (subidas ou descida), os valores contidos no elemento de estado são lidos, passam por alguma lógica combinatória e são salvos de volta no elemento de estado ... 28
Figura 5: Caminho de dados monociclo. ... 29
Figura 6: Comparação da linha de produção de bolos com e sem pipeline .. 30
Figura 7: Comparação da execução de instruções no MIPS com e sem pipeline. Sem pipeline, as instruções levam 2,5x mais tempo para serem executadas. ... 31
Figura 8: Divisão de um caminho de dados Monociclo simples em etapas menores ... 31
Figura 9: Caminho de dados MIPS Pipeline 5 estágios ... 32
Figura 10: Processador implementado neste trabalho ... 33
Figura 11: Máquina de Estados Finitos Proposta ... 41
Figura 12: Multiprocessador ... 43
Figura 13: Interconexão do sistema multiprocessado. ... 44
Figura 14: Matrizes 2x2 utilizadas nos testes ... 45
Figura 15: Matrizes 3x3 utilizadas nos testes ... 45
Figura 16: Número de instruções necessárias para multiplicação de duas Matrizes 2x2 no sistema desenvolvido ... 47
Figura 17: Número de instruções necessárias para multiplicação de duas Matrizes 3x3 no sistema desenvolvido ... 47
Figura 18: Número de ciclos necessários para multiplicação de duas
Matrizes 2x2 no sistema desenvolvido ... 48
Figura 19: Número de ciclos necessários para multiplicação de duas Matrizes 3x3 no sistema desenvolvido ... 48
Figura 20: CPI Médio da Multiplicação de duas Matrizes 2x2 com 1 núcleo e 2 núcleos ... 49
Figura 21: CPI Médio da Multiplicação de duas Matrizes 2x2 com 1 núcleo e 2 núcleos ... 49
Figura 22: Representação da matriz 2x2 no conjunto de instruções ... 54
Figura 23: Representação da matriz 3x3 no conjunto de instruções ... 56
Figura 24: Simulação da Multiplicação 2x2 com 1 núcleo ... 60
Figura 25: Simulação da Multiplicação 2x2 com 2 núcleos ... 60
Figura 26: Simulação da multiplicação 3x3 com 1 núcleo ... 61
Lista de tabelas
Tabela 1: Instruções implementadas ... 27
Tabela 2: Operações da ULA ... 36
Tabela 3: Definição da saída do controle da ULA ... 37
Tabela 4: Operações na ULA das Instruções com imediato ... 38
Tabela 5: Sinais de controle ... 39
Tabela 6: Linhas de Controle Utilizadas no Estágio de Execução/Cálculo de Endereço ... 40
Tabela 7: Linhas de Controle Utilizadas no Estágio de Acesso á Memória ... 40
Tabela 8: Linhas de Controle Utilizadas no Estágio de Escrita de Resultado ... 41
Tabela 9: Aspectos de hardware obtidos na síntese no Quartus 17.1 ... 50
Tabela 10: Instruções distribuídas nos 2 núcleos ... 55
Lista de abreviaturas e siglas
CPI – Ciclos por Instrução
DIMAp – Departamento de Informática e Matemática Aplicada EX - Execution
FPGA - Field Programmable Gate Array ID – Instruction Decode
IF – Instruction Fetch
LASIC - Laboratório de Sistemas em Chip LUT – LookUp Table
MEM - Memory
MESI – Modified, Exclusive, Shared, Invalid
MIPS - Microprocessor without Interlocked Pipeline Stages MPSoC - Multiprocessor System on Chip
NoC - Network on Chip PC – Program Counter
RASoC - Router Architecture for SoC
RISC - Reduced Instruction Set Computer SoC - System on Chip
SOCiN – SoC Interconection Network
UFRN – Universidade Federal do Rio Grande do Norte VHDL - VHSIC Hardware Description Language
VLSI - Very Large Scale Integration WB – Write Back
Sumário
1 Introdução ... 15
1.1 Organização do Trabalho ... 17
2 Trabalhos Relacionados ... 19
3 Referencial Teórico ... 23
3.1 Conjunto de Instrução do MIPS ... 23
3.2 Monociclo ... 28
3.3 Pipeline ... 29
4 Desenvolvimento do Sistema ... 33
4.1 Visão Geral do Núcleo Desenvolvido ... 33
4.2 Execução das Instruções ... 34
4.3 Controle da ULA ... 36
4.4 Controle do Pipeline ... 38
4.5 Máquina de Estados Finitos ... 41
4.6 Sistema Multiprocessado ... 41
5 Testes e Resultados ... 45
5.1 Descrição dos casos de testes ... 45
5.2 Resultados ... 46
5.3 Resultados da Síntese ... 50
6 Considerações finais ... 51
7 Referências Bibliográficas ... 52
APÊNDICE A – Instruções necessárias para a Multiplicação 2x2 com 1 núcleo ... 54
APÊNDICE B – Divisão das Instruções para a Multiplicação 2x2 com 2 núcleos ... 55 APÊNDICE C – Instruções necessárias para a Multiplicação 3x3 com 1 núcleo ... 56 APÊNDICE D – Divisão das Instruções para a Multiplicação 3x3 com 2 núcleos ... 58 APÊNDICE E – Simulações 2x2 ... 60 APÊNDICE F – Simulações 3x3 ... 61
1 Introdução
A tecnologia de fabricação de chips evolui rapidamente. Segundo a lei de Moore, a cada dezoito meses, a capacidade de integração de um mesmo circuito é dobrada (JOHANN; PONTES; LEITHARDT, 2007). Esse avanço fez com que coubessem bilhões de transistores no mesmo espaço onde cabiam na casa dos milhares há algumas décadas. Isso permitiu que os projetos de sistemas embarcados se tornassem cada vez mais complexos, possibilitando o surgimento dos sistemas em chip (SoC – System on chip), nos quais todos os componentes básicos de um computador podem ser inseridos dentro de um único chip.
A redução da área necessária para condensar bilhões de transistores num único chip permitiu um avanço ainda maior com o surgimento dos sistemas multiprocessados em um único chip (MPSoC - Multiprocessor
System on Chip). Nessa abordagem, vários processadores (núcleos) estão
presentes dentro de um mesmo chip, permitindo a exploração de um maior paralelismo na execução das aplicações e um ganho no desempenho (ALVES; NAVAUX; KASTENSMIDT, 2007).
O uso de MPSoCs não diz respeito somente à utilização de vários processadores num mesmo chip, mas também a uma otimização para sua aplicação (JOHANN; PONTES; LEITHARDT, 2007). Vários processadores dentro de um mesmo chip trazem consigo alguns desafios que os desenvolvedores têm de lidar no projeto a fim de que a arquitetura se adeque bem ao seu propósito e de forma otimizada. Em razão disso, várias soluções estão sendo estudadas e desenvolvidas a cada dia levando em consideração as características das aplicações que serão executadas. O TILE-Gx72 da (MELLANOX TECHNOLOGIES, 2015) é um exemplo de MPSoC comercial com 72 processadores conectados por uma rede em chip.
Uma dessas soluções diz respeito à energia do sistema, vários núcleos num chip provocam um maior consumo de energia. O projetista, por exemplo, tem de levar em consideração a aplicação alvo na hora de projetar a arquitetura para que não sejam incluídos blocos desnecessários que
16
dissiparão mais potência e, consequentemente, aumentarão o consumo de energia, ou então tentando diminuir a dissipação de energia por circuitos ociosos (MOTTA, 2008).
Outro desafio diz respeito à memória. O projetista terá de quantificar o total de memória requisitado pela aplicação que será executada no MPSoC e tomar decisões de projeto para definir se os núcleos terão uma única memória compartilhada, ou se cada um terá sua própria memória privada, e como será a organização das memórias na arquitetura (OLIVEIRA; SILVA, 2010).
A memória cache possui a função de entregar dados ao processador com uma baixa latência e diminuir o tráfego na comunicação. A quantidade de cache que cada núcleo irá dispor, a arquitetura das caches, a coerência das caches e o protocolo de controle das caches constituem desafios ao projetista de um MPSoC (TORTATO; HEXSEL, 2009).
A comunicação também é algo importante a ser considerado no projeto, a troca de informações é algo crucial na eficiência da arquitetura. Por muito tempo foi utilizada a tecnologia de barramento, porém ela se mostra cada vez menos eficiente à medida que se aumenta o número de processadores no chip. No contexto de MPSoC, o uso de redes em chip (NoC – Network-on-Chip) é o mais adequado para interligar os vários núcleos (JOHANN; PONTES; LEITHARDT, 2007).
Os desafios citados anteriormente têm muito conhecimento a ser explorado e permitem a observação da flexibilidade oferecida pela abordagem MPSoC. Com um único chip podendo conter vários processadores, os desenvolvedores têm a oportunidade de utilizar processadores diferentes com suas próprias características de consumo, memória, frequência, resultando em sistemas heterogêneos (OLIVEIRA, 2009). Muitos dos sistemas embarcados produzidos nos dias de hoje (telefones celulares, televisões, dentre outros) já seguem esse paradigma, com núcleos ajustados para cada tipo de aplicação contida nele.
Neste trabalho, será descrito o desenvolvimento de um sistema multiprocessado com dois núcleos baseados no MIPS Pipeline de 5 estágios com conjunto de instruções reduzido e interligados através de um barramento para que seja realizada comunicação entre eles. O processador foi implementado na linguagem de descrição de hardware VHDL (VHSIC
Hardware Description Language) e sintetizado num FPGA (Field Programmable Gate Array).
O sistema foi desenvolvido com o objetivo de analisar a viabilidade do projeto de sistemas multiprocessados em linguagem de descrição de hardware e síntese em FPGA, provendo um sistema multiprocessado para investigação dos desafios relacionados aos MPSoCs. Bem como, fornecer a avaliação de diferentes aspectos de hardware relacionados à área, memória, desempenho, comunicação, dentre outros.
O sistema desenvolvido será utilizado em outros projetos acadêmicos desenvolvidos no Laboratório de Sistemas em Chip (LASIC) do Departamento de Informática e Matemática Aplicada (DIMAp) os quais não estão no escopo deste trabalho.
1.1 Organização do Trabalho
O capítulo 2 apresenta alguns trabalhos relacionados a este aqui desenvolvido. Dentre os quais, é apresentada a principal referência utilizada nesse trabalho, alguns abordam desenvolvimento de MPSoC em VHDL e sintetizados em FPGA, são analisados nestes trabalhos aspectos de hardware e de desempenho. Outros trabalham em algum desafio relacionado à área de sistemas multiprocessados, e o impacto gerado pelas mudanças no desempenho do sistema.
O capítulo 3 apresenta a base teórica necessária para o entendimento deste trabalho. Foi apresentado o conjunto de instruções MIPS, bem o conjunto reduzido de instruções que foi implementado neste trabalho. Este capítulo também abordou os princípios de funcionamento de um caminho de dados monociclo, e também a técnica pipeline, mostrando as principais
18
vantagens em relação à abordagem monociclo e as alterações no monociclo para a construção de um caminho de dados pipeline MIPS com 5 estágios.
O capítulo 4 apresenta o desenvolvimento de um núcleo baseado no MIPS Pipeline com 5 estágios (busca de instrução, decodificação da instrução, execução/cálculo de endereço, acesso à memória de dados, escrita do resultado). São detalhadas as alterações realizadas em relação ao caminho de dados do livro Organização e Projeto de Computadores (PATTERSON; HENNESSY, 2005), e o funcionamento interno do sistema. E, por fim, foi mostrada a integração de duas instâncias do núcleo desenvolvido para a constituição de um sistema multiprocessado.
O capítulo 5 apresenta os testes que foram realizados com seus respectivos resultados. Os testes foram feitos com multiplicação de duas matrizes de dimensões 2x2 e duas matrizes 3x3. Os resultados foram obtidos medindo o número de instruções necessárias, o número de ciclos necessários para a execução e o CPI médio. Os resultados foram descritos em gráficos comparativos da execução de uma mesma multiplicação fazendo uso de 1 núcleo e de 2 núcleos.
O capítulo 6 apresenta algumas considerações finais, e o capítulo 7 apresenta as referências.
2 Trabalhos Relacionados
Este capítulo apresenta alguns trabalhos correlatos a este aqui proposto. Dos trabalhos pesquisados, este capítulo apresenta alguns que abordam os conceitos de MIPS e sistemas multiprocessados, outros abordam o desenvolvimento de projetos multicore em VHDL sintetizados em FPGA enquanto outros são voltados a algum desafio da área de multiprocessadores.
O livro Organização e Projeto de Computadores (PATTERSON; HENNESSY, 2005) fornece material detalhado sobre o conjunto de instrução do MIPS. Essa referência foi o principal material utilizado para o desenvolvimento desse trabalho. O livro apresenta o passo a passo de um projeto de caminho de dados para a execução das principais instruções do MIPS (acesso à memória, operações lógicas e aritméticas, desvios condicionais e incondicionais), explicando todos os componentes do sistema tanto para o MIPS Monociclo quanto para o Multiciclo. Este livro também traz um capítulo explicando a técnica de pipeline com cinco estágios num processador MIPS, adicionando novos componentes em relação ao caminho de dados monociclo para se ajustar à técnica.
Em (JOHANN; PONTES; LEITHARDT, 2007), são descritas características de uma possível solução para desenvolvedores de Sistemas em Chip (SoC), na dificuldade de acompanhamento do crescimento da tecnologia VLSI (Very Large Scale Integration). Destacando o projeto baseado em plataformas e sistemas multiprocessados em um único chip (MPSoC), buscando um desenvolvimento ágil e um alto nível de abstração. Este trabalho também traz um breve estudo de caso sobre a plataforma híbrida HiBRID-SoC, constituída de três núcleos num único chip, vários núcleos de memória e barramento AMBA de 64 bits. Ele une características de MPSoC e de projetos baseados em plataforma e foi desenvolvido para atender aplicações de processamento de sinais multimídia.
20
O trabalho de (ZHANG et al., 2006) descreve um MPSoC baseado em FPGA que integra 4 núcleos do tipo ARM. Nesse trabalho, o MPSoC interliga os seus núcleos através de um barramento de duas camadas, a primeira para realizar a comunicação entre cada núcleo e sua memória privada, a segunda camada interliga os núcleos à memória compartilhada do sistema. Os testes foram realizados com multiplicação de matrizes, cada processador lê uma matriz na memória compartilhada e a multiplica com uma matriz lida na sua memória local, e os resultados gravados na memória compartilhada. O desempenho é avaliado medindo o speedup em comparação com o sistema de processador único. Quando multiplicadas 16 matrizes 4x4, o sistema multiprocessado executa 2,186 vezes mais rápido que o sistema de processador único, já quando são multiplicadas 64 matrizes, executa 3,205 vezes mais rápido.
Já em (ALVES; NAVAUX; KASTENSMIDT, 2007), são avaliados alguns aspectos de uma arquitetura contendo quatro núcleos implementados numa FPGA, em linguagem VHDL. Os núcleos são do tipo mMIPS, que é uma versão reduzida do MIPS, com pipeline de cinco estágios e cada um com suas respectivas memórias privadas. Foram interconectados através da rede em chip (NoC) SOCiN, uma rede escalável baseada em uma arquitetura de roteadores paramétricos RASoC (Router Architecture for SoC). Neste trabalho, os resultados da implementação com quatro mMIPS são comparados com uma que utiliza quatro processadores MicroBlaze e são comparadas também as redes em chip SOCiN 2x2 e Hermes 2x2. De acordo com os autores, a implementação com 4 mMIPS ocupou 35% mais Flip Flops e 23% mais LUTs (LookUp Tables) do que a com 4 MicroBlazes. Já em relação às redes em chip, a SoCIN consumiu 49% menos Flip Flops e 40% menos LUTs que a Hermes.
O trabalho de (TORTATO; HEXSEL, 2009) apresenta um projeto de MPSoC com caches coerentes desenvolvido na linguagem VHDL e baseado em FPGA o qual pode suportar de 1 a 8 núcleos MIPS-I. É abordado o desafio da coerência das memórias cache, cujas funções são: entregar dados ao processador com baixa latência e reduzir o tráfego no barramento, uma
vez que acertos na cache reduz os acessos à memória. Este apresenta o protocolo de coerência MESI, utilizado no projeto, que combina eficiência facilidade de implementação. As letras da abreviatura MESI representam os estados que os blocos podem assumir. M (modified) representa um bloco que foi atualizado enquanto as outras cópias estão desatualizadas. E (exclusive), a memória está atualizada e nenhuma outra cópia existe nas caches. S (shared), o bloco é compartilhado e as outras cópias estão atualizadas. E, por fim, um bloco no estado I (invalid), não pode ser utilizado. O sistema foi simulado com 1, 2, 4 e 8 processadores, e testada uma multiplicação de matrizes 8x8 de inteiros. Os resultados obtidos com multiprocessador foram comparados ao resultado obtido utilizando somente 1 núcleo. Com 2 núcleos, houve ganho de 16,4% no número de ciclos. Com 4 núcleos, o ganho foi de 48%. Com 8 núcleos o ganho foi de 45,8%. O autor observou que o desempenho não cresce linearmente por causa da saturação do barramento que ocorre com 4 ou mais processadores.
(OLIVEIRA; SILVA, 2010) avalia o impacto dos modelos de memória distribuída e compartilhada no projeto de sistemas multiprocessados. Este trabalho utiliza a plataforma virtual baseada em NoC Storm, que fornece um processador, caches de instrução de dados, módulos de memória, módulos de diretório para manutenção da coerência das caches, um modelo de rede em chip (mesh 2D) e módulos de interface com a NoC. É utilizada como estudo de caso uma aplicação de simulação de reservatório, da área de petróleo e gás. São comparados resultados como CPI (ciclos por instrução) médio, latência média e total de instruções executadas obtido em cada um dos dois modelos. O modelo de memória distribuída apresenta resultados melhores quando avaliados o CPI médio e a carga injetada na NoC, enquanto o modelo de memória compartilhada apresenta resultados melhores quanto à latência média dos pacotes na NoC.
Os trabalhos citados acima foram utilizados para auxiliar no desenvolvimento do sistema multiprocessado. O sistema implementado neste trabalho foi baseado na versão Pipeline de 5 estágios do processador MIPS apresentada em (PATTERSON; HENNESSY, 2005). Foram considerados
22
os aspectos analisados pelos autores em (OLIVEIRA; SILVA, 2010), bem como o modelo implementado em (ALVES; NAVAUX; KASTENSMIDT, 2007), para a análise dos resultados de desempenho.
3 Referencial Teórico
Esta seção apresenta alguns dos conceitos necessários para que haja um bom entendimento deste trabalho. A seção 3.1 trata do conjunto de instruções MIPS. A seção 3.2 aborda o monociclo. A seção 3.3 apresenta o MIPS Pipeline. Por fim, a seção 3.4 aborda os Sistemas Multiprocessados em Chip (MPSoC).
3.1 Conjunto de Instrução do MIPS
Atualmente, existem diversas linguagens de programação. Cada tipo de projeto na computação exigirá certas características que impactarão na escolha da linguagem mais adequada para a sua implementação. As linguagens evoluíram ao longo dos anos de tal forma que seus códigos-fonte se tornaram de cada vez mais fácil entendimento. A legibilidade permitiu o aumento da produtividade dos programadores e facilitou a manutenção dos softwares. Sabendo uma linguagem, fica menos difícil o aprendizado de outras.
Uma máquina interpreta um programa de uma forma diferente do ser humano. Enquanto o programador escreve seus algoritmos utilizando uma linguagem de programação de alto nível de abstração, o computador o interpreta em linguagem de máquina, com um baixo nível de abstração. Em todas as linguagens de programação existentes, o compilador é o programa que realiza a conversão do código de alto nível em código de baixo nível. Ele recebe como entrada o código escrito pelo programador e retorna como saída outro programa equivalente ao original, em uma linguagem de baixo-nível que é interpretável pela máquina. Isso requer a existência de um conjunto de instruções bem definido para a execução no hardware.
O MIPS é um processador do tipo RISC surgido na década de 1980 que executa instruções utilizando valores lidos nos registradores. O conjunto de instrução do MIPS foi o escolhido para ser executado pelo multiprocessador. A opção se deu pelo fato do MIPS ser um dos tipos processadores mais utilizados desde a sua criação. Vários fabricantes utilizam processador MIPS
24
em seus microprocessadores, dentre os quais podem ser citados a ATI Technologies, Broadcom, Cisco, Nintendo, Sony, dente outros (PATTERSON; HENNESSY, 2005).
O MIPS pipeline de 5 estágios possui instruções com 32 bits de tamanho. As instruções são subdivididas em vários campos com significados distintos, sendo três formatos diferentes: R, I e J. Os significados são descritos abaixo:
Formato R
Figura 1: Campos de uma instrução Formato R (PATTERSON; HENNESSY, 2005)
op: Operação básica da instrução, também chamado de opcode;
rs: Registrador do primeiro operando de origem;
rt: Registrador do segundo operando de origem;
rd: Registrador do operando de destino;
shamt: Shift amount, quantidade de deslocamento, utilizado nas
instruções de deslocamento;
funct: Variante da operação do campo op.
Formato I
Figura 2: Campos de uma instrução Formato I (PATTERSON; HENNESSY, 2005)
op: Opcode da instrução;
rs: Registrador do primeiro operando de origem;
rt: Registrador do segundo operando de origem em operações de
desvio, registrador de destino em operações lógicas e aritméticas;
Endereço/Imediato: Endereço de desvio em instruções de desvio e segundo operando de origem em instruções lógicas e aritméticas.
Formato J
Figura 3: Campos de instrução Formato J (PATTERSON; HENNESSY, 2005)
op: Opcode da instrução;
Endereço de destino: Define o endereço da próxima instrução, o
qual será armazenado no PC.
Um processador MIPS possui 32 registradores com 32 bits cada. Estes são blocos de dados que podem ser comparados às variáveis das linguagens de programação de alto nível, tendo como diferença principal o número finito de registradores presentes na arquitetura (PATTERSON; HENNESSY, 2005). As principais operações executadas pelo MIPS são as de acesso a memória, operações lógicas e aritméticas, desvios condicionais e desvios incondicionais.
As operações de acesso à memória possuem a função de realizar a troca de informações entre a memória de dados e o banco de registradores. A operação lw (load word) carrega um valor armazenado na memória de dados e o salva no banco de registradores. A operação sw (store word) faz o inverso, ela carrega um valor no bando de registradores e faz o seu armazenamento na memória de dados.
O formato da instrução do lw é bastante simples, é a palavra lw seguida do registrador destino do dado, de uma constante que é o offset, e de um segundo registrador que tem seu valor somado ao offset para formar o endereço da memória de dados. O sw é bastante parecido ao lw, tendo como diferenças que o primeiro registrador contém o valor que será armazenado na memória de dados. Nos exemplos abaixo, a posição 10 de $s1 é carregada no registrador $t0, e $t1 é salva na posição 2 de $s2.
26
lw $t0, 10($s1) sw $t1, 2($s2)
O MIPS dispõe de várias operações lógicas aritméticas. Todas elas possuem três operandos, o primeiro sendo o registrador de destino da operação, o segundo sendo um registrador de origem e o terceiro podendo ser outro registrador de origem ou um número que é chamado de imediato. Uma execução de instruções no MIPS pode ser feita buscando valores na memória de dados com o lw, em seguida, executando as operações desejadas com os valores lidos e, por fim, salvando os resultados de volta no banco de registradores. O exemplo abaixo demonstra bem isso, dois valores são buscados, duas operações são executadas e, em seguida, os valores são salvos de volta na memória.
lw $t0, 40($s1) lw $t1, 2($s2) add $t3, $t0, $t1 subi $t4, $t1, 6 sw $t3, 40($s1) sw $t4, 2($s2)
As operações de desvio condicional tomam uma decisão referente ao fluxo de execução de programa. As principais são o beq (branch equal) e o
bne (branch not equal), a primeira altera o fluxo de execução do programa
quando os valores contidos nos dois registradores passados são iguais, a segunda altera quando os valores contidos nos registradores são diferentes. Nos exemplos abaixo, o fluxo é alterado para a instrução L1 quando os valores contidos em $t0 e $t1 são iguais e é alterado para L2 quando os valores contidos em $t2 e $t3 são diferentes.
bne $t0, $t1, L1 beq $t2, $t3, L2
A instrução de desvio incondicional, j (jump), altera o fluxo de execução do programa de forma que a próxima instrução é definida pelo endereço do salto. As células de memória do PC possuem o tamanho de 8 bits, são retornadas 4 células para compor o dado de 32 bits em cada acesso
a essa unidade. As instruções de desvio só precisam referenciar endereço de memória da primeira célula e as outras três são juntadas para formar o dado de 32 bits. Sendo assim, os endereços do PC precisam sempre ser múltiplos de 4. No exemplo abaixo, o fluxo de execução é alterado para a instrução determinada pelo label L1.
j L1
A Tabela 1 apresenta todas as instruções do MIPS implementadas nesse trabalho:
Tabela 1: Instruções implementadas
Categoria Instrução Exemplo Significado
Aritmética Add add $s1, $s2, $s3 $s1 = $s2 + $s3 Add immediate addi $s1, $s2, 20 $s1 = $s2 + 20 Subtract sub $s1, $s2, $s3 $s1 = $s2 - $s3 Subtract immediate subi $s1, $s2, 20 $s1 = $s2 - 20 Mult mult $s1, $s2 HI = ($s1* $s2)[63-32] LO = ($s1* $s2)[31-0] Mult immediate multi $s1, 20 HI = ($s1* 20)[63-32] LO = ($s1* 20)[31-0] Div div $s1, $s2 HI = ($s1mod $s2)[63-32] LO = ($s1/ $s2)[31-0] Div
immediate divi $s1, 20
HI = ($s1mod 20)[63-32] LO = ($s1/ 20)[31-0] Move from HI mfhi $s1 $s1 = HI
Move from
LO mflo $s1 $s1 = LO
Lógica
AND and $s1, $s2, $s3 $s1 = $s2 & $s3 AND
immediate andi $s1, $s2, 20 $s1 = $s2 & 20 OR or $s1, $s2, $s3 $s1 = $s2 | $s3 OR
immediate ori $s1, $s2, 20 $s1 = $s2 | 20 NAND nand $s1, $s2, $s3 $s1 = ¬($s2 & $s3)
NOR nor $s1, $s2, $s3 $s1 = ¬($s2 | $s3) XOR xor $s1, $s2, $s3 $s1 = (¬$s2 & $s3)|($s2 & ¬$s3) Shift left logical sll $s1, $s2, 10 $s1 = $s2 << 10 Shift right logical srl $s1, $s2, 10 $s1 = $s2 >> 10 Desvio Condicional Branch Equal beq $s1, $s2, 25 if ($s1 == $s2) go to PC+4 + 100 Set on less than stl $s1, $s2, $s3 if ($s2 == $s3) $s1=1 else $s1 = 0 Desvio Incondicional Jump j 20 Go to 80
28
3.2 Monociclo
Os circuitos lógicos podem ser classificados como combinacionais ou sequenciais. São combinacionais quando as portas lógicas são interconectadas para produzir uma saída para certas combinações das variáveis de entrada (FLOYD, 2007) e são classificados como sequenciais quando mudam de estado na borda positiva (borda de subida), ou na borda negativa (borda de descida) do pulso de clock (TANEMBAUM, 2007). A figura 4 exemplifica a execução de um ciclo, onde os valores armazenados nos registradores são lidos, enviados para alguma lógica combinatória e armazenados novamente nos registradores (PATTERSON; HENNESSY, 2005). Um caminho de dados pode ser construído integrando circuitos combinacionais e sequenciais.
A figura 5 mostra um caminho de dados capaz de executar as principais operações MIPS (acesso à memória, lógicas e aritméticas, desvios e jump). É um projeto bem simples e foi desenvolvido para executar uma instrução dentro de um ciclo, por isso é chamado de Monociclo. O tempo que uma instrução deverá levar para executar pode ser calculado realizando a soma das durações de cada etapa no caminho de dados.
O monociclo não é a abordagem mais utilizada nos dias de hoje. Mesmo que funcione corretamente, ele é muito ineficiente, pois o ciclo do
clock é determinado pelo tempo da instrução mais duradoura dentro do
caminho de dados (PATTERSON; HENNESSY, 2005), neste caso o load word, uma operação que passa por todos os componentes do caminho de dados.
Figura 4: Funcionamento básico de um circuito sequencial. Em uma das
bordas (subidas ou descida), os valores contidos no elemento de estado são lidos, passam por alguma lógica combinatória e são salvos de volta no
Com o tamanho fixo para todos os tipos de instruções e sem que haja paralelismo algum, o sistema fica com vários períodos de ociosidade em instruções que duram menos tempo do que o ciclo do clock. O desperdício poderá aumentar ainda mais se o processador for capaz de realizar operações de ponto flutuante.
Figura 5: Caminho de dados monociclo (PATTERSON; HENNESSY, 2005).
3.3 Pipeline
Pipelining é uma técnica de implementação em que várias instruções
são sobrepostas na execução (PATTERSON; HENNESSY, 2005), aproveitando melhor os recursos do sistema. Este conceito pode ser entendido de uma forma melhor quando é comparado a situações reproduzíveis no mundo real. Tanenbaum faz uma analogia do pipeline com a linha de produção de uma fábrica de bolos (TANEMBAUM, 2007), em que processo de embalagem de um bolo é concluído em exatamente 5 passos. A cada 10 segundos, um bolo entra na esteira. O funcionário 1 coloca uma embalagem na esteira, funcionário 2 coloca um bolo dentro dela, a funcionário 3 sela a caixa, o funcionário 4 coloca a etiqueta e o funcionário 5 estoca o produto final.
Supondo que cada funcionário realiza a sua tarefa em 10 segundos, cada bolo demorará 50 segundos para ser completamente embalado. Se um
30
novo bolo entrasse na esteira somente após o término de todas as tarefas do anterior, teríamos uma grande ociosidade no processo já que um funcionário ficaria uma boa quantidade de tempo desocupado enquanto o processo não se inicia novamente.
Utilizando pipeline, esse processo poderia ser melhorado. Após concluir a sua atividade uma vez, os funcionários já poderiam estar prontos para realizá-la novamente. Por exemplo, após funcionário 2 ter colocado um bolo na embalagem, ele já poderia colocar a embalagem em outro bolo logo em seguida. Dessa forma, haveria mais bolos prontos um período menor de tempo conforme evidenciado na Figura 6.
Figura 6: Comparação da linha de produção de bolos com e sem pipeline
Os princípios do pipeline podem ser utilizados para execução paralela de instruções no MIPS. As instruções MIPS normalmente exigem 5 estágios (PATTERSON; HENNESSY, 2005):
1. IF (Instruction Fetch): Buscar a instrução na memória.
2. ID (Instruction Decode): Ler registradores enquanto a instrução é decodificada.
3. EX: Executar a operação ou calcular um endereço. 4. MEM: Acessar um operando na memória de dados.
5. WB (Write Back): Escrever o resultado em um registrador.
A duração de cada estágio do pipeline é determinada pelo tempo do estágio mais demorado. Como as instruções possuem o mesmo número de estágios, e cada estágio tem a mesma duração, todas as instruções possuem o mesmo tempo de execução. A execução paralela proporciona ganhos no
número de ciclos de clock por instrução (CPI). Na Figura 7, as 4 instruções levariam 20 ciclos de clock para serem executadas no monociclo. Quando elas são executadas paralelamente no pipeline, levam 8 ciclos no total.
O MIPS Pipeline com 5 estágios pode ser projetado a partir de adaptações realizadas no MIPS Monociclo. Para isso, basta mapear cada etapa da instrução no caminho de dados da direita pra esquerda (PATTERSON; HENNESSY, 2005). A Figura 8 apresenta a divisão dos estágios no Monociclo.
A execução de instruções paralelamente exige a retenção das informações produzidas em cada estágio (PATTERSON; HENNESSY, 2005).
Figura 7: Comparação da execução de instruções no MIPS com e sem pipeline. Sem
pipeline, as instruções levam 2,5x mais tempo para serem executadas.
Figura 8: Divisão de um caminho de dados Monociclo simples em etapas menores
32
Isso é feito através da inserção de um buffer entre cada par de estágios intermediários. A cada ciclo de clock, as informações produzidas num estágio são guardadas e utilizadas no clock seguinte, quando a instrução estará no próximo estágio. A Figura 9 apresenta uma arquitetura simples do MIPS Pipeline com 5 estágios.
A versão do MIPS pipeline implementada neste trabalho não é exatamente igual à apresentada nesta seção. No próximo capítulo será apresentada a versão implementada juntamente com a descrição das modificações que foram necessárias.
4
Desenvolvimento do Sistema
Neste capítulo é descrito o desenvolvimento do sistema, o qual possui dois núcleos do tipo MIPS Pipeline 5 estágios. A Seção 4.1 traz uma visão geral da arquitetura implementada, a Seção 4.2 detalha as operações em cada um dos 5 estágios do pipeline, a Seção 4.3 apresenta o Controle da ULA, a Seção 4.4 apresenta o Controle do Pipeline e, por fim, a Seção 4.5 apresenta integração de duas instâncias do processador para a formação de um sistema multiprocessado. Durante este capítulo são apresentadas as mudanças em relação á arquitetura da Figura 9.
Todo o desenvolvimento foi feito na linguagem de descrição de hardware VHDL utilizando a ferramenta de síntese Quartus 17.1 64-bits.
É importante destacar que para a versão apresentada neste trabalho, o pipeline não realiza tratamento de conflitos de dados ou de controle. Os conflitos são resolvidos através da inclusão de instruções NOOP (No
Operation), manualmente ou pelo compilador antes do início da execução. O
tratamento de conflitos é parte dos trabalhos futuros.
4.1 Visão geral do núcleo desenvolvido
O núcleo desenvolvido foi baseado no caminho de dados MIPS Pipeline do livro apresentado no livro Organização e Projeto de Computadores (PATTERSON; HENNESSY, 2005), Figura 9, porém com algumas alterações que foram necessárias para se adaptar à sincronização do sistema. A figura 10 fornece uma visão geral do núcleo implementado:
34
Figura 10: Processador Implementado neste trabalho
4.2 Execução das Instruções
A execução de uma de uma instrução foi subdividida em cinco estágios, com duração de um ciclo de clock cada. O Fluxo da execução é da esquerda para a direita se olharmos a Figura 10. São os estágios: Busca de Instrução (IF – Instruction Fetch), Decodificação da Instrução (ID – Instruction
Decode), Execução (EX - Execution), Acesso à Memória (MEM – Memory Access), Escrita do Resultado (WB – Write Back).
As leituras nos Buffers dos estágios e demais elemento de estado (PC, Memória de Dados e Instruções, Banco de Registradores, Registradores HI e LO) são efetuadas na borda de descida do clock, enquanto as operações de escrita nos mesmos são realizadas na borda de subida do clock.
Cada tipo de instrução segue um fluxo de execução no caminho de dados. Abaixo são descritas as operações desempenhadas em cada estágio no pipeline.
Busca da instrução (IF): O endereço da instrução que entra no PC é
de instruções. Tem seu valor incrementado em 4, referente aos 4 Bytes que o endereço ocupa, o qual é armazenado no Buffer IF/ID (em cor roxa na figura 10) para o caso de ele ser necessário num estágio seguinte. Aqui há uma mudança em relação à arquitetura da Figura 9. A saída da memória de instruções foi interligada diretamente nos componentes do estágio seguinte em vez de ser armazenado no Buffer IF/ID. Isso foi necessário para garantir a sincronia do sistema.
Decodificação da instrução (ID): Os 16 bits menos significativos da
instrução são estendidos para 32 bits, que pode ser necessário caso a operação seja do tipo imediato. Os 26 bits menos significativos também são estendidos para 32 bits, que pode ser necessário caso a instrução seja um jump. Há também neste estágio a leitura dos sinais de controle de componentes dos 3 estágios seguintes. Todos esses valores são armazenados no Buffer ID/EX (em cor laranja na Figura10, que apesar de estar em duas partes separadas na Figura 10, são o mesmo componente). Neste estágio ocorre a busca dos operandos no banco de registradores, cujos endereços correspondem aos bits [25-21] da instrução para o primeiro operando e [20-16] da segunda instrução para o segundo operando e também é realizada a leitura dos registradores HI e LO se for necessário, estes valores não foram armazenados no Buffer IF/ID para não prejudicar a sincronização do sistema. A saída do banco de registradores e dos registradores HI e LO foram conectadas diretamente nos componentes do próximo estágio.
Execução (EX): Neste estágio, as instruções de acesso à memória
(load word e store word) realizam uma soma na ULA para calcular o endereço de leitura na memória, no caso do load word, ou de escrita na memória para o store word. Instruções lógicas e aritméticas executam na ULA sua operação correspondente. Instruções de desvio condicional fazem uma subtração na ULA para determinar a ocorrência ou não do desvio através do valor “zero”, e soma ao PC incrementado o valor estendido deslocado em 2 bits à esquerda. O resultado da operação da ULA, o sinal “zero” saído da ULA, a soma do
36
desvio e o endereço do registrador de destino são armazenados no
Buffer EX/MEM, em cor verde na Figura 10.
Acesso à memória (MEM): Ocorre o acesso à memória de dados para
leitura, se a instrução for um load word, ou escrita, se for um store
word. As demais instruções não utilizam a memória de dados. O
resultado da operação da ULA e o endereço do registrador de escritas são escritos no Buffer MEM/WB, em cor azul na Figura 10. Para uma boa sincronização do sistema, a saída da memória de dados foi conectada diretamente no próximo estágio.
Escrita do resultado (WB): Nesta última etapa, o resultado da ULA é
escrito no registrador de destino.
4.3 Controle da ULA
O controle da ULA possui 4 bits de entrada, o que permite mapear até 16 operações para execução na ULA. A Tabela 2 apresenta as operações que foram implementadas na ULA, para as quais foram 12 das combinações possíveis para mapear as operações.
Tabela 2: Operações da ULA
Linhas de Saída do
Controle da ULA Função
0000 AND 0001 OR 0010 ADD 0011 MULT 0100 DIV 0110 SUB 0111 SLT 1000 NAND 1001 NOR 1010 XOR 1110 SLL 1111 SRL
A operação realizada pela ULA dependerá da classe de instrução executada. Para instruções do se acesso à memória (load word, store word), a ULA realizará uma adição para calcular o endereço de memória. Para instruções lógicas e aritméticas, o campo funct, composto pelos 6 bits menos
significativos determinará qual operação será executada. Instruções lógicas e aritméticas com imediato realizarão suas respectivas operações na ULA. Instruções de desvio condicional sempre realizarão subtração e, por fim, a instrução jump não utiliza a ULA em sua execução.
As entradas de 4 bits da ULA são determinadas pelo componente Controle da ULA para instruções lógicas e aritméticas, acesso à memória e desvio condicional. O Controle da ULA determina a operação pelo campo
funct, correspondente aos 6 bits menos significativos da instrução. Os dois
bits mais significativos são chamados de OpULA, que determinará uma adição para operações de acesso á memória (00), uma subtração no caso de operação de desvio condicional (01), e usará o campo funct para determinar a operação da ULA para instruções do tipo R (01). Operações lógicas e aritméticas com imediato terão a operação da ULA determinadas diretamente pelo Controle do Pipeline.
Tabela 3: Definição da saída do controle da ULA
OpCode da Instrução OpULA
Operação da Instrução Funct Ação da ULA Saída do Controle da ULA
LW 100011 00 Load Word XXXXXX ADD 0010 SW 101011 00 Store Word XXXXXX ADD 0010 Branch 000100 01 Branch Equal XXXXXX subtract 0110
Tipo R 000000 10 ADD 100000 ADD 0010
Tipo R 000000 10 SUB 100010 Subtract 0110
Tipo R 000000 10 AND 100100 AND 0000
Tipo R 000000 10 OR 100101 OR 0001
Tipo R 000000 10 NAND 101100 NAND 1000
Tipo R 000000 10 NOR 101101 NOR 1001
Tipo R 000000 10 XOR 101110 XOR 1010
Tipo R 000000 10 Set on less than 101010 Set on less than 0111 Tipo R 000000 10 Shift Left Logical 101000 Shift Left Logical 1110 Tipo R 000000 10 Shift Right Logical 101001 Shift Right Logical 1111 Mult/Div 000001 10 MULT 100001 MULT 0011
Mult/Div 000001 10 DIV 100011 DIV 0100
Apesar de serem operações lógicas e aritméticas, foi atribuído à multiplicação e à divisão um OpCode separado para cada, e há uma pequena diferença em seus sinais de controle uma vez que fazem escrita no
38
registrador HI e LO, o que não é o caso das outras operações lógicas e aritméticas. Isso ficará mais claro na seção seguinte.
Para as instruções com imediato, a operação da ULA é determinada diretamente pelo Controle do Pipeline, que enviará os 4 bits de controle da ULA de acordo com o OpCode recebido na entrada:
Tabela 4: Operações na ULA das Instruções com imediato
OpCode da Instrução Ação da ULA Controle Saída do
ADDI 010000 ADD 0010 SUBI 010010 Subtract 0110 ANDI 010100 AND 0000 ORI 010110 OR 0001 MULTI 010001 MULT 0011 DIVI 010011 DIV 0100 MFLO 100000 ADD 0010 MFHI 100001 ADD 0010
Um multiplexador foi inserido na porta de entrada da operação da ULA para definir de onde virá a operação que ela vai executar. O valor ‘0’ indica que a operação da ULA será aquela vinda do Controle da ULA (para operações de acesso à memória, lógicas e aritméticas e desvio condicional), o valor ‘1’ indica que a operação da ULA será a vinda do Controle do Pipeline (para operações lógicas e aritméticas com imediato).
4.4 Controle do Pipeline
A Figura 10 permite observar que alguns componentes do processador possuem linhas azuis na entrada, estes são os sinais de controle. Estas são necessárias para permitir que o processador desempenhe ações corretas em cada estágio de pipeline, pois os diferentes tipos de instruções realizam algumas ações diferentes durante a execução. A Tabela 5 apresenta os sinais de controle:
Tabela 5: Sinais de controle
Sinal Quando Inativo Quando Ativo
PCSrc O valor escrito no PC será o que foi incrementado em 4 no somador. O valor escrito no PC será o calculado no desvio. Jump O valor escrito no PC será o selecionado no mux PCSrc. O valor escrito no PC será o do jump. RegDst
Os registrador de destino será determinado pelo campo rt (instrução[20-16]).
O registrador de destino será determinado pelo campo rd (instrução[15-11]).
ReadHI Não faz leitura no registrador HI. Faz leitura no registrador HI. ReadLO Não faz leitura no registrador LO. Faz leitura no registrador LO.
HiOrLo Seleciona o valor vindo do LO Seleciona o valor vindo do HI
AluOP1 O primeiro operando da ULA vem do banco de registradores. O primeiro operando da ULA vem dos registradores HI/LO. AluOP2 O segundo operando da ULA vem do banco de registradores. O segundo operando da ULA vem do imediato (instrução[15-0]) extendido
para 32 bits.
OpSrc O sinal de 4 bits da operação da ULA vem do Controle da ULA. O sinal de 4 bits da operação da ULA vem do Controle do Pipeline. MemRead Não faz leitura na memória de dados. Faz leitura na memória de dados. MemWrite Não faz escrita na memória de dados. Faz escrita na memória de dados. MemToReg O valor de escrita no banco de registradores vem da ULA.
O valor de escrita no banco de registradores vem da memória de dados.
RegWrite Não faz escrita no banco de registradores. Faz registradores. escrita no banco de WriteHILO Não faz escrita nos registradores HI e LO. Faz escrita nos registradores HI e LO.
Em cada estágio de execução, são consumidos alguns sinais de controle em alguns dos seus componentes:
Busca de Instrução (IF): As linhas de controle nos multiplexadores
determinam de onde virá o que atualizará o endereço do PC, podendo ter origem no somador que incrementa o endereço em 4, de uma instrução de desvio ou da instrução jump.
Decodificação da Instrução (ID): Neste estágio, as linhas utilizadas
decidem se serão lidos os valores contidos nos registradores Hi e Lo e a de um multiplexador usado para determinar qual destes dois valores é o que irá para o próximo estado.
Execução/Cálculo do Endereço (EX): Os sinais de controle
determinam qual será o registrador de destino da instrução, de onde virá o primeiro operando da ULA (dos registradores HI/LO ou do banco
40
de registradores), de onde virá o valor do segundo operando da ULA (do sinal do imediato estendido ou do banco de registradores), determinam também se o sinal da operação da ULA virá do Controle da ULA ou do Controle do Pipeline.
Acesso à memória (MEM): As linhas de controle definem se será feita
leitura e escrita na memória de dados, e se será o desvio que atualizará o valor do PC.
Escrita do Resultado (WB): As linhas de controle definem de onde
virá o valor de escrita (memória de dados ou resultado da ULA) e se haverá escrita no banco de registradores e nos registradores HI/LO. As Tabelas 6, 7 e 8 mostram os principais sinais de controle gerados para cada tipo de instrução. Os campos com valor ‘X’ são os que não fazem diferença para a instrução em determinado estágio.
Tabela 6: Linhas de Controle Utilizadas no Estágio de Execução/Cálculo de Endereço
Instrução Estágio de Execução/Calculo de Endereço RegDst OpALU AluOP1 AluOP2 OpSRC
Tipo R 0 “10” 0 0 0 Mult/Div 0 “10” 0 0 0 Imediato 0 “10” 0 1 1 Lw 1 “00” 0 1 0 Sw X “00” 0 1 0 Beq X “01’ 0 0 0 Jump X X X X X mflo 0 X 1 1 1 rlhi 0 X 1 1 1
Tabela 7: Linhas de Controle Utilizadas no Estágio de Acesso á Memória
Instrução
Estágio de Acesso à Memória
Branch Jump WriteMEM ReadMEM
Tipo R 0 0 0 0 Multi/Div 0 0 0 0 Imediato 0 0 0 0 Lw 0 0 0 1 Sw 0 0 1 0 Beq 1 0 0 0 Jump X 1 X X mflo 0 0 0 0 rlhi 0 0 0 0
Tabela 8: Linhas de Controle Utilizadas no Estágio de Escrita de Resultado
Instrução
Estágio de Escrita de Resultados
WriteReg WriteHILO MemToReg
Tipo R 0 0 0 Multi/Div 1 1 0 Imediato 1 0 0 Lw 1 0 1 Sw 0 0 X Beq 0 X X Jump X X X mflo 0 0 0 rlhi 0 0 0
4.5 Máquina de Estados Finitos
A execução de instruções num Pipeline nem sempre ocorre de forma perfeita, pois pode haver a ocorrência de dependência de dados se uma instrução precisar do valor de um registrador que ainda não foi escrito por outra instrução. Neste trabalho, o tratamento de conflitos foi realizado através de uma máquina de estados finitos.
A máquina de estados finitos proposta nesse trabalho controla a leitura e a escrita no PC e as leituras e escritas dos Buffers que retém os dados gerados pelos estados.
42
A figura 11 apresenta os estados que foram definidos para a máquina de estados deste trabalho. A execução começa no estado “00000” (cor azul) e sempre termina no estado “10011” (cor vermelha).
Os estados “00000” a “00100” controlam a execução do pipeline no fluxo normal, começando com o pipeline vazio (estado “00000”) até o pipeline ficar cheio (“00100”), ou seja, com 5 instruções executando paralelamente. À medida que os estados avançam, os sinais de leitura e escrita dos Buffers vão sendo liberados.
Os estados “00101” “01010” controlam a execução do pipeline quando é detectada uma dependência de dados entre instruções. Quando esses estágios estão ativos, a leitura e a escrita no PC são bloqueadas e a instrução que está com a dependência de dados fica parada no primeiro estágio do pipeline até que as outras instruções finalizem a execução todos os 5 estágios. Após o executar o último estado do tratamento de conflitos, a máquina volta ao fluxo de execução normal do pipeline no estado “00001” e a instrução que estava com a dependência pode obter o valor atualizado.
Os estados “01011” a “01101” finalizam a execução do pipeline quando o pipeline está completo, enquanto os estados “01110” a “10011” finalizam a execução do pipeline quando ele está incompleto. A execução do pipeline sempre finaliza no estado “10100”, quando a última instrução finaliza sua execução.
4.6 Sistema Multiprocessado
A arquitetura multiprocessada é apresentada na Figura 12. Ela é constituída por duas instâncias do processador baseado no MIPS Pipeline com 5 estágios desenvolvido neste trabalho. Os dois processadores foram interligados a uma interface que os conecta a uma única memória de dados presente no sistema.
Figura 12: Multiprocessador
Algumas mudanças foram necessárias para a formação do sistema multiprocessado com apenas uma memória de dados compartilhada. As memórias de dados do processador desenvolvido foram removidas, e os sinais de controle envolvidos no estágio de acesso à memória foram interligados à interface de comunicação. Dessa forma, as instruções de acesso à memória load word e store word de ambos os núcleos são executadas numa mesma memória de dados compartilhada.
A intercomunicação do sistema não utilizou nenhum barramento preexistente, em vez disso foi desenvolvida uma interface de comunicação que interliga os dois núcleos à memória de dados. Ela recebe, como entrada dos dois núcleos, o endereço de memória, o dado de entrada (necessário para o store word) e os sinais de controle de leitura e escrita. Envia de volta para os núcleos o dado leitura (necessária para o load word). Neste trabalho, não foi implementado nenhum mecanismo de controle de acesso à memória e detecção de conflitos. A Figura 13 apresenta a interconexão do sistema, as linhas em cor azul são as saídas dos núcleos e as linhas em vermelho são as entradas dos núcleos.
44
Figura 13: Interconexão do sistema multiprocessado.
A memória de dados também sofreu adaptações no desenvolvimento da arquitetura multiprocessada. Como ela está interligada aos dois núcleos através da interface de comunicação, passou a receber os sinais de controle de leitura e escrita dois núcleos, o endereço e o dado de entrada dois núcleos, bem como ter duas saídas de dados.
5 Testes e Resultados
Este capítulo apresenta os dois cenários testes que foram realizados no sistema desenvolvido neste trabalho, executando-os com o sistema monoprocessado e com o sistema multiprocessado contendo 2 núcleos. Foram fornecidas comparações relacionadas ao desempenho nos dois cenários, além de fornecidos alguns resultados da síntese através da ferramenta Quartus 17.1 64-bits.
5.1 Descrição dos casos de testes
Para fornecer uma boa comparação entre o sistema monoprocessado e o multiprocessado com 2 núcleos, procurou-se utilizar de uma aplicação que as instruções fossem executadas paralelamente no sistema dois núcleos sem que houvesse dependência de dados entre elas.
A multiplicação de matrizes é uma aplicação que se encaixa bem nesse critério de escolha. Cada elemento da matriz resultado é calculado em função de uma única linha da primeira matriz operando e uma coluna da segunda matriz de operandos. Assim, não haverá dependência de dados no cálculo dos valores das matrizes resultado se as linhas da primeira matriz de operandos forem distribuídas entre os dois núcleos. Essa distribuição permite que os valores das linhas da matriz resultado sejam calculados paralelamente no sistema multiprocessado.
As Figuras 14 e 15 mostram as matrizes utilizadas nos testes.
Figura 14: Matrizes 2x2 utilizadas nos testes
46
Em todos os cenários de teste descrito abaixo, as instruções necessárias para realizá-los foram organizadas manualmente de forma que não houvesse conflito entre elas durante a execução.
O primeiro cenário de testes foi realizado no sistema monoprocessado. Foram consideradas duas instâncias de testes, uma instância multiplica duas matrizes 2x2 e a outra multiplica duas matrizes 3x3. Em ambos os casos, o processador fez a leitura das duas matrizes de operandos na memória de dados, realizou a multiplicação das duas matrizes e salvou a matriz resultado na memória de dados.
Já o segundo cenário de testes foi realizado no sistema multiprocessado com 2 núcleos, cada um calculando uma parte da matriz resultado e salvando resultado na memória compartilhada. Neste cenário, foram consideradas duas instâncias, uma multiplicando duas matrizes de dimensão 2x2 e outra multiplicando duas matrizes 3x3.
No caso da multiplicação 2x2, a matriz resultado também tem dimensões 2x2, sendo assim, cada núcleo calculou uma linha da matriz resultado. No caso da multiplicação 3x3, o primeiro núcleo calculou a primeira linha, o segundo núcleo calculou a segunda linha e a terceira teve parte calculada em um e parte em outro.
5.2 Resultados
Os resultados aqui apresentados correspondem aos casos de teste descritos na seção anterior, com a multiplicação de matrizes 2x2 e 3x3.
A Figura 16 apresenta um gráfico comparando a multiplicação de duas matrizes 2x2 com 1 núcleo e com 2 núcleos. Com 1 núcleo, foram necessárias 32 instruções para realizar a multiplicação completa, enquanto foram necessárias 21 instruções em cada núcleo, no total de 42 instruções, para realizar a mesma multiplicação no sistema multiprocessado. Os Apêndices A e B descrevem as instruções necessárias para a execução da multiplicação de matrizes 2x2 com 1 núcleo e com 2 núcleos, respectivamente.
Figura 16: Número de instruções necessárias para multiplicação de duas Matrizes 2x2 no
sistema desenvolvido
A Figura 17 apresenta um gráfico comparando a multiplicação de duas matrizes 3x3 com 1 núcleo e com 2 núcleo. Com somente 1 núcleo, foram necessárias 99 instruções para realizar a multiplicação completa. Com 2 núcleos foram necessárias 60 instruções no núcleo 1 e 51 instruções no núcleo 2, num total de 111 instruções para realizar a mesma multiplicação. A diferença entre o número de instruções executadas por cada núcleo ocorre porque eles calculam um número diferentes de elementos da matriz resultado, o núcleo 1 calcula 5 elementos enquanto o núcleo 2 calcula 4 elementos. Os Apêndices C e D descrevem as instruções necessárias para a execução da multiplicação de matrizes 3x3 com 1 núcleo e 2 núcleos, respectivamente.
Figura 17: Número de instruções necessárias para multiplicação de duas Matrizes 3x3 no
48
A Figura 18 apresenta um gráfico comparando o número de ciclos necessário para realizar a multiplicação. Quando a multiplicação foi realizada no sistema multiprocessado com 2 núcleos, houve uma redução de 30,6% no número de ciclos necessários em relação ao sistema monoprocessado.
Figura 18: Número de ciclos necessários para multiplicação de duas Matrizes 2x2 no
sistema desenvolvido
A Figura 19 apresenta um gráfico comparando o número de ciclos necessário para realizar a multiplicação. Quando a multiplicação foi realizada no sistema multiprocessado com 2 núcleos, houve uma redução de 37,9% no número de ciclos necessários em relação ao sistema monoprocessado.
Figura 19: Número de ciclos necessários para multiplicação de duas Matrizes 3x3 no
sistema desenvolvido
Em relação ao CPI Médio (Ciclos por Instrução), são apresentados nas Figuras 20 e 21 os resultados obtidos nos casos de teste. No caso da
multiplicação de duas matrizes 2x2, é possível observar que houve uma redução de 47,2% no CPI Médio do sistema multiprocessdo em relação ao CPI médio do sistema multiprocessado. Já na multiplicação 3x3, houve uma redução de 44,6% no CPI Médio do sistema multiprocessado.
Figura 20: CPI Médio da Multiplicação de duas Matrizes 2x2 com 1 núcleo e 2 núcleos
Figura 21: CPI Médio da Multiplicação de duas Matrizes 2x2 com 1 núcleo e 2 núcleos
Algumas das simulações realizadas para analisar os resultados podem ser encontradas nos apêndices E e F, para a multiplicação de matrizes 2x2 e 3x3, respectivamente.
50
5.3 Resultados da Síntese
Os códigos na linguagem VHDL foram desenvolvidos na ferramenta de síntese Quartus 17.1 64-bits. O código-fonte foi sintetizado pra o FPGA EP4CE115F29C7, da família Cyclone IV E. A síntese foi realizada no sistema monoprocessado e no sistema multiprocessado com 2 núcleos. A tabela 9 apresenta os resultados obtidos:
Tabela 9: Aspectos de hardware obtidos na síntese no Quartus 17.1
Nº de Núcleos Elementos Lógicos Total de Registradores Bits de Memória elements Embedded Multiplier 9-bit 1 Núcleo 3157 (3%) 536 67584 (2%) 6 (1%) 2 Núcleos 117610 (103%) 33956 69632 (2%) 12 (2%)
Apesar de o banco de registradores possuir somente 32 registradores, houve uma utilização de 600 registradores pelo sistema com 1 núcleo, o que foi ocasionado pela metodologia utilizada no projeto de inserir sinais auxiliares nas saídas dos componentes do processador. A quantidade de bits de memória utilizados foi dentro do esperado uma vez que a memória de instruções e a memória de dados utilizam cada uma 32.768 bits.
Realizando uma comparação entre os resultados das sínteses do sistema monoprocessado e do sistema multiprocessado, houve um grande aumento na quantidade de registradores utilizado pelo sistema multiprocessado. Quando detalhados os dados da síntese do sistema multiprocessado, foi constatado que a ferramenta não conseguiu realizar simplificações no circuito durante a síntese e a memória de dados compartilhada, que deveria ter sido alocada dentre os bits de memória, foi instanciada como registradores. Um trabalho futuro trata-se da realização de simplificações na programação do sistema para corrigir tais problemas citados.