Merge pull request #815 from freechipsproject/reduce-others
Reduce others
This commit is contained in:
		| @@ -106,18 +106,14 @@ object RegMapper | ||||
|     // Forward declaration of all flow control signals | ||||
|     val rivalid = 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 woready = Wire(Vec(flat.size, Bool())) | ||||
|  | ||||
|     // Per-register list of all control signals needed for data to flow | ||||
|     val rifire = Array.tabulate(regSize) { i => Seq(Bool(true)) } | ||||
|     val wifire = Array.tabulate(regSize) { i => Seq(Bool(true)) } | ||||
|     val rofire = Array.tabulate(regSize) { i => Seq(Bool(true)) } | ||||
|     val wofire = Array.tabulate(regSize) { i => Seq(Bool(true)) } | ||||
|     val rifire = Array.fill(regSize) { Nil:List[(Bool, Bool)] } | ||||
|     val wifire = Array.fill(regSize) { Nil:List[(Bool, Bool)] } | ||||
|     val rofire = Array.fill(regSize) { Nil:List[(Bool, Bool)] } | ||||
|     val wofire = Array.fill(regSize) { Nil:List[(Bool, Bool)] } | ||||
|  | ||||
|     // The output values for each register | ||||
|     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 (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)) | ||||
|       riready(i) := f_riready || !rimask | ||||
|       wiready(i) := f_wiready || !wimask | ||||
|       rovalid(i) := f_rovalid || !romask | ||||
|       wovalid(i) := f_wovalid || !womask | ||||
|       rifire(reg) = riready(i) +: rifire(reg) | ||||
|       wifire(reg) = wiready(i) +: wifire(reg) | ||||
|       rofire(reg) = rovalid(i) +: rofire(reg) | ||||
|       wofire(reg) = wovalid(i) +: wofire(reg) | ||||
|       dataOut(reg) = dataOut(reg) | ((f_data  << low) & (~UInt(0, width = high+1))) | ||||
|       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), 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))) | ||||
|     } | ||||
|  | ||||
|     // Is the selected register ready? | ||||
|     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(_ && _)}) | ||||
|     // Which register is touched? | ||||
|     val iindex = regIndexU(front.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 oready = Mux(back .bits.read, rofireMux(oindex), wofireMux(oindex)) | ||||
|  | ||||
| @@ -166,27 +173,6 @@ object RegMapper | ||||
|     back.ready  := out.ready   && 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.data  := Mux(Vec(oRightReg)(oindex), Vec(dataOut)(oindex), UInt(0)) | ||||
|     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) | ||||
|     } | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user