VexRiscv icon indicating copy to clipboard operation
VexRiscv copied to clipboard

Fetch dosen't performed correctly in the simulation of Murax SOC.(+Custom instructions are executed in unexpected time.)

Open nohahanon opened this issue 6 months ago • 1 comments

Hi there! I appreciate your involvement in this project.

I'm developing a plugin to add shadow stack functionality to VexRiscv. I've implemented instructions, 'sspush' for pushing onto the shadow stack and 'sspop' for popping from it. However, these instructions are being executed at unintended timings.

Upon checking the waveform, at 128223900ns, it's evident that 3A646A29 is confirmed as an instruction sspop in the execute stage, reducing ShadowStackPlugin_ssp by -1. However, this instruction clearly doesn't match the key = M"00000000000000000100-----0101011" of the custom instruction sspop (listed below), and comparing this with the disassembled C program shows that 800005d4 should have nop as 00000013. Is this some sort of bug? I couldn't find such an instruction in the C program. This 3A646A29 instruction appeared unexpectedly as if interrupting.

I would appreciate any insights from anyone familiar with this phenomenon. Thank you in advance!

The 'sspush' and 'sspop' instructions are defined as follows:

package vexriscv.plugin

import vexriscv.plugin.Plugin
import vexriscv.{Stageable, DecoderService, VexRiscv}
import spinal.core._
import spinal.lib._

class  ShadowStackPlugin extends Plugin[VexRiscv] {

    object IS_SS_POP extends Stageable(Bool)
    object IS_SS_PUSH extends Stageable(Bool)
    object IS_SS_GET extends Stageable(Bool)

    override def setup(pipeline: VexRiscv): Unit = {
        import pipeline.config._
        val decoderService = pipeline.service(classOf[DecoderService])

        // add sspop
        decoderService.addDefault(IS_SS_POP, False)
        decoderService.add(
            key = M"00000000000000000100-----0101011",
            List(
                IS_SS_POP                -> True,
                REGFILE_WRITE_VALID      -> True
            )
        )

        // add sspush
        decoderService.addDefault(IS_SS_PUSH, False)
        decoderService.add(
            key = M"000000000000-----010000000001011",
            List(
                IS_SS_PUSH               -> True,
                RS1_USE                  -> True
            )
        )
    }

    override def build(pipeline: VexRiscv): Unit = {
        import pipeline._
        import pipeline.config._

        val ssgetStage = execute
        val sspopStage = execute
        val sspushStage = execute
        
        val global = pipeline plug new Area {
            val width = 32
            val depth = 32
            val bottom = 1
            val ssp = Reg(UInt(log2Up(depth) + 1 bits)) init (bottom)
            val shadowStack = Mem(UInt(width bits), depth)
            shadowStack.init(List.fill(depth)(U"32'd8"))
        }

        // sspop
        sspopStage plug new Area {
            import sspopStage._

            when(input(IS_SS_POP).rise() && global.bottom < global.ssp){
                output(REGFILE_WRITE_DATA) := global.shadowStack((global.ssp - 1).resized).asBits
                global.ssp := global.ssp - 1
            }
        }

        // sspush
        sspushStage plug new Area {
            import sspushStage._

            when(input(IS_SS_PUSH).rise() && global.ssp < global.depth){
                val rs1 = input(RS1).asUInt
                global.shadowStack(global.ssp.resized) := rs1
                global.ssp := global.ssp + 1
            }
        }
    }
}

202312151718_1

nohahanon avatar Dec 15 '23 08:12 nohahanon