OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.6/] [tools/] [src/] [librlink/] [RlinkCommand.cpp] - Rev 40

Go to most recent revision | Compare with Previous | Blame | View Log

// $Id: RlinkCommand.cpp 495 2013-03-06 17:13:48Z mueller $
//
// Copyright 2011-2013 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program 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 General Public License
// for complete details.
// 
// Revision History: 
// Date         Rev Version  Comment
// 2013-05-06   495   1.0.2  add RlinkContext to Print() args
// 2013-02-03   481   1.0.1  use Rexception
// 2011-03-27   374   1.0    Initial version
// 2011-01-15   355   0.1    First draft
// ---------------------------------------------------------------------------
 
/*!
  \file
  \version $Id: RlinkCommand.cpp 495 2013-03-06 17:13:48Z mueller $
  \brief   Implemenation of class RlinkCommand.
 */
 
// debug
#include <iostream>
 
#include <algorithm>
 
#include "RlinkCommand.hpp"
 
#include "librtools/RosFill.hpp"
#include "librtools/RosPrintf.hpp"
#include "librtools/RosPrintBvi.hpp"
#include "librtools/Rexception.hpp"
 
using namespace std;
 
/*!
  \class Retro::RlinkCommand
  \brief FIXME_docs
*/
 
// all method definitions in namespace Retro
namespace Retro {
 
//------------------------------------------+-----------------------------------
// constants definitions
 
const uint8_t  RlinkCommand::kCmdRreg;
const uint8_t  RlinkCommand::kCmdRblk;
const uint8_t  RlinkCommand::kCmdWreg;
const uint8_t  RlinkCommand::kCmdWblk;
const uint8_t  RlinkCommand::kCmdStat;
const uint8_t  RlinkCommand::kCmdAttn;
const uint8_t  RlinkCommand::kCmdInit;
 
const uint32_t RlinkCommand::kFlagInit;
const uint32_t RlinkCommand::kFlagSend;
const uint32_t RlinkCommand::kFlagDone;
const uint32_t RlinkCommand::kFlagPktBeg;
const uint32_t RlinkCommand::kFlagPktEnd;
const uint32_t RlinkCommand::kFlagRecov;
const uint32_t RlinkCommand::kFlagResend;
const uint32_t RlinkCommand::kFlagErrNak;
const uint32_t RlinkCommand::kFlagErrMiss;
const uint32_t RlinkCommand::kFlagErrCmd;
const uint32_t RlinkCommand::kFlagErrCrc;
const uint32_t RlinkCommand::kFlagChkStat;
const uint32_t RlinkCommand::kFlagChkData;
const uint32_t RlinkCommand::kFlagVol;
 
const uint8_t RlinkCommand::kStat_M_Stat;
const uint8_t RlinkCommand::kStat_V_Stat;
const uint8_t RlinkCommand::kStat_B_Stat;
const uint8_t RlinkCommand::kStat_M_Attn;
const uint8_t RlinkCommand::kStat_M_Cerr;
const uint8_t RlinkCommand::kStat_M_Derr;
const uint8_t RlinkCommand::kStat_M_RbNak;
const uint8_t RlinkCommand::kStat_M_RbErr;
 
const uint16_t RlinkCommand::kRbaddr_IInt;
const uint16_t RlinkCommand::kIInt_M_AnEna;
const uint16_t RlinkCommand::kIInt_M_ItoEna;
const uint16_t RlinkCommand::kIInt_M_ItoVal;
 
//------------------------------------------+-----------------------------------
//! Default constructor
 
RlinkCommand::RlinkCommand()
  : fRequest(0), 
    fAddress(0), 
    fData(0),
    fBlock(),
    fpBlockExt(0), 
    fBlockExtSize(0), 
    fStatRequest(0), 
    fStatus(0), 
    fFlags(0),
    fRcvSize(0),
    fpExpect(0)
{}
 
//------------------------------------------+-----------------------------------
//! Copy constructor
 
RlinkCommand::RlinkCommand(const RlinkCommand& rhs)
  : fRequest(rhs.fRequest), 
    fAddress(rhs.fAddress), 
    fData(rhs.fData),
    fBlock(rhs.fBlock),
    fpBlockExt(rhs.fpBlockExt), 
    fBlockExtSize(rhs.fBlockExtSize), 
    fStatRequest(rhs.fStatRequest), 
    fStatus(rhs.fStatus), 
    fFlags(rhs.fFlags),
    fRcvSize(rhs.fRcvSize),
    fpExpect(rhs.fpExpect ? new RlinkCommandExpect(*rhs.fpExpect) : 0)
{}
 
//------------------------------------------+-----------------------------------
//! Destructor
 
RlinkCommand::~RlinkCommand()
{
  delete fpExpect;                          // expect object owned by command
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RlinkCommand::CmdRblk(uint16_t addr, size_t size)
{
  SetCommand(kCmdRblk, addr);
  SetBlockRead(size);
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RlinkCommand::CmdRblk(uint16_t addr, uint16_t* pblock, size_t size)
{
  SetCommand(kCmdRblk, addr);
  SetBlockExt(pblock, size);
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RlinkCommand::CmdWblk(uint16_t addr, const std::vector<uint16_t>& block)
{
  SetCommand(kCmdWblk, addr);
  SetBlockWrite(block);
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RlinkCommand::CmdWblk(uint16_t addr, const uint16_t* pblock, size_t size)
{
  SetCommand(kCmdWblk, addr);
  SetBlockExt(const_cast<uint16_t*>(pblock), size);
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RlinkCommand::SetCommand(uint8_t cmd, uint16_t addr, uint16_t data)
{
  if (cmd > kCmdInit) 
    throw Rexception("RlinkCommand::SetCommand()", "Bad args: invalid cmd");
  if (addr > 0xff) 
    throw Rexception("RlinkCommand::SetCommand()", "Bad args: invalid addr");
  fRequest = cmd;
  fAddress = addr;
  fData    = data;
  fpBlockExt    = 0;
  fBlockExtSize = 0;
  fStatus  = 0;
  fFlags   = kFlagInit;
  fRcvSize = 0;
  delete fpExpect;
  fpExpect = 0;
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RlinkCommand::SetAddress(uint16_t addr)
{
  if (addr > 0xff) 
    throw Rexception("RlinkCommand::SetAddress()", "Bad args: invalid addr");
  fAddress = addr;
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RlinkCommand::SetBlockWrite(const std::vector<uint16_t>& block)
{
  if (block.size() == 0 || block.size() > 256) 
    throw Rexception("RlinkCommand::SetBlockWrite()",
                     "Bad args: invalid block size");
  fBlock = block;
  fpBlockExt    = 0;
  fBlockExtSize = 0;
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RlinkCommand::SetBlockRead(size_t size)
{
  if (size == 0 || size > 256) 
    throw Rexception("RlinkCommand::SetBlockRead()",
                     "Bad args: invalid block size");
  fBlock.clear();
  fBlock.resize(size);
  fpBlockExt    = 0;
  fBlockExtSize = 0;
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RlinkCommand::SetBlockExt(uint16_t* pblock, size_t size)
{
  if (pblock == 0) 
    throw Rexception("RlinkCommand::SetBlockExt()",
                     "Bad args: pblock is null");
  if (size == 0 || size > 256) 
    throw Rexception("RlinkCommand::SetBlockExt()",
                     "Bad args: invalid block size");
  fpBlockExt    = pblock;
  fBlockExtSize = size;
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RlinkCommand::SetExpect(RlinkCommandExpect* pexp)
{
  delete fpExpect;
  fpExpect = pexp;
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RlinkCommand::Print(std::ostream& os, const RlinkContext& cntx,
                         const RlinkAddrMap* pamap, size_t abase, 
                         size_t dbase, size_t sbase) const
{
  uint8_t ccode = Command();
 
  // separator + command mnemonic, code and flags
  // separator:  ++  first in packet
  //             --  non-first in packet
  //             -=  non-first in packet (marked volatile)
  const char* sep = "??";
  if (TestFlagAny(kFlagPktBeg)) {
    sep = "++";
  } else {
    sep = TestFlagAny(kFlagVol) ? "-=" : "--";
  }
 
  os << sep << " " << CommandName(ccode)
     << " (" << RosPrintBvi(Request(), 8)
     << ","  << RosPrintBvi(fFlags, 16, 20)
     << ")";
 
  // address field
  if (ccode==kCmdRreg || ccode==kCmdRblk ||
      ccode==kCmdWreg || ccode==kCmdWblk ||
      ccode==kCmdInit) {
    os << " a=" << RosPrintBvi(fAddress, abase);
    if (pamap) {
      string name;
      if (!pamap->Find(fAddress, name)) name.clear();
      os << "(" << name << RosFill(pamap->MaxNameLength()-name.length()) << ")";
    }
  }
 
  // data field (scalar)
  if (ccode== kCmdRreg || ccode==kCmdWreg ||
      ccode== kCmdStat || ccode==kCmdAttn ||
      ccode== kCmdInit) {
    os << " d=" << RosPrintBvi(fData, dbase);    
 
    if (fpExpect &&
        (ccode==kCmdRreg || ccode==kCmdStat || ccode==kCmdAttn)) {
      if (TestFlagAny(kFlagChkData)) {
        os << "#";
        os << " D=" << RosPrintBvi(fpExpect->DataValue(), dbase);
        if (fpExpect->DataMask() != 0x0000)  {
          os << "," << RosPrintBvi(fpExpect->DataMask(), dbase);
        }
      } else if (fpExpect->DataIsChecked()) {
        os << "!";
      } else {
        os << " ";
      }
    } else {
      os << " ";
    }
  }
 
  if (ccode== kCmdRblk || ccode==kCmdWblk) {
    os << " n=" << RosPrintf(BlockSize(), "d", 3); 
  }
 
  // ccmd field
  if (ccode == kCmdStat) {
    os << " c=" << RosPrintBvi(fStatRequest, 8);    
  }
 
  // status field
  os << " s=" << RosPrintBvi(fStatus, sbase);
  uint8_t scval  = fpExpect ? fpExpect->StatusValue() : cntx.StatusValue();
  uint8_t scmsk  = fpExpect ? fpExpect->StatusMask()  : cntx.StatusMask();
  if (TestFlagAny(kFlagChkStat)) {
    os << "#";
    os << " S=" << RosPrintBvi(scval, sbase);
    if (scmsk != 0x00) {
      os << "," << RosPrintBvi(scmsk, sbase);
    }
  } else {
    os << ( scmsk != 0xff ? "!" : " " );
  }
 
  if (TestFlagAny(kFlagDone)) {
    if (TestFlagAny(kFlagChkStat|kFlagChkData)) {
      os << " FAIL: " 
         << Rtools::Flags2String(fFlags&(kFlagChkStat|kFlagChkData),
                                 FlagNames(),',');
    } else {
      os << " OK";
    }
    if (TestFlagAny(kFlagRecov|kFlagResend)) os << " WARN: retried";
  } else if (TestFlagAny(kFlagSend)) {
    os << " FAIL: "
       << Rtools::Flags2String(fFlags&(kFlagErrNak|kFlagErrMiss|
                                       kFlagErrCmd|kFlagErrCrc),
                               FlagNames(),',');
  } else {
    os << " PEND";
  }
 
  // handle data part of rblk and wblk commands
  size_t dwidth = (dbase==2) ? 16 : ((dbase==8) ? 6 : 4);  
 
  if (ccode==kCmdRblk) {
    bool  dcheck = (fpExpect && fpExpect->BlockValue().size() > 0);
    size_t ncol  = (80-4-5)/(dwidth+2);
 
    size_t size  = BlockSize();
    const uint16_t* pdat = BlockPointer();
 
    for (size_t i=0; i<size; i++) {
      if (i%ncol == 0) os << "\n    " << RosPrintf(i,"d",3) << ": ";
      os << RosPrintBvi(pdat[i], dbase);
      if (dcheck) {
        if (!fpExpect->BlockCheck(i, pdat[i])) {
          os << "#";
        } else {
          os << (fpExpect->BlockIsChecked(i) ? "!" : "-");
        }
      } else {
        os << " ";
      }
      os << " ";
    }
 
    if (dcheck && TestFlagAny(kFlagChkData)) {
      const vector<uint16_t>& evalvec = fpExpect->BlockValue();
      const vector<uint16_t>& emskvec = fpExpect->BlockMask();
      for (size_t i=0; i<size; i++) {
        if (!fpExpect->BlockCheck(i, pdat[i])) {
          os << "\n      FAIL d[" << RosPrintf(i,"d",3) << "]: "
             << RosPrintBvi(pdat[i], dbase) << "#"
             << "  D=" << RosPrintBvi(evalvec[i], dbase);
          if (i < emskvec.size() && emskvec[i]!=0x0000) {
            os << "," << RosPrintBvi(emskvec[i], dbase);
          }
        }
      }
    } 
  }
 
  if (ccode==kCmdWblk) {
    const uint16_t* pdat = BlockPointer();
    size_t size = BlockSize();
    size_t ncol = (80-4-5)/(dwidth+2);
    for (size_t i=0; i<size; i++) {
      if (i%ncol == 0) os << "\n    " << RosPrintf(i,"d",3) << ": ";
      os << RosPrintBvi(pdat[i], dbase) << "  ";
    }
  }
 
  os << endl;
 
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
void RlinkCommand::Dump(std::ostream& os, int ind, const char* text) const
{
  RosFill bl(ind);
  os << bl << (text?text:"--") << "RlinkCommand @ " << this << endl;
 
  os << bl << "  fRequest:        " << RosPrintBvi(fRequest,8)
     << "  seq:" << RosPrintf(SeqNumber(),"d",2)
     << "  cmd:" << RosPrintf(Command(),"d",1)
     << " " << CommandName(Command()) << endl;
  os << bl << "  fAddress:        " << RosPrintBvi(fAddress,0) << endl;
  os << bl << "  fData:           " << RosPrintBvi(fData,0) << endl;
  os << bl << "  fBlock.size:     " << RosPrintf(fBlock.size(),"d",3) << endl;
  os << bl << "  fpBlockExt:      " << fpBlockExt << endl;
  os << bl << "  fBlockExtSize:   " << RosPrintf(fBlockExtSize,"d",3) << endl;
  os << bl << "  fStatRequest:    " << RosPrintBvi(fStatRequest,0) << endl;
  os << bl << "  fStatus:         " << RosPrintBvi(fStatus,0) << endl;
  os << bl << "  fFlags:          " << RosPrintBvi(fFlags,16,24)
           << "  " << Rtools::Flags2String(fFlags, FlagNames()) << endl;
  os << bl << "  fRcvSize:        " << RosPrintf(fRcvSize,"d",4) << endl;
  if (BlockSize() > 0) {
    size_t ncol  = max(1, (80-ind-4-5)/(4+1));
    os << bl << "  block data:";
    for (size_t i=0; i<BlockSize(); i++) {
      if (i%ncol == 0) os << "\n" << bl << "    " << RosPrintf(i,"d",3) << ": ";
      os << RosPrintBvi(BlockPointer()[i],16) << " ";
    }
    os << endl;
  }
  if (fpExpect) fpExpect->Dump(os, ind+2, "fpExpect: ");
 
  return;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
const char* RlinkCommand::CommandName(uint8_t cmd)
{
  static const char* cmdname[8] = {"rreg","rblk","wreg","wblk",
                                   "stat","attn","init","????"};
 
  return cmdname[cmd&0x7];
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
const Retro::RflagName* RlinkCommand::FlagNames()
{
  // use msb first order, will also be printing order
  static Retro::RflagName fnam[] = {
    {kFlagChkData, "ChkData"},
    {kFlagChkStat, "ChkStat"},
    {kFlagErrCrc,  "ErrCrc"},
    {kFlagErrCmd,  "ErrCmd"},
    {kFlagErrMiss, "ErrMiss"},
    {kFlagErrNak,  "ErrNak"},
    {kFlagResend,  "Resend"},
    {kFlagRecov,   "Recov"},
    {kFlagPktEnd,  "PktEnd"},
    {kFlagPktBeg,  "PktBeg"},
    {kFlagDone,    "Done"},
    {kFlagSend,    "Send"},
    {kFlagInit,    "Init"},
    {0u, ""}
  };
  return fnam;
}
 
//------------------------------------------+-----------------------------------
//! FIXME_docs
 
RlinkCommand& RlinkCommand::operator=(const RlinkCommand& rhs)
{
  if (&rhs == this) return *this;
  fRequest      = rhs.fRequest;
  fAddress      = rhs.fAddress; 
  fData         = rhs.fData;
  fBlock        = rhs.fBlock;
  fpBlockExt    = rhs.fpBlockExt; 
  fBlockExtSize = rhs.fBlockExtSize; 
  fStatRequest  = rhs.fStatRequest;
  fStatus       = rhs.fStatus; 
  fFlags        = rhs.fFlags;
  fRcvSize      = rhs.fRcvSize;
  delete fpExpect;
  fpExpect      = rhs.fpExpect ? new RlinkCommandExpect(*rhs.fpExpect) : 0;
  return *this;
}
 
} // end namespace Retro
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.