diff --git a/Makefile.in b/Makefile.in index c1c909b3b..8711dc937 100644 --- a/Makefile.in +++ b/Makefile.in @@ -16,7 +16,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.142 2003/01/18 23:56:06 steve Exp $" +#ident "$Id: Makefile.in,v 1.143 2003/01/26 21:15:58 steve Exp $" # # SHELL = /bin/sh @@ -128,11 +128,11 @@ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ load_module.o netlist.o netmisc.o net_assign.o \ net_design.o net_event.o net_expr.o net_force.o net_func.o \ net_link.o net_modulo.o net_nex_input.o net_nex_output.o \ -net_proc.o net_scope.o net_udp.o pad_to_width.o \ +net_proc.o net_scope.o net_udp.o net_variable.o pad_to_width.o \ parse.o parse_misc.o pform.o pform_dump.o \ set_width.o sync.o \ verinum.o verireal.o target.o targets.o \ -Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \ +Attrib.o HName.o LineInfo.o Module.o PData.o PDelays.o PEvent.o \ PExpr.o PGate.o \ PTask.o PFunction.o PWire.o Statement.o StringHeap.o \ $(FF) $(TT) diff --git a/Module.h b/Module.h index c7a06c8a7..b1f18a125 100644 --- a/Module.h +++ b/Module.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: Module.h,v 1.27 2002/08/19 02:39:16 steve Exp $" +#ident "$Id: Module.h,v 1.28 2003/01/26 21:15:58 steve Exp $" #endif # include @@ -29,6 +29,7 @@ # include "named.h" # include "LineInfo.h" # include +class PData; class PEvent; class PExpr; class PEIdent; @@ -97,6 +98,9 @@ class Module : public LineInfo { /* Keep a table of named events declared in the module. */ mapevents; + /* Keep a table of datum variables declared in the module. */ + mapdatum; + /* These are the timescale for this module. The default is set by the `timescale directive. */ int time_unit, time_precision; @@ -151,6 +155,10 @@ class Module : public LineInfo { /* * $Log: Module.h,v $ + * Revision 1.28 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.27 2002/08/19 02:39:16 steve * Support parameters with defined ranges. * diff --git a/PData.cc b/PData.cc new file mode 100644 index 000000000..7173a408c --- /dev/null +++ b/PData.cc @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2003 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 + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: PData.cc,v 1.1 2003/01/26 21:15:58 steve Exp $" +#endif + +# include "PData.h" + +PData::PData(const hname_t&h) +: hname_(h) +{ +} + +PData::~PData() +{ +} + +const hname_t&PData::name() const +{ + return hname_; +} + +/* + * $Log: PData.cc,v $ + * Revision 1.1 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * + */ + diff --git a/PData.h b/PData.h new file mode 100644 index 000000000..3fa1eb03e --- /dev/null +++ b/PData.h @@ -0,0 +1,63 @@ +#ifndef __PData_H +#define __PData_H +/* + * Copyright (c) 2003 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 + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: PData.h,v 1.1 2003/01/26 21:15:58 steve Exp $" +#endif + +# include "HName.h" +# include "netlist.h" +# include "LineInfo.h" + +/* + * The PData object represents declaration of atomic datum such as + * real and realtime variables. These are variables that cannot be bit + * or part selected, but can be used in expressions. + */ + +class PData : public LineInfo { + + public: + PData(const hname_t&hname); + ~PData(); + + // Return a hierarchical name. + const hname_t&name() const; + + void elaborate_scope(Design*des, NetScope*scope) const; + + map attributes; + + private: + hname_t hname_; + + private: + PData(const PData&); + PData& operator= (const PData&); +}; + +/* + * $Log: PData.h,v $ + * Revision 1.1 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * + */ +#endif diff --git a/PWire.h b/PWire.h index 5b0ce4019..27ff7a1c2 100644 --- a/PWire.h +++ b/PWire.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PWire.h,v 1.14 2002/08/12 01:34:58 steve Exp $" +#ident "$Id: PWire.h,v 1.15 2003/01/26 21:15:58 steve Exp $" #endif # include "netlist.h" @@ -53,7 +53,6 @@ class PWire : public LineInfo { PWire(char*name, NetNet::Type t, NetNet::PortType pt); // Return a hierarchical name. - //const string name() const; const hname_t&path() const; NetNet::Type get_wire_type() const; @@ -101,6 +100,10 @@ class PWire : public LineInfo { /* * $Log: PWire.h,v $ + * Revision 1.15 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.14 2002/08/12 01:34:58 steve * conditional ident string using autoconfig. * diff --git a/design_dump.cc b/design_dump.cc index 379af6591..547da6831 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 */ #ifdef HAVE_CVS_IDENT -#ident "$Id: design_dump.cc,v 1.135 2002/10/23 01:47:17 steve Exp $" +#ident "$Id: design_dump.cc,v 1.136 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -447,6 +447,8 @@ void NetAssign_::dump_lval(ostream&o) const if (bmux_) o << *bmux_; else o << "**oops**"; o << "]"; + } else if (var_) { + o << "basename() << ">"; } else { o << ""; } @@ -733,6 +735,11 @@ void NetScope::dump(ostream&o) const } } + for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_) { + o << " real " << cur->basename() << " // " + << cur->get_line() << endl; + } + /* Dump the events in this scope. */ for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) { o << " event " << cur->name() << "; nprobe=" @@ -896,6 +903,11 @@ void NetEConst::dump(ostream&o) const o << value_; } +void NetECReal::dump(ostream&o) const +{ + o << value_; +} + void NetEScope::dump(ostream&o) const { o << "name() << ">"; @@ -975,6 +987,11 @@ void NetEUnary::dump(ostream&o) const o << ")"; } +void NetEVariable::dump(ostream&o) const +{ + o << var_->basename(); +} + void Design::dump(ostream&o) const { o << "DESIGN TIME PRECISION: 10e" << get_precision() << endl; @@ -1004,6 +1021,10 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.136 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.135 2002/10/23 01:47:17 steve * Fix synth2 handling of aset/aclr signals where * flip-flops are split by begin-end blocks. diff --git a/dup_expr.cc b/dup_expr.cc index c351402a2..35bc2d061 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: dup_expr.cc,v 1.9 2002/11/09 00:25:27 steve Exp $" +#ident "$Id: dup_expr.cc,v 1.10 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -87,8 +87,18 @@ NetEUnary* NetEUnary::dup_expr() const return tmp; } +NetEVariable* NetEVariable::dup_expr() const +{ + NetEVariable*tmp = new NetEVariable(var_); + return tmp; +} + /* * $Log: dup_expr.cc,v $ + * Revision 1.10 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.9 2002/11/09 00:25:27 steve * Add dup_expr for user defined function calls. * diff --git a/elab_expr.cc b/elab_expr.cc index 17a0991b1..e78df286e 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2003 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 @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_expr.cc,v 1.67 2002/12/21 00:55:57 steve Exp $" +#ident "$Id: elab_expr.cc,v 1.68 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -406,8 +406,9 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, bool) const NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope, bool) const { - long val = value_->as_long(); - return new NetEConst(verinum(val)); + NetECReal*tmp = new NetECReal(*value_); + tmp->set_line(*this); + return tmp; } /* @@ -721,6 +722,15 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, return node; } + // If the identifier names a variable of some sort, then this + // is a variable reference. + if (NetVariable*var = des->find_variable(scope, path_)) { + + NetEVariable*node = new NetEVariable(var); + node->set_line(*this); + return node; + } + // Finally, if this is a scope name, then return that. Look // first to see if this is a name of a local scope. Failing // that, search globally for a heirarchical name. @@ -812,10 +822,13 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const case '-': if (NetEConst*ipc = dynamic_cast(ip)) { + /* When taking the - of a number, turn it into a + signed expression and extend it one bit to + accommodate a possible sign bit. */ verinum val = ipc->value(); - verinum zero (verinum::V0, val.len(), val.has_len()); + verinum zero (verinum::V0, val.len()+1, val.has_len()); val = zero - val; - val.has_sign(ipc->has_sign()); + val.has_sign(true); tmp = new NetEConst(val); delete ip; } else { @@ -887,6 +900,10 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const /* * $Log: elab_expr.cc,v $ + * Revision 1.68 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.67 2002/12/21 00:55:57 steve * The $time system task returns the integer time * scaled to the local units. Change the internal diff --git a/elab_lval.cc b/elab_lval.cc index 76ff68132..f61aa334d 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_lval.cc,v 1.24 2003/01/19 00:35:39 steve Exp $" +#ident "$Id: elab_lval.cc,v 1.25 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -138,17 +138,24 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const /* * Handle the ident as an l-value. This includes bit and part selects * of that ident. + * + * XXXX FIXME: The search order looks for signals all the way up the + * scope tree, then looks for memories then variables. It should be + * looking for signals, memories and variables in parallel. */ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const { - /* Get the signal referenced by the identifier, and make sure - it is a register. (Wires are not allows in this context. */ NetNet*reg = des->find_signal(scope, path_); if (reg == 0) { - NetMemory*mem = des->find_memory(scope, path_); - if (mem != 0) + if (NetMemory*mem = des->find_memory(scope, path_)) { return elaborate_mem_lval_(des, scope, mem); + } + + if (NetVariable*var = des->find_variable(scope, path_)) { + NetAssign_*cur = new NetAssign_(var); + return cur; + } cerr << get_line() << ": error: Could not find variable ``" << path_ << "'' in ``" << scope->name() << @@ -157,8 +164,11 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const des->errors += 1; return 0; } + assert(reg); + /* Get the signal referenced by the identifier, and make sure + it is a register. (Wires are not allows in this context. */ if (reg->type() != NetNet::REG) { cerr << get_line() << ": error: " << path_ << " is not a reg/integer/time in " << scope->name() << @@ -337,6 +347,10 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const /* * $Log: elab_lval.cc,v $ + * Revision 1.25 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.24 2003/01/19 00:35:39 steve * Detect null arguments to concatenation operator. * diff --git a/elab_scope.cc b/elab_scope.cc index fe79242d4..0120c45a9 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_scope.cc,v 1.17 2002/10/19 22:59:49 steve Exp $" +#ident "$Id: elab_scope.cc,v 1.18 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -32,6 +32,7 @@ */ # include "Module.h" +# include "PData.h" # include "PEvent.h" # include "PExpr.h" # include "PGate.h" @@ -40,6 +41,7 @@ # include "Statement.h" # include "netlist.h" # include +# include bool Module::elaborate_scope(Design*des, NetScope*scope) const { @@ -217,6 +219,12 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const (*et).second->elaborate_scope(des, scope); } + for (map::const_iterator cur = datum.begin() + ; cur != datum.end() ; cur ++ ) { + + (*cur).second->elaborate_scope(des, scope); + } + return des->errors == 0; } @@ -341,6 +349,14 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const } } +void PData::elaborate_scope(Design*des, NetScope*scope) const +{ + assert(hname_.component_count() == 1); + NetVariable*tmp = new NetVariable(hname_.peek_tail_name()); + tmp->set_line(*this); + scope->add_variable(tmp); +} + /* * The isn't really able to create new scopes, but it does create the * event name in the current scope, so can be done during the @@ -496,6 +512,10 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const /* * $Log: elab_scope.cc,v $ + * Revision 1.18 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.17 2002/10/19 22:59:49 steve * Redo the parameter vector support to allow * parameter names in range expressions. diff --git a/elaborate.cc b/elaborate.cc index 95c33e0d3..7deecd28c 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elaborate.cc,v 1.268 2003/01/14 21:16:18 steve Exp $" +#ident "$Id: elaborate.cc,v 1.269 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -926,23 +926,12 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const delay = elaborate_delay_expr(delay_, des, scope); - /* Elaborate the r-value expression. */ + /* Elaborate the r-value expression, then try to evaluate it. */ + assert(rval()); - - NetExpr*rv; - - if (verinum*val = rval()->eval_const(des, scope)) { - rv = new NetEConst(*val); - delete val; - - } else if (rv = rval()->elaborate_expr(des, scope)) { - - /* OK, go on. */ - - } else { - /* Unable to elaborate expression. Retreat. */ + NetExpr*rv = rval()->elaborate_expr(des, scope); + if (rv == 0) return 0; - } assert(rv); @@ -1028,10 +1017,15 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const return bl; } - { unsigned wid = count_lval_width(lv); - rv->set_width(wid); - rv = pad_to_width(rv, wid); - assert(rv->expr_width() >= wid); + /* Based on the specific type of the l-value, do cleanup + processing on the r-value. */ + if (NetVariable*tmp = lv->var()) { + + } else { + unsigned wid = count_lval_width(lv); + rv->set_width(wid); + rv = pad_to_width(rv, wid); + assert(rv->expr_width() >= wid); } NetAssign*cur = new NetAssign(lv, rv); @@ -2513,6 +2507,10 @@ Design* elaborate(listroots) /* * $Log: elaborate.cc,v $ + * Revision 1.269 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.268 2003/01/14 21:16:18 steve * Move strstream to ostringstream for compatibility. * diff --git a/emit.cc b/emit.cc index a8113e208..cb4e47729 100644 --- a/emit.cc +++ b/emit.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: emit.cc,v 1.70 2002/11/03 20:36:10 steve Exp $" +#ident "$Id: emit.cc,v 1.71 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -312,6 +312,9 @@ void NetScope::emit_scope(struct target_t*tgt) const for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) tgt->event(cur); + for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_) + tgt->variable(cur); + for (NetScope*cur = sub_ ; cur ; cur = cur->sib_) cur->emit_scope(tgt); @@ -411,6 +414,11 @@ void NetEConst::expr_scan(struct expr_scan_t*tgt) const tgt->expr_const(this); } +void NetECReal::expr_scan(struct expr_scan_t*tgt) const +{ + tgt->expr_creal(this); +} + void NetEMemory::expr_scan(struct expr_scan_t*tgt) const { tgt->expr_memory(this); @@ -462,6 +470,11 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const tgt->expr_unary(this); } +void NetEVariable::expr_scan(struct expr_scan_t*tgt) const +{ + tgt->expr_variable(this); +} + bool emit(const Design*des, const char*type) { for (unsigned idx = 0 ; target_table[idx] ; idx += 1) { @@ -479,6 +492,10 @@ bool emit(const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.71 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.70 2002/11/03 20:36:10 steve * Error message for mising code generator type. * diff --git a/expr_synth.cc b/expr_synth.cc index 5dd25169e..bcf9c5939 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: expr_synth.cc,v 1.37 2002/11/17 23:37:55 steve Exp $" +#ident "$Id: expr_synth.cc,v 1.38 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -452,6 +452,14 @@ NetNet* NetEConst::synthesize(Design*des) return osig; } +NetNet* NetECReal::synthesize(Design*des) +{ + cerr << get_line() << ": error: Real constants are " + << "not synthesizeable." << endl; + des->errors += 1; + return 0; +} + /* * The bitwise unary logic operator (there is only one) is turned * into discrete gates just as easily as the binary ones above. @@ -635,6 +643,10 @@ NetNet* NetESignal::synthesize(Design*des) /* * $Log: expr_synth.cc,v $ + * Revision 1.38 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.37 2002/11/17 23:37:55 steve * Magnitude compare to 0. * diff --git a/ivl_target.h b/ivl_target.h index 0545a774e..2a5899cd8 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -1,7 +1,7 @@ #ifndef __ivl_target_H #define __ivl_target_H /* - * Copyright (c) 2000 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2003 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 @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: ivl_target.h,v 1.109 2002/12/21 00:55:58 steve Exp $" +#ident "$Id: ivl_target.h,v 1.110 2003/01/26 21:15:58 steve Exp $" #endif #ifdef __cplusplus @@ -137,6 +137,7 @@ typedef struct ivl_scope_s *ivl_scope_t; typedef struct ivl_signal_s *ivl_signal_t; typedef struct ivl_memory_s *ivl_memory_t; typedef struct ivl_statement_s*ivl_statement_t; +typedef struct ivl_variable_s *ivl_variable_t; /* * These are types that are defined as enumerations. These have @@ -171,7 +172,9 @@ typedef enum ivl_expr_type_e { IVL_EX_TERNARY, IVL_EX_UFUNC, IVL_EX_ULONG, - IVL_EX_UNARY + IVL_EX_UNARY, + IVL_EX_VARIABLE, + IVL_EX_REALNUM } ivl_expr_type_t; /* This is the type code for an ivl_net_logic_t object. */ @@ -292,6 +295,14 @@ typedef enum ivl_statement_type_e { IVL_ST_WHILE } ivl_statement_type_t; +/* This is the type of a variable, and also used as the type for an + expression. */ +typedef enum ivl_variable_type_e { + IVL_VT_VOID = 0, /* Not used */ + IVL_VT_REAL, + IVL_VT_VECTOR +} ivl_variable_type_t; + /* This is the type of the function to apply to a process. */ typedef int (*ivl_process_f)(ivl_process_t net, void*cd); @@ -416,6 +427,10 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx); * type, which can affect how some of the other expression methods * operate on the node * + * ivl_expr_value + * Get the data type of the expression node. This uses the variable + * type enum to express the type of the expression node. + * * ivl_expr_width * This method returns the bit width of the expression at this * node. It can be applied to any expression node, and returns the @@ -430,14 +445,17 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx); */ extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net); +extern ivl_variable_type_t ivl_expr_value(ivl_expr_t net); /* IVL_EX_NUMBER */ extern const char* ivl_expr_bits(ivl_expr_t net); /* IVL_EX_UFUNC */ extern ivl_scope_t ivl_expr_def(ivl_expr_t net); + /* IVL_EX_REALNUM */ +extern double ivl_expr_dvalue(ivl_expr_t net); /* IVL_EX_SIGNAL */ extern unsigned ivl_expr_lsi(ivl_expr_t net); - /* IVL_EX_SIGNAL, IVL_EX_SFUNC */ + /* IVL_EX_SIGNAL, IVL_EX_SFUNC, IVL_EX_VARIABLE */ extern const char* ivl_expr_name(ivl_expr_t net); /* IVL_EX_BINARY IVL_EX_UNARY */ extern char ivl_expr_opcode(ivl_expr_t net); @@ -463,6 +481,8 @@ extern int ivl_expr_signed(ivl_expr_t net); extern const char* ivl_expr_string(ivl_expr_t net); /* IVL_EX_ULONG */ extern unsigned long ivl_expr_uvalue(ivl_expr_t net); + /* IVL_EX_VARIABLE */ +extern ivl_variable_t ivl_expr_variable(ivl_expr_t net); /* any expression */ extern unsigned ivl_expr_width(ivl_expr_t net); @@ -671,6 +691,12 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net); * If the l-value is a variable, this method returns the signal * object that is the target of the assign. * + * ivl_lval_var + * If the l-value is a non-signal variable (i.e. a real) this + * method returns the ivl_variable_t object that represents it. + * If the lval is this sort of variable, then the part_off, idx and + * pin methods do not apply. + * * ivl_lval_part_off * The part select of the signal is based here. This is the * canonical index of bit-0 of the part select. @@ -690,6 +716,7 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net); extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); extern ivl_expr_t ivl_lval_idx(ivl_lval_t net); extern ivl_memory_t ivl_lval_mem(ivl_lval_t net); +extern ivl_variable_t ivl_lval_var(ivl_lval_t net); extern unsigned ivl_lval_part_off(ivl_lval_t net); extern unsigned ivl_lval_pins(ivl_lval_t net); extern ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx); @@ -825,6 +852,10 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net); * ivl_scope_events * Scopes have 0 or more event objects in them. * + * ivl_scope_var + * ivl_scope_vars + * Scopes have 0 or more variable objects in them. + * * ivl_scope_log * ivl_scope_logs * Scopes have 0 or more logic devices in them. A logic device is @@ -887,6 +918,8 @@ extern unsigned ivl_scope_lpms(ivl_scope_t net); extern ivl_lpm_t ivl_scope_lpm(ivl_scope_t, unsigned idx); extern unsigned ivl_scope_mems(ivl_scope_t net); extern ivl_memory_t ivl_scope_mem(ivl_scope_t net, unsigned idx); +extern unsigned ivl_scope_vars(ivl_scope_t net); +extern ivl_variable_t ivl_scope_var(ivl_scope_t net, unsigned idx); extern const char* ivl_scope_name(ivl_scope_t net); extern const char* ivl_scope_basename(ivl_scope_t net); extern ivl_scope_t ivl_scope_parent(ivl_scope_t net); @@ -1071,6 +1104,19 @@ extern ivl_expr_t ivl_stmt_rval(ivl_statement_t net); IVL_ST_WAIT, IVL_ST_WHILE */ extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net); +/* + * These functions manipulate variable objects. + * + * ivl_variable_name + * Return the base name of the variable. + * + * ivl_variable_type + * Return the type of the variable. The ivl_variable_type_t is an + * enumeration that is defined earlier. + */ +extern const char* ivl_variable_name(ivl_variable_t net); +extern ivl_variable_type_t ivl_variable_type(ivl_variable_t net); + #if defined(__MINGW32__) || defined (__CYGWIN32__) # define DLLEXPORT __declspec(dllexport) @@ -1097,6 +1143,10 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.110 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.109 2002/12/21 00:55:58 steve * The $time system task returns the integer time * scaled to the local units. Change the internal diff --git a/lexor.lex b/lexor.lex index ca78b73f5..37968965c 100644 --- a/lexor.lex +++ b/lexor.lex @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: lexor.lex,v 1.74 2002/12/04 02:07:00 steve Exp $" +#ident "$Id: lexor.lex,v 1.75 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -974,7 +974,8 @@ static verinum*make_sized_dec(const char*txt) static verinum*make_unsized_dec(const char*txt) { - return make_dec_with_size(INTEGER_WIDTH, false, txt+1); + verinum*tmp = make_dec_with_size(INTEGER_WIDTH, false, txt+1); + tmp->has_sign(true); } /* diff --git a/net_assign.cc b/net_assign.cc index f46d3997c..40e45672e 100644 --- a/net_assign.cc +++ b/net_assign.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: net_assign.cc,v 1.15 2002/08/12 01:34:59 steve Exp $" +#ident "$Id: net_assign.cc,v 1.16 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -39,7 +39,7 @@ unsigned count_lval_width(const NetAssign_*idx) } NetAssign_::NetAssign_(NetNet*s) -: sig_(s), mem_(0), bmux_(0) +: sig_(s), mem_(0), var_(0), bmux_(0) { loff_ = 0; lwid_ = sig_->pin_count(); @@ -48,13 +48,21 @@ NetAssign_::NetAssign_(NetNet*s) } NetAssign_::NetAssign_(NetMemory*s) -: sig_(0), mem_(s), bmux_(0) +: sig_(0), mem_(s), var_(0), bmux_(0) { loff_ = 0; lwid_ = mem_->width(); more = 0; } +NetAssign_::NetAssign_(NetVariable*s) +: sig_(0), mem_(0), var_(s), bmux_(0) +{ + loff_ = 0; + lwid_ = 0; + more = 0; +} + NetAssign_::~NetAssign_() { if (sig_) { @@ -111,6 +119,11 @@ NetMemory* NetAssign_::mem() const return mem_; } +NetVariable* NetAssign_::var() const +{ + return var_; +} + void NetAssign_::set_part(unsigned lo, unsigned lw) { @@ -241,6 +254,10 @@ NetAssignNB::~NetAssignNB() /* * $Log: net_assign.cc,v $ + * Revision 1.16 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.15 2002/08/12 01:34:59 steve * conditional ident string using autoconfig. * diff --git a/net_design.cc b/net_design.cc index f822a13bd..c08d83eee 100644 --- a/net_design.cc +++ b/net_design.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: net_design.cc,v 1.31 2003/01/14 21:16:18 steve Exp $" +#ident "$Id: net_design.cc,v 1.32 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -526,6 +526,30 @@ NetEvent* Design::find_event(NetScope*scope, const hname_t&p) return 0; } +NetVariable* Design::find_variable(NetScope*scope, const hname_t&p) +{ + hname_t path = p; + assert(scope); + + char*key = path.remove_tail_name(); + if (path.peek_name(0)) + scope = find_scope(scope, path); + + while (scope) { + if (NetVariable*ev = scope->find_variable(key)) { + delete key; + return ev; + } + + if (scope->type() == NetScope::MODULE) + break; + scope = scope->parent(); + } + + delete key; + return 0; +} + void Design::add_node(NetNode*net) { assert(net->design_ == 0); @@ -601,6 +625,10 @@ void Design::delete_process(NetProcTop*top) /* * $Log: net_design.cc,v $ + * Revision 1.32 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.31 2003/01/14 21:16:18 steve * Move strstream to ostringstream for compatibility. * diff --git a/net_expr.cc b/net_expr.cc index b7a697d4f..7e72b3651 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -17,13 +17,18 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: net_expr.cc,v 1.10 2002/11/09 01:40:19 steve Exp $" +#ident "$Id: net_expr.cc,v 1.11 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" # include "netlist.h" # include +NetExpr::TYPE NetExpr::expr_type() const +{ + return ET_VECTOR; +} + /* * Create an add/sub node from the two operands. Make a best guess of * the @@ -90,6 +95,79 @@ NetEBAdd* NetEBAdd::dup_expr() const return result; } +NetExpr::TYPE NetEBAdd::expr_type() const +{ + if (left_->expr_type() == ET_REAL) + return ET_REAL; + + if (right_->expr_type() == ET_REAL) + return ET_REAL; + + return ET_VECTOR; +} + +NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r) +: NetEBinary(op, l, r) +{ + unsigned w = l->expr_width(); + if (r->expr_width() > w) + w = r->expr_width(); + + expr_width(w); + cast_signed(l->has_sign() && r->has_sign()); +} + +NetEBDiv::~NetEBDiv() +{ +} + +NetEBDiv* NetEBDiv::dup_expr() const +{ + NetEBDiv*result = new NetEBDiv(op_, left_->dup_expr(), + right_->dup_expr()); + return result; +} + +NetExpr::TYPE NetEBDiv::expr_type() const +{ + if (left_->expr_type() == ET_REAL) + return ET_REAL; + + if (right_->expr_type() == ET_REAL) + return ET_REAL; + + return ET_VECTOR; +} + +NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r) +: NetEBinary(op, l, r) +{ + expr_width(l->expr_width() + r->expr_width()); + cast_signed(l->has_sign() && r->has_sign()); +} + +NetEBMult::~NetEBMult() +{ +} + +NetEBMult* NetEBMult::dup_expr() const +{ + NetEBMult*result = new NetEBMult(op_, left_->dup_expr(), + right_->dup_expr()); + return result; +} + +NetExpr::TYPE NetEBMult::expr_type() const +{ + if (left_->expr_type() == ET_REAL) + return ET_REAL; + + if (right_->expr_type() == ET_REAL) + return ET_REAL; + + return ET_VECTOR; +} + NetEConcat::NetEConcat(unsigned cnt, NetExpr* r) : parms_(cnt), repeat_(r) { @@ -181,6 +259,32 @@ unsigned NetEConcat::repeat() const return repeat_value_; } +NetECReal::NetECReal(const verireal&val) +: value_(val) +{ +} + +NetECReal::~NetECReal() +{ +} + +const verireal& NetECReal::value() const +{ + return value_; +} + +NetECReal* NetECReal::dup_expr() const +{ + NetECReal*tmp = new NetECReal(value_); + tmp->set_line(*this); + return tmp; +} + +NetExpr::TYPE NetECReal::expr_type() const +{ + return ET_REAL; +} + NetEParam::NetEParam() : des_(0), scope_(0) { @@ -242,6 +346,10 @@ bool NetESelect::set_width(unsigned w) /* * $Log: net_expr.cc,v $ + * Revision 1.11 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.10 2002/11/09 01:40:19 steve * Postpone parameter width check to evaluation. * diff --git a/net_nex_input.cc b/net_nex_input.cc index 48756bd6d..de60c47be 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: net_nex_input.cc,v 1.7 2002/11/16 05:45:41 steve Exp $" +#ident "$Id: net_nex_input.cc,v 1.8 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -82,6 +82,11 @@ NexusSet* NetEConst::nex_input() return new NexusSet; } +NexusSet* NetECReal::nex_input() +{ + return new NexusSet; +} + NexusSet* NetEMemory::nex_input() { NexusSet*result = idx_->nex_input(); @@ -167,6 +172,11 @@ NexusSet* NetEUnary::nex_input() return expr_->nex_input(); } +NexusSet* NetEVariable::nex_input() +{ + return new NexusSet; +} + NexusSet* NetAssignBase::nex_input() { NexusSet*result = rval_->nex_input(); @@ -362,6 +372,10 @@ NexusSet* NetWhile::nex_input() /* * $Log: net_nex_input.cc,v $ + * Revision 1.8 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.7 2002/11/16 05:45:41 steve * Handle default: case in net_inputs for NetCase. * diff --git a/net_scope.cc b/net_scope.cc index f7b7ef204..5b3be1ebe 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: net_scope.cc,v 1.22 2003/01/14 21:16:18 steve Exp $" +#ident "$Id: net_scope.cc,v 1.23 2003/01/26 21:15:58 steve Exp $" #endif # include "config.h" @@ -40,6 +40,7 @@ NetScope::NetScope(NetScope*up, const char*n, NetScope::TYPE t) memories_ = 0; signals_ = 0; events_ = 0; + vars_ = 0; lcounter_ = 0; if (up) { @@ -264,6 +265,15 @@ NetEvent* NetScope::find_event(const char*name) return 0; } +NetVariable* NetScope::find_variable(const char*name) +{ + for (NetVariable*cur = vars_; cur ; cur = cur->snext_) + if (strcmp(cur->basename(), name) == 0) + return cur; + + return 0; +} + void NetScope::add_signal(NetNet*net) { if (signals_ == 0) { @@ -377,6 +387,14 @@ NetMemory* NetScope::find_memory(const string&key) return 0; } +void NetScope::add_variable(NetVariable*var) +{ + assert(var->scope_ == 0); + var->scope_ = this; + var->snext_ = vars_; + vars_ = var; +} + /* * This method locates a child scope by name. The name is the simple * name of the child, no heirarchy is searched. @@ -432,6 +450,10 @@ string NetScope::local_hsymbol() /* * $Log: net_scope.cc,v $ + * Revision 1.23 2003/01/26 21:15:58 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.22 2003/01/14 21:16:18 steve * Move strstream to ostringstream for compatibility. * diff --git a/netlist.cc b/netlist.cc index 7901a859f..27fc44104 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.cc,v 1.203 2002/11/09 00:25:27 steve Exp $" +#ident "$Id: netlist.cc,v 1.204 2003/01/26 21:15:59 steve Exp $" #endif # include "config.h" @@ -1827,28 +1827,6 @@ NetEBComp* NetEBComp::dup_expr() const return result; } -NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r) -: NetEBinary(op, l, r) -{ - unsigned w = l->expr_width(); - if (r->expr_width() > w) - w = r->expr_width(); - - expr_width(w); - cast_signed(l->has_sign() && r->has_sign()); -} - -NetEBDiv::~NetEBDiv() -{ -} - -NetEBDiv* NetEBDiv::dup_expr() const -{ - NetEBDiv*result = new NetEBDiv(op_, left_->dup_expr(), - right_->dup_expr()); - return result; -} - NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r) : op_(op), left_(l), right_(r) { @@ -1887,24 +1865,6 @@ NetEBLogic* NetEBLogic::dup_expr() const return result; } -NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r) -: NetEBinary(op, l, r) -{ - expr_width(l->expr_width() + r->expr_width()); - cast_signed(l->has_sign() && r->has_sign()); -} - -NetEBMult::~NetEBMult() -{ -} - -NetEBMult* NetEBMult::dup_expr() const -{ - NetEBMult*result = new NetEBMult(op_, left_->dup_expr(), - right_->dup_expr()); - return result; -} - NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r) : NetEBinary(op, l, r) { @@ -2286,6 +2246,10 @@ const NetProc*NetTaskDef::proc() const /* * $Log: netlist.cc,v $ + * Revision 1.204 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.203 2002/11/09 00:25:27 steve * Add dup_expr for user defined function calls. * diff --git a/netlist.h b/netlist.h index ff7858470..8958a2d6d 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.h,v 1.271 2002/12/07 02:49:24 steve Exp $" +#ident "$Id: netlist.h,v 1.272 2003/01/26 21:15:59 steve Exp $" #endif /* @@ -32,6 +32,7 @@ # include # include # include "verinum.h" +# include "verireal.h" # include "HName.h" # include "LineInfo.h" # include "svector.h" @@ -51,6 +52,7 @@ class NetProc; class NetProcTop; class NetRelease; class NetScope; +class NetVariable; class NetEvProbe; class NetExpr; class NetESignal; @@ -923,6 +925,16 @@ class NetExpr : public LineInfo { virtual void expr_scan(struct expr_scan_t*) const =0; virtual void dump(ostream&) const; + // Expressions have type. The most common type is ET_VECTOR, + // which is a vector (possibly 1 bit) of 4-value bits. The + // ET_VOID is not generally used. + // + // ET_VOID - No value at all. + // ET_VECTOR - Vector of Verilog 4-value bits + // ET_REAL - real/realtime expression + enum TYPE { ET_VOID=0, ET_VECTOR, ET_REAL }; + virtual TYPE expr_type() const; + // How wide am I? unsigned expr_width() const { return width_; } @@ -1006,6 +1018,31 @@ class NetEConst : public NetExpr { verinum value_; }; +/* + * This class represents a constant real value. + */ +class NetECReal : public NetExpr { + + public: + explicit NetECReal(const verireal&val); + ~NetECReal(); + + const verireal&value() const; + + // The type of this expression is ET_REAL + TYPE expr_type() const; + + virtual void expr_scan(struct expr_scan_t*) const; + virtual void dump(ostream&) const; + + virtual NetECReal* dup_expr() const; + virtual NetNet*synthesize(Design*); + virtual NexusSet* nex_input(); + + private: + verireal value_; +}; + /* * This is a special, magical NetNet object. It represents a constant * bit or part select of another NetNet, so is used to return that @@ -1285,6 +1322,7 @@ class NetAssign_ { public: NetAssign_(NetNet*sig); NetAssign_(NetMemory*mem); + NetAssign_(NetVariable*var); ~NetAssign_(); // If this expression exists, then only a single bit is to be @@ -1308,6 +1346,7 @@ class NetAssign_ { NetNet* sig() const; NetMemory*mem() const; + NetVariable*var() const; // This pointer is for keeping simple lists. NetAssign_* more; @@ -1317,6 +1356,7 @@ class NetAssign_ { private: NetNet *sig_; NetMemory*mem_; + NetVariable*var_; NetExpr*bmux_; unsigned loff_; @@ -2044,6 +2084,34 @@ class NetTaskDef { NetTaskDef& operator= (const NetTaskDef&); }; +/* + * Variable object such as real and realtime are represented by + * instances of this class. + */ +class NetVariable : public LineInfo { + + friend class NetScope; + + public: + NetVariable(const char* name); + ~NetVariable(); + + const char* basename() const; + + NetScope* scope(); + const NetScope* scope() const; + + private: + char* name_; + + NetScope*scope_; + NetVariable*snext_; + + private: + NetVariable(const NetVariable&); + NetVariable& operator= (const NetVariable&); +}; + /* * This node represents a function call in an expression. The object * contains a pointer to the function definition, which is used to @@ -2252,6 +2320,8 @@ class NetEBAdd : public NetEBinary { NetEBAdd(char op, NetExpr*l, NetExpr*r); ~NetEBAdd(); + virtual TYPE expr_type() const; + virtual bool set_width(unsigned w); virtual NetEBAdd* dup_expr() const; virtual NetEConst* eval_tree(); @@ -2269,6 +2339,8 @@ class NetEBDiv : public NetEBinary { NetEBDiv(char op, NetExpr*l, NetExpr*r); ~NetEBDiv(); + virtual TYPE expr_type() const; + virtual bool set_width(unsigned w); virtual NetEBDiv* dup_expr() const; virtual NetEConst* eval_tree(); @@ -2370,6 +2442,8 @@ class NetEBMult : public NetEBinary { NetEBMult(char op, NetExpr*l, NetExpr*r); ~NetEBMult(); + virtual TYPE expr_type() const; + virtual bool set_width(unsigned w); virtual NetEBMult* dup_expr() const; virtual NetEConst* eval_tree(); @@ -2443,6 +2517,29 @@ class NetEConcat : public NetExpr { bool repeat_calculated_; }; +/* + * This node represents a reference to a variable. + */ +class NetEVariable : public NetExpr { + + public: + NetEVariable(NetVariable*); + ~NetEVariable(); + + const NetVariable* variable() const; + + TYPE expr_type() const; + + void expr_scan(struct expr_scan_t*) const; + void dump(ostream&) const; + + NetEVariable*dup_expr() const; + NexusSet* nex_input(); + + private: + NetVariable*var_; +}; + /* * This clas is a placeholder for a parameter expression. When * parameters are first created, an instance of this object is used to @@ -2797,6 +2894,10 @@ class NetScope { void rem_event(NetEvent*); NetEvent*find_event(const char*name); + void add_variable(NetVariable*); + void rem_variable(NetVariable*); + NetVariable*find_variable(const char*name); + /* These methods manage signals. The add_ and rem_signal methods are used by the NetNet objects to make themselves @@ -2900,6 +3001,7 @@ class NetScope { maplocalparams_; NetEvent *events_; + NetVariable*vars_; NetNet *signals_; NetMemory*memories_; @@ -2999,6 +3101,9 @@ class Design { // Events NetEvent* find_event(NetScope*scope, const hname_t&path); + // Variables + NetVariable* find_variable(NetScope*scope, const hname_t&path); + // NODES void add_node(NetNode*); void del_node(NetNode*); @@ -3085,6 +3190,10 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.272 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.271 2002/12/07 02:49:24 steve * Named event triggers can take hierarchical names. * diff --git a/pad_to_width.cc b/pad_to_width.cc index 0201a73dd..a57f8e4be 100644 --- a/pad_to_width.cc +++ b/pad_to_width.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pad_to_width.cc,v 1.11 2002/08/12 01:35:00 steve Exp $" +#ident "$Id: pad_to_width.cc,v 1.12 2003/01/26 21:15:59 steve Exp $" #endif # include "config.h" @@ -40,13 +40,17 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid) const. This is a more efficient result. */ if (NetEConst*tmp = dynamic_cast(expr)) { verinum eval = tmp->value(); + bool signed_flag = eval.has_sign(); verinum::V pad = verinum::V0; + if (signed_flag) + pad = eval.get(eval.len()-1); verinum oval (pad, wid, eval.has_len()); for (unsigned idx = 0 ; idx < eval.len() ; idx += 1) oval.set(idx, eval.get(idx)); + oval.has_sign(signed_flag); tmp = new NetEConst(oval); delete expr; return tmp; @@ -95,6 +99,10 @@ NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid) /* * $Log: pad_to_width.cc,v $ + * Revision 1.12 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.11 2002/08/12 01:35:00 steve * conditional ident string using autoconfig. * diff --git a/parse.y b/parse.y index 27c087450..9ff679e4d 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.169 2003/01/17 05:48:02 steve Exp $" +#ident "$Id: parse.y,v 1.170 2003/01/26 21:15:59 steve Exp $" #endif # include "config.h" @@ -301,12 +301,10 @@ block_item_decl { pform_set_reg_time($2); } | K_real list_of_identifiers ';' - { delete $2; - yyerror(@1, "sorry: real variables not supported."); + { pform_make_reals($2, @1.text, @1.first_line); } | K_realtime list_of_identifiers ';' - { delete $2; - yyerror(@1, "sorry: realtime variables not supported."); + { pform_make_reals($2, @1.text, @1.first_line); } | K_parameter parameter_assign_decl ';' | K_localparam localparam_assign_list ';' diff --git a/pform.cc b/pform.cc index b16849af9..856c813b9 100644 --- a/pform.cc +++ b/pform.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform.cc,v 1.106 2003/01/17 05:47:30 steve Exp $" +#ident "$Id: pform.cc,v 1.107 2003/01/26 21:15:59 steve Exp $" #endif # include "config.h" @@ -26,6 +26,7 @@ # include "pform.h" # include "parse_misc.h" # include "parse_api.h" +# include "PData.h" # include "PEvent.h" # include "PUdp.h" # include @@ -557,6 +558,26 @@ void pform_make_events(list*names, const char*fn, unsigned ln) delete names; } +static void pform_make_datum(const char*name, const char*fn, unsigned ln) +{ + PData*datum = new PData(hname_t(name)); + datum->set_file(fn); + datum->set_lineno(ln); + pform_cur_module->datum[name] = datum; +} + +void pform_make_reals(list*names, const char*fn, unsigned ln) +{ + list::iterator cur; + for (cur = names->begin() ; cur != names->end() ; cur++) { + char*txt = *cur; + pform_make_datum(txt, fn, ln); + free(txt); + } + + delete names; +} + /* * pform_makegates is called when a list of gates (with the same type) * are ready to be instantiated. The function runs through the list of @@ -1372,6 +1393,10 @@ int pform_parse(const char*path, FILE*file) /* * $Log: pform.cc,v $ + * Revision 1.107 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.106 2003/01/17 05:47:30 steve * Missed a case of setting line on an PEident. * diff --git a/pform.h b/pform.h index 5caf43ac7..43bfca016 100644 --- a/pform.h +++ b/pform.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform.h,v 1.64 2002/09/01 03:01:48 steve Exp $" +#ident "$Id: pform.h,v 1.65 2003/01/26 21:15:59 steve Exp $" #endif # include "netlist.h" @@ -216,6 +216,11 @@ extern bool pform_expression_is_constant(const PExpr*); extern void pform_make_events(list*names, const char*file, unsigned lineno); +/* + * Make real datum objects. + */ +extern void pform_make_reals(list*names, + const char*file, unsigned lineno); /* * The makegate function creates a new gate (which need not have a @@ -259,6 +264,10 @@ extern void pform_dump(ostream&out, Module*mod); /* * $Log: pform.h,v $ + * Revision 1.65 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.64 2002/09/01 03:01:48 steve * Properly cast signedness of parameters with ranges. * diff --git a/pform_dump.cc b/pform_dump.cc index 27957f1a4..d98b08092 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform_dump.cc,v 1.77 2002/10/19 22:59:49 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.78 2003/01/26 21:15:59 steve Exp $" #endif # include "config.h" @@ -29,6 +29,7 @@ * module in question. */ # include "pform.h" +# include "PData.h" # include "PEvent.h" # include # include @@ -753,6 +754,13 @@ void Module::dump(ostream&out) const << ev->get_line() << endl; } + for (map::const_iterator cur = datum.begin() + ; cur != datum.end() ; cur ++ ) { + PData*tmp = (*cur).second; + out << " real " << tmp->name() << "; // " + << tmp->get_line() << endl; + } + // Iterate through and display all the wires. for (map::const_iterator wire = wires_.begin() ; wire != wires_.end() @@ -848,6 +856,10 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.78 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.77 2002/10/19 22:59:49 steve * Redo the parameter vector support to allow * parameter names in range expressions. @@ -890,235 +902,5 @@ void PUdp::dump(ostream&out) const * Revision 1.68 2001/12/03 04:47:15 steve * Parser and pform use hierarchical names as hname_t * objects instead of encoded strings. - * - * Revision 1.67 2001/07/25 03:10:49 steve - * Create a config.h.in file to hold all the config - * junk, and support gcc 3.0. (Stephan Boettcher) - * - * Revision 1.66 2001/01/13 22:20:08 steve - * Parse parameters within nested scopes. - * - * Revision 1.65 2000/12/11 00:31:43 steve - * Add support for signed reg variables, - * simulate in t-vvm signed comparisons. - * - * Revision 1.64 2000/12/10 22:01:36 steve - * Support decimal constants in behavioral delays. - * - * Revision 1.63 2000/11/11 01:52:09 steve - * change set for support of nmos, pmos, rnmos, rpmos, notif0, and notif1 - * change set to correct behavior of bufif0 and bufif1 - * (Tim Leight) - * - * Also includes fix for PR#27 - * - * Revision 1.62 2000/10/14 02:23:02 steve - * Check for missing concat subexpressions (PR#11) - * - * Revision 1.61 2000/07/26 05:08:07 steve - * Parse disable statements to pform. - * - * Revision 1.60 2000/05/23 16:03:13 steve - * Better parsing of expressions lists will empty expressoins. - * - * Revision 1.59 2000/05/16 04:05:16 steve - * Module ports are really special PEIdent - * expressions, because a name can be used - * many places in the port list. - * - * Revision 1.58 2000/05/11 23:37:27 steve - * Add support for procedural continuous assignment. - * - * Revision 1.57 2000/05/06 15:41:57 steve - * Carry assignment strength to pform. - * - * Revision 1.56 2000/05/04 03:37:59 steve - * Add infrastructure for system functions, move - * $time to that structure and add $random. - * - * Revision 1.55 2000/04/22 04:20:19 steve - * Add support for force assignment. - * - * Revision 1.54 2000/04/12 20:02:53 steve - * Finally remove the NetNEvent and NetPEvent classes, - * Get synthesis working with the NetEvWait class, - * and get started supporting multiple events in a - * wait in vvm. - * - * Revision 1.53 2000/04/12 04:23:58 steve - * Named events really should be expressed with PEIdent - * objects in the pform, - * - * Handle named events within the mix of net events - * and edges. As a unified lot they get caught together. - * wait statements are broken into more complex statements - * that include a conditional. - * - * Do not generate NetPEvent or NetNEvent objects in - * elaboration. NetEvent, NetEvWait and NetEvProbe - * take over those functions in the netlist. - * - * Revision 1.52 2000/04/01 19:31:57 steve - * Named events as far as the pform. - * - * Revision 1.51 2000/03/12 17:09:41 steve - * Support localparam. - * - * Revision 1.50 2000/03/08 04:36:54 steve - * Redesign the implementation of scopes and parameters. - * I now generate the scopes and notice the parameters - * in a separate pass over the pform. Once the scopes - * are generated, I can process overrides and evalutate - * paremeters before elaboration begins. - * - * Revision 1.49 2000/02/23 02:56:55 steve - * Macintosh compilers do not support ident. - * - * Revision 1.48 2000/02/18 05:15:03 steve - * Catch module instantiation arrays. - * - * Revision 1.47 2000/01/09 20:37:57 steve - * Careful with wires connected to multiple ports. - * - * Revision 1.46 2000/01/09 05:50:49 steve - * Support named parameter override lists. - * - * Revision 1.45 1999/10/10 01:59:55 steve - * Structural case equals device. - * - * Revision 1.44 1999/09/30 02:43:02 steve - * Elaborate ~^ and ~| operators. - * - * Revision 1.43 1999/09/30 00:48:50 steve - * Cope with errors during ternary operator elaboration. - * - * Revision 1.42 1999/09/29 21:15:58 steve - * Handle some mor missing names. - * - * Revision 1.41 1999/09/29 20:23:53 steve - * Handle empty named ports in the dump. - * - * Revision 1.40 1999/09/29 18:36:04 steve - * Full case support - * - * Revision 1.39 1999/09/17 02:06:26 steve - * Handle unconnected module ports. - * - * Revision 1.38 1999/09/08 02:24:39 steve - * Empty conditionals (pmonta@imedia.com) - * - * Revision 1.37 1999/09/04 19:11:46 steve - * Add support for delayed non-blocking assignments. - * - * Revision 1.36 1999/08/25 22:22:41 steve - * elaborate some aspects of functions. - * - * Revision 1.35 1999/08/23 16:48:39 steve - * Parameter overrides support from Peter Monta - * AND and XOR support wide expressions. - * - * Revision 1.34 1999/08/03 04:49:13 steve - * Proper port type names. - * - * Revision 1.33 1999/08/03 04:14:49 steve - * Parse into pform arbitrarily complex module - * port declarations. - * - * Revision 1.32 1999/08/01 16:34:50 steve - * Parse and elaborate rise/fall/decay times - * for gates, and handle the rules for partial - * lists of times. - * - * Revision 1.31 1999/07/31 19:14:47 steve - * Add functions up to elaboration (Ed Carter) - * - * Revision 1.30 1999/07/30 00:43:17 steve - * Handle dumping tasks with no ports. - * - * Revision 1.29 1999/07/24 02:11:20 steve - * Elaborate task input ports. - * - * Revision 1.28 1999/07/17 19:51:00 steve - * netlist support for ternary operator. - * - * Revision 1.27 1999/07/12 00:59:36 steve - * procedural blocking assignment delays. - * - * Revision 1.26 1999/07/03 02:12:52 steve - * Elaborate user defined tasks. - * - * Revision 1.25 1999/06/24 04:24:18 steve - * Handle expression widths for EEE and NEE operators, - * add named blocks and scope handling, - * add registers declared in named blocks. - * - * Revision 1.24 1999/06/19 21:06:16 steve - * Elaborate and supprort to vvm the forever - * and repeat statements. - * - * Revision 1.23 1999/06/17 05:34:42 steve - * Clean up interface of the PWire class, - * Properly match wire ranges. - * - * Revision 1.22 1999/06/15 05:38:39 steve - * Support case expression lists. - * - * Revision 1.21 1999/06/15 03:44:53 steve - * Get rid of the STL vector template. - * - * Revision 1.20 1999/06/13 23:51:16 steve - * l-value part select for procedural assignments. - * - * Revision 1.19 1999/06/10 04:03:53 steve - * Add support for the Ternary operator, - * Add support for repeat concatenation, - * Correct some seg faults cause by elaboration - * errors, - * Parse the casex anc casez statements. - * - * Revision 1.18 1999/06/06 20:45:39 steve - * Add parse and elaboration of non-blocking assignments, - * Replace list with an svector version, - * Add integer support. - * - * Revision 1.17 1999/05/29 02:36:17 steve - * module parameter bind by name. - * - * Revision 1.16 1999/05/10 00:16:58 steve - * Parse and elaborate the concatenate operator - * in structural contexts, Replace vector - * and list with svector, evaluate - * constant expressions with parameters, handle - * memories as lvalues. - * - * Parse task declarations, integer types. - * - * Revision 1.15 1999/05/05 03:04:46 steve - * Fix handling of null delay statements. - * - * Revision 1.14 1999/05/01 02:57:53 steve - * Handle much more complex event expressions. - * - * Revision 1.13 1999/04/29 02:16:26 steve - * Parse OR of event expressions. - * - * Revision 1.12 1999/04/19 01:59:37 steve - * Add memories to the parse and elaboration phases. - * - * Revision 1.11 1999/02/21 17:01:57 steve - * Add support for module parameters. - * - * Revision 1.10 1999/02/15 02:06:15 steve - * Elaborate gate ranges. - * - * Revision 1.9 1999/02/03 04:20:11 steve - * Parse and elaborate the Verilog CASE statement. - * - * Revision 1.8 1999/02/01 00:26:49 steve - * Carry some line info to the netlist, - * Dump line numbers for processes. - * Elaborate prints errors about port vector - * width mismatch - * Emit better handles null statements. */ diff --git a/t-dll-api.cc b/t-dll-api.cc index 91ef05794..b2f2483ef 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll-api.cc,v 1.89 2002/12/21 00:55:58 steve Exp $" +#ident "$Id: t-dll-api.cc,v 1.90 2003/01/26 21:15:59 steve Exp $" #endif # include "config.h" @@ -218,6 +218,12 @@ extern "C" ivl_scope_t ivl_expr_def(ivl_expr_t net) return 0; } +extern "C" double ivl_expr_dvalue(ivl_expr_t net) +{ + assert(net->type_ == IVL_EX_REALNUM); + return net->u_.real_.value; +} + extern "C" unsigned ivl_expr_lsi(ivl_expr_t net) { switch (net->type_) { @@ -242,6 +248,9 @@ extern "C" const char* ivl_expr_name(ivl_expr_t net) case IVL_EX_SIGNAL: return net->u_.signal_.sig->name_; + case IVL_EX_VARIABLE: + return net->u_.variable_.var->name; + default: assert(0); } @@ -414,6 +423,12 @@ extern "C" unsigned long ivl_expr_uvalue(ivl_expr_t net) return net->u_.ulong_.value; } +extern "C" ivl_variable_type_t ivl_expr_value(ivl_expr_t net) +{ + assert(net); + return net->value_; +} + extern "C" unsigned ivl_expr_width(ivl_expr_t net) { assert(net); @@ -426,6 +441,12 @@ extern "C" ivl_memory_t ivl_expr_memory(ivl_expr_t net) return net->u_.memory_.mem_; } +extern "C" ivl_variable_t ivl_expr_variable(ivl_expr_t net) +{ + assert(net->type_ == IVL_EX_VARIABLE); + return net->u_.variable_.var; +} + extern "C" const char* ivl_logic_attr(ivl_net_logic_t net, const char*key) { assert(net); @@ -899,6 +920,14 @@ extern "C" ivl_memory_t ivl_lval_mem(ivl_lval_t net) return 0x0; } +extern "C" ivl_variable_t ivl_lval_var(ivl_lval_t net) +{ + assert(net); + if (net->type_ == IVL_LVAL_VAR) + return net->n.var; + return 0x0; +} + extern "C" unsigned ivl_lval_part_off(ivl_lval_t net) { assert(net); @@ -1079,6 +1108,19 @@ extern "C" ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx) return net->event_[idx]; } +extern "C" unsigned ivl_scope_vars(ivl_scope_t net) +{ + assert(net); + return net->nvar_; +} + +extern "C" ivl_variable_t ivl_scope_var(ivl_scope_t net, unsigned idx) +{ + assert(net); + assert(idx < net->nvar_); + return net->var_[idx]; +} + extern "C" unsigned ivl_scope_logs(ivl_scope_t net) { assert(net); @@ -1484,6 +1526,9 @@ extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net) case IVL_LVAL_MEM: sum += ivl_memory_width(ivl_lval_mem(cur)); break; + case IVL_LVAL_VAR: + sum += 0; + break; default: assert(0); } @@ -1589,8 +1634,24 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net) return 0; } +extern "C" const char* ivl_variable_name(ivl_variable_t net) +{ + assert(net); + return net->name; +} + +extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net) +{ + assert(net); + return net->type; +} + /* * $Log: t-dll-api.cc,v $ + * Revision 1.90 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.89 2002/12/21 00:55:58 steve * The $time system task returns the integer time * scaled to the local units. Change the internal @@ -1634,278 +1695,5 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net) * * Revision 1.79 2002/05/24 04:36:23 steve * Verilog 2001 attriubtes on nets/wires. - * - * Revision 1.78 2002/05/23 03:08:51 steve - * Add language support for Verilog-2001 attribute - * syntax. Hook this support into existing $attribute - * handling, and add number and void value types. - * - * Add to the ivl_target API new functions for access - * of complex attributes attached to gates. - * - * Revision 1.77 2002/03/17 19:30:47 steve - * Add API to support user defined function. - * - * Revision 1.76 2002/03/09 02:10:22 steve - * Add the NetUserFunc netlist node. - * - * Revision 1.75 2002/01/28 00:52:41 steve - * Add support for bit select of parameters. - * This leads to a NetESelect node and the - * vvp code generator to support that. - * - * Revision 1.74 2002/01/03 04:19:01 steve - * Add structural modulus support down to vvp. - * - * Revision 1.73 2001/12/06 03:11:00 steve - * Add ivl_logic_delay function to ivl_target. - * - * Revision 1.72 2001/11/14 03:28:49 steve - * DLL target support for force and release. - * - * Revision 1.71 2001/11/01 04:25:31 steve - * ivl_target support for cassign. - * - * Revision 1.70 2001/10/31 05:24:52 steve - * ivl_target support for assign/deassign. - * - * Revision 1.69 2001/10/19 21:53:24 steve - * Support multiple root modules (Philip Blundell) - * - * Revision 1.68 2001/10/16 02:19:27 steve - * Support IVL_LPM_DIVIDE for structural divide. - * - * Revision 1.67 2001/09/16 22:19:42 steve - * Support attributes to logic gates. - * - * Revision 1.66 2001/09/01 01:57:31 steve - * Make constants available through the design root - * - * Revision 1.65 2001/08/31 22:58:40 steve - * Support DFF CE inputs. - * - * Revision 1.64 2001/08/28 04:07:18 steve - * Add some ivl_target convenience functions. - * - * Revision 1.63 2001/08/25 23:50:03 steve - * Change the NetAssign_ class to refer to the signal - * instead of link into the netlist. This is faster - * and uses less space. Make the NetAssignNB carry - * the delays instead of the NetAssign_ lval objects. - * - * Change the vvp code generator to support multiple - * l-values, i.e. concatenations of part selects. - * - * Revision 1.62 2001/08/10 00:40:45 steve - * tgt-vvp generates code that skips nets as inputs. - * - * Revision 1.61 2001/07/28 01:17:40 steve - * Support getting the signal from IVL_EX_SIGNAL expressions. - * - * Revision 1.60 2001/07/27 04:51:44 steve - * Handle part select expressions as variants of - * NetESignal/IVL_EX_SIGNAL objects, instead of - * creating new and useless temporary signals. - * - * Revision 1.59 2001/07/27 02:41:55 steve - * Fix binding of dangling function ports. do not elide them. - * - * Revision 1.58 2001/07/25 03:10:49 steve - * Create a config.h.in file to hold all the config - * junk, and support gcc 3.0. (Stephan Boettcher) - * - * Revision 1.57 2001/07/22 00:17:49 steve - * Support the NetESubSignal expressions in vvp.tgt. - * - * Revision 1.56 2001/07/19 04:55:06 steve - * Support calculated delays in vvp.tgt. - * - * Revision 1.55 2001/07/07 20:20:10 steve - * Pass parameters to system functions. - * - * Revision 1.54 2001/07/07 03:01:37 steve - * Detect and make available to t-dll the right shift. - * - * Revision 1.53 2001/07/04 22:59:25 steve - * handle left shifter in dll output. - * - * Revision 1.52 2001/06/30 23:03:16 steve - * support fast programming by only writing the bits - * that are listed in the input file. - * - * Revision 1.51 2001/06/16 23:45:05 steve - * Add support for structural multiply in t-dll. - * Add code generators and vvp support for both - * structural and behavioral multiply. - * - * Revision 1.50 2001/06/16 02:41:41 steve - * Generate code to support memory access in continuous - * assignment statements. (Stephan Boettcher) - * - * Revision 1.49 2001/06/15 04:14:19 steve - * Generate vvp code for GT and GE comparisons. - * - * Revision 1.48 2001/06/07 03:09:37 steve - * support subtraction in tgt-vvp. - * - * Revision 1.47 2001/06/07 02:12:43 steve - * Support structural addition. - * - * Revision 1.46 2001/05/20 01:06:16 steve - * stub ivl_expr_parms for sfunctions. - * - * Revision 1.45 2001/05/17 04:37:02 steve - * Behavioral ternary operators for vvp. - * - * Revision 1.44 2001/05/08 23:59:33 steve - * Add ivl and vvp.tgt support for memories in - * expressions and l-values. (Stephan Boettcher) - * - * Revision 1.43 2001/05/06 17:48:20 steve - * Support memory objects. (Stephan Boettcher) - * - * Revision 1.42 2001/04/29 23:17:38 steve - * Carry drive strengths in the ivl_nexus_ptr_t, and - * handle constant devices in targets.' - * - * Revision 1.41 2001/04/26 05:12:02 steve - * Implement simple MUXZ for ?: operators. - * - * Revision 1.40 2001/04/22 23:09:46 steve - * More UDP consolidation from Stephan Boettcher. - * - * Revision 1.39 2001/04/21 00:55:46 steve - * Generate code for disable. - * - * Revision 1.38 2001/04/15 02:58:11 steve - * vvp support for <= with internal delay. - * - * Revision 1.37 2001/04/06 02:28:02 steve - * Generate vvp code for functions with ports. - * - * Revision 1.36 2001/04/05 03:20:57 steve - * Generate vvp code for the repeat statement. - * - * Revision 1.35 2001/04/05 01:12:28 steve - * Get signed compares working correctly in vvp. - * - * Revision 1.34 2001/04/04 04:50:35 steve - * Support forever loops in the tgt-vvp target. - * - * Revision 1.33 2001/04/03 04:50:37 steve - * Support non-blocking assignments. - * - * Revision 1.32 2001/04/02 02:28:12 steve - * Generate code for task calls. - * - * Revision 1.31 2001/04/02 00:28:35 steve - * Support the scope expression node. - * - * Revision 1.30 2001/04/01 06:52:27 steve - * support the NetWhile statement. - * - * Revision 1.29 2001/04/01 01:48:21 steve - * Redesign event information to support arbitrary edge combining. - * - * Revision 1.28 2001/03/31 17:36:38 steve - * Generate vvp code for case statements. - * - * Revision 1.27 2001/03/30 05:49:52 steve - * Generate code for fork/join statements. - * - * Revision 1.26 2001/03/29 03:47:38 steve - * Behavioral trigger statements. - * - * Revision 1.25 2001/03/29 02:52:39 steve - * Add unary ~ operator to tgt-vvp. - * - * Revision 1.24 2001/03/28 06:07:39 steve - * Add the ivl_event_t to ivl_target, and use that to generate - * .event statements in vvp way ahead of the thread that uses it. - * - * Revision 1.23 2001/03/27 06:27:40 steve - * Generate code for simple @ statements. - * - * Revision 1.22 2001/03/20 01:44:13 steve - * Put processes in the proper scope. - * - * Revision 1.21 2001/01/15 00:47:02 steve - * Pass scope type information to the target module. - * - * Revision 1.20 2001/01/15 00:05:39 steve - * Add client data pointer for scope and process scanners. - * - * Revision 1.19 2000/12/05 06:29:33 steve - * Make signal attributes available to ivl_target API. - * - * Revision 1.18 2000/11/12 17:47:29 steve - * flip-flop pins for ivl_target API. - * - * Revision 1.17 2000/11/11 00:03:36 steve - * Add support for the t-dll backend grabing flip-flops. - * - * Revision 1.16 2000/10/28 22:32:34 steve - * API for concatenation expressions. - * - * Revision 1.15 2000/10/25 05:41:24 steve - * Get target signal from nexus_ptr. - * - * Revision 1.14 2000/10/18 20:04:39 steve - * Add ivl_lval_t and support for assignment l-values. - * - * Revision 1.13 2000/10/16 22:44:54 steve - * Stubs so that cygwin port will link ivl. - * - * Revision 1.12 2000/10/15 04:46:23 steve - * Scopes and processes are accessible randomly from - * the design, and signals and logic are accessible - * from scopes. Remove the target calls that are no - * longer needed. - * - * Add the ivl_nexus_ptr_t and the means to get at - * them from nexus objects. - * - * Give names to methods that manipulate the ivl_design_t - * type more consistent names. - * - * Revision 1.11 2000/10/08 04:01:54 steve - * Back pointers in the nexus objects into the devices - * that point to it. - * - * Collect threads into a list in the design. - * - * Revision 1.10 2000/10/06 23:46:50 steve - * ivl_target updates, including more complete - * handling of ivl_nexus_t objects. Much reduced - * dependencies on pointers to netlist objects. - * - * Revision 1.9 2000/10/05 05:03:01 steve - * xor and constant devices. - * - * Revision 1.8 2000/09/30 02:18:15 steve - * ivl_expr_t support for binary operators, - * Create a proper ivl_scope_t object. - * - * Revision 1.7 2000/09/26 00:30:07 steve - * Add EX_NUMBER and ST_TRIGGER to dll-api. - * - * Revision 1.6 2000/09/24 15:46:00 steve - * API access to signal type and port type. - * - * Revision 1.5 2000/09/24 02:21:53 steve - * Add support for signal expressions. - * - * Revision 1.4 2000/09/23 05:15:07 steve - * Add enough tgt-verilog code to support hello world. - * - * Revision 1.3 2000/09/22 03:58:30 steve - * Access to the name of a system task call. - * - * Revision 1.2 2000/09/19 04:15:27 steve - * Introduce the means to get statement types. - * - * Revision 1.1 2000/09/18 01:24:32 steve - * Get the structure for ivl_statement_t worked out. - * */ diff --git a/t-dll-expr.cc b/t-dll-expr.cc index bcc95a176..5f63e1809 100644 --- a/t-dll-expr.cc +++ b/t-dll-expr.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll-expr.cc,v 1.29 2002/10/23 01:47:17 steve Exp $" +#ident "$Id: t-dll-expr.cc,v 1.30 2003/01/26 21:15:59 steve Exp $" #endif # include "config.h" @@ -32,6 +32,26 @@ #endif # include +/* + * This is a little convenience function for converting a NetExpr + * expresion type to the expression type used by ivl_expr_t objects. + */ +static ivl_variable_type_t get_expr_type(const NetExpr*net) +{ + switch (net->expr_type()) { + case NetExpr::ET_VOID: + return IVL_VT_VOID; + + case NetExpr::ET_REAL: + return IVL_VT_REAL; + + case NetExpr::ET_VECTOR: + return IVL_VT_VECTOR; + } + + return IVL_VT_VOID; +} + /* * These methods implement the expression scan that generates the * ivl_expr_t representing the expression. Each method leaves the @@ -50,6 +70,7 @@ void dll_target::sub_off_from_expr_(long off) char*bits; ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); tmpc->type_ = IVL_EX_NUMBER; + tmpc->value_ = IVL_VT_VECTOR; tmpc->width_ = expr_->width_; tmpc->signed_ = expr_->signed_; tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_); @@ -63,6 +84,7 @@ void dll_target::sub_off_from_expr_(long off) the constant to subtract. */ ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); tmps->type_ = IVL_EX_BINARY; + tmps->value_ = IVL_VT_VECTOR; tmps->width_ = tmpc->width_; tmps->signed_ = tmpc->signed_; tmps->u_.binary_.op_ = '-'; @@ -80,6 +102,7 @@ void dll_target::mul_expr_by_const_(long val) char*bits; ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); tmpc->type_ = IVL_EX_NUMBER; + tmpc->value_ = IVL_VT_VECTOR; tmpc->width_ = expr_->width_; tmpc->signed_ = expr_->signed_; tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_); @@ -93,6 +116,7 @@ void dll_target::mul_expr_by_const_(long val) the constant to subtract. */ ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); tmps->type_ = IVL_EX_BINARY; + tmps->value_ = IVL_VT_VECTOR; tmps->width_ = tmpc->width_; tmps->signed_ = tmpc->signed_; tmps->u_.binary_.op_ = '*'; @@ -111,6 +135,7 @@ ivl_expr_t dll_target::expr_from_value_(const verinum&val) unsigned idx; char*bits; expr->type_ = IVL_EX_NUMBER; + expr->value_= IVL_VT_VECTOR; expr->width_= val.len(); expr->signed_ = val.has_sign()? 1 : 0; expr->u_.number_.bits_ = bits = (char*)malloc(expr->width_); @@ -150,6 +175,7 @@ void dll_target::expr_binary(const NetEBinary*net) assert(expr_); expr_->type_ = IVL_EX_BINARY; + expr_->value_= get_expr_type(net); expr_->width_= net->expr_width(); expr_->signed_ = net->has_sign()? 1 : 0; @@ -165,8 +191,9 @@ void dll_target::expr_concat(const NetEConcat*net) ivl_expr_t cur = new struct ivl_expr_s; assert(cur); - cur->type_ = IVL_EX_CONCAT; - cur->width_= net->expr_width(); + cur->type_ = IVL_EX_CONCAT; + cur->value_ = IVL_VT_VECTOR; + cur->width_ = net->expr_width(); cur->u_.concat_.rept = net->repeat(); cur->u_.concat_.parms = net->nparms(); @@ -194,6 +221,7 @@ void dll_target::expr_memory(const NetEMemory*net) assert(cur); cur->type_ = IVL_EX_MEMORY; + cur->value_ = IVL_VT_VECTOR; cur->width_= net->expr_width(); cur->signed_ = net->has_sign()? 1 : 0; cur->u_.memory_.mem_ = find_memory(des_, net->memory()); @@ -210,6 +238,7 @@ void dll_target::expr_const(const NetEConst*net) expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); assert(expr_); + expr_->value_= IVL_VT_VECTOR; if (net->value().is_string()) { expr_->type_ = IVL_EX_STRING; @@ -245,6 +274,17 @@ void dll_target::expr_const(const NetEConst*net) } } +void dll_target::expr_creal(const NetECReal*net) +{ + assert(expr_ == 0); + expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); + expr_->width_ = net->expr_width(); + expr_->signed_ = 1; + expr_->type_ = IVL_EX_REALNUM; + expr_->value_= IVL_VT_REAL; + expr_->u_.real_.value = net->value().as_double(); +} + void dll_target::expr_scope(const NetEScope*net) { assert(expr_ == 0); @@ -253,6 +293,7 @@ void dll_target::expr_scope(const NetEScope*net) assert(expr_); expr_->type_ = IVL_EX_SCOPE; + expr_->value_= IVL_VT_VOID; expr_->u_.scope_.scope = lookup_scope_(net->scope()); } @@ -271,6 +312,7 @@ void dll_target::expr_select(const NetESelect*net) assert(expr_); expr_->type_ = IVL_EX_SELECT; + expr_->value_= IVL_VT_VECTOR; expr_->width_= net->expr_width(); expr_->signed_ = net->has_sign()? 1 : 0; @@ -286,6 +328,7 @@ void dll_target::expr_sfunc(const NetESFunc*net) assert(expr); expr->type_ = IVL_EX_SFUNC; + expr->value_= IVL_VT_VECTOR; expr->width_= net->expr_width(); expr->u_.sfunc_.name_ = strdup(net->name()); @@ -312,6 +355,7 @@ void dll_target::expr_ternary(const NetETernary*net) assert(expr); expr->type_ = IVL_EX_TERNARY; + expr->value_= IVL_VT_VECTOR; expr->width_ = net->expr_width(); expr->signed_ = net->has_sign()? 1 : 0; @@ -340,6 +384,7 @@ void dll_target::expr_signal(const NetESignal*net) assert(expr_); expr_->type_ = IVL_EX_SIGNAL; + expr_->value_= IVL_VT_VECTOR; expr_->width_= net->expr_width(); expr_->signed_ = net->has_sign()? 1 : 0; expr_->u_.signal_.sig = find_signal(des_, net->sig()); @@ -355,6 +400,7 @@ void dll_target::expr_subsignal(const NetEBitSel*net) assert(expr); expr->type_ = IVL_EX_BITSEL; + expr->value_= IVL_VT_VECTOR; expr->width_= net->expr_width(); expr->signed_ = net->has_sign()? 1 : 0; expr->u_.bitsel_.sig = find_signal(des_, net->sig()); @@ -450,6 +496,7 @@ void dll_target::expr_ufunc(const NetEUFunc*net) assert(expr); expr->type_ = IVL_EX_UFUNC; + expr->value_= IVL_VT_VECTOR; expr->width_= net->expr_width(); expr->signed_ = net->has_sign()? 1 : 0; @@ -482,14 +529,31 @@ void dll_target::expr_unary(const NetEUnary*net) expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); expr_->type_ = IVL_EX_UNARY; + expr_->value_= IVL_VT_VECTOR; expr_->width_ = net->expr_width(); expr_->signed_ = net->has_sign()? 1 : 0; expr_->u_.unary_.op_ = net->op(); expr_->u_.unary_.sub_ = sub; } +void dll_target::expr_variable(const NetEVariable*net) +{ + assert(expr_ == 0); + + expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); + expr_->type_ = IVL_EX_VARIABLE; + expr_->value_ = IVL_VT_REAL; + expr_->width_ = 0; + expr_->signed_= net->has_sign()? 1 : 0; + expr_->u_.variable_.var = find_variable(des_, net->variable()); +} + /* * $Log: t-dll-expr.cc,v $ + * Revision 1.30 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.29 2002/10/23 01:47:17 steve * Fix synth2 handling of aset/aclr signals where * flip-flops are split by begin-end blocks. diff --git a/t-dll-proc.cc b/t-dll-proc.cc index 54b17d13c..481855fba 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll-proc.cc,v 1.54 2002/08/19 00:06:12 steve Exp $" +#ident "$Id: t-dll-proc.cc,v 1.55 2003/01/26 21:15:59 steve Exp $" #endif # include "config.h" @@ -163,6 +163,11 @@ void dll_target::proc_assign(const NetAssign*net) expr_ = 0; } + } else if (asn->var()) { + cur->type_ = IVL_LVAL_VAR; + cur->idx = 0; + cur->n.var = find_variable(des_, asn->var()); + } else { assert(asn->mem()); cur->type_ = IVL_LVAL_MEM; @@ -822,6 +827,10 @@ void dll_target::proc_while(const NetWhile*net) /* * $Log: t-dll-proc.cc,v $ + * Revision 1.55 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.54 2002/08/19 00:06:12 steve * Allow release to handle removal of target net. * diff --git a/t-dll.cc b/t-dll.cc index 7102becce..e675c3795 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2003 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 @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll.cc,v 1.102 2003/01/16 21:43:52 steve Exp $" +#ident "$Id: t-dll.cc,v 1.103 2003/01/26 21:15:59 steve Exp $" #endif # include "config.h" @@ -235,6 +235,22 @@ ivl_signal_t dll_target::find_signal(ivl_design_s &des, const NetNet*net) return 0; } +ivl_variable_t dll_target::find_variable(ivl_design_s&des, + const NetVariable*net) +{ + ivl_scope_t scope = find_scope(des, net->scope()); + assert(scope); + + const char*nname = net->basename(); + for (unsigned idx = 0 ; idx < scope->nvar_ ; idx += 1) { + if (strcmp(scope->var_[idx]->name, nname) == 0) + return scope->var_[idx]; + } + + assert(0); + return 0; +} + /* * This function locates an ivl_memory_t object that matches the * NetMemory object. The search works by looking for the parent scope, @@ -415,6 +431,14 @@ static void scope_add_mem(ivl_scope_t scope, ivl_memory_t net) scope->mem_[scope->nmem_-1] = net; } +static void scope_add_var(ivl_scope_t scope, ivl_variable_t net) +{ + scope->nvar_ += 1; + scope->var_ = (ivl_variable_t*) + realloc(scope->var_, scope->nvar_*sizeof(ivl_variable_t)); + scope->var_[scope->nvar_-1] = net; +} + void dll_target::add_root(ivl_design_s &des_, const NetScope *s) { ivl_scope_t root_ = new struct ivl_scope_s; @@ -433,6 +457,8 @@ void dll_target::add_root(ivl_design_s &des_, const NetScope *s) root_->lpm_ = 0; root_->nmem_ = 0; root_->mem_ = 0; + root_->nvar_ = 0; + root_->var_ = 0; root_->type_ = IVL_SCT_MODULE; root_->tname_ = root_->name_; root_->time_units = s->time_unit(); @@ -633,6 +659,18 @@ void dll_target::event(const NetEvent*net) } +void dll_target::variable(const NetVariable*net) +{ + struct ivl_variable_s *obj = new struct ivl_variable_s; + + ivl_scope_t scope = find_scope(des_, net->scope()); + obj->type = IVL_VT_REAL; + obj->name = strings_.add(net->basename()); + obj->scope = scope; + + scope_add_var(scope, obj); +} + void dll_target::logic(const NetLogic*net) { struct ivl_net_logic_s *obj = new struct ivl_net_logic_s; @@ -1779,6 +1817,8 @@ void dll_target::scope(const NetScope*net) scope->lpm_ = 0; scope->nmem_ = 0; scope->mem_ = 0; + scope->nvar_ = 0; + scope->var_ = 0; scope->time_units = net->time_unit(); switch (net->type()) { @@ -1993,6 +2033,10 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj }; /* * $Log: t-dll.cc,v $ + * Revision 1.103 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.102 2003/01/16 21:43:52 steve * Assert some task definition sanity. * diff --git a/t-dll.h b/t-dll.h index 54c4a1431..4e2df03d9 100644 --- a/t-dll.h +++ b/t-dll.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll.h,v 1.96 2002/12/21 00:55:58 steve Exp $" +#ident "$Id: t-dll.h,v 1.97 2003/01/26 21:15:59 steve Exp $" #endif # include "target.h" @@ -68,6 +68,7 @@ struct dll_target : public target_t, public expr_scan_t { bool bufz(const NetBUFZ*); void event(const NetEvent*); + void variable(const NetVariable*); void logic(const NetLogic*); void net_case_cmp(const NetCaseCmp*); void udp(const NetUDP*); @@ -130,6 +131,7 @@ struct dll_target : public target_t, public expr_scan_t { void expr_concat(const NetEConcat*); void expr_memory(const NetEMemory*); void expr_const(const NetEConst*); + void expr_creal(const NetECReal*); void expr_scope(const NetEScope*); void expr_select(const NetESelect*); void expr_sfunc(const NetESFunc*); @@ -138,6 +140,7 @@ struct dll_target : public target_t, public expr_scan_t { void expr_ufunc(const NetEUFunc*); void expr_unary(const NetEUnary*); void expr_signal(const NetESignal*); + void expr_variable(const NetEVariable*); ivl_scope_t lookup_scope_(const NetScope*scope); @@ -150,6 +153,7 @@ struct dll_target : public target_t, public expr_scan_t { static ivl_scope_t find_scope(ivl_design_s &des, const NetScope*cur); static ivl_signal_t find_signal(ivl_design_s &des, const NetNet*net); static ivl_memory_t find_memory(ivl_design_s &des, const NetMemory*net); + static ivl_variable_t find_variable(ivl_design_s &des, const NetVariable*net); void add_root(ivl_design_s &des_, const NetScope *s); void sub_off_from_expr_(long); @@ -177,6 +181,7 @@ struct ivl_event_s { */ struct ivl_expr_s { ivl_expr_type_t type_; + ivl_variable_type_t value_; unsigned width_ :24; unsigned signed_ : 1; @@ -243,11 +248,18 @@ struct ivl_expr_s { unsigned long value; } ulong_; + struct { + double value; + } real_; + struct { char op_; ivl_expr_t sub_; } unary_; + struct { + ivl_variable_t var; + } variable_; } u_; }; @@ -334,7 +346,8 @@ enum ivl_lval_type_t { IVL_LVAL_REG = 0, IVL_LVAL_MUX = 1, IVL_LVAL_MEM = 2, - IVL_LVAL_NET = 3 /* Only force can have NET l-values */ + IVL_LVAL_NET = 3, /* Only force can have NET l-values */ + IVL_LVAL_VAR = 4 }; struct ivl_lval_s { @@ -345,6 +358,7 @@ struct ivl_lval_s { union { ivl_signal_t sig; ivl_memory_t mem; + ivl_variable_t var; } n; }; @@ -495,6 +509,9 @@ struct ivl_scope_s { unsigned nmem_; ivl_memory_t* mem_; + unsigned nvar_; + ivl_variable_t* var_; + /* Scopes that are tasks/functions have a definition. */ ivl_statement_t def; @@ -622,8 +639,21 @@ struct ivl_statement_s { } u_; }; +/* + * This holds the details about a variable object. + */ +struct ivl_variable_s { + ivl_variable_type_t type; + const char* name; + ivl_scope_t scope; +}; + /* * $Log: t-dll.h,v $ + * Revision 1.97 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.96 2002/12/21 00:55:58 steve * The $time system task returns the integer time * scaled to the local units. Change the internal diff --git a/target.cc b/target.cc index 18e8248e6..1d9149639 100644 --- a/target.cc +++ b/target.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2002 Stephen Williams + * Copyright (c) 1998-2003 Stephen Williams * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: target.cc,v 1.63 2002/08/12 01:35:01 steve Exp $" +#ident "$Id: target.cc,v 1.64 2003/01/26 21:15:59 steve Exp $" #endif # include "config.h" @@ -47,6 +47,12 @@ void target_t::memory(const NetMemory*) "Unhandled memory." << endl; } +void target_t::variable(const NetVariable*that) +{ + cerr << that->get_line() << ": error: target (" << typeid(*this).name() + << "): Unhandled variable <" << that->basename() << ">." << endl; +} + void target_t::func_def(const NetScope*) { cerr << "target (" << typeid(*this).name() << "): " @@ -317,6 +323,12 @@ void expr_scan_t::expr_const(const NetEConst*) "unhandled expr_const." << endl; } +void expr_scan_t::expr_creal(const NetECReal*) +{ + cerr << "expr_scan_t (" << typeid(*this).name() << "): " + "unhandled expr_creal." << endl; +} + void expr_scan_t::expr_concat(const NetEConcat*that) { cerr << that->get_line() << ": expr_scan_t (" << @@ -377,6 +389,12 @@ void expr_scan_t::expr_unary(const NetEUnary*) "unhandled expr_unary." << endl; } +void expr_scan_t::expr_variable(const NetEVariable*) +{ + cerr << "expr_scan_t (" << typeid(*this).name() << "): " + "unhandled expr_variable." << endl; +} + void expr_scan_t::expr_binary(const NetEBinary*ex) { cerr << "expr_scan_t (" << typeid(*this).name() << "): " @@ -385,6 +403,10 @@ void expr_scan_t::expr_binary(const NetEBinary*ex) /* * $Log: target.cc,v $ + * Revision 1.64 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.63 2002/08/12 01:35:01 steve * conditional ident string using autoconfig. * diff --git a/target.h b/target.h index 497ce3ae6..2e92708aa 100644 --- a/target.h +++ b/target.h @@ -1,7 +1,7 @@ #ifndef __target_H #define __target_H /* - * Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2003 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 @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: target.h,v 1.60 2002/08/12 01:35:01 steve Exp $" +#ident "$Id: target.h,v 1.61 2003/01/26 21:15:59 steve Exp $" #endif # include "netlist.h" @@ -68,6 +68,9 @@ struct target_t { /* Output a memory (called for each memory object) */ virtual void memory(const NetMemory*); + /* Output an event object. Called for each named event in the scope. */ + virtual void variable(const NetVariable*); + /* Output a defined task. */ virtual void task_def(const NetScope*); virtual void func_def(const NetScope*); @@ -128,6 +131,7 @@ struct target_t { struct expr_scan_t { virtual ~expr_scan_t(); virtual void expr_const(const NetEConst*); + virtual void expr_creal(const NetECReal*); virtual void expr_concat(const NetEConcat*); virtual void expr_memory(const NetEMemory*); virtual void expr_scope(const NetEScope*); @@ -138,6 +142,7 @@ struct expr_scan_t { virtual void expr_ternary(const NetETernary*); virtual void expr_ufunc(const NetEUFunc*); virtual void expr_unary(const NetEUnary*); + virtual void expr_variable(const NetEVariable*); virtual void expr_binary(const NetEBinary*); }; @@ -162,6 +167,10 @@ extern const struct target *target_table[]; /* * $Log: target.h,v $ + * Revision 1.61 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.60 2002/08/12 01:35:01 steve * conditional ident string using autoconfig. * diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index d53283f18..600b2f0d7 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: stub.c,v 1.71 2002/12/21 00:55:58 steve Exp $" +#ident "$Id: stub.c,v 1.72 2003/01/26 21:15:59 steve Exp $" #endif # include "config.h" @@ -40,6 +40,19 @@ static void show_expression(ivl_expr_t net, unsigned ind) const ivl_expr_type_t code = ivl_expr_type(net); unsigned width = ivl_expr_width(net); const char*sign = ivl_expr_signed(net)? "signed" : "unsigned"; + const char*vt = "?"; + + switch (ivl_expr_value(net)) { + case IVL_VT_VOID: + vt = "void"; + break; + case IVL_VT_REAL: + vt = "real"; + break; + case IVL_VT_VECTOR: + vt = "vector"; + break; + } switch (code) { @@ -50,15 +63,15 @@ static void show_expression(ivl_expr_t net, unsigned ind) break; case IVL_EX_BINARY: - fprintf(out, "%*s<\"%c\" width=%u, %s>\n", ind, "", - ivl_expr_opcode(net), width, sign); + fprintf(out, "%*s<\"%c\" width=%u, %s, type=%s>\n", ind, "", + ivl_expr_opcode(net), width, sign, vt); show_expression(ivl_expr_oper1(net), ind+3); show_expression(ivl_expr_oper2(net), ind+3); break; case IVL_EX_CONCAT: - fprintf(out, "%*s\n", ind, "", - ivl_expr_repeat(net), width, sign); + fprintf(out, "%*s\n", + ind, "", ivl_expr_repeat(net), width, sign, vt); for (idx = 0 ; idx < ivl_expr_parms(net) ; idx += 1) show_expression(ivl_expr_parm(net, idx), ind+3); @@ -116,6 +129,15 @@ static void show_expression(ivl_expr_t net, unsigned ind) show_expression(ivl_expr_oper1(net), ind+4); break; + case IVL_EX_VARIABLE: + fprintf(out, "%*s\n", + ind, "", ivl_expr_name(net), vt); + break; + + case IVL_EX_REALNUM: + fprintf(out, "%*s\n", ind, "", ivl_expr_dvalue(net)); + break; + default: fprintf(out, "%*s\n", ind, "", code); break; @@ -244,6 +266,7 @@ static void show_lpm(ivl_lpm_t net) static void show_assign_lval(ivl_lval_t lval, unsigned ind) { ivl_memory_t mem; + ivl_variable_t var; if ( (mem = ivl_lval_mem(lval)) ) { @@ -254,6 +277,10 @@ static void show_assign_lval(ivl_lval_t lval, unsigned ind) show_expression(ivl_lval_idx(lval), ind+4); fprintf(out, "%*s]\n", ind, ""); + } else if ( (var = ivl_lval_var(lval)) ) { + + fprintf(out, "%*svariable %s\n", ind, "", ivl_variable_name(var)); + } else { unsigned pp; ivl_nexus_t nex = ivl_lval_pin(lval, 0); @@ -450,6 +477,26 @@ static int show_process(ivl_process_t net, void*x) return 0; } +static void show_variable(ivl_variable_t net) +{ + const char*type = "?"; + const char*name = ivl_variable_name(net); + + switch (ivl_variable_type(net)) { + case IVL_VT_VOID: + type = "void"; + break; + case IVL_VT_REAL: + type = "real"; + break; + case IVL_VT_VECTOR: + type = "vector"; + break; + } + + fprintf(out, " variable %s %s;\n", type, name); +} + static void show_event(ivl_event_t net) { unsigned idx; @@ -688,6 +735,9 @@ static int show_scope(ivl_scope_t net, void*x) fprintf(out, " time units = 10e%d\n", ivl_scope_time_units(net)); + for (idx = 0 ; idx < ivl_scope_vars(net) ; idx += 1) + show_variable(ivl_scope_var(net, idx)); + for (idx = 0 ; idx < ivl_scope_events(net) ; idx += 1) show_event(ivl_scope_event(net, idx)); @@ -730,6 +780,10 @@ int target_design(ivl_design_t des) /* * $Log: stub.c,v $ + * Revision 1.72 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.71 2002/12/21 00:55:58 steve * The $time system task returns the integer time * scaled to the local units. Change the internal diff --git a/tgt-vvp/Makefile.in b/tgt-vvp/Makefile.in index 8ea66c2e7..ecb8177fa 100644 --- a/tgt-vvp/Makefile.in +++ b/tgt-vvp/Makefile.in @@ -16,7 +16,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.12 2002/11/05 02:14:41 steve Exp $" +#ident "$Id: Makefile.in,v 1.13 2003/01/26 21:15:59 steve Exp $" # # SHELL = /bin/sh @@ -50,7 +50,7 @@ all: vvp.tgt $(CC) -Wall @ident_support@ -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o mv $*.d dep -O = vvp.o draw_mux.o eval_expr.o vector.o vvp_process.o vvp_scope.o +O = vvp.o draw_mux.o eval_expr.o eval_real.o vector.o vvp_process.o vvp_scope.o ifeq (@WIN32@,yes) TGTLDFLAGS=-L.. -livl diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index c1186722f..11a6381a7 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: eval_expr.c,v 1.88 2002/12/20 01:11:14 steve Exp $" +#ident "$Id: eval_expr.c,v 1.89 2003/01/26 21:15:59 steve Exp $" #endif # include "vvp_priv.h" @@ -189,7 +189,8 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid, } else if (lv.wid < ewid) { unsigned short base = allocate_vector(ewid); - clr_vector(lv); + if (lv.base >= 8) + clr_vector(lv); fprintf(vvp_out, " %%mov %u, %u, %u;\n", base, lv.base, lv.wid); fprintf(vvp_out, " %%mov %u, 0, %u;\n", @@ -201,6 +202,43 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid, return lv; } +/* + * This handles the special case that the operands of the comparison + * are real valued expressions. + */ +static struct vector_info draw_binary_expr_eq_real(ivl_expr_t exp) +{ + struct vector_info res; + int lword, rword; + + res.base = allocate_vector(1); + res.wid = 1; + + lword = draw_eval_real(ivl_expr_oper1(exp)); + rword = draw_eval_real(ivl_expr_oper2(exp)); + + clr_word(lword); + clr_word(rword); + + fprintf(vvp_out, " %%cmp/wr %d, %d;\n", lword, rword); + switch (ivl_expr_opcode(exp)) { + + case 'e': + fprintf(vvp_out, " %%mov %u, 4, 1;\n", res.base); + break; + + case 'n': /* != */ + fprintf(vvp_out, " %%mov %u, 4, 1;\n", res.base); + fprintf(vvp_out, " %%inv %u, 1;\n", res.base); + break; + + default: + assert(0); + } + + return res; +} + static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, unsigned ewid, int stuff_ok_flag) @@ -222,6 +260,14 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, && number_is_immediate(re, 16)) return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag); + if (ivl_expr_value(le) == IVL_VT_REAL) { + assert(ivl_expr_value(re) == IVL_VT_REAL); + return draw_binary_expr_eq_real(exp); + } + + assert(ivl_expr_value(le) == IVL_VT_VECTOR); + assert(ivl_expr_value(re) == IVL_VT_VECTOR); + wid = ivl_expr_width(le); if (ivl_expr_width(re) > wid) wid = ivl_expr_width(re); @@ -234,8 +280,10 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, assert(lv.wid == rv.wid); fprintf(vvp_out, " %%cmp/u %u, %u, %u;\n", lv.base, rv.base, lv.wid); - clr_vector(lv); - clr_vector(rv); + if (lv.base >= 8) + clr_vector(lv); + if (rv.base >= 8) + clr_vector(rv); lv.base = 6; lv.wid = 1; break; @@ -462,6 +510,40 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid) return lv; } +static struct vector_info draw_binary_expr_le_real(ivl_expr_t exp) +{ + struct vector_info res; + + ivl_expr_t le = ivl_expr_oper1(exp); + ivl_expr_t re = ivl_expr_oper2(exp); + + int lword = draw_eval_real(le); + int rword = draw_eval_real(re); + + res.base = allocate_vector(1); + res.wid = 1; + + clr_word(lword); + clr_word(rword); + + switch (ivl_expr_opcode(exp)) { + case '<': + fprintf(vvp_out, " %%cmp/wr %d, %d;\n", lword, rword); + fprintf(vvp_out, " %%mov %u, 5, 1;\n", res.base); + break; + + case '>': + fprintf(vvp_out, " %%cmp/wr %d, %d;\n", rword, lword); + fprintf(vvp_out, " %%mov %u, 5, 1;\n", res.base); + break; + + default: + assert(0); + } + + return res; +} + static struct vector_info draw_binary_expr_le(ivl_expr_t exp, unsigned wid, int stuff_ok_flag) @@ -478,6 +560,14 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp, if (ivl_expr_width(re) > owid) owid = ivl_expr_width(re); + if (ivl_expr_value(le) == IVL_VT_REAL) { + assert(ivl_expr_value(re) == IVL_VT_REAL); + return draw_binary_expr_le_real(exp); + } + + assert(ivl_expr_value(le) == IVL_VT_VECTOR); + assert(ivl_expr_value(re) == IVL_VT_VECTOR); + lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ); rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ); @@ -834,6 +924,12 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid) lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ); rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ); + if (lv.wid != wid) { + fprintf(stderr, "XXXX ivl_expr_opcode(exp) = %c," + " lv.wid=%u, wid=%u\n", ivl_expr_opcode(exp), + lv.wid, wid); + } + assert(lv.wid == wid); assert(rv.wid == wid); @@ -1164,6 +1260,19 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid) return res; } +static struct vector_info draw_realnum_expr(ivl_expr_t exp, unsigned wid) +{ + struct vector_info res; + double val = ivl_expr_dvalue(exp); + + res.base = allocate_vector(wid); + res.wid = wid; + + fprintf(vvp_out, " ; XXXX draw_realnum_expr(%f, %u)\n", val, wid); + + return res; +} + /* * A string in an expression is made up by copying constant bits into * the allocated vector. @@ -1861,6 +1970,18 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid) return res; } +static struct vector_info draw_variable_expr(ivl_expr_t exp, unsigned wid) +{ + struct vector_info res; + ivl_variable_t var = ivl_expr_variable(exp); + fprintf(vvp_out, " ; XXXX Read variable %s\n", + ivl_variable_name(var)); + + res.base = 0; + res.wid = wid; + return res; +} + /* * Sometimes we know ahead of time where we want the expression value * to go. In that case, call this function. It will check to see if @@ -1931,6 +2052,10 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid, res = draw_number_expr(exp, wid); break; + case IVL_EX_REALNUM: + res = draw_realnum_expr(exp, wid); + break; + case IVL_EX_SELECT: res = draw_select_expr(exp, wid); break; @@ -1958,6 +2083,10 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid, case IVL_EX_UNARY: res = draw_unary_expr(exp, wid); break; + + case IVL_EX_VARIABLE: + res = draw_variable_expr(exp, wid); + break; } return res; @@ -1970,79 +2099,15 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag) /* * $Log: eval_expr.c,v $ + * Revision 1.89 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.88 2002/12/20 01:11:14 steve * Evaluate shift index after shift operand because * the chift operand may use the index register itself. * * Revision 1.87 2002/12/19 23:11:29 steve * Keep bit select subexpression width if it is constant. - * - * Revision 1.86 2002/11/22 00:01:50 steve - * Careful of left operands to shift that are constant. - * - * Revision 1.85 2002/11/21 22:42:48 steve - * Allow right values of right shift to shift in. - * - * Revision 1.84 2002/11/07 03:12:17 steve - * Vectorize load from REG variables. - * - * Revision 1.83 2002/11/06 05:41:37 steve - * Concatenation can evaluate sub-expressions in place. - * - * Revision 1.82 2002/10/20 02:55:37 steve - * Properly set or clear expression lookaside for binary expressions. - * - * Revision 1.81 2002/09/27 20:24:42 steve - * Allow expression lookaside map to spam statements. - * - * Revision 1.80 2002/09/27 16:33:34 steve - * Add thread expression lookaside map. - * - * Revision 1.79 2002/09/24 04:20:32 steve - * Allow results in register bits 47 in certain cases. - * - * Revision 1.78 2002/09/18 04:29:55 steve - * Add support for binary NOR operator. - * - * Revision 1.77 2002/09/13 04:09:51 steve - * single bit optimization for != in expressions, - * and expand ++ and != results if needed. - * - * Revision 1.76 2002/09/13 03:12:50 steve - * Optimize ==1 when in context where x vs z doesnt matter. - * - * Revision 1.75 2002/09/12 15:49:43 steve - * Add support for binary nand operator. - * - * Revision 1.74 2002/09/01 01:42:34 steve - * Fix leaking vthread bits in ?: eval. - * - * Revision 1.73 2002/08/28 18:38:07 steve - * Add the %subi instruction, and use it where possible. - * - * Revision 1.72 2002/08/28 17:15:35 steve - * Generate %load/nx for indexed load of nets. - * - * Revision 1.71 2002/08/27 05:39:57 steve - * Fix l-value indexing of memories and vectors so that - * an unknown (x) index causes so cell to be addresses. - * - * Fix tangling of label identifiers in the fork-join - * code generator. - * - * Revision 1.70 2002/08/22 03:38:40 steve - * Fix behavioral eval of x?a:b expressions. - * - * Revision 1.69 2002/08/12 01:35:03 steve - * conditional ident string using autoconfig. - * - * Revision 1.68 2002/08/05 04:18:45 steve - * Store only the base name of memories. - * - * Revision 1.67 2002/08/04 18:28:15 steve - * Do not use hierarchical names of memories to - * generate vvp labels. -tdll target does not - * used hierarchical name string to look up the - * memory objects in the design. */ diff --git a/tgt-vvp/eval_real.c b/tgt-vvp/eval_real.c new file mode 100644 index 000000000..1b48e3ab9 --- /dev/null +++ b/tgt-vvp/eval_real.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2003 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 + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: eval_real.c,v 1.1 2003/01/26 21:16:00 steve Exp $" +#endif + +/* + * This file includes functions for evaluating REAL expressions. + */ +# include "vvp_priv.h" +# include +#ifdef HAVE_MALLOC_H +# include +#endif +# include +# include +# include + +static unsigned long word_alloc_mask = 0x0f; + +int allocate_word() +{ + int res = 4; + + while ((1 << res) & word_alloc_mask) + res += 1; + + word_alloc_mask |= 1 << res; + return res; +} + +void clr_word(int res) +{ + assert(word_alloc_mask & (1 << res)); + word_alloc_mask &= ~ (1 << res); +} + + +static int draw_binary_real(ivl_expr_t exp) +{ + int l, r; + + l = draw_eval_real(ivl_expr_oper1(exp)); + r = draw_eval_real(ivl_expr_oper2(exp)); + + switch (ivl_expr_opcode(exp)) { + + case '+': + fprintf(vvp_out, " %%add/wr %d, %d;\n", l, r); + clr_word(r); + break; + + case '*': + fprintf(vvp_out, " %%mul/wr %d, %d;\n", l, r); + clr_word(r); + break; + + default: + assert(0); + } + + return l; +} + +static int draw_number_real(ivl_expr_t exp) +{ + int idx; + int res = allocate_word(); + const char*bits = ivl_expr_bits(exp); + unsigned wid = ivl_expr_width(exp); + unsigned long mant = 0; + + for (idx = 0 ; idx < wid ; idx += 1) { + if (bits[idx] == '1') + mant |= 1 << idx; + } + + fprintf(vvp_out, " %%loadi/wr %d, %lu, 4096;\n", res, mant); + return res; +} + +/* + * Evaluate a real variable expression by loading the real variable + * into a real thread word. + */ +static int draw_variable_real(ivl_expr_t exp) +{ + int res = allocate_word(); + ivl_variable_t var = ivl_expr_variable(exp); + + fprintf(vvp_out, " %%load/wr %d, W_%s;\n", res, vvp_word_label(var)); + return res; +} + +static int draw_realnum_real(ivl_expr_t exp) +{ + int res = allocate_word(); + double value = ivl_expr_dvalue(exp); + + double fract; + int vexp; + unsigned long mant; + int sign = 0; + + if (value < 0) { + sign = 0x4000;; + value *= -1; + } + + fract = frexp(value, &vexp); + fract *= 0x10000; + fract *= 0x10000; + mant = fract; + vexp -= 32; + + vexp += 0x1000; + assert(vexp >= 0); + assert(vexp < 0x2000); + vexp += sign; + + fprintf(vvp_out, " %%loadi/wr %d, %lu, %d; load=%f\n", + res, mant, vexp, ivl_expr_dvalue(exp)); + return res; +} + +/* + * The real value of a signal is the integer value of a signal + * converted to real. + */ +static int draw_signal_real(ivl_expr_t exp) +{ + int res = allocate_word(); + struct vector_info sv = draw_eval_expr(exp, 0); + + fprintf(vvp_out, " %%ix/get %d, %u, %u;\n", res, sv.base, sv.wid); + clr_vector(sv); + + fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res); + + return res; +} + +int draw_eval_real(ivl_expr_t exp) +{ + int res = 0; + + switch (ivl_expr_type(exp)) { + + case IVL_EX_BINARY: + res = draw_binary_real(exp); + break; + + case IVL_EX_NUMBER: + res = draw_number_real(exp); + break; + + case IVL_EX_REALNUM: + res = draw_realnum_real(exp); + break; + + case IVL_EX_VARIABLE: + res = draw_variable_real(exp); + break; + + case IVL_EX_SIGNAL: + res = draw_signal_real(exp); + break; + + default: + fprintf(vvp_out, " ; XXXX Evaluate real expression (%d)\n", + ivl_expr_type(exp)); + return 0; + } + + return res; +} + + +/* + * $Log: eval_real.c,v $ + * Revision 1.1 2003/01/26 21:16:00 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * + */ + diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index 52f303b07..92c36e0bc 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vvp_priv.h,v 1.22 2002/09/27 16:33:34 steve Exp $" +#ident "$Id: vvp_priv.h,v 1.23 2003/01/26 21:16:00 steve Exp $" #endif # include "ivl_target.h" @@ -48,6 +48,8 @@ extern const char* vvp_signal_label(ivl_signal_t sig); */ extern const char* vvp_memory_label(ivl_memory_t mem); +extern const char* vvp_word_label(ivl_variable_t var); + /* * This function draws a process (initial or always) into the output * file. It normally returns 0, but returns !0 of there is some sort @@ -158,6 +160,19 @@ extern int number_is_unknown(ivl_expr_t ex); extern int number_is_immediate(ivl_expr_t ex, unsigned lim_wid); extern unsigned long get_number_immediate(ivl_expr_t ex); +/* + * draw_eval_real evaluates real value expressions. The return code + * from the function is the index of the word register that contains + * the result. + */ +extern int draw_eval_real(ivl_expr_t ex); + +/* + * These functions manage word register allocation. + */ +extern int allocate_word(void); +extern void clr_word(int idx); + /* * These are used to count labels as I generate code. */ @@ -166,6 +181,10 @@ extern unsigned thread_count; /* * $Log: vvp_priv.h,v $ + * Revision 1.23 2003/01/26 21:16:00 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.22 2002/09/27 16:33:34 steve * Add thread expression lookaside map. * @@ -211,37 +230,5 @@ extern unsigned thread_count; * 2. Id and name mangling * 3. A memory leak in draw_net_in_scope() * (Stephan Boettcher) - * - * Revision 1.10 2001/05/17 04:37:02 steve - * Behavioral ternary operators for vvp. - * - * Revision 1.9 2001/05/06 17:54:33 steve - * Behavioral code to read memories. (Stephan Boettcher) - * - * Revision 1.8 2001/04/06 02:28:03 steve - * Generate vvp code for functions with ports. - * - * Revision 1.7 2001/04/02 02:28:13 steve - * Generate code for task calls. - * - * Revision 1.6 2001/03/31 17:36:39 steve - * Generate vvp code for case statements. - * - * Revision 1.5 2001/03/27 06:27:41 steve - * Generate code for simple @ statements. - * - * Revision 1.4 2001/03/27 03:31:07 steve - * Support error code from target_t::end_design method. - * - * Revision 1.3 2001/03/22 05:06:21 steve - * Geneate code for conditional statements. - * - * Revision 1.2 2001/03/21 01:49:43 steve - * Scan the scopes of a design, and draw behavioral - * blocking assignments of constants to vectors. - * - * Revision 1.1 2001/03/19 01:20:46 steve - * Add the tgt-vvp code generator target. - * */ #endif diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 4d4a7cd8c..4d8a2a942 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vvp_process.c,v 1.76 2002/11/21 22:43:13 steve Exp $" +#ident "$Id: vvp_process.c,v 1.77 2003/01/26 21:16:00 steve Exp $" #endif # include "vvp_priv.h" @@ -164,7 +164,7 @@ static void calculate_into_x1(ivl_expr_t expr) clr_vector(vec); } -static int show_stmt_assign(ivl_statement_t net) +static int show_stmt_assign_vector(ivl_statement_t net) { ivl_lval_t lval; ivl_expr_t rval = ivl_stmt_rval(net); @@ -325,6 +325,56 @@ static int show_stmt_assign(ivl_statement_t net) return 0; } +static int show_stmt_assign_real(ivl_statement_t net) +{ + int res; + ivl_lval_t lval; + ivl_variable_t var; + + res = draw_eval_real(ivl_stmt_rval(net)); + clr_word(res); + + assert(ivl_stmt_lvals(net) == 1); + lval = ivl_stmt_lval(net, 0); + var = ivl_lval_var(lval); + assert(var != 0); + + fprintf(vvp_out, " %%set/wr W_%s, %d;\n", + vvp_word_label(var), res); + + return 0; +} + +static int show_stmt_assign(ivl_statement_t net) +{ + ivl_lval_t lval; + ivl_variable_t var; + + lval = ivl_stmt_lval(net, 0); + + if ( (var = ivl_lval_var(lval)) != 0 ) { + switch (ivl_variable_type(var)) { + case IVL_VT_VOID: + assert(0); + return 1; + + case IVL_VT_VECTOR: + /* Can't happen. */ + assert(0); + return 1; + + case IVL_VT_REAL: + return show_stmt_assign_real(net); + + } + + } else { + return show_stmt_assign_vector(net); + } + + return 0; +} + static int show_stmt_assign_nb(ivl_statement_t net) { ivl_lval_t lval; @@ -834,9 +884,25 @@ static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope) ivl_expr_t exp = ivl_stmt_delay_expr(net); ivl_statement_t stmt = ivl_stmt_sub_stmt(net); - { struct vector_info del = draw_eval_expr(exp, 0); - fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", del.base, del.wid); - clr_vector(del); + switch (ivl_expr_value(exp)) { + + case IVL_VT_VECTOR: { + struct vector_info del = draw_eval_expr(exp, 0); + fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", + del.base, del.wid); + clr_vector(del); + break; + } + + case IVL_VT_REAL: { + int word = draw_eval_real(exp); + fprintf(vvp_out, " %%cvt/ir 0, %d;\n", word); + clr_word(word); + break; + } + + default: + assert(0); } fprintf(vvp_out, " %%delayx 0;\n"); @@ -1131,21 +1197,33 @@ static int show_system_task_call(ivl_statement_t net) return 0; } + /* Figure out how many expressions are going to be evaluated + for this task call. I won't need to evaluate expressions + for items that are VPI objects directly. */ for (idx = 0 ; idx < parm_count ; idx += 1) { ivl_expr_t expr = ivl_stmt_parm(net, idx); switch (ivl_expr_type(expr)) { + + /* These expression types can be handled directly, + with VPI handles of their own. Therefore, skip + them in the process of evaluating expressions. */ case IVL_EX_NONE: case IVL_EX_NUMBER: case IVL_EX_STRING: case IVL_EX_SCOPE: case IVL_EX_SFUNC: + case IVL_EX_VARIABLE: continue; case IVL_EX_SIGNAL: /* If the signal node is narrower then the signal itself, then this is a part select so I'm going - to need to evaluate the expression. */ + to need to evaluate the expression. + + If I don't need to do any evaluating, then skip + it as I'll be passing the handle to the signal + itself. */ if (ivl_expr_width(expr) != ivl_signal_pins(ivl_expr_signal(expr))) { break; @@ -1153,17 +1231,32 @@ static int show_system_task_call(ivl_statement_t net) continue; } + case IVL_EX_MEMORY: if (!ivl_expr_oper1(expr)) { continue; } + + /* Everything else will need to be evaluated and + passed as a constant to the vpi task. */ default: break; } vec = (struct vector_info *) realloc(vec, (vecs+1)*sizeof(struct vector_info)); - vec[vecs] = draw_eval_expr(expr, 0); + + switch (ivl_expr_value(expr)) { + case IVL_VT_VECTOR: + vec[vecs] = draw_eval_expr(expr, 0); + break; + case IVL_VT_REAL: + vec[vecs].base = draw_eval_real(expr); + vec[vecs].wid = 0; + break; + default: + assert(0); + } vecs++; } @@ -1200,6 +1293,12 @@ static int show_system_task_call(ivl_statement_t net) continue; } + case IVL_EX_VARIABLE: { + ivl_variable_t var = ivl_expr_variable(expr); + fprintf(vvp_out, ", W_%s", vvp_word_label(var)); + continue; + } + case IVL_EX_STRING: fprintf(vvp_out, ", \"%s\"", ivl_expr_string(expr)); @@ -1231,16 +1330,31 @@ static int show_system_task_call(ivl_statement_t net) break; } assert(veci < vecs); - fprintf(vvp_out, ", T<%u,%u,%s>", vec[veci].base, - vec[veci].wid, ivl_expr_signed(expr)? "s" : "u"); + + switch (ivl_expr_value(expr)) { + + case IVL_VT_VECTOR: + fprintf(vvp_out, ", T<%u,%u,%s>", vec[veci].base, + vec[veci].wid, ivl_expr_signed(expr)? "s" : "u"); + break; + + case IVL_VT_REAL: + fprintf(vvp_out, ", W<%u,r>", vec[veci].base); + break; + + default: + assert(0); + } veci++; } assert(veci == vecs); if (vecs) { - for (idx = 0; idx < vecs; idx++) - clr_vector(vec[idx]); + for (idx = 0; idx < vecs; idx++) { + if (vec[idx].wid > 0) + clr_vector(vec[idx]); + } free(vec); } @@ -1449,6 +1563,10 @@ int draw_func_definition(ivl_scope_t scope) /* * $Log: vvp_process.c,v $ + * Revision 1.77 2003/01/26 21:16:00 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.76 2002/11/21 22:43:13 steve * %set/x0 instruction to support bounds checking. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index ad6d94c8e..467102b54 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vvp_scope.c,v 1.82 2002/12/21 00:55:58 steve Exp $" +#ident "$Id: vvp_scope.c,v 1.83 2003/01/26 21:16:00 steve Exp $" #endif # include "vvp_priv.h" @@ -139,6 +139,13 @@ const char* vvp_signal_label(ivl_signal_t sig) return buf; } +const char* vvp_word_label(ivl_variable_t sig) +{ + static char buf[32]; + sprintf(buf, "$%p", sig); + return buf; +} + /* * This makes a string suitable for use as a label for memories. */ @@ -1568,6 +1575,16 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) } + /* Scan the scope for word variables. */ + for (idx = 0 ; idx < ivl_scope_vars(net) ; idx += 1) { + ivl_variable_t var = ivl_scope_var(net, idx); + const char*type = "real"; + + fprintf(vvp_out, "W_%s .word %s, \"%s\";\n", + vvp_word_label(var), type, + ivl_variable_name(var)); + } + /* Scan the signals (reg and net) and draw the appropriate statements to make the signal function. */ @@ -1611,6 +1628,10 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) /* * $Log: vvp_scope.c,v $ + * Revision 1.83 2003/01/26 21:16:00 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.82 2002/12/21 00:55:58 steve * The $time system task returns the integer time * scaled to the local units. Change the internal diff --git a/verireal.cc b/verireal.cc index 92692d309..5b58e0b2e 100644 --- a/verireal.cc +++ b/verireal.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: verireal.cc,v 1.8 2002/08/12 01:35:01 steve Exp $" +#ident "$Id: verireal.cc,v 1.9 2003/01/26 21:15:59 steve Exp $" #endif # include "config.h" @@ -25,6 +25,7 @@ # include "verireal.h" # include # include +# include # include verireal::verireal() @@ -123,6 +124,11 @@ long verireal::as_long(int shift) const return val; } +double verireal::as_double() const +{ + return mant_ * pow(10.0, exp10_) * (sign_? -1 : 1); +} + verireal operator* (const verireal&l, const verireal&r) { verireal res; @@ -140,6 +146,10 @@ ostream& operator<< (ostream&out, const verireal&v) /* * $Log: verireal.cc,v $ + * Revision 1.9 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.8 2002/08/12 01:35:01 steve * conditional ident string using autoconfig. * diff --git a/verireal.h b/verireal.h index 524019ce7..3787e9af4 100644 --- a/verireal.h +++ b/verireal.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: verireal.h,v 1.6 2002/08/12 01:35:01 steve Exp $" +#ident "$Id: verireal.h,v 1.7 2003/01/26 21:15:59 steve Exp $" #endif #ifdef HAVE_IOSFWD @@ -53,6 +53,7 @@ class verireal { is 25. */ long as_long(int shift =0) const; + double as_double() const; private: bool sign_; @@ -65,6 +66,10 @@ extern verireal operator* (const verireal&, const verireal&); /* * $Log: verireal.h,v $ + * Revision 1.7 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.6 2002/08/12 01:35:01 steve * conditional ident string using autoconfig. * diff --git a/vpi_user.h b/vpi_user.h index 3645309fb..a5e01c0e3 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vpi_user.h,v 1.16 2003/01/09 04:10:17 steve Exp $" +#ident "$Id: vpi_user.h,v 1.17 2003/01/26 21:15:59 steve Exp $" #endif @@ -161,6 +161,7 @@ typedef struct t_vpi_value { #define vpiNamedEvent 34 #define vpiNamedFork 35 #define vpiNet 36 +#define vpiRealVar 47 #define vpiReg 48 #define vpiSysFuncCall 56 #define vpiSysTaskCall 57 @@ -366,6 +367,10 @@ EXTERN_C_END /* * $Log: vpi_user.h,v $ + * Revision 1.17 2003/01/26 21:15:59 steve + * Rework expression parsing and elaboration to + * accommodate real/realtime values and expressions. + * * Revision 1.16 2003/01/09 04:10:17 steve * Add vpi_put_userdata *