Skip to content

Commit cc9b8fb

Browse files
andrewb1999litghost
authored andcommitted
Added binary read/write to vpr
Signed-off-by: Andrew Butt <[email protected]>
1 parent c26370e commit cc9b8fb

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
@@ -2509,6 +2509,54 @@ static vtr::NdMatrix<std::vector<int>, 4> alloc_and_load_track_to_pin_lookup(vtr
25092509
return track_to_pin_lookup;
25102510
}
25112511

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

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: 166 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,14 @@ void verify_segments(pugi::xml_node parent, const pugiutil::loc_data& loc_data,
5252
void verify_blocks(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
5353
void process_blocks(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
5454
void verify_grid(pugi::xml_node parent, const pugiutil::loc_data& loc_data, const DeviceGrid& grid);
55+
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);
5556
void process_nodes(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
5657
void process_edges(pugi::xml_node parent, const pugiutil::loc_data& loc_data, int* wire_to_rr_ipin_switch, const int num_rr_switches);
5758
void process_channels(t_chan_width& chan_width, const DeviceGrid& grid, pugi::xml_node parent, const pugiutil::loc_data& loc_data);
5859
void process_rr_node_indices(const DeviceGrid& grid);
5960
void process_seg_id(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
6061
void set_cost_indices(pugi::xml_node parent, const pugiutil::loc_data& loc_data, const bool is_global_graph, const int num_seg_types);
62+
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);
6163

6264
/************************ Subroutine definitions ****************************/
6365

@@ -137,41 +139,60 @@ void load_rr_file(const t_graph_type graph_type,
137139
int max_chan_width = (is_global_graph ? 1 : nodes_per_chan.max);
138140
VTR_ASSERT(max_chan_width > 0);
139141

140-
/* Alloc rr nodes and count count nodes */
141-
next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
142-
143-
int num_rr_nodes = count_children(next_component, "node", loc_data);
144-
145-
device_ctx.rr_nodes.resize(num_rr_nodes);
146-
process_nodes(next_component, loc_data);
147-
148142
/* Loads edges, switches, and node look up tables*/
149143
next_component = get_single_child(rr_graph, "switches", loc_data);
150144

151145
int numSwitches = count_children(next_component, "switch", loc_data);
152146
device_ctx.rr_switch_inf.resize(numSwitches);
153147

154148
process_switches(next_component, loc_data);
149+
/* Branches to binary format */
150+
next_component = get_single_child(rr_graph, "binary_nodes_and_edges", loc_data, OPTIONAL);
151+
if (next_component) {
152+
auto filename = get_attribute(next_component, "file", loc_data).as_string("");
153+
VTR_LOG("Using Binary File: %s\n", filename);
154+
FILE* fp = fopen(filename, "rb");
155+
if (fp == NULL) {
156+
VPR_THROW(VPR_ERROR_OTHER, "Binary File %s Does Not Exist\n", filename);
157+
}
158+
159+
process_nodes_and_switches_bin(fp, wire_to_rr_ipin_switch, is_global_graph, segment_inf, numSwitches);
160+
161+
partition_rr_graph_edges(device_ctx);
162+
process_rr_node_indices(grid);
163+
init_fan_in(device_ctx.rr_nodes, device_ctx.rr_nodes.size());
164+
alloc_and_load_rr_indexed_data(segment_inf, device_ctx.rr_node_indices,
165+
max_chan_width, *wire_to_rr_ipin_switch, base_cost_type);
155166

156-
next_component = get_single_child(rr_graph, "rr_edges", loc_data);
157-
process_edges(next_component, loc_data, wire_to_rr_ipin_switch, numSwitches);
167+
} else {
168+
/* Alloc rr nodes and count count nodes */
169+
next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
170+
171+
int num_rr_nodes = count_children(next_component, "node", loc_data);
172+
173+
device_ctx.rr_nodes.resize(num_rr_nodes);
174+
process_nodes(next_component, loc_data);
158175

159-
//Partition the rr graph edges for efficient access to configurable/non-configurable
160-
//edge subsets. Must be done after RR switches have been allocated
161-
partition_rr_graph_edges(device_ctx);
176+
next_component = get_single_child(rr_graph, "rr_edges", loc_data);
177+
process_edges(next_component, loc_data, wire_to_rr_ipin_switch, numSwitches);
162178

163-
process_rr_node_indices(grid);
179+
//Partition the rr graph edges for efficient access to configurable/non-configurable
180+
//edge subsets. Must be done after RR switches have been allocated
181+
partition_rr_graph_edges(device_ctx);
164182

165-
init_fan_in(device_ctx.rr_nodes, device_ctx.rr_nodes.size());
183+
process_rr_node_indices(grid);
166184

167-
//sets the cost index and seg id information
168-
next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
169-
set_cost_indices(next_component, loc_data, is_global_graph, segment_inf.size());
185+
init_fan_in(device_ctx.rr_nodes, device_ctx.rr_nodes.size());
170186

171-
alloc_and_load_rr_indexed_data(segment_inf, device_ctx.rr_node_indices,
172-
max_chan_width, *wire_to_rr_ipin_switch, base_cost_type);
187+
//sets the cost index and seg id information
188+
next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
189+
set_cost_indices(next_component, loc_data, is_global_graph, segment_inf.size());
173190

174-
process_seg_id(next_component, loc_data);
191+
alloc_and_load_rr_indexed_data(segment_inf, device_ctx.rr_node_indices,
192+
max_chan_width, *wire_to_rr_ipin_switch, base_cost_type);
193+
194+
process_seg_id(next_component, loc_data);
195+
}
175196

176197
device_ctx.chan_width = nodes_per_chan;
177198
device_ctx.read_rr_graph_filename = std::string(read_rr_graph_name);
@@ -183,6 +204,103 @@ void load_rr_file(const t_graph_type graph_type,
183204
}
184205
}
185206

207+
void process_nodes_and_switches_bin(FILE* fp,
208+
int* wire_to_rr_ipin_switch,
209+
bool is_global_graph,
210+
const std::vector<t_segment_inf>& segment_inf,
211+
int numSwitches) {
212+
auto& device_ctx = g_vpr_ctx.mutable_device();
213+
uint32_t magic_num;
214+
uint16_t format_version;
215+
uint16_t header_length;
216+
uint64_t num_rr_nodes;
217+
fread_secure(&magic_num, sizeof(magic_num), 1, fp);
218+
fread_secure(&format_version, sizeof(format_version), 1, fp);
219+
fread_secure(&header_length, sizeof(header_length), 1, fp);
220+
char* header = new char[header_length + 1];
221+
header[header_length] = '\0';
222+
fread_secure(header, sizeof(char), header_length, fp);
223+
fread_secure(&num_rr_nodes, sizeof(num_rr_nodes), 1, fp);
224+
device_ctx.rr_nodes.resize(num_rr_nodes);
225+
226+
if (magic_num != BINARY_MAGIC_NUM) {
227+
VTR_LOG_WARN("Not a VPR Binary rr_graph file\n");
228+
}
229+
230+
if (format_version != BINARY_FILE_VERSION) {
231+
VTR_LOG_WARN("Binary file format versions do not match\n");
232+
}
233+
234+
int inode;
235+
t_rr_type node_type;
236+
uint16_t num_edges;
237+
e_direction direction;
238+
e_side side;
239+
int edge_sink_node;
240+
uint16_t edge_switch;
241+
uint16_t capacity;
242+
float R;
243+
float C;
244+
uint16_t pos[5];
245+
246+
for (uint64_t i = 0; i < num_rr_nodes; i++) {
247+
fread_secure(&inode, sizeof(inode), 1, fp);
248+
fread_secure(&node_type, sizeof(node_type), 1, fp);
249+
auto& node = device_ctx.rr_nodes[inode];
250+
node.set_type(node_type);
251+
if (node.type() == CHANX || node.type() == CHANY) {
252+
fread_secure(&direction, sizeof(direction), 1, fp);
253+
node.set_direction(direction);
254+
}
255+
256+
fread_secure(&capacity, sizeof(capacity), 1, fp);
257+
if (capacity > 0)
258+
node.set_capacity(capacity);
259+
fread_secure(pos, sizeof(*pos), 5, fp);
260+
node.set_coordinates(pos[0], pos[1], pos[2], pos[3]);
261+
node.set_ptc_num(pos[4]);
262+
if (node.type() == IPIN || node.type() == OPIN) {
263+
fread_secure(&side, sizeof(side), 1, fp);
264+
node.set_side(side);
265+
}
266+
267+
fread_secure(&R, sizeof(R), 1, fp);
268+
fread_secure(&C, sizeof(C), 1, fp);
269+
node.set_rc_index(find_create_rr_rc_data(R, C));
270+
271+
fread_secure(&num_edges, sizeof(num_edges), 1, fp);
272+
273+
node.set_num_edges(num_edges);
274+
for (int j = 0; j < num_edges; j++) {
275+
fread_secure(&edge_sink_node, sizeof(edge_sink_node), 1, fp);
276+
fread_secure(&edge_switch, sizeof(edge_switch), 1, fp);
277+
node.set_edge_sink_node(j, edge_sink_node);
278+
node.set_edge_switch(j, edge_switch);
279+
}
280+
set_cost_index_bin(inode, node_type, is_global_graph, segment_inf.size(), 0);
281+
}
282+
std::vector<int> count_for_wire_to_ipin_switches;
283+
count_for_wire_to_ipin_switches.resize(numSwitches, 0);
284+
for (uint64_t i = 0; i < num_rr_nodes; i++) {
285+
auto& node = device_ctx.rr_nodes[i];
286+
if (node.type() == CHANX || node.type() == CHANY) {
287+
num_edges = node.num_edges();
288+
for (int j = 0; j < num_edges; j++) {
289+
if (device_ctx.rr_nodes[node.edge_sink_node(j)].type() == IPIN) {
290+
count_for_wire_to_ipin_switches[j]++;
291+
}
292+
}
293+
}
294+
}
295+
int max = -1;
296+
for (int j = 0; j < numSwitches; j++) {
297+
if (count_for_wire_to_ipin_switches[j] > max) {
298+
*wire_to_rr_ipin_switch = j;
299+
max = count_for_wire_to_ipin_switches[j];
300+
}
301+
}
302+
}
303+
186304
/* Reads in the switch information and adds it to device_ctx.rr_switch_inf as specified*/
187305
void process_switches(pugi::xml_node parent, const pugiutil::loc_data& loc_data) {
188306
auto& device_ctx = g_vpr_ctx.mutable_device();
@@ -884,3 +1002,30 @@ void set_cost_indices(pugi::xml_node parent, const pugiutil::loc_data& loc_data,
8841002
rr_node = rr_node.next_sibling(rr_node.name());
8851003
}
8861004
}
1005+
1006+
/* This function sets the Source pins, sink pins, ipin, and opin
1007+
* to their unique cost index identifier. CHANX and CHANY cost indicies are set after the
1008+
* seg_id is read in from the rr graph */
1009+
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) {
1010+
auto& device_ctx = g_vpr_ctx.mutable_device();
1011+
auto& node = device_ctx.rr_nodes[inode];
1012+
//set the cost index in order to load the segment information, rr nodes should be set already
1013+
if (node_type == SOURCE) {
1014+
node.set_cost_index(SOURCE_COST_INDEX);
1015+
} else if (node_type == SINK) {
1016+
node.set_cost_index(SINK_COST_INDEX);
1017+
} else if (node_type == IPIN) {
1018+
node.set_cost_index(IPIN_COST_INDEX);
1019+
} else if (node_type == OPIN) {
1020+
node.set_cost_index(OPIN_COST_INDEX);
1021+
} else if (node_type == CHANX || node_type == CHANY) {
1022+
/*CHANX and CHANY cost index is dependent on the segment id*/
1023+
if (is_global_graph) {
1024+
node.set_cost_index(0);
1025+
} else if (device_ctx.rr_nodes[inode].type() == CHANX) {
1026+
node.set_cost_index(CHANX_COST_INDEX_START + seg_id);
1027+
} else if (device_ctx.rr_nodes[inode].type() == CHANY) {
1028+
node.set_cost_index(CHANX_COST_INDEX_START + num_seg_types + seg_id);
1029+
}
1030+
}
1031+
}

vpr/src/route/rr_graph_writer.cpp

Lines changed: 41 additions & 6 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
/* All values are printed with this precision value. The higher the
2022
* value, the more accurate the read in rr graph is. Using numeric_limits
@@ -35,26 +37,59 @@ void write_rr_segments(std::fstream& fp, const std::vector<t_segment_inf>& segme
3537
/* This function is used to write the rr_graph into xml format into a a file with name: file_name */
3638
void write_rr_graph(const char* file_name, const std::vector<t_segment_inf>& segment_inf) {
3739
std::fstream fp;
38-
fp.open(file_name, std::fstream::out | std::fstream::trunc);
40+
FILE* fb = nullptr;
41+
std::stringstream header;
42+
std::string filename_str(file_name);
43+
bool binary_mode = (filename_str.substr(filename_str.length() - 7) == "bin.xml");
44+
std::string bin_file_name;
45+
if (binary_mode) {
46+
bin_file_name = filename_str.substr(0, filename_str.length() - 4);
47+
VTR_LOG("RR_Graph binary file %s\n", bin_file_name.c_str());
48+
fb = vtr::fopen(bin_file_name.c_str(), "w");
49+
}
50+
fp.open(file_name, fstream::out | fstream::trunc);
3951

4052
/* Prints out general info for easy error checking*/
4153
if (!fp.is_open() || !fp.good()) {
4254
VPR_FATAL_ERROR(VPR_ERROR_OTHER,
4355
"couldn't open file \"%s\" for generating RR graph file\n", file_name);
4456
}
4557
std::cout << "Writing RR graph" << std::endl;
46-
fp << "<rr_graph tool_name=\"vpr\" tool_version=\"" << vtr::VERSION << "\" tool_comment=\"Generated from arch file "
47-
<< get_arch_file_name() << "\">" << std::endl;
58+
header << "<rr_graph tool_name=\"vpr\" tool_version=\"" << vtr::VERSION << "\" tool_comment=\"Generated from arch file "
59+
<< get_arch_file_name() << "\">" << std::endl;
60+
fp << header.rdbuf();
4861

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

5994
fp.close();
6095

0 commit comments

Comments
 (0)