@@ -71,9 +71,11 @@ void read_constraints(const char* constraints_file,
71
71
72
72
/* *
73
73
* This function reads the header (first two lines) of a placement file.
74
+ * The header consists of two lines that specify the netlist file and grid size that were used when generating placement.
74
75
* It checks whether the packed netlist file that generated the placement matches the current netlist file.
75
76
* It also checks whether the FPGA grid size has stayed the same from when the placement was generated.
76
77
* The verify_file_digests bool is used to decide whether to give a warning or an error if the netlist files do not match.
78
+ * An error is given if the grid size has changed.
77
79
*/
78
80
void read_place_header (std::ifstream& placement_file,
79
81
const char * net_file,
@@ -146,7 +148,7 @@ void read_place_header(std::ifstream& placement_file,
146
148
grid.width (), grid.height (), place_file_width, place_file_height);
147
149
}
148
150
149
- seen_grid_dimensions = true ; // if you have read the grid dimensions you are done reading the place file header
151
+ seen_grid_dimensions = true ;
150
152
151
153
} else {
152
154
// Unrecognized
@@ -159,6 +161,7 @@ void read_place_header(std::ifstream& placement_file,
159
161
160
162
/* *
161
163
* This function reads either the body of a placement file or a constraints file.
164
+ * A constraints file is in the same format as a placement file, but without the first two header lines.
162
165
* If it is reading a place file it sets the x, y, and subtile locations of the blocks in the placement context.
163
166
* If it is reading a constraints file it does the same and also marks the blocks as locked and marks the grid usage.
164
167
* The bool is_place_file indicates if the file should be read as a place file (is_place_file = true)
@@ -174,7 +177,19 @@ void read_place_body(std::ifstream& placement_file,
174
177
std::string line;
175
178
int lineno = 0 ;
176
179
177
- std::vector<ClusterBlockId> seen_blocks;
180
+ if (place_ctx.block_locs .size () != cluster_ctx.clb_nlist .blocks ().size ()) {
181
+ // Resize if needed
182
+ place_ctx.block_locs .resize (cluster_ctx.clb_nlist .blocks ().size ());
183
+ }
184
+
185
+ // used to count how many times a block has been seen in the place/constraints file so duplicate blocks can be detected
186
+ vtr::vector_map<ClusterBlockId, int > seen_blocks;
187
+
188
+ // initialize seen_blocks
189
+ for (auto block_id : cluster_ctx.clb_nlist .blocks ()) {
190
+ int seen_count = 0 ;
191
+ seen_blocks.insert (block_id, seen_count);
192
+ }
178
193
179
194
while (std::getline (placement_file, line)) { // Parse line-by-line
180
195
++lineno;
@@ -198,22 +213,25 @@ void read_place_body(std::ifstream& placement_file,
198
213
int block_y = vtr::atoi (tokens[2 ]);
199
214
int sub_tile_index = vtr::atoi (tokens[3 ]);
200
215
216
+ // c-style block name needed for printing block name in error messages
217
+ char const * c_block_name = block_name.c_str ();
218
+
201
219
ClusterBlockId blk_id = cluster_ctx.clb_nlist .find_block (block_name);
202
220
221
+ // Check if block name is valid
222
+ if (blk_id == ClusterBlockId::INVALID ()) {
223
+ VPR_THROW (VPR_ERROR_PLACE, " Block %s has an invalid name.\n " , c_block_name);
224
+ }
225
+
203
226
// Check if block is listed twice in constraints file
204
- if (find ( seen_blocks. begin (), seen_blocks. end (), blk_id) != seen_blocks. end () ) {
205
- VPR_THROW (VPR_ERROR_PLACE, " The block with ID %d is listed twice in the constraints file.\n " , blk_id);
227
+ if (seen_blocks[ blk_id] != 0 ) {
228
+ VPR_THROW (VPR_ERROR_PLACE, " Block %s with ID %d is listed twice in the constraints file.\n " , c_block_name , blk_id);
206
229
}
207
230
208
231
// Check if block location is out of range of grid dimensions
209
232
if (block_x < 0 || block_x > int (device_ctx.grid .width () - 1 )
210
233
|| block_y < 0 || block_y > int (device_ctx.grid .height () - 1 )) {
211
- VPR_THROW (VPR_ERROR_PLACE, " The block with ID %d is out of range at location (%d, %d). \n " , blk_id, block_x, block_y);
212
- }
213
-
214
- if (place_ctx.block_locs .size () != cluster_ctx.clb_nlist .blocks ().size ()) {
215
- // Resize if needed
216
- place_ctx.block_locs .resize (cluster_ctx.clb_nlist .blocks ().size ());
234
+ VPR_THROW (VPR_ERROR_PLACE, " Block %s with ID %d is out of range at location (%d, %d). \n " , c_block_name, blk_id, block_x, block_y);
217
235
}
218
236
219
237
// Set the location
@@ -222,14 +240,16 @@ void read_place_body(std::ifstream& placement_file,
222
240
place_ctx.block_locs [blk_id].loc .sub_tile = sub_tile_index;
223
241
224
242
// Check if block is at an illegal location
243
+
225
244
auto physical_tile = device_ctx.grid [block_x][block_y].type ;
226
245
auto logical_block = cluster_ctx.clb_nlist .block_type (blk_id);
227
- if (!is_sub_tile_compatible (physical_tile, logical_block, place_ctx.block_locs [blk_id].loc .sub_tile )) {
228
- VPR_THROW (VPR_ERROR_PLACE, place_file, 0 , " Attempt to place block %d at illegal location (%d, %d). \n " , blk_id, block_x, block_y);
229
- }
230
246
231
247
if (sub_tile_index >= physical_tile->capacity || sub_tile_index < 0 ) {
232
- VPR_THROW (VPR_ERROR_PLACE, place_file, vtr::get_file_line_number_of_last_opened_file (), " Block %d subtile number (%d) is out of range. \n " , blk_id, sub_tile_index);
248
+ VPR_THROW (VPR_ERROR_PLACE, " Block %s subtile number (%d) is out of range. \n " , c_block_name, sub_tile_index);
249
+ }
250
+
251
+ if (!is_sub_tile_compatible (physical_tile, logical_block, place_ctx.block_locs [blk_id].loc .sub_tile )) {
252
+ VPR_THROW (VPR_ERROR_PLACE, " Attempt to place block %s with ID %d at illegal location (%d, %d). \n " , c_block_name, blk_id, block_x, block_y);
233
253
}
234
254
235
255
// need to lock down blocks and mark grid block usage if it is a constraints file
@@ -239,8 +259,8 @@ void read_place_body(std::ifstream& placement_file,
239
259
place_ctx.grid_blocks [block_x][block_y].usage ++;
240
260
}
241
261
242
- // add to vector of blocks that have been seen
243
- seen_blocks. push_back ( blk_id) ;
262
+ // mark the block as seen
263
+ seen_blocks[ blk_id] = 1 ;
244
264
245
265
} else {
246
266
// Unrecognized
@@ -250,6 +270,15 @@ void read_place_body(std::ifstream& placement_file,
250
270
}
251
271
}
252
272
273
+ // For place files, check that all blocks have been read
274
+ if (is_place_file) {
275
+ for (auto block_id : cluster_ctx.clb_nlist .blocks ()) {
276
+ if (seen_blocks[block_id] == 0 ) {
277
+ VPR_THROW (VPR_ERROR_PLACE, " Block %d has not been read from the place file. \n " , block_id);
278
+ }
279
+ }
280
+ }
281
+
253
282
if (is_place_file) {
254
283
place_ctx.placement_id = vtr::secure_digest_file (place_file);
255
284
}
0 commit comments