Merge branch 'develop'
This commit is contained in:
		| @@ -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(ENABLE_SCV TRUE CACHE BOOL "Enable use of SCV") | ||||
| set(ENABLE_SHARED TRUE CACHE BOOL "Build shared libraries") | ||||
|  | ||||
| include(GitFunctions) | ||||
| get_branch_from_git() | ||||
| @@ -32,7 +33,8 @@ include(Conan) | ||||
| set(CMAKE_CXX_STANDARD 14) | ||||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||||
| set(CMAKE_CXX_EXTENSIONS OFF) | ||||
| 	 | ||||
| set(CMAKE_POSITION_INDEPENDENT_CODE ON) | ||||
|  | ||||
| include(CheckCXXCompilerFlag) | ||||
| CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) | ||||
| if(COMPILER_SUPPORTS_MARCH_NATIVE) | ||||
| @@ -112,7 +114,6 @@ add_subdirectory(sc-components) | ||||
| add_subdirectory(softfloat) | ||||
| GET_DIRECTORY_PROPERTY(SOFTFLOAT_INCLUDE_DIRS DIRECTORY softfloat DEFINITION SOFTFLOAT_INCLUDE_DIRS) | ||||
| add_subdirectory(riscv) | ||||
| add_subdirectory(riscv.sc) | ||||
| add_subdirectory(platform) | ||||
|  | ||||
| message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| [requires] | ||||
| 	gsl_microsoft/20180102@bincrafters/stable | ||||
| 	spdlog/0.16.3@bincrafters/stable | ||||
|     gsl_microsoft/20180102@bincrafters/stable | ||||
|     spdlog/0.16.3@bincrafters/stable | ||||
|     fmt/5.2.1@bincrafters/stable  | ||||
|     Seasocks/1.3.2@minres/stable | ||||
|     SystemC/2.3.2@minres/stable | ||||
|     SystemCVerification/2.0.1@minres/stable | ||||
| @@ -11,7 +12,8 @@ | ||||
|  | ||||
| [options] | ||||
|     Seasocks:shared=True | ||||
|     fmt:header_only=True | ||||
|     SystemC:stdcxx=14 | ||||
|     SystemC:shared=True | ||||
|     SystemCVerification:stdcxx=14 | ||||
|     SystemC-CCI:stdcxx=14 | ||||
|     SystemC-CCI:stdcxx=14 | ||||
|   | ||||
							
								
								
									
										2
									
								
								dbt-core
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								dbt-core
									
									
									
									
									
								
							 Submodule dbt-core updated: f76938cbdc...a9d808088e
									
								
							| @@ -25,7 +25,6 @@ endif() | ||||
| add_dependent_subproject(dbt-core) | ||||
| add_dependent_subproject(sc-components) | ||||
| add_dependent_subproject(riscv) | ||||
| add_dependent_subproject(riscv.sc) | ||||
|  | ||||
| include_directories( | ||||
|     ${PROJECT_SOURCE_DIR}/../external/elfio | ||||
|   | ||||
| @@ -30,7 +30,17 @@ set(LIBRARY_NAME platform) | ||||
| #add_definitions(-DSC_DEFAULT_WRITER_POLICY=SC_MANY_WRITERS) | ||||
|  | ||||
| # 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 | ||||
|   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}) | ||||
| # Links the target exe against the libraries | ||||
| target_link_libraries(${APPLICATION_NAME} ${LIBRARY_NAME}) | ||||
| target_link_libraries(${APPLICATION_NAME} riscv.sc) | ||||
| target_link_libraries(${APPLICATION_NAME} riscv) | ||||
| target_link_libraries(${APPLICATION_NAME} riscv_sc) | ||||
| target_link_libraries(${APPLICATION_NAME} dbt-core) | ||||
| target_link_libraries(${APPLICATION_NAME} softfloat) | ||||
| target_link_libraries(${APPLICATION_NAME} sc-components) | ||||
|   | ||||
| @@ -32,7 +32,6 @@ | ||||
|  | ||||
| #include "CLIParser.h" | ||||
| #include <sysc/top/system.h> | ||||
| #include <iss/jit/jit_helper.h> | ||||
| #include <iss/log_categories.h> | ||||
|  | ||||
| #include <scc/configurable_tracer.h> | ||||
| @@ -45,6 +44,7 @@ | ||||
| #include <cci_utils/broker.h> | ||||
|  | ||||
| #include <boost/program_options.hpp> | ||||
| #include <iss/llvm/jit_helper.h> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
|  | ||||
|   | ||||
| @@ -83,13 +83,13 @@ fe310::fe310(sc_core::sc_module_name nm) | ||||
|     size_t i = 0; | ||||
|     for (const auto &e : e300_plat_t_map) { | ||||
|         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_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->add_target_range(i, 0x80000000, 128_kB); | ||||
|     i_router->set_target_range(i, 0x80000000, 128_kB); | ||||
|  | ||||
|     i_uart0->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); | ||||
|     // 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); | ||||
|         reset_pending_int(v); | ||||
|         // 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 { | ||||
|     constants { | ||||
|         XLEN, | ||||
|         PCLEN, | ||||
|         XLEN_BIT_MASK:=0x1f, | ||||
|         fence:=0, | ||||
|         fencei:=1, | ||||
|         fencevmal:=2, | ||||
|         fencevmau:=3 | ||||
|     } | ||||
|      | ||||
|     address_spaces {  | ||||
|         MEM[8], CSR[XLEN], FENCE[XLEN] | ||||
|     } | ||||
|                  | ||||
|     registers {  | ||||
|         [31:0]   X[XLEN], | ||||
|                 PC[XLEN](is_pc), | ||||
|                 alias ZERO[XLEN] is X[0]  | ||||
|     } | ||||
| import "RISCVBase.core_desc" | ||||
| 
 | ||||
| InsructionSet RV32I extends RISCVBase{ | ||||
|       | ||||
|     instructions {  | ||||
|         LUI{ | ||||
|             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; | ||||
|         } | ||||
|         AUIPC{ | ||||
|             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; | ||||
|         } | ||||
|         JAL(no_cont){ | ||||
|             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; | ||||
|             PC<=PC's+imm; | ||||
|         } | ||||
|         JALR(no_cont){ | ||||
|             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 align[XLEN] <= new_pc & 0x2; | ||||
|             if(align != 0){ | ||||
| @@ -50,116 +33,116 @@ InsructionSet RV32IBase { | ||||
|         } | ||||
|         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; | ||||
|             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); | ||||
|         } | ||||
|         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; | ||||
|             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); | ||||
|         } | ||||
|         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; | ||||
|             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); | ||||
|         } | ||||
|         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; | ||||
|             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); | ||||
|         } | ||||
|         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; | ||||
|             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); | ||||
|         } | ||||
|         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; | ||||
|             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); | ||||
|         } | ||||
|         LB { | ||||
|             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; | ||||
|             if(rd!=0) X[rd]<=sext(MEM[offs]); | ||||
|         } | ||||
|         LH { | ||||
|             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; | ||||
|             if(rd!=0) X[rd]<=sext(MEM[offs]{16});             | ||||
|         } | ||||
|         LW { | ||||
|             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; | ||||
|             if(rd!=0) X[rd]<=sext(MEM[offs]{32}); | ||||
|         } | ||||
|         LBU { | ||||
|             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; | ||||
|             if(rd!=0) X[rd]<=zext(MEM[offs]); | ||||
|         } | ||||
|         LHU { | ||||
|             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; | ||||
|             if(rd!=0) X[rd]<=zext(MEM[offs]{16});             | ||||
|         } | ||||
|         SB { | ||||
|             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; | ||||
|             MEM[offs] <= X[rs2]; | ||||
|         } | ||||
|         SH { | ||||
|             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; | ||||
|             MEM[offs]{16} <= X[rs2]; | ||||
|         } | ||||
|         SW { | ||||
|             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; | ||||
|             MEM[offs]{32} <= X[rs2]; | ||||
|         } | ||||
|         ADDI { | ||||
|             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; | ||||
|         } | ||||
|         SLTI { | ||||
|             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); | ||||
|         } | ||||
|         SLTIU { | ||||
|             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; | ||||
|             if (rd != 0) X[rd] <= choose(X[rs1]'u < full_imm'u, 1, 0); | ||||
|         } | ||||
|         XORI { | ||||
|             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; | ||||
|         } | ||||
|         ORI { | ||||
|             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; | ||||
|         } | ||||
|         ANDI { | ||||
|             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; | ||||
|         } | ||||
|         SLLI { | ||||
|             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){ | ||||
|                 raise(0,0); | ||||
|             } else { | ||||
| @@ -168,7 +151,7 @@ InsructionSet RV32IBase { | ||||
|         } | ||||
|         SRLI { | ||||
|             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){ | ||||
|                 raise(0,0); | ||||
|             } else { | ||||
| @@ -177,7 +160,7 @@ InsructionSet RV32IBase { | ||||
|         } | ||||
|         SRAI { | ||||
|             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){ | ||||
|                 raise(0,0); | ||||
|             } else { | ||||
| @@ -186,52 +169,52 @@ InsructionSet RV32IBase { | ||||
|         } | ||||
|         ADD { | ||||
|             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]; | ||||
|         } | ||||
|         SUB { | ||||
|             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]; | ||||
|         } | ||||
|         SLL { | ||||
|             encoding: b0000000 | 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) X[rd] <= shll(X[rs1], X[rs2]&XLEN_BIT_MASK); | ||||
|             args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; | ||||
|             if(rd != 0) X[rd] <= shll(X[rs1], X[rs2]&(XLEN-1)); | ||||
|         } | ||||
|         SLT { | ||||
|             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); | ||||
|         } | ||||
|         SLTU { | ||||
|             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); | ||||
|         } | ||||
|         XOR { | ||||
|             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]; | ||||
|         } | ||||
|         SRL { | ||||
|             encoding: b0000000 | 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) X[rd] <= shrl(X[rs1], X[rs2]&XLEN_BIT_MASK); | ||||
|             args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; | ||||
|             if(rd != 0) X[rd] <= shrl(X[rs1], X[rs2]&(XLEN-1)); | ||||
|         } | ||||
|         SRA { | ||||
|             encoding: b0100000 | 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) X[rd] <= shra(X[rs1], X[rs2]&XLEN_BIT_MASK); | ||||
|             args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; | ||||
|             if(rd != 0) X[rd] <= shra(X[rs1], X[rs2]&(XLEN-1)); | ||||
|         } | ||||
|         OR { | ||||
|             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]; | ||||
|         } | ||||
|         AND { | ||||
|             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]; | ||||
|         } | ||||
|         FENCE { | ||||
| @@ -273,20 +256,20 @@ InsructionSet RV32IBase { | ||||
|         } | ||||
|         CSRRW { | ||||
|             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]; | ||||
|             if(rd!=0){ | ||||
|                 val csr_val[XLEN] <= CSR[csr]; | ||||
|                 CSR[csr] <= rs_val;  | ||||
|                 // make sure Xrd is updated once CSR write succeeds | ||||
|                    X[rd] <= csr_val; | ||||
|                } else { | ||||
|                 X[rd] <= csr_val; | ||||
|             } else { | ||||
|                 CSR[csr] <= rs_val; | ||||
|             } | ||||
|         } | ||||
|         CSRRS { | ||||
|             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 xrs1[XLEN] <= X[rs1]; | ||||
|             if(rd!=0) X[rd] <= xrd; | ||||
| @@ -294,7 +277,7 @@ InsructionSet RV32IBase { | ||||
|         } | ||||
|         CSRRC { | ||||
|             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 xrs1[XLEN] <= X[rs1]; | ||||
|             if(rd!=0) X[rd] <= xrd; | ||||
| @@ -302,13 +285,13 @@ InsructionSet RV32IBase { | ||||
|         } | ||||
|         CSRRWI { | ||||
|             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]; | ||||
|             CSR[csr] <= zext(zimm);     | ||||
|         } | ||||
|         CSRRSI { | ||||
|             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]; | ||||
|             if(zimm!=0) CSR[csr] <= res | zext(zimm); | ||||
|             // make sure rd is written after csr write succeeds     | ||||
| @@ -316,7 +299,7 @@ InsructionSet RV32IBase { | ||||
|         } | ||||
|         CSRRCI { | ||||
|             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]; | ||||
|             if(rd!=0) X[rd] <= res; | ||||
|             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{ | ||||
|         LWU { //    80000104: 0000ef03            lwu t5,0(ra) | ||||
|             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; | ||||
|             if(rd!=0) X[rd]<=zext(MEM[offs]{32}); | ||||
|         } | ||||
|         LD{ | ||||
|             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; | ||||
|             if(rd!=0) X[rd]<=sext(MEM[offs]{64}); | ||||
|         } | ||||
|         SD{ | ||||
|             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; | ||||
|             MEM[offs]{64} <= X[rs2]; | ||||
|         } | ||||
|         SLLI { | ||||
|             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); | ||||
|         } | ||||
|         SRLI { | ||||
|             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); | ||||
|         } | ||||
|         SRAI { | ||||
|             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); | ||||
|         } | ||||
|         ADDIW { | ||||
|             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){ | ||||
|                 val res[32] <= X[rs1]{32}'s + imm; | ||||
|                 X[rd] <= sext(res); | ||||
| @@ -45,7 +45,7 @@ InsructionSet RV64IBase extends RV32IBase { | ||||
|         } | ||||
|         SLLIW { | ||||
|             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){ | ||||
|                 val sh_val[32] <= shll(X[rs1]{32}, shamt); | ||||
|                 X[rd] <= sext(sh_val); | ||||
| @@ -53,7 +53,7 @@ InsructionSet RV64IBase extends RV32IBase { | ||||
|         } | ||||
|         SRLIW { | ||||
|             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){ | ||||
|                 val sh_val[32] <= shrl(X[rs1]{32}, shamt); | ||||
|                 X[rd] <= sext(sh_val); | ||||
| @@ -61,7 +61,7 @@ InsructionSet RV64IBase extends RV32IBase { | ||||
|         } | ||||
|         SRAIW { | ||||
|             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){ | ||||
|                 val sh_val[32] <= shra(X[rs1]{32}, shamt);     | ||||
|                 X[rd] <= sext(sh_val); | ||||
| @@ -83,7 +83,7 @@ InsructionSet RV64IBase extends RV32IBase { | ||||
|         } | ||||
|         SLLW { | ||||
|             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){ | ||||
|                 val mask[32] <= 0x1f; | ||||
|                 val count[32] <= X[rs2]{32} & mask; | ||||
| @@ -93,7 +93,7 @@ InsructionSet RV64IBase extends RV32IBase { | ||||
|         } | ||||
|         SRLW { | ||||
|             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){ | ||||
|                 val mask[32] <= 0x1f; | ||||
|                 val count[32] <= X[rs2]{32} & mask; | ||||
| @@ -103,7 +103,7 @@ InsructionSet RV64IBase extends RV32IBase { | ||||
|         } | ||||
|         SRAW { | ||||
|             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){ | ||||
|                 val mask[32] <= 0x1f; | ||||
|                 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{ | ||||
|         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; | ||||
|             args_disass: "x%rd$d, x%rs1$d, 0x%imm$x"; | ||||
|             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; | ||||
|                 PC<=new_pc & ~0x1; | ||||
|             } | ||||
|             args_disass: "{name(rd)}, {name(rs1)}, {imm:#0x}"; | ||||
|             val new_pc[XLEN] <= X[rs1]s + imm; | ||||
|             if(rd!=0) X[rd] <= PC+4; | ||||
|             PC<=new_pc & ~0x1; | ||||
|         } | ||||
|         C.ADDI4SPN { //(RES, imm=0) | ||||
|             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); | ||||
|             X[rd+8] <= X[2] + imm; | ||||
|         } | ||||
|         C.LW { // (RV32) | ||||
|             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; | ||||
|             X[rd+8] <= MEM[offs]{32}; | ||||
|             X[rd+8] <= sext(MEM[offs]{32}); | ||||
|         } | ||||
|         C.SW {//(RV32) | ||||
|             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; | ||||
|             MEM[offs]{32} <= X[rs2+8]; | ||||
|         } | ||||
|         C.ADDI {//(RV32) | ||||
|             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; | ||||
|         } | ||||
|         C.NOP { | ||||
| @@ -53,118 +39,118 @@ InsructionSet RV32IC { | ||||
|         // C.JAL will be overwritten by C.ADDIW for RV64/128 | ||||
|         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; | ||||
|             args_disass: "0x%imm$05x"; | ||||
|             args_disass: "{imm:#05x}"; | ||||
|             X[1] <= PC+2; | ||||
|             PC<=PC's+imm; | ||||
|         } | ||||
|         C.LI {//(RV32) | ||||
|             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? | ||||
|             X[rd] <= imm; | ||||
|         } | ||||
|         // order matters here as C.ADDI16SP overwrites C.LUI vor rd==2 | ||||
|         C.LUI {//(RV32) | ||||
|             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(imm == 0) raise(0, 2);   //TODO: should it be handled as trap? | ||||
|             X[rd] <= imm; | ||||
|         } | ||||
|         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; | ||||
|             args_disass: "0x%imm$05x"; | ||||
|             args_disass: "{imm:#05x}"; | ||||
|             X[2] <= X[2]s + imm; | ||||
|         } | ||||
|         C.SRLI {//(RV32 nse) | ||||
|             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; | ||||
|             X[rs1_idx] <= shrl(X[rs1_idx], shamt); | ||||
|         } | ||||
|         C.SRAI {//(RV32) | ||||
|             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; | ||||
|             X[rs1_idx] <= shra(X[rs1_idx], shamt); | ||||
|         } | ||||
|         C.ANDI {//(RV32) | ||||
|             encoding:b100 | imm[5:5] | b10 | rs1[2:0] | imm[4:0] | b01; | ||||
|             args_disass: "x(8+%rs1$d), 0x%imm$05x"; | ||||
|             encoding:b100 | imm[5:5]s | b10 | rs1[2:0] | imm[4:0]s | b01; | ||||
|             args_disass: "{name(8+rs1)}, {imm:#05x}"; | ||||
|             val rs1_idx[5] <= rs1 + 8; | ||||
|             X[rs1_idx] <= X[rs1_idx] & imm; | ||||
|             X[rs1_idx] <= X[rs1_idx]s & imm; | ||||
|         } | ||||
|         C.SUB {//(RV32) | ||||
|             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; | ||||
|             X[rd_idx] <= X[rd_idx] - X[rs2 + 8]; | ||||
|         } | ||||
|         C.XOR {//(RV32) | ||||
|             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; | ||||
|             X[rd_idx] <= X[rd_idx] ^ X[rs2 + 8]; | ||||
|         } | ||||
|         C.OR {//(RV32) | ||||
|             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; | ||||
|             X[rd_idx] <= X[rd_idx] | X[rs2 + 8]; | ||||
|         } | ||||
|         C.AND {//(RV32) | ||||
|             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; | ||||
|             X[rd_idx] <= X[rd_idx] & X[rs2 + 8]; | ||||
|         } | ||||
|         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; | ||||
|             args_disass: "0x%imm$05x"; | ||||
|             args_disass: "{imm:#05x}"; | ||||
|             PC<=PC's+imm; | ||||
|         } | ||||
|         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; | ||||
|             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); | ||||
|         } | ||||
|         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; | ||||
|             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); | ||||
|         } | ||||
|         C.SLLI {//(RV32) | ||||
|             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); | ||||
|             X[rs1] <= shll(X[rs1], shamt); | ||||
|         } | ||||
|         C.LWSP {// | ||||
|             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; | ||||
|             X[rd] <= MEM[offs]{32}; | ||||
|             X[rd] <= sext(MEM[offs]{32}); | ||||
|         } | ||||
|         // order matters as C.JR is a special case of C.MV | ||||
|         C.MV {//(RV32) | ||||
|             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]; | ||||
|         } | ||||
|         C.JR(no_cont) {//(RV32) | ||||
|             encoding:b100 | b0 | rs1[4:0] | b00000 | b10; | ||||
|             args_disass: "x%rs1$d"; | ||||
|             args_disass: "{name(rs1)}"; | ||||
|             PC <= X[rs1]; | ||||
|         } | ||||
|         // order matters as C.EBREAK is a special case of C.JALR which is a special case of C.ADD | ||||
|         C.ADD {//(RV32) | ||||
|             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]; | ||||
|         } | ||||
|         C.JALR(no_cont) {//(RV32) | ||||
|             encoding:b100 | b1 | rs1[4:0] | b00000 | b10; | ||||
|             args_disass: "x%rs1$d"; | ||||
|             args_disass: "{name(rs1)}"; | ||||
|             X[1] <= PC+2; | ||||
|             PC<=X[rs1]; | ||||
|         } | ||||
| @@ -174,7 +160,7 @@ InsructionSet RV32IC { | ||||
|         } | ||||
|         C.SWSP {// | ||||
|             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; | ||||
|             MEM[offs]{32} <= X[rs2]; | ||||
|         } | ||||
| @@ -187,19 +173,15 @@ InsructionSet RV32IC { | ||||
| 
 | ||||
| InsructionSet RV32FC extends RV32IC{ | ||||
|     constants { | ||||
|         XLEN, FLEN | ||||
|     } | ||||
|     address_spaces {  | ||||
|         MEM[8] | ||||
|         FLEN | ||||
|     } | ||||
|     registers {  | ||||
|         [31:0]   X[XLEN], | ||||
|         [31:0]   F[FLEN] | ||||
|     } | ||||
|     instructions{ | ||||
|         C.FLW { | ||||
|             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 res[32] <= MEM[offs]{32}; | ||||
|             if(FLEN==32) | ||||
| @@ -211,13 +193,13 @@ InsructionSet RV32FC extends RV32IC{ | ||||
|         }  | ||||
|         C.FSW { | ||||
|             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; | ||||
|             MEM[offs]{32}<=F[rs2+8]{32}; | ||||
|         } | ||||
|         C.FLWSP { | ||||
|             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 res[32] <= MEM[offs]{32}; | ||||
|             if(FLEN==32) | ||||
| @@ -229,7 +211,7 @@ InsructionSet RV32FC extends RV32IC{ | ||||
|         } | ||||
|         C.FSWSP { | ||||
|             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; | ||||
|             MEM[offs]{32}<=F[rs2]{32}; | ||||
|         }         | ||||
| @@ -238,19 +220,15 @@ InsructionSet RV32FC extends RV32IC{ | ||||
| 
 | ||||
| InsructionSet RV32DC extends RV32IC{ | ||||
|     constants { | ||||
|         XLEN, FLEN | ||||
|     } | ||||
|     address_spaces {  | ||||
|         MEM[8] | ||||
|         FLEN | ||||
|     } | ||||
|     registers {  | ||||
|         [31:0]   X[XLEN], | ||||
|         [31:0]   F[FLEN] | ||||
|     } | ||||
|     instructions{ | ||||
|         C.FLD { //(RV32/64) | ||||
|             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 res[64] <= MEM[offs]{64}; | ||||
|             if(FLEN==64) | ||||
| @@ -262,13 +240,13 @@ InsructionSet RV32DC extends RV32IC{ | ||||
|          } | ||||
|         C.FSD { //(RV32/64) | ||||
|             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; | ||||
|             MEM[offs]{64}<=F[rs2+8]{64}; | ||||
|         }  | ||||
|         C.FLDSP {//(RV32/64) | ||||
|             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 res[64] <= MEM[offs]{64}; | ||||
|             if(FLEN==64) | ||||
| @@ -280,7 +258,7 @@ InsructionSet RV32DC extends RV32IC{ | ||||
|         } | ||||
|         C.FSDSP {//(RV32/64) | ||||
|             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; | ||||
|             MEM[offs]{64}<=F[rs2]{64}; | ||||
|         } | ||||
| @@ -288,65 +266,94 @@ InsructionSet RV32DC extends RV32IC{ | ||||
| } | ||||
| 
 | ||||
| InsructionSet RV64IC extends RV32IC { | ||||
|     constants { | ||||
|         XLEN | ||||
|     } | ||||
|     address_spaces {  | ||||
|         MEM[8] | ||||
|     } | ||||
|     registers {  | ||||
|         [31:0]   X[XLEN], | ||||
|                 PC[XLEN](is_pc) | ||||
|     } | ||||
| 
 | ||||
|     instructions{ | ||||
|         C.LD {//(RV64/128)  | ||||
|             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)  | ||||
|             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) | ||||
|             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) | ||||
|             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) | ||||
|             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) | ||||
|             encoding:b100 | b0 | b01 | rs1[2:0] | b00000 | b01; | ||||
|         C.SRLI {//(RV64) | ||||
|             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) | ||||
|             encoding:b000 | b0 | rs1[4:0] | b00000 | b10; | ||||
|         C.SRAI {//(RV64) | ||||
|             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 | ||||
|             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) | ||||
|             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 { | ||||
|     constants { | ||||
|         XLEN | ||||
|     } | ||||
|     address_spaces {  | ||||
|         MEM[8] | ||||
|     } | ||||
|     registers {  | ||||
|         [31:0]   X[XLEN], | ||||
|                 PC[XLEN](is_pc) | ||||
|     } | ||||
| 
 | ||||
|     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) | ||||
|              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 { | ||||
|         FLEN, FFLAG_MASK := 0x1f | ||||
|     }  | ||||
| @@ -10,7 +10,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|     instructions{ | ||||
|         FLD { | ||||
|             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 res[64] <= MEM[offs]{64}; | ||||
|             if(FLEN==64) | ||||
| @@ -22,13 +22,13 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FSD { | ||||
|             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; | ||||
|             MEM[offs]{64}<=F[rs2]{64}; | ||||
|         } | ||||
|         FMADD.D { | ||||
|             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; | ||||
|             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) | ||||
| @@ -42,7 +42,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FMSUB.D { | ||||
|             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; | ||||
|             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) | ||||
| @@ -56,7 +56,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FNMADD.D { | ||||
|             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; | ||||
|             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) | ||||
| @@ -70,7 +70,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FNMSUB.D { | ||||
|             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; | ||||
|             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) | ||||
| @@ -84,7 +84,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FADD.D { | ||||
|             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; | ||||
|             val res[64] <= fdispatch_fadd_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); | ||||
|             if(FLEN==64) | ||||
| @@ -98,7 +98,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FSUB.D { | ||||
|             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; | ||||
|             val res[64] <= fdispatch_fsub_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); | ||||
|             if(FLEN==64) | ||||
| @@ -112,7 +112,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FMUL.D { | ||||
|             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; | ||||
|             val res[64] <= fdispatch_fmul_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); | ||||
|             if(FLEN==64) | ||||
| @@ -126,7 +126,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FDIV.D { | ||||
|             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; | ||||
|             val res[64] <= fdispatch_fdiv_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); | ||||
|             if(FLEN==64) | ||||
| @@ -140,7 +140,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FSQRT.D { | ||||
|             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); | ||||
|             val res[64] <= fdispatch_fsqrt_d(F[rs1]{64}, choose(rm<7, rm{8}, FCSR{8})); | ||||
|             if(FLEN==64) | ||||
| @@ -154,8 +154,11 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FSGNJ.D { | ||||
|             encoding: b0010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; | ||||
|             args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; | ||||
|             val res[64] <= (F[rs1]{64} & 0x7fffffff) | (F[rs2]{64} & 0x80000000); | ||||
|             args_disass:"f{rd}, f{rs1}, f{rs2}"; | ||||
|             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) | ||||
|                 F[rd] <= res; | ||||
|             else { // NaN boxing | ||||
| @@ -165,8 +168,11 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FSGNJN.D { | ||||
|             encoding: b0010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; | ||||
|             args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; | ||||
|             val res[64] <= (F[rs1]{64} & 0x7fffffff) | (~F[rs2]{64} & 0x80000000); | ||||
|             args_disass:"f{rd}, f{rs1}, f{rs2}"; | ||||
|             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) | ||||
|                 F[rd] <= res; | ||||
|             else { // NaN boxing | ||||
| @@ -176,8 +182,10 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FSGNJX.D { | ||||
|             encoding: b0010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; | ||||
|             args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; | ||||
|             val res[64] <= F[rs1]{64} ^ (F[rs2]{64} & 0x80000000); | ||||
|             args_disass:"f{rd}, f{rs1}, f{rs2}"; | ||||
|             val ONE[64] <= 1; | ||||
|             val MSK1[64] <= ONE<<63; | ||||
|             val res[64] <= F[rs1]{64} ^ (F[rs2]{64} & MSK1); | ||||
|             if(FLEN==64) | ||||
|                 F[rd] <= res; | ||||
|             else { // NaN boxing | ||||
| @@ -187,7 +195,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FMIN.D  { | ||||
|             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); | ||||
|             val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32)); | ||||
|             if(FLEN==64) | ||||
| @@ -201,7 +209,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FMAX.D { | ||||
|             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); | ||||
|             val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32)); | ||||
|             if(FLEN==64) | ||||
| @@ -215,7 +223,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FCVT.S.D { | ||||
|             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}); | ||||
|             // NaN boxing | ||||
|             val upper[FLEN] <= -1; | ||||
| @@ -223,7 +231,7 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FCVT.D.S { | ||||
|             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}); | ||||
|             if(FLEN==64){ | ||||
|                 F[rd] <= res; | ||||
| @@ -234,48 +242,49 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FEQ.D { | ||||
|             encoding: b1010001 | 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_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32)); | ||||
|             args_disass:"{name(rd)}, f{rs1}, f{rs2}"; | ||||
|             X[rd]<=zext(fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32))); | ||||
|             val flags[32] <= fdispatch_fget_flags(); | ||||
|             FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
|         } | ||||
|         FLT.D { | ||||
|             encoding: b1010001 | 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_d(F[rs1]{64}, F[rs2]{64}, zext(2, 32)); | ||||
|             args_disass:"{name(rd)}, f{rs1}, f{rs2}"; | ||||
|             X[rd]<=zext(fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(2, 32))); | ||||
|             val flags[32] <= fdispatch_fget_flags(); | ||||
|             FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
|         } | ||||
|         FLE.D { | ||||
|             encoding: b1010001 | 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_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32)); | ||||
|             args_disass:"{name(rd)}, f{rs1}, f{rs2}"; | ||||
|             X[rd]<=zext(fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32))); | ||||
|             val flags[32] <= fdispatch_fget_flags(); | ||||
|             FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
|         } | ||||
|         FCLASS.D { | ||||
|             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}); | ||||
|         } | ||||
|         FCVT.W.D { | ||||
|             encoding: b1100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
|             args_disass:"x%rd$d, f%rs1$d"; | ||||
|             X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(0, 32), rm{8}), XLEN); | ||||
|             args_disass:"{name(rd)}, f{rs1}"; | ||||
|             X[rd]<= sext(fdispatch_fcvt_64_32(F[rs1]{64}, zext(0, 32), rm{8}), XLEN); | ||||
|             val flags[32] <= fdispatch_fget_flags(); | ||||
|             FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
|         } | ||||
|         FCVT.WU.D { | ||||
|             encoding: b1100001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
|             args_disass:"x%rd$d, f%rs1$d"; | ||||
|             X[rd]<= zext(fdispatch_fcvt_d(F[rs1]{64}, zext(1, 32), rm{8}), XLEN); | ||||
|             args_disass:"{name(rd)}, f{rs1}"; | ||||
|             //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(); | ||||
|             FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; | ||||
|         } | ||||
|         FCVT.D.W { | ||||
|             encoding: b1101001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
|             args_disass:"f%rd$d, x%rs1$d"; | ||||
|             val res[64] <= fdispatch_fcvt_d(sext(X[rs1],64), zext(2, 32), rm{8}); | ||||
|             args_disass:"f{rd}, {name(rs1)}"; | ||||
|             val res[64] <= fdispatch_fcvt_32_64(sext(X[rs1]{32},64), zext(2, 32), rm{8}); | ||||
|             if(FLEN==64) | ||||
|                 F[rd] <= res; | ||||
|             else { // NaN boxing | ||||
| @@ -285,8 +294,8 @@ InsructionSet RV32D extends RV32IBase{ | ||||
|         } | ||||
|         FCVT.D.WU { | ||||
|             encoding: b1101001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; | ||||
|             args_disass:"f%rd$d, x%rs1$d"; | ||||
|             val res[64] <=fdispatch_fcvt_d(zext(X[rs1],64), zext(3,32), rm{8}); | ||||
|             args_disass:"f{rd}, {name(rs1)}"; | ||||
|             val res[64] <=fdispatch_fcvt_32_64(zext(X[rs1]{32},64), zext(3,32), rm{8}); | ||||
|             if(FLEN==64) | ||||
|                 F[rd] <= res; | ||||
|             else { // NaN boxing | ||||
| @@ -295,4 +304,57 @@ 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 "RV32M.core_desc" | ||||
| import "RV32A.core_desc" | ||||
| import "RV32C.core_desc" | ||||
| import "RV32F.core_desc" | ||||
| import "RV32D.core_desc" | ||||
| import "RV64IBase.core_desc" | ||||
| //import "RV64M.core_desc" | ||||
| import "RV64A.core_desc" | ||||
| import "RV32I.core_desc" | ||||
| import "RV64I.core_desc" | ||||
| import "RVM.core_desc" | ||||
| import "RVA.core_desc" | ||||
| import "RVC.core_desc" | ||||
| import "RVF.core_desc" | ||||
| import "RVD.core_desc" | ||||
|  | ||||
| Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32IC { | ||||
|     template:"vm_riscv.in.cpp"; | ||||
| Core RV32IMAC provides RV32I, RV32M, RV32A, RV32IC { | ||||
|     constants { | ||||
|         XLEN:=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 { | ||||
|         XLEN:=32; | ||||
|         FLEN:=64; | ||||
| @@ -34,16 +31,28 @@ Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC, RV32D, RV32 | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| Core RV64IA provides RV64IBase, RV64A, RV32A { | ||||
|     template:"vm_riscv.in.cpp"; | ||||
| Core RV64I provides RV64I { | ||||
|     constants { | ||||
|         XLEN:=64; | ||||
|         PCLEN:=64; | ||||
|         // definitions for the architecture wrapper | ||||
|         //          XL    ZYXWVUTSRQPONMLKJIHGFEDCBA | ||||
|         MISA_VAL:=0b10000000000001000000000100000001; | ||||
|         MISA_VAL:=0b10000000000001000000000100000000; | ||||
|         PGSIZE := 0x1000; //1 << 12; | ||||
|         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 | ||||
| // 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. | ||||
| //  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| /******************************************************************************* | ||||
|  * 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. | ||||
|  * | ||||
|  *******************************************************************************/ | ||||
|  | ||||
| <%  | ||||
| import com.minres.coredsl.coreDsl.Register | ||||
| import com.minres.coredsl.coreDsl.RegisterFile | ||||
| import com.minres.coredsl.coreDsl.RegisterAlias | ||||
| def getTypeSize(size){ | ||||
| 	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_ | ||||
| #define _${coreDef.name.toUpperCase()}_H_ | ||||
|  | ||||
| #include <array> | ||||
| #include <iss/arch/traits.h> | ||||
| #include <iss/arch_if.h> | ||||
| #include <iss/vm_if.h> | ||||
| #include <iss/arch/traits.h> | ||||
| #include <array> | ||||
|  | ||||
| namespace iss { | ||||
| namespace arch { | ||||
|  | ||||
| struct ${coreDef.name.toLowerCase()}; | ||||
|  | ||||
| template<> | ||||
| struct traits<${coreDef.name.toLowerCase()}> { | ||||
| template <> struct traits<${coreDef.name.toLowerCase()}> { | ||||
|  | ||||
| 	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(', ')}}; | ||||
|  | ||||
|     constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0}; | ||||
| @@ -65,7 +106,7 @@ struct traits<${coreDef.name.toLowerCase()}> { | ||||
|         ${reg.name}${it},<% | ||||
|                 } | ||||
|             } else if(reg instanceof Register){ %> | ||||
|         ${reg.name},<% | ||||
|         ${reg.name},<%   | ||||
|             } | ||||
|         }%> | ||||
|         NUM_REGS, | ||||
| @@ -74,7 +115,12 @@ struct traits<${coreDef.name.toLowerCase()}> { | ||||
|         PENDING_TRAP, | ||||
|         MACHINE_STATE, | ||||
|         LAST_BRANCH, | ||||
|         ICOUNT | ||||
|         ICOUNT<%  | ||||
|      	allRegs.each { reg ->  | ||||
|     		if(reg instanceof RegisterAlias){ def aliasname=getOriginalName(reg)%>, | ||||
|         ${reg.name} = ${aliasname}<% | ||||
|             } | ||||
|         }%> | ||||
|     }; | ||||
|  | ||||
|     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>; | ||||
|  | ||||
|     constexpr static unsigned reg_bit_width(unsigned r) { | ||||
|         constexpr std::array<const uint32_t, ${regSizes.size}> ${coreDef.name}_reg_size{{${regSizes.join(",")}}}; | ||||
|         return ${coreDef.name}_reg_size[r]; | ||||
|     } | ||||
|  	static constexpr std::array<const uint32_t, ${regSizes.size}> reg_bit_widths{ | ||||
|  		{${regSizes.join(",")}}}; | ||||
|  | ||||
|     constexpr static unsigned reg_byte_offset(unsigned r) { | ||||
|     	constexpr std::array<const uint32_t, ${regOffsets.size}> ${coreDef.name}_reg_byte_offset{{${regOffsets.join(",")}}}; | ||||
|         return ${coreDef.name}_reg_byte_offset[r]; | ||||
|     } | ||||
|     static constexpr std::array<const uint32_t, ${regOffsets.size}> reg_byte_offsets{ | ||||
|     	{${regOffsets.join(",")}}}; | ||||
|  | ||||
|     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 { | ||||
| @@ -126,12 +168,13 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { | ||||
|     /// deprecated | ||||
|     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){ | ||||
|         if(addr.space != traits<${coreDef.name.toLowerCase()}>::MEM || | ||||
|                 addr.type == iss::address_type::PHYSICAL || | ||||
|                 addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL){ | ||||
|         if (addr.space != traits<${coreDef.name.toLowerCase()}>::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<${coreDef.name.toLowerCase()}>::addr_mask); | ||||
|         } else | ||||
|             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; } | ||||
|  | ||||
|     inline | ||||
|     uint32_t get_last_branch(){return reg.last_branch;} | ||||
|     inline uint32_t get_last_branch() { return reg.last_branch; } | ||||
|  | ||||
| protected: | ||||
|     struct ${coreDef.name}_regs {<% | ||||
|   | ||||
| @@ -1,35 +1,73 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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. | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| /******************************************************************************* | ||||
|  * 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. | ||||
|  * | ||||
|  *******************************************************************************/ | ||||
|  <%  | ||||
| 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/logging.h> | ||||
|  | ||||
| @@ -43,18 +81,22 @@ extern "C" { | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #include <fstream> | ||||
| #include <cstdio> | ||||
| #include <cstring> | ||||
| #include <fstream> | ||||
|  | ||||
| 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()}() { | ||||
|     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) { | ||||
|     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,10 +104,11 @@ void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { | ||||
|     reg.NEXT_PC=reg.PC; | ||||
|     reg.trap_state=0; | ||||
|     reg.machine_state=0x0; | ||||
|     reg.icount=0; | ||||
| } | ||||
|  | ||||
| uint8_t* ${coreDef.name.toLowerCase()}::get_regs_base_ptr(){ | ||||
|     return reinterpret_cast<uint8_t*>(®); | ||||
| uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { | ||||
| 	return reinterpret_cast<uint8_t*>(®); | ||||
| } | ||||
|  | ||||
| ${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &pc) { | ||||
|   | ||||
| @@ -1,56 +1,52 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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. | ||||
| // | ||||
| // Contributors: | ||||
| //       eyck@minres.com - initial API and implementation | ||||
| // | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| /******************************************************************************* | ||||
|  * 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/${coreDef.name.toLowerCase()}.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 <iss/llvm/vm_base.h> | ||||
| #include <util/logging.h> | ||||
|  | ||||
| #include <boost/format.hpp> | ||||
| #include <fmt/format.h> | ||||
|  | ||||
| #include <iss/debugger/riscv_target_adapter.h> | ||||
| #include <array> | ||||
| #include <iss/debugger/riscv_target_adapter.h> | ||||
|  | ||||
| namespace iss { | ||||
| namespace vm { | ||||
| namespace fp_impl{ | ||||
| void add_fp_functions_2_module(llvm::Module *, unsigned); | ||||
| namespace fp_impl { | ||||
| void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); | ||||
| } | ||||
| } | ||||
|  | ||||
| @@ -58,10 +54,11 @@ namespace ${coreDef.name.toLowerCase()} { | ||||
| using namespace iss::arch; | ||||
| using namespace llvm; | ||||
| 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: | ||||
|     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 phys_addr_t = typename super::phys_addr_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; } | ||||
|  | ||||
|     target_adapter_if *accquire_target_adapter(server_if *srv) { | ||||
|     target_adapter_if *accquire_target_adapter(server_if *srv) override { | ||||
|         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; | ||||
|         if (vm_base<ARCH>::tgt_adapter == nullptr) | ||||
|             vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch()); | ||||
|         return vm_base<ARCH>::tgt_adapter; | ||||
|     } | ||||
|  | ||||
| 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) { | ||||
|         return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); | ||||
|     inline const char *name(size_t index){return traits<ARCH>::reg_aliases.at(index);} | ||||
|  | ||||
|     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); | ||||
|         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)); | ||||
|     } | ||||
|  | ||||
|     std::tuple<vm::continuation_e, llvm::BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &, | ||||
|                                                                                 llvm::BasicBlock *) override; | ||||
|     std::tuple<continuation_e, BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &, 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); | ||||
|  | ||||
| @@ -107,17 +105,17 @@ protected: | ||||
|  | ||||
|     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); | ||||
|     } | ||||
|  | ||||
|     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)); | ||||
|         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); | ||||
|     } | ||||
|  | ||||
| @@ -128,17 +126,17 @@ protected: | ||||
|     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); | ||||
|     using compile_func = std::tuple<continuation_e, BasicBlock *> (this_class::*)(virt_addr_t &pc, | ||||
|                                                                                   code_word_t instr, | ||||
|                                                                                   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<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[], | ||||
|                          compile_func f) { | ||||
| @@ -196,15 +194,14 @@ private: | ||||
|   | ||||
|     /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> | ||||
|     /* 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}<%}%> | ||||
|     } | ||||
|     <%}%> | ||||
|     /**************************************************************************** | ||||
|      * end opcode definitions | ||||
|      ****************************************************************************/ | ||||
|     std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, | ||||
|                                                                           llvm::BasicBlock *bb) { | ||||
|     std::tuple<continuation_e, BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, 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); | ||||
| @@ -216,7 +213,7 @@ private: | ||||
|         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); | ||||
|         return std::make_tuple(BRANCH, nullptr); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| @@ -229,7 +226,7 @@ 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) { | ||||
| : vm_base<ARCH>(core, core_id, cluster_id) { | ||||
|     qlut[0] = lut_00.data(); | ||||
|     qlut[1] = lut_01.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> | ||||
| 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) { | ||||
| std::tuple<continuation_e, BasicBlock *> | ||||
| 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 | ||||
|     enum {TRAP_ID=1<<16}; | ||||
|     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); | ||||
|     auto *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(TRAP_ID, pc.val); | ||||
|         if ((insn & 0x3) == 0x3) { // this is a 32bit instruction | ||||
|             res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); | ||||
|         } | ||||
|     } catch (trap_access &ta) { | ||||
|         throw trap_access(ta.id, pc.val); | ||||
|     } else { | ||||
|         auto res = this->core.read(paddr, 4, data); | ||||
|         if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); | ||||
|     } | ||||
|     if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' | ||||
|     // 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); | ||||
| } | ||||
|  | ||||
| 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.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) { | ||||
|     std::vector<llvm::Value *> args{ | ||||
|         this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)), | ||||
|     }; | ||||
|     std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), 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); | ||||
| @@ -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) { | ||||
|     std::vector<llvm::Value *> args{ | ||||
|         this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)), | ||||
|     }; | ||||
|     std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), 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) { | ||||
| template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) { | ||||
|     this->builder.SetInsertPoint(trap_blk); | ||||
|     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); | ||||
|     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.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), | ||||
|                               get_reg_ptr(traits<ARCH>::LAST_BRANCH), false); | ||||
|     std::vector<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) { | ||||
| 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); | ||||
|     this->gen_cond_branch(this->builder.CreateICmp( | ||||
|                               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); | ||||
| } | ||||
|  | ||||
| @@ -327,10 +316,9 @@ template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBl | ||||
|  | ||||
| template <> | ||||
| 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 = | ||||
|         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.get(), port); | ||||
|     return ret; | ||||
|     auto ret = new ${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*core, dump); | ||||
|     if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port); | ||||
|     return std::unique_ptr<vm_if>(ret); | ||||
| } | ||||
|  | ||||
| } // 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/log_categories.h" | ||||
| #include "iss/vm_if.h" | ||||
| #include <fmt/format.h> | ||||
| #include <array> | ||||
| #include <elfio/elfio.hpp> | ||||
| #include <iomanip> | ||||
| @@ -478,10 +479,8 @@ public: | ||||
|     void wait_until(uint64_t flags) override; | ||||
|  | ||||
|     void disass_output(uint64_t pc, const std::string instr) override { | ||||
|         std::stringstream s; | ||||
|         s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0') | ||||
|           << 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(); | ||||
|         CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [p:{};s:0x{:x};c:{}]", | ||||
|                 pc, instr, lvl[this->reg.machine_state], (reg_t)state.mstatus, this->reg.icount); | ||||
|     }; | ||||
|  | ||||
|     iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } | ||||
|   | ||||
| @@ -1,53 +1,59 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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. | ||||
| //  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| /******************************************************************************* | ||||
|  * 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 _RV32GC_H_ | ||||
| #define _RV32GC_H_ | ||||
|  | ||||
| #include <array> | ||||
| #include <iss/arch/traits.h> | ||||
| #include <iss/arch_if.h> | ||||
| #include <iss/vm_if.h> | ||||
| #include <iss/arch/traits.h> | ||||
| #include <array> | ||||
|  | ||||
| namespace iss { | ||||
| namespace arch { | ||||
|  | ||||
| struct rv32gc; | ||||
|  | ||||
| template<> | ||||
| struct traits<rv32gc> { | ||||
| template <> struct traits<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}; | ||||
|  | ||||
|     constexpr static unsigned FP_REGS_SIZE = 64; | ||||
| @@ -125,7 +131,39 @@ struct traits<rv32gc> { | ||||
|         PENDING_TRAP, | ||||
|         MACHINE_STATE, | ||||
|         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; | ||||
| @@ -138,21 +176,17 @@ struct traits<rv32gc> { | ||||
|  | ||||
|     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, 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}}; | ||||
|         return RV32GC_reg_size[r]; | ||||
|     } | ||||
|  	static constexpr std::array<const uint32_t, 72> 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,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}}; | ||||
|  | ||||
|     constexpr static unsigned reg_byte_offset(unsigned r) { | ||||
|     	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}}; | ||||
|         return RV32GC_reg_byte_offset[r]; | ||||
|     } | ||||
|     static constexpr std::array<const uint32_t, 73> 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,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}}; | ||||
|  | ||||
|     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 { | ||||
| @@ -177,14 +211,13 @@ struct rv32gc: public arch_if { | ||||
|     /// deprecated | ||||
|     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){ | ||||
|         if(addr.space != traits<rv32gc>::MEM || | ||||
|                 addr.type == iss::address_type::PHYSICAL || | ||||
|                 addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL){ | ||||
|         if (addr.space != traits<rv32gc>::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<rv32gc>::addr_mask); | ||||
|         } else | ||||
|             return virt2phys(addr); | ||||
| @@ -194,8 +227,7 @@ struct rv32gc: public arch_if { | ||||
|  | ||||
|     virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } | ||||
|  | ||||
|     inline | ||||
|     uint32_t get_last_branch(){return reg.last_branch;} | ||||
|     inline uint32_t get_last_branch() { return reg.last_branch; } | ||||
|  | ||||
| protected: | ||||
|     struct RV32GC_regs { | ||||
|   | ||||
| @@ -30,6 +30,7 @@ | ||||
|  * | ||||
|  *******************************************************************************/ | ||||
|  | ||||
|  | ||||
| #ifndef _RV32IMAC_H_ | ||||
| #define _RV32IMAC_H_ | ||||
|  | ||||
| @@ -45,15 +46,15 @@ struct rv32imac; | ||||
|  | ||||
| template <> struct traits<rv32imac> { | ||||
|  | ||||
|     constexpr static char const *const core_type = "RV32IMAC"; | ||||
| 	constexpr static char const* const core_type = "RV32IMAC"; | ||||
|      | ||||
|   	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 = 32, | ||||
|         PCLEN = 32, | ||||
|         MISA_VAL = 0b1000000000101000001000100000101, | ||||
|         PGSIZE = 0x1000, | ||||
|         PGMASK = 0xfff | ||||
|     }; | ||||
|     enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000101000001000100000101, PGSIZE=0x1000, PGMASK=0xfff}; | ||||
|  | ||||
|     constexpr static unsigned FP_REGS_SIZE = 0; | ||||
|  | ||||
| @@ -92,35 +93,61 @@ template <> struct traits<rv32imac> { | ||||
|         X31, | ||||
|         PC, | ||||
|         NUM_REGS, | ||||
|         NEXT_PC = NUM_REGS, | ||||
|         NEXT_PC=NUM_REGS, | ||||
|         TRAP_STATE, | ||||
|         PENDING_TRAP, | ||||
|         MACHINE_STATE, | ||||
|         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 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 phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; | ||||
|  | ||||
|     static constexpr std::array<const uint32_t, 39> RV32IMAC_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, 32, 32, 32, 32, 32, 64}}; | ||||
|  	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,64}}; | ||||
|  | ||||
|     constexpr static unsigned reg_bit_width(unsigned r) { return RV32IMAC_reg_size[r]; } | ||||
|  | ||||
|     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 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 const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); | ||||
|  | ||||
| @@ -129,41 +156,41 @@ template <> struct traits<rv32imac> { | ||||
|     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 phys_addr_t = typename traits<rv32imac>::phys_addr_t; | ||||
|     using reg_t = typename traits<rv32imac>::reg_t; | ||||
|     using reg_t =  typename traits<rv32imac>::reg_t; | ||||
|     using addr_t = typename traits<rv32imac>::addr_t; | ||||
|  | ||||
|     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 | ||||
|     void get_reg(short idx, std::vector<uint8_t> &value) override {} | ||||
|     void set_reg(short idx, const 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 {} | ||||
|     /// deprecated | ||||
|     bool get_flag(int flag) override { return false; } | ||||
|     void set_flag(int, bool value) override{}; | ||||
|     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{}; | ||||
|     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) { | ||||
|     inline phys_addr_t v2p(const iss::addr_t& addr){ | ||||
|         if (addr.space != traits<rv32imac>::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<rv32imac>::addr_mask); | ||||
|                 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); | ||||
|         } else | ||||
|             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; } | ||||
|  | ||||
| @@ -210,12 +237,14 @@ protected: | ||||
|     } reg; | ||||
|  | ||||
|     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_ */ | ||||
|   | ||||
							
								
								
									
										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 <memory> | ||||
| #include <fmt/format.h> | ||||
| #include <util/logging.h> | ||||
|  | ||||
| namespace iss { | ||||
| @@ -180,8 +181,8 @@ status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, st | ||||
|     avail.clear(); | ||||
|     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) { | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8; | ||||
|         unsigned offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         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_offsets[reg_no]; | ||||
|         for (size_t j = 0; j < reg_width; ++j) { | ||||
|             data.push_back(*(reg_base + offset + j)); | ||||
|             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 iter = data.data(); | ||||
|     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 offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         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_offsets[reg_no]; | ||||
|         std::copy(iter, iter + reg_width, reg_base); | ||||
|         iter += 4; | ||||
|         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 | ||||
|         // arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         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); | ||||
|         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::fill(avail.begin(), avail.end(), 0xff); | ||||
|     } 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) { | ||||
|     if (reg_no < 65) { | ||||
|         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 offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         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_offsets[reg_no]; | ||||
|         std::copy(data.begin(), data.begin() + reg_width, reg_base + offset); | ||||
|     } else { | ||||
|         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) { | ||||
|     if (first) { | ||||
|         std::stringstream ss; | ||||
|         ss << "m" << std::hex << thread_idx.val; | ||||
|         out_buf = ss.str(); | ||||
|         out_buf = fmt::format("m{:x}", thread_idx.val); | ||||
|     } else { | ||||
|         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, | ||||
|                                                     std::function<void(unsigned)> stop_callback) { | ||||
|     auto *reg_base = core->get_regs_base_ptr(); | ||||
|     auto reg_width = arch::traits<ARCH>::reg_bit_width(arch::traits<ARCH>::PC) / 8; | ||||
|     auto offset = traits<ARCH>::reg_byte_offset(arch::traits<ARCH>::PC); | ||||
|     auto reg_width = arch::traits<ARCH>::reg_bit_widths[arch::traits<ARCH>::PC] / 8; | ||||
|     auto offset = traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]; | ||||
|     const uint8_t *iter = reinterpret_cast<const uint8_t *>(&addr); | ||||
|     std::copy(iter, iter + reg_width, reg_base); | ||||
|     return resume_from_current(step, sig, thread, stop_callback); | ||||
|   | ||||
| @@ -4,18 +4,16 @@ set(LIB_HEADERS ${RiscVSCHeaders} ) | ||||
| set(LIB_SOURCES  | ||||
| 	iss/rv32gc.cpp | ||||
| 	iss/rv32imac.cpp | ||||
| 	iss/rv64ia.cpp | ||||
| 	iss/rv64i.cpp | ||||
| 	iss/rv64gc.cpp | ||||
| 	internal/fp_functions.cpp | ||||
| 	internal/vm_rv32gc.cpp | ||||
| 	internal/vm_rv32imac.cpp | ||||
| 	internal/vm_rv64ia.cpp | ||||
| 	internal/vm_rv64i.cpp | ||||
| 	internal/vm_rv64gc.cpp | ||||
|     plugin/instruction_count.cpp | ||||
|     plugin/cycle_estimate.cpp) | ||||
|  | ||||
| set(APP_HEADERS ) | ||||
|  | ||||
| set(APP_SOURCES main.cpp) | ||||
|  | ||||
| # Define two variables in order not to repeat ourselves. | ||||
| set(LIBRARY_NAME riscv) | ||||
|  | ||||
| @@ -27,17 +25,44 @@ set_target_properties(${LIBRARY_NAME} PROPERTIES | ||||
|   FRAMEWORK FALSE | ||||
|   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" | ||||
| set(APPLICATION_NAME riscv-sim) | ||||
|  | ||||
| add_executable(${APPLICATION_NAME} ${APP_SOURCES}) | ||||
| add_executable(${APPLICATION_NAME} main.cpp) | ||||
|  | ||||
| # Links the target exe against the libraries | ||||
| 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} softfloat) | ||||
| target_link_libraries(${APPLICATION_NAME} sc-components) | ||||
| target_link_libraries(${APPLICATION_NAME} external) | ||||
| target_link_libraries(${APPLICATION_NAME} ${llvm_libs}) | ||||
| target_link_libraries(${APPLICATION_NAME} ${Boost_LIBRARIES} ) | ||||
|   | ||||
| @@ -33,7 +33,7 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #include <iss/iss.h> | ||||
| #include <iss/vm_base.h> | ||||
| #include <iss/llvm/vm_base.h> | ||||
|  | ||||
| extern "C" { | ||||
| #include <softfloat.h> | ||||
| @@ -70,7 +70,7 @@ using namespace std; | ||||
|  | ||||
| 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){ | ||||
|         FDECL(fget_flags, INT_TYPE(32)); | ||||
|         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(fsel_s,     INT_TYPE(32), INT_TYPE(32), 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){ | ||||
|             FDECL(fconv_d2f,  INT_TYPE(32), INT_TYPE(64), 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(fsel_d,     INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); | ||||
|             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}; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float32_t r; | ||||
|     int32_t res; | ||||
|     switch(op){ | ||||
|     case 0: //w->s, fp to int32 | ||||
|         res = f32_to_i32(v1f,rmm_map[mode&0x7],true); | ||||
|     case 0:{ //w->s, fp to int32 | ||||
|         uint_fast32_t res = f32_to_i32(v1f,rmm_map[mode&0x7],true); | ||||
|         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 | ||||
|         r=i32_to_f32(v1); | ||||
|         return r.v; | ||||
| @@ -373,17 +379,19 @@ uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) { | ||||
|     float64_t v1f{v1}; | ||||
|     softfloat_exceptionFlags=0; | ||||
|     float64_t r; | ||||
|     int32_t res; | ||||
|     switch(op){ | ||||
|     case 0: //w->s, fp to int32 | ||||
|         res = f64_to_i64(v1f,rmm_map[mode&0x7],true); | ||||
|     case 0:{ //l->d, fp to int32 | ||||
|         int64_t res = f64_to_i64(v1f,rmm_map[mode&0x7],true); | ||||
|         return (uint64_t)res; | ||||
|     case 1: //wu->s | ||||
|         return f64_to_ui64(v1f,rmm_map[mode&0x7],true); | ||||
|     case 2: //s->w | ||||
|     } | ||||
|     case 1:{ //lu->s | ||||
|         uint64_t res = f64_to_ui64(v1f,rmm_map[mode&0x7],true); | ||||
|         return res; | ||||
|     } | ||||
|     case 2: //s->l | ||||
|         r=i64_to_f64(v1); | ||||
|         return r.v; | ||||
|     case 3: //s->wu | ||||
|     case 3: //s->lu | ||||
|         r=ui64_to_f64(v1); | ||||
|         return r.v; | ||||
|     } | ||||
| @@ -454,5 +462,53 @@ uint64_t fclass_d(uint64_t v1  ){ | ||||
|         ( 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 | ||||
| // 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. | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| /******************************************************************************* | ||||
|  * 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> | ||||
| @@ -49,6 +49,11 @@ extern "C" { | ||||
|  | ||||
| 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() { | ||||
|     reg.icount=0; | ||||
| } | ||||
|   | ||||
| @@ -49,8 +49,10 @@ extern "C" { | ||||
|  | ||||
| using namespace iss::arch; | ||||
|  | ||||
| constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::rv32imac>::RV32IMAC_reg_size; | ||||
| 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_names; | ||||
| 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() { | ||||
|     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/rv32imac.h> | ||||
| #include <iss/arch/rv32gc.h> | ||||
| #include <iss/arch/rv64ia.h> | ||||
| #include <iss/jit/jit_helper.h> | ||||
| #include <iss/arch/rv64gc.h> | ||||
| #include <iss/arch/rv64i.h> | ||||
| #include <iss/llvm/jit_helper.h> | ||||
| #include <iss/log_categories.h> | ||||
| #include <iss/plugin/cycle_estimate.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::string isa_opt(clim["isa"].as<std::string>()); | ||||
|         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>()); | ||||
|             cpu.reset(lcpu); | ||||
|         } else if (isa_opt=="rv32imac") { | ||||
|   | ||||
 Submodule sc-components updated: 1859c341ab...fa2e0c8998
									
								
							
		Reference in New Issue
	
	Block a user