-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from hutch31/master
Added dclib components
- Loading branch information
Showing
14 changed files
with
699 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package chisel.lib.dclib | ||
|
||
import chisel3._ | ||
import chisel3.util._ | ||
|
||
/** | ||
* Round-robin arbiter | ||
* | ||
* Accepts number of inputs and arbitrates between them on a per-cycle basis. | ||
* | ||
* @param data Data type of item to be arbitrated | ||
* @param inputs Number of inputs to arbiter | ||
* @param locking Creates a locking arbiter with a rearb input | ||
*/ | ||
class DCArbiter[D <: Data](data: D, inputs: Int, locking: Boolean) extends Module { | ||
val io = IO(new Bundle { | ||
val c = Vec(inputs, Flipped(Decoupled(data.cloneType))) | ||
val p = Decoupled(data.cloneType) | ||
val grant = Output(UInt(inputs.W)) | ||
val rearb = if(locking) Some(Input(UInt(inputs.W))) else None | ||
}) | ||
override def desiredName: String = "DCArbiter_" + data.toString | ||
|
||
val just_granted = RegInit(1.asUInt(inputs.W)) | ||
val to_be_granted = Wire(UInt(inputs.W)) | ||
val nxt_rr_locked = Wire(Bool()) | ||
val io_c_valid = Wire(UInt(inputs.W)) | ||
|
||
for (i <- 0 until inputs) { | ||
io.c(i).ready := to_be_granted(i) && io.p.ready | ||
} | ||
io.grant := to_be_granted | ||
|
||
def nxt_grant(cur_grant: UInt, cur_req: UInt, cur_accept: Bool): UInt = { | ||
val msk_req = Wire(UInt(inputs.W)) | ||
val tmp_grant = Wire(UInt(inputs.W)) | ||
val tmp_grant2 = Wire(UInt(inputs.W)) | ||
val rv = Wire(UInt(inputs.W)) | ||
|
||
msk_req := cur_req & ~((cur_grant - 1.U) | cur_grant) | ||
tmp_grant := msk_req & (~msk_req + 1.U) | ||
tmp_grant2 := cur_req & (~cur_req + 1.U) | ||
|
||
|
||
when(cur_accept) { | ||
when(msk_req =/= 0.U) { | ||
rv := tmp_grant | ||
}.otherwise { | ||
rv := tmp_grant2 | ||
} | ||
}.elsewhen(cur_req =/= 0.U) { | ||
when(msk_req =/= 0.U) { | ||
rv := Cat(tmp_grant(0), tmp_grant(inputs - 1, 1)) | ||
}.otherwise { | ||
rv := Cat(tmp_grant2(0), tmp_grant2(inputs - 1, 1)) | ||
} | ||
}.otherwise { | ||
rv := cur_grant | ||
} | ||
rv | ||
} | ||
|
||
io_c_valid := Cat(io.c.map(_.valid).reverse) | ||
|
||
io.p.valid := io_c_valid.orR() | ||
to_be_granted := just_granted | ||
|
||
if (locking) { | ||
val rr_locked = RegInit(false.B) | ||
|
||
when ((io_c_valid & just_granted).orR() && !rr_locked) { | ||
nxt_rr_locked := true.B | ||
}.elsewhen ((io_c_valid & just_granted & io.rearb.get).orR()) { | ||
nxt_rr_locked := false.B | ||
}.otherwise { | ||
nxt_rr_locked := rr_locked | ||
} | ||
|
||
when (nxt_rr_locked && (io_c_valid & just_granted).orR()) { | ||
to_be_granted := just_granted | ||
}.otherwise { | ||
when (io.p.ready) { | ||
to_be_granted := Cat(just_granted(0), just_granted(inputs-1,1)) | ||
}.otherwise { | ||
to_be_granted := just_granted | ||
} | ||
} | ||
} else { | ||
nxt_rr_locked := false.B | ||
to_be_granted := nxt_grant(just_granted, io_c_valid, io.p.ready) | ||
} | ||
|
||
when (to_be_granted =/= 0.U) { | ||
just_granted := to_be_granted | ||
} | ||
|
||
io.p.bits := io.c(0).bits | ||
for (i <- 0 until inputs) { | ||
when (to_be_granted(i)) { | ||
io.p.bits := io.c(i).bits | ||
} | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package chisel.lib.dclib | ||
|
||
import chisel3.util._ | ||
import chisel3._ | ||
|
||
/** | ||
* Demultiplex a stream of tokens with an identifier "sel", | ||
* as inverse of RRArbiter. | ||
* | ||
* @param data Data type of incoming/outgoing data | ||
* @param n Number of mux outputs | ||
*/ | ||
class DCDemux[D <: Data](data: D, n: Int) extends Module { | ||
val io = IO(new Bundle { | ||
val sel = Input(UInt(log2Ceil(n).W)) | ||
val c = Flipped(new DecoupledIO(data.cloneType)) | ||
val p = Vec(n, new DecoupledIO(data.cloneType)) | ||
}) | ||
override def desiredName: String = "DCDemux_" + data.toString | ||
|
||
io.c.ready := 0.U | ||
for (i <- 0 until n) { | ||
io.p(i).bits := io.c.bits | ||
when (i.U === io.sel) { | ||
io.p(i).valid := io.c.valid | ||
io.c.ready := io.p(i).ready | ||
}.otherwise { | ||
io.p(i).valid := 0.U | ||
} | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package chisel.lib.dclib | ||
import chisel3._ | ||
import chisel3.util._ | ||
|
||
/** | ||
* Provides timing closure on valid, ready and bits interfaces by | ||
* using DCInput and DCOutput back to back. Effectively a 2-entry | ||
* FIFO. | ||
*/ | ||
object DCFull { | ||
def apply[D <: Data](x : DecoupledIO[D]) : DecoupledIO[D] = { | ||
val tin = Module(new DCInput(x.bits.cloneType)) | ||
val tout = Module(new DCOutput(x.bits.cloneType)) | ||
tin.io.enq <> x | ||
tin.io.deq <> tout.io.enq | ||
tout.io.deq | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package chisel.lib.dclib | ||
|
||
import chisel3._ | ||
import chisel3.util.DecoupledIO | ||
|
||
/** | ||
* Creates a ready/valid holding register, will not accept new data | ||
* until current data word is unloaded. | ||
* | ||
* This block has no combinational paths through it, although it can | ||
* accept data at a maximum of every other cycle. | ||
* | ||
* @param data The data type for the payload | ||
*/ | ||
class DCHold[D <: Data](data: D) extends Module { | ||
val io = IO(new Bundle { | ||
val enq = Flipped(new DecoupledIO(data.cloneType)) | ||
val deq = new DecoupledIO(data.cloneType) | ||
}) | ||
override def desiredName: String = "DCHold_" + data.toString | ||
|
||
val p_valid = RegInit(init = 0.U) | ||
val p_data = Reg(data.cloneType) | ||
|
||
when (io.enq.valid && !p_valid) { | ||
p_valid := io.enq.valid | ||
p_data := io.enq.bits | ||
}.elsewhen((p_valid & io.deq.ready) === 1.U) { | ||
p_valid := 0.U | ||
} | ||
io.deq.valid := p_valid | ||
io.deq.bits := p_data | ||
io.enq.ready := ~p_valid | ||
} | ||
|
||
// Helper function for functional inference | ||
object DCHold { | ||
def apply[D <: Data](x : DecoupledIO[D]) : DecoupledIO[D] = { | ||
val tout = Module(new DCHold(x.bits.cloneType)) | ||
tout.io.enq <> x | ||
tout.io.deq | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package chisel.lib.dclib | ||
|
||
import chisel3._ | ||
import chisel3.util.DecoupledIO | ||
|
||
/** | ||
* Closes timing on the ready signal of a decoupled interface. Called an | ||
* "input" module because if used on input interfaces provides registered-output | ||
* ready. deq.valid and deq.bits have combination paths. | ||
* | ||
* Internally implements a single hold register to hold data in the event that | ||
* deq interface is not ready | ||
*/ | ||
class DCInput[D <: Data](data: D) extends Module { | ||
val io = IO(new Bundle { | ||
val enq = Flipped(new DecoupledIO(data.cloneType)) | ||
val deq = new DecoupledIO(data.cloneType) | ||
}) | ||
override def desiredName: String = "DCInput_" + data.toString | ||
|
||
// val r_valid = RegInit(false.B) | ||
val ready_r = RegInit(true.B) | ||
val occupied = RegInit(false.B) | ||
val hold = Reg(data.cloneType) | ||
val load = Wire(Bool()) | ||
val drain = Wire(Bool()) | ||
|
||
drain := occupied && io.deq.ready | ||
load := io.enq.valid && ready_r && (!io.deq.ready || drain) | ||
|
||
when (occupied) { | ||
io.deq.bits := hold | ||
}.otherwise { | ||
io.deq.bits := io.enq.bits | ||
} | ||
|
||
io.deq.valid := io.enq.valid || occupied | ||
when (load) { | ||
occupied := true.B | ||
hold := io.enq.bits | ||
}.elsewhen (drain) { | ||
occupied := false.B | ||
} | ||
|
||
ready_r := (!occupied && !load) || (drain && !load) | ||
io.enq.ready := ready_r | ||
} | ||
|
||
// Helper function for functional inference | ||
object DCInput { | ||
def apply[D <: Data](x: DecoupledIO[D]): DecoupledIO[D] = { | ||
val tout = Module(new DCInput(x.bits.cloneType)) | ||
tout.io.enq <> x | ||
tout.io.deq | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package chisel.lib.dclib | ||
import chisel3._ | ||
import chisel3.util._ | ||
|
||
/** | ||
* Sends tokens to multiple output destinations, as selected by bit | ||
* vector "dst". dst must have at least one bit set for correct | ||
* operation. | ||
* | ||
* @param data Payload data type | ||
* @param n Number of output destinations | ||
*/ | ||
class DCMirror[D <: Data](data: D, n: Int) extends Module { | ||
val io = IO(new Bundle { | ||
val dst = Input(UInt(n.W)) | ||
val c = Flipped(new DecoupledIO(data.cloneType)) | ||
val p = Vec(n, new DecoupledIO(data.cloneType)) | ||
}) | ||
|
||
val p_data = Reg(data.cloneType) | ||
val p_valid = RegInit(0.asUInt(n.W)) | ||
val p_ready = Cat(io.p.map(_.ready).reverse) | ||
val nxt_accept = (p_valid === 0.U) || ((p_valid =/= 0.U) && ((p_valid & p_ready) === p_valid)) | ||
|
||
when (nxt_accept) { | ||
p_valid := Fill(n, io.c.valid) & io.dst | ||
p_data := io.c.bits | ||
}.otherwise { | ||
p_valid := p_valid & ~p_ready | ||
} | ||
io.c.ready := nxt_accept | ||
|
||
for (i <- 0 until n) { | ||
io.p(i).bits := p_data | ||
io.p(i).valid := p_valid(i) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package chisel.lib.dclib | ||
|
||
import chisel3._ | ||
import chisel3.util._ | ||
|
||
/** | ||
* Closes output timing on an input of type D | ||
* deq.valid and deq.bits will be registered, enq.ready will be combinatorial | ||
*/ | ||
class DCOutput[D <: Data](data: D) extends Module { | ||
val io = IO(new Bundle { | ||
val enq = Flipped(new DecoupledIO(data.cloneType)) | ||
val deq = new DecoupledIO(data.cloneType) | ||
}) | ||
override def desiredName: String = "DCOutput_" + data.toString | ||
|
||
val r_valid = RegInit(false.B) | ||
|
||
io.enq.ready := io.deq.ready || !r_valid | ||
r_valid := io.enq.fire() || (r_valid && !io.deq.ready) | ||
io.deq.bits := RegEnable(next=io.enq.bits, enable=io.enq.fire()) | ||
io.deq.valid := r_valid | ||
} | ||
|
||
// Helper function for functional inference | ||
object DCOutput { | ||
def apply[D <: Data](x : DecoupledIO[D]) : DecoupledIO[D] = { | ||
val tout = Module(new DCOutput(x.bits.cloneType)) | ||
tout.io.enq <> x | ||
tout.io.deq | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
DecoupledIO Library | ||
=================== | ||
|
||
This is a library of components which are useful to building systems with DecoupledIO interfaces. | ||
|
||
## Components | ||
|
||
- DCInput | ||
- DCOutput | ||
- DCFull | ||
- DCHold | ||
- DCArbiter | ||
- DCDemux | ||
- DCMirror |
Oops, something went wrong.