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)
 | 
						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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user