1use crate::{attribute::Parameter, logic::Logic};
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
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, Copy)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
46enum IdentifierType {
47 Normal,
49 BitSlice(usize),
51 Escaped,
53}
54
55#[derive(Debug, Clone, PartialEq, Eq, Hash)]
57#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
58pub struct Identifier {
59 name: String,
61 id_type: IdentifierType,
63}
64
65impl Identifier {
66 pub fn new(name: String) -> Self {
68 if name.is_empty() {
69 panic!("Identifier name cannot be empty");
70 }
71
72 if let Some(root) = name.strip_prefix('\\') {
73 return Identifier {
74 name: root.to_string(),
75 id_type: IdentifierType::Escaped,
76 };
77 }
78
79 let esc_chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
81 if esc_chars.contains(&name.chars().next().unwrap()) {
82 return Identifier {
83 name,
84 id_type: IdentifierType::Escaped,
85 };
86 }
87
88 let esc_chars = [' ', '\\', '(', ')', ',', '+', '-', '$', '\'', '~'];
91 if name.chars().any(|c| esc_chars.contains(&c)) {
92 return Identifier {
93 name,
94 id_type: IdentifierType::Escaped,
95 };
96 }
97
98 if name.contains('[') && name.ends_with(']') {
99 let name_ind = name.find('[').unwrap();
100 let rname = &name[..name_ind];
101 let index_start = name_ind + 1;
102 let slice = name[index_start..name.len() - 1].parse::<usize>();
103 if let Ok(s) = slice {
104 return Identifier {
105 name: rname.to_string(),
106 id_type: IdentifierType::BitSlice(s),
107 };
108 }
109 }
110
111 Identifier {
112 name,
113 id_type: IdentifierType::Normal,
114 }
115 }
116
117 pub fn get_name(&self) -> &str {
119 &self.name
120 }
121
122 pub fn get_bit_index(&self) -> Option<usize> {
124 match self.id_type {
125 IdentifierType::BitSlice(index) => Some(index),
126 _ => None,
127 }
128 }
129
130 pub fn is_sliced(&self) -> bool {
132 matches!(self.id_type, IdentifierType::BitSlice(_))
133 }
134
135 pub fn is_escaped(&self) -> bool {
137 matches!(self.id_type, IdentifierType::Escaped)
138 }
139
140 pub fn emit_name(&self) -> String {
142 match &self.id_type {
143 IdentifierType::Normal => self.name.clone(),
144 IdentifierType::BitSlice(index) => format!("{}[{}]", self.name, index),
145 IdentifierType::Escaped => format!("\\{} ", self.name),
146 }
147 }
148}
149
150impl std::ops::Add for &Identifier {
151 type Output = Identifier;
152
153 fn add(self, rhs: Self) -> Identifier {
154 let lname = self.name.as_str();
155 let rname = rhs.name.as_str();
156
157 let new_type = match (self.id_type, rhs.id_type) {
158 (IdentifierType::Escaped, _)
159 | (_, IdentifierType::Escaped)
160 | (IdentifierType::BitSlice(_), _)
161 | (_, IdentifierType::BitSlice(_)) => IdentifierType::Escaped,
162 (IdentifierType::Normal, IdentifierType::Normal) => IdentifierType::Normal,
163 };
164
165 let new_name = match (self.id_type, rhs.id_type) {
166 (IdentifierType::BitSlice(l), IdentifierType::BitSlice(r)) => {
167 format!("{}_{}_{}_{}", lname, l, rname, r)
168 }
169 (IdentifierType::BitSlice(l), _) => format!("{}_{}_{}", lname, l, rname),
170 (_, IdentifierType::BitSlice(r)) => format!("{}_{}_{}", lname, rname, r),
171 _ => format!("{}_{}", lname, rname),
172 };
173
174 Identifier {
175 name: new_name,
176 id_type: new_type,
177 }
178 }
179}
180
181impl std::ops::Add for Identifier {
182 type Output = Identifier;
183
184 fn add(self, rhs: Self) -> Identifier {
185 &self + &rhs
186 }
187}
188
189impl From<&str> for Identifier {
190 fn from(name: &str) -> Self {
191 Identifier::new(name.to_string())
192 }
193}
194
195impl From<String> for Identifier {
196 fn from(name: String) -> Self {
197 Identifier::new(name)
198 }
199}
200
201impl std::fmt::Display for Identifier {
202 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203 match &self.id_type {
204 IdentifierType::Normal => write!(f, "{}", self.name),
205 IdentifierType::BitSlice(index) => write!(f, "{}[{}]", self.name, index),
206 IdentifierType::Escaped => write!(f, "\\{} ", self.name),
207 }
208 }
209}
210
211#[derive(Debug, Clone, PartialEq, Eq, Hash)]
213#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
214pub struct Net {
215 identifier: Identifier,
216 data_type: DataType,
217}
218
219impl Net {
220 pub fn new(identifier: Identifier, data_type: DataType) -> Self {
222 Self {
223 identifier,
224 data_type,
225 }
226 }
227
228 pub fn new_logic(name: Identifier) -> Self {
230 Self::new(name, DataType::logic())
231 }
232
233 pub fn new_escaped_logic_bus(name: String, bw: usize) -> Vec<Self> {
235 let mut vec: Vec<Self> = Vec::with_capacity(bw);
236 for i in 0..bw {
237 vec.push(Self::new(
238 Identifier {
239 name: format!("{name}[{i}]"),
240 id_type: IdentifierType::Escaped,
241 },
242 DataType::logic(),
243 ));
244 }
245 vec
246 }
247
248 pub fn set_identifier(&mut self, identifier: Identifier) {
250 self.identifier = identifier;
251 }
252
253 pub fn get_identifier(&self) -> &Identifier {
255 &self.identifier
256 }
257
258 pub fn take_identifier(self) -> Identifier {
260 self.identifier
261 }
262
263 pub fn get_type(&self) -> &DataType {
265 &self.data_type
266 }
267
268 pub fn with_name(&self, name: Identifier) -> Self {
270 Self::new(name, self.data_type)
271 }
272}
273
274#[macro_export]
276macro_rules! format_id {
277 ($($arg:tt)*) => {
278 $crate::Identifier::new(format!($($arg)*))
279 }
280}
281
282impl std::fmt::Display for Net {
283 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
284 self.identifier.fmt(f)
285 }
286}
287
288impl From<&str> for Net {
289 fn from(name: &str) -> Self {
290 Net::new_logic(name.into())
291 }
292}
293
294pub trait Instantiable: Clone {
296 fn get_name(&self) -> &Identifier;
298
299 fn get_input_ports(&self) -> impl IntoIterator<Item = &Net>;
301
302 fn get_output_ports(&self) -> impl IntoIterator<Item = &Net>;
304
305 fn has_parameter(&self, id: &Identifier) -> bool;
307
308 fn get_parameter(&self, id: &Identifier) -> Option<Parameter>;
310
311 fn set_parameter(&mut self, id: &Identifier, val: Parameter) -> Option<Parameter>;
313
314 fn parameters(&self) -> impl Iterator<Item = (Identifier, Parameter)>;
316
317 fn from_constant(val: Logic) -> Option<Self>;
320
321 fn get_constant(&self) -> Option<Logic>;
323
324 fn is_seq(&self) -> bool;
326
327 fn is_parameterized(&self) -> bool {
329 self.parameters().next().is_some()
330 }
331
332 fn get_single_output_port(&self) -> &Net {
334 let mut iter = self.get_output_ports().into_iter();
335 let ret = iter.next().expect("Primitive has no output ports");
336 if iter.next().is_some() {
337 panic!("Primitive has more than one output port");
338 }
339 ret
340 }
341
342 fn get_output_port(&self, index: usize) -> &Net {
347 self.get_output_ports()
348 .into_iter()
349 .nth(index)
350 .expect("Index out of bounds for output ports")
351 }
352
353 fn get_input_port(&self, index: usize) -> &Net {
358 self.get_input_ports()
359 .into_iter()
360 .nth(index)
361 .expect("Index out of bounds for output ports")
362 }
363
364 fn find_input(&self, id: &Identifier) -> Option<usize> {
367 self.get_input_ports()
368 .into_iter()
369 .position(|n| n.get_identifier() == id)
370 }
371
372 fn find_output(&self, id: &Identifier) -> Option<usize> {
375 self.get_output_ports()
376 .into_iter()
377 .position(|n| n.get_identifier() == id)
378 }
379
380 fn is_driverless(&self) -> bool {
383 self.get_input_ports().into_iter().next().is_none()
384 }
385}
386
387#[derive(Debug, Clone)]
389#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
390pub enum Object<I>
391where
392 I: Instantiable,
393{
394 Input(Net),
396 Instance(Vec<Net>, Identifier, I),
398}
399
400impl<I> Object<I>
401where
402 I: Instantiable,
403{
404 pub fn get_single_net(&self) -> &Net {
406 match self {
407 Object::Input(net) => net,
408 Object::Instance(nets, _, _) => {
409 if nets.len() > 1 {
410 panic!("Instance has more than one output net");
411 } else {
412 nets.first().expect("Instance has no output net")
413 }
414 }
415 }
416 }
417
418 pub fn get_net(&self, index: usize) -> &Net {
420 match self {
421 Object::Input(net) => {
422 if index > 0 {
423 panic!("Index out of bounds for input net.")
424 }
425 net
426 }
427 Object::Instance(nets, _, _) => &nets[index],
428 }
429 }
430
431 pub fn get_instance_type(&self) -> Option<&I> {
433 match self {
434 Object::Input(_) => None,
435 Object::Instance(_, _, instance) => Some(instance),
436 }
437 }
438
439 pub fn get_instance_type_mut(&mut self) -> Option<&mut I> {
441 match self {
442 Object::Input(_) => None,
443 Object::Instance(_, _, instance) => Some(instance),
444 }
445 }
446
447 pub fn get_nets(&self) -> &[Net] {
449 match self {
450 Object::Input(net) => std::slice::from_ref(net),
451 Object::Instance(nets, _, _) => nets,
452 }
453 }
454
455 pub fn get_nets_mut(&mut self) -> &mut [Net] {
457 match self {
458 Object::Input(net) => std::slice::from_mut(net),
459 Object::Instance(nets, _, _) => nets,
460 }
461 }
462}
463
464impl<I> std::fmt::Display for Object<I>
465where
466 I: Instantiable,
467{
468 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
469 match self {
470 Object::Input(net) => write!(f, "Input({net})"),
471 Object::Instance(_nets, name, instance) => {
472 write!(f, "{}({})", instance.get_name(), name)
473 }
474 }
475 }
476}
477
478#[cfg(test)]
479mod tests {
480 use super::*;
481
482 #[test]
483 fn identifier_parsing() {
484 let id = Identifier::new("wire".to_string());
485 assert!(!id.is_escaped());
486 assert!(!id.is_sliced());
487 assert!(id.get_bit_index().is_none());
488 let id = Identifier::new("\\wire".to_string());
489 assert!(id.is_escaped());
490 assert!(!id.is_sliced());
491 let id = Identifier::new("wire[3]".to_string());
492 assert!(!id.is_escaped());
493 assert!(id.is_sliced());
494 assert_eq!(id.get_bit_index(), Some(3));
495 }
496
497 #[test]
498 fn assume_escaped_identifier() {
499 let id = Identifier::new("C++".to_string());
500 assert!(id.is_escaped());
501 }
502
503 #[test]
504 fn identifier_emission() {
505 let id = Identifier::new("wire".to_string());
506 assert_eq!(id.emit_name(), "wire");
507 let id = Identifier::new("\\wire".to_string());
508 assert!(id.is_escaped());
509 assert_eq!(id.emit_name(), "\\wire ");
510 assert_eq!(format!("{id}"), "\\wire ");
511 let id = Identifier::new("wire[3]".to_string());
512 assert!(id.is_sliced());
513 assert_eq!(id.emit_name(), "wire[3]");
514 }
515
516 #[test]
517 fn test_implicits() {
518 let net: Net = "hey".into();
519 assert_ne!(*net.get_type(), DataType::boolean());
520 assert_ne!(*net.get_type(), DataType::tristate());
521 assert_eq!(*net.get_type(), DataType::logic());
522 assert_eq!(*net.get_type(), DataType::fourstate());
523 }
524}