Files
tbb/examples/graph/logic_sim/test_all.cpp
T
2016-05-12 15:59:02 +01:00

647 lines
26 KiB
C++

/*
Copyright 2005-2016 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.
*/
#include "tbb/tbb_config.h"
#include <cstdio>
#include "../../common/utility/utility.h"
#if __TBB_FLOW_GRAPH_CPP11_FEATURES
#if _MSC_VER
#pragma warning (disable: 4503) // Suppress "decorated name length exceeded, name was truncated" warning
#endif
#define USE_TWO_BIT_FULL_ADDER 1
#include "basics.h"
#include "one_bit_adder.h"
#if USE_TWO_BIT_FULL_ADDER
#include "two_bit_adder.h"
#else
#include "four_bit_adder.h"
#endif
#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;
}
#endif // __TBB_FLOW_GRAPH_CPP11_FEATURES
int main(int argc, char *argv[]) {
#if __TBB_FLOW_GRAPH_CPP11_FEATURES
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(), input_port<0>(b));
make_edge(output_port<0>(b), 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(), input_port<0>(n));
make_edge(output_port<0>(n), 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(), input_port<0>(a));
make_edge(input1.get_out(), input_port<1>(a));
make_edge(output_port<0>(a), 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(), input_port<0>(o));
make_edge(input1.get_out(), input_port<1>(o));
make_edge(input2.get_out(), input_port<2>(o));
make_edge(output_port<0>(o), 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(), input_port<0>(x));
make_edge(input1.get_out(), input_port<1>(x));
make_edge(output_port<0>(x), 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(), input_port<0>(n));
make_edge(input1.get_out(), input_port<1>(n));
make_edge(output_port<0>(n), 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(), input_port<0>(a));
make_edge(input1.get_out(), input_port<1>(a));
make_edge(output_port<0>(a), input_port<0>(output));
make_edge(input0.get_out(), input_port<0>(o));
make_edge(input1.get_out(), input_port<1>(o));
make_edge(output_port<0>(o), input_port<1>(output));
make_edge(input0.get_out(), input_port<0>(x));
make_edge(input1.get_out(), input_port<1>(x));
make_edge(output_port<0>(x), input_port<2>(output));
make_edge(input0.get_out(), input_port<0>(n));
make_edge(input1.get_out(), input_port<1>(n));
make_edge(output_port<0>(n), input_port<3>(output));
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(), input_port<0>(b));
make_edge(output_port<0>(b), 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(), input_port<P::A0>(my_adder));
make_edge(B.get_out(), input_port<P::B0>(my_adder));
make_edge(CarryIN.get_out(), input_port<P::CI>(my_adder));
make_edge(output_port<P::S0>(my_adder), Sum.get_in());
make_edge(output_port<1>(my_adder), 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));
}
#if USE_TWO_BIT_FULL_ADDER
{ // test two_bit_adder
if (!silent) printf("testing two_bit adder\n");
two_bit_adder two_adder(g);
std::vector<toggle> A(2, toggle(g));
std::vector<toggle> B(2, toggle(g));
toggle CarryIN(g);
digit Sum(g, "SUM");
led CarryOUT(g, "CarryOUT");
make_edge(A[0].get_out(), input_port<P::A0>(two_adder));
make_edge(B[0].get_out(), input_port<P::B0>(two_adder));
make_edge(output_port<P::S0>(two_adder), input_port<0>(Sum));
make_edge(A[1].get_out(), input_port<P::A1>(two_adder));
make_edge(B[1].get_out(), input_port<P::B1>(two_adder));
make_edge(output_port<P::S1>(two_adder), input_port<1>(Sum));
make_edge(CarryIN.get_out(), input_port<P::CI>(two_adder));
make_edge(output_port<P::CO>(two_adder), CarryOUT.get_in());
// Activate all switches at low state
for (int i=0; i<2; ++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));
}
#else
{ // 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");
make_edge(A[0].get_out(), input_port<P::A0>(four_adder));
make_edge(B[0].get_out(), input_port<P::B0>(four_adder));
make_edge(output_port<P::S0>(four_adder), input_port<0>(Sum));
make_edge(A[1].get_out(), input_port<P::A1>(four_adder));
make_edge(B[1].get_out(), input_port<P::B1>(four_adder));
make_edge(output_port<P::S1>(four_adder), input_port<1>(Sum));
make_edge(A[2].get_out(), input_port<P::A2>(four_adder));
make_edge(B[2].get_out(), input_port<P::B2>(four_adder));
make_edge(output_port<P::S2>(four_adder), input_port<2>(Sum));
make_edge(A[3].get_out(), input_port<P::A3>(four_adder));
make_edge(B[3].get_out(), input_port<P::B3>(four_adder));
make_edge(output_port<P::S3>(four_adder), input_port<3>(Sum));
make_edge(CarryIN.get_out(), input_port<P::CI>(four_adder));
make_edge(output_port<P::CO>(four_adder), 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));
}
#endif
{ // 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(), input_port<0>(my_d_latch));
make_edge(E.get_out(), input_port<1>(my_d_latch));
make_edge(output_port<0>(my_d_latch), Q.get_in());
make_edge(output_port<1>(my_d_latch), 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;
}
#else
utility::report_skipped();
return 0;
#endif // __TBB_FLOW_GRAPH_CPP11_FEATURES
}