readme, better plugin example

This commit is contained in:
Charles Papon 2017-07-17 14:19:28 +02:00
parent 84bba3adf0
commit 99c3397243
5 changed files with 138 additions and 38 deletions

155
README.md
View File

@ -215,56 +215,145 @@ cd ..
echo -e "\\nRISC-V Toolchain installation completed!"
```
## Cpu plugin structure
## CPU parametrization and instantiation example
There is an example of an pseudo ALU plugin :
You can find many example of different config in the https://github.com/SpinalHDL/VexRiscv/tree/master/src/main/scala/VexRiscv/demo folder. There is one :
```scala
//Define an signal name/type which could be used in the pipeline
object ALU_ENABLE extends Stageable(Bool)
object ALU_OP extends Stageable(Bits(2 bits)) // ADD, SUB, AND, OR
object ALU_SRC1 extends Stageable(UInt(32 bits))
object ALU_SRC2 extends Stageable(UInt(32 bits))
object ALU_RESULT extends Stageable(UInt(32 bits))
//Instanciate one VexRiscv
val cpu = new VexRiscv(
//Provide a configuration instance
config = VexRiscvConfig(
//Provide a list of plugins which will futher add their logic into the CPU
plugins = List(
new PcManagerSimplePlugin(
resetVector = 0x00000000l,
fastPcCalculation = true
),
new IBusSimplePlugin(
interfaceKeepData = false,
catchAccessFault = false
),
new DBusSimplePlugin(
catchAddressMisaligned = false,
catchAccessFault = false
),
new DecoderSimplePlugin(
catchIllegalInstruction = false
),
new RegFilePlugin(
regFileReadyKind = Plugin.SYNC,
zeroBoot = true
),
new IntAluPlugin,
new SrcPlugin(
separatedAddSub = false,
executeInsertion = false
),
new LightShifterPlugin,
new HazardSimplePlugin(
bypassExecute = false,
bypassMemory = false,
bypassWriteBack = false,
bypassWriteBackBuffer = false
),
new BranchPlugin(
earlyBranch = false,
catchAddressMisaligned = false,
prediction = NONE
),
new YamlPlugin("cpu0.yaml")
)
)
)
```
class AluPlugin() extends Plugin[VexRiscv]{
## CPU plugin example
There is an example of an simple plugin which add an simple SIMD add :
```scala
import spinal.core._
import VexRiscv.Plugin.Plugin
import VexRiscv.{Stageable, DecoderService, VexRiscv}
//This plugin example will add a new instruction named SIMD_ADD which do the following :
//
//RD : Regfile Destination, RS : Regfile Source
//RD( 7 downto 0) = RS1( 7 downto 0) + RS2( 7 downto 0)
//RD(16 downto 8) = RS1(16 downto 8) + RS2(16 downto 8)
//RD(23 downto 16) = RS1(23 downto 16) + RS2(23 downto 16)
//RD(31 downto 24) = RS1(31 downto 24) + RS2(31 downto 24)
//
//Instruction encoding :
//0000011----------000-----0110011
// |RS2||RS1| |RD |
//
//Note : RS1, RS2, RD positions follow the RISC-V spec and are common for all instruction of the ISA
class SimdAddPlugin extends Plugin[VexRiscv]{
//Define the concept of IS_SIMD_ADD signals, which specify if the current instruction is destined for ths plugin
object IS_SIMD_ADD extends Stageable(Bool)
//Callback to setup the plugin and ask for different services
override def setup(pipeline: VexRiscv): Unit = {
import pipeline.config._
//Do some setups as for example specifying some instruction decoding by using the Decoding service
//Retrieve the DecoderService instance
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(ALU_ENABLE,False)
decodingService.add(List(
M"0100----------" -> List(ALU_ENABLE -> True, ALU_OP -> B"01"),
M"0110---11-----" -> List(ALU_ENABLE -> True, ...)
))
//Specify the IS_SIMD_ADD default value when instruction are decoded
decoderService.addDefault(IS_SIMD_ADD, False)
//Specify the instruction decoding which should be applied when the instruction match the 'key' parttern
decoderService.add(
//Bit pattern of the new SIMD_ADD instruction
key = M"0000011----------000-----0110011",
//Decoding specification when the 'key' pattern is recognized in the instruction
List(
IS_SIMD_ADD -> True,
REGFILE_WRITE_VALID -> True, //Enable the register file write
BYPASSABLE_EXECUTE_STAGE -> True, //Notify the hazard management unit that the instruction result is already accessible in the EXECUTE stage (Bypass ready)
BYPASSABLE_MEMORY_STAGE -> True, //Same as above but for the memory stage
RS1_USE -> True, //Notify the hazard management unit that this instruction use the RS1 value
RS2_USE -> True //Same than above but for RS2.
)
)
}
//Callback to build the hardware logic
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
execute plug new Area {
import execute._
//Add some logic in the execute stage
insert(ALU_RESULT) := input(ALU_OP).mux(
B"00" -> input(ALU_SRC1) + input(ALU_SRC2),
B"01" -> input(ALU_SRC1) - input(ALU_SRC2),
B"10" -> input(ALU_SRC1) & input(ALU_SRC2),
B"11" -> input(ALU_SRC1) | input(ALU_SRC2),
)
}
//Define some signals used internally to the plugin
val rs1 = execute.input(RS1).asUInt //32 bits UInt value of the regfile[RS1]
val rs2 = execute.input(RS2).asUInt
val rd = UInt(32 bits)
writeBack plug new Area {
import writeBack._
//Add some logic in the execute stage
when(input(ALU_ENABLE)){
input(REGFILE_WRITE_DATA) := input(ALU_RESULT)
}
//Do some computation
rd( 7 downto 0) := rs1( 7 downto 0) + rs2( 7 downto 0)
rd(16 downto 8) := rs1(16 downto 8) + rs2(16 downto 8)
rd(23 downto 16) := rs1(23 downto 16) + rs2(23 downto 16)
rd(31 downto 24) := rs1(31 downto 24) + rs2(31 downto 24)
//When the instruction is a SIMD_ADD one, then write the result into the register file data path.
when(execute.input(IS_SIMD_ADD)){
execute.output(REGFILE_WRITE_DATA) := rd.asBits
}
}
}
```
Then if you want to add this plugin to a given CPU, you just need to add it in its parameterized plugin list.
This example is a very simple one, but each plugin can really have access to the whole CPU
- Halt a given stage of the CPU
- Unschedule instructions
- Emit an exception
- Introduce new instruction decoding specification
- Ask to jump the PC somewhere
- Read signals published by other plugins
- override published signals values
- Provide an alternative implementation
- ...

View File

@ -12,7 +12,10 @@ object GenFull extends App{
def cpu() = new VexRiscv(
config = VexRiscvConfig(
plugins = List(
new PcManagerSimplePlugin(0x00000000l, false),
new PcManagerSimplePlugin(
resetVector = 0x00000000l,
fastPcCalculation = false
),
new IBusCachedPlugin(
config = InstructionCacheConfig(
cacheSize = 4096,

View File

@ -12,7 +12,10 @@ object GenFullNoMmu extends App{
def cpu() = new VexRiscv(
config = VexRiscvConfig(
plugins = List(
new PcManagerSimplePlugin(0x00000000l, false),
new PcManagerSimplePlugin(
resetVector = 0x00000000l,
fastPcCalculation = false
),
new IBusCachedPlugin(
config = InstructionCacheConfig(
cacheSize = 4096,

View File

@ -11,7 +11,10 @@ object GenSmallest extends App{
def cpu() = new VexRiscv(
config = VexRiscvConfig(
plugins = List(
new PcManagerSimplePlugin(0x00000000l, true),
new PcManagerSimplePlugin(
resetVector = 0x00000000l,
fastPcCalculation = true
),
new IBusSimplePlugin(
interfaceKeepData = false,
catchAccessFault = false

View File

@ -11,7 +11,10 @@ object GenSmallestNoCsr extends App{
def cpu() = new VexRiscv(
config = VexRiscvConfig(
plugins = List(
new PcManagerSimplePlugin(0x00000000l, true),
new PcManagerSimplePlugin(
resetVector = 0x00000000l,
fastPcCalculation = true
),
new IBusSimplePlugin(
interfaceKeepData = false,
catchAccessFault = false
@ -51,6 +54,5 @@ object GenSmallestNoCsr extends App{
)
)
)
SpinalVerilog(cpu())
}