Commit 238dce73 authored by Robert Ricci's avatar Robert Ricci
Browse files

Some big changes to assign, and some related changes to assign_wrapper

and ptopgen.

Add link typing to assign. Each virtual link is given a single type.
Each physical link is given one or more types. A virtual link will
only be mapped to a physical link which can satisfy its type. In both
the top and ptop files, the link types are now mandatory, and they
fall at the end of the mandatory link arguments.

This differers from the 'regular' type system in two ways. First, a
plink is not constrained to filling only one type at a time. If we are
using emulated links, a plink could satisfy, say, an 'ethernet' link
and an 'fxp' link at the same time. This seems to more naturally match
the way we'll use link types.  Second, there are no counts assoicated
with link types, as there are for node types. ie. a link is not an
'ethernet:1' link, it's an 'ethernet' link. Presumably, when
multiplexing virtual links onto a physical one, it's bandwidth that's
the factor that limits the multiplexing.

The link type is now tak...
parent 297019fb
......@@ -333,7 +333,8 @@ void print_help()
<< endl;
cout << " -u - Print a summary of the solution." << endl;
cout << " -c <float> - Use the 'connected' pnode finding algorithm " <<
"<float>% of the time." << endl;
"<float>*100% of the time." << endl;
cout << " -n - Don't anneal - just do the prechecks." << endl;
exit(EXIT_FATAL);
}
......@@ -386,7 +387,7 @@ int type_precheck() {
}
if (ok) {
cout << "Type preecheck passed." << endl;
cout << "Type precheck passed." << endl;
return 1;
} else {
cout << "Type precheck failed!" << endl;
......@@ -424,12 +425,16 @@ int mapping_precheck() {
// This constitutes a list of the number of ptypes that matched the
// criteria. We use to guess what's wrong with the vnode.
int matched_links = 0;
int matched_bw = 0;
// Keep track of desires had how many 'hits', so that we can tell
// if any simply were not matched
tb_vnode::desires_count_map matched_desires;
// Keep track of which link types had how many 'hits', so that we can
// tell which type(s) caused this node to fail
tb_vnode::link_counts_map matched_link_counts;
map<crope,bool> matched_links;
tb_vclass *vclass = v->vclass;
tb_vclass::members_map::iterator mit;
if (vclass) {
......@@ -452,6 +457,7 @@ int mapping_precheck() {
// Grab the first node of the pclass as a representative sample
tb_pnode *pnode = *((*it)->members[this_type]->L.begin());
#if 0
// Check the number of interfaces - if the pnode is a switch,
// for now, we don't check this, since it can end up with more
// 'interfaces' due to the fact that it can have interswitch
......@@ -462,6 +468,10 @@ int mapping_precheck() {
} else {
potential_match = false;
}
#endif
// Check to see if any of the link that this pnode has are of
// the correct type for the virtual node
// Check bandwidth on emulated links
if (pnode->total_bandwidth >= v->total_bandwidth) {
......@@ -528,6 +538,26 @@ int mapping_precheck() {
}
}
// Check link types
tb_vnode::link_counts_map::iterator vit;
for (vit = v->link_counts.begin(); vit != v->link_counts.end();
vit++) {
crope type = vit->first;
int count = vit->second;
if (pnode->link_counts.find(type) !=
pnode->link_counts.end()) {
// Found at least one link of this type
matched_links[type] = true;
if (pnode->link_counts[type] >= count) {
// Great, there are enough, too
matched_link_counts[type]++;
} else {
potential_match = false;
}
} else {
potential_match = false;
}
}
if (potential_match) {
vec->push_back(*it);
......@@ -553,8 +583,20 @@ int mapping_precheck() {
if (vnode_type_table[v->name].first == 0) {
cout << " *** No possible mapping for " << v->name << endl;
// Make an attempt to figure out why it didn't match
if (!matched_links) {
cout << " Too many links!" << endl;
// Check all of its link types
tb_vnode::link_counts_map::iterator lit;
for (lit = v->link_counts.begin(); lit != v->link_counts.end();
lit++) {
crope type = lit->first;
if (!matched_links[type]) {
cout << " No links of type " << type << " found!" << endl;
} else {
if (!matched_link_counts[type]) {
cout << " Too many links of type " << type << "!"
<< endl;
}
}
}
if (!matched_bw) {
......@@ -612,12 +654,13 @@ int main(int argc,char **argv)
int seed = 0;
crope viz_prefix;
bool scoring_selftest = false;
bool prechecks_only = false;
// Handle command line
char ch;
timelimit = 0.0;
timetarget = 0.0;
while ((ch = getopt(argc,argv,"s:v:l:t:rpPTdH:oguc:")) != -1) {
while ((ch = getopt(argc,argv,"s:v:l:t:rpPTdH:oguc:n")) != -1) {
switch (ch) {
case 's':
if (sscanf(optarg,"%d",&seed) != 1) {
......@@ -674,6 +717,10 @@ int main(int argc,char **argv)
print_help();
}
break;
case 'n':
prechecks_only = true;
cout << "Doing only prechecks, exiting early" << endl;
break;
default:
print_help();
}
......@@ -753,6 +800,11 @@ int main(int argc,char **argv)
exit(EXIT_UNRETRYABLE);
}
// Bomb out early if we're only doing the prechecks
if (prechecks_only) {
exit(EXIT_SUCCESS);
}
#ifdef PER_VNODE_TT
if (prune_pclasses) {
prune_unusable_pclasses();
......
......@@ -178,27 +178,21 @@ int parse_ptop(tb_pgraph &PG, tb_sgraph &SG, istream& i)
pname2vertex[name] = pv;
}
} else if (command.compare("link") == 0) {
if (parsed_line.size() < 7) {
if (parsed_line.size() < 8) {
ptop_error("Bad link line, too few arguments.");
}
int num = 1;
#ifdef PENALIZE_BANDWIDTH
float penalty;
if (parsed_line.size() == 8) {
if (sscanf(parsed_line[7].c_str(),"%f",&penalty) != 1) {
ptop_error("Bad number argument: " << parsed_line[7] << ".");
if (parsed_line.size() == 9) {
if (sscanf(parsed_line[8].c_str(),"%f",&penalty) != 1) {
ptop_error("Bad number argument: " << parsed_line[8] << ".");
penalty=1.0;
}
}
#else
if (parsed_line.size() == 8) {
if (sscanf(parsed_line[7].c_str(),"%d",&num) != 1) {
ptop_error("Bad number argument: " << parsed_line[7] << ".");
num=1;
}
}
#endif
#if 0
#ifdef FIX_PLINK_ENDPOINTS
bool fixends;
#ifdef FIX_PLINKS_DEFAULT
......@@ -206,16 +200,18 @@ int parse_ptop(tb_pgraph &PG, tb_sgraph &SG, istream& i)
#else
fixends = false;
#endif
if (parsed_line.size() == 9) {
if (parsed_line[8].compare("fixends") == 0) {
if (parsed_line.size() == 10) {
if (parsed_line[9].compare("fixends") == 0) {
fixends = true;
}
}
#else
if (parsed_line.size() > 8) {
if (parsed_line.size() > 9) {
ptop_error("Bad link line, too many arguments.");
}
#endif
#endif
crope name = parsed_line[1];
crope src,srcmac;
split_two(parsed_line[2],':',src,srcmac,"(null)");
......@@ -224,6 +220,7 @@ int parse_ptop(tb_pgraph &PG, tb_sgraph &SG, istream& i)
crope bw = parsed_line[4];
crope delay = parsed_line[5];
crope loss = parsed_line[6];
crope link_type = parsed_line[7];
int ibw,idelay;
double gloss;
......@@ -252,14 +249,17 @@ int parse_ptop(tb_pgraph &PG, tb_sgraph &SG, istream& i)
for (int cur = 0;cur<num;++cur) {
pedge pe = (add_edge(srcv,dstv,PG)).first;
tb_plink *pl = new tb_plink(name,tb_plink::PLINK_NORMAL,srcmac,dstmac);
tb_plink *pl = new
tb_plink(name,tb_plink::PLINK_NORMAL,link_type,srcmac,dstmac);
put(pedge_pmap,pe,pl);
pl->delay_info.bandwidth = ibw;
pl->delay_info.delay = idelay;
pl->delay_info.loss = gloss;
#if 0
#ifdef FIX_PLINK_ENDPOINTS
pl->fixends = fixends;
#endif
#endif
#ifdef PENALIZE_BANDWIDTH
pl->penalty = penalty;
#endif
......@@ -275,11 +275,19 @@ int parse_ptop(tb_pgraph &PG, tb_sgraph &SG, istream& i)
tb_slink *sl = new tb_slink();
put(sedge_pmap,swedge,sl);
sl->mate = pe;
pl->type = tb_plink::PLINK_INTERSWITCH;
pl->is_type = tb_plink::PLINK_INTERSWITCH;
}
}
srcnode->total_interfaces++;
dstnode->total_interfaces++;
srcnode->link_counts[link_type]++;
dstnode->link_counts[link_type]++;
for (int i = 8; i < parsed_line.size(); i++) {
crope link_type = parsed_line[i];
pl->types.insert(link_type);
srcnode->link_counts[link_type]++;
dstnode->link_counts[link_type]++;
}
if (ISSWITCH(srcnode) &&
! ISSWITCH(dstnode)) {
dstnode->switches.insert(srcv);
......
......@@ -158,12 +158,13 @@ int parse_top(tb_vgraph &VG, istream& i)
}
}
} else if (command.compare("link") == 0) {
if (parsed_line.size() < 7) {
if (parsed_line.size() < 8) {
top_error("Bad link line, too few arguments.");
} else {
crope name = parsed_line[1];
crope src = parsed_line[2];
crope dst = parsed_line[3];
crope link_type = parsed_line[7];
crope bw,bwunder,bwover;
crope delay,delayunder,delayover;
crope loss,lossunder,lossover;
......@@ -238,6 +239,7 @@ int parse_top(tb_vgraph &VG, istream& i)
tb_vlink *l = new tb_vlink();
l->src = node1;
l->dst = node2;
l->type = link_type;
put(vedge_pmap,e,l);
if ((sscanf(bw.c_str(),"%d",&(l->delay_info.bandwidth)) != 1) ||
......@@ -264,7 +266,7 @@ int parse_top(tb_vgraph &VG, istream& i)
#endif
l->emulated = false;
for (unsigned int i = 7;i < parsed_line.size();++i) {
for (unsigned int i = 8;i < parsed_line.size();++i) {
if (parsed_line[i].compare("nodelay") == 0) {
l->allow_delayed = false;
} else if (parsed_line[i].compare("emulated") == 0) {
......@@ -288,6 +290,8 @@ int parse_top(tb_vgraph &VG, istream& i)
} else {
vnode1->num_links++;
vnode2->num_links++;
vnode1->link_counts[link_type]++;
vnode2->link_counts[link_type]++;
}
#endif
}
......
......@@ -11,7 +11,7 @@
#include <hash_map>
#include <rope>
#include <queue>
#include <slist>
#include <list>
#include <algorithm>
#include <boost/config.hpp>
......@@ -48,26 +48,15 @@ extern pclass_list pclasses;
// length of the array.
extern pclass_types type_table;
typedef pair<pvertex,int> link_info; // dst, bw
struct hashlinkinfo {
size_t operator()(link_info const &A) const {
hashptr<void *> ptrhash;
return ptrhash(A.first)/2+A.second;
}
};
// returns 1 if a and b are equivalent. They are equivalent if the
// type and features information match and if there is a one-to-one
// mapping between links that preserves bw, and destination.
int pclass_equiv(tb_pgraph &PG, tb_pnode *a,tb_pnode *b)
{
typedef hash_multiset<link_info,hashlinkinfo> link_set;
// The unique flag is used to signify that there is some reason that assign
// is not aware of that the node is unique, and shouldn't be put into a
// pclass. The usual reason for doing this is for scoring purposes - ie.
// don't prefer one just because it's the same pclass as another that, in
// don't prefer one just because it's the same pclass over another that, in
// reality, is very different.
if (a->unique || b->unique) {
return 0;
......@@ -129,33 +118,51 @@ int pclass_equiv(tb_pgraph &PG, tb_pnode *a,tb_pnode *b)
}
}
// check links - to do this we first create sets of every link in b.
// we then loop through every link in a, find a match in the set, and
// remove it from the set.
// Check links
pvertex an = pnode2vertex[a];
pvertex bn = pnode2vertex[b];
link_set b_links;
// Make a list of all links for node b
typedef list<pedge> link_list;
link_list b_links;
poedge_iterator eit,eendit;
tie(eit,eendit) = out_edges(bn,PG);
for (;eit != eendit;++eit) {
pvertex dst = target(*eit,PG);
if (dst == bn)
dst = source(*eit,PG);
b_links.insert(link_info(dst,get(pedge_pmap,*eit)->delay_info.bandwidth));
b_links.push_back(*eit);
}
// Go through all of a's links, trying to find matches on node b. If we find
// a match, we remove it from the list
tie(eit,eendit) = out_edges(an,PG);
for (;eit != eendit;++eit) {
pvertex dst = target(*eit,PG);
if (dst == an)
dst = source(*eit,PG);
int bw = get(pedge_pmap,*eit)->delay_info.bandwidth;
link_info tomatch = link_info(dst,bw);
link_set::iterator found = b_links.find(tomatch);
if (found == b_links.end()) return 0;
else b_links.erase(found);
tb_plink *plink_a = get(pedge_pmap,*eit);
pvertex dest_pv_a = target(*eit,PG);
if (dest_pv_a == a)
dest_pv_a = source(*eit,PG);
link_list::iterator bit;
for (bit = b_links.begin(); bit != b_links.end(); bit++) {
tb_plink *plink_b = get(pedge_pmap,*bit);
pvertex dest_pv_b = target(*bit,PG);
if (dest_pv_b == b)
dest_pv_b = source(*bit,PG);
// If links are equivalent, remove this link in b from further
// consideration, and go to the next link in a
if ((dest_pv_a == dest_pv_b) && plink_a->is_equiv(*plink_b)) {
b_links.erase(bit);
break;
}
}
// If we never found a match, these nodes aren't equivalent
if (bit == b_links.end()) {
return 0;
}
}
// Make sure node b has no extra links
if (b_links.size() != 0) return 0;
return 1;
}
......
......@@ -61,6 +61,8 @@ typedef hash_map<svertex,switch_dist_map*>switch_dist_map_map;
typedef list<pedge> pedge_path;
typedef list<pvertex> pvertex_list;
typedef hash_map<crope,int> link_type_count_map;
// Globals, declared in assign.cc
extern tb_pgraph_vertex_pmap pvertex_pmap;
......@@ -156,6 +158,9 @@ public:
bool is_switch; // Indicates whether or not this pnode is a
// switch
//
link_type_count_map link_counts; // Counts how many links of each type this
// node has
bool set_current_type(crope type) {
if (types.find(type) == types.end()) {
......@@ -228,17 +233,22 @@ typedef hash_map<nodepair,int,pairhash<crope> > nodepair_count_map;
class tb_plink {
public:
typedef enum {PLINK_NORMAL,PLINK_INTERSWITCH,PLINK_LAN} plinkType;
typedef hash_set<crope> type_set;
tb_plink(crope _name, plinkType _type, crope _srcmac, crope _dstmac)
: name(_name), srcmac(_srcmac), dstmac(_dstmac), type(_type),
tb_plink(crope _name, plinkType _is_type, crope _type, crope _srcmac, crope
_dstmac)
: name(_name), srcmac(_srcmac), dstmac(_dstmac), is_type(_is_type),
delay_info(), bw_used(0), emulated(0), nonemulated(0),
penalty(0.0), fixends(false), current_endpoints(), current_count(0),
vedge_counts() {;}
vedge_counts() {
types.insert(_type);
}
crope name; // the name
crope srcmac,dstmac; // source and destination MAC addresses.
plinkType type; // type of the link
plinkType is_type; // inter-switch type of the link
type_set types; // type (ie. ethernet) of the link
tb_delay_info delay_info; // the delay characteristics of this link
int bw_used; // how much is used
......@@ -258,7 +268,7 @@ public:
{
o << "tb_plink: " << link.name << " (" << &link << ")" << endl;
o << " type: ";
switch (link.type) {
switch (link.is_type) {
case tb_plink::PLINK_NORMAL:
o << "normal" << endl;
break;
......@@ -276,6 +286,21 @@ public:
o << link.delay_info;
return o;
}
// Return true if the two plinks are equivalent, in terms of type and
// bandwidth.
// NOTE: should probably use a helper function in delay_info, but right now,
// we only care about bandwidth
const bool is_equiv(const tb_plink& link) {
if (types == link.types) {
return false;
}
if (delay_info.bandwidth != link.delay_info.bandwidth) {
return false;
}
return true;
}
};
class tb_slink {
......
......@@ -129,7 +129,7 @@ void init_score()
tie(vedge_it,end_vedge_it) = edges(VG);
for (;vedge_it!=end_vedge_it;++vedge_it) {
tb_vlink *vlink=get(vedge_pmap,*vedge_it);
vlink->link_info.type=tb_link_info::LINK_UNKNOWN;
vlink->link_info.type_used=tb_link_info::LINK_UNMAPPED;
vlink->no_connection=false;
}
pvertex_iterator pvertex_it,end_pvertex_it;
......@@ -166,7 +166,7 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
// Handle vnodes that are not allowed to have a mix of trivial and
// non-trivial links
if (vlink->link_info.type == tb_link_info::LINK_TRIVIAL) {
if (vlink->link_info.type_used == tb_link_info::LINK_TRIVIAL) {
src_vnode->trivial_links--;
dst_vnode->trivial_links--;
if (src_vnode->disallow_trivial_mix &&
......@@ -185,7 +185,7 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
violated--;
vinfo.trivial_mix--;
}
} else if (vlink->link_info.type != tb_link_info::LINK_UNKNOWN) {
} else if (vlink->link_info.type_used != tb_link_info::LINK_UNMAPPED) {
src_vnode->nontrivial_links--;
dst_vnode->nontrivial_links--;
if (src_vnode->disallow_trivial_mix &&
......@@ -207,7 +207,7 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
}
// Unscore the link itself
if (vlink->link_info.type == tb_link_info::LINK_DIRECT) {
if (vlink->link_info.type_used == tb_link_info::LINK_DIRECT) {
// DIRECT LINK
SDEBUG(cerr << " direct link" << endl);
src_pnode->nontrivial_bw_used -= vlink->delay_info.bandwidth;
......@@ -216,7 +216,7 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
SSUB(SCORE_DIRECT_LINK);
unscore_link(vlink->link_info.plinks.front(),ve,src_pnode,dst_pnode);
vlink->link_info.plinks.clear();
} else if (vlink->link_info.type == tb_link_info::LINK_INTERSWITCH) {
} else if (vlink->link_info.type_used == tb_link_info::LINK_INTERSWITCH) {
// INTERSWITCH LINK
SDEBUG(cerr << " interswitch link" << endl);
src_pnode->nontrivial_bw_used -= vlink->delay_info.bandwidth;
......@@ -253,7 +253,7 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
the_switch->nontrivial_bw_used -= vlink->delay_info.bandwidth * 2;
}
vlink->link_info.switches.clear();
} else if (vlink->link_info.type == tb_link_info::LINK_INTRASWITCH) {
} else if (vlink->link_info.type_used == tb_link_info::LINK_INTRASWITCH) {
// INTRASWITCH LINK
SDEBUG(cerr << " intraswitch link" << endl);
src_pnode->nontrivial_bw_used -= vlink->delay_info.bandwidth;
......@@ -276,7 +276,7 @@ void unscore_link_info(vedge ve,tb_pnode *src_pnode,tb_pnode *dst_pnode, tb_vnod
}
#ifdef TRIVIAL_LINK_BW
else if (vlink->link_info.type == tb_link_info::LINK_TRIVIAL) {
else if (vlink->link_info.type_used == tb_link_info::LINK_TRIVIAL) {
// Trivial link - we may get to remove violations
SDEBUG(cerr << " trivial bandwidth used " <<
src_pnode->trivial_bw_used << " max is " <<
......@@ -539,7 +539,7 @@ void score_link_info(vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode, tb_vnod
{
tb_vlink *vlink = get(vedge_pmap,ve);
tb_pnode *the_switch;
switch (vlink->link_info.type) {
switch (vlink->link_info.type_used) {
case tb_link_info::LINK_DIRECT:
SADD(SCORE_DIRECT_LINK);
src_pnode->nontrivial_bw_used += vlink->delay_info.bandwidth;
......@@ -628,7 +628,7 @@ void score_link_info(vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode, tb_vnod
}
break;
#endif
case tb_link_info::LINK_UNKNOWN:
case tb_link_info::LINK_UNMAPPED:
cout << "Internal error: Should not be here either." << endl;
exit(EXIT_FATAL);
break;
......@@ -636,7 +636,7 @@ void score_link_info(vedge ve, tb_pnode *src_pnode, tb_pnode *dst_pnode, tb_vnod
// Handle vnodes that are not allowed to have a mix of trivial and
// non-trivial links
if (vlink->link_info.type == tb_link_info::LINK_TRIVIAL) {
if (vlink->link_info.type_used == tb_link_info::LINK_TRIVIAL) {
src_vnode->trivial_links++;
dst_vnode->trivial_links++;
if (src_vnode->disallow_trivial_mix &&
......@@ -849,7 +849,7 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
seen_loopback_links.insert(vlink);
}
if (allow_trivial_links && vlink->allow_trivial) {
vlink->link_info.type = tb_link_info::LINK_TRIVIAL;
vlink->link_info.type_used = tb_link_info::LINK_TRIVIAL;
// XXX - okay, this is really bad, but score_link_info doesn't
// usually get called for trivial links, and letting them fall
// through into the 'normal' link code below is disatrous!
......@@ -875,7 +875,7 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
pedge pe;
// Direct link
if (find_best_link(dest_pv,pv,vlink,pe)) {
resolutions[resolution_index].type = tb_link_info::LINK_DIRECT;
resolutions[resolution_index].type_used = tb_link_info::LINK_DIRECT;
resolutions[resolution_index].plinks.push_back(pe);
resolution_index++;
total_weight += LINK_RESOLVE_DIRECT;
......@@ -924,7 +924,8 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
}
resolutions[resolution_index].type = tb_link_info::LINK_INTRASWITCH;
resolutions[resolution_index].type_used =
tb_link_info::LINK_INTRASWITCH;
if (flipped) { // Order these need to go in depends on flipped bit
if (second_link) {
resolutions[resolution_index].plinks.push_back(second);
......@@ -997,7 +998,8 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
}
}
resolutions[resolution_index].type = tb_link_info::LINK_INTERSWITCH;
resolutions[resolution_index].type_used =
tb_link_info::LINK_INTERSWITCH;
if (flipped) { // Order these need to go in depends on flipped bit
if (second_link) {
resolutions[resolution_index].plinks.push_front(second);
......@@ -1033,7 +1035,7 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
SADD(SCORE_NO_CONNECTION);
vlink->no_connection=true;
vinfo.no_connection++;
vlink->link_info.type = tb_link_info::LINK_UNKNOWN;
vlink->link_info.type_used = tb_link_info::LINK_UNMAPPED;
violated++;
} else {
// Check to see if we are fixing a violation
......@@ -1051,14 +1053,14 @@ int add_node(vvertex vv,pvertex pv, bool deterministic, bool is_fixed)
float choice;
choice = std::random()%(int)total_weight;
for (index = 0;index < resolution_index;++index) {
switch (resolutions[index].type) {
switch (resolutions[index].type_used) {
case tb_link_info::LINK_DIRECT:
choice -= LINK_RESOLVE_DIRECT; break;
case tb_link_info::LINK_INTRASWITCH:
choice -= LINK_RESOLVE_INTRASWITCH; break;
case tb_link_info::LINK_INTERSWITCH:
choice -= LINK_RESOLVE_INTERSWITCH; break;
case tb_link_info::LINK_UNKNOWN:
case tb_link_info::LINK_UNMAPPED:
case tb_link_info::LINK_TRIVIAL:
cerr << "Internal error: Should not be here." << endl;
exit(EXIT_FATAL);
......@@ -1194,6 +1196,11 @@ bool find_best_link(pvertex pv,pvertex switch_pv,tb_vlink *vlink,
if (dest_pv == switch_pv) {
tb_plink *plink = get(pedge_pmap,*pedge_it);
// Skip any links whose type is wrong (ie. doesn't match the vlink)
if (plink->types.find(vlink->type) == plink->types.end()) {
continue;
}
// Get delay characteristics - NOTE: Currently does not actually do
// anything
tb_delay_info physical_delay;
......@@ -1303,7 +1310,7 @@ void score_link(pedge pe,vedge ve,tb_pnode *src_pnode, tb_pnode *dst_pnode)
cerr << *vlink;
#endif
if (plink->type == tb_plink::PLINK_NORMAL) {
if (plink->is_type <