diff --git a/ODIN_II/SRC/ast_elaborate.cpp b/ODIN_II/SRC/ast_elaborate.cpp index c29032c7c4b..e98c2106f8d 100644 --- a/ODIN_II/SRC/ast_elaborate.cpp +++ b/ODIN_II/SRC/ast_elaborate.cpp @@ -682,6 +682,8 @@ ast_node_t *build_hierarchy(ast_node_t *node, ast_node_t * parent, int index, sc fold_expressions = true; break; } + case TASK: //fallthrough + case STATEMENT: //fallthough case FUNCTION: // fallthrough case INITIAL: // fallthrough case ALWAYS: @@ -863,6 +865,59 @@ ast_node_t *build_hierarchy(ast_node_t *node, ast_node_t * parent, int index, sc vtr::free(temp_instance_name); } + for (i = 0; i < node->types.task.size_task_instantiations; i++) + { + + /* make the stringed up module instance name - instance name is + * MODULE_INSTANCE->MODULE_NAMED_INSTANCE(child[1])->IDENTIFIER(child[0]). + * module name is MODULE_INSTANCE->IDENTIFIER(child[0]) + */ + ast_node_t *temp_instance = node->types.task.task_instantiations_instance[i]; + char *instance_name_prefix = local_ref->instance_name_prefix; + + char *temp_instance_name = make_full_ref_name(instance_name_prefix, + temp_instance->children[0]->types.identifier, + temp_instance->children[1]->children[0]->types.identifier, + NULL, -1); + + long sc_spot; + /* lookup the name of the task associated with this instantiated point */ + if ((sc_spot = sc_lookup_string(module_names_to_idx, temp_instance->children[0]->types.identifier)) == -1) + { + error_message(NETLIST_ERROR, node->line_number, node->file_number, + "Can't find task name %s\n", temp_instance->children[0]->types.identifier); + } + + /* make a unique copy of this task */ + ast_node_t *instance = ast_node_deep_copy((ast_node_t *)module_names_to_idx->data[sc_spot]); + + long sc_spot_2 = sc_add_string(module_names_to_idx, temp_instance_name); + oassert(sc_spot_2 > -1 && module_names_to_idx->data[sc_spot_2] == NULL); + module_names_to_idx->data[sc_spot_2] = (void *)instance; + + ast_modules = (ast_node_t **)vtr::realloc(ast_modules, sizeof(ast_node_t*)*(sc_spot_2 + 1)); + ast_modules[sc_spot_2] = instance; + + /* create the string cache list for the instantiated module */ + sc_hierarchy *original_sc_hierarchy = ((ast_node_t *)module_names_to_idx->data[sc_spot])->types.hierarchy; + sc_hierarchy *task_sc_hierarchy = copy_sc_hierarchy(original_sc_hierarchy); + task_sc_hierarchy->parent = local_ref; + task_sc_hierarchy->instance_name_prefix = vtr::strdup(temp_instance_name); + task_sc_hierarchy->scope_id = vtr::strdup(temp_instance->children[1]->children[0]->types.identifier); + + /* update parent string cache list */ + int num_task_children = local_ref->num_task_children; + local_ref->task_children = (sc_hierarchy **)vtr::realloc(local_ref->task_children, sizeof(sc_hierarchy *)*(num_task_children + 1)); + local_ref->task_children[i] = task_sc_hierarchy; + local_ref->num_task_children++; + + /* elaboration */ + instance = build_hierarchy(instance, NULL, -1, task_sc_hierarchy, false, true, data); + + /* clean up */ + vtr::free(temp_instance_name); + } + break; } case MODULE_INSTANCE: @@ -1098,6 +1153,8 @@ ast_node_t *build_hierarchy(ast_node_t *node, ast_node_t * parent, int index, sc break; } + case STATEMENT: //fallthrough + case TASK: //fallthrough case FUNCTION: // fallthrough case INITIAL: // fallthrough case ALWAYS: @@ -1192,6 +1249,44 @@ ast_node_t *finalize_ast(ast_node_t *node, ast_node_t *parent, sc_hierarchy *loc break; } + case TASK: + { + if(parent != NULL) + { + skip_children = true; + } + break; + } + case TASK_INSTANCE: + { + // check ports + ast_node_t *connect_list = node->children[1]->children[1]; + bool is_ordered_list; + if (connect_list->children[1]->children[0]) // skip first connection + { + is_ordered_list = false; // name was specified + } + else + { + is_ordered_list = true; + } + + for (int i = 1; i < connect_list->num_children; i++) + { + if ((connect_list->children[i] + && connect_list->children[i]->children) + && (( connect_list->children[i]->children[0] && is_ordered_list) + || (!connect_list->children[i]->children[0] && !is_ordered_list))) + { + error_message(PARSE_ERROR, node->line_number, node->file_number, + "%s", "Cannot mix port connections by name and port connections by ordered list\n"); + } + } + + skip_children = true; + + break; + } case MODULE_ITEMS: { /* look in the string cache for in-line continuous assignments */ @@ -1299,6 +1394,7 @@ ast_node_t *finalize_ast(ast_node_t *node, ast_node_t *parent, sc_hierarchy *loc node = unroll_for_loop(node, parent, &num_unrolled, local_ref, is_generate_region); break; } + case STATEMENT: //fallthrough case ALWAYS: // fallthrough case INITIAL: { @@ -1547,6 +1643,40 @@ ast_node_t *finalize_ast(ast_node_t *node, ast_node_t *parent, sc_hierarchy *loc vtr::free(temp_instance_name); } + for (i = 0; i < node->types.task.size_task_instantiations; i++) + { + + /* make the stringed up module instance name - instance name is + * MODULE_INSTANCE->MODULE_NAMED_INSTANCE(child[1])->IDENTIFIER(child[0]). + * module name is MODULE_INSTANCE->IDENTIFIER(child[0]) + */ + ast_node_t *temp_instance = node->types.task.task_instantiations_instance[i]; + char *instance_name_prefix = local_ref->instance_name_prefix; + + char *temp_instance_name = make_full_ref_name(instance_name_prefix, + temp_instance->children[0]->types.identifier, + temp_instance->children[1]->children[0]->types.identifier, + NULL, -1); + + /* lookup the name of the task associated with this instantiated point */ + long sc_spot = sc_lookup_string(module_names_to_idx, temp_instance->children[0]->types.identifier); + oassert(sc_spot > -1 && module_names_to_idx->data[sc_spot] != NULL); + ast_node_t *instance = (ast_node_t *)module_names_to_idx->data[sc_spot]; + + sc_hierarchy *task_sc_hierarchy = local_ref->task_children[i]; + + /* update the parameter table for the instantiated module */ + STRING_CACHE *instance_param_table_sc = task_sc_hierarchy->local_param_table_sc; + update_instance_parameter_table(temp_instance, instance_param_table_sc); + + /* elaboration */ + update_string_caches(task_sc_hierarchy); + instance = finalize_ast(instance, NULL, task_sc_hierarchy, false, true); + + /* clean up */ + vtr::free(temp_instance_name); + } + break; } case MODULE_INSTANCE: @@ -1777,6 +1907,7 @@ ast_node_t *finalize_ast(ast_node_t *node, ast_node_t *parent, sc_hierarchy *loc if (node->num_children == 3) convert_2D_to_1D_array_ref(&node, local_ref); break; } + case STATEMENT: //fallthrough case ALWAYS: // fallthrough case INITIAL: { @@ -1834,6 +1965,11 @@ ast_node_t *reduce_expressions(ast_node_t *node, sc_hierarchy *local_ref, long * skip_children = true; break; } + case TASK: + { + skip_children = true; + break; + } case MODULE_INSTANCE: { skip_children = true; diff --git a/ODIN_II/SRC/ast_util.cpp b/ODIN_II/SRC/ast_util.cpp index 20d7eaff5fd..438d1920f8a 100644 --- a/ODIN_II/SRC/ast_util.cpp +++ b/ODIN_II/SRC/ast_util.cpp @@ -659,7 +659,7 @@ char **get_name_of_pins_number(ast_node_t *var_node, int /*start*/, int width) return_string = (char**)vtr::malloc(sizeof(char*)*width); int i; - for (i = 0; i < width; i++)// + for (i = 0; i < width; i++) { return_string[i] = get_name_of_pin_number(var_node, i); } @@ -680,6 +680,7 @@ char *get_name_of_pin_number(ast_node_t *var_node, int bit) case BitSpace::_1: return_string = vtr::strdup(ONE_VCC_CNS); break; case BitSpace::_0: return_string = vtr::strdup(ZERO_GND_ZERO); break; case BitSpace::_x: return_string = vtr::strdup(ZERO_GND_ZERO); break; + case BitSpace::_z: return_string = vtr::strdup(ZERO_PAD_ZERO); break; default: error_message(NETLIST_ERROR, var_node->line_number, var_node->file_number, "Unrecognised character %c in binary string \"%s\"!\n", c, var_node->types.vnumber->to_bit_string().c_str()); break; diff --git a/ODIN_II/SRC/enum_str.cpp b/ODIN_II/SRC/enum_str.cpp index 4aafaecbe94..11719b0be35 100644 --- a/ODIN_II/SRC/enum_str.cpp +++ b/ODIN_II/SRC/enum_str.cpp @@ -124,6 +124,8 @@ const char *ids_STR []= "FUNCTION", /* OTHER FUNCTION ITEMS */ "FUNCTION_ITEMS", + "TASK", + "TASK_ITEMS", /* primitives */ "GATE", "GATE_INSTANCE", @@ -140,12 +142,16 @@ const char *ids_STR []= /* Function instances*/ "FUNCTION_NAMED_INSTANCE", "FUNCTION_INSTANCE", + + "TASK_NAMED_INSTANCE", + "TASK_INSTANCE", /* Specify Items */ "SPECIFY_ITEMS", "SPECIFY_PARAMETER", "SPECIFY_PAL_CONNECTION_STATEMENT", "SPECIFY_PAL_CONNECT_LIST", /* statements */ + "STATEMENT", "BLOCK", "NON_BLOCKING_STATEMENT", "BLOCKING_STATEMENT", diff --git a/ODIN_II/SRC/hierarchy_util.cpp b/ODIN_II/SRC/hierarchy_util.cpp index fba467d8962..05c11654fec 100644 --- a/ODIN_II/SRC/hierarchy_util.cpp +++ b/ODIN_II/SRC/hierarchy_util.cpp @@ -108,6 +108,12 @@ void free_sc_hierarchy(sc_hierarchy *to_free) } to_free->function_children = (sc_hierarchy **)vtr::free(to_free->function_children); + for (i = 0; i < to_free->num_task_children; i++) + { + free_sc_hierarchy(to_free->task_children[i]); + } + to_free->task_children = (sc_hierarchy **)vtr::free(to_free->task_children); + for (i = 0; i < to_free->num_block_children; i++) { free_sc_hierarchy(to_free->block_children[i]); @@ -138,6 +144,7 @@ void free_sc_hierarchy(sc_hierarchy *to_free) to_free->num_module_children = 0; to_free->num_function_children = 0; + to_free->num_task_children = 0; to_free->num_unnamed_genblks = 0; vtr::free(to_free); @@ -195,6 +202,14 @@ ast_node_t *resolve_hierarchical_name_reference(sc_hierarchy *local_ref, char *i found = true; } } + for (int i = 0; !found && i < this_ref->num_task_children; i++) + { + if (this_ref->task_children[i]->scope_id == scope_id) + { + this_ref = this_ref->task_children[i]; + found = true; + } + } for (int i = 0; !found && i < this_ref->num_block_children; i++) { if (this_ref->block_children[i]->scope_id == scope_id) @@ -285,6 +300,14 @@ ast_node_t *resolve_hierarchical_name_reference_by_path_search(sc_hierarchy *loc } } + for (int i = 0; !var_declare && i < local_ref->num_task_children; i++) + { + if (local_ref->task_children[i]->scope_id == scope_id) + { + var_declare = resolve_hierarchical_name_reference_by_path_search(local_ref->task_children[i], identifier); + } + } + for (int i = 0; !var_declare && i < local_ref->num_block_children; i++) { if (local_ref->block_children[i]->scope_id == scope_id) diff --git a/ODIN_II/SRC/include/odin_types.h b/ODIN_II/SRC/include/odin_types.h index 197bc46a185..06f9ee332d0 100644 --- a/ODIN_II/SRC/include/odin_types.h +++ b/ODIN_II/SRC/include/odin_types.h @@ -272,6 +272,8 @@ enum ids FUNCTION, /* OTHER FUNCTION ITEMS */ FUNCTION_ITEMS, + TASK, + TASK_ITEMS, /* primitives */ GATE, GATE_INSTANCE, @@ -288,12 +290,16 @@ enum ids /* Function instances*/ FUNCTION_NAMED_INSTANCE, FUNCTION_INSTANCE, + + TASK_NAMED_INSTANCE, + TASK_INSTANCE, /* Specify Items */ SPECIFY_ITEMS, SPECIFY_PARAMETER, SPECIFY_PAL_CONNECTION_STATEMENT, SPECIFY_PAL_CONNECT_LIST, /* statements */ + STATEMENT, BLOCK, NON_BLOCKING_STATEMENT, BLOCKING_STATEMENT, @@ -378,6 +384,15 @@ struct typ STRING_CACHE *parameter_list; } function; struct + { + short is_instantiated; + ast_node_t **task_instantiations_instance; + int size_task_instantiations; + int index; + STRING_CACHE *parameter_list; + sc_hierarchy *string_cache_list; + }task; + struct { int num_bit_strings; char **bit_strings; diff --git a/ODIN_II/SRC/include/parse_making_ast.h b/ODIN_II/SRC/include/parse_making_ast.h index c42999f5588..e62da046914 100644 --- a/ODIN_II/SRC/include/parse_making_ast.h +++ b/ODIN_II/SRC/include/parse_making_ast.h @@ -52,6 +52,7 @@ ast_node_t *newIf(ast_node_t *compare_expression, ast_node_t *true_expression, a ast_node_t *newIfQuestion(ast_node_t *compare_expression, ast_node_t *true_expression, ast_node_t *false_expression, int line_number); ast_node_t *newCase(ast_node_t *compare_expression, ast_node_t *case_list, int line_number); ast_node_t *newAlways(ast_node_t *delay_control, ast_node_t *statements, int line_number); +ast_node_t *newStatement(ast_node_t *statement, int line_number); ast_node_t *newFor(ast_node_t *initial, ast_node_t *compare_expression, ast_node_t *terminal, ast_node_t *statement, int line_number); ast_node_t *newWhile(ast_node_t *compare_expression, ast_node_t *statement, int line_number); @@ -59,6 +60,8 @@ ast_node_t *newWhile(ast_node_t *compare_expression, ast_node_t *statement, int ast_node_t *newModuleConnection(char* id, ast_node_t *expression, int line_number); ast_node_t *newModuleNamedInstance(char* unique_name, ast_node_t *module_connect_list, ast_node_t *module_parameter_list, int line_number); ast_node_t *newFunctionNamedInstance(ast_node_t *module_connect_list, ast_node_t *module_parameter_list, int line_number); +ast_node_t *newTaskInstance(char *task_name, ast_node_t *task_named_instace, ast_node_t *task_parameter_list, int line_number); +ast_node_t *newTaskNamedInstance(ast_node_t *module_connect_list, int line_number); ast_node_t *newModuleInstance(char* module_ref_name, ast_node_t *module_named_instance, int line_number); ast_node_t *newFunctionInstance(char* function_ref_name, ast_node_t *function_named_instance, int line_number); ast_node_t *newHardBlockInstance(char* module_ref_name, ast_node_t *module_named_instance, int line_number); @@ -82,9 +85,11 @@ ast_node_t *newIntegerTypeVarDeclare(char* symbol, ast_node_t *expression1, ast_ /* HIGH LEVEL ITEMS */ ast_node_t *newModule(char* module_name, ast_node_t *list_of_parameters, ast_node_t *list_of_ports, ast_node_t *list_of_module_items, int line_number); -ast_node_t *newFunction(ast_node_t *list_of_ports, ast_node_t *list_of_module_items, int line_number); +ast_node_t *newFunction(ast_node_t *function_return, ast_node_t *list_of_ports, ast_node_t *list_of_module_items, int line_number, bool automatic); +ast_node_t *newTask(char *task_name, ast_node_t *list_of_ports, ast_node_t *list_of_task_items, int line_number, bool automatic); void next_module(); void next_function(); +void next_task(); ast_node_t *newDefparam(ids id, ast_node_t *val, int line_number); void next_parsed_verilog_file(ast_node_t *file_items_list); diff --git a/ODIN_II/SRC/netlist_create_from_ast.cpp b/ODIN_II/SRC/netlist_create_from_ast.cpp index 0a96dbe872f..a38b99af440 100644 --- a/ODIN_II/SRC/netlist_create_from_ast.cpp +++ b/ODIN_II/SRC/netlist_create_from_ast.cpp @@ -94,6 +94,7 @@ nnet_t* define_nodes_and_nets_with_driver(ast_node_t* var_declare, char *instanc void connect_hard_block_and_alias(ast_node_t* hb_instance, char *instance_name_prefix, int outport_size, sc_hierarchy *local_ref); void connect_module_instantiation_and_alias(short PASS, ast_node_t* module_instance, char *instance_name_prefix, sc_hierarchy *local_ref); signal_list_t * connect_function_instantiation_and_alias(short PASS, ast_node_t* module_instance, char *instance_name_prefix, sc_hierarchy *local_ref); +signal_list_t *connect_task_instantiation_and_alias(short PASS, ast_node_t* task_instance, char *instance_name_prefix, sc_hierarchy *local_ref); int check_for_initial_reg_value(ast_node_t* var_declare, long *value); void define_latchs_initial_value_inside_initial_statement(ast_node_t *initial_node, sc_hierarchy *local_ref); @@ -156,12 +157,18 @@ void create_netlist() local_ref->local_param_table_sc = ((ast_node_t *)module_names_to_idx->data[i])->types.module.parameter_list; local_ref->local_defparam_table_sc = ((ast_node_t *)module_names_to_idx->data[i])->types.module.defparam_list; } - else + else if(((ast_node_t *)module_names_to_idx->data[i])->type == FUNCTION) { oassert(((ast_node_t *)module_names_to_idx->data[i])->type == FUNCTION); ((ast_node_t *)module_names_to_idx->data[i])->types.hierarchy = local_ref; // local_ref->local_param_table_sc = ((ast_node_t *)module_names_to_idx->data[i])->types.function.parameter_list; } + else + { + oassert(((ast_node_t *)module_names_to_idx->data[i])->type == TASK); + ((ast_node_t *)module_names_to_idx->data[i])->types.hierarchy = local_ref; + // local_ref->local_param_table_sc = ((ast_node_t *)module_names_to_idx->data[i])->types.task.parameter_list; + } } /* we will find the top module */ @@ -321,7 +328,8 @@ void convert_ast_to_netlist_recursing_via_modules(ast_node_t** current_module, c /* BASE CASE is when there are no other instantiations of modules in this module */ if ((*current_module)->types.module.size_module_instantiations == 0 && - (*current_module)->types.function.size_function_instantiations == 0) + (*current_module)->types.function.size_function_instantiations == 0 && + (*current_module)->types.task.size_task_instantiations == 0) { list = netlist_expand_ast_of_module(current_module, instance_name, local_ref); } @@ -381,7 +389,7 @@ void convert_ast_to_netlist_recursing_via_modules(ast_node_t** current_module, c "Can't find instance name %s\n", temp_instance_name); } - sc_hierarchy *function_sc_hierarchy = local_ref->function_children[+k]; + sc_hierarchy *function_sc_hierarchy = local_ref->function_children[k]; oassert(!strcmp(function_sc_hierarchy->instance_name_prefix, temp_instance_name)); /* recursive call point */ @@ -391,6 +399,36 @@ void convert_ast_to_netlist_recursing_via_modules(ast_node_t** current_module, c vtr::free(temp_instance_name); } + for(k = 0; k < (*current_module)->types.task.size_task_instantiations; k++) + { + /* make the stringed up task instance name - instance name is + * MODULE_INSTANCE->MODULE_NAMED_INSTANCE(child[1])->IDENTIFIER(child[0]). + * module name is MODULE_INSTANCE->IDENTIFIER(child[0]) + */ + + char *temp_instance_name = make_full_ref_name(instance_name, + (*current_module)->types.task.task_instantiations_instance[k]->children[0]->types.identifier, + (*current_module)->types.task.task_instantiations_instance[k]->children[1]->children[0]->types.identifier, + NULL, -1); + + long sc_spot; + /* lookup the name of the module associated with this instantiated point */ + if ((sc_spot = sc_lookup_string(module_names_to_idx, temp_instance_name)) == -1) + { + error_message(NETLIST_ERROR, (*current_module)->line_number, (*current_module)->file_number, + "Can't find instance name %s\n", temp_instance_name); + } + + sc_hierarchy *task_sc_hierarchy = local_ref->task_children[k]; + oassert(!strcmp(task_sc_hierarchy->instance_name_prefix, temp_instance_name)); + + /* recursive call point */ + convert_ast_to_netlist_recursing_via_modules(((ast_node_t**)&module_names_to_idx->data[sc_spot]), temp_instance_name, task_sc_hierarchy, level+1); + + /* clean up */ + vtr::free(temp_instance_name); + } + /* once we've done everyone lower, we can do this module */ list = netlist_expand_ast_of_module(current_module, instance_name, local_ref); } @@ -448,6 +486,13 @@ signal_list_t *netlist_expand_ast_of_module(ast_node_t** node_ref, char *instanc child_skip_list[0] = true; /* skip the identifier */ child_skip_list[1] = true; /* skip portlist ... we'll use where they're defined */ break; + + case TASK: + oassert(child_skip_list); + /* set the skip list */ + child_skip_list[0] = true; /* skip the identifier */ + child_skip_list[1] = true; /* skip portlist ... we'll use where they're defined */ + break; case MODULE_ITEMS: /* items include: wire, reg, input, outputs, assign, gate, module_instance, always */ @@ -494,6 +539,10 @@ signal_list_t *netlist_expand_ast_of_module(ast_node_t** node_ref, char *instanc { child_skip_list[i] = true; } + else if(node->children[i]->type == TASK) + { + child_skip_list[i] = true; + } } } @@ -535,7 +584,6 @@ signal_list_t *netlist_expand_ast_of_module(ast_node_t** node_ref, char *instanc oassert(child_skip_list); for (i = 0; i < node->num_children; i++) { - //printf(" node->children[i]->type %ld\n",node->children[i]->type); if (node->children[i]->type == VAR_DECLARE_LIST) { /* IF - The port lists of this module are handled else where */ @@ -544,6 +592,37 @@ signal_list_t *netlist_expand_ast_of_module(ast_node_t** node_ref, char *instanc } } break; + case TASK_ITEMS: + /* items include: wire, reg, input, outputs, assign, gate, always */ + + local_clock_found = false; + + /* create all the driven nets based on the "reg" registers */ + create_all_driver_nets_in_this_scope(instance_name_prefix, local_ref); + + /* process elements in the list */ + if (node->num_children > 0) + { + oassert(child_skip_list); + for (i = 0; i < node->num_children; i++) + { + if (node->children[i]->type == VAR_DECLARE_LIST) + { + /* IF - The port lists of this task are handled else where */ + child_skip_list[i] = true; + } + else if (node->children[i]->type == FUNCTION) + { + child_skip_list[i] = true; + } + else if(node->children[i]->type == TASK) + { + child_skip_list[i] = true; + } + } + } + break; + case INITIAL: /* define initial value of latchs */ //define_latchs_initial_value_inside_initial_statement(node->children[0], instance_name_prefix); @@ -552,6 +631,10 @@ signal_list_t *netlist_expand_ast_of_module(ast_node_t** node_ref, char *instanc case FUNCTION_INSTANCE: return_sig_list = connect_function_instantiation_and_alias(INSTANTIATE_DRIVERS, node, instance_name_prefix, local_ref); skip_children = true; + break; + case TASK_INSTANCE: + return_sig_list = connect_task_instantiation_and_alias(INSTANTIATE_DRIVERS, node, instance_name_prefix, local_ref); + skip_children = true; break; case GATE: /* create gate instances */ @@ -670,6 +753,12 @@ signal_list_t *netlist_expand_ast_of_module(ast_node_t** node_ref, char *instanc free_signal_list(temp_list); // list is unused; discard break; } + case TASK_INSTANCE: + { + signal_list_t *temp_list = connect_task_instantiation_and_alias(ALIAS_INPUTS, node, instance_name_prefix, local_ref); + free_signal_list(temp_list); // list is unused; discard + break; + } case ASSIGN: //oassert(node->num_children == 1); /* attach the drivers to the driver nets */ @@ -677,6 +766,9 @@ signal_list_t *netlist_expand_ast_of_module(ast_node_t** node_ref, char *instanc terminate_continuous_assignment(node, children_signal_list[i], instance_name_prefix); } break; + case STATEMENT: + terminate_continuous_assignment(node, children_signal_list[0], instance_name_prefix); + break; case ALWAYS: /* attach the drivers to the driver nets */ switch(circuit_edge) @@ -760,6 +852,7 @@ signal_list_t *netlist_expand_ast_of_module(ast_node_t** node_ref, char *instanc && node->type != VAR_DECLARE_LIST && node->type != ASSIGN && node->type != ALWAYS + && node->type != STATEMENT && node->type != CONCATENATE) { free_signal_list(children_signal_list[i]); @@ -1381,7 +1474,7 @@ void create_symbol_table_for_scope(ast_node_t* module_items, sc_hierarchy *local long i, j; char *temp_string; long sc_spot; - oassert(module_items->type == MODULE_ITEMS || module_items->type == FUNCTION_ITEMS || module_items->type == BLOCK); + oassert(module_items->type == MODULE_ITEMS || module_items->type == FUNCTION_ITEMS || module_items->type == TASK_ITEMS || module_items->type == BLOCK); STRING_CACHE *local_symbol_table_sc = local_ref->local_symbol_table_sc; ast_node_t **local_symbol_table = local_ref->local_symbol_table; @@ -1949,8 +2042,8 @@ void connect_module_instantiation_and_alias(short PASS, ast_node_t* module_insta { long i; int j; - ast_node_t *module_node; - ast_node_t *module_list; + ast_node_t *module_node = NULL; + ast_node_t *module_list = NULL; ast_node_t *module_instance_list = module_instance->children[1]->children[1]; // MODULE_INSTANCE->MODULE_INSTANCE_NAME(child[1])->MODULE_CONNECT_LIST(child[1]) long sc_spot; long sc_spot_output; @@ -1988,12 +2081,12 @@ void connect_module_instantiation_and_alias(short PASS, ast_node_t* module_insta ast_node_t *module_var_node = module_list->children[i]; // MODULE_CONNECT_LIST(child[i])->MODULE_CONNECT(child[1]) // child[0] is for aliasing ast_node_t *module_instance_var_node = module_instance_list->children[i]->children[1]; - + if ( - // skip inputs on pass 1 - ((PASS == INSTANTIATE_DRIVERS) && (module_list->children[i]->types.variable.is_output)) - // skip outputs on pass 2 - || ((PASS == ALIAS_INPUTS) && (module_list->children[i]->types.variable.is_input)) + // skip inputs on pass 1 + ((PASS == INSTANTIATE_DRIVERS) && (module_list->children[i]->types.variable.is_output)) + // skip outputs on pass 2 + || ((PASS == ALIAS_INPUTS) && (module_list->children[i]->types.variable.is_input)) ) { @@ -2042,9 +2135,9 @@ void connect_module_instantiation_and_alias(short PASS, ast_node_t* module_insta * is already a driver at this level. IF it is a driver then we can hook the two up. * IF it's not we need to alias the pin name as it is used here since it * must be driven at a higher level of hierarchy in the tree of modules */ - char *name_of_module_instance_of_input; - char *full_name; - char *alias_name; + char *name_of_module_instance_of_input = NULL; + char *full_name = NULL; + char *alias_name = NULL; if (port_size > 1) { @@ -2169,9 +2262,9 @@ void connect_module_instantiation_and_alias(short PASS, ast_node_t* module_insta { /* ELSE IF - this is an output pin from the module. We need to alias this output * pin with it's calling name here so that everyone can see it at this level */ - char *name_of_module_instance_of_input; - char *full_name; - char *alias_name; + char *name_of_module_instance_of_input = NULL; + char *full_name = NULL; + char *alias_name = NULL; /* make the new string for the alias name - has to be a identifier in the * instantiated modules old names */ @@ -2266,8 +2359,8 @@ signal_list_t *connect_function_instantiation_and_alias(short PASS, ast_node_t* long i; int j; //signal_list_t *aux_node = NULL; - ast_node_t *module_node; - ast_node_t *module_list; + ast_node_t *module_node = NULL; + ast_node_t *module_list = NULL; ast_node_t *module_instance_list = module_instance->children[1]->children[1]; // MODULE_INSTANCE->MODULE_INSTANCE_NAME(child[1])->MODULE_CONNECT_LIST(child[1]) long sc_spot; long sc_spot_output; @@ -2280,7 +2373,7 @@ signal_list_t *connect_function_instantiation_and_alias(short PASS, ast_node_t* if ((sc_spot = sc_lookup_string(module_names_to_idx, module_instance_name)) == -1) { error_message(NETLIST_ERROR, module_instance->line_number, module_instance->file_number, - "Can't find module %s\n", module_instance_name); + "Can't find function %s\n", module_instance_name); } if (module_instance_name != module_instance->children[0]->types.identifier) @@ -2292,7 +2385,7 @@ signal_list_t *connect_function_instantiation_and_alias(short PASS, ast_node_t* if (module_list->num_children != module_instance_list->num_children) { error_message(NETLIST_ERROR, module_instance->line_number, module_instance->file_number, - "Module instantiation (%s) and definition don't match in terms of ports\n", + "Function instantiation (%s) and definition don't match in terms of ports\n", module_instance->children[0]->types.identifier); } @@ -2324,7 +2417,7 @@ signal_list_t *connect_function_instantiation_and_alias(short PASS, ast_node_t* { // TODO: This error message may not be correct. If assigning by name, the order should not matter error_message(NETLIST_ERROR, module_var_node->line_number, module_var_node->file_number, - "This module entry does not match up correctly (%s != %s). Odin expects the order of ports to be the same\n", + "This function entry does not match up correctly (%s != %s). Odin expects the order of ports to be the same\n", module_instance_list->children[i]->children[0]->types.identifier, module_var_node->children[0]->types.identifier ); @@ -2391,9 +2484,9 @@ signal_list_t *connect_function_instantiation_and_alias(short PASS, ast_node_t* * is already a driver at this level. IF it is a driver then we can hook the two up. * IF it's not we need to alias the pin name as it is used here since it * must be driven at a higher level of hierarchy in the tree of modules */ - char *name_of_module_instance_of_input; - char *full_name; - char *alias_name; + char *name_of_module_instance_of_input = NULL; + char *full_name = NULL; + char *alias_name = NULL; if (port_size > 1) { @@ -2438,8 +2531,8 @@ signal_list_t *connect_function_instantiation_and_alias(short PASS, ast_node_t* /*error_message(NETLIST_ERROR, module_instance->line_number, module_instance->file_number, "This module port %s is unused in module %s", alias_name, module_node->children[0]->types.identifier);*/ if(port_size > 1) - warning_message(NETLIST_ERROR, -1, -1, "This module port %s[%d] is unused in module %s\n", module_instance_var_node->types.identifier, j, module_node->children[0]->types.identifier); - else warning_message(NETLIST_ERROR, -1, -1, "This module port %s is unused in module %s\n", module_instance_var_node->types.identifier, module_node->children[0]->types.identifier); + warning_message(NETLIST_ERROR, -1, -1, "This function port %s[%d] is unused in module %s\n", module_instance_var_node->types.identifier, j, module_node->children[0]->types.identifier); + else warning_message(NETLIST_ERROR, -1, -1, "This function port %s is unused in module %s\n", module_instance_var_node->types.identifier, module_node->children[0]->types.identifier); } else{ @@ -2508,9 +2601,9 @@ signal_list_t *connect_function_instantiation_and_alias(short PASS, ast_node_t* { /* ELSE IF - this is an output pin from the module. We need to alias this output * pin with it's calling name here so that everyone can see it at this level */ - char *name_of_module_instance_of_input; - char *full_name; - char *alias_name; + char *name_of_module_instance_of_input = NULL; + char *full_name = NULL; + char *alias_name = NULL; /* make the new string for the alias name - has to be a identifier in the * instantiated modules old names */ @@ -2603,6 +2696,332 @@ signal_list_t *connect_function_instantiation_and_alias(short PASS, ast_node_t* } +/*--------------------------------------------------------------------------------------------- + * (function: connect_task_instantiation_and_alias) + *-------------------------------------------------------------------------------------------*/ + +signal_list_t *connect_task_instantiation_and_alias(short PASS, ast_node_t* task_instance, char *instance_name_prefix, sc_hierarchy *local_ref) +{ + signal_list_t *return_list = init_signal_list(); + + long i; + int j; + //signal_list_t *aux_node = NULL; + ast_node_t *task_node = NULL; + ast_node_t *task_list = NULL; + ast_node_t *task_instance_list = task_instance->children[1]->children[1]; // TASK_INSTANCE->TASK_NAMED_INSTANCE->MODULE_CONNECT_LIST(child[1]) + long sc_spot; + long sc_spot_output; + long sc_spot_input_old; + long sc_spot_input_new; + + char *task_instance_name = task_instance->children[0]->types.identifier; + + /* lookup the node of the task associated with this instantiated task */ + if ((sc_spot = sc_lookup_string(module_names_to_idx, task_instance_name)) == -1) + { + error_message(NETLIST_ERROR, task_instance->line_number, task_instance->file_number, + "Can't find task %s\n", task_instance_name); + } + + if (task_instance_name != task_instance->children[0]->types.identifier) + vtr::free(task_instance_name); + + task_node = (ast_node_t*)module_names_to_idx->data[sc_spot]; + task_list = task_node->children[1]; // TASK->VAR_DECLARE_LIST(child[1]) + + if (task_list->num_children != task_instance_list->num_children) + { + error_message(NETLIST_ERROR, task_instance->line_number, task_instance->file_number, + "Task instantiation (%s) and definition don't match in terms of ports\n", + task_instance->children[0]->types.identifier); + } + + for (i = 0; i < task_list->num_children; i++) + { + + int port_size = 0; + // VAR_DECLARE_LIST(child[i])->VAR_DECLARE_PORT(child[0])->VAR_DECLARE_input-or-output(child[0]) + ast_node_t *task_var_node = task_list->children[i]; + ast_node_t *task_instance_var_node = task_instance_list->children[i]->children[1]; + + if ( + // skip inputs on pass 1 + ((PASS == INSTANTIATE_DRIVERS) && (task_var_node->types.variable.is_input)) + // skip outputs on pass 2 + || ((PASS == ALIAS_INPUTS) && (task_var_node->types.variable.is_output)) + ) + { + continue; + } + + /* IF the designer users port names then make sure they line up */ + // TODO: This code may need to be moved down the line + if (i > 0 && task_instance_list->children[i]->children[0] != NULL) + { + if (strcmp(task_instance_list->children[i]->children[0]->types.identifier, task_var_node->children[0]->types.identifier) != 0) + { + // TODO: This error message may not be correct. If assigning by name, the order should not matter + error_message(NETLIST_ERROR, task_var_node->line_number, task_var_node->file_number, + "This task entry does not match up correctly (%s != %s). Odin expects the order of ports to be the same\n", + task_instance_list->children[i]->children[0]->types.identifier, + task_var_node->children[0]->types.identifier + ); + } + } + + /* calculate the port details */ + if (task_var_node->children[1] == NULL) + { + port_size = 1; + } + else if (task_var_node->children[3] == NULL) + { + char *task_name = make_full_ref_name(instance_name_prefix, + // task_name + task_instance->children[0]->types.identifier, + // instance name + task_instance->children[1]->children[0]->types.identifier, + NULL, -1); + + ast_node_t *node1 = task_var_node->children[1]; + ast_node_t *node2 = task_var_node->children[2]; + + vtr::free(task_name); + oassert(node2->type == NUMBERS && node1->type == NUMBERS); + /* assume all arrays declared [largest:smallest] */ + oassert(node2->types.vnumber->get_value() <= node1->types.vnumber->get_value()); + port_size = node1->types.vnumber->get_value() - node2->types.vnumber->get_value() + 1; + } + else if (task_var_node->children[5] == NULL) + { + char *task_name = make_full_ref_name(instance_name_prefix, + // task_name + task_instance->children[0]->types.identifier, + // instance name + task_instance->children[1]->children[0]->types.identifier, + NULL, -1); + + ast_node_t *node1 = task_var_node->children[1]; + ast_node_t *node2 = task_var_node->children[2]; + ast_node_t *node3 = task_var_node->children[3]; + ast_node_t *node4 = task_var_node->children[4]; + + vtr::free(task_name); + oassert(node2->type == NUMBERS && node1->type == NUMBERS && node3->type == NUMBERS && node4->type == NUMBERS); + /* assume all arrays declared [largest:smallest] */ + oassert(node2->types.vnumber->get_value() <= node1->types.vnumber->get_value()); + oassert(node4->types.vnumber->get_value() <= node3->types.vnumber->get_value()); + port_size = node1->types.vnumber->get_value() * node3->types.vnumber->get_value() - 1; + } + + //----------------------------------------------------------------------------------- + else if (task_var_node->children[5] != NULL) + { + /* Implicit memory */ + error_message(NETLIST_ERROR, task_var_node->children[5]->line_number, task_var_node->children[5]->file_number, "%s\n", "Unhandled implicit memory in connect_task_instantiation_and_alias"); + } + if (task_var_node->types.variable.is_input) + { + for (j = 0; j < port_size; j++) + { + /* IF - this spot in the task list is an input, then we need to find it in the + * string cache (as its old name), check if the new_name (the instantiation name) + * is already a driver at this level. IF it is a driver then we can hook the two up. + * IF it's not we need to alias the pin name as it is used here since it + * must be driven at a higher level of hierarchy in the tree of tasks */ + char *name_of_task_instance_of_input = NULL; + char *full_name = NULL; + char *alias_name = NULL; + + if (port_size > 1) + { + /* Get the name of the task instantiation pin */ + name_of_task_instance_of_input = get_name_of_pin_at_bit(task_instance_var_node, j, instance_name_prefix, local_ref); + full_name = make_full_ref_name(instance_name_prefix, NULL, NULL, name_of_task_instance_of_input, -1); + vtr::free(name_of_task_instance_of_input); + + /* make the new string for the alias name - has to be a identifier in the instantiated tasks old names */ + name_of_task_instance_of_input = get_name_of_var_declare_at_bit(task_var_node, j); + alias_name = make_full_ref_name(instance_name_prefix, + task_instance->children[0]->types.identifier, + task_instance->children[1]->children[0]->types.identifier, + name_of_task_instance_of_input, -1); + + vtr::free(name_of_task_instance_of_input); + } + else + { + oassert(j == 0); + + /* Get the name of the task instantiation pin */ + name_of_task_instance_of_input = get_name_of_pin_at_bit(task_instance_var_node, -1, instance_name_prefix, local_ref); + + + full_name = make_full_ref_name(instance_name_prefix, NULL, NULL, name_of_task_instance_of_input, -1); + vtr::free(name_of_task_instance_of_input); + + name_of_task_instance_of_input = get_name_of_var_declare_at_bit(task_var_node, 0); + alias_name = make_full_ref_name(instance_name_prefix, + task_instance->children[0]->types.identifier, + task_instance->children[1]->children[0]->types.identifier, + name_of_task_instance_of_input, -1); + + vtr::free(name_of_task_instance_of_input); + } + + /* search for the old_input name */ + if ((sc_spot_input_old = sc_lookup_string(input_nets_sc, alias_name)) == -1) + { + /* doesn it have to exist since might only be used in task */ + /*error_message(NETLIST_ERROR, task_instance->line_number, task_instance->file_number, + "This task port %s is unused in task %s", alias_name, task_node->children[0]->types.identifier);*/ + if(port_size > 1) + warning_message(NETLIST_ERROR, -1, -1, "This task port %s[%d] is unused in module %s\n", task_instance_var_node->types.identifier, j, task_node->children[0]->types.identifier); + else warning_message(NETLIST_ERROR, -1, -1, "This task port %s is unused in module %s\n", task_instance_var_node->types.identifier, task_node->children[0]->types.identifier); + + } + else{ + + /* CMM - Check if this pin should be driven by the top level VCC or GND drivers */ + if (strstr(full_name, ONE_VCC_CNS)) + { + join_nets(verilog_netlist->one_net, (nnet_t*)input_nets_sc->data[sc_spot_input_old]); + free_nnet((nnet_t*)input_nets_sc->data[sc_spot_input_old]); + input_nets_sc->data[sc_spot_input_old] = (void*)verilog_netlist->one_net; + } + else if (strstr(full_name, ZERO_GND_ZERO)) + { + join_nets(verilog_netlist->zero_net, (nnet_t*)input_nets_sc->data[sc_spot_input_old]); + free_nnet((nnet_t*)input_nets_sc->data[sc_spot_input_old]); + input_nets_sc->data[sc_spot_input_old] = (void*)verilog_netlist->zero_net; + } + /* check if the instantiation pin exists. */ + else if ((sc_spot_output = sc_lookup_string(output_nets_sc, full_name)) == -1) + { + /* IF - no driver, then assume that it needs to be aliased to move up as an input */ + if ((sc_spot_input_new = sc_lookup_string(input_nets_sc, full_name)) == -1) + { + /* if this input is not yet used in this task then we'll add it */ + sc_spot_input_new = sc_add_string(input_nets_sc, full_name); + + /* copy the pin to the old spot */ + input_nets_sc->data[sc_spot_input_new] = input_nets_sc->data[sc_spot_input_old]; + } + else + { + /* already exists so we'll join the nets */ + combine_nets((nnet_t*)input_nets_sc->data[sc_spot_input_old], (nnet_t*)input_nets_sc->data[sc_spot_input_new], verilog_netlist); + input_nets_sc->data[sc_spot_input_old] = NULL; + } + } + else + { + /* ELSE - we've found a matching net, so add this pin to the net */ + nnet_t* net = (nnet_t*)output_nets_sc->data[sc_spot_output]; + nnet_t* in_net = (nnet_t*)input_nets_sc->data[sc_spot_input_old]; + + if ((net != in_net) && (net->combined == true)) + { + /* if they haven't been combined already, then join the inputs and output */ + join_nets(net, in_net); + in_net = free_nnet(in_net); + /* since the driver net is deleted, copy the spot of the in_net over */ + input_nets_sc->data[sc_spot_input_old] = (void*)net; + } + else if ((net != in_net) && (net->combined == false)) + { + /* if they haven't been combined already, then join the inputs and output */ + combine_nets(net, in_net, verilog_netlist); + net = NULL; + /* since the driver net is deleted, copy the spot of the in_net over */ + output_nets_sc->data[sc_spot_output] = (void*)in_net; + } + } + } + + vtr::free(full_name); + vtr::free(alias_name); + } + } + else if (task_var_node->types.variable.is_output) + { + for (j = 0; j < port_size; j++) + { + /* ELSE IF - this is an output pin from the module. We need to alias this output + * pin with it's calling name here so that everyone can see it at this level */ + char *name_of_task_instance_of_input = NULL; + char *full_name = NULL; + char *alias_name = NULL; + + /* make the new string for the alias name - has to be a identifier in the + * instantiated modules old names */ + if (port_size > 1) + { + /* Get the name of the module instantiation pin */ + name_of_task_instance_of_input = get_name_of_pin_at_bit(task_instance_var_node, j, instance_name_prefix, local_ref); + full_name = make_full_ref_name(instance_name_prefix, NULL, NULL, name_of_task_instance_of_input, -1); + vtr::free(name_of_task_instance_of_input); + + name_of_task_instance_of_input = get_name_of_var_declare_at_bit(task_var_node, j); + alias_name = make_full_ref_name(instance_name_prefix, + task_instance->children[0]->types.identifier, + task_instance->children[1]->children[0]->types.identifier, name_of_task_instance_of_input, -1); + vtr::free(name_of_task_instance_of_input); + } + else + { + oassert(j == 0); + /* Get the name of the module instantiation pin */ + name_of_task_instance_of_input = get_name_of_pin_at_bit(task_instance_var_node, -1, instance_name_prefix, local_ref); + full_name = make_full_ref_name(instance_name_prefix, NULL, NULL, name_of_task_instance_of_input, -1); + vtr::free(name_of_task_instance_of_input); + name_of_task_instance_of_input = NULL; + + name_of_task_instance_of_input = get_name_of_var_declare_at_bit(task_var_node, 0); + alias_name = make_full_ref_name(instance_name_prefix, + task_instance->children[0]->types.identifier, + task_instance->children[1]->children[0]->types.identifier, name_of_task_instance_of_input, -1); + vtr::free(name_of_task_instance_of_input); + } + + + /* check if the instantiation pin exists. */ + if ((sc_spot_output = sc_lookup_string(output_nets_sc, alias_name)) == -1) + { + error_message(NETLIST_ERROR, task_var_node->line_number, task_var_node->file_number, + "This output (%s) must exist...must be an error\n", alias_name); + } + + + sc_spot_input_new = sc_add_string(output_nets_sc, full_name); + + + /* Copy over the initial value data from the net alias to the corresponding + flip-flop node if one exists. This is necessary if an initial value is + assigned on a higher-level module since the flip-flop node will have + already been instantiated without any initial value. */ + name_of_task_instance_of_input = get_name_of_pin_at_bit(task_instance_var_node, j, instance_name_prefix, local_ref); + char *pin_name = make_full_ref_name(instance_name_prefix, NULL, NULL, name_of_task_instance_of_input, -1); + + nnet_t *output_net = (nnet_t*)output_nets_sc->data[sc_spot_output]; + npin_t *new_pin2 = allocate_npin(); + new_pin2->name = pin_name; + add_fanout_pin_to_net(output_net, new_pin2); + add_pin_to_signal_list(return_list, new_pin2); + + + vtr::free(full_name); + vtr::free(alias_name); + vtr::free(name_of_task_instance_of_input); + + } + + } + + } + return return_list; +} /*--------------------------------------------------------------------------------------------- diff --git a/ODIN_II/SRC/output_blif.cpp b/ODIN_II/SRC/output_blif.cpp index 95a8578cd2e..7b64ace9a4a 100644 --- a/ODIN_II/SRC/output_blif.cpp +++ b/ODIN_II/SRC/output_blif.cpp @@ -52,16 +52,87 @@ void define_ff(nnode_t *node, FILE *out); void define_decoded_mux(nnode_t *node, FILE *out); void output_blif_pin_connect(nnode_t *node, FILE *out); + +static void print_input_pin(FILE *out, nnode_t *node, long pin_idx) +{ + oassert(pin_idx < node->num_input_pins); + nnet_t *net = node->input_pins[pin_idx]->net; + if (!net->driver_pin || !net->driver_pin->node) + { + // Add a warning for an undriven net. + int line_number = node->related_ast_node?node->related_ast_node->line_number:0; + warning_message(NETLIST_ERROR, line_number, -1, + "Net %s driving node %s is itself undriven.", + net->name, node->name); + + fprintf(out, " %s", "unconn"); + } + else if (global_args.high_level_block.provenance() == argparse::Provenance::SPECIFIED + && net->driver_pin->node->related_ast_node != NULL) + { + fprintf(out, " %s^^%i-%i", + net->driver_pin->node->name, + net->driver_pin->node->related_ast_node->far_tag, + net->driver_pin->node->related_ast_node->high_number); + } + else + { + if (net->driver_pin->name != NULL && + ((net->driver_pin->node->type == MULTIPLY) || + (net->driver_pin->node->type == HARD_IP) || + (net->driver_pin->node->type == MEMORY) || + (net->driver_pin->node->type == ADD) || + (net->driver_pin->node->type == MINUS))) + { + fprintf(out, " %s", net->driver_pin->name); + } + else + { + fprintf(out, " %s", net->driver_pin->node->name); + } + } + +} + +static void print_output_pin(FILE *out, nnode_t *node) +{ + /* now print the output */ + if (node->related_ast_node != NULL + && global_args.high_level_block.provenance() == argparse::Provenance::SPECIFIED) + fprintf(out, " %s^^%i-%i", + node->name, + node->related_ast_node->far_tag, + node->related_ast_node->high_number); + else + fprintf(out, " %s", node->name); +} + +static void print_input_pin_list(FILE *out, nnode_t *node) +{ + for( long i = 0; i < node->num_input_pins; i++) + { + print_input_pin(out, node, i); + } +} + +static void print_dot_names_header(FILE *out, nnode_t *node) +{ + fprintf(out, ".names"); + print_input_pin_list(out, node); + + oassert(node->num_output_pins == 1); + print_output_pin(out, node); + fprintf(out, "\n"); + +} + + /*--------------------------------------------------------------------------- * (function: output_blif) * The function that prints out the details for a blif formatted file *-------------------------------------------------------------------------*/ void output_blif(const char *file_name, netlist_t *netlist) { - int i; - int count = 0; - bool first_time_inputs = false; - bool first_time_outputs = false; FILE *out; /* open the file for output */ @@ -83,80 +154,34 @@ void output_blif(const char *file_name, netlist_t *netlist) fprintf(out, ".model %s\n", top_module->children[0]->types.identifier); - /* generate all te signals */ - for (i = 0; i < netlist->num_top_input_nodes; i++) - { - if (first_time_inputs == false) - { - count = fprintf(out, ".inputs"); - first_time_inputs = true; - } - if (global_args.high_level_block.provenance() == argparse::Provenance::SPECIFIED) - { - if (strlen(netlist->top_input_nodes[i]->name) + count < 79) - count = count + fprintf(out, " %s^^%i-%i", netlist->top_input_nodes[i]->name, netlist->top_input_nodes[i]->related_ast_node->far_tag, netlist->top_input_nodes[i]->related_ast_node->high_number); - else - { - /* wrapping line */ - count = fprintf(out, " \\\n %s^^%i-%i", netlist->top_input_nodes[i]->name,netlist->top_input_nodes[i]->related_ast_node->far_tag, netlist->top_input_nodes[i]->related_ast_node->high_number); - count = count - 3; - } - } - else - { - if (strlen(netlist->top_input_nodes[i]->name) + count < 79) - { - count = count + fprintf(out, " %s", netlist->top_input_nodes[i]->name); - } - else - { - /* wrapping line */ - count = fprintf(out, " \\\n %s", netlist->top_input_nodes[i]->name); - count = count - 3; - } - } + /* generate all the signals */ + fprintf(out, ".inputs"); + for (long i = 0; i < netlist->num_top_input_nodes; i++) + { + nnode_t *top_input_node = netlist->top_input_nodes[i]; + print_output_pin(out, top_input_node); } fprintf(out, "\n"); - count = 0; - for (i = 0; i < netlist->num_top_output_nodes; i++) + + fprintf(out, ".outputs"); + for (long i = 0; i < netlist->num_top_output_nodes; i++) { - if (netlist->top_output_nodes[i]->input_pins[0]->net->driver_pin == NULL) + nnode_t *top_output_node = netlist->top_output_nodes[i]; + if (top_output_node->input_pins[0]->net->driver_pin == NULL) { - warning_message(NETLIST_ERROR, netlist->top_output_nodes[i]->related_ast_node->line_number, netlist->top_output_nodes[i]->related_ast_node->file_number, "This output is undriven (%s) and will be removed\n", netlist->top_output_nodes[i]->name); + warning_message(NETLIST_ERROR, + top_output_node->related_ast_node->line_number, + top_output_node->related_ast_node->file_number, + "This output is undriven (%s) and will be removed\n", + top_output_node->name); } else { - if (first_time_outputs == false) - { - count = fprintf(out, ".outputs"); - first_time_outputs = true; - } - - if ( global_args.high_level_block.provenance() == argparse::Provenance::SPECIFIED ) - { - if ((strlen(netlist->top_output_nodes[i]->name) + count) < 79) - count = count + fprintf(out, " %s^^%i-%i", netlist->top_output_nodes[i]->name,netlist->top_output_nodes[i]->related_ast_node->far_tag, netlist->top_output_nodes[i]->related_ast_node->high_number); - else - { - /* wrapping line */ - count = fprintf(out, "\\\n %s^^%i-%i", netlist->top_output_nodes[i]->name,netlist->top_output_nodes[i]->related_ast_node->far_tag, netlist->top_output_nodes[i]->related_ast_node->high_number); - count = count - 3; - } - } - else - { - if ((strlen(netlist->top_output_nodes[i]->name) + count) < 79) - count = count + fprintf(out, " %s", netlist->top_output_nodes[i]->name); - else - { - /* wrapping line */ - count = fprintf(out, "\\\n %s", netlist->top_output_nodes[i]->name); - count = count - 3; - } - } + + print_output_pin(out, top_output_node); } } fprintf(out, "\n"); @@ -176,42 +201,16 @@ void output_blif(const char *file_name, netlist_t *netlist) } /* connect all the outputs up to the last gate */ - for (i = 0; i < netlist->num_top_output_nodes; i++) + for (long i = 0; i < netlist->num_top_output_nodes; i++) { - /* KEN -- DPRAM WORKING HERE FOR JASON */ nnode_t *node = netlist->top_output_nodes[i]; - if (node->input_pins[0]->net->driver_pin != NULL) - { - if (global_args.high_level_block.provenance() == argparse::Provenance::SPECIFIED) - { - fprintf(out, ".names %s^^%i-%i %s^^%i-%i\n1 1\n", - node->input_pins[0]->net->driver_pin->node->name, - node->input_pins[0]->net->driver_pin->node->related_ast_node->far_tag, - node->input_pins[0]->net->driver_pin->node->related_ast_node->high_number, - node->name, - node->related_ast_node->far_tag, - node->related_ast_node->high_number - ); - } - else - { - /* - * Use the name of the driver pin as the name of the driver - * as long as that name is set, and is not equal to the name of the output pin. - * - * Otherwise, use the name of the driver node. - */ - char *driver = node->input_pins[0]->net->driver_pin->name; - char *output = node->name; - if (!driver || !strcmp(driver,output)) - driver = node->input_pins[0]->net->driver_pin->node->name; - - /* Skip if the driver and output have the same name (i.e. the output of a flip-flop) */ - if (strcmp(driver,output) != 0) fprintf(out, ".names %s %s\n1 1\n", driver, output); - } - - } + + fprintf(out, ".names"); + print_input_pin(out,node,0); + print_output_pin(out, node); fprintf(out, "\n"); + + fprintf(out, "1 1\n\n"); } /* finish off the top level module */ @@ -405,74 +404,7 @@ void define_logical_function(nnode_t *node, FILE *out) int i, j; char *temp_string; - fprintf(out, ".names"); - - - if (global_args.high_level_block.provenance() == argparse::Provenance::SPECIFIED) - { - /* printout all the port hookups */ - for (i = 0; i < node->num_input_pins; i++) - { - /* now hookup the input wires with their respective ports. [1+i] to skip output spot. */ - if (node->input_pins[i]->net->driver_pin->node->related_ast_node != NULL) - fprintf(out, " %s^^%i-%i", node->input_pins[i]->net->driver_pin->node->name, node->input_pins[i]->net->driver_pin->node->related_ast_node->far_tag, node->input_pins[i]->net->driver_pin->node->related_ast_node->high_number); - else - fprintf(out, " %s", node->input_pins[i]->net->driver_pin->node->name); - } - /* now print the output */ - if (node->related_ast_node != NULL) - fprintf(out, " %s^^%i-%i", node->name, node->related_ast_node->far_tag, node->related_ast_node->high_number); - else - fprintf(out, " %s", node->name); - } - else - { - /* printout all the port hookups */ - for (i = 0; i < node->num_input_pins; i++) - { - /* now hookup the input wires with their respective ports. [1+i] to skip output spot. */ - /* Just print the driver_pin->name NOT driver_pin->node->name -- KEN */ - nnet_t *net = node->input_pins[i]->net; - if (net) - { - if(net->driver_pin) - { - if (net->driver_pin->name != NULL) - { - if ((net->driver_pin->node->type == MULTIPLY) || - (net->driver_pin->node->type == HARD_IP) || - (net->driver_pin->node->type == MEMORY) || - (net->driver_pin->node->type == ADD) || - (net->driver_pin->node->type == MINUS) ) - { - fprintf(out, " %s", net->driver_pin->name); - } - else - { - fprintf(out, " %s", net->driver_pin->node->name); - } - } - else - { - fprintf(out, " %s", net->driver_pin->node->name); - } - } - else - { - int line_number = node->related_ast_node?node->related_ast_node->line_number:0; - warning_message(NETLIST_ERROR, line_number, -1, "Net %s driving node %s is itself undriven.", net->name, node->name); - - fprintf(out, " %s", "unconn"); - } - } - - } - /* now print the output */ - fprintf(out, " %s", node->name); - } - fprintf(out, "\n"); - - oassert(node->num_output_pins == 1); + print_dot_names_header(out, node); /* print out the blif definition of this gate */ switch (node->type) @@ -576,83 +508,17 @@ void define_logical_function(nnode_t *node, FILE *out) *----------------------------------------------------------------------*/ void define_set_input_logical_function(nnode_t *node, const char *bit_output, FILE *out) { - int i; - - fprintf(out, ".names"); - oassert(node->num_output_pins == 1); oassert(node->num_input_pins >= 1); + print_dot_names_header(out, node); - if (global_args.high_level_block.provenance() == argparse::Provenance::SPECIFIED) - { - /* printout all the port hookups */ - for (i = 0; i < node->num_input_pins; i++) - { - /* now hookup the input wires with their respective ports. [1+i] to skip output spot. */ - if (node->input_pins[i]->net->driver_pin->node->related_ast_node != NULL) - fprintf(out, " %s^^%i-%i", node->input_pins[i]->net->driver_pin->node->name, node->input_pins[i]->net->driver_pin->node->related_ast_node->far_tag, node->input_pins[i]->net->driver_pin->node->related_ast_node->high_number); - else - fprintf(out, " %s", node->input_pins[i]->net->driver_pin->node->name); - } - - /* now print the output */ - if (node->related_ast_node != NULL) - fprintf(out, " %s^^%i-%i", node->name, node->related_ast_node->far_tag, node->related_ast_node->high_number); - else - fprintf(out, " %s", node->name); - fprintf(out, "\n"); - - /* print out the blif definition of this gate */ - if (bit_output != NULL) - { - fprintf(out, "%s", bit_output); - } - fprintf(out, "\n"); - } - else + /* print out the blif definition of this gate */ + if (bit_output != NULL) { - /* printout all the port hookups */ - for (i = 0; i < node->num_input_pins; i++) - { - if (node->input_pins[i]->net->driver_pin != NULL) - { - if (node->input_pins[i]->net->driver_pin->name != NULL) - { - /* now hookup the input wires with their respective ports. [1+i] to skip output spot. */ - /* Just print the driver_pin->name NOT driver_pin->node->name -- KEN */ - if ((node->input_pins[i]->net->driver_pin->node->type == MULTIPLY) || - (node->input_pins[i]->net->driver_pin->node->type == HARD_IP) || - (node->input_pins[i]->net->driver_pin->node->type == MEMORY) || - (node->input_pins[i]->net->driver_pin->node->type == ADD) || - (node->input_pins[i]->net->driver_pin->node->type == MINUS)) - { - fprintf(out, " %s", node->input_pins[i]->net->driver_pin->name); - } - else - { - fprintf(out, " %s", node->input_pins[i]->net->driver_pin->node->name); - } - } - else - { - fprintf(out, " %s", node->input_pins[i]->net->driver_pin->node->name); - } - } - } - - /* now print the output */ - fprintf(out, " %s", node->name); - fprintf(out, "\n"); - - /* print out the blif definition of this gate */ - if (bit_output != NULL) - { - fprintf(out, "%s", bit_output); - } - fprintf(out, "\n"); + fprintf(out, "%s", bit_output); } - + fprintf(out, "\n"); } @@ -682,49 +548,22 @@ void define_ff(nnode_t *node, FILE *out) std::string output; std::string clock_driver; - fprintf(out, ".latch "); + fprintf(out, ".latch"); /* input */ - if (global_args.high_level_block.provenance() == argparse::Provenance::SPECIFIED) - { - fprintf(out, "%s^^%i-%i ", - node->input_pins[0]->net->driver_pin->node->name, - node->input_pins[0]->net->driver_pin->node->related_ast_node->far_tag, - node->input_pins[0]->net->driver_pin->node->related_ast_node->high_number); - } - else if (node->input_pins[0]->net->driver_pin->name == NULL) - fprintf(out, "%s ", node->input_pins[0]->net->driver_pin->node->name); - else - fprintf(out, "%s ", node->input_pins[0]->net->driver_pin->name); - + print_input_pin(out,node, 0); /* output */ - if (global_args.high_level_block.provenance() == argparse::Provenance::SPECIFIED) - { - fprintf(out, "%s^^%i-%i ", - node->name, - node->related_ast_node->far_tag, - node->related_ast_node->high_number); - } - else - fprintf(out, "%s ", node->name); - + print_output_pin(out,node); + /* sensitivity */ + fprintf(out, " %s", edge_type_str); + /* clock */ - fprintf(out, "%s ", edge_type_str); - if(global_args.high_level_block.provenance() == argparse::Provenance::SPECIFIED) - { - fprintf(out, "%s^^%i-%i ", - node->input_pins[1]->net->driver_pin->node->name, - node->input_pins[1]->net->driver_pin->node->related_ast_node->far_tag, - node->input_pins[1]->net->driver_pin->node->related_ast_node->high_number); - } - else if (node->input_pins[1]->net->driver_pin->name == NULL) - fprintf(out, "%s ", node->input_pins[1]->net->driver_pin->node->name); - else - fprintf(out, "%s ", node->input_pins[1]->net->driver_pin->name); + print_input_pin(out,node, 1); - fprintf(out, "%d\n\n", initial_value); + /* initial value */ + fprintf(out, " %d\n\n", initial_value); } /*-------------------------------------------------------------------------- @@ -732,85 +571,14 @@ void define_ff(nnode_t *node, FILE *out) *------------------------------------------------------------------------*/ void define_decoded_mux(nnode_t *node, FILE *out) { - int i, j; - oassert(node->input_port_sizes[0] == node->input_port_sizes[1]); + print_dot_names_header(out, node); - fprintf(out, ".names"); - - if (global_args.high_level_block.provenance() == argparse::Provenance::SPECIFIED) - { - /* printout all the port hookups */ - for (i = 0; i < node->num_input_pins; i++) - { - /* now hookup the input wires with their respective ports. [1+i] to skip output spot. */ - if (node->input_pins[i]->net->driver_pin->node->related_ast_node != NULL) - { - fprintf(out, " %s^^%i-%i", node->input_pins[i]->net->driver_pin->node->name, node->input_pins[i]->net->driver_pin->node->related_ast_node->far_tag, node->input_pins[i]->net->driver_pin->node->related_ast_node->high_number); - } - else - { - fprintf(out, " %s", node->input_pins[i]->net->driver_pin->node->name); - } - } - /* now print the output */ - if (node->related_ast_node != NULL) - fprintf(out, " %s^^%i-%i", node->name, node->related_ast_node->far_tag, node->related_ast_node->high_number); - else - fprintf(out, " %s", node->name); - } - else - { - /* printout all the port hookups */ - for (i = 0; i < node->num_input_pins; i++) - { - /* now hookup the input wires with their respective ports. [1+i] to skip output spot. */ - /* Just print the driver_pin->name NOT driver_pin->node->name -- KEN */ - nnet_t *net = node->input_pins[i]->net; - - if (!net->driver_pin) - { - // Add a warning for an undriven net. - int line_number = node->related_ast_node?node->related_ast_node->line_number:0; - warning_message(NETLIST_ERROR, line_number, -1, "Net %s driving node %s is itself undriven.", net->name, node->name); - - fprintf(out, " %s", "unconn"); - } - else - { - if (net->driver_pin->name != NULL) - { - if ((net->driver_pin->node->type == MULTIPLY) || - (net->driver_pin->node->type == HARD_IP) || - (net->driver_pin->node->type == MEMORY) || - (net->driver_pin->node->type == ADD) || - (net->driver_pin->node->type == MINUS)) - { - fprintf(out, " %s", net->driver_pin->name); - } - else - { - fprintf(out, " %s", net->driver_pin->node->name); - } - } - else - { - fprintf(out, " %s", net->driver_pin->node->name); - } - } - } - - // Now print the output - fprintf(out, " %s", node->name); - } - fprintf(out, "\n"); - - oassert(node->num_output_pins == 1); /* generates: 1----- 1\n-1----- 1\n ... */ - for (i = 0; i < node->input_port_sizes[0]; i++) + for (long i = 0; i < node->input_port_sizes[0]; i++) { - for (j = 0; j < node->num_input_pins; j++) + for (long j = 0; j < node->num_input_pins; j++) { if (i == j) fprintf(out, "1"); diff --git a/ODIN_II/SRC/parse_making_ast.cpp b/ODIN_II/SRC/parse_making_ast.cpp index 907494e1534..f02014a13d1 100644 --- a/ODIN_II/SRC/parse_making_ast.cpp +++ b/ODIN_II/SRC/parse_making_ast.cpp @@ -52,6 +52,11 @@ STRING_CACHE *function_defparams_sc; STRING_CACHE *functions_inputs_sc; STRING_CACHE *functions_outputs_sc; +STRING_CACHE *task_parameters_sc; +STRING_CACHE *task_defparams_sc; +STRING_CACHE *tasks_inputs_sc; +STRING_CACHE *tasks_outputs_sc; + STRING_CACHE *module_names_to_idx; STRING_CACHE *instantiated_modules; @@ -62,11 +67,20 @@ int size_function_instantiations; ast_node_t **function_instantiations_instance_by_module; int size_function_instantiations_by_module; +ast_node_t **task_instantiations_instance; +int size_task_instantiations; +ast_node_t **task_instantiations_instance_by_module; +int size_task_instantiations_by_module; + long num_modules; ast_node_t **ast_modules; int num_functions; ast_node_t **ast_functions; + +long num_tasks; +ast_node_t **ast_tasks; + ast_node_t **all_file_items_list; int size_all_file_items_list; @@ -87,11 +101,12 @@ void parse_to_ast() /* read all the files in the configuration file */ current_parse_file = configuration.list_of_file_names.size()-1; + int parse_counter = current_parse_file; - while (current_parse_file >= 0) + while (parse_counter >= 0) { - push_include(configuration.list_of_file_names[current_parse_file].c_str()); - current_parse_file--; + push_include(configuration.list_of_file_names[parse_counter].c_str()); + parse_counter--; } current_parse_file = 0; @@ -118,22 +133,29 @@ void init_parser() module_parameters_sc = sc_new_string_cache(); functions_inputs_sc = sc_new_string_cache(); functions_outputs_sc = sc_new_string_cache(); + tasks_inputs_sc = sc_new_string_cache(); + tasks_outputs_sc = sc_new_string_cache(); instantiated_modules = sc_new_string_cache(); module_instances_sc = sc_new_string_cache(); module_defparams_sc = sc_new_string_cache(); function_parameters_sc = NULL; + task_parameters_sc = NULL; /* record of each of the individual modules */ num_modules = 0; // we're going to record all the modules in a list so we can build a tree of them later num_functions = 0; + num_tasks = 0; ast_modules = NULL; ast_functions = NULL; + ast_tasks = NULL; function_instantiations_instance = NULL; module_variables_not_defined = NULL; size_module_variables_not_defined = 0; size_function_instantiations = 0; function_instantiations_instance_by_module = NULL; size_function_instantiations_by_module = 0; + size_task_instantiations = 0; + size_task_instantiations_by_module = 0; /* keeps track of all the ast roots */ all_file_items_list = NULL; @@ -150,6 +172,8 @@ void cleanup_parser() module_parameters_sc = sc_free_string_cache(module_parameters_sc); functions_inputs_sc = sc_free_string_cache(functions_inputs_sc); functions_outputs_sc = sc_free_string_cache(functions_outputs_sc); + tasks_inputs_sc = sc_free_string_cache(tasks_inputs_sc); + tasks_outputs_sc = sc_free_string_cache(tasks_outputs_sc); instantiated_modules = sc_free_string_cache(instantiated_modules); module_instances_sc = sc_free_string_cache(module_instances_sc); module_defparams_sc = sc_free_string_cache(module_defparams_sc); @@ -284,6 +308,14 @@ static ast_node_t *resolve_symbol_node(ids top_type, ast_node_t *symbol_node) newNode = (ast_node_t *)function_parameters_sc->data[sc_spot]; } } + else if(top_type == TASK) + { + long sc_spot = sc_lookup_string(task_parameters_sc, symbol_node->types.identifier); + if (sc_spot != -1) + { + newNode = (ast_node_t *)task_parameters_sc->data[sc_spot]; + } + } if (newNode && newNode->types.variable.is_parameter == true) { @@ -417,6 +449,28 @@ ast_node_t *resolve_ports(ids top_type, ast_node_t *symbol_list) error_message(PARSE_ERROR, symbol_list->children[i]->line_number, current_parse_file, "No matching declaration for port %s\n", symbol_list->children[i]->children[0]->types.identifier); } } + else if(top_type == TASK) + { + /* find the related INPUT or OUTPUT definition and store that instead */ + if ((sc_spot = sc_lookup_string(tasks_inputs_sc, symbol_list->children[i]->children[0]->types.identifier)) != -1) + { + oassert(((ast_node_t*)tasks_inputs_sc->data[sc_spot])->type == VAR_DECLARE); + free_whole_tree(symbol_list->children[i]); + symbol_list->children[i] = (ast_node_t*)tasks_inputs_sc->data[sc_spot]; + oassert(symbol_list->children[i]->types.variable.is_input); + } + else if ((sc_spot = sc_lookup_string(tasks_outputs_sc, symbol_list->children[i]->children[0]->types.identifier)) != -1) + { + oassert(((ast_node_t*)tasks_outputs_sc->data[sc_spot])->type == VAR_DECLARE); + free_whole_tree(symbol_list->children[i]); + symbol_list->children[i] = (ast_node_t*)tasks_outputs_sc->data[sc_spot]; + oassert(symbol_list->children[i]->types.variable.is_output); + } + else + { + error_message(PARSE_ERROR, symbol_list->children[i]->line_number, current_parse_file, "No matching declaration for port %s\n", symbol_list->children[i]->children[0]->types.identifier); + } + } symbol_list->children[i]->types.variable.is_port = true; } @@ -427,10 +481,27 @@ ast_node_t *resolve_ports(ids top_type, ast_node_t *symbol_list) ast_node_t *markAndProcessPortWith(ids top_type, ids port_id, ids net_id, ast_node_t *port, bool is_signed) { + oassert((top_type == MODULE || top_type == FUNCTION || top_type == TASK) + && "can only use MODULE, FUNCTION ot TASK as top type"); + long sc_spot; + const char *top_type_name = NULL; STRING_CACHE *this_inputs_sc = NULL; STRING_CACHE *this_outputs_sc = NULL; - const char *top_type_name = (top_type == MODULE) ? "Module" : "Function"; + + if(top_type == MODULE) + { + top_type_name = "Module"; + } + else if(top_type == FUNCTION) + { + top_type_name = "Function"; + } + else + { + top_type_name = "Task"; + } + ids temp_net_id = NO_ID; if (port->types.variable.is_port) @@ -449,6 +520,11 @@ ast_node_t *markAndProcessPortWith(ids top_type, ids port_id, ids net_id, ast_no this_inputs_sc = functions_inputs_sc; this_outputs_sc = functions_outputs_sc; } + else if(top_type == TASK) + { + this_inputs_sc = tasks_inputs_sc; + this_outputs_sc = tasks_outputs_sc; + } /* look for processed inputs with this name */ sc_spot = sc_lookup_string(this_inputs_sc, port->children[0]->types.identifier); @@ -642,8 +718,8 @@ ast_node_t *markAndProcessPortWith(ids top_type, ids port_id, ids net_id, ast_no ast_node_t *markAndProcessParameterWith(ids top_type, ids id, ast_node_t *parameter, bool is_signed) { - oassert((top_type == MODULE || top_type == FUNCTION || top_type == BLOCK) - && "can only use MODULE or FUNCTION or BLOCK as top type"); + oassert((top_type == MODULE || top_type == FUNCTION || top_type == TASK || top_type == BLOCK) + && "can only use MODULE, FUNCTION, TASK, or BLOCK as top type"); long sc_spot; STRING_CACHE *this_parameters_sc = NULL; @@ -686,6 +762,11 @@ ast_node_t *markAndProcessParameterWith(ids top_type, ids id, ast_node_t *parame this_parameters_sc = function_parameters_sc; this_num_modules = num_functions; } + else if(top_type == TASK) + { + this_parameters_sc = task_parameters_sc; + this_num_modules = num_tasks; + } oassert(this_parameters_sc); @@ -726,7 +807,7 @@ ast_node_t *markAndProcessSymbolListWith(ids top_type, ids id, ast_node_t *symbo symbol_list->children[i]->children[2] = ast_node_deep_copy(range_min); } - if(top_type == MODULE) { + if(top_type == MODULE || top_type == TASK) { switch(id) { @@ -1210,21 +1291,38 @@ ast_node_t *newAlways(ast_node_t *delay_control, ast_node_t *statement, int line return new_node; } + +ast_node_t *newStatement(ast_node_t *statement, int line_number) +{ + /* create a node for this array reference */ + ast_node_t* new_node = create_node_w_type(STATEMENT, line_number, current_parse_file); + /* allocate child nodes to this node */ + allocate_children_to_node(new_node, { statement }); + + return new_node; +} + /*--------------------------------------------------------------------------------------------- * (function: newModuleConnection) *-------------------------------------------------------------------------------------------*/ ast_node_t *newModuleConnection(char* id, ast_node_t *expression, int line_number) { - ast_node_t *symbol_node; + ast_node_t *symbol_node = NULL; /* create a node for this array reference */ ast_node_t* new_node = create_node_w_type(MODULE_CONNECT, line_number, current_parse_file); - if (id != NULL) + if (id) { + if(!is_valid_identifier(id)) + { + error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", id); + } symbol_node = newSymbolNode(id, line_number); } - else + + if(expression == NULL) { - symbol_node = NULL; + char *number = vtr::strdup("'bz"); + expression = newNumberNode(number,line_number); } /* allocate child nodes to this node */ @@ -1282,7 +1380,7 @@ ast_node_t *newModuleNamedInstance(char* unique_name, ast_node_t *module_connect } /*--------------------------------------------------------------------------------------------- - * (function: newModuleNamedInstance) + * (function: newFunctionNamedInstance) *-------------------------------------------------------------------------------------------*/ ast_node_t *newFunctionNamedInstance(ast_node_t *module_connect_list, ast_node_t *module_parameter_list, int line_number) { @@ -1300,6 +1398,48 @@ ast_node_t *newFunctionNamedInstance(ast_node_t *module_connect_list, ast_node_t return new_node; } + +/*--------------------------------------------------------------------------------------------- + * (function: newTaskNamedInstance) + *-------------------------------------------------------------------------------------------*/ +ast_node_t *newTaskNamedInstance(ast_node_t *module_connect_list, int line_number) +{ + std::string buffer("task_instance_"); + buffer += std::to_string(size_task_instantiations_by_module); + + char *unique_name = vtr::strdup(buffer.c_str()); + + ast_node_t *symbol_node = newSymbolNode(unique_name, line_number); + + /* create a node for this array reference */ + ast_node_t* new_node = create_node_w_type(TASK_NAMED_INSTANCE, line_number, current_parse_file); + /* allocate child nodes to this node */ + allocate_children_to_node(new_node, { symbol_node, module_connect_list }); + + return new_node; +} + +/*--------------------------------------------------------------------------------------------- + * (function: newTaskInstance) + *-------------------------------------------------------------------------------------------*/ +ast_node_t *newTaskInstance(char *task_name, ast_node_t *task_named_instace, ast_node_t *task_parameter_list, int line_number) +{ + ast_node_t *symbol_node = newSymbolNode(task_name, line_number); + + /* create a node for this array reference */ + ast_node_t* new_node = create_node_w_type(TASK_INSTANCE, line_number, current_parse_file); + /* allocate child nodes to this node */ + add_child_to_node_at_index(task_named_instace, {task_parameter_list}, 2); + allocate_children_to_node(new_node, { symbol_node, task_named_instace }); + + /* store the module symbol name that this calls in a list that will at the end be asociated with the module node */ + task_instantiations_instance_by_module = (ast_node_t **)vtr::realloc(task_instantiations_instance_by_module, sizeof(ast_node_t*)*(size_task_instantiations_by_module+1)); + task_instantiations_instance_by_module[size_task_instantiations_by_module] = new_node; + size_task_instantiations_by_module++; + + return new_node; +} + /*------------------------------------------------------------------------- * (function: newHardBlockInstance) *-----------------------------------------------------------------------*/ @@ -1631,6 +1771,12 @@ ast_node_t *newModule(char* module_name, ast_node_t *list_of_parameters, ast_nod new_node->types.function.size_function_instantiations = size_function_instantiations_by_module; new_node->types.function.is_instantiated = false; new_node->types.function.index = num_functions; + + new_node->types.task.task_instantiations_instance = task_instantiations_instance_by_module; + new_node->types.task.size_task_instantiations = size_task_instantiations_by_module; + new_node->types.task.is_instantiated = false; + new_node->types.task.index = num_tasks; + /* record this module in the list of modules (for evaluation later in terms of just nodes) */ ast_modules = (ast_node_t **)vtr::realloc(ast_modules, sizeof(ast_node_t*)*(num_modules+1)); ast_modules[num_modules] = new_node; @@ -1669,39 +1815,52 @@ ast_node_t *newModule(char* module_name, ast_node_t *list_of_parameters, ast_nod * ---------------------------------------------------- * (function: newFunction) *-------------------------------------------------------------------------------------------*/ -ast_node_t *newFunction(ast_node_t *list_of_ports, ast_node_t *list_of_module_items, int line_number) //function and module declaration work the same way (Lucas Cambuim) +ast_node_t *newFunction(ast_node_t *function_return, ast_node_t *list_of_ports, ast_node_t *list_of_module_items, int line_number, bool automatic) //function and module declaration work the same way (Lucas Cambuim) { long i,j; long sc_spot; - ast_node_t *var_node; - ast_node_t *symbol_node, *output_node; + char *label = NULL; + ast_node_t *var_node = NULL; + ast_node_t *symbol_node = NULL; + + if(automatic) + { + warning_message(PARSE_ERROR, line_number, current_parse_file, "ODIN II does not (yet) differentiate between automatic and static tasks & functions.IGNORING ", 0); + } + if(function_return->children[0]->types.variable.is_integer) + { + warning_message(PARSE_ERROR, line_number, current_parse_file, "ODIN_II does not fully support input/output integers in functions", 0); + } - char *function_name = vtr::strdup(list_of_ports->children[0]->children[0]->types.identifier); - if (!is_valid_identifier(function_name)) + if(list_of_ports == NULL ) { - error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", function_name); + list_of_ports = create_node_w_type(VAR_DECLARE_LIST, line_number, current_parse_file); } + + label = vtr::strdup(function_return->children[0]->children[0]->types.identifier); - output_node = newList(VAR_DECLARE_LIST, list_of_ports->children[0], line_number); + var_node = newVarDeclare(label, NULL, NULL, NULL, NULL, NULL, line_number); - markAndProcessSymbolListWith(FUNCTION, OUTPUT, output_node, list_of_ports->children[0]->types.variable.is_signed); + add_child_to_node_at_index(list_of_ports, var_node, 0); - add_child_to_node_at_index(list_of_module_items, output_node, 0); - char *label = vtr::strdup(list_of_ports->children[0]->children[0]->types.identifier); + char *function_name = vtr::strdup(function_return->children[0]->children[0]->types.identifier); - var_node = newVarDeclare(label, NULL, NULL, NULL, NULL, NULL, line_number); + if (!is_valid_identifier(function_name)) + { + error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", function_name); + } - list_of_ports->children[0] = var_node; + add_child_to_node_at_index(list_of_module_items, function_return, 0); for(i = 0; i < list_of_module_items->num_children; i++) { if(list_of_module_items->children[i]->type == VAR_DECLARE_LIST){ for(j = 0; j < list_of_module_items->children[i]->num_children; j++) { if(list_of_module_items->children[i]->children[j]->types.variable.is_input){ - label = vtr::strdup(list_of_module_items->children[i]->children[j]->children[0]->types.identifier); + label = vtr::strdup(list_of_module_items->children[i]->children[j]->children[0]->types.identifier); var_node = newVarDeclare(label, NULL, NULL, NULL, NULL, NULL, line_number); newList_entry(list_of_ports,var_node); } @@ -1724,7 +1883,7 @@ ast_node_t *newFunction(ast_node_t *list_of_ports, ast_node_t *list_of_module_it /* allocate child nodes to this node */ allocate_children_to_node(new_node, { symbol_node, list_of_ports, list_of_module_items }); - /* store the list of modules this module instantiates */ + /* store the list of functions this function instantiates */ new_node->types.function.function_instantiations_instance = function_instantiations_instance; new_node->types.function.size_function_instantiations = size_function_instantiations; new_node->types.function.is_instantiated = false; @@ -1745,6 +1904,139 @@ ast_node_t *newFunction(ast_node_t *list_of_ports, ast_node_t *list_of_module_it return new_node; } + +ast_node_t *newTask(char *task_name, ast_node_t *list_of_ports, ast_node_t *list_of_task_items, int line_number, bool automatic) +{ + long sc_spot; + ast_node_t *symbol_node = newSymbolNode(task_name, line_number); + ast_node_t *var_node = NULL; + ast_node_t *port_declarations = NULL; + char *label = NULL; + + if(automatic) + { + warning_message(PARSE_ERROR, line_number, 0, "ODIN II does not (yet) differentiate between automatic and static tasks & functions. IGNORING", 0); + } + + /* create a node for this array reference */ + ast_node_t* new_node = create_node_w_type(TASK, line_number, current_parse_file); + + for(int i = 0; i < list_of_task_items->num_children; i++) + { + if(list_of_task_items->children[i]->type == VAR_DECLARE_LIST) + { + for(int j = 0; j < list_of_task_items->children[i]->num_children; j++) + { + if( list_of_task_items->children[i]->children[j]->types.variable.is_input) + { + label = vtr::strdup(list_of_task_items->children[i]->children[j]->children[0]->types.identifier); + var_node = newVarDeclare(label, NULL, NULL, NULL, NULL, NULL, line_number); + var_node->types.variable.is_input = true; + if(list_of_ports) + { + newList_entry(list_of_ports,var_node); + } + else + { + list_of_ports = newList(VAR_DECLARE_LIST, var_node, line_number); + } + } + else if(list_of_task_items->children[i]->children[j]->types.variable.is_output) + { + label = vtr::strdup(list_of_task_items->children[i]->children[j]->children[0]->types.identifier); + var_node = newVarDeclare(label, NULL, NULL, NULL, NULL, NULL, line_number); + var_node->types.variable.is_output = true; + if(list_of_ports) + { + newList_entry(list_of_ports,var_node); + } + else + { + list_of_ports = newList(VAR_DECLARE_LIST, var_node, line_number); + } + } + else if(list_of_task_items->children[i]->children[j]->types.variable.is_inout) + { + label = vtr::strdup(list_of_task_items->children[i]->children[j]->children[0]->types.identifier); + var_node = newVarDeclare(label, NULL, NULL, NULL, NULL, NULL, line_number); + var_node->types.variable.is_inout = true; + if(list_of_ports) + { + newList_entry(list_of_ports,var_node); + } + else + { + list_of_ports = newList(VAR_DECLARE_LIST, var_node, line_number); + } + } + } + } + } + + if(list_of_ports) + { + port_declarations = resolve_ports(TASK, list_of_ports); + } + /* ports are expected to be in module items */ + if (port_declarations) + { + add_child_to_node_at_index(list_of_task_items, port_declarations, 0); + } + + /* allocate child nodes to this node */ + allocate_children_to_node(new_node, { symbol_node, list_of_ports, list_of_task_items }); + + /* store the list of tasks and functions this task instantiates */ + new_node->types.task.task_instantiations_instance = task_instantiations_instance; + new_node->types.task.size_task_instantiations = size_task_instantiations; + new_node->types.task.is_instantiated = false; + + new_node->types.function.function_instantiations_instance = function_instantiations_instance; + new_node->types.function.size_function_instantiations = size_function_instantiations; + new_node->types.function.is_instantiated = false; + + /* record this module in the list of modules (for evaluation later in terms of just nodes) */ + ast_tasks = (ast_node_t **)vtr::realloc(ast_tasks, sizeof(ast_node_t*)*(num_tasks+1)); + ast_tasks[num_tasks] = new_node; + + sc_spot = sc_add_string(module_names_to_idx, task_name); + if (module_names_to_idx->data[sc_spot] != NULL) + { + error_message(PARSE_ERROR, line_number, current_parse_file, "task names with the same name -> %s\n", task_name); + } + + /* store the data which is an idx here */ + module_names_to_idx->data[sc_spot] = (void*)new_node; + + /* now that we've bottom up built the parse tree for this task, go to the next task */ + next_task(); + + return new_node; + +} + +/*--------------------------------------------------------------------------------------------- + * (function: next_task) + *-------------------------------------------------------------------------------------------*/ +void next_task() +{ + num_tasks++; + + /* define the string cache for the next task */ + // task_parameters_sc = (STRING_CACHE**)vtr::realloc(task_parameters_sc, sizeof(STRING_CACHE*)*(num_tasks+1)); + // task_parameters_sc[num_tasks] = sc_new_string_cache(); + + /* create a new list for the instantiations list */ + task_instantiations_instance = NULL; + size_task_instantiations = 0; + + /* old ones are done so clean */ + sc_free_string_cache(tasks_inputs_sc); + sc_free_string_cache(tasks_outputs_sc); + /* make for next task */ + tasks_inputs_sc = sc_new_string_cache(); + tasks_outputs_sc = sc_new_string_cache(); +} /*--------------------------------------------------------------------------------------------- * (function: next_function) *-------------------------------------------------------------------------------------------*/ diff --git a/ODIN_II/SRC/verilog_bison.y b/ODIN_II/SRC/verilog_bison.y index c01f2a538aa..6131ff40a2f 100644 --- a/ODIN_II/SRC/verilog_bison.y +++ b/ODIN_II/SRC/verilog_bison.y @@ -51,8 +51,8 @@ int yylex(void); } %token vSYMBOL_ID %token vNUMBER vDELAY_ID -%token vALWAYS vINITIAL vSPECIFY vAND vASSIGN vBEGIN vCASE vDEFAULT vDEFINE vELSE vEND vENDCASE -%token vENDMODULE vENDSPECIFY vENDGENERATE vENDFUNCTION vIF vINOUT vINPUT vMODULE vGENERATE vFUNCTION +%token vALWAYS vAUTOMATIC vINITIAL vSPECIFY vAND vASSIGN vBEGIN vCASE vDEFAULT vDEFINE vELSE vEND vENDCASE vEMPTY +%token vENDMODULE vENDSPECIFY vENDGENERATE vENDFUNCTION vENDTASK vIF vINOUT vINPUT vMODULE vGENERATE vFUNCTION vTASK %token vOUTPUT vPARAMETER vLOCALPARAM vPOSEDGE vXNOR vXOR vDEFPARAM voANDAND vNAND vNEGEDGE vNOR vNOT vOR vFOR %token voOROR voLTE voGTE voPAL voSLEFT voSRIGHT voASRIGHT voEQUAL voNOTEQUAL voCASEEQUAL %token voCASENOTEQUAL voXNOR voNAND voNOR vWHILE vINTEGER vCLOG2 vGENVAR @@ -97,20 +97,21 @@ int yylex(void); %nonassoc vELSE %type wire_types reg_types net_types net_direction -%type source_text item items module list_of_module_items list_of_function_items module_item function_item module_parameters module_ports -%type list_of_parameter_declaration parameter_declaration specparam_declaration list_of_port_declaration port_declaration -%type defparam_declaration defparam_variable_list defparam_variable function_declaration function_input_declaration -%type io_declaration variable_list function_output_variable function_id_and_output_variable +%type source_text item items module list_of_module_items list_of_task_items list_of_function_items module_item function_item task_item module_parameters module_ports +%type list_of_parameter_declaration parameter_declaration task_parameter_declaration specparam_declaration list_of_port_declaration port_declaration +%type defparam_declaration defparam_variable_list defparam_variable function_declaration function_port_list list_of_function_inputs function_input_declaration +%type task_declaration task_input_declaration task_output_declaration task_inout_declaration +%type io_declaration variable_list function_return list_of_function_return_variable function_return_variable function_integer_declaration %type integer_type_variable_list variable integer_type_variable -%type net_declaration integer_declaration function_instantiation genvar_declaration -%type continuous_assign multiple_inputs_gate_instance list_of_single_input_gate_declaration_instance +%type net_declaration integer_declaration function_instantiation task_instantiation genvar_declaration +%type procedural_continuous_assignment multiple_inputs_gate_instance list_of_single_input_gate_declaration_instance %type list_of_multiple_inputs_gate_declaration_instance list_of_module_instance %type gate_declaration single_input_gate_instance -%type module_instantiation module_instance function_instance list_of_module_connections list_of_function_connections +%type module_instantiation module_instance function_instance task_instance list_of_module_connections list_of_function_connections list_of_task_connections %type list_of_multiple_inputs_gate_connections -%type module_connection always statement function_statement blocking_assignment -%type non_blocking_assignment conditional_statement case_statement case_item_list case_items seq_block -%type stmt_list delay_control event_expression_list event_expression loop_statement +%type module_connection tf_connection always statement function_statement function_statement_items task_statement blocking_assignment +%type non_blocking_assignment conditional_statement function_conditional_statement case_statement function_case_statement case_item_list function_case_item_list case_items function_case_items seq_block function_seq_block +%type stmt_list function_stmt_list delay_control event_expression_list event_expression loop_statement function_loop_statement %type expression primary expression_list module_parameter %type list_of_module_parameters localparam_declaration %type specify_block list_of_specify_items @@ -197,43 +198,54 @@ list_of_generate_block_items: ; generate_item: - localparam_declaration {$$ = $1;} - | net_declaration {$$ = $1;} - | genvar_declaration {$$ = $1;} - | integer_declaration {$$ = $1;} - | continuous_assign {$$ = $1;} - | gate_declaration {$$ = $1;} - | module_instantiation {$$ = $1;} - | function_declaration {$$ = $1;} - | initial_block {$$ = $1;} - | always {$$ = $1;} - | defparam_declaration {$$ = $1;} - | c_function ';' {$$ = $1;} - | if_generate_construct {$$ = $1;} - | case_generate_construct {$$ = $1;} - | loop_generate_construct {$$ = $1;} + localparam_declaration {$$ = $1;} + | net_declaration {$$ = $1;} + | genvar_declaration {$$ = $1;} + | integer_declaration {$$ = $1;} + | procedural_continuous_assignment {$$ = $1;} + | gate_declaration {$$ = $1;} + | module_instantiation {$$ = $1;} + | function_declaration {$$ = $1;} + | task_declaration {$$ = $1;} + | initial_block {$$ = $1;} + | always {$$ = $1;} + | defparam_declaration {$$ = $1;} + | c_function ';' {$$ = $1;} + | if_generate_construct {$$ = $1;} + | case_generate_construct {$$ = $1;} + | loop_generate_construct {$$ = $1;} ; generate_block_item: - generate_localparam_declaration {$$ = $1;} - | net_declaration {$$ = $1;} - | genvar_declaration {$$ = $1;} - | integer_declaration {$$ = $1;} - | continuous_assign {$$ = $1;} - | gate_declaration {$$ = $1;} - | module_instantiation {$$ = $1;} - | function_declaration {$$ = $1;} - | initial_block {$$ = $1;} - | always {$$ = $1;} - | generate_defparam_declaration {$$ = $1;} - | c_function ';' {$$ = $1;} - | if_generate_construct {$$ = $1;} - | case_generate_construct {$$ = $1;} - | loop_generate_construct {$$ = $1;} + generate_localparam_declaration {$$ = $1;} + | net_declaration {$$ = $1;} + | genvar_declaration {$$ = $1;} + | integer_declaration {$$ = $1;} + | procedural_continuous_assignment {$$ = $1;} + | gate_declaration {$$ = $1;} + | module_instantiation {$$ = $1;} + | function_declaration {$$ = $1;} + | initial_block {$$ = $1;} + | always {$$ = $1;} + | generate_defparam_declaration {$$ = $1;} + | c_function ';' {$$ = $1;} + | if_generate_construct {$$ = $1;} + | case_generate_construct {$$ = $1;} + | loop_generate_construct {$$ = $1;} ; function_declaration: - vFUNCTION function_output_variable ';' list_of_function_items vENDFUNCTION {$$ = newFunction($2, $4, my_yylineno); } + vFUNCTION function_return ';' list_of_function_items vENDFUNCTION {$$ = newFunction($2, NULL, $4, my_yylineno, false);} + | vFUNCTION vAUTOMATIC function_return ';' list_of_function_items vENDFUNCTION {$$ = newFunction($3, NULL, $5, my_yylineno, true);} + | vFUNCTION function_return function_port_list ';' list_of_function_items vENDFUNCTION {$$ = newFunction($2, $3, $5, my_yylineno, false);} + | vFUNCTION vAUTOMATIC function_return function_port_list ';' list_of_function_items vENDFUNCTION {$$ = newFunction($3, $4, $6, my_yylineno, true);} + ; + +task_declaration: + vTASK vSYMBOL_ID ';' list_of_task_items vENDTASK {$$ = newTask($2, NULL, $4, my_yylineno, false);} + | vTASK vSYMBOL_ID module_ports ';' list_of_task_items vENDTASK {$$ = newTask($2, $3, $5, my_yylineno, false);} + | vTASK vAUTOMATIC vSYMBOL_ID ';' list_of_task_items vENDTASK {$$ = newTask($3, NULL, $5, my_yylineno, true);} + | vTASK vAUTOMATIC vSYMBOL_ID module_ports ';' list_of_task_items vENDTASK {$$ = newTask($3, $4, $6, my_yylineno, true);} ; initial_block: @@ -260,20 +272,57 @@ list_of_function_items: | function_item {$$ = newList(FUNCTION_ITEMS, $1, my_yylineno);} ; +task_input_declaration: + vINPUT net_declaration {$$ = markAndProcessSymbolListWith(TASK,INPUT, $2, false);} + | vINPUT integer_declaration {$$ = markAndProcessSymbolListWith(TASK,INPUT, $2, true);} + | vINPUT vSIGNED variable_list ';' {$$ = markAndProcessSymbolListWith(TASK,INPUT, $3, true);} + | vINPUT variable_list ';' {$$ = markAndProcessSymbolListWith(TASK,INPUT, $2, false);} + ; + +task_output_declaration: + vOUTPUT net_declaration {$$ = markAndProcessSymbolListWith(TASK,OUTPUT, $2, false);} + | vOUTPUT integer_declaration {$$ = markAndProcessSymbolListWith(TASK,OUTPUT, $2, true);} + | vOUTPUT vSIGNED variable_list ';' {$$ = markAndProcessSymbolListWith(TASK,OUTPUT, $3, true);} + | vOUTPUT variable_list ';' {$$ = markAndProcessSymbolListWith(TASK,OUTPUT, $2, false);} + ; + +task_inout_declaration: + vINOUT net_declaration {$$ = markAndProcessSymbolListWith(TASK,INOUT, $2, false);} + | vINOUT integer_declaration {$$ = markAndProcessSymbolListWith(TASK,INOUT, $2, true);} + | vINOUT vSIGNED variable_list ';' {$$ = markAndProcessSymbolListWith(TASK,INOUT, $3, true);} + | vINOUT variable_list ';' {$$ = markAndProcessSymbolListWith(TASK,INOUT, $2, false);} + ; + +list_of_task_items: + list_of_task_items task_item {$$ = newList_entry($1, $2); } + | task_item {$$ = newList(TASK_ITEMS, $1, my_yylineno); } + ; + function_item: parameter_declaration {$$ = $1;} | function_input_declaration {$$ = $1;} | net_declaration {$$ = $1;} - | integer_declaration {$$ = $1;} - | continuous_assign {$$ = $1;} + | function_integer_declaration ';' {$$ = $1;} | defparam_declaration {$$ = $1;} - | function_statement {$$ = $1;} //TODO It`s temporary + | function_statement {$$ = $1;} | error ';' {$$ = NULL;} ; +task_item: + task_parameter_declaration {$$ = $1;} + | task_input_declaration {$$ = $1;} + | task_output_declaration {$$ = $1;} + | task_inout_declaration {$$ = $1;} + | net_declaration {$$ = $1;} + | integer_declaration {$$ = $1;} + | defparam_declaration {$$ = $1;} + | task_statement {$$ = $1;} + ; + function_input_declaration: vINPUT vSIGNED variable_list ';' {$$ = markAndProcessSymbolListWith(FUNCTION, INPUT, $3, true);} | vINPUT variable_list ';' {$$ = markAndProcessSymbolListWith(FUNCTION, INPUT, $2, false);} + | vINPUT function_integer_declaration ';' {$$ = markAndProcessSymbolListWith(FUNCTION, INPUT, $2, false);} ; parameter_declaration: @@ -281,6 +330,11 @@ parameter_declaration: | vPARAMETER variable_list ';' {$$ = markAndProcessSymbolListWith(MODULE,PARAMETER, $2, false);} ; +task_parameter_declaration: + vPARAMETER vSIGNED variable_list ';' {$$ = markAndProcessSymbolListWith(TASK,PARAMETER, $3, true);} + | vPARAMETER variable_list ';' {$$ = markAndProcessSymbolListWith(TASK,PARAMETER, $2, false);} + ; + localparam_declaration: vLOCALPARAM vSIGNED variable_list ';' {$$ = markAndProcessSymbolListWith(MODULE,LOCALPARAM, $3, true);} | vLOCALPARAM variable_list ';' {$$ = markAndProcessSymbolListWith(MODULE,LOCALPARAM, $2, false);} @@ -319,15 +373,37 @@ genvar_declaration: vGENVAR integer_type_variable_list ';' {$$ = markAndProcessSymbolListWith(MODULE,GENVAR, $2, true);} ; -function_output_variable: - function_id_and_output_variable {$$ = newList(VAR_DECLARE_LIST, $1, my_yylineno);} +function_return: + list_of_function_return_variable {$$ = markAndProcessSymbolListWith(FUNCTION, OUTPUT, $1, false);} + | vSIGNED list_of_function_return_variable {$$ = markAndProcessSymbolListWith(FUNCTION, OUTPUT, $2, true);} + | function_integer_declaration {$$ = markAndProcessSymbolListWith(FUNCTION, OUTPUT, $1, false);} //might need to pass true, but signed ports do not work + ; + +list_of_function_return_variable: + function_return_variable {$$ = newList(VAR_DECLARE_LIST, $1, my_yylineno);} + ; + +function_return_variable: + vSYMBOL_ID {$$ = newVarDeclare($1, NULL, NULL, NULL, NULL, NULL, my_yylineno);} + | '[' expression ':' expression ']' vSYMBOL_ID {$$ = newVarDeclare($6, $2, $4, NULL, NULL, NULL, my_yylineno);} + ; + + +function_integer_declaration: + vINTEGER integer_type_variable_list {$$ = markAndProcessSymbolListWith(FUNCTION, INTEGER, $2, true);} ; -function_id_and_output_variable: - vSYMBOL_ID {$$ = newVarDeclare($1, NULL, NULL, NULL, NULL, NULL, my_yylineno);} - | '[' expression ':' expression ']' vSYMBOL_ID {$$ = newVarDeclare($6, $2, $4, NULL, NULL, NULL, my_yylineno);} +function_port_list: + '(' list_of_function_inputs ')' {$$ = $2;} + | '(' list_of_function_inputs ',' ')' {$$ = $2;} + | '(' ')' {$$ = NULL;} ; +list_of_function_inputs: + list_of_function_inputs ',' function_input_declaration {$$ = newList_entry($1, $3);} + | function_input_declaration {$$ = newList(VAR_DECLARE_LIST, $1, my_yylineno);} + ; + variable_list: variable_list ',' variable {$$ = newList_entry($1, $3);} | variable {$$ = newList(VAR_DECLARE_LIST, $1, my_yylineno);} @@ -362,7 +438,7 @@ integer_type_variable: | vSYMBOL_ID '=' primary {$$ = newIntegerTypeVarDeclare($1, NULL, NULL, NULL, NULL, $3, my_yylineno);} // ONLY FOR PARAMETER ; -continuous_assign: +procedural_continuous_assignment: vASSIGN list_of_blocking_assignment ';' {$$ = $2;} ; @@ -411,9 +487,15 @@ module_instantiation: vSYMBOL_ID list_of_module_instance ';' {$$ = newModuleInstance($1, $2, my_yylineno);} ; +task_instantiation: + vSYMBOL_ID '(' task_instance ')' ';' {$$ = newTaskInstance($1, $3, NULL, my_yylineno);} + | vSYMBOL_ID '(' ')' ';' {$$ = newTaskInstance($1, NULL, NULL, my_yylineno);} + | '#' '(' list_of_module_parameters ')' vSYMBOL_ID '(' task_instance ')' ';' {$$ = newTaskInstance($5, $7, $3, my_yylineno);} + | '#' '(' list_of_module_parameters ')' vSYMBOL_ID '(' ')' ';' {$$ = newTaskInstance($5, NULL, $3, my_yylineno);} + list_of_module_instance: list_of_module_instance ',' module_instance {$$ = newList_entry($1, $3);} - |module_instance {$$ = newList(ONE_MODULE_INSTANCE, $1, my_yylineno);} + | module_instance {$$ = newList(ONE_MODULE_INSTANCE, $1, my_yylineno);} ; // 4 Function Instantiations @@ -421,6 +503,11 @@ list_of_module_instance: vSYMBOL_ID function_instance {$$ = newFunctionInstance($1, $2, my_yylineno);} ; +// 4 Task Instantiations +task_instance: + list_of_task_connections {$$ = newTaskNamedInstance($1, my_yylineno);} + ; + function_instance: '(' list_of_function_connections ')' {$$ = newFunctionNamedInstance($2, NULL, my_yylineno);} ; @@ -433,17 +520,29 @@ module_instance: ; list_of_function_connections: - list_of_function_connections ',' module_connection {$$ = newList_entry($1, $3);} - | module_connection {$$ = newfunctionList(MODULE_CONNECT_LIST, $1, my_yylineno);} + list_of_function_connections ',' tf_connection {$$ = newList_entry($1, $3);} + | tf_connection {$$ = newfunctionList(MODULE_CONNECT_LIST, $1, my_yylineno);} + ; + +list_of_task_connections: + list_of_task_connections ',' tf_connection {$$ = newList_entry($1, $3);} + | tf_connection {$$ = newList(MODULE_CONNECT_LIST, $1, my_yylineno);} ; list_of_module_connections: list_of_module_connections ',' module_connection {$$ = newList_entry($1, $3);} + | list_of_module_connections ',' {$$ = newList_entry($1, newModuleConnection(NULL, NULL, my_yylineno));} | module_connection {$$ = newList(MODULE_CONNECT_LIST, $1, my_yylineno);} ; +tf_connection: + '.' vSYMBOL_ID '(' expression ')' {$$ = newModuleConnection($2, $4, my_yylineno);} + | expression {$$ = newModuleConnection(NULL, $1, my_yylineno);} + ; + module_connection: '.' vSYMBOL_ID '(' expression ')' {$$ = newModuleConnection($2, $4, my_yylineno);} + | '.' vSYMBOL_ID '(' ')' {$$ = newModuleConnection($2, NULL, my_yylineno);} | expression {$$ = newModuleConnection(NULL, $1, my_yylineno);} ; @@ -497,20 +596,51 @@ generate_block: ; function_statement: - statement {$$ = newAlways(NULL, $1, my_yylineno);} + function_statement_items {$$ = newStatement($1, my_yylineno);} + ; + +task_statement: + statement {$$ = newStatement($1, my_yylineno);} ; statement: seq_block {$$ = $1;} + | task_instantiation {$$ = $1;} | c_function ';' {$$ = $1;} | blocking_assignment ';' {$$ = $1;} | non_blocking_assignment ';' {$$ = $1;} + | procedural_continuous_assignment {$$ = $1;} | conditional_statement {$$ = $1;} | case_statement {$$ = $1;} | loop_statement {$$ = newList(BLOCK, $1, my_yylineno);} | ';' {$$ = NULL;} ; +function_statement_items: + function_seq_block {$$ = $1;} + | c_function ';' {$$ = $1;} + | blocking_assignment ';' {$$ = $1;} + | function_conditional_statement {$$ = $1;} + | function_case_statement {$$ = $1;} + | function_loop_statement {$$ = newList(BLOCK, $1, my_yylineno);} + | ';' {$$ = NULL;} + ; + +function_seq_block: + vBEGIN function_stmt_list vEND {$$ = $2;} + | vBEGIN ':' vSYMBOL_ID function_stmt_list vEND {free($3); $$ = $4;} + ; + +function_stmt_list: + function_stmt_list function_statement_items {$$ = newList_entry($1, $2);} + | function_statement_items {$$ = newList(BLOCK, $1, my_yylineno);} + ; + +function_loop_statement: + vFOR '(' blocking_assignment ';' expression ';' blocking_assignment ')' function_statement_items {$$ = newFor($3, $5, $7, $9, my_yylineno);} + | vWHILE '(' expression ')' function_statement_items {$$ = newWhile($3, $5, my_yylineno);} + ; + loop_statement: vFOR '(' blocking_assignment ';' expression ';' blocking_assignment ')' statement {$$ = newFor($3, $5, $7, $9, my_yylineno);} | vWHILE '(' expression ')' statement {$$ = newWhile($3, $5, my_yylineno);} @@ -520,6 +650,15 @@ case_statement: vCASE '(' expression ')' case_item_list vENDCASE {$$ = newCase($3, $5, my_yylineno);} ; +function_case_statement: + vCASE '(' expression ')' function_case_item_list vENDCASE {$$ = newCase($3, $5, my_yylineno);} + ; + +function_conditional_statement: + vIF '(' expression ')' function_statement_items %prec LOWER_THAN_ELSE {$$ = newIf($3, $5, NULL, my_yylineno);} + | vIF '(' expression ')' function_statement_items vELSE function_statement_items {$$ = newIf($3, $5, $7, my_yylineno);} + ; + conditional_statement: vIF '(' expression ')' statement %prec LOWER_THAN_ELSE {$$ = newIf($3, $5, NULL, my_yylineno);} | vIF '(' expression ')' statement vELSE statement {$$ = newIf($3, $5, $7, my_yylineno);} @@ -541,11 +680,21 @@ case_item_list: | case_items {$$ = newList(CASE_LIST, $1, my_yylineno);} ; +function_case_item_list: + function_case_item_list function_case_items {$$ = newList_entry($1, $2);} + | function_case_items {$$ = newList(CASE_LIST, $1, my_yylineno);} + ; + +function_case_items: + expression ':' function_statement_items {$$ = newCaseItem($1, $3, my_yylineno);} + | vDEFAULT ':' function_statement_items {$$ = newDefaultCase($3, my_yylineno);} + ; + case_items: expression ':' statement {$$ = newCaseItem($1, $3, my_yylineno);} | vDEFAULT ':' statement {$$ = newDefaultCase($3, my_yylineno);} ; - + seq_block: vBEGIN stmt_list vEND {$$ = $2;} | vBEGIN ':' vSYMBOL_ID stmt_list vEND {$$ = newLabelledBlock($3, $4);} diff --git a/ODIN_II/SRC/verilog_flex.l b/ODIN_II/SRC/verilog_flex.l index e40133d6002..02d7b0ebd88 100644 --- a/ODIN_II/SRC/verilog_flex.l +++ b/ODIN_II/SRC/verilog_flex.l @@ -169,6 +169,7 @@ vPUNCT [\?\:\|\^\&\<\>\-\*\/\%\(\)\{\}\[\]\~\!\;\#\,\.\@\=\+] "always" { MP(); return vALWAYS;} "and" { MP(); return vAND;} "assign" { MP(); return vASSIGN;} +"automatic" { MP(); return vAUTOMATIC;} "begin" { MP(); return vBEGIN;} "case" { MP(); return vCASE;} "default" { MP(); return vDEFAULT;} @@ -180,6 +181,7 @@ vPUNCT [\?\:\|\^\&\<\>\-\*\/\%\(\)\{\}\[\]\~\!\;\#\,\.\@\=\+] "endgenerate" { MP(); return vENDGENERATE;} "endmodule" { MP(); return vENDMODULE;} "endspecify" { MP(); return vENDSPECIFY;} +"endtask" { MP(); return vENDTASK;} "for" { MP(); return vFOR;} "if" { MP(); return vIF;} "initial" { MP(); return vINITIAL;} @@ -201,6 +203,7 @@ vPUNCT [\?\:\|\^\&\<\>\-\*\/\%\(\)\{\}\[\]\~\!\;\#\,\.\@\=\+] "posedge" { MP(); return vPOSEDGE;} "signed" { MP(); return vSIGNED;} "specify" { MP(); return vSPECIFY;} +"task" { MP(); return vTASK;} "while" { MP(); return vWHILE;} "xnor" { MP(); return vXNOR;} "xor" { MP(); return vXOR;} @@ -222,13 +225,11 @@ vPUNCT [\?\:\|\^\&\<\>\-\*\/\%\(\)\{\}\[\]\~\!\;\#\,\.\@\=\+] "reg" { MP(); return netREG;} /* unsupported Keywords */ -"automatic" { UNSUPPORTED_TOKEN;} "buf" { UNSUPPORTED_TOKEN;} "casex" { UNSUPPORTED_TOKEN;} "casez" { UNSUPPORTED_TOKEN;} "disable" { UNSUPPORTED_TOKEN;} "edge" { UNSUPPORTED_TOKEN;} -"endtask" { UNSUPPORTED_TOKEN;} "scalared" { UNSUPPORTED_TOKEN;} "bufif0" { UNSUPPORTED_TOKEN;} "bufif1" { UNSUPPORTED_TOKEN;} @@ -268,7 +269,6 @@ vPUNCT [\?\:\|\^\&\<\>\-\*\/\%\(\)\{\}\[\]\~\!\;\#\,\.\@\=\+] "supply0" { UNSUPPORTED_TOKEN;} "supply1" { UNSUPPORTED_TOKEN;} "table" { UNSUPPORTED_TOKEN;} -"task" { UNSUPPORTED_TOKEN;} "time" { UNSUPPORTED_TOKEN;} "tran" { UNSUPPORTED_TOKEN;} "tranif0" { UNSUPPORTED_TOKEN;} diff --git a/ODIN_II/regression_test/benchmark/task/syntax/task.conf b/ODIN_II/regression_test/benchmark/task/syntax/task.conf index f100b3ef4cf..4c47527a369 100644 --- a/ODIN_II/regression_test/benchmark/task/syntax/task.conf +++ b/ODIN_II/regression_test/benchmark/task/syntax/task.conf @@ -46,4 +46,10 @@ circuit_list_add=ifdef-else-syntax.v circuit_list_add=complex_post_for_loop.v circuit_list_add=inferred_ram_w_clog2.v circuit_list_add=flip_flop_enable_w_begin_label.v - +circuit_list_add=simple_task.v +circuit_list_add=simple_function.v +circuit_list_add=simple_module.v +circuit_list_add=task_automatic.v +circuit_list_add=task_multiple_instances.v +circuit_list_add=function_automatic.v +circuit_list_add=unconnected_input.v \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/_bug/bm_function_1.v b/ODIN_II/regression_test/benchmark/verilog/_bug/bm_function_1.v index b31803d3e52..59185b7324a 100644 --- a/ODIN_II/regression_test/benchmark/verilog/_bug/bm_function_1.v +++ b/ODIN_II/regression_test/benchmark/verilog/_bug/bm_function_1.v @@ -34,7 +34,7 @@ function simple_func; input in3; input in4; - simple_func <= in1[1] & in2[0] | in3 ^ in4; + simple_func = in1[1] & in2[0] | in3 ^ in4; endfunction assign part1 = simple_func(a_in[`BITS-1:0], b_in[`BITS-1:0], c_in[0], d_in[0]) & a_in; diff --git a/ODIN_II/regression_test/benchmark/verilog/_bug/bm_function_2.v b/ODIN_II/regression_test/benchmark/verilog/_bug/bm_function_2.v index 0fd22b08951..882d47be9b4 100644 --- a/ODIN_II/regression_test/benchmark/verilog/_bug/bm_function_2.v +++ b/ODIN_II/regression_test/benchmark/verilog/_bug/bm_function_2.v @@ -35,15 +35,15 @@ function simple_func; input in3; input in4; - simple_func <= in1[0] & in2[0] | in3 ^ in4; + simple_func = in1[0] & in2[0] | in3 ^ in4; endfunction function [`BITS-1:0] simple_func_2; input in3; input in4; begin - simple_func_2[1] <= in3 & in4; - simple_func_2[0] <= in3 | in4; + simple_func_2[1] = in3 & in4; + simple_func_2[0] = in3 | in4; end endfunction diff --git a/ODIN_II/regression_test/benchmark/verilog/_bug/function_hdr.v b/ODIN_II/regression_test/benchmark/verilog/_bug/function_hdr.v new file mode 100644 index 00000000000..99b030c592d --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/_bug/function_hdr.v @@ -0,0 +1,31 @@ +module simple_function ( +clk, +reset, +a, +b, +out, +clk_out +); + +input clk; +input reset; +input [1:0] a,b; + +integer test = 1; +integer output_int; + +output [2:0] out; +output clk_out; + +assign clk_out = clk; + +always @(posedge clk) +begin +output_int = func_out(a,b,reset, test); +end + +assign out = output_int; + +`include "function_hdr.vh" + +endmodule \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/_bug/function_hdr.vh b/ODIN_II/regression_test/benchmark/verilog/_bug/function_hdr.vh new file mode 100644 index 00000000000..561bddd8357 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/_bug/function_hdr.vh @@ -0,0 +1,13 @@ + +function integer func_out; +input [1:0] x, y; +input rst; +input integer test_int; + +case(rst) + 1'b0: func_out = x + y; + default: func_out = test_int; +endcase + + +endfunction diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/function_automatic.v b/ODIN_II/regression_test/benchmark/verilog/syntax/function_automatic.v new file mode 100644 index 00000000000..c58f00283e0 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/function_automatic.v @@ -0,0 +1,35 @@ +module simple_function ( +clk, +reset, +a, +b, +out, +clk_out +); + +input clk; +input reset; +input [1:0] a,b; + +output [2:0] out; +output clk_out; + +assign clk_out = clk; + +always @(posedge clk) +begin +out = func_out(a,b,reset); +end + +function automatic [2:0] func_out; +input [1:0] x, y; +input rst; + +case(rst) + 1'b0: func_out = x + y; + default: func_out = 1'b0; + endcase + +endfunction + +endmodule \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/simple_function.v b/ODIN_II/regression_test/benchmark/verilog/syntax/simple_function.v new file mode 100644 index 00000000000..a2f94da2b6b --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/simple_function.v @@ -0,0 +1,35 @@ +module simple_function ( +clk, +reset, +a, +b, +out, +clk_out +); + +input clk; +input reset; +input [1:0] a,b; + +output [2:0] out; +output clk_out; + +assign clk_out = clk; + +always @(posedge clk) +begin +out = func_out(a,b,reset); +end + +function [2:0] func_out; +input [1:0] x, y; +input rst; + +case(rst) + 1'b0: func_out = x + y; + default: func_out = 1'b0; + endcase + +endfunction + +endmodule \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/simple_module.v b/ODIN_II/regression_test/benchmark/verilog/syntax/simple_module.v new file mode 100644 index 00000000000..bd820bd3e30 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/simple_module.v @@ -0,0 +1,44 @@ +module simple_module ( + clk, + reset, + a, + b, + out, + clk_out + ); + + input clk; + input reset; + input [1:0] a,b; + + output [2:0] out; + output clk_out; + + assign clk_out = clk; + + + xor_task my_mod(.clk(clk), + .x(a), + .y(b), + .rst(reset), + .z(out)); + + + +endmodule + +module xor_task(clk,x,y,rst,z); +input clk; +input [1:0] x,y; +input rst; +output [2:0] z; + +always @(posedge clk) +begin + case(rst) + 1'b0: z <= x + y; + default: z <= 1'b0; + endcase +end + +endmodule diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/simple_task.v b/ODIN_II/regression_test/benchmark/verilog/syntax/simple_task.v new file mode 100644 index 00000000000..29304d345b9 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/simple_task.v @@ -0,0 +1,37 @@ +module simple_task ( + clk, + reset, + a, + b, + out, + clk_out + ); + + input clk; + input reset; + input [1:0] a,b; + + output [2:0] out; + output clk_out; + + assign clk_out = clk; + +always @(posedge clk) +begin + my_task(a,b,reset,out); +end + +task my_task( input [1:0] x,y, input rst, output [2:0] z ); + + + begin + case(rst) + 1'b0: z <= x + y; + default: z <= 1'b0; + endcase + end +endtask + + +endmodule + diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/task_automatic.v b/ODIN_II/regression_test/benchmark/verilog/syntax/task_automatic.v new file mode 100644 index 00000000000..e90cba5553e --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/task_automatic.v @@ -0,0 +1,37 @@ +module simple_task ( + clk, + reset, + a, + b, + out_1, + clk_out + ); + + input clk; + input reset; + input [1:0] a,b; + + output [2:0] out_1; + output clk_out; + + assign clk_out = clk; + +always @(posedge clk) +begin + my_task(a,b,reset,out_1); +end + +task automatic my_task; + + input [1:0] x,y; + input rst; + output [2:0] z; + + case(rst) + 1'b0: z <= x + y; + default: z <= 1'b0; + endcase + +endtask + +endmodule diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/task_multiple_instances.v b/ODIN_II/regression_test/benchmark/verilog/syntax/task_multiple_instances.v new file mode 100644 index 00000000000..8201b341d15 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/task_multiple_instances.v @@ -0,0 +1,40 @@ +module simple_task ( + clk, + reset, + a, + b, + c, + d, + out_1, out_2, + clk_out + ); + + input clk; + input reset; + input [1:0] a,b,c,d; + + output [2:0] out_1, out_2; + output clk_out; + + assign clk_out = clk; + +always @(posedge clk) +begin + my_task(a,b,reset,out_1); + my_task(c,d,reset,out_2); +end + +task my_task; + + input [1:0] x,y; + input rst; + output [2:0] z; + + case(rst) + 1'b0: z <= x + y; + default: z <= 1'b0; + endcase + +endtask + +endmodule diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/unconnected_input.v b/ODIN_II/regression_test/benchmark/verilog/syntax/unconnected_input.v new file mode 100644 index 00000000000..29f5af4098b --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/unconnected_input.v @@ -0,0 +1,37 @@ +module top ( + top_a, + top_c, + top_out +); + +input [2:0] top_a; +input [3:0] top_c; +output [3:0] top_out; + +unconn my_mod(.in_a(top_a), .in_b(), .in_c(top_c), .out(top_out)); + +endmodule + +module unconn ( + in_a, + in_b, + in_c, + out +); + +input [2:0] in_a; +input in_b; +input [3:0] in_c; + +output [3:0] out; + +reg [3:0] a; + +assign a[1:0] = in_a[1:0]; +assign a[3] = in_a[2]; +assign a[2] = in_b; + + +assign out = a & in_c; + +endmodule \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/undeclared_signal.v b/ODIN_II/regression_test/benchmark/verilog/syntax/undeclared_signal.v index 4219b52ef93..33362b10d70 100644 --- a/ODIN_II/regression_test/benchmark/verilog/syntax/undeclared_signal.v +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/undeclared_signal.v @@ -1,4 +1,3 @@ -/* Odin will hot replace undeclared signal module instanciation with a dummy wire */ module top( clk @@ -8,7 +7,13 @@ input clk; testmod x ( .clk(clk), .reset(1'b0), - .a(DoesNotExist) + .a() +); + +testmod y ( + clk, + 1'b0, + ); endmodule