diff --git a/uncore/build.sbt b/uncore/build.sbt index 3287e088..a34b2b9b 100644 --- a/uncore/build.sbt +++ b/uncore/build.sbt @@ -6,8 +6,8 @@ name := "uncore" scalaVersion := "2.10.2" -// Provide a managed dependency on chisel if -DchiselVersion="" is supplied on the command line. -libraryDependencies ++= (Seq("chisel").map { +// Provide a managed dependency on X if -DXVersion="" is supplied on the command line. +libraryDependencies ++= (Seq("chisel","junction").map { dep: String => sys.props.get(dep + "Version") map { "edu.berkeley.cs" %% dep % _ }}).flatten site.settings diff --git a/uncore/src/main/scala/cache.scala b/uncore/src/main/scala/cache.scala index dcfc188d..b956a2e0 100644 --- a/uncore/src/main/scala/cache.scala +++ b/uncore/src/main/scala/cache.scala @@ -3,6 +3,7 @@ package uncore import Chisel._ import scala.reflect.ClassTag +import junctions._ case object CacheName extends Field[String] case object NSets extends Field[Int] diff --git a/uncore/src/main/scala/memserdes.scala b/uncore/src/main/scala/memserdes.scala deleted file mode 100644 index 82ee61ae..00000000 --- a/uncore/src/main/scala/memserdes.scala +++ /dev/null @@ -1,640 +0,0 @@ -// See LICENSE for license details. - -package uncore -import Chisel._ -import scala.math._ - -case object PAddrBits extends Field[Int] -case object VAddrBits extends Field[Int] -case object PgIdxBits extends Field[Int] -case object PgLevels extends Field[Int] -case object PgLevelBits extends Field[Int] -case object ASIdBits extends Field[Int] -case object PPNBits extends Field[Int] -case object VPNBits extends Field[Int] - -case object MIFAddrBits extends Field[Int] -case object MIFDataBits extends Field[Int] -case object MIFTagBits extends Field[Int] -case object MIFDataBeats extends Field[Int] - -trait MIFParameters extends UsesParameters { - val mifTagBits = params(MIFTagBits) - val mifAddrBits = params(MIFAddrBits) - val mifDataBits = params(MIFDataBits) - val mifDataBeats = params(MIFDataBeats) -} - -abstract class MIFBundle extends Bundle with MIFParameters -abstract class MIFModule extends Module with MIFParameters - -trait HasMemData extends MIFBundle { - val data = Bits(width = mifDataBits) -} - -trait HasMemAddr extends MIFBundle { - val addr = UInt(width = mifAddrBits) -} - -trait HasMemTag extends MIFBundle { - val tag = UInt(width = mifTagBits) -} - -class MemReqCmd extends HasMemAddr with HasMemTag { - val rw = Bool() -} - -class MemTag extends HasMemTag -class MemData extends HasMemData -class MemResp extends HasMemData with HasMemTag - -class MemIO extends Bundle { - val req_cmd = Decoupled(new MemReqCmd) - val req_data = Decoupled(new MemData) - val resp = Decoupled(new MemResp).flip -} - -class MemPipeIO extends Bundle { - val req_cmd = Decoupled(new MemReqCmd) - val req_data = Decoupled(new MemData) - val resp = Valid(new MemResp).flip -} - -class MemSerializedIO(w: Int) extends Bundle { - val req = Decoupled(Bits(width = w)) - val resp = Valid(Bits(width = w)).flip -} - -class MemSerdes extends MIFModule -{ - val w = params(HTIFWidth) - val io = new Bundle { - val wide = new MemIO().flip - val narrow = new MemSerializedIO(w) - } - val abits = io.wide.req_cmd.bits.toBits.getWidth - val dbits = io.wide.req_data.bits.toBits.getWidth - val rbits = io.wide.resp.bits.getWidth - - val out_buf = Reg(Bits()) - val in_buf = Reg(Bits()) - - val s_idle :: s_read_addr :: s_write_addr :: s_write_idle :: s_write_data :: Nil = Enum(UInt(), 5) - val state = Reg(init=s_idle) - val send_cnt = Reg(init=UInt(0, log2Up((max(abits, dbits)+w-1)/w))) - val data_send_cnt = Reg(init=UInt(0, log2Up(mifDataBeats))) - val adone = io.narrow.req.ready && send_cnt === UInt((abits-1)/w) - val ddone = io.narrow.req.ready && send_cnt === UInt((dbits-1)/w) - - when (io.narrow.req.valid && io.narrow.req.ready) { - send_cnt := send_cnt + UInt(1) - out_buf := out_buf >> UInt(w) - } - when (io.wide.req_cmd.valid && io.wide.req_cmd.ready) { - out_buf := io.wide.req_cmd.bits.toBits - } - when (io.wide.req_data.valid && io.wide.req_data.ready) { - out_buf := io.wide.req_data.bits.toBits - } - - io.wide.req_cmd.ready := state === s_idle - io.wide.req_data.ready := state === s_write_idle - io.narrow.req.valid := state === s_read_addr || state === s_write_addr || state === s_write_data - io.narrow.req.bits := out_buf - - when (state === s_idle && io.wide.req_cmd.valid) { - state := Mux(io.wide.req_cmd.bits.rw, s_write_addr, s_read_addr) - } - when (state === s_read_addr && adone) { - state := s_idle - send_cnt := UInt(0) - } - when (state === s_write_addr && adone) { - state := s_write_idle - send_cnt := UInt(0) - } - when (state === s_write_idle && io.wide.req_data.valid) { - state := s_write_data - } - when (state === s_write_data && ddone) { - data_send_cnt := data_send_cnt + UInt(1) - state := Mux(data_send_cnt === UInt(mifDataBeats-1), s_idle, s_write_idle) - send_cnt := UInt(0) - } - - val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w))) - val data_recv_cnt = Reg(init=UInt(0, log2Up(mifDataBeats))) - val resp_val = Reg(init=Bool(false)) - - resp_val := Bool(false) - when (io.narrow.resp.valid) { - recv_cnt := recv_cnt + UInt(1) - when (recv_cnt === UInt((rbits-1)/w)) { - recv_cnt := UInt(0) - data_recv_cnt := data_recv_cnt + UInt(1) - resp_val := Bool(true) - } - in_buf := Cat(io.narrow.resp.bits, in_buf((rbits+w-1)/w*w-1,w)) - } - - io.wide.resp.valid := resp_val - io.wide.resp.bits := io.wide.resp.bits.fromBits(in_buf) -} - -class MemDesserIO(w: Int) extends Bundle { - val narrow = new MemSerializedIO(w).flip - val wide = new MemIO -} - -class MemDesser(w: Int) extends Module // test rig side -{ - val io = new MemDesserIO(w) - val abits = io.wide.req_cmd.bits.toBits.getWidth - val dbits = io.wide.req_data.bits.toBits.getWidth - val rbits = io.wide.resp.bits.getWidth - val mifDataBeats = params(MIFDataBeats) - - require(dbits >= abits && rbits >= dbits) - val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w))) - val data_recv_cnt = Reg(init=UInt(0, log2Up(mifDataBeats))) - val adone = io.narrow.req.valid && recv_cnt === UInt((abits-1)/w) - val ddone = io.narrow.req.valid && recv_cnt === UInt((dbits-1)/w) - val rdone = io.narrow.resp.valid && recv_cnt === UInt((rbits-1)/w) - - val s_cmd_recv :: s_cmd :: s_data_recv :: s_data :: s_reply :: Nil = Enum(UInt(), 5) - val state = Reg(init=s_cmd_recv) - - val in_buf = Reg(Bits()) - when (io.narrow.req.valid && io.narrow.req.ready || io.narrow.resp.valid) { - recv_cnt := recv_cnt + UInt(1) - in_buf := Cat(io.narrow.req.bits, in_buf((rbits+w-1)/w*w-1,w)) - } - io.narrow.req.ready := state === s_cmd_recv || state === s_data_recv - - when (state === s_cmd_recv && adone) { - state := s_cmd - recv_cnt := UInt(0) - } - when (state === s_cmd && io.wide.req_cmd.ready) { - state := Mux(io.wide.req_cmd.bits.rw, s_data_recv, s_reply) - } - when (state === s_data_recv && ddone) { - state := s_data - recv_cnt := UInt(0) - } - when (state === s_data && io.wide.req_data.ready) { - state := s_data_recv - when (data_recv_cnt === UInt(mifDataBeats-1)) { - state := s_cmd_recv - } - data_recv_cnt := data_recv_cnt + UInt(1) - } - when (rdone) { // state === s_reply - when (data_recv_cnt === UInt(mifDataBeats-1)) { - state := s_cmd_recv - } - recv_cnt := UInt(0) - data_recv_cnt := data_recv_cnt + UInt(1) - } - - val req_cmd = in_buf >> UInt(((rbits+w-1)/w - (abits+w-1)/w)*w) - io.wide.req_cmd.valid := state === s_cmd - io.wide.req_cmd.bits := io.wide.req_cmd.bits.fromBits(req_cmd) - - io.wide.req_data.valid := state === s_data - io.wide.req_data.bits.data := in_buf >> UInt(((rbits+w-1)/w - (dbits+w-1)/w)*w) - - val dataq = Module(new Queue(new MemResp, mifDataBeats)) - dataq.io.enq <> io.wide.resp - dataq.io.deq.ready := recv_cnt === UInt((rbits-1)/w) - - io.narrow.resp.valid := dataq.io.deq.valid - io.narrow.resp.bits := dataq.io.deq.bits.toBits >> (recv_cnt * UInt(w)) -} - -//Adapter betweewn an UncachedTileLinkIO and a mem controller MemIO -class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule with MIFParameters { - val io = new Bundle { - val tl = new ManagerTileLinkIO - val mem = new MemIO - } - val dataBits = tlDataBits*tlDataBeats - val dstIdBits = params(LNHeaderBits) - require(tlDataBits*tlDataBeats == mifDataBits*mifDataBeats, "Data sizes between LLC and MC don't agree") - require(dstIdBits + tlClientXactIdBits < mifTagBits, "MemIO converter is going truncate tags: " + dstIdBits + " + " + tlClientXactIdBits + " >= " + mifTagBits) - - io.tl.acquire.ready := Bool(false) - io.tl.probe.valid := Bool(false) - io.tl.release.ready := Bool(false) - io.tl.finish.ready := Bool(true) - io.mem.resp.ready := Bool(false) - - val gnt_arb = Module(new Arbiter(new GrantToDst, 2)) - io.tl.grant <> gnt_arb.io.out - - val dst_off = dstIdBits + tlClientXactIdBits - val acq_has_data = io.tl.acquire.bits.hasData() - val rel_has_data = io.tl.release.bits.hasData() - - // Decompose outgoing TL Acquires into MemIO cmd and data - val active_out = Reg(init=Bool(false)) - val cmd_sent_out = Reg(init=Bool(false)) - val tag_out = Reg(UInt(width = mifTagBits)) - val addr_out = Reg(UInt(width = mifAddrBits)) - val has_data = Reg(init=Bool(false)) - val data_from_rel = Reg(init=Bool(false)) - val (tl_cnt_out, tl_wrap_out) = - Counter((io.tl.acquire.fire() && acq_has_data) || - (io.tl.release.fire() && rel_has_data), tlDataBeats) - val tl_done_out = Reg(init=Bool(false)) - val make_grant_ack = Reg(init=Bool(false)) - - gnt_arb.io.in(1).valid := Bool(false) - gnt_arb.io.in(1).bits := Grant( - dst = (if(dstIdBits > 0) tag_out(dst_off, tlClientXactIdBits + 1) else UInt(0)), - is_builtin_type = Bool(true), - g_type = Mux(data_from_rel, Grant.voluntaryAckType, Grant.putAckType), - client_xact_id = tag_out >> UInt(1), - manager_xact_id = UInt(0)) - - if(tlDataBits != mifDataBits || tlDataBeats != mifDataBeats) { - val mem_cmd_q = Module(new Queue(new MemReqCmd, qDepth)) - val mem_data_q = Module(new Queue(new MemData, qDepth)) - mem_cmd_q.io.enq.valid := Bool(false) - mem_data_q.io.enq.valid := Bool(false) - val (mif_cnt_out, mif_wrap_out) = Counter(mem_data_q.io.enq.fire(), mifDataBeats) - val mif_done_out = Reg(init=Bool(false)) - val tl_buf_out = Reg(Vec(io.tl.acquire.bits.data, tlDataBeats)) - val mif_buf_out = Vec.fill(mifDataBeats){ new MemData } - mif_buf_out := mif_buf_out.fromBits(tl_buf_out.toBits) - val mif_prog_out = (mif_cnt_out+UInt(1, width = log2Up(mifDataBeats+1)))*UInt(mifDataBits) - val tl_prog_out = tl_cnt_out*UInt(tlDataBits) - - when(!active_out){ - io.tl.release.ready := Bool(true) - io.tl.acquire.ready := !io.tl.release.valid - when(io.tl.release.valid) { - active_out := Bool(true) - cmd_sent_out := Bool(false) - tag_out := Cat(io.tl.release.bits.client_id, - io.tl.release.bits.client_xact_id, - io.tl.release.bits.isVoluntary()) - addr_out := io.tl.release.bits.addr_block - has_data := rel_has_data - data_from_rel := Bool(true) - make_grant_ack := io.tl.release.bits.requiresAck() - tl_done_out := tl_wrap_out - tl_buf_out(tl_cnt_out) := io.tl.release.bits.data - } .elsewhen(io.tl.acquire.valid) { - active_out := Bool(true) - cmd_sent_out := Bool(false) - tag_out := Cat(io.tl.release.bits.client_id, - io.tl.acquire.bits.client_xact_id, - io.tl.acquire.bits.isBuiltInType()) - addr_out := io.tl.acquire.bits.addr_block - has_data := acq_has_data - data_from_rel := Bool(false) - make_grant_ack := acq_has_data - tl_done_out := tl_wrap_out - tl_buf_out(tl_cnt_out) := io.tl.acquire.bits.data - } - } - when(active_out) { - mem_cmd_q.io.enq.valid := !cmd_sent_out - cmd_sent_out := cmd_sent_out || mem_cmd_q.io.enq.fire() - when(has_data) { - when(!tl_done_out) { - io.tl.acquire.ready := Bool(true) - when(io.tl.acquire.valid) { - tl_buf_out(tl_cnt_out) := Mux(data_from_rel, - io.tl.release.bits.data, - io.tl.acquire.bits.data) - } - } - when(!mif_done_out) { - mem_data_q.io.enq.valid := tl_done_out || mif_prog_out <= tl_prog_out - } - } - when(tl_wrap_out) { tl_done_out := Bool(true) } - when(mif_wrap_out) { mif_done_out := Bool(true) } - when(tl_done_out && make_grant_ack) { - gnt_arb.io.in(1).valid := Bool(true) - when(gnt_arb.io.in(1).ready) { make_grant_ack := Bool(false) } - } - when(cmd_sent_out && (!has_data || mif_done_out) && !make_grant_ack) { - active_out := Bool(false) - } - } - - mem_cmd_q.io.enq.bits.rw := has_data - mem_cmd_q.io.enq.bits.tag := tag_out - mem_cmd_q.io.enq.bits.addr := addr_out - mem_data_q.io.enq.bits.data := mif_buf_out(mif_cnt_out).data - io.mem.req_cmd <> mem_cmd_q.io.deq - io.mem.req_data <> mem_data_q.io.deq - } else { // Don't make the data buffers and try to flow cmd and data - io.mem.req_cmd.valid := Bool(false) - io.mem.req_data.valid := Bool(false) - io.mem.req_cmd.bits.rw := has_data - io.mem.req_cmd.bits.tag := tag_out - io.mem.req_cmd.bits.addr := addr_out - io.mem.req_data.bits.data := Mux(data_from_rel, - io.tl.release.bits.data, - io.tl.acquire.bits.data) - when(!active_out){ - io.tl.release.ready := io.mem.req_data.ready - io.tl.acquire.ready := io.mem.req_data.ready && !io.tl.release.valid - io.mem.req_data.valid := (io.tl.release.valid && rel_has_data) || - (io.tl.acquire.valid && acq_has_data) - when(io.mem.req_data.ready && (io.tl.release.valid || io.tl.acquire.valid)) { - active_out := !io.mem.req_cmd.ready || io.mem.req_data.valid - io.mem.req_cmd.valid := Bool(true) - cmd_sent_out := io.mem.req_cmd.ready - tl_done_out := tl_wrap_out - when(io.tl.release.valid) { - data_from_rel := Bool(true) - make_grant_ack := io.tl.release.bits.requiresAck() - io.mem.req_data.bits.data := io.tl.release.bits.data - val tag = Cat(io.tl.release.bits.client_id, - io.tl.release.bits.client_xact_id, - io.tl.release.bits.isVoluntary()) - val addr = io.tl.release.bits.addr_block - io.mem.req_cmd.bits.tag := tag - io.mem.req_cmd.bits.addr := addr - io.mem.req_cmd.bits.rw := rel_has_data - tag_out := tag - addr_out := addr - has_data := rel_has_data - } .elsewhen(io.tl.acquire.valid) { - data_from_rel := Bool(false) - make_grant_ack := acq_has_data // i.e. is it a Put - io.mem.req_data.bits.data := io.tl.acquire.bits.data - io.mem.req_cmd.bits.rw := acq_has_data - val tag = Cat(io.tl.acquire.bits.client_id, - io.tl.acquire.bits.client_xact_id, - io.tl.acquire.bits.isBuiltInType()) - val addr = io.tl.acquire.bits.addr_block - io.mem.req_cmd.bits.tag := tag - io.mem.req_cmd.bits.addr := addr - io.mem.req_cmd.bits.rw := acq_has_data - tag_out := tag - addr_out := addr - has_data := acq_has_data - } - } - } - when(active_out) { - io.mem.req_cmd.valid := !cmd_sent_out - cmd_sent_out := cmd_sent_out || io.mem.req_cmd.fire() - when(has_data && !tl_done_out) { - when(data_from_rel) { - io.tl.release.ready := io.mem.req_data.ready - io.mem.req_data.valid := io.tl.release.valid - } .otherwise { - io.tl.acquire.ready := io.mem.req_data.ready - io.mem.req_data.valid := io.tl.acquire.valid - } - } - when(tl_wrap_out) { tl_done_out := Bool(true) } - when(tl_done_out && make_grant_ack) { - gnt_arb.io.in(1).valid := Bool(true) // TODO: grants for voluntary acks? - when(gnt_arb.io.in(1).ready) { make_grant_ack := Bool(false) } - } - when(cmd_sent_out && (!has_data || tl_done_out) && !make_grant_ack) { - active_out := Bool(false) - } - } - } - - // Aggregate incoming MemIO responses into TL Grants - val active_in = Reg(init=Bool(false)) - val (tl_cnt_in, tl_wrap_in) = Counter(io.tl.grant.fire() && io.tl.grant.bits.hasMultibeatData(), tlDataBeats) - val tag_in = Reg(UInt(width = mifTagBits)) - - if(tlDataBits != mifDataBits || tlDataBeats != mifDataBeats) { - val (mif_cnt_in, mif_wrap_in) = Counter(io.mem.resp.fire(), mifDataBeats) // TODO: Assumes all resps have data - val mif_done_in = Reg(init=Bool(false)) - val mif_buf_in = Reg(Vec(new MemData, mifDataBeats)) - val tl_buf_in = Vec.fill(tlDataBeats){ io.tl.acquire.bits.data } - tl_buf_in := tl_buf_in.fromBits(mif_buf_in.toBits) - val tl_prog_in = (tl_cnt_in+UInt(1, width = log2Up(tlDataBeats+1)))*UInt(tlDataBits) - val mif_prog_in = mif_cnt_in*UInt(mifDataBits) - gnt_arb.io.in(0).bits := Grant( - dst = (if(dstIdBits > 0) tag_in(dst_off, tlClientXactIdBits + 1) else UInt(0)), - is_builtin_type = tag_in(0), - g_type = Mux(tag_in(0), Grant.getDataBlockType, UInt(0)), // TODO: Assumes MI or MEI protocol - client_xact_id = tag_in >> UInt(1), - manager_xact_id = UInt(0), - addr_beat = tl_cnt_in, - data = tl_buf_in(tl_cnt_in)) - - when(!active_in) { - io.mem.resp.ready := Bool(true) - when(io.mem.resp.valid) { - active_in := Bool(true) - mif_done_in := mif_wrap_in - tag_in := io.mem.resp.bits.tag - mif_buf_in(tl_cnt_in).data := io.mem.resp.bits.data - } - } - when(active_in) { - gnt_arb.io.in(0).valid := mif_done_in || tl_prog_in <= mif_prog_in - when(!mif_done_in) { - io.mem.resp.ready := Bool(true) - when(io.mem.resp.valid) { - mif_buf_in(mif_cnt_in).data := io.mem.resp.bits.data - } - } - when(mif_wrap_in) { mif_done_in := Bool(true) } - when(tl_wrap_in) { active_in := Bool(false) } - } - } else { // Don't generate all the uneeded data buffers and flow resp - gnt_arb.io.in(0).valid := io.mem.resp.valid - io.mem.resp.ready := gnt_arb.io.in(0).ready - gnt_arb.io.in(0).bits := Grant( - dst = (if(dstIdBits > 0) io.mem.resp.bits.tag(dst_off, tlClientXactIdBits + 1) else UInt(0)), - is_builtin_type = io.mem.resp.bits.tag(0), - g_type = Mux(io.mem.resp.bits.tag(0), Grant.getDataBlockType, UInt(0)), // TODO: Assumes MI or MEI protocol - client_xact_id = io.mem.resp.bits.tag >> UInt(1), - manager_xact_id = UInt(0), - addr_beat = tl_cnt_in, - data = io.mem.resp.bits.data) - } -} - -class HellaFlowQueue[T <: Data](val entries: Int)(data: => T) extends Module -{ - val io = new QueueIO(data, entries) - require(entries > 1) - - val do_flow = Wire(Bool()) - val do_enq = io.enq.fire() && !do_flow - val do_deq = io.deq.fire() && !do_flow - - val maybe_full = Reg(init=Bool(false)) - val enq_ptr = Counter(do_enq, entries)._1 - val (deq_ptr, deq_done) = Counter(do_deq, entries) - when (do_enq != do_deq) { maybe_full := do_enq } - - val ptr_match = enq_ptr === deq_ptr - val empty = ptr_match && !maybe_full - val full = ptr_match && maybe_full - val atLeastTwo = full || enq_ptr - deq_ptr >= UInt(2) - do_flow := empty && io.deq.ready - - val ram = SeqMem(data, entries) - when (do_enq) { ram.write(enq_ptr, io.enq.bits) } - - val ren = io.deq.ready && (atLeastTwo || !io.deq.valid && !empty) - val raddr = Mux(io.deq.valid, Mux(deq_done, UInt(0), deq_ptr + UInt(1)), deq_ptr) - val ram_out_valid = Reg(next = ren) - - io.deq.valid := Mux(empty, io.enq.valid, ram_out_valid) - io.enq.ready := !full - io.deq.bits := Mux(empty, io.enq.bits, ram.read(raddr, ren)) -} - -class HellaQueue[T <: Data](val entries: Int)(data: => T) extends Module -{ - val io = new QueueIO(data, entries) - - val fq = Module(new HellaFlowQueue(entries)(data)) - io.enq <> fq.io.enq - io.deq <> Queue(fq.io.deq, 1, pipe = true) -} - -object HellaQueue -{ - def apply[T <: Data](enq: DecoupledIO[T], entries: Int) = { - val q = Module((new HellaQueue(entries)) { enq.bits }) - q.io.enq.valid := enq.valid // not using <> so that override is allowed - q.io.enq.bits := enq.bits - enq.ready := q.io.enq.ready - q.io.deq - } -} - -class MemIOArbiter(val arbN: Int) extends MIFModule { - val io = new Bundle { - val inner = Vec.fill(arbN){new MemIO}.flip - val outer = new MemIO - } - - if(arbN > 1) { - val cmd_arb = Module(new RRArbiter(new MemReqCmd, arbN)) - val choice_q = Module(new Queue(cmd_arb.io.chosen, 4)) - val (data_cnt, data_done) = Counter(io.outer.req_data.fire(), mifDataBeats) - - io.inner.map(_.req_cmd).zipWithIndex.zip(cmd_arb.io.in).map{ case ((req, id), arb) => { - arb.valid := req.valid - arb.bits := req.bits - arb.bits.tag := Cat(req.bits.tag, UInt(id)) - req.ready := arb.ready - }} - io.outer.req_cmd.bits := cmd_arb.io.out.bits - io.outer.req_cmd.valid := cmd_arb.io.out.valid && choice_q.io.enq.ready - cmd_arb.io.out.ready := io.outer.req_cmd.ready && choice_q.io.enq.ready - choice_q.io.enq.bits := cmd_arb.io.chosen - choice_q.io.enq.valid := cmd_arb.io.out.fire() && cmd_arb.io.out.bits.rw - - io.outer.req_data.bits := io.inner(choice_q.io.deq.bits).req_data.bits - io.outer.req_data.valid := io.inner(choice_q.io.deq.bits).req_data.valid && choice_q.io.deq.valid - io.inner.map(_.req_data.ready).zipWithIndex.foreach { - case(r, i) => r := UInt(i) === choice_q.io.deq.bits && choice_q.io.deq.valid - } - choice_q.io.deq.ready := data_done - - io.outer.resp.ready := Bool(false) - for (i <- 0 until arbN) { - io.inner(i).resp.valid := Bool(false) - when(io.outer.resp.bits.tag(log2Up(arbN)-1,0).toUInt === UInt(i)) { - io.inner(i).resp.valid := io.outer.resp.valid - io.outer.resp.ready := io.inner(i).resp.ready - } - io.inner(i).resp.bits := io.outer.resp.bits - io.inner(i).resp.bits.tag := io.outer.resp.bits.tag >> UInt(log2Up(arbN)) - } - } else { io.inner.head <> io.outer } -} - -object MemIOMemPipeIOConverter { - def apply(in: MemPipeIO): MemIO = { - val out = Wire(new MemIO()) - in.resp.valid := out.resp.valid - in.resp.bits := out.resp.bits - out.resp.ready := Bool(true) - out.req_cmd.valid := in.req_cmd.valid - out.req_cmd.bits := in.req_cmd.bits - in.req_cmd.ready := out.req_cmd.ready - out.req_data.valid := in.req_data.valid - out.req_data.bits := in.req_data.bits - in.req_data.ready := out.req_data.ready - out - } -} - -class MemPipeIOMemIOConverter(numRequests: Int) extends MIFModule { - val io = new Bundle { - val cpu = new MemIO().flip - val mem = new MemPipeIO - } - - val numEntries = numRequests * mifDataBeats - val size = log2Down(numEntries) + 1 - - val inc = Wire(Bool()) - val dec = Wire(Bool()) - val count = Reg(init=UInt(numEntries, size)) - val watermark = count >= UInt(mifDataBeats) - - when (inc && !dec) { - count := count + UInt(1) - } - when (!inc && dec) { - count := count - UInt(mifDataBeats) - } - when (inc && dec) { - count := count - UInt(mifDataBeats-1) - } - - val cmdq_mask = io.cpu.req_cmd.bits.rw || watermark - - io.mem.req_cmd.valid := io.cpu.req_cmd.valid && cmdq_mask - io.cpu.req_cmd.ready := io.mem.req_cmd.ready && cmdq_mask - io.mem.req_cmd.bits := io.cpu.req_cmd.bits - - io.mem.req_data <> io.cpu.req_data - - // Have separate queues to allow for different mem implementations - val resp_data_q = Module((new HellaQueue(numEntries)) { new MemData }) - resp_data_q.io.enq.valid := io.mem.resp.valid - resp_data_q.io.enq.bits.data := io.mem.resp.bits.data - - val resp_tag_q = Module((new HellaQueue(numEntries)) { new MemTag }) - resp_tag_q.io.enq.valid := io.mem.resp.valid - resp_tag_q.io.enq.bits.tag := io.mem.resp.bits.tag - - io.cpu.resp.valid := resp_data_q.io.deq.valid && resp_tag_q.io.deq.valid - io.cpu.resp.bits.data := resp_data_q.io.deq.bits.data - io.cpu.resp.bits.tag := resp_tag_q.io.deq.bits.tag - resp_data_q.io.deq.ready := io.cpu.resp.ready - resp_tag_q.io.deq.ready := io.cpu.resp.ready - - inc := resp_data_q.io.deq.fire() && resp_tag_q.io.deq.fire() - dec := io.mem.req_cmd.fire() && !io.mem.req_cmd.bits.rw -} - -class MemPipeIOTileLinkIOConverter(outstanding: Int) extends MIFModule { - val io = new Bundle { - val tl = new ManagerTileLinkIO - val mem = new MemPipeIO - } - - val a = Module(new MemIOTileLinkIOConverter(1)) - val b = Module(new MemPipeIOMemIOConverter(outstanding)) - a.io.tl <> io.tl - b.io.cpu.req_cmd <> Queue(a.io.mem.req_cmd, 2, pipe=true) - b.io.cpu.req_data <> Queue(a.io.mem.req_data, mifDataBeats, pipe=true) - a.io.mem.resp <> b.io.cpu.resp - b.io.mem <> io.mem -} diff --git a/uncore/src/main/scala/nasti.scala b/uncore/src/main/scala/nasti.scala deleted file mode 100644 index 904a596e..00000000 --- a/uncore/src/main/scala/nasti.scala +++ /dev/null @@ -1,295 +0,0 @@ -// See LICENSE for license details. - -package uncore -import Chisel._ -import scala.math.max - -case object NASTIDataBits extends Field[Int] -case object NASTIAddrBits extends Field[Int] -case object NASTIIdBits extends Field[Int] - -trait NASTIParameters extends UsesParameters { - val nastiXDataBits = params(NASTIDataBits) - val nastiWStrobeBits = nastiXDataBits / 8 - val nastiXAddrBits = params(NASTIAddrBits) - val nastiWIdBits = params(NASTIIdBits) - val nastiRIdBits = params(NASTIIdBits) - val nastiXIdBits = max(nastiWIdBits, nastiRIdBits) - val nastiXUserBits = 1 - val nastiAWUserBits = nastiXUserBits - val nastiWUserBits = nastiXUserBits - val nastiBUserBits = nastiXUserBits - val nastiARUserBits = nastiXUserBits - val nastiRUserBits = nastiXUserBits - val nastiXLenBits = 8 - val nastiXSizeBits = 3 - val nastiXBurstBits = 2 - val nastiXCacheBits = 4 - val nastiXProtBits = 3 - val nastiXQosBits = 4 - val nastiXRegionBits = 4 - val nastiXRespBits = 2 - - def bytesToXSize(bytes: UInt) = MuxLookup(bytes, UInt("b111"), Array( - UInt(1) -> UInt(0), - UInt(2) -> UInt(1), - UInt(4) -> UInt(2), - UInt(8) -> UInt(3), - UInt(16) -> UInt(4), - UInt(32) -> UInt(5), - UInt(64) -> UInt(6), - UInt(128) -> UInt(7))) -} - -abstract class NASTIBundle extends Bundle with NASTIParameters -abstract class NASTIModule extends Module with NASTIParameters - -trait NASTIChannel extends NASTIBundle -trait NASTIMasterToSlaveChannel extends NASTIChannel -trait NASTISlaveToMasterChannel extends NASTIChannel - -class NASTIMasterIO extends Bundle { - val aw = Decoupled(new NASTIWriteAddressChannel) - val w = Decoupled(new NASTIWriteDataChannel) - val b = Decoupled(new NASTIWriteResponseChannel).flip - val ar = Decoupled(new NASTIReadAddressChannel) - val r = Decoupled(new NASTIReadDataChannel).flip -} - -class NASTISlaveIO extends NASTIMasterIO { flip() } - -trait HasNASTIMetadata extends NASTIBundle { - val addr = UInt(width = nastiXAddrBits) - val len = UInt(width = nastiXLenBits) - val size = UInt(width = nastiXSizeBits) - val burst = UInt(width = nastiXBurstBits) - val lock = Bool() - val cache = UInt(width = nastiXCacheBits) - val prot = UInt(width = nastiXProtBits) - val qos = UInt(width = nastiXQosBits) - val region = UInt(width = nastiXRegionBits) -} - -trait HasNASTIData extends NASTIBundle { - val data = UInt(width = nastiXDataBits) - val last = Bool() -} - -class NASTIAddressChannel extends NASTIMasterToSlaveChannel with HasNASTIMetadata - -class NASTIResponseChannel extends NASTISlaveToMasterChannel { - val resp = UInt(width = nastiXRespBits) -} - -class NASTIWriteAddressChannel extends NASTIAddressChannel { - val id = UInt(width = nastiWIdBits) - val user = UInt(width = nastiAWUserBits) -} - -class NASTIWriteDataChannel extends NASTIMasterToSlaveChannel with HasNASTIData { - val strb = UInt(width = nastiWStrobeBits) - val user = UInt(width = nastiWUserBits) -} - -class NASTIWriteResponseChannel extends NASTIResponseChannel { - val id = UInt(width = nastiWIdBits) - val user = UInt(width = nastiBUserBits) -} - -class NASTIReadAddressChannel extends NASTIAddressChannel { - val id = UInt(width = nastiRIdBits) - val user = UInt(width = nastiARUserBits) -} - -class NASTIReadDataChannel extends NASTIResponseChannel with HasNASTIData { - val id = UInt(width = nastiRIdBits) - val user = UInt(width = nastiRUserBits) -} - -class MemIONASTISlaveIOConverter extends MIFModule with NASTIParameters { - val io = new Bundle { - val nasti = new NASTISlaveIO - val mem = new MemIO - } - - require(mifDataBits == nastiXDataBits, "Data sizes between LLC and MC don't agree") - val (mif_cnt_out, mif_wrap_out) = Counter(io.mem.resp.fire(), mifDataBeats) - - io.mem.req_cmd.bits.addr := Mux(io.nasti.aw.valid, io.nasti.aw.bits.addr, io.nasti.ar.bits.addr) >> - UInt(params(CacheBlockOffsetBits)) - io.mem.req_cmd.bits.tag := Mux(io.nasti.aw.valid, io.nasti.aw.bits.id, io.nasti.ar.bits.id) - io.mem.req_cmd.bits.rw := io.nasti.aw.valid - io.mem.req_cmd.valid := (io.nasti.aw.valid && io.nasti.b.ready) || io.nasti.ar.valid - io.nasti.ar.ready := io.mem.req_cmd.ready && !io.nasti.aw.valid - io.nasti.aw.ready := io.mem.req_cmd.ready && io.nasti.b.ready - - io.nasti.b.valid := io.nasti.aw.valid && io.mem.req_cmd.ready - io.nasti.b.bits.id := io.nasti.aw.bits.id - io.nasti.b.bits.resp := UInt(0) - - io.nasti.w.ready := io.mem.req_data.ready - io.mem.req_data.valid := io.nasti.w.valid - io.mem.req_data.bits.data := io.nasti.w.bits.data - assert(!io.nasti.w.valid || io.nasti.w.bits.strb.andR, "MemIO must write full cache line") - - io.nasti.r.valid := io.mem.resp.valid - io.nasti.r.bits.data := io.mem.resp.bits.data - io.nasti.r.bits.last := mif_wrap_out - io.nasti.r.bits.id := io.mem.resp.bits.tag - io.nasti.r.bits.resp := UInt(0) - io.mem.resp.ready := io.nasti.r.ready -} - -class NASTIMasterIOTileLinkIOConverter extends TLModule with NASTIParameters { - val io = new Bundle { - val tl = new ManagerTileLinkIO - val nasti = new NASTIMasterIO - } - - val dataBits = tlDataBits*tlDataBeats - val dstIdBits = params(LNHeaderBits) - require(tlDataBits == nastiXDataBits, "Data sizes between LLC and MC don't agree") // TODO: remove this restriction - require(tlDataBeats < (1 << nastiXLenBits), "Can't have that many beats") - require(dstIdBits + tlClientXactIdBits < nastiXIdBits, "NASTIMasterIO converter is going truncate tags: " + dstIdBits + " + " + tlClientXactIdBits + " >= " + nastiXIdBits) - - io.tl.acquire.ready := Bool(false) - io.tl.probe.valid := Bool(false) - io.tl.release.ready := Bool(false) - io.tl.finish.ready := Bool(true) - - io.nasti.b.ready := Bool(false) - io.nasti.r.ready := Bool(false) - io.nasti.ar.valid := Bool(false) - io.nasti.aw.valid := Bool(false) - io.nasti.w.valid := Bool(false) - - val dst_off = dstIdBits + tlClientXactIdBits - val acq_has_data = io.tl.acquire.bits.hasData() - val rel_has_data = io.tl.release.bits.hasData() - val is_write = io.tl.release.valid || (io.tl.acquire.valid && acq_has_data) - - // Decompose outgoing TL Acquires into NASTI address and data channels - val active_out = Reg(init=Bool(false)) - val cmd_sent_out = Reg(init=Bool(false)) - val tag_out = Reg(UInt(width = nastiXIdBits)) - val addr_out = Reg(UInt(width = nastiXAddrBits)) - val has_data = Reg(init=Bool(false)) - val data_from_rel = Reg(init=Bool(false)) - val (tl_cnt_out, tl_wrap_out) = - Counter((io.tl.acquire.fire() && acq_has_data) || - (io.tl.release.fire() && rel_has_data), tlDataBeats) - val tl_done_out = Reg(init=Bool(false)) - - io.nasti.ar.bits.id := tag_out - io.nasti.ar.bits.addr := addr_out - io.nasti.ar.bits.len := Mux(has_data, UInt(tlDataBeats-1), UInt(0)) - io.nasti.ar.bits.size := UInt(log2Ceil(tlDataBits)) - io.nasti.ar.bits.burst := UInt("b01") - io.nasti.ar.bits.lock := Bool(false) - io.nasti.ar.bits.cache := UInt("b0000") - io.nasti.ar.bits.prot := UInt("b000") - io.nasti.ar.bits.qos := UInt("b0000") - io.nasti.ar.bits.region := UInt("b0000") - io.nasti.ar.bits.user := UInt(0) - io.nasti.aw.bits := io.nasti.ar.bits - io.nasti.w.bits.strb := Mux(data_from_rel, SInt(-1), io.tl.acquire.bits.wmask()) - io.nasti.w.bits.data := Mux(data_from_rel, io.tl.release.bits.data, io.tl.acquire.bits.data) - io.nasti.w.bits.last := tl_wrap_out - - when(!active_out){ - io.tl.release.ready := io.nasti.w.ready - io.tl.acquire.ready := io.nasti.w.ready && !io.tl.release.valid - io.nasti.w.valid := (io.tl.release.valid && rel_has_data) || - (io.tl.acquire.valid && acq_has_data) - when(io.nasti.w.ready && (io.tl.release.valid || io.tl.acquire.valid)) { - active_out := (!is_write && !io.nasti.ar.ready) || - (is_write && !(io.nasti.aw.ready && io.nasti.w.ready)) || - (io.nasti.w.valid && Bool(tlDataBeats > 1)) - io.nasti.aw.valid := is_write - io.nasti.ar.valid := !is_write - cmd_sent_out := (!is_write && io.nasti.ar.ready) || (is_write && io.nasti.aw.ready) - tl_done_out := tl_wrap_out - when(io.tl.release.valid) { - data_from_rel := Bool(true) - io.nasti.w.bits.data := io.tl.release.bits.data - io.nasti.w.bits.strb := SInt(-1) - val tag = Cat(io.tl.release.bits.client_id, - io.tl.release.bits.client_xact_id, - io.tl.release.bits.isVoluntary()) - val addr = io.tl.release.bits.full_addr() - io.nasti.aw.bits.id := tag - io.nasti.aw.bits.addr := addr - io.nasti.aw.bits.len := UInt(tlDataBeats-1) - io.nasti.aw.bits.size := MT_Q - tag_out := tag - addr_out := addr - has_data := rel_has_data - } .elsewhen(io.tl.acquire.valid) { - data_from_rel := Bool(false) - io.nasti.w.bits.data := io.tl.acquire.bits.data - io.nasti.w.bits.strb := io.tl.acquire.bits.wmask() - val tag = Cat(io.tl.acquire.bits.client_id, - io.tl.acquire.bits.client_xact_id, - io.tl.acquire.bits.isBuiltInType()) - val addr = io.tl.acquire.bits.full_addr() - when(is_write) { - io.nasti.aw.bits.id := tag - io.nasti.aw.bits.addr := addr - io.nasti.aw.bits.len := Mux(io.tl.acquire.bits.isBuiltInType(Acquire.putBlockType), - UInt(tlDataBeats-1), UInt(0)) - io.nasti.aw.bits.size := bytesToXSize(PopCount(io.tl.acquire.bits.wmask())) - } .otherwise { - io.nasti.ar.bits.id := tag - io.nasti.ar.bits.addr := addr - io.nasti.ar.bits.len := Mux(io.tl.acquire.bits.isBuiltInType(Acquire.getBlockType), - UInt(tlDataBeats-1), UInt(0)) - io.nasti.ar.bits.size := io.tl.acquire.bits.op_size() - } - tag_out := tag - addr_out := addr - has_data := acq_has_data - } - } - } - when(active_out) { - io.nasti.ar.valid := !cmd_sent_out && !has_data - io.nasti.aw.valid := !cmd_sent_out && has_data - cmd_sent_out := cmd_sent_out || io.nasti.ar.fire() || io.nasti.aw.fire() - when(has_data && !tl_done_out) { - when(data_from_rel) { - io.tl.release.ready := io.nasti.w.ready - io.nasti.w.valid := io.tl.release.valid - } .otherwise { - io.tl.acquire.ready := io.nasti.w.ready - io.nasti.w.valid := io.tl.acquire.valid - } - } - when(tl_wrap_out) { tl_done_out := Bool(true) } - when(cmd_sent_out && (!has_data || tl_done_out)) { active_out := Bool(false) } - } - - // Aggregate incoming NASTI responses into TL Grants - val (tl_cnt_in, tl_wrap_in) = Counter(io.tl.grant.fire() && io.tl.grant.bits.hasMultibeatData(), tlDataBeats) - val gnt_arb = Module(new Arbiter(new GrantToDst, 2)) - io.tl.grant <> gnt_arb.io.out - - gnt_arb.io.in(0).valid := io.nasti.r.valid - io.nasti.r.ready := gnt_arb.io.in(0).ready - gnt_arb.io.in(0).bits := Grant( - dst = (if(dstIdBits > 0) io.nasti.r.bits.id(dst_off, tlClientXactIdBits + 1) else UInt(0)), - is_builtin_type = io.nasti.r.bits.id(0), - g_type = Mux(io.nasti.r.bits.id(0), Grant.getDataBlockType, UInt(0)), // TODO: Assumes MI or MEI protocol - client_xact_id = io.nasti.r.bits.id >> UInt(1), - manager_xact_id = UInt(0), - addr_beat = tl_cnt_in, - data = io.nasti.r.bits.data) - - gnt_arb.io.in(1).valid := io.nasti.b.valid - io.nasti.b.ready := gnt_arb.io.in(1).ready - gnt_arb.io.in(1).bits := Grant( - dst = (if(dstIdBits > 0) io.nasti.b.bits.id(dst_off, tlClientXactIdBits + 1) else UInt(0)), - is_builtin_type = Bool(true), - g_type = Mux(io.nasti.b.bits.id(0), Grant.voluntaryAckType, Grant.putAckType), - client_xact_id = io.nasti.b.bits.id >> UInt(1), - manager_xact_id = UInt(0)) -} diff --git a/uncore/src/main/scala/slowio.scala b/uncore/src/main/scala/slowio.scala deleted file mode 100644 index 95ca34e6..00000000 --- a/uncore/src/main/scala/slowio.scala +++ /dev/null @@ -1,70 +0,0 @@ -// See LICENSE for license details. - -package uncore -import Chisel._ - -class SlowIO[T <: Data](val divisor_max: Int)(data: => T) extends Module -{ - val io = new Bundle { - val out_fast = Decoupled(data).flip - val out_slow = Decoupled(data) - val in_fast = Decoupled(data) - val in_slow = Decoupled(data).flip - val clk_slow = Bool(OUTPUT) - val set_divisor = Valid(Bits(width = 32)).flip - val divisor = Bits(OUTPUT, 32) - } - - require(divisor_max >= 8 && divisor_max <= 65536 && isPow2(divisor_max)) - val divisor = Reg(init=UInt(divisor_max-1)) - val d_shadow = Reg(init=UInt(divisor_max-1)) - val hold = Reg(init=UInt(divisor_max/4-1)) - val h_shadow = Reg(init=UInt(divisor_max/4-1)) - when (io.set_divisor.valid) { - d_shadow := io.set_divisor.bits(log2Up(divisor_max)-1, 0).toUInt - h_shadow := io.set_divisor.bits(log2Up(divisor_max)-1+16, 16).toUInt - } - io.divisor := hold << UInt(16) | divisor - - val count = Reg{UInt(width = log2Up(divisor_max))} - val myclock = Reg{Bool()} - count := count + UInt(1) - - val rising = count === (divisor >> UInt(1)) - val falling = count === divisor - val held = count === (divisor >> UInt(1)) + hold - - when (falling) { - divisor := d_shadow - hold := h_shadow - count := UInt(0) - myclock := Bool(false) - } - when (rising) { - myclock := Bool(true) - } - - val in_slow_rdy = Reg(init=Bool(false)) - val out_slow_val = Reg(init=Bool(false)) - val out_slow_bits = Reg(data) - - val fromhost_q = Module(new Queue(data,1)) - fromhost_q.io.enq.valid := rising && (io.in_slow.valid && in_slow_rdy || this.reset) - fromhost_q.io.enq.bits := io.in_slow.bits - fromhost_q.io.deq <> io.in_fast - - val tohost_q = Module(new Queue(data,1)) - tohost_q.io.enq <> io.out_fast - tohost_q.io.deq.ready := rising && io.out_slow.ready && out_slow_val - - when (held) { - in_slow_rdy := fromhost_q.io.enq.ready - out_slow_val := tohost_q.io.deq.valid - out_slow_bits := Mux(this.reset, fromhost_q.io.deq.bits, tohost_q.io.deq.bits) - } - - io.in_slow.ready := in_slow_rdy - io.out_slow.valid := out_slow_val - io.out_slow.bits := out_slow_bits - io.clk_slow := myclock -} diff --git a/uncore/src/main/scala/tilelink.scala b/uncore/src/main/scala/tilelink.scala index 6c7aeb6e..71c8d909 100644 --- a/uncore/src/main/scala/tilelink.scala +++ b/uncore/src/main/scala/tilelink.scala @@ -2,6 +2,7 @@ package uncore import Chisel._ +import junctions._ import scala.math.max /** Parameters exposed to the top-level design, set based on @@ -1237,3 +1238,422 @@ trait HasDataBeatCounters { (cnt > UInt(0), up_idx, up_done, down_idx, down_done) } } + +class NASTIMasterIOTileLinkIOConverter extends TLModule with NASTIParameters { + val io = new Bundle { + val tl = new ManagerTileLinkIO + val nasti = new NASTIMasterIO + } + + val dataBits = tlDataBits*tlDataBeats + val dstIdBits = params(LNHeaderBits) + require(tlDataBits == nastiXDataBits, "Data sizes between LLC and MC don't agree") // TODO: remove this restriction + require(tlDataBeats < (1 << nastiXLenBits), "Can't have that many beats") + require(dstIdBits + tlClientXactIdBits < nastiXIdBits, "NASTIMasterIO converter is going truncate tags: " + dstIdBits + " + " + tlClientXactIdBits + " >= " + nastiXIdBits) + + io.tl.acquire.ready := Bool(false) + io.tl.probe.valid := Bool(false) + io.tl.release.ready := Bool(false) + io.tl.finish.ready := Bool(true) + + io.nasti.b.ready := Bool(false) + io.nasti.r.ready := Bool(false) + io.nasti.ar.valid := Bool(false) + io.nasti.aw.valid := Bool(false) + io.nasti.w.valid := Bool(false) + + val dst_off = dstIdBits + tlClientXactIdBits + val acq_has_data = io.tl.acquire.bits.hasData() + val rel_has_data = io.tl.release.bits.hasData() + val is_write = io.tl.release.valid || (io.tl.acquire.valid && acq_has_data) + + // Decompose outgoing TL Acquires into NASTI address and data channels + val active_out = Reg(init=Bool(false)) + val cmd_sent_out = Reg(init=Bool(false)) + val tag_out = Reg(UInt(width = nastiXIdBits)) + val addr_out = Reg(UInt(width = nastiXAddrBits)) + val has_data = Reg(init=Bool(false)) + val data_from_rel = Reg(init=Bool(false)) + val (tl_cnt_out, tl_wrap_out) = + Counter((io.tl.acquire.fire() && acq_has_data) || + (io.tl.release.fire() && rel_has_data), tlDataBeats) + val tl_done_out = Reg(init=Bool(false)) + + io.nasti.ar.bits.id := tag_out + io.nasti.ar.bits.addr := addr_out + io.nasti.ar.bits.len := Mux(has_data, UInt(tlDataBeats-1), UInt(0)) + io.nasti.ar.bits.size := UInt(log2Ceil(tlDataBits)) + io.nasti.ar.bits.burst := UInt("b01") + io.nasti.ar.bits.lock := Bool(false) + io.nasti.ar.bits.cache := UInt("b0000") + io.nasti.ar.bits.prot := UInt("b000") + io.nasti.ar.bits.qos := UInt("b0000") + io.nasti.ar.bits.region := UInt("b0000") + io.nasti.ar.bits.user := UInt(0) + io.nasti.aw.bits := io.nasti.ar.bits + io.nasti.w.bits.strb := Mux(data_from_rel, SInt(-1), io.tl.acquire.bits.wmask()) + io.nasti.w.bits.data := Mux(data_from_rel, io.tl.release.bits.data, io.tl.acquire.bits.data) + io.nasti.w.bits.last := tl_wrap_out + + when(!active_out){ + io.tl.release.ready := io.nasti.w.ready + io.tl.acquire.ready := io.nasti.w.ready && !io.tl.release.valid + io.nasti.w.valid := (io.tl.release.valid && rel_has_data) || + (io.tl.acquire.valid && acq_has_data) + when(io.nasti.w.ready && (io.tl.release.valid || io.tl.acquire.valid)) { + active_out := (!is_write && !io.nasti.ar.ready) || + (is_write && !(io.nasti.aw.ready && io.nasti.w.ready)) || + (io.nasti.w.valid && Bool(tlDataBeats > 1)) + io.nasti.aw.valid := is_write + io.nasti.ar.valid := !is_write + cmd_sent_out := (!is_write && io.nasti.ar.ready) || (is_write && io.nasti.aw.ready) + tl_done_out := tl_wrap_out + when(io.tl.release.valid) { + data_from_rel := Bool(true) + io.nasti.w.bits.data := io.tl.release.bits.data + io.nasti.w.bits.strb := SInt(-1) + val tag = Cat(io.tl.release.bits.client_id, + io.tl.release.bits.client_xact_id, + io.tl.release.bits.isVoluntary()) + val addr = io.tl.release.bits.full_addr() + io.nasti.aw.bits.id := tag + io.nasti.aw.bits.addr := addr + io.nasti.aw.bits.len := UInt(tlDataBeats-1) + io.nasti.aw.bits.size := MT_Q + tag_out := tag + addr_out := addr + has_data := rel_has_data + } .elsewhen(io.tl.acquire.valid) { + data_from_rel := Bool(false) + io.nasti.w.bits.data := io.tl.acquire.bits.data + io.nasti.w.bits.strb := io.tl.acquire.bits.wmask() + val tag = Cat(io.tl.acquire.bits.client_id, + io.tl.acquire.bits.client_xact_id, + io.tl.acquire.bits.isBuiltInType()) + val addr = io.tl.acquire.bits.full_addr() + when(is_write) { + io.nasti.aw.bits.id := tag + io.nasti.aw.bits.addr := addr + io.nasti.aw.bits.len := Mux(io.tl.acquire.bits.isBuiltInType(Acquire.putBlockType), + UInt(tlDataBeats-1), UInt(0)) + io.nasti.aw.bits.size := bytesToXSize(PopCount(io.tl.acquire.bits.wmask())) + } .otherwise { + io.nasti.ar.bits.id := tag + io.nasti.ar.bits.addr := addr + io.nasti.ar.bits.len := Mux(io.tl.acquire.bits.isBuiltInType(Acquire.getBlockType), + UInt(tlDataBeats-1), UInt(0)) + io.nasti.ar.bits.size := io.tl.acquire.bits.op_size() + } + tag_out := tag + addr_out := addr + has_data := acq_has_data + } + } + } + when(active_out) { + io.nasti.ar.valid := !cmd_sent_out && !has_data + io.nasti.aw.valid := !cmd_sent_out && has_data + cmd_sent_out := cmd_sent_out || io.nasti.ar.fire() || io.nasti.aw.fire() + when(has_data && !tl_done_out) { + when(data_from_rel) { + io.tl.release.ready := io.nasti.w.ready + io.nasti.w.valid := io.tl.release.valid + } .otherwise { + io.tl.acquire.ready := io.nasti.w.ready + io.nasti.w.valid := io.tl.acquire.valid + } + } + when(tl_wrap_out) { tl_done_out := Bool(true) } + when(cmd_sent_out && (!has_data || tl_done_out)) { active_out := Bool(false) } + } + + // Aggregate incoming NASTI responses into TL Grants + val (tl_cnt_in, tl_wrap_in) = Counter(io.tl.grant.fire() && io.tl.grant.bits.hasMultibeatData(), tlDataBeats) + val gnt_arb = Module(new Arbiter(new GrantToDst, 2)) + io.tl.grant <> gnt_arb.io.out + + gnt_arb.io.in(0).valid := io.nasti.r.valid + io.nasti.r.ready := gnt_arb.io.in(0).ready + gnt_arb.io.in(0).bits := Grant( + dst = (if(dstIdBits > 0) io.nasti.r.bits.id(dst_off, tlClientXactIdBits + 1) else UInt(0)), + is_builtin_type = io.nasti.r.bits.id(0), + g_type = Mux(io.nasti.r.bits.id(0), Grant.getDataBlockType, UInt(0)), // TODO: Assumes MI or MEI protocol + client_xact_id = io.nasti.r.bits.id >> UInt(1), + manager_xact_id = UInt(0), + addr_beat = tl_cnt_in, + data = io.nasti.r.bits.data) + + gnt_arb.io.in(1).valid := io.nasti.b.valid + io.nasti.b.ready := gnt_arb.io.in(1).ready + gnt_arb.io.in(1).bits := Grant( + dst = (if(dstIdBits > 0) io.nasti.b.bits.id(dst_off, tlClientXactIdBits + 1) else UInt(0)), + is_builtin_type = Bool(true), + g_type = Mux(io.nasti.b.bits.id(0), Grant.voluntaryAckType, Grant.putAckType), + client_xact_id = io.nasti.b.bits.id >> UInt(1), + manager_xact_id = UInt(0)) +} + +class MemPipeIOTileLinkIOConverter(outstanding: Int) extends MIFModule { + val io = new Bundle { + val tl = new ManagerTileLinkIO + val mem = new MemPipeIO + } + + val a = Module(new MemIOTileLinkIOConverter(1)) + val b = Module(new MemPipeIOMemIOConverter(outstanding)) + a.io.tl <> io.tl + b.io.cpu.req_cmd <> Queue(a.io.mem.req_cmd, 2, pipe=true) + b.io.cpu.req_data <> Queue(a.io.mem.req_data, mifDataBeats, pipe=true) + a.io.mem.resp <> b.io.cpu.resp + b.io.mem <> io.mem +} + +//Adapter betweewn an UncachedTileLinkIO and a mem controller MemIO +class MemIOTileLinkIOConverter(qDepth: Int) extends TLModule with MIFParameters { + val io = new Bundle { + val tl = new ManagerTileLinkIO + val mem = new MemIO + } + val dataBits = tlDataBits*tlDataBeats + val dstIdBits = params(LNHeaderBits) + require(tlDataBits*tlDataBeats == mifDataBits*mifDataBeats, "Data sizes between LLC and MC don't agree") + require(dstIdBits + tlClientXactIdBits < mifTagBits, "MemIO converter is going truncate tags: " + dstIdBits + " + " + tlClientXactIdBits + " >= " + mifTagBits) + + io.tl.acquire.ready := Bool(false) + io.tl.probe.valid := Bool(false) + io.tl.release.ready := Bool(false) + io.tl.finish.ready := Bool(true) + io.mem.resp.ready := Bool(false) + + val gnt_arb = Module(new Arbiter(new GrantToDst, 2)) + io.tl.grant <> gnt_arb.io.out + + val dst_off = dstIdBits + tlClientXactIdBits + val acq_has_data = io.tl.acquire.bits.hasData() + val rel_has_data = io.tl.release.bits.hasData() + + // Decompose outgoing TL Acquires into MemIO cmd and data + val active_out = Reg(init=Bool(false)) + val cmd_sent_out = Reg(init=Bool(false)) + val tag_out = Reg(UInt(width = mifTagBits)) + val addr_out = Reg(UInt(width = mifAddrBits)) + val has_data = Reg(init=Bool(false)) + val data_from_rel = Reg(init=Bool(false)) + val (tl_cnt_out, tl_wrap_out) = + Counter((io.tl.acquire.fire() && acq_has_data) || + (io.tl.release.fire() && rel_has_data), tlDataBeats) + val tl_done_out = Reg(init=Bool(false)) + val make_grant_ack = Reg(init=Bool(false)) + + gnt_arb.io.in(1).valid := Bool(false) + gnt_arb.io.in(1).bits := Grant( + dst = (if(dstIdBits > 0) tag_out(dst_off, tlClientXactIdBits + 1) else UInt(0)), + is_builtin_type = Bool(true), + g_type = Mux(data_from_rel, Grant.voluntaryAckType, Grant.putAckType), + client_xact_id = tag_out >> UInt(1), + manager_xact_id = UInt(0)) + + if(tlDataBits != mifDataBits || tlDataBeats != mifDataBeats) { + val mem_cmd_q = Module(new Queue(new MemReqCmd, qDepth)) + val mem_data_q = Module(new Queue(new MemData, qDepth)) + mem_cmd_q.io.enq.valid := Bool(false) + mem_data_q.io.enq.valid := Bool(false) + val (mif_cnt_out, mif_wrap_out) = Counter(mem_data_q.io.enq.fire(), mifDataBeats) + val mif_done_out = Reg(init=Bool(false)) + val tl_buf_out = Reg(Vec(io.tl.acquire.bits.data, tlDataBeats)) + val mif_buf_out = Vec.fill(mifDataBeats){ new MemData } + mif_buf_out := mif_buf_out.fromBits(tl_buf_out.toBits) + val mif_prog_out = (mif_cnt_out+UInt(1, width = log2Up(mifDataBeats+1)))*UInt(mifDataBits) + val tl_prog_out = tl_cnt_out*UInt(tlDataBits) + + when(!active_out){ + io.tl.release.ready := Bool(true) + io.tl.acquire.ready := !io.tl.release.valid + when(io.tl.release.valid) { + active_out := Bool(true) + cmd_sent_out := Bool(false) + tag_out := Cat(io.tl.release.bits.client_id, + io.tl.release.bits.client_xact_id, + io.tl.release.bits.isVoluntary()) + addr_out := io.tl.release.bits.addr_block + has_data := rel_has_data + data_from_rel := Bool(true) + make_grant_ack := io.tl.release.bits.requiresAck() + tl_done_out := tl_wrap_out + tl_buf_out(tl_cnt_out) := io.tl.release.bits.data + } .elsewhen(io.tl.acquire.valid) { + active_out := Bool(true) + cmd_sent_out := Bool(false) + tag_out := Cat(io.tl.release.bits.client_id, + io.tl.acquire.bits.client_xact_id, + io.tl.acquire.bits.isBuiltInType()) + addr_out := io.tl.acquire.bits.addr_block + has_data := acq_has_data + data_from_rel := Bool(false) + make_grant_ack := acq_has_data + tl_done_out := tl_wrap_out + tl_buf_out(tl_cnt_out) := io.tl.acquire.bits.data + } + } + when(active_out) { + mem_cmd_q.io.enq.valid := !cmd_sent_out + cmd_sent_out := cmd_sent_out || mem_cmd_q.io.enq.fire() + when(has_data) { + when(!tl_done_out) { + io.tl.acquire.ready := Bool(true) + when(io.tl.acquire.valid) { + tl_buf_out(tl_cnt_out) := Mux(data_from_rel, + io.tl.release.bits.data, + io.tl.acquire.bits.data) + } + } + when(!mif_done_out) { + mem_data_q.io.enq.valid := tl_done_out || mif_prog_out <= tl_prog_out + } + } + when(tl_wrap_out) { tl_done_out := Bool(true) } + when(mif_wrap_out) { mif_done_out := Bool(true) } + when(tl_done_out && make_grant_ack) { + gnt_arb.io.in(1).valid := Bool(true) + when(gnt_arb.io.in(1).ready) { make_grant_ack := Bool(false) } + } + when(cmd_sent_out && (!has_data || mif_done_out) && !make_grant_ack) { + active_out := Bool(false) + } + } + + mem_cmd_q.io.enq.bits.rw := has_data + mem_cmd_q.io.enq.bits.tag := tag_out + mem_cmd_q.io.enq.bits.addr := addr_out + mem_data_q.io.enq.bits.data := mif_buf_out(mif_cnt_out).data + io.mem.req_cmd <> mem_cmd_q.io.deq + io.mem.req_data <> mem_data_q.io.deq + } else { // Don't make the data buffers and try to flow cmd and data + io.mem.req_cmd.valid := Bool(false) + io.mem.req_data.valid := Bool(false) + io.mem.req_cmd.bits.rw := has_data + io.mem.req_cmd.bits.tag := tag_out + io.mem.req_cmd.bits.addr := addr_out + io.mem.req_data.bits.data := Mux(data_from_rel, + io.tl.release.bits.data, + io.tl.acquire.bits.data) + when(!active_out){ + io.tl.release.ready := io.mem.req_data.ready + io.tl.acquire.ready := io.mem.req_data.ready && !io.tl.release.valid + io.mem.req_data.valid := (io.tl.release.valid && rel_has_data) || + (io.tl.acquire.valid && acq_has_data) + when(io.mem.req_data.ready && (io.tl.release.valid || io.tl.acquire.valid)) { + active_out := !io.mem.req_cmd.ready || io.mem.req_data.valid + io.mem.req_cmd.valid := Bool(true) + cmd_sent_out := io.mem.req_cmd.ready + tl_done_out := tl_wrap_out + when(io.tl.release.valid) { + data_from_rel := Bool(true) + make_grant_ack := io.tl.release.bits.requiresAck() + io.mem.req_data.bits.data := io.tl.release.bits.data + val tag = Cat(io.tl.release.bits.client_id, + io.tl.release.bits.client_xact_id, + io.tl.release.bits.isVoluntary()) + val addr = io.tl.release.bits.addr_block + io.mem.req_cmd.bits.tag := tag + io.mem.req_cmd.bits.addr := addr + io.mem.req_cmd.bits.rw := rel_has_data + tag_out := tag + addr_out := addr + has_data := rel_has_data + } .elsewhen(io.tl.acquire.valid) { + data_from_rel := Bool(false) + make_grant_ack := acq_has_data // i.e. is it a Put + io.mem.req_data.bits.data := io.tl.acquire.bits.data + io.mem.req_cmd.bits.rw := acq_has_data + val tag = Cat(io.tl.acquire.bits.client_id, + io.tl.acquire.bits.client_xact_id, + io.tl.acquire.bits.isBuiltInType()) + val addr = io.tl.acquire.bits.addr_block + io.mem.req_cmd.bits.tag := tag + io.mem.req_cmd.bits.addr := addr + io.mem.req_cmd.bits.rw := acq_has_data + tag_out := tag + addr_out := addr + has_data := acq_has_data + } + } + } + when(active_out) { + io.mem.req_cmd.valid := !cmd_sent_out + cmd_sent_out := cmd_sent_out || io.mem.req_cmd.fire() + when(has_data && !tl_done_out) { + when(data_from_rel) { + io.tl.release.ready := io.mem.req_data.ready + io.mem.req_data.valid := io.tl.release.valid + } .otherwise { + io.tl.acquire.ready := io.mem.req_data.ready + io.mem.req_data.valid := io.tl.acquire.valid + } + } + when(tl_wrap_out) { tl_done_out := Bool(true) } + when(tl_done_out && make_grant_ack) { + gnt_arb.io.in(1).valid := Bool(true) // TODO: grants for voluntary acks? + when(gnt_arb.io.in(1).ready) { make_grant_ack := Bool(false) } + } + when(cmd_sent_out && (!has_data || tl_done_out) && !make_grant_ack) { + active_out := Bool(false) + } + } + } + + // Aggregate incoming MemIO responses into TL Grants + val active_in = Reg(init=Bool(false)) + val (tl_cnt_in, tl_wrap_in) = Counter(io.tl.grant.fire() && io.tl.grant.bits.hasMultibeatData(), tlDataBeats) + val tag_in = Reg(UInt(width = mifTagBits)) + + if(tlDataBits != mifDataBits || tlDataBeats != mifDataBeats) { + val (mif_cnt_in, mif_wrap_in) = Counter(io.mem.resp.fire(), mifDataBeats) // TODO: Assumes all resps have data + val mif_done_in = Reg(init=Bool(false)) + val mif_buf_in = Reg(Vec(new MemData, mifDataBeats)) + val tl_buf_in = Vec.fill(tlDataBeats){ io.tl.acquire.bits.data } + tl_buf_in := tl_buf_in.fromBits(mif_buf_in.toBits) + val tl_prog_in = (tl_cnt_in+UInt(1, width = log2Up(tlDataBeats+1)))*UInt(tlDataBits) + val mif_prog_in = mif_cnt_in*UInt(mifDataBits) + gnt_arb.io.in(0).bits := Grant( + dst = (if(dstIdBits > 0) tag_in(dst_off, tlClientXactIdBits + 1) else UInt(0)), + is_builtin_type = tag_in(0), + g_type = Mux(tag_in(0), Grant.getDataBlockType, UInt(0)), // TODO: Assumes MI or MEI protocol + client_xact_id = tag_in >> UInt(1), + manager_xact_id = UInt(0), + addr_beat = tl_cnt_in, + data = tl_buf_in(tl_cnt_in)) + + when(!active_in) { + io.mem.resp.ready := Bool(true) + when(io.mem.resp.valid) { + active_in := Bool(true) + mif_done_in := mif_wrap_in + tag_in := io.mem.resp.bits.tag + mif_buf_in(tl_cnt_in).data := io.mem.resp.bits.data + } + } + when(active_in) { + gnt_arb.io.in(0).valid := mif_done_in || tl_prog_in <= mif_prog_in + when(!mif_done_in) { + io.mem.resp.ready := Bool(true) + when(io.mem.resp.valid) { + mif_buf_in(mif_cnt_in).data := io.mem.resp.bits.data + } + } + when(mif_wrap_in) { mif_done_in := Bool(true) } + when(tl_wrap_in) { active_in := Bool(false) } + } + } else { // Don't generate all the uneeded data buffers and flow resp + gnt_arb.io.in(0).valid := io.mem.resp.valid + io.mem.resp.ready := gnt_arb.io.in(0).ready + gnt_arb.io.in(0).bits := Grant( + dst = (if(dstIdBits > 0) io.mem.resp.bits.tag(dst_off, tlClientXactIdBits + 1) else UInt(0)), + is_builtin_type = io.mem.resp.bits.tag(0), + g_type = Mux(io.mem.resp.bits.tag(0), Grant.getDataBlockType, UInt(0)), // TODO: Assumes MI or MEI protocol + client_xact_id = io.mem.resp.bits.tag >> UInt(1), + manager_xact_id = UInt(0), + addr_beat = tl_cnt_in, + data = io.mem.resp.bits.data) + } +}