Memory interface is now MMIO-capable

This commit is contained in:
2023-10-11 21:30:46 +02:00
parent d7e684ad91
commit 58b4bdb1e6
5 changed files with 242 additions and 56 deletions

View File

@@ -4,7 +4,6 @@
#include "devices/sbi/sbi.h"
#include "memory/memory.h"
#include "memory/mmu/mmu.h"
#include "vriscv.h"
#include <stdlib.h>
@@ -210,27 +209,27 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction)
{
case FUNC3_LB:
// Load Byte (8-bits)
cpu->regs.x[instruction->rd] = memory[mmu_translate(address)];
cpu->regs.x[instruction->rd] = mem_read8(address);
// Sign extend from 8 bits to 32 bits
cpu->regs.x[instruction->rd] |= (cpu->regs.x[instruction->rd] & 0x80 ? 0xFFFFFF00 : 0);
break;
case FUNC3_LH:
// Load Halfword (16-bits)
cpu->regs.x[instruction->rd] = *((uint16_t*) &memory[mmu_translate(address)]);
cpu->regs.x[instruction->rd] = mem_read16(address);
// Sign extend from 16 bits to 32 bits
cpu->regs.x[instruction->rd] |= (cpu->regs.x[instruction->rd] & 0x8000 ? 0xFFFF0000 : 0);
break;
case FUNC3_LW:
// Load Word (32-bits)
cpu->regs.x[instruction->rd] = *((uint32_t*) &memory[mmu_translate(address)]);
cpu->regs.x[instruction->rd] = mem_read32(address);
break;
case FUNC3_LBU:
// Load Byte Unsigned (8-bits)
cpu->regs.x[instruction->rd] = memory[mmu_translate(address)];
cpu->regs.x[instruction->rd] = mem_read8(address);
break;
case FUNC3_LHU:
// Load Halfword Unsigned (16-bits)
cpu->regs.x[instruction->rd] = *((uint16_t*) &memory[mmu_translate(address)]);
cpu->regs.x[instruction->rd] = mem_read16(address);
break;
default:
fprintf(stderr, "FATAL: Unknown func3 0x%x for load instruction, could not execute\n", instruction->func3);
@@ -250,15 +249,15 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction)
{
case FUNC3_SB:
// Store Byte (8-bits)
memory[mmu_translate(address)] = cpu->regs.x[instruction->rs2] & 0xFF;
mem_write8(address, cpu->regs.x[instruction->rs2] & 0xFF);
break;
case FUNC3_SH:
// Store Halfword (16-bits)
*((uint16_t*) &memory[mmu_translate(address)]) = cpu->regs.x[instruction->rs2] & 0xFFFF;
mem_write16(address, cpu->regs.x[instruction->rs2] & 0xFFFF);
break;
case FUNC3_SW:
// Store Word (32-bits)
*((uint32_t*) &memory[mmu_translate(address)]) = cpu->regs.x[instruction->rs2];
mem_write32(address, cpu->regs.x[instruction->rs2]);
break;
default:
fprintf(stderr, "FATAL: Unknown func3 0x%x for store instruction, could not execute\n", instruction->func3);
@@ -588,77 +587,76 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction)
// FUNC7 contains 2 flag bits in lower part ; ignore them, we look for func7_5
uint32_t address = cpu->regs.x[instruction->rs1];
uint32_t* ptr = ((uint32_t*) &memory[mmu_translate(address)]);
switch(instruction->func7 >> 2)
{
case FUNC75_LRW:
// Load-Reserved Word
cpu->regs.x[instruction->rd] = *ptr;
cpu->regs.x[instruction->rd] = mem_read32(address);
// TODO register reservation set that subsumes the bytes in word
fprintf(stderr, "LR.W\n");
break;
case FUNC75_SCW:
// Store-Conditional Word
// TODO succeed only if the reservation is still valid and the reservation set contains the bytes written
*ptr = cpu->regs.x[instruction->rs2];
mem_write32(address, cpu->regs.x[instruction->rs2]);
cpu->regs.x[instruction->rd] = 0; // TODO write 1 in rd on failure
fprintf(stderr, "SC.W\n");
break;
case FUNC75_AMOSWAPW:
// Atomic Memory Operation SWAP Word
cpu->regs.x[instruction->rd] = *ptr;
cpu->regs.x[instruction->rd] = mem_read32(address);
// Put in RS1 addr the value of RS2
*ptr = cpu->regs.x[instruction->rs2];
mem_write32(address, cpu->regs.x[instruction->rs2]);
// Put in RS2 the value of RS1 addr (which is in RD)
cpu->regs.x[instruction->rs2] = cpu->regs.x[instruction->rd];
break;
case FUNC75_AMOADDW:
// Atomic Memory Operation ADD Word
cpu->regs.x[instruction->rd] = *ptr;
cpu->regs.x[instruction->rd] = mem_read32(address);
// Add rs1 addr and value of rs2
*ptr = cpu->regs.x[instruction->rd] + cpu->regs.x[instruction->rs2];
mem_write32(address, cpu->regs.x[instruction->rd] + cpu->regs.x[instruction->rs2]);
break;
case FUNC75_AMOXORW:
// Atomic Memory Operation XOR Word
cpu->regs.x[instruction->rd] = *ptr;
cpu->regs.x[instruction->rd] = mem_read32(address);
// Xor rs1 addr and value of rs2
*ptr = cpu->regs.x[instruction->rd] ^ cpu->regs.x[instruction->rs2];
mem_write32(address, cpu->regs.x[instruction->rd] ^ cpu->regs.x[instruction->rs2]);
break;
case FUNC75_AMOANDW:
// Atomic Memory Operation AND Word
cpu->regs.x[instruction->rd] = *ptr;
cpu->regs.x[instruction->rd] = mem_read32(address);
// AND rs1 addr and value of rs2
*ptr = cpu->regs.x[instruction->rd] & cpu->regs.x[instruction->rs2];
mem_write32(address, cpu->regs.x[instruction->rd] & cpu->regs.x[instruction->rs2]);
break;
case FUNC75_AMOORW:
// Atomic Memory Operation OR Word
cpu->regs.x[instruction->rd] = *ptr;
cpu->regs.x[instruction->rd] = mem_read32(address);
// Or rs1 addr and value of rs2
*ptr = cpu->regs.x[instruction->rd] | cpu->regs.x[instruction->rs2];
mem_write32(address, cpu->regs.x[instruction->rd] | cpu->regs.x[instruction->rs2]);
break;
case FUNC75_AMOMINW:
// Atomic Memory Operation MIN Word
cpu->regs.x[instruction->rd] = *ptr;
cpu->regs.x[instruction->rd] = mem_read32(address);
// Min rs1 addr and value of rs2
*ptr = ((int32_t) cpu->regs.x[instruction->rd]) < ((int32_t) cpu->regs.x[instruction->rs2]) ? cpu->regs.x[instruction->rd] : cpu->regs.x[instruction->rs2];
mem_write32(address, ((int32_t) cpu->regs.x[instruction->rd]) < ((int32_t) cpu->regs.x[instruction->rs2]) ? cpu->regs.x[instruction->rd] : cpu->regs.x[instruction->rs2]);
break;
case FUNC75_AMOMAXW:
// Atomic Memory Operation MAX Word
cpu->regs.x[instruction->rd] = *ptr;
cpu->regs.x[instruction->rd] = mem_read32(address);
// Max rs1 addr and value of rs2
*ptr = ((int32_t) cpu->regs.x[instruction->rd]) > ((int32_t) cpu->regs.x[instruction->rs2]) ? cpu->regs.x[instruction->rd] : cpu->regs.x[instruction->rs2];
mem_write32(address, ((int32_t) cpu->regs.x[instruction->rd]) > ((int32_t) cpu->regs.x[instruction->rs2]) ? cpu->regs.x[instruction->rd] : cpu->regs.x[instruction->rs2]);
break;
case FUNC75_AMOMINUW:
// Atomic Memory Operation MIN Unsigned Word
cpu->regs.x[instruction->rd] = *ptr;
cpu->regs.x[instruction->rd] = mem_read32(address);
// Min rs1 addr and value of rs2
*ptr = cpu->regs.x[instruction->rd] < cpu->regs.x[instruction->rs2] ? cpu->regs.x[instruction->rd] : cpu->regs.x[instruction->rs2];
mem_write32(address, cpu->regs.x[instruction->rd] < cpu->regs.x[instruction->rs2] ? cpu->regs.x[instruction->rd] : cpu->regs.x[instruction->rs2]);
break;
case FUNC75_AMOMAXUW:
// Atomic Memory Operation MAX Unsigned Word
cpu->regs.x[instruction->rd] = *ptr;
cpu->regs.x[instruction->rd] = mem_read32(address);
// Max rs1 addr and value of rs2
*ptr = cpu->regs.x[instruction->rd] > cpu->regs.x[instruction->rs2] ? cpu->regs.x[instruction->rd] : cpu->regs.x[instruction->rs2];
mem_write32(address, cpu->regs.x[instruction->rd] > cpu->regs.x[instruction->rs2] ? cpu->regs.x[instruction->rd] : cpu->regs.x[instruction->rs2]);
break;
default:
fprintf(stderr, "FATAL: Unknown func7 0x%x for ATOMIC/0x2 instruction, could not execute\n", instruction->func7);
@@ -688,7 +686,7 @@ void cpu_loop(rv32_cpu_t* cpu)
while(!cpu->sim_ticks_left)
pthread_cond_wait(&cpu0->sim_condition, &cpu0_mutex);
pthread_mutex_lock(&memory_mutex);
// pthread_mutex_lock(&memory_mutex);
// Fetch
raw_instruction_t raw_instruction;
@@ -723,7 +721,7 @@ void cpu_loop(rv32_cpu_t* cpu)
cpu->sim_ticks_left--;
// Let go of cpu and memory mutex
pthread_mutex_unlock(&memory_mutex);
// pthread_mutex_unlock(&memory_mutex);
pthread_mutex_unlock(&cpu0_mutex);
}
}