diff --git a/AStatement.cc b/AStatement.cc index 4d59dffc2..a3617d6bf 100644 --- a/AStatement.cc +++ b/AStatement.cc @@ -25,12 +25,15 @@ AStatement::~AStatement() { } -AContrib::AContrib() +AContrib::AContrib(PExpr*lv, PExpr*rv) +: lval_(lv), rval_(rv) { } AContrib::~AContrib() { + delete lval_; + delete rval_; } AProcess::~AProcess() diff --git a/AStatement.h b/AStatement.h index fb00fc6ce..a1b2085ef 100644 --- a/AStatement.h +++ b/AStatement.h @@ -38,15 +38,29 @@ class AStatement : public LineInfo { AStatement& operator= (const AStatement&); }; +/* + * A contribution statement is like an assignment: there is an l-value + * expression and an r-value expression. The l-value is a branch probe + * expression. + */ class AContrib : public AStatement { public: - AContrib(); + AContrib(PExpr*lval, PExpr*rval); ~AContrib(); + virtual void dump(ostream&out, unsigned ind) const; + private: + PExpr*lval_; + PExpr*rval_; }; +/* + * An analog process is not a statement, but contains an analog + * statement. The process is where we attach process characteristics + * such as initial vs. always, attributes.... + */ class AProcess : public LineInfo { public: diff --git a/PExpr.cc b/PExpr.cc index 96428204f..ad2efbeda 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -90,7 +90,7 @@ PEBShift::~PEBShift() { } -PECallFunction::PECallFunction(const pform_name_t&n, const svector &parms) +PECallFunction::PECallFunction(const pform_name_t&n, const vector &parms) : path_(n), parms_(parms) { } @@ -103,7 +103,7 @@ static pform_name_t pn_from_ps(perm_string n) return tmp; } -PECallFunction::PECallFunction(perm_string n, const svector&parms) +PECallFunction::PECallFunction(perm_string n, const vector&parms) : path_(pn_from_ps(n)), parms_(parms) { } @@ -113,6 +113,17 @@ PECallFunction::PECallFunction(perm_string n) { } +// NOTE: Anachronism. Try to work all use of svector out. +PECallFunction::PECallFunction(const pform_name_t&n, const svector &parms) +: path_(n), parms_(vector_from_svector(parms)) +{ +} + +PECallFunction::PECallFunction(perm_string n, const svector&parms) +: path_(pn_from_ps(n)), parms_(vector_from_svector(parms)) +{ +} + PECallFunction::~PECallFunction() { } diff --git a/PExpr.h b/PExpr.h index 08dccdd29..7450e3e03 100644 --- a/PExpr.h +++ b/PExpr.h @@ -697,10 +697,15 @@ class PETernary : public PExpr { */ class PECallFunction : public PExpr { public: - explicit PECallFunction(const pform_name_t&n, const svector &parms); + explicit PECallFunction(const pform_name_t&n, const vector &parms); // Call of system function (name is not hierarchical) - explicit PECallFunction(perm_string n, const svector &parms); + explicit PECallFunction(perm_string n, const vector &parms); explicit PECallFunction(perm_string n); + + // svector versions. Should be removed! + explicit PECallFunction(const pform_name_t&n, const svector &parms); + explicit PECallFunction(perm_string n, const svector &parms); + ~PECallFunction(); virtual void dump(ostream &) const; @@ -721,7 +726,7 @@ class PECallFunction : public PExpr { private: pform_name_t path_; - svector parms_; + vector parms_; bool check_call_matches_definition_(Design*des, NetScope*dscope) const; diff --git a/elab_expr.cc b/elab_expr.cc index 2939b91d9..6f8470dbf 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -449,7 +449,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w and makes it into a signed expression. No bits are changed, it just changes the interpretation. */ if (strcmp(peek_tail_name(path_), "$signed") == 0) { - if ((parms_.count() != 1) || (parms_[0] == 0)) { + if ((parms_.size() != 1) || (parms_[0] == 0)) { cerr << get_fileline() << ": error: The $signed() function " << "takes exactly one(1) argument." << endl; des->errors += 1; @@ -463,7 +463,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w } /* add $unsigned to match $signed */ if (strcmp(peek_tail_name(path_), "$unsigned") == 0) { - if ((parms_.count() != 1) || (parms_[0] == 0)) { + if ((parms_.size() != 1) || (parms_[0] == 0)) { cerr << get_fileline() << ": error: The $unsigned() function " << "takes exactly one(1) argument." << endl; des->errors += 1; @@ -486,7 +486,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w deleted. */ if ((strcmp(peek_tail_name(path_), "$sizeof") == 0) || (strcmp(peek_tail_name(path_), "$bits") == 0)) { - if ((parms_.count() != 1) || (parms_[0] == 0)) { + if ((parms_.size() != 1) || (parms_[0] == 0)) { cerr << get_fileline() << ": error: The $bits() function " << "takes exactly one(1) argument." << endl; des->errors += 1; @@ -522,7 +522,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w otherwise. The subexpression is elaborated but not evaluated. */ if (strcmp(peek_tail_name(path_), "$is_signed") == 0) { - if ((parms_.count() != 1) || (parms_[0] == 0)) { + if ((parms_.size() != 1) || (parms_[0] == 0)) { cerr << get_fileline() << ": error: The $is_signed() function " << "takes exactly one(1) argument." << endl; des->errors += 1; @@ -558,7 +558,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w Functions cannot really take empty parameters, but the case ``func()'' is the same as no parameters at all. So catch that special case here. */ - unsigned nparms = parms_.count(); + unsigned nparms = parms_.size(); if ((nparms == 1) && (parms_[0] == 0)) nparms = 0; @@ -622,7 +622,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope, if (! check_call_matches_definition_(des, dscope)) return 0; - unsigned parms_count = parms_.count(); + unsigned parms_count = parms_.size(); if ((parms_count == 1) && (parms_[0] == 0)) parms_count = 0; diff --git a/elab_net.cc b/elab_net.cc index f00936882..09c040de0 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -1466,7 +1466,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope, forces it to be a signed result. Otherwise, it is as if the $signed did not exist. */ if (strcmp(name, "$signed") == 0) { - if ((parms_.count() != 1) || (parms_[0] == 0)) { + if ((parms_.size() != 1) || (parms_[0] == 0)) { cerr << get_fileline() << ": error: The $signed() function " << "takes exactly one(1) argument." << endl; des->errors += 1; @@ -1482,7 +1482,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope, /* handle $unsigned like $signed */ if (strcmp(name, "$unsigned") == 0) { - if ((parms_.count() != 1) || (parms_[0] == 0)) { + if ((parms_.size() != 1) || (parms_[0] == 0)) { cerr << get_fileline() << ": error: The $unsigned() function " << "takes exactly one(1) argument." << endl; des->errors += 1; @@ -1514,7 +1514,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope, } NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(), - def, 1+parms_.count()); + def, 1+parms_.size()); net->set_line(*this); net->rise_time(rise); net->fall_time(fall); @@ -1531,7 +1531,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope, connect(net->pin(0), osig->pin(0)); unsigned errors = 0; - for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) { + for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) { NetNet*tmp = parms_[idx]->elaborate_net(des, scope, 0, 0, 0, 0, Link::STRONG, Link::STRONG); diff --git a/net_func.cc b/net_func.cc index 5a4d4e5bb..564d16258 100644 --- a/net_func.cc +++ b/net_func.cc @@ -104,7 +104,7 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope) 1 nil pointer. This is how the parser tells me of no parameter. In other words, ``func()'' is 1 nil parameter. */ - unsigned parms_count = parms_.count(); + unsigned parms_count = parms_.size(); if ((parms_count == 1) && (parms_[0] == 0)) parms_count = 0; diff --git a/parse.y b/parse.y index 0bea41113..af4c89bd6 100644 --- a/parse.y +++ b/parse.y @@ -283,6 +283,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) %type hierarchy_identifier %type expression expr_primary expr_mintypmax %type lpvalue +%type branch_probe_expression %type delay_value delay_value_simple %type delay1 delay3 delay3_opt delay_value_list %type expression_list_with_nuls expression_list_proper @@ -854,7 +855,9 @@ event_expression function name really is a nature attribute identifier. */ branch_probe_expression : IDENTIFIER '(' IDENTIFIER ',' IDENTIFIER ')' + { $$ = pform_make_branch_probe_expression(@1, $1, $3, $5); } | IDENTIFIER '(' IDENTIFIER ')' + { $$ = pform_make_branch_probe_expression(@1, $1, $3); } ; expression @@ -3728,7 +3731,7 @@ statement_or_null analog_statement : branch_probe_expression K_CONTRIBUTE expression ';' - { $$ = pform_contribution_statement(@2); } + { $$ = pform_contribution_statement(@2, $1, $3); } ; /* Task items are, other than the statement, task port items and diff --git a/pform.h b/pform.h index c3a5f7652..c5040585c 100644 --- a/pform.h +++ b/pform.h @@ -396,6 +396,12 @@ extern void pform_dump(ostream&out, const discipline_t*); extern void pform_make_analog_behavior(const struct vlltype&loc, AProcess::Type type, AStatement*st); -extern AStatement*pform_contribution_statement(const struct vlltype&loc); +extern AStatement*pform_contribution_statement(const struct vlltype&loc, + PExpr*lval, PExpr*rval); +extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc, + char*name, char*n1, char*n2); + +extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc, + char*name, char*branch); #endif diff --git a/pform_analog.cc b/pform_analog.cc index 44c080458..55408452b 100644 --- a/pform_analog.cc +++ b/pform_analog.cc @@ -23,9 +23,10 @@ # include "parse_misc.h" # include "AStatement.h" -AStatement* pform_contribution_statement(const struct vlltype&loc) +AStatement* pform_contribution_statement(const struct vlltype&loc, + PExpr*lval, PExpr*rval) { - AContrib*tmp = new AContrib; + AContrib*tmp = new AContrib(lval, rval); FILE_NAME(tmp, loc); return tmp; } @@ -38,3 +39,31 @@ void pform_make_analog_behavior(const struct vlltype&loc, AProcess::Type pt, pform_put_behavior_in_scope(proc); } + +PExpr* pform_make_branch_probe_expression(const struct vlltype&loc, + char*name, char*n1, char*n2) +{ + vector parms (2); + parms[0] = new PEIdent(lex_strings.make(n1)); + FILE_NAME(parms[0], loc); + + parms[1] = new PEIdent(lex_strings.make(n2)); + FILE_NAME(parms[1], loc); + + PECallFunction*res = new PECallFunction(lex_strings.make(name), parms); + FILE_NAME(res, loc); + return res; +} + +PExpr* pform_make_branch_probe_expression(const struct vlltype&loc, + char*name, char*branch_name) +{ + vector parms (1); + parms[0] = new PEIdent(lex_strings.make(branch_name)); + FILE_NAME(parms[0], loc); + + PECallFunction*res = new PECallFunction(lex_strings.make(name), parms); + FILE_NAME(res, loc); + + return res; +} diff --git a/pform_dump.cc b/pform_dump.cc index 7ea9b37b1..4726aa3df 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -180,9 +180,9 @@ void PECallFunction::dump(ostream &out) const { out << path_ << "("; - if (parms_.count() > 0) { + if (parms_.size() > 0) { if (parms_[0]) parms_[0]->dump(out); - for (unsigned idx = 1; idx < parms_.count(); ++idx) { + for (unsigned idx = 1; idx < parms_.size(); ++idx) { out << ", "; if (parms_[idx]) parms_[idx]->dump(out); } @@ -541,6 +541,14 @@ void AStatement::dump(ostream&out, unsigned ind) const << " */ ;" << endl; } +void AContrib::dump(ostream&out, unsigned ind) const +{ + out << setw(ind) << ""; + out << *lval_ << " <+ " << *rval_ + << "; /* " << get_fileline() << " */" + << endl; +} + void PAssign::dump(ostream&out, unsigned ind) const { out << setw(ind) << ""; diff --git a/svector.h b/svector.h index 09181966d..c0f262e4c 100644 --- a/svector.h +++ b/svector.h @@ -1,7 +1,7 @@ #ifndef __svector_H #define __svector_H /* - * Copyright (c) 1999 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2008 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 @@ -20,12 +20,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifdef HAVE_CVS_IDENT -#ident "$Id: svector.h,v 1.11 2007/03/22 16:08:17 steve Exp $" -#endif # include "config.h" # include +# include # include /* @@ -106,41 +104,18 @@ template <> inline svector::svector(unsigned size) { } - /* - * $Log: svector.h,v $ - * Revision 1.11 2007/03/22 16:08:17 steve - * Spelling fixes from Larry - * - * Revision 1.10 2005/06/14 19:13:43 steve - * gcc3/4 compile errors. - * - * Revision 1.9 2003/07/23 02:35:44 steve - * Inline the svector constructor. - * - * Revision 1.8 2003/07/16 00:54:07 steve - * Needs the config.h header. - * - * Revision 1.7 2003/07/15 05:07:13 steve - * Move PUdp constructor into compiled file. - * - * Revision 1.6 2002/08/12 01:35:00 steve - * conditional ident string using autoconfig. - * - * Revision 1.5 2000/02/23 02:56:55 steve - * Macintosh compilers do not support ident. - * - * Revision 1.4 1999/06/15 03:44:53 steve - * Get rid of the STL vector template. - * - * Revision 1.3 1999/05/06 04:37:17 steve - * Get rid of list types. - * - * Revision 1.2 1999/05/01 02:57:53 steve - * Handle much more complex event expressions. - * - * Revision 1.1 1999/04/29 02:16:26 steve - * Parse OR of event expressions. - * - */ +* This is a convenience function that converts an svector to a +* vector. This is to ease the transition from svector to vector so +* that the svector class can be gradually removed. +*/ +template inline std::vector vector_from_svector(const svector&that) +{ + std::vector res (that.count()); + for (unsigned idx = 0 ; idx < that.count() ; idx += 1) + res[idx] = that[idx]; + + return res; +} + #endif