New DynamicRegisterValue for inspecting and manipulating register bit fields, via bit field descriptors

This commit is contained in:
Nav
2024-12-15 00:40:54 +00:00
parent 6dd8f0453e
commit 4ff7c76621
5 changed files with 150 additions and 0 deletions

View File

@@ -15,6 +15,7 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/TargetVariantDescriptor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TargetMemoryCache.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TargetPhysicalInterface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DynamicRegisterValue.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TargetDescription/TargetDescriptionFile.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR8/Avr8.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR8/Avr8TargetConfig.cpp

View File

@@ -0,0 +1,89 @@
#include "DynamicRegisterValue.hpp"
#include <bitset>
namespace Targets
{
DynamicRegisterValue::DynamicRegisterValue(const TargetRegisterDescriptorAndValuePair& pair)
: DynamicRegisterValue(pair.first, pair.second)
{}
DynamicRegisterValue::DynamicRegisterValue(
const TargetRegisterDescriptor& registerDescriptor,
TargetMemoryBufferSpan value
)
: registerDescriptor(registerDescriptor)
, value(std::uint64_t{0})
{
assert(registerDescriptor.size <= 8);
assert(value.size() == this->registerDescriptor.size);
for (const auto byte : value) {
this->value = (this->value << 8) | byte;
}
}
DynamicRegisterValue::DynamicRegisterValue(const TargetRegisterDescriptor& registerDescriptor, std::uint64_t value)
: registerDescriptor(registerDescriptor)
, value(value)
{
assert(registerDescriptor.size <= 8);
}
void DynamicRegisterValue::setBitField(
const TargetBitFieldDescriptor& bitFieldDescriptor,
std::uint64_t inputValue
) {
auto valueBitset = std::bitset<64>{this->value};
const auto maskBitset = std::bitset<64>{bitFieldDescriptor.mask};
auto inputValueIndex = std::size_t{0};
for (auto maskIndex = std::size_t{0}; maskIndex < maskBitset.size(); ++maskIndex) {
if (maskBitset[maskIndex]) {
valueBitset.set(maskIndex, static_cast<bool>(inputValue & (0x01 << inputValueIndex++)));
}
}
this->value = valueBitset.to_ullong();
}
void DynamicRegisterValue::setBitField(const std::string& bitFieldKey, std::uint64_t value) {
return this->setBitField(this->registerDescriptor.getBitFieldDescriptor(bitFieldKey), value);
}
std::uint64_t DynamicRegisterValue::bitField(const TargetBitFieldDescriptor& bitFieldDescriptor) const {
auto output = std::bitset<64>{0};
const auto maskBitset = std::bitset<64>{bitFieldDescriptor.mask};
auto outputIndex = std::size_t{0};
for (auto maskIndex = std::size_t{0}; maskIndex < maskBitset.size(); ++maskIndex) {
if (maskBitset[maskIndex]) {
output.set(outputIndex++, static_cast<bool>(this->value & (0x01 << maskIndex)));
}
}
return output.to_ullong();
}
std::uint64_t DynamicRegisterValue::bitField(const std::string& bitFieldKey) const {
return this->bitField(this->registerDescriptor.getBitFieldDescriptor(bitFieldKey));
}
bool DynamicRegisterValue::bitFieldFlag(const TargetBitFieldDescriptor& bitFieldDescriptor) const {
return static_cast<bool>(this->bitField(bitFieldDescriptor));
}
bool DynamicRegisterValue::bitFieldFlag(const std::string& bitFieldKey) const {
return this->bitFieldFlag(this->registerDescriptor.getBitFieldDescriptor(bitFieldKey));
}
TargetMemoryBuffer DynamicRegisterValue::data() const {
auto output = TargetMemoryBuffer(this->registerDescriptor.size, 0x00);
for (auto i = TargetMemorySize{0}; i < this->registerDescriptor.size; ++i) {
output[i] = static_cast<unsigned char>(this->value >> ((this->registerDescriptor.size - i - 1) * 8));
}
return output;
}
}

View File

@@ -0,0 +1,32 @@
#pragma once
#include <cstdint>
#include <string>
#include "TargetRegisterDescriptor.hpp"
#include "TargetBitFieldDescriptor.hpp"
#include "TargetMemory.hpp"
namespace Targets
{
class DynamicRegisterValue
{
public:
const TargetRegisterDescriptor& registerDescriptor;
std::uint64_t value;
explicit DynamicRegisterValue(const TargetRegisterDescriptorAndValuePair& pair);
DynamicRegisterValue(const TargetRegisterDescriptor& registerDescriptor, TargetMemoryBufferSpan value);
DynamicRegisterValue(const TargetRegisterDescriptor& registerDescriptor, std::uint64_t value);
void setBitField(const TargetBitFieldDescriptor& bitFieldDescriptor, std::uint64_t inputValue);
void setBitField(const std::string& bitFieldKey, std::uint64_t inputValue);
[[nodiscard]] std::uint64_t bitField(const TargetBitFieldDescriptor& bitFieldDescriptor) const;
[[nodiscard]] std::uint64_t bitField(const std::string& bitFieldKey) const;
[[nodiscard]] bool bitFieldFlag(const TargetBitFieldDescriptor& bitFieldDescriptor) const;
[[nodiscard]] bool bitFieldFlag(const std::string& bitFieldKey) const;
[[nodiscard]] TargetMemoryBuffer data() const;
};
}

View File

@@ -309,6 +309,28 @@ namespace Targets::RiscV
return this->programmingMode;
}
TargetMemoryBuffer RiscV::readRegister(const TargetRegisterDescriptor& descriptor) {
return this->readRegisters({&descriptor}).front().second;
}
DynamicRegisterValue RiscV::readRegisterDynamicValue(const TargetRegisterDescriptor& descriptor) {
return DynamicRegisterValue{descriptor, this->readRegister(descriptor)};
}
void RiscV::writeRegister(const TargetRegisterDescriptor& descriptor, TargetMemoryBufferSpan value) {
this->writeRegisters({{descriptor, TargetMemoryBuffer{value.begin(), value.end()}}});
}
void RiscV::writeRegister(const TargetRegisterDescriptor& descriptor, std::uint64_t value) {
auto data = TargetMemoryBuffer(descriptor.size, 0x00);
for (auto i = TargetMemorySize{0}; i < descriptor.size; ++i) {
data[i] = static_cast<unsigned char>(value >> ((descriptor.size - i - 1) * 8));
}
this->writeRegister(descriptor, data);
}
bool RiscV::probeMemory(
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,

View File

@@ -13,6 +13,7 @@
#include "src/Targets/TargetAddressSpaceDescriptor.hpp"
#include "src/Targets/TargetRegisterGroupDescriptor.hpp"
#include "src/Targets/DynamicRegisterValue.hpp"
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp"
@@ -122,6 +123,11 @@ namespace Targets::RiscV
bool programmingMode = false;
TargetMemoryBuffer readRegister(const TargetRegisterDescriptor& descriptor);
DynamicRegisterValue readRegisterDynamicValue(const TargetRegisterDescriptor& descriptor);
void writeRegister(const TargetRegisterDescriptor& descriptor, TargetMemoryBufferSpan value);
void writeRegister(const TargetRegisterDescriptor& descriptor, std::uint64_t value);
bool probeMemory(
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,