REG1/REG2 refractoring RS1/RS2

Add CustomeInstruction example
This commit is contained in:
Charles Papon 2017-07-17 14:02:56 +02:00
parent 708a8f66de
commit 84bba3adf0
16 changed files with 135 additions and 63 deletions

View File

@ -39,8 +39,8 @@ class BranchPlugin(earlyBranch : Boolean,
SRC1_CTRL -> Src1CtrlEnum.RS,
SRC2_CTRL -> Src2CtrlEnum.RS,
SRC_USE_SUB_LESS -> True,
REG1_USE -> True,
REG2_USE -> True
RS1_USE -> True,
RS2_USE -> True
)
val jActions = List[(Stageable[_ <: BaseType],Any)](
@ -55,7 +55,7 @@ class BranchPlugin(earlyBranch : Boolean,
decoderService.addDefault(BRANCH_CTRL, BranchCtrlEnum.INC)
decoderService.add(List(
JAL -> (jActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.JAL, ALU_CTRL -> AluCtrlEnum.ADD_SUB)),
JALR -> (jActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.JALR, ALU_CTRL -> AluCtrlEnum.ADD_SUB, REG1_USE -> True)),
JALR -> (jActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.JALR, ALU_CTRL -> AluCtrlEnum.ADD_SUB, RS1_USE -> True)),
BEQ -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)),
BNE -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)),
BLT -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)),
@ -108,7 +108,7 @@ class BranchPlugin(earlyBranch : Boolean,
)
val imm = IMM(input(INSTRUCTION))
val branch_src1 = (input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? input(REG1).asUInt | input(PC)
val branch_src1 = (input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? input(RS1).asUInt | input(PC)
val branch_src2 = input(BRANCH_CTRL).mux(
BranchCtrlEnum.JAL -> imm.j_sext,
BranchCtrlEnum.JALR -> imm.i_sext,
@ -212,7 +212,7 @@ class BranchPlugin(earlyBranch : Boolean,
val branch_src1,branch_src2 = UInt(32 bits)
switch(input(BRANCH_CTRL)){
is(BranchCtrlEnum.JALR){
branch_src1 := input(REG1).asUInt
branch_src1 := input(RS1).asUInt
branch_src2 := imm.i_sext.asUInt
}
default{

View File

@ -188,7 +188,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
val nonImmediatActions = defaultCsrActions ++ List(
SRC1_CTRL -> Src1CtrlEnum.RS,
REG1_USE -> True
RS1_USE -> True
)
val immediatActions = defaultCsrActions

View File

@ -28,7 +28,7 @@ class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
SRC1_CTRL -> Src1CtrlEnum.RS,
SRC_USE_SUB_LESS -> False,
MEMORY_ENABLE -> True,
REG1_USE -> True
RS1_USE -> True
) ++ (if (catchUnaligned) List(IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB) else Nil) //Used for access fault bad address in memory stage
val loadActions = stdActions ++ List(
@ -40,7 +40,7 @@ class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
val storeActions = stdActions ++ List(
SRC2_CTRL -> Src2CtrlEnum.IMS,
REG2_USE -> True
RS2_USE -> True
)
decoderService.addDefault(MEMORY_ENABLE, False)
@ -52,7 +52,7 @@ class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
def MANAGEMENT = M"-------00000-----101-----0001111"
decoderService.add(MANAGEMENT, stdActions ++ List(
SRC2_CTRL -> Src2CtrlEnum.RS,
REG2_USE -> True
RS2_USE -> True
))
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.memory,memoryTranslatorPortConfig)
@ -104,9 +104,9 @@ class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
cache.io.cpu.execute.args.wr := input(INSTRUCTION)(5)
cache.io.cpu.execute.args.address := input(SRC_ADD).asUInt
cache.io.cpu.execute.args.data := size.mux(
U(0) -> input(REG2)( 7 downto 0) ## input(REG2)( 7 downto 0) ## input(REG2)(7 downto 0) ## input(REG2)(7 downto 0),
U(1) -> input(REG2)(15 downto 0) ## input(REG2)(15 downto 0),
default -> input(REG2)(31 downto 0)
U(0) -> input(RS2)( 7 downto 0) ## input(RS2)( 7 downto 0) ## input(RS2)(7 downto 0) ## input(RS2)(7 downto 0),
U(1) -> input(RS2)(15 downto 0) ## input(RS2)(15 downto 0),
default -> input(RS2)(31 downto 0)
)
cache.io.cpu.execute.args.size := size
cache.io.cpu.execute.args.forceUncachedAccess := False

View File

@ -116,7 +116,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean, catchAccessFault : Bool
SRC1_CTRL -> Src1CtrlEnum.RS,
SRC_USE_SUB_LESS -> False,
MEMORY_ENABLE -> True,
REG1_USE -> True
RS1_USE -> True
) ++ (if(catchAccessFault || catchAddressMisaligned) List(IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB) else Nil) //Used for access fault bad address in memory stage
val loadActions = stdActions ++ List(
@ -128,7 +128,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean, catchAccessFault : Bool
val storeActions = stdActions ++ List(
SRC2_CTRL -> Src2CtrlEnum.IMS,
REG2_USE -> True
RS2_USE -> True
)
decoderService.addDefault(MEMORY_ENABLE, False)
@ -166,9 +166,9 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean, catchAccessFault : Bool
dBus.cmd.address := input(SRC_ADD).asUInt
dBus.cmd.size := input(INSTRUCTION)(13 downto 12).asUInt
dBus.cmd.payload.data := dBus.cmd.size.mux (
U(0) -> input(REG2)(7 downto 0) ## input(REG2)(7 downto 0) ## input(REG2)(7 downto 0) ## input(REG2)(7 downto 0),
U(1) -> input(REG2)(15 downto 0) ## input(REG2)(15 downto 0),
default -> input(REG2)(31 downto 0)
U(0) -> input(RS2)(7 downto 0) ## input(RS2)(7 downto 0) ## input(RS2)(7 downto 0) ## input(RS2)(7 downto 0),
U(1) -> input(RS2)(15 downto 0) ## input(RS2)(15 downto 0),
default -> input(RS2)(31 downto 0)
)
when(arbitration.isValid && input(MEMORY_ENABLE) && !dBus.cmd.ready && !input(ALIGNEMENT_FAULT)){
arbitration.haltIt := True

View File

@ -17,8 +17,8 @@ class DivPlugin extends Plugin[VexRiscv]{
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> False,
BYPASSABLE_MEMORY_STAGE -> True,
REG1_USE -> True,
REG2_USE -> True,
RS1_USE -> True,
RS2_USE -> True,
IS_DIV -> True
)

View File

@ -27,10 +27,10 @@ class HazardSimplePlugin(bypassExecute : Boolean,
if (bypassable) {
when(runtimeBypassableValue) {
when(addr0Match) {
decode.input(REG1) := stage.output(REGFILE_WRITE_DATA)
decode.input(RS1) := stage.output(REGFILE_WRITE_DATA)
}
when(addr1Match) {
decode.input(REG2) := stage.output(REGFILE_WRITE_DATA)
decode.input(RS2) := stage.output(REGFILE_WRITE_DATA)
}
}
}
@ -62,10 +62,10 @@ class HazardSimplePlugin(bypassExecute : Boolean,
when(writeBackBuffer.valid) {
if (bypassWriteBackBuffer) {
when(addr0Match) {
decode.input(REG1) := writeBackBuffer.data
decode.input(RS1) := writeBackBuffer.data
}
when(addr1Match) {
decode.input(REG2) := writeBackBuffer.data
decode.input(RS2) := writeBackBuffer.data
}
} else {
when(addr0Match) {
@ -83,10 +83,10 @@ class HazardSimplePlugin(bypassExecute : Boolean,
if(!pessimisticUseSrc) {
when(!decode.input(REG1_USE)) {
when(!decode.input(RS1_USE)) {
src0Hazard := False
}
when(!decode.input(REG2_USE)) {
when(!decode.input(RS2_USE)) {
src1Hazard := False
}
}

View File

@ -86,13 +86,14 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean)
import pipeline._
import pipeline.config._
iBus = master(IBusSimpleBus(interfaceKeepData)).setName("iBus")
prefetch plug new Area {
val pendingCmd = RegInit(False) clearWhen (iBus.rsp.ready) setWhen (iBus.cmd.fire)
//Emit iBus.cmd request
iBus.cmd.valid := prefetch.arbitration.isValid && !prefetch.arbitration.isStuckByOthers && !(pendingCmd && !iBus.rsp.ready) //prefetch.arbitration.isValid && !prefetch.arbitration.isStuckByOthers
iBus.cmd.pc := prefetch.output(PC)
prefetch.arbitration.haltIt setWhen (!iBus.cmd.ready || (pendingCmd && !iBus.rsp.ready))
}
//Bus rsp buffer
val rspBuffer = if(!interfaceKeepData) new Area{

View File

@ -28,7 +28,7 @@ class IntAluPlugin extends Plugin[VexRiscv]{
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> True,
BYPASSABLE_MEMORY_STAGE -> True,
REG1_USE -> True
RS1_USE -> True
)
val nonImmediateActions = List[(Stageable[_ <: BaseType],Any)](
@ -37,8 +37,8 @@ class IntAluPlugin extends Plugin[VexRiscv]{
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> True,
BYPASSABLE_MEMORY_STAGE -> True,
REG1_USE -> True,
REG2_USE -> True
RS1_USE -> True,
RS2_USE -> True
)
val otherAction = List[(Stageable[_ <: BaseType],Any)](

View File

@ -31,8 +31,8 @@ class MemoryTranslatorPlugin(tlbSize : Int,
def TLBW1 = M"0000001----------111-----0001111"
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(IS_TLB, False)
decoderService.add(TLBW0, List(IS_TLB -> True, REG1_USE -> True, SRC1_CTRL -> Src1CtrlEnum.RS))
decoderService.add(TLBW1, List(IS_TLB -> True, REG1_USE -> True, REG2_USE -> True, SRC1_CTRL -> Src1CtrlEnum.RS))
decoderService.add(TLBW0, List(IS_TLB -> True, RS1_USE -> True, SRC1_CTRL -> Src1CtrlEnum.RS))
decoderService.add(TLBW1, List(IS_TLB -> True, RS1_USE -> True, RS2_USE -> True, SRC1_CTRL -> Src1CtrlEnum.RS))
}
override def build(pipeline: VexRiscv): Unit = {
@ -133,12 +133,12 @@ class MemoryTranslatorPlugin(tlbSize : Int,
is(1){
val line = CacheLine()
line.virtualAddress := tlbWriteBuffer
line.physicalAddress := input(REG2)(19 downto 0).asUInt
line.allowUser := input(REG2)(27)
line.allowRead := input(REG2)(28)
line.allowWrite := input(REG2)(29)
line.allowExecute := input(REG2)(30)
line.valid := input(REG2)(31)
line.physicalAddress := input(RS2)(19 downto 0).asUInt
line.allowUser := input(RS2)(27)
line.allowRead := input(RS2)(28)
line.allowWrite := input(RS2)(29)
line.allowExecute := input(RS2)(30)
line.valid := input(RS2)(31)
core.shared.cache(input(SRC1)(log2Up(tlbSize)-1 downto 0).asUInt) := line
core.ports.foreach(_.cache.foreach(_.valid := False)) //Invalidate all ports caches

View File

@ -24,8 +24,8 @@ class MulPlugin extends Plugin[VexRiscv]{
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> False,
BYPASSABLE_MEMORY_STAGE -> False,
REG1_USE -> True,
REG2_USE -> True,
RS1_USE -> True,
RS2_USE -> True,
IS_MUL -> True
)

View File

@ -17,8 +17,8 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,zeroBoot : Boolean = fals
override def setup(pipeline: VexRiscv): Unit = {
import pipeline.config._
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(REG1_USE,False)
decoderService.addDefault(REG2_USE,False)
decoderService.addDefault(RS1_USE,False)
decoderService.addDefault(RS2_USE,False)
decoderService.addDefault(REGFILE_WRITE_VALID,False)
}
@ -54,8 +54,8 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,zeroBoot : Boolean = fals
case `SYNC` => (global.regFile.readSync(regFileReadAddress1),global.regFile.readSync(regFileReadAddress2))
}
insert(REG1) := rs1Data
insert(REG2) := rs2Data
insert(RS1) := rs1Data
insert(RS2) := rs2Data
}
//Write register file

View File

@ -26,7 +26,7 @@ class FullBarrielShifterPlugin extends Plugin[VexRiscv]{
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> False,
BYPASSABLE_MEMORY_STAGE -> True,
REG1_USE -> True
RS1_USE -> True
)
val nonImmediateActions = List[(Stageable[_ <: BaseType],Any)](
@ -35,8 +35,8 @@ class FullBarrielShifterPlugin extends Plugin[VexRiscv]{
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> False,
BYPASSABLE_MEMORY_STAGE -> True,
REG1_USE -> True,
REG2_USE -> True
RS1_USE -> True,
RS2_USE -> True
)
val decoderService = pipeline.service(classOf[DecoderService])
@ -109,7 +109,7 @@ class LightShifterPlugin extends Plugin[VexRiscv]{
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> True,
BYPASSABLE_MEMORY_STAGE -> True,
REG1_USE -> True
RS1_USE -> True
)
val nonImmediateActions = List[(Stageable[_ <: BaseType],Any)](
@ -120,8 +120,8 @@ class LightShifterPlugin extends Plugin[VexRiscv]{
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> True,
BYPASSABLE_MEMORY_STAGE -> True,
REG1_USE -> True,
REG2_USE -> True
RS1_USE -> True,
RS2_USE -> True
)
val decoderService = pipeline.service(classOf[DecoderService])

View File

@ -14,12 +14,12 @@ class SrcPlugin(separatedAddSub : Boolean, executeInsertion : Boolean = false) e
val imm = Riscv.IMM(input(INSTRUCTION))
insert(SRC1) := input(SRC1_CTRL).mux(
Src1CtrlEnum.RS -> output(REG1),
Src1CtrlEnum.RS -> output(RS1),
Src1CtrlEnum.FOUR -> B(4),
Src1CtrlEnum.IMU -> imm.u.resized
)
insert(SRC2) := input(SRC2_CTRL).mux(
Src2CtrlEnum.RS -> output(REG2),
Src2CtrlEnum.RS -> output(RS2),
Src2CtrlEnum.IMI -> imm.i_sext.resized,
Src2CtrlEnum.IMS -> imm.s_sext.resized,
Src2CtrlEnum.PC -> output(PC).asBits

View File

@ -19,6 +19,7 @@
package VexRiscv
import VexRiscv.Plugin._
import VexRiscv.demo.SimdAddPlugin
import spinal.core._
import spinal.lib._
import VexRiscv.ip._

View File

@ -1,19 +1,17 @@
package VexRiscv
import VexRiscv.Plugin.Plugin
import VexRiscv.Plugin._
import spinal.core._
import spinal.lib._
import scala.collection.mutable.ArrayBuffer
case class VexRiscvConfig(plugins : Seq[Plugin[VexRiscv]]){
//Default Stageables
object BYPASSABLE_EXECUTE_STAGE extends Stageable(Bool)
object BYPASSABLE_MEMORY_STAGE extends Stageable(Bool)
object REG1 extends Stageable(Bits(32 bits))
object REG2 extends Stageable(Bits(32 bits))
object REG1_USE extends Stageable(Bool)
object REG2_USE extends Stageable(Bool)
object RS1 extends Stageable(Bits(32 bits))
object RS2 extends Stageable(Bits(32 bits))
object RS1_USE extends Stageable(Bool)
object RS2_USE extends Stageable(Bool)
object RESULT extends Stageable(UInt(32 bits))
object PC extends Stageable(UInt(32 bits))
object PC_CALC_WITHOUT_JUMP extends Stageable(UInt(32 bits))

View File

@ -0,0 +1,72 @@
package VexRiscv.demo
import spinal.core._
import VexRiscv.Plugin.Plugin
import VexRiscv.{Stageable, DecoderService, VexRiscv}
//This plugin example will add a new instruction named SIMD_ADD which do the following :
//
//RD : Regfile Destination, RS : Regfile Source
//RD( 7 downto 0) = RS1( 7 downto 0) + RS2( 7 downto 0)
//RD(16 downto 8) = RS1(16 downto 8) + RS2(16 downto 8)
//RD(23 downto 16) = RS1(23 downto 16) + RS2(23 downto 16)
//RD(31 downto 24) = RS1(31 downto 24) + RS2(31 downto 24)
//
//Instruction encoding :
//0000011----------000-----0110011
// |RS2||RS1| |RD |
//
//Note : RS1, RS2, RD positions follow the RISC-V spec and are common for all instruction of the ISA
class SimdAddPlugin extends Plugin[VexRiscv]{
//Define the concept of IS_SIMD_ADD signals, which specify if the current instruction is destined for ths plugin
object IS_SIMD_ADD extends Stageable(Bool)
//Callback to setup the plugin and ask for different services
override def setup(pipeline: VexRiscv): Unit = {
import pipeline.config._
//Retrieve the DecoderService instance
val decoderService = pipeline.service(classOf[DecoderService])
//Specify the IS_SIMD_ADD default value when instruction are decoded
decoderService.addDefault(IS_SIMD_ADD, False)
//Specify the instruction decoding which should be applied when the instruction match the 'key' parttern
decoderService.add(
//Bit pattern of the new SIMD_ADD instruction
key = M"0000011----------000-----0110011",
//Decoding specification when the 'key' pattern is recognized in the instruction
List(
IS_SIMD_ADD -> True,
REGFILE_WRITE_VALID -> True, //Enable the register file write
BYPASSABLE_EXECUTE_STAGE -> True, //Notify the hazard management unit that the instruction result is already accessible in the EXECUTE stage (Bypass ready)
BYPASSABLE_MEMORY_STAGE -> True, //Same as above but for the memory stage
RS1_USE -> True, //Notify the hazard management unit that this instruction use the RS1 value
RS2_USE -> True //Same than above but for RS2.
)
)
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
//Define some signals used internally to the plugin
val rs1 = execute.input(RS1).asUInt //32 bits UInt value of the regfile[RS1]
val rs2 = execute.input(RS2).asUInt
val rd = UInt(32 bits)
//Do some computation
rd( 7 downto 0) := rs1( 7 downto 0) + rs2( 7 downto 0)
rd(16 downto 8) := rs1(16 downto 8) + rs2(16 downto 8)
rd(23 downto 16) := rs1(23 downto 16) + rs2(23 downto 16)
rd(31 downto 24) := rs1(31 downto 24) + rs2(31 downto 24)
//When the instruction is a SIMD_ADD one, then write the result into the register file data path.
when(execute.input(IS_SIMD_ADD)){
execute.output(REGFILE_WRITE_DATA) := rd.asBits
}
}
}