Merge branch 'work13b'
This commit is contained in:
commit
256c0986bb
25
PExpr.cc
25
PExpr.cc
|
|
@ -174,7 +174,7 @@ PEBShift::~PEBShift()
|
|||
}
|
||||
|
||||
PECallFunction::PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms)
|
||||
: path_(n), parms_(parms)
|
||||
: package_(0), path_(n), parms_(parms)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -186,19 +186,29 @@ static pform_name_t pn_from_ps(perm_string n)
|
|||
return tmp;
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(PPackage*pkg, perm_string n, const list<PExpr *> &parms)
|
||||
: package_(pkg), path_(pn_from_ps(n)), parms_(parms.size())
|
||||
{
|
||||
int tmp_idx = 0;
|
||||
assert(parms_.size() == parms.size());
|
||||
for (list<PExpr*>::const_iterator idx = parms.begin()
|
||||
; idx != parms.end() ; ++idx)
|
||||
parms_[tmp_idx++] = *idx;
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(perm_string n, const vector<PExpr*>&parms)
|
||||
: path_(pn_from_ps(n)), parms_(parms)
|
||||
: package_(0), path_(pn_from_ps(n)), parms_(parms)
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(perm_string n)
|
||||
: path_(pn_from_ps(n))
|
||||
: package_(0), path_(pn_from_ps(n))
|
||||
{
|
||||
}
|
||||
|
||||
// NOTE: Anachronism. Try to work all use of svector out.
|
||||
PECallFunction::PECallFunction(const pform_name_t&n, const list<PExpr *> &parms)
|
||||
: path_(n), parms_(parms.size())
|
||||
: package_(0), path_(n), parms_(parms.size())
|
||||
{
|
||||
int tmp_idx = 0;
|
||||
assert(parms_.size() == parms.size());
|
||||
|
|
@ -208,7 +218,7 @@ PECallFunction::PECallFunction(const pform_name_t&n, const list<PExpr *> &parms)
|
|||
}
|
||||
|
||||
PECallFunction::PECallFunction(perm_string n, const list<PExpr*>&parms)
|
||||
: path_(pn_from_ps(n)), parms_(parms.size())
|
||||
: package_(0), path_(pn_from_ps(n)), parms_(parms.size())
|
||||
{
|
||||
int tmp_idx = 0;
|
||||
assert(parms_.size() == parms.size());
|
||||
|
|
@ -333,10 +343,9 @@ PEIdent::PEIdent(perm_string s, bool no_implicit_sig)
|
|||
path_.push_back(name_component_t(s));
|
||||
}
|
||||
|
||||
PEIdent::PEIdent(PPackage*pkg, perm_string s)
|
||||
: package_(pkg), no_implicit_sig_(true)
|
||||
PEIdent::PEIdent(PPackage*pkg, const pform_name_t&that)
|
||||
: package_(pkg), path_(that), no_implicit_sig_(true)
|
||||
{
|
||||
path_.push_back(name_component_t(s));
|
||||
}
|
||||
|
||||
PEIdent::~PEIdent()
|
||||
|
|
|
|||
16
PExpr.h
16
PExpr.h
|
|
@ -291,7 +291,7 @@ class PEIdent : public PExpr {
|
|||
|
||||
public:
|
||||
explicit PEIdent(perm_string, bool no_implicit_sig=false);
|
||||
explicit PEIdent(PPackage*pkg, perm_string name);
|
||||
explicit PEIdent(PPackage*pkg, const pform_name_t&name);
|
||||
explicit PEIdent(const pform_name_t&);
|
||||
~PEIdent();
|
||||
|
||||
|
|
@ -770,11 +770,15 @@ class PETernary : public PExpr {
|
|||
class PECallFunction : public PExpr {
|
||||
public:
|
||||
explicit PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms);
|
||||
// Call function defined in package.
|
||||
explicit PECallFunction(PPackage*pkg, perm_string n, const std::vector<PExpr *> &parms);
|
||||
explicit PECallFunction(PPackage*pkg, perm_string n, const std::list<PExpr *> &parms);
|
||||
|
||||
// Call of system function (name is not hierarchical)
|
||||
explicit PECallFunction(perm_string n, const vector<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n);
|
||||
|
||||
// svector versions. Should be removed!
|
||||
// std::list versions. Should be removed!
|
||||
explicit PECallFunction(const pform_name_t&n, const list<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n, const list<PExpr *> &parms);
|
||||
|
||||
|
|
@ -794,14 +798,17 @@ class PECallFunction : public PExpr {
|
|||
width_mode_t&mode);
|
||||
|
||||
private:
|
||||
PPackage*package_;
|
||||
pform_name_t path_;
|
||||
vector<PExpr *> parms_;
|
||||
std::vector<PExpr *> parms_;
|
||||
|
||||
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
|
||||
|
||||
|
||||
NetExpr* cast_to_width_(NetExpr*expr, unsigned wid) const;
|
||||
|
||||
NetExpr*elaborate_expr_pkg_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags)const;
|
||||
NetExpr*elaborate_expr_method_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid) const;
|
||||
#if 0
|
||||
|
|
@ -820,6 +827,9 @@ class PECallFunction : public PExpr {
|
|||
unsigned test_width_method_(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
||||
NetExpr*elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
unsigned elaborate_arguments_(Design*des, NetScope*scope,
|
||||
NetFuncDef*def, bool need_const,
|
||||
std::vector<NetExpr*>&parms,
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ class PPackage : public PScopeExtra, public LineInfo {
|
|||
~PPackage();
|
||||
|
||||
bool elaborate_scope(Design*des, NetScope*scope);
|
||||
bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
bool elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
void pform_dump(std::ostream&out) const;
|
||||
};
|
||||
|
|
|
|||
15
Statement.cc
15
Statement.cc
|
|
@ -127,7 +127,18 @@ void PBlock::set_statement(const vector<Statement*>&st)
|
|||
}
|
||||
|
||||
PCallTask::PCallTask(const pform_name_t&n, const list<PExpr*>&p)
|
||||
: path_(n), parms_(p.size())
|
||||
: package_(0), path_(n), parms_(p.size())
|
||||
{
|
||||
list<PExpr*>::const_iterator cur = p.begin();
|
||||
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
parms_[idx] = *cur;
|
||||
++cur;
|
||||
}
|
||||
assert(cur == p.end());
|
||||
}
|
||||
|
||||
PCallTask::PCallTask(PPackage*pkg, const pform_name_t&n, const list<PExpr*>&p)
|
||||
: package_(pkg), path_(n), parms_(p.size())
|
||||
{
|
||||
list<PExpr*>::const_iterator cur = p.begin();
|
||||
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
|
|
@ -138,7 +149,7 @@ PCallTask::PCallTask(const pform_name_t&n, const list<PExpr*>&p)
|
|||
}
|
||||
|
||||
PCallTask::PCallTask(perm_string n, const list<PExpr*>&p)
|
||||
: parms_(p.size())
|
||||
: package_(0), parms_(p.size())
|
||||
{
|
||||
list<PExpr*>::const_iterator cur = p.begin();
|
||||
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
# include "HName.h"
|
||||
# include "LineInfo.h"
|
||||
class PExpr;
|
||||
class PPackage;
|
||||
class Statement;
|
||||
class PEventStatement;
|
||||
class Design;
|
||||
|
|
@ -198,6 +199,7 @@ class PBlock : public PScope, public Statement {
|
|||
class PCallTask : public Statement {
|
||||
|
||||
public:
|
||||
explicit PCallTask(PPackage*pkg, const pform_name_t&n, const list<PExpr*>&parms);
|
||||
explicit PCallTask(const pform_name_t&n, const list<PExpr*>&parms);
|
||||
explicit PCallTask(perm_string n, const list<PExpr*>&parms);
|
||||
~PCallTask();
|
||||
|
|
@ -217,6 +219,7 @@ class PCallTask : public Statement {
|
|||
NetProc*elaborate_build_call_(Design*des, NetScope*scope,
|
||||
NetScope*task, NetExpr*use_this) const;
|
||||
|
||||
PPackage*package_;
|
||||
pform_name_t path_;
|
||||
vector<PExpr*> parms_;
|
||||
};
|
||||
|
|
|
|||
55
elab_expr.cc
55
elab_expr.cc
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 1999-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
|
||||
|
|
@ -1775,10 +1776,41 @@ static NetExpr* check_for_class_property(const LineInfo*li,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr_pkg_(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const
|
||||
{
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PECallFunction::elaborate_expr_pkg_: "
|
||||
<< "Elaborate " << path_
|
||||
<< " as function in package " << package_->pscope_name()
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
// Find the package that contains this definition, and use the
|
||||
// package scope as the search starting point for the function
|
||||
// definition.
|
||||
NetScope*pscope = des->find_package(package_->pscope_name());
|
||||
ivl_assert(*this, pscope);
|
||||
|
||||
NetFuncDef*def = des->find_function(pscope, path_);
|
||||
ivl_assert(*this, def);
|
||||
|
||||
NetScope*dscope = def->scope();
|
||||
ivl_assert(*this, dscope);
|
||||
|
||||
if (! check_call_matches_definition_(des, dscope))
|
||||
return 0;
|
||||
|
||||
return elaborate_base_(des, scope, dscope, expr_wid, flags);
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
if (package_)
|
||||
return elaborate_expr_pkg_(des, scope, expr_wid, flags);
|
||||
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
if (peek_tail_name(path_)[0] == '$')
|
||||
|
|
@ -1835,9 +1867,20 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
|||
scope->is_const_func(false);
|
||||
}
|
||||
|
||||
return elaborate_base_(des, scope, dscope, expr_wid, flags);
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
|
||||
if (! check_call_matches_definition_(des, dscope))
|
||||
return 0;
|
||||
|
||||
NetFuncDef*def = dscope->func_def();
|
||||
|
||||
bool need_const = NEED_CONST & flags;
|
||||
|
||||
unsigned parms_count = parms_.size();
|
||||
if ((parms_count == 1) && (parms_[0] == 0))
|
||||
parms_count = 0;
|
||||
|
|
@ -2719,13 +2762,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
use_path.pop_back();
|
||||
|
||||
ivl_assert(*this, net == 0);
|
||||
symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2);
|
||||
symbol_search(this, des, use_scope, use_path, net, par, eve, ex1, ex2);
|
||||
|
||||
if (net == 0) {
|
||||
// Nope, no struct/class with member.
|
||||
|
||||
} else if (net->struct_type() != 0) {
|
||||
return check_for_struct_members(this, des, scope,
|
||||
return check_for_struct_members(this, des, use_scope,
|
||||
net, use_path.back().index,
|
||||
member_comp);
|
||||
|
||||
|
|
@ -2986,7 +3029,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
<< " for member " << member_comp << "." << endl;
|
||||
|
||||
ivl_assert(*this, net == 0);
|
||||
symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2);
|
||||
symbol_search(this, des, use_scope, use_path, net, par, eve, ex1, ex2);
|
||||
|
||||
// Check to see if we have a net and if so is it an
|
||||
// enumeration? If so then check to see if this is an
|
||||
|
|
@ -3002,7 +3045,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
// This expression cannot be a select!
|
||||
assert(use_path.back().index.empty());
|
||||
|
||||
return check_for_enum_methods(this, des, scope,
|
||||
return check_for_enum_methods(this, des, use_scope,
|
||||
netenum,
|
||||
use_path, member_comp.name,
|
||||
expr, expr_wid, NULL, 0);
|
||||
|
|
@ -3021,7 +3064,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
<< "got " << use_path.back().index.size() << "." << endl;
|
||||
}
|
||||
|
||||
return check_for_struct_members(this, des, scope,
|
||||
return check_for_struct_members(this, des, use_scope,
|
||||
net, use_path.back().index,
|
||||
member_comp);
|
||||
}
|
||||
|
|
@ -3033,7 +3076,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
<< " look for property " << member_comp << endl;
|
||||
}
|
||||
|
||||
return check_for_class_property(this, des, scope,
|
||||
return check_for_class_property(this, des, use_scope,
|
||||
net, member_comp);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
26
elab_lval.cc
26
elab_lval.cc
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / 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
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
# include "config.h"
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "PPackage.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "netstruct.h"
|
||||
|
|
@ -163,7 +164,16 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
if (NetAssign_*tmp = elaborate_lval_method_class_member_(des, scope))
|
||||
return tmp;
|
||||
|
||||
symbol_search(this, des, scope, path_, reg, par, eve);
|
||||
/* Normally find the name in the passed scope. But if this is
|
||||
imported from a package, then located the variable from the
|
||||
package scope. */
|
||||
NetScope*use_scope = scope;
|
||||
if (package_) {
|
||||
use_scope = des->find_package(package_->pscope_name());
|
||||
ivl_assert(*this, use_scope);
|
||||
}
|
||||
|
||||
symbol_search(this, des, use_scope, path_, reg, par, eve);
|
||||
|
||||
/* If the signal is not found, check to see if this is a
|
||||
member of a struct. Take the name of the form "a.b.member",
|
||||
|
|
@ -173,7 +183,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
pform_name_t use_path = path_;
|
||||
perm_string tmp_name = peek_tail_name(use_path);
|
||||
use_path.pop_back();
|
||||
symbol_search(this, des, scope, use_path, reg, par, eve);
|
||||
symbol_search(this, des, use_scope, use_path, reg, par, eve);
|
||||
|
||||
if (reg && reg->struct_type()) {
|
||||
method_name = tmp_name;
|
||||
|
|
@ -188,7 +198,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
|
||||
if (reg == 0) {
|
||||
cerr << get_fileline() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope_path(scope) <<
|
||||
<< path_ << "'' in ``" << scope_path(use_scope) <<
|
||||
"''" << endl;
|
||||
|
||||
des->errors += 1;
|
||||
|
|
@ -228,7 +238,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
unless this is the l-value of a force. */
|
||||
if ((reg->type() != NetNet::REG) && !is_force) {
|
||||
cerr << get_fileline() << ": error: " << path_ <<
|
||||
" is not a valid l-value in " << scope_path(scope) <<
|
||||
" is not a valid l-value in " << scope_path(use_scope) <<
|
||||
"." << endl;
|
||||
cerr << reg->get_fileline() << ": : " << path_ <<
|
||||
" is declared here as " << reg->type() << "." << endl;
|
||||
|
|
@ -238,13 +248,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
|
||||
if (reg->struct_type() && !method_name.nil()) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_packed_member_(des, scope, lv, method_name);
|
||||
elaborate_lval_net_packed_member_(des, use_scope, lv, method_name);
|
||||
return lv;
|
||||
}
|
||||
|
||||
if (reg->class_type() && !method_name.nil() && gn_system_verilog()) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_class_member_(des, scope, lv, method_name);
|
||||
elaborate_lval_net_class_member_(des, use_scope, lv, method_name);
|
||||
return lv;
|
||||
}
|
||||
|
||||
|
|
@ -768,7 +778,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope,
|
||||
bool PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*,
|
||||
NetAssign_*lv,
|
||||
const perm_string&method_name) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -552,7 +553,9 @@ bool PPackage::elaborate_scope(Design*des, NetScope*scope)
|
|||
}
|
||||
|
||||
collect_scope_parameters_(des, scope, parameters);
|
||||
|
||||
collect_scope_localparams_(des, scope, localparams);
|
||||
elaborate_scope_funcs(des, scope, funcs);
|
||||
elaborate_scope_tasks(des, scope, tasks);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
25
elab_sig.cc
25
elab_sig.cc
|
|
@ -29,6 +29,7 @@
|
|||
# include "PExpr.h"
|
||||
# include "PGate.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PPackage.h"
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "Statement.h"
|
||||
|
|
@ -166,7 +167,13 @@ static void elaborate_sig_funcs(Design*des, NetScope*scope,
|
|||
continue;
|
||||
}
|
||||
|
||||
(*cur).second->elaborate_sig(des, fscope);
|
||||
if (debug_elaborate) {
|
||||
cerr << cur->second->get_fileline() << ": elaborate_sig_funcs: "
|
||||
<< "Elaborate function " << use_name
|
||||
<< " in " << scope_path(fscope) << endl;
|
||||
}
|
||||
|
||||
cur->second->elaborate_sig(des, fscope);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -193,6 +200,22 @@ static void elaborate_sig_classes(Design*des, NetScope*scope,
|
|||
}
|
||||
}
|
||||
|
||||
bool PPackage::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
flag = elaborate_sig_wires_(des, scope) && flag;
|
||||
|
||||
// After all the wires are elaborated, we are free to
|
||||
// elaborate the ports of the tasks defined within this
|
||||
// module. Run through them now.
|
||||
|
||||
elaborate_sig_funcs(des, scope, funcs);
|
||||
elaborate_sig_tasks(des, scope, tasks);
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
|
|
|||
104
elaborate.cc
104
elaborate.cc
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -3206,7 +3207,13 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
NetScope*task = des->find_task(scope, path_);
|
||||
NetScope*pscope = scope;
|
||||
if (package_) {
|
||||
pscope = des->find_package(package_->pscope_name());
|
||||
ivl_assert(*this, pscope);
|
||||
}
|
||||
|
||||
NetScope*task = des->find_task(pscope, path_);
|
||||
if (task == 0) {
|
||||
// For SystemVerilog this may be a few other things.
|
||||
if (gn_system_verilog()) {
|
||||
|
|
@ -4876,6 +4883,19 @@ static void elaborate_classes(Design*des, NetScope*scope,
|
|||
}
|
||||
}
|
||||
|
||||
bool PPackage::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool result_flag = true;
|
||||
|
||||
// Elaborate function methods, and...
|
||||
elaborate_functions(des, scope, funcs);
|
||||
|
||||
// Elaborate task methods.
|
||||
elaborate_tasks(des, scope, tasks);
|
||||
|
||||
return result_flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* When a module is instantiated, it creates the scope then uses this
|
||||
* method to elaborate the contents of the module.
|
||||
|
|
@ -5122,11 +5142,6 @@ bool PScope::elaborate_behaviors_(Design*des, NetScope*scope) const
|
|||
return result_flag;
|
||||
}
|
||||
|
||||
struct root_elem {
|
||||
Module *mod;
|
||||
NetScope *scope;
|
||||
};
|
||||
|
||||
class elaborate_package_t : public elaborator_work_item_t {
|
||||
public:
|
||||
elaborate_package_t(Design*d, NetScope*scope, PPackage*p)
|
||||
|
|
@ -5298,9 +5313,21 @@ bool Design::check_proc_delay() const
|
|||
* for each root, does the whole elaboration sequence, and fills in
|
||||
* the resulting Design.
|
||||
*/
|
||||
|
||||
struct pack_elem {
|
||||
PPackage*pack;
|
||||
NetScope*scope;
|
||||
};
|
||||
|
||||
struct root_elem {
|
||||
Module *mod;
|
||||
NetScope *scope;
|
||||
};
|
||||
|
||||
Design* elaborate(list<perm_string>roots)
|
||||
{
|
||||
svector<root_elem*> root_elems(roots.size());
|
||||
vector<struct root_elem> root_elems(roots.size());
|
||||
vector<struct pack_elem> pack_elems(pform_packages.size());
|
||||
bool rc = true;
|
||||
unsigned i = 0;
|
||||
|
||||
|
|
@ -5310,6 +5337,7 @@ Design* elaborate(list<perm_string>roots)
|
|||
|
||||
// Elaborate the packages. Package elaboration is simpler
|
||||
// because there are fewer sub-scopes involved.
|
||||
i = 0;
|
||||
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
|
||||
; pac != pform_packages.end() ; ++ pac) {
|
||||
|
||||
|
|
@ -5318,9 +5346,14 @@ Design* elaborate(list<perm_string>roots)
|
|||
|
||||
elaborator_work_item_t*es = new elaborate_package_t(des, scope, pac->second);
|
||||
des->elaboration_work_list.push_back(es);
|
||||
|
||||
pack_elems[i].pack = pac->second;
|
||||
pack_elems[i].scope = scope;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// Scan the root modules by name, and elaborate their scopes.
|
||||
i = 0;
|
||||
for (list<perm_string>::const_iterator root = roots.begin()
|
||||
; root != roots.end() ; ++ root ) {
|
||||
|
||||
|
|
@ -5353,10 +5386,9 @@ Design* elaborate(list<perm_string>roots)
|
|||
|
||||
// Save this scope, along with its definition, in the
|
||||
// "root_elems" list for later passes.
|
||||
struct root_elem *r = new struct root_elem;
|
||||
r->mod = rmod;
|
||||
r->scope = scope;
|
||||
root_elems[i++] = r;
|
||||
root_elems[i].mod = rmod;
|
||||
root_elems[i].scope = scope;
|
||||
i += 1;
|
||||
|
||||
// Arrange for these scopes to be elaborated as root
|
||||
// scopes. Create an "elaborate_root_scope" object to
|
||||
|
|
@ -5413,23 +5445,36 @@ Design* elaborate(list<perm_string>roots)
|
|||
// what we need to elaborate signals and memories. This pass
|
||||
// creates all the NetNet and NetMemory objects for declared
|
||||
// objects.
|
||||
for (i = 0; i < root_elems.count(); i++) {
|
||||
for (i = 0; i < pack_elems.size(); i += 1) {
|
||||
PPackage*pack = pack_elems[i].pack;
|
||||
NetScope*scope= pack_elems[i].scope;
|
||||
|
||||
Module *rmod = root_elems[i]->mod;
|
||||
NetScope *scope = root_elems[i]->scope;
|
||||
if (! pack->elaborate_sig(des, scope)) {
|
||||
if (debug_elaborate) {
|
||||
cerr << "<toplevel>" << ": debug: " << pack->pscope_name()
|
||||
<< ": elaborate_sig failed!!!" << endl;
|
||||
}
|
||||
delete des;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < root_elems.size(); i++) {
|
||||
Module *rmod = root_elems[i].mod;
|
||||
NetScope *scope = root_elems[i].scope;
|
||||
scope->set_num_ports( rmod->port_count() );
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << "<toplevel>" << ": debug: " << rmod->mod_name()
|
||||
<< ": port elaboration root "
|
||||
<< rmod->port_count() << " ports" << endl;
|
||||
}
|
||||
if (debug_elaborate) {
|
||||
cerr << "<toplevel>" << ": debug: " << rmod->mod_name()
|
||||
<< ": port elaboration root "
|
||||
<< rmod->port_count() << " ports" << endl;
|
||||
}
|
||||
|
||||
if (! rmod->elaborate_sig(des, scope)) {
|
||||
if (debug_elaborate) {
|
||||
cerr << "<toplevel>" << ": debug: " << rmod->mod_name()
|
||||
<< ": elaborate_sig failed!!!" << endl;
|
||||
}
|
||||
if (debug_elaborate) {
|
||||
cerr << "<toplevel>" << ": debug: " << rmod->mod_name()
|
||||
<< ": elaborate_sig failed!!!" << endl;
|
||||
}
|
||||
delete des;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -5461,12 +5506,17 @@ Design* elaborate(list<perm_string>roots)
|
|||
|
||||
// Now that the structure and parameters are taken care of,
|
||||
// run through the pform again and generate the full netlist.
|
||||
for (i = 0; i < root_elems.count(); i++) {
|
||||
Module *rmod = root_elems[i]->mod;
|
||||
NetScope *scope = root_elems[i]->scope;
|
||||
|
||||
for (i = 0; i < pack_elems.size(); i += 1) {
|
||||
PPackage*pkg = pack_elems[i].pack;
|
||||
NetScope*scope = pack_elems[i].scope;
|
||||
rc &= pkg->elaborate(des, scope);
|
||||
}
|
||||
|
||||
for (i = 0; i < root_elems.size(); i++) {
|
||||
Module *rmod = root_elems[i].mod;
|
||||
NetScope *scope = root_elems[i].scope;
|
||||
rc &= rmod->elaborate(des, scope);
|
||||
delete root_elems[i];
|
||||
}
|
||||
|
||||
if (rc == false) {
|
||||
|
|
|
|||
18
emit.cc
18
emit.cc
|
|
@ -436,6 +436,7 @@ bool NetScope::emit_defs(struct target_t*tgt) const
|
|||
bool flag = true;
|
||||
|
||||
switch (type_) {
|
||||
case PACKAGE:
|
||||
case MODULE:
|
||||
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
|
||||
; cur != children_.end() ; ++ cur )
|
||||
|
|
@ -470,11 +471,17 @@ int Design::emit(struct target_t*tgt) const
|
|||
if (tgt->start_design(this) == false)
|
||||
return -2;
|
||||
|
||||
// enumerate the scopes
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
||||
scope != root_scopes_.end(); ++ scope )
|
||||
(*scope)->emit_scope(tgt);
|
||||
// enumerate package scopes
|
||||
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
|
||||
; scope != packages_.end() ; ++ scope) {
|
||||
scope->second->emit_scope(tgt);
|
||||
}
|
||||
|
||||
// enumerate root scopes
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
|
||||
; scope != root_scopes_.end(); ++ scope ) {
|
||||
(*scope)->emit_scope(tgt);
|
||||
}
|
||||
|
||||
// emit nodes
|
||||
bool nodes_rc = true;
|
||||
|
|
@ -494,6 +501,9 @@ int Design::emit(struct target_t*tgt) const
|
|||
|
||||
// emit task and function definitions
|
||||
bool tasks_rc = true;
|
||||
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
|
||||
; scope != packages_.end() ; ++ scope )
|
||||
tasks_rc &= scope->second->emit_defs(tgt);
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
|
||||
; scope != root_scopes_.end(); ++ scope )
|
||||
tasks_rc &= (*scope)->emit_defs(tgt);
|
||||
|
|
|
|||
41
lexor.lex
41
lexor.lex
|
|
@ -91,6 +91,19 @@ static bool in_module = false;
|
|||
static bool in_UDP = false;
|
||||
bool in_celldefine = false;
|
||||
UCDriveType uc_drive = UCD_NONE;
|
||||
|
||||
/*
|
||||
* The parser sometimes needs to indicate to the lexor that the next
|
||||
* identifier needs to be understood in the context of a package. The
|
||||
* parser feeds back that left context with calls to the
|
||||
* lex_in_package_scope.
|
||||
*/
|
||||
static PPackage* in_package_scope = 0;
|
||||
void lex_in_package_scope(PPackage*pkg)
|
||||
{
|
||||
in_package_scope = pkg;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%x CCOMMENT
|
||||
|
|
@ -297,6 +310,24 @@ TU [munpf]
|
|||
break;
|
||||
}
|
||||
|
||||
/* Special case: If this is part of a scoped name, then check
|
||||
the package for identifier details. For example, if the
|
||||
source file is foo::bar, the parse.y will note the
|
||||
PACKAGE_IDENTIFIER and "::" token and mark the
|
||||
"in_package_scope" variable. Then this lexor will see the
|
||||
identifier here and interpret it in the package scope. */
|
||||
if (in_package_scope) {
|
||||
if (rc == IDENTIFIER) {
|
||||
if (data_type_t*type = pform_test_type_identifier(in_package_scope, yylval.text)) {
|
||||
delete[]yylval.text;
|
||||
yylval.data_type = type;
|
||||
rc = TYPE_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
in_package_scope = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* If this identifier names a discipline, then return this as
|
||||
a DISCIPLINE_IDENTIFIER and return the discipline as the
|
||||
value instead. */
|
||||
|
|
@ -310,6 +341,16 @@ TU [munpf]
|
|||
}
|
||||
}
|
||||
|
||||
/* If this identifer names a previously declared package, then
|
||||
return this as a PACKAGE_IDENTIFIER instead. */
|
||||
if (rc == IDENTIFIER && gn_system_verilog()) {
|
||||
if (PPackage*pkg = pform_test_package_identifier(yylval.text)) {
|
||||
delete[]yylval.text;
|
||||
yylval.package = pkg;
|
||||
rc = PACKAGE_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this identifier names a previously declared type, then
|
||||
return this as a TYPE_IDENTIFIER instead. */
|
||||
if (rc == IDENTIFIER && gn_system_verilog()) {
|
||||
|
|
|
|||
|
|
@ -400,9 +400,15 @@ void NetScope::run_defparams_later(Design*des)
|
|||
|
||||
void Design::evaluate_parameters()
|
||||
{
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
||||
scope != root_scopes_.end(); ++ scope )
|
||||
for (map<perm_string,NetScope*>::const_iterator cur = packages_.begin()
|
||||
; cur != packages_.end() ; ++ cur) {
|
||||
cur->second->evaluate_parameters(this);
|
||||
}
|
||||
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
|
||||
; scope != root_scopes_.end() ; ++ scope ) {
|
||||
(*scope)->evaluate_parameters(this);
|
||||
}
|
||||
}
|
||||
|
||||
void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
||||
|
|
|
|||
61
parse.y
61
parse.y
|
|
@ -401,6 +401,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
class_type_t*class_type;
|
||||
real_type_t::type_t real_type;
|
||||
property_qualifier_t property_qualifier;
|
||||
PPackage*package;
|
||||
|
||||
verinum* number;
|
||||
|
||||
|
|
@ -410,8 +411,9 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
list<index_component_t> *dimensions;
|
||||
};
|
||||
|
||||
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL
|
||||
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL
|
||||
%token <data_type> TYPE_IDENTIFIER
|
||||
%token <package> PACKAGE_IDENTIFIER
|
||||
%token <discipline> DISCIPLINE_IDENTIFIER
|
||||
%token <text> PATHPULSE_IDENTIFIER
|
||||
%token <number> BASED_NUMBER DEC_NUMBER UNBASED_NUMBER
|
||||
|
|
@ -894,6 +896,17 @@ constraint_set /* IEEE1800-2005 A.1.9 */
|
|||
| '{' constraint_expression_list '}'
|
||||
;
|
||||
|
||||
data_declaration /* IEEE1800-2005: A.2.1.3 */
|
||||
: attribute_list_opt data_type_or_implicit list_of_variable_decl_assignments ';'
|
||||
{ data_type_t*data_type = $2;
|
||||
if (data_type == 0) {
|
||||
data_type = new vector_type_t(IVL_VT_LOGIC, false, 0);
|
||||
FILE_NAME(data_type, @2);
|
||||
}
|
||||
pform_makewire(@2, 0, str_strength, $3, NetNet::IMPLICIT_REG, data_type);
|
||||
}
|
||||
;
|
||||
|
||||
data_type /* IEEE1800-2005: A.2.2.1 */
|
||||
: integer_vector_type unsigned_signed_opt range_opt
|
||||
{ ivl_variable_type_t use_vtype = $1;
|
||||
|
|
@ -925,6 +938,12 @@ data_type /* IEEE1800-2005: A.2.2.1 */
|
|||
{ if ($2) $$ = new parray_type_t($1, $2);
|
||||
else $$ = $1;
|
||||
}
|
||||
| PACKAGE_IDENTIFIER K_SCOPE_RES
|
||||
{ lex_in_package_scope($1); }
|
||||
TYPE_IDENTIFIER
|
||||
{ lex_in_package_scope(0);
|
||||
$$ = $4;
|
||||
}
|
||||
| K_string
|
||||
{ string_type_t*tmp = new string_type_t;
|
||||
FILE_NAME(tmp, @1);
|
||||
|
|
@ -1373,14 +1392,12 @@ package_import_declaration /* IEEE1800-2005 A.2.1.3 */
|
|||
;
|
||||
|
||||
package_import_item
|
||||
: IDENTIFIER K_SCOPE_RES IDENTIFIER
|
||||
: PACKAGE_IDENTIFIER K_SCOPE_RES IDENTIFIER
|
||||
{ pform_package_import(@2, $1, $3);
|
||||
delete[]$1;
|
||||
delete[]$3;
|
||||
}
|
||||
| IDENTIFIER K_SCOPE_RES '*'
|
||||
| PACKAGE_IDENTIFIER K_SCOPE_RES '*'
|
||||
{ pform_package_import(@2, $1, 0);
|
||||
delete[]$1;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -1395,6 +1412,8 @@ package_item /* IEEE1800-2005 A.1.10 */
|
|||
| K_localparam param_type localparam_assign_list ';'
|
||||
| type_declaration
|
||||
| function_declaration
|
||||
| task_declaration
|
||||
| data_declaration
|
||||
;
|
||||
|
||||
package_item_list
|
||||
|
|
@ -2985,16 +3004,17 @@ expr_primary
|
|||
delete $1;
|
||||
}
|
||||
|
||||
| IDENTIFIER K_SCOPE_RES IDENTIFIER
|
||||
{ $$ = pform_package_ident(@2, $1, $3); }
|
||||
| PACKAGE_IDENTIFIER K_SCOPE_RES hierarchy_identifier
|
||||
{ $$ = pform_package_ident(@2, $1, $3);
|
||||
delete $3;
|
||||
}
|
||||
|
||||
/* An identifier followed by an expression list in parentheses is a
|
||||
function call. If a system identifier, then a system function
|
||||
call. */
|
||||
|
||||
| hierarchy_identifier '(' expression_list_proper ')'
|
||||
{ PECallFunction*tmp = new PECallFunction(*$1, *$3);
|
||||
FILE_NAME(tmp, @1);
|
||||
{ PECallFunction*tmp = pform_make_call_function(@1, *$1, *$3);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -3006,15 +3026,21 @@ expr_primary
|
|||
$$ = tmp;
|
||||
}
|
||||
| hierarchy_identifier '(' ')'
|
||||
{ const vector<PExpr*> empty;
|
||||
PECallFunction*tmp = new PECallFunction(*$1, empty);
|
||||
FILE_NAME(tmp, @1);
|
||||
{ const list<PExpr*> empty;
|
||||
PECallFunction*tmp = pform_make_call_function(@1, *$1, empty);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
if (!gn_system_verilog()) {
|
||||
yyerror(@1, "error: Empty function argument list requires SystemVerilog.");
|
||||
}
|
||||
}
|
||||
| PACKAGE_IDENTIFIER K_SCOPE_RES IDENTIFIER '(' expression_list_proper ')'
|
||||
{ perm_string use_name = lex_strings.make($3);
|
||||
PECallFunction*tmp = new PECallFunction($1, use_name, *$5);
|
||||
FILE_NAME(tmp, @3);
|
||||
delete[]$3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| SYSTEM_IDENTIFIER '(' ')'
|
||||
{ perm_string tn = lex_strings.make($1);
|
||||
const vector<PExpr*>empty;
|
||||
|
|
@ -3837,7 +3863,7 @@ atom2_type
|
|||
rule to reflect the rules for assignment l-values. */
|
||||
lpvalue
|
||||
: hierarchy_identifier
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
{ PEIdent*tmp = pform_new_ident(*$1);
|
||||
FILE_NAME(tmp, @1);
|
||||
$$ = tmp;
|
||||
delete $1;
|
||||
|
|
@ -5700,8 +5726,7 @@ statement_item /* This is roughly statement_item in the LRM */
|
|||
}
|
||||
|
||||
| hierarchy_identifier '(' expression_list_with_nuls ')' ';'
|
||||
{ PCallTask*tmp = new PCallTask(*$1, *$3);
|
||||
FILE_NAME(tmp, @1);
|
||||
{ PCallTask*tmp = pform_make_call_task(@1, *$1, *$3);
|
||||
delete $1;
|
||||
delete $3;
|
||||
$$ = tmp;
|
||||
|
|
@ -5735,8 +5760,7 @@ statement_item /* This is roughly statement_item in the LRM */
|
|||
|
||||
| hierarchy_identifier ';'
|
||||
{ list<PExpr*>pt;
|
||||
PCallTask*tmp = new PCallTask(*$1, pt);
|
||||
FILE_NAME(tmp, @1);
|
||||
PCallTask*tmp = pform_make_call_task(@1, *$1, pt);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -5744,8 +5768,7 @@ statement_item /* This is roughly statement_item in the LRM */
|
|||
| hierarchy_identifier '(' error ')' ';'
|
||||
{ yyerror(@3, "error: Syntax error in task arguments.");
|
||||
list<PExpr*>pt;
|
||||
PCallTask*tmp = new PCallTask(*$1, pt);
|
||||
FILE_NAME(tmp, @1);
|
||||
PCallTask*tmp = pform_make_call_task(@1, *$1, pt);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
|
|||
16
parse_misc.h
16
parse_misc.h
|
|
@ -78,6 +78,15 @@ extern UCDriveType uc_drive;
|
|||
extern bool have_timeunit_decl;
|
||||
extern bool have_timeprec_decl;
|
||||
|
||||
/*
|
||||
* The parser signals back to the lexor that the next identifier
|
||||
* should be in the package scope. For example, if the source is
|
||||
* <package> :: <foo>
|
||||
* Then the parser calls this function to set the package context so
|
||||
* that the lexor can interpret <foo> in the package context.
|
||||
*/
|
||||
extern void lex_in_package_scope(PPackage*pkg);
|
||||
|
||||
/*
|
||||
* Test if this identifier is a type identifier in the current
|
||||
* context. The pform code needs to help the lexor here because the
|
||||
|
|
@ -85,6 +94,13 @@ extern bool have_timeprec_decl;
|
|||
* type names.
|
||||
*/
|
||||
extern data_type_t* pform_test_type_identifier(const char*txt);
|
||||
extern data_type_t* pform_test_type_identifier(PPackage*pkg, const char*txt);
|
||||
|
||||
/*
|
||||
* Test if this identigier is a package name. The pform needs to help
|
||||
* the lexor here because the parser detects packages and saves them.
|
||||
*/
|
||||
extern PPackage* pform_test_package_identifier(const char*txt);
|
||||
|
||||
/*
|
||||
* Export these functions because we have to generate PENumber class
|
||||
|
|
|
|||
120
pform.cc
120
pform.cc
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -424,18 +425,15 @@ PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
|
|||
*/
|
||||
PEIdent* pform_new_ident(const pform_name_t&name)
|
||||
{
|
||||
if (name.size() != 1)
|
||||
return new PEIdent(name);
|
||||
|
||||
LexicalScope*scope = pform_peek_scope();
|
||||
map<perm_string,PPackage*>::const_iterator pkg = scope->imports.find(name.back().name);
|
||||
map<perm_string,PPackage*>::const_iterator pkg = scope->imports.find(name.front().name);
|
||||
if (pkg == scope->imports.end())
|
||||
return new PEIdent(name);
|
||||
|
||||
// XXXX For now, do not support indexed imported names.
|
||||
assert(name.back().index.size() == 0);
|
||||
|
||||
return new PEIdent(pkg->second, name.back().name);
|
||||
return new PEIdent(pkg->second, name);
|
||||
}
|
||||
|
||||
PGenerate* pform_parent_generate(void)
|
||||
|
|
@ -519,18 +517,98 @@ data_type_t* pform_test_type_identifier(const char*txt)
|
|||
return 0;
|
||||
|
||||
perm_string name = lex_strings.make(txt);
|
||||
map<perm_string,data_type_t*>::iterator cur;
|
||||
|
||||
LexicalScope*cur_scope = lexical_scope;
|
||||
do {
|
||||
map<perm_string,data_type_t*>::iterator cur;
|
||||
|
||||
// First look to see if this identifier is imported from
|
||||
// a package. If it is, see if it is a type in that
|
||||
// package. If it is, then great. If imported as
|
||||
// something other then a type, then give up now becase
|
||||
// the name has at least shadowed any other possible
|
||||
// meaning for this name.
|
||||
map<perm_string,PPackage*>::iterator cur_pkg;
|
||||
cur_pkg = cur_scope->imports.find(name);
|
||||
if (cur_pkg != cur_scope->imports.end()) {
|
||||
PPackage*pkg = cur_pkg->second;
|
||||
cur = pkg->typedefs.find(name);
|
||||
if (cur != pkg->typedefs.end())
|
||||
return cur->second;
|
||||
|
||||
// Not a type. Give up.
|
||||
return 0;
|
||||
}
|
||||
|
||||
cur = cur_scope->typedefs.find(name);
|
||||
if (cur != cur_scope->typedefs.end())
|
||||
return cur->second;
|
||||
|
||||
cur_scope = cur_scope->parent_scope();
|
||||
} while (cur_scope);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PECallFunction* pform_make_call_function(const struct vlltype&loc,
|
||||
const pform_name_t&name,
|
||||
const list<PExpr*>&parms)
|
||||
{
|
||||
PECallFunction*tmp = 0;
|
||||
|
||||
// First try to get the function name from a package. Check
|
||||
// the imports, and if the name is there, make the function as
|
||||
// a package member.
|
||||
do {
|
||||
if (name.size() != 1)
|
||||
break;
|
||||
|
||||
perm_string use_name = peek_tail_name(name);
|
||||
|
||||
map<perm_string,PPackage*>::iterator cur_pkg;
|
||||
cur_pkg = lexical_scope->imports.find(use_name);
|
||||
if (cur_pkg == lexical_scope->imports.end())
|
||||
break;
|
||||
|
||||
tmp = new PECallFunction(cur_pkg->second, use_name, parms);
|
||||
} while(0);
|
||||
|
||||
if (tmp == 0) {
|
||||
tmp = new PECallFunction(name, parms);
|
||||
}
|
||||
|
||||
FILE_NAME(tmp, loc);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
PCallTask* pform_make_call_task(const struct vlltype&loc,
|
||||
const pform_name_t&name,
|
||||
const list<PExpr*>&parms)
|
||||
{
|
||||
PCallTask*tmp = 0;
|
||||
|
||||
do {
|
||||
if (name.size() != 1)
|
||||
break;
|
||||
|
||||
perm_string use_name = peek_tail_name(name);
|
||||
|
||||
map<perm_string,PPackage*>::iterator cur_pkg;
|
||||
cur_pkg = lexical_scope->imports.find(use_name);
|
||||
if (cur_pkg == lexical_scope->imports.end())
|
||||
break;
|
||||
|
||||
tmp = new PCallTask(cur_pkg->second, name, parms);
|
||||
} while (0);
|
||||
|
||||
if (tmp == 0) {
|
||||
tmp = new PCallTask(name, parms);
|
||||
}
|
||||
|
||||
FILE_NAME(tmp, loc);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static void pform_put_behavior_in_scope(PProcess*pp)
|
||||
{
|
||||
lexical_scope->behaviors.push_back(pp);
|
||||
|
|
@ -2243,6 +2321,7 @@ void pform_makewire(const vlltype&li,
|
|||
first = first->next;
|
||||
} while (first != decls->next);
|
||||
|
||||
// The pform_set_data_type function will delete the names list.
|
||||
pform_set_data_type(li, data_type, names, type, 0);
|
||||
|
||||
// This time, go through the list, deleting cells as I'm done.
|
||||
|
|
@ -2264,6 +2343,35 @@ void pform_makewire(const vlltype&li,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This should eventually repliace the form above that takes a
|
||||
* net_decl_assign_t argument.
|
||||
*/
|
||||
void pform_makewire(const struct vlltype&li,
|
||||
std::list<PExpr*>*, str_pair_t ,
|
||||
std::list<decl_assignment_t*>*assign_list,
|
||||
NetNet::Type type,
|
||||
data_type_t*data_type)
|
||||
{
|
||||
list<perm_string>*names = new list<perm_string>;
|
||||
|
||||
for (list<decl_assignment_t*>::iterator cur = assign_list->begin()
|
||||
; cur != assign_list->end() ; ++ cur) {
|
||||
decl_assignment_t* curp = *cur;
|
||||
names->push_back(curp->name);
|
||||
}
|
||||
|
||||
pform_set_data_type(li, data_type, names, type, 0);
|
||||
|
||||
while (! assign_list->empty()) {
|
||||
decl_assignment_t*first = assign_list->front();
|
||||
assign_list->pop_front();
|
||||
// For now, do not handle assignment expressions.
|
||||
assert(! first->expr.get());
|
||||
delete first;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called by the parser to create task ports. The
|
||||
* resulting wire (which should be a register) is put into a list to
|
||||
|
|
|
|||
24
pform.h
24
pform.h
|
|
@ -57,6 +57,7 @@
|
|||
*/
|
||||
class PGate;
|
||||
class PExpr;
|
||||
class PPackage;
|
||||
class PSpecPath;
|
||||
class PClass;
|
||||
class PPackage;
|
||||
|
|
@ -207,10 +208,10 @@ extern void pform_start_package_declaration(const struct vlltype&loc,
|
|||
const char*type);
|
||||
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);
|
||||
PPackage*pkg, const char*ident);
|
||||
|
||||
extern PExpr* pform_package_ident(const struct vlltype&loc,
|
||||
const char*pkg_name, const char*ident);
|
||||
PPackage*pkg, pform_name_t*ident);
|
||||
|
||||
/*
|
||||
* This creates an identifier aware of names that may have been
|
||||
|
|
@ -272,6 +273,18 @@ extern PGenerate* pform_parent_generate(void);
|
|||
|
||||
extern void pform_set_typedef(perm_string name, data_type_t*data_type);
|
||||
|
||||
/*
|
||||
* This function makes a PECallFunction of the named function. Decide
|
||||
* if this function is in the scope or is imported from a package.
|
||||
*/
|
||||
extern PECallFunction* pform_make_call_function(const struct vlltype&loc,
|
||||
const pform_name_t&name,
|
||||
const std::list<PExpr*>&parms);
|
||||
extern PCallTask* pform_make_call_task(const struct vlltype&loc,
|
||||
const pform_name_t&name,
|
||||
const std::list<PExpr*>&parms);
|
||||
|
||||
|
||||
/*
|
||||
* The makewire functions announce to the pform code new wires. These
|
||||
* go into a module that is currently opened.
|
||||
|
|
@ -301,6 +314,13 @@ extern void pform_makewire(const struct vlltype&li,
|
|||
NetNet::Type type,
|
||||
data_type_t*data_type);
|
||||
|
||||
extern void pform_makewire(const struct vlltype&li,
|
||||
std::list<PExpr*>*delay,
|
||||
str_pair_t str,
|
||||
std::list<decl_assignment_t*>*assign_list,
|
||||
NetNet::Type type,
|
||||
data_type_t*data_type);
|
||||
|
||||
/* This form handles nets declared as structures. (See pform_struct_type.cc) */
|
||||
extern void pform_makewire(const struct vlltype&li,
|
||||
struct_type_t*struct_type,
|
||||
|
|
|
|||
|
|
@ -239,6 +239,8 @@ void PEConcat::dump(ostream&out) const
|
|||
|
||||
void PECallFunction::dump(ostream &out) const
|
||||
{
|
||||
if (package_) out << package_->pscope_name() << "::";
|
||||
|
||||
out << path_ << "(";
|
||||
|
||||
if (! parms_.empty()) {
|
||||
|
|
@ -1537,5 +1539,7 @@ void PPackage::pform_dump(std::ostream&out) const
|
|||
out << "package " << pscope_name() << endl;
|
||||
dump_localparams_(out, 4);
|
||||
dump_parameters_(out, 4);
|
||||
dump_tasks_(out, 4);
|
||||
dump_funcs_(out, 4);
|
||||
out << "endpackage" << endl;
|
||||
}
|
||||
|
|
|
|||
117
pform_package.cc
117
pform_package.cc
|
|
@ -71,18 +71,8 @@ void pform_end_package_declaration(const struct vlltype&loc)
|
|||
* package is declared in pform ahead of time (it is) and that we can
|
||||
* simply transfer definitions to the current scope (we can).
|
||||
*/
|
||||
void pform_package_import(const struct vlltype&, const char*pkg_name, const char*ident)
|
||||
void pform_package_import(const struct vlltype&, PPackage*pkg, const char*ident)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
PPackage*pkg = pcur->second;
|
||||
LexicalScope*scope = pform_peek_scope();
|
||||
|
||||
if (ident) {
|
||||
|
|
@ -90,15 +80,50 @@ void pform_package_import(const struct vlltype&, const char*pkg_name, const char
|
|||
|
||||
map<perm_string,LexicalScope::param_expr_t>::const_iterator cur
|
||||
= pkg->parameters.find(use_ident);
|
||||
if (cur == pkg->parameters.end()) {
|
||||
ostringstream msg;
|
||||
msg << "Symbol " << use_ident
|
||||
<< " not found in package " << pcur->first << "." << ends;
|
||||
VLerror(msg.str().c_str());
|
||||
if (cur != pkg->parameters.end()) {
|
||||
scope->imports[cur->first] = pkg;
|
||||
return;
|
||||
}
|
||||
|
||||
scope->imports[cur->first] = pkg;
|
||||
cur = pkg->localparams.find(use_ident);
|
||||
if (cur != pkg->localparams.end()) {
|
||||
scope->imports[cur->first] = pkg;
|
||||
return;
|
||||
}
|
||||
|
||||
map<perm_string,data_type_t*>::const_iterator tcur;
|
||||
tcur = pkg->typedefs.find(use_ident);
|
||||
if (tcur != pkg->typedefs.end()) {
|
||||
scope->imports[tcur->first] = pkg;
|
||||
return;
|
||||
}
|
||||
|
||||
map<perm_string,PFunction*>::const_iterator fcur;
|
||||
fcur = pkg->funcs.find(use_ident);
|
||||
if (fcur != pkg->funcs.end()) {
|
||||
scope->imports[fcur->first] = pkg;
|
||||
return;
|
||||
}
|
||||
|
||||
map<perm_string,PTask*>::const_iterator ttcur;
|
||||
ttcur = pkg->tasks.find(use_ident);
|
||||
if (ttcur != pkg->tasks.end()) {
|
||||
scope->imports[ttcur->first] = pkg;
|
||||
return;
|
||||
}
|
||||
|
||||
map<perm_string,PWire*>::const_iterator wcur;
|
||||
wcur = pkg->wires.find(use_ident);
|
||||
if (wcur != pkg->wires.end()) {
|
||||
scope->imports[wcur->first] = pkg;
|
||||
return;
|
||||
}
|
||||
|
||||
ostringstream msg;
|
||||
msg << "Symbol " << use_ident
|
||||
<< " not found in package " << pkg->pscope_name() << "." << ends;
|
||||
VLerror(msg.str().c_str());
|
||||
return;
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -109,24 +134,56 @@ void pform_package_import(const struct vlltype&, const char*pkg_name, const char
|
|||
|
||||
scope->imports[cur->first] = pkg;
|
||||
}
|
||||
|
||||
for (map<perm_string,LexicalScope::param_expr_t>::const_iterator cur = pkg->localparams.begin()
|
||||
; cur != pkg->localparams.end() ; ++cur) {
|
||||
|
||||
scope->imports[cur->first] = pkg;
|
||||
}
|
||||
|
||||
for (map<perm_string,data_type_t*>::const_iterator cur = pkg->typedefs.begin()
|
||||
; cur != pkg->typedefs.end() ; ++cur) {
|
||||
|
||||
scope->imports[cur->first] = pkg;
|
||||
}
|
||||
|
||||
for (map<perm_string,PFunction*>::const_iterator cur = pkg->funcs.begin()
|
||||
; cur != pkg->funcs.end() ; ++cur) {
|
||||
|
||||
scope->imports[cur->first] = pkg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PExpr* pform_package_ident(const struct vlltype&loc,
|
||||
const char*pkg_name, const char*ident_name)
|
||||
PPackage*pkg, pform_name_t*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);
|
||||
assert(ident_name);
|
||||
PEIdent*tmp = new PEIdent(pkg, *ident_name);
|
||||
FILE_NAME(tmp, loc);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
data_type_t* pform_test_type_identifier(PPackage*pkg, const char*txt)
|
||||
{
|
||||
perm_string use_name = lex_strings.make(txt);
|
||||
map<perm_string,data_type_t*>::const_iterator cur = pkg->typedefs.find(use_name);
|
||||
if (cur != pkg->typedefs.end())
|
||||
return cur->second;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The lexor uses this function to know if the
|
||||
*/
|
||||
PPackage* pform_test_package_identifier(const char*pkg_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())
|
||||
return 0;
|
||||
|
||||
assert(pcur->second);
|
||||
return pcur->second;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2035,14 +2035,14 @@ extern "C" const char* ivl_scope_name(ivl_scope_t net)
|
|||
extern "C" unsigned ivl_scope_params(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->nparam_;
|
||||
return net->param.size();
|
||||
}
|
||||
|
||||
extern "C" ivl_parameter_t ivl_scope_param(ivl_scope_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->nparam_);
|
||||
return net->param_ + idx;
|
||||
assert(idx < net->param.size());
|
||||
return & (net->param[idx]);
|
||||
}
|
||||
|
||||
extern "C" ivl_scope_t ivl_scope_parent(ivl_scope_t net)
|
||||
|
|
|
|||
36
t-dll.cc
36
t-dll.cc
|
|
@ -259,6 +259,13 @@ ivl_scope_t dll_target::find_scope(ivl_design_s &des, const NetScope*cur)
|
|||
return scope;
|
||||
}
|
||||
|
||||
for (size_t idx = 0; idx < des.packages.size(); idx += 1) {
|
||||
assert(des.packages[idx]);
|
||||
ivl_scope_t scope = find_scope_from_root(des.packages[idx], cur);
|
||||
if (scope)
|
||||
return scope;
|
||||
}
|
||||
|
||||
for (map<const NetScope*,ivl_scope_t>::iterator idx = des.classes.begin()
|
||||
; idx != des.classes.end() ; ++ idx) {
|
||||
ivl_scope_t scope = find_scope_from_root(idx->second, cur);
|
||||
|
|
@ -467,9 +474,9 @@ ivl_parameter_t dll_target::scope_find_param(ivl_scope_t scope,
|
|||
const char*name)
|
||||
{
|
||||
unsigned idx = 0;
|
||||
while (idx < scope->nparam_) {
|
||||
if (strcmp(name, scope->param_[idx].basename) == 0)
|
||||
return scope->param_ + idx;
|
||||
while (idx < scope->param.size()) {
|
||||
if (strcmp(name, scope->param[idx].basename) == 0)
|
||||
return &scope->param[idx];
|
||||
|
||||
idx += 1;
|
||||
}
|
||||
|
|
@ -484,13 +491,12 @@ ivl_parameter_t dll_target::scope_find_param(ivl_scope_t scope,
|
|||
*/
|
||||
void dll_target::make_scope_parameters(ivl_scope_t scop, const NetScope*net)
|
||||
{
|
||||
scop->nparam_ = net->parameters.size();
|
||||
if (scop->nparam_ == 0) {
|
||||
scop->param_ = 0;
|
||||
if (net->parameters.size() == 0) {
|
||||
scop->param.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
scop->param_ = new struct ivl_parameter_s [scop->nparam_];
|
||||
scop->param.resize(net->parameters.size());
|
||||
|
||||
unsigned idx = 0;
|
||||
typedef map<perm_string,NetScope::param_expr_t>::const_iterator pit_t;
|
||||
|
|
@ -498,14 +504,20 @@ void dll_target::make_scope_parameters(ivl_scope_t scop, const NetScope*net)
|
|||
for (pit_t cur_pit = net->parameters.begin()
|
||||
; cur_pit != net->parameters.end() ; ++ cur_pit ) {
|
||||
|
||||
assert(idx < scop->nparam_);
|
||||
ivl_parameter_t cur_par = scop->param_ + idx;
|
||||
cur_par->basename = (*cur_pit).first;
|
||||
assert(idx < scop->param.size());
|
||||
ivl_parameter_t cur_par = &scop->param[idx];
|
||||
cur_par->basename = cur_pit->first;
|
||||
cur_par->local = cur_pit->second.local_flag;
|
||||
cur_par->scope = scop;
|
||||
FILE_NAME(cur_par, &((*cur_pit).second));
|
||||
FILE_NAME(cur_par, &(cur_pit->second));
|
||||
|
||||
NetExpr*etmp = (*cur_pit).second.val;
|
||||
NetExpr*etmp = cur_pit->second.val;
|
||||
if (etmp == 0) {
|
||||
cerr << "?:?: internal error: "
|
||||
<< "What is the parameter expression for " << cur_pit->first
|
||||
<< " in " << net->fullname() << "?" << endl;
|
||||
}
|
||||
assert(etmp);
|
||||
make_scope_param_expr(cur_par, etmp);
|
||||
idx += 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue