Add uncached memory access support to scalar store
PiperOrigin-RevId: 582740507
diff --git a/sim/kelvin_base.isa b/sim/kelvin_base.isa
index 49e7736..518fd78 100644
--- a/sim/kelvin_base.isa
+++ b/sim/kelvin_base.isa
@@ -179,15 +179,15 @@
sw{: rs1, S_imm12, rs2 : },
resources: { next_pc, rs1, rs2 : },
disasm: "sw", "%rs2, %S_imm12(%rs1)",
- semfunc: "&mpact::sim::riscv::RV32::RiscVISw";
+ semfunc: "&KelvinIStore<uint32_t>";
sh{: rs1, S_imm12, rs2 : },
resources: { next_pc, rs1, rs2 : },
disasm: "sh", "%rs2, %S_imm12(%rs1)",
- semfunc: "&mpact::sim::riscv::RV32::RiscVISh";
+ semfunc: "&KelvinIStore<uint16_t>";
sb{: rs1, S_imm12, rs2 : },
resources: { next_pc, rs1, rs2 : },
disasm: "sb", "%rs2, %S_imm12(%rs1)",
- semfunc: "&mpact::sim::riscv::RV32::RiscVISb";
+ semfunc: "&KelvinIStore<uint8_t>";
fence{: I_imm12 : },
disasm: "fence",
semfunc: "&mpact::sim::riscv::RiscVIFence";
diff --git a/sim/kelvin_instructions.cc b/sim/kelvin_instructions.cc
index f2ac50f..4967a8d 100644
--- a/sim/kelvin_instructions.cc
+++ b/sim/kelvin_instructions.cc
@@ -113,4 +113,30 @@
}
}
+// Handle Store instructions for mmap_uncached addresses
+template <typename T>
+void KelvinIStore(Instruction *inst) {
+ uint32_t base = GetInstructionSource<uint32_t>(inst, 0);
+ int32_t offset = GetInstructionSource<int32_t>(inst, 1);
+ uint32_t address = base + offset;
+ T value = GetInstructionSource<T>(inst, 2);
+ auto *state = static_cast<KelvinState *>(inst->state());
+ // Check and exclude the cache invalidation bit. However, the semihost tests
+ // use the memory space greater than the kelvin HW configuration and do not
+ // comply to the magic bit setting. Exclude the check and mask for those
+ // tests.
+ if (state->max_physical_address() <=
+ kKelvinMaxMemoryAddress) { // exclude semihost tests
+ address &= kMemMask;
+ }
+ auto *db = state->db_factory()->Allocate(sizeof(T));
+ db->Set<T>(0, value);
+ state->StoreMemory(inst, address, db);
+ db->DecRef();
+}
+
+template void KelvinIStore<uint32_t>(mpact::sim::generic::Instruction *inst);
+template void KelvinIStore<uint16_t>(mpact::sim::generic::Instruction *inst);
+template void KelvinIStore<uint8_t>(mpact::sim::generic::Instruction *inst);
+
} // namespace kelvin::sim
diff --git a/sim/kelvin_instructions.h b/sim/kelvin_instructions.h
index d15fc67..be0f77c 100644
--- a/sim/kelvin_instructions.h
+++ b/sim/kelvin_instructions.h
@@ -29,6 +29,9 @@
void KelvinLogInstruction(int log_mode, mpact::sim::generic::Instruction *inst);
+template <typename T>
+void KelvinIStore(mpact::sim::generic::Instruction *inst);
+
} // namespace kelvin::sim
#endif // SIM_KELVIN_INSTRUCTIONS_H_
diff --git a/sim/kelvin_state.h b/sim/kelvin_state.h
index 45357cc..6eec9b0 100644
--- a/sim/kelvin_state.h
+++ b/sim/kelvin_state.h
@@ -34,6 +34,14 @@
using Instruction = ::mpact::sim::generic::Instruction;
+// Kelvin HW reserves the 31st bit as the magic cache invalidation bit.
+// SW can update the load/store address to include that bit to trigger immediate
+// cache invalidation. The actual address should exclude that bit. In ISS the
+// invalidation is no-op and the actual address should be in the lower bits.
+//
+// Note the core supports up to 2GB memory (4MB is actually integrated in RTL).
+constexpr uint64_t kMemMask = 0x0000'0000'7fff'ffff;
+
// Default to 256 to match
// https://opensecura.googlesource.com/hw/kelvin/+/master/hdl/chisel/src/kelvin/Parameters.scala.
inline constexpr uint32_t kVectorLengthInBits = 256;
diff --git a/sim/kelvin_vector_memory_instructions.cc b/sim/kelvin_vector_memory_instructions.cc
index be16c35..c63b943 100644
--- a/sim/kelvin_vector_memory_instructions.cc
+++ b/sim/kelvin_vector_memory_instructions.cc
@@ -33,14 +33,6 @@
using mpact::sim::riscv::RV32VectorDestinationOperand;
using mpact::sim::riscv::RV32VectorSourceOperand;
-// Kelvin HW reserves the 31st bit as the magic cache invalidation bit.
-// SW can update the load/store address to include that bit to trigger immediate
-// cache invalidation. The actual address should exclude that bit. In ISS the
-// invalidation is no-op and the actual address should be in the lower bits.
-//
-// Note the core supports up to 2GB memory (4MB is actually integrated in RTL).
-constexpr uint64_t kMemMask = 0x0000'0000'7fff'ffff;
-
// Vector load instruction with optional data length, stride and address
// register post-increment.
template <typename T>