riscv: misc code cleanup (now I can actually focus on stuff!)
This commit is contained in:
parent
878990a921
commit
7af85f5601
|
@ -23,7 +23,7 @@ namespace riscv {
|
||||||
constexpr void Reset() {
|
constexpr void Reset() {
|
||||||
// Initalize some state. We're cool like that :)
|
// Initalize some state. We're cool like that :)
|
||||||
pc = 0x80000000;
|
pc = 0x80000000;
|
||||||
gpr[10] = 0x0; // HART id
|
gpr[Gpr::A0] = 0x0; // HART id
|
||||||
extraflags |= 3; // Start in Machine mode
|
extraflags |= 3; // Start in Machine mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +57,7 @@ namespace riscv {
|
||||||
/// Set by [CPU::Trap] for the trap code.
|
/// Set by [CPU::Trap] for the trap code.
|
||||||
u32 trapCode { 0 };
|
u32 trapCode { 0 };
|
||||||
|
|
||||||
u32 Step(u32 instCount);
|
void Step(u32 instCount);
|
||||||
|
|
||||||
// todo: counters for chrono/inst count.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace riscv
|
} // namespace riscv
|
||||||
|
|
|
@ -1,17 +1,12 @@
|
||||||
//! Portions of this code are copyright 2022 Charles Lohr (CNLohr).
|
//! Portions of this code are copyright 2022 Charles Lohr (CNLohr),
|
||||||
|
//! from [mini-rv32ima](https://github.com/cnlohr/mini-rv32ima).
|
||||||
|
|
||||||
#include <riscv/Bus.hpp>
|
#include <riscv/Bus.hpp>
|
||||||
#include <riscv/CPU.hpp>
|
#include <riscv/CPU.hpp>
|
||||||
|
|
||||||
#include <lucore/Logger.hpp>
|
|
||||||
|
|
||||||
namespace riscv {
|
namespace riscv {
|
||||||
|
|
||||||
// Not needed
|
|
||||||
//constexpr static Address RamImageOffset = 0x80000000;
|
|
||||||
|
|
||||||
void CPU::Clock() {
|
void CPU::Clock() {
|
||||||
// do the thing
|
|
||||||
Step(1024);
|
Step(1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,14 +32,14 @@ namespace riscv {
|
||||||
// trapCode = 0x80000007;
|
// trapCode = 0x80000007;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CPU::Step(u32 instCount) {
|
void CPU::Step(u32 instCount) {
|
||||||
auto interruptsInFlight = [&]() {
|
auto interruptsInFlight = [&]() {
|
||||||
return (mip & (1 << 7) /*|| mip & (1 << 11)*/) && (mie & (1 << 7) /*|| mie & (1 << 11)*/) && (mstatus & 0x8 /*mie*/);
|
return (mip & (1 << 7) /*|| mip & (1 << 11)*/) && (mie & (1 << 7) /*|| mie & (1 << 11)*/) && (mstatus & 0x8 /*mie*/);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Don't run if waiting for an interrupt
|
// Don't run if waiting for an interrupt
|
||||||
if(extraflags & 4)
|
if(extraflags & 4)
|
||||||
return 1;
|
return;
|
||||||
|
|
||||||
u32 rdid = 0;
|
u32 rdid = 0;
|
||||||
u32 rval = 0;
|
u32 rval = 0;
|
||||||
|
@ -57,10 +52,7 @@ namespace riscv {
|
||||||
rdid = 0; // force it to gpr 0 (zero), which is not writable
|
rdid = 0; // force it to gpr 0 (zero), which is not writable
|
||||||
cycle++;
|
cycle++;
|
||||||
|
|
||||||
//lucore::LogInfo("[CPU] pc @ 0x{:08x}", pc);
|
|
||||||
|
|
||||||
if((pc & 3)) {
|
if((pc & 3)) {
|
||||||
lucore::LogWarning("[CPU] misaligned jump target.. 0x{:08x}", pc);
|
|
||||||
Trap(TrapCode::InstructionAddressMisaligned);
|
Trap(TrapCode::InstructionAddressMisaligned);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -75,8 +67,6 @@ namespace riscv {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//lucore::LogInfo("[CPU] fetch 0x{:08x} 0x{:08x}", pc, ir);
|
|
||||||
|
|
||||||
rdid = (ir >> 7) & 0x1f;
|
rdid = (ir >> 7) & 0x1f;
|
||||||
|
|
||||||
// Do the thing!
|
// Do the thing!
|
||||||
|
@ -96,7 +86,6 @@ namespace riscv {
|
||||||
if(reladdy & 0x00100000)
|
if(reladdy & 0x00100000)
|
||||||
reladdy |= 0xffe00000;
|
reladdy |= 0xffe00000;
|
||||||
rval = pc + 4;
|
rval = pc + 4;
|
||||||
//lucore::LogInfo("j/al 0x{:08x}", pc + reladdy);
|
|
||||||
pc = pc + reladdy - 4;
|
pc = pc + reladdy - 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +95,6 @@ namespace riscv {
|
||||||
i32 imm_se = imm | ((imm & 0x800) ? 0xfffff000 : 0);
|
i32 imm_se = imm | ((imm & 0x800) ? 0xfffff000 : 0);
|
||||||
rval = pc + 4;
|
rval = pc + 4;
|
||||||
pc = ((gpr[((ir >> 15) & 0x1f)] + imm_se) & ~1) - 4;
|
pc = ((gpr[((ir >> 15) & 0x1f)] + imm_se) & ~1) - 4;
|
||||||
//lucore::LogInfo("jalr {}, 0x{:08x}", RegName(static_cast<Gpr>(((ir >> 15) & 0x1f))), ((gpr[((ir >> 15) & 0x1f)] + imm_se) & ~1) - 4);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,12 +128,12 @@ namespace riscv {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: // BLTU
|
case 6: // BLTU
|
||||||
if((uint32_t)rs1 < (uint32_t)rs2)
|
if((u32)rs1 < (u32)rs2)
|
||||||
pc = immm4;
|
pc = immm4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7: // BGEU
|
case 7: // BGEU
|
||||||
if((uint32_t)rs1 >= (uint32_t)rs2)
|
if((u32)rs1 >= (u32)rs2)
|
||||||
pc = immm4;
|
pc = immm4;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -423,7 +411,7 @@ namespace riscv {
|
||||||
mstatus |= 8; // Enable interrupts
|
mstatus |= 8; // Enable interrupts
|
||||||
extraflags |= 4; // Set inernal WFI bit
|
extraflags |= 4; // Set inernal WFI bit
|
||||||
this->pc = pc + 4;
|
this->pc = pc + 4;
|
||||||
return 1;
|
return;
|
||||||
} else if(((csrno & 0xff) == 0x02)) { // MRET
|
} else if(((csrno & 0xff) == 0x02)) { // MRET
|
||||||
// https://raw.githubusercontent.com/riscv/virtual-memory/main/specs/663-Svpbmt.pdf
|
// https://raw.githubusercontent.com/riscv/virtual-memory/main/specs/663-Svpbmt.pdf
|
||||||
// Table 7.6. MRET then in mstatus/mstatush sets MPV=0, MPP=0,
|
// Table 7.6. MRET then in mstatus/mstatush sets MPV=0, MPP=0,
|
||||||
|
@ -461,12 +449,6 @@ namespace riscv {
|
||||||
u32 rs2 = gpr[(ir >> 20) & 0x1f];
|
u32 rs2 = gpr[(ir >> 20) & 0x1f];
|
||||||
u32 irmid = (ir >> 27) & 0x1f;
|
u32 irmid = (ir >> 27) & 0x1f;
|
||||||
|
|
||||||
// rs1 -= MINIRV32_RAM_IMAGE_OFFSET;
|
|
||||||
|
|
||||||
//rs1 -= RamImageOffset;
|
|
||||||
|
|
||||||
// We don't implement load/store from UART or CLNT with RV32A here.
|
|
||||||
|
|
||||||
rval = bus->PeekWord(rs1);
|
rval = bus->PeekWord(rs1);
|
||||||
if(trapped) {
|
if(trapped) {
|
||||||
rval = rs1; // + RamImageOffset;
|
rval = rs1; // + RamImageOffset;
|
||||||
|
@ -528,11 +510,8 @@ namespace riscv {
|
||||||
if(trapped)
|
if(trapped)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(rdid) {
|
if(rdid)
|
||||||
//lucore::LogInfo("writing register {} -> 0x{:08x}", RegName(static_cast<Gpr>(rdid)), rval);
|
|
||||||
gpr[rdid] = rval;
|
gpr[rdid] = rval;
|
||||||
}
|
|
||||||
|
|
||||||
pc += 4;
|
pc += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -550,13 +529,11 @@ namespace riscv {
|
||||||
else
|
else
|
||||||
mtval = pc;
|
mtval = pc;
|
||||||
}
|
}
|
||||||
mepc = pc; // TRICKY: The kernel advances mepc automatically.
|
mepc = pc; // Interrupt handler will advance mepc
|
||||||
// CSR( mstatus ) & 8 = MIE, & 0x80 = MPIE
|
|
||||||
// On an interrupt, the system moves current MIE into MPIE
|
|
||||||
mstatus = (mstatus & 0x08) << 4 | ((extraflags)&3) << 11;
|
mstatus = (mstatus & 0x08) << 4 | ((extraflags)&3) << 11;
|
||||||
pc = (mtvec - 4);
|
pc = (mtvec - 4);
|
||||||
|
|
||||||
// If trapping, always enter machine mode.
|
// Always enter machine mode when trapping.
|
||||||
extraflags |= 3;
|
extraflags |= 3;
|
||||||
|
|
||||||
// Reset trap flags
|
// Reset trap flags
|
||||||
|
@ -568,8 +545,6 @@ namespace riscv {
|
||||||
if(cyclel > cycle)
|
if(cyclel > cycle)
|
||||||
cycleh++;
|
cycleh++;
|
||||||
cyclel = cycle;
|
cyclel = cycle;
|
||||||
pc = pc;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace riscv
|
} // namespace riscv
|
||||||
|
|
|
@ -5,18 +5,21 @@ namespace riscv {
|
||||||
System* System::Create(Address ramSize) {
|
System* System::Create(Address ramSize) {
|
||||||
auto* system = new System;
|
auto* system = new System;
|
||||||
|
|
||||||
|
// create all the devices we require.
|
||||||
system->bus = new Bus();
|
system->bus = new Bus();
|
||||||
system->cpu = new CPU();
|
system->cpu = new CPU();
|
||||||
system->ram = new devices::RamDevice(0x80000000, ramSize);
|
system->ram = new devices::RamDevice(0x80000000, ramSize);
|
||||||
system->clnt = new devices::ClntDevice();
|
system->clnt = new devices::ClntDevice();
|
||||||
system->syscon = new devices::SysconDevice(system);
|
system->syscon = new devices::SysconDevice(system);
|
||||||
|
|
||||||
|
// techinically this is done on construction but lets be hard about it
|
||||||
system->cpu->Reset();
|
system->cpu->Reset();
|
||||||
|
|
||||||
system->bus->AttachDevice(system->cpu);
|
// attach everything into the bus
|
||||||
system->bus->AttachDevice(system->clnt);
|
if(!system->bus->AttachDevice(system->cpu)) return nullptr;
|
||||||
system->bus->AttachDevice(system->syscon);
|
if(!system->bus->AttachDevice(system->clnt)) return nullptr;
|
||||||
system->bus->AttachDevice(system->ram);
|
if(!system->bus->AttachDevice(system->syscon)) return nullptr;
|
||||||
|
if(!system->bus->AttachDevice(system->ram)) return nullptr;
|
||||||
|
|
||||||
return system;
|
return system;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
// 128 KB of ram. Won't be enough to boot linux but should be good enough to test most baremetal apps
|
// 128 KB of ram. Won't be enough to boot linux but should be good enough to test most baremetal apps
|
||||||
auto system = riscv::System::Create(128 * 1024);
|
auto system = riscv::System::Create(128 * 1024);
|
||||||
|
LUCORE_CHECK(system, "could not create system for some reason.");
|
||||||
|
|
||||||
// Attach our UART device
|
// Attach our UART device
|
||||||
system->bus->AttachDevice(new SimpleUartDevice);
|
system->bus->AttachDevice(new SimpleUartDevice);
|
||||||
|
|
Loading…
Reference in New Issue