1use crate::{attribute::Parameter, logic::Logic};
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, PartialOrd, Ord)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub enum DataType {
13 TwoState,
15 ThreeState,
17 FourState,
19}
20
21impl DataType {
22 pub fn boolean() -> Self {
24 DataType::TwoState
25 }
26
27 pub fn tristate() -> Self {
29 DataType::ThreeState
30 }
31
32 pub fn fourstate() -> Self {
34 DataType::FourState
35 }
36
37 pub fn logic() -> Self {
39 DataType::FourState
40 }
41}
42
43#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
46pub struct Identifier {
47 name: String,
49 escaped: bool,
51 idx: Option<usize>,
53}
54
55impl Identifier {
56 pub fn new(name: String) -> Self {
58 if name.is_empty() {
59 panic!("Identifier name cannot be empty");
60 }
61
62 if let Some(root) = name.strip_prefix('\\') {
63 return Identifier {
64 name: root.to_string(),
65 escaped: true,
66 idx: None,
67 };
68 }
69
70 let esc_chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
72 if esc_chars.contains(&name.chars().next().unwrap()) {
73 return Identifier {
74 name,
75 escaped: true,
76 idx: None,
77 };
78 }
79
80 let esc_chars = [
83 ' ', '\\', '(', ')', ',', '+', '-', '$', '\'', '~', ';', '.', ',', '?', '!',
84 ];
85 if name.chars().any(|c| esc_chars.contains(&c)) {
86 return Identifier {
87 name,
88 escaped: true,
89 idx: None,
90 };
91 }
92
93 if name.contains('[') && name.ends_with(']') {
94 let name_ind = name.find('[').unwrap();
95 let rname = &name[..name_ind];
96 let index_start = name_ind + 1;
97 let slice = name[index_start..name.len() - 1].parse::<usize>();
98 if let Ok(s) = slice {
99 let id = Identifier::new(rname.to_string());
100 if !id.is_sliced() {
101 return Identifier { idx: Some(s), ..id };
102 }
103 }
104 }
105
106 Identifier {
107 name,
108 escaped: false,
109 idx: None,
110 }
111 }
112
113 pub fn new_bus(name: String, bw: usize) -> Vec<Self> {
119 let mut vec = Vec::new();
120 let id = Identifier::new(name.clone());
121 if id.is_sliced() {
122 panic!("Cannot create a bus from an identifier that is sliced by string");
123 }
124 for i in 0..bw {
125 vec.push(Identifier {
126 idx: Some(i),
127 ..id.clone()
128 });
129 }
130 vec
131 }
132
133 pub fn get_stem(&self) -> &str {
135 &self.name
136 }
137
138 pub fn get_bit_index(&self) -> Option<usize> {
140 self.idx
141 }
142
143 pub fn is_sliced(&self) -> bool {
145 self.idx.is_some()
146 }
147
148 pub fn is_escaped(&self) -> bool {
150 self.escaped
151 }
152
153 pub fn emit_name(&self) -> String {
155 let stem = match self.escaped {
156 false => self.name.clone(),
157 true => format!("\\{} ", self.name),
158 };
159 match self.idx {
160 Some(i) => format!("{stem}[{i}]"),
161 None => stem,
162 }
163 }
164}
165
166impl std::ops::Add for &Identifier {
167 type Output = Identifier;
168
169 fn add(self, rhs: Self) -> Identifier {
170 let lname = self.name.as_str();
171 let rname = rhs.name.as_str();
172 let escaped = self.escaped || rhs.escaped;
173
174 let new_name = match (self.idx, rhs.idx) {
175 (Some(l), Some(r)) => {
176 format!("{}_{}_{}_{}", lname, l, rname, r)
177 }
178 (Some(l), None) => format!("{}_{}_{}", lname, l, rname),
179 (None, Some(r)) => format!("{}_{}_{}", lname, rname, r),
180 _ => format!("{}_{}", lname, rname),
181 };
182
183 Identifier {
184 name: new_name,
185 escaped,
186 idx: None,
187 }
188 }
189}
190
191impl std::ops::Add for Identifier {
192 type Output = Identifier;
193
194 fn add(self, rhs: Self) -> Identifier {
195 &self + &rhs
196 }
197}
198
199impl From<&str> for Identifier {
200 fn from(name: &str) -> Self {
201 Identifier::new(name.to_string())
202 }
203}
204
205impl From<String> for Identifier {
206 fn from(name: String) -> Self {
207 Identifier::new(name)
208 }
209}
210
211impl std::fmt::Display for Identifier {
212 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
213 if self.escaped {
214 write!(f, "\\")?;
215 }
216 write!(f, "{}", self.name)?;
217 if self.escaped {
218 write!(f, " ")?;
219 }
220 if let Some(idx) = self.idx {
221 write!(f, "[{idx}]")?;
222 }
223 Ok(())
224 }
225}
226
227#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
229#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
230pub struct Net {
231 identifier: Identifier,
232 data_type: DataType,
233}
234
235impl Net {
236 pub fn new(identifier: Identifier, data_type: DataType) -> Self {
238 Self {
239 identifier,
240 data_type,
241 }
242 }
243
244 pub fn new_logic(name: Identifier) -> Self {
246 Self::new(name, DataType::logic())
247 }
248
249 pub fn new_logic_bus(name: String, bw: usize) -> Vec<Self> {
251 let ids = Identifier::new_bus(name, bw);
252 ids.into_iter()
253 .map(|id| Self::new(id, DataType::logic()))
254 .collect()
255 }
256
257 pub fn set_identifier(&mut self, identifier: Identifier) {
259 self.identifier = identifier;
260 }
261
262 pub fn get_identifier(&self) -> &Identifier {
264 &self.identifier
265 }
266
267 pub fn take_identifier(self) -> Identifier {
269 self.identifier
270 }
271
272 pub fn get_type(&self) -> &DataType {
274 &self.data_type
275 }
276
277 pub fn with_name(&self, name: Identifier) -> Self {
279 Self::new(name, self.data_type)
280 }
281}
282
283#[macro_export]
285macro_rules! format_id {
286 ($($arg:tt)*) => {
287 $crate::Identifier::new(format!($($arg)*))
288 }
289}
290
291impl std::fmt::Display for Net {
292 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
293 self.identifier.fmt(f)
294 }
295}
296
297impl From<&str> for Net {
298 fn from(name: &str) -> Self {
299 Net::new_logic(name.into())
300 }
301}
302
303pub trait Instantiable: Clone {
305 fn get_name(&self) -> &Identifier;
307
308 fn get_input_ports(&self) -> impl IntoIterator<Item = &Net>;
310
311 fn get_output_ports(&self) -> impl IntoIterator<Item = &Net>;
313
314 fn has_parameter(&self, id: &Identifier) -> bool;
316
317 fn get_parameter(&self, id: &Identifier) -> Option<Parameter>;
319
320 fn set_parameter(&mut self, id: &Identifier, val: Parameter) -> Option<Parameter>;
322
323 fn parameters(&self) -> impl Iterator<Item = (Identifier, Parameter)>;
325
326 fn from_constant(val: Logic) -> Option<Self>;
329
330 fn get_constant(&self) -> Option<Logic>;
332
333 fn is_seq(&self) -> bool;
335
336 fn is_parameterized(&self) -> bool {
338 self.parameters().next().is_some()
339 }
340
341 fn get_single_output_port(&self) -> &Net {
343 let mut iter = self.get_output_ports().into_iter();
344 let ret = iter.next().expect("Primitive has no output ports");
345 if iter.next().is_some() {
346 panic!("Primitive has more than one output port");
347 }
348 ret
349 }
350
351 fn get_output_port(&self, index: usize) -> &Net {
356 self.get_output_ports()
357 .into_iter()
358 .nth(index)
359 .expect("Index out of bounds for output ports")
360 }
361
362 fn get_input_port(&self, index: usize) -> &Net {
367 self.get_input_ports()
368 .into_iter()
369 .nth(index)
370 .expect("Index out of bounds for output ports")
371 }
372
373 fn find_input(&self, id: &Identifier) -> Option<usize> {
376 self.get_input_ports()
377 .into_iter()
378 .position(|n| n.get_identifier() == id)
379 }
380
381 fn find_output(&self, id: &Identifier) -> Option<usize> {
384 self.get_output_ports()
385 .into_iter()
386 .position(|n| n.get_identifier() == id)
387 }
388
389 fn is_driverless(&self) -> bool {
392 self.get_input_ports().into_iter().next().is_none()
393 }
394}
395
396#[derive(Debug, Clone)]
398#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
399pub enum Object<I>
400where
401 I: Instantiable,
402{
403 Input(Net),
405 Instance(Vec<Net>, Identifier, I),
407}
408
409impl<I> Object<I>
410where
411 I: Instantiable,
412{
413 pub fn get_single_net(&self) -> &Net {
415 match self {
416 Object::Input(net) => net,
417 Object::Instance(nets, _, _) => {
418 if nets.len() > 1 {
419 panic!("Instance has more than one output net");
420 } else {
421 nets.first().expect("Instance has no output net")
422 }
423 }
424 }
425 }
426
427 pub fn get_net(&self, index: usize) -> &Net {
429 match self {
430 Object::Input(net) => {
431 if index > 0 {
432 panic!("Index out of bounds for input net.")
433 }
434 net
435 }
436 Object::Instance(nets, _, _) => &nets[index],
437 }
438 }
439
440 pub fn get_instance_type(&self) -> Option<&I> {
442 match self {
443 Object::Input(_) => None,
444 Object::Instance(_, _, instance) => Some(instance),
445 }
446 }
447
448 pub fn get_instance_type_mut(&mut self) -> Option<&mut I> {
450 match self {
451 Object::Input(_) => None,
452 Object::Instance(_, _, instance) => Some(instance),
453 }
454 }
455
456 pub fn get_nets(&self) -> &[Net] {
458 match self {
459 Object::Input(net) => std::slice::from_ref(net),
460 Object::Instance(nets, _, _) => nets,
461 }
462 }
463
464 pub fn get_nets_mut(&mut self) -> &mut [Net] {
466 match self {
467 Object::Input(net) => std::slice::from_mut(net),
468 Object::Instance(nets, _, _) => nets,
469 }
470 }
471}
472
473impl<I> std::fmt::Display for Object<I>
474where
475 I: Instantiable,
476{
477 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
478 match self {
479 Object::Input(net) => write!(f, "Input({net})"),
480 Object::Instance(_nets, name, instance) => {
481 write!(f, "{}({})", instance.get_name(), name)
482 }
483 }
484 }
485}
486
487#[cfg(test)]
488mod tests {
489 use super::*;
490
491 #[test]
492 fn identifier_parsing() {
493 let id = Identifier::new("wire".to_string());
494 assert!(!id.is_escaped());
495 assert!(!id.is_sliced());
496 assert!(id.get_bit_index().is_none());
497 let id = Identifier::new("\\wire".to_string());
498 assert!(id.is_escaped());
499 assert!(!id.is_sliced());
500 let id = Identifier::new("wire[3]".to_string());
501 assert!(!id.is_escaped());
502 assert!(id.is_sliced());
503 assert_eq!(id.get_bit_index(), Some(3));
504 }
505
506 #[test]
507 fn assume_escaped_identifier() {
508 let id = Identifier::new("C++".to_string());
509 assert!(id.is_escaped());
510 }
511
512 #[test]
513 fn identifier_emission() {
514 let id = Identifier::new("wire".to_string());
515 assert_eq!(id.emit_name(), "wire");
516 let id = Identifier::new("\\wire".to_string());
517 assert!(id.is_escaped());
518 assert_eq!(id.emit_name(), "\\wire ");
519 assert_eq!(format!("{id}"), "\\wire ");
520 let id = Identifier::new("wire[3]".to_string());
521 assert!(id.is_sliced());
522 assert_eq!(id.emit_name(), "wire[3]");
523 }
524
525 #[test]
526 fn test_implicits() {
527 let net: Net = "hey".into();
528 assert_ne!(*net.get_type(), DataType::boolean());
529 assert_ne!(*net.get_type(), DataType::tristate());
530 assert_eq!(*net.get_type(), DataType::logic());
531 assert_eq!(*net.get_type(), DataType::fourstate());
532 }
533}