mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 17:43:31 +02:00
Fix protect-lib without sequential logic (#2492)
* add a test for protect-lib without sequential logic that cause the follwoing error.
%Error: obj_vlt/t_prot_lib_comb/secret/secret.sv:78:14: syntax error, unexpected ')'
78 | always @() begin
| ^
* protect-lib wrapper must contain sequential signal related statements
only if the protected design is a sequential logic.
Diff looks big, but actually just add "if (m_hasClk)" condition.
Signed-off-by: Yutetsu TAKATSUKASA <[email protected]>
This commit is contained in:
+100
-61
@@ -60,6 +60,7 @@ private:
|
||||
string m_libName;
|
||||
string m_topName;
|
||||
bool m_foundTop; // Have seen the top module
|
||||
bool m_hasClk; // True if the top module has sequential logic
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
|
||||
@@ -79,6 +80,8 @@ private:
|
||||
UASSERT_OBJ(!m_foundTop, nodep, "Multiple root modules");
|
||||
}
|
||||
FileLine* fl = nodep->fileline();
|
||||
// Need to know the existence of clk before createSvFile()
|
||||
m_hasClk = checkIfClockExists(nodep);
|
||||
createSvFile(fl);
|
||||
createCppFile(fl);
|
||||
|
||||
@@ -162,14 +165,16 @@ private:
|
||||
txtp->addNodep(m_comboPortsp);
|
||||
txtp->addText(fl, ");\n\n");
|
||||
seqComment(txtp, fl);
|
||||
m_seqPortsp = new AstTextBlock(fl,
|
||||
"import \"DPI-C\" function longint " + m_libName
|
||||
+ "_protectlib_seq_update"
|
||||
"(\n",
|
||||
false, true);
|
||||
m_seqPortsp->addText(fl, "chandle handle__V\n");
|
||||
txtp->addNodep(m_seqPortsp);
|
||||
txtp->addText(fl, ");\n\n");
|
||||
if (m_hasClk) {
|
||||
m_seqPortsp = new AstTextBlock(fl,
|
||||
"import \"DPI-C\" function longint " + m_libName
|
||||
+ "_protectlib_seq_update"
|
||||
"(\n",
|
||||
false, true);
|
||||
m_seqPortsp->addText(fl, "chandle handle__V\n");
|
||||
txtp->addNodep(m_seqPortsp);
|
||||
txtp->addText(fl, ");\n\n");
|
||||
}
|
||||
comboIgnoreComment(txtp, fl);
|
||||
m_comboIgnorePortsp = new AstTextBlock(fl,
|
||||
"import \"DPI-C\" function void " + m_libName
|
||||
@@ -192,7 +197,7 @@ private:
|
||||
m_tmpDeclsp = new AstTextBlock(fl);
|
||||
txtp->addNodep(m_tmpDeclsp);
|
||||
txtp->addText(fl, "\ntime last_combo_seqnum__V;\n");
|
||||
txtp->addText(fl, "time last_seq_seqnum__V;\n\n");
|
||||
if (m_hasClk) { txtp->addText(fl, "time last_seq_seqnum__V;\n\n"); }
|
||||
|
||||
// CPP hash value
|
||||
addComment(txtp, fl, "Hash value to make sure this file and the corresponding");
|
||||
@@ -222,33 +227,41 @@ private:
|
||||
txtp->addText(fl, "end\n\n");
|
||||
|
||||
// Sequential process
|
||||
addComment(txtp, fl, "Evaluate clock edges");
|
||||
m_clkSensp = new AstTextBlock(fl, "always @(", false, true);
|
||||
txtp->addNodep(m_clkSensp);
|
||||
txtp->addText(fl, ") begin\n");
|
||||
m_comboIgnoreParamsp
|
||||
= new AstTextBlock(fl, m_libName + "_protectlib_combo_ignore(\n", false, true);
|
||||
m_comboIgnoreParamsp->addText(fl, "handle__V\n");
|
||||
txtp->addNodep(m_comboIgnoreParamsp);
|
||||
txtp->addText(fl, ");\n");
|
||||
m_seqParamsp = new AstTextBlock(
|
||||
fl, "last_seq_seqnum__V <= " + m_libName + "_protectlib_seq_update(\n", false, true);
|
||||
m_seqParamsp->addText(fl, "handle__V\n");
|
||||
txtp->addNodep(m_seqParamsp);
|
||||
txtp->addText(fl, ");\n");
|
||||
m_nbAssignsp = new AstTextBlock(fl);
|
||||
txtp->addNodep(m_nbAssignsp);
|
||||
txtp->addText(fl, "end\n\n");
|
||||
if (m_hasClk) {
|
||||
addComment(txtp, fl, "Evaluate clock edges");
|
||||
m_clkSensp = new AstTextBlock(fl, "always @(", false, true);
|
||||
txtp->addNodep(m_clkSensp);
|
||||
txtp->addText(fl, ") begin\n");
|
||||
m_comboIgnoreParamsp
|
||||
= new AstTextBlock(fl, m_libName + "_protectlib_combo_ignore(\n", false, true);
|
||||
m_comboIgnoreParamsp->addText(fl, "handle__V\n");
|
||||
txtp->addNodep(m_comboIgnoreParamsp);
|
||||
txtp->addText(fl, ");\n");
|
||||
m_seqParamsp = new AstTextBlock(
|
||||
fl, "last_seq_seqnum__V <= " + m_libName + "_protectlib_seq_update(\n", false,
|
||||
true);
|
||||
m_seqParamsp->addText(fl, "handle__V\n");
|
||||
txtp->addNodep(m_seqParamsp);
|
||||
txtp->addText(fl, ");\n");
|
||||
m_nbAssignsp = new AstTextBlock(fl);
|
||||
txtp->addNodep(m_nbAssignsp);
|
||||
txtp->addText(fl, "end\n\n");
|
||||
}
|
||||
|
||||
// Select between combinatorial and sequential results
|
||||
addComment(txtp, fl, "Select between combinatorial and sequential results");
|
||||
txtp->addText(fl, "always @(*) begin\n");
|
||||
m_seqAssignsp = new AstTextBlock(fl, "if (last_seq_seqnum__V > "
|
||||
"last_combo_seqnum__V) begin\n");
|
||||
txtp->addNodep(m_seqAssignsp);
|
||||
m_comboAssignsp = new AstTextBlock(fl, "end else begin\n");
|
||||
txtp->addNodep(m_comboAssignsp);
|
||||
txtp->addText(fl, "end\n");
|
||||
if (m_hasClk) {
|
||||
m_seqAssignsp = new AstTextBlock(fl, "if (last_seq_seqnum__V > "
|
||||
"last_combo_seqnum__V) begin\n");
|
||||
txtp->addNodep(m_seqAssignsp);
|
||||
m_comboAssignsp = new AstTextBlock(fl, "end else begin\n");
|
||||
txtp->addNodep(m_comboAssignsp);
|
||||
txtp->addText(fl, "end\n");
|
||||
} else {
|
||||
m_comboAssignsp = new AstTextBlock(fl, "");
|
||||
txtp->addNodep(m_comboAssignsp);
|
||||
}
|
||||
txtp->addText(fl, "end\n\n");
|
||||
|
||||
// Final
|
||||
@@ -327,19 +340,21 @@ private:
|
||||
txtp->addText(fl, "return handlep__V->m_seqnum++;\n");
|
||||
txtp->addText(fl, "}\n\n");
|
||||
|
||||
seqComment(txtp, fl);
|
||||
m_cSeqParamsp = new AstTextBlock(
|
||||
fl, "long long " + m_libName + "_protectlib_seq_update(\n", false, true);
|
||||
m_cSeqParamsp->addText(fl, "void* vhandlep__V\n");
|
||||
txtp->addNodep(m_cSeqParamsp);
|
||||
txtp->addText(fl, ")\n");
|
||||
m_cSeqClksp = new AstTextBlock(fl, "{\n");
|
||||
castPtr(fl, m_cSeqClksp);
|
||||
txtp->addNodep(m_cSeqClksp);
|
||||
m_cSeqOutsp = new AstTextBlock(fl, "handlep__V->eval();\n");
|
||||
txtp->addNodep(m_cSeqOutsp);
|
||||
txtp->addText(fl, "return handlep__V->m_seqnum++;\n");
|
||||
txtp->addText(fl, "}\n\n");
|
||||
if (m_hasClk) {
|
||||
seqComment(txtp, fl);
|
||||
m_cSeqParamsp = new AstTextBlock(
|
||||
fl, "long long " + m_libName + "_protectlib_seq_update(\n", false, true);
|
||||
m_cSeqParamsp->addText(fl, "void* vhandlep__V\n");
|
||||
txtp->addNodep(m_cSeqParamsp);
|
||||
txtp->addText(fl, ")\n");
|
||||
m_cSeqClksp = new AstTextBlock(fl, "{\n");
|
||||
castPtr(fl, m_cSeqClksp);
|
||||
txtp->addNodep(m_cSeqClksp);
|
||||
m_cSeqOutsp = new AstTextBlock(fl, "handlep__V->eval();\n");
|
||||
txtp->addNodep(m_cSeqOutsp);
|
||||
txtp->addText(fl, "return handlep__V->m_seqnum++;\n");
|
||||
txtp->addText(fl, "}\n\n");
|
||||
}
|
||||
|
||||
comboIgnoreComment(txtp, fl);
|
||||
m_cIgnoreParamsp = new AstTextBlock(
|
||||
@@ -369,6 +384,7 @@ private:
|
||||
}
|
||||
if (nodep->direction() == VDirection::INPUT) {
|
||||
if (nodep->isUsedClock() || nodep->attrClocker() == VVarAttrClocker::CLOCKER_YES) {
|
||||
UASSERT_OBJ(m_hasClk, nodep, "checkIfClockExists() didn't find this clock");
|
||||
handleClock(nodep);
|
||||
} else {
|
||||
handleDataInput(nodep);
|
||||
@@ -396,8 +412,10 @@ private:
|
||||
FileLine* fl = varp->fileline();
|
||||
handleInput(varp);
|
||||
m_seqPortsp->addNodep(varp->cloneTree(false));
|
||||
m_seqParamsp->addText(fl, varp->name() + "\n");
|
||||
m_clkSensp->addText(fl, "edge(" + varp->name() + ")");
|
||||
if (m_hasClk) {
|
||||
m_seqParamsp->addText(fl, varp->name() + "\n");
|
||||
m_clkSensp->addText(fl, "edge(" + varp->name() + ")");
|
||||
}
|
||||
m_cSeqParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
|
||||
m_cSeqClksp->addText(fl, cInputConnection(varp));
|
||||
}
|
||||
@@ -408,7 +426,7 @@ private:
|
||||
m_comboPortsp->addNodep(varp->cloneTree(false));
|
||||
m_comboParamsp->addText(fl, varp->name() + "\n");
|
||||
m_comboIgnorePortsp->addNodep(varp->cloneTree(false));
|
||||
m_comboIgnoreParamsp->addText(fl, varp->name() + "\n");
|
||||
if (m_hasClk) { m_comboIgnoreParamsp->addText(fl, varp->name() + "\n"); }
|
||||
m_cComboParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
|
||||
m_cComboInsp->addText(fl, cInputConnection(varp));
|
||||
m_cIgnoreParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
|
||||
@@ -421,29 +439,49 @@ private:
|
||||
m_modPortsp->addNodep(varp->cloneTree(false));
|
||||
m_comboPortsp->addNodep(varp->cloneTree(false));
|
||||
m_comboParamsp->addText(fl, varp->name() + "_combo__V\n");
|
||||
m_seqPortsp->addNodep(varp->cloneTree(false));
|
||||
m_seqParamsp->addText(fl, varp->name() + "_tmp__V\n");
|
||||
if (m_hasClk) {
|
||||
m_seqPortsp->addNodep(varp->cloneTree(false));
|
||||
m_seqParamsp->addText(fl, varp->name() + "_tmp__V\n");
|
||||
}
|
||||
|
||||
AstNodeDType* comboDtypep = varp->dtypep()->cloneTree(false);
|
||||
m_comboDeclsp->addNodep(comboDtypep);
|
||||
m_comboDeclsp->addText(fl, " " + varp->name() + "_combo__V;\n");
|
||||
|
||||
AstNodeDType* seqDtypep = varp->dtypep()->cloneTree(false);
|
||||
m_seqDeclsp->addNodep(seqDtypep);
|
||||
m_seqDeclsp->addText(fl, " " + varp->name() + "_seq__V;\n");
|
||||
if (m_hasClk) {
|
||||
AstNodeDType* seqDtypep = varp->dtypep()->cloneTree(false);
|
||||
m_seqDeclsp->addNodep(seqDtypep);
|
||||
m_seqDeclsp->addText(fl, " " + varp->name() + "_seq__V;\n");
|
||||
|
||||
AstNodeDType* tmpDtypep = varp->dtypep()->cloneTree(false);
|
||||
m_tmpDeclsp->addNodep(tmpDtypep);
|
||||
m_tmpDeclsp->addText(fl, " " + varp->name() + "_tmp__V;\n");
|
||||
AstNodeDType* tmpDtypep = varp->dtypep()->cloneTree(false);
|
||||
m_tmpDeclsp->addNodep(tmpDtypep);
|
||||
m_tmpDeclsp->addText(fl, " " + varp->name() + "_tmp__V;\n");
|
||||
|
||||
m_nbAssignsp->addText(fl, varp->name() + "_seq__V <= " + varp->name() + "_tmp__V;\n");
|
||||
m_seqAssignsp->addText(fl, varp->name() + " = " + varp->name() + "_seq__V;\n");
|
||||
m_nbAssignsp->addText(fl, varp->name() + "_seq__V <= " + varp->name() + "_tmp__V;\n");
|
||||
m_seqAssignsp->addText(fl, varp->name() + " = " + varp->name() + "_seq__V;\n");
|
||||
}
|
||||
m_comboAssignsp->addText(fl, varp->name() + " = " + varp->name() + "_combo__V;\n");
|
||||
m_cComboParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
|
||||
m_cComboOutsp->addText(fl,
|
||||
V3Task::assignInternalToDpi(varp, true, "", "", "handlep__V->"));
|
||||
m_cSeqParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
|
||||
m_cSeqOutsp->addText(fl, V3Task::assignInternalToDpi(varp, true, "", "", "handlep__V->"));
|
||||
if (m_hasClk) {
|
||||
m_cSeqParamsp->addText(fl, varp->dpiArgType(true, false) + "\n");
|
||||
m_cSeqOutsp->addText(fl,
|
||||
V3Task::assignInternalToDpi(varp, true, "", "", "handlep__V->"));
|
||||
}
|
||||
}
|
||||
|
||||
static bool checkIfClockExists(AstNodeModule* modp) {
|
||||
for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
if (AstVar* varp = VN_CAST(stmtp, Var)) {
|
||||
if (varp->direction() == VDirection::INPUT
|
||||
&& (varp->isUsedClock()
|
||||
|| varp->attrClocker() == VVarAttrClocker::CLOCKER_YES)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -475,7 +513,8 @@ public:
|
||||
, m_cIgnoreParamsp(NULL)
|
||||
, m_libName(v3Global.opt.protectLib())
|
||||
, m_topName(v3Global.opt.prefix())
|
||||
, m_foundTop(false) {
|
||||
, m_foundTop(false)
|
||||
, m_hasClk(false) {
|
||||
iterate(nodep);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user