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, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
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, PartialOrd, Ord)]
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 ' ', '\\', '(', ')', ',', '+', '-', '$', '\'', '~', ';', '.', ',', '?', '!',
92 ];
93 if name.chars().any(|c| esc_chars.contains(&c)) {
94 return Identifier {
95 name,
96 id_type: IdentifierType::Escaped,
97 };
98 }
99
100 if name.contains('[') && name.ends_with(']') {
101 let name_ind = name.find('[').unwrap();
102 let rname = &name[..name_ind];
103 let index_start = name_ind + 1;
104 let slice = name[index_start..name.len() - 1].parse::<usize>();
105 if let Ok(s) = slice {
106 return Identifier {
107 name: rname.to_string(),
108 id_type: IdentifierType::BitSlice(s),
109 };
110 }
111 }
112
113 Identifier {
114 name,
115 id_type: IdentifierType::Normal,
116 }
117 }
118
119 pub fn get_name(&self) -> &str {
121 &self.name
122 }
123
124 pub fn get_bit_index(&self) -> Option<usize> {
126 match self.id_type {
127 IdentifierType::BitSlice(index) => Some(index),
128 _ => None,
129 }
130 }
131
132 pub fn is_sliced(&self) -> bool {
134 matches!(self.id_type, IdentifierType::BitSlice(_))
135 }
136
137 pub fn is_escaped(&self) -> bool {
139 matches!(self.id_type, IdentifierType::Escaped)
140 }
141
142 pub fn emit_name(&self) -> String {
144 match &self.id_type {
145 IdentifierType::Normal => self.name.clone(),
146 IdentifierType::BitSlice(index) => format!("{}[{}]", self.name, index),
147 IdentifierType::Escaped => format!("\\{} ", self.name),
148 }
149 }
150}
151
152impl std::ops::Add for &Identifier {
153 type Output = Identifier;
154
155 fn add(self, rhs: Self) -> Identifier {
156 let lname = self.name.as_str();
157 let rname = rhs.name.as_str();
158
159 let new_type = match (self.id_type, rhs.id_type) {
160 (IdentifierType::Escaped, _)
161 | (_, IdentifierType::Escaped)
162 | (IdentifierType::BitSlice(_), _)
163 | (_, IdentifierType::BitSlice(_)) => IdentifierType::Escaped,
164 (IdentifierType::Normal, IdentifierType::Normal) => IdentifierType::Normal,
165 };
166
167 let new_name = match (self.id_type, rhs.id_type) {
168 (IdentifierType::BitSlice(l), IdentifierType::BitSlice(r)) => {
169 format!("{}_{}_{}_{}", lname, l, rname, r)
170 }
171 (IdentifierType::BitSlice(l), _) => format!("{}_{}_{}", lname, l, rname),
172 (_, IdentifierType::BitSlice(r)) => format!("{}_{}_{}", lname, rname, r),
173 _ => format!("{}_{}", lname, rname),
174 };
175
176 Identifier {
177 name: new_name,
178 id_type: new_type,
179 }
180 }
181}
182
183impl std::ops::Add for Identifier {
184 type Output = Identifier;
185
186 fn add(self, rhs: Self) -> Identifier {
187 &self + &rhs
188 }
189}
190
191impl From<&str> for Identifier {
192 fn from(name: &str) -> Self {
193 Identifier::new(name.to_string())
194 }
195}
196
197impl From<String> for Identifier {
198 fn from(name: String) -> Self {
199 Identifier::new(name)
200 }
201}
202
203impl std::fmt::Display for Identifier {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205 match &self.id_type {
206 IdentifierType::Normal => write!(f, "{}", self.name),
207 IdentifierType::BitSlice(index) => write!(f, "{}[{}]", self.name, index),
208 IdentifierType::Escaped => write!(f, "\\{} ", self.name),
209 }
210 }
211}
212
213#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
215#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
216pub struct Net {
217 identifier: Identifier,
218 data_type: DataType,
219}
220
221impl Net {
222 pub fn new(identifier: Identifier, data_type: DataType) -> Self {
224 Self {
225 identifier,
226 data_type,
227 }
228 }
229
230 pub fn new_logic(name: Identifier) -> Self {
232 Self::new(name, DataType::logic())
233 }
234
235 pub fn new_escaped_logic_bus(name: String, bw: usize) -> Vec<Self> {
237 let mut vec: Vec<Self> = Vec::with_capacity(bw);
238 for i in 0..bw {
239 vec.push(Self::new(
240 Identifier {
241 name: format!("{name}[{i}]"),
242 id_type: IdentifierType::Escaped,
243 },
244 DataType::logic(),
245 ));
246 }
247 vec
248 }
249
250 pub fn set_identifier(&mut self, identifier: Identifier) {
252 self.identifier = identifier;
253 }
254
255 pub fn get_identifier(&self) -> &Identifier {
257 &self.identifier
258 }
259
260 pub fn take_identifier(self) -> Identifier {
262 self.identifier
263 }
264
265 pub fn get_type(&self) -> &DataType {
267 &self.data_type
268 }
269
270 pub fn with_name(&self, name: Identifier) -> Self {
272 Self::new(name, self.data_type)
273 }
274}
275
276#[macro_export]
278macro_rules! format_id {
279 ($($arg:tt)*) => {
280 $crate::Identifier::new(format!($($arg)*))
281 }
282}
283
284impl std::fmt::Display for Net {
285 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
286 self.identifier.fmt(f)
287 }
288}
289
290impl From<&str> for Net {
291 fn from(name: &str) -> Self {
292 Net::new_logic(name.into())
293 }
294}
295
296pub trait Instantiable: Clone {
298 fn get_name(&self) -> &Identifier;
300
301 fn get_input_ports(&self) -> impl IntoIterator<Item = &Net>;
303
304 fn get_output_ports(&self) -> impl IntoIterator<Item = &Net>;
306
307 fn has_parameter(&self, id: &Identifier) -> bool;
309
310 fn get_parameter(&self, id: &Identifier) -> Option<Parameter>;
312
313 fn set_parameter(&mut self, id: &Identifier, val: Parameter) -> Option<Parameter>;
315
316 fn parameters(&self) -> impl Iterator<Item = (Identifier, Parameter)>;
318
319 fn from_constant(val: Logic) -> Option<Self>;
322
323 fn get_constant(&self) -> Option<Logic>;
325
326 fn is_seq(&self) -> bool;
328
329 fn is_parameterized(&self) -> bool {
331 self.parameters().next().is_some()
332 }
333
334 fn get_single_output_port(&self) -> &Net {
336 let mut iter = self.get_output_ports().into_iter();
337 let ret = iter.next().expect("Primitive has no output ports");
338 if iter.next().is_some() {
339 panic!("Primitive has more than one output port");
340 }
341 ret
342 }
343
344 fn get_output_port(&self, index: usize) -> &Net {
349 self.get_output_ports()
350 .into_iter()
351 .nth(index)
352 .expect("Index out of bounds for output ports")
353 }
354
355 fn get_input_port(&self, index: usize) -> &Net {
360 self.get_input_ports()
361 .into_iter()
362 .nth(index)
363 .expect("Index out of bounds for output ports")
364 }
365
366 fn find_input(&self, id: &Identifier) -> Option<usize> {
369 self.get_input_ports()
370 .into_iter()
371 .position(|n| n.get_identifier() == id)
372 }
373
374 fn find_output(&self, id: &Identifier) -> Option<usize> {
377 self.get_output_ports()
378 .into_iter()
379 .position(|n| n.get_identifier() == id)
380 }
381
382 fn is_driverless(&self) -> bool {
385 self.get_input_ports().into_iter().next().is_none()
386 }
387}
388
389#[derive(Debug, Clone)]
391#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
392pub enum Object<I>
393where
394 I: Instantiable,
395{
396 Input(Net),
398 Instance(Vec<Net>, Identifier, I),
400}
401
402impl<I> Object<I>
403where
404 I: Instantiable,
405{
406 pub fn get_single_net(&self) -> &Net {
408 match self {
409 Object::Input(net) => net,
410 Object::Instance(nets, _, _) => {
411 if nets.len() > 1 {
412 panic!("Instance has more than one output net");
413 } else {
414 nets.first().expect("Instance has no output net")
415 }
416 }
417 }
418 }
419
420 pub fn get_net(&self, index: usize) -> &Net {
422 match self {
423 Object::Input(net) => {
424 if index > 0 {
425 panic!("Index out of bounds for input net.")
426 }
427 net
428 }
429 Object::Instance(nets, _, _) => &nets[index],
430 }
431 }
432
433 pub fn get_instance_type(&self) -> Option<&I> {
435 match self {
436 Object::Input(_) => None,
437 Object::Instance(_, _, instance) => Some(instance),
438 }
439 }
440
441 pub fn get_instance_type_mut(&mut self) -> Option<&mut I> {
443 match self {
444 Object::Input(_) => None,
445 Object::Instance(_, _, instance) => Some(instance),
446 }
447 }
448
449 pub fn get_nets(&self) -> &[Net] {
451 match self {
452 Object::Input(net) => std::slice::from_ref(net),
453 Object::Instance(nets, _, _) => nets,
454 }
455 }
456
457 pub fn get_nets_mut(&mut self) -> &mut [Net] {
459 match self {
460 Object::Input(net) => std::slice::from_mut(net),
461 Object::Instance(nets, _, _) => nets,
462 }
463 }
464}
465
466impl<I> std::fmt::Display for Object<I>
467where
468 I: Instantiable,
469{
470 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
471 match self {
472 Object::Input(net) => write!(f, "Input({net})"),
473 Object::Instance(_nets, name, instance) => {
474 write!(f, "{}({})", instance.get_name(), name)
475 }
476 }
477 }
478}
479
480#[cfg(test)]
481mod tests {
482 use super::*;
483
484 #[test]
485 fn identifier_parsing() {
486 let id = Identifier::new("wire".to_string());
487 assert!(!id.is_escaped());
488 assert!(!id.is_sliced());
489 assert!(id.get_bit_index().is_none());
490 let id = Identifier::new("\\wire".to_string());
491 assert!(id.is_escaped());
492 assert!(!id.is_sliced());
493 let id = Identifier::new("wire[3]".to_string());
494 assert!(!id.is_escaped());
495 assert!(id.is_sliced());
496 assert_eq!(id.get_bit_index(), Some(3));
497 }
498
499 #[test]
500 fn assume_escaped_identifier() {
501 let id = Identifier::new("C++".to_string());
502 assert!(id.is_escaped());
503 }
504
505 #[test]
506 fn identifier_emission() {
507 let id = Identifier::new("wire".to_string());
508 assert_eq!(id.emit_name(), "wire");
509 let id = Identifier::new("\\wire".to_string());
510 assert!(id.is_escaped());
511 assert_eq!(id.emit_name(), "\\wire ");
512 assert_eq!(format!("{id}"), "\\wire ");
513 let id = Identifier::new("wire[3]".to_string());
514 assert!(id.is_sliced());
515 assert_eq!(id.emit_name(), "wire[3]");
516 }
517
518 #[test]
519 fn test_implicits() {
520 let net: Net = "hey".into();
521 assert_ne!(*net.get_type(), DataType::boolean());
522 assert_ne!(*net.get_type(), DataType::tristate());
523 assert_eq!(*net.get_type(), DataType::logic());
524 assert_eq!(*net.get_type(), DataType::fourstate());
525 }
526}