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

Support for coverage of Privilged Architecture #80

Merged
merged 24 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3394d08
Support for read_csr added, mstatush error resolved, immediate and rs…
MuhammadHammad001 Nov 13, 2023
03b7d07
Issues resolved for hitcovpt and any_hitcovpt when read_csr accessed
MuhammadHammad001 Nov 13, 2023
3c636da
update to check only the register of interest for the old_fn_csr_comb
MuhammadHammad001 Nov 18, 2023
6fbf910
label_to_addr and mode check support added
MuhammadHammad001 Nov 20, 2023
bb54cbf
physical address, virtual address, page table walk variables added, i…
MuhammadHammad001 Dec 2, 2023
b10a44a
Support for values from memory using mem_val
MuhammadHammad001 Dec 2, 2023
80a19d4
PTE Permission access function added
MuhammadHammad001 Dec 3, 2023
b402d0f
Issue with the option resolved
MuhammadHammad001 Dec 4, 2023
bbc0349
get_pte_per updated to take only three arguments. Useless pte_size re…
MuhammadHammad001 Dec 4, 2023
4363e0a
Virtual memory implementation changed. Now, depends on satp register,…
MuhammadHammad001 Dec 18, 2023
33b0a6e
macro support added
MuhammadHammad001 Dec 18, 2023
346aa75
False exception removed for virtual memory support
MuhammadHammad001 Jan 12, 2024
f08a623
Trap Registers Variables added in instr_vars
MuhammadHammad001 Jan 18, 2024
ac4f342
trap registers updated to maintain the arch-state
MuhammadHammad001 Jan 25, 2024
44d2a47
Merge branch 'dev' into read_csr_support
MuhammadHammad001 Jan 31, 2024
4c15ffd
Support for mnemonic flag and error resolved for inxflg
MuhammadHammad001 Feb 15, 2024
2ca4caa
Support for lr/sc added and also rd_val track added
MuhammadHammad001 Feb 19, 2024
32d0b84
Remove the feature for rs2_val and imm_val skip for csrs in val_comb …
MuhammadHammad001 Feb 21, 2024
b1489b8
Feature for read_csr removed
MuhammadHammad001 Mar 16, 2024
d7da4f5
Update the trap registers state logic and add support for fetch acces…
MuhammadHammad001 Apr 10, 2024
13571b0
Initial Support for Translator added
MuhammadHammad001 Apr 10, 2024
3d897df
Translator function added for merge coverage
MuhammadHammad001 Apr 13, 2024
86c54ff
Documentation added for priv arch functions, translator, macros
MuhammadHammad001 Apr 16, 2024
fbb62e9
Merge branch 'dev' into read_csr_support
UmerShahidengr Jul 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
332 changes: 332 additions & 0 deletions docs/source/cgf.rst

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ def get_version():
release = version

def setup(app):
app.add_stylesheet("custom.css")
app.add_css_file("_static/custom.css")
app.add_css_file("custom.css")

# -- General configuration ---------------------------------------------------

Expand Down Expand Up @@ -81,7 +80,7 @@ def setup(app):
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
language = 'en'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
Expand All @@ -92,6 +91,8 @@ def setup(app):

autodoc_member_order = 'bysource'

#Mention the reference files
bibtex_bibfiles = ['refs.bib']

# -- Options for HTML output -------------------------------------------------

Expand Down
5 changes: 4 additions & 1 deletion docs/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ Help text for each command can be accessed by executing ``riscv_isac <command> -
-e, --elf PATH ELF file
-t, --trace-file PATH Instruction trace file to be analyzed
[required]


-h, --header-file PATH YAML macro file to include
-cm, --cgf-macro CGF MACROS CGF macros to consider for this run.

-c, --cgf-file PATH Coverage Group File(s). Multiple allowed.
[required]

Expand Down
209 changes: 201 additions & 8 deletions riscv_isac/InstructionObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,18 @@
'bset','zext.h','sext.h','sext.b','zext.b','zext.w','minu','maxu','orc.b','add.uw','sh1add.uw',\
'sh2add.uw','sh3add.uw','slli.uw','clz','clzw','ctz','ctzw','cpop','cpopw','rev8',\
'bclri','bexti','binvi','bseti','fcvt.d.wu','fcvt.s.wu','fcvt.d.lu','fcvt.s.lu','c.flwsp',\
'c.not', 'c.sext.b','c.sext.h','c.zext.b','c.zext.h','c.zext.w']
'c.not', 'c.sext.b','c.sext.h','c.zext.b','c.zext.h','c.zext.w','sc.w','lr.w','sc.d','lr.d']
unsgn_rs2 = ['bgeu', 'bltu', 'sltiu', 'sltu', 'sll', 'srl', 'sra','mulhu',\
'mulhsu','divu','remu','divuw','remuw','aes64ds','aes64dsm','aes64es',\
'aes64esm','aes64ks2','sm4ed','sm4ks','ror','rol','rorw','rolw','clmul',\
'clmulh','clmulr','andn','orn','xnor','pack','packh','packu','packuw','packw',\
'xperm.n','xperm.b', 'aes32esmi', 'aes32esi', 'aes32dsmi', 'aes32dsi',\
'sha512sum1r','sha512sum0r','sha512sig1l','sha512sig1h','sha512sig0l','sha512sig0h','fsw',\
'bclr','bext','binv','bset','minu','maxu','add.uw','sh1add.uw','sh2add.uw','sh3add.uw']
'bclr','bext','binv','bset','minu','maxu','add.uw','sh1add.uw','sh2add.uw','sh3add.uw','sc.w', 'sc.d']
f_instrs_pref = ['fadd', 'fclass', 'fcvt', 'fdiv', 'feq', 'fld', 'fle', 'flt', 'flw', 'fmadd',\
'fmax', 'fmin', 'fmsub', 'fmul', 'fmv', 'fnmadd', 'fnmsub', 'fsd', 'fsgnj', 'fsqrt',\
'fsub', 'fsw']
unsgn_rd = ['lr.w','sc.w','lr.d','sc.d']


instr_var_evaluator_funcs = {} # dictionary for holding registered evaluator funcs
Expand Down Expand Up @@ -84,6 +85,10 @@ def __init__(
reg_commit = None,
csr_commit = None,
mnemonic = None,
mode = None,
vm_addr_dict = None,
mem_val = None,
trap_dict = None,
inxFlag = None,
is_sgn_extd = None
):
Expand Down Expand Up @@ -125,7 +130,11 @@ def __init__(
self.rs2_nregs = 1
self.rs3_nregs = 1
self.rd_nregs = 1

self.mode = mode
self.vm_addr_dict = vm_addr_dict
self.matches_for_options = None
self.mem_val = mem_val
self.trap_dict = trap_dict

def is_sig_update(self):
return self.instr_name in instrs_sig_update
Expand All @@ -142,8 +151,11 @@ def evaluate_instr_vars(self, xlen, flen, arch_state, csr_regfile, instr_vars):
:param csr_regfile: Architectural state of CSR register files
:param instr_vars: Dictionary to be populated by the evaluated instruction variables
'''

instr_vars['xlen'] = xlen
instr_vars['flen'] = flen
instr_vars['mode'] = self.mode
instr_vars['mnemonic'] = self.instr_name

instr_vars['iflen'] = flen
if self.instr_name.endswith(".s") or 'fmv.x.w' in self.instr_name:
Expand All @@ -167,13 +179,21 @@ def evaluate_instr_vars(self, xlen, flen, arch_state, csr_regfile, instr_vars):
instr_vars['imm_val'] = self.imm
if self.shamt is not None:
instr_vars['imm_val'] = self.shamt
if self.rl is not None:
instr_vars['rl'] = self.rl
if self.aq is not None:
instr_vars['aq'] = self.aq

imm_val = instr_vars.get('imm_val', None)

#Update the values for the trap registers
self.trap_registers_update(instr_vars,self.trap_dict)

# capture the register operand values
rs1_val = self.evaluate_instr_var("rs1_val", instr_vars, arch_state)
rs2_val = self.evaluate_instr_var("rs2_val", instr_vars, arch_state)
rs3_val = self.evaluate_instr_var("rs3_val", instr_vars, arch_state)
rd_val = self.evaluate_instr_var("rd_val", instr_vars, arch_state)

ea_align = None
# the ea_align variable is used by the eval statements of the
Expand All @@ -193,6 +213,7 @@ def evaluate_instr_vars(self, xlen, flen, arch_state, csr_regfile, instr_vars):
'rs1_val': rs1_val,
'rs2_val': rs2_val,
'rs3_val': rs3_val,
'rd_val' : rd_val,
'rm_val': self.rm,
'ea_align': ea_align,
})
Expand Down Expand Up @@ -275,19 +296,20 @@ def get_changed_regs(self, arch_state, csr_regfile):
if commit[0] == "CSR":
csr_reg = commit[1]

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

return changed_regs


def update_arch_state(self, arch_state, csr_regfile):
def update_arch_state(self, arch_state, csr_regfile, mem_vals):
'''
This function updates the arch state and csr regfiles
with the effect of this instruction.

:param csr_regfile: Architectural state of CSR register files
:param instr_vars: Dictionary to be populated by the evaluated instruction variables
:param mem_vals: Dictionary to be populated for the memory values
'''
arch_state.pc = self.instr_addr

Expand All @@ -300,10 +322,13 @@ def update_arch_state(self, arch_state, csr_regfile):

csr_commit = self.csr_commit
if csr_commit is not None:
for commits in csr_commit:
if (commits[0] == "CSR"):
csr_regfile[commits[1]] = str(commits[2][2:])
for commit in csr_commit:
if (commit[0] == "CSR"):
csr_regfile[commit[1]] = str(commit[2][2:])

mem_val = self.mem_val
if mem_val is not None:
mem_vals[int(mem_val[0][0], 16)] = int(mem_val[0][1], 16)

def evaluate_instr_var(self, instr_var_name, *args):
'''
Expand All @@ -319,13 +344,166 @@ def evaluate_instr_var(self, instr_var_name, *args):
rs1 = self.rs1,
rs2 = self.rs2,
rs3 = self.rs3,
rd = self.rd,
is_rvp = self.is_rvp,
inxFlag = self.inxFlg
): # could just instr_name suffice?
return func(self, *args)

return None

def ptw_update(self,instr_vars):
'''
This function calculates the virtual, physical address of instruction,
data and also the page table walk addresses
for the data.

:param instr_vars : dictionary to be populated by the evaluated address variables
in case when the virtual memory is mentioned under the config
label.
'''
match = ['VM']
if instr_vars['xlen'] == 32:
if ((instr_vars['satp']) >> 31) == 1:
match.append('SV32')
else:
match.append(0)
elif instr_vars['xlen'] == 64:
if ((instr_vars['satp']) >> 60) == 8:
match.append('SV39')
elif ((instr_vars['satp']) >> 60) == 9:
match.append('SV48')
elif ((instr_vars['satp']) >> 60) == 10:
match.append('SV57')
else:
match.append(0)
if match[0] == 'VM' and match[1] in ['SV32', 'SV39', 'SV48', 'SV57']:
instr_vars['depa'] = self.vm_addr_dict['depa']
instr_vars['ieva'] = self.vm_addr_dict['ieva']
instr_vars['iepa'] = self.vm_addr_dict['iepa']
instr_vars['ieva_align'] = self.vm_addr_dict['ieva_align']
instr_vars['iepa_align'] = self.vm_addr_dict['iepa_align']
instr_vars['depa_align'] = self.vm_addr_dict['depa_align']
format_max_len_mapping = {'SV32': 2, 'SV39': 3, 'SV48': 4, 'SV57': 5}
max_len = format_max_len_mapping.get(match[1],0)
size = len(self.vm_addr_dict['dptw_list'])
instr_vars['len_dptw'] = size
remain = max_len
length = max_len - size - 1
for i in range(size):
instr_vars[f'dptw{max_len-1}a'] = int(self.vm_addr_dict['dptw_list'][i][0], 16)
instr_vars[f'dptw{max_len-1}cont'] = int(self.vm_addr_dict['dptw_list'][i][1], 16)
max_len = max_len -1
for i in range(length, -1, -1):
instr_vars[f'dptw{i}cont'] = None
instr_vars[f'dptw{i}a'] = None
for i in range(remain, 5):
instr_vars[f'dptw{i}cont'] = None
instr_vars[f'dptw{i}a'] = None
else:
instr_vars['depa'] = None
instr_vars['ieva'] = None
instr_vars['iepa'] = None
instr_vars['ieva_align'] = None
instr_vars['iepa_align'] = None
instr_vars['depa_align'] = None
instr_vars['len_dptw'] = None
for i in range(0, 5):
instr_vars[f'dptw{i}a'] = None
instr_vars[f'dptw{i}cont'] = None
return None

def iptw_update(self, instr_vars, iptw_dict):
'''
This function page table walk addresses
for the data.

:param instr_vars: Dictionary holding the values of current instruction state.

:param iptw_dict : dictionary that contains the current instruction's
page table walk addresses.
'''
match = ['VM']
if instr_vars['xlen'] == 32:
if ((instr_vars['satp']) >> 31) == 1:
match.append('SV32')
else:
match.append(0)
elif instr_vars['xlen'] == 64:
if ((instr_vars['satp']) >> 60) == 8:
match.append('SV39')
elif ((instr_vars['satp']) >> 60) == 9:
match.append('SV48')
elif ((instr_vars['satp']) >> 60) == 10:
match.append('SV57')
else:
match.append(0)
if (len(self.vm_addr_dict['iptw_list'])) != 0:
if match[0] == 'VM' and match[1] in ['SV32', 'SV39', 'SV48', 'SV57']:
format_max_len_mapping = {'SV32': 2, 'SV39': 3, 'SV48': 4, 'SV57': 5}
max_len = format_max_len_mapping.get(match[1],0)
size = len(self.vm_addr_dict['iptw_list'])
iptw_dict['len_iptw'] = size
remain = max_len
length = max_len - size - 1
for i in range(size):
iptw_dict[f'iptw{max_len-1}a'] = int(self.vm_addr_dict['iptw_list'][i][0], 16)
iptw_dict[f'iptw{max_len-1}cont'] = int(self.vm_addr_dict['iptw_list'][i][1], 16)
max_len = max_len -1
for i in range(length, -1, -1):
iptw_dict[f'iptw{i}a'] = None
iptw_dict[f'iptw{i}cont'] = None
for i in range(remain, 5):
iptw_dict[f'iptw{i}a'] = None
iptw_dict[f'iptw{i}cont'] = None
else:
for i in range(0, 5):
iptw_dict[f'iptw{i}a'] = None
iptw_dict[f'iptw{i}cont'] = None
iptw_dict['len_iptw'] = 0
elif self.mode == 'M':
for i in range(0, 5):
iptw_dict[f'iptw{i}a'] = None
iptw_dict[f'iptw{i}cont'] = None
iptw_dict['len_iptw'] = 0

return None

def trap_registers_update(self, instr_vars, trap_dict):
'''
This function updates the registers related to traps
in the log.
: param instr_vars: Dictionary holding the values of current instruction state
: param trap_dict : Values for the trap registers for current instruction
'''

instr_vars['mode_change'] = trap_dict['mode_change']
instr_vars['call_type'] = trap_dict['call_type']

if trap_dict["mode_change"] is not None:
#update the registers depending upon the mode change
if trap_dict["mode_change"].split()[2] == "M":
instr_vars['mcause'] = trap_dict['exc_num']
instr_vars['mtval'] = trap_dict['tval']
#only update on the initialization
if "scause" not in instr_vars:
instr_vars['scause'] = '0'
instr_vars['stval'] = '0'

elif trap_dict["mode_change"].split()[2] == "S":
instr_vars['scause'] = trap_dict['exc_num']
instr_vars['stval'] = trap_dict['tval']
#only update on the initialization
if "mcause" not in instr_vars:
instr_vars['mcause'] = '0'
instr_vars['mtval'] = '0'
else:
instr_vars['mcause'] = '0'
instr_vars['mtval'] = '0'
instr_vars['scause'] = '0'
instr_vars['stval'] = '0'

return None

'''
Evaluator funcs for rs1_val
Expand Down Expand Up @@ -391,6 +569,21 @@ def evaluate_rs3_val_fsgn(self, instr_vars, arch_state):
return self.evaluate_reg_val_fsgn(self.rs3[0], instr_vars['flen'], instr_vars['xlen'], arch_state)


'''
Evaluator funcs for rd_val

:param arch_state: Architectural state
:param instr_vars: Dictionary of instruction variables already evaluated
'''
@evaluator_func("rd_val", lambda **params: params['instr_name'] in unsgn_rd and params['rd'] is not None)
def evaluate_rd_val_unsgn(self, instr_vars, arch_state):
return self.evaluate_reg_val_unsgn(self.rd[0], instr_vars['xlen'], arch_state)

@evaluator_func("rd_val", lambda **params: not params['instr_name'] in unsgn_rd and params['rd'] is not None and params['rd'][1] == 'x')
def evaluate_rd_val_sgn(self, instr_vars, arch_state):
return self.evaluate_reg_val_sgn(self.rd[0], instr_vars['xlen'], arch_state)


'''
Evaluator funcs for extension specific variables

Expand Down
Loading