Skip to content

Commit

Permalink
Replace the ExecutionUnitElementSimple implicit API with a cleaner ex…
Browse files Browse the repository at this point in the history
…plicit one
  • Loading branch information
Dolu1990 committed Jan 5, 2024
1 parent cf265e7 commit 98c01e1
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 32 deletions.
3 changes: 1 addition & 2 deletions src/main/scala/vexiiriscv/execute/BarrelShifterPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ class BarrelShifterPlugin(val layer : LaneLayer,
awaitBuild()
import SrcKeys._

val wb = ifp.access(formatAt)
implicit val _ = ifp -> wb
val wb = newWriteback(ifp, formatAt)

//TODO why using SRC1 ? why not directly RS1 => less combinatorial path, also not sure about SRC2 is realy wort it (for only 5/ 6 bits)
add(Rvi.SLL).srcs(SRC1.RF, SRC2.RF).decode(LEFT -> True, SIGNED -> False)
Expand Down
3 changes: 1 addition & 2 deletions src/main/scala/vexiiriscv/execute/DivPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ class DivPlugin(val layer : LaneLayer,
val logic = during setup new Logic {
awaitBuild()

val formatBus = ifp.access(writebackAt)
implicit val _ = ifp -> formatBus
val formatBus = newWriteback(ifp, writebackAt)

add(Rvi.DIV ).decode(REM -> False).rsUnsigned(true , true )
add(Rvi.DIVU).decode(REM -> False).rsUnsigned(false , false)
Expand Down
21 changes: 15 additions & 6 deletions src/main/scala/vexiiriscv/execute/ExecutionUnitElementSimple.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,24 @@ import vexiiriscv.riscv.{MicroOp, RD, RfResource}


object ExecuteUnitElementSimple{
class Api(implName : LaneLayer, val srcPlugin: SrcPlugin, val SEL : Payload[Bool], val rsUnsignedPlugin: RsUnsignedPlugin = null){
def add(microOp: MicroOp)(implicit iifpp: (IntFormatPlugin, Flow[Bits]) = null,
iwbpp: (WriteBackPlugin, Flow[Bits]) = null) = new {
val impl = implName.add(microOp)
class Api(layer : LaneLayer, val srcPlugin: SrcPlugin, val SEL : Payload[Bool], val rsUnsignedPlugin: RsUnsignedPlugin = null){
var iwbpp = Option.empty[(IntFormatPlugin, Flow[Bits])]
def setWriteback(ifp : IntFormatPlugin, bus : Flow[Bits]): Unit = {
iwbpp = Some(ifp -> bus)
}
def newWriteback(ifp: IntFormatPlugin, at : Int) : Flow[Bits] = {
val bus = ifp.access(at)
setWriteback(ifp, bus)
bus
}

def add(microOp: MicroOp) = new {
val impl = layer.add(microOp)
val spec = layer(microOp)

decode(SEL -> True)

if (iifpp != null) iifpp._1.addMicroOp(iifpp._2, impl)
if (iwbpp != null) iwbpp._1.addMicroOp(iwbpp._2, impl)
iwbpp.foreach(v => v._1.addMicroOp(v._2, impl))

def decode(decoding: DecodeListType = Nil): this.type = {
impl.addDecoding(decoding)
Expand Down
9 changes: 4 additions & 5 deletions src/main/scala/vexiiriscv/execute/IntAluPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ class IntAluPlugin(var layer: LaneLayer,
val ace = AluCtrlEnum
val abce = AluBitwiseCtrlEnum

val formatBus = ifp.access(formatAt)
implicit val _ = ifp -> formatBus
val wb = newWriteback(ifp, formatAt)

add(Rvi.ADD ).srcs(Op.ADD , SRC1.RF, SRC2.RF).decode(ALU_CTRL -> ace.ADD_SUB )
add(Rvi.SUB ).srcs(Op.SUB , SRC1.RF, SRC2.RF).decode(ALU_CTRL -> ace.ADD_SUB )
Expand All @@ -63,7 +62,7 @@ class IntAluPlugin(var layer: LaneLayer,
add(Rvi.ADDIW).srcs(Op.ADD , SRC1.RF, SRC2.I ).decode(ALU_CTRL -> ace.ADD_SUB)

for(op <- List(Rvi.ADDW, Rvi.SUBW, Rvi.ADDIW)){
ifp.signExtend(formatBus, layer(op), 32)
ifp.signExtend(wb, layer(op), 32)
}
}

Expand All @@ -88,8 +87,8 @@ class IntAluPlugin(var layer: LaneLayer,
}

val format = new eu.Execute(formatAt) {
formatBus.valid := SEL
formatBus.payload := ALU_RESULT
wb.valid := SEL
wb.payload := ALU_RESULT
}
}
}
4 changes: 2 additions & 2 deletions src/main/scala/vexiiriscv/execute/IntFormatPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ class IntFormatPlugin(val laneName : String) extends FiberPlugin{
}
val portToSpec = mutable.LinkedHashMap[Flow[Bits],Spec]()

def access(ctrlId : Int) : Flow[Bits] = {
def access(executeId : Int) : Flow[Bits] = {
val port = Flow(Bits(Riscv.XLEN bits))
portToSpec(port) = Spec(port, ctrlId)
portToSpec(port) = Spec(port, executeId)
port
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/vexiiriscv/execute/MulPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ class MulPlugin(val layer : LaneLayer,
eu.setDecodingDefault(HIGH, False)
}

val formatBus = ifp.access(writebackAt)
implicit val _ = ifp -> formatBus
val formatBus = newWriteback(ifp, writebackAt)

add(Rvi.MUL ).decode(HIGH -> False).rsUnsigned(true , true , useRsUnsignedPlugin)
add(Rvi.MULH ).decode(HIGH -> True ).rsUnsigned(true , true , useRsUnsignedPlugin)
add(Rvi.MULHSU).decode(HIGH -> True ).rsUnsigned(true , false, useRsUnsignedPlugin)
Expand Down
30 changes: 17 additions & 13 deletions src/main/scala/vexiiriscv/execute/SimdAddPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,36 @@ object SimdAddPlugin{
val ADD4 = IntRegFile.TypeR(M"0000000----------000-----0001011")
}

//ExecutionUnitElementSimple Is a base class which will be coupled to the pipeline provided by a ExecutionUnitBase with
//the same euId. It provide quite a few utilities to ease the implementation of custom instruction.
//ExecutionUnitElementSimple is a plugin base class which will integrate itself in a execute lane layer
//It provide quite a few utilities to ease the implementation of custom instruction.
//Here we will implement a plugin which provide SIMD add on the register file.
//staticLatency=true specify that our plugin will never halt the pipeling, allowing the issue queue to statically
//wake up instruction which depend on its result.
class SimdAddPlugin(val layer : LaneLayer) extends ExecutionUnitElementSimple(layer) {

//The setup code is by plugins to specify things to each others before it is too late
//create early blockOfCode will
val logic = during setup new Logic{
//Let's assume we only support RV32 for now
//Here we create an elaboration thread. The Logic class is provided by ExecutionUnitElementSimple to provide functionalities
val logic = during setup new Logic {
//Here we could have lock the elaboration of some other plugins (ex CSR), but here we don't need any of that
//as all is already sorted out in the Logic base class.
//So we just wait for the build phase
awaitBuild()

//Let's assume we only support RV32 for now
assert(Riscv.XLEN.get == 32)

val wb = ifp.access(0)
implicit val _ = ifp -> wb
//Let's get the hardware interface that we will use to provide the result of our custom instruction
val wb = newWriteback(ifp, 0)

//Specify that the current plugin will implement the ADD4 instruction
add(SimdAddPlugin.ADD4)
layer(SimdAddPlugin.ADD4).addRsSpec(RS1, 0)
layer(SimdAddPlugin.ADD4).addRsSpec(RS2, 0)
val add4 = add(SimdAddPlugin.ADD4).spec

//We need to specify on which stage we start using the register file values
add4.addRsSpec(RS1, executeAt = 0)
add4.addRsSpec(RS2, executeAt = 0)

//Now that we are done specifying everything about the instructions, we can release the Logic.uopRetainer
//This will allow a few other plugins to continue their elaboration (ex : decoder, dispatcher, ...)
uopRetainer.release()

//Let's define some logic in the execute lane [0]
val process = new eu.Execute(id = 0) {
//Get the RISC-V RS1/RS2 values from the register file
val rs1 = eu(IntRegFile, RS1).asUInt
Expand Down

0 comments on commit 98c01e1

Please sign in to comment.