diff --git a/ODIN_II/SRC/ast_elaborate.cpp b/ODIN_II/SRC/ast_elaborate.cpp index 996a2016935..889a90ee660 100644 --- a/ODIN_II/SRC/ast_elaborate.cpp +++ b/ODIN_II/SRC/ast_elaborate.cpp @@ -2656,11 +2656,11 @@ void create_param_table_for_scope(ast_node_t* module_items, sc_hierarchy* local_ /* symbols are already dealt with */ if (var_declare->types.variable.is_input || var_declare->types.variable.is_output + || var_declare->types.variable.is_inout || var_declare->types.variable.is_reg || var_declare->types.variable.is_genvar || var_declare->types.variable.is_wire || var_declare->types.variable.is_defparam) - continue; oassert(module_items->children[i]->children[j]->type == VAR_DECLARE); diff --git a/ODIN_II/SRC/netlist_create_from_ast.cpp b/ODIN_II/SRC/netlist_create_from_ast.cpp index 0b079903659..23f33867ee6 100644 --- a/ODIN_II/SRC/netlist_create_from_ast.cpp +++ b/ODIN_II/SRC/netlist_create_from_ast.cpp @@ -83,7 +83,7 @@ void create_all_driver_nets_in_this_scope(char* instance_name_prefix, sc_hierarc void create_top_driver_nets(ast_node_t* module, char* instance_name_prefix, sc_hierarchy* local_ref); void create_top_output_nodes(ast_node_t* module, char* instance_name_prefix, sc_hierarchy* local_ref); -nnet_t* define_nets_with_driver(ast_node_t* var_declare, char* instance_name_prefix); +void define_nets_with_driver(ast_node_t* var_declare, char* instance_name_prefix); nnet_t* define_nodes_and_nets_with_driver(ast_node_t* var_declare, char* instance_name_prefix); ast_node_t* resolve_top_module_parameters(ast_node_t* node, sc_hierarchy* top_sc_list); ast_node_t* resolve_top_parameters_defined_by_parameters(ast_node_t* node, sc_hierarchy* top_sc_list, int count); @@ -733,6 +733,7 @@ void create_all_driver_nets_in_this_scope(char* instance_name_prefix, sc_hierarc /* use the symbol table to decide if driver */ for (i = 0; i < num_local_symbol_table; i++) { oassert(local_symbol_table[i]->type == VAR_DECLARE || local_symbol_table[i]->type == BLOCKING_STATEMENT); + // TODO InOut if ( /* all registers are drivers */ (local_symbol_table[i]->types.variable.is_reg) @@ -867,6 +868,7 @@ void create_top_output_nodes(ast_node_t* module, char* instance_name_prefix, sc_ /* search the symbol table for outputs */ if (local_symbol_table && num_local_symbol_table > 0) { for (i = 0; i < num_local_symbol_table; i++) { + // TODO InOut if (local_symbol_table[i]->types.variable.is_output) { char* full_name; ast_node_t* var_declare = local_symbol_table[i]; @@ -970,27 +972,27 @@ void create_top_output_nodes(ast_node_t* module, char* instance_name_prefix, sc_ * (function: define_nets_with_driver) * Given a register declaration, this function defines it as a driver. *-------------------------------------------------------------------------------------------*/ -nnet_t* define_nets_with_driver(ast_node_t* var_declare, char* instance_name_prefix) { - int i; - char* temp_string = NULL; - long sc_spot; - nnet_t* new_net = NULL; - +void define_nets_with_driver(ast_node_t* var_declare, char* instance_name_prefix) { if (var_declare->children[0] == NULL || var_declare->type == BLOCKING_STATEMENT) { /* FOR single driver signal since spots 1, 2, 3, 4 are NULL */ - /* create the net */ - new_net = allocate_nnet(); - /* make the string to add to the string cache */ - temp_string = make_full_ref_name(instance_name_prefix, NULL, NULL, var_declare->identifier_node->types.identifier, -1); + char* temp_string = make_full_ref_name(instance_name_prefix, NULL, NULL, var_declare->identifier_node->types.identifier, -1); /* look for that element */ - sc_spot = sc_add_string(output_nets_sc, temp_string); + long sc_spot = sc_add_string(output_nets_sc, temp_string); if (output_nets_sc->data[sc_spot] != NULL) { + if( var_declare->types.variable.is_inout ) { + // Inout may already have been defined + vtr::free(temp_string); + return; + } error_message(NETLIST, var_declare->loc, "Net (%s) with the same name already created\n", temp_string); } + + /* create the net */ + nnet_t* new_net = allocate_nnet(); /* store the data which is an idx here */ output_nets_sc->data[sc_spot] = (void*)new_net; new_net->name = temp_string; @@ -1020,18 +1022,23 @@ nnet_t* define_nets_with_driver(ast_node_t* var_declare, char* instance_name_pre /* This register declaration is a range as opposed to a single bit so we need to define each element */ /* assume digit 1 is largest */ - for (i = min_value; i <= max_value; i++) { - /* create the net */ - new_net = allocate_nnet(); - + for (long i = min_value; i <= max_value; i++) { /* create the string to add to the cache */ - temp_string = make_full_ref_name(instance_name_prefix, NULL, NULL, var_declare->identifier_node->types.identifier, i); + char* temp_string = make_full_ref_name(instance_name_prefix, NULL, NULL, var_declare->identifier_node->types.identifier, i); - sc_spot = sc_add_string(output_nets_sc, temp_string); + long sc_spot = sc_add_string(output_nets_sc, temp_string); if (output_nets_sc->data[sc_spot] != NULL) { + if( var_declare->types.variable.is_inout ) { + // Inout may already have been defined + vtr::free(temp_string); + continue; + } error_message(NETLIST, var_declare->loc, "Net (%s) with the same name already created\n", temp_string); } + + /* create the net */ + nnet_t* new_net = allocate_nnet(); /* store the data which is an idx here */ output_nets_sc->data[sc_spot] = (void*)new_net; new_net->name = temp_string; @@ -1096,8 +1103,6 @@ nnet_t* define_nets_with_driver(ast_node_t* var_declare, char* instance_name_pre create_implicit_memory_block(data_width, address_width, name, instance_name_prefix, var_declare->loc); } - - return new_net; } /*--------------------------------------------------------------------------------------------- @@ -1248,7 +1253,7 @@ void create_symbol_table_for_scope(ast_node_t* module_items, sc_hierarchy* local continue; oassert(var_declare->type == VAR_DECLARE); - oassert((var_declare->types.variable.is_input) || (var_declare->types.variable.is_output) || (var_declare->types.variable.is_reg) || (var_declare->types.variable.is_genvar) || (var_declare->types.variable.is_wire)); + oassert((var_declare->types.variable.is_input) || (var_declare->types.variable.is_output) || (var_declare->types.variable.is_inout) || (var_declare->types.variable.is_reg) || (var_declare->types.variable.is_genvar) || (var_declare->types.variable.is_wire)); if (var_declare->types.variable.is_input && var_declare->types.variable.is_reg) { @@ -1809,15 +1814,7 @@ void connect_module_instantiation_and_alias(short PASS, ast_node_t* module_insta } /* 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 module */ - if (port_size > 1) { - warning_message(NETLIST, module_instance_var_node->loc, "This module port %s[%d] is unused in module %s\n", module_instance_var_node->types.identifier, j, module_node->identifier_node->types.identifier); - } else { - warning_message(NETLIST, module_instance_var_node->loc, "This module port %s is unused in module %s\n", module_instance_var_node->types.identifier, module_node->identifier_node->types.identifier); - } - - } else { + if ((sc_spot_input_old = sc_lookup_string(input_nets_sc, alias_name)) != -1) { /* 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]); @@ -1861,6 +1858,13 @@ void connect_module_instantiation_and_alias(short PASS, ast_node_t* module_insta output_nets_sc->data[sc_spot_output] = (void*)in_net; } } + } else if( !module_var_node->types.variable.is_inout ) { + /* doesn it have to exist since might only be used in module */ + if (port_size > 1) { + warning_message(NETLIST, module_instance_var_node->loc, "This module port %s[%d] is unused in module %s\n", module_instance_var_node->types.identifier, j, module_node->identifier_node->types.identifier); + } else { + warning_message(NETLIST, module_instance_var_node->loc, "This module port %s is unused in module %s\n", module_instance_var_node->types.identifier, module_node->identifier_node->types.identifier); + } } /* IF the designer uses port names then make sure they line up */ @@ -1877,7 +1881,9 @@ void connect_module_instantiation_and_alias(short PASS, ast_node_t* module_insta vtr::free(full_name); vtr::free(alias_name); - } else if (module_var_node->types.variable.is_output) { + } + + if (module_var_node->types.variable.is_output) { /* 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 = NULL; @@ -1912,41 +1918,41 @@ void connect_module_instantiation_and_alias(short PASS, ast_node_t* module_insta } /* check if the instantiation pin exists. */ - if ((sc_spot_output = sc_lookup_string(output_nets_sc, alias_name)) == -1) { - error_message(NETLIST, module_var_node->loc, - "This output (%s) must exist...must be an error\n", alias_name); - } - - /* can already be there */ - 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. */ - nnet_t* output_net = (nnet_t*)output_nets_sc->data[sc_spot_output]; - nnet_t* input_new_net = (nnet_t*)output_nets_sc->data[sc_spot_input_new]; - for (int k = 0; k < output_net->num_driver_pins; k++) { - if (output_net->driver_pins[k] && output_net->driver_pins[k]->node && input_new_net) { - output_net->driver_pins[k]->node->initial_value = input_new_net->initial_value; + if ((sc_spot_output = sc_lookup_string(output_nets_sc, alias_name)) != -1) { + /* can already be there */ + 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. */ + nnet_t* output_net = (nnet_t*)output_nets_sc->data[sc_spot_output]; + nnet_t* input_new_net = (nnet_t*)output_nets_sc->data[sc_spot_input_new]; + for (int k = 0; k < output_net->num_driver_pins; k++) { + if (output_net->driver_pins[k] && output_net->driver_pins[k]->node && input_new_net) { + output_net->driver_pins[k]->node->initial_value = input_new_net->initial_value; + } } - } - /* clean up input_new_net */ - if (!(input_new_net) || !(input_new_net->num_driver_pins)) - input_new_net = free_nnet(input_new_net); + /* clean up input_new_net */ + if (!(input_new_net) || !(input_new_net->num_driver_pins)) + input_new_net = free_nnet(input_new_net); - /* add this alias for the net */ - output_nets_sc->data[sc_spot_input_new] = output_nets_sc->data[sc_spot_output]; + /* add this alias for the net */ + output_nets_sc->data[sc_spot_input_new] = output_nets_sc->data[sc_spot_output]; - /* IF the designer users port names then make sure they line up */ - if (module_instance_list->children[i]->identifier_node != NULL) { - if (strcmp(module_instance_list->children[i]->identifier_node->types.identifier, module_var_node->identifier_node->types.identifier) != 0) { - error_message(NETLIST, module_var_node->loc, - "This module entry does not match up correctly (%s != %s). Odin expects the order of ports to be the same\n", - module_instance_list->children[i]->identifier_node->types.identifier, - module_var_node->identifier_node->types.identifier); + /* IF the designer users port names then make sure they line up */ + if (module_instance_list->children[i]->identifier_node != NULL) { + if (strcmp(module_instance_list->children[i]->identifier_node->types.identifier, module_var_node->identifier_node->types.identifier) != 0) { + error_message(NETLIST, module_var_node->loc, + "This module entry does not match up correctly (%s != %s). Odin expects the order of ports to be the same\n", + module_instance_list->children[i]->identifier_node->types.identifier, + module_var_node->identifier_node->types.identifier); + } } + } else if (!module_var_node->types.variable.is_inout) { + error_message(NETLIST, module_var_node->loc, + "This output (%s) must exist...must be an error\n", alias_name); } vtr::free(full_name); @@ -2004,6 +2010,7 @@ signal_list_t* connect_function_instantiation_and_alias(short PASS, ast_node_t* if (i > 0) module_instance_var_node = module_instance_list->children[i]->children[0]; + // TODO InOuts if ( // skip inputs on pass 1 ((PASS == INSTANTIATE_DRIVERS) && (module_var_node->types.variable.is_input)) @@ -2070,6 +2077,7 @@ signal_list_t* connect_function_instantiation_and_alias(short PASS, ast_node_t* error_message(NETLIST, module_var_node->children[4]->loc, "%s\n", "Unhandled implicit memory in connect_module_instantiation_and_alias"); } for (j = 0; j < port_size; j++) { + // TODO InOut if (i > 0 && module_var_node->types.variable.is_input) { /* IF - this spot in the module 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) @@ -2306,6 +2314,7 @@ signal_list_t* connect_task_instantiation_and_alias(short PASS, ast_node_t* task ast_node_t* task_var_node = task_list->children[i]; ast_node_t* task_instance_var_node = task_instance_list->children[i]->children[0]; + // TODO InOuts if ( // skip inputs on pass 1 ((PASS == INSTANTIATE_DRIVERS) && (task_var_node->types.variable.is_input)) @@ -2371,6 +2380,7 @@ signal_list_t* connect_task_instantiation_and_alias(short PASS, ast_node_t* task /* Implicit memory */ error_message(NETLIST, task_var_node->children[4]->loc, "%s\n", "Unhandled implicit memory in connect_task_instantiation_and_alias"); } + // TODO InOuts 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 diff --git a/ODIN_II/SRC/netlist_utils.cpp b/ODIN_II/SRC/netlist_utils.cpp index 66b86b7e48a..1fd26a32c49 100644 --- a/ODIN_II/SRC/netlist_utils.cpp +++ b/ODIN_II/SRC/netlist_utils.cpp @@ -296,7 +296,8 @@ nnet_t* allocate_nnet() { *-------------------------------------------------------------------------------------------*/ nnet_t* free_nnet(nnet_t* to_free) { if (to_free) { - to_free->fanout_pins = (npin_t**)vtr::free(to_free->fanout_pins); + if (to_free->num_fanout_pins) + to_free->fanout_pins = (npin_t**)vtr::free(to_free->fanout_pins); if (to_free->name) vtr::free(to_free->name); @@ -417,13 +418,13 @@ void add_driver_pin_to_net(nnet_t* net, npin_t* pin) { * The lasting one is input, and output disappears *-------------------------------------------------------------------------------------------*/ void combine_nets(nnet_t* output_net, nnet_t* input_net, netlist_t* netlist) { + /* in case there are any fanouts in output net (should only be zero and one nodes) */ + join_nets(input_net, output_net); /* copy the driver over to the new_net */ for (int i = 0; i < output_net->num_driver_pins; i++) { /* IF - there is a pin assigned to this net, then copy it */ add_driver_pin_to_net(input_net, output_net->driver_pins[i]); } - /* in case there are any fanouts in output net (should only be zero and one nodes) */ - join_nets(input_net, output_net); /* mark that this is combined */ input_net->combined = true; @@ -465,11 +466,27 @@ void join_nets(nnet_t* join_to_net, nnet_t* other_net) { } error_message(NETLIST, unknown_location, "%s", "Found a combinational loop"); - } else if (other_net->num_driver_pins > 1) { - if (other_net->name && join_to_net->name) - error_message(NETLIST, unknown_location, "Tried to join net %s to %s but this would lose %d drivers for net %s", other_net->name, join_to_net->name, other_net->num_driver_pins - 1, other_net->name); - else - error_message(NETLIST, unknown_location, "Tried to join nets but this would lose %d drivers", other_net->num_driver_pins - 1); + } else if (other_net->num_driver_pins > 1 && join_to_net->num_driver_pins != 0) { + bool drivers_match = true; + if(other_net->num_driver_pins == join_to_net->num_driver_pins) { + for (int i = 0; drivers_match && i < other_net->num_driver_pins; i++) + { + bool driver_match = false; + for (int j = 0; !driver_match && j < join_to_net->num_driver_pins; j++) + { + driver_match = join_to_net->driver_pins[j] == other_net->driver_pins[i]; + } + drivers_match &= driver_match; + } + } + // Either we tried to eliminate a buffer into a net with multiple drivers + // or we tried to combine nets that already had mismatching drivers + if(!drivers_match) { + if (other_net->name && join_to_net->name) + error_message(NETLIST, unknown_location, "Tried to join net %s to %s but this would lose %d drivers for net %s", other_net->name, join_to_net->name, other_net->num_driver_pins - 1, other_net->name); + else + error_message(NETLIST, unknown_location, "Tried to join nets but this would lose %d drivers", other_net->num_driver_pins - 1); + } } /* copy the driver over to the new_net */ diff --git a/ODIN_II/SRC/output_blif.cpp b/ODIN_II/SRC/output_blif.cpp index 1b7c8702349..9631aa72bf4 100644 --- a/ODIN_II/SRC/output_blif.cpp +++ b/ODIN_II/SRC/output_blif.cpp @@ -65,25 +65,24 @@ static bool warn_undriven(nnode_t* node, nnet_t* net) { return false; } -// TODO Uncomment this for In Outs -//static void merge_with_inputs(nnode_t* node, long pin_idx) { -// oassert(pin_idx < node->num_input_pins); -// nnet_t* net = node->input_pins[pin_idx]->net; -// warn_undriven(node, net); -// // Merge node with all inputs with fanout of 1 -// if (net->num_fanout_pins <= 1) { -// for (int i = 0; i < net->num_driver_pins; i++) { -// npin_t* driver = net->driver_pins[i]; -// if (driver->name != NULL && ((driver->node->type == MULTIPLY) || (driver->node->type == HARD_IP) || (driver->node->type == MEMORY) || (driver->node->type == ADD) || (driver->node->type == MINUS))) { -// vtr::free(driver->name); -// driver->name = vtr::strdup(node->name); -// } else { -// vtr::free(driver->node->name); -// driver->node->name = vtr::strdup(node->name); -// } -// } -// } -//} +static void merge_with_inputs(nnode_t* node, long pin_idx) { + oassert(pin_idx < node->num_input_pins); + nnet_t* net = node->input_pins[pin_idx]->net; + warn_undriven(node, net); + // Merge node with all inputs with fanout of 1 + if (net->num_fanout_pins <= 1) { + for (int i = 0; i < net->num_driver_pins; i++) { + npin_t* driver = net->driver_pins[i]; + if (driver->name != NULL && ((driver->node->type == MULTIPLY) || (driver->node->type == HARD_IP) || (driver->node->type == MEMORY) || (driver->node->type == ADD) || (driver->node->type == MINUS))) { + vtr::free(driver->name); + driver->name = vtr::strdup(node->name); + } else { + vtr::free(driver->node->name); + driver->node->name = vtr::strdup(node->name); + } + } + } +} static void print_net_driver(FILE* out, nnode_t* node, nnet_t* net, long driver_idx) { oassert(driver_idx < net->num_driver_pins); @@ -133,21 +132,27 @@ static void print_output_pin(FILE* out, nnode_t* node) { fprintf(out, " %s", node->name); } +static char* buffer_multi_drivers(FILE* out, nnode_t* node, long pin_idx) +{ + nnet_t* net = node->input_pins[pin_idx]->net; + if (net->num_driver_pins > 1) { + char* name = op_node_name(BUF_NODE, node->name); + // Assign each driver to the implicit buffer + for (int j = 0; j < net->num_driver_pins; j++) { + fprintf(out, ".names"); + print_net_driver(out, node, net, j); + fprintf(out, " %s\n1 1\n\n", name); + } + return name; + } + return NULL; +} + static void print_dot_names_header(FILE* out, nnode_t* node) { char** names = (char**)vtr::calloc(node->num_input_pins, sizeof(char*)); - // Create an implicit buffer if there are multiple drivers to the component for (int i = 0; i < node->num_input_pins; i++) { - nnet_t* input_net = node->input_pins[i]->net; - if (input_net->num_driver_pins > 1) { - names[i] = op_node_name(BUF_NODE, node->name); - // Assign each driver to the implicit buffer - for (int j = 0; j < input_net->num_driver_pins; j++) { - fprintf(out, ".names"); - print_net_driver(out, node, input_net, j); - fprintf(out, " %s\n1 1\n\n", names[i]); - } - } + names[i] = buffer_multi_drivers(out, node, i); } // Print the actual header @@ -221,14 +226,13 @@ void output_blif(FILE* out, netlist_t* netlist) { fprintf(out, "\n.names gnd\n.names unconn\n.names vcc\n1\n"); fprintf(out, "\n"); - // TODO Uncomment this for In Outs // connect all the outputs up to the last gate - // for (long i = 0; i < netlist->num_top_output_nodes; i++) { - // nnode_t* node = netlist->top_output_nodes[i]; - // for (int j = 0; j < node->num_input_pins; j++) { - // merge_with_inputs(node, j); - // } - // } + for (long i = 0; i < netlist->num_top_output_nodes; i++) { + nnode_t* node = netlist->top_output_nodes[i]; + for (int j = 0; j < node->num_input_pins; j++) { + merge_with_inputs(node, j); + } + } /* traverse the internals of the flat net-list */ if (strcmp(configuration.output_type.c_str(), "blif") == 0) { @@ -241,8 +245,7 @@ void output_blif(FILE* out, netlist_t* netlist) { for (long i = 0; i < netlist->num_top_output_nodes; i++) { nnode_t* node = netlist->top_output_nodes[i]; - // TODO Change this to > 1 for In Outs - if (node->input_pins[0]->net->num_fanout_pins > 0) { + if (node->input_pins[0]->net->num_fanout_pins > 1) { nnet_t* net = node->input_pins[0]->net; warn_undriven(node, net); for (int j = 0; j < net->num_driver_pins; j++) { @@ -541,14 +544,18 @@ void define_ff(nnode_t* node, FILE* out) { // grab the edge sensitivity of the flip flop const char* edge_type_str = edge_type_blif_str(node); - std::string input; - std::string output; - std::string clock_driver; + char* input_driver = buffer_multi_drivers(out, node, 0); fprintf(out, ".latch"); /* input */ - print_input_single_driver(out, node, 0); + if(!input_driver) + print_input_single_driver(out, node, 0); + else { + // Use the implicit buffer we created before + fprintf(out, " %s", input_driver); + vtr::free(input_driver); + } /* output */ print_output_pin(out, node); @@ -556,6 +563,7 @@ void define_ff(nnode_t* node, FILE* out) { /* sensitivity */ fprintf(out, " %s", edge_type_str); + // TODO Should clocks support mutliple drivers? /* clock */ print_input_single_driver(out, node, 1); diff --git a/ODIN_II/SRC/parse_making_ast.cpp b/ODIN_II/SRC/parse_making_ast.cpp index c8f08bac2c7..f8da41913f1 100644 --- a/ODIN_II/SRC/parse_making_ast.cpp +++ b/ODIN_II/SRC/parse_making_ast.cpp @@ -45,14 +45,17 @@ //for module STRING_CACHE* modules_inputs_sc; STRING_CACHE* modules_outputs_sc; +STRING_CACHE* modules_inouts_sc; STRING_CACHE* module_instances_sc; //for function STRING_CACHE* functions_inputs_sc; STRING_CACHE* functions_outputs_sc; +STRING_CACHE* functions_inouts_sc; STRING_CACHE* tasks_inputs_sc; STRING_CACHE* tasks_outputs_sc; +STRING_CACHE* tasks_inouts_sc; STRING_CACHE* module_names_to_idx; STRING_CACHE* instantiated_modules; @@ -124,10 +127,13 @@ ast_t* init_parser() { /* create string caches to hookup PORTS with INPUT and OUTPUTs. This is made per module and will be cleaned and remade at next_module */ modules_inputs_sc = sc_new_string_cache(); modules_outputs_sc = sc_new_string_cache(); + modules_inouts_sc = sc_new_string_cache(); functions_inputs_sc = sc_new_string_cache(); functions_outputs_sc = sc_new_string_cache(); + functions_inouts_sc = sc_new_string_cache(); tasks_inputs_sc = sc_new_string_cache(); tasks_outputs_sc = sc_new_string_cache(); + tasks_inouts_sc = sc_new_string_cache(); instantiated_modules = sc_new_string_cache(); module_instances_sc = sc_new_string_cache(); /* record of each of the individual modules */ @@ -158,10 +164,13 @@ ast_t* init_parser() { void cleanup_parser() { modules_inputs_sc = sc_free_string_cache(modules_inputs_sc); modules_outputs_sc = sc_free_string_cache(modules_outputs_sc); + modules_inouts_sc = sc_free_string_cache(modules_inouts_sc); functions_inputs_sc = sc_free_string_cache(functions_inputs_sc); functions_outputs_sc = sc_free_string_cache(functions_outputs_sc); + functions_inouts_sc = sc_free_string_cache(functions_inouts_sc); tasks_inputs_sc = sc_free_string_cache(tasks_inputs_sc); tasks_outputs_sc = sc_free_string_cache(tasks_outputs_sc); + tasks_inouts_sc = sc_free_string_cache(tasks_inouts_sc); instantiated_modules = sc_free_string_cache(instantiated_modules); module_instances_sc = sc_free_string_cache(module_instances_sc); } @@ -359,53 +368,57 @@ ast_node_t* resolve_ports(ids top_type, ast_node_t* symbol_list) { } } else { long sc_spot = -1; + STRING_CACHE* sc = NULL; if (top_type == MODULE) { /* find the related INPUT or OUTPUT definition and store that instead */ if ((sc_spot = sc_lookup_string(modules_inputs_sc, symbol_list->children[i]->identifier_node->types.identifier)) != -1) { - oassert(((ast_node_t*)modules_inputs_sc->data[sc_spot])->type == VAR_DECLARE); - free_whole_tree(symbol_list->children[i]); - symbol_list->children[i] = (ast_node_t*)modules_inputs_sc->data[sc_spot]; - oassert(symbol_list->children[i]->types.variable.is_input); + sc = modules_inputs_sc; + oassert(((ast_node_t*)sc->data[sc_spot])->types.variable.is_input); } else if ((sc_spot = sc_lookup_string(modules_outputs_sc, symbol_list->children[i]->identifier_node->types.identifier)) != -1) { - oassert(((ast_node_t*)modules_outputs_sc->data[sc_spot])->type == VAR_DECLARE); - free_whole_tree(symbol_list->children[i]); - symbol_list->children[i] = (ast_node_t*)modules_outputs_sc->data[sc_spot]; - oassert(symbol_list->children[i]->types.variable.is_output); + sc = modules_outputs_sc; + oassert(((ast_node_t*)sc->data[sc_spot])->types.variable.is_output); + } else if ((sc_spot = sc_lookup_string(modules_inouts_sc, symbol_list->children[i]->identifier_node->types.identifier)) != -1) { + sc = modules_inouts_sc; + oassert(((ast_node_t*)sc->data[sc_spot])->types.variable.is_inout); } else { error_message(AST, symbol_list->children[i]->loc, "No matching declaration for port %s\n", symbol_list->children[i]->identifier_node->types.identifier); } } else if (top_type == FUNCTION) { /* find the related INPUT or OUTPUT definition and store that instead */ if ((sc_spot = sc_lookup_string(functions_inputs_sc, symbol_list->children[i]->identifier_node->types.identifier)) != -1) { - oassert(((ast_node_t*)functions_inputs_sc->data[sc_spot])->type == VAR_DECLARE); - free_whole_tree(symbol_list->children[i]); - symbol_list->children[i] = (ast_node_t*)functions_inputs_sc->data[sc_spot]; - oassert(symbol_list->children[i]->types.variable.is_input); + sc = functions_inputs_sc; + oassert(((ast_node_t*)sc->data[sc_spot])->types.variable.is_input); } else if ((sc_spot = sc_lookup_string(functions_outputs_sc, symbol_list->children[i]->identifier_node->types.identifier)) != -1) { - oassert(((ast_node_t*)functions_outputs_sc->data[sc_spot])->type == VAR_DECLARE); - free_whole_tree(symbol_list->children[i]); - symbol_list->children[i] = (ast_node_t*)functions_outputs_sc->data[sc_spot]; - oassert(symbol_list->children[i]->types.variable.is_output); + sc = functions_outputs_sc; + oassert(((ast_node_t*)sc->data[sc_spot])->types.variable.is_output); + } else if ((sc_spot = sc_lookup_string(functions_inouts_sc, symbol_list->children[i]->identifier_node->types.identifier)) != -1) { + sc = functions_inouts_sc; + oassert(((ast_node_t*)sc->data[sc_spot])->types.variable.is_inout); } else { error_message(AST, symbol_list->children[i]->loc, "No matching declaration for port %s\n", symbol_list->children[i]->identifier_node->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]->identifier_node->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); + sc = tasks_inputs_sc; + oassert(((ast_node_t*)sc->data[sc_spot])->types.variable.is_input); } else if ((sc_spot = sc_lookup_string(tasks_outputs_sc, symbol_list->children[i]->identifier_node->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); + sc = tasks_outputs_sc; + oassert(((ast_node_t*)sc->data[sc_spot])->types.variable.is_output); + } else if ((sc_spot = sc_lookup_string(tasks_inouts_sc, symbol_list->children[i]->identifier_node->types.identifier)) != -1) { + sc = tasks_inouts_sc; + oassert(((ast_node_t*)sc->data[sc_spot])->types.variable.is_inout); } else { error_message(AST, symbol_list->children[i]->loc, "No matching declaration for port %s\n", symbol_list->children[i]->identifier_node->types.identifier); } } + + if (sc) { + oassert(((ast_node_t*)sc->data[sc_spot])->type == VAR_DECLARE); + free_whole_tree(symbol_list->children[i]); + symbol_list->children[i] = (ast_node_t*)sc->data[sc_spot]; + } } symbol_list->children[i]->types.variable.is_port = true; } @@ -424,6 +437,7 @@ ast_node_t* markAndProcessPortWith(ids top_type, ids port_id, ids net_id, ast_no const char* top_type_name = NULL; STRING_CACHE* this_inputs_sc = NULL; STRING_CACHE* this_outputs_sc = NULL; + STRING_CACHE* this_inouts_sc = NULL; if (top_type == MODULE) { top_type_name = "Module"; @@ -435,20 +449,20 @@ ast_node_t* markAndProcessPortWith(ids top_type, ids port_id, ids net_id, ast_no ids temp_net_id = NO_ID; - if (port->types.variable.is_port) { - oassert(false && "Port was already marked"); - } + oassert(!port->types.variable.is_port && "Port was already marked"); if (top_type == MODULE) { this_inputs_sc = modules_inputs_sc; this_outputs_sc = modules_outputs_sc; - + this_inouts_sc = modules_inouts_sc; } else if (top_type == FUNCTION) { this_inputs_sc = functions_inputs_sc; this_outputs_sc = functions_outputs_sc; + this_inouts_sc = functions_inouts_sc; } else if (top_type == TASK) { this_inputs_sc = tasks_inputs_sc; this_outputs_sc = tasks_outputs_sc; + this_inouts_sc = tasks_inouts_sc; } /* look for processed inputs with this name */ @@ -465,6 +479,13 @@ ast_node_t* markAndProcessPortWith(ids top_type, ids port_id, ids net_id, ast_no top_type_name, ((ast_node_t*)this_outputs_sc->data[sc_spot])->identifier_node->types.identifier); } + /* look for processed inouts with this name */ + sc_spot = sc_lookup_string(this_inouts_sc, port->identifier_node->types.identifier); + if (sc_spot > -1 && ((ast_node_t*)this_inouts_sc->data[sc_spot])->types.variable.is_port) { + error_message(AST, port->loc, "%s already has inout with this name %s\n", + top_type_name, ((ast_node_t*)this_inouts_sc->data[sc_spot])->identifier_node->types.identifier); + } + switch (net_id) { case REG: if (port_id == INPUT) { @@ -545,9 +566,15 @@ ast_node_t* markAndProcessPortWith(ids top_type, ids port_id, ids net_id, ast_no case INOUT: port->types.variable.is_inout = true; - port->types.variable.is_input = false; - port->types.variable.is_output = false; - error_message(AST, port->loc, "Odin does not handle inouts (%s)\n", port->identifier_node->types.identifier); + port->types.variable.is_input = true; + port->types.variable.is_output = true; + + /* add this output to the modules string cache */ + sc_spot = sc_add_string(this_inouts_sc, port->identifier_node->types.identifier); + + /* store the data which is an idx here */ + this_inouts_sc->data[sc_spot] = (void*)port; + break; default: @@ -559,16 +586,9 @@ ast_node_t* markAndProcessPortWith(ids top_type, ids port_id, ids net_id, ast_no && !(port->types.variable.is_input) && !(port->types.variable.is_inout)) { port = markAndProcessPortWith(top_type, OUTPUT, net_id, port, signedness); - } else if (port->types.variable.is_inout - && !(port->types.variable.is_input) - && !(port->types.variable.is_output)) { - error_message(AST, port->loc, "Odin does not handle inouts (%s)\n", port->identifier_node->types.identifier); - port = markAndProcessPortWith(top_type, INOUT, net_id, port, signedness); } else { - // shouldn't ever get here... - oassert(port->types.variable.is_input - || port->types.variable.is_output - || port->types.variable.is_inout); + oassert(port->types.variable.is_inout); + port = markAndProcessPortWith(top_type, INOUT, net_id, port, signedness); } break; @@ -668,8 +688,8 @@ ast_node_t* markAndProcessSymbolListWith(ids top_type, ids id, ast_node_t* symbo break; case WIRE: /** - * functions cannot have their wire initialized, - * TODO: should'nt this apply to all? + * functions cannot have their wire initialized, + * TODO: should'nt this apply to all? */ if (top_type == FUNCTION) { if ((symbol_list->children[i]->num_children == 5 && symbol_list->children[i]->children[4] != NULL) @@ -745,7 +765,7 @@ ast_node_t* newRangeRef(char* id, ast_node_t* expression1, ast_node_t* expressio /*--------------------------------------------------------------------------------------------- * (function: newPartSelectRangeRef) - * + * * NB!! only support [msb:lsb], will always resolve to this syntax *-------------------------------------------------------------------------------------------*/ ast_node_t* newMinusColonRangeRef(char* id, ast_node_t* expression1, ast_node_t* expression2, loc_t loc) { @@ -773,7 +793,7 @@ ast_node_t* newMinusColonRangeRef(char* id, ast_node_t* expression1, ast_node_t* /*--------------------------------------------------------------------------------------------- * (function: newPartSelectRangeRef) - * + * * NB!! only support [msb:lsb], will always resolve to this syntax *-------------------------------------------------------------------------------------------*/ ast_node_t* newPlusColonRangeRef(char* id, ast_node_t* expression1, ast_node_t* expression2, loc_t loc) { @@ -1646,28 +1666,30 @@ ast_node_t* newTask(char* task_name, ast_node_t* list_of_ports, ast_node_t* list 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) { + if (list_of_task_items->children[i]->children[j]->types.variable.is_inout) { label = vtr::strdup(list_of_task_items->children[i]->children[j]->identifier_node->types.identifier); var_node = newVarDeclare(label, NULL, NULL, NULL, NULL, NULL, loc); + var_node->types.variable.is_inout = true; var_node->types.variable.is_input = true; + 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, loc); } - } else if (list_of_task_items->children[i]->children[j]->types.variable.is_output) { + } else if (list_of_task_items->children[i]->children[j]->types.variable.is_input) { label = vtr::strdup(list_of_task_items->children[i]->children[j]->identifier_node->types.identifier); var_node = newVarDeclare(label, NULL, NULL, NULL, NULL, NULL, loc); - var_node->types.variable.is_output = true; + 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, loc); } - } else if (list_of_task_items->children[i]->children[j]->types.variable.is_inout) { + } 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]->identifier_node->types.identifier); var_node = newVarDeclare(label, NULL, NULL, NULL, NULL, NULL, loc); - var_node->types.variable.is_inout = true; + var_node->types.variable.is_output = true; if (list_of_ports) { newList_entry(list_of_ports, var_node); } else { @@ -1730,9 +1752,11 @@ void next_task() { /* old ones are done so clean */ sc_free_string_cache(tasks_inputs_sc); sc_free_string_cache(tasks_outputs_sc); + sc_free_string_cache(tasks_inouts_sc); /* make for next task */ tasks_inputs_sc = sc_new_string_cache(); tasks_outputs_sc = sc_new_string_cache(); + tasks_inouts_sc = sc_new_string_cache(); } /*--------------------------------------------------------------------------------------------- * (function: next_function) @@ -1747,9 +1771,11 @@ void next_function() { /* old ones are done so clean */ sc_free_string_cache(functions_inputs_sc); sc_free_string_cache(functions_outputs_sc); + sc_free_string_cache(functions_inouts_sc); /* make for next function */ functions_inputs_sc = sc_new_string_cache(); functions_outputs_sc = sc_new_string_cache(); + functions_inouts_sc = sc_new_string_cache(); } /*--------------------------------------------------------------------------------------------- * (function: next_module) @@ -1767,10 +1793,12 @@ void next_module() { /* old ones are done so clean */ sc_free_string_cache(modules_inputs_sc); sc_free_string_cache(modules_outputs_sc); + sc_free_string_cache(modules_inouts_sc); sc_free_string_cache(module_instances_sc); /* make for next module */ modules_inputs_sc = sc_new_string_cache(); modules_outputs_sc = sc_new_string_cache(); + modules_inouts_sc = sc_new_string_cache(); module_instances_sc = sc_new_string_cache(); } @@ -1846,12 +1874,13 @@ void graphVizOutputAst_traverse_node(FILE* fp, ast_node_t* node, ast_node_t* fro switch (node->type) { case VAR_DECLARE: { - if (node->types.variable.is_input) + std::stringstream temp; + if (node->types.variable.is_inout) + fprintf(fp, " inout"); + else if (node->types.variable.is_input) fprintf(fp, " input"); else if (node->types.variable.is_output) fprintf(fp, " output"); - else if (node->types.variable.is_inout) - fprintf(fp, " inout"); else if (node->types.variable.is_parameter) fprintf(fp, " parameter"); diff --git a/ODIN_II/SRC/partial_map.cpp b/ODIN_II/SRC/partial_map.cpp index 04fd0a9ba76..9ba40ecbc9e 100644 --- a/ODIN_II/SRC/partial_map.cpp +++ b/ODIN_II/SRC/partial_map.cpp @@ -353,7 +353,7 @@ bool eliminate_buffer(nnode_t* node, short, netlist_t*) { for (int i = 0; i < node->num_input_pins; i++) { int idx_2_buffer = node->input_pins[i]->pin_net_idx; - // Dont eliminate the buffer if there are multiple drivers or the AST included it + // Dont eliminate the buffer if there are multiple drivers if (node->output_pins[i]->net->num_driver_pins <= 1) { /* join all fanouts of the output net with the input pins net */ join_nets(node->input_pins[i]->net, node->output_pins[i]->net); diff --git a/ODIN_II/regression_test/benchmark/task/syntax/task.conf b/ODIN_II/regression_test/benchmark/task/syntax/task.conf index 3fe7ef5f05a..9b5f49cb2f5 100644 --- a/ODIN_II/regression_test/benchmark/task/syntax/task.conf +++ b/ODIN_II/regression_test/benchmark/task/syntax/task.conf @@ -16,6 +16,7 @@ arch_list_add=k6_frac_N10_frac_chain_mem32K_40nm.xml circuits_dir=regression_test/benchmark/verilog/ circuit_list_add=syntax/*.v +circuit_list_add=syntax/inout-syntax/*.v synthesis_parse_file=regression_test/parse_result/conf/synth.toml simulation_parse_file=regression_test/parse_result/conf/sim.toml diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/double_assign_inout.v b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/double_assign_inout.v new file mode 100644 index 00000000000..7fc01672ff9 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/double_assign_inout.v @@ -0,0 +1,8 @@ +module simple_op(in_out1,in_out2,en); + inout in_out1; + inout in_out2; + input en; + + assign in_out1 = (en) ? in_out2 : 1'bz; + assign in_out2 = (!en) ? in_out1 : 1'bz; +endmodule \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/double_assign_inout_input b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/double_assign_inout_input new file mode 100644 index 00000000000..165f76917f6 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/double_assign_inout_input @@ -0,0 +1,7 @@ +GLOBAL_SIM_BASE_CLK en in_out1 in_out2 +0 1 z z +1 0 z z +0 1 z 0 +1 1 z 1 +0 0 1 z +1 0 0 z \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/double_assign_inout_output b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/double_assign_inout_output new file mode 100644 index 00000000000..d913cb18c27 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/double_assign_inout_output @@ -0,0 +1,7 @@ +in_out1 in_out2 +0 0 +1 1 +0 0 +0 x +1 1 +x 1 \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_basic.v b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_basic.v new file mode 100644 index 00000000000..abbba5cc961 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_basic.v @@ -0,0 +1,4 @@ +module inout_basic(input dir, inout io, output out); + assign io = (dir) ? dir : 1'bz; + assign out = (!dir) ? io : 1'bx; +endmodule \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_basic_input b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_basic_input new file mode 100644 index 00000000000..2ebb976abef --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_basic_input @@ -0,0 +1,9 @@ +GLOBAL_SIM_BASE_CLK dir io +0 1 0 +0 1 0 +0 1 1 +0 1 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_basic_output b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_basic_output new file mode 100644 index 00000000000..9e5f9b0e24d --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_basic_output @@ -0,0 +1,9 @@ +io out +1 x +1 x +1 x +1 x +0 0 +0 0 +1 1 +1 1 \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_input_only.v b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_input_only.v new file mode 100644 index 00000000000..ed5803eaac5 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_input_only.v @@ -0,0 +1,7 @@ +module inout_assign(inout a, output b); + assign b = a; +endmodule + +module inout_basic(input a, output b); + inout_assign c(a, b); +endmodule diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_input_only_input b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_input_only_input new file mode 100644 index 00000000000..7aa0662d4f4 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_input_only_input @@ -0,0 +1,6 @@ +GLOBAL_SIM_BASE_CLK a +0 0 +0 1 +0 1 +0 0 +0 1 \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_input_only_output b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_input_only_output new file mode 100644 index 00000000000..bc390dbca86 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_input_only_output @@ -0,0 +1,6 @@ +b +0 +1 +1 +0 +1 \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_output_only.v b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_output_only.v new file mode 100644 index 00000000000..db7d22c765c --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_output_only.v @@ -0,0 +1,7 @@ +module inout_assign(input a, inout b); + assign b = a; +endmodule + +module inout_basic(input a, output b); + inout_assign c(a, b); +endmodule diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_output_only_input b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_output_only_input new file mode 100644 index 00000000000..7aa0662d4f4 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_output_only_input @@ -0,0 +1,6 @@ +GLOBAL_SIM_BASE_CLK a +0 0 +0 1 +0 1 +0 0 +0 1 \ No newline at end of file diff --git a/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_output_only_output b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_output_only_output new file mode 100644 index 00000000000..bc390dbca86 --- /dev/null +++ b/ODIN_II/regression_test/benchmark/verilog/syntax/inout-syntax/inout_output_only_output @@ -0,0 +1,6 @@ +b +0 +1 +1 +0 +1 \ No newline at end of file diff --git a/ODIN_II/verify_odin.sh b/ODIN_II/verify_odin.sh index cda231ee36e..4e4845378af 100755 --- a/ODIN_II/verify_odin.sh +++ b/ODIN_II/verify_odin.sh @@ -106,7 +106,7 @@ _prt_cur_arg() { function help() { printf "Called program with $INPUT - Usage: + Usage: $0 [ OPTIONS / FLAGS ] [ SUBTEST_LIST ... ] SUBTEST_LIST @@ -121,8 +121,8 @@ printf "Called program with $INPUT -c|--clean $(_prt_cur_arg off ) Clean temporary directory -f|--force_simulate $(_prt_cur_arg ${_FORCE_SIM}) Force the simulation to be executed regardless of the config --override $(_prt_cur_arg ${_OVERRIDE_CONFIG}) if a config file is passed in, override arguments rather than append - --dry_run $(_prt_cur_arg ${_DRY_RUN}) performs a dry run to check the validity of the task and flow - --randomize $(_prt_cur_arg ${_RANDOM_DRY_RUN}) performs a dry run randomly to check the validity of the task and flow + --dry_run $(_prt_cur_arg ${_DRY_RUN}) performs a dry run to check the validity of the task and flow + --randomize $(_prt_cur_arg ${_RANDOM_DRY_RUN}) performs a dry run randomly to check the validity of the task and flow --regenerate_expectation $(_prt_cur_arg ${_REGENERATE_EXPECTATION}) regenerate the expectation and overrides the expected value mismatches only --generate_expectation $(_prt_cur_arg ${_GENERATE_EXPECTATION}) generate the expectation and overrides the expectation file --continue $(_prt_cur_arg ${_CONTINUE}) continue running test in the same directory as the last run @@ -133,8 +133,8 @@ printf "Called program with $INPUT -j|--nb_of_process < N > $(_prt_cur_arg ${_NUMBER_OF_PROCESS}) Number of process requested to be used -d|--output_dir < /abs/path > $(_prt_cur_arg ${_RUN_DIR_OVERRIDE}) Change the run directory output -C|--config $(_prt_cur_arg ${_EXTRA_CONFIG}) Add a config file to append to the config for the tests - -t|--test < test name > $(_prt_cur_arg ${_TEST_INPUT_LIST[*]}) Test name is either a absolute or relative path to - a directory containing a task.conf, task_list.conf + -t|--test < test name > $(_prt_cur_arg ${_TEST_INPUT_LIST[*]}) Test name is either a absolute or relative path to + a directory containing a task.conf, task_list.conf (see CONFIG FILE HELP) or one of the following predefined test AVAILABLE_TEST: @@ -222,7 +222,7 @@ function create_temp() { ln -s "${NEW_RUN_DIR}" "${REGRESSION_DIR}/latest" - # put in the passed parameter for keepsake + # put in the passed parameter for keepsake echo "${_TEST_INPUT_LIST[@]}" | xargs -n 1 -I {} echo {} > "${NEW_RUN_DIR}/cmd.task" echo "=========" echo "$0 ${INPUT}" >> "${NEW_RUN_DIR}/cmd.task" @@ -237,7 +237,7 @@ function cleanup_temp() { fi for runs in "${OUTPUT_DIRECTORY}"/run* - do + do rm -Rf "${runs}" done @@ -282,15 +282,15 @@ function disable_failed_bm() { function parse_args() { PARSE_SUBTEST="off" while [ "_$*" != "_" ] - do + do if [ ${PARSE_SUBTEST} == "on" ]; then # parse subtest _SUBTEST_LIST+=( "$1" ) shift else - # parse [ OPTIONS / FLAGS ] - case $1 in + # parse [ OPTIONS / FLAGS ] + case $1 in # Help Desk -h|--help) @@ -298,12 +298,12 @@ function parse_args() { help _exit_with_code "0" - + ## directory in benchmark ;;-t|--test) # this is handled down stream if [ "_$2" == "_" ] - then + then echo "empty argument for $1" _exit_with_code "-1" fi @@ -314,11 +314,11 @@ function parse_args() { ;;-d|--output_dir) if [ "_$2" == "_" ] - then + then echo "empty argument for $1" _exit_with_code "-1" fi - + _RUN_DIR_OVERRIDE=$2 if [ ! -d "${_RUN_DIR_OVERRIDE}" ] @@ -332,11 +332,11 @@ function parse_args() { ;;-C|--config) if [ "_$2" == "_" ] - then + then echo "empty argument for $1" _exit_with_code "-1" fi - + _EXTRA_CONFIG=$2 echo "Reading extra config directive from ${_EXTRA_CONFIG}" @@ -349,29 +349,29 @@ function parse_args() { shift # Boolean flags - ;;-g|--generate_bench) + ;;-g|--generate_bench) _GENERATE_BENCH="on" echo "generating output vector for test given predefined input" - ;;-o|--generate_output) + ;;-o|--generate_output) _GENERATE_OUTPUT="on" echo "generating input and output vector for test" - ;;-b|--build_config) + ;;-b|--build_config) _GENERATE_CONFIG="on" echo "generating a config file for test directory" - ;;-c|--clean) + ;;-c|--clean) echo "Cleaning temporary run in directory" cleanup_temp - ;;-f|--force_simulate) + ;;-f|--force_simulate) _FORCE_SIM="on" - echo "Forcing Simulation" + echo "Forcing Simulation" ;;--override) _OVERRIDE_CONFIG="on" - echo "Forcing override of config" + echo "Forcing override of config" ;;--dry_run) _DRY_RUN="on" @@ -402,7 +402,7 @@ function parse_args() { _CONTINUE="on" echo "print the previous test report" - ;;*) + ;;*) PARSE_SUBTEST="on" esac @@ -449,9 +449,9 @@ printf " simulation_parse_file = < path/to/parse/file > script_synthesis_params = [see exec_wrapper.sh options] script_simulation_params= [see exec_wrapper.sh options] - synthesis_params = [see Odin options] + synthesis_params = [see Odin options] simulation_params = [see Odin options] - regression_params = + regression_params = { --verbose # display error logs after batch of tests --concat_circuit_list # concatenate the circuit list and pass it straight through to odin @@ -503,13 +503,13 @@ function populate_arg_from_file() { _key="$(echo "${formatted_line}" | cut -d '=' -f1 )" _value="$(echo "${formatted_line}" | cut -d '=' -f2 )" - if [ "_${_key}" != "_" ] && [ "_${_value}" == "_" ] + if [ "_${_key}" != "_" ] && [ "_${_value}" == "_" ] then echo "Specifying empty value for ${_key}, skipping assignment" - elif [ "_${_key}" == "_" ] && [ "_${_value}" != "_" ] + elif [ "_${_key}" == "_" ] && [ "_${_value}" != "_" ] then echo "Specifying empty key for value: ${_value}, skipping assignment" - elif [ "_${_key}" != "_" ] && [ "_${_value}" != "_" ] + elif [ "_${_key}" != "_" ] && [ "_${_value}" != "_" ] then case _${_key} in @@ -522,7 +522,7 @@ function populate_arg_from_file() { ;;_circuit_list_add) # glob the value - _circuit_list_add+=( "${_circuits_dir}"/${_value} ) + _circuit_list_add+=( "${_circuits_dir}"/${_value} ) ;;_archs_dir) if [ ! -d "${_value}" ] @@ -548,8 +548,8 @@ function populate_arg_from_file() { _local_synthesis_parse_file="${_value}" ;;_synthesis_params) - _local_synthesis_params="${_local_synthesis_params} ${_value}" - + _local_synthesis_params="${_local_synthesis_params} ${_value}" + ;;_simulation_params) _local_simulation_params="${_local_simulation_params} ${_value}" @@ -619,7 +619,7 @@ function populate_arg_from_file() { fi fi - + for circuit_list_item in "${_circuit_list_add[@]}" do if [ ! -f "${circuit_list_item}" ] @@ -635,7 +635,7 @@ function populate_arg_from_file() { echo "Passed a config file with no circuit to test" _exit_with_code "-1" fi - + for arch_list_item in "${_arch_list_add[@]}" do @@ -677,7 +677,7 @@ function move_vector() { file_name="$2" replacement_suffix="$3" - find_in_bench "${file_dir}" "${file_name}" + find_in_bench "${file_dir}" "${file_name}" # move the output vectors for sim_vectors in "${TMP_BENCH_FIND_ARRAY[@]}" do @@ -1233,7 +1233,7 @@ function run_task() { if [ ! -d "${test_dir}" ] then echo "${test_dir} Not Found! Skipping this test" - elif [ ! -f "${test_dir}/task.conf" ] + elif [ ! -f "${test_dir}/task.conf" ] then if [ ${_GENERATE_CONFIG} == "on" ] then @@ -1261,7 +1261,7 @@ function run_vtr_reg() { ########################## # This function filters vtr test to only contain -# tests using verilog files since Odin is unused +# tests using verilog files since Odin is unused # in blif tests function filter_vtr_test() { # filter test prefix i.e vtr:: @@ -1276,10 +1276,10 @@ function filter_vtr_test() { pushd "${VTR_REG_DIR}" &> /dev/null for test in $(cat "${VTR_TASK_PATH}") - do + do if grep -E "circuit_list_add=.*\.v" "${test/regression_tests\//}/config/config.txt" &> "/dev/null" - then - echo $test >> "${FILTERED_VTR_TASK_PATH}"; + then + echo $test >> "${FILTERED_VTR_TASK_PATH}"; fi done popd &> /dev/null