1/*
2 Copyright (c) 2005-2019 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#include "tbb/tbb_config.h"
18#include <cstdio>
19
20#include "../../common/utility/utility.h"
21
22#if __TBB_FLOW_GRAPH_CPP11_FEATURES
23
24#if _MSC_VER
25#pragma warning (disable: 4503) // Suppress "decorated name length exceeded, name was truncated" warning
26#endif
27
28#define USE_TWO_BIT_FULL_ADDER 1
29
30#include "basics.h"
31#include "one_bit_adder.h"
32#if USE_TWO_BIT_FULL_ADDER
33#include "two_bit_adder.h"
34#else
35#include "four_bit_adder.h"
36#endif
37#include "D_latch.h"
38#include <cassert>
39
40// User-specified globals with default values
41bool verbose = false; // prints bin details and other diagnostics to screen
42bool silent = false; // suppress all output except for time
43
44int get_default_num_threads() {
45 static int threads = 0;
46 if (threads == 0)
47 threads = tbb::task_scheduler_init::default_num_threads();
48 return threads;
49}
50
51#endif // __TBB_FLOW_GRAPH_CPP11_FEATURES
52
53int main(int argc, char *argv[]) {
54#if __TBB_FLOW_GRAPH_CPP11_FEATURES
55 try {
56 utility::thread_number_range threads(get_default_num_threads);
57 utility::parse_cli_arguments(argc, argv,
58 utility::cli_argument_pack()
59 //"-h" option for displaying help is present implicitly
60 .positional_arg(threads,"#threads",utility::thread_number_range_desc)
61 .arg(verbose,"verbose"," print diagnostic output to screen")
62 .arg(silent,"silent"," limits output to timing info; overrides verbose")
63 );
64
65 if (silent) verbose = false; // make silent override verbose
66
67 tick_count start = tick_count::now();
68 for(int p = threads.first; p <= threads.last; p = threads.step(p)) {
69 task_scheduler_init init(p);
70 if (!silent) cout << "graph test running on " << p << " threads.\n";
71
72 graph g;
73
74 { // test buffer: 0, 1
75 buffer b(g);
76 toggle input(g);
77 led output(g, "OUTPUT", false); // false means we will explicitly call display to see LED
78
79 make_edge(input.get_out(), input_port<0>(b));
80 make_edge(output_port<0>(b), output.get_in());
81
82 if (!silent) printf("Testing buffer...\n");
83 input.activate(); // 0
84 g.wait_for_all();
85 if (!silent) output.display();
86 assert(output.get_value() == low);
87 input.flip(); // 1
88 g.wait_for_all();
89 if (!silent) output.display();
90 assert(output.get_value() == high);
91 }
92
93 { // test not_gate: 0, 1
94 not_gate n(g);
95 toggle input(g);
96 led output(g, "OUTPUT", false);
97
98 make_edge(input.get_out(), input_port<0>(n));
99 make_edge(output_port<0>(n), output.get_in());
100
101 if (!silent) printf("Testing not_gate...\n");
102 input.activate(); // 0
103 g.wait_for_all();
104 if (!silent) output.display();
105 assert(output.get_value() == high);
106 input.flip(); // 1
107 g.wait_for_all();
108 if (!silent) output.display();
109 assert(output.get_value() == low);
110 }
111
112 { // test two-input and_gate: 00, 01, 10, 11
113 and_gate<2> a(g);
114 toggle input0(g);
115 toggle input1(g);
116 led output(g, "OUTPUT", false);
117
118 make_edge(input0.get_out(), input_port<0>(a));
119 make_edge(input1.get_out(), input_port<1>(a));
120 make_edge(output_port<0>(a), output.get_in());
121
122 if (!silent) printf("Testing and_gate...\n");
123 input1.activate(); input0.activate(); // 0 0
124 g.wait_for_all();
125 if (!silent) output.display();
126 assert(output.get_value() == low);
127 input0.flip(); // 0 1
128 g.wait_for_all();
129 if (!silent) output.display();
130 assert(output.get_value() == low);
131 input1.flip(); input0.flip(); // 1 0
132 g.wait_for_all();
133 if (!silent) output.display();
134 assert(output.get_value() == low);
135 input0.flip(); // 1 1
136 g.wait_for_all();
137 if (!silent) output.display();
138 assert(output.get_value() == high);
139 }
140
141 { // test three-input or_gate: 000, 001, 010, 100, 011, 101, 110, 111
142 or_gate<3> o(g);
143 toggle input0(g);
144 toggle input1(g);
145 toggle input2(g);
146 led output(g, "OUTPUT", false);
147
148 make_edge(input0.get_out(), input_port<0>(o));
149 make_edge(input1.get_out(), input_port<1>(o));
150 make_edge(input2.get_out(), input_port<2>(o));
151 make_edge(output_port<0>(o), output.get_in());
152
153 if (!silent) printf("Testing or_gate...\n");
154 input2.activate(); input1.activate(); input0.activate(); // 0 0 0
155 g.wait_for_all();
156 if (!silent) output.display();
157 assert(output.get_value() == low);
158 input0.flip(); // 0 0 1
159 g.wait_for_all();
160 if (!silent) output.display();
161 assert(output.get_value() == high);
162 input1.flip(); input0.flip(); // 0 1 0
163 g.wait_for_all();
164 if (!silent) output.display();
165 assert(output.get_value() == high);
166 input2.flip(); input1.flip(); // 1 0 0
167 g.wait_for_all();
168 if (!silent) output.display();
169 assert(output.get_value() == high);
170 input2.flip(); input1.flip(); input0.flip(); // 0 1 1
171 g.wait_for_all();
172 if (!silent) output.display();
173 assert(output.get_value() == high);
174 input2.flip(); input1.flip(); // 1 0 1
175 g.wait_for_all();
176 if (!silent) output.display();
177 assert(output.get_value() == high);
178 input1.flip(); input0.flip(); // 1 1 0
179 g.wait_for_all();
180 if (!silent) output.display();
181 assert(output.get_value() == high);
182 input0.flip(); // 1 1 1
183 g.wait_for_all();
184 if (!silent) output.display();
185 assert(output.get_value() == high);
186 }
187
188 { // test two-input xor_gate: 00, 01, 10, 11
189 xor_gate<2> x(g);
190 toggle input0(g);
191 toggle input1(g);
192 led output(g, "OUTPUT", false);
193
194 make_edge(input0.get_out(), input_port<0>(x));
195 make_edge(input1.get_out(), input_port<1>(x));
196 make_edge(output_port<0>(x), output.get_in());
197
198 if (!silent) printf("Testing xor_gate...\n");
199 input1.activate(); input0.activate(); // 0 0
200 g.wait_for_all();
201 if (!silent) output.display();
202 assert(output.get_value() == low);
203 input0.flip(); // 0 1
204 g.wait_for_all();
205 if (!silent) output.display();
206 assert(output.get_value() == high);
207 input1.flip(); input0.flip(); // 1 0
208 g.wait_for_all();
209 if (!silent) output.display();
210 assert(output.get_value() == high);
211 input0.flip(); // 1 1
212 g.wait_for_all();
213 if (!silent) output.display();
214 assert(output.get_value() == low);
215 }
216
217
218 { // test two-input nor_gate: 00, 01, 10, 11
219 nor_gate<2> n(g);
220 toggle input0(g);
221 toggle input1(g);
222 led output(g, "OUTPUT", false);
223
224 make_edge(input0.get_out(), input_port<0>(n));
225 make_edge(input1.get_out(), input_port<1>(n));
226 make_edge(output_port<0>(n), output.get_in());
227
228 if (!silent) printf("Testing nor_gate...\n");
229 input1.activate(); input0.activate(); // 0 0
230 g.wait_for_all();
231 if (!silent) output.display();
232 assert(output.get_value() == high);
233 input0.flip(); // 0 1
234 g.wait_for_all();
235 if (!silent) output.display();
236 assert(output.get_value() == low);
237 input1.flip(); input0.flip(); // 1 0
238 g.wait_for_all();
239 if (!silent) output.display();
240 assert(output.get_value() == low);
241 input0.flip(); // 1 1
242 g.wait_for_all();
243 if (!silent) output.display();
244 assert(output.get_value() == low);
245 }
246
247 { // test steady_signal and digit
248 steady_signal input0(g, high);
249 steady_signal input1(g, low);
250 and_gate<2> a(g);
251 or_gate<2> o(g);
252 xor_gate<2> x(g);
253 nor_gate<2> n(g);
254 digit output(g, "OUTPUT", false);
255
256 make_edge(input0.get_out(), input_port<0>(a));
257 make_edge(input1.get_out(), input_port<1>(a));
258 make_edge(output_port<0>(a), input_port<0>(output));
259
260 make_edge(input0.get_out(), input_port<0>(o));
261 make_edge(input1.get_out(), input_port<1>(o));
262 make_edge(output_port<0>(o), input_port<1>(output));
263
264 make_edge(input0.get_out(), input_port<0>(x));
265 make_edge(input1.get_out(), input_port<1>(x));
266 make_edge(output_port<0>(x), input_port<2>(output));
267
268 make_edge(input0.get_out(), input_port<0>(n));
269 make_edge(input1.get_out(), input_port<1>(n));
270 make_edge(output_port<0>(n), input_port<3>(output));
271
272 if (!silent) printf("Testing steady_signal...\n");
273 input0.activate(); // 1
274 input1.activate(); // 0
275 g.wait_for_all();
276 if (!silent) output.display();
277 assert(output.get_value() == 6);
278 }
279
280 { // test push_button
281 push_button p(g);
282 buffer b(g);
283 led output(g, "OUTPUT", !silent); // true means print all LED state changes
284
285 make_edge(p.get_out(), input_port<0>(b));
286 make_edge(output_port<0>(b), output.get_in());
287
288 if (!silent) printf("Testing push_button...\n");
289 p.press();
290 p.release();
291 p.press();
292 p.release();
293 g.wait_for_all();
294 }
295
296 { // test one_bit_adder
297 one_bit_adder my_adder(g);
298 toggle A(g);
299 toggle B(g);
300 toggle CarryIN(g);
301 led Sum(g, "SUM");
302 led CarryOUT(g, "CarryOUT");
303
304 make_edge(A.get_out(), input_port<P::A0>(my_adder));
305 make_edge(B.get_out(), input_port<P::B0>(my_adder));
306 make_edge(CarryIN.get_out(), input_port<P::CI>(my_adder));
307 make_edge(output_port<P::S0>(my_adder), Sum.get_in());
308 make_edge(output_port<1>(my_adder), CarryOUT.get_in());
309
310 A.activate();
311 B.activate();
312 CarryIN.activate();
313
314 if (!silent) printf("A on\n");
315 A.flip();
316 g.wait_for_all();
317 if (!silent) Sum.display();
318 if (!silent) CarryOUT.display();
319 assert((Sum.get_value() == high) && (CarryOUT.get_value() == low));
320
321 if (!silent) printf("A off\n");
322 A.flip();
323 g.wait_for_all();
324 if (!silent) Sum.display();
325 if (!silent) CarryOUT.display();
326 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
327
328 if (!silent) printf("B on\n");
329 B.flip();
330 g.wait_for_all();
331 if (!silent) Sum.display();
332 if (!silent) CarryOUT.display();
333 assert((Sum.get_value() == high) && (CarryOUT.get_value() == low));
334 if (!silent) printf("B off\n");
335 B.flip();
336 g.wait_for_all();
337 if (!silent) Sum.display();
338 if (!silent) CarryOUT.display();
339 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
340
341 if (!silent) printf("CarryIN on\n");
342 CarryIN.flip();
343 g.wait_for_all();
344 if (!silent) Sum.display();
345 if (!silent) CarryOUT.display();
346 assert((Sum.get_value() == high) && (CarryOUT.get_value() == low));
347 if (!silent) printf("CarryIN off\n");
348 CarryIN.flip();
349 g.wait_for_all();
350 if (!silent) Sum.display();
351 if (!silent) CarryOUT.display();
352 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
353
354 if (!silent) printf("A&B on\n");
355 A.flip();
356 B.flip();
357 g.wait_for_all();
358 if (!silent) Sum.display();
359 if (!silent) CarryOUT.display();
360 assert((Sum.get_value() == low) && (CarryOUT.get_value() == high));
361 if (!silent) printf("A&B off\n");
362 A.flip();
363 B.flip();
364 g.wait_for_all();
365 if (!silent) Sum.display();
366 if (!silent) CarryOUT.display();
367 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
368
369 if (!silent) printf("A&CarryIN on\n");
370 A.flip();
371 CarryIN.flip();
372 g.wait_for_all();
373 if (!silent) Sum.display();
374 if (!silent) CarryOUT.display();
375 assert((Sum.get_value() == low) && (CarryOUT.get_value() == high));
376 if (!silent) printf("A&CarryIN off\n");
377 A.flip();
378 CarryIN.flip();
379 g.wait_for_all();
380 if (!silent) Sum.display();
381 if (!silent) CarryOUT.display();
382 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
383
384 if (!silent) printf("B&CarryIN on\n");
385 B.flip();
386 CarryIN.flip();
387 g.wait_for_all();
388 if (!silent) Sum.display();
389 if (!silent) CarryOUT.display();
390 assert((Sum.get_value() == low) && (CarryOUT.get_value() == high));
391 if (!silent) printf("B&CarryIN off\n");
392 B.flip();
393 CarryIN.flip();
394 g.wait_for_all();
395 if (!silent) Sum.display();
396 if (!silent) CarryOUT.display();
397 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
398
399 if (!silent) printf("A&B&CarryIN on\n");
400 A.flip();
401 B.flip();
402 CarryIN.flip();
403 g.wait_for_all();
404 if (!silent) Sum.display();
405 if (!silent) CarryOUT.display();
406 assert((Sum.get_value() == high) && (CarryOUT.get_value() == high));
407 if (!silent) printf("A&B&CarryIN off\n");
408 A.flip();
409 B.flip();
410 CarryIN.flip();
411 g.wait_for_all();
412 if (!silent) Sum.display();
413 if (!silent) CarryOUT.display();
414 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
415 }
416
417#if USE_TWO_BIT_FULL_ADDER
418 { // test two_bit_adder
419 if (!silent) printf("testing two_bit adder\n");
420 two_bit_adder two_adder(g);
421 std::vector<toggle> A(2, toggle(g));
422 std::vector<toggle> B(2, toggle(g));
423 toggle CarryIN(g);
424 digit Sum(g, "SUM");
425 led CarryOUT(g, "CarryOUT");
426
427 make_edge(A[0].get_out(), input_port<P::A0>(two_adder));
428 make_edge(B[0].get_out(), input_port<P::B0>(two_adder));
429 make_edge(output_port<P::S0>(two_adder), input_port<0>(Sum));
430
431 make_edge(A[1].get_out(), input_port<P::A1>(two_adder));
432 make_edge(B[1].get_out(), input_port<P::B1>(two_adder));
433 make_edge(output_port<P::S1>(two_adder), input_port<1>(Sum));
434
435 make_edge(CarryIN.get_out(), input_port<P::CI>(two_adder));
436 make_edge(output_port<P::CO>(two_adder), CarryOUT.get_in());
437
438 // Activate all switches at low state
439 for (int i=0; i<2; ++i) {
440 A[i].activate();
441 B[i].activate();
442 }
443 CarryIN.activate();
444
445 if (!silent) printf("1+0\n");
446 A[0].flip();
447 g.wait_for_all();
448 if (!silent) Sum.display();
449 if (!silent) CarryOUT.display();
450 assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));
451
452 if (!silent) printf("0+1\n");
453 A[0].flip();
454 B[0].flip();
455 g.wait_for_all();
456 if (!silent) Sum.display();
457 if (!silent) CarryOUT.display();
458 assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));
459 }
460#else
461 { // test four_bit_adder
462 four_bit_adder four_adder(g);
463 std::vector<toggle> A(4, toggle(g));
464 std::vector<toggle> B(4, toggle(g));
465 toggle CarryIN(g);
466 digit Sum(g, "SUM");
467 led CarryOUT(g, "CarryOUT");
468
469 make_edge(A[0].get_out(), input_port<P::A0>(four_adder));
470 make_edge(B[0].get_out(), input_port<P::B0>(four_adder));
471 make_edge(output_port<P::S0>(four_adder), input_port<0>(Sum));
472
473 make_edge(A[1].get_out(), input_port<P::A1>(four_adder));
474 make_edge(B[1].get_out(), input_port<P::B1>(four_adder));
475 make_edge(output_port<P::S1>(four_adder), input_port<1>(Sum));
476
477 make_edge(A[2].get_out(), input_port<P::A2>(four_adder));
478 make_edge(B[2].get_out(), input_port<P::B2>(four_adder));
479 make_edge(output_port<P::S2>(four_adder), input_port<2>(Sum));
480
481 make_edge(A[3].get_out(), input_port<P::A3>(four_adder));
482 make_edge(B[3].get_out(), input_port<P::B3>(four_adder));
483 make_edge(output_port<P::S3>(four_adder), input_port<3>(Sum));
484
485 make_edge(CarryIN.get_out(), input_port<P::CI>(four_adder));
486 make_edge(output_port<P::CO>(four_adder), CarryOUT.get_in());
487
488 // Activate all switches at low state
489 for (int i=0; i<4; ++i) {
490 A[i].activate();
491 B[i].activate();
492 }
493 CarryIN.activate();
494
495 if (!silent) printf("1+0\n");
496 A[0].flip();
497 g.wait_for_all();
498 if (!silent) Sum.display();
499 if (!silent) CarryOUT.display();
500 assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));
501
502 if (!silent) printf("0+1\n");
503 A[0].flip();
504 B[0].flip();
505 g.wait_for_all();
506 if (!silent) Sum.display();
507 if (!silent) CarryOUT.display();
508 assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));
509
510 if (!silent) printf("3+4\n");
511 A[0].flip();
512 A[1].flip();
513 B[0].flip();
514 B[2].flip();
515 g.wait_for_all();
516 if (!silent) Sum.display();
517 if (!silent) CarryOUT.display();
518 assert((Sum.get_value() == 7) && (CarryOUT.get_value() == low));
519
520 if (!silent) printf("6+1\n");
521 A[0].flip();
522 A[2].flip();
523 B[0].flip();
524 B[2].flip();
525 g.wait_for_all();
526 if (!silent) Sum.display();
527 if (!silent) CarryOUT.display();
528 assert((Sum.get_value() == 7) && (CarryOUT.get_value() == low));
529
530 if (!silent) printf("0+0+carry\n");
531 A[1].flip();
532 A[2].flip();
533 B[0].flip();
534 CarryIN.flip();
535 g.wait_for_all();
536 if (!silent) Sum.display();
537 if (!silent) CarryOUT.display();
538 assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));
539
540 if (!silent) printf("15+15+carry\n");
541 A[0].flip();
542 A[1].flip();
543 A[2].flip();
544 A[3].flip();
545 B[0].flip();
546 B[1].flip();
547 B[2].flip();
548 B[3].flip();
549 g.wait_for_all();
550 if (!silent) Sum.display();
551 if (!silent) CarryOUT.display();
552 assert((Sum.get_value() == 0xf) && (CarryOUT.get_value() == high));
553
554 if (!silent) printf("8+8\n");
555 A[0].flip();
556 A[1].flip();
557 A[2].flip();
558 B[0].flip();
559 B[1].flip();
560 B[2].flip();
561 CarryIN.flip();
562 g.wait_for_all();
563 if (!silent) Sum.display();
564 if (!silent) CarryOUT.display();
565 assert((Sum.get_value() == 0) && (CarryOUT.get_value() == high));
566
567 if (!silent) printf("0+0\n");
568 A[3].flip();
569 B[3].flip();
570 g.wait_for_all();
571 if (!silent) Sum.display();
572 if (!silent) CarryOUT.display();
573 assert((Sum.get_value() == 0) && (CarryOUT.get_value() == low));
574 }
575#endif
576
577 { // test D_latch
578 D_latch my_d_latch(g);
579 toggle D(g);
580 pulse E(g, 500, 4); // clock changes every 500ms; stops after 4 changes
581 led Q(g, " Q", verbose); // if true, LEDs print at every state change
582 led notQ(g, "~Q", verbose);
583
584 make_edge(D.get_out(), input_port<0>(my_d_latch));
585 make_edge(E.get_out(), input_port<1>(my_d_latch));
586 make_edge(output_port<0>(my_d_latch), Q.get_in());
587 make_edge(output_port<1>(my_d_latch), notQ.get_in());
588
589 D.activate();
590
591 if (!silent) printf("Toggling D\n");
592 E.activate();
593 D.flip();
594 g.wait_for_all();
595 if (!silent && !verbose) { Q.display(); notQ.display(); }
596 assert((Q.get_value() == high) && (notQ.get_value() == low));
597 E.reset();
598
599 if (!silent) printf("Toggling D\n");
600 E.activate();
601 D.flip();
602 g.wait_for_all();
603 if (!silent && !verbose) { Q.display(); notQ.display(); }
604 assert((Q.get_value() == low) && (notQ.get_value() == high));
605 E.reset();
606
607 if (!silent) printf("Toggling D\n");
608 E.activate();
609 D.flip();
610 g.wait_for_all();
611 if (!silent && !verbose) { Q.display(); notQ.display(); }
612 assert((Q.get_value() == high) && (notQ.get_value() == low));
613 E.reset();
614
615 if (!silent) printf("Toggling D\n");
616 E.activate();
617 D.flip();
618 g.wait_for_all();
619 if (!silent && !verbose) { Q.display(); notQ.display(); }
620 assert((Q.get_value() == low) && (notQ.get_value() == high));
621 E.reset();
622
623 if (!silent) printf("Toggling D\n");
624 E.activate();
625 D.flip();
626 g.wait_for_all();
627 if (!silent && !verbose) { Q.display(); notQ.display(); }
628 assert((Q.get_value() == high) && (notQ.get_value() == low));
629 }
630 }
631 utility::report_elapsed_time((tbb::tick_count::now() - start).seconds());
632 return 0;
633 } catch(std::exception& e) {
634 cerr<<"error occurred. error text is :\"" <<e.what()<<"\"\n";
635 return 1;
636 }
637#else
638 utility::report_skipped();
639 return 0;
640#endif // __TBB_FLOW_GRAPH_CPP11_FEATURES
641}
642
643