简体   繁体   中英

Override/Overload operator with type parameter in Scala/Chisel

I am using Chisel but really this is a Scala problem. What I am trying to do is to override the > operator for derived objects. Considering the following classes:

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)
}

Then I would like to build a generic comparator for any record type derived from 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 
}

It is OK for me to use

Comparator(new Record)

but it fails when I try

Comparator(new RecordIndexed)

It passes compiler but the > operator is always the one from Record rather than the one from RecordIndexed.

I kind of understand why, as the > is overload rather than override. According to the type T in Comparator, the compiler would statically choose the > from Record.

How can I work around this and make Scala choose the overloaded? I think a typed trait is a way to go, but totally failed to figure out how.

Copied from an edit to the question by @wei-song:

According to suggestion from @dveim, I tried type class, finally it works:

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) 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM