Skip to content

Commit

Permalink
Merge pull request #60 from techiepriyansh/multiple-sigs-per-covpt
Browse files Browse the repository at this point in the history
Implement capturing multiple signature updates per coverpoint
  • Loading branch information
pawks authored Apr 9, 2023
2 parents 9dc9503 + 980473e commit a4b25fa
Show file tree
Hide file tree
Showing 12 changed files with 741 additions and 150 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [0.17.0] - 2022-10-25
- Improve data propagation reports to capture multiple signature updates per coverpoint
- Add a CLI flag to explicitly log the redundant coverpoints while normalizing the CGF files

## [0.16.1] - 2022-10-20
- Fix length of commitval to 32 bits if flen is 32 for f registers in sail parser.

Expand Down
12 changes: 11 additions & 1 deletion docs/source/cgf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,11 @@ A covergroup contains the following nodes:
* **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.
* ``csr_name`` : The value (as of the end of current instruction) in the CSR whose name is specified by csr_name.

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

* ``write("csr_name")`` : The value being written to the CSR in the current instruction whose name is specified by csr_name.

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

Expand Down Expand Up @@ -367,6 +371,12 @@ A covergroup contains the following nodes:
mstatus && (0x8) == 0x8
4. A coverpoint which checks whether the *M* bit of the value being written to *misa* register is unset and the final value that the register assumes has that bit still set.

.. code-block:: python
(write("misa") >> 12) & 1 == 0 and misa & 0x1000 == 0x1000
* **cross_comb**
*This node is optional.*

Expand Down
12 changes: 12 additions & 0 deletions docs/source/dpr.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
***********************
Data Propagation Report
***********************

The data propagation details quality analysis on the data propagation occurring within the test/application. It reports
the following statistics about coverpoint hits and related signature updates:

* **STAT1** : Number of instructions that hit unique coverpoints and update the signature
* **STAT2** : Number of instructions that hit covepoints which are not unique but still update the signature (completely or partially)
* **STAT3** : Number of instructions that hit a unique coverpoint but do not update the signature completely
* **STAT4** : Number of multiple signature updates for the same coverpoint
* **STAT5** : Number of times the signature was overwritten
95 changes: 94 additions & 1 deletion riscv_isac/InstructionObject.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import struct


instrs_sig_mutable = ['auipc','jal','jalr']
instrs_sig_update = ['sh','sb','sw','sd','c.sw','c.sd','c.swsp','c.sdsp','fsw','fsd',\
'c.fsw','c.fsd','c.fswsp','c.fsdsp']
instrs_no_reg_tracking = ['beq','bne','blt','bge','bltu','bgeu','fence','c.j','c.jal','c.jalr',\
'c.jr','c.beqz','c.bnez', 'c.ebreak'] + instrs_sig_update
instrs_fcsr_affected = ['fmadd.s','fmsub.s','fnmsub.s','fnmadd.s','fadd.s','fsub.s','fmul.s','fdiv.s',\
'fsqrt.s','fmin.s','fmax.s','fcvt.w.s','fcvt.wu.s','feq.s','flt.s',\
'fle.s','fcvt.s.w','fcvt.s.wu','fcvt.l.s','fcvt.lu.s','fcvt.s.l',\
'fcvt.s.lu', 'fmadd.d','fmsub.d','fnmsub.d','fnmadd.d','fadd.d','fsub.d',\
'fmul.d','fdiv.d','fsqrt.d','fmin.d','fmax.d','fcvt.s.d','fcvt.d.s',\
'feq.d','flt.d','fle.d','fcvt.w.d','fcvt.wu.d','fcvt.l.d','fcvt.lu.d',\
'fcvt.d.l','fcvt.d.lu']
unsgn_rs1 = ['sw','sd','sh','sb','ld','lw','lwu','lh','lhu','lb', 'lbu','flw','fld','fsw','fsd',\
'bgeu', 'bltu', 'sltiu', 'sltu','c.lw','c.ld','c.lwsp','c.ldsp',\
'c.sw','c.sd','c.swsp','c.sdsp','mulhu','divu','remu','divuw',\
Expand Down Expand Up @@ -112,6 +123,10 @@ def __init__(
self.rd_nregs = 1


def is_sig_update(self):
return self.instr_name in instrs_sig_update


def evaluate_instr_vars(self, xlen, flen, arch_state, csr_regfile, instr_vars):
'''
This function populates the provided instr_vars dictionary
Expand Down Expand Up @@ -179,6 +194,84 @@ def evaluate_instr_vars(self, xlen, flen, arch_state, csr_regfile, instr_vars):
instr_vars.update(ext_specific_vars)


def get_elements_to_track(self, xlen):
'''
This function returns the elements to track to aid in monitoring signature updates and related statistics.
The returned value is a tuple of three elements:
- The first element is a list of registers to track whose values cannot be modified before storing
- The second element is a list of registers to track whose value can be modified prior to storing
- The third element is a list of instructions to track for signature updates other than those of tracked registers (mostly used for branch instructions)
'''
regs_to_track_immutable = []
regs_to_track_mutable = []
instrs_to_track = []

if self.instr_name in instrs_no_reg_tracking:
store_instrs = []
if self.is_sig_update():
store_instrs = [self.instr_name]
else:
if self.instr_name.startswith("c."):
store_instrs = ['sd','c.sdsp'] if xlen == 64 else ['sw','c.swsp']
else:
store_instrs = ['sd'] if xlen == 64 else ['sw']
instrs_to_track.append(store_instrs)
elif self.instr_name in instrs_sig_mutable:
if self.rd is not None:
reg = self.rd[1] + str(self.rd[0])
regs_to_track_mutable.append(reg)
else:
if self.rd is not None:
reg = self.rd[1] + str(self.rd[0])
regs_to_track_immutable.append(reg)

if self.instr_name in instrs_fcsr_affected:
regs_to_track_immutable.append('fcsr')

if self.csr_commit is not None:
for commit in self.csr_commit:
if commit[0] == "CSR":
csr_reg = commit[1]
if csr_reg not in regs_to_track_immutable:
regs_to_track_immutable.append(csr_reg)

return (regs_to_track_immutable, regs_to_track_mutable, instrs_to_track)


def get_changed_regs(self, arch_state, csr_regfile):
'''
This function returns a list of registers whose value will be changed as
a result of executing this instruction.
:param csr_regfile: Architectural state of CSR register files
:param instr_vars: Dictionary to be populated by the evaluated instruction variables
'''
changed_regs = []

if self.reg_commit is not None:
reg = self.reg_commit[0] + self.reg_commit[1]

prev_value = None
if self.reg_commit[0] == 'x':
prev_value = arch_state.x_rf[int(self.reg_commit[1])]
elif self.reg_commit[0] == 'f':
prev_value = arch_state.f_rf[int(self.reg_commit[1])]

if prev_value != str(self.reg_commit[2][2:]): # this is a string check, but should we do an exact number check?
changed_regs.append(reg)

if self.csr_commit is not None:
for commit in self.csr_commit:
if commit[0] == "CSR":
csr_reg = commit[1]

if csr_regfile[csr_reg] != str(commit[2][2:]):
changed_regs.append(csr_reg)

return changed_regs


def update_arch_state(self, arch_state, csr_regfile):
'''
This function updates the arch state and csr regfiles
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,5 +4,5 @@

__author__ = """InCore Semiconductors Pvt Ltd"""
__email__ = 'info@incoresemi.com'
__version__ = '0.16.1'
__version__ = '0.17.0'

4 changes: 3 additions & 1 deletion riscv_isac/cgf_normalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ def alternate(var, size, signed=True, fltr_func=None,scale_func=None):
#return [(coverpoint,"Alternate") for coverpoint in coverpoints]


def expand_cgf(cgf_files, xlen,flen):
def expand_cgf(cgf_files, xlen,flen, log_redundant=False):
'''
This function will replace all the abstract functions with their unrolled
coverpoints. It replaces node
Expand Down Expand Up @@ -616,6 +616,8 @@ def expand_cgf(cgf_files, xlen,flen):
+" in "+labels+": "+str(e) )
else:
for cp,comment in exp_cp:
if log_redundant and cp in cgf[labels][label]:
logger.warn(f'Redundant coverpoint during normalization: {cp}')
cgf[labels][label].insert(l+i,cp,coverage,comment=comment)
i += 1
return dict(cgf)
Expand Down
17 changes: 11 additions & 6 deletions riscv_isac/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
dpr_template = '''
# Data Propagation Report
- **STAT1** : Number of instructions that hit unique coverpoints and update the signature.
- **STAT2** : Number of instructions that hit covepoints which are not unique but still update the signature
- **STAT3** : Number of instructions that hit a unique coverpoint but do not update signature
- **STAT1** : Number of instructions that hit unique coverpoints and update the signature
- **STAT2** : Number of instructions that hit covepoints which are not unique but still update the signature (completely or partially)
- **STAT3** : Number of instructions that hit a unique coverpoint but do not update the signature completely
- **STAT4** : Number of multiple signature updates for the same coverpoint
- **STAT5** : Number of times the signature was overwritten
Expand Down Expand Up @@ -57,10 +57,15 @@
## Details of STAT1:
- The first column indicates the signature address and the data at that location in hexadecimal in the following format:
- The first column indicates the signature address(es) and the data at that location in hexadecimal in the following format:
```
[Address]
Data
[Address1]
Data1
[Address2]
Data2
...
```
- The second column captures all the coverpoints which have been captured by that particular signature location
Expand Down
Loading

0 comments on commit a4b25fa

Please sign in to comment.