1use crate::traits::Identify;
53use crate::{util::log2_ceil, Error, NonNegative, PathName, Positive, Result};
54use indexmap::IndexMap;
55use std::str::FromStr;
56use std::{
57 cmp::Ordering,
58 convert::{TryFrom, TryInto},
59 fmt,
60};
61
62pub type BitCount = Positive;
64
65#[derive(Debug, Clone)]
93pub struct Complexity {
94 level: Vec<NonNegative>,
96}
97
98impl Default for Complexity {
99 fn default() -> Self {
100 Complexity { level: vec![4] }
101 }
102}
103
104impl PartialEq for Complexity {
105 fn eq(&self, other: &Self) -> bool {
111 (0..self.level.len().max(other.level.len()))
112 .all(|idx| self.level.get(idx).unwrap_or(&0) == other.level.get(idx).unwrap_or(&0))
113 }
114}
115
116impl Eq for Complexity {}
117
118impl PartialOrd for Complexity {
119 fn partial_cmp(&self, other: &Complexity) -> Option<Ordering> {
120 Some(self.cmp(other))
121 }
122}
123
124impl Ord for Complexity {
125 fn cmp(&self, other: &Complexity) -> Ordering {
131 (0..self.level.len().max(other.level.len()))
132 .map(|idx| {
133 (
134 self.level.get(idx).unwrap_or(&0),
135 other.level.get(idx).unwrap_or(&0),
136 )
137 })
138 .fold(None, |ord, (i, j)| match ord {
139 Some(ord) => Some(ord),
140 None => {
141 if i == j {
142 None
143 } else {
144 Some(i.cmp(j))
145 }
146 }
147 })
148 .unwrap_or(Ordering::Equal)
149 }
150}
151
152impl From<NonNegative> for Complexity {
153 fn from(major: NonNegative) -> Self {
155 Complexity::new_major(major)
156 }
157}
158
159impl TryFrom<Vec<NonNegative>> for Complexity {
160 type Error = Error;
161 fn try_from(level: Vec<NonNegative>) -> Result<Self> {
164 Complexity::new(level)
165 }
166}
167
168impl FromStr for Complexity {
169 type Err = Error;
170
171 fn from_str(s: &str) -> Result<Self> {
172 Complexity::new(
173 s.split('.')
175 .map(|d| d.trim().parse::<NonNegative>())
177 .collect::<std::result::Result<Vec<_>, std::num::ParseIntError>>()
179 .map_err(|e| Error::InvalidArgument(e.to_string()))?,
181 )
182 }
183}
184
185impl Complexity {
186 pub fn new(level: impl IntoIterator<Item = NonNegative>) -> Result<Self> {
199 let level = level.into_iter().collect::<Vec<NonNegative>>();
200 if level.is_empty() {
201 Err(Error::InvalidArgument(
202 "complexity level cannot be empty".to_string(),
203 ))
204 } else {
205 Ok(Complexity { level })
206 }
207 }
208
209 pub fn new_major(level: NonNegative) -> Self {
222 Complexity { level: vec![level] }
223 }
224
225 pub fn level(&self) -> &[NonNegative] {
237 self.level.as_ref()
238 }
239
240 pub fn major(&self) -> NonNegative {
251 self.level[0]
252 }
253}
254
255impl fmt::Display for Complexity {
256 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269 let mut result = String::new();
270 let mut level = self.level.iter().map(|x| x.to_string());
271 if let Some(x) = level.next() {
272 result.push_str(&x);
273 level.for_each(|x| {
274 result.push('.');
275 result.push_str(&x);
276 });
277 }
278 write!(f, "{}", result)
279 }
280}
281
282#[derive(Debug, Clone, PartialEq)]
283pub struct Fields(IndexMap<PathName, BitCount>);
284
285impl Fields {
286 pub fn new(iter: impl IntoIterator<Item = (PathName, BitCount)>) -> Result<Self> {
287 let fields = iter.into_iter();
288 let (lower, upper) = fields.size_hint();
289 let mut map = IndexMap::with_capacity(upper.unwrap_or(lower));
290
291 for (path_name, bit_count) in fields {
292 map.insert(path_name, bit_count)
293 .map(|_| -> Result<()> { Err(Error::UnexpectedDuplicate) })
294 .transpose()?;
295 }
296
297 Ok(Fields(map))
298 }
299
300 pub(crate) fn new_empty() -> Self {
301 Fields(IndexMap::new())
302 }
303
304 pub(crate) fn insert(&mut self, path_name: PathName, bit_count: BitCount) -> Result<()> {
305 self.0
306 .insert(path_name, bit_count)
307 .map(|_| -> Result<()> { Err(Error::UnexpectedDuplicate) })
308 .transpose()?;
309 Ok(())
310 }
311
312 pub fn iter(&self) -> impl Iterator<Item = (&PathName, &BitCount)> {
313 self.0.iter()
314 }
315
316 pub fn keys(&self) -> impl Iterator<Item = &PathName> {
317 self.0.keys()
318 }
319
320 pub fn values(&self) -> impl Iterator<Item = &BitCount> {
321 self.0.values()
322 }
323}
324
325impl<'a> IntoIterator for &'a Fields {
326 type Item = (&'a PathName, &'a BitCount);
327 type IntoIter = indexmap::map::Iter<'a, PathName, BitCount>;
328
329 fn into_iter(self) -> Self::IntoIter {
330 self.0.iter()
331 }
332}
333
334#[derive(Debug, Clone, PartialEq)]
344pub struct PhysicalStream {
345 element_fields: Fields,
347 element_lanes: Positive,
349 dimensionality: NonNegative,
351 complexity: Complexity,
353 user: Fields,
355}
356
357impl PhysicalStream {
358 pub fn try_new<T, U>(
359 element_fields: T,
360 element_lanes: usize,
361 dimensionality: usize,
362 complexity: impl Into<Complexity>,
363 user: T,
364 ) -> Result<Self>
365 where
366 T: IntoIterator<Item = (U, usize)>,
367 U: TryInto<PathName, Error = Error>,
368 {
369 let element_fields = Fields::new(
370 element_fields
371 .into_iter()
372 .map(|(path_name, bit_count)| {
373 (
374 path_name.try_into(),
375 Positive::new(bit_count as NonNegative),
376 )
377 })
378 .map(|(path_name, bit_count)| match (path_name, bit_count) {
379 (Ok(path_name), Some(bit_count)) => Ok((path_name, bit_count)),
380 (Err(e), _) => Err(e),
381 (_, None) => Err(Error::InvalidArgument(
382 "element lanes cannot be zero".to_string(),
383 )),
384 })
385 .collect::<Result<Vec<_>>>()?,
386 )?;
387 let element_lanes = Positive::new(element_lanes as NonNegative)
388 .ok_or_else(|| Error::InvalidArgument("element lanes cannot be zero".to_string()))?;
389 let dimensionality = dimensionality as NonNegative;
390 let complexity = complexity.into();
391 let user = Fields::new(
392 user.into_iter()
393 .map(|(path_name, bit_count)| {
394 (
395 path_name.try_into(),
396 Positive::new(bit_count as NonNegative),
397 )
398 })
399 .map(|(path_name, bit_count)| match (path_name, bit_count) {
400 (Ok(path_name), Some(bit_count)) => Ok((path_name, bit_count)),
401 (Err(e), _) => Err(e),
402 (_, None) => Err(Error::InvalidArgument(
403 "element lanes cannot be zero".to_string(),
404 )),
405 })
406 .collect::<Result<Vec<_>>>()?,
407 )?;
408 Ok(PhysicalStream::new(
409 element_fields,
410 element_lanes,
411 dimensionality,
412 complexity,
413 user,
414 ))
415 }
416 pub fn new(
419 element_fields: impl Into<Fields>,
420 element_lanes: Positive,
421 dimensionality: NonNegative,
422 complexity: impl Into<Complexity>,
423 user: impl Into<Fields>,
424 ) -> Self {
425 PhysicalStream {
426 element_fields: element_fields.into(),
427 element_lanes,
428 dimensionality,
429 complexity: complexity.into(),
430 user: user.into(),
431 }
432 }
433
434 pub fn element_fields(&self) -> &Fields {
436 &self.element_fields
437 }
438
439 pub fn element_lanes(&self) -> Positive {
441 self.element_lanes
442 }
443
444 pub fn dimensionality(&self) -> NonNegative {
446 self.dimensionality
447 }
448
449 pub fn complexity(&self) -> &Complexity {
451 &self.complexity
452 }
453
454 pub fn user(&self) -> &Fields {
456 &self.user
457 }
458
459 pub fn data_bit_count(&self) -> NonNegative {
463 self.element_fields
464 .values()
465 .map(|b| b.get())
466 .sum::<NonNegative>()
467 * self.element_lanes.get()
468 }
469
470 pub fn last_bit_count(&self) -> NonNegative {
473 self.dimensionality
474 }
475
476 pub fn stai_bit_count(&self) -> NonNegative {
479 if self.complexity.major() >= 6 && self.element_lanes.get() > 1 {
480 log2_ceil(self.element_lanes)
481 } else {
482 0
483 }
484 }
485
486 pub fn endi_bit_count(&self) -> NonNegative {
488 if (self.complexity.major() >= 5 || self.dimensionality >= 1)
489 && self.element_lanes.get() > 1
490 {
491 log2_ceil(self.element_lanes)
492 } else {
493 0
494 }
495 }
496
497 pub fn strb_bit_count(&self) -> NonNegative {
499 if self.complexity.major() >= 7 || self.dimensionality >= 1 {
500 self.element_lanes.get()
501 } else {
502 0
503 }
504 }
505
506 pub fn user_bit_count(&self) -> NonNegative {
508 self.user.values().map(|b| b.get()).sum::<NonNegative>()
509 }
510
511 pub fn signal_list(&self) -> SignalList {
513 let opt = |x| if x == 0 { None } else { Some(x) };
514 SignalList {
515 data: opt(self.data_bit_count()),
516 last: opt(self.last_bit_count()),
517 stai: opt(self.stai_bit_count()),
518 endi: opt(self.endi_bit_count()),
519 strb: opt(self.strb_bit_count()),
520 user: opt(self.user_bit_count()),
521 }
522 }
523
524 pub fn bit_count(&self) -> NonNegative {
527 self.data_bit_count()
528 + self.last_bit_count()
529 + self.stai_bit_count()
530 + self.endi_bit_count()
531 + self.strb_bit_count()
532 + self.user_bit_count()
533 }
534}
535
536impl From<&PhysicalStream> for SignalList {
537 fn from(physical_stream: &PhysicalStream) -> SignalList {
538 physical_stream.signal_list()
539 }
540}
541
542impl From<PhysicalStream> for SignalList {
543 fn from(physical_stream: PhysicalStream) -> SignalList {
544 physical_stream.signal_list()
545 }
546}
547
548#[derive(Debug, Copy, Clone, PartialEq)]
549pub enum Origin {
550 Source,
551 Sink,
552}
553
554#[derive(Debug, Copy, Clone, PartialEq)]
555pub enum Width {
556 Scalar,
558 Vector(NonNegative),
560}
561
562#[derive(Debug, Clone, PartialEq)]
563pub struct Signal {
564 name: String,
565 origin: Origin,
566 width: Width,
567}
568
569impl Identify for Signal {
570 fn identifier(&self) -> &str {
571 self.name.as_str()
572 }
573}
574
575impl Signal {
576 pub fn opt_vec(
578 name: impl Into<String>,
579 origin: Origin,
580 width: Option<NonNegative>,
581 ) -> Option<Signal> {
582 match width {
583 None => None,
584 Some(w) => Some(Signal {
585 name: name.into(),
586 origin,
587 width: Width::Vector(w),
588 }),
589 }
590 }
591
592 pub fn vec(name: impl Into<String>, origin: Origin, width: Positive) -> Signal {
594 Signal {
595 name: name.into(),
596 origin,
597 width: Width::Vector(width.get()),
598 }
599 }
600
601 pub fn bit(name: impl Into<String>, origin: Origin) -> Signal {
603 Signal {
604 name: name.into(),
605 origin,
606 width: Width::Scalar,
607 }
608 }
609
610 pub fn reversed(&self) -> bool {
612 self.origin == Origin::Sink
613 }
614
615 pub fn origin(&self) -> Origin {
616 self.origin
617 }
618
619 pub fn width(&self) -> Width {
620 self.width
621 }
622
623 pub fn with_name(&self, name: String) -> Signal {
624 Signal {
625 name,
626 origin: self.origin,
627 width: self.width,
628 }
629 }
630}
631
632#[derive(Debug, Copy, Clone, PartialEq)]
643pub struct SignalList {
644 data: Option<NonNegative>,
645 last: Option<NonNegative>,
646 stai: Option<NonNegative>,
647 endi: Option<NonNegative>,
648 strb: Option<NonNegative>,
649 user: Option<NonNegative>,
650}
651
652impl SignalList {
653 pub fn valid(&self) -> Signal {
655 Signal {
656 name: "valid".to_string(),
657 origin: Origin::Source,
658 width: Width::Scalar,
659 }
660 }
661
662 pub fn ready(&self) -> Signal {
664 Signal {
665 name: "ready".to_string(),
666 origin: Origin::Sink,
667 width: Width::Scalar,
668 }
669 }
670
671 pub fn data(&self) -> Option<Signal> {
673 Signal::opt_vec("data", Origin::Source, self.data)
674 }
675
676 pub fn last(&self) -> Option<Signal> {
678 Signal::opt_vec("last", Origin::Source, self.last)
679 }
680
681 pub fn stai(&self) -> Option<Signal> {
683 Signal::opt_vec("stai", Origin::Source, self.stai)
684 }
685
686 pub fn endi(&self) -> Option<Signal> {
688 Signal::opt_vec("endi", Origin::Source, self.endi)
689 }
690
691 pub fn strb(&self) -> Option<Signal> {
693 Signal::opt_vec("strb", Origin::Source, self.strb)
694 }
695
696 pub fn user(&self) -> Option<Signal> {
698 Signal::opt_vec("user", Origin::Source, self.user)
699 }
700
701 pub fn opt_bit_count(&self) -> Option<NonNegative> {
703 match self.data.unwrap_or(0)
704 + self.last.unwrap_or(0)
705 + self.stai.unwrap_or(0)
706 + self.endi.unwrap_or(0)
707 + self.strb.unwrap_or(0)
708 + self.user.unwrap_or(0)
709 {
710 0 => None,
711 x => Some(x),
712 }
713 }
714
715 pub fn bit_count(&self) -> NonNegative {
717 self.opt_bit_count().unwrap_or(0)
718 }
719}
720
721impl<'a> IntoIterator for &'a SignalList {
722 type Item = Signal;
723 type IntoIter = std::vec::IntoIter<Self::Item>;
724
725 fn into_iter(self) -> Self::IntoIter {
726 [
727 Some(self.valid()),
728 Some(self.ready()),
729 self.data(),
730 self.last(),
731 self.stai(),
732 self.endi(),
733 self.strb(),
734 self.user(),
735 ]
736 .iter()
737 .filter(|o| o.is_some())
738 .map(|s| s.clone().unwrap())
739 .collect::<Vec<_>>()
740 .into_iter()
741 }
742}
743
744#[cfg(test)]
745mod tests {
746 use super::*;
747 use std::convert::TryInto;
748
749 #[test]
750 #[allow(clippy::cognitive_complexity)]
751 fn complexity() -> Result<()> {
752 use std::convert::TryInto;
753
754 let empty = Complexity::new(vec![]);
755 assert_eq!(
756 empty.unwrap_err().to_string(),
757 "Invalid argument: complexity level cannot be empty"
758 );
759 assert_eq!(
760 Complexity::try_from(vec![]).unwrap_err().to_string(),
761 "Invalid argument: complexity level cannot be empty"
762 );
763
764 let c = Complexity::new_major(0);
765 let c3 = Complexity::new_major(3);
766 let c30 = Complexity::new(vec![3, 0])?;
767 let c31 = Complexity::new(vec![3, 1])?;
768 let c311 = Complexity::new(vec![3, 1, 1])?;
769 let c32 = Complexity::new(vec![3, 2])?;
770 let c4 = Complexity::new_major(4);
771 let c400 = Complexity::new(vec![4, 0, 0])?;
772 let c401 = Complexity::new(vec![4, 0, 1])?;
773 assert!(c < c3);
774 assert!(c3 < c31);
775 assert!(!(c3 < c30));
776 assert!(!(c3 > c30));
777 assert_eq!(c3, c30);
778 assert!(c31 < c311);
779 assert!(c311 < c32);
780 assert!(c32 < c4);
781 assert_eq!(c4, c4);
782 assert_eq!(c4, c400);
783 assert_eq!(c400, c4);
784 assert!(!(c400 > c4));
785 assert!(!(c400 < c4));
786 assert!(c400 < c401);
787 assert!(c4 < c401);
788 assert_eq!(c3, 3.into());
789 assert_eq!(c401, vec![4, 0, 1].try_into()?);
790
791 assert_eq!(c3.to_string(), "3");
792 assert_eq!(c31.to_string(), "3.1");
793
794 assert_eq!(c3.major(), 3);
795 assert_eq!(c31.major(), 3);
796 assert_eq!(c4.major(), 4);
797
798 assert_eq!(c4.level(), &[4]);
799 assert_eq!(c400.level(), &[4, 0, 0]);
800 Ok(())
801 }
802
803 #[test]
804 #[allow(clippy::cognitive_complexity)]
805 fn physical_stream() -> Result<()> {
806 let physical_stream = PhysicalStream::new(
807 Fields::new(vec![
808 ("a".try_into()?, BitCount::new(8).unwrap()),
809 ("b".try_into()?, BitCount::new(16).unwrap()),
810 ("c".try_into()?, BitCount::new(1).unwrap()),
811 ])?,
812 Positive::new(3).unwrap(),
813 4,
814 8,
815 Fields::new(vec![("user".try_into()?, BitCount::new(1).unwrap())])?,
816 );
817
818 let mut element = physical_stream.element_fields().iter();
819 assert_eq!(
820 element.next(),
821 Some((&("a".try_into()?), &BitCount::new(8).unwrap()))
822 );
823 assert_eq!(
824 element.next(),
825 Some((&("b".try_into()?), &BitCount::new(16).unwrap()))
826 );
827 assert_eq!(
828 element.next(),
829 Some((&("c".try_into()?), &BitCount::new(1).unwrap()))
830 );
831 assert_eq!(element.next(), None);
832 assert_eq!(physical_stream.element_lanes(), Positive::new(3).unwrap());
833 assert_eq!(physical_stream.dimensionality(), 4);
834 assert_eq!(physical_stream.complexity(), &Complexity::new_major(8));
835 assert_eq!(
836 physical_stream.user().iter().next().unwrap(),
837 (&("user".try_into()?), &BitCount::new(1).unwrap())
838 );
839 assert_eq!(physical_stream.bit_count(), 87);
840 assert_eq!(physical_stream.data_bit_count(), (8 + 16 + 1) * 3);
841 assert_eq!(physical_stream.last_bit_count(), 4);
842 assert_eq!(physical_stream.stai_bit_count(), 2);
843 assert_eq!(physical_stream.endi_bit_count(), 2);
844 assert_eq!(physical_stream.strb_bit_count(), 3);
845 assert_eq!(physical_stream.user_bit_count(), 1);
846 assert_eq!(
847 physical_stream.signal_list(),
848 SignalList {
849 data: Some(75),
850 last: Some(4),
851 stai: Some(2),
852 endi: Some(2),
853 strb: Some(3),
854 user: Some(1)
855 }
856 );
857
858 let physical_stream = PhysicalStream::new(
860 Fields::new(vec![("a".try_into()?, BitCount::new(8).unwrap())])?,
861 Positive::new(1).unwrap(),
862 0,
863 0,
864 Fields::new(vec![])?,
865 );
866
867 assert_eq!(physical_stream.element_fields().iter().count(), 1);
868 assert_eq!(physical_stream.element_lanes(), Positive::new(1).unwrap());
869 assert_eq!(physical_stream.dimensionality(), 0);
870 assert_eq!(physical_stream.complexity(), &Complexity::new_major(0));
871 assert_eq!(physical_stream.user().iter().next(), None);
872 assert_eq!(physical_stream.bit_count(), 8);
873 assert_eq!(physical_stream.data_bit_count(), 8);
874 assert_eq!(physical_stream.last_bit_count(), 0);
875 assert_eq!(physical_stream.stai_bit_count(), 0);
876 assert_eq!(physical_stream.endi_bit_count(), 0);
877 assert_eq!(physical_stream.strb_bit_count(), 0);
878 assert_eq!(physical_stream.user_bit_count(), 0);
879 assert_eq!(
880 physical_stream.signal_list(),
881 SignalList {
882 data: Some(8),
883 last: None,
884 stai: None,
885 endi: None,
886 strb: None,
887 user: None
888 }
889 );
890
891 Ok(())
892 }
893
894 #[test]
895 fn signal_list() -> Result<()> {
896 let physical_stream = PhysicalStream::new(
897 Fields::new(vec![
898 ("a".try_into()?, BitCount::new(3).unwrap()),
899 ("b".try_into()?, BitCount::new(2).unwrap()),
900 ])?,
901 Positive::new(2).unwrap(),
902 3,
903 8,
904 Fields::new(vec![])?,
905 );
906
907 let signal_list = SignalList::from(&physical_stream);
908 assert_eq!(physical_stream.bit_count(), 17);
909 assert_eq!(physical_stream.data_bit_count(), 2 * (3 + 2));
910 assert_eq!(physical_stream.last_bit_count(), 3);
911 assert_eq!(physical_stream.stai_bit_count(), 1);
912 assert_eq!(physical_stream.endi_bit_count(), 1);
913 assert_eq!(physical_stream.strb_bit_count(), 2);
914 assert_eq!(physical_stream.user_bit_count(), 0);
915
916 assert_eq!(
917 Width::Vector(physical_stream.data_bit_count()),
918 signal_list.data().unwrap().width
919 );
920 assert_eq!(
921 Width::Vector(physical_stream.last_bit_count()),
922 signal_list.last().unwrap().width
923 );
924 assert_eq!(
925 Width::Vector(physical_stream.stai_bit_count()),
926 signal_list.stai().unwrap().width
927 );
928 assert_eq!(
929 Width::Vector(physical_stream.endi_bit_count()),
930 signal_list.endi().unwrap().width
931 );
932 assert_eq!(
933 Width::Vector(physical_stream.strb_bit_count()),
934 signal_list.strb().unwrap().width
935 );
936 assert_eq!(
937 Width::Vector(physical_stream.user_bit_count()),
938 Width::Vector(0)
939 );
940
941 assert_eq!(signal_list.opt_bit_count(), Some(17));
942 assert_eq!(signal_list.bit_count(), 17);
943 assert_eq!(signal_list, SignalList::from(physical_stream));
944
945 assert_eq!(
946 signal_list.into_iter().collect::<Vec<_>>(),
947 vec![
948 Signal::bit("valid", Origin::Source),
949 Signal::bit("ready", Origin::Sink),
950 Signal::opt_vec("data", Origin::Source, Some(10)).unwrap(),
951 Signal::opt_vec("last", Origin::Source, Some(3)).unwrap(),
952 Signal::opt_vec("stai", Origin::Source, Some(1)).unwrap(),
953 Signal::opt_vec("endi", Origin::Source, Some(1)).unwrap(),
954 Signal::opt_vec("strb", Origin::Source, Some(2)).unwrap(),
955 ]
957 );
958
959 Ok(())
960 }
961}