void net_read_config(void) { struct config_t *config; struct list_t *net_name_list; char *section; int i; /* Configuration file */ if (!*net_config_file_name) { net_domain_index = esim_new_domain(net_frequency); return; } /* Open network configuration file */ config = config_create(net_config_file_name); if (*net_config_file_name) config_load(config); /* Section with generic configuration parameters */ section = "General"; /* Frequency */ net_frequency = config_read_int(config, section, "Frequency", net_frequency); if (!IN_RANGE(net_frequency, 1, ESIM_MAX_FREQUENCY)) fatal("%s: invalid value for 'Frequency'", net_config_file_name); /* Create frequency domain */ net_domain_index = esim_new_domain(net_frequency); /* Create a temporary list of network names found in configuration * file */ net_name_list = list_create(); for (section = config_section_first(config); section; section = config_section_next(config)) { char *delim = "."; char section_str[MAX_STRING_SIZE]; char *token; char *net_name; /* Create a copy of section name */ snprintf(section_str, sizeof section_str, "%s", section); section = section_str; /* First token must be 'Network' */ token = strtok(section, delim); if (strcasecmp(token, "Network")) continue; /* Second token is network name */ net_name = strtok(NULL, delim); if (!net_name) continue; /* No third token */ token = strtok(NULL, delim); if (token) continue; /* Insert new network name */ net_name = xstrdup(net_name); list_add(net_name_list, net_name); } /* Print network names */ net_debug("%s: loading network configuration file\n", net_config_file_name); net_debug("networks found:\n"); for (i = 0; i < net_name_list->count; i++) net_debug("\t%s\n", (char *)list_get(net_name_list, i)); net_debug("\n"); /* Load networks */ net_table = hash_table_create(0, 0); for (i = 0; i < net_name_list->count; i++) { struct net_t *network; char *net_name; net_name = list_get(net_name_list, i); network = net_create_from_config(config, net_name); hash_table_insert(net_table, net_name, network); } /* Free list of network names and configuration file */ while (net_name_list->count) free(list_remove_at(net_name_list, 0)); list_free(net_name_list); config_free(config); }
struct dram_system_t *dram_system_config_with_file(struct config_t *config, char *system_name) { int j; int controller_sections = 0; unsigned int highest_addr = 0; char *section; char section_str[MAX_STRING_SIZE]; char *row_buffer_policy_map[] = {"OpenPage", "ClosePage", "hybird"}; char *scheduling_policy_map[] = {"RankBank", "BankRank"}; struct dram_system_t *system; /* Controller parameters * FIXME: we should create a default variation for times this values * are not assigned. For now we set it as DRAM DDR3 Micron * */ unsigned int num_physical_channels = 1; unsigned int request_queue_depth = 32; enum dram_controller_row_buffer_policy_t rb_policy = open_page_row_buffer_policy; enum dram_controller_scheduling_policy_t scheduling_policy = rank_bank_round_robin; unsigned int dram_num_ranks = 8; unsigned int dram_num_devices_per_rank = 1; unsigned int dram_num_banks_per_device = 1; unsigned int dram_num_rows_per_bank = 8192; unsigned int dram_num_columns_per_row = 1024; unsigned int dram_num_bits_per_column = 16; unsigned int dram_timing_tCAS = 24; unsigned int dram_timing_tRCD = 10; unsigned int dram_timing_tRP = 10; unsigned int dram_timing_tRAS = 24; unsigned int dram_timing_tCWL = 9; unsigned int dram_timing_tCCD = 4; system = dram_system_create(system_name); /* DRAM system configuration */ snprintf(section_str, sizeof section_str, "DRAMsystem.%s", system_name); for (section = config_section_first(config); section; section = config_section_next(config)) { if (strcasecmp(section, section_str)) continue; system->num_logical_channels = config_read_int(config, section, "NumLogicalChannels", system->num_logical_channels); } /* Create controllers */ for (section = config_section_first(config); section; section = config_section_next(config)) { char *delim = "."; char *token; char *controller_name; /* First token must be 'Network' */ snprintf(section_str, sizeof section_str, "%s", section); token = strtok(section_str, delim); if (!token || strcasecmp(token, "DRAMsystem")) continue; /* Second token must be the name of the network */ token = strtok(NULL, delim); if (!token || strcasecmp(token, system_name)) continue; /* Third token must be 'Node' */ token = strtok(NULL, delim); if (!token || strcasecmp(token, "Controller")) continue; /* Get name */ controller_name = strtok(NULL, delim); token = strtok(NULL, delim); if (!controller_name || token) fatal("%s:%s: wrong format for controller name .\n%s", system->name, section, dram_err_config); /* Read Properties */ num_physical_channels = config_read_int(config, section, "NumPhysicalChannels", num_physical_channels); dram_num_ranks = config_read_int(config, section, "NumRanks", dram_num_ranks); dram_num_devices_per_rank = config_read_int(config, section, "NumDevicesPerRank", dram_num_devices_per_rank); dram_num_banks_per_device = config_read_int(config, section, "NumBanksPerDevice", dram_num_banks_per_device); dram_num_rows_per_bank = config_read_int(config, section, "NumRowsPerBank", dram_num_rows_per_bank); dram_num_columns_per_row = config_read_int(config, section, "NumColumnPerRow", dram_num_columns_per_row); dram_num_bits_per_column = config_read_int(config, section, "NumBitsPerColumn", dram_num_bits_per_column); request_queue_depth = config_read_int(config, section, "RequestQueueDepth", request_queue_depth); rb_policy = config_read_enum(config, section, "RowBufferPolicy", rb_policy, row_buffer_policy_map, 3); scheduling_policy = config_read_enum(config, section, "SchedulingPolicy", scheduling_policy, scheduling_policy_map, 2); dram_timing_tCAS = config_read_int(config, section, "tCAS", dram_timing_tCAS); dram_timing_tRCD = config_read_int(config, section, "tRCD", dram_timing_tRCD); dram_timing_tRP = config_read_int(config, section, "tRP", dram_timing_tRP); dram_timing_tRAS = config_read_int(config, section, "tRAS", dram_timing_tRAS); dram_timing_tCWL = config_read_int(config, section, "tCWL", dram_timing_tCWL); dram_timing_tCCD = config_read_int(config, section, "tCCD", dram_timing_tCCD); /* Create controller */ struct dram_controller_t *controller; controller = dram_controller_create(request_queue_depth, rb_policy, scheduling_policy); /* Assign controller parameters */ controller->id = controller_sections; if (!controller_sections) controller->lowest_addr = 0; else controller->lowest_addr = highest_addr + 1; controller->highest_addr = controller->lowest_addr + ((dram_num_bits_per_column * dram_num_devices_per_rank) / 8 * dram_num_columns_per_row * dram_num_rows_per_bank * dram_num_banks_per_device * dram_num_ranks * num_physical_channels) - 1; controller->dram_addr_bits_rank = log_base2(dram_num_ranks); controller->dram_addr_bits_row = log_base2(dram_num_rows_per_bank); controller->dram_addr_bits_bank = log_base2(dram_num_banks_per_device); controller->dram_addr_bits_column = log_base2(dram_num_columns_per_row); controller->dram_addr_bits_physical_channel = log_base2(num_physical_channels); controller->dram_addr_bits_byte = log_base2(dram_num_bits_per_column * dram_num_devices_per_rank / 8); controller->dram_timing_tCAS = dram_timing_tCAS; controller->dram_timing_tRCD = dram_timing_tRCD; controller->dram_timing_tRP = dram_timing_tRP; controller->dram_timing_tRAS = dram_timing_tRAS; controller->dram_timing_tCWL = dram_timing_tCWL; controller->dram_timing_tCCD = dram_timing_tCCD; /* Update the highest address in memory system */ highest_addr = controller->highest_addr; /* Add controller to system */ list_add(system->dram_controller_list, controller); /* Create and add DRAM*/ for (j = 0; j < num_physical_channels; j++) { struct dram_t *dram; dram = dram_create(dram_num_ranks, dram_num_devices_per_rank, dram_num_banks_per_device, dram_num_rows_per_bank, dram_num_columns_per_row, dram_num_bits_per_column); dram->timing_tCAS = dram_timing_tCAS; dram->timing_tRCD = dram_timing_tRCD; dram->timing_tRP = dram_timing_tRP; dram->timing_tRAS = dram_timing_tRAS; dram->timing_tCWL = dram_timing_tCWL; dram_controller_add_dram(list_get(system->dram_controller_list, controller_sections), dram); } controller_sections++; } if (controller_sections != system->num_logical_channels) fatal("%s: number of controllers should match the number of logical" "channels \n%s", system->name, dram_err_config); /* Request Section */ for (section = config_section_first(config); section; section = config_section_next(config)) { char *delim = "."; char *token; char *token_endl; /* First token must be 'Network' */ snprintf(section_str, sizeof section_str, "%s", section); token = strtok(section_str, delim); if (!token || strcasecmp(token, "DRAMsystem")) continue; /* Second token must be the name of the network */ token = strtok(NULL, delim); if (!token || strcasecmp(token, system_name)) continue; /* Third token must be 'Commands' */ token = strtok(NULL, delim); if (!token || strcasecmp(token, "Requests")) continue; token_endl = strtok(NULL, delim); if (token_endl) fatal("%s: %s: bad format for Commands section.\n%s", system_name, section, dram_err_config); /* Requests */ dram_config_request_create(system, config, section); config_check(config); } /* Return dram_system on success */ return system; }
void dram_system_read_config(void) { int i ; struct config_t *config; struct list_t *dram_system_list; char *section; if (!*dram_config_file_name) { dram_domain_index = esim_new_domain(dram_frequency); return; } config = config_create(dram_config_file_name); if (*dram_config_file_name) config_load(config); /* Section with Generic Configuration Parameters */ section = "General"; /* Frequency */ dram_frequency = config_read_int(config, section, "Frequency", dram_frequency); if (!IN_RANGE(dram_frequency, 1, ESIM_MAX_FREQUENCY)) fatal("%s: Invalid value for 'Frequency'", dram_config_file_name); /* Creating the Frequency Domain */ dram_domain_index = esim_new_domain(dram_frequency); /* Create a temporary List of all Dram Systems found in * the configuration file */ dram_system_list = list_create(); for (section = config_section_first(config); section; section = config_section_next(config)) { char *delim = "."; char section_str[MAX_STRING_SIZE]; char *token; char *dram_system_name; /*Creating a copy of the name of the section */ snprintf(section_str, sizeof section_str, "%s", section); section = section_str; /* First Token Must be 'DRAMsystem' */ token = strtok(section, delim); if (strcasecmp(token, "DRAMsystem")) continue; /* Second Token must be the system Name */ dram_system_name = strtok(NULL, delim); if (!dram_system_name) continue; /* No third term is required */ token = strtok(NULL, delim); if (token) continue; /* Insert the new DRAM system name */ dram_system_name = xstrdup(dram_system_name); list_add(dram_system_list, dram_system_name); } /* Print DRAM system Names in debug */ dram_debug("%s: loading DRAM system configuration file \n", dram_config_file_name); dram_debug("DRAM systems found:\n"); for (i = 0; i < dram_system_list->count; i++) dram_debug("\t%s\n", (char *) list_get(dram_system_list, i)); dram_debug("\n"); /* Load DRAM systems */ dram_system_table = hash_table_create(0, 0); for ( i = 0; i < dram_system_list->count; i++) { struct dram_system_t *system; char *dram_system_name; dram_system_name = list_get(dram_system_list, i); system = dram_system_config_with_file(config, dram_system_name); hash_table_insert(dram_system_table, dram_system_name, system); } while (dram_system_list->count) free(list_remove_at(dram_system_list, 0)); list_free(dram_system_list); config_free(config); }
struct net_t *net_create_from_config(struct config_t *config, char *name) { int routing_type = 0; struct net_t *net; char *section; char section_str[MAX_STRING_SIZE]; int def_input_buffer_size; int def_output_buffer_size; int def_bandwidth; /* Create network */ net = net_create(name); /* Main section */ snprintf(section_str, sizeof section_str, "Network.%s", name); for (section = config_section_first(config); section; section = config_section_next(config)) { if (strcasecmp(section, section_str)) continue; net->def_input_buffer_size = config_read_int(config, section, "DefaultInputBufferSize", 0); net->def_output_buffer_size = config_read_int(config, section, "DefaultOutputBufferSize", 0); def_bandwidth = config_read_int(config, section, "DefaultBandwidth", 0); if (!net->def_input_buffer_size) fatal("%s:%s: DefaultInputBufferSize: invalid/missing value.\n%s", net->name, section, net_err_config); if (!net->def_output_buffer_size) fatal("%s:%s: DefaultOutputBufferSize: invalid/missing value.\n%s", net->name, section, net_err_config); if (!def_bandwidth) fatal("%s:%s: DefaultBandwidth: invalid/missing value.\n%s", net->name, section, net_err_config); def_output_buffer_size = net->def_output_buffer_size; def_input_buffer_size = net->def_input_buffer_size; } /* Nodes */ for (section = config_section_first(config); section; section = config_section_next(config)) { char *delim = "."; char *token; char *node_name; char *node_type; int input_buffer_size; int output_buffer_size; int bandwidth; int lanes; /* BUS lanes */ /* First token must be 'Network' */ snprintf(section_str, sizeof section_str, "%s", section); token = strtok(section_str, delim); if (!token || strcasecmp(token, "Network")) continue; /* Second token must be the name of the network */ token = strtok(NULL, delim); if (!token || strcasecmp(token, name)) continue; /* Third token must be 'Node' */ token = strtok(NULL, delim); if (!token || strcasecmp(token, "Node")) continue; /* Get name */ node_name = strtok(NULL, delim); token = strtok(NULL, delim); if (!node_name || token) fatal("%s:%s: wrong format for node.\n%s", net->name, section, net_err_config); /* Get properties */ node_type = config_read_string(config, section, "Type", ""); input_buffer_size = config_read_int(config, section, "InputBufferSize", def_input_buffer_size); output_buffer_size = config_read_int(config, section, "OutputBufferSize", def_output_buffer_size); bandwidth = config_read_int(config, section, "BandWidth", def_bandwidth); lanes = config_read_int(config, section, "Lanes", 1); /* Create node */ if (!strcasecmp(node_type, "EndNode")) net_add_end_node(net, input_buffer_size, output_buffer_size, node_name, NULL); else if (!strcasecmp(node_type, "Switch")) net_add_switch(net, input_buffer_size, output_buffer_size, bandwidth, node_name); else if (!strcasecmp(node_type, "Bus")) { /* Right now we ignore the size of buffers. But we * can set it as the value for bus ports, making the * connecting switches asymmetric. */ if (input_buffer_size != def_input_buffer_size || output_buffer_size != def_output_buffer_size) fatal("%s:%s: BUS does not contain input/output buffers. " "Size values will be ignored \n", net->name, section); /* If the number of lanes is smaller than 1 produce * an error */ if (lanes < 1) fatal("%s:%s: BUS cannot have less than 1 number of lanes \n%s", net->name, section, net_err_config); net_add_bus(net, bandwidth, node_name, lanes); } else fatal("%s:%s: Type: invalid/missing value.\n%s", net->name, section, net_err_config); } /* Links */ for (section = config_section_first(config); section; section = config_section_next(config)) { char *delim = "."; char *token; char *link_name; char *link_type; char *src_node_name; char *dst_node_name; int bandwidth; int v_channel_count; int src_buffer_size; int dst_buffer_size; struct net_node_t *src_node; struct net_node_t *dst_node; /* First token must be 'Network' */ snprintf(section_str, sizeof section_str, "%s", section); token = strtok(section_str, delim); if (!token || strcasecmp(token, "Network")) continue; /* Second token must be the name of the network */ token = strtok(NULL, delim); if (!token || strcasecmp(token, name)) continue; /* Third token must be 'Link' */ token = strtok(NULL, delim); if (!token || strcasecmp(token, "Link")) continue; /* Fourth token must name of the link */ link_name = strtok(NULL, delim); token = strtok(NULL, delim); if (!link_name || token) fatal("%s: %s: bad format for link.\n%s", name, section, net_err_config); /* Fields */ link_type = config_read_string(config, section, "Type", "Unidirectional"); bandwidth = config_read_int(config, section, "Bandwidth", def_bandwidth); src_node_name = config_read_string(config, section, "Source", ""); dst_node_name = config_read_string(config, section, "Dest", ""); v_channel_count = config_read_int(config, section, "VC", 1); src_buffer_size = config_read_int(config, section, "SourceBufferSize", 0); dst_buffer_size = config_read_int(config, section, "DestBufferSize", 0); /* Nodes */ src_node = net_get_node_by_name(net, src_node_name); dst_node = net_get_node_by_name(net, dst_node_name); if (!src_node) fatal("%s: %s: %s: source node does not exist.\n%s", name, section, src_node_name, net_err_config); if (!dst_node) fatal("%s: %s: %s: destination node does not exist.\n%s", name, section, dst_node_name, net_err_config); /* If it is a link connection */ if (src_node->kind != net_node_bus && dst_node->kind != net_node_bus) { int link_src_bsize; int link_dst_bsize; if (v_channel_count >= 1) { if (!strcasecmp(link_type, "Unidirectional")) { link_src_bsize = (src_buffer_size)? src_buffer_size : src_node->output_buffer_size; link_dst_bsize = (dst_buffer_size) ?dst_buffer_size : dst_node->input_buffer_size; net_add_link(net, src_node, dst_node, bandwidth, link_src_bsize, link_dst_bsize, v_channel_count); } else if (!strcasecmp(link_type, "Bidirectional")) { net_add_bidirectional_link(net, src_node, dst_node, bandwidth, src_buffer_size, dst_buffer_size, v_channel_count); } } else fatal("%s: %s: Unacceptable number of virtual channels \n %s", name, section, net_err_config); } /* If is is a Bus Connection */ else { if (v_channel_count > 1) fatal("%s: %s: BUS can not have virtual channels. \n %s", name, section, net_err_config); if (!strcasecmp(link_type, "Unidirectional")) { if ((src_node->kind == net_node_bus && src_buffer_size) || (dst_node->kind == net_node_bus && dst_buffer_size)) { fatal ("%s: %s: Source/Destination BUS cannot have buffer. \n %s " ,name, section, net_err_config); } net_add_bus_port(net, src_node, dst_node, src_buffer_size, dst_buffer_size); } else if (!strcasecmp(link_type, "Bidirectional")) { net_add_bidirectional_bus_port(net, src_node, dst_node, src_buffer_size, dst_buffer_size); } } } /* initializing the routing table */ net_routing_table_initiate(net->routing_table); /* Routes */ for (section = config_section_first(config); section; section = config_section_next(config)) { char *delim = "."; char *token; char *token_endl; /* First token must be 'Network' */ snprintf(section_str, sizeof section_str, "%s", section); token = strtok(section_str, delim); if (!token || strcasecmp(token, "Network")) continue; /* Second token must be the name of the network */ token = strtok(NULL, delim); if (!token || strcasecmp(token, name)) continue; /* Third token must be 'Routes' */ token = strtok(NULL, delim); if (!token || strcasecmp(token, "Routes")) continue; token_endl = strtok(NULL, delim); if (token_endl) fatal("%s: %s: bad format for route.\n%s", name, section, net_err_config); /* Routes */ routing_type = 1; net_config_route_create(net, config, section); config_check(config); } /* Commands */ for (section = config_section_first(config); section; section = config_section_next(config)) { char *delim = "."; char *token; char *token_endl; /* First token must be 'Network' */ snprintf(section_str, sizeof section_str, "%s", section); token = strtok(section_str, delim); if (!token || strcasecmp(token, "Network")) continue; /* Second token must be the name of the network */ token = strtok(NULL, delim); if (!token || strcasecmp(token, name)) continue; /* Third token must be 'Commands' */ token = strtok(NULL, delim); if (!token || strcasecmp(token, "Commands")) continue; token_endl = strtok(NULL, delim); if (token_endl) fatal("%s: %s: bad format for Commands section.\n%s", name, section, net_err_config); /* Commands */ net_config_command_create(net, config, section); config_check(config); } /* If there is no route section, Floyd-Warshall calculates the * shortest path for all the nodes in the network */ if (routing_type == 0) net_routing_table_floyd_warshall(net->routing_table); /* Return */ return net; }