tilelink2 RegisterRouter: support undefZero
This commit is contained in:
		| @@ -2,8 +2,8 @@ | |||||||
|  |  | ||||||
| package uncore.tilelink2 | package uncore.tilelink2 | ||||||
|  |  | ||||||
| import Chisel._ | import chisel3._ | ||||||
| import chisel3.util.{Irrevocable, IrrevocableIO} | import chisel3.util._ | ||||||
|  |  | ||||||
| // A bus agnostic register interface to a register-based device | // A bus agnostic register interface to a register-based device | ||||||
|  |  | ||||||
| @@ -36,6 +36,23 @@ object RegMapper | |||||||
|     regmap.combinations(2).foreach { case Seq((reg1, _), (reg2, _)) => |     regmap.combinations(2).foreach { case Seq((reg1, _), (reg2, _)) => | ||||||
|       require (reg1 != reg2) |       require (reg1 != reg2) | ||||||
|     } |     } | ||||||
|  |     // Don't be an asshole... | ||||||
|  |     regmap.foreach { reg => require (reg._1 >= 0) } | ||||||
|  |     // Make sure registers fit | ||||||
|  |     val inParams = in.bits.params | ||||||
|  |     val inBits = inParams.indexBits | ||||||
|  |     assert (regmap.map(_._1).max < (1 << inBits)) | ||||||
|  |  | ||||||
|  |     val out = Wire(Irrevocable(new RegMapperOutput(inParams))) | ||||||
|  |     val front = Wire(Irrevocable(new RegMapperInput(inParams))) | ||||||
|  |     front.bits := in.bits | ||||||
|  |  | ||||||
|  |     // Must this device pipeline the control channel? | ||||||
|  |     val pipelined = regmap.map(_._2.map(_.pipelined)).flatten.reduce(_ || _) | ||||||
|  |     val depth = concurrency.getOrElse(if (pipelined) 1 else 0) | ||||||
|  |     require (depth >= 0) | ||||||
|  |     require (!pipelined || depth > 0) | ||||||
|  |     val back = if (depth > 0) Queue(front, depth, pipe = depth == 1) else front | ||||||
|  |  | ||||||
|     // Convert to and from Bits |     // Convert to and from Bits | ||||||
|     def toBits(x: Int, tail: List[Boolean] = List.empty): List[Boolean] = |     def toBits(x: Int, tail: List[Boolean] = List.empty): List[Boolean] = | ||||||
| @@ -44,36 +61,33 @@ object RegMapper | |||||||
|  |  | ||||||
|     // Find the minimal mask that can decide the register map |     // Find the minimal mask that can decide the register map | ||||||
|     val mask = AddressDecoder(regmap.map(_._1)) |     val mask = AddressDecoder(regmap.map(_._1)) | ||||||
|  |     val maskMatch = ~UInt(mask, width = inBits) | ||||||
|     val maskFilter = toBits(mask) |     val maskFilter = toBits(mask) | ||||||
|     val maskBits = maskFilter.filter(x => x).size |     val maskBits = maskFilter.filter(x => x).size | ||||||
|  |  | ||||||
|     // Calculate size and indexes into the register map |     // Calculate size and indexes into the register map | ||||||
|     val endIndex = 1 << log2Ceil(regmap.map(_._1).max+1) |  | ||||||
|     val params = RegMapperParams(log2Up(endIndex), bytes, in.bits.params.extraBits) |  | ||||||
|     val regSize = 1 << maskBits |     val regSize = 1 << maskBits | ||||||
|     def regIndexI(x: Int) = ofBits((maskFilter zip toBits(x)).filter(_._1).map(_._2)) |     def regIndexI(x: Int) = ofBits((maskFilter zip toBits(x)).filter(_._1).map(_._2)) | ||||||
|     def regIndexU(x: UInt) = if (maskBits == 0) UInt(0) else |     def regIndexU(x: UInt) = if (maskBits == 0) UInt(0) else | ||||||
|       Cat((maskFilter zip x.toBools).filter(_._1).map(_._2).reverse) |       Cat((maskFilter zip x.toBools).filter(_._1).map(_._2).reverse) | ||||||
|  |  | ||||||
|  |     // Protection flag for undefined registers | ||||||
|  |     val iRightReg = Array.fill(regSize) { Bool(true) } | ||||||
|  |     val oRightReg = Array.fill(regSize) { Bool(true) } | ||||||
|  |  | ||||||
|     // Flatten the regmap into (RegIndex:Int, Offset:Int, field:RegField) |     // Flatten the regmap into (RegIndex:Int, Offset:Int, field:RegField) | ||||||
|     val flat = regmap.map { case (reg, fields) => |     val flat = regmap.map { case (reg, fields) => | ||||||
|       val offsets = fields.scanLeft(0)(_ + _.width).init |       val offsets = fields.scanLeft(0)(_ + _.width).init | ||||||
|       val index = regIndexI(reg) |       val index = regIndexI(reg) | ||||||
|  |       val uint = UInt(reg, width = inBits) | ||||||
|  |       if (undefZero) { | ||||||
|  |         iRightReg(index) = ((front.bits.index ^ uint) & maskMatch) === UInt(0) | ||||||
|  |         oRightReg(index) = ((back .bits.index ^ uint) & maskMatch) === UInt(0) | ||||||
|  |       } | ||||||
|       // println("mapping 0x%x -> 0x%x for 0x%x/%d".format(reg, index, mask, maskBits)) |       // println("mapping 0x%x -> 0x%x for 0x%x/%d".format(reg, index, mask, maskBits)) | ||||||
|       (offsets zip fields) map { case (o, f) => (index, o, f) } |       (offsets zip fields) map { case (o, f) => (index, o, f) } | ||||||
|     }.flatten |     }.flatten | ||||||
|  |  | ||||||
|     val out = Wire(Irrevocable(new RegMapperOutput(params))) |  | ||||||
|     val front = Wire(Irrevocable(new RegMapperInput(params))) |  | ||||||
|     front.bits := in.bits |  | ||||||
|  |  | ||||||
|     // Must this device pipeline the control channel? |  | ||||||
|     val pipelined = flat.map(_._3.pipelined).reduce(_ || _) |  | ||||||
|     val depth = concurrency.getOrElse(if (pipelined) 1 else 0) |  | ||||||
|     require (depth >= 0) |  | ||||||
|     require (!pipelined || depth > 0) |  | ||||||
|     val back = if (depth > 0) Queue(front, depth, pipe = depth == 1) else front |  | ||||||
|  |  | ||||||
|     // 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())) | ||||||
| @@ -122,10 +136,10 @@ object RegMapper | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Is the selected register ready? |     // Is the selected register ready? | ||||||
|     val rifireMux = Vec(rifire.map(_.reduce(_ && _))) |     val rifireMux = Vec(rifire.zipWithIndex.map { case (seq, i) => !iRightReg(i) || seq.reduce(_ && _)}) | ||||||
|     val wifireMux = Vec(wifire.map(_.reduce(_ && _))) |     val wifireMux = Vec(wifire.zipWithIndex.map { case (seq, i) => !iRightReg(i) || seq.reduce(_ && _)}) | ||||||
|     val rofireMux = Vec(rofire.map(_.reduce(_ && _))) |     val rofireMux = Vec(rofire.zipWithIndex.map { case (seq, i) => !oRightReg(i) || seq.reduce(_ && _)}) | ||||||
|     val wofireMux = Vec(wofire.map(_.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 iready = Mux(front.bits.read, rifireMux(iindex), wifireMux(iindex)) |     val iready = Mux(front.bits.read, rifireMux(iindex), wifireMux(iindex)) | ||||||
| @@ -138,8 +152,8 @@ object RegMapper | |||||||
|     out.valid   := back.valid  && oready |     out.valid   := back.valid  && oready | ||||||
|  |  | ||||||
|     // Which register is touched? |     // Which register is touched? | ||||||
|     val frontSel = UIntToOH(iindex) |     val frontSel = UIntToOH(iindex) & Cat(iRightReg.reverse) | ||||||
|     val backSel  = UIntToOH(oindex) |     val backSel  = UIntToOH(oindex) & Cat(oRightReg.reverse) | ||||||
|  |  | ||||||
|     // Include the per-register one-hot selected criteria |     // Include the per-register one-hot selected criteria | ||||||
|     for (reg <- 0 until regSize) { |     for (reg <- 0 until regSize) { | ||||||
| @@ -159,9 +173,9 @@ object RegMapper | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     out.bits.read  := back.bits.read |     out.bits.read  := back.bits.read | ||||||
|     out.bits.data  := Vec(dataOut)(oindex) |     out.bits.data  := Mux(Vec(oRightReg)(oindex), Vec(dataOut)(oindex), UInt(0)) | ||||||
|     out.bits.extra := back.bits.extra |     out.bits.extra := back.bits.extra | ||||||
|  |  | ||||||
|     (endIndex, out) |     out | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -27,7 +27,7 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB | |||||||
|     val (sourceEnd, sourceOff) = (edge.bundle.sourceBits + sizeEnd, sizeEnd) |     val (sourceEnd, sourceOff) = (edge.bundle.sourceBits + sizeEnd, sizeEnd) | ||||||
|     val (addrLoEnd, addrLoOff) = (log2Up(beatBytes)      + sourceEnd, sourceEnd) |     val (addrLoEnd, addrLoOff) = (log2Up(beatBytes)      + sourceEnd, sourceEnd) | ||||||
|  |  | ||||||
|     val params = RegMapperParams(log2Up(address.mask+1), beatBytes, addrLoEnd) |     val params = RegMapperParams(log2Up((address.mask+1)/beatBytes), beatBytes, addrLoEnd) | ||||||
|     val in = Wire(Decoupled(new RegMapperInput(params))) |     val in = Wire(Decoupled(new RegMapperInput(params))) | ||||||
|     in.bits.read  := a.bits.opcode === TLMessages.Get |     in.bits.read  := a.bits.opcode === TLMessages.Get | ||||||
|     in.bits.index := a.bits.addr_hi |     in.bits.index := a.bits.addr_hi | ||||||
| @@ -36,10 +36,7 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB | |||||||
|     in.bits.extra := Cat(edge.addr_lo(a.bits), a.bits.source, a.bits.size) |     in.bits.extra := Cat(edge.addr_lo(a.bits), a.bits.source, a.bits.size) | ||||||
|  |  | ||||||
|     // Invoke the register map builder |     // Invoke the register map builder | ||||||
|     val (endIndex, out) = RegMapper(beatBytes, concurrency, undefZero, in, mapping:_*) |     val out = RegMapper(beatBytes, concurrency, undefZero, in, mapping:_*) | ||||||
|  |  | ||||||
|     // All registers must fit inside the device address space |  | ||||||
|     require (address.mask >= (endIndex-1)*beatBytes) |  | ||||||
|  |  | ||||||
|     // No flow control needed |     // No flow control needed | ||||||
|     in.valid  := a.valid |     in.valid  := a.valid | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user