<commit_before>#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <set>
#include <cstdint>
#include <getopt.h>
#include <cmath>
#include <boost/version.hpp>
#include <cstdio>
#include <iomanip>
#include <ctime>
#include <chrono>
#include <memory>
#include <cassert>

#include "common.h"
#include "request.h"
#include "fifo.h"
#include "shadowlru.h"
#include "shadowslab.h"
#include "partslab.h"
#include "lsm.h"
#include "lru.h"
#include "slab.h"
#include "mc.h"

namespace ch = std::chrono;
typedef ch::high_resolution_clock hrc;

const char* policy_names[7] = { "shadowlru"
                              , "fifo"
                              , "lru"
															, "slab"
                              , "shadowslab"
                              , "partslab"
                              , "lsm"
                              };
enum pol_typ {
    SHADOWLRU = 0
  , FIFO
  , LRU
  , SLAB
  , SHADOWSLAB
  , PARTSLAB
  , LSM };

// globals
size_t                appid;                           // app to consider
bool                  all_apps = true;                  // run all by default
bool                  roundup  = false;                 // no rounding default
float                 lsm_util = 1.0;                   // default util factor
std::string           trace    = "data/m.cap.out";      // default filepath
std::string           app_str;                          // for logging apps
double                hit_start_time = 86400;           // default time
size_t                global_mem = 0;
pol_typ               p_type;                           // policy type
bool                  verbose = false;
double                gfactor = 1.25;                   // def slab growth fact
bool                  memcachier_classes = false;
size_t                partitions = 2;
size_t                segment_size = 8 * 1024 * 1024;

// Only parse this many requests from the CSV file before breaking.
// Helpful for limiting runtime when playing around.
int request_limit = 0;

#ifdef DEBUG
  bool debug = true;
#else
  bool debug = false;
#endif

const std::string     usage  = "-f    specify file path\n"
                               "-a    specify app to eval\n"
                               "-r    enable rounding\n"
                               "-u    specify utilization\n"
                               "-w    specify warmup period\n"
                               "-l    number of requests after warmup\n"
                               "-s    simulated cache size in bytes\n"
                               "-p    policy 0, 1, 2; shadowlru, fifo, lru\n"
                               "-v    incremental output\n"
                               "-g    specify slab growth factor\n"
                               "-M    use memcachier slab classes\n"
                               "-P    number of partitions for partslab\n"
                               "-S    segment size in bytes for lsm\n";

// memcachier slab allocations at t=86400 (24 hours)
const int orig_alloc[15] = {
  1664, 2304, 512, 17408, 266240, 16384, 73728, 188416, 442368,
  3932160, 11665408, 34340864, 262144, 0 , 0
};

// returns true if an ID is in the spec'd set
// returns true if set is empty
// bool valid_id(const request *r) {
//  if (all_apps)
//    return true;
//  else
//    return apps.count(r->appid);
//}

int main(int argc, char *argv[]) {

  // just checking boost
  std::cerr << "Using Boost "
            << BOOST_VERSION / 100000     << "."  // major version
            << BOOST_VERSION / 100 % 1000 << "."  // minor version
            << BOOST_VERSION % 100                // patch level
            << std::endl;

  // calculate global memory
  for (int i = 0; i < 15; i++)
    global_mem += orig_alloc[i];
  global_mem *= lsm_util;

  // parse cmd args
  int c;
  std::string sets;
  while ((c = getopt(argc, argv, "p:s:l:f:a:ru:w:vhg:MP:S:")) != -1) {
    switch (c)
    {
      case 'f':
        trace = optarg;
        break;
      case 'p':
        p_type = pol_typ(atoi(optarg));
        break;
      case 's':
        global_mem = atol(optarg);
        break;
      case 'S':
        segment_size = atol(optarg);
        break;
      case 'l':
        request_limit = atoi(optarg);
        break;
      case 'a':
        {
          appid = atoi(optarg);
          break;
        }
      case 'r':
        roundup = true;
        break;
      case 'u':
        lsm_util = atof(optarg);
        break;
      case 'w':
        hit_start_time = atof(optarg);
        break;
      case 'v':
        verbose = true;
        break;
      case 'h':
        std::cerr << usage << std::endl;
        break;
      case 'g':
        gfactor = atof(optarg);
        break;
      case 'M':
        memcachier_classes = true;
        break;
      case 'P':
        partitions = atoi(optarg);
        break;
    }
  }

  //assert(apps.size() == 1);

  std::string filename_suffix = "-app" + std::to_string(appid);

  // build a stats struct with basic info relevant to every policy.
  stats sts{filename_suffix, policy_names[p_type], appid, global_mem};

  printf("APPID: %lu\n", appid);

  // instantiate a policy
  std::unique_ptr<policy> policy{};
  switch(p_type) {
    case SHADOWLRU:
      policy.reset(new shadowlru(sts));
      break;
    case FIFO :
      policy.reset(new fifo(sts));
      break;
    case LRU :
      sts.filename_suffix += "-size";
      sts.filename_suffix += std::to_string(global_mem / (1u << 20));
      sts.filename_suffix += "MB";
      policy.reset(new lru(sts));
      break;
    case SLAB :
      sts.filename_suffix += memcachier_classes ? "-memcachier" : "-memcached";
      sts.gfactor = gfactor;
      sts.memcachier_classes = memcachier_classes;
      policy.reset(new slab(sts));
      break;
    case SHADOWSLAB:
      sts.filename_suffix += memcachier_classes ? "-memcachier" : "-memcached";
      sts.memcachier_classes = memcachier_classes;
      sts.gfactor = gfactor;
      policy.reset(new shadowslab(sts));
    case PARTSLAB:
      sts.filename_suffix += "-partitions";
      sts.filename_suffix += std::to_string(partitions);
      sts.partitions = partitions;
      policy.reset(new partslab(sts));
      break;
    case LSM:
      sts.filename_suffix += "-size";
      sts.filename_suffix += std::to_string(global_mem / (1u << 20));
      sts.filename_suffix += "MB";
      sts.segment_size    = segment_size;
      sts.cleaning_width  = 4;
      policy.reset(new lsm(sts));
      break;
  }

   if (!policy) {
    std::cerr << "No valid policy selected!" << std::endl;
    exit(-1);
  }

  // List input parameters
  std::cerr << "performing trace analysis on apps: " << app_str << std::endl
            << "policy: " << policy_names[p_type] << std::endl
            << "using trace file: " << trace << std::endl
            << "rounding: " << (roundup ? "on" : "off") << std::endl
            << "utilization rate: " << lsm_util << std::endl
            << "start counting hits at t = " << hit_start_time << std::endl
            << "request limit: " << request_limit << std::endl
            << "global mem: " << global_mem << std::endl;
  if (p_type == SHADOWSLAB) {
    if (memcachier_classes)
      std::cerr << "slab growth factor: memcachier" << std::endl;
    else
      std::cerr << "slab growth factor: " << gfactor << std::endl;
  }

  // proc file line by line
  std::ifstream t_stream(trace);
  assert(t_stream.is_open());
  std::string line;

  int i = 0;
  auto start = hrc::now();
  auto last_progress = start;
  size_t bytes = 0;

  while (std::getline(t_stream, line) &&
         (request_limit == 0 || i < request_limit))
  {
    request r{line};
    bytes += line.size();

    if (verbose && ((i & ((1 << 18) - 1)) == 0)) {
      auto now  = hrc::now();
      double seconds =
        ch::duration_cast<ch::nanoseconds>(now - last_progress).count() / 1e9;
      if (seconds > 1.0) {
        stats stats = policy->get_stats();
        std::cerr << "Progress: " << r.time << " "
                  << "Rate: " << bytes / (1 << 20) / seconds << " MB/s "
                  << "Hit Rate: " << stats.get_hit_rate() * 100 << "% "
                  << "Evicted Items: " << stats.evicted_items << " "
                  << "Evicted Bytes: " << stats.evicted_bytes << " "
                  << "Utilization: " << stats.get_utilization()
                  << std::endl;
        bytes = 0;
        last_progress = now;
      }
    }

    // Only process requests for specified app, of type GET,
    // and values of size > 0, after time 'hit_start_time'.
    if ((r.type != request::GET) || (r.appid != appid) || (r.val_sz <= 0))
      continue;

    policy->proc(&r, r.time < hit_start_time);

    ++i;
  }
  auto stop = hrc::now();

  // Log curves for shadowlru, shadowslab, and partslab.
  if(p_type == 0 || p_type == 4 || p_type == 5)
    policy->log_curves();

  // Dump stats for all policies.
  policy->dump_stats();

  double seconds =
    ch::duration_cast<ch::milliseconds>(stop - start).count() / 1000.;
  std::cerr << "total execution time: " << seconds << std::endl;

  return 0;
}

<commit_msg>#9 added ability to take policy name from the comand line instead of just an integer<commit_after>#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <set>
#include <cstdint>
#include <getopt.h>
#include <cmath>
#include <boost/version.hpp>
#include <cstdio>
#include <iomanip>
#include <ctime>
#include <chrono>
#include <memory>
#include <cassert>

#include "common.h"
#include "request.h"
#include "fifo.h"
#include "shadowlru.h"
#include "shadowslab.h"
#include "partslab.h"
#include "lsm.h"
#include "lru.h"
#include "slab.h"
#include "mc.h"

namespace ch = std::chrono;
typedef ch::high_resolution_clock hrc;

const char* policy_names[7] = { "shadowlru"
                              , "fifo"
                              , "lru"
															, "slab"
                              , "shadowslab"
                              , "partslab"
                              , "lsm"
                              };
enum pol_type {
    SHADOWLRU = 0
  , FIFO
  , LRU
  , SLAB
  , SHADOWSLAB
  , PARTSLAB
  , LSM };

// globals
size_t                appid;                            // app to consider
bool                  all_apps = true;                  // run all by default
bool                  roundup  = false;                 // no rounding default
float                 lsm_util = 1.0;                   // default util factor
std::string           trace    = "data/m.cap.out";      // default filepath
std::string           app_str;                          // for logging apps
double                hit_start_time = 86400;           // default time
size_t                global_mem = 0;
pol_type              policy_type;                      // policy type
bool                  verbose = false;
double                gfactor = 1.25;                   // def slab growth fact
bool                  memcachier_classes = false;
size_t                partitions = 2;
size_t                segment_size = 8 * 1024 * 1024;

// Only parse this many requests from the CSV file before breaking.
// Helpful for limiting runtime when playing around.
int request_limit = 0;

#ifdef DEBUG
  bool debug = true;
#else
  bool debug = false;
#endif

const std::string     usage  = "-f    specify file path\n"
                               "-a    specify app to eval\n"
                               "-r    enable rounding\n"
                               "-u    specify utilization\n"
                               "-w    specify warmup period\n"
                               "-l    number of requests after warmup\n"
                               "-s    simulated cache size in bytes\n"
                               "-p    policy 0, 1, 2; shadowlru, fifo, lru\n"
                               "-v    incremental output\n"
                               "-g    specify slab growth factor\n"
                               "-M    use memcachier slab classes\n"
                               "-P    number of partitions for partslab\n"
                               "-S    segment size in bytes for lsm\n";

// memcachier slab allocations at t=86400 (24 hours)
const int orig_alloc[15] = {
  1664, 2304, 512, 17408, 266240, 16384, 73728, 188416, 442368,
  3932160, 11665408, 34340864, 262144, 0 , 0
};

// returns true if an ID is in the spec'd set
// returns true if set is empty
// bool valid_id(const request *r) {
//  if (all_apps)
//    return true;
//  else
//    return apps.count(r->appid);
//}

int main(int argc, char *argv[]) {

  // just checking boost
  std::cerr << "Using Boost "
            << BOOST_VERSION / 100000     << "."  // major version
            << BOOST_VERSION / 100 % 1000 << "."  // minor version
            << BOOST_VERSION % 100                // patch level
            << std::endl;

  // calculate global memory
  for (int i = 0; i < 15; i++)
    global_mem += orig_alloc[i];
  global_mem *= lsm_util;

  // parse cmd args
  int c;
  std::string sets;
  while ((c = getopt(argc, argv, "p:s:l:f:a:ru:w:vhg:MP:S:")) != -1) {
    switch (c)
    {
      case 'f':
        trace = optarg;
        break;
      case 'p':
        if (std::string(optarg) == "shadowlru")
          policy_type = pol_type(0);
        else if (std::string(optarg) == "fifo")
          policy_type = pol_type(1);
        else if (std::string(optarg) == "lru")
          policy_type = pol_type(2);
        else if (std::string(optarg) == "slab")
          policy_type = pol_type(3);
        else if (std::string(optarg) == "shadowslab")
          policy_type = pol_type(4);
        else if (std::string(optarg) == "partslab")
          policy_type = pol_type(5);
        else if (std::string(optarg) == "lsm")
          policy_type = pol_type(6);
        else {
          std::cerr << "Invalid policy specified" << std::endl;
          exit(EXIT_FAILURE);
        }
        break;
      case 's':
        global_mem = atol(optarg);
        break;
      case 'S':
        segment_size = atol(optarg);
        break;
      case 'l':
        request_limit = atoi(optarg);
        break;
      case 'a':
        {
          appid = atoi(optarg);
          break;
        }
      case 'r':
        roundup = true;
        break;
      case 'u':
        lsm_util = atof(optarg);
        break;
      case 'w':
        hit_start_time = atof(optarg);
        break;
      case 'v':
        verbose = true;
        break;
      case 'h':
        std::cerr << usage << std::endl;
        break;
      case 'g':
        gfactor = atof(optarg);
        break;
      case 'M':
        memcachier_classes = true;
        break;
      case 'P':
        partitions = atoi(optarg);
        break;
    }
  }

  //assert(apps.size() == 1);

  std::string filename_suffix = "-app" + std::to_string(appid);

  // build a stats struct with basic info relevant to every policy.
  stats sts{filename_suffix, policy_names[policy_type], appid, global_mem};

  printf("APPID: %lu\n", appid);

  // instantiate a policy
  std::unique_ptr<policy> policy{};
  switch(policy_type) {
    case SHADOWLRU:
      policy.reset(new shadowlru(sts));
      break;
    case FIFO :
      policy.reset(new fifo(sts));
      break;
    case LRU :
      sts.filename_suffix += "-size";
      sts.filename_suffix += std::to_string(global_mem / (1u << 20));
      sts.filename_suffix += "MB";
      policy.reset(new lru(sts));
      break;
    case SLAB :
      sts.filename_suffix += memcachier_classes ? "-memcachier" : "-memcached";
      sts.gfactor = gfactor;
      sts.memcachier_classes = memcachier_classes;
      policy.reset(new slab(sts));
      break;
    case SHADOWSLAB:
      sts.filename_suffix += memcachier_classes ? "-memcachier" : "-memcached";
      sts.memcachier_classes = memcachier_classes;
      sts.gfactor = gfactor;
      policy.reset(new shadowslab(sts));
    case PARTSLAB:
      sts.filename_suffix += "-partitions";
      sts.filename_suffix += std::to_string(partitions);
      sts.partitions = partitions;
      policy.reset(new partslab(sts));
      break;
    case LSM:
      sts.filename_suffix += "-size";
      sts.filename_suffix += std::to_string(global_mem / (1u << 20));
      sts.filename_suffix += "MB";
      sts.segment_size    = segment_size;
      sts.cleaning_width  = 4;
      policy.reset(new lsm(sts));
      break;
  }

   if (!policy) {
    std::cerr << "No valid policy selected!" << std::endl;
    exit(-1);
  }

  // List input parameters
  std::cerr << "performing trace analysis on apps: " << app_str << std::endl
            << "policy: " << policy_names[policy_type] << std::endl
            << "using trace file: " << trace << std::endl
            << "rounding: " << (roundup ? "on" : "off") << std::endl
            << "utilization rate: " << lsm_util << std::endl
            << "start counting hits at t = " << hit_start_time << std::endl
            << "request limit: " << request_limit << std::endl
            << "global mem: " << global_mem << std::endl;
  if (policy_type == SHADOWSLAB) {
    if (memcachier_classes)
      std::cerr << "slab growth factor: memcachier" << std::endl;
    else
      std::cerr << "slab growth factor: " << gfactor << std::endl;
  }

  // proc file line by line
  std::ifstream t_stream(trace);
  assert(t_stream.is_open());
  std::string line;

  int i = 0;
  auto start = hrc::now();
  auto last_progress = start;
  size_t bytes = 0;

  while (std::getline(t_stream, line) &&
         (request_limit == 0 || i < request_limit))
  {
    request r{line};
    bytes += line.size();

    if (verbose && ((i & ((1 << 18) - 1)) == 0)) {
      auto now  = hrc::now();
      double seconds =
        ch::duration_cast<ch::nanoseconds>(now - last_progress).count() / 1e9;
      if (seconds > 1.0) {
        stats stats = policy->get_stats();
        std::cerr << "Progress: " << r.time << " "
                  << "Rate: " << bytes / (1 << 20) / seconds << " MB/s "
                  << "Hit Rate: " << stats.get_hit_rate() * 100 << "% "
                  << "Evicted Items: " << stats.evicted_items << " "
                  << "Evicted Bytes: " << stats.evicted_bytes << " "
                  << "Utilization: " << stats.get_utilization()
                  << std::endl;
        bytes = 0;
        last_progress = now;
      }
    }

    // Only process requests for specified app, of type GET,
    // and values of size > 0, after time 'hit_start_time'.
    if ((r.type != request::GET) || (r.appid != appid) || (r.val_sz <= 0))
      continue;

    policy->proc(&r, r.time < hit_start_time);

    ++i;
  }
  auto stop = hrc::now();

  // Log curves for shadowlru, shadowslab, and partslab.
  if(policy_type == 0 || policy_type == 4 || policy_type == 5)
    policy->log_curves();

  // Dump stats for all policies.
  policy->dump_stats();

  double seconds =
    ch::duration_cast<ch::milliseconds>(stop - start).count() / 1000.;
  std::cerr << "total execution time: " << seconds << std::endl;

  return 0;
}

<|endoftext|>


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

#include <CoreAudio/AudioHardware.h>

#include "base/at_exit.h"
#include "media/audio/fake_audio_output_stream.h"
#include "media/audio/mac/audio_manager_mac.h"
#include "media/audio/mac/audio_output_mac.h"

bool AudioManagerMac::HasAudioDevices() {
  AudioDeviceID output_device_id = 0;
  size_t size = sizeof(output_device_id);
  OSStatus err = AudioHardwareGetProperty(
      kAudioHardwarePropertyDefaultOutputDevice, &size, &output_device_id);
  return ((err == noErr) && (output_device_id > 0));
}

AudioOutputStream* AudioManagerMac::MakeAudioStream(Format format, int channels,
                                                    int sample_rate,
                                                    char bits_per_sample) {
  if (format == AUDIO_MOCK)
    return FakeAudioOutputStream::MakeFakeStream();
  else if (format != AUDIO_PCM_LINEAR)
    return NULL;
  return new PCMQueueOutAudioOutputStream(this, channels, sample_rate,
                                          bits_per_sample);
}

void AudioManagerMac::MuteAll() {
  // TODO(cpu): implement.
}

void AudioManagerMac::UnMuteAll() {
  // TODO(cpu): implement.
}

// Called by the stream when it has been released by calling Close().
void AudioManagerMac::ReleaseStream(PCMQueueOutAudioOutputStream* stream) {
  delete stream;
}

namespace {

AudioManagerMac* g_audio_manager = NULL;

}  // namespace.

void DestroyAudioManagerMac(void* param) {
  delete g_audio_manager;
  g_audio_manager = NULL;
}

// By convention, the AudioManager is not thread safe.
AudioManager* AudioManager::GetAudioManager() {
  if (!g_audio_manager) {
    g_audio_manager = new AudioManagerMac();
    base::AtExitManager::RegisterCallback(&DestroyAudioManagerMac, NULL);
  }
  return g_audio_manager;
}
<commit_msg>AudioHardwareGetProperty is deprecated in Mac OS X 10.6 ("Snow Leopard"). All audio hardware properties can be accessed via AudioObjectGetPropertyData, present since Mac OS X 10.4 ("Tiger").<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <CoreAudio/AudioHardware.h>

#include "base/at_exit.h"
#include "media/audio/fake_audio_output_stream.h"
#include "media/audio/mac/audio_manager_mac.h"
#include "media/audio/mac/audio_output_mac.h"

bool AudioManagerMac::HasAudioDevices() {
  AudioDeviceID output_device_id = kAudioObjectUnknown;
  AudioObjectPropertyAddress property_address = {
    kAudioHardwarePropertyDefaultOutputDevice,  // mSelector
    kAudioObjectPropertyScopeGlobal,            // mScope
    kAudioObjectPropertyElementMaster           // mElement
  };
  size_t output_device_id_size = sizeof(output_device_id);
  OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject,
                                            &property_address,
                                            0,     // inQualifierDataSize
                                            NULL,  // inQualifierData
                                            &output_device_id_size,
                                            &output_device_id);
  return err == kAudioHardwareNoError &&
         output_device_id != kAudioObjectUnknown;
}

AudioOutputStream* AudioManagerMac::MakeAudioStream(Format format, int channels,
                                                    int sample_rate,
                                                    char bits_per_sample) {
  if (format == AUDIO_MOCK)
    return FakeAudioOutputStream::MakeFakeStream();
  else if (format != AUDIO_PCM_LINEAR)
    return NULL;
  return new PCMQueueOutAudioOutputStream(this, channels, sample_rate,
                                          bits_per_sample);
}

void AudioManagerMac::MuteAll() {
  // TODO(cpu): implement.
}

void AudioManagerMac::UnMuteAll() {
  // TODO(cpu): implement.
}

// Called by the stream when it has been released by calling Close().
void AudioManagerMac::ReleaseStream(PCMQueueOutAudioOutputStream* stream) {
  delete stream;
}

namespace {

AudioManagerMac* g_audio_manager = NULL;

}  // namespace.

void DestroyAudioManagerMac(void* param) {
  delete g_audio_manager;
  g_audio_manager = NULL;
}

// By convention, the AudioManager is not thread safe.
AudioManager* AudioManager::GetAudioManager() {
  if (!g_audio_manager) {
    g_audio_manager = new AudioManagerMac();
    base::AtExitManager::RegisterCallback(&DestroyAudioManagerMac, NULL);
  }
  return g_audio_manager;
}
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
#include <BALL/FORMAT/PDBFile.h>
#include <BALL/VIEW/KERNEL/client.h>

using namespace std;
using namespace BALL;
using namespace BALL::VIEW;

int main(int argc, char** argv)
{

	// check for command line arguments
	if (argc != 3)
	{
		cerr << argv[0] << " <host>[:<port>] <PDB file>" << endl;
		cerr << "  Reads a PDB file and sends its contents via the network" << endl;
		cerr << "  to the MOLVIEW server listening on <port> of <host> and" << endl;
		cerr << "  displays the contents of the file there." << endl;
		cerr << "  If no port is given, the default port 20000 is assumed." << endl << endl;
		return 1;
	}

	// open a file for input
	PDBFile	pdb_file(argv[2]);

	if (pdb_file.bad())
	{
		cerr << "Cannot open PDB file " << argv[2] << endl;
		return 2;
	}

	// create a system and read the contents of the
	// PDB file into this system
	System S;
	pdb_file >> S;
	pdb_file.close();

	// extract the hostname and port from the command line
	String host_port(argv[1]);
	String host;
	Size port;
	if (host_port.has(':'))
	{
		port = String(host_port.after(":")).toUnsignedInt();
		host = host_port.before(":");
	}
	else
	{
		host = host_port;
		port = VIEW_DEFAULT_PORT;
	}

	// create a MOLVIEW client and
	// connect to the given host and port
	cout << "connecting to port " << port << " of " << host << endl;
	Client client(host, port);

	// transmit the system
	cout << "sending " << S.countAtoms() << " atoms to " << host << endl;
	client.insert(S);

	// that's it.
	cout << "done." << endl;
	return 0;
}
<commit_msg>*** empty log message ***<commit_after><|endoftext|>


<commit_before>// CmdLineArgs.cpp
// Copyright (c) 2014 - The Foreseeable Future, zhiayang@gmail.com
// Licensed under the Apache License Version 2.0.

#include <iostream>
#include <fstream>
#include <cassert>
#include <sys/stat.h>
#include <sys/types.h>

#include <vector>
#include "compiler.h"

static std::string parseQuotedString(char** argv, int& i)
{
	std::string ret;
	if(strlen(argv[i]) > 0)
	{
		if(argv[i][0] == '"' || argv[i][0] == '\'')
		{
			while(std::string(argv[i]).back() != '\'' && std::string(argv[i]).back() != '"')
			{
				ret += " " + std::string(argv[i]);
				i++;
			}
		}
		else
		{
			ret = argv[i];
		}
	}
	return ret;
}

namespace Compiler
{
	static bool printModule = false;
	bool getDumpLlvm()
	{
		return printModule;
	}

	static bool printFIR = false;
	bool getDumpFir()
	{
		return printFIR;
	}

	static bool compileOnly = false;
	bool getIsCompileOnly()
	{
		return compileOnly;
	}

	#define DEFAULT_PREFIX		"/usr/local/lib/flaxlibs/"
	std::string getPrefix()
	{
		return DEFAULT_PREFIX;
	}

	static std::string sysroot;
	std::string getSysroot()
	{
		return sysroot;
	}

	static std::string target;
	std::string getTarget()
	{
		return target;
	}

	static int optLevel;
	int getOptimisationLevel()
	{
		return optLevel;
	}

	static uint64_t Flags;
	bool getFlag(Flag f)
	{
		return (Flags & (uint64_t) f);
	}

	static bool isPIC = false;
	bool getIsPositionIndependent()
	{
		return isPIC;
	}

	static std::string mcmodel;
	std::string getMcModel()
	{
		return mcmodel;
	}

	static bool noLowercaseTypes;
	bool getDisableLowercaseBuiltinTypes()
	{
		return noLowercaseTypes;
	}

	static bool printClangOutput;
	bool getPrintClangOutput()
	{
		return printClangOutput;
	}

	static bool runProgramWithJit;
	bool getRunProgramWithJit()
	{
		return runProgramWithJit;
	}

	static bool noAutoGlobalConstructor = false;
	bool getNoAutoGlobalConstructor()
	{
		return noAutoGlobalConstructor;
	}

	static std::vector<Warning> enabledWarnings {
		Warning::UnusedVariable,
		Warning::UseBeforeAssign,
		Warning::UseAfterFree
	};

	bool getWarningEnabled(Warning warning)
	{
		return std::find(enabledWarnings.begin(), enabledWarnings.end(), warning) != enabledWarnings.end();
	}

	static void setWarning(Warning warning, bool enabled)
	{
		auto it = std::find(enabledWarnings.begin(), enabledWarnings.end(), warning);
		if(it == enabledWarnings.end() && enabled == true)
			enabledWarnings.push_back(warning);

		else if(it != enabledWarnings.end() && enabled == false)
			enabledWarnings.erase(it);
	}

	std::pair<std::string, std::string> parseCmdLineArgs(int argc, char** argv)
	{
		// parse arguments
		std::string filename;
		std::string outname;

		if(argc > 1)
		{
			// parse the command line opts
			for(int i = 1; i < argc; i++)
			{
				if(!strcmp(argv[i], "-sysroot"))
				{
					if(i != argc - 1)
					{
						i++;
						Compiler::sysroot = parseQuotedString(argv, i);
						continue;
					}
					else
					{
						fprintf(stderr, "Error: Expected directory name after '-sysroot' option\n");
						exit(-1);
					}
				}
				if(!strcmp(argv[i], "-target"))
				{
					if(i != argc - 1)
					{
						i++;
						Compiler::target = parseQuotedString(argv, i);
						continue;
					}
					else
					{
						fprintf(stderr, "Error: Expected target string after '-target' option\n");
						exit(-1);
					}
				}
				else if(!strcmp(argv[i], "-o"))
				{
					if(i != argc - 1)
					{
						i++;
						outname = parseQuotedString(argv, i);
						continue;
					}
					else
					{
						fprintf(stderr, "Error: Expected filename name after '-o' option\n");
						exit(-1);
					}
				}
				else if(!strcmp(argv[i], "-fPIC"))
				{
					Compiler::isPIC = true;
				}
				else if(!strcmp(argv[i], "-mcmodel"))
				{
					if(i != argc - 1)
					{
						i++;
						std::string mm = parseQuotedString(argv, i);
						if(mm != "kernel" && mm != "small" && mm != "medium" && mm != "large")
						{
							fprintf(stderr, "Error: valid options for '-mcmodel' are 'small', 'medium', 'large' and 'kernel'.\n");
							exit(-1);
						}

						Compiler::mcmodel = mm;
					}
					else
					{
						fprintf(stderr, "Error: Expected mcmodel name after '-mcmodel' option\n");
						exit(-1);
					}
				}
				else if(!strcmp(argv[i], "-Werror"))
				{
					Compiler::Flags |= (uint64_t) Compiler::Flag::WarningsAsErrors;
				}
				else if(!strcmp(argv[i], "-w"))
				{
					Compiler::Flags |= (uint64_t) Compiler::Flag::NoWarnings;
				}
				else if(!strcmp(argv[i], "-print-ir"))
				{
					Compiler::printModule = true;
				}
				else if(!strcmp(argv[i], "-print-fir"))
				{
					Compiler::printFIR = true;
				}
				else if(!strcmp(argv[i], "-no-lowercase-builtin"))
				{
					Compiler::noLowercaseTypes = true;
				}
				else if(!strcmp(argv[i], "-c"))
				{
					Compiler::compileOnly = true;
				}
				else if(!strcmp(argv[i], "-show-clang"))
				{
					Compiler::printClangOutput = true;
				}
				else if(!strcmp(argv[i], "-jit") || !strcmp(argv[i], "-run"))
				{
					Compiler::runProgramWithJit = true;
				}
				else if(!strcmp(argv[i], "-no-auto-gconstr"))
				{
					Compiler::noAutoGlobalConstructor = true;
				}
				else if(strstr(argv[i], "-O") == argv[i])
				{
					// make sure we have at least 3 chars
					if(strlen(argv[i]) < 3)
					{
						fprintf(stderr, "Error: '-O' is not a valid option on its own\n");
						exit(-1);
					}

					if(argv[i][2] == 'x')
					{
						// literally nothing
						Compiler::optLevel = -1;
					}
					else
					{
						Compiler::optLevel = argv[i][2] - '0';
					}
				}

				// warnings.
				else if(!strcmp(argv[i], "-Wno-unused-variable"))
				{
					Compiler::setWarning(Compiler::Warning::UnusedVariable, false);
				}
				else if(!strcmp(argv[i], "-Wunused-variable"))
				{
					Compiler::setWarning(Compiler::Warning::UnusedVariable, true);
				}

				else if(!strcmp(argv[i], "-Wno-unused"))
				{
					Compiler::setWarning(Compiler::Warning::UnusedVariable, false);
				}
				else if(!strcmp(argv[i], "-Wunused"))
				{
					Compiler::setWarning(Compiler::Warning::UnusedVariable, true);
				}

				else if(!strcmp(argv[i], "-Wno-var-state-checker"))
				{
					Compiler::setWarning(Compiler::Warning::UseAfterFree, false);
					Compiler::setWarning(Compiler::Warning::UseBeforeAssign, false);
				}
				else if(!strcmp(argv[i], "-Wvar-state-checker"))
				{
					Compiler::setWarning(Compiler::Warning::UseAfterFree, true);
					Compiler::setWarning(Compiler::Warning::UseBeforeAssign, true);
				}
				else if(argv[i][0] == '-')
				{
					fprintf(stderr, "Error: Unrecognised option '%s'\n", argv[i]);

					exit(-1);
				}
				else
				{
					filename = argv[i];
					break;
				}
			}
		}
		else
		{
			fprintf(stderr, "Expected at least one argument\n");
			exit(-1);
		}

		return { filename, outname };
	}
}

<commit_msg>changed flag to "-print-lir" for llvm ir<commit_after>// CmdLineArgs.cpp
// Copyright (c) 2014 - The Foreseeable Future, zhiayang@gmail.com
// Licensed under the Apache License Version 2.0.

#include <iostream>
#include <fstream>
#include <cassert>
#include <sys/stat.h>
#include <sys/types.h>

#include <vector>
#include "compiler.h"

static std::string parseQuotedString(char** argv, int& i)
{
	std::string ret;
	if(strlen(argv[i]) > 0)
	{
		if(argv[i][0] == '"' || argv[i][0] == '\'')
		{
			while(std::string(argv[i]).back() != '\'' && std::string(argv[i]).back() != '"')
			{
				ret += " " + std::string(argv[i]);
				i++;
			}
		}
		else
		{
			ret = argv[i];
		}
	}
	return ret;
}

namespace Compiler
{
	static bool printModule = false;
	bool getDumpLlvm()
	{
		return printModule;
	}

	static bool printFIR = false;
	bool getDumpFir()
	{
		return printFIR;
	}

	static bool compileOnly = false;
	bool getIsCompileOnly()
	{
		return compileOnly;
	}

	#define DEFAULT_PREFIX		"/usr/local/lib/flaxlibs/"
	std::string getPrefix()
	{
		return DEFAULT_PREFIX;
	}

	static std::string sysroot;
	std::string getSysroot()
	{
		return sysroot;
	}

	static std::string target;
	std::string getTarget()
	{
		return target;
	}

	static int optLevel;
	int getOptimisationLevel()
	{
		return optLevel;
	}

	static uint64_t Flags;
	bool getFlag(Flag f)
	{
		return (Flags & (uint64_t) f);
	}

	static bool isPIC = false;
	bool getIsPositionIndependent()
	{
		return isPIC;
	}

	static std::string mcmodel;
	std::string getMcModel()
	{
		return mcmodel;
	}

	static bool noLowercaseTypes;
	bool getDisableLowercaseBuiltinTypes()
	{
		return noLowercaseTypes;
	}

	static bool printClangOutput;
	bool getPrintClangOutput()
	{
		return printClangOutput;
	}

	static bool runProgramWithJit;
	bool getRunProgramWithJit()
	{
		return runProgramWithJit;
	}

	static bool noAutoGlobalConstructor = false;
	bool getNoAutoGlobalConstructor()
	{
		return noAutoGlobalConstructor;
	}

	static std::vector<Warning> enabledWarnings {
		Warning::UnusedVariable,
		Warning::UseBeforeAssign,
		Warning::UseAfterFree
	};

	bool getWarningEnabled(Warning warning)
	{
		return std::find(enabledWarnings.begin(), enabledWarnings.end(), warning) != enabledWarnings.end();
	}

	static void setWarning(Warning warning, bool enabled)
	{
		auto it = std::find(enabledWarnings.begin(), enabledWarnings.end(), warning);
		if(it == enabledWarnings.end() && enabled == true)
			enabledWarnings.push_back(warning);

		else if(it != enabledWarnings.end() && enabled == false)
			enabledWarnings.erase(it);
	}

	std::pair<std::string, std::string> parseCmdLineArgs(int argc, char** argv)
	{
		// parse arguments
		std::string filename;
		std::string outname;

		if(argc > 1)
		{
			// parse the command line opts
			for(int i = 1; i < argc; i++)
			{
				if(!strcmp(argv[i], "-sysroot"))
				{
					if(i != argc - 1)
					{
						i++;
						Compiler::sysroot = parseQuotedString(argv, i);
						continue;
					}
					else
					{
						fprintf(stderr, "Error: Expected directory name after '-sysroot' option\n");
						exit(-1);
					}
				}
				if(!strcmp(argv[i], "-target"))
				{
					if(i != argc - 1)
					{
						i++;
						Compiler::target = parseQuotedString(argv, i);
						continue;
					}
					else
					{
						fprintf(stderr, "Error: Expected target string after '-target' option\n");
						exit(-1);
					}
				}
				else if(!strcmp(argv[i], "-o"))
				{
					if(i != argc - 1)
					{
						i++;
						outname = parseQuotedString(argv, i);
						continue;
					}
					else
					{
						fprintf(stderr, "Error: Expected filename name after '-o' option\n");
						exit(-1);
					}
				}
				else if(!strcmp(argv[i], "-fPIC"))
				{
					Compiler::isPIC = true;
				}
				else if(!strcmp(argv[i], "-mcmodel"))
				{
					if(i != argc - 1)
					{
						i++;
						std::string mm = parseQuotedString(argv, i);
						if(mm != "kernel" && mm != "small" && mm != "medium" && mm != "large")
						{
							fprintf(stderr, "Error: valid options for '-mcmodel' are 'small', 'medium', 'large' and 'kernel'.\n");
							exit(-1);
						}

						Compiler::mcmodel = mm;
					}
					else
					{
						fprintf(stderr, "Error: Expected mcmodel name after '-mcmodel' option\n");
						exit(-1);
					}
				}
				else if(!strcmp(argv[i], "-Werror"))
				{
					Compiler::Flags |= (uint64_t) Compiler::Flag::WarningsAsErrors;
				}
				else if(!strcmp(argv[i], "-w"))
				{
					Compiler::Flags |= (uint64_t) Compiler::Flag::NoWarnings;
				}
				else if(!strcmp(argv[i], "-print-lir"))
				{
					Compiler::printModule = true;
				}
				else if(!strcmp(argv[i], "-print-fir"))
				{
					Compiler::printFIR = true;
				}
				else if(!strcmp(argv[i], "-no-lowercase-builtin"))
				{
					Compiler::noLowercaseTypes = true;
				}
				else if(!strcmp(argv[i], "-c"))
				{
					Compiler::compileOnly = true;
				}
				else if(!strcmp(argv[i], "-show-clang"))
				{
					Compiler::printClangOutput = true;
				}
				else if(!strcmp(argv[i], "-jit") || !strcmp(argv[i], "-run"))
				{
					Compiler::runProgramWithJit = true;
				}
				else if(!strcmp(argv[i], "-no-auto-gconstr"))
				{
					Compiler::noAutoGlobalConstructor = true;
				}
				else if(strstr(argv[i], "-O") == argv[i])
				{
					// make sure we have at least 3 chars
					if(strlen(argv[i]) < 3)
					{
						fprintf(stderr, "Error: '-O' is not a valid option on its own\n");
						exit(-1);
					}

					if(argv[i][2] == 'x')
					{
						// literally nothing
						Compiler::optLevel = -1;
					}
					else
					{
						Compiler::optLevel = argv[i][2] - '0';
					}
				}

				// warnings.
				else if(!strcmp(argv[i], "-Wno-unused-variable"))
				{
					Compiler::setWarning(Compiler::Warning::UnusedVariable, false);
				}
				else if(!strcmp(argv[i], "-Wunused-variable"))
				{
					Compiler::setWarning(Compiler::Warning::UnusedVariable, true);
				}

				else if(!strcmp(argv[i], "-Wno-unused"))
				{
					Compiler::setWarning(Compiler::Warning::UnusedVariable, false);
				}
				else if(!strcmp(argv[i], "-Wunused"))
				{
					Compiler::setWarning(Compiler::Warning::UnusedVariable, true);
				}

				else if(!strcmp(argv[i], "-Wno-var-state-checker"))
				{
					Compiler::setWarning(Compiler::Warning::UseAfterFree, false);
					Compiler::setWarning(Compiler::Warning::UseBeforeAssign, false);
				}
				else if(!strcmp(argv[i], "-Wvar-state-checker"))
				{
					Compiler::setWarning(Compiler::Warning::UseAfterFree, true);
					Compiler::setWarning(Compiler::Warning::UseBeforeAssign, true);
				}
				else if(argv[i][0] == '-')
				{
					fprintf(stderr, "Error: Unrecognised option '%s'\n", argv[i]);

					exit(-1);
				}
				else
				{
					filename = argv[i];
					break;
				}
			}
		}
		else
		{
			fprintf(stderr, "Expected at least one argument\n");
			exit(-1);
		}

		return { filename, outname };
	}
}

<|endoftext|>


<commit_before>//===-- MainLoop.cpp --------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Config/config.h"

#include "lldb/Host/MainLoop.h"
#include "lldb/Utility/Error.h"
#include <algorithm>
#include <cassert>
#include <cerrno>
#include <csignal>
#include <vector>
#include <time.h>

#if HAVE_SYS_EVENT_H
#include <sys/event.h>
#elif defined(LLVM_ON_WIN32)
#include <winsock2.h>
#else
#include <poll.h>
#endif

#ifdef LLVM_ON_WIN32
#define POLL WSAPoll
#else
#define POLL poll
#endif

#if SIGNAL_POLLING_UNSUPPORTED
#ifdef LLVM_ON_WIN32
typedef int sigset_t;
#endif

int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout_ts,
          const sigset_t *) {
  int timeout =
      (timeout_ts == nullptr)
          ? -1
          : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
  return POLL(fds, nfds, timeout);
}

#endif

using namespace lldb;
using namespace lldb_private;

static sig_atomic_t g_signal_flags[NSIG];

static void SignalHandler(int signo, siginfo_t *info, void *) {
  assert(signo < NSIG);
  g_signal_flags[signo] = 1;
}

MainLoop::~MainLoop() {
  assert(m_read_fds.size() == 0);
  assert(m_signals.size() == 0);
}

MainLoop::ReadHandleUP
MainLoop::RegisterReadObject(const IOObjectSP &object_sp,
                                  const Callback &callback, Error &error) {
#ifdef LLVM_ON_WIN32
  if (object_sp->GetFdType() != IOObject:: eFDTypeSocket) {
    error.SetErrorString("MainLoop: non-socket types unsupported on Windows");
    return nullptr;
  }
#endif
  if (!object_sp || !object_sp->IsValid()) {
    error.SetErrorString("IO object is not valid.");
    return nullptr;
  }

  const bool inserted =
      m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second;
  if (!inserted) {
    error.SetErrorStringWithFormat("File descriptor %d already monitored.",
                                   object_sp->GetWaitableHandle());
    return nullptr;
  }

  return CreateReadHandle(object_sp);
}

// We shall block the signal, then install the signal handler. The signal will
// be unblocked in
// the Run() function to check for signal delivery.
MainLoop::SignalHandleUP
MainLoop::RegisterSignal(int signo, const Callback &callback,
                              Error &error) {
#ifdef SIGNAL_POLLING_UNSUPPORTED
  error.SetErrorString("Signal polling is not supported on this platform.");
  return nullptr;
#else
  if (m_signals.find(signo) != m_signals.end()) {
    error.SetErrorStringWithFormat("Signal %d already monitored.", signo);
    return nullptr;
  }

  SignalInfo info;
  info.callback = callback;
  struct sigaction new_action;
  new_action.sa_sigaction = &SignalHandler;
  new_action.sa_flags = SA_SIGINFO;
  sigemptyset(&new_action.sa_mask);
  sigaddset(&new_action.sa_mask, signo);

  sigset_t old_set;
  if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set)) {
    error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n",
                                   ret);
    return nullptr;
  }

  info.was_blocked = sigismember(&old_set, signo);
  if (sigaction(signo, &new_action, &info.old_action) == -1) {
    error.SetErrorToErrno();
    if (!info.was_blocked)
      pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr);
    return nullptr;
  }

  m_signals.insert({signo, info});
  g_signal_flags[signo] = 0;

  return SignalHandleUP(new SignalHandle(*this, signo));
#endif
}

void MainLoop::UnregisterReadObject(IOObject::WaitableHandle handle) {
  bool erased = m_read_fds.erase(handle);
  UNUSED_IF_ASSERT_DISABLED(erased);
  assert(erased);
}

void MainLoop::UnregisterSignal(int signo) {
#if SIGNAL_POLLING_UNSUPPORTED
  error.SetErrorString("Signal polling is not supported on this platform.");
  return nullptr;
#else
  // We undo the actions of RegisterSignal on a best-effort basis.
  auto it = m_signals.find(signo);
  assert(it != m_signals.end());

  sigaction(signo, &it->second.old_action, nullptr);

  sigset_t set;
  sigemptyset(&set);
  sigaddset(&set, signo);
  pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set,
                  nullptr);

  m_signals.erase(it);
#endif
}

Error MainLoop::Run() {
  std::vector<int> signals;
  m_terminate_request = false;
  signals.reserve(m_signals.size());

#if HAVE_SYS_EVENT_H
  int queue_id = kqueue();
  if (queue_id < 0)
    Error("kqueue failed with error %d\n", queue_id);

  std::vector<struct kevent> events;
  events.reserve(m_read_fds.size() + m_signals.size());
#else
  sigset_t sigmask;
  std::vector<struct pollfd> read_fds;
  read_fds.reserve(m_read_fds.size());
#endif

  // run until termination or until we run out of things to listen to
  while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) {
    // To avoid problems with callbacks changing the things we're supposed to
    // listen to, we
    // will store the *real* list of events separately.
    signals.clear();

#if HAVE_SYS_EVENT_H
    events.resize(m_read_fds.size() + m_signals.size());
    int i = 0;
    for (auto &fd: m_read_fds) {
      EV_SET(&events[i++], fd.first, EVFILT_READ, EV_ADD, 0, 0, 0);
    }

    for (const auto &sig : m_signals) {
      signals.push_back(sig.first);
      EV_SET(&events[i++], sig.first, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
    }

    struct kevent event_list[4];
    int num_events =
        kevent(queue_id, events.data(), events.size(), event_list, 4, NULL);

    if (num_events < 0)
      return Error("kevent() failed with error %d\n", num_events);

#else
    read_fds.clear();

#if !SIGNAL_POLLING_UNSUPPORTED
    if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask))
      return Error("pthread_sigmask failed with error %d\n", ret);

    for (const auto &sig : m_signals) {
      signals.push_back(sig.first);
      sigdelset(&sigmask, sig.first);
    }
#endif

    for (const auto &fd : m_read_fds) {
      struct pollfd pfd;
      pfd.fd = fd.first;
      pfd.events = POLLIN;
      pfd.revents = 0;
      read_fds.push_back(pfd);
    }

    if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 &&
        errno != EINTR)
      return Error(errno, eErrorTypePOSIX);
#endif

    for (int sig : signals) {
      if (g_signal_flags[sig] == 0)
        continue; // No signal
      g_signal_flags[sig] = 0;

      auto it = m_signals.find(sig);
      if (it == m_signals.end())
        continue; // Signal must have gotten unregistered in the meantime

      it->second.callback(*this); // Do the work

      if (m_terminate_request)
        return Error();
    }

#if HAVE_SYS_EVENT_H
    for (int i = 0; i < num_events; ++i) {
      auto it = m_read_fds.find(event_list[i].ident);
#else
    for (auto fd : read_fds) {
      if ((fd.revents & POLLIN) == 0)
        continue;

      auto it = m_read_fds.find(fd.fd);
#endif
      if (it == m_read_fds.end())
        continue; // File descriptor must have gotten unregistered in the
                  // meantime
      it->second(*this); // Do the work

      if (m_terminate_request)
        return Error();
    }
  }
  return Error();
}
<commit_msg>Buildbot wack-a-mole!<commit_after>//===-- MainLoop.cpp --------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Config/config.h"

#include "lldb/Host/MainLoop.h"
#include "lldb/Utility/Error.h"
#include <algorithm>
#include <cassert>
#include <cerrno>
#include <csignal>
#include <vector>
#include <time.h>

#if HAVE_SYS_EVENT_H
#include <sys/event.h>
#elif defined(LLVM_ON_WIN32)
#include <winsock2.h>
#else
#include <poll.h>
#endif

#ifdef LLVM_ON_WIN32
#define POLL WSAPoll
#else
#define POLL poll
#endif

#if SIGNAL_POLLING_UNSUPPORTED
#ifdef LLVM_ON_WIN32
typedef int sigset_t;
#endif

int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout_ts,
          const sigset_t *) {
  int timeout =
      (timeout_ts == nullptr)
          ? -1
          : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
  return POLL(fds, nfds, timeout);
}

#endif

using namespace lldb;
using namespace lldb_private;

static sig_atomic_t g_signal_flags[NSIG];

static void SignalHandler(int signo, siginfo_t *info, void *) {
  assert(signo < NSIG);
  g_signal_flags[signo] = 1;
}

MainLoop::~MainLoop() {
  assert(m_read_fds.size() == 0);
  assert(m_signals.size() == 0);
}

MainLoop::ReadHandleUP
MainLoop::RegisterReadObject(const IOObjectSP &object_sp,
                                  const Callback &callback, Error &error) {
#ifdef LLVM_ON_WIN32
  if (object_sp->GetFdType() != IOObject:: eFDTypeSocket) {
    error.SetErrorString("MainLoop: non-socket types unsupported on Windows");
    return nullptr;
  }
#endif
  if (!object_sp || !object_sp->IsValid()) {
    error.SetErrorString("IO object is not valid.");
    return nullptr;
  }

  const bool inserted =
      m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second;
  if (!inserted) {
    error.SetErrorStringWithFormat("File descriptor %d already monitored.",
                                   object_sp->GetWaitableHandle());
    return nullptr;
  }

  return CreateReadHandle(object_sp);
}

// We shall block the signal, then install the signal handler. The signal will
// be unblocked in
// the Run() function to check for signal delivery.
MainLoop::SignalHandleUP
MainLoop::RegisterSignal(int signo, const Callback &callback,
                              Error &error) {
#ifdef SIGNAL_POLLING_UNSUPPORTED
  error.SetErrorString("Signal polling is not supported on this platform.");
  return nullptr;
#else
  if (m_signals.find(signo) != m_signals.end()) {
    error.SetErrorStringWithFormat("Signal %d already monitored.", signo);
    return nullptr;
  }

  SignalInfo info;
  info.callback = callback;
  struct sigaction new_action;
  new_action.sa_sigaction = &SignalHandler;
  new_action.sa_flags = SA_SIGINFO;
  sigemptyset(&new_action.sa_mask);
  sigaddset(&new_action.sa_mask, signo);

  sigset_t old_set;
  if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set)) {
    error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n",
                                   ret);
    return nullptr;
  }

  info.was_blocked = sigismember(&old_set, signo);
  if (sigaction(signo, &new_action, &info.old_action) == -1) {
    error.SetErrorToErrno();
    if (!info.was_blocked)
      pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr);
    return nullptr;
  }

  m_signals.insert({signo, info});
  g_signal_flags[signo] = 0;

  return SignalHandleUP(new SignalHandle(*this, signo));
#endif
}

void MainLoop::UnregisterReadObject(IOObject::WaitableHandle handle) {
  bool erased = m_read_fds.erase(handle);
  UNUSED_IF_ASSERT_DISABLED(erased);
  assert(erased);
}

void MainLoop::UnregisterSignal(int signo) {
#if SIGNAL_POLLING_UNSUPPORTED
  Error("Signal polling is not supported on this platform.");
  return nullptr;
#else
  // We undo the actions of RegisterSignal on a best-effort basis.
  auto it = m_signals.find(signo);
  assert(it != m_signals.end());

  sigaction(signo, &it->second.old_action, nullptr);

  sigset_t set;
  sigemptyset(&set);
  sigaddset(&set, signo);
  pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set,
                  nullptr);

  m_signals.erase(it);
#endif
}

Error MainLoop::Run() {
  std::vector<int> signals;
  m_terminate_request = false;
  signals.reserve(m_signals.size());

#if HAVE_SYS_EVENT_H
  int queue_id = kqueue();
  if (queue_id < 0)
    Error("kqueue failed with error %d\n", queue_id);

  std::vector<struct kevent> events;
  events.reserve(m_read_fds.size() + m_signals.size());
#else
  sigset_t sigmask;
  std::vector<struct pollfd> read_fds;
  read_fds.reserve(m_read_fds.size());
#endif

  // run until termination or until we run out of things to listen to
  while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) {
    // To avoid problems with callbacks changing the things we're supposed to
    // listen to, we
    // will store the *real* list of events separately.
    signals.clear();

#if HAVE_SYS_EVENT_H
    events.resize(m_read_fds.size() + m_signals.size());
    int i = 0;
    for (auto &fd: m_read_fds) {
      EV_SET(&events[i++], fd.first, EVFILT_READ, EV_ADD, 0, 0, 0);
    }

    for (const auto &sig : m_signals) {
      signals.push_back(sig.first);
      EV_SET(&events[i++], sig.first, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
    }

    struct kevent event_list[4];
    int num_events =
        kevent(queue_id, events.data(), events.size(), event_list, 4, NULL);

    if (num_events < 0)
      return Error("kevent() failed with error %d\n", num_events);

#else
    read_fds.clear();

#if !SIGNAL_POLLING_UNSUPPORTED
    if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask))
      return Error("pthread_sigmask failed with error %d\n", ret);

    for (const auto &sig : m_signals) {
      signals.push_back(sig.first);
      sigdelset(&sigmask, sig.first);
    }
#endif

    for (const auto &fd : m_read_fds) {
      struct pollfd pfd;
      pfd.fd = fd.first;
      pfd.events = POLLIN;
      pfd.revents = 0;
      read_fds.push_back(pfd);
    }

    if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 &&
        errno != EINTR)
      return Error(errno, eErrorTypePOSIX);
#endif

    for (int sig : signals) {
      if (g_signal_flags[sig] == 0)
        continue; // No signal
      g_signal_flags[sig] = 0;

      auto it = m_signals.find(sig);
      if (it == m_signals.end())
        continue; // Signal must have gotten unregistered in the meantime

      it->second.callback(*this); // Do the work

      if (m_terminate_request)
        return Error();
    }

#if HAVE_SYS_EVENT_H
    for (int i = 0; i < num_events; ++i) {
      auto it = m_read_fds.find(event_list[i].ident);
#else
    for (auto fd : read_fds) {
      if ((fd.revents & POLLIN) == 0)
        continue;

      auto it = m_read_fds.find(fd.fd);
#endif
      if (it == m_read_fds.end())
        continue; // File descriptor must have gotten unregistered in the
                  // meantime
      it->second(*this); // Do the work

      if (m_terminate_request)
        return Error();
    }
  }
  return Error();
}
<|endoftext|>


<commit_before>

#include <iostream>
#include <iomanip>
#include <fstream>
#include <list>
#include <ctime>

#include <boost/numeric/ublas/io.hpp>

#include <scsi/constants.h>
#include <scsi/base.h>
#include <scsi/moment2.h>
#include <scsi/state/vector.h>
#include <scsi/state/matrix.h>

typedef Moment2State state_t;

typedef boost::numeric::ublas::vector<double> value_vec;
typedef boost::numeric::ublas::matrix<double> value_mat;

extern int glps_debug;

enum {maxsize = 7};

typedef boost::numeric::ublas::vector<double,
                boost::numeric::ublas::bounded_array<double, maxsize>
> vector_t;
typedef boost::numeric::ublas::matrix<double,
                boost::numeric::ublas::row_major,
                boost::numeric::ublas::bounded_array<double, maxsize*maxsize>
> matrix_t;

// Phase space dimension; including vector for orbit/1st moment.
# define PS_Dim       7

void PrtVec(const std::vector<double> &a)
{
    for (size_t k = 0; k < a.size(); k++)
        std::cout << std::scientific << std::setprecision(10)
                      << std::setw(18) << a[k];
    std::cout << "\n";
}

void PrtVec(const vector_t &a)
{
    for (size_t k = 0; k < a.size(); k++)
        std::cout << std::scientific << std::setprecision(10)
                      << std::setw(18) << a[k];
    std::cout << "\n";
}

void PrtMat(const value_mat &M)
{
    for (size_t j = 0; j < M.size1(); j++) {
        for (size_t k = 0; k < M.size2(); k++)
            std::cout << std::scientific << std::setprecision(10)
                      << std::setw(18) << M(j, k);
        std::cout << "\n";
    }
}

std::vector<double> GetChgState(Config &conf, const std::string &CSstr)
{
    return conf.get<std::vector<double> >(CSstr);
}

std::vector<double> GetNChg(Config &conf, const std::string &CAstr)
{
    return conf.get<std::vector<double> >(CAstr);
}

value_vec GetBaryCenter(Config &conf, const std::string &BCstr)
{

    const std::vector<double>& BCvec = conf.get<std::vector<double> >(BCstr);
    value_vec BC(PS_Dim);
    if (BCvec.size() > BC.data().size())
        throw std::invalid_argument("Initial state size too big");
    std::copy(BCvec.begin(), BCvec.end(), BC.data().begin());

    return BC;
}

value_mat GetBeamEnvelope(Config &conf, const std::string &BEstr)
{

    const std::vector<double>& BEvec = conf.get<std::vector<double> >(BEstr);
    value_mat BE(PS_Dim, PS_Dim);
    if (BEvec.size() > BE.data().size())
        throw std::invalid_argument("Initial state size too big");
    std::copy(BEvec.begin(), BEvec.end(), BE.data().begin());

    return BE;
}

void propagate(std::auto_ptr<Config> conf)
{

    int                        k;
    boost::shared_ptr<Machine> sim;
    std::vector<double>        ChgState(GetChgState(*conf, "IonChargeStates"));

    const int nChgStates = ChgState.size();

    state_t * StatePtr;

    for (k = 0; k < nChgStates; k++) {
        conf->set<double>("cstate", k);

        sim = boost::shared_ptr<Machine> (new Machine(*conf));
        sim->set_trace(NULL);

        std::auto_ptr<StateBase> state(sim->allocState());

        StatePtr = dynamic_cast<state_t*>(state.get());
        if(!StatePtr) throw std::runtime_error("Only sim_type MomentMatrix2 is supported");

        std::cout << std::fixed << std::setprecision(3) << "\ns [m] = " << StatePtr->pos << "\n";

        // Propagate through first element (beam initial conditions).
        sim->propagate(state.get(), 0, 1);

        clock_t tStamp[2];
        tStamp[0] = clock();
        sim->propagate(state.get(), 1);
        tStamp[1] = clock();

        std::cout << std::fixed << std::setprecision(5)
                  << "\npropagate: " << double(tStamp[1]-tStamp[0])/CLOCKS_PER_SEC << " sec" << "\n";

        std::cout << "\n";
        PrtVec(StatePtr->moment0);
        std::cout << "\n";
        PrtMat(StatePtr->state);
        std::cout << std::fixed << std::setprecision(3) << "\ns [m] = " << StatePtr->pos << "\n";
    }
}

int main(int argc, char *argv[])
{
    try {
        std::auto_ptr<Config> conf;

        if(argc>2)

        glps_debug = 0; // 0 or 1.

        try {
            GLPSParser P;
            conf.reset(P.parse_file(argc>1 ? argv[1] : NULL));
            fprintf(stderr, "Parsing succeeds\n");
        } catch(std::exception& e) {
            fprintf(stderr, "Parse error: %s\n", e.what());
            return 1;
        }

//        std::cout<<"# Reduced lattice\n";
//        GLPSPrint(std::cout, *conf);
//        std::cout<<"\n";

        // register state and element types
        registerLinear();
//        registerMoment();
        registerMoment2();

        propagate(conf);

        return 0;
    } catch(std::exception& e) {
        std::cerr << "Main exception: " << e.what() << "\n";
        Machine::registeryCleanup();
        return 1;
    }
}
<commit_msg>Added propagate1 to test_jb_2.cpp for element-by-element tracking of multiple charge states.<commit_after>

#include <iostream>
#include <iomanip>
#include <fstream>
#include <list>
#include <ctime>

#include <boost/numeric/ublas/io.hpp>

#include <scsi/constants.h>
#include <scsi/base.h>
#include <scsi/moment2.h>
#include <scsi/state/vector.h>
#include <scsi/state/matrix.h>

typedef Moment2State state_t;

typedef boost::numeric::ublas::vector<double> value_vec;
typedef boost::numeric::ublas::matrix<double> value_mat;

extern int glps_debug;

enum {maxsize = 7};

typedef boost::numeric::ublas::vector<double,
                boost::numeric::ublas::bounded_array<double, maxsize>
> vector_t;
typedef boost::numeric::ublas::matrix<double,
                boost::numeric::ublas::row_major,
                boost::numeric::ublas::bounded_array<double, maxsize*maxsize>
> matrix_t;

// Phase space dimension; including vector for orbit/1st moment.
# define PS_Dim       7

void PrtVec(const std::vector<double> &a)
{
    for (size_t k = 0; k < a.size(); k++)
        std::cout << std::scientific << std::setprecision(10)
                      << std::setw(18) << a[k];
    std::cout << "\n";
}

void PrtVec(const vector_t &a)
{
    for (size_t k = 0; k < a.size(); k++)
        std::cout << std::scientific << std::setprecision(10)
                      << std::setw(18) << a[k];
    std::cout << "\n";
}

void PrtMat(const value_mat &M)
{
    for (size_t j = 0; j < M.size1(); j++) {
        for (size_t k = 0; k < M.size2(); k++)
            std::cout << std::scientific << std::setprecision(10)
                      << std::setw(18) << M(j, k);
        std::cout << "\n";
    }
}

std::vector<double> GetChgState(Config &conf, const std::string &CSstr)
{
    return conf.get<std::vector<double> >(CSstr);
}

std::vector<double> GetNChg(Config &conf, const std::string &CAstr)
{
    return conf.get<std::vector<double> >(CAstr);
}

value_vec GetBaryCenter(Config &conf, const std::string &BCstr)
{

    const std::vector<double>& BCvec = conf.get<std::vector<double> >(BCstr);
    value_vec BC(PS_Dim);
    if (BCvec.size() > BC.data().size())
        throw std::invalid_argument("Initial state size too big");
    std::copy(BCvec.begin(), BCvec.end(), BC.data().begin());

    return BC;
}

value_mat GetBeamEnvelope(Config &conf, const std::string &BEstr)
{

    const std::vector<double>& BEvec = conf.get<std::vector<double> >(BEstr);
    value_mat BE(PS_Dim, PS_Dim);
    if (BEvec.size() > BE.data().size())
        throw std::invalid_argument("Initial state size too big");
    std::copy(BEvec.begin(), BEvec.end(), BE.data().begin());

    return BE;
}

void propagate(std::auto_ptr<Config> conf)
{

    int                        k;
    boost::shared_ptr<Machine> sim;
    std::vector<double>        ChgState(GetChgState(*conf, "IonChargeStates"));
    state_t                    *StatePtr;

    const int nChgStates = ChgState.size();

    for (k = 0; k < nChgStates; k++) {
        conf->set<double>("cstate", k);

        sim = boost::shared_ptr<Machine> (new Machine(*conf));
        sim->set_trace(NULL);

        std::auto_ptr<StateBase> state(sim->allocState());

        StatePtr = dynamic_cast<state_t*>(state.get());
        if(!StatePtr) throw std::runtime_error("Only sim_type MomentMatrix2 is supported");

        std::cout << std::fixed << std::setprecision(3) << "\ns [m] = " << StatePtr->pos << "\n";

        // Propagate through first element (beam initial conditions).
        sim->propagate(state.get(), 0, 1);

        clock_t tStamp[2];
        tStamp[0] = clock();
        sim->propagate(state.get(), 1);
        tStamp[1] = clock();

        std::cout << std::fixed << std::setprecision(5)
                  << "\npropagate: " << double(tStamp[1]-tStamp[0])/CLOCKS_PER_SEC << " sec" << "\n";

        std::cout << "\n";
        PrtVec(StatePtr->moment0);
        std::cout << "\n";
        PrtMat(StatePtr->state);
        std::cout << std::fixed << std::setprecision(3) << "\ns [m] = " << StatePtr->pos << "\n";
    }
}

void propagate1(std::auto_ptr<Config> conf)
{
    // Propagate element-by-element for each charge state.
    int                                        k;
    std::vector<double>                        ChgState(GetChgState(*conf, "IonChargeStates"));
    std::vector<boost::shared_ptr<Machine> >   sim;
    std::vector<boost::shared_ptr<StateBase> > state;
    std::vector<state_t*>                      StatePtr;
    std::vector<Machine::iterator>             it;

    const int nChgStates = ChgState.size();

    for (k = 0; k < nChgStates; k++) {
        conf->set<double>("cstate", k);

        sim.push_back(boost::shared_ptr<Machine> (new Machine(*conf)));
        sim[k]->set_trace(NULL);

        state.push_back(boost::shared_ptr<StateBase> (sim[k]->allocState()));

        StatePtr.push_back(dynamic_cast<state_t*>(state[k].get()));
        if(!StatePtr[k]) throw std::runtime_error("Only sim_type MomentMatrix2 is supported");

        // Propagate through first element (beam initial conditions).
        sim[k]->propagate(state[k].get(), 0, 1);

        it.push_back(sim[k]->begin());
        // Skip over state.
        it[k]++;

        std::cout << std::fixed << std::setprecision(3) << "\ns [m] = " << StatePtr[k]->pos << "\n";
    }

    clock_t tStamp[2];

    tStamp[0] = clock();

    while (it[0] != sim[0]->end()) {
        for (k = 0; k < nChgStates; k++) {
            (*it[k])->advance(*state[k]);
            ++it[k];
        }
    }

    tStamp[1] = clock();

    std::cout << std::fixed << std::setprecision(5)
              << "\npropagate: " << double(tStamp[1]-tStamp[0])/CLOCKS_PER_SEC << " sec" << "\n";

    for (k = 0; k < nChgStates; k++) {
        std::cout << "\n";
        PrtVec(StatePtr[k]->moment0);
        std::cout << "\n";
        PrtMat(StatePtr[k]->state);
        std::cout << std::fixed << std::setprecision(3) << "\ns [m] = " << StatePtr[k]->pos << "\n";
    }
}

int main(int argc, char *argv[])
{
    try {
        std::auto_ptr<Config> conf;

        if(argc>2)

        glps_debug = 0; // 0 or 1.

        try {
            GLPSParser P;
            conf.reset(P.parse_file(argc>1 ? argv[1] : NULL));
            fprintf(stderr, "Parsing succeeds\n");
        } catch(std::exception& e) {
            fprintf(stderr, "Parse error: %s\n", e.what());
            return 1;
        }

//        std::cout<<"# Reduced lattice\n";
//        GLPSPrint(std::cout, *conf);
//        std::cout<<"\n";

        // register state and element types
//        registerLinear();
//        registerMoment();
        registerMoment2();

//        propagate(conf);
//        propagate(conf);
        propagate1(conf);

        return 0;
    } catch(std::exception& e) {
        std::cerr << "Main exception: " << e.what() << "\n";
        Machine::registeryCleanup();
        return 1;
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2015 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders 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
 * OWNER 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.
 *
 * Authors: Ron Dreslinski
 *          Ali Saidi
 *          Andreas Hansson
 *          William Wang
 */

/**
 * @file
 * Declaration of an abstract crossbar base class.
 */

#ifndef __MEM_XBAR_HH__
#define __MEM_XBAR_HH__

#include <deque>
#include <unordered_map>

#include "base/addr_range_map.hh"
#include "base/types.hh"
#include "mem/mem_object.hh"
#include "mem/qport.hh"
#include "params/BaseXBar.hh"
#include "sim/stats.hh"

/**
 * The base crossbar contains the common elements of the non-coherent
 * and coherent crossbar. It is an abstract class that does not have
 * any of the functionality relating to the actual reception and
 * transmission of packets, as this is left for the subclasses.
 *
 * The BaseXBar is responsible for the basic flow control (busy or
 * not), the administration of retries, and the address decoding.
 */
class BaseXBar : public MemObject
{

  protected:

    /**
     * A layer is an internal crossbar arbitration point with its own
     * flow control. Each layer is a converging multiplexer tree. By
     * instantiating one layer per destination port (and per packet
     * type, i.e. request, response, snoop request and snoop
     * response), we model full crossbar structures like AXI, ACE,
     * PCIe, etc.
     *
     * The template parameter, PortClass, indicates the destination
     * port type for the layer. The retry list holds either master
     * ports or slave ports, depending on the direction of the
     * layer. Thus, a request layer has a retry list containing slave
     * ports, whereas a response layer holds master ports.
     */
    template <typename SrcType, typename DstType>
    class Layer : public Drainable
    {

      public:

        /**
         * Create a layer and give it a name. The layer uses
         * the crossbar an event manager.
         *
         * @param _port destination port the layer converges at
         * @param _xbar the crossbar this layer belongs to
         * @param _name the layer's name
         */
        Layer(DstType& _port, BaseXBar& _xbar, const std::string& _name);

        /**
         * Drain according to the normal semantics, so that the crossbar
         * can tell the layer to drain, and pass an event to signal
         * back when drained.
         *
         * @param de drain event to call once drained
         *
         * @return 1 if busy or waiting to retry, or 0 if idle
         */
        DrainState drain() override;

        /**
         * Get the crossbar layer's name
         */
        const std::string name() const { return xbar.name() + _name; }

        /**
         * Determine if the layer accepts a packet from a specific
         * port. If not, the port in question is also added to the
         * retry list. In either case the state of the layer is
         * updated accordingly.
         *
         * @param port Source port presenting the packet
         *
         * @return True if the layer accepts the packet
         */
        bool tryTiming(SrcType* src_port);

        /**
         * Deal with a destination port accepting a packet by potentially
         * removing the source port from the retry list (if retrying) and
         * occupying the layer accordingly.
         *
         * @param busy_time Time to spend as a result of a successful send
         */
        void succeededTiming(Tick busy_time);

        /**
         * Deal with a destination port not accepting a packet by
         * potentially adding the source port to the retry list (if
         * not already at the front) and occupying the layer
         * accordingly.
         *
         * @param src_port Source port
         * @param busy_time Time to spend as a result of a failed send
         */
        void failedTiming(SrcType* src_port, Tick busy_time);

        /** Occupy the layer until until */
        void occupyLayer(Tick until);

        /**
         * Send a retry to the port at the head of waitingForLayer. The
         * caller must ensure that the list is not empty.
         */
        void retryWaiting();

        /**
         * Handle a retry from a neighbouring module. This wraps
         * retryWaiting by verifying that there are ports waiting
         * before calling retryWaiting.
         */
        void recvRetry();

        /**
         * Register stats for the layer
         */
        void regStats();

      protected:

        /**
         * Sending the actual retry, in a manner specific to the
         * individual layers. Note that for a MasterPort, there is
         * both a RequestLayer and a SnoopResponseLayer using the same
         * port, but using different functions for the flow control.
         */
        virtual void sendRetry(SrcType* retry_port) = 0;

      private:

        /** The destination port this layer converges at. */
        DstType& port;

        /** The crossbar this layer is a part of. */
        BaseXBar& xbar;

        /** A name for this layer. */
        std::string _name;

        /**
         * We declare an enum to track the state of the layer. The
         * starting point is an idle state where the layer is waiting
         * for a packet to arrive. Upon arrival, the layer
         * transitions to the busy state, where it remains either
         * until the packet transfer is done, or the header time is
         * spent. Once the layer leaves the busy state, it can
         * either go back to idle, if no packets have arrived while it
         * was busy, or the layer goes on to retry the first port
         * in waitingForLayer. A similar transition takes place from
         * idle to retry if the layer receives a retry from one of
         * its connected ports. The retry state lasts until the port
         * in questions calls sendTiming and returns control to the
         * layer, or goes to a busy state if the port does not
         * immediately react to the retry by calling sendTiming.
         */
        enum State { IDLE, BUSY, RETRY };

        /** track the state of the layer */
        State state;

        /**
         * A deque of ports that retry should be called on because
         * the original send was delayed due to a busy layer.
         */
        std::deque<SrcType*> waitingForLayer;

        /**
         * Track who is waiting for the retry when receiving it from a
         * peer. If no port is waiting NULL is stored.
         */
        SrcType* waitingForPeer;

        /**
         * Release the layer after being occupied and return to an
         * idle state where we proceed to send a retry to any
         * potential waiting port, or drain if asked to do so.
         */
        void releaseLayer();

        /** event used to schedule a release of the layer */
        EventWrapper<Layer, &Layer::releaseLayer> releaseEvent;

        /**
         * Stats for occupancy and utilization. These stats capture
         * the time the layer spends in the busy state and are thus only
         * relevant when the memory system is in timing mode.
         */
        Stats::Scalar occupancy;
        Stats::Formula utilization;

    };

    class ReqLayer : public Layer<SlavePort,MasterPort>
    {
      public:
        /**
         * Create a request layer and give it a name.
         *
         * @param _port destination port the layer converges at
         * @param _xbar the crossbar this layer belongs to
         * @param _name the layer's name
         */
        ReqLayer(MasterPort& _port, BaseXBar& _xbar, const std::string& _name) :
            Layer(_port, _xbar, _name) {}

      protected:

        void sendRetry(SlavePort* retry_port)
        { retry_port->sendRetryReq(); }
    };

    class RespLayer : public Layer<MasterPort,SlavePort>
    {
      public:
        /**
         * Create a response layer and give it a name.
         *
         * @param _port destination port the layer converges at
         * @param _xbar the crossbar this layer belongs to
         * @param _name the layer's name
         */
        RespLayer(SlavePort& _port, BaseXBar& _xbar, const std::string& _name) :
            Layer(_port, _xbar, _name) {}

      protected:

        void sendRetry(MasterPort* retry_port)
        { retry_port->sendRetryResp(); }
    };

    class SnoopRespLayer : public Layer<SlavePort,MasterPort>
    {
      public:
        /**
         * Create a snoop response layer and give it a name.
         *
         * @param _port destination port the layer converges at
         * @param _xbar the crossbar this layer belongs to
         * @param _name the layer's name
         */
        SnoopRespLayer(MasterPort& _port, BaseXBar& _xbar,
                       const std::string& _name) :
            Layer(_port, _xbar, _name) {}

      protected:

        void sendRetry(SlavePort* retry_port)
        { retry_port->sendRetrySnoopResp(); }
    };

    /**
     * Cycles of front-end pipeline including the delay to accept the request
     * and to decode the address.
     */
    const Cycles frontendLatency;
    /** Cycles of forward latency */
    const Cycles forwardLatency;
    /** Cycles of response latency */
    const Cycles responseLatency;
    /** the width of the xbar in bytes */
    const uint32_t width;

    AddrRangeMap<PortID> portMap;

    /**
     * Remember where request packets came from so that we can route
     * responses to the appropriate port. This relies on the fact that
     * the underlying Request pointer inside the Packet stays
     * constant.
     */
    std::unordered_map<RequestPtr, PortID> routeTo;

    /** all contigous ranges seen by this crossbar */
    AddrRangeList xbarRanges;

    AddrRange defaultRange;

    /**
     * Function called by the port when the crossbar is recieving a
     * range change.
     *
     * @param master_port_id id of the port that received the change
     */
    virtual void recvRangeChange(PortID master_port_id);

    /** Find which port connected to this crossbar (if any) should be
     * given a packet with this address.
     *
     * @param addr Address to find port for.
     * @return id of port that the packet should be sent out of.
     */
    PortID findPort(Addr addr);

    // Cache for the findPort function storing recently used ports from portMap
    struct PortCache {
        bool valid;
        PortID id;
        AddrRange range;
    };

    PortCache portCache[3];

    // Checks the cache and returns the id of the port that has the requested
    // address within its range
    inline PortID checkPortCache(Addr addr) const {
        if (portCache[0].valid && portCache[0].range.contains(addr)) {
            return portCache[0].id;
        }
        if (portCache[1].valid && portCache[1].range.contains(addr)) {
            return portCache[1].id;
        }
        if (portCache[2].valid && portCache[2].range.contains(addr)) {
            return portCache[2].id;
        }

        return InvalidPortID;
    }

    // Clears the earliest entry of the cache and inserts a new port entry
    inline void updatePortCache(short id, const AddrRange& range) {
        portCache[2].valid = portCache[1].valid;
        portCache[2].id    = portCache[1].id;
        portCache[2].range = portCache[1].range;

        portCache[1].valid = portCache[0].valid;
        portCache[1].id    = portCache[0].id;
        portCache[1].range = portCache[0].range;

        portCache[0].valid = true;
        portCache[0].id    = id;
        portCache[0].range = range;
    }

    // Clears the cache. Needs to be called in constructor.
    inline void clearPortCache() {
        portCache[2].valid = false;
        portCache[1].valid = false;
        portCache[0].valid = false;
    }

    /**
     * Return the address ranges the crossbar is responsible for.
     *
     * @return a list of non-overlapping address ranges
     */
    AddrRangeList getAddrRanges() const;

    /**
     * Calculate the timing parameters for the packet. Updates the
     * headerDelay and payloadDelay fields of the packet
     * object with the relative number of ticks required to transmit
     * the header and the payload, respectively.
     *
     * @param pkt Packet to populate with timings
     * @param header_delay Header delay to be added
     */
    void calcPacketTiming(PacketPtr pkt, Tick header_delay);

    /**
     * Remember for each of the master ports of the crossbar if we got
     * an address range from the connected slave. For convenience,
     * also keep track of if we got ranges from all the slave modules
     * or not.
     */
    std::vector<bool> gotAddrRanges;
    bool gotAllAddrRanges;

    /** The master and slave ports of the crossbar */
    std::vector<QueuedSlavePort*> slavePorts;
    std::vector<MasterPort*> masterPorts;

    /** Port that handles requests that don't match any of the interfaces.*/
    PortID defaultPortID;

    /** If true, use address range provided by default device.  Any
       address not handled by another port and not in default device's
       range will cause a fatal error.  If false, just send all
       addresses not handled by another port to default device. */
    const bool useDefaultRange;

    BaseXBar(const BaseXBarParams *p);

    virtual ~BaseXBar();

    /**
     * Stats for transaction distribution and data passing through the
     * crossbar. The transaction distribution is globally counting
     * different types of commands. The packet count and total packet
     * size are two-dimensional vectors that are indexed by the
     * slave port and master port id (thus the neighbouring master and
     * neighbouring slave), summing up both directions (request and
     * response).
     */
    Stats::Vector transDist;
    Stats::Vector2d pktCount;
    Stats::Vector2d pktSize;

  public:

    virtual void init();

    /** A function used to return the port associated with this object. */
    BaseMasterPort& getMasterPort(const std::string& if_name,
                                  PortID idx = InvalidPortID);
    BaseSlavePort& getSlavePort(const std::string& if_name,
                                PortID idx = InvalidPortID);

    virtual void regStats();

};

#endif //__MEM_XBAR_HH__
<commit_msg>mem: Make the BaseXBar public to not confuse Python wrappers<commit_after>/*
 * Copyright (c) 2011-2015 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders 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
 * OWNER 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.
 *
 * Authors: Ron Dreslinski
 *          Ali Saidi
 *          Andreas Hansson
 *          William Wang
 */

/**
 * @file
 * Declaration of an abstract crossbar base class.
 */

#ifndef __MEM_XBAR_HH__
#define __MEM_XBAR_HH__

#include <deque>
#include <unordered_map>

#include "base/addr_range_map.hh"
#include "base/types.hh"
#include "mem/mem_object.hh"
#include "mem/qport.hh"
#include "params/BaseXBar.hh"
#include "sim/stats.hh"

/**
 * The base crossbar contains the common elements of the non-coherent
 * and coherent crossbar. It is an abstract class that does not have
 * any of the functionality relating to the actual reception and
 * transmission of packets, as this is left for the subclasses.
 *
 * The BaseXBar is responsible for the basic flow control (busy or
 * not), the administration of retries, and the address decoding.
 */
class BaseXBar : public MemObject
{

  protected:

    /**
     * A layer is an internal crossbar arbitration point with its own
     * flow control. Each layer is a converging multiplexer tree. By
     * instantiating one layer per destination port (and per packet
     * type, i.e. request, response, snoop request and snoop
     * response), we model full crossbar structures like AXI, ACE,
     * PCIe, etc.
     *
     * The template parameter, PortClass, indicates the destination
     * port type for the layer. The retry list holds either master
     * ports or slave ports, depending on the direction of the
     * layer. Thus, a request layer has a retry list containing slave
     * ports, whereas a response layer holds master ports.
     */
    template <typename SrcType, typename DstType>
    class Layer : public Drainable
    {

      public:

        /**
         * Create a layer and give it a name. The layer uses
         * the crossbar an event manager.
         *
         * @param _port destination port the layer converges at
         * @param _xbar the crossbar this layer belongs to
         * @param _name the layer's name
         */
        Layer(DstType& _port, BaseXBar& _xbar, const std::string& _name);

        /**
         * Drain according to the normal semantics, so that the crossbar
         * can tell the layer to drain, and pass an event to signal
         * back when drained.
         *
         * @param de drain event to call once drained
         *
         * @return 1 if busy or waiting to retry, or 0 if idle
         */
        DrainState drain() override;

        /**
         * Get the crossbar layer's name
         */
        const std::string name() const { return xbar.name() + _name; }

        /**
         * Determine if the layer accepts a packet from a specific
         * port. If not, the port in question is also added to the
         * retry list. In either case the state of the layer is
         * updated accordingly.
         *
         * @param port Source port presenting the packet
         *
         * @return True if the layer accepts the packet
         */
        bool tryTiming(SrcType* src_port);

        /**
         * Deal with a destination port accepting a packet by potentially
         * removing the source port from the retry list (if retrying) and
         * occupying the layer accordingly.
         *
         * @param busy_time Time to spend as a result of a successful send
         */
        void succeededTiming(Tick busy_time);

        /**
         * Deal with a destination port not accepting a packet by
         * potentially adding the source port to the retry list (if
         * not already at the front) and occupying the layer
         * accordingly.
         *
         * @param src_port Source port
         * @param busy_time Time to spend as a result of a failed send
         */
        void failedTiming(SrcType* src_port, Tick busy_time);

        /** Occupy the layer until until */
        void occupyLayer(Tick until);

        /**
         * Send a retry to the port at the head of waitingForLayer. The
         * caller must ensure that the list is not empty.
         */
        void retryWaiting();

        /**
         * Handle a retry from a neighbouring module. This wraps
         * retryWaiting by verifying that there are ports waiting
         * before calling retryWaiting.
         */
        void recvRetry();

        /**
         * Register stats for the layer
         */
        void regStats();

      protected:

        /**
         * Sending the actual retry, in a manner specific to the
         * individual layers. Note that for a MasterPort, there is
         * both a RequestLayer and a SnoopResponseLayer using the same
         * port, but using different functions for the flow control.
         */
        virtual void sendRetry(SrcType* retry_port) = 0;

      private:

        /** The destination port this layer converges at. */
        DstType& port;

        /** The crossbar this layer is a part of. */
        BaseXBar& xbar;

        /** A name for this layer. */
        std::string _name;

        /**
         * We declare an enum to track the state of the layer. The
         * starting point is an idle state where the layer is waiting
         * for a packet to arrive. Upon arrival, the layer
         * transitions to the busy state, where it remains either
         * until the packet transfer is done, or the header time is
         * spent. Once the layer leaves the busy state, it can
         * either go back to idle, if no packets have arrived while it
         * was busy, or the layer goes on to retry the first port
         * in waitingForLayer. A similar transition takes place from
         * idle to retry if the layer receives a retry from one of
         * its connected ports. The retry state lasts until the port
         * in questions calls sendTiming and returns control to the
         * layer, or goes to a busy state if the port does not
         * immediately react to the retry by calling sendTiming.
         */
        enum State { IDLE, BUSY, RETRY };

        /** track the state of the layer */
        State state;

        /**
         * A deque of ports that retry should be called on because
         * the original send was delayed due to a busy layer.
         */
        std::deque<SrcType*> waitingForLayer;

        /**
         * Track who is waiting for the retry when receiving it from a
         * peer. If no port is waiting NULL is stored.
         */
        SrcType* waitingForPeer;

        /**
         * Release the layer after being occupied and return to an
         * idle state where we proceed to send a retry to any
         * potential waiting port, or drain if asked to do so.
         */
        void releaseLayer();

        /** event used to schedule a release of the layer */
        EventWrapper<Layer, &Layer::releaseLayer> releaseEvent;

        /**
         * Stats for occupancy and utilization. These stats capture
         * the time the layer spends in the busy state and are thus only
         * relevant when the memory system is in timing mode.
         */
        Stats::Scalar occupancy;
        Stats::Formula utilization;

    };

    class ReqLayer : public Layer<SlavePort,MasterPort>
    {
      public:
        /**
         * Create a request layer and give it a name.
         *
         * @param _port destination port the layer converges at
         * @param _xbar the crossbar this layer belongs to
         * @param _name the layer's name
         */
        ReqLayer(MasterPort& _port, BaseXBar& _xbar, const std::string& _name) :
            Layer(_port, _xbar, _name) {}

      protected:

        void sendRetry(SlavePort* retry_port)
        { retry_port->sendRetryReq(); }
    };

    class RespLayer : public Layer<MasterPort,SlavePort>
    {
      public:
        /**
         * Create a response layer and give it a name.
         *
         * @param _port destination port the layer converges at
         * @param _xbar the crossbar this layer belongs to
         * @param _name the layer's name
         */
        RespLayer(SlavePort& _port, BaseXBar& _xbar, const std::string& _name) :
            Layer(_port, _xbar, _name) {}

      protected:

        void sendRetry(MasterPort* retry_port)
        { retry_port->sendRetryResp(); }
    };

    class SnoopRespLayer : public Layer<SlavePort,MasterPort>
    {
      public:
        /**
         * Create a snoop response layer and give it a name.
         *
         * @param _port destination port the layer converges at
         * @param _xbar the crossbar this layer belongs to
         * @param _name the layer's name
         */
        SnoopRespLayer(MasterPort& _port, BaseXBar& _xbar,
                       const std::string& _name) :
            Layer(_port, _xbar, _name) {}

      protected:

        void sendRetry(SlavePort* retry_port)
        { retry_port->sendRetrySnoopResp(); }
    };

    /**
     * Cycles of front-end pipeline including the delay to accept the request
     * and to decode the address.
     */
    const Cycles frontendLatency;
    /** Cycles of forward latency */
    const Cycles forwardLatency;
    /** Cycles of response latency */
    const Cycles responseLatency;
    /** the width of the xbar in bytes */
    const uint32_t width;

    AddrRangeMap<PortID> portMap;

    /**
     * Remember where request packets came from so that we can route
     * responses to the appropriate port. This relies on the fact that
     * the underlying Request pointer inside the Packet stays
     * constant.
     */
    std::unordered_map<RequestPtr, PortID> routeTo;

    /** all contigous ranges seen by this crossbar */
    AddrRangeList xbarRanges;

    AddrRange defaultRange;

    /**
     * Function called by the port when the crossbar is recieving a
     * range change.
     *
     * @param master_port_id id of the port that received the change
     */
    virtual void recvRangeChange(PortID master_port_id);

    /** Find which port connected to this crossbar (if any) should be
     * given a packet with this address.
     *
     * @param addr Address to find port for.
     * @return id of port that the packet should be sent out of.
     */
    PortID findPort(Addr addr);

    // Cache for the findPort function storing recently used ports from portMap
    struct PortCache {
        bool valid;
        PortID id;
        AddrRange range;
    };

    PortCache portCache[3];

    // Checks the cache and returns the id of the port that has the requested
    // address within its range
    inline PortID checkPortCache(Addr addr) const {
        if (portCache[0].valid && portCache[0].range.contains(addr)) {
            return portCache[0].id;
        }
        if (portCache[1].valid && portCache[1].range.contains(addr)) {
            return portCache[1].id;
        }
        if (portCache[2].valid && portCache[2].range.contains(addr)) {
            return portCache[2].id;
        }

        return InvalidPortID;
    }

    // Clears the earliest entry of the cache and inserts a new port entry
    inline void updatePortCache(short id, const AddrRange& range) {
        portCache[2].valid = portCache[1].valid;
        portCache[2].id    = portCache[1].id;
        portCache[2].range = portCache[1].range;

        portCache[1].valid = portCache[0].valid;
        portCache[1].id    = portCache[0].id;
        portCache[1].range = portCache[0].range;

        portCache[0].valid = true;
        portCache[0].id    = id;
        portCache[0].range = range;
    }

    // Clears the cache. Needs to be called in constructor.
    inline void clearPortCache() {
        portCache[2].valid = false;
        portCache[1].valid = false;
        portCache[0].valid = false;
    }

    /**
     * Return the address ranges the crossbar is responsible for.
     *
     * @return a list of non-overlapping address ranges
     */
    AddrRangeList getAddrRanges() const;

    /**
     * Calculate the timing parameters for the packet. Updates the
     * headerDelay and payloadDelay fields of the packet
     * object with the relative number of ticks required to transmit
     * the header and the payload, respectively.
     *
     * @param pkt Packet to populate with timings
     * @param header_delay Header delay to be added
     */
    void calcPacketTiming(PacketPtr pkt, Tick header_delay);

    /**
     * Remember for each of the master ports of the crossbar if we got
     * an address range from the connected slave. For convenience,
     * also keep track of if we got ranges from all the slave modules
     * or not.
     */
    std::vector<bool> gotAddrRanges;
    bool gotAllAddrRanges;

    /** The master and slave ports of the crossbar */
    std::vector<QueuedSlavePort*> slavePorts;
    std::vector<MasterPort*> masterPorts;

    /** Port that handles requests that don't match any of the interfaces.*/
    PortID defaultPortID;

    /** If true, use address range provided by default device.  Any
       address not handled by another port and not in default device's
       range will cause a fatal error.  If false, just send all
       addresses not handled by another port to default device. */
    const bool useDefaultRange;

    BaseXBar(const BaseXBarParams *p);

    /**
     * Stats for transaction distribution and data passing through the
     * crossbar. The transaction distribution is globally counting
     * different types of commands. The packet count and total packet
     * size are two-dimensional vectors that are indexed by the
     * slave port and master port id (thus the neighbouring master and
     * neighbouring slave), summing up both directions (request and
     * response).
     */
    Stats::Vector transDist;
    Stats::Vector2d pktCount;
    Stats::Vector2d pktSize;

  public:

    virtual ~BaseXBar();

    virtual void init();

    /** A function used to return the port associated with this object. */
    BaseMasterPort& getMasterPort(const std::string& if_name,
                                  PortID idx = InvalidPortID);
    BaseSlavePort& getSlavePort(const std::string& if_name,
                                PortID idx = InvalidPortID);

    virtual void regStats();

};

#endif //__MEM_XBAR_HH__
<|endoftext|>