mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 18:13:50 +02:00
IEEE compliant scheduler (#3384)
This is a major re-design of the way code is scheduled in Verilator, with the goal of properly supporting the Active and NBA regions of the SystemVerilog scheduling model, as defined in IEEE 1800-2017 chapter 4. With this change, all internally generated clocks should simulate correctly, and there should be no more need for the `clock_enable` and `clocker` attributes for correctness in the absence of Verilator generated library models (`--lib-create`). Details of the new scheduling model and algorithm are provided in docs/internals.rst. Implements #3278
This commit is contained in:
@@ -731,80 +731,3 @@ string EmitCFunc::emitVarResetRecurse(const AstVar* varp, const string& varNameP
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void EmitCFunc::doubleOrDetect(AstChangeDet* changep, bool& gotOne) {
|
||||
// cppcheck-suppress variableScope
|
||||
static int s_addDoubleOr = 10; // Determined experimentally as best
|
||||
if (!changep->rhsp()) {
|
||||
if (!gotOne) {
|
||||
gotOne = true;
|
||||
} else {
|
||||
puts(" | ");
|
||||
}
|
||||
iterateAndNextNull(changep->lhsp());
|
||||
} else {
|
||||
AstNode* const lhsp = changep->lhsp();
|
||||
AstNode* const rhsp = changep->rhsp();
|
||||
UASSERT_OBJ(VN_IS(lhsp, VarRef) || VN_IS(lhsp, ArraySel), changep, "Not ref?");
|
||||
UASSERT_OBJ(VN_IS(rhsp, VarRef) || VN_IS(rhsp, ArraySel), changep, "Not ref?");
|
||||
for (int word = 0; word < (changep->lhsp()->isWide() ? changep->lhsp()->widthWords() : 1);
|
||||
++word) {
|
||||
if (!gotOne) {
|
||||
gotOne = true;
|
||||
s_addDoubleOr = 10;
|
||||
puts("(");
|
||||
} else if (--s_addDoubleOr == 0) {
|
||||
puts("|| (");
|
||||
s_addDoubleOr = 10;
|
||||
} else {
|
||||
puts(" | (");
|
||||
}
|
||||
iterateAndNextNull(changep->lhsp());
|
||||
if (changep->lhsp()->isWide()) puts("[" + cvtToStr(word) + "]");
|
||||
if (changep->lhsp()->isDouble()) {
|
||||
puts(" != ");
|
||||
} else {
|
||||
puts(" ^ ");
|
||||
}
|
||||
iterateAndNextNull(changep->rhsp());
|
||||
if (changep->lhsp()->isWide()) puts("[" + cvtToStr(word) + "]");
|
||||
puts(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EmitCFunc::emitChangeDet() {
|
||||
putsDecoration("// Change detection\n");
|
||||
puts("QData __req = false; // Logically a bool\n"); // But not because it results in
|
||||
// faster code
|
||||
bool gotOne = false;
|
||||
for (AstChangeDet* const changep : m_blkChangeDetVec) {
|
||||
if (changep->lhsp()) {
|
||||
if (!gotOne) { // Not a clocked block
|
||||
puts("__req |= (");
|
||||
} else {
|
||||
puts("\n");
|
||||
}
|
||||
doubleOrDetect(changep, gotOne);
|
||||
}
|
||||
}
|
||||
if (gotOne) puts(");\n");
|
||||
if (gotOne && !v3Global.opt.protectIds()) {
|
||||
// puts("VL_DEBUG_IF( if (__req) cout<<\"- CLOCKREQ );");
|
||||
for (AstChangeDet* nodep : m_blkChangeDetVec) {
|
||||
if (nodep->lhsp()) {
|
||||
puts("VL_DEBUG_IF( if(__req && (");
|
||||
bool gotOneIgnore = false;
|
||||
doubleOrDetect(nodep, gotOneIgnore);
|
||||
string varname;
|
||||
if (VN_IS(nodep->lhsp(), VarRef)) {
|
||||
varname = ": " + VN_AS(nodep->lhsp(), VarRef)->varp()->prettyName();
|
||||
}
|
||||
puts(")) VL_DBG_MSGF(\" CHANGE: ");
|
||||
puts(protect(nodep->fileline()->filename()));
|
||||
puts(":" + cvtToStr(nodep->fileline()->lineno()));
|
||||
puts(varname + "\\n\"); );\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user