bool AffinityTask::staticStrongAnalysis(const TaskSet& taskSet, Time overhead) { AffinityTask::Compare compare; std::unordered_map<AffinityTask*, Time> responseTime; Affinity allCPU; for(AffinityTask* task : taskSet) { responseTime.insert(std::pair<AffinityTask*, Time>(task, task->worstExecution)); for(auto cpu : task->affinity) allCPU.insert(cpu); } while(true) { bool changed = false; bool overflow = false; std::unordered_map<AffinityTask*, Time> newResponseTime; for(auto current : responseTime) { AffinityTask* curTask = current.first; std::set<Affinity> powerSet = AffinityTask::powerSet(curTask->affinity); Time currentResponse = responseTime.find(curTask)->second; TaskSet ignoreTask; ignoreTask.insert(curTask); Time min_sumInterfere = std::numeric_limits<Time>::max(); for(Affinity s : powerSet) { assert(s.size() != 0); Size s_Size = s.size(); //Time sumInterference = 0; std::unordered_map<CPUID, std::list<TaskSet>> possibleReplacement; for(auto cpu : s) { possibleReplacement.insert(std::pair<CPUID, std::list<TaskSet>> (cpu, std::list<TaskSet>())); } for(CPUID selectedCPU : s) { Affinity ignoreCPU(s); ignoreCPU.erase(selectedCPU); for(auto alternative : allCPU) { if(ignoreCPU.find(alternative) != ignoreCPU.end()) continue; auto allPaths = allPath(taskSet, selectedCPU, alternative, ignoreCPU, ignoreTask); for(auto path : allPaths) { if(path.size() > 0) { TaskSet ignoredTask; Affinity moreCheck; for(auto item : path) { if(item.isTask()) ignoredTask.insert(item.getTask()); else moreCheck.insert(item.getCPUID()); } TaskSet highTaskSet; for(AffinityTask* highPriorityTask : taskSet) { //if(compare(curTask, highPriorityTask)) // continue; if(highPriorityTask == curTask) continue; if(ignoredTask.find(highPriorityTask) != ignoredTask.end()) continue; bool intersect = false; for(auto cpu : highPriorityTask->affinity) { if(moreCheck.find(cpu) != moreCheck.end()) { intersect = true; break; } } if(!intersect) continue; highTaskSet.insert(highPriorityTask); } possibleReplacement.find(selectedCPU)->second.push_back(highTaskSet); } } } } for(auto possibleSet : combinePossibleTaskSet(possibleReplacement)) { Time sumInterference = 0; /* if(possibleSet.size() ==0) continue; assert(possibleSet.size() > 0); */ sumInterference += overhead; for(auto highPriorityTask : possibleSet) { Time interferenceCount = currentResponse/highPriorityTask->minPeriod; Time remaining = currentResponse % highPriorityTask->minPeriod; Time interference = interferenceCount * highPriorityTask->worstExecution + std::min(remaining, highPriorityTask->worstExecution); Time contextSwitchCount = interferenceCount; if(remaining > 0) contextSwitchCount++; sumInterference += 2*(contextSwitchCount) * overhead; if(compare(curTask, highPriorityTask)) continue; sumInterference += interference; } Time floorValue = floor((Real)sumInterference / (Real)s_Size); min_sumInterfere = std::min(min_sumInterfere, floorValue); } } assert(min_sumInterfere != std::numeric_limits<Time>::max()); Time nextResponse = curTask->worstExecution + min_sumInterfere; newResponseTime.insert(std::pair<AffinityTask*, Time>(curTask, nextResponse)); if(currentResponse != nextResponse) changed = true; if(currentResponse > curTask->minPeriod) overflow = true; } if(changed) responseTime = newResponseTime; else break; if(overflow) break; } bool possible = true; for(auto iter : responseTime) { if(iter.second > iter.first->minPeriod) { possible = false; iter.first->print_log(WARN, "Execution time: %lu, Period: %lu, Response time: %lu", iter.first->worstExecution, iter.first->minPeriod, iter.second); } else { iter.first->print_log(INFO, "Execution time: %lu, Period: %lu, Response time: %lu", iter.first->worstExecution, iter.first->minPeriod, iter.second); } } return possible; }
void TrueTimeSourceVisitor::Visit_Node( const Semantics::Node & node ) { // Setup the node name std::string kernelName = node.name(); std::string kernelInitName = kernelName + "_init"; DEBUGOUT( "\tNode: " << kernelName << std::endl ); // Must be the second pass _SchedHeaderLines.push_back( string( "// Define Schedule Offsets and Durations" ) ); _SchedHeaderLines.push_back( string( "" ) ); // Create the file name std::string filename = std::string( node.name() ) + "_init"; // Create the hyperperiod symbol string for the node std::string hyp_str = kernelName + "_HYPERPERIOD"; // Set some dictionary items for this node GetMainDictionary().SetValue( "FILENAME", filename ); GetMainDictionary().SetValue( "KERNEL_SCHEDULE", "prioFP" ); GetMainDictionary().SetFormattedValue( "KERNEL_HYPERPERIOD", "%f", (double) node.hyperperiodsecs() ); GetMainDictionary().SetValue( "NODE_HYPERPERIOD_STR", hyp_str ); DeviceSet devices = node.integrates(); for ( DeviceSet::iterator devIter = devices.begin(); devIter != devices.end(); devIter++ ) { if ( (*devIter).type() == Semantics::CommInterface::meta ) { Semantics::CommInterface ci = Semantics::CommInterface::Cast( *devIter ); Semantics::CommMedium cm = ci.commMedium(); if ( cm != Udm::null ) { string busname = cm.name(); AddSectionDictionary( "BUS_DEFINES" ); GetTemplateDictionary().SetValue( "BUSNAME", busname ); PopSectionDictionary(); } } } if ( _SchedHeaderLines.size() < 4 ) { ostringstream out; out << "#define " << hyp_str << " " << (double)node.hyperperiodsecs(); _SchedHeaderLines.push_back( out.str() ); } _already_included.clear(); // clear include list for each node // Visit all tasks assigned to this node TaskSet taskSet = node.executes(); TaskVector taskVector( taskSet.begin(), taskSet.end() ); TaskVector::iterator taskIter = taskVector.begin(); for ( ; taskIter != taskVector.end(); taskIter++ ){ // Visit the task taskIter->Accept( *this ); } // Clear the analog in/out counters _analogIn = 1; _analogOut = 1; // Set up a sorted list of IChans and OChans SortedIChan_ByChanIndex_Set ichans; SortedOChan_ByChanIndex_Set ochans; // Visit all devices contained in this node DeviceSet deviceSet = node.integrates(); DeviceSet::iterator deviceIter = deviceSet.begin(); for ( ; deviceIter != deviceSet.end(); deviceIter++ ) { // Collect all of the IChans and OChans, and keep them in the proper sorted order // See if device is input if ( Semantics::InputDevice::meta == (*deviceIter).type() ) { // Cast to an InputDevice Semantics::InputDevice input = Semantics::InputDevice::Cast( *deviceIter ); // Get the associated IChans SortedIChan_ByChanIndex_Set iChanSet = input.inputChannels_sorted( IChanIndexSorter() ); ichans.insert( iChanSet.begin(), iChanSet.end() ); } // See if device is output else if ( Semantics::OutputDevice::meta == (*deviceIter).type() ) { // Cast to an InputDevice Semantics::OutputDevice output = Semantics::OutputDevice::Cast( *deviceIter ); // Get the associated OChans SortedOChan_ByChanIndex_Set oChanSet = output.outputChannels_sorted( OChanIndexSorter() ); ochans.insert( oChanSet.begin(), oChanSet.end() ); } } // Now process the IChans and OChans in order IChanVector iChanVector( ichans.begin(), ichans.end() ); for ( IChanVector::iterator ichanIter = iChanVector.begin(); ichanIter != iChanVector.end(); ichanIter++ ) { ichanIter->Accept( *this ); } OChanVector oChanVector( ochans.begin(), ochans.end() ); for ( OChanVector::iterator ochanIter = oChanVector.begin(); ochanIter != oChanVector.end(); ochanIter++ ) { ochanIter->Accept( *this ); } // Visit all local dependencies on this node LocalDependencySet dependencySet = node.nodeLocalDeps(); LocalDependencyVector dependencyVector( dependencySet.begin(), dependencySet.end() ); LocalDependencyVector::iterator dependencyIter = dependencyVector.begin(); for ( ; dependencyIter != dependencyVector.end(); dependencyIter++ ) { // Visit the dependency dependencyIter->Accept( *this ); } // Visit the dummy dependency message on this node (if we have one) Semantics::Msg dummyMsg = node.nodeDummyMsg(); if ( dummyMsg != Udm::null ) Visit_DummyMessage( dummyMsg ); // Get the template file name std::string templateName = ConfigKeeper::inst().GetTemplatePath() + "\\truetime_src.tpl"; // Initialize the template ctemplate::Template* googleTemplate = ctemplate::Template::GetTemplate( templateName, ctemplate::DO_NOT_STRIP ); std::string output; // Expand the output into a string googleTemplate->Expand( &output, &GetMainDictionary() ); // Create the _init file for this TT kernel std::string directoryName = ConfigKeeper::inst().GetDirectoryName(); string srcfilename = directoryName + "\\" + filename + ".cpp"; ofstream initFile( srcfilename.c_str() ); // Write the generated code out to the file and close initFile << output; // Close up the file initFile.close(); // Clear out the dictionary ClearDictionary(); // Write out the header file for the defines string hdrfilename = directoryName + "\\" + filename + "_defines.h"; cout << "Writing header: " << hdrfilename << endl; ofstream headerFile( hdrfilename.c_str() ); for ( std::vector< std::string >::iterator lineIter = _SchedHeaderLines.begin(); lineIter != _SchedHeaderLines.end(); lineIter++ ) { headerFile << *lineIter << endl; } headerFile.close(); _SchedHeaderLines.clear(); // flush the list }
std::list<GraphNode> AffinityTask::BFS(const TaskSet& taskSet, const GraphNode& start, const GraphNode& target, const Affinity& excludeID, const TaskSet& excludeTask) { std::list<GraphNode> returnList; //prepare link map std::unordered_map<CPUID, TaskSet> cpuToTaskList; std::unordered_map<AffinityTask*, Affinity> taskToCPUList; for(auto task : taskSet) { if(excludeTask.find(task) != excludeTask.end()) continue; Affinity affinityCopy(task->affinity); for(auto cpu : excludeID) affinityCopy.erase(cpu); taskToCPUList.insert(std::pair<AffinityTask*, Affinity>(task, affinityCopy)); for(CPUID cpu : affinityCopy) { if(cpuToTaskList.find(cpu) == cpuToTaskList.end()) cpuToTaskList.insert(std::pair<CPUID, TaskSet>(cpu, TaskSet())); cpuToTaskList.find(cpu)->second.insert(task); } } //procedure BFS(G,v) is std::unordered_map<CPUID, AffinityTask*> cpuToPrevTask; std::unordered_map<AffinityTask*, CPUID> taskToPrevCPU; bool reachable = false; std::queue<GraphNode> queue;//create a queue Q, true is Job, false is processor std::unordered_set<CPUID> visitedCPU; //create a set V std::unordered_set<AffinityTask*> visitedTask; //create a set V if(start.isTask()) visitedTask.insert(start.getTask()); //add v to V else visitedCPU.insert(start.getCPUID()); queue.push(start); //enqueue v onto Q while(!queue.empty())//while Q is not empty loop { auto currentItem = queue.front(); //t ← Q.dequeue() queue.pop(); if(currentItem.isTask()) { if(target.isTask()) if(target.getTask() == currentItem.getTask()) //if t is what we are looking for then { //return t reachable = true; break; } } else { if(!target.isTask()) if(target.getCPUID() == currentItem.getCPUID()) //if t is what we are looking for then { //return t reachable = true; break; } } //for all edges e in G.adjacentEdges(t) loop if(currentItem.isTask()) { AffinityTask* curTask = currentItem.getTask(); assert(curTask != nullptr); for(CPUID adjacentCPU : taskToCPUList.find(curTask)->second) //u ← G.adjacentVertex(t,e) { if(visitedCPU.find(adjacentCPU) == visitedCPU.end()) //if u is not in V then { visitedCPU.insert(adjacentCPU); //add u to V queue.push(GraphNode(adjacentCPU)); //enqueue u onto Q assert(cpuToPrevTask.find(adjacentCPU) == cpuToPrevTask.end()); cpuToPrevTask.insert(std::pair<CPUID,AffinityTask*>(adjacentCPU, curTask)); } } } else { CPUID curCPU = currentItem.getCPUID(); auto iter = cpuToTaskList.find(curCPU); if(iter == cpuToTaskList.end()) { continue; } assert(iter->second.size() > 0); for(AffinityTask* adjacentTask : iter->second) //u ← G.adjacentVertex(t,e) { if(visitedTask.find(adjacentTask) == visitedTask.end()) { visitedTask.insert(adjacentTask); queue.push(GraphNode(adjacentTask)); assert(taskToPrevCPU.find(adjacentTask) == taskToPrevCPU.end()); taskToPrevCPU.insert(std::pair<AffinityTask*,CPUID>(adjacentTask, curCPU)); } } } } if(reachable) { GraphNode current = target; while(true) { returnList.push_front(current); if(current.isTask()) { auto cpu_iter = taskToPrevCPU.find(current.getTask()); if(cpu_iter == taskToPrevCPU.end()) { assert(start.isTask()); assert(current.getTask() == start.getTask()); break; } current = cpu_iter->second; } else { auto task_iter = cpuToPrevTask.find(current.getCPUID()); if(task_iter == cpuToPrevTask.end()) { assert(!start.isTask()); assert(current.getCPUID() == start.getCPUID()); break; } current = task_iter->second; } } } return returnList; }