Support timescales in design units that aren't inside a module.
SystemVerilog allows tasks, functions, and classes to be defined at the
root level or inside packages, so we can't rely on an enclosing module
being present to provide the timescale.
(cherry picked from commit 7bed181f68)
This commit is contained in:
parent
07623bef2e
commit
9b55a3d67f
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2010 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
|
||||
|
|
@ -35,9 +35,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()
|
||||
|
|
|
|||
6
Module.h
6
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<perm_string,PExpr*> 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
|
||||
|
|
|
|||
37
PScope.cc
37
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,23 +24,6 @@ bool LexicalScope::var_init_needs_explicit_lifetime() const
|
|||
return false;
|
||||
}
|
||||
|
||||
PScope::PScope(perm_string n, LexicalScope*parent)
|
||||
: LexicalScope(parent), name_(n)
|
||||
{
|
||||
}
|
||||
|
||||
PScope::PScope(perm_string n)
|
||||
: LexicalScope(0), name_(n)
|
||||
{
|
||||
}
|
||||
|
||||
PScope::~PScope()
|
||||
{
|
||||
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
|
||||
it != typedefs.end(); ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
PWire* LexicalScope::wires_find(perm_string name)
|
||||
{
|
||||
map<perm_string,PWire*>::const_iterator cur = wires.find(name);
|
||||
|
|
@ -50,13 +33,23 @@ PWire* LexicalScope::wires_find(perm_string name)
|
|||
return (*cur).second;
|
||||
}
|
||||
|
||||
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
|
||||
: PScope(n, parent)
|
||||
PScope::PScope(perm_string n, LexicalScope*parent)
|
||||
: LexicalScope(parent), name_(n)
|
||||
{
|
||||
time_unit = 0;
|
||||
time_precision = 0;
|
||||
time_from_timescale = false;
|
||||
}
|
||||
|
||||
PScopeExtra::PScopeExtra(perm_string n)
|
||||
: PScope(n)
|
||||
PScope::~PScope()
|
||||
{
|
||||
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
|
||||
it != typedefs.end(); ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
|
||||
: PScope(n, parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
14
PScope.h
14
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);
|
||||
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);
|
||||
PScopeExtra(perm_string);
|
||||
explicit PScopeExtra(perm_string, LexicalScope*parent =0);
|
||||
~PScopeExtra();
|
||||
|
||||
/* Task definitions within this module */
|
||||
std::map<perm_string,PTask*> tasks;
|
||||
std::map<perm_string,PFunction*> funcs;
|
||||
/* class definitions within this module. */
|
||||
/* Class definitions within this module. */
|
||||
std::map<perm_string,PClass*> classes;
|
||||
/* This is the lexical order of the classes, and is used by
|
||||
elaboration to choose an elaboration order. */
|
||||
|
|
|
|||
|
|
@ -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 <cassert>
|
||||
# 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<perm_string,LexicalScope::param_expr_t>::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
|
||||
|
|
|
|||
11
elaborate.cc
11
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? " <<
|
||||
|
|
@ -6238,6 +6242,7 @@ Design* elaborate(list<perm_string>roots)
|
|||
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);
|
||||
|
|
@ -6274,11 +6279,7 @@ Design* elaborate(list<perm_string>roots)
|
|||
// 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.
|
||||
|
|
|
|||
50
pform.cc
50
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 "
|
||||
|
|
@ -1195,17 +1225,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);
|
||||
|
|
@ -1216,15 +1241,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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1971,12 +1971,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)));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue