Turn the NetESignal into a NetNode so

that it can connect to the netlist.
 Implement the case statement.
 Convince t-vvm to output code for
 the case statement.
This commit is contained in:
steve 1999-02-08 02:49:56 +00:00
parent 8bdd381cdf
commit 30a3953c85
8 changed files with 225 additions and 35 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: design_dump.cc,v 1.11 1999/02/03 04:20:11 steve Exp $" #ident "$Id: design_dump.cc,v 1.12 1999/02/08 02:49:56 steve Exp $"
#endif #endif
/* /*
@ -445,7 +445,14 @@ void NetEIdent::dump(ostream&o) const
void NetESignal::dump(ostream&o) const void NetESignal::dump(ostream&o) const
{ {
o << sig_->name(); o << name();
}
void NetESignal::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Expression Node: " << name() << endl;
dump_node_pins(o, ind+4);
} }
void NetEUnary::dump(ostream&o) const void NetEUnary::dump(ostream&o) const
@ -490,6 +497,13 @@ void Design::dump(ostream&o) const
/* /*
* $Log: design_dump.cc,v $ * $Log: design_dump.cc,v $
* Revision 1.12 1999/02/08 02:49:56 steve
* Turn the NetESignal into a NetNode so
* that it can connect to the netlist.
* Implement the case statement.
* Convince t-vvm to output code for
* the case statement.
*
* Revision 1.11 1999/02/03 04:20:11 steve * Revision 1.11 1999/02/03 04:20:11 steve
* Parse and elaborate the Verilog CASE statement. * Parse and elaborate the Verilog CASE statement.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: elaborate.cc,v 1.13 1999/02/03 04:20:11 steve Exp $" #ident "$Id: elaborate.cc,v 1.14 1999/02/08 02:49:56 steve Exp $"
#endif #endif
/* /*
@ -572,7 +572,9 @@ NetExpr*PEIdent::elaborate_expr(Design*des, const string&path) const
string name = path+"."+text_; string name = path+"."+text_;
NetNet*net = des->find_signal(name); NetNet*net = des->find_signal(name);
assert(net); assert(net);
return new NetESignal(net); NetESignal*node = new NetESignal(net);
des->add_node(node);
return node;
} }
} }
@ -871,6 +873,13 @@ Design* elaborate(const map<string,Module*>&modules,
/* /*
* $Log: elaborate.cc,v $ * $Log: elaborate.cc,v $
* Revision 1.14 1999/02/08 02:49:56 steve
* Turn the NetESignal into a NetNode so
* that it can connect to the netlist.
* Implement the case statement.
* Convince t-vvm to output code for
* the case statement.
*
* Revision 1.13 1999/02/03 04:20:11 steve * Revision 1.13 1999/02/03 04:20:11 steve
* Parse and elaborate the Verilog CASE statement. * Parse and elaborate the Verilog CASE statement.
* *

19
emit.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: emit.cc,v 1.5 1999/02/01 00:26:49 steve Exp $" #ident "$Id: emit.cc,v 1.6 1999/02/08 02:49:56 steve Exp $"
#endif #endif
/* /*
@ -90,6 +90,11 @@ void NetBlock::emit_proc(ostream&o, struct target_t*tgt) const
tgt->proc_block(o, this); tgt->proc_block(o, this);
} }
void NetCase::emit_proc(ostream&o, struct target_t*tgt) const
{
tgt->proc_case(o, this);
}
void NetCondit::emit_proc(ostream&o, struct target_t*tgt) const void NetCondit::emit_proc(ostream&o, struct target_t*tgt) const
{ {
tgt->proc_condit(o, this); tgt->proc_condit(o, this);
@ -205,6 +210,11 @@ void NetESignal::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_signal(this); tgt->expr_signal(this);
} }
void NetESignal::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->net_esignal(o, this);
}
void NetEUnary::expr_scan(struct expr_scan_t*tgt) const void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
{ {
tgt->expr_unary(this); tgt->expr_unary(this);
@ -224,6 +234,13 @@ void emit(ostream&o, const Design*des, const char*type)
/* /*
* $Log: emit.cc,v $ * $Log: emit.cc,v $
* Revision 1.6 1999/02/08 02:49:56 steve
* Turn the NetESignal into a NetNode so
* that it can connect to the netlist.
* Implement the case statement.
* Convince t-vvm to output code for
* the case statement.
*
* Revision 1.5 1999/02/01 00:26:49 steve * Revision 1.5 1999/02/01 00:26:49 steve
* Carry some line info to the netlist, * Carry some line info to the netlist,
* Dump line numbers for processes. * Dump line numbers for processes.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: netlist.cc,v 1.15 1999/02/03 04:20:11 steve Exp $" #ident "$Id: netlist.cc,v 1.16 1999/02/08 02:49:56 steve Exp $"
#endif #endif
# include <cassert> # include <cassert>
@ -423,13 +423,21 @@ void NetEConst::set_width(unsigned w)
expr_width(w); expr_width(w);
} }
NetESignal::NetESignal(NetNet*n)
: NetExpr(n->pin_count()), NetNode(n->name(), n->pin_count())
{
for (unsigned idx = 0 ; idx < n->pin_count() ; idx += 1) {
connect(pin(idx), n->pin(idx));
}
}
NetESignal::~NetESignal() NetESignal::~NetESignal()
{ {
} }
void NetESignal::set_width(unsigned w) void NetESignal::set_width(unsigned w)
{ {
assert(w == sig_->pin_count()); assert(w == pin_count());
expr_width(w); expr_width(w);
} }
@ -873,6 +881,13 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/* /*
* $Log: netlist.cc,v $ * $Log: netlist.cc,v $
* Revision 1.16 1999/02/08 02:49:56 steve
* Turn the NetESignal into a NetNode so
* that it can connect to the netlist.
* Implement the case statement.
* Convince t-vvm to output code for
* the case statement.
*
* Revision 1.15 1999/02/03 04:20:11 steve * Revision 1.15 1999/02/03 04:20:11 steve
* Parse and elaborate the Verilog CASE statement. * Parse and elaborate the Verilog CASE statement.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: netlist.h,v 1.17 1999/02/03 04:20:11 steve Exp $" #ident "$Id: netlist.h,v 1.18 1999/02/08 02:49:56 steve Exp $"
#endif #endif
/* /*
@ -543,7 +543,13 @@ class NetCase : public NetProc {
void set_case(unsigned idx, NetExpr*ex, NetProc*st); void set_case(unsigned idx, NetExpr*ex, NetProc*st);
//virtual void emit_proc(ostream&, struct target_t*) const; const NetExpr*expr() const { return expr_; }
unsigned nitems() const { return nitems_; }
const NetExpr*expr(unsigned idx) const { return items_[idx].guard; }
const NetProc*stat(unsigned idx) const { return items_[idx].statement; }
virtual void emit_proc(ostream&, struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
private: private:
@ -823,22 +829,22 @@ class NetEIdent : public NetExpr {
/* When a signal shows up in an expression, this type represents /* When a signal shows up in an expression, this type represents
it. From this the expression can get any kind of access to the it. From this the expression can get any kind of access to the
structural signal. */ structural signal. */
class NetESignal : public NetExpr { class NetESignal : public NetExpr, public NetNode {
public: public:
NetESignal(NetNet*n) NetESignal(NetNet*n);
: NetExpr(n->pin_count()), sig_(n) { }
~NetESignal(); ~NetESignal();
const string& name() const { return sig_->name(); } const string& name() const { return NetNode::name(); }
virtual void set_width(unsigned); virtual void set_width(unsigned);
virtual void expr_scan(struct expr_scan_t*) const; virtual void expr_scan(struct expr_scan_t*) const;
virtual void emit_node(ostream&, struct target_t*) const;
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
virtual void dump_node(ostream&, unsigned ind) const;
private: private:
NetNet*sig_;
}; };
/* /*
@ -953,6 +959,13 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $Log: netlist.h,v $
* Revision 1.18 1999/02/08 02:49:56 steve
* Turn the NetESignal into a NetNode so
* that it can connect to the netlist.
* Implement the case statement.
* Convince t-vvm to output code for
* the case statement.
*
* Revision 1.17 1999/02/03 04:20:11 steve * Revision 1.17 1999/02/03 04:20:11 steve
* Parse and elaborate the Verilog CASE statement. * Parse and elaborate the Verilog CASE statement.
* *

131
t-vvm.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: t-vvm.cc,v 1.9 1999/01/01 01:46:01 steve Exp $" #ident "$Id: t-vvm.cc,v 1.10 1999/02/08 02:49:56 steve Exp $"
#endif #endif
# include <iostream> # include <iostream>
@ -45,10 +45,12 @@ class target_vvm : public target_t {
virtual void bufz(ostream&os, const NetBUFZ*); virtual void bufz(ostream&os, const NetBUFZ*);
virtual void udp(ostream&os, const NetUDP*); virtual void udp(ostream&os, const NetUDP*);
virtual void net_const(ostream&os, const NetConst*); virtual void net_const(ostream&os, const NetConst*);
virtual void net_esignal(ostream&os, const NetESignal*);
virtual void net_pevent(ostream&os, const NetPEvent*); virtual void net_pevent(ostream&os, const NetPEvent*);
virtual void start_process(ostream&os, const NetProcTop*); virtual void start_process(ostream&os, const NetProcTop*);
virtual void proc_assign(ostream&os, const NetAssign*); virtual void proc_assign(ostream&os, const NetAssign*);
virtual void proc_block(ostream&os, const NetBlock*); virtual void proc_block(ostream&os, const NetBlock*);
virtual void proc_case(ostream&os, const NetCase*net);
virtual void proc_condit(ostream&os, const NetCondit*); virtual void proc_condit(ostream&os, const NetCondit*);
virtual void proc_task(ostream&os, const NetTask*); virtual void proc_task(ostream&os, const NetTask*);
virtual void proc_while(ostream&os, const NetWhile*); virtual void proc_while(ostream&os, const NetWhile*);
@ -307,10 +309,10 @@ void target_vvm::signal(ostream&os, const NetNet*sig)
if (sig->get_ival(idx) == verinum::Vz) if (sig->get_ival(idx) == verinum::Vz)
continue; continue;
for (NetObj::Link*lnk = sig->pin(0).next_link() for (const NetObj::Link*lnk = sig->pin(0).next_link()
; (*lnk) != sig->pin(0) ; lnk = lnk->next_link()) { ; (*lnk) != sig->pin(0) ; lnk = lnk->next_link()) {
const NetNode*net; const NetNode*net;
if (net = dynamic_cast<const NetNode*>(lnk->get_obj())) { if ((net = dynamic_cast<const NetNode*>(lnk->get_obj()))) {
init_code << " " << init_code << " " <<
mangle(lnk->get_obj()->name()) << mangle(lnk->get_obj()->name()) <<
".init(" << lnk->get_pin() << ", V" << ".init(" << lnk->get_pin() << ", V" <<
@ -520,6 +522,10 @@ void target_vvm::net_const(ostream&os, const NetConst*gate)
emit_gate_outputfun_(gate); emit_gate_outputfun_(gate);
} }
void target_vvm::net_esignal(ostream&, const NetESignal*)
{
}
/* /*
* The net_pevent device is a synthetic device type--a fabrication of * The net_pevent device is a synthetic device type--a fabrication of
* the elaboration phase. An event device receives value changes from * the elaboration phase. An event device receives value changes from
@ -574,18 +580,17 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
net->find_lval_range(lval, msb, lsb); net->find_lval_range(lval, msb, lsb);
if ((lsb == 0) && (msb == (lval->pin_count()-1))) { if ((lsb == 0) && (msb == (lval->pin_count()-1))) {
os << setw(indent_) << "" << "// " << lval->name() os << " // " << lval->name() << " = ";
<< " = ";
net->rval()->dump(os); net->rval()->dump(os);
os << endl; os << endl;
os << setw(indent_) << "" << mangle(lval->name()) os << " " << mangle(lval->name())
<< " = " << rval << ";" << endl; << " = " << rval << ";" << endl;
} else { } else {
assert(0); assert(0);
} }
os << setw(indent_) << "" << mangle(lval->name()) << os << " " << mangle(lval->name()) <<
"_mon.trigger(sim_);" << endl; "_mon.trigger(sim_);" << endl;
@ -603,15 +608,20 @@ void target_vvm::proc_assign(ostream&os, const NetAssign*net)
if (dynamic_cast<const NetAssign*>(cur)) if (dynamic_cast<const NetAssign*>(cur))
continue; continue;
// Skip NetESignal nodes. They are handled as
// expressions.
if (dynamic_cast<const NetESignal*>(cur))
continue;
if (const NetNet*sig = dynamic_cast<const NetNet*>(cur)) { if (const NetNet*sig = dynamic_cast<const NetNet*>(cur)) {
os << setw(indent_) << "" << mangle(sig->name()) os << " " << mangle(sig->name())
<< "[" << pin << "] = " << rval << "[" << idx << "[" << pin << "] = " << rval << "[" << idx
<< "];" << endl; << "];" << endl;
os <<setw(indent_) << "" << mangle(sig->name()) os << " " << mangle(sig->name())
<< "_mon.trigger(sim_);" << endl; << "_mon.trigger(sim_);" << endl;
} else { } else {
os << setw(indent_) << "" << mangle(cur->name()) << os << " " << mangle(cur->name()) <<
".set(sim_, " << pin << ", " << ".set(sim_, " << pin << ", " <<
rval << "[" << idx << "]);" << endl; rval << "[" << idx << "]);" << endl;
} }
@ -624,19 +634,95 @@ void target_vvm::proc_block(ostream&os, const NetBlock*net)
net->emit_recurse(os, this); net->emit_recurse(os, this);
} }
/*
* The code for a case statement introduces basic blocks so causes
* steps to be created. There is a step for each case, and the
* out. For example:
*
* case (foo)
* 1 : X;
* 2 : Y;
* endcase
* Z;
*
* causes code for Z to be generated, and also code for X and Y that
* each branch to Z when they finish. X, Y and Z all generate at least
* one step.
*/
void target_vvm::proc_case(ostream&os, const NetCase*net)
{
string expr = emit_proc_rval(os, indent_, net->expr());
ostrstream sc;
unsigned default_step_ = thread_step_ + 1;
thread_step_ += 1;
/* Handle the case statement like a computed goto, where the
result of the case statements is the next state to go
to. Once that is done, return true so that statement is
executed. */
for (unsigned idx = 0 ; idx < net->nitems() ; idx += 1) {
string guard = emit_proc_rval(os, indent_, net->expr(idx));
thread_step_ += 1;
os << " if (" << expr << ".eequal(" << guard <<
"))" << endl;
os << " step_ = &step_" <<
thread_step_ << "_;" << endl;
{ unsigned save_indent = indent_;
indent_ = 8;
sc << " bool step_" << thread_step_ << "_()" << endl;
sc << " {" << endl;
net->stat(idx)->emit_proc(sc, this);
sc << " step_ = &step_" << default_step_ << "_;" << endl;
sc << " return true;" << endl;
sc << " }" << endl;
indent_ = save_indent;
}
}
os << " else" << endl;
os << " step_ = &step_" << default_step_ << "_;" << endl;
os << " return true;" << endl;
os << " }" << endl;
os << sc.str();
os << " bool step_" << default_step_ << "_()" << endl;
os << " {" << endl;
}
void target_vvm::proc_condit(ostream&os, const NetCondit*net) void target_vvm::proc_condit(ostream&os, const NetCondit*net)
{ {
unsigned ind = indent_;
indent_ += 4;
string expr = emit_proc_rval(os, indent_, net->expr()); string expr = emit_proc_rval(os, indent_, net->expr());
os << setw(ind) << "" << "if (" << expr << "[0] == V1) {" << endl;
net->emit_recurse_if(os, this);
os << setw(ind) << "" << "} else {" << endl;
net->emit_recurse_else(os, this);
os << setw(ind) << "" << "}" << endl;
indent_ = ind; unsigned if_step = ++thread_step_;
unsigned else_step = ++thread_step_;
unsigned out_step = ++thread_step_;
os << " if (" << expr << "[0] == V1)" << endl;
os << " step_ = &step_" << if_step << "_;" << endl;
os << " else" << endl;
os << " step_ = &step_" << else_step << "_;" << endl;
os << " return true;" << endl;
os << " };" << endl;
os << " bool step_" << if_step << "_()" << endl;
os << " {" << endl;
net->emit_recurse_if(os, this);
os << " step_ = &step_" << out_step << "_;" << endl;
os << " return true;" << endl;
os << " }" << endl;
os << " bool step_" << else_step << "_()" << endl;
os << " {" << endl;
net->emit_recurse_else(os, this);
os << " step_ = &step_" << out_step << "_;" << endl;
os << " return true;" << endl;
os << " }" << endl;
os << " bool step_" << out_step << "_()" << endl;
os << " {" << endl;
} }
void target_vvm::proc_task(ostream&os, const NetTask*net) void target_vvm::proc_task(ostream&os, const NetTask*net)
@ -778,6 +864,13 @@ extern const struct target tgt_vvm = {
}; };
/* /*
* $Log: t-vvm.cc,v $ * $Log: t-vvm.cc,v $
* Revision 1.10 1999/02/08 02:49:56 steve
* Turn the NetESignal into a NetNode so
* that it can connect to the netlist.
* Implement the case statement.
* Convince t-vvm to output code for
* the case statement.
*
* Revision 1.9 1999/01/01 01:46:01 steve * Revision 1.9 1999/01/01 01:46:01 steve
* Add startup after initialization. * Add startup after initialization.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: target.cc,v 1.4 1998/12/01 00:42:15 steve Exp $" #ident "$Id: target.cc,v 1.5 1999/02/08 02:49:56 steve Exp $"
#endif #endif
# include "target.h" # include "target.h"
@ -61,6 +61,12 @@ void target_t::net_const(ostream&os, const NetConst*)
"Unhandled CONSTANT node." << endl; "Unhandled CONSTANT node." << endl;
} }
void target_t::net_esignal(ostream&os, const NetESignal*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled Expression Signal node." << endl;
}
void target_t::net_pevent(ostream&os, const NetPEvent*) void target_t::net_pevent(ostream&os, const NetPEvent*)
{ {
cerr << "target (" << typeid(*this).name() << "): " cerr << "target (" << typeid(*this).name() << "): "
@ -79,6 +85,13 @@ void target_t::proc_block(ostream&os, const NetBlock*)
{ {
} }
void target_t::proc_case(ostream&os, const NetCase*cur)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled case:" << endl;
cur->dump(cerr, 6);
}
void target_t::proc_condit(ostream&os, const NetCondit*condit) void target_t::proc_condit(ostream&os, const NetCondit*condit)
{ {
cerr << "target (" << typeid(*this).name() << "): " cerr << "target (" << typeid(*this).name() << "): "
@ -153,6 +166,13 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/* /*
* $Log: target.cc,v $ * $Log: target.cc,v $
* Revision 1.5 1999/02/08 02:49:56 steve
* Turn the NetESignal into a NetNode so
* that it can connect to the netlist.
* Implement the case statement.
* Convince t-vvm to output code for
* the case statement.
*
* Revision 1.4 1998/12/01 00:42:15 steve * Revision 1.4 1998/12/01 00:42:15 steve
* Elaborate UDP devices, * Elaborate UDP devices,
* Support UDP type attributes, and * Support UDP type attributes, and

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: target.h,v 1.4 1998/12/01 00:42:15 steve Exp $" #ident "$Id: target.h,v 1.5 1999/02/08 02:49:56 steve Exp $"
#endif #endif
# include "netlist.h" # include "netlist.h"
@ -64,6 +64,7 @@ struct target_t {
virtual void udp(ostream&os, const NetUDP*); virtual void udp(ostream&os, const NetUDP*);
virtual void net_assign(ostream&os, const NetAssign*); virtual void net_assign(ostream&os, const NetAssign*);
virtual void net_const(ostream&os, const NetConst*); virtual void net_const(ostream&os, const NetConst*);
virtual void net_esignal(ostream&os, const NetESignal*);
virtual void net_pevent(ostream&os, const NetPEvent*); virtual void net_pevent(ostream&os, const NetPEvent*);
/* Output a process (called for each process) */ /* Output a process (called for each process) */
@ -72,6 +73,7 @@ struct target_t {
/* Various kinds of process nodes are dispatched through these. */ /* Various kinds of process nodes are dispatched through these. */
virtual void proc_assign(ostream&os, const NetAssign*); virtual void proc_assign(ostream&os, const NetAssign*);
virtual void proc_block(ostream&os, const NetBlock*); virtual void proc_block(ostream&os, const NetBlock*);
virtual void proc_case(ostream&os, const NetCase*);
virtual void proc_condit(ostream&os, const NetCondit*); virtual void proc_condit(ostream&os, const NetCondit*);
virtual void proc_task(ostream&os, const NetTask*); virtual void proc_task(ostream&os, const NetTask*);
virtual void proc_while(ostream&os, const NetWhile*); virtual void proc_while(ostream&os, const NetWhile*);
@ -114,6 +116,13 @@ extern const struct target *target_table[];
/* /*
* $Log: target.h,v $ * $Log: target.h,v $
* Revision 1.5 1999/02/08 02:49:56 steve
* Turn the NetESignal into a NetNode so
* that it can connect to the netlist.
* Implement the case statement.
* Convince t-vvm to output code for
* the case statement.
*
* Revision 1.4 1998/12/01 00:42:15 steve * Revision 1.4 1998/12/01 00:42:15 steve
* Elaborate UDP devices, * Elaborate UDP devices,
* Support UDP type attributes, and * Support UDP type attributes, and