1pub mod conv;
4pub mod netlist;
5pub mod pex;
6pub mod schema;
7#[cfg(test)]
8mod tests;
9
10use cache::CacheHandle;
11use cache::mem::TypeCache;
12pub use codegen::NestedData;
13use pathtree::PathTree;
14use serde::{Deserialize, Serialize};
15use std::any::Any;
16use std::collections::HashMap;
17use std::fmt::Formatter;
18use std::hash::{Hash, Hasher};
19use std::marker::PhantomData;
20use std::ops::Deref;
21use std::sync::Arc;
22
23use arcstr::ArcStr;
24use once_cell::sync::OnceCell;
25
26use crate::block::Block;
27use crate::context::Context;
28use crate::diagnostics::SourceInfo;
29use crate::error::{Error, Result};
30use crate::schematic::conv::ConvError;
31use crate::schematic::schema::{FromSchema, Schema};
32use crate::types::schematic::{
33 IoNodeBundle, IoTerminalBundle, Node, NodeBundle, NodeContext, NodePriority, NodeUf, Port,
34 SchematicBundleKind,
35};
36use crate::types::{Flatten, HasBundleKind, HasNameTree, IoKind, NameBuf};
37
38pub trait Schematic: Block<Io: HasBundleKind<BundleKind: SchematicBundleKind>> {
40 type Schema: Schema;
42 type NestedData: NestedData;
47
48 fn schematic(
50 &self,
51 io: &IoNodeBundle<Self>,
52 cell: &mut CellBuilder<<Self as Schematic>::Schema>,
53 ) -> Result<Self::NestedData>;
54}
55
56impl<T: Schematic> Schematic for Arc<T> {
57 type Schema = T::Schema;
58 type NestedData = T::NestedData;
59
60 fn schematic(
61 &self,
62 io: &IoNodeBundle<Self>,
63 cell: &mut CellBuilder<<Self as Schematic>::Schema>,
64 ) -> Result<Self::NestedData> {
65 T::schematic(self.as_ref(), io, cell)
66 }
67}
68
69pub trait NestedData: HasNestedView + Send + Sync {}
71impl<T: HasNestedView + Send + Sync> NestedData for T {}
72
73pub trait HasContextView<T> {
75 type ContextView: Send + Sync;
77 fn context_view(&self, parent: &T) -> ContextView<Self, T>;
79}
80
81pub type ContextView<D, T> = <D as HasContextView<T>>::ContextView;
83
84impl<T> HasContextView<T> for () {
85 type ContextView = ();
86
87 fn context_view(&self, _parent: &T) -> ContextView<Self, T> {}
88}
89
90impl<V, T: HasContextView<V>> HasContextView<V> for Vec<T> {
92 type ContextView = Vec<ContextView<T, V>>;
93 fn context_view(&self, parent: &V) -> ContextView<Self, V> {
94 self.iter().map(|elem| elem.context_view(parent)).collect()
95 }
96}
97
98impl<V, T: HasContextView<V>> HasContextView<V> for Option<T> {
99 type ContextView = Option<ContextView<T, V>>;
100 fn context_view(&self, parent: &V) -> ContextView<Self, V> {
101 self.as_ref().map(|inner| inner.context_view(parent))
102 }
103}
104
105pub trait HasNestedView {
107 type NestedView: HasNestedView<NestedView = Self::NestedView> + Send + Sync;
111 fn nested_view(&self, parent: &InstancePath) -> NestedView<Self>;
113}
114
115pub type NestedView<D> = <D as HasNestedView>::NestedView;
117
118impl HasNestedView for () {
119 type NestedView = ();
120 fn nested_view(&self, _parent: &InstancePath) -> NestedView<Self> {}
121}
122
123impl<T: HasNestedView> HasNestedView for Vec<T> {
125 type NestedView = Vec<NestedView<T>>;
126 fn nested_view(&self, parent: &InstancePath) -> NestedView<Self> {
127 self.iter().map(|elem| elem.nested_view(parent)).collect()
128 }
129}
130
131impl<T: HasNestedView> HasNestedView for Option<T> {
132 type NestedView = Option<NestedView<T>>;
133 fn nested_view(&self, parent: &InstancePath) -> NestedView<Self> {
134 self.as_ref().map(|inner| inner.nested_view(parent))
135 }
136}
137
138#[derive_where::derive_where(Debug, Hash, PartialEq, Eq; B)]
140pub struct ConvertSchema<B, S>(Arc<B>, PhantomData<S>);
141
142impl<B, S> ConvertSchema<B, S> {
143 pub fn new(block: B) -> Self {
145 Self(Arc::new(block), PhantomData)
146 }
147}
148
149impl<B, S> Clone for ConvertSchema<B, S> {
150 fn clone(&self) -> Self {
151 Self(self.0.clone(), PhantomData)
152 }
153}
154
155impl<B: Block, S: Schema> Block for ConvertSchema<B, S> {
156 type Io = <B as Block>::Io;
157
158 fn name(&self) -> ArcStr {
159 self.0.name()
160 }
161
162 fn io(&self) -> Self::Io {
163 self.0.io()
164 }
165}
166
167impl<B: Schematic, S: FromSchema<B::Schema>> Schematic for ConvertSchema<B, S>
168where
169 NestedView<B::NestedData>: HasNestedView,
170{
171 type Schema = S;
172 type NestedData = NestedView<B::NestedData>;
173 fn schematic(
174 &self,
175 io: &IoNodeBundle<Self>,
176 cell: &mut CellBuilder<<Self as Schematic>::Schema>,
177 ) -> Result<Self::NestedData> {
178 let mut s = cell.sub_builder::<B::Schema>();
179 let b = s.instantiate_blocking(self.0.clone())?;
180 cell.connect(io, b.io());
181 cell.flatten();
182 Ok(b.data())
183 }
184}
185
186pub struct CellBuilder<S: Schema + ?Sized> {
188 pub(crate) ctx: Context,
190 pub(crate) id: CellId,
191 pub(crate) cell_name: ArcStr,
192 pub(crate) flatten: bool,
193 pub(crate) node_ctx: NodeContext,
194 pub(crate) node_names: HashMap<Node, NameBuf>,
195 pub(crate) fatal_error: bool,
197 pub(crate) ports: Vec<Port>,
203 pub(crate) contents: RawCellContentsBuilder<S>,
204}
205
206impl<S: Schema + ?Sized> CellBuilder<S> {
207 pub(crate) fn finish(self) -> RawCell<S> {
208 let mut roots = HashMap::with_capacity(self.node_names.len());
209 let mut uf = self.node_ctx.into_uf();
210 for &node in self.node_names.keys() {
211 let root = uf.probe_value(node).unwrap().source;
212 roots.insert(node, root);
213 }
214
215 RawCell {
216 id: self.id,
217 name: self.cell_name,
218 node_names: self.node_names,
219 ports: self.ports,
220 flatten: self.flatten,
221 uf,
222 roots,
223 contents: self.contents.build(),
224 }
225 }
226
227 pub fn flatten(&mut self) {
229 self.flatten = true;
230 }
231
232 #[track_caller]
234 pub fn signal<K: HasBundleKind<BundleKind: SchematicBundleKind>>(
235 &mut self,
236 name: impl Into<ArcStr>,
237 kind: K,
238 ) -> NodeBundle<K> {
239 let (nodes, data) = self.node_ctx.instantiate_undirected(
240 &kind,
241 NodePriority::Named,
242 SourceInfo::from_caller(),
243 );
244
245 let kind = kind.kind();
246 let names = kind.flat_names(Some(name.into().into()));
247 assert_eq!(nodes.len(), names.len());
248
249 self.node_names.extend(nodes.iter().copied().zip(names));
250
251 data
252 }
253
254 #[track_caller]
256 pub fn connect<D1, D2>(&mut self, s1: D1, s2: D2)
257 where
258 D1: Flatten<Node> + HasBundleKind,
259 D2: Flatten<Node> + HasBundleKind<BundleKind = <D1 as HasBundleKind>::BundleKind>,
260 {
261 let sinfo = SourceInfo::from_caller();
262 let s1_kind = s1.kind();
263 let s2_kind = s2.kind();
264 if s1_kind != s2_kind {
265 tracing::error!(
266 ?sinfo,
267 ?s1_kind,
268 ?s2_kind,
269 "tried to connect bundles of different kinds",
270 );
271 self.fatal_error = true;
272 } else {
273 let s1f: Vec<Node> = s1.flatten_vec();
274 let s2f: Vec<Node> = s2.flatten_vec();
275 s1f.into_iter().zip(s2f).for_each(|(a, b)| {
276 self.node_ctx.connect(a, b, sinfo.clone());
277 });
278 }
279 }
280
281 pub fn connect_multiple<D>(&mut self, s2: &[D])
283 where
284 D: Flatten<Node> + HasBundleKind,
285 {
286 if s2.len() > 1 {
287 for s in &s2[1..] {
288 self.connect(&s2[0], s);
289 }
290 }
291 }
292
293 pub fn set_scir(&mut self, scir: ScirBinding<S>) {
295 self.contents = RawCellContentsBuilder::Scir(scir);
296 }
297
298 pub fn set_primitive(&mut self, primitive: PrimitiveBinding<S>) {
300 self.contents = RawCellContentsBuilder::Primitive(primitive);
301 }
302
303 pub fn ctx(&self) -> &Context {
305 &self.ctx
306 }
307
308 pub fn generate<B: Schematic<Schema = S>>(
315 &mut self,
316 block: B,
317 ) -> SchemaCellHandle<B::Schema, B> {
318 self.ctx().generate_schematic(block)
319 }
320
321 pub fn generate_blocking<B: Schematic<Schema = S>>(
328 &mut self,
329 block: B,
330 ) -> Result<SchemaCellHandle<B::Schema, B>> {
331 let handle = self.ctx().generate_schematic(block);
332 handle.cell.try_cell()?;
333 Ok(handle)
334 }
335
336 #[track_caller]
347 pub fn add<B: Schematic>(&mut self, cell: SchemaCellHandle<S, B>) -> Instance<B>
348 where
349 S: FromSchema<B::Schema>,
350 {
351 self.post_instantiate(cell, SourceInfo::from_caller(), None)
352 }
353
354 #[track_caller]
372 pub fn instantiate<B: Schematic<Schema = S>>(&mut self, block: B) -> Instance<B> {
373 let cell = self.ctx().generate_schematic(block);
374 self.post_instantiate(cell, SourceInfo::from_caller(), None)
375 }
376
377 #[track_caller]
383 pub fn instantiate_named<B: Schematic<Schema = S>>(
384 &mut self,
385 block: B,
386 name: impl Into<ArcStr>,
387 ) -> Instance<B> {
388 let cell = self.ctx().generate_schematic(block);
389 self.post_instantiate(cell, SourceInfo::from_caller(), Some(name.into()))
390 }
391
392 #[track_caller]
402 pub fn instantiate_blocking<B: Schematic<Schema = S>>(
403 &mut self,
404 block: B,
405 ) -> Result<Instance<B>> {
406 let inst = self.instantiate(block);
407 inst.try_data()?;
408 Ok(inst)
409 }
410
411 pub fn instantiate_connected<B, C>(&mut self, block: B, io: C) -> Instance<B>
413 where
414 B: Schematic<Schema = S>,
415 C: Flatten<Node> + HasBundleKind<BundleKind = IoKind<B>>,
416 {
417 let inst = self.instantiate(block);
418 self.connect(inst.io(), io);
419 inst
420 }
421
422 pub fn instantiate_connected_named<B, C>(
424 &mut self,
425 block: B,
426 io: C,
427 name: impl Into<ArcStr>,
428 ) -> Instance<B>
429 where
430 B: Schematic<Schema = S>,
431 C: Flatten<Node> + HasBundleKind<BundleKind = IoKind<B>>,
432 {
433 let inst = self.instantiate_named(block, name);
434 self.connect(inst.io(), io);
435 inst
436 }
437
438 fn post_instantiate<B: Schematic>(
440 &mut self,
441 cell: SchemaCellHandle<S, B>,
442 source_info: SourceInfo,
443 name: Option<ArcStr>,
444 ) -> Instance<B>
445 where
446 S: FromSchema<B::Schema>,
447 {
448 let io = cell.cell.block.io();
449 let cell_contents = self.contents.as_mut().unwrap_cell();
450 cell_contents.next_instance_id.increment();
451
452 let inst_name =
453 name.unwrap_or_else(|| arcstr::format!("xinst{}", cell_contents.instances.len()));
454
455 let (nodes, io_data) =
456 self.node_ctx
457 .instantiate_directed(&io, NodePriority::Auto, source_info);
458
459 let names = <<B as Block>::Io as HasBundleKind>::kind(&io)
460 .flat_names(Some(inst_name.clone().into()));
461 assert_eq!(nodes.len(), names.len());
462
463 self.node_names.extend(nodes.iter().copied().zip(names));
464
465 let root = InstancePath::new(self.id);
466 let inst = Instance {
467 id: cell_contents.next_instance_id,
468 parent: root.clone(),
469 path: root.append_segment(cell_contents.next_instance_id, cell.cell.id),
470 cell: cell.cell,
471 io: Arc::new(io_data),
472 terminal_view: OnceCell::new(),
473 nested_data: OnceCell::new(),
474 };
475
476 cell_contents.instances.push(RawInstanceBuilder {
477 id: inst.id,
478 name: inst_name.clone(),
479 connections: nodes,
481 child: cell.handle.map(|handle| match handle {
482 Ok(Ok(SchemaCellCacheValue { raw, .. })) => Ok(raw.clone()),
483 Ok(Err(e)) => {
484 tracing::error!("{:?}", e);
485 panic!("cell generator failed")
486 }
487 Err(e) => {
488 tracing::error!("{:?}", e);
489 panic!("cache failed")
490 }
491 }),
492 });
493
494 inst
495 }
496
497 pub fn sub_builder<S2: Schema + ?Sized>(&mut self) -> SubCellBuilder<'_, S, S2>
499 where
500 S: FromSchema<S2>,
501 {
502 SubCellBuilder(self, PhantomData)
503 }
504}
505
506pub struct SubCellBuilder<'a, S1: Schema + ?Sized, S2: Schema + ?Sized>(
508 &'a mut CellBuilder<S1>,
509 PhantomData<S2>,
510);
511
512impl<S1: FromSchema<S2>, S2: Schema + ?Sized> SubCellBuilder<'_, S1, S2> {
513 #[track_caller]
515 pub fn signal<K: HasBundleKind<BundleKind: SchematicBundleKind>>(
516 &mut self,
517 name: impl Into<ArcStr>,
518 kind: K,
519 ) -> NodeBundle<K> {
520 self.0.signal(name, kind)
521 }
522
523 pub fn connect<D1, D2>(&mut self, s1: D1, s2: D2)
525 where
526 D1: Flatten<Node> + HasBundleKind,
527 D2: Flatten<Node> + HasBundleKind<BundleKind = <D1 as HasBundleKind>::BundleKind>,
528 {
529 self.0.connect(s1, s2)
530 }
531
532 pub fn ctx(&self) -> &Context {
534 &self.0.ctx
535 }
536
537 pub fn generate<B: Schematic<Schema = S2>>(
544 &mut self,
545 block: B,
546 ) -> SchemaCellHandle<B::Schema, B> {
547 self.ctx().generate_cross_schematic(block)
548 }
549
550 pub fn generate_blocking<B: Schematic<Schema = S2>>(
557 &mut self,
558 block: B,
559 ) -> Result<SchemaCellHandle<B::Schema, B>> {
560 let handle = self.ctx().generate_cross_schematic(block);
561 handle.cell.try_cell()?;
562 Ok(handle)
563 }
564
565 #[track_caller]
576 pub fn add<B: Schematic<Schema = S2>>(&mut self, cell: SchemaCellHandle<S1, B>) -> Instance<B> {
577 self.0.add(cell)
578 }
579
580 #[track_caller]
598 pub fn instantiate<B: Schematic<Schema = S2>>(&mut self, block: B) -> Instance<B> {
599 let cell = self.ctx().generate_cross_schematic(block);
600 self.post_instantiate(cell, SourceInfo::from_caller(), None)
601 }
602
603 #[track_caller]
609 pub fn instantiate_named<B: Schematic<Schema = S2>>(
610 &mut self,
611 block: B,
612 name: impl Into<ArcStr>,
613 ) -> Instance<B> {
614 let cell = self.ctx().generate_cross_schematic(block);
615 self.post_instantiate(cell, SourceInfo::from_caller(), Some(name.into()))
616 }
617
618 #[track_caller]
628 pub fn instantiate_blocking<B: Schematic<Schema = S2>>(
629 &mut self,
630 block: B,
631 ) -> Result<Instance<B>> {
632 let inst = self.instantiate(block);
633 inst.try_data()?;
634 Ok(inst)
635 }
636
637 pub fn instantiate_connected<B, C>(&mut self, block: B, io: C) -> Instance<B>
639 where
640 B: Schematic<Schema = S2>,
641 C: Flatten<Node> + HasBundleKind<BundleKind = IoKind<B>>,
642 {
643 let inst = self.instantiate(block);
644 self.connect(inst.io(), io);
645 inst
646 }
647
648 pub fn instantiate_connected_named<B, C>(
650 &mut self,
651 block: B,
652 io: C,
653 name: impl Into<ArcStr>,
654 ) -> Instance<B>
655 where
656 B: Schematic<Schema = S2>,
657 C: Flatten<Node> + HasBundleKind<BundleKind = IoKind<B>>,
658 {
659 let inst = self.instantiate_named(block, name);
660 self.connect(inst.io(), io);
661 inst
662 }
663
664 fn post_instantiate<B: Schematic<Schema = S2>>(
666 &mut self,
667 cell: SchemaCellHandle<S1, B>,
668 source_info: SourceInfo,
669 name: Option<ArcStr>,
670 ) -> Instance<B> {
671 self.0.post_instantiate(cell, source_info, name)
672 }
673}
674
675pub struct Cell<T: Schematic> {
677 block: Arc<T>,
679 nodes: Arc<T::NestedData>,
681 io: Arc<IoNodeBundle<T>>,
683 path: InstancePath,
685
686 pub(crate) raw: Arc<RawCell<T::Schema>>,
687
688 nested_data: OnceCell<Arc<NestedView<T::NestedData>>>,
690}
691
692impl<T: Schematic> Deref for Cell<T> {
693 type Target = NestedView<T::NestedData>;
694
695 fn deref(&self) -> &Self::Target {
696 self.nested_data
697 .get_or_init(|| Arc::new(self.data()))
698 .as_ref()
699 }
700}
701
702impl<T: Schematic> Clone for Cell<T> {
703 fn clone(&self) -> Self {
704 Self {
705 block: self.block.clone(),
706 nodes: self.nodes.clone(),
707 io: self.io.clone(),
708 path: self.path.clone(),
709 raw: self.raw.clone(),
710 nested_data: self.nested_data.clone(),
711 }
712 }
713}
714
715impl<T: Schematic> Cell<T> {
716 pub(crate) fn new(
717 id: CellId,
718 io: Arc<IoNodeBundle<T>>,
719 block: Arc<T>,
720 raw: Arc<RawCell<T::Schema>>,
721 data: Arc<T::NestedData>,
722 ) -> Self {
723 Self {
724 io,
725 block,
726 nodes: data,
727 path: InstancePath::new(id),
728 raw,
729 nested_data: OnceCell::new(),
730 }
731 }
732
733 pub fn block(&self) -> &T {
735 &self.block
736 }
737
738 pub fn data(&self) -> NestedView<T::NestedData> {
740 self.nodes.nested_view(&self.path)
741 }
742
743 pub fn context_data<V>(&self, parent: &V) -> ContextView<T::NestedData, V>
745 where
746 T::NestedData: HasContextView<V>,
747 {
748 self.nodes.context_view(parent)
749 }
750
751 pub fn io(&self) -> NestedView<IoNodeBundle<T>> {
753 self.io.nested_view(&self.path)
754 }
755}
756
757pub struct CellHandle<B: Schematic> {
759 pub(crate) id: CellId,
760 pub(crate) block: Arc<B>,
761 pub(crate) io_data: Arc<IoNodeBundle<B>>,
762 pub(crate) cell: CacheHandle<Result<Arc<Cell<B>>>>,
763}
764
765impl<B: Schematic> Clone for CellHandle<B> {
766 fn clone(&self) -> Self {
767 Self {
768 id: self.id,
769 block: self.block.clone(),
770 io_data: self.io_data.clone(),
771 cell: self.cell.clone(),
772 }
773 }
774}
775
776impl<B: Schematic> CellHandle<B> {
777 pub fn try_cell(&self) -> Result<&Cell<B>> {
781 self.cell
783 .try_get()
784 .as_ref()
785 .map_err(|_| Error::Internal)?
786 .as_ref()
787 .map(|cell| cell.as_ref())
788 .map_err(|e| e.clone())
789 }
790 pub fn cell(&self) -> &Cell<B> {
798 self.try_cell().expect("cell generation failed")
799 }
800}
801
802pub(crate) struct SchemaCellCacheValue<S: Schema + ?Sized, B: Schematic> {
803 pub(crate) raw: Arc<RawCell<S>>,
804 pub(crate) cell: Arc<Cell<B>>,
805}
806
807pub struct SchemaCellHandle<S: Schema + ?Sized, B: Schematic> {
809 pub(crate) handle: CacheHandle<Result<SchemaCellCacheValue<S, B>>>,
810 pub(crate) cell: CellHandle<B>,
811}
812
813impl<S: Schema, B: Schematic> SchemaCellHandle<S, B> {
814 pub fn try_cell(&self) -> Result<&Cell<B>> {
818 self.cell.try_cell()
820 }
821
822 pub fn cell(&self) -> &Cell<B> {
830 self.cell.cell()
831 }
832
833 #[doc(hidden)]
835 pub fn raw(&self) -> Arc<RawCell<S>> {
836 let val = self.handle.unwrap_inner();
837 val.raw.clone()
838 }
839}
840
841impl<S: Schema + ?Sized, B: Schematic> Deref for SchemaCellHandle<S, B> {
842 type Target = CellHandle<B>;
843
844 fn deref(&self) -> &Self::Target {
845 &self.cell
846 }
847}
848
849impl<S: Schema + ?Sized, B: Schematic> Clone for SchemaCellHandle<S, B> {
850 fn clone(&self) -> Self {
851 Self {
852 handle: self.handle.clone(),
853 cell: self.cell.clone(),
854 }
855 }
856}
857
858#[allow(dead_code)]
860pub struct Instance<B: Schematic> {
861 id: InstanceId,
862 parent: InstancePath,
864 path: InstancePath,
866 io: Arc<IoNodeBundle<B>>,
868 cell: CellHandle<B>,
869 terminal_view: OnceCell<Arc<IoTerminalBundle<B>>>,
871 nested_data: OnceCell<Arc<NestedView<B::NestedData>>>,
873}
874
875impl<T: Schematic> Deref for Instance<T> {
876 type Target = NestedView<T::NestedData>;
877
878 fn deref(&self) -> &Self::Target {
879 self.nested_data
880 .get_or_init(|| Arc::new(self.data()))
881 .as_ref()
882 }
883}
884
885impl<B: Schematic> Clone for Instance<B> {
886 fn clone(&self) -> Self {
887 Self {
888 id: self.id,
889 parent: self.parent.clone(),
890 path: self.path.clone(),
891 io: self.io.clone(),
892 cell: self.cell.clone(),
893 terminal_view: self.terminal_view.clone(),
894 nested_data: self.nested_data.clone(),
895 }
896 }
897}
898
899impl<B: Schematic> HasNestedView for Instance<B> {
900 type NestedView = NestedInstance<B>;
901 fn nested_view(&self, parent: &InstancePath) -> NestedView<Self> {
902 let mut inst = (*self).clone();
903 inst.path = self.path.prepend(parent);
904 inst.parent = self.parent.prepend(parent);
905 inst.nested_data = OnceCell::new();
906 inst.terminal_view = OnceCell::new();
907 NestedInstance(inst)
908 }
909}
910
911impl<T: Schematic> Instance<T> {
912 pub fn io(&self) -> &IoTerminalBundle<T> {
916 self.terminal_view
917 .get_or_init(|| {
918 Arc::new(<IoKind<T> as SchematicBundleKind>::terminal_view(
919 self.cell.id,
920 self.cell.io_data.as_ref(),
921 self.id,
922 &self.io,
923 ))
924 })
925 .as_ref()
926 }
927
928 pub fn try_data(&self) -> Result<NestedView<T::NestedData>> {
932 self.cell
933 .try_cell()
934 .map(|data| data.nodes.nested_view(&self.path))
935 }
936
937 pub fn data(&self) -> NestedView<T::NestedData> {
943 self.cell.cell().nodes.nested_view(&self.path)
944 }
945
946 pub fn block(&self) -> &T {
952 &self.cell.block
953 }
954
955 pub fn path(&self) -> &InstancePath {
957 &self.path
958 }
959}
960
961pub struct NestedInstance<T: Schematic>(Instance<T>);
963
964impl<T: Schematic> Deref for NestedInstance<T> {
965 type Target = NestedView<T::NestedData>;
966
967 fn deref(&self) -> &Self::Target {
968 &self.0
969 }
970}
971
972impl<B: Schematic> Clone for NestedInstance<B> {
973 fn clone(&self) -> Self {
974 Self(self.0.clone())
975 }
976}
977
978impl<B: Schematic> HasNestedView for NestedInstance<B> {
979 type NestedView = NestedInstance<B>;
980 fn nested_view(&self, parent: &InstancePath) -> NestedView<Self> {
981 let mut inst = (*self).clone();
982 inst.0.path = self.0.path.prepend(parent);
983 inst.0.parent = self.0.parent.prepend(parent);
984 inst.0.nested_data = OnceCell::new();
985 inst.0.terminal_view = OnceCell::new();
986 inst
987 }
988}
989
990impl<T: Schematic> NestedInstance<T> {
991 pub fn io(&self) -> NestedView<IoTerminalBundle<T>> {
995 self.0.io().nested_view(&self.0.parent)
996 }
997
998 pub fn try_data(&self) -> Result<NestedView<T::NestedData>> {
1002 self.0.try_data()
1003 }
1004
1005 pub fn data(&self) -> NestedView<T::NestedData> {
1011 self.0.data()
1012 }
1013
1014 pub fn block(&self) -> &T {
1016 self.0.block()
1017 }
1018
1019 pub fn path(&self) -> &InstancePath {
1021 &self.0.path
1022 }
1023}
1024
1025#[derive(Debug)]
1027pub struct SchematicContext {
1028 pub(crate) next_id: CellId,
1029 pub(crate) cell_cache: TypeCache,
1032}
1033
1034impl Default for SchematicContext {
1035 fn default() -> Self {
1036 Self {
1037 next_id: CellId(0),
1038 cell_cache: Default::default(),
1039 }
1040 }
1041}
1042
1043impl SchematicContext {
1044 #[allow(dead_code)]
1045 pub(crate) fn new() -> Self {
1046 Self::default()
1047 }
1048}
1049
1050pub(crate) struct CellMetadata<B: Schematic> {
1052 pub(crate) id: CellId,
1053 pub(crate) io_data: Arc<IoNodeBundle<B>>,
1054}
1055
1056impl<B: Schematic> Clone for CellMetadata<B> {
1057 fn clone(&self) -> Self {
1058 Self {
1059 id: self.id,
1060 io_data: self.io_data.clone(),
1061 }
1062 }
1063}
1064
1065pub(crate) struct CellCacheKey<B, S: ?Sized> {
1066 pub(crate) block: Arc<B>,
1067 pub(crate) phantom: PhantomData<S>,
1068}
1069
1070impl<B, S: ?Sized> Clone for CellCacheKey<B, S> {
1071 fn clone(&self) -> Self {
1072 Self {
1073 block: self.block.clone(),
1074 phantom: PhantomData,
1075 }
1076 }
1077}
1078
1079impl<B: PartialEq, S: ?Sized> PartialEq for CellCacheKey<B, S> {
1080 fn eq(&self, other: &Self) -> bool {
1081 self.block.eq(&other.block)
1082 }
1083}
1084
1085impl<B: Eq, S: ?Sized> Eq for CellCacheKey<B, S> {}
1086
1087impl<B: Hash, S: ?Sized> Hash for CellCacheKey<B, S> {
1088 fn hash<H: Hasher>(&self, state: &mut H) {
1089 self.block.hash(state)
1090 }
1091}
1092
1093pub(crate) type ConvCacheKey<B, S1, S2> = CellCacheKey<B, (PhantomData<S1>, S2)>;
1095
1096#[derive(Debug, Clone, Eq, PartialEq, Hash)]
1100pub struct InstancePath {
1101 pub(crate) top: CellId,
1103 pub(crate) bot: Option<CellId>,
1108 pub(crate) path: PathTree<InstanceId>,
1110}
1111
1112impl InstancePath {
1113 pub(crate) fn new(top: CellId) -> Self {
1114 Self {
1115 top,
1116 bot: None,
1117 path: PathTree::empty(),
1118 }
1119 }
1120 #[allow(dead_code)]
1121 pub(crate) fn append(&self, other: &Self) -> Self {
1122 if let Some(bot) = self.bot {
1123 assert_eq!(
1124 bot, other.top,
1125 "path to append must start with the cell ID that the current path ends with"
1126 );
1127 } else {
1128 assert_eq!(
1129 self.top, other.top,
1130 "path to append must start with the cell ID that the current path ends with"
1131 );
1132 }
1133 Self {
1134 top: self.top,
1135 bot: other.bot,
1136 path: self.path.append(&other.path),
1137 }
1138 }
1139
1140 pub fn prepend(&self, other: &Self) -> Self {
1142 if let Some(bot) = other.bot {
1143 assert_eq!(
1144 bot, self.top,
1145 "path to prepend must end with the cell ID that the current path starts with"
1146 );
1147 } else {
1148 assert_eq!(
1149 other.top, self.top,
1150 "path to prepend must end with the cell ID that the current path starts with"
1151 );
1152 }
1153 Self {
1154 top: other.top,
1155 bot: self.bot,
1156 path: self.path.prepend(&other.path),
1157 }
1158 }
1159
1160 pub(crate) fn append_segment(&self, id: InstanceId, cell_id: CellId) -> Self {
1161 Self {
1162 top: self.top,
1163 bot: Some(cell_id),
1164 path: self.path.append_segment(id),
1165 }
1166 }
1167
1168 #[allow(dead_code)]
1169 pub(crate) fn is_empty(&self) -> bool {
1170 self.bot.is_none()
1171 }
1172}
1173
1174#[allow(dead_code)]
1176pub(crate) struct RawInstanceBuilder<S: Schema + ?Sized> {
1177 id: InstanceId,
1178 name: ArcStr,
1179 connections: Vec<Node>,
1180 child: CacheHandle<Arc<RawCell<S>>>,
1181}
1182
1183impl<S: Schema<Primitive = impl std::fmt::Debug> + ?Sized> std::fmt::Debug
1184 for RawInstanceBuilder<S>
1185{
1186 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1187 let mut builder = f.debug_struct("RawInstanceBuilder");
1188 let _ = builder.field("id", &self.id);
1189 let _ = builder.field("name", &self.name);
1190 let _ = builder.field("connections", &self.connections);
1191 let _ = builder.field("child", &self.child);
1192 builder.finish()
1193 }
1194}
1195
1196impl<S: Schema + ?Sized> RawInstanceBuilder<S> {
1197 fn build(self) -> RawInstance<S> {
1198 RawInstance {
1199 id: self.id,
1200 name: self.name,
1201 connections: self.connections,
1202 child: self.child.get().clone(),
1203 }
1204 }
1205}
1206
1207#[allow(dead_code)]
1209pub(crate) struct RawInstance<S: Schema + ?Sized> {
1210 id: InstanceId,
1211 name: ArcStr,
1212 connections: Vec<Node>,
1213 child: Arc<RawCell<S>>,
1214}
1215
1216impl<S: Schema<Primitive = impl std::fmt::Debug> + ?Sized> std::fmt::Debug for RawInstance<S> {
1217 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1218 let mut builder = f.debug_struct("RawInstance");
1219 let _ = builder.field("id", &self.id);
1220 let _ = builder.field("name", &self.name);
1221 let _ = builder.field("connections", &self.connections);
1222 let _ = builder.field("child", &self.child);
1223 builder.finish()
1224 }
1225}
1226
1227impl<S: Schema + ?Sized> Clone for RawInstance<S> {
1228 fn clone(&self) -> Self {
1229 Self {
1230 id: self.id,
1231 name: self.name.clone(),
1232 connections: self.connections.clone(),
1233 child: self.child.clone(),
1234 }
1235 }
1236}
1237
1238impl<S: Schema + ?Sized> RawInstance<S> {
1239 fn convert_schema<S2: FromSchema<S> + ?Sized>(self) -> Result<RawInstance<S2>> {
1240 Ok(RawInstance {
1241 id: self.id,
1242 name: self.name,
1243 connections: self.connections,
1244 child: Arc::new((*self.child).clone().convert_schema()?),
1245 })
1246 }
1247}
1248
1249#[doc(hidden)]
1254pub struct RawCell<S: Schema + ?Sized> {
1255 id: CellId,
1256 pub(crate) name: ArcStr,
1257 ports: Vec<Port>,
1258 uf: NodeUf,
1259 node_names: HashMap<Node, NameBuf>,
1260 roots: HashMap<Node, Node>,
1261 flatten: bool,
1263 contents: RawCellContents<S>,
1264}
1265
1266impl<S: Schema<Primitive = impl std::fmt::Debug> + ?Sized> std::fmt::Debug for RawCell<S> {
1268 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1269 let mut builder = f.debug_struct("RawCell");
1270 let _ = builder.field("id", &self.id);
1271 let _ = builder.field("name", &self.name);
1272 let _ = builder.field("ports", &self.ports);
1273 let _ = builder.field("uf", &self.uf);
1274 let _ = builder.field("node_names", &self.node_names);
1275 let _ = builder.field("roots", &self.roots);
1276 let _ = builder.field("contents", &self.contents);
1277 let _ = builder.field("flatten", &self.flatten);
1278 builder.finish()
1279 }
1280}
1281
1282impl<S: Schema + ?Sized> Clone for RawCell<S> {
1283 fn clone(&self) -> Self {
1284 Self {
1285 id: self.id,
1286 name: self.name.clone(),
1287 ports: self.ports.clone(),
1288 uf: self.uf.clone(),
1289 node_names: self.node_names.clone(),
1290 roots: self.roots.clone(),
1291 contents: self.contents.clone(),
1292 flatten: self.flatten,
1293 }
1294 }
1295}
1296
1297impl<S: Schema + ?Sized> RawCell<S> {
1298 pub(crate) fn convert_schema<S2: FromSchema<S> + ?Sized>(self) -> Result<RawCell<S2>> {
1299 Ok(RawCell {
1300 id: self.id,
1301 name: self.name,
1302 ports: self.ports,
1303 uf: self.uf,
1304 node_names: self.node_names,
1305 roots: self.roots,
1306 flatten: self.flatten,
1307 contents: self.contents.convert_schema()?,
1308 })
1309 }
1310}
1311
1312pub(crate) type RawCellContentsBuilder<S> =
1314 RawCellKind<RawCellInnerBuilder<S>, ScirBinding<S>, PrimitiveBinding<S>, ConvertedPrimitive<S>>;
1315
1316impl<S: Schema + ?Sized> RawCellContentsBuilder<S> {
1317 fn build(self) -> RawCellContents<S> {
1318 match self {
1319 RawCellContentsBuilder::Cell(b) => RawCellContents::Cell(b.build()),
1320 RawCellContentsBuilder::Scir(s) => RawCellContents::Scir(s),
1321 RawCellContentsBuilder::Primitive(s) => RawCellContents::Primitive(s),
1322 RawCellContentsBuilder::ConvertedPrimitive(s) => RawCellContents::ConvertedPrimitive(s),
1323 }
1324 }
1325}
1326
1327pub(crate) type RawCellContents<S> =
1329 RawCellKind<RawCellInner<S>, ScirBinding<S>, PrimitiveBinding<S>, ConvertedPrimitive<S>>;
1330
1331impl<S: Schema + ?Sized> RawCellContents<S> {
1332 fn convert_schema<S2: FromSchema<S> + ?Sized>(self) -> Result<RawCellContents<S2>> {
1333 Ok(match self {
1334 RawCellContents::Cell(c) => RawCellContents::Cell(c.convert_schema()?),
1335 RawCellContents::Scir(s) => RawCellContents::Scir(ScirBinding {
1336 lib: s
1337 .lib
1338 .convert_schema()
1339 .map_err(|_| Error::UnsupportedPrimitive)?
1340 .build()
1341 .map_err(ConvError::from)?,
1342 cell: s.cell,
1343 port_map: s.port_map,
1344 }),
1345 RawCellContents::Primitive(p) => {
1346 RawCellContents::ConvertedPrimitive(ConvertedPrimitive {
1347 converted: <S2 as scir::schema::FromSchema<S>>::convert_primitive(
1348 p.primitive.clone(),
1349 )
1350 .map_err(|_| Error::UnsupportedPrimitive)?,
1351 original: Arc::new(p),
1352 })
1353 }
1354 RawCellContents::ConvertedPrimitive(p) => {
1355 RawCellContents::ConvertedPrimitive(ConvertedPrimitive {
1356 converted: <S2 as scir::schema::FromSchema<S>>::convert_primitive(
1357 p.converted.clone(),
1358 )
1359 .map_err(|_| Error::UnsupportedPrimitive)?,
1360 original: Arc::new(p),
1361 })
1362 }
1363 })
1364 }
1365}
1366
1367pub(crate) trait ConvertPrimitive<S: Schema + ?Sized>: Any + Send + Sync {
1368 fn convert_primitive(&self) -> Result<<S as Schema>::Primitive>;
1369 fn convert_instance(&self, inst: &mut scir::Instance) -> Result<()>;
1370 fn port_map(&self) -> &HashMap<ArcStr, Vec<Node>>;
1371}
1372
1373impl<S1: FromSchema<S2> + ?Sized, S2: Schema + ?Sized> ConvertPrimitive<S1>
1374 for PrimitiveBinding<S2>
1375{
1376 fn convert_primitive(&self) -> Result<<S1 as Schema>::Primitive> {
1378 <S1 as scir::schema::FromSchema<S2>>::convert_primitive(self.primitive.clone())
1379 .map_err(|_| Error::UnsupportedPrimitive)
1380 }
1381 fn convert_instance(&self, inst: &mut scir::Instance) -> Result<()> {
1382 <S1 as scir::schema::FromSchema<S2>>::convert_instance(inst, &self.primitive)
1383 .map_err(|_| Error::UnsupportedPrimitive)
1384 }
1385 fn port_map(&self) -> &HashMap<ArcStr, Vec<Node>> {
1386 &self.port_map
1387 }
1388}
1389
1390impl<S1: FromSchema<S2> + ?Sized, S2: Schema + ?Sized> ConvertPrimitive<S1>
1391 for ConvertedPrimitive<S2>
1392{
1393 fn convert_primitive(&self) -> Result<<S1 as Schema>::Primitive> {
1395 <S1 as scir::schema::FromSchema<S2>>::convert_primitive(self.original.convert_primitive()?)
1396 .map_err(|_| Error::UnsupportedPrimitive)
1397 }
1398 fn convert_instance(&self, inst: &mut scir::Instance) -> Result<()> {
1399 self.original.convert_instance(inst)?;
1400 <S1 as scir::schema::FromSchema<S2>>::convert_instance(inst, &self.converted)
1401 .map_err(|_| Error::UnsupportedPrimitive)
1402 }
1403 fn port_map(&self) -> &HashMap<ArcStr, Vec<Node>> {
1404 self.original.port_map()
1405 }
1406}
1407
1408pub struct PrimitiveBinding<S: Schema + ?Sized> {
1411 pub(crate) primitive: <S as Schema>::Primitive,
1412 pub(crate) port_map: HashMap<ArcStr, Vec<Node>>,
1413}
1414
1415impl<S: Schema<Primitive = impl std::fmt::Debug> + ?Sized> std::fmt::Debug for PrimitiveBinding<S> {
1416 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1417 let mut builder = f.debug_struct("Primitive");
1418 let _ = builder.field("primitive", &self.primitive);
1419 let _ = builder.field("port_map", &self.port_map);
1420 builder.finish()
1421 }
1422}
1423
1424impl<S: Schema + ?Sized> Clone for PrimitiveBinding<S> {
1425 fn clone(&self) -> Self {
1426 Self {
1427 primitive: self.primitive.clone(),
1428 port_map: self.port_map.clone(),
1429 }
1430 }
1431}
1432
1433impl<S: Schema> PrimitiveBinding<S> {
1434 pub fn new(primitive: <S as Schema>::Primitive) -> Self {
1436 Self {
1437 primitive,
1438 port_map: Default::default(),
1439 }
1440 }
1441
1442 pub fn connect(&mut self, port: impl Into<ArcStr>, s: impl Flatten<Node>) {
1444 self.port_map.insert(port.into(), s.flatten_vec());
1445 }
1446}
1447
1448pub(crate) struct ConvertedPrimitive<S: Schema + ?Sized> {
1449 converted: <S as Schema>::Primitive,
1450 original: Arc<dyn ConvertPrimitive<S>>,
1451}
1452
1453impl<S: Schema<Primitive = impl std::fmt::Debug> + ?Sized> std::fmt::Debug
1454 for ConvertedPrimitive<S>
1455{
1456 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1457 let mut builder = f.debug_struct("ConvertedPrimitive");
1458 let _ = builder.field("converted", &self.converted);
1459 builder.finish()
1460 }
1461}
1462
1463impl<S: Schema + ?Sized> Clone for ConvertedPrimitive<S> {
1464 fn clone(&self) -> Self {
1465 Self {
1466 converted: self.converted.clone(),
1467 original: self.original.clone(),
1468 }
1469 }
1470}
1471
1472impl<S: Schema + ?Sized> ConvertedPrimitive<S> {
1473 pub(crate) fn port_map(&self) -> &HashMap<ArcStr, Vec<Node>> {
1474 self.original.port_map()
1475 }
1476}
1477
1478#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize)]
1482#[enumify::enumify(generics_only)]
1483pub(crate) enum RawCellKind<C, S, P, CP> {
1484 Cell(C),
1485 Scir(S),
1486 Primitive(P),
1487 ConvertedPrimitive(CP),
1488}
1489
1490pub(crate) struct RawCellInnerBuilder<S: Schema + ?Sized> {
1491 pub(crate) next_instance_id: InstanceId,
1492 instances: Vec<RawInstanceBuilder<S>>,
1493}
1494
1495impl<S: Schema<Primitive = impl std::fmt::Debug> + ?Sized> std::fmt::Debug
1496 for RawCellInnerBuilder<S>
1497{
1498 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1499 let mut builder = f.debug_struct("RawCellInnerBuilder");
1500 let _ = builder.field("next_instance_id", &self.next_instance_id);
1501 let _ = builder.field("instances", &self.instances);
1502 builder.finish()
1503 }
1504}
1505
1506impl<S: Schema + ?Sized> Default for RawCellInnerBuilder<S> {
1507 fn default() -> Self {
1508 Self {
1509 next_instance_id: Default::default(),
1510 instances: Default::default(),
1511 }
1512 }
1513}
1514
1515impl<S: Schema + ?Sized> RawCellInnerBuilder<S> {
1516 fn build(self) -> RawCellInner<S> {
1517 RawCellInner {
1518 instances: self
1519 .instances
1520 .into_iter()
1521 .map(|builder| builder.build())
1522 .collect(),
1523 }
1524 }
1525}
1526
1527pub(crate) struct RawCellInner<S: Schema + ?Sized> {
1528 pub(crate) instances: Vec<RawInstance<S>>,
1529}
1530
1531impl<S: Schema<Primitive = impl std::fmt::Debug> + ?Sized> std::fmt::Debug for RawCellInner<S> {
1532 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1533 let mut builder = f.debug_struct("RawCellInner");
1534 let _ = builder.field("instances", &self.instances);
1535 builder.finish()
1536 }
1537}
1538
1539impl<S: Schema + ?Sized> Clone for RawCellInner<S> {
1540 fn clone(&self) -> Self {
1541 Self {
1542 instances: self.instances.clone(),
1543 }
1544 }
1545}
1546
1547impl<S: Schema + ?Sized> RawCellInner<S> {
1548 fn convert_schema<S2: FromSchema<S> + ?Sized>(self) -> Result<RawCellInner<S2>> {
1549 Ok(RawCellInner {
1550 instances: self
1551 .instances
1552 .into_iter()
1553 .map(|instance| instance.convert_schema())
1554 .collect::<Result<_>>()?,
1555 })
1556 }
1557}
1558
1559pub struct ScirBinding<S: Schema + ?Sized> {
1561 pub(crate) lib: scir::Library<S>,
1562 pub(crate) cell: scir::CellId,
1563 pub(crate) port_map: HashMap<ArcStr, Vec<Node>>,
1564}
1565
1566impl<S: Schema<Primitive = impl Clone> + ?Sized> Clone for ScirBinding<S> {
1567 fn clone(&self) -> Self {
1568 Self {
1569 lib: self.lib.clone(),
1570 cell: self.cell,
1571 port_map: self.port_map.clone(),
1572 }
1573 }
1574}
1575
1576impl<S: Schema<Primitive = impl std::fmt::Debug> + ?Sized> std::fmt::Debug for ScirBinding<S> {
1577 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1578 let mut builder = f.debug_struct("ScirCellInner");
1579 let _ = builder.field("lib", &self.lib);
1580 let _ = builder.field("cell", &self.cell);
1581 builder.finish()
1582 }
1583}
1584
1585impl<S: Schema + ?Sized> ScirBinding<S> {
1586 pub fn new(lib: scir::Library<S>, cell: scir::CellId) -> Self {
1593 assert!(lib.try_cell(cell).is_some());
1594 Self {
1595 lib,
1596 cell,
1597 port_map: HashMap::new(),
1598 }
1599 }
1600
1601 pub fn connect(&mut self, port: impl Into<ArcStr>, s: impl Flatten<Node>) {
1603 self.port_map.insert(port.into(), s.flatten_vec());
1604 }
1605
1606 pub fn cell(&self) -> &scir::Cell {
1608 self.lib.cell(self.cell)
1609 }
1610
1611 pub fn ports(&self) -> impl Iterator<Item = &ArcStr> {
1613 let cell = self.cell();
1614 cell.ports().map(|port| &cell.signal(port.signal()).name)
1615 }
1616
1617 fn port_map(&self) -> &HashMap<ArcStr, Vec<Node>> {
1618 &self.port_map
1619 }
1620
1621 pub fn convert_schema<S2: FromSchema<S> + ?Sized>(
1623 self,
1624 ) -> substrate::error::Result<ScirBinding<S2>> {
1625 Ok(ScirBinding {
1626 lib: self
1628 .lib
1629 .convert_schema::<S2>()
1630 .map_err(|_| Error::UnsupportedPrimitive)?
1631 .build()
1632 .unwrap(),
1633 cell: self.cell,
1634 port_map: self.port_map,
1635 })
1636 }
1637}
1638
1639#[derive(Debug, Copy, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
1641pub struct CellId(u64);
1642
1643impl CellId {
1644 pub(crate) fn increment(&mut self) {
1645 let next = self.0.checked_add(1).expect("integer overflow");
1646 *self = CellId(next)
1647 }
1648}
1649
1650#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
1652pub struct InstanceId(pub(crate) u64);
1653
1654impl InstanceId {
1655 pub(crate) fn increment(&mut self) {
1656 let next = self.0.checked_add(1).expect("integer overflow");
1657 *self = InstanceId(next)
1658 }
1659}