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 has_parameter(&self, id: &Identifier) -> bool;
348
349 fn get_parameter(&self, id: &Identifier) -> Option<Parameter>;
351
352 fn set_parameter(&mut self, id: &Identifier, val: Parameter) -> 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 is_parameterized(&self) -> bool {
374 !self.parameters().is_empty()
375 }
376
377 fn get_single_output_port(&self) -> &Net {
379 if self.get_output_ports().len() > 1 {
380 panic!("Primitive has more than one output port");
381 }
382 &self.get_output_ports()[0]
383 }
384
385 fn get_output_port(&self, index: usize) -> &Net {
390 &self.get_output_ports()[index]
391 }
392
393 fn get_input_port(&self, index: usize) -> &Net {
398 &self.get_input_ports()[index]
399 }
400
401 fn find_input(&self, id: &Identifier) -> Option<usize> {
404 self.get_input_ports()
405 .iter()
406 .position(|n| n.get_identifier() == id)
407 }
408
409 fn find_output(&self, id: &Identifier) -> Option<usize> {
412 self.get_output_ports()
413 .iter()
414 .position(|n| n.get_identifier() == id)
415 }
416
417 fn is_driverless(&self) -> bool {
420 self.get_input_ports().is_empty()
421 }
422
423 fn get_num_input_ports(&self) -> usize {
425 self.get_input_ports().len()
426 }
427
428 fn get_num_output_ports(&self) -> usize {
430 self.get_output_ports().len()
431 }
432}
433
434#[derive(Debug, Clone)]
436#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
437pub enum Object<I>
438where
439 I: Instantiable,
440{
441 Input(Net),
443 Instance(Vec<Net>, Identifier, I),
445}
446
447impl<I> Object<I>
448where
449 I: Instantiable,
450{
451 pub fn get_single_net(&self) -> &Net {
453 match self {
454 Object::Input(net) => net,
455 Object::Instance(nets, _, _) => {
456 if nets.len() > 1 {
457 panic!("Instance has more than one output net");
458 } else {
459 nets.first().expect("Instance has no output net")
460 }
461 }
462 }
463 }
464
465 pub fn get_net(&self, index: usize) -> &Net {
467 match self {
468 Object::Input(net) => {
469 if index > 0 {
470 panic!("Index out of bounds for input net.")
471 }
472 net
473 }
474 Object::Instance(nets, _, _) => &nets[index],
475 }
476 }
477
478 pub fn get_instance_type(&self) -> Option<&I> {
480 match self {
481 Object::Input(_) => None,
482 Object::Instance(_, _, instance) => Some(instance),
483 }
484 }
485
486 pub fn get_instance_type_mut(&mut self) -> Option<&mut I> {
488 match self {
489 Object::Input(_) => None,
490 Object::Instance(_, _, instance) => Some(instance),
491 }
492 }
493
494 pub fn get_nets(&self) -> &[Net] {
496 match self {
497 Object::Input(net) => std::slice::from_ref(net),
498 Object::Instance(nets, _, _) => nets,
499 }
500 }
501
502 pub fn get_nets_mut(&mut self) -> &mut [Net] {
504 match self {
505 Object::Input(net) => std::slice::from_mut(net),
506 Object::Instance(nets, _, _) => nets,
507 }
508 }
509}
510
511impl<I> std::fmt::Display for Object<I>
512where
513 I: Instantiable,
514{
515 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
516 match self {
517 Object::Input(net) => write!(f, "Input({net})"),
518 Object::Instance(_nets, name, instance) => {
519 write!(f, "{}({})", instance.get_name(), name)
520 }
521 }
522 }
523}
524
525#[cfg(test)]
526mod tests {
527 use super::*;
528
529 #[test]
530 fn identifier_parsing() {
531 let id = Identifier::new("wire".to_string());
532 assert!(!id.is_escaped());
533 assert!(!id.is_sliced());
534 assert!(id.get_bit_index().is_none());
535 let id = Identifier::new("\\wire".to_string());
536 assert!(id.is_escaped());
537 assert!(!id.is_sliced());
538 let id = Identifier::new("wire[3]".to_string());
539 assert!(!id.is_escaped());
540 assert!(id.is_sliced());
541 assert_eq!(id.get_bit_index(), Some(3));
542 }
543
544 #[test]
545 fn assume_escaped_identifier() {
546 let id = Identifier::new("C++".to_string());
547 assert!(id.is_escaped());
548 }
549
550 #[test]
551 fn identifier_emission() {
552 let id = Identifier::new("wire".to_string());
553 assert_eq!(id.emit_name(), "wire");
554 let id = Identifier::new("\\wire".to_string());
555 assert!(id.is_escaped());
556 assert_eq!(id.emit_name(), "\\wire ");
557 assert_eq!(format!("{id}"), "\\wire ");
558 let id = Identifier::new("wire[3]".to_string());
559 assert!(id.is_sliced());
560 assert_eq!(id.emit_name(), "wire[3]");
561 }
562
563 #[test]
564 fn test_implicits() {
565 let net: Net = "hey".into();
566 assert_ne!(*net.get_type(), DataType::boolean());
567 assert_ne!(*net.get_type(), DataType::tristate());
568 assert_eq!(*net.get_type(), DataType::logic());
569 assert_eq!(*net.get_type(), DataType::fourstate());
570 }
571}