Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: azonenberg/openfpga
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 52114fe3c82d
Choose a base ref
...
head repository: azonenberg/openfpga
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: b4df70a708ed
Choose a head ref
  • 5 commits
  • 5 files changed
  • 1 contributor

Commits on Jun 15, 2017

  1. Copy the full SHA
    be731db View commit details
  2. Copy the full SHA
    277affc View commit details
  3. Copy the full SHA
    693c800 View commit details
  4. Copy the full SHA
    bc3831e View commit details
  5. Copy the full SHA
    b4df70a View commit details
Showing with 838 additions and 187 deletions.
  1. +175 −69 src/xc2bit/src/bitstream.rs
  2. +4 −0 src/xc2bit/src/fb.rs
  3. +87 −0 src/xc2bit/src/fusemap_physical.rs
  4. +210 −0 src/xc2bit/src/iob.rs
  5. +362 −118 src/xc2bit/src/mc.rs
244 changes: 175 additions & 69 deletions src/xc2bit/src/bitstream.rs
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ use *;
use fb::{read_fb_logical};
use fusemap_logical::{fb_fuse_idx, gck_fuse_idx, gsr_fuse_idx, gts_fuse_idx, global_term_fuse_idx,
total_logical_fuse_count, clock_div_fuse_idx};
use fusemap_physical::{fuse_array_dims};
use fusemap_physical::{fuse_array_dims, gck_fuse_coords, gsr_fuse_coords, gts_fuse_coords, global_term_fuse_coord};
use iob::{read_small_iob_logical, read_large_iob_logical, read_32_extra_ibuf_logical};
use mc::{write_small_mc_to_jed, write_large_mc_to_jed};
use zia::{zia_get_row_width};
@@ -284,6 +284,33 @@ impl XC2GlobalNets {

Ok(())
}

/// Write the crbit representation of the global net settings to the given `fuse_array`.
pub fn to_crbit(&self, device: XC2Device, fuse_array: &mut FuseArray) {
let ((gck0x, gck0y), (gck1x, gck1y), (gck2x, gck2y)) = gck_fuse_coords(device);
fuse_array.set(gck0x, gck0y, self.gck_enable[0]);
fuse_array.set(gck1x, gck1y, self.gck_enable[1]);
fuse_array.set(gck2x, gck2y, self.gck_enable[2]);

let ((gsren_x, gsren_y), (gsrinv_x, gsrinv_y)) = gsr_fuse_coords(device);
fuse_array.set(gsren_x, gsren_y, self.gsr_enable);
fuse_array.set(gsrinv_x, gsrinv_y, self.gsr_invert);

let (((gts0en_x, gts0en_y), (gts0inv_x, gts0inv_y)), ((gts1en_x, gts1en_y), (gts1inv_x, gts1inv_y)),
((gts2en_x, gts2en_y), (gts2inv_x, gts2inv_y)), ((gts3en_x, gts3en_y), (gts3inv_x, gts3inv_y))) =
gts_fuse_coords(device);
fuse_array.set(gts0en_x, gts0en_y, !self.gts_enable[0]);
fuse_array.set(gts0inv_x, gts0inv_y, self.gts_invert[0]);
fuse_array.set(gts1en_x, gts1en_y, !self.gts_enable[1]);
fuse_array.set(gts1inv_x, gts1inv_y, self.gts_invert[1]);
fuse_array.set(gts2en_x, gts2en_y, !self.gts_enable[2]);
fuse_array.set(gts2inv_x, gts2inv_y, self.gts_invert[2]);
fuse_array.set(gts3en_x, gts3en_y, !self.gts_enable[3]);
fuse_array.set(gts3inv_x, gts3inv_y, self.gts_invert[3]);

let (term_x, term_y) = global_term_fuse_coord(device);
fuse_array.set(term_x, term_y, self.global_pu);
}
}

/// Internal function to read the global nets
@@ -600,96 +627,169 @@ impl XC2BitstreamBits {
for i in 0..self.device_type().num_fbs() {
self.get_fb()[i].to_crbit(self.device_type(), i as u32, fuse_array);
}
}

/// Dump a human-readable explanation of the bitstream to the given `writer` object.
pub fn dump_human_readable(&self, writer: &mut Write) -> Result<(), io::Error> {
// IOBs
match self {
&XC2BitstreamBits::XC2C32 {ref global_nets, ref ivoltage, ref ovoltage, ..} => {
// This match is needed because the different sizes have different IOB structures, and fixed-sized arrays
// are gimped enough that returning an array of trait objects is hard.
&XC2BitstreamBits::XC2C32 {ref iobs, ..} |
&XC2BitstreamBits::XC2C32A {ref iobs, ..} => {
for i in 0..self.device_type().num_iobs() {
iobs[i].to_crbit(self.device_type(), i as u32, fuse_array);
}
},
&XC2BitstreamBits::XC2C64 {ref iobs, ..} |
&XC2BitstreamBits::XC2C64A {ref iobs, ..} => {
for i in 0..self.device_type().num_iobs() {
iobs[i].to_crbit(self.device_type(), i as u32, fuse_array);
}
},
&XC2BitstreamBits::XC2C128 {ref iobs, ..} => {
for i in 0..self.device_type().num_iobs() {
iobs[i].to_crbit(self.device_type(), i as u32, fuse_array);
}
},
&XC2BitstreamBits::XC2C256 {ref iobs, ..} => {
for i in 0..self.device_type().num_iobs() {
iobs[i].to_crbit(self.device_type(), i as u32, fuse_array);
}
},
&XC2BitstreamBits::XC2C384 {ref iobs, ..} => {
for i in 0..self.device_type().num_iobs() {
iobs[i].to_crbit(self.device_type(), i as u32, fuse_array);
}
},
&XC2BitstreamBits::XC2C512 {ref iobs, ..} => {
for i in 0..self.device_type().num_iobs() {
iobs[i].to_crbit(self.device_type(), i as u32, fuse_array);
}
},
}

write!(writer, "device type: XC2C32\n")?;
write!(writer, "output voltage range: {}\n", if *ovoltage {"high"} else {"low"})?;
write!(writer, "input voltage range: {}\n", if *ivoltage {"high"} else {"low"})?;
global_nets.dump_human_readable(writer)?;
// Weird extra input-only pin
match self {
&XC2BitstreamBits::XC2C32 {ref inpin, ..} |
&XC2BitstreamBits::XC2C32A {ref inpin, ..} => {
fuse_array.set(131, 24, inpin.schmitt_trigger);
fuse_array.set(132, 24, inpin.termination_enabled);
},
&XC2BitstreamBits::XC2C32A {ref global_nets, ref legacy_ivoltage, ref legacy_ovoltage,
ref ivoltage, ref ovoltage, ..} => {
_ => {}
}

write!(writer, "device type: XC2C32A\n")?;
write!(writer, "legacy output voltage range: {}\n", if *legacy_ovoltage {"high"} else {"low"})?;
write!(writer, "legacy input voltage range: {}\n", if *legacy_ivoltage {"high"} else {"low"})?;
write!(writer, "bank 0 output voltage range: {}\n", if ovoltage[0] {"high"} else {"low"})?;
write!(writer, "bank 1 output voltage range: {}\n", if ovoltage[1] {"high"} else {"low"})?;
write!(writer, "bank 0 input voltage range: {}\n", if ivoltage[0] {"high"} else {"low"})?;
write!(writer, "bank 1 input voltage range: {}\n", if ivoltage[1] {"high"} else {"low"})?;
global_nets.dump_human_readable(writer)?;
// Global nets
self.get_global_nets().to_crbit(self.device_type(), fuse_array);

// Bank voltages and miscellaneous
match self {
&XC2BitstreamBits::XC2C32 {ref ivoltage, ref ovoltage, ..} |
&XC2BitstreamBits::XC2C32A {legacy_ivoltage: ref ivoltage, legacy_ovoltage: ref ovoltage, ..} => {
fuse_array.set(130, 24, !*ovoltage);
fuse_array.set(130, 25, !*ivoltage);
}
&XC2BitstreamBits::XC2C64 {ref ivoltage, ref ovoltage, ..} |
&XC2BitstreamBits::XC2C64A {legacy_ivoltage: ref ivoltage, legacy_ovoltage: ref ovoltage, ..} => {
fuse_array.set(137, 23, !*ovoltage);
fuse_array.set(138, 23, !*ivoltage);
}
&XC2BitstreamBits::XC2C128 {ref ivoltage, ref ovoltage, ref data_gate, ref use_vref, ..} => {
fuse_array.set(371, 67, !*data_gate);

fuse_array.set(8, 67, !ivoltage[0]);
fuse_array.set(9, 67, !ovoltage[0]);
fuse_array.set(368, 67, !ivoltage[1]);
fuse_array.set(369, 67, !ovoltage[1]);

fuse_array.set(10, 67, !*use_vref);
}
&XC2BitstreamBits::XC2C256 {ref ivoltage, ref ovoltage, ref data_gate, ref use_vref, ..} => {
fuse_array.set(518, 23, !*data_gate);

fuse_array.set(175, 23, !ivoltage[0]);
fuse_array.set(176, 23, !ovoltage[0]);
fuse_array.set(515, 23, !ivoltage[1]);
fuse_array.set(516, 23, !ovoltage[1]);

fuse_array.set(177, 23, !*use_vref);
}
&XC2BitstreamBits::XC2C384 {ref ivoltage, ref ovoltage, ref data_gate, ref use_vref, ..} => {
fuse_array.set(932, 17, !*data_gate);

fuse_array.set(936, 17, !ivoltage[0]);
fuse_array.set(937, 17, !ovoltage[0]);
fuse_array.set(1864, 17, !ivoltage[1]);
fuse_array.set(1865, 17, !ovoltage[1]);
fuse_array.set(1, 17, !ivoltage[2]);
fuse_array.set(2, 17, !ovoltage[2]);
fuse_array.set(929, 17, !ivoltage[3]);
fuse_array.set(930, 17, !ovoltage[3]);

fuse_array.set(3, 17, !*use_vref);
}
&XC2BitstreamBits::XC2C512 {ref ivoltage, ref ovoltage, ref data_gate, ref use_vref, ..} => {
fuse_array.set(982, 147, !*data_gate);

fuse_array.set(992, 147, ivoltage[0]);
fuse_array.set(991, 147, ovoltage[0]);
fuse_array.set(1965, 147, ivoltage[1]);
fuse_array.set(1964, 147, ovoltage[1]);
fuse_array.set(3, 147, ivoltage[2]);
fuse_array.set(2, 147, ovoltage[2]);
fuse_array.set(985, 147, ivoltage[3]);
fuse_array.set(984, 147, ovoltage[3]);

fuse_array.set(1, 147, !*use_vref);
}
}

// A-variant bank voltages
match self {
&XC2BitstreamBits::XC2C32A {ref ivoltage, ref ovoltage, ..} => {
fuse_array.set(131, 25, !ivoltage[0]);
fuse_array.set(132, 25, !ovoltage[0]);
fuse_array.set(133, 25, !ivoltage[1]);
fuse_array.set(134, 25, !ovoltage[1]);
},
&XC2BitstreamBits::XC2C64A {ref ivoltage, ref ovoltage, ..} => {
fuse_array.set(139, 23, !ivoltage[0]);
fuse_array.set(140, 23, !ovoltage[0]);
fuse_array.set(141, 23, !ivoltage[1]);
fuse_array.set(142, 23, !ovoltage[1]);
},
&XC2BitstreamBits::XC2C64 {ref global_nets, ref ivoltage, ref ovoltage, ..} => {
_ => {}
}
}

write!(writer, "device type: XC2C64\n")?;
/// Dump a human-readable explanation of the bitstream to the given `writer` object.
pub fn dump_human_readable(&self, writer: &mut Write) -> Result<(), io::Error> {
write!(writer, "device type: {}\n", self.device_type())?;

// Bank voltages
match self {
&XC2BitstreamBits::XC2C32 {ref ivoltage, ref ovoltage, ..} |
&XC2BitstreamBits::XC2C64 {ref ivoltage, ref ovoltage, ..} => {
write!(writer, "output voltage range: {}\n", if *ovoltage {"high"} else {"low"})?;
write!(writer, "input voltage range: {}\n", if *ivoltage {"high"} else {"low"})?;
global_nets.dump_human_readable(writer)?;
},
&XC2BitstreamBits::XC2C64A {ref global_nets, ref legacy_ivoltage, ref legacy_ovoltage,
ref ivoltage, ref ovoltage, ..} => {

write!(writer, "device type: XC2C64A\n")?;
&XC2BitstreamBits::XC2C32A {ref legacy_ivoltage, ref legacy_ovoltage, ref ivoltage, ref ovoltage, ..} |
&XC2BitstreamBits::XC2C64A {ref legacy_ivoltage, ref legacy_ovoltage, ref ivoltage, ref ovoltage, ..} => {
write!(writer, "legacy output voltage range: {}\n", if *legacy_ovoltage {"high"} else {"low"})?;
write!(writer, "legacy input voltage range: {}\n", if *legacy_ivoltage {"high"} else {"low"})?;
write!(writer, "bank 0 output voltage range: {}\n", if ovoltage[0] {"high"} else {"low"})?;
write!(writer, "bank 1 output voltage range: {}\n", if ovoltage[1] {"high"} else {"low"})?;
write!(writer, "bank 0 input voltage range: {}\n", if ivoltage[0] {"high"} else {"low"})?;
write!(writer, "bank 1 input voltage range: {}\n", if ivoltage[1] {"high"} else {"low"})?;
global_nets.dump_human_readable(writer)?;
},
&XC2BitstreamBits::XC2C128 {ref global_nets, ref ivoltage, ref ovoltage, ref clock_div, ref data_gate,
ref use_vref, ..} => {

write!(writer, "device type: XC2C128\n")?;
write!(writer, "bank 0 output voltage range: {}\n", if ovoltage[0] {"high"} else {"low"})?;
write!(writer, "bank 1 output voltage range: {}\n", if ovoltage[1] {"high"} else {"low"})?;
write!(writer, "bank 0 input voltage range: {}\n", if ivoltage[0] {"high"} else {"low"})?;
write!(writer, "bank 1 input voltage range: {}\n", if ivoltage[1] {"high"} else {"low"})?;
write!(writer, "DataGate used: {}\n", if *data_gate {"yes"} else {"no"})?;
write!(writer, "VREF used: {}\n", if *use_vref {"yes"} else {"no"})?;
clock_div.dump_human_readable(writer)?;
global_nets.dump_human_readable(writer)?;
},
&XC2BitstreamBits::XC2C256 {ref global_nets, ref ivoltage, ref ovoltage, ref clock_div, ref data_gate,
ref use_vref, ..} => {

write!(writer, "device type: XC2C256\n")?;
write!(writer, "bank 0 output voltage range: {}\n", if ovoltage[0] {"high"} else {"low"})?;
write!(writer, "bank 1 output voltage range: {}\n", if ovoltage[1] {"high"} else {"low"})?;
write!(writer, "bank 0 input voltage range: {}\n", if ivoltage[0] {"high"} else {"low"})?;
write!(writer, "bank 1 input voltage range: {}\n", if ivoltage[1] {"high"} else {"low"})?;
write!(writer, "DataGate used: {}\n", if *data_gate {"yes"} else {"no"})?;
write!(writer, "VREF used: {}\n", if *use_vref {"yes"} else {"no"})?;
clock_div.dump_human_readable(writer)?;
global_nets.dump_human_readable(writer)?;
},
&XC2BitstreamBits::XC2C384 {ref global_nets, ref ivoltage, ref ovoltage, ref clock_div, ref data_gate,
ref use_vref, ..} => {

write!(writer, "device type: XC2C384\n")?;
&XC2BitstreamBits::XC2C128 {ref ivoltage, ref ovoltage, ref data_gate, ref use_vref, ..} |
&XC2BitstreamBits::XC2C256 {ref ivoltage, ref ovoltage, ref data_gate, ref use_vref, ..} => {
write!(writer, "bank 0 output voltage range: {}\n", if ovoltage[0] {"high"} else {"low"})?;
write!(writer, "bank 1 output voltage range: {}\n", if ovoltage[1] {"high"} else {"low"})?;
write!(writer, "bank 2 output voltage range: {}\n", if ovoltage[2] {"high"} else {"low"})?;
write!(writer, "bank 3 output voltage range: {}\n", if ovoltage[3] {"high"} else {"low"})?;
write!(writer, "bank 0 input voltage range: {}\n", if ivoltage[0] {"high"} else {"low"})?;
write!(writer, "bank 1 input voltage range: {}\n", if ivoltage[1] {"high"} else {"low"})?;
write!(writer, "bank 2 input voltage range: {}\n", if ivoltage[2] {"high"} else {"low"})?;
write!(writer, "bank 3 input voltage range: {}\n", if ivoltage[3] {"high"} else {"low"})?;
write!(writer, "DataGate used: {}\n", if *data_gate {"yes"} else {"no"})?;
write!(writer, "VREF used: {}\n", if *use_vref {"yes"} else {"no"})?;
clock_div.dump_human_readable(writer)?;
global_nets.dump_human_readable(writer)?;
},
&XC2BitstreamBits::XC2C512 {ref global_nets, ref ivoltage, ref ovoltage, ref clock_div, ref data_gate,
ref use_vref, ..} => {

write!(writer, "device type: XC2C512\n")?;
&XC2BitstreamBits::XC2C384 {ref ivoltage, ref ovoltage, ref data_gate, ref use_vref, ..} |
&XC2BitstreamBits::XC2C512 {ref ivoltage, ref ovoltage, ref data_gate, ref use_vref, ..} => {
write!(writer, "bank 0 output voltage range: {}\n", if ovoltage[0] {"high"} else {"low"})?;
write!(writer, "bank 1 output voltage range: {}\n", if ovoltage[1] {"high"} else {"low"})?;
write!(writer, "bank 2 output voltage range: {}\n", if ovoltage[2] {"high"} else {"low"})?;
@@ -700,11 +800,17 @@ impl XC2BitstreamBits {
write!(writer, "bank 3 input voltage range: {}\n", if ivoltage[3] {"high"} else {"low"})?;
write!(writer, "DataGate used: {}\n", if *data_gate {"yes"} else {"no"})?;
write!(writer, "VREF used: {}\n", if *use_vref {"yes"} else {"no"})?;
clock_div.dump_human_readable(writer)?;
global_nets.dump_human_readable(writer)?;
}
}

// Clock divider
if let Some(clock_div) = self.get_clock_div() {
clock_div.dump_human_readable(writer)?;
}

// Global net configuration
self.get_global_nets().dump_human_readable(writer)?;

// IOBs
match self {
// This match is needed because the different sizes have different IOB structures, and fixed-sized arrays
4 changes: 4 additions & 0 deletions src/xc2bit/src/fb.rs
Original file line number Diff line number Diff line change
@@ -180,6 +180,10 @@ impl XC2BitstreamFB {
/// `device` must be the device type this FB was extracted from.
/// `fb` must be the index of this function block.
pub fn to_crbit(&self, device: XC2Device, fb: u32, fuse_array: &mut FuseArray) {
for i in 0..MCS_PER_FB {
self.ffs[i].to_crbit(device, fb, i as u32, fuse_array);
}

// ZIA
let (x, y) = zia_block_loc(device, fb);
for zia_row in 0..INPUTS_PER_ANDTERM {
Loading