Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extend Memory backend to dealing with various needs #147

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/gui/ui/hexlineedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ HexLineEdit::HexLineEdit(
set_value(0);
}

void HexLineEdit::set_value(uint32_t value) {
void HexLineEdit::set_value(uint64_t value) {
QString s, t = "";
last_set = value;
s = QString::number(value, base);
Expand All @@ -60,8 +60,8 @@ void HexLineEdit::set_value(uint32_t value) {

void HexLineEdit::on_edit_finished() {
bool ok;
uint32_t val;
val = text().toULong(&ok, 16);
uint64_t val;
val = text().toULongLong(&ok, 16);
if (!ok) {
set_value(last_set);
return;
Expand Down
4 changes: 2 additions & 2 deletions src/gui/ui/hexlineedit.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ class HexLineEdit : public QLineEdit {
const QString &prefix = "0x");

public slots:
void set_value(uint32_t value);
void set_value(uint64_t value);

signals:
void value_edit_finished(uint32_t value);
void value_edit_finished(uint64_t value);

private slots:
void on_edit_finished();
Expand Down
4 changes: 2 additions & 2 deletions src/gui/windows/memory/memorydock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : Super(parent) {
memory_content->verticalHeader()->hide();
// memory_content->setHorizontalHeader(memory_model->);

auto *go_edit = new HexLineEdit(nullptr, 8, 16, "0x");
auto *go_edit = new HexLineEdit(nullptr, 16, 16, "0x");

auto *layout_top = new QHBoxLayout;
layout_top->addWidget(cell_size);
Expand All @@ -57,7 +57,7 @@ MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : Super(parent) {
memory_model, &MemoryModel::cached_access);
connect(
go_edit, &HexLineEdit::value_edit_finished, memory_content,
[memory_content](uint32_t value) {
[memory_content](uint64_t value) {
memory_content->go_to_address(machine::Address(value));
});
connect(
Expand Down
46 changes: 35 additions & 11 deletions src/machine/machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@ Machine::Machine(MachineConfig config, bool load_symtab, bool load_executable)
if (load_executable) {
ProgramLoader program(machine_config.elf());
this->machine_config.set_simulated_endian(program.get_endian());
mem_program_only = new Memory(machine_config.get_simulated_endian());
program.to_memory(mem_program_only);

if (program.get_architecture_type() == ARCH64)
this->machine_config.set_simulated_xlen(Xlen::_64);
else
this->machine_config.set_simulated_xlen(Xlen::_32);

if (this->machine_config.get_simulated_xlen() == Xlen::_64)
mem_program_only = new Memory(machine_config.get_simulated_endian(), 64);
else
mem_program_only = new Memory(machine_config.get_simulated_endian(), 32);
program.to_memory(mem_program_only);

if (load_symtab) {
symtab = program.get_symbol_table();
}
Expand All @@ -33,12 +37,16 @@ Machine::Machine(MachineConfig config, bool load_symtab, bool load_executable)
}
mem = new Memory(*mem_program_only);
} else {
mem = new Memory(machine_config.get_simulated_endian());
mem = (this->machine_config.get_simulated_xlen() == Xlen::_64 ? new Memory(machine_config.get_simulated_endian(), 64) : new Memory(machine_config.get_simulated_endian(), 32));
}

data_bus = new MemoryDataBus(machine_config.get_simulated_endian());
data_bus->insert_device_to_range(
mem, 0x00000000_addr, 0xefffffff_addr, false);
if (this->machine_config.get_simulated_xlen() == Xlen::_32)
data_bus->insert_device_to_range(
mem, 0x00000000_addr, 0xefffffff_addr, false);
else
data_bus->insert_device_to_range(
mem, 0x00000000_addr, 0xefffffffffffffff_addr, false);

setup_serial_port();
setup_perip_spi_led();
Expand Down Expand Up @@ -112,18 +120,34 @@ Machine::Machine(MachineConfig config, bool load_symtab, bool load_executable)
}
void Machine::setup_lcd_display() {
perip_lcd_display = new LcdDisplay(machine_config.get_simulated_endian());
memory_bus_insert_range(
perip_lcd_display, 0xffe00000_addr, 0xffe4afff_addr, true);
if(this->machine_config.get_simulated_xlen() == Xlen::_64){
memory_bus_insert_range(
perip_lcd_display, 0xffffffffffe00000_addr, 0xffffffffffe4afff_addr, true);
}
else
memory_bus_insert_range(
perip_lcd_display, 0xffe00000_addr, 0xffe4afff_addr, true);
}
void Machine::setup_perip_spi_led() {
perip_spi_led = new PeripSpiLed(machine_config.get_simulated_endian());
memory_bus_insert_range(
perip_spi_led, 0xffffc100_addr, 0xffffc1ff_addr, true);
if(this->machine_config.get_simulated_xlen() == Xlen::_64){
memory_bus_insert_range(
perip_spi_led, 0xffffffffffffc100_addr, 0xffffffffffffc1ff_addr, true);
}
else
memory_bus_insert_range(
perip_spi_led, 0xffffc100_addr, 0xffffc1ff_addr, true);
}
void Machine::setup_serial_port() {
ser_port = new SerialPort(machine_config.get_simulated_endian());
memory_bus_insert_range(ser_port, 0xffffc000_addr, 0xffffc03f_addr, true);
memory_bus_insert_range(ser_port, 0xffff0000_addr, 0xffff003f_addr, false);
if(this->machine_config.get_simulated_xlen() == Xlen::_64){
memory_bus_insert_range(ser_port, 0xffffffffffffc000_addr, 0xffffffffffffc03f_addr, true);
memory_bus_insert_range(ser_port, 0xffffffffffff0000_addr, 0xffffffffffff003f_addr, false);
}
else{
memory_bus_insert_range(ser_port, 0xffffc000_addr, 0xffffc03f_addr, true);
memory_bus_insert_range(ser_port, 0xffff0000_addr, 0xffff003f_addr, false);
}
connect(
ser_port, &SerialPort::signal_interrupt, this,
&Machine::set_interrupt_signal);
Expand Down
84 changes: 60 additions & 24 deletions src/machine/memory/backend/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,22 @@ static_assert(
* ```address & generate_mask(8, 0)```
*/
constexpr uint64_t generate_mask(size_t section_size, size_t unit_size) {
return ((1U << section_size) - 1) << unit_size;
return ((1ULL << section_size) - 1) << unit_size;
}

/**
* Get index in row for given offset and row number i
*/
constexpr size_t tree_row_bit_offset(size_t i) {
return 32 - MEMORY_TREE_BITS - i * MEMORY_TREE_BITS;
constexpr uint64_t tree_row_bit_offset(size_t i, size_t xlen) {
return xlen - MEMORY_TREE_BITS - i * MEMORY_TREE_BITS;
}

/*
* Select branch index from memory tree.
*/
constexpr size_t get_tree_row(size_t offset, size_t i) {
return (offset & generate_mask(MEMORY_TREE_BITS, tree_row_bit_offset(i)))
>> tree_row_bit_offset(i);
constexpr uint64_t get_tree_row(uint64_t offset, size_t i, size_t xlen) {
return (offset & generate_mask(MEMORY_TREE_BITS, tree_row_bit_offset(i, xlen)))
>> tree_row_bit_offset(i, xlen);
}

Memory::Memory() : BackendMemory(BIG) {
Expand All @@ -128,36 +128,71 @@ Memory::Memory() : BackendMemory(BIG) {
Memory::Memory(Endian simulated_machine_endian)
: BackendMemory(simulated_machine_endian) {
this->mt_root = allocate_section_tree();
this->xlen = 32;
}

Memory::Memory(Endian simulated_machine_endian, size_t xlen)
: BackendMemory(simulated_machine_endian) {
this->mt_root = allocate_section_tree();
this->xlen = xlen;
}

Memory::Memory(const Memory &other)
: BackendMemory(other.simulated_machine_endian) {
this->mt_root = copy_section_tree(other.get_memory_tree_root(), 0);
this->xlen = other.xlen;
this->mt_root = copy_section_tree(other.get_memory_tree_root(), 0, ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS));
}

Memory::~Memory() {
free_section_tree(this->mt_root, 0);
free_section_tree(this->mt_root, 0, ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS));
delete[] this->mt_root;
}

void Memory::reset() {
free_section_tree(this->mt_root, 0);
free_section_tree(this->mt_root, 0, ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS));
delete[] this->mt_root;
this->mt_root = allocate_section_tree();
}

void Memory::reset(const Memory &m) {
free_section_tree(this->mt_root, 0);
this->mt_root = copy_section_tree(m.get_memory_tree_root(), 0);
free_section_tree(this->mt_root, 0, ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS));
if(this->xlen > m.xlen) {
union MemoryTree *cmt = allocate_section_tree();
const union MemoryTree *mt = m.get_memory_tree_root();
this->xlen = m.xlen;
for(size_t i = 0; i < MEMORY_TREE_ROW_SIZE; i++) {
if (mt[i].subtree != nullptr) {
size_t index = i >> 3 ? 15 : 0;
union MemoryTree *temp = cmt;
for (size_t j = 0; j < 8; j++, temp = temp[index].subtree) {
if (temp[index].subtree == nullptr) {
temp[index].subtree = allocate_section_tree();
}
}
temp[i].subtree = copy_section_tree(mt[i].subtree, 1, ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS));
}
}
delete[] this->mt_root;
this->mt_root = cmt;
this->xlen = 64;
}
else if (this->xlen < m.xlen) {
delete[] this->mt_root;
this->mt_root = allocate_section_tree();
}
else
this->mt_root = copy_section_tree(m.get_memory_tree_root(), 0, ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS));

}

MemorySection *Memory::get_section(size_t offset, bool create) const {
union MemoryTree *w = this->mt_root;
size_t row_num;
// Walk memory tree branch from root to leaf and create new nodes when
// needed and requested (`create` flag).
for (size_t i = 0; i < (MEMORY_TREE_DEPTH - 1); i++) {
row_num = get_tree_row(offset, i);
size_t memory_tree_depth = ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS);
for (size_t i = 0; i < (memory_tree_depth - 1); i++) {
row_num = get_tree_row(offset, i, this->xlen);
if (w[row_num].subtree == nullptr) {
// We don't have this tree so allocate it.
if (!create) {
Expand All @@ -168,7 +203,7 @@ MemorySection *Memory::get_section(size_t offset, bool create) const {
}
w = w[row_num].subtree;
}
row_num = get_tree_row(offset, MEMORY_TREE_DEPTH - 1);
row_num = get_tree_row(offset, memory_tree_depth - 1, this->xlen);
if (w[row_num].sec == nullptr) {
if (!create) {
return nullptr;
Expand Down Expand Up @@ -227,7 +262,7 @@ uint32_t Memory::get_change_counter() const {
}

bool Memory::operator==(const Memory &m) const {
return compare_section_tree(this->mt_root, m.get_memory_tree_root(), 0);
return compare_section_tree(this->mt_root, m.get_memory_tree_root(), 0 , ((this->xlen - MEMORY_SECTION_BITS) / MEMORY_TREE_BITS));
}

bool Memory::operator!=(const Memory &m) const {
Expand All @@ -244,11 +279,11 @@ union machine::MemoryTree *Memory::allocate_section_tree() {
return mt;
}

void Memory::free_section_tree(union MemoryTree *mt, size_t depth) {
if (depth < (MEMORY_TREE_DEPTH - 1)) { // Following level is memory tree
void Memory::free_section_tree(union MemoryTree *mt, size_t depth, size_t memory_tree_depth) {
if (depth < (memory_tree_depth - 1)) { // Following level is memory tree
for (size_t i = 0; i < MEMORY_TREE_ROW_SIZE; i++) {
if (mt[i].subtree != nullptr) {
free_section_tree(mt[i].subtree, depth + 1);
free_section_tree(mt[i].subtree, depth + 1, memory_tree_depth);
delete[] mt[i].subtree;
}
}
Expand All @@ -262,14 +297,15 @@ void Memory::free_section_tree(union MemoryTree *mt, size_t depth) {
bool Memory::compare_section_tree(
const union MemoryTree *mt1,
const union MemoryTree *mt2,
size_t depth) {
if (depth < (MEMORY_TREE_DEPTH - 1)) { // Following level is memory tree
size_t depth,
size_t memory_tree_depth) {
if (depth < (memory_tree_depth - 1)) { // Following level is memory tree
for (size_t i = 0; i < MEMORY_TREE_ROW_SIZE; i++) {
if (((mt1[i].subtree == nullptr || mt2[i].subtree == nullptr)
&& mt1[i].subtree != mt2[i].subtree)
|| (mt1[i].subtree != nullptr && mt2[i].subtree != nullptr
&& !compare_section_tree(
mt1[i].subtree, mt2[i].subtree, depth + 1))) {
mt1[i].subtree, mt2[i].subtree, depth + 1, memory_tree_depth))) {
return false;
}
}
Expand All @@ -287,12 +323,12 @@ bool Memory::compare_section_tree(
}

union machine::MemoryTree *
Memory::copy_section_tree(const union MemoryTree *mt, size_t depth) {
Memory::copy_section_tree(const union MemoryTree *mt, size_t depth, size_t memory_tree_depth) {
union MemoryTree *nmt = allocate_section_tree();
if (depth < (MEMORY_TREE_DEPTH - 1)) { // Following level is memory tree
if (depth < (memory_tree_depth - 1)) { // Following level is memory tree
for (size_t i = 0; i < MEMORY_TREE_ROW_SIZE; i++) {
if (mt[i].subtree != nullptr) {
nmt[i].subtree = copy_section_tree(mt[i].subtree, depth + 1);
nmt[i].subtree = copy_section_tree(mt[i].subtree, depth + 1, memory_tree_depth);
}
}
} else { // Following level is memory section
Expand Down
9 changes: 6 additions & 3 deletions src/machine/memory/backend/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class Memory final : public BackendMemory {
// This is dummy constructor for qt internal uses only.
Memory();
explicit Memory(Endian simulated_machine_endian);
Memory(Endian simulated_machine_endian, size_t xlen);
Memory(const Memory &);
~Memory() override;
void reset(); // Reset whole content of memory (removes old tree and creates
Expand Down Expand Up @@ -109,14 +110,16 @@ class Memory final : public BackendMemory {
private:
union MemoryTree *mt_root;
uint32_t change_counter = 0;
size_t xlen;
static union MemoryTree *allocate_section_tree();
static void free_section_tree(union MemoryTree *, size_t depth);
static void free_section_tree(union MemoryTree *, size_t depth , size_t memory_tree_depth);
static bool compare_section_tree(
const union MemoryTree *,
const union MemoryTree *,
size_t depth);
size_t depth,
size_t memory_tree_depth);
static union MemoryTree *
copy_section_tree(const union MemoryTree *, size_t depth);
copy_section_tree(const union MemoryTree *, size_t depth , size_t memory_tree_depth);
[[nodiscard]] uint32_t get_change_counter() const;
};
} // namespace machine
Expand Down
Loading