blob: 5c26a33dc4dd21159d0d1b2d691deb4a2ee7b3ed [file] [log] [blame]
/*
Copyright (c) 2009 Peter Andrew Jamieson (jamieson.peter@gmail.com)
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 <math.h>
#include "odin_types.h"
#include "ast_util.h"
#include "ast_elaborate.h"
#include "ast_loop_unroll.h"
#include "parse_making_ast.h"
#include "verilog_bison.h"
#include "netlist_create_from_ast.h"
#include "ctype.h"
#include "vtr_util.h"
#include "vtr_memory.h"
#include <string>
#include <iostream>
#include <vector>
#include <stack>
// #define read_node 1
// #define write_node 2
// #define e_data 1
// #define e_operation 2
// #define e_variable 3
// #define N 64
// #define Max_size 64
// long count_id = 0;
// long count_assign = 0;
// long count;
// long count_write;
//enode *head, *p;
// void reduce_assignment_expression();
// void reduce_assignment_expression(ast_node_t *ast_module);
// void find_assign_node(ast_node_t *node, std::vector<ast_node_t *> list, char *module_name);
// struct enode
// {
// struct
// {
// short operation;
// int data;
// std::string variable;
// }type;
// int id;
// int flag;
// int priority;
// struct enode *next;
// struct enode *pre;
// };
// void record_tree_info(ast_node_t *node);
// void store_exp_list(ast_node_t *node);
// void create_enode(ast_node_t *node);
// bool simplify_expression();
// bool adjoin_constant();
// enode *replace_enode(int data, enode *t, int mark);
// bool combine_constant();
// bool delete_continuous_multiply();
// void construct_new_tree(enode *tail, ast_node_t *node, int line_num, int file_num);
// void reduce_enode_list();
// enode *find_tail(enode *node);
// int check_exp_list(enode *tail);
// void create_ast_node(enode *temp, ast_node_t *node, int line_num, int file_num);
// void create_op_node(ast_node_t *node, enode *temp, int line_num, int file_num);
// void free_exp_list();
// void change_exp_list(enode *beign, enode *end, enode *s, int flag);
// enode *copy_enode_list(enode *new_head, enode *begin, enode *end);
// void copy_enode(enode *node, enode *new_node);
// bool check_tree_operation(ast_node_t *node);
// void check_operation(enode *begin, enode *end);
// bool check_mult_bracket(std::vector<int> list);
void update_string_caches(STRING_CACHE_LIST *local_string_cache_list);
void convert_2D_to_1D_array(ast_node_t **var_declare, STRING_CACHE_LIST *local_string_cache_list);
void convert_2D_to_1D_array_ref(ast_node_t **node, STRING_CACHE_LIST *local_string_cache_list);
char *make_chunk_size_name(char *instance_name_prefix, char *array_name);
ast_node_t *get_chunk_size_node(char *instance_name_prefix, char *array_name, STRING_CACHE_LIST *local_string_cache_list);
bool verify_terminal(ast_node_t *top, ast_node_t *iterator);
void verify_genvars(ast_node_t *node, STRING_CACHE_LIST *local_string_cache_list, char ***other_genvars, int num_genvars);
int simplify_ast_module(ast_node_t **ast_module, STRING_CACHE_LIST *local_string_cache_list)
{
/* resolve constant expressions */
bool is_module = (*ast_module)->type == MODULE ? true : false;
*ast_module = reduce_expressions(*ast_module, NULL, local_string_cache_list, NULL, 0, is_module);
update_string_caches(local_string_cache_list);
return 1;
}
ast_node_t *reduce_expressions(ast_node_t *node, ast_node_t *parent, STRING_CACHE_LIST *local_string_cache_list, long *max_size, long assignment_size, bool is_generate_region)
{
short *child_skip_list = NULL; // list of children not to traverse into
short skip_children = false; // skips the DFS completely if true
if (node)
{
STRING_CACHE *local_param_table_sc = local_string_cache_list->local_param_table_sc;
STRING_CACHE *local_symbol_table_sc = local_string_cache_list->local_symbol_table_sc;
if (node->num_children > 0)
{
child_skip_list = (short*)vtr::calloc(node->num_children, sizeof(short));
}
switch (node->type)
{
case MODULE:
{
// skip identifier
child_skip_list[0] = true;
break;
}
case FUNCTION:
{
skip_children = true;
break;
}
case VAR_DECLARE:
{
if (node->types.variable.is_parameter || node->types.variable.is_localparam)
{
bool is_stored = false;
long sc_spot = sc_lookup_string(local_param_table_sc, node->children[0]->types.identifier);
if (sc_spot != -1 && ((ast_node_t*)local_param_table_sc->data[sc_spot]) == node->children[5])
{
is_stored = true;
}
/* resolve right-hand side */
node->children[5] = reduce_expressions(node->children[5], node, local_string_cache_list, NULL, 0, is_generate_region);
oassert(node->children[5]->type == NUMBERS);
/* this forces parameter values as unsigned, since we don't currently support signed keyword...
must be changed once support is added */
VNumber *temp = node->children[5]->types.vnumber;
VNumber *to_unsigned = new VNumber(V_UNSIGNED(*temp));
node->children[5]->types.vnumber = to_unsigned;
delete temp;
if (is_stored)
{
local_param_table_sc->data[sc_spot] = (void *) node->children[5];
}
skip_children = true;
}
else
{
// skip identifier
child_skip_list[0] = true;
}
break;
}
case IDENTIFIERS:
{
if (local_param_table_sc != NULL && node->types.identifier)
{
long sc_spot = sc_lookup_string(local_param_table_sc, node->types.identifier);
if (sc_spot != -1)
{
ast_node_t *newNode = ast_node_deep_copy((ast_node_t *)local_param_table_sc->data[sc_spot]);
if (newNode->type != NUMBERS)
{
newNode = reduce_expressions(newNode, parent, local_string_cache_list, NULL, assignment_size, is_generate_region);
oassert(newNode->type == NUMBERS);
/* this forces parameter values as unsigned, since we don't currently support signed keyword...
must be changed once support is added */
VNumber *temp = newNode->types.vnumber;
VNumber *to_unsigned = new VNumber(V_UNSIGNED(*temp));
newNode->types.vnumber = to_unsigned;
delete temp;
if (newNode->type != NUMBERS)
{
error_message(NETLIST_ERROR, node->line_number, node->file_number, "Parameter %s is not a constant expression\n", node->types.identifier);
}
}
node = free_whole_tree(node);
node = newNode;
}
}
break;
}
case FOR:
{
// look ahead for parameters in loop conditions
node->children[0] = reduce_expressions(node->children[0], node, local_string_cache_list, max_size, assignment_size, is_generate_region);
node->children[1] = reduce_expressions(node->children[1], node, local_string_cache_list, max_size, assignment_size, is_generate_region);
node->children[2] = reduce_expressions(node->children[2], node, local_string_cache_list, max_size, assignment_size, is_generate_region);
// update skip list
child_skip_list[0] = true;
child_skip_list[1] = true;
child_skip_list[2] = true;
// if this is a loop generate construct, verify constant expressions
if (is_generate_region)
{
ast_node_t *iterator = NULL;
ast_node_t *initial = node->children[0];
ast_node_t *compare_expression = node->children[1];
ast_node_t *terminal = node->children[2];
char **genvar_list = NULL;
verify_genvars(node, local_string_cache_list, &genvar_list, 0);
if (genvar_list) vtr::free(genvar_list);
long sc_spot = sc_lookup_string(local_symbol_table_sc, initial->children[0]->types.identifier);
oassert(sc_spot > -1);
iterator = (ast_node_t *)local_symbol_table_sc->data[sc_spot];
if ( !(node_is_constant(initial->children[1]))
|| !(node_is_constant(compare_expression->children[1]))
|| !(verify_terminal(terminal->children[1], iterator))
)
{
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Loop generate construct conditions must be constant expressions");
}
}
node = unroll_for_loop(node, parent, local_string_cache_list);
break;
}
case WHILE:
break;
case BLOCKING_STATEMENT:
case NON_BLOCKING_STATEMENT:
{
/* try to resolve */
if (node->children[1]->type != FUNCTION_INSTANCE)
{
node->children[0] = reduce_expressions(node->children[0], node, local_string_cache_list, NULL, 0, is_generate_region);
assignment_size = get_size_of_variable(node->children[0], local_string_cache_list);
max_size = (long*)calloc(1, sizeof(long));
if (node->children[1]->type != NUMBERS)
{
node->children[1] = reduce_expressions(node->children[1], node, local_string_cache_list, max_size, assignment_size, is_generate_region);
if (node->children[1] == NULL)
{
/* resulting from replication of zero */
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Cannot perform assignment with nonexistent value");
}
}
else
{
VNumber *temp = node->children[1]->types.vnumber;
node->children[1]->types.vnumber = new VNumber(*temp, assignment_size);
delete temp;
}
vtr::free(max_size);
/* cast to unsigned if necessary */
if (node_is_constant(node->children[1]))
{
char *id = NULL;
if (node->children[0]->type == IDENTIFIERS)
{
id = node->children[0]->types.identifier;
}
else
{
id = node->children[0]->children[0]->types.identifier;
}
long sc_spot = sc_lookup_string(local_symbol_table_sc, id);
if (sc_spot > -1)
{
bool is_signed = ((ast_node_t *)local_symbol_table_sc->data[sc_spot])->types.variable.is_signed;
if (!is_signed)
{
VNumber *temp = node->children[1]->types.vnumber;
VNumber *to_unsigned = new VNumber(V_UNSIGNED(*temp));
node->children[1]->types.vnumber = to_unsigned;
delete temp;
}
else
{
/* leave as is */
}
}
}
else
{
/* signed keyword is not supported, meaning unresolved values will already be handled as
unsigned at the netlist level... must update once signed support is added */
}
assignment_size = 0;
}
skip_children = true;
break;
}
case BINARY_OPERATION:
break;
case UNARY_OPERATION:
break;
case CONCATENATE:
break;
case REPLICATE:
{
node->children[0] = reduce_expressions(node->children[0], node, local_string_cache_list, NULL, 0, is_generate_region);
if (!(node_is_constant(node->children[0])))
{
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Replication constant must be a constant expression");
}
else if (node->children[0]->types.vnumber->is_dont_care_string())
{
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Replication constant cannot contain x or z");
}
ast_node_t *new_node = NULL;
int64_t value = node->children[0]->types.vnumber->get_value();
if (value > 0)
{
new_node = create_node_w_type(CONCATENATE, node->line_number, node->file_number);
for (size_t i = 0; i < value; i++)
{
add_child_to_node(new_node, ast_node_deep_copy(node->children[1]));
}
}
node->children[1] = free_whole_tree(node->children[1]);
node->children[1] = NULL;
node->num_children--;
node->children[0] = free_whole_tree(node->children[0]);
node->children[0] = new_node;
break;
}
case NUMBERS:
break;
case IF_Q:
case IF:
{
ast_node_t *to_return = NULL;
node->children[0] = reduce_expressions(node->children[0], node, local_string_cache_list, NULL, 0, is_generate_region);
ast_node_t *child_condition = node->children[0];
if(node_is_constant(child_condition))
{
VNumber condition = *(child_condition->types.vnumber);
if(V_TRUE(condition))
{
to_return = node->children[1];
node->children[1] = NULL;
}
else if(V_FALSE(condition))
{
to_return = node->children[2];
node->children[2] = NULL;
}
else if (node->type == IF && is_generate_region)
{
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Could not resolve conditional generate construct");
}
// otherwise we keep it as is to build the circuitry
}
else if (node->type == IF && is_generate_region)
{
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Could not resolve conditional generate construct");
}
if (to_return)
{
free_whole_tree(node);
node = to_return;
}
break;
}
case CASE:
{
ast_node_t *to_return = NULL;
node->children[0] = reduce_expressions(node->children[0], node, local_string_cache_list, NULL, 0, is_generate_region);
ast_node_t *child_condition = node->children[0];
if(node_is_constant(child_condition))
{
ast_node_t *case_list = node->children[1];
for (int i = 0; i < case_list->num_children; i++)
{
ast_node_t *item = case_list->children[i];
if (i == case_list->num_children - 1 && item->type == CASE_DEFAULT)
{
to_return = item->children[0];
item->children[0] = NULL;
}
else
{
if (item->type != CASE_ITEM)
{
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Default case must only be the last case");
}
item->children[0] = reduce_expressions(item->children[0], item, local_string_cache_list, NULL, 0, is_generate_region);
if (node_is_constant(item->children[0]))
{
VNumber eval = V_CASE_EQUAL(*(child_condition->types.vnumber), *(item->children[0]->types.vnumber));
if (V_TRUE(eval))
{
to_return = item->children[1];
item->children[1] = NULL;
break;
}
}
else if (is_generate_region)
{
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Could not resolve conditional generate construct");
}
else
{
/* encountered non-constant item - don't continue searching */
break;
}
}
}
if (to_return)
{
free_whole_tree(node);
node = to_return;
}
else if (is_generate_region)
{
/* no case */
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Could not resolve conditional generate construct");
}
}
else if (is_generate_region)
{
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Could not resolve conditional generate construct");
}
break;
}
case RANGE_REF:
case ARRAY_REF:
break;
case MODULE_INSTANCE:
// flip hard blocks
break;
case ALWAYS: // fallthrough
case INITIALS:
{
is_generate_region = false;
break;
}
default:
break;
}
if (node->num_children > 0 && skip_children == false)
{
/* use while loop and boolean to prevent optimizations
since number of children may change during recursion */
bool done = false;
int i = 0;
/* traverse all the children */
while (done == false)
{
int num_original_children = node->num_children;
if (child_skip_list[i] == false)
{
/* recurse */
ast_node_t *old_child = node->children[i];
ast_node_t *new_child = reduce_expressions(old_child, node, local_string_cache_list, max_size, assignment_size, is_generate_region);
node->children[i] = new_child;
if (old_child != new_child)
{
/* recurse on this child again in case it can be further reduced
(e.g. resolved generate constructs) */
i--;
}
}
if (num_original_children != node->num_children)
{
child_skip_list = (short *)vtr::realloc(child_skip_list, sizeof(short)*node->num_children);
for (int j = num_original_children; j < node->num_children; j++)
{
child_skip_list[j] = false;
}
}
i++;
if (i >= node->num_children)
{
done = true;
}
}
}
/* post-amble */
switch (node->type)
{
case MODULE_INSTANCE:
{
/* this should be encountered once generate constructs are resolved, so we don't have
stray instances that never get instantiated */
/* TODO: handle hard block instantiation here! */
if (node->num_children == 2)
{
char *instance_name_prefix = local_string_cache_list->instance_name_prefix;
long sc_spot = sc_lookup_string(module_names_to_idx, instance_name_prefix);
ast_node_t *module = (ast_node_t *)module_names_to_idx->data[sc_spot];
int num_instances = module->types.module.size_module_instantiations;
char *new_instance_name = node->children[1]->children[0]->types.identifier;
bool found = false;
for (int i = 0; i < num_instances; i++)
{
ast_node_t *temp_instance_node = module->types.module.module_instantiations_instance[i];
char *temp_instance_name = temp_instance_node->children[1]->children[0]->types.identifier;
if (strcmp(new_instance_name, temp_instance_name) == 0)
{
found = true;
}
}
if (found)
{
break;
}
module->types.module.module_instantiations_instance = (ast_node_t **)vtr::realloc(module->types.module.module_instantiations_instance, sizeof(ast_node_t*)*(num_instances+1));
module->types.module.module_instantiations_instance[num_instances] = node;
module->types.module.size_module_instantiations++;
}
break;
}
case VAR_DECLARE:
{
// pack 2d array into 1d
if (node->num_children == 8
&& node->children[5]
&& node->children[6])
{
convert_2D_to_1D_array(&node, local_string_cache_list);
}
break;
}
case FOR:
break;
case WHILE:
break;
case BINARY_OPERATION:
{
if (node->children[0] == NULL || node->children[1] == NULL)
{
/* resulting from replication of zero */
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Cannot perform operation with nonexistent value");
}
ast_node_t *new_node = fold_binary(&node);
if (node_is_constant(new_node))
{
/* resize as needed */
long new_size;
long this_size = new_node->types.vnumber->size();
if (assignment_size > 0)
{
new_size = assignment_size;
}
else if (max_size)
{
new_size = *max_size;
}
else
{
new_size = this_size;
}
/* clean up */
free_resolved_children(node);
change_to_number_node(node, VNumber(*(new_node->types.vnumber), new_size));
}
new_node = free_whole_tree(new_node);
break;
}
case UNARY_OPERATION:
{
if (node->children[0] == NULL)
{
/* resulting from replication of zero */
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Cannot perform operation with nonexistent value");
}
ast_node_t *new_node = fold_unary(&node);
if (node_is_constant(new_node))
{
/* resize as needed */
long new_size;
long this_size = new_node->types.vnumber->size();
if (assignment_size > 0)
{
new_size = assignment_size;
}
else if (max_size)
{
new_size = *max_size;
}
else
{
new_size = this_size;
}
/* clean up */
free_resolved_children(node);
change_to_number_node(node, VNumber(*(new_node->types.vnumber), new_size));
}
new_node = free_whole_tree(new_node);
break;
}
case REPLICATE:
{
/* remove intermediate REPLICATE node */
ast_node_t *child = node->children[0];
node->children[0] = NULL;
node = free_whole_tree(node);
node = child;
break;
}
case CONCATENATE:
{
resolve_concat_sizes(node, local_string_cache_list);
if (node->num_children > 0)
{
size_t current = 0;
size_t previous = -1;
bool previous_is_constant = false;
while (current < node->num_children)
{
bool current_is_constant = node_is_constant(node->children[current]);
if(previous_is_constant && current_is_constant)
{
VNumber new_value = V_CONCAT({*(node->children[previous]->types.vnumber), *(node->children[current]->types.vnumber)});
node->children[current] = free_whole_tree(node->children[current]);
delete node->children[previous]->types.vnumber;
node->children[previous]->types.vnumber = new VNumber(new_value);
}
else if(node->children[current] != NULL)
{
previous += 1;
previous_is_constant = current_is_constant;
node->children[previous] = node->children[current];
}
current += 1;
}
node->num_children = previous+1;
if (node->num_children == 0)
{
// could we simply warn and continue ? any ways we can recover rather than fail?
/* resulting replication(s) of zero */
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Cannot concatenate zero bitstrings");
// free_whole_tree(node);
// node = NULL;
}
// node was all constant
if (node->num_children == 1)
{
ast_node_t *tmp = node->children[0];
node->children[0] = NULL;
free_whole_tree(node);
node = tmp;
}
}
break;
}
case IDENTIFIERS:
{
// look up to resolve unresolved range refs
ast_node_t *var_node = NULL;
oassert(node->types.identifier);
long sc_spot = sc_lookup_string(local_symbol_table_sc, node->types.identifier);
if (sc_spot > -1)
{
var_node = (ast_node_t *)local_symbol_table_sc->data[sc_spot];
if (var_node->children[1] != NULL)
{
var_node->children[1] = reduce_expressions(var_node->children[1], var_node, local_string_cache_list, NULL, 0, is_generate_region);
var_node->children[2] = reduce_expressions(var_node->children[2], var_node, local_string_cache_list, NULL, 0, is_generate_region);
}
if (var_node->children[3] != NULL)
{
var_node->children[3] = reduce_expressions(var_node->children[3], var_node, local_string_cache_list, NULL, 0, is_generate_region);
var_node->children[4] = reduce_expressions(var_node->children[4], var_node, local_string_cache_list, NULL, 0, is_generate_region);
}
if (var_node->num_children == 8 && var_node->children[5])
{
var_node->children[5] = reduce_expressions(var_node->children[5], var_node, local_string_cache_list, NULL, 0, is_generate_region);
var_node->children[6] = reduce_expressions(var_node->children[6], var_node, local_string_cache_list, NULL, 0, is_generate_region);
}
local_symbol_table_sc->data[sc_spot] = (void *)var_node;
}
if (max_size)
{
long var_size = get_size_of_variable(node, local_string_cache_list);
if (var_size > *max_size)
{
*max_size = var_size;
}
}
break;
}
case NUMBERS:
{
if (max_size)
{
if (node->types.vnumber->size() > (*max_size))
{
*max_size = node->types.vnumber->size();
}
}
break;
}
case RANGE_REF:
{
bool is_constant_ref = node_is_constant(node->children[1]);
if (is_constant_ref)
{
is_constant_ref = is_constant_ref && !(node->children[1]->types.vnumber->is_dont_care_string());
}
is_constant_ref = is_constant_ref && node_is_constant(node->children[2]);
if (is_constant_ref)
{
is_constant_ref = is_constant_ref && !(node->children[2]->types.vnumber->is_dont_care_string());
}
if (!is_constant_ref)
{
/* note: indexed part-selects (-: and +:) should support non-constant base expressions,
e.g. my_var[some_input+:3] = 4'b0101, but we don't support it right now... */
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Part-selects can only contain constant expressions");
}
break;
}
case ARRAY_REF:
{
bool is_constant_ref = node_is_constant(node->children[1]);
if (is_constant_ref)
{
is_constant_ref = is_constant_ref && !(node->children[1]->types.vnumber->is_dont_care_string());
}
if (node->num_children == 3)
{
is_constant_ref = is_constant_ref && node_is_constant(node->children[2]);
if (is_constant_ref)
{
is_constant_ref = is_constant_ref && !(node->children[2]->types.vnumber->is_dont_care_string());
}
}
if (!is_constant_ref)
{
// this must be an implicit memory
long sc_spot = sc_lookup_string(local_symbol_table_sc, node->children[0]->types.identifier);
oassert(sc_spot > -1);
((ast_node_t *)local_symbol_table_sc->data[sc_spot])->types.variable.is_memory = true;
}
if (node->num_children == 3) convert_2D_to_1D_array_ref(&node, local_string_cache_list);
break;
}
case ALWAYS: // fallthrough
case INITIALS:
{
is_generate_region = true;
break;
}
default:
break;
}
if (child_skip_list)
{
child_skip_list = (short*)vtr::free(child_skip_list);
}
}
return node;
}
void update_string_caches(STRING_CACHE_LIST *local_string_cache_list)
{
ast_node_t **local_symbol_table = local_string_cache_list->local_symbol_table;
int num_local_symbol_table = local_string_cache_list->num_local_symbol_table;
for (int i = 0; i < num_local_symbol_table; i++)
{
ast_node_t *var_declare = local_symbol_table[i];
if ((var_declare->children[1] && !node_is_constant(var_declare->children[1]))
|| (var_declare->children[2] && !node_is_constant(var_declare->children[2]))
|| (var_declare->children[3] && !node_is_constant(var_declare->children[3]))
|| (var_declare->children[4] && !node_is_constant(var_declare->children[4]))
|| var_declare->num_children == 8
)
{
reduce_expressions(var_declare, NULL, local_string_cache_list, NULL, 0, false);
}
}
}
void convert_2D_to_1D_array(ast_node_t **var_declare, STRING_CACHE_LIST *local_string_cache_list)
{
char *instance_name_prefix = local_string_cache_list->instance_name_prefix;
ast_node_t *node_max2 = (*var_declare)->children[3];
ast_node_t *node_min2 = (*var_declare)->children[4];
ast_node_t *node_max3 = (*var_declare)->children[5];
ast_node_t *node_min3 = (*var_declare)->children[6];
oassert(node_min2->type == NUMBERS && node_max2->type == NUMBERS);
oassert(node_min3->type == NUMBERS && node_max3->type == NUMBERS);
long addr_min = node_min2->types.vnumber->get_value();
long addr_max = node_max2->types.vnumber->get_value();
long addr_min1= node_min3->types.vnumber->get_value();
long addr_max1= node_max3->types.vnumber->get_value();
if((addr_min > addr_max) || (addr_min1 > addr_max1))
{
error_message(NETLIST_ERROR, (*var_declare)->children[0]->line_number, (*var_declare)->children[0]->file_number, "%s",
"Odin doesn't support arrays declared [m:n] where m is less than n.");
}
else if((addr_min < 0 || addr_max < 0) || (addr_min1 < 0 || addr_max1 < 0))
{
error_message(NETLIST_ERROR, (*var_declare)->children[0]->line_number, (*var_declare)->children[0]->file_number, "%s",
"Odin doesn't support negative number in index.");
}
char *name = (*var_declare)->children[0]->types.identifier;
if (addr_min != 0 || addr_min1 != 0)
error_message(NETLIST_ERROR, (*var_declare)->children[0]->line_number, (*var_declare)->children[0]->file_number,
"%s: right memory address index must be zero\n", name);
long addr_chunk_size = (addr_max1 - addr_min1 + 1);
ast_node_t *new_node = create_tree_node_number(addr_chunk_size, (*var_declare)->children[0]->line_number, (*var_declare)->children[0]->file_number);
STRING_CACHE *local_param_table_sc = local_string_cache_list->local_param_table_sc;
long sc_spot;
char *temp_string = make_chunk_size_name(instance_name_prefix, name);
if ((sc_spot = sc_add_string(local_param_table_sc, temp_string)) == -1)
error_message(NETLIST_ERROR, (*var_declare)->children[0]->line_number, (*var_declare)->children[0]->file_number,
"%s: name conflicts with Odin internal reference\n", temp_string);
vtr::free(temp_string);
temp_string = NULL;
local_param_table_sc->data[sc_spot] = (void *)new_node;
long new_address_max = (addr_max - addr_min + 1)*addr_chunk_size -1;
change_to_number_node((*var_declare)->children[3], new_address_max);
change_to_number_node((*var_declare)->children[4], 0);
(*var_declare)->children[5] = free_whole_tree((*var_declare)->children[5]);
(*var_declare)->children[6] = free_whole_tree((*var_declare)->children[6]);
(*var_declare)->children[5] = (*var_declare)->children[7];
(*var_declare)->children[7] = NULL;
(*var_declare)->num_children -= 2;
}
void convert_2D_to_1D_array_ref(ast_node_t **node, STRING_CACHE_LIST *local_string_cache_list)
{
char *array_name = NULL;
ast_node_t *array_row = NULL;
ast_node_t *array_col = NULL;
ast_node_t *array_size = NULL;
ast_node_t *new_node_1 = NULL;
ast_node_t *new_node_2 = NULL;
char *instance_name_prefix = local_string_cache_list->instance_name_prefix;
array_name = vtr::strdup((*node)->children[0]->types.identifier);
array_size = get_chunk_size_node(instance_name_prefix, array_name, local_string_cache_list);
array_row = (*node)->children[1];
array_col = (*node)->children[2];
// build the new AST
new_node_1 = newBinaryOperation(MULTIPLY, array_row, array_size, (*node)->children[0]->line_number);
new_node_2 = newBinaryOperation(ADD, new_node_1, array_col, (*node)->children[0]->line_number);
vtr::free(array_name);
(*node)->children[1] = new_node_2;
(*node)->children[2] = NULL;
(*node)->num_children -= 1;
return;
}
/*--------------------------------------------------------------------------
* (function: make_chunk_size_name)
* This function creates a string to reference a 2D array chunk size for
* 1D array indexing.
*------------------------------------------------------------------------*/
char *make_chunk_size_name(char *instance_name_prefix, char *array_name)
{
std::string to_return(instance_name_prefix);
to_return += "__";
to_return += array_name;
to_return += "_____CHUNK_SIZE_DEFINE";
return vtr::strdup(to_return.c_str());
}
/*--------------------------------------------------------------------------
* (function: get_chunk_size_node)
* This function gets the chunk size node for a 2D array, to be used for
* 1D array indexing.
*------------------------------------------------------------------------*/
ast_node_t *get_chunk_size_node(char *instance_name_prefix, char *array_name, STRING_CACHE_LIST *local_string_cache_list)
{
ast_node_t *array_size = NULL;
long sc_spot;
STRING_CACHE *local_param_table_sc = local_string_cache_list->local_param_table_sc;
char *temp_string = NULL;
temp_string = make_chunk_size_name(instance_name_prefix, array_name);
// look up chunk size
sc_spot = sc_lookup_string(local_param_table_sc, temp_string);
oassert(sc_spot != -1);
if (sc_spot != -1)
{
array_size = ast_node_deep_copy((ast_node_t *)local_param_table_sc->data[sc_spot]);
}
vtr::free(temp_string);
return array_size;
}
bool verify_terminal(ast_node_t *top, ast_node_t *iterator)
{
if (top)
{
if (top->type == BINARY_OPERATION)
{
return verify_terminal(top->children[0], iterator) && verify_terminal(top->children[1], iterator);
}
else if (top->type == UNARY_OPERATION)
{
return verify_terminal(top->children[0], iterator);
}
else if (top->type == IDENTIFIERS)
{
return (strcmp(top->types.identifier, iterator->children[0]->types.identifier) == 0);
}
else
{
return node_is_constant(top);
}
}
else
{
return false;
}
}
void verify_genvars(ast_node_t *node, STRING_CACHE_LIST *local_string_cache_list, char ***other_genvars, int num_genvars)
{
if (node)
{
if (node->type == FOR)
{
STRING_CACHE *local_symbol_table_sc = local_string_cache_list->local_symbol_table_sc;
ast_node_t *initial = node->children[0];
ast_node_t *terminal = node->children[2];
ast_node_t *body = node->children[3];
ast_node_t *iterator = initial->children[0];
if (strcmp(initial->children[0]->types.identifier, terminal->children[0]->types.identifier) != 0)
{
/* must match */
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Must use the same genvar for initial condition and iteration condition");
}
long sc_spot = sc_lookup_string(local_symbol_table_sc, iterator->types.identifier);
if (sc_spot < 0)
{
error_message(NETLIST_ERROR, iterator->line_number, iterator->file_number,
"Missing declaration of this symbol %s\n", iterator->types.identifier);
}
else if (!((ast_node_t *)local_symbol_table_sc->data[sc_spot])->types.variable.is_genvar)
{
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Iterator for loop generate construct must be declared as a genvar");
}
// check genvars that were already found
for (int i=0; i < num_genvars; i++)
{
if (!strcmp(iterator->types.identifier, (*other_genvars)[i]))
{
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"%s","Cannot reuse a genvar in a nested loop sequence");
}
}
(*other_genvars) = (char **)vtr::realloc((*other_genvars), sizeof(char*)*(num_genvars+1));
(*other_genvars)[num_genvars] = iterator->types.identifier;
num_genvars++;
// look for nested loops to verify that each genvar is used in only one loop
for (int i=0; i < body->num_children; i++)
{
verify_genvars(body->children[i], local_string_cache_list, other_genvars, num_genvars);
}
}
else
{
// look for nested loops to verify that each genvar is used in only one loop
for (int i=0; i < node->num_children; i++)
{
verify_genvars(node->children[i], local_string_cache_list, other_genvars, num_genvars);
}
}
}
}
// /*---------------------------------------------------------------------------
// * (function: reduce_assignment_expression)
// * reduce the number nodes which can be calculated to optimize the AST
// *-------------------------------------------------------------------------*/
// void reduce_assignment_expression(ast_node_t *ast_module)
// {
// head = NULL;
// p = NULL;
// ast_node_t *T = NULL;
// if (count_id < ast_module->unique_count)
// count_id = ast_module->unique_count;
// count_assign = 0;
// std::vector<ast_node_t *> list_assign;
// find_assign_node(ast_module, list_assign, ast_module->children[0]->types.identifier);
// for (long j = 0; j < count_assign; j++)
// {
// if (check_tree_operation(list_assign[j]->children[1]) && (list_assign[j]->children[1]->num_children > 0))
// {
// store_exp_list(list_assign[j]->children[1]);
// if (simplify_expression())
// {
// enode *tail = find_tail(head);
// free_whole_tree(list_assign[j]->children[1]);
// T = (ast_node_t*)vtr::malloc(sizeof(ast_node_t));
// construct_new_tree(tail, T, list_assign[j]->line_number, list_assign[j]->file_number);
// list_assign[j]->children[1] = T;
// }
// free_exp_list();
// }
// }
// }
// /*---------------------------------------------------------------------------
// * (function: search_assign_node)
// * find the top of the assignment expression
// *-------------------------------------------------------------------------*/
// void find_assign_node(ast_node_t *node, std::vector<ast_node_t *> list, char *module_name)
// {
// if (node && node->num_children > 0 && (node->type == BLOCKING_STATEMENT || node->type == NON_BLOCKING_STATEMENT))
// {
// list.push_back(node);
// }
// for (long i = 0; node && i < node->num_children; i++)
// find_assign_node(node->children[i], list, module_name);
// }
// /*---------------------------------------------------------------------------
// * (function: simplify_expression)
// * simplify the expression stored in the linked_list
// *-------------------------------------------------------------------------*/
// bool simplify_expression()
// {
// bool build = adjoin_constant();
// reduce_enode_list();
// if(delete_continuous_multiply())
// build = true;
// if(combine_constant())
// build = true;
// reduce_enode_list();
// return build;
// }
// /*---------------------------------------------------------------------------
// * (function: find_tail)
// *-------------------------------------------------------------------------*/
// enode *find_tail(enode *node)
// {
// enode *temp;
// enode *tail = NULL;
// for (temp = node; temp != NULL; temp = temp->next)
// if (temp->next == NULL)
// tail = temp;
// return tail;
// }
// /*---------------------------------------------------------------------------
// * (function: reduce_enode_list)
// *-------------------------------------------------------------------------*/
// void reduce_enode_list()
// {
// enode *temp;
// int a;
// while(head != NULL && (head->type.data == 0) && (head->next->priority == 2) && (head->next->type.operation == '+')){
// temp=head;
// head = head->next->next;
// head->pre = NULL;
// vtr::free(temp->next);
// vtr::free(temp);
// }
// if(head == NULL){
// return;
// }
// temp = head->next;
// while (temp != NULL)
// {
// if ((temp->flag == 1) && (temp->pre->priority == 2))
// {
// if (temp->type.data == 0)
// {
// if (temp->next == NULL)
// temp->pre->pre->next = NULL;
// else
// {
// temp->pre->pre->next = temp->next;
// temp->next->pre = temp->pre->pre;
// }
// vtr::free(temp->pre);
// enode *toBeDeleted = temp;
// temp = temp->next;
// vtr::free(toBeDeleted);
// } else if (temp->type.data < 0)
// {
// if (temp->pre->type.operation == '+')
// temp->pre->type.operation = '-';
// else
// temp->pre->type.operation = '+';
// a = temp->type.data;
// temp->type.data = -a;
// temp = temp->next;
// } else {
// temp = temp->next;
// }
// } else {
// temp = temp->next;
// }
// }
// }
// /*---------------------------------------------------------------------------
// * (function: store_exp_list)
// *-------------------------------------------------------------------------*/
// void store_exp_list(ast_node_t *node)
// {
// enode *temp;
// head = (enode*)vtr::malloc(sizeof(enode));
// p = head;
// record_tree_info(node);
// temp = head;
// head = head->next;
// head->pre = NULL;
// p->next = NULL;
// vtr::free(temp);
// }
// /*---------------------------------------------------------------------------
// * (function: record_tree_info)
// *-------------------------------------------------------------------------*/
// void record_tree_info(ast_node_t *node)
// {
// if (node){
// if (node->num_children > 0)
// {
// record_tree_info(node->children[0]);
// create_enode(node);
// if (node->num_children > 1)
// record_tree_info(node->children[1]);
// }else{
// create_enode(node);
// }
// }
// }
// /*---------------------------------------------------------------------------
// * (function: create_enode)
// * store elements of an expression in nodes consisting the linked_list
// *-------------------------------------------------------------------------*/
// void create_enode(ast_node_t *node)
// {
// enode *s = (enode*)vtr::malloc(sizeof(enode));
// s->flag = -1;
// s->priority = -1;
// s->id = node->unique_count;
// switch (node->type)
// {
// case NUMBERS:
// {
// s->type.data = node->types.vnumber->get_value();
// s->flag = 1;
// s->priority = 0;
// break;
// }
// case BINARY_OPERATION:
// {
// s->flag = 2;
// switch(node->types.operation.op)
// {
// case ADD:
// {
// s->type.operation = '+';
// s->priority = 2;
// break;
// }
// case MINUS:
// {
// s->type.operation = '-';
// s->priority = 2;
// break;
// }
// case MULTIPLY:
// {
// s->type.operation = '*';
// s->priority = 1;
// break;
// }
// case DIVIDE:
// {
// s->type.operation = '/';
// s->priority = 1;
// break;
// }
// default:
// {
// break;
// }
// }
// break;
// }
// case IDENTIFIERS:
// {
// s->type.variable = node->types.identifier;
// s->flag = 3;
// s->priority = 0;
// break;
// }
// default:
// {
// break;
// }
// }
// p->next = s;
// s->pre = p;
// p = s;
// }
// /*---------------------------------------------------------------------------
// * (function: adjoin_constant)
// * compute the constant numbers in the linked_list
// *-------------------------------------------------------------------------*/
// bool adjoin_constant()
// {
// bool build = false;
// enode *t, *replace;
// int a, b, result = 0;
// int mark;
// for (t = head; t->next!= NULL; )
// {
// mark = 0;
// if ((t->flag == 1) && (t->next->next != NULL) && (t->next->next->flag ==1))
// {
// switch (t->next->priority)
// {
// case 1:
// a = t->type.data;
// b = t->next->next->type.data;
// if (t->next->type.operation == '*')
// result = a * b;
// else
// result = a / b;
// replace = replace_enode(result, t, 1);
// build = true;
// mark = 1;
// break;
// case 2:
// if (((t == head) || (t->pre->priority == 2)) && ((t->next->next->next == NULL) ||(t->next->next->next->priority ==2)))
// {
// a = t->type.data;
// b = t->next->next->type.data;
// if (t->pre->type.operation == '+')
// {
// if (t->next->type.operation == '+')
// result = a + b;
// else
// result = a - b;
// }
// if (t->pre->type.operation == '-')
// {
// if (t->next->type.operation == '+')
// result = a - b;
// else
// result = a + b;
// }
// replace = replace_enode(result, t, 1);
// build = true;
// mark = 1;
// }
// break;
// default:
// //pass
// break;
// }
// }
// if (mark == 0)
// t = t->next;
// else
// if (mark == 1)
// t = replace;
// }
// return build;
// }
// /*---------------------------------------------------------------------------
// * (function: replace_enode)
// *-------------------------------------------------------------------------*/
// enode *replace_enode(int data, enode *t, int mark)
// {
// enode *replace;
// replace = (enode*)vtr::malloc(sizeof(enode));
// replace->type.data = data;
// replace->flag = 1;
// replace->priority = 0;
// if (t == head)
// {
// replace->pre = NULL;
// head = replace;
// }
// else
// {
// replace->pre = t->pre;
// t->pre->next = replace;
// }
// if (mark == 1)
// {
// replace->next = t->next->next->next;
// if (t->next->next->next == NULL)
// replace->next = NULL;
// else
// t->next->next->next->pre = replace;
// vtr::free(t->next->next);
// vtr::free(t->next);
// }
// else
// {
// replace->next = t->next;
// t->next->pre = replace;
// }
// vtr::free(t);
// return replace;
// }
// /*---------------------------------------------------------------------------
// * (function: combine_constant)
// *-------------------------------------------------------------------------*/
// bool combine_constant()
// {
// enode *temp, *m, *s1, *s2, *replace;
// int a, b, result;
// int mark;
// bool build = false;
// for (temp = head; temp != NULL; )
// {
// mark = 0;
// if ((temp->flag == 1) && (temp->next != NULL) && (temp->next->priority == 2))
// {
// if ((temp == head) || (temp->pre->priority == 2))
// {
// for (m = temp->next; m != NULL; m = m->next)
// {
// if((m->flag == 1) && (m->pre->priority == 2) && ((m->next == NULL) || (m->next->priority == 2)))
// {
// s1 = temp;
// s2 = m;
// a = s1->type.data;
// b = s2->type.data;
// if ((s1 == head) || (s1->pre->type.operation == '+'))
// {
// if (s2->pre->type.operation == '+')
// result = a + b;
// else
// result = a - b;
// }
// else
// {
// if (s2->pre->type.operation == '+')
// result = a - b;
// else
// result = a + b;
// }
// replace = replace_enode(result, s1, 2);
// if (s2->next == NULL)
// {
// s2->pre->pre->next = NULL;
// mark = 2;
// }
// else
// {
// s2->pre->pre->next = s2->next;
// s2->next->pre = s2->pre->pre;
// }
// vtr::free(s2->pre);
// vtr::free(s2);
// if (replace == head)
// {
// temp = replace;
// mark = 1;
// }
// else
// temp = replace->pre;
// build = true;
// break;
// }
// }
// }
// }
// if (mark == 0)
// temp = temp->next;
// else
// if (mark == 1)
// continue;
// else
// break;
// }
// return build;
// }
// /*---------------------------------------------------------------------------
// * (function: construct_new_tree)
// *-------------------------------------------------------------------------*/
// void construct_new_tree(enode *tail, ast_node_t *node, int line_num, int file_num)
// {
// enode *temp, *tail1 = NULL, *tail2 = NULL;
// int prio = 0;
// if (tail == NULL)
// return;
// prio = check_exp_list(tail);
// if (prio == 1)
// {
// for (temp = tail; temp != NULL; temp = temp->pre)
// if ((temp->flag == 2) && (temp->priority == 2))
// {
// create_ast_node(temp, node, line_num, file_num);
// tail1 = temp->pre;
// tail2 = find_tail(temp->next);
// tail1->next = NULL;
// temp->next->pre = NULL;
// break;
// }
// }
// else
// if(prio == 2)
// {
// for (temp = tail; temp != NULL; temp = temp->pre)
// if ((temp->flag ==2) && (temp->priority == 1))
// {
// create_ast_node(temp, node, line_num, file_num);
// tail1 = temp->pre;
// tail2 = temp->next;
// tail2->pre = NULL;
// tail2->next = NULL;
// break;
// }
// }
// else
// if (prio == 3)
// create_ast_node(tail, node, line_num, file_num);
// if (prio == 1 || prio == 2)
// {
// node->children = (ast_node_t**)vtr::malloc(2*sizeof(ast_node_t*));
// node->children[0] = (ast_node_t*)vtr::malloc(sizeof(ast_node_t));
// node->children[1] = (ast_node_t*)vtr::malloc(sizeof(ast_node_t));
// create_ast_node(tail1, node->children[0], line_num, file_num);
// create_ast_node(tail2, node->children[1], line_num, file_num);
// construct_new_tree(tail1, node->children[0], line_num, file_num);
// construct_new_tree(tail2, node->children[1], line_num, file_num);
// }
// return;
// }
// /*---------------------------------------------------------------------------
// * (function: check_exp_list)
// *-------------------------------------------------------------------------*/
// int check_exp_list(enode *tail)
// {
// enode *temp;
// for (temp = tail; temp != NULL; temp = temp->pre)
// if ((temp->flag == 2) && (temp->priority == 2))
// return 1;
// for (temp = tail; temp != NULL; temp = temp->pre)
// if ((temp->flag == 2) && (temp->priority ==1))
// return 2;
// return 3;
// }
// /*---------------------------------------------------------------------------
// * (function: delete_continuous_multiply)
// *-------------------------------------------------------------------------*/
// bool delete_continuous_multiply()
// {
// enode *temp, *t, *m, *replace;
// bool build = false;
// int a, b, result;
// int mark;
// for (temp = head; temp != NULL; )
// {
// mark = 0;
// if ((temp->flag == 1) && (temp->next != NULL) && (temp->next->priority == 1))
// {
// for (t = temp->next; t != NULL; t = t->next)
// {
// if ((t->flag == 1) && (t->pre->priority ==1))
// {
// for (m = temp->next; m != t; m = m->next)
// {
// if ((m->flag == 2) && (m->priority != 1))
// {
// mark = 1;
// break;
// }
// }
// if (mark == 0)
// {
// a = temp->type.data;
// b = t->type.data;
// if (t->pre->type.operation == '*')
// result = a * b;
// else
// result = a / b;
// replace = replace_enode(result, temp, 3);
// if (t->next == NULL)
// t->pre->pre->next = NULL;
// else
// {
// t->pre->pre->next = t->next;
// t->next->pre = t->pre->pre;
// }
// mark = 2;
// build = true;
// vtr::free(t->pre);
// vtr::free(t);
// break;
// }
// break;
// }
// }
// }
// if ((mark == 0) || (mark == 1))
// temp = temp->next;
// else
// if (mark == 2)
// temp = replace;
// }
// return build;
// }
// /*---------------------------------------------------------------------------
// * (function: create_ast_node)
// *-------------------------------------------------------------------------*/
// void create_ast_node(enode *temp, ast_node_t *node, int line_num, int file_num)
// {
// switch(temp->flag)
// {
// case 1:
// initial_node(node, NUMBERS, line_num, file_num, ++count_id);
// change_to_number_node(node, temp->type.data);
// break;
// case 2:
// create_op_node(node, temp, line_num, file_num);
// break;
// case 3:
// initial_node(node, IDENTIFIERS, line_num, file_num, ++count_id);
// node->types.identifier = vtr::strdup(temp->type.variable.c_str());
// break;
// default:
// break;
// }
// }
// /*---------------------------------------------------------------------------
// * (function: create_op_node)
// *-------------------------------------------------------------------------*/
// void create_op_node(ast_node_t *node, enode *temp, int line_num, int file_num)
// {
// initial_node(node, BINARY_OPERATION, line_num, file_num, ++count_id);
// node->num_children = 2;
// switch(temp->type.operation)
// {
// case '+':
// node->types.operation.op = ADD;
// break;
// case '-':
// node->types.operation.op = MINUS;
// break;
// case '*':
// node->types.operation.op = MULTIPLY;
// break;
// case '/':
// node->types.operation.op = DIVIDE;
// break;
// default:
// oassert(false);
// break;
// }
// }
// /*---------------------------------------------------------------------------
// * (function: free_exp_list)
// *-------------------------------------------------------------------------*/
// void free_exp_list()
// {
// enode *next, *temp;
// for (temp = head; temp != NULL; temp = next)
// {
// next = temp->next;
// vtr::free(temp);
// }
// }
// /*---------------------------------------------------------------------------
// * (function: change_exp_list)
// *-------------------------------------------------------------------------*/
// void change_exp_list(enode *begin, enode *end, enode *s, int flag)
// {
// enode *temp, *new_head, *tail, *p2, *partial = NULL, *start = NULL;
// int mark;
// switch (flag)
// {
// case 1:
// {
// for (temp = begin; temp != end; temp = p2->next)
// {
// mark = 0;
// for (p2 = temp; p2 != end->next; p2 = p2->next)
// {
// if (p2 == end)
// {
// mark = 2;
// break;
// }
// if ((p2->flag == 2) && (p2->priority == 2))
// {
// partial = p2->pre;
// mark = 1;
// break;
// }
// }
// if (mark == 1)
// {
// new_head = (enode*)vtr::malloc(sizeof(enode));
// tail = copy_enode_list(new_head, end->next, s);
// tail = tail->pre;
// vtr::free(tail->next);
// partial->next = new_head;
// new_head->pre = partial;
// tail->next = p2;
// p2->pre = tail;
// }
// if (mark == 2)
// break;
// }
// break;
// }
// case 2:
// {
// for (temp = begin; temp != end->next; temp = temp->next)
// if ((temp->flag == 2) && (temp->priority == 2))
// {
// start = temp;
// break;
// }
// for (temp = start; temp != end->next; temp = partial->next)
// {
// mark = 0;
// for (p2 = temp; p2 != end->next; p2 = p2->next)
// {
// if (p2 == end)
// {
// mark = 2;
// break;
// }
// if ((p2->flag == 2) && (p2->priority == 2))
// {
// partial = p2->next;
// mark = 1;
// break;
// }
// }
// if (mark == 1)
// {
// new_head = (enode*)vtr::malloc(sizeof(enode));
// tail = copy_enode_list(new_head, s, begin->pre);
// tail = tail->pre;
// vtr::free(tail->next);
// p2->next = new_head;
// new_head->pre = p2;
// tail->next = partial;
// partial->pre = tail;
// }
// if (mark == 2)
// break;
// }
// break;
// }
// default:
// break;
// }
// }
// /*---------------------------------------------------------------------------
// * (function: copy_enode_list)
// *-------------------------------------------------------------------------*/
// enode *copy_enode_list(enode *new_head, enode *begin, enode *end)
// {
// enode *temp, *new_enode, *next_enode;
// new_enode = new_head;
// for (temp = begin; temp != end->next; temp = temp->next)
// {
// copy_enode(temp, new_enode);
// next_enode = (enode*)vtr::malloc(sizeof(enode));
// new_enode->next = next_enode;
// next_enode->pre = new_enode;
// new_enode = next_enode;
// }
// return new_enode;
// }
// /*---------------------------------------------------------------------------
// * (function: copy_enode)
// *-------------------------------------------------------------------------*/
// void copy_enode(enode *node, enode *new_node)
// {
// new_node->type = node->type;
// new_node->flag = node->flag;
// new_node->priority = node->priority;
// new_node->id = -1;
// }
// /*---------------------------------------------------------------------------
// * (function: check_tree_operation)
// *-------------------------------------------------------------------------*/
// bool check_tree_operation(ast_node_t *node)
// {
// if (node && (node->type == BINARY_OPERATION) && ((node->types.operation.op == ADD ) || (node->types.operation.op == MINUS) || (node->types.operation.op == MULTIPLY)))
// return true;
// for (long i = 0; node && i < node->num_children; i++)
// if(check_tree_operation(node->children[i]))
// return true;
// return false;
// }
// /*---------------------------------------------------------------------------
// * (function: check_operation)
// *-------------------------------------------------------------------------*/
// void check_operation(enode *begin, enode *end)
// {
// enode *temp, *op;
// for (temp = begin; temp != head; temp = temp->pre)
// {
// if (temp->flag == 2 && temp->priority == 2 && temp->type.operation == '-')
// {
// for (op = begin; op != end; op = op->next)
// {
// if (op->flag == 2 && op->priority == 2)
// {
// if (op->type.operation == '+')
// op->type.operation = '-';
// else
// op->type.operation = '+';
// }
// }
// }
// }
// }