1use ::failure::Error;
2use ::std::collections::BTreeMap;
3use ::std::fmt;
4use super::Bitstream;
5use super::DeviceDefinition;
6use super::FrameAddress;
7use super::FromWord;
8use super::Opcode;
9use super::Packet;
10use super::RegisterAddress;
11use super::Word;
12use super::frame_address::BlockType;
13use super::frame_address::DeviceHalf;
14use super::registers;
15
16pub struct Frame([Word; 101]);
17
18impl fmt::Debug for Frame {
19 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
20 writeln!(f, "")?;
21 for (row, payload_line) in self.0.chunks(4).enumerate() {
22 write!(f, "{:04x}: ", row * 4)?;
23 for (col, payload_word) in payload_line.iter().enumerate() {
24 write!(f, "{:08x}{}", payload_word,
25 match col+1 {
26 n if n == payload_line.len() => "",
27 _ => " ",
28 }
29 )?;
30 }
31 writeln!(f, "")?;
32 }
33 Ok(())
34 }
35}
36
37#[derive(Debug)]
38pub struct Configuration {
39 device: DeviceDefinition,
40 frames: BTreeMap<FrameAddress, Frame>,
41}
42
43impl Configuration {
44 pub fn from_bitstream_for_device(bitstream: &Bitstream, device_def: &DeviceDefinition) -> Result<Self, Error>
45 {
46 let mut cmd_reg = registers::CommandRegister::default();
47 let mut far_reg = registers::FrameAddressRegister::default();
48 let mut mask_reg = registers::MaskRegister::default();
49 let mut ctl1_reg = registers::ControlRegister1::default();
50
51 let mut next_frame_write_address = FrameAddress::default();
52 let mut last_register_address = RegisterAddress::default();
53 let mut load_far_on_next_fdri = false;
54 let mut idcode_matched = false;
55 let mut config_frames = BTreeMap::<FrameAddress, Frame>::new();
56 for packet in bitstream.iter() {
57 match packet {
58 Packet::Type1{
59 opcode: _,
60 address,
61 payload: _,
62 } => last_register_address = *address,
63 _ => (),
64 }
65
66 match packet {
67 Packet::Type1{
68 opcode: Opcode::Write,
69 address: RegisterAddress::IDCODE,
70 payload,
71 } => {
72 let idcode = registers::IdCodeRegister::from_word(payload[0])?;
73 idcode_matched = idcode == device_def.idcode;
74 if !idcode_matched {
75 return Err(format_err!("Bitstream has wrong IDCODE expected={:x} actual={:x}", device_def.idcode, idcode));
76 }
77 },
78 Packet::Type1{
79 opcode: Opcode::Write,
80 address: RegisterAddress::CTL1,
81 payload,
82 } => {
83 ctl1_reg = registers::ControlRegister1::from_word(payload[0] & mask_reg.value)?
84 },
85 Packet::Type1{
86 opcode: Opcode::Write,
87 address: RegisterAddress::MASK,
88 payload,
89 } => {
90 mask_reg = registers::MaskRegister::from_word(payload[0])?;
91 },
92 Packet::Type1{
93 opcode: Opcode::Write,
94 address: RegisterAddress::CMD,
95 payload,
96 } => {
97 cmd_reg = registers::CommandRegister::from_word(payload[0])?;
98 if cmd_reg.command == registers::Command::WriteConfigData {
99 load_far_on_next_fdri = true;
100 }
101 },
102 Packet::Type1{
103 opcode: Opcode::Write,
104 address: RegisterAddress::FAR,
105 payload,
106 } => {
107 far_reg = registers::FrameAddressRegister::from_word(payload[0])?;
108
109 if !ctl1_reg.inhibit_cmd_reexec_on_far_write && cmd_reg.command == registers::Command::WriteConfigData {
119 load_far_on_next_fdri = true;
120 }
121 },
122 Packet::Type1{
123 opcode: Opcode::Write,
124 address: RegisterAddress::FDRI,
125 payload,
126 } if idcode_matched => {
127 if load_far_on_next_fdri {
128 next_frame_write_address = far_reg;
129 load_far_on_next_fdri = false;
130 }
131
132 let mut frame_address_iter = device_def.config_mem_layout.iter();
133 let mut frame_address_iter = frame_address_iter.skip_past(&next_frame_write_address);
134
135 let mut frame_chunk_iter = payload.chunks(101);
136 loop {
137 let current_address = next_frame_write_address;
138
139 let frame_chunk = match frame_chunk_iter.next() {
140 Some(x) => x,
141 None => break
142 };
143
144 let mut frame_words = [0u32; 101];
145 frame_words.copy_from_slice(frame_chunk);
146 config_frames.insert(current_address, Frame(frame_words));
147 debug!("Wrote {:p}", current_address);
148
149 next_frame_write_address = match frame_address_iter.next() {
150 Some(x) if !current_address.in_same_row(&x) => {
151 debug!("Skipping row switch padding");
152 frame_chunk_iter.next();
153 frame_chunk_iter.next();
154 x
155 },
156 Some(x) => x,
157 None => {
158 debug!("Skipping row switch padding at end of config mem");
159 frame_chunk_iter.next();
160 frame_chunk_iter.next();
161 current_address
162 },
163 };
164 }
165 },
166 Packet::Type2{
167 opcode: Opcode::Write,
168 payload,
169 } if idcode_matched && last_register_address == RegisterAddress::FDRI => {
170 if load_far_on_next_fdri {
171 next_frame_write_address = far_reg;
172 load_far_on_next_fdri = false;
173 }
174
175 let mut frame_address_iter = device_def.config_mem_layout.iter();
176 let mut frame_address_iter = frame_address_iter.skip_past(&next_frame_write_address);
177
178 let mut frame_chunk_iter = payload.chunks(101);
179 loop {
180 let current_address = next_frame_write_address;
181
182 let frame_chunk = match frame_chunk_iter.next() {
183 Some(x) => x,
184 None => break
185 };
186
187 let mut frame_words = [0u32; 101];
188 frame_words.copy_from_slice(frame_chunk);
189 config_frames.insert(current_address, Frame(frame_words));
190
191 next_frame_write_address = match frame_address_iter.next() {
192 Some(x) if !current_address.in_same_row(&x) => {
193 debug!("Skipping row switch padding");
194 frame_chunk_iter.next();
195 frame_chunk_iter.next();
196 x
197 },
198 Some(x) => x,
199 None => {
200 debug!("Skipping row switch padding at end of config mem");
201 frame_chunk_iter.next();
202 frame_chunk_iter.next();
203 current_address
204 },
205 };
206 }
207
208 next_frame_write_address = frame_address_iter.next().unwrap_or_default();
209 },
210 Packet::Type1{
211 opcode: Opcode::Write,
212 address: RegisterAddress::LOUT,
213 payload,
214 } => {
215 debug!("LOUT {:p}", FrameAddress::from_word(payload[0])?);
216 },
217 _ => continue,
218 }
219 }
220
221 Ok(Configuration{
222 device: device_def.clone(),
223 frames: config_frames,
224 })
225 }
226}
227
228impl Into<Bitstream> for Configuration {
229 fn into(self) -> Bitstream {
230 let mut packets = Vec::new();
231
232 packets.push(Packet::nop());
233
234 packets.push(Packet::from(registers::WatchdogTimerRegister{
235 timer_user_mon: false,
236 timer_cfg_mon: false,
237 timer_val: 0.into(),
238 }));
239 packets.push(Packet::from(registers::WarmBootStartAddressRegister{
240 rs: 0.into(),
241 rs_ts_b: false,
242 start_addr: 0.into(),
243 }));
244 packets.push(Packet::from(registers::CommandRegister{
245 command: registers::Command::Null,
246 }));
247 packets.push(Packet::nop());
248
249 packets.push(Packet::from(registers::CommandRegister{
250 command: registers::Command::ResetCrc,
251 }));
252 packets.push(Packet::nop());
253 packets.push(Packet::nop());
254
255 packets.push(Packet::from(registers::ConfigurationOptionsRegister0{
256 pwrdwn_stat: false,
257 done_pipe: true,
258 drive_done: false,
259 single: false,
260 oscfsel: 0.into(),
261 ssclksrc_jtag: false,
262 ssclksrc_user: false,
263 done_cycle: registers::StartupPhaseKeep::Phase3,
264 match_cycle: registers::StartupPhaseNoWait::NoWait,
265 lock_cycle: registers::StartupPhaseNoWait::NoWait,
266 gts_cycle: registers::StartupPhaseTracksDone::Phase5,
267 gwe_cycle: registers::StartupPhaseTracksDone::Phase6,
268 }));
269 packets.push(Packet::from(registers::ConfigurationOptionsRegister1{
270 persist_deassert_at_desync: false,
271 rb_crc_action: registers::RbCrcAction::Continue,
272 rb_crc_no_pin: false,
273 rb_crc_en: false,
274 bpi_first_read_cycle: 0.into(),
275 bpi_page_size: registers::BpiPageSize::OneBytePerWord,
276 }));
277 packets.push(Packet::from(self.device.idcode));
278 packets.push(Packet::from(registers::CommandRegister{
279 command: registers::Command::Switch,
280 }));
281 packets.push(Packet::nop());
282
283 packets.push(Packet::from(registers::MaskRegister{
284 value: 0x401,
285 }));
286 packets.push(Packet::from(registers::ControlRegister0{
287 efuse_key: false,
288 icap_select:false,
289 over_temp_power_down: false,
290 config_fallback: true,
291 glutmask_b: true,
292 farsrc: false,
293 dec: false,
294 writes_disabled: false,
295 reads_disabled: false,
296 persist: false,
297 gts_usr_b: true,
298 }));
299 packets.push(Packet::from(registers::MaskRegister{
300 value: 0x0,
301 }));
302 packets.push(Packet::from(registers::ControlRegister1{
303 inhibit_cmd_reexec_on_far_write: false,
304 }));
305 packets.append(&mut vec![Packet::nop(); 8]);
306
307 let mut frame_address_iter = None;
311 let mut fdri_payload = Vec::<Word>::new();
312 let mut last_address: Option<FrameAddress> = None;
313 for (addr, frame) in self.frames.iter() {
314 frame_address_iter = match frame_address_iter {
315 None => {
316 packets.push(Packet::from(*addr));
317 packets.push(Packet::from(registers::CommandRegister{
318 command: registers::Command::WriteConfigData,
319 }));
320 packets.push(Packet::nop());
321
322 Some(self.device.config_mem_layout.iter().skip_past(addr))
323 },
324 Some(mut x) => {
325 let next_addr_in_device = x.next().expect("Write past last address in device");
326
327 match last_address {
332 Some(x) if !x.in_same_row(&next_addr_in_device) => {
333 fdri_payload.extend_from_slice(&[0u32; 202]);
335 },
336 _ => (),
337 }
338
339 if next_addr_in_device != *addr {
342 if fdri_payload.len() > 2048 {
347 packets.push(Packet::Type1{
348 opcode: Opcode::Write,
349 address: RegisterAddress::FDRI,
350 payload: fdri_payload,
351 });
352 fdri_payload = Vec::new();
353 } else {
354 packets.push(Packet::Type1{
355 opcode: Opcode::Write,
356 address: RegisterAddress::FDRI,
357 payload: Vec::new(),
358 });
359 packets.push(Packet::Type2{
360 opcode: Opcode::Write,
361 payload: fdri_payload,
362 });
363 fdri_payload = Vec::new();
364 }
365 packets.push(Packet::from(*addr));
366 packets.push(Packet::nop());
367
368 Some(x.skip_past(addr))
369 } else {
370 Some(x)
371 }
372 }
373 };
374 fdri_payload.extend_from_slice(&frame.0);
375 last_address = Some(*addr);
376 }
377
378 if let (Some(mut iter), Some(last)) = (frame_address_iter, last_address) {
379 match iter.next() {
380 Some(ref next) if last.in_same_row(next) => (),
381 _ => {
382 fdri_payload.extend_from_slice(&[0u32; 202]);
384 }
385 }
386
387 }
388
389 if !fdri_payload.is_empty() {
390 if fdri_payload.len() < 2048 {
395 packets.push(Packet::Type1{
396 opcode: Opcode::Write,
397 address: RegisterAddress::FDRI,
398 payload: fdri_payload,
399 });
400 } else {
401 packets.push(Packet::Type1{
402 opcode: Opcode::Write,
403 address: RegisterAddress::FDRI,
404 payload: Vec::new(),
405 });
406 packets.push(Packet::Type2{
407 opcode: Opcode::Write,
408 payload: fdri_payload,
409 });
410 }
411 }
412
413 packets.push(Packet::nop());
414 packets.push(Packet::nop());
415
416 packets.push(Packet::from(registers::CommandRegister{
417 command: registers::Command::PulseGrestore,
418 }));
419 packets.push(Packet::nop());
420
421 packets.push(Packet::from(registers::CommandRegister{
422 command: registers::Command::LastFrame,
423 }));
424 packets.append(&mut vec![Packet::nop(); 100]);
425
426 packets.push(Packet::from(registers::CommandRegister{
427 command: registers::Command::Start,
428 }));
429 packets.push(Packet::nop());
430
431 packets.push(Packet::from(registers::FrameAddressRegister{
432 block_type: BlockType::Unknown,
433 device_half: DeviceHalf::Top,
434 row: 31.into(),
435 column: 0u16.into(),
436 minor: 0.into(),
437 }));
438 packets.push(Packet::from(registers::MaskRegister{
439 value: 0x501,
440 }));
441 packets.push(Packet::from(registers::ControlRegister0{
442 efuse_key: false,
443 icap_select:false,
444 over_temp_power_down: false,
445 config_fallback: true,
446 glutmask_b: true,
447 farsrc: false,
448 dec: false,
449 writes_disabled: false,
450 reads_disabled: false,
451 persist: false,
452 gts_usr_b: true,
453 }));
454 packets.push(Packet::nop());
455 packets.push(Packet::nop());
456
457 packets.push(Packet::from(registers::CommandRegister{
458 command: registers::Command::Desync,
459 }));
460 packets.append(&mut vec![Packet::nop(); 400]);
461
462 Bitstream{ packets }
463 }
464}