Merge pull request #815 from freechipsproject/reduce-others
Reduce others
This commit is contained in:
commit
9bea7c1c58
@ -106,18 +106,14 @@ object RegMapper
|
|||||||
// Forward declaration of all flow control signals
|
// Forward declaration of all flow control signals
|
||||||
val rivalid = Wire(Vec(flat.size, Bool()))
|
val rivalid = Wire(Vec(flat.size, Bool()))
|
||||||
val wivalid = Wire(Vec(flat.size, Bool()))
|
val wivalid = Wire(Vec(flat.size, Bool()))
|
||||||
val riready = Wire(Vec(flat.size, Bool()))
|
|
||||||
val wiready = Wire(Vec(flat.size, Bool()))
|
|
||||||
val rovalid = Wire(Vec(flat.size, Bool()))
|
|
||||||
val wovalid = Wire(Vec(flat.size, Bool()))
|
|
||||||
val roready = Wire(Vec(flat.size, Bool()))
|
val roready = Wire(Vec(flat.size, Bool()))
|
||||||
val woready = Wire(Vec(flat.size, Bool()))
|
val woready = Wire(Vec(flat.size, Bool()))
|
||||||
|
|
||||||
// Per-register list of all control signals needed for data to flow
|
// Per-register list of all control signals needed for data to flow
|
||||||
val rifire = Array.tabulate(regSize) { i => Seq(Bool(true)) }
|
val rifire = Array.fill(regSize) { Nil:List[(Bool, Bool)] }
|
||||||
val wifire = Array.tabulate(regSize) { i => Seq(Bool(true)) }
|
val wifire = Array.fill(regSize) { Nil:List[(Bool, Bool)] }
|
||||||
val rofire = Array.tabulate(regSize) { i => Seq(Bool(true)) }
|
val rofire = Array.fill(regSize) { Nil:List[(Bool, Bool)] }
|
||||||
val wofire = Array.tabulate(regSize) { i => Seq(Bool(true)) }
|
val wofire = Array.fill(regSize) { Nil:List[(Bool, Bool)] }
|
||||||
|
|
||||||
// The output values for each register
|
// The output values for each register
|
||||||
val dataOut = Array.tabulate(regSize) { _ => UInt(0) }
|
val dataOut = Array.tabulate(regSize) { _ => UInt(0) }
|
||||||
@ -139,24 +135,35 @@ object RegMapper
|
|||||||
val data = if (field.write.combinational) back.bits.data else front.bits.data
|
val data = if (field.write.combinational) back.bits.data else front.bits.data
|
||||||
val (f_riready, f_rovalid, f_data) = field.read.fn(rivalid(i) && rimask, roready(i) && romask)
|
val (f_riready, f_rovalid, f_data) = field.read.fn(rivalid(i) && rimask, roready(i) && romask)
|
||||||
val (f_wiready, f_wovalid) = field.write.fn(wivalid(i) && wimask, woready(i) && womask, data(high, low))
|
val (f_wiready, f_wovalid) = field.write.fn(wivalid(i) && wimask, woready(i) && womask, data(high, low))
|
||||||
riready(i) := f_riready || !rimask
|
def litOR(x: Bool, y: Bool) = if (x.isLit && x.litValue == 1) Bool(true) else x || y
|
||||||
wiready(i) := f_wiready || !wimask
|
// Add this field to the ready-valid signals for the register
|
||||||
rovalid(i) := f_rovalid || !romask
|
rifire(reg) = (rivalid(i), litOR(f_riready, !rimask)) +: rifire(reg)
|
||||||
wovalid(i) := f_wovalid || !womask
|
wifire(reg) = (wivalid(i), litOR(f_wiready, !wimask)) +: wifire(reg)
|
||||||
rifire(reg) = riready(i) +: rifire(reg)
|
rofire(reg) = (roready(i), litOR(f_rovalid, !romask)) +: rofire(reg)
|
||||||
wifire(reg) = wiready(i) +: wifire(reg)
|
wofire(reg) = (woready(i), litOR(f_wovalid, !womask)) +: wofire(reg)
|
||||||
rofire(reg) = rovalid(i) +: rofire(reg)
|
dataOut(reg) = dataOut(reg) | ((f_data << low) & (~UInt(0, width = high+1)))
|
||||||
wofire(reg) = wovalid(i) +: wofire(reg)
|
|
||||||
dataOut(reg) = dataOut(reg) | ((f_data << low) & (~UInt(0, width = high+1)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is the selected register ready?
|
// Which register is touched?
|
||||||
val rifireMux = Vec(rifire.zipWithIndex.map { case (seq, i) => !iRightReg(i) || seq.reduce(_ && _)})
|
|
||||||
val wifireMux = Vec(wifire.zipWithIndex.map { case (seq, i) => !iRightReg(i) || seq.reduce(_ && _)})
|
|
||||||
val rofireMux = Vec(rofire.zipWithIndex.map { case (seq, i) => !oRightReg(i) || seq.reduce(_ && _)})
|
|
||||||
val wofireMux = Vec(wofire.zipWithIndex.map { case (seq, i) => !oRightReg(i) || seq.reduce(_ && _)})
|
|
||||||
val iindex = regIndexU(front.bits.index)
|
val iindex = regIndexU(front.bits.index)
|
||||||
val oindex = regIndexU(back .bits.index)
|
val oindex = regIndexU(back .bits.index)
|
||||||
|
val frontSel = UIntToOH(iindex).toBools
|
||||||
|
val backSel = UIntToOH(oindex).toBools
|
||||||
|
|
||||||
|
// Compute: is the selected register ready? ... and cross-connect all ready-valids
|
||||||
|
def mux(valid: Bool, select: Seq[Bool], guard: Seq[Bool], flow: Seq[Seq[(Bool, Bool)]]): Vec[Bool] =
|
||||||
|
Vec(((select zip guard) zip flow).map { case ((s, g), f) =>
|
||||||
|
val out = Wire(Bool())
|
||||||
|
util.ReduceOthers((out, valid && s && g) +: f)
|
||||||
|
out || !g
|
||||||
|
})
|
||||||
|
|
||||||
|
// Include the per-register one-hot selected criteria
|
||||||
|
val rifireMux = mux(in.valid && front.ready && front.bits.read, frontSel, iRightReg, rifire)
|
||||||
|
val wifireMux = mux(in.valid && front.ready && !front.bits.read, frontSel, iRightReg, wifire)
|
||||||
|
val rofireMux = mux(back.valid && out.ready && back .bits.read, backSel, oRightReg, rofire)
|
||||||
|
val wofireMux = mux(back.valid && out.ready && !back .bits.read, backSel, oRightReg, wofire)
|
||||||
|
|
||||||
val iready = Mux(front.bits.read, rifireMux(iindex), wifireMux(iindex))
|
val iready = Mux(front.bits.read, rifireMux(iindex), wifireMux(iindex))
|
||||||
val oready = Mux(back .bits.read, rofireMux(oindex), wofireMux(oindex))
|
val oready = Mux(back .bits.read, rofireMux(oindex), wofireMux(oindex))
|
||||||
|
|
||||||
@ -166,27 +173,6 @@ object RegMapper
|
|||||||
back.ready := out.ready && oready
|
back.ready := out.ready && oready
|
||||||
out.valid := back.valid && oready
|
out.valid := back.valid && oready
|
||||||
|
|
||||||
// Which register is touched?
|
|
||||||
val frontSel = UIntToOH(iindex) & Cat(iRightReg.reverse)
|
|
||||||
val backSel = UIntToOH(oindex) & Cat(oRightReg.reverse)
|
|
||||||
|
|
||||||
// Include the per-register one-hot selected criteria
|
|
||||||
for (reg <- 0 until regSize) {
|
|
||||||
rifire(reg) = (in.valid && front.ready && front.bits.read && frontSel(reg)) +: rifire(reg)
|
|
||||||
wifire(reg) = (in.valid && front.ready && !front.bits.read && frontSel(reg)) +: wifire(reg)
|
|
||||||
rofire(reg) = (back.valid && out.ready && back .bits.read && backSel (reg)) +: rofire(reg)
|
|
||||||
wofire(reg) = (back.valid && out.ready && !back .bits.read && backSel (reg)) +: wofire(reg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect the field's ivalid and oready
|
|
||||||
for (i <- 0 until flat.size) {
|
|
||||||
val (reg, _, _ ) = flat(i)
|
|
||||||
rivalid(i) := rifire(reg).filter(_ ne riready(i)).reduce(_ && _)
|
|
||||||
wivalid(i) := wifire(reg).filter(_ ne wiready(i)).reduce(_ && _)
|
|
||||||
roready(i) := rofire(reg).filter(_ ne rovalid(i)).reduce(_ && _)
|
|
||||||
woready(i) := wofire(reg).filter(_ ne wovalid(i)).reduce(_ && _)
|
|
||||||
}
|
|
||||||
|
|
||||||
out.bits.read := back.bits.read
|
out.bits.read := back.bits.read
|
||||||
out.bits.data := Mux(Vec(oRightReg)(oindex), Vec(dataOut)(oindex), UInt(0))
|
out.bits.data := Mux(Vec(oRightReg)(oindex), Vec(dataOut)(oindex), UInt(0))
|
||||||
out.bits.extra := back.bits.extra
|
out.bits.extra := back.bits.extra
|
||||||
|
54
src/main/scala/util/ReduceOthers.scala
Normal file
54
src/main/scala/util/ReduceOthers.scala
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package util
|
||||||
|
import Chisel._
|
||||||
|
|
||||||
|
object ReduceOthers {
|
||||||
|
// Given a list of bools, create this output:
|
||||||
|
// out[i] = AND[j=0..out.size, j!=i] in[j]
|
||||||
|
def apply(x: Seq[Bool]): Seq[Bool] = {
|
||||||
|
val (literals, variables) = x.partition(_.isLit)
|
||||||
|
|
||||||
|
val falses = literals.count(_.litValue == 0)
|
||||||
|
if (falses > 2) {
|
||||||
|
Seq.fill(x.size) { Bool(false) }
|
||||||
|
} else if (falses == 1) {
|
||||||
|
x.map { b =>
|
||||||
|
if (b.isLit && b.litValue == 0) {
|
||||||
|
variables.foldLeft(Bool(true))(_ && _)
|
||||||
|
} else {
|
||||||
|
Bool(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var (out, all) = helper(variables)
|
||||||
|
x.map { b =>
|
||||||
|
if (b.isLit) {
|
||||||
|
all
|
||||||
|
} else {
|
||||||
|
val sel = out.head
|
||||||
|
out = out.tail
|
||||||
|
sel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Take pairs of (output_wire, input_bool)
|
||||||
|
def apply(x: Seq[(Bool, Bool)]) {
|
||||||
|
(x.map(_._1) zip apply(x.map(_._2))) foreach { case (w, x) => w := x }
|
||||||
|
}
|
||||||
|
private def helper(x: Seq[Bool]): (Seq[Bool], Bool) = {
|
||||||
|
if (x.size <= 1) {
|
||||||
|
(Seq.fill(x.size) { Bool(true) }, x.headOption.getOrElse(Bool(true)))
|
||||||
|
} else if (x.size <= 3) {
|
||||||
|
(Seq.tabulate(x.size) { i =>
|
||||||
|
(x.take(i) ++ x.drop(i+1)).reduce(_ && _)
|
||||||
|
}, x.reduce(_ && _))
|
||||||
|
} else {
|
||||||
|
val (half, all) = helper(x.grouped(2).map(_.reduce(_ && _)).toList)
|
||||||
|
(Seq.tabulate(x.size) { i =>
|
||||||
|
if ((i ^ 1) >= x.size) half(i/2) else x(i ^ 1) && half(i / 2)
|
||||||
|
}, all)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user