Merge branch 'master' into verilog-ams
This commit is contained in:
commit
b20019d8b6
10
PExpr.cc
10
PExpr.cc
|
|
@ -73,6 +73,16 @@ PEBComp::~PEBComp()
|
|||
{
|
||||
}
|
||||
|
||||
PEBLogic::PEBLogic(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
assert(op == 'a' || op == 'o');
|
||||
}
|
||||
|
||||
PEBLogic::~PEBLogic()
|
||||
{
|
||||
}
|
||||
|
||||
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
|
|
|
|||
20
PExpr.h
20
PExpr.h
|
|
@ -494,6 +494,26 @@ class PEBComp : public PEBinary {
|
|||
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* This derived class is for handling logical expressions: && and ||.
|
||||
*/
|
||||
class PEBLogic : public PEBinary {
|
||||
|
||||
public:
|
||||
explicit PEBLogic(char op, PExpr*l, PExpr*r);
|
||||
~PEBLogic();
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&flag);
|
||||
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
};
|
||||
|
||||
class PEBShift : public PEBinary {
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ extern bool debug_eval_tree;
|
|||
extern bool debug_elaborate;
|
||||
extern bool debug_synth2;
|
||||
extern bool debug_optimizer;
|
||||
extern bool debug_automatic;
|
||||
|
||||
/* Path to a directory useful for finding subcomponents. */
|
||||
extern const char*basedir;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ participating in the Icarus Verilog development process. That
|
|||
information will not be repeated here.
|
||||
|
||||
What this documentation *will* cover is the gross structure of the
|
||||
Icarus Verilog core compiler source. This will help orient you to the
|
||||
Icarus Verilog compiler source. This will help orient you to the
|
||||
source code itself, so that you can find the global parts where you
|
||||
can look for even better detail.
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ on the core itself.
|
|||
- The loadable code generators (tgt-*/)
|
||||
|
||||
This core compiler, after it is finished with parsing and semantic
|
||||
analysis, uses loadable code generators to emit code for suppoted
|
||||
analysis, uses loadable code generators to emit code for supported
|
||||
targets. The tgt-*/ directories contains the source for the target
|
||||
code generators that are bundled with Icarus Verilog. The tgt-vvp/
|
||||
directory in particular contains the code generator for the vvp
|
||||
|
|
@ -65,20 +65,20 @@ and the source is in this subdirectory.
|
|||
|
||||
The Icarus Verilog support for the deprecated PLI-1 is in this
|
||||
subdirectory. The vvp runtime does not directly support the
|
||||
PLI-1. Insead, the libveriuser library emulates it using the builtin
|
||||
PLI-1. Instead, the libveriuser library emulates it using the builtin
|
||||
PLI-2 support.
|
||||
|
||||
- The Cadence PLI module compatibility module (cadpli/)
|
||||
|
||||
It is possible in some specialized situations to load and execute
|
||||
PLI-1 code writen for Verilog-XL. This directory contains the source
|
||||
PLI-1 code written for Verilog-XL. This directory contains the source
|
||||
for the module that provides the Cadence PLI interface.
|
||||
|
||||
|
||||
* The Core Compiler
|
||||
|
||||
The "ivl" binary is the core compiler that does the heavy lifting of
|
||||
compiling the Veriog source (including libraries) and generating the
|
||||
compiling the Verilog source (including libraries) and generating the
|
||||
output. This is the most complex component of the Icarus Verilog
|
||||
compilation system.
|
||||
|
||||
|
|
@ -86,8 +86,8 @@ The process in the abstract starts with the Verilog lexical analysis
|
|||
and parsing to generate an internal "pform". The pform is then
|
||||
translated by elaboration into the "netlist" form. The netlist is
|
||||
processed by some functors (which include some optimizations and
|
||||
optional synthesys) then is translated into the ivl_target internal
|
||||
form. And finallly, the ivl_target form is passed via the ivl_target.h
|
||||
optional synthesis) then is translated into the ivl_target internal
|
||||
form. And finally, the ivl_target form is passed via the ivl_target.h
|
||||
API to the code generators.
|
||||
|
||||
- Lexical Analysis
|
||||
|
|
@ -105,9 +105,9 @@ large set of potential keywords.
|
|||
- Parsing
|
||||
|
||||
The parser input file "parse.y" is passed to the "bison" program to
|
||||
generate the parser. The parser uses the functions in parse*.,
|
||||
parse*.cc, pform*.h and pform*.cc to generate the pform from the
|
||||
stream of input tokens. The pfrom is what compiler writers call a
|
||||
generate the parser. The parser uses the functions in parse*.h,
|
||||
parse*.cc, pform.h, and pform*.cc to generate the pform from the
|
||||
stream of input tokens. The pform is what compiler writers call a
|
||||
"decorated parse tree".
|
||||
|
||||
The pform itself is described by the classes in the header files
|
||||
|
|
|
|||
|
|
@ -138,6 +138,14 @@ NetEUFunc* NetEUFunc::dup_expr() const
|
|||
return tmp;
|
||||
}
|
||||
|
||||
NetEUBits* NetEUBits::dup_expr() const
|
||||
{
|
||||
NetEUBits*tmp = new NetEUBits(op_, expr_->dup_expr());
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEUnary* NetEUnary::dup_expr() const
|
||||
{
|
||||
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
|||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, sig, mem, par, eve);
|
||||
symbol_search(this, des, scope, path_, sig, mem, par, eve);
|
||||
|
||||
|
||||
if (mem != 0) {
|
||||
|
|
@ -211,4 +211,3 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
|||
* Check lvalue of procedural continuous assign (PR#29)
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
137
elab_expr.cc
137
elab_expr.cc
|
|
@ -279,8 +279,6 @@ NetExpr* PEBinary::elaborate_expr_base_(Design*des,
|
|||
NetExpr*lp, NetExpr*rp,
|
||||
int expr_wid) const
|
||||
{
|
||||
bool flag;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: elaborate expression "
|
||||
<< *this << " expr_wid=" << expr_wid << endl;
|
||||
|
|
@ -296,11 +294,12 @@ NetExpr* PEBinary::elaborate_expr_base_(Design*des,
|
|||
|
||||
case 'a':
|
||||
case 'o':
|
||||
lp = condition_reduce(lp);
|
||||
rp = condition_reduce(rp);
|
||||
tmp = new NetEBLogic(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Elaboration of " << human_readable_op(op_)
|
||||
<< " Should have been handled in NetEBLogic::elaborate."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
|
||||
case 'p':
|
||||
tmp = new NetEBPow(op_, lp, rp);
|
||||
|
|
@ -341,38 +340,18 @@ NetExpr* PEBinary::elaborate_expr_base_(Design*des,
|
|||
|
||||
case 'E': /* === */
|
||||
case 'N': /* !== */
|
||||
if (lp->expr_type() == IVL_VT_REAL ||
|
||||
rp->expr_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< human_readable_op(op_)
|
||||
<< "may not have real operands." << endl;
|
||||
return 0;
|
||||
}
|
||||
/* Fall through... */
|
||||
case 'e': /* == */
|
||||
case 'n': /* != */
|
||||
if (dynamic_cast<NetEConst*>(rp)
|
||||
&& (lp->expr_width() > rp->expr_width()))
|
||||
rp->set_width(lp->expr_width());
|
||||
|
||||
if (dynamic_cast<NetEConst*>(lp)
|
||||
&& (lp->expr_width() < rp->expr_width()))
|
||||
lp->set_width(rp->expr_width());
|
||||
|
||||
/* from here, handle this like other compares. */
|
||||
case 'L': /* <= */
|
||||
case 'G': /* >= */
|
||||
case '<':
|
||||
case '>':
|
||||
tmp = new NetEBComp(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"expression bit width of comparison != 1." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
break;
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Elaboration of " << human_readable_op(op_)
|
||||
<< " Should have been handled in NetEBComp::elaborate."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
|
||||
case 'm': // min(l,r)
|
||||
case 'M': // max(l,r)
|
||||
|
|
@ -425,6 +404,16 @@ NetExpr* PEBinary::elaborate_expr_base_div_(Design*des,
|
|||
}
|
||||
}
|
||||
|
||||
/* The original elaboration of the left and right expressions
|
||||
already tried to elaborate to the expr_wid. If the
|
||||
expressions are not that width by now, then they need to be
|
||||
padded. The divide expression operands must be the width
|
||||
of the output. */
|
||||
if (expr_wid > 0) {
|
||||
lp = pad_to_width(lp, expr_wid);
|
||||
rp = pad_to_width(rp, expr_wid);
|
||||
}
|
||||
|
||||
NetEBDiv*tmp = new NetEBDiv(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
|
||||
|
|
@ -790,7 +779,83 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
|||
if (type_is_vectorable(rp->expr_type()))
|
||||
rp = pad_to_width(rp, use_wid);
|
||||
|
||||
return elaborate_eval_expr_base_(des, lp, rp, use_wid);
|
||||
eval_expr(lp, use_wid);
|
||||
eval_expr(rp, use_wid);
|
||||
|
||||
// Handle some operand-specific special cases...
|
||||
switch (op_) {
|
||||
case 'E': /* === */
|
||||
case 'N': /* !== */
|
||||
if (lp->expr_type() == IVL_VT_REAL ||
|
||||
rp->expr_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< human_readable_op(op_)
|
||||
<< "may not have real operands." << endl;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
NetEBComp*tmp = new NetEBComp(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
bool flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"expression bit width of comparison != 1." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
unsigned PEBLogic::test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type_out,
|
||||
bool&unsized_flag)
|
||||
{
|
||||
expr_type_ = IVL_VT_LOGIC;
|
||||
expr_width_ = 1;
|
||||
expr_type_out = expr_type_;
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
NetExpr*PEBLogic::elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width_dummp, bool sys_task_arg) const
|
||||
{
|
||||
assert(left_);
|
||||
assert(right_);
|
||||
|
||||
// The left and right expressions are self-determined and
|
||||
// independent. Run their test_width methods independently. We
|
||||
// don't need the widths here, but we do need the expressions
|
||||
// to calculate their self-determined width and type.
|
||||
|
||||
bool left_flag = false;
|
||||
ivl_variable_type_t left_type = IVL_VT_NO_TYPE;
|
||||
left_->test_width(des, scope, 0, 0, left_type, left_flag);
|
||||
|
||||
bool right_flag = false;
|
||||
ivl_variable_type_t right_type = IVL_VT_NO_TYPE;
|
||||
right_->test_width(des, scope, 0, 0, right_type, right_flag);
|
||||
|
||||
NetExpr*lp = elab_and_eval(des, scope, left_, -1);
|
||||
NetExpr*rp = elab_and_eval(des, scope, right_, -1);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lp = condition_reduce(lp);
|
||||
rp = condition_reduce(rp);
|
||||
|
||||
NetEBLogic*tmp = new NetEBLogic(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
tmp->set_width(1);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
unsigned PEBShift::test_width(Design*des, NetScope*scope,
|
||||
|
|
@ -1586,7 +1651,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
|
|||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
symbol_search(des, scope, path_, net, par, eve, ex1, ex2);
|
||||
symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2);
|
||||
|
||||
// If there is a part/bit select expression, then process it
|
||||
// here. This constrains the results no matter what kind the
|
||||
|
|
@ -1699,7 +1764,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, path_,
|
||||
NetScope*found_in = symbol_search(this, des, scope, path_,
|
||||
net, par, eve,
|
||||
ex1, ex2);
|
||||
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, reg, par, eve);
|
||||
symbol_search(this, des, scope, path_, reg, par, eve);
|
||||
if (reg == 0) {
|
||||
cerr << get_fileline() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope_path(scope) <<
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, sig, par, eve);
|
||||
symbol_search(this, des, scope, path_, sig, par, eve);
|
||||
|
||||
if (eve != 0) {
|
||||
cerr << get_fileline() << ": error: named events (" << path_
|
||||
|
|
@ -631,4 +631,3 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
|||
|
||||
return sig;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,52 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
|
|||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*PEBComp::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*lp = left_->elaborate_pexpr(des, scope);
|
||||
NetExpr*rp = right_->elaborate_pexpr(des, scope);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
suppress_binary_operand_sign_if_needed_(lp, rp);
|
||||
|
||||
NetEBComp*tmp = new NetEBComp(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
bool flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"expression bit width of comparison != 1." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*PEBLogic::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*lp = left_->elaborate_pexpr(des, scope);
|
||||
NetExpr*rp = right_->elaborate_pexpr(des, scope);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEBLogic*tmp = new NetEBLogic(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
bool flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"expression bit width of comparison != 1." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Event though parameters are not generally sized, parameter
|
||||
* expressions can include concatenation expressions. This requires
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ bool PEIdent::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if (error_implicit)
|
||||
return true;
|
||||
|
||||
symbol_search(des, scope, path_, sig, par, eve);
|
||||
symbol_search(this, des, scope, path_, sig, par, eve);
|
||||
|
||||
if (eve != 0)
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -2861,7 +2861,8 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
|||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, id->path(),
|
||||
NetScope*found_in = symbol_search(this, des, scope,
|
||||
id->path(),
|
||||
sig, par, eve);
|
||||
|
||||
if (found_in && eve) {
|
||||
|
|
@ -3463,7 +3464,7 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
|
|||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, event_,
|
||||
NetScope*found_in = symbol_search(this, des, scope, event_,
|
||||
sig, par, eve);
|
||||
|
||||
if (found_in == 0) {
|
||||
|
|
|
|||
2
eval.cc
2
eval.cc
|
|
@ -185,7 +185,7 @@ verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
|
|||
return new verinum(scope->genvar_tmp_val);
|
||||
}
|
||||
|
||||
symbol_search(des, scope, path_, net, expr, eve);
|
||||
symbol_search(this, des, scope, path_, net, expr, eve);
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -858,8 +858,10 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
|||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
// Make sure the expression is evaluated at the
|
||||
// expression width.
|
||||
verinum lval = pad_to_width(lc->value(), expr_width());
|
||||
verinum rval = pad_to_width(rc->value(), expr_width());
|
||||
|
||||
NetExpr*tmp = 0;
|
||||
switch (op_) {
|
||||
|
|
|
|||
3
main.cc
3
main.cc
|
|
@ -124,6 +124,7 @@ bool debug_eval_tree = false;
|
|||
bool debug_elaborate = false;
|
||||
bool debug_synth2 = false;
|
||||
bool debug_optimizer = false;
|
||||
bool debug_automatic = false;
|
||||
|
||||
/*
|
||||
* Verbose messages enabled.
|
||||
|
|
@ -392,6 +393,8 @@ static void read_iconfig_file(const char*ipath)
|
|||
} else if (strcmp(cp,"optimizer") == 0) {
|
||||
debug_optimizer = true;
|
||||
cerr << "debug: Enable optimizer debug" << endl;
|
||||
} else if (strcmp(cp,"automatic") == 0) {
|
||||
debug_automatic = true;
|
||||
} else {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -173,6 +173,12 @@ void NetEvent::find_similar_event(list<NetEvent*>&event_list)
|
|||
if (tmp == this)
|
||||
continue;
|
||||
|
||||
/* For automatic tasks, the VVP runtime holds state for events
|
||||
in the automatically allocated context. This means we can't
|
||||
merge similar events in different automatic tasks. */
|
||||
if (scope()->is_auto() && (tmp->scope() != scope()))
|
||||
continue;
|
||||
|
||||
if ((*idx).second != probe_count)
|
||||
continue;
|
||||
|
||||
|
|
@ -553,4 +559,3 @@ NetProc* NetEvWait::statement()
|
|||
* Simulate named event trigger and waits.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -3275,7 +3275,7 @@ class NetEBComp : public NetEBinary {
|
|||
NetEBComp(char op, NetExpr*l, NetExpr*r);
|
||||
~NetEBComp();
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual bool set_width(unsigned w, bool last_chance =false);
|
||||
|
||||
/* A compare expression has a definite width. */
|
||||
virtual bool has_width() const;
|
||||
|
|
@ -3312,7 +3312,7 @@ class NetEBLogic : public NetEBinary {
|
|||
NetEBLogic(char op, NetExpr*l, NetExpr*r);
|
||||
~NetEBLogic();
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual bool set_width(unsigned w, bool last_chance =false);
|
||||
virtual NetEBLogic* dup_expr() const;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
|
@ -3697,6 +3697,7 @@ class NetEUBits : public NetEUnary {
|
|||
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope);
|
||||
|
||||
virtual NetEUBits* dup_expr() const;
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
};
|
||||
|
|
|
|||
14
netmisc.h
14
netmisc.h
|
|
@ -36,21 +36,25 @@
|
|||
* ex2 is the lsb expression for the range. If there is no range, then
|
||||
* these values are set to 0.
|
||||
*/
|
||||
extern NetScope* symbol_search(Design*des,
|
||||
NetScope*start, pform_name_t path,
|
||||
extern NetScope* symbol_search(const LineInfo*li,
|
||||
Design*des,
|
||||
NetScope*start,
|
||||
pform_name_t path,
|
||||
NetNet*&net, /* net/reg */
|
||||
const NetExpr*&par,/* parameter */
|
||||
NetEvent*&eve, /* named event */
|
||||
const NetExpr*&ex1, const NetExpr*&ex2);
|
||||
|
||||
inline NetScope* symbol_search(Design*des,
|
||||
NetScope*start, const pform_name_t&path,
|
||||
inline NetScope* symbol_search(const LineInfo*li,
|
||||
Design*des,
|
||||
NetScope*start,
|
||||
const pform_name_t&path,
|
||||
NetNet*&net, /* net/reg */
|
||||
const NetExpr*&par,/* parameter */
|
||||
NetEvent*&eve /* named event */)
|
||||
{
|
||||
const NetExpr*ex1, *ex2;
|
||||
return symbol_search(des, start, path, net, par, eve, ex1, ex2);
|
||||
return symbol_search(li, des, start, path, net, par, eve, ex1, ex2);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
12
parse.y
12
parse.y
|
|
@ -1033,12 +1033,12 @@ expression
|
|||
$$ = tmp;
|
||||
}
|
||||
| expression K_LOR expression
|
||||
{ PEBinary*tmp = new PEBinary('o', $1, $3);
|
||||
{ PEBinary*tmp = new PEBLogic('o', $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression K_LAND expression
|
||||
{ PEBinary*tmp = new PEBinary('a', $1, $3);
|
||||
{ PEBinary*tmp = new PEBLogic('a', $1, $3);
|
||||
FILE_NAME(tmp, @2);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -2977,7 +2977,13 @@ real_variable
|
|||
{ perm_string name = lex_strings.make($1);
|
||||
pform_makewire(@1, name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
|
||||
if ($2 != 0) {
|
||||
yyerror(@2, "sorry: real variables do not currently support arrays.");
|
||||
index_component_t index;
|
||||
if ($2->size() > 1) {
|
||||
yyerror(@2, "sorry: only 1 dimensional arrays "
|
||||
"are currently supported.");
|
||||
}
|
||||
index = $2->front();
|
||||
pform_set_reg_idx(name, index.msb, index.lsb);
|
||||
delete $2;
|
||||
}
|
||||
$$ = $1;
|
||||
|
|
|
|||
31
pform.cc
31
pform.cc
|
|
@ -110,11 +110,12 @@ PTask* pform_push_task_scope(char*name, bool is_auto)
|
|||
PTask*task;
|
||||
if (pform_cur_generate) {
|
||||
task = new PTask(task_name, pform_cur_generate->lexical_scope,
|
||||
is_auto);
|
||||
is_auto || debug_automatic);
|
||||
pform_cur_generate->tasks[task->pscope_name()] = task;
|
||||
pform_cur_generate->lexical_scope = task;
|
||||
} else {
|
||||
task = new PTask(task_name, lexical_scope, is_auto);
|
||||
task = new PTask(task_name, lexical_scope,
|
||||
is_auto || debug_automatic);
|
||||
pform_cur_module->tasks[task->pscope_name()] = task;
|
||||
lexical_scope = task;
|
||||
}
|
||||
|
|
@ -129,11 +130,12 @@ PFunction* pform_push_function_scope(char*name, bool is_auto)
|
|||
PFunction*func;
|
||||
if (pform_cur_generate) {
|
||||
func = new PFunction(func_name, pform_cur_generate->lexical_scope,
|
||||
is_auto);
|
||||
is_auto || debug_automatic);
|
||||
pform_cur_generate->funcs[func->pscope_name()] = func;
|
||||
pform_cur_generate->lexical_scope = func;
|
||||
} else {
|
||||
func = new PFunction(func_name, lexical_scope, is_auto);
|
||||
func = new PFunction(func_name, lexical_scope,
|
||||
is_auto || debug_automatic);
|
||||
pform_cur_module->funcs[func->pscope_name()] = func;
|
||||
lexical_scope = func;
|
||||
}
|
||||
|
|
@ -181,6 +183,20 @@ static LexicalScope*pform_get_cur_scope()
|
|||
return lexical_scope;
|
||||
}
|
||||
|
||||
static bool pform_at_module_level()
|
||||
{
|
||||
if (pform_cur_generate)
|
||||
if (pform_cur_generate->lexical_scope)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
else
|
||||
if (lexical_scope->pscope_parent())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
PWire*pform_get_wire_in_scope(perm_string name)
|
||||
{
|
||||
/* Note that if we are processing a generate, then the
|
||||
|
|
@ -1293,6 +1309,13 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
|
|||
void pform_make_reginit(const struct vlltype&li,
|
||||
perm_string name, PExpr*expr)
|
||||
{
|
||||
if (! pform_at_module_level()) {
|
||||
VLerror(li, "variable declaration assignments are only "
|
||||
"allowed at the module level.");
|
||||
delete expr;
|
||||
return;
|
||||
}
|
||||
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
VLerror(li, "internal error: reginit to non-register?");
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@
|
|||
/*
|
||||
* Search for the hierarchical name.
|
||||
*/
|
||||
NetScope*symbol_search(Design*des, NetScope*scope, pform_name_t path,
|
||||
NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
|
||||
pform_name_t path,
|
||||
NetNet*&net,
|
||||
const NetExpr*&par,
|
||||
NetEvent*&eve,
|
||||
|
|
@ -57,6 +58,13 @@ NetScope*symbol_search(Design*des, NetScope*scope, pform_name_t path,
|
|||
return 0;
|
||||
|
||||
scope = des->find_scope(scope, path_list);
|
||||
|
||||
if (scope->is_auto() && li) {
|
||||
cerr << li->get_fileline() << ": error: Hierarchical "
|
||||
"reference to automatically allocated item "
|
||||
"`" << key << "' in path `" << path << "'" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (scope) {
|
||||
|
|
|
|||
|
|
@ -198,11 +198,11 @@ vhdl_expr *vhdl_expr::resize(int newwidth)
|
|||
else
|
||||
return this; // Doesn't make sense to resize non-vector type
|
||||
|
||||
vhdl_fcall *resize = new vhdl_fcall("Resize", rtype);
|
||||
resize->add_expr(this);
|
||||
resize->add_expr(new vhdl_const_int(newwidth));
|
||||
vhdl_fcall *resizef = new vhdl_fcall("Resize", rtype);
|
||||
resizef->add_expr(this);
|
||||
resizef->add_expr(new vhdl_const_int(newwidth));
|
||||
|
||||
return resize;
|
||||
return resizef;
|
||||
}
|
||||
|
||||
vhdl_expr *vhdl_const_int::to_vector(vhdl_type_name_t name, int w)
|
||||
|
|
|
|||
|
|
@ -157,10 +157,10 @@ int draw_stask_display(vhdl_procedural *proc, stmt_container *container,
|
|||
// function in VHDL
|
||||
|
||||
assert(i < count);
|
||||
ivl_expr_t net = ivl_stmt_parm(stmt, i++);
|
||||
assert(net);
|
||||
ivl_expr_t netp = ivl_stmt_parm(stmt, i++);
|
||||
assert(netp);
|
||||
|
||||
vhdl_expr *base = translate_expr(net);
|
||||
vhdl_expr *base = translate_expr(netp);
|
||||
if (NULL == base)
|
||||
return 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -698,11 +698,11 @@ static int draw_constant_drivers(ivl_scope_t scope, void *_parent)
|
|||
for (int i = 0; i < nsigs; i++) {
|
||||
ivl_signal_t sig = ivl_scope_sig(scope, i);
|
||||
|
||||
for (unsigned i = ivl_signal_array_base(sig);
|
||||
i < ivl_signal_array_count(sig);
|
||||
i++) {
|
||||
for (unsigned j = ivl_signal_array_base(sig);
|
||||
j < ivl_signal_array_count(sig);
|
||||
j++) {
|
||||
// Make sure the nexus code is generated
|
||||
ivl_nexus_t nex = ivl_signal_nex(sig, i);
|
||||
ivl_nexus_t nex = ivl_signal_nex(sig, j);
|
||||
seen_nexus(nex);
|
||||
|
||||
nexus_private_t *priv =
|
||||
|
|
@ -712,7 +712,7 @@ static int draw_constant_drivers(ivl_scope_t scope, void *_parent)
|
|||
vhdl_scope *arch_scope = ent->get_arch()->get_scope();
|
||||
|
||||
if (priv->const_driver) {
|
||||
assert(i == 0); // TODO: Make work for more words
|
||||
assert(j == 0); // TODO: Make work for more words
|
||||
|
||||
vhdl_var_ref *ref = nexus_to_var_ref(arch_scope, nex);
|
||||
|
||||
|
|
|
|||
133
tgt-vhdl/stmt.cc
133
tgt-vhdl/stmt.cc
|
|
@ -424,8 +424,8 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
|
|||
ivl_event_t event = ivl_stmt_events(stmt, i);
|
||||
|
||||
int nany = ivl_event_nany(event);
|
||||
for (int i = 0; i < nany; i++) {
|
||||
ivl_nexus_t nexus = ivl_event_any(event, i);
|
||||
for (int j = 0; j < nany; j++) {
|
||||
ivl_nexus_t nexus = ivl_event_any(event, j);
|
||||
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
||||
|
||||
wait->add_sensitivity(ref->get_name());
|
||||
|
|
@ -441,8 +441,8 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
|
|||
ivl_event_t event = ivl_stmt_events(stmt, i);
|
||||
|
||||
int nany = ivl_event_nany(event);
|
||||
for (int i = 0; i < nany; i++) {
|
||||
ivl_nexus_t nexus = ivl_event_any(event, i);
|
||||
for (int j = 0; j < nany; j++) {
|
||||
ivl_nexus_t nexus = ivl_event_any(event, j);
|
||||
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
||||
|
||||
ref->set_name(ref->get_name() + "'Event");
|
||||
|
|
@ -450,8 +450,8 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
|
|||
}
|
||||
|
||||
int nneg = ivl_event_nneg(event);
|
||||
for (int i = 0; i < nneg; i++) {
|
||||
ivl_nexus_t nexus = ivl_event_neg(event, i);
|
||||
for (int j = 0; j < nneg; j++) {
|
||||
ivl_nexus_t nexus = ivl_event_neg(event, j);
|
||||
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
||||
vhdl_fcall *detect =
|
||||
new vhdl_fcall("falling_edge", vhdl_type::boolean());
|
||||
|
|
@ -461,8 +461,8 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
|
|||
}
|
||||
|
||||
int npos = ivl_event_npos(event);
|
||||
for (int i = 0; i < npos; i++) {
|
||||
ivl_nexus_t nexus = ivl_event_pos(event, i);
|
||||
for (int j = 0; j < npos; j++) {
|
||||
ivl_nexus_t nexus = ivl_event_pos(event, j);
|
||||
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
|
||||
vhdl_fcall *detect =
|
||||
new vhdl_fcall("rising_edge", vhdl_type::boolean());
|
||||
|
|
@ -501,12 +501,12 @@ static int draw_if(vhdl_procedural *proc, stmt_container *container,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int draw_case(vhdl_procedural *proc, stmt_container *container,
|
||||
ivl_statement_t stmt, bool is_last)
|
||||
static vhdl_var_ref *draw_case_test(vhdl_procedural *proc, stmt_container *container,
|
||||
ivl_statement_t stmt)
|
||||
{
|
||||
vhdl_expr *test = translate_expr(ivl_stmt_cond_expr(stmt));
|
||||
if (NULL == test)
|
||||
return 1;
|
||||
return NULL;
|
||||
|
||||
// VHDL case expressions are required to be quite simple: variable
|
||||
// references or slices. So we may need to create a temporary
|
||||
|
|
@ -523,8 +523,18 @@ static int draw_case(vhdl_procedural *proc, stmt_container *container,
|
|||
vhdl_var_ref *tmp_ref = new vhdl_var_ref(tmp_name, NULL);
|
||||
container->add_stmt(new vhdl_assign_stmt(tmp_ref, test));
|
||||
|
||||
test = new vhdl_var_ref(tmp_name, test_type);
|
||||
return new vhdl_var_ref(tmp_name, test_type);
|
||||
}
|
||||
else
|
||||
return dynamic_cast<vhdl_var_ref*>(test);
|
||||
}
|
||||
|
||||
static int draw_case(vhdl_procedural *proc, stmt_container *container,
|
||||
ivl_statement_t stmt, bool is_last)
|
||||
{
|
||||
vhdl_var_ref *test = draw_case_test(proc, container, stmt);
|
||||
if (NULL == test)
|
||||
return 1;
|
||||
|
||||
vhdl_case_stmt *vhdlcase = new vhdl_case_stmt(test);
|
||||
container->add_stmt(vhdlcase);
|
||||
|
|
@ -565,6 +575,100 @@ static int draw_case(vhdl_procedural *proc, stmt_container *container,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* A casex statement cannot be directly translated to a VHDL case
|
||||
* statement as VHDL does not treat the don't-care bit as special.
|
||||
* The solution here is to generate an if statement from the casex
|
||||
* which compares only the non-don't-care bit positions.
|
||||
*/
|
||||
int draw_casezx(vhdl_procedural *proc, stmt_container *container,
|
||||
ivl_statement_t stmt, bool is_last)
|
||||
{
|
||||
vhdl_var_ref *test = draw_case_test(proc, container, stmt);
|
||||
if (NULL == test)
|
||||
return 1;
|
||||
|
||||
vhdl_if_stmt *result = NULL;
|
||||
|
||||
int nbranches = ivl_stmt_case_count(stmt);
|
||||
for (int i = 0; i < nbranches; i++) {
|
||||
stmt_container *where = NULL;
|
||||
|
||||
ivl_expr_t net = ivl_stmt_case_expr(stmt, i);
|
||||
if (net) {
|
||||
// The net must be a constant value otherwise we can't
|
||||
// generate the terms for the comparison expression
|
||||
if (ivl_expr_type(net) != IVL_EX_NUMBER) {
|
||||
error("Sorry, only casex statements with constant labels can "
|
||||
"be translated to VHDL");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *bits = ivl_expr_bits(net);
|
||||
|
||||
vhdl_binop_expr *all =
|
||||
new vhdl_binop_expr(VHDL_BINOP_AND, vhdl_type::boolean());
|
||||
for (unsigned i = 0; i < ivl_expr_width(net); i++) {
|
||||
switch (bits[i]) {
|
||||
case '?':
|
||||
case 'z':
|
||||
case 'x':
|
||||
// Ignore it
|
||||
break;
|
||||
default:
|
||||
{
|
||||
// Generate a comparison for this bit position
|
||||
vhdl_binop_expr *cmp =
|
||||
new vhdl_binop_expr(VHDL_BINOP_EQ, vhdl_type::boolean());
|
||||
|
||||
vhdl_type *type = vhdl_type::nunsigned(ivl_expr_width(net));
|
||||
vhdl_var_ref *lhs =
|
||||
new vhdl_var_ref(test->get_name().c_str(), type);
|
||||
lhs->set_slice(new vhdl_const_int(i));
|
||||
|
||||
cmp->add_expr(lhs);
|
||||
cmp->add_expr(new vhdl_const_bit(bits[i]));
|
||||
|
||||
all->add_expr(cmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
where = result->add_elsif(all);
|
||||
else {
|
||||
result = new vhdl_if_stmt(all);
|
||||
where = result->get_then_container();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// This the default case and therefore the `else' branch
|
||||
assert(result);
|
||||
where = result->get_else_container();
|
||||
}
|
||||
|
||||
// `where' now points to a branch of an if statement which
|
||||
// corresponds to this casex/z branch
|
||||
assert(where);
|
||||
draw_stmt(proc, where, ivl_stmt_case_stmt(stmt, i), is_last);
|
||||
}
|
||||
|
||||
// Add a comment to say that this corresponds to a casex/z statement
|
||||
// as this may not be obvious
|
||||
ostringstream ss;
|
||||
ss << "Generated from case"
|
||||
<< (ivl_statement_type(stmt) == IVL_ST_CASEX ? 'x' : 'z')
|
||||
<< " statement at " << ivl_stmt_file(stmt) << ":" << ivl_stmt_lineno(stmt);
|
||||
result->set_comment(ss.str());
|
||||
|
||||
container->add_stmt(result);
|
||||
|
||||
// We don't actually use the generated `test' expression
|
||||
delete test;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int draw_while(vhdl_procedural *proc, stmt_container *container,
|
||||
ivl_statement_t stmt)
|
||||
{
|
||||
|
|
@ -685,11 +789,8 @@ int draw_stmt(vhdl_procedural *proc, stmt_container *container,
|
|||
error("disable statement cannot be translated to VHDL");
|
||||
return 1;
|
||||
case IVL_ST_CASEX:
|
||||
error("casex statement cannot be translated to VHDL");
|
||||
return 1;
|
||||
case IVL_ST_CASEZ:
|
||||
error("casez statement cannot be translated to VHDL");
|
||||
return 1;
|
||||
return draw_casezx(proc, container, stmt, is_last);
|
||||
case IVL_ST_FORK:
|
||||
error("fork statement cannot be translated to VHDL");
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -664,12 +664,30 @@ vhdl_if_stmt::~vhdl_if_stmt()
|
|||
delete test_;
|
||||
}
|
||||
|
||||
stmt_container *vhdl_if_stmt::add_elsif(vhdl_expr *test)
|
||||
{
|
||||
elsif ef = { test, new stmt_container };
|
||||
elsif_parts_.push_back(ef);
|
||||
return ef.container;
|
||||
}
|
||||
|
||||
void vhdl_if_stmt::emit(std::ostream &of, int level) const
|
||||
{
|
||||
emit_comment(of, level);
|
||||
|
||||
of << "if ";
|
||||
test_->emit(of, level);
|
||||
of << " then";
|
||||
then_part_.emit(of, level);
|
||||
|
||||
std::list<elsif>::const_iterator it;
|
||||
for (it = elsif_parts_.begin(); it != elsif_parts_.end(); ++it) {
|
||||
of << "elsif ";
|
||||
(*it).test->emit(of, level);
|
||||
of << " then";
|
||||
(*it).container->emit(of, level);
|
||||
}
|
||||
|
||||
if (!else_part_.empty()) {
|
||||
of << "else";
|
||||
else_part_.emit(of, level);
|
||||
|
|
|
|||
|
|
@ -427,10 +427,17 @@ public:
|
|||
|
||||
stmt_container *get_then_container() { return &then_part_; }
|
||||
stmt_container *get_else_container() { return &else_part_; }
|
||||
stmt_container *add_elsif(vhdl_expr *test);
|
||||
void emit(std::ostream &of, int level) const;
|
||||
private:
|
||||
struct elsif {
|
||||
vhdl_expr *test;
|
||||
stmt_container *container;
|
||||
};
|
||||
|
||||
vhdl_expr *test_;
|
||||
stmt_container then_part_, else_part_;
|
||||
std::list<elsif> elsif_parts_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -354,23 +354,17 @@ static int draw_signal_real_real(ivl_expr_t exp)
|
|||
{
|
||||
ivl_signal_t sig = ivl_expr_signal(exp);
|
||||
int res = allocate_word();
|
||||
unsigned long word = 0;
|
||||
|
||||
if (ivl_signal_dimensions(sig) > 0) {
|
||||
ivl_expr_t ix = ivl_expr_oper1(exp);
|
||||
if (!number_is_immediate(ix, IMM_WID, 0)) {
|
||||
/* XXXX Need to generate a %load/ar instruction. */
|
||||
assert(0);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* The index is constant, so we can return to direct
|
||||
readout with the specific word selected. */
|
||||
word = get_number_immediate(ix);
|
||||
if (ivl_signal_dimensions(sig) == 0) {
|
||||
fprintf(vvp_out, " %%load/wr %d, v%p_0;\n", res, sig);
|
||||
return res;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%load/wr %d, v%p_%lu;\n", res, sig, word);
|
||||
|
||||
ivl_expr_t word_ex = ivl_expr_oper1(exp);
|
||||
int word_ix = allocate_word();
|
||||
draw_eval_expr_into_integer(word_ex, word_ix);
|
||||
fprintf(vvp_out, " %%load/ar %d, v%p, %d;\n", res, sig, word_ix);
|
||||
clr_word(word_ix);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -497,16 +497,30 @@ static int show_stmt_assign_sig_real(ivl_statement_t net)
|
|||
ivl_signal_t var;
|
||||
|
||||
res = draw_eval_real(ivl_stmt_rval(net));
|
||||
clr_word(res);
|
||||
|
||||
assert(ivl_stmt_lvals(net) == 1);
|
||||
lval = ivl_stmt_lval(net, 0);
|
||||
var = ivl_lval_sig(lval);
|
||||
assert(var != 0);
|
||||
|
||||
assert(ivl_signal_dimensions(var) == 0);
|
||||
if (ivl_signal_dimensions(var) == 0) {
|
||||
clr_word(res);
|
||||
fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", var, res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", var, res);
|
||||
// For now, only support 1-dimensional arrays.
|
||||
assert(ivl_signal_dimensions(var) == 1);
|
||||
|
||||
// Calculate the word index into an index register
|
||||
ivl_expr_t word_ex = ivl_lval_idx(lval);
|
||||
int word_ix = allocate_word();
|
||||
draw_eval_expr_into_integer(word_ex, word_ix);
|
||||
// Generate an assignment to write to the array.
|
||||
fprintf(vvp_out, " %%set/ar v%p, %d, %d;\n", var, word_ix, res);
|
||||
|
||||
clr_word(res);
|
||||
clr_word(word_ix);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
case vpiTimeVar:
|
||||
case vpiReg: type = "reg"; }
|
||||
|
||||
if (skip) break;
|
||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||
|
||||
name = vpi_get_str(vpiName, item);
|
||||
nexus_id = vpi_get(_vpiNexusId, item);
|
||||
|
|
@ -593,7 +593,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
case vpiRealVar:
|
||||
|
||||
if (skip) break;
|
||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||
|
||||
name = vpi_get_str(vpiName, item);
|
||||
{ char*tmp = create_full_name(name);
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
case vpiTimeVar:
|
||||
case vpiReg: type = "reg"; }
|
||||
|
||||
if (skip) break;
|
||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||
|
||||
name = vpi_get_str(vpiName, item);
|
||||
nexus_id = vpi_get(_vpiNexusId, item);
|
||||
|
|
@ -603,7 +603,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
case vpiRealVar:
|
||||
|
||||
if (skip) break;
|
||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||
|
||||
name = vpi_get_str(vpiName, item);
|
||||
{ char*tmp = create_full_name(name);
|
||||
|
|
|
|||
|
|
@ -513,7 +513,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
break;
|
||||
}
|
||||
|
||||
if (skip) break;
|
||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||
|
||||
name = vpi_get_str(vpiName, item);
|
||||
prefix = is_escaped_id(name) ? "\\" : "";
|
||||
|
|
@ -578,7 +578,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
break;
|
||||
}
|
||||
|
||||
if (skip) break;
|
||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||
|
||||
/* Declare the variable in the VCD file. */
|
||||
name = vpi_get_str(vpiName, item);
|
||||
|
|
|
|||
|
|
@ -348,6 +348,7 @@ typedef struct t_vpi_delay {
|
|||
# define vpiSysFuncReal vpiRealFunc
|
||||
# define vpiSysFuncTime vpiTimeFunc
|
||||
# define vpiSysFuncSized vpiSizedFunc
|
||||
#define vpiAutomatic 50
|
||||
#define vpiConstantSelect 53
|
||||
#define vpiSigned 65
|
||||
/* IVL private properties */
|
||||
|
|
|
|||
180
vvp/arith.cc
180
vvp/arith.cc
|
|
@ -63,7 +63,8 @@ vvp_arith_abs::~vvp_arith_abs()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_abs::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_abs::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
vvp_vector4_t out (bit.size(), BIT4_0);;
|
||||
|
||||
|
|
@ -81,13 +82,14 @@ void vvp_arith_abs::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
break;
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, out);
|
||||
vvp_send_vec4(ptr.ptr()->out, out, 0);
|
||||
}
|
||||
|
||||
void vvp_arith_abs::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_abs::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
double out = fabs(bit);
|
||||
vvp_send_real(ptr.ptr()->out, out);
|
||||
vvp_send_real(ptr.ptr()->out, out, 0);
|
||||
}
|
||||
|
||||
vvp_arith_cast_int::vvp_arith_cast_int(unsigned wid)
|
||||
|
|
@ -99,9 +101,10 @@ vvp_arith_cast_int::~vvp_arith_cast_int()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_cast_int::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_cast_int::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
vvp_send_vec4(ptr.ptr()->out, vvp_vector4_t(wid_, bit));
|
||||
vvp_send_vec4(ptr.ptr()->out, vvp_vector4_t(wid_, bit), 0);
|
||||
}
|
||||
|
||||
vvp_arith_cast_real::vvp_arith_cast_real(bool signed_flag)
|
||||
|
|
@ -113,11 +116,12 @@ vvp_arith_cast_real::~vvp_arith_cast_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_cast_real::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_cast_real::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
double val;
|
||||
vector4_to_value(bit, val, signed_);
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
// Division
|
||||
|
|
@ -135,21 +139,22 @@ void vvp_arith_div::wide4_(vvp_net_ptr_t ptr)
|
|||
{
|
||||
vvp_vector2_t a2 (op_a_);
|
||||
if (a2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t b2 (op_b_);
|
||||
if (b2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t res2 = a2 / b2;
|
||||
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res2, wid_));
|
||||
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res2, wid_), 0);
|
||||
}
|
||||
|
||||
void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -160,13 +165,13 @@ void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
unsigned long a;
|
||||
if (! vector4_to_value(op_a_, a)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long b;
|
||||
if (! vector4_to_value(op_b_, b)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +207,7 @@ void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
val >>= 1;
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, vval);
|
||||
vvp_send_vec4(ptr.ptr()->out, vval, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -219,21 +224,22 @@ void vvp_arith_mod::wide_(vvp_net_ptr_t ptr)
|
|||
{
|
||||
vvp_vector2_t a2 (op_a_);
|
||||
if (a2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t b2 (op_b_);
|
||||
if (b2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t res = a2 % b2;
|
||||
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res, res.size()));
|
||||
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res, res.size()), 0);
|
||||
}
|
||||
|
||||
void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -244,13 +250,13 @@ void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
unsigned long a;
|
||||
if (! vector4_to_value(op_a_, a)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long b;
|
||||
if (! vector4_to_value(op_b_, b)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +281,7 @@ void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1)
|
||||
xval.set_bit(idx, BIT4_X);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, xval);
|
||||
vvp_send_vec4(ptr.ptr()->out, xval, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -295,7 +301,7 @@ void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
val >>= 1;
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, vval);
|
||||
vvp_send_vec4(ptr.ptr()->out, vval, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -316,17 +322,18 @@ void vvp_arith_mult::wide_(vvp_net_ptr_t ptr)
|
|||
vvp_vector2_t b2 (op_b_);
|
||||
|
||||
if (a2.is_NaN() || b2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t result = a2 * b2;
|
||||
|
||||
vvp_vector4_t res4 = vector2_to_vector4(result, wid_);
|
||||
vvp_send_vec4(ptr.ptr()->out, res4);
|
||||
vvp_send_vec4(ptr.ptr()->out, res4, 0);
|
||||
}
|
||||
|
||||
void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -337,13 +344,13 @@ void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
long a;
|
||||
if (! vector4_to_value(op_a_, a, false, true)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
long b;
|
||||
if (! vector4_to_value(op_b_, b, false, true)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -360,7 +367,7 @@ void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
val >>= 1;
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, vval);
|
||||
vvp_send_vec4(ptr.ptr()->out, vval, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -375,14 +382,15 @@ vvp_arith_pow::~vvp_arith_pow()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
vvp_vector4_t res4;
|
||||
if (signed_flag_) {
|
||||
if (op_a_.has_xz() || op_b_.has_xz()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -396,7 +404,7 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
vvp_vector2_t b2 (op_b_);
|
||||
|
||||
if (a2.is_NaN() || b2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -404,7 +412,7 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
res4 = vector2_to_vector4(result, wid_);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res4);
|
||||
vvp_send_vec4(ptr.ptr()->out, res4, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -419,7 +427,8 @@ vvp_arith_sum::~vvp_arith_sum()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_sum::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_sum::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -438,14 +447,14 @@ void vvp_arith_sum::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
vvp_bit4_t cur = add_with_carry(a, b, carry);
|
||||
|
||||
if (cur == BIT4_X) {
|
||||
vvp_send_vec4(net->out, x_val_);
|
||||
vvp_send_vec4(net->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
value.set_bit(idx, cur);
|
||||
}
|
||||
|
||||
vvp_send_vec4(net->out, value);
|
||||
vvp_send_vec4(net->out, value, 0);
|
||||
}
|
||||
|
||||
vvp_arith_sub::vvp_arith_sub(unsigned wid)
|
||||
|
|
@ -463,7 +472,8 @@ vvp_arith_sub::~vvp_arith_sub()
|
|||
* further reduce the operation to adding in the inverted value and
|
||||
* adding a correction.
|
||||
*/
|
||||
void vvp_arith_sub::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_sub::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -482,14 +492,14 @@ void vvp_arith_sub::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
vvp_bit4_t cur = add_with_carry(a, b, carry);
|
||||
|
||||
if (cur == BIT4_X) {
|
||||
vvp_send_vec4(net->out, x_val_);
|
||||
vvp_send_vec4(net->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
value.set_bit(idx, cur);
|
||||
}
|
||||
|
||||
vvp_send_vec4(net->out, value);
|
||||
vvp_send_vec4(net->out, value, 0);
|
||||
}
|
||||
|
||||
vvp_cmp_eeq::vvp_cmp_eeq(unsigned wid)
|
||||
|
|
@ -497,7 +507,8 @@ vvp_cmp_eeq::vvp_cmp_eeq(unsigned wid)
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_eeq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_cmp_eeq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -513,7 +524,7 @@ void vvp_cmp_eeq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_send_vec4(net->out, eeq);
|
||||
vvp_send_vec4(net->out, eeq, 0);
|
||||
}
|
||||
|
||||
vvp_cmp_nee::vvp_cmp_nee(unsigned wid)
|
||||
|
|
@ -521,7 +532,8 @@ vvp_cmp_nee::vvp_cmp_nee(unsigned wid)
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_nee::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_cmp_nee::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -537,7 +549,7 @@ void vvp_cmp_nee::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_send_vec4(net->out, eeq);
|
||||
vvp_send_vec4(net->out, eeq, 0);
|
||||
}
|
||||
|
||||
vvp_cmp_eq::vvp_cmp_eq(unsigned wid)
|
||||
|
|
@ -551,7 +563,8 @@ vvp_cmp_eq::vvp_cmp_eq(unsigned wid)
|
|||
* there are X/Z bits anywhere in A or B, the result is X. Finally,
|
||||
* the result is 1.
|
||||
*/
|
||||
void vvp_cmp_eq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_cmp_eq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -583,7 +596,7 @@ void vvp_cmp_eq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
}
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_send_vec4(net->out, res);
|
||||
vvp_send_vec4(net->out, res, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -598,7 +611,8 @@ vvp_cmp_ne::vvp_cmp_ne(unsigned wid)
|
|||
* there are X/Z bits anywhere in A or B, the result is X. Finally,
|
||||
* the result is 0.
|
||||
*/
|
||||
void vvp_cmp_ne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_cmp_ne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -630,7 +644,7 @@ void vvp_cmp_ne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
}
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_send_vec4(net->out, res);
|
||||
vvp_send_vec4(net->out, res, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -651,7 +665,7 @@ void vvp_cmp_gtge_base_::recv_vec4_base_(vvp_net_ptr_t ptr,
|
|||
: compare_gtge(op_a_, op_b_, out_if_equal);
|
||||
vvp_vector4_t val (1);
|
||||
val.set_bit(0, out);
|
||||
vvp_send_vec4(ptr.ptr()->out, val);
|
||||
vvp_send_vec4(ptr.ptr()->out, val, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -662,7 +676,8 @@ vvp_cmp_ge::vvp_cmp_ge(unsigned wid, bool flag)
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_ge::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_cmp_ge::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
recv_vec4_base_(ptr, bit, BIT4_1);
|
||||
}
|
||||
|
|
@ -672,7 +687,8 @@ vvp_cmp_gt::vvp_cmp_gt(unsigned wid, bool flag)
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_gt::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_cmp_gt::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
recv_vec4_base_(ptr, bit, BIT4_0);
|
||||
}
|
||||
|
|
@ -687,7 +703,8 @@ vvp_shiftl::~vvp_shiftl()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -695,7 +712,7 @@ void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
unsigned long shift;
|
||||
if (! vector4_to_value(op_b_, shift)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -708,7 +725,7 @@ void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
for (unsigned idx = shift ; idx < out.size() ; idx += 1)
|
||||
out.set_bit(idx, op_a_.value(idx-shift));
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, out);
|
||||
vvp_send_vec4(ptr.ptr()->out, out, 0);
|
||||
}
|
||||
|
||||
vvp_shiftr::vvp_shiftr(unsigned wid, bool signed_flag)
|
||||
|
|
@ -720,7 +737,8 @@ vvp_shiftr::~vvp_shiftr()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -728,7 +746,7 @@ void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
unsigned long shift;
|
||||
if (! vector4_to_value(op_b_, shift)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -745,7 +763,7 @@ void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
for (unsigned idx = 0 ; idx < shift ; idx += 1)
|
||||
out.set_bit(idx+out.size()-shift, pad);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, out);
|
||||
vvp_send_vec4(ptr.ptr()->out, out, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -780,12 +798,13 @@ vvp_arith_mult_real::~vvp_arith_mult_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_mult_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_mult_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = op_a_ * op_b_;
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
/* Real power. */
|
||||
|
|
@ -797,12 +816,13 @@ vvp_arith_pow_real::~vvp_arith_pow_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_pow_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_pow_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = pow(op_a_, op_b_);
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
/* Real division. */
|
||||
|
|
@ -814,12 +834,13 @@ vvp_arith_div_real::~vvp_arith_div_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_div_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_div_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = op_a_ / op_b_;
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
/* Real modulus. */
|
||||
|
|
@ -831,12 +852,13 @@ vvp_arith_mod_real::~vvp_arith_mod_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_mod_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_mod_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = fmod(op_a_, op_b_);
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
/* Real summation. */
|
||||
|
|
@ -848,12 +870,13 @@ vvp_arith_sum_real::~vvp_arith_sum_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_sum_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_sum_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = op_a_ + op_b_;
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
/* Real subtraction. */
|
||||
|
|
@ -865,12 +888,13 @@ vvp_arith_sub_real::~vvp_arith_sub_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_sub_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_sub_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = op_a_ - op_b_;
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
/* Real compare equal. */
|
||||
|
|
@ -878,7 +902,8 @@ vvp_cmp_eq_real::vvp_cmp_eq_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_eq_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
||||
void vvp_cmp_eq_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -886,7 +911,7 @@ void vvp_cmp_eq_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
|||
if (op_a_ == op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res);
|
||||
vvp_send_vec4(ptr.ptr()->out, res, 0);
|
||||
}
|
||||
|
||||
/* Real compare not equal. */
|
||||
|
|
@ -894,7 +919,8 @@ vvp_cmp_ne_real::vvp_cmp_ne_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_ne_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
||||
void vvp_cmp_ne_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -902,7 +928,7 @@ void vvp_cmp_ne_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
|||
if (op_a_ != op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res);
|
||||
vvp_send_vec4(ptr.ptr()->out, res, 0);
|
||||
}
|
||||
|
||||
/* Real compare greater than or equal. */
|
||||
|
|
@ -910,7 +936,8 @@ vvp_cmp_ge_real::vvp_cmp_ge_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_ge_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
||||
void vvp_cmp_ge_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -918,7 +945,7 @@ void vvp_cmp_ge_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
|||
if (op_a_ >= op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res);
|
||||
vvp_send_vec4(ptr.ptr()->out, res, 0);
|
||||
}
|
||||
|
||||
/* Real compare greater than. */
|
||||
|
|
@ -926,7 +953,8 @@ vvp_cmp_gt_real::vvp_cmp_gt_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_gt_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
||||
void vvp_cmp_gt_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -934,5 +962,5 @@ void vvp_cmp_gt_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
|||
if (op_a_ > op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res);
|
||||
vvp_send_vec4(ptr.ptr()->out, res, 0);
|
||||
}
|
||||
|
|
|
|||
84
vvp/arith.h
84
vvp/arith.h
|
|
@ -54,8 +54,10 @@ class vvp_arith_abs : public vvp_net_fun_t {
|
|||
explicit vvp_arith_abs();
|
||||
~vvp_arith_abs();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
@ -65,7 +67,8 @@ class vvp_arith_cast_int : public vvp_net_fun_t {
|
|||
explicit vvp_arith_cast_int(unsigned wid);
|
||||
~vvp_arith_cast_int();
|
||||
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
unsigned wid_;
|
||||
|
|
@ -76,7 +79,8 @@ class vvp_arith_cast_real : public vvp_net_fun_t {
|
|||
explicit vvp_arith_cast_real(bool signed_flag);
|
||||
~vvp_arith_cast_real();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
bool signed_;
|
||||
|
|
@ -87,7 +91,8 @@ class vvp_arith_div : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_arith_div(unsigned wid, bool signed_flag);
|
||||
~vvp_arith_div();
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
private:
|
||||
void wide4_(vvp_net_ptr_t ptr);
|
||||
bool signed_flag_;
|
||||
|
|
@ -98,7 +103,8 @@ class vvp_arith_mod : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_arith_mod(unsigned wid, bool signed_flag);
|
||||
~vvp_arith_mod();
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
private:
|
||||
void wide_(vvp_net_ptr_t ptr);
|
||||
bool signed_flag_;
|
||||
|
|
@ -114,7 +120,8 @@ class vvp_cmp_eeq : public vvp_arith_ {
|
|||
|
||||
public:
|
||||
explicit vvp_cmp_eeq(unsigned wid);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -122,7 +129,8 @@ class vvp_cmp_nee : public vvp_arith_ {
|
|||
|
||||
public:
|
||||
explicit vvp_cmp_nee(unsigned wid);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -130,7 +138,8 @@ class vvp_cmp_eq : public vvp_arith_ {
|
|||
|
||||
public:
|
||||
explicit vvp_cmp_eq(unsigned wid);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -138,7 +147,8 @@ class vvp_cmp_ne : public vvp_arith_ {
|
|||
|
||||
public:
|
||||
explicit vvp_cmp_ne(unsigned wid);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -165,7 +175,8 @@ class vvp_cmp_ge : public vvp_cmp_gtge_base_ {
|
|||
public:
|
||||
explicit vvp_cmp_ge(unsigned wid, bool signed_flag);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -174,7 +185,8 @@ class vvp_cmp_gt : public vvp_cmp_gtge_base_ {
|
|||
public:
|
||||
explicit vvp_cmp_gt(unsigned wid, bool signed_flag);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -187,7 +199,8 @@ class vvp_arith_mult : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_arith_mult(unsigned wid);
|
||||
~vvp_arith_mult();
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
private:
|
||||
void wide_(vvp_net_ptr_t ptr);
|
||||
};
|
||||
|
|
@ -197,7 +210,8 @@ class vvp_arith_pow : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_arith_pow(unsigned wid, bool signed_flag);
|
||||
~vvp_arith_pow();
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
private:
|
||||
bool signed_flag_;
|
||||
};
|
||||
|
|
@ -207,7 +221,8 @@ class vvp_arith_sub : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_arith_sub(unsigned wid);
|
||||
~vvp_arith_sub();
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -216,7 +231,8 @@ class vvp_arith_sum : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_arith_sum(unsigned wid);
|
||||
~vvp_arith_sum();
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -225,7 +241,8 @@ class vvp_shiftl : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_shiftl(unsigned wid);
|
||||
~vvp_shiftl();
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_shiftr : public vvp_arith_ {
|
||||
|
|
@ -233,7 +250,8 @@ class vvp_shiftr : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_shiftr(unsigned wid, bool signed_flag);
|
||||
~vvp_shiftr();
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
bool signed_flag_;
|
||||
|
|
@ -263,7 +281,8 @@ class vvp_arith_sum_real : public vvp_arith_real_ {
|
|||
public:
|
||||
explicit vvp_arith_sum_real();
|
||||
~vvp_arith_sum_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_arith_div_real : public vvp_arith_real_ {
|
||||
|
|
@ -271,7 +290,8 @@ class vvp_arith_div_real : public vvp_arith_real_ {
|
|||
public:
|
||||
explicit vvp_arith_div_real();
|
||||
~vvp_arith_div_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_arith_mod_real : public vvp_arith_real_ {
|
||||
|
|
@ -279,7 +299,8 @@ class vvp_arith_mod_real : public vvp_arith_real_ {
|
|||
public:
|
||||
explicit vvp_arith_mod_real();
|
||||
~vvp_arith_mod_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_arith_mult_real : public vvp_arith_real_ {
|
||||
|
|
@ -287,7 +308,8 @@ class vvp_arith_mult_real : public vvp_arith_real_ {
|
|||
public:
|
||||
explicit vvp_arith_mult_real();
|
||||
~vvp_arith_mult_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_arith_pow_real : public vvp_arith_real_ {
|
||||
|
|
@ -295,7 +317,8 @@ class vvp_arith_pow_real : public vvp_arith_real_ {
|
|||
public:
|
||||
explicit vvp_arith_pow_real();
|
||||
~vvp_arith_pow_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_arith_sub_real : public vvp_arith_real_ {
|
||||
|
|
@ -303,35 +326,40 @@ class vvp_arith_sub_real : public vvp_arith_real_ {
|
|||
public:
|
||||
explicit vvp_arith_sub_real();
|
||||
~vvp_arith_sub_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_cmp_eq_real : public vvp_arith_real_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_eq_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_cmp_ne_real : public vvp_arith_real_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_ne_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_cmp_ge_real : public vvp_arith_real_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_ge_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_cmp_gt_real : public vvp_arith_real_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_gt_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
280
vvp/array.cc
280
vvp/array.cc
|
|
@ -53,7 +53,28 @@ vvp_array_t array_find(const char*label)
|
|||
|
||||
/*
|
||||
* The vpiArray object holds an array of vpi objects that themselves
|
||||
* represent the words of the array. The vpi_array_t is a pointer to this.
|
||||
* represent the words of the array. The vpi_array_t is a pointer to
|
||||
* a struct __vpiArray.
|
||||
*
|
||||
* The details of the implementation depends on what this is an array
|
||||
* of. The easiest case is if this is an array of nets.
|
||||
*
|
||||
* - Array of Nets:
|
||||
* If this represents an array of nets, then the nets member points to
|
||||
* an array of vpiHandle objects. Each vpiHandle is a word. This is
|
||||
* done because typically each word of a net array is simultaneously
|
||||
* driven and accessed by other means, so there is no advantage to
|
||||
* compacting the array in any other way.
|
||||
*
|
||||
* - Array of vector4 words.
|
||||
* In this case, the nets pointer is nil, and the vals4 member points
|
||||
* to a vvl_vector4array_t object that is a compact representation of
|
||||
* an array of vvp_vector4_t vectors.
|
||||
*
|
||||
* - Array of real variables
|
||||
* The valsr member points to a vvp_realarray_t objects that has an
|
||||
* array of double variables. This is very much line the way the
|
||||
* vector4 array works.
|
||||
*/
|
||||
struct __vpiArray {
|
||||
__vpiArray() { }
|
||||
|
|
@ -70,7 +91,8 @@ struct __vpiArray {
|
|||
// If this is a net array, nets lists the handles.
|
||||
vpiHandle*nets;
|
||||
// If this is a var array, then these are used instead of nets.
|
||||
vvp_vector4array_t *vals;
|
||||
vvp_vector4array_t *vals4;
|
||||
vvp_realarray_t *valsr;
|
||||
struct __vpiArrayWord*vals_words;
|
||||
|
||||
class vvp_fun_arrayport*ports_;
|
||||
|
|
@ -127,7 +149,7 @@ struct __vpiArrayVthrA {
|
|||
/* Get the array word size. This has only been checked for reg arrays. */
|
||||
unsigned get_array_word_size(vvp_array_t array)
|
||||
{
|
||||
assert(array->vals);
|
||||
assert(array->vals4);
|
||||
return array->vals_width;
|
||||
}
|
||||
|
||||
|
|
@ -332,6 +354,9 @@ static int vpi_array_get(int code, vpiHandle ref)
|
|||
case vpiSize:
|
||||
return (int) obj->array_count;
|
||||
|
||||
case vpiAutomatic:
|
||||
return (int) obj->scope->is_automatic;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -421,7 +446,7 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
|
|||
|
||||
switch (code) {
|
||||
case vpiSize:
|
||||
return (int) parent->vals->width();
|
||||
return (int) parent->vals4->width();
|
||||
|
||||
case vpiLeftRange:
|
||||
return parent->msb.value;
|
||||
|
|
@ -458,9 +483,9 @@ static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value value)
|
|||
|
||||
assert(obj);
|
||||
unsigned index = decode_array_word_pointer(obj, parent);
|
||||
unsigned width = parent->vals->width();
|
||||
unsigned width = parent->vals4->width();
|
||||
|
||||
vpip_vec4_get_value(parent->vals->get_word(index), width,
|
||||
vpip_vec4_get_value(parent->vals4->get_word(index), width,
|
||||
parent->signed_flag, value);
|
||||
}
|
||||
|
||||
|
|
@ -536,7 +561,7 @@ static vpiHandle array_iterator_scan(vpiHandle ref, int)
|
|||
if (obj->array->nets)
|
||||
return obj->array->nets[obj->next];
|
||||
|
||||
assert(obj->array->vals);
|
||||
assert(obj->array->vals4);
|
||||
|
||||
if (obj->array->vals_words == 0)
|
||||
array_make_vals_words(obj->array);
|
||||
|
|
@ -699,10 +724,10 @@ void array_set_word(vvp_array_t arr,
|
|||
if (address >= arr->array_count)
|
||||
return;
|
||||
|
||||
if (arr->vals) {
|
||||
if (arr->vals4) {
|
||||
assert(arr->nets == 0);
|
||||
if (part_off != 0 || val.size() != arr->vals_width) {
|
||||
vvp_vector4_t tmp = arr->vals->get_word(address);
|
||||
vvp_vector4_t tmp = arr->vals4->get_word(address);
|
||||
if ((part_off + val.size()) > tmp.size()) {
|
||||
cerr << "part_off=" << part_off
|
||||
<< " val.size()=" << val.size()
|
||||
|
|
@ -711,9 +736,9 @@ void array_set_word(vvp_array_t arr,
|
|||
assert(0);
|
||||
}
|
||||
tmp.set_vec(part_off, val);
|
||||
arr->vals->set_word(address, tmp);
|
||||
arr->vals4->set_word(address, tmp);
|
||||
} else {
|
||||
arr->vals->set_word(address, val);
|
||||
arr->vals4->set_word(address, val);
|
||||
}
|
||||
array_word_change(arr, address);
|
||||
return;
|
||||
|
|
@ -727,19 +752,26 @@ void array_set_word(vvp_array_t arr,
|
|||
assert(vsig);
|
||||
|
||||
vvp_net_ptr_t ptr (vsig->node, 0);
|
||||
vvp_send_vec4_pv(ptr, val, part_off, val.size(), vpip_size(vsig));
|
||||
vvp_send_vec4_pv(ptr, val, part_off, val.size(), vpip_size(vsig), 0);
|
||||
array_word_change(arr, address);
|
||||
}
|
||||
|
||||
void array_set_word(vvp_array_t arr, unsigned address, double val)
|
||||
{
|
||||
assert(arr->valsr!= 0);
|
||||
assert(arr->nets == 0);
|
||||
|
||||
arr->valsr->set_word(address, val);
|
||||
}
|
||||
|
||||
vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
||||
{
|
||||
if (arr->vals) {
|
||||
if (arr->vals4) {
|
||||
assert(arr->nets == 0);
|
||||
|
||||
return arr->vals->get_word(address);
|
||||
return arr->vals4->get_word(address);
|
||||
}
|
||||
|
||||
assert(arr->vals == 0);
|
||||
assert(arr->vals4 == 0);
|
||||
assert(arr->nets != 0);
|
||||
|
||||
if (address >= arr->array_count) {
|
||||
|
|
@ -764,6 +796,26 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
|||
return val;
|
||||
}
|
||||
|
||||
double array_get_word_r(vvp_array_t arr, unsigned address)
|
||||
{
|
||||
if (arr->valsr) {
|
||||
assert(arr->vals4 == 0);
|
||||
assert(arr->nets == 0);
|
||||
return arr->valsr->get_word(address);
|
||||
}
|
||||
|
||||
assert(arr->nets);
|
||||
vpiHandle word = arr->nets[address];
|
||||
struct __vpiRealVar*vsig = vpip_realvar_from_handle(word);
|
||||
assert(vsig);
|
||||
vvp_fun_signal_real*sig = dynamic_cast<vvp_fun_signal_real*> (vsig->net->fun);
|
||||
assert(sig);
|
||||
|
||||
double val = sig->real_value();
|
||||
return val;
|
||||
|
||||
}
|
||||
|
||||
static vpiHandle vpip_make_array(char*label, const char*name,
|
||||
int first_addr, int last_addr,
|
||||
bool signed_flag)
|
||||
|
|
@ -789,7 +841,8 @@ static vpiHandle vpip_make_array(char*label, const char*name,
|
|||
|
||||
// Start off now knowing if we are nets or variables.
|
||||
obj->nets = 0;
|
||||
obj->vals = 0;
|
||||
obj->vals4 = 0;
|
||||
obj->valsr = 0;
|
||||
obj->vals_width = 0;
|
||||
vpip_make_dec_const(&obj->msb, 0);
|
||||
vpip_make_dec_const(&obj->lsb, 0);
|
||||
|
|
@ -839,6 +892,19 @@ void array_attach_word(vvp_array_t array, unsigned long addr, vpiHandle word)
|
|||
sig->is_netarray = 1;
|
||||
sig->within.parent = &array->base;
|
||||
sig->id.index = vpip_make_dec_const(addr + array->first_addr.value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (struct __vpiRealVar*sig = (struct __vpiRealVar*)word) {
|
||||
vvp_net_t*net = sig->net;
|
||||
assert(net);
|
||||
vvp_fun_signal_base*fun = dynamic_cast<vvp_fun_signal_base*>(net->fun);
|
||||
assert(fun);
|
||||
fun->attach_as_word(array, addr);
|
||||
sig->is_netarray = 1;
|
||||
sig->within.parent = &array->base;
|
||||
sig->id.index = vpip_make_dec_const(addr + array->first_addr.value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -852,9 +918,13 @@ void compile_var_array(char*label, char*name, int last, int first,
|
|||
|
||||
/* Make the words. */
|
||||
arr->vals_width = labs(msb-lsb) + 1;
|
||||
arr->vals = new vvp_vector4array_t(arr->vals_width, arr->array_count,
|
||||
vpip_peek_current_scope()->is_automatic);
|
||||
vpip_add_item_to_current_scope(arr->vals);
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
arr->vals4 = new vvp_vector4array_aa(arr->vals_width,
|
||||
arr->array_count);
|
||||
} else {
|
||||
arr->vals4 = new vvp_vector4array_sa(arr->vals_width,
|
||||
arr->array_count);
|
||||
}
|
||||
vpip_make_dec_const(&arr->msb, msb);
|
||||
vpip_make_dec_const(&arr->lsb, lsb);
|
||||
|
||||
|
|
@ -871,14 +941,16 @@ void compile_real_array(char*label, char*name, int last, int first,
|
|||
vpiHandle obj = vpip_make_array(label, name, first, last, true);
|
||||
|
||||
struct __vpiArray*arr = ARRAY_HANDLE(obj);
|
||||
vvp_array_t array = array_find(label);
|
||||
|
||||
/* Make the words. */
|
||||
for (unsigned idx = 0 ; idx < arr->array_count ; idx += 1) {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof buf, "%s_%u", label, idx);
|
||||
compile_varw_real(strdup(buf), array, idx, msb, lsb);
|
||||
}
|
||||
arr->valsr = new vvp_realarray_t(arr->array_count);
|
||||
arr->vals_width = 1;
|
||||
|
||||
/* Do these even make sense for real arrays? These are the
|
||||
part select of a vector, but the real value is not
|
||||
vectorable. */
|
||||
vpip_make_dec_const(&arr->msb, msb);
|
||||
vpip_make_dec_const(&arr->lsb, lsb);
|
||||
|
||||
count_real_arrays += 1;
|
||||
count_real_array_words += arr->array_count;
|
||||
|
|
@ -908,11 +980,9 @@ class vvp_fun_arrayport : public vvp_net_fun_t {
|
|||
explicit vvp_fun_arrayport(vvp_array_t mem, vvp_net_t*net, long addr);
|
||||
~vvp_fun_arrayport();
|
||||
|
||||
void check_word_change(unsigned long addr);
|
||||
virtual void check_word_change(unsigned long addr) = 0;
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
|
||||
private:
|
||||
protected:
|
||||
vvp_array_t arr_;
|
||||
vvp_net_t *net_;
|
||||
unsigned long addr_;
|
||||
|
|
@ -938,7 +1008,37 @@ vvp_fun_arrayport::~vvp_fun_arrayport()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_arrayport::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
class vvp_fun_arrayport_sa : public vvp_fun_arrayport {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_arrayport_sa(vvp_array_t mem, vvp_net_t*net);
|
||||
explicit vvp_fun_arrayport_sa(vvp_array_t mem, vvp_net_t*net, long addr);
|
||||
~vvp_fun_arrayport_sa();
|
||||
|
||||
void check_word_change(unsigned long addr);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
vvp_fun_arrayport_sa::vvp_fun_arrayport_sa(vvp_array_t mem, vvp_net_t*net)
|
||||
: vvp_fun_arrayport(mem, net)
|
||||
{
|
||||
}
|
||||
|
||||
vvp_fun_arrayport_sa::vvp_fun_arrayport_sa(vvp_array_t mem, vvp_net_t*net, long addr)
|
||||
: vvp_fun_arrayport(mem, net, addr)
|
||||
{
|
||||
}
|
||||
|
||||
vvp_fun_arrayport_sa::~vvp_fun_arrayport_sa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_arrayport_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
bool addr_valid_flag;
|
||||
|
||||
|
|
@ -948,7 +1048,7 @@ void vvp_fun_arrayport::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
addr_valid_flag = vector4_to_value(bit, addr_);
|
||||
if (! addr_valid_flag)
|
||||
addr_ = arr_->array_count;
|
||||
vvp_send_vec4(port.ptr()->out, array_get_word(arr_,addr_));
|
||||
vvp_send_vec4(port.ptr()->out, array_get_word(arr_,addr_), 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -957,13 +1057,111 @@ void vvp_fun_arrayport::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_fun_arrayport::check_word_change(unsigned long addr)
|
||||
void vvp_fun_arrayport_sa::check_word_change(unsigned long addr)
|
||||
{
|
||||
if (addr != addr_)
|
||||
return;
|
||||
|
||||
vvp_vector4_t bit = array_get_word(arr_, addr_);
|
||||
vvp_send_vec4(net_->out, bit);
|
||||
vvp_send_vec4(net_->out, bit, 0);
|
||||
}
|
||||
|
||||
class vvp_fun_arrayport_aa : public vvp_fun_arrayport, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_arrayport_aa(vvp_array_t mem, vvp_net_t*net);
|
||||
explicit vvp_fun_arrayport_aa(vvp_array_t mem, vvp_net_t*net, long addr);
|
||||
~vvp_fun_arrayport_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void check_word_change(unsigned long addr);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
struct __vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
vvp_fun_arrayport_aa::vvp_fun_arrayport_aa(vvp_array_t mem, vvp_net_t*net)
|
||||
: vvp_fun_arrayport(mem, net)
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
}
|
||||
|
||||
vvp_fun_arrayport_aa::vvp_fun_arrayport_aa(vvp_array_t mem, vvp_net_t*net, long addr)
|
||||
: vvp_fun_arrayport(mem, net, addr)
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
}
|
||||
|
||||
vvp_fun_arrayport_aa::~vvp_fun_arrayport_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_arrayport_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
unsigned long*addr = new unsigned long;
|
||||
vvp_set_context_item(context, context_idx_, addr);
|
||||
|
||||
*addr = addr_;
|
||||
}
|
||||
|
||||
void vvp_fun_arrayport_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
unsigned long*addr = static_cast<unsigned long*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
*addr = addr_;
|
||||
}
|
||||
|
||||
void vvp_fun_arrayport_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
unsigned long*addr = static_cast<unsigned long*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
bool addr_valid_flag;
|
||||
|
||||
switch (port.port()) {
|
||||
|
||||
case 0: // Address input
|
||||
addr_valid_flag = vector4_to_value(bit, *addr);
|
||||
if (! addr_valid_flag)
|
||||
*addr = arr_->array_count;
|
||||
vvp_send_vec4(port.ptr()->out, array_get_word(arr_,*addr),
|
||||
context);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stdout, "XXXX write ports not implemented.\n");
|
||||
assert(0);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_arrayport_aa::check_word_change(unsigned long addr)
|
||||
{
|
||||
unsigned long*port_addr = static_cast<unsigned long*>
|
||||
(vthread_get_wt_context_item(context_idx_));
|
||||
|
||||
if (addr != *port_addr)
|
||||
return;
|
||||
|
||||
vvp_vector4_t bit = array_get_word(arr_, addr);
|
||||
vvp_send_vec4(net_->out, bit, vthread_get_wt_context());
|
||||
}
|
||||
|
||||
static void array_attach_port(vvp_array_t array, vvp_fun_arrayport*fun)
|
||||
|
|
@ -1000,7 +1198,7 @@ void array_word_change(vvp_array_t array, unsigned long addr)
|
|||
|
||||
if (cur->cb_data.cb_rtn != 0) {
|
||||
if (cur->cb_data.value)
|
||||
vpip_vec4_get_value(array->vals->get_word(addr),
|
||||
vpip_vec4_get_value(array->vals4->get_word(addr),
|
||||
array->vals_width,
|
||||
array->signed_flag,
|
||||
cur->cb_data.value);
|
||||
|
|
@ -1046,9 +1244,15 @@ bool array_port_resolv_list_t::resolve(bool mes)
|
|||
|
||||
vvp_fun_arrayport*fun;
|
||||
if (use_addr)
|
||||
fun = new vvp_fun_arrayport(mem, ptr, addr);
|
||||
if (vpip_peek_current_scope()->is_automatic)
|
||||
fun = new vvp_fun_arrayport_aa(mem, ptr, addr);
|
||||
else
|
||||
fun = new vvp_fun_arrayport_sa(mem, ptr, addr);
|
||||
else
|
||||
fun = new vvp_fun_arrayport(mem, ptr);
|
||||
if (vpip_peek_current_scope()->is_automatic)
|
||||
fun = new vvp_fun_arrayport_aa(mem, ptr);
|
||||
else
|
||||
fun = new vvp_fun_arrayport_sa(mem, ptr);
|
||||
ptr->fun = fun;
|
||||
|
||||
array_attach_port(mem, fun);
|
||||
|
|
@ -1130,7 +1334,7 @@ void compile_array_alias(char*label, char*name, char*src)
|
|||
|
||||
// Share the words with the source array.
|
||||
obj->nets = mem->nets;
|
||||
obj->vals = mem->vals;
|
||||
obj->vals4 = mem->vals4;
|
||||
|
||||
obj->ports_ = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,13 @@ extern void array_attach_word(vvp_array_t array, unsigned long addr,
|
|||
extern void array_alias_word(vvp_array_t array, unsigned long addr,
|
||||
vpiHandle word);
|
||||
|
||||
extern void array_set_word(vvp_array_t arr,
|
||||
unsigned idx,
|
||||
unsigned off,
|
||||
vvp_vector4_t val);
|
||||
extern void array_set_word(vvp_array_t arr, unsigned idx,
|
||||
unsigned off, vvp_vector4_t val);
|
||||
extern void array_set_word(vvp_array_t arr, unsigned idx,
|
||||
double val);
|
||||
|
||||
extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned address);
|
||||
extern double array_get_word_r(vvp_array_t array, unsigned address);
|
||||
|
||||
/* VPI hooks */
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ vvp_fun_bufif::vvp_fun_bufif(bool en_invert, bool out_invert,
|
|||
count_functors_bufif += 1;
|
||||
}
|
||||
|
||||
void vvp_fun_bufif::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_bufif::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
switch (ptr.port()) {
|
||||
case 0:
|
||||
|
|
@ -115,4 +116,3 @@ void vvp_fun_bufif::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
* Revision 1.8 2002/08/12 01:35:07 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ class vvp_fun_bufif : public vvp_net_fun_t {
|
|||
vvp_fun_bufif(bool en_invert, bool out_invert,
|
||||
unsigned str0, unsigned str1);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
vvp_vector4_t bit_;
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ extern bool of_JMP0(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JMP1(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JOIN(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_AR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_AV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t code);
|
||||
|
|
@ -138,6 +139,7 @@ extern bool of_POW_WR(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_AR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_AV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%add", of_ADD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%add/wr", of_ADD_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%addi", of_ADDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%alloc", of_ALLOC, 1, {OA_VPI_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%andi", of_ANDI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
|
|
@ -134,6 +135,7 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%force/v",of_FORCE_V,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%force/wr",of_FORCE_WR,2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%force/x0",of_FORCE_X0,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%free", of_FREE, 1, {OA_VPI_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%ix/add", of_IX_ADD, 2, {OA_BIT1, OA_NUMBER, OA_NONE} },
|
||||
{ "%ix/get", of_IX_GET, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
|
|
@ -148,6 +150,7 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%load/ar",of_LOAD_AR,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||
{ "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||
{ "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||
{ "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} },
|
||||
|
|
@ -179,11 +182,11 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%release/net",of_RELEASE_NET,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
||||
{ "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} },
|
||||
{ "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
||||
{ "%set/ar", of_SET_AR, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/wr", of_SET_WORDR,2,{OA_VPI_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%set/wr", of_SET_WORDR,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
// { "%set/x0/x",of_SET_X0_X,3,{OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||
{ "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||
{ "%shiftr/s/i0", of_SHIFTR_S_I0,2,{OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||
|
|
@ -1687,34 +1690,6 @@ void compile_fork(char*label, struct symb_s dest, struct symb_s scope)
|
|||
compile_vpi_lookup(&code->handle, scope.text);
|
||||
}
|
||||
|
||||
void compile_alloc(char*label, struct symb_s scope)
|
||||
{
|
||||
if (label)
|
||||
compile_codelabel(label);
|
||||
|
||||
|
||||
/* Fill in the basics of the %alloc in the instruction. */
|
||||
vvp_code_t code = codespace_allocate();
|
||||
code->opcode = of_ALLOC;
|
||||
|
||||
/* Figure out the target SCOPE. */
|
||||
compile_vpi_lookup(&code->handle, scope.text);
|
||||
}
|
||||
|
||||
void compile_free(char*label, struct symb_s scope)
|
||||
{
|
||||
if (label)
|
||||
compile_codelabel(label);
|
||||
|
||||
|
||||
/* Fill in the basics of the %free in the instruction. */
|
||||
vvp_code_t code = codespace_allocate();
|
||||
code->opcode = of_FREE;
|
||||
|
||||
/* Figure out the target SCOPE. */
|
||||
compile_vpi_lookup(&code->handle, scope.text);
|
||||
}
|
||||
|
||||
void compile_vpi_call(char*label, char*name,
|
||||
long file_idx, long lineno,
|
||||
unsigned argc, vpiHandle*argv)
|
||||
|
|
|
|||
|
|
@ -356,8 +356,7 @@ extern void compile_ufunc(char*label, char*code, unsigned wid,
|
|||
* the threads.
|
||||
*/
|
||||
extern void compile_event(char*label, char*type,
|
||||
unsigned argc, struct symb_s*argv,
|
||||
bool debug_flag);
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_named_event(char*label, char*type);
|
||||
|
||||
|
||||
|
|
@ -406,9 +405,6 @@ extern void compile_fork(char*label, struct symb_s targ_s,
|
|||
struct symb_s scope_s);
|
||||
extern void compile_codelabel(char*label);
|
||||
|
||||
extern void compile_alloc(char*label, struct symb_s scope_s);
|
||||
extern void compile_free(char*label, struct symb_s scope_s);
|
||||
|
||||
/*
|
||||
* The parser uses these functions to compile .scope statements.
|
||||
* The implementations of these live in the vpi_scope.cc file.
|
||||
|
|
@ -443,12 +439,13 @@ extern void compile_net_real(char*label, char*name,
|
|||
|
||||
extern void compile_netw(char*label, char*array_symbol,
|
||||
unsigned long array_addr,
|
||||
int msb, int lsb, bool signed_flag,
|
||||
bool net8_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
int msb, int lsb, bool signed_flag,
|
||||
bool net8_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_netw_real(char*label, char*array_symbol,
|
||||
int msb, int lsb,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
unsigned long array_addr,
|
||||
int msb, int lsb,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
extern void compile_alias(char*label, char*name,
|
||||
int msb, int lsb, bool signed_flag,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ vvp_fun_concat::~vvp_fun_concat()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_concat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_concat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
unsigned pdx = port.port();
|
||||
|
||||
|
|
@ -64,7 +65,7 @@ void vvp_fun_concat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
val_.set_bit(off+idx, bit.value(idx));
|
||||
}
|
||||
|
||||
vvp_send_vec4(port.ptr()->out, val_);
|
||||
vvp_send_vec4(port.ptr()->out, val_, 0);
|
||||
}
|
||||
|
||||
void compile_concat(char*label, unsigned w0, unsigned w1,
|
||||
|
|
@ -91,7 +92,8 @@ vvp_fun_repeat::~vvp_fun_repeat()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_repeat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_repeat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(bit.size() == wid_/rep_);
|
||||
|
||||
|
|
@ -105,7 +107,7 @@ void vvp_fun_repeat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
|
||||
}
|
||||
|
||||
vvp_send_vec4(port.ptr()->out, val);
|
||||
vvp_send_vec4(port.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
void compile_repeat(char*label, long width, long repeat, struct symb_s arg)
|
||||
|
|
@ -140,4 +142,3 @@ void compile_repeat(char*label, long width, long repeat, struct symb_s arg)
|
|||
* Add missing concat.cc to cvs
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
22
vvp/delay.cc
22
vvp/delay.cc
|
|
@ -183,7 +183,8 @@ void vvp_fun_delay::clean_pulse_events_(vvp_time64_t use_delay)
|
|||
* wrong. What should happen is that if there are multiple changes,
|
||||
* multiple vectors approaching the result should be scheduled.
|
||||
*/
|
||||
void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (port.port() > 0) {
|
||||
// Get the integer value of the bit vector, or 0 if
|
||||
|
|
@ -248,7 +249,7 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
if (use_delay == 0) {
|
||||
cur_vec4_ = bit;
|
||||
initial_ = false;
|
||||
vvp_send_vec4(net_->out, cur_vec4_);
|
||||
vvp_send_vec4(net_->out, cur_vec4_, 0);
|
||||
} else {
|
||||
struct event_*cur = new struct event_(use_simtime);
|
||||
cur->run_run_ptr = &vvp_fun_delay::run_run_vec4_;
|
||||
|
|
@ -283,7 +284,8 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit)
|
||||
void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (port.port() > 0) {
|
||||
/* If the port is not 0, then this is a delay value that
|
||||
|
|
@ -328,7 +330,7 @@ void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit)
|
|||
if (use_delay == 0) {
|
||||
cur_real_ = bit;
|
||||
initial_ = false;
|
||||
vvp_send_real(net_->out, cur_real_);
|
||||
vvp_send_real(net_->out, cur_real_, 0);
|
||||
} else {
|
||||
struct event_*cur = new struct event_(use_simtime);
|
||||
cur->run_run_ptr = &vvp_fun_delay::run_run_real_;
|
||||
|
|
@ -357,7 +359,7 @@ void vvp_fun_delay::run_run()
|
|||
void vvp_fun_delay::run_run_vec4_(struct event_*cur)
|
||||
{
|
||||
cur_vec4_ = cur->ptr_vec4;
|
||||
vvp_send_vec4(net_->out, cur_vec4_);
|
||||
vvp_send_vec4(net_->out, cur_vec4_, 0);
|
||||
}
|
||||
|
||||
void vvp_fun_delay::run_run_vec8_(struct vvp_fun_delay::event_*cur)
|
||||
|
|
@ -369,7 +371,7 @@ void vvp_fun_delay::run_run_vec8_(struct vvp_fun_delay::event_*cur)
|
|||
void vvp_fun_delay::run_run_real_(struct vvp_fun_delay::event_*cur)
|
||||
{
|
||||
cur_real_ = cur->ptr_real;
|
||||
vvp_send_real(net_->out, cur_real_);
|
||||
vvp_send_real(net_->out, cur_real_, 0);
|
||||
}
|
||||
|
||||
vvp_fun_modpath::vvp_fun_modpath(vvp_net_t*net)
|
||||
|
|
@ -418,7 +420,8 @@ static vvp_time64_t delay_from_edge(vvp_bit4_t a, vvp_bit4_t b,
|
|||
return array[ edge_table[a][b] ];
|
||||
}
|
||||
|
||||
void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
/* Only the first port is used. */
|
||||
if (port.port() > 0)
|
||||
|
|
@ -532,7 +535,7 @@ void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
|
||||
void vvp_fun_modpath::run_run()
|
||||
{
|
||||
vvp_send_vec4(net_->out, cur_vec4_);
|
||||
vvp_send_vec4(net_->out, cur_vec4_, 0);
|
||||
}
|
||||
|
||||
vvp_fun_modpath_src::vvp_fun_modpath_src(vvp_time64_t del[12])
|
||||
|
|
@ -561,7 +564,8 @@ void vvp_fun_modpath_src::put_delay12(const vvp_time64_t val[12])
|
|||
delay_[idx] = val[idx];
|
||||
}
|
||||
|
||||
void vvp_fun_modpath_src::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_modpath_src::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (port.port() == 0) {
|
||||
// The modpath input...
|
||||
|
|
|
|||
12
vvp/delay.h
12
vvp/delay.h
|
|
@ -85,9 +85,11 @@ class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
vvp_fun_delay(vvp_net_t*net, vvp_bit4_t init, const vvp_delay_t&d);
|
||||
~vvp_fun_delay();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
void recv_real(vvp_net_ptr_t port, double bit);
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t);
|
||||
//void recv_long(vvp_net_ptr_t port, long bit);
|
||||
|
||||
private:
|
||||
|
|
@ -153,7 +155,8 @@ class vvp_fun_modpath : public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
|
||||
void add_modpath_src(vvp_fun_modpath_src*that, bool ifnone);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
virtual void run_run();
|
||||
|
|
@ -181,7 +184,8 @@ class vvp_fun_modpath_src : public vvp_net_fun_t {
|
|||
~vvp_fun_modpath_src();
|
||||
|
||||
public:
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
virtual bool test_vec4(const vvp_vector4_t&bit);
|
||||
|
||||
void get_delay12(vvp_time64_t out[12]) const;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ vvp_dff::~vvp_dff()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
vvp_bit4_t tmp;
|
||||
|
||||
|
|
@ -57,7 +58,7 @@ void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
tmp = clk_cur_;
|
||||
clk_cur_ = bit.value(0);
|
||||
if (clk_cur_ == BIT4_1 && tmp != BIT4_1)
|
||||
vvp_send_vec4(port.ptr()->out, d_);
|
||||
vvp_send_vec4(port.ptr()->out, d_, 0);
|
||||
break;
|
||||
|
||||
case 2: // CE
|
||||
|
|
@ -67,7 +68,7 @@ void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
|
||||
case 3: // Asynch-D
|
||||
d_ = bit;
|
||||
vvp_send_vec4(port.ptr()->out, d_);
|
||||
vvp_send_vec4(port.ptr()->out, d_, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ class vvp_dff : public vvp_net_fun_t {
|
|||
explicit vvp_dff(bool invert_clk =false, bool invert_ce =false);
|
||||
~vvp_dff();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
bool iclk_, ice_;
|
||||
|
|
|
|||
526
vvp/event.cc
526
vvp/event.cc
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
# include <iostream>
|
||||
|
||||
void waitable_hooks_s::run_waiting_threads_(unsigned context_idx)
|
||||
void waitable_hooks_s::run_waiting_threads_(vthread_t&threads)
|
||||
{
|
||||
// Run the non-blocking event controls.
|
||||
last = &event_ctls;
|
||||
|
|
@ -48,17 +48,11 @@ void waitable_hooks_s::run_waiting_threads_(unsigned context_idx)
|
|||
}
|
||||
}
|
||||
|
||||
vthread_t tmp;
|
||||
if (context_idx) {
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx));
|
||||
tmp = state->threads;
|
||||
state->threads = 0;
|
||||
} else {
|
||||
tmp = threads;
|
||||
threads = 0;
|
||||
}
|
||||
if (tmp) vthread_schedule_list(tmp);
|
||||
vthread_t tmp = threads;
|
||||
if (tmp == 0) return;
|
||||
threads = 0;
|
||||
|
||||
vthread_schedule_list(tmp);
|
||||
}
|
||||
|
||||
evctl::evctl(unsigned long ecount)
|
||||
|
|
@ -117,9 +111,9 @@ evctl_vector::evctl_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&value,
|
|||
void evctl_vector::run_run()
|
||||
{
|
||||
if (wid_ != 0) {
|
||||
vvp_send_vec4_pv(ptr_, value_, off_, value_.size(), wid_);
|
||||
vvp_send_vec4_pv(ptr_, value_, off_, value_.size(), wid_, 0);
|
||||
} else {
|
||||
vvp_send_vec4(ptr_, value_);
|
||||
vvp_send_vec4(ptr_, value_, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,114 +180,156 @@ const vvp_fun_edge::edge_t vvp_edge_negedge
|
|||
const vvp_fun_edge::edge_t vvp_edge_none = 0;
|
||||
|
||||
struct vvp_fun_edge_state_s : public waitable_state_s {
|
||||
vvp_fun_edge_state_s() : bit(BIT4_X) {}
|
||||
vvp_fun_edge_state_s()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
||||
bits[idx] = BIT4_X;
|
||||
}
|
||||
|
||||
vvp_bit4_t bit;
|
||||
vvp_bit4_t bits[4];
|
||||
};
|
||||
|
||||
vvp_fun_edge::vvp_fun_edge(edge_t e, bool debug_flag)
|
||||
: edge_(e), debug_(debug_flag)
|
||||
vvp_fun_edge::vvp_fun_edge(edge_t e)
|
||||
: edge_(e)
|
||||
{
|
||||
bits_[0] = BIT4_X;
|
||||
bits_[1] = BIT4_X;
|
||||
bits_[2] = BIT4_X;
|
||||
bits_[3] = BIT4_X;
|
||||
}
|
||||
|
||||
vvp_fun_edge::~vvp_fun_edge()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_edge::alloc_instance(vvp_context_t context)
|
||||
bool vvp_fun_edge::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_bit4_t&old_bit, vthread_t&threads)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx, new vvp_fun_edge_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_edge::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx));
|
||||
state->threads = 0;
|
||||
state->bit = BIT4_X;
|
||||
}
|
||||
|
||||
void vvp_fun_edge::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
{
|
||||
vvp_bit4_t*old_bit;
|
||||
if (context_idx) {
|
||||
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx));
|
||||
old_bit = &state->bit;
|
||||
} else {
|
||||
old_bit = &bits_[port.port()];
|
||||
}
|
||||
|
||||
/* See what kind of edge this represents. */
|
||||
edge_t mask = VVP_EDGE(*old_bit, bit.value(0));
|
||||
edge_t mask = VVP_EDGE(old_bit, bit.value(0));
|
||||
|
||||
/* Save the current input for the next time around. */
|
||||
*old_bit = bit.value(0);
|
||||
old_bit = bit.value(0);
|
||||
|
||||
if ((edge_ == vvp_edge_none) || (edge_ & mask)) {
|
||||
run_waiting_threads_(context_idx);
|
||||
run_waiting_threads_(threads);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vvp_fun_edge_sa::vvp_fun_edge_sa(edge_t e)
|
||||
: vvp_fun_edge(e), threads_(0)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
||||
bits_[idx] = BIT4_X;
|
||||
}
|
||||
|
||||
vvp_fun_edge_sa::~vvp_fun_edge_sa()
|
||||
{
|
||||
}
|
||||
|
||||
vthread_t vvp_fun_edge_sa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
vthread_t tmp = threads_;
|
||||
threads_ = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_fun_edge_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (recv_vec4_(port, bit, bits_[port.port()], threads_)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit);
|
||||
vvp_send_vec4(net->out, bit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
vvp_fun_edge_aa::vvp_fun_edge_aa(edge_t e)
|
||||
: vvp_fun_edge(e)
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
}
|
||||
|
||||
vvp_fun_edge_aa::~vvp_fun_edge_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_edge_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new vvp_fun_edge_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_edge_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
state->threads = 0;
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
||||
state->bits[idx] = BIT4_X;
|
||||
}
|
||||
|
||||
|
||||
vthread_t vvp_fun_edge_aa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx_));
|
||||
|
||||
vthread_t tmp = state->threads;
|
||||
state->threads = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_fun_edge_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (recv_vec4_(port, bit, state->bits[port.port()], state->threads)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct vvp_fun_anyedge_state_s : public waitable_state_s {
|
||||
vvp_fun_anyedge_state_s() : bitsr(0.0) {}
|
||||
vvp_fun_anyedge_state_s()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
||||
bitsr[idx] = 0.0;
|
||||
}
|
||||
|
||||
vvp_vector4_t bits;
|
||||
double bitsr;
|
||||
vvp_vector4_t bits[4];
|
||||
double bitsr[4];
|
||||
};
|
||||
|
||||
vvp_fun_anyedge::vvp_fun_anyedge(bool debug_flag)
|
||||
: debug_(debug_flag)
|
||||
vvp_fun_anyedge::vvp_fun_anyedge()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
||||
bitsr_[idx] = 0.0;
|
||||
}
|
||||
|
||||
vvp_fun_anyedge::~vvp_fun_anyedge()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx, new vvp_fun_anyedge_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx));
|
||||
state->threads = 0;
|
||||
state->bits.set_to_x();
|
||||
state->bitsr = 0.0;
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
bool vvp_fun_anyedge::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_vector4_t&old_bits, vthread_t&threads)
|
||||
{
|
||||
bool flag = false;
|
||||
|
||||
vvp_vector4_t*old_bits;
|
||||
if (context_idx) {
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx));
|
||||
old_bits = &state->bits;
|
||||
} else {
|
||||
old_bits = &bits_[port.port()];
|
||||
}
|
||||
|
||||
if (old_bits->size() != bit.size()) {
|
||||
if (old_bits.size() != bit.size()) {
|
||||
flag = true;
|
||||
|
||||
} else {
|
||||
for (unsigned idx = 0 ; idx < bit.size() ; idx += 1) {
|
||||
if (old_bits->value(idx) != bit.value(idx)) {
|
||||
if (old_bits.value(idx) != bit.value(idx)) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -301,29 +337,136 @@ void vvp_fun_anyedge::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
}
|
||||
|
||||
if (flag) {
|
||||
*old_bits = bit;
|
||||
run_waiting_threads_(context_idx);
|
||||
old_bits = bit;
|
||||
run_waiting_threads_(threads);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool vvp_fun_anyedge::recv_real_(vvp_net_ptr_t port, double bit,
|
||||
double&old_bits, vthread_t&threads)
|
||||
{
|
||||
if (old_bits != bit) {
|
||||
old_bits = bit;
|
||||
run_waiting_threads_(threads);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vvp_fun_anyedge_sa::vvp_fun_anyedge_sa()
|
||||
: threads_(0)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
||||
bitsr_[idx] = 0.0;
|
||||
}
|
||||
|
||||
vvp_fun_anyedge_sa::~vvp_fun_anyedge_sa()
|
||||
{
|
||||
}
|
||||
|
||||
vthread_t vvp_fun_anyedge_sa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
vthread_t tmp = threads_;
|
||||
threads_ = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (recv_vec4_(port, bit, bits_[port.port()], threads_)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit);
|
||||
vvp_send_vec4(net->out, bit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge::recv_real(vvp_net_ptr_t port, double bit)
|
||||
void vvp_fun_anyedge_sa::recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
double*old_bits;
|
||||
if (context_idx) {
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx));
|
||||
old_bits = &state->bitsr;
|
||||
} else {
|
||||
old_bits = &bitsr_[port.port()];
|
||||
}
|
||||
|
||||
if (*old_bits != bit) {
|
||||
*old_bits = bit;
|
||||
run_waiting_threads_(context_idx);
|
||||
if (recv_real_(port, bit, bitsr_[port.port()], threads_)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, vvp_vector4_t());
|
||||
vvp_send_vec4(net->out, vvp_vector4_t(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
vvp_fun_anyedge_aa::vvp_fun_anyedge_aa()
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
}
|
||||
|
||||
vvp_fun_anyedge_aa::~vvp_fun_anyedge_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new vvp_fun_anyedge_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
state->threads = 0;
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1) {
|
||||
state->bits[idx].set_to_x();
|
||||
state->bitsr[idx] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
vthread_t vvp_fun_anyedge_aa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx_));
|
||||
|
||||
vthread_t tmp = state->threads;
|
||||
state->threads = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (recv_vec4_(port, bit, state->bits[port.port()], state->threads)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge_aa::recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (recv_real_(port, bit, state->bitsr[port.port()], state->threads)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, vvp_vector4_t(), context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_real(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -335,23 +478,82 @@ vvp_fun_event_or::~vvp_fun_event_or()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_event_or::alloc_instance(vvp_context_t context)
|
||||
vvp_fun_event_or_sa::vvp_fun_event_or_sa()
|
||||
: threads_(0)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx, new waitable_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_event_or::reset_instance(vvp_context_t context)
|
||||
vvp_fun_event_or_sa::~vvp_fun_event_or_sa()
|
||||
{
|
||||
}
|
||||
|
||||
vthread_t vvp_fun_event_or_sa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
vthread_t tmp = threads_;
|
||||
threads_ = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_fun_event_or_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
run_waiting_threads_(threads_);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, 0);
|
||||
}
|
||||
|
||||
vvp_fun_event_or_aa::vvp_fun_event_or_aa()
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
}
|
||||
|
||||
vvp_fun_event_or_aa::~vvp_fun_event_or_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_event_or_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new waitable_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_event_or_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vvp_get_context_item(context, context_idx));
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
state->threads = 0;
|
||||
}
|
||||
|
||||
void vvp_fun_event_or::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
vthread_t vvp_fun_event_or_aa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
run_waiting_threads_(context_idx);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit);
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx_));
|
||||
|
||||
vthread_t tmp = state->threads;
|
||||
state->threads = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_fun_event_or_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
run_waiting_threads_(state->threads);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, context);
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vvp_named_event::vvp_named_event(struct __vpiHandle*h)
|
||||
|
|
@ -363,25 +565,78 @@ vvp_named_event::~vvp_named_event()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_named_event::alloc_instance(vvp_context_t context)
|
||||
vvp_named_event_sa::vvp_named_event_sa(struct __vpiHandle*h)
|
||||
: vvp_named_event(h), threads_(0)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx, new waitable_state_s);
|
||||
}
|
||||
|
||||
void vvp_named_event::reset_instance(vvp_context_t context)
|
||||
vvp_named_event_sa::~vvp_named_event_sa()
|
||||
{
|
||||
}
|
||||
|
||||
vthread_t vvp_named_event_sa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
vthread_t tmp = threads_;
|
||||
threads_ = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_named_event_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
run_waiting_threads_(threads_);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, 0);
|
||||
|
||||
vpip_run_named_event_callbacks(handle_);
|
||||
}
|
||||
|
||||
vvp_named_event_aa::vvp_named_event_aa(struct __vpiHandle*h)
|
||||
: vvp_named_event(h)
|
||||
{
|
||||
context_idx_ = vpip_add_item_to_context(this, vpip_peek_context_scope());
|
||||
}
|
||||
|
||||
vvp_named_event_aa::~vvp_named_event_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_named_event_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new waitable_state_s);
|
||||
}
|
||||
|
||||
void vvp_named_event_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vvp_get_context_item(context, context_idx));
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
state->threads = 0;
|
||||
}
|
||||
|
||||
void vvp_named_event::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
vthread_t vvp_named_event_aa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
run_waiting_threads_(context_idx);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit);
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx_));
|
||||
|
||||
vpip_run_named_event_callbacks(handle_);
|
||||
vthread_t tmp = state->threads;
|
||||
state->threads = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_named_event_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
assert(context);
|
||||
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
run_waiting_threads_(state->threads);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, context);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -394,9 +649,7 @@ void vvp_named_event::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
|
||||
static void compile_event_or(char*label, unsigned argc, struct symb_s*argv);
|
||||
|
||||
void compile_event(char*label, char*type,
|
||||
unsigned argc, struct symb_s*argv,
|
||||
bool debug_flag)
|
||||
void compile_event(char*label, char*type, unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_net_fun_t*fun = 0;
|
||||
|
||||
|
|
@ -408,9 +661,12 @@ void compile_event(char*label, char*type,
|
|||
if (strcmp(type,"edge") == 0) {
|
||||
|
||||
free(type);
|
||||
vvp_fun_anyedge*event_fun = new vvp_fun_anyedge(debug_flag);
|
||||
vpip_add_item_to_current_scope(event_fun);
|
||||
fun = event_fun;
|
||||
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
fun = new vvp_fun_anyedge_aa;
|
||||
} else {
|
||||
fun = new vvp_fun_anyedge_sa;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -424,9 +680,12 @@ void compile_event(char*label, char*type,
|
|||
assert(argc <= 4);
|
||||
free(type);
|
||||
|
||||
vvp_fun_edge*event_fun = new vvp_fun_edge(edge, debug_flag);
|
||||
vpip_add_item_to_current_scope(event_fun);
|
||||
fun = event_fun;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
fun = new vvp_fun_edge_aa(edge);
|
||||
} else {
|
||||
fun = new vvp_fun_edge_sa(edge);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vvp_net_t* ptr = new vvp_net_t;
|
||||
|
|
@ -440,11 +699,12 @@ void compile_event(char*label, char*type,
|
|||
|
||||
static void compile_event_or(char*label, unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_fun_event_or*fun = new vvp_fun_event_or;
|
||||
vvp_net_t* ptr = new vvp_net_t;
|
||||
ptr->fun = fun;
|
||||
|
||||
vpip_add_item_to_current_scope(fun);
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
ptr->fun = new vvp_fun_event_or_aa;
|
||||
} else {
|
||||
ptr->fun = new vvp_fun_event_or_sa;
|
||||
}
|
||||
define_functor_symbol(label, ptr);
|
||||
free(label);
|
||||
|
||||
|
|
@ -466,10 +726,12 @@ void compile_named_event(char*label, char*name)
|
|||
vvp_net_t*ptr = new vvp_net_t;
|
||||
|
||||
vpiHandle obj = vpip_make_named_event(name, ptr);
|
||||
vvp_named_event*fun = new vvp_named_event(obj);
|
||||
ptr->fun = fun;
|
||||
|
||||
vpip_add_item_to_current_scope(fun);
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
ptr->fun = new vvp_named_event_aa(obj);
|
||||
} else {
|
||||
ptr->fun = new vvp_named_event_sa(obj);
|
||||
}
|
||||
define_functor_symbol(label, ptr);
|
||||
compile_vpi_symbol(label, obj);
|
||||
vpip_attach_to_current_scope(obj);
|
||||
|
|
|
|||
199
vvp/event.h
199
vvp/event.h
|
|
@ -102,13 +102,15 @@ extern void schedule_evctl(vvp_array_t memory, unsigned index,
|
|||
struct waitable_hooks_s {
|
||||
|
||||
public:
|
||||
waitable_hooks_s() : threads(0), event_ctls(0) { last = &event_ctls; }
|
||||
vthread_t threads;
|
||||
waitable_hooks_s() : event_ctls(0) { last = &event_ctls; }
|
||||
|
||||
virtual vthread_t add_waiting_thread(vthread_t thread) = 0;
|
||||
|
||||
evctl*event_ctls;
|
||||
evctl**last;
|
||||
|
||||
protected:
|
||||
void run_waiting_threads_(unsigned context_idx);
|
||||
void run_waiting_threads_(vthread_t&threads);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -118,6 +120,7 @@ struct waitable_hooks_s {
|
|||
*/
|
||||
struct waitable_state_s {
|
||||
waitable_state_s() : threads(0) { }
|
||||
|
||||
vthread_t threads;
|
||||
};
|
||||
|
||||
|
|
@ -130,24 +133,62 @@ class vvp_fun_edge : public vvp_net_fun_t, public waitable_hooks_s {
|
|||
|
||||
public:
|
||||
typedef unsigned short edge_t;
|
||||
explicit vvp_fun_edge(edge_t e, bool debug_flag);
|
||||
explicit vvp_fun_edge(edge_t e);
|
||||
virtual ~vvp_fun_edge();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
protected:
|
||||
bool recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_bit4_t&old_bit, vthread_t&threads);
|
||||
|
||||
private:
|
||||
vvp_bit4_t bits_[4];
|
||||
edge_t edge_;
|
||||
bool debug_;
|
||||
};
|
||||
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_posedge;
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_negedge;
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_none;
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_edge.
|
||||
*/
|
||||
class vvp_fun_edge_sa : public vvp_fun_edge {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_edge_sa(edge_t e);
|
||||
virtual ~vvp_fun_edge_sa();
|
||||
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
vthread_t threads_;
|
||||
vvp_bit4_t bits_[4];
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_edge.
|
||||
*/
|
||||
class vvp_fun_edge_aa : public vvp_fun_edge, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_edge_aa(edge_t e);
|
||||
virtual ~vvp_fun_edge_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
struct __vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The vvp_fun_anyedge functor checks to see if any value in an input
|
||||
* vector changes. Unlike the vvp_fun_edge, which watches for the LSB
|
||||
|
|
@ -161,20 +202,63 @@ extern const vvp_fun_edge::edge_t vvp_edge_none;
|
|||
class vvp_fun_anyedge : public vvp_net_fun_t, public waitable_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_anyedge(bool debug_flag);
|
||||
explicit vvp_fun_anyedge();
|
||||
virtual ~vvp_fun_anyedge();
|
||||
|
||||
protected:
|
||||
bool recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_vector4_t&old_bits, vthread_t&threads);
|
||||
bool recv_real_(vvp_net_ptr_t port, double bit,
|
||||
double&old_bits, vthread_t&threads);
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_anyedge.
|
||||
*/
|
||||
class vvp_fun_anyedge_sa : public vvp_fun_anyedge {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_anyedge_sa();
|
||||
virtual ~vvp_fun_anyedge_sa();
|
||||
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
vthread_t threads_;
|
||||
vvp_vector4_t bits_[4];
|
||||
// In case I'm a real-valued event.
|
||||
double bitsr_[4];
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_anyedge.
|
||||
*/
|
||||
class vvp_fun_anyedge_aa : public vvp_fun_anyedge, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_anyedge_aa();
|
||||
virtual ~vvp_fun_anyedge_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_real(vvp_net_ptr_t port, double bit);
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
bool debug_;
|
||||
vvp_vector4_t bits_[4];
|
||||
// In case I'm a real-valued event.
|
||||
double bitsr_[4];
|
||||
struct __vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -186,13 +270,46 @@ class vvp_fun_event_or : public vvp_net_fun_t, public waitable_hooks_s {
|
|||
public:
|
||||
explicit vvp_fun_event_or();
|
||||
~vvp_fun_event_or();
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_event_or.
|
||||
*/
|
||||
class vvp_fun_event_or_sa : public vvp_fun_event_or {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_event_or_sa();
|
||||
~vvp_fun_event_or_sa();
|
||||
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
vthread_t threads_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_event_or.
|
||||
*/
|
||||
class vvp_fun_event_or_aa : public vvp_fun_event_or, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_event_or_aa();
|
||||
~vvp_fun_event_or_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
struct __vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -206,13 +323,47 @@ class vvp_named_event : public vvp_net_fun_t, public waitable_hooks_s {
|
|||
explicit vvp_named_event(struct __vpiHandle*eh);
|
||||
~vvp_named_event();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
|
||||
private:
|
||||
protected:
|
||||
struct __vpiHandle*handle_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_named_event.
|
||||
*/
|
||||
class vvp_named_event_sa : public vvp_named_event {
|
||||
|
||||
public:
|
||||
explicit vvp_named_event_sa(struct __vpiHandle*eh);
|
||||
~vvp_named_event_sa();
|
||||
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
vthread_t threads_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_named_event.
|
||||
*/
|
||||
class vvp_named_event_aa : public vvp_named_event, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_named_event_aa(struct __vpiHandle*eh);
|
||||
~vvp_named_event_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
#endif // __event_H
|
||||
|
|
|
|||
|
|
@ -35,10 +35,11 @@ vvp_fun_extend_signed::~vvp_fun_extend_signed()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_extend_signed::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_extend_signed::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (bit.size() >= width_) {
|
||||
vvp_send_vec4(port.ptr()->out, bit);
|
||||
vvp_send_vec4(port.ptr()->out, bit, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -51,5 +52,5 @@ void vvp_fun_extend_signed::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bi
|
|||
for (unsigned idx = bit.size() ; idx < res.size() ; idx += 1)
|
||||
res.set_bit(idx, pad);
|
||||
|
||||
vvp_send_vec4(port.ptr()->out, res);
|
||||
vvp_send_vec4(port.ptr()->out, res, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,8 +183,6 @@
|
|||
"%vpi_func/r" { return K_vpi_func_r; }
|
||||
"%disable" { return K_disable; }
|
||||
"%fork" { return K_fork; }
|
||||
"%alloc" { return K_alloc; }
|
||||
"%free" { return K_free; }
|
||||
|
||||
/* Handle the specialized variable access functions. */
|
||||
|
||||
|
|
|
|||
55
vvp/logic.cc
55
vvp/logic.cc
|
|
@ -42,7 +42,8 @@ vvp_fun_boolean_::~vvp_fun_boolean_()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_boolean_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_boolean_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
unsigned port = ptr.port();
|
||||
if (input_[port] .eeq( bit ))
|
||||
|
|
@ -56,7 +57,8 @@ void vvp_fun_boolean_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
}
|
||||
|
||||
void vvp_fun_boolean_::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
unsigned port = ptr.port();
|
||||
|
||||
|
|
@ -106,7 +108,7 @@ void vvp_fun_and::run_run()
|
|||
result.set_bit(idx, bitbit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, result);
|
||||
vvp_send_vec4(ptr->out, result, 0);
|
||||
}
|
||||
|
||||
vvp_fun_buf::vvp_fun_buf()
|
||||
|
|
@ -123,7 +125,8 @@ vvp_fun_buf::~vvp_fun_buf()
|
|||
* The buf functor is very simple--change the z bits to x bits in the
|
||||
* vector it passes, and propagate the result.
|
||||
*/
|
||||
void vvp_fun_buf::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_buf::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (ptr.port() != 0)
|
||||
return;
|
||||
|
|
@ -146,7 +149,7 @@ void vvp_fun_buf::run_run()
|
|||
|
||||
vvp_vector4_t tmp (input_);
|
||||
tmp.change_z2x();
|
||||
vvp_send_vec4(ptr->out, tmp);
|
||||
vvp_send_vec4(ptr->out, tmp, 0);
|
||||
}
|
||||
|
||||
vvp_fun_bufz::vvp_fun_bufz()
|
||||
|
|
@ -162,20 +165,22 @@ vvp_fun_bufz::~vvp_fun_bufz()
|
|||
* The bufz is similar to the buf device, except that it does not
|
||||
* bother translating z bits to x.
|
||||
*/
|
||||
void vvp_fun_bufz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_bufz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (ptr.port() != 0)
|
||||
return;
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, bit);
|
||||
vvp_send_vec4(ptr.ptr()->out, bit, 0);
|
||||
}
|
||||
|
||||
void vvp_fun_bufz::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_fun_bufz::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (ptr.port() != 0)
|
||||
return;
|
||||
|
||||
vvp_send_real(ptr.ptr()->out, bit);
|
||||
vvp_send_real(ptr.ptr()->out, bit, 0);
|
||||
}
|
||||
|
||||
vvp_fun_muxr::vvp_fun_muxr()
|
||||
|
|
@ -190,7 +195,8 @@ vvp_fun_muxr::~vvp_fun_muxr()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_muxr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_muxr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
/* The real valued mux can only take in the select as a
|
||||
vector4_t. The muxed data is real. */
|
||||
|
|
@ -219,7 +225,8 @@ void vvp_fun_muxr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_fun_muxr::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_fun_muxr::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
switch (ptr.port()) {
|
||||
case 0:
|
||||
|
|
@ -252,16 +259,16 @@ void vvp_fun_muxr::run_run()
|
|||
|
||||
switch (select_) {
|
||||
case SEL_PORT0:
|
||||
vvp_send_real(ptr->out, a_);
|
||||
vvp_send_real(ptr->out, a_, 0);
|
||||
break;
|
||||
case SEL_PORT1:
|
||||
vvp_send_real(ptr->out, b_);
|
||||
vvp_send_real(ptr->out, b_, 0);
|
||||
break;
|
||||
default:
|
||||
if (a_ == b_) {
|
||||
vvp_send_real(ptr->out, a_);
|
||||
vvp_send_real(ptr->out, a_, 0);
|
||||
} else {
|
||||
vvp_send_real(ptr->out, 0.0); // Should this be NaN?
|
||||
vvp_send_real(ptr->out, 0.0, 0); // Should this be NaN?
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -284,7 +291,8 @@ vvp_fun_muxz::~vvp_fun_muxz()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_muxz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_muxz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
switch (ptr.port()) {
|
||||
case 0:
|
||||
|
|
@ -331,10 +339,10 @@ void vvp_fun_muxz::run_run()
|
|||
|
||||
switch (select_) {
|
||||
case SEL_PORT0:
|
||||
vvp_send_vec4(ptr->out, a_);
|
||||
vvp_send_vec4(ptr->out, a_, 0);
|
||||
break;
|
||||
case SEL_PORT1:
|
||||
vvp_send_vec4(ptr->out, b_);
|
||||
vvp_send_vec4(ptr->out, b_, 0);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
|
|
@ -357,7 +365,7 @@ void vvp_fun_muxz::run_run()
|
|||
for (unsigned idx = min_size ; idx < max_size ; idx += 1)
|
||||
res.set_bit(idx, BIT4_X);
|
||||
|
||||
vvp_send_vec4(ptr->out, res);
|
||||
vvp_send_vec4(ptr->out, res, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -377,7 +385,8 @@ vvp_fun_not::~vvp_fun_not()
|
|||
* The buf functor is very simple--change the z bits to x bits in the
|
||||
* vector it passes, and propagate the result.
|
||||
*/
|
||||
void vvp_fun_not::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_not::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (ptr.port() != 0)
|
||||
return;
|
||||
|
|
@ -404,7 +413,7 @@ void vvp_fun_not::run_run()
|
|||
result.set_bit(idx, bitbit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, result);
|
||||
vvp_send_vec4(ptr->out, result, 0);
|
||||
}
|
||||
|
||||
vvp_fun_or::vvp_fun_or(unsigned wid, bool invert)
|
||||
|
|
@ -440,7 +449,7 @@ void vvp_fun_or::run_run()
|
|||
result.set_bit(idx, bitbit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, result);
|
||||
vvp_send_vec4(ptr->out, result, 0);
|
||||
}
|
||||
|
||||
vvp_fun_xor::vvp_fun_xor(unsigned wid, bool invert)
|
||||
|
|
@ -476,7 +485,7 @@ void vvp_fun_xor::run_run()
|
|||
result.set_bit(idx, bitbit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, result);
|
||||
vvp_send_vec4(ptr->out, result, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
27
vvp/logic.h
27
vvp/logic.h
|
|
@ -32,9 +32,11 @@ class vvp_fun_boolean_ : public vvp_net_fun_t, protected vvp_gen_event_s {
|
|||
explicit vvp_fun_boolean_(unsigned wid);
|
||||
~vvp_fun_boolean_();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t);
|
||||
|
||||
protected:
|
||||
vvp_vector4_t input_[4];
|
||||
|
|
@ -64,7 +66,8 @@ class vvp_fun_buf: public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
explicit vvp_fun_buf();
|
||||
virtual ~vvp_fun_buf();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
void run_run();
|
||||
|
|
@ -84,8 +87,10 @@ class vvp_fun_bufz: public vvp_net_fun_t {
|
|||
explicit vvp_fun_bufz();
|
||||
virtual ~vvp_fun_bufz();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
|
||||
void recv_real(vvp_net_ptr_t p, double bit);
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_real(vvp_net_ptr_t p, double bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
@ -109,7 +114,8 @@ class vvp_fun_muxz : public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
explicit vvp_fun_muxz(unsigned width);
|
||||
virtual ~vvp_fun_muxz();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
void run_run();
|
||||
|
|
@ -128,8 +134,10 @@ class vvp_fun_muxr : public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
explicit vvp_fun_muxr();
|
||||
virtual ~vvp_fun_muxr();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
|
||||
void recv_real(vvp_net_ptr_t p, double bit);
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_real(vvp_net_ptr_t p, double bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
void run_run();
|
||||
|
|
@ -147,7 +155,8 @@ class vvp_fun_not: public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
explicit vvp_fun_not();
|
||||
virtual ~vvp_fun_not();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
void run_run();
|
||||
|
|
|
|||
15
vvp/npmos.cc
15
vvp/npmos.cc
|
|
@ -28,7 +28,8 @@ vvp_fun_pmos_::vvp_fun_pmos_(bool enable_invert)
|
|||
}
|
||||
|
||||
|
||||
void vvp_fun_pmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_pmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
/* Data input is processed through eh recv_vec8 method,
|
||||
because the strength must be preserved. */
|
||||
|
|
@ -89,7 +90,7 @@ vvp_fun_pmos::vvp_fun_pmos(bool enable_invert)
|
|||
void vvp_fun_pmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
{
|
||||
if (ptr.port() == 1) {
|
||||
recv_vec4(ptr, reduce4(bit));
|
||||
recv_vec4(ptr, reduce4(bit), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +109,7 @@ vvp_fun_rpmos::vvp_fun_rpmos(bool enable_invert)
|
|||
void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
{
|
||||
if (ptr.port() == 1) {
|
||||
recv_vec4(ptr, reduce4(bit));
|
||||
recv_vec4(ptr, reduce4(bit), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +129,8 @@ vvp_fun_cmos_::vvp_fun_cmos_()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_cmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t &bit)
|
||||
void vvp_fun_cmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t &bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
/* Data input is processed through the recv_vec8 method,
|
||||
because the strength must be preserved. */
|
||||
|
|
@ -190,7 +192,7 @@ vvp_fun_cmos::vvp_fun_cmos()
|
|||
void vvp_fun_cmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
{
|
||||
if (ptr.port() == 1 || ptr.port() == 2) {
|
||||
recv_vec4(ptr, reduce4(bit));
|
||||
recv_vec4(ptr, reduce4(bit), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -209,7 +211,7 @@ vvp_fun_rcmos::vvp_fun_rcmos()
|
|||
void vvp_fun_rcmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
{
|
||||
if (ptr.port() == 1) {
|
||||
recv_vec4(ptr, reduce4(bit));
|
||||
recv_vec4(ptr, reduce4(bit), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -219,4 +221,3 @@ void vvp_fun_rcmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
|||
bit_ = resistive_reduction(bit);
|
||||
generate_output_(ptr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ class vvp_fun_pmos_ : public vvp_net_fun_t {
|
|||
public:
|
||||
explicit vvp_fun_pmos_(bool enable_invert);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
protected:
|
||||
void generate_output_(vvp_net_ptr_t port);
|
||||
|
|
@ -107,7 +108,8 @@ class vvp_fun_cmos_ : public vvp_net_fun_t {
|
|||
public:
|
||||
explicit vvp_fun_cmos_();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit,
|
||||
vvp_context_t);
|
||||
|
||||
protected:
|
||||
void generate_output_(vvp_net_ptr_t port);
|
||||
|
|
|
|||
|
|
@ -512,9 +512,14 @@ The <wid> is, line the %load/v, the result width. But unlike the
|
|||
(%load/vp0/s) to the desired width.
|
||||
|
||||
* %load/wr <bit>, <vpi-label>
|
||||
* %load/ar <bit>, <array-label>, <index>
|
||||
|
||||
This instruction reads a real value from the vpi-like object to a word
|
||||
register.
|
||||
The %load/wr instruction reads a real value from the vpi-like object
|
||||
to a word register <bit>.
|
||||
|
||||
The %load/ar instruction reads a real value from an array. The <index>
|
||||
is the index register that contains the canonical word address into
|
||||
the array.
|
||||
|
||||
* %load/x1p <bit>, <functor-label>, <wid>
|
||||
|
||||
|
|
@ -708,8 +713,17 @@ The address (in canonical form) is precalculated and loaded into index
|
|||
register 3. This is the address of the word within the array.
|
||||
|
||||
* %set/wr <vpi-label>, <bit>
|
||||
* %set/ar <array-label>, <index>, <bit>
|
||||
|
||||
This instruction writes a real word to the specified VPI-like object.
|
||||
The %set/wr instruction writes a real word to the specified VPI-like
|
||||
object.
|
||||
|
||||
The %set/ar instruction writes a real work to the specified array
|
||||
word. The <array-label> addresses the array, and the <index> is the
|
||||
name of the index register to address into the word. The index
|
||||
register must contain an integer value that is the canonical address
|
||||
of the array word. The <bit> is the index register that contains the
|
||||
real value word to write.
|
||||
|
||||
* %set/x0 <var-label>, <bit>, <wid>
|
||||
|
||||
|
|
|
|||
19
vvp/parse.y
19
vvp/parse.y
|
|
@ -85,7 +85,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
|||
%token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP K_UFUNC
|
||||
%token K_UDP K_UDP_C K_UDP_S
|
||||
%token K_VAR K_VAR_S K_VAR_I K_VAR_R K_vpi_call K_vpi_func K_vpi_func_r
|
||||
%token K_disable K_fork K_alloc K_free
|
||||
%token K_disable K_fork
|
||||
%token K_vpi_module K_vpi_time_precision K_file_names
|
||||
|
||||
%token <text> T_INSTR
|
||||
|
|
@ -483,16 +483,16 @@ statement
|
|||
named event instead. */
|
||||
|
||||
| T_LABEL K_EVENT T_SYMBOL ',' symbols ';'
|
||||
{ compile_event($1, $3, $5.cnt, $5.vect, false); }
|
||||
{ compile_event($1, $3, $5.cnt, $5.vect); }
|
||||
|
||||
| T_LABEL K_EVENT K_DEBUG T_SYMBOL ',' symbols ';'
|
||||
{ compile_event($1, $4, $6.cnt, $6.vect, true); }
|
||||
{ compile_event($1, $4, $6.cnt, $6.vect); }
|
||||
|
||||
| T_LABEL K_EVENT T_STRING ';'
|
||||
{ compile_named_event($1, $3); }
|
||||
|
||||
| T_LABEL K_EVENT_OR symbols ';'
|
||||
{ compile_event($1, 0, $3.cnt, $3.vect, false); }
|
||||
{ compile_event($1, 0, $3.cnt, $3.vect); }
|
||||
|
||||
|
||||
/* Instructions may have a label, and have zero or more
|
||||
|
|
@ -533,12 +533,6 @@ statement
|
|||
| label_opt K_fork symbol ',' symbol ';'
|
||||
{ compile_fork($1, $3, $5); }
|
||||
|
||||
| label_opt K_alloc symbol ';'
|
||||
{ compile_alloc($1, $3); }
|
||||
|
||||
| label_opt K_free symbol ';'
|
||||
{ compile_free($1, $3); }
|
||||
|
||||
/* Scope statements come in two forms. There are the scope
|
||||
declaration and the scope recall. The declarations create the
|
||||
scope, with their association with a parent. The label of the
|
||||
|
|
@ -668,6 +662,11 @@ statement
|
|||
symbols_net ';'
|
||||
{ compile_netw($1, $3, $4, $6, $7, true, true, $9.cnt, $9.vect); }
|
||||
|
||||
| T_LABEL K_NET_R T_SYMBOL T_NUMBER ','
|
||||
signed_t_number signed_t_number ','
|
||||
symbols_net ';'
|
||||
{ compile_netw_real($1, $3, $4, $6, $7, $9.cnt, $9.vect); }
|
||||
|
||||
/* Array word versions of alias directives. */
|
||||
|
||||
| T_LABEL K_ALIAS T_SYMBOL T_NUMBER ','
|
||||
|
|
|
|||
264
vvp/part.cc
264
vvp/part.cc
|
|
@ -27,17 +27,34 @@
|
|||
# include <iostream>
|
||||
# include <assert.h>
|
||||
|
||||
struct vvp_fun_part_state_s {
|
||||
vvp_fun_part_state_s() : bitsr(0.0) {}
|
||||
|
||||
vvp_vector4_t bits;
|
||||
double bitsr;
|
||||
};
|
||||
|
||||
vvp_fun_part::vvp_fun_part(unsigned base, unsigned wid)
|
||||
: base_(base), wid_(wid)
|
||||
{
|
||||
net_ = 0;
|
||||
}
|
||||
|
||||
vvp_fun_part::~vvp_fun_part()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
vvp_fun_part_sa::vvp_fun_part_sa(unsigned base, unsigned wid)
|
||||
: vvp_fun_part(base, wid)
|
||||
{
|
||||
net_ = 0;
|
||||
}
|
||||
|
||||
vvp_fun_part_sa::~vvp_fun_part_sa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(port.port() == 0);
|
||||
|
||||
|
|
@ -55,11 +72,12 @@ void vvp_fun_part::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
/*
|
||||
* Handle the case that the part select node is actually fed by a part
|
||||
* select assignment. It's not exactly clear what might make this
|
||||
* happen, but is does seem to happen and this should have sell
|
||||
* happen, but is does seem to happen and this should have well
|
||||
* defined behavior.
|
||||
*/
|
||||
void vvp_fun_part::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
void vvp_fun_part_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(bit.size() == wid);
|
||||
|
||||
|
|
@ -69,10 +87,10 @@ void vvp_fun_part::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
|
||||
assert(tmp.size() == vwid);
|
||||
tmp.set_vec(base, bit);
|
||||
recv_vec4(port, tmp);
|
||||
recv_vec4(port, tmp, 0);
|
||||
}
|
||||
|
||||
void vvp_fun_part::run_run()
|
||||
void vvp_fun_part_sa::run_run()
|
||||
{
|
||||
vvp_net_t*ptr = net_;
|
||||
net_ = 0;
|
||||
|
|
@ -82,7 +100,90 @@ void vvp_fun_part::run_run()
|
|||
if (idx + base_ < val_.size())
|
||||
res.set_bit(idx, val_.value(base_+idx));
|
||||
}
|
||||
vvp_send_vec4(ptr->out, res);
|
||||
vvp_send_vec4(ptr->out, res, 0);
|
||||
}
|
||||
|
||||
vvp_fun_part_aa::vvp_fun_part_aa(unsigned base, unsigned wid)
|
||||
: vvp_fun_part(base, wid)
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
}
|
||||
|
||||
vvp_fun_part_aa::~vvp_fun_part_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new vvp_vector4_t);
|
||||
}
|
||||
|
||||
void vvp_fun_part_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_vector4_t*val = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
val->set_to_x();
|
||||
}
|
||||
|
||||
void vvp_fun_part_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
assert(port.port() == 0);
|
||||
|
||||
vvp_vector4_t*val = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
vvp_vector4_t tmp (wid_, BIT4_X);
|
||||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
||||
if (idx + base_ < bit.size())
|
||||
tmp.set_bit(idx, bit.value(base_+idx));
|
||||
}
|
||||
if (!val->eeq( tmp )) {
|
||||
*val = tmp;
|
||||
vvp_send_vec4(port.ptr()->out, tmp, context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the case that the part select node is actually fed by a part
|
||||
* select assignment. It's not exactly clear what might make this
|
||||
* happen, but is does seem to happen and this should have well
|
||||
* defined behavior.
|
||||
*/
|
||||
void vvp_fun_part_aa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
assert(bit.size() == wid);
|
||||
|
||||
vvp_vector4_t*val = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
vvp_vector4_t tmp = *val;
|
||||
if (tmp.size() == 0)
|
||||
tmp = vvp_vector4_t(vwid);
|
||||
|
||||
assert(tmp.size() == vwid);
|
||||
tmp.set_vec(base, bit);
|
||||
recv_vec4(port, tmp, context);
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4_pv(port, bit, base, wid, vwid, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vvp_fun_part_pv::vvp_fun_part_pv(unsigned b, unsigned w, unsigned v)
|
||||
|
|
@ -94,7 +195,8 @@ vvp_fun_part_pv::~vvp_fun_part_pv()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part_pv::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_part_pv::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
assert(port.port() == 0);
|
||||
|
||||
|
|
@ -106,7 +208,7 @@ void vvp_fun_part_pv::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
}
|
||||
assert(bit.size() == wid_);
|
||||
|
||||
vvp_send_vec4_pv(port.ptr()->out, bit, base_, wid_, vwid_);
|
||||
vvp_send_vec4_pv(port.ptr()->out, bit, base_, wid_, vwid_, context);
|
||||
}
|
||||
|
||||
void vvp_fun_part_pv::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
||||
|
|
@ -125,7 +227,7 @@ void vvp_fun_part_pv::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
|||
}
|
||||
|
||||
vvp_fun_part_var::vvp_fun_part_var(unsigned w)
|
||||
: base_(0), wid_(w)
|
||||
: wid_(w)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -133,18 +235,20 @@ vvp_fun_part_var::~vvp_fun_part_var()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part_var::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
bool vvp_fun_part_var::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned&base, vvp_vector4_t&source,
|
||||
vvp_vector4_t&ref)
|
||||
{
|
||||
unsigned long tmp;
|
||||
switch (port.port()) {
|
||||
case 0:
|
||||
source_ = bit;
|
||||
source = bit;
|
||||
break;
|
||||
case 1:
|
||||
tmp = ULONG_MAX;
|
||||
vector4_to_value(bit, tmp);
|
||||
if (tmp == base_) return;
|
||||
base_ = tmp;
|
||||
if (tmp == base) return false;
|
||||
base = tmp;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unsupported port type %d.\n", port.port());
|
||||
|
|
@ -155,21 +259,40 @@ void vvp_fun_part_var::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
vvp_vector4_t res (wid_);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
||||
unsigned adr = base_+idx;
|
||||
if (adr >= source_.size())
|
||||
unsigned adr = base+idx;
|
||||
if (adr >= source.size())
|
||||
break;
|
||||
|
||||
res.set_bit(idx, source_.value(adr));
|
||||
res.set_bit(idx, source.value(adr));
|
||||
}
|
||||
|
||||
if (! ref_.eeq(res)) {
|
||||
ref_ = res;
|
||||
vvp_send_vec4(port.ptr()->out, res);
|
||||
if (! ref.eeq(res)) {
|
||||
ref = res;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vvp_fun_part_var_sa::vvp_fun_part_var_sa(unsigned w)
|
||||
: vvp_fun_part_var(w), base_(0)
|
||||
{
|
||||
}
|
||||
|
||||
vvp_fun_part_var_sa::~vvp_fun_part_var_sa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part_var_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (recv_vec4_(port, bit, base_, source_, ref_)) {
|
||||
vvp_send_vec4(port.ptr()->out, ref_, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_part_var::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
void vvp_fun_part_var_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(bit.size() == wid);
|
||||
|
||||
|
|
@ -179,8 +302,86 @@ void vvp_fun_part_var::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
|
||||
assert(tmp.size() == vwid);
|
||||
tmp.set_vec(base, bit);
|
||||
recv_vec4(port, tmp);
|
||||
recv_vec4(port, tmp, 0);
|
||||
}
|
||||
|
||||
struct vvp_fun_part_var_state_s {
|
||||
vvp_fun_part_var_state_s() : base(0) { }
|
||||
|
||||
unsigned base;
|
||||
vvp_vector4_t source;
|
||||
vvp_vector4_t ref;
|
||||
};
|
||||
|
||||
vvp_fun_part_var_aa::vvp_fun_part_var_aa(unsigned w)
|
||||
: vvp_fun_part_var(w)
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
}
|
||||
|
||||
vvp_fun_part_var_aa::~vvp_fun_part_var_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part_var_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new vvp_fun_part_var_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_part_var_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_fun_part_var_state_s*state = static_cast<vvp_fun_part_var_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
state->base = 0;
|
||||
state->source.set_to_x();
|
||||
state->ref.set_to_x();
|
||||
}
|
||||
|
||||
void vvp_fun_part_var_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
vvp_fun_part_var_state_s*state = static_cast<vvp_fun_part_var_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (recv_vec4_(port, bit, state->base, state->source, state->ref)) {
|
||||
vvp_send_vec4(port.ptr()->out, state->ref, context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_part_var_aa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
vvp_fun_part_var_state_s*state = static_cast<vvp_fun_part_var_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
assert(bit.size() == wid);
|
||||
|
||||
vvp_vector4_t tmp = state->source;
|
||||
if (tmp.size() == 0)
|
||||
tmp = vvp_vector4_t(vwid);
|
||||
|
||||
assert(tmp.size() == vwid);
|
||||
tmp.set_vec(base, bit);
|
||||
recv_vec4(port, tmp, context);
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -201,7 +402,12 @@ void link_node_1(char*label, char*source, vvp_net_fun_t*fun)
|
|||
void compile_part_select(char*label, char*source,
|
||||
unsigned base, unsigned wid)
|
||||
{
|
||||
vvp_fun_part*fun = new vvp_fun_part(base, wid);
|
||||
vvp_fun_part*fun = 0;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
fun = new vvp_fun_part_aa(base, wid);
|
||||
} else {
|
||||
fun = new vvp_fun_part_sa(base, wid);
|
||||
}
|
||||
link_node_1(label, source, fun);
|
||||
}
|
||||
|
||||
|
|
@ -216,7 +422,12 @@ void compile_part_select_pv(char*label, char*source,
|
|||
void compile_part_select_var(char*label, char*source, char*var,
|
||||
unsigned wid)
|
||||
{
|
||||
vvp_fun_part_var*fun = new vvp_fun_part_var(wid);
|
||||
vvp_fun_part_var*fun = 0;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
fun = new vvp_fun_part_var_aa(wid);
|
||||
} else {
|
||||
fun = new vvp_fun_part_var_sa(wid);
|
||||
}
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
net->fun = fun;
|
||||
|
||||
|
|
@ -226,4 +437,3 @@ void compile_part_select_var(char*label, char*source, char*var,
|
|||
input_connect(net, 0, source);
|
||||
input_connect(net, 1, var);
|
||||
}
|
||||
|
||||
|
|
|
|||
106
vvp/part.h
106
vvp/part.h
|
|
@ -27,32 +27,73 @@
|
|||
* select starts. Input 2, which is typically constant, is the width
|
||||
* of the result.
|
||||
*/
|
||||
class vvp_fun_part : public vvp_net_fun_t, private vvp_gen_event_s {
|
||||
class vvp_fun_part : public vvp_net_fun_t {
|
||||
|
||||
public:
|
||||
vvp_fun_part(unsigned base, unsigned wid);
|
||||
~vvp_fun_part();
|
||||
|
||||
protected:
|
||||
unsigned base_;
|
||||
unsigned wid_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_part.
|
||||
*/
|
||||
class vvp_fun_part_sa : public vvp_fun_part, public vvp_gen_event_s {
|
||||
|
||||
public:
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
vvp_fun_part_sa(unsigned base, unsigned wid);
|
||||
~vvp_fun_part_sa();
|
||||
|
||||
public:
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned, unsigned, unsigned);
|
||||
unsigned, unsigned, unsigned,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
void run_run();
|
||||
|
||||
private:
|
||||
unsigned base_;
|
||||
unsigned wid_;
|
||||
vvp_vector4_t val_;
|
||||
vvp_net_t*net_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_part.
|
||||
*/
|
||||
class vvp_fun_part_aa : public vvp_fun_part, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
vvp_fun_part_aa(unsigned base, unsigned wid);
|
||||
~vvp_fun_part_aa();
|
||||
|
||||
public:
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned, unsigned, unsigned,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
struct __vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
/* vvp_fun_part_pv
|
||||
* This node takes a vector input and turns it into the part select of
|
||||
* a wider output network. It used the recv_vec4_pv methods of the
|
||||
* destination nodes to propagate the part select.
|
||||
* destination nodes to propagate the part select. It can be used in
|
||||
* both statically and automatically allocated scopes, as it has no
|
||||
* dynamic state.
|
||||
*/
|
||||
class vvp_fun_part_pv : public vvp_net_fun_t {
|
||||
|
||||
|
|
@ -61,7 +102,9 @@ class vvp_fun_part_pv : public vvp_net_fun_t {
|
|||
~vvp_fun_part_pv();
|
||||
|
||||
public:
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
|
||||
private:
|
||||
|
|
@ -81,18 +124,61 @@ class vvp_fun_part_var : public vvp_net_fun_t {
|
|||
explicit vvp_fun_part_var(unsigned wid);
|
||||
~vvp_fun_part_var();
|
||||
|
||||
protected:
|
||||
bool recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned&base, vvp_vector4_t&source,
|
||||
vvp_vector4_t&ref);
|
||||
|
||||
unsigned wid_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_part_var.
|
||||
*/
|
||||
class vvp_fun_part_var_sa : public vvp_fun_part_var {
|
||||
|
||||
public:
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
explicit vvp_fun_part_var_sa(unsigned wid);
|
||||
~vvp_fun_part_var_sa();
|
||||
|
||||
public:
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned, unsigned, unsigned);
|
||||
unsigned, unsigned, unsigned,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
unsigned base_;
|
||||
unsigned wid_;
|
||||
vvp_vector4_t source_;
|
||||
// Save the last output, for detecting change.
|
||||
vvp_vector4_t ref_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_part_var.
|
||||
*/
|
||||
class vvp_fun_part_var_aa : public vvp_fun_part_var, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_part_var_aa(unsigned wid);
|
||||
~vvp_fun_part_var_aa();
|
||||
|
||||
public:
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned, unsigned, unsigned,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
struct __vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@
|
|||
* All the reduction operations take a single vector input and produce
|
||||
* a scalar result. The vvp_reduce_base class codifies these general
|
||||
* characteristics, leaving only the calculation of the result for the
|
||||
* base class.
|
||||
* base class. This can be used in both statically and automatically
|
||||
* allocated scopes, as bits_ is only used for temporary storage.
|
||||
*/
|
||||
class vvp_reduce_base : public vvp_net_fun_t {
|
||||
|
||||
|
|
@ -42,9 +43,11 @@ class vvp_reduce_base : public vvp_net_fun_t {
|
|||
vvp_reduce_base();
|
||||
virtual ~vvp_reduce_base();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context);
|
||||
|
||||
virtual vvp_bit4_t calculate_result() const =0;
|
||||
|
||||
|
|
@ -60,16 +63,18 @@ vvp_reduce_base::~vvp_reduce_base()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_reduce_base::recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit)
|
||||
void vvp_reduce_base::recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
bits_ = bit;
|
||||
vvp_bit4_t res = calculate_result();
|
||||
vvp_vector4_t rv (1, res);
|
||||
vvp_send_vec4(prt.ptr()->out, rv);
|
||||
vvp_send_vec4(prt.ptr()->out, rv, context);
|
||||
}
|
||||
|
||||
void vvp_reduce_base::recv_vec4_pv(vvp_net_ptr_t prt, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (bits_.size() == 0) {
|
||||
bits_ = vvp_vector4_t(vwid);
|
||||
|
|
@ -80,7 +85,7 @@ void vvp_reduce_base::recv_vec4_pv(vvp_net_ptr_t prt, const vvp_vector4_t&bit,
|
|||
bits_.set_vec(base, bit);
|
||||
vvp_bit4_t res = calculate_result();
|
||||
vvp_vector4_t rv (1, res);
|
||||
vvp_send_vec4(prt.ptr()->out, rv);
|
||||
vvp_send_vec4(prt.ptr()->out, rv, context);
|
||||
}
|
||||
|
||||
class vvp_reduce_and : public vvp_reduce_base {
|
||||
|
|
|
|||
|
|
@ -35,13 +35,15 @@ resolv_functor::~resolv_functor()
|
|||
{
|
||||
}
|
||||
|
||||
void resolv_functor::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void resolv_functor::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
recv_vec8(port, vvp_vector8_t(bit, 6,6 /* STRONG */));
|
||||
}
|
||||
|
||||
void resolv_functor::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(bit.size() == wid);
|
||||
vvp_vector4_t res (vwid);
|
||||
|
|
@ -55,7 +57,7 @@ void resolv_functor::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
for (unsigned idx = base+wid ; idx < vwid ; idx += 1)
|
||||
res.set_bit(idx, BIT4_Z);
|
||||
|
||||
recv_vec4(port, res);
|
||||
recv_vec4(port, res, 0);
|
||||
}
|
||||
|
||||
void resolv_functor::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
||||
|
|
@ -123,7 +125,8 @@ resolv_wired_logic::~resolv_wired_logic()
|
|||
{
|
||||
}
|
||||
|
||||
void resolv_wired_logic::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void resolv_wired_logic::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
unsigned pdx = port.port();
|
||||
vvp_net_t*ptr = port.ptr();
|
||||
|
|
@ -143,7 +146,7 @@ void resolv_wired_logic::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
out = wired_logic_math_(out, val_[idx]);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, out);
|
||||
vvp_send_vec4(ptr->out, out, 0);
|
||||
}
|
||||
|
||||
vvp_vector4_t resolv_triand::wired_logic_math_(vvp_vector4_t&a, vvp_vector4_t&b)
|
||||
|
|
|
|||
|
|
@ -40,11 +40,13 @@ class resolv_functor : public vvp_net_fun_t {
|
|||
explicit resolv_functor(vvp_scalar_t hiz_value, const char* debug =0);
|
||||
~resolv_functor();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t);
|
||||
void recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
|
||||
|
|
@ -62,7 +64,8 @@ class resolv_wired_logic : public vvp_net_fun_t {
|
|||
explicit resolv_wired_logic(void);
|
||||
~resolv_wired_logic();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
protected:
|
||||
virtual vvp_vector4_t wired_logic_math_(vvp_vector4_t&a, vvp_vector4_t&b) =0;
|
||||
|
|
|
|||
|
|
@ -141,9 +141,9 @@ void assign_vector4_event_s::run_run(void)
|
|||
{
|
||||
count_assign_events += 1;
|
||||
if (vwid > 0)
|
||||
vvp_send_vec4_pv(ptr, val, base, val.size(), vwid);
|
||||
vvp_send_vec4_pv(ptr, val, base, val.size(), vwid, 0);
|
||||
else
|
||||
vvp_send_vec4(ptr, val);
|
||||
vvp_send_vec4(ptr, val, 0);
|
||||
}
|
||||
|
||||
static const size_t ASSIGN4_CHUNK_COUNT = 524288 / sizeof(struct assign_vector4_event_s);
|
||||
|
|
@ -205,7 +205,7 @@ struct assign_real_event_s : public event_s {
|
|||
void assign_real_event_s::run_run(void)
|
||||
{
|
||||
count_assign_events += 1;
|
||||
vvp_send_real(ptr, val);
|
||||
vvp_send_real(ptr, val, 0);
|
||||
}
|
||||
|
||||
static const size_t ASSIGNR_CHUNK_COUNT = 8192 / sizeof(struct assign_real_event_s);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "vvp_net.h"
|
||||
# include "compile.h"
|
||||
# include "symbols.h"
|
||||
# include "codes.h"
|
||||
|
|
@ -61,15 +62,15 @@ ufunc_core::~ufunc_core()
|
|||
* input variables of the function for execution. The method copies
|
||||
* the input values collected by the core to the variables.
|
||||
*/
|
||||
void ufunc_core::assign_bits_to_ports(void)
|
||||
void ufunc_core::assign_bits_to_ports(vvp_context_t context)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < port_count() ; idx += 1) {
|
||||
vvp_net_t*net = ports_[idx];
|
||||
vvp_net_ptr_t pp (net, 0);
|
||||
if (vvp_fun_signal_real*tmp = dynamic_cast<vvp_fun_signal_real*>(net->fun))
|
||||
tmp->recv_real(pp, value_r(idx));
|
||||
tmp->recv_real(pp, value_r(idx), context);
|
||||
if (vvp_fun_signal_vec*tmp = dynamic_cast<vvp_fun_signal_vec*>(net->fun))
|
||||
tmp->recv_vec4(pp, value(idx));
|
||||
tmp->recv_vec4(pp, value(idx), context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class ufunc_core : public vvp_wide_fun_core {
|
|||
struct __vpiScope*call_scope() { return call_scope_; }
|
||||
struct __vpiScope*func_scope() { return func_scope_; }
|
||||
|
||||
void assign_bits_to_ports(void);
|
||||
void assign_bits_to_ports(vvp_context_t context);
|
||||
void finish_thread(vthread_t thr);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -569,7 +569,7 @@ void vvp_vpi_callback_wordable::attach_as_word(vvp_array_t arr, unsigned long ad
|
|||
array_word_ = addr;
|
||||
}
|
||||
|
||||
void vvp_fun_signal::get_value(struct t_vpi_value*vp)
|
||||
void vvp_fun_signal4::get_value(struct t_vpi_value*vp)
|
||||
{
|
||||
switch (vp->format) {
|
||||
case vpiScalarVal:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,21 @@
|
|||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
static int named_event_get(int code, vpiHandle ref)
|
||||
{
|
||||
assert((ref->vpi_type->type_code==vpiNamedEvent));
|
||||
|
||||
struct __vpiNamedEvent*obj = (struct __vpiNamedEvent*)ref;
|
||||
|
||||
switch (code) {
|
||||
|
||||
case vpiAutomatic:
|
||||
return (int) obj->scope->is_automatic;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char* named_event_get_str(int code, vpiHandle ref)
|
||||
{
|
||||
assert((ref->vpi_type->type_code==vpiNamedEvent));
|
||||
|
|
@ -57,7 +72,7 @@ static vpiHandle named_event_get_handle(int code, vpiHandle ref)
|
|||
static const struct __vpirt vpip_named_event_rt = {
|
||||
vpiNamedEvent,
|
||||
|
||||
0,
|
||||
named_event_get,
|
||||
named_event_get_str,
|
||||
0,
|
||||
0,
|
||||
|
|
@ -122,4 +137,3 @@ void vpip_run_named_event_callbacks(vpiHandle ref)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,14 @@ struct __vpiScope* vpip_scope(__vpiSignal*sig)
|
|||
return sig->within.scope;
|
||||
}
|
||||
|
||||
struct __vpiScope* vpip_scope(__vpiRealVar*sig)
|
||||
{
|
||||
if (sig->is_netarray)
|
||||
return (struct __vpiScope*) vpi_handle(vpiScope, sig->within.parent);
|
||||
else
|
||||
return sig->within.scope;
|
||||
}
|
||||
|
||||
const char *vpip_string(const char*str)
|
||||
{
|
||||
static vpip_string_chunk first_chunk = {0, {0}};
|
||||
|
|
|
|||
|
|
@ -183,8 +183,10 @@ struct __vpiScope {
|
|||
/* Keep an array of items to be automatically allocated */
|
||||
struct automatic_hooks_s**item;
|
||||
unsigned nitem;
|
||||
/* Keep a list of live contexts. */
|
||||
vvp_context_t live_contexts;
|
||||
/* Keep a list of freed contexts. */
|
||||
vvp_context_t free_context;
|
||||
vvp_context_t free_contexts;
|
||||
/* Keep a list of threads in the scope. */
|
||||
vthread_t threads;
|
||||
signed int time_units :8;
|
||||
|
|
@ -193,7 +195,9 @@ struct __vpiScope {
|
|||
|
||||
extern struct __vpiScope* vpip_peek_current_scope(void);
|
||||
extern void vpip_attach_to_current_scope(vpiHandle obj);
|
||||
extern void vpip_add_item_to_current_scope(automatic_hooks_s*item);
|
||||
extern struct __vpiScope* vpip_peek_context_scope(void);
|
||||
extern unsigned vpip_add_item_to_context(automatic_hooks_s*item,
|
||||
struct __vpiScope*scope);
|
||||
extern vpiHandle vpip_make_root_iterator(void);
|
||||
extern void vpip_make_root_iterator(struct __vpiHandle**&table,
|
||||
unsigned&ntable);
|
||||
|
|
@ -219,6 +223,7 @@ struct __vpiSignal {
|
|||
unsigned signed_flag : 1;
|
||||
unsigned isint_ : 1; // original type was integer
|
||||
unsigned is_netarray : 1; // This is word of a net array
|
||||
unsigned is_automatic : 1;
|
||||
/* The represented value is here. */
|
||||
vvp_net_t*node;
|
||||
};
|
||||
|
|
@ -349,17 +354,22 @@ extern void vpip_real_value_change(struct __vpiCallback*cbh,
|
|||
*/
|
||||
struct __vpiRealVar {
|
||||
struct __vpiHandle base;
|
||||
vpiHandle parent;
|
||||
struct __vpiScope* scope;
|
||||
union { // The scope or parent array that contains me.
|
||||
vpiHandle parent;
|
||||
struct __vpiScope* scope;
|
||||
} within;
|
||||
/* The name of this variable, or the index for array words. */
|
||||
union {
|
||||
const char*name;
|
||||
vpiHandle index;
|
||||
} id;
|
||||
unsigned is_netarray : 1; // This is word of a net array
|
||||
vvp_net_t*net;
|
||||
};
|
||||
|
||||
extern struct __vpiScope* vpip_scope(__vpiRealVar*sig);
|
||||
extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net);
|
||||
extern struct __vpiRealVar* vpip_realvar_from_handle(vpiHandle obj);
|
||||
|
||||
/*
|
||||
* When a loaded VPI module announces a system task/function, one
|
||||
|
|
|
|||
|
|
@ -28,21 +28,33 @@
|
|||
#endif
|
||||
# include <assert.h>
|
||||
|
||||
struct __vpiRealVar* vpip_realvar_from_handle(vpiHandle obj)
|
||||
{
|
||||
assert(obj);
|
||||
if (obj->vpi_type->type_code == vpiRealVar)
|
||||
return (struct __vpiRealVar*)obj;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int real_var_get(int code, vpiHandle ref)
|
||||
{
|
||||
assert(ref->vpi_type->type_code == vpiRealVar);
|
||||
|
||||
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
||||
struct __vpiRealVar*rfp = vpip_realvar_from_handle(ref);
|
||||
|
||||
switch (code) {
|
||||
case vpiArray:
|
||||
return rfp->parent != 0;
|
||||
return rfp->is_netarray != 0;
|
||||
|
||||
case vpiSize:
|
||||
return 1;
|
||||
|
||||
case vpiLineNo:
|
||||
return 0; // Not implemented for now!
|
||||
|
||||
case vpiAutomatic:
|
||||
return (int) vpip_scope(rfp)->is_automatic;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -59,8 +71,8 @@ static char* real_var_get_str(int code, vpiHandle ref)
|
|||
}
|
||||
|
||||
char *nm, *ixs;
|
||||
if (rfp->parent) {
|
||||
nm = strdup(vpi_get_str(vpiName, rfp->parent));
|
||||
if (rfp->is_netarray) {
|
||||
nm = strdup(vpi_get_str(vpiName, rfp->within.parent));
|
||||
s_vpi_value vp;
|
||||
vp.format = vpiDecStrVal;
|
||||
vpi_get_value(rfp->id.index, &vp);
|
||||
|
|
@ -70,7 +82,7 @@ static char* real_var_get_str(int code, vpiHandle ref)
|
|||
ixs = NULL;
|
||||
}
|
||||
|
||||
char *rbuf = generic_get_str(code, &rfp->scope->base, nm, ixs);
|
||||
char *rbuf = generic_get_str(code, &(vpip_scope(rfp)->base), nm, ixs);
|
||||
free(nm);
|
||||
return rbuf;
|
||||
}
|
||||
|
|
@ -84,10 +96,13 @@ static vpiHandle real_var_get_handle(int code, vpiHandle ref)
|
|||
switch (code) {
|
||||
|
||||
case vpiParent:
|
||||
return rfp->parent;
|
||||
return rfp->is_netarray ? rfp->within.parent : 0;
|
||||
|
||||
case vpiIndex:
|
||||
return rfp->parent ? rfp->id.index : 0;
|
||||
return rfp->is_netarray ? rfp->id.index : 0;
|
||||
|
||||
case vpiScope:
|
||||
return &(vpip_scope(rfp)->base);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -100,8 +115,8 @@ static vpiHandle real_var_iterate(int code, vpiHandle ref)
|
|||
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
||||
|
||||
if (code == vpiIndex) {
|
||||
return rfp->parent ? (rfp->id.index->vpi_type->iterate_)
|
||||
(code, rfp->id.index) : 0;
|
||||
return rfp->is_netarray ? (rfp->id.index->vpi_type->iterate_)
|
||||
(code, rfp->id.index) : 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -131,11 +146,13 @@ static vpiHandle real_var_put_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
switch (vp->format) {
|
||||
|
||||
case vpiRealVal:
|
||||
vvp_send_real(destination, vp->value.real);
|
||||
vvp_send_real(destination, vp->value.real,
|
||||
vthread_get_wt_context());
|
||||
break;
|
||||
|
||||
case vpiIntVal:
|
||||
vvp_send_real(destination, (double)vp->value.integer);
|
||||
vvp_send_real(destination, (double)vp->value.integer,
|
||||
vthread_get_wt_context());
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -174,22 +191,17 @@ void vpip_real_value_change(struct __vpiCallback*cbh,
|
|||
fun->add_vpi_callback(cbh);
|
||||
}
|
||||
|
||||
/*
|
||||
* Since reals do not currently support arrays none of the array code
|
||||
* has been tested! Though it should work since it is a copy of the
|
||||
* signal code.
|
||||
*/
|
||||
vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net)
|
||||
{
|
||||
struct __vpiRealVar*obj = (struct __vpiRealVar*)
|
||||
malloc(sizeof(struct __vpiRealVar));
|
||||
|
||||
obj->base.vpi_type = &vpip_real_var_rt;
|
||||
obj->parent = 0;
|
||||
obj->id.name = vpip_name_string(name);
|
||||
obj->id.name = name ? vpip_name_string(name) : 0;
|
||||
obj->is_netarray = 0;
|
||||
obj->net = net;
|
||||
|
||||
obj->scope = vpip_peek_current_scope();
|
||||
obj->within.scope = vpip_peek_current_scope();
|
||||
|
||||
return &obj->base;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,26 +316,6 @@ static void attach_to_scope_(struct __vpiScope*scope, vpiHandle obj)
|
|||
scope->intern[idx] = obj;
|
||||
}
|
||||
|
||||
static void add_item_to_scope_(struct __vpiScope*scope, automatic_hooks_s*item)
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
// there is no need to record items for static scopes
|
||||
if (!scope->is_automatic) return;
|
||||
|
||||
unsigned idx = scope->nitem++;
|
||||
item->context_idx = 1 + idx;
|
||||
|
||||
if (scope->item == 0)
|
||||
scope->item = (automatic_hooks_s**)
|
||||
malloc(sizeof(automatic_hooks_s*));
|
||||
else
|
||||
scope->item = (automatic_hooks_s**)
|
||||
realloc(scope->item, sizeof(automatic_hooks_s*)*scope->nitem);
|
||||
|
||||
scope->item[idx] = item;
|
||||
}
|
||||
|
||||
/*
|
||||
* When the compiler encounters a scope declaration, this function
|
||||
* creates and initializes a __vpiScope object with the requested name
|
||||
|
|
@ -392,7 +372,8 @@ compile_scope_decl(char*label, char*type, char*name, const char*tname,
|
|||
scope->nintern = 0;
|
||||
scope->item = 0;
|
||||
scope->nitem = 0;
|
||||
scope->free_context = 0;
|
||||
scope->live_contexts = 0;
|
||||
scope->free_contexts = 0;
|
||||
scope->threads = 0;
|
||||
|
||||
current_scope = scope;
|
||||
|
|
@ -415,6 +396,10 @@ compile_scope_decl(char*label, char*type, char*name, const char*tname,
|
|||
scope->time_units = sp->time_units;
|
||||
scope->time_precision = sp->time_precision;
|
||||
|
||||
/* Scopes within automatic scopes are themselves automatic. */
|
||||
if (sp->is_automatic)
|
||||
scope->is_automatic = true;
|
||||
|
||||
} else {
|
||||
scope->scope = 0x0;
|
||||
|
||||
|
|
@ -458,7 +443,38 @@ void vpip_attach_to_current_scope(vpiHandle obj)
|
|||
attach_to_scope_(current_scope, obj);
|
||||
}
|
||||
|
||||
void vpip_add_item_to_current_scope(automatic_hooks_s*item)
|
||||
struct __vpiScope* vpip_peek_context_scope(void)
|
||||
{
|
||||
add_item_to_scope_(current_scope, item);
|
||||
struct __vpiScope*scope = current_scope;
|
||||
|
||||
/* A context is allocated for each automatic task or function.
|
||||
Storage for nested scopes (named blocks) is allocated in
|
||||
the parent context. */
|
||||
while (scope->scope && scope->scope->is_automatic)
|
||||
scope = scope->scope;
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
unsigned vpip_add_item_to_context(automatic_hooks_s*item,
|
||||
struct __vpiScope*scope)
|
||||
{
|
||||
assert(scope);
|
||||
assert(scope->is_automatic);
|
||||
|
||||
unsigned idx = scope->nitem++;
|
||||
|
||||
if (scope->item == 0)
|
||||
scope->item = (automatic_hooks_s**)
|
||||
malloc(sizeof(automatic_hooks_s*));
|
||||
else
|
||||
scope->item = (automatic_hooks_s**)
|
||||
realloc(scope->item, sizeof(automatic_hooks_s*)*scope->nitem);
|
||||
|
||||
scope->item[idx] = item;
|
||||
|
||||
/* Offset the context index by 2 to leave space for the list links. */
|
||||
return 2 + idx;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -531,6 +531,8 @@ static int signal_get(int code, vpiHandle ref)
|
|||
case vpiLeftRange: return rfp->msb;
|
||||
case vpiRightRange: return rfp->lsb;
|
||||
|
||||
case vpiAutomatic: return rfp->is_automatic;
|
||||
|
||||
case _vpiNexusId:
|
||||
if (rfp->msb == rfp->lsb)
|
||||
return (int) (unsigned long) rfp->node;
|
||||
|
|
@ -765,7 +767,7 @@ static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp, int flags)
|
|||
port-0. This is the port where signals receive input. */
|
||||
vvp_net_ptr_t destination (rfp->node, dest_port);
|
||||
|
||||
vvp_send_vec4(destination, val);
|
||||
vvp_send_vec4(destination, val, vthread_get_wt_context());
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
|
@ -861,6 +863,7 @@ vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_net_t*vec)
|
|||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
||||
obj->vpi_type = &vpip_reg_rt;
|
||||
rfp->isint_ = true;
|
||||
rfp->is_automatic = vpip_peek_current_scope()->is_automatic;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -871,7 +874,9 @@ vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
|
|||
bool signed_flag, vvp_net_t*vec)
|
||||
{
|
||||
vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
|
||||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
||||
obj->vpi_type = &vpip_reg_rt;
|
||||
rfp->is_automatic = vpip_peek_current_scope()->is_automatic;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -910,6 +915,7 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
|||
obj->signed_flag = signed_flag? 1 : 0;
|
||||
obj->isint_ = 0;
|
||||
obj->is_netarray = 0;
|
||||
obj->is_automatic = vpip_peek_current_scope()->is_automatic;
|
||||
obj->node = node;
|
||||
|
||||
// Place this object within a scope. If this object is
|
||||
|
|
@ -1100,9 +1106,10 @@ static vpiHandle PV_put_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
vvp_net_ptr_t dest(rfp->net, 0);
|
||||
|
||||
if (full_sig) {
|
||||
vvp_send_vec4(dest, val);
|
||||
vvp_send_vec4(dest, val, vthread_get_wt_context());
|
||||
} else {
|
||||
vvp_send_vec4_pv(dest, val, base, width, sig_size);
|
||||
vvp_send_vec4_pv(dest, val, base, width, sig_size,
|
||||
vthread_get_wt_context());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -403,7 +403,7 @@ static vpiHandle sysfunc_put_4net_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
assert(0);
|
||||
}
|
||||
|
||||
vvp_send_vec4(rfp->fnet->out, val);
|
||||
vvp_send_vec4(rfp->fnet->out, val, vthread_get_wt_context());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -427,7 +427,7 @@ static vpiHandle sysfunc_put_rnet_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
assert(0);
|
||||
}
|
||||
|
||||
vvp_send_real(rfp->fnet->out, val);
|
||||
vvp_send_real(rfp->fnet->out, val, vthread_get_wt_context());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
131
vvp/vthread.cc
131
vvp/vthread.cc
|
|
@ -303,15 +303,16 @@ static void multiply_array_imm(unsigned long*res, unsigned long*val,
|
|||
|
||||
/*
|
||||
* Allocate a context for use by a child thread. By preference, use
|
||||
* the last freed context. If none available, create a new one.
|
||||
* the last freed context. If none available, create a new one. Add
|
||||
* it to the list of live contexts in that scope.
|
||||
*/
|
||||
static vvp_context_t vthread_alloc_context(__vpiScope*scope)
|
||||
static vvp_context_t vthread_alloc_context(struct __vpiScope*scope)
|
||||
{
|
||||
assert(scope->is_automatic);
|
||||
|
||||
vvp_context_t context = scope->free_context;
|
||||
vvp_context_t context = scope->free_contexts;
|
||||
if (context) {
|
||||
scope->free_context = vvp_get_next_context(context);
|
||||
scope->free_contexts = vvp_get_next_context(context);
|
||||
for (unsigned idx = 0 ; idx < scope->nitem ; idx += 1) {
|
||||
scope->item[idx]->reset_instance(context);
|
||||
}
|
||||
|
|
@ -322,20 +323,35 @@ static vvp_context_t vthread_alloc_context(__vpiScope*scope)
|
|||
}
|
||||
}
|
||||
|
||||
vvp_set_next_context(context, scope->live_contexts);
|
||||
scope->live_contexts = context;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a context previously allocated to a child thread by pushing it
|
||||
* onto the freed context stack.
|
||||
* onto the freed context stack. Remove it from the list of live contexts
|
||||
* in that scope.
|
||||
*/
|
||||
static void vthread_free_context(vvp_context_t context, __vpiScope*scope)
|
||||
static void vthread_free_context(vvp_context_t context, struct __vpiScope*scope)
|
||||
{
|
||||
assert(scope->is_automatic);
|
||||
assert(context);
|
||||
|
||||
vvp_set_next_context(context, scope->free_context);
|
||||
scope->free_context = context;
|
||||
if (context == scope->live_contexts) {
|
||||
scope->live_contexts = vvp_get_next_context(context);
|
||||
} else {
|
||||
vvp_context_t tmp = scope->live_contexts;
|
||||
while (context != vvp_get_next_context(tmp)) {
|
||||
assert(tmp);
|
||||
tmp = vvp_get_next_context(tmp);
|
||||
}
|
||||
vvp_set_next_context(tmp, vvp_get_next_context(context));
|
||||
}
|
||||
|
||||
vvp_set_next_context(context, scope->free_contexts);
|
||||
scope->free_contexts = context;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -530,6 +546,22 @@ void vthread_schedule_list(vthread_t thr)
|
|||
schedule_vthread(thr, 0);
|
||||
}
|
||||
|
||||
vvp_context_t vthread_get_wt_context()
|
||||
{
|
||||
if (running_thread)
|
||||
return running_thread->wt_context;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
vvp_context_t vthread_get_rd_context()
|
||||
{
|
||||
if (running_thread)
|
||||
return running_thread->rd_context;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
vvp_context_item_t vthread_get_wt_context_item(unsigned context_idx)
|
||||
{
|
||||
assert(running_thread && running_thread->wt_context);
|
||||
|
|
@ -557,7 +589,7 @@ bool of_ALLOC(vthread_t thr, vvp_code_t cp)
|
|||
vvp_context_t child_context = vthread_alloc_context(cp->scope);
|
||||
|
||||
/* Push the allocated context onto the write context stack. */
|
||||
vvp_set_next_context(child_context, thr->wt_context);
|
||||
vvp_set_stacked_context(child_context, thr->wt_context);
|
||||
thr->wt_context = child_context;
|
||||
|
||||
return true;
|
||||
|
|
@ -1205,7 +1237,7 @@ bool of_CASSIGN_V(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
/* set the value into port 1 of the destination. */
|
||||
vvp_net_ptr_t ptr (net, 1);
|
||||
vvp_send_vec4(ptr, value);
|
||||
vvp_send_vec4(ptr, value, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1217,7 +1249,7 @@ bool of_CASSIGN_WR(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
/* Set the value into port 1 of the destination. */
|
||||
vvp_net_ptr_t ptr (net, 1);
|
||||
vvp_send_real(ptr, value);
|
||||
vvp_send_real(ptr, value, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1251,7 +1283,7 @@ bool of_CASSIGN_X0(vthread_t thr, vvp_code_t cp)
|
|||
vvp_vector4_t vector = vthread_bits_to_vector(thr, base, wid);
|
||||
|
||||
vvp_net_ptr_t ptr (net, 1);
|
||||
vvp_send_vec4_pv(ptr, vector, index, wid, sig->size());
|
||||
vvp_send_vec4_pv(ptr, vector, index, wid, sig->size(), 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2315,7 +2347,7 @@ bool of_FORCE_V(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
/* Set the value into port 2 of the destination. */
|
||||
vvp_net_ptr_t ptr (net, 2);
|
||||
vvp_send_vec4(ptr, value);
|
||||
vvp_send_vec4(ptr, value, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2327,7 +2359,7 @@ bool of_FORCE_WR(vthread_t thr, vvp_code_t cp)
|
|||
|
||||
/* Set the value into port 2 of the destination. */
|
||||
vvp_net_ptr_t ptr (net, 2);
|
||||
vvp_send_real(ptr, value);
|
||||
vvp_send_real(ptr, value, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2362,7 +2394,7 @@ bool of_FORCE_X0(vthread_t thr, vvp_code_t cp)
|
|||
vvp_vector4_t vector = vthread_bits_to_vector(thr, base, wid);
|
||||
|
||||
vvp_net_ptr_t ptr (net, 2);
|
||||
vvp_send_vec4_pv(ptr, vector, index, wid, sig->size());
|
||||
vvp_send_vec4_pv(ptr, vector, index, wid, sig->size(), 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2410,7 +2442,7 @@ bool of_FREE(vthread_t thr, vvp_code_t cp)
|
|||
{
|
||||
/* Pop the child context from the read context stack. */
|
||||
vvp_context_t child_context = thr->rd_context;
|
||||
thr->rd_context = vvp_get_next_context(child_context);
|
||||
thr->rd_context = vvp_get_stacked_context(child_context);
|
||||
|
||||
/* Free the context. */
|
||||
vthread_free_context(child_context, cp->scope);
|
||||
|
|
@ -2701,10 +2733,10 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
|
|||
if (thr->wt_context != thr->rd_context) {
|
||||
/* Pop the child context from the write context stack. */
|
||||
vvp_context_t child_context = thr->wt_context;
|
||||
thr->wt_context = vvp_get_next_context(child_context);
|
||||
thr->wt_context = vvp_get_stacked_context(child_context);
|
||||
|
||||
/* Push the child context onto the read context stack */
|
||||
vvp_set_next_context(child_context, thr->rd_context);
|
||||
vvp_set_stacked_context(child_context, thr->rd_context);
|
||||
thr->rd_context = child_context;
|
||||
}
|
||||
|
||||
|
|
@ -2720,6 +2752,20 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* %load/ar <bit>, <array-label>, <index>;
|
||||
*/
|
||||
bool of_LOAD_AR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
unsigned idx = cp->bit_idx[1];
|
||||
unsigned adr = thr->words[idx].w_int;
|
||||
|
||||
double word = array_get_word_r(cp->array, adr);
|
||||
thr->words[bit].w_real = word;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %load/av <bit>, <array-label>, <wid> ;
|
||||
*
|
||||
|
|
@ -3904,6 +3950,24 @@ bool of_RELEASE_WR(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %set/av <label>, <index>, <bit>
|
||||
*
|
||||
* Write the real value in register <bit> to the array indexed by the
|
||||
* integer value addressed bin index register <index>.
|
||||
*/
|
||||
bool of_SET_AR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned idx = cp->bit_idx[0];
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
unsigned adr = thr->words[idx].w_int;
|
||||
|
||||
double value = thr->words[bit].w_real;
|
||||
array_set_word(cp->array, adr, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This implements the "%set/av <label>, <bit>, <wid>" instruction. In
|
||||
* this case, the <label> is an array label, and the <bit> and <wid>
|
||||
|
|
@ -3944,19 +4008,18 @@ bool of_SET_VEC(vthread_t thr, vvp_code_t cp)
|
|||
/* set the value into port 0 of the destination. */
|
||||
vvp_net_ptr_t ptr (cp->net, 0);
|
||||
|
||||
vvp_send_vec4(ptr, vthread_bits_to_vector(thr, bit, wid));
|
||||
vvp_send_vec4(ptr, vthread_bits_to_vector(thr, bit, wid),
|
||||
thr->wt_context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_SET_WORDR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
struct __vpiHandle*tmp = cp->handle;
|
||||
t_vpi_value val;
|
||||
/* set the value into port 0 of the destination. */
|
||||
vvp_net_ptr_t ptr (cp->net, 0);
|
||||
|
||||
val.format = vpiRealVal;
|
||||
val.value.real = thr->words[cp->bit_idx[0]].w_real;
|
||||
vpi_put_value(tmp, &val, 0, vpiNoDelay);
|
||||
vvp_send_real(ptr, thr->words[cp->bit_idx[0]].w_real, thr->wt_context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -4015,7 +4078,7 @@ bool of_SET_X0(vthread_t thr, vvp_code_t cp)
|
|||
}
|
||||
|
||||
vvp_net_ptr_t ptr (net, 0);
|
||||
vvp_send_vec4_pv(ptr, bit_vec, index, wid, sig->size());
|
||||
vvp_send_vec4_pv(ptr, bit_vec, index, wid, sig->size(), thr->wt_context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -4201,18 +4264,10 @@ bool of_WAIT(vthread_t thr, vvp_code_t cp)
|
|||
thr->waiting_for_event = 1;
|
||||
|
||||
/* Add this thread to the list in the event. */
|
||||
vvp_net_fun_t*fun = cp->net->fun;
|
||||
if (fun->context_idx) {
|
||||
waitable_state_s*es = static_cast<waitable_state_s*>
|
||||
(vthread_get_wt_context_item(fun->context_idx));
|
||||
thr->wait_next = es->threads;
|
||||
es->threads = thr;
|
||||
} else {
|
||||
waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (fun);
|
||||
assert(ep);
|
||||
thr->wait_next = ep->threads;
|
||||
ep->threads = thr;
|
||||
}
|
||||
waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (cp->net->fun);
|
||||
assert(ep);
|
||||
thr->wait_next = ep->add_waiting_thread(thr);
|
||||
|
||||
/* Return false to suspend this thread. */
|
||||
return false;
|
||||
}
|
||||
|
|
@ -4316,7 +4371,7 @@ bool of_EXEC_UFUNC(vthread_t thr, vvp_code_t cp)
|
|||
/* Copy all the inputs to the ufunc object to the port
|
||||
variables of the function. This copies all the values
|
||||
atomically. */
|
||||
cp->ufunc_core_ptr->assign_bits_to_ports();
|
||||
cp->ufunc_core_ptr->assign_bits_to_ports(child_context);
|
||||
|
||||
/* Create a temporary thread and run it immediately. A function
|
||||
may not contain any blocking statements, so vthread_run() can
|
||||
|
|
|
|||
|
|
@ -62,27 +62,37 @@ extern void vthread_run(vthread_t thr);
|
|||
*/
|
||||
extern void vthread_schedule_list(vthread_t thr);
|
||||
|
||||
/*
|
||||
* This function returns a handle to the writable context of the currently
|
||||
* running thread. Normally the writable context is the context allocated
|
||||
* to the scope associated with that thread. However, between executing a
|
||||
* %alloc instruction and executing the associated %fork instruction, the
|
||||
* writable context changes to the newly allocated context, thus allowing
|
||||
* the input parameters of an automatic task or function to be written to
|
||||
* the task/function local variables.
|
||||
*/
|
||||
extern vvp_context_t vthread_get_wt_context();
|
||||
|
||||
/*
|
||||
* This function returns a handle to the readable context of the currently
|
||||
* running thread. Normally the readable context is the context allocated
|
||||
* to the scope associated with that thread. However, between executing a
|
||||
* %join instruction and executing the associated %free instruction, the
|
||||
* readable context changes to the context allocated to the newly joined
|
||||
* thread, thus allowing the output parameters of an automatic task or
|
||||
* function to be read from the task/function local variables.
|
||||
*/
|
||||
extern vvp_context_t vthread_get_rd_context();
|
||||
|
||||
/*
|
||||
* This function returns a handle to an item in the writable context
|
||||
* of the currently running thread. Normally the writable context is
|
||||
* the context allocated to the scope associated with that thread.
|
||||
* However, between executing a %alloc instruction and executing the
|
||||
* associated %fork instruction, the writable context changes to the
|
||||
* newly allocated context, thus allowing the input parameters of an
|
||||
* automatic task or function to be written to the task/function local
|
||||
* variables.
|
||||
* of the currently running thread.
|
||||
*/
|
||||
extern vvp_context_item_t vthread_get_wt_context_item(unsigned context_idx);
|
||||
|
||||
/*
|
||||
* This function returns a handle to an item in the readable context
|
||||
* of the currently running thread. Normally the readable context is
|
||||
* the context allocated to the scope associated with that thread.
|
||||
* However, between executing a %join instruction and executing the
|
||||
* associated %free instruction, the readable context changes to the
|
||||
* context allocated to the newly joined thread, thus allowing the
|
||||
* output parameters of an automatic task or function to be read from
|
||||
* the task/function local variables.
|
||||
* of the currently running thread.
|
||||
*/
|
||||
extern vvp_context_item_t vthread_get_rd_context_item(unsigned context_idx);
|
||||
|
||||
|
|
|
|||
|
|
@ -124,9 +124,11 @@ class vvp_island_port : public vvp_net_fun_t {
|
|||
explicit vvp_island_port(vvp_island*ip);
|
||||
~vvp_island_port();
|
||||
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
virtual void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t);
|
||||
virtual void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
|
||||
vvp_vector8_t invalue;
|
||||
|
|
@ -309,13 +311,15 @@ vvp_island_port::~vvp_island_port()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_island_port::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_island_port::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
recv_vec8(port, vvp_vector8_t(bit, 6, 6));
|
||||
}
|
||||
|
||||
void vvp_island_port::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
vvp_vector8_t tmp(bit, 6, 6);
|
||||
if (invalue.size()==0) {
|
||||
|
|
|
|||
574
vvp/vvp_net.cc
574
vvp/vvp_net.cc
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
# include "config.h"
|
||||
# include "vvp_net.h"
|
||||
# include "vpi_priv.h"
|
||||
# include "schedule.h"
|
||||
# include "statistics.h"
|
||||
# include <stdio.h>
|
||||
|
|
@ -227,13 +228,13 @@ void vvp_send_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&val)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_send_real(vvp_net_ptr_t ptr, double val)
|
||||
void vvp_send_real(vvp_net_ptr_t ptr, double val, vvp_context_t context)
|
||||
{
|
||||
while (struct vvp_net_t*cur = ptr.ptr()) {
|
||||
vvp_net_ptr_t next = cur->port[ptr.port()];
|
||||
|
||||
if (cur->fun)
|
||||
cur->fun->recv_real(ptr, val);
|
||||
cur->fun->recv_real(ptr, val, context);
|
||||
|
||||
ptr = next;
|
||||
}
|
||||
|
|
@ -1298,12 +1299,91 @@ bool vector4_to_value(const vvp_vector4_t&vec, double&val, bool signed_flag)
|
|||
return flag;
|
||||
}
|
||||
|
||||
vvp_vector4array_t::vvp_vector4array_t(unsigned width__, unsigned words__,
|
||||
bool is_automatic)
|
||||
: width_(width__), words_(words__), array_(0)
|
||||
vvp_realarray_t::vvp_realarray_t(unsigned wor)
|
||||
: words_(wor)
|
||||
{
|
||||
if (is_automatic) return;
|
||||
array_ = new double[words_];
|
||||
}
|
||||
|
||||
vvp_realarray_t::~vvp_realarray_t()
|
||||
{
|
||||
delete[]array_;
|
||||
}
|
||||
|
||||
void vvp_realarray_t::set_word(unsigned word, double value)
|
||||
{
|
||||
if (word >= words_)
|
||||
return;
|
||||
array_[word] = value;
|
||||
}
|
||||
|
||||
double vvp_realarray_t::get_word(unsigned word) const
|
||||
{
|
||||
if (word >= words_)
|
||||
return 0.0;
|
||||
else
|
||||
return array_[word];
|
||||
}
|
||||
|
||||
vvp_vector4array_t::vvp_vector4array_t(unsigned width__, unsigned words__)
|
||||
: width_(width__), words_(words__)
|
||||
{
|
||||
}
|
||||
|
||||
vvp_vector4array_t::~vvp_vector4array_t()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_vector4array_t::set_word_(v4cell*cell, const vvp_vector4_t&that)
|
||||
{
|
||||
assert(that.size_ == width_);
|
||||
|
||||
if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
|
||||
cell->abits_val_ = that.abits_val_;
|
||||
cell->bbits_val_ = that.bbits_val_;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned cnt = (width_ + vvp_vector4_t::BITS_PER_WORD-1)/vvp_vector4_t::BITS_PER_WORD;
|
||||
|
||||
if (cell->abits_ptr_ == 0) {
|
||||
cell->abits_ptr_ = new unsigned long[2*cnt];
|
||||
cell->bbits_ptr_ = cell->abits_ptr_ + cnt;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
cell->abits_ptr_[idx] = that.abits_ptr_[idx];
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
cell->bbits_ptr_[idx] = that.bbits_ptr_[idx];
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_vector4array_t::get_word_(v4cell*cell) const
|
||||
{
|
||||
if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
|
||||
vvp_vector4_t res;
|
||||
res.size_ = width_;
|
||||
res.abits_val_ = cell->abits_val_;
|
||||
res.bbits_val_ = cell->bbits_val_;
|
||||
return res;
|
||||
}
|
||||
|
||||
vvp_vector4_t res (width_, BIT4_X);
|
||||
if (cell->abits_ptr_ == 0)
|
||||
return res;
|
||||
|
||||
unsigned cnt = (width_ + vvp_vector4_t::BITS_PER_WORD-1)/vvp_vector4_t::BITS_PER_WORD;
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
res.abits_ptr_[idx] = cell->abits_ptr_[idx];
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
res.bbits_ptr_[idx] = cell->bbits_ptr_[idx];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
vvp_vector4array_sa::vvp_vector4array_sa(unsigned width__, unsigned words__)
|
||||
: vvp_vector4array_t(width__, words__)
|
||||
{
|
||||
array_ = new v4cell[words_];
|
||||
|
||||
if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
|
||||
|
|
@ -1319,7 +1399,7 @@ vvp_vector4array_t::vvp_vector4array_t(unsigned width__, unsigned words__,
|
|||
}
|
||||
}
|
||||
|
||||
vvp_vector4array_t::~vvp_vector4array_t()
|
||||
vvp_vector4array_sa::~vvp_vector4array_sa()
|
||||
{
|
||||
if (array_) {
|
||||
if (width_ > vvp_vector4_t::BITS_PER_WORD) {
|
||||
|
|
@ -1331,7 +1411,38 @@ vvp_vector4array_t::~vvp_vector4array_t()
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_vector4array_t::alloc_instance(vvp_context_t context)
|
||||
void vvp_vector4array_sa::set_word(unsigned index, const vvp_vector4_t&that)
|
||||
{
|
||||
assert(index < words_);
|
||||
|
||||
v4cell*cell = &array_[index];
|
||||
|
||||
set_word_(cell, that);
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_vector4array_sa::get_word(unsigned index) const
|
||||
{
|
||||
if (index >= words_)
|
||||
return vvp_vector4_t(width_, BIT4_X);
|
||||
|
||||
assert(index < words_);
|
||||
|
||||
v4cell*cell = &array_[index];
|
||||
|
||||
return get_word_(cell);
|
||||
}
|
||||
|
||||
vvp_vector4array_aa::vvp_vector4array_aa(unsigned width__, unsigned words__)
|
||||
: vvp_vector4array_t(width__, words__)
|
||||
{
|
||||
context_idx_ = vpip_add_item_to_context(this, vpip_peek_context_scope());
|
||||
}
|
||||
|
||||
vvp_vector4array_aa::~vvp_vector4array_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_vector4array_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
v4cell*array = new v4cell[words_];
|
||||
|
||||
|
|
@ -1347,13 +1458,13 @@ void vvp_vector4array_t::alloc_instance(vvp_context_t context)
|
|||
}
|
||||
}
|
||||
|
||||
vvp_set_context_item(context, context_idx, array);
|
||||
vvp_set_context_item(context, context_idx_, array);
|
||||
}
|
||||
|
||||
void vvp_vector4array_t::reset_instance(vvp_context_t context)
|
||||
void vvp_vector4array_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
v4cell*cell = static_cast<v4cell*>
|
||||
(vvp_get_context_item(context, context_idx));
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
|
||||
for (unsigned idx = 0 ; idx < words_ ; idx += 1) {
|
||||
|
|
@ -1375,72 +1486,27 @@ void vvp_vector4array_t::reset_instance(vvp_context_t context)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_vector4array_t::set_word(unsigned index, const vvp_vector4_t&that)
|
||||
void vvp_vector4array_aa::set_word(unsigned index, const vvp_vector4_t&that)
|
||||
{
|
||||
assert(index < words_);
|
||||
assert(that.size_ == width_);
|
||||
|
||||
v4cell*cell;
|
||||
if (context_idx)
|
||||
cell = static_cast<v4cell*>
|
||||
(vthread_get_wt_context_item(context_idx)) + index;
|
||||
else
|
||||
cell = &(array_[index]);
|
||||
v4cell*cell = static_cast<v4cell*>
|
||||
(vthread_get_wt_context_item(context_idx_)) + index;
|
||||
|
||||
if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
|
||||
cell->abits_val_ = that.abits_val_;
|
||||
cell->bbits_val_ = that.bbits_val_;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned cnt = (width_ + vvp_vector4_t::BITS_PER_WORD-1)/vvp_vector4_t::BITS_PER_WORD;
|
||||
|
||||
if (cell->abits_ptr_ == 0) {
|
||||
cell->abits_ptr_ = new unsigned long[2*cnt];
|
||||
cell->bbits_ptr_ = cell->abits_ptr_ + cnt;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
cell->abits_ptr_[idx] = that.abits_ptr_[idx];
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
cell->bbits_ptr_[idx] = that.bbits_ptr_[idx];
|
||||
set_word_(cell, that);
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_vector4array_t::get_word(unsigned index) const
|
||||
vvp_vector4_t vvp_vector4array_aa::get_word(unsigned index) const
|
||||
{
|
||||
if (index >= words_)
|
||||
return vvp_vector4_t(width_, BIT4_X);
|
||||
|
||||
assert(index < words_);
|
||||
|
||||
v4cell*cell;
|
||||
if (context_idx)
|
||||
cell = static_cast<v4cell*>
|
||||
(vthread_get_rd_context_item(context_idx)) + index;
|
||||
else
|
||||
cell = &(array_[index]);
|
||||
|
||||
if (width_ <= vvp_vector4_t::BITS_PER_WORD) {
|
||||
vvp_vector4_t res;
|
||||
res.size_ = width_;
|
||||
res.abits_val_ = cell->abits_val_;
|
||||
res.bbits_val_ = cell->bbits_val_;
|
||||
return res;
|
||||
}
|
||||
|
||||
vvp_vector4_t res (width_, BIT4_X);
|
||||
if (cell->abits_ptr_ == 0)
|
||||
return res;
|
||||
|
||||
unsigned cnt = (width_ + vvp_vector4_t::BITS_PER_WORD-1)/vvp_vector4_t::BITS_PER_WORD;
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
res.abits_ptr_[idx] = cell->abits_ptr_[idx];
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
res.bbits_ptr_[idx] = cell->bbits_ptr_[idx];
|
||||
|
||||
return res;
|
||||
v4cell*cell = static_cast<v4cell*>
|
||||
(vthread_get_rd_context_item(context_idx_)) + index;
|
||||
|
||||
return get_word_(cell);
|
||||
}
|
||||
|
||||
template <class T> T coerce_to_width(const T&that, unsigned width)
|
||||
|
|
@ -2257,15 +2323,17 @@ vvp_net_fun_t::~vvp_net_fun_t()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_net_fun_t::recv_vec4(vvp_net_ptr_t, const vvp_vector4_t&)
|
||||
void vvp_net_fun_t::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
fprintf(stderr, "internal error: %s: recv_vec4 not implemented\n",
|
||||
typeid(*this).name());
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_net_fun_t::recv_vec4_pv(vvp_net_ptr_t, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
void vvp_net_fun_t::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
cerr << "internal error: " << typeid(*this).name() << ": "
|
||||
<< "recv_vec4_pv(" << bit << ", " << base
|
||||
|
|
@ -2273,18 +2341,18 @@ void vvp_net_fun_t::recv_vec4_pv(vvp_net_ptr_t, const vvp_vector4_t&bit,
|
|||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_net_fun_t::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
||||
{
|
||||
recv_vec4(port, reduce4(bit), 0);
|
||||
}
|
||||
|
||||
void vvp_net_fun_t::recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
{
|
||||
recv_vec4_pv(port, reduce4(bit), base, wid, vwid);
|
||||
recv_vec4_pv(port, reduce4(bit), base, wid, vwid, 0);
|
||||
}
|
||||
|
||||
void vvp_net_fun_t::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
||||
{
|
||||
recv_vec4(port, reduce4(bit));
|
||||
}
|
||||
|
||||
void vvp_net_fun_t::recv_real(vvp_net_ptr_t, double bit)
|
||||
void vvp_net_fun_t::recv_real(vvp_net_ptr_t port, double bit, vvp_context_t)
|
||||
{
|
||||
fprintf(stderr, "internal error: %s: recv_real(%f) not implemented\n",
|
||||
typeid(*this).name(), bit);
|
||||
|
|
@ -2320,7 +2388,8 @@ vvp_fun_drive::~vvp_fun_drive()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_drive::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_drive::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(port.port() == 0);
|
||||
vvp_send_vec8(port.ptr()->out, vvp_vector8_t(bit, drive0_, drive1_));
|
||||
|
|
@ -2416,26 +2485,11 @@ void vvp_fun_signal_base::recv_long_pv(vvp_net_ptr_t ptr, long bit,
|
|||
}
|
||||
}
|
||||
|
||||
vvp_fun_signal::vvp_fun_signal(unsigned wid, vvp_bit4_t init)
|
||||
vvp_fun_signal4_sa::vvp_fun_signal4_sa(unsigned wid, vvp_bit4_t init)
|
||||
: bits4_(wid, init)
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_signal::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
unsigned wid = bits4_.size();
|
||||
|
||||
vvp_set_context_item(context, context_idx, new vvp_vector4_t(wid));
|
||||
}
|
||||
|
||||
void vvp_fun_signal::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_vector4_t*bits = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx));
|
||||
|
||||
bits->set_to_x();
|
||||
}
|
||||
|
||||
/*
|
||||
* Nets simply reflect their input to their output.
|
||||
*
|
||||
|
|
@ -2447,12 +2501,9 @@ void vvp_fun_signal::reset_instance(vvp_context_t context)
|
|||
* herein is to keep a "needs_init_" flag that is turned false after
|
||||
* the first propagation, and forces the first propagation to happen
|
||||
* even if it matches the initial value.
|
||||
*
|
||||
* Continuous and forced assignments are not permitted on automatic
|
||||
* variables. So we only need incur the overhead of checking for an
|
||||
* automatic variable when we are doing a normal unmasked assign.
|
||||
*/
|
||||
void vvp_fun_signal::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_signal4_sa::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
switch (ptr.port()) {
|
||||
case 0: // Normal input (feed from net, or set from process)
|
||||
|
|
@ -2460,15 +2511,8 @@ void vvp_fun_signal::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
copy the bits, otherwise we need to see if there are
|
||||
any holes in the mask so we can set those bits. */
|
||||
if (assign_mask_.size() == 0) {
|
||||
vvp_vector4_t*bits4;
|
||||
if (context_idx) {
|
||||
bits4 = static_cast<vvp_vector4_t*>
|
||||
(vthread_get_wt_context_item(context_idx));
|
||||
} else {
|
||||
bits4 = &bits4_;
|
||||
}
|
||||
if (needs_init_ || !bits4->eeq(bit)) {
|
||||
*bits4 = bit;
|
||||
if (needs_init_ || !bits4_.eeq(bit)) {
|
||||
bits4_ = bit;
|
||||
needs_init_ = false;
|
||||
calculate_output_(ptr);
|
||||
}
|
||||
|
|
@ -2514,8 +2558,14 @@ void vvp_fun_signal::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
void vvp_fun_signal4_sa::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
{
|
||||
recv_vec4(ptr, reduce4(bit), 0);
|
||||
}
|
||||
|
||||
void vvp_fun_signal4_sa::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(bit.size() == wid);
|
||||
assert(bits4_.size() == vwid);
|
||||
|
|
@ -2523,16 +2573,9 @@ void vvp_fun_signal::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
switch (ptr.port()) {
|
||||
case 0: // Normal input
|
||||
if (assign_mask_.size() == 0) {
|
||||
vvp_vector4_t*bits4;
|
||||
if (context_idx) {
|
||||
bits4 = static_cast<vvp_vector4_t*>
|
||||
(vthread_get_wt_context_item(context_idx));
|
||||
} else {
|
||||
bits4 = &bits4_;
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
if (base+idx >= bits4->size()) break;
|
||||
bits4->set_bit(base+idx, bit.value(idx));
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
if (base+idx >= bits4_.size()) break;
|
||||
bits4_.set_bit(base+idx, bit.value(idx));
|
||||
}
|
||||
needs_init_ = false;
|
||||
calculate_output_(ptr);
|
||||
|
|
@ -2586,13 +2629,13 @@ void vvp_fun_signal::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
void vvp_fun_signal4_sa::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
{
|
||||
recv_vec4_pv(ptr, reduce4(bit), base, wid, vwid);
|
||||
recv_vec4_pv(ptr, reduce4(bit), base, wid, vwid, 0);
|
||||
}
|
||||
|
||||
void vvp_fun_signal::calculate_output_(vvp_net_ptr_t ptr)
|
||||
void vvp_fun_signal4_sa::calculate_output_(vvp_net_ptr_t ptr)
|
||||
{
|
||||
if (force_mask_.size()) {
|
||||
assert(bits4_.size() == force_mask_.size());
|
||||
|
|
@ -2602,37 +2645,27 @@ void vvp_fun_signal::calculate_output_(vvp_net_ptr_t ptr)
|
|||
if (force_mask_.value(idx))
|
||||
bits.set_bit(idx, force_.value(idx));
|
||||
}
|
||||
vvp_send_vec4(ptr.ptr()->out, bits);
|
||||
} else if (context_idx) {
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vthread_get_wt_context_item(context_idx));
|
||||
vvp_send_vec4(ptr.ptr()->out, *bits4);
|
||||
vvp_send_vec4(ptr.ptr()->out, bits, 0);
|
||||
} else {
|
||||
vvp_send_vec4(ptr.ptr()->out, bits4_);
|
||||
vvp_send_vec4(ptr.ptr()->out, bits4_, 0);
|
||||
}
|
||||
|
||||
run_vpi_callbacks();
|
||||
}
|
||||
|
||||
void vvp_fun_signal::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
{
|
||||
recv_vec4(ptr, reduce4(bit));
|
||||
}
|
||||
|
||||
|
||||
void vvp_fun_signal::release(vvp_net_ptr_t ptr, bool net)
|
||||
void vvp_fun_signal4_sa::release(vvp_net_ptr_t ptr, bool net)
|
||||
{
|
||||
force_mask_ = vvp_vector2_t();
|
||||
if (net) {
|
||||
vvp_send_vec4(ptr.ptr()->out, bits4_);
|
||||
vvp_send_vec4(ptr.ptr()->out, bits4_, 0);
|
||||
run_vpi_callbacks();
|
||||
} else {
|
||||
bits4_ = force_;
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal::release_pv(vvp_net_ptr_t ptr, bool net,
|
||||
unsigned base, unsigned wid)
|
||||
void vvp_fun_signal4_sa::release_pv(vvp_net_ptr_t ptr, bool net,
|
||||
unsigned base, unsigned wid)
|
||||
{
|
||||
assert(bits4_.size() >= base + wid);
|
||||
|
||||
|
|
@ -2645,7 +2678,7 @@ void vvp_fun_signal::release_pv(vvp_net_ptr_t ptr, bool net,
|
|||
if (net) calculate_output_(ptr);
|
||||
}
|
||||
|
||||
unsigned vvp_fun_signal::size() const
|
||||
unsigned vvp_fun_signal4_sa::size() const
|
||||
{
|
||||
if (force_mask_.size())
|
||||
return force_.size();
|
||||
|
|
@ -2653,33 +2686,25 @@ unsigned vvp_fun_signal::size() const
|
|||
return bits4_.size();
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_fun_signal::value(unsigned idx) const
|
||||
vvp_bit4_t vvp_fun_signal4_sa::value(unsigned idx) const
|
||||
{
|
||||
if (force_mask_.size() && force_mask_.value(idx)) {
|
||||
return force_.value(idx);
|
||||
} else if (context_idx) {
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vthread_get_rd_context_item(context_idx));
|
||||
return bits4->value(idx);
|
||||
} else {
|
||||
return bits4_.value(idx);
|
||||
}
|
||||
}
|
||||
|
||||
vvp_scalar_t vvp_fun_signal::scalar_value(unsigned idx) const
|
||||
vvp_scalar_t vvp_fun_signal4_sa::scalar_value(unsigned idx) const
|
||||
{
|
||||
if (force_mask_.size() && force_mask_.value(idx)) {
|
||||
return vvp_scalar_t(force_.value(idx), 6, 6);
|
||||
} else if (context_idx) {
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vthread_get_rd_context_item(context_idx));
|
||||
return vvp_scalar_t(bits4->value(idx), 6, 6);
|
||||
} else {
|
||||
return vvp_scalar_t(bits4_.value(idx), 6, 6);
|
||||
}
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_fun_signal::vec4_value() const
|
||||
vvp_vector4_t vvp_fun_signal4_sa::vec4_value() const
|
||||
{
|
||||
if (force_mask_.size()) {
|
||||
assert(bits4_.size() == force_mask_.size());
|
||||
|
|
@ -2690,21 +2715,117 @@ vvp_vector4_t vvp_fun_signal::vec4_value() const
|
|||
bits.set_bit(idx, force_.value(idx));
|
||||
}
|
||||
return bits;
|
||||
} else if (context_idx) {
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vthread_get_rd_context_item(context_idx));
|
||||
return *bits4;
|
||||
} else {
|
||||
return bits4_;
|
||||
}
|
||||
}
|
||||
|
||||
vvp_fun_signal4_aa::vvp_fun_signal4_aa(unsigned wid, vvp_bit4_t init)
|
||||
{
|
||||
context_idx_ = vpip_add_item_to_context(this, vpip_peek_context_scope());
|
||||
size_ = wid;
|
||||
}
|
||||
|
||||
void vvp_fun_signal4_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new vvp_vector4_t(size_));
|
||||
}
|
||||
|
||||
void vvp_fun_signal4_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_vector4_t*bits = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
bits->set_to_x();
|
||||
}
|
||||
|
||||
/*
|
||||
* Continuous and forced assignments are not permitted on automatic
|
||||
* variables. So we only expect to receive on port 0.
|
||||
*/
|
||||
void vvp_fun_signal4_aa::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
assert(ptr.port() == 0);
|
||||
assert(context);
|
||||
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (!bits4->eeq(bit)) {
|
||||
*bits4 = bit;
|
||||
vvp_send_vec4(ptr.ptr()->out, *bits4, context);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal4_aa::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context)
|
||||
{
|
||||
assert(ptr.port() == 0);
|
||||
assert(bit.size() == wid);
|
||||
assert(size_ == vwid);
|
||||
assert(context);
|
||||
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
if (base+idx >= bits4->size()) break;
|
||||
bits4->set_bit(base+idx, bit.value(idx));
|
||||
}
|
||||
vvp_send_vec4(ptr.ptr()->out, *bits4, context);
|
||||
}
|
||||
|
||||
void vvp_fun_signal4_aa::release(vvp_net_ptr_t ptr, bool net)
|
||||
{
|
||||
/* Automatic variables can't be forced. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_fun_signal4_aa::release_pv(vvp_net_ptr_t ptr, bool net,
|
||||
unsigned base, unsigned wid)
|
||||
{
|
||||
/* Automatic variables can't be forced. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
unsigned vvp_fun_signal4_aa::size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_fun_signal4_aa::value(unsigned idx) const
|
||||
{
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vthread_get_rd_context_item(context_idx_));
|
||||
|
||||
return bits4->value(idx);
|
||||
}
|
||||
|
||||
vvp_scalar_t vvp_fun_signal4_aa::scalar_value(unsigned idx) const
|
||||
{
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vthread_get_rd_context_item(context_idx_));
|
||||
|
||||
return vvp_scalar_t(bits4->value(idx), 6, 6);
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_fun_signal4_aa::vec4_value() const
|
||||
{
|
||||
vvp_vector4_t*bits4 = static_cast<vvp_vector4_t*>
|
||||
(vthread_get_rd_context_item(context_idx_));
|
||||
|
||||
return *bits4;
|
||||
}
|
||||
|
||||
vvp_fun_signal8::vvp_fun_signal8(unsigned wid)
|
||||
: bits8_(wid)
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_signal8::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_signal8::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
recv_vec8(ptr, vvp_vector8_t(bit,6,6));
|
||||
}
|
||||
|
|
@ -2748,7 +2869,8 @@ void vvp_fun_signal8::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
|||
}
|
||||
|
||||
void vvp_fun_signal8::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
recv_vec8_pv(ptr, vvp_vector8_t(bit,6,6), base, wid, vwid);
|
||||
}
|
||||
|
|
@ -2879,39 +3001,6 @@ vvp_scalar_t vvp_fun_signal8::scalar_value(unsigned idx) const
|
|||
return bits8_.value(idx);
|
||||
}
|
||||
|
||||
vvp_fun_signal_real::vvp_fun_signal_real()
|
||||
{
|
||||
bits_ = 0.0;
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
double*bits = new double;
|
||||
*bits = 0.0;
|
||||
vvp_set_context_item(context, context_idx, bits);
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real::reset_instance(vvp_context_t context)
|
||||
{
|
||||
double*bits = static_cast<double*>
|
||||
(vvp_get_context_item(context, context_idx));
|
||||
|
||||
*bits = 0.0;
|
||||
}
|
||||
|
||||
double vvp_fun_signal_real::real_value() const
|
||||
{
|
||||
if (force_mask_.size()) {
|
||||
return force_;
|
||||
} else if (context_idx) {
|
||||
double*bits = static_cast<double*>
|
||||
(vthread_get_rd_context_item(context_idx));
|
||||
return *bits;
|
||||
} else {
|
||||
return bits_;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Testing for equality, we want a bitwise test instead of an
|
||||
* arithmetic test because we want to treat for example -0 different
|
||||
|
|
@ -2922,22 +3011,29 @@ bool bits_equal(double a, double b)
|
|||
return memcmp(&a, &b, sizeof a) == 0;
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
vvp_fun_signal_real_sa::vvp_fun_signal_real_sa()
|
||||
{
|
||||
bits_ = 0.0;
|
||||
}
|
||||
|
||||
double vvp_fun_signal_real_sa::real_value() const
|
||||
{
|
||||
if (force_mask_.size())
|
||||
return force_;
|
||||
else
|
||||
return bits_;
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real_sa::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
switch (ptr.port()) {
|
||||
case 0:
|
||||
if (!continuous_assign_active_) {
|
||||
double*bits;
|
||||
if (context_idx) {
|
||||
bits = static_cast<double*>
|
||||
(vthread_get_wt_context_item(context_idx));
|
||||
} else {
|
||||
bits = &bits_;
|
||||
}
|
||||
if (needs_init_ || !bits_equal(*bits,bit)) {
|
||||
*bits = bit;
|
||||
if (needs_init_ || !bits_equal(bits_, bit)) {
|
||||
bits_ = bit;
|
||||
needs_init_ = false;
|
||||
vvp_send_real(ptr.ptr()->out, bit);
|
||||
vvp_send_real(ptr.ptr()->out, bit, 0);
|
||||
run_vpi_callbacks();
|
||||
}
|
||||
}
|
||||
|
|
@ -2946,14 +3042,14 @@ void vvp_fun_signal_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
|||
case 1: // Continuous assign value
|
||||
continuous_assign_active_ = true;
|
||||
bits_ = bit;
|
||||
vvp_send_real(ptr.ptr()->out, bit);
|
||||
vvp_send_real(ptr.ptr()->out, bit, 0);
|
||||
run_vpi_callbacks();
|
||||
break;
|
||||
|
||||
case 2: // Force value
|
||||
force_mask_ = vvp_vector2_t(1, 1);
|
||||
force_ = bit;
|
||||
vvp_send_real(ptr.ptr()->out, bit);
|
||||
vvp_send_real(ptr.ptr()->out, bit, 0);
|
||||
run_vpi_callbacks();
|
||||
break;
|
||||
|
||||
|
|
@ -2964,24 +3060,81 @@ void vvp_fun_signal_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real::release(vvp_net_ptr_t ptr, bool net)
|
||||
void vvp_fun_signal_real_sa::release(vvp_net_ptr_t ptr, bool net)
|
||||
{
|
||||
force_mask_ = vvp_vector2_t();
|
||||
if (net) {
|
||||
vvp_send_real(ptr.ptr()->out, bits_);
|
||||
vvp_send_real(ptr.ptr()->out, bits_, 0);
|
||||
run_vpi_callbacks();
|
||||
} else {
|
||||
bits_ = force_;
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real::release_pv(vvp_net_ptr_t ptr, bool net,
|
||||
unsigned base, unsigned wid)
|
||||
void vvp_fun_signal_real_sa::release_pv(vvp_net_ptr_t ptr, bool net,
|
||||
unsigned base, unsigned wid)
|
||||
{
|
||||
fprintf(stderr, "Error: cannot take bit/part select of a real value!\n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_fun_signal_real_aa::vvp_fun_signal_real_aa()
|
||||
{
|
||||
context_idx_ = vpip_add_item_to_context(this, vpip_peek_context_scope());
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
double*bits = new double;
|
||||
vvp_set_context_item(context, context_idx_, bits);
|
||||
|
||||
*bits = 0.0;
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
double*bits = static_cast<double*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
*bits = 0.0;
|
||||
}
|
||||
|
||||
double vvp_fun_signal_real_aa::real_value() const
|
||||
{
|
||||
double*bits = static_cast<double*>
|
||||
(vthread_get_rd_context_item(context_idx_));
|
||||
|
||||
return *bits;
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real_aa::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
assert(ptr.port() == 0);
|
||||
assert(context);
|
||||
|
||||
double*bits = static_cast<double*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (!bits_equal(*bits,bit)) {
|
||||
*bits = bit;
|
||||
vvp_send_real(ptr.ptr()->out, bit, context);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real_aa::release(vvp_net_ptr_t ptr, bool net)
|
||||
{
|
||||
/* Automatic variables can't be forced. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_fun_signal_real_aa::release_pv(vvp_net_ptr_t ptr, bool net,
|
||||
unsigned base, unsigned wid)
|
||||
{
|
||||
/* Automatic variables can't be forced. */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* **** vvp_wide_fun_* methods **** */
|
||||
|
||||
vvp_wide_fun_core::vvp_wide_fun_core(vvp_net_t*net, unsigned nports)
|
||||
|
|
@ -3004,7 +3157,7 @@ void vvp_wide_fun_core::propagate_vec4(const vvp_vector4_t&bit,
|
|||
if (delay)
|
||||
schedule_assign_plucked_vector(ptr_->out, delay, bit, 0, bit.size());
|
||||
else
|
||||
vvp_send_vec4(ptr_->out, bit);
|
||||
vvp_send_vec4(ptr_->out, bit, 0);
|
||||
}
|
||||
|
||||
void vvp_wide_fun_core::propagate_real(double bit,
|
||||
|
|
@ -3014,7 +3167,7 @@ void vvp_wide_fun_core::propagate_real(double bit,
|
|||
// schedule_assign_vector(ptr_->out, bit, delay);
|
||||
assert(0); // Need a real-value version of assign_vector.
|
||||
} else {
|
||||
vvp_send_real(ptr_->out, bit);
|
||||
vvp_send_real(ptr_->out, bit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3069,19 +3222,20 @@ vvp_wide_fun_t::~vvp_wide_fun_t()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_wide_fun_t::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_wide_fun_t::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
unsigned pidx = port_base_ + port.port();
|
||||
core_->dispatch_vec4_from_input_(pidx, bit);
|
||||
}
|
||||
|
||||
void vvp_wide_fun_t::recv_real(vvp_net_ptr_t port, double bit)
|
||||
void vvp_wide_fun_t::recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
unsigned pidx = port_base_ + port.port();
|
||||
core_->dispatch_real_from_input_(pidx, bit);
|
||||
}
|
||||
|
||||
|
||||
/* **** vvp_scalar_t methods **** */
|
||||
|
||||
/*
|
||||
|
|
|
|||
275
vvp/vvp_net.h
275
vvp/vvp_net.h
|
|
@ -52,7 +52,9 @@ class vvp_delay_t;
|
|||
|
||||
/*
|
||||
* Storage for items declared in automatically allocated scopes (i.e. automatic
|
||||
* tasks and functions).
|
||||
* tasks and functions). The first two slots in each context are reserved for
|
||||
* linking to other contexts. The function that adds items to a context knows
|
||||
* this, and allocates context indices accordingly.
|
||||
*/
|
||||
typedef void**vvp_context_t;
|
||||
|
||||
|
|
@ -60,7 +62,8 @@ typedef void*vvp_context_item_t;
|
|||
|
||||
inline vvp_context_t vvp_allocate_context(unsigned nitem)
|
||||
{
|
||||
return (vvp_context_t)malloc((1 + nitem) * sizeof(void*));
|
||||
|
||||
return (vvp_context_t)malloc((2 + nitem) * sizeof(void*));
|
||||
}
|
||||
|
||||
inline vvp_context_t vvp_get_next_context(vvp_context_t context)
|
||||
|
|
@ -73,6 +76,16 @@ inline void vvp_set_next_context(vvp_context_t context, vvp_context_t next)
|
|||
context[0] = next;
|
||||
}
|
||||
|
||||
inline vvp_context_t vvp_get_stacked_context(vvp_context_t context)
|
||||
{
|
||||
return (vvp_context_t)context[1];
|
||||
}
|
||||
|
||||
inline void vvp_set_stacked_context(vvp_context_t context, vvp_context_t stack)
|
||||
{
|
||||
context[1] = stack;
|
||||
}
|
||||
|
||||
inline vvp_context_item_t vvp_get_context_item(vvp_context_t context,
|
||||
unsigned item_idx)
|
||||
{
|
||||
|
|
@ -88,18 +101,15 @@ inline void vvp_set_context_item(vvp_context_t context, unsigned item_idx,
|
|||
/*
|
||||
* An "automatic" functor is one which may be associated with an automatically
|
||||
* allocated scope item. This provides the infrastructure needed to allocate
|
||||
* and access the state information for individual instances of the item. A
|
||||
* context_idx value of 0 indicates a statically allocated item.
|
||||
* the state information for individual instances of the item.
|
||||
*/
|
||||
struct automatic_hooks_s {
|
||||
|
||||
automatic_hooks_s() : context_idx(0) {}
|
||||
automatic_hooks_s() {}
|
||||
virtual ~automatic_hooks_s() {}
|
||||
|
||||
virtual void alloc_instance(vvp_context_t context) {}
|
||||
virtual void reset_instance(vvp_context_t context) {}
|
||||
|
||||
unsigned context_idx;
|
||||
virtual void alloc_instance(vvp_context_t context) = 0;
|
||||
virtual void reset_instance(vvp_context_t context) = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -179,6 +189,8 @@ class vvp_vector4_t {
|
|||
|
||||
friend vvp_vector4_t operator ~(const vvp_vector4_t&that);
|
||||
friend class vvp_vector4array_t;
|
||||
friend class vvp_vector4array_sa;
|
||||
friend class vvp_vector4array_aa;
|
||||
|
||||
public:
|
||||
explicit vvp_vector4_t(unsigned size =0, vvp_bit4_t bits =BIT4_X);
|
||||
|
|
@ -456,24 +468,41 @@ extern bool vector4_to_value(const vvp_vector4_t&a, vvp_time64_t&val);
|
|||
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
|
||||
|
||||
/*
|
||||
* vvp_vector4array_t
|
||||
* The __vpiArray handle uses instances of this to keep an array of
|
||||
* real valued variables.
|
||||
*/
|
||||
class vvp_vector4array_t : public automatic_hooks_s {
|
||||
class vvp_realarray_t {
|
||||
|
||||
public:
|
||||
vvp_vector4array_t(unsigned width, unsigned words, bool is_automatic);
|
||||
~vvp_vector4array_t();
|
||||
vvp_realarray_t(unsigned words);
|
||||
~vvp_realarray_t();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
unsigned words() const { return words_; }
|
||||
|
||||
double get_word(unsigned idx) const;
|
||||
void set_word(unsigned idx, double val);
|
||||
|
||||
private:
|
||||
unsigned words_;
|
||||
double*array_;
|
||||
};
|
||||
|
||||
/*
|
||||
* vvp_vector4array_t
|
||||
*/
|
||||
class vvp_vector4array_t {
|
||||
|
||||
public:
|
||||
vvp_vector4array_t(unsigned width, unsigned words);
|
||||
virtual ~vvp_vector4array_t();
|
||||
|
||||
unsigned width() const { return width_; }
|
||||
unsigned words() const { return words_; }
|
||||
|
||||
vvp_vector4_t get_word(unsigned idx) const;
|
||||
void set_word(unsigned idx, const vvp_vector4_t&that);
|
||||
virtual vvp_vector4_t get_word(unsigned idx) const = 0;
|
||||
virtual void set_word(unsigned idx, const vvp_vector4_t&that) = 0;
|
||||
|
||||
private:
|
||||
protected:
|
||||
struct v4cell {
|
||||
union {
|
||||
unsigned long abits_val_;
|
||||
|
|
@ -485,15 +514,52 @@ class vvp_vector4array_t : public automatic_hooks_s {
|
|||
};
|
||||
};
|
||||
|
||||
vvp_vector4_t get_word_(v4cell*cell) const;
|
||||
void set_word_(v4cell*cell, const vvp_vector4_t&that);
|
||||
|
||||
unsigned width_;
|
||||
unsigned words_;
|
||||
v4cell* array_;
|
||||
|
||||
private: // Not implemented
|
||||
vvp_vector4array_t(const vvp_vector4array_t&);
|
||||
vvp_vector4array_t& operator = (const vvp_vector4array_t&);
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_vector4array_t
|
||||
*/
|
||||
class vvp_vector4array_sa : public vvp_vector4array_t {
|
||||
|
||||
public:
|
||||
vvp_vector4array_sa(unsigned width, unsigned words);
|
||||
~vvp_vector4array_sa();
|
||||
|
||||
vvp_vector4_t get_word(unsigned idx) const;
|
||||
void set_word(unsigned idx, const vvp_vector4_t&that);
|
||||
|
||||
private:
|
||||
v4cell* array_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_vector4array_t
|
||||
*/
|
||||
class vvp_vector4array_aa : public vvp_vector4array_t, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
vvp_vector4array_aa(unsigned width, unsigned words);
|
||||
~vvp_vector4array_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
vvp_vector4_t get_word(unsigned idx) const;
|
||||
void set_word(unsigned idx, const vvp_vector4_t&that);
|
||||
|
||||
private:
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
/* vvp_vector2_t
|
||||
*/
|
||||
class vvp_vector2_t {
|
||||
|
|
@ -924,21 +990,34 @@ struct vvp_net_t {
|
|||
* default behavior for recv_vec8 and recv_vec8_pv is to reduce the
|
||||
* operand to a vvp_vector4_t and pass it on to the recv_vec4 or
|
||||
* recv_vec4_pv method.
|
||||
*
|
||||
* The recv_vec4, recv_vec4_pv, and recv_real methods are also
|
||||
* passed a context pointer. When the received bit has propagated
|
||||
* from a statically allocated node, this will be a null pointer.
|
||||
* When the received bit has propagated from an automatically
|
||||
* allocated node, this will be a pointer to the context that
|
||||
* contains the instance of that bit that has just been modified.
|
||||
* When the received bit was from a procedural assignment or from
|
||||
* a VPI set_value() operation, this will be a pointer to the
|
||||
* writable context associated with the currently running thread.
|
||||
*/
|
||||
class vvp_net_fun_t : public automatic_hooks_s {
|
||||
class vvp_net_fun_t {
|
||||
|
||||
public:
|
||||
vvp_net_fun_t();
|
||||
virtual ~vvp_net_fun_t();
|
||||
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
virtual void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
virtual void recv_real(vvp_net_ptr_t port, double bit);
|
||||
virtual void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t context);
|
||||
virtual void recv_long(vvp_net_ptr_t port, long bit);
|
||||
|
||||
// Part select variants of above
|
||||
virtual void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context);
|
||||
virtual void recv_vec8_pv(vvp_net_ptr_t p, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
virtual void recv_long_pv(vvp_net_ptr_t port, long bit,
|
||||
|
|
@ -974,7 +1053,8 @@ class vvp_fun_concat : public vvp_net_fun_t {
|
|||
unsigned w2, unsigned w3);
|
||||
~vvp_fun_concat();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
unsigned wid_[4];
|
||||
|
|
@ -993,7 +1073,8 @@ class vvp_fun_repeat : public vvp_net_fun_t {
|
|||
vvp_fun_repeat(unsigned width, unsigned repeat);
|
||||
~vvp_fun_repeat();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
unsigned wid_;
|
||||
|
|
@ -1017,7 +1098,8 @@ class vvp_fun_drive : public vvp_net_fun_t {
|
|||
vvp_fun_drive(vvp_bit4_t init, unsigned str0 =6, unsigned str1 =6);
|
||||
~vvp_fun_drive();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
//void recv_long(vvp_net_ptr_t port, long bit);
|
||||
|
||||
private:
|
||||
|
|
@ -1037,7 +1119,8 @@ class vvp_fun_extend_signed : public vvp_net_fun_t {
|
|||
explicit vvp_fun_extend_signed(unsigned wid);
|
||||
~vvp_fun_extend_signed();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
unsigned width_;
|
||||
|
|
@ -1174,20 +1257,31 @@ class vvp_fun_signal_vec : public vvp_fun_signal_base {
|
|||
virtual vvp_vector4_t vec4_value() const =0;
|
||||
};
|
||||
|
||||
class vvp_fun_signal : public vvp_fun_signal_vec {
|
||||
class vvp_fun_signal4 : public vvp_fun_signal_vec {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal(unsigned wid, vvp_bit4_t init=BIT4_X);
|
||||
explicit vvp_fun_signal4() {};
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
void get_value(struct t_vpi_value*value);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_signal4.
|
||||
*/
|
||||
class vvp_fun_signal4_sa : public vvp_fun_signal4 {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal4_sa(unsigned wid, vvp_bit4_t init=BIT4_X);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
|
||||
// Part select variants of above
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t);
|
||||
void recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
|
||||
|
|
@ -1202,8 +1296,6 @@ class vvp_fun_signal : public vvp_fun_signal_vec {
|
|||
void release_pv(vvp_net_ptr_t port, bool net,
|
||||
unsigned base, unsigned wid);
|
||||
|
||||
void get_value(struct t_vpi_value*value);
|
||||
|
||||
private:
|
||||
void calculate_output_(vvp_net_ptr_t ptr);
|
||||
|
||||
|
|
@ -1211,17 +1303,54 @@ class vvp_fun_signal : public vvp_fun_signal_vec {
|
|||
vvp_vector4_t force_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_signal4.
|
||||
*/
|
||||
class vvp_fun_signal4_aa : public vvp_fun_signal4, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal4_aa(unsigned wid, vvp_bit4_t init=BIT4_X);
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
// Part select variants of above
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t);
|
||||
|
||||
// Get information about the vector value.
|
||||
unsigned size() const;
|
||||
vvp_bit4_t value(unsigned idx) const;
|
||||
vvp_scalar_t scalar_value(unsigned idx) const;
|
||||
vvp_vector4_t vec4_value() const;
|
||||
|
||||
// Commands
|
||||
void release(vvp_net_ptr_t port, bool net);
|
||||
void release_pv(vvp_net_ptr_t port, bool net,
|
||||
unsigned base, unsigned wid);
|
||||
|
||||
private:
|
||||
unsigned context_idx_;
|
||||
unsigned size_;
|
||||
};
|
||||
|
||||
class vvp_fun_signal8 : public vvp_fun_signal_vec {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal8(unsigned wid);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
|
||||
// Part select variants of above
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context);
|
||||
void recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
|
||||
|
|
@ -1245,16 +1374,27 @@ class vvp_fun_signal8 : public vvp_fun_signal_vec {
|
|||
vvp_vector8_t force_;
|
||||
};
|
||||
|
||||
class vvp_fun_signal_real : public vvp_fun_signal_base {
|
||||
class vvp_fun_signal_real : public vvp_fun_signal_base {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal_real();
|
||||
explicit vvp_fun_signal_real() {};
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
// Get information about the vector value.
|
||||
virtual double real_value() const = 0;
|
||||
|
||||
//void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_real(vvp_net_ptr_t port, double bit);
|
||||
void get_value(struct t_vpi_value*value);
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_signal_real.
|
||||
*/
|
||||
class vvp_fun_signal_real_sa : public vvp_fun_signal_real {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal_real_sa();
|
||||
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t);
|
||||
|
||||
// Get information about the vector value.
|
||||
double real_value() const;
|
||||
|
|
@ -1264,13 +1404,37 @@ class vvp_fun_signal_real : public vvp_fun_signal_base {
|
|||
void release_pv(vvp_net_ptr_t port, bool net,
|
||||
unsigned base, unsigned wid);
|
||||
|
||||
void get_value(struct t_vpi_value*value);
|
||||
|
||||
private:
|
||||
double bits_;
|
||||
double force_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_signal_real.
|
||||
*/
|
||||
class vvp_fun_signal_real_aa : public vvp_fun_signal_real, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_signal_real_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t context);
|
||||
|
||||
// Get information about the vector value.
|
||||
double real_value() const;
|
||||
|
||||
// Commands
|
||||
void release(vvp_net_ptr_t port, bool net);
|
||||
void release_pv(vvp_net_ptr_t port, bool net,
|
||||
unsigned base, unsigned wid);
|
||||
|
||||
private:
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Wide Functors:
|
||||
* Wide functors represent special devices that may have more than 4
|
||||
|
|
@ -1340,8 +1504,10 @@ class vvp_wide_fun_t : public vvp_net_fun_t {
|
|||
vvp_wide_fun_t(vvp_wide_fun_core*c, unsigned base);
|
||||
~vvp_wide_fun_t();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_real(vvp_net_ptr_t port, double bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
vvp_wide_fun_core*core_;
|
||||
|
|
@ -1349,20 +1515,22 @@ class vvp_wide_fun_t : public vvp_net_fun_t {
|
|||
};
|
||||
|
||||
|
||||
inline void vvp_send_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&val)
|
||||
inline void vvp_send_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&val,
|
||||
vvp_context_t context)
|
||||
{
|
||||
while (struct vvp_net_t*cur = ptr.ptr()) {
|
||||
vvp_net_ptr_t next = cur->port[ptr.port()];
|
||||
|
||||
if (cur->fun)
|
||||
cur->fun->recv_vec4(ptr, val);
|
||||
cur->fun->recv_vec4(ptr, val, context);
|
||||
|
||||
ptr = next;
|
||||
}
|
||||
}
|
||||
|
||||
extern void vvp_send_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&val);
|
||||
extern void vvp_send_real(vvp_net_ptr_t ptr, double val);
|
||||
extern void vvp_send_real(vvp_net_ptr_t ptr, double val,
|
||||
vvp_context_t context);
|
||||
extern void vvp_send_long(vvp_net_ptr_t ptr, long val);
|
||||
extern void vvp_send_long_pv(vvp_net_ptr_t ptr, long val,
|
||||
unsigned base, unsigned width);
|
||||
|
|
@ -1387,20 +1555,21 @@ extern void vvp_send_long_pv(vvp_net_ptr_t ptr, long val,
|
|||
* mirror of the destination vector.
|
||||
*/
|
||||
inline void vvp_send_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&val,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context)
|
||||
{
|
||||
while (struct vvp_net_t*cur = ptr.ptr()) {
|
||||
vvp_net_ptr_t next = cur->port[ptr.port()];
|
||||
|
||||
if (cur->fun)
|
||||
cur->fun->recv_vec4_pv(ptr, val, base, wid, vwid);
|
||||
cur->fun->recv_vec4_pv(ptr, val, base, wid, vwid, context);
|
||||
|
||||
ptr = next;
|
||||
}
|
||||
}
|
||||
|
||||
inline void vvp_send_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&val,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
{
|
||||
while (struct vvp_net_t*cur = ptr.ptr()) {
|
||||
vvp_net_ptr_t next = cur->port[ptr.port()];
|
||||
|
|
|
|||
68
vvp/words.cc
68
vvp/words.cc
|
|
@ -34,10 +34,15 @@ static void __compile_var_real(char*label, char*name,
|
|||
vvp_array_t array, unsigned long array_addr,
|
||||
int msb, int lsb)
|
||||
{
|
||||
vvp_fun_signal_real*fun = new vvp_fun_signal_real;
|
||||
vvp_fun_signal_real*fun;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
fun = new vvp_fun_signal_real_aa;
|
||||
} else {
|
||||
fun = new vvp_fun_signal_real_sa;
|
||||
}
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
net->fun = fun;
|
||||
vpip_add_item_to_current_scope(fun);
|
||||
|
||||
define_functor_symbol(label, net);
|
||||
|
||||
vpiHandle obj = vpip_make_real_var(name, net);
|
||||
|
|
@ -79,11 +84,15 @@ static void __compile_var(char*label, char*name,
|
|||
{
|
||||
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||
|
||||
vvp_fun_signal*vsig = new vvp_fun_signal(wid);
|
||||
vvp_fun_signal_vec*vsig;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
vsig = new vvp_fun_signal4_aa(wid);
|
||||
} else {
|
||||
vsig = new vvp_fun_signal4_sa(wid);
|
||||
}
|
||||
vvp_net_t*node = new vvp_net_t;
|
||||
|
||||
node->fun = vsig;
|
||||
vpip_add_item_to_current_scope(vsig);
|
||||
|
||||
define_functor_symbol(label, node);
|
||||
|
||||
vpiHandle obj = 0;
|
||||
|
|
@ -154,12 +163,12 @@ static void __compile_net(char*label, char*name,
|
|||
|
||||
vvp_net_t*node = new vvp_net_t;
|
||||
|
||||
vvp_array_t array = array_label? array_find(array_label) : 0;
|
||||
assert(array_label? array!=0 : true);
|
||||
vvp_array_t array = array_label ? array_find(array_label) : 0;
|
||||
assert(array_label ? array!=0 : true);
|
||||
|
||||
vvp_fun_signal_base*vsig = net8_flag
|
||||
? dynamic_cast<vvp_fun_signal_base*>(new vvp_fun_signal8(wid))
|
||||
: dynamic_cast<vvp_fun_signal_base*>(new vvp_fun_signal(wid,BIT4_Z));
|
||||
: dynamic_cast<vvp_fun_signal_base*>(new vvp_fun_signal4_sa(wid,BIT4_Z));
|
||||
node->fun = vsig;
|
||||
|
||||
/* Add the label into the functor symbol table. */
|
||||
|
|
@ -210,12 +219,17 @@ void compile_netw(char*label, char*array_label, unsigned long array_addr,
|
|||
argc, argv);
|
||||
}
|
||||
|
||||
void compile_net_real(char*label, char*name, int msb, int lsb, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
static void __compile_real(char*label, char*name,
|
||||
char*array_label, unsigned long array_addr,
|
||||
int msb, int lsb, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
|
||||
vvp_fun_signal_real*fun = new vvp_fun_signal_real;
|
||||
vvp_array_t array = array_label ? array_find(array_label) : 0;
|
||||
assert(array_label ? array!=0 : true);
|
||||
|
||||
vvp_fun_signal_real*fun = new vvp_fun_signal_real_sa;
|
||||
net->fun = fun;
|
||||
|
||||
/* Add the label into the functor symbol table. */
|
||||
|
|
@ -226,18 +240,42 @@ void compile_net_real(char*label, char*name, int msb, int lsb, bool local_flag,
|
|||
/* Connect the source to my input. */
|
||||
inputs_connect(net, 1, argv);
|
||||
|
||||
vpiHandle obj = 0;
|
||||
if (! local_flag) {
|
||||
/* Make the vpiHandle for the reg. */
|
||||
vpiHandle obj = vpip_make_real_var(name, net);
|
||||
obj = vpip_make_real_var(name, net);
|
||||
/* This attaches the label to the vpiHandle */
|
||||
compile_vpi_symbol(label, obj);
|
||||
vpip_attach_to_current_scope(obj);
|
||||
}
|
||||
|
||||
/* If this is an array word, then attach it to the
|
||||
array. Otherwise, attach it to the current scope. */
|
||||
if (array)
|
||||
array_attach_word(array, array_addr, obj);
|
||||
else if (obj)
|
||||
vpip_attach_to_current_scope(obj);
|
||||
free(label);
|
||||
free(name);
|
||||
if (name) free(name);
|
||||
if (array_label) free(array_label);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
void compile_net_real(char*label, char*name, int msb, int lsb, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
__compile_real(label, name, 0, 0,
|
||||
msb, lsb, local_flag, argc, argv);
|
||||
}
|
||||
|
||||
void compile_netw_real(char*label, char*array_label, unsigned long array_addr,
|
||||
int msb, int lsb,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
cerr << "XXXX compile_netw_real: label=" << label
|
||||
<< ", array_label=" << array_label << endl;
|
||||
__compile_real(label, 0, array_label, array_addr,
|
||||
msb, lsb, false, argc, argv);
|
||||
}
|
||||
|
||||
void compile_aliasw(char*label, char*array_label, unsigned long array_addr,
|
||||
int msb, int lsb, unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue