Import MCD support from Stephen Tell, and add

system function parameter support to the IVL core.
This commit is contained in:
steve 2000-05-07 18:20:07 +00:00
parent b90cda1f3f
commit b28f258463
14 changed files with 572 additions and 139 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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 <cassert>
@ -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.

View File

@ -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.

178
t-vvm.cc
View File

@ -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 <iostream>
@ -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
<< "["<<fun->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 <<"["<<idx<<"] = "
<< scan.result << ";" << endl;
}
}
/* Draw the call to the function. Create a vpip_bit_t array to
receive the return value, and make it into a vvm_bitset_t
when the call returns. */
os_ << " vpip_bit_t " << retval << "_bits["<<retwid<<"];" << endl;
os_ << " vpip_callfunc(\"" << fun->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.

View File

@ -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.
*

View File

@ -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.

View File

@ -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 $@

View File

@ -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

123
vvm/vpi_mcd.c Normal file
View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2000 Stephen G. Tell <steve@telltronics.org>
*
* 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 <assert.h>
# include <stdarg.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
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 = "<stdout>";
mcd_table[1].fp = stderr;
mcd_table[1].filename = "<stderr>";
mcd_table[2].fp = stdout; /* TODO: initialize this to log file */
mcd_table[2].filename = "<stdlog>";
}
/*
* 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;
free(mcd_table[i].filename);
mcd_table[i].fp = NULL;
mcd_table[i].filename = NULL;
} else {
rc |= 1<<i;
}
}
return rc;
}
char *vpi_mcd_name(unsigned int mcd)
{
int i;
for(i = 0; i < 31; i++) {
if( (mcd>>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;
}
int vpi_mcd_printf(unsigned int mcd, const char*fmt, ...)
{
int i;
int len;
int rc;
va_list ap;
rc = len = 0;
va_start(ap, fmt);
for(i = 0; i < 31; i++) {
if( (mcd>>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;
}

View File

@ -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.

View File

@ -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.

View File

@ -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 <stdlib.h>
# include <assert.h>
/*
* 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.