MO601/MC973 - Projeto I

Especificação

Você deve implementar um simulador do processador RISC-V RV32IM, que significa a versão de 32 bits com as instruções básicas e também as instruções de multiplicação e divisão.

Você pode utilizar como referência o simulador Spike para verificar seu código.

As seguintes funcionalidades básicas são necessárias:

  • Linha de log a cada instrução gerada, o log do Spike foi alterado, então veja a especificação do log desejado abaixo.
  • Contagem de ciclos de execução: neste primeiro momento, considere que cada instrução gaste um ciclo para executar. É importante que você tenha uma infraestrutura que permita alterar estes valores futuramente pois será necessário nos trabalhos futuros.
  • Você deve ser capaz de executar um programa saído de um compilador/linker. É opcional emular um sistema operacional. Você pode utilizar o objdump ou objcopy para converter os arquivos executáveis num formato mais direto seu. Neste caso, implemente esta ação através de um script já com as linhas de comando corretas.
  • Você deverá fornecer um repositório git do seu código, com toda a sua implementação e um arquivo Readme indicando como executar o programa.
  • Seu simulador deve ser capaz de executar todos os programas de inteiros do ACStone (isto significa que não precisa executar os programas de ponto flutuante).
  • O ciclo de verificação utilizado na correção será similar ao indicado no vídeo 2 da primeira semana, repetido uma vez para cada programa individual do ACStone.
  • Encapsule todos os acessos à memória através de alguma função. Futuramente você terá que inserir temporização na memória e sua implementação estará preparada.
  • Procure deixar seu código bem organizado e estruturado de forma a permitir que, no futuro, você seja capaz de executar um simulador multicore (simular a execução de mais de uma thread ao mesmo tempo).

Entrega

A entrega deverá ser feita através da atividade no Google Classroom, onde você fornecerá um link para o seu repositório git.

Formato do Log de instruções

O log de instruções deverá ser conforme o padronizado abaixo. Cada instrução executada deve gerar uma linha de log. Cada campo da linha deverá ficar entre colchetes e ter um espaço entre dois campos seguidos. A linha possui 6 campos conforme abaixo

  1. Endereço do PC da instrução atual, em hexadecimal, com 8 dígitos. Ex: [PC=00000100]
  2. Instrução em hexadecimal. Apenas o valor em hexadecimal dos 32 bits da instrução entre colchetes. Ex.: [012345678]
  3. Valor do registrador de destino (rd) após a instrução. Ex.: considerando o registrador 15 como destino, [x15=000AAA00]. Note que nem todas as instruções escrevem num registrador, mas veja que os registradores estão sempre nos mesmos campos em bits nas instruções. Então você deve imprimir sempre o registrador indicado pelos bits 7-11 da instrução após a instrução.
  4. Valor do registrador de origem 1 (rs1) antes da instrução. Ex.: considerando o registrador 3 como origem, [x03=99988877]. Observe o zero entre o x e o 3 para padronizar a formatação. Aqui você deve imprimir o registrador indicado pelos bits 15-19 da instrução, independente da instrução fazer uso desses bits para indexar um registrador.
  5. Valor do registrador de origem 2 (rs2) antes da instrução. De forma similar ao item anterior, utilizando os bits 20-24.
  6. Dissassembly da instrução. Imprima o mnemônico (sem pseudo instrução) com tamanho de 8 espaços, seguido dos registradores e campos de imediato conforme a sintaxe da instrução. Aqui você deve imprimir tudo em decimal, tomando cuidado para utilizar representação sinalizada onde for necessário. Utilize a nomenclatura conforme a ABI (dica: declare um vetor de nomes de registrador com o nome de cada um corretamente e apenas indexe com o índice do registrador). Aqui você não precisa adicionar zero à esquerda do registrador para escrever com dois dígitos.

Como sugestão de abordagem sobre a implementação, monte a linha de log numa estrutura de dados e passe para uma função fazer a impressão. Assim a saída ficará mais uniforme no seu código. Você pode fazer algo similar com o disassembly indicando o formato em que a instrução deve ser escrita na tela.