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