<commit_before>/// @file tinycc.cc
/// This example demonstrates loading, running and scripting a very simple NaCl
/// module.  To load the NaCl module, the browser first looks for the
/// CreateModule() factory method (at the end of this file).  It calls
/// CreateModule() once to load the module code from your .nexe.  After the
/// .nexe code is loaded, CreateModule() is not called again.
///
/// Once the .nexe code is loaded, the browser than calls the CreateInstance()
/// method on the object returned by CreateModule().  It calls CreateInstance()
/// each time it encounters an <embed> tag that references your NaCl module.
///
/// The browser can talk to your NaCl module via the postMessage() Javascript
/// function.  When you call postMessage() on your NaCl module from the browser,
/// this becomes a call to the HandleMessage() method of your pp::Instance
/// subclass.  You can send messages back to the browser by calling the
/// PostMessage() method on your pp::Instance.  Note that these two methods
/// (postMessage() in Javascript and PostMessage() in C++) are asynchronous.
/// This means they return immediately - there is no waiting for the message
/// to be handled.  This has implications in your program design, particularly
/// when mutating property values that are exposed to both the browser and the
/// NaCl module.

#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

#include <memory>
#include <string>
#include <vector>

#include <ppapi/cpp/instance.h>
#include <ppapi/cpp/module.h>
#include <ppapi/cpp/var.h>

#include <nacl-mounts/base/MainThreadRunner.h>
#include <nacl-mounts/base/UrlLoaderJob.h>
#include <nacl-mounts/memory/MemMount.h>

#include "../libtcc.h"

using namespace std;

extern "C" int mount(const char *type, const char *dir, int flags, void *data);
extern "C" int umount(const char *path);
extern "C" int simple_tar_extract(const char *path);

static void* InitFileSystemThread(void* data);

/// The Instance class.  One of these exists for each instance of your NaCl
/// module on the web page.  The browser will ask the Module object to create
/// a new Instance for each occurence of the <embed> tag that has these
/// attributes:
///     type="application/x-nacl"
///     src="tinycc.nmf"
/// To communicate with the browser, you must override HandleMessage() for
/// receiving messages from the borwser, and use PostMessage() to send messages
/// back to the browser.  Note that this interface is entirely asynchronous.
class TinyccInstance : public pp::Instance {
 public:
  /// The constructor creates the plugin-side instance.
  /// @param[in] instance the handle to the browser-side plugin instance.
  explicit TinyccInstance(PP_Instance instance) : pp::Instance(instance) {
    PostMessage(pp::Var("status:INITIALIZED"));
  }

  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
    runner_.reset(new MainThreadRunner(this));
    pthread_t th;
    pthread_create(&th, NULL, &InitFileSystemThread, this);
    return true;
  }

  virtual ~TinyccInstance() {
  }

  /// Handler for messages coming in from the browser via postMessage().  The
  /// @a var_message can contain anything: a JSON string; a string that encodes
  /// method names and arguments; etc.  For example, you could use
  /// JSON.stringify in the browser to create a message that contains a method
  /// name and some parameters, something like this:
  ///   var json_message = JSON.stringify({ "myMethod" : "3.14159" });
  ///   nacl_module.postMessage(json_message);
  /// On receipt of this message in @a var_message, you could parse the JSON to
  /// retrieve the method name, match it to a function call, and then call it
  /// with the parameter.
  /// @param[in] var_message The message posted by the browser.
  virtual void HandleMessage(const pp::Var& var_message) {
    if (!var_message.is_string()) {
      PostMessage(pp::Var("unexpected type: " + var_message.DebugString()));
      return;
    }

    errors_.clear();
    const string& msg = var_message.AsString();
    size_t colon_offset = msg.find(':');
    if (colon_offset == string::npos) {
      PostMessage(pp::Var("invalid command: " + var_message.DebugString()));

    }

    const string& cmd = msg.substr(0, colon_offset);
    int output_type = TCC_OUTPUT_MEMORY;
    if (cmd == "preprocess") {
      output_type = TCC_OUTPUT_PREPROCESS;
    } else if (cmd == "compile") {
      output_type = TCC_OUTPUT_OBJ;
    } else if (cmd == "run") {
      output_type = TCC_OUTPUT_MEMORY;
    } else {
      PostMessage(pp::Var("invalid command: " + cmd));
      return;
    }

    close(1);
    close(2);
    int fd;
    fd = open("/tmp/stdout.txt", O_WRONLY | O_CREAT | O_TRUNC);
    assert(fd == 1);
    fd = open("/tmp/stderr.txt", O_WRONLY | O_CREAT | O_TRUNC);
    assert(fd == 2);

    fd = open("/tmp/input.c", O_WRONLY | O_CREAT | O_TRUNC);
    assert(fd >= 0);
    write(fd, msg.c_str() + colon_offset + 1, msg.size() - colon_offset - 1);
    close(fd);

    ScopedTCCState tcc_state;
    TCCState* s1 = tcc_state.get();
    tcc_set_error_func(s1, this, &TinyccInstance::HandleTCCError);
    tcc_set_output_type(s1, output_type);
    tcc_add_include_path(s1, "/usr/include");
    tcc_add_include_path(s1, "/usr/lib/tcc/include");
    tcc_add_file(s1, "/tmp/input.c");
    if (output_type == TCC_OUTPUT_OBJ) {
      tcc_output_file(s1, "/tmp/out");
    }

    if (errors_.empty() && output_type == TCC_OUTPUT_MEMORY) {
      char* argv[] = {
        (char*)"./a.out", NULL
      };
      tcc_run(s1, 1, argv);
    }

    string out;

    close(1);
    close(2);

    if (errors_.empty()) {
      fd = open("/tmp/stdout.txt", O_RDONLY);
      if (fd >= 0) {
        string o;
        ReadFromFD(fd, &o);
        if (!o.empty()) {
          out += "=== STDOUT ===\n";
          out += o;
        }
      }
      fd = open("/tmp/stderr.txt", O_RDONLY);
      if (fd >= 0) {
        string o;
        ReadFromFD(fd, &o);
        if (!o.empty()) {
          out += "=== STDERR ===\n";
          out += o;
        }
      }
    } else {
      out += "=== COMPILE ERROR ===\n";
      for (size_t i = 0; i < errors_.size(); i++) {
          out += errors_[i];
          out += '\n';
      }
    }

    if (output_type == TCC_OUTPUT_OBJ) {
      int fd = open("/tmp/out", O_RDONLY);
      if (fd < 0) {
        PostMessage(pp::Var(
                      string("failed to read output: ") + strerror(errno)));
        return;
      }
      ReadFromFD(fd, &out);
      PostMessage(pp::Var(out));
      return;
    }

    PostMessage(pp::Var(out));
  }

  static void HandleTCCError(void* data, const char* msg) {
    TinyccInstance* self = (TinyccInstance*)data;
    self->errors_.push_back(msg);
  }

  void InitFileSystem() {
    PostMessageFromThread("status:DOWNLOADING DATA");
    UrlLoaderJob *job = new UrlLoaderJob;
    job->set_url("x86_64-nacl.sar?v16");
    std::vector<char> data;
    job->set_dst(&data);
    runner_->RunJob(job);

    PostMessageFromThread("status:WRITING DATA");
    int fd = open("/x86_64-nacl.sar", O_CREAT | O_WRONLY);
    if (fd < 0) {
      PostMessageFromThread("status:WRITE DATA FAILED");
      return;
    }
    write(fd, &data[0], data.size());
    close(fd);

    mkdir("/tmp", 0777);
    mkdir("/usr", 0777);
    chdir("/usr");
    PostMessageFromThread("status:EXTRACTING DATA");
    int r = simple_tar_extract("/x86_64-nacl.sar");
    if (r != 0) {
      PostMessageFromThread("status:EXTRACT DATA FAILED");
    }

#ifdef __x86_64__
    PostMessageFromThread("status:READY (64bit)");
#else
    PostMessageFromThread("status:READY (32bit)");
#endif
  }

private:
  class PostMessageJob : public MainThreadJob {
  public:
    PostMessageJob(const string& msg) : msg_(msg) {}
    virtual ~PostMessageJob() {}
    virtual void Run(MainThreadRunner::JobEntry* entry) {
      pp::Instance* self = MainThreadRunner::ExtractPepperInstance(entry);
      self->PostMessage(pp::Var(msg_));
      MainThreadRunner::ResultCompletion(entry, 0);
    }
  private:
    string msg_;
  };

  struct ScopedTCCState {
    ScopedTCCState() {
      s1_ = tcc_new();
    }
    ~ScopedTCCState() {
      tcc_delete(s1_);
    }
    TCCState* get() {
      return s1_;
    }
  private:
    TCCState* s1_;
  };

  void PostMessageFromThread(const string& msg) {
    PostMessageJob* job = new PostMessageJob(msg);
    runner_->RunJob(job);
  }

  static void ReadFromFD(int fd, string* out) {
    off_t size = lseek(fd, 0, SEEK_END);
    lseek(fd, 0, SEEK_SET);
    char* buf = (char*)malloc(size + 1);
    buf[size] = '\0';
    read(fd, buf, size);
    close(fd);
    *out = buf;
    free(buf);
  }

  static string ReadFromFile(const char* file) {
    int fd = open(file, O_RDONLY);
    string s;
    ReadFromFD(fd, &s);
    return s;
  }

  auto_ptr<MainThreadRunner> runner_;
  auto_ptr<MemMount> mount_;
  vector<string> errors_;
};

void* InitFileSystemThread(void* data) {
  TinyccInstance* self = (TinyccInstance*)data;
  self->InitFileSystem();
  return NULL;
}

/// The Module class.  The browser calls the CreateInstance() method to create
/// an instance of your NaCl module on the web page.  The browser creates a new
/// instance for each <embed> tag with type="application/x-nacl".
class TinyccModule : public pp::Module {
 public:
  TinyccModule() : pp::Module() {}
  virtual ~TinyccModule() {}

  /// Create and return a TinyccInstance object.
  /// @param[in] instance The browser-side instance.
  /// @return the plugin-side instance.
  virtual pp::Instance* CreateInstance(PP_Instance instance) {
    return new TinyccInstance(instance);
  }
};

namespace pp {
/// Factory function called by the browser when the module is first loaded.
/// The browser keeps a singleton of this module.  It calls the
/// CreateInstance() method on the object you return to make instances.  There
/// is one instance per <embed> tag on the page.  This is the main binding
/// point for your NaCl module with the browser.
Module* CreateModule() {
  return new TinyccModule();
}
}  // namespace pp
<commit_msg>[NaCl] correct the path to data<commit_after>/// @file tinycc.cc
/// This example demonstrates loading, running and scripting a very simple NaCl
/// module.  To load the NaCl module, the browser first looks for the
/// CreateModule() factory method (at the end of this file).  It calls
/// CreateModule() once to load the module code from your .nexe.  After the
/// .nexe code is loaded, CreateModule() is not called again.
///
/// Once the .nexe code is loaded, the browser than calls the CreateInstance()
/// method on the object returned by CreateModule().  It calls CreateInstance()
/// each time it encounters an <embed> tag that references your NaCl module.
///
/// The browser can talk to your NaCl module via the postMessage() Javascript
/// function.  When you call postMessage() on your NaCl module from the browser,
/// this becomes a call to the HandleMessage() method of your pp::Instance
/// subclass.  You can send messages back to the browser by calling the
/// PostMessage() method on your pp::Instance.  Note that these two methods
/// (postMessage() in Javascript and PostMessage() in C++) are asynchronous.
/// This means they return immediately - there is no waiting for the message
/// to be handled.  This has implications in your program design, particularly
/// when mutating property values that are exposed to both the browser and the
/// NaCl module.

#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

#include <memory>
#include <string>
#include <vector>

#include <ppapi/cpp/instance.h>
#include <ppapi/cpp/module.h>
#include <ppapi/cpp/var.h>

#include <nacl-mounts/base/MainThreadRunner.h>
#include <nacl-mounts/base/UrlLoaderJob.h>
#include <nacl-mounts/memory/MemMount.h>

#include "../libtcc.h"

using namespace std;

extern "C" int mount(const char *type, const char *dir, int flags, void *data);
extern "C" int umount(const char *path);
extern "C" int simple_tar_extract(const char *path);

static void* InitFileSystemThread(void* data);

/// The Instance class.  One of these exists for each instance of your NaCl
/// module on the web page.  The browser will ask the Module object to create
/// a new Instance for each occurence of the <embed> tag that has these
/// attributes:
///     type="application/x-nacl"
///     src="tinycc.nmf"
/// To communicate with the browser, you must override HandleMessage() for
/// receiving messages from the borwser, and use PostMessage() to send messages
/// back to the browser.  Note that this interface is entirely asynchronous.
class TinyccInstance : public pp::Instance {
 public:
  /// The constructor creates the plugin-side instance.
  /// @param[in] instance the handle to the browser-side plugin instance.
  explicit TinyccInstance(PP_Instance instance) : pp::Instance(instance) {
    PostMessage(pp::Var("status:INITIALIZED"));
  }

  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
    runner_.reset(new MainThreadRunner(this));
    pthread_t th;
    pthread_create(&th, NULL, &InitFileSystemThread, this);
    return true;
  }

  virtual ~TinyccInstance() {
  }

  /// Handler for messages coming in from the browser via postMessage().  The
  /// @a var_message can contain anything: a JSON string; a string that encodes
  /// method names and arguments; etc.  For example, you could use
  /// JSON.stringify in the browser to create a message that contains a method
  /// name and some parameters, something like this:
  ///   var json_message = JSON.stringify({ "myMethod" : "3.14159" });
  ///   nacl_module.postMessage(json_message);
  /// On receipt of this message in @a var_message, you could parse the JSON to
  /// retrieve the method name, match it to a function call, and then call it
  /// with the parameter.
  /// @param[in] var_message The message posted by the browser.
  virtual void HandleMessage(const pp::Var& var_message) {
    if (!var_message.is_string()) {
      PostMessage(pp::Var("unexpected type: " + var_message.DebugString()));
      return;
    }

    errors_.clear();
    const string& msg = var_message.AsString();
    size_t colon_offset = msg.find(':');
    if (colon_offset == string::npos) {
      PostMessage(pp::Var("invalid command: " + var_message.DebugString()));

    }

    const string& cmd = msg.substr(0, colon_offset);
    int output_type = TCC_OUTPUT_MEMORY;
    if (cmd == "preprocess") {
      output_type = TCC_OUTPUT_PREPROCESS;
    } else if (cmd == "compile") {
      output_type = TCC_OUTPUT_OBJ;
    } else if (cmd == "run") {
      output_type = TCC_OUTPUT_MEMORY;
    } else {
      PostMessage(pp::Var("invalid command: " + cmd));
      return;
    }

    close(1);
    close(2);
    int fd;
    fd = open("/tmp/stdout.txt", O_WRONLY | O_CREAT | O_TRUNC);
    assert(fd == 1);
    fd = open("/tmp/stderr.txt", O_WRONLY | O_CREAT | O_TRUNC);
    assert(fd == 2);

    fd = open("/tmp/input.c", O_WRONLY | O_CREAT | O_TRUNC);
    assert(fd >= 0);
    write(fd, msg.c_str() + colon_offset + 1, msg.size() - colon_offset - 1);
    close(fd);

    ScopedTCCState tcc_state;
    TCCState* s1 = tcc_state.get();
    tcc_set_error_func(s1, this, &TinyccInstance::HandleTCCError);
    tcc_set_output_type(s1, output_type);
    tcc_add_include_path(s1, "/data/usr/include");
    tcc_add_include_path(s1, "/data/usr/lib/tcc/include");
    tcc_add_file(s1, "/tmp/input.c");
    if (output_type == TCC_OUTPUT_OBJ) {
      tcc_output_file(s1, "/tmp/out");
    }

    if (errors_.empty() && output_type == TCC_OUTPUT_MEMORY) {
      char* argv[] = {
        (char*)"./a.out", NULL
      };
      tcc_run(s1, 1, argv);
    }

    string out;

    close(1);
    close(2);

    if (errors_.empty()) {
      fd = open("/tmp/stdout.txt", O_RDONLY);
      if (fd >= 0) {
        string o;
        ReadFromFD(fd, &o);
        if (!o.empty()) {
          out += "=== STDOUT ===\n";
          out += o;
        }
      }
      fd = open("/tmp/stderr.txt", O_RDONLY);
      if (fd >= 0) {
        string o;
        ReadFromFD(fd, &o);
        if (!o.empty()) {
          out += "=== STDERR ===\n";
          out += o;
        }
      }
    } else {
      out += "=== COMPILE ERROR ===\n";
      for (size_t i = 0; i < errors_.size(); i++) {
          out += errors_[i];
          out += '\n';
      }
    }

    if (output_type == TCC_OUTPUT_OBJ) {
      int fd = open("/tmp/out", O_RDONLY);
      if (fd < 0) {
        PostMessage(pp::Var(
                      string("failed to read output: ") + strerror(errno)));
        return;
      }
      ReadFromFD(fd, &out);
      PostMessage(pp::Var(out));
      return;
    }

    PostMessage(pp::Var(out));
  }

  static void HandleTCCError(void* data, const char* msg) {
    TinyccInstance* self = (TinyccInstance*)data;
    self->errors_.push_back(msg);
  }

  void InitFileSystem() {
    PostMessageFromThread("status:DOWNLOADING DATA");
    UrlLoaderJob *job = new UrlLoaderJob;
    job->set_url("data.sar");
    std::vector<char> data;
    job->set_dst(&data);
    runner_->RunJob(job);

    PostMessageFromThread("status:WRITING DATA");
    int fd = open("/data.sar", O_CREAT | O_WRONLY);
    if (fd < 0) {
      PostMessageFromThread("status:WRITE DATA FAILED");
      return;
    }
    write(fd, &data[0], data.size());
    close(fd);

    mkdir("/tmp", 0777);
    mkdir("/data", 0777);
    chdir("/data");
    PostMessageFromThread("status:EXTRACTING DATA");
    int r = simple_tar_extract("/data.sar");
    if (r != 0) {
      PostMessageFromThread("status:EXTRACT DATA FAILED");
    }

#ifdef __x86_64__
    PostMessageFromThread("status:READY (64bit)");
#else
    PostMessageFromThread("status:READY (32bit)");
#endif
  }

private:
  class PostMessageJob : public MainThreadJob {
  public:
    PostMessageJob(const string& msg) : msg_(msg) {}
    virtual ~PostMessageJob() {}
    virtual void Run(MainThreadRunner::JobEntry* entry) {
      pp::Instance* self = MainThreadRunner::ExtractPepperInstance(entry);
      self->PostMessage(pp::Var(msg_));
      MainThreadRunner::ResultCompletion(entry, 0);
    }
  private:
    string msg_;
  };

  struct ScopedTCCState {
    ScopedTCCState() {
      s1_ = tcc_new();
    }
    ~ScopedTCCState() {
      tcc_delete(s1_);
    }
    TCCState* get() {
      return s1_;
    }
  private:
    TCCState* s1_;
  };

  void PostMessageFromThread(const string& msg) {
    PostMessageJob* job = new PostMessageJob(msg);
    runner_->RunJob(job);
  }

  static void ReadFromFD(int fd, string* out) {
    off_t size = lseek(fd, 0, SEEK_END);
    lseek(fd, 0, SEEK_SET);
    char* buf = (char*)malloc(size + 1);
    buf[size] = '\0';
    read(fd, buf, size);
    close(fd);
    *out = buf;
    free(buf);
  }

  static string ReadFromFile(const char* file) {
    int fd = open(file, O_RDONLY);
    string s;
    ReadFromFD(fd, &s);
    return s;
  }

  auto_ptr<MainThreadRunner> runner_;
  auto_ptr<MemMount> mount_;
  vector<string> errors_;
};

void* InitFileSystemThread(void* data) {
  TinyccInstance* self = (TinyccInstance*)data;
  self->InitFileSystem();
  return NULL;
}

/// The Module class.  The browser calls the CreateInstance() method to create
/// an instance of your NaCl module on the web page.  The browser creates a new
/// instance for each <embed> tag with type="application/x-nacl".
class TinyccModule : public pp::Module {
 public:
  TinyccModule() : pp::Module() {}
  virtual ~TinyccModule() {}

  /// Create and return a TinyccInstance object.
  /// @param[in] instance The browser-side instance.
  /// @return the plugin-side instance.
  virtual pp::Instance* CreateInstance(PP_Instance instance) {
    return new TinyccInstance(instance);
  }
};

namespace pp {
/// Factory function called by the browser when the module is first loaded.
/// The browser keeps a singleton of this module.  It calls the
/// CreateInstance() method on the object you return to make instances.  There
/// is one instance per <embed> tag on the page.  This is the main binding
/// point for your NaCl module with the browser.
Module* CreateModule() {
  return new TinyccModule();
}
}  // namespace pp
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/cache/p9_hcd_l2_stopclocks.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file  p9_hcd_l2_stopclocks.C
/// @brief Quad Clock Stop
///
/// Procedure Summary:

// *HWP HWP Owner          : David Du       <daviddu@us.ibm.com>
// *HWP Backup HWP Owner   : Greg Still     <stillgs@us.ibm.com>
// *HWP FW Owner           : Sangeetha T S  <sangeet2@in.ibm.com>
// *HWP Team               : PM
// *HWP Consumed by        : HB:PERV
// *HWP Level              : 2

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------

#include <p9_misc_scom_addresses.H>
#include <p9_quad_scom_addresses.H>
#include <p9_hcd_common.H>
#include "p9_hcd_l2_stopclocks.H"

//------------------------------------------------------------------------------
// Constant Definitions
//------------------------------------------------------------------------------

enum P9_HCD_L2_STOPCLOCKS_CONSTANTS
{
    L2_CLK_SYNC_TIMEOUT_IN_MS = 1,
    L2_CLK_STOP_TIMEOUT_IN_MS = 1
};

//------------------------------------------------------------------------------
// Procedure: Quad Clock Stop
//------------------------------------------------------------------------------

fapi2::ReturnCode
p9_hcd_l2_stopclocks(
    const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target,
    const p9hcd::P9_HCD_EX_CTRL_CONSTANTS       i_select_ex)
{
    FAPI_INF(">>p9_hcd_l2_stopclocks: ex[%d]",  i_select_ex);
    fapi2::buffer<uint64_t>                     l_data64;
    uint32_t                                    l_timeout;
    uint64_t                                    l_region_clock = 0;
    uint64_t                                    l_l2sync_clock = 0;
    uint64_t                                    l_l2mask_pscom = 0;
    uint8_t                                     l_attr_chip_unit_pos = 0;
    auto l_perv = i_target.getParent<fapi2::TARGET_TYPE_PERV>();
    auto l_chip = i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_perv,
                           l_attr_chip_unit_pos));
    l_attr_chip_unit_pos = l_attr_chip_unit_pos - p9hcd::PERV_TO_QUAD_POS_OFFSET;

    if (i_select_ex & p9hcd::EVEN_EX)
    {
        l_region_clock |= p9hcd::CLK_REGION_EX0_L2;
        l_l2sync_clock |= BIT64(36);
        l_l2mask_pscom |= BIT64(2) | BIT64(10);
    }

    if (i_select_ex & p9hcd::ODD_EX)
    {
        l_region_clock |= p9hcd::CLK_REGION_EX1_L2;
        l_l2sync_clock |= BIT64(37);
        l_l2mask_pscom |= BIT64(3) | BIT64(11);
    }

    // -------------------------
    // Prepare to stop L2 clocks
    // -------------------------

    FAPI_DBG("Assert L2 pscom masks via RING_FENCE_MASK_LATCH_REG[2/3,10/11]");
    FAPI_TRY(putScom(i_target, EQ_RING_FENCE_MASK_LATCH_REG, l_l2mask_pscom));

    // -------------------------------
    // Stop L2 clocks
    // -------------------------------

    FAPI_DBG("Clear all SCAN_REGION_TYPE bits");
    FAPI_TRY(putScom(i_target, EQ_SCAN_REGION_TYPE, MASK_ZERO));

    FAPI_DBG("Stop L2 clocks via CLK_REGION");
    l_data64 = (p9hcd::CLK_STOP_CMD           |
                l_region_clock                |
                p9hcd::CLK_THOLD_ALL);
    FAPI_TRY(putScom(i_target, EQ_CLK_REGION, l_data64));

    FAPI_DBG("Poll for L2 clocks stopped via CPLT_STAT0[8]");
    l_timeout = (p9hcd::CYCLES_PER_MS / p9hcd::INSTS_PER_POLL_LOOP) *
                L2_CLK_STOP_TIMEOUT_IN_MS;

    do
    {
        FAPI_TRY(getScom(i_target, EQ_CPLT_STAT0, l_data64));
    }
    while((l_data64.getBit<8>() != 1) && ((--l_timeout) != 0));

    FAPI_ASSERT((l_timeout != 0),
                fapi2::PMPROC_L2CLKSTOP_TIMEOUT()
                .set_EQ_TARGET(i_target)
                .set_EQCPLTSTAT(l_data64),
                "L2 Clock Stop Timeout");

    FAPI_DBG("Check L2 clocks stopped");
    FAPI_TRY(getScom(i_target, EQ_CLOCK_STAT_SL, l_data64));

    FAPI_ASSERT((((~l_data64) & l_region_clock) == 0),
                fapi2::PMPROC_L2CLKSTOP_FAILED()
                .set_EQ_TARGET(i_target)
                .set_EQCLKSTAT(l_data64),
                "L2 Clock Stop Failed");
    FAPI_DBG("L2 clocks stopped now");

    // -------------------------------
    // Disable L2 clock sync
    // -------------------------------

    FAPI_DBG("Drop L2 clock sync enables via QPPM_EXCGCR[36,37]");
    FAPI_TRY(putScom(i_target, EQ_QPPM_EXCGCR_CLEAR, l_l2sync_clock));

    FAPI_DBG("Poll for L2 clock sync dones to drop via QPPM_QACSR[36,37]");
    l_timeout = (p9hcd::CYCLES_PER_MS / p9hcd::INSTS_PER_POLL_LOOP) *
                L2_CLK_SYNC_TIMEOUT_IN_MS;

    do
    {
        FAPI_TRY(getScom(i_target, EQ_QPPM_QACSR, l_data64));
    }
    while(((l_data64 & l_l2sync_clock)) && ((--l_timeout) != 0));

    FAPI_ASSERT((l_timeout != 0),
                fapi2::PMPROC_CACHECLKSYNCDROP_TIMEOUT().set_EQPPMQACSR(l_data64),
                "L2 Clock Sync Drop Timeout");
    FAPI_DBG("L2 clock sync dones dropped");

    // -------------------------------
    // Fence up
    // -------------------------------

    FAPI_DBG("Assert regional fences via CPLT_CTRL1[8/9]");
    FAPI_TRY(putScom(i_target, EQ_CPLT_CTRL1_OR, l_region_clock));

    // -------------------------------
    // Update QSSR
    // -------------------------------

    FAPI_DBG("Set EX as stopped in QSSR");
    FAPI_TRY(putScom(l_chip, PU_OCB_OCI_QSSR_OR,
                     ((uint64_t)i_select_ex << SHIFT64((l_attr_chip_unit_pos << 1) + 1))));

fapi_try_exit:

    FAPI_INF("<<p9_hcd_l2_stopclocks");
    return fapi2::current_err;
}
<commit_msg>Fix for the EKB build failure caused by hcd constant<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/cache/p9_hcd_l2_stopclocks.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file  p9_hcd_l2_stopclocks.C
/// @brief Quad Clock Stop
///
/// Procedure Summary:

// *HWP HWP Owner          : David Du       <daviddu@us.ibm.com>
// *HWP Backup HWP Owner   : Greg Still     <stillgs@us.ibm.com>
// *HWP FW Owner           : Sangeetha T S  <sangeet2@in.ibm.com>
// *HWP Team               : PM
// *HWP Consumed by        : HB:PERV
// *HWP Level              : 2

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------

#include <p9_misc_scom_addresses.H>
#include <p9_quad_scom_addresses.H>
#include <p9_hcd_common.H>
#include "p9_hcd_l2_stopclocks.H"

//------------------------------------------------------------------------------
// Constant Definitions
//------------------------------------------------------------------------------

enum P9_HCD_L2_STOPCLOCKS_CONSTANTS
{
    L2_CLK_SYNC_TIMEOUT_IN_MS = 1,
    L2_CLK_STOP_TIMEOUT_IN_MS = 1
};

//------------------------------------------------------------------------------
// Procedure: Quad Clock Stop
//------------------------------------------------------------------------------

fapi2::ReturnCode
p9_hcd_l2_stopclocks(
    const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target,
    const p9hcd::P9_HCD_EX_CTRL_CONSTANTS       i_select_ex)
{
    FAPI_INF(">>p9_hcd_l2_stopclocks: ex[%d]",  i_select_ex);
    fapi2::buffer<uint64_t>                     l_data64;
    uint32_t                                    l_timeout;
    uint64_t                                    l_region_clock = 0;
    uint64_t                                    l_l2sync_clock = 0;
    uint64_t                                    l_l2mask_pscom = 0;
    uint8_t                                     l_attr_chip_unit_pos = 0;
    auto l_perv = i_target.getParent<fapi2::TARGET_TYPE_PERV>();
    auto l_chip = i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_perv,
                           l_attr_chip_unit_pos));
//    l_attr_chip_unit_pos = l_attr_chip_unit_pos - p9hcd::PERV_TO_QUAD_POS_OFFSET;
    l_attr_chip_unit_pos = l_attr_chip_unit_pos - 0x10;

    if (i_select_ex & p9hcd::EVEN_EX)
    {
        l_region_clock |= p9hcd::CLK_REGION_EX0_L2;
        l_l2sync_clock |= BIT64(36);
        l_l2mask_pscom |= BIT64(2) | BIT64(10);
    }

    if (i_select_ex & p9hcd::ODD_EX)
    {
        l_region_clock |= p9hcd::CLK_REGION_EX1_L2;
        l_l2sync_clock |= BIT64(37);
        l_l2mask_pscom |= BIT64(3) | BIT64(11);
    }

    // -------------------------
    // Prepare to stop L2 clocks
    // -------------------------

    FAPI_DBG("Assert L2 pscom masks via RING_FENCE_MASK_LATCH_REG[2/3,10/11]");
    FAPI_TRY(putScom(i_target, EQ_RING_FENCE_MASK_LATCH_REG, l_l2mask_pscom));

    // -------------------------------
    // Stop L2 clocks
    // -------------------------------

    FAPI_DBG("Clear all SCAN_REGION_TYPE bits");
    FAPI_TRY(putScom(i_target, EQ_SCAN_REGION_TYPE, MASK_ZERO));

    FAPI_DBG("Stop L2 clocks via CLK_REGION");
    l_data64 = (p9hcd::CLK_STOP_CMD           |
                l_region_clock                |
                p9hcd::CLK_THOLD_ALL);
    FAPI_TRY(putScom(i_target, EQ_CLK_REGION, l_data64));

    FAPI_DBG("Poll for L2 clocks stopped via CPLT_STAT0[8]");
    l_timeout = (p9hcd::CYCLES_PER_MS / p9hcd::INSTS_PER_POLL_LOOP) *
                L2_CLK_STOP_TIMEOUT_IN_MS;

    do
    {
        FAPI_TRY(getScom(i_target, EQ_CPLT_STAT0, l_data64));
    }
    while((l_data64.getBit<8>() != 1) && ((--l_timeout) != 0));

    FAPI_ASSERT((l_timeout != 0),
                fapi2::PMPROC_L2CLKSTOP_TIMEOUT()
                .set_EQ_TARGET(i_target)
                .set_EQCPLTSTAT(l_data64),
                "L2 Clock Stop Timeout");

    FAPI_DBG("Check L2 clocks stopped");
    FAPI_TRY(getScom(i_target, EQ_CLOCK_STAT_SL, l_data64));

    FAPI_ASSERT((((~l_data64) & l_region_clock) == 0),
                fapi2::PMPROC_L2CLKSTOP_FAILED()
                .set_EQ_TARGET(i_target)
                .set_EQCLKSTAT(l_data64),
                "L2 Clock Stop Failed");
    FAPI_DBG("L2 clocks stopped now");

    // -------------------------------
    // Disable L2 clock sync
    // -------------------------------

    FAPI_DBG("Drop L2 clock sync enables via QPPM_EXCGCR[36,37]");
    FAPI_TRY(putScom(i_target, EQ_QPPM_EXCGCR_CLEAR, l_l2sync_clock));

    FAPI_DBG("Poll for L2 clock sync dones to drop via QPPM_QACSR[36,37]");
    l_timeout = (p9hcd::CYCLES_PER_MS / p9hcd::INSTS_PER_POLL_LOOP) *
                L2_CLK_SYNC_TIMEOUT_IN_MS;

    do
    {
        FAPI_TRY(getScom(i_target, EQ_QPPM_QACSR, l_data64));
    }
    while(((l_data64 & l_l2sync_clock)) && ((--l_timeout) != 0));

    FAPI_ASSERT((l_timeout != 0),
                fapi2::PMPROC_CACHECLKSYNCDROP_TIMEOUT().set_EQPPMQACSR(l_data64),
                "L2 Clock Sync Drop Timeout");
    FAPI_DBG("L2 clock sync dones dropped");

    // -------------------------------
    // Fence up
    // -------------------------------

    FAPI_DBG("Assert regional fences via CPLT_CTRL1[8/9]");
    FAPI_TRY(putScom(i_target, EQ_CPLT_CTRL1_OR, l_region_clock));

    // -------------------------------
    // Update QSSR
    // -------------------------------

    FAPI_DBG("Set EX as stopped in QSSR");
    FAPI_TRY(putScom(l_chip, PU_OCB_OCI_QSSR_OR,
                     ((uint64_t)i_select_ex << SHIFT64((l_attr_chip_unit_pos << 1) + 1))));

fapi_try_exit:

    FAPI_INF("<<p9_hcd_l2_stopclocks");
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>/*

This file is part of VROOM.

Copyright (c) 2015-2017, Julien Coupey.
All rights reserved (see LICENSE).

*/

#include "tsp.h"
#include "../../structures/vroom/input/input.h"

<<<<<<< HEAD
tsp::tsp(const input& input,
         index_t vehicle_rank):
  vrp(input),
  _vehicle_rank(vehicle_rank),
  _matrix(_input._matrix),      // TODO avoid this copy!
  _symmetrized_matrix(_input._matrix.size()),
  _is_symmetric(true),
  _force_start(_input._vehicles[_vehicle_rank].has_start()),
  _force_end(_input._vehicles[_vehicle_rank].has_end()) {
  if(_force_start){
    if( _input._vehicles[_vehicle_rank].start_id != boost::none ){
      _start = _input._vehicles[_vehicle_rank].start_id.get();
    }else{
      _start = _input._vehicles[_vehicle_rank].start.get().index;
    }
    assert(_start < _matrix.size());
  }
  if(_force_end){
    if( _input._vehicles[_vehicle_rank].end_id != boost::none ){
      _end = _input._vehicles[_vehicle_rank].end_id.get();
    }else{
      _end = _input._vehicles[_vehicle_rank].end.get().index;
    }
    assert(_end < _matrix.size());
  }

  // Dealing with open tour cases. At most one of the following
  // occurs.
  if (_force_start and !_force_end) {
    // Forcing first location as start, end location decided during
    // optimization.
    for (index_t i = 0; i < _matrix.size(); ++i) {
      if (i != _start) {
        _matrix[i][_start] = 0;
      }
    }
  }
  if (!_force_start and _force_end) {
    // Forcing last location as end, start location decided during
    // optimization.
    for (index_t j = 0; j < _matrix.size(); ++j) {
      if (j != _end) {
        _matrix[_end][j] = 0;
      }
    }
  }
  if (_force_start and _force_end) {
    // Forcing first location as start, last location as end to
    // produce an open tour.
    assert(_start != _end);
    _matrix[_end][_start] = 0;
    for (index_t j = 0; j < _matrix.size(); ++j) {
      if ((j != _start) and (j != _end)) {
        _matrix[_end][j] = INFINITE_DISTANCE;
      }
    }
  }

  // Compute symmetrized matrix and update _is_symmetric flag.
  const distance_t& (*sym_f) (const distance_t&, const distance_t&) =
    std::min<distance_t>;
  if ((_force_start and !_force_end) or (!_force_start and _force_end)) {
    // Using symmetrization with max as when only start or only end is
    // forced, the matrix has a line or a column filled with zeros.
    sym_f = std::max<distance_t>;
  }
  for (index_t i = 0; i < _matrix.size(); ++i) {
    _symmetrized_matrix[i][i] = _matrix[i][i];
    for (index_t j = i + 1; j < _matrix.size(); ++j) {
      _is_symmetric &= (_matrix[i][j] == _matrix[j][i]);
      distance_t val = sym_f(_matrix[i][j], _matrix[j][i]);
      _symmetrized_matrix[i][j] = val;
      _symmetrized_matrix[j][i] = val;
    }
  }
}

distance_t tsp::cost(const std::list<index_t>& tour) const {
  distance_t cost = 0;
  index_t init_step = 0;        // Initialization actually never used.

  auto step = tour.cbegin();
  if (tour.size() > 0) {
    init_step = *step;
  }

  index_t previous_step = init_step;
  ++step;
  for (; step != tour.cend(); ++step) {
    cost += _matrix[previous_step][*step];
    previous_step = *step;
  }
  if (tour.size() > 0) {
    cost += _matrix[previous_step][init_step];
  }
  return cost;
}

distance_t tsp::symmetrized_cost(const std::list<index_t>& tour) const {
  distance_t cost = 0;
  index_t init_step = 0;        // Initialization actually never used.

  auto step = tour.cbegin();
  if (tour.size() > 0) {
    init_step = *step;
  }

  index_t previous_step = init_step;
  ++step;
  for (; step != tour.cend(); ++step) {
    cost += _symmetrized_matrix[previous_step][*step];
    previous_step = *step;
  }
  if (tour.size() > 0) {
    cost += _symmetrized_matrix[previous_step][init_step];
  }
  return cost;
}

solution tsp::solve(unsigned nb_threads) const {
  // Applying heuristic.
  auto start_heuristic = std::chrono::high_resolution_clock::now();
  BOOST_LOG_TRIVIAL(info)
    << "[Heuristic] Start heuristic on symmetrized problem.";

  std::list<index_t> christo_sol = christofides(_symmetrized_matrix);
  distance_t christo_cost = this->symmetrized_cost(christo_sol);

  auto end_heuristic = std::chrono::high_resolution_clock::now();

  auto heuristic_computing_time =
    std::chrono::duration_cast<std::chrono::milliseconds>(end_heuristic -
                                                          start_heuristic)
    .count();

  BOOST_LOG_TRIVIAL(info) << "[Heuristic] Done, took "
                          << heuristic_computing_time << " ms.";

  BOOST_LOG_TRIVIAL(info) << "[Heuristic] Symmetric solution cost is "
                          << christo_cost << ".";

  // Local search on symmetric problem.
  // Applying deterministic, fast local search to improve the current
  // solution in a small amount of time. All possible moves for the
  // different neighbourhoods are performed, stopping when reaching a
  // local minima.
  auto start_sym_local_search = std::chrono::high_resolution_clock::now();
  BOOST_LOG_TRIVIAL(info)
    << "[Local search] Start local search on symmetrized problem.";
  BOOST_LOG_TRIVIAL(info)
    << "[Local search] Using " << nb_threads << " thread(s).";

  local_search sym_ls(_symmetrized_matrix,
                      true,    // Symmetrized problem.
                      christo_sol,
                      nb_threads);

  distance_t sym_two_opt_gain = 0;
  distance_t sym_relocate_gain = 0;
  distance_t sym_or_opt_gain = 0;

  do {
    // All possible 2-opt moves.
    sym_two_opt_gain = sym_ls.perform_all_two_opt_steps();

    // All relocate moves.
    sym_relocate_gain = sym_ls.perform_all_relocate_steps();

    // All or-opt moves.
    sym_or_opt_gain = sym_ls.perform_all_or_opt_steps();
  } while ((sym_two_opt_gain > 0)
           or (sym_relocate_gain > 0)
           or (sym_or_opt_gain > 0));

  index_t first_loc_index;
  if (_force_start) {
    // Use start value set in constructor from vehicle input.
    first_loc_index = _start;
  }
  else {
    assert(_force_end);
    // Requiring the tour to be described from the "forced" end
    // location.
    first_loc_index = _end;
  }

  std::list<index_t> current_sol = sym_ls.get_tour(first_loc_index);
  auto current_cost = this->symmetrized_cost(current_sol);

  auto end_sym_local_search = std::chrono::high_resolution_clock::now();

  auto sym_local_search_duration =
    std::chrono::duration_cast<std::chrono::milliseconds>
    (end_sym_local_search - start_sym_local_search)
    .count();
  BOOST_LOG_TRIVIAL(info) << "[Local search] Done, took "
                          << sym_local_search_duration << " ms.";

  BOOST_LOG_TRIVIAL(info) << "[Local search] Symmetric solution cost is now "
                          << current_cost
                          << " ("
                          << std::fixed << std::setprecision(2)
                          << 100 *(((double) current_cost) / christo_cost - 1)
                          << "%).";

  auto asym_local_search_duration = 0;

  if (!_is_symmetric) {
    auto start_asym_local_search = std::chrono::high_resolution_clock::now();

    // Back to the asymmetric problem, picking the best way.
    std::list<index_t> reverse_current_sol(current_sol);
    reverse_current_sol.reverse();
    distance_t direct_cost = this->cost(current_sol);
    distance_t reverse_cost = this->cost(reverse_current_sol);

    // Cost reference after symmetric local search.
    distance_t sym_ls_cost = std::min(direct_cost, reverse_cost);

    // Local search on asymmetric problem.
    local_search asym_ls(_matrix,
                         false, // Not the symmetrized problem.
                         (direct_cost <= reverse_cost) ?
                         current_sol: reverse_current_sol,
                         nb_threads);

    BOOST_LOG_TRIVIAL(info)
      << "[Asym. local search] Back to asymmetric problem, initial solution cost is "
      << sym_ls_cost << ".";

    BOOST_LOG_TRIVIAL(info)
      << "[Asym. local search] Start local search on asymmetric problem.";

    BOOST_LOG_TRIVIAL(info)
      << "[Asym. local search] Using " << nb_threads << " thread(s).";

    distance_t asym_two_opt_gain = 0;
    distance_t asym_relocate_gain = 0;
    distance_t asym_or_opt_gain = 0;
    distance_t asym_avoid_loops_gain = 0;

    do {
      // All avoid-loops moves.
      asym_avoid_loops_gain = asym_ls.perform_all_avoid_loop_steps();

      // All possible 2-opt moves.
      asym_two_opt_gain = asym_ls.perform_all_asym_two_opt_steps();

      // All relocate moves.
      asym_relocate_gain = asym_ls.perform_all_relocate_steps();

      // All or-opt moves.
      asym_or_opt_gain = asym_ls.perform_all_or_opt_steps();
    } while ((asym_two_opt_gain > 0)
             or (asym_relocate_gain > 0)
             or (asym_or_opt_gain > 0)
             or (asym_avoid_loops_gain > 0));

    current_sol = asym_ls.get_tour(first_loc_index);
    current_cost = this->cost(current_sol);

    auto end_asym_local_search = std::chrono::high_resolution_clock::now();

    asym_local_search_duration =
      std::chrono::duration_cast<std::chrono::milliseconds>
      (end_asym_local_search - start_asym_local_search)
      .count();
    BOOST_LOG_TRIVIAL(info) << "[Asym. local search] Done, took "
                            << asym_local_search_duration << " ms.";

    BOOST_LOG_TRIVIAL(info)
      << "[Asym. local search] Asymmetric solution cost is now "
      << current_cost
      << " ("
      << std::fixed << std::setprecision(2)
      << 100 *(((double) current_cost) / sym_ls_cost - 1)
      << "%).";
  }

  // Deal with open tour cases requiring adaptation.
  if (!_force_start and _force_end) {
    // The tour has been listed starting with the "forced" end. This
    // index has to be popped and put back, the next element being the
    // chosen start resulting from the optimization.
    current_sol.push_back(current_sol.front());
    current_sol.pop_front();
  }

  // current_sol;

  // Steps for the one route.
  std::vector<step> steps;

  // Handle start.
  auto job_start = current_sol.cbegin();
  if (_force_start) {
    // Add start step.
    if(_input._json_matrix_provided){
      index_t start_id = _input._vehicles[_vehicle_rank].start_id.get();
      steps.emplace_back(TYPE::START,
                       _input._jobs[start_id],
                       start_id
                      );
    }else{
      steps.emplace_back(TYPE::START,
                       _input.get_location_at(current_sol.front()));
    }

    // Remember that jobs start further away in the list.
    ++job_start;
  }
  // Determine where to stop for last job.
  auto job_end = current_sol.cend();
  if (_force_end) {
    --job_end;
  }
  // Handle jobs.
  for (auto job = job_start; job != job_end; ++job) {
    auto current_rank = _input.get_job_rank_from_index(*job);
    steps.emplace_back(TYPE::JOB,
                       _input._jobs[current_rank],
                       _input._jobs[current_rank].id);
  }
  // Handle end.
  if (_force_end) {
    // Add end step.
    if(_input._json_matrix_provided){
      index_t end_id = _input._vehicles[_vehicle_rank].end_id.get();
      steps.emplace_back(TYPE::END,
                       _input._jobs[end_id],
                       end_id
                      );
    }else{
      steps.emplace_back(TYPE::END,
                         _input.get_location_at(current_sol.back()));
    }
  }

  // Route.
  std::vector<route_t> routes;
  routes.emplace_back(_input._vehicles[_vehicle_rank].id,
                      steps,
                      current_cost);

  solution sol(0, std::move(routes), current_cost);

  return sol;
}
<commit_msg>removed forgotten HEAD flag<commit_after>/*

This file is part of VROOM.

Copyright (c) 2015-2017, Julien Coupey.
All rights reserved (see LICENSE).

*/

#include "tsp.h"
#include "../../structures/vroom/input/input.h"

tsp::tsp(const input& input,
         index_t vehicle_rank):
  vrp(input),
  _vehicle_rank(vehicle_rank),
  _matrix(_input._matrix),      // TODO avoid this copy!
  _symmetrized_matrix(_input._matrix.size()),
  _is_symmetric(true),
  _force_start(_input._vehicles[_vehicle_rank].has_start()),
  _force_end(_input._vehicles[_vehicle_rank].has_end()) {
  if(_force_start){
    if( _input._vehicles[_vehicle_rank].start_id != boost::none ){
      _start = _input._vehicles[_vehicle_rank].start_id.get();
    }else{
      _start = _input._vehicles[_vehicle_rank].start.get().index;
    }
    assert(_start < _matrix.size());
  }
  if(_force_end){
    if( _input._vehicles[_vehicle_rank].end_id != boost::none ){
      _end = _input._vehicles[_vehicle_rank].end_id.get();
    }else{
      _end = _input._vehicles[_vehicle_rank].end.get().index;
    }
    assert(_end < _matrix.size());
  }

  // Dealing with open tour cases. At most one of the following
  // occurs.
  if (_force_start and !_force_end) {
    // Forcing first location as start, end location decided during
    // optimization.
    for (index_t i = 0; i < _matrix.size(); ++i) {
      if (i != _start) {
        _matrix[i][_start] = 0;
      }
    }
  }
  if (!_force_start and _force_end) {
    // Forcing last location as end, start location decided during
    // optimization.
    for (index_t j = 0; j < _matrix.size(); ++j) {
      if (j != _end) {
        _matrix[_end][j] = 0;
      }
    }
  }
  if (_force_start and _force_end) {
    // Forcing first location as start, last location as end to
    // produce an open tour.
    assert(_start != _end);
    _matrix[_end][_start] = 0;
    for (index_t j = 0; j < _matrix.size(); ++j) {
      if ((j != _start) and (j != _end)) {
        _matrix[_end][j] = INFINITE_DISTANCE;
      }
    }
  }

  // Compute symmetrized matrix and update _is_symmetric flag.
  const distance_t& (*sym_f) (const distance_t&, const distance_t&) =
    std::min<distance_t>;
  if ((_force_start and !_force_end) or (!_force_start and _force_end)) {
    // Using symmetrization with max as when only start or only end is
    // forced, the matrix has a line or a column filled with zeros.
    sym_f = std::max<distance_t>;
  }
  for (index_t i = 0; i < _matrix.size(); ++i) {
    _symmetrized_matrix[i][i] = _matrix[i][i];
    for (index_t j = i + 1; j < _matrix.size(); ++j) {
      _is_symmetric &= (_matrix[i][j] == _matrix[j][i]);
      distance_t val = sym_f(_matrix[i][j], _matrix[j][i]);
      _symmetrized_matrix[i][j] = val;
      _symmetrized_matrix[j][i] = val;
    }
  }
}

distance_t tsp::cost(const std::list<index_t>& tour) const {
  distance_t cost = 0;
  index_t init_step = 0;        // Initialization actually never used.

  auto step = tour.cbegin();
  if (tour.size() > 0) {
    init_step = *step;
  }

  index_t previous_step = init_step;
  ++step;
  for (; step != tour.cend(); ++step) {
    cost += _matrix[previous_step][*step];
    previous_step = *step;
  }
  if (tour.size() > 0) {
    cost += _matrix[previous_step][init_step];
  }
  return cost;
}

distance_t tsp::symmetrized_cost(const std::list<index_t>& tour) const {
  distance_t cost = 0;
  index_t init_step = 0;        // Initialization actually never used.

  auto step = tour.cbegin();
  if (tour.size() > 0) {
    init_step = *step;
  }

  index_t previous_step = init_step;
  ++step;
  for (; step != tour.cend(); ++step) {
    cost += _symmetrized_matrix[previous_step][*step];
    previous_step = *step;
  }
  if (tour.size() > 0) {
    cost += _symmetrized_matrix[previous_step][init_step];
  }
  return cost;
}

solution tsp::solve(unsigned nb_threads) const {
  // Applying heuristic.
  auto start_heuristic = std::chrono::high_resolution_clock::now();
  BOOST_LOG_TRIVIAL(info)
    << "[Heuristic] Start heuristic on symmetrized problem.";

  std::list<index_t> christo_sol = christofides(_symmetrized_matrix);
  distance_t christo_cost = this->symmetrized_cost(christo_sol);

  auto end_heuristic = std::chrono::high_resolution_clock::now();

  auto heuristic_computing_time =
    std::chrono::duration_cast<std::chrono::milliseconds>(end_heuristic -
                                                          start_heuristic)
    .count();

  BOOST_LOG_TRIVIAL(info) << "[Heuristic] Done, took "
                          << heuristic_computing_time << " ms.";

  BOOST_LOG_TRIVIAL(info) << "[Heuristic] Symmetric solution cost is "
                          << christo_cost << ".";

  // Local search on symmetric problem.
  // Applying deterministic, fast local search to improve the current
  // solution in a small amount of time. All possible moves for the
  // different neighbourhoods are performed, stopping when reaching a
  // local minima.
  auto start_sym_local_search = std::chrono::high_resolution_clock::now();
  BOOST_LOG_TRIVIAL(info)
    << "[Local search] Start local search on symmetrized problem.";
  BOOST_LOG_TRIVIAL(info)
    << "[Local search] Using " << nb_threads << " thread(s).";

  local_search sym_ls(_symmetrized_matrix,
                      true,    // Symmetrized problem.
                      christo_sol,
                      nb_threads);

  distance_t sym_two_opt_gain = 0;
  distance_t sym_relocate_gain = 0;
  distance_t sym_or_opt_gain = 0;

  do {
    // All possible 2-opt moves.
    sym_two_opt_gain = sym_ls.perform_all_two_opt_steps();

    // All relocate moves.
    sym_relocate_gain = sym_ls.perform_all_relocate_steps();

    // All or-opt moves.
    sym_or_opt_gain = sym_ls.perform_all_or_opt_steps();
  } while ((sym_two_opt_gain > 0)
           or (sym_relocate_gain > 0)
           or (sym_or_opt_gain > 0));

  index_t first_loc_index;
  if (_force_start) {
    // Use start value set in constructor from vehicle input.
    first_loc_index = _start;
  }
  else {
    assert(_force_end);
    // Requiring the tour to be described from the "forced" end
    // location.
    first_loc_index = _end;
  }

  std::list<index_t> current_sol = sym_ls.get_tour(first_loc_index);
  auto current_cost = this->symmetrized_cost(current_sol);

  auto end_sym_local_search = std::chrono::high_resolution_clock::now();

  auto sym_local_search_duration =
    std::chrono::duration_cast<std::chrono::milliseconds>
    (end_sym_local_search - start_sym_local_search)
    .count();
  BOOST_LOG_TRIVIAL(info) << "[Local search] Done, took "
                          << sym_local_search_duration << " ms.";

  BOOST_LOG_TRIVIAL(info) << "[Local search] Symmetric solution cost is now "
                          << current_cost
                          << " ("
                          << std::fixed << std::setprecision(2)
                          << 100 *(((double) current_cost) / christo_cost - 1)
                          << "%).";

  auto asym_local_search_duration = 0;

  if (!_is_symmetric) {
    auto start_asym_local_search = std::chrono::high_resolution_clock::now();

    // Back to the asymmetric problem, picking the best way.
    std::list<index_t> reverse_current_sol(current_sol);
    reverse_current_sol.reverse();
    distance_t direct_cost = this->cost(current_sol);
    distance_t reverse_cost = this->cost(reverse_current_sol);

    // Cost reference after symmetric local search.
    distance_t sym_ls_cost = std::min(direct_cost, reverse_cost);

    // Local search on asymmetric problem.
    local_search asym_ls(_matrix,
                         false, // Not the symmetrized problem.
                         (direct_cost <= reverse_cost) ?
                         current_sol: reverse_current_sol,
                         nb_threads);

    BOOST_LOG_TRIVIAL(info)
      << "[Asym. local search] Back to asymmetric problem, initial solution cost is "
      << sym_ls_cost << ".";

    BOOST_LOG_TRIVIAL(info)
      << "[Asym. local search] Start local search on asymmetric problem.";

    BOOST_LOG_TRIVIAL(info)
      << "[Asym. local search] Using " << nb_threads << " thread(s).";

    distance_t asym_two_opt_gain = 0;
    distance_t asym_relocate_gain = 0;
    distance_t asym_or_opt_gain = 0;
    distance_t asym_avoid_loops_gain = 0;

    do {
      // All avoid-loops moves.
      asym_avoid_loops_gain = asym_ls.perform_all_avoid_loop_steps();

      // All possible 2-opt moves.
      asym_two_opt_gain = asym_ls.perform_all_asym_two_opt_steps();

      // All relocate moves.
      asym_relocate_gain = asym_ls.perform_all_relocate_steps();

      // All or-opt moves.
      asym_or_opt_gain = asym_ls.perform_all_or_opt_steps();
    } while ((asym_two_opt_gain > 0)
             or (asym_relocate_gain > 0)
             or (asym_or_opt_gain > 0)
             or (asym_avoid_loops_gain > 0));

    current_sol = asym_ls.get_tour(first_loc_index);
    current_cost = this->cost(current_sol);

    auto end_asym_local_search = std::chrono::high_resolution_clock::now();

    asym_local_search_duration =
      std::chrono::duration_cast<std::chrono::milliseconds>
      (end_asym_local_search - start_asym_local_search)
      .count();
    BOOST_LOG_TRIVIAL(info) << "[Asym. local search] Done, took "
                            << asym_local_search_duration << " ms.";

    BOOST_LOG_TRIVIAL(info)
      << "[Asym. local search] Asymmetric solution cost is now "
      << current_cost
      << " ("
      << std::fixed << std::setprecision(2)
      << 100 *(((double) current_cost) / sym_ls_cost - 1)
      << "%).";
  }

  // Deal with open tour cases requiring adaptation.
  if (!_force_start and _force_end) {
    // The tour has been listed starting with the "forced" end. This
    // index has to be popped and put back, the next element being the
    // chosen start resulting from the optimization.
    current_sol.push_back(current_sol.front());
    current_sol.pop_front();
  }

  // current_sol;

  // Steps for the one route.
  std::vector<step> steps;

  // Handle start.
  auto job_start = current_sol.cbegin();
  if (_force_start) {
    // Add start step.
    if(_input._json_matrix_provided){
      index_t start_id = _input._vehicles[_vehicle_rank].start_id.get();
      steps.emplace_back(TYPE::START,
                       _input._jobs[start_id],
                       start_id
                      );
    }else{
      steps.emplace_back(TYPE::START,
                       _input.get_location_at(current_sol.front()));
    }

    // Remember that jobs start further away in the list.
    ++job_start;
  }
  // Determine where to stop for last job.
  auto job_end = current_sol.cend();
  if (_force_end) {
    --job_end;
  }
  // Handle jobs.
  for (auto job = job_start; job != job_end; ++job) {
    auto current_rank = _input.get_job_rank_from_index(*job);
    steps.emplace_back(TYPE::JOB,
                       _input._jobs[current_rank],
                       _input._jobs[current_rank].id);
  }
  // Handle end.
  if (_force_end) {
    // Add end step.
    if(_input._json_matrix_provided){
      index_t end_id = _input._vehicles[_vehicle_rank].end_id.get();
      steps.emplace_back(TYPE::END,
                       _input._jobs[end_id],
                       end_id
                      );
    }else{
      steps.emplace_back(TYPE::END,
                         _input.get_location_at(current_sol.back()));
    }
  }

  // Route.
  std::vector<route_t> routes;
  routes.emplace_back(_input._vehicles[_vehicle_rank].id,
                      steps,
                      current_cost);

  solution sol(0, std::move(routes), current_cost);

  return sol;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/zqcal.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2017,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file zqcal.C
/// @brief Subroutines to send ZQCL commands
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <vector>
#include <fapi2.H>

#include <lib/dimm/ddr4/zqcal.H>
#include <lib/dimm/ddr4/data_buffer_ddr4.H>
#include <lib/ccs/ccs.H>
#include <lib/eff_config/timing.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_DIMM;

namespace mss
{

///
/// @brief Setup DRAM ZQCL
/// Specializaton for TARGET_TYPE_DIMM
/// @param[in] i_target the target associated with this cal
/// @param[in] i_rank the current rank
/// @param[in,out] io_inst a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS iff setup was successful
///
template<>
fapi2::ReturnCode setup_dram_zqcal( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
                                    const uint64_t i_rank,
                                    std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
{
    ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst;

    uint64_t tDLLK = 0;
    FAPI_TRY( mss::tdllk(i_target, tDLLK) );

    // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
    l_inst = ccs::zqcl_command<TARGET_TYPE_MCBIST>(i_target, i_rank);

    l_inst.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
                                MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(tDLLK + mss::tzqinit());

    // There's nothing to decode here.
    FAPI_INF("ZQCL 0x%016llx:0x%016llx %s:rank %d",
             l_inst.arr0, l_inst.arr1, mss::c_str(i_target), i_rank);

    // Add both to the CCS program
    io_inst.push_back(l_inst);

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Setup LRDIMM data buffer ZQCL
/// Specializaton for TARGET_TYPE_DIMM
/// @param[in] i_target the target associated with this cal
/// @param[in,out] io_inst a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS iff setup was successful
///
template<>
fapi2::ReturnCode setup_data_buffer_zqcal( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
        std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
{
    // For LRDIMMs, program BCW to send ZQCal Long command to all data buffers
    // in broadcast mode
    uint8_t l_dimm_type = 0;
    FAPI_TRY( eff_dimm_type(i_target, l_dimm_type) );

    if( l_dimm_type != fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM )
    {
        FAPI_INF("%s Skipping LRDIMM data buffer ZQCL, only done on LRDIMMs", mss::c_str(i_target));
        return fapi2::FAPI2_RC_SUCCESS;
    }

    FAPI_TRY( ddr4::set_command_space(i_target, ddr4::command::ZQCL, io_inst) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Setup and execute DRAM ZQCL
/// Specializaton for TARGET_TYPE_MCA
/// @param[in] i_target the target associated with this cal
/// @param[in] i_cal_steps_enabled fapi2::buffer<uint16_t> representing the cal steps to enable
/// @return FAPI2_RC_SUCCESS iff setup was successful
///
template<>
fapi2::ReturnCode setup_and_execute_zqcal( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
        const fapi2::buffer<uint32_t>& i_cal_steps_enabled)
{
    mss::ccs::program<TARGET_TYPE_MCBIST> l_program;

    for ( const auto& d : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target) )
    {
        // If this bit isn't set, nothing to do here...
        if ( i_cal_steps_enabled.getBit<DRAM_ZQCAL>() )
        {
            std::vector<uint64_t> l_ranks;
            FAPI_TRY( mss::rank::ranks(d, l_ranks) );

            for( const auto& r : l_ranks)
            {
                FAPI_TRY( mss::setup_dram_zqcal(d, r, l_program.iv_instructions) );
            }// ranks
        }

        // If this bit isn't set, nothing to do here...
        if ( i_cal_steps_enabled.getBit<DB_ZQCAL>() )
        {
            FAPI_TRY( mss::setup_data_buffer_zqcal(d, l_program.iv_instructions) );
        }
    }// dimm

    // execute ZQCAL instructions
    FAPI_TRY( mss::ccs::execute(mss::find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_program, i_target) );

fapi_try_exit:
    return fapi2::current_err;
}

} // ns mss
<commit_msg>Double POR timings (tMOD, tMRD, and tZQ) for more margin per lab<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/zqcal.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2017,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file zqcal.C
/// @brief Subroutines to send ZQCL commands
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <vector>
#include <fapi2.H>

#include <lib/dimm/ddr4/zqcal.H>
#include <lib/dimm/ddr4/data_buffer_ddr4.H>
#include <lib/ccs/ccs.H>
#include <lib/eff_config/timing.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_DIMM;

namespace mss
{

///
/// @brief Setup DRAM ZQCL
/// Specializaton for TARGET_TYPE_DIMM
/// @param[in] i_target the target associated with this cal
/// @param[in] i_rank the current rank
/// @param[in,out] io_inst a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS iff setup was successful
///
template<>
fapi2::ReturnCode setup_dram_zqcal( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
                                    const uint64_t i_rank,
                                    std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
{
    ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst;

    uint64_t tDLLK = 0;
    FAPI_TRY( mss::tdllk(i_target, tDLLK) );

    // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
    l_inst = ccs::zqcl_command<TARGET_TYPE_MCBIST>(i_target, i_rank);

    // Doubling tZQ to better margin per lab request
    {
        const size_t DELAY = 2 * (tDLLK + mss::tzqinit());
        l_inst.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
                                    MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(DELAY);
    }

    // There's nothing to decode here.
    FAPI_INF("ZQCL 0x%016llx:0x%016llx %s:rank %d",
             l_inst.arr0, l_inst.arr1, mss::c_str(i_target), i_rank);

    // Add both to the CCS program
    io_inst.push_back(l_inst);

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Setup LRDIMM data buffer ZQCL
/// Specializaton for TARGET_TYPE_DIMM
/// @param[in] i_target the target associated with this cal
/// @param[in,out] io_inst a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS iff setup was successful
///
template<>
fapi2::ReturnCode setup_data_buffer_zqcal( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
        std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
{
    // For LRDIMMs, program BCW to send ZQCal Long command to all data buffers
    // in broadcast mode
    uint8_t l_dimm_type = 0;
    FAPI_TRY( eff_dimm_type(i_target, l_dimm_type) );

    if( l_dimm_type != fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM )
    {
        FAPI_INF("%s Skipping LRDIMM data buffer ZQCL, only done on LRDIMMs", mss::c_str(i_target));
        return fapi2::FAPI2_RC_SUCCESS;
    }

    FAPI_TRY( ddr4::set_command_space(i_target, ddr4::command::ZQCL, io_inst) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Setup and execute DRAM ZQCL
/// Specializaton for TARGET_TYPE_MCA
/// @param[in] i_target the target associated with this cal
/// @param[in] i_cal_steps_enabled fapi2::buffer<uint16_t> representing the cal steps to enable
/// @return FAPI2_RC_SUCCESS iff setup was successful
///
template<>
fapi2::ReturnCode setup_and_execute_zqcal( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
        const fapi2::buffer<uint32_t>& i_cal_steps_enabled)
{
    mss::ccs::program<TARGET_TYPE_MCBIST> l_program;

    for ( const auto& d : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target) )
    {
        // If this bit isn't set, nothing to do here...
        if ( i_cal_steps_enabled.getBit<DRAM_ZQCAL>() )
        {
            std::vector<uint64_t> l_ranks;
            FAPI_TRY( mss::rank::ranks(d, l_ranks) );

            for( const auto& r : l_ranks)
            {
                FAPI_TRY( mss::setup_dram_zqcal(d, r, l_program.iv_instructions) );
            }// ranks
        }

        // If this bit isn't set, nothing to do here...
        if ( i_cal_steps_enabled.getBit<DB_ZQCAL>() )
        {
            FAPI_TRY( mss::setup_data_buffer_zqcal(d, l_program.iv_instructions) );
        }
    }// dimm

    // execute ZQCAL instructions
    FAPI_TRY( mss::ccs::execute(mss::find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_program, i_target) );

fapi_try_exit:
    return fapi2::current_err;
}

} // ns mss
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_pm_recovery_ffdc_occ.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef __PM_RECOVERY_FFDC_OCC_
#define __PM_RECOVERY_FFDC_OCC_

///
/// @file   p9_pm_recovery_ffdc_occ.H
/// @brief  Models OCC platform for the FFDC collection of PM complex
///
/// *HWP HWP Owner:      Greg Still <stillgs@us.ibm.com>
/// *HWP FW Owner:       Amit Tendolkar <amit.tendolkar@in.ibm.com>
/// *HWP Team:           PM
/// *HWP Level:          2
/// *HWP Consumed by:    Hostboot
//
// *INDENT-OFF*
//--------------------------------------------------------------------------
// Includes
//--------------------------------------------------------------------------
#include <fapi2.H>
#include <stdint.h>
#include <p9_pm_recovery_ffdc_base.H>

namespace p9_stop_recov_ffdc
{

    class PlatOcc : public PlatPmComplex
    {
            public:
            /// @brief  constructor
            PlatOcc ( const fapi2::Target <fapi2::TARGET_TYPE_PROC_CHIP>
                      i_procChipTgt );

            /// @brief  destructor
            virtual ~PlatOcc() { };

            /// @brief      collects FFDC of the OCC 405, GPE0 and GPE1.
            /// @param[in]  i_pHomerBuf     points to base of P9 HOMER.
            /// @return     fapi2 return code.
            fapi2::ReturnCode collectFfdc( void* i_pHomerBuf );

        private:
            /// @brief      collects trace info from OCC SRAM buffer.
            /// @param[in]  i_pHomerBuf     location in HOMER to write at
            /// @param[in]  i_sramAddress   location in OCC SRAM to read from
            /// @return     fapi2 return code.
            fapi2::ReturnCode  collectTrace( uint8_t * i_pHomerBuf,
                                             uint32_t  i_sramAddress );

            /// @brief updates the OCC FFDC Header
            /// @param[in]   i_pHomerBuf points to a location in HOMER meant for
            ///                          OCC FFDC Header
            ///@param[in]   i_ffdcValid  Indicates what fields in OCC FFDC are
            ///                          valid. See OccFfdcValidStatus
            ///@return      fapi2 return code.
            fapi2::ReturnCode updateOccFfdcHeader ( uint8_t* i_pHomerBuf,
                                                    uint8_t  i_ffdcValid );
    };

extern "C"
{
    typedef fapi2::ReturnCode( *p9_pm_recovery_ffdc_occ_FP_t )
            ( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_procChipTgt,
              void* i_occFfdcBuf );
}

} //namespace p9_stop_recov_ffdc ends

#endif //__PM_RECOVERY_FFDC_OCC_
<commit_msg>STOP Recovery: Misc infra. updates to enable PM FFDC in HOMER<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_pm_recovery_ffdc_occ.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef __PM_RECOVERY_FFDC_OCC_
#define __PM_RECOVERY_FFDC_OCC_

///
/// @file   p9_pm_recovery_ffdc_occ.H
/// @brief  Models OCC platform for the FFDC collection of PM complex
///
/// *HWP HWP Owner:      Greg Still <stillgs@us.ibm.com>
/// *HWP FW Owner:       Amit Tendolkar <amit.tendolkar@in.ibm.com>
/// *HWP Team:           PM
/// *HWP Level:          2
/// *HWP Consumed by:    Hostboot
//
// *INDENT-OFF*
//--------------------------------------------------------------------------
// Includes
//--------------------------------------------------------------------------
#include <fapi2.H>
#include <stdint.h>
#include <p9_pm_recovery_ffdc_base.H>

namespace p9_stop_recov_ffdc
{

    class PlatOcc : public PlatPmComplex
    {
            public:
            /// @brief  constructor
            PlatOcc ( const fapi2::Target <fapi2::TARGET_TYPE_PROC_CHIP>
                      i_procChipTgt );

            /// @brief  destructor
            virtual ~PlatOcc() { };

            /// @brief      Initializes the OCC FFDC Sub-Sections in HOMER with default header
            /// @param[in]  i_pHomerBuf  points to base of P9 HOMER.
            ///  @return    fapi2 return code
            fapi2::ReturnCode init ( void* i_pHomerBuf );

            /// @brief      collects FFDC of the OCC 405, GPE0 and GPE1.
            /// @param[in]  i_pHomerBuf  points to base of P9 HOMER.
            /// @param[in]  i_ffdcType   indicates the content type to collect
            /// @return     fapi2 return code.
            fapi2::ReturnCode collectFfdc ( void*   i_pHomerBuf,
                                            uint8_t i_ffdcType = ALL );

        private:
            /// @brief      collects trace info from a known region OCC SRAM
            /// @param[in]  i_pHomerBuf     location in HOMER to write at
            /// @param[in]  i_occSramRegion See OccFfdcValidStatus,
            ///                             Indicates OCC SRAM Region to read
            /// @return     fapi2 return code.
            fapi2::ReturnCode  collectTrace( uint8_t* i_pHomerBuf,
                                             uint8_t  i_occSramRegion );

            /// @brief      reads OCC SRAM to find out the region extent and
            ///             then collects info from that region
            /// @param[in]  i_pHomerBuf     location in HOMER to write at
            /// @param[in]  i_occSramRegion See OccFfdcValidStatus.
            ///                             Indicates OCC SRAM Region to read
            /// @return     fapi2 return code.
            fapi2::ReturnCode readSramRegion ( uint8_t* i_pHomerBuf,
                                               uint8_t i_occSramRegion );

            /// @brief updates the OCC FFDC Header
            /// @param[in]   i_pHomerBuf points to a location in HOMER meant for
            ///                          OCC FFDC Header
            ///@param[in]   i_ffdcValid  Indicates what fields in OCC FFDC are
            ///                          valid. See OccFfdcValidStatus
            ///@return      fapi2 return code.
            fapi2::ReturnCode updateOccFfdcHeader ( uint8_t* i_pHomerBuf,
                                                    uint16_t  i_ffdcValid );

            /// @brief      collects register info for a given OCC
            /// @param[in]  i_pHomerBuf     points to location of HOMER meant for OCC internal register.
            ///@return      fapi2 return code.
            fapi2::ReturnCode  collectOccReg( uint8_t * i_pHomerBuf);

    };

extern "C"
{
    typedef fapi2::ReturnCode( *p9_pm_recovery_ffdc_occ_FP_t )
            ( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> & i_procChipTgt,
              void* i_occFfdcBuf );
}

} //namespace p9_stop_recov_ffdc ends

#endif //__PM_RECOVERY_FFDC_OCC_
<|endoftext|>


<commit_before><commit_msg>Replace gmock's EXPECT_THAT by an explicit check when comparing proxy config in PrefProxyConfigServiceTest.Fallback. This should avoid having gtest print the objects, which results in uninitialized memory accesses.<commit_after><|endoftext|>


<commit_before>#include <string>
#include <vector>

#include "lms/argumenthandler.h"
#include "lms/extra/os.h"
#include "lms/extra/string.h"

#include "tclap/CmdLine.h"

namespace lms {

bool runLevelByName(const std::string &str, RunLevel &runLevel) {
    if (str == "CONFIG" || str == "0") {
        runLevel = RunLevel::CONFIG;
        return true;
    } else if (str == "ENABLE" || str == "1") {
        runLevel = RunLevel::ENABLE;
        return true;
    } else if (str == "CYCLE" || str == "2") {
        runLevel = RunLevel::CYCLE;
        return true;
    }

    return false;
}

std::ostream& operator << (std::ostream &out, RunLevel runLevel) {
    switch(runLevel) {
    case RunLevel::CONFIG:
        out << "CONFIG";
        break;
    case RunLevel::ENABLE:
        out << "ENABLE";
        break;
    case RunLevel::CYCLE:
        out << "CYCLE";
        break;
    }
    return out;
}

ArgumentHandler::ArgumentHandler() : argLoadConfiguration(""),
    argRunLevel(RunLevel::CYCLE),
    argLoggingMinLevel(logging::Level::ALL), argQuiet(false), argUser(""),
    argProfiling(false), argConfigMonitor(false), argMultithreaded(false),
    argThreadsAuto(false), argThreads(1) {

    argUser = lms::extra::username();
}

void ArgumentHandler::parseArguments(int argc, char* const*argv) {
#ifdef _WIN32
#define USER_ENV "$USERNAME on Windows"
#elif __APPLE__
#define USER_ENV "$USER on OSX"
#else
#define USER_ENV "$LOGNAME on Unix"
#endif
    std::vector<std::string> debugLevels = {"DEBUG", "INFO", "WARN", "ERROR"};
    TCLAP::ValuesConstraint<std::string> debugConstraint(debugLevels);

    std::vector<std::string> runLevels = {"0", "1", "2", "CONFIG", "ENABLE",
                                          "CYCLE"};
    TCLAP::ValuesConstraint<std::string> runLevelsConstraint(runLevels);

    ThreadsConstraint threadsConstraint;

    TCLAP::CmdLine cmd("LMS - Lightweight Modular System", ' ', "1.0");
    TCLAP::ValueArg<std::string> runLevelArg("r", "run-level",
        "Execute until a certain run level",
        false, "CYCLE", &runLevelsConstraint, cmd);
    TCLAP::ValueArg<std::string> loggingMinLevelArg("", "logging-min-level",
        "Filter logging by minimum logging level",
        false, "DEBUG", &debugConstraint, cmd);
    TCLAP::MultiArg<std::string> loggingPrefixArg("", "logging-prefix",
        "Filter logging by prefix of logging tags",
        false, "string", cmd);
    TCLAP::ValueArg<std::string> userArg("", "user",
        "Set the username, used for config loading, defaults to " USER_ENV,
        false, lms::extra::username(), "string", cmd);
    TCLAP::ValueArg<std::string> configArg("c", "config",
        "Load XML configuration file",
        false, "framework_conf", "string", cmd);
    TCLAP::ValueArg<std::string> logFileArg("", "log-file",
        "Log to the given file",
        false, "", "path", cmd);
    TCLAP::SwitchArg quietSwitch("q", "quiet",
        "Do not log anything to stdout",
        cmd, false);
    TCLAP::ValueArg<std::string> flagsArg("", "flags",
        "Config flags, can be used in <if> tags",
        false, "", "string-list", cmd);
    TCLAP::SwitchArg profilingSwitch("", "profiling",
        "Measure execution time of all modules",
        cmd, false);
    TCLAP::SwitchArg configMonitorSwitch("", "config-monitor",
        "Enable live config monitoring",
        cmd, false);
    TCLAP::ValueArg<std::string> threadsArg("", "threads",
        "Enable multithreading, number of threads or auto",
        false, "", &threadsConstraint, cmd);

    cmd.parse(argc, argv);

    argLoadConfiguration = configArg.getValue();
    logging::levelFromName(loggingMinLevelArg.getValue(), argLoggingMinLevel);
    argLoggingPrefixes = loggingPrefixArg.getValue();
    argUser = userArg.getValue();
    argLogFile = logFileArg.getValue();
    argQuiet = quietSwitch.getValue();
    argFlags = lms::extra::split(flagsArg.getValue(), ',');
    argProfiling = profilingSwitch.getValue();
    argConfigMonitor = configMonitorSwitch.getValue();
    runLevelByName(runLevelArg.getValue(), argRunLevel);
    if(threadsArg.isSet()) {
        argMultithreaded = true;
        if(threadsArg.getValue() == std::string("auto")) {
            argThreadsAuto = true;
        } else {
            argThreads = atoi(threadsArg.getValue().c_str());
        }
    }
#undef USER_ENV
}

}  // namespace lms
<commit_msg>Rename --logging-min-level -> --logging-threshold<commit_after>#include <string>
#include <vector>

#include "lms/argumenthandler.h"
#include "lms/extra/os.h"
#include "lms/extra/string.h"

#include "tclap/CmdLine.h"

namespace lms {

bool runLevelByName(const std::string &str, RunLevel &runLevel) {
    if (str == "CONFIG" || str == "0") {
        runLevel = RunLevel::CONFIG;
        return true;
    } else if (str == "ENABLE" || str == "1") {
        runLevel = RunLevel::ENABLE;
        return true;
    } else if (str == "CYCLE" || str == "2") {
        runLevel = RunLevel::CYCLE;
        return true;
    }

    return false;
}

std::ostream& operator << (std::ostream &out, RunLevel runLevel) {
    switch(runLevel) {
    case RunLevel::CONFIG:
        out << "CONFIG";
        break;
    case RunLevel::ENABLE:
        out << "ENABLE";
        break;
    case RunLevel::CYCLE:
        out << "CYCLE";
        break;
    }
    return out;
}

ArgumentHandler::ArgumentHandler() : argLoadConfiguration(""),
    argRunLevel(RunLevel::CYCLE),
    argLoggingMinLevel(logging::Level::ALL), argQuiet(false), argUser(""),
    argProfiling(false), argConfigMonitor(false), argMultithreaded(false),
    argThreadsAuto(false), argThreads(1) {

    argUser = lms::extra::username();
}

void ArgumentHandler::parseArguments(int argc, char* const*argv) {
#ifdef _WIN32
#define USER_ENV "$USERNAME on Windows"
#elif __APPLE__
#define USER_ENV "$USER on OSX"
#else
#define USER_ENV "$LOGNAME on Unix"
#endif
    std::vector<std::string> debugLevels = {"ALL", "DEBUG", "INFO", "WARN",
                                            "ERROR", "OFF"};
    TCLAP::ValuesConstraint<std::string> debugConstraint(debugLevels);

    std::vector<std::string> runLevels = {"0", "1", "2", "CONFIG", "ENABLE",
                                          "CYCLE"};
    TCLAP::ValuesConstraint<std::string> runLevelsConstraint(runLevels);

    ThreadsConstraint threadsConstraint;

    TCLAP::CmdLine cmd("LMS - Lightweight Modular System", ' ', "1.0");
    TCLAP::ValueArg<std::string> runLevelArg("r", "run-level",
        "Execute until a certain run level",
        false, "CYCLE", &runLevelsConstraint, cmd);
    TCLAP::ValueArg<std::string> loggingMinLevelArg("", "logging-threshold",
        "Filter logging by minimum logging level",
        false, "ALL", &debugConstraint, cmd);
    TCLAP::MultiArg<std::string> loggingPrefixArg("", "logging-prefix",
        "Filter logging by prefix of logging tags",
        false, "string", cmd);
    TCLAP::ValueArg<std::string> userArg("", "user",
        "Set the username, used for config loading, defaults to " USER_ENV,
        false, lms::extra::username(), "string", cmd);
    TCLAP::ValueArg<std::string> configArg("c", "config",
        "Load XML configuration file",
        false, "framework_conf", "string", cmd);
    TCLAP::ValueArg<std::string> logFileArg("", "log-file",
        "Log to the given file",
        false, "", "path", cmd);
    TCLAP::SwitchArg quietSwitch("q", "quiet",
        "Do not log anything to stdout",
        cmd, false);
    TCLAP::ValueArg<std::string> flagsArg("", "flags",
        "Config flags, can be used in <if> tags",
        false, "", "string-list", cmd);
    TCLAP::SwitchArg profilingSwitch("", "profiling",
        "Measure execution time of all modules",
        cmd, false);
    TCLAP::SwitchArg configMonitorSwitch("", "config-monitor",
        "Enable live config monitoring",
        cmd, false);
    TCLAP::ValueArg<std::string> threadsArg("", "threads",
        "Enable multithreading, number of threads or auto",
        false, "", &threadsConstraint, cmd);

    cmd.parse(argc, argv);

    argLoadConfiguration = configArg.getValue();
    logging::levelFromName(loggingMinLevelArg.getValue(), argLoggingMinLevel);
    argLoggingPrefixes = loggingPrefixArg.getValue();
    argUser = userArg.getValue();
    argLogFile = logFileArg.getValue();
    argQuiet = quietSwitch.getValue();
    argFlags = lms::extra::split(flagsArg.getValue(), ',');
    argProfiling = profilingSwitch.getValue();
    argConfigMonitor = configMonitorSwitch.getValue();
    runLevelByName(runLevelArg.getValue(), argRunLevel);
    if(threadsArg.isSet()) {
        argMultithreaded = true;
        if(threadsArg.getValue() == std::string("auto")) {
            argThreadsAuto = true;
        } else {
            argThreads = atoi(threadsArg.getValue().c_str());
        }
    }
#undef USER_ENV
}

}  // namespace lms
<|endoftext|>