1
1
#include < cstdio>
2
2
#include < cstring>
3
3
#include < fstream>
4
+ #include < algorithm>
4
5
5
6
#include " vtr_assert.h"
6
7
#include " vtr_util.h"
15
16
#include " read_place.h"
16
17
#include " read_xml_arch_file.h"
17
18
18
- /* This function reads the header of a placement file.
19
- * The header has two lines:
20
- * One for checking the netlist file
21
- * And another for checking grid dimensions
22
- */
23
- void read_place_header (const char * net_file,
24
- const char * place_file,
25
- bool verify_file_digests,
26
- const DeviceGrid& grid) {
19
+ void read_place_header (
20
+ std::ifstream& placement_file,
21
+ const char * net_file,
22
+ const char * place_file,
23
+ bool verify_file_hashes,
24
+ const DeviceGrid& grid);
25
+
26
+ void read_place_body (
27
+ std::ifstream& placement_file,
28
+ const char * place_file,
29
+ bool is_place_file);
30
+
31
+ void read_place (
32
+ const char * net_file,
33
+ const char * place_file,
34
+ bool verify_file_digests,
35
+ const DeviceGrid& grid,
36
+ bool is_place_file) {
27
37
std::ifstream fstream (place_file);
28
38
if (!fstream) {
29
39
VPR_FATAL_ERROR (VPR_ERROR_PLACE_F,
30
40
" '%s' - Cannot open place file.\n " ,
31
41
place_file);
32
42
}
33
43
44
+ VTR_LOG (" Reading %s.\n " , place_file);
45
+ VTR_LOG (" \n " );
46
+
47
+ read_place_header (fstream, net_file, place_file, verify_file_digests, grid);
48
+ read_place_body (fstream, place_file, is_place_file);
49
+
50
+ VTR_LOG (" Successfully read %s.\n " , place_file);
51
+ VTR_LOG (" \n " );
52
+ }
53
+
54
+ void read_constraints (const char * constraints_file,
55
+ bool is_place_file) {
56
+ std::ifstream fstream (constraints_file);
57
+ if (!fstream) {
58
+ VPR_FATAL_ERROR (VPR_ERROR_PLACE_F,
59
+ " '%s' - Cannot open constraints file.\n " ,
60
+ constraints_file);
61
+ }
62
+
63
+ VTR_LOG (" Reading %s.\n " , constraints_file);
64
+ VTR_LOG (" \n " );
65
+
66
+ read_place_body (fstream, constraints_file, is_place_file);
67
+
68
+ VTR_LOG (" Successfully read %s.\n " , constraints_file);
69
+ VTR_LOG (" \n " );
70
+ }
71
+
72
+ /* *
73
+ * This function reads the header (first two lines) of a placement file.
74
+ * It checks whether the packed netlist file that generated the placement matches the current netlist file.
75
+ * It also checks whether the FPGA grid size has stayed the same from when the placement was generated.
76
+ * The verify_file_digests bool is used to decide whether to give a warning or an error if the netlist files do not match.
77
+ */
78
+ void read_place_header (std::ifstream& placement_file,
79
+ const char * net_file,
80
+ const char * place_file,
81
+ bool verify_file_digests,
82
+ const DeviceGrid& grid) {
34
83
auto & cluster_ctx = g_vpr_ctx.clustering ();
35
84
36
85
std::string line;
37
86
int lineno = 0 ;
38
87
bool seen_netlist_id = false ;
39
- bool read_header_lines = false ;
88
+ bool seen_grid_dimensions = false ;
40
89
41
- while (std::getline (fstream , line) && !read_header_lines ) { // Parse line-by-line
90
+ while (std::getline (placement_file , line) && (!seen_netlist_id || !seen_grid_dimensions) ) { // Parse line-by-line
42
91
++lineno;
43
92
44
93
std::vector<std::string> tokens = vtr::split (line);
@@ -97,7 +146,7 @@ void read_place_header(const char* net_file,
97
146
grid.width (), grid.height (), place_file_width, place_file_height);
98
147
}
99
148
100
- read_header_lines = true ; // if you have read the grid dimensions you are done reading the place file header
149
+ seen_grid_dimensions = true ; // if you have read the grid dimensions you are done reading the place file header
101
150
102
151
} else {
103
152
// Unrecognized
@@ -108,35 +157,26 @@ void read_place_header(const char* net_file,
108
157
}
109
158
}
110
159
111
- /* This function reads either the body of a placement file or a constraints file.
112
- * If it is reading a constraints file it marks blocks as locked as it reads in their locations.
160
+ /* *
161
+ * This function reads either the body of a placement file or a constraints file.
162
+ * If it is reading a place file it sets the x, y, and subtile locations of the blocks in the placement context.
163
+ * If it is reading a constraints file it does the same and also marks the blocks as locked and marks the grid usage.
113
164
* The bool is_place_file indicates if the file should be read as a place file (is_place_file = true)
114
165
* or a constraints file (is_place_file = false).
115
166
*/
116
- void read_place_body (const char * place_file,
167
+ void read_place_body (std::ifstream& placement_file,
168
+ const char * place_file,
117
169
bool is_place_file) {
118
- std::ifstream fstream (place_file);
119
- if (!fstream) {
120
- VPR_FATAL_ERROR (VPR_ERROR_PLACE_F,
121
- " '%s' - Cannot open place file.\n " ,
122
- place_file);
123
- }
124
-
125
170
auto & cluster_ctx = g_vpr_ctx.clustering ();
126
171
auto & device_ctx = g_vpr_ctx.device ();
127
172
auto & place_ctx = g_vpr_ctx.mutable_placement ();
128
173
129
- // Mark unseen blocks for error-checking for constraints file
130
- if (!is_place_file) {
131
- for (auto block_id : cluster_ctx.clb_nlist .blocks ()) {
132
- place_ctx.block_locs [block_id].loc .x = OPEN; // Mark as not seen yet
133
- }
134
- }
135
-
136
174
std::string line;
137
175
int lineno = 0 ;
138
176
139
- while (std::getline (fstream, line)) { // Parse line-by-line
177
+ std::vector<ClusterBlockId> seen_blocks;
178
+
179
+ while (std::getline (placement_file, line)) { // Parse line-by-line
140
180
++lineno;
141
181
142
182
std::vector<std::string> tokens = vtr::split (line);
@@ -147,21 +187,6 @@ void read_place_body(const char* place_file,
147
187
} else if (tokens[0 ][0 ] == ' #' ) {
148
188
continue ; // Skip commented lines
149
189
150
- } else if (is_place_file
151
- && tokens.size () == 4
152
- && tokens[0 ] == " Netlist_File:"
153
- && tokens[2 ] == " Netlist_ID:" ) {
154
- continue ; // Skip netlist line if place file, already checked in read_place_header
155
-
156
- } else if (is_place_file
157
- && tokens.size () == 7
158
- && tokens[0 ] == " Array"
159
- && tokens[1 ] == " size:"
160
- && tokens[3 ] == " x"
161
- && tokens[5 ] == " logic"
162
- && tokens[6 ] == " blocks" ) {
163
- continue ; // Skip checking grid dimensions if place file, already checked in read_place_header
164
-
165
190
} else if (tokens.size () == 4 || (tokens.size () == 5 && tokens[4 ][0 ] == ' #' )) {
166
191
// Load the block location
167
192
//
@@ -176,18 +201,14 @@ void read_place_body(const char* place_file,
176
201
ClusterBlockId blk_id = cluster_ctx.clb_nlist .find_block (block_name);
177
202
178
203
// Check if block is listed twice in constraints file
179
- if (!is_place_file) {
180
- if (place_ctx.block_locs [blk_id].loc .x != OPEN) {
181
- VPR_THROW (VPR_ERROR_PLACE, " The block with ID %d is listed twice in the constraints file.\n " , blk_id);
182
- }
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);
183
206
}
184
207
185
208
// Check if block location is out of range of grid dimensions
186
- if (!is_place_file) {
187
- if (block_x < 0 || block_x > int (device_ctx.grid .width () - 1 )
188
- || block_y < 0 || block_y > int (device_ctx.grid .height () - 1 )) {
189
- 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);
190
- }
209
+ if (block_x < 0 || block_x > int (device_ctx.grid .width () - 1 )
210
+ || 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);
191
212
}
192
213
193
214
if (place_ctx.block_locs .size () != cluster_ctx.clb_nlist .blocks ().size ()) {
@@ -200,26 +221,38 @@ void read_place_body(const char* place_file,
200
221
place_ctx.block_locs [blk_id].loc .y = block_y;
201
222
place_ctx.block_locs [blk_id].loc .sub_tile = sub_tile_index;
202
223
224
+ // Check if block is at an illegal location
225
+ auto physical_tile = device_ctx.grid [block_x][block_y].type ;
226
+ 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 %s at illegal location (%d, %d). \n " , block_name, block_x, block_y);
229
+ }
230
+
231
+ 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 %s subtile number (%d) is out of range. \n " , block_name, sub_tile_index);
233
+ }
234
+
203
235
// need to lock down blocks and mark grid block usage if it is a constraints file
204
236
if (!is_place_file) {
205
237
place_ctx.block_locs [blk_id].is_fixed = true ;
206
238
place_ctx.grid_blocks [block_x][block_y].blocks [sub_tile_index] = blk_id;
207
239
place_ctx.grid_blocks [block_x][block_y].usage ++;
208
240
}
209
241
242
+ // add to vector of blocks that have been seen
243
+ seen_blocks.push_back (blk_id);
244
+
210
245
} else {
211
246
// Unrecognized
212
247
vpr_throw (VPR_ERROR_PLACE_F, place_file, lineno,
213
- " Invalid line '%s' in placement file" ,
248
+ " Invalid line '%s' in file" ,
214
249
line.c_str ());
215
250
}
216
251
}
217
252
218
- if (!is_place_file) {
219
- VTR_LOG (" Successfully read %s.\n " , place_file);
220
- VTR_LOG (" \n " );
253
+ if (is_place_file) {
254
+ place_ctx.placement_id = vtr::secure_digest_file (place_file);
221
255
}
222
- place_ctx.placement_id = vtr::secure_digest_file (place_file);
223
256
}
224
257
225
258
/* *
0 commit comments