| /* |
| * Copyright 2024 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_CHERIOT__CHERIOT_CLI_FORWARDER_H_ |
| #define MPACT_CHERIOT__CHERIOT_CLI_FORWARDER_H_ |
| |
| #include <cstddef> |
| #include <cstdint> |
| #include <string> |
| |
| #include "absl/functional/any_invocable.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "cheriot/cheriot_debug_interface.h" |
| #include "cheriot/cheriot_renode_cli_top.h" |
| #include "cheriot/cheriot_state.h" |
| #include "mpact/sim/generic/core_debug_interface.h" |
| #include "mpact/sim/util/renode/cli_forwarder.h" |
| |
| // This file defines a class that forwards calls from the CLI to the class that |
| // merges requests from the CLI and ReNode. |
| |
| namespace mpact { |
| namespace sim { |
| namespace cheriot { |
| |
| using ::mpact::sim::generic::AccessType; |
| using ::mpact::sim::util::renode::CLIForwarder; |
| |
| class CheriotCLIForwarder : public CheriotDebugInterface { |
| public: |
| explicit CheriotCLIForwarder(CheriotRenodeCLITop *top); |
| CheriotCLIForwarder() = delete; |
| CheriotCLIForwarder(const CLIForwarder &) = delete; |
| CheriotCLIForwarder &operator=(const CLIForwarder &) = delete; |
| |
| absl::StatusOr<size_t> ReadTagMemory(uint64_t address, void *buf, |
| size_t length) override; |
| // Set a data watchpoint for the given memory range. Any access matching the |
| // given access type (load/store) will halt execution following the completion |
| // of that access. |
| absl::Status SetDataWatchpoint(uint64_t address, size_t length, |
| AccessType access_type) override; |
| // Clear data watchpoint for the given memory address and access type. |
| absl::Status ClearDataWatchpoint(uint64_t address, |
| AccessType access_type) override; |
| |
| // Set an action point at the given address to execute the specified action. |
| absl::StatusOr<int> SetActionPoint( |
| uint64_t address, |
| absl::AnyInvocable<void(uint64_t, int)> action) override; |
| // Clear action point id at the given address. |
| absl::Status ClearActionPoint(uint64_t address, int id) override; |
| // Enable/disable action id at the given address. |
| absl::Status EnableAction(uint64_t address, int id) override; |
| absl::Status DisableAction(uint64_t address, int id) override; |
| // Enable breaking on control flow change. |
| void SetBreakOnControlFlowChange(bool value) override; |
| // Request that core stop running. |
| absl::Status Halt() override; |
| absl::Status Halt(HaltReason halt_reason) override; |
| absl::Status Halt(HaltReasonValueType halt_reason) override; |
| // Step the core by num instructions. |
| absl::StatusOr<int> Step(int num) override; |
| // Allow the core to free-run. The loop to run the instructions should be |
| // in a separate thread so that this method can return. This allows a user |
| // interface built on top of this interface to handle multiple cores running |
| // at the same time. |
| absl::Status Run() override; |
| // Wait until the current core halts execution. |
| absl::Status Wait() override; |
| |
| // Returns the current run status. |
| absl::StatusOr<RunStatus> GetRunStatus() override; |
| // Returns the reason for the most recent halt. |
| 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; |
| |
| // Some registers, including vector registers, have values that exceed the |
| // 64 bits supported in the Read/Write register API calls. This function |
| // obtains the DataBuffer structure for such registers, provided they use one. |
| // The data in the DataBuffer instance can be written as well as read. |
| // Note (1): DataBuffer instances are reference counted. If the simulator is |
| // advanced after obtaining the instance, it may become invalid if it isn't |
| // IncRef'ed appropriately (see data_buffer.h). |
| // Note (2): In some cases, a register write may replace the DataBuffer |
| // instance within a register so that any stored references to it become |
| // stale. |
| absl::StatusOr<DataBuffer *> GetRegisterDataBuffer( |
| const std::string &name) override; |
| |
| // Read/write the buffers to memory. |
| 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; |
| |
| // Test to see if there's a breakpoint at the given address. |
| bool HasBreakpoint(uint64_t address) override; |
| // Set/Clear software breakpoints at the given addresses. |
| absl::Status SetSwBreakpoint(uint64_t address) override; |
| absl::Status ClearSwBreakpoint(uint64_t address) override; |
| // Remove all software breakpoints. |
| absl::Status ClearAllSwBreakpoints() override; |
| |
| // Return the instruction object for the instruction at the given address. |
| absl::StatusOr<Instruction *> GetInstruction(uint64_t address) override; |
| // Return the string representation for the instruction at the given address. |
| absl::StatusOr<std::string> GetDisassembly(uint64_t address) override; |
| |
| private: |
| CheriotRenodeCLITop *cheriot_cli_top_; |
| }; |
| |
| } // namespace cheriot |
| } // namespace sim |
| } // namespace mpact |
| |
| #endif // MPACT_CHERIOT__CHERIOT_CLI_FORWARDER_H_ |