| /***************************************************************************** | |
| * McPAT | |
| * SOFTWARE LICENSE AGREEMENT | |
| * Copyright (c) 2010-2013 Advanced Micro Devices, Inc. | |
| * All Rights Reserved | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are | |
| * met: redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer; | |
| * redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution; | |
| * neither the name of the copyright holders nor the names of its | |
| * contributors may be used to endorse or promote products derived from | |
| * this software without specific prior written permission. | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| * Authors: Joel Hestness | |
| * Yasuko Eckert | |
| * | |
| ***************************************************************************/ | |
| #include <algorithm> | |
| #include <cmath> | |
| #include <cstdio> | |
| #include <fstream> | |
| #include <iostream> | |
| #include <string> | |
| #include "array.h" | |
| #include "basic_circuit.h" | |
| #include "common.h" | |
| #include "const.h" | |
| #include "parameter.h" | |
| #include "system.h" | |
| #include "version.h" | |
| // TODO: Fix this constructor to default initialize all pointers to NULL | |
| System::System(XMLNode* _xml_data) | |
| : McPATComponent(_xml_data) { | |
| int i; | |
| int currCore = 0; | |
| int currNOC = 0; | |
| name = "System"; | |
| set_proc_param(); | |
| // TODO: This loop can (and should) be called by every component in | |
| // the hierarchy. Consider moving it to McPATComponent | |
| int numChildren = xml_data->nChildNode("component"); | |
| for (i = 0; i < numChildren; i++ ) { | |
| // For each child node of the system, | |
| XMLNode* childXML = xml_data->getChildNodePtr("component", &i); | |
| XMLCSTR type = childXML->getAttribute("type"); | |
| if (!type) { | |
| warnMissingComponentType(childXML->getAttribute("id")); | |
| } STRCMP(type, "Core") { | |
| // TODO: If homogeneous cores, and currCore > 0, just copy core 0 | |
| children.push_back(new Core(childXML, currCore, &interface_ip)); | |
| currCore++; | |
| } STRCMP(type, "CacheUnit") { | |
| children.push_back(new CacheUnit(childXML, &interface_ip)); | |
| } STRCMP(type, "CacheController") { | |
| // TODO: Remove reliance on interface_ip - there should be a better | |
| // way to share global variables than passing, copying | |
| children.push_back(new CacheController(childXML, &interface_ip)); | |
| } STRCMP(type, "MemoryController") { | |
| children.push_back(new MemoryController(childXML, &interface_ip)); | |
| } STRCMP(type, "FlashController") { | |
| children.push_back(new FlashController(childXML, &interface_ip)); | |
| } STRCMP(type, "NIUController") { | |
| children.push_back(new NIUController(childXML, &interface_ip)); | |
| } STRCMP(type, "PCIeController") { | |
| children.push_back(new PCIeController(childXML, &interface_ip)); | |
| } STRCMP(type, "Memory") { | |
| // TODO: | |
| warnIncompleteComponentType(type); | |
| } STRCMP(type, "OnChipNetwork") { | |
| // TODO: Many of the parameters to this constructor should be | |
| // handled in another way | |
| children.push_back(new OnChipNetwork(childXML, currNOC, | |
| &interface_ip)); | |
| currNOC++; | |
| warnIncompleteComponentType(type); | |
| } STRCMP(type, "BusInterconnect") { | |
| // TODO: Many of the parameters to this constructor should be | |
| // handled in another way | |
| children.push_back(new BusInterconnect(childXML, &interface_ip)); | |
| warnIncompleteComponentType(type); | |
| // TODO: Add a directory data type that can handle the directories | |
| // as defined by certain McScript output | |
| } else { | |
| warnUnrecognizedComponent(type); | |
| } | |
| } | |
| } | |
| void System::displayDeviceType(int device_type_, uint32_t indent) { | |
| string indent_str(indent, ' '); | |
| cout << indent_str << "Device Type = "; | |
| switch ( device_type_ ) { | |
| case 0: | |
| cout << "ITRS high performance device type" << endl; | |
| break; | |
| case 1: | |
| cout << "ITRS low standby power device type" << endl; | |
| break; | |
| case 2: | |
| cout << "ITRS low operating power device type" << endl; | |
| break; | |
| case 3: | |
| cout << "LP-DRAM device type" << endl; | |
| break; | |
| case 4: | |
| cout << "COMM-DRAM device type" << endl; | |
| break; | |
| default: | |
| cout << indent_str << "Unknown!" << endl; | |
| exit(0); | |
| } | |
| } | |
| void System::displayInterconnectType(int interconnect_type_, uint32_t indent) { | |
| string indent_str(indent, ' '); | |
| cout << indent_str << "Interconnect metal projection = "; | |
| switch ( interconnect_type_ ) { | |
| case 0: | |
| cout << "aggressive interconnect technology projection" << endl; | |
| break; | |
| case 1: | |
| cout << "conservative interconnect technology projection" << endl; | |
| break; | |
| default: | |
| cout << indent_str << "Unknown!" << endl; | |
| exit(0); | |
| } | |
| } | |
| // TODO: Migrate this down to the McPATComponent::displayData function | |
| void System::displayData(uint32_t indent, int plevel) { | |
| string indent_str(indent, ' '); | |
| string indent_str_next(indent + 2, ' '); | |
| if (plevel < 5) { | |
| cout << "\nMcPAT (version " << VER_MAJOR << "." << VER_MINOR | |
| << " of " << VER_UPDATE << ") results (current print level is " | |
| << plevel | |
| << ", please increase print level to see the details in " | |
| << "components) " << endl; | |
| } else { | |
| cout << "\nMcPAT (version " << VER_MAJOR << "." << VER_MINOR | |
| << " of " << VER_UPDATE << ") results (current print level is 5)" | |
| << endl; | |
| } | |
| cout << "*****************************************************************" | |
| << "************************" << endl; | |
| cout << indent_str << "Technology " << core_tech_node << " nm" << endl; | |
| if (longer_channel_device) | |
| cout << indent_str << "Using Long Channel Devices When Appropriate" << endl; | |
| displayInterconnectType(interconnect_projection_type, indent); | |
| cout << indent_str << "Target Clock Rate (MHz) " << target_core_clockrate / 1e6 << endl; | |
| cout << endl; | |
| cout << "*****************************************************************" | |
| << "************************" << endl; | |
| McPATComponent::displayData(indent, plevel); | |
| } | |
| void System::set_proc_param() { | |
| // TODO: Consider creating a SystemParams class that tracks system-wide | |
| // parameters like these | |
| longer_channel_device = false; | |
| core_tech_node = -1; | |
| temperature = -1; | |
| interconnect_projection_type = -1; | |
| device_type = -1; | |
| physical_address_width = -1; | |
| int num_children = xml_data->nChildNode("param"); | |
| int i; | |
| for (i = 0; i < num_children; i++) { | |
| XMLNode* paramNode = xml_data->getChildNodePtr("param", &i); | |
| XMLCSTR node_name = paramNode->getAttribute("name"); | |
| XMLCSTR value = paramNode->getAttribute("value"); | |
| if (!node_name) | |
| warnMissingParamName(paramNode->getAttribute("id")); | |
| ASSIGN_FP_IF("core_tech_node", core_tech_node); | |
| ASSIGN_INT_IF("target_core_clockrate", target_core_clockrate); | |
| ASSIGN_INT_IF("temperature", temperature); | |
| ASSIGN_INT_IF("device_type", device_type); | |
| ASSIGN_INT_IF("longer_channel_device", longer_channel_device); | |
| ASSIGN_INT_IF("interconnect_projection_type", | |
| interconnect_projection_type); | |
| ASSIGN_INT_IF("machine_bits", data_path_width); | |
| ASSIGN_INT_IF("virtual_address_width", virtual_address_width); | |
| ASSIGN_INT_IF("physical_address_width", physical_address_width); | |
| ASSIGN_INT_IF("virtual_memory_page_size", virtual_memory_page_size); | |
| ASSIGN_INT_IF("wire_is_mat_type", interface_ip.wire_is_mat_type); | |
| ASSIGN_INT_IF("wire_os_mat_type", interface_ip.wire_os_mat_type); | |
| ASSIGN_INT_IF("delay_wt", interface_ip.delay_wt); | |
| ASSIGN_INT_IF("area_wt", interface_ip.area_wt); | |
| ASSIGN_INT_IF("dynamic_power_wt", interface_ip.dynamic_power_wt); | |
| ASSIGN_INT_IF("leakage_power_wt", interface_ip.leakage_power_wt); | |
| ASSIGN_INT_IF("cycle_time_wt", interface_ip.cycle_time_wt); | |
| ASSIGN_INT_IF("delay_dev", interface_ip.delay_dev); | |
| ASSIGN_INT_IF("area_dev", interface_ip.area_dev); | |
| ASSIGN_INT_IF("dynamic_power_dev", interface_ip.dynamic_power_dev); | |
| ASSIGN_INT_IF("leakage_power_dev", interface_ip.leakage_power_dev); | |
| ASSIGN_INT_IF("cycle_time_dev", interface_ip.cycle_time_dev); | |
| ASSIGN_INT_IF("ed", interface_ip.ed); | |
| ASSIGN_INT_IF("burst_len", interface_ip.burst_len); | |
| ASSIGN_INT_IF("int_prefetch_w", interface_ip.int_prefetch_w); | |
| ASSIGN_INT_IF("page_sz_bits", interface_ip.page_sz_bits); | |
| ASSIGN_ENUM_IF("rpters_in_htree", interface_ip.rpters_in_htree, bool); | |
| ASSIGN_INT_IF("ver_htree_wires_over_array", | |
| interface_ip.ver_htree_wires_over_array); | |
| ASSIGN_INT_IF("broadcast_addr_din_over_ver_htrees", | |
| interface_ip.broadcast_addr_din_over_ver_htrees); | |
| ASSIGN_INT_IF("nuca", interface_ip.nuca); | |
| ASSIGN_INT_IF("nuca_bank_count", interface_ip.nuca_bank_count); | |
| ASSIGN_ENUM_IF("force_cache_config", | |
| interface_ip.force_cache_config, bool); | |
| ASSIGN_ENUM_IF("wt", interface_ip.wt, Wire_type); | |
| ASSIGN_INT_IF("force_wiretype", interface_ip.force_wiretype); | |
| ASSIGN_INT_IF("print_detail", interface_ip.print_detail); | |
| ASSIGN_ENUM_IF("add_ecc_b_", interface_ip.add_ecc_b_, bool); | |
| else { | |
| warnUnrecognizedParam(node_name); | |
| } | |
| } | |
| // Change from MHz to Hz | |
| target_core_clockrate *= 1e6; | |
| interconnect_projection_type = | |
| (interconnect_projection_type == 0) ? 0 : 1; | |
| num_children = xml_data->nChildNode("stat"); | |
| for (i = 0; i < num_children; i++) { | |
| XMLNode* statNode = xml_data->getChildNodePtr("stat", &i); | |
| XMLCSTR node_name = statNode->getAttribute("name"); | |
| XMLCSTR value = statNode->getAttribute("value"); | |
| if (!node_name) | |
| warnMissingStatName(statNode->getAttribute("id")); | |
| ASSIGN_FP_IF("total_cycles", total_cycles); | |
| else { | |
| warnUnrecognizedStat(node_name); | |
| } | |
| } | |
| if (temperature < 0) { | |
| errorUnspecifiedParam("temperature"); | |
| } | |
| if (core_tech_node < 0) { | |
| errorUnspecifiedParam("core_tech_node"); | |
| } | |
| if (interconnect_projection_type < 0) { | |
| errorUnspecifiedParam("interconnect_projection_type"); | |
| } | |
| if (device_type < 0) { | |
| errorUnspecifiedParam("device_type"); | |
| } | |
| if (physical_address_width <= 0) { | |
| errorNonPositiveParam("physical_address_width"); | |
| } | |
| if (data_path_width <= 0) { | |
| errorNonPositiveParam("machine_bits"); | |
| } | |
| if (total_cycles <= 0) { | |
| fprintf(stderr, "WARNING: total_cycles <= 0 in system component, ", | |
| "power numbers will be funky...\n"); | |
| } | |
| clockRate = target_core_clockrate; | |
| execution_time = total_cycles / (target_core_clockrate); | |
| /* Basic parameters*/ | |
| interface_ip.data_arr_ram_cell_tech_type = device_type; | |
| interface_ip.data_arr_peri_global_tech_type = device_type; | |
| interface_ip.tag_arr_ram_cell_tech_type = device_type; | |
| interface_ip.tag_arr_peri_global_tech_type = device_type; | |
| interface_ip.ic_proj_type = interconnect_projection_type; | |
| interface_ip.temp = temperature; | |
| interface_ip.F_sz_nm = core_tech_node; | |
| interface_ip.F_sz_um = interface_ip.F_sz_nm / 1000; | |
| interface_ip.is_main_mem = false; | |
| // These are there just to make CACTI's error_checking() happy. | |
| // They are either not actually used or overwritten by each component. | |
| interface_ip.cache_sz = MIN_BUFFER_SIZE; | |
| interface_ip.nbanks = 1; | |
| interface_ip.out_w = 0; | |
| interface_ip.line_sz = 1; | |
| interface_ip.assoc = 1; | |
| interface_ip.num_rw_ports = 1; | |
| interface_ip.num_search_ports = 1; | |
| interface_ip.is_cache = true; | |
| interface_ip.pure_ram = false; | |
| interface_ip.pure_cam = false; | |
| //This section of code does not have real meaning; it is just to ensure | |
| //all data will have initial value to prevent errors. | |
| //They will be overridden during each components initialization | |
| interface_ip.specific_tag = 1; | |
| interface_ip.tag_w = 64; | |
| interface_ip.access_mode = 2; | |
| interface_ip.obj_func_dyn_energy = 0; | |
| interface_ip.obj_func_dyn_power = 0; | |
| interface_ip.obj_func_leak_power = 0; | |
| interface_ip.obj_func_cycle_t = 1; | |
| interface_ip.num_rw_ports = 1; | |
| interface_ip.num_rd_ports = 0; | |
| interface_ip.num_wr_ports = 0; | |
| interface_ip.num_se_rd_ports = 0; | |
| } | |
| System::~System() { | |
| // TODO: Delete children... do this in McPATComponent | |
| }; |