Skip to content

Commit a922bdf

Browse files
committed
odin - fixed hard block instantiation bug
1 parent ca194a0 commit a922bdf

File tree

10 files changed

+401
-73
lines changed

10 files changed

+401
-73
lines changed

ODIN_II/SRC/adders.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,3 +1500,34 @@ void instantiate_add_w_carry_block(int *width, nnode_t *node, short mark, netlis
15001500
connect_output_pin_to_node(width, i, 0, node, current_adder, subtraction);
15011501
}
15021502
}
1503+
1504+
bool is_ast_adder(ast_node_t *node)
1505+
{
1506+
bool is_adder;
1507+
ast_node_t *instance = node->children[1];
1508+
is_adder = (!strcmp(node->children[0]->types.identifier, "adder"))
1509+
&& (instance->children[1]->num_children == 5);
1510+
1511+
ast_node_t *connect_list = instance->children[1];
1512+
if (is_adder && connect_list->children[0]->children[0])
1513+
{
1514+
/* port connections were passed by name; verify port names */
1515+
for (int i = 0; i < connect_list->num_children && is_adder; i++)
1516+
{
1517+
char *id = connect_list->children[i]->children[0]->types.identifier;
1518+
1519+
if ((strcmp(id, "a") != 0) &&
1520+
(strcmp(id, "b") != 0) &&
1521+
(strcmp(id, "cin") != 0) &&
1522+
(strcmp(id, "cout") != 0) &&
1523+
(strcmp(id, "sumout") != 0)
1524+
)
1525+
{
1526+
is_adder = false;
1527+
break;
1528+
}
1529+
}
1530+
}
1531+
1532+
return is_adder;
1533+
}

ODIN_II/SRC/ast_elaborate.cpp

Lines changed: 256 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,13 @@ OTHER DEALINGS IN THE SOFTWARE.
2727
#include <stdlib.h>
2828
#include <math.h>
2929
#include "odin_types.h"
30+
#include "adders.h"
3031
#include "ast_util.h"
3132
#include "ast_elaborate.h"
3233
#include "ast_loop_unroll.h"
34+
#include "hard_blocks.h"
35+
#include "memories.h"
36+
#include "multipliers.h"
3337
#include "parse_making_ast.h"
3438
#include "verilog_bison.h"
3539
#include "netlist_create_from_ast.h"
@@ -101,19 +105,25 @@ OTHER DEALINGS IN THE SOFTWARE.
101105
// bool check_mult_bracket(std::vector<int> list);
102106

103107
void update_string_caches(STRING_CACHE_LIST *local_string_cache_list);
108+
104109
void convert_2D_to_1D_array(ast_node_t **var_declare, STRING_CACHE_LIST *local_string_cache_list);
105110
void convert_2D_to_1D_array_ref(ast_node_t **node, STRING_CACHE_LIST *local_string_cache_list);
106111
char *make_chunk_size_name(char *instance_name_prefix, char *array_name);
107112
ast_node_t *get_chunk_size_node(char *instance_name_prefix, char *array_name, STRING_CACHE_LIST *local_string_cache_list);
113+
108114
bool verify_terminal(ast_node_t *top, ast_node_t *iterator);
109115
void verify_genvars(ast_node_t *node, STRING_CACHE_LIST *local_string_cache_list, char ***other_genvars, int num_genvars);
110116

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+
111121
int simplify_ast_module(ast_node_t **ast_module, STRING_CACHE_LIST *local_string_cache_list)
112122
{
113123
/* resolve constant expressions */
124+
update_string_caches(local_string_cache_list);
114125
bool is_module = (*ast_module)->type == MODULE ? true : false;
115126
*ast_module = reduce_expressions(*ast_module, NULL, local_string_cache_list, NULL, 0, is_module);
116-
update_string_caches(local_string_cache_list);
117127

118128
return 1;
119129
}
@@ -147,6 +157,112 @@ ast_node_t *reduce_expressions(ast_node_t *node, ast_node_t *parent, STRING_CACH
147157
skip_children = true;
148158
break;
149159
}
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+
}
150266
case VAR_DECLARE:
151267
{
152268
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
330446
}
331447

332448
assignment_size = 0;
449+
skip_children = true;
333450
}
334-
335-
skip_children = true;
336451
break;
337452
}
338453
case BINARY_OPERATION:
@@ -491,9 +606,6 @@ ast_node_t *reduce_expressions(ast_node_t *node, ast_node_t *parent, STRING_CACH
491606
case RANGE_REF:
492607
case ARRAY_REF:
493608
break;
494-
case MODULE_INSTANCE:
495-
// flip hard blocks
496-
break;
497609
case ALWAYS: // fallthrough
498610
case INITIALS:
499611
{
@@ -556,8 +668,6 @@ ast_node_t *reduce_expressions(ast_node_t *node, ast_node_t *parent, STRING_CACH
556668
/* this should be encountered once generate constructs are resolved, so we don't have
557669
stray instances that never get instantiated */
558670

559-
/* TODO: handle hard block instantiation here! */
560-
561671
if (node->num_children == 2)
562672
{
563673
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
11161226
}
11171227
}
11181228

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+
11191367
// /*---------------------------------------------------------------------------
11201368
// * (function: reduce_assignment_expression)
11211369
// * reduce the number nodes which can be calculated to optimize the AST

ODIN_II/SRC/include/adders.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,6 @@ void free_op_nodes(nnode_t *node);
7777
int match_pins(nnode_t *node, nnode_t *next_node);
7878

7979
void instantiate_add_w_carry_block(int *width, nnode_t *node, short mark, netlist_t *netlist, short subtraction);
80-
80+
bool is_ast_adder(ast_node_t *node);
8181

8282
#endif // ADDERS_H

ODIN_II/SRC/include/memories.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,11 @@ void free_sp_ram_signals(sp_ram_signals *signalsvar);
8282
dp_ram_signals *get_dp_ram_signals(nnode_t *node);
8383
void free_dp_ram_signals(dp_ram_signals *signalsvar);
8484

85-
char is_sp_ram(nnode_t *node);
86-
char is_dp_ram(nnode_t *node);
85+
bool is_sp_ram(nnode_t *node);
86+
bool is_dp_ram(nnode_t *node);
8787

88-
char is_ast_sp_ram(ast_node_t *node);
89-
char is_ast_dp_ram(ast_node_t *node);
88+
bool is_ast_sp_ram(ast_node_t *node);
89+
bool is_ast_dp_ram(ast_node_t *node);
9090

9191
void init_memory_distribution();
9292
void check_memories_and_report_distribution();

ODIN_II/SRC/include/multipliers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ extern void add_the_blackbox_for_mults(FILE *out);
4747
extern void define_mult_function(nnode_t *node, FILE *out);
4848
extern void split_multiplier(nnode_t *node, int a0, int b0, int a1, int b1, netlist_t *netlist);
4949
extern void iterate_multipliers(netlist_t *netlist);
50+
extern bool is_ast_multiplier(ast_node_t *node);
5051
extern void clean_multipliers();
5152
extern void free_multipliers();
5253

0 commit comments

Comments
 (0)