diff --git a/src/Targets/RiscV/DebugModule/Registers/MemoryAccessControlField.hpp b/src/Targets/RiscV/DebugModule/Registers/MemoryAccessControlField.hpp new file mode 100644 index 00000000..ce504ad7 --- /dev/null +++ b/src/Targets/RiscV/DebugModule/Registers/MemoryAccessControlField.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include + +#include "src/Targets/RiscV/RiscVGeneric.hpp" + +namespace Targets::RiscV::DebugModule::Registers +{ + struct MemoryAccessControlField + { + enum class MemorySize: std::uint8_t + { + SIZE_8 = 0x00, + SIZE_16 = 0x01, + SIZE_32 = 0x02, + SIZE_64 = 0x03, + SIZE_128 = 0x04, + }; + + bool write:1 = false; + bool postIncrement:1 = false; + MemorySize size:3 = MemorySize::SIZE_32; + bool virtualAddress:1 = false; + + MemoryAccessControlField() = default; + + MemoryAccessControlField( + bool write, + bool postIncrement, + MemorySize size, + bool virtualAddress + ) + : write(write) + , postIncrement(postIncrement) + , size(size) + , virtualAddress(virtualAddress) + {} + + constexpr explicit MemoryAccessControlField(std::uint32_t controlValue) + : write(static_cast(controlValue & (0x01 << 16))) + , postIncrement(static_cast(controlValue & (0x01 << 19))) + , size(static_cast((controlValue >> 20) & 0x07)) + , virtualAddress(static_cast(controlValue & (0x01 << 23))) + {} + + constexpr std::uint32_t value() const { + return std::uint32_t{0} + | static_cast(this->write) << 16 + | static_cast(this->postIncrement) << 19 + | static_cast(this->size) << 20 + | static_cast(this->virtualAddress) << 23 + ; + } + }; +} diff --git a/src/Targets/RiscV/DebugModule/Registers/RegisterAddresses.hpp b/src/Targets/RiscV/DebugModule/Registers/RegisterAddresses.hpp index f03cf233..2338ebeb 100644 --- a/src/Targets/RiscV/DebugModule/Registers/RegisterAddresses.hpp +++ b/src/Targets/RiscV/DebugModule/Registers/RegisterAddresses.hpp @@ -9,6 +9,12 @@ namespace Targets::RiscV::DebugModule::Registers enum class RegisterAddress: ::Targets::RiscV::DebugModule::RegisterAddress { ABSTRACT_DATA_0 = 0x04, + ABSTRACT_DATA_1 = 0x05, + ABSTRACT_DATA_2 = 0x06, + ABSTRACT_DATA_3 = 0x07, + ABSTRACT_DATA_4 = 0x08, + ABSTRACT_DATA_5 = 0x09, + ABSTRACT_DATA_6 = 0x0a, CONTROL_REGISTER = 0x10, STATUS_REGISTER = 0x11, ABSTRACT_CONTROL_STATUS_REGISTER = 0x16, diff --git a/src/Targets/RiscV/RiscV.cpp b/src/Targets/RiscV/RiscV.cpp index d481322a..1ba6e65c 100644 --- a/src/Targets/RiscV/RiscV.cpp +++ b/src/Targets/RiscV/RiscV.cpp @@ -3,10 +3,12 @@ #include #include #include +#include #include "Registers/RegisterNumbers.hpp" #include "DebugModule/Registers/RegisterAddresses.hpp" #include "DebugModule/Registers/RegisterAccessControlField.hpp" +#include "DebugModule/Registers/MemoryAccessControlField.hpp" #include "src/Exceptions/Exception.hpp" #include "src/TargetController/Exceptions/TargetOperationFailure.hpp" @@ -260,7 +262,65 @@ namespace Targets::RiscV TargetMemorySize bytes, const std::set& excludedAddressRanges ) { - return {}; + // TODO: excluded addresses + + const auto pageSize = 4; + if ((startAddress % pageSize) != 0 || (bytes % pageSize) != 0) { + // Alignment required + const auto alignedStartAddress = static_cast( + std::floor(static_cast(startAddress) / static_cast(pageSize)) * pageSize + ); + + const auto alignedBytes = static_cast( + std::ceil( + static_cast(bytes + (startAddress - alignedStartAddress)) + / static_cast(pageSize) + ) * pageSize + ); + + auto memoryBuffer = this->readMemory( + memoryType, + alignedStartAddress, + alignedBytes, + excludedAddressRanges + ); + + const auto offset = memoryBuffer.begin() + (startAddress - alignedStartAddress); + + auto output = TargetMemoryBuffer(); + output.reserve(bytes); + std::move(offset, offset + bytes, std::back_inserter(output)); + + return output; + } + + using DebugModule::Registers::MemoryAccessControlField; + + auto output = TargetMemoryBuffer(); + output.reserve(bytes); + + for (auto address = startAddress; address <= (startAddress + bytes - 1); address += 4) { + auto command = AbstractCommandRegister(); + command.commandType = AbstractCommandRegister::CommandType::MEMORY_ACCESS; + command.control = MemoryAccessControlField( + false, + false, + MemoryAccessControlField::MemorySize::SIZE_32, + false + ).value(); + + this->riscVDebugInterface->writeDebugModuleRegister(RegisterAddress::ABSTRACT_DATA_1, address); + + this->executeAbstractCommand(command); + + const auto data = this->riscVDebugInterface->readDebugModuleRegister(RegisterAddress::ABSTRACT_DATA_0); + output.emplace_back(static_cast(data >> 24)); + output.emplace_back(static_cast(data >> 16)); + output.emplace_back(static_cast(data >> 8)); + output.emplace_back(static_cast(data)); + } + + return output; } void RiscV::writeMemory(