use crate::span::Span;
pub type Ident = String;
#[derive(Clone, Debug, Default)]
pub struct Netlist {
pub title: String,
pub elements: Vec<Element>,
pub models: Vec<Model>,
pub analyses: Vec<Analysis>,
pub options: Vec<Param>,
pub outputs: Vec<Output>,
pub node_inits: Vec<NodeInit>,
pub measures: Vec<Measure>,
pub control: Vec<String>,
pub width_out: Option<usize>,
}
#[derive(Clone, Debug)]
pub struct Element {
pub name: Ident,
pub nodes: Vec<Ident>,
pub device: Device,
pub span: Span,
}
#[derive(Clone, Debug)]
pub enum Device {
Resistor {
value: Option<f64>,
model: Option<Ident>,
params: Vec<Param>,
},
Capacitor {
value: Option<f64>,
model: Option<Ident>,
params: Vec<Param>,
},
Inductor {
value: Option<f64>,
params: Vec<Param>,
},
Mutual { l1: Ident, l2: Ident, k: f64 },
Source {
kind: SourceKind,
dc: Option<f64>,
ac: Option<AcSpec>,
tran: Option<TranFn>,
distof1: Option<DistoSpec>,
distof2: Option<DistoSpec>,
port: Option<RfPort>,
},
Vcvs { gain: Option<f64> },
Vccs { gain: Option<f64> },
Cccs { vname: Ident, gain: Option<f64> },
Ccvs { vname: Ident, gain: Option<f64> },
Diode {
model: Ident,
area: Option<f64>,
off: bool,
params: Vec<Param>,
},
Bjt {
model: Ident,
area: Option<f64>,
off: bool,
params: Vec<Param>,
},
Jfet {
model: Ident,
area: Option<f64>,
off: bool,
params: Vec<Param>,
},
Mesfet {
model: Ident,
area: Option<f64>,
off: bool,
params: Vec<Param>,
},
Mosfet { model: Ident, params: Vec<Param> },
SwitchV { model: Ident, state: Option<OnOff> },
SwitchI {
vname: Ident,
model: Ident,
state: Option<OnOff>,
},
TlineIdeal { params: Vec<Param> },
TlineLossy { model: Ident },
Urc { model: Ident, params: Vec<Param> },
Behavioral { kind: SourceKind, expr: Expr },
SubcktCall { subname: Ident },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SourceKind {
Voltage,
Current,
}
#[derive(Clone, Debug, PartialEq)]
pub enum Expr {
Num(f64),
V(Ident),
I(Ident),
Bin(ExprOp, Box<Expr>, Box<Expr>),
Call(ExprFunc, Box<Expr>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ExprOp {
Plus,
Minus,
Times,
Divide,
Power,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ExprFunc {
Abs,
Acos,
Acosh,
Asin,
Asinh,
Atan,
Atanh,
Cos,
Cosh,
Exp,
Ln,
Log,
Sgn,
Sin,
Sinh,
Sqrt,
Tan,
Tanh,
U,
Uramp,
Neg,
}
impl ExprFunc {
pub const TABLE: [(&'static str, ExprFunc); 20] = [
("abs", ExprFunc::Abs),
("acos", ExprFunc::Acos),
("acosh", ExprFunc::Acosh),
("asin", ExprFunc::Asin),
("asinh", ExprFunc::Asinh),
("atan", ExprFunc::Atan),
("atanh", ExprFunc::Atanh),
("cos", ExprFunc::Cos),
("cosh", ExprFunc::Cosh),
("exp", ExprFunc::Exp),
("ln", ExprFunc::Ln),
("log", ExprFunc::Log),
("sgn", ExprFunc::Sgn),
("sin", ExprFunc::Sin),
("sinh", ExprFunc::Sinh),
("sqrt", ExprFunc::Sqrt),
("tan", ExprFunc::Tan),
("tanh", ExprFunc::Tanh),
("u", ExprFunc::U),
("uramp", ExprFunc::Uramp),
];
pub fn name(self) -> &'static str {
if self == ExprFunc::Neg {
return "-";
}
Self::TABLE
.iter()
.find(|(_, f)| *f == self)
.map_or("?", |(n, _)| n)
}
}
impl Expr {
pub fn visit_refs_mut(
&mut self,
node: &mut dyn FnMut(&mut Ident),
device: &mut dyn FnMut(&mut Ident),
) {
match self {
Expr::Num(_) => {}
Expr::V(n) => node(n),
Expr::I(d) => device(d),
Expr::Bin(_, l, r) => {
l.visit_refs_mut(node, device);
r.visit_refs_mut(node, device);
}
Expr::Call(_, a) => a.visit_refs_mut(node, device),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum OnOff {
On,
Off,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct AcSpec {
pub mag: f64,
pub phase: f64,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct RfPort {
pub num: u32,
pub z0: f64,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct DistoSpec {
pub mag: f64,
pub phase: f64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct TranFn {
pub kind: TranFnKind,
pub args: Vec<f64>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TranFnKind {
Pulse,
Sin,
Exp,
Pwl,
Sffm,
TrNoise,
TrRandom,
}
#[derive(Clone, Debug)]
pub struct Param {
pub name: Ident,
pub value: ParamValue,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub enum ParamValue {
Flag,
Num(f64),
NumList(Vec<f64>),
Str(String),
}
#[derive(Clone, Debug)]
pub struct Model {
pub name: Ident,
pub mtype: Ident,
pub params: Vec<Param>,
pub span: Span,
}
#[derive(Clone, Debug)]
pub enum Analysis {
Op { span: Span },
Dc { sweeps: Vec<DcSweep>, span: Span },
Ac {
variation: Variation,
points: f64,
fstart: f64,
fstop: f64,
span: Span,
},
Tran {
tstep: f64,
tstop: f64,
tstart: Option<f64>,
tmax: Option<f64>,
uic: bool,
span: Span,
},
Pz {
nodes: [Ident; 4],
input: PzInput,
which: PzWhich,
span: Span,
},
Noise {
output: Ident,
output_ref: Option<Ident>,
src: Ident,
variation: Variation,
points: f64,
fstart: f64,
fstop: f64,
pts_per_summary: Option<f64>,
span: Span,
},
Disto {
variation: Variation,
points: f64,
fstart: f64,
fstop: f64,
f2overf1: Option<f64>,
span: Span,
},
Sens {
outvar: OutVar,
filters: Vec<Ident>,
ac: Option<(Variation, f64, f64, f64)>,
span: Span,
},
Sp {
variation: Variation,
points: f64,
fstart: f64,
fstop: f64,
donoise: bool,
span: Span,
},
Pss {
freq: f64,
tstab: f64,
osc_node: Ident,
points: Option<f64>,
harmonics: Option<f64>,
sc_iter: Option<f64>,
steady_coeff: Option<f64>,
uic: bool,
span: Span,
},
Tf {
outvar: OutVar,
insrc: Ident,
span: Span,
},
}
#[derive(Clone, Debug)]
pub struct DcSweep {
pub src: Ident,
pub start: f64,
pub stop: f64,
pub step: f64,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Variation {
Dec,
Oct,
Lin,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PzInput {
Current,
Voltage,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PzWhich {
Poles,
Zeros,
Both,
}
#[derive(Clone, Debug)]
pub struct Output {
pub kind: OutputKind,
pub analysis: Option<Ident>,
pub vars: Vec<OutVar>,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub enum OutputKind {
Print,
Plot,
Save,
Four {
freq: f64,
},
}
#[derive(Clone, Debug, PartialEq)]
pub enum OutVar {
Voltage {
node: Ident,
reference: Option<Ident>,
suffix: Option<AcSuffix>,
},
Current {
vsrc: Ident,
suffix: Option<AcSuffix>,
},
Raw(Ident),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AcSuffix {
Real,
Imag,
Mag,
Phase,
Db,
}
#[derive(Clone, Debug)]
pub struct NodeInit {
pub kind: NodeInitKind,
pub node: Ident,
pub value: f64,
pub span: Span,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum NodeInitKind {
Ic,
Nodeset,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Measure {
pub analysis: MeasAnalysis,
pub name: Ident,
pub func: MeasFunc,
pub keyword: String,
pub text: String,
pub span: Span,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MeasAnalysis {
Tran,
Ac,
Dc,
Sp,
}
impl MeasAnalysis {
pub fn keyword(self) -> &'static str {
match self {
MeasAnalysis::Tran => "tran",
MeasAnalysis::Ac => "ac",
MeasAnalysis::Dc => "dc",
MeasAnalysis::Sp => "sp",
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum MeasFunc {
Delay { trig: MeasTrig, targ: MeasTrig },
When(MeasCross),
Find { var: OutVar, at: MeasPoint },
Deriv { var: OutVar, at: MeasPoint },
Stat {
stat: MeasStat,
var: OutVar,
window: MeasWindow,
},
}
#[derive(Clone, Debug, PartialEq)]
pub enum MeasTrig {
At(f64),
Cross(MeasCross),
}
#[derive(Clone, Debug, PartialEq)]
pub enum MeasPoint {
At(f64),
When(MeasCross),
}
#[derive(Clone, Debug, PartialEq)]
pub struct MeasCross {
pub var: OutVar,
pub level: MeasLevel,
pub edge: MeasEdge,
pub window: MeasWindow,
}
#[derive(Clone, Debug, PartialEq)]
pub enum MeasLevel {
Value(f64),
Var(OutVar),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MeasEdge {
Any,
Rise(MeasCount),
Fall(MeasCount),
Cross(MeasCount),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MeasCount {
Nth(u32),
Last,
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct MeasWindow {
pub td: Option<f64>,
pub from: Option<f64>,
pub to: Option<f64>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MeasStat {
Min,
Max,
MinAt,
MaxAt,
Pp,
Avg,
Rms,
Integ,
}