<commit_before>#include "HalideRuntime.h"
#include "runtime_internal.h"

extern "C" {

WEAK __attribute__((always_inline)) int halide_profiler_set_current_func(halide_profiler_state *state, int tok, int t) {
    __sync_synchronize();
    state->current_func = tok + t;
    __sync_synchronize();
    return 0;
}

}
<commit_msg>Use a volatile store instead of a memory barrier<commit_after>#include "HalideRuntime.h"
#include "runtime_internal.h"

extern "C" {

WEAK __attribute__((always_inline)) int halide_profiler_set_current_func(halide_profiler_state *state, int tok, int t) {
    // Do a volatile store to discourage llvm from reordering it.
    volatile int *ptr = &(state->current_func);
    *ptr = tok + t;
    return 0;
}

}
<|endoftext|>


<commit_before><commit_msg>tdf#92213 - avoid potential crasher from unusual idle handler.<commit_after><|endoftext|>


<commit_before>#include "moderationpage.hpp"

#include "application.hpp"
#include "singletons/loggingmanager.hpp"
#include "controllers/taggedusers/taggeduserscontroller.hpp"
#include "controllers/taggedusers/taggedusersmodel.hpp"
#include "singletons/pathmanager.hpp"
#include "util/layoutcreator.hpp"
#include "widgets/helper/editablemodelview.hpp"

#include <QFormLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QListView>
#include <QPushButton>
#include <QTableView>
#include <QTextEdit>
#include <QVBoxLayout>

namespace chatterino {
namespace widgets {
namespace settingspages {

inline QString CreateLink(const QString &url, bool file = false)
{
    if (file) {
        return QString("" + url +
                       "");
    }

    return QString("" + url + "");
}

ModerationPage::ModerationPage()
    : SettingsPage("Moderation", "")
{
    auto app = getApp();
    util::LayoutCreator<ModerationPage> layoutCreator(this);

    auto tabs = layoutCreator.emplace<QTabWidget>();

    auto logs = tabs.appendTab(new QVBoxLayout, "Logs");
    {
        // Logs (copied from LoggingMananger)

        auto created = logs.emplace<QLabel>();
        if (app->settings->logPath == "") {
            created->setText("Logs are saved to " +
                             CreateLink(QCoreApplication::applicationDirPath(), true));
        } else {
            created->setText("Logs are saved to " + CreateLink(app->settings->logPath, true));
        }
        created->setTextFormat(Qt::RichText);
        created->setTextInteractionFlags(Qt::TextBrowserInteraction |
                                         Qt::LinksAccessibleByKeyboard |
                                         Qt::LinksAccessibleByKeyboard);
        created->setOpenExternalLinks(true);
        logs.append(this->createCheckBox("Enable logging", app->settings->enableLogging));

<
        logs->addStretch(1);

        auto selectDir = layout.emplace<QPushButton>("Set custom logpath");

        // Setting custom logpath
        QObject::connect(selectDir.getElement(), &QPushButton::clicked, this, [
            this, created, app, dirMemory = QString{app->settings->logPath}
        ]() mutable {
            auto dirName = QFileDialog::getExistingDirectory(this);
            created->setText("Logs are saved to " + CreateLink(dirName, true));

            if (dirName == "" && dirMemory == "") {
                created->setText(
                    "Logs are saved to " +
                    CreateLink(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation),
                               true));
            } else if (dirName == "") {
                dirName = dirMemory;
                created->setText("Logs are saved to " + CreateLink(dirName, true));
            }

            app->settings->logPath = dirName;
            dirMemory = dirName;
            app->logging->refreshLoggingPath();

        });
        // Reset custom logpath
        auto resetDir = layout.emplace<QPushButton>("Reset logpath");
        QObject::connect(
            resetDir.getElement(), &QPushButton::clicked, this, [this, created, app]() mutable {
                app->settings->logPath = "";
                created->setText(
                    "Logs are saved to " +
                    CreateLink(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation),
                               true));
                app->logging->refreshLoggingPath();
            });

        // Logs end
    }

    auto modMode = tabs.appendTab(new QVBoxLayout, "Moderation mode");
    {
        // clang-format off
        auto label = modMode.emplace<QLabel>("Click the moderation mod button () in a channel that you moderate to enable moderator mode.
");
        label->setWordWrap(true);
        label->setStyleSheet("color: #bbb");
        // clang-format on

        //        auto form = modMode.emplace<QFormLayout>();
        //        {
        //            form->addRow("Action on timed out messages (unimplemented):",
        //                         this->createComboBox({"Disable", "Hide"},
        //                         app->settings->timeoutAction));
        //        }

        auto modButtons =
            modMode.emplace<QGroupBox>("Custom moderator buttons").setLayoutType<QVBoxLayout>();
        {
            auto label2 =
                modButtons.emplace<QLabel>("One action per line. {user} will be replaced with the "
                                           "username.
Example `/timeout {user} 120`
");
            label2->setWordWrap(true);

            auto text = modButtons.emplace<QTextEdit>().getElement();

            text->setPlainText(app->settings->moderationActions);

            QObject::connect(text, &QTextEdit::textChanged, this,
                             [this] { this->itemsChangedTimer.start(200); });

            QObject::connect(&this->itemsChangedTimer, &QTimer::timeout, this, [text, app]() {
                app->settings->moderationActions = text->toPlainText();
            });
        }

        /*auto taggedUsers = tabs.appendTab(new QVBoxLayout, "Tagged users");
        {
            helper::EditableModelView *view = *taggedUsers.emplace<helper::EditableModelView>(
                app->taggedUsers->createModel(nullptr));

            view->setTitles({"Name"});
            view->getTableView()->horizontalHeader()->setStretchLastSection(true);

            view->addButtonPressed.connect([] {
                getApp()->taggedUsers->users.appendItem(
                    controllers::taggedusers::TaggedUser(ProviderId::Twitch, "example", "xD"));
            });
        }*/
    }

    // ---- misc
    this->itemsChangedTimer.setSingleShot(true);
}

}  // namespace settingspages
}  // namespace widgets
}  // namespace chatterino
<commit_msg>Fix some compilation errors caused by an incorrect merge<commit_after>#include "moderationpage.hpp"

#include "application.hpp"
#include "controllers/taggedusers/taggeduserscontroller.hpp"
#include "controllers/taggedusers/taggedusersmodel.hpp"
#include "singletons/loggingmanager.hpp"
#include "singletons/pathmanager.hpp"
#include "util/layoutcreator.hpp"
#include "widgets/helper/editablemodelview.hpp"

#include <QFormLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QListView>
#include <QPushButton>
#include <QTableView>
#include <QTextEdit>
#include <QVBoxLayout>

namespace chatterino {
namespace widgets {
namespace settingspages {

inline QString CreateLink(const QString &url, bool file = false)
{
    if (file) {
        return QString("" + url +
                       "");
    }

    return QString("" + url + "");
}

ModerationPage::ModerationPage()
    : SettingsPage("Moderation", "")
{
    auto app = getApp();
    util::LayoutCreator<ModerationPage> layoutCreator(this);

    auto tabs = layoutCreator.emplace<QTabWidget>();

    auto logs = tabs.appendTab(new QVBoxLayout, "Logs");
    {
        // Logs (copied from LoggingMananger)

        auto created = logs.emplace<QLabel>();
        if (app->settings->logPath == "") {
            created->setText("Logs are saved to " +
                             CreateLink(QCoreApplication::applicationDirPath(), true));
        } else {
            created->setText("Logs are saved to " + CreateLink(app->settings->logPath, true));
        }
        created->setTextFormat(Qt::RichText);
        created->setTextInteractionFlags(Qt::TextBrowserInteraction |
                                         Qt::LinksAccessibleByKeyboard |
                                         Qt::LinksAccessibleByKeyboard);
        created->setOpenExternalLinks(true);
        logs.append(this->createCheckBox("Enable logging", app->settings->enableLogging));

        logs->addStretch(1);

        auto selectDir = logs.emplace<QPushButton>("Set custom logpath");

        // Setting custom logpath
        QObject::connect(
            selectDir.getElement(), &QPushButton::clicked, this,
            [this, created, app, dirMemory = QString{app->settings->logPath}]() mutable {
                auto dirName = QFileDialog::getExistingDirectory(this);
                created->setText("Logs are saved to " + CreateLink(dirName, true));

                if (dirName == "" && dirMemory == "") {
                    created->setText("Logs are saved to " +
                                     CreateLink(QStandardPaths::writableLocation(
                                                    QStandardPaths::AppDataLocation),
                                                true));
                } else if (dirName == "") {
                    dirName = dirMemory;
                    created->setText("Logs are saved to " + CreateLink(dirName, true));
                }

                app->settings->logPath = dirName;
                dirMemory = dirName;
                app->logging->refreshLoggingPath();
            });
        // Reset custom logpath
        auto resetDir = logs.emplace<QPushButton>("Reset logpath");
        QObject::connect(
            resetDir.getElement(), &QPushButton::clicked, this, [this, created, app]() mutable {
                app->settings->logPath = "";
                created->setText(
                    "Logs are saved to " +
                    CreateLink(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation),
                               true));
                app->logging->refreshLoggingPath();
            });

        // Logs end
    }

    auto modMode = tabs.appendTab(new QVBoxLayout, "Moderation mode");
    {
        // clang-format off
        auto label = modMode.emplace<QLabel>("Click the moderation mod button () in a channel that you moderate to enable moderator mode.
");
        label->setWordWrap(true);
        label->setStyleSheet("color: #bbb");
        // clang-format on

        //        auto form = modMode.emplace<QFormLayout>();
        //        {
        //            form->addRow("Action on timed out messages (unimplemented):",
        //                         this->createComboBox({"Disable", "Hide"},
        //                         app->settings->timeoutAction));
        //        }

        auto modButtons =
            modMode.emplace<QGroupBox>("Custom moderator buttons").setLayoutType<QVBoxLayout>();
        {
            auto label2 =
                modButtons.emplace<QLabel>("One action per line. {user} will be replaced with the "
                                           "username.
Example `/timeout {user} 120`
");
            label2->setWordWrap(true);

            auto text = modButtons.emplace<QTextEdit>().getElement();

            text->setPlainText(app->settings->moderationActions);

            QObject::connect(text, &QTextEdit::textChanged, this,
                             [this] { this->itemsChangedTimer.start(200); });

            QObject::connect(&this->itemsChangedTimer, &QTimer::timeout, this, [text, app]() {
                app->settings->moderationActions = text->toPlainText();
            });
        }

        /*auto taggedUsers = tabs.appendTab(new QVBoxLayout, "Tagged users");
        {
            helper::EditableModelView *view = *taggedUsers.emplace<helper::EditableModelView>(
                app->taggedUsers->createModel(nullptr));

            view->setTitles({"Name"});
            view->getTableView()->horizontalHeader()->setStretchLastSection(true);

            view->addButtonPressed.connect([] {
                getApp()->taggedUsers->users.appendItem(
                    controllers::taggedusers::TaggedUser(ProviderId::Twitch, "example", "xD"));
            });
        }*/
    }

    // ---- misc
    this->itemsChangedTimer.setSingleShot(true);
}

}  // namespace settingspages
}  // namespace widgets
}  // namespace chatterino
<|endoftext|>


<commit_before><commit_msg>Use officecfg/Office/Common.hxx directly.<commit_after><|endoftext|>


<commit_before>#ifndef FORMAST_HPP_INCLUDED
#define FORMAST_HPP_INCLUDED

#ifdef FORMAST_STATIC
// formast static library
#  define FORMAST_API
#  define FORMAST_HIDDEN
#else
// formast shared library
#  if defined _WIN32 || defined __CYGWIN__
// Windows
#    ifdef formastlib_EXPORTS
// formast is being compiled: export API to dll
#      define FORMAST_API __declspec(dllexport)
#    else
// other code is being compiled, using formast.dll: import API from dll
#      define FORMAST_API __declspec(dllimport)
#    endif
#    define FORMAST_HIDDEN
#  elif __GNUC__ >= 4
// GNU Linux: set visibility of symbols
#    define FORMAST_API    __attribute__ ((visibility ("default")))
#    define FORMAST_HIDDEN __attribute__ ((visibility ("hidden")))
#  else
// unknown
#    define FORMAST_API
#    define FORMAST_HIDDEN
#  endif
#endif

#include <boost/cstdint.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
#include <vector>

#include "formast/detail/ast.hpp"

namespace formast
{

class Top
{
public:
    FORMAST_API Top();
private:
    // pimpl idiom
    FORMAST_HIDDEN class Impl;
    boost::shared_ptr<Impl> _impl;
    friend class Visitor;
    friend class XmlParser;
};

class Stats
{
public:
    FORMAST_API Stats();
private:
    // pimpl idiom
    FORMAST_HIDDEN class Impl;
    boost::shared_ptr<Impl> _impl;
    friend class Visitor;
    friend class XmlParser;
};

typedef formast::detail::ast::Expr Expr;

typedef std::string Doc;

struct Attr {
    std::string class_name;
    std::string name;
    boost::optional<Doc> doc;
    boost::optional<Expr> arr1;
    boost::optional<Expr> arr2;
};

class Class
{
public:
    std::string name;
    boost::optional<std::string> base_name;
    boost::optional<Doc> doc;
    boost::optional<Stats> stats;
};

struct If {
    Expr expr;
    Stats then;
    boost::optional<Stats> else_;
};

class Parser
{
public:
    FORMAST_API Parser();
    FORMAST_API virtual ~Parser();
    FORMAST_API virtual void parse_stream(std::istream & is, Top & top) = 0;
    FORMAST_API void parse_string(std::string const & s, Top & top);
};

class XmlParser : public Parser
{
public:
    FORMAST_API XmlParser();
    FORMAST_API virtual void parse_stream(std::istream & is, Top & top);
};

class Visitor
{
public:
    FORMAST_API Visitor();
    FORMAST_API virtual ~Visitor();

    FORMAST_API virtual void top(Top const & top);
    FORMAST_API virtual void top_class(Class const & class_);

    FORMAST_API virtual void stats(Stats const & stats);
    FORMAST_API virtual void stats_attr(Attr const & attr);
    FORMAST_API virtual void stats_if(If const & if_);

    FORMAST_API virtual void expr(Expr const & e);
    FORMAST_API virtual void expr_uint(boost::uint64_t const & n);
    FORMAST_API virtual void expr_id(std::string const & i);
    FORMAST_API virtual void expr_pos(Expr const & right);
    FORMAST_API virtual void expr_neg(Expr const & right);
    FORMAST_API virtual void expr_add(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_sub(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_mul(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_div(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_mod(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_pow(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_logical_and(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_logical_or(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_logical_not(Expr const & right);
    FORMAST_API virtual void expr_bitwise_and(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_bitwise_or(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_bitwise_xor(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_compare_eq(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_compare_ne(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_compare_gt(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_compare_lt(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_compare_ge(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_compare_le(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_shift_left(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_shift_right(Expr const & left, Expr const & right);
private:
    // pimpl idiom
    FORMAST_HIDDEN class ExprVisitor;
    boost::shared_ptr<ExprVisitor> _expr_visitor;
    FORMAST_HIDDEN class TopVisitor;
    boost::shared_ptr<TopVisitor> _top_visitor;
    FORMAST_HIDDEN class StatsVisitor;
    boost::shared_ptr<StatsVisitor> _stats_visitor;
};

} // namespace formast

#endif
<commit_msg>Declare Attr and If as class, for consistency.<commit_after>#ifndef FORMAST_HPP_INCLUDED
#define FORMAST_HPP_INCLUDED

#ifdef FORMAST_STATIC
// formast static library
#  define FORMAST_API
#  define FORMAST_HIDDEN
#else
// formast shared library
#  if defined _WIN32 || defined __CYGWIN__
// Windows
#    ifdef formastlib_EXPORTS
// formast is being compiled: export API to dll
#      define FORMAST_API __declspec(dllexport)
#    else
// other code is being compiled, using formast.dll: import API from dll
#      define FORMAST_API __declspec(dllimport)
#    endif
#    define FORMAST_HIDDEN
#  elif __GNUC__ >= 4
// GNU Linux: set visibility of symbols
#    define FORMAST_API    __attribute__ ((visibility ("default")))
#    define FORMAST_HIDDEN __attribute__ ((visibility ("hidden")))
#  else
// unknown
#    define FORMAST_API
#    define FORMAST_HIDDEN
#  endif
#endif

#include <boost/cstdint.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
#include <vector>

#include "formast/detail/ast.hpp"

namespace formast
{

class Top
{
public:
    FORMAST_API Top();
private:
    // pimpl idiom
    FORMAST_HIDDEN class Impl;
    boost::shared_ptr<Impl> _impl;
    friend class Visitor;
    friend class XmlParser;
};

class Stats
{
public:
    FORMAST_API Stats();
private:
    // pimpl idiom
    FORMAST_HIDDEN class Impl;
    boost::shared_ptr<Impl> _impl;
    friend class Visitor;
    friend class XmlParser;
};

typedef formast::detail::ast::Expr Expr;

typedef std::string Doc;

class Attr
{
public:
    std::string class_name;
    std::string name;
    boost::optional<Doc> doc;
    boost::optional<Expr> arr1;
    boost::optional<Expr> arr2;
};

class Class
{
public:
    std::string name;
    boost::optional<std::string> base_name;
    boost::optional<Doc> doc;
    boost::optional<Stats> stats;
};

class If
{
public:
    Expr expr;
    Stats then;
    boost::optional<Stats> else_;
};

class Parser
{
public:
    FORMAST_API Parser();
    FORMAST_API virtual ~Parser();
    FORMAST_API virtual void parse_stream(std::istream & is, Top & top) = 0;
    FORMAST_API void parse_string(std::string const & s, Top & top);
};

class XmlParser : public Parser
{
public:
    FORMAST_API XmlParser();
    FORMAST_API virtual void parse_stream(std::istream & is, Top & top);
};

class Visitor
{
public:
    FORMAST_API Visitor();
    FORMAST_API virtual ~Visitor();

    FORMAST_API virtual void top(Top const & top);
    FORMAST_API virtual void top_class(Class const & class_);

    FORMAST_API virtual void stats(Stats const & stats);
    FORMAST_API virtual void stats_attr(Attr const & attr);
    FORMAST_API virtual void stats_if(If const & if_);

    FORMAST_API virtual void expr(Expr const & e);
    FORMAST_API virtual void expr_uint(boost::uint64_t const & n);
    FORMAST_API virtual void expr_id(std::string const & i);
    FORMAST_API virtual void expr_pos(Expr const & right);
    FORMAST_API virtual void expr_neg(Expr const & right);
    FORMAST_API virtual void expr_add(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_sub(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_mul(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_div(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_mod(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_pow(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_logical_and(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_logical_or(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_logical_not(Expr const & right);
    FORMAST_API virtual void expr_bitwise_and(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_bitwise_or(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_bitwise_xor(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_compare_eq(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_compare_ne(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_compare_gt(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_compare_lt(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_compare_ge(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_compare_le(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_shift_left(Expr const & left, Expr const & right);
    FORMAST_API virtual void expr_shift_right(Expr const & left, Expr const & right);
private:
    // pimpl idiom
    FORMAST_HIDDEN class ExprVisitor;
    boost::shared_ptr<ExprVisitor> _expr_visitor;
    FORMAST_HIDDEN class TopVisitor;
    boost::shared_ptr<TopVisitor> _top_visitor;
    FORMAST_HIDDEN class StatsVisitor;
    boost::shared_ptr<StatsVisitor> _stats_visitor;
};

} // namespace formast

#endif
<|endoftext|>


<commit_before>#include "util/bitmap.h"
#include "object/object.h"
#include "util/load_exception.h"
#include "util/funcs.h"
#include "object/player.h"
#include "object/display_character.h"
#include "init.h"
#include "select_player.h"
#include "factory/font_factory.h"
#include "util/font.h"
#include "world.h"
#include "return_exception.h"
#include <iostream>
#include <vector>
#include <map>

using namespace std;

typedef map<DisplayCharacter*,string> PlayerMap;
static PlayerMap loadPlayers( const char * path ){
	PlayerMap players;
	vector< string > files = Util::getFiles( Util::getDataPath() + "/" + path, "*" );
	for ( vector< string >::iterator it = files.begin(); it != files.end(); it++ ){
		string file = (*it) + "/" + (*it).substr( (*it).find_last_of( '/' ) + 1 ) + ".txt";
		cout << "Checking " << file << endl;
		if ( Util::exists( file ) ){
			cout << "Loading " << file << endl;
			try{
				players[ new DisplayCharacter( file ) ] = file;
			} catch ( const LoadException & le ){
				cout << "Could not load " << file << " because " << le.getReason() << endl;
			}
		}
	}
	return players;
}

template< class Key, class Value >
Key getNth( const map< Key, Value > & m, int i ){
	int count = 0;
	for ( typename map<Key, Value>::const_iterator it = m.begin(); it != m.end(); it++ ){
		if ( count == i ){
			return it->first;
		}
		count += 1;
	}
	return m.begin()->first;
}

Object * selectPlayer( bool invincibile ) throw( LoadException, ReturnException ){
	Bitmap background( Util::getDataPath() + "/paintown-title.png" );

	/* hm, it would be nice to cache this I suppose */
	PlayerMap players = loadPlayers( "players/" );

	Keyboard key;

	// Bitmap work( GFX_X / 2, GFX_Y / 2 );
	Bitmap work( GFX_X, GFX_Y );

	/* currently selected character */
	int current = 0;

	int changeRemapKey = Keyboard::Key_TAB;

	key.setDelay( Keyboard::Key_RIGHT, 300 );
	key.setDelay( Keyboard::Key_UP, 300 );
	key.setDelay( Keyboard::Key_DOWN, 300 );
	key.setDelay( Keyboard::Key_LEFT, 300 );
	key.setDelay( changeRemapKey, 200 );

	/* preview box for each character */
	Bitmap temp( 120, 120 );
	Bitmap preview( GFX_X / 2, GFX_Y / 2 );

	const int unselectedColor = Bitmap::makeColor( 255, 0, 0 );
	const int selectedColor = Bitmap::makeColor( 0, 255, 0 );

	Global::speed_counter = 0;

	const int boxSize = 80;
	const int startX = 300;
	const int startY = 20;
	const int boxesPerLine = (work.getWidth() - startX) / (boxSize + 10);
	const int boxesPerColumn = (work.getHeight() - startY) / (boxSize + 10);
	int backgroundX = 0;
	int top = 0;

	const int maxGradient = 50;
	int gradient[ maxGradient ];
	/* fade from yellow to some reddish color */
	Util::blend_palette( gradient, 25, Bitmap::makeColor( 255, 255, 0 ), Bitmap::makeColor( 0xff, 0x33, 0x11 ) );
	Util::blend_palette( gradient + 25, 25, Bitmap::makeColor( 0xff, 0x33, 0x11 ), Bitmap::makeColor( 255, 255, 0 ) );

	bool draw = true;
	unsigned int clock = 0;
	while ( ! key[ Keyboard::Key_ENTER ] && ! key[ Keyboard::Key_SPACE ] ){
		key.poll();

		Character * ch = (Character *) getNth<DisplayCharacter*,string>( players, current );

		if ( Global::speed_counter > 0 ){
			double think = Global::speed_counter;
			while ( think > 0 ){
				clock += 1;

				if ( clock % 5 == 0 ){
					backgroundX -= 1;
					if ( backgroundX < - work.getWidth() ){
						backgroundX = 0;
					}
				}

				if ( key[ Keyboard::Key_LEFT ] ){
					current = current - 1;
				}

				if ( key[ Keyboard::Key_RIGHT ] ){
					current = current + 1;
				}

				if ( key[ Keyboard::Key_UP ] ){
					current = current - boxesPerLine;
				}

				if ( key[ Keyboard::Key_DOWN ] ){
					current = current + boxesPerLine;
				}

				if ( key[ changeRemapKey ] ){
					ch->nextMap();
				}

				if ( key[ Keyboard::Key_ESC ] ){
					for ( PlayerMap::iterator it = players.begin(); it != players.end(); it++ ){
						Object * o = it->first;
						delete o;
					}
					throw ReturnException();
				}

				if ( current < 0 ){
					current = 0;
				}

				if ( current >= (signed) players.size() ){
					current = players.size() - 1;
				}

				if ( ch->testAnimation() ){
					ch->testReset();
				}

				while ( current < top ){
					top -= boxesPerLine;
				}

				while ( current >= top + boxesPerLine * boxesPerColumn ){
					top += boxesPerLine;
				}

				think--;
			}

			Global::speed_counter = 0;
			draw = true;
		}

		if ( draw ){

			// background.Stretch( work );
			background.Blit( backgroundX, 0, work );
			background.Blit( work.getWidth() + backgroundX, 0, work );

			ch->setFacing( Object::FACING_RIGHT );
			Character copy( *ch );
			copy.setX( preview.getWidth() / 2 );
			copy.setY( 0 );
			copy.setZ( preview.getHeight() - 20 );
			preview.fill( Bitmap::MaskColor );

			copy.draw( &preview, 0 );
			preview.drawStretched( -GFX_X / 2 + startX / 2, 0, GFX_X, GFX_Y, work );
			const Font & font = Font::getFont( Util::getDataPath() + "/fonts/arial.ttf" );
			font.printf( 10, 10, Bitmap::makeColor( 255, 255, 255 ), work, copy.getName(), 0 );

			int x = startX, y = startY;
			unsigned int i;
			for ( i = top; i < players.size() && y + boxSize < GFX_Y; i++ ){
				temp.clear();
				Bitmap box( work, x, y, boxSize, boxSize );
				int color = unselectedColor;
				Character smaller( *getNth<DisplayCharacter*,string>( players, i ) );

				color = i == (unsigned int) current ? selectedColor : unselectedColor;
				/* draw a border */
				box.border( 0, 3, color );

				smaller.setX( temp.getWidth() / 2 );
				smaller.setY( 0 );
				smaller.setZ( temp.getHeight() );
				smaller.draw( &temp, 0 );
				temp.drawStretched( 0, 0, box.getWidth(), box.getHeight(), box );
				box.border( 0, 3, color );
				x += boxSize + 10;
				if ( x + boxSize + 10 > work.getWidth() ){
					x = startX;
					y += (boxSize + 10);
				}
			}

			if ( top > 0 ){
				int x1 = 80;
				int x2 = 140;
				work.triangle( startX + x1, 8, startX + x2, 8, startX + (x1 + x2) / 2, 3, gradient[ clock % maxGradient ] );
			}

			if ( i < players.size() ){
				int x1 = 80;
				int x2 = 140;
				work.triangle( startX + x1, GFX_Y - 8, startX + x2, GFX_Y - 8, startX + (x1 + x2) / 2, GFX_Y - 3, gradient[ clock % maxGradient ] );
			}

			work.Blit( *Bitmap::Screen );
			draw = false;
		}

		while ( Global::speed_counter == 0 ){
			key.poll();
			Util::rest( 1 );
		}
	}

	/* delete all the preview characters. its ok to delete them
	 * before looking up the selected player in the map
	 * because 'delete' doesn't affect the map, it just changes
	 * memory around.
	 */
	for ( PlayerMap::iterator it = players.begin(); it != players.end(); it++ ){
		Object * o = it->first;
		delete o;
	}

	Player * player = new Player( players[ getNth<DisplayCharacter*,string>( players, current ) ] );
	player->setInvincible( invincibile );
	return player;
}
<commit_msg>sort players by their path<commit_after>#include "util/bitmap.h"
#include "object/object.h"
#include "util/load_exception.h"
#include "util/funcs.h"
#include "object/player.h"
#include "object/display_character.h"
#include "init.h"
#include "select_player.h"
#include "factory/font_factory.h"
#include "util/font.h"
#include "world.h"
#include "return_exception.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>

using namespace std;

struct playerInfo{
	Character * guy;
	string path;
	playerInfo( Character * guy, string path ):
		guy( guy ),
		path( path ){
	}
};

typedef vector<playerInfo> PlayerVector;
static PlayerVector loadPlayers( const char * path ){
	PlayerVector players;
	vector< string > files = Util::getFiles( Util::getDataPath() + "/" + path, "*" );
	std::sort( files.begin(), files.end() );
	for ( vector< string >::iterator it = files.begin(); it != files.end(); it++ ){
		string file = (*it) + "/" + (*it).substr( (*it).find_last_of( '/' ) + 1 ) + ".txt";
		cout << "Checking " << file << endl;
		if ( Util::exists( file ) ){
			cout << "Loading " << file << endl;
			try{
				players.push_back( playerInfo( new DisplayCharacter( file ), file ) );
			} catch ( const LoadException & le ){
				cout << "Could not load " << file << " because " << le.getReason() << endl;
			}
		}
	}
	return players;
}

/*
template< class Key, class Value >
Key getNth( const map< Key, Value > & m, int i ){
	int count = 0;
	for ( typename map<Key, Value>::const_iterator it = m.begin(); it != m.end(); it++ ){
		if ( count == i ){
			return it->first;
		}
		count += 1;
	}
	return m.begin()->first;
}
*/

Object * selectPlayer( bool invincibile ) throw( LoadException, ReturnException ){
	Bitmap background( Util::getDataPath() + "/paintown-title.png" );

	/* hm, it would be nice to cache this I suppose */
	PlayerVector players = loadPlayers( "players/" );

	Keyboard key;

	// Bitmap work( GFX_X / 2, GFX_Y / 2 );
	Bitmap work( GFX_X, GFX_Y );

	/* currently selected character */
	int current = 0;

	int changeRemapKey = Keyboard::Key_TAB;

	key.setDelay( Keyboard::Key_RIGHT, 300 );
	key.setDelay( Keyboard::Key_UP, 300 );
	key.setDelay( Keyboard::Key_DOWN, 300 );
	key.setDelay( Keyboard::Key_LEFT, 300 );
	key.setDelay( changeRemapKey, 200 );

	/* preview box for each character */
	Bitmap temp( 120, 120 );
	Bitmap preview( GFX_X / 2, GFX_Y / 2 );

	const int unselectedColor = Bitmap::makeColor( 255, 0, 0 );
	const int selectedColor = Bitmap::makeColor( 0, 255, 0 );

	Global::speed_counter = 0;

	const int boxSize = 80;
	const int startX = 300;
	const int startY = 20;
	const int boxesPerLine = (work.getWidth() - startX) / (boxSize + 10);
	const int boxesPerColumn = (work.getHeight() - startY) / (boxSize + 10);
	int backgroundX = 0;
	int top = 0;

	const int maxGradient = 50;
	int gradient[ maxGradient ];
	/* fade from yellow to some reddish color */
	Util::blend_palette( gradient, 25, Bitmap::makeColor( 255, 255, 0 ), Bitmap::makeColor( 0xff, 0x33, 0x11 ) );
	Util::blend_palette( gradient + 25, 25, Bitmap::makeColor( 0xff, 0x33, 0x11 ), Bitmap::makeColor( 255, 255, 0 ) );

	bool draw = true;
	unsigned int clock = 0;
	while ( ! key[ Keyboard::Key_ENTER ] && ! key[ Keyboard::Key_SPACE ] ){
		key.poll();

		Character * ch = (Character *) players[ current ].guy;

		if ( Global::speed_counter > 0 ){
			double think = Global::speed_counter;
			while ( think > 0 ){
				clock += 1;

				if ( clock % 5 == 0 ){
					backgroundX -= 1;
					if ( backgroundX < - work.getWidth() ){
						backgroundX = 0;
					}
				}

				if ( key[ Keyboard::Key_LEFT ] ){
					current = current - 1;
				}

				if ( key[ Keyboard::Key_RIGHT ] ){
					current = current + 1;
				}

				if ( key[ Keyboard::Key_UP ] ){
					current = current - boxesPerLine;
				}

				if ( key[ Keyboard::Key_DOWN ] ){
					current = current + boxesPerLine;
				}

				if ( key[ changeRemapKey ] ){
					ch->nextMap();
				}

				if ( key[ Keyboard::Key_ESC ] ){
					for ( PlayerVector::iterator it = players.begin(); it != players.end(); it++ ){
						delete it->guy;
					}
					throw ReturnException();
				}

				if ( current < 0 ){
					current = 0;
				}

				if ( current >= (signed) players.size() ){
					current = players.size() - 1;
				}

				if ( ch->testAnimation() ){
					ch->testReset();
				}

				while ( current < top ){
					top -= boxesPerLine;
				}

				while ( current >= top + boxesPerLine * boxesPerColumn ){
					top += boxesPerLine;
				}

				think--;
			}

			Global::speed_counter = 0;
			draw = true;
		}

		if ( draw ){

			// background.Stretch( work );
			background.Blit( backgroundX, 0, work );
			background.Blit( work.getWidth() + backgroundX, 0, work );

			ch->setFacing( Object::FACING_RIGHT );
			Character copy( *ch );
			copy.setX( preview.getWidth() / 2 );
			copy.setY( 0 );
			copy.setZ( preview.getHeight() - 20 );
			preview.fill( Bitmap::MaskColor );

			copy.draw( &preview, 0 );
			preview.drawStretched( -GFX_X / 2 + startX / 2, 0, GFX_X, GFX_Y, work );
			const Font & font = Font::getFont( Util::getDataPath() + "/fonts/arial.ttf" );
			font.printf( 10, 10, Bitmap::makeColor( 255, 255, 255 ), work, copy.getName(), 0 );

			int x = startX, y = startY;
			unsigned int i;
			for ( i = top; i < players.size() && y + boxSize < GFX_Y; i++ ){
				temp.clear();
				Bitmap box( work, x, y, boxSize, boxSize );
				int color = unselectedColor;
				Character smaller( *players[ i ].guy );

				color = i == (unsigned int) current ? selectedColor : unselectedColor;
				/* draw a border */
				box.border( 0, 3, color );

				smaller.setX( temp.getWidth() / 2 );
				smaller.setY( 0 );
				smaller.setZ( temp.getHeight() );
				smaller.draw( &temp, 0 );
				temp.drawStretched( 0, 0, box.getWidth(), box.getHeight(), box );
				box.border( 0, 3, color );
				x += boxSize + 10;
				if ( x + boxSize + 10 > work.getWidth() ){
					x = startX;
					y += (boxSize + 10);
				}
			}

			if ( top > 0 ){
				int x1 = 80;
				int x2 = 140;
				work.triangle( startX + x1, 8, startX + x2, 8, startX + (x1 + x2) / 2, 3, gradient[ clock % maxGradient ] );
			}

			if ( i < players.size() ){
				int x1 = 80;
				int x2 = 140;
				work.triangle( startX + x1, GFX_Y - 8, startX + x2, GFX_Y - 8, startX + (x1 + x2) / 2, GFX_Y - 3, gradient[ clock % maxGradient ] );
			}

			work.Blit( *Bitmap::Screen );
			draw = false;
		}

		while ( Global::speed_counter == 0 ){
			key.poll();
			Util::rest( 1 );
		}
	}

	/* delete all the preview characters. its ok to delete them
	 * before looking up the selected player in the map
	 * because 'delete' doesn't affect the map, it just changes
	 * memory around.
	 */
	for ( PlayerVector::iterator it = players.begin(); it != players.end(); it++ ){
		delete it->guy;
	}

	Player * player = new Player( players[ current ].path );
	player->setInvincible( invincibile );
	return player;
}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACE_CONTINUOUSLAGRANGE_PDELAB_HH
#define DUNE_GDT_SPACE_CONTINUOUSLAGRANGE_PDELAB_HH

#include <memory>

#include <dune/common/typetraits.hh>
#include <dune/common/fvector.hh>

#include <dune/geometry/genericgeometry/topologytypes.hh>

#include <dune/grid/common/capabilities.hh>

#include <dune/pdelab/finiteelementmap/pkfem.hh>
#include <dune/pdelab/finiteelementmap/qkfem.hh>
#include <dune/pdelab/gridfunctionspace/gridfunctionspace.hh>

#include "../../mapper/pdelab.hh"
#include "../../basefunctionset/pdelab.hh"

#include "../interface.hh"
#include "../constraints.hh"

namespace Dune {
namespace GDT {
namespace ContinuousLagrangeSpace {

// forward, to be used in the traits and to allow for specialization
template <class GridPartImp, int polynomialOrder, class RangeFieldImp, int rangeDim, int rangeDimCols = 1>
class PdelabWrapper;

/**
 *  \brief Traits class for ContinuousLagrangeSpace::PdelabWrapper.
 */
template <class GridPartImp, int polynomialOrder, class RangeFieldImp, int rangeDim, int rangeDimCols = 1>
class PdelabWrapperTraits
{
public:
  typedef PdelabWrapper<GridPartImp, polynomialOrder, RangeFieldImp, rangeDim, rangeDimCols> derived_type;
  typedef GridPartImp GridPartType;
  static const int polOrder = polynomialOrder;
  static_assert(polOrder >= 1, "Wrong polOrder given!");

private:
  typedef typename GridPartType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridPartType::dimension;

public:
  typedef RangeFieldImp RangeFieldType;
  static const unsigned int dimRange     = rangeDim;
  static const unsigned int dimRangeCols = rangeDimCols;

private:
  template <class G, bool single_geom, bool is_simplex, bool is_cube>
  struct Choose
  {
    static_assert(Dune::AlwaysFalse<G>::value,
                  "This space is only implemented for either fully simplicial or fully cubic grids!");
  };
  template <class G>
  struct Choose<G, true, true, false>
  {
    typedef PDELab::PkLocalFiniteElementMap<typename GridPartType::GridViewType, DomainFieldType, RangeFieldType,
                                            polOrder> FEMapType;
  };
  template <class G>
  struct Choose<G, true, false, true>
  {
    typedef PDELab::QkLocalFiniteElementMap<typename GridPartType::GridViewType, DomainFieldType, RangeFieldType,
                                            polOrder> FEMapType;
  };
  typedef typename GridPartType::GridType GridType;
  typedef typename Choose<GridType, Dune::Capabilities::hasSingleGeometryType<GridType>::v,
                          Dune::Capabilities::hasSingleGeometryType<GridType>::topologyId
                              == GenericGeometry::SimplexTopology<dimDomain>::type::id,
                          Dune::Capabilities::hasSingleGeometryType<GridType>::topologyId
                              == GenericGeometry::CubeTopology<dimDomain>::type::id>::FEMapType FEMapType;

public:
  typedef PDELab::GridFunctionSpace<typename GridPartType::GridViewType, FEMapType> BackendType;
  typedef Mapper::PdelabWrapper<BackendType> MapperType;
  typedef typename GridPartType::template Codim<0>::EntityType EntityType;
  typedef BaseFunctionSet::PdelabWrapper<BackendType, EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange,
                                         dimRangeCols> BaseFunctionSetType;

private:
  friend class PdelabWrapper<GridPartImp, polynomialOrder, RangeFieldImp, rangeDim, rangeDimCols>;
}; // class SpaceWrappedFemContinuousLagrangeTraits

// unspecialized version, to give better compile errors
template <class GP, int p, class R, int r, int rC>
class PdelabWrapper : public SpaceInterface<PdelabWrapperTraits<GP, p, R, r, rC>>
{
public:
  typedef PdelabWrapperTraits<GP, p, R, r, rC> Traits;

  typedef typename Traits::GridPartType GridPartType;
  static const int polOrder = Traits::polOrder;
  typedef typename GridPartType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridPartType::dimension;
  typedef typename Traits::RangeFieldType RangeFieldType;
  static const unsigned int dimRange     = Traits::dimRange;
  static const unsigned int dimRangeCols = Traits::dimRangeCols;

  typedef typename Traits::BackendType BackendType;
  typedef typename Traits::MapperType MapperType;
  typedef typename Traits::BaseFunctionSetType BaseFunctionSetType;
  typedef typename Traits::EntityType EntityType;

  typedef Dune::Stuff::LA::SparsityPatternDefault PatternType;

  PdelabWrapper(const std::shared_ptr<const GridPartType>& /*grid_prt*/)
  {
    static_assert((Dune::AlwaysFalse<GP>::value), "Not yet implemented for this combination of dimensions!");
  }
}; // PdelabWrapper

template <class GridPartImp, int polynomialOrder, class RangeFieldImp>
class PdelabWrapper<GridPartImp, polynomialOrder, RangeFieldImp, 1, 1>
    : public SpaceInterface<PdelabWrapperTraits<GridPartImp, polynomialOrder, RangeFieldImp, 1, 1>>
{
  typedef SpaceInterface<PdelabWrapperTraits<GridPartImp, polynomialOrder, RangeFieldImp, 1, 1>> BaseType;
  typedef PdelabWrapper<GridPartImp, polynomialOrder, RangeFieldImp, 1, 1> ThisType;

public:
  typedef PdelabWrapperTraits<GridPartImp, polynomialOrder, RangeFieldImp, 1, 1> Traits;

  typedef typename Traits::GridPartType GridPartType;
  static const int polOrder = Traits::polOrder;
  typedef typename GridPartType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridPartType::dimension;
  typedef FieldVector<DomainFieldType, dimDomain> DomainType;
  typedef typename Traits::RangeFieldType RangeFieldType;
  static const unsigned int dimRange     = Traits::dimRange;
  static const unsigned int dimRangeCols = Traits::dimRangeCols;

  typedef typename Traits::BackendType BackendType;
  typedef typename Traits::MapperType MapperType;
  typedef typename Traits::BaseFunctionSetType BaseFunctionSetType;
  typedef typename Traits::EntityType EntityType;

private:
  typedef typename Traits::FEMapType FEMapType;

public:
  typedef Dune::Stuff::LA::SparsityPatternDefault PatternType;

  PdelabWrapper(const std::shared_ptr<const GridPartType>& gridP)
    : gridPart_(gridP)
    , fe_map_(std::make_shared<FEMapType>(gridPart_->gridView()))
    , backend_(std::make_shared<BackendType>(const_cast<GridPartType&>(*gridPart_).gridView(), *fe_map_))
    , mapper_(std::make_shared<MapperType>(*backend_))
    , tmpMappedRows_(mapper_->maxNumDofs())
    , tmpMappedCols_(mapper_->maxNumDofs())
  {
  }

  PdelabWrapper(const ThisType& other)
    : gridPart_(other.gridPart_)
    , fe_map_(other.fe_map_)
    , backend_(other.backend_)
    , mapper_(other.mapper_)
    , tmpMappedRows_(mapper_->maxNumDofs())
    , tmpMappedCols_(mapper_->maxNumDofs())
  {
  }

  ThisType& operator=(const ThisType& other)
  {
    if (this != &other) {
      gridPart_ = other.gridPart_;
      fe_map_   = other.fe_map_;
      backend_  = other.backend_;
      mapper_ = other.mapper_;
      tmpMappedRows_.resize(mapper_->maxNumDofs());
      tmpMappedCols_.resize(mapper_->maxNumDofs());
    }
    return *this;
  }

  ~PdelabWrapper()
  {
  }

  const std::shared_ptr<const GridPartType>& gridPart() const
  {
    return gridPart_;
  }

  const BackendType& backend() const
  {
    return *backend_;
  }

  bool continuous() const
  {
    return true;
  }

  const MapperType& mapper() const
  {
    return *mapper_;
  }

  BaseFunctionSetType baseFunctionSet(const EntityType& entity) const
  {
    return BaseFunctionSetType(*backend_, entity);
  }

  template <class R>
  void localConstraints(const EntityType& /*entity*/, Constraints::LocalDefault<R>& /*ret*/) const
  {
    static_assert((Dune::AlwaysFalse<R>::value), "Not implemented for arbitrary constraints!");
  }

  void
  localConstraints(const EntityType& /*entity*/,
                   Constraints::Dirichlet<typename GridPartType::IntersectionType, RangeFieldType, true>& /*ret*/) const
  {
    //    std::set< size_t > localDirichletDofs;
    //    const auto& gridBoundary = ret.gridBoundary();
    //    if (polOrder == 1) {
    //      localDirichletDofs = this->findLocalDirichletDoFs(entity, gridBoundary);
    //    } else {
    //      const auto& lagrangePointSet = backend_->lagrangePointSet(entity);
    //      // loop over all intersections
    //      const auto intersectionEndIt = gridPart_->iend(entity);
    //      for (auto intersectionIt = gridPart_->ibegin(entity); intersectionIt !=intersectionEndIt; ++intersectionIt)
    //      {
    //        const auto& intersection = *intersectionIt;
    //        // only work on dirichlet intersections
    //        if (gridBoundary.dirichlet(intersection)) {
    //          // get local face number of boundary intersection
    //          const int intersectionIndex = intersection.indexInInside();
    //          // iterate over face dofs and set unit row
    //          const auto faceDofEndIt = lagrangePointSet.template endSubEntity< 1 >(intersectionIndex);
    //          for (auto faceDofIt = lagrangePointSet.template beginSubEntity< 1 >(intersectionIndex);
    //               faceDofIt != faceDofEndIt;
    //               ++faceDofIt) {
    //            const size_t localDofIndex = *faceDofIt;
    //            localDirichletDofs.insert(localDofIndex);
    //          } // iterate over face dofs and set unit row
    //        } // only work on dirichlet intersections
    //      } // loop over all intersections
    //    }
    //    const size_t numRows = localDirichletDofs.size();
    //    if (numRows > 0) {
    //      const size_t numCols = mapper_->numDofs(entity);
    //      ret.setSize(numRows, numCols);
    //      mapper_->globalIndices(entity, tmpMappedRows_);
    //      mapper_->globalIndices(entity, tmpMappedCols_);
    //      size_t localRow = 0;
    //      const RangeFieldType zero(0);
    //      const RangeFieldType one(1);
    //      for (auto localDirichletDofIt = localDirichletDofs.begin();
    //           localDirichletDofIt != localDirichletDofs.end();
    //           ++localDirichletDofIt) {
    //        const size_t& localDirichletDofIndex = * localDirichletDofIt;
    //        ret.globalRow(localRow) = tmpMappedRows_[localDirichletDofIndex];
    //        for (size_t jj = 0; jj < ret.cols(); ++jj) {
    //          ret.globalCol(jj) = tmpMappedCols_[jj];
    //          if (tmpMappedCols_[jj] == tmpMappedRows_[localDirichletDofIndex])
    //            ret.value(localRow, jj) = one;
    //          else
    //            ret.value(localRow, jj) = zero;
    //        }
    //        ++localRow;
    //      }
    //    } else {
    //      ret.setSize(0, 0);
    //    }
  } // ... localConstraints(..., Dirichlet< ..., true >)

  void localConstraints(
      const EntityType& /*entity*/,
      Constraints::Dirichlet<typename GridPartType::IntersectionType, RangeFieldType, false>& /*ret*/) const
  {
    //    std::set< size_t > localDirichletDofs;
    //    const auto& gridBoundary = ret.gridBoundary();
    //    if (polOrder == 1) {
    //      localDirichletDofs = this->findLocalDirichletDoFs(entity, gridBoundary);
    //    } else {
    //      const auto& lagrangePointSet = backend_->lagrangePointSet(entity);
    //      // loop over all intersections
    //      const auto intersectionEndIt = gridPart_->iend(entity);
    //      for (auto intersectionIt = gridPart_->ibegin(entity); intersectionIt !=intersectionEndIt; ++intersectionIt)
    //      {
    //        const auto& intersection = *intersectionIt;
    //        // only work on dirichlet intersections
    //        if (gridBoundary.dirichlet(intersection)) {
    //          // get local face number of boundary intersection
    //          const int intersectionIndex = intersection.indexInInside();
    //          // iterate over face dofs and set unit row
    //          const auto faceDofEndIt = lagrangePointSet.template endSubEntity< 1 >(intersectionIndex);
    //          for (auto faceDofIt = lagrangePointSet.template beginSubEntity< 1 >(intersectionIndex);
    //               faceDofIt != faceDofEndIt;
    //               ++faceDofIt) {
    //            const size_t localDofIndex = *faceDofIt;
    //            localDirichletDofs.insert(localDofIndex);
    //          } // iterate over face dofs and set unit row
    //        } // only work on dirichlet intersections
    //      } // loop over all intersections
    //    }
    //    const size_t numRows = localDirichletDofs.size();
    //    if (numRows > 0) {
    //      const size_t numCols = mapper_->numDofs(entity);
    //      ret.setSize(numRows, numCols);
    //      mapper_->globalIndices(entity, tmpMappedRows_);
    //      mapper_->globalIndices(entity, tmpMappedCols_);
    //      size_t localRow = 0;
    //      const RangeFieldType zero(0);
    //      for (auto localDirichletDofIt = localDirichletDofs.begin();
    //           localDirichletDofIt != localDirichletDofs.end();
    //           ++localDirichletDofIt) {
    //        const size_t& localDirichletDofIndex = * localDirichletDofIt;
    //        ret.globalRow(localRow) = tmpMappedRows_[localDirichletDofIndex];
    //        for (size_t jj = 0; jj < ret.cols(); ++jj) {
    //          ret.globalCol(jj) = tmpMappedCols_[jj];
    //          ret.value(localRow, jj) = zero;
    //        }
    //        ++localRow;
    //      }
    //    } else {
    //      ret.setSize(0, 0);
    //    }
  } // ... localConstraints(..., Dirichlet< ..., false >)

  using BaseType::computePattern;

  template <class LocalGridPartType, class OtherSpaceType>
  PatternType* computePattern(const LocalGridPartType& localGridPart, const OtherSpaceType& otherSpace) const
  {
    return BaseType::computeCodim0Pattern(localGridPart, otherSpace);
  }

  std::vector<DomainType> lagrange_points(const EntityType& entity) const
  {
    // check
    static_assert(polOrder == 1, "Not yet implemented for other polynomial orders!");
    // get the basis and reference element
    const auto basis              = baseFunctionSet(entity);
    const auto& reference_element = ReferenceElements<DomainFieldType, dimDomain>::general(entity.type());
    const int num_vertices = reference_element.size(dimDomain);
    assert(num_vertices >= 0);
    assert(size_t(num_vertices) == basis.size() && "This should not happen with polOrder 1!");
    // prepare return vector
    std::vector<DomainType> local_vertices(num_vertices, DomainType(0));
    if (this->tmp_basis_values_.size() < basis.size())
      this->tmp_basis_values_.resize(basis.size());
    // loop over all vertices
    for (int ii = 0; ii < num_vertices; ++ii) {
      // get the local coordinate of the iith vertex
      const auto local_vertex = reference_element.position(ii, dimDomain);
      // evaluate the basefunctionset
      basis.evaluate(local_vertex, this->tmp_basis_values_);
      // find the basis function that evaluates to one here (has to be only one!)
      size_t found = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj)
        if (Dune::Stuff::Common::FloatCmp::eq(this->tmp_basis_values_[jj][0], RangeFieldType(1))) {
          ++found;
          local_vertices[jj] = local_vertex;
        }
      assert(found == 1 && "This must not happen for polOrder 1!");
    }
    return local_vertices;
  } // ... lagrange_points(...)

private:
  std::shared_ptr<const GridPartType> gridPart_;
  std::shared_ptr<const FEMapType> fe_map_;
  std::shared_ptr<const BackendType> backend_;
  std::shared_ptr<const MapperType> mapper_;
  mutable Dune::DynamicVector<size_t> tmpMappedRows_;
  mutable Dune::DynamicVector<size_t> tmpMappedCols_;
}; // class PdelabWrapper< ..., 1 >

} // namespace ContinuousLagrangeSpace
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACE_CONTINUOUSLAGRANGE_PDELAB_HH
<commit_msg>[space.continuouslagrange.pdelab] * updated use of BaseFunctionSet * implemented localConstraints<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACE_CONTINUOUSLAGRANGE_PDELAB_HH
#define DUNE_GDT_SPACE_CONTINUOUSLAGRANGE_PDELAB_HH

#include <memory>

#include <dune/common/typetraits.hh>
#include <dune/common/fvector.hh>

#include <dune/geometry/genericgeometry/topologytypes.hh>

#include <dune/grid/common/capabilities.hh>

#include <dune/pdelab/finiteelementmap/pkfem.hh>
#include <dune/pdelab/finiteelementmap/qkfem.hh>
#include <dune/pdelab/gridfunctionspace/gridfunctionspace.hh>

#include "../../mapper/pdelab.hh"
#include "../../basefunctionset/pdelab.hh"

#include "../interface.hh"
#include "../constraints.hh"

namespace Dune {
namespace GDT {
namespace ContinuousLagrangeSpace {

// forward, to be used in the traits and to allow for specialization
template <class GridPartImp, int polynomialOrder, class RangeFieldImp, int rangeDim, int rangeDimCols = 1>
class PdelabWrapper;

/**
 *  \brief Traits class for ContinuousLagrangeSpace::PdelabWrapper.
 */
template <class GridPartImp, int polynomialOrder, class RangeFieldImp, int rangeDim, int rangeDimCols = 1>
class PdelabWrapperTraits
{
public:
  typedef PdelabWrapper<GridPartImp, polynomialOrder, RangeFieldImp, rangeDim, rangeDimCols> derived_type;
  typedef GridPartImp GridPartType;
  static const int polOrder = polynomialOrder;
  static_assert(polOrder >= 1, "Wrong polOrder given!");

private:
  typedef typename GridPartType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridPartType::dimension;

public:
  typedef RangeFieldImp RangeFieldType;
  static const unsigned int dimRange     = rangeDim;
  static const unsigned int dimRangeCols = rangeDimCols;

private:
  template <class G, bool single_geom, bool is_simplex, bool is_cube>
  struct Choose
  {
    static_assert(Dune::AlwaysFalse<G>::value,
                  "This space is only implemented for either fully simplicial or fully cubic grids!");
  };
  template <class G>
  struct Choose<G, true, true, false>
  {
    typedef PDELab::PkLocalFiniteElementMap<typename GridPartType::GridViewType, DomainFieldType, RangeFieldType,
                                            polOrder> FEMapType;
  };
  template <class G>
  struct Choose<G, true, false, true>
  {
    typedef PDELab::QkLocalFiniteElementMap<typename GridPartType::GridViewType, DomainFieldType, RangeFieldType,
                                            polOrder> FEMapType;
  };
  typedef typename GridPartType::GridType GridType;
  typedef typename Choose<GridType, Dune::Capabilities::hasSingleGeometryType<GridType>::v,
                          Dune::Capabilities::hasSingleGeometryType<GridType>::topologyId
                              == GenericGeometry::SimplexTopology<dimDomain>::type::id,
                          Dune::Capabilities::hasSingleGeometryType<GridType>::topologyId
                              == GenericGeometry::CubeTopology<dimDomain>::type::id>::FEMapType FEMapType;

public:
  typedef PDELab::GridFunctionSpace<typename GridPartType::GridViewType, FEMapType> BackendType;
  typedef Mapper::PdelabWrapper<BackendType> MapperType;
  typedef typename GridPartType::template Codim<0>::EntityType EntityType;
  typedef BaseFunctionSet::PdelabWrapper<BackendType, EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange,
                                         dimRangeCols> BaseFunctionSetType;

private:
  friend class PdelabWrapper<GridPartImp, polynomialOrder, RangeFieldImp, rangeDim, rangeDimCols>;
}; // class SpaceWrappedFemContinuousLagrangeTraits

// unspecialized version, to give better compile errors
template <class GP, int p, class R, int r, int rC>
class PdelabWrapper : public SpaceInterface<PdelabWrapperTraits<GP, p, R, r, rC>>
{
public:
  typedef PdelabWrapperTraits<GP, p, R, r, rC> Traits;

  typedef typename Traits::GridPartType GridPartType;
  static const int polOrder = Traits::polOrder;
  typedef typename GridPartType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridPartType::dimension;
  typedef typename Traits::RangeFieldType RangeFieldType;
  static const unsigned int dimRange     = Traits::dimRange;
  static const unsigned int dimRangeCols = Traits::dimRangeCols;

  typedef typename Traits::BackendType BackendType;
  typedef typename Traits::MapperType MapperType;
  typedef typename Traits::BaseFunctionSetType BaseFunctionSetType;
  typedef typename Traits::EntityType EntityType;

  typedef Dune::Stuff::LA::SparsityPatternDefault PatternType;

  PdelabWrapper(const std::shared_ptr<const GridPartType>& /*grid_prt*/)
  {
    static_assert((Dune::AlwaysFalse<GP>::value), "Not yet implemented for this combination of dimensions!");
  }
}; // PdelabWrapper

template <class GridPartImp, int polynomialOrder, class RangeFieldImp>
class PdelabWrapper<GridPartImp, polynomialOrder, RangeFieldImp, 1, 1>
    : public SpaceInterface<PdelabWrapperTraits<GridPartImp, polynomialOrder, RangeFieldImp, 1, 1>>
{
  typedef SpaceInterface<PdelabWrapperTraits<GridPartImp, polynomialOrder, RangeFieldImp, 1, 1>> BaseType;
  typedef PdelabWrapper<GridPartImp, polynomialOrder, RangeFieldImp, 1, 1> ThisType;

public:
  typedef PdelabWrapperTraits<GridPartImp, polynomialOrder, RangeFieldImp, 1, 1> Traits;

  typedef typename Traits::GridPartType GridPartType;
  static const int polOrder = Traits::polOrder;
  typedef typename GridPartType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridPartType::dimension;
  typedef FieldVector<DomainFieldType, dimDomain> DomainType;
  typedef typename Traits::RangeFieldType RangeFieldType;
  static const unsigned int dimRange     = Traits::dimRange;
  static const unsigned int dimRangeCols = Traits::dimRangeCols;

  typedef typename Traits::BackendType BackendType;
  typedef typename Traits::MapperType MapperType;
  typedef typename Traits::BaseFunctionSetType BaseFunctionSetType;
  typedef typename Traits::EntityType EntityType;

private:
  typedef typename Traits::FEMapType FEMapType;

public:
  typedef Dune::Stuff::LA::SparsityPatternDefault PatternType;

  PdelabWrapper(const std::shared_ptr<const GridPartType>& gridP)
    : gridPart_(gridP)
    , fe_map_(std::make_shared<FEMapType>(gridPart_->gridView()))
    , backend_(std::make_shared<BackendType>(const_cast<GridPartType&>(*gridPart_).gridView(), *fe_map_))
    , mapper_(std::make_shared<MapperType>(*backend_))
    , tmpMappedRows_(mapper_->maxNumDofs())
    , tmpMappedCols_(mapper_->maxNumDofs())
  {
  }

  PdelabWrapper(const ThisType& other)
    : gridPart_(other.gridPart_)
    , fe_map_(other.fe_map_)
    , backend_(other.backend_)
    , mapper_(other.mapper_)
    , tmpMappedRows_(mapper_->maxNumDofs())
    , tmpMappedCols_(mapper_->maxNumDofs())
  {
  }

  ThisType& operator=(const ThisType& other)
  {
    if (this != &other) {
      gridPart_ = other.gridPart_;
      fe_map_   = other.fe_map_;
      backend_  = other.backend_;
      mapper_ = other.mapper_;
      tmpMappedRows_.resize(mapper_->maxNumDofs());
      tmpMappedCols_.resize(mapper_->maxNumDofs());
    }
    return *this;
  }

  ~PdelabWrapper()
  {
  }

  const std::shared_ptr<const GridPartType>& gridPart() const
  {
    return gridPart_;
  }

  const BackendType& backend() const
  {
    return *backend_;
  }

  bool continuous() const
  {
    return true;
  }

  const MapperType& mapper() const
  {
    return *mapper_;
  }

  BaseFunctionSetType baseFunctionSet(const EntityType& entity) const
  {
    return BaseFunctionSetType(*backend_, entity, polOrder);
  }

  template <class R>
  void localConstraints(const EntityType& /*entity*/, Constraints::LocalDefault<R>& /*ret*/) const
  {
    static_assert((Dune::AlwaysFalse<R>::value), "Not implemented for arbitrary constraints!");
  }

  void
  localConstraints(const EntityType& entity,
                   Constraints::Dirichlet<typename GridPartType::IntersectionType, RangeFieldType, true>& ret) const
  {
    static_assert(dimDomain == 2, "Not tested for other dimensions!");
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    const std::set<size_t> localDirichletDofs = this->findLocalDirichletDoFs(entity, ret.gridBoundary());
    const size_t numRows = localDirichletDofs.size();
    if (numRows > 0) {
      const size_t numCols = mapper_->numDofs(entity);
      ret.setSize(numRows, numCols);
      mapper_->globalIndices(entity, tmpMappedRows_);
      mapper_->globalIndices(entity, tmpMappedCols_);
      size_t localRow = 0;
      const RangeFieldType zero(0);
      const RangeFieldType one(1);
      for (auto localDirichletDofIt = localDirichletDofs.begin(); localDirichletDofIt != localDirichletDofs.end();
           ++localDirichletDofIt) {
        const size_t& localDirichletDofIndex = *localDirichletDofIt;
        ret.globalRow(localRow) = tmpMappedRows_[localDirichletDofIndex];
        for (size_t jj = 0; jj < ret.cols(); ++jj) {
          ret.globalCol(jj) = tmpMappedCols_[jj];
          if (tmpMappedCols_[jj] == tmpMappedRows_[localDirichletDofIndex])
            ret.value(localRow, jj) = one;
          else
            ret.value(localRow, jj) = zero;
        }
        ++localRow;
      }
    } else {
      ret.setSize(0, 0);
    }
  } // ... localConstraints(..., Dirichlet< ..., true >)

  void
  localConstraints(const EntityType& entity,
                   Constraints::Dirichlet<typename GridPartType::IntersectionType, RangeFieldType, false>& ret) const
  {
    static_assert(dimDomain == 2, "Not tested for other dimensions!");
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    const std::set<size_t> localDirichletDofs = this->findLocalDirichletDoFs(entity, ret.gridBoundary());
    const size_t numRows = localDirichletDofs.size();
    if (numRows > 0) {
      const size_t numCols = mapper_->numDofs(entity);
      ret.setSize(numRows, numCols);
      mapper_->globalIndices(entity, tmpMappedRows_);
      mapper_->globalIndices(entity, tmpMappedCols_);
      size_t localRow = 0;
      const RangeFieldType zero(0);
      for (auto localDirichletDofIt = localDirichletDofs.begin(); localDirichletDofIt != localDirichletDofs.end();
           ++localDirichletDofIt) {
        const size_t& localDirichletDofIndex = *localDirichletDofIt;
        ret.globalRow(localRow) = tmpMappedRows_[localDirichletDofIndex];
        for (size_t jj = 0; jj < ret.cols(); ++jj) {
          ret.globalCol(jj) = tmpMappedCols_[jj];
          ret.value(localRow, jj) = zero;
        }
        ++localRow;
      }
    } else {
      ret.setSize(0, 0);
    }
  } // ... localConstraints(..., Dirichlet< ..., false >)

  using BaseType::computePattern;

  template <class LocalGridPartType, class OtherSpaceType>
  PatternType* computePattern(const LocalGridPartType& localGridPart, const OtherSpaceType& otherSpace) const
  {
    return BaseType::computeCodim0Pattern(localGridPart, otherSpace);
  }

  std::vector<DomainType> lagrange_points(const EntityType& entity) const
  {
    // check
    static_assert(polOrder == 1, "Not yet implemented for other polynomial orders!");
    // get the basis and reference element
    const auto basis              = baseFunctionSet(entity);
    const auto& reference_element = ReferenceElements<DomainFieldType, dimDomain>::general(entity.type());
    const int num_vertices = reference_element.size(dimDomain);
    assert(num_vertices >= 0);
    assert(size_t(num_vertices) == basis.size() && "This should not happen with polOrder 1!");
    // prepare return vector
    std::vector<DomainType> local_vertices(num_vertices, DomainType(0));
    if (this->tmp_basis_values_.size() < basis.size())
      this->tmp_basis_values_.resize(basis.size());
    // loop over all vertices
    for (int ii = 0; ii < num_vertices; ++ii) {
      // get the local coordinate of the iith vertex
      const auto local_vertex = reference_element.position(ii, dimDomain);
      // evaluate the basefunctionset
      basis.evaluate(local_vertex, this->tmp_basis_values_);
      // find the basis function that evaluates to one here (has to be only one!)
      size_t found = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj)
        if (Dune::Stuff::Common::FloatCmp::eq(this->tmp_basis_values_[jj][0], RangeFieldType(1))) {
          ++found;
          local_vertices[jj] = local_vertex;
        }
      assert(found == 1 && "This must not happen for polOrder 1!");
    }
    return local_vertices;
  } // ... lagrange_points(...)

private:
  std::shared_ptr<const GridPartType> gridPart_;
  std::shared_ptr<const FEMapType> fe_map_;
  std::shared_ptr<const BackendType> backend_;
  std::shared_ptr<const MapperType> mapper_;
  mutable Dune::DynamicVector<size_t> tmpMappedRows_;
  mutable Dune::DynamicVector<size_t> tmpMappedCols_;
}; // class PdelabWrapper< ..., 1 >

} // namespace ContinuousLagrangeSpace
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACE_CONTINUOUSLAGRANGE_PDELAB_HH
<|endoftext|>


<commit_before>#ifndef HEADERS_HPP
#define HEADERS_HPP

#include <array>
#include <cstdint>
#include <cstring>
#include <sstream>
#include <string>

#include <arpa/inet.h>

namespace Headers {

/*! Representation of the etherner header.
 */
struct Ethernet {
	std::array<uint8_t, 6> destMac; //!< Destination MAC
	std::array<uint8_t, 6> srcMac;  //!< Source MAC
	uint16_t ethertype;				//!< Ethertype

	/*! Get the SDU
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(
			reinterpret_cast<uint8_t *>(this) + sizeof(struct Ethernet));
	}

	static std::string addrToStr(std::array<uint8_t, 6> addr) {
		std::stringstream str;
		str << std::hex << static_cast<int>(addr[0]) << ":" << std::hex
			<< static_cast<int>(addr[1]) << ":" << std::hex << static_cast<int>(addr[2])
			<< ":" << std::hex << static_cast<int>(addr[3]) << ":" << std::hex
			<< static_cast<int>(addr[4]) << ":" << std::hex << static_cast<int>(addr[5]);
		return str.str();
	}

	std::string getSrcAddr() { return addrToStr(this->srcMac); }

	std::string getDstAddr() { return addrToStr(this->destMac); }

	uint16_t getEthertype() { return ntohs(this->ethertype); }

	void setSrcAddr(const std::array<uint8_t, 6> addr) {
		memcpy(this->srcMac.data(), addr.data(), 6);
	}

	void setDstAddr(std::array<uint8_t, 6> addr) {
		memcpy(this->destMac.data(), addr.data(), 6);
	}

	void setEthertype(uint16_t type) { this->ethertype = htons(type); }
} __attribute__((packed));

/*! Representation of the IPv4 header.
 */
struct IPv4 {
	uint8_t version_ihl; //!< Version and IHL

	uint8_t version() const { return (version_ihl & 0xf0) >> 4; }
	uint8_t ihl() const { return version_ihl & 0x0f; }

	/*! Set the version field to 4
	 */
	void setVersion() {
		version_ihl &= 0x0f;
		version_ihl |= 0x40;
	}

	/*! Sets the IP header length
	 * \param len length as it will appear in the header
	 */
	void setIHL(uint8_t len) {
		version_ihl &= 0xf0;
		len &= 0x0f;
		version_ihl |= len;
	}

	uint8_t tos;				  //!< Type of Service
	uint16_t total_length;		  //!< L3-PDU length
	uint16_t id;				  //!< Identification
	uint16_t flags_fragmentation; //!< flags and fragmentation offset

	uint16_t fragmentation() const { return flags_fragmentation & 0x1fff; }
	uint16_t flags() const { return flags_fragmentation >> 18; }

	uint8_t ttl;   //!< Time to live
	uint8_t proto; //!< next protocol

	static constexpr uint8_t PROTO_ICMP = 1;
	static constexpr uint8_t PROTO_TCP = 6;
	static constexpr uint8_t PROTO_UDP = 17;

	void setProtoICMP() { proto = PROTO_ICMP; }

	void setProtoTCP() { proto = PROTO_TCP; }

	void setProtoUDP() { proto = PROTO_UDP; }

	uint16_t checksum; //!< header checksum
	uint32_t srcIP;	//!< source IPv4 address
	uint32_t dstIP;	//!< destination IPv4 address

	/*! Get the SDU
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(this) + 4 * ihl());
	}

	static std::string addrToStr(uint32_t addr) {
		std::stringstream str;
		str << (addr >> 24) << "." << ((addr >> 16) & 0xff) << "." << ((addr >> 8) & 0xff)
			<< "." << (addr & 0xff);
		return str.str();
	}

	std::string getSrcAddr() { return addrToStr(this->srcIP); }

	std::string getDstAddr() { return addrToStr(this->dstIP); }

	void setLength(uint16_t len) { this->total_length = htons(len); }

	uint16_t getLength() { return ntohs(this->total_length); }

	/*! Fill out the header checksum for this packet
	 */
	void calcChecksum() {
		uint32_t result = 0;
		uint16_t *hdr_cast = reinterpret_cast<uint16_t *>(this);

		this->checksum = 0;
		for (uint8_t i = 0; i < (this->ihl() * 4); i++) {
			result += ntohs(hdr_cast[i]);
			if (result & (1 << 16)) {
				result &= 0xffff;
				result++;
			}
		}

		this->checksum = htons(~result);
	};

} __attribute__((packed));

/*! Representation of the TCP header.
 */
struct Tcp {
	uint16_t srcPort;	  //!< Source port
	uint16_t dstPort;	  //!< Destination port
	uint32_t seq;		   //!< Sequence number
	uint32_t ack;		   //!< Acknowledgement number
	uint16_t offset_flags; //!< Data offset and flags
	uint16_t window;	   //!< Receive window
	uint16_t checksum;	 //!< Checksum
	uint16_t urgend_ptr;   //!< Urgent pointer

	/*! Get the SDU
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(
			reinterpret_cast<uint8_t *>(this) + sizeof(struct Tcp));
	}

} __attribute__((packed));

/*! Representation of the UDP header.
 */
struct Udp {
	uint16_t srcPort;  //!< Source port
	uint16_t dstPort;  //!< Destination port
	uint16_t len;	  //!< Length
	uint16_t checksum; //!< Checksum

	/*! Get the SDU
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(
			reinterpret_cast<uint8_t *>(this) + sizeof(struct Udp));
	}

} __attribute__((packed));

/*! Representation of the ICMP header
 */
struct Icmp {
	uint8_t type;	  //!< Type
	uint8_t code;	  //!< Code
	uint16_t checksum; //!< Checksum
} __attribute__((packed));

} // namespace Headers

#endif /* HEADERS_HPP */
<commit_msg>add getters and setters for more headers<commit_after>#ifndef HEADERS_HPP
#define HEADERS_HPP

#include <array>
#include <cstdint>
#include <cstring>
#include <sstream>
#include <string>

#include <arpa/inet.h>

namespace Headers {

/*! Representation of the etherner header.
 */
struct Ethernet {
	std::array<uint8_t, 6> destMac; //!< Destination MAC
	std::array<uint8_t, 6> srcMac;  //!< Source MAC
	uint16_t ethertype;				//!< Ethertype

	/*! Get the SDU
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(
			reinterpret_cast<uint8_t *>(this) + sizeof(struct Ethernet));
	}

	static std::string addrToStr(std::array<uint8_t, 6> addr) {
		std::stringstream str;
		str << std::hex << static_cast<int>(addr[0]) << ":" << std::hex
			<< static_cast<int>(addr[1]) << ":" << std::hex << static_cast<int>(addr[2])
			<< ":" << std::hex << static_cast<int>(addr[3]) << ":" << std::hex
			<< static_cast<int>(addr[4]) << ":" << std::hex << static_cast<int>(addr[5]);
		return str.str();
	}

	std::string getSrcAddr() { return addrToStr(this->srcMac); }

	std::string getDstAddr() { return addrToStr(this->destMac); }

	uint16_t getEthertype() { return ntohs(this->ethertype); }

	void setSrcAddr(const std::array<uint8_t, 6> addr) {
		memcpy(this->srcMac.data(), addr.data(), 6);
	}

	void setDstAddr(std::array<uint8_t, 6> addr) {
		memcpy(this->destMac.data(), addr.data(), 6);
	}

	void setEthertype(uint16_t type) { this->ethertype = htons(type); }
} __attribute__((packed));

/*! Representation of the IPv4 header.
 */
struct IPv4 {
	uint8_t version_ihl; //!< Version and IHL

	uint8_t version() const { return (version_ihl & 0xf0) >> 4; }
	uint8_t ihl() const { return version_ihl & 0x0f; }

	/*! Set the version field to 4
	 */
	void setVersion() {
		version_ihl &= 0x0f;
		version_ihl |= 0x40;
	}

	/*! Sets the IP header length
	 * \param len length as it will appear in the header
	 */
	void setIHL(uint8_t len) {
		version_ihl &= 0xf0;
		len &= 0x0f;
		version_ihl |= len;
	}

	uint8_t tos;		   //!< Type of Service
	uint16_t total_length; //!< L3-PDU length

	/*! Set the length of the L3-SDU
	 * \param Length of the L3-SDU (IP payload length)
	 */
	void setPayloadLength(uint16_t len) { total_length = htons(ihl() * 4 + len); }

	/*! Get the length of the L3-SDU
	 * \return The length of the payload (host byte order)
	 */
	uint16_t getPayloadLength() const { return ntohl(total_length) - ihl() * 4; }

	uint16_t id;				  //!< Identification
	uint16_t flags_fragmentation; //!< flags and fragmentation offset

	uint16_t fragmentation() const { return flags_fragmentation & 0x1fff; }
	uint16_t flags() const { return flags_fragmentation >> 18; }

	uint8_t ttl;   //!< Time to live
	uint8_t proto; //!< next protocol

	static constexpr uint8_t PROTO_ICMP = 1;
	static constexpr uint8_t PROTO_TCP = 6;
	static constexpr uint8_t PROTO_UDP = 17;

	void setProtoICMP() { proto = PROTO_ICMP; }

	void setProtoTCP() { proto = PROTO_TCP; }

	void setProtoUDP() { proto = PROTO_UDP; }

	uint16_t checksum; //!< header checksum
	uint32_t srcIP;	//!< source IPv4 address
	uint32_t dstIP;	//!< destination IPv4 address

	/*! Set the source ip
	 * \param ip Source IP in host byte order
	 */
	void setSrcIP(uint32_t ip) { srcIP = htonl(ip); }

	/*! Set the destination ip
	 * \param ip Destination IP in host byte order
	 */
	void setDstIP(uint32_t ip) { dstIP = htonl(ip); }

	/*! Get the source IP
	 * \return Source IP in host byte order
	 */
	uint32_t getSrcIP() const { return ntohl(srcIP); }

	/*! Get the destination IP
	 * \return Destination IP in host byte order
	 */
	uint32_t getDstIP() const { return ntohl(dstIP); }

	/*! Get the SDU
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(this) + 4 * ihl());
	}

	static std::string addrToStr(uint32_t addr) {
		std::stringstream str;
		str << (addr >> 24) << "." << ((addr >> 16) & 0xff) << "." << ((addr >> 8) & 0xff)
			<< "." << (addr & 0xff);
		return str.str();
	}

	std::string getSrcAddr() { return addrToStr(this->srcIP); }

	std::string getDstAddr() { return addrToStr(this->dstIP); }

	void setLength(uint16_t len) { this->total_length = htons(len); }

	uint16_t getLength() { return ntohs(this->total_length); }

	/*! Fill out the header checksum for this packet
	 */
	void calcChecksum() {
		uint32_t result = 0;
		uint16_t *hdr_cast = reinterpret_cast<uint16_t *>(this);

		this->checksum = 0;
		for (uint8_t i = 0; i < (this->ihl() * 4); i++) {
			result += ntohs(hdr_cast[i]);
			if (result & (1 << 16)) {
				result &= 0xffff;
				result++;
			}
		}

		this->checksum = htons(~result);
	};

} __attribute__((packed));

/*! Representation of the TCP header.
 */
struct Tcp {
	uint16_t srcPort;	  //!< Source port
	uint16_t dstPort;	  //!< Destination port
	uint32_t seq;		   //!< Sequence number
	uint32_t ack;		   //!< Acknowledgement number
	uint16_t offset_flags; //!< Data offset and flags
	uint16_t window;	   //!< Receive window
	uint16_t checksum;	 //!< Checksum
	uint16_t urgend_ptr;   //!< Urgent pointer

	/*! Get the SDU
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(
			reinterpret_cast<uint8_t *>(this) + sizeof(struct Tcp));
	}

} __attribute__((packed));

/*! Representation of the UDP header.
 */
struct Udp {
	uint16_t srcPort;  //!< Source port
	uint16_t dstPort;  //!< Destination port
	uint16_t len;	  //!< Length
	uint16_t checksum; //!< Checksum

	/*! Set the source port
	 * \param Source port in host byte order
	 */
	void setSrcPort(uint16_t p) { srcPort = htons(p); }

	/*! Set the destination port
	 * \param Destinatino port in host byte order
	 */
	void setDstPort(uint16_t p) { dstPort = htons(p); }

	/*! Get the source port
	 * \return Source port in host byte order
	 */
	uint16_t getSrcPort() const { return ntohs(srcPort); }

	/*! Get the destination port
	 * \return Destination port in host byte order
	 */
	uint16_t getDstPort() const { return ntohs(dstPort); }

	/*! Get the length of the L4-SDU (UDP payload)
	 * \return Length of the payload (host byte order)
	 */
	uint16_t getPayloadLength() const { return ntohs(len) - sizeof(struct Udp); }

	/*! Set the length of the L4-SDU (UDP payload)
	 * \param Length of the payload (host byte order)
	 */
	void setPayloadLength(uint16_t length) { len = htons(length + sizeof(struct Udp)); }

	/*! Get the SDU
	 */
	void *getPayload() {
		return reinterpret_cast<void *>(
			reinterpret_cast<uint8_t *>(this) + sizeof(struct Udp));
	}

} __attribute__((packed));

/*! Representation of the ICMP header
 */
struct Icmp {
	uint8_t type;	  //!< Type
	uint8_t code;	  //!< Code
	uint16_t checksum; //!< Checksum
} __attribute__((packed));

} // namespace Headers

#endif /* HEADERS_HPP */
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include <complex>
#include <vector>
#include <array>

//Metaprogramming utilities
#include "etl/tmp.hpp"

// Utilities
#include "etl/order.hpp"
#include "etl/sparse_storage.hpp"
#include "etl/config.hpp"
#include "etl/vectorization.hpp"
#include "etl/complex.hpp"
#include "etl/compat.hpp"

//Forward declarations
#include "etl/value_fwd.hpp"
#include "etl/expr_fwd.hpp"

// The traits
#include "etl/traits.hpp"

// The operators
#include "etl/op/scalar.hpp"
#include "etl/op/generators.hpp"
#include "etl/op/transformers.hpp"
#include "etl/op/views.hpp"
#include "etl/op/virtual_views.hpp"
#include "etl/op/unary_op.hpp"
#include "etl/op/binary_op.hpp"

//Global test functions
#include "etl/globals.hpp"

// The expressions
#include "etl/expr/binary_expr.hpp"
#include "etl/expr/unary_expr.hpp"
#include "etl/expr/generator_expr.hpp"
#include "etl/expr/temporary_expr.hpp"
#include "etl/expr/optimized_expr.hpp"

// The complex expressions
#include "etl/expr/mmul_expr.hpp"
#include "etl/expr/outer_product_expr.hpp"
#include "etl/expr/fft_expr.hpp"
#include "etl/expr/conv_expr.hpp"
#include "etl/expr/convmtx2_expr.hpp"
#include "etl/expr/pooling_expr.hpp"
#include "etl/expr/pooling_derivative_expr.hpp"
#include "etl/expr/upsample_expr.hpp"

// The expressions building
#include "etl/checks.hpp"
#include "etl/builder/expression_builder.hpp"
#include "etl/builder/mul_expression_builder.hpp"
#include "etl/builder/conv_expression_builder.hpp"
#include "etl/builder/fft_expression_builder.hpp"
#include "etl/builder/pooling_expression_builder.hpp"

// The evaluator and optimizer
#include "etl/evaluator.hpp"
#include "etl/optimizer.hpp"

// The value classes implementation
#include "etl/fast.hpp"
#include "etl/dyn.hpp"
#include "etl/sparse.hpp"

// The traits
#include "etl/traits.hpp"

// to_string support
#include "etl/print.hpp"
<commit_msg>Remove duplicated include<commit_after>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include <complex>
#include <vector>
#include <array>

//Metaprogramming utilities
#include "etl/tmp.hpp"

// Utilities
#include "etl/order.hpp"
#include "etl/sparse_storage.hpp"
#include "etl/config.hpp"
#include "etl/vectorization.hpp"
#include "etl/complex.hpp"
#include "etl/compat.hpp"

//Forward declarations
#include "etl/value_fwd.hpp"
#include "etl/expr_fwd.hpp"

// The traits
#include "etl/traits.hpp"

// The operators
#include "etl/op/scalar.hpp"
#include "etl/op/generators.hpp"
#include "etl/op/transformers.hpp"
#include "etl/op/views.hpp"
#include "etl/op/virtual_views.hpp"
#include "etl/op/unary_op.hpp"
#include "etl/op/binary_op.hpp"

//Global test functions
#include "etl/globals.hpp"

// The expressions
#include "etl/expr/binary_expr.hpp"
#include "etl/expr/unary_expr.hpp"
#include "etl/expr/generator_expr.hpp"
#include "etl/expr/temporary_expr.hpp"
#include "etl/expr/optimized_expr.hpp"

// The complex expressions
#include "etl/expr/mmul_expr.hpp"
#include "etl/expr/outer_product_expr.hpp"
#include "etl/expr/fft_expr.hpp"
#include "etl/expr/conv_expr.hpp"
#include "etl/expr/convmtx2_expr.hpp"
#include "etl/expr/pooling_expr.hpp"
#include "etl/expr/pooling_derivative_expr.hpp"
#include "etl/expr/upsample_expr.hpp"

// The expressions building
#include "etl/checks.hpp"
#include "etl/builder/expression_builder.hpp"
#include "etl/builder/mul_expression_builder.hpp"
#include "etl/builder/conv_expression_builder.hpp"
#include "etl/builder/fft_expression_builder.hpp"
#include "etl/builder/pooling_expression_builder.hpp"

// The evaluator and optimizer
#include "etl/evaluator.hpp"
#include "etl/optimizer.hpp"

// The value classes implementation
#include "etl/fast.hpp"
#include "etl/dyn.hpp"
#include "etl/sparse.hpp"

// to_string support
#include "etl/print.hpp"
<|endoftext|>


<commit_before>#include "writer/verilog/axi/master_controller.h"

#include "iroha/i_design.h"
#include "writer/verilog/axi/master_port.h"
#include "writer/verilog/module.h"
#include "writer/verilog/ports.h"
#include "writer/verilog/table.h"

namespace iroha {
namespace writer {
namespace verilog {
namespace axi {

MasterController::MasterController(const IResource &res, bool reset_polarity)
  : AxiController(res, reset_polarity) {
  MasterPort::GetReadWrite(res_, &r_, &w_);
  burst_len_ = (1 << sram_addr_width_);
}

MasterController::~MasterController() {
}

void MasterController::Write(ostream &os) {
  AddSramPorts();
  ports_->AddPort("addr", Port::INPUT, 32);
  ports_->AddPort("wen", Port::INPUT, 0);
  ports_->AddPort("req", Port::INPUT, 0);
  ports_->AddPort("ack", Port::OUTPUT, 0);
  string initials;
  GenReadChannel(cfg_, true, nullptr, ports_.get(), &initials);
  GenWriteChannel(cfg_, true, nullptr, ports_.get(), &initials);
  string name = MasterPort::ControllerName(res_, reset_polarity_);
  os << "module " << name << "(";
  ports_->Output(Ports::PORT_NAME, os);
  os << ");\n";
  ports_->Output(Ports::PORT_TYPE, os);
  os << "\n"
     << "  `define S_IDLE 0\n"
     << "  `define S_ADDR_WAIT 1\n";
  if (r_) {
    os << "  `define S_READ_DATA 2\n"
       << "  `define S_READ_DATA_WAIT 3\n";
  }
  if (w_) {
    os << "  `define S_WRITE_WAIT 4\n";
  }
  os << "  reg [2:0] st;\n\n";
  if (w_) {
    os << "  `define WS_IDLE 0\n"
       << "  `define WS_WRITE 1\n"
       << "  `define WS_WAIT 2\n"
       << "  reg [1:0] wst;\n\n";
  }
  if (r_) {
    os << "  reg [" << sram_addr_width_ << ":0] ridx;\n"
       << "  reg read_last;\n\n";
  }
  if (r_) {
    os << "  reg [" << sram_addr_width_ << ":0] widx;\n\n";
  }
  os << "  always @(posedge clk) begin\n"
     << "    if (" << (reset_polarity_ ? "" : "!")
     << ResetName(reset_polarity_) << ") begin\n"
     << "      ack <= 0;\n"
     << "      sram_req <= 0;\n"
     << "      sram_wen <= 0;\n"
     << "      st <= `S_IDLE;\n";
  if (w_) {
    os << "      wst <= `WS_IDLE;\n";
  }
  os << initials
     << "    end else begin\n";
  OutputMainFsm(os);
  if (w_) {
    OutputWriterFsm(os);
  }
  os << "    end\n"
     << "  end\n"
     << "endmodule\n";
}

void MasterController::AddPorts(const PortConfig &cfg,
				Module *mod, bool r, bool w,
				string *s) {
  Ports *ports = mod->GetPorts();
  if (r) {
    GenReadChannel(cfg, true, mod, ports, s);
  }
  if (w) {
    GenWriteChannel(cfg, true, mod, ports, s);
  }
}

void MasterController::OutputMainFsm(ostream &os) {
  int alen = burst_len_ - 1;
  if (r_) {
    os << "      if (!sram_EXCLUSIVE) begin\n"
       << "        sram_wen <= (st == `S_READ_DATA && RVALID);\n"
       << "      end\n";
  } else {
    os << "      sram_wen <= 0;\n";
  }
  os << "      case (st)\n"
     << "        `S_IDLE: begin\n";
  if (r_ || w_) {
    os << "          if (req) begin\n";
    if (r_) {
      os << "            ridx <= 0;\n";
    }
    os << "            st <= `S_ADDR_WAIT;\n";
    if (r_ && !w_) {
      os << "            ARVALID <= 1;\n"
	 << "            ARADDR <= addr;\n"
	 << "            ARLEN <= " << alen << ";\n";
    }
    if (!r_ && w_) {
      os << "            AWVALID <= 1;\n"
	 << "            AWADDR <= addr;\n"
	 << "            AWLEN <= " << alen << ";\n";
    }
    if (r_ && w_) {
      os << "            if (wen) begin\n"
	 << "              ARVALID <= 1;\n"
	 << "              ARADDR <= addr;\n"
	 << "              ARLEN <= " << alen << ";\n"
	 << "            end else begin\n"
	 << "              AWVALID <= 1;\n"
	 << "              AWADDR <= addr;\n"
	 << "              AWLEN <= " << alen << ";\n"
	 << "            end\n";
    }
    os << "          end\n";
  }
  os << "        end\n";
  if (r_ || w_) {
    os << "        `S_ADDR_WAIT: begin\n";
    if (r_ && !w_) {
      os << "          if (ARREADY) begin\n"
	 << "            st <= `S_READ_DATA;\n"
	 << "            ARVALID <= 0;\n"
	 << "            RREADY <= 1;\n"
	 << "          end\n";
    }
    if (!r_ && w_) {
      os << "          if (AWREADY) begin\n"
	 << "            st <= `S_WRITE_WAIT;\n"
	 << "            AWVALID <= 0;\n"
	 << "            sram_addr <= ridx;\n"
	 << "          end\n";
    }
    if (r_ && w_) {
      os << "          if (wen) begin\n"
	 << "            if (AWREADY) begin\n"
	 << "              st <= `S_WRITE_WAIT;\n"
	 << "              AWVALID <= 0;\n"
	 << "              sram_addr <= ridx;\n"
	 << "            end\n"
	 << "          end else begin\n"
	 << "            if (ARREADY) begin\n"
	 << "              st <= `S_READ_DATA;\n"
	 << "              RREADY <= 1;\n"
	 << "            end\n"
	 << "          end\n";
    }
    os << "        end\n";
  }
  if (r_) {
    ReadState(os);
  }
  if (w_) {
    os << "        `S_WRITE_WAIT: begin\n"
       << "          if (BVALID) begin\n"
       << "            st <= `S_IDLE;\n"
       << "          end\n"
       << "          if (wst == `WS_IDLE && req && wen) begin\n"
       << "            sram_addr <= 0;\n"
       << "          end\n"
       << "          if (wst == `WS_WRITE && WREADY && WVALID) begin\n"
       << "            sram_addr <= widx + 1;\n"
       << "          end\n"
       << "        end\n";
  }
  os << "      endcase\n";
}

void MasterController::ReadState(ostream &os) {
  os << "        `S_READ_DATA: begin\n"
     << "          if (RVALID) begin\n"
     << "            sram_addr <= ridx;\n"
     << "            sram_wdata <= RDATA;\n"
     << "            ridx <= ridx + 1;\n"
     << "            if (sram_EXCLUSIVE) begin\n"
     << "              if (RLAST) begin\n"
     << "                RREADY <= 0;\n"
     << "                st <= `S_IDLE;\n"
     << "              end\n"
     << "            end else begin\n"
     << "              st <= `S_READ_DATA_WAIT;\n"
     << "              sram_req <= 1;\n"
     << "              sram_wen <= 1;\n"
     << "              RREADY <= 0;\n"
     << "              read_last <= RLAST;\n"
     << "            end\n"
     << "          end\n"
     << "        end\n"
     << "        `S_READ_DATA_WAIT: begin\n" // !sram_EXCLUSIVE
     << "          if (sram_ack) begin\n"
     << "            sram_req <= 0;\n"
     << "            sram_wen <= 0;\n"
     << "            if (read_last) begin\n"
     << "              st <= `S_IDLE;\n"
     << "            end else begin\n"
     << "              st <= `S_READ_DATA;\n"
     << "              RREADY <= 1;\n"
     << "            end\n"
     << "          end\n"
     << "        end\n";
}

void MasterController::OutputWriterFsm(ostream &os) {
  os << "       case (wst)\n"
     << "        `WS_IDLE: begin\n"
     << "          if (req && wen) begin\n"
     << "            wst <= `WS_WRITE;\n"
     << "            widx <= 0;\n"
     << "          end\n"
     << "        end\n"
     << "        `WS_WRITE: begin\n"
     << "          if (widx < " << burst_len_ << ") begin\n"
     << "            WVALID <= 1;\n"
     << "            WDATA <= sram_rdata;\n"
     << "            if (WREADY && WVALID) begin\n"
     << "              widx <= widx + 1;\n"
     << "            end\n"
     << "            if (widx < " << burst_len_ << " - 1) begin\n"
     << "              WLAST <= 1;\n"
     << "            end\n"
     << "          end else begin\n"
     << "            WVALID <= 0;\n"
     << "            WLAST <= 0;\n"
     << "            wst <= `WS_WAIT;\n"
     << "            BREADY <= 1;\n"
     << "          end\n"
     << "        end\n"
     << "        `WS_WAIT: begin\n"
     << "          if (BVALID) begin\n"
     << "            BREADY <= 0;\n"
     << "            st <= `WS_IDLE;\n"
     << "          end\n"
     << "        end\n"
     << "      endcase\n";

}

}  // namespace axi
}  // namespace verilog
}  // namespace writer
}  // namespace iroha
<commit_msg>Fix sram_wen logic for exclusive mode.<commit_after>#include "writer/verilog/axi/master_controller.h"

#include "iroha/i_design.h"
#include "writer/verilog/axi/master_port.h"
#include "writer/verilog/module.h"
#include "writer/verilog/ports.h"
#include "writer/verilog/table.h"

namespace iroha {
namespace writer {
namespace verilog {
namespace axi {

MasterController::MasterController(const IResource &res, bool reset_polarity)
  : AxiController(res, reset_polarity) {
  MasterPort::GetReadWrite(res_, &r_, &w_);
  burst_len_ = (1 << sram_addr_width_);
}

MasterController::~MasterController() {
}

void MasterController::Write(ostream &os) {
  AddSramPorts();
  ports_->AddPort("addr", Port::INPUT, 32);
  ports_->AddPort("wen", Port::INPUT, 0);
  ports_->AddPort("req", Port::INPUT, 0);
  ports_->AddPort("ack", Port::OUTPUT, 0);
  string initials;
  GenReadChannel(cfg_, true, nullptr, ports_.get(), &initials);
  GenWriteChannel(cfg_, true, nullptr, ports_.get(), &initials);
  string name = MasterPort::ControllerName(res_, reset_polarity_);
  os << "module " << name << "(";
  ports_->Output(Ports::PORT_NAME, os);
  os << ");\n";
  ports_->Output(Ports::PORT_TYPE, os);
  os << "\n"
     << "  `define S_IDLE 0\n"
     << "  `define S_ADDR_WAIT 1\n";
  if (r_) {
    os << "  `define S_READ_DATA 2\n"
       << "  `define S_READ_DATA_WAIT 3\n";
  }
  if (w_) {
    os << "  `define S_WRITE_WAIT 4\n";
  }
  os << "  reg [2:0] st;\n\n";
  if (w_) {
    os << "  `define WS_IDLE 0\n"
       << "  `define WS_WRITE 1\n"
       << "  `define WS_WAIT 2\n"
       << "  reg [1:0] wst;\n\n";
  }
  if (r_) {
    os << "  reg [" << sram_addr_width_ << ":0] ridx;\n"
       << "  reg read_last;\n\n";
  }
  if (r_) {
    os << "  reg [" << sram_addr_width_ << ":0] widx;\n\n";
  }
  os << "  always @(posedge clk) begin\n"
     << "    if (" << (reset_polarity_ ? "" : "!")
     << ResetName(reset_polarity_) << ") begin\n"
     << "      ack <= 0;\n"
     << "      sram_req <= 0;\n"
     << "      sram_wen <= 0;\n"
     << "      st <= `S_IDLE;\n";
  if (w_) {
    os << "      wst <= `WS_IDLE;\n";
  }
  os << initials
     << "    end else begin\n";
  OutputMainFsm(os);
  if (w_) {
    OutputWriterFsm(os);
  }
  os << "    end\n"
     << "  end\n"
     << "endmodule\n";
}

void MasterController::AddPorts(const PortConfig &cfg,
				Module *mod, bool r, bool w,
				string *s) {
  Ports *ports = mod->GetPorts();
  if (r) {
    GenReadChannel(cfg, true, mod, ports, s);
  }
  if (w) {
    GenWriteChannel(cfg, true, mod, ports, s);
  }
}

void MasterController::OutputMainFsm(ostream &os) {
  int alen = burst_len_ - 1;
  if (r_) {
    os << "      if (sram_EXCLUSIVE) begin\n"
       << "        sram_wen <= (st == `S_READ_DATA && RVALID);\n"
       << "      end\n";
  } else {
    os << "      sram_wen <= 0;\n";
  }
  os << "      case (st)\n"
     << "        `S_IDLE: begin\n";
  if (r_ || w_) {
    os << "          if (req) begin\n";
    if (r_) {
      os << "            ridx <= 0;\n";
    }
    os << "            st <= `S_ADDR_WAIT;\n";
    if (r_ && !w_) {
      os << "            ARVALID <= 1;\n"
	 << "            ARADDR <= addr;\n"
	 << "            ARLEN <= " << alen << ";\n";
    }
    if (!r_ && w_) {
      os << "            AWVALID <= 1;\n"
	 << "            AWADDR <= addr;\n"
	 << "            AWLEN <= " << alen << ";\n";
    }
    if (r_ && w_) {
      os << "            if (wen) begin\n"
	 << "              ARVALID <= 1;\n"
	 << "              ARADDR <= addr;\n"
	 << "              ARLEN <= " << alen << ";\n"
	 << "            end else begin\n"
	 << "              AWVALID <= 1;\n"
	 << "              AWADDR <= addr;\n"
	 << "              AWLEN <= " << alen << ";\n"
	 << "            end\n";
    }
    os << "          end\n";
  }
  os << "        end\n";
  if (r_ || w_) {
    os << "        `S_ADDR_WAIT: begin\n";
    if (r_ && !w_) {
      os << "          if (ARREADY) begin\n"
	 << "            st <= `S_READ_DATA;\n"
	 << "            ARVALID <= 0;\n"
	 << "            RREADY <= 1;\n"
	 << "          end\n";
    }
    if (!r_ && w_) {
      os << "          if (AWREADY) begin\n"
	 << "            st <= `S_WRITE_WAIT;\n"
	 << "            AWVALID <= 0;\n"
	 << "            sram_addr <= ridx;\n"
	 << "          end\n";
    }
    if (r_ && w_) {
      os << "          if (wen) begin\n"
	 << "            if (AWREADY) begin\n"
	 << "              st <= `S_WRITE_WAIT;\n"
	 << "              AWVALID <= 0;\n"
	 << "              sram_addr <= ridx;\n"
	 << "            end\n"
	 << "          end else begin\n"
	 << "            if (ARREADY) begin\n"
	 << "              st <= `S_READ_DATA;\n"
	 << "              RREADY <= 1;\n"
	 << "            end\n"
	 << "          end\n";
    }
    os << "        end\n";
  }
  if (r_) {
    ReadState(os);
  }
  if (w_) {
    os << "        `S_WRITE_WAIT: begin\n"
       << "          if (BVALID) begin\n"
       << "            st <= `S_IDLE;\n"
       << "          end\n"
       << "          if (wst == `WS_IDLE && req && wen) begin\n"
       << "            sram_addr <= 0;\n"
       << "          end\n"
       << "          if (wst == `WS_WRITE && WREADY && WVALID) begin\n"
       << "            sram_addr <= widx + 1;\n"
       << "          end\n"
       << "        end\n";
  }
  os << "      endcase\n";
}

void MasterController::ReadState(ostream &os) {
  os << "        `S_READ_DATA: begin\n"
     << "          if (RVALID) begin\n"
     << "            sram_addr <= ridx;\n"
     << "            sram_wdata <= RDATA;\n"
     << "            ridx <= ridx + 1;\n"
     << "            if (sram_EXCLUSIVE) begin\n"
     << "              if (RLAST) begin\n"
     << "                RREADY <= 0;\n"
     << "                st <= `S_IDLE;\n"
     << "              end\n"
     << "            end else begin\n"
     << "              st <= `S_READ_DATA_WAIT;\n"
     << "              sram_req <= 1;\n"
     << "              sram_wen <= 1;\n"
     << "              RREADY <= 0;\n"
     << "              read_last <= RLAST;\n"
     << "            end\n"
     << "          end\n"
     << "        end\n"
     << "        `S_READ_DATA_WAIT: begin\n" // !sram_EXCLUSIVE
     << "          if (sram_ack) begin\n"
     << "            sram_req <= 0;\n"
     << "            sram_wen <= 0;\n"
     << "            if (read_last) begin\n"
     << "              st <= `S_IDLE;\n"
     << "            end else begin\n"
     << "              st <= `S_READ_DATA;\n"
     << "              RREADY <= 1;\n"
     << "            end\n"
     << "          end\n"
     << "        end\n";
}

void MasterController::OutputWriterFsm(ostream &os) {
  os << "       case (wst)\n"
     << "        `WS_IDLE: begin\n"
     << "          if (req && wen) begin\n"
     << "            wst <= `WS_WRITE;\n"
     << "            widx <= 0;\n"
     << "          end\n"
     << "        end\n"
     << "        `WS_WRITE: begin\n"
     << "          if (widx < " << burst_len_ << ") begin\n"
     << "            WVALID <= 1;\n"
     << "            WDATA <= sram_rdata;\n"
     << "            if (WREADY && WVALID) begin\n"
     << "              widx <= widx + 1;\n"
     << "            end\n"
     << "            if (widx < " << burst_len_ << " - 1) begin\n"
     << "              WLAST <= 1;\n"
     << "            end\n"
     << "          end else begin\n"
     << "            WVALID <= 0;\n"
     << "            WLAST <= 0;\n"
     << "            wst <= `WS_WAIT;\n"
     << "            BREADY <= 1;\n"
     << "          end\n"
     << "        end\n"
     << "        `WS_WAIT: begin\n"
     << "          if (BVALID) begin\n"
     << "            BREADY <= 0;\n"
     << "            st <= `WS_IDLE;\n"
     << "          end\n"
     << "        end\n"
     << "      endcase\n";

}

}  // namespace axi
}  // namespace verilog
}  // namespace writer
}  // namespace iroha
<|endoftext|>