aboutsummaryrefslogtreecommitdiff
path: root/VexRiscv/src/main/scala/vexriscv/demo/CustomInstruction.scala
diff options
context:
space:
mode:
Diffstat (limited to 'VexRiscv/src/main/scala/vexriscv/demo/CustomInstruction.scala')
-rw-r--r--VexRiscv/src/main/scala/vexriscv/demo/CustomInstruction.scala75
1 files changed, 75 insertions, 0 deletions
diff --git a/VexRiscv/src/main/scala/vexriscv/demo/CustomInstruction.scala b/VexRiscv/src/main/scala/vexriscv/demo/CustomInstruction.scala
new file mode 100644
index 0000000..dc35997
--- /dev/null
+++ b/VexRiscv/src/main/scala/vexriscv/demo/CustomInstruction.scala
@@ -0,0 +1,75 @@
+package vexriscv.demo
+
+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._
+
+ //Retrieve the DecoderService instance
+ val decoderService = pipeline.service(classOf[DecoderService])
+
+ //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.
+ )
+ )
+ }
+
+ override def build(pipeline: VexRiscv): Unit = {
+ import pipeline._
+ import pipeline.config._
+
+ //Add a new scope on the execute stage (used to give a name to signals)
+ execute plug new Area {
+ //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)
+
+ //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
+ }
+ }
+ }
+}