mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Support VPI parameter and localparam (#2370)
This commit is contained in:
parent
35226d5e1a
commit
c367b671b6
@ -2603,7 +2603,7 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) VL_
|
||||
}
|
||||
}
|
||||
|
||||
void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
|
||||
void VerilatedScope::varInsert(int finalize, const char* namep, void* datap, bool isParam,
|
||||
VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE {
|
||||
// Grab dimensions
|
||||
// In the future we may just create a large table at emit time and
|
||||
@ -2611,7 +2611,7 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
|
||||
if (!finalize) return;
|
||||
|
||||
if (!m_varsp) m_varsp = new VerilatedVarNameMap();
|
||||
VerilatedVar var(namep, datap, vltype, static_cast<VerilatedVarFlags>(vlflags), dims);
|
||||
VerilatedVar var(namep, datap, vltype, static_cast<VerilatedVarFlags>(vlflags), dims, isParam);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, dims);
|
||||
|
@ -335,8 +335,8 @@ public: // But internals only - called from VerilatedModule's
|
||||
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp,
|
||||
const char* identifier, vlsint8_t timeunit, const Type& type) VL_MT_UNSAFE;
|
||||
void exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE;
|
||||
void varInsert(int finalize, const char* namep, void* datap, VerilatedVarType vltype,
|
||||
int vlflags, int dims, ...) VL_MT_UNSAFE;
|
||||
void varInsert(int finalize, const char* namep, void* datap, bool isParam,
|
||||
VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE;
|
||||
// ACCESSORS
|
||||
const char* name() const { return m_namep; }
|
||||
const char* identifier() const { return m_identifierp; }
|
||||
|
@ -232,13 +232,15 @@ class VerilatedVar : public VerilatedVarProps {
|
||||
void* m_datap; // Location of data
|
||||
const char* m_namep; // Name - slowpath
|
||||
protected:
|
||||
bool m_isParam;
|
||||
friend class VerilatedScope;
|
||||
// CONSTRUCTORS
|
||||
VerilatedVar(const char* namep, void* datap, VerilatedVarType vltype,
|
||||
VerilatedVarFlags vlflags, int dims)
|
||||
VerilatedVarFlags vlflags, int dims, bool isParam)
|
||||
: VerilatedVarProps(vltype, vlflags, (dims > 0 ? 1 : 0), ((dims > 1) ? dims - 1 : 0))
|
||||
, m_datap(datap)
|
||||
, m_namep(namep) {}
|
||||
, m_namep(namep)
|
||||
, m_isParam(isParam) {}
|
||||
|
||||
public:
|
||||
~VerilatedVar() {}
|
||||
@ -247,6 +249,7 @@ public:
|
||||
const VerilatedRange& range() const { return packed(); } // Deprecated
|
||||
const VerilatedRange& array() const { return unpacked(); } // Deprecated
|
||||
const char* name() const { return m_namep; }
|
||||
bool isParam() const { return m_isParam; }
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3053,6 +3053,10 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
// support them. They also cause problems with GDB under GCC2.95.
|
||||
if (varp->isWide()) { // Unsupported for output
|
||||
putsDecoration("// enum WData " + varp->nameProtect() + " //wide");
|
||||
} else if (varp->isString()) {
|
||||
puts("const std::string " + protect("var_" + varp->name()) + " = ");
|
||||
iterateAndNextNull(varp->valuep());
|
||||
puts(";");
|
||||
} else if (!VN_IS(varp->valuep(), Const)) { // Unsupported for output
|
||||
// putsDecoration("// enum ..... "+varp->nameProtect()
|
||||
// +"not simple value, see variable above instead");
|
||||
@ -3060,11 +3064,16 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
&& VN_CAST(varp->dtypep(), BasicDType)
|
||||
->isOpaque()) { // Can't put out e.g. doubles
|
||||
} else {
|
||||
puts("enum ");
|
||||
puts(varp->isQuad() ? "_QData" : "_IData");
|
||||
// enum
|
||||
puts(varp->isQuad() ? "enum _QData" : "enum _IData");
|
||||
puts("" + varp->nameProtect() + " { " + varp->nameProtect() + " = ");
|
||||
iterateAndNextNull(varp->valuep());
|
||||
puts("};");
|
||||
puts("};\n");
|
||||
// var
|
||||
puts(varp->isQuad() ? "const QData" : "const IData");
|
||||
puts(" var_" + varp->nameProtect() + " = ");
|
||||
iterateAndNextNull(varp->valuep());
|
||||
puts(";");
|
||||
}
|
||||
puts("\n");
|
||||
}
|
||||
|
@ -332,10 +332,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||
virtual void visit(AstVar* nodep) VL_OVERRIDE {
|
||||
nameCheck(nodep);
|
||||
iterateChildren(nodep);
|
||||
if (nodep->isSigUserRdPublic()
|
||||
// The VPI functions require a pointer to allow modification,
|
||||
// but parameters are constants
|
||||
&& !nodep->isParam()) {
|
||||
if (nodep->isSigUserRdPublic()) {
|
||||
m_modVars.push_back(make_pair(m_modp, nodep));
|
||||
}
|
||||
}
|
||||
@ -794,16 +791,32 @@ void EmitCSyms::emitSymImp() {
|
||||
}
|
||||
puts(protect("__Vscope_" + it->second.m_scopeName) + ".varInsert(__Vfinal,");
|
||||
putsQuoted(protect(it->second.m_varBasePretty));
|
||||
puts(", &(");
|
||||
|
||||
std::string varName;
|
||||
if (modp->isTop()) {
|
||||
puts(protectIf(scopep->nameDotless() + "p", scopep->protect()));
|
||||
puts("->");
|
||||
varName += (protectIf(scopep->nameDotless() + "p", scopep->protect()) + "->");
|
||||
} else {
|
||||
puts(protectIf(scopep->nameDotless(), scopep->protect()));
|
||||
puts(".");
|
||||
varName += (protectIf(scopep->nameDotless(), scopep->protect()) + ".");
|
||||
}
|
||||
puts(varp->nameProtect());
|
||||
puts("), ");
|
||||
|
||||
if (varp->isParam()) {
|
||||
varName += protect("var_" + varp->name());
|
||||
} else {
|
||||
varName += protect(varp->name());
|
||||
}
|
||||
|
||||
if (varp->isParam() && (varp->vlEnumType() == "VLVT_STRING")) {
|
||||
puts(", const_cast<void*>(static_cast<const void*>(");
|
||||
puts(varName.c_str());
|
||||
puts(".c_str())), ");
|
||||
} else {
|
||||
puts(", const_cast<void*>(static_cast<const void*>(&(");
|
||||
puts(varName.c_str());
|
||||
puts("))), ");
|
||||
}
|
||||
|
||||
puts(varp->isParam() ? "true" : "false");
|
||||
puts(", ");
|
||||
puts(varp->vlEnumType()); // VLVT_UINT32 etc
|
||||
puts(",");
|
||||
puts(varp->vlEnumDir()); // VLVD_IN etc
|
||||
|
@ -81,7 +81,9 @@ unsigned int main_time = 0;
|
||||
#define CHECK_RESULT_CSTR_STRIP(got, exp) CHECK_RESULT_CSTR(got + strspn(got, " "), exp)
|
||||
|
||||
static int _mon_check_props(TestVpiHandle& handle, int size, int direction, int scalar, int type) {
|
||||
s_vpi_value value = {.format = vpiIntVal, .value = {.integer = 0}};
|
||||
s_vpi_value value;
|
||||
value.format = vpiIntVal;
|
||||
value.value.integer = 0;
|
||||
// check size of object
|
||||
int vpisize = vpi_get(vpiSize, handle);
|
||||
CHECK_RESULT(vpisize, size);
|
||||
|
@ -82,7 +82,9 @@ unsigned int main_time = 0;
|
||||
|
||||
int _mon_check_range(TestVpiHandle& handle, int size, int left, int right) {
|
||||
TestVpiHandle iter_h, left_h, right_h;
|
||||
s_vpi_value value = {.format = vpiIntVal, .value = {.integer = 0}};
|
||||
s_vpi_value value;
|
||||
value.format = vpiIntVal;
|
||||
value.value.integer = 0;
|
||||
// check size of object
|
||||
int vpisize = vpi_get(vpiSize, handle);
|
||||
CHECK_RESULT(vpisize, size);
|
||||
@ -108,7 +110,11 @@ int _mon_check_memory() {
|
||||
int cnt;
|
||||
TestVpiHandle mem_h, lcl_h, side_h;
|
||||
vpiHandle iter_h; // Icarus does not like auto free of iterator handles
|
||||
s_vpi_value value = {.format = vpiIntVal, .value = {.integer = 0}};
|
||||
s_vpi_value value;
|
||||
value.format = vpiIntVal;
|
||||
value.value.integer = 0;
|
||||
s_vpi_error_info e;
|
||||
|
||||
vpi_printf((PLI_BYTE8*)"Check memory vpi ...\n");
|
||||
mem_h = vpi_handle_by_name((PLI_BYTE8*)TestSimulator::rooted("mem0"), NULL);
|
||||
CHECK_RESULT_NZ(mem_h);
|
||||
@ -169,6 +175,10 @@ int _mon_check_memory() {
|
||||
vpi_get_value(side_h, &value);
|
||||
CHECK_RESULT(value.value.integer, 1);
|
||||
|
||||
// check writing to vpiConstant
|
||||
vpi_put_value(side_h, &value, NULL, vpiNoDelay);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(&e));
|
||||
|
||||
return 0; // Ok
|
||||
}
|
||||
|
||||
|
276
test_regress/t/t_vpi_param.cpp
Normal file
276
test_regress/t/t_vpi_param.cpp
Normal file
@ -0,0 +1,276 @@
|
||||
// -*- 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.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifdef IS_VPI
|
||||
|
||||
#include "vpi_user.h"
|
||||
#include <cstdlib>
|
||||
|
||||
#else
|
||||
|
||||
#include "Vt_vpi_param.h"
|
||||
#include "verilated.h"
|
||||
#include "svdpi.h"
|
||||
|
||||
#include "Vt_vpi_param__Dpi.h"
|
||||
|
||||
#include "verilated_vpi.h"
|
||||
#include "verilated_vcd_c.h"
|
||||
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include "TestSimulator.h"
|
||||
#include "TestVpi.h"
|
||||
|
||||
// __FILE__ is too long
|
||||
#define FILENM "t_vpi_param.cpp"
|
||||
|
||||
#define DEBUG \
|
||||
if (0) printf
|
||||
|
||||
unsigned int main_time = 0;
|
||||
|
||||
//======================================================================
|
||||
|
||||
#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)) { \
|
||||
std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \
|
||||
<< " EXP = " << (exp) << std::endl; \
|
||||
return __LINE__; \
|
||||
}
|
||||
|
||||
#define CHECK_RESULT_HEX(got, exp) \
|
||||
if ((got) != (exp)) { \
|
||||
std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << std::hex \
|
||||
<< ": GOT = " << (got) << " EXP = " << (exp) << std::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 check_param_int(std::string name, PLI_INT32 format, int exp_value, bool verbose) {
|
||||
int vpi_type;
|
||||
TestVpiHandle param_h;
|
||||
s_vpi_value value;
|
||||
value.format = format;
|
||||
value.value.integer = 0;
|
||||
s_vpi_error_info e;
|
||||
const char* p;
|
||||
|
||||
vpi_printf((PLI_BYTE8*)"Check parameter %s vpi ...\n", name.c_str());
|
||||
param_h = vpi_handle_by_name((PLI_BYTE8*)TestSimulator::rooted(name.c_str()), NULL);
|
||||
CHECK_RESULT_NZ(param_h);
|
||||
vpi_type = vpi_get(vpiType, param_h);
|
||||
CHECK_RESULT(vpi_type, vpiParameter);
|
||||
if (verbose) {vpi_printf((PLI_BYTE8*)" vpiType: %s (%d)\n", vpi_get_str(vpiType, param_h), vpi_type); }
|
||||
|
||||
// attributes
|
||||
p = vpi_get_str(vpiName, param_h);
|
||||
CHECK_RESULT_CSTR(p, name.c_str());
|
||||
p = vpi_get_str(vpiFullName, param_h);
|
||||
CHECK_RESULT_CSTR(p, std::string("t." + name).c_str());
|
||||
p = vpi_get_str(vpiType, param_h);
|
||||
CHECK_RESULT_CSTR(p, "vpiParameter");
|
||||
vpi_type = vpi_get(vpiLocalParam, param_h);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(&e));
|
||||
if (verbose && vpi_chk_error(&e)) {vpi_printf((PLI_BYTE8*)" vpi_chk_error: %s\n", e.message); }
|
||||
|
||||
// values
|
||||
if (verbose) {vpi_printf((PLI_BYTE8*)" Try writing value to %s ...\n", name.c_str()); }
|
||||
value.value.integer = exp_value;
|
||||
vpi_put_value(param_h, &value, NULL, vpiNoDelay);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(&e));
|
||||
if (verbose && vpi_chk_error(&e)) {vpi_printf((PLI_BYTE8*)" vpi_chk_error: %s\n", e.message); }
|
||||
|
||||
if (verbose) {vpi_printf((PLI_BYTE8*)" Try reading value of %s ...\n", name.c_str()); }
|
||||
vpi_get_value(param_h, &value);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(&e));
|
||||
if (verbose && vpi_chk_error(&e)) {vpi_printf((PLI_BYTE8*)" vpi_chk_error: %s\n", e.message); }
|
||||
if (verbose) {vpi_printf((PLI_BYTE8*)" value of %s: %d\n", name.c_str(), value.value.integer); }
|
||||
CHECK_RESULT(value.value.integer, exp_value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_param_str(std::string name, PLI_INT32 format, std::string exp_value, bool verbose) {
|
||||
int vpi_type;
|
||||
TestVpiHandle param_h;
|
||||
s_vpi_value value;
|
||||
value.format = format;
|
||||
value.value.integer = 0;
|
||||
s_vpi_error_info e;
|
||||
const char* p;
|
||||
|
||||
vpi_printf((PLI_BYTE8*)"Check parameter %s vpi ...\n", name.c_str());
|
||||
param_h = vpi_handle_by_name((PLI_BYTE8*)TestSimulator::rooted(name.c_str()), NULL);
|
||||
CHECK_RESULT_NZ(param_h);
|
||||
vpi_type = vpi_get(vpiType, param_h);
|
||||
CHECK_RESULT(vpi_type, vpiParameter);
|
||||
if (verbose) {vpi_printf((PLI_BYTE8*)" vpiType: %s (%d)\n", vpi_get_str(vpiType, param_h), vpi_type); }
|
||||
|
||||
// attributes
|
||||
p = vpi_get_str(vpiName, param_h);
|
||||
CHECK_RESULT_CSTR(p, name.c_str());
|
||||
p = vpi_get_str(vpiFullName, param_h);
|
||||
CHECK_RESULT_CSTR(p, std::string("t." + name).c_str());
|
||||
p = vpi_get_str(vpiType, param_h);
|
||||
CHECK_RESULT_CSTR(p, "vpiParameter");
|
||||
vpi_type = vpi_get(vpiLocalParam, param_h);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(&e));
|
||||
if (verbose && vpi_chk_error(&e)) {vpi_printf((PLI_BYTE8*)" vpi_chk_error: %s\n", e.message); }
|
||||
|
||||
// values
|
||||
if (verbose) {vpi_printf((PLI_BYTE8*)" Try writing value to %s ...\n", name.c_str()); }
|
||||
value.value.str = (PLI_BYTE8*) exp_value.c_str();
|
||||
vpi_put_value(param_h, &value, NULL, vpiNoDelay);
|
||||
CHECK_RESULT_NZ(vpi_chk_error(&e));
|
||||
if (verbose && vpi_chk_error(&e)) {vpi_printf((PLI_BYTE8*)" vpi_chk_error: %s\n", e.message); }
|
||||
|
||||
if (verbose) {vpi_printf((PLI_BYTE8*)" Try reading value of %s ...\n", name.c_str()); }
|
||||
vpi_get_value(param_h, &value);
|
||||
CHECK_RESULT_NZ(!vpi_chk_error(&e));
|
||||
if (verbose && vpi_chk_error(&e)) {vpi_printf((PLI_BYTE8*)" vpi_chk_error: %s\n", e.message); }
|
||||
if (verbose) {vpi_printf((PLI_BYTE8*)" value of %s: %s\n", name.c_str(), value.value.str); }
|
||||
CHECK_RESULT_CSTR(value.value.str, exp_value.c_str());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _mon_check_param() {
|
||||
int status = 0;
|
||||
#ifdef TEST_VERBOSE
|
||||
bool verbose = true;
|
||||
#else
|
||||
bool verbose = false;
|
||||
#endif
|
||||
|
||||
status += check_param_int("WIDTH", vpiIntVal, 32, verbose);
|
||||
status += check_param_int("DEPTH", vpiIntVal, 16, verbose);
|
||||
status += check_param_str("PARAM_LONG", vpiHexStrVal, "fedcba9876543210", verbose);
|
||||
status += check_param_str("PARAM_STR", vpiStringVal, "'some string value'", verbose);
|
||||
return status;
|
||||
}
|
||||
|
||||
int mon_check() {
|
||||
// Callback from initial block in monitor
|
||||
if (int status = _mon_check_param()) return status;
|
||||
return 0; // Ok
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
#ifdef IS_VPI
|
||||
|
||||
static int mon_check_vpi() {
|
||||
vpiHandle href = vpi_handle(vpiSysTfCall, 0);
|
||||
s_vpi_value vpi_value;
|
||||
|
||||
vpi_value.format = vpiIntVal;
|
||||
vpi_value.value.integer = mon_check();
|
||||
vpi_put_value(href, &vpi_value, NULL, vpiNoDelay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s_vpi_systf_data vpi_systf_data[] = {{vpiSysFunc, vpiIntFunc, (PLI_BYTE8*)"$mon_check",
|
||||
(PLI_INT32(*)(PLI_BYTE8*))mon_check_vpi, 0, 0, 0},
|
||||
0};
|
||||
|
||||
// cver entry
|
||||
void vpi_compat_bootstrap(void) {
|
||||
p_vpi_systf_data systf_data_p;
|
||||
systf_data_p = &(vpi_systf_data[0]);
|
||||
while (systf_data_p->type != 0)
|
||||
vpi_register_systf(systf_data_p++);
|
||||
}
|
||||
|
||||
// icarus entry
|
||||
void (*vlog_startup_routines[])() = {vpi_compat_bootstrap, 0};
|
||||
|
||||
#else
|
||||
|
||||
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);
|
||||
// we're going to be checking for these errors do don't crash out
|
||||
Verilated::fatalOnVpiError(0);
|
||||
|
||||
VM_PREFIX* topp = new VM_PREFIX(""); // Note null name - we're flattening it out
|
||||
|
||||
#ifdef VERILATOR
|
||||
#ifdef TEST_VERBOSE
|
||||
Verilated::scopesDump();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if VM_TRACE
|
||||
Verilated::traceEverOn(true);
|
||||
VL_PRINTF("Enabling waves...\n");
|
||||
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||
topp->trace(tfp, 99);
|
||||
tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/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
|
||||
}
|
||||
if (!Verilated::gotFinish()) {
|
||||
vl_fatal(FILENM, __LINE__, "main", "%Error: Timeout; never got a $finish");
|
||||
}
|
||||
topp->final();
|
||||
|
||||
#if VM_TRACE
|
||||
if (tfp) tfp->close();
|
||||
#endif
|
||||
|
||||
VL_DO_DANGLING(delete topp, topp);
|
||||
exit(0L);
|
||||
}
|
||||
|
||||
#endif
|
31
test_regress/t/t_vpi_param.pl
Executable file
31
test_regress/t/t_vpi_param.pl
Executable file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env 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.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
skip("Known compiler limitation")
|
||||
if $Self->cxx_version =~ /\(GCC\) 4.4/;
|
||||
|
||||
compile(
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
make_pli => 1,
|
||||
iv_flags2 => ["-g2005-sv -D USE_VPI_NOT_DPI"],
|
||||
v_flags2 => ["+define+USE_VPI_NOT_DPI"],
|
||||
verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --vpi --no-l2name $Self->{t_dir}/t_vpi_param.cpp"],
|
||||
);
|
||||
|
||||
execute(
|
||||
iv_pli => 1,
|
||||
check_finished => 1
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
58
test_regress/t/t_vpi_param.v
Normal file
58
test_regress/t/t_vpi_param.v
Normal file
@ -0,0 +1,58 @@
|
||||
// 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.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
`ifdef USE_VPI_NOT_DPI
|
||||
//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 #(
|
||||
parameter int WIDTH /* verilator public_flat_rd */ = 32
|
||||
) (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
`ifdef VERILATOR
|
||||
`systemc_header
|
||||
extern "C" int mon_check();
|
||||
`verilog
|
||||
`endif
|
||||
|
||||
input clk;
|
||||
|
||||
localparam int DEPTH /* verilator public_flat_rd */ = 16;
|
||||
localparam longint PARAM_LONG /* verilator public_flat_rd */ = 64'hFEDCBA9876543210;
|
||||
localparam string PARAM_STR /* verilator public_flat_rd */ = "'some string value'";
|
||||
|
||||
reg [WIDTH-1:0] mem0 [DEPTH:1] /*verilator public_flat_rw @(posedge clk) */;
|
||||
integer i, status;
|
||||
|
||||
// Test loop
|
||||
initial begin
|
||||
`ifdef VERILATOR
|
||||
status = $c32("mon_check()");
|
||||
`endif
|
||||
`ifdef IVERILOG
|
||||
status = $mon_check();
|
||||
`endif
|
||||
`ifndef USE_VPI_NOT_DPI
|
||||
status = mon_check();
|
||||
`endif
|
||||
|
||||
if (status!=0) begin
|
||||
$write("%%Error: t_vpi_param.cpp:%0d: C Test failed\n", status);
|
||||
$stop;
|
||||
end
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule : t
|
Loading…
Reference in New Issue
Block a user