style: Revised comments

This commit is contained in:
Jonathan Schröter 2025-12-03 13:19:16 +01:00
parent 33568f33fa
commit 84c51206bc
1 changed files with 70 additions and 235 deletions

View File

@ -39,31 +39,29 @@
VL_DEFINE_DEBUG_FUNCTIONS;
//##################################################################################
// Hook-insertion class finder
// Collect nodes and data from the AST for hook-insertion
class HookInsTargetFndr final : public VNVisitor {
AstNetlist* m_netlist
= nullptr; // Enable traversing from the beginning if the visitor is to deep
AstNodeModule* m_cellModp = nullptr; // Stores the modulep of a Cell node
AstModule* m_modp = nullptr; // Stores the current modulep the visitor is looking at
AstModule* m_targetModp = nullptr; // Stores the targeted modulep
bool m_error = false; // Displays if there was already an error message earlier
bool m_foundCellp = false; // If the visitor found the relevant instance
bool m_foundModp = false; // If the visitor found the relevant model
bool m_foundVarp = false; // If the visitor found the relevant variable
= nullptr; // Used for traversing AST from the beginning if the visitor is to deep
AstNodeModule* m_cellModp = nullptr;
AstModule* m_modp = nullptr;
AstModule* m_targetModp = nullptr;
bool m_error = false;
bool m_foundCellp = false;
bool m_foundModp = false;
bool m_foundVarp = false;
bool m_initModp = true; // If the visitor is in the first module node of the netlist
size_t m_insIdx = 0;
string m_currHier; // Stores the current hierarchy of the visited nodes (Module, Cell, Var)
string m_target; // Stores the currently visited target string from the config map
string m_currHier;
string m_target;
// METHODS
//----------------------------------------------------------------------------------
AstModule* findModp(AstNetlist* netlist, AstModule* modp) {
for (AstNode* n = netlist->op1p(); n; n = n->nextp()) {
if (VN_IS(n, Module) && VN_CAST(n, Module) == modp) { return VN_CAST(n, Module); }
}
return nullptr;
}
// Helper function to compare the target string starts with the given prefix
bool cmpPrefix(const string& prefix, const string& target) {
if (target.compare(0, prefix.size(), prefix) == 0
&& (target.size() == prefix.size() || target[prefix.size()] == '.')) {
@ -71,21 +69,18 @@ class HookInsTargetFndr final : public VNVisitor {
}
return false;
}
// Helper function to check if a parameter was already added to the tree previously
bool hasParam(AstModule* modp) {
for (AstNode* n = modp->op2p(); n; n = n->nextp()) {
if (n->name() == "HOOKINS") { return true; }
}
return false;
}
// Helper function to check if a pin was already added to the tree previously
bool hasPin(AstCell* cellp) {
for (AstNode* n = cellp->paramsp(); n; n = n->nextp()) {
if (n->name() == "HOOKINS") { return true; }
}
return false;
}
// Check if the multipleCellps flag is set for the given target
bool hasMultiple(const std::string& target) {
auto& insCfg = V3Control::getHookInsCfg();
auto it = insCfg.find(target);
@ -112,18 +107,17 @@ class HookInsTargetFndr final : public VNVisitor {
bool targetHasPointingMod(const string& pointingModuleName, const string& target) {
return pointingModuleName == reduce2Depth(split(target), KeyDepth::RelevantModule);
}
// Check if the given prefix matches the beginning of the current target string
bool targetHasPrefix(const string& prefix, const string& target) {
return cmpPrefix(prefix, target);
}
// Helper Function to split a string by '.' and return a vector of tokens
// Split given string by '.' and return a vector of tokens
std::vector<std::string> split(const std::string& str) {
static const std::regex dot_regex("\\.");
std::sregex_token_iterator iter(str.begin(), str.end(), dot_regex, -1);
std::sregex_token_iterator end;
return std::vector<std::string>(iter, end);
}
// Helper function to reduce a given key to a certain hierarchy level.
// Reduce given key to a certain hierarchy level.
enum class KeyDepth { TopModule = 0, RelevantModule = 1, Instance = 2, FullKey = 3 };
string reduce2Depth(std::vector<std::string> keyTokens, KeyDepth hierarchyLevel) {
std::string reducedKey = keyTokens[0];
@ -135,7 +129,6 @@ class HookInsTargetFndr final : public VNVisitor {
return reducedKey;
}
}
// Helper function for adding the parameters into the tree
void addParam(AstModule* modp) {
AstVar* paramp = new AstVar{modp->fileline(), VVarType::GPARAM, "HOOKINS",
VFlagChildDType{}, nullptr};
@ -144,7 +137,6 @@ class HookInsTargetFndr final : public VNVisitor {
paramp->ansi(true);
modp->addStmtsp(paramp);
}
// Helper function for adding the parameters into the tree
void addPin(AstCell* cellp, bool isInsPath, const string& target) {
int pinnum = 0;
if (isInsPath) {
@ -162,13 +154,11 @@ class HookInsTargetFndr final : public VNVisitor {
cellp->addParamsp(pinp);
}
}
// Edit the hook-insertion data for the cell in the map
void editInsData(AstCell* cellp, const string& target) {
auto& insCfg = V3Control::getHookInsCfg();
auto it = insCfg.find(target);
if (it != insCfg.end()) { it->second.cellp = cellp; }
}
// Edit the hook-insertion data for the pointing module in the map
void editInsData(AstModule* modulep, const string& target) {
auto& insCfg = V3Control::getHookInsCfg();
auto it = insCfg.find(target);
@ -187,13 +177,11 @@ class HookInsTargetFndr final : public VNVisitor {
setMultiple(m_target);
}
}
// Insert the cell node that is/will pointing/point to the targeted module
void setCell(AstCell* cellp, const string& target) {
auto& insCfg = V3Control::getHookInsCfg();
auto it = insCfg.find(target);
if (it != insCfg.end()) { it->second.cellp = cellp; }
}
// Insert the original and hook-inserted module nodes to the map
void setInsModule(AstModule* origModulep, AstModule* insModulep, const string& target) {
auto& insCfg = V3Control::getHookInsCfg();
auto it = insCfg.find(target);
@ -202,32 +190,26 @@ class HookInsTargetFndr final : public VNVisitor {
it->second.insModulep = insModulep;
}
}
// Set the multipleCellps flag
void setMultiple(const string& target) {
auto& insCfg = V3Control::getHookInsCfg();
auto it = insCfg.find(target);
if (it != insCfg.end()) { it->second.multipleCellps = true; }
}
// Insert the module node that includes the cell pointing to the targeted module
// to the map
void setPointingMod(AstModule* modulep, const string& target) {
auto& insCfg = V3Control::getHookInsCfg();
auto it = insCfg.find(target);
if (it != insCfg.end()) { it->second.pointingModulep = modulep; }
}
// Set the processed flag
void setProcessed(const string& target) {
auto& insCfg = V3Control::getHookInsCfg();
auto it = insCfg.find(target);
if (it != insCfg.end()) { it->second.processed = true; }
}
// Insert the top module node of the netlist to the map
void setTopMod(AstModule* modulep, const string& target) {
auto& insCfg = V3Control::getHookInsCfg();
auto it = insCfg.find(target);
if (it != insCfg.end()) { it->second.topModulep = modulep; }
}
// Insert the original and hook-inserted variable nodes to the map
void setVar(AstVar* varp, AstVar* insVarp, const string& target) {
auto& insCfg = V3Control::getHookInsCfg();
auto it = insCfg.find(target);
@ -244,33 +226,10 @@ class HookInsTargetFndr final : public VNVisitor {
}
// VISITORS
//----------------------------------------------------------------------------------
//ASTMODULE VISITOR FUNCTION:
//Iterates over the existing module nodes in the netlist.
//For the first module in the netlist the node name is checked if it is at the first position
//in the target string provided by the configuration file. If not an error is thown, otherwise
//the modules is checked for an already existing HOOKINS parameter. If there is no
//HOOKINS parameter present we add it to the module. This parameter is used to control the
//hook-insertion of the target. The module is then added to the map of the hook-insertion
//configs as the top module. Additionally the hierarchy the function viewed is currently add is
//initialized with the module name. This module hierarchy is used to identify the correct
//target path in the netlist. The function iterates over the children of the module, with the
//Cells and Vars beeing the relevant targets.
//After the iteration of the children the m_modp variable needs to be set by the Cell visitor
//to continue or there needs no suitable cell to be found. (See CELL VISITOR FUNCTION & VAR
//VISITOR FUNCTION) Since the module from the m_modp can appear earlier in the tree the
//fundModp function is used to iterate over the netlift from the beginning to find the module.
//The module node displayed by the m_modp variable is then checked if this is the module
//containing the target variable (relevant module) or if it the module containing the cell
//pointing to the relevant module (pointing module). If the module node suits one of these two
//conditions the module nodes are added to the hook-insertion configs map. Independetly from
//these conditions the HOOKINS parameter is added to the module nodes in the target path.
//This parameter is used to control the hook-insertion of the target.
void visit(AstModule* nodep) override {
if (m_initModp) {
if (targetHasTop(nodep->name(), m_target)) {
// Add decision parameters to the module if not present
m_foundModp = true;
m_modp = nodep;
m_currHier = nodep->name();
@ -280,8 +239,9 @@ class HookInsTargetFndr final : public VNVisitor {
m_foundCellp = true; // Set to true since there is no Instance that the cell
// visitor could find
}
// Store top module pointer for later
setTopMod(nodep, m_target);
iterateChildren(nodep);
iterateChildren(nodep); // Continue to Cell/Var nodes
} else if (!m_foundModp && nodep->name() == "@CONST-POOL@") {
v3error("Verilator-configfile': could not find initial 'module' in "
"'module.instance.__'"
@ -290,7 +250,7 @@ class HookInsTargetFndr final : public VNVisitor {
m_initModp = false;
m_error = true;
}
} else if (m_cellModp != nullptr
} else if (m_cellModp != nullptr // Find module pointed to by the cell from cell visitor
&& (nodep = findModp(m_netlist, VN_CAST(m_cellModp, Module))) != nullptr) {
if (targetHasFullName(m_currHier, m_target)) {
AstModule* insModp = nullptr;
@ -319,7 +279,7 @@ class HookInsTargetFndr final : public VNVisitor {
insModp->name(nodep->name() + "__hookIns__" + std::to_string(m_insIdx));
if (hasMultiple(m_target)) { insModp->inLibrary(true); }
setInsModule(nodep, insModp, m_target);
iterateChildren(nodep);
iterateChildren(nodep); // Continue to var node
} else if (targetHasPointingMod(m_currHier, m_target)) {
m_foundModp = true;
m_foundCellp = false;
@ -327,14 +287,14 @@ class HookInsTargetFndr final : public VNVisitor {
m_cellModp = nullptr;
if (!hasParam(nodep)) { addParam(nodep); }
setPointingMod(nodep, m_target);
iterateChildren(nodep);
iterateChildren(nodep); // Continue to cell
} else if (targetHasPrefix(m_currHier, m_target)) {
m_foundModp = true;
m_foundCellp = false;
m_modp = nodep;
m_cellModp = nullptr;
if (!hasParam(nodep)) { addParam(nodep); }
iterateChildren(nodep);
iterateChildren(nodep); // Continue to cell
}
} else if (!m_error && !m_foundCellp) {
v3error("Verilator-configfile: could not find 'instance' in "
@ -347,24 +307,6 @@ class HookInsTargetFndr final : public VNVisitor {
}
}
//ASTCELL VISITOR FUNCTION:
//This cell visitor function is called if the module visitor function found a module that
//matches the target string from the config. The first function call should be when visiting
//the initial module in the netlist. When a cell is found that matches the target string and is
//not marked as found, the current hierarchy is updated and the cell marked as found.
//Additionally, if this is the cell in the initial module, the initial module flag is set to
//false. The in the current module existing cells are checked if there are multiple cells
//linking to the next module in the target string. After that the m_modp is updated to match
//the cell's module pointer, which is needed for the next call of the module visitor. Next the
//pin for the HOOKINS parameter is added to the cell. This parameter is added either as a
//constant or as a reference, depending on the traversal stage. If there are multiple cells
//linking to the next module in the target string, the multiple flag is set in the
//hook-insertion config map. For the inistial module the found cell is then added to the
//hook-insertion configuration map with the current hierarchy as the target path. Otherwise
//the cell is added to the hook-insertion configuration map, when the current hierarchy with
//the cell name fully matches a target path, with the last two entrances removed (Module, Var).
//This function ensures that the correct cells in the design hierarchy are hook-inserted and
//tracked, supporting both unique and repeated module instances.
void visit(AstCell* nodep) override {
if (m_initModp) {
if (targetHasFullName(m_currHier + "." + nodep->name(), m_target)) {
@ -408,19 +350,14 @@ class HookInsTargetFndr final : public VNVisitor {
}
}
//ASTVAR VISITOR FUNCTION:
//The var visitor function is used to find the variable that matches the target string from the
//config. This is only done if the Cell visitor does not find a matching cell in the current
//module of the target hierarchy. Since we therefore know that we will not traverse any further
//in the hierarchy of the model, we can check for this variable. If a variable is found, with
//its name added to the current hierarchy, that siuts the target string, an edited version and
//the original version are added to the hook-insertion config map.
void visit(AstVar* nodep) override {
if (m_targetModp != nullptr) {
const HookInsertTarget& target = V3Control::getHookInsCfg().find(m_currHier)->second;
for (const auto& entry : target.entries) {
// Go over all var targets if in same module
if (nodep->name() == entry.varTarget) {
int width = 0;
// Check for if target var is supported
AstBasicDType* basicp = nodep->basicp();
bool literal = basicp->isLiteralType();
bool implicit = basicp->implicit();
@ -469,12 +406,14 @@ public:
explicit HookInsTargetFndr(AstNetlist* nodep) {
const auto& insCfg = V3Control::getHookInsCfg();
for (const auto& pair : insCfg) {
// Set initial flag values
m_netlist = nodep;
m_target = pair.first;
m_initModp = true;
m_currHier = "";
iterate(nodep);
setProcessed(m_target);
// Reset flags
m_foundModp = false;
m_foundCellp = false;
m_foundVarp = false;
@ -488,42 +427,35 @@ public:
};
//##################################################################################
// Hook-insertion class functions
// Do the hook-insertion transformations
class HookInsFunc final : public VNVisitor {
bool m_assignw = false; // Flag if a assignw exists in the netlist
bool m_assignw = false;
bool m_assignNode = false; // Set to true to indicate that the visitor is in an assign
bool m_addedport = false; // Flag if a port was already added
bool m_addedTask = false; // Flag if a task was already added
bool m_addedFunc = false; // Flag if a function was already added
bool m_interface = false; // Flag if the ParseRef node is part of an interface
int m_pinnum = 0; // Pinnumber for the new Port nodes
string m_targetKey; // Stores the target string from the hook-insertion config
bool m_addedport = false;
bool m_addedTask = false;
bool m_addedFunc = false;
int m_pinnum = 0;
string m_targetKey;
string m_task_name;
size_t m_targetIndex = 0; // Index of the target variable in the hook-insertion config
AstAlways* m_alwaysp = nullptr; // Stores the added always node
AstAssignW* m_assignwp = nullptr; // Stores the added assignw node
AstGenBlock* m_insGenBlock
= nullptr; // Store the GenBlock node for hook-insertion hierarchy check
AstTask* m_taskp = nullptr; // // Stores the created task node
AstFunc* m_funcp = nullptr; // Stores the created function node
AstFuncRef* m_funcrefp = nullptr; // Stores the created funcref node
AstLoop* m_loopp = nullptr; // Stores the created loop pointer
AstTaskRef* m_taskrefp = nullptr; // Stores the created taskref node
AstModule* m_current_module = nullptr; // Stores the currenty visited module
size_t m_targetIndex = 0;
AstAlways* m_alwaysp = nullptr;
AstAssignW* m_assignwp = nullptr;
AstGenBlock* m_insGenBlock = nullptr;
AstTask* m_taskp = nullptr;
AstFunc* m_funcp = nullptr;
AstFuncRef* m_funcrefp = nullptr;
AstLoop* m_loopp = nullptr;
AstTaskRef* m_taskrefp = nullptr;
AstModule* m_current_module = nullptr;
AstModule* m_current_module_cell_check
= nullptr; // Stores the module node(used by cell visitor)
AstVar* m_tmp_varp = nullptr; // Stores the hook-inserted variable node
AstVar* m_orig_varp = nullptr; // Stores the original variable node
AstVar* m_orig_varp_insMod
= nullptr; // Stores the original variable node in hook-inserted module node
AstVar* m_dpi_trigger
= nullptr; // Stores the variable noded for the dpi-trigger, which ensures the changing of
// a signal and the execution of the DPI function
AstPort* m_orig_portp = nullptr; // Stores the original port node
AstVar* m_tmp_varp = nullptr;
AstVar* m_orig_varp = nullptr;
AstVar* m_orig_varp_insMod = nullptr;
AstVar* m_dpi_trigger = nullptr; // Trigger ensuring changing execution of the DPI function
AstPort* m_orig_portp = nullptr;
// METHODS
//----------------------------------------------------------------------------------
// Find the relevant hook-insertion config in the map corresponding to the given key
const HookInsertTarget* getInsCfg(const std::string& key) {
const auto& map = V3Control::getHookInsCfg();
auto insCfg = map.find(key);
@ -533,23 +465,18 @@ class HookInsFunc final : public VNVisitor {
return nullptr;
}
}
// Get the Cell nodep pointer from the configuration map for the given key
AstCell* getMapEntryCell(const std::string& key) {
if (auto cfg = getInsCfg(key)) { return cfg->cellp; }
return nullptr;
}
// Get the hook-inserted Module node pointer from the configuration map for the given key
AstModule* getMapEntryInsModule(const std::string& key) {
if (auto cfg = getInsCfg(key)) { return cfg->insModulep; }
return nullptr;
}
// Get the Module node pointer pointing to the hook-inserted/original module from the
// configuration map for the given key
AstModule* getMapEntryPointingModule(const std::string& key) {
if (auto cfg = getInsCfg(key)) { return cfg->pointingModulep; }
return nullptr;
}
// Get the hook-inserted variable node pointer from the configuration map for the given key
AstVar* getMapEntryInsVar(const std::string& key, size_t index) {
if (auto cfg = getInsCfg(key)) {
const auto& entries = cfg->entries;
@ -557,7 +484,6 @@ class HookInsFunc final : public VNVisitor {
}
return nullptr;
}
// Get the original variable node pointer from the configuration map for the given key
AstVar* getMapEntryVar(const std::string& key, size_t index) {
if (auto cfg = getInsCfg(key)) {
const auto& entries = cfg->entries;
@ -570,8 +496,6 @@ class HookInsFunc final : public VNVisitor {
const auto insCfg = map.find(key);
return insCfg != map.end();
}
// Check if the given module node pointer is an hook-inserted module entry in the configuration
// map for the given key
bool isInsModEntry(AstModule* nodep, const std::string& key) {
const auto& map = V3Control::getHookInsCfg();
const auto insCfg = map.find(key);
@ -581,7 +505,6 @@ class HookInsFunc final : public VNVisitor {
return false;
}
}
// Check if the given module node pointer is the top module entry in the configuration map
bool isTopModEntry(AstModule* nodep) {
auto& insCfg = V3Control::getHookInsCfg();
for (const auto& pair : insCfg) {
@ -589,7 +512,6 @@ class HookInsFunc final : public VNVisitor {
}
return false;
}
// Check if the given module node pointer is the pointing module entry in the configuration map
bool isPointingModEntry(AstModule* nodep) {
auto& insCfg = V3Control::getHookInsCfg();
for (const auto& pair : insCfg) {
@ -597,7 +519,6 @@ class HookInsFunc final : public VNVisitor {
}
return false;
}
// Check if the given module node pointer has already been hook-inserted/done flag has been set
bool isDone(AstModule* nodep) {
auto& insCfg = V3Control::getHookInsCfg();
for (const auto& pair : insCfg) {
@ -605,7 +526,6 @@ class HookInsFunc final : public VNVisitor {
}
return true;
}
// Check if the multipleCellps flag is set for the given key in the configuration map
bool hasMultiple(const std::string& key) {
const auto& map = V3Control::getHookInsCfg();
const auto insCfg = map.find(key);
@ -615,21 +535,18 @@ class HookInsFunc final : public VNVisitor {
return false;
}
}
// Check if the module and instances defined in the target string were found in
// the previous step
// Check if issues happend during collection in HookInsTargetFndr
bool hasNullptr(const std::pair<const string, HookInsertTarget>& pair) {
bool moduleNullptr = pair.second.origModulep == nullptr;
bool cellNullptr = pair.second.cellp == nullptr;
return moduleNullptr || cellNullptr;
}
// Check if the, in the target string, defined variable was found in the previous step
bool isFound(const std::pair<const string, HookInsertTarget>& pair) {
for (auto& entry : pair.second.entries) {
if (entry.found == false) { return entry.found; }
}
return true;
}
// Get the fault case for the given key in the configuration map
int getMapEntryFaultCase(const std::string& key, size_t index) {
const auto& map = V3Control::getHookInsCfg();
const auto insCfg = map.find(key);
@ -641,8 +558,6 @@ class HookInsFunc final : public VNVisitor {
return -1;
}
}
// Get the callback function name from the hook-insertion for the given key in the
// configuration map
string getMapEntryFunction(const std::string& key, size_t index) {
const auto& map = V3Control::getHookInsCfg();
const auto insCfg = map.find(key);
@ -654,6 +569,7 @@ class HookInsFunc final : public VNVisitor {
return "";
}
}
// Remove "" from string from ->name()
string cleanString(const string& str) {
if (str.size() >= 2 && str.front() == '"' && str.back() == '"') {
return str.substr(1, str.size() - 2);
@ -661,7 +577,6 @@ class HookInsFunc final : public VNVisitor {
return "";
}
}
// Set the done flag for the given module node pointer in the configuraiton map
void setDone(AstModule* nodep) {
auto& insCfg = V3Control::getHookInsCfg();
for (auto& pair : insCfg) {
@ -673,10 +588,8 @@ class HookInsFunc final : public VNVisitor {
m_assignNode = true;
VDirection dir = m_orig_varp->direction();
if (dir == VDirection::INPUT || dir == VDirection::NONE) {
// Hier muss was mit dem rhsp gemacht werden
AstNodeExpr* rhsp = nodep->rhsp();
if (rhsp->type() != VNType::ParseRef) {
// Muss ich hier loopen?
for (AstNode* n = rhsp->op1p(); n; n = n->nextp()) {
if (n->type() == VNType::ParseRef && n->name() == m_orig_varp->name()) {
n->name(m_tmp_varp->name());
@ -741,10 +654,6 @@ class HookInsFunc final : public VNVisitor {
}
// Visitors
//----------------------------------------------------------------------------------
//ASTNETLIST VISITOR FUNCTION:
//Loop over map entries for module nodes and add them to the tree
void visit(AstNetlist* nodep) override {
const auto& insCfg = V3Control::getHookInsCfg();
for (const auto& pair : insCfg) {
@ -762,37 +671,18 @@ class HookInsFunc final : public VNVisitor {
}
}
}
//ASTMODULE VISITOR FUNCTION:
//This function is called for each module node in the netlist.
//It checks if the module node is part of the hook-insertion configuration map.
//Depending on the type of the module node (Hook-inserted, Top, Pointing, or Original),
//it performs different actions:
// - If the module is an hook-inserted module entry and has not been done, it creates a new
//task for the hook-insertion function, adds the temporary variable, and creates a task
//reference to the callback function.
// - If the module is a pointing module or a top module and has no multiple cellps, it
// checks
//the cell for the target key and counts the pins. This pin count is used in the CELL VISITOR
//FUNCTION to set a siutable pin number for the HOOKINS parameter. Look there fore further
//information.
// - If the module is a pointing module and has multiple cellps, it creates a begin block
// with
//a conditional statement to select between the hook-inserted and original cell.
// Additionally like in the previous case, the pin count is used to set a suitable pin
//number for the HOOKINS parameter.\ Since the cell which need to be edited are located not
//in the original module, but in the pointing/top module, the current_module_cell_check
//variable is set to the module visited by the function and fulfilling this condition.
void visit(AstModule* nodep) override {
const auto& insCfg = V3Control::getHookInsCfg().find(m_targetKey);
const HookInsertTarget& target = insCfg->second;
const auto& entries = target.entries;
// Insert nodes for hooks into module for each defined target
for (m_targetIndex = 0; m_targetIndex < entries.size(); ++m_targetIndex) {
m_tmp_varp = getMapEntryInsVar(m_targetKey, m_targetIndex);
m_orig_varp = getMapEntryVar(m_targetKey, m_targetIndex);
m_task_name = getMapEntryFunction(m_targetKey, m_targetIndex);
if (isInsModEntry(nodep, m_targetKey) && !isDone(nodep)) {
m_current_module = nodep;
// Add DPI function/task if not already present
for (AstNode* n = nodep->op2p(); n; n = n->nextp()) {
if (VN_IS(n, Task) && n->name() == m_task_name) {
m_taskp = VN_CAST(n, Task);
@ -821,13 +711,14 @@ class HookInsFunc final : public VNVisitor {
nodep->addStmtsp(m_taskp);
}
}
// Prepare and add faulty variable
if (m_orig_varp->direction() == VDirection::INPUT) {
m_tmp_varp->varType(VVarType::VAR);
m_tmp_varp->direction(VDirection::NONE);
m_tmp_varp->trace(true);
}
nodep->addStmtsp(m_tmp_varp);
// Pruefung einbauen ob das schon passiert ist.
// Add trigger if not already present
if (m_dpi_trigger == nullptr) {
m_dpi_trigger = new AstVar{
nodep->fileline(), VVarType::VAR, "dpi_trigger", VFlagChildDType{},
@ -840,6 +731,7 @@ class HookInsFunc final : public VNVisitor {
nodep->fileline(), new AstBegin{nodep->fileline(), "", m_loopp, false}};
nodep->addStmtsp(initialp);
}
// Add taks/function ref depending on taks/func added & create always block
if (m_taskp != nullptr) {
m_taskrefp = new AstTaskRef{
nodep->fileline(), m_task_name,
@ -860,6 +752,7 @@ class HookInsFunc final : public VNVisitor {
nodep->addStmtsp(alwaysp);
}
if (m_targetIndex == entries.size() - 1) { setDone(nodep); }
// Get pin number for cell edits
for (AstNode* n = nodep->op2p(); n; n = n->nextp()) {
if (VN_IS(n, Port)) { m_pinnum = VN_CAST(n, Port)->pinNum(); }
}
@ -875,6 +768,8 @@ class HookInsFunc final : public VNVisitor {
AstCell* insCellp = getMapEntryCell(m_targetKey)->cloneTree(false);
insCellp->modp(getMapEntryInsModule(m_targetKey));
for (AstNode* n = insCellp->pinsp(); n; n = n->nextp()) { m_pinnum++; }
// Add logic for deciding between original and hook-inserted module
// depending on the value of HOOKINS parameter
bool addedInitGenIf = false;
bool breakOuter = false;
std::string condValue = "";
@ -915,6 +810,7 @@ class HookInsFunc final : public VNVisitor {
}
if (breakOuter) { break; }
}
// If no GenIf for HOOKINS added yet, add one
if (!addedInitGenIf) {
AstGenIf* genifp = new AstGenIf{
nodep->fileline(),
@ -944,16 +840,8 @@ class HookInsFunc final : public VNVisitor {
m_loopp = nullptr;
m_targetIndex = 0;
}
//ASTPORT VISITOR FUNCTION:
//When the target variable is an ouput port, this function is called.
//If no port is added yet, two new ports are added to the current module.
//This enabled the hook-insertion of the ouput port and link this hook-inserted port to the
//modules reading from the original port. The idea behind this function is to set the
//hook-inserted port on the position of the original port in the module and move the original
//port to another pin number. This should ensure the linking over the name and the port
//position in the module should work.
void visit(AstPort* nodep) override {
// Replace original port with tmp port; keep original port for to be sure
if (m_current_module != nullptr && m_orig_varp->direction() == VDirection::OUTPUT
&& nodep->name() == m_orig_varp->name() && !m_addedport) {
m_orig_portp = nodep->cloneTree(false);
@ -966,20 +854,6 @@ class HookInsFunc final : public VNVisitor {
m_addedport = true;
}
}
//ASTCELL VISITOR FUNCTION:
//This function visits the cell nodes in the module pointing to the hook-inserted module.
//Depending if hasMultiple is set for the target key, two different actions are performed:
// - If hasMultiple is false, the cell is modified to link to the hook-inserted module and
// the
//children are iterated. This ensures that the hook-inserted mopdule is used in the cell. Also
//if the original variable is an output variable, the children of this cell nodes are visited
//by the ASTPIN VISITOR FUNCTION.
// - If hasMultiple is true, the cell is unlinked from the back and deleted.
// This ensures that the cell is not used anymore in the module, and the conditional
//statment deciding between the hook-inserted and the original cell can be created/used. A
//third action is performed if the variable beeing hook-inserted is an ouput variable. In this
//case the children of this cell nodes are visited by the ASTPIN VISITOR FUNCTION.
void visit(AstCell* nodep) override {
bool nodeHasName = false;
bool nodeHasCorrectBackp = false;
@ -987,11 +861,15 @@ class HookInsFunc final : public VNVisitor {
nodeHasName = (nodep->name() == getMapEntryCell(m_targetKey)->name());
nodeHasCorrectBackp = (nodep->backp()->type() != VNType::GenBlock);
isCorrectMultCell = nodeHasName && nodeHasCorrectBackp;
// Edit cell reference depending on situation
if (m_current_module_cell_check != nullptr && !hasMultiple(m_targetKey) && nodeHasName) {
// Not multiple cells refer to target module; edit module reference
nodep->modp(getMapEntryInsModule(m_targetKey));
if (m_orig_varp->direction() == VDirection::OUTPUT) { iterateChildren(nodep); }
} else if (m_current_module_cell_check != nullptr && hasMultiple(m_targetKey)
&& isCorrectMultCell) {
// Multiple cells link to target module;
// delete original cell add logic with module visitor
nodep->unlinkFrBack();
nodep->deleteTree();
} else if (m_insGenBlock != nullptr && nodep->modp() == getMapEntryInsModule(m_targetKey)
@ -1001,11 +879,6 @@ class HookInsFunc final : public VNVisitor {
iterateChildren(nodep);
}
}
//ASTPIN VISITOR FUNCTION:
//The function is used to change the pin name of the original variable to the hook-inserted
//variable name. This is done to ensure that the pin is correctly linked to the hook-inserted
//variable in the cell.
void visit(AstPin* nodep) override {
if (nodep->name() == m_orig_varp->name()
&& m_orig_varp->direction() == VDirection::INPUT) {
@ -1014,9 +887,6 @@ class HookInsFunc final : public VNVisitor {
nodep->name(m_tmp_varp->name());
}
}
//ASTTASK VISITOR FUNCTION:
//The function is used to further specify the task node created at the module visitor.
void visit(AstTask* nodep) override {
if (m_addedTask == false && nodep == m_taskp && m_current_module != nullptr) {
AstVar* insID = nullptr;
@ -1041,9 +911,6 @@ class HookInsFunc final : public VNVisitor {
nodep->addStmtsp(tmp_var_task);
}
}
//ASTFUNC VISITOR FUNCITON:
//The function is used to further specify the function node created at the module visitor.
void visit(AstFunc* nodep) override {
if (m_addedFunc == false && nodep == m_funcp && m_current_module != nullptr) {
AstVar* insID = nullptr;
@ -1067,11 +934,8 @@ class HookInsFunc final : public VNVisitor {
nodep->addStmtsp(var_x_func);
}
}
//ASTLOOP VISITOR FUNCTION:
//The function is used to add the logic for the dpi trigger, that triggers the DPI function at
//the smallest possible time intervals.
void visit(AstLoop* nodep) override {
// Add initial block for DPI trigger variable
if (nodep == m_loopp && m_current_module != nullptr) {
AstParseRef* initialParseRefrhsp
= new AstParseRef{nodep->fileline(), m_dpi_trigger->name()};
@ -1088,11 +952,8 @@ class HookInsFunc final : public VNVisitor {
nodep->addContsp(initialBeginp);
}
}
//ASTALWAYS VISITOR FUNCTION:
//The function is used to add the task reference node to the always node and further specify
//the always node.
void visit(AstAlways* nodep) override {
// Add task reference in the new always block
if (nodep == m_alwaysp && m_current_module != nullptr) {
AstBegin* newBegin = nullptr;
@ -1104,15 +965,12 @@ class HookInsFunc final : public VNVisitor {
}
iterateChildren(nodep);
}
void visit(AstVar* nodep) override {
// Store hooked var in hooked module to ensure correct references
if (m_current_module != nullptr && nodep->name() == m_orig_varp->name()) {
m_orig_varp_insMod = nodep;
}
}
//ASTTASKREF VISITOR FUNCTION:
//The function is used to further specify the task reference node called by the always node.
void visit(AstTaskRef* nodep) override {
if (nodep == m_taskrefp && m_current_module != nullptr) {
AstConst* constp_id = nullptr;
@ -1130,10 +988,6 @@ class HookInsFunc final : public VNVisitor {
m_orig_varp_insMod = nullptr;
}
}
//ASTFUNCREF VISITOR FUNCTION:
//The function is used to further specify the function reference node called by the assignw
//node
void visit(AstFuncRef* nodep) override {
if (nodep == m_funcrefp && m_current_module != nullptr) {
AstConst* constp_id = nullptr;
@ -1155,28 +1009,12 @@ class HookInsFunc final : public VNVisitor {
m_funcrefp = nullptr;
}
}
//ASTASSIGNW VISITOR FUNCTION:
//Sets the m_assignw flag to true if the current module is not null.
//Necessary for the AstParseRef visitor function to determine if the current node is part of an
//assignment.
void visit(AstAssignW* nodep) override { insAssigns(nodep); }
void visit(AstAssign* nodep) override { insAssigns(nodep); }
void visit(AstAssignDly* nodep) override { insAssigns(nodep); }
void visit(AstAssignForce* nodep) override { insAssigns(nodep); }
//ASTPARSE REF VISITOR FUNCTION:
//The function is used to change the parseref nodes to link to the hook-inserted variable
//instead of the original variable. Depending on the direction of the original variable,
//different actions are performed:
// - If the original variable is not an output variable and the assignment is true, the
//parseref node is changed to link to the hook-inserted variable. This ensures that the
//hook-inserted variable is used in the assignment.
// - If the original variable is an input variable, every parseref node is changed to link
// to
//the hook-inserted variable. This ensures that the hook-inserted variable is used as the new
//input.
void visit(AstAssignW* nodep) override { insAssigns(nodep); } // Edit assigns if needed
void visit(AstAssign* nodep) override { insAssigns(nodep); } // Edit assigns if needed
void visit(AstAssignDly* nodep) override { insAssigns(nodep); } // Edit assigns if needed
void visit(AstAssignForce* nodep) override { insAssigns(nodep); } // Edit assigns if needed
void visit(AstParseRef* nodep) override {
// Replace original var with tmp var in non-assign nodes
if (m_current_module != nullptr && m_orig_varp != nullptr
&& m_orig_varp->direction() != VDirection::OUTPUT) {
if (nodep->name() == m_orig_varp->name() && !m_assignNode) {
@ -1197,15 +1035,12 @@ public:
//##################################################################################
// Hook-insertion class functions
// Function to find hook-insertion targets and additional information for the hook-insertion
// process
void V3InsertHook::findTargets(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl);
{ HookInsTargetFndr{nodep}; }
V3Global::dumpCheckGlobalTree("hookInsertFinder", 0, dumpTreeEitherLevel() >= 3);
}
// Function for the actual hook-insertion process
void V3InsertHook::insertHooks(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl);
{ HookInsFunc{nodep}; }