diff --git a/PExpr.cc b/PExpr.cc index ba6451891..67f40bde5 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -174,7 +174,7 @@ PEBShift::~PEBShift() } PECallFunction::PECallFunction(const pform_name_t&n, const vector &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 &parms) +: package_(pkg), path_(pn_from_ps(n)), parms_(parms.size()) +{ + int tmp_idx = 0; + assert(parms_.size() == parms.size()); + for (list::const_iterator idx = parms.begin() + ; idx != parms.end() ; ++idx) + parms_[tmp_idx++] = *idx; +} + PECallFunction::PECallFunction(perm_string n, const vector&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 &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 &parms) } PECallFunction::PECallFunction(perm_string n, const list&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() diff --git a/PExpr.h b/PExpr.h index 21dd268c7..392ad2a01 100644 --- a/PExpr.h +++ b/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 &parms); + // Call function defined in package. + explicit PECallFunction(PPackage*pkg, perm_string n, const std::vector &parms); + explicit PECallFunction(PPackage*pkg, perm_string n, const std::list &parms); + // Call of system function (name is not hierarchical) explicit PECallFunction(perm_string n, const vector &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 &parms); explicit PECallFunction(perm_string n, const list &parms); @@ -794,14 +798,17 @@ class PECallFunction : public PExpr { width_mode_t&mode); private: + PPackage*package_; pform_name_t path_; - vector parms_; + std::vector 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&parms, diff --git a/PPackage.h b/PPackage.h index 3e498d0c4..6bd01c9c8 100644 --- a/PPackage.h +++ b/PPackage.h @@ -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; }; diff --git a/Statement.cc b/Statement.cc index 54e9ad1b1..79d63fb63 100644 --- a/Statement.cc +++ b/Statement.cc @@ -127,7 +127,18 @@ void PBlock::set_statement(const vector&st) } PCallTask::PCallTask(const pform_name_t&n, const list&p) -: path_(n), parms_(p.size()) +: package_(0), path_(n), parms_(p.size()) +{ + list::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&p) +: package_(pkg), path_(n), parms_(p.size()) { list::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&p) } PCallTask::PCallTask(perm_string n, const list&p) -: parms_(p.size()) +: package_(0), parms_(p.size()) { list::const_iterator cur = p.begin(); for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) { diff --git a/Statement.h b/Statement.h index c96d7706a..43f299443 100644 --- a/Statement.h +++ b/Statement.h @@ -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&parms); explicit PCallTask(const pform_name_t&n, const list&parms); explicit PCallTask(perm_string n, const list&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 parms_; }; diff --git a/elab_expr.cc b/elab_expr.cc index 50c1fb199..e8cf64fdc 100644 --- a/elab_expr.cc +++ b/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); } } diff --git a/elab_lval.cc b/elab_lval.cc index 02095f800..f53acc58d 100644 --- a/elab_lval.cc +++ b/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 { diff --git a/elab_scope.cc b/elab_scope.cc index 70e8b4d97..a1d07df66 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -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; } diff --git a/elab_sig.cc b/elab_sig.cc index 7d2871a34..7db92eb6e 100644 --- a/elab_sig.cc +++ b/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; diff --git a/elaborate.cc b/elaborate.cc index 5de506473..1f4857cb0 100644 --- a/elaborate.cc +++ b/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(listroots) { - svector root_elems(roots.size()); + vector root_elems(roots.size()); + vector pack_elems(pform_packages.size()); bool rc = true; unsigned i = 0; @@ -5310,6 +5337,7 @@ Design* elaborate(listroots) // Elaborate the packages. Package elaboration is simpler // because there are fewer sub-scopes involved. + i = 0; for (map::iterator pac = pform_packages.begin() ; pac != pform_packages.end() ; ++ pac) { @@ -5318,9 +5346,14 @@ Design* elaborate(listroots) 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::const_iterator root = roots.begin() ; root != roots.end() ; ++ root ) { @@ -5353,10 +5386,9 @@ Design* elaborate(listroots) // 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(listroots) // 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 << "" << ": 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 << "" << ": debug: " << rmod->mod_name() - << ": port elaboration root " - << rmod->port_count() << " ports" << endl; - } + if (debug_elaborate) { + cerr << "" << ": debug: " << rmod->mod_name() + << ": port elaboration root " + << rmod->port_count() << " ports" << endl; + } if (! rmod->elaborate_sig(des, scope)) { - if (debug_elaborate) { - cerr << "" << ": debug: " << rmod->mod_name() - << ": elaborate_sig failed!!!" << endl; - } + if (debug_elaborate) { + cerr << "" << ": debug: " << rmod->mod_name() + << ": elaborate_sig failed!!!" << endl; + } delete des; return 0; } @@ -5461,12 +5506,17 @@ Design* elaborate(listroots) // 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) { diff --git a/emit.cc b/emit.cc index bc7d19eb6..cab1d30d5 100644 --- a/emit.cc +++ b/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::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::const_iterator scope = root_scopes_.begin(); - scope != root_scopes_.end(); ++ scope ) - (*scope)->emit_scope(tgt); + // enumerate package scopes + for (map::const_iterator scope = packages_.begin() + ; scope != packages_.end() ; ++ scope) { + scope->second->emit_scope(tgt); + } + // enumerate root scopes + for (list::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::const_iterator scope = packages_.begin() + ; scope != packages_.end() ; ++ scope ) + tasks_rc &= scope->second->emit_defs(tgt); for (list::const_iterator scope = root_scopes_.begin() ; scope != root_scopes_.end(); ++ scope ) tasks_rc &= (*scope)->emit_defs(tgt); diff --git a/lexor.lex b/lexor.lex index 4d3619406..2a362be39 100644 --- a/lexor.lex +++ b/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()) { diff --git a/net_design.cc b/net_design.cc index 5d0c5b9d9..8f89b003a 100644 --- a/net_design.cc +++ b/net_design.cc @@ -400,9 +400,15 @@ void NetScope::run_defparams_later(Design*des) void Design::evaluate_parameters() { - for (list::const_iterator scope = root_scopes_.begin(); - scope != root_scopes_.end(); ++ scope ) + for (map::const_iterator cur = packages_.begin() + ; cur != packages_.end() ; ++ cur) { + cur->second->evaluate_parameters(this); + } + + for (list::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) diff --git a/parse.y b/parse.y index 49c2c30f8..88f8dcbef 100644 --- a/parse.y +++ b/parse.y @@ -401,6 +401,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector 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 list *dimensions; }; -%token IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL +%token IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL %token TYPE_IDENTIFIER +%token PACKAGE_IDENTIFIER %token DISCIPLINE_IDENTIFIER %token PATHPULSE_IDENTIFIER %token 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 empty; - PECallFunction*tmp = new PECallFunction(*$1, empty); - FILE_NAME(tmp, @1); + { const list 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 vectorempty; @@ -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 ';' { listpt; - 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."); listpt; - PCallTask*tmp = new PCallTask(*$1, pt); - FILE_NAME(tmp, @1); + PCallTask*tmp = pform_make_call_task(@1, *$1, pt); delete $1; $$ = tmp; } diff --git a/parse_misc.h b/parse_misc.h index a0a8fe817..8d1431542 100644 --- a/parse_misc.h +++ b/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 + * :: + * Then the parser calls this function to set the package context so + * that the lexor can interpret 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 diff --git a/pform.cc b/pform.cc index 3d43377d2..e817fb6cf 100644 --- a/pform.cc +++ b/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::const_iterator pkg = scope->imports.find(name.back().name); + map::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::iterator cur; + LexicalScope*cur_scope = lexical_scope; do { + map::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::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&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::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&parms) +{ + PCallTask*tmp = 0; + + do { + if (name.size() != 1) + break; + + perm_string use_name = peek_tail_name(name); + + map::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*, str_pair_t , + std::list*assign_list, + NetNet::Type type, + data_type_t*data_type) +{ + list*names = new list; + + for (list::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 diff --git a/pform.h b/pform.h index e1ac7e1a9..20d039bc7 100644 --- a/pform.h +++ b/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&parms); +extern PCallTask* pform_make_call_task(const struct vlltype&loc, + const pform_name_t&name, + const std::list&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*delay, + str_pair_t str, + std::list*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, diff --git a/pform_dump.cc b/pform_dump.cc index 1b54b275d..7d6e9d67f 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -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; } diff --git a/pform_package.cc b/pform_package.cc index 24cf52da2..d8ebdf8ff 100644 --- a/pform_package.cc +++ b/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::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::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::const_iterator tcur; + tcur = pkg->typedefs.find(use_ident); + if (tcur != pkg->typedefs.end()) { + scope->imports[tcur->first] = pkg; + return; + } + + map::const_iterator fcur; + fcur = pkg->funcs.find(use_ident); + if (fcur != pkg->funcs.end()) { + scope->imports[fcur->first] = pkg; + return; + } + + map::const_iterator ttcur; + ttcur = pkg->tasks.find(use_ident); + if (ttcur != pkg->tasks.end()) { + scope->imports[ttcur->first] = pkg; + return; + } + + map::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::const_iterator cur = pkg->localparams.begin() + ; cur != pkg->localparams.end() ; ++cur) { + + scope->imports[cur->first] = pkg; + } + + for (map::const_iterator cur = pkg->typedefs.begin() + ; cur != pkg->typedefs.end() ; ++cur) { + + scope->imports[cur->first] = pkg; + } + + for (map::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::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::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::const_iterator pcur = pform_packages.find(use_name); + if (pcur == pform_packages.end()) + return 0; + + assert(pcur->second); + return pcur->second; +} diff --git a/t-dll-api.cc b/t-dll-api.cc index c7ad20ab0..0aa7dd577 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -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) diff --git a/t-dll.cc b/t-dll.cc index 4cd03970b..d7d4fb234 100644 --- a/t-dll.cc +++ b/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::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::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; } diff --git a/t-dll.h b/t-dll.h index e7639b0b0..2876a5aa2 100644 --- a/t-dll.h +++ b/t-dll.h @@ -653,8 +653,7 @@ struct ivl_scope_s { unsigned nlpm_; ivl_lpm_t* lpm_; - unsigned nparam_; - ivl_parameter_t param_; + std::vector param; /* Scopes that are tasks/functions have a definition. */ ivl_statement_t def;