Added memory access type for mmu
This commit is contained in:
parent
5bb973e8da
commit
dcdebcd8e4
@ -682,7 +682,7 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu)
|
|||||||
{
|
{
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
// Aquire CPU and memory mutex
|
// Aquire CPU mutex
|
||||||
pthread_mutex_lock(&cpu0_mutex);
|
pthread_mutex_lock(&cpu0_mutex);
|
||||||
|
|
||||||
// No simulation ticks left : wakeup people waiting on sim end
|
// No simulation ticks left : wakeup people waiting on sim end
|
||||||
@ -692,8 +692,6 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu)
|
|||||||
while(!cpu->sim_ticks_left)
|
while(!cpu->sim_ticks_left)
|
||||||
pthread_cond_wait(&cpu0->sim_condition, &cpu0_mutex);
|
pthread_cond_wait(&cpu0->sim_condition, &cpu0_mutex);
|
||||||
|
|
||||||
// pthread_mutex_lock(&memory_mutex);
|
|
||||||
|
|
||||||
// Fetch
|
// Fetch
|
||||||
raw_instruction_t raw_instruction;
|
raw_instruction_t raw_instruction;
|
||||||
if(cpu->pc > memory_size - 4)
|
if(cpu->pc > memory_size - 4)
|
||||||
@ -701,7 +699,7 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu)
|
|||||||
fprintf(stderr, "Error: instruction fetch: pc is out of addressable memory\n");
|
fprintf(stderr, "Error: instruction fetch: pc is out of addressable memory\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
raw_instruction.data = mem_read32(cpu->pc);
|
raw_instruction.data = mem_fetch(cpu->pc);
|
||||||
|
|
||||||
// Decode
|
// Decode
|
||||||
instruction_t instruction;
|
instruction_t instruction;
|
||||||
@ -726,8 +724,7 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu)
|
|||||||
if(cpu->sim_ticks_left != (-1))
|
if(cpu->sim_ticks_left != (-1))
|
||||||
cpu->sim_ticks_left--;
|
cpu->sim_ticks_left--;
|
||||||
|
|
||||||
// Let go of cpu and memory mutex
|
// Let go of cpu mutex
|
||||||
// pthread_mutex_unlock(&memory_mutex);
|
|
||||||
pthread_mutex_unlock(&cpu0_mutex);
|
pthread_mutex_unlock(&cpu0_mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ void mem_register_mmio(uint32_t address, uint32_t reg_size, uint32_t reg_count,
|
|||||||
|
|
||||||
void mem_write8(uint32_t address, uint8_t value)
|
void mem_write8(uint32_t address, uint8_t value)
|
||||||
{
|
{
|
||||||
address = mmu_resolve(cpu0, address);
|
address = mmu_resolve(cpu0, WRITE, address);
|
||||||
|
|
||||||
// Look wether we are on an MMIO region
|
// Look wether we are on an MMIO region
|
||||||
struct MMIO_ENTRY* io = mmio;
|
struct MMIO_ENTRY* io = mmio;
|
||||||
@ -71,7 +71,7 @@ void mem_write8(uint32_t address, uint8_t value)
|
|||||||
|
|
||||||
void mem_write16(uint32_t address, uint16_t value)
|
void mem_write16(uint32_t address, uint16_t value)
|
||||||
{
|
{
|
||||||
address = mmu_resolve(cpu0, address);
|
address = mmu_resolve(cpu0, WRITE, address);
|
||||||
|
|
||||||
// Look wether we are on an MMIO region
|
// Look wether we are on an MMIO region
|
||||||
struct MMIO_ENTRY* io = mmio;
|
struct MMIO_ENTRY* io = mmio;
|
||||||
@ -102,7 +102,7 @@ void mem_write16(uint32_t address, uint16_t value)
|
|||||||
|
|
||||||
void mem_write32(uint32_t address, uint32_t value)
|
void mem_write32(uint32_t address, uint32_t value)
|
||||||
{
|
{
|
||||||
address = mmu_resolve(cpu0, address);
|
address = mmu_resolve(cpu0, WRITE, address);
|
||||||
|
|
||||||
// Look wether we are on an MMIO region
|
// Look wether we are on an MMIO region
|
||||||
struct MMIO_ENTRY* io = mmio;
|
struct MMIO_ENTRY* io = mmio;
|
||||||
@ -133,7 +133,7 @@ void mem_write32(uint32_t address, uint32_t value)
|
|||||||
|
|
||||||
uint8_t mem_read8(uint32_t address)
|
uint8_t mem_read8(uint32_t address)
|
||||||
{
|
{
|
||||||
address = mmu_resolve(cpu0, address);
|
address = mmu_resolve(cpu0, READ, address);
|
||||||
|
|
||||||
// Look wether we are on an MMIO region
|
// Look wether we are on an MMIO region
|
||||||
struct MMIO_ENTRY* io = mmio;
|
struct MMIO_ENTRY* io = mmio;
|
||||||
@ -164,7 +164,7 @@ uint8_t mem_read8(uint32_t address)
|
|||||||
|
|
||||||
uint16_t mem_read16(uint32_t address)
|
uint16_t mem_read16(uint32_t address)
|
||||||
{
|
{
|
||||||
address = mmu_resolve(cpu0, address);
|
address = mmu_resolve(cpu0, READ, address);
|
||||||
|
|
||||||
// Look wether we are on an MMIO region
|
// Look wether we are on an MMIO region
|
||||||
struct MMIO_ENTRY* io = mmio;
|
struct MMIO_ENTRY* io = mmio;
|
||||||
@ -195,7 +195,7 @@ uint16_t mem_read16(uint32_t address)
|
|||||||
|
|
||||||
uint32_t mem_read32(uint32_t address)
|
uint32_t mem_read32(uint32_t address)
|
||||||
{
|
{
|
||||||
address = mmu_resolve(cpu0, address);
|
address = mmu_resolve(cpu0, READ, address);
|
||||||
|
|
||||||
// Look wether we are on an MMIO region
|
// Look wether we are on an MMIO region
|
||||||
struct MMIO_ENTRY* io = mmio;
|
struct MMIO_ENTRY* io = mmio;
|
||||||
@ -223,3 +223,26 @@ uint32_t mem_read32(uint32_t address)
|
|||||||
pthread_mutex_unlock(&memory_mutex);
|
pthread_mutex_unlock(&memory_mutex);
|
||||||
return tr;
|
return tr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t mem_fetch(uint32_t address)
|
||||||
|
{
|
||||||
|
address = mmu_resolve(cpu0, INSTRUCTION_FETCH, address);
|
||||||
|
|
||||||
|
// Look wether we are on an MMIO region
|
||||||
|
struct MMIO_ENTRY* io = mmio;
|
||||||
|
while(io)
|
||||||
|
{
|
||||||
|
if(MMIO_INSIDE(io, address))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "MEMORY: Trying to fetch an instruction inside an MMIO region !\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
io = io->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proceed with memory read
|
||||||
|
pthread_mutex_lock(&memory_mutex);
|
||||||
|
uint32_t tr = *((uint32_t*) &memory[address]);
|
||||||
|
pthread_mutex_unlock(&memory_mutex);
|
||||||
|
return tr;
|
||||||
|
}
|
||||||
|
@ -14,5 +14,6 @@ void mem_write32(uint32_t address, uint32_t value);
|
|||||||
uint8_t mem_read8(uint32_t address);
|
uint8_t mem_read8(uint32_t address);
|
||||||
uint16_t mem_read16(uint32_t address);
|
uint16_t mem_read16(uint32_t address);
|
||||||
uint32_t mem_read32(uint32_t address);
|
uint32_t mem_read32(uint32_t address);
|
||||||
|
uint32_t mem_fetch(uint32_t address);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,7 +44,24 @@ extern uint8_t* memory;
|
|||||||
#define VADDR_VPN_0 (0x003FF000)
|
#define VADDR_VPN_0 (0x003FF000)
|
||||||
#define VADDR_PAGE_OFFSET (0x00000FFF)
|
#define VADDR_PAGE_OFFSET (0x00000FFF)
|
||||||
|
|
||||||
uint32_t mmu_resolve(rv32_cpu_t* cpu, uint32_t vaddr)
|
uint32_t mmu_scause_from_access(memory_access_type_t access_type)
|
||||||
|
{
|
||||||
|
switch(access_type)
|
||||||
|
{
|
||||||
|
case READ:
|
||||||
|
return SCAUSE_LOAD_PAGE_FAULT;
|
||||||
|
case WRITE:
|
||||||
|
return SCAUSE_STORE_AMO_PAGE_FAULT;
|
||||||
|
case INSTRUCTION_FETCH:
|
||||||
|
return SCAUSE_INSTRUCTION_PAGE_FAULT;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "mmu_scause_from_access: invalid parameter\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t mmu_resolve(rv32_cpu_t* cpu, memory_access_type_t access_type, uint32_t vaddr)
|
||||||
{
|
{
|
||||||
// TODO: Make sure we are in S-mode or U-mode
|
// TODO: Make sure we are in S-mode or U-mode
|
||||||
|
|
||||||
@ -64,8 +81,7 @@ uint32_t mmu_resolve(rv32_cpu_t* cpu, uint32_t vaddr)
|
|||||||
if(!(pte & PTE_V))
|
if(!(pte & PTE_V))
|
||||||
{
|
{
|
||||||
// Invalid PTE
|
// Invalid PTE
|
||||||
// TODO : Add a MEMORY_ACCESS_TYPE
|
exception_trigger(cpu, mmu_scause_from_access(access_type));
|
||||||
exception_trigger(cpu, SCAUSE_INSTRUCTION_PAGE_FAULT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if((pte & PTE_R) || (pte & PTE_W) || (pte & PTE_X))
|
if((pte & PTE_R) || (pte & PTE_W) || (pte & PTE_X))
|
||||||
@ -93,7 +109,7 @@ uint32_t mmu_resolve(rv32_cpu_t* cpu, uint32_t vaddr)
|
|||||||
if(!(pte & PTE_V))
|
if(!(pte & PTE_V))
|
||||||
{
|
{
|
||||||
// Invalid PTE
|
// Invalid PTE
|
||||||
exception_trigger(cpu, SCAUSE_INSTRUCTION_PAGE_FAULT);
|
exception_trigger(cpu, mmu_scause_from_access(access_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This must be a leaf PTE, as Sv32 only supports 2-level mappings
|
// This must be a leaf PTE, as Sv32 only supports 2-level mappings
|
||||||
|
@ -4,6 +4,13 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "cpu/rv32cpu.h"
|
#include "cpu/rv32cpu.h"
|
||||||
|
|
||||||
uint32_t mmu_resolve(rv32_cpu_t* cpu, uint32_t vaddr);
|
typedef enum MEMORY_ACCESS_TYPE
|
||||||
|
{
|
||||||
|
READ,
|
||||||
|
WRITE,
|
||||||
|
INSTRUCTION_FETCH
|
||||||
|
} memory_access_type_t;
|
||||||
|
|
||||||
|
uint32_t mmu_resolve(rv32_cpu_t* cpu, memory_access_type_t access_type, uint32_t vaddr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user