Merge branch 'develop'

This commit is contained in:
Eyck Jentzsch 2019-01-10 11:08:57 +00:00
commit cb3a0d8411
50 changed files with 27601 additions and 16492 deletions

View File

@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.3)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_CURRENT_SOURCE_DIR}/sc-components/cmake) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_CURRENT_SOURCE_DIR}/sc-components/cmake)
set(ENABLE_SCV TRUE CACHE BOOL "Enable use of SCV") set(ENABLE_SCV TRUE CACHE BOOL "Enable use of SCV")
set(ENABLE_SHARED TRUE CACHE BOOL "Build shared libraries")
include(GitFunctions) include(GitFunctions)
get_branch_from_git() get_branch_from_git()
@ -32,6 +33,7 @@ include(Conan)
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
@ -112,7 +114,6 @@ add_subdirectory(sc-components)
add_subdirectory(softfloat) add_subdirectory(softfloat)
GET_DIRECTORY_PROPERTY(SOFTFLOAT_INCLUDE_DIRS DIRECTORY softfloat DEFINITION SOFTFLOAT_INCLUDE_DIRS) GET_DIRECTORY_PROPERTY(SOFTFLOAT_INCLUDE_DIRS DIRECTORY softfloat DEFINITION SOFTFLOAT_INCLUDE_DIRS)
add_subdirectory(riscv) add_subdirectory(riscv)
add_subdirectory(riscv.sc)
add_subdirectory(platform) add_subdirectory(platform)
message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}")

View File

@ -1,6 +1,7 @@
[requires] [requires]
gsl_microsoft/20180102@bincrafters/stable gsl_microsoft/20180102@bincrafters/stable
spdlog/0.16.3@bincrafters/stable spdlog/0.16.3@bincrafters/stable
fmt/5.2.1@bincrafters/stable
Seasocks/1.3.2@minres/stable Seasocks/1.3.2@minres/stable
SystemC/2.3.2@minres/stable SystemC/2.3.2@minres/stable
SystemCVerification/2.0.1@minres/stable SystemCVerification/2.0.1@minres/stable
@ -11,6 +12,7 @@
[options] [options]
Seasocks:shared=True Seasocks:shared=True
fmt:header_only=True
SystemC:stdcxx=14 SystemC:stdcxx=14
SystemC:shared=True SystemC:shared=True
SystemCVerification:stdcxx=14 SystemCVerification:stdcxx=14

@ -1 +1 @@
Subproject commit f76938cbdc90da4c8fbab0fa36a155f3e0816af7 Subproject commit a9d808088e64622a6c9bf52071436e9df206bae3

View File

@ -25,7 +25,6 @@ endif()
add_dependent_subproject(dbt-core) add_dependent_subproject(dbt-core)
add_dependent_subproject(sc-components) add_dependent_subproject(sc-components)
add_dependent_subproject(riscv) add_dependent_subproject(riscv)
add_dependent_subproject(riscv.sc)
include_directories( include_directories(
${PROJECT_SOURCE_DIR}/../external/elfio ${PROJECT_SOURCE_DIR}/../external/elfio

View File

@ -30,7 +30,17 @@ set(LIBRARY_NAME platform)
#add_definitions(-DSC_DEFAULT_WRITER_POLICY=SC_MANY_WRITERS) #add_definitions(-DSC_DEFAULT_WRITER_POLICY=SC_MANY_WRITERS)
# Define the library # Define the library
add_library(${LIBRARY_NAME} ${LIB_SOURCES}) add_library(${LIBRARY_NAME} SHARED ${LIB_SOURCES})
# Links the target exe against the libraries
target_link_libraries(${LIBRARY_NAME} riscv_sc)
target_link_libraries(${LIBRARY_NAME} dbt-core)
target_link_libraries(${LIBRARY_NAME} softfloat)
target_link_libraries(${LIBRARY_NAME} sc-components)
target_link_libraries(${LIBRARY_NAME} ${CONAN_LIBS_SEASOCKS})
target_link_libraries(${LIBRARY_NAME} external)
target_link_libraries(${LIBRARY_NAME} ${llvm_libs})
target_link_libraries(${LIBRARY_NAME} ${Boost_LIBRARIES} )
set_target_properties(${LIBRARY_NAME} PROPERTIES set_target_properties(${LIBRARY_NAME} PROPERTIES
VERSION ${VERSION} # ${VERSION} was defined in the main CMakeLists. VERSION ${VERSION} # ${VERSION} was defined in the main CMakeLists.
@ -61,8 +71,7 @@ add_executable(${APPLICATION_NAME} ${APP_SOURCES})
target_include_directories(${APPLICATION_NAME} SYSTEM PRIVATE ${LLVM_INCLUDE_DIRS}) target_include_directories(${APPLICATION_NAME} SYSTEM PRIVATE ${LLVM_INCLUDE_DIRS})
# Links the target exe against the libraries # Links the target exe against the libraries
target_link_libraries(${APPLICATION_NAME} ${LIBRARY_NAME}) target_link_libraries(${APPLICATION_NAME} ${LIBRARY_NAME})
target_link_libraries(${APPLICATION_NAME} riscv.sc) target_link_libraries(${APPLICATION_NAME} riscv_sc)
target_link_libraries(${APPLICATION_NAME} riscv)
target_link_libraries(${APPLICATION_NAME} dbt-core) target_link_libraries(${APPLICATION_NAME} dbt-core)
target_link_libraries(${APPLICATION_NAME} softfloat) target_link_libraries(${APPLICATION_NAME} softfloat)
target_link_libraries(${APPLICATION_NAME} sc-components) target_link_libraries(${APPLICATION_NAME} sc-components)

View File

@ -32,7 +32,6 @@
#include "CLIParser.h" #include "CLIParser.h"
#include <sysc/top/system.h> #include <sysc/top/system.h>
#include <iss/jit/jit_helper.h>
#include <iss/log_categories.h> #include <iss/log_categories.h>
#include <scc/configurable_tracer.h> #include <scc/configurable_tracer.h>
@ -45,6 +44,7 @@
#include <cci_utils/broker.h> #include <cci_utils/broker.h>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <iss/llvm/jit_helper.h>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>

View File

@ -83,13 +83,13 @@ fe310::fe310(sc_core::sc_module_name nm)
size_t i = 0; size_t i = 0;
for (const auto &e : e300_plat_t_map) { for (const auto &e : e300_plat_t_map) {
i_router->initiator.at(i)(e.target); i_router->initiator.at(i)(e.target);
i_router->add_target_range(i, e.start, e.size); i_router->set_target_range(i, e.start, e.size);
i++; i++;
} }
i_router->initiator.at(i)(i_mem_qspi->target); i_router->initiator.at(i)(i_mem_qspi->target);
i_router->add_target_range(i, 0x20000000, 512_MB); i_router->set_target_range(i, 0x20000000, 512_MB);
i_router->initiator.at(++i)(i_mem_ram->target); i_router->initiator.at(++i)(i_mem_ram->target);
i_router->add_target_range(i, 0x80000000, 128_kB); i_router->set_target_range(i, 0x80000000, 128_kB);
i_uart0->clk_i(s_tlclk); i_uart0->clk_i(s_tlclk);
i_uart1->clk_i(s_tlclk); i_uart1->clk_i(s_tlclk);

View File

@ -50,7 +50,7 @@ plic::plic(sc_core::sc_module_name nm)
{ {
regs->registerResources(*this); regs->registerResources(*this);
// register callbacks // register callbacks
regs->claim_complete.set_write_cb([this](scc::sc_register<uint32_t> reg, uint32_t v, sc_core::sc_time d) -> bool { regs->claim_complete.set_write_cb([this](scc::sc_register<uint32_t>& reg, uint32_t v, sc_core::sc_time d) -> bool {
reg.put(v); reg.put(v);
reset_pending_int(v); reset_pending_int(v);
// std::cout << "Value of register: 0x" << std::hex << reg << std::endl; // std::cout << "Value of register: 0x" << std::hex << reg << std::endl;

View File

@ -1,93 +0,0 @@
cmake_minimum_required(VERSION 3.3)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) # main (top) cmake dir
# CMake useful variables
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
# Set the name of your project here
project("riscv.sc")
include(Common)
# check that we have averything we need
if(!SystemC_FOUND)
message( FATAL_ERROR "SystemC library not found." )
endif()
if(!CCI_FOUND)
message( FATAL_ERROR "SystemC CCI library not found." )
endif()
add_definitions(-DWITH_SYSTEMC)
include_directories(${SystemC_INCLUDE_DIRS})
link_directories(${SystemC_LIBRARY_DIRS})
include_directories(${CCI_INCLUDE_DIRS})
link_directories(${CCI_LIBRARY_DIRS})
if(SCV_FOUND)
add_definitions(-DWITH_SCV)
include_directories(${SCV_INCLUDE_DIRS})
link_directories(${SCV_LIBRARY_DIRS})
endif()
# This sets the include directory for the reference project. This is the -I flag in gcc.
include_directories(
${PROJECT_SOURCE_DIR}/incl
${LLVM_INCLUDE_DIRS}
)
add_dependent_subproject(dbt-core)
add_dependent_subproject(sc-components)
add_dependent_subproject(riscv)
include_directories(
${PROJECT_SOURCE_DIR}/incl
${PROJECT_SOURCE_DIR}/../riscv/incl
${PROJECT_SOURCE_DIR}/../external/elfio
${PROJECT_SOURCE_DIR}/../external/libGIS
${Boost_INCLUDE_DIRS}
)
# Mac needed variables (adapt for your needs - http://www.cmake.org/Wiki/CMake_RPATH_handling#Mac_OS_X_and_the_RPATH)
set(CMAKE_MACOSX_RPATH ON)
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
## the following setting needs to be consistent with the library
#add_definitions(-DSC_DEFAULT_WRITER_POLICY=SC_MANY_WRITERS)
# library files
FILE(GLOB RiscVSCHeaders *.h */*.h)
set(LIB_HEADERS ${RiscVSCHeaders} )
set(LIB_SOURCES src/core_complex.cpp )
# Define two variables in order not to repeat ourselves.
set(LIBRARY_NAME riscv.sc)
# Define the library
add_library(${LIBRARY_NAME} ${LIB_SOURCES})
set_target_properties(${LIBRARY_NAME} PROPERTIES
VERSION ${VERSION} # ${VERSION} was defined in the main CMakeLists.
FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers
)
#
# SYSTEM PACKAGING (RPM, TGZ, ...)
# _____________________________________________________________________________
#include(CPackConfig)
#
# CMAKE PACKAGING (for other CMake projects to use this one easily)
# _____________________________________________________________________________
#include(PackageConfigurator)

View File

@ -0,0 +1,50 @@
InsructionSet RISCVBase {
constants {
XLEN,
fence:=0,
fencei:=1,
fencevmal:=2,
fencevmau:=3
}
address_spaces {
MEM[8], CSR[XLEN], FENCE[XLEN], RES[8]
}
registers {
[31:0] X[XLEN],
PC[XLEN](is_pc),
alias ZERO[XLEN] is X[0],
alias RA[XLEN] is X[1],
alias SP[XLEN] is X[2],
alias GP[XLEN] is X[3],
alias TP[XLEN] is X[4],
alias T0[XLEN] is X[5],
alias T1[XLEN] is X[6],
alias T2[XLEN] is X[7],
alias S0[XLEN] is X[8],
alias S1[XLEN] is X[9],
alias A0[XLEN] is X[10],
alias A1[XLEN] is X[11],
alias A2[XLEN] is X[12],
alias A3[XLEN] is X[13],
alias A4[XLEN] is X[14],
alias A5[XLEN] is X[15],
alias A6[XLEN] is X[16],
alias A7[XLEN] is X[17],
alias S2[XLEN] is X[18],
alias S3[XLEN] is X[19],
alias S4[XLEN] is X[20],
alias S5[XLEN] is X[21],
alias S6[XLEN] is X[22],
alias S7[XLEN] is X[23],
alias S8[XLEN] is X[24],
alias S9[XLEN] is X[25],
alias S10[XLEN] is X[26],
alias S11[XLEN] is X[27],
alias T3[XLEN] is X[28],
alias T4[XLEN] is X[29],
alias T5[XLEN] is X[30],
alias T6[XLEN] is X[31]
}
}

View File

@ -1,108 +0,0 @@
import "RV32IBase.core_desc"
InsructionSet RV32A extends RV32IBase{
address_spaces {
RES[8]
}
instructions{
LR.W {
encoding: b00010 | aq[0:0] | rl[0:0] | b00000 | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d";
if(rd!=0){
val offs[XLEN] <= X[rs1];
X[rd]<= sext(MEM[offs]{32}, XLEN);
RES[offs]{32}<=sext(-1, 32);
}
}
SC.W {
encoding: b00011 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d";
val offs[XLEN] <= X[rs1];
val res1[32] <= RES[offs]{32};
if(res1!=0)
MEM[offs]{32} <= X[rs2];
if(rd!=0) X[rd]<= choose(res1!=0, 0, 1);
}
AMOSWAP.W{
encoding: b00001 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)";
val offs[XLEN]<=X[rs1];
if(rd!=0) X[rd]<=sext(MEM[offs]{32});
MEM[offs]{32}<=X[rs2];
}
AMOADD.W{
encoding: b00000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN]<=res1 + X[rs2];
MEM[offs]{32}<=res2;
}
AMOXOR.W{
encoding: b00100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN]<=res1 ^ X[rs2];
MEM[offs]{32}<=res2;
}
AMOAND.W{
encoding: b01100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN] <=res1 & X[rs2];
MEM[offs]{32}<=res2;
}
AMOOR.W {
encoding: b01000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN]<=res1 | X[rs2];
MEM[offs]{32}<=res2;
}
AMOMIN.W{
encoding: b10000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN]<= choose(res1's>X[rs2]s, X[rs2], res1);
MEM[offs]{32}<=res2;
}
AMOMAX.W{
encoding: b10100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN]<= choose(res1's<X[rs2]s, X[rs2], res1);
MEM[offs]{32}<=res2;
}
AMOMINU.W{
encoding: b11000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= zext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN]<= choose(res1>X[rs2], X[rs2], res1);
MEM[offs]{32}<=res2;
}
AMOMAXU.W{
encoding: b11100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= zext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN]<= choose(res1'u<X[rs2]'u, X[rs2], res1);
MEM[offs]{32}<=res2;
}
}
}

View File

@ -1,294 +0,0 @@
import "RV32IBase.core_desc"
InsructionSet RV32F extends RV32IBase{
constants {
FLEN, FFLAG_MASK := 0x1f
}
registers {
[31:0] F[FLEN], FCSR[32]
}
instructions{
FLW {
encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000111;
args_disass:"f%rd$d, %imm%(x%rs1$d)";
val offs[XLEN] <= X[rs1]'s + imm;
val res[32] <= MEM[offs]{32};
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FSW {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b010 | imm[4:0]s | b0100111;
args_disass:"f%rs2$d, %imm%(x%rs1$d)";
val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{32}<=F[rs2]{32};
}
FMADD.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d";
//F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f;
val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(0, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FMSUB.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d";
//F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f;
val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FNMADD.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d";
//F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f;
val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FNMSUB.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d";
//F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f;
val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FADD.S {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
// F[rd]f <= F[rs1]f + F[rs2]f;
val res[32] <= fdispatch_fadd_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FSUB.S {
encoding: b0000100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
// F[rd]f <= F[rs1]f - F[rs2]f;
val res[32] <= fdispatch_fsub_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FMUL.S {
encoding: b0001000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
// F[rd]f <= F[rs1]f * F[rs2]f;
val res[32] <= fdispatch_fmul_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FDIV.S {
encoding: b0001100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
// F[rd]f <= F[rs1]f / F[rs2]f;
val res[32] <= fdispatch_fdiv_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FSQRT.S {
encoding: b0101100 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d";
//F[rd]f<=sqrt(F[rs1]f);
val res[32] <= fdispatch_fsqrt_s(F[rs1]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FSGNJ.S {
encoding: b0010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
val res[32] <= (F[rs1]{32} & 0x7fffffff) | (F[rs2]{32} & 0x80000000);
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FSGNJN.S {
encoding: b0010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
val res[32] <= (F[rs1]{32} & 0x7fffffff) | (~F[rs2]{32} & 0x80000000);
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FSGNJX.S {
encoding: b0010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
val res[32] <= F[rs1]{32} ^ (F[rs2]{32} & 0x80000000);
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FMIN.S {
encoding: b0010100 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
//F[rd]f<= choose(F[rs1]f<F[rs2]f, F[rs1]f, F[rs2]f);
val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(0, 32));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FMAX.S {
encoding: b0010100 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
//F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f);
val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(1, 32));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.W.S {
encoding: b1100000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d";
X[rd]<= sext(fdispatch_fcvt_s(F[rs1]{32}, zext(0, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.WU.S {
encoding: b1100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d";
X[rd]<= zext(fdispatch_fcvt_s(F[rs1]{32}, zext(1, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FEQ.S {
encoding: b1010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(0, 32));
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FLT.S {
encoding: b1010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(2, 32));
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FLE.S {
encoding: b1010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(1, 32));
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCLASS.S {
encoding: b1110000 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d";
X[rd]<=fdispatch_fclass_s(F[rs1]{32});
}
FCVT.S.W {
encoding: b1101000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, x%rs1$d";
val res[32] <= fdispatch_fcvt_s(X[rs1]{32}, zext(2, 32), rm{8});
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FCVT.S.WU {
encoding: b1101000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, x%rs1$d";
val res[32] <=fdispatch_fcvt_s(X[rs1]{32}, zext(3,32), rm{8});
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FMV.X.W {
encoding: b1110000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d";
X[rd]<=sext(F[rs1]{32});
}
FMV.W.X {
encoding: b1111000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f%rd$d, x%rs1$d";
if(FLEN==32)
F[rd] <= X[rs1];
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(X[rs1], FLEN);
}
}
}
}

View File

@ -1,44 +1,27 @@
InsructionSet RV32IBase { import "RISCVBase.core_desc"
constants {
XLEN,
PCLEN,
XLEN_BIT_MASK:=0x1f,
fence:=0,
fencei:=1,
fencevmal:=2,
fencevmau:=3
}
address_spaces { InsructionSet RV32I extends RISCVBase{
MEM[8], CSR[XLEN], FENCE[XLEN]
}
registers {
[31:0] X[XLEN],
PC[XLEN](is_pc),
alias ZERO[XLEN] is X[0]
}
instructions { instructions {
LUI{ LUI{
encoding: imm[31:12]s | rd[4:0] | b0110111; encoding: imm[31:12]s | rd[4:0] | b0110111;
args_disass: "x%rd$d, 0x%imm$05x"; args_disass: "{name(rd)}, {imm:#05x}";
if(rd!=0) X[rd] <= imm; if(rd!=0) X[rd] <= imm;
} }
AUIPC{ AUIPC{
encoding: imm[31:12]s | rd[4:0] | b0010111; encoding: imm[31:12]s | rd[4:0] | b0010111;
args_disass: "x%rd%, 0x%imm$08x"; args_disass: "{name(rd)}, {imm:#08x}";
if(rd!=0) X[rd] <= PC's+imm; if(rd!=0) X[rd] <= PC's+imm;
} }
JAL(no_cont){ JAL(no_cont){
encoding: imm[20:20]s | imm[10:1]s | imm[11:11]s | imm[19:12]s | rd[4:0] | b1101111; encoding: imm[20:20]s | imm[10:1]s | imm[11:11]s | imm[19:12]s | rd[4:0] | b1101111;
args_disass: "x%rd$d, 0x%imm$x"; args_disass: "{name(rd)}, {imm:#0x}";
if(rd!=0) X[rd] <= PC+4; if(rd!=0) X[rd] <= PC+4;
PC<=PC's+imm; PC<=PC's+imm;
} }
JALR(no_cont){ JALR(no_cont){
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111; encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111;
args_disass: "x%rd$d, x%rs1$d, 0x%imm$x"; args_disass: "{name(rd)}, {name(rs1)}, {imm:#0x}";
val new_pc[XLEN] <= X[rs1]'s+ imm; val new_pc[XLEN] <= X[rs1]'s+ imm;
val align[XLEN] <= new_pc & 0x2; val align[XLEN] <= new_pc & 0x2;
if(align != 0){ if(align != 0){
@ -50,116 +33,116 @@ InsructionSet RV32IBase {
} }
BEQ(no_cont,cond){ BEQ(no_cont,cond){
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:1]s | imm[11:11]s | b1100011; encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]==X[rs2], PC's+imm, PC+4); PC<=choose(X[rs1]==X[rs2], PC's+imm, PC+4);
} }
BNE(no_cont,cond){ BNE(no_cont,cond){
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b001 | imm[4:1]s | imm[11:11]s | b1100011; encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b001 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]!=X[rs2], PC's+imm, PC+4); PC<=choose(X[rs1]!=X[rs2], PC's+imm, PC+4);
} }
BLT(no_cont,cond){ BLT(no_cont,cond){
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b100 | imm[4:1]s | imm[11:11]s | b1100011; encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b100 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]s<X[rs2]s, PC's+imm, PC+4); PC<=choose(X[rs1]s<X[rs2]s, PC's+imm, PC+4);
} }
BGE(no_cont,cond) { BGE(no_cont,cond) {
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b101 | imm[4:1]s | imm[11:11]s | b1100011; encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b101 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]s>=X[rs2]s, PC's+imm, PC+4); PC<=choose(X[rs1]s>=X[rs2]s, PC's+imm, PC+4);
} }
BLTU(no_cont,cond) { BLTU(no_cont,cond) {
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b110 | imm[4:1]s | imm[11:11]s | b1100011; encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b110 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]<X[rs2],PC's+imm, PC+4); PC<=choose(X[rs1]<X[rs2],PC's+imm, PC+4);
} }
BGEU(no_cont,cond) { BGEU(no_cont,cond) {
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b111 | imm[4:1]s | imm[11:11]s | b1100011; encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b111 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]>=X[rs2], PC's+imm, PC+4); PC<=choose(X[rs1]>=X[rs2], PC's+imm, PC+4);
} }
LB { LB {
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm; val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=sext(MEM[offs]); if(rd!=0) X[rd]<=sext(MEM[offs]);
} }
LH { LH {
encoding: imm[11:0]s | rs1[4:0] | b001 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b001 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm; val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=sext(MEM[offs]{16}); if(rd!=0) X[rd]<=sext(MEM[offs]{16});
} }
LW { LW {
encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm; val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=sext(MEM[offs]{32}); if(rd!=0) X[rd]<=sext(MEM[offs]{32});
} }
LBU { LBU {
encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm; val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=zext(MEM[offs]); if(rd!=0) X[rd]<=zext(MEM[offs]);
} }
LHU { LHU {
encoding: imm[11:0]s | rs1[4:0] | b101 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b101 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm; val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=zext(MEM[offs]{16}); if(rd!=0) X[rd]<=zext(MEM[offs]{16});
} }
SB { SB {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:0]s | b0100011; encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:0]s | b0100011;
args_disass:"x%rs2$d, %imm%(x%rs1$d)"; args_disass:"{name(rs2)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs] <= X[rs2]; MEM[offs] <= X[rs2];
} }
SH { SH {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b001 | imm[4:0]s | b0100011; encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b001 | imm[4:0]s | b0100011;
args_disass:"x%rs2$d, %imm%(x%rs1$d)"; args_disass:"{name(rs2)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{16} <= X[rs2]; MEM[offs]{16} <= X[rs2];
} }
SW { SW {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b010 | imm[4:0]s | b0100011; encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b010 | imm[4:0]s | b0100011;
args_disass:"x%rs2$d, %imm%(x%rs1$d)"; args_disass:"{name(rs2)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{32} <= X[rs2]; MEM[offs]{32} <= X[rs2];
} }
ADDI { ADDI {
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0010011; encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0) X[rd] <= X[rs1]'s + imm; if(rd != 0) X[rd] <= X[rs1]'s + imm;
} }
SLTI { SLTI {
encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0010011; encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if (rd != 0) X[rd] <= choose(X[rs1]s < imm's, 1, 0); if (rd != 0) X[rd] <= choose(X[rs1]s < imm's, 1, 0);
} }
SLTIU { SLTIU {
encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0010011; encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
val full_imm[XLEN] <= imm's; val full_imm[XLEN] <= imm's;
if (rd != 0) X[rd] <= choose(X[rs1]'u < full_imm'u, 1, 0); if (rd != 0) X[rd] <= choose(X[rs1]'u < full_imm'u, 1, 0);
} }
XORI { XORI {
encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0010011; encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0) X[rd] <= X[rs1]s ^ imm; if(rd != 0) X[rd] <= X[rs1]s ^ imm;
} }
ORI { ORI {
encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0010011; encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0) X[rd] <= X[rs1]s | imm; if(rd != 0) X[rd] <= X[rs1]s | imm;
} }
ANDI { ANDI {
encoding: imm[11:0]s | rs1[4:0] | b111 | rd[4:0] | b0010011; encoding: imm[11:0]s | rs1[4:0] | b111 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0) X[rd] <= X[rs1]s & imm; if(rd != 0) X[rd] <= X[rs1]s & imm;
} }
SLLI { SLLI {
encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0010011; encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(shamt > 31){ if(shamt > 31){
raise(0,0); raise(0,0);
} else { } else {
@ -168,7 +151,7 @@ InsructionSet RV32IBase {
} }
SRLI { SRLI {
encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(shamt > 31){ if(shamt > 31){
raise(0,0); raise(0,0);
} else { } else {
@ -177,7 +160,7 @@ InsructionSet RV32IBase {
} }
SRAI { SRAI {
encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(shamt > 31){ if(shamt > 31){
raise(0,0); raise(0,0);
} else { } else {
@ -186,52 +169,52 @@ InsructionSet RV32IBase {
} }
ADD { ADD {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] + X[rs2]; if(rd != 0) X[rd] <= X[rs1] + X[rs2];
} }
SUB { SUB {
encoding: b0100000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011; encoding: b0100000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] - X[rs2]; if(rd != 0) X[rd] <= X[rs1] - X[rs2];
} }
SLL { SLL {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= shll(X[rs1], X[rs2]&XLEN_BIT_MASK); if(rd != 0) X[rd] <= shll(X[rs1], X[rs2]&(XLEN-1));
} }
SLT { SLT {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if (rd != 0) X[rd] <= choose(X[rs1]s < X[rs2]s, 1, 0); if (rd != 0) X[rd] <= choose(X[rs1]s < X[rs2]s, 1, 0);
} }
SLTU { SLTU {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if (rd != 0) X[rd] <= choose(zext(X[rs1]) < zext(X[rs2]), 1, 0); if (rd != 0) X[rd] <= choose(zext(X[rs1]) < zext(X[rs2]), 1, 0);
} }
XOR { XOR {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] ^ X[rs2]; if(rd != 0) X[rd] <= X[rs1] ^ X[rs2];
} }
SRL { SRL {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= shrl(X[rs1], X[rs2]&XLEN_BIT_MASK); if(rd != 0) X[rd] <= shrl(X[rs1], X[rs2]&(XLEN-1));
} }
SRA { SRA {
encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011; encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= shra(X[rs1], X[rs2]&XLEN_BIT_MASK); if(rd != 0) X[rd] <= shra(X[rs1], X[rs2]&(XLEN-1));
} }
OR { OR {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] | X[rs2]; if(rd != 0) X[rd] <= X[rs1] | X[rs2];
} }
AND { AND {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] & X[rs2]; if(rd != 0) X[rd] <= X[rs1] & X[rs2];
} }
FENCE { FENCE {
@ -273,7 +256,7 @@ InsructionSet RV32IBase {
} }
CSRRW { CSRRW {
encoding: csr[11:0] | rs1[4:0] | b001 | rd[4:0] | b1110011; encoding: csr[11:0] | rs1[4:0] | b001 | rd[4:0] | b1110011;
args_disass:"x%rd$d, %csr$d, x%rs1$d"; args_disass:"{name(rd)}, {csr}, {name(rs1)}";
val rs_val[XLEN] <= X[rs1]; val rs_val[XLEN] <= X[rs1];
if(rd!=0){ if(rd!=0){
val csr_val[XLEN] <= CSR[csr]; val csr_val[XLEN] <= CSR[csr];
@ -286,7 +269,7 @@ InsructionSet RV32IBase {
} }
CSRRS { CSRRS {
encoding: csr[11:0] | rs1[4:0] | b010 | rd[4:0] | b1110011; encoding: csr[11:0] | rs1[4:0] | b010 | rd[4:0] | b1110011;
args_disass:"x%rd$d, %csr$d, x%rs1$d"; args_disass:"{name(rd)}, {csr}, {name(rs1)}";
val xrd[XLEN] <= CSR[csr]; val xrd[XLEN] <= CSR[csr];
val xrs1[XLEN] <= X[rs1]; val xrs1[XLEN] <= X[rs1];
if(rd!=0) X[rd] <= xrd; if(rd!=0) X[rd] <= xrd;
@ -294,7 +277,7 @@ InsructionSet RV32IBase {
} }
CSRRC { CSRRC {
encoding: csr[11:0] | rs1[4:0] | b011 | rd[4:0] | b1110011; encoding: csr[11:0] | rs1[4:0] | b011 | rd[4:0] | b1110011;
args_disass:"x%rd$d, %csr$d, x%rs1$d"; args_disass:"{name(rd)}, {csr}, {name(rs1)}";
val xrd[XLEN] <= CSR[csr]; val xrd[XLEN] <= CSR[csr];
val xrs1[XLEN] <= X[rs1]; val xrs1[XLEN] <= X[rs1];
if(rd!=0) X[rd] <= xrd; if(rd!=0) X[rd] <= xrd;
@ -302,13 +285,13 @@ InsructionSet RV32IBase {
} }
CSRRWI { CSRRWI {
encoding: csr[11:0] | zimm[4:0] | b101 | rd[4:0] | b1110011; encoding: csr[11:0] | zimm[4:0] | b101 | rd[4:0] | b1110011;
args_disass:"x%rd$d, %csr$d, 0x%zimm$x"; args_disass:"{name(rd)}, {csr}, {zimm:#0x}";
if(rd!=0) X[rd] <= CSR[csr]; if(rd!=0) X[rd] <= CSR[csr];
CSR[csr] <= zext(zimm); CSR[csr] <= zext(zimm);
} }
CSRRSI { CSRRSI {
encoding: csr[11:0] | zimm[4:0] | b110 | rd[4:0] | b1110011; encoding: csr[11:0] | zimm[4:0] | b110 | rd[4:0] | b1110011;
args_disass:"x%rd$d, %csr$d, 0x%zimm$x"; args_disass:"{name(rd)}, {csr}, {zimm:#0x}";
val res[XLEN] <= CSR[csr]; val res[XLEN] <= CSR[csr];
if(zimm!=0) CSR[csr] <= res | zext(zimm); if(zimm!=0) CSR[csr] <= res | zext(zimm);
// make sure rd is written after csr write succeeds // make sure rd is written after csr write succeeds
@ -316,7 +299,7 @@ InsructionSet RV32IBase {
} }
CSRRCI { CSRRCI {
encoding: csr[11:0] | zimm[4:0] | b111 | rd[4:0] | b1110011; encoding: csr[11:0] | zimm[4:0] | b111 | rd[4:0] | b1110011;
args_disass:"x%rd$d, %csr$d, 0x%zimm$x"; args_disass:"{name(rd)}, {csr}, {zimm:#0x}";
val res[XLEN] <= CSR[csr]; val res[XLEN] <= CSR[csr];
if(rd!=0) X[rd] <= res; if(rd!=0) X[rd] <= res;
if(zimm!=0) CSR[csr] <= res & ~zext(zimm, XLEN); if(zimm!=0) CSR[csr] <= res & ~zext(zimm, XLEN);

View File

@ -1,97 +0,0 @@
import "RV32IBase.core_desc"
InsructionSet RV32M extends RV32IBase {
constants {
MAXLEN:=128
}
instructions{
MUL{
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN);
X[rd]<= zext(res , XLEN);
}
}
MULH {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
val res[MAXLEN] <= sext(X[rs1], MAXLEN) * sext(X[rs2], MAXLEN);
X[rd]<= zext(res >> XLEN, XLEN);
}
}
MULHSU {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
val res[MAXLEN] <= sext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN);
X[rd]<= zext(res >> XLEN, XLEN);
}
}
MULHU {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN);
X[rd]<= zext(res >> XLEN, XLEN);
}
}
DIV {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
if(X[rs2]!=0){
val M1[XLEN] <= -1;
val MMIN[XLEN] <= -1<<(XLEN-1);
if(X[rs1]s==MMIN's)
if(X[rs2]s==M1's)
X[rd]<=MMIN;
else
X[rd] <= X[rs1]s / X[rs2]s;
else
X[rd] <= X[rs1]s / X[rs2]s;
}else
X[rd] <= -1;
}
}
DIVU {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
if(X[rs2]!=0)
X[rd] <= zext(X[rs1], 32) / zext(X[rs2], 32);
else
X[rd] <= -1;
}
}
REM {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
if(X[rs2]!=0) {
val M1[XLEN] <= -1;
val MMIN[XLEN] <= -1<<(XLEN-1);
if(X[rs1]s==MMIN's)
if(X[rs2]s==M1's)
X[rd] <= 0;
else
X[rd] <= sext(X[rs1], 32) % sext(X[rs2], 32);
else
X[rd] <= sext(X[rs1], 32) % sext(X[rs2], 32);
} else
X[rd] <= X[rs1];
}
}
REMU {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
if(X[rs2]!=0)
X[rd] <= zext(X[rs1], 32) % zext(X[rs2], 32);
else
X[rd] <= X[rs1];
}
}
}
}

View File

@ -1,112 +0,0 @@
import "RV64IBase.core_desc"
import "RV32A.core_desc"
InsructionSet RV64A extends RV64IBase {
address_spaces {
RES[8]
}
instructions{
LR.D {
encoding: b00010 | aq[0:0] | rl[0:0] | b00000 | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d";
if(rd!=0){
val offs[XLEN] <= X[rs1];
X[rd]<= sext(MEM[offs]{64}, XLEN);
RES[offs]{64}<=sext(-1, 64);
}
}
SC.D {
encoding: b00011 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d";
val offs[XLEN] <= X[rs1];
val res[64] <= RES[offs];
if(res!=0){
MEM[offs]{64} <= X[rs2];
if(rd!=0) X[rd]<=0;
} else{
if(rd!=0) X[rd]<= 1;
}
}
AMOSWAP.D{
encoding: b00001 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)";
val offs[XLEN] <= X[rs1];
if(rd!=0) X[rd] <= sext(MEM[offs]{64});
MEM[offs]{64} <= X[rs2];
}
AMOADD.D{
encoding: b00000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd]<=res;
val res2[XLEN] <= res + X[rs2];
MEM[offs]{64}<=res2;
}
AMOXOR.D{
encoding: b00100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res;
val res2[XLEN] <= res ^ X[rs2];
MEM[offs]{64} <= res2;
}
AMOAND.D{
encoding: b01100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res;
val res2[XLEN] <= res & X[rs2];
MEM[offs]{64} <= res2;
}
AMOOR.D {
encoding: b01000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res;
val res2[XLEN] <= res | X[rs2];
MEM[offs]{64} <= res2;
}
AMOMIN.D{
encoding: b10000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res;
val res2[XLEN] <= choose(res s > X[rs2]s, X[rs2], res);
MEM[offs]{64} <= res;
}
AMOMAX.D{
encoding: b10100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res;
val res2[XLEN] <= choose(res s < X[rs2]s, X[rs2], res);
MEM[offs]{64} <= res2;
}
AMOMINU.D{
encoding: b11000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= zext(MEM[offs]{64});
if(rd!=0) X[rd] <= res;
val res2[XLEN] <= choose(res > X[rs2], X[rs2], res);
MEM[offs]{64} <= res2;
}
AMOMAXU.D{
encoding: b11100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= zext(MEM[offs]{64});
if(rd!=0) X[rd] <= res;
val res2[XLEN] <= choose(res < X[rs2], X[rs2], res);
MEM[offs]{64} <= res2;
}
}
}

View File

@ -1,43 +1,43 @@
import "RV32IBase.core_desc" import "RV32I.core_desc"
InsructionSet RV64IBase extends RV32IBase { InsructionSet RV64I extends RV32I {
instructions{ instructions{
LWU { // 80000104: 0000ef03 lwu t5,0(ra) LWU { // 80000104: 0000ef03 lwu t5,0(ra)
encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm; val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=zext(MEM[offs]{32}); if(rd!=0) X[rd]<=zext(MEM[offs]{32});
} }
LD{ LD{
encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
if(rd!=0) X[rd]<=sext(MEM[offs]{64}); if(rd!=0) X[rd]<=sext(MEM[offs]{64});
} }
SD{ SD{
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100011; encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100011;
args_disass:"x%rs2$d, %imm%(x%rs1$d)"; args_disass:"{name(rs2)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{64} <= X[rs2]; MEM[offs]{64} <= X[rs2];
} }
SLLI { SLLI {
encoding: b000000 | shamt[5:0] | rs1[4:0] | b001 | rd[4:0] | b0010011; encoding: b000000 | shamt[5:0] | rs1[4:0] | b001 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(rd != 0) X[rd] <= shll(X[rs1], shamt); if(rd != 0) X[rd] <= shll(X[rs1], shamt);
} }
SRLI { SRLI {
encoding: b000000 | shamt[5:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; encoding: b000000 | shamt[5:0] | rs1[4:0] | b101 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(rd != 0) X[rd] <= shrl(X[rs1], shamt); if(rd != 0) X[rd] <= shrl(X[rs1], shamt);
} }
SRAI { SRAI {
encoding: b010000 | shamt[5:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; encoding: b010000 | shamt[5:0] | rs1[4:0] | b101 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(rd != 0) X[rd] <= shra(X[rs1], shamt); if(rd != 0) X[rd] <= shra(X[rs1], shamt);
} }
ADDIW { ADDIW {
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0011011; encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0011011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0){ if(rd != 0){
val res[32] <= X[rs1]{32}'s + imm; val res[32] <= X[rs1]{32}'s + imm;
X[rd] <= sext(res); X[rd] <= sext(res);
@ -45,7 +45,7 @@ InsructionSet RV64IBase extends RV32IBase {
} }
SLLIW { SLLIW {
encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0011011; encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0011011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(rd != 0){ if(rd != 0){
val sh_val[32] <= shll(X[rs1]{32}, shamt); val sh_val[32] <= shll(X[rs1]{32}, shamt);
X[rd] <= sext(sh_val); X[rd] <= sext(sh_val);
@ -53,7 +53,7 @@ InsructionSet RV64IBase extends RV32IBase {
} }
SRLIW { SRLIW {
encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0011011; encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0011011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(rd != 0){ if(rd != 0){
val sh_val[32] <= shrl(X[rs1]{32}, shamt); val sh_val[32] <= shrl(X[rs1]{32}, shamt);
X[rd] <= sext(sh_val); X[rd] <= sext(sh_val);
@ -61,7 +61,7 @@ InsructionSet RV64IBase extends RV32IBase {
} }
SRAIW { SRAIW {
encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0011011; encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0011011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(rd != 0){ if(rd != 0){
val sh_val[32] <= shra(X[rs1]{32}, shamt); val sh_val[32] <= shra(X[rs1]{32}, shamt);
X[rd] <= sext(sh_val); X[rd] <= sext(sh_val);
@ -83,7 +83,7 @@ InsructionSet RV64IBase extends RV32IBase {
} }
SLLW { SLLW {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0111011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
val mask[32] <= 0x1f; val mask[32] <= 0x1f;
val count[32] <= X[rs2]{32} & mask; val count[32] <= X[rs2]{32} & mask;
@ -93,7 +93,7 @@ InsructionSet RV64IBase extends RV32IBase {
} }
SRLW { SRLW {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
val mask[32] <= 0x1f; val mask[32] <= 0x1f;
val count[32] <= X[rs2]{32} & mask; val count[32] <= X[rs2]{32} & mask;
@ -103,7 +103,7 @@ InsructionSet RV64IBase extends RV32IBase {
} }
SRAW { SRAW {
encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011; encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
val mask[32] <= 0x1f; val mask[32] <= 0x1f;
val count[32] <= X[rs2]{32} & mask; val count[32] <= X[rs2]{32} & mask;

View File

@ -1,41 +0,0 @@
import "RV64IBase.core_desc"
InsructionSet RV64M extends RV64IBase {
instructions{
MULW{
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
X[rd]<= X[rs1] * X[rs2];
}
}
DIVW {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
X[rd] <= X[rs1]s / X[rs2]s;
}
}
DIVUW {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
X[rd] <= X[rs1] / X[rs2];
}
}
REMW {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
X[rd] <= X[rs1]s % X[rs2]s;
}
}
REMUW {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
X[rd] <= X[rs1] % X[rs2];
}
}
}
}

View File

@ -0,0 +1,210 @@
import "RISCVBase.core_desc"
InsructionSet RV32A extends RISCVBase{
instructions{
LR.W {
encoding: b00010 | aq[0:0] | rl[0:0] | b00000 | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}";
if(rd!=0){
val offs[XLEN] <= X[rs1];
X[rd]<= sext(MEM[offs]{32}, XLEN);
RES[offs]{32}<=sext(-1, 32);
}
}
SC.W {
encoding: b00011 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)}";
val offs[XLEN] <= X[rs1];
val res1[32] <= RES[offs]{32};
if(res1!=0)
MEM[offs]{32} <= X[rs2];
if(rd!=0) X[rd]<= choose(res1!=zext(0, 32), 0, 1);
}
AMOSWAP.W{
encoding: b00001 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1];
if(rd!=0) X[rd]<=sext(MEM[offs]{32});
MEM[offs]{32}<=X[rs2];
}
AMOADD.W{
encoding: b00000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN]<=res1 + X[rs2];
MEM[offs]{32}<=res2;
}
AMOXOR.W{
encoding: b00100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN]<=res1 ^ X[rs2];
MEM[offs]{32}<=res2;
}
AMOAND.W{
encoding: b01100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN] <=res1 & X[rs2];
MEM[offs]{32}<=res2;
}
AMOOR.W {
encoding: b01000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN]<=res1 | X[rs2];
MEM[offs]{32}<=res2;
}
AMOMIN.W{
encoding: b10000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd] <= res1;
val res2[XLEN] <= choose(res1's > X[rs2]s, X[rs2], res1);
MEM[offs]{32} <= res2;
}
AMOMAX.W{
encoding: b10100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN]<= choose(res1's<X[rs2]s, X[rs2], res1);
MEM[offs]{32}<=res2;
}
AMOMINU.W{
encoding: b11000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1;
val res2[XLEN]<= choose(res1>X[rs2], X[rs2], res1);
MEM[offs]{32}<=res2;
}
AMOMAXU.W{
encoding: b11100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd] <= res1;
val res2[XLEN] <= choose(res1 < X[rs2], X[rs2], res1);
MEM[offs]{32} <= res2;
}
}
}
InsructionSet RV64A extends RV32A {
instructions{
LR.D {
encoding: b00010 | aq[0:0] | rl[0:0] | b00000 | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}";
if(rd!=0){
val offs[XLEN] <= X[rs1];
X[rd]<= sext(MEM[offs]{64}, XLEN);
RES[offs]{64}<=sext(-1, 64);
}
}
SC.D {
encoding: b00011 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)}";
val offs[XLEN] <= X[rs1];
val res[64] <= RES[offs];
if(res!=0){
MEM[offs]{64} <= X[rs2];
if(rd!=0) X[rd]<=0;
} else{
if(rd!=0) X[rd]<= 1;
}
}
AMOSWAP.D{
encoding: b00001 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1];
if(rd!=0) X[rd] <= sext(MEM[offs]{64});
MEM[offs]{64} <= X[rs2];
}
AMOADD.D{
encoding: b00000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd]<=res;
val res2[XLEN] <= res + X[rs2];
MEM[offs]{64}<=res2;
}
AMOXOR.D{
encoding: b00100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res;
val res2[XLEN] <= res ^ X[rs2];
MEM[offs]{64} <= res2;
}
AMOAND.D{
encoding: b01100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res;
val res2[XLEN] <= res & X[rs2];
MEM[offs]{64} <= res2;
}
AMOOR.D {
encoding: b01000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res;
val res2[XLEN] <= res | X[rs2];
MEM[offs]{64} <= res2;
}
AMOMIN.D{
encoding: b10000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1];
val res1[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res1;
val res2[XLEN] <= choose(res1's > X[rs2]s, X[rs2], res1);
MEM[offs]{64} <= res2;
}
AMOMAX.D{
encoding: b10100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res;
val res2[XLEN] <= choose(res s < X[rs2]s, X[rs2], res);
MEM[offs]{64} <= res2;
}
AMOMINU.D{
encoding: b11000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res;
val res2[XLEN] <= choose(res > X[rs2], X[rs2], res);
MEM[offs]{64} <= res2;
}
AMOMAXU.D{
encoding: b11100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1];
val res1[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res1;
val res2[XLEN] <= choose(res1 < X[rs2], X[rs2], res1);
MEM[offs]{64} <= res2;
}
}
}

View File

@ -1,50 +1,36 @@
import "RV32IBase.core_desc" import "RISCVBase.core_desc"
InsructionSet RV32IC extends RISCVBase{
InsructionSet RV32IC {
constants {
XLEN
}
address_spaces {
MEM[8]
}
registers {
[31:0] X[XLEN],
PC[XLEN](is_pc)
}
instructions{ instructions{
JALR(no_cont){ // overwriting the implementation if rv32i, alignment does not need to be word JALR(no_cont){ // overwriting the implementation if rv32i, alignment does not need to be word
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111; encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111;
args_disass: "x%rd$d, x%rs1$d, 0x%imm$x"; args_disass: "{name(rd)}, {name(rs1)}, {imm:#0x}";
val new_pc[XLEN] <= X[rs1]s + imm; val new_pc[XLEN] <= X[rs1]s + imm;
val align[XLEN] <= new_pc & 0x1;
if(align != 0){
raise(0, 0);
} else {
if(rd!=0) X[rd] <= PC+4; if(rd!=0) X[rd] <= PC+4;
PC<=new_pc & ~0x1; PC<=new_pc & ~0x1;
} }
}
C.ADDI4SPN { //(RES, imm=0) C.ADDI4SPN { //(RES, imm=0)
encoding: b000 | imm[5:4] | imm[9:6] | imm[2:2] | imm[3:3] | rd[2:0] | b00; encoding: b000 | imm[5:4] | imm[9:6] | imm[2:2] | imm[3:3] | rd[2:0] | b00;
args_disass: "x%rd$d, 0x%imm$05x"; args_disass: "{name(rd)}, {imm:#05x}";
if(imm == 0) raise(0, 2); if(imm == 0) raise(0, 2);
X[rd+8] <= X[2] + imm; X[rd+8] <= X[2] + imm;
} }
C.LW { // (RV32) C.LW { // (RV32)
encoding: b010 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00; encoding: b010 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00;
args_disass: "x(8+%rd$d), x(8+%rs1$d), 0x%uimm$05x"; args_disass: "{name(8+rd)}, {uimm:#05x}({name(8+rs1)})";
val offs[XLEN] <= X[rs1+8]+uimm; val offs[XLEN] <= X[rs1+8]+uimm;
X[rd+8] <= MEM[offs]{32}; X[rd+8] <= sext(MEM[offs]{32});
} }
C.SW {//(RV32) C.SW {//(RV32)
encoding: b110 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00; encoding: b110 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00;
args_disass: "x(8+%rs1$d), x(8+%rs2$d), 0x%uimm$05x"; args_disass: "{name(8+rs2)}, {uimm:#05x}({name(8+rs1)})";
val offs[XLEN] <= X[rs1+8]+uimm; val offs[XLEN] <= X[rs1+8]+uimm;
MEM[offs]{32} <= X[rs2+8]; MEM[offs]{32} <= X[rs2+8];
} }
C.ADDI {//(RV32) C.ADDI {//(RV32)
encoding:b000 | imm[5:5]s | rs1[4:0] | imm[4:0]s | b01; encoding:b000 | imm[5:5]s | rs1[4:0] | imm[4:0]s | b01;
args_disass: "x%rs1$d, 0x%imm$05x"; args_disass: "{name(rs1)}, {imm:#05x}";
X[rs1] <= X[rs1]'s + imm; X[rs1] <= X[rs1]'s + imm;
} }
C.NOP { C.NOP {
@ -53,118 +39,118 @@ InsructionSet RV32IC {
// C.JAL will be overwritten by C.ADDIW for RV64/128 // C.JAL will be overwritten by C.ADDIW for RV64/128
C.JAL(no_cont) {//(RV32) C.JAL(no_cont) {//(RV32)
encoding: b001 | imm[11:11]s | imm[4:4]s | imm[9:8]s | imm[10:10]s | imm[6:6]s | imm[7:7]s | imm[3:1]s | imm[5:5]s | b01; encoding: b001 | imm[11:11]s | imm[4:4]s | imm[9:8]s | imm[10:10]s | imm[6:6]s | imm[7:7]s | imm[3:1]s | imm[5:5]s | b01;
args_disass: "0x%imm$05x"; args_disass: "{imm:#05x}";
X[1] <= PC+2; X[1] <= PC+2;
PC<=PC's+imm; PC<=PC's+imm;
} }
C.LI {//(RV32) C.LI {//(RV32)
encoding:b010 | imm[5:5]s | rd[4:0] | imm[4:0]s | b01; encoding:b010 | imm[5:5]s | rd[4:0] | imm[4:0]s | b01;
args_disass: "x%rd$d, 0x%imm$05x"; args_disass: "{name(rd)}, {imm:#05x}";
if(rd == 0) raise(0, 2); //TODO: should it be handled as trap? if(rd == 0) raise(0, 2); //TODO: should it be handled as trap?
X[rd] <= imm; X[rd] <= imm;
} }
// order matters here as C.ADDI16SP overwrites C.LUI vor rd==2 // order matters here as C.ADDI16SP overwrites C.LUI vor rd==2
C.LUI {//(RV32) C.LUI {//(RV32)
encoding:b011 | imm[17:17] | rd[4:0] | imm[16:12]s | b01; encoding:b011 | imm[17:17] | rd[4:0] | imm[16:12]s | b01;
args_disass: "x%rd$d, 0x%imm$05x"; args_disass: "{name(rd)}, {imm:#05x}";
if(rd == 0) raise(0, 2); //TODO: should it be handled as trap? if(rd == 0) raise(0, 2); //TODO: should it be handled as trap?
if(imm == 0) raise(0, 2); //TODO: should it be handled as trap? if(imm == 0) raise(0, 2); //TODO: should it be handled as trap?
X[rd] <= imm; X[rd] <= imm;
} }
C.ADDI16SP {//(RV32) C.ADDI16SP {//(RV32)
encoding:b011 | imm[9:9]s | b00010 | imm[4:4]s | imm[6:6]s | imm[8:7]s | imm[5:5]s | b01; encoding:b011 | imm[9:9]s | b00010 | imm[4:4]s | imm[6:6]s | imm[8:7]s | imm[5:5]s | b01;
args_disass: "0x%imm$05x"; args_disass: "{imm:#05x}";
X[2] <= X[2]s + imm; X[2] <= X[2]s + imm;
} }
C.SRLI {//(RV32 nse) C.SRLI {//(RV32 nse)
encoding:b100 | b0 | b00 | rs1[2:0] | shamt[4:0] | b01; encoding:b100 | b0 | b00 | rs1[2:0] | shamt[4:0] | b01;
args_disass: "x(8+%rs1$d), %shamt$d"; args_disass: "{name(8+rs1)}, {shamt}";
val rs1_idx[5] <= rs1+8; val rs1_idx[5] <= rs1+8;
X[rs1_idx] <= shrl(X[rs1_idx], shamt); X[rs1_idx] <= shrl(X[rs1_idx], shamt);
} }
C.SRAI {//(RV32) C.SRAI {//(RV32)
encoding:b100 | b0 | b01 | rs1[2:0] | shamt[4:0] | b01; encoding:b100 | b0 | b01 | rs1[2:0] | shamt[4:0] | b01;
args_disass: "x(8+%rs1$d), %shamt$d"; args_disass: "{name(8+rs1)}, {shamt}";
val rs1_idx[5] <= rs1+8; val rs1_idx[5] <= rs1+8;
X[rs1_idx] <= shra(X[rs1_idx], shamt); X[rs1_idx] <= shra(X[rs1_idx], shamt);
} }
C.ANDI {//(RV32) C.ANDI {//(RV32)
encoding:b100 | imm[5:5] | b10 | rs1[2:0] | imm[4:0] | b01; encoding:b100 | imm[5:5]s | b10 | rs1[2:0] | imm[4:0]s | b01;
args_disass: "x(8+%rs1$d), 0x%imm$05x"; args_disass: "{name(8+rs1)}, {imm:#05x}";
val rs1_idx[5] <= rs1 + 8; val rs1_idx[5] <= rs1 + 8;
X[rs1_idx] <= X[rs1_idx] & imm; X[rs1_idx] <= X[rs1_idx]s & imm;
} }
C.SUB {//(RV32) C.SUB {//(RV32)
encoding:b100 | b0 | b11 | rd[2:0] | b00 | rs2[2:0] | b01; encoding:b100 | b0 | b11 | rd[2:0] | b00 | rs2[2:0] | b01;
args_disass: "x(8+%rd$d), x(8+%rs2$d)"; args_disass: "{name(8+rd)}, {name(8+rs2)}";
val rd_idx[5] <= rd + 8; val rd_idx[5] <= rd + 8;
X[rd_idx] <= X[rd_idx] - X[rs2 + 8]; X[rd_idx] <= X[rd_idx] - X[rs2 + 8];
} }
C.XOR {//(RV32) C.XOR {//(RV32)
encoding:b100 | b0 | b11 | rd[2:0] | b01 | rs2[2:0] | b01; encoding:b100 | b0 | b11 | rd[2:0] | b01 | rs2[2:0] | b01;
args_disass: "x(8+%rd$d), x(8+%rs2$d)"; args_disass: "{name(8+rd)}, {name(8+rs2)}";
val rd_idx[5] <= rd + 8; val rd_idx[5] <= rd + 8;
X[rd_idx] <= X[rd_idx] ^ X[rs2 + 8]; X[rd_idx] <= X[rd_idx] ^ X[rs2 + 8];
} }
C.OR {//(RV32) C.OR {//(RV32)
encoding:b100 | b0 | b11 | rd[2:0] | b10 | rs2[2:0] | b01; encoding:b100 | b0 | b11 | rd[2:0] | b10 | rs2[2:0] | b01;
args_disass: "x(8+%rd$d), x(8+%rs2$d)"; args_disass: "{name(8+rd)}, {name(8+rs2)}";
val rd_idx[5] <= rd + 8; val rd_idx[5] <= rd + 8;
X[rd_idx] <= X[rd_idx] | X[rs2 + 8]; X[rd_idx] <= X[rd_idx] | X[rs2 + 8];
} }
C.AND {//(RV32) C.AND {//(RV32)
encoding:b100 | b0 | b11 | rd[2:0] | b11 | rs2[2:0] | b01; encoding:b100 | b0 | b11 | rd[2:0] | b11 | rs2[2:0] | b01;
args_disass: "x(8+%rd$d), x(8+%rs2$d)"; args_disass: "{name(8+rd)}, {name(8+rs2)}";
val rd_idx[5] <= rd + 8; val rd_idx[5] <= rd + 8;
X[rd_idx] <= X[rd_idx] & X[rs2 + 8]; X[rd_idx] <= X[rd_idx] & X[rs2 + 8];
} }
C.J(no_cont) {//(RV32) C.J(no_cont) {//(RV32)
encoding:b101 | imm[11:11]s | imm[4:4]s | imm[9:8]s | imm[10:10]s | imm[6:6]s | imm[7:7]s | imm[3:1]s | imm[5:5]s | b01; encoding:b101 | imm[11:11]s | imm[4:4]s | imm[9:8]s | imm[10:10]s | imm[6:6]s | imm[7:7]s | imm[3:1]s | imm[5:5]s | b01;
args_disass: "0x%imm$05x"; args_disass: "{imm:#05x}";
PC<=PC's+imm; PC<=PC's+imm;
} }
C.BEQZ(no_cont,cond) {//(RV32) C.BEQZ(no_cont,cond) {//(RV32)
encoding:b110 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s |imm[2:1]s | imm[5:5]s | b01; encoding:b110 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s |imm[2:1]s | imm[5:5]s | b01;
args_disass: "x(8+%rs1$d), 0x%imm$05x"; args_disass: "{name(8+rs1)}, {imm:#05x}";
PC<=choose(X[rs1+8]==0, PC's+imm, PC+2); PC<=choose(X[rs1+8]==0, PC's+imm, PC+2);
} }
C.BNEZ(no_cont,cond) {//(RV32) C.BNEZ(no_cont,cond) {//(RV32)
encoding:b111 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s | imm[2:1]s | imm[5:5]s | b01; encoding:b111 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s | imm[2:1]s | imm[5:5]s | b01;
args_disass: "x(8+%rs1$d), 0x%imm$05x"; args_disass: "{name(8+rs1)}, {imm:#05x}";
PC<=choose(X[rs1+8]!=0, PC's+imm, PC+2); PC<=choose(X[rs1+8]!=0, PC's+imm, PC+2);
} }
C.SLLI {//(RV32) C.SLLI {//(RV32)
encoding:b000 | b0 | rs1[4:0] | shamt[4:0] | b10; encoding:b000 | b0 | rs1[4:0] | shamt[4:0] | b10;
args_disass: "x%rs1$d, %shamt$d"; args_disass: "{name(rs1)}, {shamt}";
if(rs1 == 0) raise(0, 2); if(rs1 == 0) raise(0, 2);
X[rs1] <= shll(X[rs1], shamt); X[rs1] <= shll(X[rs1], shamt);
} }
C.LWSP {// C.LWSP {//
encoding:b010 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10; encoding:b010 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10;
args_disass: "x%rd$d, sp, 0x%uimm$05x"; args_disass: "{name(rd)}, sp, {uimm:#05x}";
val offs[XLEN] <= X[2] + uimm; val offs[XLEN] <= X[2] + uimm;
X[rd] <= MEM[offs]{32}; X[rd] <= sext(MEM[offs]{32});
} }
// order matters as C.JR is a special case of C.MV // order matters as C.JR is a special case of C.MV
C.MV {//(RV32) C.MV {//(RV32)
encoding:b100 | b0 | rd[4:0] | rs2[4:0] | b10; encoding:b100 | b0 | rd[4:0] | rs2[4:0] | b10;
args_disass: "x%rd$d, x%rs2$d"; args_disass: "{name(rd)}, {name(rs2)}";
X[rd] <= X[rs2]; X[rd] <= X[rs2];
} }
C.JR(no_cont) {//(RV32) C.JR(no_cont) {//(RV32)
encoding:b100 | b0 | rs1[4:0] | b00000 | b10; encoding:b100 | b0 | rs1[4:0] | b00000 | b10;
args_disass: "x%rs1$d"; args_disass: "{name(rs1)}";
PC <= X[rs1]; PC <= X[rs1];
} }
// order matters as C.EBREAK is a special case of C.JALR which is a special case of C.ADD // order matters as C.EBREAK is a special case of C.JALR which is a special case of C.ADD
C.ADD {//(RV32) C.ADD {//(RV32)
encoding:b100 | b1 | rd[4:0] | rs2[4:0] | b10; encoding:b100 | b1 | rd[4:0] | rs2[4:0] | b10;
args_disass: "x%rd$d, x%rs2$d"; args_disass: "{name(rd)}, {name(rs2)}";
X[rd] <= X[rd] + X[rs2]; X[rd] <= X[rd] + X[rs2];
} }
C.JALR(no_cont) {//(RV32) C.JALR(no_cont) {//(RV32)
encoding:b100 | b1 | rs1[4:0] | b00000 | b10; encoding:b100 | b1 | rs1[4:0] | b00000 | b10;
args_disass: "x%rs1$d"; args_disass: "{name(rs1)}";
X[1] <= PC+2; X[1] <= PC+2;
PC<=X[rs1]; PC<=X[rs1];
} }
@ -174,7 +160,7 @@ InsructionSet RV32IC {
} }
C.SWSP {// C.SWSP {//
encoding:b110 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10; encoding:b110 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10;
args_disass: "x2+0x%uimm$05x, x%rs2$d"; args_disass: "{name(rs2)}, {uimm:#05x}(sp)";
val offs[XLEN] <= X[2] + uimm; val offs[XLEN] <= X[2] + uimm;
MEM[offs]{32} <= X[rs2]; MEM[offs]{32} <= X[rs2];
} }
@ -187,19 +173,15 @@ InsructionSet RV32IC {
InsructionSet RV32FC extends RV32IC{ InsructionSet RV32FC extends RV32IC{
constants { constants {
XLEN, FLEN FLEN
}
address_spaces {
MEM[8]
} }
registers { registers {
[31:0] X[XLEN],
[31:0] F[FLEN] [31:0] F[FLEN]
} }
instructions{ instructions{
C.FLW { C.FLW {
encoding: b011 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00; encoding: b011 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00;
args_disass:"f(8+%rd$d), %uimm%(x(8+%rs1$d))"; args_disass:"f(8+{rd}), {uimm}({name(8+rs1)})";
val offs[XLEN] <= X[rs1+8]+uimm; val offs[XLEN] <= X[rs1+8]+uimm;
val res[32] <= MEM[offs]{32}; val res[32] <= MEM[offs]{32};
if(FLEN==32) if(FLEN==32)
@ -211,13 +193,13 @@ InsructionSet RV32FC extends RV32IC{
} }
C.FSW { C.FSW {
encoding: b111 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00; encoding: b111 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00;
args_disass:"f(8+%rs2$d), %uimm%(x(8+%rs1$d))"; args_disass:"f(8+{rs2}), {uimm}({name(8+rs1)})";
val offs[XLEN] <= X[rs1+8]+uimm; val offs[XLEN] <= X[rs1+8]+uimm;
MEM[offs]{32}<=F[rs2+8]{32}; MEM[offs]{32}<=F[rs2+8]{32};
} }
C.FLWSP { C.FLWSP {
encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10; encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10;
args_disass:"f%rd$d, %uimm%(x2)"; args_disass:"f{rd}, {uimm}(x2)";
val offs[XLEN] <= X[2]+uimm; val offs[XLEN] <= X[2]+uimm;
val res[32] <= MEM[offs]{32}; val res[32] <= MEM[offs]{32};
if(FLEN==32) if(FLEN==32)
@ -229,7 +211,7 @@ InsructionSet RV32FC extends RV32IC{
} }
C.FSWSP { C.FSWSP {
encoding:b111 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10; encoding:b111 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10;
args_disass:"f%rs2$d, %uimm%(x2), "; args_disass:"f{rs2}, {uimm}(x2), ";
val offs[XLEN] <= X[2]+uimm; val offs[XLEN] <= X[2]+uimm;
MEM[offs]{32}<=F[rs2]{32}; MEM[offs]{32}<=F[rs2]{32};
} }
@ -238,19 +220,15 @@ InsructionSet RV32FC extends RV32IC{
InsructionSet RV32DC extends RV32IC{ InsructionSet RV32DC extends RV32IC{
constants { constants {
XLEN, FLEN FLEN
}
address_spaces {
MEM[8]
} }
registers { registers {
[31:0] X[XLEN],
[31:0] F[FLEN] [31:0] F[FLEN]
} }
instructions{ instructions{
C.FLD { //(RV32/64) C.FLD { //(RV32/64)
encoding: b001 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00; encoding: b001 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00;
args_disass:"f(8+%rd$d), %uimm%(x(8+%rs1$d))"; args_disass:"f(8+{rd}), {uimm}({name(8+rs1)})";
val offs[XLEN] <= X[rs1+8]+uimm; val offs[XLEN] <= X[rs1+8]+uimm;
val res[64] <= MEM[offs]{64}; val res[64] <= MEM[offs]{64};
if(FLEN==64) if(FLEN==64)
@ -262,13 +240,13 @@ InsructionSet RV32DC extends RV32IC{
} }
C.FSD { //(RV32/64) C.FSD { //(RV32/64)
encoding: b101 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00; encoding: b101 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00;
args_disass:"f(8+%rs2$d), %uimm%(x(8+%rs1$d))"; args_disass:"f(8+{rs2}), {uimm}({name(8+rs1)})";
val offs[XLEN] <= X[rs1+8]+uimm; val offs[XLEN] <= X[rs1+8]+uimm;
MEM[offs]{64}<=F[rs2+8]{64}; MEM[offs]{64}<=F[rs2+8]{64};
} }
C.FLDSP {//(RV32/64) C.FLDSP {//(RV32/64)
encoding:b001 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10; encoding:b001 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10;
args_disass:"f%rd$d, %uimm%(x2)"; args_disass:"f{rd}, {uimm}(x2)";
val offs[XLEN] <= X[2]+uimm; val offs[XLEN] <= X[2]+uimm;
val res[64] <= MEM[offs]{64}; val res[64] <= MEM[offs]{64};
if(FLEN==64) if(FLEN==64)
@ -280,7 +258,7 @@ InsructionSet RV32DC extends RV32IC{
} }
C.FSDSP {//(RV32/64) C.FSDSP {//(RV32/64)
encoding:b101 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10; encoding:b101 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10;
args_disass:"f%rs2$d, %uimm%(x2), "; args_disass:"f{rs2}, {uimm}(x2), ";
val offs[XLEN] <= X[2]+uimm; val offs[XLEN] <= X[2]+uimm;
MEM[offs]{64}<=F[rs2]{64}; MEM[offs]{64}<=F[rs2]{64};
} }
@ -288,65 +266,94 @@ InsructionSet RV32DC extends RV32IC{
} }
InsructionSet RV64IC extends RV32IC { InsructionSet RV64IC extends RV32IC {
constants {
XLEN
}
address_spaces {
MEM[8]
}
registers {
[31:0] X[XLEN],
PC[XLEN](is_pc)
}
instructions{ instructions{
C.LD {//(RV64/128) C.LD {//(RV64/128)
encoding:b011 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00; encoding:b011 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00;
args_disass: "{name(8+rd)}, {uimm},({name(8+rs1)})";
val offs[XLEN] <= X[rs1+8] + uimm;
X[rd+8]<=sext(MEM[offs]{64});
} }
C.SD { //(RV64/128) C.SD { //(RV64/128)
encoding:b111 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00; encoding:b111 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00;
args_disass: "{name(8+rs2)}, {uimm},({name(8+rs1)})";
val offs[XLEN] <= X[rs1+8] + uimm;
MEM[offs]{64} <= X[rs2+8];
} }
C.SUBW {//(RV64/128, RV32 res) C.SUBW {//(RV64/128, RV32 res)
encoding:b100 | b1 | b11 | rd[2:0] | b00 | rs2[2:0] | b01; encoding:b100 | b1 | b11 | rd[2:0] | b00 | rs2[2:0] | b01;
args_disass: "x%rd$d, sp, 0x%imm$05x"; args_disass: "{name(8+rd)}, {name(8+rd)}, {name(8+rs2)}";
val res[32] <= X[rd+8]{32} - X[rs2+8]{32};
X[rd+8] <= sext(res);
} }
C.ADDW {//(RV64/128 RV32 res) C.ADDW {//(RV64/128 RV32 res)
encoding:b100 | b1 | b11 | rd[2:0] | b01 | rs2[2:0] | b01; encoding:b100 | b1 | b11 | rd[2:0] | b01 | rs2[2:0] | b01;
args_disass: "x%rd$d, sp, 0x%imm$05x"; args_disass: "{name(8+rd)}, {name(8+rd)}, {name(8+rs2)}";
val res[32] <= X[rd+8]{32} + X[rs2+8]{32};
X[rd+8] <= sext(res);
} }
C.ADDIW {//(RV64/128) C.ADDIW {//(RV64/128)
encoding:b001 | imm[5:5] | rs1[4:0] | imm[4:0] | b01; encoding:b001 | imm[5:5]s | rs1[4:0] | imm[4:0]s | b01;
args_disass: "{name(rs1)}, {imm:#05x}";
if(rs1 != 0){
val res[32] <= X[rs1]{32}'s + imm;
X[rs1] <= sext(res);
} }
C.SRLI64 {//(RV32/64/128)
encoding:b100 | b0 | b00 | rs1[2:0] | b00000 | b01;
} }
C.SRAI64 {//(RV32/64/128) C.SRLI {//(RV64)
encoding:b100 | b0 | b01 | rs1[2:0] | b00000 | b01; encoding:b100 | shamt[5:5] | b00 | rs1[2:0] | shamt[4:0] | b01;
args_disass: "{name(8+rs1)}, {shamt}";
val rs1_idx[5] <= rs1+8;
X[rs1_idx] <= shrl(X[rs1_idx], shamt);
} }
C.SLLI64 {//(RV128 RV32/64) C.SRAI {//(RV64)
encoding:b000 | b0 | rs1[4:0] | b00000 | b10; encoding:b100 | shamt[5:5] | b01 | rs1[2:0] | shamt[4:0] | b01;
args_disass: "{name(8+rs1)}, {shamt}";
val rs1_idx[5] <= rs1+8;
X[rs1_idx] <= shra(X[rs1_idx], shamt);
}
C.SLLI {//(RV64)
encoding:b000 | shamt[5:5] | rs1[4:0] | shamt[4:0] | b10;
args_disass: "{name(rs1)}, {shamt}";
if(rs1 == 0) raise(0, 2);
X[rs1] <= shll(X[rs1], shamt);
} }
C.LDSP {//(RV64/128 C.LDSP {//(RV64/128
encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10; encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10;
args_disass: "x%rd$d, sp, 0x%imm$05x"; args_disass:"{name(rd)}, {uimm}(sp)";
val offs[XLEN] <= X[2] + uimm;
if(rd!=0) X[rd]<=sext(MEM[offs]{64});
} }
C.SDSP {//(RV64/128) C.SDSP {//(RV64/128)
encoding:b111 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10; encoding:b111 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10;
args_disass:"{name(rs2)}, {uimm}(sp)";
val offs[XLEN] <= X[2] + uimm;
MEM[offs]{64} <= X[rs2];
} }
} }
} }
InsructionSet RV128IC extends RV64IC { InsructionSet RV128IC extends RV64IC {
constants {
XLEN
}
address_spaces {
MEM[8]
}
registers {
[31:0] X[XLEN],
PC[XLEN](is_pc)
}
instructions{ instructions{
C.SRLI {//(RV128)
encoding:b100 | shamt[5:5] | b00 | rs1[2:0] | shamt[4:0] | b01;
args_disass: "{name(8+rs1)}, {shamt}";
val rs1_idx[5] <= rs1+8;
X[rs1_idx] <= shrl(X[rs1_idx], shamt);
}
C.SRAI {//(RV128)
encoding:b100 | shamt[5:5] | b01 | rs1[2:0] | shamt[4:0] | b01;
args_disass: "{name(8+rs1)}, {shamt}";
val rs1_idx[5] <= rs1+8;
X[rs1_idx] <= shra(X[rs1_idx], shamt);
}
C.SLLI {//(RV128)
encoding:b000 | shamt[5:5] | rs1[4:0] | shamt[4:0] | b10;
args_disass: "{name(rs1)}, {shamt}";
if(rs1 == 0) raise(0, 2);
X[rs1] <= shll(X[rs1], shamt);
}
C.LQ { //(RV128) C.LQ { //(RV128)
encoding:b001 | uimm[5:4] | uimm[8:8] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00; encoding:b001 | uimm[5:4] | uimm[8:8] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00;
} }

View File

@ -1,6 +1,6 @@
import "RV32IBase.core_desc" import "RISCVBase.core_desc"
InsructionSet RV32D extends RV32IBase{ InsructionSet RV32D extends RISCVBase{
constants { constants {
FLEN, FFLAG_MASK := 0x1f FLEN, FFLAG_MASK := 0x1f
} }
@ -10,7 +10,7 @@ InsructionSet RV32D extends RV32IBase{
instructions{ instructions{
FLD { FLD {
encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000111; encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000111;
args_disass:"f%rd$d, %imm%(x%rs1$d)"; args_disass:"f{rd}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
val res[64] <= MEM[offs]{64}; val res[64] <= MEM[offs]{64};
if(FLEN==64) if(FLEN==64)
@ -22,13 +22,13 @@ InsructionSet RV32D extends RV32IBase{
} }
FSD { FSD {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100111; encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100111;
args_disass:"f%rs2$d, %imm%(x%rs1$d)"; args_disass:"f{rs2}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{64}<=F[rs2]{64}; MEM[offs]{64}<=F[rs2]{64};
} }
FMADD.D { FMADD.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011; encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f; //F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(0, 64), choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(0, 64), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -42,7 +42,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FMSUB.D { FMSUB.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111; encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f; //F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -56,7 +56,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FNMADD.D { FNMADD.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111; encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f; //F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -70,7 +70,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FNMSUB.D { FNMSUB.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011; encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f; //F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -84,7 +84,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FADD.D { FADD.D {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f + F[rs2]f; // F[rd]f <= F[rs1]f + F[rs2]f;
val res[64] <= fdispatch_fadd_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fadd_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -98,7 +98,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FSUB.D { FSUB.D {
encoding: b0000101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0000101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f - F[rs2]f; // F[rd]f <= F[rs1]f - F[rs2]f;
val res[64] <= fdispatch_fsub_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fsub_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -112,7 +112,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FMUL.D { FMUL.D {
encoding: b0001001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0001001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f * F[rs2]f; // F[rd]f <= F[rs1]f * F[rs2]f;
val res[64] <= fdispatch_fmul_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fmul_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -126,7 +126,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FDIV.D { FDIV.D {
encoding: b0001101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0001101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f / F[rs2]f; // F[rd]f <= F[rs1]f / F[rs2]f;
val res[64] <= fdispatch_fdiv_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fdiv_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -140,7 +140,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FSQRT.D { FSQRT.D {
encoding: b0101101 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0101101 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"{name(rd)}, f{rs1}";
//F[rd]f<=sqrt(F[rs1]f); //F[rd]f<=sqrt(F[rs1]f);
val res[64] <= fdispatch_fsqrt_d(F[rs1]{64}, choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fsqrt_d(F[rs1]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -154,8 +154,11 @@ InsructionSet RV32D extends RV32IBase{
} }
FSGNJ.D { FSGNJ.D {
encoding: b0010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; encoding: b0010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
val res[64] <= (F[rs1]{64} & 0x7fffffff) | (F[rs2]{64} & 0x80000000); val ONE[64] <= 1;
val MSK1[64] <= ONE<<63;
val MSK2[64] <= MSK1-1;
val res[64] <= (F[rs1]{64} & MSK2) | (F[rs2]{64} & MSK1);
if(FLEN==64) if(FLEN==64)
F[rd] <= res; F[rd] <= res;
else { // NaN boxing else { // NaN boxing
@ -165,8 +168,11 @@ InsructionSet RV32D extends RV32IBase{
} }
FSGNJN.D { FSGNJN.D {
encoding: b0010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; encoding: b0010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
val res[64] <= (F[rs1]{64} & 0x7fffffff) | (~F[rs2]{64} & 0x80000000); val ONE[64] <= 1;
val MSK1[64] <= ONE<<63;
val MSK2[64] <= MSK1-1;
val res[64] <= (F[rs1]{64} & MSK2) | (~F[rs2]{64} & MSK1);
if(FLEN==64) if(FLEN==64)
F[rd] <= res; F[rd] <= res;
else { // NaN boxing else { // NaN boxing
@ -176,8 +182,10 @@ InsructionSet RV32D extends RV32IBase{
} }
FSGNJX.D { FSGNJX.D {
encoding: b0010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; encoding: b0010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
val res[64] <= F[rs1]{64} ^ (F[rs2]{64} & 0x80000000); val ONE[64] <= 1;
val MSK1[64] <= ONE<<63;
val res[64] <= F[rs1]{64} ^ (F[rs2]{64} & MSK1);
if(FLEN==64) if(FLEN==64)
F[rd] <= res; F[rd] <= res;
else { // NaN boxing else { // NaN boxing
@ -187,7 +195,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FMIN.D { FMIN.D {
encoding: b0010101 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; encoding: b0010101 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
//F[rd]f<= choose(F[rs1]f<F[rs2]f, F[rs1]f, F[rs2]f); //F[rd]f<= choose(F[rs1]f<F[rs2]f, F[rs1]f, F[rs2]f);
val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32)); val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32));
if(FLEN==64) if(FLEN==64)
@ -201,7 +209,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FMAX.D { FMAX.D {
encoding: b0010101 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; encoding: b0010101 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
//F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f); //F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f);
val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32)); val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32));
if(FLEN==64) if(FLEN==64)
@ -215,7 +223,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FCVT.S.D { FCVT.S.D {
encoding: b0100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d"; args_disass:"f{rd}, f{rs1}";
val res[32] <= fdispatch_fconv_d2f(F[rs1], rm{8}); val res[32] <= fdispatch_fconv_d2f(F[rs1], rm{8});
// NaN boxing // NaN boxing
val upper[FLEN] <= -1; val upper[FLEN] <= -1;
@ -223,7 +231,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FCVT.D.S { FCVT.D.S {
encoding: b0100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d"; args_disass:"f{rd}, f{rs1}";
val res[64] <= fdispatch_fconv_f2d(F[rs1]{32}, rm{8}); val res[64] <= fdispatch_fconv_f2d(F[rs1]{32}, rm{8});
if(FLEN==64){ if(FLEN==64){
F[rd] <= res; F[rd] <= res;
@ -234,48 +242,49 @@ InsructionSet RV32D extends RV32IBase{
} }
FEQ.D { FEQ.D {
encoding: b1010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; encoding: b1010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32)); X[rd]<=zext(fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32)));
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FLT.D { FLT.D {
encoding: b1010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; encoding: b1010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(2, 32)); X[rd]<=zext(fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(2, 32)));
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FLE.D { FLE.D {
encoding: b1010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; encoding: b1010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32)); X[rd]<=zext(fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32)));
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FCLASS.D { FCLASS.D {
encoding: b1110001 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011; encoding: b1110001 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"{name(rd)}, f{rs1}";
X[rd]<=fdispatch_fclass_d(F[rs1]{64}); X[rd]<=fdispatch_fclass_d(F[rs1]{64});
} }
FCVT.W.D { FCVT.W.D {
encoding: b1100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b1100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"{name(rd)}, f{rs1}";
X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(0, 32), rm{8}), XLEN); X[rd]<= sext(fdispatch_fcvt_64_32(F[rs1]{64}, zext(0, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FCVT.WU.D { FCVT.WU.D {
encoding: b1100001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b1100001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"{name(rd)}, f{rs1}";
X[rd]<= zext(fdispatch_fcvt_d(F[rs1]{64}, zext(1, 32), rm{8}), XLEN); //FIXME: should be zext accodring to spec but needs to be sext according to tests
X[rd]<= sext(fdispatch_fcvt_64_32(F[rs1]{64}, zext(1, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FCVT.D.W { FCVT.D.W {
encoding: b1101001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b1101001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, x%rs1$d"; args_disass:"f{rd}, {name(rs1)}";
val res[64] <= fdispatch_fcvt_d(sext(X[rs1],64), zext(2, 32), rm{8}); val res[64] <= fdispatch_fcvt_32_64(sext(X[rs1]{32},64), zext(2, 32), rm{8});
if(FLEN==64) if(FLEN==64)
F[rd] <= res; F[rd] <= res;
else { // NaN boxing else { // NaN boxing
@ -285,8 +294,8 @@ InsructionSet RV32D extends RV32IBase{
} }
FCVT.D.WU { FCVT.D.WU {
encoding: b1101001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b1101001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, x%rs1$d"; args_disass:"f{rd}, {name(rs1)}";
val res[64] <=fdispatch_fcvt_d(zext(X[rs1],64), zext(3,32), rm{8}); val res[64] <=fdispatch_fcvt_32_64(zext(X[rs1]{32},64), zext(3,32), rm{8});
if(FLEN==64) if(FLEN==64)
F[rd] <= res; F[rd] <= res;
else { // NaN boxing else { // NaN boxing
@ -296,3 +305,56 @@ InsructionSet RV32D extends RV32IBase{
} }
} }
} }
InsructionSet RV64D extends RV32D{
instructions{
FCVT.L.D {
encoding: b1100001 | b00010 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(0, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.LU.D {
encoding: b1100001 | b00011 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(1, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.D.L {
encoding: b1101001 | b00010 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, {name(rs1)}";
val res[64] <= fdispatch_fcvt_d(sext(X[rs1],64), zext(2, 32), rm{8});
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FCVT.D.LU {
encoding: b1101001 | b00011 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, {name(rs1)}";
val res[64] <=fdispatch_fcvt_d(zext(X[rs1],64), zext(3,32), rm{8});
if(FLEN==64)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<64) | res;
}
}
FMV.X.D {
encoding: b1110001 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
X[rd]<=sext(F[rs1]);
}
FMV.D.X {
encoding: b1111001 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f{rd}, {name(rs1)}";
F[rd] <= zext(X[rs1]);
}
}
}

View File

@ -0,0 +1,400 @@
import "RV32I.core_desc"
InsructionSet RV32F extends RV32I{
constants {
FLEN, FFLAG_MASK := 0x1f
}
registers {
[31:0] F[FLEN], FCSR[32]
}
instructions{
FLW {
encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000111;
args_disass:"f{rd}, {imm}(x{rs1})";
val offs[XLEN] <= X[rs1]'s + imm;
val res[32] <= MEM[offs]{32};
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FSW {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b010 | imm[4:0]s | b0100111;
args_disass:"f{rs2}, {imm}(x{rs1})";
val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{32}<=F[rs2]{32};
}
FMADD.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011;
args_disass:"x{rd}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f;
if(FLEN==32)
F[rd] <= fdispatch_fmadd_s(F[rs1], F[rs2], F[rs3], zext(0, 32), choose(rm<7, rm{8}, FCSR{8}));
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val frs3[32] <= fdispatch_unbox_s(F[rs3]);
val res[32] <= fdispatch_fmadd_s(frs1, frs2, frs3, zext(0, 32), choose(rm<7, rm{8}, FCSR{8}));
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FMSUB.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111;
args_disass:"x{rd}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f;
if(FLEN==32)
F[rd] <= fdispatch_fmadd_s(F[rs1], F[rs2], F[rs3], zext(1, 32), choose(rm<7, rm{8}, FCSR{8}));
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val frs3[32] <= fdispatch_unbox_s(F[rs3]);
val res[32] <= fdispatch_fmadd_s(frs1, frs2, frs3, zext(1, 32), choose(rm<7, rm{8}, FCSR{8}));
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FNMADD.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111;
args_disass:"x{rd}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f;
if(FLEN==32)
F[rd] <= fdispatch_fmadd_s(F[rs1], F[rs2], F[rs3], zext(2, 32), choose(rm<7, rm{8}, FCSR{8}));
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val frs3[32] <= fdispatch_unbox_s(F[rs3]);
val res[32] <= fdispatch_fmadd_s(frs1, frs2, frs3, zext(2, 32), choose(rm<7, rm{8}, FCSR{8}));
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FNMSUB.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011;
args_disass:"x{rd}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f;
if(FLEN==32)
F[rd] <= fdispatch_fmadd_s(F[rs1], F[rs2], F[rs3], zext(3, 32), choose(rm<7, rm{8}, FCSR{8}));
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val frs3[32] <= fdispatch_unbox_s(F[rs3]);
val res[32] <= fdispatch_fmadd_s(frs1, frs2, frs3, zext(3, 32), choose(rm<7, rm{8}, FCSR{8}));
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FADD.S {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f + F[rs2]f;
if(FLEN==32)
F[rd] <= fdispatch_fadd_s(F[rs1], F[rs2], choose(rm<7, rm{8}, FCSR{8}));
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val res[32] <= fdispatch_fadd_s(frs1, frs2, choose(rm<7, rm{8}, FCSR{8}));
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FSUB.S {
encoding: b0000100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f - F[rs2]f;
if(FLEN==32)
F[rd] <= fdispatch_fsub_s(F[rs1], F[rs2], choose(rm<7, rm{8}, FCSR{8}));
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val res[32] <= fdispatch_fsub_s(frs1, frs2, choose(rm<7, rm{8}, FCSR{8}));
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FMUL.S {
encoding: b0001000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f * F[rs2]f;
if(FLEN==32)
F[rd] <= fdispatch_fmul_s(F[rs1], F[rs2], choose(rm<7, rm{8}, FCSR{8}));
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val res[32] <= fdispatch_fmul_s(frs1, frs2, choose(rm<7, rm{8}, FCSR{8}));
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FDIV.S {
encoding: b0001100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f / F[rs2]f;
if(FLEN==32)
F[rd] <= fdispatch_fdiv_s(F[rs1], F[rs2], choose(rm<7, rm{8}, FCSR{8}));
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val res[32] <= fdispatch_fdiv_s(frs1, frs2, choose(rm<7, rm{8}, FCSR{8}));
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FSQRT.S {
encoding: b0101100 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}";
//F[rd]f<=sqrt(F[rs1]f);
if(FLEN==32)
F[rd] <= fdispatch_fsqrt_s(F[rs1], choose(rm<7, rm{8}, FCSR{8}));
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val res[32] <= fdispatch_fsqrt_s(frs1, choose(rm<7, rm{8}, FCSR{8}));
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FSGNJ.S {
encoding: b0010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
if(FLEN==32)
F[rd] <= (F[rs1] & 0x7fffffff) | (F[rs2] & 0x80000000);
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val res[32] <= (frs1 & 0x7fffffff) | (frs2 & 0x80000000);
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FSGNJN.S {
encoding: b0010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
if(FLEN==32)
F[rd] <= (F[rs1] & 0x7fffffff) | (~F[rs2] & 0x80000000);
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val res[32] <= (frs1 & 0x7fffffff) | (~frs2 & 0x80000000);
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FSGNJX.S {
encoding: b0010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
if(FLEN==32)
F[rd] <= F[rs1] ^ (F[rs2] & 0x80000000);
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val res[32] <= frs1 ^ (frs2 & 0x80000000);
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FMIN.S {
encoding: b0010100 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
//F[rd]f<= choose(F[rs1]f<F[rs2]f, F[rs1]f, F[rs2]f);
if(FLEN==32)
F[rd] <= fdispatch_fsel_s(F[rs1], F[rs2], zext(0, 32));
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val res[32] <= fdispatch_fsel_s(frs1, frs2, zext(0, 32));
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FMAX.S {
encoding: b0010100 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f{rd}, f{rs1}, f{rs2}";
//F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f);
if(FLEN==32)
F[rd] <= fdispatch_fsel_s(F[rs1], F[rs2], zext(1, 32));
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
val res[32] <= fdispatch_fsel_s(frs1, frs2, zext(1, 32));
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.W.S {
encoding: b1100000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
if(FLEN==32)
X[rd] <= sext(fdispatch_fcvt_s(F[rs1], zext(0, 32), rm{8}), XLEN);
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
X[rd]<= sext(fdispatch_fcvt_s(frs1, zext(0, 32), rm{8}), XLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.WU.S {
encoding: b1100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
//FIXME: according to the spec it should be zero-extended not sign extended
if(FLEN==32)
X[rd]<= sext(fdispatch_fcvt_s(F[rs1], zext(1, 32), rm{8}), XLEN);
else { // NaN boxing
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
X[rd]<= sext(fdispatch_fcvt_s(frs1, zext(1, 32), rm{8}), XLEN);
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FEQ.S {
encoding: b1010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}, f{rs2}";
if(FLEN==32)
X[rd]<=zext(fdispatch_fcmp_s(F[rs1], F[rs2], zext(0, 32)));
else {
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
X[rd]<=zext(fdispatch_fcmp_s(frs1, frs2, zext(0, 32)));
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FLT.S {
encoding: b1010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}, f{rs2}";
if(FLEN==32)
X[rd]<=zext(fdispatch_fcmp_s(F[rs1], F[rs2], zext(2, 32)));
else {
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
X[rd]<=zext(fdispatch_fcmp_s(frs1, frs2, zext(2, 32)));
}
X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(2, 32));
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FLE.S {
encoding: b1010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}, f{rs2}";
if(FLEN==32)
X[rd]<=zext(fdispatch_fcmp_s(F[rs1], F[rs2], zext(1, 32)));
else {
val frs1[32] <= fdispatch_unbox_s(F[rs1]);
val frs2[32] <= fdispatch_unbox_s(F[rs2]);
X[rd]<=zext(fdispatch_fcmp_s(frs1, frs2, zext(1, 32)));
}
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCLASS.S {
encoding: b1110000 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
X[rd]<=fdispatch_fclass_s(fdispatch_unbox_s(F[rs1]));
}
FCVT.S.W {
encoding: b1101000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, {name(rs1)}";
if(FLEN==32)
F[rd] <= fdispatch_fcvt_s(X[rs1]{32}, zext(2, 32), rm{8});
else { // NaN boxing
val res[32] <= fdispatch_fcvt_s(X[rs1]{32}, zext(2, 32), rm{8});
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FCVT.S.WU {
encoding: b1101000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, {name(rs1)}";
if(FLEN==32)
F[rd] <=fdispatch_fcvt_s(X[rs1]{32}, zext(3,32), rm{8});
else { // NaN boxing
val res[32] <=fdispatch_fcvt_s(X[rs1]{32}, zext(3,32), rm{8});
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FMV.X.W {
encoding: b1110000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"{name(rd)}, f{rs1}";
X[rd]<=sext(F[rs1]{32});
}
FMV.W.X {
encoding: b1111000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f{rd}, {name(rs1)}";
if(FLEN==32)
F[rd] <= X[rs1]{32};
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(X[rs1]{32}, FLEN);
}
}
}
}
InsructionSet RV64F extends RV32F{
instructions{
FCVT.L.S { // fp to 64bit signed integer
encoding: b1100000 | b00010 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x{rd}, f{rs1}";
val res[64] <= fdispatch_fcvt_32_64(fdispatch_unbox_s(F[rs1]), zext(0, 32), rm{8});
X[rd]<= sext(res);
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.LU.S { // fp to 64bit unsigned integer
encoding: b1100000 | b00011 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x{rd}, f{rs1}";
val res[64] <= fdispatch_fcvt_32_64(fdispatch_unbox_s(F[rs1]), zext(1, 32), rm{8});
X[rd]<= zext(res);
val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
}
FCVT.S.L { // 64bit signed int to to fp
encoding: b1101000 | b00010 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, x{rs1}";
val res[32] <= fdispatch_fcvt_64_32(X[rs1], zext(2, 32));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
FCVT.S.LU { // 64bit unsigned int to to fp
encoding: b1101000 | b00011 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f{rd}, x{rs1}";
val res[32] <=fdispatch_fcvt_64_32(X[rs1], zext(3,32));
if(FLEN==32)
F[rd] <= res;
else { // NaN boxing
val upper[FLEN] <= -1;
F[rd] <= (upper<<32) | zext(res, FLEN);
}
}
}
}

View File

@ -0,0 +1,160 @@
import "RISCVBase.core_desc"
InsructionSet RV32M extends RISCVBase {
constants {
MAXLEN:=128
}
instructions{
MUL{
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN);
X[rd]<= zext(res , XLEN);
}
}
MULH {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
val res[MAXLEN] <= sext(X[rs1], MAXLEN) * sext(X[rs2], MAXLEN);
X[rd]<= zext(res >> XLEN, XLEN);
}
}
MULHSU {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
val res[MAXLEN] <= sext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN);
X[rd]<= zext(res >> XLEN, XLEN);
}
}
MULHU {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN);
X[rd]<= zext(res >> XLEN, XLEN);
}
}
DIV {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
if(X[rs2]!=0){
val M1[XLEN] <= -1;
val XLM1[8] <= XLEN-1;
val ONE[XLEN] <= 1;
val MMIN[XLEN] <= ONE<<XLM1;
if(X[rs1]==MMIN && X[rs2]==M1)
X[rd] <= MMIN;
else
X[rd] <= X[rs1]s / X[rs2]s;
}else
X[rd] <= -1;
}
}
DIVU {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
if(X[rs2]!=0)
X[rd] <= X[rs1] / X[rs2];
else
X[rd] <= -1;
}
}
REM {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
if(X[rs2]!=0) {
val M1[XLEN] <= -1; // constant -1
val XLM1[32] <= XLEN-1;
val ONE[XLEN] <= 1;
val MMIN[XLEN] <= ONE<<XLM1; // -2^(XLEN-1)
if(X[rs1]==MMIN && X[rs2]==M1)
X[rd] <= 0;
else
X[rd] <= X[rs1]'s % X[rs2]'s;
} else
X[rd] <= X[rs1];
}
}
REMU {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0110011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
if(X[rs2]!=0)
X[rd] <= X[rs1] % X[rs2];
else
X[rd] <= X[rs1];
}
}
}
}
InsructionSet RV64M extends RV32M {
instructions{
MULW{
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0111011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
X[rd]<= sext(X[rs1]{32} * X[rs2]{32});
}
}
DIVW {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0111011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
if(X[rs2]!=0){
val M1[32] <= -1;
val ONE[32] <= 1;
val MMIN[32] <= ONE<<31;
if(X[rs1]{32}==MMIN && X[rs2]{32}==M1)
X[rd] <= -1<<31;
else
X[rd] <= sext(X[rs1]{32}s / X[rs2]{32}s);
}else
X[rd] <= -1;
}
}
DIVUW {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
if(X[rs2]{32}!=0)
X[rd] <= sext(X[rs1]{32} / X[rs2]{32});
else
X[rd] <= -1;
}
}
REMW {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0111011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
if(X[rs2]!=0) {
val M1[32] <= -1; // constant -1
val ONE[32] <= 1;
val MMIN[32] <= ONE<<31; // -2^(XLEN-1)
if(X[rs1]{32}==MMIN && X[rs2]==M1)
X[rd] <= 0;
else
X[rd] <= sext(X[rs1]{32}s % X[rs2]{32}s);
} else
X[rd] <= sext(X[rs1]{32});
}
}
REMUW {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0111011;
args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){
if(X[rs2]{32}!=0)
X[rd] <= sext(X[rs1]{32} % X[rs2]{32});
else
X[rd] <= sext(X[rs1]{32});
}
}
}
}

View File

@ -1,15 +1,12 @@
import "RV32IBase.core_desc" import "RV32I.core_desc"
import "RV32M.core_desc" import "RV64I.core_desc"
import "RV32A.core_desc" import "RVM.core_desc"
import "RV32C.core_desc" import "RVA.core_desc"
import "RV32F.core_desc" import "RVC.core_desc"
import "RV32D.core_desc" import "RVF.core_desc"
import "RV64IBase.core_desc" import "RVD.core_desc"
//import "RV64M.core_desc"
import "RV64A.core_desc"
Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32IC { Core RV32IMAC provides RV32I, RV32M, RV32A, RV32IC {
template:"vm_riscv.in.cpp";
constants { constants {
XLEN:=32; XLEN:=32;
PCLEN:=32; PCLEN:=32;
@ -21,7 +18,7 @@ Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32IC {
} }
} }
Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC, RV32D, RV32DC { Core RV32GC provides RV32I, RV32M, RV32A, RV32F, RV32D, RV32IC, RV32FC, RV32DC {
constants { constants {
XLEN:=32; XLEN:=32;
FLEN:=64; FLEN:=64;
@ -34,16 +31,28 @@ Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC, RV32D, RV32
} }
} }
Core RV64I provides RV64I {
Core RV64IA provides RV64IBase, RV64A, RV32A {
template:"vm_riscv.in.cpp";
constants { constants {
XLEN:=64; XLEN:=64;
PCLEN:=64; PCLEN:=64;
// definitions for the architecture wrapper // definitions for the architecture wrapper
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA // XL ZYXWVUTSRQPONMLKJIHGFEDCBA
MISA_VAL:=0b10000000000001000000000100000001; MISA_VAL:=0b10000000000001000000000100000000;
PGSIZE := 0x1000; //1 << 12; PGSIZE := 0x1000; //1 << 12;
PGMASK := 0xfff; //PGSIZE-1 PGMASK := 0xfff; //PGSIZE-1
} }
} }
Core RV64GC provides RV64I, RV64M, RV64A, RV64F, RV64D, RV64IC, RV32FC, RV32DC {
constants {
XLEN:=64;
FLEN:=64;
PCLEN:=64;
// definitions for the architecture wrapper
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
MISA_VAL:=0b01000000000101000001000100101101;
PGSIZE := 0x1000; //1 << 12;
PGMASK := 0xfff; //PGSIZE-1
}
}

View File

@ -1,59 +1,100 @@
//////////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// Copyright (C) 2017, MINRES Technologies GmbH * Copyright (C) 2017, 2018 MINRES Technologies GmbH
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// *
// 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// *
// 3. Neither the name of the copyright holder nor the names of its contributors * 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
// *
//////////////////////////////////////////////////////////////////////////////// *******************************************************************************/
<% <%
import com.minres.coredsl.coreDsl.Register import com.minres.coredsl.coreDsl.Register
import com.minres.coredsl.coreDsl.RegisterFile import com.minres.coredsl.coreDsl.RegisterFile
import com.minres.coredsl.coreDsl.RegisterAlias
def getTypeSize(size){ def getTypeSize(size){
if(size > 32) 64 else if(size > 16) 32 else if(size > 8) 16 else 8 if(size > 32) 64 else if(size > 16) 32 else if(size > 8) 16 else 8
} }
def getOriginalName(reg){
if( reg.original instanceof RegisterFile) {
if( reg.index != null ) {
return reg.original.name+generator.generateHostCode(reg.index)
} else {
return reg.original.name
}
} else if(reg.original instanceof Register){
return reg.original.name
}
}
def getRegisterNames(){
def regNames = []
allRegs.each { reg ->
if( reg instanceof RegisterFile) {
(reg.range.right..reg.range.left).each{
regNames+=reg.name.toLowerCase()+it
}
} else if(reg instanceof Register){
regNames+=reg.name.toLowerCase()
}
}
return regNames
}
def getRegisterAliasNames(){
def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]}
return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg ->
if( reg instanceof RegisterFile) {
return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() }
} else if(reg instanceof Register){
regMap[reg.name]?:reg.name.toLowerCase()
}
}.flatten()
}
%> %>
#ifndef _${coreDef.name.toUpperCase()}_H_ #ifndef _${coreDef.name.toUpperCase()}_H_
#define _${coreDef.name.toUpperCase()}_H_ #define _${coreDef.name.toUpperCase()}_H_
#include <array>
#include <iss/arch/traits.h>
#include <iss/arch_if.h> #include <iss/arch_if.h>
#include <iss/vm_if.h> #include <iss/vm_if.h>
#include <iss/arch/traits.h>
#include <array>
namespace iss { namespace iss {
namespace arch { namespace arch {
struct ${coreDef.name.toLowerCase()}; struct ${coreDef.name.toLowerCase()};
template<> template <> struct traits<${coreDef.name.toLowerCase()}> {
struct traits<${coreDef.name.toLowerCase()}> {
constexpr static char const* const core_type = "${coreDef.name}"; constexpr static char const* const core_type = "${coreDef.name}";
static constexpr std::array<const char*, ${getRegisterNames().size}> reg_names{
{"${getRegisterNames().join("\", \"")}"}};
static constexpr std::array<const char*, ${getRegisterAliasNames().size}> reg_aliases{
{"${getRegisterAliasNames().join("\", \"")}"}};
enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}}; enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}};
constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0}; constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0};
@ -74,7 +115,12 @@ struct traits<${coreDef.name.toLowerCase()}> {
PENDING_TRAP, PENDING_TRAP,
MACHINE_STATE, MACHINE_STATE,
LAST_BRANCH, LAST_BRANCH,
ICOUNT ICOUNT<%
allRegs.each { reg ->
if(reg instanceof RegisterAlias){ def aliasname=getOriginalName(reg)%>,
${reg.name} = ${aliasname}<%
}
}%>
}; };
using reg_t = uint${regDataWidth}_t; using reg_t = uint${regDataWidth}_t;
@ -87,15 +133,11 @@ struct traits<${coreDef.name.toLowerCase()}> {
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
constexpr static unsigned reg_bit_width(unsigned r) { static constexpr std::array<const uint32_t, ${regSizes.size}> reg_bit_widths{
constexpr std::array<const uint32_t, ${regSizes.size}> ${coreDef.name}_reg_size{{${regSizes.join(",")}}}; {${regSizes.join(",")}}};
return ${coreDef.name}_reg_size[r];
}
constexpr static unsigned reg_byte_offset(unsigned r) { static constexpr std::array<const uint32_t, ${regOffsets.size}> reg_byte_offsets{
constexpr std::array<const uint32_t, ${regOffsets.size}> ${coreDef.name}_reg_byte_offset{{${regOffsets.join(",")}}}; {${regOffsets.join(",")}}};
return ${coreDef.name}_reg_byte_offset[r];
}
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
@ -126,11 +168,12 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
/// deprecated /// deprecated
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
uint64_t get_icount() { return reg.icount;} inline uint64_t get_icount() { return reg.icount; }
inline bool should_stop() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t& addr){ inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<${coreDef.name.toLowerCase()}>::MEM || if (addr.space != traits<${coreDef.name.toLowerCase()}>::MEM || addr.type == iss::address_type::PHYSICAL ||
addr.type == iss::address_type::PHYSICAL ||
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL) { addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL) {
return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask); return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask);
} else } else
@ -141,8 +184,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
inline inline uint32_t get_last_branch() { return reg.last_branch; }
uint32_t get_last_branch(){return reg.last_branch;}
protected: protected:
struct ${coreDef.name}_regs {<% struct ${coreDef.name}_regs {<%

View File

@ -1,35 +1,73 @@
//////////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// Copyright (C) 2017,2018 MINRES Technologies GmbH * Copyright (C) 2017, 2018 MINRES Technologies GmbH
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// *
// 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// *
// 3. Neither the name of the copyright holder nor the names of its contributors * 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
// *
//////////////////////////////////////////////////////////////////////////////// *******************************************************************************/
<%
import com.minres.coredsl.coreDsl.Register
import com.minres.coredsl.coreDsl.RegisterFile
import com.minres.coredsl.coreDsl.RegisterAlias
def getOriginalName(reg){
if( reg.original instanceof RegisterFile) {
if( reg.index != null ) {
return reg.original.name+generator.generateHostCode(reg.index)
} else {
return reg.original.name
}
} else if(reg.original instanceof Register){
return reg.original.name
}
}
def getRegisterNames(){
def regNames = []
allRegs.each { reg ->
if( reg instanceof RegisterFile) {
(reg.range.right..reg.range.left).each{
regNames+=reg.name.toLowerCase()+it
}
} else if(reg instanceof Register){
regNames+=reg.name.toLowerCase()
}
}
return regNames
}
def getRegisterAliasNames(){
def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]}
return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg ->
if( reg instanceof RegisterFile) {
return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() }
} else if(reg instanceof Register){
regMap[reg.name]?:reg.name.toLowerCase()
}
}.flatten()
}
%>
#include "util/ities.h" #include "util/ities.h"
#include <util/logging.h> #include <util/logging.h>
@ -43,18 +81,22 @@ extern "C" {
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#include <fstream>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <fstream>
using namespace iss::arch; using namespace iss::arch;
constexpr std::array<const char*, ${getRegisterNames().size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_names;
constexpr std::array<const char*, ${getRegisterAliasNames().size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_aliases;
constexpr std::array<const uint32_t, ${regSizes.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_bit_widths;
constexpr std::array<const uint32_t, ${regOffsets.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_byte_offsets;
${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { ${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() {
reg.icount = 0; reg.icount = 0;
} }
${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}(){ ${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default;
}
void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { void ${coreDef.name.toLowerCase()}::reset(uint64_t address) {
for(size_t i=0; i<traits<${coreDef.name.toLowerCase()}>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<${coreDef.name.toLowerCase()}>::reg_t),0)); for(size_t i=0; i<traits<${coreDef.name.toLowerCase()}>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<${coreDef.name.toLowerCase()}>::reg_t),0));
@ -62,6 +104,7 @@ void ${coreDef.name.toLowerCase()}::reset(uint64_t address) {
reg.NEXT_PC=reg.PC; reg.NEXT_PC=reg.PC;
reg.trap_state=0; reg.trap_state=0;
reg.machine_state=0x0; reg.machine_state=0x0;
reg.icount=0;
} }
uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() {

View File

@ -1,56 +1,52 @@
//////////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// Copyright (C) 2017, MINRES Technologies GmbH * Copyright (C) 2017, 2018 MINRES Technologies GmbH
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// *
// 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// *
// 3. Neither the name of the copyright holder nor the names of its contributors * 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
// *
// Contributors: *******************************************************************************/
// eyck@minres.com - initial API and implementation
//
//
////////////////////////////////////////////////////////////////////////////////
#include <iss/arch/${coreDef.name.toLowerCase()}.h> #include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/arch/riscv_hart_msu_vp.h> #include <iss/arch/riscv_hart_msu_vp.h>
#include <iss/debugger/gdb_session.h> #include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h> #include <iss/debugger/server.h>
#include <iss/iss.h> #include <iss/iss.h>
#include <iss/vm_base.h> #include <iss/llvm/vm_base.h>
#include <util/logging.h> #include <util/logging.h>
#include <boost/format.hpp> #include <fmt/format.h>
#include <iss/debugger/riscv_target_adapter.h>
#include <array> #include <array>
#include <iss/debugger/riscv_target_adapter.h>
namespace iss { namespace iss {
namespace vm { namespace vm {
namespace fp_impl { namespace fp_impl {
void add_fp_functions_2_module(llvm::Module *, unsigned); void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned);
} }
} }
@ -58,10 +54,11 @@ namespace ${coreDef.name.toLowerCase()} {
using namespace iss::arch; using namespace iss::arch;
using namespace llvm; using namespace llvm;
using namespace iss::debugger; using namespace iss::debugger;
using namespace iss::vm::llvm;
template <typename ARCH> class vm_impl : public vm::vm_base<ARCH> { template <typename ARCH> class vm_impl : public vm_base<ARCH> {
public: public:
using super = typename vm::vm_base<ARCH>; using super = typename iss::vm::llvm::vm_base<ARCH>;
using virt_addr_t = typename super::virt_addr_t; using virt_addr_t = typename super::virt_addr_t;
using phys_addr_t = typename super::phys_addr_t; using phys_addr_t = typename super::phys_addr_t;
using code_word_t = typename super::code_word_t; using code_word_t = typename super::code_word_t;
@ -73,33 +70,34 @@ public:
void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; }
target_adapter_if *accquire_target_adapter(server_if *srv) { target_adapter_if *accquire_target_adapter(server_if *srv) override {
debugger_if::dbg_enabled = true; debugger_if::dbg_enabled = true;
if (vm::vm_base<ARCH>::tgt_adapter == nullptr) if (vm_base<ARCH>::tgt_adapter == nullptr)
vm::vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch()); vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch());
return vm::vm_base<ARCH>::tgt_adapter; return vm_base<ARCH>::tgt_adapter;
} }
protected: protected:
using vm::vm_base<ARCH>::get_reg_ptr; using vm_base<ARCH>::get_reg_ptr;
template <typename T> inline llvm::ConstantInt *size(T type) { inline const char *name(size_t index){return traits<ARCH>::reg_aliases.at(index);}
return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits()));
template <typename T> inline ConstantInt *size(T type) {
return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits()));
} }
void setup_module(llvm::Module* m) override { void setup_module(Module* m) override {
super::setup_module(m); super::setup_module(m);
vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE); iss::vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE, traits<ARCH>::XLEN);
} }
inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, unsigned size) { inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) {
return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
} }
std::tuple<vm::continuation_e, llvm::BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &, std::tuple<continuation_e, BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override;
llvm::BasicBlock *) override;
void gen_leave_behavior(llvm::BasicBlock *leave_blk) override; void gen_leave_behavior(BasicBlock *leave_blk) override;
void gen_raise_trap(uint16_t trap_id, uint16_t cause); void gen_raise_trap(uint16_t trap_id, uint16_t cause);
@ -107,16 +105,16 @@ protected:
void gen_wait(unsigned type); void gen_wait(unsigned type);
void gen_trap_behavior(llvm::BasicBlock *) override; void gen_trap_behavior(BasicBlock *) override;
void gen_trap_check(llvm::BasicBlock *bb); void gen_trap_check(BasicBlock *bb);
inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) { inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
return this->builder.CreateLoad(get_reg_ptr(i), false); return this->builder.CreateLoad(get_reg_ptr(i), false);
} }
inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) {
llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val), Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val),
this->get_type(traits<ARCH>::XLEN)); this->get_type(traits<ARCH>::XLEN));
this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
} }
@ -128,9 +126,9 @@ protected:
enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) };
using this_class = vm_impl<ARCH>; using this_class = vm_impl<ARCH>;
using compile_func = std::tuple<vm::continuation_e, llvm::BasicBlock *> (this_class::*)(virt_addr_t &pc, using compile_func = std::tuple<continuation_e, BasicBlock *> (this_class::*)(virt_addr_t &pc,
code_word_t instr, code_word_t instr,
llvm::BasicBlock *bb); BasicBlock *bb);
std::array<compile_func, LUT_SIZE> lut; std::array<compile_func, LUT_SIZE> lut;
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10; std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
@ -196,15 +194,14 @@ private:
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
/* instruction ${idx}: ${instr.name} */ /* instruction ${idx}: ${instr.name} */
std::tuple<vm::continuation_e, llvm::BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){<%instr.code.eachLine{%> std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){<%instr.code.eachLine{%>
${it}<%}%> ${it}<%}%>
} }
<%}%> <%}%>
/**************************************************************************** /****************************************************************************
* end opcode definitions * end opcode definitions
****************************************************************************/ ****************************************************************************/
std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, std::tuple<continuation_e, BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) {
llvm::BasicBlock *bb) {
this->gen_sync(iss::PRE_SYNC, instr_descr.size()); this->gen_sync(iss::PRE_SYNC, instr_descr.size());
this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true), this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true),
get_reg_ptr(traits<ARCH>::PC), true); get_reg_ptr(traits<ARCH>::PC), true);
@ -216,7 +213,7 @@ private:
this->gen_raise_trap(0, 2); // illegal instruction trap this->gen_raise_trap(0, 2); // illegal instruction trap
this->gen_sync(iss::POST_SYNC, instr_descr.size()); this->gen_sync(iss::POST_SYNC, instr_descr.size());
this->gen_trap_check(this->leave_blk); this->gen_trap_check(this->leave_blk);
return std::make_tuple(iss::vm::BRANCH, nullptr); return std::make_tuple(BRANCH, nullptr);
} }
}; };
@ -229,7 +226,7 @@ template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
template <typename ARCH> template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm::vm_base<ARCH>(core, core_id, cluster_id) { : vm_base<ARCH>(core, core_id, cluster_id) {
qlut[0] = lut_00.data(); qlut[0] = lut_00.data();
qlut[1] = lut_01.data(); qlut[1] = lut_01.data();
qlut[2] = lut_10.data(); qlut[2] = lut_10.data();
@ -241,27 +238,24 @@ vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
} }
template <typename ARCH> template <typename ARCH>
std::tuple<vm::continuation_e, llvm::BasicBlock *> std::tuple<continuation_e, BasicBlock *>
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, llvm::BasicBlock *this_block) { vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) {
// we fetch at max 4 byte, alignment is 2 // we fetch at max 4 byte, alignment is 2
enum {TRAP_ID=1<<16};
code_word_t insn = 0; code_word_t insn = 0;
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK; const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
phys_addr_t paddr(pc); phys_addr_t paddr(pc);
try { auto *const data = (uint8_t *)&insn;
uint8_t *const data = (uint8_t *)&insn;
paddr = this->core.v2p(pc); paddr = this->core.v2p(pc);
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
auto res = this->core.read(paddr, 2, data); auto res = this->core.read(paddr, 2, data);
if (res != iss::Ok) throw trap_access(1, pc.val); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
if ((insn & 0x3) == 0x3) { // this is a 32bit instruction if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
} }
} else { } else {
auto res = this->core.read(paddr, 4, data); auto res = this->core.read(paddr, 4, data);
if (res != iss::Ok) throw trap_access(1, pc.val); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
}
} catch (trap_access &ta) {
throw trap_access(ta.id, pc.val);
} }
if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
// curr pc on stack // curr pc on stack
@ -274,7 +268,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
return (this->*f)(pc, insn, this_block); return (this->*f)(pc, insn, this_block);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(llvm::BasicBlock *leave_blk) { template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(BasicBlock *leave_blk) {
this->builder.SetInsertPoint(leave_blk); this->builder.SetInsertPoint(leave_blk);
this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false)); this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false));
} }
@ -286,9 +280,7 @@ template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, ui
} }
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) { template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
std::vector<llvm::Value *> args{ std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) };
this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)),
};
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8); auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8);
this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false); this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
@ -296,30 +288,27 @@ template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
} }
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) { template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
std::vector<llvm::Value *> args{ std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) };
this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)),
};
this->builder.CreateCall(this->mod->getFunction("wait"), args); this->builder.CreateCall(this->mod->getFunction("wait"), args);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock *trap_blk) { template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) {
this->builder.SetInsertPoint(trap_blk); this->builder.SetInsertPoint(trap_blk);
auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true); auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits<ARCH>::LAST_BRANCH), false); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
std::vector<llvm::Value *> args{ get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
this->core_ptr, std::vector<Value *> args{this->core_ptr, this->adj_to64(trap_state_val),
this->adj_to64(trap_state_val),
this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))}; this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))};
this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); this->builder.CreateCall(this->mod->getFunction("enter_trap"), args);
auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false); auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder.CreateRet(trap_addr_val); this->builder.CreateRet(trap_addr_val);
} }
template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBlock *bb) { template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(BasicBlock *bb) {
auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true); auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true);
this->gen_cond_branch(this->builder.CreateICmp( this->gen_cond_branch(this->builder.CreateICmp(
ICmpInst::ICMP_EQ, v, ICmpInst::ICMP_EQ, v,
llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))),
bb, this->trap_blk, 1); bb, this->trap_blk, 1);
} }
@ -327,10 +316,9 @@ template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBl
template <> template <>
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
std::unique_ptr<${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>> ret = auto ret = new ${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*core, dump);
std::make_unique<${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>>(*core, dump); if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret.get(), port); return std::unique_ptr<vm_if>(ret);
return ret;
} }
} // namespace iss } // namespace iss

View File

@ -1,309 +0,0 @@
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#include <iss/arch/CORE_DEF_NAME.h>
#include <iss/arch/riscv_hart_msu_vp.h>
#include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h>
#include <iss/iss.h>
#include <iss/vm_base.h>
#include <util/logging.h>
#include <boost/format.hpp>
#include <array>
#include <iss/debugger/riscv_target_adapter.h>
namespace iss {
namespace CORE_DEF_NAME {
using namespace iss::arch;
using namespace llvm;
using namespace iss::debugger;
template <typename ARCH> class vm_impl : public vm::vm_base<ARCH> {
public:
using super = typename vm::vm_base<ARCH>;
using virt_addr_t = typename super::virt_addr_t;
using phys_addr_t = typename super::phys_addr_t;
using code_word_t = typename super::code_word_t;
using addr_t = typename super::addr_t;
vm_impl();
vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0);
void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; }
target_adapter_if *accquire_target_adapter(server_if *srv) {
debugger_if::dbg_enabled = true;
if (vm::vm_base<ARCH>::tgt_adapter == nullptr)
vm::vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch());
return vm::vm_base<ARCH>::tgt_adapter;
}
protected:
using vm::vm_base<ARCH>::get_reg_ptr;
template <typename T> inline llvm::ConstantInt *size(T type) {
return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits()));
}
inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal,
unsigned size) const {
return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
}
std::tuple<vm::continuation_e, llvm::BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &,
llvm::BasicBlock *) override;
void gen_leave_behavior(llvm::BasicBlock *leave_blk) override;
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
void gen_leave_trap(unsigned lvl);
void gen_wait(unsigned type);
void gen_trap_behavior(llvm::BasicBlock *) override;
void gen_trap_check(llvm::BasicBlock *bb);
inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) {
return this->builder.CreateLoad(get_reg_ptr(i), false);
}
inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) {
llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val),
this->get_type(traits<ARCH>::XLEN));
this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
}
// some compile time constants
// enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 };
enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 };
enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 };
enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) };
using this_class = vm_impl<ARCH>;
using compile_func = std::tuple<vm::continuation_e, llvm::BasicBlock *> (this_class::*)(virt_addr_t &pc,
code_word_t instr,
llvm::BasicBlock *bb);
std::array<compile_func, LUT_SIZE> lut;
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
std::array<compile_func, LUT_SIZE> lut_11;
std::array<compile_func *, 4> qlut;
std::array<const uint32_t, 4> lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}};
void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[],
compile_func f) {
if (pos < 0) {
lut[idx] = f;
} else {
auto bitmask = 1UL << pos;
if ((mask & bitmask) == 0) {
expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f);
} else {
if ((valid & bitmask) == 0) {
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f);
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f);
} else {
auto new_val = idx << 1;
if ((value & bitmask) != 0) new_val++;
expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f);
}
}
}
}
inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); }
uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) {
if (pos >= 0) {
auto bitmask = 1UL << pos;
if ((mask & bitmask) == 0) {
lut_val = extract_fields(pos - 1, val, mask, lut_val);
} else {
auto new_val = lut_val << 1;
if ((val & bitmask) != 0) new_val++;
lut_val = extract_fields(pos - 1, val, mask, new_val);
}
}
return lut_val;
}
private:
/****************************************************************************
* start opcode definitions
****************************************************************************/
struct InstructionDesriptor {
size_t length;
uint32_t value;
uint32_t mask;
compile_func op;
};
/* «start generated code» */
std::array<InstructionDesriptor, 0> instr_descr = {{}};
/* «end generated code» */
/****************************************************************************
* end opcode definitions
****************************************************************************/
std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr,
llvm::BasicBlock *bb) {
this->gen_sync(iss::PRE_SYNC, instr_descr.size());
this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true),
get_reg_ptr(traits<ARCH>::PC), true);
this->builder.CreateStore(
this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::ICOUNT), true),
this->gen_const(64U, 1)),
get_reg_ptr(traits<ARCH>::ICOUNT), true);
pc = pc + ((instr & 3) == 3 ? 4 : 2);
this->gen_raise_trap(0, 2); // illegal instruction trap
this->gen_sync(iss::POST_SYNC, instr_descr.size());
this->gen_trap_check(this->leave_blk);
return std::make_tuple(iss::vm::BRANCH, nullptr);
}
};
template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
volatile CODE_WORD x = insn;
insn = 2 * x;
}
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm::vm_base<ARCH>(core, core_id, cluster_id) {
qlut[0] = lut_00.data();
qlut[1] = lut_01.data();
qlut[2] = lut_10.data();
qlut[3] = lut_11.data();
for (auto instr : instr_descr) {
auto quantrant = instr.value & 0x3;
expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op);
}
}
template <typename ARCH>
std::tuple<vm::continuation_e, llvm::BasicBlock *>
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, llvm::BasicBlock *this_block) {
// we fetch at max 4 byte, alignment is 2
code_word_t insn = 0;
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
phys_addr_t paddr(pc);
try {
uint8_t *const data = (uint8_t *)&insn;
paddr = this->core.v2p(pc);
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
auto res = this->core.read(paddr, 2, data);
if (res != iss::Ok) throw trap_access(1, pc.val);
if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
}
} else {
auto res = this->core.read(paddr, 4, data);
if (res != iss::Ok) throw trap_access(1, pc.val);
}
} catch (trap_access &ta) {
throw trap_access(ta.id, pc.val);
}
if (insn == 0x0000006f || (insn & 0xffff) == 0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
// curr pc on stack
typename vm_impl<ARCH>::processing_pc_entry addr(*this, pc, paddr);
++inst_cnt;
auto lut_val = extract_fields(insn);
auto f = qlut[insn & 0x3][lut_val];
if (f == nullptr) {
f = &this_class::illegal_intruction;
}
return (this->*f)(pc, insn, this_block);
}
template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(llvm::BasicBlock *leave_blk) {
this->builder.SetInsertPoint(leave_blk);
this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false));
}
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
}
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
std::vector<llvm::Value *> args{
this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)),
};
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8);
this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
}
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
std::vector<llvm::Value *> args{
this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)),
};
this->builder.CreateCall(this->mod->getFunction("wait"), args);
}
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock *trap_blk) {
this->builder.SetInsertPoint(trap_blk);
auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
std::vector<llvm::Value *> args{this->core_ptr, this->adj_to64(trap_state_val),
this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))};
this->builder.CreateCall(this->mod->getFunction("enter_trap"), args);
auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder.CreateRet(trap_addr_val);
}
template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBlock *bb) {
auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true);
this->gen_cond_branch(this->builder.CreateICmp(
ICmpInst::ICMP_EQ, v,
llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))),
bb, this->trap_blk, 1);
}
} // namespace CORE_DEF_NAME
template <>
std::unique_ptr<vm_if> create<arch::CORE_DEF_NAME>(arch::CORE_DEF_NAME *core, unsigned short port, bool dump) {
std::unique_ptr<CORE_DEF_NAME::vm_impl<arch::CORE_DEF_NAME>> ret =
std::make_unique<CORE_DEF_NAME::vm_impl<arch::CORE_DEF_NAME>>(*core, dump);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret.get(), port);
return ret;
}
} // namespace iss

View File

@ -40,6 +40,7 @@
#include "iss/instrumentation_if.h" #include "iss/instrumentation_if.h"
#include "iss/log_categories.h" #include "iss/log_categories.h"
#include "iss/vm_if.h" #include "iss/vm_if.h"
#include <fmt/format.h>
#include <array> #include <array>
#include <elfio/elfio.hpp> #include <elfio/elfio.hpp>
#include <iomanip> #include <iomanip>
@ -478,10 +479,8 @@ public:
void wait_until(uint64_t flags) override; void wait_until(uint64_t flags) override;
void disass_output(uint64_t pc, const std::string instr) override { void disass_output(uint64_t pc, const std::string instr) override {
std::stringstream s; CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]",
s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0') pc, instr, lvl[this->reg.machine_state], (reg_t)state.mstatus, this->reg.icount);
<< std::setw(sizeof(reg_t) * 2) << (reg_t)state.mstatus << std::dec << ";c:" << this->reg.icount << "]";
CLOG(INFO, disass) << "0x" << std::setw(16) << std::setfill('0') << std::hex << pc << "\t\t" << instr << "\t" << s.str();
}; };
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }

View File

@ -1,53 +1,59 @@
//////////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// Copyright (C) 2017, MINRES Technologies GmbH * Copyright (C) 2017, 2018 MINRES Technologies GmbH
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// *
// 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// *
// 3. Neither the name of the copyright holder nor the names of its contributors * 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
// *
//////////////////////////////////////////////////////////////////////////////// *******************************************************************************/
#ifndef _RV32GC_H_ #ifndef _RV32GC_H_
#define _RV32GC_H_ #define _RV32GC_H_
#include <array>
#include <iss/arch/traits.h>
#include <iss/arch_if.h> #include <iss/arch_if.h>
#include <iss/vm_if.h> #include <iss/vm_if.h>
#include <iss/arch/traits.h>
#include <array>
namespace iss { namespace iss {
namespace arch { namespace arch {
struct rv32gc; struct rv32gc;
template<> template <> struct traits<rv32gc> {
struct traits<rv32gc> {
constexpr static char const* const core_type = "RV32GC"; constexpr static char const* const core_type = "RV32GC";
static constexpr std::array<const char*, 66> reg_names{
{"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}};
static constexpr std::array<const char*, 66> reg_aliases{
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}};
enum constants {XLEN=32, FLEN=64, PCLEN=32, MISA_VAL=0b1000000000101000001000100101101, PGSIZE=0x1000, PGMASK=0xfff}; enum constants {XLEN=32, FLEN=64, PCLEN=32, MISA_VAL=0b1000000000101000001000100101101, PGSIZE=0x1000, PGMASK=0xfff};
constexpr static unsigned FP_REGS_SIZE = 64; constexpr static unsigned FP_REGS_SIZE = 64;
@ -125,7 +131,39 @@ struct traits<rv32gc> {
PENDING_TRAP, PENDING_TRAP,
MACHINE_STATE, MACHINE_STATE,
LAST_BRANCH, LAST_BRANCH,
ICOUNT ICOUNT,
ZERO = X0,
RA = X1,
SP = X2,
GP = X3,
TP = X4,
T0 = X5,
T1 = X6,
T2 = X7,
S0 = X8,
S1 = X9,
A0 = X10,
A1 = X11,
A2 = X12,
A3 = X13,
A4 = X14,
A5 = X15,
A6 = X16,
A7 = X17,
S2 = X18,
S3 = X19,
S4 = X20,
S5 = X21,
S6 = X22,
S7 = X23,
S8 = X24,
S9 = X25,
S10 = X26,
S11 = X27,
T3 = X28,
T4 = X29,
T5 = X30,
T6 = X31
}; };
using reg_t = uint32_t; using reg_t = uint32_t;
@ -138,15 +176,11 @@ struct traits<rv32gc> {
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
constexpr static unsigned reg_bit_width(unsigned r) { static constexpr std::array<const uint32_t, 72> reg_bit_widths{
constexpr std::array<const uint32_t, 72> RV32GC_reg_size{{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,32,32,64}}; {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,32,32,64}};
return RV32GC_reg_size[r];
}
constexpr static unsigned reg_byte_offset(unsigned r) { static constexpr std::array<const uint32_t, 73> reg_byte_offsets{
constexpr std::array<const uint32_t, 73> RV32GC_reg_byte_offset{{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,396,400,404,408,412,416,424}}; {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,396,400,404,408,412,416,424}};
return RV32GC_reg_byte_offset[r];
}
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
@ -177,13 +211,12 @@ struct rv32gc: public arch_if {
/// deprecated /// deprecated
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
uint64_t get_icount() { return reg.icount;} inline uint64_t get_icount() { return reg.icount; }
inline bool should_stop() { return interrupt_sim; } inline bool should_stop() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t& addr){ inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<rv32gc>::MEM || if (addr.space != traits<rv32gc>::MEM || addr.type == iss::address_type::PHYSICAL ||
addr.type == iss::address_type::PHYSICAL ||
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL) { addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL) {
return phys_addr_t(addr.access, addr.space, addr.val&traits<rv32gc>::addr_mask); return phys_addr_t(addr.access, addr.space, addr.val&traits<rv32gc>::addr_mask);
} else } else
@ -194,8 +227,7 @@ struct rv32gc: public arch_if {
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
inline inline uint32_t get_last_branch() { return reg.last_branch; }
uint32_t get_last_branch(){return reg.last_branch;}
protected: protected:
struct RV32GC_regs { struct RV32GC_regs {

View File

@ -30,6 +30,7 @@
* *
*******************************************************************************/ *******************************************************************************/
#ifndef _RV32IMAC_H_ #ifndef _RV32IMAC_H_
#define _RV32IMAC_H_ #define _RV32IMAC_H_
@ -47,13 +48,13 @@ template <> struct traits<rv32imac> {
constexpr static char const* const core_type = "RV32IMAC"; constexpr static char const* const core_type = "RV32IMAC";
enum constants { static constexpr std::array<const char*, 33> reg_names{
XLEN = 32, {"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc"}};
PCLEN = 32,
MISA_VAL = 0b1000000000101000001000100000101, static constexpr std::array<const char*, 33> reg_aliases{
PGSIZE = 0x1000, {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}};
PGMASK = 0xfff
}; enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000101000001000100000101, PGSIZE=0x1000, PGMASK=0xfff};
constexpr static unsigned FP_REGS_SIZE = 0; constexpr static unsigned FP_REGS_SIZE = 0;
@ -97,7 +98,39 @@ template <> struct traits<rv32imac> {
PENDING_TRAP, PENDING_TRAP,
MACHINE_STATE, MACHINE_STATE,
LAST_BRANCH, LAST_BRANCH,
ICOUNT ICOUNT,
ZERO = X0,
RA = X1,
SP = X2,
GP = X3,
TP = X4,
T0 = X5,
T1 = X6,
T2 = X7,
S0 = X8,
S1 = X9,
A0 = X10,
A1 = X11,
A2 = X12,
A3 = X13,
A4 = X14,
A5 = X15,
A6 = X16,
A7 = X17,
S2 = X18,
S3 = X19,
S4 = X20,
S5 = X21,
S6 = X22,
S7 = X23,
S8 = X24,
S9 = X25,
S10 = X26,
S11 = X27,
T3 = X28,
T4 = X29,
T5 = X30,
T6 = X31
}; };
using reg_t = uint32_t; using reg_t = uint32_t;
@ -110,17 +143,11 @@ template <> struct traits<rv32imac> {
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, 39> RV32IMAC_reg_size{ static constexpr std::array<const uint32_t, 39> reg_bit_widths{
{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64}};
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 64}};
constexpr static unsigned reg_bit_width(unsigned r) { return RV32IMAC_reg_size[r]; } static constexpr std::array<const uint32_t, 40> reg_byte_offsets{
{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,160}};
static constexpr std::array<const uint32_t, 40> RV32IMAC_reg_byte_offset{
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76,
80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 160}};
constexpr static unsigned reg_byte_offset(unsigned r) { return RV32IMAC_reg_byte_offset[r]; }
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
@ -215,7 +242,9 @@ protected:
uint32_t get_fcsr(){return 0;} uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){} void set_fcsr(uint32_t val){}
}; };
} }
} }
#endif /* _RV32IMAC_H_ */ #endif /* _RV32IMAC_H_ */

View File

@ -0,0 +1,316 @@
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#ifndef _RV64GC_H_
#define _RV64GC_H_
#include <array>
#include <iss/arch/traits.h>
#include <iss/arch_if.h>
#include <iss/vm_if.h>
namespace iss {
namespace arch {
struct rv64gc;
template <> struct traits<rv64gc> {
constexpr static char const* const core_type = "RV64GC";
static constexpr std::array<const char*, 66> reg_names{
{"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}};
static constexpr std::array<const char*, 66> reg_aliases{
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}};
enum constants {XLEN=64, FLEN=64, PCLEN=64, MISA_VAL=0b1000000000101000001000100101101, PGSIZE=0x1000, PGMASK=0xfff};
constexpr static unsigned FP_REGS_SIZE = 64;
enum reg_e {
X0,
X1,
X2,
X3,
X4,
X5,
X6,
X7,
X8,
X9,
X10,
X11,
X12,
X13,
X14,
X15,
X16,
X17,
X18,
X19,
X20,
X21,
X22,
X23,
X24,
X25,
X26,
X27,
X28,
X29,
X30,
X31,
PC,
F0,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
F16,
F17,
F18,
F19,
F20,
F21,
F22,
F23,
F24,
F25,
F26,
F27,
F28,
F29,
F30,
F31,
FCSR,
NUM_REGS,
NEXT_PC=NUM_REGS,
TRAP_STATE,
PENDING_TRAP,
MACHINE_STATE,
LAST_BRANCH,
ICOUNT,
ZERO = X0,
RA = X1,
SP = X2,
GP = X3,
TP = X4,
T0 = X5,
T1 = X6,
T2 = X7,
S0 = X8,
S1 = X9,
A0 = X10,
A1 = X11,
A2 = X12,
A3 = X13,
A4 = X14,
A5 = X15,
A6 = X16,
A7 = X17,
S2 = X18,
S3 = X19,
S4 = X20,
S5 = X21,
S6 = X22,
S7 = X23,
S8 = X24,
S9 = X25,
S10 = X26,
S11 = X27,
T3 = X28,
T4 = X29,
T5 = X30,
T6 = X31
};
using reg_t = uint64_t;
using addr_t = uint64_t;
using code_word_t = uint64_t; //TODO: check removal
using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, 72> reg_bit_widths{
{64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,64,32,32,32,32,64}};
static constexpr std::array<const uint32_t, 73> reg_byte_offsets{
{0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,400,408,416,424,432,440,448,456,464,472,480,488,496,504,512,520,528,536,540,544,548,552,560}};
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
enum sreg_flag_e { FLAGS };
enum mem_type_e { MEM, CSR, FENCE, RES };
};
struct rv64gc: public arch_if {
using virt_addr_t = typename traits<rv64gc>::virt_addr_t;
using phys_addr_t = typename traits<rv64gc>::phys_addr_t;
using reg_t = typename traits<rv64gc>::reg_t;
using addr_t = typename traits<rv64gc>::addr_t;
rv64gc();
~rv64gc();
void reset(uint64_t address=0) override;
uint8_t* get_regs_base_ptr() override;
/// deprecated
void get_reg(short idx, std::vector<uint8_t>& value) override {}
void set_reg(short idx, const std::vector<uint8_t>& value) override {}
/// deprecated
bool get_flag(int flag) override {return false;}
void set_flag(int, bool value) override {};
/// deprecated
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
inline uint64_t get_icount() { return reg.icount; }
inline bool should_stop() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t& addr){
if (addr.space != traits<rv64gc>::MEM || addr.type == iss::address_type::PHYSICAL ||
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL) {
return phys_addr_t(addr.access, addr.space, addr.val&traits<rv64gc>::addr_mask);
} else
return virt2phys(addr);
}
virtual phys_addr_t virt2phys(const iss::addr_t& addr);
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
inline uint32_t get_last_branch() { return reg.last_branch; }
protected:
struct RV64GC_regs {
uint64_t X0 = 0;
uint64_t X1 = 0;
uint64_t X2 = 0;
uint64_t X3 = 0;
uint64_t X4 = 0;
uint64_t X5 = 0;
uint64_t X6 = 0;
uint64_t X7 = 0;
uint64_t X8 = 0;
uint64_t X9 = 0;
uint64_t X10 = 0;
uint64_t X11 = 0;
uint64_t X12 = 0;
uint64_t X13 = 0;
uint64_t X14 = 0;
uint64_t X15 = 0;
uint64_t X16 = 0;
uint64_t X17 = 0;
uint64_t X18 = 0;
uint64_t X19 = 0;
uint64_t X20 = 0;
uint64_t X21 = 0;
uint64_t X22 = 0;
uint64_t X23 = 0;
uint64_t X24 = 0;
uint64_t X25 = 0;
uint64_t X26 = 0;
uint64_t X27 = 0;
uint64_t X28 = 0;
uint64_t X29 = 0;
uint64_t X30 = 0;
uint64_t X31 = 0;
uint64_t PC = 0;
uint64_t F0 = 0;
uint64_t F1 = 0;
uint64_t F2 = 0;
uint64_t F3 = 0;
uint64_t F4 = 0;
uint64_t F5 = 0;
uint64_t F6 = 0;
uint64_t F7 = 0;
uint64_t F8 = 0;
uint64_t F9 = 0;
uint64_t F10 = 0;
uint64_t F11 = 0;
uint64_t F12 = 0;
uint64_t F13 = 0;
uint64_t F14 = 0;
uint64_t F15 = 0;
uint64_t F16 = 0;
uint64_t F17 = 0;
uint64_t F18 = 0;
uint64_t F19 = 0;
uint64_t F20 = 0;
uint64_t F21 = 0;
uint64_t F22 = 0;
uint64_t F23 = 0;
uint64_t F24 = 0;
uint64_t F25 = 0;
uint64_t F26 = 0;
uint64_t F27 = 0;
uint64_t F28 = 0;
uint64_t F29 = 0;
uint64_t F30 = 0;
uint64_t F31 = 0;
uint32_t FCSR = 0;
uint64_t NEXT_PC = 0;
uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0;
uint64_t icount = 0;
} reg;
std::array<address_type, 4> addr_mode;
bool interrupt_sim=false;
uint32_t get_fcsr(){return reg.FCSR;}
void set_fcsr(uint32_t val){reg.FCSR = val;}
};
}
}
#endif /* _RV64GC_H_ */

250
riscv/incl/iss/arch/rv64i.h Normal file
View File

@ -0,0 +1,250 @@
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#ifndef _RV64I_H_
#define _RV64I_H_
#include <array>
#include <iss/arch/traits.h>
#include <iss/arch_if.h>
#include <iss/vm_if.h>
namespace iss {
namespace arch {
struct rv64i;
template <> struct traits<rv64i> {
constexpr static char const* const core_type = "RV64I";
static constexpr std::array<const char*, 33> reg_names{
{"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc"}};
static constexpr std::array<const char*, 33> reg_aliases{
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}};
enum constants {XLEN=64, PCLEN=64, MISA_VAL=0b10000000000001000000000100000000, PGSIZE=0x1000, PGMASK=0xfff};
constexpr static unsigned FP_REGS_SIZE = 0;
enum reg_e {
X0,
X1,
X2,
X3,
X4,
X5,
X6,
X7,
X8,
X9,
X10,
X11,
X12,
X13,
X14,
X15,
X16,
X17,
X18,
X19,
X20,
X21,
X22,
X23,
X24,
X25,
X26,
X27,
X28,
X29,
X30,
X31,
PC,
NUM_REGS,
NEXT_PC=NUM_REGS,
TRAP_STATE,
PENDING_TRAP,
MACHINE_STATE,
LAST_BRANCH,
ICOUNT,
ZERO = X0,
RA = X1,
SP = X2,
GP = X3,
TP = X4,
T0 = X5,
T1 = X6,
T2 = X7,
S0 = X8,
S1 = X9,
A0 = X10,
A1 = X11,
A2 = X12,
A3 = X13,
A4 = X14,
A5 = X15,
A6 = X16,
A7 = X17,
S2 = X18,
S3 = X19,
S4 = X20,
S5 = X21,
S6 = X22,
S7 = X23,
S8 = X24,
S9 = X25,
S10 = X26,
S11 = X27,
T3 = X28,
T4 = X29,
T5 = X30,
T6 = X31
};
using reg_t = uint64_t;
using addr_t = uint64_t;
using code_word_t = uint64_t; //TODO: check removal
using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, 39> reg_bit_widths{
{64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,64}};
static constexpr std::array<const uint32_t, 40> reg_byte_offsets{
{0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,276,280,284,288,296}};
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
enum sreg_flag_e { FLAGS };
enum mem_type_e { MEM, CSR, FENCE, RES };
};
struct rv64i: public arch_if {
using virt_addr_t = typename traits<rv64i>::virt_addr_t;
using phys_addr_t = typename traits<rv64i>::phys_addr_t;
using reg_t = typename traits<rv64i>::reg_t;
using addr_t = typename traits<rv64i>::addr_t;
rv64i();
~rv64i();
void reset(uint64_t address=0) override;
uint8_t* get_regs_base_ptr() override;
/// deprecated
void get_reg(short idx, std::vector<uint8_t>& value) override {}
void set_reg(short idx, const std::vector<uint8_t>& value) override {}
/// deprecated
bool get_flag(int flag) override {return false;}
void set_flag(int, bool value) override {};
/// deprecated
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
inline uint64_t get_icount() { return reg.icount; }
inline bool should_stop() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t& addr){
if (addr.space != traits<rv64i>::MEM || addr.type == iss::address_type::PHYSICAL ||
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL) {
return phys_addr_t(addr.access, addr.space, addr.val&traits<rv64i>::addr_mask);
} else
return virt2phys(addr);
}
virtual phys_addr_t virt2phys(const iss::addr_t& addr);
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
inline uint32_t get_last_branch() { return reg.last_branch; }
protected:
struct RV64I_regs {
uint64_t X0 = 0;
uint64_t X1 = 0;
uint64_t X2 = 0;
uint64_t X3 = 0;
uint64_t X4 = 0;
uint64_t X5 = 0;
uint64_t X6 = 0;
uint64_t X7 = 0;
uint64_t X8 = 0;
uint64_t X9 = 0;
uint64_t X10 = 0;
uint64_t X11 = 0;
uint64_t X12 = 0;
uint64_t X13 = 0;
uint64_t X14 = 0;
uint64_t X15 = 0;
uint64_t X16 = 0;
uint64_t X17 = 0;
uint64_t X18 = 0;
uint64_t X19 = 0;
uint64_t X20 = 0;
uint64_t X21 = 0;
uint64_t X22 = 0;
uint64_t X23 = 0;
uint64_t X24 = 0;
uint64_t X25 = 0;
uint64_t X26 = 0;
uint64_t X27 = 0;
uint64_t X28 = 0;
uint64_t X29 = 0;
uint64_t X30 = 0;
uint64_t X31 = 0;
uint64_t PC = 0;
uint64_t NEXT_PC = 0;
uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0;
uint64_t icount = 0;
} reg;
std::array<address_type, 4> addr_mode;
bool interrupt_sim=false;
uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}
};
}
}
#endif /* _RV64I_H_ */

View File

@ -1,218 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017, MINRES Technologies GmbH
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef _RV64IA_H_
#define _RV64IA_H_
#include <iss/arch_if.h>
#include <iss/vm_if.h>
#include <iss/arch/traits.h>
#include <array>
namespace iss {
namespace arch {
struct rv64ia;
template<>
struct traits<rv64ia> {
constexpr static char const* const core_type = "RV64IA";
enum constants {XLEN=64, PCLEN=64, MISA_VAL=0b10000000000001000000000100000001, PGSIZE=0x1000, PGMASK=0xfff};
constexpr static unsigned FP_REGS_SIZE = 0;
enum reg_e {
X0,
X1,
X2,
X3,
X4,
X5,
X6,
X7,
X8,
X9,
X10,
X11,
X12,
X13,
X14,
X15,
X16,
X17,
X18,
X19,
X20,
X21,
X22,
X23,
X24,
X25,
X26,
X27,
X28,
X29,
X30,
X31,
PC,
NUM_REGS,
NEXT_PC=NUM_REGS,
TRAP_STATE,
PENDING_TRAP,
MACHINE_STATE,
LAST_BRANCH,
ICOUNT
};
using reg_t = uint64_t;
using addr_t = uint64_t;
using code_word_t = uint64_t; //TODO: check removal
using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
constexpr static unsigned reg_bit_width(unsigned r) {
constexpr std::array<const uint32_t, 39> RV64IA_reg_size{{64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,64}};
return RV64IA_reg_size[r];
}
constexpr static unsigned reg_byte_offset(unsigned r) {
constexpr std::array<const uint32_t, 40> RV64IA_reg_byte_offset{{0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,276,280,284,288,296}};
return RV64IA_reg_byte_offset[r];
}
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
enum sreg_flag_e {FLAGS};
enum mem_type_e {MEM, CSR, FENCE, RES};
};
struct rv64ia: public arch_if {
using virt_addr_t = typename traits<rv64ia>::virt_addr_t;
using phys_addr_t = typename traits<rv64ia>::phys_addr_t;
using reg_t = typename traits<rv64ia>::reg_t;
using addr_t = typename traits<rv64ia>::addr_t;
rv64ia();
~rv64ia();
void reset(uint64_t address=0) override;
uint8_t* get_regs_base_ptr() override;
/// deprecated
void get_reg(short idx, std::vector<uint8_t>& value) override {}
void set_reg(short idx, const std::vector<uint8_t>& value) override {}
/// deprecated
bool get_flag(int flag) override {return false;}
void set_flag(int, bool value) override {};
/// deprecated
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
inline uint64_t get_icount() { return reg.icount; }
inline bool should_stop() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<rv64ia>::MEM ||
addr.type == iss::address_type::PHYSICAL ||
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL){
return phys_addr_t(addr.access, addr.space, addr.val&traits<rv64ia>::addr_mask);
} else
return virt2phys(addr);
}
virtual phys_addr_t virt2phys(const iss::addr_t& addr);
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
inline
uint32_t get_last_branch(){return reg.last_branch;}
protected:
struct RV64IA_regs {
uint64_t X0 = 0;
uint64_t X1 = 0;
uint64_t X2 = 0;
uint64_t X3 = 0;
uint64_t X4 = 0;
uint64_t X5 = 0;
uint64_t X6 = 0;
uint64_t X7 = 0;
uint64_t X8 = 0;
uint64_t X9 = 0;
uint64_t X10 = 0;
uint64_t X11 = 0;
uint64_t X12 = 0;
uint64_t X13 = 0;
uint64_t X14 = 0;
uint64_t X15 = 0;
uint64_t X16 = 0;
uint64_t X17 = 0;
uint64_t X18 = 0;
uint64_t X19 = 0;
uint64_t X20 = 0;
uint64_t X21 = 0;
uint64_t X22 = 0;
uint64_t X23 = 0;
uint64_t X24 = 0;
uint64_t X25 = 0;
uint64_t X26 = 0;
uint64_t X27 = 0;
uint64_t X28 = 0;
uint64_t X29 = 0;
uint64_t X30 = 0;
uint64_t X31 = 0;
uint64_t PC = 0;
uint64_t NEXT_PC = 0;
uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0;
uint64_t icount = 0;
} reg;
std::array<address_type, 4> addr_mode;
bool interrupt_sim=false;
uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}
};
}
}
#endif /* _RV64IA_H_ */

View File

@ -40,6 +40,7 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <fmt/format.h>
#include <util/logging.h> #include <util/logging.h>
namespace iss { namespace iss {
@ -180,8 +181,8 @@ status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, st
avail.clear(); avail.clear();
const uint8_t *reg_base = core->get_regs_base_ptr(); const uint8_t *reg_base = core->get_regs_base_ptr();
for (size_t reg_no = 0; reg_no < arch::traits<ARCH>::NUM_REGS; ++reg_no) { for (size_t reg_no = 0; reg_no < arch::traits<ARCH>::NUM_REGS; ++reg_no) {
auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8; auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
unsigned offset = traits<ARCH>::reg_byte_offset(reg_no); unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
for (size_t j = 0; j < reg_width; ++j) { for (size_t j = 0; j < reg_width; ++j) {
data.push_back(*(reg_base + offset + j)); data.push_back(*(reg_base + offset + j));
avail.push_back(0xff); avail.push_back(0xff);
@ -215,8 +216,8 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(cons
auto *reg_base = core->get_regs_base_ptr(); auto *reg_base = core->get_regs_base_ptr();
auto iter = data.data(); auto iter = data.data();
for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) { for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) {
auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8; auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
auto offset = traits<ARCH>::reg_byte_offset(reg_no); auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
std::copy(iter, iter + reg_width, reg_base); std::copy(iter, iter + reg_width, reg_base);
iter += 4; iter += 4;
reg_base += offset; reg_base += offset;
@ -231,10 +232,10 @@ status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std
// auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename // auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename
// arch::traits<ARCH>::reg_e>(reg_no))/8; // arch::traits<ARCH>::reg_e>(reg_no))/8;
auto *reg_base = core->get_regs_base_ptr(); auto *reg_base = core->get_regs_base_ptr();
auto reg_width = arch::traits<ARCH>::reg_bit_width(reg_no) / 8; auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
data.resize(reg_width); data.resize(reg_width);
avail.resize(reg_width); avail.resize(reg_width);
auto offset = traits<ARCH>::reg_byte_offset(reg_no); auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin()); std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin());
std::fill(avail.begin(), avail.end(), 0xff); std::fill(avail.begin(), avail.end(), 0xff);
} else { } else {
@ -251,8 +252,8 @@ template <typename ARCH>
status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) { status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) {
if (reg_no < 65) { if (reg_no < 65) {
auto *reg_base = core->get_regs_base_ptr(); auto *reg_base = core->get_regs_base_ptr();
auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8; auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
auto offset = traits<ARCH>::reg_byte_offset(reg_no); auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
std::copy(data.begin(), data.begin() + reg_width, reg_base + offset); std::copy(data.begin(), data.begin() + reg_width, reg_base + offset);
} else { } else {
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65); typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65);
@ -296,9 +297,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::raw_query(std::strin
template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int first, std::string &out_buf) { template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int first, std::string &out_buf) {
if (first) { if (first) {
std::stringstream ss; out_buf = fmt::format("m{:x}", thread_idx.val);
ss << "m" << std::hex << thread_idx.val;
out_buf = ss.str();
} else { } else {
out_buf = "l"; out_buf = "l";
} }
@ -348,8 +347,8 @@ template <typename ARCH>
status riscv_target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, status riscv_target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread,
std::function<void(unsigned)> stop_callback) { std::function<void(unsigned)> stop_callback) {
auto *reg_base = core->get_regs_base_ptr(); auto *reg_base = core->get_regs_base_ptr();
auto reg_width = arch::traits<ARCH>::reg_bit_width(arch::traits<ARCH>::PC) / 8; auto reg_width = arch::traits<ARCH>::reg_bit_widths[arch::traits<ARCH>::PC] / 8;
auto offset = traits<ARCH>::reg_byte_offset(arch::traits<ARCH>::PC); auto offset = traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC];
const uint8_t *iter = reinterpret_cast<const uint8_t *>(&addr); const uint8_t *iter = reinterpret_cast<const uint8_t *>(&addr);
std::copy(iter, iter + reg_width, reg_base); std::copy(iter, iter + reg_width, reg_base);
return resume_from_current(step, sig, thread, stop_callback); return resume_from_current(step, sig, thread, stop_callback);

View File

@ -4,18 +4,16 @@ set(LIB_HEADERS ${RiscVSCHeaders} )
set(LIB_SOURCES set(LIB_SOURCES
iss/rv32gc.cpp iss/rv32gc.cpp
iss/rv32imac.cpp iss/rv32imac.cpp
iss/rv64ia.cpp iss/rv64i.cpp
iss/rv64gc.cpp
internal/fp_functions.cpp internal/fp_functions.cpp
internal/vm_rv32gc.cpp internal/vm_rv32gc.cpp
internal/vm_rv32imac.cpp internal/vm_rv32imac.cpp
internal/vm_rv64ia.cpp internal/vm_rv64i.cpp
internal/vm_rv64gc.cpp
plugin/instruction_count.cpp plugin/instruction_count.cpp
plugin/cycle_estimate.cpp) plugin/cycle_estimate.cpp)
set(APP_HEADERS )
set(APP_SOURCES main.cpp)
# Define two variables in order not to repeat ourselves. # Define two variables in order not to repeat ourselves.
set(LIBRARY_NAME riscv) set(LIBRARY_NAME riscv)
@ -27,17 +25,44 @@ set_target_properties(${LIBRARY_NAME} PROPERTIES
FRAMEWORK FALSE FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers
) )
#set_property(TARGET ${LIBRARY_NAME} PROPERTY POSITION_INDEPENDENT_CODE ON)
if(SystemC_FOUND)
set(SC_LIBRARY_NAME riscv_sc)
add_library(${SC_LIBRARY_NAME} SHARED sysc/core_complex.cpp)
add_definitions(-DWITH_SYSTEMC)
include_directories(${SystemC_INCLUDE_DIRS})
include_directories(${CCI_INCLUDE_DIRS})
if(SCV_FOUND)
add_definitions(-DWITH_SCV)
include_directories(${SCV_INCLUDE_DIRS})
endif()
set_target_properties(${SC_LIBRARY_NAME} PROPERTIES
VERSION ${VERSION} # ${VERSION} was defined in the main CMakeLists.
FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers
)
target_link_libraries(${SC_LIBRARY_NAME} ${LIBRARY_NAME})
target_link_libraries(${SC_LIBRARY_NAME} dbt-core)
target_link_libraries(${SC_LIBRARY_NAME} softfloat)
target_link_libraries(${SC_LIBRARY_NAME} sc-components)
target_link_libraries(${SC_LIBRARY_NAME} external)
target_link_libraries(${SC_LIBRARY_NAME} ${llvm_libs})
target_link_libraries(${SC_LIBRARY_NAME} ${Boost_LIBRARIES} )
endif()
# This is a make target, so you can do a "make riscv-sc" # This is a make target, so you can do a "make riscv-sc"
set(APPLICATION_NAME riscv-sim) set(APPLICATION_NAME riscv-sim)
add_executable(${APPLICATION_NAME} ${APP_SOURCES}) add_executable(${APPLICATION_NAME} main.cpp)
# Links the target exe against the libraries # Links the target exe against the libraries
target_link_libraries(${APPLICATION_NAME} ${LIBRARY_NAME}) target_link_libraries(${APPLICATION_NAME} ${LIBRARY_NAME})
target_link_libraries(${APPLICATION_NAME} jsoncpp)
target_link_libraries(${APPLICATION_NAME} dbt-core) target_link_libraries(${APPLICATION_NAME} dbt-core)
target_link_libraries(${APPLICATION_NAME} softfloat) target_link_libraries(${APPLICATION_NAME} softfloat)
target_link_libraries(${APPLICATION_NAME} sc-components)
target_link_libraries(${APPLICATION_NAME} external) target_link_libraries(${APPLICATION_NAME} external)
target_link_libraries(${APPLICATION_NAME} ${llvm_libs}) target_link_libraries(${APPLICATION_NAME} ${llvm_libs})
target_link_libraries(${APPLICATION_NAME} ${Boost_LIBRARIES} ) target_link_libraries(${APPLICATION_NAME} ${Boost_LIBRARIES} )

View File

@ -33,7 +33,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include <iss/iss.h> #include <iss/iss.h>
#include <iss/vm_base.h> #include <iss/llvm/vm_base.h>
extern "C" { extern "C" {
#include <softfloat.h> #include <softfloat.h>
@ -70,7 +70,7 @@ using namespace std;
using namespace llvm; using namespace llvm;
void add_fp_functions_2_module(Module *mod, uint32_t flen) { void add_fp_functions_2_module(Module *mod, uint32_t flen, uint32_t xlen) {
if(flen){ if(flen){
FDECL(fget_flags, INT_TYPE(32)); FDECL(fget_flags, INT_TYPE(32));
FDECL(fadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
@ -83,6 +83,8 @@ void add_fp_functions_2_module(Module *mod, uint32_t flen) {
FDECL(fmadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); FDECL(fmadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fsel_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); FDECL(fsel_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32));
FDECL(fclass_s, INT_TYPE(32), INT_TYPE(32)); FDECL(fclass_s, INT_TYPE(32), INT_TYPE(32));
FDECL(fcvt_32_64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fcvt_64_32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
if(flen>32){ if(flen>32){
FDECL(fconv_d2f, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8)); FDECL(fconv_d2f, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
FDECL(fconv_f2d, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); FDECL(fconv_f2d, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
@ -96,6 +98,8 @@ void add_fp_functions_2_module(Module *mod, uint32_t flen) {
FDECL(fmadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); FDECL(fmadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
FDECL(fsel_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); FDECL(fsel_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32));
FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64)); FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64));
FDECL(unbox_s, INT_TYPE(32), INT_TYPE(64));
} }
} }
} }
@ -198,13 +202,15 @@ uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode) {
float32_t v1f{v1}; float32_t v1f{v1};
softfloat_exceptionFlags=0; softfloat_exceptionFlags=0;
float32_t r; float32_t r;
int32_t res;
switch(op){ switch(op){
case 0: //w->s, fp to int32 case 0:{ //w->s, fp to int32
res = f32_to_i32(v1f,rmm_map[mode&0x7],true); uint_fast32_t res = f32_to_i32(v1f,rmm_map[mode&0x7],true);
return (uint32_t)res; return (uint32_t)res;
case 1: //wu->s }
return f32_to_ui32(v1f,rmm_map[mode&0x7],true); case 1:{ //wu->s
uint_fast32_t res = f32_to_ui32(v1f,rmm_map[mode&0x7],true);
return (uint32_t)res;
}
case 2: //s->w case 2: //s->w
r=i32_to_f32(v1); r=i32_to_f32(v1);
return r.v; return r.v;
@ -373,17 +379,19 @@ uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) {
float64_t v1f{v1}; float64_t v1f{v1};
softfloat_exceptionFlags=0; softfloat_exceptionFlags=0;
float64_t r; float64_t r;
int32_t res;
switch(op){ switch(op){
case 0: //w->s, fp to int32 case 0:{ //l->d, fp to int32
res = f64_to_i64(v1f,rmm_map[mode&0x7],true); int64_t res = f64_to_i64(v1f,rmm_map[mode&0x7],true);
return (uint64_t)res; return (uint64_t)res;
case 1: //wu->s }
return f64_to_ui64(v1f,rmm_map[mode&0x7],true); case 1:{ //lu->s
case 2: //s->w uint64_t res = f64_to_ui64(v1f,rmm_map[mode&0x7],true);
return res;
}
case 2: //s->l
r=i64_to_f64(v1); r=i64_to_f64(v1);
return r.v; return r.v;
case 3: //s->wu case 3: //s->lu
r=ui64_to_f64(v1); r=ui64_to_f64(v1);
return r.v; return r.v;
} }
@ -454,5 +462,53 @@ uint64_t fclass_d(uint64_t v1 ){
( isNaN && !isSNaN ) << 9; ( isNaN && !isSNaN ) << 9;
} }
uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode) {
float32_t v1f{v1};
softfloat_exceptionFlags=0;
float64_t r;
switch(op){
case 0: //l->s, fp to int32
return f32_to_i64(v1f,rmm_map[mode&0x7],true);
case 1: //wu->s
return f32_to_ui64(v1f,rmm_map[mode&0x7],true);
case 2: //s->w
r=i32_to_f64(v1);
return r.v;
case 3: //s->wu
r=ui32_to_f64(v1);
return r.v;
}
return 0;
}
uint32_t fcvt_64_32(uint64_t v1, uint32_t op, uint8_t mode) {
softfloat_exceptionFlags=0;
float32_t r;
switch(op){
case 0:{ //wu->s
int32_t r=f64_to_i32(float64_t{v1}, rmm_map[mode&0x7],true);
return r;
}
case 1:{ //wu->s
uint32_t r=f64_to_ui32(float64_t{v1}, rmm_map[mode&0x7],true);
return r;
}
case 2: //l->s, fp to int32
r=i64_to_f32(v1);
return r.v;
case 3: //wu->s
r=ui64_to_f32(v1);
return r.v;
}
return 0;
}
uint32_t unbox_s(uint64_t v){
constexpr uint64_t mask = std::numeric_limits<uint64_t>::max() & ~((uint64_t)std::numeric_limits<uint32_t>::max());
if((v & mask) != mask)
return 0x7fc00000;
else
return v & std::numeric_limits<uint32_t>::max();
}
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +1,34 @@
//////////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// Copyright (C) 2017, MINRES Technologies GmbH * Copyright (C) 2017, 2018 MINRES Technologies GmbH
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// *
// 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// *
// 3. Neither the name of the copyright holder nor the names of its contributors * 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
// *
//////////////////////////////////////////////////////////////////////////////// *******************************************************************************/
#include "util/ities.h" #include "util/ities.h"
#include <util/logging.h> #include <util/logging.h>
@ -49,6 +49,11 @@ extern "C" {
using namespace iss::arch; using namespace iss::arch;
constexpr std::array<const char*, 66> iss::arch::traits<iss::arch::rv32gc>::reg_names;
constexpr std::array<const char*, 66> iss::arch::traits<iss::arch::rv32gc>::reg_aliases;
constexpr std::array<const uint32_t, 72> iss::arch::traits<iss::arch::rv32gc>::reg_bit_widths;
constexpr std::array<const uint32_t, 73> iss::arch::traits<iss::arch::rv32gc>::reg_byte_offsets;
rv32gc::rv32gc() { rv32gc::rv32gc() {
reg.icount=0; reg.icount=0;
} }

View File

@ -49,8 +49,10 @@ extern "C" {
using namespace iss::arch; using namespace iss::arch;
constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::rv32imac>::RV32IMAC_reg_size; constexpr std::array<const char*, 33> iss::arch::traits<iss::arch::rv32imac>::reg_names;
constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::rv32imac>::RV32IMAC_reg_byte_offset; constexpr std::array<const char*, 33> iss::arch::traits<iss::arch::rv32imac>::reg_aliases;
constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::rv32imac>::reg_bit_widths;
constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::rv32imac>::reg_byte_offsets;
rv32imac::rv32imac() { rv32imac::rv32imac() {
reg.icount = 0; reg.icount = 0;

81
riscv/src/iss/rv64gc.cpp Normal file
View File

@ -0,0 +1,81 @@
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#include "util/ities.h"
#include <util/logging.h>
#include <elfio/elfio.hpp>
#include <iss/arch/rv64gc.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <ihex.h>
#ifdef __cplusplus
}
#endif
#include <cstdio>
#include <cstring>
#include <fstream>
using namespace iss::arch;
constexpr std::array<const char*, 66> iss::arch::traits<iss::arch::rv64gc>::reg_names;
constexpr std::array<const char*, 66> iss::arch::traits<iss::arch::rv64gc>::reg_aliases;
constexpr std::array<const uint32_t, 72> iss::arch::traits<iss::arch::rv64gc>::reg_bit_widths;
constexpr std::array<const uint32_t, 73> iss::arch::traits<iss::arch::rv64gc>::reg_byte_offsets;
rv64gc::rv64gc() {
reg.icount = 0;
}
rv64gc::~rv64gc() = default;
void rv64gc::reset(uint64_t address) {
for(size_t i=0; i<traits<rv64gc>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<rv64gc>::reg_t),0));
reg.PC=address;
reg.NEXT_PC=reg.PC;
reg.trap_state=0;
reg.machine_state=0x0;
reg.icount=0;
}
uint8_t *rv64gc::get_regs_base_ptr() {
return reinterpret_cast<uint8_t*>(&reg);
}
rv64gc::phys_addr_t rv64gc::virt2phys(const iss::addr_t &pc) {
return phys_addr_t(pc); // change logical address to physical address
}

79
riscv/src/iss/rv64i.cpp Normal file
View File

@ -0,0 +1,79 @@
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#include "util/ities.h"
#include <util/logging.h>
#include <elfio/elfio.hpp>
#include <iss/arch/rv64i.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <ihex.h>
#ifdef __cplusplus
}
#endif
#include <cstdio>
#include <cstring>
#include <fstream>
using namespace iss::arch;
constexpr std::array<const char*, 33> iss::arch::traits<iss::arch::rv64i>::reg_names;
constexpr std::array<const char*, 33> iss::arch::traits<iss::arch::rv64i>::reg_aliases;
constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::rv64i>::reg_bit_widths;
constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::rv64i>::reg_byte_offsets;
rv64i::rv64i() {
reg.icount = 0;
}
rv64i::~rv64i() = default;
void rv64i::reset(uint64_t address) {
for(size_t i=0; i<traits<rv64i>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<rv64i>::reg_t),0));
reg.PC=address;
reg.NEXT_PC=reg.PC;
reg.trap_state=0;
reg.machine_state=0x0;
reg.icount=0;
}
uint8_t *rv64i::get_regs_base_ptr() {
return reinterpret_cast<uint8_t*>(&reg);
}
rv64i::phys_addr_t rv64i::virt2phys(const iss::addr_t &pc) {
return phys_addr_t(pc); // change logical address to physical address
}

View File

@ -1,73 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017, MINRES Technologies GmbH
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Created on: Tue Sep 05 18:57:24 CEST 2017
// * rv64ia.cpp Author: <CoreDSL Generator>
//
////////////////////////////////////////////////////////////////////////////////
#include "util/ities.h"
#include <util/logging.h>
#include <elfio/elfio.hpp>
#include <iss/arch/rv64ia.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <ihex.h>
#ifdef __cplusplus
}
#endif
#include <cstdio>
#include <cstring>
#include <fstream>
using namespace iss::arch;
rv64ia::rv64ia() { reg.icount = 0; reg.machine_state = 0x3;}
rv64ia::~rv64ia(){}
void rv64ia::reset(uint64_t address) {
for (size_t i = 0; i < traits<rv64ia>::NUM_REGS; ++i)
set_reg(i, std::vector<uint8_t>(sizeof(traits<rv64ia>::reg_t), 0));
reg.PC = address;
reg.NEXT_PC = reg.PC;
reg.trap_state = 0;
reg.machine_state = 0x3;
reg.icount=0;
}
uint8_t *rv64ia::get_regs_base_ptr() { return reinterpret_cast<uint8_t *>(&reg); }
rv64ia::phys_addr_t rv64ia::virt2phys(const iss::addr_t &pc) {
return phys_addr_t(pc); // change logical address to physical address
}

View File

@ -38,8 +38,9 @@
#include <iss/arch/riscv_hart_msu_vp.h> #include <iss/arch/riscv_hart_msu_vp.h>
#include <iss/arch/rv32imac.h> #include <iss/arch/rv32imac.h>
#include <iss/arch/rv32gc.h> #include <iss/arch/rv32gc.h>
#include <iss/arch/rv64ia.h> #include <iss/arch/rv64gc.h>
#include <iss/jit/jit_helper.h> #include <iss/arch/rv64i.h>
#include <iss/llvm/jit_helper.h>
#include <iss/log_categories.h> #include <iss/log_categories.h>
#include <iss/plugin/cycle_estimate.h> #include <iss/plugin/cycle_estimate.h>
#include <iss/plugin/instruction_count.h> #include <iss/plugin/instruction_count.h>
@ -107,7 +108,11 @@ int main(int argc, char *argv[]) {
std::unique_ptr<iss::arch_if> cpu{nullptr}; std::unique_ptr<iss::arch_if> cpu{nullptr};
std::string isa_opt(clim["isa"].as<std::string>()); std::string isa_opt(clim["isa"].as<std::string>());
if (isa_opt=="rv64ia") { if (isa_opt=="rv64ia") {
iss::arch::rv64ia* lcpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv64ia>(); iss::arch::rv64i* lcpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv64i>();
vm = iss::create(lcpu, clim["gdb-port"].as<unsigned>());
cpu.reset(lcpu);
} else if (isa_opt=="rv64gc") {
iss::arch::rv64gc* lcpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv64gc>();
vm = iss::create(lcpu, clim["gdb-port"].as<unsigned>()); vm = iss::create(lcpu, clim["gdb-port"].as<unsigned>());
cpu.reset(lcpu); cpu.reset(lcpu);
} else if (isa_opt=="rv32imac") { } else if (isa_opt=="rv32imac") {

@ -1 +1 @@
Subproject commit 1859c341ab0576c70f1cfbd67a18e3d300a5eb16 Subproject commit fa2e0c899863a2ddba4982e157ec1cc91adb9a9b