<commit_before>#include "RDom.h"
#include "Util.h"
#include "IROperator.h"
#include "IRPrinter.h"

namespace Halide {

using namespace Internal;

using std::string;
using std::vector;

RVar::operator Expr() const {
    if (!min().defined() || !extent().defined()) {
        user_error << "Use of undefined RDom dimension: " <<
            (name().empty() ? "<unknown>" : name()) << "\n";
    }
    return Variable::make(Int(32), name(), domain());
}

Expr RVar::min() const {
    if (_domain.defined()) {
        return _var().min;
    } else {
        return undef<int>();
    }
}

Expr RVar::extent() const {
    if (_domain.defined()) {
        return _var().extent;
    } else {
        return undef<int>();
    }
}

const std::string &RVar::name() const {
    if (_domain.defined()) {
        return _var().var;
    } else {
        return _name;
    }
}

template <int N>
ReductionDomain build_domain(ReductionVariable (&vars)[N]) {
    vector<ReductionVariable> d(&vars[0], &vars[N]);
    ReductionDomain dom(d);
    return dom;
}

// This just initializes the predefined x, y, z, w members of RDom.
void RDom::init_vars(string name) {
    static string var_names[] = { "x", "y", "z", "w" };

    if (name == "") {
        name = make_entity_name(this, "Halide::RDom", 'r');
    }
    const std::vector<ReductionVariable> &dom_vars = dom.domain();
    RVar *vars[] = { &x, &y, &z, &w };

    for (size_t i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) {
        if (i < dom_vars.size()) {
            *(vars[i]) = RVar(dom, i);
        } else {
            *(vars[i]) = RVar(name + "." + var_names[i]);
        }
    }
}

RDom::RDom(ReductionDomain d) : dom(d) {
    init_vars("");
}

// We suffix all RVars with $r to prevent unintentional name matches with pure vars called x, y, z, w.
RDom::RDom(Expr min, Expr extent, string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min), cast<int>(extent) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
        { name + ".z$r", cast<int>(min2), cast<int>(extent2) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, Expr min3, Expr extent3,
           string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
        { name + ".z$r", cast<int>(min2), cast<int>(extent2) },
        { name + ".w$r", cast<int>(min3), cast<int>(extent3) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, Expr min3, Expr extent3,
           Expr min4, Expr extent4, string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
        { name + ".z$r", cast<int>(min2), cast<int>(extent2) },
        { name + ".w$r", cast<int>(min3), cast<int>(extent3) },
        { name + ".4$r", cast<int>(min4), cast<int>(extent4) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, Expr min3, Expr extent3,
           Expr min4, Expr extent4, Expr min5, Expr extent5, string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
        { name + ".z$r", cast<int>(min2), cast<int>(extent2) },
        { name + ".w$r", cast<int>(min3), cast<int>(extent3) },
        { name + ".4$r", cast<int>(min4), cast<int>(extent4) },
        { name + ".5$r", cast<int>(min5), cast<int>(extent5) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, Expr min3, Expr extent3,
           Expr min4, Expr extent4, Expr min5, Expr extent5, Expr min6, Expr extent6, string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
        { name + ".z$r", cast<int>(min2), cast<int>(extent2) },
        { name + ".w$r", cast<int>(min3), cast<int>(extent3) },
        { name + ".4$r", cast<int>(min4), cast<int>(extent4) },
        { name + ".5$r", cast<int>(min5), cast<int>(extent5) },
        { name + ".6$r", cast<int>(min6), cast<int>(extent6) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, Expr min3, Expr extent3,
           Expr min4, Expr extent4, Expr min5, Expr extent5, Expr min6, Expr extent6, Expr min7, Expr extent7,
           string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
        { name + ".z$r", cast<int>(min2), cast<int>(extent2) },
        { name + ".w$r", cast<int>(min3), cast<int>(extent3) },
        { name + ".4$r", cast<int>(min4), cast<int>(extent4) },
        { name + ".5$r", cast<int>(min5), cast<int>(extent5) },
        { name + ".6$r", cast<int>(min6), cast<int>(extent6) },
        { name + ".7$r", cast<int>(min7), cast<int>(extent7) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Buffer b) {
    static string var_names[] = {"x$r", "y$r", "z$r", "w$r"};
    std::vector<ReductionVariable> vars;
    for (int i = 0; i < b.dimensions(); i++) {
        ReductionVariable var = {
            b.name() + "." + var_names[i],
            b.min(i),
            b.extent(i)
        };
        vars.push_back(var);
    }

    dom = ReductionDomain(vars);
    init_vars(b.name());
}

RDom::RDom(ImageParam p) {
    static string var_names[] = {"x$r", "y$r", "z$r", "w$r"};
    std::vector<ReductionVariable> vars;
    for (int i = 0; i < p.dimensions(); i++) {
        ReductionVariable var = {
            p.name() + "." + var_names[i],
            p.min(i),
            p.extent(i)
        };
        vars.push_back(var);
    }

    dom = ReductionDomain(vars);
    init_vars(p.name());
}

int RDom::dimensions() const {
    return (int)dom.domain().size();
}

RVar RDom::operator[](int i) const {
    if (i == 0) return x;
    if (i == 1) return y;
    if (i == 2) return z;
    if (i == 3) return w;
    if (i < dimensions()) {
        return RVar(dom, i);
    }
    user_error << "Reduction domain index out of bounds: " << i << "\n";
    return x; // Keep the compiler happy
}

RDom::operator Expr() const {
    if (dimensions() != 1) {
        user_error << "Error: Can't treat this multidimensional RDom as an Expr:\n"
                   << (*this) << "\n"
                   << "Only single-dimensional RDoms can be cast to Expr.\n";
    }
    return Expr(x);
}

RDom::operator RVar() const {
    if (dimensions() != 1) {
        user_error << "Error: Can't treat this multidimensional RDom as an RVar:\n"
                   << (*this) << "\n"
                   << "Only single-dimensional RDoms can be cast to RVar.\n";
    }
    return x;
}

/** Emit an RVar in a human-readable form */
std::ostream &operator<<(std::ostream &stream, RVar v) {
    stream << v.name() << "(" << v.min() << ", " << v.extent() << ")";
    return stream;
}

/** Emit an RDom in a human-readable form. */
std::ostream &operator<<(std::ostream &stream, RDom dom) {
    stream << "RDom(\n";
    for (int i = 0; i < dom.dimensions(); i++) {
        stream << "  " << dom[i] << "\n";
    }
    stream << ")\n";
    return stream;
}

}
<commit_msg>undef<int> -> Expr()<commit_after>#include "RDom.h"
#include "Util.h"
#include "IROperator.h"
#include "IRPrinter.h"

namespace Halide {

using namespace Internal;

using std::string;
using std::vector;

RVar::operator Expr() const {
    if (!min().defined() || !extent().defined()) {
        user_error << "Use of undefined RDom dimension: " <<
            (name().empty() ? "<unknown>" : name()) << "\n";
    }
    return Variable::make(Int(32), name(), domain());
}

Expr RVar::min() const {
    if (_domain.defined()) {
        return _var().min;
    } else {
        return Expr();
    }
}

Expr RVar::extent() const {
    if (_domain.defined()) {
        return _var().extent;
    } else {
        return Expr();
    }
}

const std::string &RVar::name() const {
    if (_domain.defined()) {
        return _var().var;
    } else {
        return _name;
    }
}

template <int N>
ReductionDomain build_domain(ReductionVariable (&vars)[N]) {
    vector<ReductionVariable> d(&vars[0], &vars[N]);
    ReductionDomain dom(d);
    return dom;
}

// This just initializes the predefined x, y, z, w members of RDom.
void RDom::init_vars(string name) {
    static string var_names[] = { "x", "y", "z", "w" };

    if (name == "") {
        name = make_entity_name(this, "Halide::RDom", 'r');
    }
    const std::vector<ReductionVariable> &dom_vars = dom.domain();
    RVar *vars[] = { &x, &y, &z, &w };

    for (size_t i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) {
        if (i < dom_vars.size()) {
            *(vars[i]) = RVar(dom, i);
        } else {
            *(vars[i]) = RVar(name + "." + var_names[i]);
        }
    }
}

RDom::RDom(ReductionDomain d) : dom(d) {
    init_vars("");
}

// We suffix all RVars with $r to prevent unintentional name matches with pure vars called x, y, z, w.
RDom::RDom(Expr min, Expr extent, string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min), cast<int>(extent) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
        { name + ".z$r", cast<int>(min2), cast<int>(extent2) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, Expr min3, Expr extent3,
           string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
        { name + ".z$r", cast<int>(min2), cast<int>(extent2) },
        { name + ".w$r", cast<int>(min3), cast<int>(extent3) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, Expr min3, Expr extent3,
           Expr min4, Expr extent4, string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
        { name + ".z$r", cast<int>(min2), cast<int>(extent2) },
        { name + ".w$r", cast<int>(min3), cast<int>(extent3) },
        { name + ".4$r", cast<int>(min4), cast<int>(extent4) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, Expr min3, Expr extent3,
           Expr min4, Expr extent4, Expr min5, Expr extent5, string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
        { name + ".z$r", cast<int>(min2), cast<int>(extent2) },
        { name + ".w$r", cast<int>(min3), cast<int>(extent3) },
        { name + ".4$r", cast<int>(min4), cast<int>(extent4) },
        { name + ".5$r", cast<int>(min5), cast<int>(extent5) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, Expr min3, Expr extent3,
           Expr min4, Expr extent4, Expr min5, Expr extent5, Expr min6, Expr extent6, string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
        { name + ".z$r", cast<int>(min2), cast<int>(extent2) },
        { name + ".w$r", cast<int>(min3), cast<int>(extent3) },
        { name + ".4$r", cast<int>(min4), cast<int>(extent4) },
        { name + ".5$r", cast<int>(min5), cast<int>(extent5) },
        { name + ".6$r", cast<int>(min6), cast<int>(extent6) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Expr min0, Expr extent0, Expr min1, Expr extent1, Expr min2, Expr extent2, Expr min3, Expr extent3,
           Expr min4, Expr extent4, Expr min5, Expr extent5, Expr min6, Expr extent6, Expr min7, Expr extent7,
           string name) {
    ReductionVariable vars[] = {
        { name + ".x$r", cast<int>(min0), cast<int>(extent0) },
        { name + ".y$r", cast<int>(min1), cast<int>(extent1) },
        { name + ".z$r", cast<int>(min2), cast<int>(extent2) },
        { name + ".w$r", cast<int>(min3), cast<int>(extent3) },
        { name + ".4$r", cast<int>(min4), cast<int>(extent4) },
        { name + ".5$r", cast<int>(min5), cast<int>(extent5) },
        { name + ".6$r", cast<int>(min6), cast<int>(extent6) },
        { name + ".7$r", cast<int>(min7), cast<int>(extent7) },
    };
    dom = build_domain(vars);
    init_vars(name);
}

RDom::RDom(Buffer b) {
    static string var_names[] = {"x$r", "y$r", "z$r", "w$r"};
    std::vector<ReductionVariable> vars;
    for (int i = 0; i < b.dimensions(); i++) {
        ReductionVariable var = {
            b.name() + "." + var_names[i],
            b.min(i),
            b.extent(i)
        };
        vars.push_back(var);
    }

    dom = ReductionDomain(vars);
    init_vars(b.name());
}

RDom::RDom(ImageParam p) {
    static string var_names[] = {"x$r", "y$r", "z$r", "w$r"};
    std::vector<ReductionVariable> vars;
    for (int i = 0; i < p.dimensions(); i++) {
        ReductionVariable var = {
            p.name() + "." + var_names[i],
            p.min(i),
            p.extent(i)
        };
        vars.push_back(var);
    }

    dom = ReductionDomain(vars);
    init_vars(p.name());
}

int RDom::dimensions() const {
    return (int)dom.domain().size();
}

RVar RDom::operator[](int i) const {
    if (i == 0) return x;
    if (i == 1) return y;
    if (i == 2) return z;
    if (i == 3) return w;
    if (i < dimensions()) {
        return RVar(dom, i);
    }
    user_error << "Reduction domain index out of bounds: " << i << "\n";
    return x; // Keep the compiler happy
}

RDom::operator Expr() const {
    if (dimensions() != 1) {
        user_error << "Error: Can't treat this multidimensional RDom as an Expr:\n"
                   << (*this) << "\n"
                   << "Only single-dimensional RDoms can be cast to Expr.\n";
    }
    return Expr(x);
}

RDom::operator RVar() const {
    if (dimensions() != 1) {
        user_error << "Error: Can't treat this multidimensional RDom as an RVar:\n"
                   << (*this) << "\n"
                   << "Only single-dimensional RDoms can be cast to RVar.\n";
    }
    return x;
}

/** Emit an RVar in a human-readable form */
std::ostream &operator<<(std::ostream &stream, RVar v) {
    stream << v.name() << "(" << v.min() << ", " << v.extent() << ")";
    return stream;
}

/** Emit an RDom in a human-readable form. */
std::ostream &operator<<(std::ostream &stream, RDom dom) {
    stream << "RDom(\n";
    for (int i = 0; i < dom.dimensions(); i++) {
        stream << "  " << dom[i] << "\n";
    }
    stream << ")\n";
    return stream;
}

}
<|endoftext|>


<commit_before>/*
    Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>

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

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "message.h"
#include "messagefetchjob.h"
#include "messagemodel.h"
#include "messagequery.h"
#include "monitor.h"

#include <kmime_message.h>

#include <kdebug.h>
#include <klocale.h>

#include <QDebug>

using namespace PIM;

class MessageModel::Private
{
  public:
    QList<Message*> messages;
    QByteArray path;
    MessageFetchJob *listingJob;
    Monitor *monitor;
    QList<MessageQuery*> fetchJobs, updateJobs;
};

PIM::MessageModel::MessageModel( QObject *parent ) :
    QAbstractTableModel( parent ),
    d( new Private() )
{
  d->listingJob = 0;
  d->monitor = 0;
}

PIM::MessageModel::~MessageModel( )
{
  delete d->listingJob;
  delete d->monitor;
  qDeleteAll( d->fetchJobs );
  qDeleteAll( d->updateJobs );
  delete d;
}

int PIM::MessageModel::columnCount( const QModelIndex & parent ) const
{
  Q_UNUSED( parent );
  return 5; // keep in sync with the column type enum
}

QVariant PIM::MessageModel::data( const QModelIndex & index, int role ) const
{
  if ( !index.isValid() )
    return QVariant();
  if ( index.row() >= d->messages.count() )
    return QVariant();
  Message* msg = d->messages.at( index.row() );
  Q_ASSERT( msg->mime() );
  if ( role == Qt::DisplayRole ) {
    switch ( index.column() ) {
      case Subject:
        return msg->mime()->subject()->asUnicodeString();
      case Sender:
        return msg->mime()->from()->asUnicodeString();
      case Receiver:
        return msg->mime()->to()->asUnicodeString();
      case Date:
        return msg->mime()->date()->asUnicodeString();
      case Size:
      // TODO
      default:
        return QVariant();
    }
  }
  return QVariant();
}

int PIM::MessageModel::rowCount( const QModelIndex & parent ) const
{
  Q_UNUSED( parent );
  return d->messages.count();
}

QVariant PIM::MessageModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
  if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
    switch ( section ) {
      case Subject:
        return i18n( "Subject" );
      case Sender:
        return i18n( "Sender" );
      case Receiver:
        return i18n( "Receiver" );
      case Date:
        return i18n( "Date" );
      case Size:
        return i18n( "Size" );
      default:
        return QString();
    }
  }
  return QAbstractTableModel::headerData( section, orientation, role );
}

void PIM::MessageModel::setPath( const QByteArray& path )
{
  if ( d->path == path )
    return;
  d->path = path;
  // the query changed, thus everything we have already is invalid
  d->messages.clear();
  reset();
  // stop all running jobs
  delete d->monitor;
  d->monitor = 0;
  qDeleteAll( d->updateJobs );
  d->updateJobs.clear();
  qDeleteAll( d->fetchJobs );
  d->updateJobs.clear();
  delete d->listingJob;
  // start listing job
  d->listingJob = new MessageFetchJob( path, this );
  connect( d->listingJob, SIGNAL( done( PIM::Job* ) ), SLOT( listingDone( PIM::Job* ) ) );
  d->listingJob->start();
}

void PIM::MessageModel::listingDone( PIM::Job * job )
{
  Q_ASSERT( job == d->listingJob );
  if ( job->error() ) {
    // TODO
    kWarning() << k_funcinfo << "Message query failed!" << endl;
  } else {
    d->messages = d->listingJob->messages();
    reset();
  }
  d->listingJob->deleteLater();
  d->listingJob = 0;

  // start monitor job
  // TODO error handling
  /*d->monitor = new Monitor( "folder=" + d->path );
  connect( d->monitor, SIGNAL( changed( const DataReference::List& ) ),
           SLOT( messagesChanged( const DataReference::List& ) ) );
  connect( d->monitor, SIGNAL( added( const DataReference::List& ) ),
           SLOT( messagesAdded( const DataReference::List& ) ) );
  connect( d->monitor, SIGNAL( removed( const DataReference::List& ) ),
           SLOT( messagesRemoved( const DataReference::List& ) ) );*/
//   d->monitor->start();
}

void PIM::MessageModel::fetchingNewDone( PIM::Job * job )
{
  Q_ASSERT( d->fetchJobs.contains( static_cast<MessageQuery*>( job ) ) );
  if ( job->error() ) {
    // TODO
    kWarning() << k_funcinfo << "Fetching new messages failed!" << endl;
  } else {
    Message::List list = static_cast<MessageQuery*>( job )->messages();
    beginInsertRows( QModelIndex(), d->messages.size(), d->messages.size() + list.size() );
    d->messages += list;
    endInsertRows();
  }
  d->fetchJobs.removeAll( static_cast<MessageQuery*>( job ) );
  job->deleteLater();
}

void PIM::MessageModel::fetchingUpdatesDone( PIM::Job * job )
{
  Q_ASSERT( d->updateJobs.contains( static_cast<MessageQuery*>( job ) ) );
  if ( job->error() ) {
    // TODO
    kWarning() << k_funcinfo << "Updating changed messages failed!" << endl;
  } else {
    Message::List list = static_cast<MessageQuery*>( job )->messages();
    foreach ( Message* msg, list ) {
      // ### *slow*
      for ( int i = 0; i < d->messages.size(); ++i ) {
        if ( d->messages.at( i )->reference() == msg->reference() ) {
          delete d->messages.at( i );
          d->messages.replace( i, msg );
          emit dataChanged( index( i, 0 ), index( i, columnCount() ) );
          break;
        }
      }
    }
  }
  d->updateJobs.removeAll( static_cast<MessageQuery*>( job ) );
  job->deleteLater();
}

void PIM::MessageModel::messagesChanged( const DataReference::List & references )
{
  // TODO: build query based on the reference list
  QString query;
  MessageQuery* job = new MessageQuery( query );
  connect( job, SIGNAL( done( PIM::Job* ) ), SLOT( fetchingUpdatesDone( PIM::Job* job ) ) );
  job->start();
  d->updateJobs.append( job );
}

void PIM::MessageModel::messagesAdded( const DataReference::List & references )
{
  // TODO: build query based on the reference list
  QString query;
  MessageQuery* job = new MessageQuery( query );
  connect( job, SIGNAL( done( PIM::Job* ) ), SLOT( fetchingNewDone( PIM::Job* job ) ) );
  job->start();
  d->fetchJobs.append( job );
}

void PIM::MessageModel::messagesRemoved( const DataReference::List & references )
{
  foreach ( DataReference ref, references ) {
    // ### *slow*
    int index = -1;
    for ( int i = 0; i < d->messages.size(); ++i ) {
      if ( d->messages.at( i )->reference() == ref ) {
        index = i;
        break;
      }
    }
    if ( index < 0 )
      continue;
    beginRemoveRows( QModelIndex(), index, index );
    Message* msg = d->messages.at( index );
    d->messages.removeAt( index );
    delete msg;
    endRemoveRows();
  }
}

DataReference PIM::MessageModel::referenceForIndex( const QModelIndex & index ) const
{
  if ( !index.isValid() )
    return DataReference();
  if ( index.row() >= d->messages.count() )
    return DataReference();
  Message *msg = d->messages.at( index.row() );
  Q_ASSERT( msg );
  return msg->reference();
}

#include "messagemodel.moc"
<commit_msg>This is a flat model, so don't report child items.<commit_after>/*
    Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>

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

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "message.h"
#include "messagefetchjob.h"
#include "messagemodel.h"
#include "messagequery.h"
#include "monitor.h"

#include <kmime_message.h>

#include <kdebug.h>
#include <klocale.h>

#include <QDebug>

using namespace PIM;

class MessageModel::Private
{
  public:
    QList<Message*> messages;
    QByteArray path;
    MessageFetchJob *listingJob;
    Monitor *monitor;
    QList<MessageQuery*> fetchJobs, updateJobs;
};

PIM::MessageModel::MessageModel( QObject *parent ) :
    QAbstractTableModel( parent ),
    d( new Private() )
{
  d->listingJob = 0;
  d->monitor = 0;
}

PIM::MessageModel::~MessageModel( )
{
  delete d->listingJob;
  delete d->monitor;
  qDeleteAll( d->fetchJobs );
  qDeleteAll( d->updateJobs );
  delete d;
}

int PIM::MessageModel::columnCount( const QModelIndex & parent ) const
{
  Q_UNUSED( parent );
  return 5; // keep in sync with the column type enum
}

QVariant PIM::MessageModel::data( const QModelIndex & index, int role ) const
{
  if ( !index.isValid() )
    return QVariant();
  if ( index.row() >= d->messages.count() )
    return QVariant();
  Message* msg = d->messages.at( index.row() );
  Q_ASSERT( msg->mime() );
  if ( role == Qt::DisplayRole ) {
    switch ( index.column() ) {
      case Subject:
        return msg->mime()->subject()->asUnicodeString();
      case Sender:
        return msg->mime()->from()->asUnicodeString();
      case Receiver:
        return msg->mime()->to()->asUnicodeString();
      case Date:
        return msg->mime()->date()->asUnicodeString();
      case Size:
      // TODO
      default:
        return QVariant();
    }
  }
  return QVariant();
}

int PIM::MessageModel::rowCount( const QModelIndex & parent ) const
{
  if ( !parent.isValid() )
    return d->messages.count();
  return 0;
}

QVariant PIM::MessageModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
  if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
    switch ( section ) {
      case Subject:
        return i18n( "Subject" );
      case Sender:
        return i18n( "Sender" );
      case Receiver:
        return i18n( "Receiver" );
      case Date:
        return i18n( "Date" );
      case Size:
        return i18n( "Size" );
      default:
        return QString();
    }
  }
  return QAbstractTableModel::headerData( section, orientation, role );
}

void PIM::MessageModel::setPath( const QByteArray& path )
{
  if ( d->path == path )
    return;
  d->path = path;
  // the query changed, thus everything we have already is invalid
  d->messages.clear();
  reset();
  // stop all running jobs
  delete d->monitor;
  d->monitor = 0;
  qDeleteAll( d->updateJobs );
  d->updateJobs.clear();
  qDeleteAll( d->fetchJobs );
  d->updateJobs.clear();
  delete d->listingJob;
  // start listing job
  d->listingJob = new MessageFetchJob( path, this );
  connect( d->listingJob, SIGNAL( done( PIM::Job* ) ), SLOT( listingDone( PIM::Job* ) ) );
  d->listingJob->start();
}

void PIM::MessageModel::listingDone( PIM::Job * job )
{
  Q_ASSERT( job == d->listingJob );
  if ( job->error() ) {
    // TODO
    kWarning() << k_funcinfo << "Message query failed!" << endl;
  } else {
    d->messages = d->listingJob->messages();
    reset();
  }
  d->listingJob->deleteLater();
  d->listingJob = 0;

  // start monitor job
  // TODO error handling
  /*d->monitor = new Monitor( "folder=" + d->path );
  connect( d->monitor, SIGNAL( changed( const DataReference::List& ) ),
           SLOT( messagesChanged( const DataReference::List& ) ) );
  connect( d->monitor, SIGNAL( added( const DataReference::List& ) ),
           SLOT( messagesAdded( const DataReference::List& ) ) );
  connect( d->monitor, SIGNAL( removed( const DataReference::List& ) ),
           SLOT( messagesRemoved( const DataReference::List& ) ) );*/
//   d->monitor->start();
}

void PIM::MessageModel::fetchingNewDone( PIM::Job * job )
{
  Q_ASSERT( d->fetchJobs.contains( static_cast<MessageQuery*>( job ) ) );
  if ( job->error() ) {
    // TODO
    kWarning() << k_funcinfo << "Fetching new messages failed!" << endl;
  } else {
    Message::List list = static_cast<MessageQuery*>( job )->messages();
    beginInsertRows( QModelIndex(), d->messages.size(), d->messages.size() + list.size() );
    d->messages += list;
    endInsertRows();
  }
  d->fetchJobs.removeAll( static_cast<MessageQuery*>( job ) );
  job->deleteLater();
}

void PIM::MessageModel::fetchingUpdatesDone( PIM::Job * job )
{
  Q_ASSERT( d->updateJobs.contains( static_cast<MessageQuery*>( job ) ) );
  if ( job->error() ) {
    // TODO
    kWarning() << k_funcinfo << "Updating changed messages failed!" << endl;
  } else {
    Message::List list = static_cast<MessageQuery*>( job )->messages();
    foreach ( Message* msg, list ) {
      // ### *slow*
      for ( int i = 0; i < d->messages.size(); ++i ) {
        if ( d->messages.at( i )->reference() == msg->reference() ) {
          delete d->messages.at( i );
          d->messages.replace( i, msg );
          emit dataChanged( index( i, 0 ), index( i, columnCount() ) );
          break;
        }
      }
    }
  }
  d->updateJobs.removeAll( static_cast<MessageQuery*>( job ) );
  job->deleteLater();
}

void PIM::MessageModel::messagesChanged( const DataReference::List & references )
{
  // TODO: build query based on the reference list
  QString query;
  MessageQuery* job = new MessageQuery( query );
  connect( job, SIGNAL( done( PIM::Job* ) ), SLOT( fetchingUpdatesDone( PIM::Job* job ) ) );
  job->start();
  d->updateJobs.append( job );
}

void PIM::MessageModel::messagesAdded( const DataReference::List & references )
{
  // TODO: build query based on the reference list
  QString query;
  MessageQuery* job = new MessageQuery( query );
  connect( job, SIGNAL( done( PIM::Job* ) ), SLOT( fetchingNewDone( PIM::Job* job ) ) );
  job->start();
  d->fetchJobs.append( job );
}

void PIM::MessageModel::messagesRemoved( const DataReference::List & references )
{
  foreach ( DataReference ref, references ) {
    // ### *slow*
    int index = -1;
    for ( int i = 0; i < d->messages.size(); ++i ) {
      if ( d->messages.at( i )->reference() == ref ) {
        index = i;
        break;
      }
    }
    if ( index < 0 )
      continue;
    beginRemoveRows( QModelIndex(), index, index );
    Message* msg = d->messages.at( index );
    d->messages.removeAt( index );
    delete msg;
    endRemoveRows();
  }
}

DataReference PIM::MessageModel::referenceForIndex( const QModelIndex & index ) const
{
  if ( !index.isValid() )
    return DataReference();
  if ( index.row() >= d->messages.count() )
    return DataReference();
  Message *msg = d->messages.at( index.row() );
  Q_ASSERT( msg );
  return msg->reference();
}

#include "messagemodel.moc"
<|endoftext|>


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

///
/// @file mrs01.C
/// @brief Run and manage the DDR4 MRS01 loading
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 1
// *HWP Consumed by: FSP:HB

#include <fapi2.H>

#include <mss.H>
#include <lib/dimm/ddr4/mrs_load_ddr4.H>

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

using fapi2::FAPI2_RC_SUCCESS;

namespace mss
{

namespace ddr4
{

///
/// @brief mrs01_data ctor
/// @param[in] a fapi2::TARGET_TYPE_DIMM target
/// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
mrs01_data::mrs01_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ):
    iv_dll_enable(fapi2::ENUM_ATTR_EFF_DRAM_DLL_ENABLE_YES),
    iv_additive_latency(0),
    iv_wl_enable(0),
    iv_tdqs(0),
    iv_qoff(0)
{
    FAPI_TRY( mss::eff_dram_dll_enable(i_target, iv_dll_enable) );
    FAPI_TRY( mss::vpd_mt_dram_drv_imp_dq_dqs(i_target, &(iv_odic[0])) );
    FAPI_TRY( mss::eff_dram_al(i_target, iv_additive_latency) );
    FAPI_TRY( mss::eff_dram_wr_lvl_enable(i_target, iv_wl_enable) );
    FAPI_TRY( mss::eff_dram_rtt_nom(i_target, &(iv_rtt_nom[0])) );
    FAPI_TRY( mss::eff_dram_tdqs(i_target, iv_tdqs) );
    FAPI_TRY( mss::eff_dram_output_buffer(i_target, iv_qoff) );

    o_rc = fapi2::FAPI2_RC_SUCCESS;
    return;

fapi_try_exit:
    o_rc = fapi2::current_err;
    FAPI_ERR("unable to get attributes for mrs0");
    return;
}

///
/// @brief Configure the ARR0 of the CCS instruction for mrs01
/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM>
/// @param[in,out] io_inst the instruction to fixup
/// @param[in] i_rank the rank in question
/// @return FAPI2_RC_SUCCESS iff OK
///
fapi2::ReturnCode mrs01(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
                        ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst,
                        const uint64_t i_rank)
{
    // Check to make sure our ctor worked ok
    mrs01_data l_data( i_target, fapi2::current_err );
    FAPI_TRY( fapi2::current_err, "Unable to construct MRS01 data from attributes");
    FAPI_TRY( mrs01(i_target, l_data, io_inst, i_rank) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Configure the ARR0 of the CCS instruction for mrs01, data object as input
/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM>
/// @param[in] i_data an mrs01_data object, filled in
/// @param[in,out] io_inst the instruction to fixup
/// @param[in] i_rank the rank in question
/// @return FAPI2_RC_SUCCESS iff OK
///
fapi2::ReturnCode mrs01(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
                        const mrs01_data& i_data,
                        ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst,
                        const uint64_t i_rank)
{
    // Little table to map Output Driver Imepdance Control. 34Ohm is index 0,
    // 48Ohm is index 1
    // Left bit is A2, right bit is A1
    constexpr uint8_t odic_map[] = { 0b00, 0b01 };

    constexpr uint64_t ODIC_LENGTH = 2;
    constexpr uint64_t ODIC_START_BIT = 7;
    constexpr uint64_t ADDITIVE_LATENCE_LENGTH = 2;
    constexpr uint64_t ADDITIVE_LATENCE_START_BIT = 7;
    constexpr uint64_t RTT_NOM_LENGTH = 3;
    constexpr uint64_t RTT_NOM_START_BIT = 7;

    fapi2::buffer<uint8_t> l_additive_latency;
    fapi2::buffer<uint8_t> l_odic_buffer;
    fapi2::buffer<uint8_t> l_rtt_nom_buffer;

    //check here to make sure the rank indexes correctly into the attribute array
    //It's equivalent to mss::index(i_rank) < l_rtt_nom.size() if C arrays had a .size() method
    fapi2::Assert( mss::index(i_rank) < MAX_RANK_PER_DIMM);

    FAPI_ASSERT( ((i_data.iv_odic[mss::index(i_rank)] == fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM34) ||
                  (i_data.iv_odic[mss::index(i_rank)] == fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM48)),
                 fapi2::MSS_BAD_MR_PARAMETER()
                 .set_MR_NUMBER(1)
                 .set_PARAMETER(OUTPUT_IMPEDANCE)
                 .set_PARAMETER_VALUE(i_data.iv_odic[mss::index(i_rank)])
                 .set_DIMM_IN_ERROR(i_target),
                 "Bad value for output driver impedance: %d (%s)", i_data.iv_odic[mss::index(i_rank)], mss::c_str(i_target));

    // Map from impedance to bits in MRS1
    l_odic_buffer = (i_data.iv_odic[mss::index(i_rank)] == fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM34) ?
                    odic_map[0] : odic_map[1];

    // Map from RTT_NOM array to the value in the map
    l_rtt_nom_buffer = i_data.iv_rtt_nom[mss::index(i_rank)];

    // Print this here as opposed to the MRS01 ctor as we want to see the specific rtt now information
    FAPI_INF("MR1 rank %d attributes: DLL_ENABLE: 0x%x, ODIC: 0x%x(0x%x), AL: 0x%x, WLE: 0x%x, "
             "RTT_NOM:0x%x, TDQS: 0x%x, QOFF: 0x%x", i_rank,
             i_data.iv_dll_enable, i_data.iv_odic[mss::index(i_rank)], uint8_t(l_odic_buffer), uint8_t(l_additive_latency),
             i_data.iv_wl_enable,
             uint8_t(l_rtt_nom_buffer), i_data.iv_tdqs, i_data.iv_qoff);

    io_inst.arr0.writeBit<A0>(i_data.iv_dll_enable);
    mss::swizzle<A1, ODIC_LENGTH, ODIC_START_BIT>(l_odic_buffer, io_inst.arr0);
    mss::swizzle<A3, ADDITIVE_LATENCE_LENGTH, ADDITIVE_LATENCE_START_BIT>(fapi2::buffer<uint8_t>
            (i_data.iv_additive_latency), io_inst.arr0);
    io_inst.arr0.writeBit<A7>(i_data.iv_wl_enable);
    mss::swizzle<A8, RTT_NOM_LENGTH, RTT_NOM_START_BIT>(l_rtt_nom_buffer, io_inst.arr0);
    io_inst.arr0.writeBit<A11>(i_data.iv_tdqs);
    io_inst.arr0.writeBit<A12>(i_data.iv_qoff);

    FAPI_INF("MR1: 0x%016llx", uint64_t(io_inst.arr0));

    return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Helper function for mrs01_decode
/// @param[in] i_inst the CCS instruction
/// @param[in] i_rank ths rank in question
/// @param[out] o_dll_enable the dll enable bit
/// @param[out] o_wrl_enable the write leveling enable bit
/// @param[out] o_tdqs the tdqs enable bit
/// @param[out] o_qoff the qoff bit
/// @param[out] o_odic the output driver impedance control setting
/// @param[out] o_additive_latency the additive latency setting
/// @param[out] o_rtt_nom the rtt_nom setting
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode mrs01_decode_helper(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst,
                                      const uint64_t i_rank,
                                      uint8_t& o_dll_enable,
                                      uint8_t& o_wrl_enable,
                                      uint8_t& o_tdqs,
                                      uint8_t& o_qoff,
                                      fapi2::buffer<uint8_t>& o_odic,
                                      fapi2::buffer<uint8_t>& o_additive_latency,
                                      fapi2::buffer<uint8_t>& o_rtt_nom)
{
    o_odic = 0;
    o_additive_latency = 0;
    o_rtt_nom = 0;

    o_dll_enable = i_inst.arr0.getBit<A0>();
    o_wrl_enable = i_inst.arr0.getBit<A7>();
    o_tdqs = i_inst.arr0.getBit<A11>();
    o_qoff = i_inst.arr0.getBit<A12>();

    mss::swizzle<6, 2, A2>(i_inst.arr0, o_odic);
    mss::swizzle<6, 2, A4>(i_inst.arr0, o_additive_latency);
    mss::swizzle<5, 3, A10>(i_inst.arr0, o_rtt_nom);

    FAPI_INF("MR1 rank %d decode: DLL_ENABLE: 0x%x, ODIC: 0x%x, AL: 0x%x, WLE: 0x%x, "
             "RTT_NOM: 0x%x, TDQS: 0x%x, QOFF: 0x%x", i_rank,
             o_dll_enable, uint8_t(o_odic), uint8_t(o_additive_latency), o_wrl_enable, uint8_t(o_rtt_nom),
             o_tdqs, o_qoff);

    return FAPI2_RC_SUCCESS;
}

///
/// @brief Given a CCS instruction which contains address bits with an encoded MRS1,
/// decode and trace the contents
/// @param[in] i_inst the CCS instruction
/// @param[in] i_rank ths rank in question
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode mrs01_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst,
                               const uint64_t i_rank)
{
    uint8_t l_dll_enable = 0;
    uint8_t l_wrl_enable = 0;
    uint8_t l_tdqs = 0;
    uint8_t l_qoff = 0;
    fapi2::buffer<uint8_t> l_odic;
    fapi2::buffer<uint8_t> l_additive_latency;
    fapi2::buffer<uint8_t> l_rtt_nom;

    return mrs01_decode_helper(i_inst, i_rank, l_dll_enable, l_wrl_enable, l_tdqs, l_qoff, l_odic,
                               l_additive_latency, l_rtt_nom);
}

fapi2::ReturnCode (*mrs01_data::make_ccs_instruction)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
        const mrs01_data& i_data,
        ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst,
        const uint64_t i_rank) = &mrs01;

fapi2::ReturnCode (*mrs01_data::decode)(const ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& i_inst,
                                        const uint64_t i_rank) = &mrs01_decode;

} // ns ddr4

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

///
/// @file mrs01.C
/// @brief Run and manage the DDR4 MRS01 loading
///
// *HWP HWP Owner: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>

#include <mss.H>
#include <lib/dimm/ddr4/mrs_load_ddr4.H>

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

using fapi2::FAPI2_RC_SUCCESS;

namespace mss
{

namespace ddr4
{

///
/// @brief mrs01_data ctor
/// @param[in] a fapi2::TARGET_TYPE_DIMM target
/// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
mrs01_data::mrs01_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ):
    iv_dll_enable(fapi2::ENUM_ATTR_EFF_DRAM_DLL_ENABLE_YES),
    iv_additive_latency(0),
    iv_wl_enable(0),
    iv_tdqs(0),
    iv_qoff(0)
{
    FAPI_TRY( mss::eff_dram_dll_enable(i_target, iv_dll_enable), "Error in mrs01_data()" );
    FAPI_TRY( mss::vpd_mt_dram_drv_imp_dq_dqs(i_target, &(iv_odic[0])), "Error in mrs01_data()" );
    FAPI_TRY( mss::eff_dram_al(i_target, iv_additive_latency), "Error in mrs01_data()" );
    FAPI_TRY( mss::eff_dram_wr_lvl_enable(i_target, iv_wl_enable), "Error in mrs01_data()" );
    FAPI_TRY( mss::eff_dram_rtt_nom(i_target, &(iv_rtt_nom[0])), "Error in mrs01_data()" );
    FAPI_TRY( mss::eff_dram_tdqs(i_target, iv_tdqs), "Error in mrs01_data()" );
    FAPI_TRY( mss::eff_dram_output_buffer(i_target, iv_qoff), "Error in mrs01_data()" );

    o_rc = fapi2::FAPI2_RC_SUCCESS;
    return;

fapi_try_exit:
    o_rc = fapi2::current_err;
    FAPI_ERR("%s unable to get attributes for mrs01");
    return;
}

///
/// @brief Configure the ARR0 of the CCS instruction for mrs01
/// @param[in] i_target a fapi2::Target<TARGET_TYPE_DIMM>
/// @param[in,out] io_inst the instruction to fixup
/// @param[in] i_rank the rank in question
/// @return FAPI2_RC_SUCCESS iff OK
///
fapi2::ReturnCode mrs01(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
                        ccs::instruction_t<TARGET_TYPE_MCBIST>& io_inst,
                        const uint64_t i_rank)
{
    // Check to make sure our ctor worked ok
    mrs01_data l_data( i_target, fapi2::current_err );
    FAPI_TRY( fapi2::current_err, "%s Unable to construct MRS01 data from attributes", mss::c_str(i_target) );
    FAPI_TRY( mrs01(i_target, l_data, io_inst, i_rank) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Configure the ARR0 of the CCS instruction for mrs01, data object as input
/// @param[in] i_target a fapi2::Target<fapi2::TARGET_TYPE_DIMM>
/// @param[in] i_data an mrs01_data object, filled in
/// @param[in,out] io_inst the instruction to fixup
/// @param[in] i_rank the rank in question
/// @return FAPI2_RC_SUCCESS iff OK
///
fapi2::ReturnCode mrs01(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
                        const mrs01_data& i_data,
                        ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst,
                        const uint64_t i_rank)
{
    // Little table to map Output Driver Imepdance Control. 34Ohm is index 0,
    // 48Ohm is index 1
    // Left bit is A2, right bit is A1
    constexpr uint8_t odic_map[] = { 0b00, 0b01 };

    constexpr uint64_t ODIC_LENGTH = 2;
    constexpr uint64_t ODIC_START_BIT = 7;
    constexpr uint64_t ADDITIVE_LATENCE_LENGTH = 2;
    constexpr uint64_t ADDITIVE_LATENCE_START_BIT = 7;
    constexpr uint64_t RTT_NOM_LENGTH = 3;
    constexpr uint64_t RTT_NOM_START_BIT = 7;

    fapi2::buffer<uint8_t> l_additive_latency;
    fapi2::buffer<uint8_t> l_odic_buffer;
    fapi2::buffer<uint8_t> l_rtt_nom_buffer;

    //check here to make sure the rank indexes correctly into the attribute array
    //It's equivalent to mss::index(i_rank) < l_rtt_nom.size() if C arrays had a .size() method
    fapi2::Assert( mss::index(i_rank) < MAX_RANK_PER_DIMM);

    FAPI_ASSERT( ((i_data.iv_odic[mss::index(i_rank)] == fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM34) ||
                  (i_data.iv_odic[mss::index(i_rank)] == fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM48)),
                 fapi2::MSS_BAD_MR_PARAMETER()
                 .set_MR_NUMBER(1)
                 .set_PARAMETER(OUTPUT_IMPEDANCE)
                 .set_PARAMETER_VALUE(i_data.iv_odic[mss::index(i_rank)])
                 .set_DIMM_IN_ERROR(i_target),
                 "Bad value for output driver impedance: %d (%s)",
                 i_data.iv_odic[mss::index(i_rank)],
                 mss::c_str(i_target));

    // Map from impedance to bits in MRS1
    l_odic_buffer = (i_data.iv_odic[mss::index(i_rank)] == fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM34) ?
                    odic_map[0] : odic_map[1];

    // Map from RTT_NOM array to the value in the map
    l_rtt_nom_buffer = i_data.iv_rtt_nom[mss::index(i_rank)];

    // Print this here as opposed to the MRS01 ctor as we want to see the specific rtt now information
    FAPI_INF("%s MR1 rank %d attributes: DLL_ENABLE: 0x%x, ODIC: 0x%x(0x%x), AL: 0x%x, WLE: 0x%x, "
             "RTT_NOM:0x%x, TDQS: 0x%x, QOFF: 0x%x",
             mss::c_str(i_target), i_rank, i_data.iv_dll_enable,
             i_data.iv_odic[mss::index(i_rank)], uint8_t(l_odic_buffer),
             uint8_t(l_additive_latency), i_data.iv_wl_enable,
             uint8_t(l_rtt_nom_buffer), i_data.iv_tdqs, i_data.iv_qoff);

    io_inst.arr0.writeBit<A0>(i_data.iv_dll_enable);
    mss::swizzle<A1, ODIC_LENGTH, ODIC_START_BIT>(l_odic_buffer, io_inst.arr0);
    mss::swizzle<A3, ADDITIVE_LATENCE_LENGTH, ADDITIVE_LATENCE_START_BIT>(fapi2::buffer<uint8_t>
            (i_data.iv_additive_latency), io_inst.arr0);
    io_inst.arr0.writeBit<A7>(i_data.iv_wl_enable);
    mss::swizzle<A8, RTT_NOM_LENGTH, RTT_NOM_START_BIT>(l_rtt_nom_buffer, io_inst.arr0);
    io_inst.arr0.writeBit<A11>(i_data.iv_tdqs);
    io_inst.arr0.writeBit<A12>(i_data.iv_qoff);

    FAPI_INF("%s MR1: 0x%016llx", mss::c_str(i_target), uint64_t(io_inst.arr0));

    return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Helper function for mrs01_decode
/// @param[in] i_inst the CCS instruction
/// @param[in] i_rank ths rank in question
/// @param[out] o_dll_enable the dll enable bit
/// @param[out] o_wrl_enable the write leveling enable bit
/// @param[out] o_tdqs the tdqs enable bit
/// @param[out] o_qoff the qoff bit
/// @param[out] o_odic the output driver impedance control setting
/// @param[out] o_additive_latency the additive latency setting
/// @param[out] o_rtt_nom the rtt_nom setting
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode mrs01_decode_helper(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst,
                                      const uint64_t i_rank,
                                      uint8_t& o_dll_enable,
                                      uint8_t& o_wrl_enable,
                                      uint8_t& o_tdqs,
                                      uint8_t& o_qoff,
                                      fapi2::buffer<uint8_t>& o_odic,
                                      fapi2::buffer<uint8_t>& o_additive_latency,
                                      fapi2::buffer<uint8_t>& o_rtt_nom)
{
    o_odic = 0;
    o_additive_latency = 0;
    o_rtt_nom = 0;

    o_dll_enable = i_inst.arr0.getBit<A0>();
    o_wrl_enable = i_inst.arr0.getBit<A7>();
    o_tdqs = i_inst.arr0.getBit<A11>();
    o_qoff = i_inst.arr0.getBit<A12>();

    mss::swizzle<6, 2, A2>(i_inst.arr0, o_odic);
    mss::swizzle<6, 2, A4>(i_inst.arr0, o_additive_latency);
    mss::swizzle<5, 3, A10>(i_inst.arr0, o_rtt_nom);

    FAPI_INF("MR1 rank %d decode: DLL_ENABLE: 0x%x, ODIC: 0x%x, AL: 0x%x, WLE: 0x%x, "
             "RTT_NOM: 0x%x, TDQS: 0x%x, QOFF: 0x%x",
             i_rank, o_dll_enable, uint8_t(o_odic), uint8_t(o_additive_latency),
             o_wrl_enable, uint8_t(o_rtt_nom), o_tdqs, o_qoff);

    return FAPI2_RC_SUCCESS;
}

///
/// @brief Given a CCS instruction which contains address bits with an encoded MRS1,
/// decode and trace the contents
/// @param[in] i_inst the CCS instruction
/// @param[in] i_rank ths rank in question
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode mrs01_decode(const ccs::instruction_t<TARGET_TYPE_MCBIST>& i_inst,
                               const uint64_t i_rank)
{
    uint8_t l_dll_enable = 0;
    uint8_t l_wrl_enable = 0;
    uint8_t l_tdqs = 0;
    uint8_t l_qoff = 0;
    fapi2::buffer<uint8_t> l_odic;
    fapi2::buffer<uint8_t> l_additive_latency;
    fapi2::buffer<uint8_t> l_rtt_nom;

    return mrs01_decode_helper(i_inst, i_rank, l_dll_enable, l_wrl_enable, l_tdqs, l_qoff, l_odic,
                               l_additive_latency, l_rtt_nom);
}

fapi2::ReturnCode (*mrs01_data::make_ccs_instruction)(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
        const mrs01_data& i_data,
        ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& io_inst,
        const uint64_t i_rank) = &mrs01;

fapi2::ReturnCode (*mrs01_data::decode)(const ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& i_inst,
                                        const uint64_t i_rank) = &mrs01_decode;

} // ns ddr4

} // ns mss
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: chips/p9/procedures/hwp/pm/p9_pm_get_poundv_bucket.C $        */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* EKB Project                                                            */
/*                                                                        */
/* COPYRIGHT 2015,2016                                                    */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file p9_pm_get_poundv_bucket.C
/// @brief Grab PM data from certain bucket in #V keyword in LRPX record
///

// ----------------------------------------------------------------------
// Includes
// ----------------------------------------------------------------------
#include <p9_pm_get_poundv_bucket.H>
#include <mvpd_access_defs.H>
#include <attribute_ids.H>

fapi2::ReturnCode p9_pm_get_poundv_bucket(
    const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target,
    fapi2::voltageBucketData_t& o_data)
{
    FAPI_IMP("Entering p9_pm_get_poundv_bucket ....");

    //Create a pointer version of the out param o_data so that
    // we can access bytes individually
    uint8_t* l_tempBuffer = reinterpret_cast<uint8_t*>(malloc(sizeof(o_data)));

    //Set up a char array to hold the bucket data from an attr read
    fapi2::ATTR_POUNDV_BUCKET_DATA_Type l_bucketAttr;

    //Perform an ATTR_GET for POUNDV_BUCKET data on the EQ target
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POUNDV_BUCKET_DATA,
                           i_target,
                           l_bucketAttr));

#ifndef _BIG_ENDIAN
    //The first byte is simply a uint8 that describes the bucket ID
    l_tempBuffer[0] = l_bucketAttr[0];

    //Skipping the first byte (which has already been taken of) start reading
    //the voltage data 2 bytes at a time.
    for(uint8_t offset = 1; offset < sizeof(o_data); offset += 2)
    {
        //Switch from Big Endian to Little Endian
        l_tempBuffer[offset] = l_bucketAttr[offset + 1];
        l_tempBuffer[offset + 1] = l_bucketAttr[offset];
    }

    memcpy(&o_data,
           l_tempBuffer,
           sizeof(o_data));

#else
    memcpy(&o_data,
           l_bucketAttr,
           sizeof(o_data));
#endif

fapi_try_exit:
    free(l_tempBuffer);
    FAPI_IMP("Exiting p9_pm_get_poundv_bucket ....");

    return fapi2::current_err;
}

fapi2::ReturnCode p9_pm_get_poundv_bucket_attr(
    const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target,
    uint8_t* o_data)
{
    FAPI_IMP("Entering p9_pm_get_poundv_bucket_attr ....");
    uint8_t* l_prDataPtr = NULL;
    uint8_t* l_fullVpdData = NULL;
    uint8_t l_overridePresent = 0;
    uint32_t l_vpdSize = 0;
    uint32_t l_eqFapiPos = 0;
    uint8_t l_bucketId;
    fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS;

    do
    {
        //To read MVPD we will need the proc parent of the inputted EQ target
        fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_procParent =
            i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

        //check if bucket num has been overriden
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POUNDV_BUCKET_NUM_OVERRIDE,
                               i_target,
                               l_overridePresent));

        if(l_overridePresent != 0)
        {
            //If it has been overriden then get the override
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POUNDV_BUCKET_NUM,
                                   i_target,
                                   l_bucketId));
        }
        else
        {
            //Otherwise get the bucket num from MVPD data
            //First read is to get size of vpd record, note the o_buffer is NULL
            l_rc = getMvpdField(fapi2::MVPD_RECORD_VINI,
                                fapi2::MVPD_KEYWORD_PR,
                                l_procParent,
                                NULL,
                                l_vpdSize);

            if(l_rc)
            {
                FAPI_ERR("p9_pm_get_poundv_bucket_attr:: Error reading PR keyword size from VINI record");
                break;
            }

            l_prDataPtr = reinterpret_cast<uint8_t*>(malloc(l_vpdSize));

            //Second read is to get data of vpd record
            l_rc = getMvpdField(fapi2::MVPD_RECORD_VINI,
                                fapi2::MVPD_KEYWORD_PR,
                                l_procParent,
                                l_prDataPtr,
                                l_vpdSize);

            if(l_rc)
            {
                FAPI_ERR("p9_pm_get_poundv_bucket_attr:: Error reading PR keyword from VINI record");
                break;
            }

            memcpy(&l_bucketId, (l_prDataPtr), sizeof(uint8_t));
        }

        //Need to determine which LRP record to read from depending on which
        //bucket we are getting the power management data from. FapiPos will
        //tell us which LRP record to use.
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FAPI_POS,
                               i_target,
                               l_eqFapiPos));
        fapi2::MvpdRecord lprRecord;

        switch(l_eqFapiPos)
        {
            case 0:
                lprRecord = fapi2::MVPD_RECORD_LRP0;
                break;

            case 1:
                lprRecord = fapi2::MVPD_RECORD_LRP1;
                break;

            case 2:
                lprRecord = fapi2::MVPD_RECORD_LRP2;
                break;

            case 3:
                lprRecord = fapi2::MVPD_RECORD_LRP3;
                break;

            case 4:
                lprRecord = fapi2::MVPD_RECORD_LRP4;
                break;

            case 5:
                lprRecord = fapi2::MVPD_RECORD_LRP5;
                break;

            default:
                FAPI_ERR("No LRP record found for EQ with fapi pos = %d", l_eqFapiPos);
                assert(0);
                break;
        }

        //Reset VPD size because we want to find size of another VPD record
        l_vpdSize = 0;

        //First read is to get size of vpd record, note the o_buffer is NULL
        l_rc = getMvpdField(lprRecord,
                            fapi2::MVPD_KEYWORD_PDV,
                            l_procParent,
                            NULL,
                            l_vpdSize);

        if(l_rc)
        {
            FAPI_ERR("p9_pm_get_poundv_bucket_attr:: Error reading PDV keyword size from LRP%d record", l_eqFapiPos);
            break;
        }

        //Allocate memory for vpd data
        l_fullVpdData = reinterpret_cast<uint8_t*>(malloc(l_vpdSize));

        FAPI_ASSERT(l_vpdSize - 4 - ((l_bucketId - 1) * 0x33) >= sizeof(fapi2::ATTR_POUNDV_BUCKET_DATA_Type),
                    fapi2::BAD_VPD_READ()
                    .set_EXPECTED_SIZE(sizeof(fapi2::ATTR_POUNDV_BUCKET_DATA_Type))
                    .set_ACTUAL_SIZE(l_vpdSize - 4 - ((l_bucketId - 1) * 0x33)),
                    "#V data read was too small!" );

        //Second read is to get data of vpd record
        l_rc = getMvpdField(lprRecord,
                            fapi2::MVPD_KEYWORD_PDV,
                            l_procParent,
                            l_fullVpdData,
                            l_vpdSize);

        if(l_rc)
        {
            FAPI_ERR("p9_pm_get_poundv_bucket_attr:: Error reading PDV keyword from LRP%d record", l_eqFapiPos);
            break;
        }

        //#V record is laid out as follows:
        //Name:     0x2 byte
        //Length:   0x2 byte
        //Version:  0x1 byte **buffer starts here
        //PNP:      0x3 byte
        //bucket a: 0x33 byte
        //bucket b: 0x33 byte
        //bucket c: 0x33 byte
        //bucket d: 0x33 byte
        //bucket e: 0x33 byte
        //bucket f: 0x33 byte
        if( *l_fullVpdData == 0x2)
        {
            memcpy(o_data,
                   l_fullVpdData + 4 + (l_bucketId - 1) * 0x33,
                   sizeof(fapi2::ATTR_POUNDV_BUCKET_DATA_Type));
        }
        else
        {
            FAPI_ERR("p9_pm_get_poundv_bucket_attr::Invalid #V record version: 0x%x", *l_fullVpdData);
            FAPI_ASSERT(0,
                        fapi2::INVALID_POUNDV_VERSION()
                        .set_POUNDV_VERSION(*l_fullVpdData),
                        "#V is of an invalid version!" );
        }

    }
    while(0);

fapi_try_exit:

    if(l_fullVpdData != NULL)
    {
        free(l_fullVpdData);
    }

    if(l_prDataPtr != NULL)
    {
        free(l_prDataPtr);
    }

    FAPI_IMP("Exiting p9_pm_get_poundv_bucket_attr ....");

    //If there is no issue in the current err, check
    //the local rc to see if the mvpd access methods caught anything
    if((fapi2::current_err == fapi2::FAPI2_RC_SUCCESS) &&
       (l_rc != fapi2::FAPI2_RC_SUCCESS))
    {
        fapi2::current_err = l_rc;
    }

    return fapi2::current_err;
}

<commit_msg>Read 4byte into PR keyword to get Bucket ID for #V data<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: chips/p9/procedures/hwp/pm/p9_pm_get_poundv_bucket.C $        */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* EKB Project                                                            */
/*                                                                        */
/* COPYRIGHT 2015,2016                                                    */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file p9_pm_get_poundv_bucket.C
/// @brief Grab PM data from certain bucket in #V keyword in LRPX record
///

// ----------------------------------------------------------------------
// Includes
// ----------------------------------------------------------------------
#include <p9_pm_get_poundv_bucket.H>
#include <mvpd_access_defs.H>
#include <attribute_ids.H>

fapi2::ReturnCode p9_pm_get_poundv_bucket(
    const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target,
    fapi2::voltageBucketData_t& o_data)
{
    FAPI_IMP("Entering p9_pm_get_poundv_bucket ....");

    //Create a pointer version of the out param o_data so that
    // we can access bytes individually
    uint8_t* l_tempBuffer = reinterpret_cast<uint8_t*>(malloc(sizeof(o_data)));

    //Set up a char array to hold the bucket data from an attr read
    fapi2::ATTR_POUNDV_BUCKET_DATA_Type l_bucketAttr;

    //Perform an ATTR_GET for POUNDV_BUCKET data on the EQ target
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POUNDV_BUCKET_DATA,
                           i_target,
                           l_bucketAttr));

#ifndef _BIG_ENDIAN
    //The first byte is simply a uint8 that describes the bucket ID
    l_tempBuffer[0] = l_bucketAttr[0];

    //Skipping the first byte (which has already been taken of) start reading
    //the voltage data 2 bytes at a time.
    for(uint8_t offset = 1; offset < sizeof(o_data); offset += 2)
    {
        //Switch from Big Endian to Little Endian
        l_tempBuffer[offset] = l_bucketAttr[offset + 1];
        l_tempBuffer[offset + 1] = l_bucketAttr[offset];
    }

    memcpy(&o_data,
           l_tempBuffer,
           sizeof(o_data));

#else
    memcpy(&o_data,
           l_bucketAttr,
           sizeof(o_data));
#endif

fapi_try_exit:
    free(l_tempBuffer);
    FAPI_IMP("Exiting p9_pm_get_poundv_bucket ....");

    return fapi2::current_err;
}

fapi2::ReturnCode p9_pm_get_poundv_bucket_attr(
    const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target,
    uint8_t* o_data)
{
    FAPI_IMP("Entering p9_pm_get_poundv_bucket_attr ....");
    uint8_t* l_prDataPtr = NULL;
    uint8_t* l_fullVpdData = NULL;
    uint8_t l_overridePresent = 0;
    uint32_t l_vpdSize = 0;
    uint32_t l_eqFapiPos = 0;
    uint8_t l_bucketId;
    fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS;

    do
    {
        //To read MVPD we will need the proc parent of the inputted EQ target
        fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_procParent =
            i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

        //check if bucket num has been overriden
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POUNDV_BUCKET_NUM_OVERRIDE,
                               i_target,
                               l_overridePresent));

        if(l_overridePresent != 0)
        {
            //If it has been overriden then get the override
            FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POUNDV_BUCKET_NUM,
                                   i_target,
                                   l_bucketId));
        }
        else
        {
            //Otherwise get the bucket num from MVPD data
            //First read is to get size of vpd record, note the o_buffer is NULL
            l_rc = getMvpdField(fapi2::MVPD_RECORD_VINI,
                                fapi2::MVPD_KEYWORD_PR,
                                l_procParent,
                                NULL,
                                l_vpdSize);

            if(l_rc)
            {
                FAPI_ERR("p9_pm_get_poundv_bucket_attr:: Error reading PR keyword size from VINI record");
                break;
            }

            l_prDataPtr = reinterpret_cast<uint8_t*>(malloc(l_vpdSize));

            //Second read is to get data of vpd record
            l_rc = getMvpdField(fapi2::MVPD_RECORD_VINI,
                                fapi2::MVPD_KEYWORD_PR,
                                l_procParent,
                                l_prDataPtr,
                                l_vpdSize);

            if(l_rc)
            {
                FAPI_ERR("p9_pm_get_poundv_bucket_attr:: Error reading PR keyword from VINI record");
                break;
            }

            //Bucket ID is byte[4] of the PR keyword
            memcpy(&l_bucketId, (l_prDataPtr + 4), sizeof(uint8_t));
        }

        //Need to determine which LRP record to read from depending on which
        //bucket we are getting the power management data from. FapiPos will
        //tell us which LRP record to use.
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_FAPI_POS,
                               i_target,
                               l_eqFapiPos));
        fapi2::MvpdRecord lprRecord;

        switch(l_eqFapiPos)
        {
            case 0:
                lprRecord = fapi2::MVPD_RECORD_LRP0;
                break;

            case 1:
                lprRecord = fapi2::MVPD_RECORD_LRP1;
                break;

            case 2:
                lprRecord = fapi2::MVPD_RECORD_LRP2;
                break;

            case 3:
                lprRecord = fapi2::MVPD_RECORD_LRP3;
                break;

            case 4:
                lprRecord = fapi2::MVPD_RECORD_LRP4;
                break;

            case 5:
                lprRecord = fapi2::MVPD_RECORD_LRP5;
                break;

            default:
                FAPI_ERR("No LRP record found for EQ with fapi pos = %d", l_eqFapiPos);
                assert(0);
                break;
        }

        //Reset VPD size because we want to find size of another VPD record
        l_vpdSize = 0;

        //First read is to get size of vpd record, note the o_buffer is NULL
        l_rc = getMvpdField(lprRecord,
                            fapi2::MVPD_KEYWORD_PDV,
                            l_procParent,
                            NULL,
                            l_vpdSize);

        if(l_rc)
        {
            FAPI_ERR("p9_pm_get_poundv_bucket_attr:: Error reading PDV keyword size from LRP%d record", l_eqFapiPos);
            break;
        }

        //Allocate memory for vpd data
        l_fullVpdData = reinterpret_cast<uint8_t*>(malloc(l_vpdSize));

        FAPI_ASSERT(l_vpdSize - 4 - ((l_bucketId - 1) * 0x33) >= sizeof(fapi2::ATTR_POUNDV_BUCKET_DATA_Type),
                    fapi2::BAD_VPD_READ()
                    .set_EXPECTED_SIZE(sizeof(fapi2::ATTR_POUNDV_BUCKET_DATA_Type))
                    .set_ACTUAL_SIZE(l_vpdSize - 4 - ((l_bucketId - 1) * 0x33)),
                    "#V data read was too small!" );

        //Second read is to get data of vpd record
        l_rc = getMvpdField(lprRecord,
                            fapi2::MVPD_KEYWORD_PDV,
                            l_procParent,
                            l_fullVpdData,
                            l_vpdSize);

        if(l_rc)
        {
            FAPI_ERR("p9_pm_get_poundv_bucket_attr:: Error reading PDV keyword from LRP%d record", l_eqFapiPos);
            break;
        }

        //#V record is laid out as follows:
        //Name:     0x2 byte
        //Length:   0x2 byte
        //Version:  0x1 byte **buffer starts here
        //PNP:      0x3 byte
        //bucket a: 0x33 byte
        //bucket b: 0x33 byte
        //bucket c: 0x33 byte
        //bucket d: 0x33 byte
        //bucket e: 0x33 byte
        //bucket f: 0x33 byte
        if( *l_fullVpdData == 0x2)
        {
            memcpy(o_data,
                   l_fullVpdData + 4 + (l_bucketId - 1) * 0x33,
                   sizeof(fapi2::ATTR_POUNDV_BUCKET_DATA_Type));
        }
        else
        {
            FAPI_ERR("p9_pm_get_poundv_bucket_attr::Invalid #V record version: 0x%x", *l_fullVpdData);
            FAPI_ASSERT(0,
                        fapi2::INVALID_POUNDV_VERSION()
                        .set_POUNDV_VERSION(*l_fullVpdData),
                        "#V is of an invalid version!" );
        }

    }
    while(0);

fapi_try_exit:

    if(l_fullVpdData != NULL)
    {
        free(l_fullVpdData);
    }

    if(l_prDataPtr != NULL)
    {
        free(l_prDataPtr);
    }

    FAPI_IMP("Exiting p9_pm_get_poundv_bucket_attr ....");

    //If there is no issue in the current err, check
    //the local rc to see if the mvpd access methods caught anything
    if((fapi2::current_err == fapi2::FAPI2_RC_SUCCESS) &&
       (l_rc != fapi2::FAPI2_RC_SUCCESS))
    {
        fapi2::current_err = l_rc;
    }

    return fapi2::current_err;
}

<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#include    "../../../StroikaPreComp.h"

#include    "Reader.h"

//// SEEE http://www.zlib.net/zlib_how.html
/// THIS SHOWS PRETTY SIMPLE EXAMPLE OF HOW TO DO COMPRESS/DECOMPRESS AND WE CAN USE THAT to amke new stream object
/// where inner loop is done each time through with a CHUNK

#if     qHasFeature_ZLib
#include    <zlib.h>

#if     defined (_MSC_VER)
// Use #pragma comment lib instead of explicit entry in the lib entry of the project file
#pragma comment (lib, "zlib.lib")
#endif

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::DataExchange;
using   namespace   Stroika::Foundation::DataExchange::Compression;
using   namespace   Stroika::Foundation::Streams;

namespace {

    void    ThrowIfZLibErr_ (int err)
    {
        if (err != Z_OK) {
            Execution::Throw (Execution::StringException (L"ZLIB ERR"));    // @todo embelish
        }
    }

    using   Memory::Byte;
    struct MyCompressionStream_ : InputStream<Byte> {
        struct  BaseRep_ : public _IRep  {
            static  constexpr   size_t  CHUNK   =   16384;
            Streams::InputStream<Memory::Byte>  fInStream_;
            z_stream                            fZStream_;
            Byte                                fInBuf_[CHUNK];
            BaseRep_ (const Streams::InputStream<Memory::Byte>& in)
                : fInStream_ (in)
                , fZStream_ {}
            {
            }
            virtual ~BaseRep_ () = default;
            virtual bool    IsSeekable () const
            {
                // for now - KISS
                return false;   // SHOULD allow seekable IFF src is seekable
            }
            virtual SeekOffsetType      GetReadOffset () const override
            {
                return SeekOffsetType {};
            }
            virtual SeekOffsetType      SeekRead (Whence whence, SignedSeekOffsetType offset) override
            {
                RequireNotReached ();
                return SeekOffsetType {};
            }
            void    _AssureInputAvailable ()
            {
                if (fZStream_.avail_in == 0) {
                    fZStream_.avail_in = fInStream_.Read (begin (fInBuf_), end (fInBuf_));
                    fZStream_.next_in = begin (fInBuf_);
                }
            }
        };
        struct  DeflateRep_ : BaseRep_  {
            DeflateRep_ (const Streams::InputStream<Memory::Byte>& in)
                : BaseRep_ (in)
            {
                int level =  Z_DEFAULT_COMPRESSION;
                ThrowIfZLibErr_ (::deflateInit (&fZStream_, level));
            }
            virtual ~DeflateRep_ ()
            {
                Verify (::deflateEnd (&fZStream_) == Z_OK);
            }
            virtual size_t  Read (SeekOffsetType* offset, ElementType* intoStart, ElementType* intoEnd) override
            {
                _AssureInputAvailable ();

                // @TODO - THIS IS WRONG- in that it doesnt take into account if strm.next_in still has data
                //tmphack - do 1 byte at a time
                Require (intoStart < intoEnd);

                fZStream_.avail_out = intoEnd - intoStart;
                fZStream_.next_out = intoStart;
                ThrowIfZLibErr_ (::deflate (&fZStream_, Z_NO_FLUSH));

                ptrdiff_t have = CHUNK - fZStream_.avail_out;
                Assert (have < intoEnd - intoStart);
                return have;
            }
        };
        struct  InflateRep_ : BaseRep_  {
            InflateRep_ (const Streams::InputStream<Memory::Byte>& in)
                : BaseRep_ (in)
            {
                ThrowIfZLibErr_ (::inflateInit (&fZStream_));
            }
            virtual ~InflateRep_ ()
            {
                Verify (::inflateEnd (&fZStream_) == Z_OK);
            }
            virtual size_t  Read (SeekOffsetType* offset, ElementType* intoStart, ElementType* intoEnd) override
            {
                _AssureInputAvailable ();

                // @TODO - THIS IS WRONG- in that it doesnt take into account if strm.next_in still has data
                //tmphack - do 1 byte at a time
                Require (intoStart < intoEnd);

                fZStream_.avail_out = intoEnd - intoStart;
                fZStream_.next_out = intoStart;
                ThrowIfZLibErr_ (::inflate (&fZStream_, Z_NO_FLUSH));

                ptrdiff_t have = CHUNK - fZStream_.avail_out;
                Assert (have < intoEnd - intoStart);
                return have;
            }
        };
        enum Compression {eCompression};
        enum DeCompression {eDeCompression};
        MyCompressionStream_ (Compression, const Streams::InputStream<Memory::Byte>& in)
            : InputStream<Byte> (make_shared<DeflateRep_> (in))
        {
        }
        MyCompressionStream_ (DeCompression, const Streams::InputStream<Memory::Byte>& in)
            : InputStream<Byte> (make_shared<InflateRep_> (in))/// tmphack cuz NYI otjer
        {
        }
    };
}
#endif

#if     qHasFeature_ZLib
class   Zip::Reader::Rep_ : public Reader::_IRep {
public:
    virtual InputStream<Byte>   Compress (const InputStream<Byte>& src) const override
    {
        return MyCompressionStream_ (MyCompressionStream_::eCompression, src);
    }
    virtual InputStream<Byte>   Decompress (const InputStream<Byte>& src) const override
    {
        return MyCompressionStream_ (MyCompressionStream_::eDeCompression, src);
    }
};

Zip::Reader::Reader ()
    : DataExchange::Compression::Reader (make_shared<Rep_> ())
{
}
#endif
<commit_msg>Some progress on flush param for DataExchange/Compression/Zip/Reader<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#include    "../../../StroikaPreComp.h"

#include    "Reader.h"

//// SEEE http://www.zlib.net/zlib_how.html
/// THIS SHOWS PRETTY SIMPLE EXAMPLE OF HOW TO DO COMPRESS/DECOMPRESS AND WE CAN USE THAT to amke new stream object
/// where inner loop is done each time through with a CHUNK

#if     qHasFeature_ZLib
#include    <zlib.h>

#if     defined (_MSC_VER)
// Use #pragma comment lib instead of explicit entry in the lib entry of the project file
#pragma comment (lib, "zlib.lib")
#endif

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::DataExchange;
using   namespace   Stroika::Foundation::DataExchange::Compression;
using   namespace   Stroika::Foundation::Streams;

namespace {

    void    ThrowIfZLibErr_ (int err)
    {
        if (err != Z_OK) {
            Execution::Throw (Execution::StringException (L"ZLIB ERR"));    // @todo embelish
        }
    }

    using   Memory::Byte;
    struct MyCompressionStream_ : InputStream<Byte> {
        struct  BaseRep_ : public _IRep  {
            static  constexpr   size_t  CHUNK   =   16384;
            Streams::InputStream<Memory::Byte>  fInStream_;
            z_stream                            fZStream_;
            Byte                                fInBuf_[CHUNK];
            BaseRep_ (const Streams::InputStream<Memory::Byte>& in)
                : fInStream_ (in)
                , fZStream_ {}
            {
            }
            virtual ~BaseRep_ () = default;
            virtual bool    IsSeekable () const
            {
                // for now - KISS
                return false;   // SHOULD allow seekable IFF src is seekable
            }
            virtual SeekOffsetType      GetReadOffset () const override
            {
                return SeekOffsetType {};
            }
            virtual SeekOffsetType      SeekRead (Whence whence, SignedSeekOffsetType offset) override
            {
                RequireNotReached ();
                return SeekOffsetType {};
            }
            void    _AssureInputAvailable ()
            {
                if (fZStream_.avail_in == 0) {
                    fZStream_.avail_in = fInStream_.Read (begin (fInBuf_), end (fInBuf_));
                    fZStream_.next_in = begin (fInBuf_);
                }
            }
        };
        struct  DeflateRep_ : BaseRep_  {
            DeflateRep_ (const Streams::InputStream<Memory::Byte>& in)
                : BaseRep_ (in)
            {
                int level =  Z_DEFAULT_COMPRESSION;
                ThrowIfZLibErr_ (::deflateInit (&fZStream_, level));
            }
            virtual ~DeflateRep_ ()
            {
                Verify (::deflateEnd (&fZStream_) == Z_OK);
            }
            virtual size_t  Read (SeekOffsetType* offset, ElementType* intoStart, ElementType* intoEnd) override
            {
                _AssureInputAvailable ();

                // @TODO - THIS IS WRONG- in that it doesnt take into account if strm.next_in still has data
                //tmphack - do 1 byte at a time
                Require (intoStart < intoEnd);
                //int   flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
                int   flush = fZStream_.avail_in == 0 ? Z_FINISH : Z_NO_FLUSH;

                fZStream_.avail_out = intoEnd - intoStart;
                fZStream_.next_out = intoStart;
                ThrowIfZLibErr_ (::deflate (&fZStream_, flush));

                ptrdiff_t have = CHUNK - fZStream_.avail_out;
                Assert (have < intoEnd - intoStart);
                return have;
            }
        };
        struct  InflateRep_ : BaseRep_  {
            InflateRep_ (const Streams::InputStream<Memory::Byte>& in)
                : BaseRep_ (in)
            {
                ThrowIfZLibErr_ (::inflateInit (&fZStream_));
            }
            virtual ~InflateRep_ ()
            {
                Verify (::inflateEnd (&fZStream_) == Z_OK);
            }
            virtual size_t  Read (SeekOffsetType* offset, ElementType* intoStart, ElementType* intoEnd) override
            {
                _AssureInputAvailable ();

                // @TODO - THIS IS WRONG- in that it doesnt take into account if strm.next_in still has data
                //tmphack - do 1 byte at a time
                Require (intoStart < intoEnd);

                fZStream_.avail_out = intoEnd - intoStart;
                fZStream_.next_out = intoStart;
                ThrowIfZLibErr_ (::inflate (&fZStream_, Z_NO_FLUSH));

                ptrdiff_t have = CHUNK - fZStream_.avail_out;
                Assert (have < intoEnd - intoStart);
                return have;
            }
        };
        enum Compression {eCompression};
        enum DeCompression {eDeCompression};
        MyCompressionStream_ (Compression, const Streams::InputStream<Memory::Byte>& in)
            : InputStream<Byte> (make_shared<DeflateRep_> (in))
        {
        }
        MyCompressionStream_ (DeCompression, const Streams::InputStream<Memory::Byte>& in)
            : InputStream<Byte> (make_shared<InflateRep_> (in))/// tmphack cuz NYI otjer
        {
        }
    };
}
#endif

#if     qHasFeature_ZLib
class   Zip::Reader::Rep_ : public Reader::_IRep {
public:
    virtual InputStream<Byte>   Compress (const InputStream<Byte>& src) const override
    {
        return MyCompressionStream_ (MyCompressionStream_::eCompression, src);
    }
    virtual InputStream<Byte>   Decompress (const InputStream<Byte>& src) const override
    {
        return MyCompressionStream_ (MyCompressionStream_::eDeCompression, src);
    }
};

Zip::Reader::Reader ()
    : DataExchange::Compression::Reader (make_shared<Rep_> ())
{
}
#endif
<|endoftext|>


<commit_before>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2019 Ryo Suzuki
//	Copyright (c) 2016-2019 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# pragma once
# include <Siv3D/Windows.hpp>
# include <d3d11.h>
# include <Siv3D/Array.hpp>
# include <Siv3D/Vertex2D.hpp>
# include "D3D11Renderer2DCommand.hpp"

namespace s3d
{
	using IndexType = Vertex2D::IndexType;

	struct BatchInfo
	{
		uint32 indexCount = 0;

		uint32 startIndexLocation = 0;

		uint32 baseVertexLocation = 0;
	};

	class D3D11SpriteBatch
	{
	private:

		struct BatchBufferPos
		{
			uint16 vertexPos = 0;

			uint32 indexPos = 0;
		};

		ID3D11Device* m_device = nullptr;
		ID3D11DeviceContext* m_context = nullptr;

		ComPtr<ID3D11Buffer> m_vertexBuffer;
		uint32 m_vertexBufferWritePos = 0;

		ComPtr<ID3D11Buffer> m_indexBuffer;
		uint32 m_indexBufferWritePos = 0;

		Array<Vertex2D> m_vertexArray;
		uint32 m_vertexArrayWritePos = 0;

		Array<IndexType> m_indexArray;
		uint32 m_indexArrayWritePos = 0;

		Array<BatchBufferPos> m_batches;

		static constexpr uint32 InitialVertexArraySize	= 4096;
		static constexpr uint32 InitialIndexArraySize	= 4096 * 8; // 32768

		static constexpr uint32 MaxVertexArraySize		= 65536 * 64; // 4,194,304
		static constexpr uint32 MaxIndexArraySize		= 65536 * 64; // 4,194,304

		static constexpr uint32 VertexBufferSize		= 65535;// 65535;
		static constexpr uint32 IndexBufferSize			= VertexBufferSize * 4; // 524,288

	public:

		D3D11SpriteBatch();

		[[nodiscard]] bool init(ID3D11Device* device, ID3D11DeviceContext* context);

		[[nodiscard]] std::tuple<Vertex2D*, IndexType*, IndexType> getBuffer(const uint16 vertexSize, const uint32 indexSize, D3D11Renderer2DCommand& command);

		[[nodiscard]] size_t num_batches() const noexcept;

		void reset();

		void setBuffers();

		[[nodiscard]] BatchInfo updateBuffers(size_t batchIndex);
	};
}
<commit_msg>update IndexBufferSize<commit_after>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2019 Ryo Suzuki
//	Copyright (c) 2016-2019 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# pragma once
# include <Siv3D/Windows.hpp>
# include <d3d11.h>
# include <Siv3D/Array.hpp>
# include <Siv3D/Vertex2D.hpp>
# include "D3D11Renderer2DCommand.hpp"

namespace s3d
{
	using IndexType = Vertex2D::IndexType;

	struct BatchInfo
	{
		uint32 indexCount = 0;

		uint32 startIndexLocation = 0;

		uint32 baseVertexLocation = 0;
	};

	class D3D11SpriteBatch
	{
	private:

		struct BatchBufferPos
		{
			uint16 vertexPos = 0;

			uint32 indexPos = 0;
		};

		ID3D11Device* m_device = nullptr;
		ID3D11DeviceContext* m_context = nullptr;

		ComPtr<ID3D11Buffer> m_vertexBuffer;
		uint32 m_vertexBufferWritePos = 0;

		ComPtr<ID3D11Buffer> m_indexBuffer;
		uint32 m_indexBufferWritePos = 0;

		Array<Vertex2D> m_vertexArray;
		uint32 m_vertexArrayWritePos = 0;

		Array<IndexType> m_indexArray;
		uint32 m_indexArrayWritePos = 0;

		Array<BatchBufferPos> m_batches;

		static constexpr uint32 InitialVertexArraySize	= 4096;
		static constexpr uint32 InitialIndexArraySize	= 4096 * 8; // 32768

		static constexpr uint32 MaxVertexArraySize		= 65536 * 64; // 4,194,304
		static constexpr uint32 MaxIndexArraySize		= 65536 * 64; // 4,194,304

		static constexpr uint32 VertexBufferSize		= 65535;// 65535;
		static constexpr uint32 IndexBufferSize			= (VertexBufferSize + 1) * 4; // 524,288

	public:

		D3D11SpriteBatch();

		[[nodiscard]] bool init(ID3D11Device* device, ID3D11DeviceContext* context);

		[[nodiscard]] std::tuple<Vertex2D*, IndexType*, IndexType> getBuffer(const uint16 vertexSize, const uint32 indexSize, D3D11Renderer2DCommand& command);

		[[nodiscard]] size_t num_batches() const noexcept;

		void reset();

		void setBuffers();

		[[nodiscard]] BatchInfo updateBuffers(size_t batchIndex);
	};
}
<|endoftext|>