<commit_before>/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include <cmath>
#include <queue>

#include "log.h"
#include "route.h"

namespace {

USING_NEXTPNR_NAMESPACE

struct QueuedWire
{
    WireId wire;
    PipId pip;

    float delay = 0, togo = 0;

    struct Greater
    {
        bool operator()(const QueuedWire &lhs, const QueuedWire &rhs) const
                noexcept
        {
            return (lhs.delay + lhs.togo) > (rhs.delay + rhs.togo);
        }
    };
};

void ripup_net(Design *design, IdString net_name)
{
    auto &chip = design->chip;
    auto net_info = design->nets.at(net_name);

    for (auto &it : net_info->wires) {
        if (it.second != PipId())
            chip.unbindPip(it.second);
        chip.unbindWire(it.first);
    }

    net_info->wires.clear();
}

struct Router
{
    std::unordered_set<IdString> rippedNets;
    int visitCnt = 0, revisitCnt = 0;
    bool routedOkay = false;
    float maxDelay = 0.0;

    Router(Design *design, IdString net_name, bool verbose, bool ripup = false,
           float ripup_pip_penalty = 5.0, float ripup_wire_penalty = 5.0)
    {
        auto &chip = design->chip;
        auto net_info = design->nets.at(net_name);

        if (verbose)
            log("Routing net %s.\n", net_name.c_str());

        if (verbose)
            log("  Source: %s.%s.\n", net_info->driver.cell->name.c_str(),
                net_info->driver.port.c_str());

        auto src_bel = net_info->driver.cell->bel;

        if (src_bel == BelId())
            log_error("Source cell %s (%s) is not mapped to a bel.\n",
                      net_info->driver.cell->name.c_str(),
                      net_info->driver.cell->type.c_str());

        if (verbose)
            log("    Source bel: %s\n", chip.getBelName(src_bel).c_str());

        IdString driver_port = net_info->driver.port;

        auto driver_port_it = net_info->driver.cell->pins.find(driver_port);
        if (driver_port_it != net_info->driver.cell->pins.end())
            driver_port = driver_port_it->second;

        auto src_wire = chip.getWireBelPin(src_bel, portPinFromId(driver_port));

        if (src_wire == WireId())
            log_error("No wire found for port %s (pin %s) on source cell %s "
                      "(bel %s).\n",
                      net_info->driver.port.c_str(), driver_port.c_str(),
                      net_info->driver.cell->name.c_str(),
                      chip.getBelName(src_bel).c_str());

        if (verbose)
            log("    Source wire: %s\n", chip.getWireName(src_wire).c_str());

        std::unordered_map<WireId, DelayInfo> src_wires;
        src_wires[src_wire] = DelayInfo();
        net_info->wires[src_wire] = PipId();
        chip.bindWire(src_wire, net_name);

        for (auto &user_it : net_info->users) {
            if (verbose)
                log("  Route to: %s.%s.\n", user_it.cell->name.c_str(),
                    user_it.port.c_str());

            auto dst_bel = user_it.cell->bel;

            if (dst_bel == BelId())
                log_error("Destination cell %s (%s) is not mapped to a bel.\n",
                          user_it.cell->name.c_str(),
                          user_it.cell->type.c_str());

            if (verbose)
                log("    Destination bel: %s\n",
                    chip.getBelName(dst_bel).c_str());

            IdString user_port = user_it.port;

            auto user_port_it = user_it.cell->pins.find(user_port);

            if (user_port_it != user_it.cell->pins.end())
                user_port = user_port_it->second;

            auto dst_wire =
                    chip.getWireBelPin(dst_bel, portPinFromId(user_port));

            if (dst_wire == WireId())
                log_error("No wire found for port %s (pin %s) on destination "
                          "cell %s (bel %s).\n",
                          user_it.port.c_str(), user_port.c_str(),
                          user_it.cell->name.c_str(),
                          chip.getBelName(dst_bel).c_str());

            if (verbose) {
                log("    Destination wire: %s\n",
                    chip.getWireName(dst_wire).c_str());
                log("    Path delay estimate: %.2f\n",
                    chip.estimateDelay(src_wire, dst_wire));
            }

            std::unordered_map<WireId, QueuedWire> visited;
            std::priority_queue<QueuedWire, std::vector<QueuedWire>,
                                QueuedWire::Greater>
                    queue;

            for (auto &it : src_wires) {
                QueuedWire qw;
                qw.wire = it.first;
                qw.pip = PipId();
                qw.delay = it.second.avgDelay();
                qw.togo = chip.estimateDelay(qw.wire, dst_wire);

                queue.push(qw);
                visited[qw.wire] = qw;
            }

            while (!queue.empty()) {
                visitCnt++;
                QueuedWire qw = queue.top();
                queue.pop();

                for (auto pip : chip.getPipsDownhill(qw.wire)) {
                    float next_delay = qw.delay;

                    if (!chip.checkPipAvail(pip)) {
                        if (ripup)
                            next_delay += ripup_pip_penalty;
                        else
                            continue;
                    }

                    WireId next_wire = chip.getPipDstWire(pip);
                    next_delay += chip.getPipDelay(pip).avgDelay();

                    if (visited.count(next_wire)) {
                        if (visited.at(next_wire).delay <= next_delay + 1e-3)
                            continue;
                        if (verbose)
                            log("Found better route to %s. Old vs new delay "
                                "estimate: %.2f %.2f\n",
                                chip.getWireName(next_wire).c_str(),
                                visited.at(next_wire).delay, next_delay);
                        revisitCnt++;
                    }

                    if (!chip.checkWireAvail(next_wire)) {
                        if (ripup)
                            next_delay += ripup_wire_penalty;
                        else
                            continue;
                    }

                    QueuedWire next_qw;
                    next_qw.wire = next_wire;
                    next_qw.pip = pip;
                    next_qw.delay = next_delay;
                    next_qw.togo = chip.estimateDelay(next_wire, dst_wire);
                    visited[next_qw.wire] = next_qw;
                    queue.push(next_qw);

                    if (next_qw.wire == dst_wire) {
                        std::priority_queue<QueuedWire, std::vector<QueuedWire>,
                                            QueuedWire::Greater>
                                empty_queue;
                        std::swap(queue, empty_queue);
                        break;
                    }
                }
            }

            if (visited.count(dst_wire) == 0) {
                if (verbose)
                    log("Failed to route %s -> %s.\n",
                        chip.getWireName(src_wire).c_str(),
                        chip.getWireName(dst_wire).c_str());
                else if (ripup)
                    log_info("Failed to route %s -> %s.\n",
                             chip.getWireName(src_wire).c_str(),
                             chip.getWireName(dst_wire).c_str());
                ripup_net(design, net_name);
                return;
            }

            if (verbose)
                log("    Final path delay: %.2f\n", visited[dst_wire].delay);
            maxDelay = fmaxf(maxDelay, visited[dst_wire].delay);

            if (verbose)
                log("    Route (from destination to source):\n");

            WireId cursor = dst_wire;

            while (1) {
                if (verbose)
                    log("    %8.2f %s\n", visited[cursor].delay,
                        chip.getWireName(cursor).c_str());

                if (src_wires.count(cursor))
                    break;

                IdString conflicting_net = chip.getWireNet(cursor, true);

                if (conflicting_net != IdString()) {
                    assert(ripup);
                    assert(conflicting_net != net_name);
                    ripup_net(design, conflicting_net);
                    rippedNets.insert(conflicting_net);
                }

                conflicting_net = chip.getPipNet(visited[cursor].pip, true);

                if (conflicting_net != IdString()) {
                    assert(ripup);
                    assert(conflicting_net != net_name);
                    ripup_net(design, conflicting_net);
                    rippedNets.insert(conflicting_net);
                }

                net_info->wires[cursor] = visited[cursor].pip;
                chip.bindWire(cursor, net_name);
                chip.bindPip(visited[cursor].pip, net_name);

                src_wires[cursor] = chip.getPipDelay(visited[cursor].pip);
                cursor = chip.getPipSrcWire(visited[cursor].pip);
            }
        }

        routedOkay = true;
    }
};

} // namespace

NEXTPNR_NAMESPACE_BEGIN

void route_design(Design *design, bool verbose)
{
    auto &chip = design->chip;
    float maxDelay = 0.0;
    float ripup_pip_penalty = 5.0;
    float ripup_wire_penalty = 5.0;

    log_info("Routing..\n");

    std::unordered_set<IdString> netsQueue;

    for (auto &net_it : design->nets) {
        auto net_name = net_it.first;
        auto net_info = net_it.second;

        if (net_info->driver.cell == nullptr)
            continue;

        if (!net_info->wires.empty())
            continue;

        netsQueue.insert(net_name);
    }

    if (netsQueue.empty()) {
        log_info("found no unrouted nets. no routing necessary.\n");
        return;
    }

    log_info("found %d unrouted nets. starting routing procedure.\n",
             int(netsQueue.size()));

    float estimatedTotalDelay = 0.0;
    int estimatedTotalDelayCnt = 0;

    for (auto net_name : netsQueue) {
        auto net_info = design->nets.at(net_name);

        auto src_bel = net_info->driver.cell->bel;

        if (src_bel == BelId())
            continue;

        IdString driver_port = net_info->driver.port;

        auto driver_port_it = net_info->driver.cell->pins.find(driver_port);
        if (driver_port_it != net_info->driver.cell->pins.end())
            driver_port = driver_port_it->second;

        auto src_wire = chip.getWireBelPin(src_bel, portPinFromId(driver_port));

        if (src_wire == WireId())
            continue;

        for (auto &user_it : net_info->users) {
            auto dst_bel = user_it.cell->bel;

            if (dst_bel == BelId())
                continue;

            IdString user_port = user_it.port;

            auto user_port_it = user_it.cell->pins.find(user_port);

            if (user_port_it != user_it.cell->pins.end())
                user_port = user_port_it->second;

            auto dst_wire =
                    chip.getWireBelPin(dst_bel, portPinFromId(user_port));

            if (dst_wire == WireId())
                continue;

            estimatedTotalDelay += chip.estimateDelay(src_wire, dst_wire);
            estimatedTotalDelayCnt++;
        }
    }

    log_info("estimated total wire delay: %.2f (avg %.2f)\n",
             estimatedTotalDelay, estimatedTotalDelay / estimatedTotalDelayCnt);

    while (!netsQueue.empty()) {
        int visitCnt = 0, revisitCnt = 0, netCnt = 0;

        std::unordered_set<IdString> ripupQueue;

        for (auto net_name : netsQueue) {
            Router router(design, net_name, verbose, false);

            netCnt++;
            visitCnt += router.visitCnt;
            revisitCnt += router.revisitCnt;

            if (router.routedOkay) {
                maxDelay = fmaxf(maxDelay, router.maxDelay);
            } else {
                ripupQueue.insert(net_name);
            }

            if (netCnt % 100 == 0)
                log_info("  processed %d nets. (%d routed, %d failed)\n",
                         netCnt, netCnt - int(ripupQueue.size()),
                         int(ripupQueue.size()));
        }

        netsQueue.clear();

        log_info("  processed %d nets. (%d routed, %d failed)\n", netCnt,
                 netCnt - int(ripupQueue.size()), int(ripupQueue.size()));
        log_info("routing pass visited %d wires (%.2f%% revisits).\n", visitCnt,
                 (100.0 * revisitCnt) / visitCnt);

        if (!ripupQueue.empty()) {
            log_info("failed to route %d nets. re-routing in ripup mode.\n",
                     int(ripupQueue.size()));

            visitCnt = 0;
            revisitCnt = 0;
            netCnt = 0;
            int ripCnt = 0;

            for (auto net_name : ripupQueue) {
                Router router(design, net_name, verbose, true,
                              ripup_pip_penalty, ripup_wire_penalty);

                netCnt++;
                visitCnt += router.visitCnt;
                revisitCnt += router.revisitCnt;

                if (!router.routedOkay)
                    log_error("Net %s is impossible to route.\n",
                              net_name.c_str());

                maxDelay = fmaxf(maxDelay, router.maxDelay);

                for (auto it : router.rippedNets)
                    netsQueue.insert(it);

                ripCnt += router.rippedNets.size();

                if (netCnt % 100 == 0)
                    log_info("  routed %d nets, ripped %d nets.\n", netCnt,
                             ripCnt);
            }

            log_info("  routed %d nets, ripped %d nets.\n", netCnt, ripCnt);
            log_info("routing pass visited %d wires (%.2f%% revisits).\n",
                     visitCnt, (100.0 * revisitCnt) / visitCnt);

            log_info("ripped up %d previously routed nets. continue routing.\n",
                     int(netsQueue.size()));

            ripup_pip_penalty *= 1.5;
            ripup_wire_penalty *= 1.5;
        }
    }

    log_info("routing complete. longest path delay: %.2f\n", maxDelay);
}

NEXTPNR_NAMESPACE_END
<commit_msg>Fix router for routing to the same dest wire twice<commit_after>/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include <cmath>
#include <queue>

#include "log.h"
#include "route.h"

namespace {

USING_NEXTPNR_NAMESPACE

struct QueuedWire
{
    WireId wire;
    PipId pip;

    float delay = 0, togo = 0;

    struct Greater
    {
        bool operator()(const QueuedWire &lhs, const QueuedWire &rhs) const
                noexcept
        {
            return (lhs.delay + lhs.togo) > (rhs.delay + rhs.togo);
        }
    };
};

void ripup_net(Design *design, IdString net_name)
{
    auto &chip = design->chip;
    auto net_info = design->nets.at(net_name);

    for (auto &it : net_info->wires) {
        if (it.second != PipId())
            chip.unbindPip(it.second);
        chip.unbindWire(it.first);
    }

    net_info->wires.clear();
}

struct Router
{
    std::unordered_set<IdString> rippedNets;
    int visitCnt = 0, revisitCnt = 0;
    bool routedOkay = false;
    float maxDelay = 0.0;

    Router(Design *design, IdString net_name, bool verbose, bool ripup = false,
           float ripup_pip_penalty = 5.0, float ripup_wire_penalty = 5.0)
    {
        auto &chip = design->chip;
        auto net_info = design->nets.at(net_name);

        if (verbose)
            log("Routing net %s.\n", net_name.c_str());

        if (verbose)
            log("  Source: %s.%s.\n", net_info->driver.cell->name.c_str(),
                net_info->driver.port.c_str());

        auto src_bel = net_info->driver.cell->bel;

        if (src_bel == BelId())
            log_error("Source cell %s (%s) is not mapped to a bel.\n",
                      net_info->driver.cell->name.c_str(),
                      net_info->driver.cell->type.c_str());

        if (verbose)
            log("    Source bel: %s\n", chip.getBelName(src_bel).c_str());

        IdString driver_port = net_info->driver.port;

        auto driver_port_it = net_info->driver.cell->pins.find(driver_port);
        if (driver_port_it != net_info->driver.cell->pins.end())
            driver_port = driver_port_it->second;

        auto src_wire = chip.getWireBelPin(src_bel, portPinFromId(driver_port));

        if (src_wire == WireId())
            log_error("No wire found for port %s (pin %s) on source cell %s "
                      "(bel %s).\n",
                      net_info->driver.port.c_str(), driver_port.c_str(),
                      net_info->driver.cell->name.c_str(),
                      chip.getBelName(src_bel).c_str());

        if (verbose)
            log("    Source wire: %s\n", chip.getWireName(src_wire).c_str());

        std::unordered_map<WireId, DelayInfo> src_wires;
        src_wires[src_wire] = DelayInfo();
        net_info->wires[src_wire] = PipId();
        chip.bindWire(src_wire, net_name);

        for (auto &user_it : net_info->users) {
            if (verbose)
                log("  Route to: %s.%s.\n", user_it.cell->name.c_str(),
                    user_it.port.c_str());

            auto dst_bel = user_it.cell->bel;

            if (dst_bel == BelId())
                log_error("Destination cell %s (%s) is not mapped to a bel.\n",
                          user_it.cell->name.c_str(),
                          user_it.cell->type.c_str());

            if (verbose)
                log("    Destination bel: %s\n",
                    chip.getBelName(dst_bel).c_str());

            IdString user_port = user_it.port;

            auto user_port_it = user_it.cell->pins.find(user_port);

            if (user_port_it != user_it.cell->pins.end())
                user_port = user_port_it->second;

            auto dst_wire =
                    chip.getWireBelPin(dst_bel, portPinFromId(user_port));

            if (dst_wire == WireId())
                log_error("No wire found for port %s (pin %s) on destination "
                          "cell %s (bel %s).\n",
                          user_it.port.c_str(), user_port.c_str(),
                          user_it.cell->name.c_str(),
                          chip.getBelName(dst_bel).c_str());

            if (verbose) {
                log("    Destination wire: %s\n",
                    chip.getWireName(dst_wire).c_str());
                log("    Path delay estimate: %.2f\n",
                    chip.estimateDelay(src_wire, dst_wire));
            }

            std::unordered_map<WireId, QueuedWire> visited;
            std::priority_queue<QueuedWire, std::vector<QueuedWire>,
                                QueuedWire::Greater>
                    queue;

            for (auto &it : src_wires) {
                QueuedWire qw;
                qw.wire = it.first;
                qw.pip = PipId();
                qw.delay = it.second.avgDelay();
                qw.togo = chip.estimateDelay(qw.wire, dst_wire);

                queue.push(qw);
                visited[qw.wire] = qw;
            }

            while (!queue.empty() && !visited.count(dst_wire)) {
                QueuedWire qw = queue.top();
                queue.pop();

                for (auto pip : chip.getPipsDownhill(qw.wire)) {
                    float next_delay = qw.delay;
                    visitCnt++;

                    if (!chip.checkPipAvail(pip)) {
                        if (!ripup || net_name == chip.getPipNet(pip, true))
                            continue;
                        next_delay += ripup_pip_penalty;
                    }

                    WireId next_wire = chip.getPipDstWire(pip);
                    next_delay += chip.getPipDelay(pip).avgDelay();

                    if (visited.count(next_wire)) {
                        if (visited.at(next_wire).delay <= next_delay + 1e-3)
                            continue;
#if 0 // FIXME
                        if (verbose)
                            log("Found better route to %s. Old vs new delay "
                                "estimate: %.2f %.2f\n",
                                chip.getWireName(next_wire).c_str(),
                                visited.at(next_wire).delay, next_delay);
#endif
                        revisitCnt++;
                    }

                    if (!chip.checkWireAvail(next_wire)) {
                        if (!ripup ||
                            net_name == chip.getWireNet(next_wire, true))
                            continue;
                        next_delay += ripup_wire_penalty;
                    }

                    QueuedWire next_qw;
                    next_qw.wire = next_wire;
                    next_qw.pip = pip;
                    next_qw.delay = next_delay;
                    next_qw.togo = chip.estimateDelay(next_wire, dst_wire);
                    visited[next_qw.wire] = next_qw;
                    queue.push(next_qw);
                }
            }

            if (visited.count(dst_wire) == 0) {
                if (verbose)
                    log("Failed to route %s -> %s.\n",
                        chip.getWireName(src_wire).c_str(),
                        chip.getWireName(dst_wire).c_str());
                else if (ripup)
                    log_info("Failed to route %s -> %s.\n",
                             chip.getWireName(src_wire).c_str(),
                             chip.getWireName(dst_wire).c_str());
                ripup_net(design, net_name);
                return;
            }

            if (verbose)
                log("    Final path delay: %.2f\n", visited[dst_wire].delay);
            maxDelay = fmaxf(maxDelay, visited[dst_wire].delay);

            if (verbose)
                log("    Route (from destination to source):\n");

            WireId cursor = dst_wire;

            while (1) {
                if (verbose)
                    log("    %8.2f %s\n", visited[cursor].delay,
                        chip.getWireName(cursor).c_str());

                if (src_wires.count(cursor))
                    break;

                IdString conflicting_net = chip.getWireNet(cursor, true);

                if (conflicting_net != IdString()) {
                    assert(ripup);
                    assert(conflicting_net != net_name);
                    ripup_net(design, conflicting_net);
                    rippedNets.insert(conflicting_net);
                }

                conflicting_net = chip.getPipNet(visited[cursor].pip, true);

                if (conflicting_net != IdString()) {
                    assert(ripup);
                    assert(conflicting_net != net_name);
                    ripup_net(design, conflicting_net);
                    rippedNets.insert(conflicting_net);
                }

                net_info->wires[cursor] = visited[cursor].pip;
                chip.bindWire(cursor, net_name);
                chip.bindPip(visited[cursor].pip, net_name);

                src_wires[cursor] = chip.getPipDelay(visited[cursor].pip);
                cursor = chip.getPipSrcWire(visited[cursor].pip);
            }
        }

        routedOkay = true;
    }
};

} // namespace

NEXTPNR_NAMESPACE_BEGIN

void route_design(Design *design, bool verbose)
{
    auto &chip = design->chip;
    float maxDelay = 0.0;
    float ripup_pip_penalty = 5.0;
    float ripup_wire_penalty = 5.0;

    log_info("Routing..\n");

    std::unordered_set<IdString> netsQueue;

    for (auto &net_it : design->nets) {
        auto net_name = net_it.first;
        auto net_info = net_it.second;

        if (net_info->driver.cell == nullptr)
            continue;

        if (!net_info->wires.empty())
            continue;

        netsQueue.insert(net_name);
    }

    if (netsQueue.empty()) {
        log_info("found no unrouted nets. no routing necessary.\n");
        return;
    }

    log_info("found %d unrouted nets. starting routing procedure.\n",
             int(netsQueue.size()));

    float estimatedTotalDelay = 0.0;
    int estimatedTotalDelayCnt = 0;

    for (auto net_name : netsQueue) {
        auto net_info = design->nets.at(net_name);

        auto src_bel = net_info->driver.cell->bel;

        if (src_bel == BelId())
            continue;

        IdString driver_port = net_info->driver.port;

        auto driver_port_it = net_info->driver.cell->pins.find(driver_port);
        if (driver_port_it != net_info->driver.cell->pins.end())
            driver_port = driver_port_it->second;

        auto src_wire = chip.getWireBelPin(src_bel, portPinFromId(driver_port));

        if (src_wire == WireId())
            continue;

        for (auto &user_it : net_info->users) {
            auto dst_bel = user_it.cell->bel;

            if (dst_bel == BelId())
                continue;

            IdString user_port = user_it.port;

            auto user_port_it = user_it.cell->pins.find(user_port);

            if (user_port_it != user_it.cell->pins.end())
                user_port = user_port_it->second;

            auto dst_wire =
                    chip.getWireBelPin(dst_bel, portPinFromId(user_port));

            if (dst_wire == WireId())
                continue;

            estimatedTotalDelay += chip.estimateDelay(src_wire, dst_wire);
            estimatedTotalDelayCnt++;
        }
    }

    log_info("estimated total wire delay: %.2f (avg %.2f)\n",
             estimatedTotalDelay, estimatedTotalDelay / estimatedTotalDelayCnt);

    while (!netsQueue.empty()) {
        int visitCnt = 0, revisitCnt = 0, netCnt = 0;

        std::unordered_set<IdString> ripupQueue;

        for (auto net_name : netsQueue) {
            Router router(design, net_name, verbose, false);

            netCnt++;
            visitCnt += router.visitCnt;
            revisitCnt += router.revisitCnt;

            if (router.routedOkay) {
                maxDelay = fmaxf(maxDelay, router.maxDelay);
            } else {
                ripupQueue.insert(net_name);
            }

            if (netCnt % 100 == 0)
                log_info("  processed %d nets. (%d routed, %d failed)\n",
                         netCnt, netCnt - int(ripupQueue.size()),
                         int(ripupQueue.size()));
        }

        netsQueue.clear();

        if (netCnt % 100 != 0)
            log_info("  processed %d nets. (%d routed, %d failed)\n", netCnt,
                     netCnt - int(ripupQueue.size()), int(ripupQueue.size()));
        log_info("routing pass visited %d PIPs (%.2f%% revisits).\n", visitCnt,
                 (100.0 * revisitCnt) / visitCnt);

        if (!ripupQueue.empty()) {
            log_info("failed to route %d nets. re-routing in ripup mode.\n",
                     int(ripupQueue.size()));

            visitCnt = 0;
            revisitCnt = 0;
            netCnt = 0;
            int ripCnt = 0;

            for (auto net_name : ripupQueue) {
                Router router(design, net_name, verbose, true,
                              ripup_pip_penalty, ripup_wire_penalty);

                netCnt++;
                visitCnt += router.visitCnt;
                revisitCnt += router.revisitCnt;

                if (!router.routedOkay)
                    log_error("Net %s is impossible to route.\n",
                              net_name.c_str());

                maxDelay = fmaxf(maxDelay, router.maxDelay);

                for (auto it : router.rippedNets)
                    netsQueue.insert(it);

                ripCnt += router.rippedNets.size();

                if (netCnt % 100 == 0)
                    log_info("  routed %d nets, ripped %d nets.\n", netCnt,
                             ripCnt);
            }

            if (netCnt % 100 != 0)
                log_info("  routed %d nets, ripped %d nets.\n", netCnt, ripCnt);
            log_info("routing pass visited %d PIPs (%.2f%% revisits).\n",
                     visitCnt, (100.0 * revisitCnt) / visitCnt);

            log_info("ripped up %d previously routed nets. continue routing.\n",
                     int(netsQueue.size()));

            ripup_pip_penalty *= 1.5;
            ripup_wire_penalty *= 1.5;
        }
    }

    log_info("routing complete. longest path delay: %.2f\n", maxDelay);
}

NEXTPNR_NAMESPACE_END
<|endoftext|>


<commit_before>// Copyright (c) 2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "scheduler.h"

#include <assert.h>
#include <boost/bind.hpp>
#include <utility>

CScheduler::CScheduler() : nThreadsServicingQueue(0), stopRequested(false), stopWhenEmpty(false)
{
}

CScheduler::~CScheduler()
{
    assert(nThreadsServicingQueue == 0);
}

#if BOOST_VERSION < 105000
static boost::system_time toPosixTime(const boost::chrono::system_clock::time_point& t)
{
    return boost::posix_time::from_time_t(boost::chrono::system_clock::to_time_t(t));
}
#endif

void CScheduler::serviceQueue()
{
    boost::unique_lock<boost::mutex> lock(newTaskMutex);
    ++nThreadsServicingQueue;
    stopRequested = false;
    stopWhenEmpty = false;

    // newTaskMutex is locked throughout this loop EXCEPT
    // when the thread is waiting or when the user's function
    // is called.
    while (!shouldStop()) {
        try {
            while (!shouldStop() && taskQueue.empty()) {
                // Wait until there is something to do.
                newTaskScheduled.wait(lock);
            }

            // Wait until either there is a new task, or until
            // the time of the first item on the queue:

// wait_until needs boost 1.50 or later; older versions have timed_wait:
#if BOOST_VERSION < 105000
            while (!shouldStop() && !taskQueue.empty() &&
                   newTaskScheduled.timed_wait(lock, toPosixTime(taskQueue.begin()->first))) {
                // Keep waiting until timeout
            }
#else
            while (!shouldStop() && !taskQueue.empty() &&
                   newTaskScheduled.wait_until(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
                // Keep waiting until timeout
            }
#endif
            // If there are multiple threads, the queue can empty while we're waiting (another
            // thread may service the task we were waiting on).
            if (shouldStop() || taskQueue.empty())
                continue;

            Function f = taskQueue.begin()->second;
            taskQueue.erase(taskQueue.begin());

            // Unlock before calling f, so it can reschedule itself or another task
            // without deadlocking:
            lock.unlock();
            f();
            lock.lock();
        } catch (...) {
            --nThreadsServicingQueue;
            throw;
        }
    }
    --nThreadsServicingQueue;
}

void CScheduler::stop(bool drain)
{
    {
        boost::unique_lock<boost::mutex> lock(newTaskMutex);
        if (drain)
            stopWhenEmpty = true;
        else
            stopRequested = true;
    }
    newTaskScheduled.notify_all();
}

void CScheduler::schedule(CScheduler::Function f, boost::chrono::system_clock::time_point t)
{
    {
        boost::unique_lock<boost::mutex> lock(newTaskMutex);
        taskQueue.insert(std::make_pair(t, f));
    }
    newTaskScheduled.notify_one();
}

void CScheduler::scheduleFromNow(CScheduler::Function f, int64_t deltaSeconds)
{
    schedule(f, boost::chrono::system_clock::now() + boost::chrono::seconds(deltaSeconds));
}

static void Repeat(CScheduler* s, CScheduler::Function f, int64_t deltaSeconds)
{
    f();
    s->scheduleFromNow(boost::bind(&Repeat, s, f, deltaSeconds), deltaSeconds);
}

void CScheduler::scheduleEvery(CScheduler::Function f, int64_t deltaSeconds)
{
    scheduleFromNow(boost::bind(&Repeat, this, f, deltaSeconds), deltaSeconds);
}

size_t CScheduler::getQueueInfo(boost::chrono::system_clock::time_point &first,
                             boost::chrono::system_clock::time_point &last) const
{
    boost::unique_lock<boost::mutex> lock(newTaskMutex);
    size_t result = taskQueue.size();
    if (!taskQueue.empty()) {
        first = taskQueue.begin()->first;
        last = taskQueue.rbegin()->first;
    }
    return result;
}
<commit_msg>Fix intermittent hang issue in scheduler_tests<commit_after>// Copyright (c) 2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "scheduler.h"

#include <assert.h>
#include <boost/bind.hpp>
#include <utility>

CScheduler::CScheduler() : nThreadsServicingQueue(0), stopRequested(false), stopWhenEmpty(false)
{
}

CScheduler::~CScheduler()
{
    assert(nThreadsServicingQueue == 0);
}

#if BOOST_VERSION < 105000
static boost::system_time toPosixTime(const boost::chrono::system_clock::time_point& t)
{
    return boost::posix_time::from_time_t(boost::chrono::system_clock::to_time_t(t));
}
#endif

void CScheduler::serviceQueue()
{
    boost::unique_lock<boost::mutex> lock(newTaskMutex);
    ++nThreadsServicingQueue;

    // newTaskMutex is locked throughout this loop EXCEPT
    // when the thread is waiting or when the user's function
    // is called.
    while (!shouldStop()) {
        try {
            while (!shouldStop() && taskQueue.empty()) {
                // Wait until there is something to do.
                newTaskScheduled.wait(lock);
            }

            // Wait until either there is a new task, or until
            // the time of the first item on the queue:

// wait_until needs boost 1.50 or later; older versions have timed_wait:
#if BOOST_VERSION < 105000
            while (!shouldStop() && !taskQueue.empty() &&
                   newTaskScheduled.timed_wait(lock, toPosixTime(taskQueue.begin()->first))) {
                // Keep waiting until timeout
            }
#else
            while (!shouldStop() && !taskQueue.empty() &&
                   newTaskScheduled.wait_until(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
                // Keep waiting until timeout
            }
#endif
            // If there are multiple threads, the queue can empty while we're waiting (another
            // thread may service the task we were waiting on).
            if (shouldStop() || taskQueue.empty())
                continue;

            Function f = taskQueue.begin()->second;
            taskQueue.erase(taskQueue.begin());

            // Unlock before calling f, so it can reschedule itself or another task
            // without deadlocking:
            lock.unlock();
            f();
            lock.lock();
        } catch (...) {
            --nThreadsServicingQueue;
            throw;
        }
    }
    --nThreadsServicingQueue;
}

void CScheduler::stop(bool drain)
{
    {
        boost::unique_lock<boost::mutex> lock(newTaskMutex);
        if (drain)
            stopWhenEmpty = true;
        else
            stopRequested = true;
    }
    newTaskScheduled.notify_all();
}

void CScheduler::schedule(CScheduler::Function f, boost::chrono::system_clock::time_point t)
{
    {
        boost::unique_lock<boost::mutex> lock(newTaskMutex);
        taskQueue.insert(std::make_pair(t, f));
    }
    newTaskScheduled.notify_one();
}

void CScheduler::scheduleFromNow(CScheduler::Function f, int64_t deltaSeconds)
{
    schedule(f, boost::chrono::system_clock::now() + boost::chrono::seconds(deltaSeconds));
}

static void Repeat(CScheduler* s, CScheduler::Function f, int64_t deltaSeconds)
{
    f();
    s->scheduleFromNow(boost::bind(&Repeat, s, f, deltaSeconds), deltaSeconds);
}

void CScheduler::scheduleEvery(CScheduler::Function f, int64_t deltaSeconds)
{
    scheduleFromNow(boost::bind(&Repeat, this, f, deltaSeconds), deltaSeconds);
}

size_t CScheduler::getQueueInfo(boost::chrono::system_clock::time_point &first,
                             boost::chrono::system_clock::time_point &last) const
{
    boost::unique_lock<boost::mutex> lock(newTaskMutex);
    size_t result = taskQueue.size();
    if (!taskQueue.empty()) {
        first = taskQueue.begin()->first;
        last = taskQueue.rbegin()->first;
    }
    return result;
}
<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <fstream>
#include <locale>
#include <libgen.h>  // for locale stuff (comma-formatted numbers)
#include <cerrno>
#include <cstdio>
#include <getopt.h>

#include "global.h"             // global variables
#include "shrinksam.h"
#include "process_stream.h"

using namespace std;

bool Shrinksam::verbose_flag = false;
char const *Shrinksam::version = "0.1";
char const *Shrinksam::progname;

void show_usage(int status) {
	cerr << Shrinksam::progname << " - shrinks a SAM file while maintaining mate pair information" << endl;
	cerr << endl << "(Written by bct - 2013)" << endl;
	cerr << endl << "Usage:" << endl;
	cerr << Shrinksam::progname << " -i <sam infile name> -k <shrunk sam outfile name>" << endl << endl;
	cerr << Shrinksam::progname << " -k <shrunk sam outfile name> <stdin>" << endl << endl;
	cerr << Shrinksam::progname << " < <stdin> > out" << endl << endl;

	cerr << "  Options:" << endl;
	cerr << "    -i, --input,        Optional - if not given, will read from stdin" << endl;
	cerr << "    -k, --shrunk,       Name for shrunk SAM output file" << endl;
	cerr << "    -d, --delete-input, Delete the input sam file (requires -i argument)" << endl;
	cerr << "    -u, --unpaired,     SAM file was from an unpaired mapping" << endl;
	cerr << "    -h, --help,         Display this help and exit" << endl;
	cerr << "    -v, --verbose,      Print extra details during the run" << endl;
	cerr << "    --version,          Output version information and exit" << endl;

	exit(status);
}

int main(int argc, char *argv[])
{
	locale loc("en_US");
	cout.imbue(loc);

	int c;                            // for getopt
	string input_name;                // input file name
	string shrunk_name;               // output file name
	bool delete_input = false;        // default to no delete
	bool using_stdin = true;          // default to true
	bool using_stdout = true;         // default to true
	bool unpaired = false;            // default to false, assumes paired

	Shrinksam::progname = argv[0];

//	if (argc < 2) {
//		show_usage(EXIT_FAILURE);
//	}

	while(1) {
		static struct option long_options[] =
		{
			{"verbose",      no_argument, 0, 'v'},
			{"version",      no_argument, 0, 'V'},
			{"help",         no_argument, 0, 'h'},
			{"delete-input", no_argument, 0, 'd'},
			{"unpaired",     no_argument, 0, 'u'},
			{"input",        required_argument, 0, 'i'},
			{"shrunk",       required_argument, 0, 'k'},
			{0, 0, 0, 0}
		};

		/* getopt_long stores the option index here. */
		int option_index = 0;

		c = getopt_long(argc, argv, "vVh?dui:k:", long_options, &option_index);

		/* Detect the end of the options. */
		if (c == -1)
			break;

		switch (c) {
			case 'v':
				Shrinksam::verbose_flag = true;
				break;

			case 'V':
				/* version */
				cerr << "Version is " << Shrinksam::version << endl;
				return EXIT_FAILURE;
				break;

			case 'h':
				show_usage(EXIT_FAILURE);
				break;

			case '?':
				/* getopt_long already printed an error message. */
				break;

			case 'i':
				input_name = optarg;
				using_stdin = false;
				break;

			case 'k':
				shrunk_name = optarg;
				using_stdout = false;
				break;

			case 'd':
				delete_input = true;
				break;

			case 'u':
				unpaired = true;
				break;

			default:
				abort ();
		}
	}

	/* check validity of given argument set */
	if (delete_input) {
		if (input_name.empty()) {
			cerr << "Error: Input file name (-i) is required when using -d option." << endl;
			return EXIT_FAILURE;
		}
	}

	if (Shrinksam::verbose_flag) {
		if (using_stdin)
			cerr << "Input is coming from stdin" << endl;
		else
			cerr << "Input is from " << input_name << endl;

		if (using_stdout)
			cerr << "Shrunk SAM output will be to stdout" << endl;
		else
			cerr << "Shrunk SAM output will be in " << shrunk_name << endl;

		if (delete_input)
			cerr << "Input file will be deleted" << endl;
		if (unpaired)
			cerr << "Input is an unpaired SAM file" << endl;
	}

	ifstream input;
	if (using_stdin)
		input.open("/dev/stdin"); // I know - using this code will only work on unix systems
	else
		input.open(input_name);

	ofstream output;
	if (using_stdout)
		output.open("/dev/stdout"); // I know - using this code will only work on unix systems
	else
		output.open(shrunk_name);

	// process the data
	if (unpaired) {
		process_shrunk_unpaired(input,output);
	} else {
		process_shrunk(input,output);
	}

	// delete original file
	if (delete_input) {
		if (Shrinksam::verbose_flag)
			cerr << "Deleting " << input_name << "... " << endl;
		if (remove(input_name.c_str()) != 0)
			cerr << "ERROR: could not delete input file!" << endl;
		else {
			if (Shrinksam::verbose_flag)
				cerr << "Success!" << endl;
		}
	}

	fclose(stderr);
	fclose(stdout);
	fclose(stdin);
	return EXIT_SUCCESS;
}
<commit_msg>updated version to 0.9.0<commit_after>#include <string>
#include <iostream>
#include <fstream>
#include <locale>
#include <libgen.h>  // for locale stuff (comma-formatted numbers)
#include <cerrno>
#include <cstdio>
#include <getopt.h>

#include "global.h"             // global variables
#include "shrinksam.h"
#include "process_stream.h"

using namespace std;

bool Shrinksam::verbose_flag = false;
char const *Shrinksam::version = "0.9.0";
char const *Shrinksam::progname;

void show_usage(int status) {
	cerr << Shrinksam::progname << " - shrinks a SAM file while maintaining mate pair information" << endl;
	cerr << endl << "(Written by bct - 2013)" << endl;
	cerr << endl << "Usage:" << endl;
	cerr << Shrinksam::progname << " -i <sam infile name> -k <shrunk sam outfile name>" << endl << endl;
	cerr << Shrinksam::progname << " -k <shrunk sam outfile name> <stdin>" << endl << endl;
	cerr << Shrinksam::progname << " < <stdin> > out" << endl << endl;

	cerr << "  Options:" << endl;
	cerr << "    -i, --input,        Optional - if not given, will read from stdin" << endl;
	cerr << "    -k, --shrunk,       Name for shrunk SAM output file" << endl;
	cerr << "    -d, --delete-input, Delete the input sam file (requires -i argument)" << endl;
	cerr << "    -u, --unpaired,     SAM file was from an unpaired mapping" << endl;
	cerr << "    -h, --help,         Display this help and exit" << endl;
	cerr << "    -v, --verbose,      Print extra details during the run" << endl;
	cerr << "    --version,          Output version information and exit" << endl;

	exit(status);
}

int main(int argc, char *argv[])
{
	locale loc("en_US");
	cout.imbue(loc);

	int c;                            // for getopt
	string input_name;                // input file name
	string shrunk_name;               // output file name
	bool delete_input = false;        // default to no delete
	bool using_stdin = true;          // default to true
	bool using_stdout = true;         // default to true
	bool unpaired = false;            // default to false, assumes paired

	Shrinksam::progname = argv[0];

//	if (argc < 2) {
//		show_usage(EXIT_FAILURE);
//	}

	while(1) {
		static struct option long_options[] =
		{
			{"verbose",      no_argument, 0, 'v'},
			{"version",      no_argument, 0, 'V'},
			{"help",         no_argument, 0, 'h'},
			{"delete-input", no_argument, 0, 'd'},
			{"unpaired",     no_argument, 0, 'u'},
			{"input",        required_argument, 0, 'i'},
			{"shrunk",       required_argument, 0, 'k'},
			{0, 0, 0, 0}
		};

		/* getopt_long stores the option index here. */
		int option_index = 0;

		c = getopt_long(argc, argv, "vVh?dui:k:", long_options, &option_index);

		/* Detect the end of the options. */
		if (c == -1)
			break;

		switch (c) {
			case 'v':
				Shrinksam::verbose_flag = true;
				break;

			case 'V':
				/* version */
				cerr << "Version is " << Shrinksam::version << endl;
				return EXIT_FAILURE;
				break;

			case 'h':
				show_usage(EXIT_FAILURE);
				break;

			case '?':
				/* getopt_long already printed an error message. */
				break;

			case 'i':
				input_name = optarg;
				using_stdin = false;
				break;

			case 'k':
				shrunk_name = optarg;
				using_stdout = false;
				break;

			case 'd':
				delete_input = true;
				break;

			case 'u':
				unpaired = true;
				break;

			default:
				abort ();
		}
	}

	/* check validity of given argument set */
	if (delete_input) {
		if (input_name.empty()) {
			cerr << "Error: Input file name (-i) is required when using -d option." << endl;
			return EXIT_FAILURE;
		}
	}

	if (Shrinksam::verbose_flag) {
		if (using_stdin)
			cerr << "Input is coming from stdin" << endl;
		else
			cerr << "Input is from " << input_name << endl;

		if (using_stdout)
			cerr << "Shrunk SAM output will be to stdout" << endl;
		else
			cerr << "Shrunk SAM output will be in " << shrunk_name << endl;

		if (delete_input)
			cerr << "Input file will be deleted" << endl;
		if (unpaired)
			cerr << "Input is an unpaired SAM file" << endl;
	}

	ifstream input;
	if (using_stdin)
		input.open("/dev/stdin"); // I know - using this code will only work on unix systems
	else
		input.open(input_name);

	ofstream output;
	if (using_stdout)
		output.open("/dev/stdout"); // I know - using this code will only work on unix systems
	else
		output.open(shrunk_name);

	// process the data
	if (unpaired) {
		process_shrunk_unpaired(input,output);
	} else {
		process_shrunk(input,output);
	}

	// delete original file
	if (delete_input) {
		if (Shrinksam::verbose_flag)
			cerr << "Deleting " << input_name << "... " << endl;
		if (remove(input_name.c_str()) != 0)
			cerr << "ERROR: could not delete input file!" << endl;
		else {
			if (Shrinksam::verbose_flag)
				cerr << "Success!" << endl;
		}
	}

	fclose(stderr);
	fclose(stdout);
	fclose(stdin);
	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "TiledMesh.h"
#include "Parser.h"
#include "InputParameters.h"

// libMesh includes
#include "libmesh/mesh_modification.h"

template<>
InputParameters validParams<TiledMesh>()
{
  InputParameters params = validParams<MooseMesh>();
  params.addRequiredParam<MeshFileName>("file", "The name of the mesh file to read");

  params.addParam<Real>("x_width", 0, "The tile width in the x direction");
  params.addParam<Real>("y_width", 0, "The tile width in the y direction");
  params.addParam<Real>("z_width", 0, "The tile width in the z direction");

  params.addParam<BoundaryName>("left_boundary", "TODO");
  params.addParam<BoundaryName>("right_boundary", "TODO");
  params.addParam<BoundaryName>("top_boundary", "TODO");
  params.addParam<BoundaryName>("bottom_boundary", "TODO");
  params.addParam<BoundaryName>("front_boundary", "TODO");
  params.addParam<BoundaryName>("back_boundary", "TODO");

  params.addParam<unsigned int>("x_tiles", 1, "TODO");
  params.addParam<unsigned int>("y_tiles", 1, "TODO");
  params.addParam<unsigned int>("z_tiles", 1, "TODO");

  return params;
}

TiledMesh::TiledMesh(const std::string & name, InputParameters parameters):
    MooseMesh(name, parameters),
    _x_width(getParam<Real>("x_width")),
    _y_width(getParam<Real>("y_width")),
    _z_width(getParam<Real>("z_width"))
{
}

TiledMesh::TiledMesh(const TiledMesh & other_mesh) :
    MooseMesh(other_mesh),
    _x_width(other_mesh._x_width),
    _y_width(other_mesh._y_width),
    _z_width(other_mesh._z_width)
{
}

MooseMesh &
TiledMesh::clone() const
{
  return *(new TiledMesh(*this));
}

void
TiledMesh::init()
{
// This class only works with SerialMesh
#ifndef LIBMESH_ENABLE_PARMESH

  std::string mesh_file(getParam<MeshFileName>("file"));

  if (mesh_file.rfind(".exd") < mesh_file.size() ||
      mesh_file.rfind(".e") < mesh_file.size())
  {
    ExodusII_IO ex(*this);
    ex.read(mesh_file);
    _mesh.prepare_for_use();
  }
  else
    _mesh.read(mesh_file);

  BoundaryID left = getBoundaryID(getParam<BoundaryName>("left_boundary"));
  BoundaryID right = getBoundaryID(getParam<BoundaryName>("right_boundary"));
  BoundaryID top = getBoundaryID(getParam<BoundaryName>("top_boundary"));
  BoundaryID bottom = getBoundaryID(getParam<BoundaryName>("bottom_boundary"));
  BoundaryID front = getBoundaryID(getParam<BoundaryName>("front_boundary"));
  BoundaryID back = getBoundaryID(getParam<BoundaryName>("back_boundary"));

  {
    AutoPtr<MeshBase> clone = _mesh.clone();

    // Build X Tiles
    for (unsigned int i=1; i<getParam<unsigned int>("x_tiles"); ++i)
    {
      MeshTools::Modification::translate(*clone, _x_width, 0, 0);
      _mesh.stitch_meshes(dynamic_cast<SerialMesh &>(*clone), right, left, TOLERANCE, true);
    }
  }
  {
    AutoPtr<MeshBase> clone = _mesh.clone();

    // Build Y Tiles
    for (unsigned int i=1; i<getParam<unsigned int>("y_tiles"); ++i)
    {
      MeshTools::Modification::translate(*clone, 0, _y_width, 0);
      _mesh.stitch_meshes(dynamic_cast<SerialMesh &>(*clone), top, bottom, TOLERANCE, true);
    }
  }
  {
    AutoPtr<MeshBase> clone = _mesh.clone();

    // Build Y Tiles
    for (unsigned int i=1; i<getParam<unsigned int>("z_tiles"); ++i)
    {
      MeshTools::Modification::translate(*clone, 0, 0, _z_width);
      _mesh.stitch_meshes(dynamic_cast<SerialMesh &>(*clone), front, back, TOLERANCE, true);
    }
  }

#else
  mooseError("TiledMesh cannot be used with --enable-parmesh");
#endif

}
<commit_msg>Adding some documentation to the TiledMesh.<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "TiledMesh.h"
#include "Parser.h"
#include "InputParameters.h"

// libMesh includes
#include "libmesh/mesh_modification.h"

template<>
InputParameters validParams<TiledMesh>()
{
  InputParameters params = validParams<MooseMesh>();
  params.addRequiredParam<MeshFileName>("file", "The name of the mesh file to read");

  params.addParam<Real>("x_width", 0, "The tile width in the x direction");
  params.addParam<Real>("y_width", 0, "The tile width in the y direction");
  params.addParam<Real>("z_width", 0, "The tile width in the z direction");

  // x boundary names
  params.addParam<BoundaryName>("left_boundary", "left_boundary", "name of the left (x) boundary");
  params.addParam<BoundaryName>("right_boundary", "right_boundary", "name of the right (x) boundary");

  // y boundary names
  params.addParam<BoundaryName>("top_boundary", "top_boundary", "name of the top (y) boundary");
  params.addParam<BoundaryName>("bottom_boundary", "bottom_boundary", "name of the bottom (y) boundary");

  // z boundary names
  params.addParam<BoundaryName>("front_boundary", "front_boundary", "name of the front (z) boundary");
  params.addParam<BoundaryName>("back_boundary", "back_boundary", "name of the back (z) boundary");

  // The number of tiles is 1 in each direction unless otherwise specified.
  // An x_tiles value of 1 means do not stitch any extra meshes together in
  // the x-direction.
  params.addParam<unsigned int>("x_tiles", 1, "Number of tiles to stitch together (left to right) in the x-direction");
  params.addParam<unsigned int>("y_tiles", 1, "Number of tiles to stitch together (top to bottom) in the y-direction");
  params.addParam<unsigned int>("z_tiles", 1, "Number of tiles to stitch together (front to back) in the z-direction");

  return params;
}

TiledMesh::TiledMesh(const std::string & name, InputParameters parameters):
    MooseMesh(name, parameters),
    _x_width(getParam<Real>("x_width")),
    _y_width(getParam<Real>("y_width")),
    _z_width(getParam<Real>("z_width"))
{
}

TiledMesh::TiledMesh(const TiledMesh & other_mesh) :
    MooseMesh(other_mesh),
    _x_width(other_mesh._x_width),
    _y_width(other_mesh._y_width),
    _z_width(other_mesh._z_width)
{
}

MooseMesh &
TiledMesh::clone() const
{
  return *(new TiledMesh(*this));
}

void
TiledMesh::init()
{
// This class only works with SerialMesh
#ifndef LIBMESH_ENABLE_PARMESH

  std::string mesh_file(getParam<MeshFileName>("file"));

  if (mesh_file.rfind(".exd") < mesh_file.size() ||
      mesh_file.rfind(".e") < mesh_file.size())
  {
    ExodusII_IO ex(*this);
    ex.read(mesh_file);
    _mesh.prepare_for_use();
  }
  else
    _mesh.read(mesh_file);

  BoundaryID left = getBoundaryID(getParam<BoundaryName>("left_boundary"));
  BoundaryID right = getBoundaryID(getParam<BoundaryName>("right_boundary"));
  BoundaryID top = getBoundaryID(getParam<BoundaryName>("top_boundary"));
  BoundaryID bottom = getBoundaryID(getParam<BoundaryName>("bottom_boundary"));
  BoundaryID front = getBoundaryID(getParam<BoundaryName>("front_boundary"));
  BoundaryID back = getBoundaryID(getParam<BoundaryName>("back_boundary"));

  {
    AutoPtr<MeshBase> clone = _mesh.clone();

    // Build X Tiles
    for (unsigned int i=1; i<getParam<unsigned int>("x_tiles"); ++i)
    {
      MeshTools::Modification::translate(*clone, _x_width, 0, 0);
      _mesh.stitch_meshes(dynamic_cast<SerialMesh &>(*clone), right, left, TOLERANCE, /*clear_stitched_boundary_ids=*/true);
    }
  }
  {
    AutoPtr<MeshBase> clone = _mesh.clone();

    // Build Y Tiles
    for (unsigned int i=1; i<getParam<unsigned int>("y_tiles"); ++i)
    {
      MeshTools::Modification::translate(*clone, 0, _y_width, 0);
      _mesh.stitch_meshes(dynamic_cast<SerialMesh &>(*clone), top, bottom, TOLERANCE, /*clear_stitched_boundary_ids=*/true);
    }
  }
  {
    AutoPtr<MeshBase> clone = _mesh.clone();

    // Build Z Tiles
    for (unsigned int i=1; i<getParam<unsigned int>("z_tiles"); ++i)
    {
      MeshTools::Modification::translate(*clone, 0, 0, _z_width);
      _mesh.stitch_meshes(dynamic_cast<SerialMesh &>(*clone), front, back, TOLERANCE, /*clear_stitched_boundary_ids=*/true);
    }
  }

#else
  mooseError("TiledMesh cannot be used with --enable-parmesh");
#endif

}
<|endoftext|>


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

#include "PPCallback.h"

#include "MacroDefinitions.h"
#include "MacroExpansions.h"

namespace CppImport {

void PPCallback::MacroExpands(const clang::Token& MacroNameTok, const clang::MacroDefinition& md,
													clang::SourceRange sr, const clang::MacroArgs* args)
{
	auto name = QString::fromStdString(MacroNameTok.getIdentifierInfo()->getName().str());

	// ignore export flags
	if (name.endsWith("_API") || name == "Q_DECL_EXPORT") return;

	macroDefinitions_.addMacroDefinition(name, md.getLocalDirective());
	macroExpansions_.addMacroExpansion(sr, md.getLocalDirective(), args);
}

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

#include "PPCallback.h"

#include "MacroDefinitions.h"
#include "MacroExpansions.h"

namespace CppImport {

void PPCallback::MacroExpands(const clang::Token& MacroNameTok, const clang::MacroDefinition& md,
													clang::SourceRange sr, const clang::MacroArgs* args)
{
	auto name = QString::fromStdString(MacroNameTok.getIdentifierInfo()->getName().str());

	// ignore export flags
	if (name.endsWith("_API") || name == "Q_DECL_EXPORT" || name == "Q_DECL_IMPORT") return;

	macroDefinitions_.addMacroDefinition(name, md.getLocalDirective());
	macroExpansions_.addMacroExpansion(sr, md.getLocalDirective(), args);
}

}
<|endoftext|>


<commit_before>#include "Abs.h"

void *Abs::operator new (size_t n, Pool *pool) {
    return pool -> palloc(sizeof(Abs));
}

void Abs::operator delete(void *ptr, Pool *pool){
    free(ptr);
}

void Abs::get_expression(ostream& out, string wrapEntity, Position position) {
    if (wrapEntity == "App")
        out << '(';

    out << '\\';
    out << l;
    out << '.';

    r -> get_expression(out, _entName, _left);

    if (wrapEntity == "App")
        out << ')';
}

vector<string> Abs::get_tree_view(int shift) {
    vector<string> treeBegin;
    treeBegin.push_back(string(shift, ' ') + _entName + _horizontalFirst + char('0' + l));
    treeBegin.push_back(string(shift + _entName.size(), ' ') + _vertical);

    int newShift = shift + _entName.size() + _horizontalFirst.size() + 1;
    vector<string> treeEnd = r->get_tree_view(newShift);

    treeEnd[0].replace(shift + _entName.size(), _horizontalSecond.size(), _horizontalSecond);
    treeBegin.insert(treeBegin.end(), treeEnd.begin(), treeEnd.end());

    return treeBegin;
}

int Abs::getvalue() {
    return l;
}

Node *Abs::reduce(Pool *pool) {
    return new(pool) Abs(l, r -> reduce(pool));
}

bool Abs::isredex() {
    return r -> isredex();
}

Node *Abs::substitute(Pool *pool, int free, int who, Node *with) {
    if (who == 0)
        return r -> substitute(pool, l, l, with);
    else
        return new(pool) Abs(free, r -> substitute(pool, free + 1, who, with));
}

Node *Abs::changeprior(Pool *pool, int prior, map<int, int> m) {
    int newl;
    if (l < 0)
        newl = l;
    else
        if (m.count(l))
            newl = m[l];
        else m[l] = newl = prior, prior++;

    return new(pool) Abs(newl, r -> changeprior(pool, prior, m));
}

Node *Abs::copy (Pool *pool) {
    return new(pool) Abs(l, r -> copy(pool));
}

Abs::~Abs() {
    delete r;
}
<commit_msg>Small bugfix in get_tree_view function<commit_after>#include "Abs.h"

void *Abs::operator new (size_t n, Pool *pool) {
    return pool -> palloc(sizeof(Abs));
}

void Abs::operator delete(void *ptr, Pool *pool){
    free(ptr);
}

void Abs::get_expression(ostream& out, string wrapEntity, Position position) {
    if (wrapEntity == "App")
        out << '(';

    out << '\\';
    out << l;
    out << '.';

    r -> get_expression(out, _entName, _left);

    if (wrapEntity == "App")
        out << ')';
}

vector<string> Abs::get_tree_view(int shift) {
    vector<string> treeBegin;
    treeBegin.push_back(string(shift, ' ') + _entName + _horizontalFirst + ' ' + char('0' + l));
    treeBegin.push_back(string(shift + _entName.size(), ' ') + _vertical);

    int newShift = shift + _entName.size() + _horizontalFirst.size() + 1;
    vector<string> treeEnd = r->get_tree_view(newShift);

    treeEnd[0].replace(shift + _entName.size(), _horizontalSecond.size(), _horizontalSecond);
    treeBegin.insert(treeBegin.end(), treeEnd.begin(), treeEnd.end());

    return treeBegin;
}

int Abs::getvalue() {
    return l;
}

Node *Abs::reduce(Pool *pool) {
    return new(pool) Abs(l, r -> reduce(pool));
}

bool Abs::isredex() {
    return r -> isredex();
}

Node *Abs::substitute(Pool *pool, int free, int who, Node *with) {
    if (who == 0)
        return r -> substitute(pool, l, l, with);
    else
        return new(pool) Abs(free, r -> substitute(pool, free + 1, who, with));
}

Node *Abs::changeprior(Pool *pool, int prior, map<int, int> m) {
    int newl;
    if (l < 0)
        newl = l;
    else
        if (m.count(l))
            newl = m[l];
        else m[l] = newl = prior, prior++;

    return new(pool) Abs(newl, r -> changeprior(pool, prior, m));
}

Node *Abs::copy (Pool *pool) {
    return new(pool) Abs(l, r -> copy(pool));
}

Abs::~Abs() {
    delete r;
}
<|endoftext|>


<commit_before>/*
  Copyright 2014 Sarah Wong

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "configuration.h"
#include "ui_configuration.h"

#include <QDebug>
#include <QResource>

#include <portaudiocpp/System.hxx>
#include <portaudiocpp/SystemHostApiIterator.hxx>
#include <portaudiocpp/SystemDeviceIterator.hxx>

#include "tinyscheme/scheme-private.h"
#include "tinyscheme/scheme.h"

namespace {

template <class IndexMapType, class ItemIter, class ItemType, class Callable1,
          class Callable2>
static void insertWithDefault(QComboBox *comboBox, IndexMapType &map,
                              ItemIter begin, ItemIter end,
                              ItemType& defaultItem,
			      Callable1 stringGenerator,
                              Callable2 mapItemGenerator) {
  int itemPosition = 0;

  comboBox->clear();
  map.clear();

  {
    map[itemPosition] = mapItemGenerator(defaultItem);

    comboBox->insertItem(itemPosition++,
                         QLatin1String("Default: ") + stringGenerator(defaultItem));
  }

  comboBox->insertSeparator(itemPosition++);

  while (begin != end) {
    ItemType& item = *begin;

    map[itemPosition] = mapItemGenerator(item);

    comboBox->insertItem(itemPosition++, stringGenerator(item));

    ++begin;
  }

}

struct GetDataFromResource {

  GetDataFromResource(const char *file)
  {
    QResource resource(file);
    Q_ASSERT(resource.isValid());
    if (resource.isCompressed())
      m_byteArray = qUncompress(resource.data(), resource.size());
    else
      m_byteArray = QByteArray(reinterpret_cast<const char*>(resource.data()), resource.size());
  }

  const QByteArray& byteArray() const { return m_byteArray; }

  QByteArray m_byteArray;
};

} // namespace anonymous

Configuration::Configuration(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Configuration)
{
  ui->setupUi(this);

  GetDataFromResource defaultConfigScm(":/tinyscheme/default-config.scm");
  ui->txtConfig->setPlainText(
      QString::fromUtf8(defaultConfigScm.byteArray().data(),
                        defaultConfigScm.byteArray().size()));

  portaudio::System& sys = portaudio::System::instance();

  insertWithDefault(
      ui->cmbAudioHost, m_indexToHostApiTypeId, sys.hostApisBegin(),
      sys.hostApisEnd(), sys.defaultHostApi(),
      [](portaudio::HostApi &hostApi) { return hostApi.name(); },
      [](portaudio::HostApi &hostApi) { return hostApi.typeId(); });
}

PaDeviceIndex Configuration::getDeviceIndex() const
{
  auto index = ui->cmbInputDevice->currentIndex();
  Q_ASSERT(index != -1);
  return m_indexToDeviceIndex[index];
}

void Configuration::on_cmbAudioHost_currentIndexChanged(int index)
{
  if (index == -1)
    return;

  portaudio::HostApi &hostApi = portaudio::System::instance().hostApiByTypeId(
      m_indexToHostApiTypeId[index]);

  insertWithDefault(
      ui->cmbInputDevice, m_indexToDeviceIndex,
      hostApi.devicesBegin(), hostApi.devicesEnd(), hostApi.defaultInputDevice(),
      [](portaudio::Device &device) { return device.name(); },
      [](portaudio::Device &device) { return device.index(); });

}

namespace {

struct Ptr {
  scheme *sc_;
  pointer p_;

  Ptr(scheme *sc, pointer p) : sc_(sc), p_(p) {}

  int is_nil          (pointer p) { return p == sc_->NIL; } //\n

  int is_string       (pointer p) { return sc_->vptr->is_string(p); }
  char *string_value  (pointer p) { return sc_->vptr->string_value(p); }
  int is_number       (pointer p) { return sc_->vptr->is_number(p); }
  num nvalue          (pointer p) { return sc_->vptr->nvalue(p); }
  long ivalue         (pointer p) { return sc_->vptr->ivalue(p); }
  double rvalue       (pointer p) { return sc_->vptr->rvalue(p); }
  int is_integer      (pointer p) { return sc_->vptr->is_integer(p); }
  int is_real         (pointer p) { return sc_->vptr->is_real(p); }
  int is_character    (pointer p) { return sc_->vptr->is_character(p); }
  long charvalue      (pointer p) { return sc_->vptr->charvalue(p); }
  int is_list         (pointer p) { return sc_->vptr->is_list(sc_, p); }
  int is_vector       (pointer p) { return sc_->vptr->is_vector(p); }
  int list_length     (pointer vec) { return sc_->vptr->list_length(sc_, vec); }
  long vector_length  (pointer vec) { return sc_->vptr->vector_length(vec); }
  pointer vector_elem (pointer vec, int ielem) { return sc_->vptr->vector_elem(vec, ielem); }
  int is_pair         (pointer p) { return sc_->vptr->is_pair(p); }
  pointer pair_car    (pointer p) { return sc_->vptr->pair_car(p); }
  pointer pair_cdr    (pointer p) { return sc_->vptr->pair_cdr(p); } //\n
  int is_symbol       (pointer p) { return sc_->vptr->is_symbol(p); }
  char *symname       (pointer p) { return sc_->vptr->symname(p); }

};

struct Config {
  Config(const char *configScript) : sc_(scheme_init_new())
  {
    Q_ASSERT(sc_ != nullptr);

    scheme_set_output_port_file(sc_, stdout);

    loadResource(":/tinyscheme/init.scm");
    loadResource(":/tinyscheme/config-helper.scm");

    read_eval("(begin (display 1337) (newline))");

    scheme_load_string(sc_, configScript);
    if (sc_->retcode != 0) qDebug() << "Scheme failed" << __LINE__;

    pointer ret = read_eval("(cdr (assv ':sample-rate (cdr (assv 'audio-config config))))");
    qDebug() << sc_->vptr->ivalue(ret);
  }

  void loadResource(const char *resource)
  {
    GetDataFromResource gdfr(resource);
    scheme_load_string(sc_, gdfr.byteArray().data());
  }

  pointer read_eval(const char* script)
  {
    // tinyscheme bug: When executing
    //
    //   (read (open-input-string script))
    //
    // sc_->inport needs to be set, or there will be an error when
    // read is restoring the previous inport value when returning.
    scheme_set_input_port_file(sc_, stdin); // TODO stdin?

    pointer fun = scheme_eval(sc_, mk_symbol(sc_, "read-eval"));
    pointer arg = mk_string(sc_, script);
    return scheme_call(sc_, fun, _cons(sc_, arg, sc_->NIL, 0));
  }

  scheme *sc_;
};

} // namespace anonymous

void Configuration::on_buttonBox_accepted()
{
  QString configText = ui->txtConfig->toPlainText();
  QByteArray configTextBa = configText.toUtf8();
  Config cfg(configTextBa.constData());

  emit accept();
}

Configuration::~Configuration()
{
    delete ui;
}
<commit_msg>Whitespace<commit_after>/*
  Copyright 2014 Sarah Wong

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "configuration.h"
#include "ui_configuration.h"

#include <QDebug>
#include <QResource>

#include <portaudiocpp/System.hxx>
#include <portaudiocpp/SystemHostApiIterator.hxx>
#include <portaudiocpp/SystemDeviceIterator.hxx>

#include "tinyscheme/scheme-private.h"
#include "tinyscheme/scheme.h"

namespace {

template <class IndexMapType, class ItemIter, class ItemType, class Callable1,
          class Callable2>
static void insertWithDefault(QComboBox *comboBox, IndexMapType &map,
                              ItemIter begin, ItemIter end,
                              ItemType& defaultItem,
			      Callable1 stringGenerator,
                              Callable2 mapItemGenerator) {
  int itemPosition = 0;

  comboBox->clear();
  map.clear();

  {
    map[itemPosition] = mapItemGenerator(defaultItem);

    comboBox->insertItem(itemPosition++,
                         QLatin1String("Default: ") + stringGenerator(defaultItem));
  }

  comboBox->insertSeparator(itemPosition++);

  while (begin != end) {
    ItemType& item = *begin;

    map[itemPosition] = mapItemGenerator(item);

    comboBox->insertItem(itemPosition++, stringGenerator(item));

    ++begin;
  }

}

struct GetDataFromResource {

  GetDataFromResource(const char *file)
  {
    QResource resource(file);
    Q_ASSERT(resource.isValid());
    if (resource.isCompressed())
      m_byteArray = qUncompress(resource.data(), resource.size());
    else
      m_byteArray = QByteArray(reinterpret_cast<const char*>(resource.data()), resource.size());
  }

  const QByteArray& byteArray() const { return m_byteArray; }

  QByteArray m_byteArray;
};

} // namespace anonymous

Configuration::Configuration(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Configuration)
{
  ui->setupUi(this);

  GetDataFromResource defaultConfigScm(":/tinyscheme/default-config.scm");
  ui->txtConfig->setPlainText(
      QString::fromUtf8(defaultConfigScm.byteArray().data(),
                        defaultConfigScm.byteArray().size()));

  portaudio::System& sys = portaudio::System::instance();

  insertWithDefault(
      ui->cmbAudioHost, m_indexToHostApiTypeId, sys.hostApisBegin(),
      sys.hostApisEnd(), sys.defaultHostApi(),
      [](portaudio::HostApi &hostApi) { return hostApi.name(); },
      [](portaudio::HostApi &hostApi) { return hostApi.typeId(); });
}

PaDeviceIndex Configuration::getDeviceIndex() const
{
  auto index = ui->cmbInputDevice->currentIndex();
  Q_ASSERT(index != -1);
  return m_indexToDeviceIndex[index];
}

void Configuration::on_cmbAudioHost_currentIndexChanged(int index)
{
  if (index == -1)
    return;

  portaudio::HostApi &hostApi = portaudio::System::instance().hostApiByTypeId(
      m_indexToHostApiTypeId[index]);

  insertWithDefault(
      ui->cmbInputDevice, m_indexToDeviceIndex,
      hostApi.devicesBegin(), hostApi.devicesEnd(), hostApi.defaultInputDevice(),
      [](portaudio::Device &device) { return device.name(); },
      [](portaudio::Device &device) { return device.index(); });

}

namespace {

struct Ptr {
  scheme *sc_;
  pointer p_;

  Ptr(scheme *sc, pointer p) : sc_(sc), p_(p) {}

  int is_nil          (pointer p)              { return p == sc_->NIL; } //\n
  int is_string       (pointer p)              { return sc_->vptr->is_string(p); }
  char *string_value  (pointer p)              { return sc_->vptr->string_value(p); }
  int is_number       (pointer p)              { return sc_->vptr->is_number(p); }
  num nvalue          (pointer p)              { return sc_->vptr->nvalue(p); }
  long ivalue         (pointer p)              { return sc_->vptr->ivalue(p); }
  double rvalue       (pointer p)              { return sc_->vptr->rvalue(p); }
  int is_integer      (pointer p)              { return sc_->vptr->is_integer(p); }
  int is_real         (pointer p)              { return sc_->vptr->is_real(p); }
  int is_character    (pointer p)              { return sc_->vptr->is_character(p); }
  long charvalue      (pointer p)              { return sc_->vptr->charvalue(p); }
  int is_list         (pointer p)              { return sc_->vptr->is_list(sc_, p); }
  int is_vector       (pointer p)              { return sc_->vptr->is_vector(p); }
  int list_length     (pointer vec)            { return sc_->vptr->list_length(sc_, vec); }
  long vector_length  (pointer vec)            { return sc_->vptr->vector_length(vec); }
  pointer vector_elem (pointer vec, int ielem) { return sc_->vptr->vector_elem(vec, ielem); }
  int is_pair         (pointer p)              { return sc_->vptr->is_pair(p); }
  pointer pair_car    (pointer p)              { return sc_->vptr->pair_car(p); }
  pointer pair_cdr    (pointer p)              { return sc_->vptr->pair_cdr(p); } //\n
  int is_symbol       (pointer p)              { return sc_->vptr->is_symbol(p); }
  char *symname       (pointer p)              { return sc_->vptr->symname(p); }

};

struct Config {
  Config(const char *configScript) : sc_(scheme_init_new())
  {
    Q_ASSERT(sc_ != nullptr);

    scheme_set_output_port_file(sc_, stdout);

    loadResource(":/tinyscheme/init.scm");
    loadResource(":/tinyscheme/config-helper.scm");

    read_eval("(begin (display 1337) (newline))");

    scheme_load_string(sc_, configScript);
    if (sc_->retcode != 0) qDebug() << "Scheme failed" << __LINE__;

    pointer ret = read_eval("(cdr (assv ':sample-rate (cdr (assv 'audio-config config))))");
    qDebug() << sc_->vptr->ivalue(ret);
  }

  void loadResource(const char *resource)
  {
    GetDataFromResource gdfr(resource);
    scheme_load_string(sc_, gdfr.byteArray().data());
  }

  pointer read_eval(const char* script)
  {
    // tinyscheme bug: When executing
    //
    //   (read (open-input-string script))
    //
    // sc_->inport needs to be set, or there will be an error when
    // read is restoring the previous inport value when returning.
    scheme_set_input_port_file(sc_, stdin); // TODO stdin?

    pointer fun = scheme_eval(sc_, mk_symbol(sc_, "read-eval"));
    pointer arg = mk_string(sc_, script);
    return scheme_call(sc_, fun, _cons(sc_, arg, sc_->NIL, 0));
  }

  scheme *sc_;
};

} // namespace anonymous

void Configuration::on_buttonBox_accepted()
{
  QString configText = ui->txtConfig->toPlainText();
  QByteArray configTextBa = configText.toUtf8();
  Config cfg(configTextBa.constData());

  emit accept();
}

Configuration::~Configuration()
{
    delete ui;
}
<|endoftext|>


<commit_before>#include "Application.h"
#include "MainMenuScene.h"
#include "SceneManager.h"

LRESULT WINAPI fakeWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    Application* app = reinterpret_cast<Application*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
    if (app != nullptr)
    {
        return app->WindowProc(hWnd, Msg, wParam, lParam);
    }
    else
    {
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
}

Application::Application()
    :_renderer(), _handle()
{
}

Application::~Application()
{
}

int Application::run(HINSTANCE hInstance, const int& nCmdShow)
{
    WNDCLASSEX wc = {0};
    wc.cbSize = sizeof(wc);
    wc.lpszClassName = "WND";
    wc.hInstance = hInstance;
    wc.lpfnWndProc = fakeWindowProc;
    wc.hCursor = LoadCursor(hInstance, IDC_ARROW);

    int ret = RegisterClassEx(&wc);

    _handle = CreateWindowEx(0, "WND", "15 PUZZLE", WS_OVERLAPPEDWINDOW, 0, 0, 500, 500, nullptr, nullptr, hInstance, nullptr);

    RECT clientRect = {0};
    GetClientRect(_handle, &clientRect);

    _renderer.init(_handle, clientRect.right, clientRect.bottom);

    SceneManager::getSingleton().setActiveScene(new MainMenuScene(&_renderer));

    ShowWindow(_handle, nCmdShow);

    MSG msg = {0};
    size_t frameCounter = 0;

    SetWindowLongPtr(_handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));

    while(true)
    {
        if (!IsWindow(_handle))
        {
            break;
        }

        if (PeekMessage(&msg, _handle, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            if (frameCounter == 10)
            {
                SceneManager::getSingleton().getActiveScene()->update();
                frameCounter = 0;
            }
            SceneManager::getSingleton().getActiveScene()->render();
            ++frameCounter;
        }
    }

    ret = UnregisterClass("WND", hInstance);

    return 0;
}

LRESULT WINAPI Application::WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch(Msg)
    {
    case WM_SIZE:
        {
            uint32_t width = LOWORD(lParam);
            uint32_t height = HIWORD(lParam);
            _renderer.resize(width, height);
        }
        return 0;

    default:
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
}<commit_msg>Application starts with GameScene now. All changes for main menu implementation will be moved into other branch<commit_after>#include "Application.h"
#include "GameScene.h"
#include "SceneManager.h"

LRESULT WINAPI fakeWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    Application* app = reinterpret_cast<Application*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
    if (app != nullptr)
    {
        return app->WindowProc(hWnd, Msg, wParam, lParam);
    }
    else
    {
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
}

Application::Application()
    :_renderer(), _handle()
{
}

Application::~Application()
{
}

int Application::run(HINSTANCE hInstance, const int& nCmdShow)
{
    WNDCLASSEX wc = {0};
    wc.cbSize = sizeof(wc);
    wc.lpszClassName = "WND";
    wc.hInstance = hInstance;
    wc.lpfnWndProc = fakeWindowProc;
    wc.hCursor = LoadCursor(hInstance, IDC_ARROW);

    int ret = RegisterClassEx(&wc);

    _handle = CreateWindowEx(0, "WND", "15 PUZZLE", WS_OVERLAPPEDWINDOW, 0, 0, 500, 500, nullptr, nullptr, hInstance, nullptr);

    RECT clientRect = {0};
    GetClientRect(_handle, &clientRect);

    _renderer.init(_handle, clientRect.right, clientRect.bottom);

    SceneManager::getSingleton().setActiveScene(new GameScene(&_renderer));

    ShowWindow(_handle, nCmdShow);

    MSG msg = {0};
    size_t frameCounter = 0;

    SetWindowLongPtr(_handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));

    while(true)
    {
        if (!IsWindow(_handle))
        {
            break;
        }

        if (PeekMessage(&msg, _handle, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            if (frameCounter == 10)
            {
                SceneManager::getSingleton().getActiveScene()->update();
                frameCounter = 0;
            }
            SceneManager::getSingleton().getActiveScene()->render();
            ++frameCounter;
        }
    }

    ret = UnregisterClass("WND", hInstance);

    return 0;
}

LRESULT WINAPI Application::WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch(Msg)
    {
    case WM_SIZE:
        {
            uint32_t width = LOWORD(lParam);
            uint32_t height = HIWORD(lParam);
            _renderer.resize(width, height);
        }
        return 0;

    default:
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
}<|endoftext|>