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,