opentitanlib/io/
emu.rs

1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5use std::collections::HashMap;
6use std::fmt;
7use std::path::PathBuf;
8
9use anyhow::Result;
10use serde::{Deserialize, Serialize};
11use thiserror::Error;
12
13use crate::impl_serializable_error;
14
15/// Error related to the `Emulator` trait.
16#[derive(Error, Debug, Serialize, Deserialize)]
17pub enum EmuError {
18    #[error("Invalid argument name: {0}")]
19    InvalidArgumetName(String),
20    #[error("Argument name: {0} has invalid value: {1}")]
21    InvalidArgumentValue(String, String),
22    #[error("Start failed with cause: {0}")]
23    StartFailureCause(String),
24    #[error("Stop failed with cause: {0}")]
25    StopFailureCause(String),
26    #[error("Can't restore resource to initial state: {0}")]
27    ResetError(String),
28    #[error("Runtime error: {0}")]
29    RuntimeError(String),
30}
31impl_serializable_error!(EmuError);
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub enum EmuValue {
35    Empty,
36    String(String),
37    FilePath(PathBuf),
38    StringList(Vec<String>),
39    FilePathList(Vec<PathBuf>),
40}
41
42impl From<String> for EmuValue {
43    fn from(s: String) -> Self {
44        EmuValue::String(s)
45    }
46}
47
48impl From<Vec<String>> for EmuValue {
49    fn from(str_array: Vec<String>) -> Self {
50        EmuValue::StringList(str_array)
51    }
52}
53
54impl From<PathBuf> for EmuValue {
55    fn from(p: PathBuf) -> Self {
56        EmuValue::FilePath(p)
57    }
58}
59
60impl From<Vec<PathBuf>> for EmuValue {
61    fn from(path_array: Vec<PathBuf>) -> Self {
62        EmuValue::FilePathList(path_array)
63    }
64}
65
66impl fmt::Display for EmuValue {
67    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68        match self {
69            EmuValue::Empty => write!(f, " "),
70            EmuValue::String(value) => write!(f, "{}", value),
71            EmuValue::FilePath(value) => write!(f, "{}", value.display()),
72            EmuValue::StringList(value_list) => write!(f, "{}", value_list.join(",")),
73            EmuValue::FilePathList(value_list) => {
74                for item in value_list.iter() {
75                    write!(f, "{} ", item.display())?;
76                }
77                Ok(())
78            }
79        }
80    }
81}
82
83#[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize)]
84pub enum EmuState {
85    Off,
86    On,
87    Busy,
88    Error,
89}
90
91impl fmt::Display for EmuState {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        match self {
94            EmuState::Off => write!(f, "Off"),
95            EmuState::On => write!(f, "On"),
96            EmuState::Busy => write!(f, "Busy"),
97            EmuState::Error => write!(f, "Error"),
98        }
99    }
100}
101
102/// A trait which represents a `Emulator` instance
103pub trait Emulator {
104    /// Simple function with return `EmuState` representing current state of Emulator instance.
105    fn get_state(&self) -> Result<EmuState>;
106
107    /// Start Emulator with provided arguments.
108    /// Parameter `factory_reset` is a flag that describe if internal state
109    /// and "resources" should be set to its "initial state" before applying
110    /// the changes from the parameter `args`.
111    /// If `factory_reset` is set to true - all internal state and "resources"
112    /// will be set to its "initial state". The "initial state" for most devices
113    /// means that the content is set to zero.
114    /// If `factory_reset` is set to false - all internal state will be preserved
115    /// form last run.
116    /// Parameter `args` describe set of named flags, value and resources passed
117    /// to Emulator in order to update the content of its internal state.
118    /// In the context of the function below, "resources" denote files
119    /// representing the state of devices, for example: EEPROM, FUSES, FLASH, SRAM...
120    /// (most often binary files). Resources files sent via parameter `args`
121    /// cannot be modified by the Emulator directly, the Emulator backend should have
122    /// copy-on-write implementations to enable resource modification during DUT Emulation.
123    /// It should be noted that the method of resources interpretation
124    /// and their format depends on the backend implementing the Emulator trait.
125    /// More detail about supported `args` value and its content can be found
126    /// in the documentation of individual backend.
127    fn start(&self, factory_reset: bool, args: &HashMap<String, EmuValue>) -> Result<()>;
128
129    /// Stop emulator instance.
130    fn stop(&self) -> Result<()>;
131}