Skip to content

Commit 31a37cc

Browse files
committed
Merge branch 'rr-graph-binary-read-write' into master+wip
Signed-off-by: Alessandro Comodi <[email protected]>
2 parents 4b66901 + 4b5455c commit 31a37cc

File tree

6 files changed

+272
-27
lines changed

6 files changed

+272
-27
lines changed

vpr/src/route/rr_graph.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2514,6 +2514,54 @@ static vtr::NdMatrix<std::vector<int>, 4> alloc_and_load_track_to_pin_lookup(vtr
25142514
return track_to_pin_lookup;
25152515
}
25162516

2517+
/* Writes out data (excludes fasm metadata) about node inode to binary in file fp *
2518+
* Writes data in the following order: int inode, t_rr_type type, e_direction *
2519+
* direction (if CHANX or CHANY), uint16_t capacity, length 5 uint16_t array pos, *
2520+
* e_side side (if IPIN or OPIN), float R, float C, uint16_t num_edges.Then loops *
2521+
* through every edge writing out int edge_sink node and uint16_t edge_switch. */
2522+
void write_rr_node(FILE* fp, const std::vector<t_rr_node>& L_rr_node, int inode) {
2523+
const auto& rr_node = L_rr_node[inode];
2524+
t_rr_type type = rr_node.type();
2525+
uint16_t num_edges = rr_node.num_edges();
2526+
int edge_sink_node;
2527+
uint16_t edge_switch;
2528+
uint16_t capacity = (uint16_t)rr_node.capacity();
2529+
float R = rr_node.R();
2530+
float C = rr_node.C();
2531+
uint16_t pos[5];
2532+
2533+
pos[0] = rr_node.xlow();
2534+
pos[1] = rr_node.ylow();
2535+
pos[2] = rr_node.xhigh();
2536+
pos[3] = rr_node.yhigh();
2537+
pos[4] = rr_node.ptc_num();
2538+
2539+
fwrite(&inode, sizeof(inode), 1, fp);
2540+
fwrite(&type, sizeof(type), 1, fp);
2541+
if (rr_node.type() == CHANX || rr_node.type() == CHANY) {
2542+
e_direction direction = rr_node.direction();
2543+
fwrite(&direction, sizeof(direction), 1, fp);
2544+
}
2545+
fwrite(&capacity, sizeof(capacity), 1, fp);
2546+
fwrite(pos, sizeof(*pos), 5, fp);
2547+
2548+
if (rr_node.type() == IPIN || rr_node.type() == OPIN) {
2549+
e_side side = rr_node.side();
2550+
fwrite(&side, sizeof(side), 1, fp);
2551+
}
2552+
2553+
fwrite(&R, sizeof(R), 1, fp);
2554+
fwrite(&C, sizeof(C), 1, fp);
2555+
fwrite(&num_edges, sizeof(num_edges), 1, fp);
2556+
2557+
for (int iedge = 0; iedge < rr_node.num_edges(); ++iedge) {
2558+
edge_sink_node = rr_node.edge_sink_node(iedge);
2559+
edge_switch = rr_node.edge_switch(iedge);
2560+
fwrite(&edge_sink_node, sizeof(edge_sink_node), 1, fp);
2561+
fwrite(&edge_switch, sizeof(edge_switch), 1, fp);
2562+
}
2563+
}
2564+
25172565
std::string describe_rr_node(int inode) {
25182566
auto& device_ctx = g_vpr_ctx.device();
25192567

vpr/src/route/rr_graph.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
* and so are not currently used in commercial architectures. */
77
#define INCLUDE_TRACK_BUFFERS false
88

9+
#define BINARY_MAGIC_NUM 0x42525247
10+
#define BINARY_FILE_VERSION 1
11+
912
#include "device_grid.h"
1013

1114
enum e_graph_type {
@@ -45,6 +48,9 @@ void free_rr_graph();
4548
//Returns a brief one-line summary of an RR node
4649
std::string describe_rr_node(int inode);
4750

51+
void print_rr_node(FILE* fp, const std::vector<t_rr_node>& L_rr_node, int inode);
52+
void write_rr_node(FILE* fp, const std::vector<t_rr_node>& L_rr_node, int inode);
53+
4854
void init_fan_in(std::vector<t_rr_node>& L_rr_node, const int num_rr_nodes);
4955

5056
// Sets the spec for the rr_switch based on the arch switch

vpr/src/route/rr_graph_reader.cpp

Lines changed: 167 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,15 @@ void verify_segments(pugi::xml_node parent, const pugiutil::loc_data& loc_data,
5555
void verify_blocks(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
5656
void process_blocks(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
5757
void verify_grid(pugi::xml_node parent, const pugiutil::loc_data& loc_data, const DeviceGrid& grid);
58+
void process_nodes_and_switches_bin(FILE* fp, int* wire_to_rr_ipin_switch, bool is_global_graph, const std::vector<t_segment_inf>& segment_inf, int numSwitches);
5859
void process_nodes(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
5960
void process_connection_boxes(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
6061
void process_edges(pugi::xml_node parent, const pugiutil::loc_data& loc_data, int* wire_to_rr_ipin_switch, const int num_rr_switches);
6162
void process_channels(t_chan_width& chan_width, const DeviceGrid& grid, pugi::xml_node parent, const pugiutil::loc_data& loc_data);
6263
void process_rr_node_indices(const DeviceGrid& grid);
6364
void process_seg_id(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
6465
void set_cost_indices(pugi::xml_node parent, const pugiutil::loc_data& loc_data, const bool is_global_graph, const int num_seg_types);
66+
void set_cost_index_bin(int inode, t_rr_type node_type, const bool is_global_graph, const int num_seg_types, short seg_id);
6567

6668
/************************ Subroutine definitions ****************************/
6769

@@ -148,42 +150,61 @@ void load_rr_file(const t_graph_type graph_type,
148150
int max_chan_width = (is_global_graph ? 1 : nodes_per_chan.max);
149151
VTR_ASSERT(max_chan_width > 0);
150152

151-
/* Alloc rr nodes and count count nodes */
152-
next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
153-
154-
int num_rr_nodes = count_children(next_component, "node", loc_data);
155-
156-
device_ctx.rr_nodes.resize(num_rr_nodes);
157-
device_ctx.connection_boxes.resize_nodes(num_rr_nodes);
158-
process_nodes(next_component, loc_data);
159-
160153
/* Loads edges, switches, and node look up tables*/
161154
next_component = get_single_child(rr_graph, "switches", loc_data);
162155

163156
int numSwitches = count_children(next_component, "switch", loc_data);
164157
device_ctx.rr_switch_inf.resize(numSwitches);
165158

166159
process_switches(next_component, loc_data);
160+
/* Branches to binary format */
161+
next_component = get_single_child(rr_graph, "binary_nodes_and_edges", loc_data, OPTIONAL);
162+
if (next_component) {
163+
auto filename = get_attribute(next_component, "file", loc_data).as_string("");
164+
VTR_LOG("Using Binary File: %s\n", filename);
165+
FILE* fp = fopen(filename, "rb");
166+
if (fp == NULL) {
167+
VPR_THROW(VPR_ERROR_OTHER, "Binary File %s Does Not Exist\n", filename);
168+
}
167169

168-
next_component = get_single_child(rr_graph, "rr_edges", loc_data);
169-
process_edges(next_component, loc_data, wire_to_rr_ipin_switch, numSwitches);
170+
process_nodes_and_switches_bin(fp, wire_to_rr_ipin_switch, is_global_graph, segment_inf, numSwitches);
171+
172+
partition_rr_graph_edges(device_ctx);
173+
process_rr_node_indices(grid);
174+
init_fan_in(device_ctx.rr_nodes, device_ctx.rr_nodes.size());
175+
alloc_and_load_rr_indexed_data(segment_inf, device_ctx.rr_node_indices,
176+
max_chan_width, *wire_to_rr_ipin_switch, base_cost_type);
177+
178+
} else {
179+
/* Alloc rr nodes and count count nodes */
180+
next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
170181

171-
//Partition the rr graph edges for efficient access to configurable/non-configurable
172-
//edge subsets. Must be done after RR switches have been allocated
173-
partition_rr_graph_edges(device_ctx);
182+
int num_rr_nodes = count_children(next_component, "node", loc_data);
174183

175-
process_rr_node_indices(grid);
184+
device_ctx.rr_nodes.resize(num_rr_nodes);
185+
device_ctx.connection_boxes.resize_nodes(num_rr_nodes);
186+
process_nodes(next_component, loc_data);
176187

177-
init_fan_in(device_ctx.rr_nodes, device_ctx.rr_nodes.size());
188+
next_component = get_single_child(rr_graph, "rr_edges", loc_data);
189+
process_edges(next_component, loc_data, wire_to_rr_ipin_switch, numSwitches);
178190

179-
//sets the cost index and seg id information
180-
next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
181-
set_cost_indices(next_component, loc_data, is_global_graph, segment_inf.size());
191+
//Partition the rr graph edges for efficient access to configurable/non-configurable
192+
//edge subsets. Must be done after RR switches have been allocated
193+
partition_rr_graph_edges(device_ctx);
182194

183-
alloc_and_load_rr_indexed_data(segment_inf, device_ctx.rr_node_indices,
184-
max_chan_width, *wire_to_rr_ipin_switch, base_cost_type);
195+
process_rr_node_indices(grid);
185196

186-
process_seg_id(next_component, loc_data);
197+
init_fan_in(device_ctx.rr_nodes, device_ctx.rr_nodes.size());
198+
199+
//sets the cost index and seg id information
200+
next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
201+
set_cost_indices(next_component, loc_data, is_global_graph, segment_inf.size());
202+
203+
alloc_and_load_rr_indexed_data(segment_inf, device_ctx.rr_node_indices,
204+
max_chan_width, *wire_to_rr_ipin_switch, base_cost_type);
205+
206+
process_seg_id(next_component, loc_data);
207+
}
187208

188209
device_ctx.chan_width = nodes_per_chan;
189210
device_ctx.read_rr_graph_filename = std::string(read_rr_graph_name);
@@ -196,6 +217,103 @@ void load_rr_file(const t_graph_type graph_type,
196217
}
197218
}
198219

220+
void process_nodes_and_switches_bin(FILE* fp,
221+
int* wire_to_rr_ipin_switch,
222+
bool is_global_graph,
223+
const std::vector<t_segment_inf>& segment_inf,
224+
int numSwitches) {
225+
auto& device_ctx = g_vpr_ctx.mutable_device();
226+
uint32_t magic_num;
227+
uint16_t format_version;
228+
uint16_t header_length;
229+
uint64_t num_rr_nodes;
230+
fread_secure(&magic_num, sizeof(magic_num), 1, fp);
231+
fread_secure(&format_version, sizeof(format_version), 1, fp);
232+
fread_secure(&header_length, sizeof(header_length), 1, fp);
233+
char* header = new char[header_length + 1];
234+
header[header_length] = '\0';
235+
fread_secure(header, sizeof(char), header_length, fp);
236+
fread_secure(&num_rr_nodes, sizeof(num_rr_nodes), 1, fp);
237+
device_ctx.rr_nodes.resize(num_rr_nodes);
238+
239+
if (magic_num != BINARY_MAGIC_NUM) {
240+
VTR_LOG_WARN("Not a VPR Binary rr_graph file\n");
241+
}
242+
243+
if (format_version != BINARY_FILE_VERSION) {
244+
VTR_LOG_WARN("Binary file format versions do not match\n");
245+
}
246+
247+
int inode;
248+
t_rr_type node_type;
249+
uint16_t num_edges;
250+
e_direction direction;
251+
e_side side;
252+
int edge_sink_node;
253+
uint16_t edge_switch;
254+
uint16_t capacity;
255+
float R;
256+
float C;
257+
uint16_t pos[5];
258+
259+
for (uint64_t i = 0; i < num_rr_nodes; i++) {
260+
fread_secure(&inode, sizeof(inode), 1, fp);
261+
fread_secure(&node_type, sizeof(node_type), 1, fp);
262+
auto& node = device_ctx.rr_nodes[inode];
263+
node.set_type(node_type);
264+
if (node.type() == CHANX || node.type() == CHANY) {
265+
fread_secure(&direction, sizeof(direction), 1, fp);
266+
node.set_direction(direction);
267+
}
268+
269+
fread_secure(&capacity, sizeof(capacity), 1, fp);
270+
if (capacity > 0)
271+
node.set_capacity(capacity);
272+
fread_secure(pos, sizeof(*pos), 5, fp);
273+
node.set_coordinates(pos[0], pos[1], pos[2], pos[3]);
274+
node.set_ptc_num(pos[4]);
275+
if (node.type() == IPIN || node.type() == OPIN) {
276+
fread_secure(&side, sizeof(side), 1, fp);
277+
node.set_side(side);
278+
}
279+
280+
fread_secure(&R, sizeof(R), 1, fp);
281+
fread_secure(&C, sizeof(C), 1, fp);
282+
node.set_rc_index(find_create_rr_rc_data(R, C));
283+
284+
fread_secure(&num_edges, sizeof(num_edges), 1, fp);
285+
286+
node.set_num_edges(num_edges);
287+
for (int j = 0; j < num_edges; j++) {
288+
fread_secure(&edge_sink_node, sizeof(edge_sink_node), 1, fp);
289+
fread_secure(&edge_switch, sizeof(edge_switch), 1, fp);
290+
node.set_edge_sink_node(j, edge_sink_node);
291+
node.set_edge_switch(j, edge_switch);
292+
}
293+
set_cost_index_bin(inode, node_type, is_global_graph, segment_inf.size(), 0);
294+
}
295+
std::vector<int> count_for_wire_to_ipin_switches;
296+
count_for_wire_to_ipin_switches.resize(numSwitches, 0);
297+
for (uint64_t i = 0; i < num_rr_nodes; i++) {
298+
auto& node = device_ctx.rr_nodes[i];
299+
if (node.type() == CHANX || node.type() == CHANY) {
300+
num_edges = node.num_edges();
301+
for (int j = 0; j < num_edges; j++) {
302+
if (device_ctx.rr_nodes[node.edge_sink_node(j)].type() == IPIN) {
303+
count_for_wire_to_ipin_switches[j]++;
304+
}
305+
}
306+
}
307+
}
308+
int max = -1;
309+
for (int j = 0; j < numSwitches; j++) {
310+
if (count_for_wire_to_ipin_switches[j] > max) {
311+
*wire_to_rr_ipin_switch = j;
312+
max = count_for_wire_to_ipin_switches[j];
313+
}
314+
}
315+
}
316+
199317
/* Reads in the switch information and adds it to device_ctx.rr_switch_inf as specified*/
200318
void process_switches(pugi::xml_node parent, const pugiutil::loc_data& loc_data) {
201319
auto& device_ctx = g_vpr_ctx.mutable_device();
@@ -940,3 +1058,30 @@ void process_connection_boxes(pugi::xml_node parent, const pugiutil::loc_data& l
9401058

9411059
device_ctx.connection_boxes.reset_boxes(std::make_pair(x_dim, y_dim), boxes);
9421060
}
1061+
1062+
/* This function sets the Source pins, sink pins, ipin, and opin
1063+
* to their unique cost index identifier. CHANX and CHANY cost indicies are set after the
1064+
* seg_id is read in from the rr graph */
1065+
void set_cost_index_bin(int inode, t_rr_type node_type, const bool is_global_graph, const int num_seg_types, short seg_id) {
1066+
auto& device_ctx = g_vpr_ctx.mutable_device();
1067+
auto& node = device_ctx.rr_nodes[inode];
1068+
//set the cost index in order to load the segment information, rr nodes should be set already
1069+
if (node_type == SOURCE) {
1070+
node.set_cost_index(SOURCE_COST_INDEX);
1071+
} else if (node_type == SINK) {
1072+
node.set_cost_index(SINK_COST_INDEX);
1073+
} else if (node_type == IPIN) {
1074+
node.set_cost_index(IPIN_COST_INDEX);
1075+
} else if (node_type == OPIN) {
1076+
node.set_cost_index(OPIN_COST_INDEX);
1077+
} else if (node_type == CHANX || node_type == CHANY) {
1078+
/*CHANX and CHANY cost index is dependent on the segment id*/
1079+
if (is_global_graph) {
1080+
node.set_cost_index(0);
1081+
} else if (device_ctx.rr_nodes[inode].type() == CHANX) {
1082+
node.set_cost_index(CHANX_COST_INDEX_START + seg_id);
1083+
} else if (device_ctx.rr_nodes[inode].type() == CHANY) {
1084+
node.set_cost_index(CHANX_COST_INDEX_START + num_seg_types + seg_id);
1085+
}
1086+
}
1087+
}

vpr/src/route/rr_graph_writer.cpp

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* children tags such as timing, location, or some general
66
* details. Each tag has attributes to describe them */
77

8+
#include <cstdio>
89
#include <fstream>
910
#include <iostream>
1011
#include <string.h>
@@ -15,6 +16,7 @@
1516
#include "read_xml_arch_file.h"
1617
#include "vtr_version.h"
1718
#include "rr_graph_writer.h"
19+
#include "rr_graph.h"
1820

1921
using namespace std;
2022

@@ -37,6 +39,16 @@ void write_rr_segments(fstream& fp, const std::vector<t_segment_inf>& segment_in
3739
/* This function is used to write the rr_graph into xml format into a a file with name: file_name */
3840
void write_rr_graph(const char* file_name, const std::vector<t_segment_inf>& segment_inf) {
3941
fstream fp;
42+
FILE* fb = nullptr;
43+
std::stringstream header;
44+
std::string filename_str(file_name);
45+
bool binary_mode = (filename_str.substr(filename_str.length() - 7) == "bin.xml");
46+
std::string bin_file_name;
47+
if (binary_mode) {
48+
bin_file_name = filename_str.substr(0, filename_str.length() - 4);
49+
VTR_LOG("RR_Graph binary file %s\n", bin_file_name.c_str());
50+
fb = vtr::fopen(bin_file_name.c_str(), "w");
51+
}
4052
fp.open(file_name, fstream::out | fstream::trunc);
4153

4254
/* Prints out general info for easy error checking*/
@@ -45,18 +57,41 @@ void write_rr_graph(const char* file_name, const std::vector<t_segment_inf>& seg
4557
"couldn't open file \"%s\" for generating RR graph file\n", file_name);
4658
}
4759
cout << "Writing RR graph" << endl;
48-
fp << "<rr_graph tool_name=\"vpr\" tool_version=\"" << vtr::VERSION << "\" tool_comment=\"Generated from arch file "
49-
<< get_arch_file_name() << "\">" << endl;
60+
header << "<rr_graph tool_name=\"vpr\" tool_version=\"" << vtr::VERSION << "\" tool_comment=\"Generated from arch file "
61+
<< get_arch_file_name() << "\">" << endl;
62+
fp << header.rdbuf();
5063

5164
/* Write out each individual component*/
5265
write_rr_channel(fp);
5366
write_rr_switches(fp);
5467
write_rr_segments(fp, segment_inf);
5568
write_rr_block_types(fp);
5669
write_rr_grid(fp);
57-
write_rr_node(fp);
58-
write_rr_edges(fp);
59-
fp << "</rr_graph>";
70+
if (binary_mode) {
71+
fp << " <binary_nodes_and_edges file=\"" << bin_file_name << "\"/>\n";
72+
auto& device_ctx = g_vpr_ctx.device();
73+
const std::string header_s = header.str();
74+
const char* header_c = header_s.c_str();
75+
uint32_t magic_num = BINARY_MAGIC_NUM;
76+
uint16_t format_version = BINARY_FILE_VERSION;
77+
uint16_t header_length = header_s.length();
78+
uint64_t num_rr_nodes = (uint64_t)device_ctx.rr_nodes.size();
79+
VTR_LOG("RR_Graph binary mode\n");
80+
printf("Header length: %d\n", header_length);
81+
fwrite(&magic_num, sizeof(magic_num), 1, fb);
82+
fwrite(&format_version, sizeof(format_version), 1, fb);
83+
fwrite(&header_length, sizeof(header_length), 1, fb);
84+
fwrite(&header_c, sizeof(char), header_length, fb);
85+
fwrite(&num_rr_nodes, sizeof(num_rr_nodes), 1, fb);
86+
for (size_t inode = 0; inode < num_rr_nodes; inode++) {
87+
write_rr_node(fb, device_ctx.rr_nodes, inode);
88+
}
89+
fclose(fb);
90+
} else {
91+
write_rr_node(fp);
92+
write_rr_edges(fp);
93+
}
94+
fp << "</rr_graph>\n";
6095

6196
fp.close();
6297

0 commit comments

Comments
 (0)