CaFactory.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2009 Kamil Dudka <xdudka00@stud.fit.vutbr.cz>
00003  *
00004  * This file is part of nucad (Non-Uniform CA Designer).
00005  *
00006  * nucad is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation, either version 3 of the License, or
00009  * any later version.
00010  *
00011  * nucad is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with nucad.  If not, see <http://www.gnu.org/licenses/>.
00018  */
00019 
00026 #include "config.h"
00027 #include "CaFactory.h"
00028 #include "Ca.h"
00029 #include "Color.h"
00030 
00031 #ifndef BUILDING_DOX
00032 #   include <map>
00033 #   include <set>
00034 #   include <stdexcept>
00035 #   include <sstream>
00036 
00037 #   define DOX_FAKE_PARENT(PARENT)
00038 #else
00039 #   define DOX_FAKE_PARENT(PARENT) : public PARENT
00040 #endif
00041 
00042 #ifndef GF_INCLUDE_TRIVIAL
00043 #   define GF_INCLUDE_TRIVIAL 0
00044 #endif
00045 
00046 #ifndef GF_INCLUDE_COMPLEX
00047 #   define GF_INCLUDE_COMPLEX 0
00048 #endif
00049 
00054 struct DefParams: public CaEvalParams {
00055     DefParams() {
00056         caSize = 5;
00057         nSteps = 6;
00058     }
00059 };
00060 
00066 template <int N_IN, int N_OUT>
00067 struct Binder
00068 {
00069     /* no tag - this will fail intentionally */
00070 };
00071 
00073 template <> struct Binder<2,1> DOX_FAKE_PARENT(Binder)
00074 {
00075     typedef BindInput<0, 1, 0,
00076             BindInput<1, 3, 0,
00077             BindOutput<0, 2, 4>
00078             > > tag;
00079 };
00080 
00082 template <> struct Binder<3,1> DOX_FAKE_PARENT(Binder)
00083 {
00084     typedef BindInput<0, 0, 0,
00085             BindInput<1, 2, 0,
00086             BindInput<2, 4, 0,
00087             BindOutput<0, 2, 4>
00088             > > > tag;
00089 };
00090 
00092 template <> struct Binder<5,1> DOX_FAKE_PARENT(Binder)
00093 {
00094     typedef BindInput<0, 0, 0,
00095             BindInput<1, 1, 0,
00096             BindInput<2, 2, 0,
00097             BindInput<3, 3, 0,
00098             BindInput<4, 4, 0,
00099             BindOutput<0, 2, 4>
00100             > > > > > tag;
00101 };
00102 
00104 template <> struct Binder<2,2> DOX_FAKE_PARENT(Binder)
00105 {
00106     typedef BindInput<0, 1, 0,
00107             BindInput<1, 3, 0,
00108             BindOutput<0, 1, 4,
00109             BindOutput<1, 3, 4>
00110             > > > tag;
00111 };
00112 
00114 template <> struct Binder<3,3> DOX_FAKE_PARENT(Binder)
00115 {
00116     typedef BindInput<0, 0, 0,
00117             BindInput<1, 2, 0,
00118             BindInput<2, 4, 0,
00119             BindOutput<0, 0, 4,
00120             BindOutput<1, 2, 4,
00121             BindOutput<2, 4, 4>
00122             > > > > > tag;
00123 };
00124 
00126 template <> struct Binder<4,4> DOX_FAKE_PARENT(Binder)
00127 {
00128     typedef BindInput<0, 0, 1,
00129             BindInput<1, 0, 3,
00130             BindInput<2, 1, 0,
00131             BindInput<3, 3, 0,
00132             BindOutput<0, 4, 3,
00133             BindOutput<1, 4, 1,
00134             BindOutput<2, 3, 4,
00135             BindOutput<3, 1, 4>
00136             > > > > > > > tag;
00137 };
00138 
00147 template <class CIRCUIT, class BINDING, class PARAMS = DefParams>
00148 class PrivateFactory {
00149     public:
00153         static CaEvaluator* create() {
00154             return new CaEvaluator(CIRCUIT(), BINDING(), PARAMS());
00155         }
00156 };
00157 
00164 template <template <int> class GATE, int N>
00165 class GateFactory {
00166     public:
00167         typedef GATE<N>                                 TGate;
00168         typedef typename Binder<N,1>::tag               TBinding;
00169 
00170     public:
00174         static CaEvaluator* create() {
00175             return PrivateFactory<TGate, TBinding>::create();
00176         }
00177 
00178     private:
00180         CT_ASSERT<TBinding::BOUND_INPUTS + 1 == 1 << N>
00181             ___COMPILE_TIME_ERROR__INAPPROPRIATE_INPUT_BINDING_FOR_GATE___;
00182 
00184         CT_ASSERT<TBinding::BOUND_OUTPUTS == 1>
00185             ___COMPILE_TIME_ERROR__INAPPROPRIATE_OUTPUT_BINDING_FOR_GATE___;
00186 };
00187 
00194 template <int N, template <int> class GATE = CrossGate>
00195 class WireCrossFactory {
00196     public:
00197         typedef GATE<N>                                 TGate;
00198         typedef typename Binder<N,N>::tag               TBinding;
00199 
00200     public:
00204         static CaEvaluator* create() {
00205             return PrivateFactory<TGate, TBinding>::create();
00206         }
00207 
00208     private:
00210         CT_ASSERT<TBinding::BOUND_INPUTS + 1 == 1 << N>
00211             ___COMPILE_TIME_ERROR__INAPPROPRIATE_INPUT_BINDING_FOR_CROSS___;
00212 
00214         CT_ASSERT<TBinding::BOUND_OUTPUTS + 1 == 1 << N>
00215             ___COMPILE_TIME_ERROR__INAPPROPRIATE_OUTPUT_BINDING_FOR_CROSS___;
00216 };
00217 
00223 template <int N> class MuxGate;
00224 
00228 template <>
00229 class MuxGate<3>: public AbstractGate<3,1> {
00230     public:
00231         virtual IGate* clone() const {
00232             return new MuxGate(*this);
00233         }
00234         virtual TBus operator[] (TBus in) const {
00235             bool result = (in & 4)
00236                 ? (in & 2)
00237                 : (in & 1);
00238             return result;
00239         }
00240 };
00241 
00245 template <>
00246 class MuxGate<6>: public AbstractGate<6,1> {
00247     public:
00248         virtual IGate* clone() const {
00249             return new MuxGate(*this);
00250         }
00251         virtual TBus operator[] (TBus in) const {
00252             const TBus select = (in & 0x30) >> 4;
00253             switch (select) {
00254                 case 0: return static_cast<bool>(in & (1 << 0));
00255                 case 1: return static_cast<bool>(in & (1 << 1));
00256                 case 2: return static_cast<bool>(in & (1 << 2));
00257                 case 3: return static_cast<bool>(in & (1 << 3));
00258                 default:
00259                     assert(false);
00260             }
00261         }
00262 };
00263 
00267 class Mux4Factory {
00268     private:
00269 #ifndef BUILDING_DOX
00270         struct Mux4Params: public CaEvalParams {
00271             Mux4Params() {
00272                 caSize = 3;
00273                 nSteps = 4;
00274             }
00275         };
00276 #endif
00277 
00278     public:
00279         typedef MuxGate<6>                              TGate;
00280         typedef BindInput<0, 0, 0,
00281                 BindInput<1, 0, 2,
00282                 BindInput<2, 2, 0,
00283                 BindInput<3, 2, 1,
00284                 BindInput<4, 0, 1,
00285                 BindInput<5, 1, 1,
00286                 BindOutput<0, 2, 2>
00287                 > > > > > >                             TBinding;
00288         typedef Mux4Params                              TParams;
00289 
00290     public:
00294         static CaEvaluator* create() {
00295             return PrivateFactory<TGate, TBinding, TParams>::create();
00296         }
00297 
00298     private:
00300         CT_ASSERT<TBinding::BOUND_INPUTS == 63>
00301             ___COMPILE_TIME_ERROR__INAPPROPRIATE_INPUT_BINDING_FOR_MUX4___;
00302 
00304         CT_ASSERT<TBinding::BOUND_OUTPUTS == 1>
00305             ___COMPILE_TIME_ERROR__INAPPROPRIATE_OUTPUT_BINDING_FOR_MUX4___;
00306 };
00307 
00313 template <int N, int CA_SIZE>
00314 struct MulBinder {
00315     /* no tag - this will fail intentionally */
00316 };
00317 
00319 template <> struct MulBinder<5, 3> DOX_FAKE_PARENT(MulBinder)
00320 {
00321     typedef BindInput<0, 0, 2,
00322             BindInput<1, 0, 1,
00323             BindInput<2, 2, 2,
00324             BindInput<3, 2, 1,
00325             BindInput<4, 2, 0,
00326             BindOutput<0, 0, 2,
00327             BindOutput<1, 2, 2,
00328             BindOutput<2, 0, 1,
00329             BindOutput<3, 2, 1,
00330             BindOutput<4, 2, 0>
00331             > > > > > > > > > tag;
00332 };
00333 
00335 template <> struct MulBinder<6, 3> DOX_FAKE_PARENT(MulBinder)
00336 {
00337     typedef BindInput<0, 1, 2,
00338             BindInput<1, 0, 1,
00339             BindInput<2, 2, 0,
00340             BindInput<3, 2, 2,
00341             BindInput<4, 1, 1,
00342             BindInput<5, 0, 0,
00343             BindOutput<0, 1, 2,
00344             BindOutput<1, 0, 2,
00345             BindOutput<2, 0, 1,
00346             BindOutput<3, 2, 1,
00347             BindOutput<4, 2, 0,
00348             BindOutput<5, 1, 0>
00349             > > > > > > > > > > > tag;
00350 };
00351 
00353 template <> struct MulBinder<6, 4> DOX_FAKE_PARENT(MulBinder)
00354 {
00355     typedef BindInput<0, 2, 3,
00356             BindInput<1, 1, 2,
00357             BindInput<2, 0, 1,
00358             BindInput<3, 3, 2,
00359             BindInput<4, 2, 1,
00360             BindInput<5, 1, 0,
00361             BindOutput<0, 2, 3,
00362             BindOutput<1, 3, 2,
00363             BindOutput<2, 1, 2,
00364             BindOutput<3, 2, 1,
00365             BindOutput<4, 0, 1,
00366             BindOutput<5, 1, 0>
00367             > > > > > > > > > > > tag;
00368 };
00369 
00375 template <int N, int CA_SIZE>
00376 class MulFactory {
00377     private:
00378         static const size_t MASK = (1 << N) - 1;
00379 #ifndef BUILDING_DOX
00380         struct MulParams: public CaEvalParams {
00381             MulParams() {
00382                 caSize = CA_SIZE;
00383                 nSteps = 13;
00384             }
00385         };
00386 #endif
00387 
00388     public:
00389         typedef MulGate<N>                              TGate;
00390         typedef typename MulBinder<N, CA_SIZE>::tag     TBinding;
00391         typedef MulParams                               TParams;
00392 
00393     public:
00397         static CaEvaluator* create() {
00398             return PrivateFactory<TGate, TBinding, TParams>::create();
00399         }
00400 
00401     private:
00403         CT_ASSERT<TBinding::BOUND_INPUTS == MASK>
00404             ___COMPILE_TIME_ERROR__INAPPROPRIATE_INPUT_BINDING_FOR_MUX4___;
00405 
00407         CT_ASSERT<TBinding::BOUND_OUTPUTS == MASK>
00408             ___COMPILE_TIME_ERROR__INAPPROPRIATE_OUTPUT_BINDING_FOR_MUX4___;
00409 };
00410 
00411 // /////////////////////////////////////////////////////////////////////////////
00412 // CaEvaluatorFactory implementation
00413 #ifndef BUILDING_DOX
00414 struct CaEvaluatorFactory::Private {
00415     typedef std::map<std::string, CaEvaluator* (*)()>   TMap;
00416     typedef std::set<std::string>                       TSet;
00417 
00418     TMap map;
00419     TSet trivialSet;
00420     TSet complexSet;
00421 };
00422 #endif
00423 
00424 CaEvaluatorFactory::CaEvaluatorFactory():
00425     d(new Private)
00426 {
00427     // 2-inputs gates
00428     d->map["and2"] = GateFactory <AndGate, 2> ::create;
00429     d->map[ "or2"] = GateFactory < OrGate, 2> ::create;
00430     d->map["xor2"] = GateFactory <XorGate, 2> ::create;
00431 
00432     // 3-inputs gates
00433     d->map["mux2"] = GateFactory <MuxGate, 3> ::create;
00434     d->map["and3"] = GateFactory <AndGate, 3> ::create;
00435     d->map[ "or3"] = GateFactory < OrGate, 3> ::create;
00436     d->map["xor3"] = GateFactory <XorGate, 3> ::create;
00437 
00438     // 5-inputs gates
00439     d->map["and5"] = GateFactory <AndGate, 5> ::create;
00440     d->map[ "or5"] = GateFactory < OrGate, 5> ::create;
00441 
00442     // xor5 converges immediately with incremental nStep
00443     // TODO: implement incremental nStep as an option
00444     d->map["xor5"] = GateFactory <XorGate, 5> ::create;
00445 
00446     // wire crossing
00447     d->map["cross2"] = WireCrossFactory <2> ::create;
00448     d->map["cross3"] = WireCrossFactory <3> ::create;
00449     d->map["cross2x2"] = WireCrossFactory <4, BusGate> ::create;
00450 
00451     // 4-input mux converges immediately with incremental caStep
00452     // TODO: implement incremental nStep as an option
00453     d->map["mux4"] = Mux4Factory::create;
00454 
00455     // mul
00456     d->map["mul2x3"] = MulFactory<5, 3>::create;
00457     d->map["mul3x3-ca3x3"] = MulFactory<6, 3>::create;
00458     d->map["mul3x3-ca4x4"] = MulFactory<6, 4>::create;
00459 
00460     // mark 2-inputs gates as trivial
00461     d->trivialSet.insert("and2");
00462     d->trivialSet.insert( "or2");
00463     d->trivialSet.insert("xor2");
00464     d->trivialSet.insert("cross2");
00465 
00466     // mark 4+ inputs gates as complex
00467     d->complexSet.insert("cross2x2");
00468     d->complexSet.insert("mux4");
00469     d->complexSet.insert("and5");
00470     d->complexSet.insert( "or5");
00471     d->complexSet.insert("xor5");
00472     d->complexSet.insert("mul2x3");
00473     d->complexSet.insert("mul3x3-ca3x3");
00474     d->complexSet.insert("mul3x3-ca4x4");
00475 }
00476 
00477 CaEvaluatorFactory::~CaEvaluatorFactory() {
00478     delete d;
00479 }
00480 
00481 CaEvaluator* CaEvaluatorFactory::create(const std::string &what) {
00482     // circuit lookup
00483     Private::TMap::iterator i = d->map.find(what);
00484     if (i != d->map.end())
00485         return (i->second)();
00486 
00487     // circuit not found
00488     // throw an exception containing list of available circuits
00489     std::ostringstream str;
00490     str << "invalid circuit: "
00491         << Color(C_LIGHT_RED) << what << Color(C_NO_COLOR)
00492         << " (implemented circuits are: " << Color(C_LIGHT_BLUE);
00493     for (i = d->map.begin(); i != d->map.end(); ++i) {
00494         if (i != d->map.begin())
00495             str << ", ";
00496         str << i->first;
00497     }
00498     str << Color(C_NO_COLOR) << ")";
00499     throw std::runtime_error(str.str());
00500 }
00501 
00502 void CaEvaluatorFactory::printList(std::ostream &str) {
00503     Private::TMap::iterator i;
00504     for (i = d->map.begin(); i != d->map.end(); ++i) {
00505 #if !GF_INCLUDE_TRIVIAL
00506         if (d->trivialSet.end() != d->trivialSet.find(i->first))
00507             continue;
00508 #endif
00509 #if !GF_INCLUDE_COMPLEX
00510         if (d->complexSet.end() != d->complexSet.find(i->first))
00511             continue;
00512 #endif
00513         str << i->first << std::endl;
00514     }
00515 }

Generated on Sat May 2 16:39:31 2009 for nucad by  doxygen 1.5.4