Skip to content

Commit 540c9ea

Browse files
andrewb1999acomodi
authored andcommitted
Added binary read/write to vpr
Signed-off-by: Andrew Butt <[email protected]>
1 parent 1ab2b93 commit 540c9ea

File tree

6 files changed

+271
-26
lines changed

6 files changed

+271
-26
lines changed

vpr/src/route/rr_graph.cpp

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

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

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 {
@@ -47,6 +50,9 @@ void free_rr_graph();
4750
//Returns a brief one-line summary of an RR node
4851
std::string describe_rr_node(int inode);
4952

53+
void print_rr_node(FILE* fp, const std::vector<t_rr_node>& L_rr_node, int inode);
54+
void write_rr_node(FILE* fp, const std::vector<t_rr_node>& L_rr_node, int inode);
55+
5056
void init_fan_in(std::vector<t_rr_node>& L_rr_node, const int num_rr_nodes);
5157

5258
// 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
@@ -55,12 +55,14 @@ 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_edges(pugi::xml_node parent, const pugiutil::loc_data& loc_data, int* wire_to_rr_ipin_switch, const int num_rr_switches);
6061
void process_channels(t_chan_width& chan_width, pugi::xml_node parent, const pugiutil::loc_data& loc_data);
6162
void process_rr_node_indices(const DeviceGrid& grid);
6263
void process_seg_id(pugi::xml_node parent, const pugiutil::loc_data& loc_data);
6364
void set_cost_indices(pugi::xml_node parent, const pugiutil::loc_data& loc_data, const bool is_global_graph, const int num_seg_types);
65+
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);
6466

6567
/************************ Subroutine definitions ****************************/
6668

@@ -140,41 +142,60 @@ void load_rr_file(const t_graph_type graph_type,
140142
int max_chan_width = (is_global_graph ? 1 : nodes_per_chan.max);
141143
VTR_ASSERT(max_chan_width > 0);
142144

143-
/* Alloc rr nodes and count count nodes */
144-
next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
145-
146-
int num_rr_nodes = count_children(next_component, "node", loc_data);
147-
148-
device_ctx.rr_nodes.resize(num_rr_nodes);
149-
process_nodes(next_component, loc_data);
150-
151145
/* Loads edges, switches, and node look up tables*/
152146
next_component = get_single_child(rr_graph, "switches", loc_data);
153147

154148
int numSwitches = count_children(next_component, "switch", loc_data);
155149
device_ctx.rr_switch_inf.resize(numSwitches);
156150

157151
process_switches(next_component, loc_data);
152+
/* Branches to binary format */
153+
next_component = get_single_child(rr_graph, "binary_nodes_and_edges", loc_data, OPTIONAL);
154+
if (next_component) {
155+
auto filename = get_attribute(next_component, "file", loc_data).as_string("");
156+
VTR_LOG("Using Binary File: %s\n", filename);
157+
FILE* fp = fopen(filename, "rb");
158+
if (fp == NULL) {
159+
VPR_THROW(VPR_ERROR_OTHER, "Binary File %s Does Not Exist\n", filename);
160+
}
158161

159-
next_component = get_single_child(rr_graph, "rr_edges", loc_data);
160-
process_edges(next_component, loc_data, wire_to_rr_ipin_switch, numSwitches);
162+
process_nodes_and_switches_bin(fp, wire_to_rr_ipin_switch, is_global_graph, segment_inf, numSwitches);
163+
164+
partition_rr_graph_edges(device_ctx);
165+
process_rr_node_indices(grid);
166+
init_fan_in(device_ctx.rr_nodes, device_ctx.rr_nodes.size());
167+
alloc_and_load_rr_indexed_data(segment_inf, device_ctx.rr_node_indices,
168+
max_chan_width, *wire_to_rr_ipin_switch, base_cost_type);
169+
170+
} else {
171+
/* Alloc rr nodes and count count nodes */
172+
next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
161173

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

166-
process_rr_node_indices(grid);
176+
device_ctx.rr_nodes.resize(num_rr_nodes);
177+
process_nodes(next_component, loc_data);
167178

168-
init_fan_in(device_ctx.rr_nodes, device_ctx.rr_nodes.size());
179+
next_component = get_single_child(rr_graph, "rr_edges", loc_data);
180+
process_edges(next_component, loc_data, wire_to_rr_ipin_switch, numSwitches);
169181

170-
//sets the cost index and seg id information
171-
next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
172-
set_cost_indices(next_component, loc_data, is_global_graph, segment_inf.size());
182+
//Partition the rr graph edges for efficient access to configurable/non-configurable
183+
//edge subsets. Must be done after RR switches have been allocated
184+
partition_rr_graph_edges(device_ctx);
173185

174-
alloc_and_load_rr_indexed_data(segment_inf, device_ctx.rr_node_indices,
175-
max_chan_width, *wire_to_rr_ipin_switch, base_cost_type);
186+
process_rr_node_indices(grid);
176187

177-
process_seg_id(next_component, loc_data);
188+
init_fan_in(device_ctx.rr_nodes, device_ctx.rr_nodes.size());
189+
190+
//sets the cost index and seg id information
191+
next_component = get_single_child(rr_graph, "rr_nodes", loc_data);
192+
set_cost_indices(next_component, loc_data, is_global_graph, segment_inf.size());
193+
194+
alloc_and_load_rr_indexed_data(segment_inf, device_ctx.rr_node_indices,
195+
max_chan_width, *wire_to_rr_ipin_switch, base_cost_type);
196+
197+
process_seg_id(next_component, loc_data);
198+
}
178199

179200
device_ctx.chan_width = nodes_per_chan;
180201

@@ -185,6 +206,103 @@ void load_rr_file(const t_graph_type graph_type,
185206
}
186207
}
187208

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

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)