1use xc2bit::*;
27
28use crate::*;
29use crate::objpool::*;
30
31pub fn produce_bitstream(device_type: XC2DeviceSpeedPackage, g: &InputGraph, go: &OutputGraph) -> XC2Bitstream {
32 let mut result = XC2Bitstream::blank_bitstream(device_type);
33
34 {
35 let fb_bits = result.bits.get_fb_mut();
36
37 for fb_i in 0..go.zia.len() {
39 for zia_i in 0..INPUTS_PER_ANDTERM {
40 *fb_bits[fb_i].get_mut_zia(zia_i) = go.zia[fb_i].get(zia_i);
41 }
42 }
43
44 for andterm_idx in g.pterms.iter_idx() {
46 let andterm_go = go.pterms.get(ObjPoolIndex::from(andterm_idx));
47 let fb_i = andterm_go.loc.unwrap().fb as usize;
48 let andterm_i = andterm_go.loc.unwrap().i as usize;
49
50 for &x in &andterm_go.inputs_true_zia {
51 fb_bits[fb_i].get_mut_andterm(andterm_i).set(x as usize, true);
52 }
53 for &x in &andterm_go.inputs_comp_zia {
54 fb_bits[fb_i].get_mut_andterm(andterm_i).set_b(x as usize, true);
55 }
56 }
57 }
58
59 for mc_idx in g.mcs.iter_idx() {
61 let mc = g.mcs.get(mc_idx);
62 let mc_go = go.mcs.get(ObjPoolIndex::from(mc_idx));
63 let fb_i = mc_go.loc.unwrap().fb;
64 let mc_i = mc_go.loc.unwrap().i;
65
66 if let Some(ref io_bits) = mc.io_bits {
67 if (device_type.dev == XC2Device::XC2C32 || device_type.dev == XC2Device::XC2C32A) && fb_i == 2 && mc_i == 0 {
68 match result.bits {
70 XC2BitstreamBits::XC2C32{inpin: ref mut extra_inpin, ..} |
71 XC2BitstreamBits::XC2C32A{inpin: ref mut extra_inpin, ..} => {
72 extra_inpin.schmitt_trigger = io_bits.schmitt_trigger;
73 extra_inpin.termination_enabled = io_bits.termination_enabled;
74 },
75 _ => unreachable!(),
76 }
77 } else {
78 let i_iob = fb_mc_num_to_iob_num(device_type.dev, fb_i as u32, mc_i as u32).unwrap();
79
80 macro_rules! output_iob_common {
81 ($iob_bit:expr) => {{
82 $iob_bit.termination_enabled = io_bits.termination_enabled;
83 $iob_bit.slew_is_fast = io_bits.slew_is_fast;
84 if let Some(input) = io_bits.input {
85 $iob_bit.obuf_uses_ff = input == InputGraphIOInputType::Reg;
86 $iob_bit.obuf_mode = match io_bits.oe {
87 None => XC2IOBOBufMode::PushPull,
88 Some(InputGraphIOOEType::OpenDrain) => XC2IOBOBufMode::OpenDrain,
89 Some(InputGraphIOOEType::PTerm(pterm)) => {
90 let pterm = go.pterms.get(ObjPoolIndex::from(pterm));
91 let pt_loc = pterm.loc.unwrap();
92 assert!(pt_loc.fb == fb_i);
93
94 if pt_loc.i == CTE {
95 XC2IOBOBufMode::TriStateCTE
96 } else if pt_loc.i == get_ptb(mc_i as u32) {
97 XC2IOBOBufMode::TriStatePTB
98 } else {
99 panic!("Internal error - not CTE or PTB");
100 }
101 },
102 Some(InputGraphIOOEType::GTS(gts)) => {
103 let gts = go.bufg_gts.get(ObjPoolIndex::from(gts));
104 let which = gts.loc.unwrap().i;
105 match which {
106 0 => XC2IOBOBufMode::TriStateGTS0,
107 1 => XC2IOBOBufMode::TriStateGTS1,
108 2 => XC2IOBOBufMode::TriStateGTS2,
109 3 => XC2IOBOBufMode::TriStateGTS3,
110 _ => panic!("Internal error - bad GTS"),
111 }
112 },
113 }
114 }
115 }}
116 }
117
118 if device_type.dev.is_small_iob() {
119 let iob_bit = result.bits.get_mut_small_iob(i_iob as usize).unwrap();
120
121 iob_bit.schmitt_trigger = io_bits.schmitt_trigger;
122 output_iob_common!(iob_bit);
123 } else {
124 let iob_bit = result.bits.get_mut_large_iob(i_iob as usize).unwrap();
125
126 iob_bit.ibuf_mode = if io_bits.schmitt_trigger {
128 XC2IOBIbufMode::NoVrefSt
129 } else {
130 XC2IOBIbufMode::NoVrefNoSt
131 };
132 iob_bit.uses_data_gate = io_bits.uses_data_gate;
133 output_iob_common!(iob_bit);
134 }
135 }
136 }
137
138 if let Some(i_iob) = fb_mc_num_to_iob_num(device_type.dev, fb_i as u32, mc_i as u32) {
140 macro_rules! output_iob_common {
141 ($iob_bit:expr) => {{
142 if mc.io_feedback_used {
143 $iob_bit.zia_mode = XC2IOBZIAMode::PAD;
145 } else if (mc.xor_feedback_used && mc.reg_feedback_used) ||
146 mc.get_type() == InputGraphMacrocellType::PinInputReg {
147
148 $iob_bit.zia_mode = XC2IOBZIAMode::REG;
151 }
152 }}
153 }
154
155 if device_type.dev.is_small_iob() {
156 let iob_bit = result.bits.get_mut_small_iob(i_iob as usize).unwrap();
157
158 output_iob_common!(iob_bit);
159 } else {
160 let iob_bit = result.bits.get_mut_large_iob(i_iob as usize).unwrap();
161
162 output_iob_common!(iob_bit);
163 }
164 }
165 }
166
167 {
168 let fb_bits = result.bits.get_fb_mut();
169
170 for mc_idx in g.mcs.iter_idx() {
172 let mc = g.mcs.get(mc_idx);
173 let mc_go = go.mcs.get(ObjPoolIndex::from(mc_idx));
174 let fb_i = mc_go.loc.unwrap().fb as usize;
175 let mc_i = mc_go.loc.unwrap().i as usize;
176
177 if let Some(ref xor_bits) = mc.xor_bits {
178 fb_bits[fb_i].mcs[mc_i].xor_mode = match (xor_bits.invert_out, xor_bits.andterm_input) {
180 (false, None) => XC2MCXorMode::ZERO,
181 (true, None) => XC2MCXorMode::ONE,
182 (false, Some(_)) => XC2MCXorMode::PTC,
183 (true, Some(_)) => XC2MCXorMode::PTCB,
184 };
185
186 for &and_to_or_idx in &xor_bits.orterm_inputs {
188 let pterm = go.pterms.get(ObjPoolIndex::from(and_to_or_idx));
189 let pt_loc = pterm.loc.unwrap();
190 assert!(pt_loc.fb as usize == fb_i);
191 fb_bits[fb_i].or_terms[mc_i].set(pt_loc.i as usize, true);
192 }
193
194 if mc.xor_feedback_used {
196 fb_bits[fb_i].mcs[mc_i].fb_mode = XC2MCFeedbackMode::COMB;
197 } else if mc.reg_feedback_used {
198 fb_bits[fb_i].mcs[mc_i].fb_mode = XC2MCFeedbackMode::REG;
199 }
200 }
201 }
202
203 for mc_idx in g.mcs.iter_idx() {
205 let mc = g.mcs.get(mc_idx);
206 let mc_go = go.mcs.get(ObjPoolIndex::from(mc_idx));
207 let fb_i = mc_go.loc.unwrap().fb as usize;
208 let mc_i = mc_go.loc.unwrap().i as usize;
209
210 if let Some(ref reg_bits) = mc.reg_bits {
211 fb_bits[fb_i].mcs[mc_i].reg_mode = reg_bits.mode;
212 fb_bits[fb_i].mcs[mc_i].clk_invert_pol = reg_bits.clkinv;
213 fb_bits[fb_i].mcs[mc_i].is_ddr = reg_bits.clkddr;
214 fb_bits[fb_i].mcs[mc_i].init_state = reg_bits.init_state;
215
216 fb_bits[fb_i].mcs[mc_i].s_src = match reg_bits.set_input {
218 None => XC2MCRegSetSrc::Disabled,
219 Some(InputGraphRegRSType::GSR(_)) => XC2MCRegSetSrc::GSR,
220 Some(InputGraphRegRSType::PTerm(pterm)) => {
221 let pterm = go.pterms.get(ObjPoolIndex::from(pterm));
222 let pt_loc = pterm.loc.unwrap();
223 assert!(pt_loc.fb as usize == fb_i);
224
225 if pt_loc.i == CTS {
226 XC2MCRegSetSrc::CTS
227 } else if pt_loc.i == get_pta(mc_i as u32) {
228 XC2MCRegSetSrc::PTA
229 } else {
230 panic!("Internal error - not CTS or PTA");
231 }
232 },
233 };
234
235 fb_bits[fb_i].mcs[mc_i].r_src = match reg_bits.reset_input {
237 None => XC2MCRegResetSrc::Disabled,
238 Some(InputGraphRegRSType::GSR(_)) => XC2MCRegResetSrc::GSR,
239 Some(InputGraphRegRSType::PTerm(pterm)) => {
240 let pterm = go.pterms.get(ObjPoolIndex::from(pterm));
241 let pt_loc = pterm.loc.unwrap();
242 assert!(pt_loc.fb as usize == fb_i);
243
244 if pt_loc.i == CTR {
245 XC2MCRegResetSrc::CTR
246 } else if pt_loc.i == get_pta(mc_i as u32) {
247 XC2MCRegResetSrc::PTA
248 } else {
249 panic!("Internal error - not CTR or PTA");
250 }
251 },
252 };
253
254 fb_bits[fb_i].mcs[mc_i].ff_in_ibuf = reg_bits.dt_input == InputGraphRegInputType::Pin;
256
257 fb_bits[fb_i].mcs[mc_i].clk_src = match reg_bits.clk_input {
259 InputGraphRegClockType::PTerm(pterm) => {
260 let pterm = go.pterms.get(ObjPoolIndex::from(pterm));
261 let pt_loc = pterm.loc.unwrap();
262 assert!(pt_loc.fb as usize == fb_i);
263
264 if pt_loc.i == CTC {
265 XC2MCRegClkSrc::CTC
266 } else if pt_loc.i == get_ptc(mc_i as u32) {
267 XC2MCRegClkSrc::PTC
268 } else {
269 panic!("Internal error - not CTC or PTC");
270 }
271 },
272 InputGraphRegClockType::GCK(gck) => {
273 let gck = go.bufg_clks.get(ObjPoolIndex::from(gck));
274 let which = gck.loc.unwrap().i;
275 match which {
276 0 => XC2MCRegClkSrc::GCK0,
277 1 => XC2MCRegClkSrc::GCK1,
278 2 => XC2MCRegClkSrc::GCK2,
279 _ => panic!("Internal error - bad GCK"),
280 }
281 },
282 }
283 }
284 }
285 }
286
287 {
288 let global_nets = result.bits.get_global_nets_mut();
289
290 for gck in go.bufg_clks.iter() {
292 let which = gck.loc.unwrap().i;
293 global_nets.gck_enable[which as usize] = true;
294 }
295 for gts_idx in g.bufg_gts.iter_idx() {
296 let gts = g.bufg_gts.get(gts_idx);
297 let gts_go = go.bufg_gts.get(ObjPoolIndex::from(gts_idx));
298 let which = gts_go.loc.unwrap().i;
299 global_nets.gts_enable[which as usize] = true;
300 global_nets.gts_invert[which as usize] = gts.invert;
301 }
302 for gsr in g.bufg_gsr.iter() {
303 global_nets.gsr_enable = true;
304 global_nets.gsr_invert = gsr.invert;
305 }
306 }
307
308 if let XC2BitstreamBits::XC2C32A{ref mut legacy_ivoltage, ref mut legacy_ovoltage,
310 ref mut ivoltage, ref mut ovoltage, ..} = result.bits {
311
312 *legacy_ivoltage = false;
313 *legacy_ovoltage = false;
314 *ivoltage = [false, false];
315 *ovoltage = [false, false];
316 }
317
318 result
319}