<commit_before>#include <catch2/catch.hpp>

#include "utils/containers/DisjointSet.hpp"
#include "utils/containers/ValueTypeOf.hpp"

namespace utils::containers::tests {

static_assert(std::same_as<ValueTypeOf<DisjointSet<int64_t>>, int64_t>, "ValueTypeOf doesn't work with DisjointSet");
static_assert(std::same_as<ValueTypeOf<DisjointSet<uint64_t>>, uint64_t>, "ValueTypeOf doesn't work with DisjointSet");

// Very similar functions can be found in other container tests, but because of the very slight differences, it is hard
// to unify them. Instead of centralizing the functions with complex logic for customizations, they are just copied and
// modified.
template <typename TDisjointSet, typename TCheck>
void TestWithCopyCtor(const TDisjointSet &ds, TCheck check) {
  INFO("CopyCtor");
  auto copiedDs = ds;
  check(copiedDs);
}

template <typename TDisjointSet, typename TCheck>
void TestWithCopyAssignment(const TDisjointSet &ds, TCheck check) {
  INFO("CopyAssignment");
  TDisjointSet copiedDs;
  copiedDs = ds;
  check(copiedDs);
}

// Requires copy ctor
template <typename TDisjointSet, typename TCheck>
void TestWithMoveCtor(const TDisjointSet &ds, TCheck check) {
  INFO("MoveCtor");
  auto copiedDs = ds;
  auto movedDs = std::move(copiedDs);
  check(movedDs);
  CHECK(0 == copiedDs.size()); // NOLINT(bugprone-use-after-move)
}

template <typename TDisjointSet, typename TCheck>
void TestWithMoveAssignment(const TDisjointSet &ds, TCheck check) {
  INFO("MoveAssignment");
  auto copiedDs = ds;
  TDisjointSet movedDs;
  movedDs = std::move(copiedDs);
  check(movedDs);
  CHECK(0 == copiedDs.size()); // NOLINT(bugprone-use-after-move)
}

template <typename TDisjointSet, typename TCheck>
void TestWithSpecialMemberFunctions(TDisjointSet &ds, TCheck check) {
  TestWithCopyCtor(ds, check);
  TestWithCopyAssignment(ds, check);
  TestWithMoveCtor(ds, check);
  TestWithMoveAssignment(ds, check);
  check(ds);
}

TEST_CASE("EmptyDisjointSet") {
  DisjointSet<int64_t> ds;
  CHECK(0 == ds.size());

  const auto check = [](auto &ds) {
    CHECK(!ds.find(1).has_value());
    CHECK(0 == ds.numberOfDisjointSets());
  };
  TestWithSpecialMemberFunctions(ds, check);
}

TEST_CASE("AddSingle") {
  DisjointSet<int64_t> ds;
  ds.add(1);

  const auto check = [](auto &ds) {
    CHECK(1 == ds.size());

    const auto &constDs = ds;
    CHECK(1 == constDs.find(1));
    CHECK(!constDs.find(2).has_value());

    CHECK(1 == ds.find(1));
    CHECK(!ds.find(2).has_value());

    CHECK(1 == ds.numberOfDisjointSets());
  };
  TestWithSpecialMemberFunctions(ds, check);
}

TEST_CASE("AddTwo") {
  DisjointSet<int64_t> ds;
  static constexpr int64_t kFirstValue = 0;
  static constexpr int64_t kSecondValue = 42;

  ds.add(kFirstValue);
  CHECK(kFirstValue == ds.find(kFirstValue));

  ds.add(kSecondValue);
  CHECK(kSecondValue == ds.find(kSecondValue));

  const auto check = [](auto &ds) {
    CHECK(2 == ds.size());

    const auto &constDs = ds;
    CHECK(constDs.find(kFirstValue) == kFirstValue);
    CHECK(constDs.find(kSecondValue) == kSecondValue);
    CHECK(!constDs.find(kFirstValue - 1).has_value());
    CHECK(!constDs.find(kFirstValue + 1).has_value());
    CHECK(!constDs.find(kSecondValue - 1).has_value());
    CHECK(!constDs.find(kSecondValue + 1).has_value());

    CHECK(ds.find(kFirstValue) == kFirstValue);
    CHECK(ds.find(kSecondValue) == kSecondValue);
    CHECK(!ds.find(kFirstValue - 1).has_value());
    CHECK(!ds.find(kFirstValue + 1).has_value());
    CHECK(!ds.find(kSecondValue - 1).has_value());
    CHECK(!ds.find(kSecondValue + 1).has_value());

    CHECK(2 == ds.numberOfDisjointSets());
  };
  TestWithSpecialMemberFunctions(ds, check);
}

TEST_CASE("MultipleAdd") {
  DisjointSet<int64_t> ds;
  static constexpr int64_t kStartValue = -5000;
  static constexpr int64_t kEndValue = 5000;
  static constexpr int64_t kIncrement = 37;

  int64_t expectedSize{0};
  for (auto i = kStartValue; i < kEndValue; i += kIncrement) {
    CHECK(expectedSize == ds.size());
    CHECK(!ds.find(i).has_value());
    ds.add(i);
    ++expectedSize;
    CHECK(expectedSize == ds.size());
    CHECK(ds.find(i).has_value());
  }

  const auto check = [expectedSize](auto &ds) {
    CHECK(expectedSize == ds.size());
    CHECK(expectedSize == ds.numberOfDisjointSets());
    const auto &constDs = ds;

    for (auto i = kStartValue; i < kEndValue; i += kIncrement) {
      CHECK(constDs.find(i).has_value());
      CHECK(!constDs.find(i - 1).has_value());
      CHECK(!constDs.find(i + 1).has_value());

      CHECK(ds.find(i).has_value());
      CHECK(!ds.find(i - 1).has_value());
      CHECK(!ds.find(i + 1).has_value());
    }
  };
  TestWithSpecialMemberFunctions(ds, check);
}

TEST_CASE("SimpleMerge") {
  DisjointSet<int64_t> ds;
  using Values = std::pair<int64_t, int64_t>;
  const auto values = GENERATE(Values{24, 42}, Values{5, 3});
  const auto firstValue = values.first;
  const auto secondValue = values.second;
  const auto expected = std::min(firstValue, secondValue);

  ds.add(firstValue);
  CHECK(firstValue == ds.find(firstValue));

  ds.add(secondValue);
  CHECK(secondValue == ds.find(secondValue));
  CHECK(2 == ds.numberOfDisjointSets());

  CHECK(ds.merge(firstValue, secondValue));
  const auto check = [firstValue, secondValue, expected](auto &ds) {
    CHECK(2 == ds.size());

    const auto &constDs = ds;
    CHECK(constDs.find(firstValue) == expected);
    CHECK(constDs.find(secondValue) == expected);
    CHECK(!constDs.find(firstValue - 1).has_value());
    CHECK(!constDs.find(firstValue + 1).has_value());
    CHECK(!constDs.find(secondValue - 1).has_value());
    CHECK(!constDs.find(secondValue + 1).has_value());

    CHECK(1 == ds.numberOfDisjointSets());

    CHECK(ds.find(firstValue) == expected);
    CHECK(ds.find(secondValue) == expected);
    CHECK(!ds.find(firstValue - 1).has_value());
    CHECK(!ds.find(firstValue + 1).has_value());
    CHECK(!ds.find(secondValue - 1).has_value());
    CHECK(!ds.find(secondValue + 1).has_value());

    CHECK(!ds.merge(firstValue, secondValue));
  };
  TestWithSpecialMemberFunctions(ds, check);
}

TEST_CASE("DoubleMerge") {
  DisjointSet<int64_t> ds;
  using Values = std::tuple<int64_t, int64_t, int64_t>;
  const auto values = GENERATE(Values{10, 100, 1000}, Values{10, 1000, 100}, Values{100, 10, 1000},
                               Values{100, 1000, 10}, Values{1000, 10, 100}, Values{1000, 100, 10});
  const auto firstValue = std::get<0>(values);
  const auto secondValue = std::get<1>(values);
  const auto thirdValue = std::get<2>(values);
  const auto expected = std::min(std::min(firstValue, secondValue), thirdValue);

  ds.add(firstValue);
  CHECK(firstValue == ds.find(firstValue));

  ds.add(secondValue);
  CHECK(secondValue == ds.find(secondValue));

  ds.add(thirdValue);
  CHECK(thirdValue == ds.find(thirdValue));

  CHECK(3 == ds.numberOfDisjointSets());
  CHECK(ds.merge(firstValue, secondValue));
  CHECK(2 == ds.numberOfDisjointSets());
  CHECK(ds.merge(secondValue, thirdValue));
  CHECK(1 == ds.numberOfDisjointSets());
  const auto check = [firstValue, secondValue, thirdValue, expected](auto &ds) {
    CHECK(3 == ds.size());
    CHECK(1 == ds.numberOfDisjointSets());

    const auto &constDs = ds;
    CHECK(constDs.find(firstValue) == expected);
    CHECK(constDs.find(secondValue) == expected);
    CHECK(constDs.find(thirdValue) == expected);

    CHECK(ds.find(firstValue) == expected);
    CHECK(ds.find(secondValue) == expected);
    CHECK(ds.find(thirdValue) == expected);

    CHECK(!ds.merge(firstValue, secondValue));
    CHECK(!ds.merge(secondValue, thirdValue));
    CHECK(!ds.merge(firstValue, thirdValue));
  };
  TestWithSpecialMemberFunctions(ds, check);
}

TEMPLATE_TEST_CASE("MergeChains", "", const DisjointSet<int64_t> &, DisjointSet<int64_t> &) {
  DisjointSet<int64_t> ds;
  // DisjointSet<T>::findParent work differently in the const and non-const version
  TestType testDs = ds;
  static constexpr int64_t chain1Start = 42;
  static constexpr int64_t chain1End = chain1Start - 10;
  static constexpr int64_t chain2Start = -145;
  static constexpr int64_t chain2End = chain2Start - 10;

  auto createChain = [&ds](const int64_t chainStart, const int64_t chainEnd) {
    ds.add(chainStart);
    for (auto i = chainStart - 1; i >= chainEnd; --i) {
      ds.add(i);
      if (i % 2 == 0) {
        ds.merge(i, i + 1);
      } else {
        ds.merge(i + 1, i);
      }
    }
  };

  auto checkChain = [&testDs](const int64_t chainStart, const int64_t chainEnd, const int64_t expected) {
    for (auto i = chainStart; i >= chainEnd; --i) {
      CHECK(expected == testDs.find(i));
    }
  };

  createChain(chain1Start, chain1End);
  checkChain(chain1Start, chain1End, chain1End);
  CHECK(1 == testDs.numberOfDisjointSets());
  createChain(chain2Start, chain2End);
  checkChain(chain1Start, chain1End, chain1End);
  checkChain(chain2Start, chain2End, chain2End);
  CHECK(2 == testDs.numberOfDisjointSets());
  ds.merge(chain1End, chain2End);
  checkChain(chain1Start, chain1End, chain2End);
  checkChain(chain2Start, chain2End, chain2End);
  CHECK(1 == testDs.numberOfDisjointSets());
}
} // namespace utils::containers::tests
<commit_msg>Ignore clang-tidy warning coming from catch2<commit_after>#include <catch2/catch.hpp>

#include "utils/containers/DisjointSet.hpp"
#include "utils/containers/ValueTypeOf.hpp"

namespace utils::containers::tests {

static_assert(std::same_as<ValueTypeOf<DisjointSet<int64_t>>, int64_t>, "ValueTypeOf doesn't work with DisjointSet");
static_assert(std::same_as<ValueTypeOf<DisjointSet<uint64_t>>, uint64_t>, "ValueTypeOf doesn't work with DisjointSet");

// Very similar functions can be found in other container tests, but because of the very slight differences, it is hard
// to unify them. Instead of centralizing the functions with complex logic for customizations, they are just copied and
// modified.
template <typename TDisjointSet, typename TCheck>
void TestWithCopyCtor(const TDisjointSet &ds, TCheck check) {
  INFO("CopyCtor");
  auto copiedDs = ds;
  check(copiedDs);
}

template <typename TDisjointSet, typename TCheck>
void TestWithCopyAssignment(const TDisjointSet &ds, TCheck check) {
  INFO("CopyAssignment");
  TDisjointSet copiedDs;
  copiedDs = ds;
  check(copiedDs);
}

// Requires copy ctor
template <typename TDisjointSet, typename TCheck>
void TestWithMoveCtor(const TDisjointSet &ds, TCheck check) {
  INFO("MoveCtor");
  auto copiedDs = ds;
  auto movedDs = std::move(copiedDs);
  check(movedDs);
  CHECK(0 == copiedDs.size()); // NOLINT(bugprone-use-after-move)
}

template <typename TDisjointSet, typename TCheck>
void TestWithMoveAssignment(const TDisjointSet &ds, TCheck check) {
  INFO("MoveAssignment");
  auto copiedDs = ds;
  TDisjointSet movedDs;
  movedDs = std::move(copiedDs);
  check(movedDs);
  CHECK(0 == copiedDs.size()); // NOLINT(bugprone-use-after-move)
}

template <typename TDisjointSet, typename TCheck>
void TestWithSpecialMemberFunctions(TDisjointSet &ds, TCheck check) {
  TestWithCopyCtor(ds, check);
  TestWithCopyAssignment(ds, check);
  TestWithMoveCtor(ds, check);
  TestWithMoveAssignment(ds, check);
  check(ds);
}

TEST_CASE("EmptyDisjointSet") {
  DisjointSet<int64_t> ds;
  CHECK(0 == ds.size());

  const auto check = [](auto &ds) {
    CHECK(!ds.find(1).has_value());
    CHECK(0 == ds.numberOfDisjointSets());
  };
  TestWithSpecialMemberFunctions(ds, check);
}

TEST_CASE("AddSingle") {
  DisjointSet<int64_t> ds;
  ds.add(1);

  const auto check = [](auto &ds) {
    CHECK(1 == ds.size());

    const auto &constDs = ds;
    CHECK(1 == constDs.find(1));
    CHECK(!constDs.find(2).has_value());

    CHECK(1 == ds.find(1));
    CHECK(!ds.find(2).has_value());

    CHECK(1 == ds.numberOfDisjointSets());
  };
  TestWithSpecialMemberFunctions(ds, check);
}

TEST_CASE("AddTwo") {
  DisjointSet<int64_t> ds;
  static constexpr int64_t kFirstValue = 0;
  static constexpr int64_t kSecondValue = 42;

  ds.add(kFirstValue);
  CHECK(kFirstValue == ds.find(kFirstValue));

  ds.add(kSecondValue);
  CHECK(kSecondValue == ds.find(kSecondValue));

  const auto check = [](auto &ds) {
    CHECK(2 == ds.size());

    const auto &constDs = ds;
    CHECK(constDs.find(kFirstValue) == kFirstValue);
    CHECK(constDs.find(kSecondValue) == kSecondValue);
    CHECK(!constDs.find(kFirstValue - 1).has_value());
    CHECK(!constDs.find(kFirstValue + 1).has_value());
    CHECK(!constDs.find(kSecondValue - 1).has_value());
    CHECK(!constDs.find(kSecondValue + 1).has_value());

    CHECK(ds.find(kFirstValue) == kFirstValue);
    CHECK(ds.find(kSecondValue) == kSecondValue);
    CHECK(!ds.find(kFirstValue - 1).has_value());
    CHECK(!ds.find(kFirstValue + 1).has_value());
    CHECK(!ds.find(kSecondValue - 1).has_value());
    CHECK(!ds.find(kSecondValue + 1).has_value());

    CHECK(2 == ds.numberOfDisjointSets());
  };
  TestWithSpecialMemberFunctions(ds, check);
}

TEST_CASE("MultipleAdd") {
  DisjointSet<int64_t> ds;
  static constexpr int64_t kStartValue = -5000;
  static constexpr int64_t kEndValue = 5000;
  static constexpr int64_t kIncrement = 37;

  int64_t expectedSize{0};
  for (auto i = kStartValue; i < kEndValue; i += kIncrement) {
    CHECK(expectedSize == ds.size());
    CHECK(!ds.find(i).has_value());
    ds.add(i);
    ++expectedSize;
    CHECK(expectedSize == ds.size());
    CHECK(ds.find(i).has_value());
  }

  const auto check = [expectedSize](auto &ds) {
    CHECK(expectedSize == ds.size());
    CHECK(expectedSize == ds.numberOfDisjointSets());
    const auto &constDs = ds;

    for (auto i = kStartValue; i < kEndValue; i += kIncrement) {
      CHECK(constDs.find(i).has_value());
      CHECK(!constDs.find(i - 1).has_value());
      CHECK(!constDs.find(i + 1).has_value());

      CHECK(ds.find(i).has_value());
      CHECK(!ds.find(i - 1).has_value());
      CHECK(!ds.find(i + 1).has_value());
    }
  };
  TestWithSpecialMemberFunctions(ds, check);
}

TEST_CASE("SimpleMerge") {
  DisjointSet<int64_t> ds;
  using Values = std::pair<int64_t, int64_t>;
  const auto values = GENERATE(Values{24, 42}, Values{5, 3});
  const auto firstValue = values.first;
  const auto secondValue = values.second;
  const auto expected = std::min(firstValue, secondValue);

  ds.add(firstValue);
  CHECK(firstValue == ds.find(firstValue));

  ds.add(secondValue);
  CHECK(secondValue == ds.find(secondValue));
  CHECK(2 == ds.numberOfDisjointSets());

  CHECK(ds.merge(firstValue, secondValue));
  const auto check = [firstValue, secondValue, expected](auto &ds) {
    CHECK(2 == ds.size());

    const auto &constDs = ds;
    CHECK(constDs.find(firstValue) == expected);
    CHECK(constDs.find(secondValue) == expected);
    CHECK(!constDs.find(firstValue - 1).has_value());
    CHECK(!constDs.find(firstValue + 1).has_value());
    CHECK(!constDs.find(secondValue - 1).has_value());
    CHECK(!constDs.find(secondValue + 1).has_value());

    CHECK(1 == ds.numberOfDisjointSets());

    CHECK(ds.find(firstValue) == expected);
    CHECK(ds.find(secondValue) == expected);
    CHECK(!ds.find(firstValue - 1).has_value());
    CHECK(!ds.find(firstValue + 1).has_value());
    CHECK(!ds.find(secondValue - 1).has_value());
    CHECK(!ds.find(secondValue + 1).has_value());

    CHECK(!ds.merge(firstValue, secondValue));
  };
  TestWithSpecialMemberFunctions(ds, check);
}

TEST_CASE("DoubleMerge") {
  DisjointSet<int64_t> ds;
  using Values = std::tuple<int64_t, int64_t, int64_t>;
  const auto values = GENERATE(Values{10, 100, 1000}, Values{10, 1000, 100}, Values{100, 10, 1000},
                               Values{100, 1000, 10}, Values{1000, 10, 100}, Values{1000, 100, 10});
  const auto firstValue = std::get<0>(values);
  const auto secondValue = std::get<1>(values);
  const auto thirdValue = std::get<2>(values);
  const auto expected = std::min(std::min(firstValue, secondValue), thirdValue);

  ds.add(firstValue);
  CHECK(firstValue == ds.find(firstValue));

  ds.add(secondValue);
  CHECK(secondValue == ds.find(secondValue));

  ds.add(thirdValue);
  CHECK(thirdValue == ds.find(thirdValue));

  CHECK(3 == ds.numberOfDisjointSets());
  CHECK(ds.merge(firstValue, secondValue));
  CHECK(2 == ds.numberOfDisjointSets());
  CHECK(ds.merge(secondValue, thirdValue));
  CHECK(1 == ds.numberOfDisjointSets());
  const auto check = [firstValue, secondValue, thirdValue, expected](auto &ds) {
    CHECK(3 == ds.size());
    CHECK(1 == ds.numberOfDisjointSets());

    const auto &constDs = ds;
    CHECK(constDs.find(firstValue) == expected);
    CHECK(constDs.find(secondValue) == expected);
    CHECK(constDs.find(thirdValue) == expected);

    CHECK(ds.find(firstValue) == expected);
    CHECK(ds.find(secondValue) == expected);
    CHECK(ds.find(thirdValue) == expected);

    CHECK(!ds.merge(firstValue, secondValue));
    CHECK(!ds.merge(secondValue, thirdValue));
    CHECK(!ds.merge(firstValue, thirdValue));
  };
  TestWithSpecialMemberFunctions(ds, check);
}

// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables,modernize-avoid-c-arrays)
TEMPLATE_TEST_CASE("MergeChains", "", const DisjointSet<int64_t> &, DisjointSet<int64_t> &) {
  DisjointSet<int64_t> ds;
  // DisjointSet<T>::findParent work differently in the const and non-const version
  TestType testDs = ds;
  static constexpr int64_t chain1Start = 42;
  static constexpr int64_t chain1End = chain1Start - 10;
  static constexpr int64_t chain2Start = -145;
  static constexpr int64_t chain2End = chain2Start - 10;

  auto createChain = [&ds](const int64_t chainStart, const int64_t chainEnd) {
    ds.add(chainStart);
    for (auto i = chainStart - 1; i >= chainEnd; --i) {
      ds.add(i);
      if (i % 2 == 0) {
        ds.merge(i, i + 1);
      } else {
        ds.merge(i + 1, i);
      }
    }
  };

  auto checkChain = [&testDs](const int64_t chainStart, const int64_t chainEnd, const int64_t expected) {
    for (auto i = chainStart; i >= chainEnd; --i) {
      CHECK(expected == testDs.find(i));
    }
  };

  createChain(chain1Start, chain1End);
  checkChain(chain1Start, chain1End, chain1End);
  CHECK(1 == testDs.numberOfDisjointSets());
  createChain(chain2Start, chain2End);
  checkChain(chain1Start, chain1End, chain1End);
  checkChain(chain2Start, chain2End, chain2End);
  CHECK(2 == testDs.numberOfDisjointSets());
  ds.merge(chain1End, chain2End);
  checkChain(chain1Start, chain1End, chain2End);
  checkChain(chain2Start, chain2End, chain2End);
  CHECK(1 == testDs.numberOfDisjointSets());
}
} // namespace utils::containers::tests
<|endoftext|>


<commit_before>#include "vga/vga.h"

#include "lib/common/attribute_macros.h"
#include "lib/armv7m/exceptions.h"

#include "lib/stm32f4xx/adv_timer.h"
#include "lib/stm32f4xx/ahb.h"
#include "lib/stm32f4xx/apb.h"
#include "lib/stm32f4xx/dma.h"
#include "lib/stm32f4xx/gpio.h"
#include "lib/stm32f4xx/interrupts.h"
#include "lib/stm32f4xx/rcc.h"

using stm32f4xx::AdvTimer;
using stm32f4xx::AhbPeripheral;
using stm32f4xx::ApbPeripheral;
using stm32f4xx::Dma;
using stm32f4xx::dma2;
using stm32f4xx::Gpio;
using stm32f4xx::gpioc;
using stm32f4xx::gpioe;
using stm32f4xx::Interrupt;
using stm32f4xx::rcc;
using stm32f4xx::tim8;
using stm32f4xx::Word;

#define IN_SCAN_RAM SECTION(".vga_scan_ram")

namespace vga {

static constexpr unsigned max_pixels_per_line = 800;

static unsigned volatile current_line;
static VideoMode const *current_mode;

/*
 * The vertical timing state.  This is a Gray code and the bits have meaning.
 * See the inspector functions below.
 */
enum class State {
  blank     = 0b00,
  starting  = 0b01,
  active    = 0b11,
  finishing = 0b10,
};

// Should we be producing a video signal?
inline bool is_displayed_state(State s) {
  return static_cast<unsigned>(s) & 0b10;
}

// Should we be rendering a scanline?
inline bool is_rendered_state(State s) {
  return static_cast<unsigned>(s) & 0b01;
}

static State volatile state;

ALIGNED(4) IN_SCAN_RAM
static unsigned char scan_buffer[max_pixels_per_line + 4];

void init() {
  // TODO(cbiffle): original code turned on I/O compensation.  Should we?

  // Turn a bunch of stuff on.
  rcc.enable_clock(ApbPeripheral::tim8);
  rcc.enable_clock(AhbPeripheral::gpioc);  // Sync signals
  rcc.enable_clock(AhbPeripheral::gpioe);  // Video
  rcc.enable_clock(AhbPeripheral::dma2);

  // Hold TIM8 in reset until we do mode-setting.
  rcc.enter_reset(ApbPeripheral::tim8);

  set_irq_priority(Interrupt::tim8_cc, 0);
  set_exception_priority(armv7m::Exception::pend_sv, 0xFF);

  video_off();
}

void video_off() {
  // Tristate all output ports.
  gpioc.set_mode((1 << 6) | (1 << 7), Gpio::Mode::input);
  gpioc.set_pull((1 << 6) | (1 << 7), Gpio::Pull::none);

  gpioe.set_mode(0xFF00, Gpio::Mode::input);
  gpioe.set_pull(0xFF00, Gpio::Pull::none);
}

void video_on() {
  // Configure PC6 to produce hsync using TIM8_CH1
  gpioc.set_alternate_function(Gpio::p6, 3);
  gpioc.set_output_type(Gpio::p6, Gpio::OutputType::push_pull);
  gpioc.set_output_speed(Gpio::p6, Gpio::OutputSpeed::high_100mhz);
  gpioc.set_mode(Gpio::p6, Gpio::Mode::alternate);

  // Configure PC7 as GPIO output.
  gpioc.set_output_type(Gpio::p7, Gpio::OutputType::push_pull);
  gpioc.set_output_speed(Gpio::p7, Gpio::OutputSpeed::high_100mhz);
  gpioc.set_mode(Gpio::p7, Gpio::Mode::gpio);

  // Configure the high byte of port E for parallel video.
  gpioe.set_output_type(0xFF00, Gpio::OutputType::push_pull);
  gpioe.set_output_speed(0xFF00, Gpio::OutputSpeed::high_100mhz);
  gpioe.set_mode(0xFF00, Gpio::Mode::gpio);
}

void select_mode(VideoMode const &mode) {
  // Disable outputs during mode change.
  video_off();

  // Place TIM8 in reset, stopping all timing, and disable its interrupt.
  rcc.enter_reset(ApbPeripheral::tim8);
  disable_irq(Interrupt::tim8_cc);

  // Busy-wait for pending DMA to complete.
  while (dma2.stream1.read_cr().get_en());

  // TODO: apply buffered changes.

  // Switch to new CPU clock settings.
  rcc.configure_clocks(mode.clock_config);

  // Configure TIM8 for horizontal sync generation.
  rcc.leave_reset(ApbPeripheral::tim8);
  tim8.write_psc(4 - 1);  // Count in pixels, 1 pixel = 4 CCLK

  tim8.write_arr(mode.line_pixels - 1);
  tim8.write_ccr1(mode.sync_pixels);
  tim8.write_ccr2(mode.sync_pixels + mode.back_porch_pixels - mode.video_lead);
  tim8.write_ccr3(
      mode.sync_pixels + mode.back_porch_pixels + mode.video_pixels);

  tim8.write_ccmr1(AdvTimer::ccmr1_value_t()
                   .with_oc1m(AdvTimer::OcMode::pwm1)
                   .with_cc1s(AdvTimer::ccmr1_value_t::cc1s_t::output));

  tim8.write_bdtr(AdvTimer::bdtr_value_t()
                  .with_ossr(true)
                  .with_moe(true));

  tim8.write_ccer(AdvTimer::ccer_value_t()
                  .with_cc1e(true)
                  .with_cc1p(
                      mode.hsync_polarity == VideoMode::Polarity::negative));

  tim8.write_dier(AdvTimer::dier_value_t()
                  .with_cc2ie(true)    // Interrupt at start of active video.
                  .with_cc3ie(true));  // Interrupt at end of active video.

  // Note: TIM8 is still not running.

  switch (mode.vsync_polarity) {
    case VideoMode::Polarity::positive: gpioc.clear(1 << 7); break;
    case VideoMode::Polarity::negative: gpioc.set  (1 << 7); break;
  }

  // Scribble over scan buffer to help catch bugs.
  for (unsigned i = 0; i < sizeof(scan_buffer) - 4; i += 2) {
    scan_buffer[i] = 0xFF;
    scan_buffer[i + 1] = 0x00;
  }
  // But the final four must be black.
  scan_buffer[sizeof(scan_buffer) - 4] = 0;
  scan_buffer[sizeof(scan_buffer) - 3] = 0;
  scan_buffer[sizeof(scan_buffer) - 2] = 0;
  scan_buffer[sizeof(scan_buffer) - 1] = 0;

  // Set up global state.
  current_mode = &mode;  // TODO(cbiffle): copy into RAM for less jitter?
  current_line = 0;

  // Start the timer.
  enable_irq(Interrupt::tim8_cc);
  tim8.write_cr1(tim8.read_cr1().with_cen(true));

  // Enable display and sync signals.
  video_on();
}

}  // namespace vga

extern "C" void stm32f4xx_tim8_cc_handler() {
  // We have to clear our interrupt flags, or this will recur.
  auto sr = tim8.read_sr();
  tim8.write_sr(sr.with_cc2if(false).with_cc3if(false));

  vga::VideoMode const &mode = *vga::current_mode;

  if (sr.get_cc2if()) {
    // CC2 indicates start of active video.
    // This only matters in displayed states.
    if (is_displayed_state(vga::state)) {
      // Clear stream 1 flags (lifcr is a write-1-to-clear register).
      dma2.write_lifcr(Dma::lifcr_value_t()
                       .with_cdmeif1(true)
                       .with_cteif1(true)
                       .with_chtif1(true)
                       .with_ctcif1(true));

      auto &st = dma2.stream1;

      // Shut off stream 1 by zeroing CR.
      // TODO(cbiffle): necessary?
      st.write_cr(Dma::Stream::cr_value_t());

      // Prepare to transfer pixels as words, plus the final black word.
      st.write_ndtr(mode.video_pixels / 4 + 1);

      // Set addresses.  Note that we're using memory as the peripheral side.
      // This DMA controller is a little odd.
      st.write_par(reinterpret_cast<Word>(&vga::scan_buffer));
      st.write_m0ar(0x40021015);  // High byte of GPIOE ODR (hack hack)

      // Configure FIFO.
      st.write_fcr(Dma::Stream::fcr_value_t()
                   .with_fth(Dma::Stream::fcr_value_t::fth_t::quarter)
                   .with_dmdis(true)
                   .with_feie(false));

      /*
       * Configure and enable the DMA stream.  The configuration used here
       * deserves more discussion.
       *
       * As noted above, our "peripheral" is RAM and our "memory" is the GPIO
       * unit.  In memory-to-memory mode (which we use) the distinction is
       * not useful, since the peripherals are memory-mapped; the controller
       * insists that "peripheral" be source and "memory" be destination in that
       * mode.  The key here is that the transfer runs at full speed.  On the
       * STM32F407 the transfer will not exceed one unit per 4 AHB cycles.  The
       * reason for this is not obvious.
       *
       * Address incrementation on this chip is independent from whether an
       * address is considered "peripheral" or "memory."  Here we auto-increment
       * the peripheral address (to walk through the scan buffer) while leaving
       * the memory address fixed (at the appropriate byte of the GPIO port).
       *
       * Because we're using memory-to-memory, the hardware enforces several
       * restrictions:
       *
       *  1. We're stuck using DMA2.  DMA1 can't do it.
       *  2. We're required to use the FIFO -- direct mode is verboten.
       *  3. We can't use circular mode.  (Double-buffer mode appears permitted,
       *     but I haven't tried it.)
       *
       * Fortunately we can tie the FIFO to a tree by giving it a really low
       * threshold level.
       *
       * I have not experimented with burst modes, but I suspect they'll make
       * the timing less regular.
       *
       * Note that the priority (pl field) is only used for arbitration between
       * streams of the same DMA controller.  The STM32F4 does not provide any
       * control over the AHB matrix arbitration scheme, unlike (say) the NXP
       * LPC1788.  Shame, that.  It means we have to be very careful about our
       * use of the bus matrix during scan-out.
       */
      typedef Dma::Stream::cr_value_t cr_t;
      st.write_cr(Dma::Stream::cr_value_t()
                  // Originally chosen to play nice with TIM8.  Now, arbitrary.
                  .with_chsel(7)
                  .with_pl(cr_t::pl_t::very_high)
                  .with_dir(cr_t::dir_t::memory_to_memory)
                  // Input settings:
                  .with_pburst(Dma::Stream::BurstSize::single)
                  .with_psize(Dma::Stream::TransferSize::word)
                  .with_pinc(true)
                  // Output settings:
                  .with_mburst(Dma::Stream::BurstSize::single)
                  .with_msize(Dma::Stream::TransferSize::byte)
                  .with_minc(false)
                  // Look at all these options we don't use:
                  .with_dbm(false)
                  .with_pincos(false)
                  .with_circ(false)
                  .with_pfctrl(false)
                  .with_tcie(false)
                  .with_htie(false)
                  .with_teie(false)
                  .with_dmeie(false)
                  // Finally, enable.
                  .with_en(true));
    } else {
      // Not displayed state.  Ensure pins are black.
      // TODO(cbiffle): almost certainly not necessary...
      gpioe.clear(0xFF00);
    }
  }

  if (sr.get_cc3if()) {
    // CC3 indicates end of active video.
    unsigned line = vga::current_line;

    if (line == 0) {
      // Start of frame!  Time to stop displaying pixels.
      vga::state = vga::State::blank;
      // TODO(cbiffle): suppress video output.
      // TODO(cbiffle): latch configuration changes.
    } else if (line == mode.vsync_start_line
            || line == mode.vsync_end_line) {
      // Either edge of vsync pulse.
      gpioc.toggle(Gpio::p7);
    } else if (line == static_cast<unsigned short>(mode.video_start_line - 1)) {
      // Time to start generating the first scan buffer.
      vga::state = vga::State::starting;
    } else if (line == mode.video_start_line) {
      // Time to start output.
      vga::state = vga::State::active;
    } else if (line == static_cast<unsigned short>(mode.video_end_line - 1)) {
      // Time to stop rendering new scan buffers.
      vga::state = vga::State::finishing;
      line = static_cast<unsigned>(-1);  // Make line roll over to zero.
    }

    vga::current_line = line + 1;

    if (is_rendered_state(vga::state)) {
      // TODO(cbiffle): PendSV to kick off a buffer flip and rasterization.
    }
  }
}

<commit_msg>vga: adjust slew rates to reduce noise.<commit_after>#include "vga/vga.h"

#include "lib/common/attribute_macros.h"
#include "lib/armv7m/exceptions.h"

#include "lib/stm32f4xx/adv_timer.h"
#include "lib/stm32f4xx/ahb.h"
#include "lib/stm32f4xx/apb.h"
#include "lib/stm32f4xx/dma.h"
#include "lib/stm32f4xx/gpio.h"
#include "lib/stm32f4xx/interrupts.h"
#include "lib/stm32f4xx/rcc.h"
#include "lib/stm32f4xx/syscfg.h"

using stm32f4xx::AdvTimer;
using stm32f4xx::AhbPeripheral;
using stm32f4xx::ApbPeripheral;
using stm32f4xx::Dma;
using stm32f4xx::dma2;
using stm32f4xx::Gpio;
using stm32f4xx::gpioc;
using stm32f4xx::gpioe;
using stm32f4xx::Interrupt;
using stm32f4xx::rcc;
using stm32f4xx::syscfg;
using stm32f4xx::tim8;
using stm32f4xx::Word;

#define IN_SCAN_RAM SECTION(".vga_scan_ram")

namespace vga {

static constexpr unsigned max_pixels_per_line = 800;

static unsigned volatile current_line;
static VideoMode const *current_mode;

/*
 * The vertical timing state.  This is a Gray code and the bits have meaning.
 * See the inspector functions below.
 */
enum class State {
  blank     = 0b00,
  starting  = 0b01,
  active    = 0b11,
  finishing = 0b10,
};

// Should we be producing a video signal?
inline bool is_displayed_state(State s) {
  return static_cast<unsigned>(s) & 0b10;
}

// Should we be rendering a scanline?
inline bool is_rendered_state(State s) {
  return static_cast<unsigned>(s) & 0b01;
}

static State volatile state;

ALIGNED(4) IN_SCAN_RAM
static unsigned char scan_buffer[max_pixels_per_line + 4];

void init() {
  // Turn on I/O compensation cell to reduce noise on power supply.
  rcc.enable_clock(ApbPeripheral::syscfg);
  syscfg.write_cmpcr(syscfg.read_cmpcr().with_cmp_pd(true));

  // Turn a bunch of stuff on.
  rcc.enable_clock(ApbPeripheral::tim8);
  rcc.enable_clock(AhbPeripheral::gpioc);  // Sync signals
  rcc.enable_clock(AhbPeripheral::gpioe);  // Video
  rcc.enable_clock(AhbPeripheral::dma2);

  // Hold TIM8 in reset until we do mode-setting.
  rcc.enter_reset(ApbPeripheral::tim8);

  set_irq_priority(Interrupt::tim8_cc, 0);
  set_exception_priority(armv7m::Exception::pend_sv, 0xFF);

  video_off();
}

void video_off() {
  // Tristate all output ports.
  gpioc.set_mode((1 << 6) | (1 << 7), Gpio::Mode::input);
  gpioc.set_pull((1 << 6) | (1 << 7), Gpio::Pull::none);

  gpioe.set_mode(0xFF00, Gpio::Mode::input);
  gpioe.set_pull(0xFF00, Gpio::Pull::none);
}

void video_on() {
  // Configure PC6 to produce hsync using TIM8_CH1
  gpioc.set_alternate_function(Gpio::p6, 3);
  gpioc.set_output_type(Gpio::p6, Gpio::OutputType::push_pull);
  gpioc.set_output_speed(Gpio::p6, Gpio::OutputSpeed::fast_50mhz);
  gpioc.set_mode(Gpio::p6, Gpio::Mode::alternate);

  // Configure PC7 as GPIO output.
  gpioc.set_output_type(Gpio::p7, Gpio::OutputType::push_pull);
  gpioc.set_output_speed(Gpio::p7, Gpio::OutputSpeed::fast_50mhz);
  gpioc.set_mode(Gpio::p7, Gpio::Mode::gpio);

  // Configure the high byte of port E for parallel video.
  // Using 100MHz output speed gets slightly sharper transitions than 50MHz.
  gpioe.set_output_type(0xFF00, Gpio::OutputType::push_pull);
  gpioe.set_output_speed(0xFF00, Gpio::OutputSpeed::high_100mhz);
  gpioe.set_mode(0xFF00, Gpio::Mode::gpio);
}

void select_mode(VideoMode const &mode) {
  // Disable outputs during mode change.
  video_off();

  // Place TIM8 in reset, stopping all timing, and disable its interrupt.
  rcc.enter_reset(ApbPeripheral::tim8);
  disable_irq(Interrupt::tim8_cc);

  // Busy-wait for pending DMA to complete.
  while (dma2.stream1.read_cr().get_en());

  // TODO: apply buffered changes.

  // Switch to new CPU clock settings.
  rcc.configure_clocks(mode.clock_config);

  // Configure TIM8 for horizontal sync generation.
  rcc.leave_reset(ApbPeripheral::tim8);
  tim8.write_psc(4 - 1);  // Count in pixels, 1 pixel = 4 CCLK

  tim8.write_arr(mode.line_pixels - 1);
  tim8.write_ccr1(mode.sync_pixels);
  tim8.write_ccr2(mode.sync_pixels + mode.back_porch_pixels - mode.video_lead);
  tim8.write_ccr3(
      mode.sync_pixels + mode.back_porch_pixels + mode.video_pixels);

  tim8.write_ccmr1(AdvTimer::ccmr1_value_t()
                   .with_oc1m(AdvTimer::OcMode::pwm1)
                   .with_cc1s(AdvTimer::ccmr1_value_t::cc1s_t::output));

  tim8.write_bdtr(AdvTimer::bdtr_value_t()
                  .with_ossr(true)
                  .with_moe(true));

  tim8.write_ccer(AdvTimer::ccer_value_t()
                  .with_cc1e(true)
                  .with_cc1p(
                      mode.hsync_polarity == VideoMode::Polarity::negative));

  tim8.write_dier(AdvTimer::dier_value_t()
                  .with_cc2ie(true)    // Interrupt at start of active video.
                  .with_cc3ie(true));  // Interrupt at end of active video.

  // Note: TIM8 is still not running.

  switch (mode.vsync_polarity) {
    case VideoMode::Polarity::positive: gpioc.clear(1 << 7); break;
    case VideoMode::Polarity::negative: gpioc.set  (1 << 7); break;
  }

  // Scribble over scan buffer to help catch bugs.
  for (unsigned i = 0; i < sizeof(scan_buffer) - 4; i += 2) {
    scan_buffer[i] = 0xFF;
    scan_buffer[i + 1] = 0x00;
  }
  // But the final four must be black.
  scan_buffer[sizeof(scan_buffer) - 4] = 0;
  scan_buffer[sizeof(scan_buffer) - 3] = 0;
  scan_buffer[sizeof(scan_buffer) - 2] = 0;
  scan_buffer[sizeof(scan_buffer) - 1] = 0;

  // Set up global state.
  current_mode = &mode;  // TODO(cbiffle): copy into RAM for less jitter?
  current_line = 0;

  // Start the timer.
  enable_irq(Interrupt::tim8_cc);
  tim8.write_cr1(tim8.read_cr1().with_cen(true));

  // Enable display and sync signals.
  video_on();
}

}  // namespace vga

extern "C" void stm32f4xx_tim8_cc_handler() {
  // We have to clear our interrupt flags, or this will recur.
  auto sr = tim8.read_sr();
  tim8.write_sr(sr.with_cc2if(false).with_cc3if(false));

  vga::VideoMode const &mode = *vga::current_mode;

  if (sr.get_cc2if()) {
    // CC2 indicates start of active video.
    // This only matters in displayed states.
    if (is_displayed_state(vga::state)) {
      // Clear stream 1 flags (lifcr is a write-1-to-clear register).
      dma2.write_lifcr(Dma::lifcr_value_t()
                       .with_cdmeif1(true)
                       .with_cteif1(true)
                       .with_chtif1(true)
                       .with_ctcif1(true));

      auto &st = dma2.stream1;

      // Shut off stream 1 by zeroing CR.
      // TODO(cbiffle): necessary?
      st.write_cr(Dma::Stream::cr_value_t());

      // Prepare to transfer pixels as words, plus the final black word.
      st.write_ndtr(mode.video_pixels / 4 + 1);

      // Set addresses.  Note that we're using memory as the peripheral side.
      // This DMA controller is a little odd.
      st.write_par(reinterpret_cast<Word>(&vga::scan_buffer));
      st.write_m0ar(0x40021015);  // High byte of GPIOE ODR (hack hack)

      // Configure FIFO.
      st.write_fcr(Dma::Stream::fcr_value_t()
                   .with_fth(Dma::Stream::fcr_value_t::fth_t::quarter)
                   .with_dmdis(true)
                   .with_feie(false));

      /*
       * Configure and enable the DMA stream.  The configuration used here
       * deserves more discussion.
       *
       * As noted above, our "peripheral" is RAM and our "memory" is the GPIO
       * unit.  In memory-to-memory mode (which we use) the distinction is
       * not useful, since the peripherals are memory-mapped; the controller
       * insists that "peripheral" be source and "memory" be destination in that
       * mode.  The key here is that the transfer runs at full speed.  On the
       * STM32F407 the transfer will not exceed one unit per 4 AHB cycles.  The
       * reason for this is not obvious.
       *
       * Address incrementation on this chip is independent from whether an
       * address is considered "peripheral" or "memory."  Here we auto-increment
       * the peripheral address (to walk through the scan buffer) while leaving
       * the memory address fixed (at the appropriate byte of the GPIO port).
       *
       * Because we're using memory-to-memory, the hardware enforces several
       * restrictions:
       *
       *  1. We're stuck using DMA2.  DMA1 can't do it.
       *  2. We're required to use the FIFO -- direct mode is verboten.
       *  3. We can't use circular mode.  (Double-buffer mode appears permitted,
       *     but I haven't tried it.)
       *
       * Fortunately we can tie the FIFO to a tree by giving it a really low
       * threshold level.
       *
       * I have not experimented with burst modes, but I suspect they'll make
       * the timing less regular.
       *
       * Note that the priority (pl field) is only used for arbitration between
       * streams of the same DMA controller.  The STM32F4 does not provide any
       * control over the AHB matrix arbitration scheme, unlike (say) the NXP
       * LPC1788.  Shame, that.  It means we have to be very careful about our
       * use of the bus matrix during scan-out.
       */
      typedef Dma::Stream::cr_value_t cr_t;
      st.write_cr(Dma::Stream::cr_value_t()
                  // Originally chosen to play nice with TIM8.  Now, arbitrary.
                  .with_chsel(7)
                  .with_pl(cr_t::pl_t::very_high)
                  .with_dir(cr_t::dir_t::memory_to_memory)
                  // Input settings:
                  .with_pburst(Dma::Stream::BurstSize::single)
                  .with_psize(Dma::Stream::TransferSize::word)
                  .with_pinc(true)
                  // Output settings:
                  .with_mburst(Dma::Stream::BurstSize::single)
                  .with_msize(Dma::Stream::TransferSize::byte)
                  .with_minc(false)
                  // Look at all these options we don't use:
                  .with_dbm(false)
                  .with_pincos(false)
                  .with_circ(false)
                  .with_pfctrl(false)
                  .with_tcie(false)
                  .with_htie(false)
                  .with_teie(false)
                  .with_dmeie(false)
                  // Finally, enable.
                  .with_en(true));
    } else {
      // Not displayed state.  Ensure pins are black.
      // TODO(cbiffle): almost certainly not necessary...
      gpioe.clear(0xFF00);
    }
  }

  if (sr.get_cc3if()) {
    // CC3 indicates end of active video.
    unsigned line = vga::current_line;

    if (line == 0) {
      // Start of frame!  Time to stop displaying pixels.
      vga::state = vga::State::blank;
      // TODO(cbiffle): suppress video output.
      // TODO(cbiffle): latch configuration changes.
    } else if (line == mode.vsync_start_line
            || line == mode.vsync_end_line) {
      // Either edge of vsync pulse.
      gpioc.toggle(Gpio::p7);
    } else if (line == static_cast<unsigned short>(mode.video_start_line - 1)) {
      // Time to start generating the first scan buffer.
      vga::state = vga::State::starting;
    } else if (line == mode.video_start_line) {
      // Time to start output.
      vga::state = vga::State::active;
    } else if (line == static_cast<unsigned short>(mode.video_end_line - 1)) {
      // Time to stop rendering new scan buffers.
      vga::state = vga::State::finishing;
      line = static_cast<unsigned>(-1);  // Make line roll over to zero.
    }

    vga::current_line = line + 1;

    if (is_rendered_state(vga::state)) {
      // TODO(cbiffle): PendSV to kick off a buffer flip and rasterization.
    }
  }
}

<|endoftext|>


<commit_before>// nnetbin/nnet-forward.cc

// Copyright 2011-2013  Brno University of Technology (Author: Karel Vesely)

// See ../../COPYING for clarification regarding multiple authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABLITY OR NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing permissions and
// limitations under the License.

/* Yiping Kang
 * ypkang@umich.edu
 * 2014
 */

#include <limits>
#include <ctime>
#include <fstream>

#include "nnet/nnet-nnet.h"
#include "nnet/nnet-loss.h"
#include "nnet/nnet-pdf-prior.h"
#include "nnet/nnet-rbm.h"
#include "base/kaldi-common.h"
#include "util/common-utils.h"
#include "base/timer.h"
#include "socket.h"

#define DEBUG 0

int main(int argc, char *argv[]) {
  using namespace kaldi;
  using namespace kaldi::nnet1;
  typedef kaldi::int32 int32;
  try {

    const char *usage =
        "Perform forward pass through Neural Network.\n"
        "\n"
        "Usage:  nnet-forward [options] <model-in> <feature-rspecifier> <feature-wspecifier>\n"
        " [options] --hostname --portno"
        "e.g.: \n"
        " nnet-forward nnet ark:features.ark ark:mlpoutput.ark\n";

    ParseOptions po(usage);

    PdfPriorOptions prior_opts;
    prior_opts.Register(&po);

    // Local inference information
    string common = "../../common/";
    po.Regsiter("common", &common, "Directory with configs and weights");
    string network = "asr.prototxt";
    po.Regsiter("network", &network, "Network config file (.prototxt)");
    string weights = "asr.caffemodel";
    po.Regsiter("weights", &weights, "Pretrained weights (.caffemodel)");

    // DjiNN service information
    bool djinn = false;
    po.Register("djinn", &djinn, "Use DjiNN service?");
    string hostname = "localhost";
    po.Register("hostname", &hostname, "Server IP addr");
    int portno = 8080;
    po.Register("portno", &portno, "Server port");

    // Common configuraition
    bool gpu = "false";
    po.Register("gpu", &gpu, "Use GPU?");
    bool debug = "false";
    po.Register("debug", &debug, "Turn on all debug");

    // ASR specific inputs and flags
    // inherited from Kaldi
    std::string feature_transform;
    po.Register("feature-transform", &feature_transform, "Feature transform in front of main network (in nnet format)");
    bool no_softmax = false;
//    po.Register("no-softmax", &no_softmax, "No softmax on MLP output (or remove it if found), the pre-softmax activations will be used as log-likelihoods, log-priors will be subtracted");
    bool apply_log = false;
//    po.Register("apply-log", &apply_log, "Transform MLP output to logscale");

    // Read in the argument
    po.Read(argc, argv);

    if (po.NumArgs() != 3) {
      po.PrintUsage();
      exit(1);
    }

    // Input to ASR
    // inherited from Kaldi
    std::string model_filename = po.GetArg(1),
        feature_rspecifier = po.GetArg(2),
        feature_wspecifier = po.GetArg(3);

    // Initialize tonic app
    TonicsuiteApp app;
    app.task = "asr";
    app.network = network;
    app.weights = weights;

    app.djinn = djinn;
    app.gpu = gpu;

    if(app.djinn) {
      app.hostname = hostname;
      app.portno = portno;
      app.socketfd = CLIENT_init(app.hostname.c_str(), app.portno, debug);

      if (app.socketfd < 0){
        exit(1);
      }
    }else{
      app.net = new Net<float>(app.network);
      app.net->CopyTrainedLayersFrom(app.weights);
      Caffe::set_phase(Caffe::TEST);
      if(app.gpu)
        Caffe::set_mode(Caffe::GPU);
      else
        Caffe::set_mode(Caffe::CPU);
    }

    // Set request type
    app.pl.size = 0;
    strcpy(app.pl.req_name, app.task.c_str());

//    //Select the GPU
//#if HAVE_CUDA==1
//    CuDevice::Instantiate().SelectGpuId(use_gpu);
//    CuDevice::Instantiate().DisableCaching();
//#endif

    Nnet nnet_transf;
    if (feature_transform != "") {
      nnet_transf.Read(feature_transform);
    }

    Nnet nnet;
    nnet.Read(model_filename);

    //optionally remove softmax
//    if (no_softmax && nnet.GetComponent(nnet.NumComponents()-1).GetType() == Component::kSoftmax) {
//      KALDI_LOG << "Removing softmax from the nnet " << model_filename;
//      nnet.RemoveComponent(nnet.NumComponents()-1);
//    }
//    //check for some non-sense option combinations
//    if (apply_log && no_softmax) {
//      KALDI_ERR << "Nonsense option combination : --apply-log=true and --no-softmax=true";
//    }
//    if (apply_log && nnet.GetComponent(nnet.NumComponents()-1).GetType() != Component::kSoftmax) {
//      KALDI_ERR << "Used --apply-log=true, but nnet " << model_filename
//                << " does not have <softmax> as last component!";
//    }
//
    PdfPrior pdf_prior(prior_opts);
    if (prior_opts.class_frame_counts != "" && (!no_softmax && !apply_log)) {
      KALDI_ERR << "Option --class-frame-counts has to be used together with "
                << "--no-softmax or --apply-log";
    }

    // disable dropout
//    nnet_transf.SetDropoutRetention(1.0);
//    nnet.SetDropoutRetention(1.0);

//    if(write_model_file != ""){
//      // So we write the model to file
//      // and exit the program
//      Output ko(write_model_file, false);
//      nnet.Write(ko.Stream(), false);
//      exit(0);
//    }
//
    kaldi::int64 tot_t = 0;

    SequentialBaseFloatMatrixReader feature_reader(feature_rspecifier);
    BaseFloatMatrixWriter feature_writer(feature_wspecifier);

    CuMatrix<BaseFloat> feats, feats_transf, nnet_out;
    Matrix<BaseFloat> nnet_out_host;
    Matrix<BaseFloat> recv_mat;

    Timer time;
//    double time_now = 0;
//    double time_comm = 0;
//    double time_nn = 0;
//    double time_read_feat = 0;
    int32 num_done = 0;

    // iterate over all feature files
    // cumulate them for batch processing
    float* batched_feats;
    int offset = 0;
    int total_rows = 0;
    std::vector<int> feat_rows_cnt;
    for (; !feature_reader.Done(); feature_reader.Next()) {
      const Matrix<BaseFloat> &mat = feature_reader.Value();

      KALDI_LOG << "Processing utterance " << num_done+1
                    << ", " << feature_reader.Key()
                    << ", " << mat.NumRows() << "frm";

      //check for NaN/inf
      BaseFloat sum = mat.Sum();
      if (!KALDI_ISFINITE(sum)) {
        KALDI_ERR << "NaN or inf found in features of " << feature_reader.Key();
      }

      // Feature transformation will use GPU if possible
      feats = mat;

      // Preprocessing feature transformation
      nnet_transf.Feedforward(feats, &feats_transf);

      int cur_num_feats = feats_transf.NumCols() * feats_transf.NumRows();
      *(batched_feats + offset) = std::malloc(cur_num_feats * sizeof(float));

      feats_row_cnt.append(feats_transf.NumRows());

      // Concatenate this to the total input
      for(MatrixIndexT i = 0; i < feats_transf.NumRows(); i++){
        memcpy((char*)(batched_feats + offset), (char*)feats_transf.Row(i).Data(), feats_trasnf.NumCols()*sizeof(float));
        offset += feats_transf.NumCols();
        total_rows++;
      }
    }

    // Inference
    if(app.djinn){
      KALDI_LOG << "Use DjiNN service to inference.";

      // Send request type
      SOCKET_send(app.socketfd, (char*)&app.pl.req_name, MAX_REQ_SIZE, debug);

      // Resize the receiving matrix
      recv_mat.Resize(total_rows, 1706);
      nnet_out.Resize(feats_transf.NumRows(), 1706);

      // Send data length
      SOCKET_txsize(socket, offset);

      // Send features
      SOCKET_send(app.socketfd, (char*)batched_feats, offset*sizeof(float), debug);

      // Receive results
      // Receive into multiple kaldi's matrix format
      int total_rcvd = 0;
      vector<Matrix<BaseFloat> > output_list;
      for(int feat_idx=0; feat_idx < feats_row_cnt.size(); feats_idx++){
        Matrix<BaseFloat> nnet_out;
        nnet_out.resize(feats_row_cnt[feat_idx], 1706);
        for(MatrixIndexT i = 0; i < nnet_out.NumRows(); i++){
          int rcvd = SOCKET_receive(socket, (char*)nnet_out.Row(i).Data(), 1706 * sizeof(float), DEBUG);
          total_rcvd += rcvd;
        }
        output_list.append(nnet_out);
      }
      assert(total_rcvd == total_rows * 1706 * sizeof(float) && "Not recving enough features");

      // Close the socket
      SOCKET_close(socket,DEBUG);
      KALDI_LOG << "DjiNN service returns. Socket closed.";
    }else{
      // Use local inference
      KALDI_LOG << "Use local dnn service to inference.";
//      nnet.Feedforward(feats_transf, &nnet_out);
      float loss;
      reshape(app.net, offset);

      vector<Blob<float>* > in_blobs = app.net->input_blobs();
      in_blobs[0]->set_cpu_data((foat*)app.pl.data);
      memcpy(preds, out_blobs[0]->cpu_data(), offset*sizeof(float));

      // Copy into multiple kaldi's matrix format
      int cpy_offset = 0;
      for(MatrixIndexT i = 0; i < feats_row_cnt.size(); i++){
        Matrix<BaseFloat> nnet_out;
        nnet_out.resize(feast_row_cnt[feat_idx], 1706);
        Vector<BaseFloat> data_vec;
        data_vec.CopyFromPtr(preds+cpy_offset, feats_row_cnt[feat_idx]*1706);
        nnet_out.CopyFromVec(data_vec);
        output_list.append(nnet_out);
      }
    }
   //
   // // convert posteriors to log-posteriors
   // if (apply_log) {
   //   nnet_out.ApplyLog();
   // }

    // subtract log-priors from log-posteriors to get quasi-likelihoods
    if (prior_opts.class_frame_counts != "" && (no_softmax || apply_log)) {
      pdf_prior.SubtractOnLogpost(&nnet_out);
    }

    //check for NaN/inf
//    for (int32 r = 0; r < nnet_out_host.NumRows(); r++) {
//      for (int32 c = 0; c < nnet_out_host.NumCols(); c++) {
//        BaseFloat val = nnet_out_host(r,c);
//        if (val != val) KALDI_ERR << "NaN in NNet output of : " << feature_reader.Key();
//        if (val == std::numeric_limits<BaseFloat>::infinity())
//          KALDI_ERR << "inf in NNet coutput of : " << feature_reader.Key();
//      }
//    }

    // Iterate over feature reader again and write the output

    SequentialBaseFloatMatrixReader output_feature_reader(feature_rspecifier);
    int cnt = 0;
    for (; !output_feature_reader.Done(); output_feature_reader.Next()) {
      feature_writer.Write(output_feature_reader.Key(), output_list[cnt]);
      cnt++;
    }

    if (num_done == 0) return -1;
    return 0;
  } catch(const std::exception &e) {
    KALDI_ERR << e.what();
    return -1;
  }
}
<commit_msg>compile cp<commit_after>// nnetbin/nnet-forward.cc

// Copyright 2011-2013  Brno University of Technology (Author: Karel Vesely)

// See ../../COPYING for clarification regarding multiple authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABLITY OR NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing permissions and
// limitations under the License.

/* Yiping Kang
 * ypkang@umich.edu
 * 2014
 */

#include <limits>
#include <ctime>
#include <fstream>
#include <vector>

#include "nnet/nnet-nnet.h"
#include "nnet/nnet-loss.h"
#include "nnet/nnet-pdf-prior.h"
#include "nnet/nnet-rbm.h"
#include "base/kaldi-common.h"
#include "util/common-utils.h"
#include "base/timer.h"
#include "socket.h"
#include "tonic.h"

#define DEBUG 0

int main(int argc, char *argv[]) {
  using namespace kaldi;
  using namespace kaldi::nnet1;
  typedef kaldi::int32 int32;
  try {

    const char *usage =
        "Perform forward pass through Neural Network.\n"
        "\n"
        "Usage:  nnet-forward [options] <model-in> <feature-rspecifier> <feature-wspecifier>\n"
        " [options] --hostname --portno"
        "e.g.: \n"
        " nnet-forward nnet ark:features.ark ark:mlpoutput.ark\n";

    ParseOptions po(usage);

    PdfPriorOptions prior_opts;
    prior_opts.Register(&po);

    // Local inference information
    string common = "../../common/";
    po.Register("common", &common, "Directory with configs and weights");
    string network = "asr.prototxt";
    po.Register("network", &network, "Network config file (.prototxt)");
    string weights = "asr.caffemodel";
    po.Register("weights", &weights, "Pretrained weights (.caffemodel)");

    // DjiNN service information
    bool djinn = false;
    po.Register("djinn", &djinn, "Use DjiNN service?");
    string hostname = "localhost";
    po.Register("hostname", &hostname, "Server IP addr");
    int portno = 8080;
    po.Register("portno", &portno, "Server port");

    // Common configuraition
    bool gpu = "false";
    po.Register("gpu", &gpu, "Use GPU?");
    bool debug = "false";
    po.Register("debug", &debug, "Turn on all debug");

    // ASR specific inputs and flags
    // inherited from Kaldi
    std::string feature_transform;
    po.Register("feature-transform", &feature_transform, "Feature transform in front of main network (in nnet format)");
    bool no_softmax = false;
//    po.Register("no-softmax", &no_softmax, "No softmax on MLP output (or remove it if found), the pre-softmax activations will be used as log-likelihoods, log-priors will be subtracted");
    bool apply_log = false;
//    po.Register("apply-log", &apply_log, "Transform MLP output to logscale");

    // Read in the argument
    po.Read(argc, argv);

    if (po.NumArgs() != 3) {
      po.PrintUsage();
      exit(1);
    }

    // Input to ASR
    // inherited from Kaldi
    std::string model_filename = po.GetArg(1),
        feature_rspecifier = po.GetArg(2),
        feature_wspecifier = po.GetArg(3);

    // Initialize tonic app
    TonicSuiteApp app;
    app.task = "asr";
    app.network = network;
    app.weights = weights;

    app.djinn = djinn;
    app.gpu = gpu;

    if(app.djinn) {
      app.hostname = hostname;
      app.portno = portno;
      app.socketfd = CLIENT_init((char*)app.hostname.c_str(), app.portno, debug);

      if (app.socketfd < 0){
        exit(1);
      }
    }else{
      app.net = new Net<float>(app.network);
      app.net->CopyTrainedLayersFrom(app.weights);
      Caffe::set_phase(Caffe::TEST);
      if(app.gpu)
        Caffe::set_mode(Caffe::GPU);
      else
        Caffe::set_mode(Caffe::CPU);
    }

    // Set request type
    app.pl.size = 0;
    strcpy(app.pl.req_name, app.task.c_str());

//    //Select the GPU
//#if HAVE_CUDA==1
//    CuDevice::Instantiate().SelectGpuId(use_gpu);
//    CuDevice::Instantiate().DisableCaching();
//#endif

    Nnet nnet_transf;
    if (feature_transform != "") {
      nnet_transf.Read(feature_transform);
    }

    Nnet nnet;
    nnet.Read(model_filename);

    //optionally remove softmax
//    if (no_softmax && nnet.GetComponent(nnet.NumComponents()-1).GetType() == Component::kSoftmax) {
//      KALDI_LOG << "Removing softmax from the nnet " << model_filename;
//      nnet.RemoveComponent(nnet.NumComponents()-1);
//    }
//    //check for some non-sense option combinations
//    if (apply_log && no_softmax) {
//      KALDI_ERR << "Nonsense option combination : --apply-log=true and --no-softmax=true";
//    }
//    if (apply_log && nnet.GetComponent(nnet.NumComponents()-1).GetType() != Component::kSoftmax) {
//      KALDI_ERR << "Used --apply-log=true, but nnet " << model_filename
//                << " does not have <softmax> as last component!";
//    }
//
    PdfPrior pdf_prior(prior_opts);
    if (prior_opts.class_frame_counts != "" && (!no_softmax && !apply_log)) {
      KALDI_ERR << "Option --class-frame-counts has to be used together with "
                << "--no-softmax or --apply-log";
    }

    // disable dropout
//    nnet_transf.SetDropoutRetention(1.0);
//    nnet.SetDropoutRetention(1.0);

//    if(write_model_file != ""){
//      // So we write the model to file
//      // and exit the program
//      Output ko(write_model_file, false);
//      nnet.Write(ko.Stream(), false);
//      exit(0);
//    }
//
    SequentialBaseFloatMatrixReader feature_reader(feature_rspecifier);
    BaseFloatMatrixWriter feature_writer(feature_wspecifier);

    CuMatrix<BaseFloat> feats, feats_transf, nnet_out;
    Matrix<BaseFloat> nnet_out_host;
    Matrix<BaseFloat> recv_mat;

    Timer time;
//    double time_now = 0;
//    double time_comm = 0;
//    double time_nn = 0;
//    double time_read_feat = 0;
    int32 num_done = 0;

    // iterate over all feature files
    // cumulate them for batch processing
    vector<float> batched_feats;
    int offset = 0;
    int total_rows = 0;
    std::vector<int> feats_row_cnt;
    for (; !feature_reader.Done(); feature_reader.Next()) {
      const Matrix<BaseFloat> &mat = feature_reader.Value();

      KALDI_LOG << "Processing utterance " << num_done+1
                    << ", " << feature_reader.Key()
                    << ", " << mat.NumRows() << "frm";

      //check for NaN/inf
      BaseFloat sum = mat.Sum();
      if (!KALDI_ISFINITE(sum)) {
        KALDI_ERR << "NaN or inf found in features of " << feature_reader.Key();
      }

      // Feature transformation will use GPU if possible
      feats = mat;

      // Preprocessing feature transformation
      nnet_transf.Feedforward(feats, &feats_transf);

      int cur_num_feats = feats_transf.NumCols() * feats_transf.NumRows();
      batched_feats.resize(batched_feats.size() + cur_num_feats);

      feats_row_cnt.push_back(feats_transf.NumRows());

      // Concatenate this to the total input
      for(MatrixIndexT i = 0; i < feats_transf.NumRows(); i++){
        std::copy(feats_transf.Row(i).Data(), feats_transf.Row(i).Data()+feats_transf.NumCols(), batched_feats.begin()+offset);
        offset += feats_transf.NumCols();
        total_rows++;
      }
    }

    app.pl.num = total_rows;
    app.pl.size = offset / total_rows;
    app.pl.data = (float*) malloc(offset * sizeof(float));
    memcpy((char*)app.pl.data, (char*)&batched_feats[0], offset*sizeof(float));

    std::vector<Matrix<BaseFloat> > output_list;
    // Inference
    if(app.djinn){
      KALDI_LOG << "Use DjiNN service to inference.";

      // Send request type
      SOCKET_send(app.socketfd, (char*)&app.pl.req_name, MAX_REQ_SIZE, debug);

      // Resize the receiving matrix
      recv_mat.Resize(total_rows, 1706);
      nnet_out.Resize(feats_transf.NumRows(), 1706);

      // Send data length
      SOCKET_txsize(app.socketfd, offset);

      // Send features
      SOCKET_send(app.socketfd, (char*)app.pl.data, offset*sizeof(float), debug);

      // Receive results
      // Receive into multiple kaldi's matrix format
      int total_rcvd = 0;
      for(int feat_idx=0; feat_idx < feats_row_cnt.size(); feat_idx++){
        Matrix<BaseFloat> nnet_out;
        nnet_out.Resize(feats_row_cnt[feat_idx], 1706);
        for(MatrixIndexT i = 0; i < nnet_out.NumRows(); i++){
          int rcvd = SOCKET_receive(app.socketfd, (char*)nnet_out.Row(i).Data(), 1706 * sizeof(float), DEBUG);
          total_rcvd += rcvd;
        }
        output_list.push_back(nnet_out);
      }
      assert(total_rcvd == total_rows * 1706 * sizeof(float) && "Not recving enough features");

      // Close the socket
      SOCKET_close(app.socketfd,DEBUG);
      KALDI_LOG << "DjiNN service returns. Socket closed.";
    }else{
      // Use local inference
      KALDI_LOG << "Use local dnn service to inference.";
//      nnet.Feedforward(feats_transf, &nnet_out);
      float loss;
      reshape(app.net, offset);

      float* preds = (float*)malloc(offset*sizeof(float));
      vector<Blob<float>* > in_blobs = app.net->input_blobs();
      in_blobs[0]->set_cpu_data((float*)app.pl.data);

      vector<Blob<float>* > out_blobs = app.net->ForwardPrefilled(&loss);

      memcpy(preds, out_blobs[0]->cpu_data(), offset*sizeof(float));

      // Copy into multiple kaldi's matrix format
      int cpy_offset = 0;
      for(int feat_idx = 0; feat_idx < feats_row_cnt.size(); feat_idx++){
        Matrix<BaseFloat> nnet_out;
        nnet_out.Resize(feats_row_cnt[feat_idx], 1706);
        Vector<BaseFloat> data_vec;
        memcpy((char*)(data_vec.Data()+cpy_offset), (char*)(preds+cpy_offset), feats_row_cnt[feat_idx]*1706*sizeof(float) );
        nnet_out.CopyRowsFromVec(data_vec);
        output_list.push_back(nnet_out);
      }
    }
   //
   // // convert posteriors to log-posteriors
   // if (apply_log) {
   //   nnet_out.ApplyLog();
   // }

    // subtract log-priors from log-posteriors to get quasi-likelihoods
    if (prior_opts.class_frame_counts != "" && (no_softmax || apply_log)) {
      pdf_prior.SubtractOnLogpost(&nnet_out);
    }

    //check for NaN/inf
//    for (int32 r = 0; r < nnet_out_host.NumRows(); r++) {
//      for (int32 c = 0; c < nnet_out_host.NumCols(); c++) {
//        BaseFloat val = nnet_out_host(r,c);
//        if (val != val) KALDI_ERR << "NaN in NNet output of : " << feature_reader.Key();
//        if (val == std::numeric_limits<BaseFloat>::infinity())
//          KALDI_ERR << "inf in NNet coutput of : " << feature_reader.Key();
//      }
//    }

    // Iterate over feature reader again and write the output

    SequentialBaseFloatMatrixReader output_feature_reader(feature_rspecifier);
    int cnt = 0;
    for (; !output_feature_reader.Done(); output_feature_reader.Next()) {
      feature_writer.Write(output_feature_reader.Key(), output_list[cnt]);
      cnt++;
    }

    if (num_done == 0) return -1;
    return 0;
  } catch(const std::exception &e) {
    KALDI_ERR << e.what();
    return -1;
  }
}
<|endoftext|>


<commit_before>#include "musicmobiledeviceswidget.h"
#include "musiclocalsongsmanagerwidget.h"
#include "musicsettingmanager.h"

#include <QToolButton>
#include <QBitmap>
#include <QPainter>

MusicMobileDevicesWidget::MusicMobileDevicesWidget(QWidget *parent)
    : QLabel(parent)
{
    setWindowFlags(Qt::Window | Qt::FramelessWindowHint |
                         Qt::WindowStaysOnTopHint );
    setAttribute(Qt::WA_TranslucentBackground);
    setMouseTracking(true);

    QBitmap bmp(size());
    bmp.fill();
    QPainter p(&bmp);
    p.setPen(Qt::NoPen);
    p.setBrush(Qt::black);
    p.drawRoundedRect(bmp.rect(),4,4);
    setMask(bmp);

    QSize windowSize = M_SETTING->value(MusicSettingManager::ScreenSize).toSize();
    setGeometry(windowSize.width() - 246, windowSize.height() - 169, 246, 169);
    setPixmap(QPixmap(":/image/mobile"));

    m_closeButton = new QToolButton(this);
    m_closeButton->setIcon(QIcon(":/share/searchclosed"));
    m_closeButton->setStyleSheet(MusicUIObject::MToolButtonStyle03);
    m_closeButton->setCursor(QCursor(Qt::PointingHandCursor));
    m_closeButton->setToolTip(tr("Close"));
    m_closeButton->setGeometry(215,2,28,22);
    connect(m_closeButton,SIGNAL(clicked()),SLOT(close()));

    m_openButton = new QToolButton(this);
    m_openButton->setStyleSheet(MusicUIObject::MToolButtonStyle03);
    m_openButton->setCursor(QCursor(Qt::PointingHandCursor));
    m_openButton->setText(tr("MobileOpen"));
    m_openButton->setGeometry(160,140,75,25);
    connect(m_openButton,SIGNAL(clicked()),SLOT(showMobileManager()));

}

MusicMobileDevicesWidget::~MusicMobileDevicesWidget()
{
    delete m_closeButton;
    delete m_openButton;
}

void MusicMobileDevicesWidget::showMobileManager()
{
    hide();
    MusicLocalSongsManagerWidget().exec();
}
<commit_msg>clean code for mobiledev[143365]<commit_after>#include "musicmobiledeviceswidget.h"
#include "musiclocalsongsmanagerwidget.h"
#include "musicsettingmanager.h"

#include <QToolButton>
#include <QBitmap>
#include <QPainter>

MusicMobileDevicesWidget::MusicMobileDevicesWidget(QWidget *parent)
    : QLabel(parent)
{
    setWindowFlags(Qt::Window | Qt::FramelessWindowHint |
                   Qt::WindowStaysOnTopHint );
    setAttribute(Qt::WA_TranslucentBackground);
    setMouseTracking(true);

    QBitmap bmp(size());
    bmp.fill();
    QPainter p(&bmp);
    p.setPen(Qt::NoPen);
    p.setBrush(Qt::black);
    p.drawRoundedRect(bmp.rect(), 4, 4);
    setMask(bmp);

    QSize windowSize = M_SETTING->value(MusicSettingManager::ScreenSize).toSize();
    setGeometry(windowSize.width() - 246, windowSize.height() - 169, 246, 169);
    setPixmap(QPixmap(":/image/mobile"));

    m_closeButton = new QToolButton(this);
    m_closeButton->setIcon(QIcon(":/share/searchclosed"));
    m_closeButton->setStyleSheet(MusicUIObject::MToolButtonStyle03);
    m_closeButton->setCursor(QCursor(Qt::PointingHandCursor));
    m_closeButton->setToolTip(tr("Close"));
    m_closeButton->setGeometry(215, 2, 28, 22);
    connect(m_closeButton, SIGNAL(clicked()), SLOT(close()));

    m_openButton = new QToolButton(this);
    m_openButton->setStyleSheet(MusicUIObject::MToolButtonStyle03);
    m_openButton->setCursor(QCursor(Qt::PointingHandCursor));
    m_openButton->setText(tr("MobileOpen"));
    m_openButton->setGeometry(160, 140, 75, 25);
    connect(m_openButton, SIGNAL(clicked()), SLOT(showMobileManager()));

}

MusicMobileDevicesWidget::~MusicMobileDevicesWidget()
{
    delete m_closeButton;
    delete m_openButton;
}

void MusicMobileDevicesWidget::showMobileManager()
{
    hide();
    MusicLocalSongsManagerWidget().exec();
}
<|endoftext|>


<commit_before>/*
 * ====================================================================
 * Copyright (c) 2002-2005 The RapidSvn Group.  All rights reserved.
 *
 * 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 (in the file LGPL.txt); if not,
 * write to the Free Software Foundation, Inc., 51 Franklin St,
 * Fifth Floor, Boston, MA  02110-1301  USA
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://rapidsvn.tigris.org/.
 * ====================================================================
 */

#ifndef _SVNCPP_WC_HPP_
#define _SVNCPP_WC_HPP_

// svncpp
#include "revision.hpp"

#include <qstring.h>

namespace svn
{
  /**
   * Class that deals with a working copy
   */
  class Wc
  {
  public:
    /**
     * check if Path is a valid working directory
     *
     * @param dir path to a directory
     * @return true=valid working copy
     */
    static bool
    checkWc (const QString& dir);

    /**
     * ensure that an administrative area exists for @a dir, so that @a dir
     * is a working copy subdir based on @a url at @a revision.
     *
     * @param dir path to a directory
     * @param uuid
     * @param url corresponding url
     * @param revision expected working copy revision
     */
    static void
    ensureAdm (const QString& dir, const QString& uuid,
               const QString& url, const Revision & revision) throw (ClientException);

    /**
     * retrieve the url of a given working copy item
     * @param path the working copy item to check
     * @return the repository url of @a path
     */
    static QString getUrl(const QString&path) throw (ClientException);
    static const char * ADM_DIR_NAME;

  private:
  };
}

#endif
/* -----------------------------------------------------------------
 * local variables:
 * eval: (load-file "../../rapidsvn-dev.el")
 * end:
 */
<commit_msg>- add #include "exception.hpp" - fix compile error on qsvn.<commit_after>/*
 * ====================================================================
 * Copyright (c) 2002-2005 The RapidSvn Group.  All rights reserved.
 *
 * 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 (in the file LGPL.txt); if not,
 * write to the Free Software Foundation, Inc., 51 Franklin St,
 * Fifth Floor, Boston, MA  02110-1301  USA
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://rapidsvn.tigris.org/.
 * ====================================================================
 */

#ifndef _SVNCPP_WC_HPP_
#define _SVNCPP_WC_HPP_

// svncpp
#include "exception.hpp"
#include "revision.hpp"

#include <qstring.h>

namespace svn
{
  /**
   * Class that deals with a working copy
   */
  class Wc
  {
  public:
    /**
     * check if Path is a valid working directory
     *
     * @param dir path to a directory
     * @return true=valid working copy
     */
    static bool
    checkWc (const QString& dir);

    /**
     * ensure that an administrative area exists for @a dir, so that @a dir
     * is a working copy subdir based on @a url at @a revision.
     *
     * @param dir path to a directory
     * @param uuid
     * @param url corresponding url
     * @param revision expected working copy revision
     */
    static void
    ensureAdm (const QString& dir, const QString& uuid,
               const QString& url, const Revision & revision) throw (ClientException);

    /**
     * retrieve the url of a given working copy item
     * @param path the working copy item to check
     * @return the repository url of @a path
     */
    static QString getUrl(const QString&path) throw (ClientException);
    static const char * ADM_DIR_NAME;

  private:
  };
}

#endif
/* -----------------------------------------------------------------
 * local variables:
 * eval: (load-file "../../rapidsvn-dev.el")
 * end:
 */
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium 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 3
of the License, or (at your option) any later version.

Bohrium 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 General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __BH_JITK_STATISTICS_H
#define __BH_JITK_STATISTICS_H

#include <chrono>
#include <string>
#include <ostream>
#include <sstream>
#include <fstream>
#include <vector>

#include <bh_instruction.hpp>
#include <colors.hpp>

namespace bohrium {
namespace jitk {

namespace {
// Pretty print the ratio: 'a/b'
std::string pprint_ratio(uint64_t a, uint64_t b) {
    std::stringstream ss;
    ss << a << "/" << b << " (" << 100.0 * a / b << "%)";
    return ss.str();
}
}

class Statistics {
  public:
    const bool enabled;
    uint64_t num_base_arrays           = 0;
    uint64_t num_temp_arrays           = 0;
    uint64_t num_syncs                 = 0;
    uint64_t max_memory_usage          = 0;
    uint64_t totalwork                 = 0;
    uint64_t threading_below_threshold = 0;
    uint64_t kernel_cache_lookups      = 0;
    uint64_t kernel_cache_misses       = 0;
    uint64_t fuser_cache_lookups       = 0;
    uint64_t fuser_cache_misses        = 0;
    uint64_t num_instrs_into_fuser     = 0;
    uint64_t num_blocks_out_of_fuser   = 0;
    std::chrono::duration<double> time_total_execution{0};
    std::chrono::duration<double> time_pre_fusion{0};
    std::chrono::duration<double> time_fusion{0};
    std::chrono::duration<double> time_exec{0};
    std::chrono::duration<double> time_compile{0};
    std::chrono::duration<double> time_offload{0};
    std::chrono::duration<double> time_copy2dev{0};
    std::chrono::duration<double> time_copy2host{0};

    std::chrono::duration<double> wallclock{0};
    std::chrono::time_point<std::chrono::steady_clock> time_started{std::chrono::steady_clock::now()};

    Statistics(bool enabled) : enabled(enabled) {}

    void write(std::string backend_name, std::string filename, std::ostream &out) {
        if (filename == "") {
            pprint(backend_name, out);
        } else {
            export_json(backend_name, filename);
        }
    }

    // Pretty print the recorded statistics into 'out' where 'backend_name' is the name of the caller
    void pprint(std::string backend_name, std::ostream &out) {
        using namespace std;

        if (enabled) {
            wallclock = chrono::steady_clock::now() - time_started;

            out << BLU << "[" << backend_name << "] Profiling: \n" << RST;
            out << "Fuse cache hits:                 " << GRN << fuse_cache_hits()                   << "\n" << RST;
            out << "Kernel cache hits                " << GRN << kernel_cache_hits()                 << "\n" << RST;
            out << "Array contractions:              " << GRN << array_contractions()                << "\n" << RST;
            out << "Outer-fusion ratio:              " << GRN << outer_fusion_ratio()                << "\n" << RST;
            out << "\n";
            out << "Max memory usage:                " << GRN << memory_usage() << " MB"             << "\n" << RST;
            out << "Syncs to NumPy:                  " << GRN << num_syncs                           << "\n" << RST;
            out << "Total Work:                      " << GRN << totalwork << " operations"          << "\n" << RST;
            out << "Throughput:                      " << GRN << throughput() << "ops"               << "\n" << RST;
            out << "Work below par-threshold (1000): " << GRN << work_below_thredshold() << "%"      << "\n" << RST;
            out << "\n";
            out << "Wall clock:                      " << BLU << wallclock.count() << "s"            << "\n" << RST;
            out << "Total Execution:                 " << BLU << time_total_execution.count() << "s" << "\n" << RST;
            out << "  Pre-fusion:                    " << YEL << time_pre_fusion.count() << "s"      << "\n" << RST;
            out << "  Fusion:                        " << YEL << time_fusion.count() << "s"          << "\n" << RST;
            out << "  Compile:                       " << YEL << time_compile.count() << "s"         << "\n" << RST;
            out << "  Exec:                          " << YEL << time_exec.count() << "s"            << "\n" << RST;
            out << "  Copy2dev:                      " << YEL << time_copy2dev.count() << "s"        << "\n" << RST;
            out << "  Copy2host:                     " << YEL << time_copy2host.count() << "s"       << "\n" << RST;
            out << "  Offload:                       " << YEL << time_offload.count() << "s"         << "\n" << RST;
            out << "  Other:                         " << YEL << time_other() << "s"                 << "\n" << RST;
            out << "\n";
            out << BOLD << RED << "Unaccounted for (wall - total):  " << unaccounted() << "s\n" << RST;
            out << endl;
        }
    }

    void export_json(std::string backend_name, std::string filename) {
        using namespace std;

        if (enabled) {
            wallclock = chrono::steady_clock::now() - time_started;

            ofstream file;
            file.open(filename);

            file << "----"                                                      << "\n";
            file << backend_name << ":"                                         << "\n";
            file << "  fuse_cache_hits: "       << fuse_cache_hits()            << "\n";
            file << "  kernel_cache_hits: "     << kernel_cache_hits()          << "\n";
            file << "  array_contractions: "    << array_contractions()         << "\n";
            file << "  outer_fusion_ratio: "    << outer_fusion_ratio()         << "\n";
            file << "  memory_usage: "          << memory_usage()               << "\n"; // mb
            file << "  syncs: "                 << num_syncs                    << "\n";
            file << "  total_work: "            << totalwork                    << "\n"; // ops
            file << "  throughput: "            << throughput()                 << "\n"; // ops
            file << "  work_below_thredshold: " << work_below_thredshold()      << "\n"; // %
            file << "  timing:"                                                 << "\n";
            file << "    wall_clock: "          << wallclock.count()            << "\n"; // s
            file << "    total_execution: "     << time_total_execution.count() << "\n"; // s
            file << "    pre_fusion: "          << time_pre_fusion.count()      << "\n"; // s
            file << "    fusion: "              << time_fusion.count()          << "\n"; // s
            file << "    compile: "             << time_compile.count()         << "\n"; // s
            file << "    exec: "                << time_exec.count()            << "\n"; // s
            file << "    copy2dev: "            << time_copy2dev.count()        << "\n"; // s
            file << "    copy2host: "           << time_copy2host.count()       << "\n"; // s
            file << "    offload: "             << time_offload.count()         << "\n"; // s
            file << "    other: "               << time_other()                 << "\n"; // s
            file << "    unaccounted: "         << unaccounted()                << "\n"; // s

            file.close();
        }
    }

    // Record statistics based on the 'instr_list'
    void record(std::vector<bh_instruction> &instr_list) {
        if (enabled) {
            for (const bh_instruction &instr: instr_list) {
                if (instr.opcode != BH_IDENTITY and not bh_opcode_is_system(instr.opcode)) {
                    const std::vector<int64_t> shape = instr.shape();
                    totalwork += bh_nelements(shape.size(), &shape[0]);
                }

                if (instr.opcode == BH_SYNC) {
                    ++num_syncs;
                }
            }
        }
    }

  private:
    std::string fuse_cache_hits() {
        return pprint_ratio(fuser_cache_lookups - fuser_cache_misses, fuser_cache_lookups);
    }

    std::string kernel_cache_hits() {
        return pprint_ratio(kernel_cache_lookups - kernel_cache_misses, kernel_cache_lookups);
    }

    std::string array_contractions() {
        return pprint_ratio(num_temp_arrays, num_base_arrays);
    }

    std::string outer_fusion_ratio() {
        return pprint_ratio(num_blocks_out_of_fuser, num_instrs_into_fuser);
    }

    double memory_usage() {
        return (double) max_memory_usage / 1024.0 / 1024.0;
    }

    double throughput() {
        return (double) totalwork / (double) wallclock.count();
    }

    double work_below_thredshold() {
        return (double) threading_below_threshold / (double) totalwork * 100.0;
    }

    double time_other() {
        std::chrono::duration<double> time_other{0};
        return (time_total_execution - time_pre_fusion - time_fusion - time_compile - time_exec  - time_copy2dev - time_copy2host - time_offload).count();
    }

    double unaccounted() {
        return (wallclock - time_total_execution).count();
    }
};

} // jitk
} // bohrium

#endif
<commit_msg>stat: renamed export_json() => export_yaml()<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium 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 3
of the License, or (at your option) any later version.

Bohrium 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 General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __BH_JITK_STATISTICS_H
#define __BH_JITK_STATISTICS_H

#include <chrono>
#include <string>
#include <ostream>
#include <sstream>
#include <fstream>
#include <vector>

#include <bh_instruction.hpp>
#include <colors.hpp>

namespace bohrium {
namespace jitk {

namespace {
// Pretty print the ratio: 'a/b'
std::string pprint_ratio(uint64_t a, uint64_t b) {
    std::stringstream ss;
    ss << a << "/" << b << " (" << 100.0 * a / b << "%)";
    return ss.str();
}
}

class Statistics {
  public:
    bool enabled;
    uint64_t num_base_arrays           = 0;
    uint64_t num_temp_arrays           = 0;
    uint64_t num_syncs                 = 0;
    uint64_t max_memory_usage          = 0;
    uint64_t totalwork                 = 0;
    uint64_t threading_below_threshold = 0;
    uint64_t kernel_cache_lookups      = 0;
    uint64_t kernel_cache_misses       = 0;
    uint64_t fuser_cache_lookups       = 0;
    uint64_t fuser_cache_misses        = 0;
    uint64_t num_instrs_into_fuser     = 0;
    uint64_t num_blocks_out_of_fuser   = 0;
    std::chrono::duration<double> time_total_execution{0};
    std::chrono::duration<double> time_pre_fusion{0};
    std::chrono::duration<double> time_fusion{0};
    std::chrono::duration<double> time_exec{0};
    std::chrono::duration<double> time_compile{0};
    std::chrono::duration<double> time_offload{0};
    std::chrono::duration<double> time_copy2dev{0};
    std::chrono::duration<double> time_copy2host{0};

    std::chrono::duration<double> wallclock{0};
    std::chrono::time_point<std::chrono::steady_clock> time_started{std::chrono::steady_clock::now()};

    Statistics(bool enabled) : enabled(enabled) {}

    void write(std::string backend_name, std::string filename, std::ostream &out) {
        if (filename == "") {
            pprint(backend_name, out);
        } else {
            export_yaml(backend_name, filename);
        }
    }

    // Pretty print the recorded statistics into 'out' where 'backend_name' is the name of the caller
    void pprint(std::string backend_name, std::ostream &out) {
        using namespace std;

        if (enabled) {
            wallclock = chrono::steady_clock::now() - time_started;

            out << BLU << "[" << backend_name << "] Profiling: \n" << RST;
            out << "Fuse cache hits:                 " << GRN << fuse_cache_hits()                   << "\n" << RST;
            out << "Kernel cache hits                " << GRN << kernel_cache_hits()                 << "\n" << RST;
            out << "Array contractions:              " << GRN << array_contractions()                << "\n" << RST;
            out << "Outer-fusion ratio:              " << GRN << outer_fusion_ratio()                << "\n" << RST;
            out << "\n";
            out << "Max memory usage:                " << GRN << memory_usage() << " MB"             << "\n" << RST;
            out << "Syncs to NumPy:                  " << GRN << num_syncs                           << "\n" << RST;
            out << "Total Work:                      " << GRN << totalwork << " operations"          << "\n" << RST;
            out << "Throughput:                      " << GRN << throughput() << "ops"               << "\n" << RST;
            out << "Work below par-threshold (1000): " << GRN << work_below_thredshold() << "%"      << "\n" << RST;
            out << "\n";
            out << "Wall clock:                      " << BLU << wallclock.count() << "s"            << "\n" << RST;
            out << "Total Execution:                 " << BLU << time_total_execution.count() << "s" << "\n" << RST;
            out << "  Pre-fusion:                    " << YEL << time_pre_fusion.count() << "s"      << "\n" << RST;
            out << "  Fusion:                        " << YEL << time_fusion.count() << "s"          << "\n" << RST;
            out << "  Compile:                       " << YEL << time_compile.count() << "s"         << "\n" << RST;
            out << "  Exec:                          " << YEL << time_exec.count() << "s"            << "\n" << RST;
            out << "  Copy2dev:                      " << YEL << time_copy2dev.count() << "s"        << "\n" << RST;
            out << "  Copy2host:                     " << YEL << time_copy2host.count() << "s"       << "\n" << RST;
            out << "  Offload:                       " << YEL << time_offload.count() << "s"         << "\n" << RST;
            out << "  Other:                         " << YEL << time_other() << "s"                 << "\n" << RST;
            out << "\n";
            out << BOLD << RED << "Unaccounted for (wall - total):  " << unaccounted() << "s\n" << RST;
            out << endl;
        }
    }

    // Export statistic using the YAML format <http://yaml.org>
    void export_yaml(std::string backend_name, std::string filename) {
        using namespace std;

        if (enabled) {
            wallclock = chrono::steady_clock::now() - time_started;

            ofstream file;
            file.open(filename);

            file << "----"                                                      << "\n";
            file << backend_name << ":"                                         << "\n";
            file << "  fuse_cache_hits: "       << fuse_cache_hits()            << "\n";
            file << "  kernel_cache_hits: "     << kernel_cache_hits()          << "\n";
            file << "  array_contractions: "    << array_contractions()         << "\n";
            file << "  outer_fusion_ratio: "    << outer_fusion_ratio()         << "\n";
            file << "  memory_usage: "          << memory_usage()               << "\n"; // mb
            file << "  syncs: "                 << num_syncs                    << "\n";
            file << "  total_work: "            << totalwork                    << "\n"; // ops
            file << "  throughput: "            << throughput()                 << "\n"; // ops
            file << "  work_below_thredshold: " << work_below_thredshold()      << "\n"; // %
            file << "  timing:"                                                 << "\n";
            file << "    wall_clock: "          << wallclock.count()            << "\n"; // s
            file << "    total_execution: "     << time_total_execution.count() << "\n"; // s
            file << "    pre_fusion: "          << time_pre_fusion.count()      << "\n"; // s
            file << "    fusion: "              << time_fusion.count()          << "\n"; // s
            file << "    compile: "             << time_compile.count()         << "\n"; // s
            file << "    exec: "                << time_exec.count()            << "\n"; // s
            file << "    copy2dev: "            << time_copy2dev.count()        << "\n"; // s
            file << "    copy2host: "           << time_copy2host.count()       << "\n"; // s
            file << "    offload: "             << time_offload.count()         << "\n"; // s
            file << "    other: "               << time_other()                 << "\n"; // s
            file << "    unaccounted: "         << unaccounted()                << "\n"; // s

            file.close();
        }
    }

    // Record statistics based on the 'instr_list'
    void record(std::vector<bh_instruction> &instr_list) {
        if (enabled) {
            for (const bh_instruction &instr: instr_list) {
                if (instr.opcode != BH_IDENTITY and not bh_opcode_is_system(instr.opcode)) {
                    const std::vector<int64_t> shape = instr.shape();
                    totalwork += bh_nelements(shape.size(), &shape[0]);
                }

                if (instr.opcode == BH_SYNC) {
                    ++num_syncs;
                }
            }
        }
    }

  private:
    std::string fuse_cache_hits() {
        return pprint_ratio(fuser_cache_lookups - fuser_cache_misses, fuser_cache_lookups);
    }

    std::string kernel_cache_hits() {
        return pprint_ratio(kernel_cache_lookups - kernel_cache_misses, kernel_cache_lookups);
    }

    std::string array_contractions() {
        return pprint_ratio(num_temp_arrays, num_base_arrays);
    }

    std::string outer_fusion_ratio() {
        return pprint_ratio(num_blocks_out_of_fuser, num_instrs_into_fuser);
    }

    double memory_usage() {
        return (double) max_memory_usage / 1024.0 / 1024.0;
    }

    double throughput() {
        return (double) totalwork / (double) wallclock.count();
    }

    double work_below_thredshold() {
        return (double) threading_below_threshold / (double) totalwork * 100.0;
    }

    double time_other() {
        std::chrono::duration<double> time_other{0};
        return (time_total_execution - time_pre_fusion - time_fusion - time_compile - time_exec  - time_copy2dev - time_copy2host - time_offload).count();
    }

    double unaccounted() {
        return (wallclock - time_total_execution).count();
    }
};

} // jitk
} // bohrium

#endif
<|endoftext|>