9. Writing Your Own Plugins¶
RISCV-ISAC uses the pluggy system for supporting plugins. The hooks are predefined and can be accessed by importing the riscv_isac.plugins
module. The template for custom plugins is available here.
Two classes of plugins are defined, namely:
Parser Plugin(
parserHookImpl
): Parse the execution trace file to yield instruction (code), mnemonics, address and register commit value for each instruction. Currently, there are plugins for execution traces from 2 RISC V models - SPIKE and SAIL.Decoder Plugin(
decoderHookImpl
): Decodes the information into a common instruction class object.
Note
The name of the python file and the name of the class should be the same.
Warning
Coverage reported by ISAC is based on the instructions reported in the trace file. Hence it is imperative that all instructions are reported in the trace file. Currently the coverage reporting using the SPIKE model and parser is inaccurate because instructions which trap are not reported in the trace file. Such problems will exist with all parsers/models which follow similar behaviour.
9.1. Function Definitions¶
9.1.1. Parser Plugin¶
9.1.1.1. def setup(self, trace, arch):¶
This function initializes each instance of parserclass()
(a subclass of ParserSpec
) of a given mode.
Arguments: (
trace
) file path of the execution trace file and (arch
) architecture of the set.
@plugins.parserHookImpl
def setup(self, trace, arch):
self.trace = trace
self.arch = arch
9.1.1.2. def __iter__(self):¶
It converts the instance of parserclass()
to an iterator. Thus, given an input trace file to the instance, this function will extract information from it line by line. An example is shown below from the c_sail parser.
Arguments:
self
instance of the class that contains the input trace file.Returns: Generates instruction (
instr
), mnemonics (mnemonic
), address (addr
) and register commit value (commitvalue
) on each call.
@plugins.parserHookImpl
def __iter__(self):
with open(self.trace) as fp:
content = fp.read()
instructions = content.split('\n\n')
for line in instructions:
instr, mnemonic = self.extractInstruction(line)
addr = self.extractAddress(line)
commitvalue = self.extractRegisterCommitVal(line)
yield instr, mnemonic, addr, commitvalue
9.1.2. Decoder Plugin¶
9.1.2.1. def setup(self, arch):¶
This function initializes each instance of decoderclass()
(a subclass of DecoderSpec
).
Arguments-
self
instance of the class andarch
architecture of the instruction set
@plugins.decoderHookImpl
def setup(self, arch):
self.arch = arch
9.1.2.2. def decode(self, instr, addr):¶
This function decodes the instruction and returns an instruction object riscv_isac.InstructionObject.instructionObject
.
Arguments:
self
instance of the class,instr
Hexcode of instruction andaddr
address.Return value: The instruction object in the standard format - (instr_name, instr_addr, rd, rs1, rs2, rs3, imm, csr, shamt)
@plugins.decoderHookImpl
def decode(self, instr, addr):
''' Decodes the type of instruction
Returns: instruction object
'''
first_two_bits = self.FIRST2_MASK & instr
if first_two_bits == 0b11:
return self.parseStandardInstruction(instr, addr, self.arch)
else:
return self.parseCompressedInstruction(instr, addr, self.arch)
9.2. Using Custom Plugins with RISC-V ISAC¶
Pass the path of the directory where the custom file is present with
--parser-path
or--decoder-path
as needed.The name of the class should be passed using the
--parser-name
or--decoder-name
argument. An example setup is shown below.
An example setup is shown below:
($) tree ./
.
├── add-01.elf
├── add-01.log
├── dataset.cgf
├── decoder
│ └── CustomDecoder.py
├── parser
│ └── CustomParser.py
└── rv32i.cgf
2 directories, 6 files
riscv_isac --verbose info coverage -d -t add-01.log --parser-path ./parser/ --parser-name CustomParser --decoder-path ./decoder/ --decoder-name CustomDecoder -o coverage.rpt --sig-label begin_signature end_signature --test-label rvtest_code_begin rvtest_code_end -e add-01.elf -c dataset.cgf -c rv32i.cgf -x 32 -l add
9.3. Templates¶
9.3.1. Parser Plugin¶
#CustomParser.py
import riscv_isac.plugins
class CustomParser()
@plugins.parserHookImpl
def setup(self, trace, arch):
self.trace = trace
self.arch = arch
@plugins.parserHookImpl
def __iter__(self):
#extract instruction, mnemonic, addr and commit value
yield instr, mnemonic, addr, commitval
9.3.2. Decoder Plugin¶
#CustomDecoder.py
from riscv_isac.plugins import decoderHookImpl
from riscv_isac.InstructionObject import instructionObject
class CustomDecoder()
@decoderHookImpl
def setup(self, arch):
self.arch = arch
@decoderHookImpl
def decode(self, instr, addr):
# construct Instruction Object and return