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 return Identifier {
105 name,
106 escaped: true,
107 idx: None,
108 };
109 }
110
111 Identifier {
112 name,
113 escaped: false,
114 idx: None,
115 }
116 }
117
118 pub fn with_index(self, index: usize) -> Self {
124 if self.idx.is_some() {
125 panic!("Cannot add an index to an identifier that already has one");
126 }
127 Identifier {
128 idx: Some(index),
129 ..self
130 }
131 }
132
133 pub fn new_bus(name: String, bw: usize) -> Vec<Self> {
139 let mut vec = Vec::new();
140 let id = Identifier::new(name.clone());
141 if id.is_sliced() {
142 panic!("Cannot create a bus from an identifier that is sliced by string");
143 }
144 for i in 0..bw {
145 vec.push(Identifier {
146 idx: Some(i),
147 ..id.clone()
148 });
149 }
150 vec
151 }
152
153 pub fn get_stem(&self) -> Identifier {
155 Identifier {
156 name: self.name.clone(),
157 escaped: self.escaped,
158 idx: None,
159 }
160 }
161
162 pub fn get_bit_index(&self) -> Option<usize> {
164 self.idx
165 }
166
167 pub fn is_sliced(&self) -> bool {
169 self.idx.is_some()
170 }
171
172 pub fn is_escaped(&self) -> bool {
174 self.escaped
175 }
176
177 pub fn emit_name(&self) -> String {
179 let stem = match self.escaped {
180 false => self.name.clone(),
181 true => format!("\\{} ", self.name),
182 };
183 match self.idx {
184 Some(i) => format!("{stem}[{i}]"),
185 None => stem,
186 }
187 }
188}
189
190impl std::ops::Add for &Identifier {
191 type Output = Identifier;
192
193 fn add(self, rhs: Self) -> Identifier {
194 let lname = self.name.as_str();
195 let rname = rhs.name.as_str();
196 let escaped = self.escaped || rhs.escaped;
197
198 if !escaped && lname.is_empty() {
199 return rhs.clone();
200 }
201
202 if !escaped && rname.is_empty() {
203 return self.clone();
204 }
205
206 let new_name = match (self.idx, rhs.idx) {
207 (Some(l), Some(r)) => {
208 format!("{}_{}_{}_{}", lname, l, rname, r)
209 }
210 (Some(l), None) => format!("{}_{}_{}", lname, l, rname),
211 (None, Some(r)) => format!("{}_{}_{}", lname, rname, r),
212 _ => format!("{}_{}", lname, rname),
213 };
214
215 Identifier {
216 name: new_name,
217 escaped,
218 idx: None,
219 }
220 }
221}
222
223impl std::ops::Add for Identifier {
224 type Output = Identifier;
225
226 fn add(self, rhs: Self) -> Identifier {
227 &self + &rhs
228 }
229}
230
231impl From<&str> for Identifier {
232 fn from(name: &str) -> Self {
233 Identifier::new(name.to_string())
234 }
235}
236
237impl From<String> for Identifier {
238 fn from(name: String) -> Self {
239 Identifier::new(name)
240 }
241}
242
243impl std::fmt::Display for Identifier {
244 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245 if self.escaped {
246 write!(f, "\\")?;
247 }
248 write!(f, "{}", self.name)?;
249 if self.escaped {
250 write!(f, " ")?;
251 }
252 if let Some(idx) = self.idx {
253 write!(f, "[{idx}]")?;
254 }
255 Ok(())
256 }
257}
258
259#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
261#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
262pub struct Net {
263 identifier: Identifier,
264 data_type: DataType,
265}
266
267impl Net {
268 pub fn new(identifier: Identifier, data_type: DataType) -> Self {
270 Self {
271 identifier,
272 data_type,
273 }
274 }
275
276 pub fn new_logic(name: Identifier) -> Self {
278 Self::new(name, DataType::logic())
279 }
280
281 pub fn new_logic_bus(name: String, bw: usize) -> Vec<Self> {
283 let ids = Identifier::new_bus(name, bw);
284 ids.into_iter()
285 .map(|id| Self::new(id, DataType::logic()))
286 .collect()
287 }
288
289 pub fn set_identifier(&mut self, identifier: Identifier) {
291 self.identifier = identifier;
292 }
293
294 pub fn get_identifier(&self) -> &Identifier {
296 &self.identifier
297 }
298
299 pub fn take_identifier(self) -> Identifier {
301 self.identifier
302 }
303
304 pub fn get_type(&self) -> &DataType {
306 &self.data_type
307 }
308
309 pub fn with_name(&self, name: Identifier) -> Self {
311 Self::new(name, self.data_type)
312 }
313}
314
315#[macro_export]
317macro_rules! format_id {
318 ($($arg:tt)*) => {
319 $crate::Identifier::new(format!($($arg)*))
320 }
321}
322
323impl std::fmt::Display for Net {
324 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
325 self.identifier.fmt(f)
326 }
327}
328
329impl From<&str> for Net {
330 fn from(name: &str) -> Self {
331 Net::new_logic(name.into())
332 }
333}
334
335pub trait Instantiable: Clone {
337 fn get_name(&self) -> &Identifier;
339
340 fn get_input_ports(&self) -> &[Net];
342
343 fn get_output_ports(&self) -> &[Net];
345
346 fn get_parameter(&self, id: &Identifier) -> Option<Parameter>;
348
349 fn set_parameter(&mut self, id: &Identifier, val: Parameter) -> Option<Parameter>;
355
356 fn clear_parameter(&mut self, id: &Identifier) -> Option<Parameter>;
358
359 fn parameters(&self) -> Vec<(Identifier, Parameter)>;
361
362 fn from_constant(val: Logic) -> Option<Self>;
365
366 fn get_constant(&self) -> Option<Logic>;
368
369 fn is_seq(&self) -> bool;
371
372 fn has_parameter(&self, id: &Identifier) -> bool {
374 self.get_parameter(id).is_some()
375 }
376
377 fn verify(&self) -> Result<(), String> {
379 Ok(())
380 }
381
382 fn is_parameterized(&self) -> bool {
384 !self.parameters().is_empty()
385 }
386
387 fn get_single_output_port(&self) -> &Net {
389 if self.get_output_ports().len() > 1 {
390 panic!("Primitive has more than one output port");
391 }
392 &self.get_output_ports()[0]
393 }
394
395 fn get_output_port(&self, index: usize) -> &Net {
400 &self.get_output_ports()[index]
401 }
402
403 fn get_input_port(&self, index: usize) -> &Net {
408 &self.get_input_ports()[index]
409 }
410
411 fn find_input(&self, id: &Identifier) -> Option<usize> {
414 self.get_input_ports()
415 .iter()
416 .position(|n| n.get_identifier() == id)
417 }
418
419 fn find_output(&self, id: &Identifier) -> Option<usize> {
422 self.get_output_ports()
423 .iter()
424 .position(|n| n.get_identifier() == id)
425 }
426
427 fn is_driverless(&self) -> bool {
430 self.get_input_ports().is_empty()
431 }
432
433 fn get_num_input_ports(&self) -> usize {
435 self.get_input_ports().len()
436 }
437
438 fn get_num_output_ports(&self) -> usize {
440 self.get_output_ports().len()
441 }
442}
443
444#[derive(Debug, Clone)]
446#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
447pub enum Object<I>
448where
449 I: Instantiable,
450{
451 Input(Net),
453 Instance(Vec<Net>, Identifier, I),
455}
456
457impl<I> Object<I>
458where
459 I: Instantiable,
460{
461 pub fn get_single_net(&self) -> &Net {
463 match self {
464 Object::Input(net) => net,
465 Object::Instance(nets, _, _) => {
466 if nets.len() > 1 {
467 panic!("Instance has more than one output net");
468 } else {
469 nets.first().expect("Instance has no output net")
470 }
471 }
472 }
473 }
474
475 pub fn get_net(&self, index: usize) -> &Net {
477 match self {
478 Object::Input(net) => {
479 if index > 0 {
480 panic!("Index out of bounds for input net.")
481 }
482 net
483 }
484 Object::Instance(nets, _, _) => &nets[index],
485 }
486 }
487
488 pub fn get_instance_type(&self) -> Option<&I> {
490 match self {
491 Object::Input(_) => None,
492 Object::Instance(_, _, instance) => Some(instance),
493 }
494 }
495
496 pub fn get_instance_type_mut(&mut self) -> Option<&mut I> {
498 match self {
499 Object::Input(_) => None,
500 Object::Instance(_, _, instance) => Some(instance),
501 }
502 }
503
504 pub fn get_nets(&self) -> &[Net] {
506 match self {
507 Object::Input(net) => std::slice::from_ref(net),
508 Object::Instance(nets, _, _) => nets,
509 }
510 }
511
512 pub fn get_nets_mut(&mut self) -> &mut [Net] {
514 match self {
515 Object::Input(net) => std::slice::from_mut(net),
516 Object::Instance(nets, _, _) => nets,
517 }
518 }
519}
520
521impl<I> std::fmt::Display for Object<I>
522where
523 I: Instantiable,
524{
525 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
526 match self {
527 Object::Input(net) => write!(f, "Input({net})"),
528 Object::Instance(_nets, name, instance) => {
529 write!(f, "{}({})", instance.get_name(), name)
530 }
531 }
532 }
533}
534
535#[cfg(test)]
536mod tests {
537 use super::*;
538
539 #[test]
540 fn identifier_parsing() {
541 let id = Identifier::new("wire".to_string());
542 assert!(!id.is_escaped());
543 assert!(!id.is_sliced());
544 assert!(id.get_bit_index().is_none());
545 let id = Identifier::new("\\wire".to_string());
546 assert!(id.is_escaped());
547 assert!(!id.is_sliced());
548 let id = Identifier::new("wire[3]".to_string());
549 assert!(!id.is_escaped());
550 assert!(id.is_sliced());
551 assert_eq!(id.get_bit_index(), Some(3));
552 }
553
554 #[test]
555 fn assume_escaped_identifier() {
556 let id = Identifier::new("C++".to_string());
557 assert!(id.is_escaped());
558 }
559
560 #[test]
561 fn identifier_emission() {
562 let id = Identifier::new("wire".to_string());
563 assert_eq!(id.emit_name(), "wire");
564 let id = Identifier::new("\\wire".to_string());
565 assert!(id.is_escaped());
566 assert_eq!(id.emit_name(), "\\wire ");
567 assert_eq!(format!("{id}"), "\\wire ");
568 let id = Identifier::new("wire[3]".to_string());
569 assert!(id.is_sliced());
570 assert_eq!(id.emit_name(), "wire[3]");
571 }
572
573 #[test]
574 fn test_implicits() {
575 let net: Net = "hey".into();
576 assert_ne!(*net.get_type(), DataType::boolean());
577 assert_ne!(*net.get_type(), DataType::tristate());
578 assert_eq!(*net.get_type(), DataType::logic());
579 assert_eq!(*net.get_type(), DataType::fourstate());
580 }
581}