Skip to content

Commit

Permalink
Merge pull request #14 from saurabhsingh99100/riscv-compliance
Browse files Browse the repository at this point in the history
Add riscv compliance test support
  • Loading branch information
saursin committed Jul 14, 2021
2 parents e7cbf26 + 8f29ec7 commit b641be7
Show file tree
Hide file tree
Showing 8 changed files with 592 additions and 17 deletions.
100 changes: 88 additions & 12 deletions sim/AtomSim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ bool verbose_flag = false;
bool debug_mode = false;
bool trace_enabled = false;
bool dump_regs_on_ebreak = false;
bool dump_signature = false;

// Global vars
std::string ifile;
#ifdef TARGET_ATOMBONES
std::string signature_file = "";
#endif
const unsigned long int default_mem_size = 134217731; // 128MB (Code & Data) + 3 Bytes (Serial IO)
const unsigned int default_entry_point = 0x00000000;
const unsigned long int default_maxitr = 10000000;
Expand Down Expand Up @@ -54,7 +57,7 @@ const std::string AtomSimBackend = "AtomBones";
* @param ifile input file name (pointer)
* @param tdir trace_dir (pointer)
*/
void parse_commandline_args(int argc, char**argv, std::string &ifile)
void parse_commandline_args(int argc, char**argv, std::string &infile)
{
try
{
Expand All @@ -67,11 +70,14 @@ void parse_commandline_args(int argc, char**argv, std::string &ifile)
options.add_options("General")
("h,help", "Show this message")
("version", "Show version information")
("i,input", "Specify an input file", cxxopts::value<std::string>(ifile));
("i,input", "Specify an input file", cxxopts::value<std::string>(infile));

options.add_options("Config")
("maxitr", "Specify maximum simulation iterations", cxxopts::value<unsigned long int>(maxitr))
("memsize", "Specify size of memory to simulate (Supported in AtomBones)", cxxopts::value<unsigned long int>(mem_size));
#ifdef TARGET_ATOMBONES
("memsize", "Specify size of memory to simulate", cxxopts::value<unsigned long int>(mem_size))
#endif
;

options.add_options("Debug")
("v,verbose", "Turn on verbose output", cxxopts::value<bool>(verbose_flag)->default_value("false"))
Expand All @@ -80,7 +86,10 @@ void parse_commandline_args(int argc, char**argv, std::string &ifile)
("trace-dir", "Specify a trace directory", cxxopts::value<std::string>(trace_dir)->default_value(default_trace_dir))
("dump-dir", "Specify a dump directory", cxxopts::value<std::string>(dump_dir)->default_value(default_trace_dir))
("ebreak-dump", "Enable state dump on ebreak", cxxopts::value<bool>(dump_regs_on_ebreak)->default_value("false"))
("signature", "Dump signature after hault (Used for riscv compliance tests)", cxxopts::value<bool>(dump_signature)->default_value("false"));
#ifdef TARGET_ATOMBONES
("signature", "Dump signature after hault (Used for riscv compliance tests)", cxxopts::value<std::string>(signature_file)->default_value(""))
#endif
;


options.parse_positional({"input"});
Expand Down Expand Up @@ -119,7 +128,8 @@ void parse_commandline_args(int argc, char**argv, std::string &ifile)
exit(0);
}

std::cout << "Input File: " << ifile << "\n";
if (verbose_flag)
std::cout << "Input File: " << infile << "\n";

}
catch(const cxxopts::OptionException& e)
Expand Down Expand Up @@ -158,7 +168,8 @@ void tick(long unsigned int cycles, Backend * b, const bool show_data = true)

if (b->tb->m_core->AtomBones->atom_core->InstructionRegister == 0x100073)
{
std::cout << "Exiting @ tick " << b->tb->m_tickcount << " due to ebreak\n";
if (verbose_flag)
std::cout << "Exiting @ tick " << b->tb->m_tickcount << " due to ebreak\n";

if(dump_regs_on_ebreak)
{
Expand All @@ -179,6 +190,71 @@ void tick(long unsigned int cycles, Backend * b, const bool show_data = true)
}
fWrite(fcontents, std::string(trace_dir)+"/dump.txt");
}

#ifdef TARGET_ATOMBONES
if(signature_file.length()!=0)
{
// ============= Get start and end address of signature. =============
long int begin_signature_at = -1;
long int end_signature_at = -1;

ELFIO::elfio reader;

if (!reader.load(ifile))
{
throwError("SIG", "Can't find or process ELF file : " + ifile + "\n", true);
}

ELFIO::Elf_Half n = reader.sections.size();
for ( ELFIO::Elf_Half i = 0; i < n; ++i ) // For all sections
{
ELFIO::section* sec = reader.sections[i];
if ( SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type() )
{
ELFIO::symbol_section_accessor symbols( reader, sec );
ELFIO::Elf_Xword sym_no = symbols.get_symbols_num();
if ( sym_no > 0 )
{
for ( ELFIO::Elf_Xword i = 0; i < sym_no; ++i ) {
std::string name;
ELFIO::Elf64_Addr value = 0;
ELFIO::Elf_Xword size = 0;
unsigned char bind = 0;
unsigned char type = 0;
ELFIO::Elf_Half section = 0;
unsigned char other = 0;
symbols.get_symbol( i, name, value, size, bind, type,
section, other );

if (name == "begin_signature")
begin_signature_at = value;
if (name == "end_signature")
end_signature_at = value;
}
}
}
}

if(begin_signature_at == -1 || end_signature_at == -1)
{
throwError("SIG", "One or both of 'begin_signature' & 'end_signature' symbols missing from ELF symbol table: " + ifile + "\n", true);
}

// ========= dump data to signature file ==============
std::vector<std::string> fcontents;
printf("Dumping signature region [0x%08lx-0x%08lx]\n", begin_signature_at, end_signature_at);

for(long int i=begin_signature_at; i<end_signature_at; i=i+4)
{
char temp [50];
sprintf(temp, "%08x", b->mem->fetchWord(i));
fcontents.push_back(temp);
}
fWrite(fcontents, signature_file);
}
#endif


exit(EXIT_SUCCESS);
}
if(b->tb->m_tickcount > maxitr)
Expand All @@ -199,14 +275,13 @@ void tick(long unsigned int cycles, Backend * b, const bool show_data = true)
*/
int main(int argc, char **argv)
{
std::cout << "AtomSim [" << AtomSimBackend << "]\n";
if (verbose_flag)
std::cout << "AtomSim [" << AtomSimBackend << "]\n";

// Initialize verilator
Verilated::commandArgs(argc, argv);


std::string ifile;

// Parse commandline arguments
parse_commandline_args(argc, argv, ifile);

Expand Down Expand Up @@ -345,13 +420,14 @@ int main(int argc, char **argv)
}
else
{
std::cout << "_________________________________________________________________\n";
tick(-1, &bkend, false);
}

if(trace_enabled) // if trace file is open, close it before exiting
bkend.tb->closeTrace();

std::cout << "Simulation ended @ tick " << bkend.tb->m_tickcount_total << " due to : " << end_simulation_reason << std::endl;

if (verbose_flag)
std::cout << "Simulation ended @ tick " << bkend.tb->m_tickcount_total << " due to : " << end_simulation_reason << std::endl;
exit(EXIT_SUCCESS);
}
6 changes: 4 additions & 2 deletions sim/Backend_AtomBones.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,8 @@ class Backend
mem = new Memory(mem_size);

unsigned int entry_point = mem->initFromElf(mem_init_file, std::vector<int>{5, 6}); // load text & data sections
printf("Entry point : 0x%08x\n", entry_point);
if (verbose_flag)
printf("Entry point : 0x%08x\n", entry_point);

// Set entry point
tb->m_core->AtomBones->atom_core->ProgramCounter = entry_point;
Expand All @@ -363,7 +364,8 @@ class Backend
// get input file disassembly
disassembly = getDisassembly(mem_init_file);

std::cout << "Initialization complete!\n";
if (verbose_flag)
std::cout << "Initialization complete!\n";
}


Expand Down
4 changes: 1 addition & 3 deletions sim/defs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,13 +293,11 @@ std::map<uint32_t, std::string> getDisassembly(std::string filename)

// Parse command output
std::map<uint32_t, std::string> dis;

unsigned long int linebreak = 0;

std::string line;
while(std::getline(s, line))
{
for(int i=0; i<line.length(); i++)
for(unsigned int i=0; i<line.length(); i++)
{
if(line[0]==' ' && line[i]==':')
{
Expand Down
36 changes: 36 additions & 0 deletions test/riscv-target/atombones/compliance_io.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// RISC-V Compliance IO Test Header File

/*
* Copyright (c) 2005-2018 Imperas Software Ltd., www.imperas.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifndef _COMPLIANCE_IO_H
#define _COMPLIANCE_IO_H

//-----------------------------------------------------------------------
// RV IO Macros (Non functional)
//-----------------------------------------------------------------------

#define RVTEST_IO_INIT
#define RVTEST_IO_WRITE_STR(_SP, _STR)
#define RVTEST_IO_CHECK()
//#define RVTEST_IO_ASSERT_GPR_EQ(_SP, _R, _I)
//#define RVTEST_IO_ASSERT_SFPR_EQ(_F, _R, _I)
//#define RVTEST_IO_ASSERT_DFPR_EQ(_D, _R, _I)

#endif // _COMPLIANCE_IO_H
22 changes: 22 additions & 0 deletions test/riscv-target/atombones/device/rv32i_m/I/Makefile.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
TARGET_SIM ?= atomsim
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
$(error Target simulator executable '$(TARGET_SIM)` not found)
endif

RUN_TARGET= $(TARGET_SIM) --maxitr=100000000 --signature=$(*).signature.output $(<) > $@

#RUN_TARGET= $(TARGET_SIM) --maxitr=100000000 $(<) > $(*).signature.output

RISCV_PREFIX ?= riscv64-unknown-elf-
RISCV_GCC ?= $(RISCV_PREFIX)gcc
RISCV_OBJCOPY ?= $(RISCV_PREFIX)objcopy
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -march=rv32i -mabi=ilp32

COMPILE_TARGET=\
$$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
-I$(ROOTDIR)/riscv-test-env/ \
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld $$< \
-o $$@; \
$$(RISCV_OBJDUMP) -D $$@ > [email protected]; \
17 changes: 17 additions & 0 deletions test/riscv-target/atombones/link.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
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 = .;
}
Loading

0 comments on commit b641be7

Please sign in to comment.