2016-01-06 05:04:49 +01:00
|
|
|
package junctions
|
|
|
|
|
|
|
|
import Chisel._
|
|
|
|
import NastiConstants._
|
2016-11-18 23:05:14 +01:00
|
|
|
import config._
|
2016-01-06 05:04:49 +01:00
|
|
|
|
|
|
|
class StreamChannel(w: Int) extends Bundle {
|
|
|
|
val data = UInt(width = w)
|
|
|
|
val last = Bool()
|
|
|
|
|
|
|
|
override def cloneType = new StreamChannel(w).asInstanceOf[this.type]
|
|
|
|
}
|
|
|
|
|
|
|
|
class StreamIO(w: Int) extends Bundle {
|
|
|
|
val out = Decoupled(new StreamChannel(w))
|
|
|
|
val in = Decoupled(new StreamChannel(w)).flip
|
|
|
|
|
|
|
|
override def cloneType = new StreamIO(w).asInstanceOf[this.type]
|
|
|
|
}
|
|
|
|
|
|
|
|
class NastiIOStreamIOConverter(w: Int)(implicit p: Parameters) extends Module {
|
|
|
|
val io = new Bundle {
|
|
|
|
val nasti = (new NastiIO).flip
|
|
|
|
val stream = new StreamIO(w)
|
|
|
|
}
|
|
|
|
|
|
|
|
val streamSize = UInt(log2Up(w / 8))
|
|
|
|
assert(!io.nasti.ar.valid || io.nasti.ar.bits.size === streamSize,
|
|
|
|
"read channel wrong size on stream")
|
2016-02-15 18:48:35 +01:00
|
|
|
assert(!io.nasti.ar.valid || io.nasti.ar.bits.len === UInt(0) ||
|
|
|
|
io.nasti.ar.bits.burst === BURST_FIXED,
|
2016-01-06 05:04:49 +01:00
|
|
|
"read channel wrong burst type on stream")
|
|
|
|
assert(!io.nasti.aw.valid || io.nasti.aw.bits.size === streamSize,
|
|
|
|
"write channel wrong size on stream")
|
2016-02-15 18:48:35 +01:00
|
|
|
assert(!io.nasti.aw.valid || io.nasti.aw.bits.len === UInt(0) ||
|
|
|
|
io.nasti.aw.bits.burst === BURST_FIXED,
|
2016-01-06 05:04:49 +01:00
|
|
|
"write channel wrong burst type on stream")
|
2016-02-15 18:48:35 +01:00
|
|
|
assert(!io.nasti.w.valid || io.nasti.w.bits.strb.andR,
|
|
|
|
"write channel cannot take partial writes")
|
2016-01-06 05:04:49 +01:00
|
|
|
|
|
|
|
val read_id = Reg(io.nasti.ar.bits.id)
|
2016-02-15 18:48:35 +01:00
|
|
|
val read_cnt = Reg(io.nasti.ar.bits.len)
|
2016-01-06 05:04:49 +01:00
|
|
|
val reading = Reg(init = Bool(false))
|
|
|
|
|
|
|
|
io.nasti.ar.ready := !reading
|
|
|
|
io.nasti.r.valid := reading && io.stream.in.valid
|
|
|
|
io.nasti.r.bits := io.stream.in.bits
|
2016-09-13 19:47:36 +02:00
|
|
|
io.nasti.r.bits.resp := RESP_OKAY
|
2016-01-06 05:04:49 +01:00
|
|
|
io.nasti.r.bits.id := read_id
|
|
|
|
io.stream.in.ready := reading && io.nasti.r.ready
|
|
|
|
|
|
|
|
when (io.nasti.ar.fire()) {
|
|
|
|
read_id := io.nasti.ar.bits.id
|
2016-02-15 18:48:35 +01:00
|
|
|
read_cnt := io.nasti.ar.bits.len
|
2016-01-06 05:04:49 +01:00
|
|
|
reading := Bool(true)
|
|
|
|
}
|
|
|
|
|
2016-02-15 18:48:35 +01:00
|
|
|
when (io.nasti.r.fire()) {
|
|
|
|
when (read_cnt === UInt(0)) {
|
|
|
|
reading := Bool(false)
|
|
|
|
} .otherwise {
|
|
|
|
read_cnt := read_cnt - UInt(1)
|
|
|
|
}
|
2016-01-06 05:04:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
val write_id = Reg(io.nasti.aw.bits.id)
|
|
|
|
val writing = Reg(init = Bool(false))
|
|
|
|
val write_resp = Reg(init = Bool(false))
|
|
|
|
|
|
|
|
io.nasti.aw.ready := !writing && !write_resp
|
|
|
|
io.nasti.w.ready := writing && io.stream.out.ready
|
|
|
|
io.stream.out.valid := writing && io.nasti.w.valid
|
|
|
|
io.stream.out.bits := io.nasti.w.bits
|
|
|
|
io.nasti.b.valid := write_resp
|
2016-09-13 19:47:36 +02:00
|
|
|
io.nasti.b.bits.resp := RESP_OKAY
|
2016-01-06 05:04:49 +01:00
|
|
|
io.nasti.b.bits.id := write_id
|
|
|
|
|
|
|
|
when (io.nasti.aw.fire()) {
|
|
|
|
write_id := io.nasti.aw.bits.id
|
|
|
|
writing := Bool(true)
|
|
|
|
}
|
|
|
|
|
|
|
|
when (io.nasti.w.fire() && io.nasti.w.bits.last) {
|
|
|
|
writing := Bool(false)
|
|
|
|
write_resp := Bool(true)
|
|
|
|
}
|
|
|
|
|
|
|
|
when (io.nasti.b.fire()) { write_resp := Bool(false) }
|
|
|
|
}
|
2016-01-22 02:39:57 +01:00
|
|
|
|
|
|
|
class StreamNarrower(win: Int, wout: Int) extends Module {
|
|
|
|
require(win > wout, "Stream narrower input width must be larger than input width")
|
|
|
|
require(win % wout == 0, "Stream narrower input width must be multiple of output width")
|
|
|
|
|
|
|
|
val io = new Bundle {
|
|
|
|
val in = Decoupled(new StreamChannel(win)).flip
|
|
|
|
val out = Decoupled(new StreamChannel(wout))
|
|
|
|
}
|
|
|
|
|
|
|
|
val n_pieces = win / wout
|
|
|
|
val buffer = Reg(Bits(width = win))
|
|
|
|
val (piece_idx, pkt_done) = Counter(io.out.fire(), n_pieces)
|
|
|
|
val pieces = Vec.tabulate(n_pieces) { i => buffer(wout * (i + 1) - 1, wout * i) }
|
|
|
|
val last_piece = (piece_idx === UInt(n_pieces - 1))
|
|
|
|
val sending = Reg(init = Bool(false))
|
|
|
|
val in_last = Reg(Bool())
|
|
|
|
|
|
|
|
when (io.in.fire()) {
|
|
|
|
buffer := io.in.bits.data
|
|
|
|
in_last := io.in.bits.last
|
|
|
|
sending := Bool(true)
|
|
|
|
}
|
|
|
|
when (pkt_done) { sending := Bool(false) }
|
|
|
|
|
|
|
|
io.out.valid := sending
|
|
|
|
io.out.bits.data := pieces(piece_idx)
|
|
|
|
io.out.bits.last := in_last && last_piece
|
|
|
|
io.in.ready := !sending
|
|
|
|
}
|
|
|
|
|
|
|
|
class StreamExpander(win: Int, wout: Int) extends Module {
|
|
|
|
require(win < wout, "Stream expander input width must be smaller than input width")
|
|
|
|
require(wout % win == 0, "Stream narrower output width must be multiple of input width")
|
|
|
|
|
|
|
|
val io = new Bundle {
|
|
|
|
val in = Decoupled(new StreamChannel(win)).flip
|
|
|
|
val out = Decoupled(new StreamChannel(wout))
|
|
|
|
}
|
|
|
|
|
|
|
|
val n_pieces = wout / win
|
|
|
|
val buffer = Reg(Vec(n_pieces, UInt(width = win)))
|
|
|
|
val last = Reg(Bool())
|
|
|
|
val collecting = Reg(init = Bool(true))
|
|
|
|
val (piece_idx, pkt_done) = Counter(io.in.fire(), n_pieces)
|
|
|
|
|
|
|
|
when (io.in.fire()) { buffer(piece_idx) := io.in.bits.data }
|
|
|
|
when (pkt_done) { last := io.in.bits.last; collecting := Bool(false) }
|
|
|
|
when (io.out.fire()) { collecting := Bool(true) }
|
|
|
|
|
|
|
|
io.in.ready := collecting
|
|
|
|
io.out.valid := !collecting
|
2016-08-01 02:13:52 +02:00
|
|
|
io.out.bits.data := buffer.asUInt
|
2016-01-22 02:39:57 +01:00
|
|
|
io.out.bits.last := last
|
|
|
|
}
|
|
|
|
|
|
|
|
object StreamUtils {
|
|
|
|
def connectStreams(a: StreamIO, b: StreamIO) {
|
|
|
|
a.in <> b.out
|
|
|
|
b.in <> a.out
|
|
|
|
}
|
2016-09-04 05:41:48 +02:00
|
|
|
def roundUp(n: Int, d: Int) = ((n - 1) / d + 1) * d
|
2016-01-22 02:39:57 +01:00
|
|
|
}
|
|
|
|
|
2016-09-04 05:41:48 +02:00
|
|
|
class SerialIO(w: Int) extends Bundle {
|
|
|
|
val out = Decoupled(UInt(width = w))
|
|
|
|
val in = Decoupled(UInt(width = w)).flip
|
|
|
|
override def cloneType = new SerialIO(w).asInstanceOf[this.type]
|
2016-01-22 02:39:57 +01:00
|
|
|
}
|
|
|
|
|
2016-09-04 05:41:48 +02:00
|
|
|
class Serializer[T <: Data](w: Int, typ: T) extends Module {
|
2016-01-22 02:39:57 +01:00
|
|
|
val io = new Bundle {
|
|
|
|
val in = Decoupled(typ).flip
|
2016-02-25 06:33:51 +01:00
|
|
|
val out = Decoupled(Bits(width = w))
|
2016-01-22 02:39:57 +01:00
|
|
|
}
|
|
|
|
|
2016-09-04 05:41:48 +02:00
|
|
|
val narrower = Module(new StreamNarrower(StreamUtils.roundUp(typ.getWidth, w), w))
|
2016-08-01 02:13:52 +02:00
|
|
|
narrower.io.in.bits.data := io.in.bits.asUInt
|
2016-01-22 02:39:57 +01:00
|
|
|
narrower.io.in.bits.last := Bool(true)
|
|
|
|
narrower.io.in.valid := io.in.valid
|
|
|
|
io.in.ready := narrower.io.in.ready
|
2016-02-25 06:33:51 +01:00
|
|
|
io.out.valid := narrower.io.out.valid
|
|
|
|
io.out.bits := narrower.io.out.bits.data
|
|
|
|
narrower.io.out.ready := io.out.ready
|
2016-01-22 02:39:57 +01:00
|
|
|
}
|
|
|
|
|
2016-09-04 05:41:48 +02:00
|
|
|
class Deserializer[T <: Data](w: Int, typ: T) extends Module {
|
2016-01-22 02:39:57 +01:00
|
|
|
val io = new Bundle {
|
2016-02-25 06:33:51 +01:00
|
|
|
val in = Decoupled(Bits(width = w)).flip
|
2016-01-22 02:39:57 +01:00
|
|
|
val out = Decoupled(typ)
|
|
|
|
}
|
|
|
|
|
2016-09-04 05:41:48 +02:00
|
|
|
val expander = Module(new StreamExpander(w, StreamUtils.roundUp(typ.getWidth, w)))
|
2016-02-25 06:33:51 +01:00
|
|
|
expander.io.in.valid := io.in.valid
|
|
|
|
expander.io.in.bits.data := io.in.bits
|
|
|
|
expander.io.in.bits.last := Bool(true)
|
|
|
|
io.in.ready := expander.io.in.ready
|
2016-01-22 02:39:57 +01:00
|
|
|
io.out.valid := expander.io.out.valid
|
2016-09-04 05:41:48 +02:00
|
|
|
io.out.bits := typ.fromBits(expander.io.out.bits.data)
|
2016-01-22 02:39:57 +01:00
|
|
|
expander.io.out.ready := io.out.ready
|
|
|
|
}
|