X-Git-Url: http://sraa.de/git/?a=blobdiff_plain;f=dol%2Fsrc%2Fdol%2Fvisitor%2Fhds%2Flib%2FPerformance_Extraction.cpp;fp=dol%2Fsrc%2Fdol%2Fvisitor%2Fhds%2Flib%2FPerformance_Extraction.cpp;h=9322648ca5f39156843a31175db400c817185bf0;hb=8c411cf24ed0eb889191aaeafd8fa1e69081df42;hp=0000000000000000000000000000000000000000;hpb=dea7a4fb1ed110d3ce6e6d9255103d724bd66c0e;p=jump.git diff --git a/dol/src/dol/visitor/hds/lib/Performance_Extraction.cpp b/dol/src/dol/visitor/hds/lib/Performance_Extraction.cpp new file mode 100644 index 0000000..9322648 --- /dev/null +++ b/dol/src/dol/visitor/hds/lib/Performance_Extraction.cpp @@ -0,0 +1,447 @@ +#include "Performance_Extraction.h" +#include +#include + + +Performance_Extraction performance_extraction("static_characterization.xml"); + +/** + * + */ +int get_current_time(CURRENT_TIME *current_time_ptr) +{ + return clock_gettime(CLOCK_REALTIME, &(current_time_ptr->ts)); +} + + +/** + * + */ +double sub_time(CURRENT_TIME *start_time_ptr, CURRENT_TIME *end_time_ptr) +{ + CURRENT_TIME diff_time; + double time_ns; + + diff_time.ts.tv_sec = end_time_ptr->ts.tv_sec - start_time_ptr->ts.tv_sec; + diff_time.ts.tv_nsec = end_time_ptr->ts.tv_nsec - start_time_ptr->ts.tv_nsec; + time_ns = diff_time.ts.tv_sec * 1E+9 + diff_time.ts.tv_nsec; + + return time_ns; +} + + +/** + * + */ +Process_Performance::Process_Performance(const char *name) +{ + strcpy(_process_name, name); + _head = NULL; + _tail = NULL; +} + + +/** + * + */ +Process_Performance::~Process_Performance() +{ + COMP_ENTRY *temp; + DBGPRINT; + while (_head != NULL) { + temp = _head; + _head = _head->next; + delete temp; + } +} + + +/** + * + */ +const char *Process_Performance::get_name() +{ + return _process_name; +} + + +/** + * + */ +COMP_ENTRY *Process_Performance::get_head_entry() +{ + return _head; +} + + +/** + * + */ +COMP_ENTRY *Process_Performance::get_entry(int start_line, int end_line) +{ + COMP_ENTRY *temp = NULL; + temp = _head; + while (temp != NULL) { + if ((temp->start_line == start_line) && (temp->end_line == end_line)) { + break; + } + temp = temp->next; + } + + return temp; +} + + +/** + * + */ +COMP_ENTRY *Process_Performance::add_entry(int start_line, int end_line) +{ + COMP_ENTRY *temp = NULL; + temp = get_entry(start_line, end_line); + if (temp == NULL) { + temp = new COMP_ENTRY; + + if (_head == NULL) { + _head = temp; + _tail = temp; + temp->next = NULL; + } else { + _tail->next = temp; + _tail = temp; + temp->next = NULL; + } + temp->start_line = start_line; + temp->end_line = end_line; + temp->total_computation_time = 0; + temp->called_times = 0; + } + + return temp; +} + + +/** + * + */ +int Process_Performance::set_entry(int start_line, int end_line, + CURRENT_TIME *start_time_ptr, + CURRENT_TIME *end_time_ptr) +{ + int ret = 0; + COMP_ENTRY *temp; + double computation_time; + computation_time = sub_time(start_time_ptr, end_time_ptr); + temp = get_entry(start_line, end_line); + if (temp == NULL) { + temp = add_entry(start_line, end_line); + } + + temp->total_computation_time += computation_time; + temp->called_times++; + + return ret; +} + + +/** + * + */ +Performance_Extraction::Performance_Extraction(const char *chr_file_name) +{ + strcpy(_chr_file_name, chr_file_name); +} + + +/** + * + */ +Performance_Extraction::~Performance_Extraction() +{ + Process_Performance *process_performance_ptr; + +#ifdef INCLUDE_PERFORMANCE + //strcpy(_processor_type, "DSP"); + //add_to_xml_file(_chr_file_name); + //strcpy(_processor_type, "RISC"); + //add_to_xml_file(_chr_file_name); + + write_to_xml_file(_chr_file_name); +#endif + + for (_iter_process_performance = _list_process_performance.begin(); + _iter_process_performance != _list_process_performance.end(); + _iter_process_performance++) + { + process_performance_ptr = *_iter_process_performance; + delete process_performance_ptr; + } + _list_process_performance.clear(); + +} + + +/** + * + */ +int Performance_Extraction::add_computation_performance( + const char *process_name, int start_line, int end_line, + CURRENT_TIME *start_time_ptr, CURRENT_TIME *end_time_ptr) +{ + int ret = 0; + Process_Performance *process_performance_ptr; + + process_performance_ptr = get_process_performance(process_name); + if (process_performance_ptr == NULL) { + process_performance_ptr = new Process_Performance(process_name); + _list_process_performance.push_back(process_performance_ptr); + } + + process_performance_ptr->set_entry(start_line, end_line, + start_time_ptr, end_time_ptr); + + return ret; +} + + +/** + * + */ +Process_Performance *Performance_Extraction::get_process_performance( + const char *process_name) +{ + Process_Performance *process_performance_ptr = NULL; + + for (_iter_process_performance = _list_process_performance.begin(); + _iter_process_performance != _list_process_performance.end(); + _iter_process_performance++) { + process_performance_ptr = *_iter_process_performance; + if (strcmp(process_performance_ptr->get_name(), process_name) == 0) { + break; + } + } + + if (_iter_process_performance == _list_process_performance.end()) { + process_performance_ptr = NULL; + } + + return process_performance_ptr; +} + + +/** + * write performance data into XML file. (identical to add_to_xml_file() + * if file does not exist). + */ +int Performance_Extraction::write_to_xml_file(const char *chr_file_name) +{ + char start_line_str[NAME_LENGTH]; + char end_line_str[NAME_LENGTH]; + char computation_time_str[NAME_LENGTH]; + double computation_time; + Process_Performance *process_performance_ptr; + COMP_ENTRY *comp_entry; + + //create xml + string text = "\n\n"; + for (_iter_process_performance = _list_process_performance.begin(); + _iter_process_performance != _list_process_performance.end(); + _iter_process_performance++) { + process_performance_ptr = *_iter_process_performance; + + text += " get_name(); + text += "\">\n"; + + for (comp_entry = process_performance_ptr->get_head_entry(); + comp_entry != NULL; + comp_entry = comp_entry->next) { + sprintf(start_line_str, "%d", comp_entry->start_line); + sprintf(end_line_str, "%d", comp_entry->end_line); + + //hack to eliminate the overhead of system call clock_gettime. + //computation_time is nano sec. To get cycles, need to mutiply + //by the frequency of cpu. result is in cycles. + computation_time = (comp_entry->total_computation_time + / comp_entry->called_times - SYS_OVERHEAD) + * HOST_FREQUENCY; + if (computation_time < 0) { + computation_time = 0; + } + sprintf(computation_time_str, "%.0f", computation_time); + + text += " \n"; + text += " \n"; + text += " \n"; + text += " \n"; + } + text += " \n"; + } + text += " \n"; + text += " \n"; + text += " \n"; + text += " \n"; + text += " \n"; + text += " \n"; + text += " \n"; + text += " \n"; + text += "\n"; + + //write xml to file + std::ofstream out(chr_file_name, ios::out); + if (!out) { + printf("Cannot open file %s. Return.\n", chr_file_name); + return -1; + } + out.write(text.c_str(), text.size()); + out.close(); + return 0; +} + + +/** + * add performance data to existing XML file (or create new one if file + * does not exist). + */ +int Performance_Extraction::add_to_xml_file(const char *chr_file_name) +{ + int ret = 0; + XMLNode file_node; + XMLNode root_node; + XMLNode process_node; + XMLNode comp_node; + int computation_index = 0; + XMLNode processor_node; + XMLNode read_node; + XMLNode write_node; + + Process_Performance *process_performance_ptr; + COMP_ENTRY *comp_entry; + + char start_line_str[NAME_LENGTH]; + char end_line_str[NAME_LENGTH]; + char computation_time_str[NAME_LENGTH]; + double computation_time; + + file_node = XMLNode::parseFile(chr_file_name); + if (file_node.isEmpty()) { + file_node = XMLNode::createXMLTopNode("xml", TRUE); + file_node.addAttribute("version", "1.0"); + root_node = file_node.addChild("characterization"); + } + + root_node = file_node.getChildNode(); + if (root_node.isEmpty()) { + ret = -1; + printf("Open characterization file error\n"); + return ret; + } + + for (_iter_process_performance = _list_process_performance.begin(); + _iter_process_performance != _list_process_performance.end(); + _iter_process_performance++) { + process_performance_ptr = *_iter_process_performance; + + printf("%s\n", process_performance_ptr->get_name()); + + process_node = root_node.getChildNodeWithAttribute( + "process", "name", process_performance_ptr->get_name()); + if (process_node.isEmpty()) + { + process_node = root_node.addChild("process"); + process_node.addAttribute( + "name",process_performance_ptr->get_name()); + } + + for (comp_entry = process_performance_ptr->get_head_entry(); + comp_entry != NULL; + comp_entry = comp_entry->next) { + sprintf(start_line_str, "%d", comp_entry->start_line); + sprintf(end_line_str, "%d", comp_entry->end_line); + + printf("%d %d\n", comp_entry->start_line, comp_entry->end_line); + + /* Hack to eliminate the overhead of system call clock_gettime. + computation_time is nano sec. To get cycles, need to mutiply + by the frequency of cpu. + result is cycles */ + computation_time = (comp_entry->total_computation_time + / comp_entry->called_times - SYS_OVERHEAD) + * HOST_FREQUENCY; + + if (computation_time < 0) { + computation_time = 0; + } + + sprintf(computation_time_str, "%.0f", computation_time); + computation_index = 0; + comp_node = process_node.getChildNode("computation", + computation_index++); + while (!comp_node.isEmpty()) { + if (strcmp(comp_node.getAttribute("start"),start_line_str)==0 + && strcmp(comp_node.getAttribute("end"),end_line_str)==0) { + break; + } + + comp_node = process_node.getChildNode("computation", + computation_index++); + } + + if (comp_node.isEmpty()) { + comp_node = process_node.addChild("computation"); + comp_node.addAttribute("start", start_line_str); + comp_node.addAttribute("end", end_line_str); + } + + processor_node = comp_node.getChildNodeWithAttribute("processor", "type", _processor_type); + if (processor_node.isEmpty()) { + processor_node = comp_node.addChild("processor"); + processor_node.addAttribute("type", _processor_type); + processor_node.addAttribute("time", computation_time_str); + } + } + } + + read_node = root_node.getChildNodeWithAttribute("communication", + "name", "read"); + if (read_node.isEmpty()) { + read_node = root_node.addChild("communication"); + read_node.addAttribute("name", "read"); + } + + processor_node = read_node.getChildNodeWithAttribute("processor", + "type", + _processor_type); + if (processor_node.isEmpty()) { + processor_node = read_node.addChild("processor"); + processor_node.addAttribute("type", _processor_type); + processor_node.addAttribute("time", "2"); + } + + write_node = root_node.getChildNodeWithAttribute("communication", + "name", "write"); + if (write_node.isEmpty()) { + write_node = root_node.addChild("communication"); + write_node.addAttribute("name", "write"); + } + + processor_node = write_node.getChildNodeWithAttribute("processor", + "type", + _processor_type); + if (processor_node.isEmpty()) { + processor_node = write_node.addChild("processor"); + processor_node.addAttribute("type", _processor_type); + processor_node.addAttribute("time", "2"); + } + + file_node.writeToFile(chr_file_name); + return 0; +}