Fix off-by-one Read/Write Memory problem
PiperOrigin-RevId: 563147950
diff --git a/sim/kelvin_top.cc b/sim/kelvin_top.cc
index 13e5c58..d3b7f03 100644
--- a/sim/kelvin_top.cc
+++ b/sim/kelvin_top.cc
@@ -525,7 +525,7 @@
if (run_status_ != RunStatus::kHalted) {
return absl::FailedPreconditionError("ReadMemory: Core must be halted");
}
- if (address >= state_->max_physical_address()) {
+ if (address > state_->max_physical_address()) {
return absl::InvalidArgumentError("Memory address invalid");
}
length =
@@ -544,7 +544,7 @@
if (run_status_ != RunStatus::kHalted) {
return absl::FailedPreconditionError("WriteMemory: Core must be halted");
}
- if (address >= state_->max_physical_address()) {
+ if (address > state_->max_physical_address()) {
return absl::InvalidArgumentError("Memory address invalid");
}
length =
diff --git a/sim/test/kelvin_top_test.cc b/sim/test/kelvin_top_test.cc
index 88f938e..e5ab21c 100644
--- a/sim/test/kelvin_top_test.cc
+++ b/sim/test/kelvin_top_test.cc
@@ -160,7 +160,8 @@
TEST_F(KelvinTopTest, ReadWriteOutOfBoundMemory) {
// Set the machine to have 16-byte physical memory
constexpr uint64_t kTestMemerySize = 0x10;
- kelvin_top_->state()->set_max_physical_address(kTestMemerySize - 1);
+ constexpr uint64_t kMaxPhysicalAddress = kTestMemerySize - 1;
+ kelvin_top_->state()->set_max_physical_address(kMaxPhysicalAddress);
uint8_t mem_bytes[kTestMemerySize + 4] = {0};
// Read the memory with the length greater than the physical memory size. The
// read operation is successful within the physical memory size range.
@@ -168,6 +169,11 @@
kelvin_top_->ReadMemory(kBinaryAddress, mem_bytes, sizeof(mem_bytes));
EXPECT_OK(result);
EXPECT_EQ(result.value(), kTestMemerySize);
+ // Read at the maximum physical address, so only one byte can be read.
+ result = kelvin_top_->ReadMemory(kMaxPhysicalAddress, mem_bytes,
+ sizeof(mem_bytes));
+ EXPECT_OK(result);
+ EXPECT_EQ(result.value(), 1);
// Read the memory with the staring address out of the physical memory range.
// The read operation returns error.
result = kelvin_top_->ReadMemory(kTestMemerySize + 4, mem_bytes,
@@ -180,6 +186,11 @@
kelvin_top_->WriteMemory(kBinaryAddress, mem_bytes, sizeof(mem_bytes));
EXPECT_OK(result);
EXPECT_EQ(result.value(), kTestMemerySize);
+ // Write at the maximum physical address, so only one byte can be written.
+ result = kelvin_top_->WriteMemory(kMaxPhysicalAddress, mem_bytes,
+ sizeof(mem_bytes));
+ EXPECT_OK(result);
+ EXPECT_EQ(result.value(), 1);
// Write the memory with the staring address out of the physical memory range.
// The write operation returns error.
result = kelvin_top_->WriteMemory(kTestMemerySize + 4, mem_bytes,