substrate/types/
mod.rs

1//! Traits and types for defining interfaces and signals in Substrate.
2
3use std::{
4    borrow::Borrow,
5    fmt::Debug,
6    ops::{Deref, Index},
7};
8
9pub use ::codegen::{BundleKind, Io};
10use arcstr::ArcStr;
11use serde::{Deserialize, Serialize};
12
13use crate::{
14    block::Block,
15    schematic::{CellId, InstanceId, InstancePath},
16};
17
18pub use scir::Direction;
19
20#[doc(hidden)]
21pub mod codegen;
22mod impls;
23pub mod layout;
24pub mod schematic;
25#[cfg(test)]
26mod tests;
27
28/// The [`BundleKind`] of a block's IO.
29pub type IoKind<T> = <<T as Block>::Io as HasBundleKind>::BundleKind;
30
31// BEGIN TRAITS
32
33/// The length of the flattened list.
34pub trait FlatLen {
35    /// The length of the flattened list.
36    fn len(&self) -> usize;
37    /// Whether or not the flattened representation is empty.
38    fn is_empty(&self) -> bool {
39        self.len() == 0
40    }
41}
42
43impl<T: FlatLen> FlatLen for &T {
44    fn len(&self) -> usize {
45        (*self).len()
46    }
47}
48
49/// Flatten a structure into a list.
50pub trait Flatten<T>: FlatLen {
51    /// Flatten a structure into a list.
52    fn flatten<E>(&self, output: &mut E)
53    where
54        E: Extend<T>;
55
56    /// Flatten into a [`Vec`].
57    fn flatten_vec(&self) -> Vec<T> {
58        let len = self.len();
59        let mut vec = Vec::with_capacity(len);
60        self.flatten(&mut vec);
61        assert_eq!(
62            vec.len(),
63            len,
64            "Flatten::flatten_vec produced a Vec with an incorrect length: expected {} from FlatLen::len, got {}",
65            len,
66            vec.len()
67        );
68        vec
69    }
70}
71
72/// Unflatten a structure from an iterator.
73pub trait Unflatten<D, T>: FlatLen + Sized {
74    /// Unflatten a structure from an iterator.
75    ///
76    /// A correct implementation must only return [`None`]
77    /// if the iterator has insufficient elements.
78    /// Returning None for any other reason is a logic error.
79    /// Unsafe code should not rely on implementations of this method being correct.
80    fn unflatten<I>(data: &D, source: &mut I) -> Option<Self>
81    where
82        I: Iterator<Item = T>;
83}
84
85impl<S, T: Flatten<S>> Flatten<S> for &T {
86    fn flatten<E>(&self, output: &mut E)
87    where
88        E: Extend<S>,
89    {
90        (*self).flatten(output)
91    }
92}
93
94/// An object with named flattened components.
95pub trait HasNameTree {
96    /// Return a tree specifying how nodes contained within this type should be named.
97    ///
98    /// Important: empty types (i.e. those with a flattened length of 0) must return [`None`].
99    /// All non-empty types must return [`Some`].
100    fn names(&self) -> Option<Vec<NameTree>>;
101
102    /// Returns a flattened list of node names.
103    fn flat_names(&self, root: Option<NameFragment>) -> Vec<NameBuf> {
104        self.names()
105            .map(|t| NameTree::with_optional_fragment(root, t).flatten())
106            .unwrap_or_default()
107    }
108}
109
110/// A bundle kind.
111pub trait BundleKind:
112    FlatLen + HasNameTree + HasBundleKind<BundleKind = Self> + Debug + Clone + Eq + Send + Sync
113{
114}
115impl<T: FlatLen + HasNameTree + HasBundleKind<BundleKind = T> + Debug + Clone + Eq + Send + Sync>
116    BundleKind for T
117{
118}
119
120/// Indicates that an IO specifies signal directions for all of its fields.
121pub trait Directed: Flatten<Direction> {}
122impl<T: Flatten<Direction>> Directed for T {}
123
124/// A trait implemented by block input/output interfaces.
125pub trait Io: Directed + HasBundleKind + Clone {}
126impl<T: Directed + HasBundleKind + Clone> Io for T {}
127
128/// A construct with an associated [`BundleKind`].
129pub trait HasBundleKind: Send + Sync {
130    /// The Rust type of the [`BundleKind`] associated with this bundle.
131    type BundleKind: BundleKind;
132
133    /// Returns the [`BundleKind`] of this bundle.
134    fn kind(&self) -> Self::BundleKind;
135}
136
137impl<T: HasBundleKind> HasBundleKind for &T {
138    type BundleKind = T::BundleKind;
139
140    fn kind(&self) -> Self::BundleKind {
141        (*self).kind()
142    }
143}
144
145// END TRAITS
146
147// BEGIN TYPES
148
149/// A portion of a node name.
150#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
151pub enum NameFragment {
152    /// An element identified by a string name, such as a struct field.
153    Str(ArcStr),
154    /// A numbered element of an array/bus.
155    Idx(usize),
156}
157
158/// An owned node name, consisting of an ordered list of [`NameFragment`]s.
159#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Default, Serialize, Deserialize)]
160pub struct NameBuf {
161    fragments: Vec<NameFragment>,
162}
163
164/// A tree for hierarchical node naming.
165#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
166pub struct NameTree {
167    fragment: Option<NameFragment>,
168    children: Vec<NameTree>,
169}
170
171/// An input port of kind `T`.
172///
173/// Recursively overrides the direction of all components of `T` to be [`Input`](Direction::Input)
174#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Serialize, Deserialize)]
175pub struct Input<T>(pub T);
176
177/// An output port of kind `T`.
178///
179/// Recursively overrides the direction of all components of `T` to be [`Output`](Direction::Output)
180#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Serialize, Deserialize)]
181pub struct Output<T>(pub T);
182
183/// An inout port of kind `T`.
184///
185/// Recursively overrides the direction of all components of `T` to be [`InOut`](Direction::InOut)
186#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Serialize, Deserialize)]
187pub struct InOut<T>(pub T);
188
189/// Flip the direction of all ports in `T`
190///
191/// See [`Direction::flip`]
192#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Serialize, Deserialize)]
193pub struct Flipped<T>(pub T);
194
195/// A type representing a single hardware wire in a [`BundleKind`].
196#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
197pub struct Signal;
198
199impl Signal {
200    /// Creates a new [`Signal`].
201    #[inline]
202    pub fn new() -> Self {
203        Self
204    }
205}
206
207/// An array containing some number of elements of kind `T`.
208#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
209pub struct Array<T> {
210    len: usize,
211    kind: T,
212}
213
214impl<T> Array<T> {
215    /// Create a new array of the given length and bundle kind.
216    #[inline]
217    pub fn new(len: usize, kind: T) -> Self {
218        Self { len, kind }
219    }
220
221    /// Returns if the array has length 0.
222    pub fn is_empty(&self) -> bool {
223        self.len == 0
224    }
225
226    /// Returns the number of elements in the array.
227    pub fn len(&self) -> usize {
228        self.len
229    }
230
231    /// Returns the kind of the elements in the array.
232    pub fn kind(&self) -> &T {
233        &self.kind
234    }
235}
236
237/// An instantiated array containing a fixed number of elements of `T`.
238#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
239pub struct ArrayBundle<T: HasBundleKind> {
240    elems: Vec<T>,
241    kind: T::BundleKind,
242}
243
244// END TYPES
245
246// BEGIN COMMON IO TYPES
247
248/// The interface to a standard 4-terminal MOSFET.
249#[derive(Debug, Default, Clone, Io)]
250pub struct MosIo {
251    /// The drain.
252    pub d: InOut<Signal>,
253    /// The gate.
254    pub g: Input<Signal>,
255    /// The source.
256    pub s: InOut<Signal>,
257    /// The body.
258    pub b: InOut<Signal>,
259}
260
261/// The interface to which simulation testbenches should conform.
262#[derive(Debug, Default, Clone, Io)]
263pub struct TestbenchIo {
264    /// The global ground net.
265    pub vss: InOut<Signal>,
266}
267
268/// The interface for 2-terminal blocks.
269#[derive(Debug, Default, Clone, Io)]
270pub struct TwoTerminalIo {
271    /// The positive terminal.
272    pub p: InOut<Signal>,
273    /// The negative terminal.
274    pub n: InOut<Signal>,
275}
276
277/// The interface for VDD and VSS rails.
278#[derive(Debug, Default, Clone, Io)]
279pub struct PowerIo {
280    /// The VDD rail.
281    pub vdd: InOut<Signal>,
282    /// The VSS rail.
283    pub vss: InOut<Signal>,
284}
285
286/// A pair of differential signals.
287// TODO: Create proc macro for defining un-directioned (non-IO) bundle types directly.
288#[derive(Debug, Default, Copy, Clone, Io)]
289pub struct DiffPair {
290    /// The positive signal.
291    pub p: InOut<Signal>,
292    /// The negative signal.
293    pub n: InOut<Signal>,
294}
295
296// END COMMON IO TYPES