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.