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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [sysc/] [src/] [TapActionDRScan.cpp] - Rev 438

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

// ----------------------------------------------------------------------------
 
// TAP DR-Scan action: implementation
 
// Copyright (C) 2009  Embecosm Limited <info@embecosm.com>
 
// Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
// This file is part of the Embecosm cycle accurate SystemC JTAG library.
 
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, 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 Lesser General Public
// License for more details.
 
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
// The C/C++ parts of this program are commented throughout in a fashion
// suitable for processing with Doxygen.
 
// ----------------------------------------------------------------------------
 
// $Id$
 
#include <iostream>
#include <stdio.h>
#include "TapActionDRScan.h"
#include "TapStateMachine.h"
 
 
//! Constructor for "large" DR registers
 
//! Sets up the superclass with the SystemC completion event and initializes
//! our state as appropriate.
 
//! This constructor represents large registers as an array of uint64_t, with
//! least significant bits in the lowest numbered element, and any odd bits in
//! the highest numbered element.
 
//! However if we are presented with an array that represents a "small"
//! (i.e. up to 64-bit) register, we will store it efficiently.
 
//! @param[in] doneEvent     SystemC event to be signalled when this action is
//!                          complete.
//! @param[in] _dRegInArray  The register to shift in.
//! @param[in] _dRegSize     Size in bits of the register to shift in.
 
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
				  uint64_t          *_dRegInArray,
				  int                _dRegSize
				  ) :
  TapAction (_doneEvent),
  dRegBitSize (_dRegSize),
  dRegWordSize ((_dRegSize + 63) / 64),
  goToPauseState(0),
  bitsBeforePause(0),
  bitsShifted (0),
  dRScanState (SHIFT_DR_PREPARING)
{
  // Small registers are represented simply. Large registers are copied to a
  // local instance (since we destroy dRegIn when shifting it)
 
  if (1 == dRegWordSize)
    {
      dRegIn  = _dRegInArray[0];
      dRegOut = 0;
    }
  else
    {
      dRegInArray  = new uint64_t [dRegWordSize];
      dRegOutArray = new uint64_t [dRegWordSize];
 
      // Copy in the in array and zero the out array
      for (int i = 0; i < dRegWordSize; i++)
	{
	  dRegInArray[i]  = _dRegInArray[i];
	  dRegOutArray[i] = 0;
	}
 
      // Create a mask for the top word
      int maskBits = ((dRegBitSize - 1) % 64) + 1;
      topMask = (1ULL << maskBits) - 1ULL;
    }
}	// TapActionDRScan ()
 
 
//! Constructor for small DR registers
 
//! Sets up the superclass with the SystemC completion event and initializes
//! our state as appropriate.
 
//! This constructor represents small registers in a single uint64_t
 
//! @param[in] doneEvent  SystemC event to be signalled when this action is
//!                       complete.
//! @param[in] _dRegIn    The register to shift in.
//! @param[in] _dRegSize  Size in bits of the register to shift in. Must be no
//!                       greater than 64, or we give a rude message and set
//!                       the value to 64 anyway.
 
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
				  uint64_t           _dRegIn,
				  int                _dRegSize) :
  TapAction (_doneEvent),
  dRegBitSize (_dRegSize),
  dRegWordSize (1),
  goToPauseState(0),
  bitsBeforePause(0),
  bitsShifted (0),
  dRScanState (SHIFT_DR_PREPARING)
{
  // Print a rude message if we are not small
  if (dRegBitSize > 64)
    {
      std::cerr << "Simple DR size reduced to 64 bits" << std::endl;
      dRegBitSize = 64;
    }
 
  // Simple representation
  dRegIn  = _dRegIn;
  dRegOut = 0;
 
}	// TapActionDRScan ()
 
//! Constructor for "large" DR registers using special PAUSE state
 
//! Sets up the superclass with the SystemC completion event and initializes
//! our state as appropriate.
 
//! This constructor represents large registers as an array of uint64_t, with
//! least significant bits in the lowest numbered element, and any odd bits in
//! the highest numbered element.
 
//! However if we are presented with an array that represents a "small"
//! (i.e. up to 64-bit) register, we will store it efficiently.
 
//! @param[in] doneEvent     SystemC event to be signalled when this action is
//!                          complete.
//! @param[in] _dRegInArray  The register to shift in.
//! @param[in] _dRegSize     Size in bits of the register to shift in.
//! @param[in] _goToPauseState     Switch determining if we go to PAUSE state after _bitsBeforePauseState and poll for TDO=0
//! @param[in] _bitsBeforePauseState     Number of bits to shift in before going to shift pause state and polling TDO, indicating transaction has completed
 
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
				  uint64_t          *_dRegInArray,
				  int                _dRegSize,
				  int                _goToPauseState,
				  int                _bitsBeforePauseState
				  ) :
  TapAction (_doneEvent),
  dRegBitSize (_dRegSize),
  dRegWordSize ((_dRegSize + 63) / 64),
  goToPauseState(_goToPauseState),
  bitsBeforePause(_bitsBeforePauseState),
  pauseStateCount(0),
  bitsShifted (0),
  dRScanState (SHIFT_DR_PREPARING)
{
  // Small registers are represented simply. Large registers are copied to a
  // local instance (since we destroy dRegIn when shifting it)
 
  if (1 == dRegWordSize)
    {
      dRegIn  = _dRegInArray[0];
      dRegOut = 0;
    }
  else
    {
      dRegInArray  = new uint64_t [dRegWordSize];
      dRegOutArray = new uint64_t [dRegWordSize];
 
      // Copy in the in array and zero the out array
      for (int i = 0; i < dRegWordSize; i++)
	{
	  dRegInArray[i]  = _dRegInArray[i];
	  dRegOutArray[i] = 0;
	}
 
      // Create a mask for the top word
      int maskBits = ((dRegBitSize - 1) % 64) + 1;
      topMask = (1ULL << maskBits) - 1ULL;
    }
}	// TapActionDRScan ()
 
 
//! Constructor for small DR registers using special PAUSE state
 
//! Sets up the superclass with the SystemC completion event and initializes
//! our state as appropriate.
 
//! This constructor represents small registers in a single uint64_t
 
//! @param[in] doneEvent  SystemC event to be signalled when this action is
//!                       complete.
//! @param[in] _dRegIn    The register to shift in.
//! @param[in] _dRegSize  Size in bits of the register to shift in. Must be no
//!                       greater than 64, or we give a rude message and set
//!                       the value to 64 anyway.
//! @param[in] _goToPauseState     Switch determining if we go to PAUSE state after _bitsBeforePauseState and poll for TDO=0
//! @param[in] _bitsBeforePauseState     Number of bits to shift in before going to shift pause state and polling TDO, indicating transaction has completed
 
 
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
				  uint64_t           _dRegIn,
				  int                _dRegSize,
				  int                _goToPauseState,
				  int                _bitsBeforePauseState
				  ) :
  TapAction (_doneEvent),
  dRegBitSize (_dRegSize),
  dRegWordSize (1),
  goToPauseState(_goToPauseState),
  bitsBeforePause(_bitsBeforePauseState),
  pauseStateCount(0),
  bitsShifted (0),
  dRScanState (SHIFT_DR_PREPARING)
{
  // Print a rude message if we are not small
  if (dRegBitSize > 64)
    {
      std::cerr << "Simple DR size reduced to 64 bits" << std::endl;
      dRegBitSize = 64;
    }
 
  // Simple representation
  dRegIn  = _dRegIn;
  dRegOut = 0;
 
}	// TapActionDRScan ()
 
 
 
 
//! Destructor.
 
//! If we allocated them, free the large registers
 
TapActionDRScan::~TapActionDRScan ()
{
  if (dRegWordSize > 1)
    {
      delete [] dRegInArray;
      delete [] dRegOutArray;
    }
}	// ~TapActionDRScan ()
 
 
//! Process the Shift-DR action
 
//! This drives the DR-Scan state. We can only do this if we have the TAP
//! state machine in a consistent state, which in turn is only possible if we
//! have been through a reset cycle.
 
//! If the state machine shows it has yet to be through a reset cycle, we
//! drive that cycle, after issuing a warning. This functionality is provided
//! by the parent class, TapAction::.
 
//! @param[in]  tapStateMachine  The TAP state machine with which this action
//!                              is associated. 
//! @param[out] tdi              The value to drive on TDI
//! @param[in]  tdo              The value currently on TDO
//! @param[out] tms              The value to drive on TMS
 
//! @return  True if the action is complete
 
bool
TapActionDRScan::process (TapStateMachine *tapStateMachine,
			  bool            &tdi,
			  bool             tdo,
			  bool            &tms)
{
  // Ensure we are in a consistent state. If not then we'll have moved towards
  // it and can return with the given tms
  if (!checkResetDone (tapStateMachine, tms, true))
    {
      return false;
    }
 
  if (goToPauseState)
    {
      switch (dRScanState)
	{
	case SHIFT_DR_PREPARING:
 
	  // Are we in the Shift-DR state yet?
	  if (!tapStateMachine->targetState (TAP_SHIFT_DR, tms))
	    {
	      return  false;		// Not there. Accept the TMS value
	    }
	  else
	    {
	      dRScanState = SHIFT_DR_SHIFTING_BEFORE_PAUSE;	// Drop through
	    }
 
	case SHIFT_DR_SHIFTING_BEFORE_PAUSE:
 
	  // Are we still shifting stuff?
	  if (bitsShifted < bitsBeforePause)
	    {
	      // We are in the Shift-DR state. Another bit about to be done, so
	      // increment the count
	      bitsShifted++;
 
	      // Set the TDI value. In a routine to keep this tidy.
	      tdi = shiftDRegOut ();
 
	      // Record the TDO value. This is always a cycle late, so we ignore
	      // it the first time. The value shifts in from the top.
	      if (bitsShifted > 1)
		{
		  shiftDRegIn (tdo);
		}
 
	      // TMS is 0 to keep us here UNLESS this is the last bit, in which case
	      // it is 1 to move us into Exit1-DR.
	      tms = (bitsShifted == bitsBeforePause);
 
	      // Not done until we've updated
	      return false;
	    }
	  else
	    {
	      // Capture the last TDO bit
	      shiftDRegIn (tdo);
 
	      // Now lower TMS to go to PAUSE_DR
	      tms = false;
 
	      dRScanState = SHIFT_DR_SHIFTING_PAUSE;
 
	    }
 
	case SHIFT_DR_SHIFTING_PAUSE:
	  {
	    if (!tapStateMachine->targetState (TAP_PAUSE_DR, tms))
	      {
		return  false;		// Not there. Accept the TMS value
	      }
 
	    if ( pauseStateCount++ < 3)
	      return false;
	    // Sit in DR_PAUSE state and cycle until TDO is low
	    // tms starts false, should get set to true on the cycle
	    // tdo goes low, then the next cycle we go back to SHIFT_DR
	    // and we return so tms isn't set again.
	    if (!tdo)
	      {
		tms = true;
		dRScanState = SHIFT_DR_EXIT2;
		return false;
	      }
	  }
 
	case SHIFT_DR_EXIT2:
	  {
	    tms = false;
	    shiftDRegIn (0);
	    dRScanState = SHIFT_DR_SHIFTING_AFTER_PAUSE;
	    return false;
 
	  }
 
	case SHIFT_DR_SHIFTING_AFTER_PAUSE:
	  {
	    if (bitsShifted < dRegBitSize)
	      {
		// We are in the Shift-DR state. Another bit about to be done, so
		// increment the count
		bitsShifted++;
 
		// Set the TDI value. In a routine to keep this tidy.
		tdi = shiftDRegOut ();
 
		//printf("shifting after pause (%d+32=%d) %d of %d tdo=%d\n",bitsBeforePause,bitsBeforePause+32, bitsShifted, dRegBitSize,(tdo) ? 1 : 0);
		shiftDRegIn (tdo);
 
		// TMS is 0 to keep us here UNLESS this is the last bit, in which case
		// it is 1 to move us into Exit1-DR.
		tms = (bitsShifted == dRegBitSize);
 
		// Not done until we've updated
		return false;
	      }
	    else
	      {
		// Capture the last TDO bit
		shiftDRegIn (tdo);
 
		dRScanState = SHIFT_DR_UPDATING;	// Drop through
	      }
	  }
 
 
	case SHIFT_DR_UPDATING:
 
	  // Are we still trying to update?
	  if (!tapStateMachine->targetState (TAP_UPDATE_DR, tms))
	    {
	      return  false;		// Not there. Accept the TMS value
	    }
	  else
	    {
	      return  true;			// All done
	    }
	}
    }
  else
    {
      switch (dRScanState)
	{
	case SHIFT_DR_PREPARING:
 
	  // Are we in the Shift-DR state yet?
	  if (!tapStateMachine->targetState (TAP_SHIFT_DR, tms))
	    {
	      return  false;		// Not there. Accept the TMS value
	    }
	  else
	    {
	      dRScanState = SHIFT_DR_SHIFTING;	// Drop through
	    }
 
	case SHIFT_DR_SHIFTING:
 
	  // Are we still shifting stuff?
	  if (bitsShifted < dRegBitSize)
	    {
	      // We are in the Shift-DR state. Another bit about to be done, so
	      // increment the count
	      bitsShifted++;
 
	      // Set the TDI value. In a routine to keep this tidy.
	      tdi = shiftDRegOut ();
 
	      // Record the TDO value. This is always a cycle late, so we ignore
	      // it the first time. The value shifts in from the top.
	      if (bitsShifted > 1)
		{
		  shiftDRegIn (tdo);
		}
 
	      // TMS is 0 to keep us here UNLESS this is the last bit, in which case
	      // it is 1 to move us into Exit1-DR.
	      tms = (bitsShifted == dRegBitSize);
 
	      // Not done until we've updated
	      return false;
	    }
	  else
	    {
	      // Capture the last TDO bit
	      shiftDRegIn (tdo);
 
	      dRScanState = SHIFT_DR_UPDATING;	// Drop through
 
	    }
 
	case SHIFT_DR_UPDATING:
 
	  // Are we still trying to update?
	  if (!tapStateMachine->targetState (TAP_UPDATE_DR, tms))
	    {
	      return  false;		// Not there. Accept the TMS value
	    }
	  else
	    {
	      return  true;			// All done
	    }
	}
    }
}	// process ()
 
 
//! Get the shifted out value.
 
//! This version works with large values.
 
//! @param[out] dRegArray  Array for the result
void
TapActionDRScan::getDRegOut (uint64_t  dRegArray[])
{
  if (1 == dRegWordSize)
    {
      dRegArray[0] = dRegOut;
    }
  else
    {
      for (int i = 0 ; i < dRegWordSize; i++)
	{
	  dRegArray[i] = dRegOutArray[i];
	}
    }
}	// getDRegOut ()
 
 
//! Get the shifted out value.
 
//! This version is for small values. For large values it silently returns the
//! bottom 64 bits only.
 
//! @todo  Should we give an error. Or is it useful to allow efficient access
//!        to the bottom 64 bits?
 
//! @return  The value shifted out (or the bottom 64 bits thereof if the
//!          register is "large").
uint64_t
TapActionDRScan::getDRegOut ()
{
  if (1 == dRegWordSize)
    {
      return dRegOut;
    }
  else
    {
      return dRegOutArray[0];
    }
}	// getDRegOut ()
 
 
//! Utility to shift the bottom bit out of the dReg.
 
//! Two flavours depending on whether we have a "small" register
 
//! @return  The bit shifted out.
bool
TapActionDRScan::shiftDRegOut ()
{
  if (1 == dRegWordSize)		// "Small" register
    {
      bool  res = dRegIn & 1;
      dRegIn >>= 1;
      return  res;
    }
  else					// "Large" register
    {
      bool  res = (dRegInArray[0] & 1) == 1;
 
      // Shift all but the first word along
      for (int  i = 0; i < (dRegWordSize - 1); i++)
	{
	  dRegInArray[i] = (dRegInArray[i] >> 1) | (dRegInArray[i+1] << 63);
	}
 
      // Shift the first word
      dRegInArray[dRegWordSize - 1] >>= 1;
 
      return  res;
    }
}	// shiftDRegOut ()
 
 
//! Utility to shift the top bit into the dReg.
 
//! Two flavours depending on whether we have a "small" register
 
//! @param bitIn  The bit to shift in the top
void
TapActionDRScan::shiftDRegIn (bool  bitIn)
{
  if (1 == dRegWordSize)		// "Small" register
    {
      dRegOut >>= 1;			// Move all the existing bits right
 
      if (bitIn)			// OR any new bit in
	{
	  uint64_t tmpBit = 1ULL << (dRegBitSize - 1);
	  dRegOut |= tmpBit;
	}
    }
  else					// "Large" register
    {
      // Shift all but the first word along
      for (int  i = 0; i < (dRegWordSize - 1); i++)
	{
	  dRegOutArray[i] >>= 1;
	  dRegOutArray[i]  |= dRegOutArray[i+1] << 63;
	}
 
      // The first word is shifted and the new bit masked in
      dRegOutArray[dRegWordSize - 1] >>= 1;
      dRegOutArray[dRegWordSize - 1]  |= bitIn ? (topMask + 1) >> 1 : 0;
    }
}	// shiftDRegIn ()
 

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.