Skip to content

Commit 9e778d0

Browse files
authored
Merge pull request #80 from riscv-software-src/isa-validation-api
new isa-validation api
2 parents 314abce + c36d6ec commit 9e778d0

File tree

8 files changed

+113
-59
lines changed

8 files changed

+113
-59
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ __pycache__/*
1111

1212
riscv_config_work/*
1313
.python-version
14+
15+
riscv_config.egg-info/

CHANGELOG.md

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

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

5+
## [2.15.0] - 2022-06-16
6+
7+
- moved ISA validation as a separate api function to enable import in other python tools
8+
59
## [2.14.1] - 2022-06-02
610

711
- add support for Zicbo* extensions

riscv_config/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from pkgutil import extend_path
22
__path__ = extend_path(__path__, __name__)
3-
__version__ = '2.14.1'
3+
__version__ = '2.15.0'

riscv_config/constants.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import os
2+
import re
23

34
root = os.path.abspath(os.path.dirname(__file__))
45

56
isa_schema = os.path.join(root, 'schemas/schema_isa.yaml')
67
debug_schema = os.path.join(root, 'schemas/schema_debug.yaml')
78
platform_schema = os.path.join(root, 'schemas/schema_platform.yaml')
8-
9+
isa_regex = re.compile("^RV(32|64|128)[IE]+[ABCDEFGHJKLMNPQSTUVX]*(Zicbom|Zicbop|Zicboz|Zicsr|Zifencei|Zihintpause|Zam|Ztso|Zkne|Zknd|Zknh|Zkse|Zksh|Zkg|Zkb|Zkr|Zks|Zkn|Zba|Zbc|Zbb|Zbp|Zbr|Zbm|Zbs|Zbe|Zbf|Zbt|Zmmul|Svnapot){,1}(_Zicbom){,1}(_Zicbop){,1}(_Zicboz){,1}(_Zicsr){,1}(_Zifencei){,1}(_Zihintpause){,1}(_Zmmul){,1}(_Zam){,1}(_Zba){,1}(_Zbb){,1}(_Zbc){,1}(_Zbe){,1}(_Zbf){,1}(_Zbm){,1}(_Zbp){,1}(_Zbr){,1}(_Zbs){,1}(_Zbt){,1}(_Zkb){,1}(_Zkg){,1}(_Zkr){,1}(_Zks){,1}(_Zkn){,1}(_Zknd){,1}(_Zkne){,1}(_Zknh){,1}(_Zkse){,1}(_Zksh){,1}(_Ztso){,1}(_Svnapot){,1}$")

riscv_config/isa_validator.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import riscv_config.constants as constants
2+
import re
3+
4+
def get_extension_list(isa):
5+
extension_list = []
6+
err = False
7+
err_list = []
8+
if not constants.isa_regex.match(isa):
9+
err = True
10+
err_list.append('Input ISA string does not match accepted canonical ordering')
11+
return (extension_list, err, err_list)
12+
13+
14+
str_match = re.findall('(?P<stdisa>[^\d]*?)(?!_)*(?P<zext>Z.*?)*(?P<sext>S[a-z]*)*(_|$)',isa)
15+
extension_list= []
16+
standard_isa = ''
17+
zext_list = []
18+
for match in str_match:
19+
stdisa, zext, sext, ignore = match
20+
if stdisa != '':
21+
for e in stdisa:
22+
extension_list.append(e)
23+
standard_isa = stdisa
24+
if zext != '':
25+
extension_list.append(zext)
26+
zext_list.append(zext)
27+
if sext != '':
28+
extension_list.append(sext)
29+
# check ordering of ISA
30+
canonical_ordering = 'IEMAFDQLCBJKTPVNSHU'
31+
order_index = {c: i for i, c in enumerate(canonical_ordering)}
32+
for i in range(len(standard_isa)-1):
33+
a1 = standard_isa[i]
34+
a2 = standard_isa[i+1]
35+
36+
if order_index[a1] > order_index[a2]:
37+
err = True
38+
err_list.append( "Alphabet '" + a1 + "' should occur after '" + a2)
39+
40+
# check canonical ordering within Zextensions
41+
for i in range(len(zext_list)-1):
42+
a1 = zext_list[i][1].upper()
43+
a2 = zext_list[i+1][1].upper()
44+
a3 = zext_list[i][2]
45+
a4 = zext_list[i+1][2]
46+
if order_index[a1] > order_index[a2]:
47+
err = True
48+
err_list.append( f"Z extension {zext_list[i]} must occur after {zext_list[i+1]}")
49+
elif a1 == a2 and a3 > a4:
50+
err = True
51+
err_list.append( f"Within the Z{a1.lower()} category extension {zext_list[i]} must occur after {zext_list[i+1]}")
52+
53+
if 'I' not in extension_list and 'E' not in extension_list:
54+
err_list.append( 'Either of I or E base extensions need to be present in the ISA string')
55+
err = True
56+
if 'F' in extension_list and not "Zicsr" in extension_list:
57+
err_list.append( "F cannot exist without Zicsr.")
58+
err = True
59+
if 'D' in extension_list and not 'F' in extension_list:
60+
err_list.append( "D cannot exist without F.")
61+
err = True
62+
if 'Q' in extension_list and not 'D' in extension_list:
63+
err_list.append( "Q cannot exist without D and F.")
64+
err = True
65+
if 'Zam' in extension_list and not 'A' in extension_list:
66+
err_list.append( "Zam cannot exist without A.")
67+
err = True
68+
if 'N' in extension_list and not 'U' in extension_list:
69+
err_list.append( "N cannot exist without U.")
70+
err = True
71+
if 'S' in extension_list and not 'U' in extension_list:
72+
err_list.append( "S cannot exist without U.")
73+
err = True
74+
if 'Zkg' in extension_list and 'Zbc' in extension_list:
75+
err_list.append( "Zkg being a proper subset of Zbc (from B extension) should be ommitted from the ISA string")
76+
err = True
77+
if 'Zkb' in extension_list and 'Zbp' in extension_list :
78+
err_list.append( "Zkb being a proper subset of Zbp (from B extension) should be ommitted from the ISA string")
79+
err = True
80+
if 'Zks' in extension_list and ( set(['Zkse', 'Zksh','Zkg','Zkb']) & set(extension_list) ):
81+
err_list.append( "Zks is a superset of Zkse, Zksh, Zkg and Zkb. In presence of Zks the subsets must be ignored in the ISA string.")
82+
err = True
83+
if 'Zkn' in extension_list and ( set(['Zkne','Zknd','Zknh','Zkg','Zkb']) & set(extension_list) ):
84+
err_list.append( "Zkn is a superset of Zkne, Zknd, Zknh, Zkg and Zkb, In presence of Zkn the subsets must be ignored in the ISA string")
85+
err = True
86+
if 'K' in extension_list and ( set(['Zkn','Zkr','Zkne','Zknd','Zknh','Zkg','Zkb']) & set(extension_list) ) :
87+
err_list.append( "K is a superset of Zkn and Zkr , In presence of K the subsets must be ignored in the ISA string")
88+
err = True
89+
return (extension_list, err, err_list)
90+
91+
92+

riscv_config/schemaValidator.py

Lines changed: 10 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from cerberus import Validator
22
from riscv_config.warl import warl_interpreter
33
import riscv_config.constants as constants
4+
from riscv_config.isa_validator import *
45
import re
5-
import os
66

77

88
class schemaValidator(Validator):
@@ -74,58 +74,15 @@ def _check_with_capture_isa_specifics(self, field, value):
7474
ext = value[5:]
7575
else:
7676
self._error(field, "Invalid width in ISA.")
77-
#ISA checks
78-
str_match = re.findall('(?P<stdisa>[^\d]*?)(?!_)*(?P<zext>Z.*?)*(?P<sext>S[a-z]*)*(_|$)',value)
79-
extension_list= []
80-
standard_isa = ''
81-
for match in str_match:
82-
stdisa, zext, sext, ignore = match
83-
if stdisa != '':
84-
for e in stdisa:
85-
extension_list.append(e)
86-
standard_isa = stdisa
87-
if zext != '':
88-
extension_list.append(zext)
89-
if sext != '':
90-
extension_list.append(sext)
91-
# check ordering of ISA
92-
canonical_ordering = 'IEMAFDQLCBJKTPVNSHU'
93-
order_index = {c: i for i, c in enumerate(canonical_ordering)}
94-
for i in range(len(standard_isa)-1):
95-
a1 = standard_isa[i]
96-
a2 = standard_isa[i+1]
97-
98-
if order_index[a1] > order_index[a2]:
99-
self._error(field, "Alphabet '" + a1 + "' should occur after '" + a2)
100-
101-
if 'I' not in extension_list and 'E' not in extension_list:
102-
self._error(field, 'Either of I or E base extensions need to be present in the ISA string')
103-
if 'F' in extension_list and not "Zicsr" in extension_list:
104-
self._error(field, "F cannot exist without Zicsr.")
105-
if 'D' in extension_list and not 'F' in extension_list:
106-
self._error(field, "D cannot exist without F.")
107-
if 'Q' in extension_list and not 'D' in extension_list:
108-
self._error(field, "Q cannot exist without D and F.")
109-
if 'Zam' in extension_list and not 'A' in extension_list:
110-
self._error(field, "Zam cannot exist without A.")
111-
if 'N' in extension_list and not 'U' in extension_list:
112-
self._error(field, "N cannot exist without U.")
113-
if 'S' in extension_list and not 'U' in extension_list:
114-
self._error(field, "S cannot exist without U.")
115-
if 'Zkg' in extension_list and 'Zbc' in extension_list:
116-
self._error(field, "Zkg being a proper subset of Zbc (from B extension) should be ommitted from the ISA string")
117-
if 'Zkb' in extension_list and 'Zbp' in extension_list :
118-
self._error(field, "Zkb being a proper subset of Zbp (from B extension) should be ommitted from the ISA string")
119-
if 'Zks' in extension_list and ( set(['Zkse', 'Zksh','Zkg','Zkb']) & set(extension_list) ):
120-
self._error(field, "Zks is a superset of Zkse, Zksh, Zkg and Zkb. In presence of Zks the subsets must be ignored in the ISA string.")
121-
if 'Zkn' in extension_list and ( set(['Zkne','Zknd','Zknh','Zkg','Zkb']) & set(extension_list) ):
122-
self._error(field, "Zkn is a superset of Zkne, Zknd, Zknh, Zkg and Zkb, In presence of Zkn the subsets must be ignored in the ISA string")
123-
if 'K' in extension_list and ( set(['Zkn','Zkr','Zkne','Zknd','Zknh','Zkg','Zkb']) & set(extension_list) ) :
124-
self._error(field, "K is a superset of Zkn and Zkr , In presence of K the subsets must be ignored in the ISA string")
125-
126-
# if 'Z' in value and not self.document['User_Spec_Version'] == "2.3":
127-
# self._error(
128-
# field, "Z is not supported in the User Spec given version.")
77+
78+
if not constants.isa_regex.match(value):
79+
self._error(field, 'Input ISA string does not match regex')
80+
81+
(extension_list, err, err_list) = get_extension_list(value)
82+
if err:
83+
for e in err_list:
84+
self._error(field, e)
85+
12986
#ISA encoding for future use.
13087
for x in "ABCDEFHIJKLMNPQSTUVX":
13188
if (x in ext):

riscv_config/schemas/schema_isa.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ hart_schema:
5656
# - Certain extensions are only valid in certain user-spec version. For, eg. Zifencei is available only in user-spec 2.3 and above.
5757
# - The ISA string must be specified as per the convention mentioned in the specifications(like subsequent Z extensions must be separated with an '_')
5858

59-
ISA: { type: string, required: true, check_with: capture_isa_specifics,
60-
regex: "^RV(32|64|128)[IE]+[ABCDEFGHJKLMNPQSTUVX]*(Zicbom|Zicbop|Zicboz|Zicsr|Zifencei|Zihintpause|Zam|Ztso|Zkne|Zknd|Zknh|Zkse|Zksh|Zkg|Zkb|Zkr|Zks|Zkn|Zba|Zbc|Zbb|Zbp|Zbr|Zbm|Zbs|Zbe|Zbf|Zbt|Zmmul|Svnapot){,1}(_Zicbom){,1}(_Zicbop){,1}(_Zicboz){,1}(_Zicsr){,1}(_Zifencei){,1}(_Zihintpause){,1}(_Zmmul){,1}(_Zam){,1}(_Zba){,1}(_Zbb){,1}(_Zbc){,1}(_Zbe){,1}(_Zbf){,1}(_Zbm){,1}(_Zbp){,1}(_Zbr){,1}(_Zbs){,1}(_Zbt){,1}(_Zkb){,1}(_Zkg){,1}(_Zkr){,1}(_Zks){,1}(_Zkn){,1}(_Zknd){,1}(_Zkne){,1}(_Zknh){,1}(_Zkse){,1}(_Zksh){,1}(_Ztso){,1}(_Svnapot){,1}$" }
59+
ISA: { type: string, required: true, check_with: capture_isa_specifics}
6160

6261
###
6362
#User_Spec_Version

setup.cfg

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

@@ -14,4 +14,3 @@ universal = 1
1414
exclude = docs
1515

1616
[aliases]
17-

0 commit comments

Comments
 (0)