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 let new_name = match (self.idx, rhs.idx) {
199 (Some(l), Some(r)) => {
200 format!("{}_{}_{}_{}", lname, l, rname, r)
201 }
202 (Some(l), None) => format!("{}_{}_{}", lname, l, rname),
203 (None, Some(r)) => format!("{}_{}_{}", lname, rname, r),
204 _ => format!("{}_{}", lname, rname),
205 };
206
207 Identifier {
208 name: new_name,
209 escaped,
210 idx: None,
211 }
212 }
213}
214
215impl std::ops::Add for Identifier {
216 type Output = Identifier;
217
218 fn add(self, rhs: Self) -> Identifier {
219 &self + &rhs
220 }
221}
222
223impl From<&str> for Identifier {
224 fn from(name: &str) -> Self {
225 Identifier::new(name.to_string())
226 }
227}
228
229impl From<String> for Identifier {
230 fn from(name: String) -> Self {
231 Identifier::new(name)
232 }
233}
234
235impl std::fmt::Display for Identifier {
236 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237 if self.escaped {
238 write!(f, "\\")?;
239 }
240 write!(f, "{}", self.name)?;
241 if self.escaped {
242 write!(f, " ")?;
243 }
244 if let Some(idx) = self.idx {
245 write!(f, "[{idx}]")?;
246 }
247 Ok(())
248 }
249}
250
251#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
253#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
254pub struct Net {
255 identifier: Identifier,
256 data_type: DataType,
257}
258
259impl Net {
260 pub fn new(identifier: Identifier, data_type: DataType) -> Self {
262 Self {
263 identifier,
264 data_type,
265 }
266 }
267
268 pub fn new_logic(name: Identifier) -> Self {
270 Self::new(name, DataType::logic())
271 }
272
273 pub fn new_logic_bus(name: String, bw: usize) -> Vec<Self> {
275 let ids = Identifier::new_bus(name, bw);
276 ids.into_iter()
277 .map(|id| Self::new(id, DataType::logic()))
278 .collect()
279 }
280
281 pub fn set_identifier(&mut self, identifier: Identifier) {
283 self.identifier = identifier;
284 }
285
286 pub fn get_identifier(&self) -> &Identifier {
288 &self.identifier
289 }
290
291 pub fn take_identifier(self) -> Identifier {
293 self.identifier
294 }
295
296 pub fn get_type(&self) -> &DataType {
298 &self.data_type
299 }
300
301 pub fn with_name(&self, name: Identifier) -> Self {
303 Self::new(name, self.data_type)
304 }
305}
306
307#[macro_export]
309macro_rules! format_id {
310 ($($arg:tt)*) => {
311 $crate::Identifier::new(format!($($arg)*))
312 }
313}
314
315impl std::fmt::Display for Net {
316 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
317 self.identifier.fmt(f)
318 }
319}
320
321impl From<&str> for Net {
322 fn from(name: &str) -> Self {
323 Net::new_logic(name.into())
324 }
325}
326
327pub trait Instantiable: Clone {
329 fn get_name(&self) -> &Identifier;
331
332 fn get_input_ports(&self) -> impl IntoIterator<Item = &Net>;
334
335 fn get_output_ports(&self) -> impl IntoIterator<Item = &Net>;
337
338 fn has_parameter(&self, id: &Identifier) -> bool;
340
341 fn get_parameter(&self, id: &Identifier) -> Option<Parameter>;
343
344 fn set_parameter(&mut self, id: &Identifier, val: Parameter) -> Option<Parameter>;
346
347 fn parameters(&self) -> impl Iterator<Item = (Identifier, Parameter)>;
349
350 fn from_constant(val: Logic) -> Option<Self>;
353
354 fn get_constant(&self) -> Option<Logic>;
356
357 fn is_seq(&self) -> bool;
359
360 fn is_parameterized(&self) -> bool {
362 self.parameters().next().is_some()
363 }
364
365 fn get_single_output_port(&self) -> &Net {
367 let mut iter = self.get_output_ports().into_iter();
368 let ret = iter.next().expect("Primitive has no output ports");
369 if iter.next().is_some() {
370 panic!("Primitive has more than one output port");
371 }
372 ret
373 }
374
375 fn get_output_port(&self, index: usize) -> &Net {
380 self.get_output_ports()
381 .into_iter()
382 .nth(index)
383 .expect("Index out of bounds for output ports")
384 }
385
386 fn get_input_port(&self, index: usize) -> &Net {
391 self.get_input_ports()
392 .into_iter()
393 .nth(index)
394 .expect("Index out of bounds for output ports")
395 }
396
397 fn find_input(&self, id: &Identifier) -> Option<usize> {
400 self.get_input_ports()
401 .into_iter()
402 .position(|n| n.get_identifier() == id)
403 }
404
405 fn find_output(&self, id: &Identifier) -> Option<usize> {
408 self.get_output_ports()
409 .into_iter()
410 .position(|n| n.get_identifier() == id)
411 }
412
413 fn is_driverless(&self) -> bool {
416 self.get_input_ports().into_iter().next().is_none()
417 }
418}
419
420#[derive(Debug, Clone)]
422#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
423pub enum Object<I>
424where
425 I: Instantiable,
426{
427 Input(Net),
429 Instance(Vec<Net>, Identifier, I),
431}
432
433impl<I> Object<I>
434where
435 I: Instantiable,
436{
437 pub fn get_single_net(&self) -> &Net {
439 match self {
440 Object::Input(net) => net,
441 Object::Instance(nets, _, _) => {
442 if nets.len() > 1 {
443 panic!("Instance has more than one output net");
444 } else {
445 nets.first().expect("Instance has no output net")
446 }
447 }
448 }
449 }
450
451 pub fn get_net(&self, index: usize) -> &Net {
453 match self {
454 Object::Input(net) => {
455 if index > 0 {
456 panic!("Index out of bounds for input net.")
457 }
458 net
459 }
460 Object::Instance(nets, _, _) => &nets[index],
461 }
462 }
463
464 pub fn get_instance_type(&self) -> Option<&I> {
466 match self {
467 Object::Input(_) => None,
468 Object::Instance(_, _, instance) => Some(instance),
469 }
470 }
471
472 pub fn get_instance_type_mut(&mut self) -> Option<&mut I> {
474 match self {
475 Object::Input(_) => None,
476 Object::Instance(_, _, instance) => Some(instance),
477 }
478 }
479
480 pub fn get_nets(&self) -> &[Net] {
482 match self {
483 Object::Input(net) => std::slice::from_ref(net),
484 Object::Instance(nets, _, _) => nets,
485 }
486 }
487
488 pub fn get_nets_mut(&mut self) -> &mut [Net] {
490 match self {
491 Object::Input(net) => std::slice::from_mut(net),
492 Object::Instance(nets, _, _) => nets,
493 }
494 }
495}
496
497impl<I> std::fmt::Display for Object<I>
498where
499 I: Instantiable,
500{
501 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
502 match self {
503 Object::Input(net) => write!(f, "Input({net})"),
504 Object::Instance(_nets, name, instance) => {
505 write!(f, "{}({})", instance.get_name(), name)
506 }
507 }
508 }
509}
510
511#[cfg(test)]
512mod tests {
513 use super::*;
514
515 #[test]
516 fn identifier_parsing() {
517 let id = Identifier::new("wire".to_string());
518 assert!(!id.is_escaped());
519 assert!(!id.is_sliced());
520 assert!(id.get_bit_index().is_none());
521 let id = Identifier::new("\\wire".to_string());
522 assert!(id.is_escaped());
523 assert!(!id.is_sliced());
524 let id = Identifier::new("wire[3]".to_string());
525 assert!(!id.is_escaped());
526 assert!(id.is_sliced());
527 assert_eq!(id.get_bit_index(), Some(3));
528 }
529
530 #[test]
531 fn assume_escaped_identifier() {
532 let id = Identifier::new("C++".to_string());
533 assert!(id.is_escaped());
534 }
535
536 #[test]
537 fn identifier_emission() {
538 let id = Identifier::new("wire".to_string());
539 assert_eq!(id.emit_name(), "wire");
540 let id = Identifier::new("\\wire".to_string());
541 assert!(id.is_escaped());
542 assert_eq!(id.emit_name(), "\\wire ");
543 assert_eq!(format!("{id}"), "\\wire ");
544 let id = Identifier::new("wire[3]".to_string());
545 assert!(id.is_sliced());
546 assert_eq!(id.emit_name(), "wire[3]");
547 }
548
549 #[test]
550 fn test_implicits() {
551 let net: Net = "hey".into();
552 assert_ne!(*net.get_type(), DataType::boolean());
553 assert_ne!(*net.get_type(), DataType::tristate());
554 assert_eq!(*net.get_type(), DataType::logic());
555 assert_eq!(*net.get_type(), DataType::fourstate());
556 }
557}