Skip to content

Commit

Permalink
xc2bit: Initial error handling refactor
Browse files Browse the repository at this point in the history
Make error types be enums rather than strings
ArcaneNibble committed Jun 22, 2017
1 parent b08ddd9 commit 8f6b576
Showing 6 changed files with 91 additions and 109 deletions.
58 changes: 29 additions & 29 deletions src/xc2bit/src/bitstream.rs
Original file line number Diff line number Diff line change
@@ -86,10 +86,10 @@ impl XC2Bitstream {

/// Construct a new blank bitstream of the given part
pub fn blank_bitstream(device: XC2Device, speed_grade: XC2Speed, package: XC2Package)
-> Result<XC2Bitstream, &'static str> {
-> Result<XC2Bitstream, XC2BitError> {

if !is_valid_part_combination(device, speed_grade, package) {
return Err("requested device/speed/package is not a legal combination")
return Err(XC2BitError::BadDeviceName(format!("{}-{}-{}", device, speed_grade, package)));
}

match device {
@@ -1158,7 +1158,7 @@ impl XC2BitstreamBits {

/// Common logic for reading bitstreams on "small" devices
pub fn read_bitstream_logical_common_small(fuses: &[bool], device: XC2Device,
fb: &mut [XC2BitstreamFB], iobs: &mut [XC2MCSmallIOB]) -> Result<(), &'static str> {
fb: &mut [XC2BitstreamFB], iobs: &mut [XC2MCSmallIOB]) -> Result<(), XC2BitError> {

for i in 0..fb.len() {
let base_fuse = fb_fuse_idx(device, i as u32);
@@ -1183,7 +1183,7 @@ pub fn read_bitstream_logical_common_small(fuses: &[bool], device: XC2Device,

/// Common logic for reading bitstreams on "large" devices
pub fn read_bitstream_logical_common_large(fuses: &[bool], device: XC2Device,
fb: &mut [XC2BitstreamFB], iobs: &mut [XC2MCLargeIOB]) -> Result<(), &'static str> {
fb: &mut [XC2BitstreamFB], iobs: &mut [XC2MCLargeIOB]) -> Result<(), XC2BitError> {

for i in 0..fb.len() {
let base_fuse = fb_fuse_idx(device, i as u32);
@@ -1212,7 +1212,7 @@ pub fn read_bitstream_logical_common_large(fuses: &[bool], device: XC2Device,
Ok(())
}
/// Internal function for parsing an XC2C32 bitstream
pub fn read_32_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_32_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 2];
let mut iobs = [XC2MCSmallIOB::default(); 32];

@@ -1233,7 +1233,7 @@ pub fn read_32_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'s
}

/// Internal function for parsing an XC2C32A bitstream
pub fn read_32a_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_32a_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 2];
let mut iobs = [XC2MCSmallIOB::default(); 32];

@@ -1262,7 +1262,7 @@ pub fn read_32a_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'
}

/// Internal function for parsing an XC2C64 bitstream
pub fn read_64_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_64_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 4];
let mut iobs = [XC2MCSmallIOB::default(); 64];

@@ -1280,7 +1280,7 @@ pub fn read_64_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'s
}

/// Internal function for parsing an XC2C64A bitstream
pub fn read_64a_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_64a_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 4];
let mut iobs = [XC2MCSmallIOB::default(); 64];

@@ -1306,7 +1306,7 @@ pub fn read_64a_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'
}

/// Internal function for parsing an XC2C128 bitstream
pub fn read_128_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_128_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 8];
let mut iobs = [XC2MCLargeIOB::default(); 100];

@@ -1333,7 +1333,7 @@ pub fn read_128_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'
}

/// Internal function for parsing an XC2C256 bitstream
pub fn read_256_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_256_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 16];
let mut iobs = [XC2MCLargeIOB::default(); 184];

@@ -1360,7 +1360,7 @@ pub fn read_256_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'
}

/// Internal function for parsing an XC2C384 bitstream
pub fn read_384_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_384_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 24];
let mut iobs = [XC2MCLargeIOB::default(); 240];

@@ -1391,7 +1391,7 @@ pub fn read_384_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'
}

/// Internal function for parsing an XC2C512 bitstream
pub fn read_512_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_512_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 32];
let mut iobs = [XC2MCLargeIOB::default(); 270];

@@ -1423,7 +1423,7 @@ pub fn read_512_bitstream_logical(fuses: &[bool]) -> Result<XC2BitstreamBits, &'

/// Common logic for reading bitstreams on "small" devices
pub fn read_bitstream_physical_common_small(fuse_array: &FuseArray, device: XC2Device,
fb: &mut [XC2BitstreamFB], iobs: &mut [XC2MCSmallIOB]) -> Result<(), &'static str> {
fb: &mut [XC2BitstreamFB], iobs: &mut [XC2MCSmallIOB]) -> Result<(), XC2BitError> {

for i in 0..fb.len() {
fb[i] = XC2BitstreamFB::from_crbit(device, i as u32, fuse_array)?;
@@ -1438,7 +1438,7 @@ pub fn read_bitstream_physical_common_small(fuse_array: &FuseArray, device: XC2D

/// Common logic for reading bitstreams on "large" devices
pub fn read_bitstream_physical_common_large(fuse_array: &FuseArray, device: XC2Device,
fb: &mut [XC2BitstreamFB], iobs: &mut [XC2MCLargeIOB]) -> Result<(), &'static str> {
fb: &mut [XC2BitstreamFB], iobs: &mut [XC2MCLargeIOB]) -> Result<(), XC2BitError> {

for i in 0..fb.len() {
fb[i] = XC2BitstreamFB::from_crbit(device, i as u32, fuse_array)?;
@@ -1452,7 +1452,7 @@ pub fn read_bitstream_physical_common_large(fuse_array: &FuseArray, device: XC2D
}

/// Internal function for parsing an XC2C32 bitstream
pub fn read_32_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_32_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 2];
let mut iobs = [XC2MCSmallIOB::default(); 32];

@@ -1473,7 +1473,7 @@ pub fn read_32_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2Bitstream
}

/// Internal function for parsing an XC2C32A bitstream
pub fn read_32a_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_32a_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 2];
let mut iobs = [XC2MCSmallIOB::default(); 32];

@@ -1502,7 +1502,7 @@ pub fn read_32a_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2Bitstrea
}

/// Internal function for parsing an XC2C64 bitstream
pub fn read_64_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_64_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 4];
let mut iobs = [XC2MCSmallIOB::default(); 64];

@@ -1520,7 +1520,7 @@ pub fn read_64_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2Bitstream
}

/// Internal function for parsing an XC2C64A bitstream
pub fn read_64a_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_64a_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 4];
let mut iobs = [XC2MCSmallIOB::default(); 64];

@@ -1546,7 +1546,7 @@ pub fn read_64a_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2Bitstrea
}

/// Internal function for parsing an XC2C128 bitstream
pub fn read_128_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_128_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 8];
let mut iobs = [XC2MCLargeIOB::default(); 100];

@@ -1573,7 +1573,7 @@ pub fn read_128_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2Bitstrea
}

/// Internal function for parsing an XC2C256 bitstream
pub fn read_256_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_256_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 16];
let mut iobs = [XC2MCLargeIOB::default(); 184];

@@ -1600,7 +1600,7 @@ pub fn read_256_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2Bitstrea
}

/// Internal function for parsing an XC2C384 bitstream
pub fn read_384_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_384_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 24];
let mut iobs = [XC2MCLargeIOB::default(); 240];

@@ -1631,7 +1631,7 @@ pub fn read_384_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2Bitstrea
}

/// Internal function for parsing an XC2C512 bitstream
pub fn read_512_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, &'static str> {
pub fn read_512_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2BitstreamBits, XC2BitError> {
let mut fb = [XC2BitstreamFB::default(); 32];
let mut iobs = [XC2MCLargeIOB::default(); 270];

@@ -1662,16 +1662,16 @@ pub fn read_512_bitstream_physical(fuse_array: &FuseArray) -> Result<XC2Bitstrea
}

/// Processes a fuse array into a bitstream object
pub fn process_jed(fuses: &[bool], device: &str) -> Result<XC2Bitstream, &'static str> {
pub fn process_jed(fuses: &[bool], device: &str) -> Result<XC2Bitstream, XC2BitError> {
let device_combination = parse_part_name_string(device);
if device_combination.is_none() {
return Err("malformed device name");
return Err(XC2BitError::BadDeviceName(device.to_owned()));
}

let (part, spd, pkg) = device_combination.unwrap();

if fuses.len() != total_logical_fuse_count(part) {
return Err("wrong number of fuses");
return Err(XC2BitError::WrongFuseCount);
}

match part {
@@ -1743,21 +1743,21 @@ pub fn process_jed(fuses: &[bool], device: &str) -> Result<XC2Bitstream, &'stati
}

/// Processes a fuse array (in physical addressing) into a bitstream object
pub fn process_crbit(fuse_array: &FuseArray) -> Result<XC2Bitstream, &'static str> {
pub fn process_crbit(fuse_array: &FuseArray) -> Result<XC2Bitstream, XC2BitError> {
// FIXME: Can we guess the device type from the dimensions?
if fuse_array.dev_name_str.is_none() {
return Err("unspecified device name");
return Err(XC2BitError::BadDeviceName(String::from("")));
}

let device_combination = parse_part_name_string(fuse_array.dev_name_str.as_ref().unwrap());
if device_combination.is_none() {
return Err("malformed device name");
return Err(XC2BitError::BadDeviceName(fuse_array.dev_name_str.as_ref().unwrap().to_owned()));
}

let (part, spd, pkg) = device_combination.unwrap();

if fuse_array.dim() != fuse_array_dims(part) {
return Err("wrong number of fuses");
return Err(XC2BitError::WrongFuseCount);
}


4 changes: 2 additions & 2 deletions src/xc2bit/src/fb.rs
Original file line number Diff line number Diff line change
@@ -359,7 +359,7 @@ impl XC2BitstreamFB {
/// Reads the crbit representation of the settings for this FB from the given `fuse_array`.
/// `device` must be the device type this FB was extracted from.
/// `fb` must be the index of this function block.
pub fn from_crbit(device: XC2Device, fb: u32, fuse_array: &FuseArray) -> Result<XC2BitstreamFB, &'static str> {
pub fn from_crbit(device: XC2Device, fb: u32, fuse_array: &FuseArray) -> Result<XC2BitstreamFB, XC2BitError> {
// ZIA
let mut zia_bits = [XC2ZIARowPiece::default(); INPUTS_PER_ANDTERM];
let (x, y) = zia_block_loc(device, fb);
@@ -619,7 +619,7 @@ impl XC2BitstreamFB {

/// Internal function that reads a function block
pub fn read_fb_logical(device: XC2Device, fuses: &[bool], fb: u32, fuse_base: usize)
-> Result<XC2BitstreamFB, &'static str> {
-> Result<XC2BitstreamFB, XC2BitError> {

let zia_row_width = zia_get_row_width(device);
let size_of_zia = zia_row_width * INPUTS_PER_ANDTERM;
12 changes: 6 additions & 6 deletions src/xc2bit/src/iob.rs
Original file line number Diff line number Diff line change
@@ -95,7 +95,7 @@ impl XC2IOBOBufMode {
}

/// decodes the Oe bits
pub fn decode(oe: (bool, bool, bool, bool)) -> Result<Self, &'static str> {
pub fn decode(oe: (bool, bool, bool, bool)) -> Result<Self, XC2BitError> {
Ok(match oe {
(false, false, false, false) => XC2IOBOBufMode::PushPull,
(false, false, false, true) => XC2IOBOBufMode::OpenDrain,
@@ -107,7 +107,7 @@ impl XC2IOBOBufMode {
(true, true, false, false) => XC2IOBOBufMode::TriStateGTS0,
(true, true, true, false) => XC2IOBOBufMode::CGND,
(true, true, true, true) => XC2IOBOBufMode::Disabled,
_ => return Err("unknown Oe mode used"),
_ => return Err(XC2BitError::UnsupportedOeConfiguration(oe)),
})
}
}
@@ -255,7 +255,7 @@ impl XC2MCSmallIOB {
/// Read the crbit representation of the settings for this IO pin from the given `fuse_array`.
/// `device` must be the device type this FB was extracted from.
/// `iob` must be the index of this IO pin.
pub fn from_crbit(device: XC2Device, iob: u32, fuse_array: &FuseArray) -> Result<XC2MCSmallIOB, &'static str> {
pub fn from_crbit(device: XC2Device, iob: u32, fuse_array: &FuseArray) -> Result<XC2MCSmallIOB, XC2BitError> {
let (fb, mc) = iob_num_to_fb_ff_num(device, iob).unwrap();
let (x, y, mirror) = mc_block_loc(device, fb);
// direction
@@ -536,7 +536,7 @@ impl XC2MCLargeIOB {
/// Read the crbit representation of the settings for this IO pin from the given `fuse_array`.
/// `device` must be the device type this FB was extracted from.
/// `iob` must be the index of this IO pin.
pub fn from_crbit(device: XC2Device, iob: u32, fuse_array: &FuseArray) -> Result<XC2MCLargeIOB, &'static str> {
pub fn from_crbit(device: XC2Device, iob: u32, fuse_array: &FuseArray) -> Result<XC2MCLargeIOB, XC2BitError> {
let (fb, mc) = iob_num_to_fb_ff_num(device, iob).unwrap();
let (x, y, mirror) = mc_block_loc(device, fb);
// direction
@@ -1215,7 +1215,7 @@ pub fn fb_ff_num_to_iob_num(device: XC2Device, fb: u32, ff: u32) -> Option<u32>
}

/// Internal function that reads only the IO-related bits from the macrocell configuration
pub fn read_small_iob_logical(fuses: &[bool], fuse_idx: usize) -> Result<XC2MCSmallIOB, &'static str> {
pub fn read_small_iob_logical(fuses: &[bool], fuse_idx: usize) -> Result<XC2MCSmallIOB, XC2BitError> {
let inz = (fuses[fuse_idx + 11],
fuses[fuse_idx + 12]);
let input_to_zia = XC2IOBZIAMode::decode(inz);
@@ -1243,7 +1243,7 @@ pub fn read_small_iob_logical(fuses: &[bool], fuse_idx: usize) -> Result<XC2MCSm
}

/// 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> {
pub fn read_large_iob_logical(fuses: &[bool], fuse_idx: usize) -> Result<XC2MCLargeIOB, XC2BitError> {
let dg = fuses[fuse_idx + 5];

let inmod = (fuses[fuse_idx + 8],
87 changes: 33 additions & 54 deletions src/xc2bit/src/jed.rs
Original file line number Diff line number Diff line change
@@ -25,6 +25,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

//! Xilinx JED file I/O
use *;

use std::num::Wrapping;
use std::str;

@@ -39,7 +41,7 @@ const STX: u8 = 0x02;
const ETX: u8 = 0x03;

/// Reads .jed file and outputs the fuses as an array of booleans and optional device name
pub fn read_jed(in_bytes: &[u8]) -> Result<(Vec<bool>, Option<String>), &'static str> {
pub fn read_jed(in_bytes: &[u8]) -> Result<(Vec<bool>, Option<String>), JedParserError> {
let mut fuse_csum = Wrapping(0u16);
let mut fuse_expected_csum = None;
let mut file_csum = Wrapping(0u16);
@@ -54,7 +56,7 @@ pub fn read_jed(in_bytes: &[u8]) -> Result<(Vec<bool>, Option<String>), &'static
while in_bytes[jed_stx] != STX {
jed_stx += 1;
if jed_stx >= in_bytes.len() {
return Err("STX not found");
return Err(JedParserError::MissingSTX);
}
}

@@ -64,36 +66,25 @@ pub fn read_jed(in_bytes: &[u8]) -> Result<(Vec<bool>, Option<String>), &'static
file_csum += Wrapping(in_bytes[jed_etx] as u16);
jed_etx += 1;
if jed_etx >= in_bytes.len() {
return Err("ETX not found");
return Err(JedParserError::MissingETX);
}
}
// Add the ETX to the checksum too
file_csum += Wrapping(ETX as u16);

// Check the checksum
if jed_etx + 4 >= in_bytes.len() {
return Err("unexpected end of file - checksum");
return Err(JedParserError::UnexpectedEnd);
}
let csum_expected = &in_bytes[jed_etx + 1..jed_etx + 5];
let csum_expected = str::from_utf8(csum_expected);
if csum_expected.is_err() {
return Err("invalid character encountered - file checksum");
}
let csum_expected = u16::from_str_radix(csum_expected.unwrap(), 16);
if csum_expected.is_err() {
return Err("invalid character encountered - file checksum");
}
let csum_expected = csum_expected.unwrap();
let csum_expected = str::from_utf8(csum_expected)?;
let csum_expected = u16::from_str_radix(csum_expected, 16)?;
if csum_expected != 0 && csum_expected != file_csum.0 {
return Err("invalid file checksum");
return Err(JedParserError::BadFileChecksum);
}

// Make a str object out of the body
let jed_body = str::from_utf8(&in_bytes[jed_stx + 1..jed_etx]);
if jed_body.is_err() {
return Err("invalid character encountered - non-ASCII");
}
let jed_body = jed_body.unwrap();
let jed_body = str::from_utf8(&in_bytes[jed_stx + 1..jed_etx])?;

// Ready to parse each line
for l in jed_body.split('*') {
@@ -113,7 +104,7 @@ pub fn read_jed(in_bytes: &[u8]) -> Result<(Vec<bool>, Option<String>), &'static
default_fuse = match default_state_str {
"0" => Ternary::Zero,
"1" => Ternary::One,
_ => return Err("invalid character encountered - F field")
_ => return Err(JedParserError::InvalidCharacter)
}
},
'N' => {
@@ -127,11 +118,7 @@ pub fn read_jed(in_bytes: &[u8]) -> Result<(Vec<bool>, Option<String>), &'static
// Look for QF
if l.starts_with("QF") {
let (_, num_fuses_str) = l.split_at(2);
let num_fuses_maybe = u32::from_str_radix(num_fuses_str, 10);
if num_fuses_maybe.is_err() {
return Err("invalid character encountered - QF field");
}
num_fuses = num_fuses_maybe.unwrap();
num_fuses = u32::from_str_radix(num_fuses_str, 10)?;
fuses_ternary.reserve(num_fuses as usize);
for _ in 0..num_fuses {
fuses_ternary.push(Ternary::Undef);
@@ -141,57 +128,49 @@ pub fn read_jed(in_bytes: &[u8]) -> Result<(Vec<bool>, Option<String>), &'static
'L' => {
// A set of fuses
if num_fuses == 0 {
return Err("missing QF field");
return Err(JedParserError::MissingQF);
}

let mut fuse_field_splitter = l.splitn(2, |c| c == ' ' || c == '\r' || c == '\n');
let fuse_idx_str = fuse_field_splitter.next();
let (_, fuse_idx_str) = fuse_idx_str.unwrap().split_at(1);
let fuse_idx_maybe = u32::from_str_radix(fuse_idx_str, 10);
if fuse_idx_maybe.is_err() {
return Err("invalid character encountered - fuse number");
}
let mut fuse_idx = fuse_idx_maybe.unwrap();
let mut fuse_idx = u32::from_str_radix(fuse_idx_str, 10)?;

let fuse_bits_part = fuse_field_splitter.next();
if fuse_bits_part.is_none() {
return Err("malformed L field");
return Err(JedParserError::InvalidFuseIndex);
}
let fuse_bits_part = fuse_bits_part.unwrap();
for fuse in fuse_bits_part.chars() {
match fuse {
'0' => {
if fuse_idx >= num_fuses {
return Err("invalid fuse index out of range");
return Err(JedParserError::InvalidFuseIndex);
}
fuses_ternary[fuse_idx as usize] = Ternary::Zero;
fuse_idx += 1;
},
'1' => {
if fuse_idx >= num_fuses {
return Err("invalid fuse index out of range");
return Err(JedParserError::InvalidFuseIndex);
}
fuses_ternary[fuse_idx as usize] = Ternary::One;
fuse_idx += 1;
},
' ' | '\r' | '\n' => {}, // Do nothing
_ => return Err("invalid character encountered - fuse value"),
_ => return Err(JedParserError::InvalidCharacter),
}
}
},
'C' => {
// Checksum
let (_, csum_str) = l.split_at(1);
if csum_str.len() != 4 {
return Err("malformed fuse checksum");
}
let csum_maybe = u16::from_str_radix(csum_str, 16);
if csum_maybe.is_err() {
return Err("invalid character encountered - C");
return Err(JedParserError::BadFuseChecksum);
}
fuse_expected_csum = Some(csum_maybe.unwrap());
fuse_expected_csum = Some(u16::from_str_radix(csum_str, 16)?);
}
_ => return Err("unrecognized field"),
_ => return Err(JedParserError::UnrecognizedField),
}
}

@@ -200,7 +179,7 @@ pub fn read_jed(in_bytes: &[u8]) -> Result<(Vec<bool>, Option<String>), &'static
if *x == Ternary::Undef {
// There cannot be undefined fuses if there isn't an F field
if default_fuse == Ternary::Undef {
return Err("missing F field")
return Err(JedParserError::MissingF)
}

*x = default_fuse;
@@ -224,7 +203,7 @@ pub fn read_jed(in_bytes: &[u8]) -> Result<(Vec<bool>, Option<String>), &'static
}

if fuse_expected_csum != fuse_csum.0 {
return Err("invalid fuse checksum");
return Err(JedParserError::BadFuseChecksum);
}
}

@@ -239,44 +218,44 @@ mod tests {
fn read_no_stx() {
let ret = read_jed(b"asdf");

assert_eq!(ret, Err("STX not found"));
assert_eq!(ret, Err(JedParserError::MissingSTX));
}

#[test]
fn read_no_etx() {
let ret = read_jed(b"asdf\x02fdsa");

assert_eq!(ret, Err("ETX not found"));
assert_eq!(ret, Err(JedParserError::MissingETX));
}

#[test]
fn read_no_csum() {
let ret = read_jed(b"asdf\x02fdsa\x03");
assert_eq!(ret, Err("unexpected end of file - checksum"));
assert_eq!(ret, Err(JedParserError::UnexpectedEnd));

let ret = read_jed(b"asdf\x02fdsa\x03AAA");
assert_eq!(ret, Err("unexpected end of file - checksum"));
assert_eq!(ret, Err(JedParserError::UnexpectedEnd));
}

#[test]
fn read_bad_csum() {
let ret = read_jed(b"asdf\x02fdsa\x03AAAA");

assert_eq!(ret, Err("invalid file checksum"));
assert_eq!(ret, Err(JedParserError::BadFileChecksum));
}

#[test]
fn read_malformed_csum() {
let ret = read_jed(b"asdf\x02fdsa\x03AAAZ");

assert_eq!(ret, Err("invalid character encountered - file checksum"));
assert_eq!(ret, Err(JedParserError::InvalidCharacter));
}

#[test]
fn read_no_f() {
let ret = read_jed(b"\x02QF1*\x030000");

assert_eq!(ret, Err("missing F field"));
assert_eq!(ret, Err(JedParserError::MissingF));
}

#[test]
@@ -290,7 +269,7 @@ mod tests {
fn read_bogus_f_command() {
let ret = read_jed(b"\x02F2*\x030000");

assert_eq!(ret, Err("invalid character encountered - F field"));
assert_eq!(ret, Err(JedParserError::InvalidCharacter));
}

#[test]
@@ -304,7 +283,7 @@ mod tests {
fn read_l_without_qf() {
let ret = read_jed(b"\x02F0*L0 0*\x030000");

assert_eq!(ret, Err("missing QF field"));
assert_eq!(ret, Err(JedParserError::MissingQF));
}

#[test]
@@ -325,7 +304,7 @@ mod tests {
fn read_one_fuse_csum_bad() {
let ret = read_jed(b"\x02F0*QF1*L0 1*C0002*\x030000");

assert_eq!(ret, Err("invalid fuse checksum"));
assert_eq!(ret, Err(JedParserError::BadFuseChecksum));
}

#[test]
3 changes: 3 additions & 0 deletions src/xc2bit/src/lib.rs
Original file line number Diff line number Diff line change
@@ -59,6 +59,9 @@ pub use bitstream::{XC2Bitstream, XC2BitstreamBits, XC2GlobalNets, XC2ClockDivRa
mod crbit;
pub use crbit::{FuseArray};

mod errors;
pub use errors::{JedParserError, XC2BitError};

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

36 changes: 18 additions & 18 deletions src/xc2bit/src/zia.rs
Original file line number Diff line number Diff line change
@@ -9159,15 +9159,15 @@ const F: bool = false;

/// Internal function that reads a piece of the ZIA corresponding to one FB and one row
pub fn read_32_zia_fb_row_logical(fuses: &[bool], block_idx: usize, row_idx: usize)
-> Result<XC2ZIARowPiece, &'static str> {
-> Result<XC2ZIARowPiece, XC2BitError> {

let zia_row_fuses = &fuses[block_idx + row_idx * 8..block_idx + (row_idx + 1) * 8];

decode_32_zia_choice(row_idx, zia_row_fuses)
}

/// Internal function that takes a ZIA row and decodes the bit encoding for it
pub fn decode_32_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPiece, &'static str> {
pub fn decode_32_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPiece, XC2BitError> {
// This is an ugly workaround for the lack of stable slice patterns
let zia_row_fuses = (
row_bits[0],
@@ -9190,7 +9190,7 @@ pub fn decode_32_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPi
(F, T, F, T, T, T, T, T) => ZIA_MAP_32[row][5],
(T, T, T, T, T, T, T, T) => XC2ZIAInput::One,
(F, F, T, T, T, T, T, T) => XC2ZIAInput::Zero,
_ => return Err("unknown ZIA input choice"),
_ => return Err(XC2BitError::UnsupportedZIAConfiguration(row_bits.to_vec())),
}})
}

@@ -9228,15 +9228,15 @@ pub fn encode_32_zia_choice(row: u32, choice: XC2ZIAInput) -> Option<[bool; 8]>

/// Internal function that reads a piece of the ZIA corresponding to one FB and one row
pub fn read_64_zia_fb_row_logical(fuses: &[bool], block_idx: usize, row_idx: usize)
-> Result<XC2ZIARowPiece, &'static str> {
-> Result<XC2ZIARowPiece, XC2BitError> {

let zia_row_fuses = &fuses[block_idx + row_idx * 16..block_idx + (row_idx + 1) * 16];

decode_64_zia_choice(row_idx, zia_row_fuses)
}

/// Internal function that takes a ZIA row and decodes the bit encoding for it
pub fn decode_64_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPiece, &'static str> {
pub fn decode_64_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPiece, XC2BitError> {
// This is an ugly workaround for the lack of stable slice patterns
let zia_row_fuses = (
row_bits[0],
@@ -9274,7 +9274,7 @@ pub fn decode_64_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPi
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) => XC2ZIAInput::One,
// TODO: This one isn't certain
(T, T, T, T, T, T, T, F, F, T, T, T, T, T, T, T) => XC2ZIAInput::Zero,
_ => return Err("unknown ZIA input choice"),
_ => return Err(XC2BitError::UnsupportedZIAConfiguration(row_bits.to_vec())),
}
})
}
@@ -9320,15 +9320,15 @@ pub fn encode_64_zia_choice(row: u32, choice: XC2ZIAInput) -> Option<[bool; 16]>

/// Internal function that reads a piece of the ZIA corresponding to one FB and one row
pub fn read_128_zia_fb_row_logical(fuses: &[bool], block_idx: usize, row_idx: usize)
-> Result<XC2ZIARowPiece, &'static str> {
-> Result<XC2ZIARowPiece, XC2BitError> {

let zia_row_fuses = &fuses[block_idx + row_idx * 28..block_idx + (row_idx + 1) * 28];

decode_128_zia_choice(row_idx, zia_row_fuses)
}

/// Internal function that takes a ZIA row and decodes the bit encoding for it
pub fn decode_128_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPiece, &'static str> {
pub fn decode_128_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPiece, XC2BitError> {
// This is an ugly workaround for the lack of stable slice patterns
let zia_row_fuses = (
row_bits[0],
@@ -9388,7 +9388,7 @@ pub fn decode_128_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowP
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) => XC2ZIAInput::One,
// TODO: This one isn't certain
(T, T, T, T, T, T, T, T, F, F, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) => XC2ZIAInput::Zero,
_ => return Err("unknown ZIA input choice"),
_ => return Err(XC2BitError::UnsupportedZIAConfiguration(row_bits.to_vec())),
}
})
}
@@ -9444,15 +9444,15 @@ pub fn encode_128_zia_choice(row: u32, choice: XC2ZIAInput) -> Option<[bool; 28]

/// Internal function that reads a piece of the ZIA corresponding to one FB and one row
pub fn read_256_zia_fb_row_logical(fuses: &[bool], block_idx: usize, row_idx: usize)
-> Result<XC2ZIARowPiece, &'static str> {
-> Result<XC2ZIARowPiece, XC2BitError> {

let zia_row_fuses = &fuses[block_idx + row_idx * 48..block_idx + (row_idx + 1) * 48];

decode_256_zia_choice(row_idx, zia_row_fuses)
}

/// Internal function that takes a ZIA row and decodes the bit encoding for it
pub fn decode_256_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPiece, &'static str> {
pub fn decode_256_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPiece, XC2BitError> {
// This is an ugly workaround for the lack of stable slice patterns
let zia_row_fuses = (
row_bits[0],
@@ -9550,7 +9550,7 @@ pub fn decode_256_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowP
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) => XC2ZIAInput::One,
// TODO: This one isn't certain
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, F, T, T, T, T, T, T) => XC2ZIAInput::Zero,
_ => return Err("unknown ZIA input choice"),
_ => return Err(XC2BitError::UnsupportedZIAConfiguration(row_bits.to_vec())),
}
})
}
@@ -9624,15 +9624,15 @@ pub fn encode_256_zia_choice(row: u32, choice: XC2ZIAInput) -> Option<[bool; 48]

/// Internal function that reads a piece of the ZIA corresponding to one FB and one row
pub fn read_384_zia_fb_row_logical(fuses: &[bool], block_idx: usize, row_idx: usize)
-> Result<XC2ZIARowPiece, &'static str> {
-> Result<XC2ZIARowPiece, XC2BitError> {

let zia_row_fuses = &fuses[block_idx + row_idx * 74..block_idx + (row_idx + 1) * 74];

decode_384_zia_choice(row_idx, zia_row_fuses)
}

/// Internal function that takes a ZIA row and decodes the bit encoding for it
pub fn decode_384_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPiece, &'static str> {
pub fn decode_384_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPiece, XC2BitError> {
// This is an ugly workaround for the lack of stable slice patterns
let zia_row_fuses = (
row_bits[0],
@@ -9778,7 +9778,7 @@ pub fn decode_384_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowP
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) => XC2ZIAInput::One,
// TODO: This one isn't certain
(T, F, F, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) => XC2ZIAInput::Zero,
_ => return Err("unknown ZIA input choice"),
_ => return Err(XC2BitError::UnsupportedZIAConfiguration(row_bits.to_vec())),
}
})
}
@@ -9874,15 +9874,15 @@ pub fn encode_384_zia_choice(row: u32, choice: XC2ZIAInput) -> Option<[bool; 74]

/// Internal function that reads a piece of the ZIA corresponding to one FB and one row
pub fn read_512_zia_fb_row_logical(fuses: &[bool], block_idx: usize, row_idx: usize)
-> Result<XC2ZIARowPiece, &'static str> {
-> Result<XC2ZIARowPiece, XC2BitError> {

let zia_row_fuses = &fuses[block_idx + row_idx * 88..block_idx + (row_idx + 1) * 88];

decode_512_zia_choice(row_idx, zia_row_fuses)
}

/// Internal function that takes a ZIA row and decodes the bit encoding for it
pub fn decode_512_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPiece, &'static str> {
pub fn decode_512_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowPiece, XC2BitError> {
// This is an ugly workaround for the lack of stable slice patterns
let zia_row_fuses = (
row_bits[0],
@@ -10058,7 +10058,7 @@ pub fn decode_512_zia_choice(row: usize, row_bits: &[bool]) -> Result<XC2ZIARowP
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) => XC2ZIAInput::One,
// TODO: This one isn't certain
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, F, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) => XC2ZIAInput::Zero,
_ => return Err("unknown ZIA input choice"),
_ => return Err(XC2BitError::UnsupportedZIAConfiguration(row_bits.to_vec())),
}
})
}

0 comments on commit 8f6b576

Please sign in to comment.