use crate::*;
pub fn get_gck(device: XC2Device, idx: usize) -> Option<(u32, u32)> {
if idx >= 3 {
return None;
}
match device {
XC2Device::XC2C32 | XC2Device::XC2C32A => match idx {
0 => Some((1, 4)), 1 => Some((1, 5)), 2 => Some((1, 6)), _ => unreachable!()
},
XC2Device::XC2C64 | XC2Device::XC2C64A => match idx {
0 => Some((1, 6)), 1 => Some((1, 7)), 2 => Some((1, 9)), _ => unreachable!()
},
XC2Device::XC2C128 => match idx {
0 => Some((1, 12)), 1 => Some((1, 13)), 2 => Some((1, 15)), _ => unreachable!()
},
XC2Device::XC2C256 => match idx {
0 => Some((4, 5)), 1 => Some((4, 3)), 2 => Some((5, 3)), _ => unreachable!()
},
XC2Device::XC2C384 => match idx {
0 => Some((6, 14)), 1 => Some((6, 11)), 2 => Some((7, 1)), _ => unreachable!()
},
XC2Device::XC2C512 => match idx {
0 => Some((10, 2)), 1 => Some((8, 15)), 2 => Some((9, 2)), _ => unreachable!()
}
}
}
pub fn get_gts(device: XC2Device, idx: usize) -> Option<(u32, u32)> {
if idx >= 4 {
return None;
}
match device {
XC2Device::XC2C32 | XC2Device::XC2C32A => match idx {
0 => Some((0, 4)), 1 => Some((0, 3)), 2 => Some((0, 6)), 3 => Some((0, 5)), _ => unreachable!()
},
XC2Device::XC2C64 | XC2Device::XC2C64A => match idx {
0 => Some((0, 9)), 1 => Some((0, 8)), 2 => Some((0, 11)), 3 => Some((0, 10)), _ => unreachable!()
},
XC2Device::XC2C128 => match idx {
0 => Some((0, 15)), 1 => Some((0, 14)), 2 => Some((2, 2)), 3 => Some((2, 1)), _ => unreachable!()
},
XC2Device::XC2C256 => match idx {
0 => Some((1, 4)), 1 => Some((1, 11)), 2 => Some((1, 0)), 3 => Some((1, 2)), _ => unreachable!()
},
XC2Device::XC2C384 => match idx {
0 => Some((1, 4)), 1 => Some((1, 14)), 2 => Some((1, 0)), 3 => Some((1, 2)), _ => unreachable!()
},
XC2Device::XC2C512 => match idx {
0 => Some((0, 0)), 1 => Some((1, 13)), 2 => Some((0, 12)), 3 => Some((0, 2)), _ => unreachable!()
}
}
}
pub fn get_gsr(device: XC2Device) -> (u32, u32) {
match device {
XC2Device::XC2C32 | XC2Device::XC2C32A => (0, 7),
XC2Device::XC2C64 | XC2Device::XC2C64A => (0, 12),
XC2Device::XC2C128 => (2, 3),
XC2Device::XC2C256 => (0, 2),
XC2Device::XC2C384 => (0, 2),
XC2Device::XC2C512 => (0, 15),
}
}
pub fn get_cdrst(device: XC2Device) -> Option<(u32, u32)> {
match device {
XC2Device::XC2C32 | XC2Device::XC2C32A => None,
XC2Device::XC2C64 | XC2Device::XC2C64A => None,
XC2Device::XC2C128 => Some((1, 14)),
XC2Device::XC2C256 => Some((5, 1)),
XC2Device::XC2C384 => Some((6, 0)),
XC2Device::XC2C512 => Some((9, 0)),
}
}
pub fn get_dge(device: XC2Device) -> Option<(u32, u32)> {
match device {
XC2Device::XC2C32 | XC2Device::XC2C32A => None,
XC2Device::XC2C64 | XC2Device::XC2C64A => None,
XC2Device::XC2C128 => Some((3, 0)),
XC2Device::XC2C256 => Some((5, 11)),
XC2Device::XC2C384 => Some((7, 4)),
XC2Device::XC2C512 => Some((9, 13)),
}
}
pub fn get_device_structure<N, W, C>(device: XC2Device,
mut node_callback: N, mut wire_callback: W, mut connection_callback: C)
where N: FnMut(&str, &str, u32, u32) -> usize,
W: FnMut(&str) -> usize,
C: FnMut(usize, usize, &'static str, u32, (u32, u32)) -> () {
let gck = (0..3).map(|i| {
let w = wire_callback(&format!("gck_{}", i));
let n = node_callback(&format!("bufg_gck_{}", i), "BUFG", 0, i);
connection_callback(n, w, "O", 0, (0, 0));
(w, n)
}).collect::<Vec<_>>();
let gts = (0..4).map(|i| {
let w = wire_callback(&format!("gts_{}", i));
let n = node_callback(&format!("bufg_gts_{}", i), "BUFGTS", 0, i);
connection_callback(n, w, "O", 0, (0, 0));
(w, n)
}).collect::<Vec<_>>();
let gsr_wire = wire_callback("gsr");
let gsr_node = node_callback("bufg_gsr", "BUFGSR", 0, 0);
connection_callback(gsr_node, gsr_wire, "O", 0, (0, 0));
let fb_things = (0..device.num_fbs() as u32).map(|fb| {
let pterm_wires = (0..ANDTERMS_PER_FB).map(|i| {
wire_callback(&format!("fb{}_pterm{}", fb, i))
}).collect::<Vec<_>>();
let orterm_wires = (0..MCS_PER_FB).map(|i| {
wire_callback(&format!("fb{}_or{}", fb, i))
}).collect::<Vec<_>>();
let xorterm_wires = (0..MCS_PER_FB).map(|i| {
wire_callback(&format!("fb{}_xor{}", fb, i))
}).collect::<Vec<_>>();
let regout_wires = (0..MCS_PER_FB).map(|i| {
wire_callback(&format!("fb{}_regout{}", fb, i))
}).collect::<Vec<_>>();
let and_nodes = (0..ANDTERMS_PER_FB).map(|i| {
let n = node_callback(&format!("fb{}_andgate{}", fb, i), "ANDTERM", fb, i as u32);
connection_callback(n, pterm_wires[i], "OUT", 0, (0, 0));
n
}).collect::<Vec<_>>();
for i in 0..MCS_PER_FB {
let n = node_callback(&format!("fb{}_orgate{}", fb, i), "ORTERM", fb, i as u32);
connection_callback(n, orterm_wires[i], "OUT", 0, (0, 0));
for j in 0..ANDTERMS_PER_FB {
connection_callback(n, pterm_wires[j], "IN", j as u32, (0, 0));
}
}
let xor_nodes = (0..MCS_PER_FB).map(|i| {
let n = node_callback(&format!("fb{}_xorgate{}", fb, i), "MACROCELL_XOR", fb, i as u32);
connection_callback(n, xorterm_wires[i], "OUT", 0, (0, 0));
connection_callback(n, orterm_wires[i], "IN_ORTERM", 0, (0, 0));
connection_callback(n, pterm_wires[get_ptc(i as u32) as usize], "IN_PTC", 0, (0, 0));
n
}).collect::<Vec<_>>();
let reg_nodes = (0..MCS_PER_FB).map(|i| {
let n = node_callback(&format!("fb{}_reg{}", fb, i), "REG", fb, i as u32);
connection_callback(n, regout_wires[i], "Q", 0, (0, 0));
connection_callback(n, xorterm_wires[i], "D/T", 0, (0, 0));
connection_callback(n, pterm_wires[get_ptc(i as u32) as usize], "CE", 0, (0, 0));
for j in 0..3 {
connection_callback(n, gck[j].0, "CLK", j as u32, (0, 0));
}
connection_callback(n, pterm_wires[CTC as usize], "CLK", 3, (0, 0));
connection_callback(n, pterm_wires[get_ptc(i as u32) as usize], "CLK", 4, (0, 0));
connection_callback(n, gsr_wire, "S", 0, (0, 0));
connection_callback(n, pterm_wires[CTS as usize], "S", 1, (0, 0));
connection_callback(n, pterm_wires[get_pta(i as u32) as usize], "S", 2, (0, 0));
connection_callback(n, gsr_wire, "R", 0, (0, 0));
connection_callback(n, pterm_wires[CTR as usize], "R", 1, (0, 0));
connection_callback(n, pterm_wires[get_pta(i as u32) as usize], "R", 2, (0, 0));
n
}).collect::<Vec<_>>();
(reg_nodes, xor_nodes, pterm_wires, and_nodes, regout_wires, xorterm_wires)
}).collect::<Vec<_>>();
let to_from_iob_wires = (0..device.num_iobs() as u32).map(|iob_idx| {
let (fb, i) = iob_num_to_fb_mc_num(device, iob_idx).unwrap();
let to_w = wire_callback(&format!("to_iob_{}", iob_idx));
let from_w = wire_callback(&format!("from_iob_{}", iob_idx));
connection_callback(fb_things[fb as usize].0[i as usize], from_w, "D/T", 1, (0, 0));
connection_callback(fb_things[fb as usize].1[i as usize], to_w, "OUT", 1, (0, 0));
connection_callback(fb_things[fb as usize].0[i as usize], to_w, "Q", 1, (0, 0));
(to_w, from_w)
}).collect::<Vec<_>>();
for iob_idx in 0..device.num_iobs() {
let n = node_callback(&format!("iob_{}", iob_idx), "IOBUFE", 0, iob_idx as u32);
connection_callback(n, to_from_iob_wires[iob_idx].0, "I", 0, (0, 0));
connection_callback(n, to_from_iob_wires[iob_idx].1, "O", 0, (0, 0));
let (iob_fb, iob_mc) = iob_num_to_fb_mc_num(device, iob_idx as u32).unwrap();
for i in 0..4 {
connection_callback(n, gts[i].0, "E", i as u32, (0, 0));
}
connection_callback(n, to_from_iob_wires[iob_idx].0, "E", 4, (0, 0));
connection_callback(n, fb_things[iob_fb as usize].2[CTE as usize], "E", 5, (0, 0));
connection_callback(n, fb_things[iob_fb as usize].2[get_ptb(iob_mc) as usize], "E", 6, (0, 0));
}
let from_ipad_w;
match device {
XC2Device::XC2C32 | XC2Device::XC2C32A => {
let w = wire_callback("from_ipad");
from_ipad_w = Some(w);
let n = node_callback("ipad", "IBUF", 0, 0);
connection_callback(n, w, "O", 0, (0, 0));
},
_ => {
from_ipad_w = None;
}
}
for i in 0..3 {
let (fb, mc) = get_gck(device, i as usize).unwrap();
let iob_idx = fb_mc_num_to_iob_num(device, fb, mc).unwrap();
connection_callback(gck[i].1, to_from_iob_wires[iob_idx as usize].1, "I", 0, (0, 0));
}
for i in 0..4 {
let (fb, mc) = get_gts(device, i as usize).unwrap();
let iob_idx = fb_mc_num_to_iob_num(device, fb, mc).unwrap();
connection_callback(gts[i].1, to_from_iob_wires[iob_idx as usize].1, "I", 0, (0, 0));
}
{
let (fb, mc) = get_gsr(device);
let iob_idx = fb_mc_num_to_iob_num(device, fb, mc).unwrap();
connection_callback(gsr_node, to_from_iob_wires[iob_idx as usize].1, "I", 0, (0, 0));
}
for zia_row_i in 0..INPUTS_PER_ANDTERM as u32 {
for (zia_choice_i, zia_choice) in zia_table_get_row(device, zia_row_i as usize).iter().enumerate() {
for and_fb in 0..device.num_fbs() as u32 {
for and_i in 0..ANDTERMS_PER_FB as u32 {
match zia_choice {
&XC2ZIAInput::Macrocell{fb: zia_fb, mc: zia_mc} => {
connection_callback(fb_things[and_fb as usize].3[and_i as usize],
fb_things[zia_fb as usize].5[zia_mc as usize], "IN", zia_row_i,
(zia_choice_i as u32, 0));
connection_callback(fb_things[and_fb as usize].3[and_i as usize],
fb_things[zia_fb as usize].4[zia_mc as usize], "IN", zia_row_i,
(zia_choice_i as u32, 1));
},
&XC2ZIAInput::IBuf{ibuf: zia_iob} => {
let (iob_fb, iob_mc) = iob_num_to_fb_mc_num(device, zia_iob as u32).unwrap();
connection_callback(fb_things[and_fb as usize].3[and_i as usize],
to_from_iob_wires[zia_iob as usize].1, "IN", zia_row_i,
(zia_choice_i as u32, 0));
connection_callback(fb_things[and_fb as usize].3[and_i as usize],
fb_things[iob_fb as usize].4[iob_mc as usize], "IN", zia_row_i,
(zia_choice_i as u32, 1));
},
&XC2ZIAInput::DedicatedInput => {
connection_callback(fb_things[and_fb as usize].3[and_i as usize],
from_ipad_w.unwrap(), "IN", zia_row_i,
(zia_choice_i as u32, 0));
},
_ => unreachable!(),
}
}
}
}
}
}