blob: 3cff450c9b6b10c16ecc4d284ef2a26d500c7401 [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_