Deleted Added
sdiff udiff text old ( 10152:52c552138ba1 ) new ( 10234:5cb711fa6176 )
full compact
1/*****************************************************************************
2 * McPAT
3 * SOFTWARE LICENSE AGREEMENT
4 * Copyright 2012 Hewlett-Packard Development Company, L.P.
5 * Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
6 * All Rights Reserved
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer;
12 * redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the

--- 7 unchanged lines hidden (view full) ---

21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 ***************************************************************************/
32#include <algorithm>
33#include <cassert>
34#include <cmath>
35#include <iostream>
36#include <string>
37
38#include "basic_circuit.h"
39#include "common.h"
40#include "const.h"
41#include "io.h"
42#include "iocontrollers.h"
43#include "logic.h"
44
45/*
46SUN Niagara 2 I/O power analysis:
47total signal bits: 711
48Total FBDIMM bits: (14+10)*2*8= 384
49PCIe bits: (8 + 8)*2 = 32
5010Gb NIC: (4*2+4*2)*2 = 32
51Debug I/Os: 168

--- 11 unchanged lines hidden (view full) ---

63
64/*
65 * A bug in Cadence ChipEstimator: After update the clock rate in the clock tab, a user
66 * need to re-select the IP clock (the same clk) and then click Estimate. if not reselect
67 * the new clock rate may not be propogate into the IPs.
68 *
69 */
70
71NIUController::NIUController(XMLNode* _xml_data,InputParameter* interface_ip_)
72 : McPATComponent(_xml_data, interface_ip_) {
73 name = "NIU";
74 set_niu_param();
75}
76
77void NIUController::computeArea() {
78 double mac_area;
79 double frontend_area;
80 double SerDer_area;
81
82 if (niup.type == 0) { //high performance NIU
83 //Area estimation based on average of die photo from Niagara 2 and
84 //Cadence ChipEstimate using 65nm.
85 mac_area = (1.53 + 0.3) / 2 * (interface_ip.F_sz_um / 0.065) *
86 (interface_ip.F_sz_um / 0.065);
87 //Area estimation based on average of die photo from Niagara 2, ISSCC
88 //"An 800mW 10Gb Ethernet Transceiver in 0.13μm CMOS"
89 //and"A 1.2-V-Only 900-mW 10 Gb Ethernet Transceiver and XAUI Interface
90 //With Robust VCO Tuning Technique" Frontend is PCS
91 frontend_area = (9.8 + (6 + 18) * 65 / 130 * 65 / 130) / 3 *
92 (interface_ip.F_sz_um / 0.065) * (interface_ip.F_sz_um / 0.065);
93 //Area estimation based on average of die photo from Niagara 2 and
94 //Cadence ChipEstimate hard IP @65nm.
95 //SerDer is very hard to scale
96 SerDer_area = (1.39 + 0.36) * (interface_ip.F_sz_um /
97 0.065);//* (interface_ip.F_sz_um/0.065);
98 } else {
99 //Low power implementations are mostly from Cadence ChipEstimator;
100 //Ignore the multiple IP effect
101 // ---When there are multiple IP (same kind or not) selected, Cadence
102 //ChipEstimator results are not a simple summation of all IPs.
103 //Ignore this effect
104 mac_area = 0.24 * (interface_ip.F_sz_um / 0.065) *
105 (interface_ip.F_sz_um / 0.065);
106 frontend_area = 0.1 * (interface_ip.F_sz_um / 0.065) *
107 (interface_ip.F_sz_um / 0.065);//Frontend is the PCS layer
108 SerDer_area = 0.35 * (interface_ip.F_sz_um / 0.065) *
109 (interface_ip.F_sz_um/0.065);
110 //Compare 130um implementation in "A 1.2-V-Only 900-mW 10 Gb Ethernet
111 //Transceiver and XAUI Interface With Robust VCO Tuning Technique"
112 //and the ChipEstimator XAUI PHY hard IP, confirm that even PHY can
113 //scale perfectly with the technology
114 }
115
116 //total area
117 output_data.area = (mac_area + frontend_area + SerDer_area) * 1e6;
118 }
119
120void NIUController::computeEnergy() {
121 double mac_dyn;
122 double frontend_dyn;
123 double SerDer_dyn;
124 double frontend_gates;
125 double mac_gates;
126 double SerDer_gates;
127 double NMOS_sizing;
128 double PMOS_sizing;
129 double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio();
130
131 if (niup.type == 0) { //high performance NIU
132 //Power
133 //Cadence ChipEstimate using 65nm (mac, front_end are all energy.
134 //E=P*T = P/F = 1.37/1Ghz = 1.37e-9);
135 //2.19W@1GHz fully active according to Cadence ChipEstimate @65nm
136 mac_dyn = 2.19e-9 * g_tp.peri_global.Vdd / 1.1 * g_tp.peri_global.Vdd /
137 1.1 * (interface_ip.F_sz_nm / 65.0);//niup.clockRate;
138 //Cadence ChipEstimate using 65nm soft IP;
139 frontend_dyn = 0.27e-9 * g_tp.peri_global.Vdd / 1.1 *
140 g_tp.peri_global.Vdd / 1.1 * (interface_ip.F_sz_nm / 65.0);
141 //according to "A 100mW 9.6Gb/s Transceiver in 90nm CMOS..." ISSCC 2006
142 //SerDer_dyn is power not energy, scaling from 10mw/Gb/s @90nm
143 SerDer_dyn = 0.01 * 10 * sqrt(interface_ip.F_sz_um / 0.09) *
144 g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd / 1.2;
145
146 //Cadence ChipEstimate using 65nm
147 mac_gates = 111700;
148 frontend_gates = 320000;
149 SerDer_gates = 200000;
150 NMOS_sizing = 5 * g_tp.min_w_nmos_;
151 PMOS_sizing = 5 * g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r;
152 } else {
153 //Power
154 //Cadence ChipEstimate using 65nm (mac, front_end are all energy.
155 ///E=P*T = P/F = 1.37/1Ghz = 1.37e-9);
156 //2.19W@1GHz fully active according to Cadence ChipEstimate @65nm
157 mac_dyn = 1.257e-9 * g_tp.peri_global.Vdd / 1.1 * g_tp.peri_global.Vdd
158 / 1.1 * (interface_ip.F_sz_nm / 65.0);//niup.clockRate;
159 //Cadence ChipEstimate using 65nm soft IP;
160 frontend_dyn = 0.6e-9 * g_tp.peri_global.Vdd / 1.1 *
161 g_tp.peri_global.Vdd / 1.1 * (interface_ip.F_sz_nm / 65.0);
162 //SerDer_dyn is power not energy, scaling from 216mw/10Gb/s @130nm
163 SerDer_dyn = 0.0216 * 10 * (interface_ip.F_sz_um / 0.13) *
164 g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd / 1.2;
165
166 mac_gates = 111700;
167 frontend_gates = 52000;
168 SerDer_gates = 199260;
169 NMOS_sizing = g_tp.min_w_nmos_;
170 PMOS_sizing = g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r;
171 }
172
173 //covert to energy per clock cycle of whole NIU
174 SerDer_dyn /= niup.clockRate;
175
176 power.readOp.dynamic = mac_dyn + frontend_dyn + SerDer_dyn;
177 power.readOp.leakage = (mac_gates + frontend_gates + frontend_gates) *
178 cmos_Isub_leakage(NMOS_sizing, PMOS_sizing, 2, nand) *
179 g_tp.peri_global.Vdd;//unit W
180 double long_channel_device_reduction =
181 longer_channel_device_reduction(Uncore_device);
182 power.readOp.longer_channel_leakage =
183 power.readOp.leakage * long_channel_device_reduction;
184 power.readOp.gate_leakage = (mac_gates + frontend_gates + frontend_gates) *
185 cmos_Ig_leakage(NMOS_sizing, PMOS_sizing, 2, nand) *
186 g_tp.peri_global.Vdd;//unit W
187
188 // Output power
189 output_data.subthreshold_leakage_power =
190 longer_channel_device ? power.readOp.longer_channel_leakage :
191 power.readOp.leakage;
192 output_data.gate_leakage_power = power.readOp.gate_leakage;
193 output_data.peak_dynamic_power = power.readOp.dynamic * nius.duty_cycle;
194 output_data.runtime_dynamic_energy = power.readOp.dynamic * nius.perc_load;
195}
196
197void NIUController::set_niu_param() {
198 int num_children = xml_data->nChildNode("param");
199 int i;
200 for (i = 0; i < num_children; i++) {
201 XMLNode* paramNode = xml_data->getChildNodePtr("param", &i);
202 XMLCSTR node_name = paramNode->getAttribute("name");
203 XMLCSTR value = paramNode->getAttribute("value");
204
205 if (!node_name)
206 warnMissingParamName(paramNode->getAttribute("id"));
207
208 ASSIGN_FP_IF("niu_clockRate", niup.clockRate);
209 ASSIGN_INT_IF("num_units", niup.num_units);
210 ASSIGN_INT_IF("type", niup.type);
211
212 else {
213 warnUnrecognizedParam(node_name);
214 }
215 }
216
217 // Change from MHz to Hz
218 niup.clockRate *= 1e6;
219
220 num_children = xml_data->nChildNode("stat");
221 for (i = 0; i < num_children; i++) {
222 XMLNode* statNode = xml_data->getChildNodePtr("stat", &i);
223 XMLCSTR node_name = statNode->getAttribute("name");
224 XMLCSTR value = statNode->getAttribute("value");
225
226 if (!node_name)
227 warnMissingStatName(statNode->getAttribute("id"));
228
229 ASSIGN_FP_IF("duty_cycle", nius.duty_cycle);
230 ASSIGN_FP_IF("perc_load", nius.perc_load);
231
232 else {
233 warnUnrecognizedStat(node_name);
234 }
235 }
236}
237
238PCIeController::PCIeController(XMLNode* _xml_data,
239 InputParameter* interface_ip_)
240 : McPATComponent(_xml_data, interface_ip_) {
241 name = "PCIe";
242 set_pcie_param();
243}
244
245void PCIeController::computeArea() {
246 double ctrl_area;
247 double SerDer_area;
248
249 /* Assuming PCIe is bit-slice based architecture
250 * This is the reason for /8 in both area and power calculation
251 * to get per lane numbers
252 */
253
254 if (pciep.type == 0) { //high performance PCIe
255 //Area estimation based on average of die photo from Niagara 2 and
256 //Cadence ChipEstimate @ 65nm.
257 ctrl_area = (5.2 + 0.5) / 2 * (interface_ip.F_sz_um / 0.065) *
258 (interface_ip.F_sz_um / 0.065);
259 //Area estimation based on average of die photo from Niagara 2 and
260 //Cadence ChipEstimate hard IP @65nm.
261 //SerDer is very hard to scale
262 SerDer_area = (3.03 + 0.36) * (interface_ip.F_sz_um /
263 0.065);//* (interface_ip.F_sz_um/0.065);
264 } else {
265 ctrl_area = 0.412 * (interface_ip.F_sz_um / 0.065) *
266 (interface_ip.F_sz_um / 0.065);
267 //Area estimation based on average of die photo from Niagara 2, and
268 //Cadence ChipEstimate @ 65nm.
269 SerDer_area = 0.36 * (interface_ip.F_sz_um / 0.065) *
270 (interface_ip.F_sz_um / 0.065);
271 }
272
273 // Total area
274 output_data.area = ((ctrl_area + (pciep.withPHY ? SerDer_area : 0)) / 8 *
275 pciep.num_channels) * 1e6;
276}
277
278void PCIeController::computeEnergy() {
279 double ctrl_dyn;
280 double SerDer_dyn;
281 double ctrl_gates;
282 double SerDer_gates = 0;
283 double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio();
284 double NMOS_sizing;
285 double PMOS_sizing;
286
287 /* Assuming PCIe is bit-slice based architecture
288 * This is the reason for /8 in both area and power calculation
289 * to get per lane numbers
290 */
291
292 if (pciep.type == 0) { //high performance PCIe
293 //Power
294 //Cadence ChipEstimate using 65nm the controller includes everything: the PHY, the data link and transaction layer
295 ctrl_dyn = 3.75e-9 / 8 * g_tp.peri_global.Vdd / 1.1 *
296 g_tp.peri_global.Vdd / 1.1 * (interface_ip.F_sz_nm / 65.0);
297 // //Cadence ChipEstimate using 65nm soft IP;
298 // frontend_dyn = 0.27e-9/8*g_tp.peri_global.Vdd/1.1*g_tp.peri_global.Vdd/1.1*(interface_ip.F_sz_nm/65.0);
299 //SerDer_dyn is power not energy, scaling from 10mw/Gb/s @90nm
300 //PCIe 2.0 max per lane speed is 4Gb/s
301 SerDer_dyn = 0.01 * 4 * (interface_ip.F_sz_um /0.09) *
302 g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd /1.2;
303
304 //Cadence ChipEstimate using 65nm
305 ctrl_gates = 900000 / 8 * pciep.num_channels;
306 // frontend_gates = 120000/8;
307 // SerDer_gates = 200000/8;
308 NMOS_sizing = 5 * g_tp.min_w_nmos_;
309 PMOS_sizing = 5 * g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r;
310 } else {
311 //Power
312 //Cadence ChipEstimate using 65nm the controller includes everything: the PHY, the data link and transaction layer
313 ctrl_dyn = 2.21e-9 / 8 * g_tp.peri_global.Vdd / 1.1 *
314 g_tp.peri_global.Vdd / 1.1 * (interface_ip.F_sz_nm / 65.0);
315 // //Cadence ChipEstimate using 65nm soft IP;
316 // frontend_dyn = 0.27e-9/8*g_tp.peri_global.Vdd/1.1*g_tp.peri_global.Vdd/1.1*(interface_ip.F_sz_nm/65.0);
317 //SerDer_dyn is power not energy, scaling from 10mw/Gb/s @90nm
318 //PCIe 2.0 max per lane speed is 4Gb/s
319 SerDer_dyn = 0.01 * 4 * (interface_ip.F_sz_um / 0.09) *
320 g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd /1.2;
321
322 //Cadence ChipEstimate using 65nm
323 ctrl_gates = 200000 / 8 * pciep.num_channels;
324 // frontend_gates = 120000/8;
325 SerDer_gates = 200000 / 8 * pciep.num_channels;
326 NMOS_sizing = g_tp.min_w_nmos_;
327 PMOS_sizing = g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r;
328
329 }
330
331 //covert to energy per clock cycle
332 SerDer_dyn /= pciep.clockRate;
333
334 power.readOp.dynamic = (ctrl_dyn + (pciep.withPHY ? SerDer_dyn : 0)) *
335 pciep.num_channels;
336 power.readOp.leakage = (ctrl_gates + (pciep.withPHY ? SerDer_gates : 0)) *
337 cmos_Isub_leakage(NMOS_sizing, PMOS_sizing, 2, nand) *
338 g_tp.peri_global.Vdd;//unit W
339 double long_channel_device_reduction =
340 longer_channel_device_reduction(Uncore_device);
341 power.readOp.longer_channel_leakage =
342 power.readOp.leakage * long_channel_device_reduction;
343 power.readOp.gate_leakage = (ctrl_gates +
344 (pciep.withPHY ? SerDer_gates : 0)) *
345 cmos_Ig_leakage(NMOS_sizing, PMOS_sizing, 2, nand) *
346 g_tp.peri_global.Vdd;//unit W
347
348 // Output power
349 output_data.subthreshold_leakage_power =
350 longer_channel_device ? power.readOp.longer_channel_leakage :
351 power.readOp.leakage;
352 output_data.gate_leakage_power = power.readOp.gate_leakage;
353 output_data.peak_dynamic_power = power.readOp.dynamic * pcies.duty_cycle;
354 output_data.runtime_dynamic_energy =
355 power.readOp.dynamic * pcies.perc_load;
356}
357
358void PCIeController::set_pcie_param() {
359 int num_children = xml_data->nChildNode("param");
360 int i;
361 for (i = 0; i < num_children; i++) {
362 XMLNode* paramNode = xml_data->getChildNodePtr("param", &i);
363 XMLCSTR node_name = paramNode->getAttribute("name");
364 XMLCSTR value = paramNode->getAttribute("value");
365
366 if (!node_name)
367 warnMissingParamName(paramNode->getAttribute("id"));
368
369 ASSIGN_FP_IF("pcie_clockRate", pciep.clockRate);
370 ASSIGN_INT_IF("num_units", pciep.num_units);
371 ASSIGN_INT_IF("num_channels", pciep.num_channels);
372 ASSIGN_INT_IF("type", pciep.type);
373 ASSIGN_ENUM_IF("withPHY", pciep.withPHY, bool);
374
375 else {
376 warnUnrecognizedParam(node_name);
377 }
378 }
379
380 // Change from MHz to Hz
381 pciep.clockRate *= 1e6;
382
383 num_children = xml_data->nChildNode("stat");
384 for (i = 0; i < num_children; i++) {
385 XMLNode* statNode = xml_data->getChildNodePtr("stat", &i);
386 XMLCSTR node_name = statNode->getAttribute("name");
387 XMLCSTR value = statNode->getAttribute("value");
388
389 if (!node_name)
390 warnMissingStatName(statNode->getAttribute("id"));
391
392 ASSIGN_FP_IF("duty_cycle", pcies.duty_cycle);
393 ASSIGN_FP_IF("perc_load", pcies.perc_load);
394
395 else {
396 warnUnrecognizedStat(node_name);
397 }
398 }
399}
400
401FlashController::FlashController(XMLNode* _xml_data,
402 InputParameter* interface_ip_)
403 : McPATComponent(_xml_data, interface_ip_) {
404 name = "Flash Controller";
405 set_fc_param();
406}
407
408void FlashController::computeArea() {
409 double ctrl_area;
410 double SerDer_area;
411
412 /* Assuming Flash is bit-slice based architecture
413 * This is the reason for /8 in both area and power calculation
414 * to get per lane numbers
415 */
416
417 if (fcp.type == 0) { //high performance flash controller
418 cout << "Current McPAT does not support high performance flash "
419 << "controller since even low power designs are enough for "
420 << "maintain throughput" <<endl;
421 exit(0);
422 } else {
423 ctrl_area = 0.243 * (interface_ip.F_sz_um / 0.065) *
424 (interface_ip.F_sz_um / 0.065);
425 //Area estimation based on Cadence ChipEstimate @ 65nm: NANDFLASH-CTRL
426 //from CAST
427 SerDer_area = 0.36 / 8 * (interface_ip.F_sz_um / 0.065) *
428 (interface_ip.F_sz_um / 0.065);
429 }
430
431 double number_channel = 1 + (fcp.num_channels - 1) * 0.2;
432 output_data.area = (ctrl_area + (fcp.withPHY ? SerDer_area : 0)) *
433 1e6 * number_channel;
434}
435
436void FlashController::computeEnergy() {
437 double ctrl_dyn;
438 double SerDer_dyn;
439 double ctrl_gates;
440 double SerDer_gates;
441 double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio();
442 double NMOS_sizing;
443 double PMOS_sizing;
444
445 /* Assuming Flash is bit-slice based architecture
446 * This is the reason for /8 in both area and power calculation
447 * to get per lane numbers
448 */
449
450 if (fcp.type == 0) { //high performance flash controller
451 cout << "Current McPAT does not support high performance flash "
452 << "controller since even low power designs are enough for "
453 << "maintain throughput" <<endl;
454 exit(0);
455 NMOS_sizing = 5 * g_tp.min_w_nmos_;
456 PMOS_sizing = 5 * g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r;
457 } else {
458 //based On PCIe PHY TSMC65GP from Cadence ChipEstimate @ 65nm, it
459 //support 8x lanes with each lane speed up to 250MB/s (PCIe1.1x).
460 //This is already saturate the 200MB/s of the flash controller core
461 //above.
462 ctrl_gates = 129267;
463 SerDer_gates = 200000 / 8;
464 NMOS_sizing = g_tp.min_w_nmos_;
465 PMOS_sizing = g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r;
466
467 //Power
468 //Cadence ChipEstimate using 65nm the controller 125mW for every
469 //200MB/s This is power not energy!
470 ctrl_dyn = 0.125 * g_tp.peri_global.Vdd / 1.1 * g_tp.peri_global.Vdd /
471 1.1 * (interface_ip.F_sz_nm / 65.0);
472 //SerDer_dyn is power not energy, scaling from 10mw/Gb/s @90nm
473 SerDer_dyn = 0.01 * 1.6 * (interface_ip.F_sz_um / 0.09) *
474 g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd / 1.2;
475 //max Per controller speed is 1.6Gb/s (200MB/s)
476 }
477
478 double number_channel = 1 + (fcp.num_channels - 1) * 0.2;
479 power.readOp.dynamic = (ctrl_dyn + (fcp.withPHY ? SerDer_dyn : 0)) *
480 number_channel;
481 power.readOp.leakage = ((ctrl_gates + (fcp.withPHY ? SerDer_gates : 0)) *
482 number_channel) *
483 cmos_Isub_leakage(NMOS_sizing, PMOS_sizing, 2, nand) *
484 g_tp.peri_global.Vdd;//unit W
485 double long_channel_device_reduction =
486 longer_channel_device_reduction(Uncore_device);
487 power.readOp.longer_channel_leakage =
488 power.readOp.leakage * long_channel_device_reduction;
489 power.readOp.gate_leakage =
490 ((ctrl_gates + (fcp.withPHY ? SerDer_gates : 0)) * number_channel) *
491 cmos_Ig_leakage(NMOS_sizing, PMOS_sizing, 2, nand) *
492 g_tp.peri_global.Vdd;//unit W
493
494 // Output power
495 output_data.subthreshold_leakage_power =
496 longer_channel_device ? power.readOp.longer_channel_leakage :
497 power.readOp.leakage;
498 output_data.gate_leakage_power = power.readOp.gate_leakage;
499 output_data.peak_dynamic_power = power.readOp.dynamic * fcs.duty_cycle;
500 output_data.runtime_dynamic_energy = power.readOp.dynamic * fcs.perc_load;
501}
502
503void FlashController::set_fc_param()
504{
505 int num_children = xml_data->nChildNode("param");
506 int i;
507 for (i = 0; i < num_children; i++) {
508 XMLNode* paramNode = xml_data->getChildNodePtr("param", &i);
509 XMLCSTR node_name = paramNode->getAttribute("name");
510 XMLCSTR value = paramNode->getAttribute("value");
511
512 if (!node_name)
513 warnMissingParamName(paramNode->getAttribute("id"));
514
515 ASSIGN_INT_IF("num_channels", fcp.num_channels);
516 ASSIGN_INT_IF("type", fcp.type);
517 ASSIGN_ENUM_IF("withPHY", fcp.withPHY, bool);
518
519 else {
520 warnUnrecognizedParam(node_name);
521 }
522 }
523
524 num_children = xml_data->nChildNode("stat");
525 for (i = 0; i < num_children; i++) {
526 XMLNode* statNode = xml_data->getChildNodePtr("stat", &i);
527 XMLCSTR node_name = statNode->getAttribute("name");
528 XMLCSTR value = statNode->getAttribute("value");
529
530 if (!node_name)
531 warnMissingStatName(statNode->getAttribute("id"));
532
533 ASSIGN_FP_IF("duty_cycle", fcs.duty_cycle);
534 ASSIGN_FP_IF("perc_load", fcs.perc_load);
535
536 else {
537 warnUnrecognizedStat(node_name);
538 }
539 }
540}