This commit is contained in:
Jonathan Schröter 2025-12-21 09:39:22 -05:00 committed by GitHub
commit ce8cfd84fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 1538 additions and 0 deletions

View File

@ -116,6 +116,7 @@ set(HEADERS
V3Inline.h
V3Inst.h
V3InstrCount.h
V3InsertHook.h
V3Interface.h
V3LangCode.h
V3LanguageWords.h
@ -289,6 +290,7 @@ set(COMMON_SOURCES
V3Inline.cpp
V3Inst.cpp
V3InstrCount.cpp
V3InsertHook.cpp
V3Interface.cpp
V3LibMap.cpp
V3Life.cpp

View File

@ -286,6 +286,7 @@ RAW_OBJS_PCH_ASTNOMT = \
V3Inline.o \
V3Inst.o \
V3InstrCount.o \
V3InsertHook.o \
V3Interface.o \
V3LibMap.o \
V3Life.o \

View File

@ -1913,6 +1913,7 @@ class AstVar final : public AstNode {
bool m_substConstOnly : 1; // Only substitute if constant
bool m_overridenParam : 1; // Overridden parameter by #(...) or defparam
bool m_trace : 1; // Trace this variable
bool m_isHookInserted : 1; // This variable is instrumented for coverage
bool m_isLatched : 1; // Not assigned in all control paths of combo always
bool m_isForceable : 1; // May be forced/released externally from user C code
bool m_isForcedByCode : 1; // May be forced/released from AstAssignForce/AstRelease
@ -1965,6 +1966,7 @@ class AstVar final : public AstNode {
m_substConstOnly = false;
m_overridenParam = false;
m_trace = false;
m_isHookInserted = false;
m_isLatched = false;
m_isForceable = false;
m_isForcedByCode = false;
@ -2109,6 +2111,8 @@ public:
bool gotNansiType() { return m_gotNansiType; }
void hasStrengthAssignment(bool flag) { m_hasStrengthAssignment = flag; }
bool hasStrengthAssignment() { return m_hasStrengthAssignment; }
void hasHookInserted(bool flag) { m_isHookInserted = flag; }
bool isHookInserted() const { return m_isHookInserted; }
void isDpiOpenArray(bool flag) { m_isDpiOpenArray = flag; }
bool isDpiOpenArray() const VL_MT_SAFE { return m_isDpiOpenArray; }
bool isHideLocal() const { return m_isHideLocal; }

View File

@ -2822,6 +2822,8 @@ void AstVar::dumpJson(std::ostream& str) const {
dumpJsonBoolFunc(str, attrSFormat);
dumpJsonBoolFunc(str, ignorePostWrite);
dumpJsonBoolFunc(str, ignoreSchedWrite);
dumpJsonBoolFunc(str, isHookInserted);
dumpJsonNum(str, "width", width());
dumpJsonGen(str);
}
void AstScope::dump(std::ostream& str) const {

View File

@ -576,6 +576,7 @@ class V3ControlResolver final {
uint8_t m_mode = NONE;
std::unordered_map<string, V3ControlResolverHierWorkerEntry> m_hierWorkers;
FileLine* m_profileFileLine = nullptr;
std::map<string, HookInsertTarget, LengthThenLexiographic> m_hookInsCfg;
V3ControlResolver() = default;
~V3ControlResolver() = default;
@ -640,6 +641,45 @@ public:
return cost;
}
}
// Helper for adding targets to the hook-insertion config map
std::pair<string, string> splitPrefixAndVar(const string& target) {
auto pos = target.rfind('.');
if (pos == string::npos) {
// No prefix, return error
}
string prefix = target.substr(0, pos);
string varTarget = target.substr(pos + 1);
return {prefix, varTarget};
}
// Add the hook-insertion config data to the map to create the initial map (Used in verilog.y)
void addHookInsCfg(FileLine* fl, const string& insFunction, int insID, const string& target) {
// Error MSG if the hook-insertion of the top module is not possible
if ((std::count(target.begin(), target.end(), '.') < 2)) {
v3fatal("In .vlt defined target tries to insert-hook to the highest MODULE, which is "
"not possible!"
" ... Target string: "
<< target);
}
// Implement custom iterator to remove the last part of the target and insert it into the
// vector of the map If the target string is the same as one already in the map, push the
// var to the vector
auto result = splitPrefixAndVar(target);
auto prefix = result.first;
auto varTarget = result.second;
HookInsertEntry entry{insID, insFunction, varTarget, {}, {}};
auto it = m_hookInsCfg.find(prefix);
if (it != m_hookInsCfg.end()) {
it->second.entries.push_back(entry);
} else {
// Create a new entry in the map
HookInsertTarget newTarget;
newTarget.entries.push_back(entry);
m_hookInsCfg[prefix] = std::move(newTarget);
}
}
std::map<string, HookInsertTarget, LengthThenLexiographic>& getHookInsCfg() {
return m_hookInsCfg;
}
};
//######################################################################
@ -698,6 +738,11 @@ void V3Control::addModulePragma(const string& module, VPragmaType pragma) {
V3ControlResolver::s().modules().at(module).addModulePragma(pragma);
}
void V3Control::addHookInsCfg(FileLine* fl, const string& insfunc, int insID,
const string& target) {
V3ControlResolver::s().addHookInsCfg(fl, insfunc, insID, target);
}
void V3Control::addProfileData(FileLine* fl, const string& hierDpi, uint64_t cost) {
V3ControlResolver::s().addProfileData(fl, hierDpi, cost);
}
@ -859,6 +904,9 @@ int V3Control::getHierWorkers(const string& model) {
FileLine* V3Control::getHierWorkersFileLine(const string& model) {
return V3ControlResolver::s().getHierWorkersFileLine(model);
}
std::map<string, HookInsertTarget, LengthThenLexiographic>& V3Control::getHookInsCfg() {
return V3ControlResolver::s().getHookInsCfg();
}
uint64_t V3Control::getProfileData(const string& hierDpi) {
return V3ControlResolver::s().getProfileData(hierDpi);
}

View File

@ -26,6 +26,32 @@
#include "V3Mutex.h"
//######################################################################
struct LengthThenLexiographic final {
// Used to sort strings by length, then lexicographically
bool operator()(const string& a, const string& b) const {
if (a.length() != b.length()) return a.length() < b.length();
return a < b;
}
};
struct HookInsertEntry final {
int insID;
std::string insFunc;
std::string varTarget;
AstVar* origVarps;
AstVar* insVarps;
bool found = false;
};
struct HookInsertTarget final {
std::vector<HookInsertEntry> entries;
AstModule* origModulep;
AstModule* insModulep;
AstModule* topModulep;
AstModule* pointingModulep;
AstCell* cellp;
bool processed = false;
bool done = false;
bool multipleCellps = false;
};
class V3Control final {
public:
@ -44,6 +70,9 @@ public:
static void addIgnoreMatch(V3ErrorCode code, const string& filename, const string& contents,
const string& match);
static void addInline(FileLine* fl, const string& module, const string& ftask, bool on);
static void addHookInsCfg(FileLine* fl, const string& insfunc, int insID,
const string& target);
static std::map<string, HookInsertTarget, LengthThenLexiographic>& getHookInsCfg();
static void addModulePragma(const string& module, VPragmaType pragma);
static void addProfileData(FileLine* fl, const string& hierDpi, uint64_t cost);
static void addProfileData(FileLine* fl, const string& model, const string& key,

1048
src/V3InsertHook.cpp Normal file

File diff suppressed because it is too large Load Diff

33
src/V3InsertHook.h Normal file
View File

@ -0,0 +1,33 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator:
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2003-2025 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
//
//*************************************************************************
#ifndef VERILATOR_V3INSERTHOOK_H_
#define VERILATOR_V3INSERTHOOK_H_
#include "config_build.h"
#include "verilatedos.h"
class AstNetlist;
//=========================================================================
class V3InsertHook final {
public:
static void findTargets(AstNetlist* nodep) VL_MT_DISABLED;
static void insertHooks(AstNetlist* nodep) VL_MT_DISABLED;
};
#endif // Guard

View File

@ -1985,6 +1985,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
addIncDirUser(parseFileArg(optdir, string{valp}));
}).notForRerun();
DECL_OPTION("-insert-hook", OnOff, &m_insertHook);
parser.finalize();
const std::string cwd = V3Os::filenameRealPath(".");

View File

@ -309,6 +309,7 @@ private:
bool m_waiverMultiline = false; // main switch: --waiver-multiline
bool m_xInitialEdge = false; // main switch: --x-initial-edge
bool m_xmlOnly = false; // main switch: --xml-only
bool m_insertHook = false; // main switch: --insert-hook
int m_buildJobs = -1; // main switch: --build-jobs, -j
int m_coverageExprMax = 32; // main switch: --coverage-expr-max
@ -586,6 +587,7 @@ public:
bool xmlOnly() const { return m_xmlOnly; }
bool serializeOnly() const { return m_xmlOnly || m_jsonOnly; }
bool topIfacesSupported() const { return lintOnly() && !hierarchical(); }
bool insertHook() const { return m_insertHook; }
int buildJobs() const VL_MT_SAFE { return m_buildJobs; }
int convergeLimit() const { return m_convergeLimit; }

View File

@ -63,6 +63,7 @@
#include "V3Graph.h"
#include "V3HierBlock.h"
#include "V3Inline.h"
#include "V3InsertHook.h"
#include "V3Inst.h"
#include "V3Interface.h"
#include "V3LibMap.h"
@ -154,6 +155,13 @@ static void process() {
v3Global.vlExit(0);
}
// Hook-insert design with the configurations given in .vlt file
if (v3Global.opt.insertHook()) {
v3Global.dpi(true);
V3InsertHook::findTargets(v3Global.rootp());
V3InsertHook::insertHooks(v3Global.rootp());
}
// Convert parseref's to varrefs, and other directly post parsing fixups
V3LinkParse::linkParse(v3Global.rootp());
// Cross-link signal names

View File

@ -141,6 +141,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"hier_params" { FL; return yVLT_HIER_PARAMS; }
"hier_workers" { FL; return yVLT_HIER_WORKERS; }
"inline" { FL; return yVLT_INLINE; }
"insert_hook" { FL; return yVLT_INSERTHOOK; }
"isolate_assignments" { FL; return yVLT_ISOLATE_ASSIGNMENTS; }
"lint_off" { FL; return yVLT_LINT_OFF; }
"lint_on" { FL; return yVLT_LINT_ON; }
@ -163,11 +164,13 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"tracing_on" { FL; return yVLT_TRACING_ON; }
-?"-block" { FL; return yVLT_D_BLOCK; }
-?"-callback" { FL; return yVLT_D_CALLBACK; }
-?"-contents" { FL; return yVLT_D_CONTENTS; }
-?"-cost" { FL; return yVLT_D_COST; }
-?"-file" { FL; return yVLT_D_FILE; }
-?"-function" { FL; return yVLT_D_FUNCTION; }
-?"-hier-dpi" { FL; return yVLT_D_HIER_DPI; }
-?"-id" { FL; return yVLT_D_ID; }
-?"-levels" { FL; return yVLT_D_LEVELS; }
-?"-lines" { FL; return yVLT_D_LINES; }
-?"-match" { FL; return yVLT_D_MATCH; }
@ -178,6 +181,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
-?"-port" { FL; return yVLT_D_PORT; }
-?"-rule" { FL; return yVLT_D_RULE; }
-?"-scope" { FL; return yVLT_D_SCOPE; }
-?"-target" { FL; return yVLT_D_TARGET; }
-?"-task" { FL; return yVLT_D_TASK; }
-?"-var" { FL; return yVLT_D_VAR; }
-?"-workers" { FL; return yVLT_D_WORKERS; }

View File

@ -250,6 +250,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yVLT_HIER_PARAMS "hier_params"
%token<fl> yVLT_HIER_WORKERS "hier_workers"
%token<fl> yVLT_INLINE "inline"
%token<fl> yVLT_INSERTHOOK "insert_hook"
%token<fl> yVLT_ISOLATE_ASSIGNMENTS "isolate_assignments"
%token<fl> yVLT_LINT_OFF "lint_off"
%token<fl> yVLT_LINT_ON "lint_on"
@ -272,11 +273,13 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yVLT_TRACING_ON "tracing_on"
%token<fl> yVLT_D_BLOCK "--block"
%token<fl> yVLT_D_CALLBACK "--callback"
%token<fl> yVLT_D_CONTENTS "--contents"
%token<fl> yVLT_D_COST "--cost"
%token<fl> yVLT_D_FILE "--file"
%token<fl> yVLT_D_FUNCTION "--function"
%token<fl> yVLT_D_HIER_DPI "--hier-dpi"
%token<fl> yVLT_D_ID "--id"
%token<fl> yVLT_D_LEVELS "--levels"
%token<fl> yVLT_D_LINES "--lines"
%token<fl> yVLT_D_MATCH "--match"
@ -287,6 +290,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yVLT_D_PORT "--port"
%token<fl> yVLT_D_RULE "--rule"
%token<fl> yVLT_D_SCOPE "--scope"
%token<fl> yVLT_D_TARGET "--target"
%token<fl> yVLT_D_TASK "--task"
%token<fl> yVLT_D_VAR "--var"
%token<fl> yVLT_D_WORKERS "--workers"
@ -8095,6 +8099,8 @@ vltItem:
{ /* Historical, now has no effect */ }
| vltInlineFront vltDModuleE vltDFTaskE
{ V3Control::addInline($<fl>1, *$2, *$3, $1); }
| yVLT_INSERTHOOK yVLT_D_CALLBACK yaSTRING yVLT_D_ID yaINTNUM yVLT_D_TARGET yaSTRING
{ V3Control::addHookInsCfg($<fl>1, *$3, $5->toSInt(), *$7); }
| yVLT_COVERAGE_BLOCK_OFF vltDFile
{ V3Control::addCoverageBlockOff(*$2, 0); }
| yVLT_COVERAGE_BLOCK_OFF vltDFile yVLT_D_LINES yaINTNUM

View File

@ -0,0 +1,51 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
#include <verilated.h>
#include <verilated_vcd_c.h>
#include <iostream>
#include VM_PREFIX_INCLUDE
vluint64_t main_time = 0;
double sc_time_stamp() { return main_time; }
int main(int argc, char** argv) {
Verilated::debug(0);
Verilated::commandArgs(argc, argv);
const std::unique_ptr<VM_PREFIX> top{new VM_PREFIX{"TOP"}};
while (main_time <= 100) {
if (main_time < 20) {
top->in1a = 5;
top->in2a = 10;
top->in1b = 20;
top->in2b = 30;
} else if (main_time >= 20 && main_time < 63) {
top->in1a = 0;
top->in2a = 5;
top->in1b = 15;
top->in2b = 25;
} else if (main_time > 78) {
top->in1a = 10;
top->in2a = 15;
top->in1b = 25;
top->in2b = 35;
}
top->eval();
std::cout << "$time: " << main_time << " | "
<< "Output outa: " << static_cast<int>(top->outa) << " | "
<< "Output outb: " << static_cast<int>(top->outb) << std::endl;
++main_time;
}
top->final();
printf("*-* All Finished *-*\n");
return 0;
}

View File

@ -0,0 +1,102 @@
$time: 0 | Output outa: 15 | Output outb: 1
$time: 1 | Output outa: 15 | Output outb: 1
$time: 2 | Output outa: 15 | Output outb: 1
$time: 3 | Output outa: 15 | Output outb: 50
$time: 4 | Output outa: 15 | Output outb: 50
$time: 5 | Output outa: 15 | Output outb: 50
$time: 6 | Output outa: 15 | Output outb: 50
$time: 7 | Output outa: 15 | Output outb: 50
$time: 8 | Output outa: 15 | Output outb: 50
$time: 9 | Output outa: 15 | Output outb: 50
$time: 10 | Output outa: 0 | Output outb: 50
$time: 11 | Output outa: 0 | Output outb: 50
$time: 12 | Output outa: 0 | Output outb: 50
$time: 13 | Output outa: 0 | Output outb: 50
$time: 14 | Output outa: 0 | Output outb: 50
$time: 15 | Output outa: 0 | Output outb: 50
$time: 16 | Output outa: 0 | Output outb: 50
$time: 17 | Output outa: 0 | Output outb: 50
$time: 18 | Output outa: 0 | Output outb: 50
$time: 19 | Output outa: 0 | Output outb: 50
$time: 20 | Output outa: 5 | Output outb: 40
$time: 21 | Output outa: 5 | Output outb: 40
$time: 22 | Output outa: 5 | Output outb: 40
$time: 23 | Output outa: 5 | Output outb: 40
$time: 24 | Output outa: 5 | Output outb: 40
$time: 25 | Output outa: 5 | Output outb: 40
$time: 26 | Output outa: 5 | Output outb: 40
$time: 27 | Output outa: 5 | Output outb: 40
$time: 28 | Output outa: 5 | Output outb: 40
$time: 29 | Output outa: 5 | Output outb: 40
$time: 30 | Output outa: 5 | Output outb: 40
$time: 31 | Output outa: 5 | Output outb: 40
$time: 32 | Output outa: 5 | Output outb: 1
$time: 33 | Output outa: 5 | Output outb: 1
$time: 34 | Output outa: 5 | Output outb: 1
$time: 35 | Output outa: 5 | Output outb: 1
$time: 36 | Output outa: 5 | Output outb: 1
$time: 37 | Output outa: 5 | Output outb: 1
$time: 38 | Output outa: 5 | Output outb: 1
$time: 39 | Output outa: 5 | Output outb: 1
$time: 40 | Output outa: 5 | Output outb: 1
$time: 41 | Output outa: 5 | Output outb: 1
$time: 42 | Output outa: 5 | Output outb: 1
$time: 43 | Output outa: 5 | Output outb: 1
$time: 44 | Output outa: 5 | Output outb: 1
$time: 45 | Output outa: 5 | Output outb: 1
$time: 46 | Output outa: 5 | Output outb: 1
$time: 47 | Output outa: 5 | Output outb: 1
$time: 48 | Output outa: 5 | Output outb: 1
$time: 49 | Output outa: 5 | Output outb: 1
$time: 50 | Output outa: 5 | Output outb: 1
$time: 51 | Output outa: 5 | Output outb: 1
$time: 52 | Output outa: 5 | Output outb: 1
$time: 53 | Output outa: 5 | Output outb: 1
$time: 54 | Output outa: 5 | Output outb: 1
$time: 55 | Output outa: 5 | Output outb: 1
$time: 56 | Output outa: 5 | Output outb: 1
$time: 57 | Output outa: 5 | Output outb: 1
$time: 58 | Output outa: 5 | Output outb: 1
$time: 59 | Output outa: 5 | Output outb: 1
$time: 60 | Output outa: 5 | Output outb: 1
$time: 61 | Output outa: 5 | Output outb: 1
$time: 62 | Output outa: 5 | Output outb: 1
$time: 63 | Output outa: 5 | Output outb: 1
$time: 64 | Output outa: 5 | Output outb: 1
$time: 65 | Output outa: 5 | Output outb: 1
$time: 66 | Output outa: 5 | Output outb: 1
$time: 67 | Output outa: 5 | Output outb: 1
$time: 68 | Output outa: 5 | Output outb: 1
$time: 69 | Output outa: 5 | Output outb: 40
$time: 70 | Output outa: 5 | Output outb: 40
$time: 71 | Output outa: 5 | Output outb: 40
$time: 72 | Output outa: 5 | Output outb: 40
$time: 73 | Output outa: 5 | Output outb: 40
$time: 74 | Output outa: 5 | Output outb: 40
$time: 75 | Output outa: 5 | Output outb: 40
$time: 76 | Output outa: 5 | Output outb: 40
$time: 77 | Output outa: 5 | Output outb: 40
$time: 78 | Output outa: 5 | Output outb: 40
$time: 79 | Output outa: 25 | Output outb: 60
$time: 80 | Output outa: 25 | Output outb: 60
$time: 81 | Output outa: 25 | Output outb: 60
$time: 82 | Output outa: 25 | Output outb: 60
$time: 83 | Output outa: 25 | Output outb: 60
$time: 84 | Output outa: 25 | Output outb: 60
$time: 85 | Output outa: 0 | Output outb: 60
$time: 86 | Output outa: 0 | Output outb: 60
$time: 87 | Output outa: 0 | Output outb: 60
$time: 88 | Output outa: 0 | Output outb: 60
$time: 89 | Output outa: 0 | Output outb: 60
$time: 90 | Output outa: 0 | Output outb: 60
$time: 91 | Output outa: 0 | Output outb: 60
$time: 92 | Output outa: 0 | Output outb: 60
$time: 93 | Output outa: 0 | Output outb: 60
$time: 94 | Output outa: 0 | Output outb: 60
$time: 95 | Output outa: 0 | Output outb: 60
$time: 96 | Output outa: 0 | Output outb: 60
$time: 97 | Output outa: 0 | Output outb: 60
$time: 98 | Output outa: 0 | Output outb: 60
$time: 99 | Output outa: 0 | Output outb: 60
$time: 100 | Output outa: 0 | Output outb: 60
*-* All Finished *-*

25
test_regress/t/t_instrument.py Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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
import vltest_bootstrap
test.scenarios('simulator')
test.top_filename = "t/t_instrument.v"
sim_filename = "t/" + test.name + ".cpp"
dpi_filename = "t/t_instrumentDPI.cpp"
vlt_filename = "t/" + test.name + ".vlt"
test.compile(
make_top_shell=False,
make_main=False,
v_flags2=["--trace --timing --exe --instrument", sim_filename, vlt_filename, dpi_filename])
test.execute(expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,38 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2012 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module top_module(
input reg [7:0] in1a,
input reg [7:0] in2a,
input reg [7:0] in1b,
input reg [7:0] in2b,
output logic [7:0] outa,
output logic [7:0] outb
);
module_a a1 (.in1(in1a), .in2(in2a), .out(outa));
module_a a2 (.in1(in1b), .in2(in2b), .out(outb));
endmodule
module module_a(
input logic [7:0] in1,
input logic [7:0] in2,
output logic [7:0] out
);
module_b b1 (.in1(in1), .in2(in2), .out(out));
endmodule
module module_b (
input logic [7:0] in1,
input logic [7:0] in2,
output logic [7:0] out
);
reg [127:0] bigRegister;
always_comb begin
out = in1 + in2;
end
endmodule

View File

@ -0,0 +1,11 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
`verilator_config
instrument -callback "instrument_var" -id 0 -target "top_module.a1.b1.out"
instrument -callback "instrument_var" -id 1 -target "top_module.a2.out"

View File

@ -0,0 +1,30 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
#include <verilated.h>
#include <svdpi.h>
extern "C" int instrument_var(int id, int trigger, const svLogic* x) {
switch (id) {
case 0:
if ((VL_TIME_Q() >= 10 && VL_TIME_Q() < 20) || VL_TIME_Q() >= 85) {
return 0;
} else {
return *x;
}
//return 0;
case 1:
if ((VL_TIME_Q() < 3) || (VL_TIME_Q() >= 32 && VL_TIME_Q() < 69)) {
return 1;
} else {
return *x;
}
default: return *x;
}
}

View File

@ -0,0 +1,2 @@
%Error: In .vlt defined target tries to instrument the highest MODULE, is not possible! ... Target string: top_module.outa
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.

View File

@ -0,0 +1,26 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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
import vltest_bootstrap
test.scenarios('simulator')
test.top_filename = "t/t_instrument.v"
sim_filename = "t/t_instrument.cpp"
dpi_filename = "t/t_instrumentDPI.cpp"
vlt_filename = "t/" + test.name + ".vlt"
test.compile(
fails=True,
make_top_shell=False,
make_main=False,
v_flags2=["--trace --timing --exe --instrument", sim_filename, vlt_filename, dpi_filename],
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,9 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
`verilator_config
instrument -callback "instrument_var" -id 0 -target "top_module.outa"

View File

@ -0,0 +1,12 @@
%Error: Verilator-configfile': could not find initial 'module' in 'module.instance.__' ... Target: 'top.a1.b1'
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Verilator-configfile: target variable 'bigRegister' in 'top_module.a1.b1' must be a supported type!
%Error: Verilator-configfile': could not find defined 'var' in 'topModule.instance.var' ... Target string: 'top_module.a1.b1.clk'
%Error: Verilator-configfile': could not find '.var' in '__.module.var' ... Target: 'top_module.a1.b1'
%Error: Verilator-configfile: could not find 'instance' in '__.instance.__' ... Target string: 'top_module.a1.b3'
%Error: Verilator-configfile': could not find initial 'instance' in 'topModule.instance.__' ... Target string: 'top_module.a3.b1'
%Error: Verilator-configfile: Incomplete instrumentation configuration for target 'top.a1.b1'. Please check previous Errors from V3Instrument:findTargets and ensure all necessary components are correct defined.
%Error: Verilator-configfile: Incomplete instrumentation configuration for target 'top_module.a1.b1'. Please check previous Errors from V3Instrument:findTargets and ensure all necessary components are correct defined.
%Error: Verilator-configfile: Incomplete instrumentation configuration for target 'top_module.a1.b3'. Please check previous Errors from V3Instrument:findTargets and ensure all necessary components are correct defined.
%Error: Verilator-configfile: Incomplete instrumentation configuration for target 'top_module.a3.b1'. Please check previous Errors from V3Instrument:findTargets and ensure all necessary components are correct defined.
%Error: Exiting due to

View File

@ -0,0 +1,26 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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
import vltest_bootstrap
test.scenarios('simulator')
test.top_filename = "t/t_instrument.v"
sim_filename = "t/t_instrument.cpp"
dpi_filename = "t/t_instrumentDPI.cpp"
vlt_filename = "t/" + test.name + ".vlt"
test.compile(
fails=True,
make_top_shell=False,
make_main=False,
v_flags2=["--trace --timing --exe --instrument", sim_filename, vlt_filename, dpi_filename],
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,17 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
`verilator_config
instrument -callback "instrument_var" -id 0 -target "top.a1.b1.out"
instrument -callback "instrument_var" -id 0 -target "top_module.a3.b1.out"
instrument -callback "instrument_var" -id 0 -target "top_module.a1.b3.out"
instrument -callback "instrument_var" -id 0 -target "top_module.a1.b1.clk"
instrument -callback "instrument_var" -id 0 -target "top_module.a1.b1.bigRegister"