nvmain源码阅读记录2

指令传递

(nvmain.cpp中)bool NVMain :: IssueCommand中,预取会插入事件

    if( CheckPrefetch( request ) )
    {
        GetEventQueue()->InsertEvent( EventResponse, this, request, 
                                      GetEventQueue()->GetCurrentCycle() + 1 );

        return true;
    }

继续走孩子

mc_rv = GetChild( request )->IssueCommand( request );

nvmain的孩子是MemoryController(nvmain.cpp的SetConfig中添加子,每个通道一个内存控制器,即一个子,共通道个子;每个MemoryController实际新的是根据其内存控制器调度类型确定的)

for( int i = 0; i < channels; i++ ){
    ……
    /* Initialize memory controller */
    memoryControllers[i] = MemoryControllerFactory::CreateNewController( channelConfig[i]->GetString( "MEM_CTL" ) );
    ……
    AddChild( memoryControllers[i] );
    ……
}
MemoryController *MemoryControllerFactory::CreateNewController( std::string controller ) 
{ 
    ……
    if( controller == "FCFS" )
        memoryController = new FCFS( );
    ……
}

MemoryController的调用setConfig中,添加孩子为互连

Interconnect *memory;
……
memory->SetParent( this );
AddChild( memory );

在FCFS中,调用MemoryController的入队函数

bool FCFS::IssueCommand( NVMainRequest *request )
{
    /* Allow up to 16 read/writes outstanding. */
    if( !IsIssuable( request ) )
        return false;

    if( request->type == READ )
        mem_reads++;
    else
        mem_writes++;

    Enqueue( 0, request );

    /*
     * Return whether the request could be queued. Return false if the queue is full.
     */
    return true;
}

 该函数中先获得翻译后的地址(注意信道可能不是原始的物理地址翻译出来的信道,修改过),再推进指定transactionQueues中,(根据调度算法不同,transactionQueues个数不同,FCFS只有一个transactionQueues,而FRFCFS-WQF有读写两个transactionQueues,根据读写放进不同的transactionQueues中)

根据queueModel是PerRankQueues / PerBankQueues / PerSubArrayQueues,以及访问的地址,得到queueId

EffectivelyEmpty函数:如果命令队列为空或在下一个循环中为空,则返回true

如果commandQueues [queueId]为空或马上为空(注意不是transactionQueues)则插入事件EventCycle,时间为当前时间,这样到该事件的时候,就会唤醒这个NVMainObject的Cycle函数

void MemoryController::Enqueue( ncounter_t queueNum, NVMainRequest *request )
{
    /* Retranslate once for this channel, but leave channel the same */
    ncounter_t channel, rank, bank, row, col, subarray;

    GetDecoder( )->Translate( request->address.GetPhysicalAddress( ), 
                               &row, &col, &bank, &rank, &channel, &subarray );
    channel = request->address.GetChannel( );
    request->address.SetTranslatedAddress( row, col, bank, rank, channel, subarray );

    /* Enqueue the request. */
    assert( queueNum < transactionQueueCount );

    transactionQueues[queueNum].push_back( request );
    
    /* If this command queue is empty, we can schedule a new transaction right away. */
    ncounter_t queueId = GetCommandQueueId( request->address );

    if( EffectivelyEmpty( queueId ) )
    {
        ncycle_t nextWakeup = GetEventQueue( )->GetCurrentCycle( );

        if( GetEventQueue( )->FindEvent( EventCycle, this, NULL, nextWakeup ) == NULL )
        {
            GetEventQueue( )->InsertEvent( EventCycle, this, nextWakeup, NULL, transactionQueuePriority );
        }
    }
}

transactionQueues在FCFS的周期中被使用; FindOldestReadyRequest找到最旧的请求(该地址对应commandQueues为空的请求中最旧的)

if( !commandQueues[queueId].empty() ) continue;
void FCFS::Cycle( ncycle_t steps )
{
    NVMainRequest *nextReq = NULL;

    /* Simply get the oldest request */
    if( !FindOldestReadyRequest( transactionQueues[0], &nextReq ) )
    {
        /* No oldest ready request, check for non-activated banks. */
        (void)FindClosedBankRequest( transactionQueues[0], &nextReq );
    }

    if( nextReq != NULL )
    {
        IssueMemoryCommands( nextReq );
    }

    CycleCommandQueues( );

    MemoryController::Cycle( steps );
}

在MemoryController的IssueMemoryCommands中,根据不同情况,将指令压入commandQueues中(还可能根据情况先压入预充电等指令进commandQueues)

ScheduleCommandWake函数暂时没看懂,涉及回调

返回先到先得的周期,调用CycleCommandQueues函数

CycleCommandQueues函数看条件可能会进行(具体待看)

GetChild( )->IssueCommand( queueHead );
GetEventQueue( )->InsertEvent( EventCycle, this, nextWakeup, NULL, transactionQueuePriority );

FCFS的Cycle调用的:: Cycle(steps)可能会

GetEventQueue( )->InsertEvent( EventCycle, this, nextWakeup, NULL, transactionQueuePriority );

MemoryController的孩子是互连

memory = InterconnectFactory :: CreateInterconnect(conf-> GetString(“INTERCONNECT”));可能为OnChipBus / OffChipBus

 

OffChipBus的调用setConfig中创建子 

Rank *nextRank = RankFactory::CreateRankNoWarn( c->GetString( "RankType" ) );

 IssueCommand中传给孩子;并且检查等级切换的开销

    success = GetChild( req )->IssueCommand( req );    
    /*
     *  To preserve rank-to-rank switching time, we need to notify the
     *  other ranks what the command sent was.
     */
    if( success )
    {
        for( ncounter_t childIdx = 0; childIdx < GetChildCount( ); childIdx++ )
          if( GetChild( req ) != GetChild( childIdx ) )
            GetChild( childIdx )->Notify( req );
    }

根据RankFactory创建的为StandardRank(StandardRank.cpp)

排名的孩子为银行(DDR3Bank)

bank的子为子阵列(subArrayNum = p-> ROWS / MATHeight;所以至少还是有一个subArray)

subArray类包含endrModel和dataEncoder(/ *我们需要在子数组级别创建耐久性模型* /)

subArray不再向下传递,通过GetEventQueue() - > InsertEvent()放进事件队列

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值