diff --git a/design_dump.cc b/design_dump.cc index 98917456e..6719f7e08 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: design_dump.cc,v 1.83 2000/05/07 04:37:56 steve Exp $" +#ident "$Id: design_dump.cc,v 1.84 2000/05/07 18:20:07 steve Exp $" #endif /* @@ -850,7 +850,12 @@ void NetEScope::dump(ostream&o) const void NetESFunc::dump(ostream&o) const { - o << name_ << "()"; + o << name_ << "("; + if (nparms() > 0) + o << *parm(0); + for (unsigned idx = 1 ; idx < nparms() ; idx += 1) + o << ", " << *parm(idx); + o << ")"; } void NetESignal::dump(ostream&o) const @@ -955,6 +960,10 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.84 2000/05/07 18:20:07 steve + * Import MCD support from Stephen Tell, and add + * system function parameter support to the IVL core. + * * Revision 1.83 2000/05/07 04:37:56 steve * Carry strength values from Verilog source to the * pform and netlist for gates. diff --git a/dup_expr.cc b/dup_expr.cc index 3d5191d75..49dc20c82 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 */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: dup_expr.cc,v 1.3 2000/05/04 03:37:58 steve Exp $" +#ident "$Id: dup_expr.cc,v 1.4 2000/05/07 18:20:07 steve Exp $" #endif # include "netlist.h" @@ -31,11 +31,19 @@ NetEScope* NetEScope::dup_expr() const NetESFunc* NetESFunc::dup_expr() const { - return new NetESFunc(name_, expr_width()); + NetESFunc*tmp = new NetESFunc(name_, expr_width(), nparms()); + for (unsigned idx = 0 ; idx < nparms() ; idx += 1) + tmp->parm(idx, tmp->parm(idx)->dup_expr()); + + return tmp; } /* * $Log: dup_expr.cc,v $ + * Revision 1.4 2000/05/07 18:20:07 steve + * Import MCD support from Stephen Tell, and add + * system function parameter support to the IVL core. + * * Revision 1.3 2000/05/04 03:37:58 steve * Add infrastructure for system functions, move * $time to that structure and add $random. diff --git a/elab_expr.cc b/elab_expr.cc index 98ad43576..5b653cb27 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elab_expr.cc,v 1.24 2000/05/04 03:37:58 steve Exp $" +#ident "$Id: elab_expr.cc,v 1.25 2000/05/07 18:20:07 steve Exp $" #endif @@ -142,25 +142,21 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des, return tmp; } -NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*) const +NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const { - if (parms_.count() > 0) { - cerr << get_line() << ": sorry: system function " - "parmaeters not supported." << endl; - des->errors += 1; - return 0; - } + unsigned wid = 32; if (name_ == "$time") - return new NetESFunc(name_, 64); + wid = 64; - if (name_ == "$random") - return new NetESFunc(name_, 32); + NetESFunc*fun = new NetESFunc(name_, wid, parms_.count()); + for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) { + PExpr*expr = parms_[idx]; + NetExpr*tmp = expr->elaborate_expr(des, scope); + fun->parm(idx, tmp); + } - cerr << get_line() << ": sorry: system function " << name_ - << " not supported." << endl; - des->errors += 1; - return 0; + return fun; } NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope) const @@ -467,6 +463,10 @@ NetEUnary* PEUnary::elaborate_expr(Design*des, NetScope*scope) const /* * $Log: elab_expr.cc,v $ + * Revision 1.25 2000/05/07 18:20:07 steve + * Import MCD support from Stephen Tell, and add + * system function parameter support to the IVL core. + * * Revision 1.24 2000/05/04 03:37:58 steve * Add infrastructure for system functions, move * $time to that structure and add $random. diff --git a/netlist.cc b/netlist.cc index a60036f9f..7a1696517 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.cc,v 1.123 2000/05/07 04:37:56 steve Exp $" +#ident "$Id: netlist.cc,v 1.124 2000/05/07 18:20:07 steve Exp $" #endif # include @@ -2234,14 +2234,22 @@ const NetScope* NetEScope::scope() const return scope_; } -NetESFunc::NetESFunc(const string&n, unsigned width) +NetESFunc::NetESFunc(const string&n, unsigned width, unsigned np) : name_(n) { expr_width(width); + nparms_ = np; + parms_ = new NetExpr*[np]; + for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) + parms_[idx] = 0; } NetESFunc::~NetESFunc() { + for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) + if (parms_[idx]) delete parms_[idx]; + + delete[]parms_; } const string& NetESFunc::name() const @@ -2249,6 +2257,31 @@ const string& NetESFunc::name() const return name_; } +unsigned NetESFunc::nparms() const +{ + return nparms_; +} + +void NetESFunc::parm(unsigned idx, NetExpr*v) +{ + assert(idx < nparms_); + if (parms_[idx]) + delete parms_[idx]; + parms_[idx] = v; +} + +const NetExpr* NetESFunc::parm(unsigned idx) const +{ + assert(idx < nparms_); + return parms_[idx]; +} + +NetExpr* NetESFunc::parm(unsigned idx) +{ + assert(idx < nparms_); + return parms_[idx]; +} + NetESignal::NetESignal(NetNet*n) : NetExpr(n->pin_count()), net_(n) { @@ -2604,6 +2637,10 @@ bool NetUDP::sequ_glob_(string input, char output) /* * $Log: netlist.cc,v $ + * Revision 1.124 2000/05/07 18:20:07 steve + * Import MCD support from Stephen Tell, and add + * system function parameter support to the IVL core. + * * Revision 1.123 2000/05/07 04:37:56 steve * Carry strength values from Verilog source to the * pform and netlist for gates. diff --git a/netlist.h b/netlist.h index 0f46e6d0a..5e79cbb9c 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.h,v 1.136 2000/05/07 04:37:56 steve Exp $" +#ident "$Id: netlist.h,v 1.137 2000/05/07 18:20:07 steve Exp $" #endif /* @@ -2035,18 +2035,21 @@ class NetEScope : public NetExpr { /* * This node represents a system function call in an expression. The * object contains the name of the system function, which the backend - * uses to to VPI matching. - * - * XXXX NOTE: parameters are not net supported. + * uses to do VPI matching. */ class NetESFunc : public NetExpr { public: - NetESFunc(const string&name, unsigned width); + NetESFunc(const string&name, unsigned width, unsigned nprms); ~NetESFunc(); const string& name() const; + unsigned nparms() const; + void parm(unsigned idx, NetExpr*expr); + NetExpr* parm(unsigned idx); + const NetExpr* parm(unsigned idx) const; + virtual bool set_width(unsigned); virtual void dump(ostream&) const; @@ -2055,6 +2058,8 @@ class NetESFunc : public NetExpr { private: string name_; + unsigned nparms_; + NetExpr**parms_; private: // not implemented NetESFunc(const NetESFunc&); @@ -2510,6 +2515,10 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.137 2000/05/07 18:20:07 steve + * Import MCD support from Stephen Tell, and add + * system function parameter support to the IVL core. + * * Revision 1.136 2000/05/07 04:37:56 steve * Carry strength values from Verilog source to the * pform and netlist for gates. diff --git a/t-vvm.cc b/t-vvm.cc index a029eb3d5..9cffc78f9 100644 --- a/t-vvm.cc +++ b/t-vvm.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-vvm.cc,v 1.144 2000/05/07 04:37:56 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.145 2000/05/07 18:20:07 steve Exp $" #endif # include @@ -94,7 +94,7 @@ class target_vvm : public target_t { void proc_condit_fun(ostream&os, const NetCondit*); virtual bool proc_force(ostream&os, const NetForce*); virtual void proc_forever(ostream&os, const NetForever*); - virtual bool target_vvm::proc_release(ostream&os, const NetRelease*); + virtual bool proc_release(ostream&os, const NetRelease*); virtual void proc_repeat(ostream&os, const NetRepeat*); virtual void proc_stask(ostream&os, const NetSTask*); virtual bool proc_trigger(ostream&os, const NetEvTrig*); @@ -222,14 +222,14 @@ target_vvm::~target_vvm() class vvm_proc_rval : public expr_scan_t { public: - explicit vvm_proc_rval(ostream&os, unsigned i) - : result(""), os_(os), indent_(i) { } + explicit vvm_proc_rval(ostream&os, target_vvm*t) + : result(""), os_(os), tgt_(t) { } string result; private: ostream&os_; - unsigned indent_; + target_vvm*tgt_; private: virtual void expr_const(const NetEConst*); @@ -245,6 +245,34 @@ class vvm_proc_rval : public expr_scan_t { virtual void expr_ufunc(const NetEUFunc*); }; +/* + * The vvm_parm_rval class scans expressions for the purpose of making + * parameters for system tasks/functions. Thus, the generated code is + * geared towards making the handles needed to make the call. + * + * The result of any parm rval scan is a vpiHandle, or a string that + * automatically converts to a vpiHandle on assignment. + */ +class vvm_parm_rval : public expr_scan_t { + + public: + explicit vvm_parm_rval(ostream&o, target_vvm*t) + : result(""), os_(o), tgt_(t) { } + + string result; + + private: + virtual void expr_const(const NetEConst*); + virtual void expr_memory(const NetEMemory*); + virtual void expr_scope(const NetEScope*); + virtual void expr_sfunc(const NetESFunc*); + virtual void expr_signal(const NetESignal*); + + private: + ostream&os_; + target_vvm*tgt_; +}; + /* * Handle the concatenation operator in a procedural r-value * expression. Evaluate the concatenation into a temporary variable @@ -269,7 +297,7 @@ void vvm_proc_rval::expr_concat(const NetEConcat*expr) pp->expr_scan(this); for (unsigned bit = 0 ; bit < pp->expr_width() ; bit += 1) { - os_ << setw(indent_) << "" << tname << "[" << pos << + os_ << " " << tname << "[" << pos << "] = " << result << "[" << bit << "];" << endl; pos+= 1; @@ -359,10 +387,38 @@ void vvm_proc_rval::expr_sfunc(const NetESFunc*fun) const string retval = make_temp(); const unsigned retwid = fun->expr_width(); + /* Make any parameters that might be needed to be passed to + the function. */ + + const string parmtab = make_temp(); + if (fun->nparms() > 0) { + os_ << " vpiHandle " << parmtab + << "["<nparms()<<"];" << endl; + + for (unsigned idx = 0 ; idx < fun->nparms() ; idx += 1) { + vvm_parm_rval scan(os_, tgt_); + fun->parm(idx)->expr_scan(&scan); + + os_ << " " << parmtab <<"["<name() << "\", " - << retval<<"_bits, " << retwid << ");" << endl; + << retwid << ", " << retval<<"_bits"; + + if (fun->nparms() == 0) + os_ << ", 0, 0"; + else + os_ << ", " << fun->nparms() << ", " << parmtab; + + os_ << ");" << endl; os_ << " vvm_bitset_t " << retval << "(" << retval<<"_bits, " << retwid << ");" << endl; @@ -555,87 +611,87 @@ void vvm_proc_rval::expr_binary(const NetEBinary*expr) switch (expr->op()) { case 'a': // logical and (&&) - os_ << setw(indent_) << "" << result << "[0] = vvm_binop_land(" + os_ << " " << result << "[0] = vvm_binop_land(" << lres << "," << rres << ");" << endl; break; case 'E': // === - os_ << setw(indent_) << "" << result << "[0] = vvm_binop_eeq(" + os_ << " " << result << "[0] = vvm_binop_eeq(" << lres << "," << rres << ");" << endl; break; case 'e': // == - os_ << setw(indent_) << "" << result << "[0] = vvm_binop_eq(" + os_ << " " << result << "[0] = vvm_binop_eq(" << lres << "," << rres << ");" << endl; break; case 'G': // >= - os_ << setw(indent_) << "" << result << "[0] = vvm_binop_ge(" + os_ << " " << result << "[0] = vvm_binop_ge(" << lres << "," << rres << ");" << endl; break; case 'l': // left shift(<<) - os_ << setw(indent_) << "" << "vvm_binop_shiftl(" << result + os_ << " " << "vvm_binop_shiftl(" << result << ", " << lres << "," << rres << ");" << endl; break; case 'L': // <= - os_ << setw(indent_) << "" << result << "[0] = vvm_binop_le(" + os_ << " " << result << "[0] = vvm_binop_le(" << lres << "," << rres << ");" << endl; break; case 'N': // !== - os_ << setw(indent_) << "" << result << "[0] = vvm_binop_nee(" + os_ << " " << result << "[0] = vvm_binop_nee(" << lres << "," << rres << ");" << endl; break; case 'n': - os_ << setw(indent_) << "" << result << "[0] = vvm_binop_ne(" + os_ << " " << result << "[0] = vvm_binop_ne(" << lres << "," << rres << ");" << endl; break; case '<': - os_ << setw(indent_) << "" << result << "[0] = vvm_binop_lt(" + os_ << " " << result << "[0] = vvm_binop_lt(" << lres << "," << rres << ");" << endl; break; case '>': - os_ << setw(indent_) << "" << result << "[0] = vvm_binop_gt(" + os_ << " " << result << "[0] = vvm_binop_gt(" << lres << "," << rres << ");" << endl; break; case 'o': // logical or (||) - os_ << setw(indent_) << "" << result << "[0] = vvm_binop_lor(" + os_ << " " << result << "[0] = vvm_binop_lor(" << lres << "," << rres << ");" << endl; break; case 'r': // right shift(>>) - os_ << setw(indent_) << "" << "vvm_binop_shiftr(" << result + os_ << " " << "vvm_binop_shiftr(" << result << ", " << lres << "," << rres << ");" << endl; break; case 'X': - os_ << setw(indent_) << "" << "vvm_binop_xnor(" << result + os_ << " " << "vvm_binop_xnor(" << result << ", " << lres << "," << rres << ");" << endl; break; case '+': - os_ << setw(indent_) << "" << "vvm_binop_plus(" << result + os_ << " " << "vvm_binop_plus(" << result << ", " << lres << "," << rres << ");" << endl; break; case '-': - os_ << setw(indent_) << "" << "vvm_binop_minus(" << result + os_ << " " << "vvm_binop_minus(" << result << ", " << lres << "," << rres << ");" << endl; break; case '&': - os_ << setw(indent_) << "" << "vvm_binop_and(" << result + os_ << " " << "vvm_binop_and(" << result << ", " << lres << ", " << rres << ");" << endl; break; case '|': - os_ << setw(indent_) << "" << "vvm_binop_or(" << result + os_ << " " << "vvm_binop_or(" << result << ", " << lres << ", " << rres << ");" << endl; break; case '^': - os_ << setw(indent_) << "" << "vvm_binop_xor(" << result + os_ << " " << "vvm_binop_xor(" << result << ", " << lres << ", " << rres << ");" << endl; break; case '*': - os_ << setw(indent_) << "" << "vvm_binop_mult(" << result + os_ << " " << "vvm_binop_mult(" << result << "," << lres << "," << rres << ");" << endl; break; case '/': - os_ << setw(indent_) << "" << "vvm_binop_idiv(" << result + os_ << " " << "vvm_binop_idiv(" << result << "," << lres << "," << rres << ");" << endl; break; case '%': - os_ << setw(indent_) << "" << "vvm_binop_imod(" << result + os_ << " " << "vvm_binop_imod(" << result << "," << lres << "," << rres << ");" << endl; break; default: @@ -648,41 +704,13 @@ void vvm_proc_rval::expr_binary(const NetEBinary*expr) } } -static string emit_proc_rval(ostream&os, unsigned indent, const NetExpr*expr) +static string emit_proc_rval(ostream&os, target_vvm*tgt, const NetExpr*expr) { - vvm_proc_rval scan (os, indent); + vvm_proc_rval scan (os, tgt); expr->expr_scan(&scan); return scan.result; } -/* - * The vvm_parm_rval class scans expressions for the purpose of making - * parameters for system tasks/functions. Thus, the generated code is - * geared towards making the handles needed to make the call. - * - * The result of any parm rval scan is a vpiHandle, or a string that - * automatically converts to a vpiHandle on assignment. - */ -class vvm_parm_rval : public expr_scan_t { - - public: - explicit vvm_parm_rval(ostream&o, target_vvm*t) - : result(""), os_(o), tgt_(t) { } - - string result; - - private: - virtual void expr_const(const NetEConst*); - virtual void expr_memory(const NetEMemory*); - virtual void expr_scope(const NetEScope*); - virtual void expr_sfunc(const NetESFunc*); - virtual void expr_signal(const NetESignal*); - - private: - ostream&os_; - target_vvm*tgt_; -}; - void vvm_parm_rval::expr_const(const NetEConst*expr) { if (expr->value().is_string()) { @@ -770,7 +798,7 @@ void vvm_parm_rval::expr_memory(const NetEMemory*mem) /* Otherwise, evaluate the index at run time and use that to select the memory word. */ - string rval = emit_proc_rval(tgt_->defn, 6, mem->index()); + string rval = emit_proc_rval(tgt_->defn, tgt_, mem->index()); result = "vpi_handle_by_index(&" + mangle(mem->name()) + ".base, " + rval + ".as_unsigned())"; } @@ -1934,7 +1962,7 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net) return; } - string rval = emit_proc_rval(defn, 8, net->rval()); + string rval = emit_proc_rval(defn, this, net->rval()); defn << " // " << net->get_line() << ": " << endl; @@ -1942,7 +1970,7 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net) // This is a bit select. Assign the low bit of the rval // to the selected bit of the lval. - string bval = emit_proc_rval(defn, 8, net->bmux()); + string bval = emit_proc_rval(defn, this, net->bmux()); defn << " switch (" << bval << ".as_unsigned()) {" << endl; @@ -1997,7 +2025,7 @@ void target_vvm::proc_assign_mem(ostream&os, const NetAssignMem*amem) << mangle(amem->index()->name()) << ".nbits);" << endl; /* Evaluate the rval that gets written into the memory word. */ - string rval = emit_proc_rval(defn, 8, amem->rval()); + string rval = emit_proc_rval(defn, this, amem->rval()); const NetMemory*mem = amem->memory(); @@ -2018,7 +2046,7 @@ void target_vvm::proc_assign_mem(ostream&os, const NetAssignMem*amem) void target_vvm::proc_assign_nb(ostream&os, const NetAssignNB*net) { - string rval = emit_proc_rval(defn, 8, net->rval()); + string rval = emit_proc_rval(defn, this, net->rval()); const unsigned long delay = net->rise_time(); if (net->bmux()) { @@ -2030,7 +2058,7 @@ void target_vvm::proc_assign_nb(ostream&os, const NetAssignNB*net) better generating a demux device and doing the assign to the device input. Food for thought. */ - string bval = emit_proc_rval(defn, 8, net->bmux()); + string bval = emit_proc_rval(defn, this, net->bmux()); defn << " switch (" << bval << ".as_unsigned()) {" << endl; for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { @@ -2068,7 +2096,7 @@ void target_vvm::proc_assign_mem_nb(ostream&os, const NetAssignMemNB*amem) /* Evaluate the rval that gets written into the memory word. */ - string rval = emit_proc_rval(defn, 8, amem->rval()); + string rval = emit_proc_rval(defn, this, amem->rval()); const NetMemory*mem = amem->memory(); @@ -2198,7 +2226,7 @@ void target_vvm::proc_case(ostream&os, const NetCase*net) } defn << " /* case (" << *net->expr() << ") */" << endl; - string expr = emit_proc_rval(defn, 8, net->expr()); + string expr = emit_proc_rval(defn, this, net->expr()); unsigned exit_step = thread_step_ + 1; thread_step_ += 1; @@ -2219,7 +2247,7 @@ void target_vvm::proc_case(ostream&os, const NetCase*net) thread_step_ += 1; defn << " /* " << *net->expr(idx) << " */" << endl; - string guard = emit_proc_rval(defn, 8, net->expr(idx)); + string guard = emit_proc_rval(defn, this, net->expr(idx)); defn << " if (B_IS1(" << test_func << "(" << guard << "," << expr << "))) {" << endl; @@ -2323,7 +2351,7 @@ void target_vvm::proc_case_fun(ostream&os, const NetCase*net) defn << " do {" << endl; - string expr = emit_proc_rval(defn, 6, net->expr()); + string expr = emit_proc_rval(defn, this, net->expr()); unsigned default_idx = net->nitems(); for (unsigned idx = 0 ; idx < net->nitems() ; idx += 1) { @@ -2335,7 +2363,7 @@ void target_vvm::proc_case_fun(ostream&os, const NetCase*net) continue; } - string guard = emit_proc_rval(defn, 6, net->expr(idx)); + string guard = emit_proc_rval(defn, this, net->expr(idx)); defn << " if (B_IS1(" << test_func << "(" << guard << "," << expr << "))) {" << endl; @@ -2360,7 +2388,7 @@ void target_vvm::proc_condit(ostream&os, const NetCondit*net) return; } - string expr = emit_proc_rval(defn, 8, net->expr()); + string expr = emit_proc_rval(defn, this, net->expr()); unsigned if_step = ++thread_step_; unsigned else_step = ++thread_step_; @@ -2408,7 +2436,7 @@ void target_vvm::proc_condit(ostream&os, const NetCondit*net) void target_vvm::proc_condit_fun(ostream&os, const NetCondit*net) { - string expr = emit_proc_rval(defn, 8, net->expr()); + string expr = emit_proc_rval(defn, this, net->expr()); defn << " // " << net->get_line() << ": conditional (if-else)" << endl; @@ -2489,7 +2517,7 @@ bool target_vvm::proc_release(ostream&os, const NetRelease*dev) void target_vvm::proc_repeat(ostream&os, const NetRepeat*net) { - string expr = emit_proc_rval(defn, 8, net->expr()); + string expr = emit_proc_rval(defn, this, net->expr()); unsigned top_step = ++thread_step_; unsigned out_step = ++thread_step_; @@ -2696,7 +2724,7 @@ void target_vvm::proc_while(ostream&os, const NetWhile*net) defn << "static bool " << thread_class_ << "_step_" << head_step << "_(vvm_thread*thr) {" << endl; - string expr = emit_proc_rval(defn, 8, net->expr()); + string expr = emit_proc_rval(defn, this, net->expr()); defn << "// " << net->expr()->get_line() << ": test while condition." << endl; @@ -2764,6 +2792,10 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.145 2000/05/07 18:20:07 steve + * Import MCD support from Stephen Tell, and add + * system function parameter support to the IVL core. + * * Revision 1.144 2000/05/07 04:37:56 steve * Carry strength values from Verilog source to the * pform and netlist for gates. diff --git a/vpi/sys_display.c b/vpi/sys_display.c index 69f989e38..e64d186b2 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: sys_display.c,v 1.13 2000/04/21 02:00:35 steve Exp $" +#ident "$Id: sys_display.c,v 1.14 2000/05/07 18:20:07 steve Exp $" #endif # include "vpi_user.h" @@ -55,7 +55,7 @@ static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv) * well so that I can look for arguments as I move forward through the * string. */ -static int format_str(char*fmt, int argc, vpiHandle*argv) +static int format_str(unsigned int mcd, char*fmt, int argc, vpiHandle*argv) { s_vpi_value value; char buf[256]; @@ -73,7 +73,7 @@ static int format_str(char*fmt, int argc, vpiHandle*argv) cnt = sizeof buf - 1; strncpy(buf, cp, cnt); buf[cnt] = 0; - vpi_printf("%s", buf); + vpi_mcd_printf(mcd, "%s", buf); cp += cnt; } else if (*cp == '%') { @@ -90,14 +90,14 @@ static int format_str(char*fmt, int argc, vpiHandle*argv) case 'B': value.format = vpiBinStrVal; vpi_get_value(argv[idx++], &value); - vpi_printf("%s", value.value.str); + vpi_mcd_printf(mcd, "%s", value.value.str); cp += 1; break; case 'd': case 'D': value.format = vpiDecStrVal; vpi_get_value(argv[idx++], &value); - vpi_printf("%s", value.value.str); + vpi_mcd_printf(mcd, "%s", value.value.str); cp += 1; break; case 'h': @@ -110,11 +110,11 @@ static int format_str(char*fmt, int argc, vpiHandle*argv) } value.format = vpiHexStrVal; vpi_get_value(argv[idx++], &value); - vpi_printf("%s", value.value.str); + vpi_mcd_printf(mcd, "%s", value.value.str); cp += 1; break; case 'm': - vpi_printf("%s", vpi_get_str(vpiFullName, argv[idx])); + vpi_mcd_printf(mcd, "%s", vpi_get_str(vpiFullName, argv[idx])); idx += 1; cp += 1; break; @@ -122,22 +122,22 @@ static int format_str(char*fmt, int argc, vpiHandle*argv) case 'O': value.format = vpiOctStrVal; vpi_get_value(argv[idx++], &value); - vpi_printf("%s", value.value.str); + vpi_mcd_printf(mcd, "%s", value.value.str); cp += 1; break; case 't': case 'T': value.format = vpiDecStrVal; vpi_get_value(argv[idx++], &value); - vpi_printf("%s", value.value.str); + vpi_mcd_printf(mcd, "%s", value.value.str); cp += 1; break; case '%': - vpi_printf("%%"); + vpi_mcd_printf(mcd, "%%"); cp += 1; break; default: - vpi_printf("%c", *cp); + vpi_mcd_printf(mcd, "%c", *cp); cp += 1; break; } @@ -149,11 +149,11 @@ static int format_str(char*fmt, int argc, vpiHandle*argv) case 0: break; case 'n': - vpi_printf("\n"); + vpi_mcd_printf(mcd, "\n"); cp += 1; break; default: - vpi_printf("%c", *cp); + vpi_mcd_printf(mcd, "%c", *cp); cp += 1; } } @@ -162,7 +162,7 @@ static int format_str(char*fmt, int argc, vpiHandle*argv) return idx; } -static void do_display(struct strobe_cb_info*info) +static void do_display(unsigned int mcd, struct strobe_cb_info*info) { s_vpi_value value; int idx; @@ -173,20 +173,20 @@ static void do_display(struct strobe_cb_info*info) switch (vpi_get(vpiType, item)) { case 0: - vpi_printf(" "); + vpi_mcd_printf(mcd, " "); break; case vpiConstant: if (vpi_get(vpiConstType, item) == vpiStringConst) { value.format = vpiStringVal; vpi_get_value(item, &value); - idx += format_str(value.value.str, + idx += format_str(mcd, value.value.str, info->nitems-idx-1, info->items+idx+1); } else { value.format = vpiBinStrVal; vpi_get_value(item, &value); - vpi_printf("%s", value.value.str); + vpi_mcd_printf(mcd, "%s", value.value.str); } break; @@ -195,17 +195,17 @@ static void do_display(struct strobe_cb_info*info) case vpiMemoryWord: value.format = vpiBinStrVal; vpi_get_value(item, &value); - vpi_printf("%s", value.value.str); + vpi_mcd_printf(mcd, "%s", value.value.str); break; case vpiTimeVar: value.format = vpiTimeVal; vpi_get_value(item, &value); - vpi_printf("%u", value.value.time->low); + vpi_mcd_printf(mcd, "%u", value.value.time->low); break; default: - vpi_printf("?"); + vpi_mcd_printf(mcd, "?"); break; } } @@ -220,7 +220,7 @@ static int sys_display_calltf(char *name) array_from_iterator(&info, argv); - do_display(&info); + do_display(1, &info); free(info.items); @@ -242,7 +242,7 @@ static int strobe_cb(p_cb_data cb) { struct strobe_cb_info*info = (struct strobe_cb_info*)cb->user_data; - do_display(info); + do_display(1, info); vpi_printf("\n"); @@ -294,7 +294,7 @@ static vpiHandle *monitor_callbacks = 0; static int monitor_cb_2(p_cb_data cb) { - do_display(&monitor_info); + do_display(1, &monitor_info); vpi_printf("\n"); monitor_scheduled = 0; return 0; @@ -385,6 +385,126 @@ static int sys_monitor_calltf(char*name) return 0; } +/* + * Implement the $fopen system function. + */ +static int sys_fopen_calltf(char *name) +{ + s_vpi_value val, value; + + vpiHandle call_handle = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, call_handle); + vpiHandle item = vpi_scan(argv); + + if (item == 0) { + vpi_printf("%s: file name parameter missing.\n", name); + return 0; + } + + if (vpi_get(vpiType, item) != vpiConstant) { + vpi_printf("ERROR: %s parameter must be a constant\n", name); + vpi_free_object(argv); + return 0; + } + + if (vpi_get(vpiConstType, item) != vpiStringConst) { + vpi_printf("ERROR: %s parameter must be a constant\n", name); + vpi_free_object(argv); + return 0; + } + + value.format = vpiStringVal; + vpi_get_value(item, &value); + + val.format = vpiIntVal; + val.value.integer = vpi_mcd_open( value.value.str ); + + vpi_put_value(call_handle, &val, 0, vpiNoDelay); + + return 0; +} + +static int sys_fopen_sizetf(char*x) +{ + return 32; +} + +/* Implement $fdisplay and $fwrite. + * Perhaps this could be merged into sys_display_calltf. + */ +static int sys_fdisplay_calltf(char *name) +{ + struct strobe_cb_info info; + unsigned int mcd; + int type; + s_vpi_value value; + vpiHandle sys = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, sys); + vpiHandle item = vpi_scan(argv); + + if (item == 0) { + vpi_printf("%s: mcd parameter missing.\n", name); + return 0; + } + + type = vpi_get(vpiType, item); + if (type != vpiReg && type != vpiReadVal) { + vpi_printf("ERROR: %s mcd parameter must be of integral, got vpiType=%d\n", + name, type); + vpi_free_object(argv); + return 0; + } + + value.format = vpiIntVal; + vpi_get_value(item, &value); + mcd = value.value.integer; + + array_from_iterator(&info, argv); + do_display(mcd, &info); + free(info.items); + + if (strcmp(name,"$fdisplay") == 0) + vpi_mcd_printf(mcd, "\n"); + + return 0; +} + + +/* + * Implement $fclose system function + */ +static int sys_fclose_calltf(char *name) +{ + unsigned int mcd; + int type; + s_vpi_value value; + + vpiHandle sys = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, sys); + vpiHandle item = vpi_scan(argv); + + if (item == 0) { + vpi_printf("%s: mcd parameter missing.\n", name); + return 0; + } + type = vpi_get(vpiType, item); + if (type != vpiReg && type != vpiReadVal) { + vpi_printf("ERROR: %s mcd parameter must be of integral type, got vpiType=%d\n", + name, type); + vpi_free_object(argv); + return 0; + } + + value.format = vpiIntVal; + vpi_get_value(item, &value); + mcd = value.value.integer; + + vpi_printf("in fclose_calltf mcd=%d type=%d\n", mcd, value.format); + vpi_mcd_close(mcd); + return 0; +} + + void sys_display_register() { s_vpi_systf_data tf_data; @@ -420,11 +540,49 @@ void sys_display_register() tf_data.sizetf = 0; tf_data.user_data = "$monitor"; vpi_register_systf(&tf_data); + + tf_data.type = vpiSysFunc; + tf_data.tfname = "$fopen"; + tf_data.calltf = sys_fopen_calltf; + tf_data.compiletf = 0; + tf_data.sizetf = sys_fopen_sizetf; + tf_data.user_data = "$fopen"; + vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.tfname = "$fclose"; + tf_data.calltf = sys_fclose_calltf; + tf_data.compiletf = 0; + tf_data.sizetf = 0; + tf_data.user_data = "$fclose"; + vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.tfname = "$fdisplay"; + tf_data.calltf = sys_fdisplay_calltf; + tf_data.compiletf = 0; + tf_data.sizetf = 0; + tf_data.user_data = "$fdisplay"; + vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.tfname = "$fwrite"; + tf_data.calltf = sys_fdisplay_calltf; + tf_data.compiletf = 0; + tf_data.sizetf = 0; + tf_data.user_data = "$fwrite"; + vpi_register_systf(&tf_data); + + vpi_mcd_init(); } /* * $Log: sys_display.c,v $ + * Revision 1.14 2000/05/07 18:20:07 steve + * Import MCD support from Stephen Tell, and add + * system function parameter support to the IVL core. + * * Revision 1.13 2000/04/21 02:00:35 steve * exit if hex value is missing. * diff --git a/vpi/vpi_user.h b/vpi/vpi_user.h index 8d71306d4..3357809d9 100644 --- a/vpi/vpi_user.h +++ b/vpi/vpi_user.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vpi_user.h,v 1.15 2000/05/04 03:37:59 steve Exp $" +#ident "$Id: vpi_user.h,v 1.16 2000/05/07 18:20:08 steve Exp $" #endif #ifdef __cplusplus @@ -145,6 +145,11 @@ typedef struct t_vpi_value { extern void vpi_register_systf(const struct t_vpi_systf_data*ss); extern void vpi_printf(const char*fmt, ...); +extern unsigned int vpi_mcd_close(unsigned int mcd); +extern char *vpi_mcd_name(unsigned int mcd); +extern unsigned int vpi_mcd_open(char *name); +extern int vpi_mcd_printf(unsigned int mcd, const char*fmt, ...); + /* * support for VPI callback functions. */ @@ -231,6 +236,10 @@ extern void (*vlog_startup_routines[])(); /* * $Log: vpi_user.h,v $ + * Revision 1.16 2000/05/07 18:20:08 steve + * Import MCD support from Stephen Tell, and add + * system function parameter support to the IVL core. + * * Revision 1.15 2000/05/04 03:37:59 steve * Add infrastructure for system functions, move * $time to that structure and add $random. diff --git a/vvm/Makefile.in b/vvm/Makefile.in index b0de7bd26..9f5526acc 100644 --- a/vvm/Makefile.in +++ b/vvm/Makefile.in @@ -18,7 +18,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.29 2000/04/22 04:20:20 steve Exp $" +#ident "$Id: Makefile.in,v 1.30 2000/05/07 18:20:08 steve Exp $" # # SHELL = /bin/sh @@ -65,7 +65,8 @@ vvm_nexus.o vvm_pevent.o vvm_signal.o vvm_thread.o vvm_udp.o vpip.o P = vpi_bit.o vpi_callback.o \ vpi_const.o vpi_iter.o vpi_memory.o vpi_null.o \ -vpi_priv.o vpi_scope.o vpi_signal.o vpi_simulation.o vpi_systask.o vpi_time.o +vpi_priv.o vpi_scope.o vpi_signal.o vpi_simulation.o vpi_systask.o vpi_time.o \ +vpi_mcd.o libvvm.a: $O rm -f $@ diff --git a/vvm/vpi_const.c b/vvm/vpi_const.c index 436f468b5..c07e78cf0 100644 --- a/vvm/vpi_const.c +++ b/vvm/vpi_const.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vpi_const.c,v 1.7 2000/03/22 04:26:41 steve Exp $" +#ident "$Id: vpi_const.c,v 1.8 2000/05/07 18:20:08 steve Exp $" #endif # include "vpi_priv.h" @@ -36,6 +36,7 @@ void vpip_bits_get_value(vpip_bit_t*bits, unsigned nbits, s_vpi_value*vp) char*cp; unsigned val; unsigned idx; + int isx; cp = buff; @@ -53,6 +54,8 @@ void vpip_bits_get_value(vpip_bit_t*bits, unsigned nbits, s_vpi_value*vp) *cp++ = 'x'; } vp->format = vpiBinStrVal; + *cp++ = 0; + vp->value.str = buff; break; case vpiDecStrVal: @@ -64,6 +67,8 @@ void vpip_bits_get_value(vpip_bit_t*bits, unsigned nbits, s_vpi_value*vp) } sprintf(cp, "%u", val); cp += strlen(cp); + *cp++ = 0; + vp->value.str = buff; break; case vpiOctStrVal: @@ -123,6 +128,8 @@ void vpip_bits_get_value(vpip_bit_t*bits, unsigned nbits, s_vpi_value*vp) else *cp++ = "01234567"[v]; } + *cp++ = 0; + vp->value.str = buff; break; case vpiHexStrVal: @@ -184,17 +191,36 @@ void vpip_bits_get_value(vpip_bit_t*bits, unsigned nbits, s_vpi_value*vp) else *cp++ = "0123456789abcdef"[v]; } + *cp++ = 0; + vp->value.str = buff; + break; + + case vpiIntVal: + val = 0; + isx = 0; + for (idx = 0 ; idx < nbits ; idx += 1) { + val *= 2; + if (B_ISXZ(bits[nbits-idx-1])) + isx = 1; + else if (B_IS1(bits[nbits-idx-1])) + val += 1; + } + if(isx) + vp->value.integer = 0; + else + vp->value.integer = val; break; default: *cp++ = '('; *cp++ = '?'; *cp++ = ')'; + *cp++ = 0; + vp->format = vpiStringVal; + vp->value.str = buff; + break; } - - *cp++ = 0; - vp->value.str = buff; } static int string_get(int code, vpiHandle ref) @@ -291,6 +317,10 @@ vpiHandle vpip_make_number_const(struct __vpiNumberConst*ref, /* * $Log: vpi_const.c,v $ + * Revision 1.8 2000/05/07 18:20:08 steve + * Import MCD support from Stephen Tell, and add + * system function parameter support to the IVL core. + * * Revision 1.7 2000/03/22 04:26:41 steve * Replace the vpip_bit_t with a typedef and * define values for all the different bit diff --git a/vvm/vpi_mcd.c b/vvm/vpi_mcd.c new file mode 100644 index 000000000..c7b3d5568 --- /dev/null +++ b/vvm/vpi_mcd.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2000 Stephen G. Tell + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(WINNT) && !defined(macintosh) +#ident "$Id: vpi_mcd.c,v 1.1 2000/05/07 18:20:08 steve Exp $" +#endif + +# include "vpi_priv.h" +# include +# include +# include +# include +# include + +struct mcd_entry { + FILE *fp; + char *filename; +}; + +static struct mcd_entry mcd_table[32]; + +/* Initialize mcd portion of vpi. Must be called before + * any vpi_mcd routines can be used. + */ +void vpi_mcd_init() +{ + mcd_table[0].fp = stdout; + mcd_table[0].filename = ""; + mcd_table[1].fp = stderr; + mcd_table[1].filename = ""; + mcd_table[2].fp = stdout; /* TODO: initialize this to log file */ + mcd_table[2].filename = ""; +} + +/* + * close one or more channels. we silently refuse to close the preopened ones. + */ +unsigned int vpi_mcd_close(unsigned int mcd) +{ + int i; + int rc; + rc = 0; + for(i = 3; i < 31; i++) { + if( ((mcd>>i) & 1) && mcd_table[i].filename) { + if(fclose(mcd_table[i].fp) != 0) + rc |= 1<>i) & 1) + return mcd_table[i].filename; + } + return NULL; +} + +unsigned int vpi_mcd_open(char *name) +{ + int i; + for(i = 0; i < 31; i++) { + if(mcd_table[i].filename == NULL) + goto got_entry; + } + return 0; /* too many open mcd's */ + +got_entry: + mcd_table[i].fp = fopen(name, "w"); + if(mcd_table[i].fp == NULL) + return 0; + mcd_table[i].filename = strdup(name); + return 1<>i) & 1) { + if(mcd_table[i].fp) + len = vfprintf(mcd_table[i].fp, fmt, ap); + else + rc = EOF; + } + } + va_end(ap); + + if(rc) + return rc; + else + return len; +} + diff --git a/vvm/vpi_priv.c b/vvm/vpi_priv.c index 8f51ab785..63524bb4e 100644 --- a/vvm/vpi_priv.c +++ b/vvm/vpi_priv.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vpi_priv.c,v 1.6 2000/05/04 03:37:59 steve Exp $" +#ident "$Id: vpi_priv.c,v 1.7 2000/05/07 18:20:08 steve Exp $" #endif # include "vpi_priv.h" @@ -75,16 +75,15 @@ void vpip_calltask(const char*fname, unsigned nparms, vpiHandle*parms) /* * System functions are kept in the same sort of table as the system * tasks, and we call them in a similar manner. - * - * XXXX Haven't handled the return value yet. */ -void vpip_callfunc(const char*fname, vpip_bit_t*res, unsigned nres) +void vpip_callfunc(const char*fname, unsigned nres, vpip_bit_t*res, + unsigned nparms, vpiHandle*parms) { struct systf_entry*idx; struct __vpiSysTaskCall cur_task; cur_task.base.vpi_type = &vpip_sysfunc_rt; - cur_task.args = 0; - cur_task.nargs = 0; + cur_task.args = parms; + cur_task.nargs = nparms; cur_task.res = res; cur_task.nres = nres; @@ -220,6 +219,10 @@ void vpi_register_systf(const struct t_vpi_systf_data*systf) /* * $Log: vpi_priv.c,v $ + * Revision 1.7 2000/05/07 18:20:08 steve + * Import MCD support from Stephen Tell, and add + * system function parameter support to the IVL core. + * * Revision 1.6 2000/05/04 03:37:59 steve * Add infrastructure for system functions, move * $time to that structure and add $random. diff --git a/vvm/vpi_priv.h b/vvm/vpi_priv.h index b94579ecf..ce0f12069 100644 --- a/vvm/vpi_priv.h +++ b/vvm/vpi_priv.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vpi_priv.h,v 1.17 2000/05/07 04:37:56 steve Exp $" +#ident "$Id: vpi_priv.h,v 1.18 2000/05/07 18:20:08 steve Exp $" #endif /* @@ -305,7 +305,8 @@ extern void vpip_calltask(const char*name, unsigned nparms, vpiHandle*parms); * This calls a system function with a given name. The return value is * taken by the res[] array. */ -extern void vpip_callfunc(const char*name, vpip_bit_t*res, unsigned nres); +extern void vpip_callfunc(const char*name, unsigned nres, vpip_bit_t*res, + unsigned nparms, vpiHandle*parms); extern void vpip_run_value_changes(struct __vpiSignal*sig); @@ -366,6 +367,10 @@ extern int vpip_finished(); /* * $Log: vpi_priv.h,v $ + * Revision 1.18 2000/05/07 18:20:08 steve + * Import MCD support from Stephen Tell, and add + * system function parameter support to the IVL core. + * * Revision 1.17 2000/05/07 04:37:56 steve * Carry strength values from Verilog source to the * pform and netlist for gates. diff --git a/vvm/vpi_systask.c b/vvm/vpi_systask.c index 9a8f4b4de..711d17cda 100644 --- a/vvm/vpi_systask.c +++ b/vvm/vpi_systask.c @@ -17,17 +17,22 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vpi_systask.c,v 1.4 2000/05/04 03:37:59 steve Exp $" +#ident "$Id: vpi_systask.c,v 1.5 2000/05/07 18:20:08 steve Exp $" #endif # include "vpi_priv.h" # include # include +/* + * the iter function only supports getting an iterator of the + * arguments. This works equally well for tasks and functions. + */ static vpiHandle systask_iter(int type, vpiHandle ref) { struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref; - assert(ref->vpi_type->type_code == vpiSysTaskCall); + assert((ref->vpi_type->type_code == vpiSysTaskCall) + || (ref->vpi_type->type_code == vpiSysFuncCall)); if (rfp->nargs == 0) return 0; @@ -88,6 +93,10 @@ const struct __vpirt vpip_sysfunc_rt = { /* * $Log: vpi_systask.c,v $ + * Revision 1.5 2000/05/07 18:20:08 steve + * Import MCD support from Stephen Tell, and add + * system function parameter support to the IVL core. + * * Revision 1.4 2000/05/04 03:37:59 steve * Add infrastructure for system functions, move * $time to that structure and add $random.