Merge branch 'develop'
This commit is contained in:
commit
cb3a0d8411
@ -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}")
|
||||||
|
@ -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
|
||||||
|
2
dbt-core
2
dbt-core
@ -1 +1 @@
|
|||||||
Subproject commit f76938cbdc90da4c8fbab0fa36a155f3e0816af7
|
Subproject commit a9d808088e64622a6c9bf52071436e9df206bae3
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
|
50
riscv/gen_input/RISCVBase.core_desc
Normal file
50
riscv/gen_input/RISCVBase.core_desc
Normal 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]
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
@ -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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
@ -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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
210
riscv/gen_input/RVA.core_desc
Normal file
210
riscv/gen_input/RVA.core_desc
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
@ -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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
400
riscv/gen_input/RVF.core_desc
Normal file
400
riscv/gen_input/RVF.core_desc
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
160
riscv/gen_input/RVM.core_desc
Normal file
160
riscv/gen_input/RVM.core_desc
Normal 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});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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,21 +133,17 @@ 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);
|
||||||
|
|
||||||
enum sreg_flag_e {FLAGS};
|
enum sreg_flag_e { FLAGS };
|
||||||
|
|
||||||
enum mem_type_e {${allSpaces.collect{s -> s.name}.join(', ')}};
|
enum mem_type_e { ${allSpaces.collect{s -> s.name}.join(', ')} };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ${coreDef.name.toLowerCase()}: public arch_if {
|
struct ${coreDef.name.toLowerCase()}: public arch_if {
|
||||||
@ -126,12 +168,13 @@ 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
|
||||||
return virt2phys(addr);
|
return virt2phys(addr);
|
||||||
@ -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 {<%
|
||||||
|
@ -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,9 +104,10 @@ 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() {
|
||||||
return reinterpret_cast<uint8_t*>(®);
|
return reinterpret_cast<uint8_t*>(®);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,17 +126,17 @@ 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;
|
||||||
std::array<compile_func, LUT_SIZE> lut_11;
|
std::array<compile_func, LUT_SIZE> lut_11;
|
||||||
|
|
||||||
std::array<compile_func*, 4> qlut;
|
std::array<compile_func *, 4> qlut;
|
||||||
|
|
||||||
std::array<const uint32_t, 4> lutmasks = { { EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32 } };
|
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[],
|
void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[],
|
||||||
compile_func f) {
|
compile_func f) {
|
||||||
@ -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
|
||||||
|
@ -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
|
|
@ -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; }
|
||||||
|
@ -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,21 +176,17 @@ 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);
|
||||||
|
|
||||||
enum sreg_flag_e {FLAGS};
|
enum sreg_flag_e { FLAGS };
|
||||||
|
|
||||||
enum mem_type_e {MEM, CSR, FENCE, RES};
|
enum mem_type_e { MEM, CSR, FENCE, RES };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rv32gc: public arch_if {
|
struct rv32gc: public arch_if {
|
||||||
@ -177,14 +211,13 @@ 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
|
||||||
return virt2phys(addr);
|
return virt2phys(addr);
|
||||||
@ -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 {
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#ifndef _RV32IMAC_H_
|
#ifndef _RV32IMAC_H_
|
||||||
#define _RV32IMAC_H_
|
#define _RV32IMAC_H_
|
||||||
|
|
||||||
@ -45,15 +46,15 @@ struct rv32imac;
|
|||||||
|
|
||||||
template <> struct traits<rv32imac> {
|
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;
|
||||||
|
|
||||||
@ -92,35 +93,61 @@ template <> struct traits<rv32imac> {
|
|||||||
X31,
|
X31,
|
||||||
PC,
|
PC,
|
||||||
NUM_REGS,
|
NUM_REGS,
|
||||||
NEXT_PC = NUM_REGS,
|
NEXT_PC=NUM_REGS,
|
||||||
TRAP_STATE,
|
TRAP_STATE,
|
||||||
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;
|
||||||
|
|
||||||
using addr_t = uint32_t;
|
using addr_t = uint32_t;
|
||||||
|
|
||||||
using code_word_t = uint32_t; // TODO: check removal
|
using code_word_t = uint32_t; //TODO: check removal
|
||||||
|
|
||||||
using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
|
using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@ -129,7 +156,7 @@ template <> struct traits<rv32imac> {
|
|||||||
enum mem_type_e { MEM, CSR, FENCE, RES };
|
enum mem_type_e { MEM, CSR, FENCE, RES };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rv32imac : public arch_if {
|
struct rv32imac: public arch_if {
|
||||||
|
|
||||||
using virt_addr_t = typename traits<rv32imac>::virt_addr_t;
|
using virt_addr_t = typename traits<rv32imac>::virt_addr_t;
|
||||||
using phys_addr_t = typename traits<rv32imac>::phys_addr_t;
|
using phys_addr_t = typename traits<rv32imac>::phys_addr_t;
|
||||||
@ -139,31 +166,31 @@ struct rv32imac : public arch_if {
|
|||||||
rv32imac();
|
rv32imac();
|
||||||
~rv32imac();
|
~rv32imac();
|
||||||
|
|
||||||
void reset(uint64_t address = 0) override;
|
void reset(uint64_t address=0) override;
|
||||||
|
|
||||||
uint8_t *get_regs_base_ptr() override;
|
uint8_t* get_regs_base_ptr() override;
|
||||||
/// deprecated
|
/// deprecated
|
||||||
void get_reg(short idx, std::vector<uint8_t> &value) override {}
|
void get_reg(short idx, std::vector<uint8_t>& value) override {}
|
||||||
void set_reg(short idx, const std::vector<uint8_t> &value) override {}
|
void set_reg(short idx, const std::vector<uint8_t>& value) override {}
|
||||||
/// deprecated
|
/// deprecated
|
||||||
bool get_flag(int flag) override { return false; }
|
bool get_flag(int flag) override {return false;}
|
||||||
void set_flag(int, bool value) override{};
|
void set_flag(int, bool value) override {};
|
||||||
/// 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 {};
|
||||||
|
|
||||||
inline 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<rv32imac>::MEM || addr.type == iss::address_type::PHYSICAL ||
|
if (addr.space != traits<rv32imac>::MEM || 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<rv32imac>::addr_mask);
|
return phys_addr_t(addr.access, addr.space, addr.val&traits<rv32imac>::addr_mask);
|
||||||
} else
|
} else
|
||||||
return virt2phys(addr);
|
return virt2phys(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual phys_addr_t virt2phys(const iss::addr_t &addr);
|
virtual phys_addr_t virt2phys(const iss::addr_t& addr);
|
||||||
|
|
||||||
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
||||||
|
|
||||||
@ -211,11 +238,13 @@ protected:
|
|||||||
|
|
||||||
std::array<address_type, 4> addr_mode;
|
std::array<address_type, 4> addr_mode;
|
||||||
|
|
||||||
bool interrupt_sim = false;
|
bool interrupt_sim=false;
|
||||||
|
|
||||||
|
uint32_t get_fcsr(){return 0;}
|
||||||
|
void set_fcsr(uint32_t val){}
|
||||||
|
|
||||||
uint32_t get_fcsr() { return 0; }
|
|
||||||
void set_fcsr(uint32_t val) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* _RV32IMAC_H_ */
|
#endif /* _RV32IMAC_H_ */
|
||||||
|
316
riscv/incl/iss/arch/rv64gc.h
Normal file
316
riscv/incl/iss/arch/rv64gc.h
Normal 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
250
riscv/incl/iss/arch/rv64i.h
Normal 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_ */
|
@ -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_ */
|
|
@ -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);
|
||||||
|
@ -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} )
|
||||||
|
@ -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
11368
riscv/src/internal/vm_rv64gc.cpp
Normal file
11368
riscv/src/internal/vm_rv64gc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3151
riscv/src/internal/vm_rv64i.cpp
Normal file
3151
riscv/src/internal/vm_rv64i.cpp
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
81
riscv/src/iss/rv64gc.cpp
Normal 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*>(®);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
79
riscv/src/iss/rv64i.cpp
Normal 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*>(®);
|
||||||
|
}
|
||||||
|
|
||||||
|
rv64i::phys_addr_t rv64i::virt2phys(const iss::addr_t &pc) {
|
||||||
|
return phys_addr_t(pc); // change logical address to physical address
|
||||||
|
}
|
||||||
|
|
@ -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 *>(®); }
|
|
||||||
|
|
||||||
rv64ia::phys_addr_t rv64ia::virt2phys(const iss::addr_t &pc) {
|
|
||||||
return phys_addr_t(pc); // change logical address to physical address
|
|
||||||
}
|
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user