Commentary
This commit is contained in:
parent
23a3271c06
commit
9df9ff59e0
|
|
@ -1913,54 +1913,71 @@ documented below.
|
||||||
Verilator has an important difference from an event based simulator; signal
|
Verilator has an important difference from an event based simulator; signal
|
||||||
values that are changed by the VPI will not immediately propagate their
|
values that are changed by the VPI will not immediately propagate their
|
||||||
values, instead the top level header file's eval() method must be called.
|
values, instead the top level header file's eval() method must be called.
|
||||||
Normally this would be part of the normal evaluation (IE the next clock
|
Normally this would be part of the normal evaluation (i.e. the next clock
|
||||||
edge), not as part of the value change. This makes the performance of VPI
|
edge), not as part of the value change. This makes the performance of VPI
|
||||||
routines extremely fast compared to event based simulators, but can confuse
|
routines extremely fast compared to event based simulators, but can confuse
|
||||||
some test-benches that expect immediate propagation.
|
some test-benches that expect immediate propagation.
|
||||||
|
|
||||||
Note the VPI by it's specified implementation will always be much slower
|
Note the VPI by its specified implementation will always be much slower
|
||||||
than accessing the Verilator values by direct reference
|
than accessing the Verilator values by direct reference
|
||||||
(structure->module->signame), as the VPI accessors perform lookup in
|
(structure->module->signame), as the VPI accessors perform lookup in
|
||||||
functions at runtime requiring at best hundreds of instructions, while the
|
functions at runtime requiring at best hundreds of instructions, while the
|
||||||
direct references are evaluated by the compiler and result in only a couple
|
direct references are evaluated by the compiler and result in only a couple
|
||||||
of instructions.
|
of instructions.
|
||||||
|
|
||||||
|
For signal callbacks to work the main loop of the program must call
|
||||||
|
VerilatedVpi::callValueCbs().
|
||||||
|
|
||||||
=head2 VPI Example
|
=head2 VPI Example
|
||||||
|
|
||||||
In the below example, we have readme marked read-only, and writeme which if
|
In the below example, we have readme marked read-only, and writeme which if
|
||||||
written from outside the model will have the same semantics as if it
|
written from outside the model will have the same semantics as if it
|
||||||
changed on the specified clock edge.
|
changed on the specified clock edge.
|
||||||
|
|
||||||
module t;
|
cat <<EOF >our.v
|
||||||
reg readme /*verilator public_flat_rd*/;
|
module our (input clk);
|
||||||
reg writeme /*verilator public_flat_rw @(posedge clk) */;
|
reg readme /*verilator public_flat_rd*/;
|
||||||
endmodule
|
reg writeme /*verilator public_flat_rw @(posedge clk) */;
|
||||||
|
initial $finish;
|
||||||
|
endmodule
|
||||||
|
EOF
|
||||||
|
|
||||||
There are many online tutorials and books on the VPI, but an example that
|
There are many online tutorials and books on the VPI, but an example that
|
||||||
accesses the above would be:
|
accesses the above signal "readme" would be:
|
||||||
|
|
||||||
void read_and_check() {
|
cat <<EOF >sim_main.cpp
|
||||||
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.readme", NULL);
|
#include "Vour.h"
|
||||||
if (!vh1) { error... }
|
#include "verilated.h"
|
||||||
const char* name = vpi_get_str(vpiName, vh1);
|
#include "verilated_vpi.h" // Required to get definitions
|
||||||
printf("Module name: %s\n"); // Prints "readme"
|
|
||||||
|
|
||||||
s_vpi_value v;
|
vluint64_t main_time = 0; // See comments in first example
|
||||||
v.format = vpiIntVal;
|
double sc_time_stamp () { return main_time; }
|
||||||
vpi_get_value(vh1, &v);
|
|
||||||
printf("Value of v: %d\n", v.value.integer); // Prints "readme"
|
|
||||||
}
|
|
||||||
|
|
||||||
For signal callbacks to work the main loop of the program must call
|
void read_and_check() {
|
||||||
VerilatedVpi::callValueCbs().
|
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"TOP.our.readme", NULL);
|
||||||
|
if (!vh1) { vl_fatal(__FILE__, __LINE__, "sim_main", "No handle found"); }
|
||||||
|
const char* name = vpi_get_str(vpiName, vh1);
|
||||||
|
printf("Module name: %s\n", name); // Prints "readme"
|
||||||
|
|
||||||
#include "verilated_vpi.h" // Required to get definitions
|
s_vpi_value v;
|
||||||
...
|
v.format = vpiIntVal;
|
||||||
while (time passes) {
|
vpi_get_value(vh1, &v);
|
||||||
...
|
printf("Value of v: %d\n", v.value.integer); // Prints "readme"
|
||||||
topp->eval();
|
}
|
||||||
VerilatedVpi::callValueCbs();
|
|
||||||
}
|
int main(int argc, char **argv, char **env) {
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
|
Vour* top = new Vour;
|
||||||
|
Verilated::internalsDump(); // See scopes to help debug
|
||||||
|
while (!Verilated::gotFinish()) {
|
||||||
|
top->eval();
|
||||||
|
VerilatedVpi::callValueCbs(); // For signal callbacks
|
||||||
|
read_and_check();
|
||||||
|
}
|
||||||
|
delete top;
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
=head1 CROSS COMPILATION
|
=head1 CROSS COMPILATION
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue