diff --git a/verif/.gitignore b/verif/.gitignore new file mode 100644 index 0000000..7ff52af --- /dev/null +++ b/verif/.gitignore @@ -0,0 +1,2 @@ +*/__* +riscof_work \ No newline at end of file diff --git a/verif/config.ini b/verif/config.ini new file mode 100644 index 0000000..dfa5746 --- /dev/null +++ b/verif/config.ini @@ -0,0 +1,14 @@ +[RISCOF] +ReferencePlugin=sail_cSim +ReferencePluginPath=./plugin-sail_cSim +DUTPlugin=serv +DUTPluginPath=./plugin-serv + +[serv] +pluginpath=./plugin-serv +ispec=./plugin-serv/serv_isa.yaml +pspec=./plugin-serv/serv_platform.yaml +target_run=1 + +[sail_cSim] +pluginpath=./plugin-sail_cSim diff --git a/verif/makehex.py b/verif/makehex.py new file mode 100644 index 0000000..c8f1820 --- /dev/null +++ b/verif/makehex.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. + +import sys + +with open(sys.argv[1], "rb") as f: + cnt = 3 + s = ["00"]*4 + while True: + data = f.read(1) + if not data: + print(''.join(s)) + exit(0) + s[cnt] = "{:02X}".format(data[0]) + if cnt == 0: + print(''.join(s)) + s = ["00"]*4 + cnt = 4 + cnt -= 1 \ No newline at end of file diff --git a/verif/plugin-sail_cSim/env/link.ld b/verif/plugin-sail_cSim/env/link.ld new file mode 100644 index 0000000..8ad95e0 --- /dev/null +++ b/verif/plugin-sail_cSim/env/link.ld @@ -0,0 +1,18 @@ +OUTPUT_ARCH( "riscv" ) +ENTRY(rvtest_entry_point) + +SECTIONS +{ + . = 0x80000000; + .text.init : { *(.text.init) } + . = ALIGN(0x1000); + .tohost : { *(.tohost) } + . = ALIGN(0x1000); + .text : { *(.text) } + . = ALIGN(0x1000); + .data : { *(.data) } + .data.string : { *(.data.string)} + .bss : { *(.bss) } + _end = .; +} + diff --git a/verif/plugin-sail_cSim/env/model_test.h b/verif/plugin-sail_cSim/env/model_test.h new file mode 100644 index 0000000..3c86dd5 --- /dev/null +++ b/verif/plugin-sail_cSim/env/model_test.h @@ -0,0 +1,55 @@ +#ifndef _COMPLIANCE_MODEL_H +#define _COMPLIANCE_MODEL_H + +#define RVMODEL_DATA_SECTION \ + .pushsection .tohost,"aw",@progbits; \ + .align 8; .global tohost; tohost: .dword 0; \ + .align 8; .global fromhost; fromhost: .dword 0; \ + .popsection; \ + .align 8; .global begin_regstate; begin_regstate: \ + .word 128; \ + .align 8; .global end_regstate; end_regstate: \ + .word 4; + +//RV_COMPLIANCE_HALT +#define RVMODEL_HALT \ + li x1, 1; \ + write_tohost: \ + sw x1, tohost, t5; \ + j write_tohost; + +#define RVMODEL_BOOT + +//RV_COMPLIANCE_DATA_BEGIN +#define RVMODEL_DATA_BEGIN \ + RVMODEL_DATA_SECTION \ + .align 4;\ + .global begin_signature; begin_signature: + +//RV_COMPLIANCE_DATA_END +#define RVMODEL_DATA_END \ + .align 4; .global end_signature; end_signature: + +//RVTEST_IO_INIT +#define RVMODEL_IO_INIT +//RVTEST_IO_WRITE_STR +#define RVMODEL_IO_WRITE_STR(_R, _STR) +//RVTEST_IO_CHECK +#define RVMODEL_IO_CHECK() +//RVTEST_IO_ASSERT_GPR_EQ +#define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I) +//RVTEST_IO_ASSERT_SFPR_EQ +#define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I) +//RVTEST_IO_ASSERT_DFPR_EQ +#define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I) + +#define RVMODEL_SET_MSW_INT + +#define RVMODEL_CLEAR_MSW_INT + +#define RVMODEL_CLEAR_MTIMER_INT + +#define RVMODEL_CLEAR_MEXT_INT + + +#endif // _COMPLIANCE_MODEL_H diff --git a/verif/plugin-sail_cSim/riscof_sail_cSim.py b/verif/plugin-sail_cSim/riscof_sail_cSim.py new file mode 100644 index 0000000..4b2c1f0 --- /dev/null +++ b/verif/plugin-sail_cSim/riscof_sail_cSim.py @@ -0,0 +1,108 @@ +import os +import shutil +import logging + +import riscof.utils as utils +from riscof.pluginTemplate import pluginTemplate + +logger = logging.getLogger() + +class sail_cSim(pluginTemplate): + __model__ = "sail_c_simulator" + __version__ = "0.5.0" + + def __init__(self, *args, **kwargs): + sclass = super().__init__(*args, **kwargs) + config = kwargs.get('config') + if config is None: + logger.error("Config node for sail_cSim missing.") + raise SystemExit(1) + self.num_jobs = str(config['jobs'] if 'jobs' in config else 1) + self.pluginpath = os.path.abspath(config['pluginpath']) + self.sail_exe = { '32' : os.path.join(config['PATH'] if 'PATH' in config else "","riscv_sim_RV32"), + '64' : os.path.join(config['PATH'] if 'PATH' in config else "","riscv_sim_RV64")} + self.isa_spec = os.path.abspath(config['ispec']) if 'ispec' in config else '' + self.platform_spec = os.path.abspath(config['pspec']) if 'ispec' in config else '' + self.make = config['make'] if 'make' in config else 'make' + logger.debug("SAIL CSim plugin initialised using the following configuration.") + for entry in config: + logger.debug(entry+' : '+config[entry]) + return sclass + + def initialise(self, suite, work_dir, archtest_env): + self.suite = suite + self.work_dir = work_dir + self.objdump_cmd = 'riscv64-unknown-elf-objdump -D {0} > {1}.disass;' + self.compile_cmd = 'riscv64-unknown-elf-gcc -march={0} \ + -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles\ + -T '+self.pluginpath+'/env/link.ld\ + -I '+self.pluginpath+'/env/\ + -I ' + archtest_env + + def build(self, isa_yaml, platform_yaml): + ispec = utils.load_yaml(isa_yaml)['hart0'] + self.xlen = ('64' if 64 in ispec['supported_xlen'] else '32') + self.isa = 'rv' + self.xlen + self.compile_cmd = self.compile_cmd+' -mabi='+('lp64 ' if 64 in ispec['supported_xlen'] else 'ilp32 ') + if "I" in ispec["ISA"]: + self.isa += 'i' + if "M" in ispec["ISA"]: + self.isa += 'm' + if "C" in ispec["ISA"]: + self.isa += 'c' + if "F" in ispec["ISA"]: + self.isa += 'f' + if "D" in ispec["ISA"]: + self.isa += 'd' + objdump = "riscv64-unknown-elf-objdump".format(self.xlen) + if shutil.which(objdump) is None: + logger.error(objdump+": executable not found. Please check environment setup.") + raise SystemExit(1) + compiler = "riscv64-unknown-elf-gcc".format(self.xlen) + if shutil.which(compiler) is None: + logger.error(compiler+": executable not found. Please check environment setup.") + raise SystemExit(1) + if shutil.which(self.sail_exe[self.xlen]) is None: + logger.error(self.sail_exe[self.xlen]+ ": executable not found. Please check environment setup.") + raise SystemExit(1) + if shutil.which(self.make) is None: + logger.error(self.make+": executable not found. Please check environment setup.") + raise SystemExit(1) + + def runTests(self, testList, cgf_file=None): + if os.path.exists(self.work_dir+ "/Makefile." + self.name[:-1]): + os.remove(self.work_dir+ "/Makefile." + self.name[:-1]) + make = utils.makeUtil(makefilePath=os.path.join(self.work_dir, "Makefile." + self.name[:-1])) + make.makeCommand = self.make + ' -j' + self.num_jobs + for file in testList: + testentry = testList[file] + test = testentry['test_path'] + test_dir = testentry['work_dir'] + file_name = 'sail-{0}'.format(test.rsplit('/',1)[1][:-2]) + elf = '{0}.elf'.format(file_name) + + execute = "@cd "+testentry['work_dir']+";" + cmd = self.compile_cmd.format(testentry['isa'].lower()) + ' ' + test + ' -o ' + elf + compile_cmd = cmd + ' -D' + " -D".join(testentry['macros']) + execute+=compile_cmd+";" + execute += self.objdump_cmd.format(elf, file_name) + sig_file = os.path.join(test_dir, self.name[:-1] + ".signature") + execute += self.sail_exe[self.xlen] + ' --test-signature={0} {1} > {2}.log 2>&1;'.format(sig_file, elf, file_name) + + cov_str = ' ' + for label in testentry['coverage_labels']: + cov_str+=' -l '+label + + if cgf_file is not None: + coverage_cmd = 'riscv_isac --verbose info coverage -d \ + -t {0}.log --parser-name c_sail -o coverage.rpt \ + --sig-label begin_signature end_signature \ + --test-label rvtest_code_begin rvtest_code_end \ + -e ref.elf -c {1} -x{2} {3};'.format(\ + file_name, ' -c '.join(cgf_file), self.xlen, cov_str) + else: + coverage_cmd = '' + execute+=coverage_cmd + + make.add_target(execute) + make.execute_all(self.work_dir) \ No newline at end of file diff --git a/verif/plugin-serv/env/link.ld b/verif/plugin-serv/env/link.ld new file mode 100644 index 0000000..db7be33 --- /dev/null +++ b/verif/plugin-serv/env/link.ld @@ -0,0 +1,18 @@ +OUTPUT_ARCH( "riscv" ) +ENTRY(_start) + +SECTIONS +{ + . = 0x00000000; + .text.init : { *(.text.init) } + . = ALIGN(0x1000); + .tohost : { *(.tohost) } + . = ALIGN(0x1000); + .text : { *(.text) } + . = ALIGN(0x1000); + .data : { *(.data) } + .data.string : { *(.data.string)} + .bss : { *(.bss) } + _end = .; +} + diff --git a/verif/plugin-serv/env/model_test.h b/verif/plugin-serv/env/model_test.h new file mode 100644 index 0000000..2b74203 --- /dev/null +++ b/verif/plugin-serv/env/model_test.h @@ -0,0 +1,71 @@ +#ifndef _COMPLIANCE_MODEL_H +#define _COMPLIANCE_MODEL_H + +#define RVMODEL_HALT \ + la a0, begin_signature; \ + la a1, end_signature; \ + li a2, 0x80000000; \ + complience_halt_loop: \ + beq a0, a1, complience_halt_break; \ + addi a3, a0, 4; \ + complience_halt_loop2: \ + addi a3, a3, -1; \ + \ + lb a4, 0 (a3); \ + srai a5, a4, 4; \ + andi a5, a5, 0xF; \ + li a6, 10; \ + blt a5, a6, notLetter; \ + addi a5, a5, 39; \ + notLetter: \ + addi a5, a5, 0x30; \ + sw a5, 0 (a2); \ + \ + srai a5, a4, 0; \ + andi a5, a5, 0xF; \ + li a6, 10; \ + blt a5, a6, notLetter2; \ + addi a5, a5, 39; \ + notLetter2: \ + addi a5, a5, 0x30; \ + sw a5, 0 (a2); \ + bne a0, a3,complience_halt_loop2; \ + addi a0, a0, 4; \ + \ + li a4, '\n'; \ + sw a4, 0 (a2); \ + j complience_halt_loop; \ + j complience_halt_break; \ + complience_halt_break:; \ + lui a0,0x90000000>>12; \ + sw a3,0(a0); + + +#define RVMODEL_DATA_BEGIN \ + .align 4; .global begin_signature; begin_signature: \ + +#define RVMODEL_DATA_END \ + .align 4; .global end_signature; end_signature: \ + + +#define RVMODEL_BOOT \ +.section .text.init; \ + .align 4; \ + .globl _start; \ +_start: + + +#define LOCAL_IO_WRITE_STR(_STR) RVMODEL_IO_WRITE_STR(x31, _STR) +#define RVMODEL_IO_WRITE_STR(_SP, _STR) +#define LOCAL_IO_PUSH(_SP) +#define LOCAL_IO_POP(_SP) +#define RVMODEL_IO_ASSERT_GPR_EQ(_SP, _R, _I) +#define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I) +#define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I) + +#define RVMODEL_SET_MSW_INT +#define RVMODEL_CLEAR_MSW_INT +#define RVMODEL_CLEAR_MTIMER_INT +#define RVMODEL_CLEAR_MEXT_INT + +#endif // _COMPLIANCE_MODEL_H \ No newline at end of file diff --git a/verif/plugin-serv/riscof_serv.py b/verif/plugin-serv/riscof_serv.py new file mode 100644 index 0000000..cfb7965 --- /dev/null +++ b/verif/plugin-serv/riscof_serv.py @@ -0,0 +1,92 @@ +import os +import logging + +import riscof.utils as utils +from riscof.pluginTemplate import pluginTemplate + +logger = logging.getLogger() + +class serv(pluginTemplate): + __model__ = "serv" + __version__ = "1.2.0" + + def __init__(self, *args, **kwargs): + sclass = super().__init__(*args, **kwargs) + config = kwargs.get('config') + if config is None: + print("Please enter input file paths in configuration.") + raise SystemExit(1) + self.dut_exe = os.path.join(config['PATH'] if 'PATH' in config else "","serv") + self.num_jobs = str(config['jobs'] if 'jobs' in config else 1) + self.pluginpath=os.path.abspath(config['pluginpath']) + self.isa_spec = os.path.abspath(config['ispec']) + self.platform_spec = os.path.abspath(config['pspec']) + if 'target_run' in config and config['target_run']=='0': + self.target_run = False + else: + self.target_run = True + return sclass + + def initialise(self, suite, work_dir, archtest_env): + self.work_dir = work_dir + self.suite_dir = suite + self.compile_cmd = 'riscv64-unknown-elf-gcc -march={0} \ + -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -g\ + -T '+self.pluginpath+'/env/link.ld\ + -I '+self.pluginpath+'/env/\ + -I ' + archtest_env + ' {1} -o {2} {3}' + self.objcopy_cmd = 'riscv64-unknown-elf-objcopy -O binary {0} {1}.bin' + self.objdump_cmd = 'riscv64-unknown-elf-objdump -D {0} > {1}.disass' + self.hexgen_cmd = 'python3 makehex.py {0}/{1}.bin > {0}/{1}.hex' + + build_serv = 'cd $WORKSPACE \n \ + fusesoc library add mdu https://github.com/zeeshanrafique23/mdu\n' + build_serv = build_serv + 'fusesoc run --target=verilator_tb --flag=mdu\ + --build --build-root=servant_test servant\ + --memsize=8388608 --compressed=1' + utils.shellCommand(build_serv).run() + self.sigdump_cmd = 'cd $WORKSPACE/servant_test/verilator_tb-verilator \n\ + ./Vservant_sim\ + +timeout=100000000000\ + +signature={0}/DUT-serv.signature\ + +firmware={0}/{1}.hex' + + def build(self, isa_yaml, platform_yaml): + ispec = utils.load_yaml(isa_yaml)['hart0'] + self.xlen = ('64' if 64 in ispec['supported_xlen'] else '32') + self.isa = 'rv' + self.xlen + if "I" in ispec["ISA"]: + self.isa += 'i' + if "M" in ispec["ISA"]: + self.isa += 'm' + if "C" in ispec["ISA"]: + self.isa += 'c' + self.compile_cmd = self.compile_cmd+' -mabi='+('lp64 ' if 64 in ispec['supported_xlen'] else 'ilp32 ') + + def runTests(self, testList): + for testname in testList: + testentry = testList[testname] + test = testentry['test_path'] + test_dir = testentry['work_dir'] + file_name = 'serv-{0}'.format(test.rsplit('/',1)[1][:-2]) + + elf = '{0}.elf'.format(file_name) + compile_macros= ' -D' + " -D".join(testentry['macros']) + marchstr = testentry['isa'].lower() + + compile_run = self.compile_cmd.format(marchstr, test, elf, compile_macros) + utils.shellCommand(compile_run).run(cwd=test_dir) + + objcopy_run = self.objcopy_cmd.format(elf,file_name) + utils.shellCommand(objcopy_run).run(cwd=test_dir) + + objdump_run = self.objdump_cmd.format(elf,file_name) + utils.shellCommand(objdump_run).run(cwd=test_dir) + + hexgen_run = self.hexgen_cmd.format(test_dir,file_name) + utils.shellCommand(hexgen_run).run() + + sigdump_run = self.sigdump_cmd.format(test_dir,file_name) + utils.shellCommand(sigdump_run).run() + if not self.target_run: + raise SystemExit \ No newline at end of file diff --git a/verif/plugin-serv/serv_isa.yaml b/verif/plugin-serv/serv_isa.yaml new file mode 100644 index 0000000..fe8f8b1 --- /dev/null +++ b/verif/plugin-serv/serv_isa.yaml @@ -0,0 +1,29 @@ +hart_ids: [0] +hart0: + ISA: RV32IMCZicsr_Zifencei + physical_addr_sz: 32 + User_Spec_Version: '2.3' + supported_xlen: [32] + misa: + reset-val: 0x40001104 + rv32: + accessible: true + mxl: + implemented: true + type: + warl: + dependency_fields: [] + legal: + - mxl[1:0] in [0x1] + wr_illegal: + - Unchanged + extensions: + implemented: true + type: + warl: + dependency_fields: [] + legal: + - extensions[25:0] bitmask [0x0001104, 0x0000000] + wr_illegal: + - Unchanged + diff --git a/verif/plugin-serv/serv_platform.yaml b/verif/plugin-serv/serv_platform.yaml new file mode 100644 index 0000000..4b99ed9 --- /dev/null +++ b/verif/plugin-serv/serv_platform.yaml @@ -0,0 +1,4 @@ +nmi: + label: nmi_vector +reset: + label: reset_vector