Changed how caches are instantiated and configured.
Since it is preferred to have absl::Flags all in one file (the file with,
main()), how that flag is used to configure caches was changed to use config
objects in the X_top classes.
PiperOrigin-RevId: 679300970
Change-Id: Ic144279e37fb2e2c7730d63e7ff35a3326ea7c62
diff --git a/cheriot/BUILD b/cheriot/BUILD
index 87dd61c..365d1c2 100644
--- a/cheriot/BUILD
+++ b/cheriot/BUILD
@@ -506,6 +506,7 @@
"@com_google_mpact-riscv//riscv:riscv_state",
"@com_google_mpact-sim//mpact/sim/generic:action_points",
"@com_google_mpact-sim//mpact/sim/generic:component",
+ "@com_google_mpact-sim//mpact/sim/generic:config",
"@com_google_mpact-sim//mpact/sim/generic:core",
"@com_google_mpact-sim//mpact/sim/generic:core_debug_interface",
"@com_google_mpact-sim//mpact/sim/generic:counters",
diff --git a/cheriot/cheriot_renode.cc b/cheriot/cheriot_renode.cc
index 30ea54a..da29a83 100644
--- a/cheriot/cheriot_renode.cc
+++ b/cheriot/cheriot_renode.cc
@@ -23,7 +23,6 @@
#include <ios>
#include <iostream>
#include <memory>
-#include <new>
#include <string>
#include <string_view>
@@ -79,6 +78,7 @@
namespace cheriot {
using ::mpact::sim::proto::ComponentData;
+using ::mpact::sim::proto::ComponentValueEntry;
using ::mpact::sim::riscv::RiscVClint;
using ::mpact::sim::riscv::RiscVCounterCsr;
using ::mpact::sim::riscv::RiscVCounterCsrHigh;
@@ -103,6 +103,8 @@
constexpr std::string_view kWaitForCLI = "waitForCLI";
constexpr std::string_view kInstProfile = "instProfile";
constexpr std::string_view kMemProfile = "memProfile";
+constexpr std::string_view kICache = "iCache";
+constexpr std::string_view kDCache = "dCache";
// Cpu names
constexpr std::string_view kBaseName = "Mpact.Cheriot";
constexpr std::string_view kRvvName = "Mpact.CheriotRvv";
@@ -166,8 +168,8 @@
delete cheriot_renode_cli_top_;
delete cheriot_cli_forwarder_;
delete cheriot_decoder_;
- delete cheriot_state_;
delete cheriot_top_;
+ delete cheriot_state_;
delete semihost_;
delete router_;
delete atomic_memory_;
@@ -342,6 +344,8 @@
absl::Status CheriotRenode::SetConfig(const char *config_names[],
const char *config_values[], int size) {
+ std::string icache_cfg;
+ std::string dcache_cfg;
uint64_t tagged_memory_base = 0;
uint64_t tagged_memory_size = 0;
uint64_t revocation_memory_base = 0;
@@ -353,32 +357,41 @@
for (int i = 0; i < size; ++i) {
std::string name(config_names[i]);
std::string str_value = config_values[i];
- auto res = ParseNumber(str_value);
- uint64_t value = 0;
- if (!res.ok()) {
- return res.status();
- }
- value = res.value();
- if (name == kTaggedMemoryBase) {
- tagged_memory_base = value;
- } else if (name == kTaggedMemorySize) {
- tagged_memory_size = value;
- } else if (name == kRevocationMemoryBase) {
- revocation_memory_base = value;
- } else if (name == kClintMMRBase) {
- clint_mmr_base = value;
- } else if (name == kClintPeriod) {
- clint_period = value;
- } else if (name == kCLIPort) {
- cli_port = value;
- } else if (name == kWaitForCLI) {
- wait_for_cli = value;
- } else if (name == kInstProfile) {
- do_inst_profile = value != 0;
- } else if (name == kMemProfile) {
- mem_profiler_->set_is_enabled(value != 0);
+ // First check string valued config values.
+ if (name == kICache) {
+ icache_cfg = str_value;
+ } else if (name == kDCache) {
+ dcache_cfg = str_value;
} else {
- LOG(ERROR) << "Unknown config name: " << name << " " << config_values[i];
+ // Numeric config values.
+ auto res = ParseNumber(str_value);
+ uint64_t value = 0;
+ if (!res.ok()) {
+ return res.status();
+ }
+ value = res.value();
+ if (name == kTaggedMemoryBase) {
+ tagged_memory_base = value;
+ } else if (name == kTaggedMemorySize) {
+ tagged_memory_size = value;
+ } else if (name == kRevocationMemoryBase) {
+ revocation_memory_base = value;
+ } else if (name == kClintMMRBase) {
+ clint_mmr_base = value;
+ } else if (name == kClintPeriod) {
+ clint_period = value;
+ } else if (name == kCLIPort) {
+ cli_port = value;
+ } else if (name == kWaitForCLI) {
+ wait_for_cli = value;
+ } else if (name == kInstProfile) {
+ do_inst_profile = value != 0;
+ } else if (name == kMemProfile) {
+ mem_profiler_->set_is_enabled(value != 0);
+ } else {
+ LOG(ERROR) << "Unknown config name: " << name << " "
+ << config_values[i];
+ }
}
}
if (tagged_memory_size == 0) {
@@ -441,6 +454,22 @@
absl::StrCat("Failed to create socket CLI (", errno, ")"));
}
}
+ if (!icache_cfg.empty()) {
+ ComponentValueEntry icache_value;
+ icache_value.set_name("icache");
+ icache_value.set_string_value(icache_cfg);
+ auto *cfg = cheriot_top_->GetConfig("icache");
+ auto status = cfg->Import(&icache_value);
+ if (!status.ok()) return status;
+ }
+ if (!dcache_cfg.empty()) {
+ ComponentValueEntry dcache_value;
+ dcache_value.set_name("dcache");
+ dcache_value.set_string_value(dcache_cfg);
+ auto *cfg = cheriot_top_->GetConfig("dcache");
+ auto status = cfg->Import(&dcache_value);
+ if (!status.ok()) return status;
+ }
return absl::OkStatus();
}
diff --git a/cheriot/cheriot_top.cc b/cheriot/cheriot_top.cc
index 9c663d0..d683b61 100644
--- a/cheriot/cheriot_top.cc
+++ b/cheriot/cheriot_top.cc
@@ -21,7 +21,6 @@
#include <thread> // NOLINT: third party code.
#include <utility>
-#include "absl/flags/flag.h"
#include "absl/functional/any_invocable.h"
#include "absl/functional/bind_front.h"
#include "absl/log/check.h"
@@ -55,9 +54,6 @@
#include "riscv//riscv_csr.h"
#include "riscv//riscv_register.h"
-// Flag to enable and configure instruction cache.
-ABSL_FLAG(std::string, icache, "", "Instruction cache configuration");
-
namespace mpact {
namespace sim {
namespace cheriot {
@@ -78,8 +74,20 @@
counter_num_cycles_("num_cycles", 0),
counter_pc_("pc", 0),
cap_reg_re_{
- R"((\w+)\.(top|base|length|tag|permissions|object_type|reserved))"} {
+ R"((\w+)\.(top|base|length|tag|permissions|object_type|reserved))"},
+ icache_config_("icache", ""),
+ dcache_config_("dcache", "") {
CHECK_OK(AddChildComponent(*state_));
+ // Register icache configuration, and set a callback for when the config
+ // entry is written to.
+ CHECK_OK(AddConfig(&icache_config_));
+ icache_config_.AddValueWrittenCallback(
+ [this]() { ConfigureCache(icache_, icache_config_); });
+ // Register dcache configuration, and set a callback for when the config
+ // entry is written to.
+ CHECK_OK(AddConfig(&dcache_config_));
+ dcache_config_.AddValueWrittenCallback(
+ [this]() { ConfigureCache(dcache_, dcache_config_); });
Initialize();
}
@@ -152,16 +160,7 @@
}
return false;
});
- // Instruction cache.
- if (!absl::GetFlag(FLAGS_icache).empty()) {
- icache_ = new Cache("icache", this);
- absl::Status status =
- icache_->Configure(absl::GetFlag(FLAGS_icache), &counter_num_cycles_);
- if (!status.ok()) {
- LOG(ERROR) << "Failed to configure instruction cache: " << status;
- }
- inst_db_ = state_->db_factory()->Allocate<uint32_t>(1);
- }
+ inst_db_ = db_factory_.Allocate<uint32_t>(1);
// Make sure the architectural and abi register aliases are added.
std::string reg_name;
@@ -191,6 +190,22 @@
}
}
+void CheriotTop::ConfigureCache(Cache *&cache, Config<std::string> &config) {
+ if (cache != nullptr) {
+ LOG(WARNING) << "Cache already configured - ignored";
+ return;
+ }
+ auto cfg_str = config.GetValue();
+ if (cfg_str.empty()) {
+ LOG(WARNING) << "Cache configuration is empty - ignored";
+ }
+ cache = new Cache(config.name(), this);
+ absl::Status status = cache->Configure(cfg_str, &counter_num_cycles_);
+ if (!status.ok()) {
+ LOG(ERROR) << "Failed to configure instruction cache: " << status.message();
+ }
+}
+
bool CheriotTop::ExecuteInstruction(Instruction *inst) {
// Check that pcc has tag set.
if (!pcc_->tag()) {
diff --git a/cheriot/cheriot_top.h b/cheriot/cheriot_top.h
index e187fac..131f531 100644
--- a/cheriot/cheriot_top.h
+++ b/cheriot/cheriot_top.h
@@ -33,6 +33,7 @@
#include "mpact/sim/generic/action_point_manager_base.h"
#include "mpact/sim/generic/breakpoint_manager.h"
#include "mpact/sim/generic/component.h"
+#include "mpact/sim/generic/config.h"
#include "mpact/sim/generic/core_debug_interface.h"
#include "mpact/sim/generic/counters.h"
#include "mpact/sim/generic/data_buffer.h"
@@ -51,6 +52,7 @@
using ::mpact::sim::generic::ActionPointManagerBase;
using ::mpact::sim::generic::BreakpointManager;
+using ::mpact::sim::generic::Config;
using ::mpact::sim::generic::DecoderInterface;
using ::mpact::sim::riscv::RiscVActionPointMemoryInterface;
using ::mpact::sim::util::Cache;
@@ -152,9 +154,14 @@
const std::string &halt_string() const { return halt_string_; }
void set_halt_string(std::string halt_string) { halt_string_ = halt_string; }
+ Cache *icache() const { return icache_; }
+ Cache *dcache() const { return dcache_; }
+
private:
// Initialize the top.
void Initialize();
+ // Configure cache helper method.
+ void ConfigureCache(Cache *&cache, Config<std::string> &config);
// Execute instruction. Returns true if the instruction was executed (or
// an exception was triggered).
bool ExecuteInstruction(Instruction *inst);
@@ -218,7 +225,11 @@
LazyRE2 cap_reg_re_;
// Flag for breaking on a control flow change.
bool break_on_control_flow_change_ = false;
- // ICache.
+ // Configuration items.
+ Config<std::string> icache_config_;
+ Config<std::string> dcache_config_;
+ // ICache & DCache.
+ Cache *dcache_ = nullptr;
Cache *icache_ = nullptr;
DataBuffer *inst_db_ = nullptr;
};
diff --git a/cheriot/mpact_cheriot.cc b/cheriot/mpact_cheriot.cc
index 3401dd7..dc6185f 100644
--- a/cheriot/mpact_cheriot.cc
+++ b/cheriot/mpact_cheriot.cc
@@ -20,7 +20,6 @@
#include <ios>
#include <iostream>
#include <memory>
-#include <new>
#include <optional>
#include <ostream>
#include <string>
@@ -157,6 +156,9 @@
ABSL_FLAG(uint64_t, clint, 0x0200'0000ULL, "Base address of clint");
ABSL_FLAG(uint64_t, uart, 0x1000'0000ULL, "Base address of uart");
+// Flag to enable and configure the instruction cache.
+ABSL_FLAG(std::string, icache, "", "Instruction cache configuration");
+
constexpr char kStackEndSymbolName[] = "__stack_end";
constexpr char kStackSizeSymbolName[] = "__stack_size";
@@ -165,6 +167,7 @@
using HaltReason = ::mpact::sim::generic::CoreDebugInterface::HaltReason;
using ::mpact::sim::cheriot::CheriotTop;
using ::mpact::sim::generic::Instruction;
+using ::mpact::sim::proto::ComponentValueEntry;
using ::mpact::sim::riscv::RiscVArmSemihost;
using ::mpact::sim::riscv::RiscVClint;
using ::mpact::sim::util::AtomicMemoryOpInterface;
@@ -289,6 +292,17 @@
CheriotTop cheriot_top("Cheriot", &cheriot_state, decoder);
+ if (!absl::GetFlag(FLAGS_icache).empty()) {
+ ComponentValueEntry icache_value;
+ icache_value.set_name("icache");
+ icache_value.set_string_value(absl::GetFlag(FLAGS_icache));
+ auto *cfg = cheriot_top.GetConfig("icache");
+ auto status = cfg->Import(&icache_value);
+ if (!status.ok()) return -1;
+ }
+
+ // TODO: enable dcache.
+
// Enable instruction profiling if the flag is set.
InstructionProfiler *inst_profiler = nullptr;
if (absl::GetFlag(FLAGS_inst_profile)) {