ncycles_t RowModel::Write( NVMainRequest *request, NVMDataBlock& /*oldData*/ ) { NVMAddress address = request->address; /* * The default life map is an stl map< uint64_t, uint64_t >. * You may map row and col to this map_key however you want. * It is up to you to ensure there are no collisions here. */ uint64_t row; ncycles_t rv = 0; /* * For our simple row model, we just set the key equal to the row. */ address.GetTranslatedAddress( &row, NULL, NULL, NULL, NULL, NULL ); /* * If using the default life map, we can call the DecrementLife * function which will check if the map_key already exists. If so, * the life value is decremented (write count incremented). Otherwise * the map_key is inserted with a write count of 1. */ if( !DecrementLife( row ) ) rv = -1; return rv; }
ncycles_t WordModel::Write( NVMainRequest *request, NVMDataBlock& /*oldData*/ ) { NVMAddress address = request->address; /* * The default life map is an stl map< uint64_t, uint64_t >. * You may map row and col to this map_key however you want. * It is up to you to ensure there are no collisions here. */ uint64_t row; uint64_t col; ncycles_t rv = 0; /* * For our simple row model, we just set the key equal to the row. */ address.GetTranslatedAddress( &row, &col, NULL, NULL, NULL, NULL ); /* * If using the default life map, we can call the DecrementLife * function which will check if the map_key already exists. If so, * the life value is decremented (write count incremented). Otherwise * the map_key is inserted with a write count of 1. */ uint64_t wordkey; uint64_t rowSize; uint64_t wordSize; uint64_t partitionCount; wordSize = p->BusWidth; wordSize *= p->tBURST * p->RATE; wordSize /= 8; rowSize = p->COLS * wordSize; /* * Think of each row being partitioned into 64-bit divisions (or * whatever the Bus Width is). Each row has rowSize / wordSize * paritions. For the key we will use: * * row * number of partitions + partition in this row */ partitionCount = rowSize / wordSize; wordkey = row * partitionCount + col; if( !DecrementLife( wordkey ) ) rv = -1; return rv; }
/* * Calculates a unique key for each possible unit of memory that can be * migrated. In this case, we are migrating single rows of a bank. */ uint64_t MQMigrator::GetAddressKey( NVMAddress& address ) { uint64_t row, bank, rank, subarray, channel; address.GetTranslatedAddress( &row, NULL, &bank, &rank, &channel, &subarray ); /* * We will migrate entire memory pages, therefore only the column is * irrelevant. */ return (row * numBanks * numRanks * numSubarrays * numChannels + bank * numRanks * numSubarrays * numChannels + rank * numSubarrays * numChannels + subarray * numChannels + channel); }
uint64_t MultiQueueMigrator::GetPageNumber( MQMigrator *at, NVMAddress address ) { uint64_t pageNum = at->GetAddressKey(address); if(at->IsMigrated(address)) { uint64_t channel; address.GetTranslatedAddress(NULL, NULL, NULL, NULL, &channel, NULL); uint64_t newChannel = at->GetNewChannel(address); pageNum = pageNum - channel + newChannel; } return pageNum; }
ncycles_t ByteModel::Write( NVMainRequest *request, NVMDataBlock& oldData ) { NVMDataBlock& newData = request->data; NVMAddress address = request->address; /* * The default life map is an stl map< uint64_t, uint64_t >. * You may map row and col to this map_key however you want. * It is up to you to ensure there are no collisions here. */ uint64_t row; uint64_t col; ncycles_t rv = 0; /* * For our simple row model, we just set the key equal to the row. */ address.GetTranslatedAddress( &row, &col, NULL, NULL, NULL, NULL ); /* * If using the default life map, we can call the DecrementLife * function which will check if the map_key already exists. If so, * the life value is decremented (write count incremented). Otherwise * the map_key is inserted with a write count of 1. */ uint64_t wordkey; uint64_t rowSize; uint64_t wordSize; uint64_t partitionCount; /* * wordSize is the size of a word written to memory, usually a cacheline. * This size is in bytes */ wordSize = p->BusWidth; wordSize *= p->tBURST * p->RATE; wordSize /= 8; /* Size of a row in bytes */ rowSize = p->COLS * wordSize; /* Check each byte to see if it was modified */ for( int i = (int)wordSize - 1; i >= 0; --i ) { uint8_t oldByte, newByte; oldByte = oldData.GetByte( i ); newByte = newData.GetByte( i ); if( oldByte == newByte ) continue; /* * Think of each row being partitioned into 8-bit divisions. Each * row has rowSize / 8 paritions. For the key we will use: * * row * number of partitions + partition in this row */ partitionCount = ( rowSize / 8 ); wordkey = row * partitionCount + col * wordSize + i; if( !DecrementLife( wordkey ) ) rv = -1; } return rv; }