blob: 08fbf0ba6a25341bf6b7230a974f124af303a3c1 [file] [log] [blame] [edit]
//===========================================================================//
// Purpose : Method definitions for the TVPR_ArchitectureSpec_c class.
//
// Public methods include:
// - TVPR_ArchitectureSpec_c, ~TVPR_ArchitectureSpec_c
// - Export
//
// Private methods include:
// - PokeConfigLayout_
// - PokeConfigDevice_
// - PokeConfigPower_
// - PokeConfigClocks_
// - PokeModelLists_
// - PokeModel_
// - PokePhysicalBlockList_
// - PokePhysicalBlock_
// - PokeSwitchBoxList_
// - PokeSegmentList_
// - PokeCarryChainList_
// - PokePbType_
// - PokePbTypeChild_
// - PokePbTypeLutClass_
// - PokePbTypeMemoryClass_
// - PokeModeList_
// - PokeMode_
// - PokeInterconnectList_
// - PokeInterconnect_
// - PokeFc_
// - PokeFcPinList_
// - PokeFcPin_
// - PokePinAssignList_
// - PokeGridAssignList_
// - PokePortList_
// - PokePort_
// - PokeTimingDelayLists_
// - PokeTimingDelay_
// - PokePower_
// - PokePowerPortList_
// - PokePowerPort_
// - InitModels_
// - InitPbType_
// - ValidateModels_
// - FindSideMode_
// - FindClassType_
// - FindInterconnectMapType_
// - FindPinAssignPatternType_
// - FindGridAssignDistrMode_
// - FindChannelDistrMode_
// - FindSwitchBoxModelType_
// - FindSegmentDirType_
// - FindSegmentBitPattern_
// - FindPowerMethodMode_
// - InheritPowerMethodMode_
//
//===========================================================================//
//---------------------------------------------------------------------------//
// Copyright (C) 2012-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 <string>
using namespace std;
#include "TC_StringUtils.h"
#include "TC_MemoryUtils.h"
#include "TVPR_ArchitectureSpec.h"
//===========================================================================//
// Method : TVPR_ArchitectureSpec_c
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
TVPR_ArchitectureSpec_c::TVPR_ArchitectureSpec_c(
void )
{
}
//===========================================================================//
// Method : ~TVPR_ArchitectureSpec_c
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
TVPR_ArchitectureSpec_c::~TVPR_ArchitectureSpec_c(
void )
{
}
//===========================================================================//
// Method : Export
// Reference : See VPR's "s_arch" data structure, as defined in the
// "physical_types.h" source code file.
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
// 07/10/13 jeffr : Added support for "PokeCarryChainList_()" method
// 07/23/13 jeffr : Added support for "PokeConfigPower_()" method
// 07/23/13 jeffr : Added support for "PokeConfigClock_()" method
//===========================================================================//
bool TVPR_ArchitectureSpec_c::Export(
const TAS_ArchitectureSpec_c& architectureSpec,
t_arch* pvpr_architecture,
t_type_descriptor** pvpr_physicalBlockArray,
int* pvpr_physicalBlockCount,
bool isTimingEnabled,
bool isPowerEnabled,
bool isClocksEnabled ) const
{
bool ok = true;
const TAS_Config_c& config = architectureSpec.config;
const TAS_CellList_t& cellList = architectureSpec.cellList;
const TAS_PhysicalBlockList_t& physicalBlockList = architectureSpec.physicalBlockList;
const TAS_SwitchBoxList_t& switchBoxList = architectureSpec.switchBoxList;
const TAS_SegmentList_t& segmentList = architectureSpec.segmentList;
const TAS_CarryChainList_t& carryChainList = architectureSpec.carryChainList;
this->PokeConfigLayout_( config,
pvpr_architecture );
this->PokeConfigDevice_( config,
pvpr_architecture,
isTimingEnabled );
this->PokeConfigPower_( config,
pvpr_architecture,
isPowerEnabled );
this->PokeConfigClocks_( config,
pvpr_architecture,
isClocksEnabled );
if( ok )
{
this->PokeModelLists_( cellList,
pvpr_architecture );
}
if( ok )
{
ok = this->PokePhysicalBlockList_( physicalBlockList,
pvpr_physicalBlockArray,
pvpr_physicalBlockCount );
}
if( ok )
{
ok = this->PokeSwitchBoxList_( switchBoxList,
&pvpr_architecture->Switches,
&pvpr_architecture->num_switches,
isTimingEnabled );
}
if( ok )
{
ok = this->PokeSegmentList_( segmentList,
&pvpr_architecture->Segments,
&pvpr_architecture->num_segments,
pvpr_architecture->Switches,
pvpr_architecture->num_switches,
isTimingEnabled );
}
if( ok )
{
ok = this->PokeCarryChainList_( carryChainList,
&pvpr_architecture->Directs,
&pvpr_architecture->num_directs );
}
if( ok )
{
ok = this->InitModels_( *pvpr_architecture,
pvpr_physicalBlockArray,
*pvpr_physicalBlockCount );
}
return( ok );
}
//===========================================================================//
// Method : PokeConfigLayout_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokeConfigLayout_(
const TAS_Config_c& config,
t_arch* pvpr_architecture ) const
{
// Write TAS_Config_c's layout parameters
if( config.layout.manualSize.gridDims.IsValid( ))
{
pvpr_architecture->clb_grid.IsAuto = static_cast< boolean >( false );
pvpr_architecture->clb_grid.W = config.layout.manualSize.gridDims.dx;
pvpr_architecture->clb_grid.H = config.layout.manualSize.gridDims.dy;
}
else if( TCTF_IsGT( config.layout.autoSize.aspectRatio, 0.0 ))
{
pvpr_architecture->clb_grid.IsAuto = static_cast< boolean >( true );
pvpr_architecture->clb_grid.Aspect = static_cast< float >( config.layout.autoSize.aspectRatio );
}
else
{
pvpr_architecture->clb_grid.IsAuto = static_cast< boolean >( true );
pvpr_architecture->clb_grid.Aspect = 1.0;
}
}
//===========================================================================//
// Method : PokeConfigDevice_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokeConfigDevice_(
const TAS_Config_c& config,
t_arch* pvpr_architecture,
bool isTimingEnabled ) const
{
// Write TAS_Config_c's device area model parameters
if( isTimingEnabled )
{
pvpr_architecture->R_minW_nmos = static_cast< float >( config.device.areaModel.resMinWidthNMOS );
}
if( isTimingEnabled )
{
pvpr_architecture->R_minW_pmos = static_cast< float >( config.device.areaModel.resMinWidthPMOS );
}
pvpr_architecture->ipin_mux_trans_size = static_cast< float >( config.device.areaModel.sizeInputPinMux );
pvpr_architecture->grid_logic_tile_area = static_cast< float >( config.device.areaModel.areaGridTile );
// Write TAS_Config_c's device timing analysis parameters
pvpr_architecture->C_ipin_cblock = static_cast< float >( config.device.connectionBoxes.capInput );
pvpr_architecture->T_ipin_cblock = static_cast< float >( config.device.connectionBoxes.delayInput );
// Write TAS_Config_c's device switch box parameters
if( config.device.switchBoxes.modelType != TAS_SWITCH_BOX_MODEL_UNDEFINED )
{
pvpr_architecture->SBType = this->FindSwitchBoxModelType_( config.device.switchBoxes.modelType );
}
if( config.device.switchBoxes.fs > 0 )
{
pvpr_architecture->Fs = config.device.switchBoxes.fs;
}
// Write TAS_Config_c's device channel width parameters
if( config.device.channelWidth.io.IsValid( ))
{
pvpr_architecture->Chans.chan_width_io = static_cast< float >( config.device.channelWidth.io.width );
}
if( config.device.channelWidth.x.IsValid( ))
{
pvpr_architecture->Chans.chan_x_dist.type = this->FindChannelDistrMode_( config.device.channelWidth.x.distrMode );
pvpr_architecture->Chans.chan_x_dist.peak = static_cast< float >( config.device.channelWidth.x.peak );
pvpr_architecture->Chans.chan_x_dist.xpeak = static_cast< float >( config.device.channelWidth.x.xpeak );
pvpr_architecture->Chans.chan_x_dist.dc = static_cast< float >( config.device.channelWidth.x.dc );
pvpr_architecture->Chans.chan_x_dist.width = static_cast< float >( config.device.channelWidth.x.width );
}
if( config.device.channelWidth.y.IsValid( ))
{
pvpr_architecture->Chans.chan_y_dist.type = this->FindChannelDistrMode_( config.device.channelWidth.y.distrMode );
pvpr_architecture->Chans.chan_y_dist.peak = static_cast< float >( config.device.channelWidth.y.peak );
pvpr_architecture->Chans.chan_y_dist.xpeak = static_cast< float >( config.device.channelWidth.y.xpeak );
pvpr_architecture->Chans.chan_y_dist.dc = static_cast< float >( config.device.channelWidth.y.dc );
pvpr_architecture->Chans.chan_y_dist.width = static_cast< float >( config.device.channelWidth.y.width );
}
}
//===========================================================================//
// Method : PokeConfigPower_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/17/13 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokeConfigPower_(
const TAS_Config_c& config,
t_arch* pvpr_architecture,
bool isPowerEnabled ) const
{
if( isPowerEnabled )
{
pvpr_architecture->power = static_cast< t_power_arch* >( TC_calloc( 1, sizeof( t_power_arch )));
}
if( pvpr_architecture->power )
{
t_power_arch* pvpr_power = pvpr_architecture->power;
pvpr_power->C_wire_local = 0.0;
pvpr_power->local_interc_factor = 0.5;
if( TCTF_IsGT( config.power.interconnect.capWire, 0.0 ))
{
pvpr_power->C_wire_local = static_cast< float >( config.power.interconnect.capWire );
pvpr_power->local_interc_factor = static_cast< float >( config.power.interconnect.factor );
}
pvpr_power->logical_effort_factor = 4.0;
if( TCTF_IsGT( config.power.buffers.logicalEffortFactor, 0.0 ))
{
pvpr_power->logical_effort_factor = static_cast< float >( config.power.buffers.logicalEffortFactor );
}
pvpr_power->transistors_per_SRAM_bit = 6.0;
if( TCTF_IsGT( config.power.sram.transistorsPerBit, 0.0 ))
{
pvpr_power->transistors_per_SRAM_bit = static_cast< float >( config.power.sram.transistorsPerBit );
}
}
}
//===========================================================================//
// Method : PokeConfigClocks_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/17/13 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokeConfigClocks_(
const TAS_Config_c& config,
t_arch* pvpr_architecture,
bool isClocksEnabled ) const
{
if( isClocksEnabled )
{
pvpr_architecture->clocks = static_cast< t_clock_arch* >( TC_calloc( 1, sizeof( t_clock_arch )));
}
if( pvpr_architecture->clocks )
{
int clockLen = static_cast< int >( config.clockList.GetLength( ));
t_clock_network* clockList = 0;
if( clockLen )
{
clockList = static_cast< t_clock_network* >( TC_calloc( clockLen, sizeof( t_clock_network )));
for( int i = 0; i < clockLen; ++i )
{
const TAS_Clock_c& clock = *config.clockList[i];
clockList[i].autosize_buffer = static_cast< boolean >( clock.autoSize );
clockList[i].buffer_size = static_cast< float >( clock.bufferSize );
clockList[i].C_wire = static_cast< float >( clock.capWire );
}
}
pvpr_architecture->clocks->num_global_clocks = clockLen;
pvpr_architecture->clocks->clock_inf = clockList;
}
}
//===========================================================================//
// Method : PokeModelLists_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokeModelLists_(
const TAS_CellList_t& cellList,
t_arch* pvpr_architecture ) const
{
int libraryLen = NUM_MODELS_IN_LIBRARY;
int libraryIndex = 0;
pvpr_architecture->model_library = static_cast< t_model* >( TC_calloc( libraryLen, sizeof( t_model )));
for( size_t i = 0; i < cellList.GetLength( ); ++i )
{
const TAS_Cell_c& cell = *cellList[i];
if( cell.GetSource( ) != TLO_CELL_SOURCE_STANDARD )
continue;
t_model* pvpr_model = &pvpr_architecture->model_library[libraryIndex];
pvpr_model->index = libraryIndex;
++libraryIndex;
this->PokeModel_( cell, pvpr_model );
if( libraryIndex < libraryLen )
{
pvpr_model->next = &( pvpr_architecture->model_library[libraryIndex] );
}
}
int modelIndex = NUM_MODELS_IN_LIBRARY;
pvpr_architecture->models = 0;
for( size_t i = 0; i < cellList.GetLength( ); ++i )
{
const TAS_Cell_c& cell = *cellList[i];
if( cell.GetSource( ) != TLO_CELL_SOURCE_CUSTOM )
continue;
t_model* pvpr_model = static_cast< t_model* >( TC_calloc( 1, sizeof( t_model )));
pvpr_model->index = modelIndex;
++modelIndex;
this->PokeModel_( cell, pvpr_model );
pvpr_model->next = pvpr_architecture->models;
pvpr_architecture->models = pvpr_model;
}
}
//===========================================================================//
// Method : PokeModel_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
// 07/10/13 jeffr : Fixed code to properly initialize the model 'index' field
// (was defaulting to '0', which failed for memory subckts)
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokeModel_(
const TAS_Cell_c& cell,
t_model* pvpr_model ) const
{
pvpr_model->name = TC_strdup( cell.GetName( ));
const TLO_PortList_t& portList = cell.GetPortList( );
size_t inputTotal = 0;
size_t outputTotal = 0;
for( size_t j = 0; j < portList.GetLength( ); ++j )
{
const TLO_Port_c& port = *portList[j];
inputTotal += (( port.GetType( ) == TC_TYPE_INPUT ) ? 1 : 0 );
inputTotal += (( port.GetType( ) == TC_TYPE_CLOCK ) ? 1 : 0 );
outputTotal += (( port.GetType( ) == TC_TYPE_OUTPUT ) ? 1 : 0 );
}
pvpr_model->inputs = static_cast< t_model_ports* >( TC_calloc( inputTotal, sizeof( t_model_ports )));
pvpr_model->outputs = static_cast< t_model_ports* >( TC_calloc( outputTotal, sizeof( t_model_ports )));
size_t inputCount = 0;
size_t inputIndex = 0;
size_t clockIndex = 0;
for( size_t j = 0; j < portList.GetLength( ); ++j )
{
const TLO_Port_c& port = *portList[j];
if(( port.GetType( ) == TC_TYPE_INPUT ) || ( port.GetType( ) == TC_TYPE_CLOCK ))
{
t_model_ports* pvpr_modelPort = &( pvpr_model->inputs[inputCount] );
++inputCount;
pvpr_modelPort->name = TC_strdup( port.GetName( ));
pvpr_modelPort->dir = IN_PORT;
pvpr_modelPort->size = ( cell.GetSource( ) == TLO_CELL_SOURCE_STANDARD ? 1 : -1 );
pvpr_modelPort->min_size = ( cell.GetSource( ) == TLO_CELL_SOURCE_STANDARD ? 1 : -1 );
if( port.GetType( ) == TC_TYPE_INPUT )
{
pvpr_modelPort->index = static_cast< int >( inputIndex );
++inputIndex;
pvpr_modelPort->is_clock = static_cast< boolean >( false );
}
else
{
pvpr_modelPort->index = static_cast< int >( clockIndex );
++clockIndex;
pvpr_modelPort->is_clock = static_cast< boolean >( true );
}
pvpr_modelPort->is_non_clock_global = static_cast< boolean >( false );
if( inputCount < inputTotal )
{
pvpr_modelPort->next = &( pvpr_model->inputs[inputCount] );
}
}
}
size_t outputCount = 0;
size_t outputIndex = 0;
for( size_t j = 0; j < portList.GetLength( ); ++j )
{
const TLO_Port_c& port = *portList[j];
if( port.GetType( ) == TC_TYPE_OUTPUT )
{
t_model_ports* pvpr_modelPort = &( pvpr_model->outputs[outputCount] );
++outputCount;
pvpr_modelPort->name = TC_strdup( port.GetName( ));
pvpr_modelPort->dir = OUT_PORT;
pvpr_modelPort->size = ( cell.GetSource( ) == TLO_CELL_SOURCE_STANDARD ? 1 : -1 );
pvpr_modelPort->min_size = ( cell.GetSource( ) == TLO_CELL_SOURCE_STANDARD ? 1 : -1 );
pvpr_modelPort->index = static_cast< int >( outputIndex );
++outputIndex;
if( outputCount < outputTotal )
{
pvpr_modelPort->next = &( pvpr_model->outputs[outputCount] );
}
}
}
}
//===========================================================================//
// Method : PokePhysicalBlockList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokePhysicalBlockList_(
const TAS_PhysicalBlockList_t& physicalBlockList,
t_type_descriptor** pvpr_physicalBlockArray,
int* pvpr_physicalBlockCount ) const
{
bool ok = true;
// [VPR] Alloc the physical block type list (with extra t_type_desctiptors for empty pseudo-type)
*pvpr_physicalBlockCount = static_cast< int >( physicalBlockList.GetLength( )) + 1;
*pvpr_physicalBlockArray = static_cast< t_type_descriptor* >( TC_calloc( *pvpr_physicalBlockCount, sizeof( t_type_descriptor )));
// [VPR] Initialize various VPR-specific global variables
type_descriptors = *pvpr_physicalBlockArray;
type_descriptors[EMPTY_TYPE_INDEX].index = EMPTY_TYPE_INDEX;
type_descriptors[IO_TYPE_INDEX].index = IO_TYPE_INDEX;
EMPTY_TYPE = &type_descriptors[EMPTY_TYPE_INDEX];
IO_TYPE = &type_descriptors[IO_TYPE_INDEX];
t_type_descriptor* pvpr_emptyBlock = &type_descriptors[EMPTY_TYPE_INDEX];
pvpr_emptyBlock->name = const_cast< char* >( "<EMPTY>" );
pvpr_emptyBlock->width = 1;
pvpr_emptyBlock->height = 1;
int index = 1; // [VPR] Skip over 'empty' type
for( size_t i = 0; i < physicalBlockList.GetLength( ); ++i )
{
const TAS_PhysicalBlock_c& physicalBlock = *physicalBlockList[i];
t_type_descriptor* pvpr_physicalBlock = &( *pvpr_physicalBlockArray )[index];
pvpr_physicalBlock->index = index;
++index;
ok = this->PokePhysicalBlock_( physicalBlock, pvpr_physicalBlock );
if( !ok )
break;
}
return( ok );
}
//===========================================================================//
// Method : PokePhysicalBlock_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokePhysicalBlock_(
const TAS_PhysicalBlock_c& physicalBlock,
t_type_descriptor* pvpr_physicalBlock ) const
{
bool ok = true;
pvpr_physicalBlock->name = TC_strdup( physicalBlock.srName.data( ));
pvpr_physicalBlock->width = (( physicalBlock.width > 0 ) ? physicalBlock.width : 1 );
pvpr_physicalBlock->height = (( physicalBlock.height > 0 ) ? physicalBlock.height : 1 );
pvpr_physicalBlock->capacity = (( physicalBlock.capacity > 0 ) ? physicalBlock.capacity : 1 );
pvpr_physicalBlock->area = -1;
// [VPR] Poke pb_type info
pvpr_physicalBlock->pb_type = static_cast< t_pb_type* >( TC_calloc( 1, sizeof( t_pb_type )));
ok = this->PokePbType_( physicalBlock, 0, pvpr_physicalBlock->pb_type );
pvpr_physicalBlock->pb_type->name = TC_strdup( pvpr_physicalBlock->name );
pvpr_physicalBlock->num_pins = pvpr_physicalBlock->capacity *
( pvpr_physicalBlock->pb_type->num_input_pins +
pvpr_physicalBlock->pb_type->num_output_pins +
pvpr_physicalBlock->pb_type->num_clock_pins );
pvpr_physicalBlock->num_receivers = pvpr_physicalBlock->capacity *
pvpr_physicalBlock->pb_type->num_input_pins;
pvpr_physicalBlock->num_drivers = pvpr_physicalBlock->capacity *
pvpr_physicalBlock->pb_type->num_output_pins;
// [VPR] Poke pin names and classes and locations
pvpr_physicalBlock->pin_location_distribution = this->FindPinAssignPatternType_( physicalBlock.pinAssignPattern );
this->PokePinAssignList_( physicalBlock.pinAssignList, pvpr_physicalBlock );
this->PokeGridAssignList_( physicalBlock.gridAssignList, pvpr_physicalBlock );
// [VPR] Poke Fc
if( ok )
{
ok = this->PokeFc_( physicalBlock, pvpr_physicalBlock );
}
return( ok );
}
//===========================================================================//
// Method : PokeSwitchBoxList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokeSwitchBoxList_(
const TAS_SwitchBoxList_t& switchBoxList,
t_switch_inf** pvpr_switchBoxArray,
int* pvpr_switchBoxCount,
bool isTimingEnabled ) const
{
bool ok = true;
*pvpr_switchBoxArray = 0;
*pvpr_switchBoxCount = static_cast< int >( switchBoxList.GetLength( ));
if( ok && ( *pvpr_switchBoxCount > 0 ))
{
*pvpr_switchBoxArray = static_cast< t_switch_inf* >( TC_calloc( *pvpr_switchBoxCount, sizeof( t_switch_inf )));
ok = ( pvpr_switchBoxArray ? true : false );
}
if( ok && ( *pvpr_switchBoxCount > 0 ))
{
for( size_t i = 0; i < switchBoxList.GetLength( ); ++i )
{
const TAS_SwitchBox_c& switchBox = *switchBoxList[i];
( *pvpr_switchBoxArray )[i].name = TC_strdup( switchBox.srName );
if(( switchBox.type == TAS_SWITCH_BOX_MUX ) ||
( switchBox.type == TAS_SWITCH_BOX_BUFFERED ))
{
( *pvpr_switchBoxArray )[i].buffered = static_cast< boolean >( true );
}
if(( switchBox.type == TAS_SWITCH_BOX_MUX ) &&
( TCTF_IsGT( switchBox.area.buffer, 0.0 )))
{
( *pvpr_switchBoxArray )[i].buf_size = static_cast< float >( switchBox.area.buffer );
}
if( TCTF_IsGT( switchBox.area.muxTransistor, 0.0 ))
{
( *pvpr_switchBoxArray )[i].mux_trans_size = static_cast< float >( switchBox.area.muxTransistor );
}
else
{
( *pvpr_switchBoxArray )[i].mux_trans_size = 1.0;
}
if( isTimingEnabled )
{
( *pvpr_switchBoxArray )[i].R = static_cast< float >( switchBox.timing.res );
}
if( isTimingEnabled )
{
( *pvpr_switchBoxArray )[i].Cin = static_cast< float >( switchBox.timing.capInput );
}
if( isTimingEnabled )
{
( *pvpr_switchBoxArray )[i].Cout = static_cast< float >( switchBox.timing.capOutput );
}
if( isTimingEnabled )
{
( *pvpr_switchBoxArray )[i].Tdel = static_cast< float >( switchBox.timing.delay );
}
if( switchBox.power.autoSize )
{
( *pvpr_switchBoxArray )[i].power_buffer_type = POWER_BUFFER_TYPE_AUTO;
}
else if( TCTF_IsGT( switchBox.power.bufferSize, 0.0 ))
{
( *pvpr_switchBoxArray )[i].power_buffer_type = POWER_BUFFER_TYPE_ABSOLUTE_SIZE;
( *pvpr_switchBoxArray )[i].power_buffer_size = static_cast< float >( switchBox.power.bufferSize );
}
}
}
return( ok );
}
//===========================================================================//
// Method : PokeSegmentList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokeSegmentList_(
const TAS_SegmentList_t& segmentList,
t_segment_inf** pvpr_segmentArray,
int* pvpr_segmentCount,
const t_switch_inf* vpr_switchBoxArray,
int vpr_switchBoxCount,
bool isTimingEnabled ) const
{
bool ok = true;
*pvpr_segmentArray = 0;
*pvpr_segmentCount = static_cast< int >( segmentList.GetLength( ));
if( ok && ( *pvpr_segmentCount > 0 ))
{
*pvpr_segmentArray = static_cast< t_segment_inf* >( TC_calloc( *pvpr_segmentCount, sizeof( t_segment_inf )));
ok = ( pvpr_segmentArray ? true : false );
}
if( ok && ( *pvpr_segmentCount > 0 ))
{
for( size_t i = 0; i < segmentList.GetLength( ); ++i )
{
const TAS_Segment_c& segment = *segmentList[i];
( *pvpr_segmentArray )[i].length = 1;
if( segment.length == UINT_MAX )
{
( *pvpr_segmentArray )[i].longline = static_cast< boolean >( true );
}
else if( segment.length > 0 )
{
( *pvpr_segmentArray )[i].length = segment.length;
}
if( segment.dirType != TAS_SEGMENT_DIR_UNDEFINED )
{
( *pvpr_segmentArray )[i].directionality = this->FindSegmentDirType_( segment.dirType );
}
( *pvpr_segmentArray )[i].frequency = static_cast< int >( 1.0 * MAX_CHANNEL_WIDTH );
if( TCTF_IsGT( segment.trackFreq, 0.0 ))
{
( *pvpr_segmentArray )[i].frequency = static_cast< int >( segment.trackFreq * MAX_CHANNEL_WIDTH );
}
if( isTimingEnabled )
{
( *pvpr_segmentArray )[i].Rmetal = static_cast< float >( segment.timing.res );
}
if( isTimingEnabled )
{
( *pvpr_segmentArray )[i].Cmetal = static_cast< float >( segment.timing.cap );
}
ok = this->FindSegmentBitPattern_( segment.sbPattern,
( *pvpr_segmentArray )[i].length + 1,
&( *pvpr_segmentArray )[i].sb,
&(( *pvpr_segmentArray )[i].sb_len ));
if( !ok )
break;
ok = this->FindSegmentBitPattern_( segment.cbPattern,
( *pvpr_segmentArray )[i].length,
&( *pvpr_segmentArray )[i].cb,
&(( *pvpr_segmentArray )[i].cb_len ));
if( !ok )
break;
if(( *pvpr_segmentArray )[i].directionality == UNI_DIRECTIONAL )
{
const char* pszMuxSwitchName = segment.srMuxSwitchName.data( );
int j = 0;
for( j = 0; j < vpr_switchBoxCount; ++j )
{
if( strcmp( pszMuxSwitchName, vpr_switchBoxArray[j].name ) == 0 )
break;
}
( *pvpr_segmentArray )[i].wire_switch = static_cast< short >( j );
( *pvpr_segmentArray )[i].opin_switch = static_cast< short >( j );
}
else // if(( *pvpr_segmentArray )[i].directionality == BI_DIRECTIONAL )
{
const char* pszWireSwitchName = segment.srWireSwitchName.data( );
int j = 0;
for( j = 0; j < vpr_switchBoxCount; ++j )
{
if( strcmp( pszWireSwitchName, vpr_switchBoxArray[j].name ) == 0 )
break;
}
( *pvpr_segmentArray )[i].wire_switch = static_cast< short >( j );
const char* pszOutputSwitchName = segment.srWireSwitchName.data( );
for( j = 0; j < vpr_switchBoxCount; ++j )
{
if( strcmp( pszOutputSwitchName, vpr_switchBoxArray[j].name ) == 0 )
break;
}
( *pvpr_segmentArray )[i].opin_switch = static_cast< short >( j );
}
}
}
return( ok );
}
//===========================================================================//
// Method : PokeCarryChainList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/13 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokeCarryChainList_(
const TAS_CarryChainList_t& carryChainList,
t_direct_inf** pvpr_directArray,
int* pvpr_directCount ) const
{
bool ok = true;
*pvpr_directArray = 0;
*pvpr_directCount = static_cast< int >( carryChainList.GetLength( ));
if( ok && ( *pvpr_directCount > 0 ))
{
*pvpr_directArray = static_cast< t_direct_inf* >( TC_calloc( *pvpr_directCount, sizeof( t_direct_inf )));
ok = ( pvpr_directArray ? true : false );
}
if( ok && ( *pvpr_directCount > 0 ))
{
for( size_t i = 0; i < carryChainList.GetLength( ); ++i )
{
const TAS_CarryChain_c& carryChain = *carryChainList[i];
( *pvpr_directArray )[i].name = TC_strdup( carryChain.srName );
( *pvpr_directArray )[i].from_pin = TC_strdup( carryChain.srFromPinName );
( *pvpr_directArray )[i].to_pin = TC_strdup( carryChain.srToPinName );
( *pvpr_directArray )[i].x_offset = carryChain.offset.dx;
( *pvpr_directArray )[i].y_offset = carryChain.offset.dy;
( *pvpr_directArray )[i].z_offset = carryChain.offset.dz;
}
}
return( ok );
}
//===========================================================================//
// Method : PokePbType_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
// 07/23/13 jeffr : Added support for calling "PokePower_()" method
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokePbType_(
const TAS_PhysicalBlock_c& physicalBlock,
const t_mode* pvpr_mode,
t_pb_type* pvpr_pb_type ) const
{
bool ok = true;
pvpr_pb_type->parent_mode = const_cast< t_mode* >( pvpr_mode );
if( pvpr_mode && pvpr_mode->parent_pb_type )
{
pvpr_pb_type->depth = pvpr_mode->parent_pb_type->depth + 1;
pvpr_pb_type->name = TC_strdup( physicalBlock.srName );
}
else
{
pvpr_pb_type->depth = 0;
}
if( pvpr_mode )
{
pvpr_pb_type->num_pb = physicalBlock.numPB;
}
else
{
pvpr_pb_type->num_pb = 1;
}
if( physicalBlock.srModelName.length( ))
{
string srModelName = ( physicalBlock.modelType == TAS_PHYSICAL_BLOCK_MODEL_STANDARD ?
"" : ".subckt " );
srModelName += TC_strdup( physicalBlock.srModelName );
pvpr_pb_type->blif_model = TC_strdup( srModelName );
}
if( physicalBlock.classType != TAS_CLASS_UNDEFINED )
{
pvpr_pb_type->class_type = this->FindClassType_( physicalBlock.classType );
}
pvpr_pb_type->max_internal_delay = UNDEFINED;
pvpr_pb_type->pb_type_power = static_cast< t_pb_type_power* >( TC_calloc( 1, sizeof( t_pb_type_power )));
pvpr_pb_type->pb_type_power->estimation_method = this->FindPowerMethodMode_( physicalBlock.power.estimateMethod,
pvpr_pb_type );
// [VPR] Process ports
this->PokePortList_( physicalBlock, pvpr_pb_type );
// [VPR] Determine if this is a leaf or container pb_type
if( pvpr_pb_type->blif_model )
{
// [VPR] Process delay and capacitance annotations
this->PokeTimingDelayLists_( physicalBlock.timingDelayLists,
&pvpr_pb_type->annotations,
&pvpr_pb_type->num_annotations );
// [VPR] If leaf is special known class, then read class lib, else treat as primitive
if( pvpr_pb_type->class_type == LUT_CLASS )
{
this->PokePbTypeLutClass_( pvpr_pb_type );
}
else if( pvpr_pb_type->class_type == MEMORY_CLASS )
{
this->PokePbTypeMemoryClass_( pvpr_pb_type );
}
else
{
pvpr_pb_type->num_modes = 0;
}
}
else
{
// [VPR] Process modes
ok = this->PokeModeList_( physicalBlock, pvpr_pb_type );
}
// [VPR] Process power (optional)
if( pvpr_pb_type->pb_type_power )
{
ok = this->PokePower_( physicalBlock, pvpr_pb_type );
}
return( ok );
}
//===========================================================================//
// Method : PokePbTypeChild_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokePbTypeChild_(
const t_pb_type& vpr_pb_type,
const string& srChildName,
t_pb_type* pvpr_pb_type ) const
{
pvpr_pb_type->name = TC_strdup( srChildName );
pvpr_pb_type->blif_model = TC_strdup( vpr_pb_type.blif_model );
pvpr_pb_type->class_type = vpr_pb_type.class_type;
pvpr_pb_type->depth = vpr_pb_type.depth;
pvpr_pb_type->model = vpr_pb_type.model;
pvpr_pb_type->modes = 0;
pvpr_pb_type->num_modes = 0;
pvpr_pb_type->num_clock_pins = vpr_pb_type.num_clock_pins;
pvpr_pb_type->num_input_pins = vpr_pb_type.num_input_pins;
pvpr_pb_type->num_output_pins = vpr_pb_type.num_output_pins;
pvpr_pb_type->num_pb = 1;
pvpr_pb_type->pb_type_power = static_cast< t_pb_type_power* >( TC_calloc( 1, sizeof( t_pb_type_power )));
pvpr_pb_type->pb_type_power->estimation_method = this->InheritPowerMethodMode_( vpr_pb_type.pb_type_power->estimation_method);
pvpr_pb_type->num_ports = vpr_pb_type.num_ports;
pvpr_pb_type->ports = static_cast< t_port* >( TC_calloc( pvpr_pb_type->num_ports, sizeof( t_port )));
for( int i = 0; i < vpr_pb_type.num_ports; ++i )
{
pvpr_pb_type->ports[i].name = TC_strdup( vpr_pb_type.ports[i].name );
pvpr_pb_type->ports[i].parent_pb_type = pvpr_pb_type;
pvpr_pb_type->ports[i].type = vpr_pb_type.ports[i].type;
pvpr_pb_type->ports[i].num_pins = vpr_pb_type.ports[i].num_pins;
pvpr_pb_type->ports[i].model_port = vpr_pb_type.ports[i].model_port;
pvpr_pb_type->ports[i].port_class = TC_strdup( vpr_pb_type.ports[i].port_class );
pvpr_pb_type->ports[i].port_power = static_cast< t_port_power* >( TC_calloc( 1, sizeof( t_port_power )));
if( pvpr_pb_type->pb_type_power->estimation_method == POWER_METHOD_AUTO_SIZES )
{
pvpr_pb_type->ports[i].port_power->wire_type = POWER_WIRE_TYPE_AUTO;
pvpr_pb_type->ports[i].port_power->buffer_type = POWER_BUFFER_TYPE_AUTO;
}
else if( pvpr_pb_type->pb_type_power->estimation_method == POWER_METHOD_SPECIFY_SIZES )
{
pvpr_pb_type->ports[i].port_power->wire_type = POWER_WIRE_TYPE_IGNORED;
pvpr_pb_type->ports[i].port_power->buffer_type = POWER_BUFFER_TYPE_NONE;
}
pvpr_pb_type->ports[i].is_clock = vpr_pb_type.ports[i].is_clock;
}
pvpr_pb_type->max_internal_delay = vpr_pb_type.max_internal_delay;
pvpr_pb_type->num_annotations = vpr_pb_type.num_annotations;
pvpr_pb_type->annotations = static_cast< t_pin_to_pin_annotation* >( TC_calloc( pvpr_pb_type->num_annotations, sizeof( t_pin_to_pin_annotation )));
for( int i = 0; i < pvpr_pb_type->num_annotations; ++i )
{
t_pin_to_pin_annotation* pvpr_annotation = &( pvpr_pb_type->annotations )[i];
pvpr_annotation->type = vpr_pb_type.annotations[i].type;
pvpr_annotation->format = vpr_pb_type.annotations[i].format;
pvpr_annotation->num_value_prop_pairs = vpr_pb_type.annotations[i].num_value_prop_pairs;
pvpr_annotation->prop = static_cast< int* >( TC_calloc( pvpr_annotation->num_value_prop_pairs, sizeof( int )));
pvpr_annotation->value = static_cast< char** >( TC_calloc( pvpr_annotation->num_value_prop_pairs, sizeof( char* )));
for( int j = 0; j < vpr_pb_type.annotations[i].num_value_prop_pairs; ++j )
{
pvpr_annotation->prop[j] = vpr_pb_type.annotations[i].prop[j];
pvpr_annotation->value[j] = TC_strdup( vpr_pb_type.annotations[i].value[j] );
}
string srDot = strstr( vpr_pb_type.annotations[i].input_pins, "." );
pvpr_annotation->input_pins = static_cast< char* >( TC_calloc( srChildName.length( ) + srDot.length( ) + 1, sizeof( char )));
pvpr_annotation->input_pins[0] = 0;
strcat( pvpr_annotation->input_pins, srChildName.data( ));
strcat( pvpr_annotation->input_pins, srDot.data( ));
if( vpr_pb_type.annotations[i].output_pins )
{
srDot = strstr( vpr_pb_type.annotations[i].output_pins, "." );
pvpr_annotation->output_pins = static_cast< char* >( TC_calloc( srChildName.length( ) + srDot.length( ) + 1, sizeof( char )));
pvpr_annotation->output_pins[0] = 0;
strcat( pvpr_annotation->output_pins, srChildName.data( ));
strcat( pvpr_annotation->output_pins, srDot.data( ));
}
else
{
pvpr_annotation->output_pins = 0;
}
pvpr_annotation->clock = TC_strdup( vpr_pb_type.annotations[i].clock );
pvpr_annotation->line_num = 0;
}
}
//===========================================================================//
// Method : PokePbTypeLutClass_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
// 07/10/13 jeffr : Fixed code to properly initialize first interconnect type
// (was using COMPLETE_INTERC, now using DIRECT_INTERC)
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokePbTypeLutClass_(
t_pb_type* pvpr_pb_type ) const
{
string srLutName(( strcmp( pvpr_pb_type->name, "lut" ) != 0 ) ? "lut" : "lut_child" );
t_port* pinPort = (( strcmp( pvpr_pb_type->ports[0].port_class, "lut_in" ) == 0 ) ?
&pvpr_pb_type->ports[0] : &pvpr_pb_type->ports[1] );
t_port* poutPort = (( strcmp( pvpr_pb_type->ports[0].port_class, "lut_in" ) == 0 ) ?
&pvpr_pb_type->ports[1] : &pvpr_pb_type->ports[0] );
pvpr_pb_type->num_modes = 2;
pvpr_pb_type->modes = static_cast< t_mode* >( TC_calloc( pvpr_pb_type->num_modes, sizeof( t_mode )));
pvpr_pb_type->pb_type_power->leakage_default_mode = 1;
// [VPR] First mode, route_through
pvpr_pb_type->modes[0].name = TC_strdup( "wire" );
pvpr_pb_type->modes[0].parent_pb_type = pvpr_pb_type;
pvpr_pb_type->modes[0].index = 0;
pvpr_pb_type->modes[0].mode_power = static_cast< t_mode_power* >( TC_calloc( 1, sizeof( t_mode_power )));
pvpr_pb_type->modes[0].num_pb_type_children = 0;
pvpr_pb_type->modes[0].num_interconnect = 1;
pvpr_pb_type->modes[0].interconnect = static_cast< t_interconnect* >( TC_calloc( 1, sizeof( t_interconnect )));
t_interconnect* pvpr_interconnect0 = &pvpr_pb_type->modes[0].interconnect[0];
pvpr_interconnect0->type = COMPLETE_INTERC;
pvpr_interconnect0->name = static_cast< char* >( TC_calloc( strlen( pvpr_pb_type->name ) + 10, sizeof( char )));
pvpr_interconnect0->input_string = static_cast< char* >( TC_calloc( strlen( pvpr_pb_type->name ) + strlen( pinPort->name ) + 2, sizeof( char )));
pvpr_interconnect0->output_string = static_cast< char* >( TC_calloc( strlen( pvpr_pb_type->name ) + strlen( poutPort->name ) + 2, sizeof( char )));
sprintf( pvpr_interconnect0->name, "complete:%s", pvpr_pb_type->name );
sprintf( pvpr_interconnect0->input_string, "%s.%s", pvpr_pb_type->name, pinPort->name );
sprintf( pvpr_interconnect0->output_string, "%s.%s", pvpr_pb_type->name, poutPort->name );
pvpr_interconnect0->parent_mode_index = 0;
pvpr_interconnect0->parent_mode = &pvpr_pb_type->modes[0];
pvpr_interconnect0->interconnect_power = static_cast< t_interconnect_power* >( TC_calloc( 1, sizeof( t_interconnect_power )));
pvpr_interconnect0->num_annotations = pvpr_pb_type->num_annotations;
pvpr_interconnect0->annotations = static_cast< t_pin_to_pin_annotation* >( TC_calloc( pvpr_interconnect0->num_annotations, sizeof( t_pin_to_pin_annotation )));
for( int i = 0; i < pvpr_interconnect0->num_annotations; ++i )
{
t_pin_to_pin_annotation* pvpr_annotation = &pvpr_interconnect0->annotations[i];
pvpr_annotation->type = pvpr_pb_type->annotations[i].type;
pvpr_annotation->format = pvpr_pb_type->annotations[i].format;
pvpr_annotation->num_value_prop_pairs = pvpr_pb_type->annotations[i].num_value_prop_pairs;
pvpr_annotation->prop = static_cast< int* >( TC_calloc( pvpr_annotation->num_value_prop_pairs, sizeof( int )));
pvpr_annotation->value = static_cast< char** >( TC_calloc( pvpr_annotation->num_value_prop_pairs, sizeof( char* )));
for( int j = 0; j < pvpr_pb_type->annotations[i].num_value_prop_pairs; ++j )
{
pvpr_annotation->prop[j] = pvpr_pb_type->annotations[i].prop[j];
pvpr_annotation->value[j] = TC_strdup( pvpr_pb_type->annotations[i].value[j] );
}
pvpr_annotation->input_pins = TC_strdup( pvpr_pb_type->annotations[i].input_pins );
pvpr_annotation->output_pins = TC_strdup( pvpr_pb_type->annotations[i].output_pins );
pvpr_annotation->clock = TC_strdup( pvpr_pb_type->annotations[i].clock );
pvpr_annotation->line_num = 0;
}
// [VPR] Second mode, LUT
pvpr_pb_type->modes[1].name = TC_strdup( pvpr_pb_type->name );
pvpr_pb_type->modes[1].parent_pb_type = pvpr_pb_type;
pvpr_pb_type->modes[1].index = 1;
pvpr_pb_type->modes[1].mode_power = static_cast< t_mode_power* >( TC_calloc( 1, sizeof( t_mode_power )));
pvpr_pb_type->modes[1].num_pb_type_children = 1;
pvpr_pb_type->modes[1].pb_type_children = static_cast< t_pb_type* >( TC_calloc( 1, sizeof( t_pb_type )));
this->PokePbTypeChild_( *pvpr_pb_type, srLutName.data( ),
pvpr_pb_type->modes[1].pb_type_children );
for( int i = 0; i < pvpr_pb_type->num_annotations; ++i )
{
for( int j = 0; j < pvpr_pb_type->annotations[i].num_value_prop_pairs; ++j )
{
free( pvpr_pb_type->annotations[i].value[j] );
}
free( pvpr_pb_type->annotations[i].value );
free( pvpr_pb_type->annotations[i].prop );
if( pvpr_pb_type->annotations[i].input_pins )
{
free( pvpr_pb_type->annotations[i].input_pins );
}
if( pvpr_pb_type->annotations[i].output_pins )
{
free( pvpr_pb_type->annotations[i].output_pins );
}
if( pvpr_pb_type->annotations[i].clock )
{
free( pvpr_pb_type->annotations[i].clock );
}
}
pvpr_pb_type->num_annotations = 0;
free( pvpr_pb_type->annotations );
pvpr_pb_type->annotations = 0;
pvpr_pb_type->modes[1].pb_type_children[0].depth = pvpr_pb_type->depth + 1;
pvpr_pb_type->modes[1].pb_type_children[0].parent_mode = &pvpr_pb_type->modes[1];
pvpr_pb_type->modes[1].num_interconnect = 2;
pvpr_pb_type->modes[1].interconnect = static_cast< t_interconnect* >( TC_calloc( 2, sizeof( t_interconnect )));
pvpr_interconnect0 = &pvpr_pb_type->modes[1].interconnect[0];
pvpr_interconnect0->type = DIRECT_INTERC;
pvpr_interconnect0->name = static_cast< char* >( TC_calloc( strlen( pvpr_pb_type->name ) + 10, sizeof( char )));
pvpr_interconnect0->input_string = static_cast< char* >( TC_calloc( strlen( pvpr_pb_type->name ) + strlen( pinPort->name ) + 2, sizeof( char )));
pvpr_interconnect0->output_string = static_cast< char* >( TC_calloc( srLutName.length( ) + strlen( pinPort->name ) + 2, sizeof( char )));
sprintf( pvpr_interconnect0->name, "direct:%s", pvpr_pb_type->name );
sprintf( pvpr_interconnect0->input_string, "%s.%s", pvpr_pb_type->name, pinPort->name );
sprintf( pvpr_interconnect0->output_string, "%s.%s", srLutName.data( ), pinPort->name );
pvpr_interconnect0->infer_annotations = static_cast< boolean >( true );
pvpr_interconnect0->parent_mode_index = 1;
pvpr_interconnect0->parent_mode = &pvpr_pb_type->modes[1];
pvpr_interconnect0->interconnect_power = static_cast< t_interconnect_power* >( TC_calloc( 1, sizeof( t_interconnect_power )));
t_interconnect* pvpr_interconnect1 = &pvpr_pb_type->modes[1].interconnect[1];
pvpr_interconnect1->type = DIRECT_INTERC;
pvpr_interconnect1->name = static_cast< char* >( TC_calloc( strlen( pvpr_pb_type->name ) + 11, sizeof( char )));
pvpr_interconnect1->input_string = static_cast< char* >( TC_calloc( srLutName.length( ) + strlen( poutPort->name ) + 4, sizeof( char )));
pvpr_interconnect1->output_string = static_cast< char* >( TC_calloc( strlen( pvpr_pb_type->name ) + strlen( poutPort->name ) + strlen( pinPort->name ) + 2, sizeof( char )));
sprintf( pvpr_interconnect1->name, "direct:%s", pvpr_pb_type->name );
sprintf( pvpr_interconnect1->input_string, "%s.%s", srLutName.data( ), poutPort->name );
sprintf( pvpr_interconnect1->output_string, "%s.%s", pvpr_pb_type->name, poutPort->name );
pvpr_interconnect1->infer_annotations = static_cast< boolean >( true );
pvpr_interconnect1->parent_mode_index = 1;
pvpr_interconnect1->parent_mode = &pvpr_pb_type->modes[1];
pvpr_interconnect1->interconnect_power = static_cast< t_interconnect_power* >( TC_calloc( 1, sizeof( t_interconnect_power )));
free( pvpr_pb_type->blif_model );
pvpr_pb_type->blif_model = 0;
pvpr_pb_type->model = 0;
}
//===========================================================================//
// Method : PokePbTypeMemoryClass_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokePbTypeMemoryClass_(
t_pb_type* pvpr_pb_type ) const
{
string srMemoryName(( strcmp( pvpr_pb_type->name, "memory_slice" ) != 0 ) ?
"memory_slice" : "memory_slice_1bit" );
pvpr_pb_type->modes = static_cast< t_mode* >( TC_calloc( 1, sizeof( t_mode )));
t_mode* pvpr_mode = &pvpr_pb_type->modes[0];
pvpr_mode->name = TC_strdup( srMemoryName );
pvpr_mode->parent_pb_type = pvpr_pb_type;
pvpr_mode->index = 0;
pvpr_mode->mode_power = static_cast< t_mode_power* >( TC_calloc( 1, sizeof( t_mode_power )));
int num_pb = OPEN;
for( int i = 0; i < pvpr_pb_type->num_ports; ++i )
{
if( pvpr_pb_type->ports[i].port_class &&
strstr( pvpr_pb_type->ports[i].port_class, "data" ) == pvpr_pb_type->ports[i].port_class )
{
if( num_pb == OPEN )
{
num_pb = pvpr_pb_type->ports[i].num_pins;
}
}
}
pvpr_mode->num_pb_type_children = 1;
pvpr_mode->pb_type_children = static_cast< t_pb_type* >( TC_calloc( 1, sizeof( t_pb_type )));
this->PokePbTypeChild_( *pvpr_pb_type, srMemoryName.data( ),
&pvpr_mode->pb_type_children[0] );
pvpr_mode->pb_type_children[0].depth = pvpr_pb_type->depth + 1;
pvpr_mode->pb_type_children[0].parent_mode = &pvpr_pb_type->modes[0];
pvpr_mode->pb_type_children[0].num_pb = num_pb;
pvpr_pb_type->num_modes = 1;
pvpr_pb_type->blif_model = 0;
pvpr_pb_type->model = 0;
pvpr_mode->num_interconnect = pvpr_pb_type->num_ports * num_pb;
pvpr_mode->interconnect = static_cast< t_interconnect* >( TC_calloc( pvpr_mode->num_interconnect, sizeof( t_interconnect )));
for( int i = 0; i < pvpr_mode->num_interconnect; ++i )
{
pvpr_mode->interconnect[i].parent_mode_index = 0;
pvpr_mode->interconnect[i].parent_mode = &pvpr_pb_type->modes[0];
}
// [VPR] Process interconnect
int index = 0;
for( int i = 0; i < pvpr_pb_type->num_ports; ++i )
{
t_interconnect* pvpr_interconnect = &pvpr_mode->interconnect[index];
pvpr_interconnect->type = DIRECT_INTERC;
string srInputPortName( pvpr_pb_type->ports[i].name );
string srOutputPortName( pvpr_pb_type->ports[i].name );
string srInputName(( pvpr_pb_type->ports[i].type == IN_PORT ) ? pvpr_pb_type->name : srMemoryName );
string srOutputName(( pvpr_pb_type->ports[i].type == IN_PORT ) ? srMemoryName : pvpr_pb_type->name );
if( pvpr_pb_type->ports[i].port_class &&
strstr( pvpr_pb_type->ports[i].port_class, "data" ) == pvpr_pb_type->ports[i].port_class )
{
pvpr_interconnect = &( pvpr_mode->interconnect )[index];
pvpr_interconnect->name = static_cast< char* >( TC_calloc( index / 10 + 8, sizeof( char )));
sprintf( pvpr_interconnect->name, "direct%d", index );
if( pvpr_pb_type->ports[i].type == IN_PORT )
{
// [VPR] Force data pins to be one bit wide and update stats
pvpr_mode->pb_type_children[0].ports[i].num_pins = 1;
pvpr_mode->pb_type_children[0].num_input_pins -= ( pvpr_pb_type->ports[i].num_pins - 1 );
pvpr_interconnect->input_string = static_cast< char* >( TC_calloc( srInputName.length( ) + srInputPortName.length( ) + 2, sizeof( char )));
pvpr_interconnect->output_string = static_cast< char* >( TC_calloc( srOutputName.length( ) + srOutputPortName.length( ) + 2 * ( 6 + num_pb / 10 ), sizeof( char )));
sprintf( pvpr_interconnect->input_string, "%s.%s", srInputName.data( ), srInputPortName.data( ));
sprintf( pvpr_interconnect->output_string, "%s[%d:0].%s", srOutputName.data( ), num_pb - 1, srOutputPortName.data( ));
}
else
{
// [VPR] Force data pins to be one bit wide and update stats
pvpr_mode->pb_type_children[0].ports[i].num_pins = 1;
pvpr_mode->pb_type_children[0].num_output_pins -= ( pvpr_pb_type->ports[i].num_pins - 1 );
pvpr_interconnect->input_string = static_cast< char* >( TC_calloc( srInputName.length( ) + srInputPortName.length( ) + 2 * ( 6 + num_pb / 10 ), sizeof( char )));
pvpr_interconnect->output_string = static_cast< char* >( TC_calloc( srOutputName.length( ) + srOutputPortName.length( ) + 2, sizeof( char )));
sprintf( pvpr_interconnect->input_string, "%s[%d:0].%s", srInputName.data( ), num_pb - 1, srInputPortName.data( ));
sprintf( pvpr_interconnect->output_string, "%s.%s", srOutputName.data( ), srOutputPortName.data( ));
}
pvpr_interconnect->interconnect_power = static_cast< t_interconnect_power* >( TC_calloc( 1, sizeof( t_interconnect_power )));
++index;
}
else
{
for( int j = 0; j < num_pb; ++j )
{
pvpr_interconnect = &( pvpr_mode->interconnect )[index];
pvpr_interconnect->name = static_cast< char* >( TC_calloc( index / 10 + j / 10 + 10, sizeof( char )));
sprintf( pvpr_interconnect->name, "direct%d_%d", index, j );
if( pvpr_pb_type->ports[i].type == IN_PORT )
{
pvpr_interconnect->type = DIRECT_INTERC;
pvpr_interconnect->input_string = static_cast< char* >( TC_calloc( srInputName.length( ) + srInputPortName.length( ) + 2, sizeof( char )));
pvpr_interconnect->output_string = static_cast< char* >( TC_calloc( srOutputName.length( ) + srOutputPortName.length( ) + 2 * ( 6 + num_pb / 10 ), sizeof( char )));
sprintf( pvpr_interconnect->input_string, "%s.%s", srInputName.data( ), srInputPortName.data( ));
sprintf( pvpr_interconnect->output_string, "%s[%d:%d].%s", srOutputName.data( ), j, j, srOutputPortName.data( ));
}
else
{
pvpr_interconnect->type = DIRECT_INTERC;
pvpr_interconnect->input_string = static_cast< char* >( TC_calloc( srInputName.length( ) + srInputPortName.length( ) + 2 * ( 6 + num_pb / 10 ), sizeof( char )));
pvpr_interconnect->output_string = static_cast< char* >( TC_calloc( srOutputName.length( ) + srOutputPortName.length( ) + 2, sizeof( char )));
sprintf( pvpr_interconnect->input_string, "%s[%d:%d].%s", srInputName.data( ), j, j, srInputPortName.data( ));
sprintf( pvpr_interconnect->output_string, "%s.%s", srOutputName.data( ), srOutputPortName.data( ));
}
pvpr_interconnect->interconnect_power = static_cast< t_interconnect_power* >( TC_calloc( 1, sizeof( t_interconnect_power )));
++index;
}
}
}
pvpr_mode->num_interconnect = index;
}
//===========================================================================//
// Method : PokeModeList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokeModeList_(
const TAS_PhysicalBlock_c& physicalBlock,
t_pb_type* pvpr_pb_type ) const
{
bool ok = true;
// [VPR] Process modes
if( physicalBlock.modeList.IsValid( ))
{
const TAS_ModeList_t& modeList = physicalBlock.modeList;
pvpr_pb_type->num_modes = static_cast< int >( modeList.GetLength( ));
pvpr_pb_type->modes = static_cast< t_mode* >( TC_calloc( pvpr_pb_type->num_modes, sizeof( t_mode )));
for( size_t i = 0; i < modeList.GetLength( ); ++i )
{
pvpr_pb_type->modes[i].parent_pb_type = pvpr_pb_type;
pvpr_pb_type->modes[i].index = static_cast< int >( i );
ok = this->PokeMode_( modeList[i]->srName,
modeList[i]->physicalBlockList,
modeList[i]->interconnectList,
&( pvpr_pb_type->modes[i] ));
if( !ok )
break;
}
}
else
{
// [VPR] Implied one mode
pvpr_pb_type->num_modes = 1;
pvpr_pb_type->modes = static_cast< t_mode* >( TC_calloc( pvpr_pb_type->num_modes, sizeof( t_mode )));
pvpr_pb_type->modes[0].parent_pb_type = pvpr_pb_type;
pvpr_pb_type->modes[0].index = 0;
ok = this->PokeMode_( physicalBlock.srName,
physicalBlock.physicalBlockList,
physicalBlock.interconnectList,
&( pvpr_pb_type->modes[0] ));
}
pvpr_pb_type->pb_type_power->leakage_default_mode = 0;
return( ok );
}
//===========================================================================//
// Method : PokeMode_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokeMode_(
const string& srName,
const TAS_PhysicalBlockList_t& physicalBlockList,
const TAS_InterconnectList_t& interconnectList,
t_mode* pvpr_mode ) const
{
bool ok = true;
pvpr_mode->name = TC_strdup( srName );
if( physicalBlockList.IsValid( ))
{
pvpr_mode->num_pb_type_children = static_cast< int >( physicalBlockList.GetLength( ));
pvpr_mode->pb_type_children = static_cast< t_pb_type* >( TC_calloc( pvpr_mode->num_pb_type_children, sizeof( t_pb_type )));
for( size_t i = 0; i < physicalBlockList.GetLength( ); ++i )
{
const TAS_PhysicalBlock_c& physicalBlock = *physicalBlockList[i];
ok = this->PokePbType_( physicalBlock, pvpr_mode,
&pvpr_mode->pb_type_children[i] );
if( !ok )
break;
}
}
else
{
pvpr_mode->num_pb_type_children = 0;
pvpr_mode->pb_type_children = 0;
}
t_mode_power* pvpr_mode_power = 0;
pvpr_mode_power = static_cast< t_mode_power* >( TC_calloc( 1, sizeof( t_mode_power )));
pvpr_mode->mode_power = pvpr_mode_power;
if( interconnectList.IsValid( ))
{
this->PokeInterconnectList_( interconnectList, pvpr_mode );
}
return( ok );
}
//===========================================================================//
// Method : PokeInterconnectList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokeInterconnectList_(
const TAS_InterconnectList_t& interconnectList,
t_mode* pvpr_mode ) const
{
pvpr_mode->num_interconnect = static_cast< int >( interconnectList.GetLength( ));
pvpr_mode->interconnect = static_cast< t_interconnect* >( TC_calloc( pvpr_mode->num_interconnect, sizeof( t_interconnect )));
int index = 0;
for( size_t i = 0; i < interconnectList.GetLength( ); ++i )
{
const TAS_Interconnect_c& interconnect = *interconnectList[i];
if( interconnect.mapType != TAS_INTERCONNECT_MAP_COMPLETE )
continue;
pvpr_mode->interconnect[index].parent_mode_index = pvpr_mode->index;
this->PokeInterconnect_( interconnect,
pvpr_mode,
&pvpr_mode->interconnect[index] );
++index;
}
for( size_t i = 0; i < interconnectList.GetLength( ); ++i )
{
const TAS_Interconnect_c& interconnect = *interconnectList[i];
if( interconnect.mapType != TAS_INTERCONNECT_MAP_DIRECT )
continue;
pvpr_mode->interconnect[index].parent_mode_index = pvpr_mode->index;
this->PokeInterconnect_( interconnect,
pvpr_mode,
&pvpr_mode->interconnect[index] );
++index;
}
for( size_t i = 0; i < interconnectList.GetLength( ); ++i )
{
const TAS_Interconnect_c& interconnect = *interconnectList[i];
if( interconnect.mapType != TAS_INTERCONNECT_MAP_MUX )
continue;
pvpr_mode->interconnect[index].parent_mode_index = pvpr_mode->index;
this->PokeInterconnect_( interconnect,
pvpr_mode,
&pvpr_mode->interconnect[index] );
++index;
}
}
//===========================================================================//
// Method : PokeInterconnect_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
// 08/09/13 jeffr : Added support for inititalizing "parent_mode" fields
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokeInterconnect_(
const TAS_Interconnect_c& interconnect,
t_mode* pvpr_mode,
t_interconnect* pvpr_interconnect ) const
{
pvpr_interconnect->name = TC_strdup( interconnect.srName );
pvpr_interconnect->type = this->FindInterconnectMapType_( interconnect.mapType );
string srInputNameList;
interconnect.inputNameList.ExtractString( &srInputNameList, false );
pvpr_interconnect->input_string = TC_strdup( srInputNameList );
string srOutputNameList;
interconnect.outputNameList.ExtractString( &srOutputNameList, false );
pvpr_interconnect->output_string = TC_strdup( srOutputNameList );
this->PokeTimingDelayLists_( interconnect.timingDelayLists,
&pvpr_interconnect->annotations,
&pvpr_interconnect->num_annotations );
pvpr_interconnect->parent_mode_index = pvpr_mode->index;
pvpr_interconnect->parent_mode = pvpr_mode;
t_interconnect_power* pvpr_interconnect_power = 0;
pvpr_interconnect_power = static_cast< t_interconnect_power* >( TC_calloc( 1, sizeof( t_interconnect_power )));
pvpr_interconnect_power->port_info_initialized = static_cast< boolean >( false );
pvpr_interconnect->interconnect_power = pvpr_interconnect_power;
pvpr_interconnect->line_num = 0;
}
//===========================================================================//
// Method : PokeFc_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
// 07/10/13 jeffr : Added support for "PokeFcPinList_()" method
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokeFc_(
const TAS_PhysicalBlock_c& physicalBlock,
t_type_descriptor* pvpr_physicalBlock ) const
{
bool ok = true;
TAS_ConnectionBoxType_t fcInType = physicalBlock.fcIn.type;
float fcInVal = -1.0;
switch( fcInType )
{
case TAS_CONNECTION_BOX_FRACTION:
fcInVal = static_cast< float >( physicalBlock.fcIn.percent );
break;
case TAS_CONNECTION_BOX_ABSOLUTE:
fcInVal = static_cast< float >( physicalBlock.fcIn.absolute );
break;
case TAS_CONNECTION_BOX_FULL:
break;
case TAS_CONNECTION_BOX_UNDEFINED:
break;
}
TAS_ConnectionBoxType_t fcOutType = physicalBlock.fcOut.type;
float fcOutVal = -1.0;
switch( physicalBlock.fcOut.type )
{
case TAS_CONNECTION_BOX_FRACTION:
fcOutVal = static_cast< float >( physicalBlock.fcOut.percent );
break;
case TAS_CONNECTION_BOX_ABSOLUTE:
fcOutVal = static_cast< float >( physicalBlock.fcOut.absolute );
break;
case TAS_CONNECTION_BOX_FULL:
fcOutVal = 0.0;
break;
case TAS_CONNECTION_BOX_UNDEFINED:
break;
}
pvpr_physicalBlock->is_Fc_frac = static_cast< boolean* >( TC_calloc( pvpr_physicalBlock->num_pins, sizeof( boolean )));
pvpr_physicalBlock->is_Fc_full_flex = static_cast< boolean* >( TC_calloc( pvpr_physicalBlock->num_pins, sizeof( boolean )));
pvpr_physicalBlock->Fc = static_cast< float* >( TC_calloc( pvpr_physicalBlock->num_pins, sizeof( float )));
for( int i = 0; i < pvpr_physicalBlock->num_pins; ++i )
{
int numClass = pvpr_physicalBlock->pin_class[i];
if( pvpr_physicalBlock->class_inf[numClass].type == DRIVER )
{
pvpr_physicalBlock->Fc[i] = fcOutVal;
pvpr_physicalBlock->is_Fc_full_flex[i] = fcOutType == TAS_CONNECTION_BOX_FULL ?
static_cast< boolean >( true ) : static_cast< boolean >( false );
pvpr_physicalBlock->is_Fc_frac[i] = fcOutType == TAS_CONNECTION_BOX_FRACTION ?
static_cast< boolean >( true ) : static_cast< boolean >( false );
}
else if( pvpr_physicalBlock->class_inf[numClass].type == RECEIVER )
{
pvpr_physicalBlock->Fc[i] = fcInVal;
pvpr_physicalBlock->is_Fc_full_flex[i] = fcInType == TAS_CONNECTION_BOX_FULL ?
static_cast< boolean >( true ) : static_cast< boolean >( false );
pvpr_physicalBlock->is_Fc_frac[i] = fcInType == TAS_CONNECTION_BOX_FRACTION ?
static_cast< boolean >( true ) : static_cast< boolean >( false );
}
else
{
pvpr_physicalBlock->Fc[i] = -1.0;
pvpr_physicalBlock->is_Fc_full_flex[i] = static_cast< boolean >( false );
pvpr_physicalBlock->is_Fc_frac[i] = static_cast< boolean >( false );
}
}
if( physicalBlock.fcPinList.IsValid( ))
{
ok = this->PokeFcPinList_( physicalBlock.fcPinList,
pvpr_physicalBlock );
}
return( ok );
}
//===========================================================================//
// Method : PokeFcPinList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/13 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokeFcPinList_(
const TAS_ConnectionFcList_t& fcPinList,
t_type_descriptor* pvpr_physicalBlock ) const
{
bool ok = true;
// Override any pin-specific fc constraints
for( size_t i = 0; i < fcPinList.GetLength( ); ++i )
{
const TAS_ConnectionFc_c& fcPin = *fcPinList[i];
ok = this->PokeFcPin_( fcPin, pvpr_physicalBlock );
if( !ok )
break;
}
return( ok );
}
//===========================================================================//
// Method : PokeFcPin_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/13 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokeFcPin_(
const TAS_ConnectionFc_c& fcPin,
t_type_descriptor* pvpr_physicalBlock ) const
{
bool ok = true;
// Extract pin-specific fc port name and indices (optional), type and value
string srPortName;
size_t pinIndex_i, pinIndex_j;
TC_ParseStringNameIndices( fcPin.srName, &srPortName, &pinIndex_i, &pinIndex_j );
TAS_ConnectionBoxType_t fcType = fcPin.type;
float fcVal = 0.0;
if( fcType == TAS_CONNECTION_BOX_FRACTION )
{
fcVal = static_cast< float >( fcPin.percent );
}
if( fcType == TAS_CONNECTION_BOX_ABSOLUTE )
{
fcVal = static_cast< float >( fcPin.absolute );
}
// Find child pin (if possible) in VPR's physical block (ie. t_type_descriptor)
bool foundPort = false;
int pinIndex = 0;
for( int i = 0; i < pvpr_physicalBlock->pb_type->num_ports; ++i )
{
if( strcmp( srPortName.data( ), pvpr_physicalBlock->pb_type->ports[i].name ) == 0 )
{
int pinOffset_i = 0;
int pinOffset_j = pvpr_physicalBlock->pb_type->ports[i].num_pins - 1;
if(( pinIndex_i != SIZE_MAX ) && ( pinIndex_j != SIZE_MAX ))
{
pinOffset_i = static_cast< int >( TCT_Min( pinIndex_i, pinIndex_j ));
pinOffset_j = static_cast< int >( TCT_Max( pinIndex_i, pinIndex_j ));
pinOffset_j = static_cast< int >( TCT_Min( pinOffset_j, pvpr_physicalBlock->pb_type->ports[i].num_pins - 1 ));
}
for( int pinOffset = pinOffset_i; pinOffset <= pinOffset_j; ++pinOffset )
{
int j = pinIndex + pinOffset;
pvpr_physicalBlock->Fc[j] = fcVal;
pvpr_physicalBlock->is_Fc_full_flex[j] = fcType == TAS_CONNECTION_BOX_FULL ?
static_cast< boolean >( true ) : static_cast< boolean >( false );
pvpr_physicalBlock->is_Fc_frac[j] = fcType == TAS_CONNECTION_BOX_FRACTION ?
static_cast< boolean >( true ) : static_cast< boolean >( false );
}
foundPort = true;
break;
}
else
{
// Advance pin index if no matching pin name
pinIndex += pvpr_physicalBlock->pb_type->ports[i].num_pins;
}
}
if( !foundPort )
{
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
ok = printHandler.Error( "Invalid architecture model pb_type fc override detected!\n"
"%sPin name \"%s\" not found in physical block \"%s\".\n",
TIO_PREFIX_ERROR_SPACE,
TIO_SR_STR( srPortName ),
TIO_PSZ_STR( pvpr_physicalBlock->name ));
}
return( ok );
}
//===========================================================================//
// Method : PokePinAssignList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokePinAssignList_(
const TAS_PinAssignList_t& pinAssignList,
t_type_descriptor* pvpr_physicalBlock ) const
{
// [VPR] Alloc and clear pin locations
int width = static_cast< int >( pvpr_physicalBlock->width );
int height = static_cast< int >( pvpr_physicalBlock->height );
int num_pins = static_cast< int >( pvpr_physicalBlock->num_pins );
pvpr_physicalBlock->pinloc = static_cast< int**** >( TC_calloc( width, sizeof( int** )));
for( int i = 0; i < width; ++i )
{
pvpr_physicalBlock->pinloc[i] = static_cast< int*** >( TC_calloc( height, sizeof( int* )));
for( int j = 0; j < pvpr_physicalBlock->height; ++j )
{
pvpr_physicalBlock->pinloc[i][j] = static_cast< int** >( TC_calloc( 4, sizeof( int* )));
for( int side = 0; side < 4; ++side )
{
pvpr_physicalBlock->pinloc[i][j][side] = static_cast< int* >( TC_calloc( num_pins, sizeof( int )));
for( int pin = 0; pin < num_pins; ++pin )
{
pvpr_physicalBlock->pinloc[i][j][side][pin] = 0;
}
}
}
}
pvpr_physicalBlock->pin_width = static_cast< int* >( TC_calloc( pvpr_physicalBlock->num_pins, sizeof( int )));
pvpr_physicalBlock->pin_height = static_cast< int* >( TC_calloc( pvpr_physicalBlock->num_pins, sizeof( int )));
pvpr_physicalBlock->pin_loc_assignments = static_cast< char***** >( TC_calloc( width, sizeof( char**** )));
pvpr_physicalBlock->num_pin_loc_assignments = static_cast< int*** >( TC_calloc( width, sizeof( int** )));
for( int i = 0; i < width; ++i )
{
pvpr_physicalBlock->pin_loc_assignments[i] = static_cast< char**** >( TC_calloc( height, sizeof( char*** )));
pvpr_physicalBlock->num_pin_loc_assignments[i] = static_cast< int** >( TC_calloc( height, sizeof( int* )));
for( int j = 0; j < height; ++j )
{
pvpr_physicalBlock->pin_loc_assignments[i][j] = static_cast< char*** >( TC_calloc( 4, sizeof( char** )));
pvpr_physicalBlock->num_pin_loc_assignments[i][j] = static_cast< int* >( TC_calloc( 4, sizeof( int )));
}
}
if( pinAssignList.IsValid( ))
{
const TAS_PinAssign_c& pinAssign = *pinAssignList[0];
pvpr_physicalBlock->pin_location_distribution = this->FindPinAssignPatternType_( pinAssign.pattern );
}
if( pvpr_physicalBlock->pin_location_distribution == E_CUSTOM_PIN_DISTR )
{
for( size_t i = 0; i < pinAssignList.GetLength( ); ++i )
{
const TAS_PinAssign_c& pinAssign = *pinAssignList[i];
int offset = pinAssign.offset;
int side = this->FindSideMode_( pinAssign.side );
int len = static_cast< int >( pinAssign.portNameList.GetLength( ));
pvpr_physicalBlock->num_pin_loc_assignments[0][offset][side] = len;
pvpr_physicalBlock->pin_loc_assignments[0][offset][side] = static_cast< char** >( TC_calloc( len, sizeof( char* )));
for( size_t port = 0; port < pinAssign.portNameList.GetLength( ); ++port )
{
const TC_Name_c& portName = *pinAssign.portNameList[port];
pvpr_physicalBlock->pin_loc_assignments[0][offset][side][port] = TC_strdup( portName.GetName( ));
}
}
}
// [VPR] Setup pin classes
const t_pb_type& vpr_pb_type = *pvpr_physicalBlock->pb_type;
int numClass = 0;
for( int i = 0; i < vpr_pb_type.num_ports; ++i )
{
if( vpr_pb_type.ports[i].equivalent )
{
numClass += pvpr_physicalBlock->capacity;
}
else
{
numClass += pvpr_physicalBlock->capacity * vpr_pb_type.ports[i].num_pins;
}
}
pvpr_physicalBlock->num_class = numClass;
pvpr_physicalBlock->class_inf = static_cast< t_class* >( TC_calloc( numClass, sizeof( t_class )));
int numPins = pvpr_physicalBlock->capacity * pvpr_physicalBlock->num_pins;
pvpr_physicalBlock->pin_class = static_cast< int* >( TC_calloc( numPins, sizeof( int )));
pvpr_physicalBlock->is_global_pin = static_cast< boolean* >( TC_calloc( numPins, sizeof( boolean )));
for( int i = 0; i < numPins; ++i )
{
pvpr_physicalBlock->pin_class[i] = OPEN;
pvpr_physicalBlock->is_global_pin[i] = static_cast< boolean >( OPEN != 0 ? true : false );
}
// [VPR] Equivalent pins share the same class, non-equivalent pins belong to different pin classes
t_class* pvpr_class_inf = pvpr_physicalBlock->class_inf;
numClass = 0;
numPins = 0;
for( int i = 0; i < pvpr_physicalBlock->capacity; ++i )
{
for( int j = 0; j < vpr_pb_type.num_ports; ++j )
{
if( vpr_pb_type.ports[j].equivalent )
{
pvpr_class_inf[numClass].num_pins = vpr_pb_type.ports[j].num_pins;
pvpr_class_inf[numClass].pinlist = static_cast< int* >( TC_calloc( pvpr_class_inf[numClass].num_pins, sizeof( int )));
}
for( int k = 0; k < vpr_pb_type.ports[j].num_pins; ++k )
{
if( !vpr_pb_type.ports[j].equivalent )
{
pvpr_class_inf[numClass].num_pins = 1;
pvpr_class_inf[numClass].pinlist = static_cast< int* >( TC_calloc( 1, sizeof( int )));
pvpr_class_inf[numClass].pinlist[0] = numPins;
}
else
{
pvpr_class_inf[numClass].pinlist[k] = numPins;
}
if( vpr_pb_type.ports[j].type == IN_PORT )
{
pvpr_class_inf[numClass].type = RECEIVER;
}
else
{
pvpr_class_inf[numClass].type = DRIVER;
}
pvpr_physicalBlock->pin_class[numPins] = numClass;
if( vpr_pb_type.ports[j].is_clock || vpr_pb_type.ports[j].is_non_clock_global )
{
pvpr_physicalBlock->is_global_pin[numPins] = static_cast< boolean >( true );
}
else
{
pvpr_physicalBlock->is_global_pin[numPins] = static_cast< boolean >( false );
}
++numPins;
if( !vpr_pb_type.ports[j].equivalent )
{
++numClass;
}
}
if( vpr_pb_type.ports[j].equivalent )
{
++numClass;
}
}
}
}
//===========================================================================//
// Method : PokeGridAssignList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokeGridAssignList_(
const TAS_GridAssignList_t& gridAssignList,
t_type_descriptor* pvpr_physicalBlock ) const
{
if( gridAssignList.IsValid( ))
{
pvpr_physicalBlock->num_grid_loc_def = static_cast< int >( gridAssignList.GetLength( ));
pvpr_physicalBlock->grid_loc_def = static_cast< t_grid_loc_def* >( TC_calloc( pvpr_physicalBlock->num_grid_loc_def, sizeof( t_grid_loc_def )));
}
for( size_t i = 0; i < gridAssignList.GetLength( ); ++i )
{
const TAS_GridAssign_c& gridAssign = *gridAssignList[i];
if( gridAssign.distr != TAS_GRID_ASSIGN_DISTR_UNDEFINED )
{
pvpr_physicalBlock->grid_loc_def[i].grid_loc_type = this->FindGridAssignDistrMode_( gridAssign.distr );
switch( gridAssign.distr )
{
case TAS_GRID_ASSIGN_DISTR_SINGLE:
pvpr_physicalBlock->grid_loc_def[i].col_rel = static_cast< float >( gridAssign.singlePercent );
break;
case TAS_GRID_ASSIGN_DISTR_MULTIPLE:
pvpr_physicalBlock->grid_loc_def[i].start_col = gridAssign.multipleStart;
pvpr_physicalBlock->grid_loc_def[i].repeat = gridAssign.multipleRepeat;
break;
case TAS_GRID_ASSIGN_DISTR_FILL:
FILL_TYPE = pvpr_physicalBlock;
break;
case TAS_GRID_ASSIGN_DISTR_PERIMETER:
// assert( IO_TYPE == pvpr_physicalBlock );
break;
case TAS_GRID_ASSIGN_DISTR_UNDEFINED:
break;
}
if( gridAssign.priority > 0 )
{
pvpr_physicalBlock->grid_loc_def[i].priority = gridAssign.priority;
}
else
{
pvpr_physicalBlock->grid_loc_def[i].priority = 1;
}
}
}
}
//===========================================================================//
// Method : PokePortList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokePortList_(
const TAS_PhysicalBlock_c& physicalBlock,
t_pb_type* pvpr_pb_type ) const
{
const TLO_PortList_t& portList = physicalBlock.portList;
pvpr_pb_type->num_ports = static_cast< int >( portList.GetLength( ));
pvpr_pb_type->ports = static_cast< t_port* >( TC_calloc( pvpr_pb_type->num_ports, sizeof( t_port )));
pvpr_pb_type->num_clock_pins = 0;
pvpr_pb_type->num_input_pins = 0;
pvpr_pb_type->num_output_pins = 0;
int index = 0;
for( size_t i = 0; i < portList.GetLength( ); ++i )
{
const TLO_Port_c& port = *portList[i];
if( port.GetType( ) != TC_TYPE_INPUT )
continue;
this->PokePort_( physicalBlock, port,
pvpr_pb_type, &pvpr_pb_type->ports[index] );
pvpr_pb_type->num_input_pins += pvpr_pb_type->ports[index].num_pins;
pvpr_pb_type->ports[index].parent_pb_type = pvpr_pb_type;
pvpr_pb_type->ports[index].index = index;
pvpr_pb_type->ports[index].port_index_by_type = 0;
++index;
}
for( size_t i = 0; i < portList.GetLength( ); ++i )
{
const TLO_Port_c& port = *portList[i];
if( port.GetType( ) != TC_TYPE_OUTPUT )
continue;
this->PokePort_( physicalBlock, port,
pvpr_pb_type, &pvpr_pb_type->ports[index] );
pvpr_pb_type->num_output_pins += pvpr_pb_type->ports[index].num_pins;
pvpr_pb_type->ports[index].parent_pb_type = pvpr_pb_type;
pvpr_pb_type->ports[index].index = index;
pvpr_pb_type->ports[index].port_index_by_type = 0;
++index;
}
for( size_t i = 0; i < portList.GetLength( ); ++i )
{
const TLO_Port_c& port = *portList[i];
if( port.GetType( ) != TC_TYPE_CLOCK )
continue;
this->PokePort_( physicalBlock, port,
pvpr_pb_type, &pvpr_pb_type->ports[index] );
pvpr_pb_type->num_clock_pins += pvpr_pb_type->ports[index].num_pins;
pvpr_pb_type->ports[index].parent_pb_type = pvpr_pb_type;
pvpr_pb_type->ports[index].index = index;
pvpr_pb_type->ports[index].port_index_by_type = 0;
++index;
}
}
//===========================================================================//
// Method : PokePort_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
// 07/23/13 jeffr : Added support for calling "PokePortPower_()" method
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokePort_(
const TAS_PhysicalBlock_c& physicalBlock,
const TLO_Port_c& port,
t_pb_type* pvpr_pb_type,
t_port* pvpr_port ) const
{
pvpr_port->name = TC_strdup( port.GetName( ));
if( port.GetClass( ))
{
pvpr_port->port_class = TC_strdup( port.GetClass( ));
}
pvpr_port->equivalent = static_cast< boolean >( port.IsEquivalent( ));
pvpr_port->num_pins = static_cast< int >( port.GetCount( ));
if( port.GetType( ) == TC_TYPE_INPUT )
{
pvpr_port->type = IN_PORT;
pvpr_port->is_clock = static_cast< boolean >( false );
}
if( port.GetType( ) == TC_TYPE_OUTPUT )
{
pvpr_port->type = OUT_PORT;
pvpr_port->is_clock = static_cast< boolean >( false );
}
if( port.GetType( ) == TC_TYPE_CLOCK )
{
pvpr_port->type = IN_PORT;
pvpr_port->is_clock = static_cast< boolean >( true );
}
pvpr_port->port_power = static_cast< t_port_power* >( TC_calloc( 1, sizeof( t_port_power )));
const TLO_Power_c& portPower = port.GetPower( );
if( portPower.IsValid( ))
{
this->PokePortPower_( physicalBlock, portPower,
pvpr_pb_type, pvpr_port->port_power );
}
}
//===========================================================================//
// Method : PokePortPower_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/17/13 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokePortPower_(
const TAS_PhysicalBlock_c& physicalBlock,
const TLO_Power_c& portPower,
t_pb_type* pvpr_pb_type,
t_port_power* pvpr_port_power ) const
{
// Initialize port power defaults
t_power_estimation_method powerMethod = POWER_METHOD_UNDEFINED;
powerMethod = this->FindPowerMethodMode_( physicalBlock.power.estimateMethod,
pvpr_pb_type );
if( powerMethod == POWER_METHOD_AUTO_SIZES )
{
pvpr_port_power->wire_type = POWER_WIRE_TYPE_AUTO;
pvpr_port_power->buffer_type = POWER_BUFFER_TYPE_AUTO;
}
else if( powerMethod == POWER_METHOD_SPECIFY_SIZES )
{
pvpr_port_power->wire_type = POWER_WIRE_TYPE_IGNORED;
pvpr_port_power->buffer_type = POWER_BUFFER_TYPE_NONE;
}
TLO_PowerType_t wireType = TLO_POWER_TYPE_UNDEFINED;
double wireCap = 0.0;
double wireRelativeLength = 0.0;
double wireAbsoluteLength = 0.0;
portPower.GetWire( &wireType, &wireCap, &wireRelativeLength, &wireAbsoluteLength );
switch( wireType )
{
case TLO_POWER_TYPE_CAP:
// Process wire capacitance value
if(( powerMethod == POWER_METHOD_AUTO_SIZES ) ||
( powerMethod == POWER_METHOD_SPECIFY_SIZES ))
{
pvpr_port_power->wire_type = POWER_WIRE_TYPE_C;
pvpr_port_power->wire.C = static_cast< float >( wireCap );
}
break;
case TLO_POWER_TYPE_RELATIVE_LENGTH:
// Process wire relative length value
if(( powerMethod == POWER_METHOD_AUTO_SIZES ) ||
( powerMethod == POWER_METHOD_SPECIFY_SIZES ))
{
pvpr_port_power->wire_type = POWER_WIRE_TYPE_RELATIVE_LENGTH;
pvpr_port_power->wire.relative_length = static_cast< float >( wireRelativeLength );
}
break;
case TLO_POWER_TYPE_ABSOLUTE_LENGTH:
// Process wire absolute length value
if( TCTF_IsGT( wireAbsoluteLength, 0.0 ))
{
pvpr_port_power->wire_type = POWER_WIRE_TYPE_ABSOLUTE_LENGTH;
pvpr_port_power->wire.absolute_length = static_cast< float >( wireAbsoluteLength );
}
else
{
pvpr_port_power->wire_type = POWER_WIRE_TYPE_AUTO;
pvpr_port_power->wire.absolute_length = 0.0;
}
break;
default:
break;
}
TLO_PowerType_t bufferType = TLO_POWER_TYPE_UNDEFINED;
double bufferAbsoluteSize = 0.0;
portPower.GetBuffer( &bufferType, &bufferAbsoluteSize );
switch( bufferType )
{
case TLO_POWER_TYPE_ABSOLUTE_SIZE:
// Process buffer absolute size value
if( TCTF_IsGT( bufferAbsoluteSize, 0.0 ))
{
pvpr_port_power->buffer_type = POWER_BUFFER_TYPE_ABSOLUTE_SIZE;
pvpr_port_power->buffer_size = static_cast< float >( bufferAbsoluteSize );
}
else
{
pvpr_port_power->buffer_type = POWER_BUFFER_TYPE_AUTO;
pvpr_port_power->buffer_size = 0.0;
}
break;
default:
break;
}
}
//===========================================================================//
// Method : PokeTimingDelayLists_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokeTimingDelayLists_(
const TAS_TimingDelayLists_c& timingDelayLists,
t_pin_to_pin_annotation** pvpr_annotationArray,
int* pvpr_annotationCount ) const
{
const TAS_TimingDelayList_t& delayList = timingDelayLists.delayList;
const TAS_TimingDelayList_t& delayMatrixList = timingDelayLists.delayMatrixList;
const TAS_TimingDelayList_t& tSetupList = timingDelayLists.tSetupList;
const TAS_TimingDelayList_t& tHoldList = timingDelayLists.tHoldList;
const TAS_TimingDelayList_t& clockToQList = timingDelayLists.clockToQList;
const TAS_TimingDelayList_t& capList = timingDelayLists.capList;
const TAS_TimingDelayList_t& capMatrixList = timingDelayLists.capMatrixList;
const TAS_TimingDelayList_t& packPatternList = timingDelayLists.packPatternList;
*pvpr_annotationCount = static_cast< int >( delayList.GetLength( ) +
delayMatrixList.GetLength( ) +
tSetupList.GetLength( ) +
tHoldList.GetLength( ) +
clockToQList.GetLength( ) +
capList.GetLength( ) +
capMatrixList.GetLength( ) +
packPatternList.GetLength( ));
*pvpr_annotationArray = static_cast< t_pin_to_pin_annotation* >( TC_calloc( *pvpr_annotationCount, sizeof( t_pin_to_pin_annotation )));
int index = 0;
for( size_t i = 0; i < delayList.GetLength( ); ++i )
{
const TAS_TimingDelay_c& delayConstant = *delayList[i];
this->PokeTimingDelay_( delayConstant,
&( *pvpr_annotationArray )[index] );
++index;
}
for( size_t i = 0; i < delayMatrixList.GetLength( ); ++i )
{
const TAS_TimingDelay_c& delayMatrix = *delayMatrixList[i];
this->PokeTimingDelay_( delayMatrix,
&( *pvpr_annotationArray )[index] );
++index;
}
for( size_t i = 0; i < tSetupList.GetLength( ); ++i )
{
const TAS_TimingDelay_c& tSetup = *tSetupList[i];
this->PokeTimingDelay_( tSetup,
&( *pvpr_annotationArray )[index] );
++index;
}
for( size_t i = 0; i < tHoldList.GetLength( ); ++i )
{
const TAS_TimingDelay_c& tHold = *tHoldList[i];
this->PokeTimingDelay_( tHold,
&( *pvpr_annotationArray )[index] );
++index;
}
for( size_t i = 0; i < clockToQList.GetLength( ); ++i )
{
const TAS_TimingDelay_c& clockToQ = *clockToQList[i];
this->PokeTimingDelay_( clockToQ,
&( *pvpr_annotationArray )[index] );
++index;
}
for( size_t i = 0; i < capList.GetLength( ); ++i )
{
const TAS_TimingDelay_c& capConstant = *capList[i];
this->PokeTimingDelay_( capConstant,
&( *pvpr_annotationArray )[index] );
++index;
}
for( size_t i = 0; i < capMatrixList.GetLength( ); ++i )
{
const TAS_TimingDelay_c& capMatrix = *capMatrixList[i];
this->PokeTimingDelay_( capMatrix,
&( *pvpr_annotationArray )[index] );
++index;
}
for( size_t i = 0; i < packPatternList.GetLength( ); ++i )
{
const TAS_TimingDelay_c& packPattern = *packPatternList[i];
this->PokeTimingDelay_( packPattern,
&( *pvpr_annotationArray )[index] );
++index;
}
}
//===========================================================================//
// Method : PokeTimingDelay_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
void TVPR_ArchitectureSpec_c::PokeTimingDelay_(
const TAS_TimingDelay_c& timingDelay,
t_pin_to_pin_annotation* pvpr_annotation ) const
{
TC_MinGrid_c& MinGrid = TC_MinGrid_c::GetInstance( );
unsigned int precision = MinGrid.GetPrecision( );
char szValueMin[TIO_FORMAT_STRING_LEN_DATA];
memset( szValueMin, 0, sizeof( szValueMin ));
sprintf( szValueMin, "%0.*e", precision + 1, timingDelay.valueMin );
char szValueMax[TIO_FORMAT_STRING_LEN_DATA];
memset( szValueMax, 0, sizeof( szValueMax ));
sprintf( szValueMax, "%0.*e", precision + 1, timingDelay.valueMax );
char szValueNom[TIO_FORMAT_STRING_LEN_DATA];
memset( szValueNom, 0, sizeof( szValueNom ));
sprintf( szValueNom, "%0.*e", precision + 1, timingDelay.valueNom );
string srDelayMatrix, srCapMatrix;
timingDelay.valueMatrix.ExtractString( TC_DATA_EXP, &srDelayMatrix, precision + 1, SIZE_MAX, 0 );
timingDelay.valueMatrix.ExtractString( TC_DATA_FLOAT, &srCapMatrix, precision, SIZE_MAX, 0 );
size_t i = 0;
size_t valueCt = ( TCTF_IsGT( timingDelay.valueMin, 0.0 ) &&
TCTF_IsGT( timingDelay.valueMax, 0.0 ) ?
2 : 1 );
pvpr_annotation->num_value_prop_pairs = static_cast< int >( valueCt );
pvpr_annotation->prop = static_cast< int* >( TC_calloc( valueCt, sizeof( int )));
pvpr_annotation->value = static_cast< char** >( TC_calloc( valueCt, sizeof( char* )));
switch( timingDelay.mode )
{
case TAS_TIMING_MODE_DELAY_CONSTANT:
pvpr_annotation->type = E_ANNOT_PIN_TO_PIN_DELAY;
pvpr_annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
if( TCTF_IsGT( timingDelay.valueMax, 0.0 ))
{
pvpr_annotation->prop[i] = E_ANNOT_PIN_TO_PIN_DELAY_MAX;
pvpr_annotation->value[i] = TC_strdup( szValueMax );
++i;
}
if( TCTF_IsGT( timingDelay.valueMin, 0.0 ))
{
pvpr_annotation->prop[i] = E_ANNOT_PIN_TO_PIN_DELAY_MIN;
pvpr_annotation->value[i] = TC_strdup( szValueMin );
}
pvpr_annotation->input_pins = TC_strdup( timingDelay.srInputPortName );
pvpr_annotation->output_pins = TC_strdup( timingDelay.srOutputPortName );
break;
case TAS_TIMING_MODE_DELAY_MATRIX:
pvpr_annotation->type = E_ANNOT_PIN_TO_PIN_DELAY;
pvpr_annotation->format = E_ANNOT_PIN_TO_PIN_MATRIX;
pvpr_annotation->prop[0] = ( timingDelay.type == TAS_TIMING_TYPE_MAX_MATRIX ?
E_ANNOT_PIN_TO_PIN_DELAY_MAX :
E_ANNOT_PIN_TO_PIN_DELAY_MIN );
pvpr_annotation->value[0] = TC_strdup( srDelayMatrix );
pvpr_annotation->input_pins = TC_strdup( timingDelay.srInputPortName );
pvpr_annotation->output_pins = TC_strdup( timingDelay.srOutputPortName );
break;
case TAS_TIMING_MODE_T_SETUP:
pvpr_annotation->type = E_ANNOT_PIN_TO_PIN_DELAY;
pvpr_annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
pvpr_annotation->prop[0] = E_ANNOT_PIN_TO_PIN_DELAY_TSETUP;
pvpr_annotation->value[0] = TC_strdup( szValueNom );
pvpr_annotation->input_pins = TC_strdup( timingDelay.srInputPortName );
pvpr_annotation->clock = TC_strdup( timingDelay.srClockPortName );
break;
case TAS_TIMING_MODE_T_HOLD:
pvpr_annotation->type = E_ANNOT_PIN_TO_PIN_DELAY;
pvpr_annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
pvpr_annotation->prop[0] = E_ANNOT_PIN_TO_PIN_DELAY_THOLD;
pvpr_annotation->value[0] = TC_strdup( szValueNom );
pvpr_annotation->input_pins = TC_strdup( timingDelay.srInputPortName );
pvpr_annotation->clock = TC_strdup( timingDelay.srClockPortName );
break;
case TAS_TIMING_MODE_CLOCK_TO_Q:
pvpr_annotation->type = E_ANNOT_PIN_TO_PIN_DELAY;
pvpr_annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
if( TCTF_IsGT( timingDelay.valueMax, 0.0 ))
{
pvpr_annotation->prop[i] = E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MAX;
pvpr_annotation->value[i] = TC_strdup( szValueMax );
++i;
}
if( TCTF_IsGT( timingDelay.valueMin, 0.0 ))
{
pvpr_annotation->prop[i] = E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MIN;
pvpr_annotation->value[i] = TC_strdup( szValueMin );
}
pvpr_annotation->input_pins = TC_strdup( timingDelay.srOutputPortName );
pvpr_annotation->clock = TC_strdup( timingDelay.srClockPortName );
break;
case TAS_TIMING_MODE_CAP_CONSTANT:
pvpr_annotation->type = E_ANNOT_PIN_TO_PIN_CAPACITANCE;
pvpr_annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
pvpr_annotation->prop[0] = E_ANNOT_PIN_TO_PIN_CAPACITANCE_C;
pvpr_annotation->value[0] = TC_strdup( szValueMax );
pvpr_annotation->input_pins = TC_strdup( timingDelay.srInputPortName );
pvpr_annotation->output_pins = TC_strdup( timingDelay.srOutputPortName );
break;
case TAS_TIMING_MODE_CAP_MATRIX:
pvpr_annotation->type = E_ANNOT_PIN_TO_PIN_CAPACITANCE;
pvpr_annotation->format = E_ANNOT_PIN_TO_PIN_MATRIX;
pvpr_annotation->prop[0] = E_ANNOT_PIN_TO_PIN_CAPACITANCE_C;
pvpr_annotation->value[0] = TC_strdup( srCapMatrix );
pvpr_annotation->input_pins = TC_strdup( timingDelay.srInputPortName );
pvpr_annotation->output_pins = TC_strdup( timingDelay.srOutputPortName );
break;
case TAS_TIMING_MODE_PACK_PATTERN:
pvpr_annotation->type = E_ANNOT_PIN_TO_PIN_PACK_PATTERN;
pvpr_annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
pvpr_annotation->prop[0] = E_ANNOT_PIN_TO_PIN_PACK_PATTERN_NAME;
pvpr_annotation->value[0] = TC_strdup( timingDelay.srPackPatternName );
pvpr_annotation->input_pins = TC_strdup( timingDelay.srInputPortName );
pvpr_annotation->output_pins = TC_strdup( timingDelay.srOutputPortName );
break;
default:
break;
}
}
//===========================================================================//
// Method : PokePower_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/17/13 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokePower_(
const TAS_PhysicalBlock_c& physicalBlock,
t_pb_type* pvpr_pb_type ) const
{
bool ok = true;
const TAS_Power_c& power = physicalBlock.power;
const TLO_PortList_t& portList = physicalBlock.portList;
t_power_estimation_method powerMethod = POWER_METHOD_UNDEFINED;
powerMethod = this->FindPowerMethodMode_( power.estimateMethod, pvpr_pb_type );
pvpr_pb_type->pb_type_power->estimation_method = powerMethod;
switch( power.estimateMethod )
{
case TAS_POWER_METHOD_PIN_TOGGLE:
pvpr_pb_type->pb_type_power->absolute_power_per_instance.leakage =
static_cast< float >( power.staticPower.absolute );
ok = this->PokePowerPortList_( power, portList, pvpr_pb_type );
break;
case TAS_POWER_METHOD_ABSOLUTE:
pvpr_pb_type->pb_type_power->absolute_power_per_instance.leakage =
static_cast< float >( power.staticPower.absolute );
pvpr_pb_type->pb_type_power->absolute_power_per_instance.dynamic =
static_cast< float >( power.dynamicPower.absolute );
break;
case TAS_POWER_METHOD_CAP_INTERNAL:
pvpr_pb_type->pb_type_power->absolute_power_per_instance.leakage =
static_cast< float >( power.staticPower.absolute );
pvpr_pb_type->pb_type_power->C_internal =
static_cast< float >( power.dynamicPower.capInternal );
break;
default:
break;
}
return( ok );
}
//===========================================================================//
// Method : PokePowerPortList_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/17/13 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokePowerPortList_(
const TAS_Power_c& power,
const TLO_PortList_t& portList,
t_pb_type* pvpr_pb_type ) const
{
bool ok = true;
for( size_t i = 0; i < power.portList.GetLength( ); ++i )
{
const TLO_Port_c& port = *power.portList[i];
ok = this->PokePowerPort_( port, portList, pvpr_pb_type );
if( !ok )
break;
}
return( ok );
}
//===========================================================================//
// Method : PokePowerPort_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/17/13 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::PokePowerPort_(
const TLO_Port_c& port,
const TLO_PortList_t& portList,
t_pb_type* pvpr_pb_type ) const
{
bool ok = true;
t_port* pvpr_port = 0;
const char* pszPortName = port.GetName( );
if( portList.Find( pszPortName ))
{
for( int i = 0; i < pvpr_pb_type->num_ports; ++i )
{
if( strcmp( pszPortName, pvpr_pb_type->ports[i].name ) == 0 )
{
pvpr_port = &pvpr_pb_type->ports[i];
break;
}
}
}
if( pvpr_port )
{
pvpr_port->port_power->scaled_by_port = pvpr_port;
string srPortName;
size_t pinIndex = 0;
TC_ParseStringNameIndex( pszPortName, &srPortName, &pinIndex );
pvpr_port->port_power->scaled_by_port_pin_idx = static_cast< int >( pinIndex );
bool initialized = false;
double energyPerToggle = 0.0;
bool scaledByStaticProb = false;
bool scaledByStaticProb_n = false;
port.GetPower( ).GetPinToggle( &initialized, &energyPerToggle,
&scaledByStaticProb, &scaledByStaticProb_n );
pvpr_port->port_power->pin_toggle_initialized = static_cast< boolean >( initialized );
pvpr_port->port_power->energy_per_toggle = static_cast< float >( energyPerToggle );
pvpr_port->port_power->reverse_scaled = static_cast< boolean >( scaledByStaticProb_n );
}
else
{
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
ok = printHandler.Error( "Invalid architecture model pb_type power detected!\n"
"%sNo port found for pin toggle \"%s\".\n",
TIO_PREFIX_ERROR_SPACE,
TIO_PSZ_STR( pszPortName ));
}
return( ok );
}
//===========================================================================//
// Method : InitModels_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::InitModels_(
const t_arch& vpr_architecture,
t_type_descriptor** pvpr_physicalBlockArray,
int vpr_physicalBlockCount ) const
{
bool ok = true;
for( int i = 0; i < vpr_physicalBlockCount; ++i )
{
if(( *pvpr_physicalBlockArray )[i].pb_type )
{
ok = this->InitPbType_( vpr_architecture,
( *pvpr_physicalBlockArray )[i].pb_type );
}
}
if( ok )
{
ok = this->ValidateModels_( vpr_architecture );
}
return( ok );
}
//===========================================================================//
// Method : InitPbType_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::InitPbType_(
const t_arch& vpr_architecture,
t_pb_type* pvpr_pb_type ) const
{
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
bool ok = true;
if( pvpr_pb_type->blif_model )
{
const char* pszBlifModelName = pvpr_pb_type->blif_model;
char delimiter = (( strstr( pszBlifModelName, ".subckt " ) == pszBlifModelName ) ? ' ' : '.' );
pszBlifModelName = strchr( pszBlifModelName, delimiter );
if( pszBlifModelName )
{
++pszBlifModelName;
}
else
{
ok = printHandler.Error( "Invalid architecture model detected!\n"
"%sUnknown BLIF model defined in pb_type \"%s\".\n",
TIO_PREFIX_ERROR_SPACE,
TIO_PSZ_STR( pvpr_pb_type->name ));
}
// [VPR] Apply two sets of models, standard library of models and user defined models
t_model* pmodel = 0;
if(( strcmp( pszBlifModelName, "input" ) == 0 ) ||
( strcmp( pszBlifModelName, "output" ) == 0 ) ||
( strcmp( pszBlifModelName, "names" ) == 0 ) ||
( strcmp( pszBlifModelName, "latch" ) == 0 ))
{
pmodel = vpr_architecture.model_library;
}
else
{
pmodel = vpr_architecture.models;
}
// [VPR] Determine which logical model to use
t_model* pvpr_model = 0;
for( ; pmodel && !pvpr_model; pmodel = pmodel->next )
{
// [VPR] Blif model always starts with .subckt, need to skip first 8 characters
if( strcmp( pszBlifModelName, pmodel->name ) == 0 )
{
pvpr_model = pmodel;
}
}
if( ok && !pvpr_model )
{
ok = printHandler.Error( "Invalid architecture model pb_type detected!\n"
"%sNo model found for pb_type \"%s\".\n",
TIO_PREFIX_ERROR_SPACE,
TIO_PSZ_STR( pvpr_pb_type->blif_model ));
}
if( ok )
{
pvpr_pb_type->model = pvpr_model;
t_linked_vptr* pvpr_pb_link = pvpr_model->pb_types;
pvpr_model->pb_types = static_cast< t_linked_vptr* >( TC_calloc( 1, sizeof( t_linked_vptr )));
pvpr_model->pb_types->next = pvpr_pb_link;
pvpr_model->pb_types->data_vptr = pvpr_pb_type;
for( int i = 0; i < pvpr_pb_type->num_ports; ++i )
{
bool foundPort = false;
for( t_model_ports* pvpr_port = pvpr_model->inputs;
pvpr_port && !foundPort ;
pvpr_port = pvpr_port->next )
{
if( strcmp( pvpr_port->name, pvpr_pb_type->ports[i].name ) == 0 )
{
if( pvpr_port->size < pvpr_pb_type->ports[i].num_pins )
{
pvpr_port->size = pvpr_pb_type->ports[i].num_pins;
}
if( pvpr_port->min_size > pvpr_pb_type->ports[i].num_pins ||
pvpr_port->min_size == -1 )
{
pvpr_port->min_size = pvpr_pb_type->ports[i].num_pins;
}
pvpr_pb_type->ports[i].model_port = pvpr_port;
foundPort = true;
}
}
for( t_model_ports* pvpr_port = pvpr_model->outputs;
pvpr_port && !foundPort ;
pvpr_port = pvpr_port->next )
{
if( strcmp( pvpr_port->name, pvpr_pb_type->ports[i].name ) == 0 )
{
if( pvpr_port->size < pvpr_pb_type->ports[i].num_pins )
{
pvpr_port->size = pvpr_pb_type->ports[i].num_pins;
}
if( pvpr_port->min_size > pvpr_pb_type->ports[i].num_pins ||
pvpr_port->min_size == -1 )
{
pvpr_port->min_size = pvpr_pb_type->ports[i].num_pins;
}
pvpr_pb_type->ports[i].model_port = pvpr_port;
foundPort = true;
}
}
if( !foundPort )
{
ok = printHandler.Error( "Invalid architecture model pb_type detected!\n"
"%sNo model port found for pb_type \"%s\" port \"%s\".\n",
TIO_PREFIX_ERROR_SPACE,
TIO_PSZ_STR( pvpr_pb_type->name ),
TIO_PSZ_STR( pvpr_pb_type->ports[i].name ));
}
}
}
}
else
{
for( int i = 0; i < pvpr_pb_type->num_modes; ++i )
{
for( int j = 0; j < pvpr_pb_type->modes[i].num_pb_type_children; ++j )
{
ok = this->InitPbType_( vpr_architecture,
&( pvpr_pb_type->modes[i].pb_type_children[j] ));
if( !ok )
break;
}
if( !ok )
break;
}
}
return( ok );
}
//===========================================================================//
// Method : ValidateModels_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::ValidateModels_(
const t_arch& vpr_architecture ) const
{
TIO_PrintHandler_c& printHandler = TIO_PrintHandler_c::GetInstance( );
bool ok = true;
const t_model* pmodel = vpr_architecture.models;
while( pmodel )
{
if( !pmodel->pb_types )
{
ok = printHandler.Error( "Invalid architecture model detected!\n"
"%sNo pb_type found for model \"%s\".\n",
TIO_PREFIX_ERROR_SPACE,
TIO_PSZ_STR( pmodel->name ));
if( !ok )
break;
}
pmodel = pmodel->next;
}
return( ok );
}
//===========================================================================//
// Method : FindSideMode_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
enum e_side TVPR_ArchitectureSpec_c::FindSideMode_(
TC_SideMode_t mode ) const
{
enum e_side mode_ = static_cast< enum e_side >( 0 );
switch( mode )
{
case TC_SIDE_LEFT: mode_ = LEFT; break;
case TC_SIDE_RIGHT: mode_ = RIGHT; break;
case TC_SIDE_LOWER:
case TC_SIDE_BOTTOM: mode_ = BOTTOM; break;
case TC_SIDE_UPPER:
case TC_SIDE_TOP: mode_ = TOP; break;
default: break;
}
return( mode_ );
}
//===========================================================================//
// Method : FindClassType_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
enum e_pb_type_class TVPR_ArchitectureSpec_c::FindClassType_(
TAS_ClassType_t type ) const
{
enum e_pb_type_class type_ = UNKNOWN_CLASS;
switch( type )
{
case TAS_CLASS_LUT: type_ = LUT_CLASS; break;
case TAS_CLASS_FLIPFLOP: type_ = LATCH_CLASS; break;
case TAS_CLASS_MEMORY: type_ = MEMORY_CLASS; break;
default: break;
}
return( type_ );
}
//===========================================================================//
// Method : FindInterconnectMapType_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
enum e_interconnect TVPR_ArchitectureSpec_c::FindInterconnectMapType_(
TAS_InterconnectMapType_t type ) const
{
enum e_interconnect type_ = static_cast< enum e_interconnect >( 0 );
switch( type )
{
case TAS_INTERCONNECT_MAP_COMPLETE: type_ = COMPLETE_INTERC; break;
case TAS_INTERCONNECT_MAP_DIRECT: type_ = DIRECT_INTERC; break;
case TAS_INTERCONNECT_MAP_MUX: type_ = MUX_INTERC; break;
case TAS_INTERCONNECT_MAP_UNDEFINED: break;
}
return( type_ );
}
//===========================================================================//
// Method : FindPinAssignPatternType_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
enum e_pin_location_distr TVPR_ArchitectureSpec_c::FindPinAssignPatternType_(
TAS_PinAssignPatternType_t type ) const
{
enum e_pin_location_distr type_ = static_cast< enum e_pin_location_distr >( 0 );
switch( type )
{
case TAS_PIN_ASSIGN_PATTERN_SPREAD: type_ = E_SPREAD_PIN_DISTR; break;
case TAS_PIN_ASSIGN_PATTERN_CUSTOM: type_ = E_CUSTOM_PIN_DISTR; break;
case TAS_PIN_ASSIGN_PATTERN_UNDEFINED: break;
}
return( type_ );
}
//===========================================================================//
// Method : FindGridAssignDistrMode_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
enum e_grid_loc_type TVPR_ArchitectureSpec_c::FindGridAssignDistrMode_(
TAS_GridAssignDistrMode_t mode ) const
{
enum e_grid_loc_type type_ = static_cast< enum e_grid_loc_type >( 0 );
switch( mode )
{
case TAS_GRID_ASSIGN_DISTR_SINGLE: type_ = COL_REL; break;
case TAS_GRID_ASSIGN_DISTR_MULTIPLE: type_ = COL_REPEAT; break;
case TAS_GRID_ASSIGN_DISTR_FILL: type_ = FILL; break;
case TAS_GRID_ASSIGN_DISTR_PERIMETER: type_ = BOUNDARY; break;
case TAS_GRID_ASSIGN_DISTR_UNDEFINED: break;
}
return( type_ );
}
//===========================================================================//
// Method : FindChannelDistrMode_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/15/12 jeffr : Original
//===========================================================================//
enum e_stat TVPR_ArchitectureSpec_c::FindChannelDistrMode_(
TAS_ChannelDistrMode_t mode ) const
{
enum e_stat mode_ = static_cast< enum e_stat >( 0 );
switch( mode )
{
case TAS_CHANNEL_DISTR_UNIFORM: mode_ = UNIFORM; break;
case TAS_CHANNEL_DISTR_GAUSSIAN: mode_ = GAUSSIAN; break;
case TAS_CHANNEL_DISTR_PULSE: mode_ = PULSE; break;
case TAS_CHANNEL_DISTR_DELTA: mode_ = DELTA; break;
case TAS_CHANNEL_DISTR_UNDEFINED: break;
}
return( mode_ );
}
//===========================================================================//
// Method : FindSwitchBoxModelType_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
enum e_switch_block_type TVPR_ArchitectureSpec_c::FindSwitchBoxModelType_(
TAS_SwitchBoxModelType_t type ) const
{
enum e_switch_block_type type_ = static_cast< enum e_switch_block_type >( 0 );
switch( type )
{
case TAS_SWITCH_BOX_MODEL_WILTON: type_ = WILTON; break;
case TAS_SWITCH_BOX_MODEL_SUBSET: type_ = SUBSET; break;
case TAS_SWITCH_BOX_MODEL_UNIVERSAL: type_ = UNIVERSAL; break;
case TAS_SWITCH_BOX_MODEL_CUSTOM: break;
case TAS_SWITCH_BOX_MODEL_UNDEFINED: break;
}
return( type_ );
}
//===========================================================================//
// Method : FindSegmentDirType_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
enum e_directionality TVPR_ArchitectureSpec_c::FindSegmentDirType_(
TAS_SegmentDirType_t type ) const
{
enum e_directionality type_ = static_cast< enum e_directionality >( 0 );
switch( type )
{
case TAS_SEGMENT_DIR_UNIDIRECTIONAL: type_ = UNI_DIRECTIONAL; break;
case TAS_SEGMENT_DIR_BIDIRECTIONAL: type_ = BI_DIRECTIONAL; break;
case TAS_SEGMENT_DIR_UNDEFINED: break;
}
return( type_ );
}
//===========================================================================//
// Method : FindSegmentBitPattern_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/10/12 jeffr : Original
//===========================================================================//
bool TVPR_ArchitectureSpec_c::FindSegmentBitPattern_(
const TAS_BitPattern_t& bitPattern,
size_t bitPatternLen,
boolean** pvpr_patternArray,
int* pvpr_patternLen ) const
{
bool ok = true;
*pvpr_patternLen = static_cast< int >( TCT_Max( bitPattern.GetLength( ), bitPatternLen ));
*pvpr_patternArray = static_cast< boolean* >( TC_calloc( *pvpr_patternLen, sizeof( boolean )));
ok = ( *pvpr_patternArray ? true : false );
if( ok )
{
for( int i = 0; i < *pvpr_patternLen; ++i )
{
( *pvpr_patternArray )[i] = static_cast< boolean >( true );
}
for( size_t i = 0; i < bitPattern.GetLength( ); ++i )
{
const TC_Bit_c& bit = *bitPattern[i];
if( bit.IsTrue( ))
{
( *pvpr_patternArray )[i] = static_cast< boolean >( true );
}
else // if( bit.IsFalse( ))
{
( *pvpr_patternArray )[i] = static_cast< boolean >( false );
}
}
}
return( ok );
}
//===========================================================================//
// Method : FindPowerMethodMode_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/17/13 jeffr : Original
//===========================================================================//
t_power_estimation_method TVPR_ArchitectureSpec_c::FindPowerMethodMode_(
TAS_PowerMethodMode_t mode,
t_pb_type* pvpr_pb_type ) const
{
t_power_estimation_method mode_ = POWER_METHOD_UNDEFINED;
switch( mode )
{
case TAS_POWER_METHOD_IGNORE: mode_ = POWER_METHOD_IGNORE; break;
case TAS_POWER_METHOD_SUM_OF_CHILDREN: mode_ = POWER_METHOD_SUM_OF_CHILDREN; break;
case TAS_POWER_METHOD_AUTO_SIZES: mode_ = POWER_METHOD_AUTO_SIZES; break;
case TAS_POWER_METHOD_SPECIFY_SIZES: mode_ = POWER_METHOD_SPECIFY_SIZES; break;
case TAS_POWER_METHOD_PIN_TOGGLE: mode_ = POWER_METHOD_TOGGLE_PINS; break;
case TAS_POWER_METHOD_CAP_INTERNAL: mode_ = POWER_METHOD_C_INTERNAL; break;
case TAS_POWER_METHOD_ABSOLUTE: mode_ = POWER_METHOD_ABSOLUTE; break;
case TAS_POWER_METHOD_UNDEFINED:
if( pvpr_pb_type->parent_mode &&
pvpr_pb_type->parent_mode->parent_pb_type &&
pvpr_pb_type->parent_mode->parent_pb_type->pb_type_power )
{
mode_ = pvpr_pb_type->parent_mode->parent_pb_type->pb_type_power->estimation_method;
}
else
{
mode_ = POWER_METHOD_AUTO_SIZES;
}
mode_ = this->InheritPowerMethodMode_( mode_ );
break;
}
return( mode_ );
}
//===========================================================================//
// Method : InheritPowerMethodMode_
// Author : Jeff Rudolph
//---------------------------------------------------------------------------//
// Version history
// 07/17/13 jeffr : Original
//===========================================================================//
t_power_estimation_method TVPR_ArchitectureSpec_c::InheritPowerMethodMode_(
t_power_estimation_method mode ) const
{
t_power_estimation_method mode_ = POWER_METHOD_UNDEFINED;
switch( mode )
{
case POWER_METHOD_IGNORE:
case POWER_METHOD_AUTO_SIZES:
case POWER_METHOD_SPECIFY_SIZES:
case POWER_METHOD_TOGGLE_PINS: mode_ = mode; break;
case POWER_METHOD_C_INTERNAL:
case POWER_METHOD_ABSOLUTE: mode_ = POWER_METHOD_IGNORE; break;
case POWER_METHOD_SUM_OF_CHILDREN: mode_ = POWER_METHOD_AUTO_SIZES; break;
default: break;
}
return( mode_ );
}