1use std::io;
29use std::io::Write;
30
31use crate::*;
32use crate::fusemap_logical::{gck_fuse_idx, gsr_fuse_idx, gts_fuse_idx, global_term_fuse_idx, clock_div_fuse_idx};
33use crate::fusemap_physical::{gck_fuse_coords, gsr_fuse_coords, gts_fuse_coords, global_term_fuse_coord,
34 clock_div_fuse_coord};
35
36#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
39pub struct XC2GlobalNets {
40 pub gck_enable: [bool; 3],
42 pub gsr_enable: bool,
44 pub gsr_invert: bool,
48 pub gts_enable: [bool; 4],
50 pub gts_invert: [bool; 4],
54 pub global_pu: bool,
58}
59
60impl Default for XC2GlobalNets {
61 fn default() -> Self {
63 XC2GlobalNets {
64 gck_enable: [false; 3],
65 gsr_enable: false,
66 gsr_invert: false,
67 gts_enable: [false; 4],
68 gts_invert: [true; 4],
69 global_pu: true,
70 }
71 }
72}
73
74impl XC2GlobalNets {
75 pub fn dump_human_readable<W: Write>(&self, mut writer: W) -> Result<(), io::Error> {
77 write!(writer, "\n")?;
78 write!(writer, "GCK0 {}\n", if self.gck_enable[0] {"enabled"} else {"disabled"})?;
79 write!(writer, "GCK1 {}\n", if self.gck_enable[1] {"enabled"} else {"disabled"})?;
80 write!(writer, "GCK2 {}\n", if self.gck_enable[2] {"enabled"} else {"disabled"})?;
81
82 write!(writer, "GSR {}, active {}\n",
83 if self.gsr_enable {"enabled"} else {"disabled"},
84 if self.gsr_invert {"high"} else {"low"})?;
85
86 write!(writer, "GTS0 {}, acts as {}\n",
87 if self.gts_enable[0] {"enabled"} else {"disabled"},
88 if self.gts_invert[0] {"!T"} else {"T"})?;
89 write!(writer, "GTS1 {}, acts as {}\n",
90 if self.gts_enable[1] {"enabled"} else {"disabled"},
91 if self.gts_invert[1] {"!T"} else {"T"})?;
92 write!(writer, "GTS2 {}, acts as {}\n",
93 if self.gts_enable[2] {"enabled"} else {"disabled"},
94 if self.gts_invert[2] {"!T"} else {"T"})?;
95 write!(writer, "GTS3 {}, acts as {}\n",
96 if self.gts_enable[3] {"enabled"} else {"disabled"},
97 if self.gts_invert[3] {"!T"} else {"T"})?;
98
99 write!(writer, "global termination is {}\n", if self.global_pu {"pull-up"} else {"bus hold"})?;
100
101 Ok(())
102 }
103
104 pub fn to_crbit(&self, device: XC2Device, fuse_array: &mut FuseArray) {
106 let ((gck0x, gck0y), (gck1x, gck1y), (gck2x, gck2y)) = gck_fuse_coords(device);
107 fuse_array.set(gck0x, gck0y, self.gck_enable[0]);
108 fuse_array.set(gck1x, gck1y, self.gck_enable[1]);
109 fuse_array.set(gck2x, gck2y, self.gck_enable[2]);
110
111 let ((gsren_x, gsren_y), (gsrinv_x, gsrinv_y)) = gsr_fuse_coords(device);
112 fuse_array.set(gsren_x, gsren_y, self.gsr_enable);
113 fuse_array.set(gsrinv_x, gsrinv_y, self.gsr_invert);
114
115 let (((gts0en_x, gts0en_y), (gts0inv_x, gts0inv_y)), ((gts1en_x, gts1en_y), (gts1inv_x, gts1inv_y)),
116 ((gts2en_x, gts2en_y), (gts2inv_x, gts2inv_y)), ((gts3en_x, gts3en_y), (gts3inv_x, gts3inv_y))) =
117 gts_fuse_coords(device);
118 fuse_array.set(gts0en_x, gts0en_y, !self.gts_enable[0]);
119 fuse_array.set(gts0inv_x, gts0inv_y, self.gts_invert[0]);
120 fuse_array.set(gts1en_x, gts1en_y, !self.gts_enable[1]);
121 fuse_array.set(gts1inv_x, gts1inv_y, self.gts_invert[1]);
122 fuse_array.set(gts2en_x, gts2en_y, !self.gts_enable[2]);
123 fuse_array.set(gts2inv_x, gts2inv_y, self.gts_invert[2]);
124 fuse_array.set(gts3en_x, gts3en_y, !self.gts_enable[3]);
125 fuse_array.set(gts3inv_x, gts3inv_y, self.gts_invert[3]);
126
127 let (term_x, term_y) = global_term_fuse_coord(device);
128 fuse_array.set(term_x, term_y, self.global_pu);
129 }
130
131 pub fn from_jed(device: XC2Device, fuses: &[bool]) -> Self {
133 XC2GlobalNets {
134 gck_enable: [
135 fuses[gck_fuse_idx(device) + 0],
136 fuses[gck_fuse_idx(device) + 1],
137 fuses[gck_fuse_idx(device) + 2],
138 ],
139 gsr_enable: fuses[gsr_fuse_idx(device) + 1],
140 gsr_invert: fuses[gsr_fuse_idx(device) + 0],
141 gts_enable: [
142 !fuses[gts_fuse_idx(device) + 1],
143 !fuses[gts_fuse_idx(device) + 3],
144 !fuses[gts_fuse_idx(device) + 5],
145 !fuses[gts_fuse_idx(device) + 7],
146 ],
147 gts_invert: [
148 fuses[gts_fuse_idx(device) + 0],
149 fuses[gts_fuse_idx(device) + 2],
150 fuses[gts_fuse_idx(device) + 4],
151 fuses[gts_fuse_idx(device) + 6],
152 ],
153 global_pu: fuses[global_term_fuse_idx(device)],
154 }
155 }
156
157 pub fn from_crbit(device: XC2Device, fuse_array: &FuseArray) -> Self {
159 let ((gck0x, gck0y), (gck1x, gck1y), (gck2x, gck2y)) = gck_fuse_coords(device);
160
161 let ((gsren_x, gsren_y), (gsrinv_x, gsrinv_y)) = gsr_fuse_coords(device);
162
163 let (((gts0en_x, gts0en_y), (gts0inv_x, gts0inv_y)), ((gts1en_x, gts1en_y), (gts1inv_x, gts1inv_y)),
164 ((gts2en_x, gts2en_y), (gts2inv_x, gts2inv_y)), ((gts3en_x, gts3en_y), (gts3inv_x, gts3inv_y))) =
165 gts_fuse_coords(device);
166
167 let (term_x, term_y) = global_term_fuse_coord(device);
168
169 XC2GlobalNets {
170 gck_enable: [
171 fuse_array.get(gck0x, gck0y),
172 fuse_array.get(gck1x, gck1y),
173 fuse_array.get(gck2x, gck2y),
174 ],
175 gsr_enable: fuse_array.get(gsren_x, gsren_y),
176 gsr_invert: fuse_array.get(gsrinv_x, gsrinv_y),
177 gts_enable: [
178 !fuse_array.get(gts0en_x, gts0en_y),
179 !fuse_array.get(gts1en_x, gts1en_y),
180 !fuse_array.get(gts2en_x, gts2en_y),
181 !fuse_array.get(gts3en_x, gts3en_y),
182 ],
183 gts_invert: [
184 fuse_array.get(gts0inv_x, gts0inv_y),
185 fuse_array.get(gts1inv_x, gts1inv_y),
186 fuse_array.get(gts2inv_x, gts2inv_y),
187 fuse_array.get(gts3inv_x, gts3inv_y),
188 ],
189 global_pu: fuse_array.get(term_x, term_y),
190 }
191 }
192}
193
194#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
196#[derive(BitPattern)]
197pub enum XC2ClockDivRatio {
198 #[bits = "000"]
199 Div2,
200 #[bits = "001"]
201 Div4,
202 #[bits = "010"]
203 Div6,
204 #[bits = "011"]
205 Div8,
206 #[bits = "100"]
207 Div10,
208 #[bits = "101"]
209 Div12,
210 #[bits = "110"]
211 Div14,
212 #[bits = "111"]
213 Div16,
214}
215
216#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
219pub struct XC2ClockDiv {
220 pub div_ratio: XC2ClockDivRatio,
222 pub delay: bool,
224 pub enabled: bool,
226}
227
228impl XC2ClockDiv {
229 pub fn dump_human_readable<W: Write>(&self, mut writer: W) -> Result<(), io::Error> {
231 write!(writer, "\n")?;
232 write!(writer, "GCK2 clock divider {}\n", if self.enabled {"enabled"} else {"disabled"})?;
233 write!(writer, "clock divider delay {}\n", if self.delay {"enabled"} else {"disabled"})?;
234
235 write!(writer, "clock division ratio: {}\n", match self.div_ratio {
236 XC2ClockDivRatio::Div2 => "2",
237 XC2ClockDivRatio::Div4 => "4",
238 XC2ClockDivRatio::Div6 => "6",
239 XC2ClockDivRatio::Div8 => "8",
240 XC2ClockDivRatio::Div10 => "10",
241 XC2ClockDivRatio::Div12 => "12",
242 XC2ClockDivRatio::Div14 => "14",
243 XC2ClockDivRatio::Div16 => "16",
244 })?;
245
246 Ok(())
247 }
248}
249
250impl Default for XC2ClockDiv {
251 fn default() -> Self {
253 XC2ClockDiv {
254 div_ratio: XC2ClockDivRatio::Div16,
255 delay: false,
256 enabled: false,
257 }
258 }
259}
260
261impl XC2ClockDiv {
262 pub fn from_jed(device: XC2Device, fuses: &[bool]) -> Self {
264 let clock_fuse_block = clock_div_fuse_idx(device);
265
266 XC2ClockDiv {
267 delay: !fuses[clock_fuse_block + 4],
268 enabled: !fuses[clock_fuse_block],
269 div_ratio: XC2ClockDivRatio::decode((fuses[clock_fuse_block + 1], fuses[clock_fuse_block + 2], fuses[clock_fuse_block + 3])),
270 }
271 }
272
273 pub fn from_crbit(device: XC2Device, fuse_array: &FuseArray) -> Self {
275 let ((clken_x, clken_y), (clkdiv0_x, clkdiv0_y), (clkdiv1_x, clkdiv1_y), (clkdiv2_x, clkdiv2_y),
276 (clkdelay_x, clkdelay_y)) = clock_div_fuse_coord(device);
277
278 let div_ratio_bits = (fuse_array.get(clkdiv0_x, clkdiv0_y),
279 fuse_array.get(clkdiv1_x, clkdiv1_y),
280 fuse_array.get(clkdiv2_x, clkdiv2_y));
281
282 XC2ClockDiv {
283 delay: !fuse_array.get(clkdelay_x, clkdelay_y),
284 enabled: !fuse_array.get(clken_x, clken_y),
285 div_ratio: XC2ClockDivRatio::decode(div_ratio_bits),
286 }
287 }
288}