<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/controls/menu/menu_item_view.h"

#include "app/resource_bundle.h"
#include "gfx/canvas_skia.h"
#include "gfx/favicon_size.h"
#include "grit/app_resources.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "views/controls/button/text_button.h"
#include "views/controls/menu/menu_config.h"
#include "views/controls/menu/submenu_view.h"

namespace views {

// Background color when the menu item is selected.
#if defined(OS_CHROMOS)
static const SkColor kSelectedBackgroundColor = SkColorSetRGB(0xDC, 0xE4, 0xFA);
#else
static const SkColor kSelectedBackgroundColor = SkColorSetRGB(246, 249, 253);
#endif

// Size of the radio button inciator.
static const int kSelectedIndicatorSize = 5;
static const int kIndicatorSize = 10;

// Used for the radio indicator. See theme_draw for details.
static const double kGradientStop = .5;
static const SkColor kGradient0 = SkColorSetRGB(255, 255, 255);
static const SkColor kGradient1 = SkColorSetRGB(255, 255, 255);
static const SkColor kGradient2 = SkColorSetRGB(0xD8, 0xD8, 0xD8);
static const SkColor kBaseStroke = SkColorSetRGB(0x8F, 0x8F, 0x8F);
static const SkColor kRadioButtonIndicatorGradient0 =
    SkColorSetRGB(0, 0, 0);
static const SkColor kRadioButtonIndicatorGradient1 =
    SkColorSetRGB(0x83, 0x83, 0x83);

static const SkColor kIndicatorStroke = SkColorSetRGB(0, 0, 0);

gfx::Size MenuItemView::GetPreferredSize() {
  const gfx::Font& font = MenuConfig::instance().font;
  // TODO(sky): this is a workaround until I figure out why font.height()
  // isn't returning the right thing. We really only want to include
  // kFavIconSize if we're showing icons.
  int content_height = std::max(kFavIconSize, font.height());
  return gfx::Size(
      font.GetStringWidth(title_) + label_start_ + item_right_margin_ +
          GetChildPreferredWidth(),
      content_height + GetBottomMargin() + GetTopMargin());
}

void MenuItemView::Paint(gfx::Canvas* canvas, bool for_drag) {
  const MenuConfig& config = MenuConfig::instance();
  bool render_selection =
      (!for_drag && IsSelected() &&
       parent_menu_item_->GetSubmenu()->GetShowSelection(this) &&
       GetChildViewCount() == 0);

  int icon_x = config.item_left_margin;
  int top_margin = GetTopMargin();
  int bottom_margin = GetBottomMargin();
  int icon_y = top_margin + (height() - config.item_top_margin -
                             bottom_margin - config.check_height) / 2;
  int icon_height = config.check_height;
  int available_height = height() - top_margin - bottom_margin;

  // Render the background. As MenuScrollViewContainer draws the background, we
  // only need the background when we want it to look different, as when we're
  // selected.
  if (render_selection)
    canvas->AsCanvasSkia()->drawColor(kSelectedBackgroundColor,
                                      SkXfermode::kSrc_Mode);

  // Render the check.
  if (type_ == CHECKBOX && GetDelegate()->IsItemChecked(GetCommand())) {
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
    SkBitmap* check = rb.GetBitmapNamed(IDR_MENU_CHECK);
    // Don't use config.check_width here as it's padded to force more padding.
    gfx::Rect check_bounds(icon_x, icon_y, check->width(), icon_height);
    AdjustBoundsForRTLUI(&check_bounds);
    canvas->DrawBitmapInt(*check, check_bounds.x(), check_bounds.y());
  } else if (type_ == RADIO) {
    // This code comes from theme_draw.cc. See it for details.
    canvas->TranslateInt(
        icon_x,
        top_margin + (height() - top_margin - bottom_margin -
                      kIndicatorSize) / 2);

    SkPoint gradient_points[3];
    gradient_points[0].set(SkIntToScalar(0), SkIntToScalar(0));
    gradient_points[1].set(
        SkIntToScalar(0),
        SkIntToScalar(static_cast<int>(kIndicatorSize * kGradientStop)));
    gradient_points[2].set(SkIntToScalar(0), SkIntToScalar(kIndicatorSize));
    SkColor gradient_colors[3] = { kGradient0, kGradient1, kGradient2 };
    SkShader* shader = SkGradientShader::CreateLinear(
        gradient_points, gradient_colors, NULL, arraysize(gradient_points),
        SkShader::kClamp_TileMode, NULL);
    SkPaint paint;
    paint.setStyle(SkPaint::kFill_Style);
    paint.setAntiAlias(true);
    paint.setShader(shader);
    shader->unref();
    int radius = kIndicatorSize / 2;
    canvas->AsCanvasSkia()->drawCircle(radius, radius, radius, paint);

    paint.setStrokeWidth(SkIntToScalar(0));
    paint.setShader(NULL);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setColor(kBaseStroke);
    canvas->AsCanvasSkia()->drawCircle(radius, radius, radius, paint);

    if (GetDelegate()->IsItemChecked(GetCommand())) {
      SkPoint selected_gradient_points[2];
      selected_gradient_points[0].set(SkIntToScalar(0), SkIntToScalar(0));
      selected_gradient_points[1].set(
          SkIntToScalar(0),
          SkIntToScalar(kSelectedIndicatorSize));
      SkColor selected_gradient_colors[2] = { kRadioButtonIndicatorGradient0,
                                              kRadioButtonIndicatorGradient1 };
      shader = SkGradientShader::CreateLinear(
          selected_gradient_points, selected_gradient_colors, NULL,
          arraysize(selected_gradient_points), SkShader::kClamp_TileMode, NULL);
      paint.setShader(shader);
      shader->unref();
      paint.setStyle(SkPaint::kFill_Style);
      canvas->AsCanvasSkia()->drawCircle(radius, radius,
                                         kSelectedIndicatorSize / 2, paint);

      paint.setStrokeWidth(SkIntToScalar(0));
      paint.setShader(NULL);
      paint.setStyle(SkPaint::kStroke_Style);
      paint.setColor(kIndicatorStroke);
      canvas->AsCanvasSkia()->drawCircle(radius, radius,
                                         kSelectedIndicatorSize / 2, paint);
    }

    canvas->TranslateInt(
        -icon_x,
        -(top_margin + (height() - top_margin - bottom_margin -
                        kIndicatorSize) / 2));
  }

  // Render the foreground.
#if defined(OS_CHROMEOS)
  SkColor fg_color =
      IsEnabled() ? SK_ColorBLACK : SkColorSetRGB(0x80, 0x80, 0x80);
#else
  SkColor fg_color =
      IsEnabled() ? TextButton::kEnabledColor : TextButton::kDisabledColor;
#endif
  const gfx::Font& font = MenuConfig::instance().font;
  int accel_width = parent_menu_item_->GetSubmenu()->max_accelerator_width();
  int width = this->width() - item_right_margin_ - label_start_ - accel_width;
  gfx::Rect text_bounds(label_start_, top_margin +
                        (available_height - font.height()) / 2, width,
                        font.height());
  text_bounds.set_x(MirroredLeftPointForRect(text_bounds));
  canvas->DrawStringInt(GetTitle(), font, fg_color,
                        text_bounds.x(), text_bounds.y(), text_bounds.width(),
                        text_bounds.height(),
                        GetRootMenuItem()->GetDrawStringFlags());

  PaintAccelerator(canvas);

  // Render the icon.
  if (icon_.width() > 0) {
    gfx::Rect icon_bounds(config.item_left_margin,
                          top_margin + (height() - top_margin -
                          bottom_margin - icon_.height()) / 2,
                          icon_.width(),
                          icon_.height());
    icon_bounds.set_x(MirroredLeftPointForRect(icon_bounds));
    canvas->DrawBitmapInt(icon_, icon_bounds.x(), icon_bounds.y());
  }

  // Render the submenu indicator (arrow).
  if (HasSubmenu()) {
    gfx::Rect arrow_bounds(this->width() - item_right_margin_ +
                           config.label_to_arrow_padding,
                           top_margin + (available_height -
                                         config.arrow_width) / 2,
                           config.arrow_width, height());
    AdjustBoundsForRTLUI(&arrow_bounds);
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
    canvas->DrawBitmapInt(*rb.GetBitmapNamed(IDR_MENU_ARROW),
                          arrow_bounds.x(), arrow_bounds.y());
  }
}

}  // namespace views
<commit_msg>Fix a typo that caused wrong menu highlight color being used for ChromeOS.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/controls/menu/menu_item_view.h"

#include "app/resource_bundle.h"
#include "gfx/canvas_skia.h"
#include "gfx/favicon_size.h"
#include "grit/app_resources.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "views/controls/button/text_button.h"
#include "views/controls/menu/menu_config.h"
#include "views/controls/menu/submenu_view.h"

namespace views {

// Background color when the menu item is selected.
#if defined(OS_CHROMEOS)
static const SkColor kSelectedBackgroundColor = SkColorSetRGB(0xDC, 0xE4, 0xFA);
#else
static const SkColor kSelectedBackgroundColor = SkColorSetRGB(246, 249, 253);
#endif

// Size of the radio button inciator.
static const int kSelectedIndicatorSize = 5;
static const int kIndicatorSize = 10;

// Used for the radio indicator. See theme_draw for details.
static const double kGradientStop = .5;
static const SkColor kGradient0 = SkColorSetRGB(255, 255, 255);
static const SkColor kGradient1 = SkColorSetRGB(255, 255, 255);
static const SkColor kGradient2 = SkColorSetRGB(0xD8, 0xD8, 0xD8);
static const SkColor kBaseStroke = SkColorSetRGB(0x8F, 0x8F, 0x8F);
static const SkColor kRadioButtonIndicatorGradient0 =
    SkColorSetRGB(0, 0, 0);
static const SkColor kRadioButtonIndicatorGradient1 =
    SkColorSetRGB(0x83, 0x83, 0x83);

static const SkColor kIndicatorStroke = SkColorSetRGB(0, 0, 0);

gfx::Size MenuItemView::GetPreferredSize() {
  const gfx::Font& font = MenuConfig::instance().font;
  // TODO(sky): this is a workaround until I figure out why font.height()
  // isn't returning the right thing. We really only want to include
  // kFavIconSize if we're showing icons.
  int content_height = std::max(kFavIconSize, font.height());
  return gfx::Size(
      font.GetStringWidth(title_) + label_start_ + item_right_margin_ +
          GetChildPreferredWidth(),
      content_height + GetBottomMargin() + GetTopMargin());
}

void MenuItemView::Paint(gfx::Canvas* canvas, bool for_drag) {
  const MenuConfig& config = MenuConfig::instance();
  bool render_selection =
      (!for_drag && IsSelected() &&
       parent_menu_item_->GetSubmenu()->GetShowSelection(this) &&
       GetChildViewCount() == 0);

  int icon_x = config.item_left_margin;
  int top_margin = GetTopMargin();
  int bottom_margin = GetBottomMargin();
  int icon_y = top_margin + (height() - config.item_top_margin -
                             bottom_margin - config.check_height) / 2;
  int icon_height = config.check_height;
  int available_height = height() - top_margin - bottom_margin;

  // Render the background. As MenuScrollViewContainer draws the background, we
  // only need the background when we want it to look different, as when we're
  // selected.
  if (render_selection)
    canvas->AsCanvasSkia()->drawColor(kSelectedBackgroundColor,
                                      SkXfermode::kSrc_Mode);

  // Render the check.
  if (type_ == CHECKBOX && GetDelegate()->IsItemChecked(GetCommand())) {
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
    SkBitmap* check = rb.GetBitmapNamed(IDR_MENU_CHECK);
    // Don't use config.check_width here as it's padded to force more padding.
    gfx::Rect check_bounds(icon_x, icon_y, check->width(), icon_height);
    AdjustBoundsForRTLUI(&check_bounds);
    canvas->DrawBitmapInt(*check, check_bounds.x(), check_bounds.y());
  } else if (type_ == RADIO) {
    // This code comes from theme_draw.cc. See it for details.
    canvas->TranslateInt(
        icon_x,
        top_margin + (height() - top_margin - bottom_margin -
                      kIndicatorSize) / 2);

    SkPoint gradient_points[3];
    gradient_points[0].set(SkIntToScalar(0), SkIntToScalar(0));
    gradient_points[1].set(
        SkIntToScalar(0),
        SkIntToScalar(static_cast<int>(kIndicatorSize * kGradientStop)));
    gradient_points[2].set(SkIntToScalar(0), SkIntToScalar(kIndicatorSize));
    SkColor gradient_colors[3] = { kGradient0, kGradient1, kGradient2 };
    SkShader* shader = SkGradientShader::CreateLinear(
        gradient_points, gradient_colors, NULL, arraysize(gradient_points),
        SkShader::kClamp_TileMode, NULL);
    SkPaint paint;
    paint.setStyle(SkPaint::kFill_Style);
    paint.setAntiAlias(true);
    paint.setShader(shader);
    shader->unref();
    int radius = kIndicatorSize / 2;
    canvas->AsCanvasSkia()->drawCircle(radius, radius, radius, paint);

    paint.setStrokeWidth(SkIntToScalar(0));
    paint.setShader(NULL);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setColor(kBaseStroke);
    canvas->AsCanvasSkia()->drawCircle(radius, radius, radius, paint);

    if (GetDelegate()->IsItemChecked(GetCommand())) {
      SkPoint selected_gradient_points[2];
      selected_gradient_points[0].set(SkIntToScalar(0), SkIntToScalar(0));
      selected_gradient_points[1].set(
          SkIntToScalar(0),
          SkIntToScalar(kSelectedIndicatorSize));
      SkColor selected_gradient_colors[2] = { kRadioButtonIndicatorGradient0,
                                              kRadioButtonIndicatorGradient1 };
      shader = SkGradientShader::CreateLinear(
          selected_gradient_points, selected_gradient_colors, NULL,
          arraysize(selected_gradient_points), SkShader::kClamp_TileMode, NULL);
      paint.setShader(shader);
      shader->unref();
      paint.setStyle(SkPaint::kFill_Style);
      canvas->AsCanvasSkia()->drawCircle(radius, radius,
                                         kSelectedIndicatorSize / 2, paint);

      paint.setStrokeWidth(SkIntToScalar(0));
      paint.setShader(NULL);
      paint.setStyle(SkPaint::kStroke_Style);
      paint.setColor(kIndicatorStroke);
      canvas->AsCanvasSkia()->drawCircle(radius, radius,
                                         kSelectedIndicatorSize / 2, paint);
    }

    canvas->TranslateInt(
        -icon_x,
        -(top_margin + (height() - top_margin - bottom_margin -
                        kIndicatorSize) / 2));
  }

  // Render the foreground.
#if defined(OS_CHROMEOS)
  SkColor fg_color =
      IsEnabled() ? SK_ColorBLACK : SkColorSetRGB(0x80, 0x80, 0x80);
#else
  SkColor fg_color =
      IsEnabled() ? TextButton::kEnabledColor : TextButton::kDisabledColor;
#endif
  const gfx::Font& font = MenuConfig::instance().font;
  int accel_width = parent_menu_item_->GetSubmenu()->max_accelerator_width();
  int width = this->width() - item_right_margin_ - label_start_ - accel_width;
  gfx::Rect text_bounds(label_start_, top_margin +
                        (available_height - font.height()) / 2, width,
                        font.height());
  text_bounds.set_x(MirroredLeftPointForRect(text_bounds));
  canvas->DrawStringInt(GetTitle(), font, fg_color,
                        text_bounds.x(), text_bounds.y(), text_bounds.width(),
                        text_bounds.height(),
                        GetRootMenuItem()->GetDrawStringFlags());

  PaintAccelerator(canvas);

  // Render the icon.
  if (icon_.width() > 0) {
    gfx::Rect icon_bounds(config.item_left_margin,
                          top_margin + (height() - top_margin -
                          bottom_margin - icon_.height()) / 2,
                          icon_.width(),
                          icon_.height());
    icon_bounds.set_x(MirroredLeftPointForRect(icon_bounds));
    canvas->DrawBitmapInt(icon_, icon_bounds.x(), icon_bounds.y());
  }

  // Render the submenu indicator (arrow).
  if (HasSubmenu()) {
    gfx::Rect arrow_bounds(this->width() - item_right_margin_ +
                           config.label_to_arrow_padding,
                           top_margin + (available_height -
                                         config.arrow_width) / 2,
                           config.arrow_width, height());
    AdjustBoundsForRTLUI(&arrow_bounds);
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
    canvas->DrawBitmapInt(*rb.GetBitmapNamed(IDR_MENU_ARROW),
                          arrow_bounds.x(), arrow_bounds.y());
  }
}

}  // namespace views
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  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 "kernel/yosys.h"
#include "kernel/sigtools.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

#include "passes/pmgen/ice40_dsp_pm.h"

void create_ice40_dsp(ice40_dsp_pm &pm)
{
	auto &st = pm.st_ice40_dsp;

#if 0
	log("\n");
	log("ffA:   %s\n", log_id(st.ffA, "--"));
	log("ffB:   %s\n", log_id(st.ffB, "--"));
	log("mul:   %s\n", log_id(st.mul, "--"));
	log("ffY:   %s\n", log_id(st.ffY, "--"));
	log("addAB: %s\n", log_id(st.addAB, "--"));
	log("muxAB: %s\n", log_id(st.muxAB, "--"));
	log("ffS:   %s\n", log_id(st.ffS, "--"));
#endif

	log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul));

	if (GetSize(st.sigA) > 16) {
		log("  input A (%s) is too large (%d > 16).\n", log_signal(st.sigA), GetSize(st.sigA));
		return;
	}

	if (GetSize(st.sigB) > 16) {
		log("  input B (%s) is too large (%d > 16).\n", log_signal(st.sigB), GetSize(st.sigB));
		return;
	}

	if (GetSize(st.sigS) > 32) {
		log("  accumulator (%s) is too large (%d > 32).\n", log_signal(st.sigS), GetSize(st.sigS));
		return;
	}

	if (GetSize(st.sigY) > 32) {
		log("  output (%s) is too large (%d > 32).\n", log_signal(st.sigY), GetSize(st.sigY));
		return;
	}

	bool mul_signed = st.mul->getParam("\\A_SIGNED").as_bool();

	if (mul_signed) {
		log("  inference of signed iCE40 DSP arithmetic is currently not supported.\n");
		return;
	}

	log("  replacing $mul with SB_MAC16 cell.\n");

	Cell *cell = pm.module->addCell(NEW_ID, "\\SB_MAC16");
	pm.module->swap_names(cell, st.mul);

	// SB_MAC16 Input Interface

	SigSpec A = st.sigA;
	A.extend_u0(16, mul_signed);

	SigSpec B = st.sigB;
	B.extend_u0(16, mul_signed);

	SigSpec CD;
	if (st.muxA)
		CD = st.muxA->getPort("\\B");
	if (st.muxB)
		CD = st.muxB->getPort("\\A");
	CD.extend_u0(32, mul_signed);

	cell->setPort("\\A", A);
	cell->setPort("\\B", B);
	cell->setPort("\\C", CD.extract(0, 16));
	cell->setPort("\\D", CD.extract(16, 16));

	cell->setParam("\\A_REG", st.ffA ? State::S1 : State::S0);
	cell->setParam("\\B_REG", st.ffB ? State::S1 : State::S0);

	cell->setPort("\\AHOLD", State::S0);
	cell->setPort("\\BHOLD", State::S0);
	cell->setPort("\\CHOLD", State::S0);
	cell->setPort("\\DHOLD", State::S0);

	cell->setPort("\\IRSTTOP", State::S0);
	cell->setPort("\\IRSTBOT", State::S0);

	if (st.clock_vld)
	{
		cell->setPort("\\CLK", st.clock);
		cell->setPort("\\CE", State::S1);
		cell->setParam("\\NEG_TRIGGER", st.clock_pol ? State::S0 : State::S1);

		log("  clock: %s (%s)", log_signal(st.clock), st.clock_pol ? "posedge" : "negedge");

		if (st.ffA)
			log(" ffA:%s", log_id(st.ffA));

		if (st.ffB)
			log(" ffB:%s", log_id(st.ffB));

		if (st.ffY)
			log(" ffY:%s", log_id(st.ffY));

		if (st.ffS)
			log(" ffS:%s", log_id(st.ffS));

		log("\n");
	}
	else
	{
		cell->setPort("\\CLK", State::S0);
		cell->setPort("\\CE", State::S0);
		cell->setParam("\\NEG_TRIGGER", State::S0);
	}

	// SB_MAC16 Cascade Interface

	cell->setPort("\\SIGNEXTIN", State::Sx);
	cell->setPort("\\SIGNEXTOUT", pm.module->addWire(NEW_ID));

	cell->setPort("\\CI", State::Sx);
	cell->setPort("\\CO", pm.module->addWire(NEW_ID));

	cell->setPort("\\ACCUMCI", State::Sx);
	cell->setPort("\\ACCUMCO", pm.module->addWire(NEW_ID));

	// SB_MAC16 Output Interface

	SigSpec O = st.ffS ? st.sigS : st.sigY;
	if (GetSize(O) < 32)
		O.append(pm.module->addWire(NEW_ID, 32-GetSize(O)));

	cell->setPort("\\O", O);

	if (st.addAB) {
		log("  accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type));
		cell->setPort("\\ADDSUBTOP", st.addAB->type == "$add" ? State::S0 : State::S1);
		cell->setPort("\\ADDSUBBOT", st.addAB->type == "$add" ? State::S0 : State::S1);
	} else {
		cell->setPort("\\ADDSUBTOP", State::S0);
		cell->setPort("\\ADDSUBBOT", State::S0);
	}

	cell->setPort("\\ORSTTOP", State::S0);
	cell->setPort("\\ORSTBOT", State::S0);

	cell->setPort("\\OHOLDTOP", State::S0);
	cell->setPort("\\OHOLDBOT", State::S0);

	SigSpec acc_reset = State::S0;
	if (st.muxA)
		acc_reset = st.muxA->getPort("\\S");
	if (st.muxB)
		acc_reset = pm.module->Not(NEW_ID, st.muxB->getPort("\\S"));

	cell->setPort("\\OLOADTOP", acc_reset);
	cell->setPort("\\OLOADBOT", acc_reset);

	// SB_MAC16 Remaining Parameters

	cell->setParam("\\C_REG", State::S0);
	cell->setParam("\\D_REG", State::S0);

	cell->setParam("\\TOP_8x8_MULT_REG", st.ffY ? State::S1 : State::S0);
	cell->setParam("\\BOT_8x8_MULT_REG", st.ffY ? State::S1 : State::S0);
	cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffY ? State::S1 : State::S0);
	cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0);

	cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffS ? 1 : 3, 2));
	cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2));
	cell->setParam("\\TOPADDSUB_UPPERINPUT", State::S0);
	cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2));

	cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffS ? 1 : 3, 2));
	cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2));
	cell->setParam("\\BOTADDSUB_UPPERINPUT", State::S0);
	cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2));

	cell->setParam("\\MODE_8x8", State::S0);
	cell->setParam("\\A_SIGNED", mul_signed ? State::S1 : State::S0);
	cell->setParam("\\B_SIGNED", mul_signed ? State::S1 : State::S0);

	pm.autoremove(st.mul);
	pm.autoremove(st.ffY);
	pm.autoremove(st.ffS);
}

struct Ice40DspPass : public Pass {
	Ice40DspPass() : Pass("ice40_dsp", "iCE40: map multipliers") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    ice40_dsp [options] [selection]\n");
		log("\n");
		log("Map multipliers and multiply-accumulate blocks to iCE40 DSP resources.\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		log_header(design, "Executing ICE40_DSP pass (map multipliers).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-singleton") {
			// 	singleton_mode = true;
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
			ice40_dsp_pm(module, module->selected_cells()).run_ice40_dsp(create_ice40_dsp);
	}
} Ice40DspPass;

PRIVATE_NAMESPACE_END
<commit_msg>Do not restrict multiplier to unsigned<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  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 "kernel/yosys.h"
#include "kernel/sigtools.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

#include "passes/pmgen/ice40_dsp_pm.h"

void create_ice40_dsp(ice40_dsp_pm &pm)
{
	auto &st = pm.st_ice40_dsp;

#if 0
	log("\n");
	log("ffA:   %s\n", log_id(st.ffA, "--"));
	log("ffB:   %s\n", log_id(st.ffB, "--"));
	log("mul:   %s\n", log_id(st.mul, "--"));
	log("ffY:   %s\n", log_id(st.ffY, "--"));
	log("addAB: %s\n", log_id(st.addAB, "--"));
	log("muxAB: %s\n", log_id(st.muxAB, "--"));
	log("ffS:   %s\n", log_id(st.ffS, "--"));
#endif

	log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul));

	if (GetSize(st.sigA) > 16) {
		log("  input A (%s) is too large (%d > 16).\n", log_signal(st.sigA), GetSize(st.sigA));
		return;
	}

	if (GetSize(st.sigB) > 16) {
		log("  input B (%s) is too large (%d > 16).\n", log_signal(st.sigB), GetSize(st.sigB));
		return;
	}

	if (GetSize(st.sigS) > 32) {
		log("  accumulator (%s) is too large (%d > 32).\n", log_signal(st.sigS), GetSize(st.sigS));
		return;
	}

	if (GetSize(st.sigY) > 32) {
		log("  output (%s) is too large (%d > 32).\n", log_signal(st.sigY), GetSize(st.sigY));
		return;
	}

	bool mul_signed = st.mul->getParam("\\A_SIGNED").as_bool();

	log("  replacing $mul with SB_MAC16 cell.\n");

	Cell *cell = pm.module->addCell(NEW_ID, "\\SB_MAC16");
	pm.module->swap_names(cell, st.mul);

	// SB_MAC16 Input Interface

	SigSpec A = st.sigA;
	A.extend_u0(16, mul_signed);

	SigSpec B = st.sigB;
	B.extend_u0(16, mul_signed);

	SigSpec CD;
	if (st.muxA)
		CD = st.muxA->getPort("\\B");
	if (st.muxB)
		CD = st.muxB->getPort("\\A");
	CD.extend_u0(32, mul_signed);

	cell->setPort("\\A", A);
	cell->setPort("\\B", B);
	cell->setPort("\\C", CD.extract(0, 16));
	cell->setPort("\\D", CD.extract(16, 16));

	cell->setParam("\\A_REG", st.ffA ? State::S1 : State::S0);
	cell->setParam("\\B_REG", st.ffB ? State::S1 : State::S0);

	cell->setPort("\\AHOLD", State::S0);
	cell->setPort("\\BHOLD", State::S0);
	cell->setPort("\\CHOLD", State::S0);
	cell->setPort("\\DHOLD", State::S0);

	cell->setPort("\\IRSTTOP", State::S0);
	cell->setPort("\\IRSTBOT", State::S0);

	if (st.clock_vld)
	{
		cell->setPort("\\CLK", st.clock);
		cell->setPort("\\CE", State::S1);
		cell->setParam("\\NEG_TRIGGER", st.clock_pol ? State::S0 : State::S1);

		log("  clock: %s (%s)", log_signal(st.clock), st.clock_pol ? "posedge" : "negedge");

		if (st.ffA)
			log(" ffA:%s", log_id(st.ffA));

		if (st.ffB)
			log(" ffB:%s", log_id(st.ffB));

		if (st.ffY)
			log(" ffY:%s", log_id(st.ffY));

		if (st.ffS)
			log(" ffS:%s", log_id(st.ffS));

		log("\n");
	}
	else
	{
		cell->setPort("\\CLK", State::S0);
		cell->setPort("\\CE", State::S0);
		cell->setParam("\\NEG_TRIGGER", State::S0);
	}

	// SB_MAC16 Cascade Interface

	cell->setPort("\\SIGNEXTIN", State::Sx);
	cell->setPort("\\SIGNEXTOUT", pm.module->addWire(NEW_ID));

	cell->setPort("\\CI", State::Sx);
	cell->setPort("\\CO", pm.module->addWire(NEW_ID));

	cell->setPort("\\ACCUMCI", State::Sx);
	cell->setPort("\\ACCUMCO", pm.module->addWire(NEW_ID));

	// SB_MAC16 Output Interface

	SigSpec O = st.ffS ? st.sigS : st.sigY;
	if (GetSize(O) < 32)
		O.append(pm.module->addWire(NEW_ID, 32-GetSize(O)));

	cell->setPort("\\O", O);

	if (st.addAB) {
		log("  accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type));
		cell->setPort("\\ADDSUBTOP", st.addAB->type == "$add" ? State::S0 : State::S1);
		cell->setPort("\\ADDSUBBOT", st.addAB->type == "$add" ? State::S0 : State::S1);
	} else {
		cell->setPort("\\ADDSUBTOP", State::S0);
		cell->setPort("\\ADDSUBBOT", State::S0);
	}

	cell->setPort("\\ORSTTOP", State::S0);
	cell->setPort("\\ORSTBOT", State::S0);

	cell->setPort("\\OHOLDTOP", State::S0);
	cell->setPort("\\OHOLDBOT", State::S0);

	SigSpec acc_reset = State::S0;
	if (st.muxA)
		acc_reset = st.muxA->getPort("\\S");
	if (st.muxB)
		acc_reset = pm.module->Not(NEW_ID, st.muxB->getPort("\\S"));

	cell->setPort("\\OLOADTOP", acc_reset);
	cell->setPort("\\OLOADBOT", acc_reset);

	// SB_MAC16 Remaining Parameters

	cell->setParam("\\C_REG", State::S0);
	cell->setParam("\\D_REG", State::S0);

	cell->setParam("\\TOP_8x8_MULT_REG", st.ffY ? State::S1 : State::S0);
	cell->setParam("\\BOT_8x8_MULT_REG", st.ffY ? State::S1 : State::S0);
	cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffY ? State::S1 : State::S0);
	cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0);

	cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffS ? 1 : 3, 2));
	cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2));
	cell->setParam("\\TOPADDSUB_UPPERINPUT", State::S0);
	cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2));

	cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffS ? 1 : 3, 2));
	cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2));
	cell->setParam("\\BOTADDSUB_UPPERINPUT", State::S0);
	cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2));

	cell->setParam("\\MODE_8x8", State::S0);
	cell->setParam("\\A_SIGNED", mul_signed ? State::S1 : State::S0);
	cell->setParam("\\B_SIGNED", mul_signed ? State::S1 : State::S0);

	pm.autoremove(st.mul);
	pm.autoremove(st.ffY);
	pm.autoremove(st.ffS);
}

struct Ice40DspPass : public Pass {
	Ice40DspPass() : Pass("ice40_dsp", "iCE40: map multipliers") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    ice40_dsp [options] [selection]\n");
		log("\n");
		log("Map multipliers and multiply-accumulate blocks to iCE40 DSP resources.\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		log_header(design, "Executing ICE40_DSP pass (map multipliers).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-singleton") {
			// 	singleton_mode = true;
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
			ice40_dsp_pm(module, module->selected_cells()).run_ice40_dsp(create_ice40_dsp);
	}
} Ice40DspPass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *                2019  Eddie Hung <eddie@fpgeh.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 "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct ClkPartPass : public Pass {
	ClkPartPass() : Pass("clkpart", "partition design according to clock domain") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    clkpart [options] [selection]\n");
		log("\n");
		log("Partition the contents of selected modules according to the clock (and optionally\n");
		log("the enable) domains of its $_DFF* cells by extracting them into sub-modules,\n");
		log("using the `submod` command.\n");
		log("Sub-modules created by this command are marked with a 'clkpart' attribute.\n");
		log("\n");
		log("    -unpart\n");
		log("        undo this operation within the selected modules, by flattening those with\n");
		log("        a 'clkpart' attribute into those modules without this attribute.\n");
		log("\n");
		log("    -enable\n");
		log("        also consider enable domains.\n");
		log("\n");
	}

	bool unpart_mode, enable_mode;

	void clear_flags() YS_OVERRIDE
	{
		unpart_mode = false;
		enable_mode = false;
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		log_header(design, "Executing CLKPART pass (TODO).\n");
		log_push();

		clear_flags();

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-unpart") {
				unpart_mode = true;
				continue;
			}
			if (args[argidx] == "-enable") {
				enable_mode = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (unpart_mode)
			unpart(design);
		else
			part(design);

		log_pop();
	}

	void part(RTLIL::Design *design)
	{
		CellTypes ct(design);
		SigMap assign_map;

		for (auto mod : design->selected_modules())
		{
			if (mod->processes.size() > 0) {
				log("Skipping module %s as it contains processes.\n", log_id(mod));
				continue;
			}

			assign_map.set(mod);

			std::vector<RTLIL::Cell*> all_cells = mod->selected_cells();
			std::set<RTLIL::Cell*> unassigned_cells(all_cells.begin(), all_cells.end());

			std::set<RTLIL::Cell*> expand_queue, next_expand_queue;
			std::set<RTLIL::Cell*> expand_queue_up, next_expand_queue_up;
			std::set<RTLIL::Cell*> expand_queue_down, next_expand_queue_down;

			typedef tuple<bool, RTLIL::SigSpec, bool, RTLIL::SigSpec> clkdomain_t;
			std::map<clkdomain_t, vector<RTLIL::IdString>> assigned_cells;
			std::map<RTLIL::Cell*, clkdomain_t> assigned_cells_reverse;

			std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_to_bit, cell_to_bit_up, cell_to_bit_down;
			std::map<RTLIL::SigBit, std::set<RTLIL::Cell*>> bit_to_cell, bit_to_cell_up, bit_to_cell_down;

			for (auto cell : all_cells)
			{
				clkdomain_t key;

				for (auto &conn : cell->connections())
				for (auto bit : conn.second) {
					bit = assign_map(bit);
					if (bit.wire != nullptr) {
						cell_to_bit[cell].insert(bit);
						bit_to_cell[bit].insert(cell);
						if (ct.cell_input(cell->type, conn.first)) {
							cell_to_bit_up[cell].insert(bit);
							bit_to_cell_down[bit].insert(cell);
						}
						if (ct.cell_output(cell->type, conn.first)) {
							cell_to_bit_down[cell].insert(bit);
							bit_to_cell_up[bit].insert(cell);
						}
					}
				}

				if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
				{
					key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec());
				}
				else
				if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
				{
					bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_));
					bool this_en_pol = !enable_mode || cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_));
					key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, enable_mode ? assign_map(cell->getPort(ID(E)) : RTLIL::SigSpec()));
				}
				else
					continue;

				unassigned_cells.erase(cell);
				expand_queue.insert(cell);
				expand_queue_up.insert(cell);
				expand_queue_down.insert(cell);

				assigned_cells[key].push_back(cell->name);
				assigned_cells_reverse[cell] = key;
			}

			while (!expand_queue_up.empty() || !expand_queue_down.empty())
			{
				if (!expand_queue_up.empty())
				{
					RTLIL::Cell *cell = *expand_queue_up.begin();
					clkdomain_t key = assigned_cells_reverse.at(cell);
					expand_queue_up.erase(cell);

					for (auto bit : cell_to_bit_up[cell])
					for (auto c : bit_to_cell_up[bit])
						if (unassigned_cells.count(c)) {
							unassigned_cells.erase(c);
							next_expand_queue_up.insert(c);
							assigned_cells[key].push_back(c->name);
							assigned_cells_reverse[c] = key;
							expand_queue.insert(c);
						}
				}

				if (!expand_queue_down.empty())
				{
					RTLIL::Cell *cell = *expand_queue_down.begin();
					clkdomain_t key = assigned_cells_reverse.at(cell);
					expand_queue_down.erase(cell);

					for (auto bit : cell_to_bit_down[cell])
					for (auto c : bit_to_cell_down[bit])
						if (unassigned_cells.count(c)) {
							unassigned_cells.erase(c);
							next_expand_queue_up.insert(c);
							assigned_cells[key].push_back(c->name);
							assigned_cells_reverse[c] = key;
							expand_queue.insert(c);
						}
				}

				if (expand_queue_up.empty() && expand_queue_down.empty()) {
					expand_queue_up.swap(next_expand_queue_up);
					expand_queue_down.swap(next_expand_queue_down);
				}
			}

			while (!expand_queue.empty())
			{
				RTLIL::Cell *cell = *expand_queue.begin();
				clkdomain_t key = assigned_cells_reverse.at(cell);
				expand_queue.erase(cell);

				for (auto bit : cell_to_bit.at(cell)) {
					for (auto c : bit_to_cell[bit])
						if (unassigned_cells.count(c)) {
							unassigned_cells.erase(c);
							next_expand_queue.insert(c);
							assigned_cells[key].push_back(c->name);
							assigned_cells_reverse[c] = key;
						}
					bit_to_cell[bit].clear();
				}

				if (expand_queue.empty())
					expand_queue.swap(next_expand_queue);
			}

			clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec());
			for (auto cell : unassigned_cells) {
				assigned_cells[key].push_back(cell->name);
				assigned_cells_reverse[cell] = key;
			}

			log_header(design, "Summary of detected clock domains:\n");
			for (auto &it : assigned_cells)
				log("  %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second),
						std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)),
						std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first)));

			for (auto &it : assigned_cells) {
				RTLIL::Selection sel(false);
				sel.selected_members[mod->name] = pool<IdString>(it.second.begin(), it.second.end());

				RTLIL::IdString submod = stringf("%s.%s", mod->name.c_str(), NEW_ID.c_str());
				Pass::call_on_selection(design, sel, stringf("submod -name %s", submod.c_str()));

				design->module(submod)->set_bool_attribute(ID(clkpart));
			}
		}
	}

	void unpart(RTLIL::Design *design)
	{
		vector<Module*> keeped;
		for (auto mod : design->selected_modules()) {
			if (mod->get_bool_attribute(ID(clkpart)))
				continue;
			if (mod->get_bool_attribute(ID(keep_hierarchy)))
				continue;
			keeped.push_back(mod);
			mod->set_bool_attribute(ID(keep_hierarchy));
		}

		Pass::call(design, "flatten");

		for (auto mod : keeped)
			mod->set_bool_attribute(ID(keep_hierarchy), false);

	}
} ClkPartPass;

PRIVATE_NAMESPACE_END
<commit_msg>Brackets<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *                2019  Eddie Hung <eddie@fpgeh.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 "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct ClkPartPass : public Pass {
	ClkPartPass() : Pass("clkpart", "partition design according to clock domain") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    clkpart [options] [selection]\n");
		log("\n");
		log("Partition the contents of selected modules according to the clock (and optionally\n");
		log("the enable) domains of its $_DFF* cells by extracting them into sub-modules,\n");
		log("using the `submod` command.\n");
		log("Sub-modules created by this command are marked with a 'clkpart' attribute.\n");
		log("\n");
		log("    -unpart\n");
		log("        undo this operation within the selected modules, by flattening those with\n");
		log("        a 'clkpart' attribute into those modules without this attribute.\n");
		log("\n");
		log("    -enable\n");
		log("        also consider enable domains.\n");
		log("\n");
	}

	bool unpart_mode, enable_mode;

	void clear_flags() YS_OVERRIDE
	{
		unpart_mode = false;
		enable_mode = false;
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		log_header(design, "Executing CLKPART pass (TODO).\n");
		log_push();

		clear_flags();

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-unpart") {
				unpart_mode = true;
				continue;
			}
			if (args[argidx] == "-enable") {
				enable_mode = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (unpart_mode)
			unpart(design);
		else
			part(design);

		log_pop();
	}

	void part(RTLIL::Design *design)
	{
		CellTypes ct(design);
		SigMap assign_map;

		for (auto mod : design->selected_modules())
		{
			if (mod->processes.size() > 0) {
				log("Skipping module %s as it contains processes.\n", log_id(mod));
				continue;
			}

			assign_map.set(mod);

			std::vector<RTLIL::Cell*> all_cells = mod->selected_cells();
			std::set<RTLIL::Cell*> unassigned_cells(all_cells.begin(), all_cells.end());

			std::set<RTLIL::Cell*> expand_queue, next_expand_queue;
			std::set<RTLIL::Cell*> expand_queue_up, next_expand_queue_up;
			std::set<RTLIL::Cell*> expand_queue_down, next_expand_queue_down;

			typedef tuple<bool, RTLIL::SigSpec, bool, RTLIL::SigSpec> clkdomain_t;
			std::map<clkdomain_t, vector<RTLIL::IdString>> assigned_cells;
			std::map<RTLIL::Cell*, clkdomain_t> assigned_cells_reverse;

			std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_to_bit, cell_to_bit_up, cell_to_bit_down;
			std::map<RTLIL::SigBit, std::set<RTLIL::Cell*>> bit_to_cell, bit_to_cell_up, bit_to_cell_down;

			for (auto cell : all_cells)
			{
				clkdomain_t key;

				for (auto &conn : cell->connections())
				for (auto bit : conn.second) {
					bit = assign_map(bit);
					if (bit.wire != nullptr) {
						cell_to_bit[cell].insert(bit);
						bit_to_cell[bit].insert(cell);
						if (ct.cell_input(cell->type, conn.first)) {
							cell_to_bit_up[cell].insert(bit);
							bit_to_cell_down[bit].insert(cell);
						}
						if (ct.cell_output(cell->type, conn.first)) {
							cell_to_bit_down[cell].insert(bit);
							bit_to_cell_up[bit].insert(cell);
						}
					}
				}

				if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
				{
					key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec());
				}
				else
				if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
				{
					bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_));
					bool this_en_pol = !enable_mode || cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_));
					key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, enable_mode ? assign_map(cell->getPort(ID(E))) : RTLIL::SigSpec());
				}
				else
					continue;

				unassigned_cells.erase(cell);
				expand_queue.insert(cell);
				expand_queue_up.insert(cell);
				expand_queue_down.insert(cell);

				assigned_cells[key].push_back(cell->name);
				assigned_cells_reverse[cell] = key;
			}

			while (!expand_queue_up.empty() || !expand_queue_down.empty())
			{
				if (!expand_queue_up.empty())
				{
					RTLIL::Cell *cell = *expand_queue_up.begin();
					clkdomain_t key = assigned_cells_reverse.at(cell);
					expand_queue_up.erase(cell);

					for (auto bit : cell_to_bit_up[cell])
					for (auto c : bit_to_cell_up[bit])
						if (unassigned_cells.count(c)) {
							unassigned_cells.erase(c);
							next_expand_queue_up.insert(c);
							assigned_cells[key].push_back(c->name);
							assigned_cells_reverse[c] = key;
							expand_queue.insert(c);
						}
				}

				if (!expand_queue_down.empty())
				{
					RTLIL::Cell *cell = *expand_queue_down.begin();
					clkdomain_t key = assigned_cells_reverse.at(cell);
					expand_queue_down.erase(cell);

					for (auto bit : cell_to_bit_down[cell])
					for (auto c : bit_to_cell_down[bit])
						if (unassigned_cells.count(c)) {
							unassigned_cells.erase(c);
							next_expand_queue_up.insert(c);
							assigned_cells[key].push_back(c->name);
							assigned_cells_reverse[c] = key;
							expand_queue.insert(c);
						}
				}

				if (expand_queue_up.empty() && expand_queue_down.empty()) {
					expand_queue_up.swap(next_expand_queue_up);
					expand_queue_down.swap(next_expand_queue_down);
				}
			}

			while (!expand_queue.empty())
			{
				RTLIL::Cell *cell = *expand_queue.begin();
				clkdomain_t key = assigned_cells_reverse.at(cell);
				expand_queue.erase(cell);

				for (auto bit : cell_to_bit.at(cell)) {
					for (auto c : bit_to_cell[bit])
						if (unassigned_cells.count(c)) {
							unassigned_cells.erase(c);
							next_expand_queue.insert(c);
							assigned_cells[key].push_back(c->name);
							assigned_cells_reverse[c] = key;
						}
					bit_to_cell[bit].clear();
				}

				if (expand_queue.empty())
					expand_queue.swap(next_expand_queue);
			}

			clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec());
			for (auto cell : unassigned_cells) {
				assigned_cells[key].push_back(cell->name);
				assigned_cells_reverse[cell] = key;
			}

			log_header(design, "Summary of detected clock domains:\n");
			for (auto &it : assigned_cells)
				log("  %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second),
						std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)),
						std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first)));

			for (auto &it : assigned_cells) {
				RTLIL::Selection sel(false);
				sel.selected_members[mod->name] = pool<IdString>(it.second.begin(), it.second.end());

				RTLIL::IdString submod = stringf("%s.%s", mod->name.c_str(), NEW_ID.c_str());
				Pass::call_on_selection(design, sel, stringf("submod -name %s", submod.c_str()));

				design->module(submod)->set_bool_attribute(ID(clkpart));
			}
		}
	}

	void unpart(RTLIL::Design *design)
	{
		vector<Module*> keeped;
		for (auto mod : design->selected_modules()) {
			if (mod->get_bool_attribute(ID(clkpart)))
				continue;
			if (mod->get_bool_attribute(ID(keep_hierarchy)))
				continue;
			keeped.push_back(mod);
			mod->set_bool_attribute(ID(keep_hierarchy));
		}

		Pass::call(design, "flatten");

		for (auto mod : keeped)
			mod->set_bool_attribute(ID(keep_hierarchy), false);

	}
} ClkPartPass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>#include "vector.h"
#include "MinIMU9.h"
#include "version.h"
#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <system_error>
#include <boost/program_options.hpp>

namespace opts = boost::program_options;

// TODO: print warning if accelerometer magnitude is not close to 1 when starting up

// An Euler angle could take 8 chars: -234.678, but usually we only need 6.
float field_width = 6;
#define FLOAT_FORMAT std::fixed << std::setprecision(3) << std::setw(field_width)

std::ostream & operator << (std::ostream & os, const vector & vector)
{
    return os << FLOAT_FORMAT << vector(0) << ' '
              << FLOAT_FORMAT << vector(1) << ' '
              << FLOAT_FORMAT << vector(2);
}

std::ostream & operator << (std::ostream & os, const matrix & matrix)
{
    return os << (vector)matrix.row(0) << ' '
              << (vector)matrix.row(1) << ' '
              << (vector)matrix.row(2);
}

std::ostream & operator << (std::ostream & os, const quaternion & quat)
{
    return os << FLOAT_FORMAT << quat.w() << ' '
              << FLOAT_FORMAT << quat.x() << ' '
              << FLOAT_FORMAT << quat.y() << ' '
              << FLOAT_FORMAT << quat.z();
}

typedef void rotation_output_function(quaternion& rotation);

void output_quaternion(quaternion & rotation)
{
    std::cout << rotation;
}

void output_matrix(quaternion & rotation)
{
    std::cout << rotation.toRotationMatrix();
}

void output_euler(quaternion & rotation)
{
    std::cout << (vector)(rotation.toRotationMatrix().eulerAngles(2, 1, 0) * (180 / M_PI));
}

int millis()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (tv.tv_sec) * 1000 + (tv.tv_usec)/1000;
}

void streamRawValues(IMU& imu)
{
    imu.enable();
    while(1)
    {
        imu.read();
        printf("%7d %7d %7d  %7d %7d %7d  %7d %7d %7d\n",
               imu.raw_m[0], imu.raw_m[1], imu.raw_m[2],
               imu.raw_a[0], imu.raw_a[1], imu.raw_a[2],
               imu.raw_g[0], imu.raw_g[1], imu.raw_g[2]
        );
        usleep(20*1000);
    }
}

//! Uses the acceleration and magnetic field readings from the compass
// to get a noisy estimate of the current rotation matrix.
// This function is where we define the coordinate system we are using
// for the ground coords:  North, East, Down.
matrix rotationFromCompass(const vector& acceleration, const vector& magnetic_field)
{
    vector down = -acceleration;     // usually true
    vector east = down.cross(magnetic_field); // actually it's magnetic east
    vector north = east.cross(down);

    east.normalize();
    north.normalize();
    down.normalize();

    matrix r;
    r.row(0) = north;
    r.row(1) = east;
    r.row(2) = down;
    return r;
}

typedef void fuse_function(quaternion& rotation, float dt, const vector& angular_velocity,
                  const vector& acceleration, const vector& magnetic_field);

void fuse_compass_only(quaternion& rotation, float dt, const vector& angular_velocity,
  const vector& acceleration, const vector& magnetic_field)
{
    // Implicit conversion of rotation matrix to quaternion.
    rotation = rotationFromCompass(acceleration, magnetic_field);
}

// Uses the given angular velocity and time interval to calculate
// a rotation and applies that rotation to the given quaternion.
// w is angular velocity in radians per second.
// dt is the time.
void rotate(quaternion& rotation, const vector& w, float dt)
{
    // Multiply by first order approximation of the
    // quaternion representing this rotation.
    rotation *= quaternion(1, w(0)*dt/2, w(1)*dt/2, w(2)*dt/2);
    rotation.normalize();
}

void fuse_gyro_only(quaternion& rotation, float dt, const vector& angular_velocity,
  const vector& acceleration, const vector& magnetic_field)
{
    rotate(rotation, angular_velocity, dt);
}

void fuse_default(quaternion& rotation, float dt, const vector& angular_velocity,
  const vector& acceleration, const vector& magnetic_field)
{
    vector correction = vector(0, 0, 0);

    if (abs(acceleration.norm() - 1) <= 0.3)
    {
        // The magnetidude of acceleration is close to 1 g, so
        // it might be pointing up and we can do drift correction.

        const float correction_strength = 1;

        matrix rotationCompass = rotationFromCompass(acceleration, magnetic_field);
        matrix rotationMatrix = rotation.toRotationMatrix();

        correction = (
            rotationCompass.row(0).cross(rotationMatrix.row(0)) +
            rotationCompass.row(1).cross(rotationMatrix.row(1)) +
            rotationCompass.row(2).cross(rotationMatrix.row(2))
          ) * correction_strength;

    }

    rotate(rotation, angular_velocity + correction, dt);
}

void ahrs(IMU & imu, fuse_function * fuse, rotation_output_function * output)
{
    imu.loadCalibration();
    imu.enable();
    imu.measureOffsets();

    // The quaternion that can convert a vector in body coordinates
    // to ground coordinates when it its changed to a matrix.
    quaternion rotation = quaternion::Identity();

    int start = millis(); // truncate 64-bit return value
    while(1)
    {
        int last_start = start;
        start = millis();
        float dt = (start-last_start)/1000.0;
        if (dt < 0){ throw std::runtime_error("Time went backwards."); }

        vector angular_velocity = imu.readGyro();
        vector acceleration = imu.readAcc();
        vector magnetic_field = imu.readMag();

        fuse(rotation, dt, angular_velocity, acceleration, magnetic_field);

        output(rotation);
        std::cout << "  " << acceleration << "  " << magnetic_field << std::endl << std::flush;

        // Ensure that each iteration of the loop takes at least 20 ms.
        while(millis() - start < 20)
        {
            usleep(1000);
        }
    }
}

int main(int argc, char *argv[])
{
    try
    {
        // Define what all the command-line parameters are.
        std::string mode, output_mode, i2cDevice;
        opts::options_description desc("Allowed options");
        desc.add_options()
            ("help,h", "produce help message")
            ("version,v", "print version number")
            ("i2c-bus,b", opts::value<std::string>(&i2cDevice)->default_value("/dev/i2c-0"),
             "i2c-bus the IMU is connected to")
            ("mode", opts::value<std::string>(&mode)->default_value("normal"),
             "specifies what algorithm to use.\n"
             "normal: Fuse compass and gyro.\n"
             "gyro-only:  Use only gyro (drifts).\n"
             "compass-only:  Use only compass (noisy).\n"
             "raw: Just print raw values from sensors.")
            ("output", opts::value<std::string>(&output_mode)->default_value("matrix"),
             "specifies how to output the orientation.\n"
             "matrix: Direction Cosine Matrix.\n"
             "quaternion: Quaternion.\n"
             "euler: Euler angles (yaw, pitch, roll).\n")
            ;
        opts::variables_map options;
        opts::store(opts::command_line_parser(argc, argv).options(desc).run(), options);
        opts::notify(options);

        if(options.count("help"))
        {
            std::cout << desc << std::endl;
            return 0;
        }

        if (options.count("version"))
        {
            std::cout << VERSION << std::endl;
            return 0;
        }

        MinIMU9 imu(i2cDevice.c_str());

        rotation_output_function * output;

        // Figure out the output mode.
        if (output_mode == "matrix")
        {
            output = &output_matrix;
        }
        else if (output_mode == "quaternion")
        {
            output = &output_quaternion;
        }
        else if (output_mode == "euler")
        {
            field_width += 2;  // See comment above for field_width.
            output = &output_euler;
        }
        else
        {
            std::cerr << "Unknown output mode '" << output_mode << "'" << std::endl;
            return 1;
        }

        // Figure out the basic operating mode and start running.
        if (mode == "raw")
        {
            streamRawValues(imu);
        }
        else if (mode == "gyro-only")
        {
            ahrs(imu, &fuse_gyro_only, output);
        }
        else if (mode == "compass-only")
        {
            ahrs(imu, &fuse_compass_only, output);
        }
        else if (mode == "normal")
        {
            ahrs(imu, &fuse_default, output);
        }
        else
        {
            std::cerr << "Unknown mode '" << mode << "'" << std::endl;
            return 1;
        }
        return 0;
    }
    catch(const std::system_error & error)
    {
        std::string what = error.what();
        const std::error_code & code = error.code();
        std::cerr << "Error: " << what << "  " << code.message() << " (" << code << ")" << std::endl;
        return 2;
    }
    catch(const opts::multiple_occurrences & error)
    {
        std::cerr << "Error: " << error.what() << " of " << error.get_option_name() << " option." << std::endl;
        return 1;
    }
    catch(const std::exception & error)
    {
        std::cerr << "Error: " << error.what() << std::endl;
        return 9;
    }
}
<commit_msg>Added a reference to the man page on the help screen.<commit_after>#include "vector.h"
#include "MinIMU9.h"
#include "version.h"
#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <system_error>
#include <boost/program_options.hpp>

namespace opts = boost::program_options;

// TODO: print warning if accelerometer magnitude is not close to 1 when starting up

// An Euler angle could take 8 chars: -234.678, but usually we only need 6.
float field_width = 6;
#define FLOAT_FORMAT std::fixed << std::setprecision(3) << std::setw(field_width)

std::ostream & operator << (std::ostream & os, const vector & vector)
{
    return os << FLOAT_FORMAT << vector(0) << ' '
              << FLOAT_FORMAT << vector(1) << ' '
              << FLOAT_FORMAT << vector(2);
}

std::ostream & operator << (std::ostream & os, const matrix & matrix)
{
    return os << (vector)matrix.row(0) << ' '
              << (vector)matrix.row(1) << ' '
              << (vector)matrix.row(2);
}

std::ostream & operator << (std::ostream & os, const quaternion & quat)
{
    return os << FLOAT_FORMAT << quat.w() << ' '
              << FLOAT_FORMAT << quat.x() << ' '
              << FLOAT_FORMAT << quat.y() << ' '
              << FLOAT_FORMAT << quat.z();
}

typedef void rotation_output_function(quaternion& rotation);

void output_quaternion(quaternion & rotation)
{
    std::cout << rotation;
}

void output_matrix(quaternion & rotation)
{
    std::cout << rotation.toRotationMatrix();
}

void output_euler(quaternion & rotation)
{
    std::cout << (vector)(rotation.toRotationMatrix().eulerAngles(2, 1, 0) * (180 / M_PI));
}

int millis()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (tv.tv_sec) * 1000 + (tv.tv_usec)/1000;
}

void streamRawValues(IMU& imu)
{
    imu.enable();
    while(1)
    {
        imu.read();
        printf("%7d %7d %7d  %7d %7d %7d  %7d %7d %7d\n",
               imu.raw_m[0], imu.raw_m[1], imu.raw_m[2],
               imu.raw_a[0], imu.raw_a[1], imu.raw_a[2],
               imu.raw_g[0], imu.raw_g[1], imu.raw_g[2]
        );
        usleep(20*1000);
    }
}

//! Uses the acceleration and magnetic field readings from the compass
// to get a noisy estimate of the current rotation matrix.
// This function is where we define the coordinate system we are using
// for the ground coords:  North, East, Down.
matrix rotationFromCompass(const vector& acceleration, const vector& magnetic_field)
{
    vector down = -acceleration;     // usually true
    vector east = down.cross(magnetic_field); // actually it's magnetic east
    vector north = east.cross(down);

    east.normalize();
    north.normalize();
    down.normalize();

    matrix r;
    r.row(0) = north;
    r.row(1) = east;
    r.row(2) = down;
    return r;
}

typedef void fuse_function(quaternion& rotation, float dt, const vector& angular_velocity,
                  const vector& acceleration, const vector& magnetic_field);

void fuse_compass_only(quaternion& rotation, float dt, const vector& angular_velocity,
  const vector& acceleration, const vector& magnetic_field)
{
    // Implicit conversion of rotation matrix to quaternion.
    rotation = rotationFromCompass(acceleration, magnetic_field);
}

// Uses the given angular velocity and time interval to calculate
// a rotation and applies that rotation to the given quaternion.
// w is angular velocity in radians per second.
// dt is the time.
void rotate(quaternion& rotation, const vector& w, float dt)
{
    // Multiply by first order approximation of the
    // quaternion representing this rotation.
    rotation *= quaternion(1, w(0)*dt/2, w(1)*dt/2, w(2)*dt/2);
    rotation.normalize();
}

void fuse_gyro_only(quaternion& rotation, float dt, const vector& angular_velocity,
  const vector& acceleration, const vector& magnetic_field)
{
    rotate(rotation, angular_velocity, dt);
}

void fuse_default(quaternion& rotation, float dt, const vector& angular_velocity,
  const vector& acceleration, const vector& magnetic_field)
{
    vector correction = vector(0, 0, 0);

    if (abs(acceleration.norm() - 1) <= 0.3)
    {
        // The magnetidude of acceleration is close to 1 g, so
        // it might be pointing up and we can do drift correction.

        const float correction_strength = 1;

        matrix rotationCompass = rotationFromCompass(acceleration, magnetic_field);
        matrix rotationMatrix = rotation.toRotationMatrix();

        correction = (
            rotationCompass.row(0).cross(rotationMatrix.row(0)) +
            rotationCompass.row(1).cross(rotationMatrix.row(1)) +
            rotationCompass.row(2).cross(rotationMatrix.row(2))
          ) * correction_strength;

    }

    rotate(rotation, angular_velocity + correction, dt);
}

void ahrs(IMU & imu, fuse_function * fuse, rotation_output_function * output)
{
    imu.loadCalibration();
    imu.enable();
    imu.measureOffsets();

    // The quaternion that can convert a vector in body coordinates
    // to ground coordinates when it its changed to a matrix.
    quaternion rotation = quaternion::Identity();

    int start = millis(); // truncate 64-bit return value
    while(1)
    {
        int last_start = start;
        start = millis();
        float dt = (start-last_start)/1000.0;
        if (dt < 0){ throw std::runtime_error("Time went backwards."); }

        vector angular_velocity = imu.readGyro();
        vector acceleration = imu.readAcc();
        vector magnetic_field = imu.readMag();

        fuse(rotation, dt, angular_velocity, acceleration, magnetic_field);

        output(rotation);
        std::cout << "  " << acceleration << "  " << magnetic_field << std::endl << std::flush;

        // Ensure that each iteration of the loop takes at least 20 ms.
        while(millis() - start < 20)
        {
            usleep(1000);
        }
    }
}

int main(int argc, char *argv[])
{
    try
    {
        // Define what all the command-line parameters are.
        std::string mode, output_mode, i2cDevice;
        opts::options_description desc("Allowed options");
        desc.add_options()
            ("help,h", "produce help message")
            ("version,v", "print version number")
            ("i2c-bus,b", opts::value<std::string>(&i2cDevice)->default_value("/dev/i2c-0"),
             "i2c-bus the IMU is connected to")
            ("mode", opts::value<std::string>(&mode)->default_value("normal"),
             "specifies what algorithm to use.\n"
             "normal: Fuse compass and gyro.\n"
             "gyro-only:  Use only gyro (drifts).\n"
             "compass-only:  Use only compass (noisy).\n"
             "raw: Just print raw values from sensors.")
            ("output", opts::value<std::string>(&output_mode)->default_value("matrix"),
             "specifies how to output the orientation.\n"
             "matrix: Direction Cosine Matrix.\n"
             "quaternion: Quaternion.\n"
             "euler: Euler angles (yaw, pitch, roll).\n")
            ;
        opts::variables_map options;
        opts::store(opts::command_line_parser(argc, argv).options(desc).run(), options);
        opts::notify(options);

        if(options.count("help"))
        {
            std::cout << desc << std::endl;
            std::cout << "For more information, run: man minimu9-ahrs" << std::endl;
            return 0;
        }

        if (options.count("version"))
        {
            std::cout << VERSION << std::endl;
            return 0;
        }

        MinIMU9 imu(i2cDevice.c_str());

        rotation_output_function * output;

        // Figure out the output mode.
        if (output_mode == "matrix")
        {
            output = &output_matrix;
        }
        else if (output_mode == "quaternion")
        {
            output = &output_quaternion;
        }
        else if (output_mode == "euler")
        {
            field_width += 2;  // See comment above for field_width.
            output = &output_euler;
        }
        else
        {
            std::cerr << "Unknown output mode '" << output_mode << "'" << std::endl;
            return 1;
        }

        // Figure out the basic operating mode and start running.
        if (mode == "raw")
        {
            streamRawValues(imu);
        }
        else if (mode == "gyro-only")
        {
            ahrs(imu, &fuse_gyro_only, output);
        }
        else if (mode == "compass-only")
        {
            ahrs(imu, &fuse_compass_only, output);
        }
        else if (mode == "normal")
        {
            ahrs(imu, &fuse_default, output);
        }
        else
        {
            std::cerr << "Unknown mode '" << mode << "'" << std::endl;
            return 1;
        }
        return 0;
    }
    catch(const std::system_error & error)
    {
        std::string what = error.what();
        const std::error_code & code = error.code();
        std::cerr << "Error: " << what << "  " << code.message() << " (" << code << ")" << std::endl;
        return 2;
    }
    catch(const opts::multiple_occurrences & error)
    {
        std::cerr << "Error: " << error.what() << " of " << error.get_option_name() << " option." << std::endl;
        return 1;
    }
    catch(const std::exception & error)
    {
        std::cerr << "Error: " << error.what() << std::endl;
        return 9;
    }
}
<|endoftext|>


<commit_before>#include "lw/co/systems/epoll.h"

#include <cstdint>
#include <exception>
#include <limits>
#include <sys/epoll.h>
#include <unistd.h>

#include "lw/err/canonical.h"
#include "lw/err/system.h"
#include "lw/flags/flags.h"

LW_FLAG(
  std::uint16_t, lw_epoll_event_buffer_size, 32,
  "Size of buffer to create when waiting for events trigger."
);

namespace lw::co::internal {
namespace {

std::uint32_t co_event_to_epoll_event(Event events) {
  std::uint32_t ret = 0;
  if (events & Event::READABLE)     ret |= EPOLLIN;
  if (events & Event::WRITABLE)     ret |= EPOLLOUT;
  if (events & Event::READ_CLOSED)  ret |= EPOLLRDHUP;
  if (events & Event::PEER_CLOSED)  ret |= EPOLLHUP;
  if (events & Event::POLLPRI)      ret |= EPOLLPRI;
  if (events & Event::ERROR)        ret |= EPOLLERR;
  if (events & Event::EDGE_TRIGGER) ret |= EPOLLET;
  if (events & Event::ONE_SHOT)     ret |= EPOLLONESHOT;
  if (events & Event::WAKE_UP)      ret |= EPOLLWAKEUP;
  if (events & Event::EXCLUSIVE)    ret |= EPOLLEXCLUSIVE;
  return ret;
}

}

EPoll::EPoll() {
  _epoll_fd = ::epoll_create1(/*flags=*/0);
  if (_epoll_fd <= 0) {
    check_system_error();
    throw Internal() << "Unknown error from epoll_create1.";
  }
}

EPoll::~EPoll() {
  if (_epoll_fd > 0) ::close(_epoll_fd);
}

void EPoll::add(int fd, Event events, callback_type callback) {
  if (_callbacks.contains(fd)) {
    throw AlreadyExists() << "Handle already registered with epoll.";
  }

  // Register to event with epoll.
  ::epoll_event ev = {
    .events = co_event_to_epoll_event(events),
    .data = {.fd = fd}
  };
  if (::epoll_ctl(_epoll_fd, EPOLL_CTL_ADD, fd, &ev) != 0) {
    check_system_error();
    throw Internal() << "Unknown error from epoll_ctl when adding handle.";
  }

  // Add the callback to our map.
  _callbacks.insert({fd, {std::move(callback), events & Event::ONE_SHOT}});
}

void EPoll::remove(int fd) {
  if (_callbacks.erase(fd) == 0) {
    throw FailedPrecondition() << "Handle not registered with epoll.";
  }
  if (::epoll_ctl(_epoll_fd, EPOLL_CTL_DEL, fd, nullptr) != 0) {
    check_system_error();
    throw Internal() << "Unknown error from epoll_ctl when removing handle.";
  }
}

std::size_t EPoll::wait_for(std::chrono::steady_clock::duration timeout) {
  auto timeout_ms =
    std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count();
  if (timeout_ms <= 0) {
    throw InvalidArgument() << "Timeout must be a positive duration.";
  } else if (timeout_ms > std::numeric_limits<int>::max()) {
    throw InvalidArgument()
      << "Timeout can be no longer than " << std::numeric_limits<int>::max()
      << " milliseconds.";
  }
  return _wait(static_cast<int>(timeout_ms));
}

std::size_t EPoll::_wait(int timeout_ms) {
  std::vector<::epoll_event> events{
    flags::lw_epoll_event_buffer_size.value(),
    {.events = 0, .data = {.fd = 0}}
  };

  int available_events = ::epoll_wait(
    _epoll_fd,
    events.data(),
    static_cast<int>(events.size()),
    timeout_ms
  );
  if (available_events < 0) {
    check_system_error();
    throw Internal() << "Unknown error from epoll_wait.";
  } else if (static_cast<std::uint32_t>(available_events) > events.size()) {
    throw Internal()
      << "Epoll returned " << available_events << " events in a buffer of size "
      << events.size();
  }

  for (int i = 0; i < available_events; ++i) {
    const ::epoll_event& event = events[i];
    if (!_callbacks.contains(event.data.fd)) {
      throw Internal()
        << "Received event trigger for handle not in callbacks map.";
    }
    auto& [callback, one_shot] = _callbacks[event.data.fd];
    try {
      if (one_shot) {
        auto callback_move = std::move(callback);
        _callbacks.erase(event.data.fd);
        callback_move();
      } else {
        callback();
      }
    } catch (const std::exception& err) {
      // TODO: handle this error more gracefully and reject the associated
      // promise higher up.
      throw Internal() << "Error thrown by callback:\n\t" << err.what();
    } catch (...) {
      throw Internal() << "Unknown error thrown by callback!";
    }
  }

  return static_cast<std::size_t>(available_events);
}

}
<commit_msg>Fixed one shot events for realzies this time.<commit_after>#include "lw/co/systems/epoll.h"

#include <cstdint>
#include <exception>
#include <limits>
#include <sys/epoll.h>
#include <unistd.h>

#include "lw/err/canonical.h"
#include "lw/err/system.h"
#include "lw/flags/flags.h"

LW_FLAG(
  std::uint16_t, lw_epoll_event_buffer_size, 32,
  "Size of buffer to create when waiting for events trigger."
);

namespace lw::co::internal {
namespace {

std::uint32_t co_event_to_epoll_event(Event events) {
  std::uint32_t ret = 0;
  if (events & Event::READABLE)     ret |= EPOLLIN;
  if (events & Event::WRITABLE)     ret |= EPOLLOUT;
  if (events & Event::READ_CLOSED)  ret |= EPOLLRDHUP;
  if (events & Event::PEER_CLOSED)  ret |= EPOLLHUP;
  if (events & Event::POLLPRI)      ret |= EPOLLPRI;
  if (events & Event::ERROR)        ret |= EPOLLERR;
  if (events & Event::EDGE_TRIGGER) ret |= EPOLLET;
  if (events & Event::ONE_SHOT)     ret |= EPOLLONESHOT;
  if (events & Event::WAKE_UP)      ret |= EPOLLWAKEUP;
  if (events & Event::EXCLUSIVE)    ret |= EPOLLEXCLUSIVE;
  return ret;
}

}

EPoll::EPoll() {
  _epoll_fd = ::epoll_create1(/*flags=*/0);
  if (_epoll_fd <= 0) {
    check_system_error();
    throw Internal() << "Unknown error from epoll_create1.";
  }
}

EPoll::~EPoll() {
  if (_epoll_fd > 0) ::close(_epoll_fd);
}

void EPoll::add(int fd, Event events, callback_type callback) {
  if (_callbacks.contains(fd)) {
    throw AlreadyExists() << "Handle already registered with epoll.";
  }

  // Register to event with epoll.
  ::epoll_event ev = {
    .events = co_event_to_epoll_event(events),
    .data = {.fd = fd}
  };
  if (::epoll_ctl(_epoll_fd, EPOLL_CTL_ADD, fd, &ev) != 0) {
    check_system_error();
    throw Internal() << "Unknown error from epoll_ctl when adding handle.";
  }

  // Add the callback to our map.
  _callbacks.insert({fd, {std::move(callback), events & Event::ONE_SHOT}});
}

void EPoll::remove(int fd) {
  if (_callbacks.erase(fd) == 0) {
    throw FailedPrecondition() << "Handle not registered with epoll.";
  }
  if (::epoll_ctl(_epoll_fd, EPOLL_CTL_DEL, fd, nullptr) != 0) {
    check_system_error();
    throw Internal() << "Unknown error from epoll_ctl when removing handle.";
  }
}

std::size_t EPoll::wait_for(std::chrono::steady_clock::duration timeout) {
  auto timeout_ms =
    std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count();
  if (timeout_ms <= 0) {
    throw InvalidArgument() << "Timeout must be a positive duration.";
  } else if (timeout_ms > std::numeric_limits<int>::max()) {
    throw InvalidArgument()
      << "Timeout can be no longer than " << std::numeric_limits<int>::max()
      << " milliseconds.";
  }
  return _wait(static_cast<int>(timeout_ms));
}

std::size_t EPoll::_wait(int timeout_ms) {
  std::vector<::epoll_event> events{
    flags::lw_epoll_event_buffer_size.value(),
    {.events = 0, .data = {.fd = 0}}
  };

  int available_events = ::epoll_wait(
    _epoll_fd,
    events.data(),
    static_cast<int>(events.size()),
    timeout_ms
  );
  if (available_events < 0) {
    check_system_error();
    throw Internal() << "Unknown error from epoll_wait.";
  } else if (static_cast<std::uint32_t>(available_events) > events.size()) {
    throw Internal()
      << "Epoll returned " << available_events << " events in a buffer of size "
      << events.size();
  }

  for (int i = 0; i < available_events; ++i) {
    const ::epoll_event& event = events[i];
    if (!_callbacks.contains(event.data.fd)) {
      throw Internal()
        << "Received event trigger for handle not in callbacks map.";
    }
    auto& [callback, one_shot] = _callbacks[event.data.fd];
    try {
      if (one_shot) {
        auto callback_move = std::move(callback);
        remove(event.data.fd);
        callback_move();
      } else {
        callback();
      }
    } catch (const std::exception& err) {
      // TODO: handle this error more gracefully and reject the associated
      // promise higher up.
      throw Internal() << "Error thrown by callback:\n\t" << err.what();
    } catch (...) {
      throw Internal() << "Unknown error thrown by callback!";
    }
  }

  return static_cast<std::size_t>(available_events);
}

}
<|endoftext|>


<commit_before>/***********************************************************************
Moses - factored phrase-based language decoder
Copyright (C) 2009 University of Edinburgh

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
***********************************************************************/

#include "Decoder.h"
#include "Manager.h"
#include "Sentence.h"
#include "InputType.h"
#include "TranslationSystem.h"
#include "Phrase.h"
#include "TrellisPathList.h"
#include "DummyScoreProducers.h"

using namespace std;
using namespace Moses;

namespace Mira {

  /**
    * Allocates a char* and copies string into it.
  **/
  static char* strToChar(const string& s) {
    char* c = new char[s.size()+1];
    strcpy(c,s.c_str());
    return c;
  }

  MosesDecoder::MosesDecoder(const string& inifile, int debuglevel, int argc, vector<string> decoder_params)
		: m_manager(NULL) {
//	  static int BASE_ARGC = 5;
  	static int BASE_ARGC = 4;
	  Parameter* params = new Parameter();
	  char ** mosesargv = new char*[BASE_ARGC + argc];
	  mosesargv[0] = strToChar("-f");
	  mosesargv[1] = strToChar(inifile);
	  mosesargv[2] = strToChar("-v");
	  stringstream dbgin;
	  dbgin << debuglevel;
	  mosesargv[3] = strToChar(dbgin.str());
//	  mosesargv[4] = strToChar("-mbr"); //so we can do nbest

	  for (int i = 0; i < argc; ++i) {
		  char *cstr = &(decoder_params[i])[0];
		  mosesargv[BASE_ARGC + i] = cstr;
	  }

	  if (!params->LoadParam(BASE_ARGC + argc,mosesargv)) {
		  cerr << "Loading static data failed, exit." << endl;
		  exit(1);
	  }
	  StaticData::LoadDataStatic(params);
	  for (int i = 0; i < BASE_ARGC; ++i) {
		  delete[] mosesargv[i];
	  }
	  delete[] mosesargv;

	  const StaticData &staticData = StaticData::Instance();
      m_bleuScoreFeature = staticData.GetBleuScoreFeature();
  }

  void MosesDecoder::cleanup() {
	  delete m_manager;
	  delete m_sentence;
  }

  vector< vector<const Word*> > MosesDecoder::getNBest(const std::string& source,
                              size_t sentenceid,
                              size_t count,
                              float bleuObjectiveWeight,
                              float bleuScoreWeight,
                              vector< ScoreComponentCollection>& featureValues,
                              vector< float>& bleuScores,
                              vector< float>& modelScores,
                              size_t numReturnedTranslations,
                              bool distinct,
                              size_t rank,
                              size_t epoch)
  {
  	StaticData &staticData = StaticData::InstanceNonConst();

  	m_sentence = new Sentence(Input);
    stringstream in(source + "\n");
    const std::vector<FactorType> &inputFactorOrder = staticData.GetInputFactorOrder();
    m_sentence->Read(in,inputFactorOrder);
    const TranslationSystem& system = staticData.GetTranslationSystem(TranslationSystem::DEFAULT);

    // set weight of BleuScoreFeature
    /*ostringstream bleuWeightStr;
    bleuWeightStr << (bleuObjectiveWeight*bleuScoreWeight);
    PARAM_VEC bleuWeight(1,bleuWeightStr.str());
    staticData.GetParameter()->OverwriteParam("weight-bl", bleuWeight);*/
    staticData.ReLoadBleuScoreFeatureParameter(bleuObjectiveWeight*bleuScoreWeight);

    m_bleuScoreFeature->SetCurrentSourceLength((*m_sentence).GetSize());
    m_bleuScoreFeature->SetCurrentShortestReference(sentenceid);

    //run the decoder
    m_manager = new Moses::Manager(*m_sentence, staticData.GetSearchAlgorithm(), &system);
    m_manager->ProcessSentence();
    TrellisPathList sentences;
    m_manager->CalcNBest(count,sentences, distinct);

    // read off the feature values and bleu scores for each sentence in the nbest list
    Moses::TrellisPathList::const_iterator iter;
    for (iter = sentences.begin() ; iter != sentences.end() ; ++iter) {
    	const Moses::TrellisPath &path = **iter;
    	featureValues.push_back(path.GetScoreBreakdown());
    	float bleuScore = getBleuScore(featureValues.back());
    	bleuScores.push_back(bleuScore);

    	//std::cout << "Score breakdown: " << path.GetScoreBreakdown() << endl;
    	float scoreWithoutBleu = path.GetTotalScore() - (bleuObjectiveWeight * bleuScoreWeight * bleuScore);
    	modelScores.push_back(scoreWithoutBleu);

    	Phrase bestPhrase = path.GetTargetPhrase();

    	if (iter != sentences.begin())
    		cerr << endl;
    	cerr << "Rank " << rank << ", epoch " << epoch << ", \"";
    	Phrase phrase = path.GetTargetPhrase();
    	for (size_t pos = 0; pos < phrase.GetSize(); ++pos) {
    		const Word &word = phrase.GetWord(pos);
    		Word *newWord = new Word(word);
    		cerr << *newWord;
    	}

    	cerr << "\", score: " << scoreWithoutBleu << ", Bleu: " << bleuScore << ", total: " << path.GetTotalScore();

    	// set bleu score to zero in the feature vector since we do not want to optimise its weight
    	setBleuScore(featureValues.back(), 0);
    }

    // prepare translations to return
    vector< vector<const Word*> > translations;
    for (size_t i=0; i < numReturnedTranslations; ++i) {
        assert(sentences.GetSize() >= numReturnedTranslations);
        const TrellisPath &path = sentences.at(i);
        Phrase phrase = path.GetTargetPhrase();

        vector<const Word*> translation;
        for (size_t pos = 0; pos < phrase.GetSize(); ++pos) {
        	const Word &word = phrase.GetWord(pos);
        	Word *newWord = new Word(word);
        	translation.push_back(newWord);
        }
        translations.push_back(translation);
    }

//    cerr << "Rank " << rank << ", use cache: " << staticData.GetUseTransOptCache() << ", weights: " << staticData.GetAllWeights() << endl;
    return translations;
  }

  size_t MosesDecoder::getCurrentInputLength() {
	  return (*m_sentence).GetSize();
  }

  float MosesDecoder::getBleuScore(const ScoreComponentCollection& scores) {
    return scores.GetScoreForProducer(m_bleuScoreFeature);
  }

  void MosesDecoder::setBleuScore(ScoreComponentCollection& scores, float bleu) {
    scores.Assign(m_bleuScoreFeature, bleu);
  }

  ScoreComponentCollection MosesDecoder::getWeights() {
    return StaticData::Instance().GetAllWeights();
  }

  void MosesDecoder::setWeights(const ScoreComponentCollection& weights) {
    StaticData::InstanceNonConst().SetAllWeights(weights);
  }

  void MosesDecoder::updateHistory(const vector<const Word*>& words) {
    m_bleuScoreFeature->UpdateHistory(words);
  }

  void MosesDecoder::updateHistory(const vector< vector< const Word*> >& words, vector<size_t>& sourceLengths, vector<size_t>& ref_ids, size_t rank, size_t epoch) {
	  m_bleuScoreFeature->UpdateHistory(words, sourceLengths, ref_ids, rank, epoch);
  }

/*  void MosesDecoder::loadReferenceSentences(const vector<vector<string> >& refs) {
  	m_bleuScoreFeature->LoadReferences(refs);
  }*/

  void MosesDecoder::printBleuFeatureHistory(std::ostream& out) {
  	m_bleuScoreFeature->PrintHistory(out);
  }

/*  void MosesDecoder::printReferenceLength(const vector<size_t>& ref_ids) {
  	m_bleuScoreFeature->PrintReferenceLength(ref_ids);
  }*/

  size_t MosesDecoder::getClosestReferenceLength(size_t ref_id, int hypoLength) {
  	return m_bleuScoreFeature->GetClosestReferenceLength(ref_id, hypoLength);
  }

  void MosesDecoder::setBleuParameters(bool scaleByInputLength, bool scaleByRefLength, bool scaleByAvgLength,
  		bool scaleByTargetLengthLinear, bool scaleByTargetLengthTrend,
		  float scaleByX, float historySmoothing, size_t scheme, float relax_BP) {
	  m_bleuScoreFeature->SetBleuParameters(scaleByInputLength, scaleByRefLength, scaleByAvgLength,
	  		scaleByTargetLengthLinear, scaleByTargetLengthTrend,
			  scaleByX, historySmoothing, scheme, relax_BP);
  }
}

<commit_msg>fix length check<commit_after>/***********************************************************************
Moses - factored phrase-based language decoder
Copyright (C) 2009 University of Edinburgh

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
***********************************************************************/

#include "Decoder.h"
#include "Manager.h"
#include "Sentence.h"
#include "InputType.h"
#include "TranslationSystem.h"
#include "Phrase.h"
#include "TrellisPathList.h"
#include "DummyScoreProducers.h"

using namespace std;
using namespace Moses;

namespace Mira {

  /**
    * Allocates a char* and copies string into it.
  **/
  static char* strToChar(const string& s) {
    char* c = new char[s.size()+1];
    strcpy(c,s.c_str());
    return c;
  }

  MosesDecoder::MosesDecoder(const string& inifile, int debuglevel, int argc, vector<string> decoder_params)
		: m_manager(NULL) {
//	  static int BASE_ARGC = 5;
  	static int BASE_ARGC = 4;
	  Parameter* params = new Parameter();
	  char ** mosesargv = new char*[BASE_ARGC + argc];
	  mosesargv[0] = strToChar("-f");
	  mosesargv[1] = strToChar(inifile);
	  mosesargv[2] = strToChar("-v");
	  stringstream dbgin;
	  dbgin << debuglevel;
	  mosesargv[3] = strToChar(dbgin.str());
//	  mosesargv[4] = strToChar("-mbr"); //so we can do nbest

	  for (int i = 0; i < argc; ++i) {
		  char *cstr = &(decoder_params[i])[0];
		  mosesargv[BASE_ARGC + i] = cstr;
	  }

	  if (!params->LoadParam(BASE_ARGC + argc,mosesargv)) {
		  cerr << "Loading static data failed, exit." << endl;
		  exit(1);
	  }
	  StaticData::LoadDataStatic(params);
	  for (int i = 0; i < BASE_ARGC; ++i) {
		  delete[] mosesargv[i];
	  }
	  delete[] mosesargv;

	  const StaticData &staticData = StaticData::Instance();
      m_bleuScoreFeature = staticData.GetBleuScoreFeature();
  }

  void MosesDecoder::cleanup() {
	  delete m_manager;
	  delete m_sentence;
  }

  vector< vector<const Word*> > MosesDecoder::getNBest(const std::string& source,
                              size_t sentenceid,
                              size_t count,
                              float bleuObjectiveWeight,
                              float bleuScoreWeight,
                              vector< ScoreComponentCollection>& featureValues,
                              vector< float>& bleuScores,
                              vector< float>& modelScores,
                              size_t numReturnedTranslations,
                              bool distinct,
                              size_t rank,
                              size_t epoch)
  {
  	StaticData &staticData = StaticData::InstanceNonConst();

  	m_sentence = new Sentence(Input);
    stringstream in(source + "\n");
    const std::vector<FactorType> &inputFactorOrder = staticData.GetInputFactorOrder();
    m_sentence->Read(in,inputFactorOrder);
    const TranslationSystem& system = staticData.GetTranslationSystem(TranslationSystem::DEFAULT);

    // set weight of BleuScoreFeature
    /*ostringstream bleuWeightStr;
    bleuWeightStr << (bleuObjectiveWeight*bleuScoreWeight);
    PARAM_VEC bleuWeight(1,bleuWeightStr.str());
    staticData.GetParameter()->OverwriteParam("weight-bl", bleuWeight);*/
    staticData.ReLoadBleuScoreFeatureParameter(bleuObjectiveWeight*bleuScoreWeight);

    m_bleuScoreFeature->SetCurrentSourceLength((*m_sentence).GetSize());
    m_bleuScoreFeature->SetCurrentShortestReference(sentenceid);

    //run the decoder
    m_manager = new Moses::Manager(*m_sentence, staticData.GetSearchAlgorithm(), &system);
    m_manager->ProcessSentence();
    TrellisPathList sentences;
    m_manager->CalcNBest(count,sentences, distinct);

    // read off the feature values and bleu scores for each sentence in the nbest list
    Moses::TrellisPathList::const_iterator iter;
    for (iter = sentences.begin() ; iter != sentences.end() ; ++iter) {
    	const Moses::TrellisPath &path = **iter;
    	featureValues.push_back(path.GetScoreBreakdown());
    	float bleuScore = getBleuScore(featureValues.back());
    	bleuScores.push_back(bleuScore);

    	//std::cout << "Score breakdown: " << path.GetScoreBreakdown() << endl;
    	float scoreWithoutBleu = path.GetTotalScore() - (bleuObjectiveWeight * bleuScoreWeight * bleuScore);
    	modelScores.push_back(scoreWithoutBleu);

    	Phrase bestPhrase = path.GetTargetPhrase();

    	if (iter != sentences.begin())
    		cerr << endl;
    	cerr << "Rank " << rank << ", epoch " << epoch << ", \"";
    	Phrase phrase = path.GetTargetPhrase();
    	for (size_t pos = 0; pos < phrase.GetSize(); ++pos) {
    		const Word &word = phrase.GetWord(pos);
    		Word *newWord = new Word(word);
    		cerr << *newWord;
    	}

    	cerr << "\", score: " << scoreWithoutBleu << ", Bleu: " << bleuScore << ", total: " << path.GetTotalScore();

    	// set bleu score to zero in the feature vector since we do not want to optimise its weight
    	setBleuScore(featureValues.back(), 0);
    }

    // prepare translations to return
    vector< vector<const Word*> > translations;
    for (size_t i=0; i < numReturnedTranslations && i < sentences.GetSize(); ++i) {
        const TrellisPath &path = sentences.at(i);
        Phrase phrase = path.GetTargetPhrase();

        vector<const Word*> translation;
        for (size_t pos = 0; pos < phrase.GetSize(); ++pos) {
        	const Word &word = phrase.GetWord(pos);
        	Word *newWord = new Word(word);
        	translation.push_back(newWord);
        }
        translations.push_back(translation);
    }

//    cerr << "Rank " << rank << ", use cache: " << staticData.GetUseTransOptCache() << ", weights: " << staticData.GetAllWeights() << endl;
    return translations;
  }

  size_t MosesDecoder::getCurrentInputLength() {
	  return (*m_sentence).GetSize();
  }

  float MosesDecoder::getBleuScore(const ScoreComponentCollection& scores) {
    return scores.GetScoreForProducer(m_bleuScoreFeature);
  }

  void MosesDecoder::setBleuScore(ScoreComponentCollection& scores, float bleu) {
    scores.Assign(m_bleuScoreFeature, bleu);
  }

  ScoreComponentCollection MosesDecoder::getWeights() {
    return StaticData::Instance().GetAllWeights();
  }

  void MosesDecoder::setWeights(const ScoreComponentCollection& weights) {
    StaticData::InstanceNonConst().SetAllWeights(weights);
  }

  void MosesDecoder::updateHistory(const vector<const Word*>& words) {
    m_bleuScoreFeature->UpdateHistory(words);
  }

  void MosesDecoder::updateHistory(const vector< vector< const Word*> >& words, vector<size_t>& sourceLengths, vector<size_t>& ref_ids, size_t rank, size_t epoch) {
	  m_bleuScoreFeature->UpdateHistory(words, sourceLengths, ref_ids, rank, epoch);
  }

/*  void MosesDecoder::loadReferenceSentences(const vector<vector<string> >& refs) {
  	m_bleuScoreFeature->LoadReferences(refs);
  }*/

  void MosesDecoder::printBleuFeatureHistory(std::ostream& out) {
  	m_bleuScoreFeature->PrintHistory(out);
  }

/*  void MosesDecoder::printReferenceLength(const vector<size_t>& ref_ids) {
  	m_bleuScoreFeature->PrintReferenceLength(ref_ids);
  }*/

  size_t MosesDecoder::getClosestReferenceLength(size_t ref_id, int hypoLength) {
  	return m_bleuScoreFeature->GetClosestReferenceLength(ref_id, hypoLength);
  }

  void MosesDecoder::setBleuParameters(bool scaleByInputLength, bool scaleByRefLength, bool scaleByAvgLength,
  		bool scaleByTargetLengthLinear, bool scaleByTargetLengthTrend,
		  float scaleByX, float historySmoothing, size_t scheme, float relax_BP) {
	  m_bleuScoreFeature->SetBleuParameters(scaleByInputLength, scaleByRefLength, scaleByAvgLength,
	  		scaleByTargetLengthLinear, scaleByTargetLengthTrend,
			  scaleByX, historySmoothing, scheme, relax_BP);
  }
}

<|endoftext|>


<commit_before>// Filename: physicsManager.cxx
// Created by:  charles (14Jun00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include "physicsManager.h"
#include "actorNode.h"

#include <algorithm>
#include "pvector.h"

////////////////////////////////////////////////////////////////////
//     Function : PhysicsManager
//       Access : Public
//  Description : Default Constructor.  NOTE: EulerIntegrator is
//                the standard default.
////////////////////////////////////////////////////////////////////
PhysicsManager::
PhysicsManager(void) {
  _linear_integrator.clear();
  _angular_integrator.clear();
}

////////////////////////////////////////////////////////////////////
//     Function : ~PhysicsManager
//       Access : Public
//  Description : Simple Destructor
////////////////////////////////////////////////////////////////////
PhysicsManager::
~PhysicsManager(void) {
}

////////////////////////////////////////////////////////////////////
//     Function : remove_linear_force
//       Access : Public
//  Description : takes a linear force out of the physics list
////////////////////////////////////////////////////////////////////
void PhysicsManager::
remove_linear_force(LinearForce *f) {
  pvector< PT(LinearForce) >::iterator found;

  PT(LinearForce) ptbf = f;
  found = find(_linear_forces.begin(), _linear_forces.end(), ptbf);

  if (found == _linear_forces.end())
    return;

  _linear_forces.erase(found);
}

////////////////////////////////////////////////////////////////////
//     Function : remove_angular_force
//       Access : Public
//  Description : takes an angular force out of the physics list
////////////////////////////////////////////////////////////////////
void PhysicsManager::
remove_angular_force(AngularForce *f) {
  pvector< PT(AngularForce) >::iterator found;

  PT(BaseForce) ptbf = f;
  found = find(_angular_forces.begin(), _angular_forces.end(), ptbf);

  if (found == _angular_forces.end())
    return;

  _angular_forces.erase(found);
}

////////////////////////////////////////////////////////////////////
//     Function : remove_physical
//       Access : Public
//  Description : takes a physical out of the object list
////////////////////////////////////////////////////////////////////
void PhysicsManager::
remove_physical(Physical *p) {
  pvector< Physical * >::iterator found;

  found = find(_physicals.begin(), _physicals.end(), p);
  if (found == _physicals.end())
    return;

  p->_physics_manager = (PhysicsManager *) NULL;
  _physicals.erase(found);
}

////////////////////////////////////////////////////////////////////
//     Function : DoPhysics
//       Access : Public
//  Description : This is the main high-level API call.  Performs
//                integration on every attached Physical.
////////////////////////////////////////////////////////////////////
void PhysicsManager::
do_physics(float dt) {
  pvector< Physical * >::iterator p_cur;

  // now, run through each physics object in the set.
  p_cur = _physicals.begin();

  for (; p_cur != _physicals.end(); p_cur++) {
    Physical *physical = *p_cur;

    // do linear
    if (_linear_integrator.is_null() == false) {
      _linear_integrator->integrate(physical, _linear_forces, dt);
    }

    // do angular
    if (_angular_integrator.is_null() == false) {
      _angular_integrator->integrate(physical, _angular_forces, dt);
    }

    // if it's an actor node, tell it to update itself.
    PhysicalNode *pn = physical->get_physical_node();
    if (pn->is_of_type(ActorNode::get_class_type())) {
      ActorNode *an = (ActorNode *) pn;
      an->update_transform();
    }
  }
}
<commit_msg>testing physical node before dereferrencing<commit_after>// Filename: physicsManager.cxx
// Created by:  charles (14Jun00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include "physicsManager.h"
#include "actorNode.h"

#include <algorithm>
#include "pvector.h"

////////////////////////////////////////////////////////////////////
//     Function : PhysicsManager
//       Access : Public
//  Description : Default Constructor.  NOTE: EulerIntegrator is
//                the standard default.
////////////////////////////////////////////////////////////////////
PhysicsManager::
PhysicsManager(void) {
  _linear_integrator.clear();
  _angular_integrator.clear();
}

////////////////////////////////////////////////////////////////////
//     Function : ~PhysicsManager
//       Access : Public
//  Description : Simple Destructor
////////////////////////////////////////////////////////////////////
PhysicsManager::
~PhysicsManager(void) {
}

////////////////////////////////////////////////////////////////////
//     Function : remove_linear_force
//       Access : Public
//  Description : takes a linear force out of the physics list
////////////////////////////////////////////////////////////////////
void PhysicsManager::
remove_linear_force(LinearForce *f) {
  pvector< PT(LinearForce) >::iterator found;

  PT(LinearForce) ptbf = f;
  found = find(_linear_forces.begin(), _linear_forces.end(), ptbf);

  if (found == _linear_forces.end())
    return;

  _linear_forces.erase(found);
}

////////////////////////////////////////////////////////////////////
//     Function : remove_angular_force
//       Access : Public
//  Description : takes an angular force out of the physics list
////////////////////////////////////////////////////////////////////
void PhysicsManager::
remove_angular_force(AngularForce *f) {
  pvector< PT(AngularForce) >::iterator found;

  PT(BaseForce) ptbf = f;
  found = find(_angular_forces.begin(), _angular_forces.end(), ptbf);

  if (found == _angular_forces.end())
    return;

  _angular_forces.erase(found);
}

////////////////////////////////////////////////////////////////////
//     Function : remove_physical
//       Access : Public
//  Description : takes a physical out of the object list
////////////////////////////////////////////////////////////////////
void PhysicsManager::
remove_physical(Physical *p) {
  pvector< Physical * >::iterator found;

  found = find(_physicals.begin(), _physicals.end(), p);
  if (found == _physicals.end())
    return;

  p->_physics_manager = (PhysicsManager *) NULL;
  _physicals.erase(found);
}

////////////////////////////////////////////////////////////////////
//     Function : DoPhysics
//       Access : Public
//  Description : This is the main high-level API call.  Performs
//                integration on every attached Physical.
////////////////////////////////////////////////////////////////////
void PhysicsManager::
do_physics(float dt) {
  // now, run through each physics object in the set.
  pvector< Physical * >::iterator p_cur = _physicals.begin();
  for (; p_cur != _physicals.end(); ++p_cur) {
    Physical *physical = *p_cur;

    // do linear
    if (_linear_integrator.is_null() == false) {
      _linear_integrator->integrate(physical, _linear_forces, dt);
    }

    // do angular
    if (_angular_integrator.is_null() == false) {
      _angular_integrator->integrate(physical, _angular_forces, dt);
    }

    // if it's an actor node, tell it to update itself.
    PhysicalNode *pn = physical->get_physical_node();
    if (pn && pn->is_of_type(ActorNode::get_class_type())) {
      ActorNode *an = (ActorNode *) pn;
      an->update_transform();
    }
  }
}
<|endoftext|>