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

Commit ba72cb7

Browse files
authored
Merge pull request #49 from edwin7026/master
Support for Instruction Aliases
2 parents b3f81ef + 0727704 commit ba72cb7

File tree

9 files changed

+185
-31
lines changed

9 files changed

+185
-31
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

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

5+
## [0.15.0] - 2022-08-25
6+
- Added support for instruction aliases
7+
58
## [0.14.0] - 2022-08-08
69
- Add fields to instruction object
710
- Enable generic coverage evaluation mechanisms for floating point instructions

docs/source/cgf.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,13 +376,16 @@ A covergroup contains the following nodes:
376376
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:
377377

378378
* ``instr_name`` : The instruction names in the opcode list
379+
380+
* ``instruction_alias``: The instruction alias for a set of instructions as defined in ``/riscv_isac/data/instr_alias.yaml``
379381

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

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

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

388+
Instruction aliases when used will be expanded into a tuple of instruction under the given alias.
386389
Along with the above mentioned variable any valid python comparison operators can be used in the condition list.
387390

388391

@@ -401,7 +404,7 @@ A covergroup contains the following nodes:
401404

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

riscv_isac/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44

55
__author__ = """InCore Semiconductors Pvt Ltd"""
66
__email__ = 'info@incoresemi.com'
7-
__version__ = '0.14.0'
7+
__version__ = '0.15.0'

riscv_isac/cgf_normalize.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# See LICENSE.incore for details
22
from math import *
3+
import pprint
34
import riscv_isac.utils as utils
45
import itertools
56
import random
@@ -579,6 +580,26 @@ def expand_cgf(cgf_files, xlen,flen):
579580
if len(cgf[labels]['mnemonics'].keys()) > 1:
580581
logger.error(f'Multiple instruction mnemonics found when base_op label defined in {labels} label.')
581582

583+
# Substitute instruction aliases with equivalent tuple of instructions
584+
if 'cross_comb' in cats:
585+
temp = cats['cross_comb']
586+
587+
for covp, covge in dict(temp).items():
588+
data = covp.split('::')
589+
ops = data[0].replace(' ', '')[1:-1].split(':')
590+
# Substitute with tuple of instructions
591+
for i in range(len(ops)):
592+
exp_alias = utils.import_instr_alias(ops[i])
593+
if exp_alias != None:
594+
ops[i] = tuple(exp_alias).__str__().replace("'", '').replace(" ", '')
595+
596+
data[0] = '[' + ':'.join(ops) + ']'
597+
data = '::'.join(data)
598+
del temp[covp]
599+
temp[data] = covge
600+
601+
cgf[labels].insert(1, 'cross_comb', temp)
602+
582603
l = len(cats.items())
583604
i = 0
584605
for label,node in cats.items():

riscv_isac/coverage.py

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050

5151
class cross():
5252

53+
BASE_REG_DICT = { 'x'+str(i) : 'x'+str(i) for i in range(32)}
54+
5355
def __init__(self,label,coverpoint):
5456

5557
self.label = label
@@ -58,24 +60,24 @@ def __init__(self,label,coverpoint):
5860

5961
## Extract relevant information from coverpt
6062
self.data = self.coverpoint.split('::')
61-
self.ops = [i for i in self.data[0][1:-1].split(':')]
62-
self.assign_lst = [i for i in self.data[1][1:-1].split(':')]
63-
self.cond_lst = [i for i in self.data[2][1:-1].split(':')]
63+
self.ops = self.data[0].replace(' ', '')[1:-1].split(':')
64+
self.assign_lst = self.data[1].replace(' ', '')[1:-1].split(':')
65+
self.cond_lst = self.data[2].lstrip().rstrip()[1:-1].split(':')
6466

6567
def process(self, queue, window_size, addr_pairs):
66-
6768
'''
6869
Check whether the coverpoint is a hit or not and update the metric
6970
'''
7071
if(len(self.ops)>window_size or len(self.ops)>len(queue)):
7172
return
7273

7374
for index in range(len(self.ops)):
75+
7476
instr = queue[index]
7577
instr_name = instr.instr_name
7678
if addr_pairs:
7779
if not (any([instr.instr_addr >= saddr and instr.instr_addr < eaddr for saddr,eaddr in addr_pairs])):
78-
continue
80+
break
7981

8082
rd = None
8183
rs1 = None
@@ -92,13 +94,13 @@ def process(self, queue, window_size, addr_pairs):
9294
rm = None
9395

9496
if instr.rd is not None:
95-
rd = int(instr.rd[0])
97+
rd = instr.rd[1] + str(instr.rd[0])
9698
if instr.rs1 is not None:
97-
rs1 = int(instr.rs1[0])
99+
rs1 = instr.rs1[1] + str(instr.rs1[0])
98100
if instr.rs2 is not None:
99-
rs2 = int(instr.rs2[0])
101+
rs2 = instr.rs2[1] + str(instr.rs2[0])
100102
if instr.rs3 is not None:
101-
rs3 = int(instr.rs3[0])
103+
rs3 = instr.rs3[1] + str(instr.rs3[0])
102104
if instr.imm is not None:
103105
imm = int(instr.imm)
104106
if instr.zimm is not None:
@@ -118,19 +120,24 @@ def process(self, queue, window_size, addr_pairs):
118120
if instr.rm is not None:
119121
rm = int(instr.rm)
120122

121-
122-
if(self.ops[index] != '?'):
123-
check_lst = [i for i in self.ops[index][1:-1].split(',')]
123+
if self.ops[index].find('?') == -1:
124+
# Handle instruction tuple
125+
if self.ops[index].find('(') != -1:
126+
check_lst = self.ops[index].replace('(', '').replace(')', '').split(',')
127+
else:
128+
check_lst = [self.ops[index]]
124129
if (instr_name not in check_lst):
125130
break
126-
if (self.cond_lst[index] != '?'):
127-
if(eval(self.cond_lst[index])):
131+
132+
if self.cond_lst[index].find('?') == -1:
133+
if(eval(self.cond_lst[index], locals(), cross.BASE_REG_DICT)):
128134
if(index==len(self.ops)-1):
129135
self.result = self.result + 1
130136
else:
131137
break
132-
if(self.assign_lst[index] != '?'):
133-
exec(self.assign_lst[index])
138+
139+
if self.assign_lst[index].find('?') == -1:
140+
exec(self.assign_lst[index], locals(), cross.BASE_REG_DICT)
134141

135142
def get_metric(self):
136143
return self.result
@@ -610,14 +617,14 @@ def compute_per_line(queue, event, cgf_queue, stats_queue, cgf, xlen, flen, addr
610617
commitvalue = instr.reg_commit
611618

612619
# assign default values to operands
613-
nxf_rs1 = None
614-
nxf_rs2 = None
615-
nxf_rs3 = None
616-
nxf_rd = None
617-
rs1_type = None
618-
rs2_type = None
619-
rs3_type = None
620-
rd_type = None
620+
nxf_rs1 = 0
621+
nxf_rs2 = 0
622+
nxf_rs3 = 0
623+
nxf_rd = 0
624+
rs1_type = 'x'
625+
rs2_type = 'x'
626+
rs3_type = 'x'
627+
rd_type = 'x'
621628

622629
csr_addr = None
623630

@@ -956,7 +963,6 @@ def compute_per_line(queue, event, cgf_queue, stats_queue, cgf, xlen, flen, addr
956963
store_val)
957964
logger.error(_log)
958965
stats.stat4.append(_log + '\n\n')
959-
960966
stats.covpt = []
961967
stats.code_seq = []
962968
stats.ucode_seq = []
@@ -1011,7 +1017,7 @@ def compute(trace_file, test_name, cgf, parser_name, decoder_name, detailed, xle
10111017
cgf = temp
10121018

10131019
# If cgf does not have the covergroup pertaining to the cover-label, throw error
1014-
# and exit
1020+
# and exit
10151021
if not cgf:
10161022
logger.err('Covergroup(s) for ' + str(cov_labels) + ' not found')
10171023
sys.exit(1)
@@ -1067,7 +1073,6 @@ def compute(trace_file, test_name, cgf, parser_name, decoder_name, detailed, xle
10671073

10681074
iterator = iter(parser.__iter__()[0])
10691075

1070-
10711076
# If number of processes to be spawned is more than that available,
10721077
# allot number of processes to be equal to one less than maximum
10731078
available_cores = mp.cpu_count()
@@ -1104,6 +1109,7 @@ def compute(trace_file, test_name, cgf, parser_name, decoder_name, detailed, xle
11041109
)
11051110
)
11061111
)
1112+
11071113
#Start each processes
11081114
for each in process_list:
11091115
each.start()
@@ -1126,6 +1132,8 @@ def compute(trace_file, test_name, cgf, parser_name, decoder_name, detailed, xle
11261132
obj_dict[(label,coverpt)].process(cross_cover_queue, window_size,addr_pairs)
11271133
cross_cover_queue.pop(0)
11281134

1135+
1136+
11291137
# Close all instruction queues
11301138
for each in queue_list:
11311139
each.close()

riscv_isac/data/instr_alias.yaml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# This file holds aliases for groups of instructions
2+
3+
rv32i_arith_reg: &rv32i_arith_reg
4+
- add
5+
- sub
6+
- slt
7+
- sltu
8+
- xor
9+
- or
10+
- and
11+
12+
rv32i_arith_imm: &rv32i_arith_imm
13+
- addi
14+
- slti
15+
- sltiu
16+
- xori
17+
- ori
18+
- andi
19+
20+
rv32i_shift_reg: &rv32i_shift_reg
21+
- sll
22+
- srl
23+
- sra
24+
25+
rv32i_shift_imm: &rv32i_shift_imm
26+
- slli
27+
- srli
28+
- srai
29+
30+
rv32i_arith: &rv32i_arith [*rv32i_arith_reg, *rv32i_arith_imm]
31+
32+
rv32i_shift: &rv32i_shift [*rv32i_shift_reg, *rv32i_shift_imm]
33+
34+
rv64i_arith_reg: &rv64i_arith_reg
35+
- *rv32i_arith_reg
36+
- addw
37+
- subw
38+
39+
rv64i_arith_imm: &rv64i_arith_imm
40+
- *rv32i_arith_imm
41+
- addiw
42+
43+
rv64i_shift_reg: &rv64i_shift_reg
44+
- *rv32i_shift_reg
45+
- sllw
46+
- srlw
47+
- sraw
48+
49+
rv64i_shift_imm: &rv64i_shift_imm
50+
- *rv32i_shift_imm
51+
- slliw
52+
- srliw
53+
54+
rv64i_arith: &rv64i_arith [*rv64i_arith_reg, *rv64i_arith_imm]
55+
56+
rv64i_shift: &rv64i_shift [*rv64i_shift_reg, *rv64i_shift_imm]
57+
58+
rv32i_branch: &rv32i_branch
59+
- beq
60+
- bge
61+
- bgeu
62+
- blt
63+
- bltu
64+
- bne
65+
66+
rv64i_branch: &rv64i_branch [*rv32i_branch]
67+
68+
rv32i_jal: &rv32i_jal
69+
- jal
70+
- jalr
71+
72+
rv64i_jal: &rv64i_jal [*rv32i_jal]
73+
74+
rv32i_load: &rv32i_load
75+
- lw
76+
- lhu
77+
- lh
78+
- lbu
79+
- lb
80+
81+
rv64i_load: &rv364i_load
82+
- *rv32i_load
83+
- ld
84+
- lwu
85+
86+
rv32i_store: &rv32i_store
87+
- sw
88+
- sh
89+
- sb
90+
91+
rv64i_store: &rv64i_store
92+
- *rv32i_store
93+
- sd

riscv_isac/utils.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import os
66
import subprocess
77
import shlex
8+
import riscv_isac
89
from riscv_isac.log import logger
910
import ruamel
1011
from ruamel.yaml import YAML
@@ -388,3 +389,28 @@ def sys_command_file(command, filename):
388389
stdout, stderr = out.communicate()
389390
fp.close()
390391

392+
def import_instr_alias(alias):
393+
'''
394+
Return instructions pertaining to a particular alias
395+
396+
alias: (string) The alias to be imported
397+
398+
'''
399+
400+
# Function to flatten nested lists
401+
from collections import Iterable
402+
def flatten(lis):
403+
for item in lis:
404+
if isinstance(item, Iterable) and not isinstance(item, str):
405+
for x in flatten(item):
406+
yield x
407+
else:
408+
yield item
409+
410+
isac_path = os.path.dirname(riscv_isac.__file__)
411+
alias_dict = load_yaml_file(isac_path + '/data/instr_alias.yaml')
412+
if alias in alias_dict:
413+
return list(flatten(alias_dict[alias]))
414+
else:
415+
return None
416+

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.14.0
2+
current_version = 0.15.0
33
commit = True
44
tag = True
55

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def read_requires():
2626

2727
setup(
2828
name='riscv_isac',
29-
version='0.14.0',
29+
version='0.15.0',
3030
description="RISC-V ISAC",
3131
long_description=readme + '\n\n',
3232
classifiers=[

0 commit comments

Comments
 (0)