Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

Commit

Permalink
Merge pull request #10 from ShrreyaSingh/new_csr
Browse files Browse the repository at this point in the history
CSR coverage, updates in merge function and plugins' architecture
  • Loading branch information
neelgala authored Jul 9, 2021
2 parents 0d23d5c + dc955d6 commit c72bdde
Show file tree
Hide file tree
Showing 14 changed files with 845 additions and 442 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.6.4] - 2021-07-08
- Added support for CSR coverage and its architectural state
- Updated the merge function to support multiprocessing
- Added a parameter '-p' ( number of processes ) in merge command
- Documentation update for CSR coverpoints
- Return value of parsers changed from 5 independent values (hexcode, addr, reg commmit, csr commit, mnemonics) to instruction object updated with these values
- Argument of decode and all decoding functions (in internaldecoder) changed from hexcode and addr to instruction object

## [0.6.3] - 2021-06-24
- Documentation updates to reflect plugin usage.
- Minor bug fixes in coverage reporting.
Expand Down
49 changes: 48 additions & 1 deletion docs/source/cgf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ A covergroup is a dictionary based on the following template. These dictionaries
* Register
* Register Operand Combinations
* Register/Immediate Value Combinations
* Control and Status Registers Value Combinations

Template
--------
Expand Down Expand Up @@ -53,6 +54,11 @@ The template for defining a covergroup is as follows:
abstract_comb:
<abscomb-str>: 0
<abscomb-str>: 0
...
csr_comb:
<csrcomb-str>: 0
<csrcomb-str>: 0
Explanation
Expand All @@ -74,7 +80,7 @@ A covergroup contains the following nodes:
.. _riscof: https://riscof.readthedocs.io/en/latest/index.html

* **opcode**
*This node is mandatory in every covergroup.*
*This node is mandatory for all covergroups except covergroups pertaining to CSR coverpoints (it's optional in this case).*

This node describes the *opcode coverpoints* necessary for the covergroup. Each *opcode* is treated as a valid coverpoint and the arguments of the corresponding instruction are used to update the rest of the coverpoint types.

Expand Down Expand Up @@ -269,4 +275,45 @@ A covergroup contains the following nodes:
.. code-block:: python
["rs1_val=="+str(x) for x in filter(lambda x:x%8!=0,range(2,xlen,2))]
* **csr_comb**
*This node is optional.*

This node describes the *CSRs value combination coverpoints* for a covergroup. ISAC maintains a copy of the architectural csrs, which thereby allows the user to describe the coverpoints based on csrs and their values. All the *Machine level* and *Supervisor level* CSRs are currently supported. If for a particular covergroup, the opcode node is present/not-empty, then the CSR coverpoints are evaluated and updated only for instructions in the log whose opcode matches. If however, the opcode node is not-present/empty in a covergroup, then the csrs coverpoints are evaluated and updated for any event/instruction.

* **csrcomb-str**
This string is interpreted as a valid python statement/expression which evaluates to a Boolean value. The variables available for use in the expression are as follows:

* ``csr_name`` : The value (as of the end of previous instruction) in the CSR whose name is specified by csr_name.

* ``xlen`` : The length of the regsiters in the machine.

Along with the above mentioned variable any valid python comparison operators can be used. An example coverpoint is elaborated below.

.. note:: The csr coverage reporting is accurate only if a change in the csr is captured in the log.

.. tip:: Bit masks and shifts can be used to access the subfields in the csrs.

**Examples**

1. A coverpoint where the value in *mcycle* register is 0.

.. code-block:: python
mcycle == 0x0
Note: Hexadecimal numbers can be used by using the prefix ``0x`` before the hex string.

2. A coverpoint which checks whether the *mxl* field of *misa* register is 1.

.. code-block:: python
misa >> (xlen-2) == 0x01
3. A coverpoint which checks whether the *mie* field of *mstatus* register is 1.

.. code-block:: python
mstatus && (0x8) == 0x8
39 changes: 22 additions & 17 deletions docs/source/python_plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ RISCV-ISAC uses the `pluggy <https://pluggy.readthedocs.io/en/latest/>`_ system

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.
* Parser Plugin(``parserHookImpl``): Parse the execution trace file to yield instruction object with updated fields - instruction code, address, register commits, CSR commits and mnemonics, 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.
Expand Down Expand Up @@ -36,11 +36,10 @@ This function initializes each instance of ``parserclass()`` (a subclass of ``Pa
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.
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 and generate an instruction object ``riscv_isac.InstructionObject.instructionObject`` . 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.
* Returns: Generates instruction object ``instrObj`` on each call.

.. code-block:: python
Expand All @@ -52,8 +51,10 @@ It converts the instance of ``parserclass()`` to an iterator. Thus, given an inp
for line in instructions:
instr, mnemonic = self.extractInstruction(line)
addr = self.extractAddress(line)
commitvalue = self.extractRegisterCommitVal(line)
yield instr, mnemonic, addr, commitvalue
reg_commit = self.extractRegisterCommitVal(line)
csr_commit = self.extractCsrCommitVal(line)
instrObj = instructionObject(instr, 'None', addr, reg_commit = reg_commit, csr_commit = csr_commit, mnemonic = mnemonic )
yield instrObj
Decoder Plugin
~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -76,23 +77,27 @@ 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 and ``addr`` address.
* Return value: The instruction object in the standard format - (instr_name, instr_addr, rd, rs1, rs2, rs3, imm, csr, shamt)
* Arguments: ``self`` instance of the class, ``instrObj_temp`` instruction object returned by the parsers.
* Return value: The instruction object in the standard format - (instr_name, instr_addr, rd, rs1, rs2, rs3, imm, zimm, csr, shamt, reg_commit, csr_commit, mnemonic)

.. code-block:: python
@plugins.decoderHookImpl
def decode(self, instr, addr):
def decode(self, instrObj_temp):
''' Decodes the type of instruction
Returns: instruction object
'''
instr = instrObj_temp.instr
first_two_bits = self.FIRST2_MASK & instr
if first_two_bits == 0b11:
return self.parseStandardInstruction(instr, addr, self.arch)
instrObj = self.parseStandardInstruction(instrObj_temp)
return instrObj
else:
return self.parseCompressedInstruction(instr, addr, self.arch)
instrObj = self.parseCompressedInstruction(instrObj_temp)
return instrObj
.. ``parseStandardInstruction`` and ``parseCompressedInstruction`` takes in the same arguments along with the architecture of the instance and return the instruction object in the
.. ``parseStandardInstruction`` and ``parseCompressedInstruction`` takes in the same arguments and return the instruction object in the
.. above mentioned format.
.. _Custom Plugin Usage:
Expand Down Expand Up @@ -145,6 +150,7 @@ Parser Plugin
#CustomParser.py
import riscv_isac.plugins
from riscv_isac.InstructionObject import instructionObject
class CustomParser()
Expand All @@ -155,8 +161,8 @@ Parser Plugin
@plugins.parserHookImpl
def __iter__(self):
#extract instruction, mnemonic, addr and commit value
yield instr, mnemonic, addr, commitval
#extract instruction, mnemonic, addr, commit values and yields instruction object
yield instr_Obj
Decoder Plugin
~~~~~~~~~~~~~~
Expand All @@ -166,7 +172,6 @@ Decoder Plugin
#CustomDecoder.py
from riscv_isac.plugins import decoderHookImpl
from riscv_isac.InstructionObject import instructionObject
class CustomDecoder()
Expand All @@ -175,5 +180,5 @@ Decoder Plugin
self.arch = arch
@decoderHookImpl
def decode(self, instr, addr):
# construct Instruction Object and return
def decode(self, instr_Obj):
# Update fields of Instruction Object and return
1 change: 1 addition & 0 deletions docs/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ Help text for each command can be accessed by executing ``riscv_isac <command> -
Options:
-d, --detailed Select detailed mode of coverage printing
-p Number of processes
-c, --cgf-file PATH Coverage Group File [required]
-o, --output-file PATH Coverage Group File.
--help Show this message and exit.
Expand Down
26 changes: 22 additions & 4 deletions riscv_isac/InstructionObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,24 @@ class instructionObject():
'''
def __init__(
self,
instr,
instr_name,
instr_addr,
rd = None,
rs1 = None,
rs2 = None,
rs3 = None,
imm = None,
zimm = None,
csr = None,
shamt = None):
shamt = None,
reg_commit = None,
csr_commit = None,
mnemonic = None
):

'''
Constructor.
:param instr_name: name of instruction as accepted by a standard RISC-V assembler
:param instr_addr: pc value of the instruction
:param rd: tuple containing the register index and registerfile (x or f) that will be updated by this instruction
Expand All @@ -28,18 +33,23 @@ def __init__(
:param csr: csr index, if any, used by the instruction
:param shamt: shift amount, if any, used by the instruction
'''
self.instr = instr
self.instr_name = instr_name
self.instr_addr = instr_addr
self.rd = rd
self.rs1 = rs1
self.rs2 = rs2
self.rs3 = rs3
self.imm = imm
self.zimm = zimm
self.csr = csr
self.shamt = shamt
self.reg_commit = reg_commit
self.csr_commit = csr_commit
self.mnemonic = mnemonic

def __str__(self):
line = 'addr: '+ str(hex(self.instr_addr)) +' instr: '+ str(self.instr_name)
line = 'instr: '+ str(self.instr)+ ' addr: '+ str(hex(self.instr_addr)) +' instr_name: '+ str(self.instr_name)
if self.rd:
line+= ' rd: '+ str(self.rd)
if self.rs1:
Expand All @@ -52,6 +62,14 @@ def __str__(self):
line+= ' csr: '+ str(self.csr)
if self.imm:
line+= ' imm: '+ str(self.imm)
if self.zimm:
line+= ' zimm: '+ str(self.zimm)
if self.shamt:
line+= ' shamt: '+ str(self.shamt)
return line
if self.reg_commit:
line+= ' reg_commit: '+ str(self.reg_commit)
if self.csr_commit:
line+= ' csr_commit: '+ str(self.csr_commit)
if self.mnemonic:
line+= ' mnemonic: '+ str(self.mnemonic)
return line
2 changes: 1 addition & 1 deletion riscv_isac/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

__author__ = """InCore Semiconductors Pvt Ltd"""
__email__ = '[email protected]'
__version__ = '0.6.3'
__version__ = '0.6.4'
Loading

0 comments on commit c72bdde

Please sign in to comment.