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 #21 from riscv-software-src/cross-coverage
Browse files Browse the repository at this point in the history
Feature addition: Cross coverage
  • Loading branch information
neelgala authored Nov 1, 2021
2 parents cc10db5 + 5d13c1d commit 94e62c9
Show file tree
Hide file tree
Showing 11 changed files with 1,228 additions and 983 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

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

## [0.8.0] - 2021-10-30
- Added cross combination coverage support.

## [0.7.3] - 2021-09-02
- Updated logger to enable logging for API calls.

Expand Down
134 changes: 134 additions & 0 deletions docs/source/Cross_coverage.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
###############
Cross Coverage
###############

ISAC supports extraction of data dependencies across different instructions in the log file. It can check for possible data hazards (RAW, WAW, WAR) between instructions.
The hazards are checked for instructions belonging to the same window. The window size of the instruction is a parameter (by default taken as 32).
The coverpoints are updated whenever the conditions mentioned in them are matched for a given instruction.

Syntax for the coverpoints
===========================

Each coverpoint is a string constituting of three sections - opcode list, assign list and condition list separated by ``::`` symbol. In each of these lists symbol
``?`` signifies a don't care condition. The delimiter for elements of the list is ``:`` symbol. The template of a generic coverpoint is shown below:

``[list of opcodes]::[list of assignment statements]::[list of condition statements]``

Opcode List:
--------------
This is the list of instruction names against which we check the name of the current instruction in the queue. Here ``?`` signifies that we needn't check the name
for that instruction as that won't affect the conditions of that coverpoint. Opcode list is a list of tuples and don't care conditions.

An example of a opcode list : ``[(add,sub):?:?:(mul,mulh):?]``

Assign List:
-------------
This list contains the assigning statements for registers. These statements are evaluated using ``exec`` command. The register numbers are assigned to variables.
Under don't care conditions, no assignment is done.

An example of assign list: ``[a=rd:?:?]``

Here a is any variable which is assigned the destination register number of the first instruction.

Condition List:
----------------
This contains the evaluation statements to check the data dependencies. In case of don't care conditions, we don't check for data dependecies for that
particular instruction. It conatins conditions for both source as well as destination registers. We can check for both consuming and non-consuming instructions.

Example of condition list: ``[?:rs1==a or rs2==a]``

Here let a be the destination register of the first instruction (assigned by assign list). Then this checks whether any of the source registers are equal to the
destination register of the previous instruction. It basically checks for read after write hazard.

Cross Coverage Queue
=====================

This is list of instruction objects in which the data is pushed in the sequence they are parsed. Whenever the queue size becomes equal to the window size, we check for all potential data hazards between the front element of the queue and the rest of the instructions according to the coverpoint and then pop the first element.

Cross Coverage Class
=====================

def __init__(self,label,coverpoint):
---------------------------------------

The cross coverage class ``cross`` is initialized with the ``label`` and ``coverpoint``. ``result`` stores the coverage for that coverpoint.

* Arguments: ``self`` instance of the class, ``label`` the instruction name, ``coverpoint`` the coverpoint to be evaluated.


.. code-block:: python
def __init__(self,label,coverpoint):
self.label = label
self.coverpoint = coverpoint
self.result = 0
An instance of a class is created for each ``(label,coverpoint)`` pair present in the CGF and all the relevant information about the coverpoint - opcode list, assign list and condition list are extracted.

def process(self, queue, window_size, addr_pairs):
----------------------------------------------------

The ``process`` function of ``cross`` evaluates each coverpoint and updates ``result`` if there is a hit. The data in the coverpoint is evaluated against their corresponding instruction in the queue i.e. if the index of an instruction is i, then it will check and assign statments at index i of the three lists of the coverpoints. If the instruction address doesn't belong to any list of addresses in ``addr_pairs`` we treat is as a don't care. These coverpoints are checked in three steps.

- First, the name of the first instruction is checked against the corresponding entry in the opcode list.
- If the instruction is present, we assign its register value to a variable using ``exec`` command on the assign list elements.
- Then we check for the conditions in the condition list using ``eval`` command.
The above steps are repeated until the entire coverpoint is evaluated and it's a hit or the conditions are not satisfied and the loop breaks.

* Arguments: ``self`` instance of the class, ``queue`` the list containing the instructions to be evaluated, ``window_size`` maximum number of instructions to be checked for any coverpoint, ``addr_pairs`` the addresses to be considered while evaluating an instruction
* Returns: None

def get_metric(self):
----------------------

It returns the coverage for that instance.

* Arguments: ``self`` instance of the class
* Returns: ``result`` the final coverage for that coverpoint

Updating the CGF
========================

- An object dictionary ``obj_dict`` contains an instance of ``cross`` for each ``(label,coverpoint)`` pair.
- As the instrcutions are parsed, they are appended to the ``cross_cover_queue`` which is the list of instructions to be checked.
- When the size of queue becomes equal to the window size, for each entry in ``obj_dict``, the coverpoints are evaluated in ``process``
- The first element of the queue is popped and the process is repeated.
- After all the instrcutions are parsed, all the instructions in the queue are again evaluated in the above manner till there is nothing to evaluate.
- The final metric for each ``(label,coverpoint)`` instance is updated for each node in the CGF.

**Examples of coverpoints**
The window size is fixed and equal to 5.

1. RAW for an add instruction followed immediately by a subtract instruction.

.. code-block:: python
[(add,sub) : (add,sub) ] :: [a=rd : ? ] :: [? : rs1==a or rs2==a ]
2. RAW on x10 register for an add instruction followed by a subtract instruction with one non-consuming/non-updating instruction in between.
No update happens to the rd register in between.

.. code-block:: python
[(add,sub) : ? : (add,sub) ] :: [a=rd : ? : ? ] :: [rd==x10 : rd!=a and rs1!=a and rs2!=a : rs1==a or rs2==a ]
3. WAW for an add instruction followed by a subtract instruction with 3 non-consuming instructions in between.

.. code-block:: python
[add : ? : ? : ? : sub] :: [a=rd : ? : ? : ? : ?] :: [? : ? : ? : ? : rd==a]
4. WAW for add followed by subtract with 3 consuming instructions in between.

.. code-block:: python
[(add,sub) : ? : ? : ? : (add,sub)] :: [a=rd : ? : ? : ? : ?] :: [? : rs1==a or rs2==a : rs1==a or rs2==a : rs1==a or rs2==a : rd==a]
5. WAR for an add instruction followed immediately by a subtract instruction.

.. code-block:: python
[(add,sub) : (add,sub) ] :: [a=rs1; b=rs2 : ? ] :: [? : rd==a or rd==b ]
60 changes: 60 additions & 0 deletions docs/source/cgf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ A covergroup is a dictionary based on the following template. These dictionaries
* Register Operand Combinations
* Register/Immediate Value Combinations
* Control and Status Registers Value Combinations
* Cross coverage nodes

Template
--------
Expand Down Expand Up @@ -58,6 +59,10 @@ The template for defining a covergroup is as follows:
csr_comb:
<csrcomb-str>: 0
<csrcomb-str>: 0
...
cross_comb:
<crosscomb_str>:0
<crosscomb_str>:0
Expand Down Expand Up @@ -308,12 +313,67 @@ A covergroup contains the following nodes:
.. 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
* **cross_comb**
*This node is optional.*

This node describes the *Cross combination coverpoints* for a covergroup. Cross coverage can identify potential data hazards between instructions - Read after Write, Write after Write, Write after Read.

* **crosscomb-str**
This string is divided into three parts - opcode list, assign list and condition list separated by :: symbol. It is parsed and all the three lists are obtained separately. The variables available for use in the expression are as follows:

* ``instr_name`` : The instruction names in the opcode list

* ``rs1`` : The register number of source register 1 of the current instruction in the assign list.

* ``rs2`` : The register number of source register 2 of the current instruction in the assign list.

* ``rd`` : The register number of destination register of the current instruction in the assign list.

Along with the above mentioned variable any valid python comparison operators can be used in the condition list.


**Examples**

The window size is fixed and equal to 5.

1. RAW for an add instruction followed immediately by a subtract instruction.

.. code-block:: python
[(add,sub) : (add,sub) ] :: [a=rd : ? ] :: [? : rs1==a or rs2==a]
2. RAW on x10 register for an add instruction followed by a subtract instruction with one non-consuming/non-updating instruction in between.
No update happens to the rd register in between.

.. code-block:: python
[(add,sub) : ? : (add,sub) ] :: [a=rd : ? : ? ] :: [rd==x10 : rd!=a and rs1!=a and rs2!=a : rs1==a or rs2==a ]
3. WAW for an add instruction followed by a subtract instruction with 3 non-consuming instructions in between.

.. code-block:: python
[add : ? : ? : ? : sub] :: [a=rd : ? : ? : ? : ?] :: [? : ? : ? : ? : rd==a]
4. WAW for add followed by subtract with 3 consuming instructions in between.

.. code-block:: python
[(add,sub) : ? : ? : ? : (add,sub)] :: [a=rd : ? : ? : ? : ?] :: [? : rs1==a or rs2==a : rs1==a or rs2==a : rs1==a or rs2==a : rd==a]
5. WAR for an add instruction followed immediately by a subtract instruction.

.. code-block:: python
[(add,sub) : (add,sub) ] :: [a=rs1; b=rs2 : ? ] :: [? : rd==a or rd==b]
20 changes: 20 additions & 0 deletions riscv_isac/InstructionObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ def __init__(
zimm = None,
csr = None,
shamt = None,
succ = None,
pred = None,
rl = None,
aq = None,
rm = None,
reg_commit = None,
csr_commit = None,
mnemonic = None
Expand Down Expand Up @@ -44,6 +49,11 @@ def __init__(
self.zimm = zimm
self.csr = csr
self.shamt = shamt
self.succ = succ
self.pred = pred
self.rl = rl
self.aq = aq
self.rm = rm
self.reg_commit = reg_commit
self.csr_commit = csr_commit
self.mnemonic = mnemonic
Expand All @@ -66,6 +76,16 @@ def __str__(self):
line+= ' zimm: '+ str(self.zimm)
if self.shamt:
line+= ' shamt: '+ str(self.shamt)
if self.succ:
line+= ' succ: '+ str(self.succ)
if self.pred:
line+= ' pred: '+ str(self.pred)
if self.rl:
line+= ' rl: '+ str(self.rl)
if self.aq:
line+= ' aq: '+ str(self.aq)
if self.rm:
line+= ' rm: '+ str(self.rm)
if self.reg_commit:
line+= ' reg_commit: '+ str(self.reg_commit)
if self.csr_commit:
Expand Down
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.7.3'
__version__ = '0.8.0'
Loading

0 comments on commit 94e62c9

Please sign in to comment.