diff --git a/elab_scope.cc b/elab_scope.cc index 984a93af9..da9030141 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -152,6 +152,21 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, verinum cur_value (0); verinum one_value (1); size_t name_idx = 0; + // Find the minimum and maximum allowed enumeration values. + verinum min_value (0); + verinum max_value (0); + if (enum_type->signed_flag) { + min_value = v_not((pow(verinum(2), + verinum(use_enum->base_width()-1)))) + + one_value; + max_value = pow(verinum(2), verinum(use_enum->base_width()-1)) - + one_value; + } else { + max_value = pow(verinum(2), verinum(use_enum->base_width())) - + one_value; + } + min_value.has_sign(true); + max_value.has_sign(enum_type->signed_flag); for (list::const_iterator cur = enum_type->names->begin() ; cur != enum_type->names->end() ; ++ cur, name_idx += 1) { @@ -159,38 +174,60 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, if (cur->parm) { // There is an explicit value. elaborate/evaluate // the value and assign it to the enumeration name. - NetExpr*val = elab_and_eval(des, scope, cur->parm, - use_enum->base_width()); + NetExpr*val = elab_and_eval(des, scope, cur->parm, -1); NetEConst*val_const = dynamic_cast (val); if (val_const == 0) { - cerr << "<>:0: error: Enumeration expression is not constant." << endl; + cerr << "<>:0: error: Enumeration expression is not " + "constant." << endl; des->errors += 1; continue; } cur_value = val_const->value(); - if (enum_type->base_type==IVL_VT_BOOL && ! cur_value.is_defined()) { + if (enum_type->base_type==IVL_VT_BOOL && + ! cur_value.is_defined()) { cerr << "<>:0: error: Enumeration name " << cur->name - << " cannot have a logic value." << endl; + << " cannot have an undefined value." << endl; des->errors += 1; + continue; } } else if (! cur_value.is_defined()) { cerr << "<>:0: error: Enumeration name " << cur->name - << " cannot have an inferred value." << endl; + << " cannot have an undefined inferred value." << endl; des->errors += 1; continue; } + // The enumeration value must fit into the enumeration bits. + if ((cur_value > max_value) || + (cur_value.has_sign() && (cur_value < min_value))) { + cerr << "<>:0: error: Enumeration name " << cur->name + << " cannot have a value equal to " << cur_value + << "." << endl; + des->errors += 1; + } + // The values are explicitly sized to the width of the // base type of the enumeration. - verinum tmp_val (cur_value, use_enum->base_width()); + verinum tmp_val (0); + if (cur_value.len() < use_enum->base_width()) { + // Pad the current value if it is narrower than the final + // width of the enum. + tmp_val = pad_to_width (cur_value, use_enum->base_width()); + tmp_val.has_len(true); + } else { + // Truncate an oversized value. We report out of bound + // values above. This may create duplicates. + tmp_val = verinum(cur_value, use_enum->base_width()); + } tmp_val.has_sign(enum_type->signed_flag); rc_flag = use_enum->insert_name(name_idx, cur->name, tmp_val); rc_flag &= scope->add_enumeration_name(use_enum, cur->name); if (! rc_flag) { - cerr << "<>:0: error: Duplicate enumeration name " << cur->name << endl; + cerr << "<>:0: error: Duplicate enumeration name " + << cur->name << endl; des->errors += 1; } diff --git a/lexor.lex b/lexor.lex index ce3916746..d4788e9da 100644 --- a/lexor.lex +++ b/lexor.lex @@ -145,6 +145,20 @@ TU [munpf] "<=" { return K_LE; } ">=" { return K_GE; } "=>" { return K_EG; } +"+=>"|"-=>" { + /* + * Resolve the ambiguity between the += assignment + * operator and +=> polarity edge path operator + * + * +=> should be treated as two separate tokens '+' and + * '=>' (K_EG), therefore we only consume the first + * character of the matched pattern i.e. either + or - + * and push back the rest of the matches text (=>) in + * the input stream. + */ + yyless(1); + return yytext[0]; + } "*>" { return K_SG; } "==" { return K_EQ; } "!=" { return K_NE; } @@ -161,6 +175,19 @@ TU [munpf] "+:" { return K_PO_POS; } "-:" { return K_PO_NEG; } "<+" { return K_CONTRIBUTE; } +"+=" { return K_PLUS_EQ; } +"-=" { return K_MINUS_EQ; } +"*=" { return K_MUL_EQ; } +"/=" { return K_DIV_EQ; } +"%=" { return K_MOD_EQ; } +"&=" { return K_AND_EQ; } +"|=" { return K_OR_EQ; } +"^=" { return K_XOR_EQ; } +"<<=" { return K_LS_EQ; } +">>=" { return K_RS_EQ; } +"<<<=" { return K_LS_EQ; } +">>>=" { return K_RSS_EQ; } + /* Watch out for the tricky case of (*). Cannot parse this as "(*" and ")", but since I know that this is really ( * ), replace it diff --git a/netmisc.cc b/netmisc.cc index 6bb216e85..3a544f681 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -184,7 +184,15 @@ NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src) NetExpr* cast_to_int2(NetExpr*expr) { - NetECast*cast = new NetECast('2', expr, expr->expr_width(), + // Special case: The expression is alreadt BOOL + if (expr->expr_type() == IVL_VT_BOOL) + return expr; + + unsigned use_width = expr->expr_width(); + if (expr->expr_type() == IVL_VT_REAL) + use_width = 64; + + NetECast*cast = new NetECast('2', expr, use_width, expr->has_sign()); cast->set_line(*expr); return cast; diff --git a/parse.y b/parse.y index 2f66e6075..dcae0f02a 100644 --- a/parse.y +++ b/parse.y @@ -197,14 +197,26 @@ static list* make_named_numbers(perm_string name, long first, lon { list*lst = new list; named_pexpr_t tmp; - assert(first <= last); - for (long idx = first ; idx <= last ; idx += 1) { - ostringstream buf; - buf << name.str() << idx << ends; - tmp.name = lex_strings.make(buf.str()); - tmp.parm = val; - val = 0; - lst->push_back(tmp); + // We are counting up. + if (first <= last) { + for (long idx = first ; idx <= last ; idx += 1) { + ostringstream buf; + buf << name.str() << idx << ends; + tmp.name = lex_strings.make(buf.str()); + tmp.parm = val; + val = 0; + lst->push_back(tmp); + } + // We are counting down. + } else { + for (long idx = first ; idx >= last ; idx -= 1) { + ostringstream buf; + buf << name.str() << idx << ends; + tmp.name = lex_strings.make(buf.str()); + tmp.parm = val; + val = 0; + lst->push_back(tmp); + } } return lst; } @@ -219,6 +231,28 @@ static list* make_named_number(perm_string name, PExpr*val =0) return lst; } +static long check_enum_seq_value(const YYLTYPE&loc, verinum *arg, bool zero_ok) +{ + long value = 1; + // We can never have an undefined value in an enumeration name + // declaration sequence. + if (! arg->is_defined()) { + yyerror(loc, "error: undefined value used in enum name sequence."); + // We can never have a negative value in an enumeration name + // declaration sequence. + } else if (arg->is_negative()) { + yyerror(loc, "error: negative value used in enum name sequence."); + } else { + value = arg->as_ulong(); + // We cannot have a zero enumeration name declaration count. + if (! zero_ok && (value == 0)) { + yyerror(loc, "error: zero count used in enum name sequence."); + value = 1; + } + } + return value; +} + %} %union { @@ -296,6 +330,7 @@ static list* make_named_number(perm_string name, PExpr*val =0) %token PATHPULSE_IDENTIFIER %token BASED_NUMBER DEC_NUMBER %token REALTIME +%token K_PLUS_EQ K_MINUS_EQ %token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LS K_RS K_RSS K_SG /* K_CONTRIBUTE is <+, the contribution assign. */ %token K_CONTRIBUTE @@ -387,7 +422,7 @@ static list* make_named_number(perm_string name, PExpr*val =0) %token K_zi_nd K_zi_np K_zi_zd K_zi_zp %type from_exclude -%type number +%type number pos_neg_number %type unsigned_signed_opt signed_unsigned_opt reg_opt %type udp_reg_opt edge_operator automatic_opt %type drive_strength drive_strength_opt dr_strength0 dr_strength1 @@ -455,7 +490,7 @@ static list* make_named_number(perm_string name, PExpr*val =0) %type event_expression_list %type event_expression %type event_control -%type statement statement_or_null +%type statement statement_or_null compressed_statement %type statement_list %type analog_statement @@ -469,6 +504,8 @@ static list* make_named_number(perm_string name, PExpr*val =0) %type atom2_type %token K_TAND +%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ +%right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ %right '?' ':' %left K_LOR %left K_LAND @@ -774,22 +811,34 @@ enum_name_list } ; +pos_neg_number + : number + { $$ = $1; + } + | '-' number + { verinum tmp = v_not(*($2)) + verinum(1); + *($2) = tmp; + $$ = $2; + } + ; + enum_name : IDENTIFIER { perm_string name = lex_strings.make($1); delete[]$1; $$ = make_named_number(name); } - | IDENTIFIER '[' DEC_NUMBER ']' + | IDENTIFIER '[' pos_neg_number ']' { perm_string name = lex_strings.make($1); - long count = $3->as_ulong(); + long count = check_enum_seq_value(@1, $3, false); delete[]$1; $$ = make_named_numbers(name, 0, count-1); delete $3; } - | IDENTIFIER '[' DEC_NUMBER ':' DEC_NUMBER ']' + | IDENTIFIER '[' pos_neg_number ':' pos_neg_number ']' { perm_string name = lex_strings.make($1); - $$ = make_named_numbers(name, $3->as_long(), $5->as_long()); + $$ = make_named_numbers(name, check_enum_seq_value(@1, $3, true), + check_enum_seq_value(@1, $5, true)); delete[]$1; delete $3; delete $5; @@ -799,16 +848,17 @@ enum_name delete[]$1; $$ = make_named_number(name, $3); } - | IDENTIFIER '[' DEC_NUMBER ']' '=' expression + | IDENTIFIER '[' pos_neg_number ']' '=' expression { perm_string name = lex_strings.make($1); - long count = $3->as_ulong(); + long count = check_enum_seq_value(@1, $3, false); $$ = make_named_numbers(name, 0, count-1, $6); delete[]$1; delete $3; } - | IDENTIFIER '[' DEC_NUMBER ':' DEC_NUMBER ']' '=' expression + | IDENTIFIER '[' pos_neg_number ':' pos_neg_number ']' '=' expression { perm_string name = lex_strings.make($1); - $$ = make_named_numbers(name, $3->as_long(), $5->as_long(), $8); + $$ = make_named_numbers(name, check_enum_seq_value(@1, $3, true), + check_enum_seq_value(@1, $5, true), $8); delete[]$1; delete $3; delete $5; @@ -976,21 +1026,21 @@ delay_value_simple delete[]$1; } | TIME_LITERAL - { - int unit; + { int unit; - based_size = 0; - $$ = 0; - if ($1 == 0 || !get_time_unit($1, unit)) - yyerror(@1, "internal error: delay."); - else { - double p = pow(10, unit - pform_get_timeunit()); - double time = atof($1) * p; + based_size = 0; + $$ = 0; + if ($1 == 0 || !get_time_unit($1, unit)) + yyerror(@1, "internal error: delay."); + else { + double p = pow(10.0, + (double)(unit - pform_get_timeunit())); + double time = atof($1) * p; - verireal *v = new verireal(time); - $$ = new PEFNumber(v); - FILE_NAME($$, @1); - } + verireal *v = new verireal(time); + $$ = new PEFNumber(v); + FILE_NAME($$, @1); + } } ; @@ -4278,6 +4328,8 @@ statement { $$ = 0; yyerror(@1, "error: Error in while loop condition."); } + | compressed_statement ';' + { $$ = $1; } | delay1 statement_or_null { PExpr*del = $1->front(); assert($1->size() == 1); @@ -4421,6 +4473,86 @@ statement } ; +compressed_statement + : lpvalue K_PLUS_EQ expression + { + PEBinary *t = new PEBinary('+', $1, $3); + PAssign *tmp = new PAssign($1, t); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | lpvalue K_MINUS_EQ expression + { + PEBinary *t = new PEBinary('-', $1, $3); + PAssign *tmp = new PAssign($1, t); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | lpvalue K_MUL_EQ expression + { + PEBinary *t = new PEBinary('*', $1, $3); + PAssign *tmp = new PAssign($1, t); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | lpvalue K_DIV_EQ expression + { + PEBinary *t = new PEBinary('/', $1, $3); + PAssign *tmp = new PAssign($1, t); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | lpvalue K_MOD_EQ expression + { + PEBinary *t = new PEBinary('%', $1, $3); + PAssign *tmp = new PAssign($1, t); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | lpvalue K_AND_EQ expression + { + PEBinary *t = new PEBinary('&', $1, $3); + PAssign *tmp = new PAssign($1, t); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | lpvalue K_OR_EQ expression + { + PEBinary *t = new PEBinary('|', $1, $3); + PAssign *tmp = new PAssign($1, t); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | lpvalue K_XOR_EQ expression + { + PEBinary *t = new PEBinary('^', $1, $3); + PAssign *tmp = new PAssign($1, t); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | lpvalue K_LS_EQ expression + { + PEBShift *t = new PEBShift('l', $1, $3); + PAssign *tmp = new PAssign($1, t); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | lpvalue K_RS_EQ expression + { + PEBShift *t = new PEBShift('r', $1, $3); + PAssign *tmp = new PAssign($1, t); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | lpvalue K_RSS_EQ expression + { + PEBShift *t = new PEBShift('R', $1, $3); + PAssign *tmp = new PAssign($1, t); + FILE_NAME(tmp, @1); + $$ = tmp; + } + ; + statement_list : statement_list statement { svector*tmp = new svector(*$1, $2); diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index 9196e757a..388a56275 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -1542,3 +1542,128 @@ void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig) assert(0); } + +static void dump_drive(ivl_drive_t drive) +{ + switch (drive) { + case IVL_DR_HiZ: fprintf(stderr, "highz"); break; + case IVL_DR_SMALL: fprintf(stderr, "small"); break; + case IVL_DR_MEDIUM: fprintf(stderr, "medium"); break; + case IVL_DR_WEAK: fprintf(stderr, "weak"); break; + case IVL_DR_LARGE: fprintf(stderr, "large"); break; + case IVL_DR_PULL: fprintf(stderr, "pull"); break; + case IVL_DR_STRONG: fprintf(stderr, "strong"); break; + case IVL_DR_SUPPLY: fprintf(stderr, "supply"); break; + } +} + +/* + * Routine to dump the nexus information. + */ +void dump_nexus_information(ivl_scope_t scope, ivl_nexus_t nex) +{ + unsigned idx, count = ivl_nexus_ptrs(nex); + fprintf(stderr, "Dumping nexus from scope: %s\n", + ivl_scope_name(scope)); + for (idx = 0; idx < count; idx += 1) { + ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx); + ivl_lpm_t lpm = ivl_nexus_ptr_lpm(nex_ptr); + ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr); + ivl_net_logic_t net_logic = ivl_nexus_ptr_log(nex_ptr); + ivl_signal_t sig = ivl_nexus_ptr_sig(nex_ptr); + fprintf(stderr, " %u (", idx); + dump_drive(ivl_nexus_ptr_drive1(nex_ptr)); + fprintf(stderr, "1 ,"); + dump_drive(ivl_nexus_ptr_drive0(nex_ptr)); + fprintf(stderr, "0) "); + if (lpm) { + ivl_scope_t lpm_scope = ivl_lpm_scope(lpm); + assert(! net_const); + assert(! net_logic); + assert(! sig); + fprintf(stderr, "LPM: "); + fprintf(stderr, "%s:%d ", ivl_lpm_file(lpm), + ivl_lpm_lineno(lpm)); + if (scope != lpm_scope) fprintf(stderr, "%s ", + ivl_scope_name(lpm_scope)); + switch (ivl_lpm_type(lpm)) { + case IVL_LPM_ABS: fprintf(stderr, "abs"); break; + case IVL_LPM_ADD: fprintf(stderr, "add"); break; + case IVL_LPM_ARRAY: fprintf(stderr, "array"); break; + case IVL_LPM_CAST_INT: fprintf(stderr, ""); break; + case IVL_LPM_CAST_INT2: fprintf(stderr, ""); break; + case IVL_LPM_CAST_REAL: fprintf(stderr, ""); break; + case IVL_LPM_CONCAT: fprintf(stderr, "concat"); break; + case IVL_LPM_CMP_EEQ: fprintf(stderr, "eeq"); break; + case IVL_LPM_CMP_EQ: fprintf(stderr, "eq"); break; + case IVL_LPM_CMP_GE: fprintf(stderr, "ge"); break; + case IVL_LPM_CMP_GT: fprintf(stderr, "gt"); break; + case IVL_LPM_CMP_NE: fprintf(stderr, "ne"); break; + case IVL_LPM_CMP_NEE: fprintf(stderr, "nee"); break; + case IVL_LPM_DIVIDE: fprintf(stderr, "divide"); break; + case IVL_LPM_FF: fprintf(stderr, "dff"); break; + case IVL_LPM_MOD: fprintf(stderr, "mod"); break; + case IVL_LPM_MULT: fprintf(stderr, "mult"); break; + case IVL_LPM_MUX: fprintf(stderr, "mux"); break; + case IVL_LPM_PART_VP: fprintf(stderr, "part-VP"); break; + case IVL_LPM_PART_PV: fprintf(stderr, "part-PV"); break; + case IVL_LPM_POW: fprintf(stderr, "pow"); break; + case IVL_LPM_RE_AND: fprintf(stderr, "R-AND"); break; + case IVL_LPM_RE_NAND: fprintf(stderr, "R-NAND"); break; + case IVL_LPM_RE_OR: fprintf(stderr, "R-OR"); break; + case IVL_LPM_RE_NOR: fprintf(stderr, "R-NOR"); break; + case IVL_LPM_RE_XNOR: fprintf(stderr, "R-XNOR"); break; + case IVL_LPM_RE_XOR: fprintf(stderr, "R-XOR"); break; + case IVL_LPM_REPEAT: fprintf(stderr, "repeat"); break; + case IVL_LPM_SFUNC: fprintf(stderr, "S-func"); break; + case IVL_LPM_SHIFTL: fprintf(stderr, "shiftl"); break; + case IVL_LPM_SHIFTR: fprintf(stderr, "shiftr"); break; + case IVL_LPM_SIGN_EXT: fprintf(stderr, "sign"); break; + case IVL_LPM_SUB: fprintf(stderr, "sub"); break; + case IVL_LPM_UFUNC: fprintf(stderr, "U-func"); break; + } + } else if (net_const) { + assert(! net_logic); + assert(! sig); + fprintf(stderr, "Const: "); + } else if (net_logic) { + assert(! sig); + fprintf(stderr, "Logic: "); + } else if (sig) { + ivl_scope_t sig_scope = ivl_signal_scope(sig); + fprintf(stderr, "Signal: "); + if (scope != sig_scope) fprintf(stderr, "%s.", + ivl_scope_name(sig_scope)); + fprintf(stderr, "%s", ivl_signal_basename(sig)); +// HERE: Do we need to add support for an array word or is that an LPM. + if (ivl_signal_local(sig)) fprintf(stderr, " (local)"); + switch (ivl_signal_port(sig)) { + case IVL_SIP_INPUT: fprintf(stderr, " input"); break; + case IVL_SIP_OUTPUT: fprintf(stderr, " output"); break; + case IVL_SIP_INOUT: fprintf(stderr, " inout"); break; + case IVL_SIP_NONE: break; + } + switch (ivl_signal_type(sig)) { + case IVL_SIT_NONE: fprintf(stderr, " "); break; + case IVL_SIT_REG: fprintf(stderr, " reg"); break; + case IVL_SIT_TRI: fprintf(stderr, " tri"); break; + case IVL_SIT_TRI0: fprintf(stderr, " tri0"); break; + case IVL_SIT_TRI1: fprintf(stderr, " tri1"); break; + case IVL_SIT_TRIAND: fprintf(stderr, " triand"); break; + case IVL_SIT_TRIOR: fprintf(stderr, " trior"); break; + case IVL_SIT_UWIRE: fprintf(stderr, " uwire"); break; + } + switch (ivl_signal_data_type(sig)) { + case IVL_VT_VOID: fprintf(stderr, " "); break; + case IVL_VT_NO_TYPE: fprintf(stderr, " "); break; + case IVL_VT_REAL: fprintf(stderr, " real"); break; + case IVL_VT_BOOL: fprintf(stderr, " bool"); break; + case IVL_VT_LOGIC: fprintf(stderr, " logic"); break; + case IVL_VT_STRING: fprintf(stderr, " string"); break; + } + } else { + fprintf(stderr, "Error: No/missing information!"); + } + fprintf(stderr, " (%u)\n", ivl_nexus_ptr_pin(nex_ptr)); + } +} diff --git a/tgt-vlog95/misc.c b/tgt-vlog95/misc.c index e9acba726..f94dc0f0b 100644 --- a/tgt-vlog95/misc.c +++ b/tgt-vlog95/misc.c @@ -505,7 +505,7 @@ static void emit_number_as_string(ivl_net_const_t net_const) if (val == '"') fprintf(vlog_out, "\\\""); else if (val == '\\') fprintf(vlog_out, "\\\\"); /* Print the printable characters. */ - else if (isprint(val)) fprintf(vlog_out, "%c", val); + else if (isprint((int)val)) fprintf(vlog_out, "%c", val); /* Print the non-printable characters as an octal escape. */ else fprintf(vlog_out, "\\%03o", val); } @@ -641,6 +641,7 @@ void emit_name_of_nexus(ivl_scope_t scope, ivl_nexus_t nex) /* It is possible that the nexus does not have a name. For this * case do not print an actual name. */ fprintf(vlog_out, "/* Empty */"); + dump_nexus_information(scope, nex); } /* diff --git a/tgt-vlog95/vlog95_priv.h b/tgt-vlog95/vlog95_priv.h index 2404a9405..492057491 100644 --- a/tgt-vlog95/vlog95_priv.h +++ b/tgt-vlog95/vlog95_priv.h @@ -122,4 +122,9 @@ extern uint64_t get_uint64_from_number(ivl_expr_t expr, int *return_type); */ extern void free_emitted_scope_list(); +/* + * Debug routine to dump the various pieces of nexus information. +*/ +extern void dump_nexus_information(ivl_scope_t scope, ivl_nexus_t nex); + #endif /* __vlog95_priv_H */ diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 8d10e52fb..e79043543 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -3118,19 +3118,37 @@ static struct vector_info draw_unary_expr(ivl_expr_t expr, unsigned wid) local_count += 1; break; - case '2': /* Cast logic to bool */ - assert(ivl_expr_value(sub) == IVL_VT_LOGIC); - res = draw_eval_expr_wid(sub, wid, 0); + case '2': /* Cast expression to bool */ + switch (ivl_expr_value(sub)) { + case IVL_VT_BOOL: + res = draw_eval_expr_wid(sub, wid, 0); + break; - /* Handle special case that value is 0 or 1. */ - if (res.base == 0 || res.base == 1) + case IVL_VT_LOGIC: + res = draw_eval_expr_wid(sub, wid, 0); + + /* Handle special case that value is 0 or 1. */ + if (res.base == 0 || res.base == 1) + break; + if (res.base == 2 || res.base == 2) { + res.base = 0; + break; + } + + fprintf(vvp_out, " %%cast2 %d, %d, %u;\n", res.base, res.base, res.wid); break; - if (res.base == 2 || res.base == 2) { - res.base = 0; + + case IVL_VT_REAL: + word = draw_eval_real(sub); + res.base = allocate_vector(wid); + res.wid = wid; + fprintf(vvp_out, " %%cvt/vr %d, %d, %u;\n", res.base, word, wid); + clr_word(word); break; + + default: + assert(0); } - - fprintf(vvp_out, " %%cast2 %d, %d, %u;\n", res.base, res.base, res.wid); break; case 'i': /* Cast a real value to an integer. */ diff --git a/verinum.cc b/verinum.cc index 143c0cac9..d59d47c81 100644 --- a/verinum.cc +++ b/verinum.cc @@ -804,7 +804,8 @@ verinum::V operator <= (const verinum&left, const verinum&right) { verinum::V left_pad = verinum::V0; verinum::V right_pad = verinum::V0; - if (left.has_sign() && right.has_sign()) { + bool signed_calc = left.has_sign() && right.has_sign(); + if (signed_calc) { left_pad = left.get(left.len()-1); right_pad = right.get(right.len()-1); @@ -816,11 +817,23 @@ verinum::V operator <= (const verinum&left, const verinum&right) unsigned idx; for (idx = left.len() ; idx > right.len() ; idx -= 1) { - if (left[idx-1] != right_pad) return verinum::V0; + if (left[idx-1] != right_pad) { + // A change of padding for a negative left argument + // denotes the left value is less than the right. + return (signed_calc && + (left_pad == verinum::V1)) ? verinum::V1 : + verinum::V0; + } } for (idx = right.len() ; idx > left.len() ; idx -= 1) { - if (right[idx-1] != left_pad) return verinum::V1; + if (right[idx-1] != left_pad) { + // A change of padding for a negative right argument + // denotes the left value is not less than the right. + return (signed_calc && + (right_pad == verinum::V1)) ? verinum::V0 : + verinum::V1; + } } idx = right.len(); @@ -843,7 +856,8 @@ verinum::V operator < (const verinum&left, const verinum&right) { verinum::V left_pad = verinum::V0; verinum::V right_pad = verinum::V0; - if (left.has_sign() && right.has_sign()) { + bool signed_calc = left.has_sign() && right.has_sign(); + if (signed_calc) { left_pad = left.get(left.len()-1); right_pad = right.get(right.len()-1); @@ -855,11 +869,23 @@ verinum::V operator < (const verinum&left, const verinum&right) unsigned idx; for (idx = left.len() ; idx > right.len() ; idx -= 1) { - if (left[idx-1] != right_pad) return verinum::V0; + if (left[idx-1] != right_pad) { + // A change of padding for a negative left argument + // denotes the left value is less than the right. + return (signed_calc && + (left_pad == verinum::V1)) ? verinum::V1 : + verinum::V0; + } } for (idx = right.len() ; idx > left.len() ; idx -= 1) { - if (right[idx-1] != left_pad) return verinum::V1; + if (right[idx-1] != left_pad) { + // A change of padding for a negative right argument + // denotes the left value is not less than the right. + return (signed_calc && + (right_pad == verinum::V1)) ? verinum::V0 : + verinum::V1; + } } while (idx > 0) { diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index b3e5cfc4f..79ccbb20f 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -32,6 +32,8 @@ Architecture::Architecture(perm_string name, const ScopeBase&ref, Architecture::~Architecture() { + delete_all(statements_); + ScopeBase::cleanup(); } Architecture::Statement::Statement() @@ -69,12 +71,15 @@ ComponentInstantiation::ComponentInstantiation(perm_string i, perm_string c, while (! ports->empty()) { named_expr_t*cur = ports->front(); ports->pop_front(); - port_map_[cur->name()] = cur->expr(); + port_map_.insert(make_pair(cur->name(), cur->expr())); } } ComponentInstantiation::~ComponentInstantiation() { + for(map::iterator it = port_map_.begin() + ; it != port_map_.end(); ++it) + delete it->second; } ProcessStatement::ProcessStatement(perm_string iname, diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index 508bb787a..ba6b8160d 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -122,7 +122,7 @@ class ComponentInstantiation : public Architecture::Statement { perm_string iname_; perm_string cname_; - std::map port_map_; + std::multimap port_map_; }; class ProcessStatement : public Architecture::Statement { diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 6533ee465..a3767ad95 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -54,10 +54,12 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc) return 1; } - map port_match; - for (map::iterator cur = port_map_.begin() + for (multimap::const_iterator cur = port_map_.begin() ; cur != port_map_.end() ; ++cur) { + /* check if a port from component instantiation + exists in the component declaration + */ const InterfacePort*iport = base->find_port(cur->first); if (iport == 0) { cerr << get_fileline() << ": error: No port " << cur->first @@ -66,12 +68,25 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc) continue; } + ExpName* tmp; + if (cur->second && (tmp = dynamic_cast(cur->second))) + errors += tmp->elaborate_rval(ent, arc, iport); /* It is possible for the port to be explicitly unconnected. In that case, the Expression will be nil */ + if (cur->second) cur->second->elaborate_expr(ent, arc, iport->type); } + //each formal (component's) port should be associated at most once + for(multimap::const_iterator cur = port_map_.begin() + ; cur != port_map_.end() ; ++cur) + if(port_map_.count(cur->first) != 1) { + //at least one port is associated twice or more + cerr << cur->second->get_fileline() << ": error: At least one port is associated" + << " twice or more in a single component instantiation." << endl; + errors += 1; + } return errors; } diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index ce60631af..52ddb7b54 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -30,12 +30,16 @@ int Scope::emit_signals(ostream&out, Entity*entity, Architecture*arc) { int errors = 0; - for (map::iterator cur = signals_.begin() - ; cur != signals_.end() ; ++cur) { + for (map::iterator cur = old_signals_.begin() + ; cur != old_signals_.end() ; ++cur) { errors += cur->second->emit(out, entity, arc); } + for (map::iterator cur = new_signals_.begin() + ; cur != new_signals_.end() ; ++cur) { + errors += cur->second->emit(out, entity, arc); + } return errors; } @@ -43,12 +47,19 @@ int Architecture::emit(ostream&out, Entity*entity) { int errors = 0; - for (map::iterator cur = constants_.begin() - ; cur != constants_.end() ; ++cur) { + for (map::iterator cur = old_constants_.begin() + ; cur != old_constants_.end() ; ++cur) { - out << "localparam " << cur->first << " = "; - errors += cur->second.val->emit(out, entity, this); - out << ";" << endl; + out << "localparam " << cur->first << " = "; + errors += cur->second->val->emit(out, entity, this); + out << ";" << endl; + } + for (map::iterator cur = new_constants_.begin() + ; cur != new_constants_.end() ; ++cur) { + + out << "localparam " << cur->first << " = "; + errors += cur->second->val->emit(out, entity, this); + out << ";" << endl; } errors += emit_signals(out, entity, this); @@ -94,7 +105,7 @@ int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc) out << cname_ << " " << iname_ << "("; const char*comma = ""; - for (map::iterator cur = port_map_.begin() + for (multimap::iterator cur = port_map_.begin() ; cur != port_map_.end() ; ++cur) { // Skip unconnected ports if (cur->second == 0) diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 0847f11a3..54fac14d8 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -79,36 +79,58 @@ void ComponentBase::dump_ports(ostream&out, int indent) const void Scope::dump_scope(ostream&out) const { // Dump types - for (map::const_iterator cur = types_.begin() - ; cur != types_.end() ; ++cur) { + for (map::const_iterator cur = old_types_.begin() + ; cur != old_types_.end() ; ++cur) { out << " " << cur->first << ": "; cur->second->show(out); out << endl; } + for (map::const_iterator cur = new_types_.begin() + ; cur != new_types_.end() ; ++cur) { + out << " " << cur->first << ": "; + cur->second->show(out); + out << endl; + } // Dump constants - for (map::const_iterator cur = constants_.begin() - ; cur != constants_.end() ; ++cur) { + for (map::const_iterator cur = old_constants_.begin() + ; cur != old_constants_.end() ; ++cur) { out << " constant " << cur->first << " = "; out << endl; } - - // Dump signal declarations - for (map::const_iterator cur = signals_.begin() - ; cur != signals_.end() ; ++cur) { - if (cur->second) - cur->second->dump(out, 3); - else - out << " signal " << cur->first.str() << ": ???" << endl; + for (map::const_iterator cur = new_constants_.begin() + ; cur != new_constants_.end() ; ++cur) { + out << " constant " << cur->first << " = "; + out << endl; + } + // Dump signal declarations + for (map::const_iterator cur = old_signals_.begin() + ; cur != old_signals_.end() ; ++cur) { + if (cur->second) + cur->second->dump(out, 3); + else + out << " signal " << cur->first.str() << ": ???" << endl; + } + for (map::const_iterator cur = new_signals_.begin() + ; cur != new_signals_.end() ; ++cur) { + if (cur->second) + cur->second->dump(out, 3); + else + out << " signal " << cur->first.str() << ": ???" << endl; } - // Dump component declarations - for (map::const_iterator cur = components_.begin() - ; cur != components_.end() ; ++cur) { + for (map::const_iterator cur = old_components_.begin() + ; cur != old_components_.end() ; ++cur) { out << " component " << cur->first << " is" << endl; cur->second->dump_ports(out); out << " end component " << cur->first << endl; } + for (map::const_iterator cur = new_components_.begin() + ; cur != new_components_.end() ; ++cur) { + out << " component " << cur->first << " is" << endl; + cur->second->dump_ports(out); + out << " end component " << cur->first << endl; + } } void Entity::dump(ostream&out, int indent) const diff --git a/vhdlpp/entity.cc b/vhdlpp/entity.cc index b9ccbff0a..de3846fb2 100644 --- a/vhdlpp/entity.cc +++ b/vhdlpp/entity.cc @@ -33,6 +33,9 @@ ComponentBase::ComponentBase(perm_string name) ComponentBase::~ComponentBase() { + for(std::vector::iterator it = ports_.begin() + ; it != ports_.end(); ++it) + delete *it; } void ComponentBase::set_interface(std::list*ports) @@ -60,6 +63,9 @@ Entity::Entity(perm_string name) Entity::~Entity() { + for(map::reverse_iterator it = arch_.rbegin() + ; it != arch_.rend(); ++it) + delete it->second; } Architecture* Entity::add_architecture(Architecture*that) diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index fdec70340..d626501aa 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -21,6 +21,7 @@ # include "StringHeap.h" # include "LineInfo.h" +# include "entity.h" # include # include # include @@ -322,6 +323,7 @@ class ExpName : public Expression { public: // Base methods int elaborate_lval(Entity*ent, Architecture*arc, bool); + int elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*); const VType* probe_type(Entity*ent, Architecture*arc) const; int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); int emit(ostream&out, Entity*ent, Architecture*arc); diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index e2c93374c..048474cb8 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -71,6 +71,44 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) return errors; } +int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lval) +{ + int errors = 0; + + if (const InterfacePort*cur = ent->find_port(name_)) { + /* IEEE 1076-2008, p.80: + * For a formal port IN, associated port should be IN, OUT, INOUT or BUFFER + * For a formal port OUT, associated port should be OUT, INOUT or BUFFER + * For a formal port INOUT, associated prot should be OUT, INOUT or BUFFER + * For a formal port BUFFER, associated port should be OUT, INOUT or BUFFER + */ + switch(lval->mode) { + case PORT_OUT: + //case PORT_INOUT: + if (cur->mode == PORT_IN) { + cerr << get_fileline() << ": error: Connecting " + "formal output port " << lval->name << " to actual input port " + << name_ << "." << endl; + errors += 1; + } + break; + case PORT_IN: + case PORT_NONE: + default: + break; + } + } else if (Signal* fs = arc->find_signal(name_)) { + /* OK */ + + } else { + cerr << get_fileline() << ": error: No port or signal " << name_ + << " to be used as r-value." << endl; + errors += 1; + } + + return errors; +} + int ExpNameALL::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) { return Expression::elaborate_lval(ent, arc, is_sequ); diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index 987fb265b..7a8509aba 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -165,7 +165,7 @@ static void import_ieee_use_std_logic_1164(ActiveScope*res, perm_string name) if (all_flag || name == "std_logic_vector") { vector dims (1); res->bind_name(perm_string::literal("std_logic_vector"), - new VTypeArray(&primitive_STDLOGIC, dims, false)); + new VTypeArray(primitive_STDLOGIC, dims, false)); } } @@ -176,12 +176,12 @@ static void import_ieee_use_numeric_bit(ActiveScope*res, perm_string name) if (all_flag || name == "signed") { vector dims (1); res->bind_name(perm_string::literal("signed"), - new VTypeArray(&primitive_STDLOGIC, dims, true)); + new VTypeArray(primitive_STDLOGIC, dims, true)); } if (all_flag || name == "unsigned") { vector dims (1); res->bind_name(perm_string::literal("unsigned"), - new VTypeArray(&primitive_BIT, dims, false)); + new VTypeArray(primitive_BIT, dims, false)); } } @@ -192,12 +192,12 @@ static void import_ieee_use_numeric_std(ActiveScope*res, perm_string name) if (all_flag || name == "signed") { vector dims (1); res->bind_name(perm_string::literal("signed"), - new VTypeArray(&primitive_STDLOGIC, dims, true)); + new VTypeArray(primitive_STDLOGIC, dims, true)); } if (all_flag || name == "unsigned") { vector dims (1); res->bind_name(perm_string::literal("unsigned"), - new VTypeArray(&primitive_STDLOGIC, dims, false)); + new VTypeArray(primitive_STDLOGIC, dims, false)); } } @@ -219,22 +219,21 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na } } +const VTypePrimitive* primitive_BOOLEAN = new VTypePrimitive(VTypePrimitive::BOOLEAN); +const VTypePrimitive* primitive_BIT = new VTypePrimitive(VTypePrimitive::BIT); +const VTypePrimitive* primitive_INTEGER = new VTypePrimitive(VTypePrimitive::INTEGER); +const VTypePrimitive* primitive_STDLOGIC = new VTypePrimitive(VTypePrimitive::STDLOGIC); -const VTypePrimitive primitive_BOOLEAN (VTypePrimitive::BOOLEAN); -const VTypePrimitive primitive_BIT (VTypePrimitive::BIT); -const VTypePrimitive primitive_INTEGER (VTypePrimitive::INTEGER); -const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC); - -const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector (1)); -const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector (1)); +const VTypeArray* primitive_BIT_VECTOR = new VTypeArray(primitive_BIT, vector (1)); +const VTypeArray* primitive_BOOL_VECTOR = new VTypeArray(primitive_BOOLEAN, vector (1)); void generate_global_types(ActiveScope*res) { - res->bind_name(perm_string::literal("boolean"), &primitive_BOOLEAN); - res->bind_name(perm_string::literal("bit"), &primitive_BIT); - res->bind_name(perm_string::literal("integer"), &primitive_INTEGER); - res->bind_name(perm_string::literal("std_logic"), &primitive_STDLOGIC); - res->bind_name(perm_string::literal("bit_vector"),&primitive_BOOL_VECTOR); + res->bind_name(perm_string::literal("boolean"), primitive_BOOLEAN); + res->bind_name(perm_string::literal("bit"), primitive_BIT); + res->bind_name(perm_string::literal("integer"), primitive_INTEGER); + res->bind_name(perm_string::literal("std_logic"), primitive_STDLOGIC); + res->bind_name(perm_string::literal("bit_vector"),primitive_BOOL_VECTOR); } void library_set_work_path(const char*path) diff --git a/vhdlpp/main.cc b/vhdlpp/main.cc index b15de59cf..1a3d2f3f2 100644 --- a/vhdlpp/main.cc +++ b/vhdlpp/main.cc @@ -59,6 +59,7 @@ const char*dump_libraries_path = 0; extern void dump_libraries(ostream&file); +extern void parser_cleanup(); static void process_debug_token(const char*word) { @@ -158,21 +159,25 @@ int main(int argc, char*argv[]) dump_design_entities(file); } - if (errors > 0) + if (errors > 0) { + parser_cleanup(); return 2; + } errors = elaborate_entities(); if (errors > 0) { fprintf(stderr, "%d errors elaborating design.\n", errors); + parser_cleanup(); return 3; } errors = emit_entities(); if (errors > 0) { fprintf(stderr, "%d errors emitting design.\n", errors); + parser_cleanup(); return 4; } - lex_strings.cleanup(); + parser_cleanup(); return 0; } diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index aa14ebab1..211b422f9 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -27,14 +27,20 @@ Package::Package(perm_string n, const ScopeBase&ref) Package::~Package() { + ScopeBase::cleanup(); } void Package::write_to_stream(ostream&fd) const { fd << "package " << name_ << " is" << endl; - for (map::const_iterator cur = components_.begin() - ; cur != components_.end() ; ++cur) { + for (map::const_iterator cur = old_components_.begin() + ; cur != old_components_.end() ; ++cur) { + + cur->second->write_to_stream(fd); + } + for (map::const_iterator cur = new_components_.begin() + ; cur != new_components_.end() ; ++cur) { cur->second->write_to_stream(fd); } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 7cc694404..63616566d 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -39,6 +39,7 @@ # include # include # include +# include # include # include # include "parse_types.h" @@ -77,7 +78,7 @@ extern int yylex(union YYSTYPE*yylvalp,YYLTYPE*yyllocp,yyscan_t yyscanner); * manage lexical scopes. */ static ActiveScope*active_scope = new ActiveScope; -static list scope_stack; +static stack scope_stack; /* * When a scope boundary starts, call the push_scope function to push @@ -89,7 +90,7 @@ static list scope_stack; static void push_scope(void) { assert(active_scope); - scope_stack.push_front(active_scope); + scope_stack.push(active_scope); active_scope = new ActiveScope (active_scope); } @@ -97,8 +98,8 @@ static void pop_scope(void) { delete active_scope; assert(scope_stack.size() > 0); - active_scope = scope_stack.front(); - scope_stack.pop_front(); + active_scope = scope_stack.top(); + scope_stack.pop(); } @@ -107,6 +108,31 @@ void preload_global_types(void) generate_global_types(active_scope); } +//Remove the scope created at the beginning of parser's work. +//After the parsing active_scope should keep it's address + +static void delete_global_scope(void) +{ + active_scope->destroy_global_scope(); + delete active_scope; +} + +//delete global entities that were gathered over the parsing process +static void delete_design_entities(void) +{ + for(map::iterator cur = design_entities.begin() + ; cur != design_entities.end(); ++cur) + delete cur->second; +} + +//clean the mess caused by the parser +void parser_cleanup(void) +{ + delete_design_entities(); + delete_global_scope(); + lex_strings.cleanup(); +} + const VType*parse_type_by_name(perm_string name) { return active_scope->find_type(name); @@ -473,7 +499,10 @@ component_declaration } ComponentBase*comp = new ComponentBase(name); - if ($4) comp->set_interface($4); + if ($4) { + comp->set_interface($4); + delete $4; + } active_scope->bind_name(name, comp); delete[]$2; if ($7) delete[] $7; @@ -492,6 +521,7 @@ component_instantiation_statement { perm_string iname = lex_strings.make($1); perm_string cname = lex_strings.make($4); ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $5); + delete $5; FILE_NAME(tmp, @1); delete[]$1; delete[]$4; @@ -681,7 +711,7 @@ entity_declaration errormsg(@1, "Syntax error in entity clause. Closing name doesn't match.\n"); yyerrok; } - delete $7; + delete[]$7; } } | K_entity error K_end K_entity_opt identifier_opt ';' diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 6f2da84b9..6c27d0ed9 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -18,61 +18,122 @@ */ # include "scope.h" +# include # include +# include using namespace std; ScopeBase::ScopeBase(const ScopeBase&ref) { - constants_ = ref.constants_; - signals_ = ref.signals_; - components_ = ref.components_; - types_ = ref.types_; + merge(ref.old_constants_.begin(), ref.old_constants_.end(), + ref.new_constants_.begin(), ref.new_constants_.end(), + insert_iterator >( + old_constants_, old_constants_.end()) + ); + merge(ref.old_signals_.begin(), ref.old_signals_.end(), + ref.new_signals_.begin(), ref.new_signals_.end(), + insert_iterator >( + old_signals_, old_signals_.end()) + ); + merge(ref.old_components_.begin(), ref.old_components_.end(), + ref.new_components_.begin(), ref.new_components_.end(), + insert_iterator >( + old_components_, old_components_.end()) + ); + merge(ref.old_types_.begin(), ref.old_types_.end(), + ref.new_types_.begin(), ref.new_types_.end(), + insert_iterator >( + old_types_, old_types_.end()) + ); } ScopeBase::~ScopeBase() { + //freeing of member objects is performed by child classes +} + +void ScopeBase::cleanup() +{ + /* + * A parent scope is destroyed only if all child scopes + * were previously destroyed. There for we can delete all + * objects that were defined in this scope, leaving + * objects from the other scopes untouched. + */ + delete_all(new_signals_); + delete_all(new_components_); + delete_all(new_types_); + delete_all(new_constants_); } const VType*ScopeBase::find_type(perm_string by_name) { - map::const_iterator cur = types_.find(by_name); - if (cur == types_.end()) - return 0; - else + map::const_iterator cur = new_types_.find(by_name); + if (cur == new_types_.end()) { + cur = old_types_.find(by_name); + if (cur == old_types_.end()) + return 0; + else + return cur->second; + } else return cur->second; } bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp) { - map::const_iterator cur = constants_.find(by_name); - if (cur == constants_.end()) - return false; - - typ = cur->second.typ; - exp = cur->second.val; - return true; + map::const_iterator cur = new_constants_.find(by_name); + if (cur == new_constants_.end()) { + cur = old_constants_.find(by_name); + if (cur == old_constants_.end()) + return false; + else { + typ = cur->second->typ; + exp = cur->second->val; + return true; + } + } else { + typ = cur->second->typ; + exp = cur->second->val; + return true; + } } void ScopeBase::do_use_from(const ScopeBase*that) { - for (map::const_iterator cur = that->components_.begin() - ; cur != that->components_.end() ; ++ cur) { + for (map::const_iterator cur = that->old_components_.begin() + ; cur != that->old_components_.end() ; ++ cur) { if (cur->second == 0) continue; - components_[cur->first] = cur->second; + old_components_[cur->first] = cur->second; + } + for (map::const_iterator cur = that->new_components_.begin() + ; cur != that->new_components_.end() ; ++ cur) { + if (cur->second == 0) + continue; + old_components_[cur->first] = cur->second; } - for (map::const_iterator cur = that->types_.begin() - ; cur != that->types_.end() ; ++ cur) { + for (map::const_iterator cur = that->old_types_.begin() + ; cur != that->old_types_.end() ; ++ cur) { if (cur->second == 0) continue; - types_[cur->first] = cur->second; + old_types_[cur->first] = cur->second; + } + for (map::const_iterator cur = that->new_types_.begin() + ; cur != that->new_types_.end() ; ++ cur) { + if (cur->second == 0) + continue; + old_types_[cur->first] = cur->second; } - for (map::const_iterator cur = that->constants_.begin() - ; cur != that->constants_.end() ; ++ cur) { - constants_[cur->first] = cur->second; + for (map::const_iterator cur = that->old_constants_.begin() + ; cur != that->old_constants_.end() ; ++ cur) { + old_constants_[cur->first] = cur->second; + } + for (map::const_iterator cur = that->new_constants_.begin() + ; cur != that->new_constants_.end() ; ++ cur) { + old_constants_[cur->first] = cur->second; } } @@ -87,18 +148,27 @@ Scope::~Scope() ComponentBase* Scope::find_component(perm_string by_name) { - map::const_iterator cur = components_.find(by_name); - if (cur == components_.end()) - return 0; - else + map::const_iterator cur = new_components_.find(by_name); + if (cur == new_components_.end()) { + cur = old_components_.find(by_name); + if (cur == old_components_.end()) + return 0; + else + return cur->second; + } else return cur->second; } Signal* Scope::find_signal(perm_string by_name) { - map::const_iterator cur = signals_.find(by_name); - if (cur == signals_.end()) - return 0; - else + map::const_iterator cur = new_signals_.find(by_name); + if (cur == new_signals_.end()) { + cur = old_signals_.find(by_name); + if (cur == old_signals_.end()) + return 0; + else + return cur->second; + } else { return cur->second; + } } diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index fd5e80272..69a8de4a7 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -19,17 +19,28 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +# include # include # include # include "StringHeap.h" +# include "entity.h" +# include "expression.h" +# include "vsignal.h" class Architecture; class ComponentBase; -class Entity; -class Expression; -class Signal; class VType; +template +struct delete_object{ + void operator()(T* item) { delete item; } +}; + +template +struct delete_pair_second{ + void operator()(pair item){ delete item.second; } +}; + class ScopeBase { public: @@ -40,18 +51,37 @@ class ScopeBase { const VType* find_type(perm_string by_name); bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp); protected: + void cleanup(); + + //containers' cleaning helper functions + template void delete_all(list& c) + { + for_each(c.begin(), c.end(), ::delete_object()); + } + template void delete_all(map& c) + { + for_each(c.begin(), c.end(), ::delete_pair_second()); + } + // Signal declarations... - std::map signals_; + std::map old_signals_; //previous scopes + std::map new_signals_; //current scope // Component declarations... - std::map components_; + std::map old_components_; //previous scopes + std::map new_components_; //current scope // Type declarations... - std::map types_; + std::map old_types_; //previous scopes + std::map new_types_; //current scope // Constant declarations... struct const_t { + ~const_t() {delete typ; delete val;} + const_t(const VType*t, Expression* v) : typ(t), val(v) {}; + const VType*typ; Expression*val; }; - std::map constants_; + std::map old_constants_; //previous scopes + std::map new_constants_; //current scope void do_use_from(const ScopeBase*that); }; @@ -90,20 +120,44 @@ class ActiveScope : public ScopeBase { void use_from(const ScopeBase*that) { do_use_from(that); } + + /* All bind_name function check if the given name was present + * in previous scopes. If it is found, it is erased (but the pointer + * is not freed), in order to implement name shadowing. The pointer + * be freed only in the scope where the object was defined. This is + * done in ScopeBase::cleanup() function .*/ + void bind_name(perm_string name, Signal*obj) - { signals_[name] = obj; } + { map::iterator it; + if((it = old_signals_.find(name)) != old_signals_.end() ) + old_signals_.erase(it); + new_signals_[name] = obj; + } void bind_name(perm_string name, ComponentBase*obj) - { components_[name] = obj; } + { map::iterator it; + if((it = old_components_.find(name)) != old_components_.end() ) + old_components_.erase(it); + new_components_[name] = obj; + } - void bind_name(perm_string name, const VType*obj) - { types_[name] = obj; } + void bind_name(perm_string name, const VType* t) + { map::iterator it; + if((it = old_types_.find(name)) != old_types_.end() ) + old_types_.erase(it); + new_types_[name] = t; + } void bind_name(perm_string name, const VType*obj, Expression*val) + { map::iterator it; + if((it = old_constants_.find(name)) != old_constants_.end() ) + old_constants_.erase(it); + new_constants_[name] = new const_t(obj, val); + } + + void destroy_global_scope() { - const_t&tmp = constants_[name]; - tmp.typ = obj; - tmp.val = val; + cleanup(); } }; diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 4950927aa..fbe89a7a0 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -89,10 +89,10 @@ class VTypePrimitive : public VType { type_t type_; }; -extern const VTypePrimitive primitive_BOOLEAN; -extern const VTypePrimitive primitive_BIT; -extern const VTypePrimitive primitive_INTEGER; -extern const VTypePrimitive primitive_STDLOGIC; +extern const VTypePrimitive* primitive_BOOLEAN; +extern const VTypePrimitive* primitive_BIT; +extern const VTypePrimitive* primitive_INTEGER; +extern const VTypePrimitive* primitive_STDLOGIC; /* * An array is a compound N-dimensional array of element type. The diff --git a/vhdlpp/vtype_stream.cc b/vhdlpp/vtype_stream.cc index 2b2d70534..eac28c8ed 100644 --- a/vhdlpp/vtype_stream.cc +++ b/vhdlpp/vtype_stream.cc @@ -31,7 +31,7 @@ void VType::write_to_stream(ostream&fd) const void VTypeArray::write_to_stream(ostream&fd) const { // Special case: std_logic_vector - if (etype_ == &primitive_STDLOGIC) { + if (etype_ == primitive_STDLOGIC) { fd << "std_logic_vector"; if (ranges_.size() > 0) { assert(ranges_.size() < 2);