@@ -27,9 +27,13 @@ OTHER DEALINGS IN THE SOFTWARE.
27
27
#include < stdlib.h>
28
28
#include < math.h>
29
29
#include " odin_types.h"
30
+ #include " adders.h"
30
31
#include " ast_util.h"
31
32
#include " ast_elaborate.h"
32
33
#include " ast_loop_unroll.h"
34
+ #include " hard_blocks.h"
35
+ #include " memories.h"
36
+ #include " multipliers.h"
33
37
#include " parse_making_ast.h"
34
38
#include " verilog_bison.h"
35
39
#include " netlist_create_from_ast.h"
@@ -101,19 +105,25 @@ OTHER DEALINGS IN THE SOFTWARE.
101
105
// bool check_mult_bracket(std::vector<int> list);
102
106
103
107
void update_string_caches (STRING_CACHE_LIST *local_string_cache_list);
108
+
104
109
void convert_2D_to_1D_array (ast_node_t **var_declare, STRING_CACHE_LIST *local_string_cache_list);
105
110
void convert_2D_to_1D_array_ref (ast_node_t **node, STRING_CACHE_LIST *local_string_cache_list);
106
111
char *make_chunk_size_name (char *instance_name_prefix, char *array_name);
107
112
ast_node_t *get_chunk_size_node (char *instance_name_prefix, char *array_name, STRING_CACHE_LIST *local_string_cache_list);
113
+
108
114
bool verify_terminal (ast_node_t *top, ast_node_t *iterator);
109
115
void verify_genvars (ast_node_t *node, STRING_CACHE_LIST *local_string_cache_list, char ***other_genvars, int num_genvars);
110
116
117
+ ast_node_t *look_for_matching_hard_block (ast_node_t *node, char *hard_block_name);
118
+ ast_node_t *look_for_matching_soft_logic (ast_node_t *node, char *hard_block_name);
119
+
120
+
111
121
int simplify_ast_module (ast_node_t **ast_module, STRING_CACHE_LIST *local_string_cache_list)
112
122
{
113
123
/* resolve constant expressions */
124
+ update_string_caches (local_string_cache_list);
114
125
bool is_module = (*ast_module)->type == MODULE ? true : false ;
115
126
*ast_module = reduce_expressions (*ast_module, NULL , local_string_cache_list, NULL , 0 , is_module);
116
- update_string_caches (local_string_cache_list);
117
127
118
128
return 1 ;
119
129
}
@@ -147,6 +157,112 @@ ast_node_t *reduce_expressions(ast_node_t *node, ast_node_t *parent, STRING_CACH
147
157
skip_children = true ;
148
158
break ;
149
159
}
160
+ case FUNCTION_INSTANCE:
161
+ {
162
+ // check ports
163
+ ast_node_t *connect_list = node->children [1 ]->children [1 ];
164
+ bool is_ordered_list;
165
+ if (connect_list->children [1 ]->children [0 ]) // skip first connection
166
+ {
167
+ is_ordered_list = false ; // name was specified
168
+ }
169
+ else
170
+ {
171
+ is_ordered_list = true ;
172
+ }
173
+
174
+ for (int i = 1 ; i < connect_list->num_children ; i++)
175
+ {
176
+ if ((connect_list->children [i]->children [0 ] && is_ordered_list)
177
+ || (!connect_list->children [i]->children [0 ] && !is_ordered_list))
178
+ {
179
+ error_message (PARSE_ERROR, node->line_number , node->file_number ,
180
+ " %s" , " Cannot mix port connections by name and port connections by ordered list\n " );
181
+ }
182
+ }
183
+
184
+ skip_children = true ;
185
+
186
+ break ;
187
+ }
188
+ case MODULE_ITEMS:
189
+ {
190
+ /* look in the string cache for in-line continuous assignments */
191
+ ast_node_t **local_symbol_table = local_string_cache_list->local_symbol_table ;
192
+ int num_local_symbol_table = local_string_cache_list->num_local_symbol_table ;
193
+
194
+ for (int i = 0 ; i < num_local_symbol_table; i++)
195
+ {
196
+ ast_node_t *var_declare = local_symbol_table[i];
197
+ if (var_declare->types .variable .is_wire && var_declare->children [5 ] != NULL )
198
+ {
199
+ /* in-line assignment; split into its own continuous assignment */
200
+ ast_node_t *id = ast_node_copy (var_declare->children [0 ]);
201
+ ast_node_t *val = var_declare->children [5 ];
202
+ var_declare->children [5 ] = NULL ;
203
+
204
+ ast_node_t *blocking_node = newBlocking (id, val, var_declare->line_number );
205
+ ast_node_t *assign_node = newList (ASSIGN, blocking_node);
206
+
207
+ add_child_to_node (node, assign_node);
208
+ }
209
+ }
210
+
211
+ break ;
212
+ }
213
+ case MODULE_INSTANCE:
214
+ {
215
+ /* flip hard blocks */
216
+
217
+ if (node->num_children == 1 )
218
+ {
219
+ // check ports
220
+ ast_node_t *connect_list = node->children [0 ]->children [1 ]->children [1 ];
221
+ bool is_ordered_list;
222
+ if (connect_list->children [0 ]->children [0 ])
223
+ {
224
+ is_ordered_list = false ; // name was specified
225
+ }
226
+ else
227
+ {
228
+ is_ordered_list = true ;
229
+ }
230
+
231
+ for (int i = 1 ; i < connect_list->num_children ; i++)
232
+ {
233
+ if ((connect_list->children [i]->children [0 ] && is_ordered_list)
234
+ || (!connect_list->children [i]->children [0 ] && !is_ordered_list))
235
+ {
236
+ error_message (PARSE_ERROR, node->line_number , node->file_number ,
237
+ " %s" , " Cannot mix port connections by name and port connections by ordered list\n " );
238
+ }
239
+ }
240
+
241
+ char *module_ref_name = node->children [0 ]->children [0 ]->types .identifier ;
242
+ long sc_spot = sc_lookup_string (hard_block_names, module_ref_name);
243
+
244
+ /* TODO: strcmp on "multiply", "adder" for soft logic implementation? */
245
+ if
246
+ (
247
+ sc_spot != -1
248
+ || !strcmp (module_ref_name, SINGLE_PORT_RAM_string)
249
+ || !strcmp (module_ref_name, DUAL_PORT_RAM_string)
250
+ )
251
+ {
252
+ ast_node_t *hb_node = look_for_matching_hard_block (node->children [0 ], module_ref_name);
253
+ if (hb_node != node->children [0 ])
254
+ {
255
+ free_whole_tree (node);
256
+ node = hb_node;
257
+
258
+ child_skip_list = (short *)vtr::realloc (child_skip_list, sizeof (short )*node->num_children );
259
+ child_skip_list[1 ] = false ;
260
+ break ;
261
+ }
262
+ }
263
+ }
264
+ break ;
265
+ }
150
266
case VAR_DECLARE:
151
267
{
152
268
if (node->types .variable .is_parameter || node->types .variable .is_localparam )
@@ -330,9 +446,8 @@ ast_node_t *reduce_expressions(ast_node_t *node, ast_node_t *parent, STRING_CACH
330
446
}
331
447
332
448
assignment_size = 0 ;
449
+ skip_children = true ;
333
450
}
334
-
335
- skip_children = true ;
336
451
break ;
337
452
}
338
453
case BINARY_OPERATION:
@@ -491,9 +606,6 @@ ast_node_t *reduce_expressions(ast_node_t *node, ast_node_t *parent, STRING_CACH
491
606
case RANGE_REF:
492
607
case ARRAY_REF:
493
608
break ;
494
- case MODULE_INSTANCE:
495
- // flip hard blocks
496
- break ;
497
609
case ALWAYS: // fallthrough
498
610
case INITIALS:
499
611
{
@@ -556,8 +668,6 @@ ast_node_t *reduce_expressions(ast_node_t *node, ast_node_t *parent, STRING_CACH
556
668
/* this should be encountered once generate constructs are resolved, so we don't have
557
669
stray instances that never get instantiated */
558
670
559
- /* TODO: handle hard block instantiation here! */
560
-
561
671
if (node->num_children == 2 )
562
672
{
563
673
char *instance_name_prefix = local_string_cache_list->instance_name_prefix ;
@@ -1116,6 +1226,144 @@ void verify_genvars(ast_node_t *node, STRING_CACHE_LIST *local_string_cache_list
1116
1226
}
1117
1227
}
1118
1228
1229
+ ast_node_t *look_for_matching_hard_block (ast_node_t *node, char *hard_block_name)
1230
+ {
1231
+ t_model *hb_model = find_hard_block (hard_block_name);
1232
+ bool is_hb = true ;
1233
+
1234
+ if (!hb_model)
1235
+ {
1236
+ /* check for soft logic RAM */
1237
+ return look_for_matching_soft_logic (node, hard_block_name);
1238
+ }
1239
+ else
1240
+ {
1241
+
1242
+ t_model_ports *hb_input_ports = hb_model->inputs ;
1243
+ t_model_ports *hb_output_ports = hb_model->outputs ;
1244
+
1245
+ int num_hb_inputs = 0 ;
1246
+ int num_hb_outputs = 0 ;
1247
+
1248
+ while (hb_input_ports != NULL )
1249
+ {
1250
+ num_hb_inputs++;
1251
+ hb_input_ports = hb_input_ports->next ;
1252
+ }
1253
+
1254
+ while (hb_output_ports != NULL )
1255
+ {
1256
+ num_hb_outputs++;
1257
+ hb_output_ports = hb_output_ports->next ;
1258
+ }
1259
+
1260
+ ast_node_t *connect_list = node->children [1 ]->children [1 ];
1261
+
1262
+ /* first check if the number of ports match up */
1263
+ if (connect_list->num_children != (num_hb_inputs + num_hb_outputs))
1264
+ {
1265
+ is_hb = false ;
1266
+ }
1267
+
1268
+ if (is_hb && connect_list->children [0 ]->children [0 ] != NULL )
1269
+ {
1270
+ /* if all port names match up, this is a hard block */
1271
+ for (int i = 0 ; i < connect_list->num_children && is_hb; i++)
1272
+ {
1273
+ oassert (connect_list->children [i]->children [0 ]);
1274
+ char *id = connect_list->children [i]->children [0 ]->types .identifier ;
1275
+ hb_input_ports = hb_model->inputs ;
1276
+ hb_output_ports = hb_model->outputs ;
1277
+
1278
+ while ((hb_input_ports != NULL ) && (strcmp (hb_input_ports->name , id) != 0 ))
1279
+ {
1280
+ hb_input_ports = hb_input_ports->next ;
1281
+ }
1282
+
1283
+ if (hb_input_ports == NULL )
1284
+ {
1285
+ while ((hb_output_ports != NULL ) && (strcmp (hb_output_ports->name , id) != 0 ))
1286
+ {
1287
+ hb_output_ports = hb_output_ports->next ;
1288
+ }
1289
+ }
1290
+ else
1291
+ {
1292
+ continue ; // matching input was found
1293
+ }
1294
+
1295
+ if (hb_output_ports == NULL )
1296
+ {
1297
+ is_hb = false ; // ports don't match up
1298
+ }
1299
+ else
1300
+ {
1301
+ continue ; // matching output was found
1302
+ }
1303
+ }
1304
+ }
1305
+ else if (is_hb)
1306
+ {
1307
+ /* number of ports match, so default to a hard block */
1308
+ warning_message (NETLIST_ERROR, connect_list->line_number , connect_list->file_number ,
1309
+ " Converting this instance to a hard block (%s) - unnamed port connections will be matched according to hard block specification\n " , hard_block_name);
1310
+
1311
+ hb_input_ports = hb_model->inputs ;
1312
+ hb_output_ports = hb_model->outputs ;
1313
+ int i = 0 ;
1314
+
1315
+ while (hb_output_ports)
1316
+ {
1317
+ oassert (connect_list->children [i] && !connect_list->children [i]->children [0 ]);
1318
+ connect_list->children [i]->children [0 ] = newSymbolNode (vtr::strdup (hb_output_ports->name ), connect_list->line_number );
1319
+ hb_output_ports = hb_output_ports->next ;
1320
+ i++;
1321
+ }
1322
+
1323
+ while (hb_input_ports)
1324
+ {
1325
+ oassert (connect_list->children [i] && !connect_list->children [i]->children [0 ]);
1326
+ connect_list->children [i]->children [0 ] = newSymbolNode (vtr::strdup (hb_input_ports->name ), connect_list->line_number );
1327
+ hb_input_ports = hb_input_ports->next ;
1328
+ i++;
1329
+ }
1330
+ }
1331
+ }
1332
+
1333
+ if (is_hb)
1334
+ {
1335
+ ast_node_t *instance = ast_node_deep_copy (node->children [1 ]);
1336
+ char *new_hard_block_name = vtr::strdup (hard_block_name);
1337
+
1338
+ return newHardBlockInstance (new_hard_block_name, instance, instance->line_number );
1339
+ }
1340
+ else
1341
+ {
1342
+ return look_for_matching_soft_logic (node, hard_block_name);
1343
+ }
1344
+ }
1345
+
1346
+ ast_node_t *look_for_matching_soft_logic (ast_node_t *node, char *hard_block_name)
1347
+ {
1348
+ bool is_hb = true ;
1349
+
1350
+ if (!is_ast_sp_ram (node) && !is_ast_dp_ram (node) && !is_ast_adder (node) && !is_ast_multiplier (node))
1351
+ {
1352
+ is_hb = false ;
1353
+ }
1354
+
1355
+ if (is_hb)
1356
+ {
1357
+ ast_node_t *instance = ast_node_deep_copy (node->children [1 ]);
1358
+ char *new_hard_block_name = vtr::strdup (hard_block_name);
1359
+ return newHardBlockInstance (new_hard_block_name, instance, instance->line_number );
1360
+ }
1361
+ else
1362
+ {
1363
+ return node;
1364
+ }
1365
+ }
1366
+
1119
1367
// /*---------------------------------------------------------------------------
1120
1368
// * (function: reduce_assignment_expression)
1121
1369
// * reduce the number nodes which can be calculated to optimize the AST
0 commit comments