bool dSceneGraph::HasLinkToRoot (dTreeNode* node) { int stack; char parentEdge[D_GRAPH_MAX_STACK_DEPTH]; dTreeNode* pool[D_GRAPH_MAX_STACK_DEPTH]; pool[0] = node; stack = 1; int lru = GetLRU(); node->GetInfo().SetLRU (lru); while (stack) { stack --; node = pool[stack]; if (node == m_rootNode) { return true; } int index = 0; for (index = stack - 1; (index >= 0) && parentEdge[index]; index --); if ((index >= 0) && !parentEdge[index]) { index ++; _ASSERTE (index <= stack); } for (dGraphNode::dLink::dListNode* link = node->GetInfo().m_children.GetFirst(); link; link = link->GetNext()){ dGraphNode& info = link->GetInfo()->GetInfo(); if (info.GetLRU() != lru) { info.SetLRU(lru); if (index >= 0) { pool[stack] = pool[index]; parentEdge[stack] = parentEdge[index]; pool[index] = link->GetInfo(); parentEdge[index] = 0; index ++; } else { pool[stack] = link->GetInfo(); parentEdge[stack] = 0; } stack ++; _ASSERTE (stack < (sizeof (parentEdge) / sizeof (parentEdge[0]))); } } for (dGraphNode::dLink::dListNode* link = node->GetInfo().m_parents.GetFirst(); link; link = link->GetNext()){ dGraphNode& info = link->GetInfo()->GetInfo(); if (info.GetLRU() != lru) { info.SetLRU(lru); pool[stack] = link->GetInfo(); parentEdge[stack] = 1; stack ++; _ASSERTE (stack < (sizeof (parentEdge) / sizeof (parentEdge[0]))); } } } return false; }
/*============================================================================ ** ** Function Name: Read ** ** Visibility: Public ** ** Description: Read data from the cache. On a miss, ** identifies LRU and evicts the data prior to reading data ** from next lower level memory. ** ** Invocation: By the CPU of adjecent memory hierarchy. ** ** Input Parameters: const UINT32 address, ** ** Return Values: UINT8 data ** **==========================================================================*/ UINT8 CCacheWriteThru::Read(const UINT32 address) { // Separate tag, index and offset bits UINT32 offset = GetOffsetBits(address); UINT32 index = GetIndexBits(address); UINT32 tag = GetTagBits(address); UINT32 way_to_read = WAY_INVALID; // The byte to be returned UINT8 data = 0xFF; // Starting address of a line. // Useful for reading a line from next memory hierarchy. UINT32 line_start_add; #ifdef __debug__ std::cout << std::endl << "--------------------------------------------------------" << std::endl; std::cout << " Address = " << std::hex << address << std::dec << " Set No = " << index << std::endl; #endif // Make sure sets exists if(m_sets) { // All is well way_to_read = MatchTagBits(m_sets[index], tag); if(WAY_INVALID != way_to_read) { // Cache Read hit. Yay! // Do nothing m_hits++; #ifdef __debug__ std::cout << "Cache Read Hit. " << " Way to read = " << way_to_read << std::endl; #endif } else { UINT32 empty_way = GetEmptyWay(m_sets[index]); if(empty_way != WAY_INVALID) { // The set is not full, an empty way has been found m_misses++; way_to_read = empty_way; #ifdef __debug__ std::cout << "Cache miss. Set not full. " << " Way to read = " << way_to_read << std::endl; #endif } else { // The set is full // Cache read miss m_misses++; UINT32 way_lru = GetLRU(m_sets[index]); way_to_read = way_lru; } // if(empty_way == WAY_INVALID) // Need to read new cache line from L2 (Common to Is there an empty way, Conflict / Compulsory misses) line_start_add = (m_sets[index].lines[way_to_read].tag << (m_num_offset_bits + m_num_index_bits)) | (index << m_num_offset_bits); for(UINT32 item_offset = 0; item_offset < m_line_size; item_offset++) { m_sets[index].lines[way_to_read].line_data[item_offset] = m_next_mem->Read(line_start_add + item_offset); } } // if(WAY_INVALID == way_to_read) // Get the requested byte and update the state bits data = m_sets[index].lines[way_to_read].line_data[offset]; m_sets[index].lines[way_to_read].valid = 1; m_sets[index].lines[way_to_read].tag = tag; m_num_reads++; UpdateLRU(m_sets[index],way_to_read); #ifdef __debug__ printf("Data Read = %x\n", data); std::cout << std::dec << "Stats: Total Reads = " << m_num_reads << " Total Writes = " << m_num_writes << std::endl; std::cout << "Stats: Total Hits = " << m_hits << " Total Misses = " << m_misses << std::endl; for(UINT32 item_offset = 0; item_offset < m_line_size; item_offset++) { printf("\n Line data %d = %x ", item_offset, m_sets[index].lines[way_to_read].line_data[item_offset]); } #endif } else { // Sets not allocated!! SERIOUS ERROR!!! } return data; }
/*============================================================================ ** ** Function Name: Write ** ** Visibility: Public ** ** Description: Write data into the cache. Writes through to second ** level memory to maintain inclusivity. On a miss, ** identifies LRU and evicts the data prior to reading data ** from next lower level memory ** ** Invocation: By the CPU or adjecent memory hierarchy. ** ** Input Parameters: const UINT32 address, const UINT8 data ** ** Return Values: CACHE_HM // Cache hit or miss info ** **==========================================================================*/ CACHE_HM CCacheWriteThru::Write(const UINT32 address, const UINT8 data) { CACHE_HM hm_type = CACHE_HIT; // Separate Tag, index, offset bits UINT32 offset = GetOffsetBits(address); UINT32 index = GetIndexBits(address); UINT32 tag = GetTagBits(address); UINT32 way_to_write = WAY_INVALID; // Starting address of a line. // Useful for reading a line from next memory hierarchy. UINT32 line_start_add; #ifdef __debug__ std::cout << std::endl << "--------------------------------------------------------" << std::endl; std::cout << " Address = " << std::hex << address << " Data = " << data << std::dec << " Set No = " << index << std::endl; #endif // Make sure sets exists if(m_sets) { // All is well way_to_write = MatchTagBits(m_sets[index], tag); if(WAY_INVALID != way_to_write) { // Cache write hit // Do nothing m_hits++; hm_type = CACHE_HIT; #ifdef __debug__ std::cout << "Cache Hit. " << " Way to write = " << way_to_write << std::endl; #endif } else { UINT32 empty_way = GetEmptyWay(m_sets[index]); if(empty_way != WAY_INVALID) { // The set is not full m_misses++; hm_type = CACHE_MISS; way_to_write = empty_way; #ifdef __debug__ std::cout << "Cache miss. Set not full. " << " Way to write = " << way_to_write << std::endl; #endif } else { // The set is full // Cache write miss m_misses++; hm_type = CACHE_MISS; UINT32 way_lru = GetLRU(m_sets[index]); way_to_write = way_lru; }// if(WAY_INVALID == way_to_write) // Need to read new cache line from L2. Common to compuslory and confilct misses line_start_add = (m_sets[index].lines[way_to_write].tag << (m_num_offset_bits + m_num_index_bits)) | (index << m_num_offset_bits); for(UINT32 item_offset = 0; item_offset < m_line_size; item_offset++) { m_sets[index].lines[way_to_write].line_data[item_offset] = m_next_mem->Read(line_start_add + item_offset); } } m_sets[index].lines[way_to_write].line_data[offset] = data; // Need to write to next memeory hierarchy (L2) to maintain inclusivity line_start_add = (m_sets[index].lines[way_to_write].tag << (m_num_offset_bits + m_num_index_bits)) | (index << m_num_offset_bits); // No need to write the whole line, since we write only one byte at time. m_next_mem->Write(address, data); m_sets[index].lines[way_to_write].valid = 1; m_sets[index].lines[way_to_write].tag = tag; m_num_writes++; UpdateLRU(m_sets[index],way_to_write); #ifdef __debug__ std::cout << "Stats: Total Reads = " << m_num_reads << " Total Writes = " << m_num_writes << std::endl; std::cout << "Stats: Total Hits = " << m_hits << " Total Misses = " << m_misses << std::endl; for(UINT32 item_offset = 0; item_offset < m_line_size; item_offset++) { printf("\n Line data %d = %x ", item_offset, m_sets[index].lines[way_to_write].line_data[item_offset]); } #endif } else { // Sets not allocated!! SERIOUS ERROR!!! hm_type = hm_type; } return hm_type; }
void dSceneGraph::DeleteNode (dTreeNode* node) { dList<dTreeNode*> conectedNodes; dTree<dTreeNode*, unsigned> deleteList; dGraphNode& info = node->GetInfo(); deleteList.Insert(node, node->GetKey()); while (info.m_parents.GetFirst()) { dTreeNode* const twinNode = info.m_parents.GetFirst()->GetInfo(); conectedNodes.Append (twinNode); dGraphNode& twinInfo = twinNode->GetInfo(); for (dGraphNode::dLink::dListNode* link = twinInfo.m_children.GetFirst(); link; link = link->GetNext()){ if (link->GetInfo() == node) { twinInfo.m_children.Remove (link); break; } } for (dGraphNode::dLink::dListNode* link = twinInfo.m_parents.GetFirst(); link; link = link->GetNext()){ if (link->GetInfo() == node) { twinInfo.m_parents.Remove (link); break; } } info.m_parents.Remove(info.m_parents.GetFirst()); } while (info.m_children.GetFirst()) { dTreeNode* const twinNode = info.m_children.GetFirst()->GetInfo(); conectedNodes.Append (twinNode); dGraphNode& twinInfo = twinNode->GetInfo(); for (dGraphNode::dLink::dListNode* link = twinInfo.m_children.GetFirst(); link; link = link->GetNext()){ if (link->GetInfo() == node) { twinInfo.m_children.Remove (link); break; } } for (dGraphNode::dLink::dListNode* link = twinInfo.m_parents.GetFirst(); link; link = link->GetNext()){ if (link->GetInfo() == node) { twinInfo.m_parents.Remove (link); break; } } info.m_children.Remove(info.m_children.GetFirst()); } for (dList<dTreeNode*>::dListNode* ptr = conectedNodes.GetFirst(); ptr; ptr = ptr->GetNext()){ //char parentEdge[D_GRAPH_MAX_STACK_DEPTH]; dTreeNode* pool[D_GRAPH_MAX_STACK_DEPTH]; int stack = 1; int lru = GetLRU(); pool[0] = ptr->GetInfo(); node->GetInfo().SetLRU (lru); bool listIsDangling = true; dList<dTreeNode*> danglingNodes; while (stack) { stack --; dTreeNode* const node = pool[stack]; if (node == m_rootNode) { listIsDangling = false; break; } danglingNodes.Append(node); for (dGraphNode::dLink::dListNode* link = node->GetInfo().m_children.GetFirst(); link; link = link->GetNext()){ dGraphNode& info = link->GetInfo()->GetInfo(); if (info.GetLRU() != lru) { info.SetLRU(lru); pool[stack] = link->GetInfo(); stack ++; _ASSERTE (stack < (sizeof (pool) / sizeof (pool[0]))); } } for (dGraphNode::dLink::dListNode* link = node->GetInfo().m_parents.GetFirst(); link; link = link->GetNext()){ dGraphNode& info = link->GetInfo()->GetInfo(); if (info.GetLRU() != lru) { info.SetLRU(lru); pool[stack] = link->GetInfo(); stack ++; _ASSERTE (stack < (sizeof (pool) / sizeof (pool[0]))); } } } if (listIsDangling) { for (dList<dTreeNode*>::dListNode* first = danglingNodes.GetFirst(); first; first = first->GetNext()) { deleteList.Insert(first->GetInfo(), first->GetInfo()->GetKey()); } } danglingNodes.RemoveAll(); } dTree<dTreeNode*, unsigned>::Iterator iter (deleteList); for (iter.Begin(); iter; iter ++) { dTreeNode* node = (*iter); if (Find(node->GetKey())) { dGraphNode& info = node->GetInfo(); info.m_parents.RemoveAll(); info.m_children.RemoveAll(); info.m_nodeInfo->Release(); info.m_nodeInfo = NULL; Remove (node); } } }