gaffe_xilinx/xc7/
bitstream.rs

1use ::byteorder::BigEndian;
2use ::byteorder::ReadBytesExt;
3use ::byteorder::WriteBytesExt;
4use ::failure::Error;
5use ::failure::ResultExt;
6use ::from_bytes::BufReadFromBytesExt;
7use ::from_bytes::FromBytes;
8use ::from_bytes::ToBytes;
9use ::packed_struct::prelude::*;
10use ::packed_struct::debug_fmt::PackedStructDebug;
11use ::std::fmt;
12use ::std::io::prelude::*;
13use super::FromWord;
14use super::ToWord;
15use super::Register;
16use super::Word;
17
18#[derive(Debug, Display, Clone, Copy, PartialEq, PrimitiveEnum)]
19pub enum Opcode {
20    NOP = 0b00,
21    Read = 0b01,
22    Write = 0b10,
23}
24impl Default for Opcode {
25    fn default() -> Self {
26        Opcode::NOP
27    }
28}
29
30#[derive(Debug, Display, Clone, Copy, PartialEq, PrimitiveEnum)]
31#[allow(non_camel_case_types)]
32pub enum RegisterAddress {
33    CRC = 0b00000,
34    FAR = 0b00001,
35    FDRI = 0b00010,
36    FDRO = 0b00011,
37    CMD = 0b00100,
38    CTL0 = 0b00101,
39    MASK = 0b00110,
40    STAT = 0b00111,
41    LOUT = 0b01000,
42    COR0 = 0b01001,
43    MFWR = 0b01010,
44    CBC = 0b01011,
45    IDCODE = 0b01100,
46    AXSS = 0b01101,
47    COR1 = 0b01110,
48    WBSTAR = 0b10000,
49    TIMER = 0b10001,
50    UNKNOWN_1 = 0b10011,
51    BOOTSTS = 0b10110,
52    CTL1 = 0b11000,
53    BSPI = 0b11111,
54}
55impl Default for RegisterAddress {
56    fn default() -> Self {
57        RegisterAddress::CRC
58    }
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, PrimitiveEnum)]
62enum PacketType {
63    Type0 = 0b000,
64    Type1 = 0b001,
65    Type2 = 0b010,
66}
67impl Default for PacketType {
68    fn default() -> Self {
69        PacketType::Type0
70    }
71}
72
73#[derive(PackedStruct, Default, Debug, PartialEq)]
74#[packed_struct(size_bytes="4", bit_numbering="lsb0", endian="msb")]
75pub struct Type0Header {
76    #[packed_field(bits="31:29", ty="enum")]
77    packet_type: PacketType,
78
79    #[packed_field(bits="28:0")]
80    _reserved: ReservedZeroes<packed_bits::Bits29>,
81}
82
83#[derive(PackedStruct, Default, Debug, PartialEq)]
84#[packed_struct(size_bytes="4", bit_numbering="lsb0", endian="msb")]
85pub struct Type1Header {
86    #[packed_field(bits="31:29", ty="enum")]
87    packet_type: PacketType,
88
89    #[packed_field(bits="28:27", ty="enum")]
90    opcode: Opcode,
91
92    #[packed_field(bits="26:18")]
93    _address_reserved: ReservedZeroes<packed_bits::Bits9>,
94
95    #[packed_field(bits="17:13", ty="enum")]
96    address: RegisterAddress,
97
98    #[packed_field(bits="12:11")]
99    _reserved: ReservedZeroes<packed_bits::Bits2>,
100
101    #[packed_field(bits="10:0")]
102    word_count: Integer<u16, packed_bits::Bits11>,
103}
104
105#[derive(PackedStruct, Default, Debug, PartialEq)]
106#[packed_struct(size_bytes="4", bit_numbering="lsb0", endian="msb")]
107pub struct Type2Header {
108    #[packed_field(bits="31:29", ty="enum")]
109    packet_type: PacketType,
110
111    #[packed_field(bits="28:27", ty="enum")]
112    opcode: Opcode,
113
114    #[packed_field(bits="26:0")]
115    word_count: Integer<u32, packed_bits::Bits27>,
116}
117
118
119#[derive(Debug, Clone)]
120pub enum Packet {
121    Type0,
122    Type1 {
123        opcode: Opcode,
124        address: RegisterAddress,
125        payload: Vec<Word>,
126    },
127    Type2 {
128        opcode: Opcode,
129        payload: Vec<Word>,
130    },
131}
132
133impl Packet {
134    pub fn nop() -> Self {
135        Packet::Type1{
136            opcode: Opcode::NOP,
137            address: RegisterAddress::CRC,
138            payload: Vec::new(),
139        }
140    }
141}
142
143impl<T> From<T> for Packet
144where
145    T: ToWord + Register
146{
147    fn from(reg: T) -> Self {
148        Packet::Type1{
149            opcode: Opcode::Write,
150            address: reg.register_address(),
151            payload: vec![reg.to_word()],
152        }
153    }
154}
155
156fn write_reg_value<T>(f: &mut fmt::Formatter, payload: &Vec<Word>) -> fmt::Result
157where
158    T: FromWord + PackedStructDebug
159{
160    match T::from_word(payload[0]) {
161        Ok(x) => {
162            writeln!(f, "")?;
163            x.fmt_fields(f)
164        },
165        Err(_) => {
166            error!("Register decoding failed");
167            write_payload(f, payload)
168        },
169    }
170}
171
172fn write_payload(f: &mut fmt::Formatter, payload: &Vec<Word>) -> fmt::Result
173{
174    for (row, payload_line) in payload.chunks(4).enumerate() {
175        write!(f, "{:04x}:    ", row * 4)?;
176        for (col, payload_word) in payload_line.iter().enumerate() {
177            write!(f, "{:08x}{}", payload_word,
178                match col+1 {
179                    n if n == payload_line.len() => "",
180                    _ => " ",
181                }
182            )?;
183        }
184        writeln!(f, "")?;
185    }
186    Ok(())    
187}
188
189impl fmt::Display for Packet {
190    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
191        match *self {
192            Packet::Type0 => writeln!(f, "[Type0]"),
193            Packet::Type1 { opcode, address, ref payload } => {
194                match opcode {
195                    Opcode::NOP => writeln!(f, "[Type1 NOP]"),
196                    _ => {
197                        writeln!(f, "[Type1 {}({}) {}]", opcode, payload.len(), address)?;
198                        match address {
199                            RegisterAddress::CRC => write_reg_value::<super::registers::CrcRegister>(f, payload),
200                            RegisterAddress::FAR => write_reg_value::<super::registers::FrameAddressRegister>(f, payload),
201                            RegisterAddress::CMD => write_reg_value::<super::registers::CommandRegister>(f, payload),
202                            RegisterAddress::CTL0 => write_reg_value::<super::registers::ControlRegister0>(f, payload),
203                            RegisterAddress::STAT => write_reg_value::<super::registers::StatusRegister>(f, payload),
204                            RegisterAddress::LOUT => write_reg_value::<super::registers::LoutRegister>(f, payload),
205                            RegisterAddress::COR0 => write_reg_value::<super::registers::ConfigurationOptionsRegister0>(f, payload),
206                            RegisterAddress::CBC => write_reg_value::<super::registers::CbcRegister>(f, payload),
207                            RegisterAddress::IDCODE => write_reg_value::<super::registers::IdCodeRegister>(f, payload),
208                            RegisterAddress::COR1 => write_reg_value::<super::registers::ConfigurationOptionsRegister1>(f, payload),
209                            RegisterAddress::WBSTAR => write_reg_value::<super::registers::WarmBootStartAddressRegister>(f, payload),
210                            RegisterAddress::TIMER => write_reg_value::<super::registers::WatchdogTimerRegister>(f, payload),
211                            RegisterAddress::BOOTSTS => write_reg_value::<super::registers::BootHistoryStatusRegister>(f, payload),
212                            RegisterAddress::CTL1 => write_reg_value::<super::registers::ControlRegister1>(f, payload),
213                            RegisterAddress::BSPI => write_reg_value::<super::registers::BpiSpiConfigurationOptionsRegister>(f, payload),
214                            _ => write_payload(f, payload),
215                        }
216                    }
217                }
218            },
219            Packet::Type2 { opcode, ref payload } => {
220                writeln!(f, "[Type2 {}({})", opcode, payload.len())?;
221                write_payload(f, payload)
222            }
223        }
224    }
225}
226
227impl FromBytes for Packet {
228    fn from_bytes(bytes: &mut BufRead) -> Result<Self, Error> {
229        let mut header_bytes = [0u8; 4];
230        bytes.read_exact(&mut header_bytes).context(format!("Unable to read {}::Packet header bytes", module_path!()))?;
231
232        // Assume Type0 to start as it only exposes the packet type field. Once
233        // the actual packet type is known, use that type's header.
234        match Type0Header::unpack(&header_bytes).context(format!("Unexpected packet type: {:#?}", header_bytes))?.packet_type {
235            PacketType::Type0 => Ok(Packet::Type0),
236            PacketType::Type1 => {
237                let header = Type1Header::unpack(&header_bytes)
238                    .context(format!("Failed to unpack 0x{} as {}::Packet::Type1", ::hex::encode(header_bytes), module_path!()))?;
239
240                let mut payload = vec![0u32; *header.word_count as usize];
241                bytes.read_u32_into::<BigEndian>(&mut payload)?;
242
243                Ok(Packet::Type1 {
244                    opcode: header.opcode,
245                    address: header.address,
246                    payload: payload,
247                })
248            },
249            PacketType::Type2 => {
250                let header = Type2Header::unpack(&header_bytes)
251                                        .context(format!("Failed to unpack 0x{} as {}::Packet::Type2", ::hex::encode(header_bytes), module_path!()))?;
252
253                let mut payload = vec![0u32; *header.word_count as usize];
254                bytes.read_u32_into::<BigEndian>(&mut payload)?;
255
256                Ok(Packet::Type2 {
257                    opcode: header.opcode,
258                    payload: payload,
259                })
260            },
261        }
262    }
263}
264
265impl ToBytes for Packet {
266    fn to_bytes(&self, writer: &mut Write) -> Result<(), Error> {
267        match *self {
268            Packet::Type0 => Type0Header{
269                    packet_type: PacketType::Type0,
270                    ..Type0Header::default()
271                }.to_bytes(writer),
272            Packet::Type1 { opcode, address, ref payload } => {
273                if payload.len() > (1usize << 11) - 1 {
274                    return Err(format_err!("Payload too large for Type 1 packet"));
275                }
276
277                Type1Header{
278                    packet_type: PacketType::Type1,
279                    opcode,
280                    address,
281                    word_count: (payload.len() as u16).into(),
282                    ..Type1Header::default()
283                }.to_bytes(writer)?;
284                for word in payload.iter() {
285                    writer.write_u32::<BigEndian>(*word)?
286                }
287                Ok(())
288            },
289            Packet::Type2 { opcode, ref payload } => {
290                if payload.len() > (1usize << 27) - 1 {
291                    return Err(format_err!("Payload too large for Type 2 packet"));
292                }
293
294                Type2Header{
295                    packet_type: PacketType::Type2,
296                    opcode,
297                    word_count: (payload.len() as u32).into(),
298                    ..Type2Header::default()
299                }.to_bytes(writer)?;
300                for word in payload.iter() {
301                    writer.write_u32::<BigEndian>(*word)?
302                }
303                Ok(())
304            }
305        }
306    }
307}
308
309#[derive(Debug)]
310pub struct Bitstream {
311    pub packets: Vec<Packet>,
312}
313
314impl Bitstream {
315    const BIT_WIDTH_DETECTION_PATTERN: [u8; 20] = [
316        0xFF, 0xFF, 0xFF, 0xFF,
317        0x00, 0x00, 0x00, 0xBB,
318        0x11, 0x22, 0x00, 0x44,
319        0xFF, 0xFF, 0xFF, 0xFF,
320        0xFF, 0xFF, 0xFF, 0xFF,
321    ];
322
323    const SYNC_WORD: [u8; 4] = [0xAA, 0x99, 0x55, 0x66];
324
325    /// Returns an iterator over the packets contained in the bitstream.
326    pub fn iter(&self) -> ::std::slice::Iter<Packet> {
327        self.packets.iter()
328    }
329}
330
331impl fmt::Display for Bitstream {
332    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
333        writeln!(f, "Packets: {}", self.packets.len())?;
334        for packet in self.packets.iter() {
335            packet.fmt(f)?;
336        }
337        Ok(())
338    }
339}
340
341impl FromBytes for Bitstream {
342    fn from_bytes(mut bytes: &mut BufRead) -> Result<Self, Error> {
343        if !bytes.skip_until_match(&Self::SYNC_WORD).context("xc7 sync word not found")? {
344            return Err(format_err!("Sync word not found"))
345        }
346
347        let mut packets: Vec<Packet> = Vec::new();
348        loop {
349            if bytes.fill_buf()?.len() == 0 {
350                break;
351            }
352
353            packets.push(Packet::from_bytes(bytes).context("Failed to read packet from bitstream")?);
354        }
355
356        Ok(Bitstream{packets: packets})
357    }
358}
359
360impl ToBytes for Bitstream {
361    fn to_bytes(&self, writer: &mut Write) -> Result<(), Error> {
362        writer.write_all(&Self::BIT_WIDTH_DETECTION_PATTERN).context("I/O error while writing bitstream bit width detection pattern")?;
363        writer.write_all(&Self::SYNC_WORD).context("I/O error while writing bitstream sync word")?;
364        for packet in self.packets.iter() {
365            packet.to_bytes(writer)?
366        }
367        Ok(())
368    }
369}