Skip to main content

xc2par/
output.rs

1/*
2Copyright (c) 2016-2017, Robert Ou <rqou@robertou.com> and contributors
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
81. Redistributions of source code must retain the above copyright notice,
9   this list of conditions and the following disclaimer.
102. Redistributions in binary form must reproduce the above copyright notice,
11   this list of conditions and the following disclaimer in the documentation
12   and/or other materials provided with the distribution.
13
14THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24*/
25
26use 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        // ZIA settings
38        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        // AND terms
45        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    // IO bits
60    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                // Special input-only pin
69                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                    // TODO: Pins that are/use Vref
127                    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        // Set the ZIA feedback mode (even if the io bit isn't actually used)
139        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                        // We need to set the ZIA mode to use the IO pad.
144                        $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                        // If both of these are used, then the register _has_ to come from here. Otherwise use the
149                        // "normal" one. Additionally, if we are a registered input pin, use the register.
150                        $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        // OR/XOR gates
171        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                // XOR
179                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                // OR
187                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                // Feedback
195                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        // Register bits
204        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                // Set
217                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                // Reset
236                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                // D/T input
255                fb_bits[fb_i].mcs[mc_i].ff_in_ibuf = reg_bits.dt_input == InputGraphRegInputType::Pin;
256
257                // Clock input
258                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        // Global buffers
291        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    // XXX TODO other global bits
309    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}