1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
// Copyright lowRISC contributors (OpenTitan project).
// 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<()>;
}