diff --git a/PExpr.h b/PExpr.h index 1a0140c65..1095795bd 100644 --- a/PExpr.h +++ b/PExpr.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: PExpr.h,v 1.6 1999/04/29 02:16:26 steve Exp $" +#ident "$Id: PExpr.h,v 1.7 1999/05/01 02:57:52 steve Exp $" #endif # include @@ -64,17 +64,17 @@ ostream& operator << (ostream&, const PExpr&); class PEEvent : public PExpr { public: - PEEvent(NetPEvent::Type t, PExpr*e) + PEEvent(NetNEvent::Type t, PExpr*e) : type_(t), expr_(e) { } - NetPEvent::Type type() const { return type_; } + NetNEvent::Type type() const { return type_; } PExpr* expr() const { return expr_; } virtual void dump(ostream&) const; private: - NetPEvent::Type type_; + NetNEvent::Type type_; PExpr*expr_; }; @@ -169,6 +169,9 @@ class PEBinary : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.7 1999/05/01 02:57:52 steve + * Handle much more complex event expressions. + * * Revision 1.6 1999/04/29 02:16:26 steve * Parse OR of event expressions. * diff --git a/design_dump.cc b/design_dump.cc index 0932eadcf..16bd5bd4d 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) -#ident "$Id: design_dump.cc,v 1.18 1999/04/25 00:44:10 steve Exp $" +#ident "$Id: design_dump.cc,v 1.19 1999/05/01 02:57:52 steve Exp $" #endif /* @@ -246,7 +246,7 @@ void NetUDP::dump_node(ostream&o, unsigned ind) const dump_comb_(o, ind); } -void NetPEvent::dump_node(ostream&o, unsigned ind) const +void NetNEvent::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "event: "; switch (edge_) { @@ -360,21 +360,15 @@ void NetPDelay::dump(ostream&o, unsigned ind) const void NetPEvent::dump(ostream&o, unsigned ind) const { - o << setw(ind) << "" ; - switch (edge_) { - case NEGEDGE: - o << "@" << "(negedge " << name() << ")"; - break; - case POSEDGE: - o << "@" << "(posedge " << name() << ")"; - break; - case ANYEDGE: - o << "@" << name(); - break; - case POSITIVE: - o << "wait (" << name() << ")"; - break; + o << setw(ind) << "" << "@("; + svector*list = back_list(); + (*list)[0]->dump_proc(o); + for (unsigned idx = 1 ; idx < list->count() ; idx += 1) { + o << " or "; + (*list)[idx]->dump_proc(o); } + delete list; + o << ") /* " << name_ << " */"; if (statement_) { o << endl; @@ -384,7 +378,24 @@ void NetPEvent::dump(ostream&o, unsigned ind) const } } - +void NetNEvent::dump_proc(ostream&o) const +{ + switch (edge_) { + case ANYEDGE: + o << "anyedge "; + break; + case POSEDGE: + o << "posedge "; + break; + case NEGEDGE: + o << "negedge "; + break; + case POSITIVE: + o << "positive "; + break; + } + o << name(); +} void NetTask::dump(ostream&o, unsigned ind) const { @@ -551,6 +562,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.19 1999/05/01 02:57:52 steve + * Handle much more complex event expressions. + * * Revision 1.18 1999/04/25 00:44:10 steve * Core handles subsignal expressions. * diff --git a/elaborate.cc b/elaborate.cc index 492f387e5..0e6042f40 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: elaborate.cc,v 1.21 1999/04/29 02:16:26 steve Exp $" +#ident "$Id: elaborate.cc,v 1.22 1999/05/01 02:57:53 steve Exp $" #endif /* @@ -882,29 +882,28 @@ NetProc* PEventStatement::elaborate(Design*des, const string&path) const return 0; } - if (expr_.count() != 1) { - cerr << get_line() << ": Sorry, unable to elaborate event " - "OR expressions." << endl; - des->errors += 1; - return 0; + /* Create a single NetPEvent, and a unique NetNEvent for each + conjuctive event. */ + + NetPEvent*pe = new NetPEvent(des->local_symbol(path), enet); + for (unsigned idx = 0 ; idx < expr_.count() ; idx += 1) { + NetNet*expr = expr_[idx]->expr()->elaborate_net(des, path); + if (expr == 0) { + cerr << get_line() << ": Failed to elaborate expression: "; + expr_[0]->dump(cerr); + cerr << endl; + delete pe; + return 0; + } + assert(expr); + NetNEvent*ne = new NetNEvent(des->local_symbol(path), + expr_[idx]->type(), pe); + + connect(ne->pin(0), expr->pin(0)); + des->add_node(ne); } - NetPEvent*ev = new NetPEvent(des->local_symbol(path), - expr_[0]->type(), enet); - - NetNet*expr = expr_[0]->expr()->elaborate_net(des, path); - if (expr == 0) { - cerr << get_line() << ": Failed to elaborate expression: "; - expr_[0]->dump(cerr); - cerr << endl; - delete ev; - return 0; - } - assert(expr); - connect(ev->pin(0), expr->pin(0)); - - des->add_node(ev); - return ev; + return pe; } /* @@ -1051,6 +1050,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.22 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.21 1999/04/29 02:16:26 steve * Parse OR of event expressions. * diff --git a/emit.cc b/emit.cc index 9fdfe33a3..cd3a2bda4 100644 --- a/emit.cc +++ b/emit.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: emit.cc,v 1.8 1999/04/25 00:44:10 steve Exp $" +#ident "$Id: emit.cc,v 1.9 1999/05/01 02:57:53 steve Exp $" #endif /* @@ -55,9 +55,9 @@ void NetConst::emit_node(ostream&o, struct target_t*tgt) const tgt->net_const(o, this); } -void NetPEvent::emit_node(ostream&o, struct target_t*tgt) const +void NetNEvent::emit_node(ostream&o, struct target_t*tgt) const { - tgt->net_pevent(o, this); + tgt->net_event(o, this); } void NetBUFZ::emit_node(ostream&o, struct target_t*tgt) const @@ -253,6 +253,9 @@ void emit(ostream&o, const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.9 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.8 1999/04/25 00:44:10 steve * Core handles subsignal expressions. * diff --git a/netlist.cc b/netlist.cc index 37dce1348..cbfcbb33a 100644 --- a/netlist.cc +++ b/netlist.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: netlist.cc,v 1.21 1999/04/25 00:44:10 steve Exp $" +#ident "$Id: netlist.cc,v 1.22 1999/05/01 02:57:53 steve Exp $" #endif # include @@ -480,6 +480,7 @@ void NetEBinary::set_width(unsigned w) case '+': case '-': + case '^': left_->set_width(w); right_->set_width(w); expr_width(w); @@ -532,6 +533,11 @@ NetESignal::~NetESignal() void NetESignal::set_width(unsigned w) { + if (w != pin_count()) { + cerr << "Width of " << w << " does not match " << *this << + endl; + abort(); + } assert(w == pin_count()); expr_width(w); } @@ -553,7 +559,15 @@ NetEUnary::~NetEUnary() void NetEUnary::set_width(unsigned w) { - expr_->set_width(w); + switch (op_) { + case '&': + assert(w == 1); + break; + default: + case '~': + expr_->set_width(w); + break; + } expr_width(w); } @@ -1026,6 +1040,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * Revision 1.22 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.21 1999/04/25 00:44:10 steve * Core handles subsignal expressions. * diff --git a/netlist.h b/netlist.h index 005845d98..9856dbdf6 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) -#ident "$Id: netlist.h,v 1.26 1999/04/25 22:52:32 steve Exp $" +#ident "$Id: netlist.h,v 1.27 1999/05/01 02:57:53 steve Exp $" #endif /* @@ -31,6 +31,7 @@ # include # include # include "verinum.h" +# include "sref.h" # include "LineInfo.h" class NetNode; @@ -715,33 +716,55 @@ class NetPDelay : public NetProc { }; /* - * The NetPEvent is a NetNode that connects to the structural part of - * the design. It has only inputs, which cause the side effect of - * triggering an event that the procedural part of the design can use. + * The NetPEvent is associated with NetNEvents. The NetPEvent receives + * eventss from any one of the associated NetNEvents and in response + * causes the attached statement to be executed. Objects of this type + * are not nodes, but require a name anyhow so that backends can + * generate objects to refer to it. */ -class NetPEvent : public NetProc, public NetNode { +class NetNEvent; +class NetPEvent : public NetProc, public sref_back { public: - enum Type { ANYEDGE, POSEDGE, NEGEDGE, POSITIVE }; + NetPEvent(const string&n, NetProc*st) + : name_(n), statement_(st) { } - public: - NetPEvent(const string&ev, Type ed, NetProc*st) - : NetNode(ev, 1), edge_(ed), statement_(st) { } - - Type edge() const { return edge_; } + string name() const { return name_; } virtual void emit_proc(ostream&, struct target_t*) const; - virtual void emit_node(ostream&, struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; - virtual void dump_node(ostream&, unsigned ind) const; void emit_proc_recurse(ostream&, struct target_t*) const; private: - Type edge_; + string name_; NetProc*statement_; }; +/* + * The NetNEvent is a NetNode that connects to the structural part of + * the design. It has only inputs, which cause the side effect of + * triggering an event that the procedural part of the design can use. + */ +class NetNEvent : public NetNode, public sref { + + public: + enum Type { ANYEDGE, POSEDGE, NEGEDGE, POSITIVE }; + + NetNEvent(const string&ev, Type e, NetPEvent*pe) + : NetNode(ev, 1), sref(pe), edge_(e) { } + + Type type() const { return edge_; } + + virtual void emit_node(ostream&, struct target_t*) const; + + void dump_proc(ostream&) const; + virtual void dump_node(ostream&, unsigned ind) const; + + private: + Type edge_; +}; + /* The elaborator should expand all the user defined tasks in line, so this leaves the NetTask to represent activations of system tasks, @@ -1129,6 +1152,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.27 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.26 1999/04/25 22:52:32 steve * Generate SubSignal refrences in vvm. * diff --git a/parse.y b/parse.y index 1bb95e022..227f2fda0 100644 --- a/parse.y +++ b/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: parse.y,v 1.18 1999/04/29 02:16:26 steve Exp $" +#ident "$Id: parse.y,v 1.19 1999/05/01 02:57:53 steve Exp $" #endif # include "parse_misc.h" @@ -241,7 +241,7 @@ event_control event_expression : K_posedge expression - { PEEvent*tmp = new PEEvent(NetPEvent::POSEDGE, $2); + { PEEvent*tmp = new PEEvent(NetNEvent::POSEDGE, $2); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); svector*tl = new svector(1); @@ -249,7 +249,7 @@ event_expression $$ = tl; } | K_negedge expression - { PEEvent*tmp = new PEEvent(NetPEvent::NEGEDGE, $2); + { PEEvent*tmp = new PEEvent(NetNEvent::NEGEDGE, $2); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); svector*tl = new svector(1); @@ -257,7 +257,7 @@ event_expression $$ = tl; } | expression - { PEEvent*tmp = new PEEvent(NetPEvent::ANYEDGE, $1); + { PEEvent*tmp = new PEEvent(NetNEvent::ANYEDGE, $1); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); svector*tl = new svector(1); @@ -776,7 +776,7 @@ statement } | K_wait '(' expression ')' statement_opt { PEventStatement*tmp; - PEEvent*etmp = new PEEvent(NetPEvent::POSITIVE, $3); + PEEvent*etmp = new PEEvent(NetNEvent::POSITIVE, $3); tmp = new PEventStatement(etmp); tmp->set_statement($5); $$ = tmp; diff --git a/pform_dump.cc b/pform_dump.cc index 291d3056c..cfddcda6f 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: pform_dump.cc,v 1.13 1999/04/29 02:16:26 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.14 1999/05/01 02:57:53 steve Exp $" #endif /* @@ -45,15 +45,15 @@ void PExpr::dump(ostream&out) const void PEEvent::dump(ostream&out) const { switch (type_) { - case NetPEvent::ANYEDGE: + case NetNEvent::ANYEDGE: break; - case NetPEvent::POSEDGE: + case NetNEvent::POSEDGE: out << "posedge "; break; - case NetPEvent::NEGEDGE: + case NetNEvent::NEGEDGE: out << "negedge "; break; - case NetPEvent::POSITIVE: + case NetNEvent::POSITIVE: out << "positive "; break; } @@ -434,6 +434,9 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.14 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.13 1999/04/29 02:16:26 steve * Parse OR of event expressions. * diff --git a/sref.h b/sref.h new file mode 100644 index 000000000..1d4a518af --- /dev/null +++ b/sref.h @@ -0,0 +1,111 @@ +#ifndef __sref_H +#define __sref_H +/* + * Copyright (c) 1999 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. In order to redistribute the software in + * binary form, you will need a Picture Elements Binary Software + * License. + * + * 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) +#ident "$Id: sref.h,v 1.1 1999/05/01 02:57:53 steve Exp $" +#endif + +# include +# include "svector.h" + +/* + * The sref class is a reference with automatic reference counting. It + * implementes a many-to-one linkage where T1 is the many type and T2 + * is the one type. + */ + +template class sref; +template class sref_back; + +template class sref_back { + + friend class sref; + + public: + sref_back() : sback_(0) { } + ~sref_back() { assert(sback_ == 0); } + + svector* back_list() const; + + private: + sref*sback_; +}; + +template class sref { + + friend class sref_back; + + public: + sref(T1*d) : dest_(d) { insert_(); } + virtual ~sref() { desert_(); } + + T1*fore_ptr() { return dest_; } + const T1*fore_ptr() const { return dest_; } + + private: + T1*dest_; + sref*next_; + + void insert_() + { if (dest_->sback_ == 0) { + next_ = this; + dest_->sback_ = this; + } else { + next_ = dest_->sback_->next_; + dest_->sback_->next_ = this; + } + } + + // Not implemented yet. + void desert_() { assert(0); } +}; + +template +svector* sref_back::back_list() const +{ + if (sback_ == 0) return 0; + unsigned cnt = 1; + sref*cur = sback_->next_; + while (cur != sback_) { + cnt += 1; + cur = cur->next_; + } + + svector* result = new svector(cnt); + (*result)[0] = dynamic_cast(sback_); + cur = sback_->next_; + cnt = 1; + while (cur != sback_) { + (*result)[cnt] = dynamic_cast(cur); + cnt += 1; + cur = cur->next_; + } + return result; +} + +/* + * $Log: sref.h,v $ + * Revision 1.1 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * + */ +#endif diff --git a/svector.h b/svector.h index 066ef02e2..3ef31ae23 100644 --- a/svector.h +++ b/svector.h @@ -1,8 +1,7 @@ #ifndef __svector_H #define __svector_H /* - * Copyright (c) 1999 Picture Elements, Inc. - * Stephen Williams (steve@picturel.com) + * Copyright (c) 1999 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -20,15 +19,9 @@ * 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 - * --- - * You should also have recieved a copy of the Picture Elements - * Binary Software License offer along with the source. This offer - * allows you to obtain the right to redistribute the software in - * binary (compiled) form. If you have not received it, contact - * Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704. */ #if !defined(WINNT) -#ident "$Id: svector.h,v 1.1 1999/04/29 02:16:26 steve Exp $" +#ident "$Id: svector.h,v 1.2 1999/05/01 02:57:53 steve Exp $" #endif # include @@ -87,6 +80,9 @@ template class svector { /* * $Log: svector.h,v $ + * Revision 1.2 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.1 1999/04/29 02:16:26 steve * Parse OR of event expressions. * diff --git a/t-verilog.cc b/t-verilog.cc index 261141913..0b45e6da7 100644 --- a/t-verilog.cc +++ b/t-verilog.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: t-verilog.cc,v 1.3 1998/12/01 00:42:15 steve Exp $" +#ident "$Id: t-verilog.cc,v 1.4 1999/05/01 02:57:53 steve Exp $" #endif /* @@ -222,21 +222,25 @@ void target_verilog::proc_event(ostream&os, const NetPEvent*net) { os << setw(indent_) << "" << "@"; +#if 0 unsigned sidx; const NetNet*sig = find_link_signal(net, 0, sidx); switch (net->edge()) { - case NetPEvent::ANYEDGE: + case NetNEvent::ANYEDGE: os << mangle(sig->name()) << "[" << sidx << "]"; break; - case NetPEvent::POSEDGE: + case NetNEvent::POSEDGE: os << "(posedge " << mangle(sig->name()) << "[" << sidx << "])"; break; - case NetPEvent::NEGEDGE: + case NetNEvent::NEGEDGE: os << "(negedge " << mangle(sig->name()) << "[" << sidx << "])"; break; } - +#else + os << endl; + os << "#error \"proc_event temporarily out of order\""; +#endif os << endl; indent_ += 4; @@ -294,6 +298,9 @@ const struct target tgt_verilog = { /* * $Log: t-verilog.cc,v $ + * Revision 1.4 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.3 1998/12/01 00:42:15 steve * Elaborate UDP devices, * Support UDP type attributes, and diff --git a/t-vvm.cc b/t-vvm.cc index c56b3e403..da86014fd 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) -#ident "$Id: t-vvm.cc,v 1.17 1999/04/25 22:52:32 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.18 1999/05/01 02:57:53 steve Exp $" #endif # include @@ -47,7 +47,7 @@ class target_vvm : public target_t { virtual void udp(ostream&os, const NetUDP*); 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_event(ostream&os, const NetNEvent*); virtual void start_process(ostream&os, const NetProcTop*); virtual void proc_assign(ostream&os, const NetAssign*); virtual void proc_block(ostream&os, const NetBlock*); @@ -584,7 +584,7 @@ void target_vvm::net_esignal(ostream&os, const NetESignal*net) } /* - * The net_pevent device is a synthetic device type--a fabrication of + * The net_event device is a synthetic device type--a fabrication of * the elaboration phase. An event device receives value changes from * the attached signal. It is an input only device, its only value * being the side-effects that threads waiting on events can be @@ -593,10 +593,32 @@ void target_vvm::net_esignal(ostream&os, const NetESignal*net) * The proc_event method handles the other half of this, the process * that blocks on the event. */ -void target_vvm::net_pevent(ostream&os, const NetPEvent*gate) +void target_vvm::net_event(ostream&os, const NetNEvent*gate) { - os << "static vvm_pevent " << mangle(gate->name()) << ";" - " /* " << gate->name() << " */" << endl; + string pevent = mangle(gate->fore_ptr()->name()); + os << " /* " << gate->name() << " */" << endl; + + os << "#ifndef PEVENT_" << pevent << endl; + os << "#define PEVENT_" << pevent << endl; + os << "static vvm_sync " << pevent << ";" << endl; + os << "#endif" << endl; + + os << "static vvm_pevent " << mangle(gate->name()) << "(&" << + pevent << ", "; + switch (gate->type()) { + case NetNEvent::POSEDGE: + os << "vvm_pevent::POSEDGE"; + break; + case NetNEvent::NEGEDGE: + os << "vvm_pevent::NEGEDGE"; + break; + case NetNEvent::ANYEDGE: + os << "vvm_pevent::ANYEDGE"; + break; + default: + assert(0); + } + os << ");" << endl; } void target_vvm::start_process(ostream&os, const NetProcTop*proc) @@ -829,6 +851,7 @@ void target_vvm::proc_event(ostream&os, const NetPEvent*proc) thread_step_ += 1; os << " step_ = &step_" << thread_step_ << "_;" << endl; +#if 0 /* POSITIVE is for the wait construct, and needs to be handled specially. The structure of the generated code is: @@ -879,7 +902,18 @@ void target_vvm::proc_event(ostream&os, const NetPEvent*proc) os << " }" << endl; os << " bool step_" << thread_step_ << "_()" << endl; os << " {" << endl; - +#else + /* The canonical wait for an edge puts the thread into the + correct wait object, then returns false from the thread to + suspend execution. When things are ready to proceed, the + correct vvm_pevent will send a wakeup to start the next + basic block. */ + os << " " << mangle(proc->name()) << ".wait(this);" << endl; + os << " return false;" << endl; + os << " }" << endl; + os << " bool step_" << thread_step_ << "_()" << endl; + os << " {" << endl; +#endif proc->emit_proc_recurse(os, this); } @@ -923,6 +957,9 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.18 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.17 1999/04/25 22:52:32 steve * Generate SubSignal refrences in vvm. * diff --git a/target.cc b/target.cc index 57caa252e..82f649534 100644 --- a/target.cc +++ b/target.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: target.cc,v 1.7 1999/04/25 00:44:10 steve Exp $" +#ident "$Id: target.cc,v 1.8 1999/05/01 02:57:53 steve Exp $" #endif # include "target.h" @@ -73,10 +73,10 @@ void target_t::net_esignal(ostream&os, const NetESignal*) "Unhandled Expression Signal node." << endl; } -void target_t::net_pevent(ostream&os, const NetPEvent*) +void target_t::net_event(ostream&os, const NetNEvent*) { cerr << "target (" << typeid(*this).name() << "): " - "Unhandled EVENT node." << endl; + "Unhandled EVENT net node." << endl; } void target_t::start_process(ostream&os, const NetProcTop*) @@ -184,6 +184,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex) /* * $Log: target.cc,v $ + * Revision 1.8 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.7 1999/04/25 00:44:10 steve * Core handles subsignal expressions. * diff --git a/target.h b/target.h index cc92c1411..587dd595e 100644 --- a/target.h +++ b/target.h @@ -1,7 +1,7 @@ #ifndef __target_H #define __target_H /* - * Copyright (c) 1998 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: target.h,v 1.7 1999/04/25 00:44:10 steve Exp $" +#ident "$Id: target.h,v 1.8 1999/05/01 02:57:53 steve Exp $" #endif # include "netlist.h" @@ -68,7 +68,7 @@ struct target_t { virtual void net_assign(ostream&os, const NetAssign*); 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_event(ostream&os, const NetNEvent*); /* Output a process (called for each process) */ virtual void start_process(ostream&os, const NetProcTop*); @@ -121,6 +121,9 @@ extern const struct target *target_table[]; /* * $Log: target.h,v $ + * Revision 1.8 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.7 1999/04/25 00:44:10 steve * Core handles subsignal expressions. * diff --git a/targets.cc b/targets.cc index 82b70e39a..568780184 100644 --- a/targets.cc +++ b/targets.cc @@ -17,19 +17,19 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: targets.cc,v 1.3 1999/01/24 01:35:36 steve Exp $" +#ident "$Id: targets.cc,v 1.4 1999/05/01 02:57:53 steve Exp $" #endif # include "target.h" extern const struct target tgt_null; -extern const struct target tgt_verilog; +//extern const struct target tgt_verilog; extern const struct target tgt_vvm; extern const struct target tgt_xnf; const struct target *target_table[] = { &tgt_null, - &tgt_verilog, + //&tgt_verilog, &tgt_vvm, &tgt_xnf, 0 @@ -37,6 +37,9 @@ const struct target *target_table[] = { /* * $Log: targets.cc,v $ + * Revision 1.4 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.3 1999/01/24 01:35:36 steve * Support null target for generating no output. * diff --git a/vvm/.cvsignore b/vvm/.cvsignore index 7b5d7e4bc..cad51a157 100644 --- a/vvm/.cvsignore +++ b/vvm/.cvsignore @@ -1 +1,2 @@ dep +Makefile diff --git a/vvm/vvm_gates.h b/vvm/vvm_gates.h index a7c647674..e0c9edcd4 100644 --- a/vvm/vvm_gates.h +++ b/vvm/vvm_gates.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm_gates.h,v 1.7 1999/02/15 05:52:50 steve Exp $" +#ident "$Id: vvm_gates.h,v 1.8 1999/05/01 02:57:53 steve Exp $" #endif # include "vvm.h" @@ -341,20 +341,45 @@ class vvm_bufz { vvm_out_event::action_t output_; }; +/* + * Threads use the vvm_sync to wait for something to happen. This + * class cooperates with the vvm_pevent class that is the actual gates + * that receive signals. By handling the suspension and the awakening + * separately, I can trivially handle event OR expressions. + * + * When there is an event expression in the source, the elaborator + * makes NetNEvent objects, which are approximately represented by the + * vvm_pevent class. + */ +class vvm_sync { + + public: + vvm_sync(); + + void wait(vvm_thread*); + void wakeup(vvm_simulation*sim); + + private: + vvm_thread*hold_; + + private: // not implemented + vvm_sync(const vvm_sync&); + vvm_sync& operator= (const vvm_sync&); +}; + class vvm_pevent { public: enum EDGE { ANYEDGE, POSEDGE, NEGEDGE }; - explicit vvm_pevent(); - void wait(EDGE, vvm_thread*); + explicit vvm_pevent(vvm_sync*tgt, EDGE e); void set(vvm_simulation*sim, unsigned, vvm_bit_t val); vvm_bit_t get() const { return value_; } private: + vvm_sync*target_; vvm_bit_t value_; - vvm_thread*hold_; - EDGE hold_edge_; + EDGE edge_; private: // not implemented vvm_pevent(const vvm_pevent&); @@ -363,6 +388,9 @@ class vvm_pevent { /* * $Log: vvm_gates.h,v $ + * Revision 1.8 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.7 1999/02/15 05:52:50 steve * Mangle that handles device instance numbers. * diff --git a/vvm/vvm_pevent.cc b/vvm/vvm_pevent.cc index f5454c5ab..50abb85bb 100644 --- a/vvm/vvm_pevent.cc +++ b/vvm/vvm_pevent.cc @@ -17,52 +17,49 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm_pevent.cc,v 1.1 1998/11/09 23:44:11 steve Exp $" +#ident "$Id: vvm_pevent.cc,v 1.2 1999/05/01 02:57:53 steve Exp $" #endif # include "vvm.h" # include "vvm_gates.h" -vvm_pevent::vvm_pevent() -: value_(V0), hold_(0) +vvm_sync::vvm_sync() +: hold_(0) { } -void vvm_pevent::wait(EDGE edge, vvm_thread*thr) +void vvm_sync::wait(vvm_thread*thr) { assert(hold_ == 0); hold_ = thr; - hold_edge_ = edge; +} + +void vvm_sync::wakeup(vvm_simulation*sim) +{ + vvm_thread*tmp = hold_; + hold_ = 0; + if (tmp) sim->thread_active(tmp); +} + +vvm_pevent::vvm_pevent(vvm_sync*tgt, EDGE e) +: target_(tgt), value_(V0), edge_(e) +{ } void vvm_pevent::set(vvm_simulation*sim, unsigned, vvm_bit_t val) { - if (hold_ == 0) { - value_ = val; - return; - } - if (value_ != val) { - vvm_thread*tmp; - switch (hold_edge_) { + switch (edge_) { case ANYEDGE: - tmp = hold_; - hold_ = 0; - sim->thread_active(tmp); + target_->wakeup(sim); break; case POSEDGE: - if (val == V1) { - tmp = hold_; - hold_ = 0; - sim->thread_active(tmp); - } + if (val == V1) + target_->wakeup(sim); break; case NEGEDGE: - if (val == V0) { - tmp = hold_; - hold_ = 0; - sim->thread_active(tmp); - } + if (val == V0) + target_->wakeup(sim); break; } value_ = val; @@ -71,6 +68,9 @@ void vvm_pevent::set(vvm_simulation*sim, unsigned, vvm_bit_t val) /* * $Log: vvm_pevent.cc,v $ + * Revision 1.2 1999/05/01 02:57:53 steve + * Handle much more complex event expressions. + * * Revision 1.1 1998/11/09 23:44:11 steve * Add vvm library. *