Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl

This commit is contained in:
Nick Gasson 2008-10-30 20:00:53 +00:00
commit ea9bbf804c
92 changed files with 2626 additions and 4573 deletions

130
BUGS.txt
View File

@ -4,23 +4,24 @@ HOW TO REPORT BUGS
Before I can fix an error, I need to understand what the problem
is. Try to explain what is wrong and why you think it is wrong. Please
try to include sample code that demonstrates the problem. Include a
description of what ivl does that is wrong, and what you expect should
happen. And include the command line flags passed to the compiler to make
the error happen. (This is often overlooked, and sometimes important.)
description of what Icarus Verilog does that is wrong, and what you
expect should happen. And include the command line flags passed to the
compiler to make the error happen. (This is often overlooked, and
sometimes important.)
* The Compiler Doesn't Compile
If the Icarus Verilog don't compile, I need to know about the
If Icarus Verilog doesn't compile, I need to know about the
compilation tools you are using. Specifically, I need to know:
- Operating system and processor type,
- Compiler w/ version,
- Library version, and
- Versions of any libraries being linked, and
- anything else you think relevant.
Be aware that I do not have at my disposal a porting lab. I have the
alpha on my desk, and the Linux/Intel box with a logic analyzer and
'scope hanging off it.
workstation on my desk, a Mac laptop, and the Linux/Intel box with a
logic analyzer and 'scope hanging off it.
* The Compiler Crashes
@ -28,26 +29,26 @@ No compiler should crash, no matter what kind of garbage is fed to
it. If the compiler crashes, you definitely found a bug and I need to
know about it.
Ivl internally checks its state while it works, and if it detects
something wrong that it cannot recover from, it will abort
Icarus Verilog internally checks its state while it works, and if it
detects something wrong that it cannot recover from, it will abort
intentionally. The "assertion failure" message that the program
prints in the process of dying is very important. It tells me where in
the source the bad thing happened. Include that message in the bug
report.
If there are not assertion messages, I need to know that as well.
If there are no assertion messages, I need to know that as well.
I also need a complete test program that demonstrates the crash.
* It Doesn't Like My Perfectly Valid Program(tm)
I need to know what you think is right that ivl gets wrong. Does it
reject your "Perfectly Valid Program(tm)" or does it compile it but
give incorrect results? The latter is the most insidious as it doesn't
scream out to be fixed unless someone is watching closely. However, if
I get a sample program from you, and I can compile it, and I run it
and nuclear junk doesn't fall from the sky, I'm moving on to the next
problem.
I need to know what you think is right that Icarus Verilog gets
wrong. Does it reject your "Perfectly Valid Program(tm)" or does it
compile it but give incorrect results? The latter is the most
insidious as it doesn't scream out to be fixed unless someone is
watching closely. However, if I get a sample program from you, and I
can compile it, and I run it and nuclear junk doesn't fall from the
sky, I'm moving on to the next problem.
So, if your program doesn't compile, tell me so, tell me where the
error occurs, and include a complete Perfectly Valid Test Program(tm).
@ -57,24 +58,25 @@ know. What's on my disk is more recent then the latest snapshot.
If your program does compile, but generates incorrect output, I need
to know what it says and what you think it should say. From this I can
take your sample program and work on ivl until it gets the proper
results. For this to work, of course, I first need to know what is
wrong with the output. Spell it out, because I've been known to miss
the obvious. Compiler writers often get buried in the details of the
wrong problem.
take your sample program and work on Icarus Verilog until it gets the
proper results. For this to work, of course, I first need to know what
is wrong with the output. Spell it out, because I've been known to
miss the obvious. Compiler writers often get buried in the details of
the wrong problem.
* It Generates Incorrect Target Code (XNF, EDIF/LPM, etc.)
* It Generates Incorrect Target Code
As ivl adds target code generators, there will be cases where errors
in the output netlist format occur. This is a tough nut because I
might not have all the tools to test the target format you are
reporting problems with. However, if you clearly explain what is right
and wrong about the generated netlist, I will probably be able to fix
the problem. It may take a few iterations.
As Icarus Verilog adds target code generators, there will be cases
where errors in the output netlist format occur. This is a tough nut
because I might not have all the tools to test the target format you
are reporting problems with. However, if you clearly explain what is
right and wrong about the generated output, I will probably be able
to fix the problem. It may take a few iterations.
In this case, if possible include not only the sample Verilog program,
but the generated netlist file(s) and a clear indication of what went
wrong. If it is not clear to me, I will ask for clarification.
wrong or what is expected. If it is not clear to me, I will ask for
clarification.
* The Output is Correct, But Less Than Ideal
@ -91,13 +93,13 @@ demonstrates the problem. If the error occurs after elaboration,
please include a top level module in the program that is suitable for
the target format. If I have to write the module myself, I might not
write it in a way that tickles the bug. So please, send all the
Verilog source (after preprocessing) that I need to invoke the error.
Verilog source that I need to invoke the error.
Also, include the command line you use to invoke the compiler. For
example:
ivl foo.vl -o foo.cc -tvvm
ivl foo.vl -s starthere
iverilog -o foo.out -tvvp foo.v
iverilog foo.vl -s starthere
If the error occurs with the null target (``-tnull'') then a top level
module may not be needed as long as the ``-s <name>'' switch is
@ -108,15 +110,19 @@ invoke the error without any Verilog other than what is included?" And
while we are at it, please place a copyright notice in your test
program and include a GPL license statement if you can. Your test
program may find its way into the test suite, and the notices will
make it all nice and legal.
make it all nice and legal. Please look at the existing tests in the
test suite <http://sourceforge.net/ivtest> for examples of good test
programs.
RESEARCHING EXISTING/PAST BUGS, AND FILING REPORTS
The URL <http://www.icarus.com/cgi-bin/ivl-bugs> is the main bug
tracking system. Once you believe you have found a bug, you may browse
the bugs database for existing bugs that may be related to yours. You
might find that your bug has already been fixed in a later release or
snapshot. If that's the case, then you are set.
The URL <http://sourceforge.net/tracker/?group_id=149850> is the main
bug tracking system. Once you believe you have found a bug, you may
browse the bugs database for existing bugs that may be related to
yours. You might find that your bug has already been fixed in a later
release or snapshot. If that's the case, then you are set. Also,
consider if you are reporting a bug or really asking for a new
feature, and use the appropriate tracker.
The bug database supports basic keyword searches, and you can
optionally limit your search to active bugs, or fixed bugs. You may
@ -125,8 +131,7 @@ broken. You may for example find a related bug that explains your
symptom.
The root page of the bug report database describes how to submit your
completed bug report. You may submit it via the web form, or via
e-mail.
completed bug report.
HOW TO SEND PATCHES
@ -134,21 +139,26 @@ Bug reports with patches are very welcome, especially if they are
formatted such that I can inspect them, decide that they are obviously
correct, and apply them without worry.
I prefer context diffs as emitted by diff from GNU diffutils. Human
beings can read such things, and they are resilient to changing
originals. A good set of flags to diff are ``diff -cNB''. With such
diffs, I can look at the changes you are offering and probably tell at
a glance that they are plausible. Then I can use patch(1) to apply
them. Or I can apply them by hand.
I prefer patches generated by the git source code tracking system. If
you are editing the source, you really should be using the latest
version from git. Please see the developer documentation for more
detailed instructions -- <http://iverilog.wikia.com/wiki/>.
However, if you send patches, *please* tell me what this patch is
supposed to accomplish, and if appropriate include a test program that
demonstrates the efficacy of the patch. (If I have no idea what the
patch is for, I will ask for clarification before applying it.)
When you make a patch, submit it to the "Patches" tracker at
<http://sourceforge.net/tracker/?group_id=149850>. Patches added to
the "Patches" tracker enter the developer workflow, are checked,
applied to the appropriate git branch, and are pushed. Then the
tracker item is closed.
If you send patches, *please* tell me what this patch is supposed to
accomplish, which branch you intended to be patched, and if
appropriate include a test program that demonstrates the efficacy of
the patch. (If I have no idea what the patch is for, I will ask for
clarification before applying it.)
COPYRIGHT ISSUES
Icarus Verilog is Copyright (c) 1998-2003 Stephen Williams except
Icarus Verilog is Copyright (c) 1998-2008 Stephen Williams except
where otherwise noted. Minor patches are covered as derivative works
(or editorial comment or whatever the appropriate legal term is) and
folded into the rest of ivl. However, if a submission can reasonably
@ -158,19 +168,3 @@ then falls under the "otherwise noted" category.
I must insist that any copyright material submitted for inclusion
include the GPL license notice as shown in the rest of the source.
$Id: BUGS.txt,v 1.5 2007/03/22 16:08:14 steve Exp $
$Log: BUGS.txt,v $
Revision 1.5 2007/03/22 16:08:14 steve
Spelling fixes from Larry
Revision 1.4 2003/02/19 04:36:31 steve
Notes on hte bug database.
Revision 1.3 2003/01/30 16:23:07 steve
Spelling fixes.
Revision 1.2 1999/08/06 04:05:28 steve
Handle scope of parameters.

View File

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

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

View File

@ -9,7 +9,7 @@
echo "Autoconf in root..."
autoconf -f
for dir in vpip vpi vvp tgt-vvp tgt-fpga tgt-stub tgt-vhdl libveriuser cadpli
for dir in vpi vvp tgt-vvp tgt-fpga tgt-stub tgt-vhdl libveriuser cadpli
do
echo "Autoconf in $dir..."
( cd ./$dir ; autoconf -f --include=.. )

View File

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

View File

@ -1148,12 +1148,9 @@ void NetScope::dump(ostream&o) const
}
// Dump the signals,
if (signals_) {
NetNet*cur = signals_->sig_next_;
do {
cur->dump_net(o, 4);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
for (signals_map_iter_t cur = signals_map_.begin()
; cur != signals_map_.end() ; cur ++) {
cur->second->dump_net(o, 4);
}
// Dump specparams

149
developer-quick-start.txt Normal file
View File

@ -0,0 +1,149 @@
Developer Quick Start for Icarus Verilog
The documentation for getting, building and installing Icarus Verilog
is kept and maintained at the iverilog documentation wiki at
<http://iverilog.wikia.com>. See the Installation Guide for getting
the current source from the git repository (and how to use the git
repository) and see the Developer Guide for instructions on
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
source code itself, so that you can find the global parts where you
can look for even better detail.
* Compiler Components
- The compiler driver (driver/)
This is the binary that is installed as "iverilog". This program takes
the command line arguments and assembles invocations of all the other
subcommands to perform the steps of compilation.
- The preprocessor (ivlpp/)
This implements the Verilog pre-processor. In Icarus Verilog, the
compiler directives `define, `include, `ifdef and etc. are implemented
in an external program. The ivlpp/ directory contains the source for
this program.
- The core compiler (this directory)
The "ivl" program is the core that does all the Verilog compiler
processing that is not handled elsewhere. This is the main core of the
Icarus Verilog compiler, not the runtime. See below for more details
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
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
runtime.
* Runtime Components
- The vvp runtime (vvp/)
This program implements the runtime environment for Icarus
Verilog. It implements the "vvp" command described in the user
documentation. See the vvp/ subdirectory for further developer
documentation.
- The system tasks implementations (vpi/)
The standard Verilog system tasks are implemented using VPI (PLI-2)
and the source is in this subdirectory.
- The PLI-1 compatibility library (libveriuser/)
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-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
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
output. This is the most complex component of the Icarus Verilog
compilation system.
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
API to the code generators.
- Lexical Analysis
Lexical analysis and parsing use the tools "flex", "gperf", and
"bison". The "flex" input file "lexor.lex" recognizes the tokens in
the input stream. This is called "lexical analysis". The lexical
analyzer also does some processing of compiler directives that are not
otherwise taken care of by the external preprocessor. The lexical
analyzer uses a table of keywords that is generated using the "gperf"
program and the input file "lexor_keywords.gperf". This table allows
the lexical analyzer to efficiently check input words with the rather
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
"decorated parse tree".
The pform itself is described by the classes in the header files
"PScope.h", "Module.h", "PGenerate.h", "Statement.h", and
"PExpr.h". The implementations of the classes in those header files
are in the similarly named C++ files.
- Elaboration
Elaboration transforms the pform to the netlist form. Elaboration is
conceptually divided into several major steps: Scope elaboration,
parameter overrides and defparam propagation, signal elaboration, and
statement and expression elaboration.
The elaboration of scopes and parameter overrides and defparam
propagation are conceptually separate, but are in practice
intermingled. The elaboration of scopes scans the pform to find and
instantiate all the scopes of the design. New scopes are created by
instantiation of modules (starting with the root instances) by user
defined tasks and functions, named blocks, and generate schemes. The
elaborate_scope methods implement scope elaboration, and the
elab_scope.cc source file has the implementations of those
methods.
The elaborate.cc source file contains the initial calls to the
elaborate_scope for the root scopes to get the process started. In
particular, see the "elaborate" function near the bottom of the
elaborate.cc source file. The calls to Design::make_root_scope create
the initial root scopes, and the creation and enqueue of the
elaborate_root_scope_t work items primes the scope elaboration work
list.
Intermingled in the work list are defparms work items that call the
Design::run_defparams and Design::evaluate_parameters methods that
override and evaluate parameters. The override and evaluation of
parameters must be intermingled with the elaboration of scopes because
the exact values of parameters may impact the scopes created (imagine
generate schemes and instance arrays) and the created scopes in turn
create new parameters that need override and evaluation.

View File

@ -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)
*
*/

View File

@ -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)
@ -790,7 +769,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 +1641,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 +1754,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);

View File

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

View File

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

View File

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

View File

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

View File

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

29
emit.cc
View File

@ -373,23 +373,20 @@ void NetScope::emit_scope(struct target_t*tgt) const
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
cur->emit_scope(tgt);
if (signals_) {
NetNet*cur = signals_->sig_next_;
do {
tgt->signal(cur);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
for (signals_map_iter_t cur = signals_map_.begin()
; cur != signals_map_.end() ; cur ++) {
tgt->signal(cur->second);
}
/* Run the signals again, but this time to connect the
delay paths. This is done as a second pass because
the paths reference other signals that may be later
in the list. We can do it here because delay paths are
always connected within the scope. */
cur = signals_->sig_next_;
do {
tgt->signal_paths(cur);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
// Run the signals again, but this time to connect the
// delay paths. This is done as a second pass because
// the paths reference other signals that may be later
// in the list. We can do it here because delay paths are
// always connected within the scope.
for (signals_map_iter_t cur = signals_map_.begin()
; cur != signals_map_.end() ; cur ++) {
tgt->signal_paths(cur->second);
}
}

View File

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

View File

@ -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_) {

View File

@ -111,20 +111,12 @@ void NetScope::run_functor(Design*des, functor_t*fun)
// apply to signals. Each iteration, allow for the possibility
// that the current signal deletes itself.
if (signals_) {
unsigned count = 0;
NetNet*cur = signals_->sig_next_;
do {
count += 1;
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
cur = signals_->sig_next_;
for (unsigned idx = 0 ; idx < count ; idx += 1) {
NetNet*tmp = cur->sig_next_;
fun->signal(des, cur);
cur = tmp;
}
signals_map_iter_t cur = signals_map_.begin();
while (cur != signals_map_.end()) {
signals_map_iter_t tmp = cur;
cur ++;
fun->signal(des, tmp->second);
}
}

View File

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

View File

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

View File

@ -38,7 +38,6 @@
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
: type_(t), up_(up), sib_(0), sub_(0)
{
signals_ = 0;
events_ = 0;
lcounter_ = 0;
is_auto_ = false;
@ -360,30 +359,13 @@ NetEvent* NetScope::find_event(perm_string name)
void NetScope::add_signal(NetNet*net)
{
if (signals_ == 0) {
net->sig_next_ = net;
net->sig_prev_ = net;
} else {
net->sig_next_ = signals_->sig_next_;
net->sig_prev_ = signals_;
net->sig_next_->sig_prev_ = net;
net->sig_prev_->sig_next_ = net;
}
signals_ = net;
signals_map_[net->name()]=net;
}
void NetScope::rem_signal(NetNet*net)
{
assert(net->scope() == this);
if (signals_ == net)
signals_ = net->sig_prev_;
if (signals_ == net) {
signals_ = 0;
} else {
net->sig_prev_->sig_next_ = net->sig_next_;
net->sig_next_->sig_prev_ = net->sig_prev_;
}
signals_map_.erase(net->name());
}
/*
@ -393,16 +375,10 @@ void NetScope::rem_signal(NetNet*net)
*/
NetNet* NetScope::find_signal(perm_string key)
{
if (signals_ == 0)
if (signals_map_.find(key)!=signals_map_.end())
return signals_map_[key];
else
return 0;
NetNet*cur = signals_;
do {
if (cur->name() == key)
return cur;
cur = cur->sig_prev_;
} while (cur != signals_);
return 0;
}
/*

View File

@ -427,7 +427,7 @@ const Link& NetDelaySrc::condit_pin() const
}
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
: NetObj(s, n, 1), sig_next_(0), sig_prev_(0),
: NetObj(s, n, 1),
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
signed_(false), isint_(false), discipline_(0), msb_(npins-1), lsb_(0),
dimensions_(0),
@ -466,8 +466,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
NetNet::NetNet(NetScope*s, perm_string n, Type t,
long ms, long ls)
: NetObj(s, n, 1),
sig_next_(0), sig_prev_(0), type_(t),
: NetObj(s, n, 1), type_(t),
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
isint_(false), discipline_(0), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
local_flag_(false), eref_count_(0), lref_count_(0)
@ -514,7 +513,7 @@ static unsigned calculate_count(long s, long e)
NetNet::NetNet(NetScope*s, perm_string n, Type t,
long ms, long ls, long array_s, long array_e)
: NetObj(s, n, calculate_count(array_s, array_e)),
sig_next_(0), sig_prev_(0), type_(t), port_type_(NOT_A_PORT),
type_(t), port_type_(NOT_A_PORT),
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
discipline_(0), msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
local_flag_(false), eref_count_(0), lref_count_(0)

View File

@ -614,11 +614,6 @@ class NetNet : public NetObj {
virtual void dump_net(ostream&, unsigned) const;
private:
// The NetScope class uses this for listing signals.
friend class NetScope;
NetNet*sig_next_, *sig_prev_;
private:
Type type_;
PortType port_type_;
@ -861,7 +856,8 @@ class NetScope : public Attrib {
NetNet::Type default_nettype_;
NetEvent *events_;
NetNet *signals_;
typedef std::map<perm_string,NetNet*>::const_iterator signals_map_iter_t;
std::map <perm_string,NetNet*> signals_map_;
perm_string module_name_;
union {
NetTaskDef*task_;
@ -3237,7 +3233,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;
@ -3274,7 +3270,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);

View File

@ -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);
}
/*

View File

@ -1034,12 +1034,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;
}

View File

@ -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?");

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,101 +0,0 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version. In order to redistribute the software in
# binary form, you will need a Picture Elements Binary Software
# License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.9 2007/02/06 05:07:32 steve Exp $"
#
#
SHELL = /bin/sh
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
VPATH = $(srcdir)
bindir = @bindir@
libdir = @libdir@
includedir = $(prefix)/include
CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @ident_support@ -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
STRIP = @STRIP@
P = vpi_bit.o vpi_callback.o \
vpi_const.o vpi_iter.o vpi_memory.o vpi_null.o \
vpi_priv.o vpi_scope.o vpi_signal.o vpi_simulation.o vpi_systask.o vpi_time.o \
vpi_mcd.o vpi_vlog_info.o
all: dep libvpip.a
check: all
Makefile: Makefile.in config.status
./config.status
libvpip.a: $P
ld -r -o vpip.o $P
rm -f $@
ar cvq $@ vpip.o
libvvm.a: $O
rm -f $@
ar cvq $@ $O
dep:
mkdir dep
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
mv $*.d dep
clean:
rm -rf *.o dep libvpip.a
distclean: clean
rm -f Makefile config.status config.log config.cache
install:: all installdirs \
$(libdir)/libvpip.a \
$(includedir)/vpi_priv.h
$(libdir)/libvpip.a: ./libvpip.a
$(INSTALL_DATA) ./libvpip.a $(libdir)/libvpip.a
$(includedir)/vpi_priv.h: $(srcdir)/vpi_priv.h
$(INSTALL_DATA) $(srcdir)/vpi_priv.h $(includedir)/vpi_priv.h
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
uninstall::
rm -f $(libdir)/libvpip.a
rm -f $(includedir)/vpi_priv.h
-include $(patsubst %.o, dep/%.d, $O $P)

View File

@ -1,21 +0,0 @@
AC_INIT(Makefile.in)
AC_CANONICAL_HOST
AC_PROG_CC
AC_CHECK_TOOL(STRIP, strip, true)
AC_PROG_INSTALL
AC_EXEEXT
AC_SUBST(EXEEXT)
# Combined check for Microsoft-related bogosities; sets WIN32 if found
AX_WIN32
# may modify CPPFLAGS and CFLAGS
AX_CPP_PRECOMP
# linker options when building a shared library
# AX_LD_SHAREDLIB_OPTS
AC_OUTPUT(Makefile)

View File

@ -1,40 +0,0 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
# $Id: mkinstalldirs,v 1.1 2001/03/14 19:27:44 steve Exp $
errstatus=0
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp" 1>&2
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# mkinstalldirs ends here

View File

@ -1,166 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_bit.c,v 1.2 2002/08/12 01:35:05 steve Exp $"
#endif
# include "vpi_priv.h"
# include <stdio.h>
/*
* A signal value is unambiguous if the top 4 bits and the bottom 4
* bits are identical. This means that the VSSSvsss bits of the 8bit
* value have V==v and SSS==sss.
*/
#define UNAMBIG(v) (! B_ISAMBIG(v))
# define STREN1(v) ( ((v)&0x80)? ((v)&0xf0) : (0x70 - ((v)&0xf0)) )
# define STREN0(v) ( ((v)&0x08)? ((v)&0x0f) : (0x07 - ((v)&0x0f)) )
vpip_bit_t vpip_pair_resolve(vpip_bit_t a, vpip_bit_t b)
{
vpip_bit_t res = a;
if (B_ISZ(b))
return a;
if (UNAMBIG(a) && UNAMBIG(b)) {
/* If both signals are unambiguous, simply choose
the stronger. If they have the same strength
but different values, then this becomes
ambiguous. */
if (a == b) {
/* values are equal. do nothing. */
} else if ((b&0x07) > (res&0x07)) {
/* New value is stronger. Take it. */
res = b;
} else if ((b&0x77) == (res&0x77)) {
/* Strengths are the same. Make value ambiguous. */
res = (res&0x70) | (b&0x07) | 0x80;
} else {
/* Must be res is the stronger one. */
}
} else if (UNAMBIG(res) || UNAMBIG(b)) {
/* If one of the signals is unambiguous, then it
will sweep up the weaker parts of the ambiguous
signal. The result may be ambiguous, or maybe not. */
vpip_bit_t tmp = 0;
if ((res&0x70) > (b&0x70))
tmp |= res&0xf0;
else
tmp |= b&0xf0;
if ((res&0x07) > (b&0x07))
tmp |= res&0x0f;
else
tmp |= b&0x0f;
res = tmp;
} else {
/* If both signals are ambiguous, then the result
has an even wider ambiguity. */
vpip_bit_t tmp = 0;
if (STREN1(b) > STREN1(res))
tmp |= b&0xf0;
else
tmp |= res&0xf0;
if (STREN0(b) < STREN0(res))
tmp |= b&0x0f;
else
tmp |= res&0x0f;
res = tmp;
}
/* Canonicalize the HiZ value. */
if ((res&0x77) == 0)
res = HiZ;
return res;
}
vpip_bit_t vpip_bits_resolve(const vpip_bit_t*bits, unsigned nbits)
{
unsigned idx;
vpip_bit_t res = bits[0];
idx = 1;
while ((idx < nbits) && B_ISZ(res)) {
res = bits[idx];
idx += 1;
}
for ( ; idx < nbits ; idx += 1)
res = vpip_pair_resolve(res, bits[idx]);
return res;
}
/*
* $Log: vpi_bit.c,v $
* Revision 1.2 2002/08/12 01:35:05 steve
* conditional ident string using autoconfig.
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.5 2000/05/11 01:37:33 steve
* Calculate the X output value from drive0 and drive1
*
* Revision 1.4 2000/05/09 21:16:35 steve
* Give strengths to logic and bufz devices.
*
* Revision 1.3 2000/05/07 04:37:56 steve
* Carry strength values from Verilog source to the
* pform and netlist for gates.
*
* Change vvm constants to use the driver_t to drive
* a constant value. This works better if there are
* multiple drivers on a signal.
*
* Revision 1.2 2000/03/22 05:16:38 steve
* Integrate drive resolution function.
*
* Revision 1.1 2000/03/22 04:26:40 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
*/

View File

@ -1,228 +0,0 @@
/*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_callback.c,v 1.2 2002/08/12 01:35:05 steve Exp $"
#endif
# include "vpi_priv.h"
# include <stdlib.h>
# include <assert.h>
static struct __vpirt vpip_callback_rt = {
vpiCallback,
0,
0,
0,
0,
0,
0
};
/*
* This function is called by the scheduler to execute an event of
* some sort. The parameter is a vpiHandle of the callback that is to
* be executed.
*/
static void vpip_call_callback(void*cp)
{
unsigned long now;
struct __vpiCallback*rfp = (struct __vpiCallback*)cp;
assert(rfp->base.vpi_type->type_code == vpiCallback);
switch (rfp->cb_data.time->type) {
case vpiSuppressTime:
case vpiScaledRealTime: /* XXXX not supported */
break;
case vpiSimTime:
now = ((struct __vpiTimeVar*)vpip_sim_time())->time;
rfp->cb_data.time->low = now;
rfp->cb_data.time->high = 0;
break;
}
rfp->cb_data.cb_rtn(&rfp->cb_data);
free(rfp);
}
/*
* This function is called by the product when it changes the value of
* a signal. It arranges for all the value chance callbacks to be
* called.
*/
void vpip_run_value_changes(struct __vpiSignal*sig)
{
struct __vpiCallback*cur;
while (sig->mfirst) {
cur = sig->mfirst;
sig->mfirst = cur->next;
if (sig->mfirst == 0)
sig->mlast = 0;
cur->next = 0;
cur->ev = vpip_sim_insert_event(0, cur, vpip_call_callback, 0);
}
}
/*
* Handle read-only synch events. This causes the callback to be
* scheduled for a moment at the end of the time period. This method
* handles scheduling with time delays.
*/
static void go_readonly_synch(struct __vpiCallback*rfp)
{
unsigned long tim;
assert(rfp->cb_data.time);
assert(rfp->cb_data.time->type == vpiSimTime);
assert(rfp->cb_data.time->high == 0);
tim = rfp->cb_data.time->low;
rfp->ev = vpip_sim_insert_event(tim, rfp, vpip_call_callback, 1);
}
/*
* To schedule a value change, attach the callback to the signal to me
* monitored. I'll be inserted as an event later.
*/
static void go_value_change(struct __vpiCallback*rfp)
{
struct __vpiSignal*sig = (struct __vpiSignal*)rfp->cb_data.obj;
assert((sig->base.vpi_type->type_code == vpiReg)
|| (sig->base.vpi_type->type_code == vpiNet));
/* If there are no monitor events, start the list. */
if (sig->mfirst == 0) {
rfp->sig = sig;
rfp->next = 0;
sig->mfirst = rfp;
sig->mlast = rfp;
return;
}
/* Put me at the end of the list. Remember that the monitor
points to the *last* item in the list. */
rfp->sig = sig;
rfp->next = 0;
sig->mlast->next = rfp;
}
/*
* Register callbacks. This supports a variety of callback reasons,
* mostly by dispatching them to a type specific handler.
*/
vpiHandle vpi_register_cb(p_cb_data data)
{
struct __vpiCallback*rfp = calloc(1, sizeof(struct __vpiCallback));
rfp->base.vpi_type = &vpip_callback_rt;
rfp->cb_data = *data;
switch (data->reason) {
case cbReadOnlySynch:
go_readonly_synch(rfp);
break;
case cbValueChange:
go_value_change(rfp);
break;
default:
assert(0);
}
return &(rfp->base);
}
int vpi_remove_cb(vpiHandle ref)
{
struct __vpiCallback*rfp = (struct __vpiCallback*)ref;
assert(ref->vpi_type->type_code == vpiCallback);
if (rfp->ev) {
/* callbacks attached to events are easy. */
vpip_sim_cancel_event(rfp->ev);
} else if (rfp->sig) {
/* callbacks to signals need to be removed from the
signal's list of monitor callbacks. */
struct __vpiSignal*sig = rfp->sig;
if (sig->mfirst == rfp) {
sig->mfirst = rfp->next;
if (sig->mfirst == 0)
sig->mlast = 0;
rfp->next = 0;
rfp->sig = 0;
} else {
struct __vpiCallback*cur = sig->mfirst;
while (cur->next != rfp) {
assert(cur->next);
cur = cur->next;
}
cur->next = rfp->next;
if (cur->next == 0)
sig->mlast = cur;
}
} else {
assert(0);
}
free(rfp);
return 0;
}
/*
* $Log: vpi_callback.c,v $
* Revision 1.2 2002/08/12 01:35:05 steve
* conditional ident string using autoconfig.
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.8 2000/08/20 17:49:05 steve
* Clean up warnings and portability issues.
*
* Revision 1.7 2000/03/31 07:08:39 steve
* allow cancelling of cbValueChange events.
*
* Revision 1.6 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.5 1999/12/15 04:01:14 steve
* Add the VPI implementation of $readmemh.
*
* Revision 1.4 1999/11/07 20:33:30 steve
* Add VCD output and related system tasks.
*
* Revision 1.3 1999/10/29 03:37:22 steve
* Support vpiValueChance callbacks.
*
* Revision 1.2 1999/10/28 04:47:57 steve
* Support delay in constSync callback.
*
* Revision 1.1 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*
*/

View File

@ -1,526 +0,0 @@
/*
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_const.c,v 1.3 2002/08/12 01:35:05 steve Exp $"
#endif
# include "vpi_priv.h"
# include <assert.h>
# include <string.h>
# include <stdio.h>
static unsigned vpip_bits_to_dec_str(const vpip_bit_t*bits, unsigned nbits,
char*buf, unsigned nbuf, int signed_flag)
{
unsigned idx, len;
unsigned count_x = 0, count_z = 0;
unsigned long val = 0;
assert( nbits <= 8*sizeof(val) );
for (idx = 0 ; idx < nbits ; idx += 1) {
val *= 2;
if (B_ISZ(bits[nbits-idx-1]))
count_z += 1;
else if (B_ISX(bits[nbits-idx-1]))
count_x += 1;
else if (B_IS1(bits[nbits-idx-1]))
val += 1;
}
if (count_x == nbits) {
len = 1;
buf[0] = 'x';
buf[1] = 0;
} else if (count_x > 0) {
len = 1;
buf[0] = 'X';
buf[1] = 0;
} else if (count_z == nbits) {
len = 1;
buf[0] = 'z';
buf[1] = 0;
} else if (count_z > 0) {
len = 1;
buf[0] = 'Z';
buf[1] = 0;
} else {
if (signed_flag && B_IS1(bits[nbits-1])) {
long tmp = -1;
assert(sizeof(tmp) == sizeof(val));
tmp <<= nbits;
tmp |= val;
sprintf(buf, "%ld", tmp);
len = strlen(buf);
} else {
sprintf(buf, "%lu", val);
len = strlen(buf);
}
}
return len;
}
/*
* This function is used in a couple places to interpret a bit string
* as a value.
*/
void vpip_bits_get_value(const vpip_bit_t*bits, unsigned nbits,
s_vpi_value*vp, int signed_flag)
{
static char buff[1024];
static s_vpi_vecval vect[64];
char* cp = buff;
unsigned val;
unsigned idx;
int isx;
vp->value.str = buff;
switch (vp->format) {
case vpiObjTypeVal:
case vpiBinStrVal:
for (idx = 0 ; idx < nbits ; idx += 1) {
if (B_IS0(bits[nbits-idx-1]))
*cp++ = '0';
else if (B_IS1(bits[nbits-idx-1]))
*cp++ = '1';
else if (B_ISZ(bits[nbits-idx-1]))
*cp++ = 'z';
else
*cp++ = 'x';
}
vp->format = vpiBinStrVal;
*cp++ = 0;
break;
case vpiDecStrVal:
cp += vpip_bits_to_dec_str(bits, nbits, cp,
1024-(cp-buff), signed_flag);
break;
case vpiOctStrVal:
if (nbits%3) {
unsigned x = 0;
unsigned z = 0;
unsigned v = 0;
unsigned i;
for (i = 0 ; i < nbits%3 ; i += 1) {
v *= 2;
if (B_IS0(bits[nbits-i-1]))
;
else if (B_IS1(bits[nbits-i-1]))
v += 1;
else if (B_ISX(bits[nbits-i-1]))
x += 1;
else if (B_ISZ(bits[nbits-i-1]))
z += 1;
}
if (x == nbits%3)
*cp++ = 'x';
else if (x > 0)
*cp++ = 'X';
else if (z == nbits%3)
*cp++ = 'z';
else if (z > 0)
*cp++ = 'Z';
else
*cp++ = "01234567"[v];
}
for (idx = nbits%3 ; idx < nbits ; idx += 3) {
unsigned x = 0;
unsigned z = 0;
unsigned v = 0;
unsigned i;
for (i = idx ; i < idx+3 ; i += 1) {
v *= 2;
if (B_IS0(bits[nbits-i-1]))
;
else if (B_IS1(bits[nbits-i-1]))
v += 1;
else if (B_ISX(bits[nbits-i-1]))
x += 1;
else if (B_ISZ(bits[nbits-i-1]))
z += 1;
}
if (x == 3)
*cp++ = 'x';
else if (x > 0)
*cp++ = 'X';
else if (z == 3)
*cp++ = 'z';
else if (z > 0)
*cp++ = 'Z';
else
*cp++ = "01234567"[v];
}
*cp++ = 0;
break;
case vpiHexStrVal:
if (nbits%4) {
unsigned x = 0;
unsigned z = 0;
unsigned v = 0;
unsigned i;
for (i = 0 ; i < nbits%4 ; i += 1) {
v *= 2;
if (B_IS0(bits[nbits-i-1]))
;
else if (B_IS1(bits[nbits-i-1]))
v += 1;
else if (B_ISX(bits[nbits-i-1]))
x += 1;
else if (B_ISZ(bits[nbits-i-1]))
z += 1;
}
if (x == nbits%4)
*cp++ = 'x';
else if (x > 0)
*cp++ = 'X';
else if (z == nbits%4)
*cp++ = 'z';
else if (z > 0)
*cp++ = 'Z';
else
*cp++ = "0123456789abcdef"[v];
}
for (idx = nbits%4 ; idx < nbits ; idx += 4) {
unsigned x = 0;
unsigned z = 0;
unsigned v = 0;
unsigned i;
for (i = idx ; i < idx+4 ; i += 1) {
v *= 2;
if (B_IS0(bits[nbits-i-1]))
;
else if (B_IS1(bits[nbits-i-1]))
v += 1;
else if (B_ISX(bits[nbits-i-1]))
x += 1;
else if (B_ISZ(bits[nbits-i-1]))
z += 1;
}
if (x == 4)
*cp++ = 'x';
else if (x > 0)
*cp++ = 'X';
else if (z == 4)
*cp++ = 'z';
else if (z > 0)
*cp++ = 'Z';
else
*cp++ = "0123456789abcdef"[v];
}
*cp++ = 0;
break;
case vpiIntVal:
val = 0;
isx = 0;
for (idx = 0 ; idx < nbits ; idx += 1) {
val *= 2;
if (B_ISXZ(bits[nbits-idx-1]))
isx = 1;
else if (B_IS1(bits[nbits-idx-1]))
val += 1;
}
if(isx)
vp->value.integer = 0;
else
vp->value.integer = val;
break;
case vpiStringVal:
/* Turn the bits into an ASCII string, terminated by a
null. This is actually a bit tricky as nulls in the
bit array would terminate the C string. I therefore
translate them to ASCII ' ' characters. */
assert(nbits%8 == 0);
for (idx = nbits ; idx >= 8 ; idx -= 8) {
char tmp = 0;
unsigned bdx;
for (bdx = 8 ; bdx > 0 ; bdx -= 1) {
tmp <<= 1;
if (B_IS1(bits[idx-8+bdx-1]))
tmp |= 1;
}
*cp++ = tmp? tmp : ' ';
}
*cp++ = 0;
break;
case vpiVectorVal:
vp->value.vector = vect;
for (idx = 0 ; idx < nbits ; idx += 1) {
int major = idx/32;
int minor = idx%32;
vect[major].aval &= (1<<minor) - 1;
vect[major].bval &= (1<<minor) - 1;
if (B_IS1(bits[idx]) || B_ISX(bits[idx]))
vect[major].aval |= 1<<minor;
if (B_ISXZ(bits[idx]))
vect[major].bval |= 1<<minor;
}
break;
default:
*cp++ = '(';
*cp++ = '?';
*cp++ = ')';
*cp++ = 0;
vp->format = vpiStringVal;
break;
}
}
void vpip_bits_set_value(vpip_bit_t*bits, unsigned nbits, s_vpi_value*vp)
{
switch (vp->format) {
case vpiScalarVal:
switch (vp->value.scalar) {
case vpi0:
bits[0] = St0;
break;
case vpi1:
bits[0] = St1;
break;
case vpiX:
bits[0] = StX;
break;
case vpiZ:
bits[0] = HiZ;
break;
default:
assert(0);
}
break;
case vpiVectorVal: {
unsigned long aval = vp->value.vector->aval;
unsigned long bval = vp->value.vector->bval;
int idx;
for (idx = 0 ; idx < nbits ; idx += 1) {
int bit = (aval&1) | ((bval<<1)&2);
switch (bit) {
case 0:
bits[idx] = St0;
break;
case 1:
bits[idx] = St1;
break;
case 2:
bits[idx] = HiZ;
break;
case 3:
bits[idx] = StX;
break;
}
aval >>= 1;
bval >>= 1;
}
break;
}
case vpiIntVal: {
long val = vp->value.integer;
unsigned idx;
for (idx = 0 ; idx < nbits ; idx += 1) {
bits[idx] = (val&1)? St1 : St0;
val >>= 1;
}
break;
}
default:
assert(0);
}
}
static int string_get(int code, vpiHandle ref)
{
struct __vpiStringConst*rfp = (struct __vpiStringConst*)ref;
assert(ref->vpi_type->type_code == vpiConstant);
switch (code) {
case vpiConstType:
return vpiStringConst;
default:
assert(0);
return 0;
}
}
static void string_value(vpiHandle ref, p_vpi_value vp)
{
struct __vpiStringConst*rfp = (struct __vpiStringConst*)ref;
assert(ref->vpi_type->type_code == vpiConstant);
switch (vp->format) {
case vpiObjTypeVal:
case vpiStringVal:
vp->value.str = (char*)rfp->value;
vp->format = vpiStringVal;
break;
default:
vp->format = vpiSuppressVal;
break;
}
}
static int number_get(int code, vpiHandle ref)
{
struct __vpiNumberConst*rfp = (struct __vpiNumberConst*)ref;
assert(ref->vpi_type->type_code == vpiConstant);
switch (code) {
case vpiConstType:
return vpiBinaryConst;
default:
assert(0);
return 0;
}
}
static void number_value(vpiHandle ref, p_vpi_value vp)
{
struct __vpiNumberConst*rfp = (struct __vpiNumberConst*)ref;
assert(ref->vpi_type->type_code == vpiConstant);
vpip_bits_get_value(rfp->bits, rfp->nbits, vp, 0);
}
static const struct __vpirt vpip_string_rt = {
vpiConstant,
string_get,
0,
string_value,
0,
0,
0
};
static const struct __vpirt vpip_number_rt = {
vpiConstant,
number_get,
0,
number_value,
0,
0,
0
};
vpiHandle vpip_make_string_const(struct __vpiStringConst*ref, const char*val)
{
ref->base.vpi_type = &vpip_string_rt;
ref->value = val;
return &(ref->base);
}
vpiHandle vpip_make_number_const(struct __vpiNumberConst*ref,
const vpip_bit_t*bits,
unsigned nbits)
{
ref->base.vpi_type = &vpip_number_rt;
ref->bits = bits;
ref->nbits = nbits;
return &(ref->base);
}
/*
* $Log: vpi_const.c,v $
* Revision 1.3 2002/08/12 01:35:05 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2001/04/24 15:47:37 steve
* Fix setting StX in vpip_bits_set_value.
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.17 2001/01/07 18:22:15 steve
* Assert on length of bit vector.
*
* Revision 1.16 2001/01/06 22:22:17 steve
* Support signed decimal display of variables.
*
* Revision 1.15 2000/12/10 19:15:19 steve
* vpiStringVal handles leding nulls as blanks. (PR#62)
*
* Revision 1.14 2000/12/02 02:40:56 steve
* Support for %s in $display (PR#62)
*
* Revision 1.13 2000/09/23 16:34:47 steve
* Handle unknowns in decimal strings.
*
* Revision 1.12 2000/08/20 17:49:05 steve
* Clean up warnings and portability issues.
*
* Revision 1.11 2000/08/08 01:47:40 steve
* Add vpi_vlog_info support from Adrian
*
* Revision 1.10 2000/07/08 22:40:07 steve
* Allow set vpiIntVal on bitset type objects.
*
* Revision 1.9 2000/05/18 03:27:32 steve
* Support writing scalars and vectors to signals.
*
* Revision 1.8 2000/05/07 18:20:08 steve
* Import MCD support from Stephen Tell, and add
* system function parameter support to the IVL core.
*
* Revision 1.7 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.6 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.5 1999/12/15 04:01:14 steve
* Add the VPI implementation of $readmemh.
*
* Revision 1.4 1999/11/06 22:16:50 steve
* Get the $strobe task working.
*
* Revision 1.3 1999/11/06 16:52:16 steve
* complete value retrieval for number constants.
*
* Revision 1.2 1999/11/06 16:00:18 steve
* Put number constants into a static table.
*
* Revision 1.1 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*
*/

View File

@ -1,90 +0,0 @@
/*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_iter.c,v 1.2 2002/08/12 01:35:05 steve Exp $"
#endif
/*
* Find here the methods functions in support of iterator objects.
*/
# include "vpi_priv.h"
# include <stdlib.h>
# include <assert.h>
static const struct __vpirt vpip_iterator_rt = {
vpiIterator,
0,
0,
0,
0,
0,
0
};
vpiHandle vpip_make_iterator(unsigned nargs, vpiHandle*args)
{
struct __vpiIterator*res = calloc(1, sizeof(struct __vpiIterator));
res->base.vpi_type = &vpip_iterator_rt;
res->args = args;
res->nargs = nargs;
res->next = 0;
return &(res->base);
}
/*
* The vpi_scan function only applies to iterators. It returns the
* next vpiHandle in the iterated list.
*/
vpiHandle vpi_scan(vpiHandle ref)
{
struct __vpiIterator*hp = (struct __vpiIterator*)ref;
assert(ref->vpi_type->type_code == vpiIterator);
if (hp->next == hp->nargs) {
vpi_free_object(ref);
return 0;
}
return hp->args[hp->next++];
}
/*
* $Log: vpi_iter.c,v $
* Revision 1.2 2002/08/12 01:35:05 steve
* conditional ident string using autoconfig.
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.3 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.2 1999/12/15 04:01:14 steve
* Add the VPI implementation of $readmemh.
*
* Revision 1.1 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*
*/

View File

@ -1,160 +0,0 @@
/*
* Copyright (c) 2000 Stephen G. Tell <steve@telltronics.org>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_mcd.c,v 1.7 2004/10/04 01:10:58 steve Exp $"
#endif
# include "vpi_priv.h"
# include <assert.h>
# include <stdarg.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
struct mcd_entry {
FILE *fp;
char *filename;
};
static struct mcd_entry mcd_table[32];
/* Initialize mcd portion of vpi. Must be called before
* any vpi_mcd routines can be used.
*/
void vpi_mcd_init(void)
{
mcd_table[0].fp = stdout;
mcd_table[0].filename = "<stdout>";
mcd_table[1].fp = stderr;
mcd_table[1].filename = "<stderr>";
mcd_table[2].fp = 0; /* TODO: initialize this to log file */
mcd_table[2].filename = "<stdlog>";
}
/*
* close one or more channels. we silently refuse to close the preopened ones.
*/
unsigned int vpi_mcd_close(unsigned int mcd)
{
int i;
int rc;
rc = 0;
for(i = 3; i < 31; i++) {
if( ((mcd>>i) & 1) && mcd_table[i].filename) {
if(fclose(mcd_table[i].fp) != 0)
rc |= 1<<i;
free(mcd_table[i].filename);
mcd_table[i].fp = NULL;
mcd_table[i].filename = NULL;
} else {
rc |= 1<<i;
}
}
return rc;
}
char *vpi_mcd_name(unsigned int mcd)
{
int i;
for(i = 0; i < 31; i++) {
if( (mcd>>i) & 1)
return mcd_table[i].filename;
}
return NULL;
}
unsigned int vpi_mcd_open_x(char *name, char *mode)
{
int i;
for(i = 0; i < 31; i++) {
if(mcd_table[i].filename == NULL)
goto got_entry;
}
return 0; /* too many open mcd's */
got_entry:
mcd_table[i].fp = fopen(name, mode);
if(mcd_table[i].fp == NULL)
return 0;
mcd_table[i].filename = strdup(name);
return 1<<i;
}
unsigned int vpi_mcd_open(char *name)
{
return vpi_mcd_open_x(name, "w");
}
extern int vpi_mcd_vprintf(unsigned int mcd, const char*fmt, va_list ap)
{
int i;
int len;
int rc;
rc = len = 0;
for(i = 0; i < 31; i++) {
if( (mcd>>i) & 1) {
if(mcd_table[i].fp)
len = vfprintf(mcd_table[i].fp, fmt, ap);
else
rc = EOF;
}
}
if(rc)
return rc;
else
return len;
}
int vpi_mcd_fputc(unsigned int mcd, unsigned char x)
{
int i;
for(i = 0; i < 31; i++) {
if( (mcd>>i) & 1) {
return fputc(x, mcd_table[i].fp);
}
}
return 0;
}
int vpi_mcd_fgetc(unsigned int mcd)
{
int i;
for(i = 0; i < 31; i++) {
if( (mcd>>i) & 1) {
return fgetc(mcd_table[i].fp);
}
}
return 0;
}
/*
* $Log: vpi_mcd.c,v $
* Revision 1.7 2004/10/04 01:10:58 steve
* Clean up spurious trailing white space.
*
* Revision 1.6 2002/08/12 01:35:05 steve
* conditional ident string using autoconfig.
*
* Revision 1.5 2002/08/11 23:47:04 steve
* Add missing Log and Ident strings.
*
*/

View File

@ -1,246 +0,0 @@
/*
* Copyright (c) 1999-2000 Picture Elements, Inc.
* Stephen Williams (steve@picturel.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version. In order to redistribute the software in
* binary form, you will need a Picture Elements Binary Software
* License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* ---
* You should also have received a copy of the Picture Elements
* Binary Software License offer along with the source. This offer
* allows you to obtain the right to redistribute the software in
* binary (compiled) form. If you have not received it, contact
* Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_memory.c,v 1.4 2007/02/26 19:49:51 steve Exp $"
#endif
# include "vpi_priv.h"
# include <stdlib.h>
# include <assert.h>
static int memory_get(int code, vpiHandle ref)
{
struct __vpiMemory*rfp = (struct __vpiMemory*)ref;
assert(ref->vpi_type->type_code==vpiMemory);
switch (code) {
case vpiSize:
return rfp->size;
default:
return 0;
}
}
static const char* memory_get_str(int code, vpiHandle ref)
{
struct __vpiMemory*rfp = (struct __vpiMemory*)ref;
assert(ref->vpi_type->type_code==vpiMemory);
switch (code) {
case vpiFullName:
return (char*)rfp->name;
}
return 0;
}
static vpiHandle memory_iterate(int code, vpiHandle ref)
{
unsigned idx;
struct __vpiMemory*rfp = (struct __vpiMemory*)ref;
assert(ref->vpi_type->type_code==vpiMemory);
switch (code) {
case vpiMemoryWord:
if (rfp->args == 0) {
rfp->args = calloc(rfp->size, sizeof(vpiHandle));
for (idx = 0 ; idx < rfp->size ; idx += 1)
rfp->args[idx] = &rfp->words[idx].base;
}
return vpip_make_iterator(rfp->size, rfp->args);
default:
return 0;
}
}
static vpiHandle memory_index(vpiHandle ref, int index)
{
struct __vpiMemory*rfp = (struct __vpiMemory*)ref;
assert(ref->vpi_type->type_code==vpiMemory);
if (rfp->args == 0) {
unsigned idx;
rfp->args = calloc(rfp->size, sizeof(vpiHandle));
for (idx = 0 ; idx < rfp->size ; idx += 1)
rfp->args[idx] = &rfp->words[idx].base;
}
if (index > rfp->size) return 0;
if (index < 0) return 0;
return &(rfp->words[index].base);
}
static int memory_word_get(int code, vpiHandle ref)
{
struct __vpiMemoryWord*rfp = (struct __vpiMemoryWord*)ref;
assert(ref->vpi_type->type_code==vpiMemoryWord);
switch (code) {
case vpiSize:
return rfp->mem->width;
default:
return 0;
}
}
static vpiHandle memory_word_put(vpiHandle ref, p_vpi_value val,
p_vpi_time tim, int flags)
{
unsigned idx;
vpip_bit_t*base;
struct __vpiMemoryWord*rfp = (struct __vpiMemoryWord*)ref;
assert(ref->vpi_type->type_code==vpiMemoryWord);
base = rfp->mem->bits + rfp->index*rfp->mem->width;
assert(val->format == vpiVectorVal);
for (idx = 0 ; idx < rfp->mem->width ; idx += 1) {
p_vpi_vecval cur = val->value.vector + (idx/32);
int aval = cur->aval >> (idx%32);
int bval = cur->bval >> (idx%32);
if (bval & 1) {
if (aval & 1)
*base = StX;
else
*base = HiZ;
} else {
if (aval & 1)
*base = St1;
else
*base = St0;
}
base += 1;
}
return 0;
}
static void memory_word_get_value(vpiHandle ref, s_vpi_value*vp)
{
struct __vpiMemoryWord*rfp = (struct __vpiMemoryWord*)ref;
assert(ref->vpi_type->type_code==vpiMemoryWord);
vpip_bits_get_value(rfp->mem->bits+rfp->index*rfp->mem->width,
rfp->mem->width, vp, 0);
}
static const struct __vpirt vpip_memory_rt = {
vpiMemory,
memory_get,
memory_get_str,
0,
0,
0,
memory_iterate,
memory_index
};
static const struct __vpirt vpip_memory_word_rt = {
vpiMemoryWord,
memory_word_get,
0,
memory_word_get_value,
memory_word_put,
0,
0,
0
};
vpiHandle vpip_make_memory(struct __vpiMemory*ref, const char*name,
unsigned wid, unsigned siz)
{
unsigned idx;
ref->base.vpi_type = &vpip_memory_rt;
ref->name = name;
ref->bits = calloc(wid*siz, sizeof(vpip_bit_t));
for (idx = 0 ; idx < wid*siz ; idx += 1)
ref->bits[idx] = StX;
ref->words = calloc(siz, sizeof(struct __vpiMemoryWord));
ref->args = 0;
ref->width = wid;
ref->size = siz;
for (idx = 0 ; idx < siz ; idx += 1) {
ref->words[idx].base.vpi_type = &vpip_memory_word_rt;
ref->words[idx].mem = ref;
ref->words[idx].index = idx;
}
return &(ref->base);
}
/*
* $Log: vpi_memory.c,v $
* Revision 1.4 2007/02/26 19:49:51 steve
* Spelling fixes (larry doolittle)
*
* Revision 1.3 2002/08/12 01:35:05 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2001/10/26 02:29:10 steve
* const/non-const warnings. (Stephan Boettcher)
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.9 2001/01/06 22:22:17 steve
* Support signed decimal display of variables.
*
* Revision 1.8 2000/06/28 18:38:00 steve
* Initialize memories as they are create.
*
* Revision 1.7 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.6 2000/02/29 01:41:32 steve
* Fix warning and typo.
*
* Revision 1.5 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 2000/02/13 19:18:28 steve
* Accept memory words as parameter to $display.
*
* Revision 1.3 1999/12/15 04:15:17 steve
* Implement vpi_put_value for memory words.
*
* Revision 1.2 1999/12/15 04:01:14 steve
* Add the VPI implementation of $readmemh.
*
* Revision 1.1 1999/11/10 02:52:24 steve
* Create the vpiMemory handle type.
*
*/

View File

@ -1,71 +0,0 @@
/*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_null.c,v 1.3 2004/10/04 01:10:58 steve Exp $"
#endif
# include "vpi_priv.h"
static const struct __vpirt vpip_null_rt = {
0,
0,
0,
0,
0,
0,
0
};
static struct __vpiNull vpip_null = {
{ &vpip_null_rt }
};
extern struct __vpiNull *vpip_get_null(void)
{
return &vpip_null;
}
/*
* $Log: vpi_null.c,v $
* Revision 1.3 2004/10/04 01:10:58 steve
* Clean up spurious trailing white space.
*
* Revision 1.2 2002/08/12 01:35:05 steve
* conditional ident string using autoconfig.
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.4 2000/10/06 23:11:39 steve
* Replace data references with function calls. (Venkat)
*
* Revision 1.3 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.2 1999/12/15 04:01:14 steve
* Add the VPI implementation of $readmemh.
*
* Revision 1.1 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*
*/

View File

@ -1,303 +0,0 @@
/*
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_priv.c,v 1.5 2002/08/12 01:35:05 steve Exp $"
#endif
# include "vpi_priv.h"
# include <assert.h>
# include <stdarg.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
/*
* Keep a list of vpi_systf_data structures. This list is searched
* forward whenever a function is invoked by name, and items are
* pushed in front of the list whenever they are registered. This
* allows entries to override older entries.
*/
struct systf_entry {
struct systf_entry* next;
s_vpi_systf_data systf_data;
};
static struct systf_entry*systf_func_list = 0;
static struct systf_entry*systf_task_list = 0;
/* This is the handle of the task currently being called. */
static struct __vpiSysTaskCall*vpip_cur_task;
void vpip_calltask(struct __vpiScope*scope, const char*fname,
unsigned nparms, vpiHandle*parms)
{
struct systf_entry*idx;
struct __vpiSysTaskCall cur_task;
cur_task.base.vpi_type = vpip_get_systask_rt();
cur_task.scope = scope;
cur_task.args = parms;
cur_task.nargs = nparms;
cur_task.res = 0;
cur_task.nres = 0;
vpip_cur_task = &cur_task;
/* Look for a systf function to invoke. */
for (idx = systf_task_list ; idx ; idx = idx->next)
if (strcmp(fname, idx->systf_data.tfname) == 0) {
cur_task.info = &idx->systf_data;
idx->systf_data.calltf(idx->systf_data.user_data);
return;
}
/* Finally, if nothing is found then something is not
right. Print out the function name all the parameters
passed, so that someone can deal with it. */
vpi_printf("Call %s\n", fname);
}
/*
* System functions are kept in the same sort of table as the system
* tasks, and we call them in a similar manner.
*/
void vpip_callfunc(const char*fname, unsigned nres, vpip_bit_t*res,
unsigned nparms, vpiHandle*parms)
{
struct systf_entry*idx;
struct __vpiSysTaskCall cur_task;
cur_task.base.vpi_type = vpip_get_sysfunc_rt();
cur_task.args = parms;
cur_task.nargs = nparms;
cur_task.res = res;
cur_task.nres = nres;
vpip_cur_task = &cur_task;
/* Look for a systf function to invoke. */
for (idx = systf_func_list ; idx ; idx = idx->next)
if (strcmp(fname, idx->systf_data.tfname) == 0) {
cur_task.info = &idx->systf_data;
idx->systf_data.calltf(idx->systf_data.user_data);
return;
}
/* Finally, if nothing is found then something is not
right. Print out the function name all the parameters
passed, so that someone can deal with it. */
vpi_printf("Call %s with width==%u\n", fname, nres);
}
int vpi_free_object(vpiHandle ref)
{
free(ref);
return 0;
}
static int vpip_get_global(int property)
{
switch (property) {
case vpiTimePrecision:
return vpip_get_simulation_obj()->time_precision;
default:
assert(0);
return -1;
}
}
int vpi_get(int property, vpiHandle ref)
{
if (property == vpiType)
return ref->vpi_type->type_code;
if (ref == 0)
return vpip_get_global(property);
if (ref->vpi_type->vpi_get_ == 0)
return -1;
return (ref->vpi_type->vpi_get_)(property, ref);
}
char* vpi_get_str(int property, vpiHandle ref)
{
if (ref->vpi_type->vpi_get_str_ == 0)
return 0;
return (char*)(ref->vpi_type->vpi_get_str_)(property, ref);
}
void vpi_get_time(vpiHandle obj, s_vpi_time*t)
{
s_vpi_value value;
vpiHandle tm = vpip_sim_time();
value.format = vpiTimeVal;
vpi_get_value(tm, &value);
memcpy(t, value.value.time, sizeof (*t));
}
void vpi_get_value(vpiHandle expr, s_vpi_value*vp)
{
if (expr->vpi_type->vpi_get_value_) {
(expr->vpi_type->vpi_get_value_)(expr, vp);
return;
}
vp->format = vpiSuppressVal;
}
vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
s_vpi_time*tp, int flags)
{
if (obj->vpi_type->vpi_put_value_)
return (obj->vpi_type->vpi_put_value_)(obj, vp, tp, flags);
else
return 0;
}
vpiHandle vpi_handle(int type, vpiHandle ref)
{
if (type == vpiSysTfCall) {
assert(ref == 0);
return &vpip_cur_task->base;
}
assert(ref->vpi_type->handle_);
return (ref->vpi_type->handle_)(type, ref);
}
/*
* This function asks the object to return an iterator for
* the specified reference. It is up to the iterate_ method to
* allocate a properly formed iterator.
*/
vpiHandle vpi_iterate(int type, vpiHandle ref)
{
assert(ref->vpi_type->iterate_);
return (ref->vpi_type->iterate_)(type, ref);
}
vpiHandle vpi_handle_by_index(vpiHandle ref, int idx)
{
assert(ref->vpi_type->index_);
return (ref->vpi_type->index_)(ref, idx);
}
extern void vpi_vprintf(const char*fmt, va_list ap)
{
vprintf(fmt, ap);
}
extern void vpi_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap,fmt);
vpi_vprintf(fmt,ap);
va_end(ap);
}
/*
* This function adds the information that the user supplies to a list
* that I keep.
*/
void vpi_register_systf(const struct t_vpi_systf_data*systf)
{
struct systf_entry*cur = calloc(1, sizeof(struct systf_entry));
cur->systf_data = *systf;
cur->systf_data.tfname = strdup(systf->tfname);
switch (systf->type) {
case vpiSysFunc:
cur->next = systf_func_list;
systf_func_list = cur;
break;
case vpiSysTask:
cur->next = systf_task_list;
systf_task_list = cur;
break;
default:
assert(0);
}
}
/*
* $Log: vpi_priv.c,v $
* Revision 1.5 2002/08/12 01:35:05 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2001/10/26 02:29:10 steve
* const/non-const warnings. (Stephan Boettcher)
*
* Revision 1.3 2001/06/19 14:57:10 steve
* Get va_start arguments in right order.
*
* Revision 1.2 2001/06/12 03:53:10 steve
* Change the VPI call process so that loaded .vpi modules
* use a function table instead of implicit binding.
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.11 2000/10/28 00:51:42 steve
* Add scope to threads in vvm, pass that scope
* to vpi sysTaskFunc objects, and add vpi calls
* to access that information.
*
* $display displays scope in %m (PR#1)
*
* Revision 1.10 2000/10/06 23:11:39 steve
* Replace data references with function calls. (Venkat)
*
* Revision 1.9 2000/08/20 17:49:05 steve
* Clean up warnings and portability issues.
*
* Revision 1.8 2000/07/26 03:53:12 steve
* Make simulation precision available to VPI.
*
* Revision 1.7 2000/05/07 18:20:08 steve
* Import MCD support from Stephen Tell, and add
* system function parameter support to the IVL core.
*
* Revision 1.6 2000/05/04 03:37:59 steve
* Add infrastructure for system functions, move
* $time to that structure and add $random.
*
* Revision 1.5 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 2000/02/13 19:18:28 steve
* Accept memory words as parameter to $display.
*
* Revision 1.3 2000/01/20 06:04:55 steve
* $dumpall checkpointing in VCD dump.
*
* Revision 1.2 1999/12/15 04:01:14 steve
* Add the VPI implementation of $readmemh.
*
* Revision 1.1 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*
*/

View File

@ -1,542 +0,0 @@
#ifndef __vpi_priv_H
#define __vpi_priv_H
/*
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_priv.h,v 1.4 2004/10/04 01:10:58 steve Exp $"
#endif
/*
* This header file describes the "back side" of the VPI
* interface. The product that offers the VPI interface uses types and
* methods declared here to manage the VPI structures and provide the
* needed behaviors.
*/
# include "vpi_user.h"
#ifdef __cplusplus
extern "C" {
#endif
struct __vpirt;
/*
* The simulation engine internally carries the strengths along with
* the bit values, and that includes ambiguous strengths. The complete
* bit value (including ambiguity) is encoded in 8 bits like so:
*
* VSSSvsss
*
* The V and v bits encode the bit logic values, and the SSS and sss
* bits encode the strength range. The logic values are like so:
*
* 0SSS0sss - Logic 0
* 1SSS1sss - Logic 1
* 1xxx0xxx - Logic X
* 00001000 - Logic Z
*
* 00000000 - Invalid/No signal
*
* So as you can see, logic values can be quickly compared by masking
* the strength bits.
*
* If the value is unambiguous, then the SSS and sss bits have the
* same value, and encode the strength of the driven value. If the
* value is logic X, then "unambiguous" in this context means the
* strength is well known, even though the logic value is
* not. However, it is treated as ambiguous by the resolver.
*
* If the strength is ambiguous, then the high 4 bits are always
* arithmetically larger then the low 4 bits. For logic 0 and logic 1
* values, this means that the SSS value is >= the sss value. For
* logic X values, the 'V' bit is set and SSS is the strength toward 1,
* and the 'v' bit is 0 and sss is the strength toward 0.
*/
typedef unsigned char vpip_bit_t;
# define Su1 0xff //supply1
# define St1 0xee //strong1
# define Pu1 0xdd //pull1
# define La1 0xcc //large1
# define We1 0xbb //weak1
# define Me1 0xaa //medium1
# define Sm1 0x99 //samll1
# define Su0 0x77 //supply0
# define St0 0x66 //strong0
# define Pu0 0x55 //pull0
# define La0 0x44 //large0
# define We0 0x33 //weak0
# define Me0 0x22 //medium0
# define Sm0 0x11 //small0
# define SuX 0xf7 //supplyx
# define StX 0xe6 //strongx
# define PuX 0xd5 //pullx
# define LaX 0xc4 //largex
# define WeX 0xb3 //weakx
# define MeX 0xa2 //mediumx
# define SmX 0x91 //smallx
# define HiZ 0x08 //highz
# define HiZ0 0x08 //highz
# define HiZ1 0x08 //highz
# define StH 0xe8 //strong 1 highz
# define StL 0x06 //highz strong0
/* Compare the logic values of two vpip_bit_t variables. This
is like the === operator of Verilog, it ignored strengths. */
# define B_EQ(l,r) (((l)&0x88) == ((r)&0x88))
/* Test and return true if the value has ambiguous
strength. The logic value may yet be knowable. */
# define B_ISAMBIG(v) (((v)&0x0f) != (((v)>>4)&0x0f))
/* Test whether the value is of the specified logic value. It
is possible for even ambiguous signals to have a known
logic value. */
# define B_IS0(v) (((v)&0x88) == 0x00)
# define B_IS1(v) (((v)&0x88) == 0x88)
# define B_ISX(v) (((v)&0x88) == 0x80)
# define B_ISZ(v) ((v) == HiZ)
# define B_ISXZ(v) (1 & (((v)>>7) ^ ((v)>>3)))
/* Take as input an array of bits, and return the resolved
value. The result accounts for the strengths involved. */
extern vpip_bit_t vpip_pair_resolve(vpip_bit_t a, vpip_bit_t b);
extern vpip_bit_t vpip_bits_resolve(const vpip_bit_t*bits, unsigned nbits);
extern void vpip_bits_get_value(const vpip_bit_t*bits, unsigned nbits,
s_vpi_value*vp, int signed_flag);
extern void vpip_bits_set_value(vpip_bit_t*bits, unsigned nbits,
s_vpi_value*vp);
/*
* This structure is the very base of a vpiHandle. Every handle
* structure starts with this structure, so that the library can
* internally pass the derived types as pointers to one of these.
*/
struct __vpiHandle {
const struct __vpirt *vpi_type;
};
/*
* Objects with this structure are used to represent a type of
* vpiHandle. A specific object becomes of this type by holding a
* pointer to an instance of this structure.
*/
struct __vpirt {
int type_code;
/* These methods extract information from the handle. */
int (*vpi_get_)(int, vpiHandle);
const char* (*vpi_get_str_)(int, vpiHandle);
void (*vpi_get_value_)(vpiHandle, p_vpi_value);
vpiHandle (*vpi_put_value_)(vpiHandle, p_vpi_value, p_vpi_time, int);
/* These methods follow references. */
vpiHandle (*handle_)(int, vpiHandle);
vpiHandle (*iterate_)(int, vpiHandle);
vpiHandle (*index_)(vpiHandle, int);
};
/*
* This is a private handle type that doesn't seem to be well defined
* by the VPI standard.
*/
struct __vpiCallback {
struct __vpiHandle base;
struct t_cb_data cb_data;
/* Set this value if I'm pending in the event queue. */
struct vpip_event*ev;
/* Set this value if I'm waiting for a value change on a signal*/
struct __vpiSignal*sig;
struct __vpiCallback*next;
};
/*
* The vpiHandle for an iterator has this structure. The definition of
* the methods lives in vpi_iter.c
*/
struct __vpiIterator {
struct __vpiHandle base;
vpiHandle *args;
unsigned nargs;
unsigned next;
};
/*
* Memory is an array of bits that is accessible in N-bit chunks, with
* N being the width of a word. The memory word handle just points
* back to the memory and uses an index to identify its position in
* the memory.
*/
struct __vpiMemory {
struct __vpiHandle base;
/* The signal has a name (this points to static memory.) */
const char*name;
vpip_bit_t*bits;
struct __vpiMemoryWord*words;
vpiHandle*args;
unsigned width;
unsigned size;
};
struct __vpiMemoryWord {
struct __vpiHandle base;
struct __vpiMemory*mem;
int index;
};
/*
* This type is occasionally useful. Really! And while we're at it,
* create a single instance of the null object. (This is all we need.)
*/
struct __vpiNull {
struct __vpiHandle base;
};
extern struct __vpiNull *vpip_get_null(void);
/*
* This type represents the handle to a Verilog scope. These include
* module instantiations and named begin-end blocks. The attach
* function is used to attach handles to the scope by the runtime
* initialization.
*/
struct __vpiScope {
struct __vpiHandle base;
/* The scope has a name. (this points to static memory.) */
const char*name;
/* Keep an array of internal scope items. */
struct __vpiHandle**intern;
unsigned nintern;
};
extern void vpip_attach_to_scope(struct __vpiScope*scope, vpiHandle obj);
/*
* This structure represents nets and registers. You can tell which by
* the type_code in the base. The bits member points to the actual
* array of bits that the environment provides. The bits must persist
* as long as this object persists.
*/
struct __vpiSignal {
struct __vpiHandle base;
/* The signal has a name (this points to static memory.) */
const char*name;
/* The signal has a value and dimension. */
vpip_bit_t*bits;
unsigned nbits;
unsigned signed_flag : 1;
/* monitors are added here. */
struct __vpiCallback*mfirst;
struct __vpiCallback*mlast;
};
extern const struct __vpirt *vpip_get_systask_rt(void);
extern const struct __vpirt *vpip_get_sysfunc_rt(void);
struct __vpiSysTaskCall {
struct __vpiHandle base;
struct __vpiScope*scope;
s_vpi_systf_data*info;
vpiHandle*args;
unsigned nargs;
vpip_bit_t*res;
unsigned nres;
const char*file;
unsigned lineno;
int subtype;
};
/*
* Represent a TimeVar variable. The actual time is stored in the
* "time" member for fast manipulation by various bits of the
* simulation engine. The time_obj member is used as persistent
* storage of the time value when get_value is used (on the opaque
* handle) to the get time.
*/
struct __vpiTimeVar {
struct __vpiHandle base;
const char*name;
unsigned long time;
struct t_vpi_time time_obj;
};
struct __vpiStringConst {
struct __vpiHandle base;
const char*value;
};
struct __vpiNumberConst {
struct __vpiHandle base;
const vpip_bit_t*bits;
unsigned nbits;
};
/*
* These are methods to initialize specific handle types. Except for
* vpip_make_iterator, all the vpi_make_* functions expect the caller
* to allocate the memory for the handle. The result is the vpiHandle
* of the constructed object.
*/
extern vpiHandle vpip_make_iterator(unsigned nargs, vpiHandle*args);
extern vpiHandle vpip_make_net(struct __vpiSignal*ref, const char*name,
vpip_bit_t*bits, unsigned nbits,
int signed_flag);
extern vpiHandle vpip_make_scope(struct __vpiScope*ref,
int type_code,
const char*name);
extern vpiHandle vpip_make_string_const(struct __vpiStringConst*ref,
const char*val);
extern vpiHandle vpip_make_number_const(struct __vpiNumberConst*ref,
const vpip_bit_t*bits,
unsigned nbits);
extern vpiHandle vpip_make_memory(struct __vpiMemory*ref, const char*name,
unsigned width, unsigned size);
extern vpiHandle vpip_make_reg(struct __vpiSignal*ref, const char*name,
vpip_bit_t*bits, unsigned nbits,
int signed_flag);
extern vpiHandle vpip_make_time_var(struct __vpiTimeVar*ref,
const char*val);
/* Use this function to call a registered task. */
extern void vpip_calltask(struct __vpiScope*scope, const char*name,
unsigned nparms, vpiHandle*parms);
/*
* This calls a system function with a given name. The return value is
* taken by the res[] array.
*/
extern void vpip_callfunc(const char*name, unsigned nres, vpip_bit_t*res,
unsigned nparms, vpiHandle*parms);
extern void vpip_run_value_changes(struct __vpiSignal*sig);
/*
* The simulation object holds the current state of the
* simulation. There is a single global variable that is the
* simulation.
*/
struct vpip_simulation_cycle;
struct vpip_event;
struct vpip_simulation {
/* Current simulation time. */
struct __vpiTimeVar sim_time;
/* List of cbReadOnlySynch callbacks. */
struct __vpiCallback*read_sync_list;
/* List of simulation cycles, starting with the next time. */
struct vpip_simulation_cycle*sim;
int going_flag;
/* This is the precision of the simulation clock. It may be
used by the run time to scale time values. */
short time_precision;
};
extern struct vpip_simulation *vpip_get_simulation_obj(void);
extern void vpip_set_vlog_info(int argc, char**argv);
extern void vpip_init_simulation();
extern void vpip_time_scale(int precision);
extern void vpip_simulation_run();
extern void vpi_mcd_init(void);
/*
* Schedule an event to be run sometime in the future. The d parameter
* is the delay in simulation units before the event is processed. If
* the non-block flag is set, the event is scheduled to happen at the
* end of the time step.
*
* The return value from the insert method is a cookie that can be
* used to manipulate the event before it is executed.
*/
extern struct vpip_event* vpip_sim_insert_event(unsigned long d,
void*user_data,
void (*sim_fun)(void*),
int nonblock_flag);
extern void vpip_sim_cancel_event(struct vpip_event*cookie);
/*
* This function returns a handle to the vpiTimeVar that is th main
* simulation time clock.
*/
extern vpiHandle vpip_sim_time();
/*
* Return true if the going_flag is false.
*/
extern int vpip_finished();
#ifdef __cplusplus
}
#endif
/*
* $Log: vpi_priv.h,v $
* Revision 1.4 2004/10/04 01:10:58 steve
* Clean up spurious trailing white space.
*
* Revision 1.3 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2001/10/26 02:29:10 steve
* const/non-const warnings. (Stephan Boettcher)
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.31 2001/01/06 22:22:17 steve
* Support signed decimal display of variables.
*
* Revision 1.30 2000/11/11 01:52:09 steve
* change set for support of nmos, pmos, rnmos, rpmos, notif0, and notif1
* change set to correct behavior of bufif0 and bufif1
* (Tim Leight)
*
* Also includes fix for PR#27
*
* Revision 1.29 2000/10/28 00:51:42 steve
* Add scope to threads in vvm, pass that scope
* to vpi sysTaskFunc objects, and add vpi calls
* to access that information.
*
* $display displays scope in %m (PR#1)
*
* Revision 1.28 2000/10/06 23:11:39 steve
* Replace data references with function calls. (Venkat)
*
* Revision 1.27 2000/10/04 02:37:44 steve
* Use .def file instead of _dllexport.
*
* Revision 1.26 2000/10/03 16:15:35 steve
* Cleanup build of VPI modules under Cygwin. (Venkat)
*
* Revision 1.25 2000/09/30 03:20:48 steve
* Cygwin port changes from Venkat
*
* Revision 1.24 2000/09/08 17:08:10 steve
* initialize vlog info.
*
* Revision 1.23 2000/08/20 17:49:05 steve
* Clean up warnings and portability issues.
*
* Revision 1.22 2000/07/26 03:53:12 steve
* Make simulation precision available to VPI.
*
* Revision 1.21 2000/05/18 03:27:32 steve
* Support writing scalars and vectors to signals.
*
* Revision 1.20 2000/05/11 01:37:33 steve
* Calculate the X output value from drive0 and drive1
*
* Revision 1.19 2000/05/09 21:16:35 steve
* Give strengths to logic and bufz devices.
*
* Revision 1.18 2000/05/07 18:20:08 steve
* Import MCD support from Stephen Tell, and add
* system function parameter support to the IVL core.
*
* Revision 1.17 2000/05/07 04:37:56 steve
* Carry strength values from Verilog source to the
* pform and netlist for gates.
*
* Change vvm constants to use the driver_t to drive
* a constant value. This works better if there are
* multiple drivers on a signal.
*
* Revision 1.16 2000/05/04 03:37:59 steve
* Add infrastructure for system functions, move
* $time to that structure and add $random.
*
* Revision 1.15 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
* Revision 1.14 2000/03/31 07:08:39 steve
* allow cancelling of cbValueChange events.
*
* Revision 1.13 2000/03/25 05:02:24 steve
* signal bits are referenced at run time by the vpiSignal struct.
*
* Revision 1.12 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.11 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.10 2000/02/13 19:18:28 steve
* Accept memory words as parameter to $display.
*
* Revision 1.9 1999/12/15 04:01:14 steve
* Add the VPI implementation of $readmemh.
*
* Revision 1.8 1999/11/28 00:56:08 steve
* Build up the lists in the scope of a module,
* and get $dumpvars to scan the scope for items.
*
* Revision 1.7 1999/11/27 19:07:58 steve
* Support the creation of scopes.
*
* Revision 1.6 1999/11/10 02:52:24 steve
* Create the vpiMemory handle type.
*
* Revision 1.5 1999/11/06 16:52:16 steve
* complete value retrieval for number constants.
*
* Revision 1.4 1999/11/06 16:00:18 steve
* Put number constants into a static table.
*
* Revision 1.3 1999/10/29 03:37:22 steve
* Support vpiValueChance callbacks.
*
* Revision 1.2 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*
* Revision 1.1 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
*/
#endif

View File

@ -1,205 +0,0 @@
/*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_scope.c,v 1.3 2002/08/12 01:35:06 steve Exp $"
#endif
# include "vpi_priv.h"
# include <stdlib.h>
# include <assert.h>
static const char* scope_get_str(int code, vpiHandle obj)
{
struct __vpiScope*ref = (struct __vpiScope*)obj;
assert((obj->vpi_type->type_code == vpiModule)
|| (obj->vpi_type->type_code == vpiNamedBegin)
|| (obj->vpi_type->type_code == vpiTask));
switch (code) {
case vpiFullName:
return ref->name;
default:
assert(0);
return 0;
}
}
static vpiHandle module_iter(int code, vpiHandle obj)
{
struct __vpiScope*ref = (struct __vpiScope*)obj;
assert((obj->vpi_type->type_code == vpiModule)
|| (obj->vpi_type->type_code == vpiNamedBegin)
|| (obj->vpi_type->type_code == vpiTask)
|| (obj->vpi_type->type_code == vpiFunction));
switch (code) {
case vpiInternalScope:
return vpip_make_iterator(ref->nintern, ref->intern);
}
return 0;
}
static const struct __vpirt vpip_module_rt = {
vpiModule,
0,
scope_get_str,
0,
0,
0,
module_iter
};
static const struct __vpirt vpip_task_rt = {
vpiTask,
0,
scope_get_str,
0,
0,
0,
module_iter
};
static const struct __vpirt vpip_function_rt = {
vpiFunction,
0,
scope_get_str,
0,
0,
0,
module_iter
};
static const struct __vpirt vpip_named_begin_rt = {
vpiNamedBegin,
0,
scope_get_str,
0,
0,
0,
module_iter
};
static const struct __vpirt vpip_named_fork_rt = {
vpiNamedFork,
0,
0,
0,
0,
0,
module_iter
};
vpiHandle vpip_make_scope(struct __vpiScope*ref, int type, const char*name)
{
ref->intern = 0;
ref->nintern = 0;
ref->name = name;
switch (type) {
case vpiModule:
ref->base.vpi_type = &vpip_module_rt;
break;
case vpiNamedBegin:
ref->base.vpi_type = &vpip_named_begin_rt;
break;
case vpiNamedFork:
ref->base.vpi_type = &vpip_named_fork_rt;
break;
case vpiTask:
ref->base.vpi_type = &vpip_task_rt;
break;
case vpiFunction:
ref->base.vpi_type = &vpip_function_rt;
break;
default:
assert(0);
}
return &ref->base;
}
void vpip_attach_to_scope(struct __vpiScope*ref, vpiHandle obj)
{
unsigned idx = ref->nintern++;
if (ref->intern == 0)
ref->intern = malloc(sizeof(vpiHandle));
else
ref->intern = realloc(ref->intern, sizeof(vpiHandle)*ref->nintern);
ref->intern[idx] = obj;
}
/*
* $Log: vpi_scope.c,v $
* Revision 1.3 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2001/10/21 23:37:49 steve
* Kill const-nonconst warning.
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.11 2001/01/01 08:10:35 steve
* Handle function scopes in dumpvars scn (PR#95)
*
* Revision 1.10 2000/11/01 06:05:44 steve
* VCD scans tasks (PR#35)
*
* Revision 1.9 2000/10/29 17:10:02 steve
* task threads ned their scope initialized. (PR#32)
*
* Revision 1.8 2000/10/28 00:51:42 steve
* Add scope to threads in vvm, pass that scope
* to vpi sysTaskFunc objects, and add vpi calls
* to access that information.
*
* $display displays scope in %m (PR#1)
*
* Revision 1.7 2000/05/03 05:03:26 steve
* Support named for in VPI.
*
* Revision 1.6 2000/03/08 04:36:54 steve
* Redesign the implementation of scopes and parameters.
* I now generate the scopes and notice the parameters
* in a separate pass over the pform. Once the scopes
* are generated, I can process overrides and evalutate
* paremeters before elaboration begins.
*
* Revision 1.5 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 1999/12/15 18:21:20 steve
* Support named begin scope at run time.
*
* Revision 1.3 1999/12/15 04:01:14 steve
* Add the VPI implementation of $readmemh.
*
* Revision 1.2 1999/11/28 00:56:08 steve
* Build up the lists in the scope of a module,
* and get $dumpvars to scan the scope for items.
*
* Revision 1.1 1999/11/27 19:07:58 steve
* Support the creation of scopes.
*
*/

View File

@ -1,179 +0,0 @@
/*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_signal.c,v 1.3 2002/08/12 01:35:06 steve Exp $"
#endif
# include "vpi_priv.h"
# include <assert.h>
static int signal_get(int code, vpiHandle ref)
{
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
assert((ref->vpi_type->type_code==vpiNet)
|| (ref->vpi_type->type_code==vpiReg));
switch (code) {
case vpiSigned:
return rfp->signed_flag;
case vpiSize:
return rfp->nbits;
default:
return 0;
}
}
static const char* signal_get_str(int code, vpiHandle ref)
{
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
assert((ref->vpi_type->type_code==vpiNet)
|| (ref->vpi_type->type_code==vpiReg));
switch (code) {
case vpiFullName:
return (char*)rfp->name;
}
return 0;
}
static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
{
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
assert((ref->vpi_type->type_code==vpiNet)
|| (ref->vpi_type->type_code==vpiReg));
vpip_bits_get_value(rfp->bits, rfp->nbits, vp, rfp->signed_flag);
}
static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp,
p_vpi_time when, int flags)
{
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
assert((ref->vpi_type->type_code==vpiNet)
|| (ref->vpi_type->type_code==vpiReg));
vpip_bits_set_value(rfp->bits, rfp->nbits, vp);
return ref;
}
static const struct __vpirt vpip_net_rt = {
vpiNet,
signal_get,
signal_get_str,
signal_get_value,
signal_put_value,
0,
0
};
vpiHandle vpip_make_net(struct __vpiSignal*ref, const char*name,
vpip_bit_t*b, unsigned nb, int signed_flag)
{
ref->base.vpi_type = &vpip_net_rt;
ref->name = name;
ref->bits = b;
ref->nbits = nb;
ref->signed_flag = signed_flag? 1 : 0;
ref->mfirst = 0;
ref->mlast = 0;
return &(ref->base);
}
static const struct __vpirt vpip_reg_rt = {
vpiReg,
signal_get,
signal_get_str,
signal_get_value,
signal_put_value,
0,
0
};
vpiHandle vpip_make_reg(struct __vpiSignal*ref, const char*name,
vpip_bit_t*b, unsigned nb, int signed_flag)
{
ref->base.vpi_type = &vpip_reg_rt;
ref->name = name;
ref->bits = b;
ref->nbits = nb;
ref->signed_flag = signed_flag? 1 : 0;
ref->mfirst = 0;
ref->mlast = 0;
return &(ref->base);
}
/*
* $Log: vpi_signal.c,v $
* Revision 1.3 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2001/10/26 02:29:10 steve
* const/non-const warnings. (Stephan Boettcher)
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.12 2001/01/06 22:22:17 steve
* Support signed decimal display of variables.
*
* Revision 1.11 2000/08/20 17:49:05 steve
* Clean up warnings and portability issues.
*
* Revision 1.10 2000/05/18 03:27:32 steve
* Support writing scalars and vectors to signals.
*
* Revision 1.9 2000/03/31 07:08:39 steve
* allow cancelling of cbValueChange events.
*
* Revision 1.8 2000/03/25 05:02:25 steve
* signal bits are referenced at run time by the vpiSignal struct.
*
* Revision 1.7 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.6 1999/12/15 04:01:14 steve
* Add the VPI implementation of $readmemh.
*
* Revision 1.5 1999/11/07 20:33:30 steve
* Add VCD output and related system tasks.
*
* Revision 1.4 1999/11/07 02:25:08 steve
* Add the $monitor implementation.
*
* Revision 1.3 1999/11/06 16:52:16 steve
* complete value retrieval for number constants.
*
* Revision 1.2 1999/10/29 03:37:22 steve
* Support vpiValueChance callbacks.
*
* Revision 1.1 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*
*/

View File

@ -1,243 +0,0 @@
/*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_simulation.c,v 1.3 2002/08/12 01:35:06 steve Exp $"
#endif
# include "vpi_priv.h"
# include <stdlib.h>
# include <stdarg.h>
# include <assert.h>
struct vpip_event {
void*user_data;
void (*sim_fun)(void*);
struct vpip_event*next;
};
static struct vpip_simulation vpip_simulation_obj;
struct vpip_simulation *vpip_get_simulation_obj(void)
{
return &vpip_simulation_obj;
}
extern void vpi_sim_vcontrol(int func, va_list ap)
{
switch (func) {
case vpiFinish:
vpip_simulation_obj.going_flag = 0;
break;
}
}
/*
* The simulation event queue is a list of simulation cycles that in
* turn contain lists of simulation events. The simulation cycle
* represents the happening at some simulation time.
*/
struct vpip_simulation_cycle {
unsigned long delay;
struct vpip_simulation_cycle*next;
struct vpip_simulation_cycle*prev;
struct vpip_event*event_list;
struct vpip_event*event_last;
struct vpip_event*nonblock_list;
struct vpip_event*nonblock_last;
};
void vpip_init_simulation()
{
struct vpip_simulation_cycle*cur;
vpip_make_time_var(&vpip_simulation_obj.sim_time, "$time");
vpip_simulation_obj.read_sync_list = 0;
/* Allocate a header cell for the simulation event list. */
cur = calloc(1, sizeof(struct vpip_simulation_cycle));
cur->delay = 0;
cur->next = cur->prev = cur;
vpip_simulation_obj.sim = cur;
vpip_simulation_obj.time_precision = 0;
vpi_mcd_init();
}
void vpip_time_scale(int precision)
{
vpip_simulation_obj.time_precision = precision;
}
vpiHandle vpip_sim_time()
{
return &vpip_simulation_obj.sim_time.base;
}
struct vpip_event* vpip_sim_insert_event(unsigned long delay,
void*user_data,
void (*sim_fun)(void*),
int nonblock_flag)
{
struct vpip_event*event;
struct vpip_simulation_cycle*cur;
event = calloc(1, sizeof(struct vpip_event));
event->user_data = user_data;
event->sim_fun = sim_fun;
cur = vpip_simulation_obj.sim->next;
while ((cur != vpip_simulation_obj.sim) && (cur->delay < delay)) {
delay -= cur->delay;
cur = cur->next;
}
/* If there is no cycle cell for the specified time, create one. */
if ((cur == vpip_simulation_obj.sim) || (cur->delay > delay)) {
struct vpip_simulation_cycle*cell
= calloc(1,sizeof(struct vpip_simulation_cycle));
cell->delay = delay;
if (cur != vpip_simulation_obj.sim)
cur->delay -= delay;
cell->next = cur;
cell->prev = cur->prev;
cell->next->prev = cell;
cell->prev->next = cell;
cur = cell;
}
/* Put the event into the end of the cycle list. */
event->next = 0;
if (nonblock_flag) {
if (cur->nonblock_list == 0) {
cur->nonblock_list = cur->nonblock_last = event;
} else {
cur->nonblock_last->next = event;
cur->nonblock_last = event;
}
} else {
if (cur->event_list == 0) {
cur->event_list = cur->event_last = event;
} else {
cur->event_last->next = event;
cur->event_last = event;
}
}
return event;
}
void vpip_sim_cancel_event(struct vpip_event*ev)
{
assert(0);
}
int vpip_finished()
{
return ! vpip_simulation_obj.going_flag;
}
void vpip_simulation_run()
{
vpip_simulation_obj.sim_time.time = 0;
vpip_simulation_obj.going_flag = !0;
while (vpip_simulation_obj.going_flag) {
struct vpip_simulation_cycle*sim = vpip_simulation_obj.sim;
/* Step the time forward to the next time cycle. */
vpip_simulation_obj.sim_time.time += sim->delay;
sim->delay = 0;
while (vpip_simulation_obj.going_flag) {
struct vpip_event*active = sim->event_list;
sim->event_list = 0;
sim->event_last = 0;
if (active == 0) {
active = sim->nonblock_list;
sim->nonblock_list = 0;
sim->nonblock_last = 0;
}
if (active == 0)
break;
while (active && vpip_simulation_obj.going_flag) {
struct vpip_event*cur = active;
active = cur->next;
(cur->sim_fun)(cur->user_data);
free(cur);
}
}
if (! vpip_simulation_obj.going_flag)
break;
{ struct vpip_simulation_cycle*next = sim->next;
if (next == sim) {
vpip_simulation_obj.going_flag = 0;
break;
}
sim->next->prev = sim->prev;
sim->prev->next = sim->next;
free(sim);
vpip_simulation_obj.sim = next;
}
}
}
/*
* $Log: vpi_simulation.c,v $
* Revision 1.3 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2001/06/12 03:53:10 steve
* Change the VPI call process so that loaded .vpi modules
* use a function table instead of implicit binding.
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.5 2000/10/06 23:11:39 steve
* Replace data references with function calls. (Venkat)
*
* Revision 1.4 2000/08/20 17:49:05 steve
* Clean up warnings and portability issues.
*
* Revision 1.3 2000/07/26 03:53:12 steve
* Make simulation precision available to VPI.
*
* Revision 1.2 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.1 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*
*/

View File

@ -1,175 +0,0 @@
/*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_systask.c,v 1.5 2002/08/12 01:35:06 steve Exp $"
#endif
# include "vpi_priv.h"
# include <stdlib.h>
# include <assert.h>
static vpiHandle systask_handle(int type, vpiHandle ref)
{
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
assert((ref->vpi_type->type_code == vpiSysTaskCall)
|| (ref->vpi_type->type_code == vpiSysFuncCall));
switch (type) {
case vpiScope:
return &rfp->scope->base;
default:
assert(0);
return 0;
}
}
/*
* the iter function only supports getting an iterator of the
* arguments. This works equally well for tasks and functions.
*/
static vpiHandle systask_iter(int type, vpiHandle ref)
{
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
assert((ref->vpi_type->type_code == vpiSysTaskCall)
|| (ref->vpi_type->type_code == vpiSysFuncCall));
if (rfp->nargs == 0)
return 0;
return vpip_make_iterator(rfp->nargs, rfp->args);
}
static const struct __vpirt vpip_systask_rt = {
vpiSysTaskCall,
0,
0,
0,
0,
systask_handle,
systask_iter
};
const struct __vpirt *vpip_get_systask_rt(void)
{
return &vpip_systask_rt;
}
/*
* A value *can* be put to a vpiSysFuncCall object. This is how the
* return value is set. The value that is given should be converted to
* bits and set into the return value bit array.
*/
static vpiHandle sysfunc_put_value(vpiHandle ref, p_vpi_value val,
p_vpi_time t, int flag)
{
long tmp;
int idx;
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
assert(ref->vpi_type->type_code == vpiSysFuncCall);
/* There *must* be a return value array. */
assert(rfp->res);
assert(rfp->nres > 0);
/* XXXX For now, only support very specific formats. */
assert(val->format == vpiIntVal);
/* This fills the result bits with the signed value of the
integer. This automagically extends the sign bit by nature
of how the >> works in C. */
tmp = val->value.integer;
for (idx = 0 ; idx < rfp->nres ; idx += 1) {
rfp->res[idx] = (tmp&1) ? St1 : St0;
tmp >>= 1;
}
return 0;
}
static const struct __vpirt vpip_sysfunc_rt = {
vpiSysFuncCall,
0,
0,
0,
sysfunc_put_value,
0,
systask_iter
};
const struct __vpirt *vpip_get_sysfunc_rt(void)
{
return &vpip_sysfunc_rt;
}
/*
* $Log: vpi_systask.c,v $
* Revision 1.5 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2001/09/30 16:45:10 steve
* Fix some Cygwin DLL handling. (Venkat Iyer)
*
* Revision 1.3 2001/05/22 02:14:47 steve
* Update the mingw build to not require cygwin files.
*
* Revision 1.2 2001/05/20 15:09:40 steve
* Mingw32 support (Venkat Iyer)
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.9 2000/11/01 03:19:36 steve
* Add the general $time system function.
*
* Revision 1.8 2000/10/28 00:51:42 steve
* Add scope to threads in vvm, pass that scope
* to vpi sysTaskFunc objects, and add vpi calls
* to access that information.
*
* $display displays scope in %m (PR#1)
*
* Revision 1.7 2000/10/06 23:11:39 steve
* Replace data references with function calls. (Venkat)
*
* Revision 1.6 2000/09/30 03:20:48 steve
* Cygwin port changes from Venkat
*
* Revision 1.5 2000/05/07 18:20:08 steve
* Import MCD support from Stephen Tell, and add
* system function parameter support to the IVL core.
*
* Revision 1.4 2000/05/04 03:37:59 steve
* Add infrastructure for system functions, move
* $time to that structure and add $random.
*
* Revision 1.3 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.2 1999/12/15 04:01:14 steve
* Add the VPI implementation of $readmemh.
*
* Revision 1.1 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*
*/

View File

@ -1,97 +0,0 @@
/*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_time.c,v 1.2 2002/08/12 01:35:06 steve Exp $"
#endif
# include "vpi_priv.h"
# include <assert.h>
# include <stdio.h>
/*
* IEEE-1364 VPI pretty much mandates the existence of this sort of
* thing. (Either this or a huge memory leak.) Sorry.
*/
static char buf_obj[128];
static void timevar_get_value(vpiHandle ref, s_vpi_value*vp)
{
struct __vpiTimeVar*rfp = (struct __vpiTimeVar*)ref;
assert(ref->vpi_type->type_code == vpiTimeVar);
switch (vp->format) {
case vpiObjTypeVal:
case vpiTimeVal:
rfp->time_obj.low = rfp->time;
vp->value.time = &rfp->time_obj;
vp->format = vpiTimeVal;
break;
case vpiDecStrVal:
sprintf(buf_obj, "%lu", rfp->time);
vp->value.str = buf_obj;
break;
default:
vp->format = vpiSuppressVal;
vp->value.str = 0;
break;
}
}
static const struct __vpirt vpip_time_var_rt = {
vpiTimeVar,
0,
0,
timevar_get_value,
0,
0,
0
};
vpiHandle vpip_make_time_var(struct __vpiTimeVar*ref, const char*val)
{
ref->base.vpi_type = &vpip_time_var_rt;
ref->name = val;
return &(ref->base);
}
/*
* $Log: vpi_time.c,v $
* Revision 1.2 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.1 2001/03/14 19:27:44 steve
* Rearrange VPI support libraries.
*
* Revision 1.3 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.2 1999/12/15 04:01:14 steve
* Add the VPI implementation of $readmemh.
*
* Revision 1.1 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*
*/

View File

@ -1,91 +0,0 @@
/*
* Copyright (c) 2000 Adrian Lewis (indproj@yahoo.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_vlog_info.c,v 1.3 2002/08/12 01:35:06 steve Exp $"
#endif
#include <vpi_priv.h>
// STORAGE FOR COMMAND LINE ARGUMENTS
static int vpip_argc;
static char** vpip_argv;
// ROUTINE: vpi_get_vlog_info
//
// ARGUMENT: vlog_info_p
// Pointer to a structure containing simulation information.
//
// RETURNS:
// Boolean: true on success and false on failure.
//
// DESCRIPTION:
// Retrieve information about Verilog simulation execution.
int
vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p)
{
// AUTOMATICALLY UPDATING THE VERSION NUMBER WOULD BE A GOOD IDEA
static char* version = "$Name: $";
static char* product = "Icarus Verilog";
// CHECK THAT THE USER DIDN'T PASS A NULL POINTER
if (vlog_info_p != 0)
{
// FILL IN INFORMATION FIELDS
vlog_info_p->product = product;
vlog_info_p->version = version;
vlog_info_p->argc = vpip_argc;
vlog_info_p->argv = vpip_argv;
return 1==1;
}
else
return 1==0;
}
// ROUTINE: vpip_set_vlog_info
//
// ARGUMENTS: argc, argv
// Standard command line arguments.
//
// DESCRIPTION:
// Saves command line arguments to retrieval by vpi_get_vlog_info.
void
vpip_set_vlog_info(int argc, char** argv)
{
// SAVE COMMAND LINE ARGUMENTS IN STATIC VARIABLES
vpip_argc = argc;
vpip_argv = argv;
}
/*
* $Log: vpi_vlog_info.c,v $
* Revision 1.3 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2002/08/11 23:47:05 steve
* Add missing Log and Ident strings.
*
*/

View File

@ -1,55 +0,0 @@
EXPORTS
vpi_free_object
vpi_get
vpi_get_str
vpi_get_time
vpi_get_value
vpi_get_vlog_info
vpi_handle
vpi_handle_by_index
vpi_iterate
vpi_mcd_close
vpi_mcd_fgetc
vpi_mcd_fputc
vpi_mcd_init
vpi_mcd_name
vpi_mcd_open
vpi_mcd_open_x
vpi_mcd_printf
vpi_printf
vpi_put_value
vpi_register_cb
vpi_register_systf
vpi_remove_cb
vpi_scan
vpi_sim_control
vpip_attach_to_scope
vpip_bits_get_value
vpip_bits_resolve
vpip_bits_set_value
vpip_callfunc
vpip_calltask
vpip_finished
vpip_init_simulation
vpip_make_iterator
vpip_make_memory
vpip_make_net
vpip_make_number_const
vpip_make_reg
vpip_make_scope
vpip_make_string_const
vpip_make_time_var
vpip_get_null
vpip_pair_resolve
vpip_run_value_changes
vpip_set_vlog_info
vpip_sim_cancel_event
vpip_sim_insert_event
vpip_sim_time
vpip_get_simulation_obj
vpip_simulation_run
vpip_get_sysfunc_rt
vpip_get_systask_rt
vpip_time_scale

View File

@ -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);
}

View File

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

View File

@ -332,6 +332,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;
}
@ -727,7 +730,7 @@ 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);
}
@ -852,9 +855,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->vals = new vvp_vector4array_aa(arr->vals_width,
arr->array_count);
} else {
arr->vals = new vvp_vector4array_sa(arr->vals_width,
arr->array_count);
}
vpip_make_dec_const(&arr->msb, msb);
vpip_make_dec_const(&arr->lsb, lsb);
@ -908,11 +915,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 +943,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 +983,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 +992,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)
@ -1046,9 +1179,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);

View File

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

View File

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

View File

@ -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} },
@ -181,7 +183,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
{ "%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} },
@ -1687,34 +1689,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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
}

View File

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

View File

@ -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);
}
/*

View File

@ -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();

View File

@ -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);
}

View File

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

View File

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

View File

@ -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);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -43,6 +43,9 @@ static int real_var_get(int code, vpiHandle ref)
case vpiLineNo:
return 0; // Not implemented for now!
case vpiAutomatic:
return (int) rfp->scope->is_automatic;
}
return 0;
@ -131,11 +134,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:
@ -186,7 +191,7 @@ vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net)
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->net = net;
obj->scope = vpip_peek_current_scope();

View File

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

View File

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

View File

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

View File

@ -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;
}
@ -3944,19 +3976,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 +4046,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 +4232,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 +4339,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

View File

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

View File

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

View File

@ -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,65 @@ 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_vector4array_t::vvp_vector4array_t(unsigned width__, unsigned words__)
: width_(width__), words_(words__)
{
if (is_automatic) return;
}
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 +1373,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 +1385,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 +1432,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 +1460,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 +2297,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 +2315,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 +2362,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 +2459,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 +2475,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 +2485,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 +2532,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 +2547,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 +2603,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 +2619,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 +2652,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 +2660,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 +2689,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 +2843,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 +2975,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 +2985,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 +3016,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 +3034,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 +3131,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 +3141,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 +3196,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 **** */
/*

View File

@ -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);
@ -458,22 +470,19 @@ extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
/*
* vvp_vector4array_t
*/
class vvp_vector4array_t : public automatic_hooks_s {
class vvp_vector4array_t {
public:
vvp_vector4array_t(unsigned width, unsigned words, bool is_automatic);
~vvp_vector4array_t();
void alloc_instance(vvp_context_t context);
void reset_instance(vvp_context_t context);
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 +494,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 +970,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 +1033,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 +1053,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 +1078,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 +1099,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 +1237,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 +1276,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 +1283,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 +1354,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 +1384,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 +1484,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 +1495,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 +1535,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()];

View File

@ -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,40 @@ 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)
{
__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)
{