@@ -38,6 +38,30 @@ static FVInt convertSVIntToFVInt(const slang::SVInt &svint) {
3838 return FVInt (APInt (svint.getBitWidth (), value));
3939}
4040
41+ // / Check if a Moore integer value contains any unknown (x/z) bits.
42+ // / Returns a Moore i1 result: 1 if any bit is unknown, 0 otherwise.
43+ static Value getIsUnknown (OpBuilder &builder, Location loc, Value value,
44+ moore::IntType valTy, MLIRContext *ctx) {
45+ Value bitVal = value;
46+ if (valTy.getWidth () > 1 ) {
47+ auto mooreI1Type = moore::IntType::get (ctx, 1 , valTy.getDomain ());
48+ bitVal = moore::ReduceXorOp::create (builder, loc, mooreI1Type, value);
49+ }
50+ auto xType = moore::IntType::get (ctx, 1 , moore::Domain::FourValued);
51+ auto xConst =
52+ moore::ConstantOp::create (builder, loc, xType, FVInt::getAllX (1 ));
53+ return moore::CaseEqOp::create (builder, loc, bitVal, xConst).getResult ();
54+ }
55+
56+ // / Coerce a Moore integer value to a builtin integer, handling four-valued
57+ // / inputs by first mapping x/z to 0 via LogicToIntOp.
58+ static Value coerceToBuiltinInt (OpBuilder &builder, Location loc, Value value,
59+ moore::IntType valTy) {
60+ if (valTy.getDomain () == moore::Domain::FourValued)
61+ value = builder.createOrFold <moore::LogicToIntOp>(loc, value);
62+ return builder.createOrFold <moore::ToBuiltinIntOp>(loc, value);
63+ }
64+
4165// / Map an index into an array, with bounds `range`, to a bit offset of the
4266// / underlying bit storage. This is a dynamic version of
4367// / `slang::ConstantRange::translateIndex`.
@@ -3281,17 +3305,7 @@ Value Context::convertSystemCall(
32813305 mlir::emitError (loc) << " expected integer argument for `$isunknown`" ;
32823306 return {};
32833307 }
3284- Value bitVal = value;
3285- if (valTy.getWidth () > 1 ) {
3286- auto mooreI1Type =
3287- moore::IntType::get (getContext (), 1 , valTy.getDomain ());
3288- bitVal = moore::ReduceXorOp::create (builder, loc, mooreI1Type, value);
3289- }
3290- auto xType =
3291- moore::IntType::get (getContext (), 1 , moore::Domain::FourValued);
3292- auto xValue = FVInt::getAllX (1 );
3293- auto xConst = moore::ConstantOp::create (builder, loc, xType, xValue);
3294- return moore::CaseEqOp::create (builder, loc, bitVal, xConst).getResult ();
3308+ return getIsUnknown (builder, loc, value, valTy, getContext ());
32953309 }
32963310
32973311 if (nameId == ksn::OneHot0 || nameId == ksn::OneHot) {
@@ -3310,30 +3324,14 @@ Value Context::convertSystemCall(
33103324 // contains any unknown (x/z) bits. Detect and squash if four-valued.
33113325 Value isUnknown;
33123326 if (valTy.getDomain () == Domain::FourValued) {
3313- Value bitVal = value;
3314- if (valTy.getWidth () > 1 ) {
3315- auto mooreI1Type =
3316- moore::IntType::get (getContext (), 1 , valTy.getDomain ());
3317- bitVal = moore::ReduceXorOp::create (builder, loc, mooreI1Type, value);
3318- }
3319- auto xType =
3320- moore::IntType::get (getContext (), 1 , moore::Domain::FourValued);
3321- auto xConst =
3322- moore::ConstantOp::create (builder, loc, xType, FVInt::getAllX (1 ));
33233327 Value isUnknownMoore =
3324- moore::CaseEqOp::create (builder, loc, bitVal, xConst). getResult ( );
3328+ getIsUnknown (builder, loc, value, valTy, getContext () );
33253329 isUnknown =
33263330 builder.createOrFold <moore::ToBuiltinIntOp>(loc, isUnknownMoore);
33273331 }
33283332
33293333 // Coerce four-valued input to two-valued for the comb ops.
3330- Value intVal;
3331- if (valTy.getDomain () == Domain::FourValued) {
3332- Value coerced = builder.createOrFold <moore::LogicToIntOp>(loc, value);
3333- intVal = builder.createOrFold <moore::ToBuiltinIntOp>(loc, coerced);
3334- } else {
3335- intVal = builder.createOrFold <moore::ToBuiltinIntOp>(loc, value);
3336- }
3334+ Value intVal = coerceToBuiltinInt (builder, loc, value, valTy);
33373335
33383336 // Compute onehot0: (value & (value - 1)) == 0
33393337 auto one = hw::ConstantOp::create (builder, loc, intVal.getType (), 1 );
@@ -3350,22 +3348,15 @@ Value Context::convertSystemCall(
33503348 result = comb::AndOp::create (builder, loc, result, isNotZero);
33513349 }
33523350
3353- // Wrap back into Moore type.
3354- result = moore::FromBuiltinIntOp::create (builder, loc, result);
3355-
33563351 // If four-valued, squash to 0 when unknown bits exist.
33573352 if (isUnknown) {
3358- Value resultI1 = convertToI1 (result);
33593353 Value zeroI1 =
33603354 hw::ConstantOp::create (builder, loc, builder.getI1Type (), 0 );
3361- Value squashed =
3362- comb::MuxOp::create (builder, loc, isUnknown, zeroI1, resultI1);
3363- Value squashedMoore =
3364- moore::FromBuiltinIntOp::create (builder, loc, squashed);
3365- return moore::IntToLogicOp::create (builder, loc, squashedMoore)
3366- .getResult ();
3355+ result = comb::MuxOp::create (builder, loc, isUnknown, zeroI1, result);
3356+ Value resultMoore = moore::FromBuiltinIntOp::create (builder, loc, result);
3357+ return moore::IntToLogicOp::create (builder, loc, resultMoore).getResult ();
33673358 }
3368- return result;
3359+ return moore::FromBuiltinIntOp::create (builder, loc, result) ;
33693360 }
33703361
33713362 if (nameId == ksn::CountOnes) {
@@ -3380,13 +3371,7 @@ Value Context::convertSystemCall(
33803371 }
33813372
33823373 // Coerce four-valued input to two-valued for the comb ops.
3383- Value intVal;
3384- if (valTy.getDomain () == Domain::FourValued) {
3385- Value coerced = builder.createOrFold <moore::LogicToIntOp>(loc, value);
3386- intVal = builder.createOrFold <moore::ToBuiltinIntOp>(loc, coerced);
3387- } else {
3388- intVal = builder.createOrFold <moore::ToBuiltinIntOp>(loc, value);
3389- }
3374+ Value intVal = coerceToBuiltinInt (builder, loc, value, valTy);
33903375
33913376 // Popcount: extract each bit, zero-extend to result width, and sum.
33923377 auto builtinIntTy = cast<IntegerType>(intVal.getType ());
0 commit comments