This commit is contained in:
Dolu1990 2017-03-11 00:34:49 +01:00
parent fc7e9a7730
commit fcb70a333f
4 changed files with 330 additions and 51 deletions

View File

@ -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"
)

View File

@ -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
}
}
}

View File

@ -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 = ???

View File

@ -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)