Skip to content

Commit 29c66b1

Browse files
committed
vpr: Add command-line option to control routing of constant nets
The new option '--constant_net_method' controls how nets driven by a constant value are treated by VPR: * global: The nets are treated as global and not routed * route : The nets are treated as regular nets and routed The default is 'global' to match previous behaviour. Warnings are produced if a global net connects to a non-global pin. In the longer term VPR should be taught to understand which pins in an architecture are tie-able to vcc/gnd (Issue #163). The 'global' method above is effectively an approximation of this where it is assumed all pins in the architecture are tie-able.
1 parent 9f944ec commit 29c66b1

File tree

7 files changed

+104
-57
lines changed

7 files changed

+104
-57
lines changed

vpr/src/base/check_netlist.cpp

Lines changed: 8 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ using namespace std;
2121

2222
/**************** Subroutines local to this module **************************/
2323

24-
static int check_connections_to_global_clb_pins(ClusterNetId net_id);
24+
static void check_connections_to_global_clb_pins(ClusterNetId net_id);
2525

2626
static int check_for_duplicated_names(void);
2727

@@ -49,7 +49,7 @@ void check_netlist() {
4949
"Net %s has multiple drivers.\n", cluster_ctx.clb_nlist.net_name(net_id).c_str());
5050
error++;
5151
}
52-
error += check_connections_to_global_clb_pins(net_id);
52+
check_connections_to_global_clb_pins(net_id);
5353
if (error >= ERROR_THRESHOLD) {
5454
vtr::printf_error(__FILE__, __LINE__,
5555
"Too many errors in netlist, exiting.\n");
@@ -74,39 +74,14 @@ void check_netlist() {
7474
vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
7575
"Found %d fatal Errors in the input netlist.\n", error);
7676
}
77-
78-
/*
79-
* Enhanced HACK: July 2017
80-
* Do not route constant nets (e.g. gnd/vcc). Identifying these nets as constants
81-
* is more robust than the previous approach (exact name match to gnd/vcc).
82-
* Note that by not routing constant nets we are implicitly assuming that all pins
83-
* in the FPGA can be tied to gnd/vcc, and hence we do not need to route them.
84-
*
85-
* TODO: We should ultimately make this architecture driven (e.g. specify which
86-
* pins which can be tied to gnd/vcc), and then route from those pins to
87-
* deliver any constants to those primitive input pins which can not be directly
88-
* tied directly to gnd/vcc.
89-
*/
90-
auto& atom_ctx = g_vpr_ctx.atom();
91-
for (auto net_id : cluster_ctx.clb_nlist.nets()) {
92-
AtomNetId atom_net = atom_ctx.lookup.atom_net(net_id);
93-
VTR_ASSERT(atom_net);
94-
95-
if (atom_ctx.nlist.net_is_constant(atom_net)) {
96-
//Mark net as global, so that it is not routed
97-
vtr::printf_warning(__FILE__, __LINE__, "Treating constant net '%s' as global, so it will not be routed\n", atom_ctx.nlist.net_name(atom_net).c_str());
98-
cluster_ctx.clb_nlist.set_net_is_global(net_id, true);
99-
}
100-
}
10177
}
10278

10379
/* Checks that a global net (net_id) connects only to global CLB input pins *
10480
* and that non-global nets never connects to a global CLB pin. Either *
10581
* global or non-global nets are allowed to connect to pads. */
106-
static int check_connections_to_global_clb_pins(ClusterNetId net_id) {
82+
static void check_connections_to_global_clb_pins(ClusterNetId net_id) {
10783
auto& cluster_ctx = g_vpr_ctx.clustering();
10884

109-
unsigned int error = 0;
11085
bool is_global_net = cluster_ctx.clb_nlist.net_is_global(net_id);
11186

11287
/* For now global signals can be driven by an I/O pad or any CLB output *
@@ -120,32 +95,13 @@ static int check_connections_to_global_clb_pins(ClusterNetId net_id) {
12095
if (cluster_ctx.clb_nlist.block_type(blk_id)->is_global_pin[pin_index] != is_global_net
12196
&& !is_io_type(cluster_ctx.clb_nlist.block_type(blk_id))) {
12297

123-
//Allow a CLB output pin to drive a global net (warning only).
124-
if (pin_id == cluster_ctx.clb_nlist.net_driver(net_id) && is_global_net) {
125-
vtr::printf_warning(__FILE__, __LINE__,
126-
"in check_connections_to_global_clb_pins:\n");
127-
vtr::printf_warning(__FILE__, __LINE__,
128-
"\tnet #%d (%s) is driven by CLB output pin (#%d) on block #%d (%s).\n",
129-
net_id, cluster_ctx.clb_nlist.net_name(net_id).c_str(), pin_index, blk_id, cluster_ctx.clb_nlist.block_name(blk_id).c_str());
130-
}
131-
else { //Otherwise -> Error
132-
vtr::printf_error(__FILE__, __LINE__,
133-
"in check_connections_to_global_clb_pins:\n");
134-
vtr::printf_error(__FILE__, __LINE__,
135-
"\tpin %d on net #%d (%s) connects to CLB input pin (#%d) on block #%d (%s).\n",
136-
pin_id, net_id, cluster_ctx.clb_nlist.net_name(net_id).c_str(), pin_index, blk_id, cluster_ctx.clb_nlist.block_name(blk_id).c_str());
137-
error++;
138-
}
139-
140-
if (is_global_net)
141-
vtr::printf_info("Net is global, but CLB pin is not.\n");
142-
else
143-
vtr::printf_info("CLB pin is global, but net is not.\n");
144-
vtr::printf_info("\n");
98+
vtr::printf_warning(__FILE__, __LINE__,
99+
"Global net '%s' connects to non-global architecture pin '%s' (netlist pin '%s')\n",
100+
cluster_ctx.clb_nlist.net_name(net_id).c_str(),
101+
block_type_pin_index_to_name(cluster_ctx.clb_nlist.block_type(blk_id), pin_index).c_str(),
102+
cluster_ctx.clb_nlist.pin_name(pin_id).c_str());
145103
}
146104
}
147-
148-
return error;
149105
}
150106

151107
/* Checks that the connections into and out of the clb make sense. */

vpr/src/base/constant_nets.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include "constant_nets.h"
2+
3+
#include "clustered_netlist.h"
4+
5+
#include "vtr_assert.h"
6+
7+
8+
9+
void process_constant_nets(ClusteredNetlist& nlist, e_constant_net_method method) {
10+
11+
if (method == CONSTANT_NET_GLOBAL) {
12+
/*
13+
* Treat constant nets (e.g. gnd/vcc) as globals so they are not routed.
14+
* Identifying these nets as constants is more robust than the previous
15+
* approach (exact name match to gnd/vcc).
16+
*
17+
* Note that by not routing constant nets we are implicitly assuming that all pins
18+
* in the FPGA can be tied to gnd/vcc, and hence we do not need to route them.
19+
*/
20+
for (ClusterNetId net : nlist.nets()) {
21+
22+
if (nlist.net_is_constant(net)) {
23+
//Mark net as global, so that it is not routed
24+
vtr::printf_warning(__FILE__, __LINE__, "Treating constant net '%s' as global (will not be routed)\n",
25+
nlist.net_name(net).c_str());
26+
nlist.set_net_is_global(net, true);
27+
}
28+
}
29+
} else {
30+
VTR_ASSERT(method == CONSTANT_NET_ROUTE);
31+
/* Treat constants the same as any other net, so they will be routed. Note that this requires
32+
* they have a valid driver (e.g. constant LUT).
33+
*
34+
* TODO: We should ultimately make this architecture driven (e.g. specify which
35+
* pins which can be tied to gnd/vcc), and then route from those pins to
36+
* deliver any constants to those primitive input pins which can not be directly
37+
* tied directly to gnd/vcc.
38+
*/
39+
}
40+
}

vpr/src/base/constant_nets.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#ifndef CONSTANT_NETS_H
2+
#define CONSTANT_NETS_H
3+
4+
#include "clustered_netlist_fwd.h"
5+
6+
enum e_constant_net_method {
7+
CONSTANT_NET_GLOBAL, //Treat constant nets as globals (i.e. not routed)
8+
CONSTANT_NET_ROUTE //Treat constant nets a non-globals (i.e. routed)
9+
};
10+
11+
void process_constant_nets(ClusteredNetlist& nlist, e_constant_net_method method);
12+
13+
#endif

vpr/src/base/read_options.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "read_options.h"
2+
#include "constant_nets.h"
23
#include "vpr_error.h"
34

45
#include "argparse.hpp"
@@ -214,6 +215,26 @@ struct ParseClusterSeed {
214215
}
215216
};
216217

218+
struct ParseConstantNetMethod {
219+
e_constant_net_method from_str(std::string str) {
220+
if (str == "global") return CONSTANT_NET_GLOBAL;
221+
else if (str == "route") return CONSTANT_NET_ROUTE;
222+
std::stringstream msg;
223+
msg << "Invalid conversion from '" << str << "' to e_constant_net_method (expected one of: " << argparse::join(default_choices(), ", ") << ")";
224+
throw argparse::ArgParseConversionError(msg.str());
225+
}
226+
227+
std::string to_str(e_constant_net_method val) {
228+
if (val == CONSTANT_NET_GLOBAL) return "global";
229+
VTR_ASSERT(val == CONSTANT_NET_ROUTE);
230+
return "route";
231+
}
232+
233+
std::vector<std::string> default_choices() {
234+
return {"global", "route"};
235+
}
236+
};
237+
217238
static argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& args) {
218239
std::string description = "Implements the specified circuit onto the target FPGA architecture"
219240
" by performing packing/placement/routing, and analyzes the result.\n"
@@ -357,6 +378,15 @@ static argparse::ArgumentParser create_arg_parser(std::string prog_name, t_optio
357378
.default_value("1.0")
358379
.show_in(argparse::ShowIn::HELP_ONLY);
359380

381+
gen_grp.add_argument<e_constant_net_method,ParseConstantNetMethod>(args.constant_net_method, "--constant_net_method")
382+
.help("Specifies how constant nets (i.e. those driven to a constant\n"
383+
"value) are handled:\n"
384+
" * global: Treat constant nets as globals (not routed)\n"
385+
" * route : Treat constant nets as normal nets (routed)\n")
386+
.default_value("global")
387+
.show_in(argparse::ShowIn::HELP_ONLY);
388+
389+
360390
auto& file_grp = parser.add_argument_group("file options");
361391

362392
file_grp.add_argument(args.BlifFile, "--circuit_file")
@@ -369,9 +399,9 @@ static argparse::ArgumentParser create_arg_parser(std::string prog_name, t_optio
369399
" * blif: Strict structural BLIF format\n"
370400
" * eblif: Structure BLIF format with the extensions:\n"
371401
" .conn - Connection between two wires\n"
372-
" .cname - Custom name for atom primitives\n"
373-
" .param - Parameters on atom primitives\n"
374-
" .attr - Attributes on atom primitives\n")
402+
" .cname - Custom name for atom primitive\n"
403+
" .param - Parameter on atom primitive\n"
404+
" .attr - Attribute on atom primitive\n")
375405
.default_value("auto")
376406
.show_in(argparse::ShowIn::HELP_ONLY);
377407

vpr/src/base/read_options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "read_blif.h"
44

55
#include "vpr_types.h"
6+
#include "constant_nets.h"
67
#include "argparse_value.hpp"
78

89
struct t_options {
@@ -47,6 +48,7 @@ struct t_options {
4748
argparse::ArgValue<bool> verify_file_digests;
4849
argparse::ArgValue<std::string> device_layout;
4950
argparse::ArgValue<float> target_device_utilization;
51+
argparse::ArgValue<e_constant_net_method> constant_net_method;
5052

5153
/* Atom netlist options */
5254
argparse::ArgValue<bool> absorb_buffer_luts;

vpr/src/base/vpr_api.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ using namespace std;
6666
#include "net_delay.h"
6767
#include "RoutingDelayCalculator.h"
6868
#include "check_route.h"
69+
#include "constant_nets.h"
6970

7071
#include "timing_graph_builder.h"
7172
#include "timing_reports.h"
@@ -201,9 +202,9 @@ void vpr_init(const int argc, const char **argv,
201202
}
202203
#endif
203204

204-
/* Timing option priorities */
205205
vpr_setup->TimingEnabled = options->timing_analysis;
206206
vpr_setup->device_layout = options->device_layout;
207+
vpr_setup->constant_net_method = options->constant_net_method;
207208

208209
vtr::printf_info("\n");
209210
vtr::printf_info("Architecture file: %s\n", options->ArchFile.value().c_str());
@@ -502,8 +503,11 @@ void vpr_load_packing(t_vpr_setup& vpr_setup, const t_arch& arch) {
502503

503504
auto& cluster_ctx = g_vpr_ctx.mutable_clustering();
504505

505-
cluster_ctx.clb_nlist = read_netlist(vpr_setup.FileNameOpts.NetFile.c_str(), &arch, vpr_setup.FileNameOpts.verify_file_digests);
506+
cluster_ctx.clb_nlist = read_netlist(vpr_setup.FileNameOpts.NetFile.c_str(),
507+
&arch,
508+
vpr_setup.FileNameOpts.verify_file_digests);
506509

510+
process_constant_nets(cluster_ctx.clb_nlist, vpr_setup.constant_net_method);
507511
}
508512

509513
bool vpr_place_flow(t_vpr_setup& vpr_setup, const t_arch& arch) {

vpr/src/base/vpr_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "arch_types.h"
2929
#include "atom_netlist_fwd.h"
3030
#include "clustered_netlist_fwd.h"
31+
#include "constant_nets.h"
3132

3233
#include "vtr_assert.h"
3334
#include "vtr_ndmatrix.h"
@@ -1117,6 +1118,7 @@ struct t_vpr_setup {
11171118
int GraphPause; /* user interactiveness graphics option */
11181119
t_power_opts PowerOpts;
11191120
std::string device_layout;
1121+
e_constant_net_method constant_net_method; //How constant nets should be handled
11201122
};
11211123

11221124
class RouteStatus {

0 commit comments

Comments
 (0)