mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 09:33:41 +02:00
Optimize assertion control queries (#8547)
This commit is contained in:
+3
-19
@@ -3128,32 +3128,16 @@ VerilatedContext::Serialized::Serialized() {
|
||||
|
||||
bool VerilatedContext::assertOn() const VL_MT_SAFE { return m_s.m_assertOn; }
|
||||
void VerilatedContext::assertOn(bool flag) VL_MT_SAFE {
|
||||
if (assertCtlsLocked()) return;
|
||||
if (m_ns.m_assertCtlsLocked) return;
|
||||
// Set all assert and directive types when true, clear otherwise.
|
||||
m_s.m_assertOn = VL_MASK_I(ASSERT_ON_WIDTH) * flag;
|
||||
}
|
||||
bool VerilatedContext::assertOnGet(VerilatedAssertType_t type,
|
||||
VerilatedAssertDirectiveType_t directive) const VL_MT_SAFE {
|
||||
return assertCtlGet(VerilatedAssertCtlQuery::ASSERT_CTL_ON, type, directive);
|
||||
}
|
||||
void VerilatedContext::assertOnSet(VerilatedAssertType_t types,
|
||||
VerilatedAssertDirectiveType_t directives) VL_MT_SAFE {
|
||||
if (assertCtlsLocked()) return;
|
||||
m_s.m_assertOn |= assertOnMask(types, directives);
|
||||
}
|
||||
void VerilatedContext::assertOnClear(VerilatedAssertType_t types,
|
||||
VerilatedAssertDirectiveType_t directives) VL_MT_SAFE {
|
||||
if (assertCtlsLocked()) return;
|
||||
m_s.m_assertOn &= ~assertOnMask(types, directives);
|
||||
}
|
||||
bool VerilatedContext::assertCtlsLocked() const VL_MT_SAFE { return m_ns.m_assertCtlsLocked; }
|
||||
void VerilatedContext::assertCtlsLocked(bool flag) VL_MT_SAFE { m_ns.m_assertCtlsLocked = flag; }
|
||||
void VerilatedContext::assertCtl(uint32_t controlType, VerilatedAssertType_t types,
|
||||
VerilatedAssertDirectiveType_t directives) VL_MT_SAFE {
|
||||
// IEEE 1800-2023 Table 20-5 control_type. Lock freezes the On/Off state of the
|
||||
// selected bits until Unlock; On/Off/Kill leave locked bits unchanged.
|
||||
// +verilator+assert+lock freezes everything, including Lock/Unlock itself.
|
||||
if (assertCtlsLocked()) return;
|
||||
if (m_ns.m_assertCtlsLocked) return;
|
||||
const uint32_t mask = assertOnMask(types, directives);
|
||||
const uint32_t lockedMask = mask & ~m_s.m_assertLock;
|
||||
switch (controlType) {
|
||||
@@ -3598,7 +3582,7 @@ void VerilatedContextImp::commandArgVl(const std::string& arg) {
|
||||
std::string str;
|
||||
uint64_t u64;
|
||||
if (arg == "+verilator+assert+lock") {
|
||||
assertCtlsLocked(true);
|
||||
m_ns.m_assertCtlsLocked = true;
|
||||
} else if (commandArgVlString(arg, "+verilator+coverage+file+", str)) {
|
||||
coverageFilename(str);
|
||||
} else if (arg == "+verilator+debug") {
|
||||
|
||||
+21
-32
@@ -510,8 +510,8 @@ private:
|
||||
= ASSERT_DIRECTIVE_TYPE_MASK_WIDTH * std::numeric_limits<VerilatedAssertType_t>::digits
|
||||
+ 1;
|
||||
// Build the assertion-control bit mask for the given assertion x directive types.
|
||||
static inline uint32_t assertOnMask(VerilatedAssertType_t types,
|
||||
VerilatedAssertDirectiveType_t directives) VL_PURE;
|
||||
static constexpr uint32_t assertOnMask(VerilatedAssertType_t types,
|
||||
VerilatedAssertDirectiveType_t directives) VL_PURE;
|
||||
static constexpr size_t ASSERT_CONTROL_SLOT_COUNT = ASSERT_ON_WIDTH - 1;
|
||||
// No termination request has stamped m_finishPendingTime yet
|
||||
static constexpr uint64_t TIME_UNSET = ~0ULL;
|
||||
@@ -651,28 +651,9 @@ public:
|
||||
bool assertOn() const VL_MT_SAFE;
|
||||
/// Enable all assertion types
|
||||
void assertOn(bool flag) VL_MT_SAFE;
|
||||
/// Get enabled status for given assertion types
|
||||
bool assertOnGet(VerilatedAssertType_t type,
|
||||
VerilatedAssertDirectiveType_t directive) const VL_MT_SAFE;
|
||||
/// Set enabled status for given assertion types
|
||||
void assertOnSet(VerilatedAssertType_t types,
|
||||
VerilatedAssertDirectiveType_t directives) VL_MT_SAFE;
|
||||
/// Clear enabled status for given assertion types
|
||||
void assertOnClear(VerilatedAssertType_t types,
|
||||
VerilatedAssertDirectiveType_t directives) VL_MT_SAFE;
|
||||
/// Return if assertion-control updates are locked. When locked, RTL assert
|
||||
// control statements ($asserton/$assertoff/$assertcontrol) are ignored, as
|
||||
// are updates from the C++ API.
|
||||
bool assertCtlsLocked() const VL_MT_SAFE;
|
||||
/// Lock/unlock assertion-control updates.
|
||||
void assertCtlsLocked(bool flag) VL_MT_SAFE;
|
||||
/// Apply assertion control for given control, assertion, and directive types
|
||||
void assertCtl(uint32_t controlType, VerilatedAssertType_t types,
|
||||
VerilatedAssertDirectiveType_t directives) VL_MT_SAFE;
|
||||
/// Get assertion-control runtime state. Boolean queries return 0/1, Kill returns
|
||||
/// the generation count.
|
||||
inline uint32_t assertCtlGet(VerilatedAssertCtlQuery query, VerilatedAssertType_t type,
|
||||
VerilatedAssertDirectiveType_t directive) const VL_MT_SAFE;
|
||||
/// Return if calculating of unused signals (for traces)
|
||||
bool calcUnusedSigs() const VL_MT_SAFE { return m_s.m_calcUnusedSigs; }
|
||||
/// Enable calculation of unused signals (for traces)
|
||||
@@ -848,6 +829,10 @@ public:
|
||||
bool stopRequestReserve(bool maybe) VL_MT_SAFE;
|
||||
void stopRequestRelease() VL_MT_SAFE;
|
||||
|
||||
// Internal: assertCtlGet() for generated code, with constant type and directive
|
||||
template <VerilatedAssertType_t T_Type, VerilatedAssertDirectiveType_t T_Directive>
|
||||
VL_ATTR_ALWINLINE uint32_t assertCtlGet(VerilatedAssertCtlQuery query) const VL_MT_SAFE;
|
||||
|
||||
// Internal: access to implementation class
|
||||
VerilatedContextImp* impp() VL_MT_SAFE { return reinterpret_cast<VerilatedContextImp*>(this); }
|
||||
const VerilatedContextImp* impp() const VL_MT_SAFE {
|
||||
@@ -1356,8 +1341,9 @@ void VerilatedContext::timeprecision(int value) VL_MT_SAFE {
|
||||
}
|
||||
|
||||
// Defined here, not in-class: VL_CLOG2_I / VL_FATAL_MT (verilated_funcs.h) are not yet in scope
|
||||
uint32_t VerilatedContext::assertOnMask(VerilatedAssertType_t types,
|
||||
VerilatedAssertDirectiveType_t directives) VL_PURE {
|
||||
constexpr uint32_t
|
||||
VerilatedContext::assertOnMask(VerilatedAssertType_t types,
|
||||
VerilatedAssertDirectiveType_t directives) VL_PURE {
|
||||
// Place the directive bits at each selected assertion type's 3-bit group.
|
||||
uint32_t mask = 0;
|
||||
for (int i = 0; i < std::numeric_limits<VerilatedAssertType_t>::digits; ++i) {
|
||||
@@ -1365,21 +1351,24 @@ uint32_t VerilatedContext::assertOnMask(VerilatedAssertType_t types,
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
uint32_t
|
||||
VerilatedContext::assertCtlGet(VerilatedAssertCtlQuery query, VerilatedAssertType_t type,
|
||||
VerilatedAssertDirectiveType_t directive) const VL_MT_SAFE {
|
||||
const uint32_t mask = assertOnMask(type, directive);
|
||||
template <VerilatedAssertType_t T_Type, VerilatedAssertDirectiveType_t T_Directive>
|
||||
uint32_t VerilatedContext::assertCtlGet(VerilatedAssertCtlQuery query) const VL_MT_SAFE {
|
||||
// A constexpr local forces compile-time evaluation of the mask, which a plain
|
||||
// assertOnMask() call does not get from GCC at -Os
|
||||
constexpr uint32_t mask = assertOnMask(T_Type, T_Directive);
|
||||
if (!mask) return 0;
|
||||
// Explicit load(): G++ -Os inlines it but not the implicit conversion.
|
||||
switch (query) { // LCOV_EXCL_BR_LINE
|
||||
case VerilatedAssertCtlQuery::ASSERT_CTL_ON: return (m_s.m_assertOn & mask) != 0;
|
||||
case VerilatedAssertCtlQuery::ASSERT_CTL_ON: return (m_s.m_assertOn.load() & mask) != 0;
|
||||
case VerilatedAssertCtlQuery::ASSERT_CTL_KILL:
|
||||
assert(mask && (mask & (mask - 1)) == 0);
|
||||
return m_s.m_assertKill[VL_CLOG2_I(mask)];
|
||||
return m_s.m_assertKill[VL_CLOG2_I(mask)].load();
|
||||
case VerilatedAssertCtlQuery::ASSERT_CTL_PASS_ON_VACUOUS:
|
||||
return (m_s.m_assertPassOnVacuous & mask) != 0;
|
||||
return (m_s.m_assertPassOnVacuous.load() & mask) != 0;
|
||||
case VerilatedAssertCtlQuery::ASSERT_CTL_PASS_ON_NONVACUOUS:
|
||||
return (m_s.m_assertPassOnNonvacuous & mask) != 0;
|
||||
case VerilatedAssertCtlQuery::ASSERT_CTL_FAIL_ON: return (m_s.m_assertFailOn & mask) != 0;
|
||||
return (m_s.m_assertPassOnNonvacuous.load() & mask) != 0;
|
||||
case VerilatedAssertCtlQuery::ASSERT_CTL_FAIL_ON:
|
||||
return (m_s.m_assertFailOn.load() & mask) != 0;
|
||||
default: // LCOV_EXCL_START
|
||||
VL_FATAL_MT("", 0, "", "Internal: Bad assertCtlGet query");
|
||||
VL_UNREACHABLE;
|
||||
|
||||
+16
-11
@@ -154,6 +154,13 @@ void V3AssertCommon::lowerSequenceEvents(AstNetlist* nodep) {
|
||||
V3Global::dumpCheckGlobalTree("assertseqevent", 0, dumpTreeEitherLevel() >= 3);
|
||||
}
|
||||
|
||||
string V3AssertCommon::assertCtlGetCall(const char* query, VAssertType type,
|
||||
VAssertDirectiveType directiveType) {
|
||||
// Template arguments let the runtime build the type/directive mask at C++ compile time
|
||||
return "vlSymsp->_vm_contextp__->assertCtlGet<"s + std::to_string(type) + ", "s
|
||||
+ std::to_string(directiveType) + ">(VerilatedAssertCtlQuery::"s + query + ")"s;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// AssertDeFutureVisitor
|
||||
// If any AstFuture, then move all non-future varrefs to be one cycle behind,
|
||||
@@ -335,11 +342,6 @@ class AssertVisitor final : public VNVisitor {
|
||||
std::unordered_map<const AstAlways*, AstVar*> m_delayedAlways2TickTimep;
|
||||
|
||||
// METHODS
|
||||
static string assertCtlGetCall(const char* query, VAssertType type,
|
||||
VAssertDirectiveType directiveType) {
|
||||
return "vlSymsp->_vm_contextp__->assertCtlGet(VerilatedAssertCtlQuery::"s + query + ", "s
|
||||
+ std::to_string(type) + ", "s + std::to_string(directiveType) + ")"s;
|
||||
}
|
||||
static const char* assertPassOnQuery(bool vacuous) {
|
||||
static constexpr const char* queries[2]
|
||||
= {"ASSERT_CTL_PASS_ON_NONVACUOUS", "ASSERT_CTL_PASS_ON_VACUOUS"};
|
||||
@@ -363,8 +365,9 @@ class AssertVisitor final : public VNVisitor {
|
||||
case VAssertDirectiveType::COVER:
|
||||
case VAssertDirectiveType::ASSUME: {
|
||||
if (v3Global.opt.assertOn()) {
|
||||
return new AstCExpr{fl, AstCExpr::Pure{},
|
||||
assertCtlGetCall("ASSERT_CTL_ON", type, directiveType), 1};
|
||||
return new AstCExpr{
|
||||
fl, AstCExpr::Pure{},
|
||||
V3AssertCommon::assertCtlGetCall("ASSERT_CTL_ON", type, directiveType), 1};
|
||||
}
|
||||
return new AstConst{fl, AstConst::BitFalse{}};
|
||||
}
|
||||
@@ -391,15 +394,17 @@ class AssertVisitor final : public VNVisitor {
|
||||
VAssertDirectiveType directiveType, bool vacuous) {
|
||||
if (!isControlled(directiveType)) return new AstConst{fl, AstConst::BitTrue{}};
|
||||
if (!v3Global.opt.assertOn()) return new AstConst{fl, AstConst::BitFalse{}};
|
||||
return new AstCExpr{fl, AstCExpr::Pure{},
|
||||
assertCtlGetCall(assertPassOnQuery(vacuous), type, directiveType), 1};
|
||||
return new AstCExpr{
|
||||
fl, AstCExpr::Pure{},
|
||||
V3AssertCommon::assertCtlGetCall(assertPassOnQuery(vacuous), type, directiveType), 1};
|
||||
}
|
||||
static AstNodeExpr* assertFailOnCond(FileLine* fl, VAssertType type,
|
||||
VAssertDirectiveType directiveType) {
|
||||
if (!isControlled(directiveType)) return new AstConst{fl, AstConst::BitTrue{}};
|
||||
if (!v3Global.opt.assertOn()) return new AstConst{fl, AstConst::BitFalse{}};
|
||||
return new AstCExpr{fl, AstCExpr::Pure{},
|
||||
assertCtlGetCall("ASSERT_CTL_FAIL_ON", type, directiveType), 1};
|
||||
return new AstCExpr{
|
||||
fl, AstCExpr::Pure{},
|
||||
V3AssertCommon::assertCtlGetCall("ASSERT_CTL_FAIL_ON", type, directiveType), 1};
|
||||
}
|
||||
string assertDisplayMessage(const AstNode* nodep, const string& prefix, const string& message,
|
||||
VDisplayType severity) {
|
||||
|
||||
@@ -28,6 +28,8 @@ class V3AssertCommon final {
|
||||
public:
|
||||
static void collectDefaultDisable(AstNetlist* nodep) VL_MT_DISABLED;
|
||||
static void lowerSequenceEvents(AstNetlist* nodep) VL_MT_DISABLED;
|
||||
static string assertCtlGetCall(const char* query, VAssertType type,
|
||||
VAssertDirectiveType directiveType) VL_MT_DISABLED;
|
||||
};
|
||||
|
||||
class V3Assert final {
|
||||
|
||||
+14
-17
@@ -243,12 +243,6 @@ static AstNodeExpr* sampled(AstNodeExpr* exprp) {
|
||||
return new AstSampled{exprp->fileline(), exprp, exprp->dtypep(), true};
|
||||
}
|
||||
|
||||
static string assertCtlGetCall(const char* query, VAssertType type,
|
||||
VAssertDirectiveType directiveType) {
|
||||
return "vlSymsp->_vm_contextp__->assertCtlGet(VerilatedAssertCtlQuery::"s + query + ", "s
|
||||
+ std::to_string(type) + ", "s + std::to_string(directiveType) + ")"s;
|
||||
}
|
||||
|
||||
static const char* assertPassOnQuery(bool vacuous) {
|
||||
static constexpr const char* queries[2]
|
||||
= {"ASSERT_CTL_PASS_ON_NONVACUOUS", "ASSERT_CTL_PASS_ON_VACUOUS"};
|
||||
@@ -259,13 +253,14 @@ static AstNodeExpr* assertOnCond(FileLine* flp, VAssertType type,
|
||||
VAssertDirectiveType directiveType) {
|
||||
if (!v3Global.opt.assertOn()) { return new AstConst{flp, AstConst::BitFalse{}}; }
|
||||
return new AstCExpr{flp, AstCExpr::Pure{},
|
||||
assertCtlGetCall("ASSERT_CTL_ON", type, directiveType), 1};
|
||||
V3AssertCommon::assertCtlGetCall("ASSERT_CTL_ON", type, directiveType), 1};
|
||||
}
|
||||
|
||||
static AstNodeExpr* assertKillGet(FileLine* flp, VAssertType type,
|
||||
VAssertDirectiveType directiveType) {
|
||||
return new AstCExpr{flp, AstCExpr::Pure{},
|
||||
assertCtlGetCall("ASSERT_CTL_KILL", type, directiveType), 32};
|
||||
V3AssertCommon::assertCtlGetCall("ASSERT_CTL_KILL", type, directiveType),
|
||||
32};
|
||||
}
|
||||
|
||||
static string assertActionControlPrefix(VAssertDirectiveType directiveType) {
|
||||
@@ -280,19 +275,21 @@ static string assertActionControlPrefix(VAssertDirectiveType directiveType) {
|
||||
|
||||
static AstNodeExpr* assertPassOnCond(FileLine* flp, VAssertType type,
|
||||
VAssertDirectiveType directiveType, bool vacuous) {
|
||||
return new AstCExpr{flp, AstCExpr::Pure{},
|
||||
assertActionControlPrefix(directiveType)
|
||||
+ assertCtlGetCall(assertPassOnQuery(vacuous), type, directiveType)
|
||||
+ "))"s,
|
||||
1};
|
||||
return new AstCExpr{
|
||||
flp, AstCExpr::Pure{},
|
||||
assertActionControlPrefix(directiveType)
|
||||
+ V3AssertCommon::assertCtlGetCall(assertPassOnQuery(vacuous), type, directiveType)
|
||||
+ "))"s,
|
||||
1};
|
||||
}
|
||||
|
||||
static AstNodeExpr* assertFailOnCond(FileLine* flp, VAssertType type,
|
||||
VAssertDirectiveType directiveType) {
|
||||
return new AstCExpr{flp, AstCExpr::Pure{},
|
||||
assertActionControlPrefix(directiveType)
|
||||
+ assertCtlGetCall("ASSERT_CTL_FAIL_ON", type, directiveType) + "))"s,
|
||||
1};
|
||||
return new AstCExpr{
|
||||
flp, AstCExpr::Pure{},
|
||||
assertActionControlPrefix(directiveType)
|
||||
+ V3AssertCommon::assertCtlGetCall("ASSERT_CTL_FAIL_ON", type, directiveType) + "))"s,
|
||||
1};
|
||||
}
|
||||
|
||||
static AstIf* newPassOnIf(FileLine* flp, AstNodeExpr* firep, AstNode* bodyp, VAssertType type,
|
||||
|
||||
@@ -27,140 +27,15 @@ void verilatedTest() {
|
||||
TEST_CHECK_NZ(contextp->assertOn());
|
||||
contextp->assertOn(false);
|
||||
TEST_CHECK_Z(contextp->assertOn());
|
||||
TEST_CHECK_Z(contextp->assertOnGet(1, 1));
|
||||
|
||||
// Setting one type
|
||||
contextp->assertOnSet(1, 1);
|
||||
TEST_CHECK_NZ(contextp->assertOnGet(1, 1));
|
||||
TEST_CHECK_NZ(contextp->assertOn());
|
||||
TEST_CHECK_Z(contextp->assertOnGet(2, 2));
|
||||
|
||||
// Setting types
|
||||
contextp->assertOn(false);
|
||||
contextp->assertOnSet(1, 3);
|
||||
TEST_CHECK_NZ(contextp->assertOnGet(1, 3));
|
||||
TEST_CHECK_NZ(contextp->assertOnGet(1, 2));
|
||||
TEST_CHECK_NZ(contextp->assertOnGet(1, 1));
|
||||
TEST_CHECK_Z(contextp->assertOnGet(1, 0));
|
||||
TEST_CHECK_Z(contextp->assertOnGet(2, 0));
|
||||
TEST_CHECK_Z(contextp->assertOnGet(0, 0));
|
||||
|
||||
// Setting multiple types separately
|
||||
contextp->assertOn(false);
|
||||
contextp->assertOnSet(0, 1);
|
||||
contextp->assertOnSet(1, 2);
|
||||
contextp->assertOnSet(2, 3);
|
||||
TEST_CHECK_NZ(contextp->assertOn());
|
||||
TEST_CHECK_Z(contextp->assertOnGet(0, 1));
|
||||
TEST_CHECK_Z(contextp->assertOnGet(1, 1));
|
||||
TEST_CHECK_NZ(contextp->assertOnGet(1, 2));
|
||||
TEST_CHECK_NZ(contextp->assertOnGet(2, 1));
|
||||
TEST_CHECK_NZ(contextp->assertOnGet(2, 2));
|
||||
TEST_CHECK_NZ(contextp->assertOnGet(2, 3));
|
||||
TEST_CHECK_Z(contextp->assertOnGet(0, 2));
|
||||
TEST_CHECK_Z(contextp->assertOnGet(4, 1));
|
||||
TEST_CHECK_Z(contextp->assertOnGet(8, 7));
|
||||
|
||||
// Clearing selected types
|
||||
contextp->assertOn(true);
|
||||
contextp->assertOnClear(1, 3);
|
||||
contextp->assertOnClear(1, 4);
|
||||
TEST_CHECK_Z(contextp->assertOnGet(1, 1));
|
||||
TEST_CHECK_Z(contextp->assertOnGet(1, 2));
|
||||
TEST_CHECK_Z(contextp->assertOnGet(1, 4));
|
||||
contextp->assertOnClear(4, 4);
|
||||
TEST_CHECK_Z(contextp->assertOnGet(4, 4));
|
||||
TEST_CHECK_NZ(contextp->assertOnGet(4, 1));
|
||||
TEST_CHECK_NZ(contextp->assertOnGet(4, 2));
|
||||
TEST_CHECK_NZ(contextp->assertOn());
|
||||
|
||||
// Clearing all assert types
|
||||
contextp->assertOn(true);
|
||||
contextp->assertOnClear(255, 7);
|
||||
// Everything is disabled except internal asserts
|
||||
TEST_CHECK_NZ(contextp->assertOn());
|
||||
contextp->assertOn(false);
|
||||
// Now everything is disabled
|
||||
TEST_CHECK_Z(contextp->assertOn());
|
||||
|
||||
// Unified runtime query getter
|
||||
using Query = VerilatedAssertCtlQuery;
|
||||
constexpr uint32_t LOCK = 1;
|
||||
constexpr uint32_t UNLOCK = 2;
|
||||
constexpr uint32_t ON = 3;
|
||||
constexpr uint32_t OFF = 4;
|
||||
constexpr uint32_t KILL = 5;
|
||||
constexpr uint32_t PASS_ON = 6;
|
||||
constexpr uint32_t PASS_OFF = 7;
|
||||
constexpr uint32_t FAIL_ON = 8;
|
||||
constexpr uint32_t FAIL_OFF = 9;
|
||||
constexpr uint32_t NONVACUOUS_ON = 10;
|
||||
constexpr uint32_t VACUOUS_OFF = 11;
|
||||
constexpr uint32_t TYPE = 1;
|
||||
constexpr uint32_t DIRECTIVE = 1;
|
||||
|
||||
TEST_CHECK_Z(contextp->assertCtlGet(Query::ASSERT_CTL_ON, TYPE, DIRECTIVE));
|
||||
TEST_CHECK_Z(contextp->assertCtlGet(Query::ASSERT_CTL_ON, 0, DIRECTIVE));
|
||||
|
||||
contextp->assertCtl(LOCK, TYPE, DIRECTIVE);
|
||||
contextp->assertCtl(ON, TYPE, DIRECTIVE);
|
||||
TEST_CHECK_Z(contextp->assertCtlGet(Query::ASSERT_CTL_ON, TYPE, DIRECTIVE));
|
||||
contextp->assertCtl(UNLOCK, TYPE, DIRECTIVE);
|
||||
contextp->assertCtl(ON, TYPE, DIRECTIVE);
|
||||
TEST_CHECK_NZ(contextp->assertCtlGet(Query::ASSERT_CTL_ON, TYPE, DIRECTIVE));
|
||||
contextp->assertCtl(OFF, TYPE, DIRECTIVE);
|
||||
TEST_CHECK_Z(contextp->assertCtlGet(Query::ASSERT_CTL_ON, TYPE, DIRECTIVE));
|
||||
|
||||
const uint32_t killBefore = contextp->assertCtlGet(Query::ASSERT_CTL_KILL, TYPE, DIRECTIVE);
|
||||
contextp->assertCtl(KILL, TYPE, DIRECTIVE);
|
||||
TEST_CHECK_EQ(contextp->assertCtlGet(Query::ASSERT_CTL_KILL, TYPE, DIRECTIVE), killBefore + 1);
|
||||
TEST_CHECK_Z(contextp->assertCtlGet(Query::ASSERT_CTL_ON, TYPE, DIRECTIVE));
|
||||
|
||||
TEST_CHECK_NZ(contextp->assertCtlGet(Query::ASSERT_CTL_PASS_ON_NONVACUOUS, TYPE, DIRECTIVE));
|
||||
TEST_CHECK_NZ(contextp->assertCtlGet(Query::ASSERT_CTL_PASS_ON_VACUOUS, TYPE, DIRECTIVE));
|
||||
contextp->assertCtl(PASS_OFF, TYPE, DIRECTIVE);
|
||||
TEST_CHECK_Z(contextp->assertCtlGet(Query::ASSERT_CTL_PASS_ON_NONVACUOUS, TYPE, DIRECTIVE));
|
||||
TEST_CHECK_Z(contextp->assertCtlGet(Query::ASSERT_CTL_PASS_ON_VACUOUS, TYPE, DIRECTIVE));
|
||||
|
||||
contextp->assertCtl(NONVACUOUS_ON, TYPE, DIRECTIVE);
|
||||
TEST_CHECK_NZ(contextp->assertCtlGet(Query::ASSERT_CTL_PASS_ON_NONVACUOUS, TYPE, DIRECTIVE));
|
||||
TEST_CHECK_Z(contextp->assertCtlGet(Query::ASSERT_CTL_PASS_ON_VACUOUS, TYPE, DIRECTIVE));
|
||||
contextp->assertCtl(PASS_ON, TYPE, DIRECTIVE);
|
||||
TEST_CHECK_NZ(contextp->assertCtlGet(Query::ASSERT_CTL_PASS_ON_NONVACUOUS, TYPE, DIRECTIVE));
|
||||
TEST_CHECK_NZ(contextp->assertCtlGet(Query::ASSERT_CTL_PASS_ON_VACUOUS, TYPE, DIRECTIVE));
|
||||
contextp->assertCtl(VACUOUS_OFF, TYPE, DIRECTIVE);
|
||||
TEST_CHECK_NZ(contextp->assertCtlGet(Query::ASSERT_CTL_PASS_ON_NONVACUOUS, TYPE, DIRECTIVE));
|
||||
TEST_CHECK_Z(contextp->assertCtlGet(Query::ASSERT_CTL_PASS_ON_VACUOUS, TYPE, DIRECTIVE));
|
||||
|
||||
TEST_CHECK_NZ(contextp->assertCtlGet(Query::ASSERT_CTL_FAIL_ON, TYPE, DIRECTIVE));
|
||||
contextp->assertCtl(FAIL_OFF, TYPE, DIRECTIVE);
|
||||
TEST_CHECK_Z(contextp->assertCtlGet(Query::ASSERT_CTL_FAIL_ON, TYPE, DIRECTIVE));
|
||||
contextp->assertCtl(FAIL_ON, TYPE, DIRECTIVE);
|
||||
TEST_CHECK_NZ(contextp->assertCtlGet(Query::ASSERT_CTL_FAIL_ON, TYPE, DIRECTIVE));
|
||||
}
|
||||
|
||||
void verilatedLockedTest() {
|
||||
// With +verilator+assert+lock, every assertion-control update is a no-op
|
||||
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
|
||||
|
||||
// Clear some bits to test assertOnSet
|
||||
contextp->assertOnClear(2, 3);
|
||||
const char* argsp[] = {"+verilator+assert+lock"};
|
||||
contextp->commandArgsAdd(1, argsp);
|
||||
TEST_CHECK_EQ(contextp->assertCtlsLocked(), true);
|
||||
|
||||
// Validate each assert control API call is a no-op
|
||||
contextp->assertOn(false);
|
||||
TEST_CHECK_NZ(contextp->assertOn());
|
||||
|
||||
contextp->assertOnSet(2, 3);
|
||||
TEST_CHECK_Z(contextp->assertOnGet(2, 3));
|
||||
|
||||
contextp->assertOnClear(1, 1);
|
||||
TEST_CHECK_NZ(contextp->assertOnGet(1, 1));
|
||||
|
||||
contextp->assertCtl(4, 4, 1);
|
||||
TEST_CHECK_NZ(contextp->assertOnGet(4, 1));
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
Reference in New Issue
Block a user