English
Kamil Dudka

Non-Uniform CA Designer (C++, GAlib, Boost)

Detail souboru

Jméno:StáhnoutCaFactory.h [Stáhnout]
Umístění: nucad > src
Velikost:9.4 KB
Poslední změna:2022-09-09 13:06

Zdrojový kód

/*
 * 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