| /* |
| * Copyright 2023 Google LLC |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef MPACT_SIM_CODELABS_OTHER_RV32I_TOP_H_ |
| #define MPACT_SIM_CODELABS_OTHER_RV32I_TOP_H_ |
| |
| #include <string> |
| |
| #include "absl/status/status.h" |
| #include "absl/synchronization/notification.h" |
| #include "mpact/sim/generic/component.h" |
| #include "mpact/sim/generic/core_debug_interface.h" |
| #include "mpact/sim/generic/decode_cache.h" |
| #include "mpact/sim/util/memory/flat_demand_memory.h" |
| #include "mpact/sim/util/memory/memory_interface.h" |
| #include "mpact/sim/util/memory/memory_watcher.h" |
| #include "other/riscv_simple_state.h" |
| #include "riscv/riscv32_htif_semihost.h" |
| #include "riscv/riscv_action_point.h" |
| #include "riscv/riscv_breakpoint.h" |
| #include "riscv/riscv_register.h" |
| #include "riscv_full_decoder/solution/riscv32_decoder.h" |
| #include "riscv_isa_decoder/solution/riscv32i_enums.h" |
| |
| namespace mpact { |
| namespace sim { |
| namespace codelab { |
| |
| using riscv::RiscV32HtifSemiHost; |
| using riscv::RiscVBreakpointManager; |
| using riscv::RiscVActionPointManager; |
| using riscv::RiscVState; |
| using riscv::RV32Register; |
| |
| // Top level class for the RiscV32G simulator. This is the main interface for |
| // interacting and controlling execution of programs running on the simulator. |
| // This class brings together the decoder, the architecture state, and control. |
| class RV32ITop : public generic::Component, public generic::CoreDebugInterface { |
| public: |
| using RunStatus = generic::CoreDebugInterface::RunStatus; |
| using HaltReasonValueType = generic::CoreDebugInterface::HaltReasonValueType; |
| using SemiHostAddresses = RiscV32HtifSemiHost::SemiHostAddresses; |
| |
| explicit RV32ITop(std::string name); |
| ~RV32ITop() override; |
| |
| // Methods inherited from CoreDebugInterface. |
| absl::Status Halt() override; |
| absl::StatusOr<int> Step(int num) override; |
| absl::Status Run() override; |
| absl::Status Wait() override; |
| |
| absl::StatusOr<RunStatus> GetRunStatus() override; |
| absl::StatusOr<HaltReasonValueType> GetLastHaltReason() override; |
| |
| absl::StatusOr<uint64_t> ReadRegister(const std::string &name) override; |
| absl::Status WriteRegister(const std::string &name, uint64_t value) override; |
| absl::StatusOr<generic::DataBuffer *> GetRegisterDataBuffer( |
| const std::string &name) override; |
| // Read and Write memory methods bypass any semihosting. |
| absl::StatusOr<size_t> ReadMemory(uint64_t address, void *buf, |
| size_t length) override; |
| absl::StatusOr<size_t> WriteMemory(uint64_t address, const void *buf, |
| size_t length) override; |
| |
| bool HasBreakpoint(uint64_t address) override; |
| absl::Status SetSwBreakpoint(uint64_t address) override; |
| absl::Status ClearSwBreakpoint(uint64_t address) override; |
| absl::Status ClearAllSwBreakpoints() override; |
| |
| absl::StatusOr<Instruction *>GetInstruction(uint64_t address) override; |
| |
| absl::StatusOr<std::string> GetDisassembly(uint64_t address) override; |
| |
| // Set up semihosting with the given magic addresses. |
| absl::Status SetUpSemiHosting(const SemiHostAddresses &magic); |
| |
| // Accessors. |
| RiscVState *state() const { return state_; } |
| util::MemoryInterface *memory() const { return memory_; } |
| |
| private: |
| // Called when a halt is requested. |
| void RequestHalt(HaltReason halt_reason, const Instruction *inst); |
| |
| uint32_t previous_pc_; |
| // The DB factory is used to manage data buffers for memory read/writes. |
| generic::DataBufferFactory db_factory_; |
| // Current status and last halt reasons. |
| RunStatus run_status_ = RunStatus::kHalted; |
| HaltReason halt_reason_ = HaltReason::kNone; |
| // Halting flag. This is set to true when execution must halt. |
| bool halted_ = false; |
| absl::Notification *run_halted_ = nullptr; |
| // The local RiscV32 state. |
| RiscVState *state_; |
| // Semihosting class. |
| RiscV32HtifSemiHost *rv32_semihost_ = nullptr; |
| // Action point manager. |
| RiscVActionPointManager *rv_ap_manager_ = nullptr; |
| // Breakpoint manager. |
| RiscVBreakpointManager *rv_bp_manager_ = nullptr; |
| // The pc register instance. |
| RV32Register *pc_; |
| // RiscV32 decoder instance. |
| RiscV32Decoder *rv32_decoder_ = nullptr; |
| // Decode cache, memory and memory watcher. |
| generic::DecodeCache *rv32_decode_cache_ = nullptr; |
| util::FlatDemandMemory *memory_ = nullptr; |
| util::MemoryWatcher *watcher_ = nullptr; |
| // Counter for the number of instructions simulated. |
| generic::SimpleCounter<uint64_t> |
| counter_opcode_[static_cast<int>(OpcodeEnum::kPastMaxValue)]; |
| generic::SimpleCounter<uint64_t> counter_num_instructions_; |
| }; |
| |
| } // namespace codelab |
| } // namespace sim |
| } // namespace mpact |
| |
| #endif // MPACT_SIM_CODELABS_OTHER_RV32I_TOP_H_ |