blob: aacfef8588a43aec82ced0503ac38c091d537551 [file] [log] [blame]
/*
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <sstream>
#include "odin_globals.h"
#include "odin_types.h"
#include "odin_util.h"
#include "ast_util.h"
#include "parse_making_ast.h"
#include "string_cache.h"
#include "verilog_bison_user_defined.h"
#include "verilog_bison.h"
#include "hard_blocks.h"
#include "vtr_util.h"
#include "vtr_memory.h"
#include "scope_util.h"
//for module
STRING_CACHE *modules_inputs_sc;
STRING_CACHE *modules_outputs_sc;
STRING_CACHE *module_instances_sc;
//for function
STRING_CACHE *functions_inputs_sc;
STRING_CACHE *functions_outputs_sc;
STRING_CACHE *tasks_inputs_sc;
STRING_CACHE *tasks_outputs_sc;
STRING_CACHE *module_names_to_idx;
STRING_CACHE *instantiated_modules;
ast_node_t **module_variables_not_defined;
int size_module_variables_not_defined;
ast_node_t **function_instantiations_instance;
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;
/*
* File-scope function declarations
*/
ast_node_t *newFunctionAssigning(ast_node_t *expression1, ast_node_t *expression2, int line_number);
ast_node_t *resolve_ports(ids top_type, ast_node_t *symbol_list);
bool is_valid_identifier(char *str);
/*---------------------------------------------------------------------------------------------
* (function: parse_to_ast)
*-------------------------------------------------------------------------------------------*/
void parse_to_ast()
{
extern void push_include(const char *file_name);
/* 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 (parse_counter >= 0)
{
push_include(configuration.list_of_file_names[parse_counter].c_str());
parse_counter--;
}
current_parse_file = 0;
/* parse all the files */
yyparse();
/* verify that the parser did not trigger delayed errors */
verify_delayed_error();
/* for error messages - this is in case we use any of the parser functions after parsing (i.e. create_case_control_signals()) */
current_parse_file = -1;
}
/*---------------------------------------------------------------------------------------------
* (function: init_parser)
*-------------------------------------------------------------------------------------------*/
void 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();
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();
/* 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;
size_all_file_items_list = 0;
}
/*---------------------------------------------------------------------------------------------
* (function: cleanup_parser)
*-------------------------------------------------------------------------------------------*/
void cleanup_parser()
{
modules_inputs_sc = sc_free_string_cache(modules_inputs_sc);
modules_outputs_sc = sc_free_string_cache(modules_outputs_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);
}
/*---------------------------------------------------------------------------------------------
* (function: next_parsed_verilog_file)
*-------------------------------------------------------------------------------------------*/
void next_parsed_verilog_file(ast_node_t *file_items_list)
{
long i;
/* optimization entry point */
printf("Optimizing module by AST based optimizations\n");
if (configuration.output_ast_graphs == 1)
{
/* IF - we want outputs for the graphViz files of each module */
for (i = 0; i < file_items_list->num_children; i++)
{
assert(file_items_list->children[i]);
graphVizOutputAst(configuration.debug_output_path, file_items_list->children[i]);
}
}
/* store the root of this files ast */
all_file_items_list = (ast_node_t**)vtr::realloc(all_file_items_list, sizeof(ast_node_t*)*(size_all_file_items_list+1));
all_file_items_list[size_all_file_items_list] = file_items_list;
size_all_file_items_list ++;
}
/*---------------------------------------------------------------------------------------------
* (function: newSymbolNode)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newSymbolNode(char *id, int line_number)
{
return create_tree_node_id(id, line_number, current_parse_file);
}
/*---------------------------------------------------------------------------------------------
* (function: newNumberNode)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newNumberNode(char *num, int line_number)
{
ast_node_t *current_node = create_tree_node_number(num, line_number, current_parse_file);
vtr::free(num);
return current_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newList)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newList(ids node_type, ast_node_t *child, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(node_type, line_number, current_parse_file);
/* allocate child nodes to this node */
if (child) allocate_children_to_node(new_node, { child });
return new_node;
}
ast_node_t *newfunctionList(ids node_type, ast_node_t *child, int line_number)
{
/* create a output node for this array reference that is going to be the first child */
ast_node_t* output_node = create_node_w_type(IDENTIFIERS, line_number, current_parse_file);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(node_type, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { output_node, child });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newList_entry)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newList_entry(ast_node_t *list, ast_node_t *child)
{
/* allocate child nodes to this node */
if (child) add_child_to_node(list, child);
return list;
}
/*---------------------------------------------------------------------------------------------
* (function: newListReplicate)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newListReplicate(ast_node_t *exp, ast_node_t *child, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(REPLICATE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { exp, child });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newBlock)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newBlock(char *id, ast_node_t *block_node)
{
oassert(block_node->type == BLOCK);
if(id)
{
block_node->types.identifier = id;
block_node->types.scope = pop_scope();
}
else
{
merge_top_scopes();
}
return block_node;
}
static ast_node_t *resolve_symbol_node(ast_node_t *symbol_node)
{
ast_node_t *to_return = NULL;
switch(symbol_node->type)
{
case IDENTIFIERS:
{
ast_node_t *newNode = NULL;
long sc_spot = sc_lookup_string(current_scope->param_sc, symbol_node->types.identifier);
if(sc_spot != -1)
{
newNode = (ast_node_t *)current_scope->param_sc->data[sc_spot];
}
if (newNode && newNode->types.variable.is_parameter == true)
{
to_return = symbol_node;
}
else
{
error_message(PARSE_ERROR, symbol_node->line_number, current_parse_file,
"no match for parameter %s\n", symbol_node->types.identifier);
}
break;
}
case NUMBERS:
case BINARY_OPERATION:
case UNARY_OPERATION:
{
to_return = symbol_node;
break;
}
default:
{
to_return = NULL;
break;
}
}
return to_return;
}
ast_node_t *resolve_ports(ids top_type, ast_node_t *symbol_list)
{
ast_node_t *unprocessed_ports = NULL;
long sc_spot;
for (long i = 0; i < symbol_list->num_children; i++)
{
if (symbol_list->children[i]->types.variable.is_port)
{
ast_node_t *this_port = symbol_list->children[i];
if (!unprocessed_ports)
{
unprocessed_ports = newList(VAR_DECLARE_LIST, this_port, this_port->line_number);
}
else
{
unprocessed_ports = newList_entry(unprocessed_ports, this_port);
}
/* grab and update all typeless ports immediately following this one */
long j = 0;
for (j = i + 1; j < symbol_list->num_children && !(symbol_list->children[j]->types.variable.is_port); j++)
{
/* port type */
symbol_list->children[j]->types.variable.is_input = this_port->types.variable.is_input;
symbol_list->children[j]->types.variable.is_output = this_port->types.variable.is_output;
symbol_list->children[j]->types.variable.is_inout = this_port->types.variable.is_inout;
/* net type */
symbol_list->children[j]->types.variable.is_wire = this_port->types.variable.is_wire;
symbol_list->children[j]->types.variable.is_reg = this_port->types.variable.is_reg;
symbol_list->children[j]->types.variable.is_integer = this_port->types.variable.is_integer;
/* signedness */
symbol_list->children[j]->types.variable.is_signed = this_port->types.variable.is_signed;
/* range */
if (symbol_list->children[j]->children[1] == NULL)
{
symbol_list->children[j]->children[1] = ast_node_deep_copy(this_port->children[1]);
symbol_list->children[j]->children[2] = ast_node_deep_copy(this_port->children[2]);
symbol_list->children[j]->children[3] = ast_node_deep_copy(this_port->children[3]);
symbol_list->children[j]->children[4] = ast_node_deep_copy(this_port->children[4]);
if (this_port->num_children == 8)
{
symbol_list->children[j]->children = (ast_node_t**) realloc(symbol_list->children[j]->children, sizeof(ast_node_t*)*8);
symbol_list->children[j]->children[7] = symbol_list->children[j]->children[5];
symbol_list->children[j]->children[5] = ast_node_deep_copy(this_port->children[5]);
symbol_list->children[j]->children[6] = ast_node_deep_copy(this_port->children[6]);
}
}
/* error checking */
symbol_list->children[j] = markAndProcessPortWith(MODULE, NO_ID, NO_ID, symbol_list->children[j], this_port->types.variable.is_signed);
}
}
else
{
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]->children[0]->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);
}
else if ((sc_spot = sc_lookup_string(modules_outputs_sc, symbol_list->children[i]->children[0]->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);
}
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);
}
}
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]->children[0]->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);
}
else if ((sc_spot = sc_lookup_string(functions_outputs_sc, symbol_list->children[i]->children[0]->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);
}
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);
}
}
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;
}
}
return unprocessed_ports;
}
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;
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)
{
oassert(false && "Port was already marked");
}
if (top_type == MODULE)
{
this_inputs_sc = modules_inputs_sc;
this_outputs_sc = modules_outputs_sc;
}
else if (top_type == FUNCTION)
{
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);
if (sc_spot > -1 && ((ast_node_t*)this_inputs_sc->data[sc_spot])->types.variable.is_port)
{
error_message(PARSE_ERROR, port->line_number, current_parse_file, "%s already has input with this name %s\n",
top_type_name, ((ast_node_t*)this_inputs_sc->data[sc_spot])->children[0]->types.identifier);
}
/* look for processed outputs with this name */
sc_spot = sc_lookup_string(this_outputs_sc, port->children[0]->types.identifier);
if (sc_spot > -1 && ((ast_node_t*)this_outputs_sc->data[sc_spot])->types.variable.is_port)
{
error_message(PARSE_ERROR, port->line_number, current_parse_file, "%s already has output with this name %s\n",
top_type_name, ((ast_node_t*)this_outputs_sc->data[sc_spot])->children[0]->types.identifier);
}
switch (net_id)
{
case REG:
if (port_id == INPUT)
{
error_message(NETLIST_ERROR, port->line_number, port->file_number, "%s",
"Input cannot be defined as a reg\n");
}
if (port_id == INOUT)
{
error_message(NETLIST_ERROR, port->line_number, port->file_number, "%s",
"Inout cannot be defined as a reg\n");
}
port->types.variable.is_reg = true;
port->types.variable.is_wire = false;
port->types.variable.is_integer = false;
break;
case INTEGER:
if (port_id == INPUT)
{
error_message(NETLIST_ERROR, port->line_number, port->file_number, "%s",
"Input cannot be defined as an integer\n");
}
else if (port_id == INOUT)
{
error_message(NETLIST_ERROR, port->line_number, port->file_number, "%s",
"Inout cannot be defined as an integer\n");
}
else if (port_id == OUTPUT)
{
/* cannot support signed ports right now (integers are signed) */
error_message(PARSE_ERROR, port->line_number, current_parse_file,
"Odin does not handle signed ports (%s)\n", port->children[0]->types.identifier);
}
port->types.variable.is_integer = true;
port->types.variable.is_reg = false;
port->types.variable.is_wire = false;
break;
case WIRE:
if ((port->num_children == 6 && port->children[5] != NULL)
|| (port->num_children == 8 && port->children[7] != NULL))
{
error_message(NETLIST_ERROR, port->line_number, port->file_number, "%s",
"Ports of type net cannot be initialized\n");
}
port->types.variable.is_wire = true;
port->types.variable.is_reg = false;
port->types.variable.is_integer = false;
break;
default:
if ((port->num_children == 6 && port->children[5] != NULL)
|| (port->num_children == 8 && port->children[7] != NULL))
{
error_message(NETLIST_ERROR, port->line_number, port->file_number, "%s",
"Ports with undefined type cannot be initialized\n");
}
if (port->types.variable.is_reg
&& !(port->types.variable.is_wire)
&& !(port->types.variable.is_integer))
{
temp_net_id = REG;
}
else if (port->types.variable.is_integer
&& !(port->types.variable.is_wire)
&& !(port->types.variable.is_reg))
{
temp_net_id = INTEGER;
}
else if (port->types.variable.is_wire
&& !(port->types.variable.is_reg)
&& !(port->types.variable.is_integer))
{
temp_net_id = WIRE;
}
else
{
/* port cannot have more than one type */
oassert(!(port->types.variable.is_wire) &&
!(port->types.variable.is_reg) &&
!(port->types.variable.is_integer));
}
if (net_id == NO_ID)
{
/* will be marked later */
net_id = temp_net_id;
}
break;
}
switch (port_id)
{
case INPUT:
port->types.variable.is_input = true;
port->types.variable.is_output = false;
port->types.variable.is_inout = false;
/* add this input to the modules string cache */
sc_spot = sc_add_string(this_inputs_sc, port->children[0]->types.identifier);
/* store the data which is an idx here */
this_inputs_sc->data[sc_spot] = (void*)port;
break;
case OUTPUT:
port->types.variable.is_output = true;
port->types.variable.is_input = false;
port->types.variable.is_inout = false;
/* add this output to the modules string cache */
sc_spot = sc_add_string(this_outputs_sc, port->children[0]->types.identifier);
/* store the data which is an idx here */
this_outputs_sc->data[sc_spot] = (void*)port;
break;
case INOUT:
port->types.variable.is_inout = true;
port->types.variable.is_input = false;
port->types.variable.is_output = false;
error_message(PARSE_ERROR, port->line_number, current_parse_file, "Odin does not handle inouts (%s)\n", port->children[0]->types.identifier);
break;
default:
if (port->types.variable.is_input
&& !(port->types.variable.is_output)
&& !(port->types.variable.is_inout))
{
port = markAndProcessPortWith(top_type, INPUT, net_id, port, is_signed);
}
else if (port->types.variable.is_output
&& !(port->types.variable.is_input)
&& !(port->types.variable.is_inout))
{
port = markAndProcessPortWith(top_type, OUTPUT, net_id, port, is_signed);
}
else if (port->types.variable.is_inout
&& !(port->types.variable.is_input)
&& !(port->types.variable.is_output))
{
error_message(PARSE_ERROR, port->line_number, current_parse_file, "Odin does not handle inouts (%s)\n", port->children[0]->types.identifier);
port = markAndProcessPortWith(top_type, INOUT, net_id, port, is_signed);
}
else
{
// shouldn't ever get here...
oassert(port->types.variable.is_input
|| port->types.variable.is_output
|| port->types.variable.is_inout);
}
break;
}
if (is_signed)
{
/* cannot support signed ports right now */
error_message(PARSE_ERROR, port->line_number, current_parse_file,
"Odin does not handle signed ports (%s)\n", port->children[0]->types.identifier);
}
port->types.variable.is_signed = is_signed;
port->types.variable.is_port = true;
return port;
}
ast_node_t *markAndProcessParameterWith(ids id, ast_node_t *parameter, bool is_signed)
{
if (id == PARAMETER)
{
parameter->children[5]->types.variable.is_parameter = true;
parameter->types.variable.is_parameter = true;
}
else if (id == LOCALPARAM)
{
parameter->children[5]->types.variable.is_localparam = true;
parameter->types.variable.is_localparam = true;
}
if (is_signed)
{
/* cannot support signed parameters right now */
error_message(PARSE_ERROR, parameter->line_number, current_parse_file,
"Odin does not handle signed parameters (%s)\n", parameter->children[0]->types.identifier);
}
parameter->children[5]->types.variable.is_signed = is_signed;
parameter->types.variable.is_signed = is_signed;
long sc_spot = -1;
oassert(current_scope->param_sc);
/* create an entry in the symbol table for this parameter */
if ((sc_spot = sc_lookup_string(current_scope->param_sc, parameter->children[0]->types.identifier)) > -1)
{
error_message(PARSE_ERROR, parameter->children[5]->line_number, current_parse_file,
"Module already has parameter with this name (%s)\n", parameter->children[0]->types.identifier);
}
sc_spot = sc_add_string(current_scope->param_sc, parameter->children[0]->types.identifier);
current_scope->param_sc->data[sc_spot] = (void*)parameter->children[5];
return parameter;
}
ast_node_t *markAndProcessSymbolListWith(ids top_type, ids id, ast_node_t *symbol_list, bool is_signed)
{
long i;
ast_node_t *range_min = NULL;
ast_node_t *range_max = NULL;
if(symbol_list)
{
if(symbol_list->children[0] && symbol_list->children[0]->children[1])
{
range_max = resolve_symbol_node(symbol_list->children[0]->children[1]);
range_min = resolve_symbol_node(symbol_list->children[0]->children[2]);
}
for (i = 0; i < symbol_list->num_children; i++)
{
if ((symbol_list->children[i]->children[1] == NULL) && (symbol_list->children[i]->children[2] == NULL))
{
symbol_list->children[i]->children[1] = ast_node_deep_copy(range_max);
symbol_list->children[i]->children[2] = ast_node_deep_copy(range_min);
}
if(top_type == MODULE || top_type == TASK) {
switch(id)
{
case PARAMETER:
case LOCALPARAM:
{
markAndProcessParameterWith(id, symbol_list->children[i], is_signed);
break;
}
case INPUT:
case OUTPUT:
case INOUT:
symbol_list->children[i] = markAndProcessPortWith(top_type, id, NO_ID, symbol_list->children[i], is_signed);
break;
case WIRE:
if (is_signed)
{
/* cannot support signed nets right now */
error_message(PARSE_ERROR, symbol_list->children[i]->line_number, current_parse_file,
"Odin does not handle signed nets (%s)\n", symbol_list->children[i]->children[0]->types.identifier);
}
symbol_list->children[i]->types.variable.is_wire = true;
break;
case REG:
if (is_signed)
{
/* cannot support signed regs right now */
error_message(PARSE_ERROR, symbol_list->children[i]->line_number, current_parse_file,
"Odin does not handle signed regs (%s)\n", symbol_list->children[i]->children[0]->types.identifier);
}
symbol_list->children[i]->types.variable.is_reg = true;
break;
case INTEGER:
oassert(is_signed && "Integers must always be signed");
symbol_list->children[i]->types.variable.is_signed = is_signed;
symbol_list->children[i]->types.variable.is_integer = true;
break;
case GENVAR:
oassert(is_signed && "Genvars must always be signed");
symbol_list->children[i]->types.variable.is_signed = is_signed;
symbol_list->children[i]->types.variable.is_genvar = true;
break;
default:
oassert(false);
}
}
else if(top_type == FUNCTION) {
switch(id)
{
case PARAMETER:
case LOCALPARAM:
{
markAndProcessParameterWith( id, symbol_list->children[i], is_signed);
break;
}
case INPUT:
case OUTPUT:
case INOUT:
symbol_list->children[i] = markAndProcessPortWith(top_type, id, NO_ID, symbol_list->children[i], is_signed);
break;
case WIRE:
if ((symbol_list->children[i]->num_children == 6 && symbol_list->children[i]->children[5] != NULL)
|| (symbol_list->children[i]->num_children == 8 && symbol_list->children[i]->children[7] != NULL))
{
error_message(NETLIST_ERROR, symbol_list->children[i]->line_number, symbol_list->children[i]->file_number, "%s",
"Nets cannot be initialized\n");
}
if (is_signed)
{
/* cannot support signed nets right now */
error_message(PARSE_ERROR, symbol_list->children[i]->line_number, current_parse_file,
"Odin does not handle signed nets (%s)\n", symbol_list->children[i]->children[0]->types.identifier);
}
symbol_list->children[i]->types.variable.is_wire = true;
break;
case REG:
if (is_signed)
{
/* cannot support signed regs right now */
error_message(PARSE_ERROR, symbol_list->children[i]->line_number, current_parse_file,
"Odin does not handle signed regs (%s)\n", symbol_list->children[i]->children[0]->types.identifier);
}
symbol_list->children[i]->types.variable.is_reg = true;
break;
case INTEGER:
oassert(is_signed && "Integers must always be signed");
symbol_list->children[i]->types.variable.is_signed = is_signed;
symbol_list->children[i]->types.variable.is_integer = true;
break;
default:
oassert(false);
}
}
else if (top_type == BLOCK)
{
switch(id)
{
case LOCALPARAM:
{
markAndProcessParameterWith(id, symbol_list->children[i], is_signed);
break;
}
case WIRE:
if (is_signed)
{
/* cannot support signed nets right now */
error_message(PARSE_ERROR, symbol_list->children[i]->line_number, current_parse_file,
"Odin does not handle signed nets (%s)\n", symbol_list->children[i]->children[0]->types.identifier);
}
symbol_list->children[i]->types.variable.is_wire = true;
break;
case REG:
if (is_signed)
{
/* cannot support signed regs right now */
error_message(PARSE_ERROR, symbol_list->children[i]->line_number, current_parse_file,
"Odin does not handle signed regs (%s)\n", symbol_list->children[i]->children[0]->types.identifier);
}
symbol_list->children[i]->types.variable.is_reg = true;
break;
case INTEGER:
oassert(is_signed && "Integers must always be signed");
symbol_list->children[i]->types.variable.is_signed = is_signed;
symbol_list->children[i]->types.variable.is_integer = true;
break;
case GENVAR:
oassert(is_signed && "Genvars must always be signed");
symbol_list->children[i]->types.variable.is_signed = is_signed;
symbol_list->children[i]->types.variable.is_genvar = true;
break;
default:
oassert(false);
}
}
}
/* parameters don't live in the AST */
if (top_type != BLOCK && (id == PARAMETER || id == LOCALPARAM))
{
for (i = 0; i < symbol_list->num_children; i++)
{
symbol_list->children[i]->children[5] = NULL;
}
free_whole_tree(symbol_list);
symbol_list = NULL;
}
}
return symbol_list;
}
/*---------------------------------------------------------------------------------------------
* (function: newArrayRef)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newArrayRef(char *id, ast_node_t *expression, int line_number)
{
/* allocate or check if there's a node for this */
ast_node_t *symbol_node = newSymbolNode(id, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(ARRAY_REF, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, expression });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newRangeRef)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newRangeRef(char *id, ast_node_t *expression1, ast_node_t *expression2, int line_number)
{
/* allocate or check if there's a node for this */
ast_node_t *symbol_node = newSymbolNode(id, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(RANGE_REF, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, expression1, expression2 });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (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, int line_number)
{
ast_node_t *msb = NULL;
ast_node_t *lsb = NULL;
if ( expression1 == NULL )
{
error_message(PARSE_ERROR, line_number, current_parse_file,
"first expression for range ref is NULL %s", id);
}
else if ( expression2 == NULL )
{
error_message(PARSE_ERROR, line_number, current_parse_file,
"first expression for range ref is NULL %s", id);
}
// expression 1 is the msb here since we subtract expression 2 from it
msb = expression1;
ast_node_t *number_one = create_tree_node_number(1L, line_number, current_parse_file);
ast_node_t *size_to_index = newBinaryOperation(MINUS, expression2, number_one, line_number);
lsb = newBinaryOperation(MINUS, ast_node_deep_copy(expression1), size_to_index, line_number);
return newRangeRef(id, msb, lsb, line_number);
}
/*---------------------------------------------------------------------------------------------
* (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, int line_number)
{
ast_node_t *msb = NULL;
ast_node_t *lsb = NULL;
if ( expression1 == NULL )
{
error_message(PARSE_ERROR, line_number, current_parse_file,
"first expression for range ref is NULL %s", id);
}
else if ( expression2 == NULL )
{
error_message(PARSE_ERROR, line_number, current_parse_file,
"first expression for range ref is NULL %s", id);
}
// expression 1 is the lsb here since we add expression 2 to it
lsb = expression1;
ast_node_t *number_one = create_tree_node_number(1L, line_number, current_parse_file);
ast_node_t *size_to_index = newBinaryOperation(MINUS, expression2, number_one, line_number);
msb = newBinaryOperation(ADD, ast_node_deep_copy(expression1), size_to_index, line_number);
return newRangeRef(id, msb, lsb, line_number);
}
/*---------------------------------------------------------------------------------------------
* (function: newBinaryOperation)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newBinaryOperation(operation_list op_id, ast_node_t *expression1, ast_node_t *expression2, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(BINARY_OPERATION, line_number, current_parse_file);
/* store the operation type */
new_node->types.operation.op = op_id;
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { expression1, expression2 });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newUnaryOperation)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newUnaryOperation(operation_list op_id, ast_node_t *expression, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(UNARY_OPERATION, line_number, current_parse_file);
/* store the operation type */
new_node->types.operation.op = op_id;
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { expression });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newNegedgeSymbol)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newNegedgeSymbol(char *symbol, int line_number)
{
/* get the symbol node */
ast_node_t *symbol_node = newSymbolNode(symbol, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(NEGEDGE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newPosedgeSymbol)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newPosedgeSymbol(char *symbol, int line_number)
{
/* get the symbol node */
ast_node_t *symbol_node = newSymbolNode(symbol, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(POSEDGE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newCaseItem)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newCaseItem(ast_node_t *expression, ast_node_t *statement, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(CASE_ITEM, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { expression, statement });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newDefaultCase)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newDefaultCase(ast_node_t *statement, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(CASE_DEFAULT, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { statement });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newNonBlocking)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newParallelConnection(ast_node_t *expression1, ast_node_t *expression2, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(SPECIFY_PAL_CONNECTION_STATEMENT, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { expression1, expression2 });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newNonBlocking)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newNonBlocking(ast_node_t *expression1, ast_node_t *expression2, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(NON_BLOCKING_STATEMENT, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { expression1, expression2 });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newInitial)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newInitial(ast_node_t *expression1, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(INITIAL, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { expression1 });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newBlocking)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newBlocking(ast_node_t *expression1, ast_node_t *expression2, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(BLOCKING_STATEMENT, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { expression1, expression2 });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newBlocking)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newFunctionAssigning(ast_node_t *expression1, ast_node_t *expression2, int line_number)
{
char *label = vtr::strdup(expression1->types.identifier);
ast_node_t *node = newSymbolNode(label,line_number);
expression2->children[1]->children[1]->children[0] = newModuleConnection(NULL, node, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(BLOCKING_STATEMENT, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { expression1, expression2 });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newFor)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newFor(ast_node_t *initial, ast_node_t *compare_expression, ast_node_t *terminal, ast_node_t *statement, int line_number)
{
/* create a node for this for reference */
ast_node_t* new_node = create_node_w_type(FOR, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { initial, compare_expression, terminal, statement });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newWhile)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newWhile(ast_node_t *compare_expression, ast_node_t *statement, int line_number)
{
/* create a node for this for reference */
ast_node_t* new_node = create_node_w_type(WHILE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { compare_expression, statement });
/* This needs to be removed once support is added */
error_message(PARSE_ERROR, line_number, current_parse_file, "%s", "While statements are NOT supported");
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newIf)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newIf(ast_node_t *compare_expression, ast_node_t *true_expression, ast_node_t *false_expression, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(IF, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { compare_expression, true_expression, false_expression });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newIfQuestion) for f = a ? b : c;
*-------------------------------------------------------------------------------------------*/
ast_node_t *newIfQuestion(ast_node_t *compare_expression, ast_node_t *true_expression, ast_node_t *false_expression, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(IF_Q, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { compare_expression, true_expression, false_expression });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newCase)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newCase(ast_node_t *compare_expression, ast_node_t *case_list, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(CASE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { compare_expression, case_list });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newAlways)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newAlways(ast_node_t *delay_control, ast_node_t *statement, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(ALWAYS, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { delay_control, statement });
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 = 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)
{
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);
}
if(expression == NULL)
{
char *number = vtr::strdup("'bz");
expression = newNumberNode(number,line_number);
}
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, expression });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newModuleParameter)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newModuleParameter(char* id, ast_node_t *expression, int line_number)
{
ast_node_t *symbol_node = NULL;
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(MODULE_PARAMETER, line_number, current_parse_file);
if (id != NULL)
{
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);
}
/* allocate child nodes to this node */
// leave 4 blank nodes so that expression is the 6th node to behave just like
// a default var_declare parameter (see create_symbol_table_for_module)
allocate_children_to_node(new_node, { symbol_node, NULL, NULL, NULL, NULL, expression });
// set is_parameter for the same reason
new_node->types.variable.is_parameter = true;
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newModuleNamedInstance)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newModuleNamedInstance(char* unique_name, ast_node_t *module_connect_list, ast_node_t *module_parameter_list, int line_number)
{
if (!is_valid_identifier(unique_name))
{
error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", unique_name);
}
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(MODULE_NAMED_INSTANCE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, module_connect_list, module_parameter_list });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newFunctionNamedInstance)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newFunctionNamedInstance(ast_node_t *module_connect_list, ast_node_t *module_parameter_list, int line_number)
{
std::string buffer("function_instance_");
buffer += std::to_string(size_function_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(FUNCTION_NAMED_INSTANCE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, module_connect_list, module_parameter_list });
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)
*-----------------------------------------------------------------------*/
ast_node_t *newHardBlockInstance(char* module_ref_name, ast_node_t *module_named_instance, int line_number)
{
if (!is_valid_identifier(module_ref_name))
{
error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", module_ref_name);
}
ast_node_t *symbol_node = newSymbolNode(module_ref_name, line_number);
// create a node for this array reference
ast_node_t* new_node = create_node_w_type(HARD_BLOCK, line_number, current_parse_file);
// allocate child nodes to this node
allocate_children_to_node(new_node, { symbol_node, module_named_instance });
// mark as hard block
module_named_instance->type = HARD_BLOCK_NAMED_INSTANCE;
ast_node_t *connect_list_node = module_named_instance->children[1];
connect_list_node->type = HARD_BLOCK_CONNECT_LIST;
for (int i = 0; i < connect_list_node->num_children; i++)
{
connect_list_node->children[i]->type = HARD_BLOCK_CONNECT;
}
return new_node;
}
/*-------------------------------------------------------------------------
* (function: newModuleInstance)
*-----------------------------------------------------------------------*/
ast_node_t *newModuleInstance(char* module_ref_name, ast_node_t *module_named_instance, int line_number)
{
if (!is_valid_identifier(module_ref_name))
{
error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", module_ref_name);
}
long i;
/* create a node for this array reference */
ast_node_t* new_master_node = create_node_w_type(MODULE_INSTANCE, line_number, current_parse_file);
for(i = 0; i < module_named_instance->num_children; i++)
{
/* check if this name was already used */
long sc_spot = sc_add_string(module_instances_sc, module_named_instance->children[i]->children[0]->types.identifier);
if (module_instances_sc->data[sc_spot] != NULL)
{
error_message(PARSE_ERROR, line_number, current_parse_file,
"Module already has an instance with this name (%s)\n",
module_named_instance->children[i]->children[0]->types.identifier);
}
module_instances_sc->data[sc_spot] = module_named_instance->children[i];
ast_node_t *symbol_node = newSymbolNode(module_ref_name, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(MODULE_INSTANCE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, module_named_instance->children[i] });
if(i == 0) allocate_children_to_node(new_master_node, { new_node });
else add_child_to_node(new_master_node,new_node);
/* store the module symbol name that this calls in a list that will at the end be asociated with the module node */
sc_add_string(instantiated_modules, module_ref_name);
/* if this module has already been parsed, update */
for (int j = 0; j < num_modules; j++)
{
if (sc_lookup_string(instantiated_modules, ast_modules[j]->children[0]->types.identifier) != -1)
{
ast_modules[j]->types.module.is_instantiated = true;
}
}
}
vtr::free(module_named_instance->children);
vtr::free(module_named_instance);
return new_master_node;
}
/*-------------------------------------------------------------------------
* (function: newFunctionInstance)
*-----------------------------------------------------------------------*/
ast_node_t *newFunctionInstance(char* function_ref_name, ast_node_t *function_named_instance, int line_number)
{
ast_node_t *symbol_node = newSymbolNode(function_ref_name, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(FUNCTION_INSTANCE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, function_named_instance });
/* store the module symbol name that this calls in a list that will at the end be asociated with the module node */
function_instantiations_instance_by_module = (ast_node_t **)vtr::realloc(function_instantiations_instance_by_module, sizeof(ast_node_t*)*(size_function_instantiations_by_module+1));
function_instantiations_instance_by_module[size_function_instantiations_by_module] = new_node;
size_function_instantiations_by_module++;
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newGateInstance)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newGateInstance(char* gate_instance_name, ast_node_t *expression1, ast_node_t *expression2, ast_node_t *expression3, int line_number)
{
if (!is_valid_identifier(gate_instance_name))
{
error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", gate_instance_name);
}
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(GATE_INSTANCE, line_number, current_parse_file);
ast_node_t *symbol_node = NULL;
if (gate_instance_name != NULL)
{
symbol_node = newSymbolNode(gate_instance_name, line_number);
}
char *newChar = vtr::strdup(expression1->types.identifier);
ast_node_t *newVar = newVarDeclare(newChar, NULL, NULL, NULL, NULL, NULL, line_number);
ast_node_t *newVarList = newList(VAR_DECLARE_LIST, newVar, line_number);
ast_node_t *newVarMaked = markAndProcessSymbolListWith(MODULE,WIRE, newVarList, false);
if(size_module_variables_not_defined == 0){
module_variables_not_defined = (ast_node_t **)vtr::calloc(1, sizeof(ast_node_t*));
}
else{
module_variables_not_defined = (ast_node_t **)vtr::realloc(module_variables_not_defined, sizeof(ast_node_t*)*(size_module_variables_not_defined+1));
}
module_variables_not_defined[size_module_variables_not_defined] = newVarMaked;
size_module_variables_not_defined++;
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, expression1, expression2, expression3 });
return new_node;
}
ast_node_t *newMultipleInputsGateInstance(char* gate_instance_name, ast_node_t *expression1, ast_node_t *expression2, ast_node_t *expression3, int line_number)
{
if (!is_valid_identifier(gate_instance_name))
{
error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", gate_instance_name);
}
long i;
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(GATE_INSTANCE, line_number, current_parse_file);
ast_node_t* symbol_node = NULL;
if (gate_instance_name != NULL)
{
symbol_node = newSymbolNode(gate_instance_name, line_number);
}
char *newChar = vtr::strdup(expression1->types.identifier);
ast_node_t *newVar = newVarDeclare(newChar, NULL, NULL, NULL, NULL, NULL, line_number);
ast_node_t *newVarList = newList(VAR_DECLARE_LIST, newVar, line_number);
ast_node_t *newVarMarked = markAndProcessSymbolListWith(MODULE, WIRE, newVarList, false);
if(size_module_variables_not_defined == 0){
module_variables_not_defined = (ast_node_t **)vtr::calloc(1, sizeof(ast_node_t*));
}
else{
module_variables_not_defined = (ast_node_t **)vtr::realloc(module_variables_not_defined, sizeof(ast_node_t*)*(size_module_variables_not_defined+1));
}
module_variables_not_defined[size_module_variables_not_defined] = newVarMarked;
size_module_variables_not_defined++;
allocate_children_to_node(new_node, { symbol_node, expression1, expression2 });
/* allocate n children nodes to this node */
for(i = 1; i < expression3->num_children; i++) add_child_to_node(new_node, expression3->children[i]);
/* clean up */
if (expression3->type == MODULE_CONNECT) expression3 = free_single_node(expression3);
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newGate)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newGate(operation_list op_id, ast_node_t *gate_instance, int line_number)
{
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(GATE, line_number, current_parse_file);
/* store the operation type */
new_node->types.operation.op = op_id;
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { gate_instance });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newDefparamVarDeclare)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newDefparamVarDeclare(char* symbol, ast_node_t *expression1, ast_node_t *expression2, ast_node_t *expression3, ast_node_t *expression4, ast_node_t *value, int line_number)
{
ast_node_t *symbol_node = newSymbolNode(symbol, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(VAR_DECLARE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, expression1, expression2, expression3, expression4, value });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newVarDeclare)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newVarDeclare(char* symbol, ast_node_t *expression1, ast_node_t *expression2, ast_node_t *expression3, ast_node_t *expression4, ast_node_t *value, int line_number)
{
if (!is_valid_identifier(symbol))
{
error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", symbol);
}
ast_node_t *symbol_node = newSymbolNode(symbol, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(VAR_DECLARE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, expression1, expression2, expression3, expression4, value });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newIntegerTypeVarDeclare)
*-------------------------------------------------------------------------------------------*/
ast_node_t *newIntegerTypeVarDeclare(char* symbol, ast_node_t * /*expression1*/ , ast_node_t * /*expression2*/ , ast_node_t *expression3, ast_node_t *expression4, ast_node_t *value, int line_number)
{
if (!is_valid_identifier(symbol))
{
error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", symbol);
}
ast_node_t *symbol_node = newSymbolNode(symbol, line_number);
ast_node_t *number_node_with_value_31 = create_tree_node_number(31L, line_number,current_parse_file);
ast_node_t *number_node_with_value_0 = create_tree_node_number(0L, line_number,current_parse_file);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(VAR_DECLARE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, number_node_with_value_31, number_node_with_value_0, expression3, expression4, value });
return new_node;
}
/*-----------------------------------------
* ----------------------------------------------------
* (function: newModule)
*-------------------------------------------------------------------------------------------*/
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)
{
if (!is_valid_identifier(module_name))
{
error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", module_name);
}
int i;
long j, k;
long sc_spot;
ast_node_t *symbol_node = newSymbolNode(module_name, line_number);
if( sc_lookup_string(hard_block_names, module_name) != -1
|| !strcmp(module_name, SINGLE_PORT_RAM_string)
|| !strcmp(module_name, DUAL_PORT_RAM_string)
)
{
error_message(PARSE_ERROR, line_number, current_parse_file,
"Module name collides with hard block of the same name (%s)\n", module_name);
}
/* create a node for this array reference */
ast_node_t *new_node = create_node_w_type(MODULE, line_number, current_parse_file);
/* mark all the ports symbols as ports */
ast_node_t *port_declarations = resolve_ports(MODULE, list_of_ports);
/* ports are expected to be in module items */
if (port_declarations)
{
add_child_to_node_at_index(list_of_module_items, port_declarations, 0);
}
/* parameters don't live in the AST */
if (list_of_parameters)
{
for (i = 0; i < list_of_parameters->num_children; i++)
{
list_of_parameters->children[i]->children[5] = NULL;
}
free_whole_tree(list_of_parameters);
}
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, list_of_ports, list_of_module_items });
/* check if this module has been instantiated */
if (new_node->types.module.is_instantiated == false)
{
new_node->types.module.is_instantiated = (sc_lookup_string(instantiated_modules, module_name) != -1);
}
new_node->types.scope = pop_scope();
new_node->types.function.function_instantiations_instance = function_instantiations_instance_by_module;
new_node->types.function.size_function_instantiations = size_function_instantiations_by_module;
new_node->types.function.is_instantiated = false;
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;
/* 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;
for(i = 0; i < size_module_variables_not_defined; i++)
{
short variable_found = false;
for(j = 0; j < list_of_module_items->num_children && variable_found == false; j++){
if(list_of_module_items->children[j]->type == VAR_DECLARE_LIST){
for(k = 0; k < list_of_module_items->children[j]->num_children; k++){
if(strcmp(list_of_module_items->children[j]->children[k]->children[0]->types.identifier,module_variables_not_defined[i]->children[0]->children[0]->types.identifier) == 0)
variable_found = true;
}
}
}
if(!variable_found) add_child_to_node_at_index(list_of_module_items, module_variables_not_defined[i], 0);
else free_whole_tree(module_variables_not_defined[i]);
}
/* clean up */
vtr::free(module_variables_not_defined);
sc_spot = sc_add_string(module_names_to_idx, module_name);
if (module_names_to_idx->data[sc_spot] != NULL)
{
error_message(PARSE_ERROR, line_number, current_parse_file, "module names with the same name -> %s\n", module_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 module, go to the next module */
next_module();
return new_node;
}
/*-----------------------------------------
* ----------------------------------------------------
* (function: newFunction)
*-------------------------------------------------------------------------------------------*/
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)
{
long i,j;
long sc_spot;
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, "%s", "ODIN II does not (yet) differentiate between automatic and static tasks & functions.IGNORING ");
}
if(function_return->children[0]->types.variable.is_integer)
{
warning_message(PARSE_ERROR, line_number, current_parse_file,"%s", "ODIN_II does not fully support input/output integers in functions");
}
if(list_of_ports == NULL )
{
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);
var_node = newVarDeclare(label, NULL, NULL, NULL, NULL, NULL, line_number);
add_child_to_node_at_index(list_of_ports, var_node, 0);
char *function_name = vtr::strdup(function_return->children[0]->children[0]->types.identifier);
if (!is_valid_identifier(function_name))
{
error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", function_name);
}
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);
var_node = newVarDeclare(label, NULL, NULL, NULL, NULL, NULL, line_number);
newList_entry(list_of_ports,var_node);
}
}
}
}
symbol_node = newSymbolNode(function_name, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(FUNCTION, line_number, current_parse_file);
/* mark all the ports symbols as ports */
ast_node_t *port_declarations = resolve_ports(FUNCTION, list_of_ports);
if (port_declarations)
{
add_child_to_node_at_index(list_of_module_items, port_declarations, 0);
}
/* 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 functions this function instantiates */
new_node->types.scope = pop_scope();
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_modules = (ast_node_t **)vtr::realloc(ast_modules, sizeof(ast_node_t*)*(num_modules+1));
ast_modules[num_modules] = new_node;
sc_spot = sc_add_string(module_names_to_idx, function_name);
if (module_names_to_idx->data[sc_spot] != NULL)
{
error_message(PARSE_ERROR, line_number, current_parse_file, "module names with the same name -> %s\n", function_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 module, go to the next module */
next_function();
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, "%s", "ODIN II does not (yet) differentiate between automatic and static tasks & functions. IGNORING");
}
/* 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 });
new_node->types.scope = pop_scope();
/* 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++;
/* 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)
*-------------------------------------------------------------------------------------------*/
void next_function()
{
num_functions++;
/* create a new list for the instantiations list */
function_instantiations_instance = NULL;
size_function_instantiations = 0;
/* old ones are done so clean */
sc_free_string_cache(functions_inputs_sc);
sc_free_string_cache(functions_outputs_sc);
/* make for next function */
functions_inputs_sc = sc_new_string_cache();
functions_outputs_sc = sc_new_string_cache();
}
/*---------------------------------------------------------------------------------------------
* (function: next_module)
*-------------------------------------------------------------------------------------------*/
void next_module()
{
num_modules ++;
num_functions = 0;
/* define the string cache for the next module */
function_instantiations_instance_by_module = NULL;
size_function_instantiations_by_module = 0;
module_variables_not_defined = NULL;
size_module_variables_not_defined = 0;
/* old ones are done so clean */
sc_free_string_cache(modules_inputs_sc);
sc_free_string_cache(modules_outputs_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();
module_instances_sc = sc_new_string_cache();
}
/*--------------------------------------------------------------------------
* (function: newDefparam)
*------------------------------------------------------------------------*/
ast_node_t *newDefparam(ids top_type, ast_node_t *val, int line_number)
{
ast_node_t *new_node = NULL;
if(val)
{
for (int i = 0; i < val->num_children; i++)
{
new_node = val->children[i];
new_node->type = MODULE_PARAMETER;
new_node->types.variable.is_defparam = true;
new_node->children[5]->types.variable.is_defparam = true;
new_node->line_number = line_number;
/* defparams within named or generate blocks are handled during elaboration */
if (top_type != BLOCK)
{
long sc_spot = sc_add_string(current_scope->defparam_sc, new_node->children[0]->types.identifier);
current_scope->defparam_sc->data[sc_spot] = (void *)new_node;
}
}
}
return val;
}
/* --------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
AST VIEWING FUNCTIONS
--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------*/
int unique_label_count;
/*---------------------------------------------------------------------------
* (function: graphVizOutputAst)
*-------------------------------------------------------------------------*/
void graphVizOutputAst(std::string path, ast_node_t *top)
{
char path_and_file[4096];
FILE *fp;
static int file_num = 0;
/* open the file */
odin_sprintf(path_and_file, "%s/%s_ast.dot", path.c_str(), top->children[0]->types.identifier);
fp = fopen(path_and_file, "w");
file_num++;
/* open graph */
fprintf(fp, "digraph G {\t\nranksep=.25;\n");
unique_label_count = 0;
graphVizOutputAst_traverse_node(fp, top, NULL, -1);
/* close graph */
fprintf(fp, "}\n");
fclose(fp);
}
/*---------------------------------------------------------------------------------------------
* (function: graphVizOutputAst_traverse_node)
*-------------------------------------------------------------------------------------------*/
void graphVizOutputAst_traverse_node(FILE *fp, ast_node_t *node, ast_node_t *from, int from_num)
{
if(!node)
return;
/* increase the unique count for other nodes since ours is recorded */
int my_label = unique_label_count++;
fprintf(fp, "\t%d [label=\"", my_label);
fprintf(fp, "%s", ids_STR[node->type]);
switch(node->type)
{
case VAR_DECLARE:
{
std::stringstream temp;
if(node->types.variable.is_input) temp << " INPUT";
if(node->types.variable.is_output) temp << " OUTPUT";
if(node->types.variable.is_inout) temp << " INOUT";
if(node->types.variable.is_port) temp << " PORT";
if(node->types.variable.is_parameter) temp << " PARAMETER";
if(node->types.variable.is_wire) temp << " WIRE";
if(node->types.variable.is_reg) temp << " REG";
fprintf(fp, ": %s", temp.str().c_str());
break;
}
case NUMBERS:
fprintf(fp, ": %s (%s)",
node->types.vnumber->to_bit_string().c_str(),
node->types.vnumber->to_printable().c_str());
break;
case UNARY_OPERATION: //fallthrough
case BINARY_OPERATION:
fprintf(fp, ": %s", name_based_on_op(node->types.operation.op));
break;
case IDENTIFIERS:
fprintf(fp, ": %s", node->types.identifier);
break;
default:
break;
}
fprintf(fp, "\"];\n");
/* print out the connection with the previous node */
if (from != NULL)
fprintf(fp, "\t%d -> %d;\n", from_num, my_label);
for (long i = 0; i < node->num_children; i++)
{
graphVizOutputAst_traverse_node(fp, node->children[i], node, my_label);
}
}
/*---------------------------------------------------------------------------------------------
* (function: newVarDeclare) for 2D Array
*-------------------------------------------------------------------------------------------*/
ast_node_t *newVarDeclare2D(char* symbol, ast_node_t *expression1, ast_node_t *expression2, ast_node_t *expression3, ast_node_t *expression4, ast_node_t *expression5, ast_node_t *expression6,ast_node_t *value, int line_number)
{
if (!is_valid_identifier(symbol))
{
error_message(PARSE_ERROR, line_number, current_parse_file, "Invalid character in identifier (%s)\n", symbol);
}
ast_node_t *symbol_node = newSymbolNode(symbol, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(VAR_DECLARE, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, expression1, expression2, expression3, expression4, expression5, expression6, value });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newArrayRef) for 2D Array
*-------------------------------------------------------------------------------------------*/
ast_node_t *newArrayRef2D(char *id, ast_node_t *expression1, ast_node_t *expression2, int line_number)
{
/* allocate or check if there's a node for this */
ast_node_t *symbol_node = newSymbolNode(id, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(ARRAY_REF, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, expression1,expression2 });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: newRangeRef) for 2D Array
*-------------------------------------------------------------------------------------------*/
ast_node_t *newRangeRef2D(char *id, ast_node_t *expression1, ast_node_t *expression2, ast_node_t *expression3, ast_node_t *expression4, int line_number)
{
/* allocate or check if there's a node for this */
ast_node_t *symbol_node = newSymbolNode(id, line_number);
/* create a node for this array reference */
ast_node_t* new_node = create_node_w_type(RANGE_REF, line_number, current_parse_file);
/* allocate child nodes to this node */
allocate_children_to_node(new_node, { symbol_node, expression1, expression2, expression3, expression4 });
return new_node;
}
/*---------------------------------------------------------------------------------------------
* (function: is_valid_identifier) for identifiers
*-------------------------------------------------------------------------------------------*/
bool is_valid_identifier(char *str)
{
if (str)
{
int i = 0;
char ch = str[i];
while (ch != 0)
{
if (ch == '.')
{
return false;
}
ch = str[++i];
}
}
return true;
}