/****************************************************************************** -------------------------------------------------------------------------- -------------------------------------------------------------------------- -- File Name : routines.cc -- File type : GNU/ES-Kit C++ file -- Introduction : Contains routines of CLASS_NAME. The class -- should be defined externally using a #define. -- Date Created : Jan 10, 1991. -- -- Author : Jayanta Roy -- Affiliation : University of Cincinnati, -- Department of Computer Engg. -- -- This document was created as a part of the project funded by -- the Defense Advanced Research Projects Agency under order no. -- 7056 monitored by the Federal Bureau of Investigation under -- contract no. J-FBI-89-094 and by the University of Cincinnati -- Research Council. -- -- Use of this document is strictly prohibited to those members of -- the community who do not beleive in sharing their efforts with -- others. Duplication and distribution is limited to specific -- request to the author. -- -- Copyright (C) 1990 -- University of Cincinnati, The Ohio Board of Regents -- Jayanta Roy and Ranga Vemuri -- All Rights Reserved -- -------------------------------------------------------------------------- -- Modification History : -- Till Jan 25/91 : Stabilized the code. -- Jan 26/91 : Make the CLASS_NAME generic. -- Feb 25/91 : Added mk_wait_module() to take care of WAITs. -- Feb 26/91 : Removed all the field initializations for -- structures. Initializations are performed in -- the structure declarations. -- May 6/91 : Distributed the deletion of last operator of all -- select branches from pop_SSR() into mk_branch() -- and cl_select_op(). -- May 7/91 : Modified mk_alias() such that "alias"es are -- treated as locals to the module they are declared -- in. The Symbol Table entry of the "alias"es -- captures all information about their parent. -- May 7/91 : Debugged mk_operator() to avoid duplicate constant -- records of same width and value. -- May 14/91 : Modified pop_SSR() so that all the outputs of the -- parent SELECT operator get reflected in the -- carrier list of the parent level. -- May 14/91 : Modified update_parent() - It does not modify the -- carrier list of the parent SELECT envioronment -- any more. It's done in pop_SSR() instead. -- May 20/91 : Introduced mk_procedure() and mk_formal_param() -- to take care of procedure declarations. -- May 21/91 : Introduced procedure_call() to take care of -- procedure calls. -- May 22/91 : Modified the following to take care of procedure -- declarations in packages - -- (1) mk_arch_module(), -- (2) push(), -- May 24/91 : Added an extra field for the RD/WR operator that -- indicates the start bit of the RD/WR. -- May 25/91 : Got rid of all the "aliases". Any alias now -- directly refers to their parents. Any time a -- "alias" is referred, a "RD" or "WR" operator -- is created to take care of the "alias". Routines -- affected are - -- (1)mk_alias(), (2)source_id(), (3)mk_operator(), -- (4)simple_assignment(), (5)update_carrier_info(), -- (6)update_parent(), (7)procedure_call(). -- May 30/91 : Changed SELECT operator handling. The mk_select_op() -- does not create the next operator anymore. It is -- done by the corresponding cl_select_op(). In this -- scenerio, we do not need the curr_op_ptr field in -- the select_stack_rec. Routines effected are - -- (1)mk_select_op(), (2)cl_select_op(), (3)pop_SSR(). -- May 30/91 : Added debug information in get_op_ptr() to detect -- any persisting blank operators. -- May 30/91 : Debugged source_arr(). It was not handling constant -- indexes properly. -- Jun 3/91 : Added the CONCAT operator in the mk_operator(). -- Right now I am doing a very straight forward thing -- of producing a merged output. May need to change at -- a later stage. -- Jun 4/91 : Added routine to handle all sort of constants (eg. -- HEX, OCT, BIN, DEC etc.) -- str2num(). -- Jun 4/91 : Added definitions of two routines that are s'posed -- to handle explicit r-value range specifications -- of VHDL expressions. These routines are - -- (1)mk_range_rec(), (2)range_spec(). -- Jun 15/91 : Added initialize_storage() to take care of all the -- signal/variable declaration time initializations. -- Jun 17/91 : Modified the way symbols are stored. Instead of -- saving them in the main symbol table, now we have -- symbol tables corresponding to each module. So, -- for every storage/alias declaration, the info is -- is stored in the corresponding modules. This will -- affect looking for the symbols. Routines affected : -- (1) mk_reg(), (2) mk_alias, (3) mk_formal(), -- (4) get_STR_ptr(). -- Jun 17/91 : Taken out use of curr_STR_ptr (for convenience). -- Routines affected are : -- (1) mk_entity(), (2) mk_interface(), -- (3) mk_wait_module(), (4) mk_loop_module(), -- (5) mk_conc_stmnt_module(), (6) mk_proc_module(). -- Jun 17/91 : Modified the way carrier_info is manipulated. A -- carrier_info record is created for abstract operator -- like RD/ARRRD - even if these operators don't modify -- the storage. These records are stored at the end of -- the list. Certain functions needs access to the -- storage that these operator outputs refer to - and -- hence this arrangement. Once these operator outputs -- are modified, the corresponding carrier_info recs -- are deleted from the list. Routines affected are - -- (1) source_arr(), (2) source_id(), -- Jun 19/91 : Modified the way I was updating the current module's -- output. Previously, I was updating only for signals. -- Now, we update if lhs is formal and if lhs is a -- variable and current module is a loop. Routines -- affected are - -- (1) simple_assignment(), (2) array_assignment(), -- (3) mk_ENTER(). -- July 17/91 : Modified mk_select_op(). Made sure that the SELECT -- operator's parent is always a RD operator. -- Sept 5/91 : Re-modified source_id() so that any operator -- created due to reading an alias does not effect -- the carrier info. This nullifies the modification -- of Jun 17/91. It makes more sense, as source_id() -- is used to read data, it does not modify the -- storage to reflect in the carrier info. -- Sept 5/91 : Modified get_op_inp_STR_ptr(). If it is called -- with an inp_id that refers to the output of a -- operator, that reads an alias, it returns the -- STR of the alias. Previously it was returning the -- STR of the parent. -- Sept 5/91 : Modified simple_assignment() to take care of -- writes into aliases. It is done via the use of -- the operator that identifies the start bit -- and the width of the destination storage. -- Sept 5/91 : An Observation : The above three changes -- effectively nullifies the reason why I chosen to -- let source_id() modify the carrier info in case -- of an alias read. It had to do with the routine -- procedure_call() and handling of the actuals that -- were aliases. -- PENDING MODIFICATION : Proper scaling of array indexing. -------------------------------------------------------------------------- -------------------------------------------------------------------------- ******************************************************************************/ void CLASS_NAME :: mk_entity(char *name) { // This routine does the following -- // (1) Creates a symbol table entry for the entity // (2) Assigns "curr_ent_STR_ptr" to this record #ifdef DEBUG cout << "Entered : mk_entity()\n"; #endif // Create the record symbol_table_rec *STR_ptr=(symbol_table_rec *) new symbol_table_rec; STR_ptr->symbol_id=this->rename("e",STR_cnt++); STR_ptr->name=(char *) new char[strlen(name)+1]; strcpy(STR_ptr->name,name); delete name; // set the curr_ent_STR_ptr curr_ent_STR_ptr=STR_ptr; // insert in the Symbol Table symbol_table_rec *tmp_STR_ptr=global_STR_ptr; if (tmp_STR_ptr){ for(;tmp_STR_ptr->next_str_ptr != NULL; tmp_STR_ptr=tmp_STR_ptr->next_str_ptr); tmp_STR_ptr->next_str_ptr=STR_ptr; } else global_STR_ptr=STR_ptr; #ifdef DEBUG cout << "Leaving : mk_entity()\n"; #endif VOID_RETURN; } void CLASS_NAME :: mk_interface(id_rec *id_list,int mode, type_mark *type_mark_ptr) { // For each entry in the id_list, it creates an entity of type port. // It uses the "curr_ent_STR_ptr" to find the id of the parent. // Inserts the entries at the end of the symbol table #ifdef DEBUG cout << "Entered : mk_interface()\n"; #endif id_rec *id_ptr; symbol_table_rec *STR_ptr, *res_fn_STR_ptr; for(id_ptr = id_list; id_ptr != 0; id_ptr = id_ptr->next_id_ptr) { STR_ptr = (symbol_table_rec *) new symbol_table_rec; STR_ptr->symbol_id=this->rename("s",STR_cnt++); STR_ptr->parent_id=(char *) new char[strlen(curr_ent_STR_ptr->symbol_id)+1]; strcpy(STR_ptr->parent_id,curr_ent_STR_ptr->symbol_id); STR_ptr->mode=mode; STR_ptr->flags.is_port=1; STR_ptr->name=(char *) new char[strlen(id_ptr->id)+1]; strcpy(STR_ptr->name,id_ptr->id); // now for the type information if (type_mark_ptr->type == ARRAY){ STR_ptr->flags.is_array = 1; STR_ptr->word_struct.from=type_mark_ptr->arr_from; STR_ptr->word_struct.to=type_mark_ptr->arr_to; } STR_ptr->flags.is_bit_vector = 1; STR_ptr->bit_struct.from=type_mark_ptr->bit_from; STR_ptr->bit_struct.to=type_mark_ptr->bit_to; // It may have a resolution fn if (type_mark_ptr->res_fn_name){ res_fn_STR_ptr=this->get_STR_ptr(type_mark_ptr->res_fn_name); STR_ptr->resn_fn_id=(char *) new char[strlen(res_fn_STR_ptr->symbol_id)+1]; strcpy(STR_ptr->resn_fn_id,res_fn_STR_ptr->symbol_id); } // now enter the record in the symbol table symbol_table_rec *tmp_STR_ptr=global_STR_ptr; if (tmp_STR_ptr){ for(;tmp_STR_ptr->next_str_ptr != NULL; tmp_STR_ptr=tmp_STR_ptr->next_str_ptr); tmp_STR_ptr->next_str_ptr=STR_ptr; } else global_STR_ptr=STR_ptr; } // free the id_rec_list this->free_id(id_list); #ifdef DEBUG cout << "Leaving : mk_interface()\n"; #endif VOID_RETURN; } type_mark* CLASS_NAME :: typemark(int type,int from,int to,type_mark *ret_ptr) { ret_ptr->type = type; ret_ptr->arr_from = from; ret_ptr->arr_to = to; PTR_RETURN(ret_ptr); } type_mark* CLASS_NAME :: basetype(int from,int to) { type_mark *ptr = new type_mark; ptr->bit_from = from; ptr->bit_to = to; PTR_RETURN(ptr); } id_rec* CLASS_NAME :: identifier_list(char *name,id_rec *list) { id_rec *ptr; ptr = (id_rec *) new id_rec; ptr->id = (char *) new char[strlen(name)+1]; strcpy(ptr->id,name); ptr->next_id_ptr = list; PTR_RETURN(ptr); } int CLASS_NAME :: _index(int val1,int direction,int val2) { if (direction == TO) /* ie. direction is "to" */ {INT_RETURN(val1);} else /* ie. direction is "downto" */ {INT_RETURN(val2);} } void CLASS_NAME :: mk_alias(char *name, type_mark *type_mark_ptr, char *alias_of_name, int start_index) { /******************************************************************** Aliases are treated as aliases. The inputs of the module are checked to see if the parent is present. If not, the parent is added as the module input. For such a case to occur, the parent of the alias has to be global in scope to the current module. Algo - (1) Create a Symbol Table Record for the alias. (2) Create a Constant record that indicates the start index of the alias. (3) Update the input list of the current module - if needed. (4) Update the carrier info if needed. ********************************************************************/ #ifdef DEBUG cout << "Entered : mk_alias()\n"; #endif int i,j,width; symbol_table_rec *alias_of_STR_ptr; symbol_table_rec *STR_ptr=(symbol_table_rec *) new symbol_table_rec; inout *IO_ptr, *tmp_IO_ptr; carrier_info *tmp_CI_ptr; // Create the Symbol Table Rec for the alias -- Step (1) STR_ptr->symbol_id=this->rename("A",STR_cnt); // do not increment STR_cnt STR_ptr->name=(char *) new char[strlen(name)+1]; strcpy(STR_ptr->name,name); STR_ptr->parent_id=(char*) new char[strlen(curr_MR_ptr->str_ptr->symbol_id)+1]; strcpy(STR_ptr->parent_id,curr_MR_ptr->str_ptr->symbol_id); // type information STR_ptr->bit_struct.from=type_mark_ptr->bit_from; STR_ptr->bit_struct.to=type_mark_ptr->bit_to; // alias specific information STR_ptr->flags.is_alias=1; STR_ptr->alias_info.alias_of=this->get_STR_ptr(alias_of_name); STR_ptr->alias_info.start_index=start_index; // Create the constant table rec width=((i=(STR_ptr->alias_info.alias_of->bit_struct.from - STR_ptr->alias_info.alias_of->bit_struct.to)) > 0 ? i+1:1-i); // Add the constant record STR_ptr->alias_info.cr_ptr=this->add_constant(this->log2(width),start_index); // If needed, update module rec input_list -- Step (3) tmp_IO_ptr=curr_MR_ptr->input_list; for(;tmp_IO_ptr != NULL;tmp_IO_ptr=tmp_IO_ptr->next_io_ptr) if(strcmp(tmp_IO_ptr->destn_id,STR_ptr->alias_info.alias_of->symbol_id)==0) break; if (tmp_IO_ptr==NULL){ // Create an inout record IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("i",MO_inp_cnt++); IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->alias_info.alias_of->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->alias_info.alias_of->symbol_id); IO_ptr->width=width; IO_ptr->name=(char*) new char[strlen(STR_ptr->alias_info.alias_of->name)+1]; strcpy(IO_ptr->name,STR_ptr->alias_info.alias_of->name); if(tmp_IO_ptr=curr_MR_ptr->input_list){ for(;tmp_IO_ptr->next_io_ptr != NULL;tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=IO_ptr; } else curr_MR_ptr->input_list=IO_ptr; // Update the carrier_info of the module_rec -- Step (3) tmp_CI_ptr=(carrier_info*) new carrier_info; tmp_CI_ptr->str_ptr=STR_ptr->alias_info.alias_of; tmp_CI_ptr->op_inp_id=(char*) new char[strlen(STR_ptr->parent_id)+strlen(IO_ptr->inout_id)+2]; // Create the op_inp_id i=j=0; while((tmp_CI_ptr->op_inp_id[i++] = STR_ptr->parent_id[j++]) != '\0'); j=0;--i; tmp_CI_ptr->op_inp_id[i++]='.'; while((tmp_CI_ptr->op_inp_id[i++] = IO_ptr->inout_id[j++]) != '\0'); tmp_CI_ptr->next_ci_ptr=CI_ptr; CI_ptr=tmp_CI_ptr; } // now enter the record in the symbol table symbol_table_rec *tmp_STR_ptr=curr_MR_ptr->STR_list; if (tmp_STR_ptr){ for(;tmp_STR_ptr->next_str_ptr != NULL; tmp_STR_ptr=tmp_STR_ptr->next_str_ptr); tmp_STR_ptr->next_str_ptr=STR_ptr; } else curr_MR_ptr->STR_list=STR_ptr; // free some space delete name; delete alias_of_name; #ifdef DEBUG cout << "Leaving : mk_alias()\n"; #endif VOID_RETURN; } void CLASS_NAME :: mk_reg(id_rec *name_list,type_mark *type_mark_ptr, constant_rec *init_CR_list,int type) { /********************************************************************** This routine processes information about storage. Common operations :- (1) Create a symbol table entry for each name in the id_list. (2) Put it at the end of the symbol table.(Of the current_module). Type specific operations :- (1) Creates an inout record for the "module_rec" and puts it in it's input list. (2) Creates operators for initializing the storage - if needed. (2) Creates an "carrier information" entry to be used later while processing the process body. Global variables used :- (1) global_STR_ptr (2) curr_MR_ptr (3) CI_ptr ************************************************************************/ #ifdef DEBUG cout << "Entered : mk_reg()\n"; #endif id_rec *id_rec_ptr; symbol_table_rec *STR_ptr, *res_fn_STR_ptr; inout *IO_ptr, *tmp_IO_ptr; carrier_info *tmp_CI_ptr; int i, j, width; // create a symbol table entry for each name in the id_list for(id_rec_ptr=name_list;id_rec_ptr != 0; id_rec_ptr=id_rec_ptr->next_id_ptr){ // Create the STR STR_ptr=(symbol_table_rec *) new symbol_table_rec; STR_ptr->symbol_id=this->rename("s",STR_cnt++); STR_ptr->parent_id=(char*) new char[strlen(curr_MR_ptr->str_ptr->symbol_id)+1]; strcpy(STR_ptr->parent_id,curr_MR_ptr->str_ptr->symbol_id); STR_ptr->name=(char *) new char[strlen(id_rec_ptr->id)+1]; strcpy(STR_ptr->name,id_rec_ptr->id); // now for the type information if (type_mark_ptr->type == ARRAY){ STR_ptr->flags.is_array = 1; STR_ptr->word_struct.from=type_mark_ptr->arr_from; STR_ptr->word_struct.to=type_mark_ptr->arr_to; } STR_ptr->flags.is_bit_vector = 1; STR_ptr->bit_struct.from=type_mark_ptr->bit_from; STR_ptr->bit_struct.to=type_mark_ptr->bit_to; // It may have a resolution fn if (type_mark_ptr->res_fn_name){ res_fn_STR_ptr=this->get_STR_ptr(type_mark_ptr->res_fn_name); STR_ptr->resn_fn_id=(char *) new char[strlen(res_fn_STR_ptr->symbol_id)+1]; strcpy(STR_ptr->resn_fn_id,res_fn_STR_ptr->symbol_id); } // Type dependent processing // Update module rec input_list IO_ptr=(inout*) new inout; switch (type){ case VARIABLE : STR_ptr->flags.is_variable=1; IO_ptr->inout_id=this->rename("l",MO_inp_cnt++); break; case SIGNAL : STR_ptr->flags.is_signal=1; IO_ptr->inout_id=this->rename("l",MO_inp_cnt++); break; } IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->symbol_id); width=((i=(STR_ptr->bit_struct.from - STR_ptr->bit_struct.to)) > 0 ? i+1 : 1-i); IO_ptr->width=width; IO_ptr->name=(char*) new char[strlen(id_rec_ptr->id)+1]; strcpy(IO_ptr->name,id_rec_ptr->id); if(tmp_IO_ptr=curr_MR_ptr->input_list){ for(;tmp_IO_ptr->next_io_ptr != 0;tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=IO_ptr; } else curr_MR_ptr->input_list=IO_ptr; // Update the carrier_info of the module_rec tmp_CI_ptr=(carrier_info*) new carrier_info; tmp_CI_ptr->str_ptr=STR_ptr; tmp_CI_ptr->op_inp_id=(char*) new char[strlen(STR_ptr->parent_id)+strlen(IO_ptr->inout_id)+2]; // Create the op_inp_id i=j=0; while((tmp_CI_ptr->op_inp_id[i++] = STR_ptr->parent_id[j++]) != '\0'); j=0;--i; tmp_CI_ptr->op_inp_id[i++]='.'; while((tmp_CI_ptr->op_inp_id[i++] = IO_ptr->inout_id[j++]) != '\0'); tmp_CI_ptr->next_ci_ptr=CI_ptr; CI_ptr=tmp_CI_ptr; // now enter the record in the symbol table symbol_table_rec *tmp_STR_ptr=curr_MR_ptr->STR_list; if (tmp_STR_ptr){ for(;tmp_STR_ptr->next_str_ptr != NULL; tmp_STR_ptr=tmp_STR_ptr->next_str_ptr); tmp_STR_ptr->next_str_ptr=STR_ptr; } else curr_MR_ptr->STR_list=STR_ptr; // Now perform any initializations needed if (init_CR_list) this->initialize_storage(STR_ptr,init_CR_list); } // end for // Free some space this->free_id(name_list); #ifdef DEBUG cout << "Leaving : mk_reg()\n"; #endif VOID_RETURN; } void CLASS_NAME :: mk_formal_param(int cl_type,id_rec *name_list,int mode, type_mark *type_mark_ptr) { /********************************************************************** This routine processes information about formal parameters. Common operations :- (1) Create a symbol table entry for each name in the id_list. (2) Put it at the end of the symbol table. Type specific operations :- (1) Creates an inout record for the "module_rec" and puts it in it's input list. (2) Creates an "carrier information" entry to be used later while processing the process body. Global variables used :- (1) global_STR_ptr (2) curr_MR_ptr (3) CI_ptr ************************************************************************/ #ifdef DEBUG cout << "Entered : mk_formal_param()\n"; #endif id_rec *id_rec_ptr; symbol_table_rec *STR_ptr, *res_fn_STR_ptr; inout *IO_ptr, *tmp_IO_ptr, *out_IO_ptr; carrier_info *tmp_CI_ptr; int i, j, width; // First decide on the cl_type if (cl_type == UNDEFINED) cl_type=VARIABLE; // create a symbol table entry for each name in the id_list for(id_rec_ptr=name_list;id_rec_ptr != 0; id_rec_ptr=id_rec_ptr->next_id_ptr){ STR_ptr=(symbol_table_rec *) new symbol_table_rec; STR_ptr->symbol_id=this->rename("s",STR_cnt++); STR_ptr->parent_id=(char*) new char[strlen(curr_MR_ptr->str_ptr->symbol_id)+1]; strcpy(STR_ptr->parent_id,curr_MR_ptr->str_ptr->symbol_id); STR_ptr->name=(char *) new char[strlen(id_rec_ptr->id)+1]; strcpy(STR_ptr->name,id_rec_ptr->id); STR_ptr->flags.is_formal=1; if (cl_type==VARIABLE) STR_ptr->flags.is_variable=1; else STR_ptr->flags.is_signal=1; STR_ptr->mode=mode; // now for the type information if (type_mark_ptr->type == ARRAY){ STR_ptr->flags.is_array = 1; STR_ptr->word_struct.from=type_mark_ptr->arr_from; STR_ptr->word_struct.to=type_mark_ptr->arr_to; } STR_ptr->flags.is_bit_vector = 1; STR_ptr->bit_struct.from=type_mark_ptr->bit_from; STR_ptr->bit_struct.to=type_mark_ptr->bit_to; // It may have a resolution fn if (type_mark_ptr->res_fn_name){ res_fn_STR_ptr=this->get_STR_ptr(type_mark_ptr->res_fn_name); STR_ptr->resn_fn_id=(char *) new char[strlen(res_fn_STR_ptr->symbol_id)+1]; strcpy(STR_ptr->resn_fn_id,res_fn_STR_ptr->symbol_id); } // Type dependent processing // Update module rec input/output list switch (mode){ case IN : // Create inout record only for the module input inout *IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("f",MO_inp_cnt++); IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->symbol_id); width=((i=(STR_ptr->bit_struct.from - STR_ptr->bit_struct.to)) > 0 ? i+1 : 1-i); IO_ptr->width=width; IO_ptr->name=(char*) new char[strlen(id_rec_ptr->id)+1]; strcpy(IO_ptr->name,id_rec_ptr->id); // Insert it in the module's input list if(tmp_IO_ptr=curr_MR_ptr->input_list){ for(;tmp_IO_ptr->next_io_ptr != 0; tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=IO_ptr; } else curr_MR_ptr->input_list=IO_ptr; // Update the carrier_info of the module_rec tmp_CI_ptr=(carrier_info*) new carrier_info; tmp_CI_ptr->str_ptr=STR_ptr; tmp_CI_ptr->op_inp_id=(char*) new char[strlen(STR_ptr->parent_id)+strlen(IO_ptr->inout_id)+2]; // Create the op_inp_id i=j=0; while((tmp_CI_ptr->op_inp_id[i++] = STR_ptr->parent_id[j++]) != '\0'); j=0;--i; tmp_CI_ptr->op_inp_id[i++]='.'; while((tmp_CI_ptr->op_inp_id[i++] = IO_ptr->inout_id[j++]) != '\0'); tmp_CI_ptr->next_ci_ptr=CI_ptr; CI_ptr=tmp_CI_ptr; break; case INOUT : // Create inout record for both module input and output IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("f",MO_inp_cnt++); IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->symbol_id); width=((i=(STR_ptr->bit_struct.from - STR_ptr->bit_struct.to)) > 0 ? i+1 : 1-i); IO_ptr->width=width; IO_ptr->name=(char*) new char[strlen(id_rec_ptr->id)+1]; strcpy(IO_ptr->name,id_rec_ptr->id); // Insert it in the module's input list if(tmp_IO_ptr=curr_MR_ptr->input_list){ for(;tmp_IO_ptr->next_io_ptr != 0; tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=IO_ptr; } else curr_MR_ptr->input_list=IO_ptr; // Update the carrier_info of the module_rec tmp_CI_ptr=(carrier_info*) new carrier_info; tmp_CI_ptr->str_ptr=STR_ptr; tmp_CI_ptr->op_inp_id=(char*) new char[strlen(STR_ptr->parent_id)+strlen(IO_ptr->inout_id)+2]; // Create the op_inp_id i=j=0; while((tmp_CI_ptr->op_inp_id[i++] = STR_ptr->parent_id[j++]) != '\0'); j=0;--i; tmp_CI_ptr->op_inp_id[i++]='.'; while((tmp_CI_ptr->op_inp_id[i++] = IO_ptr->inout_id[j++]) != '\0'); tmp_CI_ptr->next_ci_ptr=CI_ptr; CI_ptr=tmp_CI_ptr; // Now for the module's output list out_IO_ptr=(inout*) new inout; out_IO_ptr->inout_id=rename("p",MO_out_cnt++); out_IO_ptr->destn_id=(char*) new char[strlen(IO_ptr->destn_id)+1]; strcpy(out_IO_ptr->destn_id,IO_ptr->destn_id); out_IO_ptr->name=(char*) new char[strlen(IO_ptr->name)+1]; strcpy(out_IO_ptr->name,IO_ptr->name); out_IO_ptr->width=width; // Insert it in the module's output list if(tmp_IO_ptr=curr_MR_ptr->output_list){ for(;tmp_IO_ptr->next_io_ptr != NULL; tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=out_IO_ptr; } else curr_MR_ptr->output_list=out_IO_ptr; break; case OUT : // Just the module's output list out_IO_ptr=(inout*) new inout; out_IO_ptr->inout_id=rename("p",MO_out_cnt++); out_IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(out_IO_ptr->destn_id,STR_ptr->symbol_id); out_IO_ptr->name=(char*) new char[strlen(STR_ptr->name)+1]; strcpy(out_IO_ptr->name,STR_ptr->name); width=((i=(STR_ptr->bit_struct.from - STR_ptr->bit_struct.to)) > 0 ? i+1 : 1-i); out_IO_ptr->width=width; // Insert it in the module's output list if(tmp_IO_ptr=curr_MR_ptr->output_list){ for(;tmp_IO_ptr->next_io_ptr != NULL; tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=out_IO_ptr; } else curr_MR_ptr->output_list=out_IO_ptr; } // end case // now enter the record in the symbol table symbol_table_rec *tmp_STR_ptr=curr_MR_ptr->STR_list; if (tmp_STR_ptr){ for(;tmp_STR_ptr->next_str_ptr != NULL; tmp_STR_ptr=tmp_STR_ptr->next_str_ptr); tmp_STR_ptr->next_str_ptr=STR_ptr; } else curr_MR_ptr->STR_list=STR_ptr; } // end for // Free some space this->free_id(name_list); #ifdef DEBUG cout << "Leaving : mk_formal_param()\n"; #endif VOID_RETURN; } int CLASS_NAME :: log2(int val) /* return ceiling of log2 of value */ { int ret_val; if (val == 1) {INT_RETURN(1);} else{ val=val-1; for(ret_val=1;val != 1;ret_val++) val = val / 2; INT_RETURN(ret_val); } } void CLASS_NAME :: yyerror(char *junk){} int CLASS_NAME :: bin_to_int(int bin_num) { /* This routine translates a binary number into integer equivalent eg. if bin_num is 101 it returns 5 etc. */ int ret_value=0; int base_value=1; int digit; while(bin_num){ digit = bin_num % 10; ret_value += base_value * digit; bin_num /= 10; base_value *= 2; } INT_RETURN(ret_value); } int CLASS_NAME :: two_to_pow(int x) { int i,ret_value=1; for(i=0;i < x;i++){ ret_value *= 2; } INT_RETURN(ret_value); } int CLASS_NAME :: ten_to_pow(int x) { int i,ret_value=1; for(i=0;i < x;i++){ ret_value *= 10; } INT_RETURN(ret_value); } int CLASS_NAME :: log10(int x) { int ret_value=0; for (;x > 10;ret_value++,x /= 10); INT_RETURN(++ret_value); } void CLASS_NAME :: mk_type_decl(char *name, type_mark *type_mark_ptr) { // This routine creates a type_decl record and puts this record at the // begining of the list pointed to by "global_type_decl_ptr" #ifdef DEBUG cout << "Entered : mk_type_decl()\n"; #endif // create the record type_decl *TD_ptr=(type_decl *) new type_decl; TD_ptr->name=(char *) new char[strlen(name)+1]; strcpy(TD_ptr->name,name); TD_ptr->type_mark_ptr=type_mark_ptr; TD_ptr->next_td_ptr=0; /* now put it at the begining of the list */ TD_ptr->next_td_ptr=global_TD_ptr; global_TD_ptr=TD_ptr; // Free some space delete name; #ifdef DEBUG cout << "Leaving : mk_type_decl()\n"; #endif VOID_RETURN; } type_mark* CLASS_NAME :: get_type_mark(char *name) { /* This routine goes thru the list pointed to by "global_type_decl_ptr" and returns the record whose name matches with the name stored in the record */ #ifdef DEBUG cout << "Entered : get_type_mark()\n"; #endif type_decl *type_decl_ptr=global_TD_ptr; for(;type_decl_ptr != 0;type_decl_ptr=type_decl_ptr->next_td_ptr) if(strcmp(type_decl_ptr->name,name)==0){ // Free some space delete name; #ifdef DEBUG cout << "Leaving : get_type_mark()\n"; #endif PTR_RETURN(type_decl_ptr->type_mark_ptr); } /* still here ?? -- bug in vantage/mcc analyzer */ cout << "haha PAKRHA\n"; exit(1); } type_mark* CLASS_NAME :: resolved_type(char *res_fn_name,type_mark *type_mark_ptr) { // install resulution function name in type_mark_ptr and return it type_mark_ptr->res_fn_name = (char *) new char[strlen(res_fn_name)+1]; strcpy(type_mark_ptr->res_fn_name,res_fn_name); // Free space delete res_fn_name; PTR_RETURN(type_mark_ptr); } int CLASS_NAME :: check_for_function_name(char *name) { /* checks if the name is any of the function names needed by the stupid simulator. The names are stored in stupid_simulator */ char *fn_name; int i; for(i=0;i "ba" */ int c, i, j; for(i=0,j=strlen(string)-1; i < j; i++, j--) { c = *(string+i); *(string + i) = *(string + j); *(string + j) = c ; } STRING_RETURN(string); } char* CLASS_NAME :: mk_ext(int value,int ext) { /* convert integer to string and append it with "_" if ext = 1 */ char *ret_ptr=0; int i, sign, length=1; /* one for "\0" */ if(ext == 1) length++; /* for "_" */ if ((sign = value) < 0){ /* note that num was negetive */ value = -value; /* negate value */ length++; } i=value; for (;i>9;length++,i /= 10); length++; // For values between 0 and 9 ret_ptr = (char *) new char[length]; /* assign return pointer */ i = 0; do { /* generate digits in reverse order */ *(ret_ptr + i++) = value % 10 + '0'; /* get next digit */ } while ((value /= 10) > 0); /* delete it */ if (sign < 0) /* take care of sign */ *(ret_ptr + i++) = '-'; if (ext == 1) *(ret_ptr + i++) = '_'; /* put the underscore */ *(ret_ptr + i++) = '\0';/* take care of end_of_string */ ret_ptr = this->reverse(ret_ptr); /* now reverse the string */ STRING_RETURN(ret_ptr); } char* CLASS_NAME :: rename(char *base_name,int extension) { /* this routine takes a base_name and an extension, and produces */ /* an extended name - eg. this->rename("junk",1) => junk_1 */ int i=0,j=0; char *char_rep_of_int=this->mk_ext(extension,0); char *ret_ptr=(char *) new char[(i=strlen(base_name))+strlen(char_rep_of_int)+1]; strcpy(ret_ptr,base_name); while((ret_ptr[i++]=char_rep_of_int[j++]) != '\0'); delete char_rep_of_int; STRING_RETURN(ret_ptr); } /************** V2IF routines added ****************************************/ input* CLASS_NAME :: source_id(char *name) { // This routine takes the name of a storage and returns a "input" record. // It performs the above as follows // - Checks if the storage refers to an alias. If so, call yourself // with the name of the parent. Then create a RD operator to indicate // that an alias is being read. // - Checks to see if the storage is already in the carrier_list. If // not, it appends the storage in the carrier_list with a proper // identifier and updates the inputs of the module. If it already // exists, then it simply returns an input record reflecting the input_id. // Assume that variables, formal parameters etc. already defined in // the "carrier information" list. // - For first time encountered storage, it also checks for any parent // SELECT operator and if so, it updates the parent carrier info also. // // - Global pointers used : // (1) CI_ptr; // (2) curr_MR_ptr; #ifdef DEBUG cout << "Entered : source_id()\n"; #endif input *ret_ptr=(input *) new input; carrier_info *loop_ptr=CI_ptr; carrier_info *tmp_CI_ptr; symbol_table_rec *STR_ptr; inout *temp_ptr; char *module_id, *inp_id; select_stack_rec* stack_ptr; int i, j; STR_ptr=this->get_STR_ptr(name); // get the symbol_table info of the storage // Check if I'm an alias if (STR_ptr->flags.is_alias == 1) { symbol_table_rec *parent_STR_ptr=STR_ptr->alias_info.alias_of; // First the RD inputs input *inp1=this->source_id(parent_STR_ptr->name); input *inp2=(input*) new input; inp2->inp_id=(char*) new char[strlen(STR_ptr->alias_info.cr_ptr->constant_id)+3]; i=j=0; inp2->inp_id[i++]='#'; inp2->inp_id[i++]='.'; while((inp2->inp_id[i++]=STR_ptr->alias_info.cr_ptr->constant_id[j++]) != '\0'); inp1->next_in_ptr=inp2; // Now the RD output inout *IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",1); IO_ptr->width=((i=(STR_ptr->bit_struct.from - STR_ptr->bit_struct.to)) > 0 ? i+1 : 1-i); // Now create the RD operator curr_OP_ptr->op_code=RD; curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->input_list=inp1; curr_OP_ptr->output_list=IO_ptr; // Now for the return pointer ret_ptr->inp_id=(char*) new char[strlen(curr_OP_ptr->op_id)+4]; i=j=0; while((ret_ptr->inp_id[i++]=curr_OP_ptr->op_id[j++]) != '\0'); ret_ptr->inp_id[i-1]='.'; ret_ptr->inp_id[i++]='p'; ret_ptr->inp_id[i++]='1'; ret_ptr->inp_id[i++]='\0'; // Create the carrier information for this ret_ptr - add it at end of list // Not needed : Note that source_id() is used to refer to some storage // or its alias. It is not modifying the storage, and hence the // corresponding carrier info should not be altered. /************************************************************************* carrier_info *tmp_CI_ptr=CI_ptr; if (tmp_CI_ptr){ for(;tmp_CI_ptr->next_ci_ptr != NULL;tmp_CI_ptr=tmp_CI_ptr->next_ci_ptr); tmp_CI_ptr=tmp_CI_ptr->next_ci_ptr=(carrier_info*) new carrier_info; } else tmp_CI_ptr=CI_ptr=(carrier_info*) new carrier_info; tmp_CI_ptr->op_inp_id=(char*) new char[strlen(ret_ptr->inp_id)+1]; strcpy(tmp_CI_ptr->op_inp_id,ret_ptr->inp_id); tmp_CI_ptr->str_ptr=parent_STR_ptr; *************************************************************************/ // Create another operator curr_OP_ptr->next_op_ptr=(op_erator*) new op_erator; curr_OP_ptr=curr_OP_ptr->next_op_ptr; // Now return #ifdef DEBUG cout << "Leaving : source_id()\n"; #endif PTR_RETURN(ret_ptr); } // Check if the storage is in the input list of the current module. If not, // add it. (Note - It is possible that the storage is in the carrier list // but not in the module's input list. This can happen when the storage is // written into first. inout *IO_ptr=curr_MR_ptr->input_list; for (;IO_ptr != NULL; IO_ptr=IO_ptr->next_io_ptr) if (strcmp(IO_ptr->destn_id,STR_ptr->symbol_id) == 0) break; if (IO_ptr == NULL){ if (IO_ptr=curr_MR_ptr->input_list){ for(;IO_ptr->next_io_ptr != NULL;IO_ptr=IO_ptr->next_io_ptr); IO_ptr=IO_ptr->next_io_ptr=(inout*) new inout; } else IO_ptr=curr_MR_ptr->input_list=(inout*) new inout; IO_ptr->inout_id=this->rename("i",MO_inp_cnt++); IO_ptr->destn_id=(char *) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->symbol_id); IO_ptr->width=((i=(STR_ptr->bit_struct.from - STR_ptr->bit_struct.to)) > 0 ? i+1 : 1-i); IO_ptr->name=(char *) new char[strlen(STR_ptr->name)+1]; strcpy(IO_ptr->name,STR_ptr->name); } // Now loop thru the carrier_list for (;loop_ptr != 0;loop_ptr=loop_ptr->next_ci_ptr){ if (loop_ptr->str_ptr == STR_ptr){ // Is in the list ret_ptr->inp_id=(char*) new char[strlen(loop_ptr->op_inp_id)+1]; strcpy(ret_ptr->inp_id,loop_ptr->op_inp_id); #ifdef DEBUG cout << "Leaving : source_id()\n"; #endif PTR_RETURN(ret_ptr); } } // If you are here, update the carrier_list loop_ptr=(carrier_info*) new carrier_info; loop_ptr->op_inp_id=(char *) new char[strlen(curr_MR_ptr->str_ptr->symbol_id) + strlen(IO_ptr->inout_id) + 2]; i=j=0; while((loop_ptr->op_inp_id[i++]=curr_MR_ptr->str_ptr->symbol_id[j++])!='\0'); j=0;--i; loop_ptr->op_inp_id[i++]='.'; while((loop_ptr->op_inp_id[i++] = IO_ptr->inout_id[j++]) != '\0'); loop_ptr->str_ptr=STR_ptr; // now insert it in the list loop_ptr->next_ci_ptr=CI_ptr; CI_ptr=loop_ptr; // Check if it is in the scope of the SELECT operation. If so, update all // the carrier_lists in the stack. Note we are updating all the carriers // in the carrier list only for READS // REMEMBER top_SSR_ptr ?? if (stack_ptr=top_SSR_ptr){ // It is inside a SELECT operator for(;stack_ptr != 0;stack_ptr=stack_ptr->parent_ssr_ptr){ // make a copy of the carrier info tmp_CI_ptr=(carrier_info*) new carrier_info; tmp_CI_ptr->str_ptr=STR_ptr; tmp_CI_ptr->op_inp_id=(char*) new char[strlen(loop_ptr->op_inp_id)+1]; strcpy(tmp_CI_ptr->op_inp_id,loop_ptr->op_inp_id); tmp_CI_ptr->next_ci_ptr=stack_ptr->parent_ci_ptr; stack_ptr->parent_ci_ptr=tmp_CI_ptr; } } // now for the return_ptr ret_ptr->inp_id=(char *) new char[strlen(loop_ptr->op_inp_id)+1]; strcpy(ret_ptr->inp_id,loop_ptr->op_inp_id); #ifdef DEBUG cout << "Leaving : source_id()\n"; #endif PTR_RETURN(ret_ptr); } input* CLASS_NAME :: source_bit(int width, int val) { // It takes as input a constant bit_vector information. It creates a // constant record with this information and returns a record in the // input format #ifdef DEBUG cout << "Entered : source_bit()\n"; #endif constant_rec *CR_temp; input *ret_ptr=(input *) new input; int i,j; // Create the constant record constant_rec *CR_ptr=this->add_constant(width,val); // now update the return pointer ret_ptr->inp_id=(char *) new char[strlen(CR_ptr->constant_id)+3]; ret_ptr->inp_id[0]='#'; ret_ptr->inp_id[1]='.'; i=2;j=0; while((ret_ptr->inp_id[i++]=CR_ptr->constant_id[j++]) != '\0'); #ifdef DEBUG cout << "Leaving : source_bit()\n"; #endif PTR_RETURN(ret_ptr); } constant_rec* CLASS_NAME :: str2num(int base,char *val_string) { // Converts a character string into it's equivalent value depending on the // base (can be DEC, BIN, OCT or HEX). int i,j,value,width,mult_by,width_map; int int_eq; constant_rec *ret_ptr=(constant_rec*) new constant_rec; // First find the base switch (base) { case DEC : mult_by=10;width_map=0; break; case BIN : mult_by=2; width_map=1; break; case OCT : mult_by=8; width_map=3; break; case HEX : mult_by=16; width_map=4; break; } // First convert the string into it's value i=strlen(val_string); j=1;value=0;width=0; for(i=i-1 ;i >= 0; i--){ if (val_string[i] == '_') continue; // neglect this one switch (val_string[i]){ case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : int_eq = val_string[i] - '0'; break; case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' : int_eq = val_string[i] - 87; // 97 is equivalent of 'a' break; case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' : int_eq = val_string[i] - 55; // 65 is equivalent of 'A' break; default : int_eq = 0; } value = value + j * int_eq; j *= mult_by; width += width_map; } ret_ptr->value=value; if (width==0) ret_ptr->width=UNKNOWN; else ret_ptr->width=width; PTR_RETURN(ret_ptr); } input* CLASS_NAME :: source_int(int val) { // It creates a constant record for an INTEGER constant. The record is // created and appended to the constant table - but the width field is // left to be UNKNOWN. The width of the constant is determined when // information about the other operand is available. It is done in the // "mk_operator" routine. #ifdef DEBUG cout << "Entered : source_int()\n"; #endif constant_rec *CR_temp; constant_rec *CR_ptr=(constant_rec *) new constant_rec; input *ret_ptr=(input *) new input; int i, j; // create the constant record CR_ptr->value=val; CR_ptr->width=UNKNOWN; CR_ptr->constant_id=this->rename("c",CR_cnt++); // insert it in the constant table at the end if (CR_temp=global_CR_ptr){ for (;CR_temp->next_cr_ptr != 0;CR_temp=CR_temp->next_cr_ptr); CR_temp->next_cr_ptr=CR_ptr; } else global_CR_ptr=CR_ptr; // now update the return pointer and return it ret_ptr->inp_id=(char *) new char[strlen(CR_ptr->constant_id)+3]; ret_ptr->inp_id[0]='#'; ret_ptr->inp_id[1]='.'; i=2;j=0; while((ret_ptr->inp_id[i++]=CR_ptr->constant_id[j++]) != '\0'); #ifdef DEBUG cout << "Leaving : source_int()\n"; #endif PTR_RETURN(ret_ptr); } input* CLASS_NAME :: source_arr(char *arr_name, input *index_ptr) { // The source is an array reference. So, we create an array read // operator (ARR_RD) with the information about the array name // and the index_ptr. // Note : If the index is a constant, index_ptr is of form "#.c", // then we need to find the no of bits needed to address the // array and update the constant table with this width. // Algo :- // (1) use this->source_id() rtn to get the input format to be used // by the ARR_RD operator. // (2) Update constant table. // (3) Create the ARR_RD opertor. // (4) Create a carrier_info record for the ret_ptr // The third input ie. the start bit information is not incorporated yet. #ifdef DEBUG cout << "Entered : source_arr()\n"; #endif int i=0,j=2,bit_width,arr_width; char *const_id; constant_rec *CR_ptr=global_CR_ptr,*temp_CR_ptr=global_CR_ptr; input *inp_1=this->source_id(arr_name); // first input of ARR_RD input *inp_2=index_ptr; // by default input *ret_ptr=(input *) new input; // Get the STR_ptr symbol_table_rec *arr_STR_ptr=this->get_STR_ptr(arr_name); delete arr_name; // find the bit_width and arr_width of the array if((bit_width=arr_STR_ptr->bit_struct.to-arr_STR_ptr->bit_struct.from) < 0 ) bit_width = (1 - bit_width); else bit_width++; if((arr_width=arr_STR_ptr->bit_struct.to-arr_STR_ptr->bit_struct.from) < 0 ) arr_width = (1 - arr_width); else arr_width++; // now for the index if (index_ptr->inp_id[0]=='#'){ // is a constant and must be an INTEGER const_id=(char *) new char[strlen(index_ptr->inp_id)-1]; //for(;index_ptr->inp_id[j] != '\0';const_id[i++]=index_ptr->inp_id[j++]); i=0; j=2; while((const_id[i++]=index_ptr->inp_id[j++]) != '\0'); for(;strcmp(CR_ptr->constant_id,const_id)!=0;CR_ptr=CR_ptr->next_cr_ptr); temp_CR_ptr=this->update_const_width(this->log2(arr_width),CR_ptr); if (CR_ptr != temp_CR_ptr){ // modify inp_2 for ARR_RD operator inp_2=(input *) new input; inp_2->inp_id=(char *) new char[strlen(temp_CR_ptr->constant_id)+3]; inp_2->inp_id[0]='#'; inp_2->inp_id[1]='.'; i=2;j=0; while((inp_2->inp_id[i++]=temp_CR_ptr->constant_id[j++]) != '\0'); } } // now we are all set to create the ARR_RD operator curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=ARRRD; inp_1->next_in_ptr=inp_2; curr_OP_ptr->input_list=inp_1; inout *IO_ptr=(inout *) new inout; IO_ptr->inout_id=this->rename("p",1); IO_ptr->width=bit_width; //IO_ptr->destn_id=(char *) new char[strlen(arr_STR_ptr->symbol_id)+1]; //strcpy(IO_ptr->destn_id,arr_STR_ptr->symbol_id); //IO_ptr->name=(char *) new char[strlen(arr_STR_ptr->name)+1]; //strcpy(IO_ptr->name,arr_STR_ptr->name); curr_OP_ptr->output_list=IO_ptr; // now for the return pointer i=strlen(curr_OP_ptr->op_id)+strlen(IO_ptr->inout_id)+2; ret_ptr->inp_id=(char *) new char[i]; i=j=0; while((ret_ptr->inp_id[i++] = curr_OP_ptr->op_id[j++]) != '\0'); j=0;--i; ret_ptr->inp_id[i++]='.'; while((ret_ptr->inp_id[i++] = IO_ptr->inout_id[j++]) != '\0'); // Create the carrier information for this ret_ptr - add it at end of list carrier_info *tmp_CI_ptr=CI_ptr; if (tmp_CI_ptr){ for(;tmp_CI_ptr->next_ci_ptr != NULL;tmp_CI_ptr=tmp_CI_ptr->next_ci_ptr); tmp_CI_ptr=tmp_CI_ptr->next_ci_ptr=(carrier_info*) new carrier_info; } else tmp_CI_ptr=CI_ptr=(carrier_info*) new carrier_info; tmp_CI_ptr->op_inp_id=(char*) new char[strlen(ret_ptr->inp_id)+1]; strcpy(tmp_CI_ptr->op_inp_id,ret_ptr->inp_id); tmp_CI_ptr->str_ptr=arr_STR_ptr; // Create the next operator record and set the "curr_OP_ptr" to it op_erator *OP_ptr=(op_erator *) new op_erator; curr_OP_ptr->next_op_ptr=OP_ptr; curr_OP_ptr=OP_ptr; #ifdef DEBUG cout << "Leaving : source_arr()\n"; #endif PTR_RETURN(ret_ptr); } constant_rec* CLASS_NAME :: add_constant(int width, int value) { // check if the constant with the specification as that of the input // record exists in the constant table. If so, return the ptr. constant_rec *ret_ptr=global_CR_ptr; for(;ret_ptr != NULL;ret_ptr=ret_ptr->next_cr_ptr) if (ret_ptr->value==value && ret_ptr->width==width){ PTR_RETURN(ret_ptr); } // Else create and append a constant constant_rec *CR_ptr=(constant_rec*) new constant_rec; CR_ptr->constant_id=this->rename("c",CR_cnt++); CR_ptr->value=value; CR_ptr->width=width; if (ret_ptr=global_CR_ptr){ for(;ret_ptr->next_cr_ptr != NULL;ret_ptr=ret_ptr->next_cr_ptr); ret_ptr->next_cr_ptr=CR_ptr; ret_ptr=CR_ptr; } else ret_ptr=global_CR_ptr=CR_ptr; PTR_RETURN(ret_ptr); } constant_rec* CLASS_NAME :: update_const_width(int width,constant_rec *inp_CR_ptr) { // It takes as input a constant_rec_ptr and width and updates the constant // table. Algorithm followed :- // (1) update the particular record. // (2) Check to see if a similar record exists // (3) If so, delete the current record from the table and return the // pointer for the existing record. // (4) Else, return the same pointer. #ifdef DEBUG cout << "Entered : update_const_width()\n"; #endif constant_rec *ret_ptr=inp_CR_ptr; constant_rec *temp_CR_ptr=global_CR_ptr; inp_CR_ptr->width=width; // now check if a similar constant exists for(;temp_CR_ptr != NULL;temp_CR_ptr=temp_CR_ptr->next_cr_ptr) if (temp_CR_ptr != inp_CR_ptr && temp_CR_ptr->width==inp_CR_ptr->width && temp_CR_ptr->value==inp_CR_ptr->value) break; if (temp_CR_ptr && temp_CR_ptr != inp_CR_ptr){ ret_ptr=temp_CR_ptr; this->delete_const_rec(inp_CR_ptr); } #ifdef DEBUG cout << "Leaving : update_const_width()\n"; #endif PTR_RETURN(ret_ptr); } void CLASS_NAME :: delete_const_rec(constant_rec *inp_CR_ptr) { /********************************************************************** Deletes the constant record pointed to by the inp_CR_ptr from the Constant Table. ***********************************************************************/ #ifdef DEBUG cout << "Entered : delete_const_rec()\n"; #endif constant_rec *tmp_CR_ptr=global_CR_ptr,*prev_CR_ptr=NULL; for(;tmp_CR_ptr != NULL;tmp_CR_ptr=tmp_CR_ptr->next_cr_ptr){ if (tmp_CR_ptr==inp_CR_ptr && prev_CR_ptr) prev_CR_ptr->next_cr_ptr=tmp_CR_ptr->next_cr_ptr; else if (tmp_CR_ptr==inp_CR_ptr && prev_CR_ptr==NULL) global_CR_ptr=tmp_CR_ptr->next_cr_ptr; else prev_CR_ptr=tmp_CR_ptr; } delete inp_CR_ptr; #ifdef DEBUG cout << "Leaving : delete_const_rec()\n"; #endif VOID_RETURN; } input* CLASS_NAME :: mk_operator(int op_type,input *inp_1, input* inp_2) { /************************************************************************ This routine creates an operator and inserts it in the operator list of the current module. Operators are grouped into 4 major categories (1) Arithmatic : PLUS, MINUS, MULT, DIV These operators take inputs of the same size and produce output of size that is greater than the input sizes. The PLUS and MINUS operators increment the size of the output by '1' to account for the sign/overflow bit. The MULT operator produces an output that is double the size of the inputs. The DIV operator produces an output of size same as that of the inputs. (2) Relational : GT , LT , EQ Produces a single bit output. (3) Logical : AND , OR , NOT, XOR, NAND, NOR, XNOR Produces output of the same size as the inputs. (4) VHDL specific : STABLE, QUIET, CONCAT Produces a single bit output. Common operations performed are : these are performed first. (1) the NOT, STABLE, QUIET, RSHIFT and LSHIFT operators have 1 operand. So, take care of these first. Note that the shift operators will modify the storage. (2) Take care of the CONCAT operation. This operator does not care about matching the two input operands. It just concatenates them. (3) Check to see if any of the inputs is a constant whose width is UNKNOWN (must be an INTEGER constant). If so, then get the width of the other source and update the constant table. (4) If the sources width differ, then pad the source of smaller width with '0's to make their sizes equal. !! Think more. ************************************************************************/ #ifdef DEBUG cout << "Entered : mk_operator()\n"; #endif char *const_id; int i=0,j=2; int inp1_width, inp2_width; constant_rec *CR_ptr1=global_CR_ptr; constant_rec *CR_ptr2=global_CR_ptr; constant_rec *temp_CR_ptr; inout *IO_ptr; op_erator *OP_ptr, *temp_OP_ptr; input *ret_ptr; // NOT | STABLE | QUIET | RSHIFT | LSHIFT operator if (op_type==NOT || op_type==STABLE || op_type==QUIET || op_type==RSHIFT || op_type==LSHIFT){ curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=op_type; curr_OP_ptr->input_list=inp_1; IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",1); // find width of the operand if (inp_1->inp_id[0]=='#'){ // Constant operand const_id=(char*) new char[strlen(inp_1->inp_id)-1]; i=0;j=2; while((const_id[i++]=inp_1->inp_id[j++]) != '\0'); for(;strcmp(const_id,CR_ptr1->constant_id) != 0; CR_ptr1=CR_ptr1->next_cr_ptr); if ((inp1_width=CR_ptr1->width) == UNKNOWN) // INTEGER Constant {inp1_width=CR_ptr1->width=this->log2(CR_ptr1->value);} } else inp1_width=this->get_width(inp_1); // If the operator is STABLE | QUIET then the output of the operator // is just 1 if (op_type==STABLE || op_type==QUIET) IO_ptr->width=1; else // Bit-wise NOT or SHIFT operation IO_ptr->width=inp1_width; curr_OP_ptr->output_list=IO_ptr; // now for the return record ret_ptr=(input*) new input; ret_ptr->inp_id=(char*) new char[(i=strlen(curr_OP_ptr->op_id))+4]; strcpy(ret_ptr->inp_id,curr_OP_ptr->op_id); ret_ptr->inp_id[i++]='.'; ret_ptr->inp_id[i++]='p'; ret_ptr->inp_id[i++]='1'; ret_ptr->inp_id[i++]='\0'; // If a Shift operation, the storage will be modified -- identify it // in the output of the operator and also update the carrier list if (op_type==RSHIFT || op_type==LSHIFT){ symbol_table_rec *STR_ptr=this->get_op_inp_STR_ptr(inp_1->inp_id); IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->symbol_id); IO_ptr->name=(char*) new char[strlen(STR_ptr->name)+1]; strcpy(IO_ptr->name,STR_ptr->name); this->update_carrier_info(STR_ptr,ret_ptr->inp_id); } // Create the next operator record and set the "curr_OP_ptr" to it OP_ptr=(op_erator *) new op_erator; curr_OP_ptr->next_op_ptr=OP_ptr; curr_OP_ptr=OP_ptr; #ifdef DEBUG cout << "Leaving : mk_operator()\n"; #endif PTR_RETURN(ret_ptr); } // CONCAT operator if (op_type==CONCAT){ curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=op_type; curr_OP_ptr->input_list=inp_1; IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",1); // find width of the operands if (inp_1->inp_id[0]=='#'){ // Constant operand i=0;j=2; const_id=(char*) new char[strlen(inp_1->inp_id)-1]; while((const_id[i++]=inp_1->inp_id[j++]) != '\0'); for(;strcmp(const_id,CR_ptr1->constant_id) != 0; CR_ptr1=CR_ptr1->next_cr_ptr); if ((inp1_width=CR_ptr1->width) == UNKNOWN) // INTEGER Constant inp1_width=CR_ptr1->width=this->log2(CR_ptr1->value); } else inp1_width=this->get_width(inp_1); if (inp_2->inp_id[0]=='#'){ // Constant operand const_id=(char*) new char[strlen(inp_1->inp_id)-1]; i=0;j=2; while((const_id[i++]=inp_2->inp_id[j++]) != '\0'); for(;strcmp(const_id,CR_ptr2->constant_id) != 0; CR_ptr2=CR_ptr2->next_cr_ptr); if ((inp2_width=CR_ptr2->width) == UNKNOWN) // INTEGER Constant inp2_width=CR_ptr2->width=this->log2(CR_ptr2->value); } else inp2_width=this->get_width(inp_2); inp_1->next_in_ptr=inp_2; IO_ptr->width=inp1_width + inp2_width; curr_OP_ptr->output_list=IO_ptr; // now for the return record ret_ptr=(input*) new input; ret_ptr->inp_id=(char*) new char[(i=strlen(curr_OP_ptr->op_id))+4]; strcpy(ret_ptr->inp_id,curr_OP_ptr->op_id); ret_ptr->inp_id[i++]='.'; ret_ptr->inp_id[i++]='p'; ret_ptr->inp_id[i++]='1'; ret_ptr->inp_id[i++]='\0'; // Create the next operator record and set the "curr_OP_ptr" to it OP_ptr=(op_erator *) new op_erator; curr_OP_ptr->next_op_ptr=OP_ptr; curr_OP_ptr=OP_ptr; #ifdef DEBUG cout << "Leaving : mk_operator()\n"; #endif PTR_RETURN(ret_ptr); } // Now the common operations // (1) Constant as input ? if (inp_1->inp_id[0]=='#'){ // inp_1 is Constant const_id=(char *) new char[strlen(inp_1->inp_id)-1]; i=0;j=2; while((const_id[i++]=inp_1->inp_id[j++]) != '\0'); for(;strcmp(CR_ptr1->constant_id,const_id) != 0; CR_ptr1=CR_ptr1->next_cr_ptr); if (CR_ptr1->width==UNKNOWN){ // inp_1 is INTEGER if (inp_2->inp_id[0]=='#'){ // inp_1 is INTEGER inp_2 is Constant const_id=(char *) new char[strlen(inp_2->inp_id)-1]; i=0;j=2; while((const_id[i++]=inp_2->inp_id[j++]) != '\0'); for(;strcmp(CR_ptr2->constant_id,const_id) != 0; CR_ptr2=CR_ptr2->next_cr_ptr); if (CR_ptr2->width==UNKNOWN){ // inp_1 is INTEGER inp_2 is INTEGER switch (op_type){ case PLUS : // add the two values and create a new constant_rec i=CR_ptr1->value+CR_ptr2->value; ret_ptr=this->source_int(i); cout << "Warning : Expression "; cout << CR_ptr1->value << " + " << CR_ptr2->value; cout << " reduced to a new constant\n"; this->delete_const_rec(CR_ptr1); this->delete_const_rec(CR_ptr2); #ifdef DEBUG cout << "Leaving : mk_operator()\n"; #endif PTR_RETURN(ret_ptr); case MINUS : // sub the two values and create a new constant_rec i=CR_ptr1->value-CR_ptr2->value; ret_ptr=this->source_int(i); cout << "Warning : Expression "; cout << CR_ptr1->value << " - " << CR_ptr2->value; cout << " reduced to a new constant\n"; this->delete_const_rec(CR_ptr1); this->delete_const_rec(CR_ptr2); #ifdef DEBUG cout << "Leaving : mk_operator()\n"; #endif PTR_RETURN(ret_ptr); case MULT : // mult the two values and create a new constant_rec i=CR_ptr1->value*CR_ptr2->value; ret_ptr=this->source_int(i); cout << "Warning : Expression "; cout << CR_ptr1->value << " * " << CR_ptr2->value; cout << " reduced to a new constant\n"; this->delete_const_rec(CR_ptr1); this->delete_const_rec(CR_ptr2); #ifdef DEBUG cout << "Leaving : mk_operator()\n"; #endif PTR_RETURN(ret_ptr); case DIV : // divide the two values and create a new constant_rec i=CR_ptr1->value/CR_ptr2->value; ret_ptr=this->source_int(i); cout << "Warning : Expression "; cout << CR_ptr1->value << " / " << CR_ptr2->value; cout << " reduced to a new constant\n"; this->delete_const_rec(CR_ptr1); this->delete_const_rec(CR_ptr2); #ifdef DEBUG cout << "Leaving : mk_operator()\n"; #endif PTR_RETURN(ret_ptr); case GT : case LT : case EQ : // relational operators i=((i=CR_ptr1->value) > (j=CR_ptr2->value) ? i : j); CR_ptr1->value=CR_ptr2->value=this->log2(i); break; default : // not allowed cout << "Error : Expression : "; cout << CR_ptr1->value << " COND_OP " << CR_ptr2->value; cout << " not allowed\n"; exit(1); } //end case } else { // inp_1 is INTEGER inp_2 is BIT_VECTOR inp1_width=inp2_width=CR_ptr2->width; temp_CR_ptr=this->update_const_width(inp1_width,CR_ptr1); if (temp_CR_ptr != CR_ptr1){ delete inp_1->inp_id; CR_ptr1=temp_CR_ptr; inp_1->inp_id=(char*) new char[strlen(CR_ptr1->constant_id)+3]; i=j=0; inp_1->inp_id[i++]='#'; inp_1->inp_id[i++]='.'; while((inp_1->inp_id[i++]=CR_ptr1->constant_id[j++]) != '\0'); } } // end else } // end if inp_2 is Constant else {// inp_1 is INTEGER inp_2 is VARIABLE inp1_width=inp2_width=this->get_width(inp_2); temp_CR_ptr=this->update_const_width(inp1_width,CR_ptr1); if (temp_CR_ptr != CR_ptr1){ delete inp_1->inp_id; CR_ptr1=temp_CR_ptr; inp_1->inp_id=(char*) new char[strlen(CR_ptr1->constant_id)+3]; i=j=0; inp_1->inp_id[i++]='#'; inp_1->inp_id[i++]='.'; while((inp_1->inp_id[i++]=CR_ptr1->constant_id[j++]) != '\0'); } } } // end if inp_1 is INTEGER else { // inp_1 is BIT_VECTOR if (inp_2->inp_id[0]=='#'){ // inp_1 is BIT_VECTOR inp_2 is Constant const_id=(char *) new char[strlen(inp_2->inp_id)-1]; i=0;j=2; while((const_id[i++]=inp_2->inp_id[j++]) != '\0'); for(;strcmp(CR_ptr2->constant_id,const_id) != 0; CR_ptr2=CR_ptr2->next_cr_ptr); if (CR_ptr2->width==UNKNOWN){ // inp_1 is BIT_VECTOR inp_2 is INTEGER inp1_width=inp2_width=CR_ptr1->width; temp_CR_ptr=this->update_const_width(inp2_width,CR_ptr2); if (temp_CR_ptr != CR_ptr2){ delete inp_2->inp_id; CR_ptr2=temp_CR_ptr; inp_2->inp_id=(char*) new char[strlen(CR_ptr2->constant_id)+3]; i=j=0; inp_2->inp_id[i++]='#'; inp_2->inp_id[i++]='.'; while((inp_2->inp_id[i++]=CR_ptr2->constant_id[j++]) != '\0'); } } else { // inp_1 is BIT_VECTOR inp_2 is BIT_VECTOR inp1_width=CR_ptr1->width; inp2_width=CR_ptr2->width; } } else { // inp_1 is BIT_VECOR inp_2 is VARIABLE inp1_width=CR_ptr1->width; inp2_width=this->get_width(inp_2); } } } else { // inp_1 is VARIABLE inp1_width=this->get_width(inp_1); if (inp_2->inp_id[0]=='#'){ // inp_1 is VARIABLE inp_2 is Constant const_id=(char *) new char[strlen(inp_2->inp_id)-1]; i=0;j=2; while((const_id[i++]=inp_2->inp_id[j++]) != '\0'); for(;strcmp(CR_ptr2->constant_id,const_id) != 0; CR_ptr2=CR_ptr2->next_cr_ptr); if (CR_ptr2->width==UNKNOWN){ // inp_1 is VARIABLE inp_2 is INTEGER inp2_width=inp1_width; temp_CR_ptr=this->update_const_width(inp2_width,CR_ptr2); if (temp_CR_ptr != CR_ptr2){ delete inp_2->inp_id; CR_ptr2=temp_CR_ptr; inp_2->inp_id=(char*) new char[strlen(CR_ptr2->constant_id)+3]; i=j=0; inp_2->inp_id[i++]='#'; inp_2->inp_id[i++]='.'; while((inp_2->inp_id[i++]=CR_ptr2->constant_id[j++]) != '\0'); } } else // inp_1 is VARIABLE inp_2 is BIT_VECTOR inp2_width=CR_ptr2->width; } else // inp_1 is VARIABLE inp_2 is VARIABLE inp2_width=this->get_width(inp_2); } // end if : Check for constant inputs done // Now check to see if the inputs are of the same size. If not create a // PAD operator to pad the smaller input with '0's. Note the widths of the // inputs have already been updated in "inp1_width & inp2_width" if(inp1_width != inp2_width){ // Create the operator if (inp1_width < inp2_width){ curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=PAD; // Make a copy of the input input *PAD_inp=(input*) new input; PAD_inp->inp_id=(char*) new char[strlen(inp_1->inp_id)+1]; strcpy(PAD_inp->inp_id,inp_1->inp_id); curr_OP_ptr->input_list=PAD_inp; IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",1); inp1_width=IO_ptr->width=inp2_width; curr_OP_ptr->output_list=IO_ptr; // Modify the inp_1 record for use by the next operator delete inp_1->inp_id; inp_1->inp_id=(char*) new char[(i=strlen(curr_OP_ptr->op_id))+4]; strcpy(inp_1->inp_id,curr_OP_ptr->op_id); inp_1->inp_id[i++]='.'; inp_1->inp_id[i++]='p'; inp_1->inp_id[i++]='1'; inp_1->inp_id[i++]='\0'; } else{ curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=PAD; // Make a copy of the input input *PAD_inp=(input*) new input; PAD_inp->inp_id=(char*) new char[strlen(inp_2->inp_id)+1]; strcpy(PAD_inp->inp_id,inp_2->inp_id); curr_OP_ptr->input_list=PAD_inp; IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",1); IO_ptr->width=inp1_width; curr_OP_ptr->output_list=IO_ptr; // Modify the inp_2 record for use by the next operator delete inp_2->inp_id; inp_2->inp_id=(char*) new char[(i=strlen(curr_OP_ptr->op_id))+4]; strcpy(inp_2->inp_id,curr_OP_ptr->op_id); inp_2->inp_id[i++]='.'; inp_2->inp_id[i++]='p'; inp_2->inp_id[i++]='1'; inp_2->inp_id[i]='\0'; } // Create the next operator record and set the "curr_OP_ptr" to it op_erator *OP_ptr=(op_erator *) new op_erator; curr_OP_ptr->next_op_ptr=OP_ptr; curr_OP_ptr=OP_ptr; } // taken care of input width discrepencies // Now Create the main operator for which you wrote so many lines of code // By now, the inputs of the operator have the same width which is stored // in inp1_width curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=op_type; inp_1->next_in_ptr=inp_2; curr_OP_ptr->input_list=inp_1; IO_ptr=(inout *) new inout; IO_ptr->inout_id=this->rename("p",1); curr_OP_ptr->output_list=IO_ptr; switch(op_type){ case PLUS : case MINUS : IO_ptr->width=inp1_width + 1; break; case MULT : IO_ptr->width=inp1_width * 2; break; case DIV : case AND : case OR : case NAND : case NOR : case XOR : case XNOR : IO_ptr->width=inp1_width; break; case GT : case LT : case EQ : IO_ptr->width=1; break; default : cout << "Something wrong here \n"; exit(1); } // Now for the return pointer ret_ptr=(input*) new input; ret_ptr->inp_id=(char*) new char[(i=strlen(curr_OP_ptr->op_id))+4]; strcpy(ret_ptr->inp_id,curr_OP_ptr->op_id); ret_ptr->inp_id[i++]='.'; ret_ptr->inp_id[i++]='p'; ret_ptr->inp_id[i++]='1'; ret_ptr->inp_id[i++]='\0'; // Create the next operator record and set the "curr_OP_ptr" to it OP_ptr=(op_erator *) new op_erator; curr_OP_ptr->next_op_ptr=OP_ptr; curr_OP_ptr=OP_ptr; #ifdef DEBUG cout << "Leaving : mk_operator()\n"; #endif PTR_RETURN(ret_ptr); } int CLASS_NAME :: get_width(input *inp_ptr) { // Gets an input* which is NOT A CONSTANT and return the bit width // Current module is assumed to decipher information #ifdef DEBUG cout << "Entered : get_width()\n"; #endif int i=0, j=0, ret_val; char *id, *inp_id; inout *IO_ptr; op_erator *OP_ptr; inp_id=inp_ptr->inp_id; id=(char *) new char[strlen(inp_id)+1]; if (inp_id[0]=='m'){ // must be m.i while(inp_id[i++] != '.'); while((id[j++] = inp_id[i++]) != '\0'); // id[j]='\0'; IO_ptr=curr_MR_ptr->input_list; for(;strcmp(IO_ptr->inout_id,id) != 0; IO_ptr=IO_ptr->next_io_ptr); ret_val=IO_ptr->width; } else { // must be x.p i=j=0; while((id[i++]=inp_id[j++]) != '.'); id[--i]='\0'; if (OP_ptr=this->get_op_ptr(id,curr_MR_ptr->operator_list)){ i=0; while((id[i++]=inp_id[j++]) != '\0'); IO_ptr=OP_ptr->output_list; for(;strcmp(IO_ptr->inout_id,id) != 0; IO_ptr=IO_ptr->next_io_ptr); ret_val=IO_ptr->width; } else{ cout << "Something Wrong : Quitting from :: get_width()\n"; exit(1); } } // Free space delete id; #ifdef DEBUG cout << "Leaving : get_width()\n"; #endif INT_RETURN(ret_val); } op_erator* CLASS_NAME :: get_op_ptr(char *op_id,op_erator *OP_list) { /************************************************************************ Takes as input an operator id and a operator start list. Searches recursively thru this operator list to get the op_ptr. The recursion comes from the fact that some operators are compound eg. SELECT or DIVERGE. In such case it calls itself with the new operator list. ************************************************************************/ op_erator *tmp_OP_ptr=OP_list, *ret_ptr; branch_rec *BR_ptr; for(;tmp_OP_ptr != NULL;tmp_OP_ptr=tmp_OP_ptr->next_op_ptr){ if (tmp_OP_ptr->op_id==NULL){ // ERROR detection Cout << "<> Found a BLANK operator in the list headed by : "; Cout << OP_list->op_id << "\n"; break; } if (strcmp(tmp_OP_ptr->op_id,op_id)==0) {PTR_RETURN(tmp_OP_ptr);} else { if (tmp_OP_ptr->op_code == SELECT || tmp_OP_ptr->op_code == DIVERGE){ BR_ptr=tmp_OP_ptr->br_ptr; for(;BR_ptr != 0;BR_ptr=BR_ptr->next_br_ptr){ ret_ptr=this->get_op_ptr(op_id,BR_ptr->op_ptr); if (ret_ptr) PTR_RETURN(ret_ptr); } // end for } // end else if } // end else } // end for // If still here, return NULL PTR_RETURN((void *)0); // PTR_RETURN(0); } void CLASS_NAME :: simple_assignment(int st_type, char *st_name, input *rhs_ptr) { /************************************************************************* Implements the last phase of a simple assignment statement. It's inputs are - (1) storage type (SIGNAL or VARIABLE), (2) l.h.s. storage's name. (3) r.h.s. identification in the "input" format. Algo followed - (1) Find width of l.h.s. (2) Find width of r.h.s. (3) Determine if the l.h.s. is an alias. If it is an alias, we use the operator to implement the assignment. Also, since the aliases refer to their parents, the parent is identified. The 2nd input of the operator identifies the start index of the destination. (4) Here we decide how to implement the simple assignment. (a) If destn. is an alias, we check the lhs and rhs width to see if an additional PAD is needed. Then we create the operator. (b) For normal destinations, we compare the lhs and rhs widths and create a PAD or a operator. Moreover, if the rhs is output of a , then we just modify that operator and do not create any new operator. (5) If the statement is in the scope of a SELECT operator, then the lhs is to become the output of the parent SELECT operator and the parent carrier list has to be modified accordingly. Call the routine update_parent() routine to implement this. (6) Check if the module's output has to be updated. (a) If storage type is a signal, (b) If storage type is formal, (c) If storage type is variable and current module is loop. (7) Update the carrier info for the lhs Global pointers/variables used (1) curr_MR_ptr (2) OP_cnt (3) CI_ptr (4) MO_out_cnt *************************************************************************/ #ifdef DEBUG cout << "Entered : simple_assignment()\n"; #endif int lhs_width, rhs_width; int i,j,use_OP_ptr=0,is_alias=0,rhs_is_op=0; char *id; constant_rec *CR_ptr; op_erator* OP_ptr; inout *tmp_IO_ptr, *IO_ptr; carrier_info *tmp_CI_ptr; symbol_table_rec *STR_ptr; select_stack_rec *SSR_ptr; input *inp2=(input*) new input; // lhs width STR_ptr=this->get_STR_ptr(st_name); delete st_name; lhs_width=((i=(STR_ptr->bit_struct.from-STR_ptr->bit_struct.to))>0 ?i+1:1-i); // Now find the source width switch(rhs_ptr->inp_id[0]){ case '#' : // rhs is a constant i=0;j=2; id=(char*) new char[strlen(rhs_ptr->inp_id)-1]; while((id[i++]=rhs_ptr->inp_id[j++]) != '\0'); CR_ptr=global_CR_ptr; for(;strcmp(CR_ptr->constant_id,id) != 0;CR_ptr=CR_ptr->next_cr_ptr); if (CR_ptr->width==UNKNOWN) // rhs is INTEGER rhs_width=CR_ptr->width=lhs_width; else rhs_width=CR_ptr->width; // Now check if a similar constant already exists in the Constant Table constant_rec *tmp_CR_ptr=this->update_const_width(lhs_width,CR_ptr); if (CR_ptr != tmp_CR_ptr){ delete(rhs_ptr->inp_id); CR_ptr=tmp_CR_ptr; rhs_ptr->inp_id=(char*) new char[strlen(CR_ptr->constant_id)+3]; i=j=0; rhs_ptr->inp_id[i++]='#'; rhs_ptr->inp_id[i++]='.'; while((rhs_ptr->inp_id[i++]=CR_ptr->constant_id[j++]) != '\0'); } break; case 'm' : // rhs is a VARIABLE or SIGNAL rhs_width=this->get_width(rhs_ptr); break; case 'x' : // rhs is an operator output rhs_is_op = 1; rhs_width=this->get_width(rhs_ptr); id=(char*) new char[strlen(rhs_ptr->inp_id)]; i=j=0; while((id[i++]=rhs_ptr->inp_id[j++]) != '.'); id[--i]='\0'; OP_ptr=this->get_op_ptr(id,curr_MR_ptr->operator_list); break; default : // Not possible break; } // end case // Check if lhs is an alias - if so, do the following -- // (1) set a flag to indicate that destn is an alias // (2) set the start_index for the operator // (3) set the STR to that of the parent b'cos aliases refer to the parents if (STR_ptr->flags.is_alias == 1){ is_alias = 1; CR_ptr=STR_ptr->alias_info.cr_ptr; inp2->inp_id=(char*) new char[strlen(CR_ptr->constant_id)+3]; i=j=0; inp2->inp_id[i++]='#'; inp2->inp_id[i++]='.'; while((inp2->inp_id[i++]=CR_ptr->constant_id[j++]) != '\0'); STR_ptr=STR_ptr->alias_info.alias_of; } else { CR_ptr=this->add_constant(this->log2(rhs_width),0); inp2->inp_id=(char*) new char[strlen(CR_ptr->constant_id)+3]; i=j=0; inp2->inp_id[i++]='#'; inp2->inp_id[i++]='.'; while((inp2->inp_id[i++]=CR_ptr->constant_id[j++]) != '\0'); } // Now we have all the ingradients to make proper desicion about how to // implement the assignment operation if (is_alias == 1){ // We have to create a operator for sure if (lhs_width > rhs_width){ // Create an extra PAD operator with floating output curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=PAD; rhs_ptr->next_in_ptr=(input*) new input; CR_ptr=this->add_constant(this->log2(rhs_width),0); rhs_ptr->next_in_ptr->inp_id=(char*) new char[strlen(CR_ptr->constant_id)+3]; i=j=0; rhs_ptr->next_in_ptr->inp_id[i++]='#'; rhs_ptr->next_in_ptr->inp_id[i++]='.'; while((rhs_ptr->next_in_ptr->inp_id[i++]=CR_ptr->constant_id[j++]) != '\0'); curr_OP_ptr->input_list=rhs_ptr; curr_OP_ptr->output_list=IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",1); IO_ptr->width=lhs_width; // Update the rhs_ptr to reflect to the newly created PAD rhs_ptr=(input*) new input; rhs_ptr->inp_id=(char*) new char[strlen(curr_OP_ptr->op_id)+4]; i=j=0; while((rhs_ptr->inp_id[i++]=curr_OP_ptr->op_id[j++]) != '\0'); rhs_ptr->inp_id[i-1]='.'; rhs_ptr->inp_id[i++] = 'p'; rhs_ptr->inp_id[i++] = '1'; rhs_ptr->inp_id[i] = '\0'; // Update curr_OP_ptr , rhs_width curr_OP_ptr=curr_OP_ptr->next_op_ptr=(op_erator*) new op_erator; rhs_width = lhs_width; } // Now create the regular operator curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=WR; rhs_ptr->next_in_ptr=inp2; curr_OP_ptr->input_list=rhs_ptr; curr_OP_ptr->output_list=IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",1); IO_ptr->width=lhs_width; IO_ptr->name=(char*) new char[strlen(STR_ptr->name)+1]; strcpy(IO_ptr->name,STR_ptr->name); IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->symbol_id); } else { // lhs is not an alias -- create a or a PAD operator. Moreover, if // rhs is a operator, then just modify this operator to write into // the lhs storage if (lhs_width > rhs_width) { // Create a PAD operator curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=PAD; rhs_ptr->next_in_ptr=inp2; curr_OP_ptr->input_list=rhs_ptr; curr_OP_ptr->output_list=IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",1); IO_ptr->width=lhs_width; IO_ptr->name=(char*) new char[strlen(STR_ptr->name)+1]; strcpy(IO_ptr->name,STR_ptr->name); IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->symbol_id); } else { // If rhs is output of a operator, modify it to write into the // lhs. Otherwise create a operator if (rhs_is_op == 1 && OP_ptr->op_code == RD){ use_OP_ptr=1; OP_ptr->output_list->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(OP_ptr->output_list->destn_id,STR_ptr->symbol_id); OP_ptr->output_list->name=(char*) new char[strlen(STR_ptr->name)+1]; strcpy(OP_ptr->output_list->name,STR_ptr->name); OP_ptr->output_list->width=lhs_width; delete inp2->inp_id; delete inp2; } else { // Create the operator curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=RD; rhs_ptr->next_in_ptr=inp2; curr_OP_ptr->input_list=rhs_ptr; curr_OP_ptr->output_list=IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",1); IO_ptr->width=lhs_width; IO_ptr->name=(char*) new char[strlen(STR_ptr->name)+1]; strcpy(IO_ptr->name,STR_ptr->name); IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->symbol_id); } // end if (rhs is operator } // end if (lhs_width > rhs_width) } // end if (lhs is alias) // Check for SELECT operator if (SSR_ptr=top_SSR_ptr){ for(;SSR_ptr != 0; SSR_ptr=SSR_ptr->parent_ssr_ptr) this->update_parent(STR_ptr,SSR_ptr); } // Check if the module's output is to be updated int update_mo_output=0; // If signal, update it (Note ports will be mapped as signals here) if (st_type==SIGNAL) // a signal update_mo_output=1; else if (curr_MR_ptr->str_ptr->flags.is_loop==1) // a loop module update_mo_output=1; else if (STR_ptr->flags.is_formal==1) // a formal update_mo_output=1; else { // Check if the same storage appears in the input list of the module. IO_ptr=curr_MR_ptr->input_list; for(;IO_ptr != NULL;IO_ptr=IO_ptr->next_io_ptr) if (strcmp(STR_ptr->name,IO_ptr->name)==0) break; if (IO_ptr && IO_ptr->inout_id[0] == 'l') update_mo_output=0; else update_mo_output=1; } // Now check update_mo_output if (update_mo_output == 1){ IO_ptr=curr_MR_ptr->output_list; for(;IO_ptr != 0;IO_ptr=IO_ptr->next_io_ptr) if (strcmp(IO_ptr->name,STR_ptr->name)==0) break; if (IO_ptr == 0){ // new signal to be added to the output_list IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("o",MO_out_cnt++); IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->symbol_id); IO_ptr->width=lhs_width; IO_ptr->name=(char*) new char[strlen(STR_ptr->name)+1]; strcpy(IO_ptr->name,STR_ptr->name); if (tmp_IO_ptr=curr_MR_ptr->output_list){ for(;tmp_IO_ptr->next_io_ptr != 0; tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=IO_ptr; } else curr_MR_ptr->output_list=IO_ptr; } } // Check to see if lhs is in the carrier list char *new_inp_id; if (use_OP_ptr==0){ new_inp_id=(char*) new char[(i=strlen(curr_OP_ptr->op_id))+4]; strcpy(new_inp_id,curr_OP_ptr->op_id); } else{ new_inp_id=(char*) new char[(i=strlen(OP_ptr->op_id))+4]; strcpy(new_inp_id,OP_ptr->op_id); } new_inp_id[i++]='.'; new_inp_id[i++]='p'; new_inp_id[i++]='1'; new_inp_id[i++]='\0'; this->update_carrier_info(STR_ptr,new_inp_id); // Create the next operator record and set the "curr_OP_ptr" to it if (use_OP_ptr==0){ OP_ptr=(op_erator *) new op_erator; curr_OP_ptr->next_op_ptr=OP_ptr; curr_OP_ptr=OP_ptr; } #ifdef DEBUG cout << "Leaving : simple_assignment()\n"; #endif VOID_RETURN; } void CLASS_NAME :: array_assignment(int st_type,char *arr_name, input *index_ptr,input *rhs_ptr) { /************************************************************************* Implements the last phase of a array assignment statement. It's inputs are - (1) storage type (SIGNAL or VARIABLE), (2) l.h.s. array's name. (3) array index identification in the "input" format. (4) r.h.s. identification in the "input" format. Algo followed - (1) Find width of l.h.s. (1a) If the index is a constant, it must be an integer. Update it's width. (2) If the statement is in the scope of a SELECT operator, then the lhs is to become the output of the parent SELECT operator and the parent carrier list has to be modified accordingly. Call the routine update_parent() routine to implement this. (3) If storage concerned is not local to the current module, update the module's output. (4) If r.h.s. is an INTEGER, update it's width to that of the array. (5) Get r.h.s. width. (6) If rhs and lhs width don't match, create a or PAD operator. (7) Create the [w] operator. (8) Update the carrier info for the lhs. Global pointers/variables used (1) curr_MR_ptr (2) OP_cnt (3) CI_ptr (4) MO_out_cnt *************************************************************************/ #ifdef DEBUG cout << "Entered : array_assignment()\n"; #endif int lhs_width, rhs_width, i,j; char *id; input *inp1_ptr; constant_rec *CR_ptr; op_erator *OP_ptr; inout *tmp_IO_ptr, *IO_ptr; carrier_info *tmp_CI_ptr; symbol_table_rec *STR_ptr; select_stack_rec *SSR_ptr; // lhs width STR_ptr=this->get_STR_ptr(arr_name); delete arr_name; lhs_width=((i=(STR_ptr->bit_struct.from-STR_ptr->bit_struct.to))>0?i+1:1-i); // Check if the index is a constant if (index_ptr->inp_id[0]=='#'){ // It is a constant // Get the constant id char *const_id=(char*) new char[strlen(index_ptr->inp_id)-1]; i=0;j=2; while((const_id[i++]=index_ptr->inp_id[j++]) != '\0'); // Now get the constant record constant_rec *index_CR_ptr=global_CR_ptr; for(;index_CR_ptr != NULL;index_CR_ptr=index_CR_ptr->next_cr_ptr) if (strcmp(index_CR_ptr->constant_id,const_id)==0) break; // Now get the array width of arr_name j=((i=(STR_ptr->word_struct.from-STR_ptr->word_struct.to))>0?i+1:1-i); index_CR_ptr=this->update_const_width(this->log2(j),index_CR_ptr); // Now update the index_ptr delete index_ptr->inp_id; index_ptr->inp_id=(char*) new char[strlen(index_CR_ptr->constant_id)+3]; index_ptr->inp_id[0]='#'; index_ptr->inp_id[1]='.'; i=2;j=0; while((index_ptr->inp_id[i++]=index_CR_ptr->constant_id[j++]) != '\0'); } // end if // Check for SELECT operator if (SSR_ptr=top_SSR_ptr){ for(;SSR_ptr != 0; SSR_ptr=SSR_ptr->parent_ssr_ptr) this->update_parent(STR_ptr,SSR_ptr); } // storage concerned is not local to current module int update_mo_output=0; // If signal or port or formal, update it if (STR_ptr->flags.is_signal==1 || STR_ptr->flags.is_port==1 || STR_ptr->flags.is_formal==1) update_mo_output=1; else { // Update the module's output if the storage concerned is not local IO_ptr=curr_MR_ptr->input_list; for(;IO_ptr != NULL; IO_ptr=IO_ptr->next_io_ptr) if (strcmp(IO_ptr->name,STR_ptr->name)==0) break; if (IO_ptr && IO_ptr->inout_id[0] == 'l') update_mo_output=0; else update_mo_output=1; } // Now check update_mo_output if (update_mo_output == 1){ IO_ptr=curr_MR_ptr->output_list; for(;IO_ptr != 0;IO_ptr=IO_ptr->next_io_ptr) if (strcmp(IO_ptr->name,STR_ptr->name)==0) break; if (IO_ptr == 0){ // new signal to be added to the output_list IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("o",MO_out_cnt++); IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->symbol_id); IO_ptr->width=lhs_width; IO_ptr->name=(char*) new char[strlen(STR_ptr->name)+1]; strcpy(IO_ptr->name,STR_ptr->name); if (tmp_IO_ptr=curr_MR_ptr->output_list){ for(;tmp_IO_ptr->next_io_ptr != 0; tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=IO_ptr; } else curr_MR_ptr->output_list=IO_ptr; } } // If rhs is INTEGER, update it's width & get rhs width if (rhs_ptr->inp_id[0] == '#'){ i=0;j=2; id=(char*) new char[strlen(rhs_ptr->inp_id)-1]; while((id[i++]=rhs_ptr->inp_id[j++]) != '\0'); CR_ptr=global_CR_ptr; for(;strcmp(CR_ptr->constant_id,id) != 0;CR_ptr=CR_ptr->next_cr_ptr); if (CR_ptr->width==UNKNOWN) // rhs is INTEGER rhs_width=CR_ptr->width=lhs_width; else rhs_width=CR_ptr->width; } else rhs_width=this->get_width(rhs_ptr); // Check to see if the rhs and lhs widths match. If not create either a // operator or a PAD operator if (rhs_width != lhs_width){ curr_OP_ptr->op_id=this->rename("x",OP_cnt++); if (rhs_width < lhs_width) // Create a PAD operator curr_OP_ptr->op_code=PAD; else { // Create a RD operator curr_OP_ptr->op_code=RD; // Create the 2nd input of the RD operator constant_rec *CR_ptr=this->add_constant(this->log2(rhs_width),0); input *inp2=(input*) new input; inp2->inp_id=(char*) new char[strlen(CR_ptr->constant_id)+3]; i=j=0; inp2->inp_id[i++]='#'; inp2->inp_id[i++]='.'; while((inp2->inp_id[i++]=CR_ptr->constant_id[j++]) != '\0'); rhs_ptr->next_in_ptr=inp2; } curr_OP_ptr->input_list=rhs_ptr; // Create the output list IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",1); IO_ptr->width=lhs_width; curr_OP_ptr->output_list=IO_ptr; // update the rhs pointer to be used by the [w] operator to be // created next rhs_ptr=(input*) new input; rhs_ptr->inp_id=(char*) new char[(i=strlen(curr_OP_ptr->op_id))+4]; strcpy(rhs_ptr->inp_id,curr_OP_ptr->op_id); rhs_ptr->inp_id[i++]='.'; rhs_ptr->inp_id[i++]='p'; rhs_ptr->inp_id[i++]='1'; rhs_ptr->inp_id[i++]='\0'; // Create the next operator record and set the "curr_OP_ptr" to it op_erator *OP_ptr=(op_erator *) new op_erator; curr_OP_ptr->next_op_ptr=OP_ptr; curr_OP_ptr=OP_ptr; } // Now create the [w] operator for the assignment curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=ARRWR; inp1_ptr=this->source_id(STR_ptr->name); // "input" equivalent of array name inp1_ptr->next_in_ptr=index_ptr; index_ptr->next_in_ptr=rhs_ptr; curr_OP_ptr->input_list=inp1_ptr; IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",1); IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->symbol_id); IO_ptr->width=lhs_width; IO_ptr->name=(char*) new char[strlen(STR_ptr->name)+1]; strcpy(IO_ptr->name,STR_ptr->name); curr_OP_ptr->output_list=IO_ptr; // Update the carrier info for the array. tmp_CI_ptr=CI_ptr; for (;tmp_CI_ptr != 0;tmp_CI_ptr=tmp_CI_ptr->next_ci_ptr){ if (tmp_CI_ptr->str_ptr == STR_ptr){ // Is in the list delete tmp_CI_ptr->op_inp_id; tmp_CI_ptr->op_inp_id=(char*) new char[(i=strlen(curr_OP_ptr->op_id))+4]; strcpy(tmp_CI_ptr->op_inp_id,curr_OP_ptr->op_id); tmp_CI_ptr->op_inp_id[i++]='.'; tmp_CI_ptr->op_inp_id[i++]='p'; tmp_CI_ptr->op_inp_id[i++]='1'; tmp_CI_ptr->op_inp_id[i++]='\0'; // Create the next operator record and set the "curr_OP_ptr" to it op_erator *OP_ptr=(op_erator *) new op_erator; curr_OP_ptr->next_op_ptr=OP_ptr; curr_OP_ptr=OP_ptr; #ifdef DEBUG cout << "Leaving : array_assignment()\n"; #endif VOID_RETURN; } } // IF you are still here, something unexplainable has hapenned.B'cos // a carrier info will be created by this->source_id in case it does'nt // already exist cout << "Bailing out in array_assignment - unexplainable behavior\n"; exit(1); } void CLASS_NAME :: push(module_rec *inp_ptr) { /************************************************************************** This routine takes as input a module_rec ptr and does the following (1) Put the input module at the end of the module list. (2) Creates a new context record and saves the global variables and pointers in it. (3) Puts this context record in the stack. (4) Initializes all the global variables for the new context. Global variables referenced/modified : (1) curr_CXR_ptr; (2) OP_cnt (3) MO_inp_cnt (4) MO_out_cnt (5) OP_out_cnt (6) CI_ptr (7) curr_MR_ptr (8) global_MR_ptr (9) curr_OP_ptr **************************************************************************/ #ifdef DEBUG cout << "Entered : push()\n"; #endif // Put the newly created module at the end of the module list module_rec *tmp_MR_ptr=global_MR_ptr; if (tmp_MR_ptr){ for (;tmp_MR_ptr->next_mr_ptr != 0; tmp_MR_ptr=tmp_MR_ptr->next_mr_ptr); tmp_MR_ptr->next_mr_ptr=inp_ptr; } else global_MR_ptr=inp_ptr; // create a new context record to save the current context context_rec *new_CXR_ptr=(context_rec*) new context_rec; // Save the existing global variables new_CXR_ptr->op_cnt=OP_cnt; new_CXR_ptr->mo_inp_cnt=MO_inp_cnt; new_CXR_ptr->mo_out_cnt=MO_out_cnt; new_CXR_ptr->op_out_cnt=OP_out_cnt; new_CXR_ptr->ci_ptr=CI_ptr; new_CXR_ptr->mr_ptr=curr_MR_ptr; new_CXR_ptr->curr_op_ptr=curr_OP_ptr; // Stack it up new_CXR_ptr->prev_cxr_ptr=curr_CXR_ptr; curr_CXR_ptr=new_CXR_ptr; // Initialize the global variables MO_inp_cnt=MO_out_cnt=OP_cnt=OP_out_cnt=1; CI_ptr=0; curr_MR_ptr=inp_ptr; curr_OP_ptr=inp_ptr->operator_list=(op_erator*) new op_erator; #ifdef DEBUG cout << "Leaving : push()\n"; #endif VOID_RETURN; } module_rec* CLASS_NAME :: pop() { /********************************************************************** Pops the topmost context record out. Initializes the global variables to that stored in the previous context record. It also frees the last operator of the current module which is s'posed to be blank. ***********************************************************************/ context_rec *temp_ptr=curr_CXR_ptr; module_rec *ret_ptr=curr_MR_ptr; // Free the CI_ptr and curr_OP_ptr this->free_ci(CI_ptr); // find the last operator of the current module which is s'posed to // a blank operator and delete it. op_erator *OP_ptr=curr_MR_ptr->operator_list ,*prev_OP_ptr=NULL; for (;OP_ptr->next_op_ptr!=0;prev_OP_ptr=OP_ptr,OP_ptr=OP_ptr->next_op_ptr); delete OP_ptr; if (prev_OP_ptr) prev_OP_ptr->next_op_ptr=NULL; else curr_MR_ptr->operator_list=NULL; // Initialize the global variables OP_cnt=curr_CXR_ptr->op_cnt; MO_inp_cnt=curr_CXR_ptr->mo_inp_cnt; MO_out_cnt=curr_CXR_ptr->mo_out_cnt; OP_out_cnt=curr_CXR_ptr->op_out_cnt; CI_ptr=curr_CXR_ptr->ci_ptr; curr_MR_ptr=curr_CXR_ptr->mr_ptr; curr_OP_ptr=curr_CXR_ptr->curr_op_ptr; curr_CXR_ptr=curr_CXR_ptr->prev_cxr_ptr; delete temp_ptr; PTR_RETURN(ret_ptr); } void CLASS_NAME :: update_parent(symbol_table_rec *inp_STR_ptr, select_stack_rec *inp_SSR_ptr) { /********************************************************************** This routine basically takes care of a SELECT operator (IF statement). Consider the following code -- if then x := a + b; end if; The above is converted such that "x" becomes the output of the SELECT operator representing the "if". Also, at the level of the "if" statement, "x" becomes the output of the SELECT operator. **********************************************************************/ #ifdef DEBUG cout << "Entered : update_parent()\n"; #endif symbol_table_rec *STR_ptr; inout *OUT_ptr, *tmp_OUT_ptr; carrier_info *tmp_CI_ptr; int width,i,j; char *id; // First check to see if the variable already exists in the output // list of the parent SELECT operator. If it does, return OUT_ptr=inp_SSR_ptr->parent_sel_op_ptr->output_list; for(;OUT_ptr != 0;OUT_ptr=OUT_ptr->next_io_ptr){ if (strcmp(OUT_ptr->destn_id,inp_STR_ptr->symbol_id)==0){ #ifdef DEBUG cout << "Leaving : update_parent()\n"; #endif VOID_RETURN; } } // If you are still here, then create an output record for the SELECT // operator and modify the carrier info to this effect OUT_ptr=(inout*) new inout; OUT_ptr->inout_id=this->rename("p",inp_SSR_ptr->output_cnt++); OUT_ptr->destn_id=(char*) new char[strlen(inp_STR_ptr->symbol_id)+1]; strcpy(OUT_ptr->destn_id,inp_STR_ptr->symbol_id); width=((i=(inp_STR_ptr->bit_struct.from - inp_STR_ptr->bit_struct.to)) > 0 ?i+1:1-i); OUT_ptr->width=width; OUT_ptr->name=(char*) new char[strlen(inp_STR_ptr->name)+1]; strcpy(OUT_ptr->name,inp_STR_ptr->name); // now insert it at the end of the list if(tmp_OUT_ptr=inp_SSR_ptr->parent_sel_op_ptr->output_list){ for(;tmp_OUT_ptr->next_io_ptr != 0;tmp_OUT_ptr=tmp_OUT_ptr->next_io_ptr); tmp_OUT_ptr->next_io_ptr=OUT_ptr; } else inp_SSR_ptr->parent_sel_op_ptr->output_list=OUT_ptr; #ifdef DEBUG cout << "Leaving : update_parent()\n"; #endif VOID_RETURN; } void CLASS_NAME :: push_SSR(select_stack_rec *inp_SSR_ptr) { // Just pushes the inp pointer to make it the top of stack inp_SSR_ptr->parent_ssr_ptr=top_SSR_ptr; top_SSR_ptr=inp_SSR_ptr; VOID_RETURN; } void CLASS_NAME :: pop_SSR() { // Sets the global pointers "curr_OP_ptr" and "CI_ptr" to that of the // immediate parent and pops the parent record. // Also for all the outputs of the parent SELECT operator, it modifies // the carrier list accordingly. carrier_info *tmp_CI_ptr; int i,j; select_stack_rec *tmp_ptr=top_SSR_ptr; this->free_ci(CI_ptr); CI_ptr=top_SSR_ptr->parent_ci_ptr; curr_OP_ptr=top_SSR_ptr->parent_sel_op_ptr; // Now for updation of the carrier list op_erator *OP_ptr=top_SSR_ptr->parent_sel_op_ptr; inout *IO_ptr=OP_ptr->output_list; for(;IO_ptr != NULL;IO_ptr=IO_ptr->next_io_ptr){ symbol_table_rec *STR_ptr=get_STR_ptr(IO_ptr->name); tmp_CI_ptr=CI_ptr; for(;tmp_CI_ptr != NULL;tmp_CI_ptr=tmp_CI_ptr->next_ci_ptr){ if (tmp_CI_ptr->str_ptr==STR_ptr){ // Is in the carrier list delete tmp_CI_ptr->op_inp_id; tmp_CI_ptr->op_inp_id = (char*) new char[strlen(OP_ptr->op_id)+strlen(IO_ptr->inout_id)+2]; i=j=0; while((tmp_CI_ptr->op_inp_id[i++]=OP_ptr->op_id[j++]) != '\0'); j=0;tmp_CI_ptr->op_inp_id[i-1]='.'; while((tmp_CI_ptr->op_inp_id[i++]=IO_ptr->inout_id[j++]) != '\0'); break; } // end if } // end for if (tmp_CI_ptr==NULL){ // Not in the carrier list tmp_CI_ptr=(carrier_info*) new carrier_info; tmp_CI_ptr->str_ptr=STR_ptr; tmp_CI_ptr->op_inp_id = (char*) new char[strlen(OP_ptr->op_id)+strlen(IO_ptr->inout_id)+2]; i=j=0; while((tmp_CI_ptr->op_inp_id[i++]=OP_ptr->op_id[j++]) != '\0'); j=0;tmp_CI_ptr->op_inp_id[i-1]='.'; while((tmp_CI_ptr->op_inp_id[i++]=IO_ptr->inout_id[j++]) != '\0'); tmp_CI_ptr->next_ci_ptr=CI_ptr; CI_ptr=tmp_CI_ptr; } // end if } // end for top_SSR_ptr=top_SSR_ptr->parent_ssr_ptr; delete tmp_ptr; VOID_RETURN; } select_stack_rec* CLASS_NAME :: mk_select_op(input *cond_ptr) { /********************************************************************* This routine creates the enviornment to process the IF statement. The following things are performed -- (0) Checks if the cond_ptr is coming from a RD operator. If not, it introduces a RD operator that reads the cond_ptr. - Commented out. (1) Creates a SELECT operator. (2) Creates another free operator for the curr_OP_ptr. !! - No, let cl_select_op() do that. (3) Creates a "select_stack_rec" to store the parent information. These include - CI_ptr, current SELECT operator ptr and curr_OP_ptr (4) Calls push_SSR() to push this record on the stack (5) returns the pointer to select_stack_rec created to be used later by the cl_select_op() routine. **********************************************************************/ #ifdef DEBUG cout << "Entered : mk_select_op()\n"; #endif int i,j; /*************************************************************************** // Check if the cond_ptr is coming from a RD operator int RD_output=0; if (cond_ptr->inp_id[0] == 'x'){ char *op_id=(char*) new char[strlen(cond_ptr->inp_id)-2]; i=j=0; while((op_id[i++]=cond_ptr->inp_id[j++]) != '.'); op_id[i-1]='\0'; op_erator *tmp_OP_ptr=this->get_op_ptr(op_id,curr_MR_ptr->operator_list); if (tmp_OP_ptr->op_code == RD) RD_output=1; } if (RD_output == 0){ // Create a RD operator curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=RD; // Input 1 curr_OP_ptr->input_list=(input*) new input; curr_OP_ptr->input_list->inp_id=cond_ptr->inp_id; // Input 2 constant_rec *CR_ptr=this->add_constant(1,0); input *inp2=(input*) new input; inp2->inp_id=(char*) new char[strlen(CR_ptr->constant_id)+3]; i=j=0; inp2->inp_id[i++]='#'; inp2->inp_id[i++]='.'; while((inp2->inp_id[i++]=CR_ptr->constant_id[j++]) != '\0'); curr_OP_ptr->input_list->next_in_ptr=inp2; // RD output curr_OP_ptr->output_list=(inout*) new input; curr_OP_ptr->output_list->inout_id=this->rename("p",1); curr_OP_ptr->output_list->width=1; // Modify cond_ptr cond_ptr->inp_id=(char*) new char[strlen(curr_OP_ptr->op_id)+4]; i=j=0; while((cond_ptr->inp_id[i++]=curr_OP_ptr->op_id[j++]) != '\0'); cond_ptr->inp_id[i-1]='.'; cond_ptr->inp_id[i++]='p'; cond_ptr->inp_id[i++]='1'; cond_ptr->inp_id[i++]='\0'; // Create another operator curr_OP_ptr=curr_OP_ptr->next_op_ptr=(op_erator*) new op_erator; } ***************************************************************************/ // Create the SEL operator curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=SELECT; curr_OP_ptr->input_list=cond_ptr; // Now for the next operator // op_erator* OP_ptr=(op_erator*) new op_erator; // curr_OP_ptr->next_op_ptr=OP_ptr; // Now create the select_stack record select_stack_rec *SSR_ptr=(select_stack_rec*) new select_stack_rec; SSR_ptr->parent_sel_op_ptr=curr_OP_ptr; SSR_ptr->output_cnt=1; SSR_ptr->br_cnt=1; SSR_ptr->parent_ci_ptr=CI_ptr; // SSR_ptr->curr_op_ptr=curr_OP_ptr; CI_ptr=NULL; // Push the SSR into the stack this->push_SSR(SSR_ptr); // Set the curr_OP_ptr to NULL curr_OP_ptr=NULL; // return the pointer #ifdef DEBUG cout << "Leaving : mk_select_op()\n"; #endif PTR_RETURN(SSR_ptr); } void CLASS_NAME :: cl_select_op(select_stack_rec *till_SSR_ptr) { /********************************************************************** This routine closes the current SELECT operator. As input, it takes as input a "select_stack_rec" pointer and pops the select_stack till (and including) the till_SSR_ptr. This unstructured form of handling the VHDL IF statements deems necessary due to the following scenerio -- if then if then elsif then else ---> then elsif then ---> else else if then end if; else end if; In the above scenerio, it is evident that when we encounter the "end if" directive, we need to go back to the level of the top level "if" statement. To achieve this, while parsing, when we come across the "if" statement, we create a "select_stack_rec" and save it's pointer. The select_stack may then be developed as needed. When we come to the "end if" directive, we pop the stack to the point of the top level "if" statement. - See also the parser code. Algo - Keep popping till top of stack matches the input pointer. Pop once more. Also - It deletes the last operator record of the last branch. This branch is obtained from the top_SSR_ptr's select operator pointer. It also creates the next operator and sets the curr_OP_ptr to it. *******************************************************************/ #ifdef DEBUG cout << "Entered : cl_select_op()\n"; #endif // Delete the last operator of the last branch branch_rec *tmp_BR_ptr; if (tmp_BR_ptr=top_SSR_ptr->parent_sel_op_ptr->br_ptr){ for(;tmp_BR_ptr->next_br_ptr != 0; tmp_BR_ptr=tmp_BR_ptr->next_br_ptr); // Now delete the last operator of the previous branch op_erator *OP_ptr, *prev_OP_ptr=NULL; OP_ptr=tmp_BR_ptr->op_ptr; for(;OP_ptr->next_op_ptr!=NULL;prev_OP_ptr=OP_ptr,OP_ptr=OP_ptr->next_op_ptr); delete(OP_ptr); if (prev_OP_ptr) prev_OP_ptr->next_op_ptr=NULL; else tmp_BR_ptr->op_ptr=NULL; } // Do the poppings for(;top_SSR_ptr != till_SSR_ptr;this->pop_SSR()); this->pop_SSR(); // Create the next operator record op_erator *OP_ptr=(op_erator*) new op_erator; curr_OP_ptr->next_op_ptr=OP_ptr; curr_OP_ptr=OP_ptr; #ifdef DEBUG cout << "Leaving : cl_select_op()\n"; #endif VOID_RETURN; } carrier_info* CLASS_NAME :: copy_ci(carrier_info *inp_CI_ptr) { /************************************************************************* Makes a copy of the input carrier_info pointer - recursively and return the copied list *************************************************************************/ #ifdef DEBUG cout << "Entered : copy_ci()\n"; #endif carrier_info *ret_ptr=NULL, *tmp1_CI_ptr=inp_CI_ptr, *tmp2_CI_ptr; for(;tmp1_CI_ptr != 0; tmp1_CI_ptr=tmp1_CI_ptr->next_ci_ptr){ tmp2_CI_ptr=(carrier_info*) new carrier_info; tmp2_CI_ptr->str_ptr=tmp1_CI_ptr->str_ptr; tmp2_CI_ptr->op_inp_id=(char*) new char[strlen(tmp1_CI_ptr->op_inp_id)+1]; strcpy(tmp2_CI_ptr->op_inp_id,tmp1_CI_ptr->op_inp_id); tmp2_CI_ptr->next_ci_ptr=ret_ptr; ret_ptr=tmp2_CI_ptr; } #ifdef DEBUG cout << "Leaving : copy_ci()\n"; #endif PTR_RETURN(ret_ptr); } void CLASS_NAME :: mk_if_branch(int value) { /************************************************************************ Just creates a branch_val_rec and calls mk_branch with it ************************************************************************/ branch_val_rec *BVR_ptr=(branch_val_rec*) new branch_val_rec; BVR_ptr->value=value; BVR_ptr->next_bvr_ptr=NULL; this->mk_branch(BVR_ptr); VOID_RETURN; } void CLASS_NAME :: mk_branch(branch_val_rec *BVR_list) { /************************************************************************ This routine creates a branch record with the input branch condition. It puts the branch record at the end of the branch list of the parent select operator. It also frees space of the previous branches carrier info and the curr_OP_ptr which is s'posed to be a blank operator of the previous branch_record operator list. Global pointers used : (1) top_SSR_ptr (2) CI_ptr Global variables initialized (1) curr_OP_ptr (2) CI_ptr ************************************************************************/ #ifdef DEBUG cout << "Entered : mk_branch()\n"; #endif branch_rec *tmp_BR_ptr; char *id; int width, i, j; this->free_ci(CI_ptr); // Create the branch record branch_rec *BR_ptr=(branch_rec*) new branch_rec; id=this->rename("b",top_SSR_ptr->br_cnt++); width=strlen(top_SSR_ptr->parent_sel_op_ptr->op_id)+(i=strlen(id))+2; BR_ptr->branch_id=(char*) new char[width]; strcpy(BR_ptr->branch_id,id); BR_ptr->branch_id[i++]='.'; j=0; while((BR_ptr->branch_id[i++]=top_SSR_ptr->parent_sel_op_ptr->op_id[j++]) != '\0'); BR_ptr->bvr_list=BVR_list; BR_ptr->op_ptr=curr_OP_ptr=(op_erator*) new op_erator; // put it at the end of the branch_list if (tmp_BR_ptr=top_SSR_ptr->parent_sel_op_ptr->br_ptr){ for(;tmp_BR_ptr->next_br_ptr != 0; tmp_BR_ptr=tmp_BR_ptr->next_br_ptr); tmp_BR_ptr->next_br_ptr=BR_ptr; // Now delete the last operator of the previous branch op_erator *OP_ptr=tmp_BR_ptr->op_ptr,*prev_OP_ptr=NULL; for(;OP_ptr->next_op_ptr!=NULL;prev_OP_ptr=OP_ptr,OP_ptr=OP_ptr->next_op_ptr); delete(OP_ptr); if (prev_OP_ptr) prev_OP_ptr->next_op_ptr=NULL; else tmp_BR_ptr->op_ptr=NULL; } else top_SSR_ptr->parent_sel_op_ptr->br_ptr=BR_ptr; // Now for the Initializing the global variables CI_ptr=this->copy_ci(top_SSR_ptr->parent_ci_ptr); #ifdef DEBUG cout << "Leaving : mk_branch()\n"; #endif VOID_RETURN; } void CLASS_NAME :: mk_wait_module(id_rec* inp_list) { /************************************************************************ Creates a "wait" module. It takes as input an id_list that has the names of the signals that the process "WAITs ON". These signals are treated as local to the wait module. The "UNTIL" part is implemented as normal operator list inside the "wait" module. It performs the following tasks - (1) Creates a new "module_rec" and a symbol table entry indicating that it is a wait statement. (2) calls push() to push the parent context information in the stack (3) Goes thru the "inp_list" and creates a local input for each entry in the "inp_list". Globals used : curr_MR_ptr ***********************************************************************/ #ifdef DEBUG cout << "Entered : mk_wait_module()\n"; #endif // Create the Symbol table entry and update it symbol_table_rec *STR_ptr=(symbol_table_rec*) new symbol_table_rec; STR_ptr->symbol_id=this->rename("m",STR_cnt++); STR_ptr->parent_id=(char*) new char[strlen(curr_MR_ptr->str_ptr->symbol_id)+1]; strcpy(STR_ptr->parent_id,curr_MR_ptr->str_ptr->symbol_id); STR_ptr->flags.is_wait=1; // Update the symbol table (curr_MR_ptr has to be defined at this point) symbol_table_rec *tmp_STR_ptr=curr_MR_ptr->STR_list; if (tmp_STR_ptr){ for(;tmp_STR_ptr->next_str_ptr != NULL; tmp_STR_ptr=tmp_STR_ptr->next_str_ptr); tmp_STR_ptr->next_str_ptr=STR_ptr; } else curr_MR_ptr->STR_list=STR_ptr; // Create the module record and set the envioronment module_rec *MR_ptr=(module_rec*) new module_rec; MR_ptr->str_ptr=STR_ptr; // push the parent module -- Step (2) this->push(MR_ptr); // Take care of the "inp_list" (if any) -- Step (3) id_rec *IR_ptr=inp_list; for(;IR_ptr != NULL;IR_ptr=IR_ptr->next_id_ptr){ int i,j, width; STR_ptr=this->get_STR_ptr(IR_ptr->id); inout *IO_ptr = (inout*) new inout; IO_ptr->inout_id=this->rename("l",MO_inp_cnt++); IO_ptr->destn_id=(char*) new char[strlen(STR_ptr->symbol_id)+1]; strcpy(IO_ptr->destn_id,STR_ptr->symbol_id); width=((i=(STR_ptr->bit_struct.from-STR_ptr->bit_struct.to)) > 0 ?i+1:1-i); IO_ptr->width=width; IO_ptr->name=(char*) new char[strlen(IR_ptr->id)+1]; strcpy(IO_ptr->name,IR_ptr->id); // Now put it at the begining of the "module input list" if (MR_ptr->input_list){ inout *tmp_IO_ptr=MR_ptr->input_list; for(;tmp_IO_ptr->next_io_ptr!=NULL;tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=IO_ptr; } else MR_ptr->input_list=IO_ptr; } #ifdef DEBUG cout << "Leaving : mk_wait_module()\n"; #endif VOID_RETURN; } void CLASS_NAME :: mk_loop_module(char* name) { /************************************************************************ Sets up the envioronment to process a "loop" statement. In doing so, it performs the following tasks - (1) Creates a new "module_rec" and a symbol table entry indicating that it is a loop statement. (2) calls push() to push the parent context information in the stack Globals used : curr_MR_ptr ***********************************************************************/ #ifdef DEBUG cout << "Entered : mk_loop_module()\n"; #endif // Create the Symbol table entry and update it symbol_table_rec *STR_ptr=(symbol_table_rec*) new symbol_table_rec; STR_ptr->symbol_id=this->rename("m",STR_cnt++); STR_ptr->parent_id=(char*) new char[strlen(curr_MR_ptr->str_ptr->symbol_id)+1]; strcpy(STR_ptr->parent_id,curr_MR_ptr->str_ptr->symbol_id); STR_ptr->flags.is_loop=1; if (name){ // has a name STR_ptr->name=(char*) new char[strlen(name)+1]; strcpy(STR_ptr->name,name); } // Update the symbol table symbol_table_rec *tmp_STR_ptr=curr_MR_ptr->STR_list; if (tmp_STR_ptr){ for(;tmp_STR_ptr->next_str_ptr != NULL; tmp_STR_ptr=tmp_STR_ptr->next_str_ptr); tmp_STR_ptr->next_str_ptr=STR_ptr; } else curr_MR_ptr->STR_list=STR_ptr; // Create the module record and set the envioronment module_rec *MR_ptr=(module_rec*) new module_rec; MR_ptr->str_ptr=STR_ptr; // push the parent module this->push(MR_ptr); #ifdef DEBUG cout << "Leaving : mk_loop_module()\n"; #endif VOID_RETURN; } void CLASS_NAME :: mk_while_condition(input *inp_ptr) { /************************************************************************* Creates a SELECT operator for the while condition. while loop ----> SELECT ----> BRANCH [FALSE] => leave module end loop; RESTART module This routine creates the SELECT operator that takes care of the while condition. ************************************************************************/ #ifdef DEBUG cout << "Entered : mk_while_condition()\n"; #endif int i,j; // Create the SELECT operator curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=SELECT; curr_OP_ptr->input_list=inp_ptr; branch_rec *BR_ptr=(branch_rec*) new branch_rec; BR_ptr->branch_id=(char*) new char[strlen(curr_OP_ptr->op_id)+4]; i=0;j=0; BR_ptr->branch_id[i++]='b'; BR_ptr->branch_id[i++]='1'; BR_ptr->branch_id[i++]='.'; while((BR_ptr->branch_id[i++]=curr_OP_ptr->op_id[j++]) != '\0'); BR_ptr->bvr_list=(branch_val_rec*) new branch_val_rec; BR_ptr->bvr_list->value=FALSE; BR_ptr->bvr_list->next_bvr_ptr=NULL; BR_ptr->op_ptr=(op_erator*) new op_erator; BR_ptr->op_ptr->op_id=this->rename("x",OP_cnt++); BR_ptr->op_ptr->op_code=LEAVE; BR_ptr->op_ptr->module_id=(char*) new char[strlen(curr_MR_ptr->str_ptr->symbol_id)+1]; strcpy(BR_ptr->op_ptr->module_id,curr_MR_ptr->str_ptr->symbol_id); curr_OP_ptr->br_ptr=BR_ptr; // Remember to update the curr_OP_ptr op_erator *OP_ptr=(op_erator*) new op_erator; curr_OP_ptr->next_op_ptr=OP_ptr; curr_OP_ptr=OP_ptr; #ifdef DEBUG cout << "Leaving : mk_while_condition()\n"; #endif VOID_RETURN; } module_rec* CLASS_NAME :: cl_module() { /************************************************************************* It finishes the processing of a module by simply popping the parent envioronment. It returns the pointer to the child module's rec **************************************************************************/ module_rec *ret_ptr=curr_MR_ptr; this->pop(); PTR_RETURN(ret_ptr); } void CLASS_NAME :: loop_or_wait_stmnt(module_rec *inp_MR_ptr) { /*********************************************************************** Creates an equivalent ENTER operator for the input loop_module and appends it to the operator list of the current module. It calls mk_ENTER() - which operates on the current module envioronment. ************************************************************************/ #ifdef DEBUG cout << "Entered : loop_or_wait_stmnt()\n"; #endif this->mk_ENTER(inp_MR_ptr); // update the curr_OP_ptr op_erator* OP_ptr=(op_erator*) new op_erator; curr_OP_ptr->next_op_ptr=OP_ptr; curr_OP_ptr=OP_ptr; #ifdef DEBUG cout << "Leaving : loop_or_wait_stmnt()\n"; #endif VOID_RETURN; } op_erator* CLASS_NAME :: mk_par_ENTER(module_rec *inp_MR_ptr) { /************************************************************************ It creates an ENTER operator for a "concurrent_statement" that is a part of an "architecture" or "block". It operates and modifies the current module envioronment (an "architecture" or "block"). Algo - (1) It goes thru the Input list of the "inp_module" and creates the input list for the ENTER operator. In doing so, it calls the this->source_id() to append any new signals to the input list of the current module. (2) It creates the ENTER operator. (3) Loops thru the output list of the "inp_module" and - If the storage concerned is a signal, looks for possible updation needed in the current module's output. - Creates the ENTER operators output. ************************************************************************/ #ifdef DEBUG cout << "Entered : mk_par_ENTER()\n"; #endif inout *IO_ptr, *tmp_IO_ptr, *loop_ptr; input *IN_ptr, *OP_in_list=NULL, *tmp_IN_ptr; symbol_table_rec *STR_ptr; int i,j; OP_out_cnt=1; // This routine operates partially on the processes envioronment to look for // proper STRs. So, make the set the curr_MR_ptr to that of the concurrent // statement for which U are creating this ENTER operator as needed module_rec *parent_MR_ptr=curr_MR_ptr; // First create the input list for the ENTER operator for(IO_ptr=inp_MR_ptr->input_list;IO_ptr != 0;IO_ptr=IO_ptr->next_io_ptr){ if (IO_ptr->inout_id[0] == 'i'){ IN_ptr=this->source_id(IO_ptr->name); if (OP_in_list==NULL) OP_in_list=tmp_IN_ptr=IN_ptr; else { tmp_IN_ptr->next_in_ptr=IN_ptr; tmp_IN_ptr=tmp_IN_ptr->next_in_ptr; } } } // Now create the ENTER operator op_erator *ret_ptr=(op_erator*) new op_erator; ret_ptr->op_id=this->rename("x",OP_cnt++); ret_ptr->op_code=ENTER; ret_ptr->module_id=(char*) new char[(i=strlen(inp_MR_ptr->str_ptr->symbol_id))+2]; strcpy(ret_ptr->module_id,inp_MR_ptr->str_ptr->symbol_id); ret_ptr->input_list=OP_in_list; // Loop thru the output list of the input module curr_MR_ptr=inp_MR_ptr; loop_ptr=inp_MR_ptr->output_list; for(;loop_ptr != NULL;loop_ptr=loop_ptr->next_io_ptr){ STR_ptr=this->get_STR_ptr(loop_ptr->name); // If storage concerned is a signal, may need to update module output list if ((STR_ptr->flags.is_signal == 1) || (STR_ptr->flags.is_port == 1)){ IO_ptr=parent_MR_ptr->output_list; for(;IO_ptr != NULL;IO_ptr=IO_ptr->next_io_ptr) if (strcmp(IO_ptr->name,loop_ptr->name)==0) break; if (IO_ptr == NULL){ // new signal to be added to the output_list IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("o",MO_out_cnt++); IO_ptr->destn_id=(char*) new char[strlen(loop_ptr->destn_id)+1]; strcpy(IO_ptr->destn_id,loop_ptr->destn_id); IO_ptr->width=loop_ptr->width; IO_ptr->name=(char*) new char[strlen(loop_ptr->name)+1]; strcpy(IO_ptr->name,loop_ptr->name); if (tmp_IO_ptr=parent_MR_ptr->output_list){ for(;tmp_IO_ptr->next_io_ptr != 0;tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=IO_ptr; } else parent_MR_ptr->output_list=IO_ptr; } } // Now create an output for the ENTER operator and put it in the list IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",OP_out_cnt++); IO_ptr->destn_id=(char*) new char[strlen(loop_ptr->destn_id)+1]; strcpy(IO_ptr->destn_id,loop_ptr->destn_id); IO_ptr->width=loop_ptr->width; IO_ptr->name=(char*) new char[strlen(loop_ptr->name)+1]; strcpy(IO_ptr->name,loop_ptr->name); if (tmp_IO_ptr=ret_ptr->output_list){ for(;tmp_IO_ptr->next_io_ptr != 0;tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=IO_ptr; } else ret_ptr->output_list=IO_ptr; } // End of looping the "inp_module" output list // Now reset the envioronment curr_MR_ptr=parent_MR_ptr; // After you are done with all the outputs of the ENTER operator, set // the OP_out_cnt to 1 OP_out_cnt=1; #ifdef DEBUG cout << "Leaving : mk_par_ENTER()\n"; #endif PTR_RETURN(ret_ptr); } void CLASS_NAME :: mk_ENTER(module_rec *inp_MR_ptr) { /************************************************************************ It creates a ENTER/WAIT operator for the input module with proper inputs and outputs as identified by the module_rec of the input module. It operates and modifies the current module envioronment. Algo - (1) It goes thru the Input list of the "loop_module" and creates the input list for the ENTER operator. In doing so, it calls the this->source_id() to append any new signals to the input list of the current module. (2) It creates the ENTER/WAIT operator. (3) Loops thru the output list of the "loop_module" and - If the storage concerned is a signal, or is a formal, or the current module is a loop or the storage concerned is not local to the current module, update the output. - Creates the ENTER operators output. - Updates the carrier list for the particular storage. ************************************************************************/ #ifdef DEBUG cout << "Entered : mk_ENTER()\n"; #endif inout *IO_ptr, *tmp_IO_ptr, *loop_ptr; input *IN_ptr, *OP_in_list=NULL, *tmp_IN_ptr; carrier_info *tmp_CI_ptr; symbol_table_rec *STR_ptr; op_erator *OP_ptr; int i,j; OP_out_cnt=1; // First create the input list for the ENTER operator for(IO_ptr=inp_MR_ptr->input_list;IO_ptr != 0;IO_ptr=IO_ptr->next_io_ptr){ if (IO_ptr->inout_id[0] == 'i'){ IN_ptr=this->source_id(IO_ptr->name); if (OP_in_list==NULL) OP_in_list=tmp_IN_ptr=IN_ptr; else { tmp_IN_ptr->next_in_ptr=IN_ptr; tmp_IN_ptr=tmp_IN_ptr->next_in_ptr; } } } // Now create the ENTER/WAIT operator curr_OP_ptr->op_id=this->rename("x",OP_cnt++); if (inp_MR_ptr->str_ptr->flags.is_wait == 1) curr_OP_ptr->op_code=WAIT; else curr_OP_ptr->op_code=ENTER; curr_OP_ptr->module_id=(char*) new char[(i=strlen(inp_MR_ptr->str_ptr->symbol_id))+2]; strcpy(curr_OP_ptr->module_id,inp_MR_ptr->str_ptr->symbol_id); curr_OP_ptr->input_list=OP_in_list; // Loop thru the output list of the "loop_module" loop_ptr=inp_MR_ptr->output_list; for(;loop_ptr != 0;loop_ptr=loop_ptr->next_io_ptr){ STR_ptr=this->get_STR_ptr(loop_ptr->name); // Check for SELECT operator select_stack_rec *SSR_ptr; if (SSR_ptr=top_SSR_ptr){ for(;SSR_ptr != 0; SSR_ptr=SSR_ptr->parent_ssr_ptr) this->update_parent(STR_ptr,SSR_ptr); } // Check if the current module needs possible updation int update_mo_output=0; // If signal or port or formal, update it if (STR_ptr->flags.is_signal==1 || STR_ptr->flags.is_port==1 || STR_ptr->flags.is_formal==1) update_mo_output=1; else { // Update the module's output if the storage concerned is not local IO_ptr=curr_MR_ptr->input_list; for(;IO_ptr != NULL; IO_ptr=IO_ptr->next_io_ptr) if (strcmp(IO_ptr->name,STR_ptr->name)==0) break; if (IO_ptr && IO_ptr->inout_id[0] == 'l') update_mo_output=0; else update_mo_output=1; } // If variable and current module is loop, update it if (curr_MR_ptr->str_ptr->flags.is_loop==1) update_mo_output=1; // Now check update_mo_output if (update_mo_output == 1){ IO_ptr=curr_MR_ptr->output_list; for(;IO_ptr != 0;IO_ptr=IO_ptr->next_io_ptr) if (strcmp(IO_ptr->name,loop_ptr->name)==0) break; if (IO_ptr == 0){ // new signal to be added to the output_list IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("o",MO_out_cnt++); IO_ptr->destn_id=(char*) new char[strlen(loop_ptr->destn_id)+1]; strcpy(IO_ptr->destn_id,loop_ptr->destn_id); IO_ptr->width=loop_ptr->width; IO_ptr->name=(char*) new char[strlen(loop_ptr->name)+1]; strcpy(IO_ptr->name,loop_ptr->name); if (tmp_IO_ptr=curr_MR_ptr->output_list){ for(;tmp_IO_ptr->next_io_ptr != 0;tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=IO_ptr; } else curr_MR_ptr->output_list=IO_ptr; } } // Now create an output for the ENTER operator and put it in the list IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",OP_out_cnt++); IO_ptr->destn_id=(char*) new char[strlen(loop_ptr->destn_id)+1]; strcpy(IO_ptr->destn_id,loop_ptr->destn_id); IO_ptr->width=loop_ptr->width; IO_ptr->name=(char*) new char[strlen(loop_ptr->name)+1]; strcpy(IO_ptr->name,loop_ptr->name); if (tmp_IO_ptr=curr_OP_ptr->output_list){ for(;tmp_IO_ptr->next_io_ptr != 0;tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=IO_ptr; } else curr_OP_ptr->output_list=IO_ptr; // Update carrier list tmp_CI_ptr=CI_ptr; for (;tmp_CI_ptr != 0;tmp_CI_ptr=tmp_CI_ptr->next_ci_ptr){ if (tmp_CI_ptr->str_ptr == STR_ptr){ // Is in the list delete tmp_CI_ptr->op_inp_id; tmp_CI_ptr->op_inp_id=(char*) new char[(i=strlen(curr_OP_ptr->op_id))+strlen(IO_ptr->inout_id)+1]; strcpy(tmp_CI_ptr->op_inp_id,curr_OP_ptr->op_id); tmp_CI_ptr->op_inp_id[i++]='.'; j=0; while((tmp_CI_ptr->op_inp_id[i++]=IO_ptr->inout_id[j++]) != '\0'); } } if (tmp_CI_ptr == 0){ // means that storage is not in carrier list tmp_CI_ptr=(carrier_info*) new carrier_info; tmp_CI_ptr->str_ptr=STR_ptr; tmp_CI_ptr->op_inp_id=(char*) new char[(i=strlen(curr_OP_ptr->op_id))+strlen(IO_ptr->inout_id)+1]; strcpy(tmp_CI_ptr->op_inp_id,curr_OP_ptr->op_id); tmp_CI_ptr->op_inp_id[i++]='.'; j=0; while((tmp_CI_ptr->op_inp_id[i++]=IO_ptr->inout_id[j++]) != '\0'); tmp_CI_ptr->next_ci_ptr=CI_ptr; CI_ptr=tmp_CI_ptr; } } // End of looping the "inp_module" output list // After you are done with all the outputs of the ENTER operator, set // the OP_out_cnt to 1 OP_out_cnt=1; #ifdef DEBUG cout << "Leaving : mk_ENTER()\n"; #endif VOID_RETURN; } void CLASS_NAME :: mk_conc_stmnt_module(char* name, int stmnt_type) { /************************************************************************ Sets up the envioronment to process a "concurrent" statement. The concurrent statements can be of the following types - (1) PROCESS statement, (2) CONC_SA (CONCurrent Signal Assignment) statement, (3) BLOCK statement. In doing so, it performs the following tasks - (1) Creates a new "module_rec" and a symbol table entry indicating the type of the concurrent statement. (2) Calls push() to push the parent context information in the stack. The push() updates the curr_OP_ptr properly. Globals used : global_STR_ptr ***********************************************************************/ #ifdef DEBUG cout << "Entered mk_conc_stmnt_module()\n"; #endif // Create the Symbol table entry and update it symbol_table_rec *STR_ptr=(symbol_table_rec*) new symbol_table_rec; STR_ptr->symbol_id=this->rename("m",STR_cnt++); STR_ptr->parent_id=(char*) new char[strlen(curr_MR_ptr->str_ptr->symbol_id)+1]; strcpy(STR_ptr->parent_id,curr_MR_ptr->str_ptr->symbol_id); switch (stmnt_type) { case PROCESS : STR_ptr->flags.is_process=1; break; case BLCK : STR_ptr->flags.is_block=1; break; case CONC_SA : STR_ptr->flags.is_conc_sa=1; break; } // End switch if (name){ // has a name STR_ptr->name=(char*) new char[strlen(name)+1]; strcpy(STR_ptr->name,name); delete name; } // Update the symbol table symbol_table_rec *tmp_STR_ptr=curr_MR_ptr->STR_list; if (tmp_STR_ptr){ for(;tmp_STR_ptr->next_str_ptr != NULL; tmp_STR_ptr=tmp_STR_ptr->next_str_ptr); tmp_STR_ptr->next_str_ptr=STR_ptr; } else curr_MR_ptr->STR_list=STR_ptr; // Create the module record and set the envioronment module_rec *MR_ptr=(module_rec*) new module_rec; MR_ptr->str_ptr=STR_ptr; // push the parent module this->push(MR_ptr); #ifdef DEBUG cout << "Leaving mk_conc_stmnt_module()\n"; #endif VOID_RETURN; } void CLASS_NAME :: mk_procedure_module(char* name) { /************************************************************************ Sets up the envioronment to process a procedure declaration statement. In doing so, it performs the following tasks - (1) Creates a new "module_rec" and a symbol table entry indicating the type of the concurrent statement. (2) Calls push() to push the parent context information in the stack. The push() updates the curr_OP_ptr properly. Globals used : global_STR_ptr ***********************************************************************/ #ifdef DEBUG cout << "Entered mk_procedure_module()\n"; #endif // Create the Symbol table entry and update it symbol_table_rec *STR_ptr=(symbol_table_rec*) new symbol_table_rec; STR_ptr->symbol_id=this->rename("m",STR_cnt++); if (curr_MR_ptr){ STR_ptr->parent_id=(char*) new char[strlen(curr_MR_ptr->str_ptr->symbol_id)+1]; strcpy(STR_ptr->parent_id,curr_MR_ptr->str_ptr->symbol_id); } STR_ptr->flags.is_subprogram=1; STR_ptr->name=(char*) new char[strlen(name)+1]; strcpy(STR_ptr->name,name); delete name; // Update the symbol table symbol_table_rec *tmp_STR_ptr; if (curr_MR_ptr){ tmp_STR_ptr=curr_MR_ptr->STR_list; if (tmp_STR_ptr){ for(;tmp_STR_ptr->next_str_ptr != NULL; tmp_STR_ptr=tmp_STR_ptr->next_str_ptr); tmp_STR_ptr->next_str_ptr=STR_ptr; } else curr_MR_ptr->STR_list=STR_ptr; } else { // put it in the global symbol table tmp_STR_ptr=global_STR_ptr; if (tmp_STR_ptr){ for(;tmp_STR_ptr->next_str_ptr != NULL; tmp_STR_ptr=tmp_STR_ptr->next_str_ptr); tmp_STR_ptr->next_str_ptr=STR_ptr; } else global_STR_ptr=STR_ptr; } // Create the module record and set the envioronment module_rec *MR_ptr=(module_rec*) new module_rec; MR_ptr->str_ptr=STR_ptr; // push the parent module this->push(MR_ptr); #ifdef DEBUG cout << "Leaving mk_procedure_module()\n"; #endif VOID_RETURN; } void CLASS_NAME :: free_id(id_rec *inp_ID_ptr) { // Frees space of the carrier list id_rec *tmp_ID_ptr=inp_ID_ptr; while (tmp_ID_ptr != 0){ inp_ID_ptr=tmp_ID_ptr->next_id_ptr; delete tmp_ID_ptr->id; delete tmp_ID_ptr; tmp_ID_ptr=inp_ID_ptr; } VOID_RETURN; } void CLASS_NAME :: free_ci(carrier_info *inp_CI_ptr) { // Frees space of carrier list carrier_info *tmp_CI_ptr=inp_CI_ptr; while (tmp_CI_ptr != 0){ inp_CI_ptr=tmp_CI_ptr->next_ci_ptr; delete tmp_CI_ptr->op_inp_id; delete tmp_CI_ptr; tmp_CI_ptr=inp_CI_ptr; } CI_ptr=NULL; VOID_RETURN; } symbol_table_rec* CLASS_NAME :: get_STR_ptr(char *name) { /************************************************************************ Gets a STR_ptr for the symbol identified by the input parameter "namr". B'cos the organization of storing the symbols has changed, This routine fetches starts looking for the symbol name in the curr_MR_ptr and goes up thru the parent information to look for the symbol identified by name. *************************************************************************/ symbol_table_rec *ret_ptr=NULL; if (curr_MR_ptr){ char *curr_mo_id=curr_MR_ptr->str_ptr->symbol_id; while(curr_mo_id){ // Till you have exhaused looking into all the modules // First get the module_rec module_rec *tmp_MR_ptr=global_MR_ptr; for(;tmp_MR_ptr != NULL;tmp_MR_ptr=tmp_MR_ptr->next_mr_ptr) if (strcmp(curr_mo_id,tmp_MR_ptr->str_ptr->symbol_id)==0) break; if (tmp_MR_ptr==NULL) break; // Now look into this module's symbol table ret_ptr=tmp_MR_ptr->STR_list; for(;ret_ptr != NULL; ret_ptr=ret_ptr->next_str_ptr) if (ret_ptr->name && strcmp(ret_ptr->name,name) == 0) break; if (ret_ptr) PTR_RETURN(ret_ptr); // If you are here, then look into the parent's symbol_table curr_mo_id=tmp_MR_ptr->str_ptr->parent_id; } // end while } // If ret_ptr is NULL, look in the global symbol table if (ret_ptr == NULL){ ret_ptr=global_STR_ptr; for(;ret_ptr != NULL;ret_ptr=ret_ptr->next_str_ptr) if (strcmp(ret_ptr->name,name)==0) break; } // Now return the ret_ptr PTR_RETURN(ret_ptr); } symbol_table_rec* CLASS_NAME :: get_op_inp_STR_ptr(char* op_inp_id) { /*************************************************************************** Gets the STR_ptr corresponding to the op_inp_id. The op_inp_id can reflect one of the following - (1) module - if op_inp_id[0] == 'a' or 'm' (2) operator output - if op_inp_id[0] == 'x' (3) constant - if op_inp_id[0] == '#' : we assume that it wouldn't be called for a constant inp. This routine is being called from the routine procedure_call() to get the STR of some actual that is to be written into. Under this circumstance, the actual has to correspond to some storage. If the op_inp_id refers to an operator that is used to read an alias, it returns the STR corresponding to that alias. ***************************************************************************/ symbol_table_rec *ret_ptr=NULL; inout *IO_ptr; int i,j; if (op_inp_id[0] == '#'){ // A constant Cout << "<> get_op_inp_STR() called for" << op_inp_id << "\n"; PTR_RETURN(ret_ptr); } if (op_inp_id[0]=='m' || op_inp_id[0]=='a'){ // A module input // Get the particular inout ptr of the module's input char *mo_inp_id=(char*) new char[strlen(op_inp_id)-1]; i=j=0; while(op_inp_id[i++] != '.'); while((mo_inp_id[j++]=op_inp_id[i++]) != '\0'); IO_ptr=curr_MR_ptr->input_list; for(;IO_ptr != NULL;IO_ptr=IO_ptr->next_io_ptr) if (strcmp(IO_ptr->inout_id,mo_inp_id)==0) break; ret_ptr=this->get_STR_ptr(IO_ptr->name); delete(mo_inp_id); PTR_RETURN(ret_ptr); } if (op_inp_id[0]=='x'){ // An operator // Get the op_id char *op_id=(char*) new char[strlen(op_inp_id)-1]; char *op_io_id=(char*) new char[strlen(op_inp_id)-1]; i=j=0; while((op_id[i++]=op_inp_id[j++]) != '.'); op_id[i-1]='\0';i=0; while((op_io_id[i++]=op_inp_id[j++]) != '\0'); // Now get the particular operator op_erator *OP_ptr=this->get_op_ptr(op_id,curr_MR_ptr->operator_list); // Now check the type of operator switch(OP_ptr->op_code){ // All Physical operators are to be neglected case AND : case OR : case NOT : case PLUS : case CONCAT : case MINUS : case MULT : case DIV : case GT : case LT : case EQ : case NAND : case NOR : case XOR : case XNOR : break; case RD : // A operator is used in two circumstances. (1) To read an // alias, and (2) to write the output of a physical operator into // a storage. For case (1) the operator would not be writing // into anything. In the second case, it would. If it is not // writing into anything, call yourself with the first parameter // to get the STR of the parent - and from that get the STR of // the alias. Otherwise, return the STR of the storage the // is writing into. IO_ptr=OP_ptr->output_list; if (IO_ptr->name) ret_ptr=this->get_STR_ptr(IO_ptr->name); else{ // Get the STR of the alias. To do this, get the STR of the // parent. Then go thru the symbol table and compare all // STRs that are aliases to see if it is an alias of the parent // that this operator refers to. For this to be true, the // information in the alias_info field of the STR is used. symbol_table_rec *par_STR_ptr; par_STR_ptr=this->get_op_inp_STR_ptr(OP_ptr->input_list->inp_id); input *IN_ptr=OP_ptr->input_list->next_in_ptr; char *start_index=(char*) new char[strlen(IN_ptr->inp_id)-1]; i=2;j=0; while((start_index[j++]=IN_ptr->inp_id[i++]) != '\0'); ret_ptr=par_STR_ptr; for(;ret_ptr != NULL; ret_ptr=ret_ptr->next_str_ptr) if (ret_ptr->flags.is_alias == 1 && ret_ptr->alias_info.alias_of == par_STR_ptr && strcmp(ret_ptr->alias_info.cr_ptr->constant_id, start_index) == 0){ int alias_width=((i=(ret_ptr->bit_struct.from-ret_ptr->bit_struct.to)) > 0 ?i+1:1-i); if (alias_width == OP_ptr->output_list->width) break; } } break; case PAD : case ARRRD : // If it is not writing into anything, call yorself with the first // parameter IO_ptr=OP_ptr->output_list; if (IO_ptr->name) ret_ptr=this->get_STR_ptr(IO_ptr->name); else ret_ptr=this->get_op_inp_STR_ptr(OP_ptr->input_list->inp_id); break; case WR : case ARRWR : case ENTER : case CALL : case SELECT : case DIVERGE : // Has to be writing into one of the outputs IO_ptr=OP_ptr->output_list; for(;IO_ptr != NULL;IO_ptr=IO_ptr->next_io_ptr) if (strcmp(IO_ptr->inout_id,op_io_id)==0) break; ret_ptr=this->get_STR_ptr(IO_ptr->name); break; case NO_OP : case LEAVE : break; } // end switch } // end if PTR_RETURN(ret_ptr); } void CLASS_NAME :: conc_stmnt(module_rec *inp_MR_ptr) { /*********************************************************************** This routine creates a ENTER operator for a process in the architecture In doing so, it performs the following - (1) Creates a branch record for the current DIVERGE operator and appends it to the branch-list of the DIVERGE operator. (2) It calls mk_par_ENTER() to create an ENTER operator equivalent of the process statement. ************************************************************************/ #ifdef DEBUG cout << "Entered : conc_stmnt()\n"; #endif char *id; int i, j; branch_rec *BR_ptr, *tmp_BR_ptr; // Step (1) BR_ptr=(branch_rec*) new branch_rec; if (tmp_BR_ptr=curr_OP_ptr->br_ptr){ // Append it for(;tmp_BR_ptr->next_br_ptr != 0;tmp_BR_ptr=tmp_BR_ptr->next_br_ptr); tmp_BR_ptr->next_br_ptr=BR_ptr; } else curr_OP_ptr->br_ptr=BR_ptr; id=this->rename("d",BR_cnt++); i=strlen(id); BR_ptr->branch_id=(char*) new char[strlen(curr_OP_ptr->op_id)+i+2]; strcpy(BR_ptr->branch_id,id); BR_ptr->branch_id[i++]='.'; j=0; while((BR_ptr->branch_id[i++]=curr_OP_ptr->op_id[j++]) != '\0'); // Step (2) BR_ptr->op_ptr=this->mk_par_ENTER(inp_MR_ptr); #ifdef DEBUG cout << "Leaving : conc_stmnt()\n"; #endif VOID_RETURN; } void CLASS_NAME :: mk_arch_module(char *arch_name,char *ent_name) { /************************************************************************ Takes as input the architecture name and the entity name. It creates a module record for the architecture. In doing so, it does the following - (1) Gets the entity STR_ptr. (2) Creates a symbol table entry for the architecture. (3) Creates the first module in the data_base and puts it as the top of the module list. Also set the curr_MR_ptr to it. (4) Creates a dummy operator for use by any initialization needed. ************************************************************************/ #ifdef DEBUG cout << "Entered : mk_arch_module()\n"; #endif symbol_table_rec *tmp_STR_ptr=global_STR_ptr; // Get entity STR_ptr symbol_table_rec *ent_STR_ptr=this->get_STR_ptr(ent_name); delete ent_name; // Create a symbol_table entry for the architecture symbol_table_rec *STR_ptr=(symbol_table_rec*) new symbol_table_rec; STR_ptr->symbol_id=this->rename("a",STR_cnt++); STR_ptr->parent_id=(char*) new char[strlen(ent_STR_ptr->symbol_id)+1]; strcpy(STR_ptr->parent_id,ent_STR_ptr->symbol_id); STR_ptr->name=(char*) new char[strlen(arch_name)+1]; strcpy(STR_ptr->name,arch_name); delete arch_name; // Add it to the symbol_table tmp_STR_ptr=global_STR_ptr; if (tmp_STR_ptr){ for(;tmp_STR_ptr->next_str_ptr != NULL; tmp_STR_ptr=tmp_STR_ptr->next_str_ptr); tmp_STR_ptr->next_str_ptr=STR_ptr; } else global_STR_ptr=STR_ptr; // Create the module rec for the architecture if (global_MR_ptr) { // Must be a procedure declaration in package module_rec *tmp_MR_ptr=global_MR_ptr; for(;tmp_MR_ptr->next_mr_ptr != NULL;tmp_MR_ptr=tmp_MR_ptr->next_mr_ptr); curr_MR_ptr=tmp_MR_ptr->next_mr_ptr=(module_rec*) new module_rec; curr_MR_ptr->str_ptr=STR_ptr; } else { global_MR_ptr=curr_MR_ptr=(module_rec*) new module_rec; curr_MR_ptr->str_ptr=STR_ptr; } // Create the dummy operator curr_OP_ptr=curr_MR_ptr->operator_list=(op_erator*) new op_erator; #ifdef DEBUG cout << "Leaving : mk_arch_module()\n"; #endif VOID_RETURN; } void CLASS_NAME :: cl_arch_module() { /*********************************************************************** Closes the architecture module. ***********************************************************************/ VOID_RETURN; } branch_val_rec* CLASS_NAME :: add_case_value(int value, branch_val_rec *BVR_ptr) { /************************************************************************** Creates a branch_value rec and adds it to the list. Returns the list. **************************************************************************/ branch_val_rec *new_BVR_ptr=(branch_val_rec*) new branch_val_rec; new_BVR_ptr->value=value; new_BVR_ptr->next_bvr_ptr=BVR_ptr; PTR_RETURN(new_BVR_ptr); } input* CLASS_NAME :: add_actual(input *IN1_ptr, input *IN2_ptr) { /************************************************************************* Gets one input_rec and another input list and makes one list and returns it *************************************************************************/ IN1_ptr->next_in_ptr=IN2_ptr; PTR_RETURN(IN1_ptr); } void CLASS_NAME :: update_carrier_info(symbol_table_rec *STR_ptr, char *inp_id) { /************************************************************************* Goes thru the Carrier Information list. If an carrier info record exists for the carrier represented by the inp_STR_ptr, it modifies that record. Otherwise, it creates a carrier info record and adds it to the list. *************************************************************************/ // Now update the carrier list for the lhs // Check to see if lhs is in the carrier list carrier_info *tmp_CI_ptr=CI_ptr; for (;tmp_CI_ptr != NULL;tmp_CI_ptr=tmp_CI_ptr->next_ci_ptr) if (tmp_CI_ptr->str_ptr == STR_ptr){ // Is in the list delete tmp_CI_ptr->op_inp_id; tmp_CI_ptr->op_inp_id=(char*) new char[strlen(inp_id)+1]; strcpy(tmp_CI_ptr->op_inp_id,inp_id); VOID_RETURN; } // end if // If you are still here, that means that lhs is not in carrier list tmp_CI_ptr=(carrier_info*) new carrier_info; tmp_CI_ptr->str_ptr=STR_ptr; tmp_CI_ptr->op_inp_id=(char*) new char[strlen(inp_id)+1]; strcpy(tmp_CI_ptr->op_inp_id,inp_id); tmp_CI_ptr->next_ci_ptr=CI_ptr; CI_ptr=tmp_CI_ptr; VOID_RETURN; } range_rec* CLASS_NAME :: mk_range_rec(int from, int to) { // Creates a range_rec from the two inputs - from and to int i; range_rec *RR_ptr=(range_rec*) new range_rec; RR_ptr->range=((i=(from - to)) > 0 ? i+1 : 1-i); RR_ptr->start_index=(from > to ? to : from); PTR_RETURN(RR_ptr); } input* CLASS_NAME :: range_spec(input *inp_IN_ptr, range_rec *inp_RR_ptr) { // Creates a RD operator if the inp_RR_ptr is not NULL if (inp_RR_ptr==NULL) PTR_RETURN(inp_IN_ptr); int i,j; // Create the 2nd input for the RD operator constant_rec *CR_ptr=this->add_constant(this->log2(inp_RR_ptr->range), inp_RR_ptr->start_index); input *inp2=(input*) new input; inp2->inp_id=(char*) new char[strlen(CR_ptr->constant_id)+3]; i=j=0; inp2->inp_id[i++]='#'; inp2->inp_id[i++]='.'; while((inp2->inp_id[i++]=CR_ptr->constant_id[j++]) != '\0'); inp_IN_ptr->next_in_ptr=inp2; // Output of the RD operator inout *IO_ptr=(inout*) new inout; IO_ptr->inout_id=this->rename("p",1); IO_ptr->width=inp_RR_ptr->range; // The RD operator curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=RD; curr_OP_ptr->input_list=inp_IN_ptr; curr_OP_ptr->output_list=IO_ptr; // Now for the return pointer input *ret_ptr=(input*) new input; ret_ptr->inp_id=(char*) new char[strlen(curr_OP_ptr->op_id)+4]; i=j=0; while((ret_ptr->inp_id[i++]=curr_OP_ptr->op_id[j++]) != '\0'); ret_ptr->inp_id[i-1]='.'; ret_ptr->inp_id[i++]='p'; ret_ptr->inp_id[i++]='1'; ret_ptr->inp_id[i++]='\0'; // Now for the next operator op_erator *OP_ptr=(op_erator*) new op_erator; curr_OP_ptr->next_op_ptr=OP_ptr; curr_OP_ptr=OP_ptr; PTR_RETURN(ret_ptr); } void CLASS_NAME :: initialize_storage(symbol_table_rec *STR_ptr, constant_rec *CR_list) { /*************************************************************************** Creates operators to perform the initializations. The code is generic - in terms of where to put the operators created to implement the initialization part. It works in the current_MTR_ptr's envioronment. It uses the curr_OP_ptr and creates the next one - and so on. Algo followed - (1) Determine the type of storage (SIGNAL/VARIABLE , ARRAY/BIT_VECTOR). (2) Call either simple_assignment() or array_assignment() with proper arguments to implement the initialization(s). Routines used - (1) simple_assignment(); (2) array_assignment(); (3) source_int(); -- initial INTEGER values (4) source_bit(); -- for initial BIT_VECTOR values and array indexing ***************************************************************************/ // First get a few information int st_type=(STR_ptr->flags.is_signal==1) ? SIGNAL : VARIABLE; int simple_or_array=(STR_ptr->flags.is_array==1) ? ARRAY : SIMPLE; char *st_name=(char*) new char[strlen(STR_ptr->name)+1]; strcpy(st_name,STR_ptr->name); input *rhs_ptr; // Now for the algo part if (simple_or_array==SIMPLE){ // X // Find out if the initial_value is an Integer or Bit_Vector if (CR_list->width > 0) // is a Bit_vector rhs_ptr=this->source_bit(CR_list->width,CR_list->value); else rhs_ptr=this->source_int(CR_list->value); // Now call simple_assignment() this->simple_assignment(st_type,st_name,rhs_ptr); } if (simple_or_array==ARRAY){ // We have to invoke array_assignment() for each element of the array // Find out the first and the last index of the array and do the // looping properly. Eg. // X[1:0]<1:0> := ("11","00"); => (1) array_assignment( ,X,1,"11"); // (2) array_assignment( ,X,0,"00"); int offset,arr_width,index_width,min_index; int arr_index=STR_ptr->word_struct.from; if (STR_ptr->word_struct.from < STR_ptr->word_struct.to){ offset= 1; arr_width=STR_ptr->word_struct.to - STR_ptr->word_struct.from + 1; min_index=STR_ptr->word_struct.from; } else { offset= -1; arr_width=STR_ptr->word_struct.from - STR_ptr->word_struct.to + 1; min_index=STR_ptr->word_struct.to; } // Find width of the arr_index index_width=this->log2(arr_width); // Now loop thru the CR_list and invoke array_assignment for each element constant_rec *CR_ptr=CR_list; for(;CR_ptr != NULL;CR_ptr=CR_ptr->next_cr_ptr){ // Create the index input *index_ptr=this->source_bit(index_width,arr_index-min_index); // Create the rhs_ptr if (CR_list->width > 0) // is a Bit_vector rhs_ptr=this->source_bit(CR_ptr->width,CR_ptr->value); else rhs_ptr=this->source_int(CR_ptr->value); // Now call array_assignment() this->array_assignment(st_type,st_name,index_ptr,rhs_ptr); // Recopy array name - b'cos array_asignment deletes it st_name=(char*) new char[strlen(STR_ptr->name)+1]; strcpy(st_name,STR_ptr->name); // Set the arr_index arr_index += offset; } // end for } // end if // delete(st_name); VOID_RETURN; } void CLASS_NAME :: st_arch_stmnt_part() { // Creates the DIVERGE operator using the curr_OP_ptr curr_OP_ptr->op_id=this->rename("x",OP_cnt++); curr_OP_ptr->op_code=DIVERGE; VOID_RETURN; } constant_rec* CLASS_NAME :: append_cr(constant_rec *CR_ptr, constant_rec *CR_list) { // Gets a pointer and a list. Appends the list at the end of the 1st record CR_ptr->next_cr_ptr=CR_list; PTR_RETURN(CR_ptr); } void CLASS_NAME :: procedure_call(module_rec *inp_MR_ptr,input *IN_list) { /************************************************************************* This routine processes a procedure call. The two input parameters are (1) the module record pointer that implements the procedure (2) a input list indicating the actuals for the procedure call. Algorithm - (1) Create a CALL operator. (2) Go into the procedure module and get all non-formal inputs. Use source_id() to create a list of all non-formals inputs for this procedure call/ Store it somewhere. (3) Go thru the IN_list. (4) For each actual, check the corresponding formal's mode. (5) If mode is IN/INOUT, add the input rec to the input list of the CALL OP. (6) If mode is INOUT/OUT, add a dummy output rec for the CALL operator. (7) If the input refers to an ARRRD operator then make a copy of the index_ptr. If mode is OUT delete the operator. (8) If the input refers to an RD operator and mode is OUT delete operator. (9) Use array_assignment() or simple_assignment() to copy output formal into the actual. (10) Go thru the output list of the procedure module and update the output list of the CALL operator - and the carrier info as needed. (11) Append the list that you created in step (2) to the CALL operator's input list. ***************************************************************************/ #ifdef DEBUG Cout << "Entered vhdl_par :: procedure_call()\n"; #endif input *tmp_IN_ptr; input *non_formal_IN_list=NULL; input *IN_ptr; inout *tmp_IO_ptr; op_erator *tmp_OP_ptr; inout *IO_ptr; int i,j,width; module_rec *parent_MR_ptr; OP_out_cnt=1; // Create the CALL operator - Step(1) op_erator *CALL_OP_ptr=curr_OP_ptr; CALL_OP_ptr->op_code=CALL; CALL_OP_ptr->op_id=rename("x",OP_cnt++); CALL_OP_ptr->module_id=(char*) new char[strlen(inp_MR_ptr->str_ptr->symbol_id)+1]; strcpy(CALL_OP_ptr->module_id,inp_MR_ptr->str_ptr->symbol_id); // Create the next dummy operator curr_OP_ptr=CALL_OP_ptr->next_op_ptr=(op_erator*) new op_erator; // Now for other inputs of the procedure (if any) - Step(2) IO_ptr=inp_MR_ptr->input_list; for(;IO_ptr != NULL;IO_ptr=IO_ptr->next_io_ptr){ if (IO_ptr->inout_id[0] == 'i'){ IN_ptr=this->source_id(IO_ptr->name); if (tmp_IN_ptr=non_formal_IN_list){ for(;tmp_IN_ptr->next_in_ptr != 0;tmp_IN_ptr=tmp_IN_ptr->next_in_ptr); tmp_IN_ptr->next_in_ptr=IN_ptr; } else non_formal_IN_list=IN_ptr; } } // end for // STR_ptr for the first formal symbol_table_rec *formal_STR_ptr=inp_MR_ptr->STR_list; // Go thru the IN_list - Steps (3) to (9) IN_ptr=IN_list; for(;IN_ptr != NULL;IN_ptr=IN_ptr->next_in_ptr){ // If the mode is IN or INOUT add this to the CALL operator's input // list - Step (5) if (formal_STR_ptr->mode==IN || formal_STR_ptr->mode==INOUT){ input *CALL_IN_ptr=(input*) new input; CALL_IN_ptr->inp_id=(char*) new char[strlen(IN_ptr->inp_id)+1]; strcpy(CALL_IN_ptr->inp_id,IN_ptr->inp_id); // Add it in the CALL operator input list if (tmp_IN_ptr=CALL_OP_ptr->input_list){ for(;tmp_IN_ptr->next_in_ptr != 0;tmp_IN_ptr=tmp_IN_ptr->next_in_ptr); tmp_IN_ptr->next_in_ptr=CALL_IN_ptr; } else CALL_OP_ptr->input_list=CALL_IN_ptr; } // end if // If the mode is INOUT or OUT create a output for the CALL op - Step(6) if (formal_STR_ptr->mode==INOUT || formal_STR_ptr->mode==OUT){ // Create the output for the CALL operator IO_ptr=(inout*) new inout; IO_ptr->inout_id=rename("p",OP_out_cnt++); width=((i=(formal_STR_ptr->bit_struct.from - formal_STR_ptr->bit_struct.to)) > 0 ?i+1:1-i); IO_ptr->width=width; // Now insert it if (tmp_IO_ptr=CALL_OP_ptr->output_list){ for(;tmp_IO_ptr->next_io_ptr != 0;tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=IO_ptr; } else CALL_OP_ptr->output_list=IO_ptr; } // end if // Now do further processing if the formal's mode is INOUT | OUT if (formal_STR_ptr->mode==INOUT || formal_STR_ptr->mode==OUT){ // Create the rhs pointer input *rhs_ptr=(input*) new input; i=strlen(IO_ptr->inout_id) + strlen(CALL_OP_ptr->op_id) + 2; rhs_ptr->inp_id=(char*) new char[i]; i=j=0; while((rhs_ptr->inp_id[i++]=CALL_OP_ptr->op_id[j++]) != '\0'); rhs_ptr->inp_id[i-1]='.'; j=0; while((rhs_ptr->inp_id[i++]=IO_ptr->inout_id[j++]) != '\0'); // STR of the actual symbol_table_rec *actual_STR_ptr =this->get_op_inp_STR_ptr(IN_ptr->inp_id); // Some useful information and declarations int rtn_type=SIMPLE; int st_type; if (actual_STR_ptr->flags.is_signal==1 || actual_STR_ptr->flags.is_port==1) st_type=SIGNAL; else st_type=VARIABLE; input *index_ptr=NULL; char *st_name=(char*) new char[strlen(actual_STR_ptr->name)+1]; strcpy(st_name,actual_STR_ptr->name); // Now see if the parent was an operator if (IN_ptr->inp_id[0]=='x'){ // get the operator pointer of the parent char *op_id=(char*) new char[strlen(IN_ptr->inp_id)-1]; i=0; while((op_id[i]=IN_ptr->inp_id[i++]) != '.'); op_id[i-1]='\0'; op_erator *OP_ptr=this->get_op_ptr(op_id, curr_MR_ptr->operator_list); // If operator was ARRRD | RD, need to do some processing if (OP_ptr->op_code==ARRRD || OP_ptr->op_code==RD){ // If the mode is OUT delete the operator if (formal_STR_ptr->mode==OUT) OP_ptr->op_code=NO_OP; // If the op is ARRRD, make a copy of it's index_ptr (input 2) if (OP_ptr->op_code==ARRRD){ index_ptr=(input*) new input; index_ptr->inp_id=(char*) new char[strlen(OP_ptr->input_list->next_in_ptr->inp_id)+1]; strcpy(index_ptr->inp_id,OP_ptr->input_list->next_in_ptr->inp_id); // Set the rtn_type rtn_type=ARRAY; } } // end if op_code == ARRRD || RD } // end if input is coming from an operator // Now we have all the info to invoke either simple/array_assignment if (rtn_type==SIMPLE) this->simple_assignment(st_type,st_name,rhs_ptr); else this->array_assignment(st_type,st_name,index_ptr,rhs_ptr); // If input is a module's input } // end if mode == INOUT || OUT - additional processing // update formal_STR_ptr for the next formal formal_STR_ptr=formal_STR_ptr->next_str_ptr; } // end for // Now for the other outputs of the procedure module IO_ptr=inp_MR_ptr->output_list; for(;IO_ptr != NULL;IO_ptr=IO_ptr->next_io_ptr){ // save the parent envioronment parent_MR_ptr=curr_MR_ptr; curr_MR_ptr=inp_MR_ptr; // Get the equivalent STR of the procedure module's output symbol_table_rec *proc_out_STR_ptr=this->get_STR_ptr(IO_ptr->name); // Restore parent's envioronment curr_MR_ptr=parent_MR_ptr; // If not a formal if (proc_out_STR_ptr->flags.is_formal==0){ // Create an output for the CALL operator tmp_IO_ptr=(inout*) new inout; tmp_IO_ptr->inout_id=this->rename("p",OP_out_cnt++); tmp_IO_ptr->destn_id=(char*) new char[strlen(IO_ptr->destn_id)+1]; strcpy(tmp_IO_ptr->destn_id,IO_ptr->destn_id); tmp_IO_ptr->name=(char*) new char[strlen(IO_ptr->name)+1]; strcpy(tmp_IO_ptr->name,IO_ptr->name); tmp_IO_ptr->width=IO_ptr->width; // Insert it inout *loop_IO_ptr=CALL_OP_ptr->output_list; if (loop_IO_ptr){ for(;loop_IO_ptr->next_io_ptr!=0;loop_IO_ptr=loop_IO_ptr->next_io_ptr); loop_IO_ptr->next_io_ptr=tmp_IO_ptr; } else CALL_OP_ptr->output_list=tmp_IO_ptr; // Update the Carrier info carrier_info *tmp_CI_ptr=CI_ptr; for (;tmp_CI_ptr != NULL;tmp_CI_ptr=tmp_CI_ptr->next_ci_ptr){ if (tmp_CI_ptr->str_ptr == proc_out_STR_ptr){ // Is in the list delete tmp_CI_ptr->op_inp_id; i=strlen(CALL_OP_ptr->op_id); width = i + strlen(tmp_IO_ptr->inout_id) + 2; tmp_CI_ptr->op_inp_id=(char*) new char[width]; strcpy(tmp_CI_ptr->op_inp_id,CALL_OP_ptr->op_id); j=0; tmp_CI_ptr->op_inp_id[i++]='.'; while((tmp_CI_ptr->op_inp_id[i++]=tmp_IO_ptr->inout_id[j++])!='\0'); break; } // end if } // end for if (tmp_CI_ptr == NULL){ // Has to be added to the list tmp_CI_ptr=(carrier_info*) new carrier_info; tmp_CI_ptr->str_ptr=proc_out_STR_ptr; i=strlen(CALL_OP_ptr->op_id); width = i + strlen(tmp_IO_ptr->inout_id) + 2; tmp_CI_ptr->op_inp_id=(char*) new char[width]; strcpy(tmp_CI_ptr->op_inp_id,CALL_OP_ptr->op_id); j=0; tmp_CI_ptr->op_inp_id[i++]='.'; while((tmp_CI_ptr->op_inp_id[i++]=tmp_IO_ptr->inout_id[j++])!='\0'); // Insert it tmp_CI_ptr->next_ci_ptr=CI_ptr; CI_ptr=tmp_CI_ptr; } // end if // Check for SELECT operator select_stack_rec *SSR_ptr; if (SSR_ptr=top_SSR_ptr){ for(;SSR_ptr != 0; SSR_ptr=SSR_ptr->parent_ssr_ptr) this->update_parent(proc_out_STR_ptr,SSR_ptr); } // Check if the current module needs possible updation int update_mo_output=0; // If signal or port or formal, update it if (proc_out_STR_ptr->flags.is_signal==1 || proc_out_STR_ptr->flags.is_port==1 || proc_out_STR_ptr->flags.is_formal==1) update_mo_output=1; else { // Update the module's output if the storage concerned is not local loop_IO_ptr=curr_MR_ptr->input_list; for(;loop_IO_ptr != NULL; loop_IO_ptr=loop_IO_ptr->next_io_ptr) if (strcmp(IO_ptr->name,loop_IO_ptr->name)==0) break; if (loop_IO_ptr && loop_IO_ptr->inout_id[0] == 'l') update_mo_output=0; else update_mo_output=1; } // If variable and current module is loop, update it if (curr_MR_ptr->str_ptr->flags.is_loop==1) update_mo_output=1; // Now check update_mo_output if (update_mo_output == 1){ loop_IO_ptr=curr_MR_ptr->output_list; for(;loop_IO_ptr != 0;loop_IO_ptr=loop_IO_ptr->next_io_ptr) if (strcmp(loop_IO_ptr->name,IO_ptr->name)==0) break; if (loop_IO_ptr == NULL){ // new signal to be added loop_IO_ptr=(inout*) new inout; loop_IO_ptr->inout_id=this->rename("o",MO_out_cnt++); loop_IO_ptr->destn_id=(char*) new char[strlen(IO_ptr->destn_id)+1]; strcpy(loop_IO_ptr->destn_id,IO_ptr->destn_id); loop_IO_ptr->width=IO_ptr->width; loop_IO_ptr->name=(char*) new char[strlen(IO_ptr->name)+1]; strcpy(loop_IO_ptr->name,IO_ptr->name); if (tmp_IO_ptr=curr_MR_ptr->output_list){ for(;tmp_IO_ptr->next_io_ptr != NULL; tmp_IO_ptr=tmp_IO_ptr->next_io_ptr); tmp_IO_ptr->next_io_ptr=loop_IO_ptr; } else curr_MR_ptr->output_list=loop_IO_ptr; } // end if loop_IO_ptr == NULL } // end if update_mo_output == 1 } // end if not formal } // end for all outputs of procedure module // Now add the non_formal_IN_list at the end of the CALL op's input list if (tmp_IN_ptr=CALL_OP_ptr->input_list){ for(;tmp_IN_ptr->next_in_ptr != NULL;tmp_IN_ptr=tmp_IN_ptr->next_in_ptr); tmp_IN_ptr->next_in_ptr=non_formal_IN_list; } else CALL_OP_ptr->input_list=non_formal_IN_list; // Reset the OP_out_cnt OP_out_cnt=1; #ifdef DEBUG Cout << "Leaving vhdl_par :: procedure_call()\n"; #endif VOID_RETURN; }