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 #40 from edwin7026/pseudo-ops-support
Browse files Browse the repository at this point in the history
Support for pseudoinstructions
  • Loading branch information
neelgala authored May 4, 2022
2 parents a4505bc + cd75755 commit 785c887
Show file tree
Hide file tree
Showing 8 changed files with 229 additions and 107 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

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

## [0.13.0] - 2022-05-02
- Covergroup format revised.
- Added support for Pseudoinstructions for coverage computation.

## [0.12.0] - 2022-04-15
- Parallelized coverage computation.
- Added feature to remove coverpoints when hit.
Expand Down
64 changes: 55 additions & 9 deletions docs/source/cgf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Covergroup
==========
A covergroup is a dictionary based on the following template. These dictionaries constitute the nodes in a cgf file. Each cover group contains the following type of coverpoints:

* Opcode
* Mnemonics (Used in conjunction with a `base_op` and a condtion `p_op_cond` node to describe a pseudo-instruction)
* Register
* Register Operand Combinations
* Register/Immediate Value Combinations
Expand All @@ -22,16 +22,16 @@ A covergroup is a dictionary based on the following template. These dictionaries
Template
--------

The template for defining a covergroup is as follows:
The template for defining a non pseudo-op covergroup is as follows:

.. code-block:: yaml
<label>:
config:
- <config-str>
opcode:
<opcode-str>: 0
<opcode-str>: 0
mnemonics:
<mnemonics-str>: 0
<mnemonics-str>: 0
...
rs1:
<reg-str>: 0
Expand Down Expand Up @@ -64,7 +64,20 @@ The template for defining a covergroup is as follows:
<crosscomb_str>:0
<crosscomb_str>:0
The template for defining a covergroup pertaining to a pseudo-op is as follows:

.. code-block:: yaml
<label>:
config:
- <config-str>
mnemonics:
<mnemonics-str>: 0
base_op:
<base_op-str>
p_op_cond:
<p_op_cond-str>
...
Explanation
-----------
Expand All @@ -84,13 +97,46 @@ A covergroup contains the following nodes:
.. _RVTEST_CASE Condition Formating: https://riscof.readthedocs.io/en/latest/testformat.html?highlight=Macro#rvtest-case-condition-formating
.. _riscof: https://riscof.readthedocs.io/en/latest/index.html

* **opcode**
* **mnemonics**
*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.
This node describes the *mnemonics coverpoints* necessary for the covergroup. Multiple entries are not allowed under this node when the `base_op` node is defined. Each mnemonic defined under *mnemonics* is treated as a valid coverpoint and the arguments of the corresponding instruction are used to update the rest of the coverpoint types.

* **mnemonics-str**
A valid instruction or pseudoinstruction *mnemonic* in the RISCV Instruction Set.

* **base_op**
*This node is optional and should be used only when the mnemonics node has a singular entry which is a pseudo-instruction.*

If the instruction defined in mnemonics is a pseudo-op, *base_op* field can be used to provide its corresponding base instruction.

Note that when *base_op* node is defined, the *mnemonics* node should only hold the pseudo-instruction.

* **base_op-str**
The base instruction corresponding to the pseudoinstruction defined in *mnemonics*

* **p_op_cond**
*This node is mandatory when the ``base_op`` node is defined.*

This node is used to supply the requisite conditions for the *base_op* to be identified as the pseudo-instruction in *mnemonics* node i.e describe th e instance of the base instruction corresponding to the pseudo-instruction.

* **opcode-str**
A valid *opcode* in the RISCV Instruction Set.
* **p_op_cond-str**
Conditions required for the base instruction to be congruent to the pseudoinstruction in *mnemonics*. Multiple conditions are joined using ``and``. For example, ``rs1 == x0 and imm == 3``

Example: ``zext.h`` is a pseudo-instruction based on the ``pack`` instruction in ``RV32``. The node for ``zext.h`` will look like the following.

.. code-block:: yaml
zext.h_32:
config:
- check ISA:=regex(.*RV32.*B.*)
- check ISA:=regex(.*RV32.*Zbb.*)
mnemonics:
zext.h: 0
base_op: pack
p_op_cond: rs2 == x0
...
* **rs1**
*This node is optional.*
Expand Down
48 changes: 48 additions & 0 deletions docs/source/pseudo_op_support.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
*********************************
Pseudo-Ops Support for RISCV-ISAC
*********************************

Coverpoints are defined in a CGF file under the ``opcode`` node in the CGF. This is a misnomer as ISAC and CTG
deals with mnemonics of the instruction rather than the actual encoding. In order to deal with mnemonics of pseudo-Ops,
and its congruent base instruction definition, changes are brought to the CGF format.

Format
######
The ``opcode`` field is renamed to ``mnemonics``. To support pseudo-instructions two new fields ``base_op`` and ``p_op_cond``
are added to the covergroups. The ``base_op`` and ``p_op_cond`` are optional fields which specify the base operation and the
condition over the different fields of the instruction which when satisfied results in the instruction being recognized as the
pseudo-op mentioned in ``mnemonics``. As an example, ``zext.h`` is a pseudo-op of ``pack`` in RV32 and packw in RV64 with ``rs2``
equal to ``x0``. Covergroup for ``zext.h`` pseudo-op can be expressed as follows: ::

zext.h_32:
config:
- check ISA:=regex(.*RV32.*B.*)
- check ISA:=regex(.*RV32.*Zbb.*)
mnemonics:
zext.h: 0
base_op: packw
p_op_cond: rs2 == x0
...

zext.h_64:
config:
- check ISA:=regex(.*RV64.*B.*)
- check ISA:=regex(.*RV64.*Zbb.*)
mnemonics:
zext.h: 0
base_op: pack
p_op_cond: rs2 == x0
...

The ``expand_cgf`` method defined in ``cgf_normalize.py`` goes through every covergroup in the working cgf dictionary. If it encounters
``opcode`` node, a deprecation warning is printed and ``opcode`` is renamed to ``mnemonics``. The method also facilitates checks to see
if ``base_op`` and ``p_op_cond`` meets required conditions.

While computing the coverage, if the decoded instruction under scrutiny is equal to the instruction mentioned in ``base_op`` of working
covergroup, the conditions mentioned in ``p_op_cond`` are evaluated. If a match is found, the instruction defined in ``mnemonic`` field is
assumed to be hit and the coverpoint hit statistics is updated accordingly.

Note
####
- The ``p_op_cond`` node is relevant only if the ``base_op`` node has been defined.
- The ``mnemonics`` node is allowed to have multiple entries only if the ``base_op`` node is empty.
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.12.0'
__version__ = '0.13.0'
20 changes: 18 additions & 2 deletions riscv_isac/cgf_normalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import copy
from riscv_isac.fp_dataset import *

import time

def twos(val,bits):
'''
Finds the twos complement of the number
Expand Down Expand Up @@ -549,18 +551,32 @@ def alternate(var, size, signed=True, fltr_func=None,scale_func=None):
def expand_cgf(cgf_files, xlen):
'''
This function will replace all the abstract functions with their unrolled
coverpoints
coverpoints. It replaces node
:param cgf_files: list of yaml file paths which together define the coverpoints
:param xlen: XLEN of the riscv-trace
:type cgf: list
:type xlen: int
'''

cgf = utils.load_cgf(cgf_files)
for labels, cats in cgf.items():
if labels != 'datasets':
# If 'opcode' found, rename it to 'mnemonics'
if 'opcode' in cats:
logger.warning("Deprecated node used: 'opcode'. Use 'mnemonics' instead")

temp = cgf[labels]['opcode']
del cgf[labels]['opcode']
cgf[labels].insert(1, 'mnemonics', temp)

if 'base_op' in cats:
if 'p_op_cond' not in cats:
logger.error(f'p_op_cond node not found in {labels} label.')

if len(cgf[labels]['mnemonics'].keys()) > 1:
logger.error(f'Multiple instruction mnemonics found when base_op label defined in {labels} label.')

for label,node in cats.items():
if isinstance(node,dict):
if 'abstract_comb' in node:
Expand Down
Loading

0 comments on commit 785c887

Please sign in to comment.