66import logging
77import random
88import string
9+ import json
910from string import Template
10- import sys
1111
1212import riscof .utils as utils
13- import riscof .constants as constants
1413from riscof .pluginTemplate import pluginTemplate
14+ import riscof .constants as constants
15+ from riscv_isac .isac import isac
1516
1617logger = logging .getLogger ()
1718
18- class refname (pluginTemplate ):
19- __model__ = "refname"
20-
21- #TODO: please update the below to indicate family, version, etc of your DUT.
22- __version__ = "XXX"
19+ class sail_cSim (pluginTemplate ):
20+ __model__ = "sail_c_simulator"
21+ __version__ = "0.5.0"
2322
2423 def __init__ (self , * args , ** kwargs ):
2524 sclass = super ().__init__ (* args , ** kwargs )
2625
2726 config = kwargs .get ('config' )
28-
29- self .ref_exe = os .path .join (config ['PATH' ] if 'PATH' in config else "" ,"refname" )
27+ if config is None :
28+ logger .error ("Config node for sail_cSim missing." )
29+ raise SystemExit (1 )
3030 self .num_jobs = str (config ['jobs' ] if 'jobs' in config else 1 )
31- self .pluginpath = os .path .abspath (config ['pluginpath' ])
31+ self .pluginpath = os .path .abspath (config ['pluginpath' ])
32+ self .sail_exe = { '32' : os .path .join (config ['PATH' ] if 'PATH' in config else "" ,"riscv_sim_rv32d" ),
33+ '64' : os .path .join (config ['PATH' ] if 'PATH' in config else "" ,"riscv_sim_rv64d" )}
3234 self .isa_spec = os .path .abspath (config ['ispec' ]) if 'ispec' in config else ''
3335 self .platform_spec = os .path .abspath (config ['pspec' ]) if 'ispec' in config else ''
3436 self .make = config ['make' ] if 'make' in config else 'make'
35- logger .debug ("refname plugin initialised using the following configuration." )
37+ logger .debug ("SAIL CSim plugin initialised using the following configuration." )
3638 for entry in config :
3739 logger .debug (entry + ' : ' + config [entry ])
3840 return sclass
3941
4042 def initialise (self , suite , work_dir , archtest_env ):
4143 self .suite = suite
42- if shutil .which (self .ref_exe ) is None :
43- logger .error ('Please install Executable for DUTNAME to proceed further' )
44- raise SystemExit (1 )
4544 self .work_dir = work_dir
46-
47- #TODO: The following assumes you are using the riscv-gcc toolchain. If
48- # not please change appropriately
4945 self .objdump_cmd = 'riscv{1}-unknown-elf-objdump -D {0} > {2};'
5046 self .compile_cmd = 'riscv{1}-unknown-elf-gcc -march={0} \
5147 -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles\
5248 -T '+ self .pluginpath + '/env/link.ld\
5349 -I '+ self .pluginpath + '/env/\
5450 -I ' + archtest_env
5551
56- # set all the necessary variables like compile command, elf2hex
57- # commands, objdump cmds. etc whichever you feel necessary and required
58- # for your plugin.
59-
6052 def build (self , isa_yaml , platform_yaml ):
6153 ispec = utils .load_yaml (isa_yaml )['hart0' ]
6254 self .xlen = ('64' if 64 in ispec ['supported_xlen' ] else '32' )
55+ self .isa_yaml_path = isa_yaml
6356 self .isa = 'rv' + self .xlen
64- #TODO: The following assumes you are using the riscv-gcc toolchain. If
65- # not please change appropriately
6657 self .compile_cmd = self .compile_cmd + ' -mabi=' + ('lp64 ' if 64 in ispec ['supported_xlen' ] else 'ilp32 ' )
6758 if "I" in ispec ["ISA" ]:
6859 self .isa += 'i'
6960 if "M" in ispec ["ISA" ]:
7061 self .isa += 'm'
71- if "C " in ispec ["ISA" ]:
72- self .isa += 'c '
62+ if "A " in ispec ["ISA" ]:
63+ self .isa += 'a '
7364 if "F" in ispec ["ISA" ]:
7465 self .isa += 'f'
7566 if "D" in ispec ["ISA" ]:
7667 self .isa += 'd'
68+ if "C" in ispec ["ISA" ]:
69+ self .isa += 'c'
70+ objdump = "riscv{0}-unknown-elf-objdump" .format (self .xlen )
71+ if shutil .which (objdump ) is None :
72+ logger .error (objdump + ": executable not found. Please check environment setup." )
73+ raise SystemExit (1 )
74+ compiler = "riscv{0}-unknown-elf-gcc" .format (self .xlen )
75+ if shutil .which (compiler ) is None :
76+ logger .error (compiler + ": executable not found. Please check environment setup." )
77+ raise SystemExit (1 )
78+ if shutil .which (self .sail_exe [self .xlen ]) is None :
79+ logger .error (self .sail_exe [self .xlen ]+ ": executable not found. Please check environment setup." )
80+ raise SystemExit (1 )
81+ if shutil .which (self .make ) is None :
82+ logger .error (self .make + ": executable not found. Please check environment setup." )
83+ raise SystemExit (1 )
7784
78- # based on the validated isa and platform configure your simulator or
79- # build your RTL here
80-
81- def runTests (self , testList , cgf_file = None ):
85+ def runTests (self , testList , cgf_file = None , header_file = None ):
8286 if os .path .exists (self .work_dir + "/Makefile." + self .name [:- 1 ]):
8387 os .remove (self .work_dir + "/Makefile." + self .name [:- 1 ])
8488 make = utils .makeUtil (makefilePath = os .path .join (self .work_dir , "Makefile." + self .name [:- 1 ]))
@@ -94,36 +98,75 @@ def runTests(self, testList, cgf_file=None):
9498 execute = "@cd " + testentry ['work_dir' ]+ ";"
9599
96100 cmd = self .compile_cmd .format (testentry ['isa' ].lower (), self .xlen ) + ' ' + test + ' -o ' + elf
97-
98- #TODO: we are using -D to enable compile time macros. If your
99- # toolchain is not riscv-gcc you may want to change the below code
100101 compile_cmd = cmd + ' -D' + " -D" .join (testentry ['macros' ])
101102 execute += compile_cmd + ";"
102103
103104 execute += self .objdump_cmd .format (elf , self .xlen , 'ref.disass' )
104105 sig_file = os .path .join (test_dir , self .name [:- 1 ] + ".signature" )
105106
106- #TODO: You will need to add any other arguments to your DUT
107- # executable if any in the quotes below
108- execute += self .ref_exe + ''
109-
110- #TODO: The following is useful only if your reference model can
111- # support coverage extraction from riscv-isac. Else leave it
112- # commented out
113-
114- #cov_str = ' '
115- #for label in testentry['coverage_labels']:
116- # cov_str+=' -l '+label
117- #if cgf_file is not None:
118- # coverage_cmd = 'riscv_isac --verbose info coverage -d \
119- # -t {0}.log --parser-name c_sail -o coverage.rpt \
120- # --sig-label begin_signature end_signature \
121- # --test-label rvtest_code_begin rvtest_code_end \
122- # -e {0}.elf -c {1} -x{2} {3};'.format(\
123- # test_name, ' -c '.join(cgf_file), self.xlen, cov_str)
124- #else:
125- # coverage_cmd = ''
126- #execute+=coverage_cmd
107+ isa_yaml = utils .load_yaml (self .isa_yaml_path )
108+ # Verify the availability of PMP:
109+ if "PMP" in isa_yaml ['hart0' ]:
110+ pmp_flags = {}
111+ if isa_yaml ['hart0' ]["PMP" ]["implemented" ] == True :
112+ if "pmp-grain" in isa_yaml ['hart0' ]["PMP" ]:
113+ pmp_flags ["pmp-grain" ] = isa_yaml ['hart0' ]["PMP" ]["pmp-grain" ]
114+ else :
115+ logger .error ("PMP grain not defined" )
116+ pmp_flags = ""
117+ if "pmp-count" in isa_yaml ['hart0' ]["PMP" ]:
118+ pmp_flags ["pmp-count" ] = isa_yaml ['hart0' ]["PMP" ]["pmp-count" ]
119+ else :
120+ logger .error ("PMP count not defined" )
121+ pmp_flags = ""
122+ else :
123+ pmp_flags = ""
124+
125+ try :
126+ sail_config = subprocess .run (["riscv_sim_rv64d" , "--print-default-config" ], check = True , text = True , capture_output = True )
127+ sail_config = json .loads (sail_config .stdout )
128+ except subprocess .CalledProcessError as e :
129+ print ("riscv_sim_rv64d --print-default-config failed:" , e .stderr )
130+ exit (1 )
131+ except json .JSONDecodeError :
132+ print ("riscv_sim_rv64d --print-default-config output is not valid JSON." )
133+ exit (1 )
134+
135+ sail_config ["memory" ]["pmp" ]["grain" ] = pmp_flags ["pmp-grain" ]
136+ sail_config ["memory" ]["pmp" ]["count" ] = pmp_flags ["pmp-count" ]
137+
138+ #For User-configuration: Replace this variable with your configuration. "/home/riscv-arch-test/custom_sail_config.json"
139+ sail_config_path = os .path .join (self .pluginpath , 'env' , 'sail_config.json' )
140+
141+ # Write the updated configuration back to the file
142+ with open (sail_config_path , 'w' , encoding = 'utf-8' ) as file :
143+ json .dump (sail_config , file , indent = 4 )
144+
145+ execute += self .sail_exe [self .xlen ] + ' --config={0} -v --trace=step --signature-granularity=8 --test-signature={1} {2} > {3}.log 2>&1;' .format (sail_config_path , sig_file , elf , test_name )
146+
147+ cov_str = ' '
148+ for label in testentry ['coverage_labels' ]:
149+ cov_str += ' -l ' + label
150+
151+ cgf_mac = ' '
152+ header_file_flag = ' '
153+ if header_file is not None :
154+ header_file_flag = f' -h { header_file } '
155+ cgf_mac += ' -cm common '
156+ for macro in testentry ['mac' ]:
157+ cgf_mac += ' -cm ' + macro
158+
159+ if cgf_file is not None :
160+ coverage_cmd = 'riscv_isac --verbose info coverage -d \
161+ -t {0}.log --parser-name c_sail -o coverage.rpt \
162+ --sig-label begin_signature end_signature \
163+ -e ref.elf -c {1} -x{2} {3} {4} {5};' .format (\
164+ test_name , ' -c ' .join (cgf_file ), self .xlen , cov_str , header_file_flag , cgf_mac )
165+ else :
166+ coverage_cmd = ''
167+
168+
169+ execute += coverage_cmd
127170
128171 make .add_target (execute )
129172 make .execute_all (self .work_dir )
0 commit comments