<commit_before>//
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
//
// This file is part of Qt Creator Boost.Build plugin project.
//
// This is free software; you can redistribute and/or modify it under
// the terms of the  GNU Lesser General Public License, Version 2.1
// as published by the Free Software Foundation.
// See accompanying file LICENSE.txt or copy at
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
//
#include "bbprojectnode.hpp"
#include "bbproject.hpp"
#include "bbutility.hpp"
// Qt Creator
#include <coreplugin/idocument.h>
#include <projectexplorer/projectnodes.h>
#include <utils/qtcassert.h>
// Qt
#include <QFutureInterface>
#include <QHash>
#include <QList>
#include <QSet>
#include <QString>
#include <QStringList>

namespace BoostBuildProjectManager {
namespace Internal {

ProjectNode::ProjectNode(Project* project, Core::IDocument* projectFile)
    : ProjectExplorer::ProjectNode(projectFile->filePath().toString())
    , project_(project)
    , projectFile_(projectFile)
{
    // TODO: setDisplayName(QFileInfo(projectFile->filePath()).completeBaseName());
}

bool ProjectNode::hasBuildTargets() const
{
    return false;
}

QList<ProjectExplorer::ProjectAction>
ProjectNode::supportedActions(Node* node) const
{
    Q_UNUSED(node);

    // TODO: Jamfiles (auto)editing not supported, does it make sense to manage files?
    return QList<ProjectExplorer::ProjectAction>();
}

bool ProjectNode::canAddSubProject(QString const& filePath) const
{
    Q_UNUSED(filePath)
    return false;
}

bool ProjectNode::addSubProjects(QStringList const& filePaths)
{
    Q_UNUSED(filePaths)
    return false;
}

bool ProjectNode::removeSubProjects(QStringList const& filePath)
{
    Q_UNUSED(filePath)
    return false;
}

bool ProjectNode::addFiles(QStringList const& filePaths, QStringList* notAdded = 0)
{
    Q_UNUSED(filePaths);
    Q_UNUSED(notAdded);
    return false;
}

bool ProjectNode::removeFiles(QStringList const& filePaths, QStringList* notRemoved = 0)
{
    Q_UNUSED(filePaths);
    Q_UNUSED(notRemoved);
    return false;
}

bool ProjectNode::deleteFiles(QStringList const& filePaths)
{
    Q_UNUSED(filePaths);
    return false;
}

bool ProjectNode::renameFile(QString const& filePath, QString const& newFilePath)
{
    Q_UNUSED(filePath);
    Q_UNUSED(newFilePath);
    return false;
}

QList<ProjectExplorer::RunConfiguration*> ProjectNode::runConfigurationsFor(Node* node)
{
    Q_UNUSED(node);
    return QList<ProjectExplorer::RunConfiguration*>();
}

void ProjectNode::refresh(QSet<QString> oldFileList)
{
    // The idea of refreshing files in project explorer taken from GenericProjectManager

    // Only do this once, at first run.
    if (oldFileList.isEmpty())
    {
        using ProjectExplorer::FileNode;
        FileNode* projectFileNode = new FileNode(project_->projectFilePath().toString()
                                               , ProjectExplorer::ProjectFileType
                                               , Constants::FileNotGenerated);

        FileNode* filesFileNode = new FileNode(project_->filesFilePath()
                                             , ProjectExplorer::ProjectFileType
                                             , Constants::FileNotGenerated);

        FileNode* includesFileNode = new FileNode(project_->includesFilePath()
                                             , ProjectExplorer::ProjectFileType
                                             , Constants::FileNotGenerated);

        addFileNodes(QList<FileNode*>()
            << projectFileNode << filesFileNode << includesFileNode);
    }

    oldFileList.remove(project_->filesFilePath());
    oldFileList.remove(project_->includesFilePath());

    QSet<QString> newFileList = project_->files().toSet();
    newFileList.remove(project_->filesFilePath());
    newFileList.remove(project_->includesFilePath());

    // Calculate set of added and removed files
    QSet<QString> removed = oldFileList;
    removed.subtract(newFileList);
    QSet<QString> added = newFileList;
    added.subtract(oldFileList);

    typedef QHash<QString, QStringList> FilesInPaths;
    typedef FilesInPaths::ConstIterator FilesInPathsIterator;
    using ProjectExplorer::FileNode;
    using ProjectExplorer::FileType;
    QString const baseDir = QFileInfo(path()).absolutePath();

    // Process all added files
    FilesInPaths filesInPaths = Utility::sortFilesIntoPaths(baseDir, added);
    for (FilesInPathsIterator it = filesInPaths.constBegin(),
         cend = filesInPaths.constEnd(); it != cend; ++it)
    {
        // Create node
        QString const& filePath = it.key();
        QStringList parts;
        if (!filePath.isEmpty())
            parts = filePath.split(QLatin1Char('/'));

        FolderNode* folder = findFolderByName(parts, parts.size());
        if (!folder)
            folder = createFolderByName(parts, parts.size());

        // Attach content to node
        QList<FileNode*> fileNodes;
        foreach (QString const& file, it.value())
        {
            // TODO: handle various types, mime to FileType
            FileType fileType = ProjectExplorer::SourceType;
            FileNode* fileNode = new FileNode(file, fileType, Constants::FileNotGenerated);
            fileNodes.append(fileNode);
        }

        addFileNodes(fileNodes);
    }

    // Process all removed files
    filesInPaths = Utility::sortFilesIntoPaths(baseDir, removed);
    for (FilesInPathsIterator it = filesInPaths.constBegin(),
         cend = filesInPaths.constEnd(); it != cend; ++it)
    {
        // Create node
        QString const& filePath = it.key();
        QStringList parts;
        if (!filePath.isEmpty())
            parts = filePath.split(QLatin1Char('/'));
        FolderNode* folder = findFolderByName(parts, parts.size());

        QList<FileNode*> fileNodes;
        foreach (QString const& file, it.value())
        {
            foreach (FileNode* fn, folder->fileNodes())
                if (fn->path() == file)
                    fileNodes.append(fn);
        }

        removeFileNodes(fileNodes);
    }

    // Clean up
    foreach (FolderNode* fn, subFolderNodes())
        removeEmptySubFolders(this, fn);

}

void ProjectNode::removeEmptySubFolders(FolderNode* parent, FolderNode* subParent)
{
    foreach (FolderNode* fn, subParent->subFolderNodes())
        removeEmptySubFolders(subParent, fn);

    if (subParent->subFolderNodes().isEmpty() && subParent->fileNodes().isEmpty())
        removeFolderNodes(QList<FolderNode*>() << subParent);
}

QString appendPathComponents(QStringList const& components, int const end)
{
    QString folderName;
    for (int i = 0; i < end; ++i)
    {
        folderName.append(components.at(i));
        folderName += QLatin1Char('/');
    }
    return folderName;
}

ProjectExplorer::FolderNode*
ProjectNode::createFolderByName(QStringList const& components, int const end)
{
    if (end == 0)
        return this;

    using ProjectExplorer::FolderNode;
    QString const baseDir = QFileInfo(path()).path();
    QString const folderName = appendPathComponents(components, end);
    FolderNode* folder = new FolderNode(baseDir + QLatin1Char('/') + folderName);
    folder->setDisplayName(components.at(end - 1));

    FolderNode* parent = findFolderByName(components, end - 1);
    if (!parent)
        parent = createFolderByName(components, end - 1);
    addFolderNodes(QList<FolderNode*>() << folder);

    return folder;
}

ProjectExplorer::FolderNode*
ProjectNode::findFolderByName(QStringList const& components, int const end) const
{
    if (end == 0)
        return const_cast<ProjectNode*>(this);

    using ProjectExplorer::FolderNode;
    FolderNode *parent = findFolderByName(components, end - 1);
    if (!parent)
        return 0;

    QString const folderName = appendPathComponents(components, end);
    QString const baseDir = QFileInfo(path()).path();
    foreach (FolderNode* fn, parent->subFolderNodes())
    {
        if (fn->path() == baseDir + QLatin1Char('/') + folderName)
            return fn;
    }

    return 0;
}

} // namespace Internal
} // namespace BoostBuildProjectManager
<commit_msg>Clarify conversions between QString and Utils::FileName<commit_after>//
// Copyright (C) 2013 Mateusz Łoskot <mateusz@loskot.net>
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
//
// This file is part of Qt Creator Boost.Build plugin project.
//
// This is free software; you can redistribute and/or modify it under
// the terms of the  GNU Lesser General Public License, Version 2.1
// as published by the Free Software Foundation.
// See accompanying file LICENSE.txt or copy at
// http://www.gnu.org/licenses/lgpl-2.1-standalone.html.
//
#include "bbprojectnode.hpp"
#include "bbproject.hpp"
#include "bbutility.hpp"
// Qt Creator
#include <coreplugin/idocument.h>
#include <projectexplorer/projectnodes.h>
#include <utils/qtcassert.h>
// Qt
#include <QFutureInterface>
#include <QHash>
#include <QList>
#include <QSet>
#include <QString>
#include <QStringList>

namespace BoostBuildProjectManager {
namespace Internal {

ProjectNode::ProjectNode(Project* project, Core::IDocument* projectFile)
    : ProjectExplorer::ProjectNode(projectFile->filePath())
    , project_(project)
    , projectFile_(projectFile)
{
    // TODO: setDisplayName(QFileInfo(projectFile->filePath()).completeBaseName());
}

bool ProjectNode::hasBuildTargets() const
{
    return false;
}

QList<ProjectExplorer::ProjectAction>
ProjectNode::supportedActions(Node* node) const
{
    Q_UNUSED(node);

    // TODO: Jamfiles (auto)editing not supported, does it make sense to manage files?
    return QList<ProjectExplorer::ProjectAction>();
}

bool ProjectNode::canAddSubProject(QString const& filePath) const
{
    Q_UNUSED(filePath)
    return false;
}

bool ProjectNode::addSubProjects(QStringList const& filePaths)
{
    Q_UNUSED(filePaths)
    return false;
}

bool ProjectNode::removeSubProjects(QStringList const& filePath)
{
    Q_UNUSED(filePath)
    return false;
}

bool ProjectNode::addFiles(QStringList const& filePaths, QStringList* notAdded = 0)
{
    Q_UNUSED(filePaths);
    Q_UNUSED(notAdded);
    return false;
}

bool ProjectNode::removeFiles(QStringList const& filePaths, QStringList* notRemoved = 0)
{
    Q_UNUSED(filePaths);
    Q_UNUSED(notRemoved);
    return false;
}

bool ProjectNode::deleteFiles(QStringList const& filePaths)
{
    Q_UNUSED(filePaths);
    return false;
}

bool ProjectNode::renameFile(QString const& filePath, QString const& newFilePath)
{
    Q_UNUSED(filePath);
    Q_UNUSED(newFilePath);
    return false;
}

QList<ProjectExplorer::RunConfiguration*> ProjectNode::runConfigurationsFor(Node* node)
{
    Q_UNUSED(node);
    return QList<ProjectExplorer::RunConfiguration*>();
}

void ProjectNode::refresh(QSet<QString> oldFileList)
{
    // The idea of refreshing files in project explorer taken from GenericProjectManager

    // Only do this once, at first run.
    if (oldFileList.isEmpty())
    {
        using ProjectExplorer::FileNode;
        FileNode* projectFileNode = new FileNode(project_->projectFilePath()
                                               , ProjectExplorer::ProjectFileType
                                               , Constants::FileNotGenerated);

        FileNode* filesFileNode = new FileNode(Utils::FileName::fromString(project_->filesFilePath())
                                             , ProjectExplorer::ProjectFileType
                                             , Constants::FileNotGenerated);

        FileNode* includesFileNode = new FileNode(Utils::FileName::fromString(project_->includesFilePath())
                                             , ProjectExplorer::ProjectFileType
                                             , Constants::FileNotGenerated);

        addFileNodes(QList<FileNode*>()
            << projectFileNode << filesFileNode << includesFileNode);
    }

    oldFileList.remove(project_->filesFilePath());
    oldFileList.remove(project_->includesFilePath());

    QSet<QString> newFileList = project_->files().toSet();
    newFileList.remove(project_->filesFilePath());
    newFileList.remove(project_->includesFilePath());

    // Calculate set of added and removed files
    QSet<QString> removed = oldFileList;
    removed.subtract(newFileList);
    QSet<QString> added = newFileList;
    added.subtract(oldFileList);

    typedef QHash<QString, QStringList> FilesInPaths;
    typedef FilesInPaths::ConstIterator FilesInPathsIterator;
    using ProjectExplorer::FileNode;
    using ProjectExplorer::FileType;
    QString const baseDir = QFileInfo(path().toString()).absolutePath();

    // Process all added files
    FilesInPaths filesInPaths = Utility::sortFilesIntoPaths(baseDir, added);
    for (FilesInPathsIterator it = filesInPaths.constBegin(),
         cend = filesInPaths.constEnd(); it != cend; ++it)
    {
        // Create node
        QString const& filePath = it.key();
        QStringList parts;
        if (!filePath.isEmpty())
            parts = filePath.split(QLatin1Char('/'));

        FolderNode* folder = findFolderByName(parts, parts.size());
        if (!folder)
            folder = createFolderByName(parts, parts.size());

        // Attach content to node
        QList<FileNode*> fileNodes;
        foreach (QString const& file, it.value())
        {
            // TODO: handle various types, mime to FileType
            FileType fileType = ProjectExplorer::SourceType;
            FileNode* fileNode = new FileNode(Utils::FileName::fromString(file), fileType, Constants::FileNotGenerated);
            fileNodes.append(fileNode);
        }

        addFileNodes(fileNodes);
    }

    // Process all removed files
    filesInPaths = Utility::sortFilesIntoPaths(baseDir, removed);
    for (FilesInPathsIterator it = filesInPaths.constBegin(),
         cend = filesInPaths.constEnd(); it != cend; ++it)
    {
        // Create node
        QString const& filePath = it.key();
        QStringList parts;
        if (!filePath.isEmpty())
            parts = filePath.split(QLatin1Char('/'));
        FolderNode* folder = findFolderByName(parts, parts.size());

        QList<FileNode*> fileNodes;
        foreach (QString const& file, it.value())
        {
            foreach (FileNode* fn, folder->fileNodes())
                if (fn->path() == Utils::FileName::fromString(file))
                    fileNodes.append(fn);
        }

        removeFileNodes(fileNodes);
    }

    // Clean up
    foreach (FolderNode* fn, subFolderNodes())
        removeEmptySubFolders(this, fn);

}

void ProjectNode::removeEmptySubFolders(FolderNode* parent, FolderNode* subParent)
{
    foreach (FolderNode* fn, subParent->subFolderNodes())
        removeEmptySubFolders(subParent, fn);

    if (subParent->subFolderNodes().isEmpty() && subParent->fileNodes().isEmpty())
        removeFolderNodes(QList<FolderNode*>() << subParent);
}

QString appendPathComponents(QStringList const& components, int const end)
{
    QString folderName;
    for (int i = 0; i < end; ++i)
    {
        folderName.append(components.at(i));
        folderName += QLatin1Char('/');
    }
    return folderName;
}

ProjectExplorer::FolderNode*
ProjectNode::createFolderByName(QStringList const& components, int const end)
{
    if (end == 0)
        return this;

    using ProjectExplorer::FolderNode;
    QString const baseDir = QFileInfo(path().toString()).path();
    QString const folderName = appendPathComponents(components, end);
    FolderNode* folder = new FolderNode(Utils::FileName::fromString(baseDir + QLatin1Char('/') + folderName));
    folder->setDisplayName(components.at(end - 1));

    FolderNode* parent = findFolderByName(components, end - 1);
    if (!parent)
        parent = createFolderByName(components, end - 1);
    addFolderNodes(QList<FolderNode*>() << folder);

    return folder;
}

ProjectExplorer::FolderNode*
ProjectNode::findFolderByName(QStringList const& components, int const end) const
{
    if (end == 0)
        return const_cast<ProjectNode*>(this);

    using ProjectExplorer::FolderNode;
    FolderNode *parent = findFolderByName(components, end - 1);
    if (!parent)
        return 0;

    QString const folderName = appendPathComponents(components, end);
    QString const baseDir = QFileInfo(path().toString()).path();
    foreach (FolderNode* fn, parent->subFolderNodes())
    {
        if (fn->path() == Utils::FileName::fromString(baseDir + QLatin1Char('/') + folderName))
            return fn;
    }

    return 0;
}

} // namespace Internal
} // namespace BoostBuildProjectManager
<|endoftext|>


<commit_before>#include "bochs.h"

bx_iodebug_c bx_iodebug;
bx_iodebug_c *bx_iodebug_ptr;

  struct bx_iodebug_s_type {
    Boolean enabled;
    unsigned int register_select;
    Bit32u registers[2];
    Bit32u monitored_mem_areas_start[BX_IODEBUG_MAX_AREAS];
    Bit32u monitored_mem_areas_end[BX_IODEBUG_MAX_AREAS];
  } bx_iodebug_s;

// Constructor
bx_iodebug_c::bx_iodebug_c( void )
{
  put("IODEBUG");
  settype(IODEBUGLOG);

}

// Destructor
bx_iodebug_c::~bx_iodebug_c( void )
{
}

int bx_iodebug_c::init( bx_devices_c *d )
{
  int i;

  BX_IODEBUG_THIS devices = d;
  BX_IODEBUG_THIS devices->register_io_read_handler(this, read_handler, 0x8A00,"BOCHS IODEBUG");
  BX_IODEBUG_THIS devices->register_io_write_handler(this, write_handler, 0x8A00,"BOCHS IODEBUG");
  BX_IODEBUG_THIS devices->register_io_write_handler(this, write_handler, 0x8A01,"BOCHS IODEBUG");
  fprintf( stderr, "IODEBUG initialized\n");

  bx_iodebug_s.enabled = 0;
  bx_iodebug_s.register_select = 0;
  for(i=0;i<BX_IODEBUG_MAX_AREAS;i++) {
    bx_iodebug_s.monitored_mem_areas_start[i] = 0;
    bx_iodebug_s.monitored_mem_areas_end[i] = 0;
  }

  return(1);
}

Bit32u bx_iodebug_c::read_handler(void *this_ptr, Bit32u addr, unsigned io_len)
{
  bx_iodebug_ptr = (bx_iodebug_c *) this_ptr;
  return( bx_iodebug_ptr->read(addr, io_len) );
}

Bit32u bx_iodebug_c::read( Bit32u addr, unsigned io_len )
{

  if(bx_iodebug_s.enabled) return(0x8A00);
  return(0);
}

void bx_iodebug_c::write_handler(void *this_ptr, Bit32u addr, Bit32u dvalue, unsigned io_len)
{
  bx_iodebug_c *class_ptr = (bx_iodebug_c *) this_ptr;
  class_ptr->write( addr, dvalue, io_len );
}

void bx_iodebug_c::write( Bit32u addr, Bit32u dvalue, unsigned int io_len )
{

  fprintf(stderr, "IODEBUG addr: %4x\tdvalue: %8x\tio_len: %8x\n", (unsigned int)addr, (unsigned int)dvalue, io_len);

  if( addr == 0x8A01 && io_len == 2 )
  {
      bx_iodebug_s.registers[bx_iodebug_s.register_select] =
        (bx_iodebug_s.registers[bx_iodebug_s.register_select] << 16) +
	(dvalue & 0x0000FFFF );
  }

  if( (addr != 0x8A00) || (io_len != 2) ) return;

  if( !bx_iodebug_s.enabled )
  {
    if( dvalue == 0x8A00 )
    {
      bx_iodebug_s.enabled = 1;
      fprintf(stderr, "IODEBUG enabled\n");
      bx_iodebug_s.registers[0] = 0;
      bx_iodebug_s.registers[1] = 0;
    }
    return;
  }

  switch( dvalue )
  {
    case( 0x8A01 ):
      bx_iodebug_s.register_select = 0;
      fprintf( stderr, "IODEBUG register 0 selected\n");
      break;

    case( 0x8A02 ):
      bx_iodebug_s.register_select = 1;
      fprintf( stderr, "IODEBUG register 1 selected\n");
      break;

    case( 0x8A80 ):
      bx_iodebug_s.register_select = 0;
      bx_iodebug_c::add_range(
          bx_iodebug_s.registers[0],
	  bx_iodebug_s.registers[1]);
      bx_iodebug_s.registers[0] = 0;
      bx_iodebug_s.registers[1] = 0;
      break;

    case( 0x8AFF ):
      bx_iodebug_s.enabled = 0;
      fprintf( stderr, "IODEBUG device deactivated\n");
      break;

    default:
      fprintf(stderr,"IODEBUG unsupported register code\n");
  }
}

// Static function
void bx_iodebug_c::mem_write( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data)
{
  Bit32u data32;
  Bit16u data16;
  Bit8u  data8;

  unsigned int area;
  if( !bx_iodebug_s.enabled ) return;

  area = bx_iodebug_c::range_test( addr, len );
  // Device is enabled, testing address ranges
  if( area )
  {
    area--;
    fprintf( stderr,
             "IODEBUG write to monitored memory area: %2i\tby EIP:\t\t%08X\n\trange start: \t\t%08X\trange end:\t%08X\n\taddress accessed:\t%08X\tdata written:\t",
	     area,
	     bx_cpu.eip,
	     bx_iodebug_s.monitored_mem_areas_start[area],
	     bx_iodebug_s.monitored_mem_areas_end[area],
	     (unsigned int)addr);
    data32 = * (Bit32u *)data;
    data16 = (Bit16u)data32;
    data8  = (Bit8u)data32;

    switch(len)
    {
      case(1):
        fprintf(stderr,"%02X\n", (unsigned int)data8);
	break;

      case(2):
        fprintf(stderr,"%04X\n", (unsigned int)data16);
	break;

      case(4):
        fprintf(stderr,"%08X\n", (unsigned int)data32);
	break;

      default:
        fprintf(stderr, "unsupported write size\n");
    }
  }
}

void bx_iodebug_c::mem_read( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data)
{
  if( !bx_iodebug_s.enabled ) return;

  // Device is enabled, testing address range
}

unsigned int bx_iodebug_c::range_test( Bit32u addr, unsigned int len )
{
  unsigned int i;

  for(i=0;i<BX_IODEBUG_MAX_AREAS;i++)
  {
    if( (bx_iodebug_s.monitored_mem_areas_start[i]!=0) ||
        (bx_iodebug_s.monitored_mem_areas_end[i]!=0) )
    {
      if( (Bit32u)(addr+len-1) < bx_iodebug_s.monitored_mem_areas_start[i] )
        continue;
      if( addr < bx_iodebug_s.monitored_mem_areas_end[i] )
      {
        return(++i);
      }
    }
  }
  return(0);
}

void bx_iodebug_c::add_range( Bit32u addr_start, Bit32u addr_end )
{
  unsigned int i;
  for(i=0;i<BX_IODEBUG_MAX_AREAS;i++)
  {
    if( !bx_iodebug_s.monitored_mem_areas_start[i] &&
        !bx_iodebug_s.monitored_mem_areas_end[i] )
    {
	bx_iodebug_s.monitored_mem_areas_start[i] = addr_start;
	bx_iodebug_s.monitored_mem_areas_end[i] = addr_end;
	fprintf(stderr, "IODEBUG added range successfully in slot: %i\n",i);
	return;
    }
  }
  fprintf(stderr, "IODEBUG unable to register memory range, all slots taken\n");
}
<commit_msg>added support for the debugger, it now returns to the debugger prompt<commit_after>#include "bochs.h"

bx_iodebug_c bx_iodebug;
bx_iodebug_c *bx_iodebug_ptr;

  struct bx_iodebug_s_type {
    Boolean enabled;
    unsigned int register_select;
    Bit32u registers[2];
    Bit32u monitored_mem_areas_start[BX_IODEBUG_MAX_AREAS];
    Bit32u monitored_mem_areas_end[BX_IODEBUG_MAX_AREAS];
  } bx_iodebug_s;

// Constructor
bx_iodebug_c::bx_iodebug_c( void )
{
  put("IODEBUG");
  settype(IODEBUGLOG);

}

// Destructor
bx_iodebug_c::~bx_iodebug_c( void )
{
}

int bx_iodebug_c::init( bx_devices_c *d )
{
  int i;

  BX_IODEBUG_THIS devices = d;
  BX_IODEBUG_THIS devices->register_io_read_handler(this, read_handler, 0x8A00,"BOCHS IODEBUG");
  BX_IODEBUG_THIS devices->register_io_write_handler(this, write_handler, 0x8A00,"BOCHS IODEBUG");
  BX_IODEBUG_THIS devices->register_io_write_handler(this, write_handler, 0x8A01,"BOCHS IODEBUG");
//  fprintf( stderr, "IODEBUG initialized\n");

  bx_iodebug_s.enabled = 0;
  bx_iodebug_s.register_select = 0;
  for(i=0;i<BX_IODEBUG_MAX_AREAS;i++) {
    bx_iodebug_s.monitored_mem_areas_start[i] = 0;
    bx_iodebug_s.monitored_mem_areas_end[i] = 0;
  }

  return(1);
}

Bit32u bx_iodebug_c::read_handler(void *this_ptr, Bit32u addr, unsigned io_len)
{
  bx_iodebug_ptr = (bx_iodebug_c *) this_ptr;
  return( bx_iodebug_ptr->read(addr, io_len) );
}

Bit32u bx_iodebug_c::read( Bit32u addr, unsigned io_len )
{

  if(bx_iodebug_s.enabled) return(0x8A00);
  return(0);
}

void bx_iodebug_c::write_handler(void *this_ptr, Bit32u addr, Bit32u dvalue, unsigned io_len)
{
  bx_iodebug_c *class_ptr = (bx_iodebug_c *) this_ptr;
  class_ptr->write( addr, dvalue, io_len );
}

void bx_iodebug_c::write( Bit32u addr, Bit32u dvalue, unsigned int io_len )
{

//  fprintf(stderr, "IODEBUG addr: %4x\tdvalue: %8x\tio_len: %8x\n", (unsigned int)addr, (unsigned int)dvalue, io_len);

  if( addr == 0x8A01 && io_len == 2 )
  {
      bx_iodebug_s.registers[bx_iodebug_s.register_select] =
        (bx_iodebug_s.registers[bx_iodebug_s.register_select] << 16) +
	(dvalue & 0x0000FFFF );
  }

  if( (addr != 0x8A00) || (io_len != 2) ) return;

  if( !bx_iodebug_s.enabled )
  {
    if( dvalue == 0x8A00 )
    {
      bx_iodebug_s.enabled = 1;
//      fprintf(stderr, "IODEBUG enabled\n");
      bx_iodebug_s.registers[0] = 0;
      bx_iodebug_s.registers[1] = 0;
    }
    return;
  }

  switch( dvalue )
  {
    case( 0x8A01 ):
      bx_iodebug_s.register_select = 0;
//      fprintf( stderr, "IODEBUG register 0 selected\n");
      break;

    case( 0x8A02 ):
      bx_iodebug_s.register_select = 1;
//      fprintf( stderr, "IODEBUG register 1 selected\n");
      break;

    case( 0x8A80 ):
      bx_iodebug_s.register_select = 0;
      bx_iodebug_c::add_range(
          bx_iodebug_s.registers[0],
	  bx_iodebug_s.registers[1]);
      bx_iodebug_s.registers[0] = 0;
      bx_iodebug_s.registers[1] = 0;
      break;

    case( 0x8AFF ):
      bx_iodebug_s.enabled = 0;
//      fprintf( stderr, "IODEBUG device deactivated\n");
//      break;

//    default:
//      fprintf(stderr,"IODEBUG unsupported register code\n");
  }
}

// Static function
void bx_iodebug_c::mem_write( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data)
{
  Bit32u data32;
  Bit16u data16;
  Bit8u  data8;

  unsigned int area;
  if( !bx_iodebug_s.enabled ) return;

  area = bx_iodebug_c::range_test( addr, len );
  // Device is enabled, testing address ranges
  if( area )
  {
    area--;
#if BX_DEBUGGER
  fprintf( stdout, "%s @ eip: %8X wrote at monitored memory location %8X\n", cpu->name, cpu->eip, addr);
  bx_guard.interrupt_requested=1;
#else
    fprintf( stderr,
             "IODEBUG write to monitored memory area: %2i\tby EIP:\t\t%08X\n\trange start: \t\t%08X\trange end:\t%08X\n\taddress accessed:\t%08X\tdata written:\t",
	     area,
	     cpu->eip,
	     bx_iodebug_s.monitored_mem_areas_start[area],
	     bx_iodebug_s.monitored_mem_areas_end[area],
	     (unsigned int)addr);

    data32 = * (Bit32u *)data;
    data16 = (Bit16u)data32;
    data8  = (Bit8u)data32;

    switch(len)
    {
      case(1):
        fprintf(stderr,"%02X\n", (unsigned int)data8);
	break;

      case(2):
        fprintf(stderr,"%04X\n", (unsigned int)data16);
	break;

      case(4):
        fprintf(stderr,"%08X\n", (unsigned int)data32);
	break;

      default:
        fprintf(stderr, "unsupported write size\n");
    }
#endif
  }
}

void bx_iodebug_c::mem_read( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data)
{
  Bit32u data32;
  Bit16u data16;
  Bit8u  data8;

  unsigned int area;
  if( !bx_iodebug_s.enabled ) return;

  area = bx_iodebug_c::range_test( addr, len );
  // Device is enabled, testing address ranges
  if( area )
  {
    area--;
#if BX_DEBUGGER
  fprintf( stdout, "%s @ eip: %8X wrote at monitored memory location %8X\n", cpu->name, cpu->eip, addr);
  bx_guard.interrupt_requested=1;
#else
    fprintf( stderr,
             "IODEBUG read to monitored memory area: %2i\tby EIP:\t\t%08X\n\trange start: \t\t%08X\trange end:\t%08X\n\taddress accessed:\t%08X\tdata written:\t",
	     area,
	     cpu->eip,
	     bx_iodebug_s.monitored_mem_areas_start[area],
	     bx_iodebug_s.monitored_mem_areas_end[area],
	     (unsigned int)addr);
    data32 = * (Bit32u *)data;
    data16 = (Bit16u)data32;
    data8  = (Bit8u)data32;

    switch(len)
    {
      case(1):
        fprintf(stderr,"%02X\n", (unsigned int)data8);
	break;

      case(2):
        fprintf(stderr,"%04X\n", (unsigned int)data16);
	break;

      case(4):
        fprintf(stderr,"%08X\n", (unsigned int)data32);
	break;

      default:
        fprintf(stderr, "unsupported write size\n");
    }
#endif
  }
}

unsigned int bx_iodebug_c::range_test( Bit32u addr, unsigned int len )
{
  unsigned int i;

  for(i=0;i<BX_IODEBUG_MAX_AREAS;i++)
  {
    if( (bx_iodebug_s.monitored_mem_areas_start[i]!=0) ||
        (bx_iodebug_s.monitored_mem_areas_end[i]!=0) )
    {
      if( (Bit32u)(addr+len-1) < bx_iodebug_s.monitored_mem_areas_start[i] )
        continue;
      if( addr < bx_iodebug_s.monitored_mem_areas_end[i] )
      {
        return(++i);
      }
    }
  }
  return(0);
}

void bx_iodebug_c::add_range( Bit32u addr_start, Bit32u addr_end )
{
  unsigned int i;
  for(i=0;i<BX_IODEBUG_MAX_AREAS;i++)
  {
    if( !bx_iodebug_s.monitored_mem_areas_start[i] &&
        !bx_iodebug_s.monitored_mem_areas_end[i] )
    {
	bx_iodebug_s.monitored_mem_areas_start[i] = addr_start;
	bx_iodebug_s.monitored_mem_areas_end[i] = addr_end;
//	fprintf(stderr, "IODEBUG added range successfully in slot: %i\n",i);
	return;
    }
  }
//  fprintf(stderr, "IODEBUG unable to register memory range, all slots taken\n");
}
<|endoftext|>


<commit_before><commit_msg>Planning: remove dup code<commit_after><|endoftext|>


<commit_before>/*
* Copyright (c) 2003-2006 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/
//#define TEST_MYSTRING
#define TEST_TWOFISH
#define TEST_SHA256
#define TEST_HMAC_SHA256
#define TEST_XSTRING

#ifdef TEST_MYSTRING
#include "MyStringTest.h"
#endif
#ifdef TEST_TWOFISH
#include "TwoFishTest.h"
#endif
#ifdef TEST_SHA256
#include "SHA256Test.h"
#endif
#ifdef TEST_HMAC_SHA256
#include "HMAC_SHA256Test.h"
#endif
#ifdef TEST_XSTRING
#include "StringXTest.h"
#endif
#include <iostream>
using namespace std;

int main()
{
#ifdef TEST_MYSTRING
  CMyStringTest t1;
  t1.setStream(&cout);
  t1.run();
  t1.report();
#endif
#ifdef TEST_TWOFISH
  CTwoFishTest t2;
  t2.setStream(&cout);
  t2.run();
  t2.report();
#endif
#ifdef TEST_SHA256
  CSHA256Test t3;
  t3.setStream(&cout);
  t3.run();
  t3.report();
#endif
#ifdef TEST_HMAC_SHA256
  CHMAC_SHA256Test t4;
  t4.setStream(&cout);
  t4.run();
  t4.report();
#endif
#ifdef TEST_XSTRING
  StringXTest t5;
  t5.setStream(&cout);
  t5.run();
  t5.report();
#endif
  return 0;
}
<commit_msg>Murphy - wait with CMyString for Linux for now...<commit_after>/*
* Copyright (c) 2003-2006 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/
#define TEST_MYSTRING
#define TEST_TWOFISH
#define TEST_SHA256
#define TEST_HMAC_SHA256
#define TEST_STRINGX

#ifdef TEST_MYSTRING
#include "MyStringTest.h"
#endif
#ifdef TEST_TWOFISH
#include "TwoFishTest.h"
#endif
#ifdef TEST_SHA256
#include "SHA256Test.h"
#endif
#ifdef TEST_HMAC_SHA256
#include "HMAC_SHA256Test.h"
#endif
#ifdef TEST_STRINGX
#include "StringXTest.h"
#endif
#include <iostream>
using namespace std;

int main()
{
#ifdef TEST_MYSTRING
  CMyStringTest t1;
  t1.setStream(&cout);
  t1.run();
  t1.report();
#endif
#ifdef TEST_TWOFISH
  CTwoFishTest t2;
  t2.setStream(&cout);
  t2.run();
  t2.report();
#endif
#ifdef TEST_SHA256
  CSHA256Test t3;
  t3.setStream(&cout);
  t3.run();
  t3.report();
#endif
#ifdef TEST_HMAC_SHA256
  CHMAC_SHA256Test t4;
  t4.setStream(&cout);
  t4.run();
  t4.report();
#endif
#ifdef TEST_STRINGX
  StringXTest t5;
  t5.setStream(&cout);
  t5.run();
  t5.report();
#endif
  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016, Nils Asmussen
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 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.
 *
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of the FreeBSD Project.
 */

#include "cpu/dtu-accel/yieldsm.hh"

std::string
YieldSM::stateName() const
{
    std::ostringstream os;
    static const char *names[] =
    {
        "CHECK", "WAIT", "REPORT", "SYSCALL", "SLEEP"
    };
    os << names[static_cast<size_t>(state)];
    if (state == YLD_SYSCALL)
        os << ":" << syscsm->stateName();
    return os.str();
}

PacketPtr
YieldSM::tick()
{
    PacketPtr pkt = nullptr;

    switch(state)
    {
        case State::YLD_CHECK:
        {
            pkt = accel->createPacket(
                DtuAccel::RCTMUX_YIELD, sizeof(uint64_t), MemCmd::ReadReq
            );
            break;
        }
        case State::YLD_WAIT:
        {
            yieldStart = accel->curCycle();
            pkt = accel->createDtuCmdPkt(Dtu::Command::SLEEP, 0, 0, 0, report);
            break;
        }
        case State::YLD_REPORT:
        {
            syscall.opcode = 10;   /* VPE_CTRL */
            syscall.vpe_sel = 0;   /* self */
            syscall.op = 2;        /* VCTRL_YIELD */
            syscall.arg = 0;       /* unused */

            pkt = accel->createPacket(
                accel->sendMsgAddr(), sizeof(syscall), MemCmd::WriteReq
            );
            memcpy(pkt->getPtr<void>(), &syscall, sizeof(syscall));
            break;
        }
        case State::YLD_SYSCALL:
        {
            pkt = syscsm->tick();
            break;
        }
        case State::YLD_SLEEP:
        {
            pkt = accel->createDtuCmdPkt(Dtu::Command::SLEEP, 0, 0, 0, 0);
            break;
        }
    }

    return pkt;
}

bool
YieldSM::handleMemResp(PacketPtr pkt)
{
    auto lastState = state;

    switch(state)
    {
        case State::YLD_CHECK:
        {
            report = *pkt->getConstPtr<uint64_t>();
            if (report > 0)
                state = State::YLD_WAIT;
            else
                state = State::YLD_SLEEP;
            break;
        }
        case State::YLD_WAIT:
        {
            if (accel->curCycle() < yieldStart + report)
                return true;

            state = State::YLD_REPORT;
            break;
        }
        case State::YLD_REPORT:
        {
            syscsm->start(sizeof(syscall));
            state = State::YLD_SYSCALL;
            break;
        }
        case State::YLD_SYSCALL:
        {
            if(syscsm->handleMemResp(pkt))
                state = State::YLD_SLEEP;
            break;
        }
        case State::YLD_SLEEP:
        {
            return true;
        }
    }

    stateChanged = state != lastState;

    return false;
}
<commit_msg>DtuAccel: use syscall constants in yield SM.<commit_after>/*
 * Copyright (c) 2016, Nils Asmussen
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 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.
 *
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of the FreeBSD Project.
 */

#include "cpu/dtu-accel/yieldsm.hh"

std::string
YieldSM::stateName() const
{
    std::ostringstream os;
    static const char *names[] =
    {
        "CHECK", "WAIT", "REPORT", "SYSCALL", "SLEEP"
    };
    os << names[static_cast<size_t>(state)];
    if (state == YLD_SYSCALL)
        os << ":" << syscsm->stateName();
    return os.str();
}

PacketPtr
YieldSM::tick()
{
    PacketPtr pkt = nullptr;

    switch(state)
    {
        case State::YLD_CHECK:
        {
            pkt = accel->createPacket(
                DtuAccel::RCTMUX_YIELD, sizeof(uint64_t), MemCmd::ReadReq
            );
            break;
        }
        case State::YLD_WAIT:
        {
            yieldStart = accel->curCycle();
            pkt = accel->createDtuCmdPkt(Dtu::Command::SLEEP, 0, 0, 0, report);
            break;
        }
        case State::YLD_REPORT:
        {
            syscall.opcode = SyscallSM::VPE_CTRL;
            syscall.vpe_sel = 0;   /* self */
            syscall.op = SyscallSM::VCTRL_YIELD;
            syscall.arg = 0;       /* unused */

            pkt = accel->createPacket(
                accel->sendMsgAddr(), sizeof(syscall), MemCmd::WriteReq
            );
            memcpy(pkt->getPtr<void>(), &syscall, sizeof(syscall));
            break;
        }
        case State::YLD_SYSCALL:
        {
            pkt = syscsm->tick();
            break;
        }
        case State::YLD_SLEEP:
        {
            pkt = accel->createDtuCmdPkt(Dtu::Command::SLEEP, 0, 0, 0, 0);
            break;
        }
    }

    return pkt;
}

bool
YieldSM::handleMemResp(PacketPtr pkt)
{
    auto lastState = state;

    switch(state)
    {
        case State::YLD_CHECK:
        {
            report = *pkt->getConstPtr<uint64_t>();
            if (report > 0)
                state = State::YLD_WAIT;
            else
                state = State::YLD_SLEEP;
            break;
        }
        case State::YLD_WAIT:
        {
            if (accel->curCycle() < yieldStart + report)
                return true;

            state = State::YLD_REPORT;
            break;
        }
        case State::YLD_REPORT:
        {
            syscsm->start(sizeof(syscall));
            state = State::YLD_SYSCALL;
            break;
        }
        case State::YLD_SYSCALL:
        {
            if(syscsm->handleMemResp(pkt))
                state = State::YLD_SLEEP;
            break;
        }
        case State::YLD_SLEEP:
        {
            return true;
        }
    }

    stateChanged = state != lastState;

    return false;
}
<|endoftext|>


<commit_before>#pragma once

// ----------------------------------------------------------------------
// std::vector<std::string> split(const std::string& s, const std::string& delim, bool keep_empty = Split::KeepEmpty)
// Split string by delimiter into array of substrings
// std::vector<std::string> split(const std::string& s, const std::string& delim, bool keep_empty = Split::KeepEmpty)

// std::string strip(std::string source)
// Removes leading and trailing spaces from string
//
// ----------------------------------------------------------------------

#include <string>
#include <vector>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <iterator>
#include <utility>
#include <initializer_list>
#include <numeric>

// ----------------------------------------------------------------------

namespace string
{

// ----------------------------------------------------------------------

    enum class Split { RemoveEmpty, KeepEmpty };

      // http://stackoverflow.com/questions/236129/split-a-string-in-c
    inline std::vector<std::string> split(std::string s, std::string delim, Split keep_empty = Split::KeepEmpty)
    {
        std::vector<std::string> result;
        if (! delim.empty()) {
            for (std::string::iterator substart = s.begin(), subend = substart; substart <= s.end(); substart = subend + static_cast<std::string::difference_type>(delim.size())) {
                subend = std::search(substart, s.end(), delim.begin(), delim.end());
                if (substart != subend || keep_empty == Split::KeepEmpty) {
                    result.push_back(std::string(substart, subend));
                }
            }
        }
        else {
            result.push_back(s);
        }
        return result;
    }

      // ----------------------------------------------------------------------

    namespace _internal {
        template <typename InputIterator, typename Source> inline std::pair<InputIterator, InputIterator> strip_begin_end(Source& source)
        {
            auto predicate = [](auto c) { return std::isspace(c); }; // have to use lambda, other compiler cannot infer Predicate type from isspace
            auto e = std::find_if_not(source.rbegin(), source.rend(), predicate);
            auto b = std::find_if_not(source.begin(), e.base(), predicate);
            return std::make_pair(b, e.base());
        }
    } // namespace _internal

    // inline std::string& strip(std::string& source)
    // {
    //     auto be = _internal::strip_begin_end<std::string::iterator>(source);
    //     source.erase(be.second, source.end()); // erase at the end first
    //     source.erase(source.begin(), be.first); // invalidates be.second!
    //     return source;
    // }

    // inline std::string strip(std::string&& source)
    // {
    //     auto be = _internal::strip_begin_end<std::string::iterator>(source);
    //     source.erase(be.second, source.end()); // erase at the end first
    //     source.erase(source.begin(), be.first); // invalidates be.second!
    //     return source;
    // }

    inline std::string strip(std::string source)
    {
        auto be = _internal::strip_begin_end<std::string::const_iterator>(source);
        return std::string(be.first, be.second);
    }

      // ----------------------------------------------------------------------

    inline std::string replace(std::string source, std::string look_for, std::string replace_with)
    {
        std::string result;
        std::string::size_type start = 0;
        while (true) {
            const auto pos = source.find(look_for, start);
            if (pos != std::string::npos) {
                result.append(source.begin() + static_cast<std::string::difference_type>(start), source.begin() + static_cast<std::string::difference_type>(pos));
                result.append(replace_with);
                start = pos + look_for.size();
            }
            else {
                result.append(source.begin() + static_cast<std::string::difference_type>(start), source.end());
                break;
            }
        }
        return result;
    }

      // ----------------------------------------------------------------------

    // inline std::string& lower(std::string& source)
    // {
    //     std::transform(source.begin(), source.end(), source.begin(), ::tolower);
    //     return source;
    // }

    inline std::string lower(std::string source)
    {
        std::string result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), ::tolower);
        return result;
    }

    // inline std::string& upper(std::string& source)
    // {
    //     std::transform(source.begin(), source.end(), source.begin(), ::toupper);
    //     return source;
    // }

    inline std::string upper(std::string source)
    {
        std::string result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), ::toupper);
        return result;
    }

    // inline std::string& capitalize(std::string& source)
    // {
    //     if (!source.empty()) {
    //         std::transform(source.begin(), source.begin() + 1, source.begin(), ::toupper);
    //         std::transform(source.begin() + 1, source.end(), source.begin() + 1, ::tolower);
    //     }
    //     return source;
    // }

    inline std::string capitalize(std::string source)
    {
        std::string result;
        if (!source.empty()) {
            std::transform(source.begin(), source.begin() + 1, std::back_inserter(result), ::toupper);
            std::transform(source.begin() + 1, source.end(), std::back_inserter(result), ::tolower);
        }
        return result;
    }

    template <typename Collection> inline std::string join(std::string separator, const Collection& values)
    {
        const size_t resulting_size = std::accumulate(values.begin(), values.end(), separator.size() * (values.size() - 1), [](size_t acc, const std::string& n) -> size_t { return acc + n.size(); });
        std::string result;
        result.reserve(resulting_size);
        for (const auto& value: values) {
            if (!result.empty())
                result.append(separator);
            result.append(value);
        }
        return result;
    }

// ----------------------------------------------------------------------

} // namespace string

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>improvements in string::join<commit_after>#pragma once

// ----------------------------------------------------------------------
// std::vector<std::string> split(const std::string& s, const std::string& delim, bool keep_empty = Split::KeepEmpty)
// Split string by delimiter into array of substrings
// std::vector<std::string> split(const std::string& s, const std::string& delim, bool keep_empty = Split::KeepEmpty)

// std::string strip(std::string source)
// Removes leading and trailing spaces from string
//
// ----------------------------------------------------------------------

#include <string>
#include <vector>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <iterator>
#include <utility>
#include <initializer_list>
#include <numeric>

// ----------------------------------------------------------------------

namespace string
{

// ----------------------------------------------------------------------

    enum class Split { RemoveEmpty, KeepEmpty };

      // http://stackoverflow.com/questions/236129/split-a-string-in-c
    inline std::vector<std::string> split(std::string s, std::string delim, Split keep_empty = Split::KeepEmpty)
    {
        std::vector<std::string> result;
        if (! delim.empty()) {
            for (std::string::iterator substart = s.begin(), subend = substart; substart <= s.end(); substart = subend + static_cast<std::string::difference_type>(delim.size())) {
                subend = std::search(substart, s.end(), delim.begin(), delim.end());
                if (substart != subend || keep_empty == Split::KeepEmpty) {
                    result.push_back(std::string(substart, subend));
                }
            }
        }
        else {
            result.push_back(s);
        }
        return result;
    }

      // ----------------------------------------------------------------------

    namespace _internal {
        template <typename InputIterator, typename Source> inline std::pair<InputIterator, InputIterator> strip_begin_end(Source& source)
        {
            auto predicate = [](auto c) { return std::isspace(c); }; // have to use lambda, other compiler cannot infer Predicate type from isspace
            auto e = std::find_if_not(source.rbegin(), source.rend(), predicate);
            auto b = std::find_if_not(source.begin(), e.base(), predicate);
            return std::make_pair(b, e.base());
        }
    } // namespace _internal

    // inline std::string& strip(std::string& source)
    // {
    //     auto be = _internal::strip_begin_end<std::string::iterator>(source);
    //     source.erase(be.second, source.end()); // erase at the end first
    //     source.erase(source.begin(), be.first); // invalidates be.second!
    //     return source;
    // }

    // inline std::string strip(std::string&& source)
    // {
    //     auto be = _internal::strip_begin_end<std::string::iterator>(source);
    //     source.erase(be.second, source.end()); // erase at the end first
    //     source.erase(source.begin(), be.first); // invalidates be.second!
    //     return source;
    // }

    inline std::string strip(std::string source)
    {
        auto be = _internal::strip_begin_end<std::string::const_iterator>(source);
        return std::string(be.first, be.second);
    }

      // ----------------------------------------------------------------------

    inline std::string replace(std::string source, std::string look_for, std::string replace_with)
    {
        std::string result;
        std::string::size_type start = 0;
        while (true) {
            const auto pos = source.find(look_for, start);
            if (pos != std::string::npos) {
                result.append(source.begin() + static_cast<std::string::difference_type>(start), source.begin() + static_cast<std::string::difference_type>(pos));
                result.append(replace_with);
                start = pos + look_for.size();
            }
            else {
                result.append(source.begin() + static_cast<std::string::difference_type>(start), source.end());
                break;
            }
        }
        return result;
    }

      // ----------------------------------------------------------------------

    // inline std::string& lower(std::string& source)
    // {
    //     std::transform(source.begin(), source.end(), source.begin(), ::tolower);
    //     return source;
    // }

    inline std::string lower(std::string source)
    {
        std::string result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), ::tolower);
        return result;
    }

    // inline std::string& upper(std::string& source)
    // {
    //     std::transform(source.begin(), source.end(), source.begin(), ::toupper);
    //     return source;
    // }

    inline std::string upper(std::string source)
    {
        std::string result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), ::toupper);
        return result;
    }

    // inline std::string& capitalize(std::string& source)
    // {
    //     if (!source.empty()) {
    //         std::transform(source.begin(), source.begin() + 1, source.begin(), ::toupper);
    //         std::transform(source.begin() + 1, source.end(), source.begin() + 1, ::tolower);
    //     }
    //     return source;
    // }

    inline std::string capitalize(std::string source)
    {
        std::string result;
        if (!source.empty()) {
            std::transform(source.begin(), source.begin() + 1, std::back_inserter(result), ::toupper);
            std::transform(source.begin() + 1, source.end(), std::back_inserter(result), ::tolower);
        }
        return result;
    }

    template <typename Collection> inline std::string join(std::string separator, const Collection& values)
    {
        std::string result;
        if (!values.empty()) {
            const size_t resulting_size = std::accumulate(values.begin(), values.end(), separator.size() * (values.size() - 1), [](size_t acc, const std::string& n) -> size_t { return acc + n.size(); });
            result.reserve(resulting_size);
            for (const auto& value: values) {
                if (!result.empty())
                    result.append(separator);
                result.append(value);
            }
        }
        return result;
    }

// ----------------------------------------------------------------------

} // namespace string

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2004-2006 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: Kevin Lim
 */

#include "config/use_checker.hh"

#include "arch/alpha/faults.hh"
#include "arch/alpha/isa_traits.hh"
#include "base/cprintf.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "cpu/checker/thread_context.hh"
#include "sim/sim_events.hh"
#include "sim/stats.hh"

#include "cpu/o3/alpha/cpu.hh"
#include "cpu/o3/alpha/params.hh"
#include "cpu/o3/alpha/thread_context.hh"
#include "cpu/o3/comm.hh"
#include "cpu/o3/thread_state.hh"

#if FULL_SYSTEM
#include "arch/alpha/osfpal.hh"
#include "arch/isa_traits.hh"
#include "arch/kernel_stats.hh"
#include "cpu/quiesce_event.hh"
#include "sim/sim_exit.hh"
#include "sim/system.hh"
#endif

template <class Impl>
AlphaO3CPU<Impl>::AlphaO3CPU(Params *params)
#if FULL_SYSTEM
    : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
#else
    : FullO3CPU<Impl>(params)
#endif
{
    DPRINTF(O3CPU, "Creating AlphaO3CPU object.\n");

    // Setup any thread state.
    this->thread.resize(this->numThreads);

    for (int i = 0; i < this->numThreads; ++i) {
#if FULL_SYSTEM
        // SMT is not supported in FS mode yet.
        assert(this->numThreads == 1);
        this->thread[i] = new Thread(this, 0);
        this->thread[i]->setStatus(ThreadContext::Suspended);
#else
        if (i < params->workload.size()) {
            DPRINTF(O3CPU, "Workload[%i] process is %#x",
                    i, this->thread[i]);
            this->thread[i] = new Thread(this, i, params->workload[i], i);

            this->thread[i]->setStatus(ThreadContext::Suspended);

            //usedTids[i] = true;
            //threadMap[i] = i;
        } else {
            //Allocate Empty thread so M5 can use later
            //when scheduling threads to CPU
            Process* dummy_proc = NULL;

            this->thread[i] = new Thread(this, i, dummy_proc, i);
            //usedTids[i] = false;
        }
#endif // !FULL_SYSTEM

        ThreadContext *tc;

        // Setup the TC that will serve as the interface to the threads/CPU.
        AlphaTC<Impl> *alpha_tc =
            new AlphaTC<Impl>;

        tc = alpha_tc;

        // If we're using a checker, then the TC should be the
        // CheckerThreadContext.
#if USE_CHECKER
        if (params->checker) {
            tc = new CheckerThreadContext<AlphaTC<Impl> >(
                alpha_tc, this->checker);
        }
#endif

        alpha_tc->cpu = this;
        alpha_tc->thread = this->thread[i];

#if FULL_SYSTEM
        // Setup quiesce event.
        this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc);

        Port *mem_port;
        FunctionalPort *phys_port;
        VirtualPort *virt_port;
        phys_port = new FunctionalPort(csprintf("%s-%d-funcport",
                                                name(), i));
        mem_port = this->system->physmem->getPort("functional");
        mem_port->setPeer(phys_port);
        phys_port->setPeer(mem_port);

        virt_port = new VirtualPort(csprintf("%s-%d-vport",
                                             name(), i));
        mem_port = this->system->physmem->getPort("functional");
        mem_port->setPeer(virt_port);
        virt_port->setPeer(mem_port);

        this->thread[i]->setPhysPort(phys_port);
        this->thread[i]->setVirtPort(virt_port);
#endif
        // Give the thread the TC.
        this->thread[i]->tc = tc;

        // Add the TC to the CPU's list of TC's.
        this->threadContexts.push_back(tc);
    }

    for (int i=0; i < this->numThreads; i++) {
        this->thread[i]->setFuncExeInst(0);
    }

    // Sets CPU pointers. These must be set at this level because the CPU
    // pointers are defined to be the highest level of CPU class.
    this->fetch.setCPU(this);
    this->decode.setCPU(this);
    this->rename.setCPU(this);
    this->iew.setCPU(this);
    this->commit.setCPU(this);

    this->rob.setCPU(this);
    this->regFile.setCPU(this);

    lockAddr = 0;
    lockFlag = false;
}

template <class Impl>
void
AlphaO3CPU<Impl>::regStats()
{
    // Register stats for everything that has stats.
    this->fullCPURegStats();
    this->fetch.regStats();
    this->decode.regStats();
    this->rename.regStats();
    this->iew.regStats();
    this->commit.regStats();
}

template <class Impl>
TheISA::MiscReg
AlphaO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
{
    return this->regFile.readMiscReg(misc_reg, tid);
}

template <class Impl>
TheISA::MiscReg
AlphaO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, unsigned tid)
{
    return this->regFile.readMiscRegWithEffect(misc_reg, tid);
}

template <class Impl>
void
AlphaO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
{
    this->regFile.setMiscReg(misc_reg, val, tid);
}

template <class Impl>
void
AlphaO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
                                       unsigned tid)
{
    this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
}

template <class Impl>
void
AlphaO3CPU<Impl>::squashFromTC(unsigned tid)
{
    this->thread[tid]->inSyscall = true;
    this->commit.generateTCEvent(tid);
}

#if FULL_SYSTEM

template <class Impl>
void
AlphaO3CPU<Impl>::post_interrupt(int int_num, int index)
{
    BaseCPU::post_interrupt(int_num, index);

    if (this->thread[0]->status() == ThreadContext::Suspended) {
        DPRINTF(IPI,"Suspended Processor awoke\n");
        this->threadContexts[0]->activate();
    }
}

template <class Impl>
Fault
AlphaO3CPU<Impl>::hwrei(unsigned tid)
{
    // Need to clear the lock flag upon returning from an interrupt.
    this->setMiscReg(TheISA::Lock_Flag_DepTag, false, tid);

    this->thread[tid]->kernelStats->hwrei();

    this->checkInterrupts = true;

    // FIXME: XXX check for interrupts? XXX
    return NoFault;
}

template <class Impl>
bool
AlphaO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid)
{
    if (this->thread[tid]->kernelStats)
        this->thread[tid]->kernelStats->callpal(palFunc,
                                                this->threadContexts[tid]);

    switch (palFunc) {
      case PAL::halt:
        halt();
        if (--System::numSystemsRunning == 0)
            exitSimLoop("all cpus halted");
        break;

      case PAL::bpt:
      case PAL::bugchk:
        if (this->system->breakpoint())
            return false;
        break;
    }

    return true;
}

template <class Impl>
void
AlphaO3CPU<Impl>::processInterrupts()
{
    // Check for interrupts here.  For now can copy the code that
    // exists within isa_fullsys_traits.hh.  Also assume that thread 0
    // is the one that handles the interrupts.
    // @todo: Possibly consolidate the interrupt checking code.
    // @todo: Allow other threads to handle interrupts.

    // Check if there are any outstanding interrupts
    //Handle the interrupts
    Fault interrupt = this->interrupts.getInterrupt(this->tcBase(0));

    if (interrupt != NoFault) {
        this->checkInterrupts = false;
        this->trap(interrupt, 0);
    }
}

#endif // FULL_SYSTEM

template <class Impl>
void
AlphaO3CPU<Impl>::trap(Fault fault, unsigned tid)
{
    // Pass the thread's TC into the invoke method.
    fault->invoke(this->threadContexts[tid]);
}

#if !FULL_SYSTEM

template <class Impl>
void
AlphaO3CPU<Impl>::syscall(int64_t callnum, int tid)
{
    DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);

    DPRINTF(Activity,"Activity: syscall() called.\n");

    // Temporarily increase this by one to account for the syscall
    // instruction.
    ++(this->thread[tid]->funcExeInst);

    // Execute the actual syscall.
    this->thread[tid]->syscall(callnum);

    // Decrease funcExeInst by one as the normal commit will handle
    // incrementing it.
    --(this->thread[tid]->funcExeInst);
}

template <class Impl>
TheISA::IntReg
AlphaO3CPU<Impl>::getSyscallArg(int i, int tid)
{
    return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid);
}

template <class Impl>
void
AlphaO3CPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
{
    this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid);
}

template <class Impl>
void
AlphaO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
{
    // check for error condition.  Alpha syscall convention is to
    // indicate success/failure in reg a3 (r19) and put the
    // return value itself in the standard return value reg (v0).
    if (return_value.successful()) {
        // no error
        this->setArchIntReg(TheISA::SyscallSuccessReg, 0, tid);
        this->setArchIntReg(TheISA::ReturnValueReg, return_value.value(), tid);
    } else {
        // got an error, return details
        this->setArchIntReg(TheISA::SyscallSuccessReg, (IntReg) -1, tid);
        this->setArchIntReg(TheISA::ReturnValueReg, -return_value.value(), tid);
    }
}
#endif
<commit_msg>The Lock_Flag_DepTag went away earlier, and using TheISA gives the false impression that this code is ISA independent.<commit_after>/*
 * Copyright (c) 2004-2006 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: Kevin Lim
 */

#include "config/use_checker.hh"

#include "arch/alpha/faults.hh"
#include "arch/alpha/isa_traits.hh"
#include "base/cprintf.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "cpu/checker/thread_context.hh"
#include "sim/sim_events.hh"
#include "sim/stats.hh"

#include "cpu/o3/alpha/cpu.hh"
#include "cpu/o3/alpha/params.hh"
#include "cpu/o3/alpha/thread_context.hh"
#include "cpu/o3/comm.hh"
#include "cpu/o3/thread_state.hh"

#if FULL_SYSTEM
#include "arch/alpha/osfpal.hh"
#include "arch/isa_traits.hh"
#include "arch/kernel_stats.hh"
#include "cpu/quiesce_event.hh"
#include "sim/sim_exit.hh"
#include "sim/system.hh"
#endif

template <class Impl>
AlphaO3CPU<Impl>::AlphaO3CPU(Params *params)
#if FULL_SYSTEM
    : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
#else
    : FullO3CPU<Impl>(params)
#endif
{
    DPRINTF(O3CPU, "Creating AlphaO3CPU object.\n");

    // Setup any thread state.
    this->thread.resize(this->numThreads);

    for (int i = 0; i < this->numThreads; ++i) {
#if FULL_SYSTEM
        // SMT is not supported in FS mode yet.
        assert(this->numThreads == 1);
        this->thread[i] = new Thread(this, 0);
        this->thread[i]->setStatus(ThreadContext::Suspended);
#else
        if (i < params->workload.size()) {
            DPRINTF(O3CPU, "Workload[%i] process is %#x",
                    i, this->thread[i]);
            this->thread[i] = new Thread(this, i, params->workload[i], i);

            this->thread[i]->setStatus(ThreadContext::Suspended);

            //usedTids[i] = true;
            //threadMap[i] = i;
        } else {
            //Allocate Empty thread so M5 can use later
            //when scheduling threads to CPU
            Process* dummy_proc = NULL;

            this->thread[i] = new Thread(this, i, dummy_proc, i);
            //usedTids[i] = false;
        }
#endif // !FULL_SYSTEM

        ThreadContext *tc;

        // Setup the TC that will serve as the interface to the threads/CPU.
        AlphaTC<Impl> *alpha_tc =
            new AlphaTC<Impl>;

        tc = alpha_tc;

        // If we're using a checker, then the TC should be the
        // CheckerThreadContext.
#if USE_CHECKER
        if (params->checker) {
            tc = new CheckerThreadContext<AlphaTC<Impl> >(
                alpha_tc, this->checker);
        }
#endif

        alpha_tc->cpu = this;
        alpha_tc->thread = this->thread[i];

#if FULL_SYSTEM
        // Setup quiesce event.
        this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc);

        Port *mem_port;
        FunctionalPort *phys_port;
        VirtualPort *virt_port;
        phys_port = new FunctionalPort(csprintf("%s-%d-funcport",
                                                name(), i));
        mem_port = this->system->physmem->getPort("functional");
        mem_port->setPeer(phys_port);
        phys_port->setPeer(mem_port);

        virt_port = new VirtualPort(csprintf("%s-%d-vport",
                                             name(), i));
        mem_port = this->system->physmem->getPort("functional");
        mem_port->setPeer(virt_port);
        virt_port->setPeer(mem_port);

        this->thread[i]->setPhysPort(phys_port);
        this->thread[i]->setVirtPort(virt_port);
#endif
        // Give the thread the TC.
        this->thread[i]->tc = tc;

        // Add the TC to the CPU's list of TC's.
        this->threadContexts.push_back(tc);
    }

    for (int i=0; i < this->numThreads; i++) {
        this->thread[i]->setFuncExeInst(0);
    }

    // Sets CPU pointers. These must be set at this level because the CPU
    // pointers are defined to be the highest level of CPU class.
    this->fetch.setCPU(this);
    this->decode.setCPU(this);
    this->rename.setCPU(this);
    this->iew.setCPU(this);
    this->commit.setCPU(this);

    this->rob.setCPU(this);
    this->regFile.setCPU(this);

    lockAddr = 0;
    lockFlag = false;
}

template <class Impl>
void
AlphaO3CPU<Impl>::regStats()
{
    // Register stats for everything that has stats.
    this->fullCPURegStats();
    this->fetch.regStats();
    this->decode.regStats();
    this->rename.regStats();
    this->iew.regStats();
    this->commit.regStats();
}

template <class Impl>
TheISA::MiscReg
AlphaO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
{
    return this->regFile.readMiscReg(misc_reg, tid);
}

template <class Impl>
TheISA::MiscReg
AlphaO3CPU<Impl>::readMiscRegWithEffect(int misc_reg, unsigned tid)
{
    return this->regFile.readMiscRegWithEffect(misc_reg, tid);
}

template <class Impl>
void
AlphaO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
{
    this->regFile.setMiscReg(misc_reg, val, tid);
}

template <class Impl>
void
AlphaO3CPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
                                       unsigned tid)
{
    this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
}

template <class Impl>
void
AlphaO3CPU<Impl>::squashFromTC(unsigned tid)
{
    this->thread[tid]->inSyscall = true;
    this->commit.generateTCEvent(tid);
}

#if FULL_SYSTEM

template <class Impl>
void
AlphaO3CPU<Impl>::post_interrupt(int int_num, int index)
{
    BaseCPU::post_interrupt(int_num, index);

    if (this->thread[0]->status() == ThreadContext::Suspended) {
        DPRINTF(IPI,"Suspended Processor awoke\n");
        this->threadContexts[0]->activate();
    }
}

template <class Impl>
Fault
AlphaO3CPU<Impl>::hwrei(unsigned tid)
{
    // Need to clear the lock flag upon returning from an interrupt.
    this->setMiscReg(AlphaISA::MISCREG_LOCKFLAG, false, tid);

    this->thread[tid]->kernelStats->hwrei();

    this->checkInterrupts = true;

    // FIXME: XXX check for interrupts? XXX
    return NoFault;
}

template <class Impl>
bool
AlphaO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid)
{
    if (this->thread[tid]->kernelStats)
        this->thread[tid]->kernelStats->callpal(palFunc,
                                                this->threadContexts[tid]);

    switch (palFunc) {
      case PAL::halt:
        halt();
        if (--System::numSystemsRunning == 0)
            exitSimLoop("all cpus halted");
        break;

      case PAL::bpt:
      case PAL::bugchk:
        if (this->system->breakpoint())
            return false;
        break;
    }

    return true;
}

template <class Impl>
void
AlphaO3CPU<Impl>::processInterrupts()
{
    // Check for interrupts here.  For now can copy the code that
    // exists within isa_fullsys_traits.hh.  Also assume that thread 0
    // is the one that handles the interrupts.
    // @todo: Possibly consolidate the interrupt checking code.
    // @todo: Allow other threads to handle interrupts.

    // Check if there are any outstanding interrupts
    //Handle the interrupts
    Fault interrupt = this->interrupts.getInterrupt(this->tcBase(0));

    if (interrupt != NoFault) {
        this->checkInterrupts = false;
        this->trap(interrupt, 0);
    }
}

#endif // FULL_SYSTEM

template <class Impl>
void
AlphaO3CPU<Impl>::trap(Fault fault, unsigned tid)
{
    // Pass the thread's TC into the invoke method.
    fault->invoke(this->threadContexts[tid]);
}

#if !FULL_SYSTEM

template <class Impl>
void
AlphaO3CPU<Impl>::syscall(int64_t callnum, int tid)
{
    DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);

    DPRINTF(Activity,"Activity: syscall() called.\n");

    // Temporarily increase this by one to account for the syscall
    // instruction.
    ++(this->thread[tid]->funcExeInst);

    // Execute the actual syscall.
    this->thread[tid]->syscall(callnum);

    // Decrease funcExeInst by one as the normal commit will handle
    // incrementing it.
    --(this->thread[tid]->funcExeInst);
}

template <class Impl>
TheISA::IntReg
AlphaO3CPU<Impl>::getSyscallArg(int i, int tid)
{
    return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid);
}

template <class Impl>
void
AlphaO3CPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
{
    this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid);
}

template <class Impl>
void
AlphaO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
{
    // check for error condition.  Alpha syscall convention is to
    // indicate success/failure in reg a3 (r19) and put the
    // return value itself in the standard return value reg (v0).
    if (return_value.successful()) {
        // no error
        this->setArchIntReg(TheISA::SyscallSuccessReg, 0, tid);
        this->setArchIntReg(TheISA::ReturnValueReg, return_value.value(), tid);
    } else {
        // got an error, return details
        this->setArchIntReg(TheISA::SyscallSuccessReg, (IntReg) -1, tid);
        this->setArchIntReg(TheISA::ReturnValueReg, -return_value.value(), tid);
    }
}
#endif
<|endoftext|>


<commit_before>#include "KeyIDClient.h"
#include <cpprest/filestream.h>
#include <chrono>

using namespace std;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace concurrency::streams;

/// <summary>
/// KeyID services client.
/// </summary>
/// <param name="settings"> KeyID settings struct</param>
KeyIDClient::KeyIDClient(KeyIDSettings settings)
{
	this->settings = settings;
	this->service = make_shared<KeyIDService>(settings.url, settings.license, settings.timeout);
}

KeyIDClient::KeyIDClient()
{
	this->service = make_shared<KeyIDService>(settings.url, settings.license, settings.timeout);
}

/// <summary>
/// KeyID client destructor.
/// </summary>
KeyIDClient::~KeyIDClient()
{
}

const KeyIDSettings& KeyIDClient::GetSettings()
{
	return settings;
}

void KeyIDClient::SetSettings(KeyIDSettings settings)
{
	this->settings = settings;
}

/// <summary>
/// Saves a given KeyID profile entry.
/// </summary>
/// <param name="entityID">Profile name to save.</param>
/// <param name="tsData">Typing sample data to save.</param>
/// <param name="sessionID">Session identifier for logging purposes.</param>
/// <returns>JSON value (task)</returns>
pplx::task<web::json::value> KeyIDClient::SaveProfile(std::wstring entityID, std::wstring tsData, std::wstring sessionID)
{
	/*
	// try to save profile without a token
	return service->SaveProfile(entityID, tsData)
	.then([=](http_response response)
	{
		json::value data = ParseResponse(response);

		// token is required
		if (data[L"Error"].as_string() != L"")
		{
			// get a save token
			return service->SaveToken(entityID, tsData)
			.then([=](http_response response)
			{
				json::value data = ParseResponse(response);
				// try to save profile with a token
				return service->SaveProfile(entityID, tsData, data[L"Token"].as_string());
			})
			.then([=](http_response response)
			{
				json::value data = ParseResponse(response);
				//todo this isn't a task?
				return data;
			});
		}

		return pplx::task_from_result(data);
	});
	*/

	// get a save token
	return service->SaveToken(entityID, tsData)
		.then([=](http_response response)
	{
		json::value data = ParseResponse(response);
		// try to save profile with a token
		return service->SaveProfile(entityID, tsData, data[L"Token"].as_string());
	})
		.then([=](http_response response)
	{
		json::value data = ParseResponse(response);
		//todo this isn't a task?
		return data;
	});
}

/// <summary>
/// Removes a KeyID profile.
/// </summary>
/// <param name="entityID">Profile name to remove.</param>
/// <param name="tsData">Optional typing sample for removal authorization.</param>
/// <param name="sessionID">Session identifier for logging purposes.</param>
/// <returns>JSON value (task)</returns>
pplx::task<web::json::value> KeyIDClient::RemoveProfile(std::wstring entityID, std::wstring tsData, std::wstring sessionID)
{
	// get a removal token
	return service->RemoveToken(entityID, tsData)
	.then([=](http_response response)
	{
		json::value data = ParseResponse(response);

		// remove profile
		if (data.has_field(L"Token")) {
			return service->RemoveProfile(entityID, data[L"Token"].as_string())
				.then([=](http_response response)
			{
				json::value data = ParseResponse(response);
				return pplx::task_from_result(data);
			});
		}
		else
			return pplx::task_from_result(data);
	});
}

/// <summary>
/// Evaluates a KeyID profile.
/// </summary>
/// <param name="entityID">Profile name to evaluate.</param>
/// <param name="tsData">Typing sample to evaluate against profile.</param>
/// <param name="sessionID">Session identifier for logging purposes.</param>
/// <returns></returns>
pplx::task<web::json::value> KeyIDClient::EvaluateProfile(std::wstring entityID, std::wstring tsData, std::wstring sessionID)
{
	long long nonceTime = DotNetTicks();

	return service->Nonce(nonceTime)
	.then([=](http_response response)
	{
		return service->EvaluateSample(entityID, tsData, response.extract_string().get());
	})
	.then([=](http_response response)
	{
		json::value data = ParseResponse(response);

		// return early if there is an error
		if (data[L"Error"].as_string() != L"")
		{
			return data;
		}

		// coerce string to boolean
		data[L"Match"] = json::value::boolean(AlphaToBool(data[L"Match"].as_string()));
		data[L"IsReady"] = json::value::boolean(AlphaToBool(data[L"IsReady"].as_string()));

		// set match to true and return early if using passive validation
		if (settings.passiveValidation)
		{
			data[L"Match"] = json::value::boolean(true);
			return data;
		}
		// evaluate match value using custom threshold if enabled
		else if (settings.customThreshold)
		{
			data[L"Match"] = json::value::boolean(EvalThreshold(data[L"Confidence"].as_double(), data[L"Fidelity"].as_double()));
		}

		return data;
	});
}

/// <summary>
/// Evaluates a given profile and adds typing sample to profile.
/// </summary>
/// <param name="entityID">Profile to evaluate.</param>
/// <param name="tsData">Typing sample to evaluate and save.</param>
/// <param name="sessionID">Session identifier for logging purposes.</param>
/// <returns></returns>
pplx::task<web::json::value> KeyIDClient::LoginPassiveEnrollment(std::wstring entityID, std::wstring tsData, std::wstring sessionID)
{
	return EvaluateProfile(entityID, tsData, sessionID)
	.then([=](json::value data)
	{
		// in base case that no profile exists save profile async and return early
		if (data[L"Error"].as_string() == L"EntityID does not exist." ||
			data[L"Error"].as_string() == L"The profile has too little data for a valid evaluation." ||
			data[L"Error"].as_string() == L"The entry varied so much from the model, no evaluation is possible.")
		{
			return SaveProfile(entityID, tsData, sessionID)
			.then([=](json::value saveData)
			{
				json::value evalData = data;
				evalData[L"Match"] = json::value::boolean(true);
				evalData[L"IsReady"] = json::value::boolean(false);
				evalData[L"Confidence"] = json::value::number(100.0);
				evalData[L"Fidelity"] = json::value::number(100.0);
				return evalData;
			});
		}

		// if profile is not ready save profile async and return early
		if (data[L"IsReady"].as_bool() == false)
		{
			return SaveProfile(entityID, tsData, sessionID)
			.then([=](json::value saveData)
			{
				json::value evalData = data;
				evalData[L"Match"] = json::value::boolean(true);
				return evalData;
			});
		}

		return pplx::task_from_result(data);
	});
}

/// <summary>
/// Returns profile information without modifying the profile.
/// </summary>
/// <param name="entityID">Profile to inspect.</param>
/// <returns></returns>
pplx::task<web::json::value> KeyIDClient::GetProfileInfo(std::wstring entityID)
{
	return service->GetProfileInfo(entityID)
	.then([=](http_response response)
	{
		json::value data = ParseResponse(response);
		return pplx::task_from_result(data);
	});
}

/// <summary>
/// Compares a given confidence and fidelity against pre-determined thresholds.
/// </summary>
/// <param name="confidence">KeyID evaluation confidence.</param>
/// <param name="fidelity">KeyID evaluation fidelity.</param>
/// <returns>Whether confidence and fidelity meet thresholds.</returns>
bool KeyIDClient::EvalThreshold(double confidence, double fidelity)
{
	if (confidence >= settings.thresholdConfidence &&
		fidelity >= settings.thresholdFidelity)
	{
		return true;
	}
	else
	{
		return false;
	}
}

/// <summary>
/// Converts a string value like 'true' to a boolean object.
/// </summary>
/// <param name="input">String to convert to boolean.</param>
/// <returns>Boolean value.</returns>
bool KeyIDClient::AlphaToBool(std::wstring input)
{
	std::transform(input.begin(), input.end(), input.begin(), ::toupper);

	if (input == L"TRUE")
		return true;
	else
		return false;
}

/// <summary>
/// Converts current time to Microsoft .Net 'ticks'. A tick is 100 nanoseconds.
/// </summary>
/// <returns>Current time in 'ticks'.</returns>
long long KeyIDClient::DotNetTicks()
{
	const long long EPOCH_OFFSET = 621355968000000000;
	const long MS_PER_TICK = 10000;
	long long ms_since_epoch = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
	long long ticks = ((ms_since_epoch * MS_PER_TICK) + EPOCH_OFFSET);
	return ticks;
}

/// <summary>
/// Extracts a JSON value from a http_response
/// </summary>
/// <param name="response">HTTP response</param>
/// <returns>JSON value</returns>
web::json::value KeyIDClient::ParseResponse(const web::http::http_response& response)
{
	if (response.status_code() == status_codes::OK)
	{
		return response.extract_json().get();
	}
	else
	{
		throw http_exception(L"HTTP response not 200 OK.");
	}
}<commit_msg>Oops commit.<commit_after>#include "KeyIDClient.h"
#include <cpprest/filestream.h>
#include <chrono>

using namespace std;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace concurrency::streams;

/// <summary>
/// KeyID services client.
/// </summary>
/// <param name="settings"> KeyID settings struct</param>
KeyIDClient::KeyIDClient(KeyIDSettings settings)
{
	this->settings = settings;
	this->service = make_shared<KeyIDService>(settings.url, settings.license, settings.timeout);
}

KeyIDClient::KeyIDClient()
{
	this->service = make_shared<KeyIDService>(settings.url, settings.license, settings.timeout);
}

/// <summary>
/// KeyID client destructor.
/// </summary>
KeyIDClient::~KeyIDClient()
{
}

const KeyIDSettings& KeyIDClient::GetSettings()
{
	return settings;
}

void KeyIDClient::SetSettings(KeyIDSettings settings)
{
	this->settings = settings;
}

/// <summary>
/// Saves a given KeyID profile entry.
/// </summary>
/// <param name="entityID">Profile name to save.</param>
/// <param name="tsData">Typing sample data to save.</param>
/// <param name="sessionID">Session identifier for logging purposes.</param>
/// <returns>JSON value (task)</returns>
pplx::task<web::json::value> KeyIDClient::SaveProfile(std::wstring entityID, std::wstring tsData, std::wstring sessionID)
{
	// try to save profile without a token
	return service->SaveProfile(entityID, tsData)
	.then([=](http_response response)
	{
		json::value data = ParseResponse(response);

		// token is required
		if (data[L"Error"].as_string() != L"")
		{
			// get a save token
			return service->SaveToken(entityID, tsData)
			.then([=](http_response response)
			{
				json::value data = ParseResponse(response);
				// try to save profile with a token
				return service->SaveProfile(entityID, tsData, data[L"Token"].as_string());
			})
			.then([=](http_response response)
			{
				json::value data = ParseResponse(response);
				//todo this isn't a task?
				return data;
			});
		}

		return pplx::task_from_result(data);
	});
}

/// <summary>
/// Removes a KeyID profile.
/// </summary>
/// <param name="entityID">Profile name to remove.</param>
/// <param name="tsData">Optional typing sample for removal authorization.</param>
/// <param name="sessionID">Session identifier for logging purposes.</param>
/// <returns>JSON value (task)</returns>
pplx::task<web::json::value> KeyIDClient::RemoveProfile(std::wstring entityID, std::wstring tsData, std::wstring sessionID)
{
	// get a removal token
	return service->RemoveToken(entityID, tsData)
	.then([=](http_response response)
	{
		json::value data = ParseResponse(response);

		// remove profile
		if (data.has_field(L"Token")) {
			return service->RemoveProfile(entityID, data[L"Token"].as_string())
				.then([=](http_response response)
			{
				json::value data = ParseResponse(response);
				return pplx::task_from_result(data);
			});
		}
		else
			return pplx::task_from_result(data);
	});
}

/// <summary>
/// Evaluates a KeyID profile.
/// </summary>
/// <param name="entityID">Profile name to evaluate.</param>
/// <param name="tsData">Typing sample to evaluate against profile.</param>
/// <param name="sessionID">Session identifier for logging purposes.</param>
/// <returns></returns>
pplx::task<web::json::value> KeyIDClient::EvaluateProfile(std::wstring entityID, std::wstring tsData, std::wstring sessionID)
{
	long long nonceTime = DotNetTicks();

	return service->Nonce(nonceTime)
	.then([=](http_response response)
	{
		return service->EvaluateSample(entityID, tsData, response.extract_string().get());
	})
	.then([=](http_response response)
	{
		json::value data = ParseResponse(response);

		// return early if there is an error
		if (data[L"Error"].as_string() != L"")
		{
			return data;
		}

		// coerce string to boolean
		data[L"Match"] = json::value::boolean(AlphaToBool(data[L"Match"].as_string()));
		data[L"IsReady"] = json::value::boolean(AlphaToBool(data[L"IsReady"].as_string()));

		// set match to true and return early if using passive validation
		if (settings.passiveValidation)
		{
			data[L"Match"] = json::value::boolean(true);
			return data;
		}
		// evaluate match value using custom threshold if enabled
		else if (settings.customThreshold)
		{
			data[L"Match"] = json::value::boolean(EvalThreshold(data[L"Confidence"].as_double(), data[L"Fidelity"].as_double()));
		}

		return data;
	});
}

/// <summary>
/// Evaluates a given profile and adds typing sample to profile.
/// </summary>
/// <param name="entityID">Profile to evaluate.</param>
/// <param name="tsData">Typing sample to evaluate and save.</param>
/// <param name="sessionID">Session identifier for logging purposes.</param>
/// <returns></returns>
pplx::task<web::json::value> KeyIDClient::LoginPassiveEnrollment(std::wstring entityID, std::wstring tsData, std::wstring sessionID)
{
	return EvaluateProfile(entityID, tsData, sessionID)
	.then([=](json::value data)
	{
		// in base case that no profile exists save profile async and return early
		if (data[L"Error"].as_string() == L"EntityID does not exist." ||
			data[L"Error"].as_string() == L"The profile has too little data for a valid evaluation." ||
			data[L"Error"].as_string() == L"The entry varied so much from the model, no evaluation is possible.")
		{
			return SaveProfile(entityID, tsData, sessionID)
			.then([=](json::value saveData)
			{
				json::value evalData = data;
				evalData[L"Match"] = json::value::boolean(true);
				evalData[L"IsReady"] = json::value::boolean(false);
				evalData[L"Confidence"] = json::value::number(100.0);
				evalData[L"Fidelity"] = json::value::number(100.0);
				return evalData;
			});
		}

		// if profile is not ready save profile async and return early
		if (data[L"IsReady"].as_bool() == false)
		{
			return SaveProfile(entityID, tsData, sessionID)
			.then([=](json::value saveData)
			{
				json::value evalData = data;
				evalData[L"Match"] = json::value::boolean(true);
				return evalData;
			});
		}

		return pplx::task_from_result(data);
	});
}

/// <summary>
/// Returns profile information without modifying the profile.
/// </summary>
/// <param name="entityID">Profile to inspect.</param>
/// <returns></returns>
pplx::task<web::json::value> KeyIDClient::GetProfileInfo(std::wstring entityID)
{
	return service->GetProfileInfo(entityID)
	.then([=](http_response response)
	{
		json::value data = ParseResponse(response);
		return pplx::task_from_result(data);
	});
}

/// <summary>
/// Compares a given confidence and fidelity against pre-determined thresholds.
/// </summary>
/// <param name="confidence">KeyID evaluation confidence.</param>
/// <param name="fidelity">KeyID evaluation fidelity.</param>
/// <returns>Whether confidence and fidelity meet thresholds.</returns>
bool KeyIDClient::EvalThreshold(double confidence, double fidelity)
{
	if (confidence >= settings.thresholdConfidence &&
		fidelity >= settings.thresholdFidelity)
	{
		return true;
	}
	else
	{
		return false;
	}
}

/// <summary>
/// Converts a string value like 'true' to a boolean object.
/// </summary>
/// <param name="input">String to convert to boolean.</param>
/// <returns>Boolean value.</returns>
bool KeyIDClient::AlphaToBool(std::wstring input)
{
	std::transform(input.begin(), input.end(), input.begin(), ::toupper);

	if (input == L"TRUE")
		return true;
	else
		return false;
}

/// <summary>
/// Converts current time to Microsoft .Net 'ticks'. A tick is 100 nanoseconds.
/// </summary>
/// <returns>Current time in 'ticks'.</returns>
long long KeyIDClient::DotNetTicks()
{
	const long long EPOCH_OFFSET = 621355968000000000;
	const long MS_PER_TICK = 10000;
	long long ms_since_epoch = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
	long long ticks = ((ms_since_epoch * MS_PER_TICK) + EPOCH_OFFSET);
	return ticks;
}

/// <summary>
/// Extracts a JSON value from a http_response
/// </summary>
/// <param name="response">HTTP response</param>
/// <returns>JSON value</returns>
web::json::value KeyIDClient::ParseResponse(const web::http::http_response& response)
{
	if (response.status_code() == status_codes::OK)
	{
		return response.extract_json().get();
	}
	else
	{
		throw http_exception(L"HTTP response not 200 OK.");
	}
}<|endoftext|>