forked from pulp-platform/snitch_cluster
-
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.
- Loading branch information
1 parent
f936698
commit 58b4b4a
Showing
3 changed files
with
209 additions
and
6 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
125 changes: 125 additions & 0 deletions
125
hw/chisel_acc/src/main/scala/snax_acc/utils/CustomOperators.scala
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,125 @@ | ||
package snax_acc.utils | ||
|
||
import chisel3._ | ||
import chisel3.util._ | ||
|
||
/** The definition of -|> / -||> / -|||> connector for decoupled signal it | ||
* connects leftward Decoupled signal (Decoupled port) and rightward Decoupled | ||
* signal (Flipped port); and insert one level of pipeline in between to avoid | ||
* long combinatorial datapath | ||
*/ | ||
|
||
class DataCut[T <: Data](gen: T, delay: Int) extends Module { | ||
val io = IO(new Bundle { | ||
val in = Flipped(Decoupled(gen)) | ||
val out = Decoupled(gen) | ||
}) | ||
|
||
val in = Wire(ValidIO(gen)) | ||
val out = Wire(ValidIO(gen)) | ||
val shiftPermission = Wire(Bool()) | ||
val shiftSuggestion = Wire(Bool()) | ||
val shift = | ||
shiftPermission && shiftSuggestion // shift is true when both shiftPermission and shiftSuggestion are true | ||
in.bits := io.in.bits | ||
in.valid := io.in.valid | ||
io.in.ready := shiftPermission | ||
io.out.valid := out.valid | ||
io.out.bits := out.bits | ||
out := ShiftRegister(in, delay, shift) | ||
|
||
// shiftPermission is true when last item's valid is true and io.out.ready is true or last item's valid is false | ||
shiftPermission := (out.valid && io.out.ready) || !out.valid | ||
|
||
val dataInsideShiftRegister = Wire(Bool()) | ||
|
||
// shiftSuggestion is true when dataInsideShiftRegister is true or input.valid is true | ||
shiftSuggestion := dataInsideShiftRegister || io.in.valid | ||
|
||
// When the counter is abbout to overflow, data does not inside the shift register | ||
val insideCounter = Counter(0 to delay, shift, io.in.valid) | ||
dataInsideShiftRegister := insideCounter._1 =/= delay.U | ||
|
||
} | ||
|
||
object DecoupledCut { | ||
implicit class BufferedDecoupledConnectionOp[T <: Data]( | ||
val left: DecoupledIO[T] | ||
) { | ||
// This class defines the implicit class for the new operand -|>,-||>, -|||> for DecoupleIO | ||
|
||
def -|>( | ||
right: DecoupledIO[T] | ||
)(implicit sourceInfo: chisel3.experimental.SourceInfo): DecoupledIO[T] = { | ||
val buffer = Module( | ||
new Queue(chiselTypeOf(left.bits), entries = 1, pipe = false) | ||
) | ||
buffer.suggestName("fullCutHalfBandwidth") | ||
|
||
left <> buffer.io.enq | ||
buffer.io.deq <> right | ||
right | ||
} | ||
|
||
def -||>( | ||
right: DecoupledIO[T] | ||
)(implicit sourceInfo: chisel3.experimental.SourceInfo): DecoupledIO[T] = { | ||
val buffer = Module( | ||
new Queue(chiselTypeOf(left.bits), entries = 2, pipe = false) | ||
) | ||
buffer.suggestName("fullCutFullBandwidth") | ||
left <> buffer.io.enq | ||
buffer.io.deq <> right | ||
right | ||
} | ||
|
||
def -\>( | ||
right: DecoupledIO[T] | ||
)(implicit sourceInfo: chisel3.experimental.SourceInfo): DecoupledIO[T] = { | ||
val buffer = Module( | ||
new DataCut(chiselTypeOf(left.bits), delay = 1) | ||
) | ||
buffer.suggestName("dataCut1") | ||
|
||
left <> buffer.io.in | ||
buffer.io.out <> right | ||
right | ||
} | ||
|
||
def -\\>( | ||
right: DecoupledIO[T] | ||
)(implicit sourceInfo: chisel3.experimental.SourceInfo): DecoupledIO[T] = { | ||
val buffer = Module( | ||
new DataCut(chiselTypeOf(left.bits), delay = 2) | ||
) | ||
buffer.suggestName("dataCut2") | ||
|
||
left <> buffer.io.in | ||
buffer.io.out <> right | ||
right | ||
} | ||
|
||
def -\\\>( | ||
right: DecoupledIO[T] | ||
)(implicit sourceInfo: chisel3.experimental.SourceInfo): DecoupledIO[T] = { | ||
val buffer = Module( | ||
new DataCut(chiselTypeOf(left.bits), delay = 3) | ||
) | ||
buffer.suggestName("dataCut3") | ||
|
||
left <> buffer.io.in | ||
buffer.io.out <> right | ||
right | ||
} | ||
} | ||
} | ||
|
||
object BitsConcat { | ||
implicit class UIntConcatOp[T <: Bits](val left: T) { | ||
// This class defines the implicit class for the new operand ++ for UInt | ||
def ++( | ||
right: T | ||
)(implicit sourceInfo: chisel3.experimental.SourceInfo): T = | ||
Cat(left, right).asInstanceOf[T] | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
hw/chisel_acc/src/main/scala/snax_acc/utils/DecoupledCat.scala
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,44 @@ | ||
package snax_acc.utils | ||
|
||
import chisel3._ | ||
import chisel3.util._ | ||
|
||
class DecoupledCat2to1[T <: Data](aWidth: Int, bWidth: Int) extends Module{ | ||
val io = IO(new Bundle { | ||
val in1 = Flipped(Decoupled(UInt(aWidth.W))) // First decoupled input interface | ||
val in2 = Flipped(Decoupled(UInt(bWidth.W))) // Second decoupled input interface | ||
val out = Decoupled(UInt((aWidth + bWidth).W)) // Decoupled output interface | ||
}) | ||
|
||
// Combine the bits of in1 and in2, in1 in higher bits | ||
io.out.bits := Cat(io.in1.bits, io.in2.bits) | ||
|
||
// Output is valid only when both inputs are valid | ||
io.out.valid := io.in1.valid && io.in2.valid | ||
|
||
// Ready is asserted to inputs when the output is ready | ||
io.in1.ready := io.out.ready && io.out.valid | ||
io.in2.ready := io.out.ready && io.out.valid | ||
|
||
} | ||
|
||
class DecoupledSplit1to2(cWidth: Int, aWidth: Int, bWidth: Int) extends Module { | ||
require(cWidth == aWidth + bWidth, "cWidth must be the sum of aWidth and bWidth") | ||
|
||
val io = IO(new Bundle { | ||
val in = Flipped(Decoupled(UInt(cWidth.W))) // Large decoupled input (c) | ||
val out1 = Decoupled(UInt(aWidth.W)) // Smaller decoupled output (a) | ||
val out2 = Decoupled(UInt(bWidth.W)) // Smaller decoupled output (b) | ||
}) | ||
|
||
// Split the input bits into two parts | ||
io.out1.bits := io.in.bits(cWidth - 1, bWidth) // Upper bits go to out1 (a) | ||
io.out2.bits := io.in.bits(bWidth - 1, 0) // Lower bits go to out2 (b) | ||
|
||
// Both outputs are valid when the input is valid | ||
io.out1.valid := io.in.valid | ||
io.out2.valid := io.in.valid | ||
|
||
// Input is ready when both outputs are ready | ||
io.in.ready := io.out1.ready && io.out2.ready | ||
} |