forked from kmurray/libargparse
-
Notifications
You must be signed in to change notification settings - Fork 0
/
argparse_test.cpp
580 lines (527 loc) · 29.6 KB
/
argparse_test.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
#include "argparse.hpp"
#include "argparse_util.hpp"
using argparse::ArgValue;
using argparse::ConvertedValue;
#define TEST
struct Args {
ArgValue<std::string> architecture_file;
ArgValue<std::string> circuit;
ArgValue<bool> disp;
ArgValue<bool> auto_value;
ArgValue<bool> pack;
ArgValue<bool> place;
ArgValue<bool> route;
ArgValue<bool> show_help;
ArgValue<bool> timing_analysis;
ArgValue<const char*> slack_definition;
ArgValue<bool> echo_files;
ArgValue<bool> verify_file_digests;
ArgValue<unsigned> num_workers;
ArgValue<std::string> blif_file;
ArgValue<std::string> net_file;
ArgValue<std::string> place_file;
ArgValue<std::string> route_file;
ArgValue<std::string> sdc_file;
ArgValue<std::string> outfile_prefix;
ArgValue<bool> absorb_buffer_luts;
ArgValue<bool> sweep_dangling_primary_ios;
ArgValue<bool> sweep_dangling_nets;
ArgValue<bool> sweep_dangling_blocks;
ArgValue<bool> sweep_constant_primary_outputs;
ArgValue<bool> connection_driven_clustering;
ArgValue<bool> allow_unrelated_clustering;
ArgValue<float> alpha_clustering;
ArgValue<float> beta_clustering;
ArgValue<bool> timing_driven_clustering;
ArgValue<std::string> cluster_seed_type;
ArgValue<size_t> seed;
ArgValue<bool> enable_timing_computations;
ArgValue<float> inner_num;
ArgValue<float> init_t;
ArgValue<float> exit_t;
ArgValue<float> alpha_t;
ArgValue<std::string> fix_pins;
ArgValue<std::string> place_algorithm;
ArgValue<size_t> place_chan_width;
ArgValue<float> timing_tradeoff;
ArgValue<int> recompute_crit_iter;
ArgValue<int> inner_loop_recompute_divider;
ArgValue<float> td_place_exp_first;
ArgValue<float> td_place_exp_last;
ArgValue<int> max_router_iterations;
ArgValue<float> first_iter_pres_fac;
ArgValue<float> initial_pres_fac;
ArgValue<float> pres_fac_mult;
ArgValue<float> acc_fac;
ArgValue<int> bb_factor;
ArgValue<std::string> base_cost_type;
ArgValue<float> bend_cost;
ArgValue<std::string> route_type;
ArgValue<size_t> route_chan_width;
ArgValue<size_t> min_route_chan_width_hint;
ArgValue<bool> verify_binary_search;
ArgValue<std::string> router_algorithm;
ArgValue<int> min_incremental_reroute_fanout;
ArgValue<float> astar_fac;
ArgValue<float> max_criticality;
ArgValue<float> criticality_exp;
ArgValue<std::string> routing_failure_predictor;
ArgValue<bool> power;
ArgValue<std::string> tech_properties_file;
ArgValue<std::string> activity_file;
ArgValue<bool> full_stats;
ArgValue<bool> gen_post_synthesis_netlist;
ArgValue<std::vector<float>> one_or_more;
ArgValue<std::vector<float>> zero_or_more;
};
bool expect_pass(argparse::ArgumentParser& parser, std::vector<std::string> cmd_line);
bool expect_fail(argparse::ArgumentParser& parser, std::vector<std::string> cmd_line);
struct OnOff {
ConvertedValue<bool> from_str(std::string str) {
ConvertedValue<bool> converted_value;
if (str == "on") converted_value.set_value(true);
else if (str == "off") converted_value.set_value(false);
else converted_value.set_error("Invalid argument value");
return converted_value;
}
ConvertedValue<std::string> to_str(bool val) {
ConvertedValue<std::string> converted_value;
if (val) converted_value.set_value("on");
else converted_value.set_value("off");
return converted_value;
}
std::vector<std::string> default_choices() {
return {"on", "off"};
}
};
int main(
int
#ifndef TEST
argc
#endif
, const char** argv) {
Args args;
auto parser = argparse::ArgumentParser(argv[0], "Test parser for libargparse");
parser.epilog("This is the epilog");
auto& pos_grp = parser.add_argument_group("positional arguments");
pos_grp.add_argument(args.architecture_file, "architecture")
.help("FPGA Architecture description file (XML)");
pos_grp.add_argument(args.circuit, "circuit")
.help("Circuit file (or circuit name if --blif_file specified)");
auto& stage_grp = parser.add_argument_group("stage options");
stage_grp.add_argument<bool,OnOff>(args.pack, "--pack")
.help("Run packing")
.action(argparse::Action::STORE_TRUE)
.default_value("off");
stage_grp.add_argument<bool,OnOff>(args.place, "--place")
.help("Run placement")
.action(argparse::Action::STORE_TRUE)
.default_value("off");
stage_grp.add_argument<bool,OnOff>(args.route, "--route")
.help("Run routing")
.action(argparse::Action::STORE_TRUE)
.default_value("off");
stage_grp.add_argument<bool,OnOff>(args.route, "--analysis")
.help("Run analysis")
.action(argparse::Action::STORE_TRUE)
.required(true)
.default_value("off");
stage_grp.epilog("If none of the stage options are specified, all stages are run.\n"
"Analysis is always run after routing.");
auto& gfx_grp = parser.add_argument_group("graphics options");
gfx_grp.add_argument<bool,OnOff>(args.disp, "--disp")
.help("Enable or disable interactive graphics")
.default_value("off");
gfx_grp.add_argument(args.auto_value, "--auto")
.help("Controls how often VPR pauses for interactive"
" graphics (requiring Proceed to be clicked)."
" Higher values pause less frequently")
.default_value("1")
.choices({"0", "1", "2"})
.show_in(argparse::ShowIn::HELP_ONLY);
auto& gen_grp = parser.add_argument_group("general options");
gen_grp.add_argument(args.show_help, "--help", "-h")
.help("Show this help message then exit")
.action(argparse::Action::HELP);
gen_grp.add_argument<bool,OnOff>(args.timing_analysis, "--timing_analysis")
.help("Controls whether timing analysis (and timing driven optimizations) are enabled.")
.default_value("on") ;
gen_grp.add_argument(args.slack_definition, "--slack_definition")
.help("Sets the slack definition used by the classic timing analyyzer")
.default_value("R")
.choices({"R", "I", "S", "G", "C", "N"})
.show_in(argparse::ShowIn::HELP_ONLY);
gen_grp.add_argument<bool,OnOff>(args.echo_files, "--echo_file")
.help("Generate echo files of key internal data structures."
" Useful for debugging VPR, and typically end in .echo")
.default_value("off")
.show_in(argparse::ShowIn::HELP_ONLY);
gen_grp.add_argument<bool,OnOff>(args.verify_file_digests, "--verify_file_digests")
.help("Verify that files loaded by VPR (e.g. architecture, netlist,"
" previous packing/placement/routing) are consistent")
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);
gen_grp.add_argument(args.num_workers, "--num_workers", "-j")
.help("Number of parallel workers")
.default_value("1")
.show_in(argparse::ShowIn::HELP_ONLY);
auto& file_grp = parser.add_argument_group("filename options");
file_grp.add_argument(args.blif_file, "--blif_file")
.help("Path to technology mapped circuit in BLIF format")
.show_in(argparse::ShowIn::HELP_ONLY);
file_grp.add_argument(args.net_file, "--net_file")
.help("Path to packed netlist file")
.show_in(argparse::ShowIn::HELP_ONLY);
file_grp.add_argument(args.place_file, "--place_file")
.help("Path to placement file")
.show_in(argparse::ShowIn::HELP_ONLY);
file_grp.add_argument(args.route_file, "--route_file")
.help("Path to routing file")
.show_in(argparse::ShowIn::HELP_ONLY);
file_grp.add_argument(args.sdc_file, "--sdc_file")
.help("Path to timing constraints file in SDC format")
.show_in(argparse::ShowIn::HELP_ONLY);
file_grp.add_argument(args.outfile_prefix, "--outfile_prefix")
.help("Prefix for output files")
.show_in(argparse::ShowIn::HELP_ONLY);
auto& netlist_grp = parser.add_argument_group("netlist options");
netlist_grp.add_argument<bool,OnOff>(args.absorb_buffer_luts, "--absorb_buffer_luts")
.help("Controls whether LUTS programmed as buffers are absorbed by downstream logic")
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);
netlist_grp.add_argument<bool,OnOff>(args.sweep_dangling_primary_ios, "--sweep_dangling_primary_ios")
.help("Controls whether dangling primary inputs and outputs are removed from the netlist")
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);
netlist_grp.add_argument<bool,OnOff>(args.sweep_dangling_nets, "--sweep_dangling_nets")
.help("Controls whether dangling nets are removed from the netlist")
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);
netlist_grp.add_argument<bool,OnOff>(args.sweep_dangling_blocks, "--sweep_dangling_blocks")
.help("Controls whether dangling blocks are removed from the netlist")
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);
netlist_grp.add_argument<bool,OnOff>(args.sweep_constant_primary_outputs, "--sweep_constant_primary_outputs")
.help("Controls whether primary outputs driven by constant values are removed from the netlist")
.default_value("off")
.show_in(argparse::ShowIn::HELP_ONLY);
auto& pack_grp = parser.add_argument_group("packing options");
pack_grp.add_argument<bool,OnOff>(args.connection_driven_clustering, "--connection_driven_clustering")
.help("Controls whether or not packing prioritizes the absorption of nets with fewer"
" connections into a complex logic block over nets with more connections")
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);
pack_grp.add_argument<bool,OnOff>(args.allow_unrelated_clustering, "--allow_unrelated_clustering")
.help("Controls whether or not primitives with no attraction to the current cluster"
" can be packed into it")
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);
pack_grp.add_argument(args.alpha_clustering, "--alpha_clustering")
.help("Parameter that weights the optimization of timing vs area. 0.0 focuses solely on"
" area, 1.0 solely on timing.")
.default_value("0.75")
.show_in(argparse::ShowIn::HELP_ONLY);
pack_grp.add_argument(args.beta_clustering, "--beta_clustering")
.help("Parameter that weights the absorption of small nets vs signal sharing."
" 0.0 focuses solely on sharing, 1.0 solely on small net absoprtion."
" Only meaningful if --connection_driven_clustering=on")
.default_value("0.9")
.show_in(argparse::ShowIn::HELP_ONLY);
pack_grp.add_argument<bool,OnOff>(args.timing_driven_clustering, "--timing_driven_clustering")
.help("Controls whether custering optimizes for timing")
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);
pack_grp.add_argument(args.cluster_seed_type, "--cluster_seed_type")
.help("Controls how primitives are chosen as seeds."
" (Default: blend if timing driven, max_inputs otherwise)")
.choices({"blend", "timing", "max_inputs"})
.show_in(argparse::ShowIn::HELP_ONLY);
auto& place_grp = parser.add_argument_group("placement options");
place_grp.add_argument(args.seed, "--seed")
.help("Placement random number generator seed")
.default_value("1")
.show_in(argparse::ShowIn::HELP_ONLY);
place_grp.add_argument<bool,OnOff>(args.enable_timing_computations, "--enable_timing_computations")
.help("Displays delay statistics even if placement is not timing driven")
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);
place_grp.add_argument(args.inner_num, "--inner_num")
.help("Controls number of moves per temperature: inner_num * num_blocks ^ (4/3)")
.default_value("10.0")
.show_in(argparse::ShowIn::HELP_ONLY);
place_grp.add_argument(args.init_t, "--init_t")
.help("Initial temperature for manual annealing schedule")
.default_value("100.0")
.show_in(argparse::ShowIn::HELP_ONLY);
place_grp.add_argument(args.exit_t, "--exit_t")
.help("Temperature at which annealing which terminate for manual annealing schedule")
.default_value("0.01")
.show_in(argparse::ShowIn::HELP_ONLY);
place_grp.add_argument(args.alpha_t, "--alpha_t")
.help("Temperature scaling factor for manual annealing schedule."
" Old temperature is multiplied by alpha_t")
.default_value("0.01")
.show_in(argparse::ShowIn::HELP_ONLY);
place_grp.add_argument(args.fix_pins, "--fix_pins")
.help("Fixes I/O pad locations during placement."
" Can be 'random' for a random initial assignment,"
" 'off' to allow the place to optimize pad locations,"
" or a file specifying the pad locations.")
.default_value("off")
.show_in(argparse::ShowIn::HELP_ONLY);
place_grp.add_argument(args.place_algorithm, "--place_algorithm")
.help("Controls which placement algorithm is used")
.default_value("path_timing_driven")
.choices({"bounding_box", "path_timing_driven"})
.show_in(argparse::ShowIn::HELP_ONLY);
place_grp.add_argument(args.place_chan_width, "--place_chan_width")
.help("Sets the assumed channel width during placement")
.default_value("100")
.show_in(argparse::ShowIn::HELP_ONLY);
auto& place_timing_grp = parser.add_argument_group("timing-driven placement options");
place_timing_grp.add_argument(args.timing_tradeoff, "--timing_tradeoff")
.help("Trade-off control between delay and wirelength during placement."
" 0.0 focuses completely on wirelength, 1.0 completely on timing")
.default_value("0.5")
.show_in(argparse::ShowIn::HELP_ONLY);
place_timing_grp.add_argument(args.recompute_crit_iter, "--recompute_crit_iter")
.help("Controls how many temperature updates occur between timing analysis during placement")
.default_value("1")
.show_in(argparse::ShowIn::HELP_ONLY);
place_timing_grp.add_argument(args.inner_loop_recompute_divider, "--inner_loop_recompute_divider")
.help("Controls how many timing analysies are perform per temperature during placement")
.default_value("0")
.show_in(argparse::ShowIn::HELP_ONLY);
place_timing_grp.add_argument(args.td_place_exp_first, "--td_place_exp_first")
.help("Controls how critical a connection is as a function of slack at the start of placement."
" A value of zero treats all connections as equally critical (regardless of slack)."
" Values larger than 1.0 cause low slack connections to be treated more critically."
" The value increases to --td_place_exp_last during placement.")
.default_value("1.0")
.show_in(argparse::ShowIn::HELP_ONLY);
place_timing_grp.add_argument(args.td_place_exp_last, "--td_place_exp_last")
.help("Controls how critical a connection is as a function of slack at the end of placement.")
.default_value("8.0")
.show_in(argparse::ShowIn::HELP_ONLY);
auto& route_grp = parser.add_argument_group("routing options");
route_grp.add_argument(args.max_router_iterations, "--max_route_iterations")
.help("Maximum number of Pathfinder-based routing iterations before the circuit is"
" declared unroutable at a given channel width")
.default_value("50")
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.initial_pres_fac, "--first_iter_pres_fac")
.help("Sets the present overuse factor for the first routing iteration")
.default_value("0.0")
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.initial_pres_fac, "--initial_pres_fac")
.help("Sets the present overuse factor for the second routing iteration")
.default_value("0.5")
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.pres_fac_mult, "--pres_fac_mult")
.help("Sets the growth factor by which the present overuse penalty factor is"
" multiplied after each routing iteration")
.default_value("1.3")
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.acc_fac, "--acc_fac")
.help("Specifies the accumulated overuse factor (historical congestion cost factor)")
.default_value("1.0")
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.bb_factor, "--bb_factor")
.help("Sets the distance (in channels) outside a connection's bounding box which can be explored")
.default_value("3")
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.base_cost_type, "--base_cost_type")
.help("Sets the basic cost of routing resource nodes:\n"
" * demand_only: based on expected demand of node type\n"
" * delay_normalized: like demand_only but normalized to magnitude of typical routing resource delay\n"
"(Default: demand_only for bread-first router, delay_normalized for timing-driven router)")
.choices({"demand_only", "delay_normalized"})
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.bend_cost, "--bend_cost")
.help("The cost of a bend. (Default: 1.0 for global routing, 0.0 for detailed routing)")
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.route_type, "--route_type")
.help("Specifies whether global, or combined global and detailed routing is performed.")
.choices({"global", "detailed"})
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.route_chan_width, "--route_chan_width")
.help("Specifies a fixed channel width to route at.")
.metavar("CHANNEL_WIDTH");
route_grp.add_argument(args.min_route_chan_width_hint, "--min_route_chan_width_hint")
.help("Hint to the router what the minimum routable channel width is."
" Good hints can speed-up determining the minimum channel width.")
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument<bool,OnOff>(args.verify_binary_search, "--verify_binary_search")
.help("Force the router to verify the minimum channel width by routing at"
" consecutively lower channel widths until two consecutive failures are observed.")
.default_value("off")
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.router_algorithm, "--router_algorithm")
.help("Specifies the router algorithm to use.\n"
" * breadth_first: focuses solely on routability\n"
" * timing driven: focuses on routability and circuit speed\n")
.default_value("timing_driven")
.choices({"breadth_first", "timing_driven"})
.show_in(argparse::ShowIn::HELP_ONLY);
route_grp.add_argument(args.min_incremental_reroute_fanout, "--min_incremental_reroute_fanout")
.help("The net fanout thershold above which nets will be re-routed incrementally.")
.default_value("64")
.show_in(argparse::ShowIn::HELP_ONLY);
auto& route_timing_grp = parser.add_argument_group("timing-driven routing options");
route_timing_grp.add_argument(args.astar_fac, "--astar_fac")
.help("How aggressive the directed search used by the timing-driven router is."
" Values between 1 and 2 are resonable; higher values trade some quality for reduced run-time")
.default_value("1.2")
.show_in(argparse::ShowIn::HELP_ONLY);
route_timing_grp.add_argument(args.max_criticality, "--max_criticality")
.help("Sets the maximum fraction of routing cost derived from delay (vs routability) for any net."
" 0.0 means no attention is paid to delay, 1.0 means nets on the critical path ignore congestion")
.default_value("0.99")
.show_in(argparse::ShowIn::HELP_ONLY);
route_timing_grp.add_argument(args.criticality_exp, "--criticality_exp")
.help("Controls the delay-routability trade-off for nets as a function of slack."
" 0.0 implies all nets treated equally regardless of slack."
" At large values (>> 1) only nets on the critical path will consider delay.")
.default_value("1.0")
.show_in(argparse::ShowIn::HELP_ONLY);
route_timing_grp.add_argument(args.routing_failure_predictor, "--routing_failure_predictor")
.help("Controls how aggressively the router will predict a routing as unsuccessful"
" and give up early. This can significantly reducing the run-time required"
" to find the minimum channel width).\n"
" * safe: Only abort when it is extremely unlikely a routing will succeed\n"
" * aggressive: Further reduce run-time by giving up earlier. This may increase the reported minimum channel width\n"
" * off: Only abort when the maximum number of iterations is reached\n")
.default_value("safe")
.choices({"safe", "aggressive", "off"})
.show_in(argparse::ShowIn::HELP_ONLY);
auto& analysis_grp = parser.add_argument_group("analysis options");
analysis_grp.add_argument<bool,OnOff>(args.full_stats, "--full_stats")
.help("Print extra statistics about the circuit and it's routing (useful for wireability analysis)")
.default_value("off")
.show_in(argparse::ShowIn::HELP_ONLY);
analysis_grp.add_argument<bool,OnOff>(args.gen_post_synthesis_netlist, "--gen_post_synthesis_netlist")
.help("Generates the post-synthesis netlist (in BLIF and Verilog) along with delay information (in SDF)."
" Used for post-implementation simulation and verification")
.default_value("off")
.show_in(argparse::ShowIn::HELP_ONLY);
auto& power_grp = parser.add_argument_group("power analysis options");
power_grp.add_argument<bool,OnOff>(args.power, "--power")
.help("Enable power estimation")
.action(argparse::Action::STORE_TRUE)
.default_value("off")
.show_in(argparse::ShowIn::HELP_ONLY);
power_grp.add_argument(args.tech_properties_file, "--tech_properties_file")
.help("XML file containing CMOS technology properties (see documentation).")
.show_in(argparse::ShowIn::HELP_ONLY);
power_grp.add_argument(args.activity_file, "--activity_file")
.help("Signal activities file for all nets (see documentation).")
.show_in(argparse::ShowIn::HELP_ONLY);
auto& test_grp = parser.add_argument_group("test options");
test_grp.add_argument(args.one_or_more, "--one_or_more")
.nargs('+');
test_grp.add_argument(args.zero_or_more, "--zero_or_more")
.nargs('*');
#ifndef TEST
auto specified_args = parser.parse_args(argc, argv);
for(auto& arg : specified_args) {
std::cout << "Group: " << arg->group_name() << " Specified argument: " << arg->long_option();
auto short_opt = arg->short_option();
if (!short_opt.empty()) {
std::cout << "/" << short_opt;
}
std::cout << "\n";
}
return 0;
#else
parser.print_help();
std::cout << "\n";
std::vector<std::vector<std::string>> pass_cases = {
{"my_arch1.xml", "my_circuit1.blif", "--analysis"},
{"my_arch2.xml", "my_circuit2.blif", "--analysis", "--pack"},
{"my_arch3.xml", "my_circuit3.blif", "--analysis", "--timing_analysis", "on"},
{"my_arch4.xml", "my_circuit4.blif", "--analysis", "--route_chan_width", "300"},
{"my_arch5.xml", "my_circuit5.blif", "--analysis", "--criticality_exp", "2"}, //Float from integer
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "--criticality_exp", "2.0"}, //Float
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "-j", "3"},
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "-j3"}, //No-space for single letter arg
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "-j 3"}, //Space in short arg (but one string)
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "-j3", "--analysis"}, //Space in short arg (but one string)
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "--one_or_more", "3.24"}, //Single value argument
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "--one_or_more", "3.24", "10", "29"}, //Multiple values
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "--zero_or_more"}, //No values
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "--zero_or_more", "234"}, //One values
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "--zero_or_more", "234", "254", "1.23"}, //Multiple values
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "--zero_or_more", "234", "254", "1.23", "--one_or_more", "284"}, //* followed by +
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "--zero_or_more", "--one_or_more", "284"}, //* followed by +
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "--one_or_more", "284", "--zero_or_more", }, //+ followed by *
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "--one_or_more", "284", "--zero_or_more", "798"}, //+ followed by *
{"my_arch6.xml", "--analysis", "--one_or_more", "3.24", "10", "29", "my_circuit6.blif"}, //positional after nargs='+'
{"my_arch6.xml", "--analysis", "--one_or_more", "3.24", "10", "29", "my_circuit6.blif"}, //positional after nargs='+'
{"my_arch6.xml", "--analysis", "--zero_or_more", "3.24", "10", "29", "my_circuit6.blif"}, //positional after nargs='*'
};
int num_failed = 0;
for(const auto& cmd_line : pass_cases) {
bool pass = expect_pass(parser, cmd_line);
if(!pass) {
std::cout << " Failed to parse: '" << argparse::join(cmd_line, " ") << "'" << std::endl;
++num_failed;
}
}
std::vector<std::vector<std::string>> fail_cases = {
{"--analysis"}, //Missing positional
{"my_arch7.xml", "--analysis"}, //Missing positional
{"my_arch8.xml", "my_circuit8.blif", "--analysis", "extra"}, //Extra positional
{"my_arch9.xml", "my_circuit9.blif", "--analysis", "--route_chan_width"}, //Missing value to option
{"my_arch10.xml", "my_circuit10.blif", "--analysis", "--route_chan_width", "off"}, //Wrong option value type
{"my_arch11.xml", "my_circuit11.blif", "--analysis", "--disp", "132"}, //Wrong option value
{"my_arch12.xml", "my_circuit12.blif", "--analysis", "--route_chan_width", "300", "5"}, //Extra option value
{"my_arch13.xml", "my_circuit13.blif", "--analysis", "--pack", "on"}, //Extra option value to toggle option
{"my_arch14.xml", "my_circuit14.blif", "--analysis", "--route_chan_width", "300.5"}, //Type mismatch: float->int
{"my_arch15.xml", "my_circuit15.blif", "--analysis", "--criticality_exp", "on"}, //Wrong value type for float
{"my_arch16.xml", "my_circuit16.blif", "--analysis", "--slack_definition", "Z"}, //Valid type, but wrong choice
{"my_arch17.xml", "my_circuit17.blif"}, //Missing required
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "-j", "3.4"}, //Float when expected unsigned
{"my_arch6.xml", "my_circuit6.blif", "--analysis", "--one_or_more"}, //Expected at least one argument
};
for(const auto& cmd_line : fail_cases) {
bool pass = expect_fail(parser, cmd_line);
if(!pass) {
std::cout << " Parsed successfully when expected failure: '" << argparse::join(cmd_line, " ") << "'" << std::endl;
++num_failed;
}
}
if (num_failed != 0) {
std::cout << "\n";
std::cout << "FAILED: " << num_failed << " test(s)!" << "\n";
}
return num_failed;
#endif
}
bool expect_pass(argparse::ArgumentParser& parser, std::vector<std::string> cmd_line) {
try {
parser.parse_args_throw(cmd_line);
} catch(const argparse::ArgParseHelp&) {
parser.reset_destinations();
std::cout << "[PASS] Parsed help OK" << std::endl;
return true;
} catch(const argparse::ArgParseError& err) {
std::cout << "[FAIL] " << err.what() << std::endl;
parser.reset_destinations();
return false;
}
std::cout << "[PASS] Parsed OK" << std::endl;
parser.reset_destinations();
return true;
}
bool expect_fail(argparse::ArgumentParser& parser, std::vector<std::string> cmd_line) {
try {
parser.parse_args_throw(cmd_line);
} catch(const argparse::ArgParseError& err) {
std::cout << "[PASS] " << err.what() << std::endl;
parser.reset_destinations();
return true;
}
std::cout << "[FAIL] Parsed OK when expected fail" << std::endl;
parser.reset_destinations();
return false;
}