boot
This commit is contained in:
commit
130ed6345c
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
||||||
|
)
|
|
@ -0,0 +1,2 @@
|
||||||
|
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")
|
||||||
|
|
|
@ -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())
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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))
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
//}
|
|
@ -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
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue