在Scala / Chisel中使用类型参数覆盖/重载运算符

时间:2017-02-28 11:41:43

标签: scala chisel

我正在使用Chisel,但实际上这是一个Scala问题。 我想要做的是覆盖>派生对象的运算符。 考虑以下类别:

class Record extends Bundle {
    val key = UInt(32.W)
    val data = UInt(8.W)
    def > (rhs:Record) = key > rhs.key
}

class RecordIndexed extends Record {
    val index = UInt(8.W)
    def > (rhs:RecordIndexed) = key > rhs.key || (key === rhs.key && index > rhs.index)
}

然后我想为从Record:

派生的任何记录类型构建一个通用比较器
class Comparator[T <: Record](gen: T) extends Module {
    val io = IO(new bundle {
        val a = Flipped(Valid(gen))
        val b = Flipped(Valid(gen))
        val o = Output(Bool())
    }

    io.o := io.a.valid && io.b.valid && io.a.bits > io.b.bits 
}

我可以使用

Comparator(new Record)

但是当我尝试

时它失败了
Comparator(new RecordIndexed)

它传递编译器但是&gt; operator始终是Record中的一个,而不是RecordIndexed中的一个。

我有点理解为什么,因为&gt;是过载而不是覆盖。根据比较器中的类型T,编译器将静态选择&gt;来自记录。

我如何解决这个问题并让Scala选择重载?我认为打字特质是一种方法,但完全没有弄清楚如何。

1 个答案:

答案 0 :(得分:0)

@ wei-song从编辑到问题复制:

根据@dveim的建议,我尝试了类型,最后它起作用了:

class Record extends Bundle {
    val key = UInt(32.W)
    val data = UInt(8.W)
}

class RecordIndexed extends Record {
    val index = UInt(8.W)
}

object record_operation {
    trait RecordLike[t] {
        def isLarger(l: T, r: T): Bool
    }

    object RecordLike {
        implicit object RecordLikeRecord extends RecordLike[Record] {
            def isLarger(l: Record, r: Record): Bool =
                l.key > r.key
        }

        implicit object RecordLikeRecordIndexed extends RecordLike[RecordIndexed] {
            def isLarger(l: RecordIndexed, r: RecordIndexed): Bool =
                l.key > r.key || (l.key === r.key && l.index > r.index)
        }
    }

    def larger[T](l: T, r: T)(implicit op: RecordLike[T]): Bool = op.isLarger(l, r)
}

class Comparator[T <: Record : RecordLike](gen: T) extends Module {
    val io = IO(new bundle {
        val a = Flipped(Valid(gen))
        val b = Flipped(Valid(gen))
        val o = Output(Bool())
    }
    import record_operation._
    io.o := io.a.valid && io.b.valid && larger(io.a.bits, io.b.bits) 
}