From 18eb34921f6370e81eeefad971ec9a2c65fa8889 Mon Sep 17 00:00:00 2001 From: steve Date: Fri, 7 Jul 2000 04:53:53 +0000 Subject: [PATCH] Add support for non-constant delays in delay statements, Support evaluating ! in constant expressions, and move some code from netlist.cc to net_proc.cc. --- Makefile.in | 5 +-- README.txt | 5 --- design_dump.cc | 15 +++++++-- elaborate.cc | 42 ++++++++++++++++++++---- eval_tree.cc | 49 +++++++++++++++++++++++++++- net_proc.cc | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ netlist.cc | 33 ++++--------------- netlist.h | 31 +++++++++++++++--- parse.y | 5 +-- t-vvm.cc | 34 +++++++++++++++---- 10 files changed, 248 insertions(+), 59 deletions(-) create mode 100644 net_proc.cc diff --git a/Makefile.in b/Makefile.in index 1d6cd6fe4..c1570e81a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -18,7 +18,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.58 2000/06/25 19:59:41 steve Exp $" +#ident "$Id: Makefile.in,v 1.59 2000/07/07 04:53:53 steve Exp $" # # SHELL = /bin/sh @@ -73,7 +73,8 @@ O = main.o cprop.o design_dump.o dup_expr.o elaborate.o elab_expr.o \ elab_net.o elab_pexpr.o elab_scope.o elab_sig.o emit.o eval.o eval_tree.o \ expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ mangle.o netlist.o \ -net_design.o net_event.o net_force.o net_link.o net_scope.o net_udp.o \ +net_design.o net_event.o net_force.o net_link.o net_proc.o net_scope.o \ +net_udp.o \ pad_to_width.o \ parse.o parse_misc.o pform.o pform_dump.o \ set_width.o \ diff --git a/README.txt b/README.txt index 460091960..b6abf729d 100644 --- a/README.txt +++ b/README.txt @@ -331,11 +331,6 @@ current state of support for Verilog. - System functions are supported, but the compiler presumes that they return 32 bits. This is the typical case. - - non-constant delay expressions, i.e.: - - reg [7:0] del; - always #(reg) $display($time,,"del = %d", del); // sorry - - Specify blocks are parsed but ignored in general. diff --git a/design_dump.cc b/design_dump.cc index a6235b3a7..4969053bd 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: design_dump.cc,v 1.88 2000/06/25 19:59:42 steve Exp $" +#ident "$Id: design_dump.cc,v 1.89 2000/07/07 04:53:53 steve Exp $" #endif /* @@ -626,7 +626,13 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const void NetPDelay::dump(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "#" << delay_; + if (expr_) { + o << setw(ind) << "" << "#" << *expr_; + + } else { + o << setw(ind) << "" << "#" << delay_; + } + if (statement_) { o << endl; statement_->dump(o, ind+2); @@ -967,6 +973,11 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.89 2000/07/07 04:53:53 steve + * Add support for non-constant delays in delay statements, + * Support evaluating ! in constant expressions, and + * move some code from netlist.cc to net_proc.cc. + * * Revision 1.88 2000/06/25 19:59:42 steve * Redesign Links to include the Nexus class that * carries properties of the connected set of links. diff --git a/elaborate.cc b/elaborate.cc index a028a44d0..89471519f 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elaborate.cc,v 1.176 2000/06/13 03:24:48 steve Exp $" +#ident "$Id: elaborate.cc,v 1.177 2000/07/07 04:53:54 steve Exp $" #endif /* @@ -1573,21 +1573,44 @@ NetDeassign* PDeassign::elaborate(Design*des, const string&path) const return dev; } +/* + * Elaborate the delay statment (of the form # ) as a + * NetPDelay object. If the expression is constant, evaluate it now + * and make a constant delay. If not, then pass an elaborated + * expression to the constructor of NetPDelay so that the code + * generator knows to evaluate the expression at run time. + */ NetProc* PDelayStatement::elaborate(Design*des, const string&path) const { + NetScope*scope = des->find_scope(path); + assert(scope); + verinum*num = delay_->eval_const(des, path); if (num == 0) { - cerr << get_line() << ": sorry: delay expression " - "must be constant." << endl; - return 0; + /* Ah, the delay is not constant. OK, elaborate the + expression and let the run-time handle it. */ + NetExpr*dex = delay_->elaborate_expr(des, scope); + if (statement_) + return new NetPDelay(dex, statement_->elaborate(des, path)); + else + return new NetPDelay(dex, 0); } assert(num); + + /* If there is a statement, then elaborate it and create a + NetPDelay statement to contain it. Note that we create a + NetPDelay statement even if the value is 0 because #0 does + in fact have a well defined meaning in Verilog. */ + unsigned long val = num->as_ulong(); - if (statement_) - return new NetPDelay(val, statement_->elaborate(des, path)); - else + if (statement_) { + NetProc*stmt = statement_->elaborate(des, path); + return new NetPDelay(val, stmt); + + } else { return new NetPDelay(val, 0); + } } /* @@ -2435,6 +2458,11 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.177 2000/07/07 04:53:54 steve + * Add support for non-constant delays in delay statements, + * Support evaluating ! in constant expressions, and + * move some code from netlist.cc to net_proc.cc. + * * Revision 1.176 2000/06/13 03:24:48 steve * Index in memory assign should be a NetExpr. * diff --git a/eval_tree.cc b/eval_tree.cc index 51f79077c..e531b7dfd 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: eval_tree.cc,v 1.10 2000/04/28 18:43:23 steve Exp $" +#ident "$Id: eval_tree.cc,v 1.11 2000/07/07 04:53:54 steve Exp $" #endif # include "netlist.h" @@ -273,8 +273,55 @@ NetExpr* NetEParam::eval_tree() return res->dup_expr(); } +NetEConst* NetEUnary::eval_tree() +{ + NetExpr*oper = expr_->eval_tree(); + NetEConst*rval = dynamic_cast(oper); + + if (rval == 0) + return 0; + + verinum val = rval->value(); + + switch (op_) { + + case '!': { + /* Evaluate the unary logical not by first scanning + the operand value for V1 and Vx bits. If we find + any V1 bits we know that the value is TRUE, so + the result of ! is V0. If there are no V1 bits + but there are some Vx/Vz bits, the result is + unknown. Otherwise, the result is V1. */ + unsigned v1 = 0, vx = 0; + for (unsigned idx = 0 ; idx < val.len() ; idx += 1) { + switch (val.get(idx)) { + case verinum::V0: + break; + case verinum::V1: + v1 += 1; + break; + default: + vx += 1; + break; + } + } + verinum out(v1? verinum::V0 : (vx? verinum::Vx : verinum::V1)); + return new NetEConst(out); + } + + default: + delete rval; + return 0; + } +} + /* * $Log: eval_tree.cc,v $ + * Revision 1.11 2000/07/07 04:53:54 steve + * Add support for non-constant delays in delay statements, + * Support evaluating ! in constant expressions, and + * move some code from netlist.cc to net_proc.cc. + * * Revision 1.10 2000/04/28 18:43:23 steve * integer division in expressions properly get width. * diff --git a/net_proc.cc b/net_proc.cc new file mode 100644 index 000000000..43b78b47d --- /dev/null +++ b/net_proc.cc @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2000 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(WINNT) && !defined(macintosh) +#ident "$Id: net_proc.cc,v 1.1 2000/07/07 04:53:54 steve Exp $" +#endif + +# include "netlist.h" +# include + +NetForever::NetForever(NetProc*p) +: statement_(p) +{ +} + +NetForever::~NetForever() +{ + delete statement_; +} + +NetPDelay::NetPDelay(unsigned long d, NetProc*st) +: delay_(d), expr_(0), statement_(st) +{ +} + +NetPDelay::NetPDelay(NetExpr*d, NetProc*st) +: delay_(0), expr_(d), statement_(st) +{ +} + +NetPDelay::~NetPDelay() +{ + if (expr_) delete expr_; +} + +unsigned long NetPDelay::delay() const +{ + assert(expr_ == 0); + return delay_; +} + +const NetExpr* NetPDelay::expr() const +{ + return expr_; +} + +NetRepeat::NetRepeat(NetExpr*e, NetProc*p) +: expr_(e), statement_(p) +{ +} + +NetRepeat::~NetRepeat() +{ + delete expr_; + delete statement_; +} + +const NetExpr* NetRepeat::expr() const +{ + return expr_; +} + + + +/* + * $Log: net_proc.cc,v $ + * Revision 1.1 2000/07/07 04:53:54 steve + * Add support for non-constant delays in delay statements, + * Support evaluating ! in constant expressions, and + * move some code from netlist.cc to net_proc.cc. + * + */ + diff --git a/netlist.cc b/netlist.cc index 49ed2c46c..05bb214d0 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.cc,v 1.131 2000/06/25 19:59:42 steve Exp $" +#ident "$Id: netlist.cc,v 1.132 2000/07/07 04:53:54 steve Exp $" #endif # include @@ -2241,16 +2241,6 @@ NetEUBits::~NetEUBits() { } -NetForever::NetForever(NetProc*p) -: statement_(p) -{ -} - -NetForever::~NetForever() -{ - delete statement_; -} - NetLogic::NetLogic(const string&n, unsigned pins, TYPE t) : NetNode(n, pins), type_(t) { @@ -2262,22 +2252,6 @@ NetLogic::NetLogic(const string&n, unsigned pins, TYPE t) } } -NetRepeat::NetRepeat(NetExpr*e, NetProc*p) -: expr_(e), statement_(p) -{ -} - -NetRepeat::~NetRepeat() -{ - delete expr_; - delete statement_; -} - -const NetExpr* NetRepeat::expr() const -{ - return expr_; -} - NetTaskDef::NetTaskDef(const string&n, const svector&po) : name_(n), proc_(0), ports_(po) { @@ -2464,6 +2438,11 @@ bool NetUDP::sequ_glob_(string input, char output) /* * $Log: netlist.cc,v $ + * Revision 1.132 2000/07/07 04:53:54 steve + * Add support for non-constant delays in delay statements, + * Support evaluating ! in constant expressions, and + * move some code from netlist.cc to net_proc.cc. + * * Revision 1.131 2000/06/25 19:59:42 steve * Redesign Links to include the Nexus class that * carries properties of the connected set of links. diff --git a/netlist.h b/netlist.h index d08ffc4ea..f9952b295 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.h,v 1.143 2000/06/25 19:59:42 steve Exp $" +#ident "$Id: netlist.h,v 1.144 2000/07/07 04:53:54 steve Exp $" #endif /* @@ -1626,13 +1626,29 @@ class NetFuncDef { svectorports_; }; +/* + * This class represents delay statements of the form: + * + * # + * + * Where the statement may be null. The delay is evaluated at + * elaboration time to make a constant unsigned long that is the delay + * in simulation ticks. + * + * If the delay expression is non-constant, construct the NetPDelay + * object with a NetExpr* instead of the d value, and use th expr() + * method to get the expression. If expr() returns 0, use the delay() + * method to get the constant delay. + */ class NetPDelay : public NetProc { public: - NetPDelay(unsigned long d, NetProc*st) - : delay_(d), statement_(st) { } + NetPDelay(unsigned long d, NetProc*st); + NetPDelay(NetExpr* d, NetProc*st); + ~NetPDelay(); - unsigned long delay() const { return delay_; } + unsigned long delay() const; + const NetExpr*expr() const; virtual bool emit_proc(ostream&, struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -1641,6 +1657,7 @@ class NetPDelay : public NetProc { private: unsigned long delay_; + NetExpr*expr_; NetProc*statement_; }; @@ -2242,6 +2259,7 @@ class NetEUnary : public NetExpr { virtual bool set_width(unsigned w); virtual NetEUnary* dup_expr() const; + virtual NetEConst* eval_tree(); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -2630,6 +2648,11 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.144 2000/07/07 04:53:54 steve + * Add support for non-constant delays in delay statements, + * Support evaluating ! in constant expressions, and + * move some code from netlist.cc to net_proc.cc. + * * Revision 1.143 2000/06/25 19:59:42 steve * Redesign Links to include the Nexus class that * carries properties of the connected set of links. diff --git a/parse.y b/parse.y index 393e479e5..b69c910e7 100644 --- a/parse.y +++ b/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: parse.y,v 1.101 2000/06/30 15:50:20 steve Exp $" +#ident "$Id: parse.y,v 1.102 2000/07/07 04:53:54 steve Exp $" #endif # include "parse_misc.h" @@ -344,9 +344,6 @@ delay3_opt delay_value : expression { PExpr*tmp = $1; - if (! pform_expression_is_constant(tmp)) - yyerror(@1, "error: delay expression must " - "be constant."); $$ = tmp; } | expression ':' expression ':' expression diff --git a/t-vvm.cc b/t-vvm.cc index 6815df8e3..c971d5971 100644 --- a/t-vvm.cc +++ b/t-vvm.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-vvm.cc,v 1.160 2000/06/25 19:59:42 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.161 2000/07/07 04:53:54 steve Exp $" #endif # include @@ -3025,16 +3025,31 @@ void target_vvm::proc_while(ostream&os, const NetWhile*net) /* - * A delay suspends the thread for a period of time. + * A delay suspends the thread for a period of time. If the delay + * is an expression expresion, evaluate it at run time and use the + * unsigned interpretation of it as the actual delay. */ void target_vvm::proc_delay(ostream&os, const NetPDelay*proc) { thread_step_ += 1; - defn << " thr->step_ = &" << thread_class_ << "_step_" - << thread_step_ << "_;" << endl; - defn << " thr->thread_yield(" << proc->delay() << ");" << endl; - defn << " return false;" << endl; - defn << "}" << endl; + + if (proc->expr()) { + string rval = emit_proc_rval(this, proc->expr()); + defn << " thr->step_ = &" << thread_class_ << "_step_" + << thread_step_ << "_;" << endl; + defn << " thr->thread_yield(" << rval << ".as_unsigned());" + << endl; + defn << " return false;" << endl; + defn << "}" << endl; + + } else { + defn << " thr->step_ = &" << thread_class_ << "_step_" + << thread_step_ << "_;" << endl; + defn << " thr->thread_yield(" << proc->delay() << ");" + << endl; + defn << " return false;" << endl; + defn << "}" << endl; + } os << "static bool " << thread_class_ << "_step_" << thread_step_ << "_(vvm_thread*thr);" << endl; @@ -3068,6 +3083,11 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.161 2000/07/07 04:53:54 steve + * Add support for non-constant delays in delay statements, + * Support evaluating ! in constant expressions, and + * move some code from netlist.cc to net_proc.cc. + * * Revision 1.160 2000/06/25 19:59:42 steve * Redesign Links to include the Nexus class that * carries properties of the connected set of links.