1use std::path::Path;
6
7use crate::design::{Interface, Streamlet};
8use crate::generator::common::{Component, Library, Mode, Port, Project, Record, Type};
9use crate::logical::{Group, LogicalStreamType, Stream, Union};
10use crate::physical::{Origin, Signal, Width};
11use crate::traits::Identify;
12use crate::Result;
13
14pub mod chisel;
15pub mod common;
16pub mod vhdl;
17
18pub const CANON_SUFFIX: Option<&str> = Some("com");
24
25#[macro_export]
28macro_rules! cat {
29 ($a:expr) => {{
30 format!("{}", $a)
31 }};
32
33 ($a:expr, $($b:expr),+) => {{
34 let left : String = format!("{}", $a);
35 let right : String = format!("{}", cat!($($b),+));
36 if left == "" {
37 right
38 } else if right == "" {
39 left
40 } else {
41 format!("{}_{}", left, right)
42 }
43 }};
44}
45
46pub trait GenerateProject {
49 fn generate(&self, project: &Project, path: impl AsRef<Path>) -> Result<()>;
51}
52
53pub trait Typify {
56 fn user(&self, _prefix: impl Into<String>) -> Option<Type> {
57 None
58 }
59 fn canonical(&self, prefix: impl Into<String>) -> Vec<Signal>;
60}
61
62pub trait Portify {
65 fn user(
66 &self,
67 _port_name: impl Into<String>,
68 _port_type_prefix: impl Into<String>,
69 ) -> Vec<Port> {
70 Vec::new()
71 }
72 fn canonical(&self, name: impl Into<String>) -> Vec<Port>;
73}
74
75pub trait Componentify {
78 fn user(&self, _suffix: Option<&str>) -> Option<Component> {
79 None
80 }
81 fn canonical(&self, suffix: Option<&str>) -> Component;
82}
83
84impl Typify for LogicalStreamType {
85 fn user(&self, prefix: impl Into<String>) -> Option<Type> {
88 match self {
89 LogicalStreamType::Null => None,
90 LogicalStreamType::Bits(width) => Some(Type::bitvec(width.get())),
91 LogicalStreamType::Group(group) => group.user(prefix),
92 LogicalStreamType::Stream(stream) => stream.user(prefix),
93 LogicalStreamType::Union(union) => union.user(prefix),
94 }
95 }
96
97 fn canonical(&self, prefix: impl Into<String>) -> Vec<Signal> {
98 match self {
99 LogicalStreamType::Null => Vec::new(),
100 LogicalStreamType::Bits(width) => {
101 vec![Signal::vec(prefix.into(), Origin::Source, *width)]
102 }
103 LogicalStreamType::Group(group) => group.canonical(prefix),
104 LogicalStreamType::Stream(stream) => stream.canonical(prefix),
105 LogicalStreamType::Union(union) => union.canonical(prefix),
106 }
107 }
108}
109
110impl Typify for Group {
111 fn user(&self, prefix: impl Into<String>) -> Option<Type> {
112 let n: String = prefix.into();
113 let mut rec = Record::new_empty(cat!(n.clone(), "type"));
114 for (field_name, field_logical) in self.iter() {
115 if let Some(field_common_type) = field_logical.user(cat!(n.clone(), field_name)) {
116 rec.insert_new_field(field_name.to_string(), field_common_type, false)
117 }
118 }
119 Some(Type::Record(rec))
120 }
121
122 fn canonical(&self, prefix: impl Into<String>) -> Vec<Signal> {
123 let n: String = prefix.into();
124 let mut result = Vec::new();
125 for (field_name, field_logical) in self.iter() {
126 let field_result = field_logical.canonical(cat!(n.clone(), field_name));
127 result.extend(field_result);
128 }
129 result
130 }
131}
132
133impl Typify for Union {
134 fn user(&self, prefix: impl Into<String>) -> Option<Type> {
135 let n: String = prefix.into();
136 let mut rec = Record::new_empty(cat!(n.clone(), "type"));
137 if let Some((tag_name, tag_bc)) = self.tag() {
138 rec.insert_new_field(tag_name, Type::bitvec(tag_bc.get()), false);
139 }
140 for (field_name, field_logical) in self.iter() {
141 if let Some(field_common_type) = field_logical.user(cat!(n.clone(), field_name)) {
142 rec.insert_new_field(field_name, field_common_type, false);
143 }
144 }
145 Some(Type::Record(rec))
146 }
147
148 fn canonical(&self, prefix: impl Into<String>) -> Vec<Signal> {
149 let n: String = prefix.into();
150 let mut result = Vec::new();
151 if let Some((tag_name, tag_bc)) = self.tag() {
152 result.push(Signal::vec(
153 cat!(n.clone(), tag_name),
154 Origin::Source,
155 tag_bc,
156 ));
157 }
158 for (field_name, field_logical) in self.iter() {
159 let field_result = field_logical.canonical(cat!(n.clone(), field_name));
160 result.extend(field_result);
161 }
162 result
163 }
164}
165
166impl Typify for Stream {
167 fn user(&self, prefix: impl Into<String>) -> Option<Type> {
170 let logical = LogicalStreamType::from(self.clone());
173
174 assert!(logical.is_element_only());
177
178 if !logical.is_null() {
180 let synth = logical.synthesize();
182
183 let (name, physical) = synth.streams().next().unwrap();
187 let signals = physical.signal_list();
188
189 let mut rec = Record::new_empty_stream(match name.len() {
191 0 => cat!(prefix.into(), "type"),
192 _ => cat!(prefix.into(), name, "type"),
193 });
194
195 rec.insert_new_field("data", self.data().user("data").unwrap(), false);
197
198 if let Some(sig) = signals.last() {
200 rec.insert_new_field("last", sig.width().into(), sig.reversed());
201 }
202 if let Some(sig) = signals.stai() {
203 rec.insert_new_field("stai", sig.width().into(), sig.reversed());
204 }
205 if let Some(sig) = signals.endi() {
206 rec.insert_new_field("endi", sig.width().into(), sig.reversed());
207 }
208 if let Some(sig) = signals.strb() {
209 rec.insert_new_field("strb", sig.width().into(), sig.reversed());
210 }
211
212 Some(Type::Record(rec))
213 } else {
214 None
215 }
216 }
217
218 fn canonical(&self, prefix: impl Into<String>) -> Vec<Signal> {
221 let n: String = prefix.into();
222 let mut result = Vec::new();
223
224 let logical = LogicalStreamType::from(self.clone());
225 assert!(logical.is_element_only());
226 if !logical.is_null() {
227 let synth = logical.synthesize();
228 let (path, phys) = synth.streams().next().unwrap();
229 for signal in phys.signal_list().into_iter() {
230 let n = cat!(n.clone(), path, signal.identifier());
231 result.push(signal.with_name(n));
232 }
233 }
234
235 result
236 }
237}
238
239impl From<Width> for Type {
240 fn from(width: Width) -> Self {
241 match width {
242 Width::Scalar => Type::Bit,
243 Width::Vector(w) => Type::bitvec(w),
244 }
245 }
246}
247
248pub trait ModeFor {
251 fn mode_for(&self, streamlet_mode: crate::design::Mode) -> Mode;
253}
254
255impl ModeFor for Origin {
256 fn mode_for(&self, streamlet_mode: crate::design::Mode) -> Mode {
258 match self {
259 Origin::Sink => match streamlet_mode {
260 crate::design::Mode::In => Mode::Out,
261 crate::design::Mode::Out => Mode::In,
262 },
263 Origin::Source => match streamlet_mode {
264 crate::design::Mode::In => Mode::In,
265 crate::design::Mode::Out => Mode::Out,
266 },
267 }
268 }
269}
270
271impl Portify for Interface {
272 fn user(&self, name: impl Into<String>, type_name: impl Into<String>) -> Vec<Port> {
273 let n: String = name.into();
274 let tn: String = type_name.into();
275
276 let mut result = Vec::new();
277
278 let split = self.typ().split();
279
280 if let Some(sig_type) = split.signal().user(tn.clone()) {
281 result.push(Port::new(cat!(n.clone()), self.mode().into(), sig_type));
282 }
283
284 for (path, simple_stream) in self.typ().split().streams() {
286 if let Some(typ) = simple_stream.user(cat!(tn.clone(), path)) {
287 result.push(Port::new(cat!(n.clone(), path), self.mode().into(), typ));
288 }
289 }
290
291 result
292 }
293
294 fn canonical(&self, prefix: impl Into<String>) -> Vec<Port> {
295 let signals = self.typ().canonical(prefix.into());
296 signals
297 .iter()
298 .map(|s| {
299 Port::new(
300 s.identifier(),
301 s.origin().mode_for(self.mode()),
302 s.width().into(),
303 )
304 })
305 .collect()
306 }
307}
308
309impl From<crate::design::Mode> for Mode {
310 fn from(m: crate::design::Mode) -> Self {
311 match m {
312 crate::design::Mode::Out => Mode::Out,
313 crate::design::Mode::In => Mode::In,
314 }
315 }
316}
317
318impl Componentify for Streamlet {
319 fn user(&self, suffix: Option<&str>) -> Option<Component> {
320 Some(Component::new(
321 cat!(self.identifier().to_string(), suffix.unwrap_or("")),
322 vec![],
323 self.interfaces()
324 .into_iter()
325 .flat_map(|interface| {
326 interface.user(
327 interface.identifier(),
328 cat!(self.identifier().to_string(), interface.identifier()),
329 )
330 })
331 .collect(),
332 ))
333 }
334
335 fn canonical(&self, suffix: Option<&str>) -> Component {
336 Component::new(
337 cat!(self.identifier().to_string(), suffix.unwrap_or("")),
338 vec![],
339 {
340 let mut all_ports = Vec::new();
341 self.interfaces().into_iter().for_each(|interface| {
342 all_ports.extend(interface.canonical(interface.identifier()));
343 });
344 all_ports
345 },
346 )
347 }
348}
349
350impl From<crate::design::Library> for Library {
351 fn from(l: crate::design::Library) -> Self {
352 Library {
353 identifier: l.identifier().to_string(),
354 components: l
355 .streamlets()
356 .into_iter()
357 .flat_map(|s| {
358 let mut result = vec![s.canonical(CANON_SUFFIX)];
359 if let Some(user) = s.user(None) {
360 result.push(user);
361 }
362 result
363 })
364 .collect(),
365 }
366 }
367}
368
369impl From<crate::design::Project> for Project {
370 fn from(p: crate::design::Project) -> Self {
371 Project {
372 identifier: p.identifier().to_string(),
373 libraries: p.libraries().into_iter().map(|l| l.into()).collect(),
374 }
375 }
376}
377
378#[cfg(test)]
379pub(crate) mod tests {
380 use super::*;
381 use crate::design::{Interface, Streamlet};
382 use crate::generator::common::test::records;
383 use crate::generator::vhdl::Declare;
384 use crate::logical::tests::{elements, streams};
385 use crate::{Name, Positive, UniquelyNamedBuilder};
386
387 #[test]
388 fn test_cat() {
389 assert_eq!(cat!("ok"), "ok");
390 assert_eq!(cat!("ok", "tydi"), "ok_tydi");
391 assert_eq!(cat!("ok", "tydi", ""), "ok_tydi");
392 assert_eq!(cat!("", ""), "");
393 }
394
395 mod canonical {
396 use super::*;
397
398 #[test]
399 fn logical_to_common_prim() {
400 let typ = elements::prim(8).canonical("test");
401 assert_eq!(
402 typ,
403 vec![Signal::vec(
404 "test".to_string(),
405 Origin::Source,
406 Positive::new(8).unwrap()
407 )]
408 )
409 }
410
411 #[test]
412 fn logical_to_common_groups() {
413 let typ0 = elements::group().canonical("test");
414 assert_eq!(
415 typ0,
416 vec![
417 Signal::vec(
418 "test_a".to_string(),
419 Origin::Source,
420 Positive::new(42).unwrap()
421 ),
422 Signal::vec(
423 "test_b".to_string(),
424 Origin::Source,
425 Positive::new(1337).unwrap()
426 )
427 ]
428 );
429
430 let typ1 = elements::group_nested().canonical("test");
431 assert_eq!(
432 typ1,
433 vec![
434 Signal::vec(
435 "test_c_a".to_string(),
436 Origin::Source,
437 Positive::new(42).unwrap()
438 ),
439 Signal::vec(
440 "test_c_b".to_string(),
441 Origin::Source,
442 Positive::new(1337).unwrap()
443 ),
444 Signal::vec(
445 "test_d_a".to_string(),
446 Origin::Source,
447 Positive::new(42).unwrap()
448 ),
449 Signal::vec(
450 "test_d_b".to_string(),
451 Origin::Source,
452 Positive::new(1337).unwrap()
453 ),
454 ]
455 );
456
457 let typ2 = elements::group_of_single().canonical("test");
458 assert_eq!(
459 typ2,
460 vec![Signal::vec(
461 "test_a".to_string(),
462 Origin::Source,
463 Positive::new(42).unwrap()
464 ),]
465 );
466 }
467
468 #[test]
469 fn logical_to_common_streams() {
470 let typ0 = streams::prim(8).canonical("test");
471 dbg!(&typ0);
472
473 let typ1 = streams::group().canonical("test");
474 dbg!(&typ1);
475 }
477
478 #[test]
479 fn interface_to_port() {
480 let if0 =
481 Interface::try_new("test", crate::design::Mode::In, streams::prim(8)).unwrap();
482 dbg!(if0.canonical("test"));
483 let if1 =
484 Interface::try_new("test", crate::design::Mode::Out, streams::group()).unwrap();
485 dbg!(if1.canonical("test"));
486 }
488 }
489
490 mod user {
491 use super::*;
492 use crate::generator::common::Field;
493
494 #[test]
495 fn logical_to_common_prim() {
496 let typ: Type = elements::prim(8).user("test").unwrap();
497 assert_eq!(typ, records::prim(8));
498 }
499
500 #[test]
501 fn logical_to_common_groups() {
502 let typ0: Type = elements::group().user("test").unwrap();
503 assert_eq!(typ0, records::rec("test"));
504
505 let typ1: Type = elements::group_nested().user("test").unwrap();
506 assert_eq!(typ1, records::rec_nested("test"));
507
508 let typ2: Type = elements::group_of_single().user("test").unwrap();
509 assert_eq!(typ2, records::rec_of_single("test"));
510 }
511
512 #[test]
513 fn logical_to_common_streams() {
514 let typ0: Type = streams::prim(8).user("test").unwrap();
515 assert_eq!(
516 typ0,
517 Type::record(
518 "test_type",
519 vec![
520 Field::new("valid", Type::Bit, false),
521 Field::new("ready", Type::Bit, true),
522 Field::new("data", Type::bitvec(8), false)
523 ]
524 )
525 );
526
527 let typ1: Type = streams::group().user("test").unwrap();
528 assert_eq!(
529 typ1,
530 Type::record(
531 "test_type",
532 vec![
533 Field::new(
534 "a",
535 Type::record(
536 "test_a_type",
537 vec![
538 Field::new("valid", Type::Bit, false),
539 Field::new("ready", Type::Bit, true),
540 Field::new("data", Type::bitvec(42), false)
541 ]
542 ),
543 false
544 ),
545 Field::new(
546 "b",
547 Type::record(
548 "test_b_type",
549 vec![
550 Field::new("valid", Type::Bit, false),
551 Field::new("ready", Type::Bit, true),
552 Field::new("data", Type::bitvec(1337), false)
553 ]
554 ),
555 false
556 )
557 ]
558 )
559 );
560 }
561
562 #[test]
563 fn interface_to_port() {
564 let if0 =
565 Interface::try_new("test", crate::design::Mode::In, streams::prim(8)).unwrap();
566 dbg!(if0.user("test", "test"));
567 let if1 =
568 Interface::try_new("test", crate::design::Mode::Out, streams::group()).unwrap();
569 dbg!(if1.user("test", "test"));
570 }
572 }
573
574 #[test]
575 pub(crate) fn simple_streamlet() -> Result<()> {
576 let streamlet = Streamlet::from_builder(
577 Name::try_new("test")?,
578 UniquelyNamedBuilder::new().with_items(vec![
579 Interface::try_new("x", crate::design::Mode::In, streams::prim(8))?,
580 Interface::try_new("y", crate::design::Mode::Out, streams::group())?,
581 ]),
582 )?;
583 let common_streamlet = streamlet.user(None).unwrap();
585 let pkg = Library {
586 identifier: "boomer".to_string(),
587 components: vec![common_streamlet],
588 };
589 println!("{}", pkg.declare()?);
590 Ok(())
591 }
592
593 #[test]
594 pub(crate) fn nested_streams_streamlet() -> Result<()> {
595 let streamlet = Streamlet::from_builder(
596 Name::try_new("test")?,
597 UniquelyNamedBuilder::new().with_items(vec![
598 Interface::try_new("x", crate::design::Mode::In, streams::prim(8))?,
599 Interface::try_new("y", crate::design::Mode::Out, streams::nested())?,
600 ]),
601 )?;
602 let common_streamlet = streamlet.user(None).unwrap();
604 let pkg = Library {
605 identifier: "testing".to_string(),
606 components: vec![common_streamlet],
607 };
608 println!("{}", pkg.declare()?);
609 Ok(())
610 }
611
612 }