1use std::convert::TryFrom;
2use std::fmt::Display;
3
4#[macro_use]
5extern crate bitfield;
6
7#[derive(Debug, Clone, PartialEq)]
9pub enum TlpError {
10 InvalidFormat,
12 InvalidType,
14 UnsupportedCombination,
16}
17
18#[repr(u8)]
19#[derive(PartialEq, Copy, Clone)]
20pub enum TlpFmt {
21 NoDataHeader3DW = 0b000,
22 NoDataHeader4DW = 0b001,
23 WithDataHeader3DW = 0b010,
24 WithDataHeader4DW = 0b011,
25 TlpPrefix = 0b100,
26}
27
28impl Display for TlpFmt {
29 fn fmt (&self, fmt: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
30 let name = match &self {
31 TlpFmt::NoDataHeader3DW => "3DW no Data Header",
32 TlpFmt::NoDataHeader4DW => "4DW no Data Header",
33 TlpFmt::WithDataHeader3DW => "3DW with Data Header",
34 TlpFmt::WithDataHeader4DW => "4DW with Data Header",
35 TlpFmt::TlpPrefix => "Tlp Prefix",
36 };
37 write!(fmt, "{}", name)
38 }
39}
40
41impl TryFrom<u32> for TlpFmt {
42 type Error = TlpError;
43
44 fn try_from(v: u32) -> Result<Self, Self::Error> {
45 match v {
46 x if x == TlpFmt::NoDataHeader3DW as u32 => Ok(TlpFmt::NoDataHeader3DW),
47 x if x == TlpFmt::NoDataHeader4DW as u32 => Ok(TlpFmt::NoDataHeader4DW),
48 x if x == TlpFmt::WithDataHeader3DW as u32 => Ok(TlpFmt::WithDataHeader3DW),
49 x if x == TlpFmt::WithDataHeader4DW as u32 => Ok(TlpFmt::WithDataHeader4DW),
50 x if x == TlpFmt::TlpPrefix as u32 => Ok(TlpFmt::TlpPrefix),
51 _ => Err(TlpError::InvalidFormat),
52 }
53 }
54}
55
56#[derive(PartialEq)]
57pub enum TlpFormatEncodingType {
58 MemoryRequest = 0b00000,
59 MemoryLockRequest = 0b00001,
60 IORequest = 0b00010,
61 ConfigType0Request = 0b00100,
62 ConfigType1Request = 0b00101,
63 Completion = 0b01010,
64 CompletionLocked = 0b01011,
65 FetchAtomicOpRequest = 0b01100,
66 UnconSwapAtomicOpRequest= 0b01101,
67 CompSwapAtomicOpRequest = 0b01110,
68}
69
70impl TryFrom<u32> for TlpFormatEncodingType {
71 type Error = TlpError;
72
73 fn try_from(v: u32) -> Result<Self, Self::Error> {
74 match v {
75 x if x == TlpFormatEncodingType::MemoryRequest as u32 => Ok(TlpFormatEncodingType::MemoryRequest),
76 x if x == TlpFormatEncodingType::MemoryLockRequest as u32 => Ok(TlpFormatEncodingType::MemoryLockRequest),
77 x if x == TlpFormatEncodingType::IORequest as u32 => Ok(TlpFormatEncodingType::IORequest),
78 x if x == TlpFormatEncodingType::ConfigType0Request as u32 => Ok(TlpFormatEncodingType::ConfigType0Request),
79 x if x == TlpFormatEncodingType::ConfigType1Request as u32 => Ok(TlpFormatEncodingType::ConfigType1Request),
80 x if x == TlpFormatEncodingType::Completion as u32 => Ok(TlpFormatEncodingType::Completion),
81 x if x == TlpFormatEncodingType::CompletionLocked as u32 => Ok(TlpFormatEncodingType::CompletionLocked),
82 x if x == TlpFormatEncodingType::FetchAtomicOpRequest as u32 => Ok(TlpFormatEncodingType::FetchAtomicOpRequest),
83 x if x == TlpFormatEncodingType::UnconSwapAtomicOpRequest as u32 => Ok(TlpFormatEncodingType::UnconSwapAtomicOpRequest),
84 x if x == TlpFormatEncodingType::CompSwapAtomicOpRequest as u32 => Ok(TlpFormatEncodingType::CompSwapAtomicOpRequest),
85 _ => Err(TlpError::InvalidType),
86 }
87 }
88}
89
90#[derive(PartialEq)]
91#[derive(Debug)]
92pub enum TlpType {
93 MemReadReq,
94 MemReadLockReq,
95 MemWriteReq,
96 IOReadReq,
97 IOWriteReq,
98 ConfType0ReadReq,
99 ConfType0WriteReq,
100 ConfType1ReadReq,
101 ConfType1WriteReq,
102 MsgReq,
103 MsgReqData,
104 Cpl,
105 CplData,
106 CplLocked,
107 CplDataLocked,
108 FetchAddAtomicOpReq,
109 SwapAtomicOpReq,
110 CompareSwapAtomicOpReq,
111 LocalTlpPrefix,
112 EndToEndTlpPrefix,
113}
114
115impl Display for TlpType {
116 fn fmt (&self, fmt: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
117 let name = match &self {
118 TlpType::MemReadReq => "Memory Read Request",
119 TlpType::MemReadLockReq => "Locked Memory Read Request",
120 TlpType::MemWriteReq => "Memory Write Request",
121 TlpType::IOReadReq => "IO Read Request",
122 TlpType::IOWriteReq => "IO Write Request",
123 TlpType::ConfType0ReadReq => "Type 0 Config Read Request",
124 TlpType::ConfType0WriteReq => "Type 0 Config Write Request",
125 TlpType::ConfType1ReadReq => "Type 1 Config Read Request",
126 TlpType::ConfType1WriteReq => "Type 1 Config Write Request",
127 TlpType::MsgReq => "Message Request",
128 TlpType::MsgReqData => "Message with Data Request",
129 TlpType::Cpl => "Completion",
130 TlpType::CplData => "Completion with Data",
131 TlpType::CplLocked => "Locked Completion",
132 TlpType::CplDataLocked => "Locked Completion with Data",
133 TlpType::FetchAddAtomicOpReq => "Fetch Add Atomic Op Request",
134 TlpType::SwapAtomicOpReq => "Swap Atomic Op Request",
135 TlpType::CompareSwapAtomicOpReq => "Compare Swap Atomic Op Request",
136 TlpType::LocalTlpPrefix => "Local Tlp Prefix",
137 TlpType::EndToEndTlpPrefix => "End To End Tlp Prefix",
138 };
139 write!(fmt, "{}", name)
140 }
141}
142
143bitfield! {
144 struct TlpHeader(MSB0 [u8]);
145 u32;
146 get_format, _: 2, 0;
147 get_type, _: 7, 3;
148 get_t9, _: 8, 8;
149 get_tc, _: 11, 9;
150 get_t8, _: 12, 12;
151 get_attr_b2, _: 13, 13;
152 get_ln, _: 14, 14;
153 get_th, _: 15, 15;
154 get_td, _: 16, 16;
155 get_ep, _: 17, 17;
156 get_attr, _: 19, 18;
157 get_at, _: 21, 20;
158 get_length, _: 31, 22;
159}
160
161impl<T: AsRef<[u8]>> TlpHeader<T> {
162
163 fn get_tlp_type(&self) -> Result<TlpType, TlpError> {
164 let tlp_type = self.get_type();
165 let tlp_fmt = self.get_format();
166
167 match TlpFormatEncodingType::try_from(tlp_type) {
168 Ok(TlpFormatEncodingType::MemoryRequest) => {
169 match TlpFmt::try_from(tlp_fmt) {
170 Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::MemReadReq),
171 Ok(TlpFmt::NoDataHeader4DW) => Ok(TlpType::MemReadReq),
172 Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::MemWriteReq),
173 Ok(TlpFmt::WithDataHeader4DW) => Ok(TlpType::MemWriteReq),
174 Ok(_) => Err(TlpError::UnsupportedCombination),
175 Err(e) => Err(e),
176 }
177 }
178 Ok(TlpFormatEncodingType::MemoryLockRequest) => {
179 match TlpFmt::try_from(tlp_fmt) {
180 Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::MemReadLockReq),
181 Ok(TlpFmt::NoDataHeader4DW) => Ok(TlpType::MemReadLockReq),
182 Ok(_) => Err(TlpError::UnsupportedCombination),
183 Err(e) => Err(e),
184 }
185 }
186 Ok(TlpFormatEncodingType::IORequest) => {
187 match TlpFmt::try_from(tlp_fmt) {
188 Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::IOReadReq),
189 Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::IOWriteReq),
190 Ok(_) => Err(TlpError::UnsupportedCombination),
191 Err(e) => Err(e),
192 }
193 }
194 Ok(TlpFormatEncodingType::ConfigType0Request) => {
195 match TlpFmt::try_from(tlp_fmt) {
196 Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::ConfType0ReadReq),
197 Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::ConfType0WriteReq),
198 Ok(_) => Err(TlpError::UnsupportedCombination),
199 Err(e) => Err(e),
200 }
201 }
202 Ok(TlpFormatEncodingType::ConfigType1Request) => {
203 match TlpFmt::try_from(tlp_fmt) {
204 Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::ConfType1ReadReq),
205 Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::ConfType1WriteReq),
206 Ok(_) => Err(TlpError::UnsupportedCombination),
207 Err(e) => Err(e),
208 }
209 }
210 Ok(TlpFormatEncodingType::Completion) => {
211 match TlpFmt::try_from(tlp_fmt) {
212 Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::Cpl),
213 Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::CplData),
214 Ok(_) => Err(TlpError::UnsupportedCombination),
215 Err(e) => Err(e),
216 }
217 }
218 Ok(TlpFormatEncodingType::CompletionLocked) => {
219 match TlpFmt::try_from(tlp_fmt) {
220 Ok(TlpFmt::NoDataHeader3DW) => Ok(TlpType::CplLocked),
221 Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::CplDataLocked),
222 Ok(_) => Err(TlpError::UnsupportedCombination),
223 Err(e) => Err(e),
224 }
225 }
226 Ok(TlpFormatEncodingType::FetchAtomicOpRequest) => {
227 match TlpFmt::try_from(tlp_fmt) {
228 Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::FetchAddAtomicOpReq),
229 Ok(TlpFmt::WithDataHeader4DW) => Ok(TlpType::FetchAddAtomicOpReq),
230 Ok(_) => Err(TlpError::UnsupportedCombination),
231 Err(e) => Err(e),
232 }
233 }
234 Ok(TlpFormatEncodingType::UnconSwapAtomicOpRequest) => {
235 match TlpFmt::try_from(tlp_fmt) {
236 Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::SwapAtomicOpReq),
237 Ok(TlpFmt::WithDataHeader4DW) => Ok(TlpType::SwapAtomicOpReq),
238 Ok(_) => Err(TlpError::UnsupportedCombination),
239 Err(e) => Err(e),
240 }
241 }
242 Ok(TlpFormatEncodingType::CompSwapAtomicOpRequest) => {
243 match TlpFmt::try_from(tlp_fmt) {
244 Ok(TlpFmt::WithDataHeader3DW) => Ok(TlpType::CompareSwapAtomicOpReq),
245 Ok(TlpFmt::WithDataHeader4DW) => Ok(TlpType::CompareSwapAtomicOpReq),
246 Ok(_) => Err(TlpError::UnsupportedCombination),
247 Err(e) => Err(e),
248 }
249 }
250 Err(e) => Err(e)
251 }
252 }
253}
254
255pub trait MemRequest {
262 fn address(&self) -> u64;
263 fn req_id(&self) -> u16;
264 fn tag(&self) -> u8;
265 fn ldwbe(&self) -> u8;
266 fn fdwbe(&self) -> u8;
267}
268
269bitfield! {
271 pub struct MemRequest3DW(MSB0 [u8]);
272 u32;
273 pub get_requester_id, _: 15, 0;
274 pub get_tag, _: 23, 16;
275 pub get_last_dw_be, _: 27, 24;
276 pub get_first_dw_be, _: 31, 28;
277 pub get_address32, _: 63, 32;
278}
279
280bitfield! {
281 pub struct MemRequest4DW(MSB0 [u8]);
282 u64;
283 pub get_requester_id, _: 15, 0;
284 pub get_tag, _: 23, 16;
285 pub get_last_dw_be, _: 27, 24;
286 pub get_first_dw_be, _: 31, 28;
287 pub get_address64, _: 95, 32;
288}
289
290impl <T: AsRef<[u8]>> MemRequest for MemRequest3DW<T> {
291 fn address(&self) -> u64 {
292 self.get_address32().into()
293 }
294 fn req_id(&self) -> u16 {
295 self.get_requester_id() as u16
296 }
297 fn tag(&self) -> u8 {
298 self.get_tag() as u8
299 }
300 fn ldwbe(&self) -> u8 {
301 self.get_last_dw_be() as u8
302 }
303 fn fdwbe(&self) -> u8 {
304 self.get_first_dw_be() as u8
305 }
306}
307
308impl <T: AsRef<[u8]>> MemRequest for MemRequest4DW<T> {
309 fn address(&self) -> u64 {
310 self.get_address64()
311 }
312 fn req_id(&self) -> u16 {
313 self.get_requester_id() as u16
314 }
315 fn tag(&self) -> u8 {
316 self.get_tag() as u8
317 }
318 fn ldwbe(&self) -> u8 {
319 self.get_last_dw_be() as u8
320 }
321 fn fdwbe(&self) -> u8 {
322 self.get_first_dw_be() as u8
323 }
324}
325
326pub fn new_mem_req(bytes: Vec<u8>, format: &TlpFmt) -> Box<dyn MemRequest> {
356 match format {
357 TlpFmt::NoDataHeader3DW => Box::new(MemRequest3DW(bytes)),
358 TlpFmt::NoDataHeader4DW => Box::new(MemRequest4DW(bytes)),
359 TlpFmt::WithDataHeader3DW => Box::new(MemRequest3DW(bytes)),
360 TlpFmt::WithDataHeader4DW => Box::new(MemRequest4DW(bytes)),
361 TlpFmt::TlpPrefix => Box::new(MemRequest3DW(bytes)),
362 }
363}
364
365pub trait ConfigurationRequest {
369 fn req_id(&self) -> u16;
370 fn tag(&self) -> u8;
371 fn bus_nr(&self) -> u8;
372 fn dev_nr(&self) -> u8;
373 fn func_nr(&self) -> u8;
374 fn ext_reg_nr(&self) -> u8;
375 fn reg_nr(&self) -> u8;
376}
377
378pub fn new_conf_req(bytes: Vec<u8>, _format: &TlpFmt) -> Box<dyn ConfigurationRequest> {
400 Box::new(ConfigRequest(bytes))
401}
402
403bitfield! {
404 pub struct ConfigRequest(MSB0 [u8]);
405 u32;
406 pub get_requester_id, _: 15, 0;
407 pub get_tag, _: 23, 16;
408 pub get_last_dw_be, _: 27, 24;
409 pub get_first_dw_be, _: 31, 28;
410 pub get_bus_nr, _: 39, 32;
411 pub get_dev_nr, _: 44, 40;
412 pub get_func_nr, _: 47, 45;
413 pub rsvd, _: 51, 48;
414 pub get_ext_reg_nr, _: 55, 52;
415 pub get_register_nr, _: 61, 56;
416 r, _: 63, 62;
417}
418
419impl <T: AsRef<[u8]>> ConfigurationRequest for ConfigRequest<T> {
420 fn req_id(&self) -> u16 {
421 self.get_requester_id() as u16
422 }
423 fn tag(&self) -> u8 {
424 self.get_tag() as u8
425 }
426 fn bus_nr(&self) -> u8 {
427 self.get_bus_nr() as u8
428 }
429 fn dev_nr(&self) -> u8 {
430 self.get_dev_nr() as u8
431 }
432 fn func_nr(&self) -> u8 {
433 self.get_func_nr() as u8
434 }
435 fn ext_reg_nr(&self) -> u8 {
436 self.get_ext_reg_nr() as u8
437 }
438 fn reg_nr(&self) -> u8 {
439 self.get_register_nr() as u8
440 }
441}
442
443pub trait CompletionRequest {
449 fn cmpl_id(&self) -> u16;
450 fn cmpl_stat(&self) -> u8;
451 fn bcm(&self) -> u8;
452 fn byte_cnt(&self) -> u16;
453 fn req_id(&self) -> u16;
454 fn tag(&self) -> u8;
455 fn laddr(&self) -> u8;
456}
457
458bitfield! {
459 pub struct CompletionReqDW23(MSB0 [u8]);
460 u16;
461 pub get_completer_id, _: 15, 0;
462 pub get_cmpl_stat, _: 18, 16;
463 pub get_bcm, _: 19, 19;
464 pub get_byte_cnt, _: 31, 20;
465 pub get_req_id, _: 47, 32;
466 pub get_tag, _: 55, 48;
467 r, _: 57, 56;
468 pub get_laddr, _: 63, 58;
469}
470
471impl <T: AsRef<[u8]>> CompletionRequest for CompletionReqDW23<T> {
472 fn cmpl_id(&self) -> u16 {
473 self.get_completer_id()
474 }
475 fn cmpl_stat(&self) -> u8 {
476 self.get_cmpl_stat() as u8
477 }
478 fn bcm(&self) -> u8 {
479 self.get_bcm() as u8
480 }
481 fn byte_cnt(&self) -> u16 {
482 self.get_byte_cnt()
483 }
484 fn req_id(&self) -> u16 {
485 self.get_req_id()
486 }
487 fn tag(&self) -> u8 {
488 self.get_tag() as u8
489 }
490 fn laddr(&self) -> u8 {
491 self.get_laddr() as u8
492 }
493}
494
495pub fn new_cmpl_req(bytes: Vec<u8>, _format: &TlpFmt) -> Box<dyn CompletionRequest> {
513 Box::new(CompletionReqDW23(bytes))
514}
515
516pub trait MessageRequest {
519 fn req_id(&self) -> u16;
520 fn tag(&self) -> u8;
521 fn msg_code(&self) -> u8;
522 fn dw3(&self) -> u32;
524 fn dw4(&self) -> u32;
525}
526
527bitfield! {
528 pub struct MessageReqDW24(MSB0 [u8]);
529 u16;
530 pub get_requester_id, _: 15, 0;
531 pub get_tag, _: 23, 16;
532 pub get_msg_code, _: 31, 24;
533 pub get_dw3, _: 63, 32;
534 pub get_dw4, _: 96, 64;
535}
536
537impl <T: AsRef<[u8]>> MessageRequest for MessageReqDW24<T> {
538 fn req_id(&self) -> u16 {
539 self.get_requester_id()
540 }
541 fn tag(&self) -> u8 {
542 self.get_tag() as u8
543 }
544 fn msg_code(&self) -> u8 {
545 self.get_msg_code() as u8
546 }
547 fn dw3(&self) -> u32 {
548 self.get_dw3() as u32
549 }
550 fn dw4(&self) -> u32 {
551 self.get_dw4() as u32
552 }
553 }
555
556pub fn new_msg_req(bytes: Vec<u8>, _format: &TlpFmt) -> Box<dyn MessageRequest> {
573 Box::new(MessageReqDW24(bytes))
574}
575
576pub struct TlpPacketHeader {
579 header: TlpHeader<Vec<u8>>,
580}
581
582impl TlpPacketHeader {
583 pub fn new(bytes: Vec<u8>) -> TlpPacketHeader {
584 let mut dw0 = vec![0; 4];
585 dw0[..4].clone_from_slice(&bytes[0..4]);
586
587 TlpPacketHeader { header: TlpHeader(dw0) }
588 }
589
590 pub fn get_tlp_type(&self) -> Result<TlpType, TlpError> {
591 self.header.get_tlp_type()
592 }
593
594 pub fn get_format(&self) -> u32 {self.header.get_format()}
595 pub fn get_type(&self) -> u32 {self.header.get_type()}
596 pub fn get_t9(&self) -> u32 {self.header.get_t9()}
597 pub fn get_tc(&self) -> u32 {self.header.get_tc()}
598 pub fn get_t8(&self) -> u32 {self.header.get_t8()}
599 pub fn get_attr_b2(&self) -> u32 {self.header.get_attr_b2()}
600 pub fn get_ln(&self) -> u32 {self.header.get_ln()}
601 pub fn get_th(&self) -> u32 {self.header.get_th()}
602 pub fn get_td(&self) -> u32 {self.header.get_td()}
603 pub fn get_ep(&self) -> u32 {self.header.get_ep()}
604 pub fn get_attr(&self) -> u32 {self.header.get_attr()}
605 pub fn get_at(&self) -> u32 {self.header.get_at()}
606 pub fn get_length(&self) -> u32 {self.header.get_length()}
607
608}
609
610pub struct TlpPacket {
658 header: TlpPacketHeader,
659 data: Vec<u8>,
660}
661
662impl TlpPacket {
663 pub fn new(bytes: Vec<u8>) -> TlpPacket {
664 let mut ownbytes = bytes.to_vec();
665 let mut header = vec![0; 4];
666 header.clone_from_slice(&ownbytes[0..4]);
667 let data = ownbytes.drain(4..).collect();
668 TlpPacket {
669 header: TlpPacketHeader::new(header),
670 data,
671 }
672 }
673
674 pub fn get_header(&self) -> &TlpPacketHeader {
675 &self.header
676 }
677
678 pub fn get_data(&self) -> Vec<u8> {
679 self.data.to_vec()
680 }
681
682 pub fn get_tlp_type(&self) -> Result<TlpType, TlpError> {
683 self.header.get_tlp_type()
684 }
685
686 pub fn get_tlp_format(&self) -> TlpFmt {
687 let fmt : TlpFmt = TlpFmt::try_from(self.header.get_format()).unwrap();
688
689 fmt
690 }
691}
692
693
694#[cfg(test)]
695mod tests {
696 use super::*;
697
698 #[test]
699 fn test_tlp_packet() {
700 let d = vec![0x04, 0x00, 0x00, 0x01, 0x20, 0x01, 0xFF, 0x00, 0xC2, 0x81, 0xFF, 0x10];
701 let tlp = TlpPacket::new(d);
702
703 assert_eq!(tlp.get_tlp_type().unwrap(), TlpType::ConfType0ReadReq);
704 assert_eq!(tlp.get_data(), vec![0x20, 0x01, 0xFF, 0x00, 0xC2, 0x81, 0xFF, 0x10]);
705 }
706
707 #[test]
708 fn test_complreq_trait() {
709 let cmpl_req = CompletionReqDW23([0x20, 0x01, 0xFF, 0x00, 0xC2, 0x81, 0xFF, 0x10]);
710
711 assert_eq!(0x2001, cmpl_req.cmpl_id());
712 assert_eq!(0x7, cmpl_req.cmpl_stat());
713 assert_eq!(0x1, cmpl_req.bcm());
714 assert_eq!(0xF00, cmpl_req.byte_cnt());
715 assert_eq!(0xC281, cmpl_req.req_id());
716 assert_eq!(0xFF, cmpl_req.tag());
717 assert_eq!(0x10, cmpl_req.laddr());
718 }
719
720 #[test]
721 fn test_configreq_trait() {
722 let conf_req = ConfigRequest([0x20, 0x01, 0xFF, 0x00, 0xC2, 0x81, 0xFF, 0x10]);
723
724 assert_eq!(0x2001, conf_req.req_id());
725 assert_eq!(0xFF, conf_req.tag());
726 assert_eq!(0xC2, conf_req.bus_nr());
727 assert_eq!(0x10, conf_req.dev_nr());
728 assert_eq!(0x01, conf_req.func_nr());
729 assert_eq!(0x0F, conf_req.ext_reg_nr());
730 assert_eq!(0x04, conf_req.reg_nr());
731 }
732
733 #[test]
734 fn is_memreq_tag_works() {
735 let mr3dw1 = MemRequest3DW([0x00, 0x00, 0x20, 0x0F, 0xF6, 0x20, 0x00, 0x0C]);
736 let mr3dw2 = MemRequest3DW([0x00, 0x00, 0x01, 0x0F, 0xF6, 0x20, 0x00, 0x0C]);
737 let mr3dw3 = MemRequest3DW([0x00, 0x00, 0x10, 0x0F, 0xF6, 0x20, 0x00, 0x0C]);
738 let mr3dw4 = MemRequest3DW([0x00, 0x00, 0x81, 0x0F, 0xF6, 0x20, 0x00, 0x0C]);
739
740 assert_eq!(0x20, mr3dw1.tag());
741 assert_eq!(0x01, mr3dw2.tag());
742 assert_eq!(0x10, mr3dw3.tag());
743 assert_eq!(0x81, mr3dw4.tag());
744
745 let mr4dw1 = MemRequest4DW([0x00, 0x00, 0x01, 0x0F, 0x00, 0x00, 0x01, 0x7f, 0xc0, 0x00, 0x00, 0x00]);
746 let mr4dw2 = MemRequest4DW([0x00, 0x00, 0x10, 0x0F, 0x00, 0x00, 0x01, 0x7f, 0xc0, 0x00, 0x00, 0x00]);
747 let mr4dw3 = MemRequest4DW([0x00, 0x00, 0x81, 0x0F, 0x00, 0x00, 0x01, 0x7f, 0xc0, 0x00, 0x00, 0x00]);
748 let mr4dw4 = MemRequest4DW([0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x01, 0x7f, 0xc0, 0x00, 0x00, 0x00]);
749 let mr4dw5 = MemRequest4DW([0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x01, 0x7f, 0xc0, 0x00, 0x00, 0x00]);
750
751 assert_eq!(0x01, mr4dw1.tag());
752 assert_eq!(0x10, mr4dw2.tag());
753 assert_eq!(0x81, mr4dw3.tag());
754 assert_eq!(0xFF, mr4dw4.tag());
755 assert_eq!(0x00, mr4dw5.tag());
756 }
757
758 #[test]
759 fn is_memreq_3dw_address_works() {
760 let memreq_3dw = [0x00, 0x00, 0x20, 0x0F, 0xF6, 0x20, 0x00, 0x0C];
761 let mr = MemRequest3DW(memreq_3dw);
762
763 assert_eq!(0xF620000C, mr.address());
764 }
765
766 #[test]
767 fn is_memreq_4dw_address_works() {
768 let memreq_4dw = [0x00, 0x00, 0x20, 0x0F, 0x00, 0x00, 0x01, 0x7f, 0xc0, 0x00, 0x00, 0x00];
769 let mr = MemRequest4DW(memreq_4dw);
770
771 assert_eq!(0x17fc0000000, mr.address());
772 }
773
774 #[test]
775 fn is_tlppacket_creates() {
776 let memrd32_header = [0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x20, 0x0F, 0xF6, 0x20, 0x00, 0x0C];
777
778 let mr = TlpPacketHeader::new(memrd32_header.to_vec());
779 assert_eq!(mr.get_tlp_type().unwrap(), TlpType::MemReadReq);
780 }
781
782 #[test]
783 fn tlp_header_type() {
784 let memread = TlpHeader([0x0, 0x0, 0x0, 0x0]);
786 assert_eq!(memread.get_tlp_type().unwrap(), TlpType::MemReadReq);
787
788 let memread32 = TlpHeader([0x00, 0x00, 0x20, 0x01]);
790 assert_eq!(memread32.get_tlp_type().unwrap(), TlpType::MemReadReq);
791
792 let memwrite32 = TlpHeader([0x40, 0x00, 0x00, 0x01]);
794 assert_eq!(memwrite32.get_tlp_type().unwrap(), TlpType::MemWriteReq);
795
796 let cpl_no_data = TlpHeader([0x0a, 0x00, 0x10, 0x00]);
798 assert_eq!(cpl_no_data.get_tlp_type().unwrap(), TlpType::Cpl);
799
800 let cpl_with_data = TlpHeader([0x4a, 0x00, 0x20, 0x40]);
802 assert_eq!(cpl_with_data.get_tlp_type().unwrap(), TlpType::CplData);
803
804 let memread_4dw = TlpHeader([0x20, 0x00, 0x20, 0x40]);
806 assert_eq!(memread_4dw.get_tlp_type().unwrap(), TlpType::MemReadReq);
807
808 let conf_t0_read = TlpHeader([0x04, 0x00, 0x00, 0x01]);
810 assert_eq!(conf_t0_read.get_tlp_type().unwrap(), TlpType::ConfType0ReadReq);
811
812 let conf_t0_write = TlpHeader([0x44, 0x00, 0x00, 0x01]);
814 assert_eq!(conf_t0_write.get_tlp_type().unwrap(), TlpType::ConfType0WriteReq);
815
816 let conf_t1_read = TlpHeader([0x05, 0x88, 0x80, 0x01]);
818 assert_eq!(conf_t1_read.get_tlp_type().unwrap(), TlpType::ConfType1ReadReq);
819
820 let conf_t1_write = TlpHeader([0x45, 0x88, 0x80, 0x01]);
822 assert_eq!(conf_t1_write.get_tlp_type().unwrap(), TlpType::ConfType1WriteReq);
823
824 let memwrite64 = TlpHeader([0x60, 0x00, 0x90, 0x01]);
827 assert_eq!(memwrite64.get_tlp_type().unwrap(), TlpType::MemWriteReq);
828 }
829
830 #[test]
831 fn tlp_header_works_all_zeros() {
832 let bits_locations = TlpHeader([0x0, 0x0, 0x0, 0x0]);
833
834 assert_eq!(bits_locations.get_format(), 0);
835 assert_eq!(bits_locations.get_type(), 0);
836 assert_eq!(bits_locations.get_t9(), 0);
837 assert_eq!(bits_locations.get_tc(), 0);
838 assert_eq!(bits_locations.get_t8(), 0);
839 assert_eq!(bits_locations.get_attr_b2(), 0);
840 assert_eq!(bits_locations.get_ln(), 0);
841 assert_eq!(bits_locations.get_th(), 0);
842 assert_eq!(bits_locations.get_td(), 0);
843 assert_eq!(bits_locations.get_ep(), 0);
844 assert_eq!(bits_locations.get_attr(), 0);
845 assert_eq!(bits_locations.get_at(), 0);
846 assert_eq!(bits_locations.get_length(), 0);
847 }
848
849 #[test]
850 fn tlp_header_works_all_ones() {
851 let bits_locations = TlpHeader([0xff, 0xff, 0xff, 0xff]);
852
853 assert_eq!(bits_locations.get_format(), 0x7);
854 assert_eq!(bits_locations.get_type(), 0x1f);
855 assert_eq!(bits_locations.get_t9(), 0x1);
856 assert_eq!(bits_locations.get_tc(), 0x7);
857 assert_eq!(bits_locations.get_t8(), 0x1);
858 assert_eq!(bits_locations.get_attr_b2(), 0x1);
859 assert_eq!(bits_locations.get_ln(), 0x1);
860 assert_eq!(bits_locations.get_th(), 0x1);
861 assert_eq!(bits_locations.get_td(), 0x1);
862 assert_eq!(bits_locations.get_ep(), 0x1);
863 assert_eq!(bits_locations.get_attr(), 0x3);
864 assert_eq!(bits_locations.get_at(), 0x3);
865 assert_eq!(bits_locations.get_length(), 0x3ff);
866 }
867
868 #[test]
869 fn test_invalid_format_error() {
870 let invalid_fmt = TlpHeader([0xa0, 0x00, 0x00, 0x01]); let result = invalid_fmt.get_tlp_type();
873 assert!(result.is_err());
874 assert_eq!(result.unwrap_err(), TlpError::InvalidFormat);
875 }
876
877 #[test]
878 fn test_invalid_type_error() {
879 let invalid_type = TlpHeader([0x0f, 0x00, 0x00, 0x01]); let result = invalid_type.get_tlp_type();
882 assert!(result.is_err());
883 assert_eq!(result.unwrap_err(), TlpError::InvalidType);
884 }
885
886 #[test]
887 fn test_unsupported_combination_error() {
888 let invalid_combo = TlpHeader([0x22, 0x00, 0x00, 0x01]); let result = invalid_combo.get_tlp_type();
892 assert!(result.is_err());
893 assert_eq!(result.unwrap_err(), TlpError::UnsupportedCombination);
894 }
895
896 #[test]
897 fn test_tlp_packet_invalid_type() {
898 let invalid_data = vec![0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00];
900 let packet = TlpPacket::new(invalid_data);
901 let result = packet.get_tlp_type();
902 assert!(result.is_err());
903 assert_eq!(result.unwrap_err(), TlpError::InvalidType);
904 }
905}