Skip to content

[FIRRTL] Chisel generates FIRRTL which fails new Cat signedness check #8618

@tymcauley

Description

@tymcauley

I was trying the new firtool-1.123.0 release, and am running into an issue with the FIRRTL generated by RocketChip, and its interaction with a new check added in #8557. The code in question is here:

FIRRTLType CatPrimOp::inferReturnType(ValueRange operands, DictionaryAttr attrs,
OpaqueProperties properties,
mlir::RegionRange regions,
std::optional<Location> loc) {
// If no operands, return a 0-bit UInt
if (operands.empty())
return UIntType::get(attrs.getContext(), 0);
// Check that all operands are Int types with same signedness
bool isSigned = type_isa<SIntType>(operands[0].getType());
for (auto operand : operands) {
auto type = type_dyn_cast<IntType>(operand.getType());
if (!type)
return emitInferRetTypeError(loc, "all operands must be Int type");
if (type.isSigned() != isSigned)
return emitInferRetTypeError(loc,
"all operands must have same signedness");
}

I'm getting this error message:

generators/rocket-chip/src/main/scala/rocket/RocketCore.scala:1385:8: error: all operands must have same signedness
generators/rocket-chip/src/main/scala/rocket/RocketCore.scala:1385:8: error: 'firrtl.cat' op failed to infer returned types
generators/rocket-chip/src/main/scala/rocket/RocketCore.scala:1385:8: note: see current operation: %1737 = "firrtl.cat"(%1697, %1702, %1709, %1719, %1722, %1731, %1736) {name = "_ex_imm_T"} : (!firrtl.sint<1>, !firrtl.sint<11>, !firrtl.sint<8>, !firrtl.sint<1>, !firrtl.uint<6>, !firrtl.uint<4>, !firrtl.uint<1>) -> !firrtl.uint<32>

The Chisel code which causes this issue can be found here: https://github.com/chipsalliance/rocket-chip/blob/c357a0f32ecec9ee046ca1d6378c21ec7fec179b/src/main/scala/rocket/RocketCore.scala#L1369-L1387

I'm on Chisel 7.0.0-RC1+37-f8a2dec3-SNAPSHOT.

Is this a situation where Chisel is generating illegal FIRRTL? Or a situation where the new variadic form of firrtl.cat is interacting with a weird edge-case in FIRRTL? The FIRRTL Spec says that the cat function has two legal signatures: (UInt, UInt) -> SInt or (SInt, SInt) -> UInt. I can imagine that, since each two-operand cat generates a UInt, so long as you create the appropriate tree of cat operators, you can get a legal cat result from many arguments which have mixed signedness. For example: cat(cat(SInt, SInt), UInt) -> cat(UInt, UInt) -> UInt. But if you fold this into a 3-input cat, you get cat(SInt, SInt, UInt) which fails this check.

Any idea how to resolve this?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions