Non-Uniform CA Designer (C++, GAlib, Boost)
File detail
Source code
/*
* Copyright (C) 2009 Kamil Dudka <xdudka00@stud.fit.vutbr.cz>
*
* This file is part of nucad (Non-Uniform CA Designer).
*
* nucad is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* nucad 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 nucad. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file CaFactory.h
* Basic building blocks of simulated circuits, generic implementation of common
* gates and templates from their binding to CA.
*/
#ifndef CA_FACTORY_H
#define CA_FACTORY_H
#include "Ca.h"
#ifndef BUILDING_DOX
# include <string>
#endif
class CaEvaluator;
/**
* Class responsible for evaluators creation. Available evaluators are
* registered in the constructor and then addressed by name.
*/
class CaEvaluatorFactory {
public:
CaEvaluatorFactory();
~CaEvaluatorFactory();
/**
* Return newly allocated object of CaEvaluator corresponding to given
* name.
* @param name Name of evaluator to create.
*/
CaEvaluator *create(const std::string &name);
/**
* Print list of available evaluator's names to stream.
* The list can be filtered by GF_INCLUDE_TRIVIAL and GF_INCLUDE_COMPLEX
* compile-time options.
* @param str Standard output stream to write the list to.
*/
void printList(std::ostream &str);
private:
struct Private;
Private *d;
};
/// compile-time assertion (used to check binding)
template <bool> struct CT_ASSERT;
/// compile-time assertion (used to check binding)
template <> struct CT_ASSERT <true> { };
/**
* Empty IGateBinding implementation which binds nothing.
* It is mainly used by BindInput and BindOutput as default template parameter.
*/
class BindNothing
#ifndef BUILDING_DOX
: public IGateBinding
#endif
{
public:
static const TBus BOUND_INPUTS = 0;
static const TBus BOUND_OUTPUTS = 0;
public:
virtual IGateBinding* clone() const {
return new BindNothing(*this);
}
virtual void setInput(CaState &, TBus) const {
}
virtual void setOutput(CaState &, TBus) const {
}
virtual TBus getOutput(const CaState &) const {
return 0;
}
};
/**
* Template for input wire binding.
* @param INPUT Input wire index in range <0, n-1>.
* @param ROW CA's row index in range <0, caSize-1>.
* @param COL CA's column index in range <0, caSize-1>.
* @param PARENT Another class implementing IGateBinding interface used as
* a base class.
*/
template <int INPUT, int ROW, int COL, class PARENT = BindNothing>
class BindInput:
#ifdef BUILDING_DOX
public IGateBinding
#else
public PARENT
#endif
{
public:
static const TBus MASK = 1 << INPUT;
static const TBus BOUND_INPUTS = PARENT::BOUND_INPUTS | MASK;
static const TBus BOUND_OUTPUTS = PARENT::BOUND_OUTPUTS;
public:
virtual IGateBinding* clone() const {
return new BindInput(*this);
}
virtual void setInput(CaState &ca, TBus in) const {
PARENT::setInput(ca, in);
ca.setCellAtPos(Pos(ROW, COL), in & MASK);
}
private:
// abort compilation if input INPUT is already bound
CT_ASSERT<!(PARENT::BOUND_INPUTS & MASK)>
___COMPILE_TIME_ERROR__INPUT_ALREADY_BOUND___;
};
/**
* Template for output wire binding.
* @param OUTPUT Output wire index in range <0, n-1>.
* @param ROW CA's row index in range <0, caSize-1>.
* @param COL CA's column index in range <0, caSize-1>.
* @param PARENT Another class implementing IGateBinding interface used as
* a base class.
*/
template <int OUTPUT, int ROW, int COL, class PARENT = BindNothing>
class BindOutput:
#ifdef BUILDING_DOX
public IGateBinding
#else
public PARENT
#endif
{
public:
static const TBus MASK = 1 << OUTPUT;
static const TBus BOUND_INPUTS = PARENT::BOUND_INPUTS;
static const TBus BOUND_OUTPUTS = PARENT::BOUND_OUTPUTS | MASK;
public:
virtual IGateBinding* clone() const {
return new BindOutput(*this);
}
virtual void setOutput(CaState &ca, TBus out) const {
PARENT::setOutput(ca, out);
ca.setCellAtPos(Pos(ROW, COL), out & MASK);
}
virtual TBus getOutput(const CaState &ca) const {
TBus val = ca.getCellAtPos(Pos(ROW,COL));
val <<= OUTPUT;
val |= PARENT::getOutput(ca);
return val;
}
private:
// abort compilation if output OUTPUT is already bound
CT_ASSERT<!(PARENT::BOUND_OUTPUTS & MASK)>
___COMPILE_TIME_ERROR__OUTPUT_ALREADY_BOUND___;
};
/**
* Abstract IGate implementation defining gate's interface only.
* The behavior has to be defined in the derived class and the clone() method
* as well.
* @param N_IN Count of input signals.
* @param N_OUT Count of output signals.
*/
template <int N_IN, int N_OUT>
class AbstractGate: public IGate {
public:
virtual size_t nInputs() const {
return N_IN;
}
virtual size_t nOutputs() const {
return N_OUT;
}
};
/**
* Trivial gate's implementation which gives its input to its output unchanged.
* @param N Count of input/output signals.
*/
template <int N>
class BusGate: public AbstractGate<N, N> {
public:
virtual IGate* clone() const {
return new BusGate(*this);
}
virtual TBus operator[] (TBus in) const {
return in;
}
};
/**
* Same as BusGate, but output wires are connected in reverse order.
* @param N Count of input/output signals.
*/
template <int N>
class CrossGate: public AbstractGate<N, N> {
public:
virtual IGate* clone() const {
return new CrossGate(*this);
}
virtual TBus operator[] (TBus in) const {
TBus out = 0;
for (int i = 0; i < N; ++i) {
const TBus mask = 1 << (N - 1 -i);
if (in & mask)
out |= 1 << i;
}
return out;
}
};
/**
* Logical multiplier. Number of outputs is equal to total count of inputs.
* Half of input is used as operand A and the rest of input is used as operand
* B. If N is odd number, count of A wires is less than count of B wires.
* @param N Count if input/output signals.
*/
template <int N>
class MulGate: public AbstractGate<N, N> {
static const int A = N >> 1;
static const int B = N - A;
public:
virtual IGate* clone() const {
return new MulGate(*this);
}
virtual TBus operator[] (TBus in) const {
TBus inA = in & ((1 << A) - 1);
in >>= A;
TBus inB = in & ((1 << B) - 1);
TBus out = inA * inB;
return out & ((1 << N) - 1);
}
};
/**
* Common base class for all gates defined by a binary operator.
* There is always only one output wire.
* @param N Count of input signals.
*/
template <int N>
class CommonGateBase: public AbstractGate<N, 1> {
public:
virtual TBus operator[] (TBus in) const {
bool out = this->init();
for (unsigned i = 0; i < N; ++i)
this->perform (out, in & (1 << i));
return out;
}
protected:
/**
* Override this method to initialize output value.
* @return Return value used for output initialization.
*/
virtual bool init() const = 0;
/**
* Override this method to define the binary operator.
* @param out Reference to output signal.
* @param in Corresponding part of input which is being processed.
*/
virtual void perform(bool &out, bool in) const = 0;
};
/**
* AND gate generic implementation. See CommonGateBase documentation.
* @param N Count of input signals.
*/
template <int N>
class AndGate: public CommonGateBase<N> {
public:
virtual IGate* clone() const {
return new AndGate(*this);
}
protected:
virtual bool init() const {
return true;
}
virtual void perform(bool &out, bool in) const {
out &= in;
}
};
/**
* OR gate generic implementation. See CommonGateBase documentation.
* @param N Count of input signals.
*/
template <int N>
class OrGate: public CommonGateBase<N> {
public:
virtual IGate* clone() const {
return new OrGate(*this);
}
protected:
virtual bool init() const {
return false;
}
virtual void perform(bool &out, bool in) const {
out |= in;
}
};
/**
* XOR gate generic implementation. See CommonGateBase documentation.
* @param N Count of input signals.
*/
template <int N>
class XorGate: public CommonGateBase<N> {
public:
virtual IGate* clone() const {
return new XorGate(*this);
}
protected:
virtual bool init() const {
return false;
}
virtual void perform(bool &out, bool in) const {
out ^= in;
}
};
#endif // CA_FACTORY_H