From 2d8b2f4edde62381d2943bb2b9a52bd3dd420fb6 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 23 Jun 2017 00:28:05 -0700 Subject: [PATCH] ReduceOthers: remove constants from the balanced AND tree --- src/main/scala/regmapper/RegMapper.scala | 9 ++--- src/main/scala/util/ReduceOthers.scala | 45 +++++++++++++++++++----- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/main/scala/regmapper/RegMapper.scala b/src/main/scala/regmapper/RegMapper.scala index 1cb9638b..862df684 100644 --- a/src/main/scala/regmapper/RegMapper.scala +++ b/src/main/scala/regmapper/RegMapper.scala @@ -135,11 +135,12 @@ object RegMapper 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_wiready, f_wovalid) = field.write.fn(wivalid(i) && wimask, woready(i) && womask, data(high, low)) + def litOR(x: Bool, y: Bool) = if (x.isLit && x.litValue == 1) Bool(true) else x || y // Add this field to the ready-valid signals for the register - rifire(reg) = (rivalid(i), f_riready || !rimask) +: rifire(reg) - wifire(reg) = (wivalid(i), f_wiready || !wimask) +: wifire(reg) - rofire(reg) = (roready(i), f_rovalid || !romask) +: rofire(reg) - wofire(reg) = (woready(i), f_wovalid || !womask) +: wofire(reg) + rifire(reg) = (rivalid(i), litOR(f_riready, !rimask)) +: rifire(reg) + wifire(reg) = (wivalid(i), litOR(f_wiready, !wimask)) +: wifire(reg) + rofire(reg) = (roready(i), litOR(f_rovalid, !romask)) +: rofire(reg) + wofire(reg) = (woready(i), litOR(f_wovalid, !womask)) +: wofire(reg) dataOut(reg) = dataOut(reg) | ((f_data << low) & (~UInt(0, width = high+1))) } diff --git a/src/main/scala/util/ReduceOthers.scala b/src/main/scala/util/ReduceOthers.scala index 7084a7a4..6dec6e1c 100644 --- a/src/main/scala/util/ReduceOthers.scala +++ b/src/main/scala/util/ReduceOthers.scala @@ -1,4 +1,4 @@ -// See LICENSE.Berkeley for license details. +// See LICENSE.SiFive for license details. package util import Chisel._ @@ -7,16 +7,29 @@ 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] = { - if (x.size <= 1) { - Seq.fill(x.size) { Bool(true) } - } else if (x.size <= 3) { - Seq.tabulate(x.size) { i => - (x.take(i) ++ x.drop(i+1)).reduce(_ && _) + 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 { - val half = ReduceOthers(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) + var (out, all) = helper(variables) + x.map { b => + if (b.isLit) { + all + } else { + val sel = out.head + out = out.tail + sel + } } } } @@ -24,4 +37,18 @@ object ReduceOthers { 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) + } + } }