FE310G: um microcontrolador open source RISC-V – Introdução

Que tal utilizar um microcontrolador de alto desempenho e de código/hardware aberto? Nesta série de artigos (também publicado no portal Embarcados) eu falo um pouco sobre o FE310G desenvolvido pela SiFive, a primeira implementação comercial do core RISC-V. Para quem não conhece, a iniciativa RISC-V (riscv.org) foi criada com o objetivo de desenvolver um processador de alto desempenho e código aberto, que possa ser utilizado no desenvolvimento de aplicações e produtos de uso geral. RISC-V é uma ISA (Instruction Set Architecture ou arquitetura de conjunto de instruções) desenvolvida originalmente na Universidade da Califórnia e que compreende conjuntos de instruções de 32, 64 bits e 128 bits, além de variações como um conjunto de instruções comprimido (similar ao THUMB da ARM e o MIPS16e) além de extensões para multiplicação e divisão, operações vetoriais, ponto flutuante (simples, dupla ou quádrupla precisão), operações atômicas, SIMD (Single Instruction Multiple Data), sistemas embarcados (uma versão simplificada do processador), etc. Em termos de desempenho, segundo os seus criadores, ele pode atingir até 1.61 DMIPs/MHz ou 2.73 Coremark/MHz.

Uma das características interessantes a respeito do RISC-V é que o conjunto de instruções comprimidas pode coexistir diretamente com as instruções de tamanho normal, ou seja, não é necessário trocar o estado da CPU para que se utilize instruções de 16 ou 32 bits (como normalmente acontece nos ARM com os estados ARM e THUMB e também nos MIPS). Vale lembrar que os cores Cortex mais recentes da ARM implementam novas versões do THUMB (THUMB-2) que incluem instruções de 16 e de 32 bits, mas mesmo assim, nos processadores que incluem instruções ARM e THUMB-2 (como os Cortex-A), é necessário trocar de estado para se alternar entre instruções ARM e THUMB-2.

Outro detalhe que a vale a pena ser mencionado é o fato de que, até o presente momento, a ISA RISC-V não apresenta nenhuma extensão voltada ao processamento digital de sinais com inteiros, algo já bastante comum em outras arquiteturas voltadas para sistemas embarcados, tais como ARMv7-M, ARMv8-M, Renesas RX, MIPS, etc. No entanto, as extensões FPU seguem o padrão IEEE754-2008 e incluem instruções para multiplicação e acúmulo e multiplicação e subtração, mas elas são voltadas para aritmética de ponto flutuante apenas.

Vale lembrar também que além do E31 (o core de 32 bits utilizado no FE310G) a SiFive possui o E51 (um core de 64 bits) e o U5 (um sistema multicore de alta performance capaz de rodar Linux e com até oito cores U54 mais um core opcional U51, todos de 64 bits).

Importante também frisar que a ISA RISC-V é totalmente suportada pelo GCC e dispõe de ambiente de programação (Freedom Studio) baseado no Eclipse e GDB, ou seja, tanto o hardware quanto o software são gratuitos e open source!

A Arquitetura RISC-V

A ISA RISC-V possui basicamente três especificações conforme o tamanho dos operandos: 32 bits (RV32I e RV32E), 64 bits (RV64I) e 128 bits (RV128I). O sufixo I indica que trata-se da versão integer, ao passo que o sufixo E indica que se trata da versão embarcada (e um pouco simplificada). Outros sufixos podem estar presentes quando a implementação inclui extensões, como A (suporte a instruções e operações atômicas), C (suporte a instruções comprimidas), M (multiplicação e divisão), F (FPU com suporte a float ou precisão simples), D (FPU com suporte a double ou precisão dupla), Q (FPU com suporte a quad ou precisão quadrupla), V (suporte a operações vetoriais), etc.

Estão definidos 32 registradores de uso geral (nomeados x0 a x31), além de um registrador para o contador de programa (PC) (o RV32E possui apenas 16 registradores de uso geral e o PC).

[table “1” not found /]

Tabela 1 – Registradores da CPU

Uma característica interessante do RISC-V reside no fato de que não há um registrador de status para armazenar flags da ULA, ao invés disso, a ISA implementa instruções de desvio que podem comparar diretamente registradores.

A ISA inclui também alguns outros registradores especiais (CSR – Control and Status Register) que residem num espaço especial de memória (até 2048 registradores) e que são acessados por instruções especiais:

  • CSRRW – leitura e escrita de um CSR (o CSR é lido para o registrador de destino e o conteúdo do registrador fonte é copiado para o CSR);
  • CSRRS – leitura e set de um CSR (o CSR é lido para o destino e em seguida seus bits são setados de acordo com a máscara no registrador fonte);
  • CSRRC – leitura e apagamento de bits de um CSR (o CSR é lido para o destino e em seguida seus bits são apagados de acordo com a máscara no registrador fonte);
  • CSRRWI – o CSR é lido para o registrador de destino e em seguida alterado conforme a constante imediata;
  • CSRRSI – o CSR é lido para o registrador de destino e setado conforme a máscara imediata;
  • CSRRCI – o CSR é lido para o registrador de destino e apagado conforme a máscara imediata;

A princípio três registradores são mandatários (exceto na RV32E) e devem estar implementados em todas as versões de cores RISC-V. Estes registradores (todos somente leitura) podem ser utilizados para estatísticas de desempenho do core e outras tarefas:

  • RDCYCLE e RDCYCLEH – armazenam o número de ciclos de clock (64 bits) desde um instante inicial arbitrário;
  • RDTIME e RDTIMEH – armazenam o número de ciclos do standard timer (64 bits) desde um instante inicial arbitrário;
  • RDINSTRET e RDINSTRETH – armazenam o número (64 bits) de instruções retiradas (executadas) desde um instante inicial arbitrário.

Além destes, outros registradores CSR relativos aos modos privilegiados de execução (que no RISC-V podem ser até três: usuário, supervisor e máquina) deverão estar presentes quando o core implementar a ISA de execução privilegiada (que até a presente data encontra-se ainda no draft v1.10 e sujeita a alterações). Basicamente o modo usuário é o modo não privilegiado normalmente utilizado para a aplicação enquanto que o modo supervisor permite acesso mais amplo ao sistema e o modo máquina permite acesso irrestrito. As tabelas a seguir apresentam os CSR relativos aos três modos de operação.

Tabela 2 – Registradores CSR de Usuário
Tabela 3 – CSRs do Modo Supervisor
Tabela 4 – CSRs do Modo Máquina

Relativamente às instruções, a ISA RV32I inclui um total de 47, sendo possível uma implementação reduzida com apenas 38 instruções (removendo-se algumas instruções como FENCE, ECALL, EBREAK e as instruções CSSRxx). A tabela 5 a seguir mostra os seis formatos básicos de opcodes da RV32I e a tabela 6 apresenta o conjunto de instruções.

Tabela 5 – Formatos Básicos de Instruções RV32I
Tabela 6 – Instruções RV32I

Todas as instruções de manipulação de dados operam com operandos de 32-bits, mas as instruções de carga e armazenamento podem operar com outros tamanhos de operandos: LB e LBU carregam um byte da memória (LBU também faz a extensão de sinal), LH e LHU carregam uma half-word (16 bits) da memória (LHU também faz a extensão de sinal). SB, SH e SW são utilizadas para armazenar um byte, half-word ou word na memória respectivamente.

Repare na existência de duas instruções voltadas a sincronização de acesso a memória (instruções e dados) em sistemas multiprocessados (FENCE e FENCE.I). FENCE.I é especialmente útil para assegurar que o cache de instruções está atualizado após qualquer tipo de escrita na memória de programa.

Além das instruções RV32I, o microcontrolador apresentado nesta série de artigos inclui ainda extensões de multiplicação e divisão (sufixo M) e operações atômicas (sufixo A). As tabelas a seguir apresentam as instruções relativas a estas extensões.

Tabela 7 – Instruções da Extensão M (Multiplicação e Divisão)
Tabela 8 – Instruções da Extensão A (Operações Atômicas)

Com relação à extensão de instruções compridas (C), é importante destacar que a ISA RISC-V prevê que a CPU irá traduzir (descomprimir) em tempo real as instruções de 16 bits nos seus equivalentes de 32 bits, sem qualquer perda de performance. Além disso, graças ao seu formato extensível, é possível ter instruções com comprimentos de 16, 32, 48, 64 ou mais bits. A distinção entre os diversos comprimentos é determinada pela codificação dos bits menos significativos conforme ilustra a tabela 9.

Tabela 9 – Codificação da Largura de Instruções RISC-V

O conjunto de instruções comprimidas é apresentado nas tabelas 10, 11 e 12 a seguir.

Tabela 10 – Instruções RISC-V comprimidas (quadrante 0)
Tabela 11 – Instruções RISC-V comprimidas (quadrante 1)
Tabela 12 – Instruções RISC-V comprimidas (quadrante 2)

Por fim, há também um pequeno conjunto de instruções de modo privilegiado (Supervisor e Máquina) que se encontram listadas na tabela 13. Note aqui a existência de uma instrução voltada à suspensão da execução e espera por uma interrupção (WFI – Wait For Interrupt).

Tabela 13 – Instruções Privilegiadas

Na próxima parte deste artigo vamos conhecer sobre o sistema de interrupções e processamento de exceção do RISC-V e também alguns detalhes sobre o FE310G, a primeira implementação comercial em silício do RISC-V. Até lá!

Referências

Nota: as tabelas utilizadas neste artigo foram retiradas da documentação da SiFive no website indicado nas referências acima.

Leave a Reply