Add packages and their own scope.

This makes <pkg>::<name> work properly, and also makes the
package descriptions available through VPI.
This commit is contained in:
Stephen Williams 2013-02-17 14:42:07 -08:00
parent 97f3a01dc5
commit 60cb78e4ab
23 changed files with 255 additions and 60 deletions

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 1998-2012 Stephen Williams <steve@icarus.com>
* Copyright CERN 2013 / 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
@ -305,12 +306,18 @@ const verireal& PEFNumber::value() const
}
PEIdent::PEIdent(const pform_name_t&that)
: path_(that), no_implicit_sig_(false)
: package_(0), path_(that), no_implicit_sig_(false)
{
}
PEIdent::PEIdent(perm_string s, bool no_implicit_sig)
: no_implicit_sig_(no_implicit_sig)
: package_(0), no_implicit_sig_(no_implicit_sig)
{
path_.push_back(name_component_t(s));
}
PEIdent::PEIdent(PPackage*pkg, perm_string s)
: package_(pkg), no_implicit_sig_(true)
{
path_.push_back(name_component_t(s));
}

View File

@ -2,6 +2,7 @@
#define __PExpr_H
/*
* Copyright (c) 1998-2011 Stephen Williams <steve@icarus.com>
* Copyright CERN 2013 / 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
@ -33,6 +34,7 @@ class LexicalScope;
class NetNet;
class NetExpr;
class NetScope;
class PPackage;
/*
* The PExpr class hierarchy supports the description of
@ -286,6 +288,7 @@ class PEIdent : public PExpr {
public:
explicit PEIdent(perm_string, bool no_implicit_sig=false);
explicit PEIdent(PPackage*pkg, perm_string name);
explicit PEIdent(const pform_name_t&);
~PEIdent();
@ -329,6 +332,7 @@ class PEIdent : public PExpr {
const pform_name_t& path() const { return path_; }
private:
PPackage*package_;
pform_name_t path_;
bool no_implicit_sig_;

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2012 Picture Elements, Inc.
* Stephen Williams (steve@icarus.com)
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / 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

View File

@ -2,6 +2,7 @@
#define __PPackage_H
/*
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / 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,6 +37,8 @@ class PPackage : public PScopeExtra, public LineInfo {
explicit PPackage (perm_string name, LexicalScope*parent);
~PPackage();
bool elaborate_scope(Design*des, NetScope*scope);
void pform_dump(std::ostream&out) const;
};

View File

@ -1643,10 +1643,18 @@ void NetEUnary::dump(ostream&o) const
void Design::dump(ostream&o) const
{
o << "DESIGN TIME PRECISION: 10e" << get_precision() << endl;
o << "PACKAGES:" << endl;
for (map<perm_string,NetScope*>::const_iterator cur = packages_.begin()
; cur != packages_.end() ; ++cur) {
cur->second->dump(o);
}
o << "SCOPES:" << endl;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); ++ scope )
scope != root_scopes_.end(); ++ scope ) {
(*scope)->dump(o);
}
o << "ELABORATED NODES:" << endl;

View File

@ -24,6 +24,7 @@
# include <climits>
# include "compiler.h"
# include "PPackage.h"
# include "pform.h"
# include "netlist.h"
# include "netclass.h"
@ -2410,7 +2411,14 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
const NetExpr*ex1, *ex2;
NetScope*found_in = symbol_search(this, des, scope, path_, net, par, eve,
NetScope*use_scope = scope;
if (package_) {
use_scope = des->find_package(package_->pscope_name());
ivl_assert(*this, use_scope);
}
NetScope*found_in = symbol_search(this, des, use_scope, path_,
net, par, eve,
ex1, ex2);
// If there is a part/bit select expression, then process it
@ -2610,7 +2618,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
NetEvent* eve = 0;
const NetExpr*ex1, *ex2;
/* NetScope*found_in = */ symbol_search(this, des, scope, path_,
NetScope*use_scope = scope;
if (package_) {
use_scope = des->find_package(package_->pscope_name());
ivl_assert(*this, use_scope);
}
/* NetScope*found_in = */ symbol_search(this, des, use_scope, path_,
net, par, eve,
ex1, ex2);
@ -2718,7 +2732,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
if (debug_elaborate)
cerr << get_fileline() << ": PEIdent::elaborate_expr: path_=" << path_ << endl;
NetScope*found_in = symbol_search(this, des, scope, path_,
NetScope*use_scope = scope;
if (package_) {
use_scope = des->find_package(package_->pscope_name());
ivl_assert(*this, use_scope);
}
NetScope*found_in = symbol_search(this, des, use_scope, path_,
net, par, eve,
ex1, ex2);

View File

@ -39,6 +39,7 @@
# include "PClass.h"
# include "PGate.h"
# include "PGenerate.h"
# include "PPackage.h"
# include "PTask.h"
# include "PWire.h"
# include "Statement.h"
@ -495,6 +496,18 @@ class generate_schemes_work_item_t : public elaborator_work_item_t {
Module*mod_;
};
bool PPackage::elaborate_scope(Design*des, NetScope*scope)
{
if (debug_scopes) {
cerr << get_fileline() << ": debug: Elaborate package scope "
<< scope_path(scope) << "." << endl;
}
collect_scope_parameters_(des, scope, parameters);
return true;
}
bool Module::elaborate_scope(Design*des, NetScope*scope,
const replace_t&replacements)
{

View File

@ -33,6 +33,7 @@
# include "pform.h"
# include "PEvent.h"
# include "PGenerate.h"
# include "PPackage.h"
# include "PSpec.h"
# include "netlist.h"
# include "netvector.h"
@ -4860,6 +4861,25 @@ struct root_elem {
NetScope *scope;
};
class elaborate_package_t : public elaborator_work_item_t {
public:
elaborate_package_t(Design*d, NetScope*scope, PPackage*p)
: elaborator_work_item_t(d), scope_(scope), package_(p)
{ }
~elaborate_package_t() { }
virtual void elaborate_runrun()
{
if (! package_->elaborate_scope(des, scope_))
des->errors += 1;
}
private:
NetScope*scope_;
PPackage*package_;
};
class elaborate_root_scope_t : public elaborator_work_item_t {
public:
elaborate_root_scope_t(Design*des__, NetScope*scope, Module*rmod)
@ -5022,6 +5042,18 @@ Design* elaborate(list<perm_string>roots)
// module and elaborate what I find.
Design*des = new Design;
// Elaborate the packages. Package elaboration is simpler
// because there are fewer sub-scopes involved.
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
; pac != pform_packages.end() ; ++ pac) {
NetScope*scope = des->make_package_scope(pac->first);
scope->set_line(pac->second);
elaborator_work_item_t*es = new elaborate_package_t(des, scope, pac->second);
des->elaboration_work_list.push_back(es);
}
// Scan the root modules by name, and elaborate their scopes.
for (list<perm_string>::const_iterator root = roots.begin()
; root != roots.end() ; ++ root ) {

View File

@ -353,7 +353,8 @@ typedef enum ivl_scope_type_e {
IVL_SCT_TASK = 2,
IVL_SCT_BEGIN = 3,
IVL_SCT_FORK = 4,
IVL_SCT_GENERATE= 5
IVL_SCT_GENERATE= 5,
IVL_SCT_PACKAGE = 6
} ivl_scope_type_t;
/* Signals (ivl_signal_t) that are ports into the scope that contains

View File

@ -47,8 +47,12 @@ struct ivl_design_s {
ivl_process_t threads_;
ivl_scope_t *roots_;
unsigned nroots_;
// Keep arrays of root scopes.
std::vector<ivl_scope_t> packages;
std::vector<ivl_scope_t> roots;
// This is used to implement the ivl_design_roots function.
std::vector<ivl_scope_t> root_scope_list;
// Keep an array of constants objects.
std::valarray<ivl_net_const_t> consts;

View File

@ -119,14 +119,39 @@ NetScope* Design::find_root_scope()
return root_scopes_.front();
}
list<NetScope*> Design::find_root_scopes()
list<NetScope*> Design::find_root_scopes() const
{
return root_scopes_;
}
const list<NetScope*> Design::find_root_scopes() const
NetScope* Design::make_package_scope(perm_string name)
{
return root_scopes_;
NetScope*scope;
scope = new NetScope(0, hname_t(name), NetScope::PACKAGE, false, false);
scope->set_module_name(scope->basename());
packages_[name] = scope;
return scope;
}
NetScope* Design::find_package(perm_string name) const
{
map<perm_string,NetScope*>::const_iterator cur = packages_.find(name);
if (cur == packages_.end())
return 0;
return cur->second;
}
list<NetScope*> Design::find_package_scopes() const
{
list<NetScope*>res;
for (map<perm_string,NetScope*>::const_iterator cur = packages_.begin()
; cur != packages_.end() ; ++cur) {
res.push_back (cur->second);
}
return res;
}
/*

View File

@ -60,7 +60,7 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bo
time_unit_ = 0;
time_prec_ = 0;
time_from_timescale_ = false;
assert(t == MODULE);
assert(t==MODULE || t==PACKAGE);
}
switch (t) {
@ -71,6 +71,7 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bo
func_ = 0;
break;
case NetScope::MODULE:
case NetScope::PACKAGE:
module_name_ = perm_string();
break;
default: /* BEGIN_END and FORK_JOIN, do nothing */
@ -301,8 +302,7 @@ void NetScope::print_type(ostream&stream) const
stream << "function";
break;
case MODULE:
stream << "module <" << (module_name_ ? module_name_.str() : "")
<< "> instance";
stream << "module <" << module_name_ << "> instance";
break;
case TASK:
stream << "task";
@ -310,6 +310,9 @@ void NetScope::print_type(ostream&stream) const
case GENBLOCK:
stream << "generate block";
break;
case PACKAGE:
stream << "package " << module_name_;
break;
}
}
@ -358,13 +361,13 @@ const NetFuncDef* NetScope::func_def() const
void NetScope::set_module_name(perm_string n)
{
assert(type_ == MODULE);
module_name_ = n; /* NOTE: n must have been permallocated. */
assert(type_==MODULE || type_==PACKAGE);
module_name_ = n;
}
perm_string NetScope::module_name() const
{
assert(type_ == MODULE);
assert(type_==MODULE || type_==PACKAGE);
return module_name_;
}

View File

@ -2,6 +2,7 @@
#define __netlist_H
/*
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / 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
@ -763,7 +764,7 @@ class NetNet : public NetObj, public PortType {
class NetScope : public Attrib {
public:
enum TYPE { MODULE, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK };
enum TYPE { MODULE, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK, PACKAGE };
/* Create a new scope, and attach it to the given parent. The
name is expected to have been permallocated. */
@ -4281,9 +4282,10 @@ class Design {
NetScope* make_root_scope(perm_string name, bool program_block);
NetScope* find_root_scope();
list<NetScope*> find_root_scopes();
std::list<NetScope*> find_root_scopes() const;
const list<NetScope*> find_root_scopes() const;
NetScope* make_package_scope(perm_string name);
std::list<NetScope*> find_package_scopes() const;
/* Attempt to set the precision to the specified value. If the
precision is already more precise, the keep the precise
@ -4304,6 +4306,9 @@ class Design {
NetScope* find_scope(const hname_t&path) const;
NetScope* find_scope(NetScope*, const hname_t&name,
NetScope::TYPE type = NetScope::MODULE) const;
NetScope* find_package(perm_string name) const;
// Note: Try to remove these versions of find_scope. Avoid
// using these in new code, use the above forms (or
// symbol_search) instead.
@ -4372,6 +4377,10 @@ class Design {
// tree and per-hop searches for me.
list<NetScope*>root_scopes_;
// Keep a map of all the elaborated packages. Note that
// packages do not nest.
std::map<perm_string,NetScope*>packages_;
// List the nodes in the design.
NetNode*nodes_;
// These are in support of the node functor iterator.

View File

@ -1,8 +1,8 @@
%{
/*
* Copyright (c) 1998-2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2013 / 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
@ -2962,6 +2962,9 @@ expr_primary
delete $1;
}
| IDENTIFIER K_SCOPE_RES IDENTIFIER
{ $$ = pform_package_ident(@3, $1, $3); }
/* An identifier followed by an expression list in parentheses is a
function call. If a system identifier, then a system function
call. */

View File

@ -207,6 +207,9 @@ extern void pform_end_package_declaration(const struct vlltype&loc);
extern void pform_package_import(const struct vlltype&loc,
const char*pkg_name, const char*ident);
extern PExpr* pform_package_ident(const struct vlltype&loc,
const char*pkg_name, const char*ident);
/*
* Enter/exit name scopes. The push_scope function pushes the scope
* name string onto the scope hierarchy. The pop pulls it off and

View File

@ -304,6 +304,8 @@ void PENumber::dump(ostream&out) const
void PEIdent::dump(ostream&out) const
{
if (package_)
out << package_->pscope_name() << "::";
out << path_;
}

View File

@ -111,3 +111,22 @@ void pform_package_import(const struct vlltype&, const char*pkg_name, const char
}
}
}
PExpr* pform_package_ident(const struct vlltype&loc,
const char*pkg_name, const char*ident_name)
{
perm_string use_name = lex_strings.make(pkg_name);
map<perm_string,PPackage*>::const_iterator pcur = pform_packages.find(use_name);
if (pcur == pform_packages.end()) {
ostringstream msg;
msg << "Package " << pkg_name << " not found." << ends;
VLerror(msg.str().c_str());
return 0;
}
assert(pcur->second);
perm_string use_ident = lex_strings.make(ident_name);
PEIdent*tmp = new PEIdent(pcur->second, use_ident);
FILE_NAME(tmp, loc);
return tmp;
}

View File

@ -43,6 +43,7 @@
EXTERN_C_START
/********* OBJECT TYPES ***********/
#define vpiPackage 600
#define vpiLongIntVar 610
#define vpiShortIntVar 611
#define vpiIntVar 612

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / 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
@ -73,16 +74,24 @@ extern "C" ivl_scope_t ivl_design_root(ivl_design_t des)
cerr << "ANACHRONISM: ivl_design_root called. "
"Use ivl_design_roots instead." << endl;
assert (des->nroots_);
return des->roots_[0];
assert (des->roots.size() > 0);
return des->roots[0];
}
extern "C" void ivl_design_roots(ivl_design_t des, ivl_scope_t **scopes,
unsigned int *nscopes)
{
assert (nscopes && scopes);
*scopes = &des->roots_[0];
*nscopes = des->nroots_;
if (des->root_scope_list.size() == 0) {
des->root_scope_list.resize(des->packages.size() + des->roots.size());
for (size_t idx = 0 ; idx < des->packages.size() ; idx += 1)
des->root_scope_list[idx] = des->packages[idx];
for (size_t idx = 0 ; idx < des->roots.size() ; idx += 1)
des->root_scope_list[idx+des->packages.size()] = des->roots[idx];
}
*scopes = &des->root_scope_list[0];
*nscopes = des->root_scope_list.size();
}
extern "C" int ivl_design_time_precision(ivl_design_t des)

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / 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
@ -234,10 +235,21 @@ ivl_scope_t dll_target::find_scope(ivl_design_s &des, const NetScope*cur)
{
assert(cur);
// If the scope is a PACKAGE, then it is a special kind of
// root scope and it in the packages array instead.
if (cur->type() == NetScope::PACKAGE) {
perm_string cur_name = cur->module_name();
for (size_t idx = 0 ; idx < des.packages.size() ; idx += 1) {
if (des.packages[idx]->name_ = cur_name)
return des.packages[idx];
}
return 0;
}
ivl_scope_t scope = 0;
for (unsigned i = 0; i < des.nroots_ && scope == 0; i += 1) {
assert(des.roots_[i]);
scope = find_scope_from_root(des.roots_[i], cur);
for (unsigned i = 0; i < des.roots.size() && scope == 0; i += 1) {
assert(des.roots[i]);
scope = find_scope_from_root(des.roots[i], cur);
}
return scope;
}
@ -537,7 +549,7 @@ void dll_target::add_root(ivl_design_s &des__, const NetScope *s)
root_->lpm_ = 0;
root_->def = 0;
make_scope_parameters(root_, s);
root_->type_ = IVL_SCT_MODULE;
root_->type_ = s->type()==NetScope::PACKAGE? IVL_SCT_PACKAGE : IVL_SCT_MODULE;
root_->tname_ = root_->name_;
root_->time_precision = s->time_precision();
root_->time_units = s->time_unit();
@ -545,29 +557,26 @@ void dll_target::add_root(ivl_design_s &des__, const NetScope *s)
root_->attr = fill_in_attributes(s);
root_->is_auto = 0;
root_->is_cell = s->is_cell();
root_->ports = s->module_port_nets();
if (root_->ports > 0) {
root_->u_.net = new NetNet*[root_->ports];
for (unsigned idx = 0; idx < root_->ports; idx += 1) {
root_->u_.net[idx] = s->module_port_net(idx);
if (s->type()==NetScope::MODULE) {
root_->ports = s->module_port_nets();
if (root_->ports > 0) {
root_->u_.net = new NetNet*[root_->ports];
for (unsigned idx = 0; idx < root_->ports; idx += 1) {
root_->u_.net[idx] = s->module_port_net(idx);
}
}
}
root_->module_ports_info = s->module_port_info();
root_->module_ports_info = s->module_port_info();
des__.nroots_++;
if (des__.roots_)
des__.roots_ = (ivl_scope_t *)realloc(des__.roots_,
des__.nroots_ *
sizeof(ivl_scope_t));
else
des__.roots_ = (ivl_scope_t *)malloc(des__.nroots_ *
sizeof(ivl_scope_t));
des__.roots_[des__.nroots_ - 1] = root_;
des__.roots.push_back(root_);
} else {
root_->ports = 0;
des__.packages.push_back(root_);
}
}
bool dll_target::start_design(const Design*des)
{
list<NetScope *> root_scopes;
const char*dll_path_ = des->get_flag("DLL");
dll_ = ivl_dlopen(dll_path_);
@ -591,8 +600,6 @@ bool dll_target::start_design(const Design*des)
// Initialize the design object.
des_.self = des;
des_.time_precision = des->get_precision();
des_.nroots_ = 0;
des_.roots_ = NULL;
des_.disciplines.resize(disciplines.size());
unsigned idx = 0;
@ -603,11 +610,17 @@ bool dll_target::start_design(const Design*des)
}
assert(idx == des_.disciplines.size());
root_scopes = des->find_root_scopes();
for (list<NetScope*>::const_iterator scop = root_scopes.begin();
scop != root_scopes.end(); ++ scop )
list<NetScope *> package_scopes = des->find_package_scopes();
for (list<NetScope*>::const_iterator scop = package_scopes.begin();
scop != package_scopes.end(); ++ scop ) {
add_root(des_, *scop);
}
list<NetScope *> root_scopes = des->find_root_scopes();
for (list<NetScope*>::const_iterator scop = root_scopes.begin();
scop != root_scopes.end(); ++ scop ) {
add_root(des_, *scop);
}
target_ = (target_design_f)ivl_dlsym(dll_, LU "target_design" TU);
if (target_ == 0) {
@ -2267,9 +2280,9 @@ void dll_target::scope(const NetScope*net)
if (net->parent() == 0) {
unsigned i;
scop = NULL;
for (i = 0; i < des_.nroots_ && scop == NULL; i++) {
if (strcmp(des_.roots_[i]->name_, net->basename()) == 0)
scop = des_.roots_[i];
for (i = 0; i < des_.roots.size() && scop == NULL; i++) {
if (strcmp(des_.roots[i]->name_, net->basename()) == 0)
scop = des_.roots[i];
}
assert(scop);
@ -2297,6 +2310,9 @@ void dll_target::scope(const NetScope*net)
scop->is_cell = net->is_cell();
switch (net->type()) {
case NetScope::PACKAGE:
cerr << "?:?" << ": internal error: "
<< "Package scopes should not have parents." << endl;
case NetScope::MODULE:
scop->type_ = IVL_SCT_MODULE;
scop->tname_ = net->module_name();

View File

@ -1701,8 +1701,13 @@ int target_design(ivl_design_t des)
ivl_design_roots(des, &root_scopes, &nroot);
for (idx = 0 ; idx < nroot ; idx += 1) {
fprintf(out, "root module = %s;\n",
ivl_scope_name(root_scopes[idx]));
if (ivl_scope_type(root_scopes[idx]) == IVL_SCT_PACKAGE) {
fprintf(out, "package = %s;\n",
ivl_scope_name(root_scopes[idx]));
} else {
fprintf(out, "root module = %s;\n",
ivl_scope_name(root_scopes[idx]));
}
show_scope(root_scopes[idx], 0);
}

View File

@ -2145,6 +2145,7 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
case IVL_SCT_BEGIN: type = "begin"; break;
case IVL_SCT_FORK: type = "fork"; break;
case IVL_SCT_GENERATE: type = "generate"; break;
case IVL_SCT_PACKAGE: type = "package"; break;
default: type = "?"; assert(0);
}

View File

@ -346,6 +346,11 @@ struct vpiScopeModule : public __vpiScope {
int get_type_code(void) const { return vpiModule; }
};
struct vpiScopePackage : public __vpiScope {
inline vpiScopePackage() { }
int get_type_code(void) const { return vpiPackage; }
};
struct vpiScopeTask : public __vpiScope {
inline vpiScopeTask() { }
int get_type_code(void) const { return vpiTask; }
@ -424,6 +429,8 @@ compile_scope_decl(char*label, char*type, char*name, char*tname,
scope = new vpiScopeBegin;
} else if (strcmp(base_type,"generate") == 0) {
scope = new vpiScopeBegin;
} else if (strcmp(base_type,"package") == 0) {
scope = new vpiScopePackage;
} else {
scope = new vpiScopeModule;
assert(0);