Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl
This commit is contained in:
commit
ea9bbf804c
130
BUGS.txt
130
BUGS.txt
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
10
PExpr.cc
10
PExpr.cc
|
|
@ -73,6 +73,16 @@ PEBComp::~PEBComp()
|
|||
{
|
||||
}
|
||||
|
||||
PEBLogic::PEBLogic(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
assert(op == 'a' || op == 'o');
|
||||
}
|
||||
|
||||
PEBLogic::~PEBLogic()
|
||||
{
|
||||
}
|
||||
|
||||
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
|
|
|
|||
20
PExpr.h
20
PExpr.h
|
|
@ -494,6 +494,26 @@ class PEBComp : public PEBinary {
|
|||
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* This derived class is for handling logical expressions: && and ||.
|
||||
*/
|
||||
class PEBLogic : public PEBinary {
|
||||
|
||||
public:
|
||||
explicit PEBLogic(char op, PExpr*l, PExpr*r);
|
||||
~PEBLogic();
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
ivl_variable_type_t&expr_type,
|
||||
bool&flag);
|
||||
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
};
|
||||
|
||||
class PEBShift : public PEBinary {
|
||||
|
|
|
|||
|
|
@ -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=.. )
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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)
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
127
elab_expr.cc
127
elab_expr.cc
|
|
@ -279,8 +279,6 @@ NetExpr* PEBinary::elaborate_expr_base_(Design*des,
|
|||
NetExpr*lp, NetExpr*rp,
|
||||
int expr_wid) const
|
||||
{
|
||||
bool flag;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: elaborate expression "
|
||||
<< *this << " expr_wid=" << expr_wid << endl;
|
||||
|
|
@ -296,11 +294,12 @@ NetExpr* PEBinary::elaborate_expr_base_(Design*des,
|
|||
|
||||
case 'a':
|
||||
case 'o':
|
||||
lp = condition_reduce(lp);
|
||||
rp = condition_reduce(rp);
|
||||
tmp = new NetEBLogic(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Elaboration of " << human_readable_op(op_)
|
||||
<< " Should have been handled in NetEBLogic::elaborate."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
|
||||
case 'p':
|
||||
tmp = new NetEBPow(op_, lp, rp);
|
||||
|
|
@ -341,38 +340,18 @@ NetExpr* PEBinary::elaborate_expr_base_(Design*des,
|
|||
|
||||
case 'E': /* === */
|
||||
case 'N': /* !== */
|
||||
if (lp->expr_type() == IVL_VT_REAL ||
|
||||
rp->expr_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< human_readable_op(op_)
|
||||
<< "may not have real operands." << endl;
|
||||
return 0;
|
||||
}
|
||||
/* Fall through... */
|
||||
case 'e': /* == */
|
||||
case 'n': /* != */
|
||||
if (dynamic_cast<NetEConst*>(rp)
|
||||
&& (lp->expr_width() > rp->expr_width()))
|
||||
rp->set_width(lp->expr_width());
|
||||
|
||||
if (dynamic_cast<NetEConst*>(lp)
|
||||
&& (lp->expr_width() < rp->expr_width()))
|
||||
lp->set_width(rp->expr_width());
|
||||
|
||||
/* from here, handle this like other compares. */
|
||||
case 'L': /* <= */
|
||||
case 'G': /* >= */
|
||||
case '<':
|
||||
case '>':
|
||||
tmp = new NetEBComp(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"expression bit width of comparison != 1." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
break;
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Elaboration of " << human_readable_op(op_)
|
||||
<< " Should have been handled in NetEBComp::elaborate."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
|
||||
case 'm': // min(l,r)
|
||||
case 'M': // max(l,r)
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, reg, par, eve);
|
||||
symbol_search(this, des, scope, path_, reg, par, eve);
|
||||
if (reg == 0) {
|
||||
cerr << get_fileline() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope_path(scope) <<
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, sig, par, eve);
|
||||
symbol_search(this, des, scope, path_, sig, par, eve);
|
||||
|
||||
if (eve != 0) {
|
||||
cerr << get_fileline() << ": error: named events (" << path_
|
||||
|
|
@ -631,4 +631,3 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
|||
|
||||
return sig;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,52 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
|
|||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*PEBComp::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*lp = left_->elaborate_pexpr(des, scope);
|
||||
NetExpr*rp = right_->elaborate_pexpr(des, scope);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
suppress_binary_operand_sign_if_needed_(lp, rp);
|
||||
|
||||
NetEBComp*tmp = new NetEBComp(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
bool flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"expression bit width of comparison != 1." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*PEBLogic::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*lp = left_->elaborate_pexpr(des, scope);
|
||||
NetExpr*rp = right_->elaborate_pexpr(des, scope);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEBLogic*tmp = new NetEBLogic(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
bool flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"expression bit width of comparison != 1." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Event though parameters are not generally sized, parameter
|
||||
* expressions can include concatenation expressions. This requires
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ bool PEIdent::elaborate_sig(Design*des, NetScope*scope) const
|
|||
if (error_implicit)
|
||||
return true;
|
||||
|
||||
symbol_search(des, scope, path_, sig, par, eve);
|
||||
symbol_search(this, des, scope, path_, sig, par, eve);
|
||||
|
||||
if (eve != 0)
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -2861,7 +2861,8 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
|||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, id->path(),
|
||||
NetScope*found_in = symbol_search(this, des, scope,
|
||||
id->path(),
|
||||
sig, par, eve);
|
||||
|
||||
if (found_in && eve) {
|
||||
|
|
@ -3463,7 +3464,7 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
|
|||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, event_,
|
||||
NetScope*found_in = symbol_search(this, des, scope, event_,
|
||||
sig, par, eve);
|
||||
|
||||
if (found_in == 0) {
|
||||
|
|
|
|||
29
emit.cc
29
emit.cc
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
2
eval.cc
2
eval.cc
|
|
@ -185,7 +185,7 @@ verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
|
|||
return new verinum(scope->genvar_tmp_val);
|
||||
}
|
||||
|
||||
symbol_search(des, scope, path_, net, expr, eve);
|
||||
symbol_search(this, des, scope, path_, net, expr, eve);
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -858,8 +858,10 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
|||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
// Make sure the expression is evaluated at the
|
||||
// expression width.
|
||||
verinum lval = pad_to_width(lc->value(), expr_width());
|
||||
verinum rval = pad_to_width(rc->value(), expr_width());
|
||||
|
||||
NetExpr*tmp = 0;
|
||||
switch (op_) {
|
||||
|
|
|
|||
18
functor.cc
18
functor.cc
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
3
main.cc
3
main.cc
|
|
@ -124,6 +124,7 @@ bool debug_eval_tree = false;
|
|||
bool debug_elaborate = false;
|
||||
bool debug_synth2 = false;
|
||||
bool debug_optimizer = false;
|
||||
bool debug_automatic = false;
|
||||
|
||||
/*
|
||||
* Verbose messages enabled.
|
||||
|
|
@ -392,6 +393,8 @@ static void read_iconfig_file(const char*ipath)
|
|||
} else if (strcmp(cp,"optimizer") == 0) {
|
||||
debug_optimizer = true;
|
||||
cerr << "debug: Enable optimizer debug" << endl;
|
||||
} else if (strcmp(cp,"automatic") == 0) {
|
||||
debug_automatic = true;
|
||||
} else {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -173,6 +173,12 @@ void NetEvent::find_similar_event(list<NetEvent*>&event_list)
|
|||
if (tmp == this)
|
||||
continue;
|
||||
|
||||
/* For automatic tasks, the VVP runtime holds state for events
|
||||
in the automatically allocated context. This means we can't
|
||||
merge similar events in different automatic tasks. */
|
||||
if (scope()->is_auto() && (tmp->scope() != scope()))
|
||||
continue;
|
||||
|
||||
if ((*idx).second != probe_count)
|
||||
continue;
|
||||
|
||||
|
|
@ -553,4 +559,3 @@ NetProc* NetEvWait::statement()
|
|||
* Simulate named event trigger and waits.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
34
net_scope.cc
34
net_scope.cc
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
12
netlist.h
12
netlist.h
|
|
@ -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);
|
||||
|
|
|
|||
14
netmisc.h
14
netmisc.h
|
|
@ -36,21 +36,25 @@
|
|||
* ex2 is the lsb expression for the range. If there is no range, then
|
||||
* these values are set to 0.
|
||||
*/
|
||||
extern NetScope* symbol_search(Design*des,
|
||||
NetScope*start, pform_name_t path,
|
||||
extern NetScope* symbol_search(const LineInfo*li,
|
||||
Design*des,
|
||||
NetScope*start,
|
||||
pform_name_t path,
|
||||
NetNet*&net, /* net/reg */
|
||||
const NetExpr*&par,/* parameter */
|
||||
NetEvent*&eve, /* named event */
|
||||
const NetExpr*&ex1, const NetExpr*&ex2);
|
||||
|
||||
inline NetScope* symbol_search(Design*des,
|
||||
NetScope*start, const pform_name_t&path,
|
||||
inline NetScope* symbol_search(const LineInfo*li,
|
||||
Design*des,
|
||||
NetScope*start,
|
||||
const pform_name_t&path,
|
||||
NetNet*&net, /* net/reg */
|
||||
const NetExpr*&par,/* parameter */
|
||||
NetEvent*&eve /* named event */)
|
||||
{
|
||||
const NetExpr*ex1, *ex2;
|
||||
return symbol_search(des, start, path, net, par, eve, ex1, ex2);
|
||||
return symbol_search(li, des, start, path, net, par, eve, ex1, ex2);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
4
parse.y
4
parse.y
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
31
pform.cc
31
pform.cc
|
|
@ -110,11 +110,12 @@ PTask* pform_push_task_scope(char*name, bool is_auto)
|
|||
PTask*task;
|
||||
if (pform_cur_generate) {
|
||||
task = new PTask(task_name, pform_cur_generate->lexical_scope,
|
||||
is_auto);
|
||||
is_auto || debug_automatic);
|
||||
pform_cur_generate->tasks[task->pscope_name()] = task;
|
||||
pform_cur_generate->lexical_scope = task;
|
||||
} else {
|
||||
task = new PTask(task_name, lexical_scope, is_auto);
|
||||
task = new PTask(task_name, lexical_scope,
|
||||
is_auto || debug_automatic);
|
||||
pform_cur_module->tasks[task->pscope_name()] = task;
|
||||
lexical_scope = task;
|
||||
}
|
||||
|
|
@ -129,11 +130,12 @@ PFunction* pform_push_function_scope(char*name, bool is_auto)
|
|||
PFunction*func;
|
||||
if (pform_cur_generate) {
|
||||
func = new PFunction(func_name, pform_cur_generate->lexical_scope,
|
||||
is_auto);
|
||||
is_auto || debug_automatic);
|
||||
pform_cur_generate->funcs[func->pscope_name()] = func;
|
||||
pform_cur_generate->lexical_scope = func;
|
||||
} else {
|
||||
func = new PFunction(func_name, lexical_scope, is_auto);
|
||||
func = new PFunction(func_name, lexical_scope,
|
||||
is_auto || debug_automatic);
|
||||
pform_cur_module->funcs[func->pscope_name()] = func;
|
||||
lexical_scope = func;
|
||||
}
|
||||
|
|
@ -181,6 +183,20 @@ static LexicalScope*pform_get_cur_scope()
|
|||
return lexical_scope;
|
||||
}
|
||||
|
||||
static bool pform_at_module_level()
|
||||
{
|
||||
if (pform_cur_generate)
|
||||
if (pform_cur_generate->lexical_scope)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
else
|
||||
if (lexical_scope->pscope_parent())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
PWire*pform_get_wire_in_scope(perm_string name)
|
||||
{
|
||||
/* Note that if we are processing a generate, then the
|
||||
|
|
@ -1293,6 +1309,13 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
|
|||
void pform_make_reginit(const struct vlltype&li,
|
||||
perm_string name, PExpr*expr)
|
||||
{
|
||||
if (! pform_at_module_level()) {
|
||||
VLerror(li, "variable declaration assignments are only "
|
||||
"allowed at the module level.");
|
||||
delete expr;
|
||||
return;
|
||||
}
|
||||
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
VLerror(li, "internal error: reginit to non-register?");
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@
|
|||
/*
|
||||
* Search for the hierarchical name.
|
||||
*/
|
||||
NetScope*symbol_search(Design*des, NetScope*scope, pform_name_t path,
|
||||
NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
|
||||
pform_name_t path,
|
||||
NetNet*&net,
|
||||
const NetExpr*&par,
|
||||
NetEvent*&eve,
|
||||
|
|
@ -57,6 +58,13 @@ NetScope*symbol_search(Design*des, NetScope*scope, pform_name_t path,
|
|||
return 0;
|
||||
|
||||
scope = des->find_scope(scope, path_list);
|
||||
|
||||
if (scope->is_auto() && li) {
|
||||
cerr << li->get_fileline() << ": error: Hierarchical "
|
||||
"reference to automatically allocated item "
|
||||
"`" << key << "' in path `" << path << "'" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (scope) {
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
case vpiTimeVar:
|
||||
case vpiReg: type = "reg"; }
|
||||
|
||||
if (skip) break;
|
||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||
|
||||
name = vpi_get_str(vpiName, item);
|
||||
nexus_id = vpi_get(_vpiNexusId, item);
|
||||
|
|
@ -593,7 +593,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
case vpiRealVar:
|
||||
|
||||
if (skip) break;
|
||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||
|
||||
name = vpi_get_str(vpiName, item);
|
||||
{ char*tmp = create_full_name(name);
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
case vpiTimeVar:
|
||||
case vpiReg: type = "reg"; }
|
||||
|
||||
if (skip) break;
|
||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||
|
||||
name = vpi_get_str(vpiName, item);
|
||||
nexus_id = vpi_get(_vpiNexusId, item);
|
||||
|
|
@ -603,7 +603,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
|
||||
case vpiRealVar:
|
||||
|
||||
if (skip) break;
|
||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||
|
||||
name = vpi_get_str(vpiName, item);
|
||||
{ char*tmp = create_full_name(name);
|
||||
|
|
|
|||
|
|
@ -513,7 +513,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
break;
|
||||
}
|
||||
|
||||
if (skip) break;
|
||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||
|
||||
name = vpi_get_str(vpiName, item);
|
||||
prefix = is_escaped_id(name) ? "\\" : "";
|
||||
|
|
@ -578,7 +578,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
|||
break;
|
||||
}
|
||||
|
||||
if (skip) break;
|
||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||
|
||||
/* Declare the variable in the VCD file. */
|
||||
name = vpi_get_str(vpiName, item);
|
||||
|
|
|
|||
|
|
@ -348,6 +348,7 @@ typedef struct t_vpi_delay {
|
|||
# define vpiSysFuncReal vpiRealFunc
|
||||
# define vpiSysFuncTime vpiTimeFunc
|
||||
# define vpiSysFuncSized vpiSizedFunc
|
||||
#define vpiAutomatic 50
|
||||
#define vpiConstantSelect 53
|
||||
#define vpiSigned 65
|
||||
/* IVL private properties */
|
||||
|
|
|
|||
101
vpip/Makefile.in
101
vpip/Makefile.in
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
166
vpip/vpi_bit.c
166
vpip/vpi_bit.c
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
526
vpip/vpi_const.c
526
vpip/vpi_const.c
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
160
vpip/vpi_mcd.c
160
vpip/vpi_mcd.c
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
303
vpip/vpi_priv.c
303
vpip/vpi_priv.c
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
542
vpip/vpi_priv.h
542
vpip/vpi_priv.h
|
|
@ -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
|
||||
205
vpip/vpi_scope.c
205
vpip/vpi_scope.c
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
|
@ -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
|
||||
180
vvp/arith.cc
180
vvp/arith.cc
|
|
@ -63,7 +63,8 @@ vvp_arith_abs::~vvp_arith_abs()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_abs::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_abs::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
vvp_vector4_t out (bit.size(), BIT4_0);;
|
||||
|
||||
|
|
@ -81,13 +82,14 @@ void vvp_arith_abs::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
break;
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, out);
|
||||
vvp_send_vec4(ptr.ptr()->out, out, 0);
|
||||
}
|
||||
|
||||
void vvp_arith_abs::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_abs::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
double out = fabs(bit);
|
||||
vvp_send_real(ptr.ptr()->out, out);
|
||||
vvp_send_real(ptr.ptr()->out, out, 0);
|
||||
}
|
||||
|
||||
vvp_arith_cast_int::vvp_arith_cast_int(unsigned wid)
|
||||
|
|
@ -99,9 +101,10 @@ vvp_arith_cast_int::~vvp_arith_cast_int()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_cast_int::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_cast_int::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
vvp_send_vec4(ptr.ptr()->out, vvp_vector4_t(wid_, bit));
|
||||
vvp_send_vec4(ptr.ptr()->out, vvp_vector4_t(wid_, bit), 0);
|
||||
}
|
||||
|
||||
vvp_arith_cast_real::vvp_arith_cast_real(bool signed_flag)
|
||||
|
|
@ -113,11 +116,12 @@ vvp_arith_cast_real::~vvp_arith_cast_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_cast_real::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_cast_real::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
double val;
|
||||
vector4_to_value(bit, val, signed_);
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
// Division
|
||||
|
|
@ -135,21 +139,22 @@ void vvp_arith_div::wide4_(vvp_net_ptr_t ptr)
|
|||
{
|
||||
vvp_vector2_t a2 (op_a_);
|
||||
if (a2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t b2 (op_b_);
|
||||
if (b2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t res2 = a2 / b2;
|
||||
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res2, wid_));
|
||||
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res2, wid_), 0);
|
||||
}
|
||||
|
||||
void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -160,13 +165,13 @@ void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
unsigned long a;
|
||||
if (! vector4_to_value(op_a_, a)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long b;
|
||||
if (! vector4_to_value(op_b_, b)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +207,7 @@ void vvp_arith_div::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
val >>= 1;
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, vval);
|
||||
vvp_send_vec4(ptr.ptr()->out, vval, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -219,21 +224,22 @@ void vvp_arith_mod::wide_(vvp_net_ptr_t ptr)
|
|||
{
|
||||
vvp_vector2_t a2 (op_a_);
|
||||
if (a2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t b2 (op_b_);
|
||||
if (b2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t res = a2 % b2;
|
||||
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res, res.size()));
|
||||
vvp_send_vec4(ptr.ptr()->out, vector2_to_vector4(res, res.size()), 0);
|
||||
}
|
||||
|
||||
void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -244,13 +250,13 @@ void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
unsigned long a;
|
||||
if (! vector4_to_value(op_a_, a)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long b;
|
||||
if (! vector4_to_value(op_b_, b)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +281,7 @@ void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1)
|
||||
xval.set_bit(idx, BIT4_X);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, xval);
|
||||
vvp_send_vec4(ptr.ptr()->out, xval, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -295,7 +301,7 @@ void vvp_arith_mod::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
val >>= 1;
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, vval);
|
||||
vvp_send_vec4(ptr.ptr()->out, vval, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -316,17 +322,18 @@ void vvp_arith_mult::wide_(vvp_net_ptr_t ptr)
|
|||
vvp_vector2_t b2 (op_b_);
|
||||
|
||||
if (a2.is_NaN() || b2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vvp_vector2_t result = a2 * b2;
|
||||
|
||||
vvp_vector4_t res4 = vector2_to_vector4(result, wid_);
|
||||
vvp_send_vec4(ptr.ptr()->out, res4);
|
||||
vvp_send_vec4(ptr.ptr()->out, res4, 0);
|
||||
}
|
||||
|
||||
void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -337,13 +344,13 @@ void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
long a;
|
||||
if (! vector4_to_value(op_a_, a, false, true)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
long b;
|
||||
if (! vector4_to_value(op_b_, b, false, true)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -360,7 +367,7 @@ void vvp_arith_mult::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
val >>= 1;
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, vval);
|
||||
vvp_send_vec4(ptr.ptr()->out, vval, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -375,14 +382,15 @@ vvp_arith_pow::~vvp_arith_pow()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
vvp_vector4_t res4;
|
||||
if (signed_flag_) {
|
||||
if (op_a_.has_xz() || op_b_.has_xz()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -396,7 +404,7 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
vvp_vector2_t b2 (op_b_);
|
||||
|
||||
if (a2.is_NaN() || b2.is_NaN()) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -404,7 +412,7 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
res4 = vector2_to_vector4(result, wid_);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res4);
|
||||
vvp_send_vec4(ptr.ptr()->out, res4, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -419,7 +427,8 @@ vvp_arith_sum::~vvp_arith_sum()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_sum::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_sum::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -438,14 +447,14 @@ void vvp_arith_sum::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
vvp_bit4_t cur = add_with_carry(a, b, carry);
|
||||
|
||||
if (cur == BIT4_X) {
|
||||
vvp_send_vec4(net->out, x_val_);
|
||||
vvp_send_vec4(net->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
value.set_bit(idx, cur);
|
||||
}
|
||||
|
||||
vvp_send_vec4(net->out, value);
|
||||
vvp_send_vec4(net->out, value, 0);
|
||||
}
|
||||
|
||||
vvp_arith_sub::vvp_arith_sub(unsigned wid)
|
||||
|
|
@ -463,7 +472,8 @@ vvp_arith_sub::~vvp_arith_sub()
|
|||
* further reduce the operation to adding in the inverted value and
|
||||
* adding a correction.
|
||||
*/
|
||||
void vvp_arith_sub::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_arith_sub::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -482,14 +492,14 @@ void vvp_arith_sub::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
vvp_bit4_t cur = add_with_carry(a, b, carry);
|
||||
|
||||
if (cur == BIT4_X) {
|
||||
vvp_send_vec4(net->out, x_val_);
|
||||
vvp_send_vec4(net->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
value.set_bit(idx, cur);
|
||||
}
|
||||
|
||||
vvp_send_vec4(net->out, value);
|
||||
vvp_send_vec4(net->out, value, 0);
|
||||
}
|
||||
|
||||
vvp_cmp_eeq::vvp_cmp_eeq(unsigned wid)
|
||||
|
|
@ -497,7 +507,8 @@ vvp_cmp_eeq::vvp_cmp_eeq(unsigned wid)
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_eeq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_cmp_eeq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -513,7 +524,7 @@ void vvp_cmp_eeq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_send_vec4(net->out, eeq);
|
||||
vvp_send_vec4(net->out, eeq, 0);
|
||||
}
|
||||
|
||||
vvp_cmp_nee::vvp_cmp_nee(unsigned wid)
|
||||
|
|
@ -521,7 +532,8 @@ vvp_cmp_nee::vvp_cmp_nee(unsigned wid)
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_nee::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_cmp_nee::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -537,7 +549,7 @@ void vvp_cmp_nee::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_send_vec4(net->out, eeq);
|
||||
vvp_send_vec4(net->out, eeq, 0);
|
||||
}
|
||||
|
||||
vvp_cmp_eq::vvp_cmp_eq(unsigned wid)
|
||||
|
|
@ -551,7 +563,8 @@ vvp_cmp_eq::vvp_cmp_eq(unsigned wid)
|
|||
* there are X/Z bits anywhere in A or B, the result is X. Finally,
|
||||
* the result is 1.
|
||||
*/
|
||||
void vvp_cmp_eq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_cmp_eq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -583,7 +596,7 @@ void vvp_cmp_eq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
}
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_send_vec4(net->out, res);
|
||||
vvp_send_vec4(net->out, res, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -598,7 +611,8 @@ vvp_cmp_ne::vvp_cmp_ne(unsigned wid)
|
|||
* there are X/Z bits anywhere in A or B, the result is X. Finally,
|
||||
* the result is 0.
|
||||
*/
|
||||
void vvp_cmp_ne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_cmp_ne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -630,7 +644,7 @@ void vvp_cmp_ne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
}
|
||||
|
||||
vvp_net_t*net = ptr.ptr();
|
||||
vvp_send_vec4(net->out, res);
|
||||
vvp_send_vec4(net->out, res, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -651,7 +665,7 @@ void vvp_cmp_gtge_base_::recv_vec4_base_(vvp_net_ptr_t ptr,
|
|||
: compare_gtge(op_a_, op_b_, out_if_equal);
|
||||
vvp_vector4_t val (1);
|
||||
val.set_bit(0, out);
|
||||
vvp_send_vec4(ptr.ptr()->out, val);
|
||||
vvp_send_vec4(ptr.ptr()->out, val, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -662,7 +676,8 @@ vvp_cmp_ge::vvp_cmp_ge(unsigned wid, bool flag)
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_ge::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_cmp_ge::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
recv_vec4_base_(ptr, bit, BIT4_1);
|
||||
}
|
||||
|
|
@ -672,7 +687,8 @@ vvp_cmp_gt::vvp_cmp_gt(unsigned wid, bool flag)
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_gt::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_cmp_gt::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
recv_vec4_base_(ptr, bit, BIT4_0);
|
||||
}
|
||||
|
|
@ -687,7 +703,8 @@ vvp_shiftl::~vvp_shiftl()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -695,7 +712,7 @@ void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
unsigned long shift;
|
||||
if (! vector4_to_value(op_b_, shift)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -708,7 +725,7 @@ void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
for (unsigned idx = shift ; idx < out.size() ; idx += 1)
|
||||
out.set_bit(idx, op_a_.value(idx-shift));
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, out);
|
||||
vvp_send_vec4(ptr.ptr()->out, out, 0);
|
||||
}
|
||||
|
||||
vvp_shiftr::vvp_shiftr(unsigned wid, bool signed_flag)
|
||||
|
|
@ -720,7 +737,8 @@ vvp_shiftr::~vvp_shiftr()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -728,7 +746,7 @@ void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
|
||||
unsigned long shift;
|
||||
if (! vector4_to_value(op_b_, shift)) {
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_);
|
||||
vvp_send_vec4(ptr.ptr()->out, x_val_, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -745,7 +763,7 @@ void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
for (unsigned idx = 0 ; idx < shift ; idx += 1)
|
||||
out.set_bit(idx+out.size()-shift, pad);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, out);
|
||||
vvp_send_vec4(ptr.ptr()->out, out, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -780,12 +798,13 @@ vvp_arith_mult_real::~vvp_arith_mult_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_mult_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_mult_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = op_a_ * op_b_;
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
/* Real power. */
|
||||
|
|
@ -797,12 +816,13 @@ vvp_arith_pow_real::~vvp_arith_pow_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_pow_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_pow_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = pow(op_a_, op_b_);
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
/* Real division. */
|
||||
|
|
@ -814,12 +834,13 @@ vvp_arith_div_real::~vvp_arith_div_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_div_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_div_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = op_a_ / op_b_;
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
/* Real modulus. */
|
||||
|
|
@ -831,12 +852,13 @@ vvp_arith_mod_real::~vvp_arith_mod_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_mod_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_mod_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = fmod(op_a_, op_b_);
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
/* Real summation. */
|
||||
|
|
@ -848,12 +870,13 @@ vvp_arith_sum_real::~vvp_arith_sum_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_sum_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_sum_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = op_a_ + op_b_;
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
/* Real subtraction. */
|
||||
|
|
@ -865,12 +888,13 @@ vvp_arith_sub_real::~vvp_arith_sub_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_arith_sub_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_arith_sub_real::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
double val = op_a_ - op_b_;
|
||||
vvp_send_real(ptr.ptr()->out, val);
|
||||
vvp_send_real(ptr.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
/* Real compare equal. */
|
||||
|
|
@ -878,7 +902,8 @@ vvp_cmp_eq_real::vvp_cmp_eq_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_eq_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
||||
void vvp_cmp_eq_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -886,7 +911,7 @@ void vvp_cmp_eq_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
|||
if (op_a_ == op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res);
|
||||
vvp_send_vec4(ptr.ptr()->out, res, 0);
|
||||
}
|
||||
|
||||
/* Real compare not equal. */
|
||||
|
|
@ -894,7 +919,8 @@ vvp_cmp_ne_real::vvp_cmp_ne_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_ne_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
||||
void vvp_cmp_ne_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -902,7 +928,7 @@ void vvp_cmp_ne_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
|||
if (op_a_ != op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res);
|
||||
vvp_send_vec4(ptr.ptr()->out, res, 0);
|
||||
}
|
||||
|
||||
/* Real compare greater than or equal. */
|
||||
|
|
@ -910,7 +936,8 @@ vvp_cmp_ge_real::vvp_cmp_ge_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_ge_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
||||
void vvp_cmp_ge_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -918,7 +945,7 @@ void vvp_cmp_ge_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
|||
if (op_a_ >= op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res);
|
||||
vvp_send_vec4(ptr.ptr()->out, res, 0);
|
||||
}
|
||||
|
||||
/* Real compare greater than. */
|
||||
|
|
@ -926,7 +953,8 @@ vvp_cmp_gt_real::vvp_cmp_gt_real()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_cmp_gt_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
||||
void vvp_cmp_gt_real::recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
dispatch_operand_(ptr, bit);
|
||||
|
||||
|
|
@ -934,5 +962,5 @@ void vvp_cmp_gt_real::recv_real(vvp_net_ptr_t ptr, const double bit)
|
|||
if (op_a_ > op_b_) res.set_bit(0, BIT4_1);
|
||||
else res.set_bit(0, BIT4_0);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, res);
|
||||
vvp_send_vec4(ptr.ptr()->out, res, 0);
|
||||
}
|
||||
|
|
|
|||
84
vvp/arith.h
84
vvp/arith.h
|
|
@ -54,8 +54,10 @@ class vvp_arith_abs : public vvp_net_fun_t {
|
|||
explicit vvp_arith_abs();
|
||||
~vvp_arith_abs();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
@ -65,7 +67,8 @@ class vvp_arith_cast_int : public vvp_net_fun_t {
|
|||
explicit vvp_arith_cast_int(unsigned wid);
|
||||
~vvp_arith_cast_int();
|
||||
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
unsigned wid_;
|
||||
|
|
@ -76,7 +79,8 @@ class vvp_arith_cast_real : public vvp_net_fun_t {
|
|||
explicit vvp_arith_cast_real(bool signed_flag);
|
||||
~vvp_arith_cast_real();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
bool signed_;
|
||||
|
|
@ -87,7 +91,8 @@ class vvp_arith_div : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_arith_div(unsigned wid, bool signed_flag);
|
||||
~vvp_arith_div();
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
private:
|
||||
void wide4_(vvp_net_ptr_t ptr);
|
||||
bool signed_flag_;
|
||||
|
|
@ -98,7 +103,8 @@ class vvp_arith_mod : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_arith_mod(unsigned wid, bool signed_flag);
|
||||
~vvp_arith_mod();
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
private:
|
||||
void wide_(vvp_net_ptr_t ptr);
|
||||
bool signed_flag_;
|
||||
|
|
@ -114,7 +120,8 @@ class vvp_cmp_eeq : public vvp_arith_ {
|
|||
|
||||
public:
|
||||
explicit vvp_cmp_eeq(unsigned wid);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -122,7 +129,8 @@ class vvp_cmp_nee : public vvp_arith_ {
|
|||
|
||||
public:
|
||||
explicit vvp_cmp_nee(unsigned wid);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -130,7 +138,8 @@ class vvp_cmp_eq : public vvp_arith_ {
|
|||
|
||||
public:
|
||||
explicit vvp_cmp_eq(unsigned wid);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -138,7 +147,8 @@ class vvp_cmp_ne : public vvp_arith_ {
|
|||
|
||||
public:
|
||||
explicit vvp_cmp_ne(unsigned wid);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -165,7 +175,8 @@ class vvp_cmp_ge : public vvp_cmp_gtge_base_ {
|
|||
public:
|
||||
explicit vvp_cmp_ge(unsigned wid, bool signed_flag);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -174,7 +185,8 @@ class vvp_cmp_gt : public vvp_cmp_gtge_base_ {
|
|||
public:
|
||||
explicit vvp_cmp_gt(unsigned wid, bool signed_flag);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -187,7 +199,8 @@ class vvp_arith_mult : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_arith_mult(unsigned wid);
|
||||
~vvp_arith_mult();
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
private:
|
||||
void wide_(vvp_net_ptr_t ptr);
|
||||
};
|
||||
|
|
@ -197,7 +210,8 @@ class vvp_arith_pow : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_arith_pow(unsigned wid, bool signed_flag);
|
||||
~vvp_arith_pow();
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
private:
|
||||
bool signed_flag_;
|
||||
};
|
||||
|
|
@ -207,7 +221,8 @@ class vvp_arith_sub : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_arith_sub(unsigned wid);
|
||||
~vvp_arith_sub();
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -216,7 +231,8 @@ class vvp_arith_sum : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_arith_sum(unsigned wid);
|
||||
~vvp_arith_sum();
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -225,7 +241,8 @@ class vvp_shiftl : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_shiftl(unsigned wid);
|
||||
~vvp_shiftl();
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_shiftr : public vvp_arith_ {
|
||||
|
|
@ -233,7 +250,8 @@ class vvp_shiftr : public vvp_arith_ {
|
|||
public:
|
||||
explicit vvp_shiftr(unsigned wid, bool signed_flag);
|
||||
~vvp_shiftr();
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
bool signed_flag_;
|
||||
|
|
@ -263,7 +281,8 @@ class vvp_arith_sum_real : public vvp_arith_real_ {
|
|||
public:
|
||||
explicit vvp_arith_sum_real();
|
||||
~vvp_arith_sum_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_arith_div_real : public vvp_arith_real_ {
|
||||
|
|
@ -271,7 +290,8 @@ class vvp_arith_div_real : public vvp_arith_real_ {
|
|||
public:
|
||||
explicit vvp_arith_div_real();
|
||||
~vvp_arith_div_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_arith_mod_real : public vvp_arith_real_ {
|
||||
|
|
@ -279,7 +299,8 @@ class vvp_arith_mod_real : public vvp_arith_real_ {
|
|||
public:
|
||||
explicit vvp_arith_mod_real();
|
||||
~vvp_arith_mod_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_arith_mult_real : public vvp_arith_real_ {
|
||||
|
|
@ -287,7 +308,8 @@ class vvp_arith_mult_real : public vvp_arith_real_ {
|
|||
public:
|
||||
explicit vvp_arith_mult_real();
|
||||
~vvp_arith_mult_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_arith_pow_real : public vvp_arith_real_ {
|
||||
|
|
@ -295,7 +317,8 @@ class vvp_arith_pow_real : public vvp_arith_real_ {
|
|||
public:
|
||||
explicit vvp_arith_pow_real();
|
||||
~vvp_arith_pow_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_arith_sub_real : public vvp_arith_real_ {
|
||||
|
|
@ -303,35 +326,40 @@ class vvp_arith_sub_real : public vvp_arith_real_ {
|
|||
public:
|
||||
explicit vvp_arith_sub_real();
|
||||
~vvp_arith_sub_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_cmp_eq_real : public vvp_arith_real_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_eq_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_cmp_ne_real : public vvp_arith_real_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_ne_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_cmp_ge_real : public vvp_arith_real_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_ge_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
class vvp_cmp_gt_real : public vvp_arith_real_ {
|
||||
|
||||
public:
|
||||
explicit vvp_cmp_gt_real();
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit);
|
||||
void recv_real(vvp_net_ptr_t ptr, const double bit,
|
||||
vvp_context_t);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
167
vvp/array.cc
167
vvp/array.cc
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ vvp_fun_bufif::vvp_fun_bufif(bool en_invert, bool out_invert,
|
|||
count_functors_bufif += 1;
|
||||
}
|
||||
|
||||
void vvp_fun_bufif::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_bufif::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
switch (ptr.port()) {
|
||||
case 0:
|
||||
|
|
@ -115,4 +116,3 @@ void vvp_fun_bufif::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
* Revision 1.8 2002/08/12 01:35:07 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ class vvp_fun_bufif : public vvp_net_fun_t {
|
|||
vvp_fun_bufif(bool en_invert, bool out_invert,
|
||||
unsigned str0, unsigned str1);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
vvp_vector4_t bit_;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -356,8 +356,7 @@ extern void compile_ufunc(char*label, char*code, unsigned wid,
|
|||
* the threads.
|
||||
*/
|
||||
extern void compile_event(char*label, char*type,
|
||||
unsigned argc, struct symb_s*argv,
|
||||
bool debug_flag);
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_named_event(char*label, char*type);
|
||||
|
||||
|
||||
|
|
@ -406,9 +405,6 @@ extern void compile_fork(char*label, struct symb_s targ_s,
|
|||
struct symb_s scope_s);
|
||||
extern void compile_codelabel(char*label);
|
||||
|
||||
extern void compile_alloc(char*label, struct symb_s scope_s);
|
||||
extern void compile_free(char*label, struct symb_s scope_s);
|
||||
|
||||
/*
|
||||
* The parser uses these functions to compile .scope statements.
|
||||
* The implementations of these live in the vpi_scope.cc file.
|
||||
|
|
@ -443,12 +439,13 @@ extern void compile_net_real(char*label, char*name,
|
|||
|
||||
extern void compile_netw(char*label, char*array_symbol,
|
||||
unsigned long array_addr,
|
||||
int msb, int lsb, bool signed_flag,
|
||||
bool net8_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
int msb, int lsb, bool signed_flag,
|
||||
bool net8_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_netw_real(char*label, char*array_symbol,
|
||||
int msb, int lsb,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
unsigned long array_addr,
|
||||
int msb, int lsb,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
extern void compile_alias(char*label, char*name,
|
||||
int msb, int lsb, bool signed_flag,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ vvp_fun_concat::~vvp_fun_concat()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_concat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_concat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
unsigned pdx = port.port();
|
||||
|
||||
|
|
@ -64,7 +65,7 @@ void vvp_fun_concat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
val_.set_bit(off+idx, bit.value(idx));
|
||||
}
|
||||
|
||||
vvp_send_vec4(port.ptr()->out, val_);
|
||||
vvp_send_vec4(port.ptr()->out, val_, 0);
|
||||
}
|
||||
|
||||
void compile_concat(char*label, unsigned w0, unsigned w1,
|
||||
|
|
@ -91,7 +92,8 @@ vvp_fun_repeat::~vvp_fun_repeat()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_repeat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_repeat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(bit.size() == wid_/rep_);
|
||||
|
||||
|
|
@ -105,7 +107,7 @@ void vvp_fun_repeat::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
|
||||
}
|
||||
|
||||
vvp_send_vec4(port.ptr()->out, val);
|
||||
vvp_send_vec4(port.ptr()->out, val, 0);
|
||||
}
|
||||
|
||||
void compile_repeat(char*label, long width, long repeat, struct symb_s arg)
|
||||
|
|
@ -140,4 +142,3 @@ void compile_repeat(char*label, long width, long repeat, struct symb_s arg)
|
|||
* Add missing concat.cc to cvs
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
22
vvp/delay.cc
22
vvp/delay.cc
|
|
@ -183,7 +183,8 @@ void vvp_fun_delay::clean_pulse_events_(vvp_time64_t use_delay)
|
|||
* wrong. What should happen is that if there are multiple changes,
|
||||
* multiple vectors approaching the result should be scheduled.
|
||||
*/
|
||||
void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (port.port() > 0) {
|
||||
// Get the integer value of the bit vector, or 0 if
|
||||
|
|
@ -248,7 +249,7 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
if (use_delay == 0) {
|
||||
cur_vec4_ = bit;
|
||||
initial_ = false;
|
||||
vvp_send_vec4(net_->out, cur_vec4_);
|
||||
vvp_send_vec4(net_->out, cur_vec4_, 0);
|
||||
} else {
|
||||
struct event_*cur = new struct event_(use_simtime);
|
||||
cur->run_run_ptr = &vvp_fun_delay::run_run_vec4_;
|
||||
|
|
@ -283,7 +284,8 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit)
|
||||
void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (port.port() > 0) {
|
||||
/* If the port is not 0, then this is a delay value that
|
||||
|
|
@ -328,7 +330,7 @@ void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit)
|
|||
if (use_delay == 0) {
|
||||
cur_real_ = bit;
|
||||
initial_ = false;
|
||||
vvp_send_real(net_->out, cur_real_);
|
||||
vvp_send_real(net_->out, cur_real_, 0);
|
||||
} else {
|
||||
struct event_*cur = new struct event_(use_simtime);
|
||||
cur->run_run_ptr = &vvp_fun_delay::run_run_real_;
|
||||
|
|
@ -357,7 +359,7 @@ void vvp_fun_delay::run_run()
|
|||
void vvp_fun_delay::run_run_vec4_(struct event_*cur)
|
||||
{
|
||||
cur_vec4_ = cur->ptr_vec4;
|
||||
vvp_send_vec4(net_->out, cur_vec4_);
|
||||
vvp_send_vec4(net_->out, cur_vec4_, 0);
|
||||
}
|
||||
|
||||
void vvp_fun_delay::run_run_vec8_(struct vvp_fun_delay::event_*cur)
|
||||
|
|
@ -369,7 +371,7 @@ void vvp_fun_delay::run_run_vec8_(struct vvp_fun_delay::event_*cur)
|
|||
void vvp_fun_delay::run_run_real_(struct vvp_fun_delay::event_*cur)
|
||||
{
|
||||
cur_real_ = cur->ptr_real;
|
||||
vvp_send_real(net_->out, cur_real_);
|
||||
vvp_send_real(net_->out, cur_real_, 0);
|
||||
}
|
||||
|
||||
vvp_fun_modpath::vvp_fun_modpath(vvp_net_t*net)
|
||||
|
|
@ -418,7 +420,8 @@ static vvp_time64_t delay_from_edge(vvp_bit4_t a, vvp_bit4_t b,
|
|||
return array[ edge_table[a][b] ];
|
||||
}
|
||||
|
||||
void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
/* Only the first port is used. */
|
||||
if (port.port() > 0)
|
||||
|
|
@ -532,7 +535,7 @@ void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
|
||||
void vvp_fun_modpath::run_run()
|
||||
{
|
||||
vvp_send_vec4(net_->out, cur_vec4_);
|
||||
vvp_send_vec4(net_->out, cur_vec4_, 0);
|
||||
}
|
||||
|
||||
vvp_fun_modpath_src::vvp_fun_modpath_src(vvp_time64_t del[12])
|
||||
|
|
@ -561,7 +564,8 @@ void vvp_fun_modpath_src::put_delay12(const vvp_time64_t val[12])
|
|||
delay_[idx] = val[idx];
|
||||
}
|
||||
|
||||
void vvp_fun_modpath_src::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_modpath_src::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (port.port() == 0) {
|
||||
// The modpath input...
|
||||
|
|
|
|||
12
vvp/delay.h
12
vvp/delay.h
|
|
@ -85,9 +85,11 @@ class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
vvp_fun_delay(vvp_net_t*net, vvp_bit4_t init, const vvp_delay_t&d);
|
||||
~vvp_fun_delay();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
void recv_real(vvp_net_ptr_t port, double bit);
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t);
|
||||
//void recv_long(vvp_net_ptr_t port, long bit);
|
||||
|
||||
private:
|
||||
|
|
@ -153,7 +155,8 @@ class vvp_fun_modpath : public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
|
||||
void add_modpath_src(vvp_fun_modpath_src*that, bool ifnone);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
virtual void run_run();
|
||||
|
|
@ -181,7 +184,8 @@ class vvp_fun_modpath_src : public vvp_net_fun_t {
|
|||
~vvp_fun_modpath_src();
|
||||
|
||||
public:
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
virtual bool test_vec4(const vvp_vector4_t&bit);
|
||||
|
||||
void get_delay12(vvp_time64_t out[12]) const;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ vvp_dff::~vvp_dff()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
vvp_bit4_t tmp;
|
||||
|
||||
|
|
@ -57,7 +58,7 @@ void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
tmp = clk_cur_;
|
||||
clk_cur_ = bit.value(0);
|
||||
if (clk_cur_ == BIT4_1 && tmp != BIT4_1)
|
||||
vvp_send_vec4(port.ptr()->out, d_);
|
||||
vvp_send_vec4(port.ptr()->out, d_, 0);
|
||||
break;
|
||||
|
||||
case 2: // CE
|
||||
|
|
@ -67,7 +68,7 @@ void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
|
||||
case 3: // Asynch-D
|
||||
d_ = bit;
|
||||
vvp_send_vec4(port.ptr()->out, d_);
|
||||
vvp_send_vec4(port.ptr()->out, d_, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ class vvp_dff : public vvp_net_fun_t {
|
|||
explicit vvp_dff(bool invert_clk =false, bool invert_ce =false);
|
||||
~vvp_dff();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
bool iclk_, ice_;
|
||||
|
|
|
|||
526
vvp/event.cc
526
vvp/event.cc
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
# include <iostream>
|
||||
|
||||
void waitable_hooks_s::run_waiting_threads_(unsigned context_idx)
|
||||
void waitable_hooks_s::run_waiting_threads_(vthread_t&threads)
|
||||
{
|
||||
// Run the non-blocking event controls.
|
||||
last = &event_ctls;
|
||||
|
|
@ -48,17 +48,11 @@ void waitable_hooks_s::run_waiting_threads_(unsigned context_idx)
|
|||
}
|
||||
}
|
||||
|
||||
vthread_t tmp;
|
||||
if (context_idx) {
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx));
|
||||
tmp = state->threads;
|
||||
state->threads = 0;
|
||||
} else {
|
||||
tmp = threads;
|
||||
threads = 0;
|
||||
}
|
||||
if (tmp) vthread_schedule_list(tmp);
|
||||
vthread_t tmp = threads;
|
||||
if (tmp == 0) return;
|
||||
threads = 0;
|
||||
|
||||
vthread_schedule_list(tmp);
|
||||
}
|
||||
|
||||
evctl::evctl(unsigned long ecount)
|
||||
|
|
@ -117,9 +111,9 @@ evctl_vector::evctl_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&value,
|
|||
void evctl_vector::run_run()
|
||||
{
|
||||
if (wid_ != 0) {
|
||||
vvp_send_vec4_pv(ptr_, value_, off_, value_.size(), wid_);
|
||||
vvp_send_vec4_pv(ptr_, value_, off_, value_.size(), wid_, 0);
|
||||
} else {
|
||||
vvp_send_vec4(ptr_, value_);
|
||||
vvp_send_vec4(ptr_, value_, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,114 +180,156 @@ const vvp_fun_edge::edge_t vvp_edge_negedge
|
|||
const vvp_fun_edge::edge_t vvp_edge_none = 0;
|
||||
|
||||
struct vvp_fun_edge_state_s : public waitable_state_s {
|
||||
vvp_fun_edge_state_s() : bit(BIT4_X) {}
|
||||
vvp_fun_edge_state_s()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
||||
bits[idx] = BIT4_X;
|
||||
}
|
||||
|
||||
vvp_bit4_t bit;
|
||||
vvp_bit4_t bits[4];
|
||||
};
|
||||
|
||||
vvp_fun_edge::vvp_fun_edge(edge_t e, bool debug_flag)
|
||||
: edge_(e), debug_(debug_flag)
|
||||
vvp_fun_edge::vvp_fun_edge(edge_t e)
|
||||
: edge_(e)
|
||||
{
|
||||
bits_[0] = BIT4_X;
|
||||
bits_[1] = BIT4_X;
|
||||
bits_[2] = BIT4_X;
|
||||
bits_[3] = BIT4_X;
|
||||
}
|
||||
|
||||
vvp_fun_edge::~vvp_fun_edge()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_edge::alloc_instance(vvp_context_t context)
|
||||
bool vvp_fun_edge::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_bit4_t&old_bit, vthread_t&threads)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx, new vvp_fun_edge_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_edge::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx));
|
||||
state->threads = 0;
|
||||
state->bit = BIT4_X;
|
||||
}
|
||||
|
||||
void vvp_fun_edge::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
{
|
||||
vvp_bit4_t*old_bit;
|
||||
if (context_idx) {
|
||||
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx));
|
||||
old_bit = &state->bit;
|
||||
} else {
|
||||
old_bit = &bits_[port.port()];
|
||||
}
|
||||
|
||||
/* See what kind of edge this represents. */
|
||||
edge_t mask = VVP_EDGE(*old_bit, bit.value(0));
|
||||
edge_t mask = VVP_EDGE(old_bit, bit.value(0));
|
||||
|
||||
/* Save the current input for the next time around. */
|
||||
*old_bit = bit.value(0);
|
||||
old_bit = bit.value(0);
|
||||
|
||||
if ((edge_ == vvp_edge_none) || (edge_ & mask)) {
|
||||
run_waiting_threads_(context_idx);
|
||||
run_waiting_threads_(threads);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vvp_fun_edge_sa::vvp_fun_edge_sa(edge_t e)
|
||||
: vvp_fun_edge(e), threads_(0)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
||||
bits_[idx] = BIT4_X;
|
||||
}
|
||||
|
||||
vvp_fun_edge_sa::~vvp_fun_edge_sa()
|
||||
{
|
||||
}
|
||||
|
||||
vthread_t vvp_fun_edge_sa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
vthread_t tmp = threads_;
|
||||
threads_ = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_fun_edge_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (recv_vec4_(port, bit, bits_[port.port()], threads_)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit);
|
||||
vvp_send_vec4(net->out, bit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
vvp_fun_edge_aa::vvp_fun_edge_aa(edge_t e)
|
||||
: vvp_fun_edge(e)
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
}
|
||||
|
||||
vvp_fun_edge_aa::~vvp_fun_edge_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_edge_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new vvp_fun_edge_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_edge_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
state->threads = 0;
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
||||
state->bits[idx] = BIT4_X;
|
||||
}
|
||||
|
||||
|
||||
vthread_t vvp_fun_edge_aa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx_));
|
||||
|
||||
vthread_t tmp = state->threads;
|
||||
state->threads = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_fun_edge_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (recv_vec4_(port, bit, state->bits[port.port()], state->threads)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct vvp_fun_anyedge_state_s : public waitable_state_s {
|
||||
vvp_fun_anyedge_state_s() : bitsr(0.0) {}
|
||||
vvp_fun_anyedge_state_s()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
||||
bitsr[idx] = 0.0;
|
||||
}
|
||||
|
||||
vvp_vector4_t bits;
|
||||
double bitsr;
|
||||
vvp_vector4_t bits[4];
|
||||
double bitsr[4];
|
||||
};
|
||||
|
||||
vvp_fun_anyedge::vvp_fun_anyedge(bool debug_flag)
|
||||
: debug_(debug_flag)
|
||||
vvp_fun_anyedge::vvp_fun_anyedge()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
||||
bitsr_[idx] = 0.0;
|
||||
}
|
||||
|
||||
vvp_fun_anyedge::~vvp_fun_anyedge()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx, new vvp_fun_anyedge_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx));
|
||||
state->threads = 0;
|
||||
state->bits.set_to_x();
|
||||
state->bitsr = 0.0;
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
bool vvp_fun_anyedge::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_vector4_t&old_bits, vthread_t&threads)
|
||||
{
|
||||
bool flag = false;
|
||||
|
||||
vvp_vector4_t*old_bits;
|
||||
if (context_idx) {
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx));
|
||||
old_bits = &state->bits;
|
||||
} else {
|
||||
old_bits = &bits_[port.port()];
|
||||
}
|
||||
|
||||
if (old_bits->size() != bit.size()) {
|
||||
if (old_bits.size() != bit.size()) {
|
||||
flag = true;
|
||||
|
||||
} else {
|
||||
for (unsigned idx = 0 ; idx < bit.size() ; idx += 1) {
|
||||
if (old_bits->value(idx) != bit.value(idx)) {
|
||||
if (old_bits.value(idx) != bit.value(idx)) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -301,29 +337,136 @@ void vvp_fun_anyedge::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
}
|
||||
|
||||
if (flag) {
|
||||
*old_bits = bit;
|
||||
run_waiting_threads_(context_idx);
|
||||
old_bits = bit;
|
||||
run_waiting_threads_(threads);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool vvp_fun_anyedge::recv_real_(vvp_net_ptr_t port, double bit,
|
||||
double&old_bits, vthread_t&threads)
|
||||
{
|
||||
if (old_bits != bit) {
|
||||
old_bits = bit;
|
||||
run_waiting_threads_(threads);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vvp_fun_anyedge_sa::vvp_fun_anyedge_sa()
|
||||
: threads_(0)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1)
|
||||
bitsr_[idx] = 0.0;
|
||||
}
|
||||
|
||||
vvp_fun_anyedge_sa::~vvp_fun_anyedge_sa()
|
||||
{
|
||||
}
|
||||
|
||||
vthread_t vvp_fun_anyedge_sa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
vthread_t tmp = threads_;
|
||||
threads_ = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (recv_vec4_(port, bit, bits_[port.port()], threads_)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit);
|
||||
vvp_send_vec4(net->out, bit, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge::recv_real(vvp_net_ptr_t port, double bit)
|
||||
void vvp_fun_anyedge_sa::recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
double*old_bits;
|
||||
if (context_idx) {
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx));
|
||||
old_bits = &state->bitsr;
|
||||
} else {
|
||||
old_bits = &bitsr_[port.port()];
|
||||
}
|
||||
|
||||
if (*old_bits != bit) {
|
||||
*old_bits = bit;
|
||||
run_waiting_threads_(context_idx);
|
||||
if (recv_real_(port, bit, bitsr_[port.port()], threads_)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, vvp_vector4_t());
|
||||
vvp_send_vec4(net->out, vvp_vector4_t(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
vvp_fun_anyedge_aa::vvp_fun_anyedge_aa()
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
}
|
||||
|
||||
vvp_fun_anyedge_aa::~vvp_fun_anyedge_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new vvp_fun_anyedge_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
state->threads = 0;
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1) {
|
||||
state->bits[idx].set_to_x();
|
||||
state->bitsr[idx] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
vthread_t vvp_fun_anyedge_aa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx_));
|
||||
|
||||
vthread_t tmp = state->threads;
|
||||
state->threads = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (recv_vec4_(port, bit, state->bits[port.port()], state->threads)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_anyedge_aa::recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (recv_real_(port, bit, state->bitsr[port.port()], state->threads)) {
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, vvp_vector4_t(), context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_real(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -335,23 +478,82 @@ vvp_fun_event_or::~vvp_fun_event_or()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_event_or::alloc_instance(vvp_context_t context)
|
||||
vvp_fun_event_or_sa::vvp_fun_event_or_sa()
|
||||
: threads_(0)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx, new waitable_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_event_or::reset_instance(vvp_context_t context)
|
||||
vvp_fun_event_or_sa::~vvp_fun_event_or_sa()
|
||||
{
|
||||
}
|
||||
|
||||
vthread_t vvp_fun_event_or_sa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
vthread_t tmp = threads_;
|
||||
threads_ = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_fun_event_or_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
run_waiting_threads_(threads_);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, 0);
|
||||
}
|
||||
|
||||
vvp_fun_event_or_aa::vvp_fun_event_or_aa()
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
}
|
||||
|
||||
vvp_fun_event_or_aa::~vvp_fun_event_or_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_event_or_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new waitable_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_event_or_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vvp_get_context_item(context, context_idx));
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
state->threads = 0;
|
||||
}
|
||||
|
||||
void vvp_fun_event_or::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
vthread_t vvp_fun_event_or_aa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
run_waiting_threads_(context_idx);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit);
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx_));
|
||||
|
||||
vthread_t tmp = state->threads;
|
||||
state->threads = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_fun_event_or_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
run_waiting_threads_(state->threads);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, context);
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vvp_named_event::vvp_named_event(struct __vpiHandle*h)
|
||||
|
|
@ -363,25 +565,78 @@ vvp_named_event::~vvp_named_event()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_named_event::alloc_instance(vvp_context_t context)
|
||||
vvp_named_event_sa::vvp_named_event_sa(struct __vpiHandle*h)
|
||||
: vvp_named_event(h), threads_(0)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx, new waitable_state_s);
|
||||
}
|
||||
|
||||
void vvp_named_event::reset_instance(vvp_context_t context)
|
||||
vvp_named_event_sa::~vvp_named_event_sa()
|
||||
{
|
||||
}
|
||||
|
||||
vthread_t vvp_named_event_sa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
vthread_t tmp = threads_;
|
||||
threads_ = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_named_event_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
run_waiting_threads_(threads_);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, 0);
|
||||
|
||||
vpip_run_named_event_callbacks(handle_);
|
||||
}
|
||||
|
||||
vvp_named_event_aa::vvp_named_event_aa(struct __vpiHandle*h)
|
||||
: vvp_named_event(h)
|
||||
{
|
||||
context_idx_ = vpip_add_item_to_context(this, vpip_peek_context_scope());
|
||||
}
|
||||
|
||||
vvp_named_event_aa::~vvp_named_event_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_named_event_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new waitable_state_s);
|
||||
}
|
||||
|
||||
void vvp_named_event_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vvp_get_context_item(context, context_idx));
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
state->threads = 0;
|
||||
}
|
||||
|
||||
void vvp_named_event::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
vthread_t vvp_named_event_aa::add_waiting_thread(vthread_t thread)
|
||||
{
|
||||
run_waiting_threads_(context_idx);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit);
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vthread_get_wt_context_item(context_idx_));
|
||||
|
||||
vpip_run_named_event_callbacks(handle_);
|
||||
vthread_t tmp = state->threads;
|
||||
state->threads = thread;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void vvp_named_event_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
assert(context);
|
||||
|
||||
waitable_state_s*state = static_cast<waitable_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
run_waiting_threads_(state->threads);
|
||||
vvp_net_t*net = port.ptr();
|
||||
vvp_send_vec4(net->out, bit, context);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -394,9 +649,7 @@ void vvp_named_event::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
|
||||
static void compile_event_or(char*label, unsigned argc, struct symb_s*argv);
|
||||
|
||||
void compile_event(char*label, char*type,
|
||||
unsigned argc, struct symb_s*argv,
|
||||
bool debug_flag)
|
||||
void compile_event(char*label, char*type, unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_net_fun_t*fun = 0;
|
||||
|
||||
|
|
@ -408,9 +661,12 @@ void compile_event(char*label, char*type,
|
|||
if (strcmp(type,"edge") == 0) {
|
||||
|
||||
free(type);
|
||||
vvp_fun_anyedge*event_fun = new vvp_fun_anyedge(debug_flag);
|
||||
vpip_add_item_to_current_scope(event_fun);
|
||||
fun = event_fun;
|
||||
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
fun = new vvp_fun_anyedge_aa;
|
||||
} else {
|
||||
fun = new vvp_fun_anyedge_sa;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -424,9 +680,12 @@ void compile_event(char*label, char*type,
|
|||
assert(argc <= 4);
|
||||
free(type);
|
||||
|
||||
vvp_fun_edge*event_fun = new vvp_fun_edge(edge, debug_flag);
|
||||
vpip_add_item_to_current_scope(event_fun);
|
||||
fun = event_fun;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
fun = new vvp_fun_edge_aa(edge);
|
||||
} else {
|
||||
fun = new vvp_fun_edge_sa(edge);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vvp_net_t* ptr = new vvp_net_t;
|
||||
|
|
@ -440,11 +699,12 @@ void compile_event(char*label, char*type,
|
|||
|
||||
static void compile_event_or(char*label, unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_fun_event_or*fun = new vvp_fun_event_or;
|
||||
vvp_net_t* ptr = new vvp_net_t;
|
||||
ptr->fun = fun;
|
||||
|
||||
vpip_add_item_to_current_scope(fun);
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
ptr->fun = new vvp_fun_event_or_aa;
|
||||
} else {
|
||||
ptr->fun = new vvp_fun_event_or_sa;
|
||||
}
|
||||
define_functor_symbol(label, ptr);
|
||||
free(label);
|
||||
|
||||
|
|
@ -466,10 +726,12 @@ void compile_named_event(char*label, char*name)
|
|||
vvp_net_t*ptr = new vvp_net_t;
|
||||
|
||||
vpiHandle obj = vpip_make_named_event(name, ptr);
|
||||
vvp_named_event*fun = new vvp_named_event(obj);
|
||||
ptr->fun = fun;
|
||||
|
||||
vpip_add_item_to_current_scope(fun);
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
ptr->fun = new vvp_named_event_aa(obj);
|
||||
} else {
|
||||
ptr->fun = new vvp_named_event_sa(obj);
|
||||
}
|
||||
define_functor_symbol(label, ptr);
|
||||
compile_vpi_symbol(label, obj);
|
||||
vpip_attach_to_current_scope(obj);
|
||||
|
|
|
|||
199
vvp/event.h
199
vvp/event.h
|
|
@ -102,13 +102,15 @@ extern void schedule_evctl(vvp_array_t memory, unsigned index,
|
|||
struct waitable_hooks_s {
|
||||
|
||||
public:
|
||||
waitable_hooks_s() : threads(0), event_ctls(0) { last = &event_ctls; }
|
||||
vthread_t threads;
|
||||
waitable_hooks_s() : event_ctls(0) { last = &event_ctls; }
|
||||
|
||||
virtual vthread_t add_waiting_thread(vthread_t thread) = 0;
|
||||
|
||||
evctl*event_ctls;
|
||||
evctl**last;
|
||||
|
||||
protected:
|
||||
void run_waiting_threads_(unsigned context_idx);
|
||||
void run_waiting_threads_(vthread_t&threads);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -118,6 +120,7 @@ struct waitable_hooks_s {
|
|||
*/
|
||||
struct waitable_state_s {
|
||||
waitable_state_s() : threads(0) { }
|
||||
|
||||
vthread_t threads;
|
||||
};
|
||||
|
||||
|
|
@ -130,24 +133,62 @@ class vvp_fun_edge : public vvp_net_fun_t, public waitable_hooks_s {
|
|||
|
||||
public:
|
||||
typedef unsigned short edge_t;
|
||||
explicit vvp_fun_edge(edge_t e, bool debug_flag);
|
||||
explicit vvp_fun_edge(edge_t e);
|
||||
virtual ~vvp_fun_edge();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
protected:
|
||||
bool recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_bit4_t&old_bit, vthread_t&threads);
|
||||
|
||||
private:
|
||||
vvp_bit4_t bits_[4];
|
||||
edge_t edge_;
|
||||
bool debug_;
|
||||
};
|
||||
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_posedge;
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_negedge;
|
||||
extern const vvp_fun_edge::edge_t vvp_edge_none;
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_edge.
|
||||
*/
|
||||
class vvp_fun_edge_sa : public vvp_fun_edge {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_edge_sa(edge_t e);
|
||||
virtual ~vvp_fun_edge_sa();
|
||||
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
vthread_t threads_;
|
||||
vvp_bit4_t bits_[4];
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_edge.
|
||||
*/
|
||||
class vvp_fun_edge_aa : public vvp_fun_edge, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_edge_aa(edge_t e);
|
||||
virtual ~vvp_fun_edge_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
struct __vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The vvp_fun_anyedge functor checks to see if any value in an input
|
||||
* vector changes. Unlike the vvp_fun_edge, which watches for the LSB
|
||||
|
|
@ -161,20 +202,63 @@ extern const vvp_fun_edge::edge_t vvp_edge_none;
|
|||
class vvp_fun_anyedge : public vvp_net_fun_t, public waitable_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_anyedge(bool debug_flag);
|
||||
explicit vvp_fun_anyedge();
|
||||
virtual ~vvp_fun_anyedge();
|
||||
|
||||
protected:
|
||||
bool recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_vector4_t&old_bits, vthread_t&threads);
|
||||
bool recv_real_(vvp_net_ptr_t port, double bit,
|
||||
double&old_bits, vthread_t&threads);
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_anyedge.
|
||||
*/
|
||||
class vvp_fun_anyedge_sa : public vvp_fun_anyedge {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_anyedge_sa();
|
||||
virtual ~vvp_fun_anyedge_sa();
|
||||
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
vthread_t threads_;
|
||||
vvp_vector4_t bits_[4];
|
||||
// In case I'm a real-valued event.
|
||||
double bitsr_[4];
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_anyedge.
|
||||
*/
|
||||
class vvp_fun_anyedge_aa : public vvp_fun_anyedge, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_anyedge_aa();
|
||||
virtual ~vvp_fun_anyedge_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_real(vvp_net_ptr_t port, double bit);
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
void recv_real(vvp_net_ptr_t port, double bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
bool debug_;
|
||||
vvp_vector4_t bits_[4];
|
||||
// In case I'm a real-valued event.
|
||||
double bitsr_[4];
|
||||
struct __vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -186,13 +270,46 @@ class vvp_fun_event_or : public vvp_net_fun_t, public waitable_hooks_s {
|
|||
public:
|
||||
explicit vvp_fun_event_or();
|
||||
~vvp_fun_event_or();
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_event_or.
|
||||
*/
|
||||
class vvp_fun_event_or_sa : public vvp_fun_event_or {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_event_or_sa();
|
||||
~vvp_fun_event_or_sa();
|
||||
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
vthread_t threads_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_event_or.
|
||||
*/
|
||||
class vvp_fun_event_or_aa : public vvp_fun_event_or, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_event_or_aa();
|
||||
~vvp_fun_event_or_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
struct __vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -206,13 +323,47 @@ class vvp_named_event : public vvp_net_fun_t, public waitable_hooks_s {
|
|||
explicit vvp_named_event(struct __vpiHandle*eh);
|
||||
~vvp_named_event();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
|
||||
private:
|
||||
protected:
|
||||
struct __vpiHandle*handle_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_named_event.
|
||||
*/
|
||||
class vvp_named_event_sa : public vvp_named_event {
|
||||
|
||||
public:
|
||||
explicit vvp_named_event_sa(struct __vpiHandle*eh);
|
||||
~vvp_named_event_sa();
|
||||
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
vthread_t threads_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_named_event.
|
||||
*/
|
||||
class vvp_named_event_aa : public vvp_named_event, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_named_event_aa(struct __vpiHandle*eh);
|
||||
~vvp_named_event_aa();
|
||||
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
vthread_t add_waiting_thread(vthread_t thread);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
#endif // __event_H
|
||||
|
|
|
|||
|
|
@ -35,10 +35,11 @@ vvp_fun_extend_signed::~vvp_fun_extend_signed()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_extend_signed::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_extend_signed::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (bit.size() >= width_) {
|
||||
vvp_send_vec4(port.ptr()->out, bit);
|
||||
vvp_send_vec4(port.ptr()->out, bit, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -51,5 +52,5 @@ void vvp_fun_extend_signed::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bi
|
|||
for (unsigned idx = bit.size() ; idx < res.size() ; idx += 1)
|
||||
res.set_bit(idx, pad);
|
||||
|
||||
vvp_send_vec4(port.ptr()->out, res);
|
||||
vvp_send_vec4(port.ptr()->out, res, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,8 +183,6 @@
|
|||
"%vpi_func/r" { return K_vpi_func_r; }
|
||||
"%disable" { return K_disable; }
|
||||
"%fork" { return K_fork; }
|
||||
"%alloc" { return K_alloc; }
|
||||
"%free" { return K_free; }
|
||||
|
||||
/* Handle the specialized variable access functions. */
|
||||
|
||||
|
|
|
|||
55
vvp/logic.cc
55
vvp/logic.cc
|
|
@ -42,7 +42,8 @@ vvp_fun_boolean_::~vvp_fun_boolean_()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_boolean_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_boolean_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
unsigned port = ptr.port();
|
||||
if (input_[port] .eeq( bit ))
|
||||
|
|
@ -56,7 +57,8 @@ void vvp_fun_boolean_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
}
|
||||
|
||||
void vvp_fun_boolean_::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
unsigned port = ptr.port();
|
||||
|
||||
|
|
@ -106,7 +108,7 @@ void vvp_fun_and::run_run()
|
|||
result.set_bit(idx, bitbit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, result);
|
||||
vvp_send_vec4(ptr->out, result, 0);
|
||||
}
|
||||
|
||||
vvp_fun_buf::vvp_fun_buf()
|
||||
|
|
@ -123,7 +125,8 @@ vvp_fun_buf::~vvp_fun_buf()
|
|||
* The buf functor is very simple--change the z bits to x bits in the
|
||||
* vector it passes, and propagate the result.
|
||||
*/
|
||||
void vvp_fun_buf::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_buf::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (ptr.port() != 0)
|
||||
return;
|
||||
|
|
@ -146,7 +149,7 @@ void vvp_fun_buf::run_run()
|
|||
|
||||
vvp_vector4_t tmp (input_);
|
||||
tmp.change_z2x();
|
||||
vvp_send_vec4(ptr->out, tmp);
|
||||
vvp_send_vec4(ptr->out, tmp, 0);
|
||||
}
|
||||
|
||||
vvp_fun_bufz::vvp_fun_bufz()
|
||||
|
|
@ -162,20 +165,22 @@ vvp_fun_bufz::~vvp_fun_bufz()
|
|||
* The bufz is similar to the buf device, except that it does not
|
||||
* bother translating z bits to x.
|
||||
*/
|
||||
void vvp_fun_bufz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_bufz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (ptr.port() != 0)
|
||||
return;
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, bit);
|
||||
vvp_send_vec4(ptr.ptr()->out, bit, 0);
|
||||
}
|
||||
|
||||
void vvp_fun_bufz::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_fun_bufz::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (ptr.port() != 0)
|
||||
return;
|
||||
|
||||
vvp_send_real(ptr.ptr()->out, bit);
|
||||
vvp_send_real(ptr.ptr()->out, bit, 0);
|
||||
}
|
||||
|
||||
vvp_fun_muxr::vvp_fun_muxr()
|
||||
|
|
@ -190,7 +195,8 @@ vvp_fun_muxr::~vvp_fun_muxr()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_muxr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_muxr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
/* The real valued mux can only take in the select as a
|
||||
vector4_t. The muxed data is real. */
|
||||
|
|
@ -219,7 +225,8 @@ void vvp_fun_muxr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_fun_muxr::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
void vvp_fun_muxr::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
switch (ptr.port()) {
|
||||
case 0:
|
||||
|
|
@ -252,16 +259,16 @@ void vvp_fun_muxr::run_run()
|
|||
|
||||
switch (select_) {
|
||||
case SEL_PORT0:
|
||||
vvp_send_real(ptr->out, a_);
|
||||
vvp_send_real(ptr->out, a_, 0);
|
||||
break;
|
||||
case SEL_PORT1:
|
||||
vvp_send_real(ptr->out, b_);
|
||||
vvp_send_real(ptr->out, b_, 0);
|
||||
break;
|
||||
default:
|
||||
if (a_ == b_) {
|
||||
vvp_send_real(ptr->out, a_);
|
||||
vvp_send_real(ptr->out, a_, 0);
|
||||
} else {
|
||||
vvp_send_real(ptr->out, 0.0); // Should this be NaN?
|
||||
vvp_send_real(ptr->out, 0.0, 0); // Should this be NaN?
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -284,7 +291,8 @@ vvp_fun_muxz::~vvp_fun_muxz()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_muxz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_muxz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
switch (ptr.port()) {
|
||||
case 0:
|
||||
|
|
@ -331,10 +339,10 @@ void vvp_fun_muxz::run_run()
|
|||
|
||||
switch (select_) {
|
||||
case SEL_PORT0:
|
||||
vvp_send_vec4(ptr->out, a_);
|
||||
vvp_send_vec4(ptr->out, a_, 0);
|
||||
break;
|
||||
case SEL_PORT1:
|
||||
vvp_send_vec4(ptr->out, b_);
|
||||
vvp_send_vec4(ptr->out, b_, 0);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
|
|
@ -357,7 +365,7 @@ void vvp_fun_muxz::run_run()
|
|||
for (unsigned idx = min_size ; idx < max_size ; idx += 1)
|
||||
res.set_bit(idx, BIT4_X);
|
||||
|
||||
vvp_send_vec4(ptr->out, res);
|
||||
vvp_send_vec4(ptr->out, res, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -377,7 +385,8 @@ vvp_fun_not::~vvp_fun_not()
|
|||
* The buf functor is very simple--change the z bits to x bits in the
|
||||
* vector it passes, and propagate the result.
|
||||
*/
|
||||
void vvp_fun_not::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_not::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (ptr.port() != 0)
|
||||
return;
|
||||
|
|
@ -404,7 +413,7 @@ void vvp_fun_not::run_run()
|
|||
result.set_bit(idx, bitbit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, result);
|
||||
vvp_send_vec4(ptr->out, result, 0);
|
||||
}
|
||||
|
||||
vvp_fun_or::vvp_fun_or(unsigned wid, bool invert)
|
||||
|
|
@ -440,7 +449,7 @@ void vvp_fun_or::run_run()
|
|||
result.set_bit(idx, bitbit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, result);
|
||||
vvp_send_vec4(ptr->out, result, 0);
|
||||
}
|
||||
|
||||
vvp_fun_xor::vvp_fun_xor(unsigned wid, bool invert)
|
||||
|
|
@ -476,7 +485,7 @@ void vvp_fun_xor::run_run()
|
|||
result.set_bit(idx, bitbit);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, result);
|
||||
vvp_send_vec4(ptr->out, result, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
27
vvp/logic.h
27
vvp/logic.h
|
|
@ -32,9 +32,11 @@ class vvp_fun_boolean_ : public vvp_net_fun_t, protected vvp_gen_event_s {
|
|||
explicit vvp_fun_boolean_(unsigned wid);
|
||||
~vvp_fun_boolean_();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t);
|
||||
|
||||
protected:
|
||||
vvp_vector4_t input_[4];
|
||||
|
|
@ -64,7 +66,8 @@ class vvp_fun_buf: public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
explicit vvp_fun_buf();
|
||||
virtual ~vvp_fun_buf();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
void run_run();
|
||||
|
|
@ -84,8 +87,10 @@ class vvp_fun_bufz: public vvp_net_fun_t {
|
|||
explicit vvp_fun_bufz();
|
||||
virtual ~vvp_fun_bufz();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
|
||||
void recv_real(vvp_net_ptr_t p, double bit);
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_real(vvp_net_ptr_t p, double bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
@ -109,7 +114,8 @@ class vvp_fun_muxz : public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
explicit vvp_fun_muxz(unsigned width);
|
||||
virtual ~vvp_fun_muxz();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
void run_run();
|
||||
|
|
@ -128,8 +134,10 @@ class vvp_fun_muxr : public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
explicit vvp_fun_muxr();
|
||||
virtual ~vvp_fun_muxr();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
|
||||
void recv_real(vvp_net_ptr_t p, double bit);
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_real(vvp_net_ptr_t p, double bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
void run_run();
|
||||
|
|
@ -147,7 +155,8 @@ class vvp_fun_not: public vvp_net_fun_t, private vvp_gen_event_s {
|
|||
explicit vvp_fun_not();
|
||||
virtual ~vvp_fun_not();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
void run_run();
|
||||
|
|
|
|||
15
vvp/npmos.cc
15
vvp/npmos.cc
|
|
@ -28,7 +28,8 @@ vvp_fun_pmos_::vvp_fun_pmos_(bool enable_invert)
|
|||
}
|
||||
|
||||
|
||||
void vvp_fun_pmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
void vvp_fun_pmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
/* Data input is processed through eh recv_vec8 method,
|
||||
because the strength must be preserved. */
|
||||
|
|
@ -89,7 +90,7 @@ vvp_fun_pmos::vvp_fun_pmos(bool enable_invert)
|
|||
void vvp_fun_pmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
{
|
||||
if (ptr.port() == 1) {
|
||||
recv_vec4(ptr, reduce4(bit));
|
||||
recv_vec4(ptr, reduce4(bit), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +109,7 @@ vvp_fun_rpmos::vvp_fun_rpmos(bool enable_invert)
|
|||
void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
{
|
||||
if (ptr.port() == 1) {
|
||||
recv_vec4(ptr, reduce4(bit));
|
||||
recv_vec4(ptr, reduce4(bit), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +129,8 @@ vvp_fun_cmos_::vvp_fun_cmos_()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_cmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t &bit)
|
||||
void vvp_fun_cmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t &bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
/* Data input is processed through the recv_vec8 method,
|
||||
because the strength must be preserved. */
|
||||
|
|
@ -190,7 +192,7 @@ vvp_fun_cmos::vvp_fun_cmos()
|
|||
void vvp_fun_cmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
{
|
||||
if (ptr.port() == 1 || ptr.port() == 2) {
|
||||
recv_vec4(ptr, reduce4(bit));
|
||||
recv_vec4(ptr, reduce4(bit), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -209,7 +211,7 @@ vvp_fun_rcmos::vvp_fun_rcmos()
|
|||
void vvp_fun_rcmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
||||
{
|
||||
if (ptr.port() == 1) {
|
||||
recv_vec4(ptr, reduce4(bit));
|
||||
recv_vec4(ptr, reduce4(bit), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -219,4 +221,3 @@ void vvp_fun_rcmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
|
|||
bit_ = resistive_reduction(bit);
|
||||
generate_output_(ptr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ class vvp_fun_pmos_ : public vvp_net_fun_t {
|
|||
public:
|
||||
explicit vvp_fun_pmos_(bool enable_invert);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
protected:
|
||||
void generate_output_(vvp_net_ptr_t port);
|
||||
|
|
@ -107,7 +108,8 @@ class vvp_fun_cmos_ : public vvp_net_fun_t {
|
|||
public:
|
||||
explicit vvp_fun_cmos_();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit,
|
||||
vvp_context_t);
|
||||
|
||||
protected:
|
||||
void generate_output_(vvp_net_ptr_t port);
|
||||
|
|
|
|||
19
vvp/parse.y
19
vvp/parse.y
|
|
@ -85,7 +85,7 @@ static struct __vpiModPath*modpath_dst = 0;
|
|||
%token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP K_UFUNC
|
||||
%token K_UDP K_UDP_C K_UDP_S
|
||||
%token K_VAR K_VAR_S K_VAR_I K_VAR_R K_vpi_call K_vpi_func K_vpi_func_r
|
||||
%token K_disable K_fork K_alloc K_free
|
||||
%token K_disable K_fork
|
||||
%token K_vpi_module K_vpi_time_precision K_file_names
|
||||
|
||||
%token <text> T_INSTR
|
||||
|
|
@ -483,16 +483,16 @@ statement
|
|||
named event instead. */
|
||||
|
||||
| T_LABEL K_EVENT T_SYMBOL ',' symbols ';'
|
||||
{ compile_event($1, $3, $5.cnt, $5.vect, false); }
|
||||
{ compile_event($1, $3, $5.cnt, $5.vect); }
|
||||
|
||||
| T_LABEL K_EVENT K_DEBUG T_SYMBOL ',' symbols ';'
|
||||
{ compile_event($1, $4, $6.cnt, $6.vect, true); }
|
||||
{ compile_event($1, $4, $6.cnt, $6.vect); }
|
||||
|
||||
| T_LABEL K_EVENT T_STRING ';'
|
||||
{ compile_named_event($1, $3); }
|
||||
|
||||
| T_LABEL K_EVENT_OR symbols ';'
|
||||
{ compile_event($1, 0, $3.cnt, $3.vect, false); }
|
||||
{ compile_event($1, 0, $3.cnt, $3.vect); }
|
||||
|
||||
|
||||
/* Instructions may have a label, and have zero or more
|
||||
|
|
@ -533,12 +533,6 @@ statement
|
|||
| label_opt K_fork symbol ',' symbol ';'
|
||||
{ compile_fork($1, $3, $5); }
|
||||
|
||||
| label_opt K_alloc symbol ';'
|
||||
{ compile_alloc($1, $3); }
|
||||
|
||||
| label_opt K_free symbol ';'
|
||||
{ compile_free($1, $3); }
|
||||
|
||||
/* Scope statements come in two forms. There are the scope
|
||||
declaration and the scope recall. The declarations create the
|
||||
scope, with their association with a parent. The label of the
|
||||
|
|
@ -668,6 +662,11 @@ statement
|
|||
symbols_net ';'
|
||||
{ compile_netw($1, $3, $4, $6, $7, true, true, $9.cnt, $9.vect); }
|
||||
|
||||
| T_LABEL K_NET_R T_SYMBOL T_NUMBER ','
|
||||
signed_t_number signed_t_number ','
|
||||
symbols_net ';'
|
||||
{ compile_netw_real($1, $3, $4, $6, $7, $9.cnt, $9.vect); }
|
||||
|
||||
/* Array word versions of alias directives. */
|
||||
|
||||
| T_LABEL K_ALIAS T_SYMBOL T_NUMBER ','
|
||||
|
|
|
|||
264
vvp/part.cc
264
vvp/part.cc
|
|
@ -27,17 +27,34 @@
|
|||
# include <iostream>
|
||||
# include <assert.h>
|
||||
|
||||
struct vvp_fun_part_state_s {
|
||||
vvp_fun_part_state_s() : bitsr(0.0) {}
|
||||
|
||||
vvp_vector4_t bits;
|
||||
double bitsr;
|
||||
};
|
||||
|
||||
vvp_fun_part::vvp_fun_part(unsigned base, unsigned wid)
|
||||
: base_(base), wid_(wid)
|
||||
{
|
||||
net_ = 0;
|
||||
}
|
||||
|
||||
vvp_fun_part::~vvp_fun_part()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
vvp_fun_part_sa::vvp_fun_part_sa(unsigned base, unsigned wid)
|
||||
: vvp_fun_part(base, wid)
|
||||
{
|
||||
net_ = 0;
|
||||
}
|
||||
|
||||
vvp_fun_part_sa::~vvp_fun_part_sa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(port.port() == 0);
|
||||
|
||||
|
|
@ -55,11 +72,12 @@ void vvp_fun_part::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
/*
|
||||
* Handle the case that the part select node is actually fed by a part
|
||||
* select assignment. It's not exactly clear what might make this
|
||||
* happen, but is does seem to happen and this should have sell
|
||||
* happen, but is does seem to happen and this should have well
|
||||
* defined behavior.
|
||||
*/
|
||||
void vvp_fun_part::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
void vvp_fun_part_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(bit.size() == wid);
|
||||
|
||||
|
|
@ -69,10 +87,10 @@ void vvp_fun_part::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
|
||||
assert(tmp.size() == vwid);
|
||||
tmp.set_vec(base, bit);
|
||||
recv_vec4(port, tmp);
|
||||
recv_vec4(port, tmp, 0);
|
||||
}
|
||||
|
||||
void vvp_fun_part::run_run()
|
||||
void vvp_fun_part_sa::run_run()
|
||||
{
|
||||
vvp_net_t*ptr = net_;
|
||||
net_ = 0;
|
||||
|
|
@ -82,7 +100,90 @@ void vvp_fun_part::run_run()
|
|||
if (idx + base_ < val_.size())
|
||||
res.set_bit(idx, val_.value(base_+idx));
|
||||
}
|
||||
vvp_send_vec4(ptr->out, res);
|
||||
vvp_send_vec4(ptr->out, res, 0);
|
||||
}
|
||||
|
||||
vvp_fun_part_aa::vvp_fun_part_aa(unsigned base, unsigned wid)
|
||||
: vvp_fun_part(base, wid)
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
}
|
||||
|
||||
vvp_fun_part_aa::~vvp_fun_part_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new vvp_vector4_t);
|
||||
}
|
||||
|
||||
void vvp_fun_part_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_vector4_t*val = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
val->set_to_x();
|
||||
}
|
||||
|
||||
void vvp_fun_part_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
assert(port.port() == 0);
|
||||
|
||||
vvp_vector4_t*val = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
vvp_vector4_t tmp (wid_, BIT4_X);
|
||||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
||||
if (idx + base_ < bit.size())
|
||||
tmp.set_bit(idx, bit.value(base_+idx));
|
||||
}
|
||||
if (!val->eeq( tmp )) {
|
||||
*val = tmp;
|
||||
vvp_send_vec4(port.ptr()->out, tmp, context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the case that the part select node is actually fed by a part
|
||||
* select assignment. It's not exactly clear what might make this
|
||||
* happen, but is does seem to happen and this should have well
|
||||
* defined behavior.
|
||||
*/
|
||||
void vvp_fun_part_aa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
assert(bit.size() == wid);
|
||||
|
||||
vvp_vector4_t*val = static_cast<vvp_vector4_t*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
vvp_vector4_t tmp = *val;
|
||||
if (tmp.size() == 0)
|
||||
tmp = vvp_vector4_t(vwid);
|
||||
|
||||
assert(tmp.size() == vwid);
|
||||
tmp.set_vec(base, bit);
|
||||
recv_vec4(port, tmp, context);
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4_pv(port, bit, base, wid, vwid, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vvp_fun_part_pv::vvp_fun_part_pv(unsigned b, unsigned w, unsigned v)
|
||||
|
|
@ -94,7 +195,8 @@ vvp_fun_part_pv::~vvp_fun_part_pv()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part_pv::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_fun_part_pv::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
assert(port.port() == 0);
|
||||
|
||||
|
|
@ -106,7 +208,7 @@ void vvp_fun_part_pv::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
}
|
||||
assert(bit.size() == wid_);
|
||||
|
||||
vvp_send_vec4_pv(port.ptr()->out, bit, base_, wid_, vwid_);
|
||||
vvp_send_vec4_pv(port.ptr()->out, bit, base_, wid_, vwid_, context);
|
||||
}
|
||||
|
||||
void vvp_fun_part_pv::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
||||
|
|
@ -125,7 +227,7 @@ void vvp_fun_part_pv::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
|||
}
|
||||
|
||||
vvp_fun_part_var::vvp_fun_part_var(unsigned w)
|
||||
: base_(0), wid_(w)
|
||||
: wid_(w)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -133,18 +235,20 @@ vvp_fun_part_var::~vvp_fun_part_var()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part_var::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
bool vvp_fun_part_var::recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned&base, vvp_vector4_t&source,
|
||||
vvp_vector4_t&ref)
|
||||
{
|
||||
unsigned long tmp;
|
||||
switch (port.port()) {
|
||||
case 0:
|
||||
source_ = bit;
|
||||
source = bit;
|
||||
break;
|
||||
case 1:
|
||||
tmp = ULONG_MAX;
|
||||
vector4_to_value(bit, tmp);
|
||||
if (tmp == base_) return;
|
||||
base_ = tmp;
|
||||
if (tmp == base) return false;
|
||||
base = tmp;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unsupported port type %d.\n", port.port());
|
||||
|
|
@ -155,21 +259,40 @@ void vvp_fun_part_var::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
vvp_vector4_t res (wid_);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
||||
unsigned adr = base_+idx;
|
||||
if (adr >= source_.size())
|
||||
unsigned adr = base+idx;
|
||||
if (adr >= source.size())
|
||||
break;
|
||||
|
||||
res.set_bit(idx, source_.value(adr));
|
||||
res.set_bit(idx, source.value(adr));
|
||||
}
|
||||
|
||||
if (! ref_.eeq(res)) {
|
||||
ref_ = res;
|
||||
vvp_send_vec4(port.ptr()->out, res);
|
||||
if (! ref.eeq(res)) {
|
||||
ref = res;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vvp_fun_part_var_sa::vvp_fun_part_var_sa(unsigned w)
|
||||
: vvp_fun_part_var(w), base_(0)
|
||||
{
|
||||
}
|
||||
|
||||
vvp_fun_part_var_sa::~vvp_fun_part_var_sa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part_var_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
if (recv_vec4_(port, bit, base_, source_, ref_)) {
|
||||
vvp_send_vec4(port.ptr()->out, ref_, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_part_var::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
void vvp_fun_part_var_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(bit.size() == wid);
|
||||
|
||||
|
|
@ -179,8 +302,86 @@ void vvp_fun_part_var::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
|
||||
assert(tmp.size() == vwid);
|
||||
tmp.set_vec(base, bit);
|
||||
recv_vec4(port, tmp);
|
||||
recv_vec4(port, tmp, 0);
|
||||
}
|
||||
|
||||
struct vvp_fun_part_var_state_s {
|
||||
vvp_fun_part_var_state_s() : base(0) { }
|
||||
|
||||
unsigned base;
|
||||
vvp_vector4_t source;
|
||||
vvp_vector4_t ref;
|
||||
};
|
||||
|
||||
vvp_fun_part_var_aa::vvp_fun_part_var_aa(unsigned w)
|
||||
: vvp_fun_part_var(w)
|
||||
{
|
||||
context_scope_ = vpip_peek_context_scope();
|
||||
context_idx_ = vpip_add_item_to_context(this, context_scope_);
|
||||
}
|
||||
|
||||
vvp_fun_part_var_aa::~vvp_fun_part_var_aa()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_fun_part_var_aa::alloc_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_set_context_item(context, context_idx_, new vvp_fun_part_var_state_s);
|
||||
}
|
||||
|
||||
void vvp_fun_part_var_aa::reset_instance(vvp_context_t context)
|
||||
{
|
||||
vvp_fun_part_var_state_s*state = static_cast<vvp_fun_part_var_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
state->base = 0;
|
||||
state->source.set_to_x();
|
||||
state->ref.set_to_x();
|
||||
}
|
||||
|
||||
void vvp_fun_part_var_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
vvp_fun_part_var_state_s*state = static_cast<vvp_fun_part_var_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
if (recv_vec4_(port, bit, state->base, state->source, state->ref)) {
|
||||
vvp_send_vec4(port.ptr()->out, state->ref, context);
|
||||
}
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_fun_part_var_aa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (context) {
|
||||
vvp_fun_part_var_state_s*state = static_cast<vvp_fun_part_var_state_s*>
|
||||
(vvp_get_context_item(context, context_idx_));
|
||||
|
||||
assert(bit.size() == wid);
|
||||
|
||||
vvp_vector4_t tmp = state->source;
|
||||
if (tmp.size() == 0)
|
||||
tmp = vvp_vector4_t(vwid);
|
||||
|
||||
assert(tmp.size() == vwid);
|
||||
tmp.set_vec(base, bit);
|
||||
recv_vec4(port, tmp, context);
|
||||
} else {
|
||||
context = context_scope_->live_contexts;
|
||||
while (context) {
|
||||
recv_vec4(port, bit, context);
|
||||
context = vvp_get_next_context(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -201,7 +402,12 @@ void link_node_1(char*label, char*source, vvp_net_fun_t*fun)
|
|||
void compile_part_select(char*label, char*source,
|
||||
unsigned base, unsigned wid)
|
||||
{
|
||||
vvp_fun_part*fun = new vvp_fun_part(base, wid);
|
||||
vvp_fun_part*fun = 0;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
fun = new vvp_fun_part_aa(base, wid);
|
||||
} else {
|
||||
fun = new vvp_fun_part_sa(base, wid);
|
||||
}
|
||||
link_node_1(label, source, fun);
|
||||
}
|
||||
|
||||
|
|
@ -216,7 +422,12 @@ void compile_part_select_pv(char*label, char*source,
|
|||
void compile_part_select_var(char*label, char*source, char*var,
|
||||
unsigned wid)
|
||||
{
|
||||
vvp_fun_part_var*fun = new vvp_fun_part_var(wid);
|
||||
vvp_fun_part_var*fun = 0;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
fun = new vvp_fun_part_var_aa(wid);
|
||||
} else {
|
||||
fun = new vvp_fun_part_var_sa(wid);
|
||||
}
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
net->fun = fun;
|
||||
|
||||
|
|
@ -226,4 +437,3 @@ void compile_part_select_var(char*label, char*source, char*var,
|
|||
input_connect(net, 0, source);
|
||||
input_connect(net, 1, var);
|
||||
}
|
||||
|
||||
|
|
|
|||
106
vvp/part.h
106
vvp/part.h
|
|
@ -27,32 +27,73 @@
|
|||
* select starts. Input 2, which is typically constant, is the width
|
||||
* of the result.
|
||||
*/
|
||||
class vvp_fun_part : public vvp_net_fun_t, private vvp_gen_event_s {
|
||||
class vvp_fun_part : public vvp_net_fun_t {
|
||||
|
||||
public:
|
||||
vvp_fun_part(unsigned base, unsigned wid);
|
||||
~vvp_fun_part();
|
||||
|
||||
protected:
|
||||
unsigned base_;
|
||||
unsigned wid_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_part.
|
||||
*/
|
||||
class vvp_fun_part_sa : public vvp_fun_part, public vvp_gen_event_s {
|
||||
|
||||
public:
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
vvp_fun_part_sa(unsigned base, unsigned wid);
|
||||
~vvp_fun_part_sa();
|
||||
|
||||
public:
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned, unsigned, unsigned);
|
||||
unsigned, unsigned, unsigned,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
void run_run();
|
||||
|
||||
private:
|
||||
unsigned base_;
|
||||
unsigned wid_;
|
||||
vvp_vector4_t val_;
|
||||
vvp_net_t*net_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_part.
|
||||
*/
|
||||
class vvp_fun_part_aa : public vvp_fun_part, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
vvp_fun_part_aa(unsigned base, unsigned wid);
|
||||
~vvp_fun_part_aa();
|
||||
|
||||
public:
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned, unsigned, unsigned,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
struct __vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
/* vvp_fun_part_pv
|
||||
* This node takes a vector input and turns it into the part select of
|
||||
* a wider output network. It used the recv_vec4_pv methods of the
|
||||
* destination nodes to propagate the part select.
|
||||
* destination nodes to propagate the part select. It can be used in
|
||||
* both statically and automatically allocated scopes, as it has no
|
||||
* dynamic state.
|
||||
*/
|
||||
class vvp_fun_part_pv : public vvp_net_fun_t {
|
||||
|
||||
|
|
@ -61,7 +102,9 @@ class vvp_fun_part_pv : public vvp_net_fun_t {
|
|||
~vvp_fun_part_pv();
|
||||
|
||||
public:
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
|
||||
private:
|
||||
|
|
@ -81,18 +124,61 @@ class vvp_fun_part_var : public vvp_net_fun_t {
|
|||
explicit vvp_fun_part_var(unsigned wid);
|
||||
~vvp_fun_part_var();
|
||||
|
||||
protected:
|
||||
bool recv_vec4_(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned&base, vvp_vector4_t&source,
|
||||
vvp_vector4_t&ref);
|
||||
|
||||
unsigned wid_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Statically allocated vvp_fun_part_var.
|
||||
*/
|
||||
class vvp_fun_part_var_sa : public vvp_fun_part_var {
|
||||
|
||||
public:
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
explicit vvp_fun_part_var_sa(unsigned wid);
|
||||
~vvp_fun_part_var_sa();
|
||||
|
||||
public:
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned, unsigned, unsigned);
|
||||
unsigned, unsigned, unsigned,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
unsigned base_;
|
||||
unsigned wid_;
|
||||
vvp_vector4_t source_;
|
||||
// Save the last output, for detecting change.
|
||||
vvp_vector4_t ref_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Automatically allocated vvp_fun_part_var.
|
||||
*/
|
||||
class vvp_fun_part_var_aa : public vvp_fun_part_var, public automatic_hooks_s {
|
||||
|
||||
public:
|
||||
explicit vvp_fun_part_var_aa(unsigned wid);
|
||||
~vvp_fun_part_var_aa();
|
||||
|
||||
public:
|
||||
void alloc_instance(vvp_context_t context);
|
||||
void reset_instance(vvp_context_t context);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned, unsigned, unsigned,
|
||||
vvp_context_t context);
|
||||
|
||||
private:
|
||||
struct __vpiScope*context_scope_;
|
||||
unsigned context_idx_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@
|
|||
* All the reduction operations take a single vector input and produce
|
||||
* a scalar result. The vvp_reduce_base class codifies these general
|
||||
* characteristics, leaving only the calculation of the result for the
|
||||
* base class.
|
||||
* base class. This can be used in both statically and automatically
|
||||
* allocated scopes, as bits_ is only used for temporary storage.
|
||||
*/
|
||||
class vvp_reduce_base : public vvp_net_fun_t {
|
||||
|
||||
|
|
@ -42,9 +43,11 @@ class vvp_reduce_base : public vvp_net_fun_t {
|
|||
vvp_reduce_base();
|
||||
virtual ~vvp_reduce_base();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit,
|
||||
vvp_context_t context);
|
||||
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context);
|
||||
|
||||
virtual vvp_bit4_t calculate_result() const =0;
|
||||
|
||||
|
|
@ -60,16 +63,18 @@ vvp_reduce_base::~vvp_reduce_base()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_reduce_base::recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit)
|
||||
void vvp_reduce_base::recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit,
|
||||
vvp_context_t context)
|
||||
{
|
||||
bits_ = bit;
|
||||
vvp_bit4_t res = calculate_result();
|
||||
vvp_vector4_t rv (1, res);
|
||||
vvp_send_vec4(prt.ptr()->out, rv);
|
||||
vvp_send_vec4(prt.ptr()->out, rv, context);
|
||||
}
|
||||
|
||||
void vvp_reduce_base::recv_vec4_pv(vvp_net_ptr_t prt, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t context)
|
||||
{
|
||||
if (bits_.size() == 0) {
|
||||
bits_ = vvp_vector4_t(vwid);
|
||||
|
|
@ -80,7 +85,7 @@ void vvp_reduce_base::recv_vec4_pv(vvp_net_ptr_t prt, const vvp_vector4_t&bit,
|
|||
bits_.set_vec(base, bit);
|
||||
vvp_bit4_t res = calculate_result();
|
||||
vvp_vector4_t rv (1, res);
|
||||
vvp_send_vec4(prt.ptr()->out, rv);
|
||||
vvp_send_vec4(prt.ptr()->out, rv, context);
|
||||
}
|
||||
|
||||
class vvp_reduce_and : public vvp_reduce_base {
|
||||
|
|
|
|||
|
|
@ -35,13 +35,15 @@ resolv_functor::~resolv_functor()
|
|||
{
|
||||
}
|
||||
|
||||
void resolv_functor::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void resolv_functor::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
recv_vec8(port, vvp_vector8_t(bit, 6,6 /* STRONG */));
|
||||
}
|
||||
|
||||
void resolv_functor::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
assert(bit.size() == wid);
|
||||
vvp_vector4_t res (vwid);
|
||||
|
|
@ -55,7 +57,7 @@ void resolv_functor::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
for (unsigned idx = base+wid ; idx < vwid ; idx += 1)
|
||||
res.set_bit(idx, BIT4_Z);
|
||||
|
||||
recv_vec4(port, res);
|
||||
recv_vec4(port, res, 0);
|
||||
}
|
||||
|
||||
void resolv_functor::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
||||
|
|
@ -123,7 +125,8 @@ resolv_wired_logic::~resolv_wired_logic()
|
|||
{
|
||||
}
|
||||
|
||||
void resolv_wired_logic::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void resolv_wired_logic::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
unsigned pdx = port.port();
|
||||
vvp_net_t*ptr = port.ptr();
|
||||
|
|
@ -143,7 +146,7 @@ void resolv_wired_logic::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
out = wired_logic_math_(out, val_[idx]);
|
||||
}
|
||||
|
||||
vvp_send_vec4(ptr->out, out);
|
||||
vvp_send_vec4(ptr->out, out, 0);
|
||||
}
|
||||
|
||||
vvp_vector4_t resolv_triand::wired_logic_math_(vvp_vector4_t&a, vvp_vector4_t&b)
|
||||
|
|
|
|||
|
|
@ -40,11 +40,13 @@ class resolv_functor : public vvp_net_fun_t {
|
|||
explicit resolv_functor(vvp_scalar_t hiz_value, const char* debug =0);
|
||||
~resolv_functor();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
|
||||
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t);
|
||||
void recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
|
||||
|
|
@ -62,7 +64,8 @@ class resolv_wired_logic : public vvp_net_fun_t {
|
|||
explicit resolv_wired_logic(void);
|
||||
~resolv_wired_logic();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
protected:
|
||||
virtual vvp_vector4_t wired_logic_math_(vvp_vector4_t&a, vvp_vector4_t&b) =0;
|
||||
|
|
|
|||
|
|
@ -141,9 +141,9 @@ void assign_vector4_event_s::run_run(void)
|
|||
{
|
||||
count_assign_events += 1;
|
||||
if (vwid > 0)
|
||||
vvp_send_vec4_pv(ptr, val, base, val.size(), vwid);
|
||||
vvp_send_vec4_pv(ptr, val, base, val.size(), vwid, 0);
|
||||
else
|
||||
vvp_send_vec4(ptr, val);
|
||||
vvp_send_vec4(ptr, val, 0);
|
||||
}
|
||||
|
||||
static const size_t ASSIGN4_CHUNK_COUNT = 524288 / sizeof(struct assign_vector4_event_s);
|
||||
|
|
@ -205,7 +205,7 @@ struct assign_real_event_s : public event_s {
|
|||
void assign_real_event_s::run_run(void)
|
||||
{
|
||||
count_assign_events += 1;
|
||||
vvp_send_real(ptr, val);
|
||||
vvp_send_real(ptr, val, 0);
|
||||
}
|
||||
|
||||
static const size_t ASSIGNR_CHUNK_COUNT = 8192 / sizeof(struct assign_real_event_s);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "vvp_net.h"
|
||||
# include "compile.h"
|
||||
# include "symbols.h"
|
||||
# include "codes.h"
|
||||
|
|
@ -61,15 +62,15 @@ ufunc_core::~ufunc_core()
|
|||
* input variables of the function for execution. The method copies
|
||||
* the input values collected by the core to the variables.
|
||||
*/
|
||||
void ufunc_core::assign_bits_to_ports(void)
|
||||
void ufunc_core::assign_bits_to_ports(vvp_context_t context)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < port_count() ; idx += 1) {
|
||||
vvp_net_t*net = ports_[idx];
|
||||
vvp_net_ptr_t pp (net, 0);
|
||||
if (vvp_fun_signal_real*tmp = dynamic_cast<vvp_fun_signal_real*>(net->fun))
|
||||
tmp->recv_real(pp, value_r(idx));
|
||||
tmp->recv_real(pp, value_r(idx), context);
|
||||
if (vvp_fun_signal_vec*tmp = dynamic_cast<vvp_fun_signal_vec*>(net->fun))
|
||||
tmp->recv_vec4(pp, value(idx));
|
||||
tmp->recv_vec4(pp, value(idx), context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class ufunc_core : public vvp_wide_fun_core {
|
|||
struct __vpiScope*call_scope() { return call_scope_; }
|
||||
struct __vpiScope*func_scope() { return func_scope_; }
|
||||
|
||||
void assign_bits_to_ports(void);
|
||||
void assign_bits_to_ports(vvp_context_t context);
|
||||
void finish_thread(vthread_t thr);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -569,7 +569,7 @@ void vvp_vpi_callback_wordable::attach_as_word(vvp_array_t arr, unsigned long ad
|
|||
array_word_ = addr;
|
||||
}
|
||||
|
||||
void vvp_fun_signal::get_value(struct t_vpi_value*vp)
|
||||
void vvp_fun_signal4::get_value(struct t_vpi_value*vp)
|
||||
{
|
||||
switch (vp->format) {
|
||||
case vpiScalarVal:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,21 @@
|
|||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
static int named_event_get(int code, vpiHandle ref)
|
||||
{
|
||||
assert((ref->vpi_type->type_code==vpiNamedEvent));
|
||||
|
||||
struct __vpiNamedEvent*obj = (struct __vpiNamedEvent*)ref;
|
||||
|
||||
switch (code) {
|
||||
|
||||
case vpiAutomatic:
|
||||
return (int) obj->scope->is_automatic;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char* named_event_get_str(int code, vpiHandle ref)
|
||||
{
|
||||
assert((ref->vpi_type->type_code==vpiNamedEvent));
|
||||
|
|
@ -57,7 +72,7 @@ static vpiHandle named_event_get_handle(int code, vpiHandle ref)
|
|||
static const struct __vpirt vpip_named_event_rt = {
|
||||
vpiNamedEvent,
|
||||
|
||||
0,
|
||||
named_event_get,
|
||||
named_event_get_str,
|
||||
0,
|
||||
0,
|
||||
|
|
@ -122,4 +137,3 @@ void vpip_run_named_event_callbacks(vpiHandle ref)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -316,26 +316,6 @@ static void attach_to_scope_(struct __vpiScope*scope, vpiHandle obj)
|
|||
scope->intern[idx] = obj;
|
||||
}
|
||||
|
||||
static void add_item_to_scope_(struct __vpiScope*scope, automatic_hooks_s*item)
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
// there is no need to record items for static scopes
|
||||
if (!scope->is_automatic) return;
|
||||
|
||||
unsigned idx = scope->nitem++;
|
||||
item->context_idx = 1 + idx;
|
||||
|
||||
if (scope->item == 0)
|
||||
scope->item = (automatic_hooks_s**)
|
||||
malloc(sizeof(automatic_hooks_s*));
|
||||
else
|
||||
scope->item = (automatic_hooks_s**)
|
||||
realloc(scope->item, sizeof(automatic_hooks_s*)*scope->nitem);
|
||||
|
||||
scope->item[idx] = item;
|
||||
}
|
||||
|
||||
/*
|
||||
* When the compiler encounters a scope declaration, this function
|
||||
* creates and initializes a __vpiScope object with the requested name
|
||||
|
|
@ -392,7 +372,8 @@ compile_scope_decl(char*label, char*type, char*name, const char*tname,
|
|||
scope->nintern = 0;
|
||||
scope->item = 0;
|
||||
scope->nitem = 0;
|
||||
scope->free_context = 0;
|
||||
scope->live_contexts = 0;
|
||||
scope->free_contexts = 0;
|
||||
scope->threads = 0;
|
||||
|
||||
current_scope = scope;
|
||||
|
|
@ -415,6 +396,10 @@ compile_scope_decl(char*label, char*type, char*name, const char*tname,
|
|||
scope->time_units = sp->time_units;
|
||||
scope->time_precision = sp->time_precision;
|
||||
|
||||
/* Scopes within automatic scopes are themselves automatic. */
|
||||
if (sp->is_automatic)
|
||||
scope->is_automatic = true;
|
||||
|
||||
} else {
|
||||
scope->scope = 0x0;
|
||||
|
||||
|
|
@ -458,7 +443,38 @@ void vpip_attach_to_current_scope(vpiHandle obj)
|
|||
attach_to_scope_(current_scope, obj);
|
||||
}
|
||||
|
||||
void vpip_add_item_to_current_scope(automatic_hooks_s*item)
|
||||
struct __vpiScope* vpip_peek_context_scope(void)
|
||||
{
|
||||
add_item_to_scope_(current_scope, item);
|
||||
struct __vpiScope*scope = current_scope;
|
||||
|
||||
/* A context is allocated for each automatic task or function.
|
||||
Storage for nested scopes (named blocks) is allocated in
|
||||
the parent context. */
|
||||
while (scope->scope && scope->scope->is_automatic)
|
||||
scope = scope->scope;
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
unsigned vpip_add_item_to_context(automatic_hooks_s*item,
|
||||
struct __vpiScope*scope)
|
||||
{
|
||||
assert(scope);
|
||||
assert(scope->is_automatic);
|
||||
|
||||
unsigned idx = scope->nitem++;
|
||||
|
||||
if (scope->item == 0)
|
||||
scope->item = (automatic_hooks_s**)
|
||||
malloc(sizeof(automatic_hooks_s*));
|
||||
else
|
||||
scope->item = (automatic_hooks_s**)
|
||||
realloc(scope->item, sizeof(automatic_hooks_s*)*scope->nitem);
|
||||
|
||||
scope->item[idx] = item;
|
||||
|
||||
/* Offset the context index by 2 to leave space for the list links. */
|
||||
return 2 + idx;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -531,6 +531,8 @@ static int signal_get(int code, vpiHandle ref)
|
|||
case vpiLeftRange: return rfp->msb;
|
||||
case vpiRightRange: return rfp->lsb;
|
||||
|
||||
case vpiAutomatic: return rfp->is_automatic;
|
||||
|
||||
case _vpiNexusId:
|
||||
if (rfp->msb == rfp->lsb)
|
||||
return (int) (unsigned long) rfp->node;
|
||||
|
|
@ -765,7 +767,7 @@ static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp, int flags)
|
|||
port-0. This is the port where signals receive input. */
|
||||
vvp_net_ptr_t destination (rfp->node, dest_port);
|
||||
|
||||
vvp_send_vec4(destination, val);
|
||||
vvp_send_vec4(destination, val, vthread_get_wt_context());
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
|
@ -861,6 +863,7 @@ vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_net_t*vec)
|
|||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
||||
obj->vpi_type = &vpip_reg_rt;
|
||||
rfp->isint_ = true;
|
||||
rfp->is_automatic = vpip_peek_current_scope()->is_automatic;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -871,7 +874,9 @@ vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
|
|||
bool signed_flag, vvp_net_t*vec)
|
||||
{
|
||||
vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
|
||||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
||||
obj->vpi_type = &vpip_reg_rt;
|
||||
rfp->is_automatic = vpip_peek_current_scope()->is_automatic;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -910,6 +915,7 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
|||
obj->signed_flag = signed_flag? 1 : 0;
|
||||
obj->isint_ = 0;
|
||||
obj->is_netarray = 0;
|
||||
obj->is_automatic = vpip_peek_current_scope()->is_automatic;
|
||||
obj->node = node;
|
||||
|
||||
// Place this object within a scope. If this object is
|
||||
|
|
@ -1100,9 +1106,10 @@ static vpiHandle PV_put_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
vvp_net_ptr_t dest(rfp->net, 0);
|
||||
|
||||
if (full_sig) {
|
||||
vvp_send_vec4(dest, val);
|
||||
vvp_send_vec4(dest, val, vthread_get_wt_context());
|
||||
} else {
|
||||
vvp_send_vec4_pv(dest, val, base, width, sig_size);
|
||||
vvp_send_vec4_pv(dest, val, base, width, sig_size,
|
||||
vthread_get_wt_context());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -403,7 +403,7 @@ static vpiHandle sysfunc_put_4net_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
assert(0);
|
||||
}
|
||||
|
||||
vvp_send_vec4(rfp->fnet->out, val);
|
||||
vvp_send_vec4(rfp->fnet->out, val, vthread_get_wt_context());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -427,7 +427,7 @@ static vpiHandle sysfunc_put_rnet_value(vpiHandle ref, p_vpi_value vp, int)
|
|||
assert(0);
|
||||
}
|
||||
|
||||
vvp_send_real(rfp->fnet->out, val);
|
||||
vvp_send_real(rfp->fnet->out, val, vthread_get_wt_context());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -62,27 +62,37 @@ extern void vthread_run(vthread_t thr);
|
|||
*/
|
||||
extern void vthread_schedule_list(vthread_t thr);
|
||||
|
||||
/*
|
||||
* This function returns a handle to the writable context of the currently
|
||||
* running thread. Normally the writable context is the context allocated
|
||||
* to the scope associated with that thread. However, between executing a
|
||||
* %alloc instruction and executing the associated %fork instruction, the
|
||||
* writable context changes to the newly allocated context, thus allowing
|
||||
* the input parameters of an automatic task or function to be written to
|
||||
* the task/function local variables.
|
||||
*/
|
||||
extern vvp_context_t vthread_get_wt_context();
|
||||
|
||||
/*
|
||||
* This function returns a handle to the readable context of the currently
|
||||
* running thread. Normally the readable context is the context allocated
|
||||
* to the scope associated with that thread. However, between executing a
|
||||
* %join instruction and executing the associated %free instruction, the
|
||||
* readable context changes to the context allocated to the newly joined
|
||||
* thread, thus allowing the output parameters of an automatic task or
|
||||
* function to be read from the task/function local variables.
|
||||
*/
|
||||
extern vvp_context_t vthread_get_rd_context();
|
||||
|
||||
/*
|
||||
* This function returns a handle to an item in the writable context
|
||||
* of the currently running thread. Normally the writable context is
|
||||
* the context allocated to the scope associated with that thread.
|
||||
* However, between executing a %alloc instruction and executing the
|
||||
* associated %fork instruction, the writable context changes to the
|
||||
* newly allocated context, thus allowing the input parameters of an
|
||||
* automatic task or function to be written to the task/function local
|
||||
* variables.
|
||||
* of the currently running thread.
|
||||
*/
|
||||
extern vvp_context_item_t vthread_get_wt_context_item(unsigned context_idx);
|
||||
|
||||
/*
|
||||
* This function returns a handle to an item in the readable context
|
||||
* of the currently running thread. Normally the readable context is
|
||||
* the context allocated to the scope associated with that thread.
|
||||
* However, between executing a %join instruction and executing the
|
||||
* associated %free instruction, the readable context changes to the
|
||||
* context allocated to the newly joined thread, thus allowing the
|
||||
* output parameters of an automatic task or function to be read from
|
||||
* the task/function local variables.
|
||||
* of the currently running thread.
|
||||
*/
|
||||
extern vvp_context_item_t vthread_get_rd_context_item(unsigned context_idx);
|
||||
|
||||
|
|
|
|||
|
|
@ -124,9 +124,11 @@ class vvp_island_port : public vvp_net_fun_t {
|
|||
explicit vvp_island_port(vvp_island*ip);
|
||||
~vvp_island_port();
|
||||
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
virtual void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid);
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t);
|
||||
virtual void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||
|
||||
vvp_vector8_t invalue;
|
||||
|
|
@ -309,13 +311,15 @@ vvp_island_port::~vvp_island_port()
|
|||
{
|
||||
}
|
||||
|
||||
void vvp_island_port::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
void vvp_island_port::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
recv_vec8(port, vvp_vector8_t(bit, 6, 6));
|
||||
}
|
||||
|
||||
void vvp_island_port::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||
unsigned base, unsigned wid, unsigned vwid)
|
||||
unsigned base, unsigned wid, unsigned vwid,
|
||||
vvp_context_t)
|
||||
{
|
||||
vvp_vector8_t tmp(bit, 6, 6);
|
||||
if (invalue.size()==0) {
|
||||
|
|
|
|||
548
vvp/vvp_net.cc
548
vvp/vvp_net.cc
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
# include "config.h"
|
||||
# include "vvp_net.h"
|
||||
# include "vpi_priv.h"
|
||||
# include "schedule.h"
|
||||
# include "statistics.h"
|
||||
# include <stdio.h>
|
||||
|
|
@ -227,13 +228,13 @@ void vvp_send_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&val)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_send_real(vvp_net_ptr_t ptr, double val)
|
||||
void vvp_send_real(vvp_net_ptr_t ptr, double val, vvp_context_t context)
|
||||
{
|
||||
while (struct vvp_net_t*cur = ptr.ptr()) {
|
||||
vvp_net_ptr_t next = cur->port[ptr.port()];
|
||||
|
||||
if (cur->fun)
|
||||
cur->fun->recv_real(ptr, val);
|
||||
cur->fun->recv_real(ptr, val, context);
|
||||
|
||||
ptr = next;
|
||||
}
|
||||
|
|
@ -1298,12 +1299,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 **** */
|
||||
|
||||
/*
|
||||
|
|
|
|||
255
vvp/vvp_net.h
255
vvp/vvp_net.h
|
|
@ -52,7 +52,9 @@ class vvp_delay_t;
|
|||
|
||||
/*
|
||||
* Storage for items declared in automatically allocated scopes (i.e. automatic
|
||||
* tasks and functions).
|
||||
* tasks and functions). The first two slots in each context are reserved for
|
||||
* linking to other contexts. The function that adds items to a context knows
|
||||
* this, and allocates context indices accordingly.
|
||||
*/
|
||||
typedef void**vvp_context_t;
|
||||
|
||||
|
|
@ -60,7 +62,8 @@ typedef void*vvp_context_item_t;
|
|||
|
||||
inline vvp_context_t vvp_allocate_context(unsigned nitem)
|
||||
{
|
||||
return (vvp_context_t)malloc((1 + nitem) * sizeof(void*));
|
||||
|
||||
return (vvp_context_t)malloc((2 + nitem) * sizeof(void*));
|
||||
}
|
||||
|
||||
inline vvp_context_t vvp_get_next_context(vvp_context_t context)
|
||||
|
|
@ -73,6 +76,16 @@ inline void vvp_set_next_context(vvp_context_t context, vvp_context_t next)
|
|||
context[0] = next;
|
||||
}
|
||||
|
||||
inline vvp_context_t vvp_get_stacked_context(vvp_context_t context)
|
||||
{
|
||||
return (vvp_context_t)context[1];
|
||||
}
|
||||
|
||||
inline void vvp_set_stacked_context(vvp_context_t context, vvp_context_t stack)
|
||||
{
|
||||
context[1] = stack;
|
||||
}
|
||||
|
||||
inline vvp_context_item_t vvp_get_context_item(vvp_context_t context,
|
||||
unsigned item_idx)
|
||||
{
|
||||
|
|
@ -88,18 +101,15 @@ inline void vvp_set_context_item(vvp_context_t context, unsigned item_idx,
|
|||
/*
|
||||
* An "automatic" functor is one which may be associated with an automatically
|
||||
* allocated scope item. This provides the infrastructure needed to allocate
|
||||
* and access the state information for individual instances of the item. A
|
||||
* context_idx value of 0 indicates a statically allocated item.
|
||||
* the state information for individual instances of the item.
|
||||
*/
|
||||
struct automatic_hooks_s {
|
||||
|
||||
automatic_hooks_s() : context_idx(0) {}
|
||||
automatic_hooks_s() {}
|
||||
virtual ~automatic_hooks_s() {}
|
||||
|
||||
virtual void alloc_instance(vvp_context_t context) {}
|
||||
virtual void reset_instance(vvp_context_t context) {}
|
||||
|
||||
unsigned context_idx;
|
||||
virtual void alloc_instance(vvp_context_t context) = 0;
|
||||
virtual void reset_instance(vvp_context_t context) = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -179,6 +189,8 @@ class vvp_vector4_t {
|
|||
|
||||
friend vvp_vector4_t operator ~(const vvp_vector4_t&that);
|
||||
friend class vvp_vector4array_t;
|
||||
friend class vvp_vector4array_sa;
|
||||
friend class vvp_vector4array_aa;
|
||||
|
||||
public:
|
||||
explicit vvp_vector4_t(unsigned size =0, vvp_bit4_t bits =BIT4_X);
|
||||
|
|
@ -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()];
|
||||
|
|
|
|||
66
vvp/words.cc
66
vvp/words.cc
|
|
@ -34,10 +34,15 @@ static void __compile_var_real(char*label, char*name,
|
|||
vvp_array_t array, unsigned long array_addr,
|
||||
int msb, int lsb)
|
||||
{
|
||||
vvp_fun_signal_real*fun = new vvp_fun_signal_real;
|
||||
vvp_fun_signal_real*fun;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
fun = new vvp_fun_signal_real_aa;
|
||||
} else {
|
||||
fun = new vvp_fun_signal_real_sa;
|
||||
}
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
net->fun = fun;
|
||||
vpip_add_item_to_current_scope(fun);
|
||||
|
||||
define_functor_symbol(label, net);
|
||||
|
||||
vpiHandle obj = vpip_make_real_var(name, net);
|
||||
|
|
@ -79,11 +84,15 @@ static void __compile_var(char*label, char*name,
|
|||
{
|
||||
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||
|
||||
vvp_fun_signal*vsig = new vvp_fun_signal(wid);
|
||||
vvp_fun_signal_vec*vsig;
|
||||
if (vpip_peek_current_scope()->is_automatic) {
|
||||
vsig = new vvp_fun_signal4_aa(wid);
|
||||
} else {
|
||||
vsig = new vvp_fun_signal4_sa(wid);
|
||||
}
|
||||
vvp_net_t*node = new vvp_net_t;
|
||||
|
||||
node->fun = vsig;
|
||||
vpip_add_item_to_current_scope(vsig);
|
||||
|
||||
define_functor_symbol(label, node);
|
||||
|
||||
vpiHandle obj = 0;
|
||||
|
|
@ -154,12 +163,12 @@ static void __compile_net(char*label, char*name,
|
|||
|
||||
vvp_net_t*node = new vvp_net_t;
|
||||
|
||||
vvp_array_t array = array_label? array_find(array_label) : 0;
|
||||
assert(array_label? array!=0 : true);
|
||||
vvp_array_t array = array_label ? array_find(array_label) : 0;
|
||||
assert(array_label ? array!=0 : true);
|
||||
|
||||
vvp_fun_signal_base*vsig = net8_flag
|
||||
? dynamic_cast<vvp_fun_signal_base*>(new vvp_fun_signal8(wid))
|
||||
: dynamic_cast<vvp_fun_signal_base*>(new vvp_fun_signal(wid,BIT4_Z));
|
||||
: dynamic_cast<vvp_fun_signal_base*>(new vvp_fun_signal4_sa(wid,BIT4_Z));
|
||||
node->fun = vsig;
|
||||
|
||||
/* Add the label into the functor symbol table. */
|
||||
|
|
@ -210,12 +219,17 @@ void compile_netw(char*label, char*array_label, unsigned long array_addr,
|
|||
argc, argv);
|
||||
}
|
||||
|
||||
void compile_net_real(char*label, char*name, int msb, int lsb, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
static void __compile_real(char*label, char*name,
|
||||
char*array_label, unsigned long array_addr,
|
||||
int msb, int lsb, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_net_t*net = new vvp_net_t;
|
||||
|
||||
vvp_fun_signal_real*fun = new vvp_fun_signal_real;
|
||||
vvp_array_t array = array_label ? array_find(array_label) : 0;
|
||||
assert(array_label ? array!=0 : true);
|
||||
|
||||
vvp_fun_signal_real*fun = new vvp_fun_signal_real_sa;
|
||||
net->fun = fun;
|
||||
|
||||
/* Add the label into the functor symbol table. */
|
||||
|
|
@ -226,18 +240,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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue