1mod aliasing;
2mod assertion_codegen;
3pub mod codegen;
4pub mod diff;
5pub mod diff_printing;
6mod enum_util;
7pub mod eval;
8pub mod macros;
9pub mod passes;
10pub mod renaming;
11mod type_list;
12pub mod types;
13pub mod unit_name;
14pub mod verilator_wrapper;
15mod verilog;
16mod wal;
17
18use derive_where::derive_where;
19use itertools::Itertools;
20use num::{BigInt, BigUint};
21use renaming::VerilogNameSource;
22use serde::{Deserialize, Serialize};
23use spade_common::id_tracker::ExprID;
24use types::Type;
25
26use spade_common::location_info::Loc;
27use spade_common::name::NameID;
28use spade_common::num_ext::InfallibleToBigInt;
29
30pub use unit_name::UnitName;
31
32#[derive(Clone, PartialEq, Debug, Eq, Hash)]
33pub enum ConstantValue {
34 Int(BigInt),
35 Bool(bool),
36 String(String),
37 HighImp,
38}
39
40impl ConstantValue {
41 pub fn int(val: i32) -> Self {
42 Self::Int(val.to_bigint())
43 }
44}
45
46impl std::fmt::Display for ConstantValue {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 match self {
49 ConstantValue::Int(val) => write!(f, "{val}"),
50 ConstantValue::Bool(val) => write!(f, "{val}"),
51 ConstantValue::String(val) => write!(f, "{val:?}"),
52 ConstantValue::HighImp => write!(f, "HIGHIMP"),
53 }
54 }
55}
56
57#[derive(Clone, PartialEq, Debug, Hash, Eq, serde::Serialize, serde::Deserialize)]
58pub enum ValueNameSource {
59 Name(NameID),
60 Expr(ExprID),
61}
62
63impl From<NameID> for ValueNameSource {
64 fn from(value: NameID) -> Self {
65 (&value).into()
66 }
67}
68
69impl From<&NameID> for ValueNameSource {
70 fn from(value: &NameID) -> Self {
71 Self::Name(value.clone())
72 }
73}
74
75impl From<&ValueName> for ValueNameSource {
76 fn from(value: &ValueName) -> Self {
77 match value {
78 ValueName::Named(_, _, source) => source.clone(),
79 ValueName::Expr(id) => Self::Expr(*id),
80 }
81 }
82}
83
84#[derive(Clone, Debug, Serialize, Deserialize)]
87#[derive_where(Hash, Eq, PartialEq)]
88pub enum ValueName {
89 Named(
91 u64,
93 String,
96 #[derive_where(skip)] ValueNameSource,
99 ),
100 Expr(ExprID),
103}
104
105impl ValueName {
106 pub fn verilog_name_source_fwd(&self) -> VerilogNameSource {
107 match self {
108 ValueName::Named(_, _, ValueNameSource::Name(name_id)) => {
109 VerilogNameSource::ForwardName(name_id.clone())
110 }
111 ValueName::Named(_, _, ValueNameSource::Expr(id)) | ValueName::Expr(id) => {
112 VerilogNameSource::ForwardExpr(*id)
113 }
114 }
115 }
116
117 pub fn verilog_name_source_back(&self) -> VerilogNameSource {
118 match self {
119 ValueName::Named(_, _, ValueNameSource::Name(name_id)) => {
120 VerilogNameSource::BackwardName(name_id.clone())
121 }
122 ValueName::Named(_, _, ValueNameSource::Expr(id)) | ValueName::Expr(id) => {
123 VerilogNameSource::BackwardExpr(*id)
124 }
125 }
126 }
127
128 pub fn _test_named(id: u64, name: String) -> Self {
129 use spade_common::name::Path;
130
131 Self::Named(
132 id,
133 name.clone(),
134 NameID(id, Path::from_strs(&[name.as_str()])).into(),
135 )
136 }
137}
138
139impl std::fmt::Display for ValueName {
140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 match self {
142 ValueName::Named(id, s, _) => {
143 if *id == 0 && s != "new" {
148 write!(f, "{s}")
149 } else {
150 write!(f, "{s}_n{id}")
151 }
152 }
153 ValueName::Expr(id) => write!(f, "e{}", id.0),
154 }
155 }
156}
157
158#[derive(Clone, PartialEq, Eq, Hash, Debug)]
159pub struct ParamName {
160 pub name: String,
161 pub no_mangle: Option<Loc<()>>,
162}
163
164#[derive_where(PartialEq, Eq, Hash)]
165#[derive(Clone, Debug)]
166pub enum Operator {
167 Add,
169 UnsignedAdd,
170 Sub,
171 UnsignedSub,
172 Mul,
173 UnsignedMul,
174 Div,
175 UnsignedDiv,
176 Mod,
177 UnsignedMod,
178 Eq,
179 NotEq,
180 Gt,
181 UnsignedGt,
182 Lt,
183 UnsignedLt,
184 Ge,
185 UnsignedGe,
186 Le,
187 UnsignedLe,
188 LeftShift,
189 RightShift,
190 ArithmeticRightShift,
191 LogicalAnd,
192 LogicalOr,
193 LogicalXor,
194 LogicalNot,
195 BitwiseAnd,
196 BitwiseOr,
197 BitwiseXor,
198 ReduceAnd,
199 ReduceOr,
200 ReduceXor,
201 USub,
202 Not,
203 ReadPort,
204 ReadWriteInOut,
205 BitwiseNot,
206 DivPow2,
208 SignExtend,
210 ZeroExtend,
211 Truncate,
214 Concat,
216 Select,
218 Match,
224 ConstructArray,
226 DeclClockedMemory {
230 initial: Option<Vec<Vec<Statement>>>,
232 },
233 IndexArray,
234 IndexMemory,
235 RangeIndexArray {
237 start: BigUint,
238 end_exclusive: BigUint,
239 },
240 RangeIndexBits {
243 start: BigUint,
244 end_exclusive: BigUint,
245 },
246 ConstructTuple,
248 ConstructEnum {
250 variant: usize,
251 },
252 IsEnumVariant {
254 variant: usize,
255 },
256 EnumMember {
258 variant: usize,
259 member_index: usize,
260 },
261 IndexTuple(u64),
264
265 FlipPort,
268
269 ReadMutWires,
278
279 Instance {
286 name: UnitName,
287 params: Vec<(String, ConstantValue)>,
288 argument_names: Vec<ParamName>,
292 #[derive_where(skip)]
293 loc: Option<Loc<()>>,
294 },
295 Alias,
297 Nop,
299}
300
301impl Operator {
302 pub fn simple_instance(name: UnitName, argument_names: Vec<&str>) -> Self {
303 Self::Instance {
304 name,
305 params: Vec::default(),
306 argument_names: argument_names
307 .iter()
308 .map(|p| ParamName {
309 name: p.to_string(),
310 no_mangle: None,
311 })
312 .collect(),
313 loc: None,
314 }
315 }
316}
317
318impl std::fmt::Display for Operator {
319 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
320 match self {
321 Operator::Add => write!(f, "Add"),
322 Operator::UnsignedAdd => write!(f, "UnsignedAdd"),
323 Operator::Sub => write!(f, "Sub"),
324 Operator::UnsignedSub => write!(f, "UnsignedSub"),
325 Operator::Mul => write!(f, "Mul"),
326 Operator::UnsignedMul => write!(f, "UnsignedMul"),
327 Operator::Div => write!(f, "Div"),
328 Operator::UnsignedDiv => write!(f, "UnsignedDiv"),
329 Operator::Mod => write!(f, "Mod"),
330 Operator::UnsignedMod => write!(f, "UnsignedMod"),
331 Operator::Eq => write!(f, "Eq"),
332 Operator::NotEq => write!(f, "NotEq"),
333 Operator::Gt => write!(f, "Gt"),
334 Operator::UnsignedGt => write!(f, "UnsignedGt"),
335 Operator::Lt => write!(f, "Lt"),
336 Operator::UnsignedLt => write!(f, "UnsignedLt"),
337 Operator::Ge => write!(f, "Ge"),
338 Operator::UnsignedGe => write!(f, "UnsignedGe"),
339 Operator::Le => write!(f, "Le"),
340 Operator::UnsignedLe => write!(f, "UnsignedLe"),
341 Operator::RightShift => write!(f, "RightShift"),
342 Operator::ArithmeticRightShift => write!(f, "ArithmeticRightShift"),
343 Operator::LogicalAnd => write!(f, "LogicalAnd"),
344 Operator::LogicalOr => write!(f, "LogicalOr"),
345 Operator::LogicalXor => write!(f, "LogicalXor"),
346 Operator::LogicalNot => write!(f, "LogicalNot"),
347 Operator::BitwiseAnd => write!(f, "BitwiseAnd"),
348 Operator::BitwiseOr => write!(f, "BitwiseOr"),
349 Operator::BitwiseNot => write!(f, "BitwiseNot"),
350 Operator::BitwiseXor => write!(f, "BitwiseXor"),
351 Operator::ReduceAnd => write!(f, "ReduceAnd"),
352 Operator::ReduceOr => write!(f, "ReduceOr"),
353 Operator::ReduceXor => write!(f, "ReduceXor"),
354 Operator::USub => write!(f, "USub"),
355 Operator::Not => write!(f, "Not"),
356 Operator::Select => write!(f, "Select"),
357 Operator::Match => write!(f, "Match"),
358 Operator::LeftShift => write!(f, "LeftShift"),
359 Operator::DivPow2 => write!(f, "DivPow2"),
360 Operator::SignExtend => write!(f, "SignExtend"),
361 Operator::ZeroExtend => write!(f, "ZeroExtend"),
362 Operator::Truncate => write!(f, "Truncate"),
363 Operator::Concat => write!(f, "Concat"),
364 Operator::ConstructEnum { variant } => write!(f, "ConstructEnum({})", variant),
365 Operator::IsEnumVariant { variant } => write!(f, "IsEnumVariant({})", variant),
366 Operator::EnumMember {
367 variant,
368 member_index,
369 } => write!(f, "EnumMember({} {})", variant, member_index),
370 Operator::ConstructTuple => write!(f, "ConstructTuple"),
371 Operator::ConstructArray => write!(f, "ConstructArray"),
372 Operator::DeclClockedMemory { initial } => write!(
373 f,
374 "DeclClockedMemory({})",
375 if let Some(values) = initial {
376 format!(
377 "[{}]",
378 values
379 .iter()
380 .map(|v| format!("[{}]", v.iter().map(|v| format!("{v}")).join(", ")))
381 .join(", ")
382 )
383 } else {
384 "None".to_owned()
385 }
386 ),
387 Operator::IndexArray => write!(f, "IndexArray"),
388 Operator::IndexTuple(idx) => write!(f, "IndexTuple({})", idx),
389 Operator::RangeIndexArray {
390 start,
391 end_exclusive: end,
392 } => write!(f, "RangeIndexArray({start}, {end})"),
393 Operator::RangeIndexBits {
394 start,
395 end_exclusive: end,
396 } => write!(f, "RangeIndexBits({start}, {end})"),
397 Operator::IndexMemory => write!(f, "IndexMemory"),
398 Operator::Instance { name, .. } => write!(f, "Instance({})", name.as_verilog()),
399 Operator::Alias => write!(f, "Alias"),
400 Operator::FlipPort => write!(f, "FlipPort"),
401 Operator::ReadMutWires => write!(f, "ReadMutWires"),
402 Operator::Nop => write!(f, "Nop"),
403 Operator::ReadPort => write!(f, "ReadPort"),
404 Operator::ReadWriteInOut => write!(f, "ReadWriteInOut"),
405 }
406 }
407}
408
409#[derive(Clone, PartialEq, Eq, Hash, Debug)]
410pub struct Binding {
411 pub name: ValueName,
412 pub operator: Operator,
413 pub operands: Vec<ValueName>,
414 pub ty: Type,
415 pub loc: Option<Loc<()>>,
416}
417
418impl std::fmt::Display for Binding {
419 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
420 let Binding {
421 name,
422 operator,
423 operands,
424 ty,
425 loc: _,
426 } = self;
427 write!(
428 f,
429 "let {name}: {ty} = {operator}({})",
430 operands.iter().map(|op| format!("{op}")).join(", ")
431 )
432 }
433}
434
435#[derive(Clone, PartialEq, Eq, Hash, Debug)]
436pub struct Register {
437 pub name: ValueName,
438 pub ty: Type,
439 pub clock: ValueName,
440 pub reset: Option<(ValueName, ValueName)>,
441 pub initial: Option<Vec<Statement>>,
442 pub value: ValueName,
443 pub loc: Option<Loc<()>>,
444 pub traced: Option<ValueName>,
447}
448
449impl std::fmt::Display for Register {
450 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
451 let Register {
452 name,
453 ty,
454 clock,
455 reset,
456 initial,
457 value,
458 loc: _,
459 traced: _,
460 } = self;
461
462 let reset = reset
463 .as_ref()
464 .map(|(trig, val)| format!("({trig}, {val})"))
465 .unwrap_or_else(String::new);
466
467 let initial = initial
468 .as_ref()
469 .map(|i| format!("initial({})", i.iter().map(|s| format!("{s}")).join("; ")))
470 .unwrap_or_else(String::new);
471
472 write!(f, "reg({clock}) {name}: {ty}{reset}{initial} = {value}")
473 }
474}
475
476#[derive(Clone, PartialEq, Eq, Hash, Debug)]
477pub enum Statement {
478 Binding(Binding),
479 Register(Register),
480 Constant(ExprID, Type, ConstantValue),
482 Assert(Loc<ValueName>),
483 Set {
484 target: Loc<ValueName>,
485 value: Loc<ValueName>,
486 },
487 WalTrace {
503 name: ValueName,
504 val: ValueName,
505 suffix: String,
506 ty: Type,
507 },
508 Error,
509}
510
511impl std::fmt::Display for Statement {
512 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
513 match self {
514 Statement::Binding(b) => write!(f, "{b}"),
515 Statement::Register(r) => write!(f, "{r}"),
516 Statement::Constant(id, ty, val) => write!(f, "const e{id}: {ty} = {val}", id = id.0),
517 Statement::Assert(val) => write!(f, "assert {val}"),
518 Statement::Set { target, value } => write!(f, "set {target} = {value}"),
519 Statement::WalTrace {
520 name,
521 val,
522 suffix,
523 ty: _,
524 } => write!(f, "wal_trace({name}, {val}, {suffix})"),
525 Statement::Error => write!(f, "Error"),
526 }
527 }
528}
529
530#[derive(Clone, PartialEq, Debug)]
531pub struct MirInput {
532 pub name: String,
533 pub val_name: ValueName,
534 pub ty: Type,
535 pub no_mangle: Option<Loc<()>>,
536}
537#[derive(Clone, PartialEq, Debug)]
538pub struct Entity {
539 pub name: UnitName,
541 pub inputs: Vec<MirInput>,
543 pub output: ValueName,
544 pub output_type: Type,
545 pub verilog_attr_groups: Vec<Vec<(String, Option<String>)>>,
546 pub statements: Vec<Statement>,
547}
548
549impl std::fmt::Display for Entity {
550 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
551 let Entity {
552 name,
553 inputs,
554 output,
555 output_type,
556 statements,
557 verilog_attr_groups,
558 } = self;
559
560 let inputs = inputs
561 .iter()
562 .map(
563 |MirInput {
564 name,
565 val_name,
566 ty,
567 no_mangle,
568 }| {
569 format!(
570 "({}{name}, {val_name}, {ty})",
571 no_mangle.map(|_| "#[no_mangle]").unwrap_or("")
572 )
573 },
574 )
575 .join(", ");
576
577 let statements = statements.iter().map(|s| format!("\t{s}\n")).join("");
578
579 for attrs in verilog_attr_groups {
580 let contents = attrs
581 .iter()
582 .map(|(key, value)| match value {
583 Some(v) => format!("{key} = {v:?}"),
584 None => key.clone(),
585 })
586 .join(",");
587
588 writeln!(f, "#[verilog_attrs({contents})]")?;
589 }
590
591 writeln!(
592 f,
593 "entity {name}({inputs}) -> {output_type} {{",
594 name = name.as_verilog()
595 )?;
596 write!(f, "{statements}")?;
597 write!(f, "}} => {output}")
598 }
599}