bitsy_lang/
circuit.rs

1mod check;
2mod mlir;
3
4use super::*;
5use std::collections::BTreeSet;
6use std::sync::Arc;
7
8/// A [`Circuit`] is a module instance.
9/// It allows you to walk the instance, following references to definitions.
10#[derive(Debug, Clone)]
11pub struct Circuit(pub(crate) Package, pub(crate) Arc<Component>);
12
13impl Circuit {
14    pub fn package(&self) -> &Package {
15        &self.0
16    }
17
18    /// The module definition for this [`Circuit`].
19    pub fn top(&self) -> Arc<Component> {
20        self.1.clone()
21    }
22
23    /// Dot into the given path.
24    /// Follow [`Component::ModInst`]s to their definitions.
25    pub fn component(&self, path: Path) -> Option<Arc<Component>> {
26        if path == "top".into() {
27            return Some(self.top());
28        }
29        let root_prefix = format!("top.");
30        if !path.starts_with(&root_prefix) {
31            return None;
32        }
33        let path: Path = path[root_prefix.len()..].into();
34        self.component_from(self.top(), path)
35    }
36
37    fn component_from(&self, component: Arc<Component>, path: Path) -> Option<Arc<Component>> {
38        let mut result: Arc<Component> = component;
39        for part in path.split(".") {
40            if let Some(child) = result.child(part) {
41                if let Component::ModInst(_loc, _name, moddef) = &*child {
42                    result = moddef.clone();
43                } else {
44                    result = child.clone();
45                }
46            }
47        }
48        Some(result)
49    }
50
51    /// Walk the instance's module hierarchy, returning all [`Wire`]s.
52    pub fn wires(&self) -> Vec<(Path, Wire)> {
53        let mut results = vec![];
54        for (path, component) in self.walk_instances() {
55            for wire in component.wires() {
56                // TODO _loc should be loc?
57                results.push((path.clone(), wire));
58            }
59        }
60        results
61    }
62
63    pub fn exts(&self) -> Vec<Path> {
64        let mut results = vec![];
65        for (path, component) in self.walk_instances() {
66            if let Component::Ext(_loc, _name, _children) = &*component {
67                results.push(path);
68            }
69        }
70        results
71    }
72
73    /// Walk the instance's module hierarchy, returning all [`Wire`]s.
74    pub fn regs(&self) -> Vec<Path> {
75        let mut results = vec![];
76        for (path, component) in self.walk_instances() {
77            if let Component::Reg(_loc, _name, _typ, _reset) = &*component {
78                results.push(path);
79            }
80        }
81        results
82    }
83
84    /// Walk the instance's module hierarchy, returning all [`Path`]s for everything.
85    pub fn paths(&self) -> Vec<Path> {
86        self.top().paths_rec("top".into())
87    }
88
89    /// Given a [`Path`], if it is a [`Component::Reg`], return its reset value.
90    pub fn reset_for_reg(&self, path: Path) -> Option<Arc<Expr>> {
91        if let Component::Reg(_loc, _name, _typ, reset) = &*self.component(path)? {
92            reset.clone()
93        } else {
94            None
95        }
96    }
97
98    fn walk_instances(&self) -> Vec<(Path, Arc<Component>)> {
99        self.walk_instances_rec(self.top(), "top".into())
100    }
101
102    fn walk_instances_rec(
103        &self,
104        component: Arc<Component>,
105        path: Path,
106    ) -> Vec<(Path, Arc<Component>)> {
107        let mut results = vec![(path.clone(), component.clone())];
108        for child in component.children() {
109            if let Component::ModInst(_loc, name, reference) = &*child {
110                if let Some(moddef) = self.package().moddef(reference.name()) {
111                    results.extend(
112                        self.walk_instances_rec(moddef.clone(), path.join(child.name().into())),
113                    );
114                } else {
115                    panic!("Undefined reference to ext: {name}")
116                }
117            } else {
118                results
119                    .extend(self.walk_instances_rec(child.clone(), path.join(child.name().into())));
120            }
121        }
122        results
123    }
124}