Skip to content

Commit fe0d75e

Browse files
committed
vpr/archfpga: Add utilization-based packing heuristic to select block types
If a particular netlist primitive can be implemented in multiple block types, VPR's packer will now prefer to use the type with the (currently) lowest utilization. This is a very simple heuristic which considers *only* the current utilization, it considers no other factors (e.g. timing, optimal resource allocation). Previously VPR would use the first legal block type encountered, which could leave alternative block types unused. Also updates libarchfpga and VPR to use the same built-in model names in both the models and pb graph data structures, using the common MODEL_* strings defined in arch_types.h.
1 parent c33056c commit fe0d75e

File tree

19 files changed

+197
-163
lines changed

19 files changed

+197
-163
lines changed

libs/libarchfpga/src/arch_types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,10 @@ constexpr int UNDEFINED = -1;
2121
/* Maximum value for mininum channel width to avoid overflows of short data type. */
2222
constexpr int MAX_CHANNEL_WIDTH = 8000;
2323

24+
/* Built-in library models */
25+
constexpr const char* MODEL_NAMES = ".names";
26+
constexpr const char* MODEL_LATCH = ".latch";
27+
constexpr const char* MODEL_INPUT = ".input";
28+
constexpr const char* MODEL_OUTPUT = ".output";
2429
#endif
2530

libs/libarchfpga/src/arch_util.cpp

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -940,7 +940,7 @@ void CreateModelLibrary(t_arch *arch) {
940940
model_library = new t_model[4];
941941

942942
//INPAD
943-
model_library[0].name = vtr::strdup("input");
943+
model_library[0].name = vtr::strdup(MODEL_INPUT);
944944
model_library[0].index = 0;
945945
model_library[0].inputs = NULL;
946946
model_library[0].instances = NULL;
@@ -955,7 +955,7 @@ void CreateModelLibrary(t_arch *arch) {
955955
model_library[0].outputs->is_clock = false;
956956

957957
//OUTPAD
958-
model_library[1].name = vtr::strdup("output");
958+
model_library[1].name = vtr::strdup(MODEL_OUTPUT);
959959
model_library[1].index = 1;
960960
model_library[1].inputs = new t_model_ports[1];
961961
model_library[1].inputs->dir = IN_PORT;
@@ -970,7 +970,7 @@ void CreateModelLibrary(t_arch *arch) {
970970
model_library[1].outputs = NULL;
971971

972972
//LATCH
973-
model_library[2].name = vtr::strdup("latch");
973+
model_library[2].name = vtr::strdup(MODEL_LATCH);
974974
model_library[2].index = 2;
975975
model_library[2].inputs = new t_model_ports[2];
976976

@@ -1005,7 +1005,7 @@ void CreateModelLibrary(t_arch *arch) {
10051005
model_library[2].outputs[0].clock = "clk";
10061006

10071007
//NAMES
1008-
model_library[3].name = vtr::strdup("names");
1008+
model_library[3].name = vtr::strdup(MODEL_NAMES);
10091009
model_library[3].index = 3;
10101010

10111011
model_library[3].inputs = new t_model_ports[1];
@@ -1049,31 +1049,26 @@ void SyncModelsPbTypes_rec(t_arch *arch,
10491049
t_model *model_match_prim, *cur_model;
10501050
t_model_ports *model_port;
10511051
vtr::t_linked_vptr *old;
1052-
char* blif_model_name;
1052+
char* blif_model_name = nullptr;
10531053

10541054
bool found;
10551055

10561056
if (pb_type->blif_model != NULL) {
10571057

10581058
/* get actual name of subckt */
1059-
if (strstr(pb_type->blif_model, ".subckt ") == pb_type->blif_model) {
1060-
blif_model_name = strchr(pb_type->blif_model, ' ');
1061-
} else {
1062-
blif_model_name = strchr(pb_type->blif_model, '.');
1059+
blif_model_name = pb_type->blif_model;
1060+
if (strstr(blif_model_name, ".subckt ") == blif_model_name) {
1061+
blif_model_name = strchr(blif_model_name, ' ');
1062+
++blif_model_name; //Advance past space
10631063
}
1064-
if (blif_model_name) {
1065-
blif_model_name++; /* get character after the '.' or ' ' */
1066-
} else {
1064+
if (!blif_model_name) {
10671065
archfpga_throw(get_arch_file_name(), 0,
10681066
"Unknown blif model %s in pb_type %s\n",
10691067
pb_type->blif_model, pb_type->name);
10701068
}
10711069

10721070
/* There are two sets of models to consider, the standard library of models and the user defined models */
1073-
if ((strcmp(blif_model_name, "input") == 0)
1074-
|| (strcmp(blif_model_name, "output") == 0)
1075-
|| (strcmp(blif_model_name, "names") == 0)
1076-
|| (strcmp(blif_model_name, "latch") == 0)) {
1071+
if (is_library_model(blif_model_name)) {
10771072
cur_model = arch->model_library;
10781073
} else {
10791074
cur_model = arch->models;
@@ -1254,3 +1249,17 @@ bool segment_exists(const t_arch* arch, std::string name) {
12541249
return find_segment(arch, name) != nullptr;
12551250
}
12561251

1252+
bool is_library_model(const char* model_name) {
1253+
if (model_name == std::string(MODEL_NAMES)
1254+
|| model_name == std::string(MODEL_LATCH)
1255+
|| model_name == std::string(MODEL_INPUT)
1256+
|| model_name == std::string(MODEL_OUTPUT)) {
1257+
return true;
1258+
}
1259+
return false;
1260+
}
1261+
1262+
bool is_library_model(const t_model* model) {
1263+
return is_library_model(model->name);
1264+
}
1265+

libs/libarchfpga/src/arch_util.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,6 @@ void primitives_annotation_clock_match(
4040

4141
bool segment_exists(const t_arch* arch, std::string name);
4242
t_segment_inf* find_segment(const t_arch* arch, std::string name);
43+
bool is_library_model(const char* model_name);
44+
bool is_library_model(const t_model* model);
4345
#endif

libs/libarchfpga/src/echo_arch.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -395,9 +395,9 @@ static void PrintPb_types_rec(FILE* Echo, const t_pb_type * pb_type,
395395
I/O has no annotations to be displayed
396396
All other library or user models may have delays specificied, e.g. Tsetup and Tcq
397397
Display the additional information*/
398-
if (strcmp(pb_type->model->name, "names")
399-
&& strcmp(pb_type->model->name, "input")
400-
&& strcmp(pb_type->model->name, "output")) {
398+
if (strcmp(pb_type->model->name, MODEL_NAMES)
399+
&& strcmp(pb_type->model->name, MODEL_INPUT)
400+
&& strcmp(pb_type->model->name, MODEL_OUTPUT)) {
401401
for (k = 0; k < pb_type->num_annotations; k++) {
402402
fprintf(Echo, "%s\t\t\tannotation %s %s %s %d: %s\n", tabs,
403403
pb_type->annotations[k].clock,

libs/libarchfpga/src/read_xml_arch_file.cpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ std::string inst_port_to_port_name(std::string inst_port);
148148
static bool attribute_to_bool(const pugi::xml_node node,
149149
const pugi::xml_attribute attr,
150150
const pugiutil::loc_data& loc_data);
151-
bool is_library_model(const t_model* model);
152151
int find_switch_by_name(const t_arch& arch, std::string switch_name);
153152

154153
/*
@@ -3348,10 +3347,7 @@ bool check_leaf_pb_model_timing_consistency(const t_pb_type* pb_type, const t_ar
33483347
// by removing the leading '.subckt'
33493348
VTR_ASSERT(pb_type->blif_model);
33503349
std::string blif_model = pb_type->blif_model;
3351-
if(blif_model[0] == '.') {
3352-
blif_model = blif_model.substr(1);
3353-
}
3354-
std::string subckt = "subckt ";
3350+
std::string subckt = ".subckt ";
33553351
auto pos = blif_model.find(subckt);
33563352
if(pos != std::string::npos) {
33573353
blif_model = blif_model.substr(pos + subckt.size());
@@ -3669,13 +3665,6 @@ static bool attribute_to_bool(const pugi::xml_node node,
36693665
return false;
36703666
}
36713667

3672-
bool is_library_model(const t_model* model) {
3673-
if (model->name == std::string("names") || model->name == std::string("latch")) {
3674-
return true;
3675-
}
3676-
return false;
3677-
}
3678-
36793668
int find_switch_by_name(const t_arch& arch, std::string switch_name) {
36803669

36813670
for (int iswitch = 0; iswitch < arch.num_switches; ++iswitch) {

vpr/src/base/SetupVPR.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,10 @@ void SetupVPR(t_options *Options,
113113
VTR_ASSERT(device_ctx.EMPTY_TYPE == nullptr);
114114
device_ctx.EMPTY_TYPE = type;
115115
} else {
116-
if (block_type_contains_blif_model(type, ".input")) {
116+
if (block_type_contains_blif_model(type, MODEL_INPUT)) {
117117
device_ctx.input_types.insert(type);
118118
}
119-
if (block_type_contains_blif_model(type, ".output")) {
119+
if (block_type_contains_blif_model(type, MODEL_OUTPUT)) {
120120
device_ctx.output_types.insert(type);
121121
}
122122
}

vpr/src/base/atom_netlist.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ AtomBlockType AtomNetlist::block_type (const AtomBlockId id) const {
2929
const t_model* blk_model = block_model(id);
3030

3131
AtomBlockType type = AtomBlockType::BLOCK;
32-
if (blk_model->name == std::string("input")) {
32+
if (blk_model->name == std::string(MODEL_INPUT)) {
3333
type = AtomBlockType::INPAD;
3434
}
35-
else if (blk_model->name == std::string("output")) {
35+
else if (blk_model->name == std::string(MODEL_OUTPUT)) {
3636
type = AtomBlockType::OUTPAD;
3737
}
3838
else {

vpr/src/base/atom_netlist_utils.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,7 @@ void print_netlist_as_blif(FILE* f, const AtomNetlist& netlist) {
123123
for(auto blk_id : netlist.blocks()) {
124124
if(netlist.block_type(blk_id) == AtomBlockType::BLOCK) {
125125
const t_model* blk_model = netlist.block_model(blk_id);
126-
if(blk_model->name != std::string("latch")) continue;
127-
126+
if(blk_model->name != std::string(MODEL_LATCH)) continue;
128127

129128
//Nets
130129
std::string d_net;
@@ -199,7 +198,7 @@ void print_netlist_as_blif(FILE* f, const AtomNetlist& netlist) {
199198
for(auto blk_id : netlist.blocks()) {
200199
if(netlist.block_type(blk_id) == AtomBlockType::BLOCK) {
201200
const t_model* blk_model = netlist.block_model(blk_id);
202-
if(blk_model->name != std::string("names")) continue;
201+
if(blk_model->name != std::string(MODEL_NAMES)) continue;
203202

204203

205204
std::vector<AtomNetId> nets;
@@ -260,10 +259,10 @@ void print_netlist_as_blif(FILE* f, const AtomNetlist& netlist) {
260259
std::set<const t_model*> subckt_models;
261260
for(auto blk_id : netlist.blocks()) {
262261
const t_model* blk_model = netlist.block_model(blk_id);
263-
if ( blk_model->name == std::string("latch")
264-
|| blk_model->name == std::string("names")
265-
|| blk_model->name == std::string("input")
266-
|| blk_model->name == std::string("output")) {
262+
if ( blk_model->name == std::string(MODEL_LATCH)
263+
|| blk_model->name == std::string(MODEL_NAMES)
264+
|| blk_model->name == std::string(MODEL_INPUT)
265+
|| blk_model->name == std::string(MODEL_OUTPUT)) {
267266
continue;
268267
}
269268

@@ -397,7 +396,7 @@ bool is_buffer_lut(const AtomNetlist& netlist, const AtomBlockId blk) {
397396
if(netlist.block_type(blk) == AtomBlockType::BLOCK) {
398397
const t_model* blk_model = netlist.block_model(blk);
399398

400-
if(blk_model->name != std::string("names")) return false;
399+
if(blk_model->name != std::string(MODEL_NAMES)) return false;
401400

402401
auto input_ports = netlist.block_input_ports(blk);
403402
auto output_ports = netlist.block_output_ports(blk);
@@ -591,7 +590,7 @@ void fix_clock_to_data_conversions(AtomNetlist& netlist, const t_model* library_
591590
auto clock_data_pins = find_clock_used_as_data_pins(netlist);
592591

593592
//Use the latch D port to generate the data version fo the clock
594-
const t_model* model = find_model(library_models, "latch");
593+
const t_model* model = find_model(library_models, MODEL_LATCH);
595594
VTR_ASSERT(model);
596595
const t_model_ports* clock_port = find_model_port(model, "clk");
597596
VTR_ASSERT(clock_port);

vpr/src/base/netlist_writer.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -823,13 +823,13 @@ class NetlistWriterVisitor : public NetlistVisitor {
823823

824824
const t_model* model = atom_ctx.nlist.block_model(atom_ctx.lookup.pb_atom(atom));
825825

826-
if(model->name == std::string("input")) {
826+
if(model->name == std::string(MODEL_INPUT)) {
827827
inputs_.emplace_back(make_io(atom, PortType::INPUT));
828-
} else if(model->name == std::string("output")) {
828+
} else if(model->name == std::string(MODEL_OUTPUT)) {
829829
outputs_.emplace_back(make_io(atom, PortType::OUTPUT));
830-
} else if(model->name == std::string("names")) {
830+
} else if(model->name == std::string(MODEL_NAMES)) {
831831
cell_instances_.push_back(make_lut_instance(atom));
832-
} else if(model->name == std::string("latch")) {
832+
} else if(model->name == std::string(MODEL_LATCH)) {
833833
cell_instances_.push_back(make_latch_instance(atom));
834834
} else if(model->name == std::string("single_port_ram")) {
835835
cell_instances_.push_back(make_ram_instance(atom));
@@ -1646,7 +1646,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
16461646
auto& atom_ctx = g_vpr_ctx.atom();
16471647

16481648
const t_model* model = atom_ctx.nlist.block_model(atom_ctx.lookup.pb_atom(atom));
1649-
VTR_ASSERT(model->name == std::string("names"));
1649+
VTR_ASSERT(model->name == std::string(MODEL_NAMES));
16501650

16511651
#ifdef DEBUG_LUT_MASK
16521652
std::cout << "Loading LUT mask for: " << atom->name << std::endl;

vpr/src/base/read_blif.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ struct BlifAllocCallback : public blifparse::Callback {
8989
}
9090

9191
void inputs(std::vector<std::string> input_names) override {
92-
const t_model* blk_model = find_model("input");
92+
const t_model* blk_model = find_model(MODEL_INPUT);
9393

9494
VTR_ASSERT_MSG(!blk_model->inputs, "Inpad model has an input port");
9595
VTR_ASSERT_MSG(blk_model->outputs, "Inpad model has no output port");
@@ -106,7 +106,7 @@ struct BlifAllocCallback : public blifparse::Callback {
106106
}
107107

108108
void outputs(std::vector<std::string> output_names) override {
109-
const t_model* blk_model = find_model("output");
109+
const t_model* blk_model = find_model(MODEL_OUTPUT);
110110

111111
VTR_ASSERT_MSG(!blk_model->outputs, "Outpad model has an output port");
112112
VTR_ASSERT_MSG(blk_model->inputs, "Outpad model has no input port");
@@ -125,7 +125,7 @@ struct BlifAllocCallback : public blifparse::Callback {
125125
}
126126

127127
void names(std::vector<std::string> nets, std::vector<std::vector<blifparse::LogicValue>> so_cover) override {
128-
const t_model* blk_model = find_model("names");
128+
const t_model* blk_model = find_model(MODEL_NAMES);
129129

130130
VTR_ASSERT_MSG(nets.size() > 0, "BLIF .names has no connections");
131131

@@ -207,7 +207,7 @@ struct BlifAllocCallback : public blifparse::Callback {
207207
vpr_throw(VPR_ERROR_BLIF_F, filename_.c_str(), lineno_, "Latch must have a clock\n");
208208
}
209209

210-
const t_model* blk_model = find_model("latch");
210+
const t_model* blk_model = find_model(MODEL_LATCH);
211211

212212
VTR_ASSERT_MSG(blk_model->inputs, "Has one input port");
213213
VTR_ASSERT_MSG(blk_model->inputs->next, "Has two input port");
@@ -590,7 +590,7 @@ struct BlifAllocCallback : public blifparse::Callback {
590590
//We look for combinational blocks which are not .names (i.e.
591591
//combinational .subckts)
592592
if(curr_model().block_is_combinational(blk_id)
593-
&& arch_model->name != std::string("names")) {
593+
&& arch_model->name != std::string(MODEL_NAMES)) {
594594

595595
//A subckt is a constant generator if all its input nets are either:
596596
// 1) Constant nets (i.e. driven by constant pins), or
@@ -765,7 +765,7 @@ static void show_blif_stats(const AtomNetlist& netlist) {
765765
for(auto blk_id : netlist.blocks()) {
766766

767767
const t_model* blk_model = netlist.block_model(blk_id);
768-
if(blk_model->name == std::string("names")) {
768+
if(blk_model->name == std::string(MODEL_NAMES)) {
769769
//LUT
770770
size_t lut_size = 0;
771771
auto in_ports = netlist.block_input_ports(blk_id);

vpr/src/base/read_netlist.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,7 @@ static void mark_constant_generators_rec(const t_pb *pb, const t_pb_route *pb_ro
948948
}
949949
}
950950
}
951-
} else if (strcmp(pb->pb_graph_node->pb_type->blif_model, ".input") != 0) {
951+
} else if (strcmp(pb->pb_graph_node->pb_type->blif_model, MODEL_INPUT) != 0) {
952952
const_gen = true;
953953
for (i = 0; i < pb->pb_graph_node->num_input_ports && const_gen == true; i++) {
954954
for (j = 0; j < pb->pb_graph_node->num_input_pins[i] && const_gen == true; j++) {

vpr/src/base/vpr_types.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -290,12 +290,6 @@ struct t_cluster_placement_stats {
290290
t_cluster_placement_primitive *invalid; /* ptrs to primitives that are invalid */
291291
};
292292

293-
/* Built-in library models */
294-
#define MODEL_LOGIC "names"
295-
#define MODEL_LATCH "latch"
296-
#define MODEL_INPUT "input"
297-
#define MODEL_OUTPUT "output"
298-
299293
/******************************************************************
300294
* Timing data types
301295
*******************************************************************/

0 commit comments

Comments
 (0)