Added RV32F extension, fixed RV32M bugs

This commit is contained in:
Eyck Jentzsch 2018-04-24 11:05:11 +02:00
parent bc7450dad2
commit 48ad30dcae
21 changed files with 8208 additions and 512 deletions

View File

@ -13,7 +13,7 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.debug.1751741082" name="Debug" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=" parent="cdt.managedbuild.config.gnu.exe.debug">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.debug.1751741082" name="Debug" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="cdt.managedbuild.config.gnu.exe.debug">
<folderInfo id="cdt.managedbuild.config.gnu.exe.debug.1751741082." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.1289745146" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
<targetPlatform binaryParser="org.eclipse.cdt.core.GNU_ELF;org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.exe.debug.1460698591" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/>
@ -46,6 +46,13 @@
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule buildDir="build/${ConfigName}" moduleId="de.marw.cdt.cmake.core.settings">
<options/>
<linux command="cmake" generator="UnixMakefiles" use-default="true">
<defs>
<def name="CMAKE_VERBOSE_MAKEFILE" type="BOOL" val="OFF"/>
</defs>
</linux>
<win32 command="cmake" generator="MinGWMakefiles" use-default="true">
</win32>
</storageModule>
</cconfiguration>
<cconfiguration id="cdt.managedbuild.config.gnu.exe.release.1745230171">
@ -177,4 +184,5 @@
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
</cproject>

View File

@ -0,0 +1,11 @@
eclipse.preferences.version=1
environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/LLVM_HOME/delimiter=\:
environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/LLVM_HOME/operation=replace
environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/LLVM_HOME/value=/usr/lib/llvm-4.0
environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true
environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/delimiter=\:
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/operation=append
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/value=/usr/lib/llvm-6.0
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true

@ -1 +1 @@
Subproject commit bc05d40184ccb8871afa61620fe2c67ce2951fa4
Subproject commit d9512853b22e869938013c8dc0c6678a92d52c0e

View File

@ -2,7 +2,7 @@
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/dbt-riscv/riscv&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LAUNCH_CONFIGURATION_BUILD_SCOPE" value="${none}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/usr/lib/jvm/java-8-oracle/bin/java"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-jar ${env_var:HOME}/git/JIT-ISS-CoreDsl/com.minres.coredsl.standalone/target/com.minres.coredsl.standalone-1.0.0-SNAPSHOT.jar&#10;-i=${project_loc:dbt-riscv}/riscv/incl/iss/arch&#10;-s=${project_loc:dbt-riscv}/riscv/src/iss&#10;-v=${project_loc:dbt-riscv}/riscv/src/internal&#10;-t=${project_loc:dbt-riscv}/riscv/gen_input/templates&#10;${project_loc:dbt-riscv}/riscv/gen_input/minres_rv.core_desc"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/dbt-riscv}/riscv/gen_input"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/usr/bin/java"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-Xmx1G -jar ${env_var:HOME}/git/JIT-ISS-CoreDsl/com.minres.coredsl.standalone/target/com.minres.coredsl.standalone-1.0.0-SNAPSHOT.jar&#10;-i=${project_loc:DBT-RISE-RISCV}/riscv/incl/iss/arch&#10;-s=${project_loc:DBT-RISE-RISCV}/riscv/src/iss&#10;-v=${project_loc:DBT-RISE-RISCV}/riscv/src/internal&#10;-t=${project_loc:DBT-RISE-RISCV}/riscv/gen_input/templates&#10;${project_loc:DBT-RISE-RISCV}/riscv/gen_input/minres_rv.core_desc"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/DBT-RISE-RISCV}/riscv/gen_input"/>
</launchConfiguration>

View File

@ -1,6 +1,6 @@
import "RV32IBase.core_desc"
InsructionSet RV32CI {
InsructionSet RV32IC {
constants {
XLEN
}
@ -197,7 +197,64 @@ InsructionSet RV32CI {
}
}
InsructionSet RV32CF extends RV32CI {
InsructionSet RV32FC extends RV32IC{
constants {
XLEN, FLEN
}
address_spaces {
MEM[8]
}
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))";
val rs1_idx[5] <= rs1+8;
val rd_idx[5] <= rd+8;
val offs[XLEN] <= X[rs1_idx]+uimm;
val res[32] <= MEM[offs]{32};
if(FLEN==32)
F[rd_idx] <= res;
else {
val upper[FLEN] <= (-1<<31);
F[rd_idx] <= upper*2 | res;
}
}
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))";
val rs1_idx[5] <= rs1+8;
val rs2_idx[5] <= rs2+8;
val offs[XLEN] <= X[rs1_idx]+uimm;
MEM[offs]{32}<=F[rs2_idx]{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)";
val x2_idx[5] <= 2;
val offs[XLEN] <= X[x2_idx]+uimm;
val res[32] <= MEM[offs]{32};
if(FLEN==32)
F[rd] <= res;
else {
val upper[FLEN] <= (-1<<31);
F[rd] <= upper*2 | res;
}
}
C.FSWSP {
encoding:b111 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10;
args_disass:"f%rs2$d, %uimm%(x2), ";
val x2_idx[5] <= 2;
val offs[XLEN] <= X[x2_idx]+uimm;
MEM[offs]{32}<=F[rs2];
}
}
}
InsructionSet RV32DC extends RV32IC{
constants {
XLEN, FLEN
}
@ -212,31 +269,19 @@ InsructionSet RV32CF extends RV32CI {
C.FLD { //(RV32/64)
encoding: b001 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00;
}
C.FLW {//(RV32)
encoding: b011 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00;
}
C.FSD { //(RV32/64)
encoding: b101 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00;
}
C.FSW {//(RV32)
encoding: b111 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00;
}
C.FLDSP {//(RV32/64)
encoding:b001 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10;
}
C.FLWSP {//RV32
encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10;
}
C.FSDSP {//(RV32/64)
encoding:b101 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10;
}
C.FSWSP {//(RV32)
encoding:b111 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10;
}
}
}
InsructionSet RV64CI extends RV32CI {
InsructionSet RV64IC extends RV32IC {
constants {
XLEN
}
@ -284,7 +329,7 @@ InsructionSet RV64CI extends RV32CI {
}
}
InsructionSet RV128CI extends RV64CI {
InsructionSet RV128IC extends RV64IC {
constants {
XLEN
}

View File

@ -2,104 +2,293 @@ import "RV32IBase.core_desc"
InsructionSet RV32F extends RV32IBase{
constants {
FLEN, fcsr
FLEN, FFLAG_MASK
}
registers {
[31:0] F[FLEN]
[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]+imm;
F[rd]<=MEM[offs];
val res[32] <= MEM[offs]{32};
if(FLEN==32)
F[rd] <= res;
else {
val upper[FLEN] <= (-1<<31);
F[rd] <= upper*2 | res;
}
}
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]+imm;
MEM[offs]<=F[rs2];
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;
F[rd]f<= F[rs1]f * F[rs2]f * F[rs3]f;
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 {
val upper[FLEN] <= (-1<<31);
F[rd] <= upper*2 | res;
}
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;
F[rd]f<=F[rs1]f * F[rs2]f -F[rs3]f;
}
FNMSUB.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011;
F[rd]f<=-F[rs1]f * F[rs2]f- F[rs3]f;
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 {
val upper[FLEN] <= (-1<<31);
F[rd] <= upper*2 | res;
}
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;
F[rd]f<=-F[rs1]f*F[rs2]f+F[rs3]f;
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 {
val upper[FLEN] <= (-1<<31);
F[rd] <= upper*2 | res;
}
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 {
val upper[FLEN] <= (-1<<31);
F[rd] <= upper*2 | res;
}
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;
F[rd]f <= F[rs1]f + F[rs2]f;
args_disass:"x%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 {
val upper[FLEN] <= (-1<<31);
F[rd] <= upper*2 | res;
}
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;
F[rd]f <= F[rs1]f - F[rs2]f;
args_disass:"x%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 {
val upper[FLEN] <= -1<<31;
F[rd] <= upper*2 | res;
}
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;
F[rd]f <= F[rs1]f * F[rs2];
args_disass:"x%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 {
val upper[FLEN] <= -1<<31;
F[rd] <= upper*2 | res;
}
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;
F[rd]f <= F[rs1]f / F[rs2]f;
args_disass:"x%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 {
val upper[FLEN] <= -1<<31;
F[rd] <= upper*2 | res;
}
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;
F[rd]f<=sqrt(F[rs1]f);
args_disass:"x%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 {
val upper[FLEN] <= -1<<31;
F[rd] <= upper*2 | res;
}
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 {
val upper[FLEN] <= -1<<31;
F[rd] <= upper*2 | res;
}
}
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 {
val upper[FLEN] <= -1<<31;
F[rd] <= upper*2 | res;
}
}
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 {
val upper[FLEN] <= -1<<31;
F[rd] <= upper*2 | res;
}
}
FMIN.S {
encoding: b0010100 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
F[rd]f<= choose(F[rs1]f<F[rs2]f, F[rs1]f, F[rs2]f);
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 {
val upper[FLEN] <= -1<<31;
F[rd] <= upper*2 | res;
}
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;
F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f);
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 {
val upper[FLEN] <= -1<<31;
F[rd] <= upper*2 | res;
}
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;
}
FMV.X.W {
encoding: b1110000 | b00000 | rs1[4:0] | b000 | 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 {
val upper[FLEN] <= -1<<31;
F[rd] <= upper*2 | res;
}
}
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 {
val upper[FLEN] <= -1<<31;
F[rd] <= upper*2 | res;
}
}
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 {
val upper[FLEN] <= -1<<31;
F[rd] <= upper*2 | X[rs1];
}
}
}
}

View File

@ -41,9 +41,17 @@ InsructionSet RV32M extends RV32IBase {
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)
X[rd] <= sext(X[rs1], 32) / sext(X[rs2], 32);
else
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;
}
}
@ -61,9 +69,17 @@ InsructionSet RV32M extends RV32IBase {
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)
X[rd] <= sext(X[rs1], 32) % sext(X[rs2], 32);
else
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];
}
}

View File

@ -2,12 +2,13 @@ import "RV32IBase.core_desc"
import "RV32M.core_desc"
import "RV32A.core_desc"
import "RV32C.core_desc"
import "RV32F.core_desc"
import "RV64IBase.core_desc"
//import "RV64M.core_desc"
import "RV64A.core_desc"
Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32CI {
Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32IC {
template:"vm_riscv.in.cpp";
constants {
XLEN:=32;
@ -25,6 +26,25 @@ Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32CI {
}
}
Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC {
constants {
XLEN:=32;
FLEN:=32;
XLEN2:=64;
XLEN_BIT_MASK:=0x1f;
PCLEN:=32;
fence:=0;
fencei:=1;
fencevmal:=2;
fencevmau:=3;
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
MISA_VAL:=0b01000000000101000001000100000001;
PGSIZE := 4096; //1 << 12;
PGMASK := 4095; //PGSIZE-1
FFLAG_MASK:=0x1f;
}
}
Core RV64IA provides RV64IBase, RV64A, RV32A {
template:"vm_riscv.in.cpp";

View File

@ -100,6 +100,8 @@ struct traits<${coreDef.name.toLowerCase()}> {
enum mem_type_e {${allSpaces.collect{s -> s.name}.join(', ')}};
constexpr static bool has_fp_regs = ${allRegs.find {it.name=='FCSR'}!= null ?'true':'false'};
};
struct ${coreDef.name.toLowerCase()}: public arch_if {
@ -112,8 +114,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
${coreDef.name.toLowerCase()}();
~${coreDef.name.toLowerCase()}();
const std::string core_type_name() const override {return traits<${coreDef.name.toLowerCase()}>::core_type;}
void reset(uint64_t address=0) override;
uint8_t* get_regs_base_ptr() override;
@ -158,9 +158,16 @@ protected:
} reg;
std::array<address_type, 4> addr_mode;
uint64_t cycles = 0;
<%
def fcsr = allRegs.find {it.name=='FCSR'}
if(fcsr != null) {%>
uint${generator.getSize(fcsr)}_t get_fcsr(){return reg.FCSR;}
void set_fcsr(uint${generator.getSize(fcsr)}_t val){reg.FCSR = val;}
<%} else { %>
uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}
<%}%>
};
}

View File

@ -68,6 +68,7 @@ uint8_t* ${coreDef.name.toLowerCase()}::get_regs_base_ptr(){
return reinterpret_cast<uint8_t*>(&reg);
}
${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::v2p(const iss::addr_t& pc) {
return phys_addr_t(pc); //change logical address to physical address
${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &pc) {
return phys_addr_t(pc); // change logical address to physical address
}

View File

@ -48,6 +48,12 @@
#include <array>
namespace iss {
namespace vm {
namespace fp_impl{
void add_fp_functions_2_module(llvm::Module *mod);
}
}
namespace ${coreDef.name.toLowerCase()} {
using namespace iss::arch;
using namespace llvm;
@ -81,6 +87,11 @@ protected:
return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits()));
}
void setup_module(llvm::Module* m) override {
super::setup_module(m);
vm::fp_impl::add_fp_functions_2_module(m);
}
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));
@ -106,6 +117,10 @@ protected:
return this->builder.CreateLoad(get_reg_ptr(i), false);
}
llvm::Value* gen_fdispatch(std::string fname, const std::vector<llvm::Value*>& args);
llvm::Value* gen_dispatch(std::string name, llvm::Value*, llvm::Value*, llvm::Value*);
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));
@ -310,7 +325,16 @@ template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBl
bb, this->trap_blk, 1);
}
} // namespace ${coreDef.name.toLowerCase()}
template<typename ARCH>
inline llvm::Value* vm_impl<ARCH>::gen_fdispatch(std::string fname, const std::vector<llvm::Value*>& args) {
return this->builder.CreateCall(this->mod->getFunction(fname), args);
}
template<typename ARCH>
inline llvm::Value* vm_impl<ARCH>::gen_dispatch(std::string name, llvm::Value* val1, llvm::Value* val2, llvm::Value* val3) {
}
} // namespace rv32imacf
template <>
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {

View File

@ -48,6 +48,7 @@
#include <util/sparse_array.h>
#include <util/bit_field.h>
#include <array>
#include <type_traits>
namespace iss {
namespace arch {
@ -537,6 +538,8 @@ private:
iss::status write_ip(unsigned addr, reg_t val);
iss::status read_satp(unsigned addr, reg_t &val);
iss::status write_satp(unsigned addr, reg_t val);
iss::status read_fcsr(unsigned addr, reg_t& val);
iss::status write_fcsr(unsigned addr, reg_t val);
protected:
void check_interrupt();
};
@ -579,6 +582,13 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
csr_wr_cb[uie] = &riscv_hart_msu_vp<BASE>::write_ie;
csr_rd_cb[satp] = &riscv_hart_msu_vp<BASE>::read_satp;
csr_wr_cb[satp] = &riscv_hart_msu_vp<BASE>::write_satp;
csr_rd_cb[fcsr] = &riscv_hart_msu_vp<BASE>::read_fcsr;
csr_wr_cb[fcsr] = &riscv_hart_msu_vp<BASE>::write_fcsr;
csr_rd_cb[fflags] = &riscv_hart_msu_vp<BASE>::read_fcsr;
csr_wr_cb[fflags] = &riscv_hart_msu_vp<BASE>::write_fcsr;
csr_rd_cb[frm] = &riscv_hart_msu_vp<BASE>::read_fcsr;
csr_wr_cb[frm] = &riscv_hart_msu_vp<BASE>::write_fcsr;
}
template <typename BASE> std::pair<uint64_t,bool> riscv_hart_msu_vp<BASE>::load_file(std::string name, int type) {
@ -940,6 +950,39 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_satp(unsigne
update_vm_info();
return iss::Ok;
}
template<typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_fcsr(unsigned addr, reg_t& val) {
switch(addr){
case 1: //fflags, 4:0
val = bit_sub<0, 5>(this->get_fcsr());
break;
case 2: // frm, 7:5
val = bit_sub<5, 3>(this->get_fcsr());
break;
case 3: // fcsr
val=this->get_fcsr();
break;
default:
return iss::Err;
}
return iss::Ok;
}
template<typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigned addr, reg_t val) {
switch(addr){
case 1: //fflags, 4:0
this->set_fcsr( (this->get_fcsr() & 0xffffffe0) | (val&0x1f));
break;
case 2: // frm, 7:5
this->set_fcsr( (this->get_fcsr() & 0xffffff1f) | ((val&0x7)<<5));
break;
case 3: // fcsr
this->set_fcsr(val&0xff);
break;
default:
return iss::Err;
}
return iss::Ok;
}
template <typename BASE>
iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
@ -1299,4 +1342,5 @@ template <typename BASE> void riscv_hart_msu_vp<BASE>::wait_until(uint64_t flags
}
}
#endif /* _RISCV_CORE_H_ */

View File

@ -0,0 +1,278 @@
////////////////////////////////////////////////////////////////////////////////
// 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 _RV32GC_H_
#define _RV32GC_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> {
constexpr static char const* const core_type = "RV32GC";
enum constants {XLEN=32, FLEN=32, XLEN2=64, XLEN_BIT_MASK=31, PCLEN=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=1075056897, PGSIZE=4096, PGMASK=4095, FFLAG_MASK=31};
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,
ICOUNT
};
using reg_t = uint32_t;
using addr_t = uint32_t;
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>;
constexpr static unsigned reg_bit_width(unsigned r) {
constexpr std::array<const uint32_t, 71> 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,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}};
return RV32GC_reg_size[r];
}
constexpr static unsigned reg_byte_offset(unsigned r) {
constexpr std::array<const uint32_t, 72> 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,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,288}};
return RV32GC_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};
constexpr static bool has_fp_regs = true;
};
struct rv32gc: public arch_if {
using virt_addr_t = typename traits<rv32gc>::virt_addr_t;
using phys_addr_t = typename traits<rv32gc>::phys_addr_t;
using reg_t = typename traits<rv32gc>::reg_t;
using addr_t = typename traits<rv32gc>::addr_t;
rv32gc();
~rv32gc();
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 {};
uint64_t get_icount() { return reg.icount;}
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){
return phys_addr_t(addr.access, addr.space, addr.val&traits<rv32gc>::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; }
protected:
struct RV32GC_regs {
uint32_t X0 = 0;
uint32_t X1 = 0;
uint32_t X2 = 0;
uint32_t X3 = 0;
uint32_t X4 = 0;
uint32_t X5 = 0;
uint32_t X6 = 0;
uint32_t X7 = 0;
uint32_t X8 = 0;
uint32_t X9 = 0;
uint32_t X10 = 0;
uint32_t X11 = 0;
uint32_t X12 = 0;
uint32_t X13 = 0;
uint32_t X14 = 0;
uint32_t X15 = 0;
uint32_t X16 = 0;
uint32_t X17 = 0;
uint32_t X18 = 0;
uint32_t X19 = 0;
uint32_t X20 = 0;
uint32_t X21 = 0;
uint32_t X22 = 0;
uint32_t X23 = 0;
uint32_t X24 = 0;
uint32_t X25 = 0;
uint32_t X26 = 0;
uint32_t X27 = 0;
uint32_t X28 = 0;
uint32_t X29 = 0;
uint32_t X30 = 0;
uint32_t X31 = 0;
uint32_t PC = 0;
uint32_t F0 = 0;
uint32_t F1 = 0;
uint32_t F2 = 0;
uint32_t F3 = 0;
uint32_t F4 = 0;
uint32_t F5 = 0;
uint32_t F6 = 0;
uint32_t F7 = 0;
uint32_t F8 = 0;
uint32_t F9 = 0;
uint32_t F10 = 0;
uint32_t F11 = 0;
uint32_t F12 = 0;
uint32_t F13 = 0;
uint32_t F14 = 0;
uint32_t F15 = 0;
uint32_t F16 = 0;
uint32_t F17 = 0;
uint32_t F18 = 0;
uint32_t F19 = 0;
uint32_t F20 = 0;
uint32_t F21 = 0;
uint32_t F22 = 0;
uint32_t F23 = 0;
uint32_t F24 = 0;
uint32_t F25 = 0;
uint32_t F26 = 0;
uint32_t F27 = 0;
uint32_t F28 = 0;
uint32_t F29 = 0;
uint32_t F30 = 0;
uint32_t F31 = 0;
uint32_t FCSR = 0;
uint32_t NEXT_PC = 0;
uint32_t trap_state = 0, pending_trap = 0, machine_state = 0;
uint64_t icount = 0;
} reg;
std::array<address_type, 4> addr_mode;
uint32_t get_fcsr(){return reg.FCSR;}
void set_fcsr(uint32_t val){reg.FCSR = val;}
};
}
}
#endif /* _RV32GC_H_ */

View File

@ -118,6 +118,8 @@ struct traits<rv32imac> {
enum mem_type_e {MEM, CSR, FENCE, RES};
constexpr static bool has_fp_regs = false;
};
struct rv32imac: public arch_if {
@ -198,6 +200,10 @@ protected:
} reg;
std::array<address_type, 4> addr_mode;
uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}
};

View File

@ -118,6 +118,8 @@ struct traits<rv64ia> {
enum mem_type_e {MEM, CSR, FENCE, RES};
constexpr static bool has_fp_regs = false;
};
struct rv64ia: public arch_if {
@ -198,6 +200,10 @@ protected:
} reg;
std::array<address_type, 4> addr_mode;
uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}
};

View File

@ -0,0 +1,290 @@
////////////////////////////////////////////////////////////////////////////////
// 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
////////////////////////////////////////////////////////////////////////////////
#include <iss/iss.h>
#include <iss/vm_base.h>
extern "C" {
#include <softfloat.h>
#include "internals.h"
#include "specialize.h"
}
namespace iss {
namespace vm {
namespace fp_impl {
using namespace std;
#define INT_TYPE(L) Type::getIntNTy(mod->getContext(), L)
#define FLOAT_TYPE Type::getFloatTy(mod->getContext())
#define DOUBLE_TYPE Type::getDoubleTy(mod->getContext())
#define VOID_TYPE Type::getVoidTy(mod->getContext())
#define THIS_PTR_TYPE Type::getIntNPtrTy(mod->getContext(), 8)
#define FDECLL(NAME, RET, ...) \
Function *NAME##_func = CurrentModule->getFunction(#NAME); \
if (!NAME##_func) { \
std::vector<Type *> NAME##_args{__VA_ARGS__}; \
FunctionType *NAME##_type = FunctionType::get(RET, NAME##_args, false); \
NAME##_func = Function::Create(NAME##_type, GlobalValue::ExternalLinkage, #NAME, CurrentModule); \
NAME##_func->setCallingConv(CallingConv::C); \
}
#define FDECL(NAME, RET, ...) \
std::vector<Type *> NAME##_args{__VA_ARGS__}; \
FunctionType *NAME##_type = llvm::FunctionType::get(RET, NAME##_args, false); \
mod->getOrInsertFunction(#NAME, NAME##_type);
using namespace llvm;
void add_fp_functions_2_module(Module *mod) {
FDECL(fget_flags, INT_TYPE(32));
FDECL(fadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fsub_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fmul_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fdiv_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fsqrt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fcmp_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32));
FDECL(fcvt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8));
FDECL(fmadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(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));
}
}
}
}
using this_t = uint8_t *;
const uint8_t rmm_map[] = {
softfloat_round_near_even /*RNE*/,
softfloat_round_minMag/*RTZ*/,
softfloat_round_min/*RDN*/,
softfloat_round_max/*RUP?*/,
softfloat_round_near_maxMag /*RMM*/,
softfloat_round_max/*RTZ*/,
softfloat_round_max/*RTZ*/,
softfloat_round_max/*RTZ*/,
};
const uint32_t quiet_nan32=0x7fC00000;
extern "C" {
uint32_t fget_flags(){
return softfloat_exceptionFlags&0x1f;
}
uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1},v2f{v2};
softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0;
float32_t r =f32_add(v1f, v2f);
return r.v;
}
uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1},v2f{v2};
softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0;
float32_t r=f32_sub(v1f, v2f);
return r.v;
}
uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1},v2f{v2};
softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0;
float32_t r=f32_mul(v1f, v2f);
return r.v;
}
uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1},v2f{v2};
softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0;
float32_t r=f32_div(v1f, v2f);
return r.v;
}
uint32_t fsqrt_s(uint32_t v1, uint8_t mode) {
float32_t v1f{v1};
softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0;
float32_t r=f32_sqrt(v1f);
return r.v;
}
uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) {
float32_t v1f{v1},v2f{v2};
softfloat_exceptionFlags=0;
bool nan = (v1&defaultNaNF32UI)==quiet_nan32 || (v2&defaultNaNF32UI)==quiet_nan32;
bool snan = softfloat_isSigNaNF32UI(v1) || softfloat_isSigNaNF32UI(v2);
switch(op){
case 0:
if(nan | snan){
if(snan) softfloat_raiseFlags(softfloat_flag_invalid);
return 0;
} else
return f32_eq(v1f,v2f )?1:0;
case 1:
if(nan | snan){
softfloat_raiseFlags(softfloat_flag_invalid);
return 0;
} else
return f32_le(v1f,v2f )?1:0;
case 2:
if(nan | snan){
softfloat_raiseFlags(softfloat_flag_invalid);
return 0;
} else
return f32_lt(v1f,v2f )?1:0;
default:
break;
}
return -1;
}
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);
return (uint32_t)res;
case 1: //wu->s
return f32_to_ui32(v1f,rmm_map[mode&0x7],true);
case 2: //s->w
r=i32_to_f32(v1);
return r.v;
case 3: //s->wu
r=ui32_to_f32(v1);
return r.v;
}
return 0;
}
uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode) {
// op should be {softfloat_mulAdd_subProd(2), softfloat_mulAdd_subC(1)}
softfloat_roundingMode=rmm_map[mode&0x7];
softfloat_exceptionFlags=0;
float32_t res = softfloat_mulAddF32(v1, v2, v3, op&0x1);
if(op>1) res.v ^= 0x80000000UL;
return res.v;
}
uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op) {
softfloat_exceptionFlags = 0;
bool v1_nan = (v1 & defaultNaNF32UI) == quiet_nan32;
bool v2_nan = (v2 & defaultNaNF32UI) == quiet_nan32;
bool v1_snan = softfloat_isSigNaNF32UI(v1);
bool v2_snan = softfloat_isSigNaNF32UI(v2);
if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid);
if (v1_nan || v1_snan)
return (v2_nan || v2_snan) ? defaultNaNF32UI : v2;
else
if (v2_nan || v2_snan)
return v1;
else {
if ((v1 & 0x7fffffff) == 0 && (v2 & 0x7fffffff) == 0) {
return op == 0 ? ((v1 & 0x80000000) ? v1 : v2) : ((v1 & 0x80000000) ? v2 : v1);
} else {
float32_t v1f{ v1 }, v2f{ v2 };
return op == 0 ? (f32_lt(v1f, v2f) ? v1 : v2) : (f32_lt(v1f, v2f) ? v2 : v1);
}
}
}
uint32_t fclass_s( uint32_t v1 ){
float32_t a{v1};
union ui32_f32 uA;
uint_fast32_t uiA;
uA.f = a;
uiA = uA.ui;
uint_fast16_t infOrNaN = expF32UI( uiA ) == 0xFF;
uint_fast16_t subnormalOrZero = expF32UI( uiA ) == 0;
bool sign = signF32UI( uiA );
bool fracZero = fracF32UI( uiA ) == 0;
bool isNaN = isNaNF32UI( uiA );
bool isSNaN = softfloat_isSigNaNF32UI( uiA );
return
( sign && infOrNaN && fracZero ) << 0 |
( sign && !infOrNaN && !subnormalOrZero ) << 1 |
( sign && subnormalOrZero && !fracZero ) << 2 |
( sign && subnormalOrZero && fracZero ) << 3 |
( !sign && infOrNaN && fracZero ) << 7 |
( !sign && !infOrNaN && !subnormalOrZero ) << 6 |
( !sign && subnormalOrZero && !fracZero ) << 5 |
( !sign && subnormalOrZero && fracZero ) << 4 |
( isNaN && isSNaN ) << 8 |
( isNaN && !isSNaN ) << 9;
}
uint64_t fclass_d(uint64_t v1 ){
float64_t a{v1};
union ui64_f64 uA;
uint_fast64_t uiA;
uA.f = a;
uiA = uA.ui;
uint_fast16_t infOrNaN = expF64UI( uiA ) == 0x7FF;
uint_fast16_t subnormalOrZero = expF64UI( uiA ) == 0;
bool sign = signF64UI( uiA );
bool fracZero = fracF64UI( uiA ) == 0;
bool isNaN = isNaNF64UI( uiA );
bool isSNaN = softfloat_isSigNaNF64UI( uiA );
return
( sign && infOrNaN && fracZero ) << 0 |
( sign && !infOrNaN && !subnormalOrZero ) << 1 |
( sign && subnormalOrZero && !fracZero ) << 2 |
( sign && subnormalOrZero && fracZero ) << 3 |
( !sign && infOrNaN && fracZero ) << 7 |
( !sign && !infOrNaN && !subnormalOrZero ) << 6 |
( !sign && subnormalOrZero && !fracZero ) << 5 |
( !sign && subnormalOrZero && fracZero ) << 4 |
( isNaN && isSNaN ) << 8 |
( isNaN && !isSNaN ) << 9;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

74
riscv/src/iss/rv32gc.cpp Normal file
View File

@ -0,0 +1,74 @@
////////////////////////////////////////////////////////////////////////////////
// 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.
//
////////////////////////////////////////////////////////////////////////////////
#include "util/ities.h"
#include <util/logging.h>
#include <elfio/elfio.hpp>
#include <iss/arch/rv32gc.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <ihex.h>
#ifdef __cplusplus
}
#endif
#include <fstream>
#include <cstdio>
#include <cstring>
using namespace iss::arch;
rv32gc::rv32gc() {
reg.icount=0;
}
rv32gc::~rv32gc(){
}
void rv32gc::reset(uint64_t address) {
for(size_t i=0; i<traits<rv32gc>::NUM_REGS; ++i) set_reg(i, std::vector<uint8_t>(sizeof(traits<rv32gc>::reg_t),0));
reg.PC=address;
reg.NEXT_PC=reg.PC;
reg.trap_state=0;
reg.machine_state=0x0;
}
uint8_t* rv32gc::get_regs_base_ptr(){
return reinterpret_cast<uint8_t*>(&reg);
}
rv32gc::phys_addr_t rv32gc::virt2phys(const iss::addr_t &pc) {
return phys_addr_t(pc); // change logical address to physical address
}

View File

@ -39,6 +39,7 @@
#include <boost/program_options.hpp>
#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/MCJIThelper.h>
#include <iss/log_categories.h>
@ -103,15 +104,19 @@ int main(int argc, char *argv[]) {
// instantiate the simulator
std::unique_ptr<iss::vm_if> vm{nullptr};
std::string isa_opt(clim["isa"].as<std::string>());
iss::plugin::instruction_count ic_plugin("riscv/gen_input/src-gen/rv32imac_cyles.txt");
iss::plugin::cycle_estimate ce_plugin("riscv/gen_input/src-gen/rv32imac_cyles.txt");
// iss::plugin::instruction_count ic_plugin("riscv/gen_input/src-gen/rv32imac_cyles.txt");
// iss::plugin::cycle_estimate ce_plugin("riscv/gen_input/src-gen/rv32imac_cyles.txt");
if (isa_opt.substr(0, 4)=="rv64") {
iss::arch::rv64ia* cpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv64ia>();
vm = iss::create(cpu, clim["gdb-port"].as<unsigned>());
} else if (isa_opt.substr(0, 4)=="rv32") {
} else if (isa_opt.substr(0, 5)=="rv32i") {
iss::arch::rv32imac* cpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv32imac>();
vm = iss::create(cpu, clim["gdb-port"].as<unsigned>());
//vm->register_plugin(ce_plugin);
} else if (isa_opt.substr(0, 5)=="rv32g") {
iss::arch::rv32gc* cpu = new iss::arch::riscv_hart_msu_vp<iss::arch::rv32gc>();
vm = iss::create(cpu, clim["gdb-port"].as<unsigned>());
//vm->register_plugin(ce_plugin);
} else {
LOG(ERROR) << "Illegal argument value for '--isa': " << clim["isa"].as<std::string>() << std::endl;
return 127;