mirror of
https://github.com/wjakob/tbb.git
synced 2026-08-30 09:00:40 +08:00
570 lines
23 KiB
C++
570 lines
23 KiB
C++
/*
|
|
Copyright 2005-2014 Intel Corporation. All Rights Reserved.
|
|
|
|
This file is part of Threading Building Blocks. Threading Building Blocks is free software;
|
|
you can redistribute it and/or modify it under the terms of the GNU General Public License
|
|
version 2 as published by the Free Software Foundation. Threading Building Blocks is
|
|
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
See the GNU General Public License for more details. You should have received a copy of
|
|
the GNU General Public License along with Threading Building Blocks; if not, write to the
|
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
As a special exception, you may use this file as part of a free software library without
|
|
restriction. Specifically, if other files instantiate templates or use macros or inline
|
|
functions from this file, or you compile this file and link it with other files to produce
|
|
an executable, this file does not by itself cause the resulting executable to be covered
|
|
by the GNU General Public License. This exception does not however invalidate any other
|
|
reasons why the executable file might be covered by the GNU General Public License.
|
|
*/
|
|
|
|
#if _MSC_VER
|
|
#pragma warning (disable: 4503) // Suppress "decorated name length exceeded, name was truncated" warning
|
|
#endif
|
|
|
|
#include "basics.h"
|
|
#include "one_bit_adder.h"
|
|
#include "four_bit_adder.h"
|
|
#include "D_latch.h"
|
|
#include <cassert>
|
|
|
|
// User-specified globals with default values
|
|
bool verbose = false; // prints bin details and other diagnostics to screen
|
|
bool silent = false; // suppress all output except for time
|
|
|
|
int get_default_num_threads() {
|
|
static int threads = 0;
|
|
if (threads == 0)
|
|
threads = tbb::task_scheduler_init::default_num_threads();
|
|
return threads;
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
try {
|
|
utility::thread_number_range threads(get_default_num_threads);
|
|
utility::parse_cli_arguments(argc, argv,
|
|
utility::cli_argument_pack()
|
|
//"-h" option for displaying help is present implicitly
|
|
.positional_arg(threads,"#threads",utility::thread_number_range_desc)
|
|
.arg(verbose,"verbose"," print diagnostic output to screen")
|
|
.arg(silent,"silent"," limits output to timing info; overrides verbose")
|
|
);
|
|
|
|
if (silent) verbose = false; // make silent override verbose
|
|
|
|
tick_count start = tick_count::now();
|
|
for(int p = threads.first; p <= threads.last; p = threads.step(p)) {
|
|
task_scheduler_init init(p);
|
|
if (!silent) cout << "graph test running on " << p << " threads.\n";
|
|
|
|
graph g;
|
|
|
|
{ // test buffer: 0, 1
|
|
buffer b(g);
|
|
toggle input(g);
|
|
led output(g, "OUTPUT", false); // false means we will explicitly call display to see LED
|
|
|
|
make_edge(input.get_out(), b.get_in(0));
|
|
make_edge(b.get_out(), output.get_in());
|
|
|
|
if (!silent) printf("Testing buffer...\n");
|
|
input.activate(); // 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == low);
|
|
input.flip(); // 1
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
}
|
|
|
|
{ // test not_gate: 0, 1
|
|
not_gate n(g);
|
|
toggle input(g);
|
|
led output(g, "OUTPUT", false);
|
|
|
|
make_edge(input.get_out(), n.get_in(0));
|
|
make_edge(n.get_out(), output.get_in());
|
|
|
|
if (!silent) printf("Testing not_gate...\n");
|
|
input.activate(); // 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
input.flip(); // 1
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == low);
|
|
}
|
|
|
|
{ // test two-input and_gate: 00, 01, 10, 11
|
|
and_gate<2> a(g);
|
|
toggle input0(g);
|
|
toggle input1(g);
|
|
led output(g, "OUTPUT", false);
|
|
|
|
make_edge(input0.get_out(), a.get_in(0));
|
|
make_edge(input1.get_out(), a.get_in(1));
|
|
make_edge(a.get_out(), output.get_in());
|
|
|
|
if (!silent) printf("Testing and_gate...\n");
|
|
input1.activate(); input0.activate(); // 0 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == low);
|
|
input0.flip(); // 0 1
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == low);
|
|
input1.flip(); input0.flip(); // 1 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == low);
|
|
input0.flip(); // 1 1
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
}
|
|
|
|
{ // test three-input or_gate: 000, 001, 010, 100, 011, 101, 110, 111
|
|
or_gate<3> o(g);
|
|
toggle input0(g);
|
|
toggle input1(g);
|
|
toggle input2(g);
|
|
led output(g, "OUTPUT", false);
|
|
|
|
make_edge(input0.get_out(), o.get_in(0));
|
|
make_edge(input1.get_out(), o.get_in(1));
|
|
make_edge(input2.get_out(), o.get_in(2));
|
|
make_edge(o.get_out(), output.get_in());
|
|
|
|
if (!silent) printf("Testing or_gate...\n");
|
|
input2.activate(); input1.activate(); input0.activate(); // 0 0 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == low);
|
|
input0.flip(); // 0 0 1
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
input1.flip(); input0.flip(); // 0 1 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
input2.flip(); input1.flip(); // 1 0 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
input2.flip(); input1.flip(); input0.flip(); // 0 1 1
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
input2.flip(); input1.flip(); // 1 0 1
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
input1.flip(); input0.flip(); // 1 1 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
input0.flip(); // 1 1 1
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
}
|
|
|
|
{ // test two-input xor_gate: 00, 01, 10, 11
|
|
xor_gate<2> x(g);
|
|
toggle input0(g);
|
|
toggle input1(g);
|
|
led output(g, "OUTPUT", false);
|
|
|
|
make_edge(input0.get_out(), x.get_in(0));
|
|
make_edge(input1.get_out(), x.get_in(1));
|
|
make_edge(x.get_out(), output.get_in());
|
|
|
|
if (!silent) printf("Testing xor_gate...\n");
|
|
input1.activate(); input0.activate(); // 0 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == low);
|
|
input0.flip(); // 0 1
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
input1.flip(); input0.flip(); // 1 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
input0.flip(); // 1 1
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == low);
|
|
}
|
|
|
|
|
|
{ // test two-input nor_gate: 00, 01, 10, 11
|
|
nor_gate<2> n(g);
|
|
toggle input0(g);
|
|
toggle input1(g);
|
|
led output(g, "OUTPUT", false);
|
|
|
|
make_edge(input0.get_out(), n.get_in(0));
|
|
make_edge(input1.get_out(), n.get_in(1));
|
|
make_edge(n.get_out(), output.get_in());
|
|
|
|
if (!silent) printf("Testing nor_gate...\n");
|
|
input1.activate(); input0.activate(); // 0 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == high);
|
|
input0.flip(); // 0 1
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == low);
|
|
input1.flip(); input0.flip(); // 1 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == low);
|
|
input0.flip(); // 1 1
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == low);
|
|
}
|
|
|
|
{ // test steady_signal and digit
|
|
steady_signal input0(g, high);
|
|
steady_signal input1(g, low);
|
|
and_gate<2> a(g);
|
|
or_gate<2> o(g);
|
|
xor_gate<2> x(g);
|
|
nor_gate<2> n(g);
|
|
digit output(g, "OUTPUT", false);
|
|
|
|
make_edge(input0.get_out(), a.get_in(0));
|
|
make_edge(input1.get_out(), a.get_in(1));
|
|
make_edge(a.get_out(), output.get_in(0));
|
|
|
|
make_edge(input0.get_out(), o.get_in(0));
|
|
make_edge(input1.get_out(), o.get_in(1));
|
|
make_edge(o.get_out(), output.get_in(1));
|
|
|
|
make_edge(input0.get_out(), x.get_in(0));
|
|
make_edge(input1.get_out(), x.get_in(1));
|
|
make_edge(x.get_out(), output.get_in(2));
|
|
|
|
make_edge(input0.get_out(), n.get_in(0));
|
|
make_edge(input1.get_out(), n.get_in(1));
|
|
make_edge(n.get_out(), output.get_in(3));
|
|
|
|
if (!silent) printf("Testing steady_signal...\n");
|
|
input0.activate(); // 1
|
|
input1.activate(); // 0
|
|
g.wait_for_all();
|
|
if (!silent) output.display();
|
|
assert(output.get_value() == 6);
|
|
}
|
|
|
|
{ // test push_button
|
|
push_button p(g);
|
|
buffer b(g);
|
|
led output(g, "OUTPUT", !silent); // true means print all LED state changes
|
|
|
|
make_edge(p.get_out(), b.get_in(0));
|
|
make_edge(b.get_out(), output.get_in());
|
|
|
|
if (!silent) printf("Testing push_button...\n");
|
|
p.press();
|
|
p.release();
|
|
p.press();
|
|
p.release();
|
|
g.wait_for_all();
|
|
}
|
|
|
|
{ // test one_bit_adder
|
|
one_bit_adder my_adder(g);
|
|
toggle A(g);
|
|
toggle B(g);
|
|
toggle CarryIN(g);
|
|
led Sum(g, "SUM");
|
|
led CarryOUT(g, "CarryOUT");
|
|
|
|
make_edge(A.get_out(), my_adder.get_A());
|
|
make_edge(B.get_out(), my_adder.get_B());
|
|
make_edge(CarryIN.get_out(), my_adder.get_CI());
|
|
make_edge(my_adder.get_out(), Sum.get_in());
|
|
make_edge(my_adder.get_CO(), CarryOUT.get_in());
|
|
|
|
A.activate();
|
|
B.activate();
|
|
CarryIN.activate();
|
|
|
|
if (!silent) printf("A on\n");
|
|
A.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == high) && (CarryOUT.get_value() == low));
|
|
|
|
if (!silent) printf("A off\n");
|
|
A.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
|
|
|
|
if (!silent) printf("B on\n");
|
|
B.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == high) && (CarryOUT.get_value() == low));
|
|
if (!silent) printf("B off\n");
|
|
B.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
|
|
|
|
if (!silent) printf("CarryIN on\n");
|
|
CarryIN.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == high) && (CarryOUT.get_value() == low));
|
|
if (!silent) printf("CarryIN off\n");
|
|
CarryIN.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
|
|
|
|
if (!silent) printf("A&B on\n");
|
|
A.flip();
|
|
B.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == low) && (CarryOUT.get_value() == high));
|
|
if (!silent) printf("A&B off\n");
|
|
A.flip();
|
|
B.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
|
|
|
|
if (!silent) printf("A&CarryIN on\n");
|
|
A.flip();
|
|
CarryIN.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == low) && (CarryOUT.get_value() == high));
|
|
if (!silent) printf("A&CarryIN off\n");
|
|
A.flip();
|
|
CarryIN.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
|
|
|
|
if (!silent) printf("B&CarryIN on\n");
|
|
B.flip();
|
|
CarryIN.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == low) && (CarryOUT.get_value() == high));
|
|
if (!silent) printf("B&CarryIN off\n");
|
|
B.flip();
|
|
CarryIN.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
|
|
|
|
if (!silent) printf("A&B&CarryIN on\n");
|
|
A.flip();
|
|
B.flip();
|
|
CarryIN.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == high) && (CarryOUT.get_value() == high));
|
|
if (!silent) printf("A&B&CarryIN off\n");
|
|
A.flip();
|
|
B.flip();
|
|
CarryIN.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
|
|
}
|
|
|
|
{ // test four_bit_adder
|
|
four_bit_adder four_adder(g);
|
|
std::vector<toggle> A(4, toggle(g));
|
|
std::vector<toggle> B(4, toggle(g));
|
|
toggle CarryIN(g);
|
|
digit Sum(g, "SUM");
|
|
led CarryOUT(g, "CarryOUT");
|
|
|
|
for (int i=0; i<4; ++i) {
|
|
make_edge(A[i].get_out(), four_adder.get_A(i));
|
|
make_edge(B[i].get_out(), four_adder.get_B(i));
|
|
make_edge(four_adder.get_out(i), Sum.get_in(i));
|
|
}
|
|
make_edge(CarryIN.get_out(), four_adder.get_CI());
|
|
make_edge(four_adder.get_CO(), CarryOUT.get_in());
|
|
|
|
// Activate all switches at low state
|
|
for (int i=0; i<4; ++i) {
|
|
A[i].activate();
|
|
B[i].activate();
|
|
}
|
|
CarryIN.activate();
|
|
|
|
if (!silent) printf("1+0\n");
|
|
A[0].flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));
|
|
|
|
if (!silent) printf("0+1\n");
|
|
A[0].flip();
|
|
B[0].flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));
|
|
|
|
if (!silent) printf("3+4\n");
|
|
A[0].flip();
|
|
A[1].flip();
|
|
B[0].flip();
|
|
B[2].flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == 7) && (CarryOUT.get_value() == low));
|
|
|
|
if (!silent) printf("6+1\n");
|
|
A[0].flip();
|
|
A[2].flip();
|
|
B[0].flip();
|
|
B[2].flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == 7) && (CarryOUT.get_value() == low));
|
|
|
|
if (!silent) printf("0+0+carry\n");
|
|
A[1].flip();
|
|
A[2].flip();
|
|
B[0].flip();
|
|
CarryIN.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));
|
|
|
|
if (!silent) printf("15+15+carry\n");
|
|
A[0].flip();
|
|
A[1].flip();
|
|
A[2].flip();
|
|
A[3].flip();
|
|
B[0].flip();
|
|
B[1].flip();
|
|
B[2].flip();
|
|
B[3].flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == 0xf) && (CarryOUT.get_value() == high));
|
|
|
|
if (!silent) printf("8+8\n");
|
|
A[0].flip();
|
|
A[1].flip();
|
|
A[2].flip();
|
|
B[0].flip();
|
|
B[1].flip();
|
|
B[2].flip();
|
|
CarryIN.flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == 0) && (CarryOUT.get_value() == high));
|
|
|
|
if (!silent) printf("0+0\n");
|
|
A[3].flip();
|
|
B[3].flip();
|
|
g.wait_for_all();
|
|
if (!silent) Sum.display();
|
|
if (!silent) CarryOUT.display();
|
|
assert((Sum.get_value() == 0) && (CarryOUT.get_value() == low));
|
|
}
|
|
|
|
{ // test D_latch
|
|
D_latch my_d_latch(g);
|
|
toggle D(g);
|
|
pulse E(g, 500, 4); // clock changes every 500ms; stops after 4 changes
|
|
led Q(g, " Q", verbose); // if true, LEDs print at every state change
|
|
led notQ(g, "~Q", verbose);
|
|
|
|
make_edge(D.get_out(), my_d_latch.get_D());
|
|
make_edge(E.get_out(), my_d_latch.get_E());
|
|
make_edge(my_d_latch.get_Q(), Q.get_in());
|
|
make_edge(my_d_latch.get_notQ(), notQ.get_in());
|
|
|
|
D.activate();
|
|
|
|
if (!silent) printf("Toggling D\n");
|
|
E.activate();
|
|
D.flip();
|
|
g.wait_for_all();
|
|
if (!silent && !verbose) { Q.display(); notQ.display(); }
|
|
assert((Q.get_value() == high) && (notQ.get_value() == low));
|
|
E.reset();
|
|
|
|
if (!silent) printf("Toggling D\n");
|
|
E.activate();
|
|
D.flip();
|
|
g.wait_for_all();
|
|
if (!silent && !verbose) { Q.display(); notQ.display(); }
|
|
assert((Q.get_value() == low) && (notQ.get_value() == high));
|
|
E.reset();
|
|
|
|
if (!silent) printf("Toggling D\n");
|
|
E.activate();
|
|
D.flip();
|
|
g.wait_for_all();
|
|
if (!silent && !verbose) { Q.display(); notQ.display(); }
|
|
assert((Q.get_value() == high) && (notQ.get_value() == low));
|
|
E.reset();
|
|
|
|
if (!silent) printf("Toggling D\n");
|
|
E.activate();
|
|
D.flip();
|
|
g.wait_for_all();
|
|
if (!silent && !verbose) { Q.display(); notQ.display(); }
|
|
assert((Q.get_value() == low) && (notQ.get_value() == high));
|
|
E.reset();
|
|
|
|
if (!silent) printf("Toggling D\n");
|
|
E.activate();
|
|
D.flip();
|
|
g.wait_for_all();
|
|
if (!silent && !verbose) { Q.display(); notQ.display(); }
|
|
assert((Q.get_value() == high) && (notQ.get_value() == low));
|
|
}
|
|
}
|
|
utility::report_elapsed_time((tbb::tick_count::now() - start).seconds());
|
|
return 0;
|
|
} catch(std::exception& e) {
|
|
cerr<<"error occurred. error text is :\"" <<e.what()<<"\"\n";
|
|
return 1;
|
|
}
|
|
}
|