blob: cc9879c9af0ad1ec5231cb2ebecc4c9674320b24 [file] [log] [blame] [edit]
//===========================================================================//
// Purpose : Method definitions for the TCH_RelativePlaceHandler class.
//
// Public methods include:
// - NewInstance, DeleteInstance, GetInstance, HasInstance
// - Configure
// - Set, Reset
// - LoadCarryChains
// - InitialPlace
// - Place
// - IsCandidate
// - IsValid
//
// Protected methods include:
// - TCH_RelativePlaceHandler_c, ~TCH_RelativePlaceHandler_c
//
// Private methods include:
// - AddLinkConstraint_
// - NewLinkConstraint_
// - MergeLinkConstraints_
// - ExistingLinkConstraint_
// - HasExistingLinkConstraint_
// - IsAvailableLinkConstraint_
// - ResetRelativeMacroList_
// - ResetRelativeBlockList_
// - InitialPlaceMacros_
// - InitialPlaceMacroNodes_
// - InitialPlaceMacroUpdate_
// - InitialPlaceMacroResetCoords_
// - InitialPlaceMacroIsLegal_
// - InitialPlaceMacroIsOpen_
// - PlaceSwapMacros_
// - PlaceSwapUpdate_
// - PlaceMacroIsRelativeCoord_
// - PlaceMacroIsAvailableCoord_
// - PlaceMacroResetRotate_
// - PlaceMacroIsLegalRotate_
// - PlaceMacroIsValidRotate_
// - PlaceMacroUpdateMoveList_
// - PlaceMacroIsLegalMoveList_
// - FindRandomRotateMode_
// - FindRandomOriginPoint_
// - FindRandomRelativeNodeIndex_
// - FindRelativeMacroIndex_
// - FindRelativeNodeIndex_
// - FindRelativeMacro_
// - FindRelativeNode_
// - FindRelativeBlock_
// - DecideAntiLink_
// - ShowIllegalRelativeMacroWarning_
// - ShowMissingBlockNameError_
// - ShowInvalidConstraintError_
//
//===========================================================================//
//---------------------------------------------------------------------------//
// Copyright (C) 2013 Jeff Rudolph, Texas Instruments (jrudolph@ti.com) //
// //
// Permission is hereby granted, free of charge, to any person obtaining a //
// copy of this software and associated documentation files (the "Software"),//
// to deal in the Software without restriction, including without limitation //
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
// and/or sell copies of the Software, and to permit persons to whom the //
// Software is furnished to do so, subject to the following conditions: //
// //
// The above copyright notice and this permission notice shall be included //
// in all copies or substantial portions of the Software. //
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS //
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF //
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN //
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, //
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR //
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE //
// USE OR OTHER DEALINGS IN THE SOFTWARE. //
//---------------------------------------------------------------------------//
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
#include "TC_Typedefs.h"
#include "TCT_Generic.h"
#include "TIO_PrintHandler.h"
#include "TGO_StringUtils.h"
#include "TCH_Typedefs.h"
#include "TCH_RelativeMove.h"
#include "TCH_RelativePlaceHandler.h"
// Initialize the relative place handler "singleton" class, as needed
TCH_RelativePlaceHandler_c* TCH_RelativePlaceHandler_c::pinstance_ = 0;
//===========================================================================//
// Method : TCH_RelativePlaceHandler_c
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
TCH_RelativePlaceHandler_c::TCH_RelativePlaceHandler_c(
void )
:
relativeMacroList_( TCH_RELATIVE_MACRO_LIST_DEF_CAPACITY ),
relativeBlockList_( TCH_RELATIVE_BLOCK_LIST_DEF_CAPACITY )
{
this->placeOptions_.rotateEnable = false;
this->placeOptions_.carryChainEnable = false;
this->placeOptions_.maxPlaceRetryCt = 0;
this->placeOptions_.maxMacroRetryCt = 0;
pinstance_ = 0;
}
//===========================================================================//
// Method : ~TCH_RelativePlaceHandler_c
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
TCH_RelativePlaceHandler_c::~TCH_RelativePlaceHandler_c(
void )
{
}
//===========================================================================//
// Method : NewInstance
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
void TCH_RelativePlaceHandler_c::NewInstance(
void )
{
pinstance_ = new TC_NOTHROW TCH_RelativePlaceHandler_c;
}
//===========================================================================//
// Method : DeleteInstance
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
void TCH_RelativePlaceHandler_c::DeleteInstance(
void )
{
if( pinstance_ )
{
delete pinstance_;
pinstance_ = 0;
}
}
//===========================================================================//
// Method : GetInstance
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
TCH_RelativePlaceHandler_c& TCH_RelativePlaceHandler_c::GetInstance(
bool newInstance )
{
if( !pinstance_ )
{
if( newInstance )
{
NewInstance( );
}
}
return( *pinstance_ );
}
//===========================================================================//
// Method : HasInstance
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::HasInstance(
void )
{
return( pinstance_ ? true : false );
}
//===========================================================================//
// Method : Configure
// Description : Configure a relative place handler (singleton) based on
// VPR's block array (ie. instance list), along with Toro's
// block list and associated options. This may include
// defining any relative macros based on relative placement
// constraints.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
// 06/25/13 jeffr : Extended to support relative placement dx|dy constraints
// 07/08/13 jeffr : Extended to support relative placement enable per macro
//===========================================================================//
bool TCH_RelativePlaceHandler_c::Configure(
bool placeOptions_rotateEnable, // See Toro's placement options
bool placeOptions_carryChainEnable, // "
size_t placeOptions_maxPlaceRetryCt, // "
size_t placeOptions_maxMacroRetryCt, // "
const TPO_InstList_t& toro_circuitBlockList ) // Defined by Toro's block list
{
bool ok = true;
// Start by caching placement options and VPR data (for later reference)
this->placeOptions_.rotateEnable = placeOptions_rotateEnable;
this->placeOptions_.carryChainEnable = placeOptions_carryChainEnable;
this->placeOptions_.maxPlaceRetryCt = placeOptions_maxPlaceRetryCt;
this->placeOptions_.maxMacroRetryCt = placeOptions_maxMacroRetryCt;
// Followed up clearing any existing relative block and macro list data
this->relativeMacroList_.Clear( );
this->relativeBlockList_.Clear( );
// Continue by setting relative block and macro list estimated capacities
int toro_circuitBlockCount = static_cast< int >( toro_circuitBlockList.GetLength( ));
this->relativeMacroList_.SetCapacity( toro_circuitBlockCount );
this->relativeBlockList_.SetCapacity( toro_circuitBlockCount );
// Initialize the local relative block list based on Toro's block list
for( size_t i = 0; i < toro_circuitBlockList.GetLength( ); ++i )
{
const TPO_Inst_c& toro_circuitBlock = *toro_circuitBlockList[i];
const char* pszBlockName = toro_circuitBlock.GetName( );
TCH_RelativeBlock_c relativeBlock( pszBlockName );
this->relativeBlockList_.Add( relativeBlock );
}
// Update the local relative block list based on Toro's block list
// (specifically, update based on any relative placement constraints)
for( size_t i = 0; i < toro_circuitBlockList.GetLength( ); ++i )
{
const TPO_Inst_c& toro_circuitBlock = *toro_circuitBlockList[i];
const TPO_PlaceRelativeList_t& placeRelativeList = toro_circuitBlock.GetPlaceRelativeList( );
if( !placeRelativeList.IsValid( ))
continue;
const char* pszFromBlockName = toro_circuitBlock.GetName( );
for( size_t j = 0; j < placeRelativeList.GetLength( ); ++j )
{
const TPO_PlaceRelative_c& placeRelative = *placeRelativeList[j];
const char* pszToBlockName = placeRelative.GetName( );
TC_SideMode_t side = placeRelative.GetSide( );
int dx = placeRelative.GetDx( );
int dy = placeRelative.GetDy( );
TGO_IntDims_t fromToLink( 0, 0 );
if( side != TC_SIDE_UNDEFINED )
{
switch( side )
{
case TC_SIDE_LEFT: fromToLink.Set( -1, 0 ); break;
case TC_SIDE_RIGHT: fromToLink.Set( 1, 0 ); break;
case TC_SIDE_LOWER: fromToLink.Set( 0, -1 ); break;
case TC_SIDE_UPPER: fromToLink.Set( 0, 1 ); break;
default: break;
}
}
if(( dx != INT_MAX ) && ( dy != INT_MAX ))
{
fromToLink.Set( fromToLink.dx + dx, fromToLink.dy + dy );
}
bool rotateMacroEnabled = ( this->placeOptions_.rotateEnable ||
placeRelative.GetRotateEnable( ) ?
true : false );
// Add a new relative placement side constraint
// (by default, this also includes appropriate validation)
ok = this->AddLinkConstraint_( pszFromBlockName, pszToBlockName,
fromToLink, rotateMacroEnabled );
if( !ok )
break;
}
if( !ok )
break;
}
return( ok );
}
//===========================================================================//
// Method : Set
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
void TCH_RelativePlaceHandler_c::Set(
t_grid_tile** vpr_gridArray,
int vpr_nx,
int vpr_ny,
t_block* vpr_blockArray,
int vpr_blockCount,
const t_type_descriptor* vpr_typeArray,
int vpr_typeCount,
int* vpr_freeLocationArray,
t_legal_pos** vpr_legalPosArray )
{
// Set local reference to VPR's grid array
this->vpr_data_.Init( vpr_gridArray, vpr_nx, vpr_ny,
vpr_blockArray, vpr_blockCount,
vpr_typeArray, vpr_typeCount,
vpr_freeLocationArray, vpr_legalPosArray );
}
//===========================================================================//
// Method : Reset
// Description : Resets the relative place handler in order to clear any
// existing placement information in VPR's grid array, the
// local relative macro list, and local relative block list.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::Reset(
void )
{
bool ok = true;
// Reset local VPR's data placement information
this->vpr_data_.Reset( );
// Reset placement and type information for relative macro and block lists
ok = this->ResetRelativeBlockList_( this->vpr_data_.vpr_blockArray,
this->vpr_data_.vpr_blockCount,
&this->relativeBlockList_ );
if( ok )
{
this->ResetRelativeMacroList_( this->relativeBlockList_,
&this->relativeMacroList_ );
}
return( ok );
}
//===========================================================================//
// Method : LoadCarryChains
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::LoadCarryChains(
const t_block* vpr_blockArray,
const t_pl_macro* vpr_placeMacroArray,
int vpr_placeMacroCount )
{
bool ok = true;
if( this->placeOptions_.carryChainEnable )
{
if( !this->relativeBlockList_.IsValid( ))
{
// Initialize the local relative block list based on VPR's macro list
for( int i = 0; i < vpr_placeMacroCount; ++i )
{
for( int j = 0; j < vpr_placeMacroArray[i].num_blocks; ++j )
{
int blockIndex = vpr_placeMacroArray[i].members[j].blk_index;
const char* pszBlockName = vpr_blockArray[blockIndex].name;
TCH_RelativeBlock_c relativeBlock( pszBlockName );
this->relativeBlockList_.Add( relativeBlock );
}
}
}
for( int i = 0; i < vpr_placeMacroCount; ++i )
{
if( vpr_placeMacroArray[i].num_blocks <= 1 )
continue;
int fromBlockIndex = vpr_placeMacroArray[i].members[0].blk_index;
const char* pszFromBlockName = vpr_blockArray[fromBlockIndex].name;
for( int j = 1; j < vpr_placeMacroArray[i].num_blocks; ++j )
{
int toBlockIndex = vpr_placeMacroArray[i].members[j].blk_index;
const char* pszToBlockName = vpr_blockArray[toBlockIndex].name;
int dx = vpr_placeMacroArray[i].members[j].x_offset;
int dy = vpr_placeMacroArray[i].members[j].y_offset;
int dz = vpr_placeMacroArray[i].members[j].z_offset;
TGO_IntDims_t fromToLink( dx, dy, dz );
// Add a new relative placement side constraint
// (by default, this also includes appropriate validation)
ok = this->AddLinkConstraint_( pszFromBlockName, pszToBlockName,
fromToLink );
if( !ok )
break;
}
if( !ok )
break;
}
}
return( ok );
}
//===========================================================================//
// Method : InitialPlace
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::InitialPlace(
t_grid_tile** vpr_gridArray,
int vpr_nx,
int vpr_ny,
t_block* vpr_blockArray,
int vpr_blockCount,
const t_type_descriptor* vpr_typeArray,
int vpr_typeCount,
int* vpr_freeLocationArray,
t_legal_pos** vpr_legalPosArray )
{
bool ok = true;
// Initialize local VPR grid array and block list structures
this->Set( vpr_gridArray, vpr_nx, vpr_ny,
vpr_blockArray, vpr_blockCount,
vpr_typeArray, vpr_typeCount,
vpr_freeLocationArray, vpr_legalPosArray );
// At least one relative placement constraint has been defined
bool placedAllMacros = true;
// Define how many times we can retry when searching for initial placement
size_t maxPlaceCt = this->placeOptions_.maxPlaceRetryCt;
size_t tryPlaceCt = 0;
while( tryPlaceCt < maxPlaceCt )
{
// Reset VPR grid array, and relative macro and block lists, then try place
ok = this->Reset( );
if( !ok )
break;
ok = this->InitialPlaceMacros_( &placedAllMacros );
if( !ok )
break;
if( placedAllMacros )
break;
++tryPlaceCt;
if( tryPlaceCt < maxPlaceCt )
{
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
printHandler.Info( "Retrying initial relative macro placement, attempt %d of %d...\n",
tryPlaceCt, maxPlaceCt );
}
}
if( ok && !placedAllMacros ) // Failed to comply - the Force is weak here
{
ok = this->Reset( );
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
ok = printHandler.Error( "Failed to find initial placement based on relative placement constraints.\n" );
}
return( ok );
}
//===========================================================================//
// Method : Place
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::Place(
int x1, int y1, int z1,
int x2, int y2, int z2,
t_pl_blocks_to_be_moved& vpr_blocksAffected )
{
TGO_Point_c fromPoint( x1, y1, z1 );
TGO_Point_c toPoint( x2, y2, z2 );
return( this->Place( fromPoint, toPoint, vpr_blocksAffected ));
}
//===========================================================================//
bool TCH_RelativePlaceHandler_c::Place(
const TGO_Point_c& fromPoint,
const TGO_Point_c& toPoint,
t_pl_blocks_to_be_moved& vpr_blocksAffected )
{
bool ok = true;
if( this->PlaceMacroIsRelativeCoord_( fromPoint ) ||
this->PlaceMacroIsRelativeCoord_( toPoint ))
{
// Reset relative macros based on latest VPR block placement coordinates
// (which may no longer match if the most recent macro move was rejected)
this->PlaceResetMacros_( );
// Search for valid relative move list based on "from" and "to" grid points
TCH_RelativeMoveList_t relativeMoveList;
ok = this->PlaceSwapMacros_( fromPoint, toPoint,
&relativeMoveList );
if( ok )
{
// Load VPR's "blocks_affected" array based on relative move list
for( size_t i = 0; i < relativeMoveList.GetLength( ); ++i )
{
const TCH_RelativeMove_c& relativeMove = *relativeMoveList[i];
this->PlaceSwapUpdate_( relativeMove,
vpr_blocksAffected );
}
}
}
return( ok );
}
//===========================================================================//
// Method : IsCandidate
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::IsCandidate(
int x1, int y1, int z1,
int x2, int y2, int z2 ) const
{
TGO_Point_c fromPoint( x1, y1, z1 );
TGO_Point_c toPoint( x2, y2, z2 );
return( this->IsCandidate( fromPoint, toPoint ));
}
//===========================================================================//
bool TCH_RelativePlaceHandler_c::IsCandidate(
const TGO_Point_c& fromPoint,
const TGO_Point_c& toPoint ) const
{
return( this->PlaceMacroIsRelativeCoord_( fromPoint ) ||
this->PlaceMacroIsRelativeCoord_( toPoint ) ?
true : false );
}
//===========================================================================//
// Method : IsValid
// Description : Returns TRUE if at least one relative macro exists
// (ie. at least one placement constraint has been defined).
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::IsValid(
void ) const
{
return( this->relativeMacroList_.IsValid( ) ||
this->placeOptions_.carryChainEnable ?
true : false );
}
//===========================================================================//
// Method : AddLinkConstraint_
// Description : Adds a new relative placement constraint based on the
// given "from"|"to" names and relative link offsets.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
// 06/25/13 jeffr : Migrated original side-based "AddSideConstraint_() method
//===========================================================================//
bool TCH_RelativePlaceHandler_c::AddLinkConstraint_(
const char* pszFromBlockName,
const char* pszToBlockName,
const TGO_IntDims_t& fromToLink,
bool rotateMacroEnabled,
size_t relativeMacroIndex )
{
bool ok = true;
// Look up "from" and "to" relative macro indices based on given block names
TCH_RelativeBlock_c* pfromBlock = this->relativeBlockList_.Find( pszFromBlockName );
TCH_RelativeBlock_c* ptoBlock = this->relativeBlockList_.Find( pszToBlockName );
if( pfromBlock && ptoBlock )
{
ok = this->AddLinkConstraint_( pfromBlock, ptoBlock, fromToLink,
rotateMacroEnabled, relativeMacroIndex );
}
else
{
if( !pfromBlock )
{
ok = this->ShowMissingBlockNameError_( pszFromBlockName );
}
if( !ptoBlock )
{
ok = this->ShowMissingBlockNameError_( pszToBlockName );
}
}
return( ok );
}
//===========================================================================//
bool TCH_RelativePlaceHandler_c::AddLinkConstraint_(
TCH_RelativeBlock_c* pfromBlock,
TCH_RelativeBlock_c* ptoBlock,
const TGO_IntDims_t& fromToLink,
bool rotateMacroEnabled,
size_t relativeMacroIndex )
{
bool ok = true;
TGO_IntDims_t toFromLink;
this->DecideAntiLink_( fromToLink, &toFromLink );
if( !pfromBlock->HasRelativeMacroIndex( ) &&
!ptoBlock->HasRelativeMacroIndex( ))
{
// No relative macros are currently asso. with either "from" or "to" block
// Add new relative macro, along with asso. "from" and "to" relative nodes
this->NewLinkConstraint_( pfromBlock, ptoBlock, fromToLink,
rotateMacroEnabled, relativeMacroIndex );
}
else if( pfromBlock->HasRelativeMacroIndex( ) &&
!ptoBlock->HasRelativeMacroIndex( ))
{
// Update existing relative macro based on "from" block, add a "to" block
string srFromBlockName, srToBlockName;
ok = this->ExistingLinkConstraint_( *pfromBlock, ptoBlock, fromToLink,
rotateMacroEnabled,
&srFromBlockName, &srToBlockName );
if( !ok )
{
// Link is already in use for the existing macro "from" node, report error
ok = this->ShowInvalidConstraintError_( *pfromBlock, *ptoBlock, fromToLink,
srFromBlockName, srToBlockName );
}
}
else if( !pfromBlock->HasRelativeMacroIndex( ) &&
ptoBlock->HasRelativeMacroIndex( ))
{
// Update existing relative macro based on "to" block, add a "from" block
string srToBlockName, srFromBlockName;
ok = this->ExistingLinkConstraint_( *ptoBlock, pfromBlock, toFromLink,
rotateMacroEnabled,
&srToBlockName, &srFromBlockName );
if( !ok )
{
// Link is already in use for the existing macro "to" node, report error
ok = this->ShowInvalidConstraintError_( *ptoBlock, *pfromBlock, toFromLink,
srToBlockName, srFromBlockName );
}
}
else if( pfromBlock->HasRelativeMacroIndex( ) &&
ptoBlock->HasRelativeMacroIndex( ))
{
if( pfromBlock->GetRelativeMacroIndex( ) == ptoBlock->GetRelativeMacroIndex( ))
{
// Same macro index => "from" and "to" blocks are from same relative macro
// Verify link constraint is "existing" wrt. "from" and "to" relative nodes
string srFromBlockName, srToBlockName;
if( this->HasExistingLinkConstraint_( *pfromBlock, *ptoBlock, fromToLink,
&srFromBlockName, &srToBlockName ))
{
// Move along, nothing to see here (given relative constraint is redundant)
}
else
{
ok = this->ShowInvalidConstraintError_( *pfromBlock, *ptoBlock, fromToLink,
srFromBlockName, srToBlockName );
}
}
else
{
// Diff macro index => "from" and "to" blocks are from different relative macros
// Verify link constraint is "available" wrt. "from" and "to" relative nodes
bool fromAvailable = true;
bool toAvailable = true;
string srFromBlockName, srToBlockName;
if( this->IsAvailableLinkConstraint_( *pfromBlock, *ptoBlock, fromToLink,
&fromAvailable, &toAvailable,
&srFromBlockName, &srToBlockName ))
{
// Merge the "from" and "to" relative macros based on common link constraint
ok = this->MergeLinkConstraints_( pfromBlock, ptoBlock, fromToLink,
rotateMacroEnabled );
}
else
{
if( !fromAvailable )
{
ok = this->ShowInvalidConstraintError_( *ptoBlock, *pfromBlock, toFromLink,
srToBlockName, srFromBlockName );
}
if( !toAvailable )
{
ok = this->ShowInvalidConstraintError_( *pfromBlock, *ptoBlock, fromToLink,
srFromBlockName, srToBlockName );
}
}
}
}
return( ok );
}
//===========================================================================//
// Method : NewLinkConstraint_
// Description : Add a new relative macro, along with the associated
// "from" and "to" relative nodes, based on the given link
// constraint.
//
// Note: This method assumes no relative macros are already
// associated with either the "from" or "to" relative
// blocks.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
// 06/25/13 jeffr : Migrated original side-based "NewSideConstraint_() method
// 07/08/13 jeffr : Extended to support relative placement enable per macro
//===========================================================================//
void TCH_RelativePlaceHandler_c::NewLinkConstraint_(
TCH_RelativeBlock_c* pfromBlock,
TCH_RelativeBlock_c* ptoBlock,
const TGO_IntDims_t& fromToLink,
bool rotateMacroEnabled,
size_t relativeMacroIndex )
{
// First, add new relative macro (or use existing, per optional parameter)
if( relativeMacroIndex == TCH_RELATIVE_MACRO_UNDEFINED )
{
relativeMacroIndex = this->relativeMacroList_.GetLength( );
TCH_RelativeMacro_c relativeMacro;
this->relativeMacroList_.Add( relativeMacro );
}
TCH_RelativeMacro_c* prelativeMacro = this->relativeMacroList_[relativeMacroIndex];
// Next, add new relative nodes based on given block names and relative link
const char* pszFromBlockName = pfromBlock->GetName( );
const char* pszToBlockName = ptoBlock->GetName( );
size_t fromNodeIndex = TCH_RELATIVE_NODE_UNDEFINED;
size_t toNodeIndex = TCH_RELATIVE_NODE_UNDEFINED;
prelativeMacro->Add( pszFromBlockName, pszToBlockName, fromToLink,
&fromNodeIndex, &toNodeIndex );
// And, update rotate enabled state, as needed
if( rotateMacroEnabled )
{
prelativeMacro->SetRotateEnabled( true );
}
// Finally, update relative block macro and node indices
pfromBlock->SetRelativeMacroIndex( relativeMacroIndex );
pfromBlock->SetRelativeNodeIndex( fromNodeIndex );
ptoBlock->SetRelativeMacroIndex( relativeMacroIndex );
ptoBlock->SetRelativeNodeIndex( toNodeIndex );
}
//===========================================================================//
void TCH_RelativePlaceHandler_c::NewLinkConstraint_(
const TCH_RelativeBlock_c& fromBlock,
const TCH_RelativeBlock_c& toBlock,
const TGO_IntDims_t& fromToLink )
{
size_t relativeMacroIndex = fromBlock.GetRelativeMacroIndex( );
size_t fromNodeIndex = fromBlock.GetRelativeNodeIndex( );
size_t toNodeIndex = toBlock.GetRelativeNodeIndex( );
// First, find existing relative macro
TCH_RelativeMacro_c* prelativeMacro = this->relativeMacroList_[relativeMacroIndex];
// Next, add new relative nodes based on given block names and relative link
prelativeMacro->Add( fromNodeIndex, toNodeIndex, fromToLink );
}
//===========================================================================//
// Method : MergeLinkConstraints_
// Description : Merge the "from" and "to" relative macros based on a
// common link constraint.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
// 06/25/13 jeffr : Migrated original "MergeSideConstraints_() method
// 07/08/13 jeffr : Extended to support relative placement enable per macro
//===========================================================================//
bool TCH_RelativePlaceHandler_c::MergeLinkConstraints_(
TCH_RelativeBlock_c* pfromBlock,
TCH_RelativeBlock_c* ptoBlock,
const TGO_IntDims_t& fromToLink,
bool rotateMacroEnabled )
{
bool ok = true;
size_t fromMacroIndex = pfromBlock->GetRelativeMacroIndex( );
size_t fromNodeIndex = pfromBlock->GetRelativeNodeIndex( );
const TCH_RelativeMacro_c& fromMacro = *this->relativeMacroList_[fromMacroIndex];
const TCH_RelativeNode_c& fromNode = *fromMacro.Find( fromNodeIndex );
TGO_Point_c fromPoint = fromNode.GetRelativePoint( );
size_t toMacroIndex = ptoBlock->GetRelativeMacroIndex( );
size_t toNodeIndex = ptoBlock->GetRelativeNodeIndex( );
TCH_RelativeMacro_c toMacro = *this->relativeMacroList_[toMacroIndex];
const TCH_RelativeNode_c& toNode = *toMacro.Find( toNodeIndex );
TGO_Point_c toPoint = toNode.GetRelativePoint( );
// Start by clearing all block indices asso. with existing "to" relative macro
for( size_t i = 0; i < toMacro.GetLength( ); ++i )
{
const TCH_RelativeNode_c& toNode_ = *toMacro[i];
const char* pszToBlockName = toNode_.GetBlockName( );
TCH_RelativeBlock_c* ptoBlock_ = this->relativeBlockList_.Find( pszToBlockName );
ptoBlock_->Reset( );
}
// Then, iterate the "to" relative macro...
// Recursively add link constraints to existing "from" relative macro
toMacro.ForceRelativeLinks( fromPoint, toPoint, fromToLink );
for( size_t i = 0; i < toMacro.GetLength( ); ++i )
{
const TCH_RelativeNode_c& toNode_ = *toMacro[i];
const TGO_Point_c& toPoint_ = toNode_.GetRelativePoint( );
const char* pszToBlockName = toNode_.GetBlockName( );
TCH_RelativeBlock_c* ptoBlock_ = this->relativeBlockList_.Find( pszToBlockName );
TGO_IntDims_t fromToLink_( toPoint_.x - fromPoint.x,
toPoint_.y - fromPoint.y );
this->AddLinkConstraint_( pfromBlock, ptoBlock_, fromToLink_,
rotateMacroEnabled, fromMacroIndex );
}
// All done with the original "to" relative macro...
// but need to leave an empty macro in the list to avoid having to
// re-index all existing relative block index references
TCH_RelativeMacro_c* ptoMacro = this->relativeMacroList_[toMacroIndex];
ptoMacro->Clear( );
return( ok );
}
//===========================================================================//
// Method : ExistingLinkConstraint_
// Description : Update an existing relative macro and "from" relative
// node with a new "to" relative node, based on the given
// relative link constraint.
//
// Note: This method assumes a relative macro is currently
// associated with the "from" relative block.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
// 06/25/13 jeffr : Migrated original "ExistingSideConstraint_() method
// 07/08/13 jeffr : Extended to support relative placement enable per macro
//===========================================================================//
bool TCH_RelativePlaceHandler_c::ExistingLinkConstraint_(
const TCH_RelativeBlock_c& fromBlock,
TCH_RelativeBlock_c* ptoBlock,
const TGO_IntDims_t& fromToLink,
bool rotateMacroEnabled,
string* psrFromBlockName,
string* psrToBlockName )
{
bool ok = true;
// Find existing relative macro and node based on "from" block's indices
size_t relativeMacroIndex = fromBlock.GetRelativeMacroIndex( );
size_t fromNodeIndex = fromBlock.GetRelativeNodeIndex( );
TCH_RelativeMacro_c* prelativeMacro = this->relativeMacroList_[relativeMacroIndex];
if( !prelativeMacro->HasRelativeLink( fromNodeIndex, fromToLink ))
{
// Relative link is available on existing macro "from" node, now add a "to" node
// Add new "to" relative node
const char* pszToBlockName = ptoBlock->GetName( );
size_t toNodeIndex = TCH_RELATIVE_NODE_UNDEFINED;
prelativeMacro->Add( fromNodeIndex, pszToBlockName, fromToLink,
&toNodeIndex );
// And, update rotate enabled state, as needed
if( rotateMacroEnabled )
{
prelativeMacro->SetRotateEnabled( true );
}
// And, update relative block macro and node indices
ptoBlock->SetRelativeMacroIndex( relativeMacroIndex );
ptoBlock->SetRelativeNodeIndex( toNodeIndex );
}
else
{
// Relative link is already in use for existing macro "from" node, return error
ok = false;
}
if( psrFromBlockName )
{
*psrFromBlockName = fromBlock.GetBlockName( );
}
if( psrToBlockName )
{
const TCH_RelativeNode_c& fromNode = *prelativeMacro->Find( fromNodeIndex );
const TCH_RelativeNode_c* ptoNode = prelativeMacro->Find( fromNode, fromToLink );
*psrToBlockName = ( ptoNode ? ptoNode->GetBlockName( ) : "" );
}
return( ok );
}
//===========================================================================//
// Method : HasExistingLinkConstraint_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
// 06/25/13 jeffr : Migrated original "HasExistingSideConstraint_() method
//===========================================================================//
bool TCH_RelativePlaceHandler_c::HasExistingLinkConstraint_(
const TCH_RelativeBlock_c& fromBlock,
const TCH_RelativeBlock_c& toBlock,
const TGO_IntDims_t& fromToLink,
string* psrFromBlockName,
string* psrToBlockName ) const
{
bool isExisting = false;
TGO_IntDims_t toFromLink;
this->DecideAntiLink_( fromToLink, &toFromLink );
size_t fromMacroIndex = fromBlock.GetRelativeMacroIndex( );
size_t fromNodeIndex = fromBlock.GetRelativeNodeIndex( );
size_t toMacroIndex = toBlock.GetRelativeMacroIndex( );
size_t toNodeIndex = toBlock.GetRelativeNodeIndex( );
if(( fromMacroIndex != TCH_RELATIVE_MACRO_UNDEFINED ) &&
( toMacroIndex != TCH_RELATIVE_MACRO_UNDEFINED ))
{
if(( fromMacroIndex == toMacroIndex ) &&
( fromNodeIndex != toNodeIndex ))
{
const TCH_RelativeMacro_c& relativeMacro = *this->relativeMacroList_[fromMacroIndex];
const TCH_RelativeNode_c& fromNode = *relativeMacro[fromNodeIndex];
const TCH_RelativeNode_c& toNode = *relativeMacro[toNodeIndex];
if(( fromNode.HasRelativeLink( toNodeIndex )) &&
( toNode.HasRelativeLink( fromNodeIndex )))
{
const TCH_RelativeNode_c* pfromNode = relativeMacro.Find( toNode, fromToLink );
const TCH_RelativeNode_c* ptoNode = relativeMacro.Find( fromNode, toFromLink );
if( pfromNode && ptoNode )
{
if((( *pfromNode == fromNode ) && ( *ptoNode == toNode )) ||
(( *pfromNode == toNode ) && ( *ptoNode == fromNode )))
{
isExisting = true;
}
}
}
if( psrFromBlockName )
{
const TCH_RelativeNode_c* pfromNode = 0;
pfromNode = ( relativeMacro.HasRelativeLink( toNode, fromToLink ) ?
relativeMacro.Find( toNode, fromToLink ) :
relativeMacro[fromNodeIndex] );
*psrFromBlockName = ( pfromNode ? pfromNode->GetBlockName( ) : "" );
}
if( psrToBlockName )
{
const TCH_RelativeNode_c* ptoNode = 0;
ptoNode = ( relativeMacro.HasRelativeLink( fromNode, toFromLink ) ?
relativeMacro.Find( fromNode, toFromLink ) :
relativeMacro[toNodeIndex] );
*psrToBlockName = ( ptoNode ? ptoNode->GetBlockName( ) : "" );
}
}
}
return( isExisting );
}
//===========================================================================//
// Method : IsAvailableLinkConstraint_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
// 06/25/13 jeffr : Migrated original "IsAvailableSideConstraint_() method
// 07/08/13 jeffr : Extended to support relative placement enable per macro
//===========================================================================//
bool TCH_RelativePlaceHandler_c::IsAvailableLinkConstraint_(
const TCH_RelativeBlock_c& fromBlock,
const TCH_RelativeBlock_c& toBlock,
const TGO_IntDims_t& fromToLink,
bool* pfromAvailable,
bool* ptoAvailable,
string* psrFromBlockName,
string* psrToBlockName ) const
{
bool isAvailable = false;
size_t fromMacroIndex = fromBlock.GetRelativeMacroIndex( );
size_t fromNodeIndex = fromBlock.GetRelativeNodeIndex( );
size_t toMacroIndex = toBlock.GetRelativeMacroIndex( );
size_t toNodeIndex = toBlock.GetRelativeNodeIndex( );
if(( fromMacroIndex != TCH_RELATIVE_MACRO_UNDEFINED ) &&
( toMacroIndex != TCH_RELATIVE_MACRO_UNDEFINED ))
{
if( fromMacroIndex != toMacroIndex )
{
isAvailable = true;
const TCH_RelativeMacro_c& fromMacro = *this->relativeMacroList_[fromMacroIndex];
const TCH_RelativeNode_c& fromNode = *fromMacro[fromNodeIndex];
TCH_RelativeMacro_c toMacro = *this->relativeMacroList_[toMacroIndex];
const TCH_RelativeNode_c& toNode = *toMacro[toNodeIndex];
toMacro.ForceRelativeLinks( fromNode, toNode, fromToLink );
if( toMacro.IsRotateEnabled( ))
{
TCH_RelativeMacro_c* pfromMacro = this->relativeMacroList_[fromMacroIndex];
pfromMacro->SetRotateEnabled( true );
}
const TCH_RelativeNodeList_t& toNodeList = toMacro.GetRelativeNodeList( );
for( size_t i = 0; i < toNodeList.GetLength( ); ++i )
{
const TCH_RelativeNode_c& toNode_ = *toNodeList[i];
if( fromMacro.Find( toNode_ ))
{
toNodeIndex = i;
isAvailable = false;
break;
}
}
if( pfromAvailable )
{
*pfromAvailable = true;
}
if( ptoAvailable )
{
*ptoAvailable = isAvailable;
}
if( psrFromBlockName )
{
const TCH_RelativeNode_c* pfromNode = fromMacro.Find( fromNodeIndex );
*psrFromBlockName = ( pfromNode ? pfromNode->GetBlockName( ) : "" );
}
if( psrToBlockName )
{
const TCH_RelativeNode_c* ptoNode = toMacro.Find( toNodeIndex );
*psrToBlockName = ( ptoNode ? ptoNode->GetBlockName( ) : "" );
}
}
}
return( isAvailable );
}
//===========================================================================//
// Method : ResetRelativeMacroList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
void TCH_RelativePlaceHandler_c::ResetRelativeMacroList_(
const TCH_RelativeBlockList_t& relativeBlockList,
TCH_RelativeMacroList_t* prelativeMacroList )
{
// Reset all macro node 'vpr_type' fields based on relative block list
for( size_t i = 0; i < prelativeMacroList->GetLength( ); ++i )
{
TCH_RelativeMacro_c* prelativeMacro = (*prelativeMacroList)[i];
for( size_t j = 0; j < prelativeMacro->GetLength( ); ++j )
{
TCH_RelativeNode_c* prelativeNode = (*prelativeMacro)[j];
TGO_Point_c vpr_gridPoint;
prelativeNode->SetVPR_GridPoint( vpr_gridPoint );
const char* pszBlockName = prelativeNode->GetBlockName( );
const TCH_RelativeBlock_c* prelativeBlock = relativeBlockList.Find( pszBlockName );
if( !prelativeBlock )
continue;
const t_type_descriptor* vpr_type = prelativeBlock->GetVPR_Type( );
prelativeNode->SetVPR_Type( vpr_type );
}
}
}
//===========================================================================//
// Method : ResetRelativeBlockList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::ResetRelativeBlockList_(
t_block* vpr_blockArray,
int vpr_blockCount,
TCH_RelativeBlockList_t* prelativeBlockList )
{
bool ok = true;
// Initialize relative block list based on given VPR block array types
for( int blockIndex = 0; blockIndex < vpr_blockCount; ++blockIndex )
{
const char* pszBlockName = vpr_blockArray[blockIndex].name;
TCH_RelativeBlock_c* prelativeBlock = prelativeBlockList->Find( pszBlockName );
if( !prelativeBlock )
continue;
int vpr_index = blockIndex;
prelativeBlock->SetVPR_Index( vpr_index );
const t_type_descriptor* vpr_type = vpr_blockArray[blockIndex].type;
prelativeBlock->SetVPR_Type( vpr_type );
}
// Validate relative block list based on local VPR block name list
TCH_RelativeBlockList_t vpr_blockList( vpr_blockCount );
for( int blockIndex = 0; blockIndex < vpr_blockCount; ++blockIndex )
{
const char* pszBlockName = vpr_blockArray[blockIndex].name;
vpr_blockList.Add( pszBlockName );
}
for( size_t i = 0; i < prelativeBlockList->GetLength( ); ++i )
{
const TCH_RelativeBlock_c& relativeBlock = *(*prelativeBlockList)[i];
const char* pszBlockName = relativeBlock.GetBlockName( );
if( !vpr_blockList.IsMember( pszBlockName ))
{
ok = this->ShowMissingBlockNameError_( pszBlockName );
if( !ok )
break;
}
}
return( ok );
}
//===========================================================================//
// Method : InitialPlaceMacros_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::InitialPlaceMacros_(
bool* pplacedAllMacros )
{
bool ok = true;
bool foundAllPlacements = true;
for( size_t i = 0; i < this->relativeMacroList_.GetLength( ); ++i )
{
TCH_RelativeMacro_c* prelativeMacro = this->relativeMacroList_[i];
// Reset (ie. clear) and existing macro placement coords
this->InitialPlaceMacroResetCoords_( );
// Define how many times we can retry when searching for an initial placement
size_t maxMacroCt = this->placeOptions_.maxMacroRetryCt * prelativeMacro->GetLength( );
size_t tryMacroCt = 0;
while( tryMacroCt < maxMacroCt )
{
bool validPlacement = false;
bool triedPlacement = false;
bool foundPlacement = false;
ok = this->InitialPlaceMacroNodes_( prelativeMacro,
&validPlacement, &triedPlacement, &foundPlacement );
if( !ok )
break;
foundAllPlacements = validPlacement;
if( !validPlacement )
break;
if( !triedPlacement )
continue;
if( foundPlacement )
break;
++tryMacroCt;
if( tryMacroCt < maxMacroCt )
{
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
printHandler.Info( "Retrying relative macro placement, attempt %d of %d...\n",
tryMacroCt, maxMacroCt );
}
}
if( tryMacroCt > maxMacroCt )
{
foundAllPlacements = false;
}
if( !foundAllPlacements )
break;
}
if( !foundAllPlacements ) // Failed to place at least one of the relative macros
{
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
ok = printHandler.Warning( "Failed initial relative placement based on relative placement constraints.\n" );
}
if( *pplacedAllMacros )
{
*pplacedAllMacros = foundAllPlacements;
}
return( ok );
}
//===========================================================================//
// Method : InitialPlaceMacroNodes_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
// 07/08/13 jeffr : Extended to support relative placement enable per macro
//===========================================================================//
bool TCH_RelativePlaceHandler_c::InitialPlaceMacroNodes_(
TCH_RelativeMacro_c* prelativeMacro,
bool* pvalidPlacement,
bool* ptriedPlacement,
bool* pfoundPlacement )
{
bool ok = true;
*pvalidPlacement = false;
*ptriedPlacement = false;
*pfoundPlacement = false;
// Select a random relative node index based on relative macro length
size_t relativeNodeIndex = this->FindRandomRelativeNodeIndex_( *prelativeMacro );
// Select a random (and available) point from within VPR's grid array
TGO_Point_c origin = this->FindRandomOriginPoint_( *prelativeMacro,
relativeNodeIndex );
// Select a random rotate mode (if enabled)
TGO_RotateMode_t rotate = this->FindRandomRotateMode_( *prelativeMacro );
// Test if we already tried this combination of node, origin, and rotate
if( origin.IsValid( ) &&
this->InitialPlaceMacroIsLegal_( relativeNodeIndex, origin, rotate ))
{
*pvalidPlacement = true;
*ptriedPlacement = true;
if( this->InitialPlaceMacroIsOpen_( *prelativeMacro,
relativeNodeIndex, origin, rotate ))
{
// Accept current relative placement node, origin, and rotate
prelativeMacro->Set( relativeNodeIndex, origin, rotate );
// And, update VPR's grid and block arrays based on relative macro
this->InitialPlaceMacroUpdate_( *prelativeMacro,
this->relativeBlockList_ );
*pfoundPlacement = true;
}
else
{
ok = this->ShowIllegalRelativeMacroWarning_( *prelativeMacro,
relativeNodeIndex,
origin, rotate );
}
}
else if( origin.IsValid( ))
{
*pvalidPlacement = true;
}
return( ok );
}
//===========================================================================//
// Method : InitialPlaceMacroUpdate_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
void TCH_RelativePlaceHandler_c::InitialPlaceMacroUpdate_(
const TCH_RelativeMacro_c& relativeMacro,
const TCH_RelativeBlockList_t& relativeBlockList )
{
for( size_t i = 0; i < relativeMacro.GetLength( ); ++i )
{
const TCH_RelativeNode_c& relativeNode = *relativeMacro[i];
const TGO_Point_c& vpr_gridPoint = relativeNode.GetVPR_GridPoint( );
const char* pszBlockName = relativeNode.GetBlockName( );
const TCH_RelativeBlock_c& relativeBlock = *relativeBlockList.Find( pszBlockName );
int vpr_blockIndex = relativeBlock.GetVPR_Index( );
this->vpr_data_.Set( vpr_gridPoint, vpr_blockIndex );
}
}
//===========================================================================//
// Method : InitialPlaceMacroResetCoords_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
void TCH_RelativePlaceHandler_c::InitialPlaceMacroResetCoords_(
void )
{
TCH_RotateMaskHash_t* protateMaskHash = &this->initialPlaceMacroCoords_;
protateMaskHash->Clear( );
}
//===========================================================================//
// Method : InitialPlaceMacroIsLegal_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::InitialPlaceMacroIsLegal_(
size_t relativeNodeIndex,
const TGO_Point_c& origin,
TGO_RotateMode_t rotate ) const
{
bool isLegal = true;
TCH_RotateMaskHash_t* protateMaskHash = const_cast< TCH_RotateMaskHash_t* >( &this->initialPlaceMacroCoords_ );
TCH_RotateMaskKey_c rotateMaskKey( origin, relativeNodeIndex );
TCH_RotateMaskValue_c* protateMaskValue = 0;
if( protateMaskHash->Find( rotateMaskKey, &protateMaskValue ) &&
!protateMaskValue->GetBit( rotate ))
{
isLegal = false;
}
else
{
isLegal = true;
if( !protateMaskHash->IsMember( rotateMaskKey ))
{
TCH_RotateMaskValue_c rotateMaskValue( true );
protateMaskHash->Add( rotateMaskKey, rotateMaskValue );
protateMaskHash->Find( rotateMaskKey, &protateMaskValue );
}
protateMaskValue->ClearBit( rotate );
}
return( isLegal );
}
//===========================================================================//
// Method : InitialPlaceMacroIsOpen_
// Description : Returns TRUE if the given relative macro placement origin
// point and associated transform is open, as determined by
// the current state of VPR's grid array.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::InitialPlaceMacroIsOpen_(
const TCH_RelativeMacro_c& relativeMacro,
size_t relativeNodeIndex,
const TGO_Point_c& origin,
TGO_RotateMode_t rotate ) const
{
bool isOpen = false;
TCH_RelativeMacro_c relativeMacro_( relativeMacro );
relativeMacro_.Set( relativeNodeIndex, origin, rotate );
for( size_t i = 0; i < relativeMacro_.GetLength( ); ++i )
{
const TCH_RelativeNode_c& relativeNode = *relativeMacro_[i];
// Query VPR's grid array to test (1) open && (2) matching type ptr
const TGO_Point_c& gridPoint = relativeNode.GetVPR_GridPoint( );
const t_type_descriptor* vpr_type = relativeNode.GetVPR_Type( );
if( this->vpr_data_.IsOpenGridPoint( gridPoint, vpr_type ))
{
isOpen = true;
continue;
}
else
{
isOpen = false;
break;
}
}
return( isOpen );
}
//===========================================================================//
bool TCH_RelativePlaceHandler_c::InitialPlaceMacroIsOpen_(
size_t relativeMacroIndex,
size_t relativeNodeIndex,
const TGO_Point_c& origin,
TGO_RotateMode_t rotate ) const
{
bool isOpen = false;
const TCH_RelativeMacro_c* prelativeMacro = this->relativeMacroList_[relativeMacroIndex];
if( prelativeMacro )
{
isOpen = this->InitialPlaceMacroIsOpen_( *prelativeMacro,
relativeNodeIndex, origin, rotate );
}
return( isOpen );
}
//===========================================================================//
// Method : PlaceResetMacros_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
void TCH_RelativePlaceHandler_c::PlaceResetMacros_(
void )
{
for( size_t i = 0; i < this->relativeMacroList_.GetLength( ); ++i )
{
TCH_RelativeMacro_c* prelativeMacro = this->relativeMacroList_[i];
for( size_t j = 0; j < prelativeMacro->GetLength( ); ++j )
{
TCH_RelativeNode_c* prelativeNode = (*prelativeMacro)[j];
const char* pszBlockName = prelativeNode->GetBlockName( );
const TCH_RelativeBlock_c& relativeBlock = *this->relativeBlockList_.Find( pszBlockName );
const t_block* vpr_blockArray = this->vpr_data_.vpr_blockArray;
int vpr_index = relativeBlock.GetVPR_Index( );
TGO_Point_c vpr_gridPoint( vpr_blockArray[vpr_index].x,
vpr_blockArray[vpr_index].y,
vpr_blockArray[vpr_index].z );
prelativeNode->SetVPR_GridPoint( vpr_gridPoint );
}
}
}
//===========================================================================//
// Method : PlaceSwapMacros_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
// 07/08/13 jeffr : Extended to support relative placement enable per macro
//===========================================================================//
bool TCH_RelativePlaceHandler_c::PlaceSwapMacros_(
const TGO_Point_c& fromPoint,
const TGO_Point_c& toPoint,
TCH_RelativeMoveList_t* prelativeMoveList )
{
TCH_RelativeMoveList_t fromToMoveList;
TCH_RelativeMoveList_t toFromMoveList;
bool foundPlaceSwap = false;
// Iterate attempt to swap "from" => "to" based available (optional) rotation
this->PlaceMacroResetRotate_( TCH_PLACE_MACRO_ROTATE_TO, fromPoint );
while( this->PlaceMacroIsValidRotate_( TCH_PLACE_MACRO_ROTATE_TO ))
{
// Select a random rotate mode (if enabled)
TGO_RotateMode_t toRotate = this->FindRandomRotateMode_( fromPoint );
if( this->PlaceMacroIsLegalRotate_( TCH_PLACE_MACRO_ROTATE_TO, toRotate ))
{
fromToMoveList.Clear( );
// Query if "to" is available based on "from" origin and "to" transform
// (and return list of "from->to" moves corresponding to availability)
if( this->PlaceMacroIsAvailableCoord_( fromPoint, toPoint, toRotate,
&fromToMoveList ))
{
// Iterate attempt to swap "to" => "from" based available rotation
this->PlaceMacroResetRotate_( TCH_PLACE_MACRO_ROTATE_FROM, toPoint );
while( this->PlaceMacroIsValidRotate_( TCH_PLACE_MACRO_ROTATE_FROM ))
{
// Select a random rotate mode (if enabled)
TGO_RotateMode_t fromRotate = this->FindRandomRotateMode_( toPoint );
if( this->PlaceMacroIsLegalRotate_( TCH_PLACE_MACRO_ROTATE_FROM, fromRotate ))
{
toFromMoveList.Clear( );
// Query if "from" is available based on "to" origin and inverse
// (and return list of "to->from" moves corresponding to availability)
if( this->PlaceMacroIsAvailableCoord_( toPoint, fromPoint, fromRotate,
&toFromMoveList ) &&
this->PlaceMacroIsLegalMoveList_( fromToMoveList,
toFromMoveList ))
{
// Found swappable "from" and "to" move lists
foundPlaceSwap = true;
break;
}
}
}
if( foundPlaceSwap )
break;
}
}
}
if( foundPlaceSwap )
{
prelativeMoveList->Add( fromToMoveList );
prelativeMoveList->Add( toFromMoveList );
this->PlaceMacroUpdateMoveList_( prelativeMoveList );
}
return( foundPlaceSwap );
}
//===========================================================================//
// Method : PlaceSwapUpdate_
// Reference : Set VPR's setup_blocks_affected function
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
void TCH_RelativePlaceHandler_c::PlaceSwapUpdate_(
const TCH_RelativeMove_c& relativeMove,
t_pl_blocks_to_be_moved& vpr_blocksAffected ) const
{
const TGO_Point_c& fromPoint = relativeMove.GetFromPoint( );
const TGO_Point_c& toPoint = relativeMove.GetToPoint( );
// Update relative node grid points per from/to points, as needed
TCH_RelativeNode_c* pfromNode = this->FindRelativeNode_( fromPoint );
if( pfromNode )
{
pfromNode->SetVPR_GridPoint( toPoint );
}
TCH_RelativeNode_c* ptoNode = this->FindRelativeNode_( toPoint );
if( ptoNode )
{
ptoNode->SetVPR_GridPoint( fromPoint );
}
// Find VPR's global "block" array indices per from/to points
int fromBlockIndex = this->vpr_data_.FindGridPointBlockIndex( fromPoint );
bool fromEmpty = relativeMove.GetFromEmpty( );
bool toEmpty = relativeMove.GetToEmpty( );
// Update VPR's global "block" array using locally cached reference
t_block* vpr_blockArray = this->vpr_data_.vpr_blockArray;
vpr_blockArray[fromBlockIndex].x = toPoint.x;
vpr_blockArray[fromBlockIndex].y = toPoint.y;
vpr_blockArray[fromBlockIndex].z = toPoint.z;
// Update VPR's global "blocks_affected" array using locally passed reference
int i = vpr_blocksAffected.num_moved_blocks;
vpr_blocksAffected.moved_blocks[i].block_num = fromBlockIndex;
vpr_blocksAffected.moved_blocks[i].xold = fromPoint.x;
vpr_blocksAffected.moved_blocks[i].yold = fromPoint.y;
vpr_blocksAffected.moved_blocks[i].zold = fromPoint.z;
vpr_blocksAffected.moved_blocks[i].xnew = toPoint.x;
vpr_blocksAffected.moved_blocks[i].ynew = toPoint.y;
vpr_blocksAffected.moved_blocks[i].znew = toPoint.z;
vpr_blocksAffected.moved_blocks[i].swapped_to_was_empty = toEmpty;
vpr_blocksAffected.moved_blocks[i].swapped_from_is_empty = fromEmpty;
vpr_blocksAffected.num_moved_blocks ++;
}
//===========================================================================//
// Method : PlaceMacroIsRelativeCoord_
// Description : Returns TRUE if the given VPR grid array coordinate is
// associated with a relative macro.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::PlaceMacroIsRelativeCoord_(
const TGO_Point_c& point ) const
{
bool isMacro = false;
// Find relative block based on VPR's grid array point
const TCH_RelativeBlock_c* prelativeBlock = this->FindRelativeBlock_( point );
// Decide if relative block has a relative macro associated with it
if( prelativeBlock &&
prelativeBlock->HasRelativeMacroIndex( ) &&
prelativeBlock->HasRelativeNodeIndex( ))
{
isMacro = true;
}
return( isMacro );
}
//===========================================================================//
// Method : PlaceMacroIsAvailableCoord_
// Description : Returns TRUE if the given relative macro placement can be
// transformed to a legal placement based on the current
// state of VPR's grid array. Optionally, returns a list of
// moves corresponding to the availability testing.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::PlaceMacroIsAvailableCoord_(
const TGO_Point_c& fromOrigin,
const TGO_Point_c& toOrigin,
TGO_RotateMode_t toRotate,
TCH_RelativeMoveList_t* prelativeMoveList ) const
{
bool isAvailable = true;
size_t fromMacroIndex = this->FindRelativeMacroIndex_( fromOrigin );
size_t toMacroIndex = this->FindRelativeMacroIndex_( toOrigin );
TCH_RelativeMacro_c fromMacro_;
const TCH_RelativeMacro_c* pfromMacro = this->FindRelativeMacro_( fromOrigin );
if( !pfromMacro )
{
fromMacro_.Add( );
fromMacro_.Set( 0, fromOrigin );
pfromMacro = &fromMacro_;
}
TCH_RelativeMoveList_t relativeMoveList( 2 * pfromMacro->GetLength( ));
for( size_t i = 0; i < pfromMacro->GetLength( ); ++i )
{
const TCH_RelativeNode_c& fromNode = *(*pfromMacro)[i];
TGO_Point_c fromPoint = fromNode.GetVPR_GridPoint( );
// Apply transform to relative node's grid point (based on origin point)
TGO_Transform_c toTransform( toOrigin, toRotate, fromOrigin, fromPoint );
TGO_Point_c toPoint;
toTransform.Apply( toOrigin, &toPoint );
// Validate that transformed point is still valid wrt. VPR's grid array
if( !this->vpr_data_.IsWithinGridArray( toPoint ))
{
isAvailable = false;
break;
}
// Validate that we are attempting between non-identifical macros
if( fromMacroIndex == toMacroIndex )
{
isAvailable = false;
break;
}
const t_type_descriptor* vpr_fromType = this->vpr_data_.FindGridPointType( fromPoint );
const t_type_descriptor* vpr_toType = this->vpr_data_.FindGridPointType( toPoint );
if( vpr_fromType != vpr_toType )
{
// VPR's grid types do not match => location is *not* available
isAvailable = false;
break;
}
if( this->vpr_data_.IsEmptyGridPoint( fromPoint ))
{
// VPR's grid location is empty => really not much we can do today
continue;
}
if( this->vpr_data_.IsEmptyGridPoint( toPoint ))
{
// VPR's grid location is empty => it is available
// Add move "from" relative macro node -> "to" empty block location
TCH_RelativeMove_c fromMove( fromMacroIndex, fromPoint, toPoint );
relativeMoveList.Add( fromMove );
continue;
}
const TCH_RelativeBlock_c* pfromBlock = this->FindRelativeBlock_( fromPoint );
if( !pfromBlock ||
!pfromBlock->HasRelativeMacroIndex( ))
{
// VPR's grid block name is not asso. with a relative macro => not available
continue;
}
const TCH_RelativeBlock_c* ptoBlock = this->FindRelativeBlock_( toPoint );
if( !ptoBlock ||
!ptoBlock->HasRelativeMacroIndex( ))
{
// VPR's grid block name is not asso. with a relative macro => it is available
// Add move "from" relative macro node -> "to" single block location,
// and add move "to" single block -> "from" relative macro node
// (since "to" block location not a member of a relative macro)
TCH_RelativeMove_c fromMove( fromMacroIndex, fromPoint, toPoint );
TCH_RelativeMove_c toMove( toPoint, fromMacroIndex, fromPoint );
relativeMoveList.Add( fromMove );
relativeMoveList.Add( toMove );
continue;
}
if( ptoBlock &&
ptoBlock->GetRelativeMacroIndex( ) == toMacroIndex )
{
// VPR's grid block name matches the given "to" relative macro => it is available
// Add move "from" relative macro node -> "to" single block location,
// but ignore move "to" relative macro node -> "from" relative macro node
// (since "to" move will be captured by to->from availability processing)
TCH_RelativeMove_c fromMove( fromMacroIndex, fromPoint, toMacroIndex, toPoint );
relativeMoveList.Add( fromMove );
continue;
}
// If we arrive at this point, then we know that VPR's grid block must
// be a member of some other unrelated relative macro
isAvailable = false;
break;
}
if( isAvailable )
{
// Add list of local moves to the optional relative move list
prelativeMoveList->Add( relativeMoveList );
}
return( isAvailable ); // TRUE => all relative nodes can be transformed
}
//===========================================================================//
// Method : PlaceMacroResetRotate_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
// 07/08/13 jeffr : Extended to support relative placement enable per macro
//===========================================================================//
void TCH_RelativePlaceHandler_c::PlaceMacroResetRotate_(
TCH_PlaceMacroRotateMode_t mode,
const TGO_Point_c& point )
{
TCH_RotateMaskValue_c* protateMaskValue = ( mode == TCH_PLACE_MACRO_ROTATE_FROM ?
&this->fromPlaceMacroRotate_ :
&this->toPlaceMacroRotate_ );
const TCH_RelativeMacro_c* prelativeMacro = this->FindRelativeMacro_( point );
bool rotateEnabled = ( prelativeMacro ? prelativeMacro->IsRotateEnabled( ) : false );
protateMaskValue->Init( rotateEnabled );
}
//===========================================================================//
// Method : PlaceMacroIsLegalRotate_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::PlaceMacroIsLegalRotate_(
TCH_PlaceMacroRotateMode_t mode,
TGO_RotateMode_t rotate ) const
{
bool isLegal = true;
const TCH_RotateMaskValue_c* pplaceMacroRotate = ( mode == TCH_PLACE_MACRO_ROTATE_FROM ?
&this->fromPlaceMacroRotate_ :
&this->toPlaceMacroRotate_ );
TCH_RotateMaskValue_c* protateMaskValue = const_cast< TCH_RotateMaskValue_c* >( pplaceMacroRotate );
if( !protateMaskValue->GetBit( rotate ))
{
isLegal = false;
}
else
{
isLegal = true;
protateMaskValue->ClearBit( rotate );
}
return( isLegal );
}
//===========================================================================//
// Method : PlaceMacroIsValidRotate_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::PlaceMacroIsValidRotate_(
TCH_PlaceMacroRotateMode_t mode ) const
{
const TCH_RotateMaskValue_c* pplaceMacroRotate = ( mode == TCH_PLACE_MACRO_ROTATE_FROM ?
&this->fromPlaceMacroRotate_ :
&this->toPlaceMacroRotate_ );
return( pplaceMacroRotate->IsValid( ) ?
true : false );
}
//===========================================================================//
// Method : PlaceMacroUpdateMoveList_
// Description : Updates a relative move list to insure the "fromEmpty"
// and "toEmpty" values accurately reflect when a grid point
// will become empty after a relative move. This situation
// may occur undetected in "PlaceMacroIsAvailableCoord_()"
// if a move has been made from a relative macro node point
// that is not subsequently used by another move (which can
// occur due to different random "from" and "to" rotate
// modes). This relative move list update is needed in order
// to insure that VPR's 'blocks_affected array' is
// subsequently correctly loaded by "PlaceSwapUpdate_()"
// such that the 'swapped_to_empty' fields properly indicate
// when a move leaves a grid point empty.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
void TCH_RelativePlaceHandler_c::PlaceMacroUpdateMoveList_(
TCH_RelativeMoveList_t* prelativeMoveList ) const
{
for( size_t i = 0; i < prelativeMoveList->GetLength( ); ++i )
{
TCH_RelativeMove_c* prelativeMove = (*prelativeMoveList)[i];
const TGO_Point_c& fromPoint = prelativeMove->GetFromPoint( );
const TGO_Point_c& toPoint = prelativeMove->GetToPoint( );
bool fromEmpty = true;
bool toEmpty = true;
for( size_t j = 0; j < prelativeMoveList->GetLength( ); ++j )
{
const TCH_RelativeMove_c& relativeMove = *(*prelativeMoveList)[j];
if( relativeMove.GetToPoint( ) == fromPoint )
{
fromEmpty = false;
}
if( relativeMove.GetFromPoint( ) == toPoint )
{
toEmpty = false;
}
}
prelativeMove->SetFromEmpty( fromEmpty );
prelativeMove->SetToEmpty( toEmpty );
}
}
//===========================================================================//
// Method : PlaceMacroIsLegalMoveList_
// Description : Returns TRUE if-and-only-if no two relative moves share
// the same "to" point. This situation may exist undetected
// during "PlaceMacroIsAvailableCoord_()" if two relative
// macros are near enough to each other and they end of
// sharing a common "to" point.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::PlaceMacroIsLegalMoveList_(
const TCH_RelativeMoveList_t& fromToMoveList,
const TCH_RelativeMoveList_t& toFromMoveList ) const
{
bool isLegal = true;
for( size_t i = 0; i < toFromMoveList.GetLength( ); ++i )
{
const TCH_RelativeMove_c& toFromMove = *toFromMoveList[i];
for( size_t j = 0; j < fromToMoveList.GetLength( ); ++j )
{
const TCH_RelativeMove_c& fromToMove = *fromToMoveList[j];
if( toFromMove.GetToPoint( ) == fromToMove.GetToPoint( ))
{
// Found at least two relative moves that share same "to" point
isLegal = false;
}
if( !isLegal )
break;
}
if( !isLegal )
break;
}
return( isLegal );
}
//===========================================================================//
// Method : FindRandomRotateMode_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
// 07/08/13 jeffr : Extended to support relative placement enable per macro
//===========================================================================//
TGO_RotateMode_t TCH_RelativePlaceHandler_c::FindRandomRotateMode_(
const TCH_RelativeMacro_c& relativeMacro ) const
{
// Select a random rotate mode (if enabled)
int rotate = ( relativeMacro.IsRotateEnabled( ) ?
TCT_Rand( 1, TGO_ROTATE_MAX - 1 ) :
TGO_ROTATE_R0 );
return( static_cast< TGO_RotateMode_t >( rotate ));
}
//===========================================================================//
TGO_RotateMode_t TCH_RelativePlaceHandler_c::FindRandomRotateMode_(
const TGO_Point_c& point ) const
{
TGO_RotateMode_t rotate = TGO_ROTATE_R0;
const TCH_RelativeMacro_c* prelativeMacro = this->FindRelativeMacro_( point );
if( prelativeMacro )
{
rotate = this->FindRandomRotateMode_( *prelativeMacro );
}
return( rotate );
}
//===========================================================================//
// Method : FindRandomOriginPoint_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
TGO_Point_c TCH_RelativePlaceHandler_c::FindRandomOriginPoint_(
const TCH_RelativeMacro_c& relativeMacro,
size_t relativeNodeIndex ) const
{
const TCH_RelativeNodeList_t& relativeNodeList = relativeMacro.GetRelativeNodeList( );
const TCH_RelativeNode_c& relativeNode = *relativeNodeList[relativeNodeIndex];
return( this->FindRandomOriginPoint_( relativeNode ));
}
//===========================================================================//
TGO_Point_c TCH_RelativePlaceHandler_c::FindRandomOriginPoint_(
const TCH_RelativeNode_c& relativeNode ) const
{
const char* pszBlockName = relativeNode.GetBlockName( );
return( this->FindRandomOriginPoint_( pszBlockName ));
}
//===========================================================================//
TGO_Point_c TCH_RelativePlaceHandler_c::FindRandomOriginPoint_(
const char* pszBlockName ) const
{
TGO_Point_c origin;
const TCH_RelativeBlock_c& relativeBlock = *this->relativeBlockList_.Find( pszBlockName );
const t_type_descriptor* vpr_type = relativeBlock.GetVPR_Type( );
int typeIndex = ( vpr_type ? vpr_type->index : EMPTY );
int posIndex = 0;
t_grid_tile** vpr_gridArray = this->vpr_data_.vpr_gridArray;
int* vpr_freeLocationArray = this->vpr_data_.vpr_freeLocationArray;
t_legal_pos** vpr_legalPosArray = this->vpr_data_.vpr_legalPosArray;
if(( typeIndex != EMPTY ) &&
( typeIndex != INVALID ) &&
( vpr_freeLocationArray[typeIndex] >= 0 ))
{
// Attempt to select a random (and available) point from within VPR's grid array
// (based on VPR's internal 'free_locations' and 'legal_pos' structures)
for( size_t i = 0; i < TCH_FIND_RANDOM_ORIGIN_POINT_MAX_ATTEMPTS; ++i )
{
posIndex = TCT_Rand( 0, vpr_freeLocationArray[typeIndex] - 1 );
int x = vpr_legalPosArray[typeIndex][posIndex].x;
int y = vpr_legalPosArray[typeIndex][posIndex].y;
int z = vpr_legalPosArray[typeIndex][posIndex].z;
if( vpr_gridArray[x][y].blocks[z] == EMPTY )
{
origin.Set( x, y, z );
break;
}
}
}
if(( typeIndex != EMPTY ) &&
( typeIndex != INVALID ) &&
( vpr_freeLocationArray[typeIndex] >= 0 ) &&
( !origin.IsValid( )))
{
// Handle case where we failed to find placement location
// (due to exceeding the max number of random placement attempts)
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
printHandler.Warning( "Failed initial relative macro placement for block \"%s\" after %u random tries.\n",
TIO_PSZ_STR( pszBlockName ),
TCH_FIND_RANDOM_ORIGIN_POINT_MAX_ATTEMPTS );
printHandler.Info( "%sAttempting to find available location based on exhaustive search of all free locations.\n",
TIO_PREFIX_WARNING_SPACE );
// Perform an exhaustive search for 1st free location
for( posIndex = 0; posIndex < vpr_freeLocationArray[typeIndex]; ++posIndex )
{
int x = vpr_legalPosArray[typeIndex][posIndex].x;
int y = vpr_legalPosArray[typeIndex][posIndex].y;
int z = vpr_legalPosArray[typeIndex][posIndex].z;
if( vpr_gridArray[x][y].blocks[z] == EMPTY )
{
origin.Set( x, y, z );
break;
}
}
}
if(( typeIndex != EMPTY ) &&
( typeIndex != INVALID ) &&
( vpr_freeLocationArray[typeIndex] >= 0 ) &&
( !origin.IsValid( )))
{
// Handle case where we still failed to find placement location
// (even after an exhaustive iteration over all free locations)
const t_type_descriptor* vpr_typeArray = this->vpr_data_.vpr_typeArray;
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
printHandler.Error( "Initial relative placement failed!\n" );
printHandler.Info( "%sCould not place block \"%s\", no free locations of type \"%s\".\n",
TIO_PREFIX_ERROR_SPACE,
TIO_PSZ_STR( pszBlockName ),
TIO_PSZ_STR( vpr_typeArray[typeIndex].name ));
}
if(( typeIndex != EMPTY ) &&
( typeIndex != INVALID ) &&
( vpr_freeLocationArray[typeIndex] >= 0 ) &&
( origin.IsValid( )))
{
// Update VPR's 'free_locations' and 'legal_pos' structures to prevent
// randomly finding same origin point again - IFF rotate not enabled
// (for further reference, see VPR's initial_place_blocks() function)
size_t relativeMacroIndex = relativeBlock.GetRelativeMacroIndex( );
const TCH_RelativeMacro_c& relativeMacro = *this->relativeMacroList_[relativeMacroIndex];
if( !relativeMacro.IsRotateEnabled( ))
{
int lastIndex = vpr_freeLocationArray[typeIndex] - 1;
if( lastIndex >= 0 )
{
vpr_legalPosArray[typeIndex][posIndex] = vpr_legalPosArray[typeIndex][lastIndex];
}
--vpr_freeLocationArray[typeIndex];
}
}
return( origin );
}
//===========================================================================//
// Method : FindRandomRelativeNodeIndex_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
size_t TCH_RelativePlaceHandler_c::FindRandomRelativeNodeIndex_(
const TCH_RelativeMacro_c& relativeMacro ) const
{
size_t relativeNodeIndex = TCT_Rand( static_cast< size_t >( 0 ),
relativeMacro.GetLength( ) - 1 );
return( relativeNodeIndex );
}
//===========================================================================//
// Method : FindRelativeMacroIndex_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
size_t TCH_RelativePlaceHandler_c::FindRelativeMacroIndex_(
const TGO_Point_c& point ) const
{
size_t relativeMacroIndex = TCH_RELATIVE_MACRO_UNDEFINED;
if( this->vpr_data_.IsWithinGridArray( point ))
{
// Find relative block based on VPR's grid array point
const TCH_RelativeBlock_c* prelativeBlock = this->FindRelativeBlock_( point );
// Find relative macro index, if any, based on relative block
if( prelativeBlock )
{
relativeMacroIndex = prelativeBlock->GetRelativeMacroIndex( );
}
}
return( relativeMacroIndex );
}
//===========================================================================//
// Method : FindRelativeNodeIndex_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
size_t TCH_RelativePlaceHandler_c::FindRelativeNodeIndex_(
const TGO_Point_c& point ) const
{
size_t relativeNodeIndex = TCH_RELATIVE_NODE_UNDEFINED;
if( this->vpr_data_.IsWithinGridArray( point ))
{
// Find relative block based on VPR's grid array point
const TCH_RelativeBlock_c* prelativeBlock = this->FindRelativeBlock_( point );
// Find relative node index, if any, based on relative block
if( prelativeBlock )
{
relativeNodeIndex = prelativeBlock->GetRelativeNodeIndex( );
}
}
return( relativeNodeIndex );
}
//===========================================================================//
// Method : FindRelativeMacro_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
TCH_RelativeMacro_c* TCH_RelativePlaceHandler_c::FindRelativeMacro_(
const TGO_Point_c& point ) const
{
TCH_RelativeMacro_c* prelativeMacro = 0;
if( this->vpr_data_.IsWithinGridArray( point ))
{
// Find relative macro index based on VPR's grid array point
size_t relativeMacroIndex = this->FindRelativeMacroIndex_( point );
// Find relative macro, if any, based on relative macro index
prelativeMacro = this->relativeMacroList_[relativeMacroIndex];
}
return( prelativeMacro );
}
//===========================================================================//
// Method : FindRelativeNode_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
TCH_RelativeNode_c* TCH_RelativePlaceHandler_c::FindRelativeNode_(
const TGO_Point_c& point ) const
{
TCH_RelativeNode_c* prelativeNode = 0;
if( this->vpr_data_.IsWithinGridArray( point ))
{
// Find relative macro and node indices based on VPR's grid array point
size_t relativeMacroIndex = this->FindRelativeMacroIndex_( point );
size_t relativeNodeIndex = this->FindRelativeNodeIndex_( point );
// Find relative macro, if any, based on relative macro index
const TCH_RelativeMacro_c* prelativeMacro = 0;
prelativeMacro = this->relativeMacroList_[relativeMacroIndex];
if( prelativeMacro )
{
prelativeNode = (*prelativeMacro)[relativeNodeIndex];
}
}
return( prelativeNode );
}
//===========================================================================//
// Method : FindRelativeBlock_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
const TCH_RelativeBlock_c* TCH_RelativePlaceHandler_c::FindRelativeBlock_(
const TGO_Point_c& point ) const
{
const TCH_RelativeBlock_c* prelativeBlock = 0;
if( this->vpr_data_.IsWithinGridArray( point ))
{
// Look up VPR block name based on VPR's grid array
const char* pszBlockName = this->vpr_data_.FindGridPointBlockName( point );
// Find relative block, if any, based on VPR's block name
prelativeBlock = this->relativeBlockList_.Find( pszBlockName );
}
return( prelativeBlock );
}
//===========================================================================//
// Method : DecideAntiLink_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
// 06/25/13 jeffr : Migrated original side-based "DecideAntiLink_() method
//===========================================================================//
void TCH_RelativePlaceHandler_c::DecideAntiLink_(
const TGO_IntDims_t& relativeLink,
TGO_IntDims_t* pantiLink ) const
{
if( pantiLink )
{
pantiLink->Set( -1 * relativeLink.dx, -1 * relativeLink.dy );
}
}
//===========================================================================//
// Method : ShowIllegalRelativeMacroWarning_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::ShowIllegalRelativeMacroWarning_(
const TCH_RelativeMacro_c& relativeMacro,
size_t relativeNodeIndex,
const TGO_Point_c& origin,
TGO_RotateMode_t rotate ) const
{
const TCH_RelativeNode_c& relativeNode = *relativeMacro.Find( relativeNodeIndex );
const char* pszBlockName = relativeNode.GetBlockName( );
string srOrigin;
origin.ExtractString( &srOrigin );
string srRotate;
TGO_ExtractStringRotateMode( rotate, &srRotate );
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
bool ok = printHandler.Warning( "Failed relative macro placement based on reference block \"%s\" at origin (%s) and rotate %s.\n",
TIO_PSZ_STR( pszBlockName ),
TIO_SR_STR( srOrigin ),
TIO_SR_STR( srRotate ));
return( ok );
}
//===========================================================================//
// Method : ShowMissingBlockNameError_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::ShowMissingBlockNameError_(
const char* pszBlockName ) const
{
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
bool ok = printHandler.Error( "Invalid relative placement constraint!\n" );
printHandler.Info( "%sBlock \"%s\" was not found in VPR's block list.\n",
TIO_PREFIX_ERROR_SPACE,
TIO_PSZ_STR( pszBlockName ));
return( ok );
}
//===========================================================================//
// Method : ShowInvalidConstraintError_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 01/15/13 jeffr : Original
//===========================================================================//
bool TCH_RelativePlaceHandler_c::ShowInvalidConstraintError_(
const TCH_RelativeBlock_c& fromBlock,
const TCH_RelativeBlock_c& toBlock,
const TGO_IntDims_t& fromToLink,
const string& srExistingFromBlockName,
const string& srExistingToBlockName ) const
{
const char* pszFromBlockName = fromBlock.GetName( );
const char* pszToBlockName = toBlock.GetName( );
string srFromToLink;
fromToLink.ExtractString( TC_DATA_INT, &srFromToLink );
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
bool ok = printHandler.Error( "Invalid relative placement constraint!\n" );
if( srExistingFromBlockName.length( ) &&
srExistingToBlockName.length( ))
{
printHandler.Info( "%sConstraint conflict exists between \"%s\" and \"%s\".\n",
TIO_PREFIX_ERROR_SPACE,
TIO_SR_STR( srExistingFromBlockName ),
TIO_SR_STR( srExistingToBlockName ));
}
printHandler.Info( "%sIgnoring constraint from \"%s\" to \"%s\" based on [%s] relative placement'.\n",
TIO_PREFIX_ERROR_SPACE,
TIO_PSZ_STR( pszFromBlockName ),
TIO_PSZ_STR( pszToBlockName ),
TIO_SR_STR( srFromToLink ));
return( ok );
}