This commit is contained in:
Dolu1990 2017-03-08 22:17:48 +01:00
commit 130ed6345c
9 changed files with 474 additions and 0 deletions

37
.gitignore vendored Normal file
View File

@ -0,0 +1,37 @@
*.class
*.log
*.bak
# sbt specific
.cache/
.history/
.lib/
dist/*
target
lib_managed/
src_managed/
project/boot/
project/plugins/project/
# Scala-IDE specific
.scala_dependencies
.worksheet
.idea
out
# Eclipse
bin/
.classpath
.project
.settings
.cache-main
#User
/*.vhd
/*.v
*.cf
*.json
*.vcd
!tester/src/test/resources/*.vhd

1
README.md Normal file
View File

@ -0,0 +1 @@
WIP

54
backup Normal file
View File

@ -0,0 +1,54 @@
class PcManagerSimple(resetVector : BigInt,pcWidth : Int,fastFetchCmdPcCalculation : Boolean) extends Plugin[SpinalRiscv] with PcManagerService{
import StandardStageables._
//FetchService interface
case class JumpInfo(pc: UInt, cond: Bool, stage: Stage)
val jumpInfos = ArrayBuffer[JumpInfo]()
override def jumpTo(pc: UInt, cond: Bool, stage: Stage): Unit = jumpInfos += JumpInfo(pc,cond,stage)
override def build(pipeline: SpinalRiscv): Unit = {
import pipeline.prefetch
prefetch.plug(new Area {
import prefetch._
//PC calculation without Jump
val pcReg = Reg(UInt(pcWidth bit)) init(resetVector)
val inc = RegInit(False)
val pc = if(fastFetchCmdPcCalculation){
val pcPlus4 = pcReg + 4
pcPlus4.addAttribute("keep")
Mux(inc,pcPlus4,pcReg)
}else{
pcReg + (inc ? U(4) | U(0))
}
//Stage always valid
arbitration.isValid := True
//FetchService hardware implementation
val jumpInfoSorted = jumpInfos.sortWith((a,b) => pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage))
val jumpRequestValids = jumpInfoSorted.map(_.cond)
val jumpRequestPcs = jumpInfoSorted.map(_.pc)
val pcLoad = Flow(pcReg)
pcLoad.valid := jumpInfos.foldLeft(False)(_ || _.cond)
pcLoad.payload := MuxOH(jumpRequestValids,jumpRequestPcs)
//Register managments
when(pcLoad.valid){
pc := pcLoad.payload
inc := False
pcReg := pc
}
when(arbitration.isFiring){
inc := True
pcReg := pc
}
//Pipeline insertions
insert(PC) := pc
})
}
}

12
build.sbt Normal file
View File

@ -0,0 +1,12 @@
name := "SpinalBaseProject"
version := "1.0"
scalaVersion := "2.11.6"
EclipseKeys.withSource := true
libraryDependencies ++= Seq(
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "latest.release",
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "latest.release"
)

2
project/plugins.sbt Normal file
View File

@ -0,0 +1,2 @@
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")

View File

@ -0,0 +1,108 @@
package SpinalRiscv
import spinal.core._
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
trait Pipeline {
type T <: Pipeline
val plugins = ArrayBuffer[Plugin[T]]()
var stages = ArrayBuffer[Stage]()
val services = ArrayBuffer[Any]()
def indexOf(stage : Stage) = stages.indexOf(stage)
def service[T](clazz : Class[T]) = {
val filtered = services.filter(_.getClass == clazz)
assert(filtered.length == 1)
filtered.head.asInstanceOf[T]
}
def build(): Unit ={
//Build plugins
plugins.foreach(_.build(this.asInstanceOf[T]))
//Interconnect stages
class KeyInfo{
var insertStageId = Int.MaxValue
var lastInputStageId = Int.MinValue
var lastOutputStageId = Int.MinValue
def addInputStageIndex(stageId : Int): Unit = {
require(stageId > insertStageId)
lastInputStageId = Math.max(lastInputStageId,stageId)
lastOutputStageId = Math.max(lastOutputStageId,stageId-1)
}
def addOutputStageIndex(stageId : Int): Unit = {
require(stageId >= insertStageId)
if(stageId != insertStageId) lastInputStageId = Math.min(lastInputStageId,stageId)
lastOutputStageId = Math.max(lastOutputStageId,stageId)
}
def setInsertStageId(stageId : Int) = insertStageId = stageId
}
val inputOutputKeys = mutable.HashMap[Stageable[Data],KeyInfo]()
for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)){
stage.inserts.keysIterator.foreach(signal => inputOutputKeys.getOrElseUpdate(signal,new KeyInfo).setInsertStageId(stageIndex))
}
for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)){
stage.inputs.keysIterator.foreach(key => inputOutputKeys.getOrElseUpdate(key,new KeyInfo).addInputStageIndex(stageIndex))
stage.outputs.keysIterator.foreach(key => inputOutputKeys.getOrElseUpdate(key,new KeyInfo).addOutputStageIndex(stageIndex))
}
for((key,info) <- inputOutputKeys){
//Interconnect inputs -> outputs
for(stageIndex <- info.insertStageId to info.lastOutputStageId;
stage = stages(stageIndex)) {
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)
}
}
}
//Interconnect outputs -> inputs
for(stageIndex <- info.insertStageId + 1 to info.lastInputStageId) {
val stageBefore = stages(stageIndex - 1)
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
}
}
//Arbitration
for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)){
stage.arbitration.isStuck := stages.takeRight(stages.length - stageIndex).map(_.arbitration.haltIt).reduce(_ || _)
stage.arbitration.isFiring := stage.arbitration.isValid && !stage.arbitration.isStuck && !stage.arbitration.removeIt
}
for(stageIndex <- 1 until stages.length){
val stageBefore = stages(stageIndex - 1)
val stage = stages(stageIndex)
stage.arbitration.isStuck := stages.takeRight(stages.length-stageIndex).map(_.arbitration.haltIt).reduce(_ || _)
when(!stageBefore.arbitration.isStuck) {
stage.arbitration.isValid := stage.arbitration.isValid && !stage.arbitration.removeIt
}
when(stage.arbitration.removeIt){
stage.arbitration.isValid := False
}
}
}
}
Component.current.addPrePopTask(() => build())
}

View File

@ -0,0 +1,17 @@
package SpinalRiscv
import spinal.core.Area
/**
* Created by PIC32F_USER on 03/03/2017.
*/
trait Plugin[T <: Pipeline] {
def getName() = this.getClass.getSimpleName.replace("$","")
def setup(pipeline: T) : Unit = {}
def build(pipeline: T) : Unit
implicit class implicits(stage: Stage){
def plug(area : Area) = area.setCompositeName(stage,getName()).reflectNames()
}
}

View File

@ -0,0 +1,73 @@
package SpinalRiscv
import spinal.core._
import spinal.lib._
import scala.collection.mutable
class Stageable[T <: Data](dataType : T) extends HardType[T](dataType) with Nameable{
setWeakName(this.getClass.getSimpleName.replace("$",""))
}
class Stage() extends Area{
def input[T <: Data](key : Stageable[T]) : T = {
inputs.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],{
val input,inputDefault = key()
inputsDefault(key.asInstanceOf[Stageable[Data]]) = inputDefault
input := inputDefault
input.setPartialName(this,"input_" + key.getName())
}).asInstanceOf[T]
}
def output[T <: Data](key : Stageable[T]) : T = {
outputs.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],{
val output,outputDefault = key()
outputsDefault(key.asInstanceOf[Stageable[Data]]) = outputDefault
output := outputDefault
output.setPartialName(this,"output_" + key.getName())
}).asInstanceOf[T]
}
def insert[T <: Data](key : Stageable[T]) : T = inserts.getOrElseUpdate(key.asInstanceOf[Stageable[Data]],key()).asInstanceOf[T].setPartialName(this,key.getName())
def apply[T <: Data](key : Stageable[T]) : T = ???
val arbitration = new Bundle{
val haltIt = False
val removeIt = False
val isValid = RegInit(False)
val isStuck = Bool
val isFiring = Bool
}
val inputs = mutable.HashMap[Stageable[Data],Data]()
val outputs = mutable.HashMap[Stageable[Data],Data]()
val signals = mutable.HashMap[Stageable[Data],Data]()
val inserts = mutable.HashMap[Stageable[Data],Data]()
val inputsDefault = mutable.HashMap[Stageable[Data],Data]()
val outputsDefault = mutable.HashMap[Stageable[Data],Data]()
}
//object StageMain{
//
// object OpEnum extends SpinalEnum{
// val AND,OR = newElement()
// }
// object OP extends Stageable(OpEnum())
// object SRC1 extends Stageable(Bits(32 bits))
// object SRC2 extends Stageable(Bits(32 bits))
// object RESULT extends Stageable(Bits(32 bits))
// def main(args: Array[String]) {
// val E = List.fill(2)(new Stage(9))
// val E0 = E(0)
// import E0._
// output(RESULT) := E(0).input(OP).mux(
// OpEnum.AND -> (E(0).input(SRC1) & E(0).input(SRC2)),
// OpEnum.OR -> (E(0).input(SRC1) | E(0).input(SRC2))
// )
// }
//}

View File

@ -0,0 +1,170 @@
/*
* SpinalHDL
* Copyright (c) Dolu, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package SpinalRiscv
import spinal.core._
import spinal.lib._
import scala.collection.mutable.ArrayBuffer
object StandardStageables{
object Execute0Bypass extends Stageable(Bool)
object Execute1Bypass extends Stageable(Bool)
object SRC1 extends Stageable(UInt(32 bits))
object SRC2 extends Stageable(UInt(32 bits))
object RESULT extends Stageable(UInt(32 bits))
object PC extends Stageable(UInt())
object INST extends Stageable(Bits(32 bits))
}
class SpinalRiscv(pluginConfig : Seq[Plugin[SpinalRiscv]]) extends Component with Pipeline{
type T = SpinalRiscv
stages ++= List.fill(6)(new Stage())
val prefetch :: fetch :: decode :: execute :: memory :: writeBack :: Nil = stages.toList
plugins ++= pluginConfig
}
trait DecoderService{
def add(key : MaskedLiteral,values : Seq[(Stageable[_],BaseType)])
def add(encoding :Seq[(MaskedLiteral,Seq[(Stageable[_],BaseType)])])
}
class DecoderSimplePlugin extends Plugin[SpinalRiscv] 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 build(pipeline: SpinalRiscv): Unit = ???
}
trait PcManagerService{
def jumpTo(pc : UInt,cond : Bool,stage : Stage) : Unit
}
class PcManagerSimplePlugin(resetVector : BigInt,pcWidth : Int,fastFetchCmdPcCalculation : Boolean) extends Plugin[SpinalRiscv] with PcManagerService{
import StandardStageables._
//FetchService interface
case class JumpInfo(pc: UInt, cond: Bool, stage: Stage)
val jumpInfos = ArrayBuffer[JumpInfo]()
override def jumpTo(pc: UInt, cond: Bool, stage: Stage): Unit = jumpInfos += JumpInfo(pc,cond,stage)
override def build(pipeline: SpinalRiscv): Unit = {
import pipeline.prefetch
prefetch.plug(new Area {
import prefetch._
//Stage always valid
arbitration.isValid := True
//PC calculation without Jump
val pc = Reg(UInt(pcWidth bits)) init(resetVector)
when(arbitration.isValid && !arbitration.isStuck){
val pcPlus4 = pc + 4
if(fastFetchCmdPcCalculation) pcPlus4.addAttribute("keep") //Disallow to use the carry in as enable
pc := pcPlus4
}
//FetchService hardware implementation
val jump = if(jumpInfos.length != 0) {
val sortedByStage = jumpInfos.sortWith((a, b) => pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage))
val valids = sortedByStage.map(_.cond)
val pcs = sortedByStage.map(_.pc)
val pcLoad = Flow(UInt(pcWidth bits))
pcLoad.valid := jumpInfos.foldLeft(False)(_ || _.cond)
pcLoad.payload := MuxOH(valids, pcs)
//Register managments
when(pcLoad.valid) {
pc := pcLoad.payload
arbitration.removeIt := True
}
}
//Pipeline insertions
insert(PC) := pc
})
}
}
case class IBusSimpleCmd() extends Bundle{
val pc = UInt(32 bits)
}
case class IBusSimpleRsp() extends Bundle{
val inst = Bits(32 bits)
}
class IBusSimplePlugin extends Plugin[SpinalRiscv]{
import StandardStageables._
var iCmd : Stream[IBusSimpleCmd] = null
var iRsp : IBusSimpleRsp = null
override def build(pipeline: SpinalRiscv): Unit = {
import pipeline._
iCmd = master(Stream(IBusSimpleCmd()))
iCmd.valid := prefetch.arbitration.isFiring
iCmd.pc := prefetch.output(PC)
iRsp = IBusSimpleRsp()
fetch.insert(INST) := iRsp.inst
}
}
class IntAluPlugin extends Plugin[SpinalRiscv]{
import StandardStageables._
override def setup(pipeline: SpinalRiscv): Unit = {
pipeline.service(classOf[DecoderService]).add(List(
M"0101010---" ->
List(
Execute0Bypass -> True,
Execute1Bypass -> True
)
)
)
}
override def build(pipeline: SpinalRiscv): Unit = {
import pipeline._
}
}
object MyTopLevel {
def main(args: Array[String]) {
SpinalVhdl(new SpinalRiscv(List(
// new IntAluPlugin
new PcManagerSimplePlugin(0,32,true),
new IBusSimplePlugin
)))
}
}