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,