Adds a new CSR type RiscVShadowCsr that allows a CSR to provide a more
restrictive view of another CSR.

Adds cycle/cycleh and instret/instreth as shadow CSRs

PiperOrigin-RevId: 705657616
Change-Id: I6c15b939de524f2d135dd429726da892807ec538
diff --git a/riscv/riscv_csr.h b/riscv/riscv_csr.h
index b3b9480..6765b2c 100644
--- a/riscv/riscv_csr.h
+++ b/riscv/riscv_csr.h
@@ -69,12 +69,12 @@
   kTime = 0xc01,
   kInstret = 0xc02,
 
+  // Ignoring perf monitoring counters for now.
+
   kCycleH = 0xc80,
   kTimeH = 0xc81,
   kInstretH = 0x82,
 
-  // Ignoring perf monitoring counters for now.
-
   // Ignoring high bits of perf monitoring counters for now.
 
   // Supervisor trap setup.
@@ -388,94 +388,6 @@
   RiscVCsrClearBitsDb *clear_bits_target_;
 };
 
-// The shadow csr class is used to implement a more restricted view of another
-// CSR, for instance, making a read-only view version of a CSR that may be
-// accessible at lower privilege levels.
-template <typename T>
-class RiscVShadowCsr : public RiscVCsrInterface {
- public:
-  RiscVShadowCsr(std::string name, RiscVCsrEnum index, T read_mask,
-                 T write_mask, ArchState *state, RiscVCsrInterface *csr)
-      : RiscVCsrInterface(name, static_cast<uint64_t>(index), state),
-        csr_(csr),
-        read_mask_(read_mask),
-        write_mask_(write_mask),
-        write_target_(new RiscVCsrWriteDb(this)),
-        set_bits_target_(new RiscVCsrSetBitsDb(this)),
-        clear_bits_target_(new RiscVCsrClearBitsDb(this)) {}
-  RiscVShadowCsr() = delete;
-  RiscVShadowCsr(const RiscVShadowCsr &) = delete;
-  RiscVShadowCsr &operator=(const RiscVShadowCsr &) = delete;
-
-  ~RiscVShadowCsr() override {
-    delete write_target_;
-    delete set_bits_target_;
-    delete clear_bits_target_;
-  }
-
-  // Return the value, modified as per read mask.
-  uint32_t AsUint32() override {
-    return static_cast<uint32_t>(static_cast<T>(csr_->AsUint32()) & read_mask_);
-  }
-  uint64_t AsUint64() override {
-    return static_cast<uint64_t>(static_cast<T>(csr_->AsUint64()) & read_mask_);
-  }
-  // Write the value, modified as per write mask.
-  void Write(uint32_t value) override {
-    if (write_mask_ != 0) {
-      csr_->Write((static_cast<T>(csr_->GetUint32()) & ~write_mask_) |
-                  (static_cast<T>(value) & write_mask_));
-    }
-  }
-  void Write(uint64_t value) override {
-    if (write_mask_ != 0) {
-      csr_->Write((static_cast<T>(csr_->GetUint64()) & ~write_mask_) |
-                  (static_cast<T>(value) & write_mask_));
-    }
-  }
-  // Set the bits that are set in value, leave other bits unchanged.
-  // Set the bits specified in the value. Don't change the other bits.
-  void SetBits(uint32_t value) override { Write(GetUint32() | value); }
-  void SetBits(uint64_t value) override { Write(GetUint64() | value); }
-  // Clear the bits specified in the value. Don't change the other bits.
-  void ClearBits(uint32_t value) override { Write(GetUint32() & ~value); }
-  void ClearBits(uint64_t value) override { Write(GetUint64() & ~value); }
-  // Return the value, ignoring the read mask.
-  uint32_t GetUint32() override { return csr_->GetUint32(); }
-  uint64_t GetUint64() override { return csr_->GetUint64(); }
-  // Sets the value, ignoring the write mask.
-  void Set(uint32_t value) override { csr_->Set(static_cast<T>(value)); }
-  void Set(uint64_t value) override { csr_->Set(static_cast<T>(value)); }
-  // Size of value.
-  size_t size() const override { return sizeof(T); }
-  // Set to reset value.
-  void Reset() override { /* Empty. */ }
-  // Operand creation interface.
-  generic::SourceOperandInterface *CreateSourceOperand() override;
-  generic::DestinationOperandInterface *CreateSetDestinationOperand(
-      int latency, std::string op_name) override;
-  generic::DestinationOperandInterface *CreateClearDestinationOperand(
-      int latency, std::string op_name) override;
-  generic::DestinationOperandInterface *CreateWriteDestinationOperand(
-      int latency, std::string op_name) override;
-
-  RiscVCsrWriteDb *write_target() const { return write_target_; }
-  RiscVCsrSetBitsDb *set_bits_target() const { return set_bits_target_; }
-  RiscVCsrClearBitsDb *clear_bits_target() const { return clear_bits_target_; }
-
-  RiscVCsrInterface *csr() const { return csr_; }
-  T read_mask() const { return read_mask_; }
-  T write_mask() const { return write_mask_; }
-
- private:
-  RiscVCsrInterface *csr_;
-  T read_mask_;
-  T write_mask_;
-  RiscVCsrWriteDb *write_target_;
-  RiscVCsrSetBitsDb *set_bits_target_;
-  RiscVCsrClearBitsDb *clear_bits_target_;
-};
-
 using RiscV32SimpleCsr = RiscVSimpleCsr<uint32_t>;
 using RiscV64SimpleCsr = RiscVSimpleCsr<uint64_t>;
 
@@ -609,35 +521,6 @@
   return new RiscVCsrSourceOperand(this);
 }
 
-template <typename T>
-generic::DestinationOperandInterface *
-RiscVShadowCsr<T>::CreateSetDestinationOperand(int latency,
-                                               std::string op_name) {
-  return new RiscVCsrDestinationOperand(this, this->set_bits_target(), latency,
-                                        op_name);
-}
-
-template <typename T>
-generic::DestinationOperandInterface *
-RiscVShadowCsr<T>::CreateClearDestinationOperand(int latency,
-                                                 std::string op_name) {
-  return new RiscVCsrDestinationOperand(this, this->clear_bits_target(),
-                                        latency, op_name);
-}
-
-template <typename T>
-generic::DestinationOperandInterface *
-RiscVShadowCsr<T>::CreateWriteDestinationOperand(int latency,
-                                                 std::string op_name) {
-  return new RiscVCsrDestinationOperand(this, this->write_target(), latency,
-                                        op_name);
-}
-
-template <typename T>
-generic::SourceOperandInterface *RiscVShadowCsr<T>::CreateSourceOperand() {
-  return new RiscVCsrSourceOperand(this);
-}
-
 }  // namespace riscv
 }  // namespace sim
 }  // namespace mpact
diff --git a/riscv/riscv_state.cc b/riscv/riscv_state.cc
index 36e4fe9..8d71bad 100644
--- a/riscv/riscv_state.cc
+++ b/riscv/riscv_state.cc
@@ -234,23 +234,23 @@
   auto *minstret = CreateCsr<RiscVCounterCsr<T, RiscVState>>(
       state, csr_vec, "minstret", RiscVCsrEnum ::kMInstret, state);
   CHECK_NE(minstret, nullptr);
-  RiscVCsrInterface *minstreth = nullptr;
   if (sizeof(T) == sizeof(uint32_t)) {
-    minstreth = CreateCsr<RiscVCounterCsrHigh<RiscVState>>(
-        state, csr_vec, "minstreth", RiscVCsrEnum::kMInstretH, state,
-        reinterpret_cast<RiscVCounterCsr<uint32_t, RiscVState> *>(minstret));
-    CHECK_NE(minstreth, nullptr);
+    CHECK_NE(CreateCsr<RiscVCounterCsrHigh<RiscVState>>(
+                 state, csr_vec, "minstreth", RiscVCsrEnum::kMInstretH, state,
+                 reinterpret_cast<RiscVCounterCsr<uint32_t, RiscVState> *>(
+                     minstret)),
+             nullptr);
   }
   // mcycle/mcycleh
   auto *mcycle = CreateCsr<RiscVCounterCsr<T, RiscVState>>(
       state, csr_vec, "mcycle", RiscVCsrEnum::kMCycle, state);
   CHECK_NE(mcycle, nullptr);
-  RiscVCsrInterface *mcycleh = nullptr;
   if (sizeof(T) == sizeof(uint32_t)) {
-    mcycleh = CreateCsr<RiscVCounterCsrHigh<RiscVState>>(
-        state, csr_vec, "mcycleh", RiscVCsrEnum::kMCycleH, state,
-        reinterpret_cast<RiscVCounterCsr<uint32_t, RiscVState> *>(mcycle));
-    CHECK_NE(mcycleh, nullptr);
+    CHECK_NE(
+        CreateCsr<RiscVCounterCsrHigh<RiscVState>>(
+            state, csr_vec, "mcycleh", RiscVCsrEnum::kMCycleH, state,
+            reinterpret_cast<RiscVCounterCsr<uint32_t, RiscVState> *>(mcycle)),
+        nullptr);
   }
 
   // Hypervisor level CSRs
@@ -318,29 +318,6 @@
 
   // User level CSRs
 
-  // instret/instreth
-  CHECK_NE(CreateCsr<RiscVShadowCsr<T>>(
-               state, csr_vec, "instret", RiscVCsrEnum ::kInstret,
-               std::numeric_limits<T>::max(), 0, state, minstret),
-           nullptr);
-  if (sizeof(T) == sizeof(uint32_t)) {
-    CHECK_NE(CreateCsr<RiscVShadowCsr<T>>(
-                 state, csr_vec, "instreth", RiscVCsrEnum::kInstretH,
-                 std::numeric_limits<T>::max(), 0, state, minstreth),
-             nullptr);
-  }
-  // cycle/cycleh
-  CHECK_NE(CreateCsr<RiscVShadowCsr<T>>(
-               state, csr_vec, "cycle", RiscVCsrEnum::kCycle,
-               std::numeric_limits<T>::max(), 0, state, mcycle),
-           nullptr);
-  if (sizeof(T) == sizeof(uint32_t)) {
-    CHECK_NE(CreateCsr<RiscVShadowCsr<T>>(
-                 state, csr_vec, "cycleh", RiscVCsrEnum::kCycleH,
-                 std::numeric_limits<T>::max(), 0, state, mcycleh),
-             nullptr);
-  }
-
   // ustatus
   CHECK_NE(CreateCsr<RiscVSimpleCsr<T>>(
                state, csr_vec, "ustatus", RiscVCsrEnum::kUStatus, 0,
diff --git a/riscv/riscv_top.cc b/riscv/riscv_top.cc
index ab18240..17885c7 100644
--- a/riscv/riscv_top.cc
+++ b/riscv/riscv_top.cc
@@ -144,7 +144,7 @@
         << "Failed to register opcode counter";
   }
 
-  // Connect counters to minstret(h) and mcycle(h) CSRs.
+  // Connect counters to instret(h) and mcycle(h) CSRs.
   auto csr_res = state_->csr_set()->GetCsr("minstret");
   CHECK_OK(csr_res.status()) << "Failed to get minstret CSR";
   if (state_->xlen() == RiscVXlen::RV32) {
@@ -169,13 +169,11 @@
         reinterpret_cast<RiscVCounterCsrHigh<RiscVState> *>(csr_res.value());
     mcycleh->set_counter(&counter_num_cycles_);
   } else {
-    // Minstret.
-    csr_res = state_->csr_set()->GetCsr("minstret");
+    // Minstret/minstreth.
     auto *minstret = reinterpret_cast<RiscVCounterCsr<uint64_t, RiscVState> *>(
         csr_res.value());
     minstret->set_counter(&counter_num_instructions_);
-    // Mcycle
-    csr_res = state_->csr_set()->GetCsr("mcycle");
+    // Mcycle/mcycleh.
     auto *mcycle = reinterpret_cast<RiscVCounterCsr<uint64_t, RiscVState> *>(
         csr_res.value());
     mcycle->set_counter(&counter_num_cycles_);
diff --git a/riscv/test/riscv_csr_test.cc b/riscv/test/riscv_csr_test.cc
index 10801d3..1f6650a 100644
--- a/riscv/test/riscv_csr_test.cc
+++ b/riscv/test/riscv_csr_test.cc
@@ -30,7 +30,6 @@
 
 using ::mpact::sim::riscv::RiscV32SimpleCsr;
 using ::mpact::sim::riscv::RiscVCsrEnum;
-using ::mpact::sim::riscv::RiscVShadowCsr;
 using ::mpact::sim::riscv::RiscVState;
 using ::mpact::sim::riscv::RiscVXlen;
 using ::mpact::sim::util::FlatDemandMemory;
@@ -125,25 +124,4 @@
   delete csr;
 }
 
-// Test that the shadow csr constructs properly and with the expected values.
-TEST_F(RiscV32CsrTest, ShadowCsrConstruction) {
-  auto *csr0 = new RiscV32SimpleCsr(kCsrName0, RiscVCsrEnum::kMScratch,
-                                    kDeadBeef, state_);
-  EXPECT_EQ(csr0->name(), kCsrName0);
-  EXPECT_EQ(csr0->index(), static_cast<int>(RiscVCsrEnum::kMScratch));
-
-  auto *csr1 = new RiscVShadowCsr<uint32_t>(
-      kCsrName1, RiscVCsrEnum::kUScratch, kReadMask, kWriteMask, state_, csr0);
-  EXPECT_EQ(csr1->name(), kCsrName1);
-  EXPECT_EQ(csr1->index(), static_cast<int>(RiscVCsrEnum::kUScratch));
-  EXPECT_EQ(csr1->read_mask(), kReadMask);
-  EXPECT_EQ(csr1->write_mask(), kWriteMask);
-
-  EXPECT_EQ(csr1->AsUint32(), csr0->AsUint32() & kReadMask);
-  csr1->Write(kAllOnes);
-  EXPECT_EQ(csr0->AsUint32(), kDeadBeef | (kAllOnes & kWriteMask));
-  delete csr0;
-  delete csr1;
-}
-
 }  // namespace