<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2015 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/gpu/trace_dump.h"

#include <gflags/gflags.h>

#include "third_party/stb/stb_image_write.h"
#include "xenia/base/logging.h"
#include "xenia/base/profiling.h"
#include "xenia/base/string.h"
#include "xenia/base/threading.h"
#include "xenia/gpu/command_processor.h"
#include "xenia/gpu/graphics_system.h"
#include "xenia/memory.h"
#include "xenia/ui/file_picker.h"
#include "xenia/ui/window.h"
#include "xenia/xbox.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#undef _CRT_SECURE_NO_WARNINGS
#undef _CRT_NONSTDC_NO_DEPRECATE
#include "third_party/stb/stb_image_write.h"

DEFINE_string(target_trace_file, "", "Specifies the trace file to load.");
DEFINE_string(trace_dump_path, "", "Output path for dumped files.");

namespace xe {
namespace gpu {

using namespace xe::gpu::xenos;

TraceDump::TraceDump() = default;

TraceDump::~TraceDump() = default;

int TraceDump::Main(const std::vector<std::wstring>& args) {
  // Grab path from the flag or unnamed argument.
  std::wstring path;
  if (!FLAGS_target_trace_file.empty()) {
    // Passed as a named argument.
    // TODO(benvanik): find something better than gflags that supports
    // unicode.
    path = xe::to_wstring(FLAGS_target_trace_file);
  } else if (args.size() >= 2) {
    // Passed as an unnamed argument.
    path = args[1];
  } else {
    // Open a file chooser and ask the user.
    auto file_picker = xe::ui::FilePicker::Create();
    file_picker->set_mode(ui::FilePicker::Mode::kOpen);
    file_picker->set_type(ui::FilePicker::Type::kFile);
    file_picker->set_multi_selection(false);
    file_picker->set_title(L"Select Trace File");
    file_picker->set_extensions({
        {L"Supported Files", L"*.xenia_gpu_trace"},
        {L"All Files (*.*)", L"*.*"},
    });
    if (file_picker->Show()) {
      auto selected_files = file_picker->selected_files();
      if (!selected_files.empty()) {
        path = selected_files[0];
      }
    }
  }

  if (path.empty()) {
    xe::FatalError("No trace file specified");
    return 1;
  }

  // Normalize the path and make absolute.
  auto abs_path = xe::to_absolute_path(path);
  XELOGI("Loading trace file %ls...", abs_path.c_str());

  if (!Setup()) {
    xe::FatalError("Unable to setup trace dump tool");
    return 1;
  }
  if (!Load(std::move(abs_path))) {
    xe::FatalError("Unable to load trace file; not found?");
    return 1;
  }

  // Root file name for outputs.
  base_output_path_ =
      xe::fix_path_separators(xe::to_wstring(FLAGS_trace_dump_path));
  base_output_path_ =
      xe::join_paths(base_output_path_,
                     xe::find_name_from_path(xe::fix_path_separators(path)));

  // Ensure output path exists.
  xe::filesystem::CreateParentFolder(base_output_path_);

  return Run();
}

bool TraceDump::Setup() {
  // Main display window.
  loop_ = ui::Loop::Create();
  window_ = xe::ui::Window::Create(loop_.get(), L"xenia-gpu-trace-dump");
  loop_->PostSynchronous([&]() {
    xe::threading::set_name("Win32 Loop");
    if (!window_->Initialize()) {
      xe::FatalError("Failed to initialize main window");
      return;
    }
  });
  window_->on_closed.AddListener([&](xe::ui::UIEvent* e) {
    loop_->Quit();
    XELOGI("User-initiated death!");
    exit(1);
  });
  loop_->on_quit.AddListener([&](xe::ui::UIEvent* e) { window_.reset(); });
  window_->Resize(1920, 1200);

  // Create the emulator but don't initialize so we can setup the window.
  emulator_ = std::make_unique<Emulator>(L"");
  X_STATUS result =
      emulator_->Setup(window_.get(), nullptr,
                       [this]() { return CreateGraphicsSystem(); }, nullptr);
  if (XFAILED(result)) {
    XELOGE("Failed to setup emulator: %.8X", result);
    return false;
  }
  memory_ = emulator_->memory();
  graphics_system_ = emulator_->graphics_system();

  window_->on_key_char.AddListener([&](xe::ui::KeyEvent* e) {
    if (e->key_code() == 0x74 /* VK_F5 */) {
      graphics_system_->ClearCaches();
      e->set_handled(true);
    }
  });

  player_ = std::make_unique<TracePlayer>(loop_.get(), graphics_system_);

  window_->on_painting.AddListener([&](xe::ui::UIEvent* e) {
    // Update titlebar status.
    auto file_name = xe::find_name_from_path(trace_file_path_);
    std::wstring title = std::wstring(L"Xenia GPU Trace Dump: ") + file_name;
    if (player_->is_playing_trace()) {
      int percent =
          static_cast<int>(player_->playback_percent() / 10000.0 * 100.0);
      title += xe::format_string(L" (%d%%)", percent);
    }
    window_->set_title(title);

    // Continuous paint.
    window_->Invalidate();
  });
  window_->Invalidate();

  return true;
}

bool TraceDump::Load(std::wstring trace_file_path) {
  trace_file_path_ = std::move(trace_file_path);

  if (!player_->Open(trace_file_path_)) {
    XELOGE("Could not load trace file");
    return false;
  }

  return true;
}

int TraceDump::Run() {
  loop_->Post([&]() {
    player_->SeekFrame(0);
    player_->SeekCommand(
        static_cast<int>(player_->current_frame()->commands.size() - 1));
  });
  player_->WaitOnPlayback();

  loop_->PostSynchronous([&]() {
    // Breathe.
  });
  loop_->PostSynchronous([&]() {
    // Breathe.
  });

  xe::threading::Fence capture_fence;
  int result = 0;
  loop_->PostDelayed(
      [&]() {
        // Capture.
        auto raw_image = graphics_system_->Capture();
        if (!raw_image) {
          // Failed to capture anything.
          result = -1;
          capture_fence.Signal();
          return;
        }

        // Save framebuffer png.
        std::string png_path = xe::to_string(base_output_path_ + L".png");
        stbi_write_png(png_path.c_str(), static_cast<int>(raw_image->width),
                       static_cast<int>(raw_image->height), 4,
                       raw_image->data.data(),
                       static_cast<int>(raw_image->stride));

        result = 0;
        capture_fence.Signal();
      },
      50);

  capture_fence.Wait();

  // Wait until we are exited.
  loop_->Quit();
  loop_->AwaitQuit();

  Profiler::Shutdown();
  window_.reset();
  loop_.reset();
  player_.reset();
  emulator_.reset();

  return result;
}

}  //  namespace gpu
}  //  namespace xe
<commit_msg>[GPU] Accept input and output path as command line parameters<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2015 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/gpu/trace_dump.h"

#include <gflags/gflags.h>

#include "third_party/stb/stb_image_write.h"
#include "xenia/base/logging.h"
#include "xenia/base/profiling.h"
#include "xenia/base/string.h"
#include "xenia/base/threading.h"
#include "xenia/gpu/command_processor.h"
#include "xenia/gpu/graphics_system.h"
#include "xenia/memory.h"
#include "xenia/ui/file_picker.h"
#include "xenia/ui/window.h"
#include "xenia/xbox.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#undef _CRT_SECURE_NO_WARNINGS
#undef _CRT_NONSTDC_NO_DEPRECATE
#include "third_party/stb/stb_image_write.h"

DEFINE_string(target_trace_file, "", "Specifies the trace file to load.");
DEFINE_string(trace_dump_path, "", "Output path for dumped files.");

namespace xe {
namespace gpu {

using namespace xe::gpu::xenos;

TraceDump::TraceDump() = default;

TraceDump::~TraceDump() = default;

int TraceDump::Main(const std::vector<std::wstring>& args) {
  // Grab path from the flag or unnamed argument.
  std::wstring path;
  std::wstring output_path;
  if (!FLAGS_target_trace_file.empty()) {
    // Passed as a named argument.
    // TODO(benvanik): find something better than gflags that supports
    // unicode.
    path = xe::to_wstring(FLAGS_target_trace_file);
  } else if (args.size() >= 2) {
    // Passed as an unnamed argument.
    path = args[1];

    if (args.size() >= 3) {
      output_path = args[2];
    }
  } else {
    // Open a file chooser and ask the user.
    auto file_picker = xe::ui::FilePicker::Create();
    file_picker->set_mode(ui::FilePicker::Mode::kOpen);
    file_picker->set_type(ui::FilePicker::Type::kFile);
    file_picker->set_multi_selection(false);
    file_picker->set_title(L"Select Trace File");
    file_picker->set_extensions({
        {L"Supported Files", L"*.xenia_gpu_trace"},
        {L"All Files (*.*)", L"*.*"},
    });
    if (file_picker->Show()) {
      auto selected_files = file_picker->selected_files();
      if (!selected_files.empty()) {
        path = selected_files[0];
      }
    }
  }

  if (path.empty()) {
    xe::FatalError("No trace file specified");
    return 1;
  }

  // Normalize the path and make absolute.
  auto abs_path = xe::to_absolute_path(path);
  XELOGI("Loading trace file %ls...", abs_path.c_str());

  if (!Setup()) {
    xe::FatalError("Unable to setup trace dump tool");
    return 1;
  }
  if (!Load(std::move(abs_path))) {
    xe::FatalError("Unable to load trace file; not found?");
    return 1;
  }

  // Root file name for outputs.
  if (output_path.empty()) {
    base_output_path_ =
        xe::fix_path_separators(xe::to_wstring(FLAGS_trace_dump_path));
    base_output_path_ =
        xe::join_paths(base_output_path_,
                       xe::find_name_from_path(xe::fix_path_separators(path)));
  } else {
    base_output_path_ = xe::fix_path_separators(output_path);
  }

  // Ensure output path exists.
  xe::filesystem::CreateParentFolder(base_output_path_);

  return Run();
}

bool TraceDump::Setup() {
  // Main display window.
  loop_ = ui::Loop::Create();
  window_ = xe::ui::Window::Create(loop_.get(), L"xenia-gpu-trace-dump");
  loop_->PostSynchronous([&]() {
    xe::threading::set_name("Win32 Loop");
    if (!window_->Initialize()) {
      xe::FatalError("Failed to initialize main window");
      return;
    }
  });
  window_->on_closed.AddListener([&](xe::ui::UIEvent* e) {
    loop_->Quit();
    XELOGI("User-initiated death!");
    exit(1);
  });
  loop_->on_quit.AddListener([&](xe::ui::UIEvent* e) { window_.reset(); });
  window_->Resize(1920, 1200);

  // Create the emulator but don't initialize so we can setup the window.
  emulator_ = std::make_unique<Emulator>(L"");
  X_STATUS result =
      emulator_->Setup(window_.get(), nullptr,
                       [this]() { return CreateGraphicsSystem(); }, nullptr);
  if (XFAILED(result)) {
    XELOGE("Failed to setup emulator: %.8X", result);
    return false;
  }
  memory_ = emulator_->memory();
  graphics_system_ = emulator_->graphics_system();

  window_->on_key_char.AddListener([&](xe::ui::KeyEvent* e) {
    if (e->key_code() == 0x74 /* VK_F5 */) {
      graphics_system_->ClearCaches();
      e->set_handled(true);
    }
  });

  player_ = std::make_unique<TracePlayer>(loop_.get(), graphics_system_);

  window_->on_painting.AddListener([&](xe::ui::UIEvent* e) {
    // Update titlebar status.
    auto file_name = xe::find_name_from_path(trace_file_path_);
    std::wstring title = std::wstring(L"Xenia GPU Trace Dump: ") + file_name;
    if (player_->is_playing_trace()) {
      int percent =
          static_cast<int>(player_->playback_percent() / 10000.0 * 100.0);
      title += xe::format_string(L" (%d%%)", percent);
    }
    window_->set_title(title);

    // Continuous paint.
    window_->Invalidate();
  });
  window_->Invalidate();

  return true;
}

bool TraceDump::Load(std::wstring trace_file_path) {
  trace_file_path_ = std::move(trace_file_path);

  if (!player_->Open(trace_file_path_)) {
    XELOGE("Could not load trace file");
    return false;
  }

  return true;
}

int TraceDump::Run() {
  loop_->Post([&]() {
    player_->SeekFrame(0);
    player_->SeekCommand(
        static_cast<int>(player_->current_frame()->commands.size() - 1));
  });
  player_->WaitOnPlayback();

  loop_->PostSynchronous([&]() {
    // Breathe.
  });
  loop_->PostSynchronous([&]() {
    // Breathe.
  });

  xe::threading::Fence capture_fence;
  int result = 0;
  loop_->PostDelayed(
      [&]() {
        // Capture.
        auto raw_image = graphics_system_->Capture();
        if (!raw_image) {
          // Failed to capture anything.
          result = -1;
          capture_fence.Signal();
          return;
        }

        // Save framebuffer png.
        std::string png_path = xe::to_string(base_output_path_ + L".png");
        stbi_write_png(png_path.c_str(), static_cast<int>(raw_image->width),
                       static_cast<int>(raw_image->height), 4,
                       raw_image->data.data(),
                       static_cast<int>(raw_image->stride));

        result = 0;
        capture_fence.Signal();
      },
      50);

  capture_fence.Wait();

  // Wait until we are exited.
  loop_->Quit();
  loop_->AwaitQuit();

  Profiler::Shutdown();
  window_.reset();
  loop_.reset();
  player_.reset();
  emulator_.reset();

  return result;
}

}  //  namespace gpu
}  //  namespace xe
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//  mos6502.cc
//------------------------------------------------------------------------------
#include "mos6502.h"
#include "yakc/core/system_bus.h"

namespace YAKC {

//------------------------------------------------------------------------------
//  address mode table
//
uint8_t mos_6502::addr_modes[4][8][8] = {
    // cc = 00
    {
        //---    BIT    JMP    JMP()  STY    LDY    CPY    CPX
        { A____, A____, A____, A____, A____, A_IMM, A_IMM, A_IMM },
        { A____, A_ZER, A____, A____, A_ZER, A_ZER, A_ZER, A_ZER },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A_ZPX, A_ZPY, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A_ABX, A____, A____ },
    },
    // cc = 01
    {
        //ORA    AND    EOR    ADC    STA    LDA    CMP    SBC
        { A_IDX, A_IDX, A_IDX, A_IDX, A_IDX, A_IDX, A_IDX, A_IDX },
        { A_ZER, A_ZER, A_ZER, A_ZER, A_ZER, A_ZER, A_ZER, A_ZER },
        { A_IMM, A_IMM, A_IMM, A_IMM, A____, A_IMM, A_IMM, A_IMM },
        { A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS },
        { A_IDY, A_IDY, A_IDY, A_IDY, A_IDY, A_IDY, A_IDY, A_IDY },
        { A_ZPX, A_ZPX, A_ZPX, A_ZPX, A_ZPX, A_ZPX, A_ZPX, A_ZPX },
        { A_ABY, A_ABY, A_ABY, A_ABY, A_ABY, A_ABY, A_ABY, A_ABY },
        { A_ABX, A_ABX, A_ABX, A_ABX, A_ABX, A_ABX, A_ABX, A_ABX },
    }
    // cc = 02
    {
        //ASL    ROL    LSR    ROR    STX    LDX    DEC    INC
        { A____, A____, A____, A____, A____, A_IMM, A____, A____ },
        { A_ZER, A_ZER, A_ZER, A_ZER, A_ZER, A_ZER, A_ZER, A_ZER },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A_ZPX, A_ZPX, A_ZPX, A_ZPX, A_ZPY, A_ZPY, A_ZPX, A_ZPX },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A_ABX, A_ABX, A_ABX, A_ABX, A____, A_ABY, A_ABX, A_ABX },
    }
    // cc = 03
    {
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
    },
};

//------------------------------------------------------------------------------
mos6502::mos6502() {
    this->init();
}

//------------------------------------------------------------------------------
void
mos6502::init() {
    A = 0; X = 0; Y = 0; S = 0; P = XF; PC = 0;
    OP = 0;
    RW = true;
    Cycle = 0;
    FetchReady = true;
    AddrReady = false;
    ExecReady = false;
    AddrMode = A____;
    AddrStep = 0;
}

//------------------------------------------------------------------------------
void
mos6502::reset() {
    P = (IF | XF);
    S = 0xFD;
    PC = mem.r16(0xFFFC);
    RW = true;
    Cycle = 0;
    FetchReady = true;
    AddrReady = false;
    ExecReady = false;
    AddrMode = A____;
    AddrStep = 0;
}

//------------------------------------------------------------------------------
void
mos6502::step(system_bus* bus) {
    // FIXME: Decode overlaps with Execute from the last instruction
    if (FetchReady) {
        step_fetch(bus);
    }
    if (AddReady) {
        step_addr(bus);
    }
    if (ExecReady) {
        step_exec(bus);
    }
    Cycle++;
}

//------------------------------------------------------------------------------
void
mos6502::step_fetch() {
    // fetch next instruction byte
    ADDR = PC++;
    OP = mem.r8(ADDR);

    // decode:
    //  - determine addressing mode
    //  - determine load/store
    uint8_t cc  = OP & 0x03;
    uint8_t bbb = (OP >> 2) & 0x07;
    uint8_t aaa = (OP >> 5) & 0x07;
    AddrMode = addr_modes[cc][bbb][aaa];
    AddrReady = true;
    FetchReady = false;
    ExecReady = false;
    Cycle = 0;
}

//------------------------------------------------------------------------------
void
mos6502::step_exec() {
    FetchReady = true;
}

//------------------------------------------------------------------------------
void
mos6502::step_addr() {
    if (Cycle > 0) {
        switch (AddrMode) {
            case A_IMM: this->step_addr_imm(); break;
            case A_ZER: this->step_addr_zer(); break;
            case A_ZPX: this->step_addr_zpx(); break;
            case A_ZPY: this->step_addr_zpy(); break;
            case A_ABS: this->step_addr_abs(); break;
            case A_ABX: this->step_addr_abx(); break;
            case A_ABY: this->step_addr_aby(); break;
            case A_IDX: this->step_addr_idx(); break;
            case A_IDY: this->step_addr_idy(); break;
            default: ExecReady = true; break;
        }
        DATA = mem.r8(ADDR);
    }
}

//------------------------------------------------------------------------------
void
mos6502::step_addr_imm() {
    ADDR = PC++;
    ExecReady = true;
}

//------------------------------------------------------------------------------
void
mos6502::step_addr_zer() {
    switch (AddrCycle) {
        case 1: ADDR = PC++; break;
        case 2: ADDR = DATA; ExecReady = true; break;
    }
}

//------------------------------------------------------------------------------
void
mos6502::step_addr_zpx() {
    switch (AddrCycle) {
        case 1: ADDR = PC++; break;
        case 2: ADDR = DATA; break;
        case 3: ADDR = (ADDR + X) & 0x00FF; ExecReady = true; break;
    }
}

//------------------------------------------------------------------------------
void
mos6502::step_addr_zpy() {
    switch (AddrCycle) {
        case 1: ADDR = PC++; break;
        case 2: ADDR = DATA; break;
        case 3: ADDR = (ADDR + Y) & 0x00FF; ExecReady = true; break;
    }
}

//------------------------------------------------------------------------------
void
mos6502::step_addr_abs() {
    switch (AddrCycle) {
        case 1: ADDR = PC++; break;
        case 2: tmp = DATA; ADDR = PC++; break;
        case 3: ADDR = DATA<<8 | tmp; ExecReady = true; break;
    }
}

//------------------------------------------------------------------------------
void
mos6502::step_abx() {
    switch (AddrCycle) {
        case 1: ADDR = PC++; break;
        case 2: tmp = DATA + X; ADDR = PC++; break;
        case 3:
            ADDR = (DATA<<8) | (tmp&0xFF);
            if ((tmp & 0xFF00) == 0x00) {
                // page boundary not crossed, can exit early
                ExecReady = true;
            }
            break;
        case 4:
            // only arrives here if page boundary was crossed
            ADDR = (DATA<<8) + tmp;
            ExecReady = true;
            break;
    }
}

} // namespace YAKC
<commit_msg>some more minor 6502 fixes<commit_after>//------------------------------------------------------------------------------
//  mos6502.cc
//------------------------------------------------------------------------------
#include "mos6502.h"
#include "yakc/core/system_bus.h"

namespace YAKC {

//------------------------------------------------------------------------------
//  address mode table
//
uint8_t mos_6502::addr_modes[4][8][8] = {
    // cc = 00
    {
        //---    BIT    JMP    JMP()  STY    LDY    CPY    CPX
        { A____, A____, A____, A____, A____, A_IMM, A_IMM, A_IMM },
        { A____, A_ZER, A____, A____, A_ZER, A_ZER, A_ZER, A_ZER },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A_ZPX, A_ZPY, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A_ABX, A____, A____ },
    },
    // cc = 01
    {
        //ORA    AND    EOR    ADC    STA    LDA    CMP    SBC
        { A_IDX, A_IDX, A_IDX, A_IDX, A_IDX, A_IDX, A_IDX, A_IDX },
        { A_ZER, A_ZER, A_ZER, A_ZER, A_ZER, A_ZER, A_ZER, A_ZER },
        { A_IMM, A_IMM, A_IMM, A_IMM, A____, A_IMM, A_IMM, A_IMM },
        { A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS },
        { A_IDY, A_IDY, A_IDY, A_IDY, A_IDY, A_IDY, A_IDY, A_IDY },
        { A_ZPX, A_ZPX, A_ZPX, A_ZPX, A_ZPX, A_ZPX, A_ZPX, A_ZPX },
        { A_ABY, A_ABY, A_ABY, A_ABY, A_ABY, A_ABY, A_ABY, A_ABY },
        { A_ABX, A_ABX, A_ABX, A_ABX, A_ABX, A_ABX, A_ABX, A_ABX },
    }
    // cc = 02
    {
        //ASL    ROL    LSR    ROR    STX    LDX    DEC    INC
        { A____, A____, A____, A____, A____, A_IMM, A____, A____ },
        { A_ZER, A_ZER, A_ZER, A_ZER, A_ZER, A_ZER, A_ZER, A_ZER },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS, A_ABS },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A_ZPX, A_ZPX, A_ZPX, A_ZPX, A_ZPY, A_ZPY, A_ZPX, A_ZPX },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A_ABX, A_ABX, A_ABX, A_ABX, A____, A_ABY, A_ABX, A_ABX },
    }
    // cc = 03
    {
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
        { A____, A____, A____, A____, A____, A____, A____, A____ },
    },
};

//------------------------------------------------------------------------------
mos6502::mos6502() {
    this->init();
}

//------------------------------------------------------------------------------
void
mos6502::init() {
    A = 0; X = 0; Y = 0; S = 0; P = XF; PC = 0;
    OP = 0;
    RW = true;
    Cycle = 0;
    FetchReady = true;
    AddrReady = false;
    ExecReady = false;
    AddrMode = A____;
    AddrStep = 0;
}

//------------------------------------------------------------------------------
void
mos6502::reset() {
    P = (IF | XF);
    S = 0xFD;
    PC = mem.r16(0xFFFC);
    RW = true;
    Cycle = 0;
    FetchReady = true;
    AddrReady = false;
    ExecReady = false;
    AddrMode = A____;
    AddrStep = 0;
}

//------------------------------------------------------------------------------
void
mos6502::step(system_bus* bus) {
    // FIXME: Decode overlaps with Execute from the last instruction
    if (FetchReady) {
        step_fetch(bus);
    }
    if (AddReady) {
        step_addr(bus);
    }
    if (ExecReady) {
        step_exec(bus);
    }
    Cycle++;
}

//------------------------------------------------------------------------------
void
mos6502::step_fetch() {
    // fetch next instruction byte
    ADDR = PC++;
    OP = mem.r8(ADDR);

    // decode:
    //  - determine addressing mode
    //  - determine load/store
    uint8_t cc  = OP & 0x03;
    uint8_t bbb = (OP >> 2) & 0x07;
    uint8_t aaa = (OP >> 5) & 0x07;
    AddrMode = addr_modes[cc][bbb][aaa];
    AddrReady = true;
    FetchReady = false;
    ExecReady = false;
    Cycle = 0;
}

//------------------------------------------------------------------------------
void
mos6502::step_exec() {
    FetchReady = true;
}

//------------------------------------------------------------------------------
void
mos6502::step_addr() {
    if (Cycle > 0) {
        switch (AddrMode) {
            case A_IMM: this->step_addr_imm(); break;
            case A_ZER: this->step_addr_zer(); break;
            case A_ZPX: this->step_addr_zpx(); break;
            case A_ZPY: this->step_addr_zpy(); break;
            case A_ABS: this->step_addr_abs(); break;
            case A_ABX: this->step_addr_abx(); break;
            case A_ABY: this->step_addr_aby(); break;
            case A_IDX: this->step_addr_idx(); break;
            case A_IDY: this->step_addr_idy(); break;
            default: ExecReady = true; break;
        }
        DATA = mem.r8(ADDR);
    }
}

//------------------------------------------------------------------------------
void
mos6502::step_addr_imm() {
    ADDR = PC++;
    ExecReady = true;
}

//------------------------------------------------------------------------------
void
mos6502::step_addr_zer() {
    switch (Cycle) {
        case 1: ADDR = PC++; break;
        case 2: ADDR = DATA; ExecReady = true; break;
    }
}

//------------------------------------------------------------------------------
void
mos6502::step_addr_zpx() {
    switch (Cycle) {
        case 1: ADDR = PC++; break;
        case 2: ADDR = DATA; break;
        case 3: ADDR = (DATA + X) & 0x00FF; ExecReady = true; break;
    }
}

//------------------------------------------------------------------------------
void
mos6502::step_addr_zpy() {
    switch (Cycle) {
        case 1: ADDR = PC++; break;
        case 2: ADDR = DATA; break;
        case 3: ADDR = (ADDR + Y) & 0x00FF; ExecReady = true; break;
    }
}

//------------------------------------------------------------------------------
void
mos6502::step_addr_abs() {
    switch (Cycle) {
        case 1: ADDR = PC++; break;
        case 2: tmp = DATA; ADDR = PC++; break;
        case 3: ADDR = DATA<<8 | tmp; ExecReady = true; break;
    }
}

//------------------------------------------------------------------------------
void
mos6502::step_abx() {
    switch (Cycle) {
        case 1: ADDR = PC++; break;
        case 2: tmp = DATA + X; ADDR = PC++; break;
        case 3:
            // first read from within current page
            ADDR = (DATA<<8) | (tmp&0xFF);
            if ((tmp & 0xFF00) == 0x00) {
                // page boundary not crossed, can exit early
                ExecReady = true;
            }
            break;
        case 4:
            // only arrives here if page boundary was crossed
            ADDR = (DATA<<8) + tmp;
            ExecReady = true;
            break;
    }
}

} // namespace YAKC
<|endoftext|>


<commit_before>/**
 * Clever programming language
 * Copyright (c) 2011-2012 Clever Team
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <map>
#include <string>

#ifndef __APPLE__
# include <ffi.h>
#else
# include <ffi/ffi.h>
#endif

#ifdef CLEVER_WIN32
# include <windows.h>
#else
# include <dlfcn.h>
#endif

#include "modules/std/ffi/ffiobject.h"
#include "modules/std/ffi/ffi.h"
#include "types/nativetypes.h"

namespace clever { namespace packages { namespace std { namespace ffi {

extern "C" {
	typedef void (*ffi_call_func)();
}

#ifndef CLEVER_WIN32
	ExtMap ext_mod_map;
#endif

#if defined(CLEVER_WIN32)
	const char* CLEVER_DYLIB_EXT = ".dll";
#elif defined(CLEVER_APPLE)
	const char* CLEVER_DYLIB_EXT = ".dylib";
#else
	const char* CLEVER_DYLIB_EXT = ".so";
#endif

ffi_type* find_ffi_type(const char* tn) {
	switch (tn[0]) {
		case 'i': return &ffi_type_sint32;
		case 'd': return &ffi_type_double;
		case 'b': return &ffi_type_schar;
		case 's': return &ffi_type_pointer;
		case 'c': return &ffi_type_schar;
		case 'v': return &ffi_type_void;
		case 'p': return &ffi_type_pointer;
	}
	return NULL;
}

/**
 * call_ext_func(..., str function_name, str library_name)
 * Returns call an external function
 */
static CLEVER_FUNCTION(call_ext_func) {
	size_t size = CLEVER_NUM_ARGS();
	size_t n_args = size - 3;

	::std::string lib = CLEVER_ARG_STR(size-3);
	::std::string rt = CLEVER_ARG_STR(size-2);
	::std::string func = CLEVER_ARG_STR(size-1);

#ifndef CLEVER_WIN32
	void* fpf;
	ffi_call_func pf;

	ExtMap::iterator it = ext_mod_map.find(lib),
		end = ext_mod_map.end();

	if (it == end) {
		::std::string libname = ::std::string("./") + lib + CLEVER_DYLIB_EXT;
		void* m = ext_mod_map[lib] = dlopen(libname.c_str(), 1);

		if (m == NULL) {
			::std::fprintf(stderr,"[FFI] Shared library %s don't found!\n",libname.c_str());
			CLEVER_RETURN_BOOL(false);
			return;
		}
		it=ext_mod_map.find(lib);
	}

	fpf = dlsym(it->second, func.c_str());

	if (fpf == NULL) {
		::std::fprintf(stderr,"[FFI] function %s don't found at %s!\n",func.c_str(),lib.c_str());
		CLEVER_RETURN_BOOL(false);
		return;
	}

	pf = reinterpret_cast<ffi_call_func>(fpf);
#endif

	ffi_cif cif;

	ffi_type* ffi_rt = find_ffi_type(rt.c_str());
	ffi_type** ffi_args = (ffi_type**) malloc(n_args*sizeof(ffi_type*));

	void** ffi_values = (void**) malloc(n_args*sizeof(void*));

	for (size_t i = 0; i < n_args; ++i) {
		if (CLEVER_ARG_IS_INT(i)) {
			ffi_args[i] = &ffi_type_sint32;

			int* vi= (int*) malloc(sizeof(int));

			*vi = CLEVER_ARG_INT(i);

			ffi_values[i] =  vi;
		} else if (CLEVER_ARG_IS_BOOL(i)) {
			ffi_args[i] = find_ffi_type("b");

			char* b=(char*) malloc (sizeof(char));

			*b = CLEVER_ARG_BOOL(i);

			ffi_values[i] = b;
		} else if (CLEVER_ARG_IS_STR(i)) {
			const char* st = CLEVER_ARG_STR(i).c_str();

			char** s= (char**) malloc (sizeof(char*));
			*s = (char*) malloc (sizeof(char)* (strlen(st)+1));

			strcpy(*s,st);
			(*s)[strlen(st)]='\0';

			ffi_args[i] = find_ffi_type("s");

			ffi_values[i] =  s;
		} else if (CLEVER_ARG_IS_BYTE(i)) {
			ffi_args[i] = find_ffi_type("c");

			char* b = (char*) malloc (sizeof(char));
			*b = CLEVER_ARG_BYTE(i);

			ffi_values[i] = b;
		} else if (CLEVER_ARG_IS_DOUBLE(i)) {
			ffi_args[i] = &ffi_type_double;

			double* d = (double*)malloc(sizeof(double));
			*d = CLEVER_ARG_DOUBLE(i);
			ffi_values[i] = d;
		} else if ( CLEVER_ARG_IS_USER(i) ) {
			ffi_args[i] = find_ffi_type("p");

			FFIObjectValue* obj = static_cast<FFIObjectValue*>(CLEVER_ARG_DATA_VALUE(i));

			ffi_values[i] = &obj->pointer;
		}
	}

	if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, n_args, ffi_rt, ffi_args) != FFI_OK) {
		 CLEVER_RETURN_BOOL(false);
	}

#ifndef CLEVER_WIN32

	if (rt[0] == 'i') {
		int vi;

		ffi_call(&cif, pf, &vi, ffi_values);

		CLEVER_RETURN_INT(vi);
	} else if (rt[0] == 'd') {
		double vd;

		ffi_call(&cif, pf, &vd, ffi_values);

		CLEVER_RETURN_DOUBLE(vd);
	} else if (rt[0] == 'b') {
		bool vb;

		ffi_call(&cif, pf, &vb, ffi_values);

		CLEVER_RETURN_BOOL(vb);
	} else if (rt[0] == 's') {
		char* vs[1];
		vs[0]=0;

		ffi_call(&cif, pf, &vs, ffi_values);

		CLEVER_RETURN_STR(CSTRING(*vs));
	} else if (rt[0] == 'c') {
		char vc;

		ffi_call(&cif, pf, &vc, ffi_values);

		CLEVER_RETURN_BYTE(vc);
	} else if (rt[0] == 'v') {

		ffi_call(&cif, pf, NULL, ffi_values);

		CLEVER_RETURN_BOOL(true);
	} else if (rt[0] == 'p') {
		FFIObjectValue* x = new FFIObjectValue();

		ffi_call(&cif, pf, &(x->pointer), ffi_values);

		CLEVER_RETURN_DATA_VALUE(x);
	} else {
		CLEVER_RETURN_BOOL(true);
	}

#endif

	for (size_t i = 0; i < n_args; ++i) {
		if (CLEVER_ARG_IS_INT(i)) {
			free((int*)ffi_values[i]);
		} else if (CLEVER_ARG_IS_BOOL(i)) {
			free((char*)ffi_values[i]);
		} else if (CLEVER_ARG_IS_STR(i)) {
			char** v=(char**)ffi_values[i];
			free(v[0]);
			free(v);
		} else if (CLEVER_ARG_IS_BYTE(i)) {
			free((char*)ffi_values[i]);
		} else if (CLEVER_ARG_IS_DOUBLE(i)) {
			free((double*)ffi_values[i]);
		} else if (CLEVER_ARG_IS_USER(i)) {
		}
	}

	free(ffi_args);
	free(ffi_values);
}

} // ffi

/**
 * Load module data
 */
void FFI::init() {

	Class* FFIObject = new ffi::FFIObject();

	addClass(FFIObject);

	addFunction(new Function("call_ext_func", &CLEVER_NS_FNAME(ffi, call_ext_func), CLEVER_BOOL))
		->setVariadic()
		->setMinNumArgs(2);
}

FFI::~FFI() {
	ExtMap::const_iterator it = ffi::ext_mod_map.begin(),
		end = ffi::ext_mod_map.end();

	while (it != end) {
		if (it->second != NULL) dlclose(it->second);
		++it;
	}
}

}}} // clever::packages::std
<commit_msg>Using clever_fatal to FFI error messages<commit_after>/**
 * Clever programming language
 * Copyright (c) 2011-2012 Clever Team
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <map>
#include <string>

#ifndef __APPLE__
# include <ffi.h>
#else
# include <ffi/ffi.h>
#endif

#ifdef CLEVER_WIN32
# include <windows.h>
#else
# include <dlfcn.h>
#endif

#include "modules/std/ffi/ffiobject.h"
#include "modules/std/ffi/ffi.h"
#include "types/nativetypes.h"

namespace clever { namespace packages { namespace std { namespace ffi {

extern "C" {
	typedef void (*ffi_call_func)();
}

#ifndef CLEVER_WIN32
	ExtMap ext_mod_map;
#endif

#if defined(CLEVER_WIN32)
	const char* CLEVER_DYLIB_EXT = ".dll";
#elif defined(CLEVER_APPLE)
	const char* CLEVER_DYLIB_EXT = ".dylib";
#else
	const char* CLEVER_DYLIB_EXT = ".so";
#endif

ffi_type* find_ffi_type(const char* tn) {
	switch (tn[0]) {
		case 'i': return &ffi_type_sint32;
		case 'd': return &ffi_type_double;
		case 'b': return &ffi_type_schar;
		case 's': return &ffi_type_pointer;
		case 'c': return &ffi_type_schar;
		case 'v': return &ffi_type_void;
		case 'p': return &ffi_type_pointer;
	}
	return NULL;
}

/**
 * call_ext_func(..., str function_name, str library_name)
 * Returns call an external function
 */
static CLEVER_FUNCTION(call_ext_func) {
	size_t size = CLEVER_NUM_ARGS();
	size_t n_args = size - 3;

	::std::string lib = CLEVER_ARG_STR(size-3);
	::std::string rt = CLEVER_ARG_STR(size-2);
	::std::string func = CLEVER_ARG_STR(size-1);

#ifndef CLEVER_WIN32
	void* fpf;
	ffi_call_func pf;

	ExtMap::iterator it = ext_mod_map.find(lib),
		end = ext_mod_map.end();

	if (it == end) {
		::std::string libname = ::std::string("./") + lib + CLEVER_DYLIB_EXT;
		void* m = ext_mod_map[lib] = dlopen(libname.c_str(), 1);

		if (m == NULL) {
			clever_fatal("[FFI] Shared library`%S' not found!", &CLEVER_ARG_STR(size-3));
			CLEVER_RETURN_BOOL(false);
			return;
		}
		it=ext_mod_map.find(lib);
	}

	fpf = dlsym(it->second, func.c_str());

	if (fpf == NULL) {
		clever_fatal("[FFI] function`%S' not found at `%S'!", &CLEVER_ARG_STR(size-1),&CLEVER_ARG_STR(size-3));
		CLEVER_RETURN_BOOL(false);
		return;
	}

	pf = reinterpret_cast<ffi_call_func>(fpf);
#endif

	ffi_cif cif;

	ffi_type* ffi_rt = find_ffi_type(rt.c_str());
	ffi_type** ffi_args = (ffi_type**) malloc(n_args*sizeof(ffi_type*));

	void** ffi_values = (void**) malloc(n_args*sizeof(void*));

	for (size_t i = 0; i < n_args; ++i) {
		if (CLEVER_ARG_IS_INT(i)) {
			ffi_args[i] = &ffi_type_sint32;

			int* vi= (int*) malloc(sizeof(int));

			*vi = CLEVER_ARG_INT(i);

			ffi_values[i] =  vi;
		} else if (CLEVER_ARG_IS_BOOL(i)) {
			ffi_args[i] = find_ffi_type("b");

			char* b=(char*) malloc (sizeof(char));

			*b = CLEVER_ARG_BOOL(i);

			ffi_values[i] = b;
		} else if (CLEVER_ARG_IS_STR(i)) {
			const char* st = CLEVER_ARG_STR(i).c_str();

			char** s= (char**) malloc (sizeof(char*));
			*s = (char*) malloc (sizeof(char)* (strlen(st)+1));

			strcpy(*s,st);
			(*s)[strlen(st)]='\0';

			ffi_args[i] = find_ffi_type("s");

			ffi_values[i] =  s;
		} else if (CLEVER_ARG_IS_BYTE(i)) {
			ffi_args[i] = find_ffi_type("c");

			char* b = (char*) malloc (sizeof(char));
			*b = CLEVER_ARG_BYTE(i);

			ffi_values[i] = b;
		} else if (CLEVER_ARG_IS_DOUBLE(i)) {
			ffi_args[i] = &ffi_type_double;

			double* d = (double*)malloc(sizeof(double));
			*d = CLEVER_ARG_DOUBLE(i);
			ffi_values[i] = d;
		} else if ( CLEVER_ARG_IS_USER(i) ) {
			ffi_args[i] = find_ffi_type("p");

			FFIObjectValue* obj = static_cast<FFIObjectValue*>(CLEVER_ARG_DATA_VALUE(i));

			ffi_values[i] = &obj->pointer;
		}
	}

	if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, n_args, ffi_rt, ffi_args) != FFI_OK) {
		 CLEVER_RETURN_BOOL(false);
	}

#ifndef CLEVER_WIN32

	if (rt[0] == 'i') {
		int vi;

		ffi_call(&cif, pf, &vi, ffi_values);

		CLEVER_RETURN_INT(vi);
	} else if (rt[0] == 'd') {
		double vd;

		ffi_call(&cif, pf, &vd, ffi_values);

		CLEVER_RETURN_DOUBLE(vd);
	} else if (rt[0] == 'b') {
		bool vb;

		ffi_call(&cif, pf, &vb, ffi_values);

		CLEVER_RETURN_BOOL(vb);
	} else if (rt[0] == 's') {
		char* vs[1];
		vs[0]=0;

		ffi_call(&cif, pf, &vs, ffi_values);

		CLEVER_RETURN_STR(CSTRING(*vs));
	} else if (rt[0] == 'c') {
		char vc;

		ffi_call(&cif, pf, &vc, ffi_values);

		CLEVER_RETURN_BYTE(vc);
	} else if (rt[0] == 'v') {

		ffi_call(&cif, pf, NULL, ffi_values);

		CLEVER_RETURN_BOOL(true);
	} else if (rt[0] == 'p') {
		FFIObjectValue* x = new FFIObjectValue();

		ffi_call(&cif, pf, &(x->pointer), ffi_values);

		CLEVER_RETURN_DATA_VALUE(x);
	} else {
		CLEVER_RETURN_BOOL(true);
	}

#endif

	for (size_t i = 0; i < n_args; ++i) {
		if (CLEVER_ARG_IS_INT(i)) {
			free((int*)ffi_values[i]);
		} else if (CLEVER_ARG_IS_BOOL(i)) {
			free((char*)ffi_values[i]);
		} else if (CLEVER_ARG_IS_STR(i)) {
			char** v=(char**)ffi_values[i];
			free(v[0]);
			free(v);
		} else if (CLEVER_ARG_IS_BYTE(i)) {
			free((char*)ffi_values[i]);
		} else if (CLEVER_ARG_IS_DOUBLE(i)) {
			free((double*)ffi_values[i]);
		} else if (CLEVER_ARG_IS_USER(i)) {
		}
	}

	free(ffi_args);
	free(ffi_values);
}

} // ffi

/**
 * Load module data
 */
void FFI::init() {

	Class* FFIObject = new ffi::FFIObject();

	addClass(FFIObject);

	addFunction(new Function("call_ext_func", &CLEVER_NS_FNAME(ffi, call_ext_func), CLEVER_BOOL))
		->setVariadic()
		->setMinNumArgs(2);
}

FFI::~FFI() {
	ExtMap::const_iterator it = ffi::ext_mod_map.begin(),
		end = ffi::ext_mod_map.end();

	while (it != end) {
		if (it->second != NULL) dlclose(it->second);
		++it;
	}
}

}}} // clever::packages::std
<|endoftext|>


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

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <vector>
#include <cmath>

#if defined(_OPENMP)
# include <omp.h>
#endif

#if defined(LIBXSMM_OFFLOAD)
# pragma offload_attribute(pop)
#endif

#include <libxsmm.h>

// make sure that stacksize is covering the problem size
#define SMM_MAX_PROBLEM_SIZE (5 * LIBXSMM_MAX_MNK)

#if (0 < (LIBXSMM_ALIGNED_STORES))
# define SMM_ALIGNMENT LIBXSMM_ALIGNED_STORES
#else
# define SMM_ALIGNMENT LIBXSMM_ALIGNMENT
#endif

#define SMM_CHECK

template<typename T>
LIBXSMM_TARGET(mic) void nrand(T& a)
{
  static const double scale = 1.0 / RAND_MAX;
  a = static_cast<T>(scale * (2 * std::rand() - RAND_MAX));
}

template<typename T>
LIBXSMM_TARGET(mic) void add(T *LIBXSMM_RESTRICT dst, const T *LIBXSMM_RESTRICT c, int m, int n, int ldc)
{
#if (0 < LIBXSMM_ALIGNED_STORES)
  LIBXSMM_ASSUME_ALIGNED(c, SMM_ALIGNMENT);
#endif
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
#if (0 != LIBXSMM_ROW_MAJOR)
      const T value = c[i*ldc+j];
#else
      const T value = c[j*ldc+i];
#endif
#if defined(_OPENMP)
#     pragma omp atomic
#endif
#if (0 != LIBXSMM_ROW_MAJOR)
      dst[i*n+j] += value;
#else
      dst[j*m+i] += value;
#endif
    }
  }
}

template<typename T>
LIBXSMM_TARGET(mic) double max_diff(const T *LIBXSMM_RESTRICT result, const T *LIBXSMM_RESTRICT expect, int m, int n, int ldc)
{
  double diff = 0;
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
#if (0 != LIBXSMM_ROW_MAJOR)
      const int k = i * ldc + j;
#else
      const int k = j * ldc + i;
#endif
      diff = std::max(diff, std::abs(static_cast<double>(result[k]) - static_cast<double>(expect[k])));
    }
  }
  return diff;
}

int main(int argc, char* argv[])
{
  try {
    typedef double T;
    const int default_psize = 500000, default_batch = 100;
    const int m = 1 < argc ? std::atoi(argv[1]) : 23;
    const int s = 2 < argc ? (0 < std::atoi(argv[2]) ? std::atoi(argv[2]) : ('+' == *argv[2]
      ? (default_psize << std::strlen(argv[2]))
      : (default_psize >> std::strlen(argv[2])))) : default_psize;
    const int t = 3 < argc ? (0 < std::atoi(argv[3]) ? std::atoi(argv[3]) : ('+' == *argv[3]
      ? (default_batch << std::strlen(argv[3]))
      : (default_batch >> std::strlen(argv[3])))) : default_batch;
    const int n = 4 < argc ? std::atoi(argv[4]) : m;
    const int k = 5 < argc ? std::atoi(argv[5]) : m;

#if (0 != LIBXSMM_ALIGNED_STORES)
# if (0 != LIBXSMM_ROW_MAJOR)
    const int ldc = LIBXSMM_ALIGN_VALUE(int, T, n, LIBXSMM_ALIGNED_STORES);
    const int csize = m * ldc + (LIBXSMM_ALIGNED_STORES) / sizeof(T) - 1;
# else
    const int ldc = LIBXSMM_ALIGN_VALUE(int, T, m, LIBXSMM_ALIGNED_STORES);
    const int csize = n * ldc + (LIBXSMM_ALIGNED_STORES) / sizeof(T) - 1;
# endif
#else
# if (0 != LIBXSMM_ROW_MAJOR)
    const int ldc = n, csize = m * ldc;
# else
    const int ldc = m, csize = n * ldc;
# endif
#endif

#if defined(LIBXSMM_OFFLOAD)
#   pragma offload target(mic)
#endif
    {
#if defined(_OPENMP)
      const double gflops = (2ULL * s * m * n * k) * 1E-9;
#endif
      const int asize = m * k, bsize = k * n;
      std::vector<T> a(s * asize), b(s * bsize), result(csize);
#if defined(SMM_CHECK)
      std::vector<T> expect(csize);
#endif
      std::for_each(a.begin(), a.end(), nrand<T>);
      std::for_each(b.begin(), b.end(), nrand<T>);
      fprintf(stdout, "psize=%i batch=%i m=%i n=%i k=%i ldc=%i\n", s, t, m, n, k, ldc);

      { // LAPACK/BLAS3 (fallback)
        fprintf(stdout, "LAPACK/BLAS...\n");
        std::fill(result.begin(), result.end(), 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            libxsmm_blasmm(m, n, k, &a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(&result[0], tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        std::copy(result.begin(), result.end(), expect.begin());
#endif
      }

      { // auto-dispatched
        fprintf(stdout, "Dispatched...\n");
        std::fill(result.begin(), result.end(), 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            libxsmm_mm(m, n, k, &a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(&result[0], tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        fprintf(stdout, "\tdiff=%f\n", max_diff(&result[0], &expect[0], m, n, ldc));
#endif
      }

      { // inline an optimized implementation
        fprintf(stdout, "Inlined...\n");
        std::fill(result.begin(), result.end(), 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            libxsmm_imm(m, n, k, &a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(&result[0], tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        fprintf(stdout, "\tdiff=%f\n", max_diff(&result[0], &expect[0], m, n, ldc));
#endif
      }

      const libxsmm_mm_dispatch<T> xmm(m, n, k);
      if (xmm) { // specialized routine
        fprintf(stdout, "Specialized...\n");
        std::fill(result.begin(), result.end(), 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            xmm(&a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(&result[0], tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        fprintf(stdout, "\tdiff=%f\n", max_diff(&result[0], &expect[0], m, n, ldc));
#endif
      }
    }
  }
  catch(const std::exception& e) {
    fprintf(stderr, "Error: %s\n", e.what());
    return EXIT_FAILURE;
  }
  catch(...) {
    fprintf(stderr, "Error: unknown exception caught!\n");
    return EXIT_FAILURE;
  }

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

#if defined(LIBXSMM_OFFLOAD)
# pragma offload_attribute(push,target(mic))
#endif

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <vector>
#include <cmath>

#if defined(_OPENMP)
# include <omp.h>
#endif

#if defined(LIBXSMM_OFFLOAD)
# pragma offload_attribute(pop)
#endif

// make sure that stacksize is covering the problem size
#define SMM_MAX_PROBLEM_SIZE (5 * LIBXSMM_MAX_MNK)

#if (0 < (LIBXSMM_ALIGNED_STORES))
# define SMM_ALIGNMENT LIBXSMM_ALIGNED_STORES
#else
# define SMM_ALIGNMENT LIBXSMM_ALIGNMENT
#endif

#define SMM_CHECK

template<typename T>
LIBXSMM_TARGET(mic) void nrand(T& a)
{
  static const double scale = 1.0 / RAND_MAX;
  a = static_cast<T>(scale * (2 * std::rand() - RAND_MAX));
}

template<typename T>
LIBXSMM_TARGET(mic) void add(T *LIBXSMM_RESTRICT dst, const T *LIBXSMM_RESTRICT c, int m, int n, int ldc)
{
#if (0 < LIBXSMM_ALIGNED_STORES)
  LIBXSMM_ASSUME_ALIGNED(c, SMM_ALIGNMENT);
#endif
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
#if (0 != LIBXSMM_ROW_MAJOR)
      const T value = c[i*ldc+j];
#else
      const T value = c[j*ldc+i];
#endif
#if defined(_OPENMP)
#     pragma omp atomic
#endif
#if (0 != LIBXSMM_ROW_MAJOR)
      dst[i*n+j] += value;
#else
      dst[j*m+i] += value;
#endif
    }
  }
}

template<typename T>
LIBXSMM_TARGET(mic) double max_diff(const T *LIBXSMM_RESTRICT result, const T *LIBXSMM_RESTRICT expect, int m, int n, int ldc)
{
  double diff = 0;
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
#if (0 != LIBXSMM_ROW_MAJOR)
      const int k = i * ldc + j;
#else
      const int k = j * ldc + i;
#endif
      diff = std::max(diff, std::abs(static_cast<double>(result[k]) - static_cast<double>(expect[k])));
    }
  }
  return diff;
}

int main(int argc, char* argv[])
{
  try {
    typedef double T;
    const int default_psize = 500000, default_batch = 100;
    const int m = 1 < argc ? std::atoi(argv[1]) : 23;
    const int s = 2 < argc ? (0 < std::atoi(argv[2]) ? std::atoi(argv[2]) : ('+' == *argv[2]
      ? (default_psize << std::strlen(argv[2]))
      : (default_psize >> std::strlen(argv[2])))) : default_psize;
    const int t = 3 < argc ? (0 < std::atoi(argv[3]) ? std::atoi(argv[3]) : ('+' == *argv[3]
      ? (default_batch << std::strlen(argv[3]))
      : (default_batch >> std::strlen(argv[3])))) : default_batch;
    const int n = 4 < argc ? std::atoi(argv[4]) : m;
    const int k = 5 < argc ? std::atoi(argv[5]) : m;

#if (0 != LIBXSMM_ALIGNED_STORES)
# if (0 != LIBXSMM_ROW_MAJOR)
    const int ldc = LIBXSMM_ALIGN_VALUE(int, T, n, LIBXSMM_ALIGNED_STORES);
    const int csize = m * ldc + (LIBXSMM_ALIGNED_STORES) / sizeof(T) - 1;
# else
    const int ldc = LIBXSMM_ALIGN_VALUE(int, T, m, LIBXSMM_ALIGNED_STORES);
    const int csize = n * ldc + (LIBXSMM_ALIGNED_STORES) / sizeof(T) - 1;
# endif
#else
# if (0 != LIBXSMM_ROW_MAJOR)
    const int ldc = n, csize = m * ldc;
# else
    const int ldc = m, csize = n * ldc;
# endif
#endif

#if defined(LIBXSMM_OFFLOAD)
#   pragma offload target(mic)
#endif
    {
#if defined(_OPENMP)
      const double gflops = (2ULL * s * m * n * k) * 1E-9;
#endif
      const int asize = m * k, bsize = k * n;
      std::vector<T> a(s * asize), b(s * bsize), result(csize);
#if defined(SMM_CHECK)
      std::vector<T> expect(csize);
#endif
      std::for_each(a.begin(), a.end(), nrand<T>);
      std::for_each(b.begin(), b.end(), nrand<T>);
      fprintf(stdout, "psize=%i batch=%i m=%i n=%i k=%i ldc=%i\n", s, t, m, n, k, ldc);

      { // LAPACK/BLAS3 (fallback)
        fprintf(stdout, "LAPACK/BLAS...\n");
        std::fill(result.begin(), result.end(), 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            libxsmm_blasmm(m, n, k, &a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(&result[0], tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        std::copy(result.begin(), result.end(), expect.begin());
#endif
      }

      { // auto-dispatched
        fprintf(stdout, "Dispatched...\n");
        std::fill(result.begin(), result.end(), 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            libxsmm_mm(m, n, k, &a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(&result[0], tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        fprintf(stdout, "\tdiff=%f\n", max_diff(&result[0], &expect[0], m, n, ldc));
#endif
      }

      { // inline an optimized implementation
        fprintf(stdout, "Inlined...\n");
        std::fill(result.begin(), result.end(), 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            libxsmm_imm(m, n, k, &a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(&result[0], tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        fprintf(stdout, "\tdiff=%f\n", max_diff(&result[0], &expect[0], m, n, ldc));
#endif
      }

      const libxsmm_mm_dispatch<T> xmm(m, n, k);
      if (xmm) { // specialized routine
        fprintf(stdout, "Specialized...\n");
        std::fill(result.begin(), result.end(), 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            xmm(&a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(&result[0], tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        fprintf(stdout, "\tdiff=%f\n", max_diff(&result[0], &expect[0], m, n, ldc));
#endif
      }
    }
  }
  catch(const std::exception& e) {
    fprintf(stderr, "Error: %s\n", e.what());
    return EXIT_FAILURE;
  }
  catch(...) {
    fprintf(stderr, "Error: unknown exception caught!\n");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
    Kopete , The KDE Instant Messenger
    Copyright (c) 2001-2002 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Viva Chile Mierda!
    Started at Wed Dec 26 03:12:10 CLST 2001, Santiago de Chile

    Kopete    (c) 2002-2008 by the Kopete developers  <kopete-devel@kde.org>

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

#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include <klocale.h>

#include "kopeteapplication.h"
#include "kopeteversion.h"

static const char description[] =
	I18N_NOOP( "Kopete, the KDE Instant Messenger" );

int main( int argc, char *argv[] )
{
	KAboutData aboutData( "kopete", 0, ki18n("Kopete"),
		KOPETE_VERSION_STRING, ki18n(description), KAboutData::License_GPL,
		ki18n("(c) 2001-2004, Duncan Mac-Vicar Prett\n(c) 2002-2008, Kopete Development Team"), ki18n("kopete-devel@kde.org"), "http://kopete.kde.org");

	aboutData.addAuthor ( ki18n("Duncan Mac-Vicar Prett"), ki18n("Developer and Project founder"), "duncan@kde.org", "http://www.mac-vicar.org/~duncan" );
	aboutData.addAuthor ( ki18n("Andre Duffeck"), ki18n("Developer, Yahoo plugin maintainer"), "duffeck@kde.org" );
	aboutData.addAuthor ( ki18n("Andy Goossens"), ki18n("Developer"), "andygoossens@telenet.be" );
	aboutData.addAuthor ( ki18n("Chris Howells"), ki18n("Developer, Connection status plugin author"), "howells@kde.org", "http://chrishowells.co.uk");
	aboutData.addAuthor ( ki18n("Cláudio da Silveira Pinheiro"), ki18n("Developer, Video device support"), "taupter@gmail.com", "http://taupter.homelinux.org" );
	aboutData.addAuthor ( ki18n("Gregg Edghill"), ki18n("Developer, MSN"), "gregg.edghill@gmail.com");
	aboutData.addAuthor ( ki18n("Grzegorz Jaskiewicz"), ki18n("Developer, Gadu plugin maintainer"), "gj@pointblue.com.pl" );
	aboutData.addAuthor ( ki18n("Gustavo Pichorim Boiko"), ki18n("Developer"), "gustavo.boiko@kdemail.net" );
	aboutData.addAuthor ( ki18n("Jason Keirstead"), ki18n("Developer"), "jason@keirstead.org", "http://www.keirstead.org");
	aboutData.addAuthor ( ki18n("Matt Rogers"), ki18n("Lead Developer, AIM and ICQ plugin maintainer"), "mattr@kde.org" );
	aboutData.addAuthor ( ki18n("Michel Hermier"), ki18n("IRC plugin maintainer"), "michel.hermier@wanadoo.fr" );
	aboutData.addAuthor ( ki18n("Michaël Larouche"), ki18n("Lead Developer, Telepathy and Messenger plugin maintainer"), "larouche@kde.org", "http://www.tehbisnatch.org/" );
	aboutData.addAuthor ( ki18n("Olivier Goffart"), ki18n("Lead Developer, MSN plugin maintainer"), "ogoffart@kde.org");
	aboutData.addAuthor ( ki18n("Ollivier Lapeyre Johann"), ki18n("Artist / Developer, Artwork maintainer"), "johann.ollivierlapeyre@gmail.com" );
	aboutData.addAuthor ( ki18n("Richard Smith"), ki18n("Developer, UI maintainer"), "kde@metafoo.co.uk" );
	aboutData.addAuthor ( ki18n("Tiago Salem Herrmann"), ki18n("Developer, WLM plugin maintainer"), "tiagosh@gmail.com");
	aboutData.addAuthor ( ki18n("Till Gerken"), ki18n("Developer, Jabber plugin maintainer"), "till@tantalo.net");
	aboutData.addAuthor ( ki18n("Will Stephenson"), ki18n("Lead Developer, GroupWise maintainer"), "wstephenson@kde.org" );
	aboutData.addAuthor ( ki18n("Rafael Fernández López"), ki18n("Developer"), "ereslibre@kde.org" );
	aboutData.addAuthor ( ki18n("Roman Jarosz"), ki18n("Developer, AIM and ICQ"), "kedgedev@centrum.cz" );
	aboutData.addAuthor ( ki18n("Charles Connell"), ki18n("Developer"), "charles@connells.org" );
	aboutData.addAuthor ( ki18n("Tejas Dinkar"), ki18n("Developer, Bonjour Plugin Maintainer"), "tejas@gja.in", "http://www.gja.in" );
	aboutData.addAuthor ( ki18n("Pali Rohár"), ki18n("Developer, Skype plugin maintainer"), "pali.rohar@gmail.com" );

	aboutData.addCredit ( ki18n("Vally8"), ki18n("Konki style author"), "vally8@gmail.com", "http://vally8.free.fr/" );
	aboutData.addCredit ( ki18n("Tm_T"), ki18n("Hacker style author"), "jussi.kekkonen@gmail.com");
	aboutData.addCredit ( ki18n("Luciash d' Being"), ki18n("Kopete's icon author") );
	aboutData.addCredit ( ki18n("Steve Cable"), ki18n("Sounds") );
	aboutData.addCredit ( ki18n("Jessica Hall"), ki18n("Kopete Docugoddess, Bug and Patch Testing.") );
	aboutData.addCredit ( ki18n("Justin Karneges"), ki18n("Iris Jabber Backend Library") );
	aboutData.addCredit ( ki18n("Tom Linsky"), ki18n("OscarSocket author"), "twl6@po.cwru.edu" );
	aboutData.addCredit ( ki18n("Olaf Lueg"), ki18n("Kmerlin MSN code") );
	aboutData.addCredit ( ki18n("Chetan Reddy"), ki18n("Former developer"), "chetan13@gmail.com" );
	aboutData.addCredit ( ki18n("Nick Betcher"), ki18n("Former developer, project co-founder"), "nbetcher@kde.org");
	aboutData.addCredit ( ki18n("Ryan Cumming"), ki18n("Former developer"), "ryan@kde.org" );
	aboutData.addCredit ( ki18n("Stefan Gehn"), ki18n("Former developer"), "metz@gehn.net", "http://metz.gehn.net" );
	aboutData.addCredit ( ki18n("Martijn Klingens"), ki18n("Former developer"), "klingens@kde.org" );
	aboutData.addCredit ( ki18n("Andres Krapf"), ki18n("Former developer"), "dae@chez.com" );
	aboutData.addCredit ( ki18n("Carsten Pfeiffer"), ki18n("Misc bugfixes and enhancements"), "pfeiffer@kde.org" );
	aboutData.addCredit ( ki18n("Zack Rusin"), ki18n("Former developer, original Gadu plugin author"), "zack@kde.org" );
	aboutData.addCredit ( ki18n("Richard Stellingwerff"), ki18n("Former developer"), "remenic@linuxfromscratch.org");
	aboutData.addCredit ( ki18n("Daniel Stone"), ki18n("Former developer, Jabber plugin author"), "daniel@fooishbar.org", "http://fooishbar.org");
	aboutData.addCredit ( ki18n("Chris TenHarmsel"), ki18n("Former developer, Oscar plugin"), "chris@tenharmsel.com");
	aboutData.addCredit ( ki18n("Hendrik vom Lehn"), ki18n("Former developer"), "hennevl@hennevl.de", "http://www.hennevl.de");
	aboutData.addCredit ( ki18n("Gav Wood"), ki18n("Former developer and WinPopup maintainer"), "gav@indigoarchive.net" );

	aboutData.setTranslator( ki18nc("NAME OF TRANSLATORS","Your names"),
		ki18nc("EMAIL OF TRANSLATORS","Your emails") );

	KCmdLineArgs::init( argc, argv, &aboutData );

	KCmdLineOptions options;
	options.add("noplugins", ki18n( "Do not load plugins. This option overrides all other options." ));
	options.add("noconnect", ki18n( "Disable auto-connection" ));
	options.add("autoconnect <accounts>", ki18n( "Auto-connect the specified accounts. Use a comma-separated list\n"
		"to auto-connect multiple accounts." ));
	options.add("disable <plugins>", ki18n( "Do not load the specified plugin. Use a comma-separated list\n"
		"to disable multiple plugins." ));
	options.add("load-plugins <plugins>", ki18n( "Load only the specified plugins. Use a comma-separated list\n"
		"to load multiple plugins. This option has no effect when\n"
		"--noplugins is set and overrides all other plugin related\n"
		"command line options." ));
	//	{ "url <url>",              I18N_NOOP( "Load the given Kopete URL" ), 0 },
//	{ "!+[plugin]",            I18N_NOOP( "Load specified plugins" ), 0 },
	options.add("!+[URL]", ki18n("URLs to pass to kopete / emoticon themes to install"));
	KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
	KUniqueApplication::addCmdLineOptions();

	KopeteApplication kopete;
	return kopete.exec();
}
// vim: set noet ts=4 sts=4 sw=4:
<commit_msg>Update my credits<commit_after>/*
    Kopete , The KDE Instant Messenger
    Copyright (c) 2001-2002 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Viva Chile Mierda!
    Started at Wed Dec 26 03:12:10 CLST 2001, Santiago de Chile

    Kopete    (c) 2002-2008 by the Kopete developers  <kopete-devel@kde.org>

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

#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include <klocale.h>

#include "kopeteapplication.h"
#include "kopeteversion.h"

static const char description[] =
	I18N_NOOP( "Kopete, the KDE Instant Messenger" );

int main( int argc, char *argv[] )
{
	KAboutData aboutData( "kopete", 0, ki18n("Kopete"),
		KOPETE_VERSION_STRING, ki18n(description), KAboutData::License_GPL,
		ki18n("(c) 2001-2004, Duncan Mac-Vicar Prett\n(c) 2002-2008, Kopete Development Team"), ki18n("kopete-devel@kde.org"), "http://kopete.kde.org");

	aboutData.addAuthor ( ki18n("Pali Rohár"), ki18n("Developer and maintainer"), "pali.rohar@gmail.com" );
	aboutData.addAuthor ( ki18n("Duncan Mac-Vicar Prett"), ki18n("Developer and Project founder"), "duncan@kde.org", "http://www.mac-vicar.org/~duncan" );
	aboutData.addAuthor ( ki18n("Andre Duffeck"), ki18n("Developer, Yahoo plugin maintainer"), "duffeck@kde.org" );
	aboutData.addAuthor ( ki18n("Andy Goossens"), ki18n("Developer"), "andygoossens@telenet.be" );
	aboutData.addAuthor ( ki18n("Chris Howells"), ki18n("Developer, Connection status plugin author"), "howells@kde.org", "http://chrishowells.co.uk");
	aboutData.addAuthor ( ki18n("Cláudio da Silveira Pinheiro"), ki18n("Developer, Video device support"), "taupter@gmail.com", "http://taupter.homelinux.org" );
	aboutData.addAuthor ( ki18n("Gregg Edghill"), ki18n("Developer, MSN"), "gregg.edghill@gmail.com");
	aboutData.addAuthor ( ki18n("Grzegorz Jaskiewicz"), ki18n("Developer, Gadu plugin maintainer"), "gj@pointblue.com.pl" );
	aboutData.addAuthor ( ki18n("Gustavo Pichorim Boiko"), ki18n("Developer"), "gustavo.boiko@kdemail.net" );
	aboutData.addAuthor ( ki18n("Jason Keirstead"), ki18n("Developer"), "jason@keirstead.org", "http://www.keirstead.org");
	aboutData.addAuthor ( ki18n("Matt Rogers"), ki18n("Lead Developer, AIM and ICQ plugin maintainer"), "mattr@kde.org" );
	aboutData.addAuthor ( ki18n("Michel Hermier"), ki18n("IRC plugin maintainer"), "michel.hermier@wanadoo.fr" );
	aboutData.addAuthor ( ki18n("Michaël Larouche"), ki18n("Lead Developer, Telepathy and Messenger plugin maintainer"), "larouche@kde.org", "http://www.tehbisnatch.org/" );
	aboutData.addAuthor ( ki18n("Olivier Goffart"), ki18n("Lead Developer, MSN plugin maintainer"), "ogoffart@kde.org");
	aboutData.addAuthor ( ki18n("Ollivier Lapeyre Johann"), ki18n("Artist / Developer, Artwork maintainer"), "johann.ollivierlapeyre@gmail.com" );
	aboutData.addAuthor ( ki18n("Richard Smith"), ki18n("Developer, UI maintainer"), "kde@metafoo.co.uk" );
	aboutData.addAuthor ( ki18n("Tiago Salem Herrmann"), ki18n("Developer, WLM plugin maintainer"), "tiagosh@gmail.com");
	aboutData.addAuthor ( ki18n("Till Gerken"), ki18n("Developer, Jabber plugin maintainer"), "till@tantalo.net");
	aboutData.addAuthor ( ki18n("Will Stephenson"), ki18n("Lead Developer, GroupWise maintainer"), "wstephenson@kde.org" );
	aboutData.addAuthor ( ki18n("Rafael Fernández López"), ki18n("Developer"), "ereslibre@kde.org" );
	aboutData.addAuthor ( ki18n("Roman Jarosz"), ki18n("Developer, AIM and ICQ"), "kedgedev@centrum.cz" );
	aboutData.addAuthor ( ki18n("Charles Connell"), ki18n("Developer"), "charles@connells.org" );
	aboutData.addAuthor ( ki18n("Tejas Dinkar"), ki18n("Developer, Bonjour Plugin Maintainer"), "tejas@gja.in", "http://www.gja.in" );

	aboutData.addCredit ( ki18n("Vally8"), ki18n("Konki style author"), "vally8@gmail.com", "http://vally8.free.fr/" );
	aboutData.addCredit ( ki18n("Tm_T"), ki18n("Hacker style author"), "jussi.kekkonen@gmail.com");
	aboutData.addCredit ( ki18n("Luciash d' Being"), ki18n("Kopete's icon author") );
	aboutData.addCredit ( ki18n("Steve Cable"), ki18n("Sounds") );
	aboutData.addCredit ( ki18n("Jessica Hall"), ki18n("Kopete Docugoddess, Bug and Patch Testing.") );
	aboutData.addCredit ( ki18n("Justin Karneges"), ki18n("Iris Jabber Backend Library") );
	aboutData.addCredit ( ki18n("Tom Linsky"), ki18n("OscarSocket author"), "twl6@po.cwru.edu" );
	aboutData.addCredit ( ki18n("Olaf Lueg"), ki18n("Kmerlin MSN code") );
	aboutData.addCredit ( ki18n("Chetan Reddy"), ki18n("Former developer"), "chetan13@gmail.com" );
	aboutData.addCredit ( ki18n("Nick Betcher"), ki18n("Former developer, project co-founder"), "nbetcher@kde.org");
	aboutData.addCredit ( ki18n("Ryan Cumming"), ki18n("Former developer"), "ryan@kde.org" );
	aboutData.addCredit ( ki18n("Stefan Gehn"), ki18n("Former developer"), "metz@gehn.net", "http://metz.gehn.net" );
	aboutData.addCredit ( ki18n("Martijn Klingens"), ki18n("Former developer"), "klingens@kde.org" );
	aboutData.addCredit ( ki18n("Andres Krapf"), ki18n("Former developer"), "dae@chez.com" );
	aboutData.addCredit ( ki18n("Carsten Pfeiffer"), ki18n("Misc bugfixes and enhancements"), "pfeiffer@kde.org" );
	aboutData.addCredit ( ki18n("Zack Rusin"), ki18n("Former developer, original Gadu plugin author"), "zack@kde.org" );
	aboutData.addCredit ( ki18n("Richard Stellingwerff"), ki18n("Former developer"), "remenic@linuxfromscratch.org");
	aboutData.addCredit ( ki18n("Daniel Stone"), ki18n("Former developer, Jabber plugin author"), "daniel@fooishbar.org", "http://fooishbar.org");
	aboutData.addCredit ( ki18n("Chris TenHarmsel"), ki18n("Former developer, Oscar plugin"), "chris@tenharmsel.com");
	aboutData.addCredit ( ki18n("Hendrik vom Lehn"), ki18n("Former developer"), "hennevl@hennevl.de", "http://www.hennevl.de");
	aboutData.addCredit ( ki18n("Gav Wood"), ki18n("Former developer and WinPopup maintainer"), "gav@indigoarchive.net" );

	aboutData.setTranslator( ki18nc("NAME OF TRANSLATORS","Your names"),
		ki18nc("EMAIL OF TRANSLATORS","Your emails") );

	KCmdLineArgs::init( argc, argv, &aboutData );

	KCmdLineOptions options;
	options.add("noplugins", ki18n( "Do not load plugins. This option overrides all other options." ));
	options.add("noconnect", ki18n( "Disable auto-connection" ));
	options.add("autoconnect <accounts>", ki18n( "Auto-connect the specified accounts. Use a comma-separated list\n"
		"to auto-connect multiple accounts." ));
	options.add("disable <plugins>", ki18n( "Do not load the specified plugin. Use a comma-separated list\n"
		"to disable multiple plugins." ));
	options.add("load-plugins <plugins>", ki18n( "Load only the specified plugins. Use a comma-separated list\n"
		"to load multiple plugins. This option has no effect when\n"
		"--noplugins is set and overrides all other plugin related\n"
		"command line options." ));
	//	{ "url <url>",              I18N_NOOP( "Load the given Kopete URL" ), 0 },
//	{ "!+[plugin]",            I18N_NOOP( "Load specified plugins" ), 0 },
	options.add("!+[URL]", ki18n("URLs to pass to kopete / emoticon themes to install"));
	KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
	KUniqueApplication::addCmdLineOptions();

	KopeteApplication kopete;
	return kopete.exec();
}
// vim: set noet ts=4 sts=4 sw=4:
<|endoftext|>


<commit_before>#define PROG_VERSION "v0.1.0-alpha"

//Owns files
#include "cmdparser.hpp"
#include "log.hpp"
#include "reads.hpp"
#include "readsTools.hpp"
#include "workerCL.hpp"

//Standards libs
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <thread>

using namespace std;

/*
Function to get the scores matrix between all contigs of a same set. Used in mono and multithreading.
*/

void contigs_cmp(size_t id_begin, size_t id_end, vector< vector< int8_t> >& scores, const Contigs& contigs){
	ReadsTools readsTools; //Toolsbox containing the function to cmp reads
	for(size_t c = 0; c < contigs.get_nbContigs(); c++){
		string seq_c = contigs.get_seqContig(c);
		for(size_t i=id_begin; i <= id_end; i++){
			//if same read, score = 0
			//Else compare
			if(c == i){scores[c][i] = 0;}
			else{
				string seq_i = contigs.get_seqContig(i);

				scores[c][i] = readsTools.scoreCmpReads(seq_c, seq_i);
			}
		}
	}
}

/*
Heart of the program
*/

int main(int argc, char* argv[]){
	/* Initialisation :
		1/ Check and parse parameters and options
		2/ Display infos
		3/ Initialize OpenCL
	*/
	//Get parameters and options (Includes/cmdparser.hpp using optionsparser.h)
	Params params = parse(argc, argv);
	Log log(params.logs);

	//Display infos
	log.write( "[STEP]\tInitialisation" );

	if(!params.gpu_infos){ //normal infos
		log.write( "=== Infos ===" );
		log.write(params.infosToString());
	}
	else{ //Asked GPU infos
		log.write( "=== OpenCL infos ===" );
		WorkerCL::list_infos(log);
		return 0; //End prog
	}

	//Initialize gpu (used only if gpu is asked)
	WorkerCL* workerCL = nullptr;
	try{
		if(params.gpu){
			log.write("=== OpenCL initialisation ===");
			workerCL = new WorkerCL(params.opencl_platform_id, params.opencl_device_id, log);
		}
	}
	catch(string opencl_err){
		log.write(opencl_err);
	}

	/* Data gathering :
		1/ read file (get reads) (encode and store them)
		2/ Create the contigs list. It creates a "contig" for each read. A contig contain the ids of its reads and its sequence
		3/ Initialize the 2D array (vector) to store each reads-reads score alignment
	*/
	log.write( "\n[STEP]\tData gathering" );

	log.write( "=== File reading ===" );
	Reads reads;
	reads.readFile_fasta(params.readsFile);
	{
		string s = "nbReads = " + to_string(reads.get_nbReads());
		log.write(s);
	}
	log.write( "=== Create contigs ===" );
	Contigs contigs( &reads );
	size_t nbContigs = contigs.get_nbContigs();
	{
		string s = "number of contigs = " + to_string(nbContigs);
		log.write(s);
	}

	// Cycles
	log.write( "\n[STEP]\tCycles" );

	bool in_progress = true; //There is still progress ?
	size_t cycles = 0;

	while(in_progress){
		cycles++;
		{
			string s = "===== Cycle "+to_string(cycles)+" =====";
			log.write(s);
			log.write( "=== Calculate score between each contig ===" );
		}

		/*
		 Create a 2D array of size of nb of contigs storing for each pair of contigs their alignment score.
		 0 means a bad alignment.
		 The second element is match on the first element.
		 >0 gives the score of a normal alignment
		 <0 gives the score (the absolute value) of the complementary alignment
		 The highest absolute value is stored (for example: for two read A et B if the score of the normal is 10 and
		 the score of the complementary alignment is 25, -25 will be stored
		*/
		nbContigs = contigs.get_nbContigs();
		vector< vector< int8_t > > scores = vector< vector<int8_t> >(nbContigs, vector<int8_t>(nbContigs, 0));

			// GPU ?
		if(params.gpu){
			workerCL->run(contigs, params.opencl_work_group_size);
		}
			// Multithreading ?
		else if(params.nbthreads > 1){
			vector<thread> workers;
			size_t id_begin=0;

			//the main is a thread; So the number of worker = (number_of_threads_asked - 1).
			//Launch threads
			for(size_t w=0; w < params.nbthreads-1; w++){
				//Number of contigs to cmp in this thread
				size_t nb_contigs_cmp = nbContigs/params.nbthreads + (( w < (nbContigs % params.nbthreads) )?1:0);
				//cout << "Thread " << w << ": " << nb_contigs_cmp << " contigs." << endl;

				//If there is contigs to cmp, we run the thread
				if(nb_contigs_cmp){
					size_t id_end=id_begin+nb_contigs_cmp-1;
					workers.emplace_back(contigs_cmp, id_begin, id_end, ref(scores), ref(contigs));
					//cout << "Thread " << w << " on " << id_begin << " to " << id_end << endl;
					id_begin = id_end+1; //Prepare next
				}

			}

			//Run remainings contigs on main
			if(id_begin < nbContigs){
				//cout << "Thread main on " << id_begin << " to " << nbContigs-1 << endl;
				contigs_cmp(id_begin, nbContigs-1, scores, contigs);
			}

			//Wait the end of threads
			for(size_t w = 0; w < workers.size(); w++){
				workers[w].join();
			}

		}
			// Monothreading
		else{
			contigs_cmp(0, nbContigs-1, scores, contigs);
		}

		/*
		log.write("---- matrix of scores ----");
		string out;
		for(size_t i=0; i < nbContigs; i++){out += "\t" + to_string(i);}
		log.write(out);

		for(size_t i=0; i < nbContigs; i++){
			out = to_string(i);
			for(size_t j=0; j < nbContigs; j++){
				out += "\t"+to_string(scores[i][j]);
			}
			log.write(out);
		}
		log.write("---- end of matrix ----");
		*/

		//Merge best couples (when score >= requirement)
		log.write("=== Merging best contigs couples ===");
		int8_t b; //best couples score
		do {
			b=0;
			size_t b_id1=0;
			size_t b_id2=0;
			// Get best couple
			for(size_t id1=0; id1 < nbContigs; id1++){
				for(size_t id2=id1+1; id2 < nbContigs; id2++){
					//Get score, is it better ?
					if(abs(scores[id1][id2]) > b){
						//keep this couple
						b = abs(scores[id1][id2]);
						b_id1 = id1;
						b_id2 = id2;
					}
				}
			}
			//If score > requirement : merge this 2
			if(b >= params.requiredScore){
				//Merge
				contigs.merge_contigs(b_id1, b_id2, scores[b_id1][b_id2]);

				//clean the done and not possible couples after this merge
					//This couple and its opposite
				scores[b_id1][b_id2]=0;
				scores[b_id2][b_id1]=0;
					//The 'end' of contig1 is used
						//All couple with contig1 first
				for(size_t i=0; i < nbContigs; i++){
					scores[b_id1][i]=0;
				}
						//All couple with contig1 reversed as second
				for(size_t i=0; i < nbContigs; i++){
					if(scores[i][b_id1]<0){scores[i][b_id1]=0;}
				}

					//contig2 normal ? The begin is used
				if(scores[b_id1][b_id2] > 0){
					for(size_t i=0; i < nbContigs; i++){
						if(scores[i][b_id2]>0){scores[i][b_id2]=0;}
					}
				}
					//else contig2 is reversed: the end is used
				else{
						//All couples beginning with contig2
					for(size_t i=0; i < nbContigs; i++){
						scores[b_id2][i]=0;
					}
						//All couples with contig2 as second and reversed
					for(size_t i=0; i < nbContigs; i++){
						if(scores[i][b_id2] < 0){scores[i][b_id2]=0;}
					}
				}

			}
		} while (b >= params.requiredScore);

		//Synchronize the contigs list
		log.write("=== Synchronisation ===");
		contigs.sync_contigs_list();

		//Get the evolution. None: stop it.
		size_t new_nbContigs = contigs.get_nbContigs();

		string s = "nb contigs merged = " + to_string(nbContigs - new_nbContigs);
		s += "\nnb contigs remaining = " + to_string(new_nbContigs);
		if(new_nbContigs == nbContigs){
			s += "\nNo evolution. Stopping.";
			in_progress=false;
		}
		log.write(s);

		//End of cycle
		log.write("===== Cycle end =====\n");
	}

	//Free workerCL (if created)
	if(params.gpu){
		cout << "Deleting gpu worker" << endl;
		delete workerCL;
		workerCL = nullptr;
		cout << "\t- Done" << endl;
	}

	//End of program
	return 0;
}
<commit_msg>Get scores matrix from gpu run. Display (debug) matrix.<commit_after>#define PROG_VERSION "v0.1.0-alpha"

//Owns files
#include "cmdparser.hpp"
#include "log.hpp"
#include "reads.hpp"
#include "readsTools.hpp"
#include "workerCL.hpp"

//Standards libs
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <thread>

using namespace std;

/*
Function to get the scores matrix between all contigs of a same set. Used in mono and multithreading.
*/

void contigs_cmp(size_t id_begin, size_t id_end, vector< vector< int8_t> >& scores, const Contigs& contigs){
	ReadsTools readsTools; //Toolsbox containing the function to cmp reads
	for(size_t c = 0; c < contigs.get_nbContigs(); c++){
		string seq_c = contigs.get_seqContig(c);
		for(size_t i=id_begin; i <= id_end; i++){
			//if same read, score = 0
			//Else compare
			if(c == i){scores[c][i] = 0;}
			else{
				string seq_i = contigs.get_seqContig(i);

				scores[c][i] = readsTools.scoreCmpReads(seq_c, seq_i);
			}
		}
	}
}

/*
Heart of the program
*/

int main(int argc, char* argv[]){
	/* Initialisation :
		1/ Check and parse parameters and options
		2/ Display infos
		3/ Initialize OpenCL
	*/
	//Get parameters and options (Includes/cmdparser.hpp using optionsparser.h)
	Params params = parse(argc, argv);
	Log log(params.logs);

	//Display infos
	log.write( "[STEP]\tInitialisation" );

	if(!params.gpu_infos){ //normal infos
		log.write( "=== Infos ===" );
		log.write(params.infosToString());
	}
	else{ //Asked GPU infos
		log.write( "=== OpenCL infos ===" );
		WorkerCL::list_infos(log);
		return 0; //End prog
	}

	//Initialize gpu (used only if gpu is asked)
	WorkerCL* workerCL = nullptr;
	try{
		if(params.gpu){
			log.write("=== OpenCL initialisation ===");
			workerCL = new WorkerCL(params.opencl_platform_id, params.opencl_device_id, log);
		}
	}
	catch(string opencl_err){
		log.write(opencl_err);
	}

	/* Data gathering :
		1/ read file (get reads) (encode and store them)
		2/ Create the contigs list. It creates a "contig" for each read. A contig contain the ids of its reads and its sequence
		3/ Initialize the 2D array (vector) to store each reads-reads score alignment
	*/
	log.write( "\n[STEP]\tData gathering" );

	log.write( "=== File reading ===" );
	Reads reads;
	reads.readFile_fasta(params.readsFile);
	{
		string s = "nbReads = " + to_string(reads.get_nbReads());
		log.write(s);
	}
	log.write( "=== Create contigs ===" );
	Contigs contigs( &reads );
	size_t nbContigs = contigs.get_nbContigs();
	{
		string s = "number of contigs = " + to_string(nbContigs);
		log.write(s);
	}

	// Cycles
	log.write( "\n[STEP]\tCycles" );

	bool in_progress = true; //There is still progress ?
	size_t cycles = 0;

	while(in_progress){
		cycles++;
		{
			string s = "===== Cycle "+to_string(cycles)+" =====";
			log.write(s);
			log.write( "=== Calculate score between each contig ===" );
		}

		/*
		 Create a 2D array of size of nb of contigs storing for each pair of contigs their alignment score.
		 0 means a bad alignment.
		 The second element is match on the first element.
		 >0 gives the score of a normal alignment
		 <0 gives the score (the absolute value) of the complementary alignment
		 The highest absolute value is stored (for example: for two read A et B if the score of the normal is 10 and
		 the score of the complementary alignment is 25, -25 will be stored
		*/
		nbContigs = contigs.get_nbContigs();
		vector< vector< int8_t > > scores = vector< vector<int8_t> >(nbContigs, vector<int8_t>(nbContigs, 0));

			// GPU ?
		if(params.gpu){
			scores = workerCL->run(contigs, params.opencl_work_group_size);
		}
			// Multithreading ?
		else if(params.nbthreads > 1){
			vector<thread> workers;
			size_t id_begin=0;

			//the main is a thread; So the number of worker = (number_of_threads_asked - 1).
			//Launch threads
			for(size_t w=0; w < params.nbthreads-1; w++){
				//Number of contigs to cmp in this thread
				size_t nb_contigs_cmp = nbContigs/params.nbthreads + (( w < (nbContigs % params.nbthreads) )?1:0);
				//cout << "Thread " << w << ": " << nb_contigs_cmp << " contigs." << endl;

				//If there is contigs to cmp, we run the thread
				if(nb_contigs_cmp){
					size_t id_end=id_begin+nb_contigs_cmp-1;
					workers.emplace_back(contigs_cmp, id_begin, id_end, ref(scores), ref(contigs));
					//cout << "Thread " << w << " on " << id_begin << " to " << id_end << endl;
					id_begin = id_end+1; //Prepare next
				}

			}

			//Run remainings contigs on main
			if(id_begin < nbContigs){
				//cout << "Thread main on " << id_begin << " to " << nbContigs-1 << endl;
				contigs_cmp(id_begin, nbContigs-1, scores, contigs);
			}

			//Wait the end of threads
			for(size_t w = 0; w < workers.size(); w++){
				workers[w].join();
			}

		}
			// Monothreading
		else{
			contigs_cmp(0, nbContigs-1, scores, contigs);
		}

		log.write("---- matrix of scores ----");
		string out;
		for(size_t i=0; i < nbContigs; i++){out += "\t" + to_string(i);}
		log.write(out);

		for(size_t i=0; i < nbContigs; i++){
			out = to_string(i);
			for(size_t j=0; j < nbContigs; j++){
				out += "\t"+to_string(scores[i][j]);
			}
			log.write(out);
		}
		log.write("---- end of matrix ----");

		//Merge best couples (when score >= requirement)
		log.write("=== Merging best contigs couples ===");
		int8_t b; //best couples score
		do {
			b=0;
			size_t b_id1=0;
			size_t b_id2=0;
			// Get best couple
			for(size_t id1=0; id1 < nbContigs; id1++){
				for(size_t id2=id1+1; id2 < nbContigs; id2++){
					//Get score, is it better ?
					if(abs(scores[id1][id2]) > b){
						//keep this couple
						b = abs(scores[id1][id2]);
						b_id1 = id1;
						b_id2 = id2;
					}
				}
			}
			//If score > requirement : merge this 2
			if(b >= params.requiredScore){
				//Merge
				contigs.merge_contigs(b_id1, b_id2, scores[b_id1][b_id2]);

				//clean the done and not possible couples after this merge
					//This couple and its opposite
				scores[b_id1][b_id2]=0;
				scores[b_id2][b_id1]=0;
					//The 'end' of contig1 is used
						//All couple with contig1 first
				for(size_t i=0; i < nbContigs; i++){
					scores[b_id1][i]=0;
				}
						//All couple with contig1 reversed as second
				for(size_t i=0; i < nbContigs; i++){
					if(scores[i][b_id1]<0){scores[i][b_id1]=0;}
				}

					//contig2 normal ? The begin is used
				if(scores[b_id1][b_id2] > 0){
					for(size_t i=0; i < nbContigs; i++){
						if(scores[i][b_id2]>0){scores[i][b_id2]=0;}
					}
				}
					//else contig2 is reversed: the end is used
				else{
						//All couples beginning with contig2
					for(size_t i=0; i < nbContigs; i++){
						scores[b_id2][i]=0;
					}
						//All couples with contig2 as second and reversed
					for(size_t i=0; i < nbContigs; i++){
						if(scores[i][b_id2] < 0){scores[i][b_id2]=0;}
					}
				}

			}
		} while (b >= params.requiredScore);

		//Synchronize the contigs list
		log.write("=== Synchronisation ===");
		contigs.sync_contigs_list();

		//Get the evolution. None: stop it.
		size_t new_nbContigs = contigs.get_nbContigs();

		string s = "nb contigs merged = " + to_string(nbContigs - new_nbContigs);
		s += "\nnb contigs remaining = " + to_string(new_nbContigs);
		if(new_nbContigs == nbContigs){
			s += "\nNo evolution. Stopping.";
			in_progress=false;
		}
		log.write(s);

		//End of cycle
		log.write("===== Cycle end =====\n");
	}

	//Free workerCL (if created)
	if(params.gpu){
		cout << "Deleting gpu worker" << endl;
		delete workerCL;
		workerCL = nullptr;
		cout << "\t- Done" << endl;
	}

	//End of program
	return 0;
}
<|endoftext|>