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

Posted

技术标签:

【中文标题】在 Scala/Chisel 中使用类型参数覆盖/重载运算符【英文标题】:Override/Overload operator with type parameter in Scala/Chisel 【发布时间】:2017-02-28 11:41:43 【问题描述】:

我正在使用 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)

它通过了编译器,但 > 运算符始终是 Record 中的那个,而不是 RecordIndexed 中的那个。

我有点理解为什么,因为 > 是重载而不是覆盖。根据 Comparator 中的 T 类型,编译器会静态选择 Record 中的 >。

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

【问题讨论】:

听起来你想使用类型类。你试过了吗? @dveim 没有。但是类型类看起来很有前途。今晚我会试一试。我在 Scala 方面并没有真正的经验。任何更多的提示或示例都会非常有帮助。 @dveim Typeclass 工作!非常感谢。你想提出一个简单的答案然后我可以接受。 很高兴能为您提供帮助。不要在意声誉:) 如果您有问题的解决方案,那么您可以将其发布为答案而不是编辑您的问题吗? 【参考方案1】:

从@wei-song 对问题的编辑中复制:

根据@dveim 的建议,我尝试了type class,终于成功了:

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) 

【讨论】:

以上是关于在 Scala/Chisel 中使用类型参数覆盖/重载运算符的主要内容,如果未能解决你的问题,请参考以下文章

Chisel3 - util - Pipe

Chisel3 - util - RRArbiter

Chisel3 - util - Valid

覆盖在Ada中接收类范围类型作为参数的过程

Java基础知识(重载和覆盖)

Unity - 使用正常分辨率混合参数覆盖