blob: a51ef667e1a15d3713779072419808d1ccbc1c57 [file] [log] [blame]
// SPDX-FileCopyrightText: 2020 Muhammad Hadir Khan
//
// 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.
// SPDX-License-Identifier: Apache-2.0
package merl.uit.tilelink
import chisel3._
import chisel3.util.{Cat, log2Ceil}
class TLSocketM_1(M: Int)(implicit val conf:TLConfiguration) extends Module {
val io = IO(new Bundle {
val tl_h_i = Vec(M, Flipped(new TL_H2D))
val tl_h_o = Vec(M, new TL_D2H)
val tl_d_o = new TL_H2D
val tl_d_i = Flipped(new TL_D2H)
})
val STIDW = log2Ceil(M) // the bits required for identifying hosts.
val tl_h2d = Wire(Vec(M, Flipped(new TL_H2D))) // create an intermediate bundles of wire for capturing the host request
val hRequest = Wire(Vec(M, Bool())) // this bundle of wires is used to have the valid signals of all hosts.
val respReady = Wire(Vec(M, Bool()))
val respValid = Wire(Vec(M, Bool()))
for(i <- 0 until M) {
val reqid_sub = Wire(UInt(STIDW.W))
val shifted_id = Wire(UInt(conf.TL_AIW.W))
reqid_sub := i.asUInt // this will be used to identify hosts connected with the socket
shifted_id := Cat(io.tl_h_i(i).a_source((conf.TL_AIW-STIDW)-1,0), reqid_sub)
tl_h2d(i).a_valid := io.tl_h_i(i).a_valid
tl_h2d(i).a_opcode := io.tl_h_i(i).a_opcode
tl_h2d(i).a_param := io.tl_h_i(i).a_param
tl_h2d(i).a_size := io.tl_h_i(i).a_size
tl_h2d(i).a_source := shifted_id
tl_h2d(i).a_address := io.tl_h_i(i).a_address
tl_h2d(i).a_mask := io.tl_h_i(i).a_mask
tl_h2d(i).a_data := io.tl_h_i(i).a_data
tl_h2d(i).d_ready := io.tl_h_i(i).d_ready
}
for(i <- 0 until M) {
hRequest(i) := tl_h2d(i).a_valid
}
for(i <- 0 until M) {
respValid(i) := io.tl_d_i.d_valid && (io.tl_d_i.d_source(STIDW-1,0) === i.asUInt)
respReady(i) := tl_h2d(i).d_ready && (io.tl_d_i.d_source(STIDW-1,0) === i.asUInt) && io.tl_d_i.d_valid
}
val arb = Module(new Arbiter(M))
arb.io.req_i := hRequest
arb.io.ready_i := io.tl_d_i.a_ready
arb.io.data_i <> tl_h2d
io.tl_d_o.a_valid := arb.io.valid_o
io.tl_d_o.a_opcode := arb.io.data_o.a_opcode
io.tl_d_o.a_param := arb.io.data_o.a_param
io.tl_d_o.a_size := arb.io.data_o.a_size
io.tl_d_o.a_source := arb.io.data_o.a_source
io.tl_d_o.a_address := arb.io.data_o.a_address
io.tl_d_o.a_mask := arb.io.data_o.a_mask
io.tl_d_o.a_data := arb.io.data_o.a_data
io.tl_d_o.d_ready := respReady.contains(true.B) // this is to check if any wire inside the respReady bundle is true.
for(i <- 0 until M) {
io.tl_h_o(i).d_valid := respValid(i)
io.tl_h_o(i).d_opcode := io.tl_d_i.d_opcode
io.tl_h_o(i).d_param := io.tl_d_i.d_param
io.tl_h_o(i).d_size := io.tl_d_i.d_size
io.tl_h_o(i).d_source := Cat(0.U,io.tl_d_i.d_source(conf.TL_AIW-1,STIDW)) // making sure we pass the same a_source in d_source.
io.tl_h_o(i).d_sink := io.tl_d_i.d_sink
io.tl_h_o(i).d_data := io.tl_d_i.d_data
io.tl_h_o(i).d_error := io.tl_d_i.d_error
io.tl_h_o(i).a_ready := arb.io.gnt_o(i)
}
}