1use crate::block::Block;
4use crate::diagnostics::SourceInfo;
5use crate::schematic::{CellId, HasNestedView, InstanceId, InstancePath, NestedView};
6use crate::types::{FlatLen, Flatten};
7use arcstr::ArcStr;
8use scir::Direction;
9use serde::{Deserialize, Serialize};
10use std::collections::{BTreeMap, HashMap};
11use std::ops::Deref;
12
13use super::{Array, ArrayBundle, BundleKind, HasBundleKind, Io, Signal, Unflatten};
14
15pub trait HasNodeBundle: HasBundleKind + Sized + Send + Sync {
17 type NodeBundle: HasNestedView<NestedView: HasBundleKind<BundleKind = <Self as HasBundleKind>::BundleKind>>
19 + HasBundleKind<BundleKind = <Self as HasBundleKind>::BundleKind>
20 + Unflatten<<Self as HasBundleKind>::BundleKind, Node>
21 + Flatten<Node>;
22}
23
24pub trait HasTerminalBundle: HasBundleKind + Sized + Send + Sync {
26 type TerminalBundle: HasNestedView<NestedView: HasBundleKind<BundleKind = <Self as HasBundleKind>::BundleKind>>
28 + HasBundleKind<BundleKind = <Self as HasBundleKind>::BundleKind>
29 + Unflatten<<Self as HasBundleKind>::BundleKind, Terminal>
30 + Flatten<Terminal>
31 + Flatten<Node>;
32}
33
34pub trait SchematicBundleKind: BundleKind + HasNodeBundle + HasTerminalBundle {
36 fn terminal_view(
38 cell: CellId,
39 cell_io: &NodeBundle<Self>,
40 instance: InstanceId,
41 instance_io: &NodeBundle<Self>,
42 ) -> TerminalBundle<Self>;
43}
44
45pub trait DataView<T: SchematicBundleKind>: SchematicBundleKind {
47 fn view_nodes_as(nodes: &NodeBundle<Self>) -> NodeBundle<T>;
49
50 fn view_terminals_as(terminals: &TerminalBundle<Self>) -> TerminalBundle<T> {
52 let kind = terminals.kind();
54 let flat_terminals = Flatten::<Terminal>::flatten_vec(terminals);
55 let terminal_map = flat_terminals
56 .iter()
57 .map(|terminal| (terminal.instance_node, terminal))
58 .collect::<HashMap<_, _>>();
59 let mut flat_nodes = flat_terminals.iter().map(|terminal| terminal.instance_node);
60 let nodes = NodeBundle::<Self>::unflatten(&kind, &mut flat_nodes).unwrap();
61 let nodes_view = Self::view_nodes_as(&nodes);
62 let nodes_view_kind = nodes_view.kind();
63 let flat_nodes_view = Flatten::<Node>::flatten_vec(&nodes_view);
64 let mut flat_terminals_view = flat_nodes_view.iter().map(|node| *terminal_map[node]);
65 TerminalBundle::<T>::unflatten(&nodes_view_kind, &mut flat_terminals_view).unwrap()
66 }
67}
68
69impl<T: SchematicBundleKind> DataView<Array<Signal>> for T {
70 fn view_nodes_as(nodes: &NodeBundle<Self>) -> NodeBundle<Array<Signal>> {
71 ArrayBundle::new(
72 Signal,
73 <NodeBundle<Self> as Flatten<Node>>::flatten_vec(nodes),
74 )
75 }
76}
77
78pub type IoNodeBundle<T> = NodeBundle<<T as Block>::Io>;
80pub type IoTerminalBundle<T> = TerminalBundle<<T as Block>::Io>;
82pub type NodeBundle<T> = <<T as HasBundleKind>::BundleKind as HasNodeBundle>::NodeBundle;
84pub type TerminalBundle<T> =
86 <<T as HasBundleKind>::BundleKind as HasTerminalBundle>::TerminalBundle;
87
88#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
90pub(crate) enum NodePriority {
91 Io = 3,
95 Named = 2,
97 Auto = 1,
101}
102
103pub type NodeUf = ena::unify::InPlaceUnificationTable<Node>;
105
106#[derive(Clone, Debug)]
107pub(crate) struct NodeConnectDirectionError {
108 #[allow(dead_code)]
109 data: Vec<[(Direction, NodeDriverData); 2]>,
110}
111
112#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
114pub struct Node(u32);
115
116impl FlatLen for Node {
117 fn len(&self) -> usize {
118 1
119 }
120}
121
122impl Flatten<Node> for Node {
123 fn flatten<E>(&self, output: &mut E)
124 where
125 E: Extend<Node>,
126 {
127 output.extend(std::iter::once(*self));
128 }
129}
130
131impl Unflatten<Signal, Node> for Node {
132 fn unflatten<I>(_data: &Signal, source: &mut I) -> Option<Self>
133 where
134 I: Iterator<Item = Node>,
135 {
136 source.next()
137 }
138}
139
140impl HasBundleKind for Node {
141 type BundleKind = Signal;
142
143 fn kind(&self) -> Self::BundleKind {
144 Signal
145 }
146}
147
148impl HasNestedView for Node {
149 type NestedView = NestedNode;
150 fn nested_view(&self, parent: &InstancePath) -> NestedView<Self> {
151 NestedNode {
152 node: *self,
153 instances: parent.clone(),
154 }
155 }
156}
157
158#[derive(Clone, Debug)]
162pub struct NestedNode {
163 pub(crate) instances: InstancePath,
164 pub(crate) node: Node,
165}
166
167#[derive(Clone, Debug)]
171pub struct RawNestedNode {
172 pub(crate) instances: InstancePath,
173 pub(crate) tail: ArcStr,
174}
175
176impl RawNestedNode {
177 pub fn new(instances: InstancePath, tail: impl Into<ArcStr>) -> Self {
179 Self {
180 instances,
181 tail: tail.into(),
182 }
183 }
184
185 pub fn instances(&self) -> &InstancePath {
189 &self.instances
190 }
191
192 pub fn tail(&self) -> &ArcStr {
194 &self.tail
195 }
196}
197
198impl HasNestedView for RawNestedNode {
199 type NestedView = RawNestedNode;
200 fn nested_view(&self, parent: &InstancePath) -> NestedView<Self> {
201 RawNestedNode {
202 tail: self.tail.clone(),
203 instances: self.instances.prepend(parent),
204 }
205 }
206}
207
208#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
210pub struct NodePath {
211 pub(crate) top: CellId,
212 pub(crate) instances: Vec<InstanceId>,
213 pub(crate) node: Node,
214}
215
216impl NestedNode {
217 pub fn path(&self) -> NodePath {
219 NodePath {
220 top: self.instances.top,
221 instances: self.instances.path.iter().copied().collect(),
222 node: self.node,
223 }
224 }
225}
226
227impl FlatLen for NestedNode {
228 fn len(&self) -> usize {
229 1
230 }
231}
232
233impl Flatten<NestedNode> for NestedNode {
234 fn flatten<E>(&self, output: &mut E)
235 where
236 E: Extend<NestedNode>,
237 {
238 output.extend(std::iter::once(self.clone()));
239 }
240}
241
242impl HasBundleKind for NestedNode {
243 type BundleKind = Signal;
244
245 fn kind(&self) -> Self::BundleKind {
246 Signal
247 }
248}
249
250impl HasNestedView for NestedNode {
251 type NestedView = NestedNode;
252 fn nested_view(&self, parent: &InstancePath) -> NestedView<Self> {
253 NestedNode {
254 node: self.node,
255 instances: self.instances.prepend(parent),
256 }
257 }
258}
259
260impl FlatLen for Vec<Node> {
261 fn len(&self) -> usize {
262 self.len()
263 }
264}
265
266impl Flatten<Node> for Vec<Node> {
267 fn flatten<E>(&self, output: &mut E)
268 where
269 E: Extend<Node>,
270 {
271 output.extend(self.iter().copied());
272 }
273}
274
275impl From<NestedNode> for NodePath {
276 fn from(value: NestedNode) -> Self {
277 value.path()
278 }
279}
280
281impl From<&NestedNode> for NodePath {
282 fn from(value: &NestedNode) -> Self {
283 value.path()
284 }
285}
286
287#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
289pub struct Terminal {
290 pub(crate) cell_id: CellId,
291 pub(crate) cell_node: Node,
292 pub(crate) instance_id: InstanceId,
293 pub(crate) instance_node: Node,
294}
295
296impl Deref for Terminal {
297 type Target = Node;
298
299 fn deref(&self) -> &Self::Target {
300 &self.instance_node
301 }
302}
303
304impl AsRef<Node> for Terminal {
305 fn as_ref(&self) -> &Node {
306 self
307 }
308}
309
310impl FlatLen for Terminal {
311 fn len(&self) -> usize {
312 1
313 }
314}
315
316impl Flatten<Node> for Terminal {
317 fn flatten<E>(&self, output: &mut E)
318 where
319 E: Extend<Node>,
320 {
321 output.extend(std::iter::once(self.instance_node));
322 }
323}
324
325impl Flatten<Terminal> for Terminal {
326 fn flatten<E>(&self, output: &mut E)
327 where
328 E: Extend<Terminal>,
329 {
330 output.extend(std::iter::once(*self));
331 }
332}
333
334impl Unflatten<Signal, Terminal> for Terminal {
335 fn unflatten<I>(_data: &Signal, source: &mut I) -> Option<Self>
336 where
337 I: Iterator<Item = Terminal>,
338 {
339 source.next()
340 }
341}
342
343impl HasBundleKind for Terminal {
344 type BundleKind = Signal;
345
346 fn kind(&self) -> Self::BundleKind {
347 Signal
348 }
349}
350
351impl HasNestedView for Terminal {
352 type NestedView = NestedTerminal;
353 fn nested_view(&self, parent: &InstancePath) -> NestedView<Self> {
354 NestedTerminal(NestedNode {
355 instances: parent.append_segment(self.instance_id, self.cell_id),
356 node: self.cell_node,
357 })
358 }
359}
360
361#[derive(Clone, Debug)]
363pub struct NestedTerminal(NestedNode);
364
365impl Deref for NestedTerminal {
366 type Target = NestedNode;
367
368 fn deref(&self) -> &Self::Target {
369 &self.0
370 }
371}
372
373impl AsRef<NestedNode> for NestedTerminal {
374 fn as_ref(&self) -> &NestedNode {
375 self
376 }
377}
378
379impl NestedTerminal {
380 pub fn path(&self) -> TerminalPath {
382 TerminalPath(self.0.path())
383 }
384}
385
386impl FlatLen for NestedTerminal {
387 fn len(&self) -> usize {
388 1
389 }
390}
391
392impl Flatten<NestedTerminal> for NestedTerminal {
393 fn flatten<E>(&self, output: &mut E)
394 where
395 E: Extend<NestedTerminal>,
396 {
397 output.extend(std::iter::once(self.clone()));
398 }
399}
400
401impl HasBundleKind for NestedTerminal {
402 type BundleKind = Signal;
403
404 fn kind(&self) -> Self::BundleKind {
405 Signal
406 }
407}
408
409impl HasNestedView for NestedTerminal {
410 type NestedView = NestedTerminal;
411 fn nested_view(&self, parent: &InstancePath) -> NestedView<Self> {
412 NestedTerminal(<NestedNode as HasNestedView>::nested_view(&self.0, parent))
413 }
414}
415
416#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
418pub struct TerminalPath(NodePath);
419
420impl Deref for TerminalPath {
421 type Target = NodePath;
422
423 fn deref(&self) -> &Self::Target {
424 &self.0
425 }
426}
427
428impl AsRef<NodePath> for TerminalPath {
429 fn as_ref(&self) -> &NodePath {
430 self
431 }
432}
433
434impl From<NestedTerminal> for TerminalPath {
435 fn from(value: NestedTerminal) -> Self {
436 value.path()
437 }
438}
439
440impl From<&NestedTerminal> for TerminalPath {
441 fn from(value: &NestedTerminal) -> Self {
442 value.path()
443 }
444}
445
446#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
448#[doc(hidden)]
449pub struct NodeUfValue {
450 priority: NodePriority,
455
456 pub(crate) source: Node,
461}
462
463impl ena::unify::UnifyValue for NodeUfValue {
464 type Error = ena::unify::NoError;
465
466 fn unify_values(value1: &Self, value2: &Self) -> std::result::Result<Self, Self::Error> {
467 if value1.priority == NodePriority::Io
468 && value2.priority == NodePriority::Io
469 && value1.source != value2.source
470 {
471 panic!("shorted IOs are not supported")
472 }
473 Ok(if value1.priority >= value2.priority {
474 *value1
475 } else {
476 *value2
477 })
478 }
479}
480
481impl ena::unify::UnifyKey for Node {
482 type Value = Option<NodeUfValue>;
483 fn index(&self) -> u32 {
484 self.0
485 }
486
487 fn from_index(u: u32) -> Self {
488 Self(u)
489 }
490
491 fn tag() -> &'static str {
492 "Node"
493 }
494}
495
496#[derive(Clone)]
497pub(crate) struct NodeContext {
498 uf: NodeUf,
499 connections_data: Vec<Option<NodeConnectionsData>>,
500}
501
502#[derive(Clone, Debug)]
503struct NodeConnectionsData {
504 drivers: BTreeMap<Direction, NodeDriverData>,
506}
507
508impl NodeConnectionsData {
509 fn merge_from(&mut self, other: Self) {
510 for (direction, data) in other.drivers {
511 use std::collections::btree_map::Entry;
512 match self.drivers.entry(direction) {
513 Entry::Vacant(entry) => {
514 entry.insert(data);
515 }
516 Entry::Occupied(mut entry) => {
517 entry.get_mut().merge_from(data);
518 }
519 }
520 }
521 }
522
523 fn from_single(direction: Direction, source_info: SourceInfo) -> Self {
524 Self {
525 drivers: [(direction, NodeDriverData::from_single(source_info))].into(),
526 }
527 }
528
529 fn empty() -> Self {
530 Self { drivers: [].into() }
531 }
532}
533
534impl Default for NodeConnectionsData {
535 fn default() -> Self {
536 Self::empty()
537 }
538}
539
540#[derive(Clone, Debug)]
542struct NodeDriverData {
543 sources: Vec<SourceInfo>,
547}
548
549impl NodeDriverData {
550 fn merge_from(&mut self, other: Self) {
551 self.sources.extend(other.sources);
552 }
553
554 fn from_single(source_info: SourceInfo) -> Self {
555 Self {
556 sources: vec![source_info],
557 }
558 }
559}
560
561impl NodeContext {
562 #[inline]
563 pub(crate) fn new() -> Self {
564 Self {
565 uf: Default::default(),
566 connections_data: vec![],
567 }
568 }
569
570 fn connections_data(&self, node: Node) -> &Option<NodeConnectionsData> {
571 &self.connections_data[usize::try_from(ena::unify::UnifyKey::index(&node)).unwrap()]
572 }
573
574 fn connections_data_mut(&mut self, node: Node) -> &mut Option<NodeConnectionsData> {
575 &mut self.connections_data[usize::try_from(ena::unify::UnifyKey::index(&node)).unwrap()]
576 }
577
578 pub(crate) fn node(
579 &mut self,
580 direction: Option<Direction>,
581 priority: NodePriority,
582 source_info: SourceInfo,
583 ) -> Node {
584 let id = self.uf.new_key(Default::default());
585
586 assert_eq!(
587 usize::try_from(ena::unify::UnifyKey::index(&id)).unwrap(),
588 self.connections_data.len()
589 );
590 self.connections_data.push(Some(
591 direction
592 .map(|direction| NodeConnectionsData::from_single(direction, source_info))
593 .unwrap_or_default(),
594 ));
595 debug_assert!(self.connections_data_mut(id).is_some());
597
598 self.uf.union_value(
599 id,
600 Some(NodeUfValue {
601 priority,
602 source: id,
603 }),
604 );
605
606 id
607 }
608
609 #[inline]
610 pub fn into_uf(self) -> NodeUf {
611 self.uf
612 }
613
614 fn nodes_directed(
615 &mut self,
616 directions: &[Direction],
617 priority: NodePriority,
618 source_info: SourceInfo,
619 ) -> Vec<Node> {
620 directions
621 .iter()
622 .map(|dir| self.node(Some(*dir), priority, source_info.clone()))
623 .collect()
624 }
625
626 fn nodes_undirected(
627 &mut self,
628 n: usize,
629 priority: NodePriority,
630 source_info: SourceInfo,
631 ) -> Vec<Node> {
632 (0..n)
633 .map(|_| self.node(None, priority, source_info.clone()))
634 .collect()
635 }
636
637 pub fn instantiate_directed<IO: Io + HasBundleKind<BundleKind: SchematicBundleKind>>(
638 &mut self,
639 io: &IO,
640 priority: NodePriority,
641 source_info: SourceInfo,
642 ) -> (Vec<Node>, NodeBundle<IO>) {
643 let nodes = self.nodes_directed(&io.flatten_vec(), priority, source_info);
644 let data = NodeBundle::<IO>::unflatten(&io.kind(), &mut nodes.iter().copied()).unwrap();
645 (nodes, data)
646 }
647
648 pub fn instantiate_undirected<K: HasBundleKind<BundleKind: SchematicBundleKind>>(
649 &mut self,
650 kind: &K,
651 priority: NodePriority,
652 source_info: SourceInfo,
653 ) -> (Vec<Node>, NodeBundle<K>) {
654 let kind = kind.kind();
655 let nodes = self.nodes_undirected(kind.len(), priority, source_info);
656 let data = NodeBundle::<K>::unflatten(&kind, &mut nodes.iter().copied()).unwrap();
657 (nodes, data)
658 }
659
660 pub(crate) fn connect(&mut self, n1: Node, n2: Node, source_info: SourceInfo) {
661 fn get_root(this: &mut NodeContext, n: Node) -> Node {
662 this.uf
663 .probe_value(n)
664 .expect("node should be populated")
665 .source
666 }
667
668 let n1_root = get_root(self, n1);
669 let n2_root = get_root(self, n2);
670
671 if n1_root == n2_root {
672 tracing::info!(?source_info, "connecting nodes that are already connected");
673 return;
674 }
675
676 let n1_connections_data = self
677 .connections_data(n1_root)
678 .as_ref()
679 .expect("n1 should be populated");
680 let n2_connections_data = self
681 .connections_data(n2_root)
682 .as_ref()
683 .expect("n1 should be populated");
684
685 let incompatible_drivers: Vec<_> = n1_connections_data
687 .drivers
688 .iter()
689 .flat_map(|e1| n2_connections_data.drivers.iter().map(move |e2| [e1, e2]))
690 .filter(|[(k1, _), (k2, _)]| !k1.is_compatible_with(**k2))
691 .collect();
692 if !incompatible_drivers.is_empty() {
693 let err = NodeConnectDirectionError {
698 data: incompatible_drivers
699 .iter()
700 .map(|&[(&k1, v1), (&k2, v2)]| [(k1, v1.clone()), (k2, v2.clone())])
701 .collect(),
702 };
703 tracing::warn!(?err, "incompatible drivers");
704 }
705
706 self.uf.union(n1, n2);
707
708 let new_root = get_root(self, n1);
709 let old_root = match new_root {
710 x if x == n1_root => n2_root,
711 x if x == n2_root => n1_root,
712 _ => panic!(
713 "connect: new root isn't any of the old roots? (got {:?}, had {:?} {:?})",
714 new_root, n1_root, n2_root
715 ),
716 };
717
718 let old_connections_data = self
719 .connections_data_mut(old_root)
720 .take()
721 .expect("old root should be populated");
722 self.connections_data_mut(new_root)
723 .as_mut()
724 .expect("new root should be populated")
725 .merge_from(old_connections_data);
726 }
727}
728
729#[allow(dead_code)]
731#[derive(Debug, Clone, Serialize, Deserialize)]
732pub struct Port {
733 direction: Direction,
734 node: Node,
735}
736
737impl Port {
738 #[inline]
739 pub(crate) fn new(node: Node, direction: Direction) -> Self {
740 Self { node, direction }
741 }
742
743 #[inline]
744 #[allow(dead_code)]
745 pub(crate) fn direction(&self) -> Direction {
746 self.direction
747 }
748
749 #[inline]
750 pub(crate) fn node(&self) -> Node {
751 self.node
752 }
753}