From d6fe6ea9361d501d18250589df3ba9e09f962818 Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 24 Jul 2013 19:36:11 -0700 Subject: [PATCH] Add support for calling a user functions as a task (SV) --- PExpr.cc | 5 +++++ PExpr.h | 3 +++ elaborate.cc | 35 +++++++++++++++++++++++++++++------ pform_dump.cc | 5 ++++- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/PExpr.cc b/PExpr.cc index a9984adcd..09e9e73e5 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -178,6 +178,11 @@ PECallFunction::PECallFunction(const pform_name_t&n, const vector &parm { } +PECallFunction::PECallFunction(PPackage*pkg, const pform_name_t&n, const vector &parms) +: package_(pkg), path_(n), parms_(parms) +{ +} + static pform_name_t pn_from_ps(perm_string n) { name_component_t tmp_name (n); diff --git a/PExpr.h b/PExpr.h index 2c7dceb8f..40a75a9ed 100644 --- a/PExpr.h +++ b/PExpr.h @@ -814,6 +814,9 @@ class PECallFunction : public PExpr { explicit PECallFunction(PPackage*pkg, perm_string n, const std::vector &parms); explicit PECallFunction(PPackage*pkg, perm_string n, const std::list &parms); + // Used to convert a user function called as a task + explicit PECallFunction(PPackage*pkg, const pform_name_t&n, const std::vector &parms); + // Call of system function (name is not hierarchical) explicit PECallFunction(perm_string n, const vector &parms); explicit PECallFunction(perm_string n); diff --git a/elaborate.cc b/elaborate.cc index b519634af..084d627aa 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2212,7 +2212,23 @@ NetProc* Statement::elaborate(Design*des, NetScope*) const NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const { - assert(lval_); + // A function called as a task does not have an L-value. + if (! lval_) { + // The R-value must be a simple function call. + assert (dynamic_cast(rval_)); + PExpr::width_mode_t mode = PExpr::SIZED; + rval_->test_width(des, scope, mode); + // Create a L-value that matches the function return type. + netvector_t*tmp_vec = new netvector_t(rval_->expr_type(), + rval_->expr_width()-1, 0, + rval_->has_sign()); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), + NetNet::REG, tmp_vec); + tmp->set_file(rval_->get_file()); + tmp->set_lineno(rval_->get_lineno()); + NetAssign_*lv = new NetAssign_(tmp); + return lv; + } return lval_->elaborate_lval(des, scope, false, false); } @@ -3344,11 +3360,18 @@ NetProc* PCallTask::elaborate_function_(Design*des, NetScope*scope) const // call with a missing return assignment. if (! func) return 0; -// HERE: Should this be an assign to a dummy variable or something else? - cerr << get_fileline() << ": sorry: Icarus cannot currently call " - "functions like a tasks." << endl; - des->errors += 1; - return 0; + // Generate a function call version of this task call. + PExpr*rval = new PECallFunction(package_, path_, parms_); + rval->set_file(get_file()); + rval->set_lineno(get_lineno()); + // Generate an assign to nothing. + PAssign*tmp = new PAssign(0, rval); + tmp->set_file(get_file()); + tmp->set_lineno(get_lineno()); + cerr << get_fileline() << ": warning: User function '" + << peek_tail_name(path_) << "' is being called as a task." << endl; + // Elaborate the assignment to a dummy variable. + return tmp->elaborate(des, scope); } NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope, diff --git a/pform_dump.cc b/pform_dump.cc index 0a69ba2a1..4ab900fb1 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -684,7 +684,10 @@ void AContrib::dump(ostream&out, unsigned ind) const void PAssign::dump(ostream&out, unsigned ind) const { - out << setw(ind) << "" << *lval() << " = "; + out << setw(ind) << ""; + if (lval()) out << *lval(); + else out << ""; + out << " = "; if (delay_) out << "#" << *delay_ << " "; if (count_) out << "repeat(" << *count_ << ") "; if (event_) out << *event_ << " ";