<commit_before>/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Clifford Wolf <clifford@symbioticeda.com>
 *  Copyright (C) 2018  David Shah <david@symbioticeda.com>
 *
 *  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 "cells.h"
#include "design_utils.h"
#include "log.h"

NEXTPNR_NAMESPACE_BEGIN

void add_port(const Context *ctx, CellInfo *cell, std::string name, PortType dir)
{
    IdString id = ctx->id(name);
    cell->ports[id] = PortInfo{id, nullptr, dir};
}

std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::string name)
{
    static int auto_idx = 0;
    std::unique_ptr<CellInfo> new_cell = std::unique_ptr<CellInfo>(new CellInfo());
    if (name.empty()) {
        new_cell->name = ctx->id("$nextpnr_" + type.str(ctx) + "_" + std::to_string(auto_idx++));
    } else {
        new_cell->name = ctx->id(name);
    }
    new_cell->type = type;
    if (type == ctx->id("ICESTORM_LC")) {
        new_cell->params[ctx->id("LUT_INIT")] = "0";
        new_cell->params[ctx->id("NEG_CLK")] = "0";
        new_cell->params[ctx->id("CARRY_ENABLE")] = "0";
        new_cell->params[ctx->id("DFF_ENABLE")] = "0";
        new_cell->params[ctx->id("SET_NORESET")] = "0";
        new_cell->params[ctx->id("ASYNC_SR")] = "0";
        new_cell->params[ctx->id("CIN_CONST")] = "0";
        new_cell->params[ctx->id("CIN_SET")] = "0";

        add_port(ctx, new_cell.get(), "I0", PORT_IN);
        add_port(ctx, new_cell.get(), "I1", PORT_IN);
        add_port(ctx, new_cell.get(), "I2", PORT_IN);
        add_port(ctx, new_cell.get(), "I3", PORT_IN);
        add_port(ctx, new_cell.get(), "CIN", PORT_IN);

        add_port(ctx, new_cell.get(), "CLK", PORT_IN);
        add_port(ctx, new_cell.get(), "CEN", PORT_IN);
        add_port(ctx, new_cell.get(), "SR", PORT_IN);

        add_port(ctx, new_cell.get(), "LO", PORT_OUT);
        add_port(ctx, new_cell.get(), "O", PORT_OUT);
        add_port(ctx, new_cell.get(), "OUT", PORT_OUT);
    } else if (type == ctx->id("SB_IO")) {
        new_cell->params[ctx->id("PIN_TYPE")] = "0";
        new_cell->params[ctx->id("PULLUP")] = "0";
        new_cell->params[ctx->id("NEG_TRIGGER")] = "0";
        new_cell->params[ctx->id("IOSTANDARD")] = "SB_LVCMOS";

        add_port(ctx, new_cell.get(), "PACKAGE_PIN", PORT_INOUT);

        add_port(ctx, new_cell.get(), "LATCH_INPUT_VALUE", PORT_IN);
        add_port(ctx, new_cell.get(), "CLOCK_ENABLE", PORT_IN);
        add_port(ctx, new_cell.get(), "INPUT_CLK", PORT_IN);
        add_port(ctx, new_cell.get(), "OUTPUT_CLK", PORT_IN);

        add_port(ctx, new_cell.get(), "OUTPUT_ENABLE", PORT_IN);
        add_port(ctx, new_cell.get(), "D_OUT_0", PORT_IN);
        add_port(ctx, new_cell.get(), "D_OUT_1", PORT_IN);

        add_port(ctx, new_cell.get(), "D_IN_0", PORT_OUT);
        add_port(ctx, new_cell.get(), "D_IN_1", PORT_OUT);
    } else if (type == ctx->id("ICESTORM_RAM")) {
        new_cell->params[ctx->id("NEG_CLK_W")] = "0";
        new_cell->params[ctx->id("NEG_CLK_R")] = "0";
        new_cell->params[ctx->id("WRITE_MODE")] = "0";
        new_cell->params[ctx->id("READ_MODE")] = "0";

        add_port(ctx, new_cell.get(), "RCLK", PORT_IN);
        add_port(ctx, new_cell.get(), "RCLKE", PORT_IN);
        add_port(ctx, new_cell.get(), "RE", PORT_IN);

        add_port(ctx, new_cell.get(), "WCLK", PORT_IN);
        add_port(ctx, new_cell.get(), "WCLKE", PORT_IN);
        add_port(ctx, new_cell.get(), "WE", PORT_IN);

        for (int i = 0; i < 16; i++) {
            add_port(ctx, new_cell.get(), "WDATA_" + std::to_string(i), PORT_IN);
            add_port(ctx, new_cell.get(), "MASK_" + std::to_string(i), PORT_IN);
            add_port(ctx, new_cell.get(), "RDATA_" + std::to_string(i), PORT_OUT);
        }

        for (int i = 0; i < 11; i++) {
            add_port(ctx, new_cell.get(), "RADDR_" + std::to_string(i), PORT_IN);
            add_port(ctx, new_cell.get(), "WADDR_" + std::to_string(i), PORT_IN);
        }
    } else if (type == ctx->id("ICESTORM_LFOSC")) {
        add_port(ctx, new_cell.get(), "CLKLFEN", PORT_IN);
        add_port(ctx, new_cell.get(), "CLKLFPU", PORT_IN);
        add_port(ctx, new_cell.get(), "CLKLF", PORT_OUT);
        add_port(ctx, new_cell.get(), "CLKLF_FABRIC", PORT_OUT);
    } else if (type == ctx->id("ICESTORM_HFOSC")) {
        new_cell->params[ctx->id("CLKHF_DIV")] = "0";
        new_cell->params[ctx->id("TRIM_EN")] = "0";

        add_port(ctx, new_cell.get(), "CLKHFEN", PORT_IN);
        add_port(ctx, new_cell.get(), "CLKHFPU", PORT_IN);
        add_port(ctx, new_cell.get(), "CLKHF", PORT_OUT);
        add_port(ctx, new_cell.get(), "CLKHF_FABRIC", PORT_OUT);
        for (int i = 0; i < 10; i++)
            add_port(ctx, new_cell.get(), "TRIM" + std::to_string(i), PORT_IN);
    } else if (type == ctx->id("SB_GB")) {
        add_port(ctx, new_cell.get(), "USER_SIGNAL_TO_GLOBAL_BUFFER", PORT_IN);
        add_port(ctx, new_cell.get(), "GLOBAL_BUFFER_OUTPUT", PORT_OUT);
    } else {
        log_error("unable to create iCE40 cell of type %s", type.c_str(ctx));
    }
    return std::move(new_cell);
}

void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
{
    lc->params[ctx->id("LUT_INIT")] = lut->params[ctx->id("LUT_INIT")];
    replace_port(lut, ctx->id("I0"), lc, ctx->id("I0"));
    replace_port(lut, ctx->id("I1"), lc, ctx->id("I1"));
    replace_port(lut, ctx->id("I2"), lc, ctx->id("I2"));
    replace_port(lut, ctx->id("I3"), lc, ctx->id("I3"));
    if (no_dff) {
        replace_port(lut, ctx->id("O"), lc, ctx->id("O"));
        lc->params[ctx->id("DFF_ENABLE")] = "0";
    }
}

void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut)
{
    lc->params[ctx->id("DFF_ENABLE")] = "1";
    std::string config = dff->type.str(ctx).substr(6);
    auto citer = config.begin();
    replace_port(dff, ctx->id("C"), lc, ctx->id("CLK"));

    if (citer != config.end() && *citer == 'N') {
        lc->params[ctx->id("NEG_CLK")] = "1";
        ++citer;
    } else {
        lc->params[ctx->id("NEG_CLK")] = "0";
    }

    if (citer != config.end() && *citer == 'E') {
        replace_port(dff, ctx->id("E"), lc, ctx->id("CEN"));
        ++citer;
    }

    if (citer != config.end()) {
        if ((config.end() - citer) >= 2) {
            char c = *(citer++);
            assert(c == 'S');
            lc->params[ctx->id("ASYNC_SR")] = "0";
        } else {
            lc->params[ctx->id("ASYNC_SR")] = "1";
        }

        if (*citer == 'S') {
            citer++;
            replace_port(dff, ctx->id("S"), lc, ctx->id("SR"));
            lc->params[ctx->id("SET_NORESET")] = "1";
        } else {
            assert(*citer == 'R');
            citer++;
            replace_port(dff, ctx->id("R"), lc, ctx->id("SR"));
            lc->params[ctx->id("SET_NORESET")] = "0";
        }
    }

    assert(citer == config.end());

    if (pass_thru_lut) {
        lc->params[ctx->id("LUT_INIT")] = "2";
        replace_port(dff, ctx->id("D"), lc, ctx->id("I0"));
    }

    replace_port(dff, ctx->id("Q"), lc, ctx->id("O"));
}

void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio)
{
    if (nxio->type == ctx->id("$nextpnr_ibuf")) {
        sbio->params[ctx->id("PIN_TYPE")] = "1";
        auto pu_attr = nxio->attrs.find(ctx->id("PULLUP"));
        if (pu_attr != nxio->attrs.end())
            sbio->params[ctx->id("PULLUP")] = pu_attr->second;
        replace_port(nxio, ctx->id("O"), sbio, ctx->id("D_IN_0"));
    } else if (nxio->type == ctx->id("$nextpnr_obuf")) {
        sbio->params[ctx->id("PIN_TYPE")] = "25";
        replace_port(nxio, ctx->id("I"), sbio, ctx->id("D_OUT_0"));
    } else if (nxio->type == ctx->id("$nextpnr_iobuf")) {
        // N.B. tristate will be dealt with below
        sbio->params[ctx->id("PIN_TYPE")] = "25";
        replace_port(nxio, ctx->id("I"), sbio, ctx->id("D_OUT_0"));
        replace_port(nxio, ctx->id("O"), sbio, ctx->id("D_IN_0"));
    } else {
        assert(false);
    }
    NetInfo *donet = sbio->ports.at(ctx->id("D_OUT_0")).net;
    CellInfo *tbuf = net_driven_by(
            ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); },
            ctx->id("Y"));
    if (tbuf) {
        sbio->params[ctx->id("PIN_TYPE")] = "41";
        replace_port(tbuf, ctx->id("A"), sbio, ctx->id("D_OUT_0"));
        replace_port(tbuf, ctx->id("E"), sbio, ctx->id("OUTPUT_ENABLE"));
        ctx->nets.erase(donet->name);
        if (!donet->users.empty())
            log_error("unsupported tristate IO pattern for IO buffer '%s', "
                      "instantiate SB_IO manually to ensure correct behaviour\n",
                      nxio->name.c_str(ctx));
        ctx->cells.erase(tbuf->name);
    }
}

bool is_clock_port(const BaseCtx *ctx, const PortRef &port)
{
    if (port.cell == nullptr)
        return false;
    if (is_ff(ctx, port.cell))
        return port.port == ctx->id("C");
    if (port.cell->type == ctx->id("ICESTORM_LC"))
        return port.port == ctx->id("CLK");
    if (is_ram(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_RAM"))
        return port.port == ctx->id("RCLK") || port.port == ctx->id("WCLK");
    return false;
}

bool is_reset_port(const BaseCtx *ctx, const PortRef &port)
{
    if (port.cell == nullptr)
        return false;
    if (is_ff(ctx, port.cell))
        return port.port == ctx->id("R") || port.port == ctx->id("S");
    if (port.cell->type == ctx->id("ICESTORM_LC"))
        return port.port == ctx->id("SR");
    return false;
}

bool is_enable_port(const BaseCtx *ctx, const PortRef &port)
{
    if (port.cell == nullptr)
        return false;
    if (is_ff(ctx, port.cell))
        return port.port == ctx->id("E");
    if (port.cell->type == ctx->id("ICESTORM_LC"))
        return port.port == ctx->id("CEN");
    return false;
}

NEXTPNR_NAMESPACE_END
<commit_msg>clang fix<commit_after>/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Clifford Wolf <clifford@symbioticeda.com>
 *  Copyright (C) 2018  David Shah <david@symbioticeda.com>
 *
 *  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 "cells.h"
#include "design_utils.h"
#include "log.h"

NEXTPNR_NAMESPACE_BEGIN

void add_port(const Context *ctx, CellInfo *cell, std::string name, PortType dir)
{
    IdString id = ctx->id(name);
    cell->ports[id] = PortInfo{id, nullptr, dir};
}

std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::string name)
{
    static int auto_idx = 0;
    std::unique_ptr<CellInfo> new_cell = std::unique_ptr<CellInfo>(new CellInfo());
    if (name.empty()) {
        new_cell->name = ctx->id("$nextpnr_" + type.str(ctx) + "_" + std::to_string(auto_idx++));
    } else {
        new_cell->name = ctx->id(name);
    }
    new_cell->type = type;
    if (type == ctx->id("ICESTORM_LC")) {
        new_cell->params[ctx->id("LUT_INIT")] = "0";
        new_cell->params[ctx->id("NEG_CLK")] = "0";
        new_cell->params[ctx->id("CARRY_ENABLE")] = "0";
        new_cell->params[ctx->id("DFF_ENABLE")] = "0";
        new_cell->params[ctx->id("SET_NORESET")] = "0";
        new_cell->params[ctx->id("ASYNC_SR")] = "0";
        new_cell->params[ctx->id("CIN_CONST")] = "0";
        new_cell->params[ctx->id("CIN_SET")] = "0";

        add_port(ctx, new_cell.get(), "I0", PORT_IN);
        add_port(ctx, new_cell.get(), "I1", PORT_IN);
        add_port(ctx, new_cell.get(), "I2", PORT_IN);
        add_port(ctx, new_cell.get(), "I3", PORT_IN);
        add_port(ctx, new_cell.get(), "CIN", PORT_IN);

        add_port(ctx, new_cell.get(), "CLK", PORT_IN);
        add_port(ctx, new_cell.get(), "CEN", PORT_IN);
        add_port(ctx, new_cell.get(), "SR", PORT_IN);

        add_port(ctx, new_cell.get(), "LO", PORT_OUT);
        add_port(ctx, new_cell.get(), "O", PORT_OUT);
        add_port(ctx, new_cell.get(), "OUT", PORT_OUT);
    } else if (type == ctx->id("SB_IO")) {
        new_cell->params[ctx->id("PIN_TYPE")] = "0";
        new_cell->params[ctx->id("PULLUP")] = "0";
        new_cell->params[ctx->id("NEG_TRIGGER")] = "0";
        new_cell->params[ctx->id("IOSTANDARD")] = "SB_LVCMOS";

        add_port(ctx, new_cell.get(), "PACKAGE_PIN", PORT_INOUT);

        add_port(ctx, new_cell.get(), "LATCH_INPUT_VALUE", PORT_IN);
        add_port(ctx, new_cell.get(), "CLOCK_ENABLE", PORT_IN);
        add_port(ctx, new_cell.get(), "INPUT_CLK", PORT_IN);
        add_port(ctx, new_cell.get(), "OUTPUT_CLK", PORT_IN);

        add_port(ctx, new_cell.get(), "OUTPUT_ENABLE", PORT_IN);
        add_port(ctx, new_cell.get(), "D_OUT_0", PORT_IN);
        add_port(ctx, new_cell.get(), "D_OUT_1", PORT_IN);

        add_port(ctx, new_cell.get(), "D_IN_0", PORT_OUT);
        add_port(ctx, new_cell.get(), "D_IN_1", PORT_OUT);
    } else if (type == ctx->id("ICESTORM_RAM")) {
        new_cell->params[ctx->id("NEG_CLK_W")] = "0";
        new_cell->params[ctx->id("NEG_CLK_R")] = "0";
        new_cell->params[ctx->id("WRITE_MODE")] = "0";
        new_cell->params[ctx->id("READ_MODE")] = "0";

        add_port(ctx, new_cell.get(), "RCLK", PORT_IN);
        add_port(ctx, new_cell.get(), "RCLKE", PORT_IN);
        add_port(ctx, new_cell.get(), "RE", PORT_IN);

        add_port(ctx, new_cell.get(), "WCLK", PORT_IN);
        add_port(ctx, new_cell.get(), "WCLKE", PORT_IN);
        add_port(ctx, new_cell.get(), "WE", PORT_IN);

        for (int i = 0; i < 16; i++) {
            add_port(ctx, new_cell.get(), "WDATA_" + std::to_string(i), PORT_IN);
            add_port(ctx, new_cell.get(), "MASK_" + std::to_string(i), PORT_IN);
            add_port(ctx, new_cell.get(), "RDATA_" + std::to_string(i), PORT_OUT);
        }

        for (int i = 0; i < 11; i++) {
            add_port(ctx, new_cell.get(), "RADDR_" + std::to_string(i), PORT_IN);
            add_port(ctx, new_cell.get(), "WADDR_" + std::to_string(i), PORT_IN);
        }
    } else if (type == ctx->id("ICESTORM_LFOSC")) {
        add_port(ctx, new_cell.get(), "CLKLFEN", PORT_IN);
        add_port(ctx, new_cell.get(), "CLKLFPU", PORT_IN);
        add_port(ctx, new_cell.get(), "CLKLF", PORT_OUT);
        add_port(ctx, new_cell.get(), "CLKLF_FABRIC", PORT_OUT);
    } else if (type == ctx->id("ICESTORM_HFOSC")) {
        new_cell->params[ctx->id("CLKHF_DIV")] = "0";
        new_cell->params[ctx->id("TRIM_EN")] = "0";

        add_port(ctx, new_cell.get(), "CLKHFEN", PORT_IN);
        add_port(ctx, new_cell.get(), "CLKHFPU", PORT_IN);
        add_port(ctx, new_cell.get(), "CLKHF", PORT_OUT);
        add_port(ctx, new_cell.get(), "CLKHF_FABRIC", PORT_OUT);
        for (int i = 0; i < 10; i++)
            add_port(ctx, new_cell.get(), "TRIM" + std::to_string(i), PORT_IN);
    } else if (type == ctx->id("SB_GB")) {
        add_port(ctx, new_cell.get(), "USER_SIGNAL_TO_GLOBAL_BUFFER", PORT_IN);
        add_port(ctx, new_cell.get(), "GLOBAL_BUFFER_OUTPUT", PORT_OUT);
    } else {
        log_error("unable to create iCE40 cell of type %s", type.c_str(ctx));
    }
    return new_cell;
}

void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
{
    lc->params[ctx->id("LUT_INIT")] = lut->params[ctx->id("LUT_INIT")];
    replace_port(lut, ctx->id("I0"), lc, ctx->id("I0"));
    replace_port(lut, ctx->id("I1"), lc, ctx->id("I1"));
    replace_port(lut, ctx->id("I2"), lc, ctx->id("I2"));
    replace_port(lut, ctx->id("I3"), lc, ctx->id("I3"));
    if (no_dff) {
        replace_port(lut, ctx->id("O"), lc, ctx->id("O"));
        lc->params[ctx->id("DFF_ENABLE")] = "0";
    }
}

void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut)
{
    lc->params[ctx->id("DFF_ENABLE")] = "1";
    std::string config = dff->type.str(ctx).substr(6);
    auto citer = config.begin();
    replace_port(dff, ctx->id("C"), lc, ctx->id("CLK"));

    if (citer != config.end() && *citer == 'N') {
        lc->params[ctx->id("NEG_CLK")] = "1";
        ++citer;
    } else {
        lc->params[ctx->id("NEG_CLK")] = "0";
    }

    if (citer != config.end() && *citer == 'E') {
        replace_port(dff, ctx->id("E"), lc, ctx->id("CEN"));
        ++citer;
    }

    if (citer != config.end()) {
        if ((config.end() - citer) >= 2) {
            char c = *(citer++);
            assert(c == 'S');
            lc->params[ctx->id("ASYNC_SR")] = "0";
        } else {
            lc->params[ctx->id("ASYNC_SR")] = "1";
        }

        if (*citer == 'S') {
            citer++;
            replace_port(dff, ctx->id("S"), lc, ctx->id("SR"));
            lc->params[ctx->id("SET_NORESET")] = "1";
        } else {
            assert(*citer == 'R');
            citer++;
            replace_port(dff, ctx->id("R"), lc, ctx->id("SR"));
            lc->params[ctx->id("SET_NORESET")] = "0";
        }
    }

    assert(citer == config.end());

    if (pass_thru_lut) {
        lc->params[ctx->id("LUT_INIT")] = "2";
        replace_port(dff, ctx->id("D"), lc, ctx->id("I0"));
    }

    replace_port(dff, ctx->id("Q"), lc, ctx->id("O"));
}

void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio)
{
    if (nxio->type == ctx->id("$nextpnr_ibuf")) {
        sbio->params[ctx->id("PIN_TYPE")] = "1";
        auto pu_attr = nxio->attrs.find(ctx->id("PULLUP"));
        if (pu_attr != nxio->attrs.end())
            sbio->params[ctx->id("PULLUP")] = pu_attr->second;
        replace_port(nxio, ctx->id("O"), sbio, ctx->id("D_IN_0"));
    } else if (nxio->type == ctx->id("$nextpnr_obuf")) {
        sbio->params[ctx->id("PIN_TYPE")] = "25";
        replace_port(nxio, ctx->id("I"), sbio, ctx->id("D_OUT_0"));
    } else if (nxio->type == ctx->id("$nextpnr_iobuf")) {
        // N.B. tristate will be dealt with below
        sbio->params[ctx->id("PIN_TYPE")] = "25";
        replace_port(nxio, ctx->id("I"), sbio, ctx->id("D_OUT_0"));
        replace_port(nxio, ctx->id("O"), sbio, ctx->id("D_IN_0"));
    } else {
        assert(false);
    }
    NetInfo *donet = sbio->ports.at(ctx->id("D_OUT_0")).net;
    CellInfo *tbuf = net_driven_by(
            ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); },
            ctx->id("Y"));
    if (tbuf) {
        sbio->params[ctx->id("PIN_TYPE")] = "41";
        replace_port(tbuf, ctx->id("A"), sbio, ctx->id("D_OUT_0"));
        replace_port(tbuf, ctx->id("E"), sbio, ctx->id("OUTPUT_ENABLE"));
        ctx->nets.erase(donet->name);
        if (!donet->users.empty())
            log_error("unsupported tristate IO pattern for IO buffer '%s', "
                      "instantiate SB_IO manually to ensure correct behaviour\n",
                      nxio->name.c_str(ctx));
        ctx->cells.erase(tbuf->name);
    }
}

bool is_clock_port(const BaseCtx *ctx, const PortRef &port)
{
    if (port.cell == nullptr)
        return false;
    if (is_ff(ctx, port.cell))
        return port.port == ctx->id("C");
    if (port.cell->type == ctx->id("ICESTORM_LC"))
        return port.port == ctx->id("CLK");
    if (is_ram(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_RAM"))
        return port.port == ctx->id("RCLK") || port.port == ctx->id("WCLK");
    return false;
}

bool is_reset_port(const BaseCtx *ctx, const PortRef &port)
{
    if (port.cell == nullptr)
        return false;
    if (is_ff(ctx, port.cell))
        return port.port == ctx->id("R") || port.port == ctx->id("S");
    if (port.cell->type == ctx->id("ICESTORM_LC"))
        return port.port == ctx->id("SR");
    return false;
}

bool is_enable_port(const BaseCtx *ctx, const PortRef &port)
{
    if (port.cell == nullptr)
        return false;
    if (is_ff(ctx, port.cell))
        return port.port == ctx->id("E");
    if (port.cell->type == ctx->id("ICESTORM_LC"))
        return port.port == ctx->id("CEN");
    return false;
}

NEXTPNR_NAMESPACE_END
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkContourFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
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 name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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 REGENTS 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 <math.h>
#include "vtkContourFilter.h"
#include "vtkScalars.h"
#include "vtkCell.h"
#include "vtkMergePoints.h"
#include "vtkContourValues.h"
#include "vtkScalarTree.h"
#include "vtkObjectFactory.h"
#include "vtkTimerLog.h"
#include "vtkUnstructuredGrid.h"
#include "vtkContourGrid.h"

//------------------------------------------------------------------------------
vtkContourFilter* vtkContourFilter::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkContourFilter");
  if(ret)
    {
    return (vtkContourFilter*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkContourFilter;
}

// Construct object with initial range (0,1) and single contour value
// of 0.0.
vtkContourFilter::vtkContourFilter()
{
  this->ContourValues = vtkContourValues::New();

  this->ComputeNormals = 1;
  this->ComputeGradients = 0;
  this->ComputeScalars = 1;

  this->Locator = NULL;

  this->UseScalarTree = 0;
  this->ScalarTree = NULL;
}

vtkContourFilter::~vtkContourFilter()
{
  this->ContourValues->Delete();
  if ( this->Locator )
    {
    this->Locator->UnRegister(this);
    this->Locator = NULL;
    }
  if ( this->ScalarTree )
    {
    this->ScalarTree->Delete();
    }
}

// Overload standard modified time function. If contour values are modified,
// then this object is modified as well.
unsigned long vtkContourFilter::GetMTime()
{
  unsigned long mTime=this->vtkDataSetToPolyDataFilter::GetMTime();
  unsigned long time;

  if (this->ContourValues)
    {
    time = this->ContourValues->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }
  if (this->Locator)
    {
    time = this->Locator->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }

  return mTime;
}

//
// General contouring filter.  Handles arbitrary input.
//
void vtkContourFilter::Execute()
{
  int cellId, i, abortExecute=0;
  vtkIdList *cellPts;
  vtkScalars *inScalars;
  vtkCell *cell;
  float range[2];
  vtkCellArray *newVerts, *newLines, *newPolys;
  vtkPoints *newPts;
  vtkDataSet *input=this->GetInput();
  vtkPolyData *output=this->GetOutput();
  int numCells, estimatedSize;
  vtkPointData *inPd=input->GetPointData(), *outPd=output->GetPointData();
  vtkCellData *inCd=input->GetCellData(), *outCd=output->GetCellData();
  int numContours=this->ContourValues->GetNumberOfContours();
  float *values=this->ContourValues->GetValues();
  vtkScalars *cellScalars;
	vtkTimerLog *timer = vtkTimerLog::New();

	timer->StartTimer();
  vtkDebugMacro(<< "Executing contour filter");

	if (input->GetDataObjectType() == VTK_UNSTRUCTURED_GRID)
		{
		vtkContourGrid *cgrid;

		cgrid = vtkContourGrid::New();
		cgrid->SetInput(input);
		cgrid->Update();
		output = cgrid->GetOutput();
		} //if type VTK_UNSTRUCTURED_GRID
	else
		{
		numCells = input->GetNumberOfCells();
	  inScalars = input->GetPointData()->GetScalars();
		if ( ! inScalars || numCells < 1 )
			{
			vtkErrorMacro(<<"No data to contour");
			return;
			}

		inScalars->GetRange(range);
//
// Create objects to hold output of contour operation. First estimate allocation size.
//
	  estimatedSize = (int) pow ((double) numCells, .75);
	  estimatedSize *= numContours;
	  estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024
	  if (estimatedSize < 1024)
	    {
	    estimatedSize = 1024;
	    }

	  newPts = vtkPoints::New();
	  newPts->Allocate(estimatedSize,estimatedSize);
	  newVerts = vtkCellArray::New();
	  newVerts->Allocate(estimatedSize,estimatedSize);
	  newLines = vtkCellArray::New();
	  newLines->Allocate(estimatedSize,estimatedSize);
	  newPolys = vtkCellArray::New();
	  newPolys->Allocate(estimatedSize,estimatedSize);
	  cellScalars = vtkScalars::New();
	  cellScalars->Allocate(VTK_CELL_SIZE);

   // locator used to merge potentially duplicate points
	  if ( this->Locator == NULL )
		  {
			this->CreateDefaultLocator();
			}
		this->Locator->InitPointInsertion (newPts, input->GetBounds(),estimatedSize);

  // interpolate data along edge
  // if we did not ask for scalars to be computed, don't copy them
		if (!this->ComputeScalars)
		  {
		  outPd->CopyScalarsOff();
		  }
		outPd->InterpolateAllocate(inPd,estimatedSize,estimatedSize);
		outCd->CopyAllocate(inCd,estimatedSize,estimatedSize);

  // If enabled, build a scalar tree to accelerate search
  //
		if ( !this->UseScalarTree )
		  {
		  for (cellId=0; cellId < numCells && !abortExecute; cellId++)
		    {
			  cell = input->GetCell(cellId);
				cellPts = cell->GetPointIds();
			  inScalars->GetScalars(cellPts,cellScalars);

			  if ( ! (cellId % 5000) )
				  {
					vtkDebugMacro(<<"Contouring #" << cellId);
					this->UpdateProgress ((float)cellId/numCells);
					if (this->GetAbortExecute())
					  {
					  abortExecute = 1;
					  break;
					  }
					}

				for (i=0; i < numContours; i++)
					{
					cell->Contour(values[i], cellScalars, this->Locator,
					              newVerts, newLines, newPolys, inPd, outPd,
												inCd, cellId, outCd);

					} // for all contour values
				} // for all cells
			} //if using scalar tree
		else
			{
			if ( this->ScalarTree == NULL )
			  {
			this->ScalarTree = vtkScalarTree::New();
			  }
			this->ScalarTree->SetDataSet(input);
			//
			// Loop over all contour values.  Then for each contour value,
			// loop over all cells.
			//
			for (i=0; i < numContours; i++)
				{
				for ( this->ScalarTree->InitTraversal(values[i]);
						(cell=this->ScalarTree->GetNextCell(cellId,cellPts,cellScalars)) != NULL; )
					{
					cell->Contour(values[i], cellScalars, this->Locator,
						            newVerts, newLines, newPolys, inPd, outPd,
												inCd, cellId, outCd);

					} //for all cells
				} //for all contour values
			} //using scalar tree
		} //else (for if vtkUnstructuredGrid)

	vtkDebugMacro(<<"Created: "
			          << newPts->GetNumberOfPoints() << " points, "
				        << newVerts->GetNumberOfCells() << " verts, "
						    << newLines->GetNumberOfCells() << " lines, "
							  << newPolys->GetNumberOfCells() << " triangles");
  //
  // Update ourselves.  Because we don't know up front how many verts, lines,
  // polys we've created, take care to reclaim memory.
  //
	output->SetPoints(newPts);
	newPts->Delete();
	cellScalars->Delete();

	if (newVerts->GetNumberOfCells())
		{
		output->SetVerts(newVerts);
		}
	newVerts->Delete();

	if (newLines->GetNumberOfCells())
	   {
	  output->SetLines(newLines);
	  }
	newLines->Delete();

	if (newPolys->GetNumberOfCells())
		{
		output->SetPolys(newPolys);
		}
	newPolys->Delete();

	this->Locator->Initialize();//releases leftover memory
	output->Squeeze();

	timer->StopTimer();
	vtkErrorMacro(<<"elapsed time: " << timer->GetElapsedTime());
	timer->Delete();
}

// Specify a spatial locator for merging points. By default,
// an instance of vtkMergePoints is used.
void vtkContourFilter::SetLocator(vtkPointLocator *locator)
{
  if ( this->Locator == locator )
    {
    return;
    }
  if ( this->Locator )
    {
    this->Locator->UnRegister(this);
    this->Locator = NULL;
    }
  if ( locator )
    {
    locator->Register(this);
    }
  this->Locator = locator;
  this->Modified();
}

void vtkContourFilter::CreateDefaultLocator()
{
  if ( this->Locator == NULL )
    {
    this->Locator = vtkMergePoints::New();
    }
}

void vtkContourFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToPolyDataFilter::PrintSelf(os,indent);

  os << indent << "Compute Gradients: " << (this->ComputeGradients ? "On\n" : "Off\n");
  os << indent << "Compute Normals: " << (this->ComputeNormals ? "On\n" : "Off\n");
  os << indent << "Compute Scalars: " << (this->ComputeScalars ? "On\n" : "Off\n");
  os << indent << "Use Scalar Tree: " << (this->UseScalarTree ? "On\n" : "Off\n");

  this->ContourValues->PrintSelf(os,indent);

  if ( this->Locator )
    {
    os << indent << "Locator: " << this->Locator << "\n";
    }
  else
    {
    os << indent << "Locator: (none)\n";
    }
}

<commit_msg>This moves the calls to Delete for objects being created only if we do not have an unstructured grid inside the appropriate if statement.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkContourFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
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 name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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 REGENTS 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 <math.h>
#include "vtkContourFilter.h"
#include "vtkScalars.h"
#include "vtkCell.h"
#include "vtkMergePoints.h"
#include "vtkContourValues.h"
#include "vtkScalarTree.h"
#include "vtkObjectFactory.h"
#include "vtkTimerLog.h"
#include "vtkUnstructuredGrid.h"
#include "vtkContourGrid.h"

//------------------------------------------------------------------------------
vtkContourFilter* vtkContourFilter::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkContourFilter");
  if(ret)
    {
    return (vtkContourFilter*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkContourFilter;
}

// Construct object with initial range (0,1) and single contour value
// of 0.0.
vtkContourFilter::vtkContourFilter()
{
  this->ContourValues = vtkContourValues::New();

  this->ComputeNormals = 1;
  this->ComputeGradients = 0;
  this->ComputeScalars = 1;

  this->Locator = NULL;

  this->UseScalarTree = 0;
  this->ScalarTree = NULL;
}

vtkContourFilter::~vtkContourFilter()
{
  this->ContourValues->Delete();
  if ( this->Locator )
    {
    this->Locator->UnRegister(this);
    this->Locator = NULL;
    }
  if ( this->ScalarTree )
    {
    this->ScalarTree->Delete();
    }
}

// Overload standard modified time function. If contour values are modified,
// then this object is modified as well.
unsigned long vtkContourFilter::GetMTime()
{
  unsigned long mTime=this->vtkDataSetToPolyDataFilter::GetMTime();
  unsigned long time;

  if (this->ContourValues)
    {
    time = this->ContourValues->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }
  if (this->Locator)
    {
    time = this->Locator->GetMTime();
    mTime = ( time > mTime ? time : mTime );
    }

  return mTime;
}

//
// General contouring filter.  Handles arbitrary input.
//
void vtkContourFilter::Execute()
{
  int cellId, i, abortExecute=0;
  vtkIdList *cellPts;
  vtkScalars *inScalars;
  vtkCell *cell;
  float range[2];
  vtkCellArray *newVerts, *newLines, *newPolys;
  vtkPoints *newPts;
  vtkDataSet *input=this->GetInput();
  vtkPolyData *output=this->GetOutput();
  int numCells, estimatedSize;
  vtkPointData *inPd=input->GetPointData(), *outPd=output->GetPointData();
  vtkCellData *inCd=input->GetCellData(), *outCd=output->GetCellData();
  int numContours=this->ContourValues->GetNumberOfContours();
  float *values=this->ContourValues->GetValues();
  vtkScalars *cellScalars;

  vtkDebugMacro(<< "Executing contour filter");

	if (input->GetDataObjectType() == VTK_UNSTRUCTURED_GRID)
		{
		vtkContourGrid *cgrid;

		cgrid = vtkContourGrid::New();
		cgrid->SetInput(input);
		cgrid->Update();
		output = cgrid->GetOutput();
		} //if type VTK_UNSTRUCTURED_GRID
	else
		{
		numCells = input->GetNumberOfCells();
	  inScalars = input->GetPointData()->GetScalars();
		if ( ! inScalars || numCells < 1 )
			{
			vtkErrorMacro(<<"No data to contour");
			return;
			}

		inScalars->GetRange(range);
//
// Create objects to hold output of contour operation. First estimate allocation size.
//
	  estimatedSize = (int) pow ((double) numCells, .75);
	  estimatedSize *= numContours;
	  estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024
	  if (estimatedSize < 1024)
	    {
	    estimatedSize = 1024;
	    }

	  newPts = vtkPoints::New();
	  newPts->Allocate(estimatedSize,estimatedSize);
	  newVerts = vtkCellArray::New();
	  newVerts->Allocate(estimatedSize,estimatedSize);
	  newLines = vtkCellArray::New();
	  newLines->Allocate(estimatedSize,estimatedSize);
	  newPolys = vtkCellArray::New();
	  newPolys->Allocate(estimatedSize,estimatedSize);
	  cellScalars = vtkScalars::New();
	  cellScalars->Allocate(VTK_CELL_SIZE);

   // locator used to merge potentially duplicate points
	  if ( this->Locator == NULL )
		  {
			this->CreateDefaultLocator();
			}
		this->Locator->InitPointInsertion (newPts, input->GetBounds(),estimatedSize);

  // interpolate data along edge
  // if we did not ask for scalars to be computed, don't copy them
		if (!this->ComputeScalars)
		  {
		  outPd->CopyScalarsOff();
		  }
		outPd->InterpolateAllocate(inPd,estimatedSize,estimatedSize);
		outCd->CopyAllocate(inCd,estimatedSize,estimatedSize);

  // If enabled, build a scalar tree to accelerate search
  //
		if ( !this->UseScalarTree )
		  {
		  for (cellId=0; cellId < numCells && !abortExecute; cellId++)
		    {
			  cell = input->GetCell(cellId);
				cellPts = cell->GetPointIds();
			  inScalars->GetScalars(cellPts,cellScalars);

			  if ( ! (cellId % 5000) )
				  {
					vtkDebugMacro(<<"Contouring #" << cellId);
					this->UpdateProgress ((float)cellId/numCells);
					if (this->GetAbortExecute())
					  {
					  abortExecute = 1;
					  break;
					  }
					}

				for (i=0; i < numContours; i++)
					{
					cell->Contour(values[i], cellScalars, this->Locator,
					              newVerts, newLines, newPolys, inPd, outPd,
												inCd, cellId, outCd);

					} // for all contour values
				} // for all cells
			} //if using scalar tree
		else
			{
			if ( this->ScalarTree == NULL )
			  {
			this->ScalarTree = vtkScalarTree::New();
			  }
			this->ScalarTree->SetDataSet(input);
			//
			// Loop over all contour values.  Then for each contour value,
			// loop over all cells.
			//
			for (i=0; i < numContours; i++)
				{
				for ( this->ScalarTree->InitTraversal(values[i]);
						(cell=this->ScalarTree->GetNextCell(cellId,cellPts,cellScalars)) != NULL; )
					{
					cell->Contour(values[i], cellScalars, this->Locator,
						            newVerts, newLines, newPolys, inPd, outPd,
												inCd, cellId, outCd);

					} //for all cells
				} //for all contour values
			} //using scalar tree

		vtkDebugMacro(<<"Created: "
				          << newPts->GetNumberOfPoints() << " points, "
					        << newVerts->GetNumberOfCells() << " verts, "
							    << newLines->GetNumberOfCells() << " lines, "
								  << newPolys->GetNumberOfCells() << " triangles");
		//
		// Update ourselves.  Because we don't know up front how many verts, lines,
		// polys we've created, take care to reclaim memory.
		//
		output->SetPoints(newPts);
		newPts->Delete();
		cellScalars->Delete();

		if (newVerts->GetNumberOfCells())
			{
			output->SetVerts(newVerts);
			}
		newVerts->Delete();

		if (newLines->GetNumberOfCells())
			{
			output->SetLines(newLines);
			}
		newLines->Delete();

		if (newPolys->GetNumberOfCells())
			{
			output->SetPolys(newPolys);
			}
		newPolys->Delete();

		this->Locator->Initialize();//releases leftover memory
		output->Squeeze();
		} //else (for if vtkUnstructuredGrid)
}

// Specify a spatial locator for merging points. By default,
// an instance of vtkMergePoints is used.
void vtkContourFilter::SetLocator(vtkPointLocator *locator)
{
  if ( this->Locator == locator )
    {
    return;
    }
  if ( this->Locator )
    {
    this->Locator->UnRegister(this);
    this->Locator = NULL;
    }
  if ( locator )
    {
    locator->Register(this);
    }
  this->Locator = locator;
  this->Modified();
}

void vtkContourFilter::CreateDefaultLocator()
{
  if ( this->Locator == NULL )
    {
    this->Locator = vtkMergePoints::New();
    }
}

void vtkContourFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToPolyDataFilter::PrintSelf(os,indent);

  os << indent << "Compute Gradients: " << (this->ComputeGradients ? "On\n" : "Off\n");
  os << indent << "Compute Normals: " << (this->ComputeNormals ? "On\n" : "Off\n");
  os << indent << "Compute Scalars: " << (this->ComputeScalars ? "On\n" : "Off\n");
  os << indent << "Use Scalar Tree: " << (this->UseScalarTree ? "On\n" : "Off\n");

  this->ContourValues->PrintSelf(os,indent);

  if ( this->Locator )
    {
    os << indent << "Locator: " << this->Locator << "\n";
    }
  else
    {
    os << indent << "Locator: (none)\n";
    }
}

<|endoftext|>


<commit_before>#include "script_system.h"
#include <Windows.h>
#include <cstdio>
#include "core/crc32.h"
#include "core/file_system.h"
#include "core/ifile.h"
#include "core/json_serializer.h"
#include "core/log.h"
#include "core/pod_array.h"
#include "engine/engine.h"
#include "universe/universe.h"
#include "universe/component_event.h"
#include "base_script.h"
#include "save_script_visitor.h"

static const uint32_t script_type = crc32("script");

namespace Lux
{
	struct ScriptSystemImpl
	{
		void postDeserialize();
		void compile();
		void getDll(const char* script_path, char* dll_path, int max_length);
		void getScriptDefaultPath(Entity e, char* path, char* full_path, int max_path, const char* ext);

		PODArray<int> m_scripts;
		PODArray<BaseScript*> m_script_objs;
		PODArray<HMODULE> m_libs;
		Array<string> m_paths;
		Universe* m_universe;
		Engine* m_engine;
		bool m_is_running;
		ScriptSystem* m_owner;
	};

	typedef BaseScript* (*CreateScriptFunction)();
	typedef void (*DestroyScriptFunction)(BaseScript* script);

	ScriptSystem::ScriptSystem()
	{
		m_impl = LUX_NEW(ScriptSystemImpl);
		m_impl->m_owner = this;
		m_impl->m_is_running = false;
	}

	ScriptSystem::~ScriptSystem()
	{
		LUX_DELETE(m_impl);
	}

	void ScriptSystem::setEngine(Engine& engine)
	{
		m_impl->m_engine = &engine;
	}

	Universe* ScriptSystem::getUniverse() const
	{
		return m_impl->m_universe;
	}

	Engine* ScriptSystem::getEngine() const
	{
		return m_impl->m_engine;
	}

	void ScriptSystem::setUniverse(Universe* universe)
	{
		m_impl->m_universe = universe;
	}

	void ScriptSystem::start()
	{
		char path[MAX_PATH];
		for(int i = 0; i < m_impl->m_scripts.size(); ++i)
		{
			Entity e(m_impl->m_universe, m_impl->m_scripts[i]);
			m_impl->getDll(m_impl->m_paths[i].c_str(), path, MAX_PATH);
			HMODULE h = LoadLibrary(path);
			m_impl->m_libs.push(h);
			if(h)
			{
				CreateScriptFunction f = (CreateScriptFunction)GetProcAddress(h, TEXT("createScript"));
				BaseScript* script = f();
				if(!f)
				{
					g_log_warning.log("script", "failed to create script %s", m_impl->m_paths[i].c_str());
					m_impl->m_script_objs.push(0);
				}
				else
				{
					m_impl->m_script_objs.push(script);
					script->create(*this, e);
				}
			}
			else
			{
				g_log_warning.log("script", "failed to load script %s", m_impl->m_paths[i].c_str());
				m_impl->m_script_objs.push(0);
			}
		}
		m_impl->m_is_running = true;
	}

	void ScriptSystem::deserialize(ISerializer& serializer)
	{
		int count;
		serializer.deserialize("count", count);
		m_impl->m_scripts.resize(count);
		m_impl->m_paths.resize(count);
		serializer.deserializeArrayBegin("scripts");
		for(int i = 0; i < m_impl->m_scripts.size(); ++i)
		{
			serializer.deserializeArrayItem(m_impl->m_scripts[i]);
			serializer.deserializeArrayItem(m_impl->m_paths[i]);
		}
		serializer.deserializeArrayEnd();
		m_impl->postDeserialize();
	}

	void ScriptSystem::serialize(ISerializer& serializer)
	{
		serializer.serialize("count", m_impl->m_scripts.size());
		serializer.beginArray("scripts");
		for(int i = 0; i < m_impl->m_scripts.size(); ++i)
		{
			serializer.serializeArrayItem(m_impl->m_scripts[i]);
			serializer.serializeArrayItem(m_impl->m_paths[i]);
		}
		serializer.endArray();
	}

	void ScriptSystem::stop()
	{
		m_impl->m_is_running = false;
		for(int i = 0; i < m_impl->m_scripts.size(); ++i)
		{
			DestroyScriptFunction f = (DestroyScriptFunction)GetProcAddress(m_impl->m_libs[i], "destroyScript");
			f(m_impl->m_script_objs[i]);
			FreeLibrary(m_impl->m_libs[i]);
		}
		m_impl->m_libs.clear();
		m_impl->m_script_objs.clear();
	}

	void ScriptSystem::update(float dt)
	{
		if(m_impl->m_is_running)
		{
			for(int i = 0; i < m_impl->m_scripts.size(); ++i)
			{
				m_impl->m_script_objs[i]->update(dt);
			}
		}
	}

	void ScriptSystem::getScriptPath(Component cmp, string& str)
	{
		str = m_impl->m_paths[cmp.index];
	}

	void ScriptSystem::setScriptPath(Component cmp, const string& str)
	{
		m_impl->m_paths[cmp.index] = str;
	}

	void ScriptSystemImpl::getDll(const char* script_path, char* dll_path, int max_length)
	{
		strcpy_s(dll_path, max_length, script_path);
		int len = strlen(script_path);
		if(len > 4)
		{
			strcpy_s(dll_path + len - 4, 5, ".dll");
		}
	}

	void ScriptSystemImpl::getScriptDefaultPath(Entity e, char* path, char* full_path, int max_path, const char* ext)
	{
		sprintf_s(full_path, max_path, "%s\\scripts\\e%d.%s", m_engine->getBasePath(), e.index, ext);
		sprintf_s(path, max_path, "scripts\\e%d.%s", e.index, ext);
	}

	void ScriptSystemImpl::postDeserialize()
	{
		for(int i = 0; i < m_scripts.size(); ++i)
		{
			Entity e(m_universe, m_scripts[i]);
			m_universe->getEventManager()->emitEvent(ComponentEvent(Component(e, script_type, m_owner, i)));
		}
	}

	Component ScriptSystem::createScript(Entity entity)
	{
		char path[MAX_PATH];
		char full_path[MAX_PATH];
		m_impl->getScriptDefaultPath(entity, path, full_path, MAX_PATH, "cpp");

		FS::FileSystem& fs = m_impl->m_engine->getFileSystem();
		FS::IFile* file = fs.open(fs.getDefaultDevice(), full_path, FS::Mode::OPEN_OR_CREATE | FS::Mode::WRITE);
		fs.close(file);

		m_impl->m_scripts.push(entity.index);
		m_impl->m_paths.push(string(path));

		Component cmp(entity, script_type, this, m_impl->m_scripts.size() - 1);
		m_impl->m_universe->getEventManager()->emitEvent(ComponentEvent(cmp));

		return cmp;
	}

} // ~namespace Lux<commit_msg>load script libraries using right path after open dialog is shown<commit_after>#include "script_system.h"
#include <Windows.h>
#include <cstdio>
#include "core/crc32.h"
#include "core/file_system.h"
#include "core/ifile.h"
#include "core/json_serializer.h"
#include "core/log.h"
#include "core/pod_array.h"
#include "engine/engine.h"
#include "universe/universe.h"
#include "universe/component_event.h"
#include "base_script.h"
#include "save_script_visitor.h"

static const uint32_t script_type = crc32("script");

namespace Lux
{
	struct ScriptSystemImpl
	{
		void postDeserialize();
		void compile();
		void getDll(const char* script_path, char* dll_path, char* full_path, int max_length);
		void getScriptDefaultPath(Entity e, char* path, char* full_path, int max_path, const char* ext);

		PODArray<int> m_scripts;
		PODArray<BaseScript*> m_script_objs;
		PODArray<HMODULE> m_libs;
		Array<string> m_paths;
		Universe* m_universe;
		Engine* m_engine;
		bool m_is_running;
		ScriptSystem* m_owner;
	};

	typedef BaseScript* (*CreateScriptFunction)();
	typedef void (*DestroyScriptFunction)(BaseScript* script);

	ScriptSystem::ScriptSystem()
	{
		m_impl = LUX_NEW(ScriptSystemImpl);
		m_impl->m_owner = this;
		m_impl->m_is_running = false;
	}

	ScriptSystem::~ScriptSystem()
	{
		LUX_DELETE(m_impl);
	}

	void ScriptSystem::setEngine(Engine& engine)
	{
		m_impl->m_engine = &engine;
	}

	Universe* ScriptSystem::getUniverse() const
	{
		return m_impl->m_universe;
	}

	Engine* ScriptSystem::getEngine() const
	{
		return m_impl->m_engine;
	}

	void ScriptSystem::setUniverse(Universe* universe)
	{
		m_impl->m_universe = universe;
	}

	void ScriptSystem::start()
	{
		char path[MAX_PATH];
		char full_path[MAX_PATH];
		for(int i = 0; i < m_impl->m_scripts.size(); ++i)
		{
			Entity e(m_impl->m_universe, m_impl->m_scripts[i]);
			m_impl->getDll(m_impl->m_paths[i].c_str(), path, full_path, MAX_PATH);
			HMODULE h = LoadLibrary(full_path);
			m_impl->m_libs.push(h);
			if(h)
			{
				CreateScriptFunction f = (CreateScriptFunction)GetProcAddress(h, TEXT("createScript"));
				BaseScript* script = f();
				if(!f)
				{
					g_log_warning.log("script", "failed to create script %s", m_impl->m_paths[i].c_str());
					m_impl->m_script_objs.push(0);
				}
				else
				{
					m_impl->m_script_objs.push(script);
					script->create(*this, e);
				}
			}
			else
			{
				g_log_warning.log("script", "failed to load script %s", m_impl->m_paths[i].c_str());
				m_impl->m_script_objs.push(0);
			}
		}
		m_impl->m_is_running = true;
	}

	void ScriptSystem::deserialize(ISerializer& serializer)
	{
		int count;
		serializer.deserialize("count", count);
		m_impl->m_scripts.resize(count);
		m_impl->m_paths.resize(count);
		serializer.deserializeArrayBegin("scripts");
		for(int i = 0; i < m_impl->m_scripts.size(); ++i)
		{
			serializer.deserializeArrayItem(m_impl->m_scripts[i]);
			serializer.deserializeArrayItem(m_impl->m_paths[i]);
		}
		serializer.deserializeArrayEnd();
		m_impl->postDeserialize();
	}

	void ScriptSystem::serialize(ISerializer& serializer)
	{
		serializer.serialize("count", m_impl->m_scripts.size());
		serializer.beginArray("scripts");
		for(int i = 0; i < m_impl->m_scripts.size(); ++i)
		{
			serializer.serializeArrayItem(m_impl->m_scripts[i]);
			serializer.serializeArrayItem(m_impl->m_paths[i]);
		}
		serializer.endArray();
	}

	void ScriptSystem::stop()
	{
		m_impl->m_is_running = false;
		for(int i = 0; i < m_impl->m_scripts.size(); ++i)
		{
			DestroyScriptFunction f = (DestroyScriptFunction)GetProcAddress(m_impl->m_libs[i], "destroyScript");
			f(m_impl->m_script_objs[i]);
			FreeLibrary(m_impl->m_libs[i]);
		}
		m_impl->m_libs.clear();
		m_impl->m_script_objs.clear();
	}

	void ScriptSystem::update(float dt)
	{
		if(m_impl->m_is_running)
		{
			for(int i = 0; i < m_impl->m_scripts.size(); ++i)
			{
				m_impl->m_script_objs[i]->update(dt);
			}
		}
	}

	void ScriptSystem::getScriptPath(Component cmp, string& str)
	{
		str = m_impl->m_paths[cmp.index];
	}

	void ScriptSystem::setScriptPath(Component cmp, const string& str)
	{
		m_impl->m_paths[cmp.index] = str;
	}

	void ScriptSystemImpl::getDll(const char* script_path, char* dll_path, char* full_path, int max_length)
	{
		strcpy_s(dll_path, max_length, script_path);
		int len = strlen(script_path);
		if(len > 4)
		{
			strcpy_s(dll_path + len - 4, 5, ".dll");
		}
		strcpy(full_path, m_engine->getBasePath());
		strcat(full_path, "\\");
		strcat(full_path, dll_path);
	}

	void ScriptSystemImpl::getScriptDefaultPath(Entity e, char* path, char* full_path, int max_path, const char* ext)
	{
		sprintf_s(full_path, max_path, "%s\\scripts\\e%d.%s", m_engine->getBasePath(), e.index, ext);
		sprintf_s(path, max_path, "scripts\\e%d.%s", e.index, ext);
	}

	void ScriptSystemImpl::postDeserialize()
	{
		for(int i = 0; i < m_scripts.size(); ++i)
		{
			Entity e(m_universe, m_scripts[i]);
			m_universe->getEventManager()->emitEvent(ComponentEvent(Component(e, script_type, m_owner, i)));
		}
	}

	Component ScriptSystem::createScript(Entity entity)
	{
		char path[MAX_PATH];
		char full_path[MAX_PATH];
		m_impl->getScriptDefaultPath(entity, path, full_path, MAX_PATH, "cpp");

		FS::FileSystem& fs = m_impl->m_engine->getFileSystem();
		FS::IFile* file = fs.open(fs.getDefaultDevice(), full_path, FS::Mode::OPEN_OR_CREATE | FS::Mode::WRITE);
		fs.close(file);

		m_impl->m_scripts.push(entity.index);
		m_impl->m_paths.push(string(path));

		Component cmp(entity, script_type, this, m_impl->m_scripts.size() - 1);
		m_impl->m_universe->getEventManager()->emitEvent(ComponentEvent(cmp));

		return cmp;
	}

} // ~namespace Lux<|endoftext|>


<commit_before>AliAnalysisTaskNewJetSubstructure* AddTaskNewJetSubstructure(const char * njetsBase,
                                                     const char * njetsUS,
						     const char * njetsTrue,
                                                     const char * njetsPartLevel,
						     const Double_t R,
						     const char * nrhoBase,
						     const char * ntracks,
                                                     const char * ntracksUS,
                                                     const char *ntracksPartLevel,
						     const char * nclusters,
						     const char * ntracksTrue,
						     const char *type,
						     const char *CentEst,
						     Int_t       pSel,
						     TString     trigClass      = "",
						     TString     kEmcalTriggers = "",
						     TString     tag            = "",
						     AliAnalysisTaskNewJetSubstructure::JetShapeType jetShapeType = AliAnalysisTaskNewJetSubstructure::kMCTrue,
						     AliAnalysisTaskNewJetSubstructure::JetShapeSub jetShapeSub = AliAnalysisTaskNewJetSubstructure::kNoSub,
						     AliAnalysisTaskNewJetSubstructure::JetSelectionType jetSelection = AliAnalysisTaskNewJetSubstructure::kInclusive,
						     Float_t minpTHTrigger =0.,  Float_t maxpTHTrigger =0., Float_t acut =0.6, AliAnalysisTaskNewJetSubstructure::DerivSubtrOrder derivSubtrOrder = AliAnalysisTaskNewJetSubstructure::kSecondOrder ) {

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr)
    {
      Error("AddTaskNewJetSubstructure","No analysis manager found.");
      return 0;
    }
  Bool_t ismc=kFALSE;
  ismc = (mgr->GetMCtruthEventHandler())?kTRUE:kFALSE;

  // Check the analysis type using the event handlers connected to the analysis manager.
  //==============================================================================
  if (!mgr->GetInputEventHandler())
    {
      ::Error("AddTaskNewJetSubstructure", "This task requires an input event handler");
      return NULL;
    }

  TString wagonName1 = Form("JetSubstructure_%s_TC%s%s",njetsBase,trigClass.Data(),tag.Data());
  TString wagonName2 = Form("JetSubstructure_%s_TC%s%sTree",njetsBase,trigClass.Data(),tag.Data());
  //Configure jet tagger task
  AliAnalysisTaskNewJetSubstructure *task = new AliAnalysisTaskNewJetSubstructure(wagonName1.Data());

  //task->SetNCentBins(4);
  task->SetJetShapeType(jetShapeType);
  task->SetJetShapeSub(jetShapeSub);
  task->SetJetSelection(jetSelection);
  task->SetDerivativeSubtractionOrder(derivSubtrOrder);

  TString thename(njetsBase);
  //if(thename.Contains("Sub")) task->SetIsConstSub(kTRUE);
  //task->SetVzRange(-10.,10.);

  AliParticleContainer *trackCont;// = task->AddTrackContainer(ntracks);

  if ((jetShapeSub==AliAnalysisTaskNewJetSubstructure::kConstSub) && ((jetShapeType==AliAnalysisTaskNewJetSubstructure::kData) || (jetShapeType==AliAnalysisTaskNewJetSubstructure::kDetEmbPartPythia) || (jetShapeType==AliAnalysisTaskNewJetSubstructure::kPythiaDef))){
    trackCont = task->AddParticleContainer(ntracks);}
  else trackCont = task->AddTrackContainer(ntracks);

  //Printf("tracks() = %s, trackCont =%p", ntracks, trackCont);
  AliParticleContainer *trackContUS  = task->AddTrackContainer(ntracksUS);
  //Printf("tracksUS() = %s", ntracksUS);
  AliParticleContainer *trackContTrue = task->AddMCParticleContainer(ntracksTrue);
  //Printf("ntracksTrue() = %s, trackContTrue=%p ", ntracksTrue, trackContTrue);
   if (jetShapeType==AliAnalysisTaskNewJetSubstructure::kDetEmbPartPythia) trackContTrue->SetIsEmbedding(true);
  AliParticleContainer *trackContPartLevel=0;

  if ((jetShapeSub==AliAnalysisTaskNewJetSubstructure::kConstSub) && ((jetShapeType==AliAnalysisTaskNewJetSubstructure::kMCTrue) || (jetShapeType==AliAnalysisTaskNewJetSubstructure::kPythiaDef))){
    trackContPartLevel = task->AddParticleContainer(ntracksPartLevel);
  }
  else trackContPartLevel = task->AddMCParticleContainer(ntracksPartLevel);
    if (jetShapeType==AliAnalysisTaskNewJetSubstructure::kDetEmbPartPythia) trackContPartLevel->SetIsEmbedding(true);
   //Printf("ntracksPartLevel() = %s, trackContPartLevel=%p ", ntracksPartLevel, trackContPartLevel);

  AliClusterContainer *clusterCont = task->AddClusterContainer(nclusters);

  AliJetContainer *jetContBase=0x0;
  AliJetContainer *jetContUS=0x0;
  AliJetContainer *jetContTrue=0x0;
  AliJetContainer *jetContPart=0x0;
  TString strType(type);

  if ((jetShapeType==AliAnalysisTaskNewJetSubstructure::kMCTrue || (jetShapeType==AliAnalysisTaskNewJetSubstructure::kGenOnTheFly))) {
    jetContBase = task->AddJetContainer(njetsBase,strType,R);
    if(jetContBase) {
      jetContBase->SetRhoName(nrhoBase);
      jetContBase->ConnectParticleContainer(trackContPartLevel);
      jetContBase->ConnectClusterContainer(clusterCont);
      jetContBase->SetPercAreaCut(acut);
    }
  }

  if (jetShapeType==AliAnalysisTaskNewJetSubstructure::kData){
    jetContBase = task->AddJetContainer(njetsBase,strType,R);
    if(jetContBase) {
      jetContBase->SetRhoName(nrhoBase);
      jetContBase->ConnectParticleContainer(trackCont);
      jetContBase->ConnectClusterContainer(clusterCont);
      jetContBase->SetPercAreaCut(acut);
      if(jetShapeSub==AliAnalysisTaskNewJetSubstructure::kConstSub) jetContBase->SetAreaEmcCut(-2);
    }
  }

  if (jetShapeType==AliAnalysisTaskNewJetSubstructure::kDetEmbPartPythia){
    jetContBase = task->AddJetContainer(njetsBase,strType,R);
    if(jetContBase) {
      jetContBase->SetRhoName(nrhoBase);
      jetContBase->ConnectParticleContainer(trackCont);
      jetContBase->ConnectClusterContainer(clusterCont);
      jetContBase->SetPercAreaCut(acut);

      if(jetShapeSub==AliAnalysisTaskNewJetSubstructure::kConstSub) jetContBase->SetAreaEmcCut(-2);
    }

    jetContTrue = task->AddJetContainer(njetsTrue,strType,R);
    if(jetContTrue) {

      jetContTrue->SetRhoName(nrhoBase);
      jetContTrue->ConnectParticleContainer(trackContTrue);
      jetContTrue->SetPercAreaCut(acut);

    }

    if(jetShapeSub==AliAnalysisTaskNewJetSubstructure::kConstSub){
      jetContUS=task->AddJetContainer(njetsUS,strType,R);
      if(jetContUS) {
        jetContUS->SetRhoName(nrhoBase);
        jetContUS->ConnectParticleContainer(trackContUS);
        jetContUS->SetPercAreaCut(acut);

      }
    }

     jetContPart = task->AddJetContainer(njetsPartLevel,strType,R);
      if(jetContPart) {

        jetContPart->SetRhoName(nrhoBase);
        jetContPart->ConnectParticleContainer(trackContPartLevel);
        jetContPart->SetPercAreaCut(acut);

      }
  }

  if (jetShapeType==AliAnalysisTaskNewJetSubstructure::kPythiaDef){

    jetContBase = task->AddJetContainer(njetsBase,strType,R);
    if(jetContBase) {
      jetContBase->ConnectParticleContainer(trackCont);
      jetContBase->ConnectClusterContainer(clusterCont);
      jetContBase->SetPercAreaCut(acut);
    }

    jetContTrue = task->AddJetContainer(njetsTrue,strType,R);
    if(jetContTrue) {
      jetContTrue->SetRhoName(nrhoBase);
      jetContTrue->ConnectParticleContainer(trackContTrue);
      jetContTrue->SetPercAreaCut(acut);

    }

    if(jetShapeSub==AliAnalysisTaskNewJetSubstructure::kConstSub){
      jetContUS=task->AddJetContainer(njetsUS,strType,R);
      if(jetContUS) {
        jetContUS->SetRhoName(nrhoBase);
        jetContUS->ConnectParticleContainer(trackContUS);
        jetContUS->SetPercAreaCut(acut);

      }
    }

    jetContPart = task->AddJetContainer(njetsPartLevel,strType,R);
    if(jetContPart) {
      jetContPart->SetRhoName(nrhoBase);
      jetContPart->ConnectParticleContainer(trackContPartLevel);
      jetContPart->SetPercAreaCut(acut);
    }

  }

  task->SetCaloTriggerPatchInfoName(kEmcalTriggers.Data());
  task->SetCentralityEstimator(CentEst);
  task->SelectCollisionCandidates(pSel);
  task->SetUseAliAnaUtils(kFALSE);

  mgr->AddTask(task);

  //Connnect input
  mgr->ConnectInput (task, 0, mgr->GetCommonInputContainer() );

  //Connect output
  TString contName1(wagonName1);
  TString contName2(wagonName2);

  if (jetShapeType == AliAnalysisTaskNewJetSubstructure::kMCTrue) contName1 += "_MCTrue";
  if (jetShapeType == AliAnalysisTaskNewJetSubstructure::kData) contName1 += "_Data";

  if (jetShapeType == AliAnalysisTaskNewJetSubstructure::kPythiaDef) contName1 +="_PythiaDef";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kNoSub) contName1 += "_NoSub";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kConstSub) contName1 += "_ConstSub";
   if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kEventSub) contName1 += "_EventSub";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kDerivSub) contName1 += "_DerivSub";

  if (jetSelection == AliAnalysisTaskNewJetSubstructure::kInclusive) contName1 += "_Incl";

    if (jetShapeType == AliAnalysisTaskNewJetSubstructure::kMCTrue) contName2 += "_MCTrue";
  if (jetShapeType == AliAnalysisTaskNewJetSubstructure::kData) contName2 += "_Data";

  if (jetShapeType == AliAnalysisTaskNewJetSubstructure::kPythiaDef) contName2 +="_PythiaDef";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kNoSub) contName2 += "_NoSub";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kConstSub) contName2 += "_ConstSub";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kEventSub) contName2 += "_EventSub";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kDerivSub) contName2 += "_DerivSub";

  if (jetSelection == AliAnalysisTaskNewJetSubstructure::kInclusive) contName2 += "_Incl";

  TString outputfile = Form("%s",AliAnalysisManager::GetCommonFileName());
  AliAnalysisDataContainer *coutput1 = mgr->CreateContainer(contName1.Data(), TList::Class(),AliAnalysisManager::kOutputContainer,outputfile);
   mgr->ConnectOutput(task,1,coutput1);

   AliAnalysisDataContainer *coutput2 = mgr->CreateContainer(contName2.Data(), TTree::Class(),AliAnalysisManager::kOutputContainer,outputfile);
  mgr->ConnectOutput(task,2,coutput2);

  return task;

}

<commit_msg>i also forgot to add the unsub container<commit_after>AliAnalysisTaskNewJetSubstructure* AddTaskNewJetSubstructure(const char * njetsBase,
                                                     const char * njetsUS,
						     const char * njetsTrue,
                                                     const char * njetsPartLevel,
						     const Double_t R,
						     const char * nrhoBase,
						     const char * ntracks,
                                                     const char * ntracksUS,
                                                     const char *ntracksPartLevel,
						     const char * nclusters,
						     const char * ntracksTrue,
						     const char *type,
						     const char *CentEst,
						     Int_t       pSel,
						     TString     trigClass      = "",
						     TString     kEmcalTriggers = "",
						     TString     tag            = "",
						     AliAnalysisTaskNewJetSubstructure::JetShapeType jetShapeType = AliAnalysisTaskNewJetSubstructure::kMCTrue,
						     AliAnalysisTaskNewJetSubstructure::JetShapeSub jetShapeSub = AliAnalysisTaskNewJetSubstructure::kNoSub,
						     AliAnalysisTaskNewJetSubstructure::JetSelectionType jetSelection = AliAnalysisTaskNewJetSubstructure::kInclusive,
						     Float_t minpTHTrigger =0.,  Float_t maxpTHTrigger =0., Float_t acut =0.6, AliAnalysisTaskNewJetSubstructure::DerivSubtrOrder derivSubtrOrder = AliAnalysisTaskNewJetSubstructure::kSecondOrder ) {

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr)
    {
      Error("AddTaskNewJetSubstructure","No analysis manager found.");
      return 0;
    }
  Bool_t ismc=kFALSE;
  ismc = (mgr->GetMCtruthEventHandler())?kTRUE:kFALSE;

  // Check the analysis type using the event handlers connected to the analysis manager.
  //==============================================================================
  if (!mgr->GetInputEventHandler())
    {
      ::Error("AddTaskNewJetSubstructure", "This task requires an input event handler");
      return NULL;
    }

  TString wagonName1 = Form("JetSubstructure_%s_TC%s%s",njetsBase,trigClass.Data(),tag.Data());
  TString wagonName2 = Form("JetSubstructure_%s_TC%s%sTree",njetsBase,trigClass.Data(),tag.Data());
  //Configure jet tagger task
  AliAnalysisTaskNewJetSubstructure *task = new AliAnalysisTaskNewJetSubstructure(wagonName1.Data());

  //task->SetNCentBins(4);
  task->SetJetShapeType(jetShapeType);
  task->SetJetShapeSub(jetShapeSub);
  task->SetJetSelection(jetSelection);
  task->SetDerivativeSubtractionOrder(derivSubtrOrder);

  TString thename(njetsBase);
  //if(thename.Contains("Sub")) task->SetIsConstSub(kTRUE);
  //task->SetVzRange(-10.,10.);

  AliParticleContainer *trackCont;// = task->AddTrackContainer(ntracks);

  if ((jetShapeSub==AliAnalysisTaskNewJetSubstructure::kConstSub) && ((jetShapeType==AliAnalysisTaskNewJetSubstructure::kData) || (jetShapeType==AliAnalysisTaskNewJetSubstructure::kDetEmbPartPythia) || (jetShapeType==AliAnalysisTaskNewJetSubstructure::kPythiaDef))){
    trackCont = task->AddParticleContainer(ntracks);}
  else trackCont = task->AddTrackContainer(ntracks);

  //Printf("tracks() = %s, trackCont =%p", ntracks, trackCont);
  AliParticleContainer *trackContUS  = task->AddTrackContainer(ntracksUS);
  //Printf("tracksUS() = %s", ntracksUS);
  AliParticleContainer *trackContTrue = task->AddMCParticleContainer(ntracksTrue);
  //Printf("ntracksTrue() = %s, trackContTrue=%p ", ntracksTrue, trackContTrue);
   if (jetShapeType==AliAnalysisTaskNewJetSubstructure::kDetEmbPartPythia) trackContTrue->SetIsEmbedding(true);
  AliParticleContainer *trackContPartLevel=0;

  if ((jetShapeSub==AliAnalysisTaskNewJetSubstructure::kConstSub) && ((jetShapeType==AliAnalysisTaskNewJetSubstructure::kMCTrue) || (jetShapeType==AliAnalysisTaskNewJetSubstructure::kPythiaDef))){
    trackContPartLevel = task->AddParticleContainer(ntracksPartLevel);
  }
  else trackContPartLevel = task->AddMCParticleContainer(ntracksPartLevel);
    if (jetShapeType==AliAnalysisTaskNewJetSubstructure::kDetEmbPartPythia) trackContPartLevel->SetIsEmbedding(true);
   //Printf("ntracksPartLevel() = %s, trackContPartLevel=%p ", ntracksPartLevel, trackContPartLevel);

  AliClusterContainer *clusterCont = task->AddClusterContainer(nclusters);

  AliJetContainer *jetContBase=0x0;
  AliJetContainer *jetContUS=0x0;
  AliJetContainer *jetContTrue=0x0;
  AliJetContainer *jetContPart=0x0;
  TString strType(type);

  if ((jetShapeType==AliAnalysisTaskNewJetSubstructure::kMCTrue || (jetShapeType==AliAnalysisTaskNewJetSubstructure::kGenOnTheFly))) {
    jetContBase = task->AddJetContainer(njetsBase,strType,R);
    if(jetContBase) {
      jetContBase->SetRhoName(nrhoBase);
      jetContBase->ConnectParticleContainer(trackContPartLevel);
      jetContBase->ConnectClusterContainer(clusterCont);
      jetContBase->SetPercAreaCut(acut);
    }
  }

  if (jetShapeType==AliAnalysisTaskNewJetSubstructure::kData){
    jetContBase = task->AddJetContainer(njetsBase,strType,R);
    if(jetContBase) {
      jetContBase->SetRhoName(nrhoBase);
      jetContBase->ConnectParticleContainer(trackCont);
      jetContBase->ConnectClusterContainer(clusterCont);
      jetContBase->SetPercAreaCut(acut);
      if(jetShapeSub==AliAnalysisTaskNewJetSubstructure::kConstSub) jetContBase->SetAreaEmcCut(-2);
    }
  }

  if (jetShapeType==AliAnalysisTaskNewJetSubstructure::kDetEmbPartPythia){
    jetContBase = task->AddJetContainer(njetsBase,strType,R);
    if(jetContBase) {
      jetContBase->SetRhoName(nrhoBase);
      jetContBase->ConnectParticleContainer(trackCont);
      jetContBase->ConnectClusterContainer(clusterCont);
      jetContBase->SetPercAreaCut(acut);

      if(jetShapeSub==AliAnalysisTaskNewJetSubstructure::kConstSub) jetContBase->SetAreaEmcCut(-2);
    }

    jetContTrue = task->AddJetContainer(njetsTrue,strType,R);
    if(jetContTrue) {

      jetContTrue->SetRhoName(nrhoBase);
      jetContTrue->ConnectParticleContainer(trackContTrue);
      jetContTrue->SetPercAreaCut(acut);

    }

    if(jetShapeSub==AliAnalysisTaskNewJetSubstructure::kConstSub || jetShapeSub==AliAnalysisTaskNewJetSubstructure::kEventSub){
      jetContUS=task->AddJetContainer(njetsUS,strType,R);
      if(jetContUS) {
        jetContUS->SetRhoName(nrhoBase);
        jetContUS->ConnectParticleContainer(trackContUS);
        jetContUS->SetPercAreaCut(acut);

      }
    }

     jetContPart = task->AddJetContainer(njetsPartLevel,strType,R);
      if(jetContPart) {

        jetContPart->SetRhoName(nrhoBase);
        jetContPart->ConnectParticleContainer(trackContPartLevel);
        jetContPart->SetPercAreaCut(acut);

      }
  }

  if (jetShapeType==AliAnalysisTaskNewJetSubstructure::kPythiaDef){

    jetContBase = task->AddJetContainer(njetsBase,strType,R);
    if(jetContBase) {
      jetContBase->ConnectParticleContainer(trackCont);
      jetContBase->ConnectClusterContainer(clusterCont);
      jetContBase->SetPercAreaCut(acut);
    }

    jetContTrue = task->AddJetContainer(njetsTrue,strType,R);
    if(jetContTrue) {
      jetContTrue->SetRhoName(nrhoBase);
      jetContTrue->ConnectParticleContainer(trackContTrue);
      jetContTrue->SetPercAreaCut(acut);

    }

    if(jetShapeSub==AliAnalysisTaskNewJetSubstructure::kConstSub){
      jetContUS=task->AddJetContainer(njetsUS,strType,R);
      if(jetContUS) {
        jetContUS->SetRhoName(nrhoBase);
        jetContUS->ConnectParticleContainer(trackContUS);
        jetContUS->SetPercAreaCut(acut);

      }
    }

    jetContPart = task->AddJetContainer(njetsPartLevel,strType,R);
    if(jetContPart) {
      jetContPart->SetRhoName(nrhoBase);
      jetContPart->ConnectParticleContainer(trackContPartLevel);
      jetContPart->SetPercAreaCut(acut);
    }

  }

  task->SetCaloTriggerPatchInfoName(kEmcalTriggers.Data());
  task->SetCentralityEstimator(CentEst);
  task->SelectCollisionCandidates(pSel);
  task->SetUseAliAnaUtils(kFALSE);

  mgr->AddTask(task);

  //Connnect input
  mgr->ConnectInput (task, 0, mgr->GetCommonInputContainer() );

  //Connect output
  TString contName1(wagonName1);
  TString contName2(wagonName2);

  if (jetShapeType == AliAnalysisTaskNewJetSubstructure::kMCTrue) contName1 += "_MCTrue";
  if (jetShapeType == AliAnalysisTaskNewJetSubstructure::kData) contName1 += "_Data";

  if (jetShapeType == AliAnalysisTaskNewJetSubstructure::kPythiaDef) contName1 +="_PythiaDef";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kNoSub) contName1 += "_NoSub";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kConstSub) contName1 += "_ConstSub";
   if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kEventSub) contName1 += "_EventSub";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kDerivSub) contName1 += "_DerivSub";

  if (jetSelection == AliAnalysisTaskNewJetSubstructure::kInclusive) contName1 += "_Incl";

    if (jetShapeType == AliAnalysisTaskNewJetSubstructure::kMCTrue) contName2 += "_MCTrue";
  if (jetShapeType == AliAnalysisTaskNewJetSubstructure::kData) contName2 += "_Data";

  if (jetShapeType == AliAnalysisTaskNewJetSubstructure::kPythiaDef) contName2 +="_PythiaDef";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kNoSub) contName2 += "_NoSub";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kConstSub) contName2 += "_ConstSub";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kEventSub) contName2 += "_EventSub";
  if (jetShapeSub == AliAnalysisTaskNewJetSubstructure::kDerivSub) contName2 += "_DerivSub";

  if (jetSelection == AliAnalysisTaskNewJetSubstructure::kInclusive) contName2 += "_Incl";

  TString outputfile = Form("%s",AliAnalysisManager::GetCommonFileName());
  AliAnalysisDataContainer *coutput1 = mgr->CreateContainer(contName1.Data(), TList::Class(),AliAnalysisManager::kOutputContainer,outputfile);
   mgr->ConnectOutput(task,1,coutput1);

   AliAnalysisDataContainer *coutput2 = mgr->CreateContainer(contName2.Data(), TTree::Class(),AliAnalysisManager::kOutputContainer,outputfile);
  mgr->ConnectOutput(task,2,coutput2);

  return task;

}

<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * BaseUsbProWidget.cpp
 * Read and Write to a USB Widget.
 * Copyright (C) 2010 Simon Newton
 */

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include <string>
#include "ola/BaseTypes.h"
#include "ola/Logging.h"
#include "plugins/usbpro/BaseUsbProWidget.h"

namespace ola {
namespace plugin {
namespace usbpro {

const unsigned int BaseUsbProWidget::HEADER_SIZE =
  sizeof(BaseUsbProWidget::message_header);

BaseUsbProWidget::BaseUsbProWidget(
    ola::io::ConnectedDescriptor *descriptor)
    : m_descriptor(descriptor),
      m_state(PRE_SOM),
      m_bytes_received(0) {
  m_descriptor->SetOnData(
      NewCallback(this, &BaseUsbProWidget::DescriptorReady));
}

BaseUsbProWidget::~BaseUsbProWidget() {
  m_descriptor->SetOnData(NULL);
}

/*
 * Read data from the widget
 */
void BaseUsbProWidget::DescriptorReady() {
  while (m_descriptor->DataRemaining() > 0) {
    ReceiveMessage();
  }
}

/*
 * Send a DMX frame.
 * @returns true if we sent ok, false otherwise
 */
bool BaseUsbProWidget::SendDMX(const DmxBuffer &buffer) {
  struct {
    uint8_t start_code;
    uint8_t dmx[DMX_UNIVERSE_SIZE];
  } widget_dmx;

  widget_dmx.start_code = DMX512_START_CODE;
  unsigned int length = DMX_UNIVERSE_SIZE;
  buffer.Get(widget_dmx.dmx, &length);
  return SendMessage(DMX_LABEL,
                     reinterpret_cast<uint8_t*>(&widget_dmx),
                     length + 1);
}

/*
 * Send the msg
 * @return true if successful, false otherwise
 */
bool BaseUsbProWidget::SendMessage(uint8_t label,
                                   const uint8_t *data,
                                   unsigned int length) const {
  if (length && !data)
    return false;

  ssize_t frame_size = HEADER_SIZE + length + 1;
  uint8_t frame[frame_size];
  message_header *header = reinterpret_cast<message_header*>(frame);
  header->som = SOM;
  header->label = label;
  header->len = length & 0xFF;
  header->len_hi = (length & 0xFF00) >> 8;

  memcpy(frame + sizeof(message_header), data, length);
  frame[frame_size - 1] = EOM;

  ssize_t bytes_sent = m_descriptor->Send(frame, frame_size);
  if (bytes_sent != frame_size)
    // we've probably screwed framing at this point
    return false;

  return true;
}

/**
 * Open a path and apply the settings required for talking to widgets.
 */
ola::io::ConnectedDescriptor *BaseUsbProWidget::OpenDevice(
    const string &path) {
  struct termios newtio;
  int fd = open(path.data(), O_RDWR | O_NONBLOCK | O_NOCTTY);

  if (fd == -1) {
    OLA_WARN << "Failed to open " << path << " " << strerror(errno);
    return NULL;
  }

  bzero(&newtio, sizeof(newtio));  // clear struct for new port settings
  newtio.c_cflag |= CREAD;
  cfsetispeed(&newtio, B115200);
  cfsetospeed(&newtio, B115200);
  tcsetattr(fd, TCSANOW, &newtio);

  return new ola::io::DeviceDescriptor(fd);
}

/*
 * Read the data and handle the messages.
 */
void BaseUsbProWidget::ReceiveMessage() {
  unsigned int count, packet_length;

  switch (m_state) {
    case PRE_SOM:
      do {
        m_descriptor->Receive(&m_header.som, 1, count);
        if (count != 1)
          return;
      } while (m_header.som != SOM);
      m_state = RECV_LABEL;
    case RECV_LABEL:
      m_descriptor->Receive(&m_header.label, 1, count);
      if (count != 1)
        return;
      m_state = RECV_SIZE_LO;
    case RECV_SIZE_LO:
      m_descriptor->Receive(&m_header.len, 1, count);
      if (count != 1)
        return;
      m_state = RECV_SIZE_HI;
    case RECV_SIZE_HI:
      m_descriptor->Receive(&m_header.len_hi, 1, count);
      if (count != 1)
        return;

      packet_length = (m_header.len_hi << 8) + m_header.len;
      if (packet_length == 0) {
        m_state = RECV_EOM;
        return;
      } else if (packet_length > MAX_DATA_SIZE) {
        m_state = PRE_SOM;
        return;
      }

      m_bytes_received = 0;
      m_state = RECV_BODY;
    case RECV_BODY:
      packet_length = (m_header.len_hi << 8) + m_header.len;
      m_descriptor->Receive(
          reinterpret_cast<uint8_t*>(&m_recv_buffer) + m_bytes_received,
          packet_length - m_bytes_received,
          count);

      if (!count)
        return;

      m_bytes_received += count;
      if (m_bytes_received != packet_length)
        return;

      m_state = RECV_EOM;
    case RECV_EOM:
      // check this is a valid frame with an end byte
      uint8_t eom;
      m_descriptor->Receive(&eom, 1, count);
      if (count != 1)
        return;

      packet_length = (m_header.len_hi << 8) + m_header.len;

      if (eom == EOM)
        HandleMessage(m_header.label,
                      packet_length ? m_recv_buffer : NULL,
                      packet_length);
      m_state = PRE_SOM;
  }
  return;
}
}  // usbpro
}  // plugin
}  // ola
<commit_msg>Set the char size to 8 bits for the usb serial devices. As suggested by Michael Markstaller<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * BaseUsbProWidget.cpp
 * Read and Write to a USB Widget.
 * Copyright (C) 2010 Simon Newton
 */

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <termios.h>
#include <unistd.h>
#include <string>
#include "ola/BaseTypes.h"
#include "ola/Logging.h"
#include "plugins/usbpro/BaseUsbProWidget.h"

namespace ola {
namespace plugin {
namespace usbpro {

const unsigned int BaseUsbProWidget::HEADER_SIZE =
  sizeof(BaseUsbProWidget::message_header);

BaseUsbProWidget::BaseUsbProWidget(
    ola::io::ConnectedDescriptor *descriptor)
    : m_descriptor(descriptor),
      m_state(PRE_SOM),
      m_bytes_received(0) {
  m_descriptor->SetOnData(
      NewCallback(this, &BaseUsbProWidget::DescriptorReady));
}

BaseUsbProWidget::~BaseUsbProWidget() {
  m_descriptor->SetOnData(NULL);
}

/*
 * Read data from the widget
 */
void BaseUsbProWidget::DescriptorReady() {
  while (m_descriptor->DataRemaining() > 0) {
    ReceiveMessage();
  }
}

/*
 * Send a DMX frame.
 * @returns true if we sent ok, false otherwise
 */
bool BaseUsbProWidget::SendDMX(const DmxBuffer &buffer) {
  struct {
    uint8_t start_code;
    uint8_t dmx[DMX_UNIVERSE_SIZE];
  } widget_dmx;

  widget_dmx.start_code = DMX512_START_CODE;
  unsigned int length = DMX_UNIVERSE_SIZE;
  buffer.Get(widget_dmx.dmx, &length);
  return SendMessage(DMX_LABEL,
                     reinterpret_cast<uint8_t*>(&widget_dmx),
                     length + 1);
}

/*
 * Send the msg
 * @return true if successful, false otherwise
 */
bool BaseUsbProWidget::SendMessage(uint8_t label,
                                   const uint8_t *data,
                                   unsigned int length) const {
  if (length && !data)
    return false;

  ssize_t frame_size = HEADER_SIZE + length + 1;
  uint8_t frame[frame_size];
  message_header *header = reinterpret_cast<message_header*>(frame);
  header->som = SOM;
  header->label = label;
  header->len = length & 0xFF;
  header->len_hi = (length & 0xFF00) >> 8;

  memcpy(frame + sizeof(message_header), data, length);
  frame[frame_size - 1] = EOM;

  ssize_t bytes_sent = m_descriptor->Send(frame, frame_size);
  if (bytes_sent != frame_size)
    // we've probably screwed framing at this point
    return false;

  return true;
}

/**
 * Open a path and apply the settings required for talking to widgets.
 */
ola::io::ConnectedDescriptor *BaseUsbProWidget::OpenDevice(
    const string &path) {
  struct termios newtio;
  int fd = open(path.data(), O_RDWR | O_NONBLOCK | O_NOCTTY);

  if (fd == -1) {
    OLA_WARN << "Failed to open " << path << " " << strerror(errno);
    return NULL;
  }

  bzero(&newtio, sizeof(newtio));  // clear struct for new port settings
  newtio.c_cflag |= CREAD;
  newtio.c_cflag |= CS8;
  cfsetispeed(&newtio, B115200);
  cfsetospeed(&newtio, B115200);
  tcsetattr(fd, TCSANOW, &newtio);

  return new ola::io::DeviceDescriptor(fd);
}

/*
 * Read the data and handle the messages.
 */
void BaseUsbProWidget::ReceiveMessage() {
  unsigned int count, packet_length;

  switch (m_state) {
    case PRE_SOM:
      do {
        m_descriptor->Receive(&m_header.som, 1, count);
        if (count != 1)
          return;
      } while (m_header.som != SOM);
      m_state = RECV_LABEL;
    case RECV_LABEL:
      m_descriptor->Receive(&m_header.label, 1, count);
      if (count != 1)
        return;
      m_state = RECV_SIZE_LO;
    case RECV_SIZE_LO:
      m_descriptor->Receive(&m_header.len, 1, count);
      if (count != 1)
        return;
      m_state = RECV_SIZE_HI;
    case RECV_SIZE_HI:
      m_descriptor->Receive(&m_header.len_hi, 1, count);
      if (count != 1)
        return;

      packet_length = (m_header.len_hi << 8) + m_header.len;
      if (packet_length == 0) {
        m_state = RECV_EOM;
        return;
      } else if (packet_length > MAX_DATA_SIZE) {
        m_state = PRE_SOM;
        return;
      }

      m_bytes_received = 0;
      m_state = RECV_BODY;
    case RECV_BODY:
      packet_length = (m_header.len_hi << 8) + m_header.len;
      m_descriptor->Receive(
          reinterpret_cast<uint8_t*>(&m_recv_buffer) + m_bytes_received,
          packet_length - m_bytes_received,
          count);

      if (!count)
        return;

      m_bytes_received += count;
      if (m_bytes_received != packet_length)
        return;

      m_state = RECV_EOM;
    case RECV_EOM:
      // check this is a valid frame with an end byte
      uint8_t eom;
      m_descriptor->Receive(&eom, 1, count);
      if (count != 1)
        return;

      packet_length = (m_header.len_hi << 8) + m_header.len;

      if (eom == EOM)
        HandleMessage(m_header.label,
                      packet_length ? m_recv_buffer : NULL,
                      packet_length);
      m_state = PRE_SOM;
  }
  return;
}
}  // usbpro
}  // plugin
}  // ola
<|endoftext|>