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 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 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}