https://www.verific.com/faq/index.php?title=Where_in_RTL_is_it_get_assigned%3F&feed=atom&action=history
Where in RTL is it get assigned? - Revision history
2024-03-29T13:29:50Z
Revision history for this page on the wiki
MediaWiki 1.26.3
https://www.verific.com/faq/index.php?title=Where_in_RTL_is_it_get_assigned%3F&diff=655&oldid=prev
Hoa: Created page with "This example illustrates how to find where a signal gets assigned in the RTL code. C++: <nowiki> #include <iostream> #include "veri_file.h" #include "VeriModule.h" #include..."
2021-03-23T20:22:08Z
<p>Created page with "This example illustrates how to find where a signal gets assigned in the RTL code. C++: <nowiki> #include <iostream> #include "veri_file.h" #include "VeriModule.h" #include..."</p>
<p><b>New page</b></p><div>This example illustrates how to find where a signal gets assigned in the RTL code.<br />
<br />
C++:<br />
<nowiki><br />
#include <iostream><br />
<br />
#include "veri_file.h"<br />
#include "VeriModule.h"<br />
#include "VeriId.h"<br />
#include "VeriMisc.h"<br />
#include "VeriExpression.h"<br />
#include "veri_tokens.h"<br />
#include "VeriVisitor.h"<br />
#include "VeriStatement.h"<br />
<br />
#ifdef VERIFIC_NAMESPACE<br />
using namespace Verific ;<br />
#endif<br />
<br />
class MyVisitor : public VeriVisitor<br />
{<br />
public:<br />
MyVisitor() : VeriVisitor(), _assign(0) { }<br />
virtual ~MyVisitor() { _assign = 0 ; }<br />
<br />
virtual void VERI_VISIT(VeriIdRef, node) ;<br />
virtual void VERI_VISIT(VeriIndexedId, node) ;<br />
virtual void VERI_VISIT(VeriIndexedMemoryId, node) ;<br />
virtual void VERI_VISIT(VeriSelectedName, node) ;<br />
<br />
virtual void VERI_VISIT(VeriNetRegAssign, node) ;<br />
virtual void VERI_VISIT(VeriBlockingAssign, node) ;<br />
virtual void VERI_VISIT(VeriNonBlockingAssign, node) ;<br />
virtual void VERI_VISIT(VeriBinaryOperator, node) ;<br />
<br />
private:<br />
VeriTreeNode *_assign ;<br />
} ; // class MyVisitor<br />
<br />
void<br />
MyVisitor::VERI_VISIT(VeriIdRef, node)<br />
{<br />
VeriIdDef *id = node.GetId() ;<br />
if (!_assign || !id) return ;<br />
<br />
char *str = _assign->GetPrettyPrintedString() ;<br />
unsigned l = Strings::len(str) ;<br />
if (str && (str[l-1] == '\n')) str[l-1] = '\0' ;<br />
node.Info("%s is assigned here as: %s", id->Name(), str) ;<br />
Strings::free(str) ;<br />
}<br />
<br />
void<br />
MyVisitor::VERI_VISIT(VeriIndexedId, node)<br />
{<br />
// Call of Base class Visit<br />
VeriVisitor::VERI_VISIT_NODE(VeriName, node) ;<br />
TraverseNode(node.GetPrefix()) ;<br />
// Do not traverse the index!<br />
}<br />
<br />
void<br />
MyVisitor::VERI_VISIT(VeriIndexedMemoryId, node)<br />
{<br />
// Call of Base class Visit<br />
VeriVisitor::VERI_VISIT_NODE(VeriName, node) ;<br />
TraverseNode(node.GetPrefix()) ;<br />
// Do not traverse the index!<br />
}<br />
<br />
void<br />
MyVisitor::VERI_VISIT(VeriSelectedName, node)<br />
{<br />
VeriIdDef *id = node.GetId() ;<br />
if (!_assign || !id) return ;<br />
<br />
char *str = _assign->GetPrettyPrintedString() ;<br />
unsigned l = Strings::len(str) ;<br />
if (str && (str[l-1] == '\n')) str[l-1] = '\0' ;<br />
char *my_name = node.GetPrettyPrintedString() ;<br />
id->Info("%s is assigned here as: %s", my_name, str) ;<br />
Strings::free(my_name) ;<br />
Strings::free(str) ;<br />
}<br />
<br />
void<br />
MyVisitor::VERI_VISIT(VeriNetRegAssign, node)<br />
{<br />
// Call of Base class Visit<br />
VeriVisitor::VERI_VISIT_NODE(VeriTreeNode, node) ;<br />
<br />
VERIFIC_ASSERT(!_assign) ; // It should not be set here<br />
_assign = &node ;<br />
<br />
// Traverse the left hand side expression<br />
TraverseNode(node.GetLValExpr()) ;<br />
<br />
_assign = 0 ;<br />
<br />
// Trverse the right hand side expression<br />
TraverseNode(node.GetRValExpr()) ;<br />
}<br />
<br />
void<br />
MyVisitor::VERI_VISIT(VeriBlockingAssign, node)<br />
{<br />
// Call of Base class Visit<br />
VeriVisitor::VERI_VISIT_NODE(VeriStatement, node) ;<br />
<br />
VERIFIC_ASSERT(!_assign) ; // It should not be set here<br />
_assign = &node ;<br />
<br />
// Traverse left hand side of assignment<br />
TraverseNode(node.GetLVal()) ;<br />
<br />
// Pre increment decrement has right expression set, so do not reset it here:<br />
if ((node.OperType() != VERI_INC_OP) && (node.OperType() != VERI_DEC_OP)) _assign = 0 ;<br />
<br />
// Traverse the value of assignment<br />
TraverseNode(node.GetValue()) ;<br />
<br />
_assign = 0 ;<br />
<br />
// Traverse delay or event control<br />
TraverseNode(node.GetControl()) ;<br />
}<br />
<br />
void<br />
MyVisitor::VERI_VISIT(VeriNonBlockingAssign, node)<br />
{<br />
// Call of Base class Visit<br />
VeriVisitor::VERI_VISIT_NODE(VeriStatement, node) ;<br />
<br />
VERIFIC_ASSERT(!_assign) ; // It should not be set here<br />
_assign = &node ;<br />
<br />
// Traverse left hand side of assignment<br />
TraverseNode(node.GetLVal()) ;<br />
<br />
_assign = 0 ;<br />
<br />
// Traverse delay or event control<br />
TraverseNode(node.GetControl()) ;<br />
<br />
// Traverse the value<br />
TraverseNode(node.GetValue()) ;<br />
}<br />
<br />
void<br />
MyVisitor::VERI_VISIT(VeriBinaryOperator, node)<br />
{<br />
switch (node.OperType()) {<br />
case VERI_INC_OP :<br />
case VERI_DEC_OP :<br />
case VERI_PLUS_ASSIGN :<br />
case VERI_MIN_ASSIGN :<br />
case VERI_MUL_ASSIGN :<br />
case VERI_DIV_ASSIGN :<br />
case VERI_MOD_ASSIGN :<br />
case VERI_AND_ASSIGN :<br />
case VERI_OR_ASSIGN :<br />
case VERI_XOR_ASSIGN :<br />
case VERI_LSHIFT_ASSIGN :<br />
case VERI_RSHIFT_ASSIGN :<br />
case VERI_ALSHIFT_ASSIGN :<br />
case VERI_ARSHIFT_ASSIGN :<br />
case VERI_EQUAL_ASSIGN : break ;<br />
default:<br />
{<br />
// Not interested in this binary operator:<br />
VeriVisitor::VERI_VISIT_NODE(VeriBinaryOperator, node) ;<br />
return ;<br />
}<br />
}<br />
<br />
// Call of Base class Visit<br />
VeriVisitor::VERI_VISIT_NODE(VeriExpression, node) ;<br />
<br />
VERIFIC_ASSERT(!_assign) ; // It should not be set here<br />
_assign = &node ;<br />
<br />
// Traverse left operand<br />
TraverseNode(node.GetLeft()) ;<br />
<br />
// Pre increment decrement has right expression set, so do not reset it here:<br />
if ((node.OperType() != VERI_INC_OP) && (node.OperType() != VERI_DEC_OP)) _assign = 0 ;<br />
<br />
// Traverse right operand<br />
TraverseNode(node.GetRight()) ;<br />
<br />
_assign = 0 ;<br />
}<br />
<br />
int main(void)<br />
{<br />
if (!veri_file::Analyze("prep5.v", veri_file::SYSTEM_VERILOG, "work", veri_file::SFCU)) return 1 ;<br />
VeriModule *mod = veri_file::GetModule("prep5") ;<br />
if (!mod) return 2 ;<br />
<br />
MyVisitor mv ;<br />
mod->Accept(mv) ;<br />
<br />
return 0 ;<br />
}<br />
</nowiki><br />
<br />
Verilog testcase:<br />
<br />
<nowiki><br />
1 // PREP Benchmark 5, Arithmetic Circuit<br />
2 /* PREP5 contains a multiplier and accumulator<br />
3 Copyright (c) 1994 Synplicity, Inc.<br />
4 You may distribute freely, as long as this header remains attached. */<br />
5<br />
6 module prep5(Q, CLK, MAC, RST, A, B);<br />
7 output [7:0] Q;<br />
8 input CLK, MAC, RST;<br />
9 input [3:0] A, B;<br />
10 reg [7:0] Q;<br />
11 wire [7:0] multiply_output;<br />
12 wire [7:0] adder_output;<br />
13<br />
14 assign multiply_output = A * B;<br />
15 assign adder_output = MAC ? multiply_output + Q : multiply_output;<br />
16<br />
17 always @(posedge CLK or posedge RST)<br />
18 if (RST)<br />
19 Q = 0;<br />
20 else<br />
21 Q = adder_output;<br />
22<br />
23 endmodule<br />
</nowiki><br />
<br />
Output:<br />
<br />
<nowiki><br />
-- Analyzing Verilog file 'prep5.v' (VERI-1482)<br />
prep5.v(14): INFO: multiply_output is assigned here as: multiply_output = (A * B)<br />
prep5.v(15): INFO: adder_output is assigned here as: adder_output = (MAC ? (multiply_output + Q) : multiply_output)<br />
prep5.v(19): INFO: Q is assigned here as: Q = 0 ;<br />
prep5.v(21): INFO: Q is assigned here as: Q = adder_output ;<br />
</nowiki></div>
Hoa