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: 48edca9452d9
Choose a base ref
...
head repository: azonenberg/openfpga
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 81de7f3f455c
Choose a head ref
  • 9 commits
  • 6 files changed
  • 1 contributor

Commits on Jun 10, 2017

  1. Copy the full SHA
    265ca6d View commit details
  2. Copy the full SHA
    0910a3b View commit details
  3. Copy the full SHA
    2675b65 View commit details
  4. Copy the full SHA
    f2c9aab View commit details
  5. Copy the full SHA
    ff3ea77 View commit details
  6. Copy the full SHA
    ded1948 View commit details
  7. Copy the full SHA
    b1a9b1a View commit details
  8. Copy the full SHA
    5c1d4cd View commit details
  9. Copy the full SHA
    81de7f3 View commit details
Showing with 1,996 additions and 10 deletions.
  1. +497 −3 src/xc2bit/src/bitstream.rs
  2. +61 −2 src/xc2bit/src/fb.rs
  3. +223 −1 src/xc2bit/src/iob.rs
  4. +4 −4 src/xc2bit/src/lib.rs
  5. +160 −0 src/xc2bit/src/mc.rs
  6. +1,051 −0 src/xc2bit/src/zia.rs
500 changes: 497 additions & 3 deletions src/xc2bit/src/bitstream.rs

Large diffs are not rendered by default.

63 changes: 61 additions & 2 deletions src/xc2bit/src/fb.rs
Original file line number Diff line number Diff line change
@@ -30,8 +30,8 @@ use std::io::Write;

use *;
use pla::{read_and_term_logical, read_or_term_logical};
use mc::{read_small_ff_logical};
use zia::{read_32_zia_fb_row_logical, read_64_zia_fb_row_logical, zia_get_row_width};
use mc::{read_small_ff_logical, read_large_ff_logical, read_large_buried_ff_logical};
use zia::{read_32_zia_fb_row_logical, read_64_zia_fb_row_logical, read_128_zia_fb_row_logical, zia_get_row_width};

/// Represents a collection of all the parts that make up one function block
#[derive(Copy)]
@@ -189,6 +189,65 @@ pub fn read_small_fb_logical(device: XC2Device, fuses: &[bool], block_idx: usize
})
}

/// Internal function that reads a function block for "large" (>=128-macrocell) devices
pub fn read_large_fb_logical(device: XC2Device, fuses: &[bool], fb: u32, fuse_base: usize)
-> Result<XC2BitstreamFB, &'static str> {

let zia_row_width = zia_get_row_width(device);
let size_of_zia = zia_row_width * INPUTS_PER_ANDTERM;
let size_of_and = INPUTS_PER_ANDTERM * 2 * ANDTERMS_PER_FB;
let size_of_or = ANDTERMS_PER_FB * MCS_PER_FB;

let zia_row_read_function = match device {
XC2Device::XC2C128 => read_128_zia_fb_row_logical,
_ => unreachable!(),
};

let mut and_terms = [XC2PLAAndTerm::default(); ANDTERMS_PER_FB];
let and_block_idx = fuse_base + size_of_zia;
for i in 0..and_terms.len() {
and_terms[i] = read_and_term_logical(fuses, and_block_idx, i);
}

let mut or_terms = [XC2PLAOrTerm::default(); MCS_PER_FB];
let or_block_idx = fuse_base + size_of_zia + size_of_and;
for i in 0..or_terms.len() {
or_terms[i] = read_or_term_logical(fuses, or_block_idx, i);
}

let mut zia_bits = [XC2ZIARowPiece::default(); INPUTS_PER_ANDTERM];
let zia_block_idx = fuse_base;
for i in 0..zia_bits.len() {
let result = zia_row_read_function(fuses, zia_block_idx, i);
if let Err(err) = result {
return Err(err);
}
zia_bits[i] = result.unwrap();
}

let mut ff_bits = [XC2Macrocell::default(); MCS_PER_FB];
let ff_block_idx = fuse_base + size_of_zia + size_of_and + size_of_or;
let mut cur_ff_idx = ff_block_idx;
for i in 0..ff_bits.len() {
if fb_ff_num_to_iob_num(device, fb, i as u32).is_none() {
// Buried
ff_bits[i] = read_large_buried_ff_logical(fuses, cur_ff_idx);
cur_ff_idx += 16;
} else {
// Not buried
ff_bits[i] = read_large_ff_logical(fuses, cur_ff_idx);
cur_ff_idx += 29;
}
}

Ok(XC2BitstreamFB {
and_terms: and_terms,
or_terms: or_terms,
zia_bits: zia_bits,
ffs: ff_bits,
})
}

// TODO: This is the same across all sizes, right?

/// The index of the special CTC product term
224 changes: 223 additions & 1 deletion src/xc2bit/src/iob.rs
Original file line number Diff line number Diff line change
@@ -124,6 +124,97 @@ impl XC2MCSmallIOB {
}
}

/// Input mode selection on larger parts with VREF
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum XC2IOBIbufMode {
/// This input buffer is not using VREF, and it is also not using the Schmitt trigger
NoVrefNoSt,
/// This input buffer is not using VREF, but it is using the Schmitt trigger
NoVrefSt,
/// This input buffer is using VREF (supposedly it always has the Schmitt trigger?)
UsesVref,
/// This input pin is serving as VREF
IsVref,
}

/// Represents an I/O pin on "large" (128 and greater macrocell) devices.
#[derive(Copy, Clone)]
pub struct XC2MCLargeIOB {
/// Mux selection for the ZIA input for this pin
pub zia_mode: XC2IOBZIAMode,
/// Selects the input mode for this pin
pub ibuf_mode: XC2IOBIbufMode,
/// Selects the source used to drive this pin's output (if the output is enabled).
/// `false` selects the XOR gate in the macrocell (combinatorial output), and `true` selects the register output
/// (registered output).
pub obuf_uses_ff: bool,
/// Selects the output mode for this pin
pub obuf_mode: XC2IOBOBufMode,
/// Selects if the global termination (bus hold or pull-up) is enabled on this pin
pub termination_enabled: bool,
/// Selects if fast slew rate is used on this pin
pub slew_is_fast: bool,
/// Whether this pin is making use of the DataGate feature
pub uses_data_gate: bool,
}

impl Default for XC2MCLargeIOB {
/// Returns a "default" I/O pin configuration. The default state is for the output and the input into the ZIA
/// to be disabled.
// FIXME: Do the other defaults come from the particular way I invoked the Xilinx tools??
fn default() -> XC2MCLargeIOB {
XC2MCLargeIOB {
zia_mode: XC2IOBZIAMode::Disabled,
ibuf_mode: XC2IOBIbufMode::NoVrefSt,
obuf_uses_ff: false,
obuf_mode: XC2IOBOBufMode::Disabled,
termination_enabled: true,
slew_is_fast: true,
uses_data_gate: false,
}
}
}

impl XC2MCLargeIOB {
/// Dump a human-readable explanation of the settings for this pin to the given `writer` object.
/// `my_idx` must be the index of this I/O pin in the internal numbering scheme.
pub fn dump_human_readable(&self, device: XC2Device, my_idx: u32, writer: &mut Write) -> Result<(), io::Error> {
write!(writer, "\n")?;
let (fb, ff) = iob_num_to_fb_ff_num(device, my_idx).unwrap();
write!(writer, "I/O configuration for FB{}_{}\n", fb + 1, ff + 1)?;
write!(writer, "output mode: {}\n", match self.obuf_mode {
XC2IOBOBufMode::Disabled => "disabled",
XC2IOBOBufMode::PushPull => "push-pull",
XC2IOBOBufMode::OpenDrain => "open-drain",
XC2IOBOBufMode::TriStateGTS0 => "GTS0-controlled tri-state",
XC2IOBOBufMode::TriStateGTS1 => "GTS1-controlled tri-state",
XC2IOBOBufMode::TriStateGTS2 => "GTS2-controlled tri-state",
XC2IOBOBufMode::TriStateGTS3 => "GTS3-controlled tri-state",
XC2IOBOBufMode::TriStatePTB => "PTB-controlled tri-state",
XC2IOBOBufMode::TriStateCTE => "CTE-controlled tri-state",
XC2IOBOBufMode::CGND => "CGND",
})?;
write!(writer, "input mode: {}\n", match self.ibuf_mode {
XC2IOBIbufMode::NoVrefNoSt => "no VREF, no Schmitt trigger",
XC2IOBIbufMode::NoVrefSt => "no VREF, Schmitt trigger",
XC2IOBIbufMode::UsesVref => "uses VREF (HSTL/SSTL)",
XC2IOBIbufMode::IsVref => "is a VREF pin",
})?;
write!(writer, "output comes from {}\n", if self.obuf_uses_ff {"FF"} else {"XOR gate"})?;
write!(writer, "slew rate: {}\n", if self.slew_is_fast {"fast"} else {"slow"})?;
write!(writer, "ZIA driven from: {}\n", match self.zia_mode {
XC2IOBZIAMode::Disabled => "disabled",
XC2IOBZIAMode::PAD => "input pad",
XC2IOBZIAMode::REG => "register",
})?;
write!(writer, "termination: {}\n", if self.termination_enabled {"yes"} else {"no"})?;
write!(writer, "DataGate used: {}\n", if self.uses_data_gate {"yes"} else {"no"})?;

Ok(())
}
}

/// Represents the one additional special input-only pin on 32-macrocell devices.
pub struct XC2ExtraIBuf {
pub schmitt_trigger: bool,
@@ -170,6 +261,32 @@ pub fn iob_num_to_fb_ff_num(device: XC2Device, iob: u32) -> Option<(u32, u32)> {
} else {
Some((iob / MCS_PER_FB as u32, iob % MCS_PER_FB as u32))
}
},
XC2Device::XC2C128 => {
match iob {
// "Missing" 4 IOBs
0... 5 => Some((0, iob - 0 + 0)),
6...11 => Some((0, iob - 6 + 10)),
12...17 => Some((1, iob - 12 + 0)),
18...23 => Some((1, iob - 18 + 10)),
// "Missing" 3 IOBs
24...30 => Some((2, iob - 24 + 0)),
31...36 => Some((2, iob - 31 + 10)),
37...43 => Some((3, iob - 37 + 0)),
44...49 => Some((3, iob - 44 + 10)),
50...56 => Some((4, iob - 50 + 0)),
57...62 => Some((4, iob - 57 + 10)),
// "Missing" 4 IOBs
63...68 => Some((5, iob - 63 + 0)),
69...74 => Some((5, iob - 69 + 10)),
// "Missing" 3 IOBs
75...81 => Some((6, iob - 75 + 0)),
82...87 => Some((6, iob - 82 + 10)),
// "Missing" 4 IOBs
88...93 => Some((7, iob - 88 + 0)),
94...99 => Some((7, iob - 94 + 10)),
_ => None,
}
}
_ => unreachable!(),
}
@@ -191,7 +308,57 @@ pub fn fb_ff_num_to_iob_num(device: XC2Device, fb: u32, ff: u32) -> Option<u32>
} else {
Some(fb * MCS_PER_FB as u32 + ff)
}
}
},
XC2Device::XC2C128 => {
match fb {
// "Missing" 4 IOBs
0 => match ff {
0...5 => Some(0 + ff),
10...15 => Some(6 + (ff - 10)),
_ => None,
},
1 => match ff {
0...5 => Some(12 + ff),
10...15 => Some(18 + (ff - 10)),
_ => None,
},
// "Missing" 3 IOBs
2 => match ff {
0...6 => Some(24 + ff),
10...15 => Some(31 + (ff - 10)),
_ => None,
},
3 => match ff {
0...6 => Some(37 + ff),
10...15 => Some(44 + (ff - 10)),
_ => None,
},
4 => match ff {
0...6 => Some(50 + ff),
10...15 => Some(57 + (ff - 10)),
_ => None,
},
// "Missing" 4 IOBs
5 => match ff {
0...5 => Some(63 + ff),
10...15 => Some(69 + (ff - 10)),
_ => None,
},
// "Missing" 3 IOBs
6 => match ff {
0...6 => Some(75 + ff),
10...15 => Some(82 + (ff - 10)),
_ => None,
},
// "Missing" 4 IOBs
7 => match ff {
0...5 => Some(88 + ff),
10...15 => Some(94 + (ff - 10)),
_ => None,
},
_ => None,
}
},
_ => unreachable!(),
}
}
@@ -240,6 +407,61 @@ pub fn read_small_iob_logical(fuses: &[bool], block_idx: usize, io_idx: usize) -
})
}

/// Internal function that reads only the IO-related bits from the macrocell configuration
pub fn read_large_iob_logical(fuses: &[bool], fuse_idx: usize) -> Result<XC2MCLargeIOB, &'static str> {
let dg = fuses[fuse_idx + 5];

let inmod = (fuses[fuse_idx + 8],
fuses[fuse_idx + 9]);
let input_mode = match inmod {
(false, false) => XC2IOBIbufMode::NoVrefNoSt,
(false, true) => XC2IOBIbufMode::IsVref,
(true, false) => XC2IOBIbufMode::UsesVref,
(true, true) => XC2IOBIbufMode::NoVrefSt,
};

let inz = (fuses[fuse_idx + 11],
fuses[fuse_idx + 12]);
let input_to_zia = match inz {
(false, false) => XC2IOBZIAMode::PAD,
(true, false) => XC2IOBZIAMode::REG,
(_, true) => XC2IOBZIAMode::Disabled,
};

let oe = (fuses[fuse_idx + 13],
fuses[fuse_idx + 14],
fuses[fuse_idx + 15],
fuses[fuse_idx + 16]);
let output_mode = match oe {
(false, false, false, false) => XC2IOBOBufMode::PushPull,
(false, false, false, true) => XC2IOBOBufMode::OpenDrain,
(false, false, true, false) => XC2IOBOBufMode::TriStateGTS1,
(false, true, false, false) => XC2IOBOBufMode::TriStatePTB,
(false, true, true, false) => XC2IOBOBufMode::TriStateGTS3,
(true, false, false, false) => XC2IOBOBufMode::TriStateCTE,
(true, false, true, false) => XC2IOBOBufMode::TriStateGTS2,
(true, true, false, false) => XC2IOBOBufMode::TriStateGTS0,
(true, true, true, false) => XC2IOBOBufMode::CGND,
(true, true, true, true) => XC2IOBOBufMode::Disabled,
_ => return Err("unknown Oe mode used"),
};

let regcom = fuses[fuse_idx + 20];

let slw = fuses[fuse_idx + 25];
let tm = fuses[fuse_idx + 26];

Ok(XC2MCLargeIOB {
zia_mode: input_to_zia,
ibuf_mode: input_mode,
obuf_uses_ff: !regcom,
obuf_mode: output_mode,
termination_enabled: tm,
slew_is_fast: !slw,
uses_data_gate: dg,
})
}

/// Internal function that reads only the input-only pin configuration
pub fn read_32_extra_ibuf_logical(fuses: &[bool]) -> XC2ExtraIBuf {
let st = fuses[12272];
8 changes: 4 additions & 4 deletions src/xc2bit/src/lib.rs
Original file line number Diff line number Diff line change
@@ -53,14 +53,14 @@ pub const ANDTERMS_PER_FB: usize = 56;
pub const MCS_PER_FB: usize = 16;

mod bitstream;
pub use bitstream::{XC2Bitstream, XC2BitstreamBits, XC2GlobalNets, process_jed};
pub use bitstream::{XC2Bitstream, XC2BitstreamBits, XC2GlobalNets, XC2ClockDivRatio, XC2ClockDiv, process_jed};

mod fb;
pub use fb::{XC2BitstreamFB, CTC, CTR, CTS, CTE, get_pta, get_ptb, get_ptc};

mod iob;
pub use iob::{XC2MCSmallIOB, XC2IOBZIAMode, XC2IOBOBufMode, XC2ExtraIBuf, iob_num_to_fb_ff_num,
fb_ff_num_to_iob_num};
pub use iob::{XC2MCSmallIOB, XC2IOBZIAMode, XC2IOBOBufMode, XC2ExtraIBuf, XC2IOBIbufMode, XC2MCLargeIOB,
iob_num_to_fb_ff_num, fb_ff_num_to_iob_num};

mod mc;
pub use mc::{XC2Macrocell, XC2MCRegClkSrc, XC2MCRegResetSrc, XC2MCRegSetSrc, XC2MCRegMode, XC2MCFeedbackMode,
@@ -73,7 +73,7 @@ mod pla;
pub use pla::{XC2PLAAndTerm, XC2PLAOrTerm};

mod zia;
pub use zia::{XC2ZIARowPiece, XC2ZIAInput, ZIA_MAP_32, ZIA_MAP_64};
pub use zia::{XC2ZIARowPiece, XC2ZIAInput, ZIA_MAP_32, ZIA_MAP_64, ZIA_MAP_128};

mod jed;
pub use jed::{read_jed};
160 changes: 160 additions & 0 deletions src/xc2bit/src/mc.rs
Original file line number Diff line number Diff line change
@@ -279,3 +279,163 @@ pub fn read_small_ff_logical(fuses: &[bool], block_idx: usize, ff_idx: usize) ->
xor_mode: xormode,
}
}

/// Internal function that reads only the macrocell-related bits from the macrcocell configuration
pub fn read_large_ff_logical(fuses: &[bool], fuse_idx: usize) -> XC2Macrocell {
let aclk = fuses[fuse_idx + 0];

let clk = (fuses[fuse_idx + 1],
fuses[fuse_idx + 2]);
let clk_src = match clk {
(false, false) => XC2MCRegClkSrc::GCK0,
(false, true) => XC2MCRegClkSrc::GCK1,
(true, false) => XC2MCRegClkSrc::GCK2,
(true, true) => match aclk {
true => XC2MCRegClkSrc::CTC,
false => XC2MCRegClkSrc::PTC,
},
};

let clkfreq = fuses[fuse_idx + 3];
let clkop = fuses[fuse_idx + 4];

let fb = (fuses[fuse_idx + 6],
fuses[fuse_idx + 7]);
let fb_mode = match fb {
(false, false) => XC2MCFeedbackMode::COMB,
(true, false) => XC2MCFeedbackMode::REG,
(_, true) => XC2MCFeedbackMode::Disabled,
};

let inreg = fuses[fuse_idx + 10];

let p = (fuses[fuse_idx + 17],
fuses[fuse_idx + 18]);
let set_mode = match p {
(false, false) => XC2MCRegSetSrc::PTA,
(false, true) => XC2MCRegSetSrc::GSR,
(true, false) => XC2MCRegSetSrc::CTS,
(true, true) => XC2MCRegSetSrc::Disabled,
};

let pu = fuses[fuse_idx + 19];

let regmod = (fuses[fuse_idx + 21],
fuses[fuse_idx + 22]);
let reg_mode = match regmod {
(false, false) => XC2MCRegMode::DFF,
(false, true) => XC2MCRegMode::LATCH,
(true, false) => XC2MCRegMode::TFF,
(true, true) => XC2MCRegMode::DFFCE,
};

let r = (fuses[fuse_idx + 23],
fuses[fuse_idx + 24]);
let reset_mode = match r {
(false, false) => XC2MCRegResetSrc::PTA,
(false, true) => XC2MCRegResetSrc::GSR,
(true, false) => XC2MCRegResetSrc::CTR,
(true, true) => XC2MCRegResetSrc::Disabled,
};

let xorin = (fuses[fuse_idx + 27],
fuses[fuse_idx + 28]);
let xormode = match xorin {
(false, false) => XC2MCXorMode::ZERO,
(false, true) => XC2MCXorMode::PTCB,
(true, false) => XC2MCXorMode::PTC,
(true, true) => XC2MCXorMode::ONE,
};

XC2Macrocell {
clk_src: clk_src,
clk_invert_pol: clkop,
is_ddr: clkfreq,
r_src: reset_mode,
s_src: set_mode,
init_state: !pu,
reg_mode: reg_mode,
fb_mode: fb_mode,
ff_in_ibuf: !inreg,
xor_mode: xormode,
}
}

/// Internal function that reads only the macrocell-related bits from the macrcocell configuration
pub fn read_large_buried_ff_logical(fuses: &[bool], fuse_idx: usize) -> XC2Macrocell {
let aclk = fuses[fuse_idx + 0];

let clk = (fuses[fuse_idx + 1],
fuses[fuse_idx + 2]);
let clk_src = match clk {
(false, false) => XC2MCRegClkSrc::GCK0,
(false, true) => XC2MCRegClkSrc::GCK1,
(true, false) => XC2MCRegClkSrc::GCK2,
(true, true) => match aclk {
true => XC2MCRegClkSrc::CTC,
false => XC2MCRegClkSrc::PTC,
},
};

let clkfreq = fuses[fuse_idx + 3];
let clkop = fuses[fuse_idx + 4];

let fb = (fuses[fuse_idx + 5],
fuses[fuse_idx + 6]);
let fb_mode = match fb {
(false, false) => XC2MCFeedbackMode::COMB,
(true, false) => XC2MCFeedbackMode::REG,
(_, true) => XC2MCFeedbackMode::Disabled,
};

let p = (fuses[fuse_idx + 7],
fuses[fuse_idx + 8]);
let set_mode = match p {
(false, false) => XC2MCRegSetSrc::PTA,
(false, true) => XC2MCRegSetSrc::GSR,
(true, false) => XC2MCRegSetSrc::CTS,
(true, true) => XC2MCRegSetSrc::Disabled,
};

let pu = fuses[fuse_idx + 9];

let regmod = (fuses[fuse_idx + 10],
fuses[fuse_idx + 11]);
let reg_mode = match regmod {
(false, false) => XC2MCRegMode::DFF,
(false, true) => XC2MCRegMode::LATCH,
(true, false) => XC2MCRegMode::TFF,
(true, true) => XC2MCRegMode::DFFCE,
};

let r = (fuses[fuse_idx + 12],
fuses[fuse_idx + 13]);
let reset_mode = match r {
(false, false) => XC2MCRegResetSrc::PTA,
(false, true) => XC2MCRegResetSrc::GSR,
(true, false) => XC2MCRegResetSrc::CTR,
(true, true) => XC2MCRegResetSrc::Disabled,
};

let xorin = (fuses[fuse_idx + 14],
fuses[fuse_idx + 15]);
let xormode = match xorin {
(false, false) => XC2MCXorMode::ZERO,
(false, true) => XC2MCXorMode::PTCB,
(true, false) => XC2MCXorMode::PTC,
(true, true) => XC2MCXorMode::ONE,
};

XC2Macrocell {
clk_src: clk_src,
clk_invert_pol: clkop,
is_ddr: clkfreq,
r_src: reset_mode,
s_src: set_mode,
init_state: !pu,
reg_mode: reg_mode,
fb_mode: fb_mode,
ff_in_ibuf: false,
xor_mode: xormode,
}
}
1,051 changes: 1,051 additions & 0 deletions src/xc2bit/src/zia.rs

Large diffs are not rendered by default.