blob: 614244026234bdd4882305c23fa1e0e4c8808531 [file]
#ifndef LEARNING_BRAIN_RESEARCH_MPACT_SIM_CHERI_RISCV_SIMPLE_UART_H_
#define LEARNING_BRAIN_RESEARCH_MPACT_SIM_CHERI_RISCV_SIMPLE_UART_H_
#include <cstdint>
#include <ostream>
#include "mpact/sim/generic/arch_state.h"
#include "mpact/sim/generic/data_buffer.h"
#include "mpact/sim/generic/instruction.h"
#include "mpact/sim/generic/ref_count.h"
#include "mpact/sim/util/memory/memory_interface.h"
// This file declares the class to implement a very trivial uart with only
// output capabilities for now. The following memory mapped registers are
// defined:
//
// Offset: Dlab: Semantics:
// 0x0000 1 Divisor latch low byte.
// 0x0000 0 TX(write)/RX(read) buffer.
// 0x0004 1 Divisor latch high byte.
// 0x0004 0 Interrupt enable register.
// 0x0008 x Interrupt identification register.
// 0x000c x Line control register.
// 0x0010 x Modem control register.
// 0x0014 x Line status register.
// 0x0018 x Modem status register.
// 0x001c x Scratch register.
namespace mpact::sim::util {
using ::mpact::sim::generic::ArchState;
using ::mpact::sim::generic::DataBuffer;
using ::mpact::sim::generic::Instruction;
using ::mpact::sim::generic::ReferenceCount;
using ::mpact::sim::util::MemoryInterface;
class SimpleUart : public MemoryInterface {
public:
// Constructors.
// Instantiate the uart and set the output to std::cerr.
explicit SimpleUart(ArchState *state);
// Instantiate the uart and set the output to the given ostream.
SimpleUart(ArchState *state, std::ostream &output);
// Memory interface methods used to write to the memory mapped registers.
void Load(uint64_t address, DataBuffer *db, Instruction *inst,
ReferenceCount *context) override;
void Load(DataBuffer *address_db, DataBuffer *mask_db, int el_size,
DataBuffer *db, Instruction *inst,
ReferenceCount *context) override;
void Store(uint64_t address, DataBuffer *db) override;
void Store(DataBuffer *address, DataBuffer *mask_db, int el_size,
DataBuffer *db) override;
private:
// Helper methods.
uint32_t Read(uint32_t offset);
void Write(uint32_t offset, uint32_t value);
// The dlab_ bit of the line control register. The dlab bit changes the
// register map for offsets 0x0 and 0x4 when set.
bool dlab_ = false;
// Selected uart registers.
uint32_t line_control_reg_ = 0;
uint32_t divisor_high_byte_ = 0;
uint32_t divisor_low_byte_ = 0;
uint32_t interrupt_enable_ = 0;
uint32_t scratch_;
std::ostream *output_;
};
} // namespace mpact::sim::util
#endif // LEARNING_BRAIN_RESEARCH_MPACT_SIM_CHERI_RISCV_SIMPLE_UART_H_