Support VPI product info, warning calls, etc, bug588.

This commit is contained in:
Wilson Snyder 2013-01-17 21:40:37 -05:00
parent de4016dcff
commit e7ba6ef492
15 changed files with 1531 additions and 102 deletions

View File

@ -12,6 +12,8 @@ indicates the contributor was also the author of the fix; Thanks!
*** Support bind, to module names only, bug602. [Ed Lander]
*** Support VPI product info, warning calls, etc, bug588. [Rick Porter]
*** Define SYSTEMVERILOG, SV_COV_START and other IEEE mandated predefines.
**** Fix pin width mismatch error, bug595. [Alex Solomatnikov]

View File

@ -455,7 +455,7 @@ clean mostlyclean distclean maintainer-clean::
distclean maintainer-clean::
rm -f Makefile config.status config.cache config.log verilator_bin* TAGS
rm -f include/verilated.mk
rm -f include/verilated.mk include/verilated_config.h
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \
${srcdir}/*.in ${srcdir}/*.pod

View File

@ -8,7 +8,7 @@
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[3.845 devel])
AC_CONFIG_HEADER(src/config_build.h)
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
AC_MSG_RESULT([configuring for $PACKAGE_STRING])

1
include/.gitignore vendored
View File

@ -1 +1,2 @@
verilated.mk
verilated_config.h

View File

@ -40,6 +40,7 @@ Verilated::Serialized Verilated::s_s;
VL_THREAD const VerilatedScope* Verilated::t_dpiScopep = NULL;
VL_THREAD const char* Verilated::t_dpiFilename = "";
VL_THREAD int Verilated::t_dpiLineno = 0;
struct Verilated::CommandArgValues Verilated::s_args = {0, NULL};
VerilatedImp VerilatedImp::s_s;
@ -86,6 +87,7 @@ Verilated::Serialized::Serialized() {
s_calcUnusedSigs = false;
s_gotFinish = false;
s_assertOn = true;
s_fatalOnVpiError = true; // retains old default behaviour
}
//===========================================================================
@ -1064,6 +1066,8 @@ void Verilated::flushCb(VerilatedVoidCb cb) {
}
void Verilated::commandArgs(int argc, const char** argv) {
s_args.argc = argc;
s_args.argv = argv;
VerilatedImp::commandArgs(argc,argv);
}

View File

@ -28,6 +28,7 @@
#ifndef _VERILATED_H_
#define _VERILATED_H_ 1 ///< Header Guard
#include "verilated_config.h"
#include "verilatedos.h"
#include <cassert>
@ -229,6 +230,7 @@ private:
bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
bool s_gotFinish; ///< A $finish statement executed
bool s_assertOn; ///< Assertions are enabled
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
Serialized();
} s_s;
@ -236,6 +238,13 @@ private:
static VL_THREAD const char* t_dpiFilename; ///< DPI context filename
static VL_THREAD int t_dpiLineno; ///< DPI context line number
// no need to be save-restored (serialized) the
// assumption is that the restore is allowed to pass different arguments
static struct CommandArgValues {
int argc;
const char** argv;
} s_args;
public:
// METHODS - User called
@ -268,6 +277,9 @@ public:
/// Enable/disable assertions
static void assertOn(bool flag) { s_s.s_assertOn=flag; }
static bool assertOn() { return s_s.s_assertOn; }
/// Enable/disable vpi fatal
static void fatalOnVpiError(bool flag) { s_s.s_fatalOnVpiError=flag; }
static bool fatalOnVpiError() { return s_s.s_fatalOnVpiError; }
/// Flush callback for VCD waves
static void flushCb(VerilatedVoidCb cb);
static void flushCall() { if (s_flushCb) (*s_flushCb)(); }
@ -275,8 +287,13 @@ public:
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
static void commandArgs(int argc, const char** argv);
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
static CommandArgValues* getCommandArgs() {return &s_args;}
static const char* commandArgsPlusMatch(const char* prefixp);
/// Produce name & version for (at least) VPI
static const char* productName() { return VERILATOR_PRODUCT; }
static const char* productVersion() { return VERILATOR_VERSION; }
/// For debugging, print text list of all scope names with
/// dpiImport/Export context. This function may change in future
/// releases - contact the authors before production use.

View File

@ -0,0 +1,28 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2003-2012 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
//
// Verilator 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.
//
//*************************************************************************
///
/// \file
/// \brief Verilator: Auto version information include for all Verilated C files
///
/// Code available from: http://www.veripool.org/verilator
///
//*************************************************************************
///**** Product and Version name
// Autoconf substitutes this with the strings from AC_INIT.
#define VERILATOR_PRODUCT "@PACKAGE_NAME@"
#define VERILATOR_VERSION "@PACKAGE_VERSION@"

View File

@ -31,3 +31,334 @@ VerilatedVpi VerilatedVpi::s_s; // Singleton
vluint8_t* VerilatedVpio::s_freeHead = NULL;
//======================================================================
const char* VerilatedVpiError::strFromVpiVal(PLI_INT32 vpiVal) {
static const char *names[] = {
"*undefined*",
"vpiBinStrVal",
"vpiOctStrVal",
"vpiDecStrVal",
"vpiHexStrVal",
"vpiScalarVal",
"vpiIntVal",
"vpiRealVal",
"vpiStringVal",
"vpiVectorVal",
"vpiStrengthVal",
"vpiTimeVal",
"vpiObjTypeVal",
"vpiSuppressVal",
"vpiShortIntVal",
"vpiLongIntVal",
"vpiShortRealVal",
"vpiRawTwoStateVal",
"vpiRawFourStateVal",
};
if (vpiVal < 0) return names[0];
return names[(vpiVal<=vpiRawFourStateVal)?vpiVal:0];
}
const char* VerilatedVpiError::strFromVpiObjType(PLI_INT32 vpiVal) {
static const char *names[] = {
"*undefined*",
"vpiAlways",
"vpiAssignStmt",
"vpiAssignment",
"vpiBegin",
"vpiCase",
"vpiCaseItem",
"vpiConstant",
"vpiContAssign",
"vpiDeassign",
"vpiDefParam",
"vpiDelayControl",
"vpiDisable",
"vpiEventControl",
"vpiEventStmt",
"vpiFor",
"vpiForce",
"vpiForever",
"vpiFork",
"vpiFuncCall",
"vpiFunction",
"vpiGate",
"vpiIf",
"vpiIfElse",
"vpiInitial",
"vpiIntegerVar",
"vpiInterModPath",
"vpiIterator",
"vpiIODecl",
"vpiMemory",
"vpiMemoryWord",
"vpiModPath",
"vpiModule",
"vpiNamedBegin",
"vpiNamedEvent",
"vpiNamedFork",
"vpiNet",
"vpiNetBit",
"vpiNullStmt",
"vpiOperation",
"vpiParamAssign",
"vpiParameter",
"vpiPartSelect",
"vpiPathTerm",
"vpiPort",
"vpiPortBit",
"vpiPrimTerm",
"vpiRealVar",
"vpiReg",
"vpiRegBit",
"vpiRelease",
"vpiRepeat",
"vpiRepeatControl",
"vpiSchedEvent",
"vpiSpecParam",
"vpiSwitch",
"vpiSysFuncCall",
"vpiSysTaskCall",
"vpiTableEntry",
"vpiTask",
"vpiTaskCall",
"vpiTchk",
"vpiTchkTerm",
"vpiTimeVar",
"vpiTimeQueue",
"vpiUdp",
"vpiUdpDefn",
"vpiUserSystf",
"vpiVarSelect",
"vpiWait",
"vpiWhile",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"vpiAttribute",
"vpiBitSelect",
"vpiCallback",
"vpiDelayTerm",
"vpiDelayDevice",
"vpiFrame",
"vpiGateArray",
"vpiModuleArray",
"vpiPrimitiveArray",
"vpiNetArray",
"vpiRange",
"vpiRegArray",
"vpiSwitchArray",
"vpiUdpArray",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"*undefined*",
"vpiContAssignBit",
"vpiNamedEventArray",
"vpiIndexedPartSelect",
"*undefined*",
"*undefined*",
"vpiGenScopeArray",
"vpiGenScope",
"vpiGenVar"
};
if (vpiVal < 0) return names[0];
return names[(vpiVal<=vpiGenVar)?vpiVal:0];
}
const char* VerilatedVpiError::strFromVpiMethod(PLI_INT32 vpiVal) {
static const char *names[] = {
"vpiCondition",
"vpiDelay",
"vpiElseStmt",
"vpiForIncStmt",
"vpiForInitStmt",
"vpiHighConn",
"vpiLhs",
"vpiIndex",
"vpiLeftRange",
"vpiLowConn",
"vpiParent",
"vpiRhs",
"vpiRightRange",
"vpiScope",
"vpiSysTfCall",
"vpiTchkDataTerm",
"vpiTchkNotifier",
"vpiTchkRefTerm",
"vpiArgument",
"vpiBit",
"vpiDriver",
"vpiInternalScope",
"vpiLoad",
"vpiModDataPathIn",
"vpiModPathIn",
"vpiModPathOut",
"vpiOperand",
"vpiPortInst",
"vpiProcess",
"vpiVariables",
"vpiUse",
"vpiExpr",
"vpiPrimitive",
"vpiStmt"
};
if (vpiVal>vpiStmt || vpiVal<vpiCondition) {
return "*undefined*";
}
return names[vpiVal-vpiCondition];
}
const char* VerilatedVpiError::strFromVpiCallbackReason(PLI_INT32 vpiVal) {
static const char *names[] = {
"*undefined*",
"cbValueChange",
"cbStmt",
"cbForce",
"cbRelease",
"cbAtStartOfSimTime",
"cbReadWriteSynch",
"cbReadOnlySynch",
"cbNextSimTime",
"cbAfterDelay",
"cbEndOfCompile",
"cbStartOfSimulation",
"cbEndOfSimulation",
"cbError",
"cbTchkViolation",
"cbStartOfSave",
"cbEndOfSave",
"cbStartOfRestart",
"cbEndOfRestart",
"cbStartOfReset",
"cbEndOfReset",
"cbEnterInteractive",
"cbExitInteractive",
"cbInteractiveScopeChange",
"cbUnresolvedSystf",
"cbAssign",
"cbDeassign",
"cbDisable",
"cbPLIError",
"cbSignal",
"cbNBASynch",
"cbAtEndOfSimTime"
};
if (vpiVal < 0) return names[0];
return names[(vpiVal<=cbAtEndOfSimTime)?vpiVal:0];
}
const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) {
static const char *names[] = {
"*undefined or other*",
"vpiType",
"vpiName",
"vpiFullName",
"vpiSize",
"vpiFile",
"vpiLineNo",
"vpiTopModule",
"vpiCellInstance",
"vpiDefName",
"vpiProtected",
"vpiTimeUnit",
"vpiTimePrecision",
"vpiDefNetType",
"vpiUnconnDrive",
"vpiDefFile",
"vpiDefLineNo",
"vpiScalar",
"vpiVector",
"vpiExplicitName",
"vpiDirection",
"vpiConnByName",
"vpiNetType",
"vpiExplicitScalared",
"vpiExplicitVectored",
"vpiExpanded",
"vpiImplicitDecl",
"vpiChargeStrength",
"vpiArray",
"vpiPortIndex",
"vpiTermIndex",
"vpiStrength0",
"vpiStrength1",
"vpiPrimType",
"vpiPolarity",
"vpiDataPolarity",
"vpiEdge",
"vpiPathType",
"vpiTchkType",
"vpiOpType",
"vpiConstType",
"vpiBlocking",
"vpiCaseType",
"vpiFuncType",
"vpiNetDeclAssign",
"vpiUserDefn",
"vpiScheduled",
"*undefined*",
"*undefined*",
"vpiActive",
"vpiAutomatic",
"vpiCell",
"vpiConfig",
"vpiConstantSelect",
"vpiDecompile",
"vpiDefAttribute",
"vpiDelayType",
"vpiIteratorType",
"vpiLibrary",
"*undefined*",
"vpiOffset",
"vpiResolvedNetType",
"vpiSaveRestartID",
"vpiSaveRestartLocation",
"vpiValid",
"vpiSigned",
"vpiStop",
"vpiFinish",
"vpiReset",
"vpiSetInteractiveScope",
"vpiLocalParam",
"vpiModPathHasIfNone",
"vpiIndexedPartSelectType",
"vpiIsMemory",
"vpiIsProtected"
};
if (vpiVal == vpiUndefined) {
return "vpiUndefined";
}
return names[(vpiVal<=vpiIsProtected)?vpiVal:0];
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,208 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2010-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License.
// Version 2.0.
//
// Verilator 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.
//
//*************************************************************************
#include "Vt_vpi_unimpl.h"
#include "verilated.h"
#include "svdpi.h"
#include "Vt_vpi_unimpl__Dpi.h"
#include "verilated_vpi.h"
#include "verilated_vpi.cpp"
#include "verilated_vcd_c.h"
#include <iostream>
// __FILE__ is too long
#define FILENM "t_vpi_unimpl.cpp"
#define DEBUG if (0) printf
unsigned int main_time = false;
unsigned int callback_count = false;
//======================================================================
class VlVpiHandle {
/// For testing, etc, wrap vpiHandle in an auto-releasing class
vpiHandle m_handle;
public:
VlVpiHandle() : m_handle(NULL) { }
VlVpiHandle(vpiHandle h) : m_handle(h) { }
~VlVpiHandle() { if (m_handle) { vpi_release_handle(m_handle); m_handle=NULL; } }
operator vpiHandle () const { return m_handle; }
inline VlVpiHandle& operator= (vpiHandle h) { m_handle = h; return *this; }
};
//======================================================================
#define CHECK_RESULT_VH(got, exp) \
if ((got) != (exp)) { \
printf("%%Error: %s:%d: GOT = %p EXP = %p\n", \
FILENM,__LINE__, (got), (exp)); \
return __LINE__; \
}
#define CHECK_RESULT_NZ(got) \
if (!(got)) { \
printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM,__LINE__); \
return __LINE__; \
}
// Use cout to avoid issues with %d/%lx etc
#define CHECK_RESULT(got, exp) \
if ((got != exp)) { \
cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__ \
<<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \
return __LINE__; \
}
#define CHECK_RESULT_HEX(got, exp) \
if ((got != exp)) { \
cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__<<hex \
<<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \
return __LINE__; \
}
#define CHECK_RESULT_CSTR(got, exp) \
if (strcmp((got),(exp))) { \
printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", \
FILENM,__LINE__, (got)?(got):"<null>", (exp)?(exp):"<null>"); \
return __LINE__; \
}
#define CHECK_RESULT_CSTR_STRIP(got, exp) \
CHECK_RESULT_CSTR(got+strspn(got, " "), exp)
int _mon_check_unimpl(p_cb_data cb_data) {
static VlVpiHandle cb, clk_h;
if (cb_data) {
// this is the callback
s_vpi_error_info info;
vpi_chk_error(&info);
callback_count++;
printf("%%Info: got pli message %s\n", info.message);
} else {
// setup and install
static t_cb_data cb_data;
clk_h = vpi_handle_by_name((PLI_BYTE8*)"t.clk", NULL);
cb_data.reason = cbPLIError;
cb_data.cb_rtn = _mon_check_unimpl; // this function
cb = vpi_register_cb(&cb_data);
CHECK_RESULT_NZ(cb);
// now exercise unimplemented fns
vpi_get_cb_info(cb, NULL);
CHECK_RESULT(callback_count, 1);
vpi_register_systf(NULL);
CHECK_RESULT(callback_count, 2);
vpi_get_systf_info(NULL, NULL);
CHECK_RESULT(callback_count, 3);
vpi_handle_multi(0, NULL, NULL);
CHECK_RESULT(callback_count, 4);
vpi_get64(0, NULL);
CHECK_RESULT(callback_count, 5);
vpi_get_delays(NULL, NULL);
CHECK_RESULT(callback_count, 6);
vpi_put_delays(NULL, NULL);
CHECK_RESULT(callback_count, 7);
vpi_get_value_array(NULL, NULL, NULL, 0);
CHECK_RESULT(callback_count, 8);
vpi_put_value_array(NULL, NULL, NULL, 0);
CHECK_RESULT(callback_count, 9);
vpi_get_time(NULL, NULL);
CHECK_RESULT(callback_count, 10);
vpi_mcd_name(0);
CHECK_RESULT(callback_count, 11);
vpi_compare_objects(NULL, NULL);
CHECK_RESULT(callback_count, 12);
vpi_get_data(0, NULL, 0);
CHECK_RESULT(callback_count, 13);
vpi_put_data(0, NULL, 0);
CHECK_RESULT(callback_count, 14);
vpi_get_userdata(NULL);
CHECK_RESULT(callback_count, 15);
vpi_put_userdata(NULL, NULL);
CHECK_RESULT(callback_count, 16);
vpi_handle_by_multi_index(NULL, 0, NULL);
CHECK_RESULT(callback_count, 17);
}
return 0; // Ok
}
int mon_check() {
// Callback from initial block in monitor
if (int status = _mon_check_unimpl(NULL)) return status;
return 0; // Ok
}
//======================================================================
double sc_time_stamp () {
return main_time;
}
int main(int argc, char **argv, char **env) {
double sim_time = 1100;
Verilated::commandArgs(argc, argv);
Verilated::debug(0);
Verilated::fatalOnVpiError(0); // we're going to be checking for these errors do don't crash out
VM_PREFIX* topp = new VM_PREFIX (""); // Note null name - we're flattening it out
#ifdef VERILATOR
# ifdef TEST_VERBOSE
Verilated::scopesDump();
# endif
#endif
Verilated::traceEverOn(true);
VerilatedVcdC* tfp = new VerilatedVcdC;
#if VM_TRACE
VL_PRINTF("Enabling waves...\n");
topp->trace (tfp, 99);
tfp->open ("obj_dir/t_vpi_var/simx.vcd");
#endif
topp->eval();
topp->clk = 0;
main_time += 10;
while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) {
main_time += 1;
topp->eval();
VerilatedVpi::callValueCbs();
topp->clk = !topp->clk;
//mon_do();
#if VM_TRACE
if (tfp) tfp->dump (main_time);
#endif
}
CHECK_RESULT(callback_count, 17);
if (!Verilated::gotFinish()) {
vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish");
}
topp->final();
#if VM_TRACE
if (tfp) tfp->close();
#endif
delete topp; topp=NULL;
exit(0L);
}

View File

@ -0,0 +1,21 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2010 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
make_top_shell => 0,
make_main => 0,
verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --no-l2name $Self->{t_dir}/t_vpi_unimpl.cpp"],
);
execute (
check_finished=>1
);
ok(1);
1;

View File

@ -0,0 +1,42 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// Copyright 2010 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
`ifdef VERILATOR
//We call it via $c so we can verify DPI isn't required - see bug572
`else
import "DPI-C" context function integer mon_check();
`endif
module t (/*AUTOARG*/
// Inputs
clk
);
`ifdef VERILATOR
`systemc_header
extern "C" int mon_check();
`verilog
`endif
input clk;
reg onebit /*verilator public_flat_rw @(posedge clk) */;
integer status;
// Test loop
initial begin
`ifdef VERILATOR
status = $c32("mon_check()");
`else
status = mon_check();
`endif
$write("*-* All Finished *-*\n");
$finish;
end
endmodule : t

View File

@ -28,10 +28,14 @@
// __FILE__ is too long
#define FILENM "t_vpi_var.cpp"
#define TEST_MSG if (0) printf
unsigned int main_time = false;
unsigned int callback_count = false;
unsigned int callback_count_half = false;
unsigned int callback_count_quad = false;
unsigned int callback_count_strs = false;
unsigned int callback_count_strs_max = 500;
//======================================================================
@ -64,15 +68,15 @@ public:
// Use cout to avoid issues with %d/%lx etc
#define CHECK_RESULT(got, exp) \
if ((got != exp)) { \
if ((got) != (exp)) { \
cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__ \
<<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \
return __LINE__; \
}
#define CHECK_RESULT_HEX(got, exp) \
if ((got != exp)) { \
cout<<hex<<"%Error: "<<FILENM<<":"<<__LINE__ \
if ((got) != (exp)) { \
cout<<dec<<"%Error: "<<FILENM<<":"<<__LINE__<<hex \
<<": GOT = "<<(got)<<" EXP = "<<(exp)<<endl; \
return __LINE__; \
}
@ -84,6 +88,9 @@ public:
return __LINE__; \
}
#define CHECK_RESULT_CSTR_STRIP(got, exp) \
CHECK_RESULT_CSTR(got+strspn(got, " "), exp)
int _mon_check_mcd() {
PLI_INT32 status;
@ -352,6 +359,213 @@ int _mon_check_quad() {
return 0;
}
int _mon_check_string() {
static struct {
const char *name;
const char *initial;
const char *value;
} text_test_obs[] = {
{"t.text_byte", "B", "xxA"}, // x's dropped
{"t.text_half", "Hf", "xxT2"}, // x's dropped
{"t.text_word", "Word", "Tree"},
{"t.text_long", "Long64b", "44Four44"},
{"t.text" , "Verilog Test module", "lorem ipsum"},
};
for (int i=0; i<5; i++) {
VlVpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)text_test_obs[i].name, NULL);
CHECK_RESULT_NZ(vh1);
s_vpi_value v;
s_vpi_time t = { vpiSimTime, 0, 0};
s_vpi_error_info e;
v.format = vpiStringVal;
vpi_get_value(vh1, &v);
if (vpi_chk_error(&e)) {
printf("%%vpi_chk_error : %s\n", e.message);
}
CHECK_RESULT_CSTR_STRIP(v.value.str, text_test_obs[i].initial);
v.value.str = (PLI_BYTE8*)text_test_obs[i].value;
vpi_put_value(vh1, &v, &t, vpiNoDelay);
}
return 0;
}
int _mon_check_putget_str(p_cb_data cb_data) {
static VlVpiHandle cb;
static struct {
VlVpiHandle scope, sig, rfr, check, verbose;
char str[128+1]; // char per bit plus null terminator
int type; // value type in .str
union {
PLI_INT32 integer;
s_vpi_vecval vector[4];
} value; // reference
} data[129];
if (cb_data) {
// this is the callback
static unsigned int seed = 1;
s_vpi_time t;
t.type = vpiSimTime;
t.high = 0;
t.low = 0;
for (int i=2; i<=128; i++) {
static s_vpi_value v;
int words = (i+31)>>5;
TEST_MSG("========== %d ==========\n", i);
if (callback_count_strs) {
// check persistance
if (data[i].type) {
v.format = data[i].type;
} else {
static PLI_INT32 vals[] = {vpiBinStrVal, vpiOctStrVal, vpiHexStrVal, vpiDecStrVal};
v.format = vals[rand_r(&seed) % ((words>2)?3:4)];
TEST_MSG("new format %d\n", v.format);
}
vpi_get_value(data[i].sig, &v);
TEST_MSG("%s\n", v.value.str);
if (data[i].type) {
CHECK_RESULT_CSTR(v.value.str, data[i].str);
} else {
data[i].type = v.format;
strcpy(data[i].str, v.value.str);
}
}
// check for corruption
v.format = (words==1)?vpiIntVal:vpiVectorVal;
vpi_get_value(data[i].sig, &v);
if (v.format == vpiIntVal) {
TEST_MSG("%08x %08x\n", v.value.integer, data[i].value.integer);
CHECK_RESULT(v.value.integer, data[i].value.integer);
} else {
for (int k=0; k < words; k++) {
TEST_MSG("%d %08x %08x\n", k, v.value.vector[k].aval, data[i].value.vector[k].aval);
CHECK_RESULT_HEX(v.value.vector[k].aval, data[i].value.vector[k].aval);
}
}
if (callback_count_strs & 7) {
// put same value back - checking encoding/decoding equivalent
v.format = data[i].type;
v.value.str = data[i].str;
vpi_put_value(data[i].sig, &v, &t, vpiNoDelay);
v.format = vpiIntVal;
v.value.integer = 1;
//vpi_put_value(data[i].verbose, &v, &t, vpiNoDelay);
vpi_put_value(data[i].check, &v, &t, vpiNoDelay);
} else {
// stick a new random value in
unsigned int mask = ((i&31)?(1<<(i&31)):0)-1;
if (words == 1) {
v.value.integer = rand_r(&seed);
data[i].value.integer = v.value.integer &= mask;
v.format = vpiIntVal;
TEST_MSG("new value %08x\n", data[i].value.integer);
} else {
TEST_MSG("new value\n");
for (int j=0; j<4; j++) {
data[i].value.vector[j].aval = rand_r(&seed);
if (j==(words-1)) {
data[i].value.vector[j].aval &= mask;
}
TEST_MSG(" %08x\n", data[i].value.vector[j].aval);
}
v.value.vector = data[i].value.vector;
v.format = vpiVectorVal;
}
vpi_put_value(data[i].sig, &v, &t, vpiNoDelay);
vpi_put_value(data[i].rfr, &v, &t, vpiNoDelay);
}
if ((callback_count_strs & 1) == 0) data[i].type = 0;
}
if (++callback_count_strs == callback_count_strs_max) {
int success = vpi_remove_cb(cb);
CHECK_RESULT_NZ(success);
};
} else {
// setup and install
for (int i=1; i<=128; i++) {
char buf[32];
snprintf(buf, sizeof(buf), "t.arr[%d].arr", i);
CHECK_RESULT_NZ(data[i].scope = vpi_handle_by_name((PLI_BYTE8*)buf, NULL));
CHECK_RESULT_NZ(data[i].sig = vpi_handle_by_name((PLI_BYTE8*)"sig", data[i].scope));
CHECK_RESULT_NZ(data[i].rfr = vpi_handle_by_name((PLI_BYTE8*)"rfr", data[i].scope));
CHECK_RESULT_NZ(data[i].check = vpi_handle_by_name((PLI_BYTE8*)"check", data[i].scope));
CHECK_RESULT_NZ(data[i].verbose = vpi_handle_by_name((PLI_BYTE8*)"verbose", data[i].scope));
}
static t_cb_data cb_data;
static s_vpi_value v;
static VlVpiHandle count_h = vpi_handle_by_name((PLI_BYTE8*)"t.count", NULL);
cb_data.reason = cbValueChange;
cb_data.cb_rtn = _mon_check_putget_str; // this function
cb_data.obj = count_h;
cb_data.value = &v;
v.format = vpiIntVal;
cb = vpi_register_cb(&cb_data);
CHECK_RESULT_NZ(cb);
}
return 0;
}
int _mon_check_vlog_info() {
s_vpi_vlog_info vlog_info;
PLI_INT32 rtn = vpi_get_vlog_info(&vlog_info);
CHECK_RESULT(rtn, 1);
CHECK_RESULT(vlog_info.argc, 4);
CHECK_RESULT_CSTR(vlog_info.argv[1], "+PLUS");
CHECK_RESULT_CSTR(vlog_info.argv[2], "+INT=1234");
CHECK_RESULT_CSTR(vlog_info.argv[3], "+STRSTR");
CHECK_RESULT_CSTR(vlog_info.product, "Verilator");
CHECK_RESULT(strlen(vlog_info.version) > 0, 1);
return 0;
}
#define CHECK_ENUM_STR(fn, enum) \
do { \
const char* strVal = VerilatedVpiError::fn(enum); \
CHECK_RESULT_CSTR(strVal, #enum); \
} while (0)
int _mon_check_vl_str() {
CHECK_ENUM_STR(strFromVpiVal, vpiBinStrVal);
CHECK_ENUM_STR(strFromVpiVal, vpiRawFourStateVal);
CHECK_ENUM_STR(strFromVpiObjType, vpiAlways);
CHECK_ENUM_STR(strFromVpiObjType, vpiWhile);
CHECK_ENUM_STR(strFromVpiObjType, vpiAttribute);
CHECK_ENUM_STR(strFromVpiObjType, vpiUdpArray);
CHECK_ENUM_STR(strFromVpiObjType, vpiContAssignBit);
CHECK_ENUM_STR(strFromVpiObjType, vpiGenVar);
CHECK_ENUM_STR(strFromVpiMethod, vpiCondition);
CHECK_ENUM_STR(strFromVpiMethod, vpiStmt);
CHECK_ENUM_STR(strFromVpiCallbackReason, cbValueChange);
CHECK_ENUM_STR(strFromVpiCallbackReason, cbAtEndOfSimTime);
CHECK_ENUM_STR(strFromVpiProp, vpiType);
CHECK_ENUM_STR(strFromVpiProp, vpiProtected);
CHECK_ENUM_STR(strFromVpiProp, vpiDirection);
CHECK_ENUM_STR(strFromVpiProp, vpiTermIndex);
CHECK_ENUM_STR(strFromVpiProp, vpiConstType);
CHECK_ENUM_STR(strFromVpiProp, vpiAutomatic);
CHECK_ENUM_STR(strFromVpiProp, vpiOffset);
CHECK_ENUM_STR(strFromVpiProp, vpiStop);
CHECK_ENUM_STR(strFromVpiProp, vpiIsProtected);
return 0;
}
int mon_check() {
// Callback from initial block in monitor
if (int status = _mon_check_mcd()) return status;
@ -361,6 +575,10 @@ int mon_check() {
if (int status = _mon_check_varlist()) return status;
if (int status = _mon_check_getput()) return status;
if (int status = _mon_check_quad()) return status;
if (int status = _mon_check_string()) return status;
if (int status = _mon_check_putget_str(NULL)) return status;
if (int status = _mon_check_vlog_info()) return status;
if (int status = _mon_check_vl_str()) return status;
return 0; // Ok
}
@ -408,6 +626,7 @@ int main(int argc, char **argv, char **env) {
CHECK_RESULT(callback_count, 501);
CHECK_RESULT(callback_count_half, 250);
CHECK_RESULT(callback_count_quad, 2);
CHECK_RESULT(callback_count_strs, callback_count_strs_max);
if (!Verilated::gotFinish()) {
vl_fatal(FILENM,__LINE__,"main", "%Error: Timeout; never got a $finish");
}

View File

@ -10,11 +10,12 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
compile (
make_top_shell => 0,
make_main => 0,
verilator_flags2 => ["-CFLAGS '-ggdb' --exe --no-l2name $Self->{t_dir}/t_vpi_var.cpp"],
verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --no-l2name $Self->{t_dir}/t_vpi_var.cpp"],
);
execute (
check_finished=>1,
all_run_flags => ['+PLUS +INT=1234 +STRSTR']
);
ok(1);

View File

@ -33,6 +33,12 @@ extern "C" int mon_check();
reg [31:0] count /*verilator public_flat_rd */;
reg [31:0] half_count /*verilator public_flat_rd */;
reg [7:0] text_byte /*verilator public_flat_rw @(posedge clk) */;
reg [15:0] text_half /*verilator public_flat_rw @(posedge clk) */;
reg [31:0] text_word /*verilator public_flat_rw @(posedge clk) */;
reg [63:0] text_long /*verilator public_flat_rw @(posedge clk) */;
reg [511:0] text /*verilator public_flat_rw @(posedge clk) */;
integer status;
sub sub();
@ -40,6 +46,11 @@ extern "C" int mon_check();
// Test loop
initial begin
onebit = 1'b0;
text_byte = "B";
text_half = "Hf";
text_word = "Word";
text_long = "Long64b";
text = "Verilog Test module";
`ifdef VERILATOR
status = $c32("mon_check()");
`else
@ -52,6 +63,11 @@ extern "C" int mon_check();
if (onebit != 1'b1) $stop;
if (quads[2] != 62'h12819213_abd31a1c) $stop;
if (quads[3] != 62'h1c77bb9b_3784ea09) $stop;
if (text_byte != "A") $stop;
if (text_half != "T2") $stop;
if (text_word != "Tree") $stop;
if (text_long != "44Four44") $stop;
if (text != "lorem ipsum") $stop;
end
always @(posedge clk) begin
@ -65,9 +81,33 @@ extern "C" int mon_check();
end
end
genvar i;
generate
for (i=1;i<=128;i++) begin : arr
arr #(.LENGTH(i)) arr();
end endgenerate
endmodule
module sub;
reg subsig1 /*verilator public_flat_rd*/;
reg subsig2 /*verilator public_flat_rd*/;
endmodule
module arr;
parameter LENGTH = 1;
reg [LENGTH-1:0] sig /*verilator public_flat_rw*/;
reg [LENGTH-1:0] rfr /*verilator public_flat_rw*/;
reg check /*verilator public_flat_rw*/;
reg verbose /*verilator public_flat_rw*/;
always @(posedge check) begin
if (verbose) $display("%m : %x %x", sig, rfr);
if (check && sig != rfr) $stop;
check <= 0;
end
endmodule : arr