You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
6.2 KiB
192 lines
6.2 KiB
/**
|
|
@file
|
|
|
|
@ingroup cplusplus
|
|
|
|
@brief Test program for multiple managers (one per thread).
|
|
|
|
@details This program tests the ability to run different CUDD managers
|
|
in different threads. Each thread builds the hidden weight bit function
|
|
for a certain number of variables and then reorders the variables.
|
|
|
|
@author Fabio Somenzi
|
|
|
|
@copyright@parblock
|
|
Copyright (c) 1995-2015, Regents of the University of Colorado
|
|
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
|
|
Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
Neither the name of the University of Colorado nor the names of its
|
|
contributors may be used to endorse or promote products derived from
|
|
this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
@endparblock
|
|
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "cuddObj.hh"
|
|
#include <cstdlib>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#if HAVE_WORKING_THREAD == 1
|
|
#include <thread>
|
|
|
|
/**
|
|
* @brief Taks performed by each thread.
|
|
*/
|
|
class Task {
|
|
public:
|
|
/** Constructor. */
|
|
Task(int n, std::ostringstream & os) : n(n), os(os) {}
|
|
/** Builds the hidden weight bit function and reorders the variables. */
|
|
void operator()(void) {
|
|
Cudd mgr;
|
|
mgr.AutodynEnable();
|
|
int nvars = n + 32;
|
|
std::vector<BDD> vars;
|
|
for (int i = 0; i != nvars; ++i) {
|
|
vars.push_back(mgr.bddVar());
|
|
}
|
|
os << "Report from thread " << n << " with " << nvars << " variables: ";
|
|
// The hidden weight bit function is built from a tally circuit and
|
|
// a multiplexer. First the tally circuit...
|
|
std::vector<BDD> oldt;
|
|
oldt.push_back(mgr.bddOne());
|
|
std::vector<BDD> t;
|
|
for (int i = 1; i != nvars + 1; ++i) {
|
|
t.clear();
|
|
t.push_back(oldt.at(0) & !vars.at(i-1));
|
|
for (int j = 1; j != i; ++j) {
|
|
t.push_back(vars.at(i-1).Ite(oldt.at(j-1), oldt.at(j)));
|
|
}
|
|
t.push_back(oldt.at(i-1) & vars.at(i-1));
|
|
oldt = t;
|
|
}
|
|
#if 0
|
|
// Diagnostic print.
|
|
for (int i = 0; i != nvars + 1; ++i) {
|
|
os << "t(" << i << ") = " << t.at(i).FactoredFormString()
|
|
<< std::endl;
|
|
}
|
|
#endif
|
|
// ...then the multiplexer.
|
|
BDD hwb = mgr.bddZero();
|
|
for (int i = 0; i != nvars; ++i) {
|
|
hwb |= t.at(i+1) & vars.at(i);
|
|
}
|
|
mgr.ReduceHeap(CUDD_REORDER_SIFT_CONVERGE);
|
|
|
|
int nodes = hwb.nodeCount();
|
|
os << nodes << " nodes and ";
|
|
int digits;
|
|
DdApaNumber apa_minterms = hwb.ApaCountMinterm(nvars, &digits);
|
|
os << mgr.ApaStringDecimal(digits, apa_minterms) << " minterms\n";
|
|
free(apa_minterms);
|
|
os << "Variable order: " << mgr.OrderString() << "\n";
|
|
mgr.Srandom(n+11);
|
|
os << "A random number from our generator: " << mgr.Random() << "\n";
|
|
#if 0
|
|
// Diagnostic prints.
|
|
hwb.summary(nvars);
|
|
os << hwb.FactoredFormString() << std::endl;
|
|
#endif
|
|
}
|
|
private:
|
|
int n;
|
|
std::ostringstream & os;
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief Class to join threads in RAII fashion.
|
|
*/
|
|
class joinThreads {
|
|
public:
|
|
explicit joinThreads(std::vector<std::thread>& t) : threads_(t) {}
|
|
/** It completes once all threads have been joined. */
|
|
~joinThreads() {
|
|
for (std::vector<std::thread>::iterator it = threads_.begin();
|
|
it != threads_.end(); ++it)
|
|
if (it->joinable())
|
|
it->join();
|
|
}
|
|
joinThreads(joinThreads const &) = delete;
|
|
joinThreads& operator=(joinThreads const &) = delete;
|
|
private:
|
|
std::vector<std::thread>& threads_; /**< vector of threads to be joined. */
|
|
};
|
|
#endif
|
|
|
|
/**
|
|
@brief Main program for testmulti.
|
|
*/
|
|
int main(int argc, char **argv)
|
|
{
|
|
int nthreads = 4; // default value
|
|
|
|
// If there's an argument, it's the number of threads.
|
|
if (argc == 2) {
|
|
int nread;
|
|
int retval = sscanf(argv[1], "%d%n", &nthreads, &nread);
|
|
if (retval != 1 || argv[1][nread]) {
|
|
std::cerr << "The argument should be an integer." << std::endl;
|
|
return 1;
|
|
}
|
|
} else if (argc != 1) {
|
|
std::cerr << "Either no arguments or one argument." << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
#if HAVE_WORKING_THREAD == 1
|
|
// Each thread has its own output stream, so that main can print thread
|
|
// reports without interleaving. We can't use an std::vector here because
|
|
// old versions of g++ don't support move semantics (and streams can't
|
|
// be copied). We can't use a variable-length array either because it's
|
|
// a g++ extension and clang++ rejects it. Hence we use new/delete.
|
|
std::ostringstream *oss = new std::ostringstream[nthreads];
|
|
|
|
// Multi-threaded code in this block.
|
|
{
|
|
std::vector<std::thread> t;
|
|
joinThreads joiner(t); // threads are joined by its destructor
|
|
for (int n = 0; n != nthreads; ++n) {
|
|
t.push_back(std::thread(Task(n, oss[n])));
|
|
}
|
|
}
|
|
|
|
// Print the reports.
|
|
for (int n = 0; n != nthreads; ++n) {
|
|
std::cout << oss[n].str();
|
|
}
|
|
|
|
delete [] oss;
|
|
|
|
return 0;
|
|
#else
|
|
return 77; // test skipped
|
|
#endif
|
|
}
|