Support clocking blocks (#3674)

This commit is contained in:
Krzysztof Bieganski
2022-12-23 07:34:49 -05:00
committed by GitHub
parent d64971ba35
commit bb44d4e4f2
58 changed files with 1817 additions and 218 deletions
+62
View File
@@ -60,6 +60,8 @@ private:
AstNodeModule* m_modp = nullptr; // Current module
AstNodeFTask* m_ftaskp = nullptr; // Current task
AstNodeDType* m_dtypep = nullptr; // Current data type
AstNodeExpr* m_defaultInSkewp = nullptr; // Current default input skew
AstNodeExpr* m_defaultOutSkewp = nullptr; // Current default output skew
int m_genblkAbove = 0; // Begin block number of if/case/for above
int m_genblkNum = 0; // Begin block number, 0=none seen
VLifetime m_lifetime = VLifetime::STATIC; // Propagating lifetime
@@ -632,6 +634,66 @@ private:
nodep->classOrPackagep(m_stdPackagep);
}
}
void visit(AstClocking* nodep) override {
VL_RESTORER(m_defaultInSkewp);
VL_RESTORER(m_defaultOutSkewp);
// Find default input and output skews
AstClockingItem* nextItemp = nodep->itemsp();
for (AstClockingItem* itemp = nextItemp; itemp; itemp = nextItemp) {
nextItemp = VN_AS(itemp->nextp(), ClockingItem);
if (itemp->exprp() || itemp->assignp()) continue;
if (itemp->skewp()) {
if (itemp->direction() == VDirection::INPUT) {
// Disallow default redefinition; note some simulators allow this
if (m_defaultInSkewp) {
itemp->skewp()->v3error("Multiple default input skews not allowed");
}
m_defaultInSkewp = itemp->skewp();
} else if (itemp->direction() == VDirection::OUTPUT) {
if (AstConst* const constp = VN_CAST(itemp->skewp(), Const)) {
if (constp->num().is1Step()) {
itemp->skewp()->v3error("1step not allowed as output skew");
}
}
// Disallow default redefinition; note some simulators allow this
if (m_defaultOutSkewp) {
itemp->skewp()->v3error("Multiple default output skews not allowed");
}
m_defaultOutSkewp = itemp->skewp();
} else {
itemp->v3fatalSrc("Incorrect direction");
}
}
pushDeletep(itemp->unlinkFrBack());
}
iterateChildren(nodep);
}
void visit(AstClockingItem* nodep) override {
if (nodep->direction() == VDirection::OUTPUT) {
if (!nodep->skewp()) {
if (m_defaultOutSkewp) {
nodep->skewp(m_defaultOutSkewp->cloneTree(false));
} else {
// Default is 0 (IEEE 1800-2017 14.3)
nodep->skewp(new AstConst{nodep->fileline(), 0});
}
} else if (AstConst* const constp = VN_CAST(nodep->skewp(), Const)) {
if (constp->num().is1Step()) {
nodep->skewp()->v3error("1step not allowed as output skew");
}
}
} else if (nodep->direction() == VDirection::INPUT) {
if (!nodep->skewp()) {
if (m_defaultInSkewp) {
nodep->skewp(m_defaultInSkewp->cloneTree(false));
} else {
// Default is 1step (IEEE 1800-2017 14.3)
nodep->skewp(new AstConst{nodep->fileline(), AstConst::OneStep{}});
}
}
}
iterateChildren(nodep);
}
void visit(AstNode* nodep) override {
// Default: Just iterate