Added memory access type for mmu
This commit is contained in:
		@@ -682,7 +682,7 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu)
 | 
			
		||||
{
 | 
			
		||||
	while(1)
 | 
			
		||||
	{
 | 
			
		||||
		// Aquire CPU and memory mutex
 | 
			
		||||
		// Aquire CPU mutex
 | 
			
		||||
		pthread_mutex_lock(&cpu0_mutex);
 | 
			
		||||
 | 
			
		||||
		// 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)
 | 
			
		||||
			pthread_cond_wait(&cpu0->sim_condition, &cpu0_mutex);
 | 
			
		||||
 | 
			
		||||
		// pthread_mutex_lock(&memory_mutex);
 | 
			
		||||
 | 
			
		||||
		// Fetch
 | 
			
		||||
		raw_instruction_t raw_instruction;
 | 
			
		||||
		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");
 | 
			
		||||
			exit(EXIT_FAILURE);
 | 
			
		||||
		}
 | 
			
		||||
		raw_instruction.data = mem_read32(cpu->pc);
 | 
			
		||||
		raw_instruction.data = mem_fetch(cpu->pc);
 | 
			
		||||
 | 
			
		||||
		// Decode
 | 
			
		||||
		instruction_t instruction;
 | 
			
		||||
@@ -726,8 +724,7 @@ __attribute__((noreturn)) void cpu_loop(rv32_cpu_t* cpu)
 | 
			
		||||
		if(cpu->sim_ticks_left != (-1))
 | 
			
		||||
			cpu->sim_ticks_left--;
 | 
			
		||||
 | 
			
		||||
		// Let go of cpu and memory mutex
 | 
			
		||||
		// pthread_mutex_unlock(&memory_mutex);
 | 
			
		||||
		// Let go of cpu 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)
 | 
			
		||||
{
 | 
			
		||||
	address = mmu_resolve(cpu0, address);
 | 
			
		||||
	address = mmu_resolve(cpu0, WRITE, address);
 | 
			
		||||
 | 
			
		||||
	// Look wether we are on an MMIO region
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	address = mmu_resolve(cpu0, address);
 | 
			
		||||
	address = mmu_resolve(cpu0, WRITE, address);
 | 
			
		||||
 | 
			
		||||
	// Look wether we are on an MMIO region
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	address = mmu_resolve(cpu0, address);
 | 
			
		||||
	address = mmu_resolve(cpu0, WRITE, address);
 | 
			
		||||
 | 
			
		||||
	// Look wether we are on an MMIO region
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	address = mmu_resolve(cpu0, address);
 | 
			
		||||
	address = mmu_resolve(cpu0, READ, address);
 | 
			
		||||
 | 
			
		||||
    // Look wether we are on an MMIO region
 | 
			
		||||
	struct MMIO_ENTRY* io = mmio;
 | 
			
		||||
@@ -164,7 +164,7 @@ uint8_t mem_read8(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
 | 
			
		||||
	struct MMIO_ENTRY* io = mmio;
 | 
			
		||||
@@ -195,7 +195,7 @@ uint16_t mem_read16(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
 | 
			
		||||
	struct MMIO_ENTRY* io = mmio;
 | 
			
		||||
@@ -223,3 +223,26 @@ uint32_t mem_read32(uint32_t address)
 | 
			
		||||
	pthread_mutex_unlock(&memory_mutex);
 | 
			
		||||
    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);
 | 
			
		||||
uint16_t mem_read16(uint32_t address);
 | 
			
		||||
uint32_t mem_read32(uint32_t address);
 | 
			
		||||
uint32_t mem_fetch(uint32_t address);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,24 @@ extern uint8_t* memory;
 | 
			
		||||
#define VADDR_VPN_0 (0x003FF000)
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
@@ -64,8 +81,7 @@ uint32_t mmu_resolve(rv32_cpu_t* cpu, uint32_t vaddr)
 | 
			
		||||
	if(!(pte & PTE_V))
 | 
			
		||||
	{
 | 
			
		||||
		// Invalid PTE
 | 
			
		||||
		// TODO : Add a MEMORY_ACCESS_TYPE
 | 
			
		||||
		exception_trigger(cpu, SCAUSE_INSTRUCTION_PAGE_FAULT);
 | 
			
		||||
		exception_trigger(cpu, mmu_scause_from_access(access_type));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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))
 | 
			
		||||
	{
 | 
			
		||||
		// 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
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,13 @@
 | 
			
		||||
#include <stdint.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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user