Add support for force assignment.

This commit is contained in:
steve 2000-04-22 04:20:19 +00:00
parent ad8811282b
commit 44838f8973
18 changed files with 413 additions and 46 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: Statement.cc,v 1.19 2000/04/12 04:23:57 steve Exp $"
#ident "$Id: Statement.cc,v 1.20 2000/04/22 04:20:19 steve Exp $"
#endif
# include "Statement.h"
@ -167,6 +167,17 @@ void PEventStatement::set_statement(Statement*st)
statement_ = st;
}
PForce::PForce(PExpr*l, PExpr*r)
: lval_(l), expr_(r)
{
}
PForce::~PForce()
{
delete lval_;
delete expr_;
}
PForever::PForever(Statement*s)
: statement_(s)
{
@ -182,6 +193,16 @@ PProcess::~PProcess()
delete statement_;
}
PRelease::PRelease(PExpr*l)
: lval_(l)
{
}
PRelease::~PRelease()
{
delete lval_;
}
PRepeat::PRepeat(PExpr*e, Statement*s)
: expr_(e), statement_(s)
{
@ -210,6 +231,9 @@ PWhile::~PWhile()
/*
* $Log: Statement.cc,v $
* Revision 1.20 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.19 2000/04/12 04:23:57 steve
* Named events really should be expressed with PEIdent
* objects in the pform,

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: Statement.h,v 1.24 2000/04/12 04:23:57 steve Exp $"
#ident "$Id: Statement.h,v 1.25 2000/04/22 04:20:19 steve Exp $"
#endif
# include <string>
@ -288,6 +288,20 @@ class PEventStatement : public Statement {
Statement*statement_;
};
class PForce : public Statement {
public:
explicit PForce(PExpr*l, PExpr*r);
~PForce();
virtual NetProc* elaborate(Design*des, const string&path) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*lval_;
PExpr*expr_;
};
class PForever : public Statement {
public:
explicit PForever(Statement*s);
@ -346,6 +360,19 @@ class PRepeat : public Statement {
Statement*statement_;
};
class PRelease : public Statement {
public:
explicit PRelease(PExpr*l);
~PRelease();
virtual NetProc* elaborate(Design*des, const string&path) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
PExpr*lval_;
};
/*
* The PTrigger statement sends a trigger to a named event. Take the
* name here.
@ -381,6 +408,9 @@ class PWhile : public Statement {
/*
* $Log: Statement.h,v $
* Revision 1.25 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.24 2000/04/12 04:23:57 steve
* Named events really should be expressed with PEIdent
* objects in the pform,

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.76 2000/04/12 20:02:52 steve Exp $"
#ident "$Id: design_dump.cc,v 1.77 2000/04/22 04:20:19 steve Exp $"
#endif
/*
@ -154,6 +154,12 @@ void NetDivide::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetForce::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "force " << lval_->name() << endl;
dump_node_pins(o, ind+4);
}
void NetMult::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_MULT (NetMult): " << name() << endl;
@ -546,6 +552,12 @@ void NetEvWait::dump(ostream&o, unsigned ind) const
o << setw(ind+2) << "" << "/* noop */ ;" << endl;
}
void NetForce::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "force " << lval_->name() << " = "
<< name() << ";" << endl;
}
void NetForever::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "forever" << endl;
@ -890,6 +902,9 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.77 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.76 2000/04/12 20:02:52 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,

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: elaborate.cc,v 1.160 2000/04/21 04:38:15 steve Exp $"
#ident "$Id: elaborate.cc,v 1.161 2000/04/22 04:20:19 steve Exp $"
#endif
/*
@ -1802,6 +1802,32 @@ NetProc* PForever::elaborate(Design*des, const string&path) const
return proc;
}
NetProc* PForce::elaborate(Design*des, const string&path) const
{
NetScope*scope = des->find_scope(path);
assert(scope);
NetNet*lval = lval_->elaborate_net(des, path, 0, 0, 0, 0);
if (lval == 0)
return 0;
NetNet*rval = expr_->elaborate_net(des, path, lval->pin_count(),
0, 0, 0);
if (rval == 0)
return 0;
if (rval->pin_count() < lval->pin_count())
rval = pad_to_width(des, path, rval, lval->pin_count());
NetForce* dev = new NetForce(des->local_symbol(path), lval);
des->add_node(dev);
for (unsigned idx = 0 ; idx < dev->pin_count() ; idx += 1)
connect(dev->pin(idx), rval->pin(idx));
return dev;
}
/*
* elaborate the for loop as the equivalent while loop. This eases the
* task for the target code generator. The structure is:
@ -1941,6 +1967,13 @@ void PFunction::elaborate_2(Design*des, NetScope*scope) const
def->set_proc(st);
}
NetProc* PRelease::elaborate(Design*des, const string&path) const
{
cerr << get_line() << ": sorry: I do not elaborate release yet."
<< endl;
return 0;
}
NetProc* PRepeat::elaborate(Design*des, const string&path) const
{
NetScope*scope = des->find_scope(path);
@ -2228,6 +2261,9 @@ Design* elaborate(const map<string,Module*>&modules,
/*
* $Log: elaborate.cc,v $
* Revision 1.161 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.160 2000/04/21 04:38:15 steve
* Bit padding in assignment to memory.
*

15
emit.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: emit.cc,v 1.39 2000/04/12 04:23:58 steve Exp $"
#ident "$Id: emit.cc,v 1.40 2000/04/22 04:20:19 steve Exp $"
#endif
/*
@ -95,6 +95,11 @@ void NetFF::emit_node(ostream&o, struct target_t*tgt) const
tgt->lpm_ff(o, this);
}
void NetForce::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->net_force(o, this);
}
void NetMult::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->lpm_mult(o, this);
@ -167,6 +172,11 @@ bool NetCondit::emit_proc(ostream&o, struct target_t*tgt) const
return true;
}
bool NetForce::emit_proc(ostream&o, struct target_t*tgt) const
{
return tgt->proc_force(o, this);
}
bool NetForever::emit_proc(ostream&o, struct target_t*tgt) const
{
tgt->proc_forever(o, this);
@ -416,6 +426,9 @@ bool emit(ostream&o, const Design*des, const char*type)
/*
* $Log: emit.cc,v $
* Revision 1.40 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.39 2000/04/12 04:23:58 steve
* Named events really should be expressed with PEIdent
* objects in the pform,

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.116 2000/04/18 01:02:54 steve Exp $"
#ident "$Id: netlist.cc,v 1.117 2000/04/22 04:20:19 steve Exp $"
#endif
# include <cassert>
@ -1735,6 +1735,25 @@ verinum::V NetConst::value(unsigned idx) const
return value_[idx];
}
NetForce::NetForce(const string&n, NetNet*l)
: NetNode(n, l->pin_count()), lval_(l)
{
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name("I", idx);
}
}
NetForce::~NetForce()
{
}
const NetObj::Link& NetForce::lval_pin(unsigned idx) const
{
assert(idx < lval_->pin_count());
return lval_->pin(idx);
}
NetFuncDef::NetFuncDef(NetScope*s, const svector<NetNet*>&po)
: scope_(s), statement_(0), ports_(po)
{
@ -2483,6 +2502,9 @@ bool NetUDP::sequ_glob_(string input, char output)
/*
* $Log: netlist.cc,v $
* Revision 1.117 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.116 2000/04/18 01:02:54 steve
* Minor cleanup of NetTaskDef.
*

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.126 2000/04/20 00:28:03 steve Exp $"
#ident "$Id: netlist.h,v 1.127 2000/04/22 04:20:19 steve Exp $"
#endif
/*
@ -1401,6 +1401,33 @@ class NetEvProbe : public NetNode {
NetEvProbe*enext_;
};
/*
* The force statement causes the r-val net to be forced onto the
* l-val net when it is executed. The code generator is expected to
* know what that means. All the expressions are structural and behave
* like nets.
*
* This class is a NetProc because it it turned on by procedural
* behavior. However, it is also a NetNode because it connects to
* nets, and when activated follows the net values.
*/
class NetForce : public NetProc, public NetNode {
public:
explicit NetForce(const string&n, NetNet*l);
~NetForce();
const NetObj::Link& lval_pin(unsigned) const;
virtual void dump(ostream&, unsigned ind) const;
virtual bool emit_proc(ostream&, struct target_t*) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual void emit_node(ostream&, struct target_t*) const;
private:
NetNet*lval_;
};
/*
* A forever statement is executed over and over again forever. Or
* until its block is disabled.
@ -2391,6 +2418,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.127 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.126 2000/04/20 00:28:03 steve
* Catch some simple identity compareoptimizations.
*

14
parse.y
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: parse.y,v 1.91 2000/04/21 03:22:18 steve Exp $"
#ident "$Id: parse.y,v 1.92 2000/04/22 04:20:19 steve Exp $"
#endif
# include "parse_misc.h"
@ -1671,8 +1671,10 @@ statement
$$ = 0;
}
| K_force lavalue '=' expression ';'
{ yyerror(@1, "sorry: procedural force assign not supported.");
$$ = 0;
{ PForce*tmp = new PForce($2, $4);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| K_TRIGGER IDENTIFIER ';'
{ PTrigger*tmp = new PTrigger($2);
@ -1718,8 +1720,10 @@ statement
$$ = tmp;
}
| K_release lavalue ';'
{ yyerror(@1, "sorry: release not supported.");
$$ = 0;
{ PRelease*tmp = new PRelease($2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
}
| K_repeat '(' expression ')' statement
{ PRepeat*tmp = new PRepeat($3, $5);

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: pform_dump.cc,v 1.54 2000/04/12 20:02:53 steve Exp $"
#ident "$Id: pform_dump.cc,v 1.55 2000/04/22 04:20:19 steve Exp $"
#endif
/*
@ -483,6 +483,12 @@ void PEventStatement::dump(ostream&out, unsigned ind) const
}
}
void PForce::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "force " << *lval_ << " = " << *expr_
<< "; /* " << get_line() << " */" << endl;
}
void PForever::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "forever /* " << get_line() << " */" << endl;
@ -512,6 +518,12 @@ void PFunction::dump(ostream&out, unsigned ind) const
out << setw(ind) << "" << "/* NOOP */" << endl;
}
void PRelease::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "release " << *lval_ << "; /* "
<< get_line() << " */" << endl;
}
void PRepeat::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "repeat (" << *expr_ << ")" << endl;
@ -733,6 +745,9 @@ void PUdp::dump(ostream&out) const
/*
* $Log: pform_dump.cc,v $
* Revision 1.55 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.54 2000/04/12 20:02:53 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,

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.137 2000/04/15 19:51:30 steve Exp $"
#ident "$Id: t-vvm.cc,v 1.138 2000/04/22 04:20:19 steve Exp $"
#endif
# include <iostream>
@ -80,6 +80,7 @@ class target_vvm : public target_t {
virtual void net_assign_nb(ostream&os, const NetAssignNB*);
virtual void net_case_cmp(ostream&os, const NetCaseCmp*);
virtual void net_const(ostream&os, const NetConst*);
virtual bool net_force(ostream&os, const NetForce*);
virtual void net_probe(ostream&os, const NetEvProbe*);
virtual bool process(ostream&os, const NetProcTop*);
virtual void proc_assign(ostream&os, const NetAssign*);
@ -91,6 +92,7 @@ class target_vvm : public target_t {
void proc_case_fun(ostream&os, const NetCase*net);
virtual void proc_condit(ostream&os, const NetCondit*);
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 void proc_repeat(ostream&os, const NetRepeat*);
virtual void proc_stask(ostream&os, const NetSTask*);
@ -802,7 +804,7 @@ void target_vvm::end_design(ostream&os, const Design*mod)
os << "static struct __vpiNumberConst number_table[" <<
number_counter+1 << "];" << endl;
if (nexus_wire_counter > 0)
os << "static vvm_nexus_wire nexus_wire_table[" <<
os << "static vvm_nexus nexus_wire_table[" <<
nexus_wire_counter << "];" << endl;
if (signal_bit_counter > 0)
os << "static vpip_bit_t signal_bit_table[" <<
@ -1734,6 +1736,24 @@ void target_vvm::net_const(ostream&os, const NetConst*gate)
}
bool target_vvm::net_force(ostream&os, const NetForce*dev)
{
string mname = mangle(dev->name());
os << "static vvm_force " << mname << "(" << dev->pin_count()
<< ");" << endl;
for (unsigned idx = 0 ; idx < dev->pin_count() ; idx += 1) {
string nexus = nexus_from_link(&dev->pin(idx));
unsigned ncode = nexus_wire_map[nexus];
init_code << " nexus_wire_table["<<ncode<<"].connect(&"
<< mname << ", " << idx << ");" << endl;
}
return true;
}
void target_vvm::net_probe(ostream&os, const NetEvProbe*net)
{
string mname = mangle(net->name());
@ -2310,6 +2330,21 @@ void target_vvm::proc_condit_fun(ostream&os, const NetCondit*net)
defn << " }" << endl;
}
bool target_vvm::proc_force(ostream&os, const NetForce*dev)
{
const string mname = mangle(dev->name());
for (unsigned idx = 0 ; idx < dev->pin_count() ; idx += 1) {
string nexus = nexus_from_link(&dev->lval_pin(idx));
unsigned ncode = nexus_wire_map[nexus];
defn << " " << mname << ".force("<<idx<<", "
<< "nexus_wire_table+"<<ncode << ");" << endl;
}
return true;
}
/*
* The forever loop is implemented by starting a basic block, handing
* the statement, and putting in a goto to the beginning of the block.
@ -2626,6 +2661,9 @@ extern const struct target tgt_vvm = {
};
/*
* $Log: t-vvm.cc,v $
* Revision 1.138 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.137 2000/04/15 19:51:30 steve
* fork-join support in vvm.
*

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: target.cc,v 1.35 2000/04/12 04:23:58 steve Exp $"
#ident "$Id: target.cc,v 1.36 2000/04/22 04:20:19 steve Exp $"
#endif
# include "target.h"
@ -155,6 +155,13 @@ void target_t::net_const(ostream&os, const NetConst*)
"Unhandled CONSTANT node." << endl;
}
bool target_t::net_force(ostream&os, const NetForce*dev)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetForce node." << endl;
return false;
}
void target_t::net_probe(ostream&os, const NetEvProbe*net)
{
cerr << "target (" << typeid(*this).name() << "): "
@ -218,6 +225,13 @@ void target_t::proc_delay(ostream&os, const NetPDelay*)
"Unhandled proc_delay." << endl;
}
bool target_t::proc_force(ostream&os, const NetForce*dev)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled proc_force." << endl;
return false;
}
void target_t::proc_forever(ostream&os, const NetForever*)
{
cerr << "target (" << typeid(*this).name() << "): "
@ -339,6 +353,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/*
* $Log: target.cc,v $
* Revision 1.36 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.35 2000/04/12 04:23:58 steve
* Named events really should be expressed with PEIdent
* objects in the pform,

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: target.h,v 1.34 2000/04/12 04:23:58 steve Exp $"
#ident "$Id: target.h,v 1.35 2000/04/22 04:20:20 steve Exp $"
#endif
# include "netlist.h"
@ -91,6 +91,7 @@ struct target_t {
virtual void net_assign_nb(ostream&os, const NetAssignNB*);
virtual void net_case_cmp(ostream&os, const NetCaseCmp*);
virtual void net_const(ostream&os, const NetConst*);
virtual bool net_force(ostream&os, const NetForce*);
virtual void net_probe(ostream&os, const NetEvProbe*);
/* Output a process (called for each process). It is up to the
@ -105,6 +106,7 @@ struct target_t {
virtual bool proc_block(ostream&os, const NetBlock*);
virtual void proc_case(ostream&os, const NetCase*);
virtual void proc_condit(ostream&os, const NetCondit*);
virtual bool proc_force(ostream&os, const NetForce*);
virtual void proc_forever(ostream&os, const NetForever*);
virtual void proc_repeat(ostream&os, const NetRepeat*);
virtual bool proc_trigger(ostream&os, const NetEvTrig*);
@ -152,6 +154,9 @@ extern const struct target *target_table[];
/*
* $Log: target.h,v $
* Revision 1.35 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
* Revision 1.34 2000/04/12 04:23:58 steve
* Named events really should be expressed with PEIdent
* objects in the pform,

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.28 2000/04/01 21:40:23 steve Exp $"
#ident "$Id: Makefile.in,v 1.29 2000/04/22 04:20:20 steve Exp $"
#
#
SHELL = /bin/sh
@ -59,7 +59,7 @@ all: libvvm.a
mv $*.d dep
O = vvm_add_sub.o vvm_bit.o vvm_calltf.o vvm_clshift.o vvm_compare.o \
vvm_event.o vvm_ff.o \
vvm_event.o vvm_ff.o vvm_force.o \
vvm_func.o vvm_gates.o vvm_idiv.o vvm_mult.o vvm_mux.o \
vvm_nexus.o vvm_pevent.o vvm_signal.o vvm_thread.o vvm_udp.o vpip.o

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.14 2000/03/31 07:08:39 steve Exp $"
#ident "$Id: vpi_priv.h,v 1.15 2000/04/22 04:20:20 steve Exp $"
#endif
/*
@ -51,6 +51,8 @@ struct __vpirt;
* 1xxx0xxx - Logic X
* 00001000 - Logic Z
*
* 00000000 - Invalid/No signal
*
* So as you can see, logic values can be quickly compared by masking
* the strength bits.
*
@ -342,6 +344,9 @@ extern int vpip_finished();
/*
* $Log: vpi_priv.h,v $
* Revision 1.15 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
* Revision 1.14 2000/03/31 07:08:39 steve
* allow cancelling of cbValueChange events.
*

72
vvm/vvm_force.cc Normal file
View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: vvm_force.cc,v 1.1 2000/04/22 04:20:20 steve Exp $"
#endif
# include "vvm_gates.h"
# include <assert.h>
vvm_force::vvm_force(unsigned w)
: width_(w)
{
bits_ = new vpip_bit_t[width_];
target_ = new vvm_nexus*[width_];
for (unsigned idx = 0 ; idx < width_ ; idx += 1)
target_[idx] = 0;
}
vvm_force::~vvm_force()
{
delete[]bits_;
delete[]target_;
}
void vvm_force::init_I(unsigned key, vpip_bit_t val)
{
assert(key < width_);
bits_[key] = val;
}
void vvm_force::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (bits_[key] == val)
return;
bits_[key] = val;
target_[key]->force_assign(val);
}
void vvm_force::force(unsigned key, vvm_nexus*tgt)
{
assert(key < width_);
assert(target_[key] == 0);
target_[key] = tgt;
target_[key]->force_assign(bits_[key]);
}
/*
* $Log: vvm_force.cc,v $
* Revision 1.1 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
*/

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: vvm_gates.h,v 1.57 2000/04/15 02:25:32 steve Exp $"
#ident "$Id: vvm_gates.h,v 1.58 2000/04/22 04:20:20 steve Exp $"
#endif
# include "vvm.h"
@ -279,6 +279,35 @@ class vvm_ff : public vvm_nexus::recvr_t {
vvm_ff& operator= (const vvm_ff&);
};
/*
* This class supports the handling of the procedural force
* assignment. It is a device on the netlist that receives a bit value
* and forces it onto the target vvm_nexus. That target is enabled by
* the execution of the force statement in behavioral code.
*/
class vvm_force : public vvm_nexus::recvr_t {
public:
explicit vvm_force(unsigned w);
~vvm_force();
void init_I(unsigned key, vpip_bit_t val);
void force(unsigned key, vvm_nexus*tgt);
void release();
private:
void take_value(unsigned key, vpip_bit_t val);
unsigned width_;
vpip_bit_t*bits_;
vvm_nexus**target_;
private: // not implemented
vvm_force(const vvm_force&);
vvm_force& operator= (const vvm_force&);
};
/*
* This class behaves like a combinational divider. There isn't really
* such a practical device, but this is useful for simulating code
@ -887,6 +916,9 @@ class vvm_posedge : public vvm_nexus::recvr_t {
/*
* $Log: vvm_gates.h,v $
* Revision 1.58 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
* Revision 1.57 2000/04/15 02:25:32 steve
* Support chained events.
*

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: vvm_nexus.cc,v 1.5 2000/03/22 05:16:38 steve Exp $"
#ident "$Id: vvm_nexus.cc,v 1.6 2000/04/22 04:20:20 steve Exp $"
#endif
# include "vvm_nexus.h"
@ -128,10 +128,20 @@ void vvm_nexus::reg_assign(vpip_bit_t val)
{
assert(drivers_ == 0);
value_ = val;
if (force_ != 0)
return;
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
cur->dev->take_value(cur->key, value_);
}
void vvm_nexus::force_assign(vpip_bit_t val)
{
force_ = val;
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
cur->dev->take_value(cur->key, force_);
}
/*
* This method is invoked when something interesting happens at one of
* the drivers. It collects all the driver values, resolves them into
@ -159,6 +169,9 @@ void vvm_nexus::run_values()
if (value_ == val) return;
value_ = val;
if (force_ != 0)
return;
/* Now deliver that output value to all the receivers
connected to this nexus. */
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
@ -197,16 +210,8 @@ vvm_nexus::recvr_t::~recvr_t()
{
}
vvm_nexus_wire::vvm_nexus_wire()
{
}
vvm_nexus_wire::~vvm_nexus_wire()
{
}
vpip_bit_t vvm_nexus_wire::resolution_function(const vpip_bit_t*bits,
unsigned nbits) const
vpip_bit_t vvm_nexus::resolution_function(const vpip_bit_t*bits,
unsigned nbits) const
{
if (nbits == 0) return HiZ;
return vpip_bits_resolve(bits, nbits);
@ -233,6 +238,9 @@ void vvm_delayed_assign(vvm_nexus&l_val, vpip_bit_t r_val,
/*
* $Log: vvm_nexus.cc,v $
* Revision 1.6 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
* Revision 1.5 2000/03/22 05:16:38 steve
* Integrate drive resolution function.
*

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: vvm_nexus.h,v 1.1 2000/03/16 19:03:04 steve Exp $"
#ident "$Id: vvm_nexus.h,v 1.2 2000/04/22 04:20:20 steve Exp $"
#endif
# include "vvm.h"
@ -85,7 +85,7 @@ class vvm_nexus {
public:
vvm_nexus();
virtual ~vvm_nexus() =0;
~vvm_nexus();
// These methods support connecting the receiver and driver to
// the nexus.
@ -100,12 +100,17 @@ class vvm_nexus {
// to procedural assignments to the node, as if it where a reg.
void reg_assign(vpip_bit_t val);
// This method causes the specified value to be forced onto
// the nexus. This overrides all drivers that are attached.
void force_assign(vpip_bit_t val);
void release();
// The run_values() method collects all the current driver
// values and, with the aid of the resolution_function,
// generates the current value for the nexus. It also passes
// that value on to the receuvers.
void run_values();
virtual vpip_bit_t resolution_function(const vpip_bit_t*, unsigned) const =0;
vpip_bit_t resolution_function(const vpip_bit_t*, unsigned) const;
private:
vpip_bit_t value_;
@ -119,31 +124,27 @@ class vvm_nexus {
vpip_bit_t*ival_;
unsigned nival_;
vpip_bit_t force_;
private: // not implemented
vvm_nexus(const vvm_nexus&);
vvm_nexus& operator= (const vvm_nexus&);
};
class vvm_nexus_wire : public vvm_nexus {
public:
vvm_nexus_wire();
~vvm_nexus_wire();
vpip_bit_t resolution_function(const vpip_bit_t*, unsigned) const;
};
/*
* This function arranges for a non-blocking reg_assign to a nexus. It
* creates all the events needed to make it happen after the specified
* delay.
*/
void vvm_delayed_assign(vvm_nexus&l_val, vpip_bit_t r_val,
unsigned long delay);
extern void vvm_delayed_assign(vvm_nexus&l_val, vpip_bit_t r_val,
unsigned long delay);
/*
* $Log: vvm_nexus.h,v $
* Revision 1.2 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
* Revision 1.1 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and