static struct net_node_t * net_command_get_node(struct net_t *net, struct list_t *token_list, char *command_line, enum net_node_kind_t expected_kind) { struct net_node_t *node; char *node_name; /* Getting the end node name */ net_command_expect(token_list, command_line); node_name = str_token_list_first(token_list); node = net_get_node_by_name(net, node_name); if (!node) { fatal("%s: %s: invalid node name.\n\t> %s", __FUNCTION__, node_name, command_line); } else if (expected_kind != net_node_invalid && node->kind != expected_kind) { fatal("%s: %s: Unexpected node type \n\t > %s", __FUNCTION__, node_name, command_line); } /* Return module */ str_token_list_shift(token_list); return node; }
struct net_node_t *net_node_create(struct net_t *net, enum net_node_kind_t kind, int index, int input_buffer_size, int output_buffer_size, int bandwidth, char *name, void *user_data) { struct net_node_t *node; /* Fields */ node = xcalloc(1, sizeof(struct net_node_t)); node->net = net; node->name = xstrdup(name); node->kind = kind; node->index = index; node->user_data = user_data; node->bandwidth = bandwidth; node->input_buffer_size = input_buffer_size; node->output_buffer_size = output_buffer_size; if (kind != net_node_end && bandwidth < 1) panic("%s: invalid bandwidth", __FUNCTION__); if (net_get_node_by_name(net, name)) fatal("%s: duplicated node name.\n%s", net->name, net_err_node_name_duplicate); /* Lists of ports */ node->output_buffer_list = list_create_with_size(4); node->input_buffer_list = list_create_with_size(4); return node; }
static void net_config_route_create(struct net_t *net, struct config_t *config, char *section) { char *token; char section_str[MAX_STRING_SIZE]; char *delim_sep = ":"; for (int i = 0; i < net->node_count; i++) { for (int j = 0; j < net->node_count; j++) { int vc_used = 0; char spr_result_size[MAX_STRING_SIZE]; char *nxt_node_name; struct net_node_t *src_node_r; struct net_node_t *dst_node_r; struct net_node_t *nxt_node_r; src_node_r = list_get(net->node_list, i); dst_node_r = list_get(net->node_list, j); if (dst_node_r->kind == net_node_end) { snprintf(spr_result_size, sizeof spr_result_size, "%s.to.%s", src_node_r->name, dst_node_r->name); nxt_node_name = config_read_string(config, section, spr_result_size, "---"); /* Token Separates the next node and * VC */ snprintf(section_str, sizeof section_str, "%s", nxt_node_name); token = strtok(section_str, delim_sep); nxt_node_name = token; token = strtok(NULL, delim_sep); if (token != NULL) { vc_used = atoi(token); if (vc_used < 0) fatal("Network %s:%s: Unacceptable virtual channel \n %s", net->name, section, net_err_config); } int name_check = strcmp(nxt_node_name, "---"); nxt_node_r = net_get_node_by_name(net, nxt_node_name); if (name_check != 0) { if (nxt_node_r == NULL) fatal("Network %s:%s: Invalid node Name.\n %s", net->name, section,net_err_config); else net_routing_table_route_create (net->routing_table, src_node_r, dst_node_r, nxt_node_r, vc_used); } } } } }
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; }