| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| use std::collections::HashMap; |
| use std::fmt; |
| use std::path::PathBuf; |
| |
| use anyhow::Result; |
| use serde::{Deserialize, Serialize}; |
| use thiserror::Error; |
| |
| use crate::impl_serializable_error; |
| |
| /// Error related to the `Emulator` trait. |
| #[derive(Error, Debug, Serialize, Deserialize)] |
| pub enum EmuError { |
| #[error("Invalid argument name: {0}")] |
| InvalidArgumetName(String), |
| #[error("Argument name: {0} has invalid value: {1}")] |
| InvalidArgumentValue(String, String), |
| #[error("Start failed with cause: {0}")] |
| StartFailureCause(String), |
| #[error("Stop failed with cause: {0}")] |
| StopFailureCause(String), |
| #[error("Can't restore resource to initial state: {0}")] |
| ResetError(String), |
| #[error("Runtime error: {0}")] |
| RuntimeError(String), |
| } |
| impl_serializable_error!(EmuError); |
| |
| #[derive(Debug, Clone, Serialize, Deserialize)] |
| pub enum EmuValue { |
| Empty, |
| String(String), |
| FilePath(PathBuf), |
| StringList(Vec<String>), |
| FilePathList(Vec<PathBuf>), |
| } |
| |
| impl From<String> for EmuValue { |
| fn from(s: String) -> Self { |
| EmuValue::String(s) |
| } |
| } |
| |
| impl From<Vec<String>> for EmuValue { |
| fn from(str_array: Vec<String>) -> Self { |
| EmuValue::StringList(str_array) |
| } |
| } |
| |
| impl From<PathBuf> for EmuValue { |
| fn from(p: PathBuf) -> Self { |
| EmuValue::FilePath(p) |
| } |
| } |
| |
| impl From<Vec<PathBuf>> for EmuValue { |
| fn from(path_array: Vec<PathBuf>) -> Self { |
| EmuValue::FilePathList(path_array) |
| } |
| } |
| |
| impl fmt::Display for EmuValue { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| match self { |
| EmuValue::Empty => write!(f, " "), |
| EmuValue::String(value) => write!(f, "{}", value), |
| EmuValue::FilePath(value) => write!(f, "{}", value.display()), |
| EmuValue::StringList(value_list) => write!(f, "{}", value_list.join(",")), |
| EmuValue::FilePathList(value_list) => { |
| for item in value_list.iter() { |
| write!(f, "{} ", item.display())?; |
| } |
| Ok(()) |
| } |
| } |
| } |
| } |
| |
| #[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize)] |
| pub enum EmuState { |
| Off, |
| On, |
| Busy, |
| Error, |
| } |
| |
| impl fmt::Display for EmuState { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| match self { |
| EmuState::Off => write!(f, "Off"), |
| EmuState::On => write!(f, "On"), |
| EmuState::Busy => write!(f, "Busy"), |
| EmuState::Error => write!(f, "Error"), |
| } |
| } |
| } |
| |
| /// A trait which represents a `Emulator` instance |
| pub trait Emulator { |
| /// Simple function with return `EmuState` representing current state of Emulator instance. |
| fn get_state(&self) -> Result<EmuState>; |
| |
| /// Start Emulator with provided arguments. |
| /// Parameter `factory_reset` is a flag that describe if internal state |
| /// and "resources" should be set to its "initial state" before applying |
| /// the changes from the parameter `args`. |
| /// If `factory_reset` is set to true - all internal state and "resources" |
| /// will be set to its "initial state". The "initial state" for most devices |
| /// means that the content is set to zero. |
| /// If `factory_reset` is set to false - all internal state will be preserved |
| /// form last run. |
| /// Parameter `args` describe set of named flags, value and resources passed |
| /// to Emulator in order to update the content of its internal state. |
| /// In the context of the function below, "resources" denote files |
| /// representing the state of devices, for example: EEPROM, FUSES, FLASH, SRAM... |
| /// (most often binary files). Resources files sent via parameter `args` |
| /// cannot be modified by the Emulator directly, the Emulator backend should have |
| /// copy-on-write implementations to enable resource modification during DUT Emulation. |
| /// It should be noted that the method of resources interpretation |
| /// and their format depends on the backend implementing the Emulator trait. |
| /// More detail about supported `args` value and its content can be found |
| /// in the documentation of individual backend. |
| fn start(&self, factory_reset: bool, args: &HashMap<String, EmuValue>) -> Result<()>; |
| |
| /// Stop emulator instance. |
| fn stop(&self) -> Result<()>; |
| } |