diff --git a/Module.cc b/Module.cc index b577410417..7c2d14dfb0 100644 --- a/Module.cc +++ b/Module.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2016 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 @@ -36,9 +36,6 @@ Module::Module(LexicalScope*parent, perm_string n) program_block = false; uc_drive = UCD_NONE; timescale_warn_done = false; - time_unit = 0; - time_precision = 0; - time_from_timescale = false; } Module::~Module() diff --git a/Module.h b/Module.h index f142a761d8..66c60af4f7 100644 --- a/Module.h +++ b/Module.h @@ -1,7 +1,7 @@ #ifndef IVL_Module_H #define IVL_Module_H /* - * Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2016 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 @@ -121,10 +121,6 @@ class Module : public PScopeExtra, public LineInfo { map attributes; - /* These are the timescale for this module. The default is - set by the `timescale directive. */ - int time_unit, time_precision; - bool time_from_timescale; bool timescale_warn_done; /* The module has a list of generate schemes that appear in diff --git a/PScope.cc b/PScope.cc index 9add20a1b5..0b6a132d3e 100644 --- a/PScope.cc +++ b/PScope.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008,2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008,2016 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 @@ -24,14 +24,21 @@ bool LexicalScope::var_init_needs_explicit_lifetime() const return false; } -PScope::PScope(perm_string n, LexicalScope*parent) -: LexicalScope(parent), name_(n) +PWire* LexicalScope::wires_find(perm_string name) { + map::const_iterator cur = wires.find(name); + if (cur == wires.end()) + return 0; + else + return (*cur).second; } -PScope::PScope(perm_string n) -: LexicalScope(0), name_(n) +PScope::PScope(perm_string n, LexicalScope*parent) +: LexicalScope(parent), name_(n) { + time_unit = 0; + time_precision = 0; + time_from_timescale = false; } PScope::~PScope() @@ -41,25 +48,11 @@ PScope::~PScope() delete it->second; } -PWire* LexicalScope::wires_find(perm_string name) -{ - map::const_iterator cur = wires.find(name); - if (cur == wires.end()) - return 0; - else - return (*cur).second; -} - PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent) : PScope(n, parent) { } -PScopeExtra::PScopeExtra(perm_string n) -: PScope(n) -{ -} - PScopeExtra::~PScopeExtra() { } diff --git a/PScope.h b/PScope.h index 6ef04b1f14..7e4fd6fa38 100644 --- a/PScope.h +++ b/PScope.h @@ -159,12 +159,17 @@ class PScope : public LexicalScope { // modules do not nest in Verilog, the parent must be nil for // modules. Scopes for tasks and functions point to their // containing module. - PScope(perm_string name, LexicalScope*parent); - explicit PScope(perm_string name); + explicit PScope(perm_string name, LexicalScope*parent =0); virtual ~PScope(); perm_string pscope_name() const { return name_; } + /* These are the timescale for this scope. The default is + set by the `timescale directive or, in SystemVerilog, + by timeunit and timeprecision statements. */ + int time_unit, time_precision; + bool time_from_timescale; + protected: bool elaborate_sig_wires_(Design*des, NetScope*scope) const; @@ -182,14 +187,13 @@ class PScope : public LexicalScope { class PScopeExtra : public PScope { public: - PScopeExtra(perm_string, LexicalScope*parent); - explicit PScopeExtra(perm_string); + explicit PScopeExtra(perm_string, LexicalScope*parent =0); ~PScopeExtra(); /* Task definitions within this module */ std::map tasks; std::map funcs; - /* class definitions within this module. */ + /* Class definitions within this module. */ std::map classes; /* This is the lexical order of the classes, and is used by elaboration to choose an elaboration order. */ diff --git a/elab_scope.cc b/elab_scope.cc index 6f37e63d73..73834249c0 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -54,6 +54,15 @@ # include # include "ivl_assert.h" + +void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope) +{ + scope->time_unit(pscope->time_unit); + scope->time_precision(pscope->time_precision); + scope->time_from_timescale(pscope->time_from_timescale); + des->set_precision(pscope->time_precision); +} + typedef map::const_iterator mparm_it_t; static void collect_parm_item_(Design*des, NetScope*scope, perm_string name, @@ -523,6 +532,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) class_scope->set_class_def(use_class); use_class->set_class_scope(class_scope); use_class->set_definition_scope(scope); + set_scope_timescale(des, class_scope, pclass); // Collect the properties, elaborate them, and add them to the // elaborated class definition. @@ -654,8 +664,10 @@ static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task) task_scope->is_auto(task->is_auto()); task_scope->set_line(task); - if (scope==0) + if (scope==0) { + set_scope_timescale(des, task_scope, task); des->add_root_task(task_scope, task); + } if (debug_scopes) { cerr << task->get_fileline() << ": elaborate_scope_task: " @@ -719,8 +731,10 @@ static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task) task_scope->is_auto(task->is_auto()); task_scope->set_line(task); - if (scope==0) + if (scope==0) { + set_scope_timescale(des, task_scope, task); des->add_root_task(task_scope, task); + } if (debug_scopes) { cerr << task->get_fileline() << ": elaborate_scope_func: " @@ -1750,11 +1764,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s instances[idx] = my_scope; - // Set time units and precision. - my_scope->time_unit(mod->time_unit); - my_scope->time_precision(mod->time_precision); - my_scope->time_from_timescale(mod->time_from_timescale); - des->set_precision(mod->time_precision); + set_scope_timescale(des, my_scope, mod); // Look for module parameter replacements. The "replace" map // maps parameter name to replacement expression that is diff --git a/elaborate.cc b/elaborate.cc index 19bfd74e01..3af46e3407 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -36,6 +36,7 @@ # include "PEvent.h" # include "PGenerate.h" # include "PPackage.h" +# include "PScope.h" # include "PSpec.h" # include "netlist.h" # include "netenum.h" @@ -50,6 +51,9 @@ # include "ivl_assert.h" +// Implemented in elab_scope.cc +extern void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope); + void PGate::elaborate(Design*, NetScope*) const { cerr << "internal error: what kind of gate? " << @@ -6215,6 +6219,7 @@ Design* elaborate(listroots) ivl_assert(*pac->second, pac->first == pac->second->pscope_name()); NetScope*scope = des->make_package_scope(pac->first); scope->set_line(pac->second); + set_scope_timescale(des, scope, pac->second); elaborator_work_item_t*es = new elaborate_package_t(des, scope, pac->second); des->elaboration_work_list.push_back(es); @@ -6251,11 +6256,7 @@ Design* elaborate(listroots) // Collect some basic properties of this scope from the // Module definition. scope->set_line(rmod); - scope->time_unit(rmod->time_unit); - scope->time_precision(rmod->time_precision); - scope->time_from_timescale(rmod->time_from_timescale); - des->set_precision(rmod->time_precision); - + set_scope_timescale(des, scope, rmod); // Save this scope, along with its definition, in the // "root_elems" list for later passes. diff --git a/pform.cc b/pform.cc index 5b163f9639..0ab187a725 100644 --- a/pform.cc +++ b/pform.cc @@ -345,6 +345,28 @@ static PScopeExtra* find_nearest_scopex(LexicalScope*scope) return scopex; } +/* + * Set the local time unit/precision to the global value. + */ +static void pform_set_scope_timescale(PScope*scope, const struct vlltype&loc) +{ + scope->time_unit = pform_time_unit; + scope->time_precision = pform_time_prec; + /* If we have a timescale file then the time information is from + * a timescale directive. */ + scope->time_from_timescale = pform_timescale_file != 0; + + if (warn_timescale && (lexical_scope == 0) && pform_timescale_file + && (strcmp(pform_timescale_file, loc.text) != 0)) { + + cerr << loc.get_fileline() << ": warning: " + << "timescale for " << scope->pscope_name() + << " inherited from another file." << endl; + cerr << pform_timescale_file << ":" << pform_timescale_line + << ": ...: The inherited timescale is here." << endl; + } +} + PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name, LexicalScope::lifetime_t lifetime) { @@ -352,6 +374,8 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name, class_scope->default_lifetime = find_lifetime(lifetime); FILE_NAME(class_scope, loc); + pform_set_scope_timescale(class_scope, loc); + PScopeExtra*scopex = find_nearest_scopex(lexical_scope); assert(!pform_cur_generate); @@ -384,6 +408,8 @@ PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name, pkg_scope->default_lifetime = find_lifetime(lifetime); FILE_NAME(pkg_scope, loc); + pform_set_scope_timescale(pkg_scope, loc); + lexical_scope = pkg_scope; return pkg_scope; } @@ -400,6 +426,8 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, task->default_lifetime = default_lifetime; FILE_NAME(task, loc); + pform_set_scope_timescale(task, loc); + PScopeExtra*scopex = find_nearest_scopex(lexical_scope); if ((scopex == 0) && !gn_system_verilog()) { cerr << task->get_fileline() << ": error: task declarations " @@ -455,6 +483,8 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name, func->default_lifetime = default_lifetime; FILE_NAME(func, loc); + pform_set_scope_timescale(func, loc); + PScopeExtra*scopex = find_nearest_scopex(lexical_scope); if ((scopex == 0) && (generation_flag < GN_VER2005_SV)) { cerr << func->get_fileline() << ": error: function declarations " @@ -1200,17 +1230,12 @@ void pform_startmodule(const struct vlltype&loc, const char*name, cur_module->is_interface = is_interface; cur_module->default_lifetime = find_lifetime(lifetime); - /* Set the local time unit/precision to the global value. */ - cur_module->time_unit = pform_time_unit; - cur_module->time_precision = pform_time_prec; + FILE_NAME(cur_module, loc); + + pform_set_scope_timescale(cur_module, loc); tu_local_flag = tu_global_flag; tp_local_flag = tp_global_flag; - /* If we have a timescale file then the time information is from - * a timescale directive. */ - cur_module->time_from_timescale = pform_timescale_file != 0; - - FILE_NAME(cur_module, loc); cur_module->library_flag = pform_library_flag; pform_cur_module.push_front(cur_module); @@ -1221,15 +1246,6 @@ void pform_startmodule(const struct vlltype&loc, const char*name, zero. That's just the way it is, thanks to the standard. */ scope_generate_counter = 1; - if (warn_timescale && pform_timescale_file - && (strcmp(pform_timescale_file,loc.text) != 0)) { - - cerr << cur_module->get_fileline() << ": warning: " - << "timescale for " << name - << " inherited from another file." << endl; - cerr << pform_timescale_file << ":" << pform_timescale_line - << ": ...: The inherited timescale is here." << endl; - } pform_bind_attributes(cur_module->attributes, attr); } diff --git a/vpi/sys_display.c b/vpi/sys_display.c index 7654b7c0a5..dc04182fd6 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -2055,12 +2055,7 @@ static PLI_INT32 sys_printtimescale_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) item = vpi_scan(argv); vpi_free_object(argv); } - - if (vpi_get(vpiType, item) != vpiModule) { - scope = vpi_handle(vpiModule, item); - } else { - scope = item; - } + scope = sys_func_module(item); vpi_printf("Time scale of (%s) is ", vpi_get_str(vpiFullName, item)); vpi_printf("%s / ", pts_convert(vpi_get(vpiTimeUnit, scope))); diff --git a/vpi/sys_priv.c b/vpi/sys_priv.c index 08529ccede..1d5e977bbc 100644 --- a/vpi/sys_priv.c +++ b/vpi/sys_priv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2016 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 @@ -229,15 +229,18 @@ unsigned is_string_obj(vpiHandle obj) /* - * Find the enclosing module. + * Find the enclosing module. If there is no enclosing module (which can be + * the case in SystemVerilog), return the highest enclosing scope. */ vpiHandle sys_func_module(vpiHandle obj) { assert(obj); while (vpi_get(vpiType, obj) != vpiModule) { - obj = vpi_handle(vpiScope, obj); - assert(obj); + vpiHandle scope = vpi_handle(vpiScope, obj); + if (scope == 0) + break; + obj = scope; } return obj; diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 803baf105f..9cac4c796a 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2016 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 @@ -1409,6 +1409,9 @@ static vpiHandle PV_get_handle(int code, vpiHandle ref) case vpiParent: return rfp->parent; + case vpiScope: + return vpi_handle(vpiScope, rfp->parent); + case vpiModule: return vpi_handle(vpiModule, rfp->parent); }