Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates for Virtual Memory coverage functionality and Translator #551

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@
*.DS_Store

riscv-target/

#ignore venv
riscv-isac/riscv-env
2 changes: 2 additions & 0 deletions riscv-isac/docs/source/cgf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,8 @@ syntax for the Translator:

Operations can be performed on the *number_placeholder_index* to get the required value. Consider another example:

.. tip:: Use the modulus operator represented by % in python if you want to traverse over the length of the list !!!

.. code-block:: python

csr_comb:
Expand Down
31 changes: 23 additions & 8 deletions riscv-isac/riscv_isac/InstructionObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,18 @@ def evaluate_instr_vars(self, xlen, flen, arch_state, csr_regfile, instr_vars):

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

#update the variable for the length of the load or store:
if self.instr_name in ['ld','lw','lb','lh','sd','sw','sb','sh']:
if self.instr_name in ['ld','sd']:
instr_vars['access_len'] = 8
if self.instr_name in ['lw','sw']:
instr_vars['access_len'] = 4
if self.instr_name in ['lh','sh']:
instr_vars['access_len'] = 2
if self.instr_name in ['lb','sb']:
instr_vars['access_len'] = 1
else:
instr_vars['access_len'] = None
#Update the values for the trap registers
self.trap_registers_update(instr_vars,self.trap_dict)

Expand Down Expand Up @@ -487,21 +499,24 @@ def trap_registers_update(self, instr_vars, trap_dict):
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'
instr_vars['scause'] = None
instr_vars['stval'] = None

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'
instr_vars['mcause'] = None
instr_vars['mtval'] = None

else:
instr_vars['mcause'] = '0'
instr_vars['mtval'] = '0'
instr_vars['scause'] = '0'
instr_vars['stval'] = '0'
#initialize them to None for the first time in the instr_vars
#reset them to None in case the mode change is ret
instr_vars['mcause'] = None
instr_vars['mtval'] = None
instr_vars['scause'] = None
instr_vars['stval'] = None

return None

Expand Down
81 changes: 44 additions & 37 deletions riscv-isac/riscv_isac/coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,10 @@
940: 'pmpcfg12',
941: 'pmpcfg13',
942: 'pmpcfg14',
943: 'pmpcfg15'
943: 'pmpcfg15',
266: 'senvcfg',
778: 'menvcfg',
1863: 'mseccfg'
}

class cross():
Expand Down Expand Up @@ -571,7 +574,10 @@ def __init__ (self, xlen):
"vxsat": int('009',16),
"fflags":int('1',16),
"frm":int('2',16),
"fcsr":int('3',16)
"fcsr":int('3',16),
"menvcfg":int('30A', 16),
"senvcfg":int('10A', 16),
"mseccfg":int('747', 16)
}
for i in range(16):
self.csr_regs["pmpaddr"+str(i)] = int('3B0',16)+i
Expand Down Expand Up @@ -951,7 +957,10 @@ def compute_per_line(queue, event, cgf_queue, stats_queue, cgf, xlen, flen, addr
#csr regfile track for the previous instruction(old_csr_regfile)
old_csr_regfile = {}
for i in csr_regfile.csr_regs:
old_csr_regfile[i] = int(csr_regfile[i],16)
if isinstance(csr_regfile[i], str):
old_csr_regfile[i] = int(csr_regfile[i],16)
else:
old_csr_regfile[i] = csr_regfile[i]
def old_fn_csr_comb_covpt(csr_reg):
return old_csr_regfile[csr_reg]

Expand All @@ -961,11 +970,11 @@ def old_fn_csr_comb_covpt(csr_reg):
instr.evaluate_instr_vars(xlen, flen, arch_state, csr_regfile, instr_vars)

#update the state of trap registers in csr_reg file using instr_vars
if instr_vars["mode_change"] is not None: #change the state only on the instruction
csr_regfile["mcause"] = instr_vars["mcause"]
csr_regfile["scause"] = instr_vars["scause"]
csr_regfile["mtval"] = instr_vars["mtval"]
csr_regfile["stval"] = instr_vars["stval"]
# if instr_vars["mode_change"] is not None: #change the state only on the instruction
csr_regfile["mcause"] = instr_vars["mcause"]
csr_regfile["scause"] = instr_vars["scause"]
csr_regfile["mtval"] = instr_vars["mtval"]
csr_regfile["stval"] = instr_vars["stval"]

if 'rs1' in instr_vars:
rs1 = instr_vars['rs1']
Expand All @@ -980,8 +989,10 @@ def old_fn_csr_comb_covpt(csr_reg):
is_rd_valid = False

for i in csr_regfile.csr_regs:
instr_vars[i] = int(csr_regfile[i],16)

if isinstance(csr_regfile[i], str):
instr_vars[i] = int(csr_regfile[i],16)
else:
instr_vars[i] = csr_regfile[i]
instr.iptw_update(instr_vars, iptw_dict)
instr.ptw_update(instr_vars)

Expand Down Expand Up @@ -1026,40 +1037,37 @@ def get_pte(pa, pte_addr, pgtb_addr):
else:
return None

def get_pte_prop(prop_name,pa, pte_addr, pgtb_addr):
pte_per = get_pte(pa, pte_addr, pgtb_addr)
if pte_per is not None:
pte_per = get_pte(pa, pte_addr, pgtb_addr) & 0x3FF
prop_name_lower = prop_name.lower()
if prop_name_lower == 'v' and (pte_per & 0x01 != 0):
return 1
elif prop_name_lower == 'r' and (pte_per & 0x02 != 0):
return 1
elif prop_name_lower == 'w' and (pte_per & 0x04 != 0):
return 1
elif prop_name_lower == 'x' and (pte_per & 0x08 != 0):
return 1
elif prop_name_lower == 'u' and (pte_per & 0x10 != 0):
return 1
elif prop_name_lower == 'g' and (pte_per & 0x20 != 0):
return 1
elif prop_name_lower == 'a' and (pte_per & 0x40 != 0):
return 1
elif prop_name_lower == 'd' and (pte_per & 0x80 != 0):
return 1
else:
return 0

def get_pte_prop(prop_name, pte_addr):
'''
Function to return whether a specific Permission is given to the PTE or not
:param prop_name: an input property ., example: 'U' for U bit or 'RWX' for a combination of bits
:param pte_addr: PTE address for which we want to get the information

:type prop_name: str
:type pte_addr: hex/int

:return: 1 or 0 depending whether the specific (or combination of) permission/s is set or not respectively.
'''
bitmask_dict = {'v': 0x01, 'r': 0x02, 'w': 0x04, 'x': 0x08, 'u': 0x10, 'g': 0x20, 'a': 0x40, 'd': 0x80}

if pte_addr is not None:
# Get the permissions bit out of the pte_addr
pte_per = pte_addr & 0x3FF

# Check each character in prop_name
for char in prop_name.lower():
if char in bitmask_dict and (pte_per & bitmask_dict[char] == 0):
return 0
return 1
else:
return None
return 0

globals()['get_addr'] = check_label_address
globals()['get_mem_val'] = get_mem_val
globals()['get_pte'] = get_pte
globals()['get_pte_prop'] = get_pte_prop

if enable :
print(instr_vars)
ucovpt = []
covpt = []
csr_covpt = []
Expand Down Expand Up @@ -1136,7 +1144,6 @@ def get_pte_prop(prop_name,pa, pte_addr, pgtb_addr):
value['rs3'][rs3] += 1

if 'op_comb' in value and len(value['op_comb']) != 0 :

for coverpoints in value['op_comb']:
if eval(coverpoints, globals(), instr_vars):
if cgf[cov_labels]['op_comb'][coverpoints] == 0:
Expand Down
36 changes: 28 additions & 8 deletions riscv-isac/riscv_isac/plugins/c_sail.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def setup(self, trace, arch):
instr_pattern_c_sail_csr_reg_val = re.compile('(?P<CSR>CSR|clint::tick)\s(?P<reg>[a-z0-9]+)\s<-\s(?P<val>[0-9xABCDEF]+)(?:\s\(input:\s(?P<input_val>[0-9xABCDEF]+)\))?')
instr_pattern_c_sail_mem_val = re.compile('mem\[(?P<addr>[0-9xABCDEF]+)\]\s<-\s(?P<val>[0-9xABCDEF]+)')
instr_pattern_c_sail_trap = re.compile(r'trapping\sfrom\s(?P<mode_change>\w+\sto\s\w+)\sto\shandle\s(?P<call_type>\w+.*)\shandling\sexc#(?P<exc_num>0x[0-9a-fA-F]+)\sat\spriv\s\w\swith\stval\s(?P<tval>0x[0-9a-fA-F]+)')
instr_pattern_c_sail_ret = re.compile(r'ret-ing\sfrom\s(?P<mode_change>\w+\sto\s\w+)')
def extractInstruction(self, line):
instr_pattern = self.instr_pattern_c_sail
re_search = instr_pattern.search(line)
Expand Down Expand Up @@ -60,6 +61,13 @@ def extractVirtualMemory(self, line):
mem_r_pattern = re.compile(r'mem\[R,([0-9xABCDEF]+)\] -> 0x([0-9xABCDEF]+)')
mem_x_pattern = re.compile(r'mem\[X,([0-9xABCDEF]+)\] -> 0x([0-9xABCDEF]+)')
mem_depa_pattern = re.compile(r'mem\[([0-9xABCDEF]+)\]')
instr_trap_pattern = self.instr_pattern_c_sail_trap.search(line)

#in case of a trap
if instr_trap_pattern:
trap = 1
else:
trap = 0

match_search_mnemonic = self.instr_pattern_c_sail.search(line)
depa, ieva, ieva_align, depa_align, iepa, iepa_align = None, None, None, None, None, None
Expand All @@ -78,14 +86,19 @@ def extractVirtualMemory(self, line):
iptw_list=(mem_r_pattern.findall(line_upper_part))
dptw_list=(mem_r_pattern.findall(line_lower_part))

#Update the data physical address only when there is no trap else it will not be present in the log.
if dptw_list is not None:
if "lw" in match_search_mnemonic.group('mnemonic') and dptw_list:
depa_list=dptw_list.pop()
depa=int(depa_list[0],16)
else:
depa_list=mem_depa_pattern.findall(line_lower_part)
if len(depa_list) != 0:
if trap == 0:
#Since, the load has the same pattern as the page table walk, skip the last one as it is a false positive.
loads_exception_list = {"lw", "ld", "lh", "lb", "lr.w", "lr.d", "lbu", "lhu", "lwu", "c.lw", "c.ld", "c.lwsp", "c.ldsp", "flw", "fld"}
if match_search_mnemonic.group('mnemonic').split()[0] in loads_exception_list and dptw_list:
depa_list=dptw_list.pop()
depa=int(depa_list[0],16)
#Stores and other page table walks are normal
else:
depa_list=mem_depa_pattern.findall(line_lower_part)
if len(depa_list) != 0:
depa=int(depa_list[0],16)

ieva_align = 1 if ieva is not None and ieva & 0b11 == 0 else 0
iepa_align = 1 if iepa is not None and iepa & 0b11 == 0 else 0
Expand Down Expand Up @@ -114,15 +127,22 @@ def extracttrapvals(self, line):
instr_trap_pattern = self.instr_pattern_c_sail_trap.search(line)
trap_dict = {"mode_change": None, "call_type": None, "exc_num": None, "tval": None}

#ret will tell us to delete the previous state of the cause registers
instr_ret_pattern = self.instr_pattern_c_sail_ret.search(line)
if instr_trap_pattern:
trap_dict["mode_change"] = instr_trap_pattern.group("mode_change")
trap_dict["call_type"] = instr_trap_pattern.group("call_type")
trap_dict["exc_num"] = instr_trap_pattern.group("exc_num")
trap_dict["tval"] = instr_trap_pattern.group("tval")
self.old_trap_dict = trap_dict

#maintain the value if None
if instr_trap_pattern is None:
elif instr_ret_pattern:
#if ret_signal is 1 then clear the values of the mode_change, call_type, exc_num, tval
trap_dict = {"mode_change": None, "call_type": None, "exc_num": None, "tval": None}
self.old_trap_dict = trap_dict

#maintain the values if None unit the new trap appears
if instr_trap_pattern is None or instr_ret_pattern is None:
trap_dict = self.old_trap_dict
return trap_dict

Expand Down
Loading