blob: b132e4e710ded94c1d4ebd8d1ef5df8fc2552dfb [file]
/*
* 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_