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