00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
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
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
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
00439 d->map["and5"] = GateFactory <AndGate, 5> ::create;
00440 d->map[ "or5"] = GateFactory < OrGate, 5> ::create;
00441
00442
00443
00444 d->map["xor5"] = GateFactory <XorGate, 5> ::create;
00445
00446
00447 d->map["cross2"] = WireCrossFactory <2> ::create;
00448 d->map["cross3"] = WireCrossFactory <3> ::create;
00449 d->map["cross2x2"] = WireCrossFactory <4, BusGate> ::create;
00450
00451
00452
00453 d->map["mux4"] = Mux4Factory::create;
00454
00455
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
00461 d->trivialSet.insert("and2");
00462 d->trivialSet.insert( "or2");
00463 d->trivialSet.insert("xor2");
00464 d->trivialSet.insert("cross2");
00465
00466
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
00483 Private::TMap::iterator i = d->map.find(what);
00484 if (i != d->map.end())
00485 return (i->second)();
00486
00487
00488
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 }