<commit_before>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef LUABIND_PROPERTY_HPP_INCLUDED
#define LUABIND_PROPERTY_HPP_INCLUDED

#include <luabind/config.hpp>

namespace luabind { namespace detail
{
	class object_rep;
/*
	template<class R, class T, class Policies>
	int get(R(T::*f)() const, T* obj, lua_State* L, Policies* policies)  { return returns<R>::call(f, obj, L, policies); }

	template<class R, class T, class Policies>
	int get(R(*f)(const T*), T* obj, lua_State* L, Policies* policies) { return returns<R>::call(f, obj, L, policies); }

	template<class R, class T, class Policies>
	int get(R(*f)(const T&), T* obj, lua_State* L, Policies* policies) { return returns<R>::call(f, obj, L, policies); }
*/

	template<class R, class T, class Policies>
	int get(R(T::*f)() const, T* obj, lua_State* L, Policies* policies)  { return returns<R>::call(f, obj, L, policies); }

	template<class R, class T, class U, class Policies>
	int get(R(*f)(T), U* obj, lua_State* L, Policies* policies) { return returns<R>::call(f, obj, L, policies); }

	template<class T, class F, class Policies>
	struct get_caller : Policies
	{
		get_caller() {}
		get_caller(const Policies& p): Policies(p) {}

		int operator()(lua_State* L, int pointer_offset, F f)
		{
			// parameters on the lua stack:
			// 1. object_rep
			// 2. key (property name)

			object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
			class_rep* crep = obj->crep();

			void* ptr;

			if (crep->has_holder())
				ptr = crep->extractor()(obj->ptr());
			else
				ptr = obj->ptr();

			return get(f, reinterpret_cast<T*>(static_cast<char*>(ptr) + pointer_offset), L, static_cast<Policies*>(this));
		}
	};

	template<class T, class A1, class Policies>
	int set(void(T::*f)(A1), T* obj, lua_State* L, Policies* policies)  { return returns<void>::call(f, obj, L, policies); }
/*
	template<class R, class T, class A1, class Policies>
	int set(void(*f)(T*, A1), T* obj, lua_State* L, Policies* policies) { return returns<void>::call(f, obj, L, policies); }

	template<class T, class A1, class Policies>
	int set(void(*f)(T&, A1), T* obj, lua_State* L, Policies* policies) { return returns<void>::call(f, obj, L, policies); }
*/

	template<class T, class U, class A1, class Policies>
	int set(void(*f)(T, A1), U* obj, lua_State* L, Policies* policies) { return returns<void>::call(f, obj, L, policies); }

	template<class T, class F, class Policies>
	struct set_caller : Policies
	{
		int operator()(lua_State* L, int pointer_offset, F f)
		{
			// parameters on the lua stack:
			// 1. object_rep
			// 2. key (property name)
			// 3. value

			// and since call() expects it's first
			// parameter on index 2 we need to
			// remove the key-parameter (parameter 2).
			object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));
			class_rep* crep = obj->crep();

			void* ptr;

			if (crep->has_holder())
				ptr = crep->extractor()(obj->ptr());
			else
				ptr = obj->ptr();

			lua_remove(L, 2);
			return set(f, reinterpret_cast<T*>(static_cast<char*>(ptr) + pointer_offset), L, static_cast<Policies*>(this));
		}
	};

	// TODO: add support for policies
	template<class T, class D, class Policies>
	struct auto_set : Policies
	{
		auto_set() {}
		auto_set(const Policies& p): Policies(p) {}

		int operator()(lua_State* L, int pointer_offset, D T::*member)
		{
			int nargs = lua_gettop(L);

			// parameters on the lua stack:
			// 1. object_rep
			// 2. key (property name)
			// 3. value
			object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
			T* ptr =  reinterpret_cast<T*>(static_cast<char*>(obj->ptr()) + pointer_offset);

			typedef typename find_conversion_policy<1,Policies>::type converter_policy;
			typename converter_policy::template generate_converter<D,lua_to_cpp>::type converter;
			ptr->*member = converter.apply(L, LUABIND_DECORATE_TYPE(D), 3);

			int nret = lua_gettop(L) - nargs;

			const int indices[] = { 1, nargs + nret, 3 };

			policy_list_postcall<Policies>::apply(L, indices);

			return nret;
		}
	};

	// TODO: add support for policies
	template<class T, class D, class Policies>
	struct auto_get : Policies
	{
		auto_get() {}
		auto_get(const Policies& p): Policies(p) {}

		int operator()(lua_State* L, int pointer_offset, D T::*member)
		{
			int nargs = lua_gettop(L);

			// parameters on the lua stack:
			// 1. object_rep
			// 2. key (property name)
			object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
			T* ptr =  reinterpret_cast<T*>(static_cast<char*>(obj->ptr()) + pointer_offset);

			typedef typename find_conversion_policy<0,Policies>::type converter_policy;
			typename converter_policy::template generate_converter<D,cpp_to_lua>::type converter;
			converter.apply(L, ptr->*member);

			int nret = lua_gettop(L) - nargs;

			const int indices[] = { 1, nargs + nret };

			policy_list_postcall<Policies>::apply(L, indices);

			return nret;
		}
	};

}}

#endif // LUABIND_PROPERTY_HPP_INCLUDED

<commit_msg>fixed bug with holders and properties<commit_after>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef LUABIND_PROPERTY_HPP_INCLUDED
#define LUABIND_PROPERTY_HPP_INCLUDED

#include <luabind/config.hpp>

namespace luabind { namespace detail
{
	class object_rep;
/*
	template<class R, class T, class Policies>
	int get(R(T::*f)() const, T* obj, lua_State* L, Policies* policies)  { return returns<R>::call(f, obj, L, policies); }

	template<class R, class T, class Policies>
	int get(R(*f)(const T*), T* obj, lua_State* L, Policies* policies) { return returns<R>::call(f, obj, L, policies); }

	template<class R, class T, class Policies>
	int get(R(*f)(const T&), T* obj, lua_State* L, Policies* policies) { return returns<R>::call(f, obj, L, policies); }
*/

	template<class R, class T, class Policies>
	int get(R(T::*f)() const, T* obj, lua_State* L, Policies* policies)  { return returns<R>::call(f, obj, L, policies); }

	template<class R, class T, class U, class Policies>
	int get(R(*f)(T), U* obj, lua_State* L, Policies* policies) { return returns<R>::call(f, obj, L, policies); }

	template<class T, class F, class Policies>
	struct get_caller : Policies
	{
		get_caller() {}
		get_caller(const Policies& p): Policies(p) {}

		int operator()(lua_State* L, int pointer_offset, F f)
		{
			// parameters on the lua stack:
			// 1. object_rep
			// 2. key (property name)

			object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
			class_rep* crep = obj->crep();

			void* ptr;

			if (crep->has_holder())
				ptr = crep->extractor()(obj->ptr());
			else
				ptr = obj->ptr();

			return get(f, reinterpret_cast<T*>(static_cast<char*>(ptr) + pointer_offset), L, static_cast<Policies*>(this));
		}
	};

	template<class T, class A1, class Policies>
	int set(void(T::*f)(A1), T* obj, lua_State* L, Policies* policies)  { return returns<void>::call(f, obj, L, policies); }
/*
	template<class R, class T, class A1, class Policies>
	int set(void(*f)(T*, A1), T* obj, lua_State* L, Policies* policies) { return returns<void>::call(f, obj, L, policies); }

	template<class T, class A1, class Policies>
	int set(void(*f)(T&, A1), T* obj, lua_State* L, Policies* policies) { return returns<void>::call(f, obj, L, policies); }
*/

	template<class T, class U, class A1, class Policies>
	int set(void(*f)(T, A1), U* obj, lua_State* L, Policies* policies) { return returns<void>::call(f, obj, L, policies); }

	template<class T, class F, class Policies>
	struct set_caller : Policies
	{
		int operator()(lua_State* L, int pointer_offset, F f)
		{
			// parameters on the lua stack:
			// 1. object_rep
			// 2. key (property name)
			// 3. value

			// and since call() expects it's first
			// parameter on index 2 we need to
			// remove the key-parameter (parameter 2).
			object_rep* obj = reinterpret_cast<object_rep*>(lua_touserdata(L, 1));
			class_rep* crep = obj->crep();

			void* ptr;

			if (crep->has_holder())
				ptr = crep->extractor()(obj->ptr());
			else
				ptr = obj->ptr();

			lua_remove(L, 2);
			return set(f, reinterpret_cast<T*>(static_cast<char*>(ptr) + pointer_offset), L, static_cast<Policies*>(this));
		}
	};

	// TODO: add support for policies
	template<class T, class D, class Policies>
	struct auto_set : Policies
	{
		auto_set() {}
		auto_set(const Policies& p): Policies(p) {}

		int operator()(lua_State* L, int pointer_offset, D T::*member)
		{
			int nargs = lua_gettop(L);

			// parameters on the lua stack:
			// 1. object_rep
			// 2. key (property name)
			// 3. value
			object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
			class_rep* crep = obj->crep();

			void* raw_ptr;

			if (crep->has_holder())
				raw_ptr = crep->extractor()(obj->ptr());
			else
				raw_ptr = obj->ptr();

			T* ptr =  reinterpret_cast<T*>(static_cast<char*>(raw_ptr) + pointer_offset);

			typedef typename find_conversion_policy<1,Policies>::type converter_policy;
			typename converter_policy::template generate_converter<D,lua_to_cpp>::type converter;
			ptr->*member = converter.apply(L, LUABIND_DECORATE_TYPE(D), 3);

			int nret = lua_gettop(L) - nargs;

			const int indices[] = { 1, nargs + nret, 3 };

			policy_list_postcall<Policies>::apply(L, indices);

			return nret;
		}
	};

	// TODO: add support for policies
	template<class T, class D, class Policies>
	struct auto_get : Policies
	{
		auto_get() {}
		auto_get(const Policies& p): Policies(p) {}

		int operator()(lua_State* L, int pointer_offset, D T::*member)
		{
			int nargs = lua_gettop(L);

			// parameters on the lua stack:
			// 1. object_rep
			// 2. key (property name)
			object_rep* obj = static_cast<object_rep*>(lua_touserdata(L, 1));
			class_rep* crep = obj->crep();

			void* raw_ptr;

			if (crep->has_holder())
				raw_ptr = crep->extractor()(obj->ptr());
			else
				raw_ptr = obj->ptr();

			T* ptr =  reinterpret_cast<T*>(static_cast<char*>(raw_ptr) + pointer_offset);

			typedef typename find_conversion_policy<0,Policies>::type converter_policy;
			typename converter_policy::template generate_converter<D,cpp_to_lua>::type converter;
			converter.apply(L, ptr->*member);

			int nret = lua_gettop(L) - nargs;

			const int indices[] = { 1, nargs + nret };

			policy_list_postcall<Policies>::apply(L, indices);

			return nret;
		}
	};

}}

#endif // LUABIND_PROPERTY_HPP_INCLUDED

<|endoftext|>


<commit_before>#include "type-reference.h"

using namespace arua;
using namespace std;

TypeReference::TypeReference()
		: Type(TypeType::REFERENCE) {
}

void TypeReference::setBaseType(Ptr<Type> baseType) throw() {
	this->baseType = baseType;
}

Ptr<Type> TypeReference::getBaseType() throw() {
	return this->baseType;
}

bool TypeReference::operator ==(const Type &other) const throw() {
	return (other.getTypeType() == TypeType::REFERENCE)
		&& (this->baseType == ((TypeReference *)&other)->baseType);
}

bool TypeReference::canBeAssignedTo(const Type &other) const throw() {
	return *this == other;
}
<commit_msg>fix cosmetic blemish<commit_after>#include "type-reference.h"

using namespace arua;
using namespace std;

TypeReference::TypeReference()
		: Type(TypeType::REFERENCE) {
}

void TypeReference::setBaseType(Ptr<Type> baseType) throw() {
	this->baseType = baseType;
}

Ptr<Type> TypeReference::getBaseType() throw() {
	return this->baseType;
}

bool TypeReference::operator ==(const Type &other) const throw() {
	return (other.getTypeType() == TypeType::REFERENCE)
		&& (this->baseType == ((TypeReference *)&other)->baseType);
}

bool TypeReference::canBeAssignedTo(const Type &other) const throw() {
	return *this == other;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 Plenluno All rights reserved.

#include <libj/collection.h>
#include <libj/console.h>
#include <libj/json.h>
#include <libj/map.h>
#include <libj/string.h>

#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
#include <string>

#pragma GCC diagnostic ignored "-Wformat-security"

namespace libj {
namespace console {

static Level logLevel = DEBUG;

static Boolean isPrintable(Level level) {
    return level != OFF && logLevel <= level;
}

void setLevel(Level level) {
    logLevel = level;
}

static Color foreDebug   = DEFAULT;
static Color backDebug   = DEFAULT;
static Color foreInfo    = DEFAULT;
static Color backInfo    = DEFAULT;
static Color foreNormal  = DEFAULT;
static Color backNormal  = DEFAULT;
static Color foreWarning = DEFAULT;
static Color backWarning = DEFAULT;
static Color foreError   = DEFAULT;
static Color backError   = DEFAULT;

static const char* fore(Color color) {
    switch (color) {
    case DEFAULT:
        return "";
    case BLACK:
        return "\033[30m";
    case RED:
        return "\033[31m";
    case GREEN:
        return "\033[32m";
    case YELLOW:
        return "\033[33m";
    case BLUE:
        return "\033[34m";
    case MAGENTA:
        return "\033[35m";
    case CYAN:
        return "\033[36m";
    case WHITE:
        return "\033[37m";
    default:
        assert(false);
        return "";
    }
}

static const char* back(Color color) {
    switch (color) {
    case DEFAULT:
        return "";
    case BLACK:
        return "\033[40m";
    case RED:
        return "\033[41m";
    case GREEN:
        return "\033[42m";
    case YELLOW:
        return "\033[43m";
    case BLUE:
        return "\033[44m";
    case MAGENTA:
        return "\033[45m";
    case CYAN:
        return "\033[46m";
    case WHITE:
        return "\033[47m";
    default:
        assert(false);
        return "";
    }
}

static const char* fore(Level level) {
    Color color;
    switch (level) {
    case DEBUG:
        color = foreDebug;
        break;
    case INFO:
        color = foreInfo;
        break;
    case NORMAL:
        color = foreNormal;
        break;
    case WARNING:
        color = foreWarning;
        break;
    case ERROR:
        color = foreError;
        break;
    case OFF:
        color = DEFAULT;
        break;
    }
    return fore(color);
}

static const char* back(Level level) {
    Color color;
    switch (level) {
    case DEBUG:
        color = backDebug;
        break;
    case INFO:
        color = backInfo;
        break;
    case NORMAL:
        color = backNormal;
        break;
    case WARNING:
        color = backWarning;
        break;
    case ERROR:
        color = backError;
        break;
    case OFF:
        color = DEFAULT;
        break;
    }
    return back(color);
}

void setForegroundColor(Level level, Color color) {
    switch (level) {
    case DEBUG:
        foreDebug = color;
        break;
    case INFO:
        foreInfo = color;
        break;
    case NORMAL:
        foreNormal = color;
        break;
    case WARNING:
        foreWarning = color;
        break;
    case ERROR:
        foreError = color;
        break;
    case OFF:
        break;
    }
}

void setBackgroundColor(Level level, Color color) {
    switch (level) {
    case DEBUG:
        backDebug = color;
        break;
    case INFO:
        backInfo = color;
        break;
    case NORMAL:
        backNormal = color;
        break;
    case WARNING:
        backWarning = color;
        break;
    case ERROR:
        backError = color;
        break;
    case OFF:
        break;
    }
}

#define LIBJ_VFPRINTF(LEVEL, OUT, FMT) \
    va_list argp; \
    va_start(argp, FMT); \
    fprintf(OUT, fore(LEVEL)); \
    fprintf(OUT, back(LEVEL)); \
    vfprintf(OUT, FMT, argp); \
    fprintf(OUT, "\033[0m"); \
    fprintf(OUT, "\033[0m");

void printf(Level level, const char* fmt, ...) {
    if (!isPrintable(level)) return;

    FILE* out = 0;
    switch (level) {
    case DEBUG:
    case INFO:
    case NORMAL:
        out = stdout;
        break;
    case WARNING:
    case ERROR:
        out = stderr;
        break;
    case OFF:
        assert(false);
    }

    LIBJ_VFPRINTF(level, out, fmt);
}

static String::CPtr toString(const Value& val) {
    String::CPtr s = String::null();
    if (val.instanceof(Type<Map>::id()) ||
        val.instanceof(Type<Collection>::id())) {
        s = json::stringify(val);
    } else {
        s = String::valueOf(val);
    }
    return s;
}

void printv(
    Level level, const char* fmt,
    const Value& v0, const Value& v1,
    const Value& v2, const Value& v3,
    const Value& v4, const Value& v5,
    const Value& v6, const Value& v7,
    const Value& v8, const Value& v9) {
    if (!isPrintable(level)) return;

    const Size kMax = 10;
    std::string format(fmt);
    Size count = 0;
    size_t pos = 0;
    while (1) {
        pos = format.find("%v", pos);
        if (pos == std::string::npos) {
            break;
        } else {
            format.replace(pos, 2, "%s");
            count++;
        }
    }

    String::CPtr s[kMax];
    s[0] = toString(v0);
    s[1] = toString(v1);
    s[2] = toString(v2);
    s[3] = toString(v3);
    s[4] = toString(v4);
    s[5] = toString(v5);
    s[6] = toString(v6);
    s[7] = toString(v7);
    s[8] = toString(v8);
    s[9] = toString(v9);
    for (Size i = count; i < kMax; i++) {
        format += "%s";
        s[i] = String::null();
    }

    printf(level, format.c_str(),
        s[0] ? s[0]->toStdString().c_str() : "",
        s[1] ? s[1]->toStdString().c_str() : "",
        s[2] ? s[2]->toStdString().c_str() : "",
        s[3] ? s[3]->toStdString().c_str() : "",
        s[4] ? s[4]->toStdString().c_str() : "",
        s[5] ? s[5]->toStdString().c_str() : "",
        s[6] ? s[6]->toStdString().c_str() : "",
        s[7] ? s[7]->toStdString().c_str() : "",
        s[8] ? s[8]->toStdString().c_str() : "",
        s[9] ? s[9]->toStdString().c_str() : "");
}

#define LIBJ_PRINTLN(LEVEL, OUT, FMT) \
    if (!isPrintable(LEVEL)) return; \
    if (FMT) { \
        LIBJ_VFPRINTF(LEVEL, OUT, FMT) \
        fprintf(OUT, "\n"); \
        return; \
    }

void log(const char* fmt, ...) {
    LIBJ_PRINTLN(NORMAL, stdout, fmt);
    if (!fmt) { log(static_cast<Value>(0)); }
}

void debug(const char* fmt, ...) {
    LIBJ_PRINTLN(DEBUG, stdout, fmt);
    if (!fmt) { debug(static_cast<Value>(0)); }
}

void info(const char* fmt, ...) {
    LIBJ_PRINTLN(INFO, stdout, fmt);
    if (!fmt) { info(static_cast<Value>(0)); }
}

void warn(const char* fmt, ...) {
    LIBJ_PRINTLN(WARNING, stderr, fmt);
    if (!fmt) { warn(static_cast<Value>(0)); }
}

void error(const char* fmt, ...) {
    LIBJ_PRINTLN(ERROR, stderr, fmt);
    if (!fmt) { error(static_cast<Value>(0)); }
}

Boolean log(const Value& val) {
    if (val.isUndefined() || !isPrintable(NORMAL))
        return false;

    String::CPtr s = toString(val);
    if (s) {
        log(s->toStdString().c_str());
        return true;
    } else {
        return false;
    }
}

Boolean debug(const Value& val) {
    if (val.isUndefined() || !isPrintable(DEBUG))
        return false;

    String::CPtr s = toString(val);
    if (s) {
        debug(s->toStdString().c_str());
        return true;
    } else {
        return false;
    }
}

Boolean info(const Value& val) {
    if (val.isUndefined() || !isPrintable(INFO))
        return false;

    String::CPtr s = toString(val);
    if (s) {
        info(s->toStdString().c_str());
        return true;
    } else {
        return false;
    }
}

Boolean warn(const Value& val) {
    if (val.isUndefined() || !isPrintable(WARNING))
        return false;

    String::CPtr s = toString(val);
    if (s) {
        warn(s->toStdString().c_str());
        return true;
    } else {
        return false;
    }
}

Boolean error(const Value& val) {
    if (val.isUndefined() || !isPrintable(ERROR))
        return false;

    String::CPtr s = toString(val);
    if (s) {
        error(s->toStdString().c_str());
        return true;
    } else {
        return false;
    }
}

}  // namespace console
}  // namespace libj
<commit_msg>make console thread-safe<commit_after>// Copyright (c) 2012 Plenluno All rights reserved.

#include <libj/collection.h>
#include <libj/console.h>
#include <libj/json.h>
#include <libj/map.h>
#include <libj/string.h>
#include <libj/detail/mutex.h>

#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
#include <string>

#pragma GCC diagnostic ignored "-Wformat-security"

namespace libj {
namespace console {

static Level logLevel = DEBUG;

static Boolean isPrintable(Level level) {
    return level != OFF && logLevel <= level;
}

#ifdef LIBJ_USE_THREAD
    static detail::Mutex mutex;

    static Boolean lock() {
        return mutex.lock();
    }

    static Boolean unlock() {
        return mutex.unlock();
    }
#else
    static Boolean lock() {
        return true;
    }

    static Boolean unlock() {
        return true;
    }
#endif  // LIBJ_USE_THREAD

void setLevel(Level level) {
    lock();
    logLevel = level;
    unlock();
}

static Color foreDebug   = DEFAULT;
static Color backDebug   = DEFAULT;
static Color foreInfo    = DEFAULT;
static Color backInfo    = DEFAULT;
static Color foreNormal  = DEFAULT;
static Color backNormal  = DEFAULT;
static Color foreWarning = DEFAULT;
static Color backWarning = DEFAULT;
static Color foreError   = DEFAULT;
static Color backError   = DEFAULT;

static const char* fore(Color color) {
    switch (color) {
    case DEFAULT:
        return "";
    case BLACK:
        return "\033[30m";
    case RED:
        return "\033[31m";
    case GREEN:
        return "\033[32m";
    case YELLOW:
        return "\033[33m";
    case BLUE:
        return "\033[34m";
    case MAGENTA:
        return "\033[35m";
    case CYAN:
        return "\033[36m";
    case WHITE:
        return "\033[37m";
    default:
        assert(false);
        return "";
    }
}

static const char* back(Color color) {
    switch (color) {
    case DEFAULT:
        return "";
    case BLACK:
        return "\033[40m";
    case RED:
        return "\033[41m";
    case GREEN:
        return "\033[42m";
    case YELLOW:
        return "\033[43m";
    case BLUE:
        return "\033[44m";
    case MAGENTA:
        return "\033[45m";
    case CYAN:
        return "\033[46m";
    case WHITE:
        return "\033[47m";
    default:
        assert(false);
        return "";
    }
}

static const char* fore(Level level) {
    Color color;
    switch (level) {
    case DEBUG:
        color = foreDebug;
        break;
    case INFO:
        color = foreInfo;
        break;
    case NORMAL:
        color = foreNormal;
        break;
    case WARNING:
        color = foreWarning;
        break;
    case ERROR:
        color = foreError;
        break;
    case OFF:
        color = DEFAULT;
        break;
    }
    return fore(color);
}

static const char* back(Level level) {
    Color color;
    switch (level) {
    case DEBUG:
        color = backDebug;
        break;
    case INFO:
        color = backInfo;
        break;
    case NORMAL:
        color = backNormal;
        break;
    case WARNING:
        color = backWarning;
        break;
    case ERROR:
        color = backError;
        break;
    case OFF:
        color = DEFAULT;
        break;
    }
    return back(color);
}

void setForegroundColor(Level level, Color color) {
    lock();
    switch (level) {
    case DEBUG:
        foreDebug = color;
        break;
    case INFO:
        foreInfo = color;
        break;
    case NORMAL:
        foreNormal = color;
        break;
    case WARNING:
        foreWarning = color;
        break;
    case ERROR:
        foreError = color;
        break;
    case OFF:
        break;
    }
    unlock();
}

void setBackgroundColor(Level level, Color color) {
    lock();
    switch (level) {
    case DEBUG:
        backDebug = color;
        break;
    case INFO:
        backInfo = color;
        break;
    case NORMAL:
        backNormal = color;
        break;
    case WARNING:
        backWarning = color;
        break;
    case ERROR:
        backError = color;
        break;
    case OFF:
        break;
    }
    unlock();
}

#define LIBJ_VFPRINTF(LEVEL, OUT, FMT) \
    va_list argp; \
    va_start(argp, FMT); \
    fprintf(OUT, fore(LEVEL)); \
    fprintf(OUT, back(LEVEL)); \
    vfprintf(OUT, FMT, argp); \
    fprintf(OUT, "\033[0m"); \
    fprintf(OUT, "\033[0m");

void printf(Level level, const char* fmt, ...) {
    if (!isPrintable(level)) return;

    FILE* out = 0;
    switch (level) {
    case DEBUG:
    case INFO:
    case NORMAL:
        out = stdout;
        break;
    case WARNING:
    case ERROR:
        out = stderr;
        break;
    case OFF:
        assert(false);
    }

    lock();
    LIBJ_VFPRINTF(level, out, fmt);
    unlock();
}

static String::CPtr toString(const Value& val) {
    String::CPtr s = String::null();
    if (val.instanceof(Type<Map>::id()) ||
        val.instanceof(Type<Collection>::id())) {
        s = json::stringify(val);
    } else {
        s = String::valueOf(val);
    }
    return s;
}

void printv(
    Level level, const char* fmt,
    const Value& v0, const Value& v1,
    const Value& v2, const Value& v3,
    const Value& v4, const Value& v5,
    const Value& v6, const Value& v7,
    const Value& v8, const Value& v9) {
    if (!isPrintable(level)) return;

    const Size kMax = 10;
    std::string format(fmt);
    Size count = 0;
    size_t pos = 0;
    while (1) {
        pos = format.find("%v", pos);
        if (pos == std::string::npos) {
            break;
        } else {
            format.replace(pos, 2, "%s");
            count++;
        }
    }

    String::CPtr s[kMax];
    s[0] = toString(v0);
    s[1] = toString(v1);
    s[2] = toString(v2);
    s[3] = toString(v3);
    s[4] = toString(v4);
    s[5] = toString(v5);
    s[6] = toString(v6);
    s[7] = toString(v7);
    s[8] = toString(v8);
    s[9] = toString(v9);
    for (Size i = count; i < kMax; i++) {
        format += "%s";
        s[i] = String::null();
    }

    printf(level, format.c_str(),
        s[0] ? s[0]->toStdString().c_str() : "",
        s[1] ? s[1]->toStdString().c_str() : "",
        s[2] ? s[2]->toStdString().c_str() : "",
        s[3] ? s[3]->toStdString().c_str() : "",
        s[4] ? s[4]->toStdString().c_str() : "",
        s[5] ? s[5]->toStdString().c_str() : "",
        s[6] ? s[6]->toStdString().c_str() : "",
        s[7] ? s[7]->toStdString().c_str() : "",
        s[8] ? s[8]->toStdString().c_str() : "",
        s[9] ? s[9]->toStdString().c_str() : "");
}

#define LIBJ_PRINTLN(LEVEL, OUT, FMT) \
    if (!isPrintable(LEVEL)) return; \
    if (FMT) { \
        lock(); \
        LIBJ_VFPRINTF(LEVEL, OUT, FMT) \
        fprintf(OUT, "\n"); \
        unlock(); \
        return; \
    }

void log(const char* fmt, ...) {
    LIBJ_PRINTLN(NORMAL, stdout, fmt);
    if (!fmt) { log(static_cast<Value>(0)); }
}

void debug(const char* fmt, ...) {
    LIBJ_PRINTLN(DEBUG, stdout, fmt);
    if (!fmt) { debug(static_cast<Value>(0)); }
}

void info(const char* fmt, ...) {
    LIBJ_PRINTLN(INFO, stdout, fmt);
    if (!fmt) { info(static_cast<Value>(0)); }
}

void warn(const char* fmt, ...) {
    LIBJ_PRINTLN(WARNING, stderr, fmt);
    if (!fmt) { warn(static_cast<Value>(0)); }
}

void error(const char* fmt, ...) {
    LIBJ_PRINTLN(ERROR, stderr, fmt);
    if (!fmt) { error(static_cast<Value>(0)); }
}

Boolean log(const Value& val) {
    if (val.isUndefined() || !isPrintable(NORMAL))
        return false;

    String::CPtr s = toString(val);
    if (s) {
        log(s->toStdString().c_str());
        return true;
    } else {
        return false;
    }
}

Boolean debug(const Value& val) {
    if (val.isUndefined() || !isPrintable(DEBUG))
        return false;

    String::CPtr s = toString(val);
    if (s) {
        debug(s->toStdString().c_str());
        return true;
    } else {
        return false;
    }
}

Boolean info(const Value& val) {
    if (val.isUndefined() || !isPrintable(INFO))
        return false;

    String::CPtr s = toString(val);
    if (s) {
        info(s->toStdString().c_str());
        return true;
    } else {
        return false;
    }
}

Boolean warn(const Value& val) {
    if (val.isUndefined() || !isPrintable(WARNING))
        return false;

    String::CPtr s = toString(val);
    if (s) {
        warn(s->toStdString().c_str());
        return true;
    } else {
        return false;
    }
}

Boolean error(const Value& val) {
    if (val.isUndefined() || !isPrintable(ERROR))
        return false;

    String::CPtr s = toString(val);
    if (s) {
        error(s->toStdString().c_str());
        return true;
    } else {
        return false;
    }
}

}  // namespace console
}  // namespace libj
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <sstream>
#include <unordered_map>
#include "BigInt.hpp"

class Tests : public ::testing::Test {};

using hausp::BigInt;

const std::vector<std::string>& sampleNumbers() {
    static bool prepared = false;
    static std::vector<std::string> numbers = {
        "42",
        "123456781234567812345678"
    };

    if (!prepared) {
        std::stringstream ss;
        for (size_t i = 0; i < 300; i++) {
            ss << "123456781234567812345678";
        }
        numbers.push_back(ss.str());
        prepared = true;
    }

    return numbers;
}

inline std::string repeat(size_t v, size_t n) {
    return std::string(n, v + '0');
}

inline BigInt fs(const std::string& s) {
    return BigInt::fromString(s);
}

TEST_F(Tests, SimpleConstruction) {
    const auto& numbers = sampleNumbers();
    std::stringstream ss;
    for (auto& number : numbers) {
        ss << fs(number);
        ASSERT_EQ(ss.str(), number);
        ss.str("");
    }
}

TEST_F(Tests, ExplicitSignConstruction) {
    const auto& numbers = sampleNumbers();
    std::stringstream ss;
    for (auto& number : numbers) {
        auto n = "-" + number;
        ss << fs(n);
        ASSERT_EQ(ss.str(), n);
        ss.str("");

        ss << fs("+" + number);
        ASSERT_EQ(ss.str(), number);
        ss.str("");
    }
}

TEST_F(Tests, Inequalities) {
    ASSERT_TRUE(
        fs("8423982138934987132893497547132978423978132") ==
        fs("8423982138934987132893497547132978423978132")
    );

    ASSERT_TRUE(
        fs("8423982138934987132893497547132978423978132") !=
        fs("8423982138934987132893497547132978423978131")
    );

    ASSERT_TRUE(
        fs("8423982138934987132893497547132978423978132") !=
        fs("2349547891279342674589009129045978120945789")
    );

    ASSERT_TRUE(
        fs("8423982138934987132893497547132978423978132") !=
        fs("234954789127934229045978120945789")
    );

    ASSERT_TRUE(BigInt(-42) == BigInt(-42));
    ASSERT_TRUE(BigInt(-42) < BigInt(42));
    ASSERT_TRUE(BigInt(42) > BigInt(-42));

    ASSERT_TRUE(BigInt() == BigInt(0));
    ASSERT_TRUE(BigInt(0) <= BigInt(0));
    ASSERT_TRUE(BigInt(0) >= BigInt(0));
    ASSERT_TRUE(BigInt(-1) < BigInt(0));
    ASSERT_TRUE(BigInt(0) > BigInt(-1));
    ASSERT_FALSE(BigInt(0) > BigInt(0));
    ASSERT_FALSE(BigInt(0) < BigInt(0));

    auto n1 = fs("1323089548042380213098650892138790");
    auto n2 = fs("2109428218005820520572960106810672");
    auto n3 = fs("132308954804238021309865089213879450");
    ASSERT_TRUE(n1 < n2);
    ASSERT_TRUE(n2 < n3);
    ASSERT_TRUE(n1 < n3);
    ASSERT_TRUE(n2 > n1);
    ASSERT_TRUE(n3 > n2);
    ASSERT_TRUE(n3 > n1);
}

TEST_F(Tests, Shifts) {
    std::unordered_map<size_t, BigInt> powers = {
        {1, 2},
        {2, 4},
        {3, 8},
        {4, 16},
        {5, 32},
        {100, fs("1267650600228229401496703205376")},
        {150, fs("1427247692705959881058285969449495136382746624")},
        {200, fs("1606938044258990275541962092341162602522202993782792835301376")}
    };

    auto n = BigInt(1);
    for (size_t i = 1; i <= 200; i++) {
        n <<= 1;
        if (powers.count(i) > 0) {
            ASSERT_EQ(n, powers[i]);
        }
    }

    for (size_t i = 199; i > 0; i--) {
        n >>= 1;
        if (powers.count(i) > 0) {
            ASSERT_EQ(n, powers[i]);
        }
    }

    auto a = fs("46819283774865195682109389689290389645910928367102845391784");
    auto b = fs("365775654491134341266479606947581169108679127867990979623");
    auto c = fs("46819283774865195682109389689290389645910928367102845391744");
    ASSERT_EQ(a >> 0, a);
    ASSERT_EQ(b >> 0, b);
    ASSERT_EQ(c >> 0, c);
    ASSERT_EQ(a << 0, a);
    ASSERT_EQ(b << 0, b);
    ASSERT_EQ(c << 0, c);

    ASSERT_EQ(a >> 7, b);
    ASSERT_EQ(b << 7, c);
    ASSERT_EQ(a >> 2 >> 3 >> 1 >> 1, b);
    ASSERT_EQ(b << 3 << 4, c);
    ASSERT_EQ(a >> 2 >> 2 >> 1 >> 2, b);
    ASSERT_EQ(b << 2 << 2 << 1 << 2, c);

    ASSERT_EQ(a << -7, b);
    ASSERT_EQ(b >> -7, c);
    ASSERT_EQ(a << -2 << -3 << -1 << -1, b);
    ASSERT_EQ(b >> -3 >> -4, c);
    ASSERT_EQ(a << -2 << -2 << -1 << -2, b);
    ASSERT_EQ(b >> -2 >> -2 >> -1 >> -2, c);

    ASSERT_EQ(a << 2 << -3 << -2 << 3, a);
    ASSERT_EQ(a >> 2 >> -3 >> -2 >> 3, a);

    ASSERT_EQ(BigInt(-2) << 31, BigInt(-4294967296));
    ASSERT_EQ(BigInt(-2) >> 31, BigInt(-1));
    ASSERT_EQ(BigInt(-2) >> 999999999, BigInt(-1));
    ASSERT_EQ(BigInt(-2) << -999999999, BigInt(-1));

    ASSERT_EQ(
        a << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10
          >> 5 >> 2 >> 7 >> 1 >> 9 >> 4 >> 3 >> 10 >> 6 >> 8,
        a
    );

    ASSERT_EQ(
        a >> -2 >> -9 >> -3 >> -1 >> -7 >> -10 >> -4 >> -8 >> -6 >> -5
          << -1 << -2 << -3 << -4 << -5 << -6 << -7 << -8 << -9 << -10,
        a
    );
}

TEST_F(Tests, AddAndSub) {
    for (long i = -10; i <= 10; i++) {
        auto value = BigInt(i);
        ASSERT_EQ(value + 0, value);
        ASSERT_EQ(value - 0, value);
    }

    auto n1 = fs(repeat(1, 1000));
    auto n2 = fs(repeat(2, 1000));
    auto n3 = fs(repeat(3, 1000));
    ASSERT_EQ(n1 + n1, n2);
    ASSERT_EQ(n1 + n2, n3);
    ASSERT_EQ(n3 - n1, n2);
    ASSERT_EQ(n3 - n2, n1);
    ASSERT_EQ(n1 - n2, -n1);
    ASSERT_EQ(n1 + n1 + n1, n3);
    ASSERT_EQ(n1 + 0, n1);
    ASSERT_EQ(n1 - 0, n1);
    ASSERT_EQ(n2 + 0, n2);
    ASSERT_EQ(n2 - 0, n2);
    ASSERT_EQ(n3 + 0, n3);
    ASSERT_EQ(n3 - 0, n3);

    ASSERT_EQ(
        fs("1" + repeat(0, 100)) - fs(repeat(9, 100)),
        BigInt(1)
    );

    ASSERT_EQ(
        fs(repeat(9, 100)) - fs("1" + repeat(0, 100)),
        BigInt(-1)
    );

    ASSERT_EQ(
        fs(repeat(4, 123)) + fs(repeat(5, 123)) + fs(repeat(1, 123)),
        fs(repeat(1, 123) + "0")
    );
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>Added multiplication/division tests<commit_after>#include <gtest/gtest.h>
#include <sstream>
#include <unordered_map>
#include "BigInt.hpp"

class Tests : public ::testing::Test {};

using hausp::BigInt;

const std::vector<std::string>& sampleNumbers() {
    static bool prepared = false;
    static std::vector<std::string> numbers = {
        "42",
        "123456781234567812345678"
    };

    if (!prepared) {
        std::stringstream ss;
        for (size_t i = 0; i < 300; i++) {
            ss << "123456781234567812345678";
        }
        numbers.push_back(ss.str());
        prepared = true;
    }

    return numbers;
}

inline std::string repeat(size_t v, size_t n) {
    return std::string(n, v + '0');
}

inline BigInt fs(const std::string& s) {
    return BigInt::fromString(s);
}

TEST_F(Tests, SimpleConstruction) {
    const auto& numbers = sampleNumbers();
    std::stringstream ss;
    for (auto& number : numbers) {
        ss << fs(number);
        ASSERT_EQ(ss.str(), number);
        ss.str("");
    }
}

TEST_F(Tests, ExplicitSignConstruction) {
    const auto& numbers = sampleNumbers();
    std::stringstream ss;
    for (auto& number : numbers) {
        auto n = "-" + number;
        ss << fs(n);
        ASSERT_EQ(ss.str(), n);
        ss.str("");

        ss << fs("+" + number);
        ASSERT_EQ(ss.str(), number);
        ss.str("");
    }
}

TEST_F(Tests, Inequalities) {
    ASSERT_TRUE(
        fs("8423982138934987132893497547132978423978132") ==
        fs("8423982138934987132893497547132978423978132")
    );

    ASSERT_TRUE(
        fs("8423982138934987132893497547132978423978132") !=
        fs("8423982138934987132893497547132978423978131")
    );

    ASSERT_TRUE(
        fs("8423982138934987132893497547132978423978132") !=
        fs("2349547891279342674589009129045978120945789")
    );

    ASSERT_TRUE(
        fs("8423982138934987132893497547132978423978132") !=
        fs("234954789127934229045978120945789")
    );

    ASSERT_TRUE(BigInt(-42) == BigInt(-42));
    ASSERT_TRUE(BigInt(-42) < BigInt(42));
    ASSERT_TRUE(BigInt(42) > BigInt(-42));

    ASSERT_TRUE(BigInt() == BigInt(0));
    ASSERT_TRUE(BigInt(0) <= BigInt(0));
    ASSERT_TRUE(BigInt(0) >= BigInt(0));
    ASSERT_TRUE(BigInt(-1) < BigInt(0));
    ASSERT_TRUE(BigInt(0) > BigInt(-1));
    ASSERT_FALSE(BigInt(0) > BigInt(0));
    ASSERT_FALSE(BigInt(0) < BigInt(0));

    auto n1 = fs("1323089548042380213098650892138790");
    auto n2 = fs("2109428218005820520572960106810672");
    auto n3 = fs("132308954804238021309865089213879450");
    ASSERT_TRUE(n1 < n2);
    ASSERT_TRUE(n2 < n3);
    ASSERT_TRUE(n1 < n3);
    ASSERT_TRUE(n2 > n1);
    ASSERT_TRUE(n3 > n2);
    ASSERT_TRUE(n3 > n1);
}

TEST_F(Tests, Shifts) {
    std::unordered_map<size_t, BigInt> powers = {
        {1, 2},
        {2, 4},
        {3, 8},
        {4, 16},
        {5, 32},
        {100, fs("1267650600228229401496703205376")},
        {150, fs("1427247692705959881058285969449495136382746624")},
        {200, fs("1606938044258990275541962092341162602522202993782792835301376")}
    };

    auto n = BigInt(1);
    for (size_t i = 1; i <= 200; i++) {
        n <<= 1;
        if (powers.count(i) > 0) {
            ASSERT_EQ(n, powers[i]);
        }
    }

    for (size_t i = 199; i > 0; i--) {
        n >>= 1;
        if (powers.count(i) > 0) {
            ASSERT_EQ(n, powers[i]);
        }
    }

    auto a = fs("46819283774865195682109389689290389645910928367102845391784");
    auto b = fs("365775654491134341266479606947581169108679127867990979623");
    auto c = fs("46819283774865195682109389689290389645910928367102845391744");
    ASSERT_EQ(a >> 0, a);
    ASSERT_EQ(b >> 0, b);
    ASSERT_EQ(c >> 0, c);
    ASSERT_EQ(a << 0, a);
    ASSERT_EQ(b << 0, b);
    ASSERT_EQ(c << 0, c);

    ASSERT_EQ(a >> 7, b);
    ASSERT_EQ(b << 7, c);
    ASSERT_EQ(a >> 2 >> 3 >> 1 >> 1, b);
    ASSERT_EQ(b << 3 << 4, c);
    ASSERT_EQ(a >> 2 >> 2 >> 1 >> 2, b);
    ASSERT_EQ(b << 2 << 2 << 1 << 2, c);

    ASSERT_EQ(a << -7, b);
    ASSERT_EQ(b >> -7, c);
    ASSERT_EQ(a << -2 << -3 << -1 << -1, b);
    ASSERT_EQ(b >> -3 >> -4, c);
    ASSERT_EQ(a << -2 << -2 << -1 << -2, b);
    ASSERT_EQ(b >> -2 >> -2 >> -1 >> -2, c);

    ASSERT_EQ(a << 2 << -3 << -2 << 3, a);
    ASSERT_EQ(a >> 2 >> -3 >> -2 >> 3, a);

    ASSERT_EQ(BigInt(-2) << 31, BigInt(-4294967296));
    ASSERT_EQ(BigInt(-2) >> 31, BigInt(-1));
    ASSERT_EQ(BigInt(-2) >> 999999999, BigInt(-1));
    ASSERT_EQ(BigInt(-2) << -999999999, BigInt(-1));

    ASSERT_EQ(
        a << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10
          >> 5 >> 2 >> 7 >> 1 >> 9 >> 4 >> 3 >> 10 >> 6 >> 8,
        a
    );

    ASSERT_EQ(
        a >> -2 >> -9 >> -3 >> -1 >> -7 >> -10 >> -4 >> -8 >> -6 >> -5
          << -1 << -2 << -3 << -4 << -5 << -6 << -7 << -8 << -9 << -10,
        a
    );
}

TEST_F(Tests, AddAndSub) {
    for (long i = -10; i <= 10; i++) {
        auto value = BigInt(i);
        ASSERT_EQ(value + 0, value);
        ASSERT_EQ(value - 0, value);
    }

    auto n1 = fs(repeat(1, 1000));
    auto n2 = fs(repeat(2, 1000));
    auto n3 = fs(repeat(3, 1000));
    ASSERT_EQ(n1 + n1, n2);
    ASSERT_EQ(n1 + n2, n3);
    ASSERT_EQ(n3 - n1, n2);
    ASSERT_EQ(n3 - n2, n1);
    ASSERT_EQ(n1 - n2, -n1);
    ASSERT_EQ(n1 + n1 + n1, n3);
    ASSERT_EQ(n1 + 0, n1);
    ASSERT_EQ(n1 - 0, n1);
    ASSERT_EQ(n2 + 0, n2);
    ASSERT_EQ(n2 - 0, n2);
    ASSERT_EQ(n3 + 0, n3);
    ASSERT_EQ(n3 - 0, n3);

    ASSERT_EQ(
        fs("1" + repeat(0, 100)) - fs(repeat(9, 100)),
        BigInt(1)
    );

    ASSERT_EQ(
        fs(repeat(9, 100)) - fs("1" + repeat(0, 100)),
        BigInt(-1)
    );

    ASSERT_EQ(
        fs(repeat(4, 123)) + fs(repeat(5, 123)) + fs(repeat(1, 123)),
        fs(repeat(1, 123) + "0")
    );
}

TEST_F(Tests, MultAndDiv) {
    for (long i = -10; i <= 10; i++) {
        auto n = BigInt(i);
        ASSERT_EQ(n * n, i * i);
    }

    auto a = fs("4098409820375475120983947658360293812094745981398749580238");
    auto b = fs("8138293712938792187354957049128038575479103980193812038203");
    auto c = fs("33354062874208333776063429386921166451576596124501770016498051490381316034098384194122679983367790328261517469832314");
    ASSERT_EQ(a * b, c);
    ASSERT_EQ(b * a, c);
    ASSERT_EQ(-a * b, -c);
    ASSERT_EQ(a * -b, -c);
    ASSERT_EQ(-a * -b, c);

    ASSERT_EQ(a * (a + b), a * a + a * b);
    ASSERT_EQ(a * (a - b), a * a - a * b);
    ASSERT_EQ((a + b) * (a - b), a * a - b * b);
    ASSERT_EQ((a - b) * (a + b), a * a - b * b);
    ASSERT_EQ((a + b) * (a + b), a * a + 2 * a * b + b * b);
    ASSERT_EQ((a - b) * (a - b), a * a - 2 * a * b + b * b);

    // ASSERT_EQ(BigInt(3) / 2, 1);
    // ASSERT_EQ(BigInt(-3) / 2, -1);
    // ASSERT_EQ(BigInt(3) / -2, -1);
    // ASSERT_EQ(BigInt(-3) / -2, 1);
    // ASSERT_EQ(a / 1, a);
    // ASSERT_EQ(b / 1, b);
    // ASSERT_EQ(c / 1, c);
    // ASSERT_EQ(a / a, 1);
    // ASSERT_EQ(b / b, 1);
    // ASSERT_EQ(c / c, 1);
    // ASSERT_EQ(c / a, b);
    // ASSERT_EQ(c / b, a);
    // ASSERT_EQ(-c / a, -b);
    // ASSERT_EQ(c / -b, -a);
    // ASSERT_EQ((a + c) / a, 1 + b);
    // ASSERT_EQ(-(a + c) / -a, 1 + b);
    // ASSERT_EQ((a - c) / a, 1 - b);
    // ASSERT_ANY_THROW(BigInt(1) / 0);
    // ASSERT_ANY_THROW(BigInt(-1) / 0);
    // ASSERT_ANY_THROW(BigInt(0) / 0);
    // ASSERT_ANY_THROW(a / 0);
    // ASSERT_ANY_THROW(a / (a - a));
    // ASSERT_ANY_THROW(b / (b * a - a * b));
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#ifndef CONTEXT_HPP
#define CONTEXT_HPP

//-------------------------------------------
// Context provides support of variables in a
// broader context than the statement itself.
//-------------------------------------------
class Context
{
public:
	Context ();
};

#endif
<commit_msg>Added context<commit_after>#ifndef CONTEXT_HPP
#define CONTEXT_HPP

//-------------------------------------------
// Context provides support of variables in a
// broader context than the statement itself.
//-------------------------------------------
class Context
{
public:
	Context ();
	virtual ~Context () = default;
};

#endif
<|endoftext|>


<commit_before>#include "control.hpp"
#include "model.hpp"

#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <GL/glu.h>
#include <SOIL/SOIL.h>

#include <chrono>
#include <cmath>
#include <iostream>
#include <memory>
#include <sstream>

#include "omp.h"

namespace Control {
	bool control::init(std::atomic_bool &alive) {
		//using namespace Util;
		// Task 1: view before model (splash)
		using namespace View;
		glfwSetInputMode(viewer.win, GLFW_STICKY_KEYS, 1);
		glfwMakeContextCurrent(viewer.win);

		using namespace Model;
		mesh_t mesh(50, 50, [](float s, float t, std::vector<float> &vertices) {
			vertices.push_back(2*s-1);
			vertices.emplace_back(2*t-1);
			vertices.emplace_back(s*s+t*t);
		});

		glGenBuffers(1, &viewer.ids[view::e_id_vbuf]);
		glBindBuffer(GL_ARRAY_BUFFER, viewer.ids[view::e_id_vbuf]);
		glBufferData(GL_ARRAY_BUFFER, mesh.vertices.size(),
			(void*) &mesh.vertices[0], GL_STATIC_DRAW);

		glGenBuffers(1, &viewer.ids[view::e_id_fbuf]);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, viewer.ids[view::e_id_fbuf]);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.faces.size(),
			(void*) &mesh.faces[0], viewer.ids[view::e_id_fbuf]);
		viewer.nTriangles = mesh.faces.size()/3;
		return alive;
		/*
		// Task 2: wavefront obj model loading
		using namespace Model;
		obj_t object;
		auto status = obj_t::load(this -> mpath, object);
		if(status != obj_t::e_ok) {
			errors.push_back("The model failed to load.");
			return alive = false;
		}

		glGenBuffers(view::e_id_model-view::e_id_vbuf,
				&viewer.ids[view::e_id_vbuf]);
		// TODO Use more than first range of each obj type
		if(object.v_beg.size() == 0) {
			errors.push_back("The loaded model does not contain vertices.");
			return alive = false;
		} else {
			auto v0 = object.v_beg[0], v1 = object.v_end[0];
			glBindBuffer(GL_ARRAY_BUFFER, viewer.ids[view::e_id_vbuf]);
			glBufferData(GL_ARRAY_BUFFER, v1-v0,
					(void*)(&object.floats[v0]), GL_STATIC_DRAW);
		}
		if(object.vn_beg.size() != 0) {
			auto vn0 = object.vn_beg[0], vn1 = object.vn_end[0];
			glBindBuffer(GL_ARRAY_BUFFER, viewer.ids[view::e_id_vnbuf]);
			glBufferData(GL_ARRAY_BUFFER, vn1-vn0,
					(void*)(&object.floats[vn0]), GL_STATIC_DRAW);
		}
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
				viewer.ids[view::e_id_fbuf]);
		int f0, f1;
		if(object.f0_beg.size() != 0) {
			f0 = object.f0_beg[0];
			f1 = object.f0_end[0];
		} else if(object.f1_beg.size() != 0) {
			f0 = object.f1_beg[0];
			f1 = object.f1_end[0];
		} else if(object.f2_beg.size() != 0) {
			f0 = object.f2_beg[0];
			f1 = object.f2_end[0];
		} else if(object.f3_beg.size() != 0) {
			f0 = object.f3_beg[0];
			f1 = object.f3_end[0];
		} else {
			errors.push_back("The loaded model does not contain faces.");
			return alive = false;
		}
		viewer.nTriangles = (f1-f0)/3;
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, viewer.nTriangles*3,
				(void*)(&object.ints[f0]), GL_STATIC_DRAW);*/

		/*
		// Task 2: model loading
		using namespace Model::Ply;
 		Header model(this -> mpath);
 		if(model.status) {
			std::cout << model.statusContext << std::endl;
			return;
		}
		auto start = begin(model.elements),
				 stop = end(model.elements);
		auto vertices = std::find_if(start, stop,
			[](Element const& el) -> bool {
				// TODO Change behavior based on the number of elements
				return el.name == "vertex" && !el.has_list;
		}), indices = std::find_if(start, stop,
			[](Element const& el) -> bool {
				int sz = el.properties.size();
				return el.name == "face"
					&& (el.has_list ? sz==1 : sz==3);
		});
		if(vertices == stop || indices == stop) {
			std::cout << "The model is valid, but does not match "
				"the anticipated structure." << std::endl;
			return;
		Task 3: view after model
		glGenBuffers(1, &viewer.ids[view::e_id_vbuf]);
		glBindBuffer(GL_ARRAY_BUFFER, viewer.ids[view::e_id_vbuf]);
		glBufferData(GL_ARRAY_BUFFER, vertices->data.size(),
				(void*)(&vertices->data[0]), GL_STATIC_DRAW);

		glGenBuffers(1, &viewer.ids[view::e_id_ibuf]);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
				viewer.ids[view::e_id_ibuf]);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices->data.size(),
				(void*)(&indices->data[0]), GL_STATIC_DRAW);
		viewer.nTriangles = indices -> instances;
		glUseProgram(viewer.ids[view::e_id_prog]);*/
	}

	bool control::poll(std::atomic_bool &alive) {
		std::ostringstream oss;
		if(alive)
			viewer.poll(alive);
		if(alive) {
			if(glfwGetKey(viewer.win, GLFW_KEY_ESCAPE) == GLFW_PRESS)
				alive = false;
			int nButtons;
			const uint8_t *buttons =
				glfwGetJoystickButtons(GLFW_JOYSTICK_1, &nButtons);
			for(int i = 0; i < nButtons; i++) {
				bool pressed = buttons[i] == GLFW_PRESS;
				if(i==8 && pressed)
					alive = false;
			}
			int nAxes;
			const GLfloat *axes =
				glfwGetJoystickAxes(GLFW_JOYSTICK_1, &nAxes);
			for(int i = 0; i < nAxes; i++) {
				if(i == 0) {
					viewer.theta = axes[i]*2 + 1.5;
				} else if(i == 1) {
					viewer.phi = axes[i];
				}
			}
		}
		return alive;
	}

	bool control::run(std::atomic_bool &alive) {
		using namespace Model::Ply;
		auto delay = std::chrono::milliseconds(150);

		int frame = 0, dFrames = 0, fps = 0;
		auto kill = [&alive] {alive = false;};
		double t1 = glfwGetTime(), t2;
		while(true) {
			if(poll(alive)) viewer.run(alive);
			t2 = glfwGetTime() - t1;
			frame++;
			dFrames++;
			if(t2 > 1.0) {
				std::cout << "FPS: " << int(dFrames/t2) << std::endl;
				t1 += t2;
				dFrames = 0;
			}
			if(!alive) break;
		}
		return alive;
	}

	control::control(std::atomic_bool &alive, const char *mpath):
		task(), mpath(mpath), viewer(alive) {}
}
<commit_msg>Fixed buffer data call<commit_after>#include "control.hpp"
#include "model.hpp"

#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <GL/glu.h>
#include <SOIL/SOIL.h>

#include <chrono>
#include <cmath>
#include <iostream>
#include <memory>
#include <sstream>

#include "omp.h"

namespace Control {
	bool control::init(std::atomic_bool &alive) {
		//using namespace Util;
		// Task 1: view before model (splash)
		using namespace View;
		glfwSetInputMode(viewer.win, GLFW_STICKY_KEYS, 1);
		glfwMakeContextCurrent(viewer.win);

		using namespace Model;
		mesh_t mesh(50, 50, [](float s, float t, std::vector<float> &vertices) {
			vertices.push_back(s-.5);
			vertices.emplace_back(t-.5);
			vertices.emplace_back(s*s+t*t);
		});

		glGenBuffers(1, &viewer.ids[view::e_id_vbuf]);
		glBindBuffer(GL_ARRAY_BUFFER, viewer.ids[view::e_id_vbuf]);
		glBufferData(GL_ARRAY_BUFFER, mesh.vertices.size(),
			(void*) &mesh.vertices[0], GL_STATIC_DRAW);

		glGenBuffers(1, &viewer.ids[view::e_id_fbuf]);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, viewer.ids[view::e_id_fbuf]);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.faces.size(),
			(void*) &mesh.faces[0], GL_STATIC_DRAW);
		viewer.nTriangles = mesh.faces.size()/3;
		return alive;
		/*
		// Task 2: wavefront obj model loading
		using namespace Model;
		obj_t object;
		auto status = obj_t::load(this -> mpath, object);
		if(status != obj_t::e_ok) {
			errors.push_back("The model failed to load.");
			return alive = false;
		}

		glGenBuffers(view::e_id_model-view::e_id_vbuf,
				&viewer.ids[view::e_id_vbuf]);
		// TODO Use more than first range of each obj type
		if(object.v_beg.size() == 0) {
			errors.push_back("The loaded model does not contain vertices.");
			return alive = false;
		} else {
			auto v0 = object.v_beg[0], v1 = object.v_end[0];
			glBindBuffer(GL_ARRAY_BUFFER, viewer.ids[view::e_id_vbuf]);
			glBufferData(GL_ARRAY_BUFFER, v1-v0,
					(void*)(&object.floats[v0]), GL_STATIC_DRAW);
		}
		if(object.vn_beg.size() != 0) {
			auto vn0 = object.vn_beg[0], vn1 = object.vn_end[0];
			glBindBuffer(GL_ARRAY_BUFFER, viewer.ids[view::e_id_vnbuf]);
			glBufferData(GL_ARRAY_BUFFER, vn1-vn0,
					(void*)(&object.floats[vn0]), GL_STATIC_DRAW);
		}
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
				viewer.ids[view::e_id_fbuf]);
		int f0, f1;
		if(object.f0_beg.size() != 0) {
			f0 = object.f0_beg[0];
			f1 = object.f0_end[0];
		} else if(object.f1_beg.size() != 0) {
			f0 = object.f1_beg[0];
			f1 = object.f1_end[0];
		} else if(object.f2_beg.size() != 0) {
			f0 = object.f2_beg[0];
			f1 = object.f2_end[0];
		} else if(object.f3_beg.size() != 0) {
			f0 = object.f3_beg[0];
			f1 = object.f3_end[0];
		} else {
			errors.push_back("The loaded model does not contain faces.");
			return alive = false;
		}
		viewer.nTriangles = (f1-f0)/3;
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, viewer.nTriangles*3,
				(void*)(&object.ints[f0]), GL_STATIC_DRAW);*/

		/*
		// Task 2: model loading
		using namespace Model::Ply;
 		Header model(this -> mpath);
 		if(model.status) {
			std::cout << model.statusContext << std::endl;
			return;
		}
		auto start = begin(model.elements),
				 stop = end(model.elements);
		auto vertices = std::find_if(start, stop,
			[](Element const& el) -> bool {
				// TODO Change behavior based on the number of elements
				return el.name == "vertex" && !el.has_list;
		}), indices = std::find_if(start, stop,
			[](Element const& el) -> bool {
				int sz = el.properties.size();
				return el.name == "face"
					&& (el.has_list ? sz==1 : sz==3);
		});
		if(vertices == stop || indices == stop) {
			std::cout << "The model is valid, but does not match "
				"the anticipated structure." << std::endl;
			return;
		Task 3: view after model
		glGenBuffers(1, &viewer.ids[view::e_id_vbuf]);
		glBindBuffer(GL_ARRAY_BUFFER, viewer.ids[view::e_id_vbuf]);
		glBufferData(GL_ARRAY_BUFFER, vertices->data.size(),
				(void*)(&vertices->data[0]), GL_STATIC_DRAW);

		glGenBuffers(1, &viewer.ids[view::e_id_ibuf]);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
				viewer.ids[view::e_id_ibuf]);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices->data.size(),
				(void*)(&indices->data[0]), GL_STATIC_DRAW);
		viewer.nTriangles = indices -> instances;
		glUseProgram(viewer.ids[view::e_id_prog]);*/
	}

	bool control::poll(std::atomic_bool &alive) {
		std::ostringstream oss;
		if(alive)
			viewer.poll(alive);
		if(alive) {
			if(glfwGetKey(viewer.win, GLFW_KEY_ESCAPE) == GLFW_PRESS)
				alive = false;
			int nButtons;
			const uint8_t *buttons =
				glfwGetJoystickButtons(GLFW_JOYSTICK_1, &nButtons);
			for(int i = 0; i < nButtons; i++) {
				bool pressed = buttons[i] == GLFW_PRESS;
				if(i==8 && pressed)
					alive = false;
			}
			int nAxes;
			const GLfloat *axes =
				glfwGetJoystickAxes(GLFW_JOYSTICK_1, &nAxes);
			for(int i = 0; i < nAxes; i++) {
				if(i == 0) {
					viewer.theta = axes[i]*2 + 1.5;
				} else if(i == 1) {
					viewer.phi = axes[i];
				}
			}
		}
		return alive;
	}

	bool control::run(std::atomic_bool &alive) {
		using namespace Model::Ply;
		auto delay = std::chrono::milliseconds(150);

		int frame = 0, dFrames = 0, fps = 0;
		auto kill = [&alive] {alive = false;};
		double t1 = glfwGetTime(), t2;
		while(true) {
			if(poll(alive)) viewer.run(alive);
			t2 = glfwGetTime() - t1;
			frame++;
			dFrames++;
			if(t2 > 1.0) {
				std::cout << "FPS: " << int(dFrames/t2) << std::endl;
				t1 += t2;
				dFrames = 0;
			}
			if(!alive) break;
		}
		return alive;
	}

	control::control(std::atomic_bool &alive, const char *mpath):
		task(), mpath(mpath), viewer(alive) {}
}
<|endoftext|>


<commit_before>#include "ImageAnalyzer.h"

int main( int argc, char * argv[] )
{
  if( argc < 2 )
    {
    std::cerr << "Usage: " << argv[0];
    std::cerr << " inputImageFile";
    return EXIT_FAILURE;
    }

  // baseImageDir in cloud server: "/data/amnh/darwin"
  std::string baseImageDir = "/home/ibanez/data/amnh/darwin_notes/";

  ImageAnalyzer analyzer;

  analyzer.SetBaseDirectory(baseImageDir);
  analyzer.SetInputFilename(argv[1]);

  analyzer.ReadInputImage();

  analyzer.ThresholdInputImage();
  analyzer.WriteThresholdedImage();

  analyzer.ExtractLargestConnectedComponentImage();
  analyzer.WriteLargestConnectedComponentImage();

  analyzer.ComputeLinearScaleFromRuler();

  analyzer.FindImageMargins();

  analyzer.ExtractNorthSouthContours();
  analyzer.WriteNorthSouthContours();

  return EXIT_SUCCESS;
}
<commit_msg>Restore the input data directory as appears in the cloud VM.<commit_after>#include "ImageAnalyzer.h"

int main( int argc, char * argv[] )
{
  if( argc < 2 )
    {
    std::cerr << "Usage: " << argv[0];
    std::cerr << " inputImageFile";
    return EXIT_FAILURE;
    }

  std::string baseImageDir = "/data/amnh/darwin/";

  ImageAnalyzer analyzer;

  analyzer.SetBaseDirectory(baseImageDir);
  analyzer.SetInputFilename(argv[1]);

  analyzer.ReadInputImage();

  analyzer.ThresholdInputImage();
  analyzer.WriteThresholdedImage();

  analyzer.ExtractLargestConnectedComponentImage();
  analyzer.WriteLargestConnectedComponentImage();

  analyzer.ComputeLinearScaleFromRuler();

  analyzer.FindImageMargins();

  analyzer.ExtractNorthSouthContours();
  analyzer.WriteNorthSouthContours();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#pragma once
#ifndef AMFITEM_HPP
#define AMFITEM_HPP

#include <vector>

#include "amf.hpp"

namespace amf {

enum AmfMarker : u8 {
	AMF_UNDEFINED,
	AMF_NULL,
	AMF_FALSE,
	AMF_TRUE,
	AMF_INTEGER,
	AMF_DOUBLE,
	AMF_STRING,
	AMF_XMLDOC,
	AMF_DATE,
	AMF_ARRAY,
	AMF_OBJECT,
	AMF_XML,
	AMF_BYTEARRAY,
	AMF_VECTOR_INT,
	AMF_VECTOR_UINT,
	AMF_VECTOR_DOUBLE,
	AMF_VECTOR_OBJECT,
	AMF_DICTIONARY
};

class AmfItem {
public:

	virtual std::vector<u8> serialize() const = 0;
};

} // namespace amf

#endif
<commit_msg>Add virtual ctor to AmfItem.<commit_after>#pragma once
#ifndef AMFITEM_HPP
#define AMFITEM_HPP

#include <vector>

#include "amf.hpp"

namespace amf {

enum AmfMarker : u8 {
	AMF_UNDEFINED,
	AMF_NULL,
	AMF_FALSE,
	AMF_TRUE,
	AMF_INTEGER,
	AMF_DOUBLE,
	AMF_STRING,
	AMF_XMLDOC,
	AMF_DATE,
	AMF_ARRAY,
	AMF_OBJECT,
	AMF_XML,
	AMF_BYTEARRAY,
	AMF_VECTOR_INT,
	AMF_VECTOR_UINT,
	AMF_VECTOR_DOUBLE,
	AMF_VECTOR_OBJECT,
	AMF_DICTIONARY
};

class AmfItem {
public:
	virtual ~AmfItem() { }
	virtual std::vector<u8> serialize() const = 0;
};

} // namespace amf

#endif
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/phy/phy_cntrl.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file phy_cntrl.H
/// @brief Subroutines for the PHY phy control registers
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#ifndef _MSS_PHY_CNTRL_H_
#define _MSS_PHY_CNTRL_H_

#include <fapi2.H>
#include "p9_mc_scom_addresses.H"

namespace mss
{

// I have a dream that the PHY code can be shared among controllers. So, I drive the
// engine from a set of traits. This might be folly. Allow me to dream. BRS

///
/// @class pcTraits
/// @brief a collection of traits associated with the PHY phy control
/// @tparam T fapi2::TargetType representing the PHY
///
template< fapi2::TargetType T >
class pcTraits;

///
/// @class pcTraits
/// @brief a collection of traits associated with the Centaur PHY
///
template<>
class pcTraits<fapi2::TARGET_TYPE_MBA>
{
};

///
/// @class pcTraits
/// @brief a collection of traits associated with the Nimbus PHY phy control
///
template<>
class pcTraits<fapi2::TARGET_TYPE_MCA>
{
    public:
        // MCA phy control registers
        static const uint64_t PC_ERROR_STATUS0_REG = MCA_DDRPHY_PC_ERROR_STATUS0_P0;
        static const uint64_t PC_INIT_CAL_ERROR_REG = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0;

        enum
        {
            INIT_CAL_ERROR_WR_LEVEL = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_WR_LEVEL,
            INIT_CAL_ERROR_INITIAL_PAT_WRITE = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_INITIAL_PAT_WRITE,
            INIT_CAL_ERROR_DQS_ALIGN = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_DQS_ALIGN,
            INIT_CAL_ERROR_RDCLK_ALIGN = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_RDCLK_ALIGN,
            INIT_CAL_ERROR_READ_CTR = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_READ_CTR,
            INIT_CAL_ERROR_WRITE_CTR = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_WRITE_CTR,
            INIT_CAL_ERROR_INITIAL_COARSE_WR = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_INITIAL_COARSE_WR,
            INIT_CAL_ERROR_COARSE_RD = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_COARSE_RD,
            INIT_CAL_ERROR_CUSTOM_RD = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_CUSTOM_RD,
            INIT_CAL_ERROR_CUSTOM_WR = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_CUSTOM_WR,
            INIT_CAL_ERROR_DIGITAL_EYE = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_DIGITAL_EYE,
            INIT_CAL_ERROR_VREF = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_VREF,
            INIT_CAL_ERROR_RANK_PAIR = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_RANK_PAIR,
            INIT_CAL_ERROR_RANK_PAIR_LEN = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_RANK_PAIR_LEN,
        };

};

///
/// @class mss::pc
/// @brief Phy Control Class
/// @tparam T fapi2 Target Type
/// @tparam TT traits type defaults to pcTraits<T>
///
template< fapi2::TargetType T, typename TT = pcTraits<T> >
class pc
{
    public:

        ///
        /// @brief read PC_ERROR_STATUS0
        /// @param[in] i_target the fapi2 target of the port
        /// @param[out] o_data the value of the register
        /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode read_error_status0( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
        {
            FAPI_TRY( mss::getScom(i_target, TT::PC_ERROR_STATUS0_REG, o_data) );
            FAPI_DBG("pc_error_status0: 0x%016llx", o_data);
        fapi_try_exit:
            return fapi2::current_err;
        }

        ///
        /// @brief Write PC_ERROR_STATUS0
        /// @param[in] i_target the fapi2 target of the port
        /// @param[in] i_data the value of the register
        /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode write_error_status0( const fapi2::Target<T>& i_target,
                const fapi2::buffer<uint64_t>& i_data )
        {
            FAPI_DBG("pc_error_status0: 0x%016llx", i_data);
            FAPI_TRY( mss::putScom(i_target, TT::PC_ERROR_STATUS0_REG, i_data) );
        fapi_try_exit:
            return fapi2::current_err;
        }

        ///
        /// @brief reset pc_error_status0
        /// @param[in] i_target fapi2 target of the port
        /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode reset_error_status0( const fapi2::Target<T>& i_target )
        {
            FAPI_TRY( write_error_status0(i_target, 0) );

        fapi_try_exit:
            return fapi2::current_err;
        }

        ///
        /// @brief read PC_INIT_CAL_ERROR
        /// @param[in] i_target the fapi2 target of the port
        /// @param[out] o_data the value of the register
        /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode read_init_cal_error( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
        {
            FAPI_TRY( mss::getScom(i_target, TT::PC_INIT_CAL_ERROR_REG, o_data) );
            FAPI_DBG("pc_init_cal_error: 0x%016llx", o_data);
        fapi_try_exit:
            return fapi2::current_err;
        }

        ///
        /// @brief Write PC_INIT_CAL_ERROR
        /// @param[in] i_target the fapi2 target of the port
        /// @param[in] i_data the value of the register
        /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode write_init_cal_error( const fapi2::Target<T>& i_target,
                const fapi2::buffer<uint64_t>& i_data )
        {
            FAPI_DBG("pc_init_cal_error: 0x%016llx", i_data);
            FAPI_TRY( mss::putScom(i_target, TT::PC_INIT_CAL_ERROR_REG, i_data) );
        fapi_try_exit:
            return fapi2::current_err;
        }

        ///
        /// @brief reset pc_init_cal_error
        /// @param[in] i_target fapi2 target of the port
        /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode reset_init_cal_error( const fapi2::Target<T>& i_target )
        {
            FAPI_TRY( write_init_cal_error(i_target, 0) );

        fapi_try_exit:
            return fapi2::current_err;
        }

        ///
        /// @brief reset rc
        /// @param[in] i_target fapi2 target of the port
        /// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode reset( const fapi2::Target<T>& i_target )
        {
            FAPI_TRY( reset_error_status0(i_target) );

        fapi_try_exit:
            return fapi2::current_err;
        }

};

}

#endif
<commit_msg>Change include paths in memory/lib, tests<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/phy/phy_cntrl.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file phy_cntrl.H
/// @brief Subroutines for the PHY phy control registers
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#ifndef _MSS_PHY_CNTRL_H_
#define _MSS_PHY_CNTRL_H_

#include <fapi2.H>
#include <p9_mc_scom_addresses.H>

namespace mss
{

// I have a dream that the PHY code can be shared among controllers. So, I drive the
// engine from a set of traits. This might be folly. Allow me to dream. BRS

///
/// @class pcTraits
/// @brief a collection of traits associated with the PHY phy control
/// @tparam T fapi2::TargetType representing the PHY
///
template< fapi2::TargetType T >
class pcTraits;

///
/// @class pcTraits
/// @brief a collection of traits associated with the Centaur PHY
///
template<>
class pcTraits<fapi2::TARGET_TYPE_MBA>
{
};

///
/// @class pcTraits
/// @brief a collection of traits associated with the Nimbus PHY phy control
///
template<>
class pcTraits<fapi2::TARGET_TYPE_MCA>
{
    public:
        // MCA phy control registers
        static const uint64_t PC_ERROR_STATUS0_REG = MCA_DDRPHY_PC_ERROR_STATUS0_P0;
        static const uint64_t PC_INIT_CAL_ERROR_REG = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0;

        enum
        {
            INIT_CAL_ERROR_WR_LEVEL = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_WR_LEVEL,
            INIT_CAL_ERROR_INITIAL_PAT_WRITE = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_INITIAL_PAT_WRITE,
            INIT_CAL_ERROR_DQS_ALIGN = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_DQS_ALIGN,
            INIT_CAL_ERROR_RDCLK_ALIGN = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_RDCLK_ALIGN,
            INIT_CAL_ERROR_READ_CTR = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_READ_CTR,
            INIT_CAL_ERROR_WRITE_CTR = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_WRITE_CTR,
            INIT_CAL_ERROR_INITIAL_COARSE_WR = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_INITIAL_COARSE_WR,
            INIT_CAL_ERROR_COARSE_RD = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_COARSE_RD,
            INIT_CAL_ERROR_CUSTOM_RD = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_CUSTOM_RD,
            INIT_CAL_ERROR_CUSTOM_WR = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_CUSTOM_WR,
            INIT_CAL_ERROR_DIGITAL_EYE = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_DIGITAL_EYE,
            INIT_CAL_ERROR_VREF = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_VREF,
            INIT_CAL_ERROR_RANK_PAIR = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_RANK_PAIR,
            INIT_CAL_ERROR_RANK_PAIR_LEN = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0_RANK_PAIR_LEN,
        };

};

///
/// @class mss::pc
/// @brief Phy Control Class
/// @tparam T fapi2 Target Type
/// @tparam TT traits type defaults to pcTraits<T>
///
template< fapi2::TargetType T, typename TT = pcTraits<T> >
class pc
{
    public:

        ///
        /// @brief read PC_ERROR_STATUS0
        /// @param[in] i_target the fapi2 target of the port
        /// @param[out] o_data the value of the register
        /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode read_error_status0( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
        {
            FAPI_TRY( mss::getScom(i_target, TT::PC_ERROR_STATUS0_REG, o_data) );
            FAPI_DBG("pc_error_status0: 0x%016llx", o_data);
        fapi_try_exit:
            return fapi2::current_err;
        }

        ///
        /// @brief Write PC_ERROR_STATUS0
        /// @param[in] i_target the fapi2 target of the port
        /// @param[in] i_data the value of the register
        /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode write_error_status0( const fapi2::Target<T>& i_target,
                const fapi2::buffer<uint64_t>& i_data )
        {
            FAPI_DBG("pc_error_status0: 0x%016llx", i_data);
            FAPI_TRY( mss::putScom(i_target, TT::PC_ERROR_STATUS0_REG, i_data) );
        fapi_try_exit:
            return fapi2::current_err;
        }

        ///
        /// @brief reset pc_error_status0
        /// @param[in] i_target fapi2 target of the port
        /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode reset_error_status0( const fapi2::Target<T>& i_target )
        {
            FAPI_TRY( write_error_status0(i_target, 0) );

        fapi_try_exit:
            return fapi2::current_err;
        }

        ///
        /// @brief read PC_INIT_CAL_ERROR
        /// @param[in] i_target the fapi2 target of the port
        /// @param[out] o_data the value of the register
        /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode read_init_cal_error( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
        {
            FAPI_TRY( mss::getScom(i_target, TT::PC_INIT_CAL_ERROR_REG, o_data) );
            FAPI_DBG("pc_init_cal_error: 0x%016llx", o_data);
        fapi_try_exit:
            return fapi2::current_err;
        }

        ///
        /// @brief Write PC_INIT_CAL_ERROR
        /// @param[in] i_target the fapi2 target of the port
        /// @param[in] i_data the value of the register
        /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode write_init_cal_error( const fapi2::Target<T>& i_target,
                const fapi2::buffer<uint64_t>& i_data )
        {
            FAPI_DBG("pc_init_cal_error: 0x%016llx", i_data);
            FAPI_TRY( mss::putScom(i_target, TT::PC_INIT_CAL_ERROR_REG, i_data) );
        fapi_try_exit:
            return fapi2::current_err;
        }

        ///
        /// @brief reset pc_init_cal_error
        /// @param[in] i_target fapi2 target of the port
        /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode reset_init_cal_error( const fapi2::Target<T>& i_target )
        {
            FAPI_TRY( write_init_cal_error(i_target, 0) );

        fapi_try_exit:
            return fapi2::current_err;
        }

        ///
        /// @brief reset rc
        /// @param[in] i_target fapi2 target of the port
        /// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS if ok
        ///
        inline fapi2::ReturnCode reset( const fapi2::Target<T>& i_target )
        {
            FAPI_TRY( reset_error_status0(i_target) );

        fapi_try_exit:
            return fapi2::current_err;
        }

};

}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Steve Reinhardt
 *          Nathan Binkert
 */

#ifndef __CPU_BASE_HH__
#define __CPU_BASE_HH__

#include <vector>

#include "arch/isa_traits.hh"
#include "base/statistics.hh"
#include "config/full_system.hh"
#include "sim/eventq.hh"
#include "sim/insttracer.hh"
#include "mem/mem_object.hh"

#if FULL_SYSTEM
#include "arch/interrupts.hh"
#endif

class BranchPred;
class CheckerCPU;
class ThreadContext;
class System;
class Port;

namespace TheISA
{
    class Predecoder;
}

class CPUProgressEvent : public Event
{
  protected:
    Tick interval;
    Counter lastNumInst;
    BaseCPU *cpu;

  public:
    CPUProgressEvent(EventQueue *q, Tick ival, BaseCPU *_cpu);

    void process();

    virtual const char *description();
};

class BaseCPU : public MemObject
{
  protected:
    // CPU's clock period in terms of the number of ticks of curTime.
    Tick clock;
    // @todo remove me after debugging with legion done
    Tick instCnt;

  public:
//    Tick currentTick;
    inline Tick frequency() const { return Clock::Frequency / clock; }
    inline Tick ticks(int numCycles) const { return clock * numCycles; }
    inline Tick curCycle() const { return curTick / clock; }
    inline Tick tickToCycles(Tick val) const { return val / clock; }
    // @todo remove me after debugging with legion done
    Tick instCount() { return instCnt; }

    /** The next cycle the CPU should be scheduled, given a cache
     * access or quiesce event returning on this cycle.  This function
     * may return curTick if the CPU should run on the current cycle.
     */
    Tick nextCycle();

    /** The next cycle the CPU should be scheduled, given a cache
     * access or quiesce event returning on the given Tick.  This
     * function may return curTick if the CPU should run on the
     * current cycle.
     * @param begin_tick The tick that the event is completing on.
     */
    Tick nextCycle(Tick begin_tick);

#if FULL_SYSTEM
  protected:
//    uint64_t interrupts[TheISA::NumInterruptLevels];
//    uint64_t intstatus;
    TheISA::Interrupts interrupts;

  public:
    virtual void post_interrupt(int int_num, int index);
    virtual void clear_interrupt(int int_num, int index);
    virtual void clear_interrupts();
    virtual uint64_t get_interrupts(int int_num);

    bool check_interrupts(ThreadContext * tc) const
    { return interrupts.check_interrupts(tc); }

    class ProfileEvent : public Event
    {
      private:
        BaseCPU *cpu;
        int interval;

      public:
        ProfileEvent(BaseCPU *cpu, int interval);
        void process();
    };
    ProfileEvent *profileEvent;
#endif

  protected:
    std::vector<ThreadContext *> threadContexts;
    std::vector<TheISA::Predecoder *> predecoders;

    Trace::InstTracer * tracer;

  public:

    /// Provide access to the tracer pointer
    Trace::InstTracer * getTracer() { return tracer; }

    /// Notify the CPU that the indicated context is now active.  The
    /// delay parameter indicates the number of ticks to wait before
    /// executing (typically 0 or 1).
    virtual void activateContext(int thread_num, int delay) {}

    /// Notify the CPU that the indicated context is now suspended.
    virtual void suspendContext(int thread_num) {}

    /// Notify the CPU that the indicated context is now deallocated.
    virtual void deallocateContext(int thread_num) {}

    /// Notify the CPU that the indicated context is now halted.
    virtual void haltContext(int thread_num) {}

   /// Given a Thread Context pointer return the thread num
   int findContext(ThreadContext *tc);

   /// Given a thread num get tho thread context for it
   ThreadContext *getContext(int tn) { return threadContexts[tn]; }

  public:
    struct Params
    {
        std::string name;
        int numberOfThreads;
        bool deferRegistration;
        Counter max_insts_any_thread;
        Counter max_insts_all_threads;
        Counter max_loads_any_thread;
        Counter max_loads_all_threads;
        Tick clock;
        bool functionTrace;
        Tick functionTraceStart;
        System *system;
        int cpu_id;
        Trace::InstTracer * tracer;

        Tick phase;
#if FULL_SYSTEM
        Tick profile;

        bool do_statistics_insts;
        bool do_checkpoint_insts;
        bool do_quiesce;
#endif
        Tick progress_interval;
        BaseCPU *checker;

#if THE_ISA == MIPS_ISA
      /* Note: It looks like it will be better to allow simulator users
         to specify the values of individual variables instead of requiring
         users to define the values of entire registers
         Especially since a lot of these variables can be created from other
         user parameters  (cache descriptions)
                                               -jpp
      */
      // MIPS CP0 State - First individual variables
      // Page numbers refer to revision 2.50 (July 2005) of the MIPS32 ARM, Volume III (PRA)
      unsigned CP0_IntCtl_IPTI; // Page 93, IP Timer Interrupt
      unsigned CP0_IntCtl_IPPCI; // Page 94, IP Performance Counter Interrupt
      unsigned CP0_SrsCtl_HSS; // Page 95, Highest Implemented Shadow Set
      unsigned CP0_PRId_CompanyOptions; // Page 105, Manufacture options
      unsigned CP0_PRId_CompanyID; // Page 105, Company ID - (0-255, 1=>MIPS)
      unsigned CP0_PRId_ProcessorID; // Page 105
      unsigned CP0_PRId_Revision; // Page 105
      unsigned CP0_EBase_CPUNum; // Page 106, CPU Number in a multiprocessor system
      unsigned CP0_Config_BE; // Page 108, Big/Little Endian mode
      unsigned CP0_Config_AT; //Page 109
      unsigned CP0_Config_AR; //Page 109
      unsigned CP0_Config_MT; //Page 109
      unsigned CP0_Config_VI; //Page 109
      unsigned CP0_Config1_M; // Page 110
      unsigned CP0_Config1_MMU; // Page 110
      unsigned CP0_Config1_IS; // Page 110
      unsigned CP0_Config1_IL; // Page 111
      unsigned CP0_Config1_IA; // Page 111
      unsigned CP0_Config1_DS; // Page 111
      unsigned CP0_Config1_DL; // Page 112
      unsigned CP0_Config1_DA; // Page 112
      bool CP0_Config1_C2; // Page 112
      bool CP0_Config1_MD;// Page 112 - Technically not used in MIPS32
      bool CP0_Config1_PC;// Page 112
      bool CP0_Config1_WR;// Page 113
      bool CP0_Config1_CA;// Page 113
      bool CP0_Config1_EP;// Page 113
      bool CP0_Config1_FP;// Page 113
      bool CP0_Config2_M; // Page 114
      unsigned CP0_Config2_TU;// Page 114
      unsigned CP0_Config2_TS;// Page 114
      unsigned CP0_Config2_TL;// Page 115
      unsigned CP0_Config2_TA;// Page 115
      unsigned CP0_Config2_SU;// Page 115
      unsigned CP0_Config2_SS;// Page 115
      unsigned CP0_Config2_SL;// Page 116
      unsigned CP0_Config2_SA;// Page 116
      bool CP0_Config3_M; //// Page 117
      bool CP0_Config3_DSPP;// Page 117
      bool CP0_Config3_LPA;// Page 117
      bool CP0_Config3_VEIC;// Page 118
      bool CP0_Config3_VInt; // Page 118
      bool CP0_Config3_SP;// Page 118
      bool CP0_Config3_MT;// Page 119
      bool CP0_Config3_SM;// Page 119
      bool CP0_Config3_TL;// Page 119

      bool CP0_WatchHi_M; // Page 124
      bool CP0_PerfCtr_M; // Page 130
      bool CP0_PerfCtr_W; // Page 130

      // Then, whole registers
      unsigned CP0_PRId;
      unsigned CP0_Config;
      unsigned CP0_Config1;
      unsigned CP0_Config2;
      unsigned CP0_Config3;

#endif

        Params();
    };

    const Params *params;

    BaseCPU(Params *params);
    virtual ~BaseCPU();

    virtual void init();
    virtual void startup();
    virtual void regStats();

    virtual void activateWhenReady(int tid) {};

    void registerThreadContexts();

    /// Prepare for another CPU to take over execution.  When it is
    /// is ready (drained pipe) it signals the sampler.
    virtual void switchOut();

    /// Take over execution from the given CPU.  Used for warm-up and
    /// sampling.
    virtual void takeOverFrom(BaseCPU *, Port *ic, Port *dc);

    /**
     *  Number of threads we're actually simulating (<= SMT_MAX_THREADS).
     * This is a constant for the duration of the simulation.
     */
    int number_of_threads;

    /**
     * Vector of per-thread instruction-based event queues.  Used for
     * scheduling events based on number of instructions committed by
     * a particular thread.
     */
    EventQueue **comInstEventQueue;

    /**
     * Vector of per-thread load-based event queues.  Used for
     * scheduling events based on number of loads committed by
     *a particular thread.
     */
    EventQueue **comLoadEventQueue;

    System *system;

    Tick phase;

#if FULL_SYSTEM
    /**
     * Serialize this object to the given output stream.
     * @param os The stream to serialize to.
     */
    virtual void serialize(std::ostream &os);

    /**
     * Reconstruct the state of this object from a checkpoint.
     * @param cp The checkpoint use.
     * @param section The section name of this object
     */
    virtual void unserialize(Checkpoint *cp, const std::string &section);

#endif

    /**
     * Return pointer to CPU's branch predictor (NULL if none).
     * @return Branch predictor pointer.
     */
    virtual BranchPred *getBranchPred() { return NULL; };

    virtual Counter totalInstructions() const { return 0; }

    // Function tracing
  private:
    bool functionTracingEnabled;
    std::ostream *functionTraceStream;
    Addr currentFunctionStart;
    Addr currentFunctionEnd;
    Tick functionEntryTick;
    void enableFunctionTrace();
    void traceFunctionsInternal(Addr pc);

  protected:
    void traceFunctions(Addr pc)
    {
        if (functionTracingEnabled)
            traceFunctionsInternal(pc);
    }

  private:
    static std::vector<BaseCPU *> cpuList;   //!< Static global cpu list

  public:
    static int numSimulatedCPUs() { return cpuList.size(); }
    static Counter numSimulatedInstructions()
    {
        Counter total = 0;

        int size = cpuList.size();
        for (int i = 0; i < size; ++i)
            total += cpuList[i]->totalInstructions();

        return total;
    }

  public:
    // Number of CPU cycles simulated
    Stats::Scalar<> numCycles;
};

#endif // __CPU_BASE_HH__
<commit_msg>add core specific parameter to BaseCPU params<commit_after>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Steve Reinhardt
 *          Nathan Binkert
 */

#ifndef __CPU_BASE_HH__
#define __CPU_BASE_HH__

#include <vector>

#include "arch/isa_traits.hh"
#include "base/statistics.hh"
#include "config/full_system.hh"
#include "sim/eventq.hh"
#include "sim/insttracer.hh"
#include "mem/mem_object.hh"

#if FULL_SYSTEM
#include "arch/interrupts.hh"
#endif

class BranchPred;
class CheckerCPU;
class ThreadContext;
class System;
class Port;

namespace TheISA
{
    class Predecoder;
}

class CPUProgressEvent : public Event
{
  protected:
    Tick interval;
    Counter lastNumInst;
    BaseCPU *cpu;

  public:
    CPUProgressEvent(EventQueue *q, Tick ival, BaseCPU *_cpu);

    void process();

    virtual const char *description();
};

class BaseCPU : public MemObject
{
  protected:
    // CPU's clock period in terms of the number of ticks of curTime.
    Tick clock;
    // @todo remove me after debugging with legion done
    Tick instCnt;

  public:
//    Tick currentTick;
    inline Tick frequency() const { return Clock::Frequency / clock; }
    inline Tick ticks(int numCycles) const { return clock * numCycles; }
    inline Tick curCycle() const { return curTick / clock; }
    inline Tick tickToCycles(Tick val) const { return val / clock; }
    // @todo remove me after debugging with legion done
    Tick instCount() { return instCnt; }

    /** The next cycle the CPU should be scheduled, given a cache
     * access or quiesce event returning on this cycle.  This function
     * may return curTick if the CPU should run on the current cycle.
     */
    Tick nextCycle();

    /** The next cycle the CPU should be scheduled, given a cache
     * access or quiesce event returning on the given Tick.  This
     * function may return curTick if the CPU should run on the
     * current cycle.
     * @param begin_tick The tick that the event is completing on.
     */
    Tick nextCycle(Tick begin_tick);

#if FULL_SYSTEM
  protected:
//    uint64_t interrupts[TheISA::NumInterruptLevels];
//    uint64_t intstatus;
    TheISA::Interrupts interrupts;

  public:
    virtual void post_interrupt(int int_num, int index);
    virtual void clear_interrupt(int int_num, int index);
    virtual void clear_interrupts();
    virtual uint64_t get_interrupts(int int_num);

    bool check_interrupts(ThreadContext * tc) const
    { return interrupts.check_interrupts(tc); }

    class ProfileEvent : public Event
    {
      private:
        BaseCPU *cpu;
        int interval;

      public:
        ProfileEvent(BaseCPU *cpu, int interval);
        void process();
    };
    ProfileEvent *profileEvent;
#endif

  protected:
    std::vector<ThreadContext *> threadContexts;
    std::vector<TheISA::Predecoder *> predecoders;

    Trace::InstTracer * tracer;

  public:

    /// Provide access to the tracer pointer
    Trace::InstTracer * getTracer() { return tracer; }

    /// Notify the CPU that the indicated context is now active.  The
    /// delay parameter indicates the number of ticks to wait before
    /// executing (typically 0 or 1).
    virtual void activateContext(int thread_num, int delay) {}

    /// Notify the CPU that the indicated context is now suspended.
    virtual void suspendContext(int thread_num) {}

    /// Notify the CPU that the indicated context is now deallocated.
    virtual void deallocateContext(int thread_num) {}

    /// Notify the CPU that the indicated context is now halted.
    virtual void haltContext(int thread_num) {}

   /// Given a Thread Context pointer return the thread num
   int findContext(ThreadContext *tc);

   /// Given a thread num get tho thread context for it
   ThreadContext *getContext(int tn) { return threadContexts[tn]; }

  public:
    struct Params
    {
        std::string name;
        int numberOfThreads;
        bool deferRegistration;
        Counter max_insts_any_thread;
        Counter max_insts_all_threads;
        Counter max_loads_any_thread;
        Counter max_loads_all_threads;
        Tick clock;
        bool functionTrace;
        Tick functionTraceStart;
        System *system;
        int cpu_id;
        Trace::InstTracer * tracer;

        Tick phase;
#if FULL_SYSTEM
        Tick profile;

        bool do_statistics_insts;
        bool do_checkpoint_insts;
        bool do_quiesce;
#endif
        Tick progress_interval;
        BaseCPU *checker;

        TheISA::CoreSpecific coreParams; //ISA-Specific Params That Set Up State in Core

        Params();
    };

    const Params *params;

    BaseCPU(Params *params);
    virtual ~BaseCPU();

    virtual void init();
    virtual void startup();
    virtual void regStats();

    virtual void activateWhenReady(int tid) {};

    void registerThreadContexts();

    /// Prepare for another CPU to take over execution.  When it is
    /// is ready (drained pipe) it signals the sampler.
    virtual void switchOut();

    /// Take over execution from the given CPU.  Used for warm-up and
    /// sampling.
    virtual void takeOverFrom(BaseCPU *, Port *ic, Port *dc);

    /**
     *  Number of threads we're actually simulating (<= SMT_MAX_THREADS).
     * This is a constant for the duration of the simulation.
     */
    int number_of_threads;

    /**
     * Vector of per-thread instruction-based event queues.  Used for
     * scheduling events based on number of instructions committed by
     * a particular thread.
     */
    EventQueue **comInstEventQueue;

    /**
     * Vector of per-thread load-based event queues.  Used for
     * scheduling events based on number of loads committed by
     *a particular thread.
     */
    EventQueue **comLoadEventQueue;

    System *system;

    Tick phase;

#if FULL_SYSTEM
    /**
     * Serialize this object to the given output stream.
     * @param os The stream to serialize to.
     */
    virtual void serialize(std::ostream &os);

    /**
     * Reconstruct the state of this object from a checkpoint.
     * @param cp The checkpoint use.
     * @param section The section name of this object
     */
    virtual void unserialize(Checkpoint *cp, const std::string &section);

#endif

    /**
     * Return pointer to CPU's branch predictor (NULL if none).
     * @return Branch predictor pointer.
     */
    virtual BranchPred *getBranchPred() { return NULL; };

    virtual Counter totalInstructions() const { return 0; }

    // Function tracing
  private:
    bool functionTracingEnabled;
    std::ostream *functionTraceStream;
    Addr currentFunctionStart;
    Addr currentFunctionEnd;
    Tick functionEntryTick;
    void enableFunctionTrace();
    void traceFunctionsInternal(Addr pc);

  protected:
    void traceFunctions(Addr pc)
    {
        if (functionTracingEnabled)
            traceFunctionsInternal(pc);
    }

  private:
    static std::vector<BaseCPU *> cpuList;   //!< Static global cpu list

  public:
    static int numSimulatedCPUs() { return cpuList.size(); }
    static Counter numSimulatedInstructions()
    {
        Counter total = 0;

        int size = cpuList.size();
        for (int i = 0; i < size; ++i)
            total += cpuList[i]->totalInstructions();

        return total;
    }

  public:
    // Number of CPU cycles simulated
    Stats::Scalar<> numCycles;
};

#endif // __CPU_BASE_HH__
<|endoftext|>