diff --git a/Module.h b/Module.h index 9b80b17c7..5985ab717 100644 --- a/Module.h +++ b/Module.h @@ -82,6 +82,8 @@ class Module : public PScope, public LineInfo { PExpr*expr; PExpr*msb; PExpr*lsb; + perm_string file; + unsigned lineno; bool signed_flag; }; mapparameters; @@ -119,7 +121,7 @@ class Module : public PScope, public LineInfo { /* The module has a list of genvars that may be used in various generate schemes. */ - list genvars; + list > genvars; /* the module has a list of generate schemes that appear in the module definition. These are used at elaboration time. */ @@ -156,7 +158,8 @@ class Module : public PScope, public LineInfo { map funcs_; static void elaborate_parm_item_(perm_string name, const param_expr_t&cur, - Design*des, NetScope*scope); + Design*des, NetScope*scope, + perm_string file, unsigned lineno); private: // Not implemented Module(const Module&); diff --git a/elab_scope.cc b/elab_scope.cc index 11f310753..175d0474c 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -45,7 +45,8 @@ # include void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur, - Design*des, NetScope*scope) + Design*des, NetScope*scope, + perm_string file, unsigned lineno) { PExpr*ex = cur.expr; assert(ex); @@ -81,7 +82,7 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur, } val = scope->set_parameter(name, val, - msb, lsb, signed_flag); + msb, lsb, signed_flag, file, lineno); assert(val); delete val; } @@ -119,7 +120,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, tmp->set_line(*((*cur).second.expr)); tmp->cast_signed( (*cur).second.signed_flag ); - scope->set_parameter((*cur).first, tmp, 0, 0, false); + scope->set_parameter((*cur).first, tmp, 0, 0, false, + (*cur).second.file, (*cur).second.lineno); } for (mparm_it_t cur = localparams.begin() @@ -130,7 +132,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, if ((*cur).second.msb) tmp->cast_signed( (*cur).second.signed_flag ); - scope->set_parameter((*cur).first, tmp, 0, 0, false); + scope->set_parameter((*cur).first, tmp, 0, 0, false, + (*cur).second.file, (*cur).second.lineno); } @@ -142,7 +145,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, for (mparm_it_t cur = parameters.begin() ; cur != parameters.end() ; cur ++) { - elaborate_parm_item_((*cur).first, (*cur).second, des, scope); + elaborate_parm_item_((*cur).first, (*cur).second, des, scope, + (*cur).second.file, (*cur).second.lineno); } /* run parameter replacements that were collected from the @@ -174,7 +178,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, for (mparm_it_t cur = localparams.begin() ; cur != localparams.end() ; cur ++) { - elaborate_parm_item_((*cur).first, (*cur).second, des, scope); + elaborate_parm_item_((*cur).first, (*cur).second, des, scope, + (*cur).second.file, (*cur).second.lineno); } // Run through the defparams for this module, elaborate the @@ -339,6 +344,11 @@ bool PGenerate::generate_scope(Design*des, NetScope*container) */ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) { + // Check that the loop_index variable was declared in a + // genvar statement. + + // MISSING CODE! + // We're going to need a genvar... int genvar; @@ -354,12 +364,24 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) return false; } + // Since we will be adding the genvar value as a local parameter + // to each instances scope. We need to make sure a parameter does + // not already exist. + const NetExpr*tmsb; + const NetExpr*tlsb; + const NetExpr*texpr = container->get_parameter(loop_index, tmsb, tlsb); + if (texpr != 0) { + cerr << get_fileline() << ": error: Cannot have a genvar " + << "and parameter with the same name: " << loop_index << endl; + des->errors += 1; + return false; + } + genvar = init->value().as_long(); delete init_ex; if (debug_scopes) cerr << get_fileline() << ": debug: genvar init = " << genvar << endl; - container->genvar_tmp = loop_index; container->genvar_tmp_val = genvar; NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1); @@ -397,7 +419,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) NetEConstParam*gp = new NetEConstParam(scope, loop_index, genvar_verinum); - scope->set_localparam(loop_index, gp); + // The file and line information should really come + // from the genvar statement, not the for loop. + scope->set_localparam(loop_index, gp, get_file(), + get_lineno()); if (debug_scopes) cerr << get_fileline() << ": debug: " diff --git a/eval_tree.cc b/eval_tree.cc index 47d7d211f..f6608e7b7 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -1217,7 +1217,12 @@ NetExpr* NetEParam::eval_tree(int prune_to_width) // The result can be saved as the value of the parameter for // future reference, and return a copy to the caller. - scope_->replace_parameter(name_, res); + bool flag = scope_->replace_parameter(name_, res); + if (!flag) { + cerr << get_fileline() << ": internal error: Could not " + << "replace parameter expression for " << name_ << endl; + return 0; + } /* Return as a result a NetEConstParam or NetECRealParam object, depending on the type of the expression. */ diff --git a/ivl.def b/ivl.def index 3b8f10462..8e151f590 100644 --- a/ivl.def +++ b/ivl.def @@ -118,6 +118,8 @@ ivl_nexus_ptr_sig ivl_parameter_basename ivl_parameter_expr +ivl_parameter_file +ivl_parameter_lineno ivl_path_condit ivl_path_delay @@ -163,7 +165,9 @@ ivl_signal_attr_val ivl_signal_basename ivl_signal_data_type ivl_signal_dimensions +ivl_signal_file ivl_signal_integer +ivl_signal_lineno ivl_signal_local ivl_signal_lsb ivl_signal_msb diff --git a/ivl_target.h b/ivl_target.h index 6beca4af4..827901241 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -1339,11 +1339,18 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net); * ivl_parameter_expr * Return the value of the parameter. This should be a simple * constant expression, an IVL_EX_STRING or IVL_EX_NUMBER. + * + * ivl_parameter_file + * ivl_parameter_lineno + * Returns the file and line where this parameter is define */ extern const char* ivl_parameter_basename(ivl_parameter_t net); extern ivl_scope_t ivl_parameter_scope(ivl_parameter_t net); extern ivl_expr_t ivl_parameter_expr(ivl_parameter_t net); +extern const char* ivl_parameter_file(ivl_parameter_t net); +extern unsigned ivl_parameter_lineno(ivl_parameter_t net); + /* SCOPE * Scopes of various sort have these properties. Use these methods to @@ -1586,6 +1593,10 @@ extern int ivl_scope_time_units(ivl_scope_t net); * the attribute value (a string) associated with a key. This * function returns the attribute value for the given key. If the * key does not exist, the function returns 0. + * + * ivl_signal_file + * ivl_signal_lineno + * Returns the file and line where this signal is defined. */ extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word); @@ -1607,6 +1618,9 @@ extern const char* ivl_signal_name(ivl_signal_t net); extern const char* ivl_signal_basename(ivl_signal_t net); extern const char* ivl_signal_attr(ivl_signal_t net, const char*key); +extern const char* ivl_signal_file(ivl_signal_t net); +extern unsigned ivl_signal_lineno(ivl_signal_t net); + extern unsigned ivl_signal_attr_cnt(ivl_signal_t net); extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx); diff --git a/net_scope.cc b/net_scope.cc index cff2b7ab7..01799f107 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -104,7 +104,8 @@ void NetScope::set_line(perm_string file, perm_string def_file, } NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr, - NetExpr*msb, NetExpr*lsb, bool signed_flag) + NetExpr*msb, NetExpr*lsb, bool signed_flag, + perm_string file, unsigned lineno) { param_expr_t&ref = parameters[key]; NetExpr* res = ref.expr; @@ -112,6 +113,8 @@ NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr, ref.msb = msb; ref.lsb = lsb; ref.signed_flag = signed_flag; + ref.file = file; + ref.lineno = lineno; return res; } @@ -134,29 +137,30 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix) } /* - * Return false if this creates a new parameter. + * Return false if the parameter does not already exist. + * A parameter is not automatically created. */ bool NetScope::replace_parameter(perm_string key, NetExpr*expr) { - bool flag = true; - param_expr_t&ref = parameters[key]; + bool flag = false; - NetExpr* res = ref.expr; + if (parameters.find(key) != parameters.end()) { + param_expr_t&ref = parameters[key]; - if (res) { - delete res; - } else { - flag = false; - ref.msb = 0; - ref.lsb = 0; - ref.signed_flag = false; + delete ref.expr; + ref.expr = expr; + flag = true; } - ref.expr = expr; return flag; } -NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr) +/* + * This is not really complete (msb, lsb, sign). It is currently only + * used to add a genver to the local parameter list. + */ +NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr, + perm_string file, unsigned lineno) { param_expr_t&ref = localparams[key]; NetExpr* res = ref.expr; @@ -164,6 +168,8 @@ NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr) ref.msb = 0; ref.lsb = 0; ref.signed_flag = false; + ref.file = file; + ref.lineno = lineno; return res; } diff --git a/netlist.h b/netlist.h index 891864b84..b473050a4 100644 --- a/netlist.h +++ b/netlist.h @@ -3294,8 +3294,10 @@ class NetScope : public Attrib { previous expression, if there was one. */ NetExpr* set_parameter(perm_string name, NetExpr*val, - NetExpr*msb, NetExpr*lsb, bool signed_flag); - NetExpr* set_localparam(perm_string name, NetExpr*val); + NetExpr*msb, NetExpr*lsb, bool signed_flag, + perm_string file, unsigned lineno); + NetExpr* set_localparam(perm_string name, NetExpr*val, + perm_string file, unsigned lineno); const NetExpr*get_parameter(const char* name, const NetExpr*&msb, @@ -3410,6 +3412,8 @@ class NetScope : public Attrib { NetExpr*expr; NetExpr*msb; NetExpr*lsb; + perm_string file; + unsigned lineno; bool signed_flag; }; mapparameters; diff --git a/parse.y b/parse.y index 35a139fca..9f3bdb3a5 100644 --- a/parse.y +++ b/parse.y @@ -2087,7 +2087,7 @@ module_item | K_generate module_item_list_opt K_endgenerate | K_genvar list_of_identifiers ';' - { pform_genvars($2); } + { pform_genvars(@1, $2); } | K_for '(' IDENTIFIER '=' expression ';' expression ';' @@ -2309,7 +2309,8 @@ parameter_assign } else { pform_set_parameter(lex_strings.make($1), active_signed, - active_range, tmp); + active_range, tmp, + @1.text, @1.first_line); } delete[]$1; } @@ -2331,7 +2332,8 @@ localparam_assign } else { pform_set_localparam(lex_strings.make($1), active_signed, - active_range, tmp); + active_range, tmp, + @1.text, @1.first_line); } delete[]$1; } diff --git a/pform.cc b/pform.cc index 91fbd1cb8..8a613fb13 100644 --- a/pform.cc +++ b/pform.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -363,11 +363,14 @@ void pform_endmodule(const char*name) pform_cur_module = 0; } -void pform_genvars(list*names) +void pform_genvars(const struct vlltype&li, list*names) { list::const_iterator cur; for (cur = names->begin(); cur != names->end() ; *cur++) { - pform_cur_module->genvars.push_back( *cur ); + LineInfo*lni = new LineInfo(); + FILE_NAME(lni, li); + pform_cur_module->genvars.push_back( + pair(*cur, lni)); } delete names; @@ -1639,7 +1642,8 @@ void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r) } void pform_set_parameter(perm_string name, bool signed_flag, - svector*range, PExpr*expr) + svector*range, PExpr*expr, + const char*file, unsigned lineno) { assert(expr); pform_cur_module->parameters[name].expr = expr; @@ -1655,12 +1659,15 @@ void pform_set_parameter(perm_string name, bool signed_flag, pform_cur_module->parameters[name].lsb = 0; } pform_cur_module->parameters[name].signed_flag = signed_flag; + pform_cur_module->parameters[name].file = filename_strings.make(file); + pform_cur_module->parameters[name].lineno = lineno; pform_cur_module->param_names.push_back(name); } void pform_set_localparam(perm_string name, bool signed_flag, - svector*range, PExpr*expr) + svector*range, PExpr*expr, + const char*file, unsigned lineno) { assert(expr); pform_cur_module->localparams[name].expr = expr; @@ -1676,6 +1683,8 @@ void pform_set_localparam(perm_string name, bool signed_flag, pform_cur_module->localparams[name].lsb = 0; } pform_cur_module->localparams[name].signed_flag = signed_flag; + pform_cur_module->localparams[name].file = filename_strings.make(file); + pform_cur_module->localparams[name].lineno = lineno; } void pform_set_specparam(perm_string name, PExpr*expr) @@ -1925,4 +1934,3 @@ void pform_error_nested_modules() cerr << pform_cur_module->get_fileline() << ": error: original module " "(" << pform_cur_module->mod_name() << ") defined here." << endl; } - diff --git a/pform.h b/pform.h index af08b4e87..ed953cb99 100644 --- a/pform.h +++ b/pform.h @@ -1,7 +1,7 @@ #ifndef __pform_H #define __pform_H /* - * Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: pform.h,v 1.91 2007/05/24 04:07:12 steve Exp $" -#endif # include "netlist.h" # include "HName.h" @@ -175,13 +172,13 @@ extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt); extern verinum* pform_verinum_with_size(verinum*s, verinum*val, - const char*file, unsigned loneno); + const char*file, unsigned lineno); /* * This function takes the list of names as new genvars to declare in * the current module scope. */ -extern void pform_genvars(list*names); +extern void pform_genvars(const struct vlltype&li, list*names); extern void pform_start_generate_for(const struct vlltype&li, char*ident1, @@ -263,11 +260,13 @@ extern void pform_set_type_attrib(perm_string name, const string&key, extern void pform_set_parameter(perm_string name, bool signed_flag, svector*range, - PExpr*expr); + PExpr*expr, + const char*file, unsigned lineno); extern void pform_set_localparam(perm_string name, - bool signed_flag, - svector*range, - PExpr*expr); + bool signed_flag, + svector*range, + PExpr*expr, + const char*file, unsigned lineno); extern void pform_set_defparam(const pform_name_t&name, PExpr*expr); /* diff --git a/pform_dump.cc b/pform_dump.cc index d8efeab24..9bcc7efa3 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2006 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -995,10 +995,10 @@ void Module::dump(ostream&out) const out << "/* ERROR */;" << endl; } - typedef list::const_iterator genvar_iter_t; + typedef list >::const_iterator genvar_iter_t; for (genvar_iter_t cur = genvars.begin() ; cur != genvars.end() ; cur++) { - out << " genvar " << (*cur) << ";" << endl; + out << " genvar " << ((*cur).first) << ";" << endl; } typedef list::const_iterator genscheme_iter_t; @@ -1123,4 +1123,3 @@ void PUdp::dump(ostream&out) const out << "endprimitive" << endl; } - diff --git a/t-dll-api.cc b/t-dll-api.cc index db8dd8b64..4d3a90fef 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1344,6 +1344,18 @@ extern "C" ivl_expr_t ivl_parameter_expr(ivl_parameter_t net) return net->value; } +extern "C" const char* ivl_parameter_file(ivl_parameter_t net) +{ + assert(net); + return net->file.str(); +} + +extern "C" unsigned ivl_parameter_lineno(ivl_parameter_t net) +{ + assert(net); + return net->lineno; +} + extern "C" ivl_scope_t ivl_parameter_scope(ivl_parameter_t net) { assert(net); @@ -1739,6 +1751,18 @@ extern "C" int ivl_signal_signed(ivl_signal_t net) return net->signed_; } +extern "C" const char* ivl_signal_file(ivl_signal_t net) +{ + assert(net); + return net->file.str(); +} + +extern "C" unsigned ivl_signal_lineno(ivl_signal_t net) +{ + assert(net); + return net->lineno; +} + extern "C" int ivl_signal_integer(ivl_signal_t net) { return net->isint_; diff --git a/t-dll.cc b/t-dll.cc index edade0859..fd7ba497e 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -470,6 +470,8 @@ void dll_target::make_scope_parameters(ivl_scope_t scope, const NetScope*net) ivl_parameter_t cur_par = scope->param_ + idx; cur_par->basename = (*cur_pit).first; cur_par->scope = scope; + cur_par->file = (*cur_pit).second.file; + cur_par->lineno = (*cur_pit).second.lineno; NetExpr*etmp = (*cur_pit).second.expr; make_scope_param_expr(cur_par, etmp); @@ -482,6 +484,8 @@ void dll_target::make_scope_parameters(ivl_scope_t scope, const NetScope*net) ivl_parameter_t cur_par = scope->param_ + idx; cur_par->basename = (*cur_pit).first; cur_par->scope = scope; + cur_par->file = (*cur_pit).second.file; + cur_par->lineno = (*cur_pit).second.lineno; NetExpr*etmp = (*cur_pit).second.expr; make_scope_param_expr(cur_par, etmp); @@ -2216,6 +2220,8 @@ void dll_target::signal(const NetNet*net) object, or creating the sigs_ array if this is the first signal. */ obj->scope_ = find_scope(des_, net->scope()); + obj->file = perm_string::literal("N/A"); + obj->lineno = 0; assert(obj->scope_); if (obj->scope_->nsigs_ == 0) { diff --git a/t-dll.h b/t-dll.h index 9d7440ada..d1e68eaad 100644 --- a/t-dll.h +++ b/t-dll.h @@ -509,6 +509,8 @@ struct ivl_parameter_s { perm_string basename; ivl_scope_t scope; ivl_expr_t value; + perm_string file; + unsigned lineno; }; /* * All we know about a process it its type (initial or always) and the @@ -581,6 +583,8 @@ struct ivl_signal_s { ivl_signal_type_t type_; ivl_signal_port_t port_; ivl_variable_type_t data_type; + perm_string file; + unsigned lineno; unsigned width_; unsigned signed_ : 1; diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 2f8e98f24..2d1b6d184 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -2466,13 +2466,17 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) ivl_expr_t pex = ivl_parameter_expr(par); switch (ivl_expr_type(pex)) { case IVL_EX_STRING: - fprintf(vvp_out, "P_%p .param/str \"%s\", \"%s\";\n", + fprintf(vvp_out, "P_%p .param/str \"%s\" %d %d, \"%s\";\n", par, ivl_parameter_basename(par), + ivl_file_table_index(ivl_parameter_file(par)), + ivl_parameter_lineno(par), ivl_expr_string(pex)); break; case IVL_EX_NUMBER: - fprintf(vvp_out, "P_%p .param/l \"%s\", %sC4<", + fprintf(vvp_out, "P_%p .param/l \"%s\" %d %d, %sC4<", par, ivl_parameter_basename(par), + ivl_file_table_index(ivl_parameter_file(par)), + ivl_parameter_lineno(par), ivl_expr_signed(pex)? "+":""); { const char*bits = ivl_expr_bits(pex); unsigned nbits = ivl_expr_width(pex); @@ -2483,8 +2487,10 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) fprintf(vvp_out, ">;\n"); break; case IVL_EX_REALNUM: - fprintf(vvp_out, "P_%p .param/real \"%s\", %s; value=%g\n", + fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; value=%g\n", par, ivl_parameter_basename(par), + ivl_file_table_index(ivl_parameter_file(par)), + ivl_parameter_lineno(par), draw_Cr_to_string(ivl_expr_dvalue(pex)), ivl_expr_dvalue(pex)); break; diff --git a/vvp/compile.cc b/vvp/compile.cc index a8f2dc033..e152ff7e0 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -1852,10 +1852,12 @@ void compile_thread(char*start_sym, char*flag) free(flag); } -void compile_param_logic(char*label, char*name, char*value, bool signed_flag) +void compile_param_logic(char*label, char*name, char*value, bool signed_flag, + long file_idx, long lineno) { vvp_vector4_t value4 = c4string_to_vector4(value); - vpiHandle obj = vpip_make_binary_param(name, value4, signed_flag); + vpiHandle obj = vpip_make_binary_param(name, value4, signed_flag, + file_idx, lineno); compile_vpi_symbol(label, obj); vpip_attach_to_current_scope(obj); @@ -1863,19 +1865,21 @@ void compile_param_logic(char*label, char*name, char*value, bool signed_flag) free(value); } -void compile_param_string(char*label, char*name, char*value) +void compile_param_string(char*label, char*name, char*value, + long file_idx, long lineno) { - vpiHandle obj = vpip_make_string_param(name, value); + vpiHandle obj = vpip_make_string_param(name, value, file_idx, lineno); compile_vpi_symbol(label, obj); vpip_attach_to_current_scope(obj); free(label); } -void compile_param_real(char*label, char*name, char*value) +void compile_param_real(char*label, char*name, char*value, + long file_idx, long lineno) { double dvalue = crstring_to_double(value); - vpiHandle obj = vpip_make_real_param(name, dvalue); + vpiHandle obj = vpip_make_real_param(name, dvalue, file_idx, lineno); compile_vpi_symbol(label, obj); vpip_attach_to_current_scope(obj); diff --git a/vvp/compile.h b/vvp/compile.h index b8e61a38b..74c723f9d 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -233,10 +233,13 @@ extern void compile_timescale(long units, long precision); extern void compile_vpi_symbol(const char*label, vpiHandle obj); extern void compile_vpi_lookup(vpiHandle *objref, char*label); -extern void compile_param_string(char*label, char*name, char*value); +extern void compile_param_string(char*label, char*name, char*value, + long file_idx, long lineno); extern void compile_param_logic(char*label, char*name, char*value, - bool signed_flag); -extern void compile_param_real(char*label, char*name, char*value); + bool signed_flag, + long file_idx, long lineno); +extern void compile_param_real(char*label, char*name, char*value, + long file_idx, long lineno); /* * This function schedules a lookup of an indexed label. The ref diff --git a/vvp/parse.y b/vvp/parse.y index c2521712d..c07dc451b 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -658,17 +658,17 @@ statement /* Parameter statements come in a few simple forms. The most basic is the string parameter. */ - | T_LABEL K_PARAM_STR T_STRING ',' T_STRING ';' - { compile_param_string($1, $3, $5); } + | T_LABEL K_PARAM_STR T_STRING T_NUMBER T_NUMBER',' T_STRING ';' + { compile_param_string($1, $3, $7, $4, $5); } - | T_LABEL K_PARAM_L T_STRING ',' T_SYMBOL ';' - { compile_param_logic($1, $3, $5, false); } + | T_LABEL K_PARAM_L T_STRING T_NUMBER T_NUMBER',' T_SYMBOL ';' + { compile_param_logic($1, $3, $7, false, $4, $5); } - | T_LABEL K_PARAM_L T_STRING ',' '+' T_SYMBOL ';' - { compile_param_logic($1, $3, $6, true); } + | T_LABEL K_PARAM_L T_STRING T_NUMBER T_NUMBER',' '+' T_SYMBOL ';' + { compile_param_logic($1, $3, $8, true, $4, $5); } - | T_LABEL K_PARAM_REAL T_STRING ',' T_SYMBOL ';' - { compile_param_real($1, $3, $5); } + | T_LABEL K_PARAM_REAL T_STRING T_NUMBER T_NUMBER',' T_SYMBOL ';' + { compile_param_real($1, $3, $7, $4, $5); } /* Oh and by the way, empty statements are OK as well. */ diff --git a/vvp/vpi_const.cc b/vvp/vpi_const.cc index 3f2f04856..75c96be8d 100644 --- a/vvp/vpi_const.cc +++ b/vvp/vpi_const.cc @@ -32,9 +32,6 @@ static int string_get(int code, vpiHandle ref) struct __vpiStringConst*rfp; switch (code) { - case vpiLineNo: - return 0; // Not implemented for now! - case vpiSize: rfp = (struct __vpiStringConst*)ref; @@ -247,17 +244,33 @@ vpiHandle vpip_make_string_const(char*text, bool persistent_flag) struct __vpiStringParam : public __vpiStringConst { const char*basename; struct __vpiScope* scope; + unsigned file_idx; + unsigned lineno; }; +static int string_param_get(int code, vpiHandle ref) +{ + struct __vpiStringParam*rfp = (struct __vpiStringParam*)ref; + + assert(ref->vpi_type->type_code == vpiParameter); + + if (code == vpiLineNo) { + return rfp->lineno; + } + + return string_get(code, ref); +} + static char* string_param_get_str(int code, vpiHandle obj) { struct __vpiStringParam*rfp = (struct __vpiStringParam*)obj; assert(obj->vpi_type->type_code == vpiParameter); - if (code == vpiFile) { // Not implemented for now! - return simple_set_rbuf_str(file_names[0]); + if (code == vpiFile) { + return simple_set_rbuf_str(file_names[rfp->file_idx]); } + return generic_get_str(code, &rfp->scope->base, rfp->basename, NULL); } @@ -278,7 +291,7 @@ static vpiHandle string_param_handle(int code, vpiHandle obj) static const struct __vpirt vpip_string_param_rt = { vpiParameter, - string_get, + string_param_get, string_param_get_str, string_value, 0, @@ -291,7 +304,8 @@ static const struct __vpirt vpip_string_param_rt = { }; -vpiHandle vpip_make_string_param(char*name, char*text) +vpiHandle vpip_make_string_param(char*name, char*text, + long file_idx, long lineno) { struct __vpiStringParam*obj; @@ -302,6 +316,8 @@ vpiHandle vpip_make_string_param(char*name, char*text) obj->value_len = 0; obj->basename = name; obj->scope = vpip_peek_current_scope(); + obj->file_idx = (unsigned) file_idx; + obj->lineno = (unsigned) lineno; vpip_process_string(obj); @@ -426,17 +442,33 @@ vpiHandle vpip_make_binary_const(unsigned wid, const char*bits) struct __vpiBinaryParam : public __vpiBinaryConst { const char*basename; struct __vpiScope*scope; + unsigned file_idx; + unsigned lineno; }; +static int binary_param_get(int code, vpiHandle ref) +{ + struct __vpiBinaryParam*rfp = (struct __vpiBinaryParam*)ref; + + assert(ref->vpi_type->type_code == vpiParameter); + + if (code == vpiLineNo) { + return rfp->lineno; + } + + return binary_get(code, ref); +} + static char* binary_param_get_str(int code, vpiHandle obj) { struct __vpiBinaryParam*rfp = (struct __vpiBinaryParam*)obj; assert(obj->vpi_type->type_code == vpiParameter); - if (code == vpiFile) { // Not implemented for now! - return simple_set_rbuf_str(file_names[0]); + if (code == vpiFile) { + return simple_set_rbuf_str(file_names[rfp->file_idx]); } + return generic_get_str(code, &rfp->scope->base, rfp->basename, NULL); } @@ -457,7 +489,7 @@ static vpiHandle binary_param_handle(int code, vpiHandle obj) static const struct __vpirt vpip_binary_param_rt = { vpiParameter, - binary_get, + binary_param_get, binary_param_get_str, binary_value, 0, @@ -470,7 +502,8 @@ static const struct __vpirt vpip_binary_param_rt = { }; vpiHandle vpip_make_binary_param(char*name, const vvp_vector4_t&bits, - bool signed_flag) + bool signed_flag, + long file_idx, long lineno) { struct __vpiBinaryParam*obj = new __vpiBinaryParam; @@ -480,6 +513,8 @@ vpiHandle vpip_make_binary_param(char*name, const vvp_vector4_t&bits, obj->sized_flag = 0; obj->basename = name; obj->scope = vpip_peek_current_scope(); + obj->file_idx = (unsigned) file_idx; + obj->lineno = (unsigned) lineno; return &obj->base; } @@ -654,17 +689,33 @@ vpiHandle vpip_make_real_const(double value) struct __vpiRealParam : public __vpiRealConst { const char*basename; struct __vpiScope* scope; + unsigned file_idx; + unsigned lineno; }; +static int real_param_get(int code, vpiHandle ref) +{ + struct __vpiRealParam*rfp = (struct __vpiRealParam*)ref; + + assert(ref->vpi_type->type_code == vpiParameter); + + if (code == vpiLineNo) { + return rfp->lineno; + } + + return real_get(code, ref); +} + static char* real_param_get_str(int code, vpiHandle obj) { struct __vpiRealParam*rfp = (struct __vpiRealParam*)obj; assert(obj->vpi_type->type_code == vpiParameter); - if (code == vpiFile) { // Not implemented for now! - return simple_set_rbuf_str(file_names[0]); + if (code == vpiFile) { + return simple_set_rbuf_str(file_names[rfp->file_idx]); } + return generic_get_str(code, &rfp->scope->base, rfp->basename, NULL); } @@ -685,7 +736,7 @@ static vpiHandle real_param_handle(int code, vpiHandle obj) static const struct __vpirt vpip_real_param_rt = { vpiParameter, - real_get, + real_param_get, real_param_get_str, real_value, 0, @@ -697,7 +748,8 @@ static const struct __vpirt vpip_real_param_rt = { 0 }; -vpiHandle vpip_make_real_param(char*name, double value) +vpiHandle vpip_make_real_param(char*name, double value, + long file_idx, long lineno) { struct __vpiRealParam*obj; @@ -707,6 +759,8 @@ vpiHandle vpip_make_real_param(char*name, double value) obj->value = value; obj->basename = name; obj->scope = vpip_peek_current_scope(); + obj->file_idx = (unsigned) file_idx; + obj->lineno = (unsigned) lineno; return &obj->base; } diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index bcd743014..d515a0b62 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -390,7 +390,8 @@ struct __vpiStringConst { }; vpiHandle vpip_make_string_const(char*text, bool persistent =true); -vpiHandle vpip_make_string_param(char*name, char*value); +vpiHandle vpip_make_string_param(char*name, char*value, + long file_idx, long lineno); struct __vpiBinaryConst { struct __vpiHandle base; @@ -403,7 +404,8 @@ struct __vpiBinaryConst { vpiHandle vpip_make_binary_const(unsigned wid, const char*bits); vpiHandle vpip_make_binary_param(char*name, const vvp_vector4_t&bits, - bool signed_flag); + bool signed_flag, + long file_idx, long lineno); struct __vpiDecConst { struct __vpiHandle base; @@ -419,7 +421,8 @@ struct __vpiRealConst { }; vpiHandle vpip_make_real_const(double value); -vpiHandle vpip_make_real_param(char*name, double value); +vpiHandle vpip_make_real_param(char*name, double value, + long file_idx, long lineno); /* * This one looks like a constant, but really is a vector in the current