1#![allow(dead_code)]
2use arcstr::ArcStr;
3use rust_decimal::Decimal;
4use scir::schema::StringSchema;
5use substrate::block::Block;
6use substrate::schematic::{
7 CellBuilder, HasNestedView, InstancePath, NestedData, NestedView, Schematic,
8};
9use substrate::types::schematic::{DataView, IoNodeBundle, Node, NodeBundle};
10use substrate::types::{Array, BundleKind, Flipped, InOut, Input, Io, Output, Signal};
11
12#[derive(Clone)]
13pub enum ExamplePrimitive {}
14
15#[derive(BundleKind, Clone, Default, Debug, PartialEq, Eq)]
17pub struct DiffPair {
18 pub p: Signal,
19 pub n: Signal,
20}
21#[derive(Io, Clone, Default, Debug)]
25pub struct InverterIo {
26 pub vdd: InOut<Signal>,
27 pub vss: InOut<Signal>,
28 pub din: Input<Signal>,
29 pub dout: Output<Signal>,
30}
31
32#[derive(Debug, Clone, Hash, PartialEq, Eq)]
33pub struct Inverter {
34 strength: usize,
35}
36
37impl Inverter {
39 pub fn new(strength: usize) -> Self {
40 Self { strength }
41 }
42}
43
44impl Block for Inverter {
46 type Io = InverterIo;
47
48 fn name(&self) -> arcstr::ArcStr {
49 arcstr::format!("inverter_{}", self.strength)
50 }
51
52 fn io(&self) -> Self::Io {
53 Default::default()
54 }
55}
56#[derive(Io, Clone, Copy, Default)]
60pub struct BufferIo {
61 vdd: InOut<Signal>,
62 vss: InOut<Signal>,
63 din: Input<Signal>,
64 dout: Output<Signal>,
65}
66#[derive(Debug, Clone, Hash, PartialEq, Eq)]
69pub struct Buffer {
70 strength: usize,
71}
72
73impl Buffer {
74 pub fn new(strength: usize) -> Self {
75 Self { strength }
76 }
77}
78
79impl Block for Buffer {
80 type Io = BufferIo;
81
82 fn name(&self) -> ArcStr {
83 arcstr::format!("buffer_{}", self.strength)
84 }
85
86 fn io(&self) -> Self::Io {
87 Default::default()
88 }
89}
90
91fn io() {
92 #[derive(Io, Clone, Debug)]
94 pub struct ArrayIo {
95 pub in_bus: Input<Array<Signal>>,
96 pub out_bus: Output<Array<Signal>>,
97 }
98
99 let io_type = ArrayIo {
100 in_bus: Input(Array::new(5, Signal::new())),
101 out_bus: Output(Array::new(5, Signal::new())),
102 };
103 impl ArrayIo {
107 pub fn new(in_size: usize, m: usize) -> Self {
108 Self {
109 in_bus: Input(Array::new(in_size, Signal::new())),
110 out_bus: Output(Array::new(in_size * m, Signal::new())),
111 }
112 }
113 }
114 #[derive(Io, Clone, Default, Debug)]
118 pub struct ThreePortMosIo {
119 pub d: InOut<Signal>,
120 pub g: Input<Signal>,
121 pub s: InOut<Signal>,
122 }
123
124 #[derive(Io, Clone, Default, Debug)]
125 pub struct FourPortMosIo {
126 pub d: InOut<Signal>,
127 pub g: Input<Signal>,
128 pub s: InOut<Signal>,
129 pub b: InOut<Signal>,
130 }
131 impl DataView<FourPortMosIoKind> for ThreePortMosIoKind {
135 fn view_nodes_as(nodes: &NodeBundle<Self>) -> NodeBundle<FourPortMosIoKind> {
136 NodeBundle::<FourPortMosIoKind> {
137 d: nodes.d,
138 g: nodes.g,
139 s: nodes.s,
140 b: nodes.s,
141 }
142 }
143 }
144 #[derive(Block, Debug, Copy, Clone, Hash, PartialEq, Eq)]
147 #[substrate(io = "()")]
148 pub struct ExampleBlockA;
149
150 impl Schematic for ExampleBlockA {
151 type Schema = StringSchema;
152 type NestedData = ();
153 fn schematic(
154 &self,
155 _io: &IoNodeBundle<Self>,
156 cell: &mut CellBuilder<<Self as Schematic>::Schema>,
157 ) -> substrate::error::Result<Self::NestedData> {
158 let three_port_signal = cell.signal("three_port_signal", ThreePortMosIo::default());
160 let four_port_signal = cell.signal("four_port_signal", FourPortMosIo::default());
161 cell.connect(
162 three_port_signal.view_as::<FourPortMosIo>(),
163 four_port_signal,
164 );
165 Ok(())
167 }
168 }
169
170 #[derive(BundleKind, Clone, Default, Debug, PartialEq, Eq)]
172 pub struct WithBody<T> {
173 inner: T,
174 b: Signal,
175 }
176
177 impl DataView<FourPortMosIoKind> for WithBody<ThreePortMosIoKind> {
178 fn view_nodes_as(nodes: &NodeBundle<Self>) -> NodeBundle<FourPortMosIoKind> {
179 NodeBundle::<FourPortMosIoKind> {
180 d: nodes.inner.d,
181 g: nodes.inner.g,
182 s: nodes.inner.s,
183 b: nodes.b,
184 }
185 }
186 }
187 #[derive(Block, Debug, Copy, Clone, Hash, PartialEq, Eq)]
190 #[substrate(io = "()")]
191 pub struct ExampleBlockB;
192
193 impl Schematic for ExampleBlockB {
194 type Schema = StringSchema;
195 type NestedData = ();
196 fn schematic(
197 &self,
198 _io: &IoNodeBundle<Self>,
199 cell: &mut CellBuilder<<Self as Schematic>::Schema>,
200 ) -> substrate::error::Result<Self::NestedData> {
201 let three_port_signal = cell.signal("three_port_signal", ThreePortMosIo::default());
203 let body = cell.signal("body", Signal);
204 let four_port_signal = cell.signal("four_port_signal", FourPortMosIo::default());
205 cell.connect(
206 NodeBundle::<WithBody<ThreePortMosIoKind>> {
207 inner: three_port_signal,
208 b: body,
209 }
210 .view_as::<FourPortMosIo>(),
211 four_port_signal,
212 );
213 Ok(())
215 }
216 }
217
218 mod arbitrary_connect {
219 use super::*;
220 #[derive(Io, Clone, Default, Debug)]
222 pub struct ThreePortMosIo {
223 pub d: InOut<Signal>,
224 pub g: Input<Signal>,
225 pub s: InOut<Signal>,
226 }
227
228 #[derive(Io, Clone, Default, Debug)]
229 pub struct OtherThreePortMosIo {
230 pub drain: InOut<Signal>,
231 pub gate: Input<Signal>,
232 pub source: InOut<Signal>,
233 }
234 #[derive(Block, Debug, Copy, Clone, Hash, PartialEq, Eq)]
237 #[substrate(io = "()")]
238 pub struct ExampleBlockC;
239
240 impl Schematic for ExampleBlockC {
241 type Schema = StringSchema;
242 type NestedData = ();
243 fn schematic(
244 &self,
245 _io: &IoNodeBundle<Self>,
246 cell: &mut CellBuilder<<Self as Schematic>::Schema>,
247 ) -> substrate::error::Result<Self::NestedData> {
248 let three_port_signal = cell.signal("three_port_signal", ThreePortMosIo::default());
250 let other_three_port_signal =
251 cell.signal("other_three_port_signal", OtherThreePortMosIo::default());
252 cell.connect(
253 three_port_signal.view_as::<Array<Signal>>(),
254 other_three_port_signal.view_as::<Array<Signal>>(),
255 );
256 Ok(())
258 }
259 }
260 }
261
262 #[derive(Io, Clone, Debug)]
264 pub struct SramIo {
265 pub clk: Input<Signal>,
266 pub we: Input<Signal>,
267 pub addr: Input<Array<Signal>>,
268 pub din: Input<Array<Signal>>,
269 pub dout: Output<Array<Signal>>,
270 }
271
272 pub type SramObserverIo = Input<SramIo>;
273 pub type SramDriverIo = Flipped<SramIo>;
277 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
281 pub struct Sram {
282 num_words: usize,
283 data_width: usize,
284 }
285
286 impl Block for Sram {
287 type Io = SramIo;
288
289 fn name(&self) -> ArcStr {
290 arcstr::format!("sram{}x{}", self.num_words, self.data_width)
291 }
292
293 fn io(&self) -> Self::Io {
294 Self::Io {
295 clk: Default::default(),
296 we: Default::default(),
297 addr: Input(Array::new(
298 (self.num_words - 1).ilog2() as usize + 1,
299 Signal::new(),
300 )),
301 din: Input(Array::new(self.data_width, Signal::new())),
302 dout: Output(Array::new(self.data_width, Signal::new())),
303 }
304 }
305 }
306 let _ = io_type;
309}
310
311#[derive(Io, Clone, Default, Debug)]
312pub struct VdividerIo {
313 pub vdd: InOut<Signal>,
314 pub vss: InOut<Signal>,
315 pub dout: Output<Signal>,
316}
317
318#[allow(clippy::derived_hash_with_manual_eq)]
319#[derive(Block, Debug, Copy, Clone, Hash, Eq)]
320#[substrate(io = "()")]
321pub struct Vdivider {
322 pub r1: Decimal,
324 pub r2: Decimal,
326}
327
328impl PartialEq<Self> for Vdivider {
330 fn eq(&self, other: &Self) -> bool {
331 self.r1 == other.r1
332 }
333}
334pub mod nested_data {
337 use super::*;
338 use ::scir::schema::StringSchema;
339 use substrate::schematic::Instance;
340 use substrate::types::schematic::IoNodeBundle;
341
342 #[derive(Block, Debug, Copy, Clone, Hash, PartialEq, Eq)]
343 #[substrate(io = "()")]
344 pub struct Inverter;
345
346 impl Schematic for Inverter {
347 type Schema = StringSchema;
348 type NestedData = ();
349 fn schematic(
350 &self,
351 _io: &IoNodeBundle<Self>,
352 _cell: &mut CellBuilder<<Self as Schematic>::Schema>,
353 ) -> substrate::error::Result<Self::NestedData> {
354 Ok(())
355 }
356 }
357
358 #[derive(Block, Debug, Copy, Clone, Hash, PartialEq, Eq)]
359 #[substrate(io = "()")]
360 pub struct Buffer;
361
362 #[derive(NestedData)]
364 pub struct BufferData {
365 inv1: Instance<Inverter>,
366 inv2: Instance<Inverter>,
367 x: Node,
368 }
369 #[derive(Clone, Copy)]
373 pub struct MyMetadata {
374 my_calculated_value: i64,
375 }
376
377 impl HasNestedView for MyMetadata {
378 type NestedView = Self;
379
380 fn nested_view(&self, _parent: &InstancePath) -> Self::NestedView {
381 *self
382 }
383 }
384
385 #[derive(NestedData)]
386 pub struct BufferDataWithMetadata {
387 inv1: Instance<Inverter>,
388 inv2: Instance<Inverter>,
389 metadata: MyMetadata,
390 }
391 pub struct BufferDataWithMetadataV2 {
395 inv1: Instance<Inverter>,
396 inv2: Instance<Inverter>,
397 metadata: i64,
398 }
399
400 pub struct NestedBufferDataWithMetadataV2 {
401 inv1: NestedView<Instance<Inverter>>,
402 inv2: NestedView<Instance<Inverter>>,
403 metadata: i64,
404 }
405
406 impl HasNestedView for BufferDataWithMetadataV2 {
407 type NestedView = NestedBufferDataWithMetadataV2;
408
409 fn nested_view(&self, parent: &InstancePath) -> Self::NestedView {
410 Self::NestedView {
411 inv1: self.inv1.nested_view(parent),
412 inv2: self.inv2.nested_view(parent),
413 metadata: self.metadata,
414 }
415 }
416 }
417
418 impl HasNestedView for NestedBufferDataWithMetadataV2 {
419 type NestedView = NestedBufferDataWithMetadataV2;
420
421 fn nested_view(&self, parent: &InstancePath) -> Self::NestedView {
422 Self::NestedView {
423 inv1: self.inv1.nested_view(parent),
424 inv2: self.inv2.nested_view(parent),
425 metadata: self.metadata,
426 }
427 }
428 }
429 }
431
432#[derive(Io, Clone, Default, Debug)]
433pub struct ResistorIo {
434 pub p: InOut<Signal>,
435 pub n: InOut<Signal>,
436}
437
438#[derive(Block, Debug, Copy, Clone, Hash, PartialEq, Eq)]
439#[substrate(io = "ResistorIo")]
440pub struct Resistor(Decimal);
441
442impl Resistor {
443 pub fn new(val: impl Into<Decimal>) -> Self {
444 Self(val.into())
445 }
446}
447
448mod try_data {
449 use ::scir::schema::StringSchema;
450 use substrate::types::schematic::IoNodeBundle;
451
452 use super::*;
453
454 impl Schematic for Resistor {
455 type Schema = StringSchema;
456 type NestedData = ();
457
458 fn schematic(
459 &self,
460 _io: &IoNodeBundle<Resistor>,
461 _cell: &mut super::CellBuilder<<Self as Schematic>::Schema>,
462 ) -> substrate::error::Result<Self::NestedData> {
463 Ok(())
464 }
465 }
466
467 #[derive(Block, Debug, Copy, Clone, Hash, PartialEq, Eq)]
468 #[substrate(io = "super::VdividerIo")]
469 pub struct Vdivider {
470 pub r1: Decimal,
472 pub r2: Decimal,
474 }
475
476 impl Schematic for Vdivider {
478 type Schema = StringSchema;
479 type NestedData = ();
480
481 fn schematic(
482 &self,
483 io: &IoNodeBundle<Self>,
484 cell: &mut CellBuilder<<Self as Schematic>::Schema>,
485 ) -> substrate::error::Result<Self::NestedData> {
486 let r1 = cell.instantiate(Resistor::new(self.r1));
487 let r2 = cell.instantiate(Resistor::new(self.r2));
488 r1.try_data()?;
489 r2.try_data()?;
490
491 cell.connect(io.vdd, r1.io().p);
492 cell.connect(io.dout, r1.io().n);
493 cell.connect(io.dout, r2.io().p);
494 cell.connect(io.vss, r2.io().n);
495
496 Ok(())
497 }
498 }
499 }
501
502mod instantiate_blocking {
503 use ::scir::schema::StringSchema;
504 use substrate::types::schematic::IoNodeBundle;
505
506 use super::*;
507
508 #[derive(Block, Debug, Copy, Clone, Hash, PartialEq, Eq)]
509 #[substrate(io = "super::VdividerIo")]
510 pub struct Vdivider {
511 pub r1: Decimal,
513 pub r2: Decimal,
515 }
516
517 impl Schematic for Vdivider {
519 type Schema = StringSchema;
520 type NestedData = ();
521 fn schematic(
522 &self,
523 io: &IoNodeBundle<Self>,
524 cell: &mut CellBuilder<<Self as Schematic>::Schema>,
525 ) -> substrate::error::Result<Self::NestedData> {
526 let r1 = cell.instantiate_blocking(Resistor::new(self.r1))?;
527 let r2 = cell.instantiate_blocking(Resistor::new(self.r2))?;
528
529 cell.connect(io.vdd, r1.io().p);
530 cell.connect(io.dout, r1.io().n);
531 cell.connect(io.dout, r2.io().p);
532 cell.connect(io.vss, r2.io().n);
533
534 Ok(())
535 }
536 }
537 }
539
540mod instantiate_blocking_bad {
541 use ::scir::schema::StringSchema;
542
543 use super::*;
544
545 #[derive(Block, Debug, Copy, Clone, Hash, PartialEq, Eq)]
546 #[substrate(io = "super::VdividerIo")]
547 pub struct Vdivider {
548 pub r1: Decimal,
550 pub r2: Decimal,
552 }
553
554 impl Schematic for Vdivider {
556 type Schema = StringSchema;
557 type NestedData = ();
558 fn schematic(
559 &self,
560 io: &substrate::types::schematic::IoNodeBundle<Self>,
561 cell: &mut CellBuilder<<Self as Schematic>::Schema>,
562 ) -> substrate::error::Result<Self::NestedData> {
563 if let Ok(r1) = cell.instantiate_blocking(Resistor::new(self.r1)) {
564 cell.connect(io.vdd, r1.io().p);
565 cell.connect(io.dout, r1.io().n);
566 } else {
567 cell.connect(io.vdd, io.dout);
568 }
569 let r2 = cell.instantiate_blocking(Resistor::new(self.r1))?;
570 cell.connect(io.dout, r2.io().p);
571 cell.connect(io.vss, r2.io().n);
572
573 Ok(())
574 }
575 }
576 }
578
579mod generate {
580 use ::scir::schema::StringSchema;
581 use substrate::types::schematic::IoNodeBundle;
582
583 use super::*;
584
585 #[derive(Block, Debug, Copy, Clone, Hash, PartialEq, Eq)]
586 #[substrate(io = "super::VdividerIo")]
587 pub struct Vdivider {
588 pub r1: Decimal,
590 pub r2: Decimal,
592 }
593
594 impl Schematic for Vdivider {
596 type Schema = StringSchema;
597 type NestedData = ();
598 fn schematic(
599 &self,
600 io: &IoNodeBundle<Self>,
601 cell: &mut CellBuilder<<Self as Schematic>::Schema>,
602 ) -> substrate::error::Result<Self::NestedData> {
603 let r1_cell = cell.generate(Resistor::new(self.r1));
604 let r2 = cell.instantiate_blocking(Resistor::new(self.r2))?;
605
606 if r1_cell.try_cell().is_ok() {
608 let r1 = cell.add(r1_cell);
609 cell.connect(io.vdd, r1.io().p);
610 cell.connect(io.dout, r1.io().n);
611 } else {
612 cell.connect(io.vdd, io.dout);
613 }
614
615 cell.connect(io.dout, r2.io().p);
616 cell.connect(io.vss, r2.io().n);
617
618 Ok(())
619 }
620 }
621 }
623
624mod scir_examples {
625 use scir::schema::{Schema, StringSchema};
626 use scir::{Cell, Direction, Instance, LibraryBuilder};
627 use substrate::block::Block;
628 use substrate::schematic::{CellBuilder, PrimitiveBinding, Schematic, ScirBinding};
629 use substrate::types::TwoTerminalIo;
630 use substrate::types::schematic::IoNodeBundle;
631
632 pub struct MySchema;
634
635 #[derive(Debug, Copy, Clone)]
636 pub enum MyPrimitive {
637 Resistor(i64),
638 Capacitor(i64),
639 }
640
641 impl Schema for MySchema {
642 type Primitive = MyPrimitive;
643 }
644 #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Block)]
648 #[substrate(io = "TwoTerminalIo")]
649 pub struct Resistor(i64);
650
651 impl Schematic for Resistor {
652 type Schema = MySchema;
653 type NestedData = ();
654 fn schematic(
655 &self,
656 io: &IoNodeBundle<Self>,
657 cell: &mut CellBuilder<<Self as Schematic>::Schema>,
658 ) -> substrate::error::Result<Self::NestedData> {
659 let mut prim = PrimitiveBinding::new(MyPrimitive::Resistor(self.0));
660
661 prim.connect("p", io.p);
662 prim.connect("n", io.n);
663
664 cell.set_primitive(prim);
665 Ok(())
666 }
667 }
668 #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Block)]
672 #[substrate(io = "TwoTerminalIo")]
673 pub struct ParallelResistors(i64, i64);
674
675 impl Schematic for ParallelResistors {
676 type Schema = MySchema;
677 type NestedData = ();
678 fn schematic(
679 &self,
680 io: &IoNodeBundle<Self>,
681 cell: &mut CellBuilder<<Self as Schematic>::Schema>,
682 ) -> substrate::error::Result<Self::NestedData> {
683 let mut lib = LibraryBuilder::<MySchema>::new();
685 let r1 = lib.add_primitive(MyPrimitive::Resistor(self.0));
686 let r2 = lib.add_primitive(MyPrimitive::Resistor(self.1));
687 let mut parallel_resistors = Cell::new("parallel_resistors");
688 let p = parallel_resistors.add_node("p");
689 let n = parallel_resistors.add_node("n");
690 parallel_resistors.expose_port(p, Direction::InOut);
691 parallel_resistors.expose_port(n, Direction::InOut);
692 let mut r1 = Instance::new("r1", r1);
693 r1.connect("p", p);
694 r1.connect("n", n);
695 parallel_resistors.add_instance(r1);
696 let mut r2 = Instance::new("r2", r2);
697 r2.connect("p", p);
698 r2.connect("n", n);
699 parallel_resistors.add_instance(r2);
700 let cell_id = lib.add_cell(parallel_resistors);
701
702 let mut scir = ScirBinding::new(lib.build().unwrap(), cell_id);
704
705 scir.connect("p", io.p);
706 scir.connect("n", io.n);
707
708 cell.set_scir(scir);
709 Ok(())
710 }
711 }
712 #[allow(unused_variables)]
715 fn library() {
716 let mut lib = LibraryBuilder::<StringSchema>::new();
718 let empty_cell = Cell::new("empty");
721 let empty_cell_id = lib.add_cell(empty_cell);
722 let resistor_id = lib.add_primitive(arcstr::literal!("resistor"));
725 let mut vdivider = Cell::new("vdivider");
728
729 let vdd = vdivider.add_node("vdd");
730 let vout = vdivider.add_node("vout");
731 let vss = vdivider.add_node("vss");
732
733 vdivider.expose_port(vdd, Direction::InOut);
734 vdivider.expose_port(vout, Direction::Output);
735 vdivider.expose_port(vss, Direction::InOut);
736 let mut r1 = Instance::new("r1", resistor_id);
739
740 r1.connect("p", vdd);
741 r1.connect("n", vout);
742
743 vdivider.add_instance(r1);
744
745 let mut r2 = Instance::new("r2", resistor_id);
746
747 r2.connect("p", vout);
748 r2.connect("n", vss);
749
750 vdivider.add_instance(r2);
751
752 let vdivider_id = lib.add_cell(vdivider);
753 let mut stacked_vdivider = Cell::new("stacked_vdivider");
756
757 let vdd = stacked_vdivider.add_node("vdd");
758 let v1 = stacked_vdivider.add_node("v1");
759 let v2 = stacked_vdivider.add_node("v2");
760 let v3 = stacked_vdivider.add_node("v3");
761 let vss = stacked_vdivider.add_node("vss");
762
763 let mut vdiv1 = Instance::new("vdiv1", vdivider_id);
764
765 vdiv1.connect("vdd", vdd);
766 vdiv1.connect("vout", v1);
767 vdiv1.connect("vss", v2);
768
769 stacked_vdivider.add_instance(vdiv1);
770
771 let mut vdiv2 = Instance::new("vdiv2", vdivider_id);
772
773 vdiv2.connect("vdd", v2);
774 vdiv2.connect("vout", v3);
775 vdiv2.connect("vss", vss);
776
777 stacked_vdivider.add_instance(vdiv2);
778
779 let stacked_vdivider_id = lib.add_cell(stacked_vdivider);
780 }
782}
783
784fn main() {}