finish writing, ready to debug

This commit is contained in:
2024-07-31 15:19:00 +00:00
parent 39f7468531
commit 90bb66a182
6 changed files with 365 additions and 54 deletions

View File

@ -4,6 +4,7 @@
#ifndef MEMORY_H
#include <cstdint>
#include <ios>
#include <set>
#include <vector>
#include "tools.h"
using dark::max_size_t;
@ -16,22 +17,56 @@ struct Memory_Input {
dark::Wire<32> address_input;
dark::Wire<32> data_input;
dark::Wire<5> request_ROB_index;
dark::Wire<1> is_committing;
dark::Wire<5> commit_ins_ROB_index;
};
struct Memory_Output {
dark::Register<2> data_sign;
dark::Register<5> completed_memins_ROB_index;
dark::Register<32> completed_memins_read_data;
};
struct Change {
dark::Register<1> this_byte_changed;
dark::Register<32> addr;
dark::Register<8> before;
};
struct OperationPlayback {
dark::Register<1> has_uncommitted_write;
dark::Register<32> timestamp;
std::array<Change, 4> changes;
};
struct Memory_Private {
dark::Register<3> status;
dark::Register<32> cur_opt_addr;
dark::Register<32> cur_opt_data;
dark::Register<2> cur_opt_type;
dark::Register<2> cur_opt_bytes;
std::array<OperationPlayback, 32> playback;
dark::Register<32> cur_timestamp;
};
struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
private:
std::vector<uint8_t> memory_data;
void Undo() {
std::set<std::pair<uint32_t, std::pair<uint32_t, uint8_t>>> undo_list; // (timestamp, (addr, before))
for (int i = 0; i < 32; i++) {
if (bool(playback[i].has_uncommitted_write)) {
for (int j = 0; j < 4; j++) {
if (bool(playback[i].changes[j].this_byte_changed)) {
undo_list.insert(std::make_pair(static_cast<max_size_t>(playback[i].timestamp),
std::make_pair(static_cast<max_size_t>(playback[i].changes[j].addr),
static_cast<max_size_t>(playback[i].changes[j].before))));
}
}
}
}
size_t sz = undo_list.size();
auto it = undo_list.end();
for (int i = 0; i < sz; i++) {
it--;
memory_data[it->second.first] = it->second.second;
}
}
public:
Memory() { memory_data.resize(1 << 20, 0); }
@ -40,13 +75,22 @@ struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
// do some initialization
status <= 0;
data_sign <= 1;
cur_timestamp <= 0;
for (int i = 0; i < 32; i++) playback[i].has_uncommitted_write <= 0;
return;
}
if (bool(force_clear_receiver)) {
status <= 0;
data_sign <= 1;
Undo();
cur_timestamp <= 0;
for (int i = 0; i < 32; i++) playback[i].has_uncommitted_write <= 0;
return;
}
if (bool(is_committing)) {
playback[static_cast<max_size_t>(commit_ins_ROB_index)].has_uncommitted_write <= 0;
}
cur_timestamp <= static_cast<max_size_t>(cur_timestamp) + 1;
max_size_t request_type_signal = max_size_t(request_type_input);
uint8_t rw_type = request_type_signal & 3; // 0b00->none,0b01->read,0b10->write,0b11->invalid
uint8_t opt_bytes = (request_type_signal >> 2) & 3; // 0->1, 1->2, 2->4
@ -91,24 +135,59 @@ struct Memory : dark::Module<Memory_Input, Memory_Output, Memory_Private> {
default:
throw std::runtime_error("Invalid bytes");
}
data_sign <= 2; // has data and free
return;
} else {
size_t len = 1 << max_size_t(cur_opt_bytes);
uint32_t cur_opt_ROB_index = static_cast<max_size_t>(completed_memins_ROB_index);
switch (len) {
case 1:
playback[cur_opt_ROB_index].has_uncommitted_write <= 1;
playback[cur_opt_ROB_index].timestamp <= cur_timestamp;
playback[cur_opt_ROB_index].changes[0].this_byte_changed <= 1;
playback[cur_opt_ROB_index].changes[0].addr <= cur_opt_addr;
playback[cur_opt_ROB_index].changes[0].before <= memory_data[max_size_t(cur_opt_addr)];
playback[cur_opt_ROB_index].changes[1].this_byte_changed <= 0;
playback[cur_opt_ROB_index].changes[2].this_byte_changed <= 0;
playback[cur_opt_ROB_index].changes[3].this_byte_changed <= 0;
memory_data[max_size_t(cur_opt_addr)] = max_size_t(cur_opt_data) & 0xff;
break;
case 2:
playback[cur_opt_ROB_index].has_uncommitted_write <= 1;
playback[cur_opt_ROB_index].timestamp <= cur_timestamp;
playback[cur_opt_ROB_index].changes[0].this_byte_changed <= 1;
playback[cur_opt_ROB_index].changes[0].addr <= cur_opt_addr;
playback[cur_opt_ROB_index].changes[0].before <= memory_data[max_size_t(cur_opt_addr)];
playback[cur_opt_ROB_index].changes[1].this_byte_changed <= 1;
playback[cur_opt_ROB_index].changes[1].addr <= cur_opt_addr + 1;
playback[cur_opt_ROB_index].changes[1].before <= memory_data[max_size_t(cur_opt_addr) + 1];
playback[cur_opt_ROB_index].changes[2].this_byte_changed <= 0;
playback[cur_opt_ROB_index].changes[3].this_byte_changed <= 0;
*reinterpret_cast<uint16_t *>(&memory_data[max_size_t(cur_opt_addr)]) = max_size_t(cur_opt_data) & 0xffff;
break;
case 4:
playback[cur_opt_ROB_index].has_uncommitted_write <= 1;
playback[cur_opt_ROB_index].timestamp <= cur_timestamp;
playback[cur_opt_ROB_index].changes[0].this_byte_changed <= 1;
playback[cur_opt_ROB_index].changes[0].addr <= cur_opt_addr;
playback[cur_opt_ROB_index].changes[0].before <= memory_data[max_size_t(cur_opt_addr)];
playback[cur_opt_ROB_index].changes[1].this_byte_changed <= 1;
playback[cur_opt_ROB_index].changes[1].addr <= cur_opt_addr + 1;
playback[cur_opt_ROB_index].changes[1].before <= memory_data[max_size_t(cur_opt_addr) + 1];
playback[cur_opt_ROB_index].changes[2].this_byte_changed <= 1;
playback[cur_opt_ROB_index].changes[2].addr <= cur_opt_addr + 2;
playback[cur_opt_ROB_index].changes[2].before <= memory_data[max_size_t(cur_opt_addr) + 2];
playback[cur_opt_ROB_index].changes[3].this_byte_changed <= 1;
playback[cur_opt_ROB_index].changes[3].addr <= cur_opt_addr + 3;
playback[cur_opt_ROB_index].changes[3].before <= memory_data[max_size_t(cur_opt_addr) + 3];
*reinterpret_cast<uint32_t *>(&memory_data[max_size_t(cur_opt_addr)]) = max_size_t(cur_opt_data);
break;
default:
throw std::runtime_error("Invalid bytes");
}
data_sign <= 1; // free
return;
}
data_sign <= 2; // has data and free
return;
}
// now the memory is not busy
if (request_type_signal == 0) {