<commit_before>#ifndef _DBLAYER_HPP
#define _DBLAYER_HPP

#include <infra/util/Type.hpp>
#include <string>
#include <memory>
#include <vector>

#include <inttypes.h>

//#define AGGR_NO 0
//#define AGGR_SKIP_LAST 1
//#define AGGR_SKIP_2LAST 2

class DBLayer {
public:

    typedef enum { AGGR_NO, AGGR_SKIP_LAST, AGGR_SKIP_2LAST } Aggr_t;

    class Scan {
    public:
        virtual uint64_t getValue1() = 0;

        virtual uint64_t getValue2() = 0;

        virtual uint64_t getValue3() = 0;

        virtual uint64_t getCount() = 0;

        virtual bool next() = 0;

        virtual bool first() = 0;

        virtual bool first(uint64_t, bool) = 0;

        virtual bool first(uint64_t, bool, uint64_t, bool) = 0;

        virtual bool first(uint64_t, bool, uint64_t, bool, uint64_t, bool) = 0;

        virtual ~Scan() {}
    };

    class Hint {
    private:
	std::vector<uint64_t> *hashKeys = NULL;	// Keys of a hashjoin. Significant for the right iterator.
	int varbitset = 0;

    public:
	std::vector<uint64_t> *getKeys(int *bitset) {
	    if (bitset != NULL) {
		*bitset = varbitset;
	    }
	    return hashKeys;
	}

	void setKeys(std::vector<uint64_t> *keys, int bitset) {
	    hashKeys = keys;
	    varbitset = bitset;
	}

        virtual void next(uint64_t& value1,
                          uint64_t& value2,
                          uint64_t& value3) {
            throw 10;
        }

        virtual void next(uint64_t& value1,
                          uint64_t& value2) {
            throw 10;
        }

        virtual void next(uint64_t& value1) {
            throw 10;
        }
    };

    enum DataOrder {
        Order_Subject_Predicate_Object = 0,
        Order_Subject_Object_Predicate,
        Order_Object_Predicate_Subject,
        Order_Object_Subject_Predicate,
        Order_Predicate_Subject_Object,
        Order_Predicate_Object_Subject,
        Order_No_Order_SPO,
        Order_No_Order_SOP,
        Order_No_Order_OPS,
        Order_No_Order_OSP,
        Order_No_Order_POS,
        Order_No_Order_PSO,
    };

    virtual bool lookup(const std::string& text,
                        ::Type::ID type,
                        unsigned subType,
                        uint64_t& id) = 0;

    virtual bool lookupById(uint64_t id,
                            //char *output,
                            //size_t &length,
                            const char*& start,
                            const char*& stop,
                            ::Type::ID& type,
                            unsigned& subType) = 0;

    virtual uint64_t getNextId() = 0;

    virtual double getScanCost(DBLayer::DataOrder order,
                               uint64_t value1,
                               uint64_t value1C,
                               uint64_t value2,
                               uint64_t value2C,
                               uint64_t value3,
                               uint64_t value3C) = 0;

    virtual double getScanCost(DBLayer::DataOrder order,
                               uint64_t value1,
                               uint64_t value1C,
                               uint64_t value2,
                               uint64_t value2C) = 0;

    virtual double getJoinSelectivity(bool valueL1,
                                      uint64_t value1CL,
                                      bool value2L,
                                      uint64_t value2CL,
                                      bool value3L,
                                      uint64_t value3CL,
                                      bool value1R,
                                      uint64_t value1CR,
                                      bool value2R,
                                      uint64_t value2CR,
                                      bool value3R,
                                      uint64_t value3CR) = 0;

    virtual double getScanCost(DBLayer::DataOrder order,
                               uint64_t value1,
                               uint64_t value1C) = 0;

    virtual uint64_t getCardinality(uint64_t c1,
                                    uint64_t c2,
                                    uint64_t c3) = 0;

    virtual uint64_t getCardinality() = 0;

    virtual std::unique_ptr<DBLayer::Scan> getScan(const DataOrder order,
            const Aggr_t aggr,
            Hint *hint) = 0;
};

#endif
<commit_msg>Added virtual destructor for DBLayer<commit_after>#ifndef _DBLAYER_HPP
#define _DBLAYER_HPP

#include <infra/util/Type.hpp>
#include <string>
#include <memory>
#include <vector>

#include <inttypes.h>

//#define AGGR_NO 0
//#define AGGR_SKIP_LAST 1
//#define AGGR_SKIP_2LAST 2

class DBLayer {
public:

    typedef enum { AGGR_NO, AGGR_SKIP_LAST, AGGR_SKIP_2LAST } Aggr_t;

    class Scan {
    public:
        virtual uint64_t getValue1() = 0;

        virtual uint64_t getValue2() = 0;

        virtual uint64_t getValue3() = 0;

        virtual uint64_t getCount() = 0;

        virtual bool next() = 0;

        virtual bool first() = 0;

        virtual bool first(uint64_t, bool) = 0;

        virtual bool first(uint64_t, bool, uint64_t, bool) = 0;

        virtual bool first(uint64_t, bool, uint64_t, bool, uint64_t, bool) = 0;

        virtual ~Scan() {}
    };

    class Hint {
    private:
	std::vector<uint64_t> *hashKeys = NULL;	// Keys of a hashjoin. Significant for the right iterator.
	int varbitset = 0;

    public:
	std::vector<uint64_t> *getKeys(int *bitset) {
	    if (bitset != NULL) {
		*bitset = varbitset;
	    }
	    return hashKeys;
	}

	void setKeys(std::vector<uint64_t> *keys, int bitset) {
	    hashKeys = keys;
	    varbitset = bitset;
	}

        virtual void next(uint64_t& value1,
                          uint64_t& value2,
                          uint64_t& value3) {
            throw 10;
        }

        virtual void next(uint64_t& value1,
                          uint64_t& value2) {
            throw 10;
        }

        virtual void next(uint64_t& value1) {
            throw 10;
        }
    };

    enum DataOrder {
        Order_Subject_Predicate_Object = 0,
        Order_Subject_Object_Predicate,
        Order_Object_Predicate_Subject,
        Order_Object_Subject_Predicate,
        Order_Predicate_Subject_Object,
        Order_Predicate_Object_Subject,
        Order_No_Order_SPO,
        Order_No_Order_SOP,
        Order_No_Order_OPS,
        Order_No_Order_OSP,
        Order_No_Order_POS,
        Order_No_Order_PSO,
    };

    virtual bool lookup(const std::string& text,
                        ::Type::ID type,
                        unsigned subType,
                        uint64_t& id) = 0;

    virtual bool lookupById(uint64_t id,
                            //char *output,
                            //size_t &length,
                            const char*& start,
                            const char*& stop,
                            ::Type::ID& type,
                            unsigned& subType) = 0;

    virtual uint64_t getNextId() = 0;

    virtual double getScanCost(DBLayer::DataOrder order,
                               uint64_t value1,
                               uint64_t value1C,
                               uint64_t value2,
                               uint64_t value2C,
                               uint64_t value3,
                               uint64_t value3C) = 0;

    virtual double getScanCost(DBLayer::DataOrder order,
                               uint64_t value1,
                               uint64_t value1C,
                               uint64_t value2,
                               uint64_t value2C) = 0;

    virtual double getJoinSelectivity(bool valueL1,
                                      uint64_t value1CL,
                                      bool value2L,
                                      uint64_t value2CL,
                                      bool value3L,
                                      uint64_t value3CL,
                                      bool value1R,
                                      uint64_t value1CR,
                                      bool value2R,
                                      uint64_t value2CR,
                                      bool value3R,
                                      uint64_t value3CR) = 0;

    virtual double getScanCost(DBLayer::DataOrder order,
                               uint64_t value1,
                               uint64_t value1C) = 0;

    virtual uint64_t getCardinality(uint64_t c1,
                                    uint64_t c2,
                                    uint64_t c3) = 0;

    virtual uint64_t getCardinality() = 0;

    virtual std::unique_ptr<DBLayer::Scan> getScan(const DataOrder order,
            const Aggr_t aggr,
            Hint *hint) = 0;

    virtual ~DBLayer() {
    }
};

#endif
<|endoftext|>


<commit_before>
#include "EflagsExpressions.h"
#include "Registers.h"

std::string EflagsExpressions::af(SymbolicElement *parent,
                                  uint32_t bvSize,
                                  std::stringstream &op1,
                                  std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * af = 0x10 == (0x10 & (regDst ^ op1 ^ op2))
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::bv(0x10, bvSize),
              smt2lib::bvand(
                smt2lib::bv(0x10, bvSize),
                smt2lib::bvxor(
                  parent->getID2Str(),
                  smt2lib::bvxor(op1.str(), op2.str())
                )
              )
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::afNeg(SymbolicElement *parent,
                                     uint32_t bvSize,
                                     std::stringstream &op1)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * af = 0x10 == (0x10 & (op1 ^ regDst))
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::bv(0x10, bvSize),
              smt2lib::bvand(
                smt2lib::bv(0x10, bvSize),
                smt2lib::bvxor(
                  op1.str(),
                  parent->getID2Str()
                )
              )
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::cfAdd(SymbolicElement *parent,
                                     std::stringstream &op1)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * cf = regDst < op1
   */
  expr << smt2lib::ite(
            smt2lib::bvult(
              parent->getID2Str(),
              op1.str()
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::cfNeg(uint32_t bvSize,
                                     std::stringstream &op1)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * cf = 0 if op1 == 0 else 1
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              op1.str(),
              smt2lib::bv(0, bvSize)
            ),
            smt2lib::bv(0, 1),
            smt2lib::bv(1, 1));

  return expr.str();
}

std::string EflagsExpressions::cfSar(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * if op2 != 0:
   *   if op2 > bvSize:
   *     cf.id = ((op1 >> (bvSize - 1)) & 1)
   *   else:
   *     cf.id = ((op1 >> (op2 - 1)) & 1)
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(0, bvSize)),
            ap.buildSymbolicFlagOperand(ID_CF),
            smt2lib::ite(
              smt2lib::bvugt(op2.str(), smt2lib::bv(bvSize, bvSize)),
              smt2lib::extract(0, 0, smt2lib::bvlshr(op1.str(), smt2lib::bvsub(smt2lib::bv(bvSize, bvSize), smt2lib::bv(1, bvSize)))),
              smt2lib::extract(0, 0, smt2lib::bvlshr(op1.str(), smt2lib::bvsub(op2.str(), smt2lib::bv(1, bvSize))))
            )
          );

  return expr.str();
}

std::string EflagsExpressions::cfShl(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * cf = (op1 >> (bvSize - op2) & 1) if op2 != 0
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(0, bvSize)),
            ap.buildSymbolicFlagOperand(ID_CF),
            smt2lib::extract(0, 0, smt2lib::bvlshr(op1.str(), smt2lib::bvsub(smt2lib::bv(bvSize, bvSize), op2.str())))
          );

  return expr.str();
}

std::string EflagsExpressions::cfShr(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * cf = ((op1 >> (op2 - 1)) & 1) if op2 != 0
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(0, bvSize)),
            ap.buildSymbolicFlagOperand(ID_CF),
            smt2lib::extract(0, 0, smt2lib::bvlshr(op1.str(), smt2lib::bvsub(op2.str(), smt2lib::bv(1, bvSize))))
          );

  return expr.str();
}

std::string EflagsExpressions::cfSub(std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * cf = op1 < op2
   */
  expr << smt2lib::ite(
            smt2lib::bvult(
              op1.str(),
              op2.str()
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::clearFlag(void)
{
  std::stringstream expr;

  expr << smt2lib::bv(0, 1);

  return expr.str();
}

std::string EflagsExpressions::ofAdd(SymbolicElement *parent,
                                     uint32_t extractSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * of = high:bool((op1 ^ ~op2) & (op1 ^ regDst))
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::extract(extractSize, extractSize,
                smt2lib::bvand(
                  smt2lib::bvxor(op1.str(), smt2lib::bvnot(op2.str())),
                  smt2lib::bvxor(op1.str(), parent->getID2Str())
                )
              ),
              smt2lib::bv(1, 1)
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::ofNeg(SymbolicElement *parent,
                                     uint32_t bvSize,
                                     std::stringstream &op1)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * of = bit_cast((res & op1) >> (bvSize - 1), int1(1));
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::extract(0, 0,
                smt2lib::bvshl(
                  smt2lib::bvand(parent->getID2Str(), op1.str()),
                  smt2lib::bvsub(smt2lib::bv(bvSize, bvSize), smt2lib::bv(1, bvSize))
                )
              ),
              smt2lib::bv(1, 1)
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::ofSar(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * of = 0 if op2 == 1
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(1, bvSize)),
            smt2lib::bv(0, 1),
            ap.buildSymbolicFlagOperand(ID_OF)
          );

  return expr.str();
}

std::string EflagsExpressions::ofShl(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * of = bit_cast((op1 >> (bvSize - 1)) ^ (op1 >> (bvSize - 2)), int1(1)); if op2 == 1
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(1, bvSize)),
            smt2lib::extract(0, 0,
              smt2lib::bvxor(
                smt2lib::bvlshr(op1.str(), smt2lib::bvsub(smt2lib::bv(bvSize, bvSize), smt2lib::bv(1, bvSize))),
                smt2lib::bvlshr(op1.str(), smt2lib::bvsub(smt2lib::bv(bvSize, bvSize), smt2lib::bv(2, bvSize)))
              )
            ),
            ap.buildSymbolicFlagOperand(ID_OF)
          );

  return expr.str();
}

std::string EflagsExpressions::ofShr(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * of = (op1 >> (bvSize - 1) & 1) if op2 == 1
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(1, bvSize)),
            smt2lib::extract(0, 0,
                smt2lib::bvlshr(op1.str(), smt2lib::bvsub(smt2lib::bv(bvSize, bvSize), smt2lib::bv(1, bvSize)))
            ),
            ap.buildSymbolicFlagOperand(ID_OF)
          );

  return expr.str();
}

std::string EflagsExpressions::ofSub(SymbolicElement *parent,
                                     uint32_t extractSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * of = high:bool((op1 ^ op2) & (op1 ^ regDst))
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::extract(extractSize, extractSize,
                smt2lib::bvand(
                  smt2lib::bvxor(op1.str(), op2.str()),
                  smt2lib::bvxor(op1.str(), parent->getID2Str())
                )
              ),
              smt2lib::bv(1, 1)
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::pf(SymbolicElement *parent)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   *
   * pf is set to one if there is a even number of bit set to 1 in the least
   * significant byte of the result.
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::parityFlag(
                smt2lib::extract(7, 0, parent->getID2Str())),
              smt2lib::bv(0, 1)
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::pfShl(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * pf if op2 != 0
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(0, bvSize)),
            ap.buildSymbolicFlagOperand(ID_PF),
            EflagsExpressions::pf(parent)
          );

  return expr.str();
}

std::string EflagsExpressions::setFlag(void)
{
  std::stringstream expr;

  expr << smt2lib::bv(1, 1);

  return expr.str();
}

std::string EflagsExpressions::sf(SymbolicElement *parent,
                                  uint32_t extractSize)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * sf = high:bool(regDst)
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::extract(extractSize, extractSize, parent->getID2Str()),
              smt2lib::bv(1, 1)
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::sfShl(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     uint32_t extractSize,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * sf if op2 != 0
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(0, bvSize)),
            ap.buildSymbolicFlagOperand(ID_SF),
            EflagsExpressions::sf(parent, extractSize)
          );

  return expr.str();
}

std::string EflagsExpressions::zf(SymbolicElement *parent,
                                  uint32_t bvSize)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * zf = 0 == regDst
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              parent->getID2Str(),
              smt2lib::bv(0, bvSize)
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::zfShl(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * zf if op2 != 0
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(0, bvSize)),
            ap.buildSymbolicFlagOperand(ID_ZF),
            EflagsExpressions::zf(parent, bvSize)
          );

  return expr.str();
}

<commit_msg>Fix indent<commit_after>
#include "EflagsExpressions.h"
#include "Registers.h"

std::string EflagsExpressions::af(SymbolicElement *parent,
                                  uint32_t bvSize,
                                  std::stringstream &op1,
                                  std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * af = 0x10 == (0x10 & (regDst ^ op1 ^ op2))
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::bv(0x10, bvSize),
              smt2lib::bvand(
                smt2lib::bv(0x10, bvSize),
                smt2lib::bvxor(
                  parent->getID2Str(),
                  smt2lib::bvxor(op1.str(), op2.str())
                )
              )
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::afNeg(SymbolicElement *parent,
                                     uint32_t bvSize,
                                     std::stringstream &op1)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * af = 0x10 == (0x10 & (op1 ^ regDst))
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::bv(0x10, bvSize),
              smt2lib::bvand(
                smt2lib::bv(0x10, bvSize),
                smt2lib::bvxor(
                  op1.str(),
                  parent->getID2Str()
                )
              )
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::cfAdd(SymbolicElement *parent,
                                     std::stringstream &op1)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * cf = regDst < op1
   */
  expr << smt2lib::ite(
            smt2lib::bvult(
              parent->getID2Str(),
              op1.str()
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::cfNeg(uint32_t bvSize,
                                     std::stringstream &op1)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * cf = 0 if op1 == 0 else 1
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              op1.str(),
              smt2lib::bv(0, bvSize)
            ),
            smt2lib::bv(0, 1),
            smt2lib::bv(1, 1));

  return expr.str();
}

std::string EflagsExpressions::cfSar(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * if op2 != 0:
   *   if op2 > bvSize:
   *     cf.id = ((op1 >> (bvSize - 1)) & 1)
   *   else:
   *     cf.id = ((op1 >> (op2 - 1)) & 1)
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(0, bvSize)),
            ap.buildSymbolicFlagOperand(ID_CF),
            smt2lib::ite(
              smt2lib::bvugt(op2.str(), smt2lib::bv(bvSize, bvSize)),
              smt2lib::extract(0, 0, smt2lib::bvlshr(op1.str(), smt2lib::bvsub(smt2lib::bv(bvSize, bvSize), smt2lib::bv(1, bvSize)))),
              smt2lib::extract(0, 0, smt2lib::bvlshr(op1.str(), smt2lib::bvsub(op2.str(), smt2lib::bv(1, bvSize))))
            )
          );

  return expr.str();
}

std::string EflagsExpressions::cfShl(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * cf = (op1 >> (bvSize - op2) & 1) if op2 != 0
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(0, bvSize)),
            ap.buildSymbolicFlagOperand(ID_CF),
            smt2lib::extract(0, 0, smt2lib::bvlshr(op1.str(), smt2lib::bvsub(smt2lib::bv(bvSize, bvSize), op2.str())))
          );

  return expr.str();
}

std::string EflagsExpressions::cfShr(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * cf = ((op1 >> (op2 - 1)) & 1) if op2 != 0
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(0, bvSize)),
            ap.buildSymbolicFlagOperand(ID_CF),
            smt2lib::extract(0, 0, smt2lib::bvlshr(op1.str(), smt2lib::bvsub(op2.str(), smt2lib::bv(1, bvSize))))
          );

  return expr.str();
}

std::string EflagsExpressions::cfSub(std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * cf = op1 < op2
   */
  expr << smt2lib::ite(
            smt2lib::bvult(
              op1.str(),
              op2.str()
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::clearFlag(void)
{
  std::stringstream expr;

  expr << smt2lib::bv(0, 1);

  return expr.str();
}

std::string EflagsExpressions::ofAdd(SymbolicElement *parent,
                                     uint32_t extractSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * of = high:bool((op1 ^ ~op2) & (op1 ^ regDst))
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::extract(extractSize, extractSize,
                smt2lib::bvand(
                  smt2lib::bvxor(op1.str(), smt2lib::bvnot(op2.str())),
                  smt2lib::bvxor(op1.str(), parent->getID2Str())
                )
              ),
              smt2lib::bv(1, 1)
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::ofNeg(SymbolicElement *parent,
                                     uint32_t bvSize,
                                     std::stringstream &op1)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * of = bit_cast((res & op1) >> (bvSize - 1), int1(1));
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::extract(0, 0,
                smt2lib::bvshl(
                  smt2lib::bvand(parent->getID2Str(), op1.str()),
                  smt2lib::bvsub(smt2lib::bv(bvSize, bvSize), smt2lib::bv(1, bvSize))
                )
              ),
              smt2lib::bv(1, 1)
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::ofSar(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * of = 0 if op2 == 1
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(1, bvSize)),
            smt2lib::bv(0, 1),
            ap.buildSymbolicFlagOperand(ID_OF)
          );

  return expr.str();
}

std::string EflagsExpressions::ofShl(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * of = bit_cast((op1 >> (bvSize - 1)) ^ (op1 >> (bvSize - 2)), int1(1)); if op2 == 1
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(1, bvSize)),
            smt2lib::extract(0, 0,
              smt2lib::bvxor(
                smt2lib::bvlshr(op1.str(), smt2lib::bvsub(smt2lib::bv(bvSize, bvSize), smt2lib::bv(1, bvSize))),
                smt2lib::bvlshr(op1.str(), smt2lib::bvsub(smt2lib::bv(bvSize, bvSize), smt2lib::bv(2, bvSize)))
              )
            ),
            ap.buildSymbolicFlagOperand(ID_OF)
          );

  return expr.str();
}

std::string EflagsExpressions::ofShr(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * of = (op1 >> (bvSize - 1) & 1) if op2 == 1
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(1, bvSize)),
            smt2lib::extract(0, 0,
                smt2lib::bvlshr(op1.str(), smt2lib::bvsub(smt2lib::bv(bvSize, bvSize), smt2lib::bv(1, bvSize)))
            ),
            ap.buildSymbolicFlagOperand(ID_OF)
          );

  return expr.str();
}

std::string EflagsExpressions::ofSub(SymbolicElement *parent,
                                     uint32_t extractSize,
                                     std::stringstream &op1,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * of = high:bool((op1 ^ op2) & (op1 ^ regDst))
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::extract(extractSize, extractSize,
                smt2lib::bvand(
                  smt2lib::bvxor(op1.str(), op2.str()),
                  smt2lib::bvxor(op1.str(), parent->getID2Str())
                )
              ),
              smt2lib::bv(1, 1)
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::pf(SymbolicElement *parent)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   *
   * pf is set to one if there is a even number of bit set to 1 in the least
   * significant byte of the result.
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::parityFlag(
                smt2lib::extract(7, 0, parent->getID2Str())),
              smt2lib::bv(0, 1)
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::pfShl(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * pf if op2 != 0
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(0, bvSize)),
            ap.buildSymbolicFlagOperand(ID_PF),
            EflagsExpressions::pf(parent)
          );

  return expr.str();
}

std::string EflagsExpressions::setFlag(void)
{
  std::stringstream expr;

  expr << smt2lib::bv(1, 1);

  return expr.str();
}

std::string EflagsExpressions::sf(SymbolicElement *parent,
                                  uint32_t extractSize)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * sf = high:bool(regDst)
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              smt2lib::extract(extractSize, extractSize, parent->getID2Str()),
              smt2lib::bv(1, 1)
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::sfShl(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     uint32_t extractSize,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * sf if op2 != 0
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(0, bvSize)),
            ap.buildSymbolicFlagOperand(ID_SF),
            EflagsExpressions::sf(parent, extractSize)
          );

  return expr.str();
}

std::string EflagsExpressions::zf(SymbolicElement *parent,
                                  uint32_t bvSize)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * zf = 0 == regDst
   */
  expr << smt2lib::ite(
            smt2lib::equal(
              parent->getID2Str(),
              smt2lib::bv(0, bvSize)
            ),
            smt2lib::bv(1, 1),
            smt2lib::bv(0, 1)
          );

  return expr.str();
}

std::string EflagsExpressions::zfShl(SymbolicElement *parent,
                                     AnalysisProcessor &ap,
                                     uint32_t bvSize,
                                     std::stringstream &op2)
{
  std::stringstream expr;

  /*
   * Create the SMT semantic.
   * zf if op2 != 0
   */
  expr << smt2lib::ite(
            smt2lib::equal(op2.str(), smt2lib::bv(0, bvSize)),
            ap.buildSymbolicFlagOperand(ID_ZF),
            EflagsExpressions::zf(parent, bvSize)
          );

  return expr.str();
}

<|endoftext|>


<commit_before>/* Copyright 2007-2015 QReal Research Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "interpreterCore/interpreter/interpreter.h"

#include <QtCore/QCoreApplication>
#include <QtWidgets/QAction>

#include <qrtext/languageToolboxInterface.h>

#include <utils/timelineInterface.h>
#include <kitBase/robotModel/robotModelInterface.h>

using namespace qReal;
using namespace interpreterCore::interpreter;
using namespace kitBase::robotModel;

const Id startingElementType = Id("RobotsMetamodel", "RobotsDiagram", "InitialNode");
const int maxThreadsCount = 100;

Interpreter::Interpreter(const GraphicalModelAssistInterface &graphicalModelApi
		, LogicalModelAssistInterface &logicalModelApi
		, qReal::gui::MainWindowInterpretersInterface &interpretersInterface
		, const qReal::ProjectManagementInterface &projectManager
		, BlocksFactoryManagerInterface &blocksFactoryManager
		, const kitBase::robotModel::RobotModelManagerInterface &robotModelManager
		, qrtext::LanguageToolboxInterface &languageToolbox
		, QAction &connectToRobotAction
		)
	: mGraphicalModelApi(graphicalModelApi)
	, mLogicalModelApi(logicalModelApi)
	, mInterpretersInterface(interpretersInterface)
	, mState(idle)
	, mRobotModelManager(robotModelManager)
	, mBlocksTable(new details::BlocksTable(blocksFactoryManager, robotModelManager))
	, mActionConnectToRobot(connectToRobotAction)
	, mSensorVariablesUpdater(robotModelManager, languageToolbox)
	, mAutoconfigurer(mGraphicalModelApi, *mBlocksTable, *mInterpretersInterface.errorReporter())
	, mLanguageToolbox(languageToolbox)
{
	// Other components may want to subscribe to allDevicesConfigured() signal because
	// it seems to be the only way to perform robot devices additional initialization.
	// We must let them work out before interpretation starts, so creating queued connection.
	connect(
			&mRobotModelManager
			, &kitBase::robotModel::RobotModelManagerInterface::allDevicesConfigured
			, this
			, &Interpreter::devicesConfiguredSlot
			, Qt::QueuedConnection
			);

	connect(
			&mRobotModelManager
			, &kitBase::robotModel::RobotModelManagerInterface::connected
			, this
			, &Interpreter::connectedSlot
			);

	connect(&projectManager, &qReal::ProjectManagementInterface::beforeOpen, this, &Interpreter::userStopRobot);

	connectDevicesConfigurationProvider(&mAutoconfigurer);
}

Interpreter::~Interpreter()
{
	qDeleteAll(mThreads);
	delete mBlocksTable;
}

void Interpreter::interpret()
{
	mInterpretersInterface.errorReporter()->clear();

	if (mRobotModelManager.model().connectionState() != RobotModelInterface::connectedState) {
		mInterpretersInterface.errorReporter()->addInformation(tr("No connection to robot"));
		return;
	}

	if (mState != idle) {
		mInterpretersInterface.errorReporter()->addInformation(tr("Interpreter is already running"));
		return;
	}

	mRobotModelManager.model().stopRobot();
	mBlocksTable->clear();
	mState = waitingForDevicesConfiguredToLaunch;

	if (!mAutoconfigurer.configure(mGraphicalModelApi.children(Id::rootId()), mRobotModelManager.model().robotId())) {
		return;
	}

	mLanguageToolbox.clear();

	/// @todo Temporarily loading initial configuration from a network of SensorConfigurationProviders.
	///       To be done more adequately.
	const QString modelName = mRobotModelManager.model().robotId();
	for (const PortInfo &port : mRobotModelManager.model().configurablePorts()) {
		const DeviceInfo deviceInfo = currentConfiguration(modelName, port);
		mRobotModelManager.model().configureDevice(port, deviceInfo);
	}

	mRobotModelManager.model().applyConfiguration();
}

void Interpreter::stopRobot(qReal::interpretation::StopReason reason)
{
	mSensorVariablesUpdater.suspend();
	mRobotModelManager.model().stopRobot();
	mState = idle;
	qDeleteAll(mThreads);
	mThreads.clear();
	mBlocksTable->setFailure();
	emit stopped(reason);
}

int Interpreter::timeElapsed() const
{
	return mState == interpreting
			? mRobotModelManager.model().timeline().timestamp() - mInterpretationStartedTimestamp
			: 0;
}

void Interpreter::connectedSlot(bool success, const QString &errorString)
{
	if (success) {
		if (mRobotModelManager.model().needsConnection()) {
			mInterpretersInterface.errorReporter()->addInformation(tr("Connected successfully"));
		}
	} else {
		if (errorString.isEmpty()) {
			mInterpretersInterface.errorReporter()->addError(tr("Can't connect to a robot."));
		} else {
			mInterpretersInterface.errorReporter()->addError(errorString);
		}
	}

	mActionConnectToRobot.setChecked(success);
}

void Interpreter::devicesConfiguredSlot()
{
	if (mRobotModelManager.model().connectionState() != RobotModelInterface::connectedState) {
		mInterpretersInterface.errorReporter()->addInformation(tr("No connection to robot"));
		mState = idle;
		return;
	}

	if (mState == waitingForDevicesConfiguredToLaunch) {
		mState = interpreting;
		mInterpretationStartedTimestamp = mRobotModelManager.model().timeline().timestamp();

		mSensorVariablesUpdater.run();

		const Id &currentDiagramId = mInterpretersInterface.activeDiagram();

		qReal::interpretation::Thread * const initialThread = new qReal::interpretation::Thread(&mGraphicalModelApi
				, mInterpretersInterface, startingElementType, currentDiagramId, *mBlocksTable, "main");

		emit started();

		addThread(initialThread, "main");
	}
}

void Interpreter::threadStopped(qReal::interpretation::StopReason reason)
{
	qReal::interpretation::Thread * const thread = static_cast<qReal::interpretation::Thread *>(sender());

	mThreads.remove(thread->id());
	delete thread;

	if (mThreads.isEmpty()) {
		stopRobot(reason);
	}
}

void Interpreter::newThread(const Id &startBlockId, const QString &threadId)
{
	if (mThreads.contains(threadId)) {
		reportError(tr("Cannot create new thread with already occupied id %1").arg(threadId));
		stopRobot(qReal::interpretation::StopReason::error);
		return;
	}

	qReal::interpretation::Thread * const thread = new qReal::interpretation::Thread(&mGraphicalModelApi
			, mInterpretersInterface, startingElementType, *mBlocksTable, startBlockId, threadId);

	addThread(thread, threadId);
}

void Interpreter::addThread(qReal::interpretation::Thread * const thread, const QString &threadId)
{
	if (mThreads.count() >= maxThreadsCount) {
		reportError(tr("Threads limit exceeded. Maximum threads count is %1").arg(maxThreadsCount));
		stopRobot(qReal::interpretation::StopReason::error);
	}

	mThreads[threadId] = thread;
	connect(thread, &interpretation::Thread::stopped, this, &Interpreter::threadStopped);

	connect(thread, &qReal::interpretation::Thread::newThread, this, &Interpreter::newThread);
	connect(thread, &qReal::interpretation::Thread::killThread, this, &Interpreter::killThread);
	connect(thread, &qReal::interpretation::Thread::sendMessage, this, &Interpreter::sendMessage);

	QCoreApplication::processEvents();
	if (mState != idle) {
		thread->interpret();
	}
}

void Interpreter::killThread(const QString &threadId)
{
	if (mThreads.contains(threadId)) {
		mThreads[threadId]->stop();
	} else {
		reportError(tr("Killing non-existent thread %1").arg(threadId));
	}
}

void Interpreter::sendMessage(const QString &threadId, const QString &message)
{
	if (mThreads.contains(threadId)) {
		mThreads[threadId]->newMessage(message);
	}
}

void Interpreter::connectToRobot()
{
	if (mState == interpreting) {
		return;
	}

	if (mRobotModelManager.model().connectionState() == RobotModelInterface::connectedState) {
		mRobotModelManager.model().stopRobot();
		mRobotModelManager.model().disconnectFromRobot();
	} else {
		mRobotModelManager.model().connectToRobot();
	}

	mActionConnectToRobot.setChecked(
			mRobotModelManager.model().connectionState() == RobotModelInterface::connectedState);
}

void Interpreter::reportError(const QString &message)
{
	mInterpretersInterface.errorReporter()->addError(message);
}
<commit_msg>Fixed interpreter is already running error after sensors configuration conflict<commit_after>/* Copyright 2007-2015 QReal Research Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "interpreterCore/interpreter/interpreter.h"

#include <QtCore/QCoreApplication>
#include <QtWidgets/QAction>

#include <qrtext/languageToolboxInterface.h>

#include <utils/timelineInterface.h>
#include <kitBase/robotModel/robotModelInterface.h>

using namespace qReal;
using namespace interpreterCore::interpreter;
using namespace kitBase::robotModel;

const Id startingElementType = Id("RobotsMetamodel", "RobotsDiagram", "InitialNode");
const int maxThreadsCount = 100;

Interpreter::Interpreter(const GraphicalModelAssistInterface &graphicalModelApi
		, LogicalModelAssistInterface &logicalModelApi
		, qReal::gui::MainWindowInterpretersInterface &interpretersInterface
		, const qReal::ProjectManagementInterface &projectManager
		, BlocksFactoryManagerInterface &blocksFactoryManager
		, const kitBase::robotModel::RobotModelManagerInterface &robotModelManager
		, qrtext::LanguageToolboxInterface &languageToolbox
		, QAction &connectToRobotAction
		)
	: mGraphicalModelApi(graphicalModelApi)
	, mLogicalModelApi(logicalModelApi)
	, mInterpretersInterface(interpretersInterface)
	, mState(idle)
	, mRobotModelManager(robotModelManager)
	, mBlocksTable(new details::BlocksTable(blocksFactoryManager, robotModelManager))
	, mActionConnectToRobot(connectToRobotAction)
	, mSensorVariablesUpdater(robotModelManager, languageToolbox)
	, mAutoconfigurer(mGraphicalModelApi, *mBlocksTable, *mInterpretersInterface.errorReporter())
	, mLanguageToolbox(languageToolbox)
{
	// Other components may want to subscribe to allDevicesConfigured() signal because
	// it seems to be the only way to perform robot devices additional initialization.
	// We must let them work out before interpretation starts, so creating queued connection.
	connect(
			&mRobotModelManager
			, &kitBase::robotModel::RobotModelManagerInterface::allDevicesConfigured
			, this
			, &Interpreter::devicesConfiguredSlot
			, Qt::QueuedConnection
			);

	connect(
			&mRobotModelManager
			, &kitBase::robotModel::RobotModelManagerInterface::connected
			, this
			, &Interpreter::connectedSlot
			);

	connect(&projectManager, &qReal::ProjectManagementInterface::beforeOpen, this, &Interpreter::userStopRobot);

	connectDevicesConfigurationProvider(&mAutoconfigurer);
}

Interpreter::~Interpreter()
{
	qDeleteAll(mThreads);
	delete mBlocksTable;
}

void Interpreter::interpret()
{
	mInterpretersInterface.errorReporter()->clear();

	if (mRobotModelManager.model().connectionState() != RobotModelInterface::connectedState) {
		mInterpretersInterface.errorReporter()->addInformation(tr("No connection to robot"));
		return;
	}

	if (mState != idle) {
		mInterpretersInterface.errorReporter()->addInformation(tr("Interpreter is already running"));
		return;
	}

	mRobotModelManager.model().stopRobot();
	mBlocksTable->clear();
	mState = waitingForDevicesConfiguredToLaunch;

	if (!mAutoconfigurer.configure(mGraphicalModelApi.children(Id::rootId()), mRobotModelManager.model().robotId())) {
		mState = idle;
		return;
	}

	mLanguageToolbox.clear();

	/// @todo Temporarily loading initial configuration from a network of SensorConfigurationProviders.
	///       To be done more adequately.
	const QString modelName = mRobotModelManager.model().robotId();
	for (const PortInfo &port : mRobotModelManager.model().configurablePorts()) {
		const DeviceInfo deviceInfo = currentConfiguration(modelName, port);
		mRobotModelManager.model().configureDevice(port, deviceInfo);
	}

	mRobotModelManager.model().applyConfiguration();
}

void Interpreter::stopRobot(qReal::interpretation::StopReason reason)
{
	mSensorVariablesUpdater.suspend();
	mRobotModelManager.model().stopRobot();
	mState = idle;
	qDeleteAll(mThreads);
	mThreads.clear();
	mBlocksTable->setFailure();
	emit stopped(reason);
}

int Interpreter::timeElapsed() const
{
	return mState == interpreting
			? mRobotModelManager.model().timeline().timestamp() - mInterpretationStartedTimestamp
			: 0;
}

void Interpreter::connectedSlot(bool success, const QString &errorString)
{
	if (success) {
		if (mRobotModelManager.model().needsConnection()) {
			mInterpretersInterface.errorReporter()->addInformation(tr("Connected successfully"));
		}
	} else {
		if (errorString.isEmpty()) {
			mInterpretersInterface.errorReporter()->addError(tr("Can't connect to a robot."));
		} else {
			mInterpretersInterface.errorReporter()->addError(errorString);
		}
	}

	mActionConnectToRobot.setChecked(success);
}

void Interpreter::devicesConfiguredSlot()
{
	if (mRobotModelManager.model().connectionState() != RobotModelInterface::connectedState) {
		mInterpretersInterface.errorReporter()->addInformation(tr("No connection to robot"));
		mState = idle;
		return;
	}

	if (mState == waitingForDevicesConfiguredToLaunch) {
		mState = interpreting;
		mInterpretationStartedTimestamp = mRobotModelManager.model().timeline().timestamp();

		mSensorVariablesUpdater.run();

		const Id &currentDiagramId = mInterpretersInterface.activeDiagram();

		qReal::interpretation::Thread * const initialThread = new qReal::interpretation::Thread(&mGraphicalModelApi
				, mInterpretersInterface, startingElementType, currentDiagramId, *mBlocksTable, "main");

		emit started();

		addThread(initialThread, "main");
	}
}

void Interpreter::threadStopped(qReal::interpretation::StopReason reason)
{
	qReal::interpretation::Thread * const thread = static_cast<qReal::interpretation::Thread *>(sender());

	mThreads.remove(thread->id());
	delete thread;

	if (mThreads.isEmpty()) {
		stopRobot(reason);
	}
}

void Interpreter::newThread(const Id &startBlockId, const QString &threadId)
{
	if (mThreads.contains(threadId)) {
		reportError(tr("Cannot create new thread with already occupied id %1").arg(threadId));
		stopRobot(qReal::interpretation::StopReason::error);
		return;
	}

	qReal::interpretation::Thread * const thread = new qReal::interpretation::Thread(&mGraphicalModelApi
			, mInterpretersInterface, startingElementType, *mBlocksTable, startBlockId, threadId);

	addThread(thread, threadId);
}

void Interpreter::addThread(qReal::interpretation::Thread * const thread, const QString &threadId)
{
	if (mThreads.count() >= maxThreadsCount) {
		reportError(tr("Threads limit exceeded. Maximum threads count is %1").arg(maxThreadsCount));
		stopRobot(qReal::interpretation::StopReason::error);
	}

	mThreads[threadId] = thread;
	connect(thread, &interpretation::Thread::stopped, this, &Interpreter::threadStopped);

	connect(thread, &qReal::interpretation::Thread::newThread, this, &Interpreter::newThread);
	connect(thread, &qReal::interpretation::Thread::killThread, this, &Interpreter::killThread);
	connect(thread, &qReal::interpretation::Thread::sendMessage, this, &Interpreter::sendMessage);

	QCoreApplication::processEvents();
	if (mState != idle) {
		thread->interpret();
	}
}

void Interpreter::killThread(const QString &threadId)
{
	if (mThreads.contains(threadId)) {
		mThreads[threadId]->stop();
	} else {
		reportError(tr("Killing non-existent thread %1").arg(threadId));
	}
}

void Interpreter::sendMessage(const QString &threadId, const QString &message)
{
	if (mThreads.contains(threadId)) {
		mThreads[threadId]->newMessage(message);
	}
}

void Interpreter::connectToRobot()
{
	if (mState == interpreting) {
		return;
	}

	if (mRobotModelManager.model().connectionState() == RobotModelInterface::connectedState) {
		mRobotModelManager.model().stopRobot();
		mRobotModelManager.model().disconnectFromRobot();
	} else {
		mRobotModelManager.model().connectToRobot();
	}

	mActionConnectToRobot.setChecked(
			mRobotModelManager.model().connectionState() == RobotModelInterface::connectedState);
}

void Interpreter::reportError(const QString &message)
{
	mInterpretersInterface.errorReporter()->addError(message);
}
<|endoftext|>


<commit_before>/*
 * This program 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
 * (at your option) any later version.
 *
 * Written (W) 1999-2009 Soeren Sonnenburg
 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include "lib/common.h"
#include "kernel/CustomKernel.h"
#include "features/Features.h"
#include "features/DummyFeatures.h"
#include "lib/io.h"

using namespace shogun;

void
CCustomKernel::init(void)
{
	m_parameters->add_matrix(&kmatrix.matrix, &kmatrix.num_rows, &kmatrix.num_cols, "kmatrix",
							 "Kernel matrix.");
	m_parameters->add(&upper_diagonal, "upper_diagonal");
}

CCustomKernel::CCustomKernel()
: CKernel(10), kmatrix(), upper_diagonal(false)
{
	init();
}

CCustomKernel::CCustomKernel(CKernel* k)
: CKernel(10)
{
	set_full_kernel_matrix_from_full(k->get_kernel_matrix());
}

CCustomKernel::CCustomKernel(SGMatrix<float64_t> km)
: CKernel(10), upper_diagonal(false)
{
	init();
	set_full_kernel_matrix_from_full(km);
}

CCustomKernel::~CCustomKernel()
{
	cleanup();
}

bool CCustomKernel::dummy_init(int32_t rows, int32_t cols)
{
	return init(new CDummyFeatures(rows), new CDummyFeatures(cols));
}

bool CCustomKernel::init(CFeatures* l, CFeatures* r)
{
	CKernel::init(l, r);

	SG_DEBUG( "num_vec_lhs: %d vs num_rows %d\n", l->get_num_vectors(), kmatrix.num_rows);
	SG_DEBUG( "num_vec_rhs: %d vs num_cols %d\n", r->get_num_vectors(), kmatrix.num_cols);
	ASSERT(l->get_num_vectors()==kmatrix.num_rows);
	ASSERT(r->get_num_vectors()==kmatrix.num_cols);
	return init_normalizer();
}

void CCustomKernel::cleanup_custom()
{
	SG_DEBUG("cleanup up custom kernel\n");
	delete[] kmatrix.matrix;
	kmatrix.matrix=NULL;
	upper_diagonal=false;
	kmatrix.num_cols=0;
	kmatrix.num_rows=0;
}

void CCustomKernel::cleanup()
{
	cleanup_custom();
	CKernel::cleanup();
}

<commit_msg>Fix for CustomKernel<commit_after>/*
 * This program 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
 * (at your option) any later version.
 *
 * Written (W) 1999-2009 Soeren Sonnenburg
 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include "lib/common.h"
#include "kernel/CustomKernel.h"
#include "features/Features.h"
#include "features/DummyFeatures.h"
#include "lib/io.h"

using namespace shogun;

void
CCustomKernel::init(void)
{
	m_parameters->add(&kmatrix, "kmatrix", "Kernel matrix.");
	m_parameters->add(&upper_diagonal, "upper_diagonal");
}

CCustomKernel::CCustomKernel()
: CKernel(10), kmatrix(), upper_diagonal(false)
{
	init();
}

CCustomKernel::CCustomKernel(CKernel* k)
: CKernel(10)
{
	set_full_kernel_matrix_from_full(k->get_kernel_matrix());
}

CCustomKernel::CCustomKernel(SGMatrix<float64_t> km)
: CKernel(10), upper_diagonal(false)
{
	init();
	set_full_kernel_matrix_from_full(km);
}

CCustomKernel::~CCustomKernel()
{
	cleanup();
}

bool CCustomKernel::dummy_init(int32_t rows, int32_t cols)
{
	return init(new CDummyFeatures(rows), new CDummyFeatures(cols));
}

bool CCustomKernel::init(CFeatures* l, CFeatures* r)
{
	CKernel::init(l, r);

	SG_DEBUG( "num_vec_lhs: %d vs num_rows %d\n", l->get_num_vectors(), kmatrix.num_rows);
	SG_DEBUG( "num_vec_rhs: %d vs num_cols %d\n", r->get_num_vectors(), kmatrix.num_cols);
	ASSERT(l->get_num_vectors()==kmatrix.num_rows);
	ASSERT(r->get_num_vectors()==kmatrix.num_cols);
	return init_normalizer();
}

void CCustomKernel::cleanup_custom()
{
	SG_DEBUG("cleanup up custom kernel\n");
	delete[] kmatrix.matrix;
	kmatrix.matrix=NULL;
	upper_diagonal=false;
	kmatrix.num_cols=0;
	kmatrix.num_rows=0;
}

void CCustomKernel::cleanup()
{
	cleanup_custom();
	CKernel::cleanup();
}

<|endoftext|>


<commit_before>/*
 * Copyright 2009-2020 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Standard includes
#include <fstream>

// Third party includes
#include <boost/format.hpp>
#include <boost/progress.hpp>

// VOTCA includes
#include <votca/tools/constants.h>
#include <votca/tools/property.h>

// Local VOTCA includes
#include "kmclifetime.h"
#include "votca/xtp/eigen.h"
#include "votca/xtp/gnode.h"
#include "votca/xtp/qmstate.h"
#include "votca/xtp/topology.h"

namespace votca {
namespace xtp {

void KMCLifetime::Initialize(const tools::Property& user_options) {

  tools::Property options =
      LoadDefaultsAndUpdateWithUserOptions("xtp", user_options);
  ParseCommonOptions(user_options);

  _insertions = options.get(".numberofinsertions").as<unsigned long>();
  _lifetimefile = options.get(".lifetimefile").as<std::string>();

  _probfile = options.ifExistsReturnElseReturnDefault<std::string>(
      ".decayprobfile", "");

  const tools::Property& carrier_options = options.get(".carrierenergy");
  _do_carrierenergy = carrier_options.get(".run").as<bool>();
  _energy_outputfile = carrier_options.get(".outputfile").as<std::string>();
  _alpha = carrier_options.get(".alpha").as<double>();
  _outputsteps = carrier_options.get(".outputsteps").as<unsigned long>();

  _log.setReportLevel(Log::current_level);
  _log.setCommonPreface("\n ...");

  _carriertype = QMStateType(QMStateType::Singlet);
  XTP_LOG(Log::error, _log)
      << "carrier type:" << _carriertype.ToLongString() << std::flush;
  _field = Eigen::Vector3d::Zero();
}

void KMCLifetime::WriteDecayProbability(std::string filename) {

  Eigen::VectorXd outrates = Eigen::VectorXd::Zero(_nodes.size());
  Eigen::VectorXd inrates = Eigen::VectorXd::Zero(_nodes.size());
  Eigen::VectorXd decayrates = Eigen::VectorXd::Ones(_nodes.size());

  for (unsigned i = 0; i < _nodes.size(); i++) {
    GNode& node = _nodes[i];
    if (node.canDecay()) {
      for (const GLink& event : node.Events()) {
        if (event.isDecayEvent()) {
          decayrates[i] = event.getRate();
        } else {
          inrates[event.getDestination()->getId()] += event.getRate();
          outrates[i] += event.getRate();
        }
      }
    }
  }
  outrates = decayrates.cwiseQuotient(outrates + decayrates);
  inrates = decayrates.cwiseQuotient(inrates + decayrates);

  std::fstream probs;
  if (!probs.open(filename, std::fstream::out)) {
    std::string error_msg = "Unable to write to file " + filename;
    throw std::exception(error_msg);
  }
  probs << "#SiteID, Relative Prob outgoing, Relative Prob ingoing\n";
  for (unsigned i = 0; i < _nodes.size(); i++) {
    probs << _nodes[i].getId() << " " << outrates[i] << " " << inrates[i]
          << std::endl;
  }
  probs.close();
  return;
}

void KMCLifetime::ReadLifetimeFile(std::string filename) {
  tools::Property xml;
  xml.LoadFromXML(filename);
  std::vector<tools::Property*> jobProps = xml.Select("lifetimes.site");
  if (jobProps.size() != _nodes.size()) {
    throw std::runtime_error(
        (boost::format("The number of sites in the topology: %i does not match "
                       "the number in the lifetimefile: %i") %
         _nodes.size() % jobProps.size())
            .str());
  }

  for (tools::Property* prop : jobProps) {
    Index site_id = prop->getAttribute<Index>("id");
    double lifetime = boost::lexical_cast<double>(prop->value());
    bool check = false;
    for (auto& node : _nodes) {
      if (node.getId() == site_id && !(node.canDecay())) {
        node.AddDecayEvent(1.0 / lifetime);
        check = true;
        break;
      } else if (node.getId() == site_id && node.canDecay()) {
        throw std::runtime_error(
            (boost::format("Node %i appears twice in your list") % site_id)
                .str());
      }
    }
    if (!check) {
      throw std::runtime_error(
          (boost::format("Site from file with id: %i not found in state file") %
           site_id)
              .str());
    }
  }
  for (auto& node : _nodes) {
    node.InitEscapeRate();
    node.MakeHuffTree();
  }
  return;
}

void KMCLifetime::WriteToTraj(std::fstream& traj, unsigned long insertioncount,
                              double simtime,
                              const Chargecarrier& affectedcarrier) const {
  const Eigen::Vector3d& dr_travelled = affectedcarrier.get_dRtravelled();
  traj << simtime << "\t" << insertioncount << "\t" << affectedcarrier.getId()
       << "\t" << affectedcarrier.getLifetime() << "\t"
       << affectedcarrier.getSteps() << "\t"
       << affectedcarrier.getCurrentNodeId() + 1 << "\t"
       << dr_travelled.x() * tools::conv::bohr2nm << "\t"
       << dr_travelled.y() * tools::conv::bohr2nm << "\t"
       << dr_travelled.z() * tools::conv::bohr2nm << std::endl;
}

void KMCLifetime::RunVSSM() {

  std::chrono::time_point<std::chrono::system_clock> realtime_start =
      std::chrono::system_clock::now();
  XTP_LOG(Log::error, _log)
      << "\nAlgorithm: VSSM for Multiple Charges with finite Lifetime\n"
         "number of charges: "
      << _numberofcarriers << "\nnumber of nodes: " << _nodes.size()
      << std::flush;

  if (_numberofcarriers > Index(_nodes.size())) {
    throw std::runtime_error(
        "ERROR in kmclifetime: specified number of charges is greater than the "
        "number of nodes. This conflicts with single occupation.");
  }

  std::fstream traj;
  std::fstream energyfile;

  XTP_LOG(Log::error, _log)
      << "Writing trajectory to " << _trajectoryfile << "." << std::flush;

  if (!traj.open(_trajectoryfile, std::fstream::out)) {
    std::string error_msg = "Unable to write to file " + _trajectoryfile;
    throw std::exception(error_msg);
  }

  traj << "#Simtime [s]\t Insertion\t Carrier ID\t Lifetime[s]\tSteps\t Last "
          "Segment\t x_travelled[nm]\t y_travelled[nm]\t z_travelled[nm]\n";

  if (_do_carrierenergy) {

    XTP_LOG(Log::error, _log)
        << "Tracking the energy of one charge carrier and exponential average "
           "with alpha="
        << _alpha << " to " << _energy_outputfile << std::flush;

    if (!energyfile.open(_energy_outputfile, std::fstream::out)) {
      std::string error_msg = "Unable to write to file " + _energy_outputfile;
      throw std::exception(error_msg);
    }

    energyfile << "Simtime [s]\tSteps\tCarrier ID\tEnergy_a=" << _alpha
               << "[eV]\n";
  }

  // Injection
  XTP_LOG(Log::error, _log)
      << "\ninjection method: " << _injectionmethod << std::flush;

  RandomlyCreateCharges();

  unsigned long insertioncount = 0;
  unsigned long step = 0;
  double simtime = 0.0;

  std::vector<GNode*> forbiddennodes;
  std::vector<GNode*> forbiddendests;

  time_t now = time(nullptr);
  tm* localtm = localtime(&now);
  XTP_LOG(Log::error, _log)
      << "Run started at " << asctime(localtm) << std::flush;

  double avlifetime = 0.0;
  double meanfreepath = 0.0;
  Eigen::Vector3d difflength_squared = Eigen::Vector3d::Zero();

  double avgenergy = _carriers[0].getCurrentEnergy();
  Index carrieridold = _carriers[0].getId();

  while (insertioncount < _insertions) {
    std::chrono::duration<double> elapsed_time =
        std::chrono::system_clock::now() - realtime_start;
    if (elapsed_time.count() > (_maxrealtime * 60. * 60.)) {
      XTP_LOG(Log::error, _log)
          << "\nReal time limit of " << _maxrealtime << " hours ("
          << Index(_maxrealtime * 60 * 60 + 0.5)
          << " seconds) has been reached. Stopping here.\n"
          << std::flush;
      break;
    }

    double cumulated_rate = 0;

    for (const auto& carrier : _carriers) {
      cumulated_rate += carrier.getCurrentEscapeRate();
    }
    if (cumulated_rate == 0) {  // this should not happen: no possible jumps
                                // defined for a node
      throw std::runtime_error(
          "ERROR in kmclifetime: Incorrect rates in the database file. All the "
          "escape rates for the current setting are 0.");
    }
    // go forward in time
    double dt = Promotetime(cumulated_rate);

    if (_do_carrierenergy) {
      bool print = false;
      if (_carriers[0].getId() > carrieridold) {
        avgenergy = _carriers[0].getCurrentEnergy();
        print = true;
        carrieridold = _carriers[0].getId();
      } else if (step % _outputsteps == 0) {
        avgenergy =
            _alpha * _carriers[0].getCurrentEnergy() + (1 - _alpha) * avgenergy;
        print = true;
      }
      if (print) {
        energyfile << simtime << "\t" << step << "\t" << _carriers[0].getId()
                   << "\t" << avgenergy * tools::conv::hrt2ev << std::endl;
      }
    }

    simtime += dt;
    step++;
    for (auto& carrier : _carriers) {
      carrier.updateLifetime(dt);
      carrier.updateSteps(1);
      carrier.updateOccupationtime(dt);
    }

    ResetForbiddenlist(forbiddennodes);
    bool secondlevel = true;
    while (secondlevel) {

      // determine which carrier will escape
      GNode* newnode = nullptr;
      Chargecarrier* affectedcarrier = ChooseAffectedCarrier(cumulated_rate);

      if (CheckForbidden(affectedcarrier->getCurrentNode(), forbiddennodes)) {
        continue;
      }

      // determine where it will jump to
      ResetForbiddenlist(forbiddendests);
      boost::progress_display progress(_insertions);

      while (true) {
        // LEVEL 2

        newnode = nullptr;
        const GLink& event =
            ChooseHoppingDest(affectedcarrier->getCurrentNode());

        if (event.isDecayEvent()) {
          const Eigen::Vector3d& dr_travelled =
              affectedcarrier->get_dRtravelled();
          avlifetime += affectedcarrier->getLifetime();
          meanfreepath += dr_travelled.norm();
          difflength_squared += dr_travelled.cwiseAbs2();
          WriteToTraj(traj, insertioncount, simtime, *affectedcarrier);
          ++progress;
          RandomlyAssignCarriertoSite(*affectedcarrier);
          affectedcarrier->resetCarrier();
          insertioncount++;
          affectedcarrier->setId(_numberofcarriers - 1 + insertioncount);
          secondlevel = false;
          break;
        } else {
          newnode = event.getDestination();
        }

        // check after the event if this was allowed
        if (CheckForbidden(*newnode, forbiddendests)) {
          continue;
        }

        // if the new segment is unoccupied: jump; if not: add to forbidden list
        // and choose new hopping destination
        if (newnode->isOccupied()) {
          if (CheckSurrounded(affectedcarrier->getCurrentNode(),
                              forbiddendests)) {
            AddtoForbiddenlist(affectedcarrier->getCurrentNode(),
                               forbiddennodes);
            break;  // select new escape node (ends level 2 but without setting
                    // level1step to 1)
          }
          AddtoForbiddenlist(*newnode, forbiddendests);
          continue;  // select new destination
        } else {
          affectedcarrier->jumpAccordingEvent(event);
          secondlevel = false;

          break;  // this ends LEVEL 2 , so that the time is updated and the
                  // next MC step started
        }

        // END LEVEL 2
      }
      // END LEVEL 1
    }
  }

  XTP_LOG(Log::error, _log)
      << "\nTotal runtime:\t\t\t\t\t" << simtime
      << " s\n"
         "Total KMC steps:\t\t\t\t"
      << step << "\nAverage lifetime:\t\t\t\t"
      << avlifetime / double(insertioncount) << " s\n"
      << "Mean freepath\t l=<|r_x-r_o|> :\t\t"
      << (meanfreepath * tools::conv::bohr2nm / double(insertioncount))
      << " nm\n"
      << "Average diffusionlength\t d=sqrt(<(r_x-r_o)^2>)\t"
      << std::sqrt(difflength_squared.norm() / double(insertioncount)) *
             tools::conv::bohr2nm
      << " nm\n"
      << std::flush;

  WriteOccupationtoFile(simtime, _occfile);
  traj.close();
  if (_do_carrierenergy) {
    energyfile.close();
  }
  return;
}

bool KMCLifetime::EvaluateFrame(Topology& top) {
  XTP_LOG(Log::error, _log) << "\n-----------------------------------"
                               "\n      KMCLIFETIME started"
                               "\n-----------------------------------\n"
                            << std::flush;

  XTP_LOG(Log::info, _log) << "\nInitialising random number generator"
                           << std::flush;

  _RandomVariable.init(_seed);
  LoadGraph(top);
  ReadLifetimeFile(_lifetimefile);

  if (!_probfile.empty()) {
    WriteDecayProbability(_probfile);
  }
  RunVSSM();

  time_t now = time(nullptr);
  tm* localtm = localtime(&now);
  XTP_LOG(Log::error, _log)
      << " KMCLIFETIME finished at:" << asctime(localtm) << std::flush;

  return true;
}

}  // namespace xtp
}  // namespace votca
<commit_msg>Fixed syntax<commit_after>/*
 * Copyright 2009-2020 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Standard includes
#include <fstream>

// Third party includes
#include <boost/format.hpp>
#include <boost/progress.hpp>

// VOTCA includes
#include <votca/tools/constants.h>
#include <votca/tools/property.h>

// Local VOTCA includes
#include "kmclifetime.h"
#include "votca/xtp/eigen.h"
#include "votca/xtp/gnode.h"
#include "votca/xtp/qmstate.h"
#include "votca/xtp/topology.h"

namespace votca {
namespace xtp {

void KMCLifetime::Initialize(const tools::Property& user_options) {

  tools::Property options =
      LoadDefaultsAndUpdateWithUserOptions("xtp", user_options);
  ParseCommonOptions(user_options);

  _insertions = options.get(".numberofinsertions").as<unsigned long>();
  _lifetimefile = options.get(".lifetimefile").as<std::string>();

  _probfile = options.ifExistsReturnElseReturnDefault<std::string>(
      ".decayprobfile", "");

  const tools::Property& carrier_options = options.get(".carrierenergy");
  _do_carrierenergy = carrier_options.get(".run").as<bool>();
  _energy_outputfile = carrier_options.get(".outputfile").as<std::string>();
  _alpha = carrier_options.get(".alpha").as<double>();
  _outputsteps = carrier_options.get(".outputsteps").as<unsigned long>();

  _log.setReportLevel(Log::current_level);
  _log.setCommonPreface("\n ...");

  _carriertype = QMStateType(QMStateType::Singlet);
  XTP_LOG(Log::error, _log)
      << "carrier type:" << _carriertype.ToLongString() << std::flush;
  _field = Eigen::Vector3d::Zero();
}

void KMCLifetime::WriteDecayProbability(std::string filename) {

  Eigen::VectorXd outrates = Eigen::VectorXd::Zero(_nodes.size());
  Eigen::VectorXd inrates = Eigen::VectorXd::Zero(_nodes.size());
  Eigen::VectorXd decayrates = Eigen::VectorXd::Ones(_nodes.size());

  for (unsigned i = 0; i < _nodes.size(); i++) {
    GNode& node = _nodes[i];
    if (node.canDecay()) {
      for (const GLink& event : node.Events()) {
        if (event.isDecayEvent()) {
          decayrates[i] = event.getRate();
        } else {
          inrates[event.getDestination()->getId()] += event.getRate();
          outrates[i] += event.getRate();
        }
      }
    }
  }
  outrates = decayrates.cwiseQuotient(outrates + decayrates);
  inrates = decayrates.cwiseQuotient(inrates + decayrates);

  std::fstream probs;
  probs.open(filename, std::fstream::out);
  if (!probs.is_open()) {
    std::string error_msg = "Unable to write to file " + filename;
    throw std::exception(error_msg);
  }
  probs << "#SiteID, Relative Prob outgoing, Relative Prob ingoing\n";
  for (unsigned i = 0; i < _nodes.size(); i++) {
    probs << _nodes[i].getId() << " " << outrates[i] << " " << inrates[i]
          << std::endl;
  }
  probs.close();
  return;
}

void KMCLifetime::ReadLifetimeFile(std::string filename) {
  tools::Property xml;
  xml.LoadFromXML(filename);
  std::vector<tools::Property*> jobProps = xml.Select("lifetimes.site");
  if (jobProps.size() != _nodes.size()) {
    throw std::runtime_error(
        (boost::format("The number of sites in the topology: %i does not match "
                       "the number in the lifetimefile: %i") %
         _nodes.size() % jobProps.size())
            .str());
  }

  for (tools::Property* prop : jobProps) {
    Index site_id = prop->getAttribute<Index>("id");
    double lifetime = boost::lexical_cast<double>(prop->value());
    bool check = false;
    for (auto& node : _nodes) {
      if (node.getId() == site_id && !(node.canDecay())) {
        node.AddDecayEvent(1.0 / lifetime);
        check = true;
        break;
      } else if (node.getId() == site_id && node.canDecay()) {
        throw std::runtime_error(
            (boost::format("Node %i appears twice in your list") % site_id)
                .str());
      }
    }
    if (!check) {
      throw std::runtime_error(
          (boost::format("Site from file with id: %i not found in state file") %
           site_id)
              .str());
    }
  }
  for (auto& node : _nodes) {
    node.InitEscapeRate();
    node.MakeHuffTree();
  }
  return;
}

void KMCLifetime::WriteToTraj(std::fstream& traj, unsigned long insertioncount,
                              double simtime,
                              const Chargecarrier& affectedcarrier) const {
  const Eigen::Vector3d& dr_travelled = affectedcarrier.get_dRtravelled();
  traj << simtime << "\t" << insertioncount << "\t" << affectedcarrier.getId()
       << "\t" << affectedcarrier.getLifetime() << "\t"
       << affectedcarrier.getSteps() << "\t"
       << affectedcarrier.getCurrentNodeId() + 1 << "\t"
       << dr_travelled.x() * tools::conv::bohr2nm << "\t"
       << dr_travelled.y() * tools::conv::bohr2nm << "\t"
       << dr_travelled.z() * tools::conv::bohr2nm << std::endl;
}

void KMCLifetime::RunVSSM() {

  std::chrono::time_point<std::chrono::system_clock> realtime_start =
      std::chrono::system_clock::now();
  XTP_LOG(Log::error, _log)
      << "\nAlgorithm: VSSM for Multiple Charges with finite Lifetime\n"
         "number of charges: "
      << _numberofcarriers << "\nnumber of nodes: " << _nodes.size()
      << std::flush;

  if (_numberofcarriers > Index(_nodes.size())) {
    throw std::runtime_error(
        "ERROR in kmclifetime: specified number of charges is greater than the "
        "number of nodes. This conflicts with single occupation.");
  }

  std::fstream traj;
  std::fstream energyfile;

  XTP_LOG(Log::error, _log)
      << "Writing trajectory to " << _trajectoryfile << "." << std::flush;

  traj.open(_trajectoryfile, std::fstream::out);
  if (!traj.is_open()) {
    std::string error_msg = "Unable to write to file " + _trajectoryfile;
    throw std::exception(error_msg);
  }

  traj << "#Simtime [s]\t Insertion\t Carrier ID\t Lifetime[s]\tSteps\t Last "
          "Segment\t x_travelled[nm]\t y_travelled[nm]\t z_travelled[nm]\n";

  if (_do_carrierenergy) {

    XTP_LOG(Log::error, _log)
        << "Tracking the energy of one charge carrier and exponential average "
           "with alpha="
        << _alpha << " to " << _energy_outputfile << std::flush;
    energyfile.open(_energy_outputfile, std::fstream::out);
    if (!energyfile.is_open()) {
      std::string error_msg = "Unable to write to file " + _energy_outputfile;
      throw std::exception(error_msg);
    }

    energyfile << "Simtime [s]\tSteps\tCarrier ID\tEnergy_a=" << _alpha
               << "[eV]\n";
  }

  // Injection
  XTP_LOG(Log::error, _log)
      << "\ninjection method: " << _injectionmethod << std::flush;

  RandomlyCreateCharges();

  unsigned long insertioncount = 0;
  unsigned long step = 0;
  double simtime = 0.0;

  std::vector<GNode*> forbiddennodes;
  std::vector<GNode*> forbiddendests;

  time_t now = time(nullptr);
  tm* localtm = localtime(&now);
  XTP_LOG(Log::error, _log)
      << "Run started at " << asctime(localtm) << std::flush;

  double avlifetime = 0.0;
  double meanfreepath = 0.0;
  Eigen::Vector3d difflength_squared = Eigen::Vector3d::Zero();

  double avgenergy = _carriers[0].getCurrentEnergy();
  Index carrieridold = _carriers[0].getId();

  while (insertioncount < _insertions) {
    std::chrono::duration<double> elapsed_time =
        std::chrono::system_clock::now() - realtime_start;
    if (elapsed_time.count() > (_maxrealtime * 60. * 60.)) {
      XTP_LOG(Log::error, _log)
          << "\nReal time limit of " << _maxrealtime << " hours ("
          << Index(_maxrealtime * 60 * 60 + 0.5)
          << " seconds) has been reached. Stopping here.\n"
          << std::flush;
      break;
    }

    double cumulated_rate = 0;

    for (const auto& carrier : _carriers) {
      cumulated_rate += carrier.getCurrentEscapeRate();
    }
    if (cumulated_rate == 0) {  // this should not happen: no possible jumps
                                // defined for a node
      throw std::runtime_error(
          "ERROR in kmclifetime: Incorrect rates in the database file. All the "
          "escape rates for the current setting are 0.");
    }
    // go forward in time
    double dt = Promotetime(cumulated_rate);

    if (_do_carrierenergy) {
      bool print = false;
      if (_carriers[0].getId() > carrieridold) {
        avgenergy = _carriers[0].getCurrentEnergy();
        print = true;
        carrieridold = _carriers[0].getId();
      } else if (step % _outputsteps == 0) {
        avgenergy =
            _alpha * _carriers[0].getCurrentEnergy() + (1 - _alpha) * avgenergy;
        print = true;
      }
      if (print) {
        energyfile << simtime << "\t" << step << "\t" << _carriers[0].getId()
                   << "\t" << avgenergy * tools::conv::hrt2ev << std::endl;
      }
    }

    simtime += dt;
    step++;
    for (auto& carrier : _carriers) {
      carrier.updateLifetime(dt);
      carrier.updateSteps(1);
      carrier.updateOccupationtime(dt);
    }

    ResetForbiddenlist(forbiddennodes);
    bool secondlevel = true;
    while (secondlevel) {

      // determine which carrier will escape
      GNode* newnode = nullptr;
      Chargecarrier* affectedcarrier = ChooseAffectedCarrier(cumulated_rate);

      if (CheckForbidden(affectedcarrier->getCurrentNode(), forbiddennodes)) {
        continue;
      }

      // determine where it will jump to
      ResetForbiddenlist(forbiddendests);
      boost::progress_display progress(_insertions);

      while (true) {
        // LEVEL 2

        newnode = nullptr;
        const GLink& event =
            ChooseHoppingDest(affectedcarrier->getCurrentNode());

        if (event.isDecayEvent()) {
          const Eigen::Vector3d& dr_travelled =
              affectedcarrier->get_dRtravelled();
          avlifetime += affectedcarrier->getLifetime();
          meanfreepath += dr_travelled.norm();
          difflength_squared += dr_travelled.cwiseAbs2();
          WriteToTraj(traj, insertioncount, simtime, *affectedcarrier);
          ++progress;
          RandomlyAssignCarriertoSite(*affectedcarrier);
          affectedcarrier->resetCarrier();
          insertioncount++;
          affectedcarrier->setId(_numberofcarriers - 1 + insertioncount);
          secondlevel = false;
          break;
        } else {
          newnode = event.getDestination();
        }

        // check after the event if this was allowed
        if (CheckForbidden(*newnode, forbiddendests)) {
          continue;
        }

        // if the new segment is unoccupied: jump; if not: add to forbidden list
        // and choose new hopping destination
        if (newnode->isOccupied()) {
          if (CheckSurrounded(affectedcarrier->getCurrentNode(),
                              forbiddendests)) {
            AddtoForbiddenlist(affectedcarrier->getCurrentNode(),
                               forbiddennodes);
            break;  // select new escape node (ends level 2 but without setting
                    // level1step to 1)
          }
          AddtoForbiddenlist(*newnode, forbiddendests);
          continue;  // select new destination
        } else {
          affectedcarrier->jumpAccordingEvent(event);
          secondlevel = false;

          break;  // this ends LEVEL 2 , so that the time is updated and the
                  // next MC step started
        }

        // END LEVEL 2
      }
      // END LEVEL 1
    }
  }

  XTP_LOG(Log::error, _log)
      << "\nTotal runtime:\t\t\t\t\t" << simtime
      << " s\n"
         "Total KMC steps:\t\t\t\t"
      << step << "\nAverage lifetime:\t\t\t\t"
      << avlifetime / double(insertioncount) << " s\n"
      << "Mean freepath\t l=<|r_x-r_o|> :\t\t"
      << (meanfreepath * tools::conv::bohr2nm / double(insertioncount))
      << " nm\n"
      << "Average diffusionlength\t d=sqrt(<(r_x-r_o)^2>)\t"
      << std::sqrt(difflength_squared.norm() / double(insertioncount)) *
             tools::conv::bohr2nm
      << " nm\n"
      << std::flush;

  WriteOccupationtoFile(simtime, _occfile);
  traj.close();
  if (_do_carrierenergy) {
    energyfile.close();
  }
  return;
}

bool KMCLifetime::EvaluateFrame(Topology& top) {
  XTP_LOG(Log::error, _log) << "\n-----------------------------------"
                               "\n      KMCLIFETIME started"
                               "\n-----------------------------------\n"
                            << std::flush;

  XTP_LOG(Log::info, _log) << "\nInitialising random number generator"
                           << std::flush;

  _RandomVariable.init(_seed);
  LoadGraph(top);
  ReadLifetimeFile(_lifetimefile);

  if (!_probfile.empty()) {
    WriteDecayProbability(_probfile);
  }
  RunVSSM();

  time_t now = time(nullptr);
  tm* localtm = localtime(&now);
  XTP_LOG(Log::error, _log)
      << " KMCLIFETIME finished at:" << asctime(localtm) << std::flush;

  return true;
}

}  // namespace xtp
}  // namespace votca
<|endoftext|>


<commit_before>#include <Arduino.h>
#include <SoftwareSerial.h>
#include "Adafruit_BNO055.h"
#include "Adafruit_DRV2605.h"

extern "C" {
	//#include "pfleury/uart.h"
};

FUSES =
{
	.low = 0xFF,	//0xFF
	.high = FUSE_SPIEN & FUSE_BOOTSZ0 & FUSE_BOOTRST,	//0xDC
	.extended = FUSE_BODLEVEL1	//0xFD
};
LOCKBITS = LB_MODE_3;	//0xFC

#define UART_BAUD_RATE	115200
#define FILTER_LOG2		4		// power of two

Adafruit_BNO055 bno = Adafruit_BNO055(55);
Adafruit_DRV2605 drv = Adafruit_DRV2605();

SoftwareSerial SoftSerial(2, 3);
unsigned char buffer[64];
#define ID_LENGTH 12
unsigned char last[ID_LENGTH];
uint8_t listcnt = 0;
uint8_t ledcnt = 0;
#define VIB_CNT 15
#define VIB_BIB 1
#define VIB_NR 14
uint8_t vibcnt = 0;

uint8_t vibr[] = {14,15,16,47,48,54,64,70,73};

void process_rfid(uint8_t c)
{
	static int count = 0;
	if (c == 0x02)
	{
		count = 0;
	}
	else if (c == 0x03)
	{
		ledcnt = 0;
		if (memcmp(buffer, last, sizeof(last)) != 0)
		{
			memcpy(last, buffer, sizeof(last));
			drv.setWaveform(VIB_BIB, VIB_NR);
			drv.go();
			vibcnt = VIB_CNT;
		}
	}
	else if(count < 64)
	{
		buffer[count++] = c;
	}
}

inline void set_led(void)
{
	if (ledcnt < 10)
	{
		if (ledcnt == 0)
		{
			digitalWrite(LED_BUILTIN, HIGH);
		}
		ledcnt++;
	}
	else
	{
		digitalWrite(LED_BUILTIN, LOW);
	}
}

inline void set_vib(uint8_t vibnr)
{
	if (vibnr < sizeof(vibr))
	{
		drv.setWaveform(VIB_BIB, vibr[vibnr]);
		drv.go();
	}
}

inline void set_vib_2nd(void)
{
	if (vibcnt != 0)
	{
		vibcnt--;
		if (vibcnt == 0)
		{
			drv.setWaveform(VIB_BIB, VIB_NR);
			drv.go();
		}
	}
}

inline void print_bno(void)
{
	sensors_event_t event;
	bno.getEvent(&event);
	imu::Vector<3> vec = bno.getVector(Adafruit_BNO055::VECTOR_LINEARACCEL);

	Serial.print("{\"rfid\":\"");
	Serial.write(buffer,ID_LENGTH);
	Serial.print("\",\"imu\":{\"e\":{\"x\":");
	Serial.print(event.orientation.x, 4);
	Serial.print(",\"y\":");
	Serial.print(event.orientation.y, 4);
	Serial.print(",\"z\":");
	Serial.print(event.orientation.z, 4);
	Serial.print("},\"a\":{\"x\":");
	Serial.print(vec.x(), 4);
	Serial.print(",\"y\":");
	Serial.print(vec.y(), 4);
	Serial.print(",\"z\":");
	Serial.print(vec.z(), 4);
	Serial.print("}}}\n");
}

void setup()
{
	pinMode(LED_BUILTIN, OUTPUT);
	Serial.begin(115200);
	SoftSerial.begin(9600);
	if(!bno.begin())
	{
		//uart_puts("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
		while(1);
	}
	delay(1000);
	bno.setExtCrystalUse(true);

	drv.begin();
	drv.useERM();
	drv.selectLibrary(2);
	drv.setWaveform(VIB_BIB, VIB_NR);

	sei();
}

void loop()
{
	print_bno();

	set_led();

	delay(20);

	while(SoftSerial.available())
	{
		process_rfid(SoftSerial.read());
	}
	if (Serial.available())
	{
		set_vib(Serial.read());
	}
	set_vib_2nd();
}
<commit_msg>Add digital inputs<commit_after>#include <Arduino.h>
#include <SoftwareSerial.h>
#include "Adafruit_BNO055.h"
#include "Adafruit_DRV2605.h"

extern "C" {
	//#include "pfleury/uart.h"
};

FUSES =
{
	.low = 0xFF,	//0xFF
	.high = FUSE_SPIEN & FUSE_BOOTSZ0 & FUSE_BOOTRST,	//0xDC
	.extended = FUSE_BODLEVEL1	//0xFD
};
LOCKBITS = LB_MODE_3;	//0xFC

#define UART_BAUD_RATE	115200
#define FILTER_LOG2		4		// power of two

Adafruit_BNO055 bno = Adafruit_BNO055(55);
Adafruit_DRV2605 drv = Adafruit_DRV2605();

SoftwareSerial SoftSerial(2, 3);
unsigned char buffer[64];
#define ID_LENGTH 12
unsigned char last[ID_LENGTH];
uint8_t listcnt = 0;
uint8_t ledcnt = 0;
#define VIB_CNT 15
#define VIB_BIB 1
#define VIB_NR 14
uint8_t vibcnt = 0;
uint8_t vibr[] = {14,15,16,47,48,54,64,70,73};
#define KEY	6
#define SWITCH	7
#define CAPSENS	8

void process_rfid(uint8_t c)
{
	static int count = 0;
	if (c == 0x02)
	{
		count = 0;
	}
	else if (c == 0x03)
	{
		ledcnt = 0;
		if (memcmp(buffer, last, sizeof(last)) != 0)
		{
			memcpy(last, buffer, sizeof(last));
			drv.setWaveform(VIB_BIB, VIB_NR);
			drv.go();
			vibcnt = VIB_CNT;
		}
	}
	else if(count < 64)
	{
		buffer[count++] = c;
	}
}

inline void set_led(void)
{
	if (ledcnt < 10)
	{
		if (ledcnt == 0)
		{
			digitalWrite(LED_BUILTIN, HIGH);
		}
		ledcnt++;
	}
	else
	{
		digitalWrite(LED_BUILTIN, LOW);
	}
}

inline void set_vib(uint8_t vibnr)
{
	if (vibnr < sizeof(vibr))
	{
		drv.setWaveform(VIB_BIB, vibr[vibnr]);
		drv.go();
	}
}

inline void set_vib_2nd(void)
{
	if (vibcnt != 0)
	{
		vibcnt--;
		if (vibcnt == 0)
		{
			drv.setWaveform(VIB_BIB, VIB_NR);
			drv.go();
		}
	}
}

inline void print_bno(void)
{
	sensors_event_t event;
	bno.getEvent(&event);
	imu::Vector<3> vec = bno.getVector(Adafruit_BNO055::VECTOR_LINEARACCEL);

	Serial.print("{\"rfid\":\"");
	Serial.write(buffer,ID_LENGTH);
	Serial.print("\",\"imu\":{\"e\":{\"x\":");
	Serial.print(event.orientation.x, 4);
	Serial.print(",\"y\":");
	Serial.print(event.orientation.y, 4);
	Serial.print(",\"z\":");
	Serial.print(event.orientation.z, 4);
	Serial.print("},\"a\":{\"x\":");
	Serial.print(vec.x(), 4);
	Serial.print(",\"y\":");
	Serial.print(vec.y(), 4);
	Serial.print(",\"z\":");
	Serial.print(vec.z(), 4);
	Serial.print("}}");
}

inline void print_dig(void)
{
	Serial.print(",\"key\" :");
	Serial.print(digitalRead(KEY) ? '1' : '0');
	Serial.print(",\"switch\" :");
	Serial.print(digitalRead(SWITCH) ? '1' : '0');
	Serial.print(",\"capsens\" :");
	Serial.print(digitalRead(CAPSENS) ? '1' : '0');
	Serial.print("}\n");
}

void setup()
{
	pinMode(LED_BUILTIN, OUTPUT);
	pinMode(KEY, INPUT_PULLUP);
	pinMode(SWITCH, INPUT_PULLUP);
	pinMode(CAPSENS, INPUT_PULLUP);
	Serial.begin(115200);
	SoftSerial.begin(9600);
	if(!bno.begin())
	{
		//uart_puts("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
		while(1);
	}
	delay(1000);
	bno.setExtCrystalUse(true);

	drv.begin();
	drv.useERM();
	drv.selectLibrary(2);
	drv.setWaveform(VIB_BIB, VIB_NR);

	sei();
}

void loop()
{
	print_bno();
	print_dig();

	set_led();

	delay(20);

	while(SoftSerial.available())
	{
		process_rfid(SoftSerial.read());
	}
	if (Serial.available())
	{
		set_vib(Serial.read());
	}
	set_vib_2nd();
}
<|endoftext|>


<commit_before>//
//  Video.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 12/10/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "Video.hpp"

using namespace Oric;

VideoOutput::VideoOutput(uint8_t *memory) :
	_ram(memory),
	_frame_counter(0), _counter(0),
	_state(Sync), _cycles_in_state(0),
	_is_graphics_mode(false),
	_character_set_base_address(0xb400),
	_phase(0)
{
	_crt.reset(new Outputs::CRT::CRT(64*6, 6, Outputs::CRT::DisplayType::PAL50, 1));

	// TODO: this is a copy and paste from the Electron; factor out.
	_crt->set_rgb_sampling_function(
		"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
		"{"
			"uint texValue = texture(sampler, coordinate).r;"
			"texValue >>= 4 - (int(icoordinate.x * 8) & 4);"
			"return vec3( uvec3(texValue) & uvec3(4u, 2u, 1u));"
		"}");

	_crt->set_output_device(Outputs::CRT::Television);
	_crt->set_visible_area(_crt->get_rect_for_area(50, 224, 16 * 6, 40 * 6, 4.0f / 3.0f));
}

std::shared_ptr<Outputs::CRT::CRT> VideoOutput::get_crt()
{
	return _crt;
}

void VideoOutput::run_for_cycles(int number_of_cycles)
{
	// Vertical: 0–39: pixels; otherwise blank; 48–53 sync
	// Horizontal: 0–223: pixels; otherwise blank; 256–259 sync

	while(number_of_cycles--)
	{
		_counter = (_counter + 1)%(312 * 64);	// TODO: NTSC
		int h_counter =_counter & 63;

		if(!h_counter)
		{
			_ink = 0xff;
			_paper = 0x00;
			_use_alternative_character_set = _use_double_height_characters = _blink_text = false;
			set_character_set_base_address();
			_phase += 64;

			if(!_counter)
			{
				_phase += 64;
				_frame_counter++;
			}
		}

		State new_state = Blank;
		if(
			(h_counter >= 48 && h_counter <= 53) ||
			(_counter >= 256*64 && _counter <= 259*64)) new_state = Sync;
		else if(h_counter >= 54 && h_counter <= 56) new_state = ColourBurst;
		else if(_counter < 224*64 && h_counter < 40) new_state = Pixels;

		if(_state != new_state)
		{
			switch(_state)
			{
				case ColourBurst:	_crt->output_colour_burst(_cycles_in_state * 6, _phase, 128);	break;
				case Sync:			_crt->output_sync(_cycles_in_state * 6);						break;
				case Blank:			_crt->output_blank(_cycles_in_state * 6);						break;
				case Pixels:		_crt->output_data(_cycles_in_state * 6, 2);						break;
			}
			_state = new_state;
			_cycles_in_state = 0;
			if(_state == Pixels) _pixel_target = _crt->allocate_write_area(120);
		}
		_cycles_in_state++;

		if(new_state == Pixels) {
			uint8_t pixels, control_byte;

			if(_is_graphics_mode && _counter < 200*64)
			{
				control_byte = pixels = _ram[0xa000 + (_counter >> 6) * 40 + h_counter];
			}
			else
			{
				int address = 0xbb80 + (_counter >> 9) * 40 + h_counter;
				control_byte = _ram[address];
				int line = _use_double_height_characters ? ((_counter >> 7) & 7) : ((_counter >> 6) & 7);
				pixels = _ram[_character_set_base_address + (control_byte&127) * 8 + line];
			}

			uint8_t inverse_mask = (control_byte & 0x80) ? 0x77 : 0x00;
			if(_blink_text) inverse_mask ^= (_frame_counter&32) ? 0x77 : 0x00;

			if((control_byte & 0x7f) >= 32)
			{
				uint8_t colours[2] = {
					(uint8_t)(_paper ^ inverse_mask),
					(uint8_t)(_ink ^ inverse_mask),
				};

				_pixel_target[0] = (colours[(pixels >> 4)&1] & 0x0f) | (colours[(pixels >> 5)&1] & 0xf0);
				_pixel_target[1] = (colours[(pixels >> 2)&1] & 0x0f) | (colours[(pixels >> 3)&1] & 0xf0);
				_pixel_target[2] = (colours[(pixels >> 0)&1] & 0x0f) | (colours[(pixels >> 1)&1] & 0xf0);
			}
			else
			{
				switch(control_byte & 0x7f)
				{
					case 0x00:		_ink = 0x00;	break;
					case 0x01:		_ink = 0x44;	break;
					case 0x02:		_ink = 0x22;	break;
					case 0x03:		_ink = 0x66;	break;
					case 0x04:		_ink = 0x11;	break;
					case 0x05:		_ink = 0x55;	break;
					case 0x06:		_ink = 0x33;	break;
					case 0x07:		_ink = 0x77;	break;

					case 0x08:	case 0x09:	case 0x0a: case 0x0b:
					case 0x0c:	case 0x0d:	case 0x0e: case 0x0f:
						_use_alternative_character_set = (control_byte&1);
						_use_double_height_characters = (control_byte&2);
						_blink_text = (control_byte&4);
						set_character_set_base_address();
					break;

					case 0x10:		_paper = 0x00;	break;
					case 0x11:		_paper = 0x44;	break;
					case 0x12:		_paper = 0x22;	break;
					case 0x13:		_paper = 0x66;	break;
					case 0x14:		_paper = 0x11;	break;
					case 0x15:		_paper = 0x55;	break;
					case 0x16:		_paper = 0x33;	break;
					case 0x17:		_paper = 0x77;	break;

					case 0x18: case 0x19: case 0x1a: case 0x1b:
					case 0x1c: case 0x1d: case 0x1e: case 0x1f:
						_is_graphics_mode = (control_byte & 4);
						_is_sixty_hertz = !(control_byte & 2);
					break;

					default: break;
				}
				_pixel_target[0] = _pixel_target[1] = _pixel_target[2] = (uint8_t)(_paper ^ inverse_mask);
			}
			_pixel_target += 3;
		}
	}
}
<commit_msg>Altered phase so that it now merely accounts for accumulated error across a frame. Can probably do better.<commit_after>//
//  Video.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 12/10/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#include "Video.hpp"

using namespace Oric;

VideoOutput::VideoOutput(uint8_t *memory) :
	_ram(memory),
	_frame_counter(0), _counter(0),
	_state(Sync), _cycles_in_state(0),
	_is_graphics_mode(false),
	_character_set_base_address(0xb400),
	_phase(0)
{
	_crt.reset(new Outputs::CRT::CRT(64*6, 6, Outputs::CRT::DisplayType::PAL50, 1));

	// TODO: this is a copy and paste from the Electron; factor out.
	_crt->set_rgb_sampling_function(
		"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
		"{"
			"uint texValue = texture(sampler, coordinate).r;"
			"texValue >>= 4 - (int(icoordinate.x * 8) & 4);"
			"return vec3( uvec3(texValue) & uvec3(4u, 2u, 1u));"
		"}");

	_crt->set_output_device(Outputs::CRT::Television);
	_crt->set_visible_area(_crt->get_rect_for_area(50, 224, 16 * 6, 40 * 6, 4.0f / 3.0f));
}

std::shared_ptr<Outputs::CRT::CRT> VideoOutput::get_crt()
{
	return _crt;
}

void VideoOutput::run_for_cycles(int number_of_cycles)
{
	// Vertical: 0–39: pixels; otherwise blank; 48–53 sync
	// Horizontal: 0–223: pixels; otherwise blank; 256–259 sync

	while(number_of_cycles--)
	{
		_counter = (_counter + 1)%(312 * 64);	// TODO: NTSC
		int h_counter =_counter & 63;

		if(!h_counter)
		{
			_ink = 0xff;
			_paper = 0x00;
			_use_alternative_character_set = _use_double_height_characters = _blink_text = false;
			set_character_set_base_address();
			_phase += 64;

			if(!_counter)
			{
				_phase += 128;
				_frame_counter++;
			}
		}

		State new_state = Blank;
		if(
			(h_counter >= 48 && h_counter <= 53) ||
			(_counter >= 256*64 && _counter <= 259*64)) new_state = Sync;
		else if(h_counter >= 54 && h_counter <= 56) new_state = ColourBurst;
		else if(_counter < 224*64 && h_counter < 40) new_state = Pixels;

		if(_state != new_state)
		{
			switch(_state)
			{
				case ColourBurst:	_crt->output_colour_burst(_cycles_in_state * 6, _phase, 128);	break;
				case Sync:			_crt->output_sync(_cycles_in_state * 6);						break;
				case Blank:			_crt->output_blank(_cycles_in_state * 6);						break;
				case Pixels:		_crt->output_data(_cycles_in_state * 6, 2);						break;
			}
			_state = new_state;
			_cycles_in_state = 0;
			if(_state == Pixels) _pixel_target = _crt->allocate_write_area(120);
		}
		_cycles_in_state++;

		if(new_state == Pixels) {
			uint8_t pixels, control_byte;

			if(_is_graphics_mode && _counter < 200*64)
			{
				control_byte = pixels = _ram[0xa000 + (_counter >> 6) * 40 + h_counter];
			}
			else
			{
				int address = 0xbb80 + (_counter >> 9) * 40 + h_counter;
				control_byte = _ram[address];
				int line = _use_double_height_characters ? ((_counter >> 7) & 7) : ((_counter >> 6) & 7);
				pixels = _ram[_character_set_base_address + (control_byte&127) * 8 + line];
			}

			uint8_t inverse_mask = (control_byte & 0x80) ? 0x77 : 0x00;
			if(_blink_text) inverse_mask ^= (_frame_counter&32) ? 0x77 : 0x00;

			if((control_byte & 0x7f) >= 32)
			{
				uint8_t colours[2] = {
					(uint8_t)(_paper ^ inverse_mask),
					(uint8_t)(_ink ^ inverse_mask),
				};

				_pixel_target[0] = (colours[(pixels >> 4)&1] & 0x0f) | (colours[(pixels >> 5)&1] & 0xf0);
				_pixel_target[1] = (colours[(pixels >> 2)&1] & 0x0f) | (colours[(pixels >> 3)&1] & 0xf0);
				_pixel_target[2] = (colours[(pixels >> 0)&1] & 0x0f) | (colours[(pixels >> 1)&1] & 0xf0);
			}
			else
			{
				switch(control_byte & 0x7f)
				{
					case 0x00:		_ink = 0x00;	break;
					case 0x01:		_ink = 0x44;	break;
					case 0x02:		_ink = 0x22;	break;
					case 0x03:		_ink = 0x66;	break;
					case 0x04:		_ink = 0x11;	break;
					case 0x05:		_ink = 0x55;	break;
					case 0x06:		_ink = 0x33;	break;
					case 0x07:		_ink = 0x77;	break;

					case 0x08:	case 0x09:	case 0x0a: case 0x0b:
					case 0x0c:	case 0x0d:	case 0x0e: case 0x0f:
						_use_alternative_character_set = (control_byte&1);
						_use_double_height_characters = (control_byte&2);
						_blink_text = (control_byte&4);
						set_character_set_base_address();
					break;

					case 0x10:		_paper = 0x00;	break;
					case 0x11:		_paper = 0x44;	break;
					case 0x12:		_paper = 0x22;	break;
					case 0x13:		_paper = 0x66;	break;
					case 0x14:		_paper = 0x11;	break;
					case 0x15:		_paper = 0x55;	break;
					case 0x16:		_paper = 0x33;	break;
					case 0x17:		_paper = 0x77;	break;

					case 0x18: case 0x19: case 0x1a: case 0x1b:
					case 0x1c: case 0x1d: case 0x1e: case 0x1f:
						_is_graphics_mode = (control_byte & 4);
						_is_sixty_hertz = !(control_byte & 2);
					break;

					default: break;
				}
				_pixel_target[0] = _pixel_target[1] = _pixel_target[2] = (uint8_t)(_paper ^ inverse_mask);
			}
			_pixel_target += 3;
		}
	}
}
<|endoftext|>