blob: fa8df28efffb30e4a3169bb3664f36a03af72a2f [file] [log] [blame]
// 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<()>;
}