substrate/simulation/
mod.rs

1//! Substrate's simulation API.
2
3use std::any::Any;
4use std::path::PathBuf;
5use std::sync::Arc;
6
7use data::{Save, Saved};
8use impl_trait_for_tuples::impl_for_tuples;
9use rust_decimal::Decimal;
10use serde::{Deserialize, Serialize};
11
12use crate::block::Block;
13use crate::context::{Context, Installation};
14use crate::schematic::conv::RawLib;
15use crate::schematic::schema::Schema;
16use crate::schematic::{Cell, HasNestedView, NestedView, Schematic};
17use crate::types::TestbenchIo;
18
19pub mod data;
20pub mod options;
21pub mod waveform;
22
23/// A process-voltage-temperature corner.
24///
25/// Contains a process corner, a voltage, and a temperature (in Celsius).
26#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
27pub struct Pvt<C> {
28    /// The process corner.
29    pub corner: C,
30    /// The voltage.
31    pub voltage: Decimal,
32    /// The temperature, in degrees celsius.
33    pub temp: Decimal,
34}
35
36impl<C> Pvt<C> {
37    /// Create a new PVT corner.
38    #[inline]
39    pub fn new(corner: C, voltage: Decimal, temp: Decimal) -> Self {
40        Self {
41            corner,
42            voltage,
43            temp,
44        }
45    }
46}
47
48/// A single simulator analysis.
49pub trait Analysis {
50    /// The output produced by this analysis.
51    type Output;
52}
53
54/// A circuit simulator.
55pub trait Simulator: Installation + Any + Send + Sync {
56    /// The schema that this simulator uses.
57    type Schema: Schema;
58    /// The input type this simulator accepts.
59    type Input;
60    /// Options shared across all analyses for a given simulator run.
61    type Options;
62    /// The output type produced by this simulator.
63    type Output;
64    /// The error type returned by the simulator.
65    type Error;
66
67    /// Simulates the given set of analyses.
68    fn simulate_inputs(
69        &self,
70        ctx: &SimulationContext<Self>,
71        options: Self::Options,
72        input: Vec<Self::Input>,
73    ) -> Result<Vec<Self::Output>, Self::Error>;
74
75    /// Simulates the given, possibly composite, analysis.
76    fn simulate<A>(
77        &self,
78        ctx: &SimulationContext<Self>,
79        options: Self::Options,
80        input: A,
81    ) -> Result<A::Output, Self::Error>
82    where
83        A: SupportedBy<Self>,
84        Self: Sized,
85    {
86        let mut inputs = Vec::new();
87        input.into_input(&mut inputs);
88        let output = self.simulate_inputs(ctx, options, inputs)?;
89        let mut output = output.into_iter();
90        Ok(A::from_output(&mut output))
91    }
92}
93
94/// Substrate-defined simulation context.
95pub struct SimulationContext<S: Simulator + ?Sized> {
96    /// The simulator's intended working directory.
97    pub work_dir: PathBuf,
98    /// The SCIR library to simulate with associated Substrate metadata.
99    pub lib: Arc<RawLib<S::Schema>>,
100    /// The global context.
101    pub ctx: Context,
102}
103
104/// Indicates that a particular analysis is supported by a simulator.
105pub trait SupportedBy<S: Simulator>: Analysis {
106    /// Convert the analysis into inputs accepted by this simulator.
107    fn into_input(self, inputs: &mut Vec<<S as Simulator>::Input>);
108    /// Convert this simulator's outputs to the analysis's expected output.
109    fn from_output(outputs: &mut impl Iterator<Item = <S as Simulator>::Output>) -> Self::Output;
110}
111
112/// Controls simulation options.
113pub struct SimController<S: Simulator, T: Schematic> {
114    pub(crate) simulator: Arc<S>,
115    /// The current testbench cell.
116    pub tb: Arc<Cell<T>>,
117    pub(crate) ctx: SimulationContext<S>,
118}
119
120/// Data saved by block `T` in simulator `S` for analysis `A`.
121pub type SavedData<T, S, A> = Saved<NestedView<<T as Schematic>::NestedData>, S, A>;
122
123impl<S: Simulator, T: Testbench<S>> SimController<S, T> {
124    /// Run the given analysis, returning the default output.
125    pub fn simulate_default<A: SupportedBy<S>>(
126        &self,
127        options: S::Options,
128        input: A,
129    ) -> Result<A::Output, S::Error> {
130        self.simulator.simulate(&self.ctx, options, input)
131    }
132
133    /// Run the given analysis, returning the desired output type.
134    pub fn simulate<A: SupportedBy<S>>(
135        &self,
136        mut options: S::Options,
137        input: A,
138    ) -> Result<SavedData<T, S, A>, S::Error>
139    where
140        T: Schematic<NestedData: HasNestedView<NestedView: Save<S, A>>>,
141    {
142        let key = <NestedView<<T as Schematic>::NestedData> as Save<S, A>>::save(
143            &self.tb.data(),
144            &self.ctx,
145            &mut options,
146        );
147        let output = self.simulate_default(options, input)?;
148        Ok(
149            <<<T as Schematic>::NestedData as HasNestedView>::NestedView>::from_saved(
150                &output, &key,
151            ),
152        )
153    }
154
155    /// Set an option by mutating the given options.
156    pub fn set_option<O>(&self, opt: O, options: &mut S::Options)
157    where
158        O: options::SimOption<S>,
159    {
160        opt.set_option(options, &self.ctx);
161    }
162}
163
164/// A testbench that can be simulated.
165pub trait Testbench<S: Simulator>: Schematic<Schema = S::Schema> + Block<Io = TestbenchIo> {}
166impl<S: Simulator, T: Schematic<Schema = S::Schema> + Block<Io = TestbenchIo>> Testbench<S> for T {}
167
168#[impl_for_tuples(64)]
169impl Analysis for Tuple {
170    for_tuples!( type Output = ( #( Tuple::Output ),* ); );
171}
172
173#[impl_for_tuples(64)]
174impl<S: Simulator> SupportedBy<S> for Tuple {
175    fn into_input(self, inputs: &mut Vec<<S as Simulator>::Input>) {
176        for_tuples!( #( <Tuple as SupportedBy<S>>::into_input(self.Tuple, inputs); )* )
177    }
178
179    #[allow(clippy::unused_unit)]
180    fn from_output(
181        outputs: &mut impl Iterator<Item = <S as Simulator>::Output>,
182    ) -> <Self as Analysis>::Output {
183        (for_tuples!( #( <Tuple as SupportedBy<S>>::from_output(outputs) ),* ))
184    }
185}