Use an output iterator for the lucore stdout sink
This commit is contained in:
parent
58ee03c249
commit
6ebebae770
|
@ -1,3 +1,6 @@
|
||||||
|
#include <bits/iterator_concepts.h>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <lucore/Logger.hpp>
|
#include <lucore/Logger.hpp>
|
||||||
|
|
||||||
|
@ -35,11 +38,31 @@ namespace lucore {
|
||||||
}
|
}
|
||||||
|
|
||||||
void StdoutSink::OutputMessage(const Logger::MessageData& data) {
|
void StdoutSink::OutputMessage(const Logger::MessageData& data) {
|
||||||
// This is very nasty, but required until more standard libraries support the C++23 <print>
|
// This is kinda iffy, but required until more standard libraries support the C++23 <print>
|
||||||
// header.
|
// header.
|
||||||
std::puts(std::format("[Lucore/{}] [{}] {}", Logger::SeverityToString(data.severity),
|
struct FileOutIterator {
|
||||||
data.time, std::vformat(data.format, data.args))
|
using iterator_category = std::output_iterator_tag;
|
||||||
.c_str());
|
using value_type = void;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = void;
|
||||||
|
using reference = void;
|
||||||
|
|
||||||
|
FileOutIterator(std::FILE* file) : file(file) {}
|
||||||
|
FileOutIterator& operator*() { return *this; }
|
||||||
|
FileOutIterator& operator++() { return *this; }
|
||||||
|
FileOutIterator& operator++(int) { return *this; }
|
||||||
|
|
||||||
|
FileOutIterator& operator=(const char& val) {
|
||||||
|
fputc(val, file);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::FILE* file;
|
||||||
|
};
|
||||||
|
std::format_to(FileOutIterator(data.severity < Logger::MessageSeverity::Error ? stdout : stderr), "[Lucore/{}] [{}] {}\n",
|
||||||
|
Logger::SeverityToString(data.severity), data.time,
|
||||||
|
std::vformat(data.format, data.args));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoggerAttachStdout() {
|
void LoggerAttachStdout() {
|
||||||
|
|
|
@ -29,12 +29,8 @@ namespace riscv {
|
||||||
/// the ability to... well, clock!
|
/// the ability to... well, clock!
|
||||||
virtual void Clock() {}
|
virtual void Clock() {}
|
||||||
|
|
||||||
// TODO(feat): Need to implement ability to generate interrupts
|
// TODO(feat): default implementations of Peek* and Poke* should exist
|
||||||
// from devices. This needs to be implemented to facilitate the
|
// and trap the CPU (similarly to what happens if a unmapped bus read occurs).
|
||||||
// implementation of the timer device as an actual Device implmentation
|
|
||||||
// instead of poorly hard-coding it into the CPU core logic.
|
|
||||||
//
|
|
||||||
// Also, default implementations of Peek* and Poke* should trap.
|
|
||||||
|
|
||||||
|
|
||||||
// Peek() -> reads a value from this device.
|
// Peek() -> reads a value from this device.
|
||||||
|
@ -49,6 +45,7 @@ namespace riscv {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Bus(CPU* cpu);
|
||||||
~Bus();
|
~Bus();
|
||||||
|
|
||||||
/// Attach a device to the bus.
|
/// Attach a device to the bus.
|
||||||
|
@ -66,7 +63,6 @@ namespace riscv {
|
||||||
/// Clock all clocked devices.
|
/// Clock all clocked devices.
|
||||||
void Clock();
|
void Clock();
|
||||||
|
|
||||||
//
|
|
||||||
u8 PeekByte(AddressT address);
|
u8 PeekByte(AddressT address);
|
||||||
u16 PeekShort(AddressT address);
|
u16 PeekShort(AddressT address);
|
||||||
u32 PeekWord(AddressT address);
|
u32 PeekWord(AddressT address);
|
||||||
|
|
|
@ -1,11 +1,43 @@
|
||||||
|
#include <riscv/Bus.hpp>
|
||||||
|
#include <riscv/Types.hpp>
|
||||||
|
|
||||||
namespace riscv {
|
namespace riscv {
|
||||||
|
|
||||||
/** The CPU core. There will be one of these in a [System]. */
|
/** The CPU core. */
|
||||||
struct CPU {
|
struct CPU {
|
||||||
|
struct State {
|
||||||
|
u32 gpr[32];
|
||||||
|
u32 pc;
|
||||||
|
u32 mstatus;
|
||||||
|
u32 cyclel;
|
||||||
|
u32 cycleh;
|
||||||
|
|
||||||
|
u32 timerl;
|
||||||
|
u32 timerh;
|
||||||
|
u32 timermatchl;
|
||||||
|
u32 timermatchh;
|
||||||
|
|
||||||
|
u32 mscratch;
|
||||||
|
u32 mtvec;
|
||||||
|
u32 mie;
|
||||||
|
u32 mip;
|
||||||
|
|
||||||
|
u32 mepc;
|
||||||
|
u32 mtval;
|
||||||
|
u32 mcause;
|
||||||
|
|
||||||
|
// Note: only a few bits are used. (Machine = 3, User = 0)
|
||||||
|
// Bits 0..1 = privilege.
|
||||||
|
// Bit 2 = WFI (Wait for interrupt)
|
||||||
|
// Bit 3+ = Load/Store reservation LSBs.
|
||||||
|
u32 extraflags;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
State& GetState() { return state; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
State state;
|
||||||
|
Bus bus;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace riscv
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
|
|
||||||
namespace riscv {
|
namespace riscv {
|
||||||
|
|
||||||
|
Bus::Bus(CPU* cpu)
|
||||||
|
: attachedCpu(cpu) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Bus::~Bus() {
|
Bus::~Bus() {
|
||||||
// Free all devices
|
// Free all devices
|
||||||
for(auto& pair : mapped_devices)
|
for(auto& pair : mapped_devices)
|
||||||
|
|
Loading…
Reference in New Issue