Skip to content

Read flat router .route file #2343

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 49 additions & 47 deletions vpr/src/base/read_route.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@
#include "old_traceback.h"

/*************Functions local to this module*************/
static void process_route(std::ifstream& fp, const char* filename, int& lineno);
static void process_nodes(std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno);
static void process_nets(std::ifstream& fp, ClusterNetId inet, std::string name, std::vector<std::string> input_tokens, const char* filename, int& lineno);
static void process_global_blocks(std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno);
static void process_route(const Netlist<>& net_list, std::ifstream& fp, const char* filename, int& lineno, bool is_flat);
static void process_nodes(const Netlist<>& net_list, std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno);
static void process_nets(const Netlist<>& net_list, std::ifstream& fp, ClusterNetId inet, std::string name, std::vector<std::string> input_tokens, const char* filename, int& lineno, bool is_flat);
static void process_global_blocks(const Netlist<>& net_list, std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno, bool is_flat);
static void format_coordinates(int& layer_num, int& x, int& y, std::string coord, ClusterNetId net, const char* filename, const int lineno);
static void format_pin_info(std::string& pb_name, std::string& port_name, int& pb_pin_num, std::string input);
static std::string format_name(std::string name);
Expand All @@ -69,7 +69,7 @@ void print_route(const Netlist<>& net_list, FILE* fp, bool is_flat);
* Perform a series of verification tests to ensure the netlist,
* placement, and routing files match
*/
bool read_route(const char* route_file, const t_router_opts& router_opts, bool verify_file_digests) {
bool read_route(const char* route_file, const t_router_opts& router_opts, bool verify_file_digests, bool is_flat) {
auto& device_ctx = g_vpr_ctx.mutable_device();
auto& place_ctx = g_vpr_ctx.placement();
bool flat_router = router_opts.flat_routing;
Expand Down Expand Up @@ -124,7 +124,7 @@ bool read_route(const char* route_file, const t_router_opts& router_opts, bool v
}

/* Read in every net */
process_route(fp, route_file, lineno);
process_route(router_net_list, fp, route_file, lineno, is_flat);

fp.close();

Expand Down Expand Up @@ -157,7 +157,7 @@ bool read_route(const char* route_file, const t_router_opts& router_opts, bool v
}

///@brief Walks through every net and add the routing appropriately
static void process_route(std::ifstream& fp, const char* filename, int& lineno) {
static void process_route(const Netlist<>& net_list, std::ifstream& fp, const char* filename, int& lineno, bool is_flat) {
std::string input;
std::vector<std::string> tokens;
while (std::getline(fp, input)) {
Expand All @@ -170,59 +170,55 @@ static void process_route(std::ifstream& fp, const char* filename, int& lineno)
continue; //Skip commented lines
} else if (tokens[0] == "Net") {
ClusterNetId inet(atoi(tokens[1].c_str()));
process_nets(fp, inet, tokens[2], tokens, filename, lineno);
process_nets(net_list, fp, inet, tokens[2], tokens, filename, lineno, is_flat);
}
}

tokens.clear();
}

///@brief Check if the net is global or not, and process appropriately
static void process_nets(std::ifstream& fp, ClusterNetId inet, std::string name, std::vector<std::string> input_tokens, const char* filename, int& lineno) {
auto& cluster_ctx = g_vpr_ctx.mutable_clustering();

static void process_nets(const Netlist<>& net_list, std::ifstream& fp, ClusterNetId inet, std::string name, std::vector<std::string> input_tokens, const char* filename, int& lineno, bool is_flat) {
if (input_tokens.size() > 3 && input_tokens[3] == "global"
&& input_tokens[4] == "net" && input_tokens[5] == "connecting:") {
/* Global net. Never routed. */
if (!cluster_ctx.clb_nlist.net_is_ignored(inet)) {
if (!net_list.net_is_ignored(inet)) {
vpr_throw(VPR_ERROR_ROUTE, filename, lineno,
"Net %lu should be a global net", size_t(inet));
}
/*erase an extra colon for global nets*/
name.erase(name.end() - 1);
name = format_name(name);

if (0 != cluster_ctx.clb_nlist.net_name(inet).compare(name)) {
if (0 != net_list.net_name(inet).compare(name)) {
vpr_throw(VPR_ERROR_ROUTE, filename, lineno,
"Net name %s for net number %lu specified in the routing file does not match given %s",
name.c_str(), size_t(inet), cluster_ctx.clb_nlist.net_name(inet).c_str());
"Net name %s for net number %lu specified in the routing file does not match given %s. Running without flat routing; if this file was created with flat routing, re-run vpr with the --flat_routing option",
name.c_str(), size_t(inet), net_list.net_name(inet).c_str());
}

process_global_blocks(fp, inet, filename, lineno);
process_global_blocks(net_list, fp, inet, filename, lineno, is_flat);
} else {
/* Not a global net */
if (cluster_ctx.clb_nlist.net_is_ignored(inet)) {
VTR_LOG_WARN("Net %lu (%s) is marked as global in the netlist, but is non-global in the .route file\n", size_t(inet), cluster_ctx.clb_nlist.net_name(inet).c_str());
if (net_list.net_is_ignored(inet)) {
VTR_LOG_WARN("Net %lu (%s) is marked as global in the netlist, but is non-global in the .route file\n", size_t(inet), net_list.net_name(inet).c_str());
}

name = format_name(name);

if (0 != cluster_ctx.clb_nlist.net_name(inet).compare(name)) {
if (0 != net_list.net_name(inet).compare(name)) {
vpr_throw(VPR_ERROR_ROUTE, filename, lineno,
"Net name %s for net number %lu specified in the routing file does not match given %s",
name.c_str(), size_t(inet), cluster_ctx.clb_nlist.net_name(inet).c_str());
"Net name %s for net number %lu specified in the routing file does not match given %s. Running without flat routing; if this file was created with flat routing, re-run vpr with the --flat_routing option",
name.c_str(), size_t(inet), net_list.net_name(inet).c_str());
}

process_nodes(fp, inet, filename, lineno);
process_nodes(net_list, fp, inet, filename, lineno);
}
input_tokens.clear();
return;
}

static void process_nodes(std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno) {
static void process_nodes(const Netlist<>& net_list, std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno) {
/* Not a global net. Goes through every node and add it into trace.head*/

auto& cluster_ctx = g_vpr_ctx.mutable_clustering();
auto& device_ctx = g_vpr_ctx.mutable_device();
const auto& rr_graph = device_ctx.rr_graph;
auto& route_ctx = g_vpr_ctx.mutable_routing();
Expand Down Expand Up @@ -257,7 +253,7 @@ static void process_nodes(std::ifstream& fp, ClusterNetId inet, const char* file
fp.seekg(oldpos);
break;
} else if (input == "\n\nUsed in local cluster only, reserved one CLB pin\n\n") {
if (cluster_ctx.clb_nlist.net_sinks(inet).size() != 0) {
if (net_list.net_sinks(inet).size() != 0) {
vpr_throw(VPR_ERROR_ROUTE, filename, lineno,
"Net %d should be used in local cluster only, reserved one CLB pin");
}
Expand Down Expand Up @@ -327,7 +323,7 @@ static void process_nodes(std::ifstream& fp, ClusterNetId inet, const char* file
ptc = atoi(tokens[5 + offset].c_str());
if (rr_graph.node_ptc_num(RRNodeId(inode)) != ptc) {
vpr_throw(VPR_ERROR_ROUTE, filename, lineno,
"The ptc num of node %d does not match the rr graph", inode);
"The ptc num of node %d does not match the rr graph, Running without flat routing; if this file was created with flat routing, re-run vpr with the --flat_routing option", inode);
}

/*Process switches and pb pin info if it is ipin or opin type*/
Expand All @@ -336,17 +332,25 @@ static void process_nodes(std::ifstream& fp, ClusterNetId inet, const char* file
auto type = device_ctx.grid.get_physical_type({x, y, layer_num});
if (!is_io_type(type) && (tokens[2] == "IPIN" || tokens[2] == "OPIN")) {
int pin_num = rr_graph.node_pin_num(RRNodeId(inode));

int width_offset = device_ctx.grid.get_width_offset({x, y, layer_num});
int height_offset = device_ctx.grid.get_height_offset({x, y, layer_num});
auto physical_tile = device_ctx.grid.get_physical_type({x, y, layer_num});
const t_sub_tile* sub_tile;
int sub_tile_rel_cap;
std::tie(sub_tile, sub_tile_rel_cap) = get_sub_tile_from_pin_physical_num(physical_tile, pin_num);
int sub_tile_offset = sub_tile->capacity.low + sub_tile_rel_cap;

int capacity, relative_pin;
std::tie(capacity, relative_pin) = get_capacity_location_from_physical_pin(type, pin_num);
ClusterBlockId iblock = place_ctx.grid_blocks.block_at_location({x - width_offset, y - height_offset, sub_tile_offset, layer_num});
VTR_ASSERT(iblock);

ClusterBlockId iblock = place_ctx.grid_blocks.block_at_location({x, y - height_offset, capacity, layer_num});
const t_pb_graph_pin* pb_pin;

t_pb_graph_pin* pb_pin;
if (is_pin_on_tile(physical_tile, pin_num)) {
pb_pin = get_pb_graph_node_pin_from_block_pin(iblock, pin_num);
} else {
pb_pin = get_pb_pin_from_pin_physical_num(physical_tile, pin_num);
}

pb_pin = get_pb_graph_node_pin_from_block_pin(iblock, pin_num);
t_pb_type* pb_type = pb_pin->parent_node->pb_type;

std::string pb_name, port_name;
Expand Down Expand Up @@ -415,14 +419,10 @@ static void process_nodes(std::ifstream& fp, ClusterNetId inet, const char* file
* @brief This function goes through all the blocks in a global net and verify
* it with the clustered netlist and the placement
*/
static void process_global_blocks(std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno) {
auto& cluster_ctx = g_vpr_ctx.mutable_clustering();
auto& place_ctx = g_vpr_ctx.placement();

static void process_global_blocks(const Netlist<>& net_list, std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno, bool is_flat) {
std::string block, bnum_str;
int layer_num, x, y;
std::vector<std::string> tokens;
int pin_counter = 0;

std::streampos oldpos = fp.tellg();
/*Walk through every block line*/
Expand All @@ -446,27 +446,29 @@ static void process_global_blocks(std::ifstream& fp, ClusterNetId inet, const ch
bnum_str = format_name(tokens[2]);
/*remove #*/
bnum_str.erase(bnum_str.begin());
ClusterBlockId bnum(atoi(bnum_str.c_str()));
ParentBlockId bnum(atoi(bnum_str.c_str()));

/*Check for name, coordinate, and pins*/
if (0 != cluster_ctx.clb_nlist.block_name(bnum).compare(tokens[1])) {
if (0 != net_list.block_name(bnum).compare(tokens[1])) {
vpr_throw(VPR_ERROR_ROUTE, filename, lineno,
"Block %s for block number %lu specified in the routing file does not match given %s",
tokens[1].c_str(), size_t(bnum), cluster_ctx.clb_nlist.block_name(bnum).c_str());
tokens[1].c_str(), size_t(bnum), net_list.block_name(bnum).c_str());
}
if (place_ctx.block_locs[bnum].loc.x != x || place_ctx.block_locs[bnum].loc.y != y) {

auto block_loc = get_block_loc(bnum, is_flat);

if (block_loc.loc.x != x || block_loc.loc.y != y) {
vpr_throw(VPR_ERROR_ROUTE, filename, lineno,
"The placement coordinates (%d, %d) of %d block does not match given (%d, %d)",
x, y, place_ctx.block_locs[bnum].loc.x, place_ctx.block_locs[bnum].loc.y);
x, y, block_loc.loc.x, block_loc.loc.y);
}

int pin_index = net_pin_to_tile_pin_index(inet, pin_counter);
if (physical_tile_type(bnum)->pin_class[pin_index] != atoi(tokens[7].c_str())) {
auto pin_class = get_class_range_for_block(bnum, is_flat);
if (pin_class.low > atoi(tokens[7].c_str()) || pin_class.high < atoi(tokens[7].c_str())) {
vpr_throw(VPR_ERROR_ROUTE, filename, lineno,
"The pin class %d of %lu net does not match given ",
atoi(tokens[7].c_str()), size_t(inet), physical_tile_type(bnum)->pin_class[pin_index]);
atoi(tokens[7].c_str()), size_t(inet));
}
pin_counter++;
}
oldpos = fp.tellg();
}
Expand Down
2 changes: 1 addition & 1 deletion vpr/src/base/read_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "netlist.h"
#include "vpr_types.h"

bool read_route(const char* route_file, const t_router_opts& RouterOpts, bool verify_file_digests);
bool read_route(const char* route_file, const t_router_opts& RouterOpts, bool verify_file_digests, bool is_flat);
void print_route(const Netlist<>& net_list, const char* placement_file, const char* route_file, bool is_flat);

#endif /* READ_ROUTE_H */
22 changes: 14 additions & 8 deletions vpr/src/base/vpr_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,14 +819,20 @@ RouteStatus vpr_route_flow(const Netlist<>& net_list,
is_flat);
} else {
VTR_ASSERT(router_opts.doRouting == STAGE_LOAD);

//Load a previous routing
// TODO: flat routing is not implemented for this part
//if the previous load file is generated using flat routing,
//we need to create rr_graph with is_flat flag to add additional
//internal nodes/edges.
if (is_flat) {
vpr_create_rr_graph(vpr_setup, arch, chan_width, is_flat);
}

route_status = vpr_load_routing(vpr_setup,
arch,
chan_width,
timing_info,
net_delay);
net_delay,
is_flat);
}

//Post-implementation
Expand Down Expand Up @@ -969,7 +975,8 @@ RouteStatus vpr_load_routing(t_vpr_setup& vpr_setup,
const t_arch& /*arch*/,
int fixed_channel_width,
std::shared_ptr<SetupHoldTimingInfo> timing_info,
NetPinsMatrix<float>& net_delay) {
NetPinsMatrix<float>& net_delay,
bool is_flat) {
vtr::ScopedStartFinishTimer timer("Load Routing");
if (NO_FIXED_CHANNEL_WIDTH == fixed_channel_width) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Fixed channel width must be specified when loading routing (was %d)", fixed_channel_width);
Expand All @@ -978,13 +985,12 @@ RouteStatus vpr_load_routing(t_vpr_setup& vpr_setup,
auto& filename_opts = vpr_setup.FileNameOpts;

//Load the routing from a file
bool is_legal = read_route(filename_opts.RouteFile.c_str(), vpr_setup.RouterOpts, filename_opts.verify_file_digests);

bool is_legal = read_route(filename_opts.RouteFile.c_str(), vpr_setup.RouterOpts, filename_opts.verify_file_digests, is_flat);
const Netlist<>& router_net_list = is_flat ? (const Netlist<>&)g_vpr_ctx.atom().nlist : (const Netlist<>&)g_vpr_ctx.clustering().clb_nlist;
if (vpr_setup.Timing.timing_analysis_enabled) {
//Update timing info
load_net_delay_from_routing((const Netlist<>&)g_vpr_ctx.clustering().clb_nlist,
load_net_delay_from_routing(router_net_list,
net_delay);

timing_info->update();
}
init_draw_coords(fixed_channel_width);
Expand Down
3 changes: 2 additions & 1 deletion vpr/src/base/vpr_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ RouteStatus vpr_load_routing(t_vpr_setup& vpr_setup,
const t_arch& arch,
int fixed_channel_width,
std::shared_ptr<SetupHoldTimingInfo> timing_info,
NetPinsMatrix<float>& net_delay);
NetPinsMatrix<float>& net_delay,
bool is_flat);

/* Analysis */

Expand Down