@@ -357,11 +357,48 @@ FailureOr<Value> Context::convertAssertionSystemCallArity1(
357357 case ksn::Past:
358358 return castToMoore (ltl::PastOp::create (builder, loc, value, 1 , clockVal));
359359
360+ case ksn::OneHot0: {
361+ auto one = hw::ConstantOp::create (builder, loc, value.getType (), 1 );
362+ auto minusOne = builder.create <comb::SubOp>(loc, value, one);
363+ auto anded = builder.create <comb::AndOp>(loc, value, minusOne);
364+ auto zero = hw::ConstantOp::create (builder, loc, value.getType (), 0 );
365+ return castToMoore (comb::ICmpOp::create (
366+ builder, loc, comb::ICmpPredicate::eq, anded, zero, false ));
367+ }
368+
369+ case ksn::OneHot: {
370+ auto one = hw::ConstantOp::create (builder, loc, value.getType (), 1 );
371+ auto minusOne = builder.create <comb::SubOp>(loc, value, one);
372+ auto anded = builder.create <comb::AndOp>(loc, value, minusOne);
373+ auto zero = hw::ConstantOp::create (builder, loc, value.getType (), 0 );
374+ auto isOneHot0 = comb::ICmpOp::create (builder, loc, comb::ICmpPredicate::eq,
375+ anded, zero, false );
376+ auto isNotZero = comb::ICmpOp::create (builder, loc, comb::ICmpPredicate::ne,
377+ value, zero, false );
378+ auto result = comb::AndOp::create (builder, loc, isOneHot0, isNotZero);
379+ return castToMoore (result);
380+ }
381+
360382 default :
361383 return Value{};
362384 }
363385}
364386
387+ static Value getIsUnknown (OpBuilder &builder, Location loc, Value value,
388+ moore::IntType valTy, MLIRContext *ctx) {
389+ Value bitVal = value;
390+ if (valTy.getWidth () > 1 ) {
391+ auto mooreI1Type = moore::IntType::get (ctx, 1 , valTy.getDomain ());
392+ bitVal = moore::ReduceXorOp::create (builder, loc, mooreI1Type, value);
393+ }
394+
395+ auto xType = moore::IntType::get (ctx, 1 , moore::Domain::FourValued);
396+ auto xValue = FVInt::getAllX (1 );
397+ auto xConst = moore::ConstantOp::create (builder, loc, xType, xValue);
398+
399+ return moore::CaseEqOp::create (builder, loc, bitVal, xConst).getResult ();
400+ }
401+
365402Value Context::convertAssertionCallExpression (
366403 const slang::ast::CallExpression &expr,
367404 const slang::ast::CallExpression::SystemCallInfo &info, Location loc) {
@@ -421,19 +458,46 @@ Value Context::convertAssertionCallExpression(
421458 // would have already been converted to an integer type rather than bool
422459 // type as here.
423460 if (subroutine.knownNameId == slang::parsing::KnownSystemName::IsUnknown) {
424- Value bitVal = value;
425- if (valTy.getWidth () > 1 ) {
426- auto mooreI1Type =
427- moore::IntType::get (getContext (), 1 , valTy.getDomain ());
428- bitVal = moore::ReduceXorOp::create (builder, loc, mooreI1Type, value);
429- }
430-
431- auto xType =
432- moore::IntType::get (getContext (), 1 , moore::Domain::FourValued);
433- auto xValue = FVInt::getAllX (1 );
434- auto xConst = moore::ConstantOp::create (builder, loc, xType, xValue);
461+ return getIsUnknown (builder, loc, value, valTy, getContext ());
462+ }
435463
436- return moore::CaseEqOp::create (builder, loc, bitVal, xConst).getResult ();
464+ // OneHot/OneHot0 are handled both here and below.
465+ if (subroutine.knownNameId == slang::parsing::KnownSystemName::OneHot ||
466+ subroutine.knownNameId == slang::parsing::KnownSystemName::OneHot0) {
467+ if (valTy.getDomain () == Domain::FourValued) {
468+ // In SystemVerilog, these system only returns 1b1 if the expression is
469+ // fully known and the condition is met. So if any x or y bits, then
470+ // these must return 1'b0.
471+
472+ // Detect if input contain unknown bits.
473+ Value isUnknownMoore =
474+ getIsUnknown (builder, loc, value, valTy, getContext ());
475+ Value isUnknown =
476+ builder.createOrFold <moore::ToBuiltinIntOp>(loc, isUnknownMoore);
477+
478+ Value coerced = builder.createOrFold <moore::LogicToIntOp>(loc, value);
479+ Value state2IntVal =
480+ builder.createOrFold <moore::ToBuiltinIntOp>(loc, coerced);
481+ if (!state2IntVal)
482+ return {};
483+
484+ auto systemResult = this ->convertAssertionSystemCallArity1 (
485+ subroutine, loc, state2IntVal, originalType, clockVal);
486+ if (failed (systemResult) || !*systemResult)
487+ return {};
488+ Value onehot2state = *systemResult;
489+
490+ // Squash to 0 if unknown bits exist.
491+ Value onehot2stateBuiltin = convertToI1 (onehot2state);
492+ Value zeroBuiltin =
493+ hw::ConstantOp::create (builder, loc, builder.getI1Type (), 0 );
494+ Value resultBuiltin = builder.create <comb::MuxOp>(
495+ loc, isUnknown, zeroBuiltin, onehot2stateBuiltin);
496+
497+ Value finalResult =
498+ moore::FromBuiltinIntOp::create (builder, loc, resultBuiltin);
499+ return moore::IntToLogicOp::create (builder, loc, finalResult);
500+ }
437501 }
438502
439503 // If the value is four-valued, we need to map it to two-valued before we
0 commit comments