Crossbar.scala 5.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/**************************************************************************************
* Copyright (c) 2020 Institute of Computing Technology, CAS
* Copyright (c) 2020 University of Chinese Academy of Sciences
* 
* NutShell is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2. 
* You may obtain a copy of Mulan PSL v2 at:
*             http://license.coscl.org.cn/MulanPSL2 
* 
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER 
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR 
* FIT FOR A PARTICULAR PURPOSE.  
*
* See the Mulan PSL v2 for more details.  
***************************************************************************************/

17 18 19 20 21 22 23
package bus.simplebus

import chisel3._
import chisel3.util._

import utils._

Z
Zihao Yu 已提交
24
class SimpleBusCrossbar1toN(addressSpace: List[(Long, Long)]) extends Module {
25
  val io = IO(new Bundle {
Z
Zihao Yu 已提交
26
    val in = Flipped(new SimpleBusUC)
27
    val out = Vec(addressSpace.length, new SimpleBusUC)
28 29
  })

30
  val s_idle :: s_resp :: s_error :: Nil = Enum(3)
31 32
  val state = RegInit(s_idle)

Z
Zihao Yu 已提交
33
  // select the output channel according to the address
Z
Zihao Yu 已提交
34
  val addr = io.in.req.bits.addr
Z
Zihao Yu 已提交
35
  val outSelVec = VecInit(addressSpace.map(
36
    range => (addr >= range._1.U && addr < (range._1 + range._2).U)))
Z
Zihao Yu 已提交
37 38
  val outSelIdx = PriorityEncoder(outSelVec)
  val outSel = io.out(outSelIdx)
39 40
  val outSelIdxResp = RegEnable(outSelIdx, outSel.req.fire() && (state === s_idle))
  val outSelResp = io.out(outSelIdxResp)
41
  val reqInvalidAddr = io.in.req.valid && !outSelVec.asUInt.orR
Z
Zihao Yu 已提交
42

43 44
  when(!(!io.in.req.valid || outSelVec.asUInt.orR) || !(!(io.in.req.valid && outSelVec.asUInt.andR))){printf("[ERROR] bad addr %x, time %d\n", addr, GTimer())}
  // assert(!io.in.req.valid || outSelVec.asUInt.orR, "address decode error, bad addr = 0x%x\n", addr)
Z
Zihao Yu 已提交
45
  assert(!(io.in.req.valid && outSelVec.asUInt.andR), "address decode error, bad addr = 0x%x\n", addr)
46

Z
Zihao Yu 已提交
47 48
  // bind out.req channel
  (io.out zip outSelVec).map { case (o, v) => {
Z
Zihao Yu 已提交
49 50
    o.req.bits := io.in.req.bits
    o.req.valid := v && (io.in.req.valid && (state === s_idle))
51
    o.resp.ready := v
Z
Zihao Yu 已提交
52
  }}
53

Z
Zihao Yu 已提交
54
  switch (state) {
55 56 57 58
    is (s_idle) { 
      when (outSel.req.fire()) { state := s_resp } 
      when (reqInvalidAddr) { state := s_error } 
    }
59
    is (s_resp) { when (outSelResp.resp.fire()) { state := s_idle } }
60
    is (s_error) { when(io.in.resp.fire()){ state := s_idle } }
61 62
  }

63
  io.in.resp.valid := outSelResp.resp.fire() || state === s_error
64
  io.in.resp.bits <> outSelResp.resp.bits
65
  // io.in.resp.bits.exc.get := state === s_error
66
  outSelResp.resp.ready := io.in.resp.ready
67
  io.in.req.ready := outSel.req.ready || reqInvalidAddr
68

Z
Zihao Yu 已提交
69
  Debug() {
Z
Zihao Yu 已提交
70 71
    when (state === s_idle && io.in.req.valid) {
      printf(p"${GTimer()}: xbar: in.req: ${io.in.req.bits}\n")
Z
Zihao Yu 已提交
72
    }
73

Z
Zihao Yu 已提交
74 75 76 77 78 79
    when (outSel.req.fire()) {
      printf(p"${GTimer()}: xbar: outSelIdx = ${outSelIdx}, outSel.req: ${outSel.req.bits}\n")
    }
    when (outSel.resp.fire()) {
      printf(p"${GTimer()}: xbar: outSelIdx= ${outSelIdx}, outSel.resp: ${outSel.resp.bits}\n")
    }
80

Z
Zihao Yu 已提交
81 82 83 84 85 86
    when (io.in.resp.fire()) {
      printf(p"${GTimer()}: xbar: in.resp: ${io.in.resp.bits}\n")
    }
  }
}

87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
class SimpleBusCrossbarNto1(n: Int, userBits:Int = 0) extends Module {
  val io = IO(new Bundle {
    val in = Flipped(Vec(n, new SimpleBusUC(userBits)))
    val out = new SimpleBusUC(userBits)
  })

  val s_idle :: s_readResp :: s_writeResp :: Nil = Enum(3)
  val state = RegInit(s_idle)

  val lockWriteFun = ((x: SimpleBusReqBundle) => x.isWrite() && x.isBurst())
  val inputArb = Module(new LockingArbiter(chiselTypeOf(io.in(0).req.bits), n, 8, Some(lockWriteFun)))
  (inputArb.io.in zip io.in.map(_.req)).map{ case (arb, in) => arb <> in }
  val thisReq = inputArb.io.out
  assert(!(thisReq.valid && !thisReq.bits.isRead() && !thisReq.bits.isWrite()))
  val inflightSrc = Reg(UInt(log2Up(n).W))

  io.out.req.bits := thisReq.bits
  // bind correct valid and ready signals
  io.out.req.valid := thisReq.valid && (state === s_idle)
  thisReq.ready := io.out.req.ready && (state === s_idle)

  io.in.map(_.resp.bits := io.out.resp.bits)
  io.in.map(_.resp.valid := false.B)
  (io.in(inflightSrc).resp, io.out.resp) match { case (l, r) => {
    l.valid := r.valid
    r.ready := l.ready
  }}

  switch (state) {
    is (s_idle) {
      when (thisReq.fire()) {
        inflightSrc := inputArb.io.chosen
        when (thisReq.bits.isRead()) { state := s_readResp }
        .elsewhen (thisReq.bits.isWriteLast() || thisReq.bits.isWriteSingle()) { state := s_writeResp }
      }
    }
    is (s_readResp) { when (io.out.resp.fire() && io.out.resp.bits.isReadLast()) { state := s_idle } }
    is (s_writeResp) { when (io.out.resp.fire()) { state := s_idle } }
  }
}

Z
Zihao Yu 已提交
128 129 130 131 132 133 134 135 136 137 138 139
class SimpleBusCrossbar(n: Int, addressSpace: List[(Long, Long)]) extends Module {
  val io = IO(new Bundle {
    val in = Flipped(Vec(n, new SimpleBusUC))
    val out = Vec(addressSpace.length, new SimpleBusUC)
  })

  val inXbar = Module(new SimpleBusCrossbarNto1(n))
  val outXbar = Module(new SimpleBusCrossbar1toN(addressSpace))
  inXbar.io.in <> io.in
  outXbar.io.in <> inXbar.io.out
  io.out <> outXbar.io.out
}