Skip to content

Commit 3778166

Browse files
committed
Added riscof tests
1 parent 327f434 commit 3778166

13 files changed

+580
-0
lines changed
Binary file not shown.
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
hart_ids: [0]
2+
hart0:
3+
ISA: RV32IMCZicsr_Zifencei
4+
physical_addr_sz: 32
5+
User_Spec_Version: '2.3'
6+
supported_xlen: [32]
7+
misa:
8+
reset-val: 0x40001104
9+
rv32:
10+
accessible: true
11+
mxl:
12+
implemented: true
13+
type:
14+
warl:
15+
dependency_fields: []
16+
legal:
17+
- mxl[1:0] in [0x1]
18+
wr_illegal:
19+
- Unchanged
20+
extensions:
21+
implemented: true
22+
type:
23+
warl:
24+
dependency_fields: []
25+
legal:
26+
- extensions[25:0] bitmask [0x0001104, 0x0000000]
27+
wr_illegal:
28+
- Unchanged
29+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
mtime:
2+
implemented: true
3+
address: 0xbff8
4+
mtimecmp:
5+
implemented: true
6+
address: 0x4000
7+
nmi:
8+
label: nmi_vector
9+
reset:
10+
label: reset_vector

test/computerraria/env/link.ld

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
OUTPUT_ARCH( "riscv" )
2+
ENTRY(rvtest_entry_point)
3+
4+
SECTIONS
5+
{
6+
. = 0x80000000;
7+
.text.init : { *(.text.init) }
8+
. = ALIGN(0x1000);
9+
.tohost : { *(.tohost) }
10+
. = ALIGN(0x1000);
11+
.text : { *(.text) }
12+
. = ALIGN(0x1000);
13+
.data : { *(.data) }
14+
.data.string : { *(.data.string)}
15+
.bss : { *(.bss) }
16+
_end = .;
17+
}
18+

test/computerraria/env/model_test.h

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#ifndef _COMPLIANCE_MODEL_H
2+
#define _COMPLIANCE_MODEL_H
3+
#define RVMODEL_DATA_SECTION \
4+
.pushsection .tohost,"aw",@progbits; \
5+
.align 8; .global tohost; tohost: .dword 0; \
6+
.align 8; .global fromhost; fromhost: .dword 0; \
7+
.popsection; \
8+
.align 8; .global begin_regstate; begin_regstate: \
9+
.word 128; \
10+
.align 8; .global end_regstate; end_regstate: \
11+
.word 4;
12+
13+
//RV_COMPLIANCE_HALT
14+
#define RVMODEL_HALT \
15+
li x1, 1; \
16+
write_tohost: \
17+
sw x1, tohost, t5; \
18+
j write_tohost;
19+
20+
#define RVMODEL_BOOT
21+
22+
//RV_COMPLIANCE_DATA_BEGIN
23+
#define RVMODEL_DATA_BEGIN \
24+
RVMODEL_DATA_SECTION \
25+
.align 4;\
26+
.global begin_signature; begin_signature:
27+
28+
//RV_COMPLIANCE_DATA_END
29+
#define RVMODEL_DATA_END \
30+
.align 4;\
31+
.global end_signature; end_signature:
32+
33+
//RVTEST_IO_INIT
34+
#define RVMODEL_IO_INIT
35+
//RVTEST_IO_WRITE_STR
36+
#define RVMODEL_IO_WRITE_STR(_R, _STR)
37+
//RVTEST_IO_CHECK
38+
#define RVMODEL_IO_CHECK()
39+
//RVTEST_IO_ASSERT_GPR_EQ
40+
#define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I)
41+
//RVTEST_IO_ASSERT_SFPR_EQ
42+
#define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I)
43+
//RVTEST_IO_ASSERT_DFPR_EQ
44+
#define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I)
45+
46+
#define RVMODEL_SET_MSW_INT \
47+
li t1, 1; \
48+
li t2, 0x2000000; \
49+
sw t1, 0(t2);
50+
51+
#define RVMODEL_CLEAR_MSW_INT \
52+
li t2, 0x2000000; \
53+
sw x0, 0(t2);
54+
55+
#define RVMODEL_CLEAR_MTIMER_INT
56+
57+
#define RVMODEL_CLEAR_MEXT_INT
58+
59+
60+
#endif // _COMPLIANCE_MODEL_H
+250
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
import os
2+
import re
3+
import shutil
4+
import subprocess
5+
import shlex
6+
import logging
7+
import random
8+
import string
9+
from string import Template
10+
import sys
11+
12+
import riscof.utils as utils
13+
import riscof.constants as constants
14+
from riscof.pluginTemplate import pluginTemplate
15+
16+
logger = logging.getLogger()
17+
18+
class computerraria(pluginTemplate):
19+
__model__ = "computerraria"
20+
21+
#TODO: please update the below to indicate family, version, etc of your DUT.
22+
__version__ = "XXX"
23+
24+
def __init__(self, *args, **kwargs):
25+
super().__init__(*args, **kwargs)
26+
27+
config = kwargs.get('config')
28+
29+
# If the config node for this DUT is missing or empty. Raise an error. At minimum we need
30+
# the paths to the ispec and pspec files
31+
if config is None:
32+
print("Please enter input file paths in configuration.")
33+
raise SystemExit(1)
34+
35+
# In case of an RTL based DUT, this would be point to the final binary executable of your
36+
# test-bench produced by a simulator (like verilator, vcs, incisive, etc). In case of an iss or
37+
# emulator, this variable could point to where the iss binary is located. If 'PATH variable
38+
# is missing in the config.ini we can hardcode the alternate here.
39+
self.dut_exe = os.path.join(config['PATH'] if 'PATH' in config else "","computerraria")
40+
41+
# Number of parallel jobs that can be spawned off by RISCOF
42+
# for various actions performed in later functions, specifically to run the tests in
43+
# parallel on the DUT executable. Can also be used in the build function if required.
44+
self.num_jobs = str(config['jobs'] if 'jobs' in config else 1)
45+
46+
# Path to the directory where this python file is located. Collect it from the config.ini
47+
self.pluginpath=os.path.abspath(config['pluginpath'])
48+
49+
# Collect the paths to the riscv-config absed ISA and platform yaml files. One can choose
50+
# to hardcode these here itself instead of picking it from the config.ini file.
51+
self.isa_spec = os.path.abspath(config['ispec'])
52+
self.platform_spec = os.path.abspath(config['pspec'])
53+
54+
#We capture if the user would like the run the tests on the target or
55+
#not. If you are interested in just compiling the tests and not running
56+
#them on the target, then following variable should be set to False
57+
if 'target_run' in config and config['target_run']=='0':
58+
self.target_run = False
59+
else:
60+
self.target_run = True
61+
62+
def initialise(self, suite, work_dir, archtest_env):
63+
64+
# capture the working directory. Any artifacts that the DUT creates should be placed in this
65+
# directory. Other artifacts from the framework and the Reference plugin will also be placed
66+
# here itself.
67+
self.work_dir = work_dir
68+
69+
# capture the architectural test-suite directory.
70+
self.suite_dir = suite
71+
72+
# Note the march is not hardwired here, because it will change for each
73+
# test. Similarly the output elf name and compile macros will be assigned later in the
74+
# runTests function
75+
self.compile_cmd = 'riscv{1}-unknown-elf-gcc -march={0} \
76+
-static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -g\
77+
-T '+self.pluginpath+'/env/link.ld\
78+
-I '+self.pluginpath+'/env/\
79+
-I ' + archtest_env + ' {2} -o {3} {4}'
80+
81+
# add more utility snippets here
82+
83+
def build(self, isa_yaml, platform_yaml):
84+
85+
# load the isa yaml as a dictionary in python.
86+
ispec = utils.load_yaml(isa_yaml)['hart0']
87+
88+
# capture the XLEN value by picking the max value in 'supported_xlen' field of isa yaml. This
89+
# will be useful in setting integer value in the compiler string (if not already hardcoded);
90+
self.xlen = ('64' if 64 in ispec['supported_xlen'] else '32')
91+
92+
# for computerraria start building the '--isa' argument. the self.isa is dutnmae specific and may not be
93+
# useful for all DUTs
94+
self.isa = 'rv' + self.xlen
95+
if "I" in ispec["ISA"]:
96+
self.isa += 'i'
97+
if "M" in ispec["ISA"]:
98+
self.isa += 'm'
99+
if "F" in ispec["ISA"]:
100+
self.isa += 'f'
101+
if "D" in ispec["ISA"]:
102+
self.isa += 'd'
103+
if "C" in ispec["ISA"]:
104+
self.isa += 'c'
105+
106+
#TODO: The following assumes you are using the riscv-gcc toolchain. If
107+
# not please change appropriately
108+
self.compile_cmd = self.compile_cmd+' -mabi='+('lp64 ' if 64 in ispec['supported_xlen'] else 'ilp32 ')
109+
110+
def runTests(self, testList):
111+
112+
# Delete Makefile if it already exists.
113+
if os.path.exists(self.work_dir+ "/Makefile." + self.name[:-1]):
114+
os.remove(self.work_dir+ "/Makefile." + self.name[:-1])
115+
# create an instance the makeUtil class that we will use to create targets.
116+
make = utils.makeUtil(makefilePath=os.path.join(self.work_dir, "Makefile." + self.name[:-1]))
117+
118+
# set the make command that will be used. The num_jobs parameter was set in the __init__
119+
# function earlier
120+
make.makeCommand = 'make -k -j' + self.num_jobs
121+
122+
# we will iterate over each entry in the testList. Each entry node will be refered to by the
123+
# variable testname.
124+
for testname in testList:
125+
126+
# for each testname we get all its fields (as described by the testList format)
127+
testentry = testList[testname]
128+
129+
# we capture the path to the assembly file of this test
130+
test = testentry['test_path']
131+
132+
# capture the directory where the artifacts of this test will be dumped/created. RISCOF is
133+
# going to look into this directory for the signature files
134+
test_dir = testentry['work_dir']
135+
136+
# name of the elf file after compilation of the test
137+
elf = 'my.elf'
138+
139+
# name of the signature file as per requirement of RISCOF. RISCOF expects the signature to
140+
# be named as DUT-<dut-name>.signature. The below variable creates an absolute path of
141+
# signature file.
142+
sig_file = os.path.join(test_dir, self.name[:-1] + ".signature")
143+
144+
# for each test there are specific compile macros that need to be enabled. The macros in
145+
# the testList node only contain the macros/values. For the gcc toolchain we need to
146+
# prefix with "-D". The following does precisely that.
147+
compile_macros= ' -D' + " -D".join(testentry['macros'])
148+
149+
# substitute all variables in the compile command that we created in the initialize
150+
# function
151+
cmd = self.compile_cmd.format(testentry['isa'].lower(), self.xlen, test, elf, compile_macros)
152+
153+
# if the user wants to disable running the tests and only compile the tests, then
154+
# the "else" clause is executed below assigning the sim command to simple no action
155+
# echo statement.
156+
if self.target_run:
157+
# set up the simulation command. Template is for spike. Please change.
158+
simcmd = self.dut_exe + ' --isa={0} +signature={1} +signature-granularity=4 {2}'.format(self.isa, sig_file, elf)
159+
else:
160+
simcmd = 'echo "NO RUN"'
161+
162+
# concatenate all commands that need to be executed within a make-target.
163+
execute = '@cd {0}; {1}; {2};'.format(testentry['work_dir'], cmd, simcmd)
164+
165+
# create a target. The makeutil will create a target with the name "TARGET<num>" where num
166+
# starts from 0 and increments automatically for each new target that is added
167+
make.add_target(execute)
168+
169+
# if you would like to exit the framework once the makefile generation is complete uncomment the
170+
# following line. Note this will prevent any signature checking or report generation.
171+
#raise SystemExit
172+
173+
# once the make-targets are done and the makefile has been created, run all the targets in
174+
# parallel using the make command set above.
175+
make.execute_all(self.work_dir)
176+
177+
# if target runs are not required then we simply exit as this point after running all
178+
# the makefile targets.
179+
if not self.target_run:
180+
raise SystemExit(0)
181+
182+
#The following is an alternate template that can be used instead of the above.
183+
#The following template only uses shell commands to compile and run the tests.
184+
185+
# def runTests(self, testList):
186+
#
187+
# # we will iterate over each entry in the testList. Each entry node will be referred to by the
188+
# # variable testname.
189+
# for testname in testList:
190+
#
191+
# logger.debug('Running Test: {0} on DUT'.format(testname))
192+
# # for each testname we get all its fields (as described by the testList format)
193+
# testentry = testList[testname]
194+
#
195+
# # we capture the path to the assembly file of this test
196+
# test = testentry['test_path']
197+
#
198+
# # capture the directory where the artifacts of this test will be dumped/created.
199+
# test_dir = testentry['work_dir']
200+
#
201+
# # name of the elf file after compilation of the test
202+
# elf = 'my.elf'
203+
#
204+
# # name of the signature file as per requirement of RISCOF. RISCOF expects the signature to
205+
# # be named as DUT-<dut-name>.signature. The below variable creates an absolute path of
206+
# # signature file.
207+
# sig_file = os.path.join(test_dir, self.name[:-1] + ".signature")
208+
#
209+
# # for each test there are specific compile macros that need to be enabled. The macros in
210+
# # the testList node only contain the macros/values. For the gcc toolchain we need to
211+
# # prefix with "-D". The following does precisely that.
212+
# compile_macros= ' -D' + " -D".join(testentry['macros'])
213+
#
214+
# # collect the march string required for the compiler
215+
# marchstr = testentry['isa'].lower()
216+
#
217+
# # substitute all variables in the compile command that we created in the initialize
218+
# # function
219+
# cmd = self.compile_cmd.format(marchstr, self.xlen, test, elf, compile_macros)
220+
#
221+
# # just a simple logger statement that shows up on the terminal
222+
# logger.debug('Compiling test: ' + test)
223+
#
224+
# # the following command spawns a process to run the compile command. Note here, we are
225+
# # changing the directory for this command to that pointed by test_dir. If you would like
226+
# # the artifacts to be dumped else where change the test_dir variable to the path of your
227+
# # choice.
228+
# utils.shellCommand(cmd).run(cwd=test_dir)
229+
#
230+
# # for debug purposes if you would like stop the DUT plugin after compilation, you can
231+
# # comment out the lines below and raise a SystemExit
232+
#
233+
# if self.target_run:
234+
# # build the command for running the elf on the DUT. In this case we use spike and indicate
235+
# # the isa arg that we parsed in the build stage, elf filename and signature filename.
236+
# # Template is for spike. Please change for your DUT
237+
# execute = self.dut_exe + ' --isa={0} +signature={1} +signature-granularity=4 {2}'.format(self.isa, sig_file, elf)
238+
# logger.debug('Executing on Spike ' + execute)
239+
#
240+
# # launch the execute command. Change the test_dir if required.
241+
# utils.shellCommand(execute).run(cwd=test_dir)
242+
#
243+
# # post-processing steps can be added here in the template below
244+
# #postprocess = 'mv {0} temp.sig'.format(sig_file)'
245+
# #utils.shellCommand(postprocess).run(cwd=test_dir)
246+
#
247+
# # if target runs are not required then we simply exit as this point after running all
248+
# # the makefile targets.
249+
# if not self.target_run:
250+
# raise SystemExit

test/config.ini

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[RISCOF]
2+
ReferencePlugin=sail_cSim
3+
ReferencePluginPath=/home/xander/dev/terraria/terraria-computer/test/sail_cSim
4+
DUTPlugin=computerraria
5+
DUTPluginPath=/home/xander/dev/terraria/terraria-computer/test/computerraria
6+
7+
[computerraria]
8+
pluginpath=/home/xander/dev/terraria/terraria-computer/test/computerraria
9+
ispec=/home/xander/dev/terraria/terraria-computer/test/computerraria/computerraria_isa.yaml
10+
pspec=/home/xander/dev/terraria/terraria-computer/test/computerraria/computerraria_platform.yaml
11+
target_run=1
12+
13+
[sail_cSim]
14+
pluginpath=/home/xander/dev/terraria/terraria-computer/test/sail_cSim

test/sail_cSim/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from pkgutil import extend_path
2+
__path__ = extend_path(__path__, __name__)
261 Bytes
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)