Skip to content

Commit 5d21ac7

Browse files
committed
Add support for constant networks
Update to new mainline Signed-off-by: Maciej Dudek <[email protected]>
1 parent 026455a commit 5d21ac7

File tree

3 files changed

+164
-42
lines changed

3 files changed

+164
-42
lines changed

libs/libarchfpga/src/read_fpga_interchange_arch.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,6 +2069,7 @@ struct ArchReader {
20692069
t_sub_tile sub_tile;
20702070
sub_tile.index = 0;
20712071
sub_tile.name = vtr::strdup(const_block_.c_str());
2072+
sub_tile.capacity.set(0, 0);
20722073
int count = 0;
20732074
for (auto const_cell : const_cells) {
20742075
sub_tile.sub_tile_to_tile_pin_indices.push_back(count);
@@ -2079,7 +2080,7 @@ struct ArchReader {
20792080

20802081
port.name = vtr::strdup((const_cell.first + "_" + const_cell.second).c_str());
20812082

2082-
port.index = port.absolute_first_pin_index = port.port_index_by_type = 0;
2083+
port.index = port.absolute_first_pin_index = port.port_index_by_type = count;
20832084

20842085
sub_tile.ports.push_back(port);
20852086

@@ -2159,10 +2160,10 @@ struct ArchReader {
21592160
grid_def.loc_defs.emplace_back(std::move(single));
21602161
}
21612162

2162-
// The constant source tile will be placed at (0, 0)
2163+
// The constant source tile will be placed at (1, max_height)
21632164
t_grid_loc_def constant(const_block_, 1);
21642165
constant.x.start_expr = std::to_string(1);
2165-
constant.y.start_expr = std::to_string(1);
2166+
constant.y.start_expr = std::to_string(grid_def.height -1);
21662167

21672168
constant.x.end_expr = constant.x.start_expr + " + w - 1";
21682169
constant.y.end_expr = constant.y.start_expr + " + h - 1";

vpr/src/route/rr_graph_fpga_interchange.cpp

Lines changed: 158 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,15 @@ struct RR_Graph_Builder {
178178
std::unordered_map<std::tuple<int /*timing_model*/, bool /*buffered*/>, int /*idx*/, hash_tuple::hash<std::tuple<int, bool>>> pips_models_;
179179
std::unordered_map<std::tuple<int /*node_id*/, int /*node_id*/>, std::tuple<int /*switch_id*/, int /* tile_id */, std::tuple<int /*name*/, int /*wire0*/, int /*wire1*/, bool /*forward*/>>, hash_tuple::hash<std::tuple<int, int>>> pips_;
180180

181-
std::map<std::tuple<int, int>, int> wire_to_node_;
181+
std::unordered_map<std::tuple<int, int>,
182+
int,
183+
hash_tuple::hash<std::tuple<int,int>>> wire_to_node_;
182184
std::unordered_map<int, std::set<location>> node_to_locs_;
183-
std::map<std::tuple<int, int> /*<node, tile_id>*/, int /*segment type*/> node_tile_to_segment_;
185+
std::unordered_map<std::tuple<int, int> /*<node, tile_id>*/,
186+
int /*segment type*/,
187+
hash_tuple::hash<std::tuple<int,int>>> node_tile_to_segment_;
188+
std::unordered_map<int, std::pair<float, float>> node_to_RC_;
189+
int total_node_count_;
184190

185191
/*
186192
* Offsets for FPGA Interchange node processing
@@ -246,6 +252,8 @@ struct RR_Graph_Builder {
246252
}
247253

248254
std::string str(int idx) {
255+
if (idx == -1)
256+
return std::string("constant_block");
249257
return std::string(ar_.getStrList()[idx].cStr());
250258
}
251259

@@ -379,10 +387,10 @@ struct RR_Graph_Builder {
379387
device_ctx_.rr_switch_inf.reserve(seen.size() + 1);
380388
int id = 2;
381389
make_room_in_vector(&device_ctx_.rr_switch_inf, 0);
382-
fill_switch(device_ctx_.rr_switch_inf[0], 0, 0, 0, 0, 0, 0, 0,
390+
fill_switch(device_ctx_.rr_switch_inf[RRSwitchId(0)], 0, 0, 0, 0, 0, 0, 0,
383391
vtr::strdup("short"), SwitchType::SHORT);
384392
make_room_in_vector(&device_ctx_.rr_switch_inf, 1);
385-
fill_switch(device_ctx_.rr_switch_inf[1], 0, 0, 0, 0, 0, 0, 0,
393+
fill_switch(device_ctx_.rr_switch_inf[RRSwitchId(1)], 0, 0, 0, 0, 0, 0, 0,
386394
vtr::strdup("generic"), SwitchType::MUX);
387395
const auto& pip_models = ar_.getPipTimings();
388396
float R, Cin, Cout, Cint, Tdel;
@@ -423,7 +431,7 @@ struct RR_Graph_Builder {
423431
type = buffered ? SwitchType::MUX : SwitchType::PASS_GATE;
424432
mux_trans_size = buffered ? 1 : 0;
425433

426-
fill_switch(device_ctx_.rr_switch_inf[id], R, Cin, Cout, Cint, Tdel,
434+
fill_switch(device_ctx_.rr_switch_inf[RRSwitchId(id)], R, Cin, Cout, Cint, Tdel,
427435
mux_trans_size, 0, vtr::strdup(switch_name.c_str()), type);
428436

429437
id++;
@@ -434,32 +442,121 @@ struct RR_Graph_Builder {
434442
* Create mapping form tile_id to its location
435443
*/
436444
void create_tile_id_to_loc() {
445+
int max_height = 0;
437446
for (const auto& tile : ar_.getTileList()) {
438447
tile_to_loc_[tile.getName()] = location(tile.getCol() + 1, tile.getRow() + 1);
448+
max_height = std::max(max_height, (int)(tile.getRow() +1));
439449
loc_to_tile_[location(tile.getCol() + 1, tile.getRow() + 1)] = tile.getName();
440450
}
451+
/* tile with name -1 is assosiated with constant source tile */
452+
tile_to_loc_[-1] = location(1, max_height + 1);
453+
loc_to_tile_[location(1, max_height + 1)] = -1;
441454
}
442455

443456
/*
444457
* Create uniq id for each FPGA Interchange node.
445458
* Create mapping from wire to node id and from node id to its locations
446459
* These ids are used later for site pins and pip conections (rr_edges)
447460
*/
461+
void process_const_nodes() {
462+
for (const auto& tile : ar_.getTileList()) {
463+
int tile_id = tile.getName();
464+
auto tile_type = ar_.getTileTypeList()[tile.getType()];
465+
auto wires = tile_type.getWires();
466+
for (const auto& constant : tile_type.getConstants()){
467+
int const_id = constant.getConstant() == Device::ConstantType::VCC ? 1 : 0;
468+
for (const auto wire_id : constant.getWires()) {
469+
wire_to_node_[std::make_tuple(tile_id, wires[wire_id])] = const_id;
470+
node_to_locs_[const_id].insert(tile_to_loc_[tile_id]);
471+
if (wire_name_to_seg_idx_.find(str(wires[wire_id])) == wire_name_to_seg_idx_.end())
472+
wire_name_to_seg_idx_[str(wires[wire_id])] = -1;
473+
node_tile_to_segment_[std::make_tuple(const_id, tile_id)] = wire_name_to_seg_idx_[str(wires[wire_id])];
474+
}
475+
}
476+
}
477+
for (const auto& node_source : ar_.getConstants().getNodeSources()) {
478+
int tile_id = node_source.getTile();
479+
int wire_id = node_source.getWire();
480+
int const_id = node_source.getConstant() == Device::ConstantType::VCC ? 1 : 0;
481+
wire_to_node_[std::make_tuple(tile_id, wire_id)] = const_id;
482+
node_to_locs_[const_id].insert(tile_to_loc_[tile_id]);
483+
if (wire_name_to_seg_idx_.find(str(wire_id)) == wire_name_to_seg_idx_.end())
484+
wire_name_to_seg_idx_[str(wire_id)] = -1;
485+
node_tile_to_segment_[std::make_tuple(const_id, tile_id)] = wire_name_to_seg_idx_[str(wire_id)];
486+
}
487+
for (int i = 0; i < 2; ++i) {
488+
wire_to_node_[std::make_tuple(-1, i)] = i;
489+
node_to_locs_[i].insert(tile_to_loc_[-1]);
490+
node_tile_to_segment_[std::make_tuple(i, -1)] = -1;
491+
}
492+
}
493+
448494
void create_uniq_node_ids() {
449-
int id = 0;
495+
/*
496+
Process constant sources
497+
*/
498+
process_const_nodes();
499+
/*
500+
Process nodes
501+
*/
502+
int id = 2;
503+
bool constant_node;
504+
int node_id;
450505
for (const auto& node : ar_.getNodes()) {
506+
constant_node = false;
507+
/*
508+
Nodes connected to constant sources should be combined into single constant node
509+
*/
451510
for (const auto& wire_id_ : node.getWires()) {
452511
const auto& wire = ar_.getWires()[wire_id_];
453512
int tile_id = wire.getTile();
454513
int wire_id = wire.getWire();
455-
wire_to_node_[std::make_tuple(tile_id, wire_id)] = id;
456-
node_to_locs_[id].insert(tile_to_loc_[tile_id]);
514+
if (wire_to_node_.find(std::make_tuple(tile_id, wire_id)) != wire_to_node_.end() &&
515+
wire_to_node_[std::make_tuple(tile_id, wire_id)] < 2) {
516+
constant_node = true;
517+
node_id = wire_to_node_[std::make_tuple(tile_id, wire_id)];
518+
}
519+
}
520+
if (!constant_node){
521+
node_id = id++;
522+
}
523+
float capacitance = 0.0, resistance = 0.0; // Some random data
524+
if (node_to_RC_.find(node_id) == node_to_RC_.end()) {
525+
node_to_RC_[node_id] = std::pair<float, float>(0, 0);
526+
capacitance = 0.000000001; resistance = 5.7;
527+
}
528+
if (ar_.hasNodeTimings()) {
529+
auto model = ar_.getNodeTimings()[node.getNodeTiming()];
530+
capacitance = get_corner_value(model.getCapacitance(), "slow", "typ");
531+
resistance = get_corner_value(model.getResistance(), "slow", "typ");
532+
}
533+
node_to_RC_[node_id].first += resistance;
534+
node_to_RC_[node_id].second += capacitance;
535+
#ifdef DEBUG
536+
if (constant_node) {
537+
const auto& wires = ar_.getWires();
538+
std::tuple<int, int> base_wire_(wires[node.getWires()[0]].getTile(), wires[node.getWires()[0]].getWire());
539+
VTR_LOG("Constant_node: %s\n", wire_to_node_[base_wire_] == 1 ? "VCC\0": "GND\0");
540+
for (const auto& wire_id_ : node.getWires()) {
541+
const auto& wire = ar_.getWires()[wire_id_];
542+
int tile_id = wire.getTile();
543+
int wire_id = wire.getWire();
544+
VTR_LOG("tile:%s wire:%s\n", str(tile_id).c_str(), str(wire_id).c_str());
545+
}
546+
}
547+
#endif
548+
for (const auto& wire_id_ : node.getWires()) {
549+
const auto& wire = ar_.getWires()[wire_id_];
550+
int tile_id = wire.getTile();
551+
int wire_id = wire.getWire();
552+
wire_to_node_[std::make_tuple(tile_id, wire_id)] = node_id;
553+
node_to_locs_[node_id].insert(tile_to_loc_[tile_id]);
457554
if (wire_name_to_seg_idx_.find(str(wire_id)) == wire_name_to_seg_idx_.end())
458555
wire_name_to_seg_idx_[str(wire_id)] = -1;
459-
node_tile_to_segment_[std::make_tuple(id, tile_id)] = wire_name_to_seg_idx_[str(wire_id)];
556+
node_tile_to_segment_[std::make_tuple(node_id, tile_id)] = wire_name_to_seg_idx_[str(wire_id)];
460557
}
461-
id++;
462558
}
559+
total_node_count_ = id;
463560
}
464561

465562
/*
@@ -473,8 +570,6 @@ struct RR_Graph_Builder {
473570
const auto& tile_type = ar_.getTileTypeList()[tile.getType()];
474571

475572
for (const auto& pip : tile_type.getPips()) {
476-
if (pip.isPseudoCells())
477-
continue;
478573
int wire0_name, wire1_name;
479574
int node0, node1;
480575
int switch_id;
@@ -487,6 +582,9 @@ struct RR_Graph_Builder {
487582
continue;
488583
node0 = wire_to_node_[std::make_tuple(tile_id, wire0_name)];
489584
node1 = wire_to_node_[std::make_tuple(tile_id, wire1_name)];
585+
// Allow for pseudopips that connect from/to VCC/GND
586+
if (pip.isPseudoCells() && (node0 > 1 && node1> 1))
587+
continue;
490588

491589
used_by_pip_.emplace(node0, loc);
492590
used_by_pip_.emplace(node1, loc);
@@ -903,6 +1001,7 @@ struct RR_Graph_Builder {
9031001
}
9041002

9051003
void process_set(std::unordered_set<intermediate_node*>& set,
1004+
std::unordered_set<location, hash_tuple::hash<location>>& nodes_used,
9061005
std::map<location, intermediate_node*>& existing_nodes,
9071006
std::map<location, std::tuple<location, e_rr_type, int>>& local_redirect,
9081007
float R,
@@ -920,6 +1019,7 @@ struct RR_Graph_Builder {
9201019
auto key = std::make_tuple(add_vec(start->loc, offset), chan_type);
9211020
idx = virtual_chan_loc_map_[key].size();
9221021
do {
1022+
nodes_used.insert(end->loc);
9231023
len++;
9241024
local_redirect.emplace(end->loc, std::make_tuple(add_vec(start->loc, offset), chan_type, idx));
9251025
if (!end->links[side])
@@ -962,6 +1062,7 @@ struct RR_Graph_Builder {
9621062
float R,
9631063
float C) {
9641064
std::unordered_set<intermediate_node*> chanxs, chanys;
1065+
std::unordered_set<location, hash_tuple::hash<location>> nodes_in_chanxs, nodes_in_chanys;
9651066
bool chanx_start, chany_start, single_node;
9661067
for (auto const& i : existing_nodes) {
9671068
single_node = true;
@@ -973,11 +1074,15 @@ struct RR_Graph_Builder {
9731074
chanx_start = pip_uses_node_loc(node_id, left_node->loc) || left_node->links[TOP_EDGE] || left_node->links[BOTTOM_EDGE];
9741075
} else {
9751076
chanx_start = i.second->has_pins || single_node;
1077+
if (i.second->links[RIGHT_EDGE])
1078+
nodes_in_chanxs.insert(i.first);
9761079
}
9771080
if (i.second->links[TOP_EDGE]) {
9781081
intermediate_node* top_node = existing_nodes[add_vec(i.second->loc, offsets[TOP_EDGE])];
9791082
chany_start = pip_uses_node_loc(node_id, top_node->loc) || pin_uses_node_loc(node_id, top_node->loc);
9801083
chany_start |= top_node->links[LEFT_EDGE] || top_node->links[RIGHT_EDGE];
1084+
} else if (i.second->links[BOTTOM_EDGE]) {
1085+
nodes_in_chanys.insert(i.first);
9811086
}
9821087
if (chanx_start)
9831088
chanxs.insert(i.second);
@@ -987,25 +1092,35 @@ struct RR_Graph_Builder {
9871092

9881093
std::map<location, std::tuple<location, e_rr_type, int>> local_redirect_x, local_redirect_y;
9891094

990-
process_set(chanys, existing_nodes, local_redirect_y, R, C, location(0, 0), BOTTOM_EDGE, CHANY);
991-
process_set(chanxs, existing_nodes, local_redirect_x, R, C, offsets[BOTTOM_EDGE], RIGHT_EDGE, CHANX);
1095+
process_set(chanys, nodes_in_chanys, existing_nodes, local_redirect_y, R, C, location(0, 0), BOTTOM_EDGE, CHANY);
1096+
process_set(chanxs, nodes_in_chanxs, existing_nodes, local_redirect_x, R, C, offsets[BOTTOM_EDGE], RIGHT_EDGE, CHANX);
9921097
connect_base_on_redirects(chanys, TOP_EDGE, local_redirect_y, local_redirect_y);
993-
connect_base_on_redirects(chanxs, LEFT_EDGE, local_redirect_x, local_redirect_y);
1098+
//connect_base_on_redirects(chanxs, LEFT_EDGE, local_redirect_x, local_redirect_y);
9941099
connect_base_on_redirects(chanxs, LEFT_EDGE, local_redirect_x, local_redirect_x);
995-
connect_base_on_redirects(chanys, TOP_EDGE, local_redirect_y, local_redirect_x);
1100+
//connect_base_on_redirects(chanys, TOP_EDGE, local_redirect_y, local_redirect_x);
9961101

9971102
bool ry, rx;
1103+
for (auto i : nodes_in_chanys) {
1104+
location node = i;
1105+
if (nodes_in_chanxs.find(i) != nodes_in_chanxs.end()){
1106+
ry = local_redirect_y.find(node) != local_redirect_y.end();
1107+
rx = local_redirect_x.find(node) != local_redirect_x.end();
1108+
location x,y;
1109+
if (rx)
1110+
x = node;
1111+
else
1112+
x = add_vec(node, offsets[RIGHT_EDGE]);
1113+
if (ry)
1114+
y = node;
1115+
else
1116+
y = add_vec(node, offsets[BOTTOM_EDGE]);
1117+
add_short(y, x, local_redirect_y, local_redirect_x);
1118+
}
1119+
}
1120+
9981121
for (auto const node : existing_nodes) {
9991122
ry = local_redirect_y.find(node.first) != local_redirect_y.end();
10001123
rx = local_redirect_x.find(node.first) != local_redirect_x.end();
1001-
if (node.second->links[RIGHT_EDGE] && node.second->links[BOTTOM_EDGE]) {
1002-
location bottom_node = add_vec(node.first, offsets[BOTTOM_EDGE]);
1003-
location right_node = add_vec(node.first, offsets[RIGHT_EDGE]);
1004-
add_short(bottom_node, right_node, local_redirect_y, local_redirect_x);
1005-
}
1006-
if (ry && rx) {
1007-
add_short(node.first, node.first, local_redirect_y, local_redirect_x);
1008-
}
10091124
if (rx) {
10101125
virtual_redirect_.emplace(std::make_tuple(node_id, node.first), local_redirect_x[node.first]);
10111126
} else if (ry) {
@@ -1037,10 +1152,7 @@ struct RR_Graph_Builder {
10371152
* Process FPGA Interchange nodes
10381153
*/
10391154
void process_nodes() {
1040-
auto wires = ar_.getWires();
1041-
for (auto const& node : ar_.getNodes()) {
1042-
std::tuple<int, int> base_wire_(wires[node.getWires()[0]].getTile(), wires[node.getWires()[0]].getWire());
1043-
int node_id = wire_to_node_[base_wire_];
1155+
for (int node_id = 0; node_id < total_node_count_; ++node_id) {
10441156
int seg_id;
10451157
if (usefull_node_.find(node_id) == usefull_node_.end()) {
10461158
continue;
@@ -1060,12 +1172,8 @@ struct RR_Graph_Builder {
10601172
}
10611173
node_id_count_[node_id] = div;
10621174
VTR_ASSERT(div > 0);
1063-
float capacitance = 0.000000001, resistance = 5.7; // Some random data
1064-
if (ar_.hasNodeTimings()) {
1065-
auto model = ar_.getNodeTimings()[node.getNodeTiming()];
1066-
capacitance = get_corner_value(model.getCapacitance(), "slow", "typ") / div;
1067-
resistance = get_corner_value(model.getResistance(), "slow", "typ") / div;
1068-
}
1175+
float resistance = node_to_RC_[node_id].first / div;
1176+
float capacitance = node_to_RC_[node_id].second / div;
10691177
graph_reduction_stage2(node_id, existing_nodes, resistance, capacitance);
10701178
delete_nodes(existing_nodes);
10711179
}
@@ -1147,6 +1255,16 @@ struct RR_Graph_Builder {
11471255
it = next_good_site(it + 1, tile);
11481256
}
11491257
}
1258+
/*
1259+
Add constant ource
1260+
*/
1261+
sink_source_loc_map_[-1].resize(2);
1262+
for ( auto i : {0, 1}) {
1263+
location loc = tile_to_loc_[-1];
1264+
used_by_pin_.insert(std::make_tuple(i, loc));
1265+
usefull_node_.insert(i);
1266+
sink_source_loc_map_[-1][i] = std::make_tuple(false, 0, i);
1267+
}
11501268
}
11511269

11521270
void sweep(location loc,
@@ -1382,8 +1500,12 @@ struct RR_Graph_Builder {
13821500
sink_src = mux_id;
13831501
src = input ? track_id : pin_id;
13841502

1385-
device_ctx_.rr_graph_builder.emplace_back_edge(RRNodeId(src), RRNodeId(sink_src), 0);
1386-
device_ctx_.rr_graph_builder.emplace_back_edge(RRNodeId(sink_src), RRNodeId(sink), sink == track_id ? 1 : 0);
1503+
device_ctx_.rr_graph_builder.emplace_back_edge(RRNodeId(src),
1504+
RRNodeId(sink_src),
1505+
src == track_id ? 1 :0);
1506+
device_ctx_.rr_graph_builder.emplace_back_edge(RRNodeId(sink_src),
1507+
RRNodeId(sink),
1508+
sink == track_id ? 1 : 0);
13871509
}
13881510
}
13891511
}

vpr/src/route/rr_graph_fpga_interchange.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,12 @@ struct hash<std::pair<T1, T2>> {
3333
size_t lhs, rhs;
3434
lhs = std::hash<T1>()(p.first);
3535
rhs = std::hash<T2>()(p.second);
36-
lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
37-
return lhs;
36+
return (lhs * lhs + 3UL * lhs + 2UL * lhs * rhs + rhs + rhs * rhs) / 2UL;
3837
}
3938
};
4039
template<class T>
4140
inline void hash_combine(std::size_t& seed, T const& v) {
42-
seed ^= hash_tuple::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
41+
seed ^= hash_tuple::hash<T>()(v) + 0x9e3779b97f4a7c15UL + (seed << 12) + (seed >> 4);
4342
}
4443
// Recursive template code derived from Matthieu M.
4544
template<class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>

0 commit comments

Comments
 (0)