Skip to content

Commit b568631

Browse files
committed
Add error check to ensure all pins have locations when pattern="custom"
Previously this was not checked and exhibited itself as unconnectible pins during routing, with no obvious cause (see Github issue #181).
1 parent 1d9b571 commit b568631

File tree

3 files changed

+101
-12
lines changed

3 files changed

+101
-12
lines changed

libarchfpga/src/read_xml_arch_file.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,77 @@ static void SetupPinLocationsAndPinClasses(pugi::xml_node Locations,
427427
}
428428
Cur = Cur.next_sibling(Cur.name());
429429
}
430+
431+
//Verify that all top-level pins have had thier locations specified
432+
433+
//Count up all the specified pins
434+
std::map<std::string,std::set<int>> port_pins_with_specified_locations;
435+
for (int w = 0; w < Type->width; ++w) {
436+
for (int h = 0; h < Type->height; ++h) {
437+
for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) {
438+
for (int itoken = 0; itoken < Type->num_pin_loc_assignments[w][h][side]; ++itoken) {
439+
const char* pin_spec = Type->pin_loc_assignments[w][h][side][itoken];
440+
InstPort inst_port(Type->pin_loc_assignments[w][h][side][itoken]);
441+
442+
//A pin specification should contain only the block name, and not any instace count information
443+
if (inst_port.instance_low_index() != InstPort::UNSPECIFIED || inst_port.instance_high_index() != InstPort::UNSPECIFIED) {
444+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
445+
"Pin location specification '%s' should not contain an instance range (should only be the block name)",
446+
pin_spec);
447+
}
448+
449+
//Check that the block name matches
450+
if (inst_port.instance_name() != Type->name) {
451+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
452+
"Mismatched block name in pin location specification (expected '%s' was '%s')",
453+
Type->name, inst_port.instance_name().c_str());
454+
}
455+
456+
int pin_low_idx = inst_port.port_low_index();
457+
int pin_high_idx = inst_port.port_high_index();
458+
459+
if(pin_low_idx == InstPort::UNSPECIFIED && pin_high_idx == InstPort::UNSPECIFIED) {
460+
//Empty range, so full port
461+
462+
//Find the matching pb type to get the total number of pins
463+
const t_port* port = nullptr;
464+
for (int iport = 0; iport < Type->pb_type->num_ports; ++iport) {
465+
const t_port* tmp_port = &Type->pb_type->ports[iport];
466+
if (tmp_port->name == inst_port.port_name()) {
467+
port = tmp_port;
468+
break;
469+
}
470+
}
471+
VTR_ASSERT(port);
472+
473+
pin_low_idx = 0;
474+
pin_high_idx = port->num_pins - 1;
475+
}
476+
VTR_ASSERT(pin_low_idx >= 0);
477+
VTR_ASSERT(pin_high_idx >= 0);
478+
479+
for (int ipin = pin_low_idx; ipin <= pin_high_idx; ++ipin) {
480+
//Record that the pin has it's location specified
481+
port_pins_with_specified_locations[inst_port.port_name()].insert(ipin);
482+
}
483+
}
484+
}
485+
}
486+
}
487+
488+
//Check for any pins missing location specs
489+
for (int iport = 0; iport < Type->pb_type->num_ports; ++iport) {
490+
const t_port* port = &Type->pb_type->ports[iport];
491+
492+
for (int ipin = 0; ipin < port->num_pins; ++ipin) {
493+
if (!port_pins_with_specified_locations[port->name].count(ipin)) {
494+
//Missing
495+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Locations),
496+
"Pin '%s.%s[%d]' has no pin location specificed with pin location pattern=\"custom\"",
497+
Type->name, port->name, ipin);
498+
}
499+
}
500+
}
430501
}
431502

432503
/* Setup pin classes */

libarchfpga/src/read_xml_util.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ InstPort::InstPort(std::string str) {
1818
std::vector<std::string> inst_port = vtr::split(str, ".");
1919

2020
if(inst_port.size() == 1) {
21-
instance_ = {"", 0, 0};
21+
instance_ = {"", -1, -1};
2222
port_ = parse_name_index(inst_port[0]);
2323

2424
} else if(inst_port.size() == 2) {
@@ -29,8 +29,18 @@ InstPort::InstPort(std::string str) {
2929
}
3030
}
3131

32-
InstPort::InstPort(pugi::xml_attribute attr, pugi::xml_node node, const pugiutil::loc_data& loc_data) {
32+
InstPort::InstPort(std::string str, pugi::xml_node node, const pugiutil::loc_data& loc_data) {
33+
try {
34+
*this = InstPort(str);
35+
} catch (const ArchFpgaError& e) {
36+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(node),
37+
"Failed to parse instance port specification '%s' for"
38+
" on <%s> tag, %s",
39+
str.c_str(), node.name(), e.what());
40+
}
41+
}
3342

43+
InstPort::InstPort(pugi::xml_attribute attr, pugi::xml_node node, const pugiutil::loc_data& loc_data) {
3444
try {
3545
*this = InstPort(attr.value());
3646
} catch (const ArchFpgaError& e) {
@@ -92,23 +102,28 @@ InstPort::name_index InstPort::parse_name_index(std::string str) {
92102
second_idx_str = str.substr(colon_pos + 1, close_bracket_pos);
93103
}
94104

95-
size_t first_idx = 0;
105+
int first_idx = UNSPECIFIED;
96106
if(!first_idx_str.empty()) {
97107
std::stringstream ss(first_idx_str);
98-
ss >> first_idx;
108+
size_t idx;
109+
ss >> idx;
99110
if(!ss.good()) {
100111
std::string msg = "near '" + str + "', expected positive integer";
101112
throw ArchFpgaError(msg);
102113
}
114+
first_idx = idx;
103115
}
104-
size_t second_idx = 0;
116+
117+
int second_idx = UNSPECIFIED;
105118
if(!second_idx_str.empty()) {
106119
std::stringstream ss(second_idx_str);
107-
ss >> second_idx;
120+
size_t idx;
121+
ss >> idx;
108122
if(!ss.good()) {
109123
std::string msg = "near '" + str + "', expected positive integer";
110124
throw ArchFpgaError(msg);
111125
}
126+
second_idx = idx;
112127
}
113128

114129
return {name, std::min(first_idx, second_idx), std::max(first_idx, second_idx)};

libarchfpga/src/read_xml_util.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,24 @@ void bad_attribute_value(const pugi::xml_attribute attr,
2525

2626
class InstPort {
2727
public:
28+
static constexpr int UNSPECIFIED = -1;
29+
2830
InstPort(std::string str);
31+
InstPort(std::string str, pugi::xml_node node, const pugiutil::loc_data& loc_data);
2932
InstPort(pugi::xml_attribute attr, pugi::xml_node node, const pugiutil::loc_data& loc_data);
3033
std::string instance_name() { return instance_.name; }
3134
std::string port_name() { return port_.name; }
3235

33-
size_t instance_low_index() { return instance_.low_idx; }
34-
size_t instance_high_index() { return instance_.high_idx; }
35-
size_t port_low_index() { return port_.low_idx; }
36-
size_t port_high_index() { return port_.high_idx; }
36+
int instance_low_index() { return instance_.low_idx; }
37+
int instance_high_index() { return instance_.high_idx; }
38+
int port_low_index() { return port_.low_idx; }
39+
int port_high_index() { return port_.high_idx; }
3740

3841
private:
3942
struct name_index {
4043
std::string name;
41-
size_t low_idx;
42-
size_t high_idx;
44+
int low_idx;
45+
int high_idx;
4346
};
4447

4548
name_index parse_name_index(std::string str);

0 commit comments

Comments
 (0)