spade_mir/
unit_name.rs
1use std::collections::{BTreeMap, HashMap};
2
3use derive_where::derive_where;
4use itertools::Itertools;
5use serde::{Deserialize, Serialize};
6use spade_common::name::{NameID, Path};
7
8#[derive(Serialize, Deserialize, Debug)]
40pub struct InstanceMap {
41 pub inner: HashMap<NameID, BTreeMap<String, NameID>>,
42}
43
44impl Default for InstanceMap {
45 fn default() -> Self {
46 Self::new()
47 }
48}
49
50impl InstanceMap {
51 pub fn new() -> Self {
52 Self {
53 inner: HashMap::new(),
54 }
55 }
56}
57
58pub struct InstanceNameTracker {
59 previous_names: HashMap<String, usize>,
60}
61
62impl Default for InstanceNameTracker {
63 fn default() -> Self {
64 Self::new()
65 }
66}
67
68impl InstanceNameTracker {
69 pub fn new() -> Self {
70 Self {
71 previous_names: HashMap::new(),
72 }
73 }
74
75 pub fn use_name(
76 &mut self,
77 unit_name: NameID,
79 instance_name: &str,
82 in_unit: NameID,
84 map: &mut InstanceMap,
85 ) -> String {
86 let e = self
87 .previous_names
88 .entry(instance_name.to_string())
89 .or_default();
90 let result = format!("{instance_name}_{e}");
91 *e += 1;
92
93 map.inner
94 .entry(in_unit)
95 .or_default()
96 .insert(result.clone(), unit_name);
97
98 result
99 }
100}
101
102#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
103pub enum UnitNameKind {
105 Unescaped(String),
110 Escaped { name: String, path: Vec<String> },
113}
114
115#[derive_where(PartialOrd, Ord, PartialEq, Eq, Hash)]
116#[derive(Clone, Debug)]
117pub struct UnitName {
118 pub kind: UnitNameKind,
119 #[derive_where(skip)]
120 pub source: NameID,
121}
122
123impl UnitName {
124 pub fn _test_from_strs(strs: &[&str]) -> Self {
127 UnitName {
128 source: NameID(0, Path::from_strs(strs)),
129 kind: UnitNameKind::Escaped {
130 name: strs.iter().join("::"),
131 path: strs.iter().map(|s| s.to_string()).collect(),
132 },
133 }
134 }
135 pub fn as_verilog(&self) -> String {
136 match &self.kind {
137 UnitNameKind::Unescaped(name) => name.clone(),
138 UnitNameKind::Escaped { name, path: _ } => format!("\\{name} "),
139 }
140 }
141
142 pub fn instance_name(
143 &self,
144 inside: NameID,
145 instance_map: &mut InstanceMap,
146 names: &mut InstanceNameTracker,
147 ) -> String {
148 let name = match &self.kind {
149 UnitNameKind::Escaped { name, path } => path.last().unwrap_or(name),
150 UnitNameKind::Unescaped(name) => name,
151 };
152 names.use_name(self.source.clone(), name, inside, instance_map)
153 }
154
155 pub fn without_escapes(&self) -> &str {
158 match &self.kind {
159 UnitNameKind::Escaped { name, path: _ } => name,
160 UnitNameKind::Unescaped(s) => s,
161 }
162 }
163}
164
165impl std::fmt::Display for UnitName {
166 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167 write!(f, "{}", self.as_verilog())
168 }
169}
170
171pub trait IntoUnitName {
172 fn _test_into_unit_name(&self) -> UnitName;
173}
174
175impl<'a, T> IntoUnitName for T
176where
177 T: AsRef<[&'a str]>,
178{
179 fn _test_into_unit_name(&self) -> UnitName {
180 UnitName {
181 kind: UnitNameKind::Escaped {
182 name: self.as_ref().iter().join("::"),
183 path: self.as_ref().iter().map(|s| s.to_string()).collect(),
184 },
185 source: NameID(0, Path::from_strs(self.as_ref())),
186 }
187 }
188}
189
190impl IntoUnitName for str {
191 fn _test_into_unit_name(&self) -> UnitName {
192 UnitName {
193 kind: UnitNameKind::Unescaped(self.to_string()),
194 source: NameID(0, Path::from_strs(&[self])),
195 }
196 }
197}
198
199impl IntoUnitName for UnitName {
200 fn _test_into_unit_name(&self) -> UnitName {
201 self.clone()
202 }
203}