WIP
This commit is contained in:
parent
fc7e9a7730
commit
fcb70a333f
|
@ -1,12 +1,12 @@
|
|||
name := "SpinalBaseProject"
|
||||
name := "VexRiscv"
|
||||
|
||||
version := "1.0"
|
||||
|
||||
scalaVersion := "2.11.6"
|
||||
scalaVersion := "2.11.8"
|
||||
|
||||
EclipseKeys.withSource := true
|
||||
|
||||
libraryDependencies ++= Seq(
|
||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "latest.release",
|
||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "latest.release"
|
||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "0.10.11",
|
||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "0.10.11"
|
||||
)
|
|
@ -15,12 +15,14 @@ trait Pipeline {
|
|||
def indexOf(stage : Stage) = stages.indexOf(stage)
|
||||
|
||||
def service[T](clazz : Class[T]) = {
|
||||
val filtered = plugins.filter(o => classOf[PcManagerService].isAssignableFrom(o.getClass))
|
||||
val filtered = plugins.filter(o => clazz.isAssignableFrom(o.getClass))
|
||||
assert(filtered.length == 1)
|
||||
filtered.head.asInstanceOf[T]
|
||||
}
|
||||
|
||||
def build(): Unit ={
|
||||
plugins.foreach(_.setup(this.asInstanceOf[T]))
|
||||
|
||||
//Build plugins
|
||||
plugins.foreach(_.build(this.asInstanceOf[T]))
|
||||
|
||||
|
@ -31,7 +33,7 @@ trait Pipeline {
|
|||
var lastOutputStageId = Int.MinValue
|
||||
|
||||
def addInputStageIndex(stageId : Int): Unit = {
|
||||
require(stageId > insertStageId)
|
||||
require(stageId >= insertStageId)
|
||||
lastInputStageId = Math.max(lastInputStageId,stageId)
|
||||
lastOutputStageId = Math.max(lastOutputStageId,stageId-1)
|
||||
}
|
||||
|
@ -39,7 +41,7 @@ trait Pipeline {
|
|||
|
||||
def addOutputStageIndex(stageId : Int): Unit = {
|
||||
require(stageId >= insertStageId)
|
||||
if(stageId != insertStageId) lastInputStageId = Math.min(lastInputStageId,stageId)
|
||||
lastInputStageId = Math.max(lastInputStageId,stageId)
|
||||
lastOutputStageId = Math.max(lastOutputStageId,stageId)
|
||||
}
|
||||
|
||||
|
@ -47,8 +49,20 @@ trait Pipeline {
|
|||
}
|
||||
|
||||
val inputOutputKeys = mutable.HashMap[Stageable[Data],KeyInfo]()
|
||||
val insertedStageable = mutable.Set[Stageable[Data]]()
|
||||
for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)){
|
||||
stage.inserts.keysIterator.foreach(signal => inputOutputKeys.getOrElseUpdate(signal,new KeyInfo).setInsertStageId(stageIndex))
|
||||
stage.inserts.keysIterator.foreach(insertedStageable += _)
|
||||
}
|
||||
|
||||
val missingInserts = mutable.Set[Stageable[Data]]()
|
||||
for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)){
|
||||
stage.inputs.keysIterator.foreach(key => if(!insertedStageable.contains(key)) missingInserts += key)
|
||||
stage.outputs.keysIterator.foreach(key => if(!insertedStageable.contains(key)) missingInserts += key)
|
||||
}
|
||||
|
||||
if(missingInserts.nonEmpty){
|
||||
throw new Exception("Missing inserts : " + missingInserts.map(_.getName()).mkString(", "))
|
||||
}
|
||||
|
||||
for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)){
|
||||
|
@ -63,22 +77,22 @@ trait Pipeline {
|
|||
stage.output(key)
|
||||
val outputDefault = stage.outputsDefault.getOrElse(key, null)
|
||||
if (outputDefault != null) {
|
||||
if (stageIndex == info.insertStageId) {
|
||||
outputDefault := stage.inserts(key)
|
||||
} else {
|
||||
outputDefault := stage.input(key)
|
||||
}
|
||||
outputDefault := stage.input(key)
|
||||
}
|
||||
}
|
||||
|
||||
//Interconnect outputs -> inputs
|
||||
for(stageIndex <- info.insertStageId + 1 to info.lastInputStageId) {
|
||||
val stageBefore = stages(stageIndex - 1)
|
||||
for(stageIndex <- info.insertStageId to info.lastInputStageId) {
|
||||
val stage = stages(stageIndex)
|
||||
stage.input(key)
|
||||
val inputDefault = stage.inputsDefault.getOrElse(key, null)
|
||||
if (inputDefault != null) {
|
||||
inputDefault := RegNextWhen(stageBefore.output(key),!stageBefore.arbitration.isStuck) //!stage.input.valid || stage.input.ready
|
||||
if (stageIndex == info.insertStageId) {
|
||||
inputDefault := stage.inserts(key)
|
||||
} else {
|
||||
val stageBefore = stages(stageIndex - 1)
|
||||
inputDefault := RegNextWhen(stageBefore.output(key), !stageBefore.arbitration.isStuck) //!stage.input.valid || stage.input.ready
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,19 @@ class Stageable[T <: Data](dataType : T) extends HardType[T](dataType) with Name
|
|||
}
|
||||
|
||||
class Stage() extends Area{
|
||||
def outsideCondScope[T](that : => T) : T = {
|
||||
val condStack = GlobalData.get.conditionalAssignStack.stack.toList
|
||||
val switchStack = GlobalData.get.switchStack.stack.toList
|
||||
GlobalData.get.conditionalAssignStack.stack.clear()
|
||||
GlobalData.get.switchStack.stack.clear()
|
||||
val ret = that
|
||||
GlobalData.get.conditionalAssignStack.stack.pushAll(condStack.reverseIterator)
|
||||
GlobalData.get.switchStack.stack.pushAll(switchStack.reverseIterator)
|
||||
ret
|
||||
}
|
||||
|
||||
def input[T <: Data](key : Stageable[T]) : T = {
|
||||
inputs.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],{
|
||||
inputs.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],outsideCondScope{
|
||||
val input,inputDefault = key()
|
||||
inputsDefault(key.asInstanceOf[Stageable[Data]]) = inputDefault
|
||||
input := inputDefault
|
||||
|
@ -21,7 +32,7 @@ class Stage() extends Area{
|
|||
}
|
||||
|
||||
def output[T <: Data](key : Stageable[T]) : T = {
|
||||
outputs.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],{
|
||||
outputs.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],outsideCondScope{
|
||||
val output,outputDefault = key()
|
||||
outputsDefault(key.asInstanceOf[Stageable[Data]]) = outputDefault
|
||||
output := outputDefault
|
||||
|
@ -29,7 +40,7 @@ class Stage() extends Area{
|
|||
}).asInstanceOf[T]
|
||||
}
|
||||
|
||||
def insert[T <: Data](key : Stageable[T]) : T = inserts.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],key()).asInstanceOf[T].setPartialName(this,key.getName())
|
||||
def insert[T <: Data](key : Stageable[T]) : T = inserts.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],outsideCondScope(key())).asInstanceOf[T].setPartialName(this,key.getName())
|
||||
// def apply[T <: Data](key : Stageable[T]) : T = ???
|
||||
|
||||
|
||||
|
|
|
@ -18,9 +18,12 @@
|
|||
|
||||
package SpinalRiscv
|
||||
|
||||
import java.io.File
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
|
||||
|
@ -30,20 +33,83 @@ object Riscv{
|
|||
def funct3Range = 14 downto 12
|
||||
def rs1Range = 19 downto 15
|
||||
def rs2Range = 24 downto 20
|
||||
|
||||
case class IMM(instruction : Bits) extends Area{
|
||||
// immediates
|
||||
def i = instruction(31 downto 20)
|
||||
def s = instruction(31, 25) ## instruction(11, 7)
|
||||
def b = instruction(31) ## instruction(7) ## instruction(30 downto 25) ## instruction(11 downto 8)
|
||||
def u = instruction(31 downto 12) ## U"x000"
|
||||
def j = instruction(31) ## instruction(19 downto 12) ## instruction(20) ## instruction(30 downto 21)
|
||||
def z = instruction(19 downto 15)
|
||||
|
||||
// sign-extend immediates
|
||||
def i_sext = B((19 downto 0) -> i(11)) ## i
|
||||
def s_sext = B((19 downto 0) -> s(11)) ## s
|
||||
def b_sext = B((18 downto 0) -> b(11)) ## b ## False
|
||||
def j_sext = B((10 downto 0) -> j(19)) ## j ## False
|
||||
}
|
||||
|
||||
|
||||
def ADD = M"0000000----------000-----0110011"
|
||||
def SUB = M"0100000----------000-----0110011"
|
||||
def SLL = M"0000000----------001-----0110011"
|
||||
def SLT = M"0000000----------010-----0110011"
|
||||
def SLTU = M"0000000----------011-----0110011"
|
||||
def XOR = M"0000000----------100-----0110011"
|
||||
def SRL = M"0000000----------101-----0110011"
|
||||
def SRA = M"0100000----------101-----0110011"
|
||||
def OR = M"0000000----------110-----0110011"
|
||||
def AND = M"0000000----------111-----0110011"
|
||||
|
||||
def ADDI = M"-----------------000-----0010011"
|
||||
def SLLI = M"000000-----------001-----0010011"
|
||||
def SLTI = M"-----------------010-----0010011"
|
||||
def SLTIU = M"-----------------011-----0010011"
|
||||
def XORI = M"-----------------100-----0010011"
|
||||
def SRLI = M"000000-----------101-----0010011"
|
||||
def SRAI = M"010000-----------101-----0010011"
|
||||
def ORI = M"-----------------110-----0010011"
|
||||
def ANDI = M"-----------------111-----0010011"
|
||||
}
|
||||
|
||||
|
||||
|
||||
case class VexRiscvConfig(pcWidth : Int){
|
||||
val plugins = ArrayBuffer[Plugin[VexRiscv]]()
|
||||
|
||||
//Default Stageables
|
||||
object Execute0Bypass extends Stageable(Bool)
|
||||
object BYPASSABLE_EXECUTE_STAGE extends Stageable(Bool)
|
||||
object BYPASSABLE_MEMORY_STAGE extends Stageable(Bool)
|
||||
object Execute1Bypass extends Stageable(Bool)
|
||||
object SRC1 extends Stageable(Bits(32 bits))
|
||||
object SRC2 extends Stageable(Bits(32 bits))
|
||||
object REG1 extends Stageable(Bits(32 bits))
|
||||
object REG2 extends Stageable(Bits(32 bits))
|
||||
object RESULT extends Stageable(UInt(32 bits))
|
||||
object PC extends Stageable(UInt(pcWidth bits))
|
||||
object INSTRUCTION extends Stageable(Bits(32 bits))
|
||||
object LEGAL_INSTRUCTION extends Stageable(Bool)
|
||||
object REGFILE_WRITE_VALID extends Stageable(Bool)
|
||||
object REGFILE_WRITE_DATA extends Stageable(Bits(32 bits))
|
||||
|
||||
object SRC1 extends Stageable(Bits(32 bits))
|
||||
object SRC2 extends Stageable(Bits(32 bits))
|
||||
object SRC_ADD_SUB extends Stageable(Bits(32 bits))
|
||||
object SRC_LESS extends Stageable(Bool)
|
||||
object SRC_USE_SUB_LESS extends Stageable(Bool)
|
||||
object SRC_LESS_UNSIGNED extends Stageable(Bool)
|
||||
|
||||
|
||||
object ALU_RESULT extends Stageable(Bits(32 bits))
|
||||
|
||||
object Src1CtrlEnum extends SpinalEnum(binarySequential){
|
||||
val RS, IMU, IMZ, IMJB = newElement()
|
||||
}
|
||||
|
||||
object Src2CtrlEnum extends SpinalEnum(binarySequential){
|
||||
val RS, IMI, IMS, PC = newElement()
|
||||
}
|
||||
object SRC1_CTRL extends Stageable(Src1CtrlEnum())
|
||||
object SRC2_CTRL extends Stageable(Src2CtrlEnum())
|
||||
}
|
||||
|
||||
|
||||
|
@ -58,17 +124,40 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{
|
|||
|
||||
|
||||
trait DecoderService{
|
||||
def add(key : MaskedLiteral,values : Seq[(Stageable[_],BaseType)])
|
||||
def add(encoding :Seq[(MaskedLiteral,Seq[(Stageable[_],BaseType)])])
|
||||
def add(key : MaskedLiteral,values : Seq[(Stageable[_ <: Data],Any)])
|
||||
def add(encoding :Seq[(MaskedLiteral,Seq[(Stageable[_ <: Data],Any)])])
|
||||
}
|
||||
|
||||
class DecoderSimplePlugin extends Plugin[VexRiscv] with DecoderService {
|
||||
override def add(encoding: Seq[(MaskedLiteral, Seq[(Stageable[_], BaseType)])]): Unit = encoding.foreach(e => this.add(e._1,e._2))
|
||||
override def add(key: MaskedLiteral, values: Seq[(Stageable[_], BaseType)]): Unit = {
|
||||
???
|
||||
override def add(encoding: Seq[(MaskedLiteral, Seq[(Stageable[_ <: Data], Any)])]): Unit = encoding.foreach(e => this.add(e._1,e._2))
|
||||
override def add(key: MaskedLiteral, values: Seq[(Stageable[_ <: Data], Any)]): Unit = {
|
||||
require(!encodings.contains(key))
|
||||
encodings(key) = values.map{case (a,b) => (a,b match{
|
||||
case e : SpinalEnumElement[_] => e()
|
||||
case e => e
|
||||
})}
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = ???
|
||||
val encodings = mutable.HashMap[MaskedLiteral,Seq[(Stageable[_ <: Data], Any)]]()
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
import pipeline.decode._
|
||||
import pipeline.config._
|
||||
|
||||
val stageables = encodings.flatMap(_._2.map(_._1)).toSet
|
||||
stageables.foreach(e => (insert(e).asInstanceOf[Data] := e().asInstanceOf[Data].getZero))
|
||||
stageables.foreach(insert(_) match{
|
||||
case e : Bits => println(e.getWidth)
|
||||
case _ =>
|
||||
})
|
||||
for((key,values) <- encodings){
|
||||
when(input(INSTRUCTION) === key){
|
||||
for((stageable,value) <- values){
|
||||
insert(stageable).assignFrom(value.asInstanceOf[AnyRef],false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait PcManagerService{
|
||||
|
@ -166,8 +255,8 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind) extends Plugin[VexRiscv]
|
|||
decode plug new Area{
|
||||
import decode._
|
||||
|
||||
val addr0 = input(INSTRUCTION)(Riscv.rs1Range).asUInt
|
||||
val addr1 = input(INSTRUCTION)(Riscv.rs2Range).asUInt
|
||||
val rs1 = input(INSTRUCTION)(Riscv.rs1Range).asUInt
|
||||
val rs2 = input(INSTRUCTION)(Riscv.rs2Range).asUInt
|
||||
|
||||
//read register file
|
||||
val srcInstruction = regFileReadyKind match{
|
||||
|
@ -175,16 +264,16 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind) extends Plugin[VexRiscv]
|
|||
case `SYNC` => Mux(arbitration.isStuck,input(INSTRUCTION),fetch.output(INSTRUCTION))
|
||||
}
|
||||
|
||||
val regFileReadAddress0 = srcInstruction(Riscv.rs1Range).asUInt
|
||||
val regFileReadAddress1 = srcInstruction(Riscv.rs2Range).asUInt
|
||||
val regFileReadAddress1 = srcInstruction(Riscv.rs1Range).asUInt
|
||||
val regFileReadAddress2 = srcInstruction(Riscv.rs2Range).asUInt
|
||||
|
||||
val (src0,src1) = regFileReadyKind match{
|
||||
case `ASYNC` => (global.regFile.readAsync(regFileReadAddress0),global.regFile.readAsync(regFileReadAddress1))
|
||||
case `SYNC` => (global.regFile.readSync(regFileReadAddress0),global.regFile.readSync(regFileReadAddress1))
|
||||
val (rs1Data,rs2Data) = regFileReadyKind match{
|
||||
case `ASYNC` => (global.regFile.readAsync(regFileReadAddress1),global.regFile.readAsync(regFileReadAddress2))
|
||||
case `SYNC` => (global.regFile.readSync(regFileReadAddress1),global.regFile.readSync(regFileReadAddress2))
|
||||
}
|
||||
|
||||
insert(SRC1) := Mux(addr0 =/= 0, src0, B(0, 32 bit))
|
||||
insert(SRC2) := Mux(addr1 =/= 0, src1, B(0, 32 bit))
|
||||
insert(REG1) := Mux(rs1 =/= 0, rs1Data, B(0, 32 bit))
|
||||
insert(REG2) := Mux(rs2 =/= 0, rs2Data, B(0, 32 bit))
|
||||
}
|
||||
|
||||
writeBack plug new Area{
|
||||
|
@ -194,34 +283,195 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind) extends Plugin[VexRiscv]
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class SrcPlugin extends Plugin[VexRiscv]{
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
import pipeline._
|
||||
import pipeline.config._
|
||||
|
||||
decode plug new Area{
|
||||
import decode._
|
||||
|
||||
val imm = Riscv.IMM(input(INSTRUCTION))
|
||||
insert(SRC1) := input(SRC1_CTRL).mux(
|
||||
Src1CtrlEnum.RS -> output(REG1),
|
||||
Src1CtrlEnum.IMU -> imm.u.resized,
|
||||
Src1CtrlEnum.IMZ -> imm.z.resized,
|
||||
Src1CtrlEnum.IMJB -> B(0) //TODO
|
||||
)
|
||||
insert(SRC2) := input(SRC2_CTRL).mux(
|
||||
Src2CtrlEnum.RS -> output(REG2),
|
||||
Src2CtrlEnum.IMI -> imm.i_sext.resized,
|
||||
Src2CtrlEnum.IMS -> imm.s_sext.resized,
|
||||
Src2CtrlEnum.PC -> output(PC).asBits
|
||||
)
|
||||
}
|
||||
|
||||
execute plug new Area{
|
||||
import execute._
|
||||
|
||||
// ADD, SUB
|
||||
val addSub = (input(SRC1).asSInt + Mux(input(SRC_USE_SUB_LESS), ~input(SRC2), input(SRC2)).asSInt + Mux(input(SRC_USE_SUB_LESS),S(1),S(0))).asBits
|
||||
|
||||
// SLT, SLTU
|
||||
val less = Mux(input(SRC1).msb === input(SRC2).msb, addSub.msb,
|
||||
Mux(input(SRC_LESS_UNSIGNED), input(SRC2).msb, input(SRC1).msb))
|
||||
|
||||
insert(SRC_ADD_SUB) := addSub.resized
|
||||
insert(SRC_LESS) := less
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IntAluPlugin extends Plugin[VexRiscv]{
|
||||
|
||||
object AluCtrlEnum extends SpinalEnum(binarySequential){
|
||||
val ADD_SUB, SLT_SLTU, XOR, OR, AND = newElement()
|
||||
}
|
||||
|
||||
object ALU_CTRL extends Stageable(AluCtrlEnum())
|
||||
|
||||
// override def setup(pipeline: VexRiscv): Unit = {
|
||||
// pipeline.service(classOf[DecoderService]).add(List(
|
||||
// M"0101010---" ->
|
||||
// List(
|
||||
// Execute0Bypass -> True,
|
||||
// Execute1Bypass -> True
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import pipeline.config._
|
||||
import Riscv._
|
||||
|
||||
val immediateActions = List[(Stageable[_ <: Data],Any)](
|
||||
LEGAL_INSTRUCTION -> True,
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.IMI,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> True,
|
||||
BYPASSABLE_MEMORY_STAGE -> True
|
||||
)
|
||||
|
||||
val nonImmediateActions = List[(Stageable[_ <: Data],Any)](
|
||||
LEGAL_INSTRUCTION -> True,
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> True,
|
||||
BYPASSABLE_MEMORY_STAGE -> True
|
||||
)
|
||||
|
||||
pipeline.service(classOf[DecoderService]).add(List(
|
||||
ADD -> (nonImmediateActions ++ List(ALU_CTRL -> AluCtrlEnum.ADD_SUB, SRC_USE_SUB_LESS -> False)),
|
||||
SUB -> (nonImmediateActions ++ List(ALU_CTRL -> AluCtrlEnum.ADD_SUB, SRC_USE_SUB_LESS -> True)),
|
||||
SLT -> (nonImmediateActions ++ List(ALU_CTRL -> AluCtrlEnum.SLT_SLTU, SRC_USE_SUB_LESS -> True, SRC_LESS_UNSIGNED -> False)),
|
||||
SLTU -> (nonImmediateActions ++ List(ALU_CTRL -> AluCtrlEnum.SLT_SLTU, SRC_USE_SUB_LESS -> True, SRC_LESS_UNSIGNED -> True)),
|
||||
XOR -> (nonImmediateActions ++ List(ALU_CTRL -> AluCtrlEnum.XOR)),
|
||||
OR -> (nonImmediateActions ++ List(ALU_CTRL -> AluCtrlEnum.OR)),
|
||||
AND -> (nonImmediateActions ++ List(ALU_CTRL -> AluCtrlEnum.AND))
|
||||
))
|
||||
|
||||
pipeline.service(classOf[DecoderService]).add(List(
|
||||
ADDI -> (immediateActions ++ List(ALU_CTRL -> AluCtrlEnum.ADD_SUB, SRC_USE_SUB_LESS -> False)),
|
||||
SLTI -> (immediateActions ++ List(ALU_CTRL -> AluCtrlEnum.SLT_SLTU, SRC_USE_SUB_LESS -> True, SRC_LESS_UNSIGNED -> False)),
|
||||
SLTIU -> (immediateActions ++ List(ALU_CTRL -> AluCtrlEnum.SLT_SLTU, SRC_USE_SUB_LESS -> True, SRC_LESS_UNSIGNED -> True)),
|
||||
XORI -> (immediateActions ++ List(ALU_CTRL -> AluCtrlEnum.XOR)),
|
||||
ORI -> (immediateActions ++ List(ALU_CTRL -> AluCtrlEnum.OR)),
|
||||
ANDI -> (immediateActions ++ List(ALU_CTRL -> AluCtrlEnum.AND))
|
||||
))
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
import pipeline._
|
||||
import pipeline.config._
|
||||
|
||||
out(execute.input(SRC1) & execute.input(SRC2))
|
||||
|
||||
execute plug new Area{
|
||||
import execute._
|
||||
|
||||
// mux results
|
||||
insert(ALU_RESULT) := input(ALU_CTRL).mux(
|
||||
AluCtrlEnum.AND -> (input(SRC1) & input(SRC2)),
|
||||
AluCtrlEnum.OR -> (input(SRC1) | input(SRC2)),
|
||||
AluCtrlEnum.XOR -> (input(SRC1) ^ input(SRC2)),
|
||||
AluCtrlEnum.SLT_SLTU -> input(SRC_LESS).asBits(32 bit),
|
||||
AluCtrlEnum.ADD_SUB -> input(SRC_ADD_SUB)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
object MyTopLevel {
|
||||
class FullBarrielShifterPlugin extends Plugin[VexRiscv]{
|
||||
object ShiftCtrlEnum extends SpinalEnum(binarySequential){
|
||||
val DISABLE, SLL, SRL, SRA = newElement() //TODO default
|
||||
}
|
||||
|
||||
object SHIFT_CTRL extends Stageable(ShiftCtrlEnum())
|
||||
object SHIFT_RIGHT extends Stageable(Bits(32 bits))
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import pipeline.config._
|
||||
import Riscv._
|
||||
|
||||
val immediateActions = List[(Stageable[_ <: Data],Any)](
|
||||
LEGAL_INSTRUCTION -> True,
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.IMI,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> False,
|
||||
BYPASSABLE_MEMORY_STAGE -> True
|
||||
)
|
||||
|
||||
val nonImmediateActions = List[(Stageable[_ <: Data],Any)](
|
||||
LEGAL_INSTRUCTION -> True,
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> False,
|
||||
BYPASSABLE_MEMORY_STAGE -> True
|
||||
)
|
||||
|
||||
pipeline.service(classOf[DecoderService]).add(List(
|
||||
SLL -> (nonImmediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SLL)),
|
||||
SRL -> (nonImmediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SRL)),
|
||||
SRA -> (nonImmediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SRA))
|
||||
))
|
||||
|
||||
pipeline.service(classOf[DecoderService]).add(List(
|
||||
SLLI -> (immediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SLL)),
|
||||
SRLI -> (immediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SRL)),
|
||||
SRAI -> (immediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SRA))
|
||||
))
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
import pipeline._
|
||||
import pipeline.config._
|
||||
|
||||
|
||||
execute plug new Area{
|
||||
import execute._
|
||||
val amplitude = input(SRC2)(4 downto 0).asUInt
|
||||
val reversed = Mux(input(SHIFT_CTRL) === ShiftCtrlEnum.SLL, Reverse(input(SRC1)), input(SRC1))
|
||||
insert(SHIFT_RIGHT) := (Cat(input(SHIFT_CTRL) === ShiftCtrlEnum.SRA & reversed.msb, reversed).asSInt >> amplitude)(31 downto 0).asBits
|
||||
}
|
||||
|
||||
memory plug new Area{
|
||||
import memory._
|
||||
switch(input(SHIFT_CTRL)){
|
||||
is(ShiftCtrlEnum.SLL){
|
||||
output(ALU_RESULT) := Reverse(input(SHIFT_RIGHT))
|
||||
}
|
||||
is(ShiftCtrlEnum.SRL,ShiftCtrlEnum.SRA){
|
||||
output(ALU_RESULT) := input(SHIFT_RIGHT)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class OutputAluResult extends Plugin[VexRiscv]{
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
out(pipeline.writeBack.input(pipeline.config.ALU_RESULT))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object TopLevel {
|
||||
def main(args: Array[String]) {
|
||||
SpinalVhdl{
|
||||
val config = VexRiscvConfig(
|
||||
|
@ -231,8 +481,12 @@ object MyTopLevel {
|
|||
config.plugins ++= List(
|
||||
new PcManagerSimplePlugin(0,true),
|
||||
new IBusSimplePlugin,
|
||||
new DecoderSimplePlugin,
|
||||
new RegFilePlugin(SYNC),
|
||||
new IntAluPlugin
|
||||
new IntAluPlugin,
|
||||
new SrcPlugin,
|
||||
new FullBarrielShifterPlugin,
|
||||
new OutputAluResult
|
||||
)
|
||||
|
||||
new VexRiscv(config)
|
||||
|
|
Loading…
Reference in New Issue