blob: 88543a0137f99b32798137ea21582b347bfed762 [file] [log] [blame]
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package kelvin
import chisel3._
import chisel3.util._
import bus.AxiMasterIO
import common._
class CoreAxiSlaveMux(p: Parameters, regions: Seq[MemoryRegion], sourceCount: Int) extends Module {
val portCount = regions.length
val io = IO(new Bundle {
val axi_slave = Vec(sourceCount, Flipped(new AxiMasterIO(p.axi2AddrBits, p.axi2DataBits, p.axi2IdBits)))
val ports = Vec(portCount, new AxiMasterIO(p.axi2AddrBits, p.axi2DataBits, p.axi2IdBits))
})
val portTieOff = 0.U.asTypeOf(io.ports(0))
val sourceTieOff = 0.U.asTypeOf(io.axi_slave(0))
val readTarget = RegInit(0.U(portCount.W))
val readSource = RegInit(0.U(sourceCount.W))
val readAddrValids = VecInit(io.axi_slave.map(_.read.addr.valid)).asUInt
when (readAddrValids.orR && !readTarget.orR) {
val source = PriorityEncoderOH(readAddrValids)
readSource := source
val contains = VecInit(regions.map(_.contains(io.axi_slave(OHToUInt(source)).read.addr.bits.addr))).asUInt
assert(PopCount(contains) <= 1.U)
readTarget := contains
}
for (i <- 0 until portCount) {
when (readTarget(i)) {
io.ports(i).read.addr <> io.axi_slave(OHToUInt(readSource)).read.addr
io.ports(i).read.addr.bits.addr := io.axi_slave(OHToUInt(readSource)).read.addr.bits.addr & ~regions(i).memStart.U(p.fetchAddrBits.W)
io.axi_slave(OHToUInt(readSource)).read.data <> io.ports(i).read.data
} .otherwise {
io.ports(i).read.addr <> portTieOff.read.addr
portTieOff.read.data <> io.ports(i).read.data
}
}
when (io.axi_slave(OHToUInt(readSource)).read.data.fire && io.axi_slave(OHToUInt(readSource)).read.data.bits.last) {
readTarget := 0.U(portCount.W)
readSource := 0.U(sourceCount.W)
}
val writeTarget = RegInit(0.U(portCount.W))
val writeSource = RegInit(0.U(sourceCount.W))
val writeAddrValids = VecInit(io.axi_slave.map(_.write.addr.valid)).asUInt
when (writeAddrValids.orR && !writeTarget.orR) {
val source = PriorityEncoderOH(writeAddrValids)
writeSource := source
val contains = VecInit(regions.map(_.contains(io.axi_slave(OHToUInt(source)).write.addr.bits.addr))).asUInt
assert(PopCount(contains) <= 1.U)
writeTarget := contains
}
for (i <- 0 until portCount) {
when (writeTarget(i)) {
io.ports(i).write.addr <> io.axi_slave(OHToUInt(writeSource)).write.addr
io.ports(i).write.addr.bits.addr := io.axi_slave(OHToUInt(writeSource)).write.addr.bits.addr & ~regions(i).memStart.U(p.fetchAddrBits.W)
io.ports(i).write.data <> io.axi_slave(OHToUInt(writeSource)).write.data
io.axi_slave(OHToUInt(writeSource)).write.resp <> io.ports(i).write.resp
} .otherwise {
io.ports(i).write.addr <> portTieOff.write.addr
io.ports(i).write.data <> portTieOff.write.data
portTieOff.write.resp <> io.ports(i).write.resp
}
}
when (io.axi_slave(OHToUInt(writeSource)).write.resp.fire) {
writeTarget := 0.U(portCount.W)
writeSource := 0.U(sourceCount.W)
}
for (i <- 0 until sourceCount) {
io.axi_slave(i).write.addr.ready :=
Mux(writeTarget.orR && OHToUInt(writeSource) === i.U,
io.ports(OHToUInt(writeTarget)).write.addr.ready, false.B)
io.axi_slave(i).write.data.ready :=
Mux(writeTarget.orR && OHToUInt(writeSource) === i.U,
io.ports(OHToUInt(writeTarget)).write.data.ready, false.B)
io.axi_slave(i).write.resp.valid :=
Mux(writeTarget.orR && OHToUInt(writeSource) === i.U,
io.ports(OHToUInt(writeTarget)).write.resp.valid, false.B)
io.axi_slave(i).write.resp.bits.id :=
Mux(writeTarget.orR && OHToUInt(writeSource) === i.U,
io.ports(OHToUInt(writeTarget)).write.resp.bits.id, 0.U)
io.axi_slave(i).write.resp.bits.resp :=
Mux(writeTarget.orR && OHToUInt(writeSource) === i.U,
io.ports(OHToUInt(writeTarget)).write.resp.bits.resp, 0.U)
io.axi_slave(i).read.addr.ready :=
Mux(readTarget.orR && OHToUInt(readSource) === i.U,
io.ports(OHToUInt(readTarget)).read.addr.ready, false.B)
io.axi_slave(i).read.data.valid :=
Mux(readTarget.orR && OHToUInt(readSource) === i.U,
io.ports(OHToUInt(readTarget)).read.data.valid, false.B)
io.axi_slave(i).read.data.bits :=
Mux(readTarget.orR && OHToUInt(readSource) === i.U,
io.ports(OHToUInt(readTarget)).read.data.bits, 0.U.asTypeOf(io.axi_slave(i).read.data.bits))
}
}