Skip to content

Commit 4b5455c

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

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
@@ -2516,6 +2516,54 @@ static vtr::NdMatrix<std::vector<int>, 4> alloc_and_load_track_to_pin_lookup(vtr
25162516
return track_to_pin_lookup;
25172517
}
25182518

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

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

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

5157
// 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, const DeviceGrid& grid, 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
device_ctx.read_rr_graph_filename = std::string(read_rr_graph_name);
@@ -186,6 +207,103 @@ void load_rr_file(const t_graph_type graph_type,
186207
}
187208
}
188209

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

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)