diff --git a/rocket/src/main/scala/dtlb.scala b/rocket/src/main/scala/dtlb.scala index 6c0af2a0..eb7a91cf 100644 --- a/rocket/src/main/scala/dtlb.scala +++ b/rocket/src/main/scala/dtlb.scala @@ -118,12 +118,9 @@ class rocketDTLB(entries: Int) extends Component } // high if there are any unused (invalid) entries in the TLB - val invalid_entry = (tag_cam.io.valid_bits != ~Bits(0,entries)); - val ie_enc = new priorityEncoder(entries); - ie_enc.io.in := ~tag_cam.io.valid_bits.toUFix; - val ie_addr = ie_enc.io.out; - - val repl_waddr = Mux(invalid_entry, ie_addr, repl_count).toUFix; + val has_invalid_entry = !tag_cam.io.valid_bits.andR + val invalid_entry = PriorityEncoder(~tag_cam.io.valid_bits) + val repl_waddr = Mux(has_invalid_entry, invalid_entry, repl_count).toUFix; val lookup = (state === s_ready) && r_cpu_req_val && !io.cpu_req.bits.kill && (req_load || req_store || req_amo || req_pf); val lookup_hit = lookup && tag_hit; @@ -136,7 +133,7 @@ class rocketDTLB(entries: Int) extends Component when (tlb_miss) { r_refill_tag := lookup_tag; r_refill_waddr := repl_waddr; - when (!invalid_entry) { + when (!has_invalid_entry) { repl_count := repl_count + UFix(1); } } diff --git a/rocket/src/main/scala/itlb.scala b/rocket/src/main/scala/itlb.scala index 231010b9..06cd6e2b 100644 --- a/rocket/src/main/scala/itlb.scala +++ b/rocket/src/main/scala/itlb.scala @@ -146,12 +146,9 @@ class rocketITLB(entries: Int) extends Component } // high if there are any unused entries in the ITLB - val invalid_entry = (tag_cam.io.valid_bits != ~Bits(0,entries)); - val ie_enc = new priorityEncoder(entries); - ie_enc.io.in := ~tag_cam.io.valid_bits.toUFix; - val ie_addr = ie_enc.io.out; - - val repl_waddr = Mux(invalid_entry, ie_addr, repl_count).toUFix; + val has_invalid_entry = !tag_cam.io.valid_bits.andR + val invalid_entry = PriorityEncoder(~tag_cam.io.valid_bits) + val repl_waddr = Mux(has_invalid_entry, invalid_entry, repl_count).toUFix; val lookup = (state === s_ready) && r_cpu_req_val; val lookup_hit = lookup && tag_hit; @@ -162,7 +159,7 @@ class rocketITLB(entries: Int) extends Component when (tlb_miss) { r_refill_tag := lookup_tag; r_refill_waddr := repl_waddr; - when (!invalid_entry) { + when (!has_invalid_entry) { repl_count := repl_count + UFix(1); } } diff --git a/rocket/src/main/scala/nbdcache.scala b/rocket/src/main/scala/nbdcache.scala index 50dd9fc3..57d223b6 100644 --- a/rocket/src/main/scala/nbdcache.scala +++ b/rocket/src/main/scala/nbdcache.scala @@ -361,10 +361,8 @@ class ReplayUnit extends Component { val cpu_resp_tag = Bits(DCACHE_TAG_BITS, OUTPUT) } - val sdq_val = Reg(resetVal = UFix(0, NSDQ)) - val sdq_allocator = new priorityEncoder(NSDQ) - sdq_allocator.io.in := ~sdq_val - val sdq_alloc_id = sdq_allocator.io.out.toUFix + val sdq_val = Reg(resetVal = UFix(0)) + val sdq_alloc_id = PriorityEncoder(~sdq_val(NSDQ-1,0)) val replay_val = Reg(resetVal = Bool(false)) val replay_retry = replay_val && !io.data_req.ready diff --git a/rocket/src/main/scala/queues.scala b/rocket/src/main/scala/queues.scala index 14f416ba..12f4aeae 100644 --- a/rocket/src/main/scala/queues.scala +++ b/rocket/src/main/scala/queues.scala @@ -53,3 +53,37 @@ class queue[T <: Data](entries: Int, pipe: Boolean = false, flushable: Boolean = io.enq.ready := !maybe_full || enq_ptr != deq_ptr || (if (pipe) io.deq.ready else Bool(false)) io.deq.bits <> Mem(entries, do_enq, enq_ptr, io.enq.bits).read(deq_ptr) } + +object Queue +{ + def apply[T <: Data](enq: ioDecoupled[T], entries: Int = 2, pipe: Boolean = false) = { + val q = (new queue(entries, pipe)) { enq.bits.clone } + q.io.enq <> enq + q.io.deq + } +} + +class pipereg[T <: Data]()(data: => T) extends Component +{ + val io = new Bundle { + val enq = new ioValid()(data) + val deq = new ioValid()(data).flip + } + + //val bits = Reg() { io.enq.bits.clone } + //when (io.enq.valid) { + // bits := io.enq.bits + //} + + io.deq.valid := Reg(io.enq.valid, resetVal = Bool(false)) + io.deq.bits <> Mem(1, io.enq.valid, UFix(0), io.enq.bits).read(UFix(0)) +} + +object PipeReg +{ + def apply[T <: Data](enq: ioValid[T]) = { + val q = (new pipereg) { enq.bits.clone } + q.io.enq <> enq + q.io.deq + } +} diff --git a/rocket/src/main/scala/top.scala b/rocket/src/main/scala/top.scala index 7a472a94..52925b3e 100644 --- a/rocket/src/main/scala/top.scala +++ b/rocket/src/main/scala/top.scala @@ -27,25 +27,14 @@ class Top() extends Component { arbiter.io.requestor(2) <> htif.io.mem val hub = new CoherenceHubNull - // connect tile to hub (figure out how to do this more compactly) - val xact_init_q = (new queue(2)) { new TransactionInit } - xact_init_q.io.enq <> arbiter.io.mem.xact_init - xact_init_q.io.deq <> hub.io.tile.xact_init - val xact_init_data_q = (new queue(2)) { new TransactionInitData } - xact_init_data_q.io.enq <> arbiter.io.mem.xact_init_data - xact_init_data_q.io.deq <> hub.io.tile.xact_init_data - val xact_rep_q = (new queue(1, pipe = true)) { new TransactionReply } - xact_rep_q.io.enq <> hub.io.tile.xact_rep - xact_rep_q.io.deq <> arbiter.io.mem.xact_rep + // connect tile to hub + hub.io.tile.xact_init <> Queue(arbiter.io.mem.xact_init) + hub.io.tile.xact_init_data <> Queue(arbiter.io.mem.xact_init_data) + arbiter.io.mem.xact_rep <> Queue(hub.io.tile.xact_rep, 1, pipe = true) // connect hub to memory - val mem_req_q = (new queue(2)) { new MemReqCmd } - mem_req_q.io.enq <> hub.io.mem.req_cmd - mem_req_q.io.deq <> io.mem.req_cmd - val mem_req_data_q = (new queue(2)) { new MemData } - mem_req_data_q.io.enq <> hub.io.mem.req_data - mem_req_data_q.io.deq <> io.mem.req_data - hub.io.mem.resp.valid := Reg(io.mem.resp.valid, resetVal = Bool(false)) - hub.io.mem.resp.bits := Reg(io.mem.resp.bits) + io.mem.req_cmd <> Queue(hub.io.mem.req_cmd) + io.mem.req_data <> Queue(hub.io.mem.req_data) + hub.io.mem.resp <> PipeReg(io.mem.resp) if (HAVE_VEC) diff --git a/rocket/src/main/scala/util.scala b/rocket/src/main/scala/util.scala index 47361d2e..1856a3ba 100644 --- a/rocket/src/main/scala/util.scala +++ b/rocket/src/main/scala/util.scala @@ -166,14 +166,7 @@ class Mux1H [T <: Data](n: Int)(gen: => T) extends Component } - - - - - - - -class ioDecoupled[T <: Data]()(data: => T) extends Bundle +class ioDecoupled[+T <: Data]()(data: => T) extends Bundle { val valid = Bool(INPUT) val ready = Bool(OUTPUT) @@ -211,46 +204,51 @@ class Arbiter[T <: Data](n: Int)(data: => T) extends Component { dout <> io.out.bits } -class ioPriorityDecoder(in_width: Int, out_width: Int) extends Bundle -{ - val in = UFix(in_width, INPUT); - val out = Bits(out_width, OUTPUT); +class ioLockingArbiter[T <: Data](n: Int)(data: => T) extends Bundle { + val in = Vec(n) { (new ioDecoupled()) { data } } + val lock = Vec(n) { Bool() } + val out = (new ioDecoupled()) { data }.flip() } -class priorityDecoder(width: Int) extends Component -{ - val in_width = ceil(log10(width)/log10(2)).toInt; - val io = new ioPriorityEncoder(in_width, width); - val l_out = Wire() { Bits() }; - - l_out := Bits(0, width); - for (i <- width-1 to 0 by -1) { - when (io.in === UFix(i, in_width)) { - l_out := Bits(1,1) << UFix(i); +class LockingArbiter[T <: Data](n: Int)(data: => T) extends Component { + val io = new ioLockingArbiter(n)(data) + val locked = Reg(){ Bits(n) } + var dout = Wire(){ data } + var vout = Wire(){ Bool() } + + when((locked && io.lock.toBits).orR) { + dout := io.in(0).bits + for (i <- 0 until n) { + io.in(i).ready := io.out.ready && locked(i) + vout := io.in(i).valid && locked(i) + dout := Mux(locked(i), io.in(i).bits, dout) } - } - - io.out := l_out; -} - -class ioPriorityEncoder(in_width: Int, out_width: Int) extends Bundle -{ - val in = Bits(in_width, INPUT); - val out = UFix(out_width, OUTPUT); -} - -class priorityEncoder(width: Int) extends Component -{ - val out_width = ceil(log10(width)/log10(2)).toInt; - val io = new ioPriorityDecoder(width, out_width); - val l_out = Wire() { UFix() }; - - l_out := UFix(0, out_width); - for (i <- width-1 to 1 by -1) { - when (io.in(i).toBool) { - l_out := UFix(i, out_width); + } .otherwise { + io.in(0).ready := io.out.ready + for (i <- 1 until n) { + io.in(i).ready := !io.in(i-1).valid && io.in(i-1).ready + locked(i) := !io.in(i-1).valid && io.in(i-1).ready && io.lock(i) } + + dout := io.in(n-1).bits + for (i <- 1 until n) + dout = Mux(io.in(n-1-i).valid, io.in(n-1-i).bits, dout) + + vout := io.in(0).valid + for (i <- 1 until n) + vout = vout || io.in(i).valid + } + + vout <> io.out.valid + dout <> io.out.bits +} + +object PriorityEncoder +{ + def apply(in: Bits, n: Int = 0): UFix = { + if (n >= in.getWidth-1) + UFix(n) + else + Mux(in(n), UFix(n), PriorityEncoder(in, n+1)) } - - io.out := l_out; }